Add sub configs edit component
This commit is contained in:
1 parent
d70263e798
commit
152d8f5283
10 files changed
+386
-44
No files matched your search
+2
-1
@@ -52,7 +52,8 @@ const externals = [
|
|||||||
"mithril",
|
"mithril",
|
||||||
"parsimmon",
|
"parsimmon",
|
||||||
"codemirror",
|
"codemirror",
|
||||||
"codemirror/mode/javascript/javascript"
|
"codemirror/mode/javascript/javascript",
|
||||||
|
"codemirror/mode/yaml/yaml"
|
||||||
];
|
];
|
||||||
|
|
||||||
function rmDirSync(dirPath): void {
|
function rmDirSync(dirPath): void {
|
||||||
|
|||||||
+26
-9
@@ -363,26 +363,42 @@ function refresh(callback): void {
|
|||||||
|
|
||||||
conf.sort((a, b) => (a.id > b.id ? 1 : a.id < b.id ? -1 : 0));
|
conf.sort((a, b) => (a.id > b.id ? 1 : a.id < b.id ? -1 : 0));
|
||||||
|
|
||||||
|
const ui = {
|
||||||
|
filters: {},
|
||||||
|
device: {},
|
||||||
|
index: {},
|
||||||
|
overview: { charts: {}, groups: {} }
|
||||||
|
};
|
||||||
const _config = {};
|
const _config = {};
|
||||||
|
|
||||||
for (const c of conf) {
|
for (const c of conf) {
|
||||||
|
// Evaluate expressions to simplify them
|
||||||
|
const val = expression.evaluate(c.value);
|
||||||
|
_config[c.id] = val;
|
||||||
if (c.id.startsWith("ui.")) {
|
if (c.id.startsWith("ui.")) {
|
||||||
const keys = c.id.split(".");
|
const keys = c.id.split(".");
|
||||||
let ref = _config;
|
// remove the first key(ui)
|
||||||
|
keys.shift();
|
||||||
|
let ref = ui;
|
||||||
while (keys.length > 1) {
|
while (keys.length > 1) {
|
||||||
const k = keys.shift();
|
const k = keys.shift();
|
||||||
if (typeof ref[k] !== "object") ref[k] = {};
|
if (typeof ref[k] !== "object") ref[k] = {};
|
||||||
ref = ref[k];
|
ref = ref[k];
|
||||||
}
|
}
|
||||||
// Evaluate expressions to simplify them
|
ref[keys[0]] = val;
|
||||||
ref[keys[0]] = expression.evaluate(c.value);
|
|
||||||
} else {
|
|
||||||
// Evaluate expressions to simplify them
|
|
||||||
_config[c.id] = expression.evaluate(c.value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve(_config);
|
if (!Object.keys(ui["index"]).length) {
|
||||||
|
ui["index"] = {
|
||||||
|
"0": {
|
||||||
|
label: "ID",
|
||||||
|
parameter: ["PARAM", "DeviceID.ID"]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve([_config, ui]);
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -396,7 +412,8 @@ function refresh(callback): void {
|
|||||||
files: res[3],
|
files: res[3],
|
||||||
permissions: res[4],
|
permissions: res[4],
|
||||||
users: res[5],
|
users: res[5],
|
||||||
config: res[6]
|
config: res[6][0],
|
||||||
|
ui: res[6][1]
|
||||||
};
|
};
|
||||||
|
|
||||||
if (currentSnapshot) {
|
if (currentSnapshot) {
|
||||||
@@ -536,5 +553,5 @@ export function getUiConfig(snapshotKey): {} {
|
|||||||
const snapshot = snapshots.get(snapshotKey);
|
const snapshot = snapshots.get(snapshotKey);
|
||||||
if (!snapshot) throw new Error("Cache snapshot does not exist");
|
if (!snapshot) throw new Error("Cache snapshot does not exist");
|
||||||
|
|
||||||
return snapshot.config.ui;
|
return snapshot.ui;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
import { ClosureComponent, Component } from "mithril";
|
||||||
|
import { m } from "./components";
|
||||||
|
import { codeMirror } from "./dynamic-loader";
|
||||||
|
|
||||||
|
const component: ClosureComponent = (): Component => {
|
||||||
|
return {
|
||||||
|
view: vnode => {
|
||||||
|
return m("textarea", {
|
||||||
|
name: vnode.attrs["id"],
|
||||||
|
value: vnode.attrs["value"],
|
||||||
|
oncreate: _vnode => {
|
||||||
|
const editor = codeMirror.fromTextArea(_vnode.dom, {
|
||||||
|
mode: vnode.attrs["mode"],
|
||||||
|
lineNumbers: true,
|
||||||
|
readOnly: vnode.attrs["readOnly"],
|
||||||
|
extraKeys: {
|
||||||
|
"Ctrl-Enter": () => {
|
||||||
|
if (vnode.attrs["onSubmit"])
|
||||||
|
vnode.attrs["onSubmit"](_vnode.dom);
|
||||||
|
},
|
||||||
|
"Cmd-Enter": () => {
|
||||||
|
if (vnode.attrs["onSubmit"])
|
||||||
|
vnode.attrs["onSubmit"](_vnode.dom);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (vnode.attrs["onChange"]) {
|
||||||
|
editor.on("change", e => {
|
||||||
|
vnode.attrs["onChange"](e.getValue());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vnode.attrs["focus"]) editor.focus();
|
||||||
|
if (vnode.attrs["onReady"]) vnode.attrs["onReady"](editor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default component;
|
||||||
@@ -10,6 +10,7 @@ const component: ClosureComponent = (): Component => {
|
|||||||
view: vnode => {
|
view: vnode => {
|
||||||
const device = vnode.attrs["device"];
|
const device = vnode.attrs["device"];
|
||||||
const chart = CHARTS[vnode.attrs["chart"]];
|
const chart = CHARTS[vnode.attrs["chart"]];
|
||||||
|
if (!chart) return null;
|
||||||
for (const slice of Object.values(chart.slices)) {
|
for (const slice of Object.values(chart.slices)) {
|
||||||
const filter = slice["filter"];
|
const filter = slice["filter"];
|
||||||
if (store.evaluateExpression(filter, device)) {
|
if (store.evaluateExpression(filter, device)) {
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
interface Config {
|
||||||
|
_id: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Diff {
|
||||||
|
add: Config[];
|
||||||
|
remove: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function flattenConfig(config): any {
|
||||||
|
const flatten = {};
|
||||||
|
const recuresive = (obj: any, root: string): void => {
|
||||||
|
for (const [k, v] of Object.entries(obj)) {
|
||||||
|
const key = root ? `${root}.${k}` : k;
|
||||||
|
if (v === undefined) continue;
|
||||||
|
if (v === null || typeof v !== "object") flatten[key] = v;
|
||||||
|
else recuresive(v, key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (config !== null && typeof config === "object") recuresive(config, "");
|
||||||
|
return flatten;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function structureConfig(config: Config[]): any {
|
||||||
|
config.sort((a, b) => (a._id > b._id ? 1 : a._id < b._id ? -1 : 0));
|
||||||
|
const _config = {};
|
||||||
|
for (const c of config) {
|
||||||
|
const keys = c._id.split(".");
|
||||||
|
let ref = _config;
|
||||||
|
while (keys.length > 1) {
|
||||||
|
const k = keys.shift();
|
||||||
|
if (typeof ref[k] !== "object") ref[k] = {};
|
||||||
|
ref = ref[k];
|
||||||
|
}
|
||||||
|
ref[keys[0]] = c.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
const toArray = function(object): any {
|
||||||
|
const MAX_BITS = 30;
|
||||||
|
const MAX_ARRAY_SIZE = MAX_BITS * 10;
|
||||||
|
|
||||||
|
if (object == null || typeof object !== "object") return object;
|
||||||
|
|
||||||
|
if (Object.keys(object).length <= MAX_ARRAY_SIZE) {
|
||||||
|
let indexes = [];
|
||||||
|
for (const key of Object.keys(object)) {
|
||||||
|
const idx = Math.floor(+key);
|
||||||
|
if (idx >= 0 && idx < MAX_ARRAY_SIZE && String(idx) === key) {
|
||||||
|
const pos = Math.floor(idx / MAX_BITS);
|
||||||
|
if (!indexes[pos]) indexes[pos] = 0;
|
||||||
|
indexes[pos] |= 1 << idx % MAX_BITS;
|
||||||
|
} else {
|
||||||
|
indexes = [];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let index = 0;
|
||||||
|
while (indexes.length && (index = indexes.shift()) === 1073741823);
|
||||||
|
|
||||||
|
if (index && (~index & (index + 1)) === index + 1) {
|
||||||
|
// its an array
|
||||||
|
const array = [];
|
||||||
|
for (let i = 0; i < Object.keys(object).length; i++)
|
||||||
|
array[i] = object[i];
|
||||||
|
|
||||||
|
object = array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const [k, v] of Object.entries(object)) object[k] = toArray(v);
|
||||||
|
return object;
|
||||||
|
};
|
||||||
|
|
||||||
|
return toArray(_config);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function diffConfig(current, target): Diff {
|
||||||
|
const diff = {
|
||||||
|
add: [],
|
||||||
|
remove: []
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const [k, v] of Object.entries(target))
|
||||||
|
if (!current[k] || current[k] !== v) diff.add.push({ _id: k, value: v });
|
||||||
|
|
||||||
|
for (const k of Object.keys(current)) if (!target[k]) diff.remove.push(k);
|
||||||
|
|
||||||
|
return diff;
|
||||||
|
}
|
||||||
+75
-6
@@ -2,9 +2,10 @@ import { m } from "./components";
|
|||||||
import * as store from "./store";
|
import * as store from "./store";
|
||||||
import * as notifications from "./notifications";
|
import * as notifications from "./notifications";
|
||||||
import putFormComponent from "./put-form-component";
|
import putFormComponent from "./put-form-component";
|
||||||
|
import uiConfigComponent from "./ui-config-component";
|
||||||
import * as overlay from "./overlay";
|
import * as overlay from "./overlay";
|
||||||
import * as expressionParser from "../lib/common/expression-parser";
|
import * as expressionParser from "../lib/common/expression-parser";
|
||||||
import { loadCodeMirror } from "./dynamic-loader";
|
import { loadCodeMirror, loadYaml } from "./dynamic-loader";
|
||||||
import { ClosureComponent, Component, Children } from "mithril";
|
import { ClosureComponent, Component, Children } from "mithril";
|
||||||
|
|
||||||
const attributes = [
|
const attributes = [
|
||||||
@@ -92,7 +93,7 @@ export function init(): Promise<{}> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
loadCodeMirror()
|
Promise.all([loadCodeMirror(), loadYaml()])
|
||||||
.then(() => {
|
.then(() => {
|
||||||
resolve({});
|
resolve({});
|
||||||
})
|
})
|
||||||
@@ -209,7 +210,11 @@ export const component: ClosureComponent = (): Component => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const confs = store.fetch("config", true);
|
||||||
|
|
||||||
let newConfig;
|
let newConfig;
|
||||||
|
const subs = [];
|
||||||
|
|
||||||
if (window.authorizer.hasAccess("config", 3)) {
|
if (window.authorizer.hasAccess("config", 3)) {
|
||||||
newConfig = m(
|
newConfig = m(
|
||||||
"button.primary",
|
"button.primary",
|
||||||
@@ -250,11 +255,75 @@ export const component: ClosureComponent = (): Component => {
|
|||||||
overlay.open(cb);
|
overlay.open(cb);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"New"
|
"New config"
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
const confs = store.fetch("config", true);
|
const subsData = [
|
||||||
|
{ name: "overview", prefix: "ui.overview.groups.", data: [] },
|
||||||
|
{ name: "charts", prefix: "ui.overview.charts.", data: [] },
|
||||||
|
{ name: "filters", prefix: "ui.filters.", data: [] },
|
||||||
|
{ name: "index page", prefix: "ui.index.", data: [] },
|
||||||
|
{ name: "device page", prefix: "ui.device.", data: [] }
|
||||||
|
];
|
||||||
|
|
||||||
|
if (confs.fulfilled) {
|
||||||
|
for (const conf of confs.value) {
|
||||||
|
for (const sub of subsData) {
|
||||||
|
if (conf["_id"].startsWith(sub["prefix"])) {
|
||||||
|
sub["data"].push(conf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const sub of subsData) {
|
||||||
|
const attrs = { prefix: sub.prefix, name: sub.name, data: sub.data };
|
||||||
|
subs.push(
|
||||||
|
m(
|
||||||
|
"button",
|
||||||
|
{
|
||||||
|
onclick: () => {
|
||||||
|
const cb = (): Children => {
|
||||||
|
return m(
|
||||||
|
uiConfigComponent,
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
onUpdate: errs => {
|
||||||
|
const errors = errs ? Object.values(errs) : [];
|
||||||
|
if (errors.length) {
|
||||||
|
for (const err of errors)
|
||||||
|
notifications.push("error", err);
|
||||||
|
} else {
|
||||||
|
notifications.push(
|
||||||
|
"success",
|
||||||
|
`${sub.name.replace(
|
||||||
|
/^[a-z]/,
|
||||||
|
sub.name[0].toUpperCase()
|
||||||
|
)} config updated`
|
||||||
|
);
|
||||||
|
overlay.close(cb);
|
||||||
|
}
|
||||||
|
store.fulfill(0, Date.now());
|
||||||
|
},
|
||||||
|
onError: err => {
|
||||||
|
notifications.push("error", err.message);
|
||||||
|
store.fulfill(0, Date.now());
|
||||||
|
overlay.close(cb);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
attrs
|
||||||
|
)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
overlay.open(cb);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
`Edit ${sub.name}`
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
m("h1", "Listing config"),
|
m("h1", "Listing config"),
|
||||||
@@ -266,7 +335,7 @@ export const component: ClosureComponent = (): Component => {
|
|||||||
{ style: "height: 400px" },
|
{ style: "height: 400px" },
|
||||||
renderTable(confs, vnode.state["searchString"])
|
renderTable(confs, vnode.state["searchString"])
|
||||||
),
|
),
|
||||||
m(".actions-bar", newConfig)
|
m(".actions-bar", [newConfig].concat(subs))
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@ export function loadCodeMirror(): Promise<void> {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const promises = [
|
const promises = [
|
||||||
import(/* webpackChunkName: "codemirror" */ "codemirror"),
|
import(/* webpackChunkName: "codemirror" */ "codemirror"),
|
||||||
import(/* webpackChunkName: "codemirror" */ "codemirror/mode/javascript/javascript")
|
import(/* webpackChunkName: "codemirror" */ "codemirror/mode/javascript/javascript"),
|
||||||
|
import(/* webpackChunkName: "codemirror" */ "codemirror/mode/yaml/yaml")
|
||||||
];
|
];
|
||||||
Promise.all(promises)
|
Promise.all(promises)
|
||||||
.then(modules => {
|
.then(modules => {
|
||||||
|
|||||||
+11
-27
@@ -1,6 +1,6 @@
|
|||||||
import { VnodeDOM, ClosureComponent, Component, Children } from "mithril";
|
import { VnodeDOM, ClosureComponent, Component, Children } from "mithril";
|
||||||
import { m } from "./components";
|
import { m } from "./components";
|
||||||
import { codeMirror } from "./dynamic-loader";
|
import codeEditorComponent from "./code-editor-component";
|
||||||
|
|
||||||
const singular = {
|
const singular = {
|
||||||
presets: "preset",
|
presets: "preset",
|
||||||
@@ -59,34 +59,18 @@ function createField(current, attr, focus): Children {
|
|||||||
|
|
||||||
return m("table", options);
|
return m("table", options);
|
||||||
} else if (attr.type === "code") {
|
} else if (attr.type === "code") {
|
||||||
return m("textarea", {
|
const attrs = {
|
||||||
name: attr.id,
|
id: attr.id,
|
||||||
value: current.object[attr.id],
|
value: current.object[attr.id],
|
||||||
oncreate: _vnode => {
|
mode: "javascript",
|
||||||
const editor = codeMirror.fromTextArea(_vnode.dom, {
|
onSubmit: dom => {
|
||||||
mode: "javascript",
|
dom.form.querySelector("button[type=submit]").click();
|
||||||
lineNumbers: true,
|
},
|
||||||
extraKeys: {
|
onChange: value => {
|
||||||
"Ctrl-Enter": () => {
|
current.object[attr.id] = value;
|
||||||
((_vnode.dom as HTMLTextAreaElement).form.querySelector(
|
|
||||||
"button[type=submit]"
|
|
||||||
) as HTMLButtonElement).click();
|
|
||||||
},
|
|
||||||
"Cmd-Enter": () => {
|
|
||||||
((_vnode.dom as HTMLTextAreaElement).form.querySelector(
|
|
||||||
"button[type=submit]"
|
|
||||||
) as HTMLButtonElement).click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
editor.on("change", e => {
|
|
||||||
current.object[attr.id] = e.getValue();
|
|
||||||
});
|
|
||||||
|
|
||||||
if (focus) editor.focus();
|
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
|
return m(codeEditorComponent, attrs);
|
||||||
} else if (attr.type === "file") {
|
} else if (attr.type === "file") {
|
||||||
return m("input", {
|
return m("input", {
|
||||||
type: "file",
|
type: "file",
|
||||||
|
|||||||
@@ -520,6 +520,15 @@ export function putResource(resourceType, id, object): Promise<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function queryConfig(pattern = "%"): Promise<any[]> {
|
||||||
|
const filter = stringify(["LIKE", ["PARAM", "_id"], pattern]);
|
||||||
|
return m.request({
|
||||||
|
method: "GET",
|
||||||
|
url: `api/config/?${m.buildQueryString({ filter: filter })}`,
|
||||||
|
background: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
export function resourceExists(resource, id): Promise<number> {
|
export function resourceExists(resource, id): Promise<number> {
|
||||||
const param = resource === "devices" ? "DeviceID.ID" : "_id";
|
const param = resource === "devices" ? "DeviceID.ID" : "_id";
|
||||||
const filter = ["=", ["PARAM", param], id];
|
const filter = ["=", ["PARAM", param], id];
|
||||||
|
|||||||
@@ -0,0 +1,126 @@
|
|||||||
|
import { ClosureComponent, Component } from "mithril";
|
||||||
|
import { m } from "./components";
|
||||||
|
import * as store from "./store";
|
||||||
|
import { yaml } from "./dynamic-loader";
|
||||||
|
import * as configFunctions from "./config-functions";
|
||||||
|
import codeEditorComponent from "./code-editor-component";
|
||||||
|
import { parse } from "../lib/common/expression-parser";
|
||||||
|
|
||||||
|
function putActionHandler(prefix: string[], dataYaml: string): Promise<any> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
try {
|
||||||
|
let updated = yaml.parse(dataYaml, { schema: "failsafe" });
|
||||||
|
if (updated) {
|
||||||
|
const config = {};
|
||||||
|
let ref = config;
|
||||||
|
prefix.forEach((seg, index) => {
|
||||||
|
if (index < prefix.length - 1) {
|
||||||
|
ref[seg] = {};
|
||||||
|
ref = ref[seg];
|
||||||
|
} else {
|
||||||
|
ref[seg] = updated;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
updated = configFunctions.flattenConfig(config);
|
||||||
|
} else {
|
||||||
|
updated = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try parse to ensure valid expressions
|
||||||
|
for (const v of Object.values(updated)) parse(v);
|
||||||
|
|
||||||
|
store
|
||||||
|
.queryConfig(`${prefix.join(".")}.%`)
|
||||||
|
.then(res => {
|
||||||
|
const current = {};
|
||||||
|
for (const f of res) current[f._id] = f.value;
|
||||||
|
|
||||||
|
const diff = configFunctions.diffConfig(current, updated);
|
||||||
|
if (!diff.add.length && !diff.remove.length) return void resolve();
|
||||||
|
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
for (const obj of diff.add)
|
||||||
|
promises.push(store.putResource("config", obj._id, obj));
|
||||||
|
|
||||||
|
for (const id of diff.remove)
|
||||||
|
promises.push(store.deleteResource("config", id));
|
||||||
|
|
||||||
|
Promise.all(promises)
|
||||||
|
.then(() => {
|
||||||
|
resolve();
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
})
|
||||||
|
.catch(reject);
|
||||||
|
} catch (error) {
|
||||||
|
resolve({ config: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const component: ClosureComponent = (): Component => {
|
||||||
|
return {
|
||||||
|
view: vnode => {
|
||||||
|
const prefix = vnode.attrs["prefix"].split(".");
|
||||||
|
const name = vnode.attrs["name"];
|
||||||
|
const data = vnode.attrs["data"];
|
||||||
|
|
||||||
|
if (prefix[prefix.length - 1] === "") prefix.pop();
|
||||||
|
|
||||||
|
let config;
|
||||||
|
if (data.length) {
|
||||||
|
config = configFunctions.structureConfig(data);
|
||||||
|
for (const seg of prefix) config = config[seg];
|
||||||
|
}
|
||||||
|
|
||||||
|
const yamlString =
|
||||||
|
config && Object.values(config).length
|
||||||
|
? yaml.stringify(config, {
|
||||||
|
schema: "failsafe",
|
||||||
|
tags: args => {
|
||||||
|
return args;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const attrs = {
|
||||||
|
id: `${name}-ui-config`,
|
||||||
|
value: yamlString,
|
||||||
|
mode: "yaml",
|
||||||
|
focus: true,
|
||||||
|
onSubmit: dom => {
|
||||||
|
dom.form.querySelector("button[type=submit]").click();
|
||||||
|
},
|
||||||
|
onChange: value => {
|
||||||
|
vnode.state["updatedYaml"] = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const code = m(codeEditorComponent, attrs);
|
||||||
|
const submit = m("button.primary", { type: "submit" }, "Save");
|
||||||
|
|
||||||
|
return m("div.put-form", [
|
||||||
|
m("h1", `Editing ${name}`),
|
||||||
|
m(
|
||||||
|
"form",
|
||||||
|
{
|
||||||
|
onsubmit: e => {
|
||||||
|
e.redraw = false;
|
||||||
|
e.preventDefault();
|
||||||
|
if (vnode.state["updatedYaml"] == null)
|
||||||
|
vnode.state["updatedYaml"] = yamlString;
|
||||||
|
|
||||||
|
putActionHandler(prefix, vnode.state["updatedYaml"])
|
||||||
|
.then(vnode.attrs["onUpdate"])
|
||||||
|
.catch(vnode.attrs["onError"]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[code, m(".actions-bar", [submit])]
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default component;
|
||||||
Reference in new issue
Block a user