Update linting
This commit is contained in:
1 parent
4f2dfb4f48
commit
0c9c027a77
112 files changed
+3781
-4125
No files matched your search
+18
-14
@@ -31,8 +31,8 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"li",
|
||||
{ class: active["presets"] },
|
||||
m("a", { href: "#!/admin/presets" }, "Presets")
|
||||
)
|
||||
m("a", { href: "#!/admin/presets" }, "Presets"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"li",
|
||||
{ class: active["provisions"] },
|
||||
m("a", { href: "#!/admin/provisions" }, "Provisions")
|
||||
)
|
||||
m("a", { href: "#!/admin/provisions" }, "Provisions"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -51,8 +51,12 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"li",
|
||||
{ class: active["virtualParameters"] },
|
||||
m("a", { href: "#!/admin/virtualParameters" }, "Virtual Parameters")
|
||||
)
|
||||
m(
|
||||
"a",
|
||||
{ href: "#!/admin/virtualParameters" },
|
||||
"Virtual Parameters",
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -61,8 +65,8 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"li",
|
||||
{ class: active["files"] },
|
||||
m("a", { href: "#!/admin/files" }, "Files")
|
||||
)
|
||||
m("a", { href: "#!/admin/files" }, "Files"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -71,8 +75,8 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"li",
|
||||
{ class: active["config"] },
|
||||
m("a", { href: "#!/admin/config" }, "Config")
|
||||
)
|
||||
m("a", { href: "#!/admin/config" }, "Config"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,8 +85,8 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"li",
|
||||
{ class: active["permissions"] },
|
||||
m("a", { href: "#!/admin/permissions" }, "Permissions")
|
||||
)
|
||||
m("a", { href: "#!/admin/permissions" }, "Permissions"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -91,8 +95,8 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"li",
|
||||
{ class: active["users"] },
|
||||
m("a", { href: "#!/admin/users" }, "Users")
|
||||
)
|
||||
m("a", { href: "#!/admin/users" }, "Users"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ m.route(document.body, "/overview", {
|
||||
"/admin/provisions": pagify("provisions", provisionsPage),
|
||||
"/admin/virtualParameters": pagify(
|
||||
"virtualParameters",
|
||||
virtualParametersPage
|
||||
virtualParametersPage,
|
||||
),
|
||||
"/admin/files": pagify("files", filesPage),
|
||||
"/admin/config": pagify("config", configPage),
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
type AutocompleteCallback = (
|
||||
value: string,
|
||||
callback: (suggestions: { value: string; tip?: string }[]) => void
|
||||
callback: (suggestions: { value: string; tip?: string }[]) => void,
|
||||
) => void;
|
||||
|
||||
export default class Autocomplete {
|
||||
@@ -180,14 +180,14 @@ export default class Autocomplete {
|
||||
if (selectedElement) {
|
||||
this.container.scrollTop = Math.min(
|
||||
this.container.scrollTop,
|
||||
selectedElement.offsetTop
|
||||
selectedElement.offsetTop,
|
||||
);
|
||||
|
||||
this.container.scrollTop = Math.max(
|
||||
this.container.scrollTop,
|
||||
selectedElement.offsetTop +
|
||||
selectedElement.scrollHeight -
|
||||
this.container.clientHeight
|
||||
this.container.clientHeight,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -52,7 +52,7 @@ const component: ClosureComponent<Attrs> = () => {
|
||||
oncreate: (_vnode) => {
|
||||
(_vnode.dom as HTMLSelectElement).focus();
|
||||
},
|
||||
})
|
||||
}),
|
||||
),
|
||||
];
|
||||
|
||||
@@ -75,8 +75,8 @@ const component: ClosureComponent<Attrs> = () => {
|
||||
oninput: (e) => {
|
||||
vnode.state[f] = e.target.value;
|
||||
},
|
||||
})
|
||||
)
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -85,7 +85,7 @@ const component: ClosureComponent<Attrs> = () => {
|
||||
{
|
||||
type: "submit",
|
||||
},
|
||||
"Change password"
|
||||
"Change password",
|
||||
) as VnodeDOM;
|
||||
|
||||
form.push(m(".actions-bar", submit));
|
||||
@@ -109,19 +109,19 @@ const component: ClosureComponent<Attrs> = () => {
|
||||
) {
|
||||
notifications.push(
|
||||
"error",
|
||||
"Password confirm doesn't match new password"
|
||||
"Password confirm doesn't match new password",
|
||||
);
|
||||
} else {
|
||||
(submit.dom as HTMLFormElement).disabled = true;
|
||||
changePassword(
|
||||
vnode.state["username"],
|
||||
vnode.state["newPassword"],
|
||||
vnode.state["authPassword"]
|
||||
vnode.state["authPassword"],
|
||||
)
|
||||
.then(() => {
|
||||
notifications.push(
|
||||
"success",
|
||||
"Password updated successfully"
|
||||
"Password updated successfully",
|
||||
);
|
||||
if (onPasswordChange) onPasswordChange();
|
||||
(submit.dom as HTMLFormElement).disabled = false;
|
||||
@@ -133,7 +133,7 @@ const component: ClosureComponent<Attrs> = () => {
|
||||
}
|
||||
},
|
||||
},
|
||||
form
|
||||
form,
|
||||
),
|
||||
];
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ const component: ClosureComponent<Attrs> = () => {
|
||||
if (vnode.attrs.onSubmit) vnode.attrs.onSubmit(_vnode.dom);
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
if (vnode.attrs.onChange) {
|
||||
|
||||
+6
-5
@@ -63,10 +63,11 @@ const vnodeContext = new WeakMap<Vnode, Attributes>();
|
||||
|
||||
interface MC extends Static {
|
||||
context: {
|
||||
(ctx: Attributes, selector: string, ...children: Children[]): Vnode<
|
||||
any,
|
||||
any
|
||||
>;
|
||||
(
|
||||
ctx: Attributes,
|
||||
selector: string,
|
||||
...children: Children[]
|
||||
): Vnode<any, any>;
|
||||
(
|
||||
ctx: Attributes,
|
||||
selector: string,
|
||||
@@ -150,7 +151,7 @@ export function contextifyComponent(component: ComponentTypes): ComponentTypes {
|
||||
title: "Click to print stack trace to console",
|
||||
onclick: () => console.error(err),
|
||||
},
|
||||
"Error!"
|
||||
"Error!",
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -17,14 +17,16 @@
|
||||
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ClosureComponent, Component } from "mithril";
|
||||
import { ClosureComponent } from "mithril";
|
||||
import { m } from "../components";
|
||||
import * as taskQueue from "../task-queue";
|
||||
import { parse } from "../../lib/common/expression/parser";
|
||||
import memoize from "../../lib/common/memoize";
|
||||
import { getIcon } from "../icons";
|
||||
import { evaluateExpression } from "../store";
|
||||
import { QueryResponse, evaluateExpression } from "../store";
|
||||
import debounce from "../../lib/common/debounce";
|
||||
import { Expression } from "../../lib/types";
|
||||
import { FlatDevice } from "../../lib/ui/db";
|
||||
|
||||
const memoizedParse = memoize(parse);
|
||||
|
||||
@@ -52,7 +54,13 @@ function orderKeysByDepth(device: Record<string, unknown>): string[][] {
|
||||
return res;
|
||||
}
|
||||
|
||||
const component: ClosureComponent = (): Component => {
|
||||
interface Attrs {
|
||||
device: FlatDevice;
|
||||
limit: Expression;
|
||||
deviceQuery: QueryResponse;
|
||||
}
|
||||
|
||||
const component: ClosureComponent<Attrs> = () => {
|
||||
let queryString: string;
|
||||
const formQueryString = debounce((args: string[]) => {
|
||||
queryString = args[args.length - 1];
|
||||
@@ -61,9 +69,10 @@ const component: ClosureComponent = (): Component => {
|
||||
|
||||
return {
|
||||
view: (vnode) => {
|
||||
const device = vnode.attrs["device"];
|
||||
const device = vnode.attrs.device;
|
||||
|
||||
const limit = evaluateExpression(vnode.attrs["limit"], device) || 100;
|
||||
const limit =
|
||||
(evaluateExpression(vnode.attrs.limit, device) as number) || 100;
|
||||
|
||||
const search = m("input", {
|
||||
type: "text",
|
||||
@@ -108,8 +117,8 @@ const component: ClosureComponent = (): Component => {
|
||||
val.push(
|
||||
m(
|
||||
"parameter",
|
||||
Object.assign({ device: device, parameter: memoizedParse(k) })
|
||||
)
|
||||
Object.assign({ device: device, parameter: memoizedParse(k) }),
|
||||
),
|
||||
);
|
||||
} else if (p.object && p.writable) {
|
||||
if (instanceRegex.test(k)) {
|
||||
@@ -121,13 +130,13 @@ const component: ClosureComponent = (): Component => {
|
||||
onclick: () => {
|
||||
taskQueue.queueTask({
|
||||
name: "deleteObject",
|
||||
device: device["DeviceID.ID"].value[0],
|
||||
device: device["DeviceID.ID"].value[0] as string,
|
||||
objectName: k,
|
||||
});
|
||||
},
|
||||
},
|
||||
getIcon("delete-instance")
|
||||
)
|
||||
getIcon("delete-instance"),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
val.push(
|
||||
@@ -138,13 +147,13 @@ const component: ClosureComponent = (): Component => {
|
||||
onclick: () => {
|
||||
taskQueue.queueTask({
|
||||
name: "addObject",
|
||||
device: device["DeviceID.ID"].value[0],
|
||||
device: device["DeviceID.ID"].value[0] as string,
|
||||
objectName: k,
|
||||
});
|
||||
},
|
||||
},
|
||||
getIcon("add-instance")
|
||||
)
|
||||
getIcon("add-instance"),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -157,38 +166,38 @@ const component: ClosureComponent = (): Component => {
|
||||
onclick: () => {
|
||||
taskQueue.queueTask({
|
||||
name: "getParameterValues",
|
||||
device: device["DeviceID.ID"].value[0],
|
||||
device: device["DeviceID.ID"].value[0] as string,
|
||||
parameterNames: [k],
|
||||
});
|
||||
},
|
||||
},
|
||||
getIcon("refresh")
|
||||
)
|
||||
getIcon("refresh"),
|
||||
),
|
||||
);
|
||||
|
||||
return m(
|
||||
"tr",
|
||||
attrs,
|
||||
m("td.left", m("long-text", { text: k })),
|
||||
m("td.right", val)
|
||||
m("td.right", val),
|
||||
);
|
||||
});
|
||||
|
||||
return m(
|
||||
"loading",
|
||||
{ queries: [vnode.attrs["deviceQuery"]] },
|
||||
{ queries: [vnode.attrs.deviceQuery] },
|
||||
m(
|
||||
".all-parameters",
|
||||
m(
|
||||
"a.download-csv",
|
||||
{
|
||||
href: `api/devices/${encodeURIComponent(
|
||||
device["DeviceID.ID"].value[0]
|
||||
device["DeviceID.ID"].value[0],
|
||||
)}.csv`,
|
||||
download: "",
|
||||
style: "float: right;",
|
||||
},
|
||||
"Download"
|
||||
"Download",
|
||||
),
|
||||
search,
|
||||
m(
|
||||
@@ -196,10 +205,10 @@ const component: ClosureComponent = (): Component => {
|
||||
m("table", m("tbody", rows)),
|
||||
m(
|
||||
"m",
|
||||
`Displaying ${filteredKeys.length} out of ${count} parameters.`
|
||||
)
|
||||
)
|
||||
)
|
||||
`Displaying ${filteredKeys.length} out of ${count} parameters.`,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -17,18 +17,19 @@
|
||||
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Attributes, ClosureComponent, Component } from "mithril";
|
||||
import { Attributes, ClosureComponent } from "mithril";
|
||||
import { map } from "../../lib/common/expression/parser";
|
||||
import memoize from "../../lib/common/memoize";
|
||||
import { Expression } from "../../lib/types";
|
||||
import { m } from "../components";
|
||||
import { evaluateExpression, getTimestamp } from "../store";
|
||||
import { FlatDevice } from "../../lib/ui/db";
|
||||
|
||||
const evaluateAttributes = memoize(
|
||||
(
|
||||
attrs: Record<string, Expression>,
|
||||
obj: Record<string, unknown>,
|
||||
now: number // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
now: number, // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
): Attributes => {
|
||||
const res: Attributes = {};
|
||||
for (const [k, v] of Object.entries(attrs)) {
|
||||
@@ -47,19 +48,24 @@ const evaluateAttributes = memoize(
|
||||
res[k] = evaluateExpression(vv, obj);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
const component: ClosureComponent = (): Component => {
|
||||
interface Attrs {
|
||||
device: FlatDevice;
|
||||
filter: Expression;
|
||||
components: unknown;
|
||||
}
|
||||
|
||||
const component: ClosureComponent<Attrs> = () => {
|
||||
return {
|
||||
view: (vnode) => {
|
||||
const device = vnode.attrs["device"];
|
||||
const device = vnode.attrs.device;
|
||||
if ("filter" in vnode.attrs) {
|
||||
if (!evaluateExpression(vnode.attrs["filter"], device || {}))
|
||||
return null;
|
||||
if (!evaluateExpression(vnode.attrs.filter, device || {})) return null;
|
||||
}
|
||||
|
||||
const children = Object.values(vnode.attrs["components"]).map((c) => {
|
||||
const children = Object.values(vnode.attrs.components).map((c) => {
|
||||
if (Array.isArray(c)) c = evaluateExpression(c, device || {});
|
||||
if (typeof c !== "object") return `${c}`;
|
||||
const type = evaluateExpression(c["type"], device || {});
|
||||
@@ -79,7 +85,7 @@ const component: ClosureComponent = (): Component => {
|
||||
attrs = evaluateAttributes(
|
||||
el["attributes"],
|
||||
device || {},
|
||||
getTimestamp()
|
||||
getTimestamp(),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -42,8 +42,8 @@ const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Reboot"
|
||||
)
|
||||
"Reboot",
|
||||
),
|
||||
);
|
||||
|
||||
buttons.push(
|
||||
@@ -58,8 +58,8 @@ const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Reset"
|
||||
)
|
||||
"Reset",
|
||||
),
|
||||
);
|
||||
|
||||
buttons.push(
|
||||
@@ -74,8 +74,8 @@ const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Push file"
|
||||
)
|
||||
"Push file",
|
||||
),
|
||||
);
|
||||
|
||||
buttons.push(
|
||||
@@ -98,8 +98,8 @@ const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Delete"
|
||||
)
|
||||
"Delete",
|
||||
),
|
||||
);
|
||||
|
||||
return m(".actions-bar", buttons);
|
||||
|
||||
@@ -76,8 +76,8 @@ const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
getIcon("remove")
|
||||
)
|
||||
getIcon("remove"),
|
||||
),
|
||||
),
|
||||
]);
|
||||
}
|
||||
@@ -86,19 +86,19 @@ const component: ClosureComponent = (): Component => {
|
||||
if (rows.length) {
|
||||
tbody = m(
|
||||
"tbody",
|
||||
rows.map((r) => m("tr", r))
|
||||
rows.map((r) => m("tr", r)),
|
||||
);
|
||||
} else {
|
||||
tbody = m(
|
||||
"tbody",
|
||||
m("tr.empty", m("td", { colspan: headers.length }, "No faults"))
|
||||
m("tr.empty", m("td", { colspan: headers.length }, "No faults")),
|
||||
);
|
||||
}
|
||||
|
||||
return m(
|
||||
"loading",
|
||||
{ queries: [faults] },
|
||||
m("table.table", thead, tbody)
|
||||
m("table.table", thead, tbody),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@ const component: ClosureComponent = (): Component => {
|
||||
return m(
|
||||
"a",
|
||||
{ href: `#!/devices/${encodeURIComponent(deviceId)}` },
|
||||
children
|
||||
children,
|
||||
);
|
||||
} else {
|
||||
return children;
|
||||
|
||||
@@ -47,7 +47,7 @@ const component: ClosureComponent = (): Component => {
|
||||
cy: "0.5em",
|
||||
r: "0.4em",
|
||||
fill: slice["color"],
|
||||
})
|
||||
}),
|
||||
);
|
||||
return m("span.overview-dot", dot, `${slice["label"]}`);
|
||||
}
|
||||
|
||||
@@ -17,24 +17,35 @@
|
||||
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ClosureComponent, Component, VnodeDOM } from "mithril";
|
||||
import { ClosureComponent, VnodeDOM } from "mithril";
|
||||
import { m } from "../components";
|
||||
import { evaluateExpression } from "../store";
|
||||
import { QueryResponse, evaluateExpression } from "../store";
|
||||
import { FlatDevice } from "../../lib/ui/db";
|
||||
import { Expression } from "../../lib/types";
|
||||
|
||||
const component: ClosureComponent = (): Component => {
|
||||
interface Attrs {
|
||||
device: FlatDevice;
|
||||
parameters: Record<
|
||||
string,
|
||||
{ type?: Expression; label: string; parameter: Expression }
|
||||
>;
|
||||
deviceQuery: QueryResponse;
|
||||
}
|
||||
|
||||
const component: ClosureComponent<Attrs> = () => {
|
||||
return {
|
||||
view: (vnode) => {
|
||||
const device = vnode.attrs["device"];
|
||||
const device = vnode.attrs.device;
|
||||
|
||||
const rows = Object.values(vnode.attrs["parameters"]).map((parameter) => {
|
||||
const type = evaluateExpression(parameter["type"], device);
|
||||
const rows = Object.values(vnode.attrs.parameters).map((parameter) => {
|
||||
const type = evaluateExpression(parameter.type, device);
|
||||
const p = m.context(
|
||||
{
|
||||
device: device,
|
||||
parameter: parameter["parameter"],
|
||||
parameter: parameter.parameter,
|
||||
},
|
||||
(type as string) || "parameter",
|
||||
parameter
|
||||
parameter,
|
||||
);
|
||||
|
||||
return m(
|
||||
@@ -52,14 +63,14 @@ const component: ClosureComponent = (): Component => {
|
||||
},
|
||||
},
|
||||
m("th", parameter["label"]),
|
||||
m("td", p)
|
||||
m("td", p),
|
||||
);
|
||||
});
|
||||
|
||||
return m(
|
||||
"loading",
|
||||
{ queries: [vnode.attrs["deviceQuery"]] },
|
||||
m("table.parameter-list", rows)
|
||||
{ queries: [vnode.attrs.deviceQuery] },
|
||||
m("table.parameter-list", rows),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -17,24 +17,35 @@
|
||||
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ClosureComponent, Component } from "mithril";
|
||||
import { ClosureComponent } from "mithril";
|
||||
import { m } from "../components";
|
||||
import * as taskQueue from "../task-queue";
|
||||
import { evaluateExpression } from "../store";
|
||||
import { QueryResponse, evaluateExpression } from "../store";
|
||||
import * as expressionParser from "../../lib/common/expression/parser";
|
||||
import { getIcon } from "../icons";
|
||||
import { FlatDevice } from "../../lib/ui/db";
|
||||
import { Expression } from "../../lib/types";
|
||||
|
||||
const component: ClosureComponent = (): Component => {
|
||||
interface Attrs {
|
||||
device: FlatDevice;
|
||||
parameter: Expression;
|
||||
label: Expression;
|
||||
childParameters: Record<string, { label: string; parameter: Expression }>;
|
||||
filter?: Expression;
|
||||
deviceQuery: QueryResponse;
|
||||
}
|
||||
|
||||
const component: ClosureComponent<Attrs> = () => {
|
||||
return {
|
||||
oninit: (vnode) => {
|
||||
const obj = vnode.attrs["parameter"];
|
||||
const obj = vnode.attrs.parameter;
|
||||
if (!Array.isArray(obj) || obj[0] !== "PARAM")
|
||||
throw new Error("Object must be a parameter path");
|
||||
vnode.state["object"] = obj[1];
|
||||
vnode.state["parameters"] = Object.values(vnode.attrs["childParameters"]);
|
||||
vnode.state["parameters"] = Object.values(vnode.attrs.childParameters);
|
||||
},
|
||||
view: (vnode) => {
|
||||
const device = vnode.attrs["device"];
|
||||
const device = vnode.attrs.device;
|
||||
const object = evaluateExpression(vnode.state["object"], device);
|
||||
const parameters = vnode.state["parameters"];
|
||||
|
||||
@@ -56,7 +67,7 @@ const component: ClosureComponent = (): Component => {
|
||||
|
||||
const rows = [];
|
||||
for (const i of instances) {
|
||||
let filter = "filter" in vnode.attrs ? vnode.attrs["filter"] : true;
|
||||
let filter = "filter" in vnode.attrs ? vnode.attrs.filter : true;
|
||||
|
||||
filter = expressionParser.map(filter, (e) => {
|
||||
if (Array.isArray(e) && e[0] === "PARAM")
|
||||
@@ -84,8 +95,8 @@ const component: ClosureComponent = (): Component => {
|
||||
device: device,
|
||||
parameter: param,
|
||||
label: null,
|
||||
})
|
||||
)
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
@@ -100,14 +111,14 @@ const component: ClosureComponent = (): Component => {
|
||||
onclick: () => {
|
||||
taskQueue.queueTask({
|
||||
name: "deleteObject",
|
||||
device: device["DeviceID.ID"].value[0],
|
||||
device: device["DeviceID.ID"].value[0] as string,
|
||||
objectName: i,
|
||||
});
|
||||
},
|
||||
},
|
||||
getIcon("delete-instance")
|
||||
)
|
||||
)
|
||||
getIcon("delete-instance"),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
rows.push(m("tr", row));
|
||||
@@ -115,7 +126,7 @@ const component: ClosureComponent = (): Component => {
|
||||
|
||||
if (!rows.length) {
|
||||
rows.push(
|
||||
m("tr.empty", m("td", { colspan: headers.length }, "No instances"))
|
||||
m("tr.empty", m("td", { colspan: headers.length }, "No instances")),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -133,29 +144,29 @@ const component: ClosureComponent = (): Component => {
|
||||
onclick: () => {
|
||||
taskQueue.queueTask({
|
||||
name: "addObject",
|
||||
device: device["DeviceID.ID"].value[0],
|
||||
device: device["DeviceID.ID"].value[0] as string,
|
||||
objectName: object,
|
||||
});
|
||||
},
|
||||
},
|
||||
getIcon("add-instance")
|
||||
)
|
||||
)
|
||||
)
|
||||
getIcon("add-instance"),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
let label;
|
||||
|
||||
const l = evaluateExpression(vnode.attrs["label"], device);
|
||||
const l = evaluateExpression(vnode.attrs.label, device);
|
||||
if (l != null) label = m("h2", l);
|
||||
|
||||
return [
|
||||
label,
|
||||
m(
|
||||
"loading",
|
||||
{ queries: [vnode.attrs["deviceQuery"]] },
|
||||
m("table.table", thead, m("tbody", rows))
|
||||
{ queries: [vnode.attrs.deviceQuery] },
|
||||
m("table.table", thead, m("tbody", rows)),
|
||||
),
|
||||
];
|
||||
},
|
||||
|
||||
@@ -78,7 +78,7 @@ const component: ClosureComponent = (): Component => {
|
||||
const { value, timestamp, parameter } = evaluateParam(
|
||||
vnode.attrs["parameter"],
|
||||
device,
|
||||
store.getTimestamp() + store.getClockSkew()
|
||||
store.getTimestamp() + store.getClockSkew(),
|
||||
);
|
||||
|
||||
if (value == null) return null;
|
||||
@@ -103,7 +103,7 @@ const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
getIcon("edit")
|
||||
getIcon("edit"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -124,7 +124,7 @@ const component: ClosureComponent = (): Component => {
|
||||
},
|
||||
},
|
||||
el,
|
||||
edit
|
||||
edit,
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -62,19 +62,19 @@ const component: ClosureComponent = (): Component => {
|
||||
if (connectionRequestStatus !== "OK") {
|
||||
notifications.push(
|
||||
"error",
|
||||
`${deviceId}: ${connectionRequestStatus}`
|
||||
`${deviceId}: ${connectionRequestStatus}`,
|
||||
);
|
||||
} else if (tasks2[0].status === "stale") {
|
||||
notifications.push(
|
||||
"error",
|
||||
`${deviceId}: No contact from device`
|
||||
`${deviceId}: No contact from device`,
|
||||
);
|
||||
} else if (tasks2[0].status === "fault") {
|
||||
notifications.push("error", `${deviceId}: Refresh faulted`);
|
||||
} else {
|
||||
notifications.push("success", `${deviceId}: Summoned`);
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
.then(() => {
|
||||
e.target.disabled = false;
|
||||
@@ -86,7 +86,7 @@ const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Summon"
|
||||
"Summon",
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
+22
-15
@@ -17,20 +17,27 @@
|
||||
* along with GenieACS. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { ClosureComponent, Component } from "mithril";
|
||||
import { ClosureComponent } from "mithril";
|
||||
import { m } from "../components";
|
||||
import * as notifications from "../notifications";
|
||||
import * as store from "../store";
|
||||
import { getIcon } from "../icons";
|
||||
import { decodeTag } from "../../lib/util";
|
||||
import { Expression } from "../../lib/types";
|
||||
import { FlatDevice } from "../../lib/ui/db";
|
||||
|
||||
const component: ClosureComponent = (): Component => {
|
||||
interface Attrs {
|
||||
device: FlatDevice;
|
||||
writable?: Expression;
|
||||
}
|
||||
|
||||
const component: ClosureComponent<Attrs> = () => {
|
||||
return {
|
||||
view: (vnode) => {
|
||||
const device = vnode.attrs["device"];
|
||||
const device = vnode.attrs.device;
|
||||
let writable = true;
|
||||
if ("writable" in vnode.attrs)
|
||||
writable = !!store.evaluateExpression(vnode.attrs["writable"], device);
|
||||
writable = !!store.evaluateExpression(vnode.attrs.writable, device);
|
||||
|
||||
const tags = [];
|
||||
for (const p of Object.keys(device))
|
||||
@@ -41,7 +48,7 @@ const component: ClosureComponent = (): Component => {
|
||||
if (!writable) {
|
||||
return m(
|
||||
".tags",
|
||||
tags.map((t) => m("span.tag", t))
|
||||
tags.map((t) => m("span.tag", t)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,14 +63,14 @@ const component: ClosureComponent = (): Component => {
|
||||
{
|
||||
onclick: (e) => {
|
||||
e.target.disabled = true;
|
||||
const deviceId = device["DeviceID.ID"].value[0];
|
||||
const deviceId = device["DeviceID.ID"].value[0] as string;
|
||||
store
|
||||
.updateTags(deviceId, { [tag]: false })
|
||||
.then(() => {
|
||||
e.target.disabled = false;
|
||||
notifications.push(
|
||||
"success",
|
||||
`${deviceId}: Tags updated`
|
||||
`${deviceId}: Tags updated`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
})
|
||||
@@ -71,14 +78,14 @@ const component: ClosureComponent = (): Component => {
|
||||
e.target.disabled = false;
|
||||
notifications.push(
|
||||
"error",
|
||||
`${deviceId}: ${err.message}`
|
||||
`${deviceId}: ${err.message}`,
|
||||
);
|
||||
});
|
||||
},
|
||||
},
|
||||
getIcon("remove")
|
||||
)
|
||||
)
|
||||
getIcon("remove"),
|
||||
),
|
||||
),
|
||||
),
|
||||
m(
|
||||
"span.tag.writable",
|
||||
@@ -88,7 +95,7 @@ const component: ClosureComponent = (): Component => {
|
||||
{
|
||||
onclick: (e) => {
|
||||
e.target.disabled = true;
|
||||
const deviceId = device["DeviceID.ID"].value[0];
|
||||
const deviceId = device["DeviceID.ID"].value[0] as string;
|
||||
const tag = prompt(`Enter tag to assign to device:`);
|
||||
if (!tag) {
|
||||
e.target.disabled = false;
|
||||
@@ -108,9 +115,9 @@ const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
getIcon("add")
|
||||
)
|
||||
)
|
||||
getIcon("add"),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -129,7 +129,7 @@ export function structureConfig(config: Config[]): any {
|
||||
|
||||
export function diffConfig(
|
||||
current: Record<string, unknown>,
|
||||
target: Record<string, unknown>
|
||||
target: Record<string, unknown>,
|
||||
): Diff {
|
||||
const diff = {
|
||||
add: [],
|
||||
|
||||
+24
-24
@@ -74,7 +74,7 @@ function putActionHandler(action, _object, isNew?): Promise<ValidationErrors> {
|
||||
.then(() => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`Config ${exists ? "updated" : "created"}`
|
||||
`Config ${exists ? "updated" : "created"}`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
resolve(null);
|
||||
@@ -112,7 +112,7 @@ function escapeRegExp(str): string {
|
||||
export function init(): Promise<Record<string, unknown>> {
|
||||
if (!window.authorizer.hasAccess("config", 2)) {
|
||||
return Promise.reject(
|
||||
new Error("You are not authorized to view this page")
|
||||
new Error("You are not authorized to view this page"),
|
||||
);
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -173,19 +173,19 @@ function renderTable(confsResponse, searchString): Children {
|
||||
});
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = () => comp;
|
||||
overlay.open(
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
getIcon("edit")
|
||||
getIcon("edit"),
|
||||
);
|
||||
|
||||
const del = m(
|
||||
@@ -200,7 +200,7 @@ function renderTable(confsResponse, searchString): Children {
|
||||
});
|
||||
},
|
||||
},
|
||||
getIcon("remove")
|
||||
getIcon("remove"),
|
||||
);
|
||||
|
||||
rows.push(
|
||||
@@ -210,9 +210,9 @@ function renderTable(confsResponse, searchString): Children {
|
||||
m("td.left", m("long-text", { text: conf._id })),
|
||||
m(
|
||||
"td.right",
|
||||
m("span", [m("long-text", { text: `${conf.value}` }), edit, del])
|
||||
)
|
||||
)
|
||||
m("span", [m("long-text", { text: `${conf.value}` }), edit, del]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -276,19 +276,19 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = () => comp;
|
||||
overlay.open(
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
"New config"
|
||||
"New config",
|
||||
);
|
||||
|
||||
const subsData = [
|
||||
@@ -332,8 +332,8 @@ export const component: ClosureComponent = (): Component => {
|
||||
"success",
|
||||
`${sub.name.replace(
|
||||
/^[a-z]/,
|
||||
sub.name[0].toUpperCase()
|
||||
)} config updated`
|
||||
sub.name[0].toUpperCase(),
|
||||
)} config updated`,
|
||||
);
|
||||
overlay.close(cb);
|
||||
}
|
||||
@@ -345,20 +345,20 @@ export const component: ClosureComponent = (): Component => {
|
||||
overlay.close(cb);
|
||||
},
|
||||
},
|
||||
attrs
|
||||
)
|
||||
attrs,
|
||||
),
|
||||
);
|
||||
cb = () => comp;
|
||||
overlay.open(
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
`Edit ${sub.name}`
|
||||
)
|
||||
`Edit ${sub.name}`,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -374,10 +374,10 @@ export const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
".parameter-list",
|
||||
{ style: "height: 400px" },
|
||||
renderTable(confs, vnode.state["searchString"])
|
||||
renderTable(confs, vnode.state["searchString"]),
|
||||
),
|
||||
m(".actions-bar", [newConfig].concat(subs))
|
||||
)
|
||||
m(".actions-bar", [newConfig].concat(subs)),
|
||||
),
|
||||
),
|
||||
];
|
||||
},
|
||||
|
||||
+18
-6
@@ -54,7 +54,9 @@ textarea {
|
||||
a {
|
||||
color: var(--color4);
|
||||
cursor: pointer;
|
||||
transition: background-color var(--fade), color var(--fade);
|
||||
transition:
|
||||
background-color var(--fade),
|
||||
color var(--fade);
|
||||
&:visited {
|
||||
color: var(--color4);
|
||||
}
|
||||
@@ -122,7 +124,9 @@ body {
|
||||
margin-top: -1px;
|
||||
box-shadow: 0 0 10px #ccc;
|
||||
overflow: hidden;
|
||||
transition: height var(--fade), opacity var(--fade);
|
||||
transition:
|
||||
height var(--fade),
|
||||
opacity var(--fade);
|
||||
|
||||
& > div {
|
||||
padding: 0.3em;
|
||||
@@ -228,7 +232,9 @@ body {
|
||||
border: 1px solid var(--color1);
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 0 10px #ccc;
|
||||
transition: opacity var(--fade), top var(--fade);
|
||||
transition:
|
||||
opacity var(--fade),
|
||||
top var(--fade);
|
||||
|
||||
&.error {
|
||||
background-color: hsl(var(--status-red) / 0.9);
|
||||
@@ -437,7 +443,9 @@ button {
|
||||
border: 0;
|
||||
color: var(--color4);
|
||||
border-radius: 4px;
|
||||
transition: background-color var(--fade), color var(--fade);
|
||||
transition:
|
||||
background-color var(--fade),
|
||||
color var(--fade);
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
||||
@@ -468,7 +476,9 @@ input {
|
||||
border: 1px solid var(--color1);
|
||||
background-color: var(--color3);
|
||||
border-radius: 4px;
|
||||
transition: border-color var(--fade), background-color var(--fade);
|
||||
transition:
|
||||
border-color var(--fade),
|
||||
background-color var(--fade);
|
||||
&.error {
|
||||
background-color: #efcbcf;
|
||||
border-color: #e6b2b7;
|
||||
@@ -670,7 +680,9 @@ span.tag {
|
||||
bottom: 0;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
z-index: 100;
|
||||
transition: opacity var(--fade), top var(--fade);
|
||||
transition:
|
||||
opacity var(--fade),
|
||||
top var(--fade);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ export function getDatalistId(options: string[]): string {
|
||||
const n = m(
|
||||
"datalist",
|
||||
{ id },
|
||||
options.map((o) => m("option", { value: o }))
|
||||
options.map((o) => m("option", { value: o })),
|
||||
);
|
||||
elements.set(id, n);
|
||||
}
|
||||
|
||||
+4
-4
@@ -23,11 +23,11 @@ import config from "./config";
|
||||
import * as store from "./store";
|
||||
|
||||
export function init(
|
||||
args: Record<string, unknown>
|
||||
args: Record<string, unknown>,
|
||||
): Promise<Record<string, unknown>> {
|
||||
if (!window.authorizer.hasAccess("devices", 2)) {
|
||||
return Promise.reject(
|
||||
new Error("You are not authorized to view this page")
|
||||
new Error("You are not authorized to view this page"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
return m(
|
||||
"loading",
|
||||
{ queries: [dev] },
|
||||
m("div", { style: "height: 100px;" })
|
||||
m("div", { style: "height: 100px;" }),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
|
||||
for (const c of Object.values(conf)) {
|
||||
cmps.push(
|
||||
m.context({ device: dev.value[0], deviceQuery: dev }, c["type"], c)
|
||||
m.context({ device: dev.value[0], deviceQuery: dev }, c["type"], c),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+18
-18
@@ -61,7 +61,7 @@ const unpackSmartQuery = memoize((query) => {
|
||||
});
|
||||
|
||||
export function init(
|
||||
args: Record<string, unknown>
|
||||
args: Record<string, unknown>,
|
||||
): Promise<Record<string, unknown>> {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!window.authorizer.hasAccess("devices", 2))
|
||||
@@ -97,8 +97,8 @@ function renderActions(selected: Set<string>): Children {
|
||||
queueTask(...tasks);
|
||||
},
|
||||
},
|
||||
"Reboot"
|
||||
)
|
||||
"Reboot",
|
||||
),
|
||||
);
|
||||
|
||||
buttons.push(
|
||||
@@ -115,8 +115,8 @@ function renderActions(selected: Set<string>): Children {
|
||||
queueTask(...tasks);
|
||||
},
|
||||
},
|
||||
"Reset"
|
||||
)
|
||||
"Reset",
|
||||
),
|
||||
);
|
||||
|
||||
buttons.push(
|
||||
@@ -132,8 +132,8 @@ function renderActions(selected: Set<string>): Children {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Push file"
|
||||
)
|
||||
"Push file",
|
||||
),
|
||||
);
|
||||
|
||||
buttons.push(
|
||||
@@ -163,8 +163,8 @@ function renderActions(selected: Set<string>): Children {
|
||||
if (--counter === 0) store.setTimestamp(Date.now());
|
||||
},
|
||||
},
|
||||
"Delete"
|
||||
)
|
||||
"Delete",
|
||||
),
|
||||
);
|
||||
|
||||
buttons.push(
|
||||
@@ -195,8 +195,8 @@ function renderActions(selected: Set<string>): Children {
|
||||
if (--counter === 0) store.setTimestamp(Date.now());
|
||||
},
|
||||
},
|
||||
"Tag"
|
||||
)
|
||||
"Tag",
|
||||
),
|
||||
);
|
||||
|
||||
buttons.push(
|
||||
@@ -208,7 +208,7 @@ function renderActions(selected: Set<string>): Children {
|
||||
onclick: () => {
|
||||
const ids = Array.from(selected);
|
||||
const tag = prompt(
|
||||
`Enter tag to unassign from ${ids.length} devices:`
|
||||
`Enter tag to unassign from ${ids.length} devices:`,
|
||||
);
|
||||
if (!tag) return;
|
||||
|
||||
@@ -229,8 +229,8 @@ function renderActions(selected: Set<string>): Children {
|
||||
if (--counter === 0) store.setTimestamp(Date.now());
|
||||
},
|
||||
},
|
||||
"Untag"
|
||||
)
|
||||
"Untag",
|
||||
),
|
||||
);
|
||||
|
||||
return buttons;
|
||||
@@ -270,7 +270,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
const _sort = {};
|
||||
for (const index of sortedAttrs) {
|
||||
const param = memoizedGetSortable(
|
||||
attributes[Math.abs(index) - 1].parameter
|
||||
attributes[Math.abs(index) - 1].parameter,
|
||||
);
|
||||
_sort[param] = Math.sign(index);
|
||||
}
|
||||
@@ -296,7 +296,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
return m.context(
|
||||
{ device: device, parameter: attr.parameter },
|
||||
attr.type || "parameter",
|
||||
attr
|
||||
attr,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -314,10 +314,10 @@ export const component: ClosureComponent = (): Component => {
|
||||
"a",
|
||||
{
|
||||
href: `#!/devices/${encodeURIComponent(
|
||||
device["DeviceID.ID"].value[0]
|
||||
device["DeviceID.ID"].value[0],
|
||||
)}`,
|
||||
},
|
||||
"Show"
|
||||
"Show",
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
+51
-51
@@ -73,7 +73,7 @@ function renderStagingSpv(task: StageTask, queueFunc, cancelFunc): Children {
|
||||
[
|
||||
m("option", { value: "true" }, "true"),
|
||||
m("option", { value: "false" }, "false"),
|
||||
]
|
||||
],
|
||||
);
|
||||
} else {
|
||||
const type = task.parameterValues[0][2];
|
||||
@@ -134,8 +134,8 @@ function renderStagingDownload(task: StageTask): Children {
|
||||
m(
|
||||
"option",
|
||||
{ disabled: !t, value: t, selected: (task.fileType || "") === t },
|
||||
t
|
||||
)
|
||||
t,
|
||||
),
|
||||
);
|
||||
|
||||
const filesList = [""]
|
||||
@@ -145,16 +145,16 @@ function renderStagingDownload(task: StageTask): Children {
|
||||
(f) =>
|
||||
(!f["metadata.oui"] || f["metadata.oui"] === oui) &&
|
||||
(!f["metadata.productClass"] ||
|
||||
f["metadata.productClass"] === productClass)
|
||||
f["metadata.productClass"] === productClass),
|
||||
)
|
||||
.map((f) => f._id)
|
||||
.map((f) => f._id),
|
||||
)
|
||||
.map((f) =>
|
||||
m(
|
||||
"option",
|
||||
{ disabled: !f, value: f, selected: (task.fileName || "") === f },
|
||||
f
|
||||
)
|
||||
f,
|
||||
),
|
||||
);
|
||||
|
||||
return [
|
||||
@@ -172,7 +172,7 @@ function renderStagingDownload(task: StageTask): Children {
|
||||
disabled: files.fulfilling,
|
||||
style: "width: 350px",
|
||||
},
|
||||
filesList
|
||||
filesList,
|
||||
),
|
||||
" as ",
|
||||
m(
|
||||
@@ -182,7 +182,7 @@ function renderStagingDownload(task: StageTask): Children {
|
||||
task.fileType = e.target.value;
|
||||
},
|
||||
},
|
||||
typesList
|
||||
typesList,
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -211,12 +211,12 @@ function renderStaging(staging: Set<StageTask>): Child[] {
|
||||
const queue = m(
|
||||
"button.primary",
|
||||
{ title: "Queue task", onclick: queueFunc, disabled: invalid.has(s) },
|
||||
"Queue"
|
||||
"Queue",
|
||||
);
|
||||
const cancel = m(
|
||||
"button",
|
||||
{ title: "Cancel edit", onclick: cancelFunc },
|
||||
"Cancel"
|
||||
"Cancel",
|
||||
);
|
||||
|
||||
elements.push(m(".staging", elms, m("div.actions", queue, cancel)));
|
||||
@@ -247,8 +247,8 @@ function renderQueue(queue: Set<QueueTask>): Child[] {
|
||||
queueTask(t);
|
||||
},
|
||||
},
|
||||
getIcon("retry")
|
||||
)
|
||||
getIcon("retry"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -261,8 +261,8 @@ function renderQueue(queue: Set<QueueTask>): Child[] {
|
||||
deleteTask(t);
|
||||
},
|
||||
},
|
||||
getIcon("remove")
|
||||
)
|
||||
getIcon("remove"),
|
||||
),
|
||||
);
|
||||
|
||||
if (t.name === "setParameterValues") {
|
||||
@@ -275,56 +275,56 @@ function renderQueue(queue: Set<QueueTask>): Child[] {
|
||||
mparam(t.parameterValues[0][0]),
|
||||
" to '",
|
||||
mval(t.parameterValues[0][1]),
|
||||
"'"
|
||||
"'",
|
||||
),
|
||||
m(".actions", actions)
|
||||
)
|
||||
m(".actions", actions),
|
||||
),
|
||||
);
|
||||
} else if (t.name === "refreshObject") {
|
||||
details.push(
|
||||
m(
|
||||
`div.${t.status}`,
|
||||
m("span", "Refresh ", mparam(t.parameterName)),
|
||||
m(".actions", actions)
|
||||
)
|
||||
m(".actions", actions),
|
||||
),
|
||||
);
|
||||
} else if (t.name === "reboot") {
|
||||
details.push(m(`div.${t.status}`, "Reboot", m(".actions", actions)));
|
||||
} else if (t.name === "factoryReset") {
|
||||
details.push(
|
||||
m(`div.${t.status}`, "Factory reset", m(".actions", actions))
|
||||
m(`div.${t.status}`, "Factory reset", m(".actions", actions)),
|
||||
);
|
||||
} else if (t.name === "addObject") {
|
||||
details.push(
|
||||
m(
|
||||
`div.${t.status}`,
|
||||
m("span", "Add ", mparam(t.objectName)),
|
||||
m(".actions", actions)
|
||||
)
|
||||
m(".actions", actions),
|
||||
),
|
||||
);
|
||||
} else if (t.name === "deleteObject") {
|
||||
details.push(
|
||||
m(
|
||||
`div.${t.status}`,
|
||||
m("span", "Delete ", mparam(t.objectName)),
|
||||
m(".actions", actions)
|
||||
)
|
||||
m(".actions", actions),
|
||||
),
|
||||
);
|
||||
} else if (t.name === "getParameterValues") {
|
||||
details.push(
|
||||
m(
|
||||
`div.${t.status}`,
|
||||
`Refresh ${t.parameterNames.length} parameters`,
|
||||
m(".actions", actions)
|
||||
)
|
||||
m(".actions", actions),
|
||||
),
|
||||
);
|
||||
} else if (t.name === "download") {
|
||||
details.push(
|
||||
m(
|
||||
`div.${t.status}`,
|
||||
`Push file: ${t.fileName} (${t.fileType})`,
|
||||
m(".actions", actions)
|
||||
)
|
||||
m(".actions", actions),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
details.push(m(`div.${t.status}`, t.name, m(".actions", actions)));
|
||||
@@ -342,7 +342,7 @@ function renderNotifications(notifs): Child[] {
|
||||
let buttons;
|
||||
if (n.actions) {
|
||||
const btns = Object.entries(n.actions).map(([label, onclick]) =>
|
||||
m("button.primary", { onclick: onclick }, label)
|
||||
m("button.primary", { onclick: onclick }, label),
|
||||
);
|
||||
if (btns.length) buttons = m("div", { style: "float: right" }, btns);
|
||||
}
|
||||
@@ -366,8 +366,8 @@ function renderNotifications(notifs): Child[] {
|
||||
},
|
||||
key: n.timestamp,
|
||||
},
|
||||
m("div", buttons, n.message)
|
||||
)
|
||||
m("div", buttons, n.message),
|
||||
),
|
||||
);
|
||||
}
|
||||
return notificationElements;
|
||||
@@ -401,7 +401,7 @@ const component: ClosureComponent = (): Component => {
|
||||
height = Math.max(
|
||||
height,
|
||||
(s.dom as HTMLDivElement).offsetTop +
|
||||
(s.dom as HTMLDivElement).offsetHeight
|
||||
(s.dom as HTMLDivElement).offsetHeight,
|
||||
);
|
||||
}
|
||||
} else if (vnode.state["mouseIn"]) {
|
||||
@@ -424,7 +424,7 @@ const component: ClosureComponent = (): Component => {
|
||||
disabled: !statusCount.queued,
|
||||
onclick: () => {
|
||||
const tasks = Array.from(getQueue()).filter(
|
||||
(t) => t["status"] === "queued"
|
||||
(t) => t["status"] === "queued",
|
||||
);
|
||||
commit(
|
||||
tasks,
|
||||
@@ -432,7 +432,7 @@ const component: ClosureComponent = (): Component => {
|
||||
if (err) {
|
||||
notifications.push(
|
||||
"error",
|
||||
`${deviceId}: ${err.message}`
|
||||
`${deviceId}: ${err.message}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -440,7 +440,7 @@ const component: ClosureComponent = (): Component => {
|
||||
if (connectionRequestStatus !== "OK") {
|
||||
notifications.push(
|
||||
"error",
|
||||
`${deviceId}: ${connectionRequestStatus}`
|
||||
`${deviceId}: ${connectionRequestStatus}`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -449,13 +449,13 @@ const component: ClosureComponent = (): Component => {
|
||||
if (t.status === "stale") {
|
||||
notifications.push(
|
||||
"error",
|
||||
`${deviceId}: No contact from device`
|
||||
`${deviceId}: No contact from device`,
|
||||
);
|
||||
return;
|
||||
} else if (t.status === "fault") {
|
||||
notifications.push(
|
||||
"error",
|
||||
`${deviceId}: Task(s) faulted`
|
||||
`${deviceId}: Task(s) faulted`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
@@ -463,9 +463,9 @@ const component: ClosureComponent = (): Component => {
|
||||
|
||||
notifications.push(
|
||||
"success",
|
||||
`${deviceId}: Task(s) committed`
|
||||
`${deviceId}: Task(s) committed`,
|
||||
);
|
||||
}
|
||||
},
|
||||
)
|
||||
.then(() => {
|
||||
store.setTimestamp(Date.now());
|
||||
@@ -475,7 +475,7 @@ const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Commit"
|
||||
"Commit",
|
||||
),
|
||||
m(
|
||||
"button",
|
||||
@@ -484,8 +484,8 @@ const component: ClosureComponent = (): Component => {
|
||||
onclick: clear,
|
||||
disabled: !queueElements.length,
|
||||
},
|
||||
"Clear"
|
||||
)
|
||||
"Clear",
|
||||
),
|
||||
);
|
||||
|
||||
statusElement = m(
|
||||
@@ -493,24 +493,24 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"span.queued",
|
||||
{ class: statusCount.queued ? "active" : "" },
|
||||
`Queued: ${statusCount.queued}`
|
||||
`Queued: ${statusCount.queued}`,
|
||||
),
|
||||
m(
|
||||
"span.pending",
|
||||
{ class: statusCount.pending ? "active" : "" },
|
||||
`Pending: ${statusCount.pending}`
|
||||
`Pending: ${statusCount.pending}`,
|
||||
),
|
||||
m(
|
||||
"span.fault",
|
||||
{ class: statusCount.fault ? "active" : "" },
|
||||
`Fault: ${statusCount.fault}`
|
||||
`Fault: ${statusCount.fault}`,
|
||||
),
|
||||
m(
|
||||
"span.stale",
|
||||
{ class: statusCount.stale ? "active" : "" },
|
||||
`Stale: ${statusCount.stale}`
|
||||
`Stale: ${statusCount.stale}`,
|
||||
),
|
||||
actions
|
||||
actions,
|
||||
);
|
||||
|
||||
drawerElement = m(
|
||||
@@ -545,7 +545,7 @@ const component: ClosureComponent = (): Component => {
|
||||
},
|
||||
},
|
||||
statusElement,
|
||||
stagingElements.length ? stagingElements : m(".queue", queueElements)
|
||||
stagingElements.length ? stagingElements : m(".queue", queueElements),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -560,8 +560,8 @@ const component: ClosureComponent = (): Component => {
|
||||
onupdate: repositionNotifications,
|
||||
oncreate: repositionNotifications,
|
||||
},
|
||||
notificationElements
|
||||
)
|
||||
notificationElements,
|
||||
),
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -33,7 +33,7 @@ function onError(): void {
|
||||
Reload: () => {
|
||||
window.location.reload();
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -65,7 +65,7 @@ export function loadYaml(): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
import("yaml")
|
||||
.then((module) => {
|
||||
yaml = module;
|
||||
yaml = module.default;
|
||||
resolve();
|
||||
})
|
||||
.catch((err) => {
|
||||
|
||||
+8
-8
@@ -66,11 +66,11 @@ const unpackSmartQuery = memoize((query) => {
|
||||
});
|
||||
|
||||
export function init(
|
||||
args: Record<string, unknown>
|
||||
args: Record<string, unknown>,
|
||||
): Promise<Record<string, unknown>> {
|
||||
if (!window.authorizer.hasAccess("faults", 2)) {
|
||||
return Promise.reject(
|
||||
new Error("You are not authorized to view this page")
|
||||
new Error("You are not authorized to view this page"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
const valueCallback = (attr, fault): Children => {
|
||||
if (attr.id === "device") {
|
||||
const deviceHref = `#!/devices/${encodeURIComponent(
|
||||
fault["device"]
|
||||
fault["device"],
|
||||
)}`;
|
||||
|
||||
return m("a", { href: deviceHref }, fault["device"]);
|
||||
@@ -175,13 +175,13 @@ export const component: ClosureComponent = (): Component => {
|
||||
|
||||
Promise.all(
|
||||
Array.from(selected).map((id) =>
|
||||
store.deleteResource("faults", id)
|
||||
)
|
||||
store.deleteResource("faults", id),
|
||||
),
|
||||
)
|
||||
.then((res) => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`${res.length} faults deleted`
|
||||
`${res.length} faults deleted`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
})
|
||||
@@ -191,7 +191,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Delete"
|
||||
"Delete",
|
||||
);
|
||||
};
|
||||
}
|
||||
@@ -208,7 +208,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"loading",
|
||||
{ queries: [faults, count] },
|
||||
m(indexTableComponent, attrs)
|
||||
m(indexTableComponent, attrs),
|
||||
),
|
||||
];
|
||||
},
|
||||
|
||||
+14
-14
@@ -77,13 +77,13 @@ function upload(
|
||||
file: File,
|
||||
headers: Record<string, string>,
|
||||
abortSignal?: AbortSignal,
|
||||
progressListener?: (e: ProgressEvent) => void
|
||||
progressListener?: (e: ProgressEvent) => void,
|
||||
): Promise<void> {
|
||||
headers = Object.assign(
|
||||
{
|
||||
"Content-Type": "application/octet-stream",
|
||||
},
|
||||
headers
|
||||
headers,
|
||||
);
|
||||
return store.xhrRequest({
|
||||
method: "PUT",
|
||||
@@ -112,11 +112,11 @@ const getDownloadUrl = memoize((filter) => {
|
||||
});
|
||||
|
||||
export function init(
|
||||
args: Record<string, unknown>
|
||||
args: Record<string, unknown>,
|
||||
): Promise<Record<string, unknown>> {
|
||||
if (!window.authorizer.hasAccess("files", 2)) {
|
||||
return Promise.reject(
|
||||
new Error("You are not authorized to view this page")
|
||||
new Error("You are not authorized to view this page"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
file,
|
||||
headers,
|
||||
abortController.signal,
|
||||
progressListener
|
||||
progressListener,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
notifications.push("success", "File created");
|
||||
@@ -247,8 +247,8 @@ export const component: ClosureComponent = (): Component => {
|
||||
progress = -1;
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = () => {
|
||||
if (progress < 0) return [null, comp];
|
||||
@@ -257,7 +257,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
"div.progress",
|
||||
m("div.progress-bar", {
|
||||
style: `width: ${Math.trunc(progress * 100)}%`,
|
||||
})
|
||||
}),
|
||||
),
|
||||
comp,
|
||||
];
|
||||
@@ -273,7 +273,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"New"
|
||||
"New",
|
||||
),
|
||||
m(
|
||||
"button.primary",
|
||||
@@ -290,13 +290,13 @@ export const component: ClosureComponent = (): Component => {
|
||||
e.target.disabled = true;
|
||||
Promise.all(
|
||||
Array.from(selected).map((id) =>
|
||||
store.deleteResource("files", id)
|
||||
)
|
||||
store.deleteResource("files", id),
|
||||
),
|
||||
)
|
||||
.then((res) => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`${res.length} files deleted`
|
||||
`${res.length} files deleted`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
})
|
||||
@@ -306,7 +306,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Delete"
|
||||
"Delete",
|
||||
),
|
||||
];
|
||||
};
|
||||
@@ -324,7 +324,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"loading",
|
||||
{ queries: [files, count] },
|
||||
m(indexTableComponent, attrs)
|
||||
m(indexTableComponent, attrs),
|
||||
),
|
||||
];
|
||||
},
|
||||
|
||||
@@ -35,7 +35,7 @@ const getAutocomplete = memoize((resource) => {
|
||||
.map((s) => ({
|
||||
value: `${s}: `,
|
||||
tip: smartQuery.getTip(resource, s),
|
||||
}))
|
||||
})),
|
||||
);
|
||||
});
|
||||
return autocomplete;
|
||||
|
||||
+1
-1
@@ -25,6 +25,6 @@ export function getIcon(name: string): Children {
|
||||
return m(
|
||||
`svg.icon.icon-${name}`,
|
||||
{ key: `icon-${name}` },
|
||||
m("use", { href: `${ICONS_SVG}#icon-${name}` })
|
||||
m("use", { href: `${ICONS_SVG}#icon-${name}` }),
|
||||
);
|
||||
}
|
||||
+13
-11
@@ -41,7 +41,9 @@ function renderTable(
|
||||
downloadUrl?: string,
|
||||
valueCallback?: (attr: Attribute, record: Record<string, any>) => Children,
|
||||
actionsCallback?: Children | ((sel: Set<string>) => Children),
|
||||
recordActionsCallback?: Children | ((record: Record<string, any>) => Children)
|
||||
recordActionsCallback?:
|
||||
| Children
|
||||
| ((record: Record<string, any>) => Children),
|
||||
): Children {
|
||||
const records = data || [];
|
||||
|
||||
@@ -92,7 +94,7 @@ function renderTable(
|
||||
onSort(i);
|
||||
},
|
||||
},
|
||||
symbol
|
||||
symbol,
|
||||
);
|
||||
|
||||
labels.push(m("th", [label, sortable]));
|
||||
@@ -162,8 +164,8 @@ function renderTable(
|
||||
if (!selected.delete(id)) selected.add(id);
|
||||
},
|
||||
},
|
||||
tds
|
||||
)
|
||||
tds,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -184,19 +186,19 @@ function renderTable(
|
||||
disabled:
|
||||
!data.length || records.length >= Math.min(MAX_PAGE_SIZE, total),
|
||||
},
|
||||
"More"
|
||||
)
|
||||
"More",
|
||||
),
|
||||
);
|
||||
|
||||
if (downloadUrl) {
|
||||
footerElements.push(
|
||||
m("a.download-csv", { href: downloadUrl, download: "" }, "Download")
|
||||
m("a.download-csv", { href: downloadUrl, download: "" }, "Download"),
|
||||
);
|
||||
}
|
||||
|
||||
const tfoot = m(
|
||||
"tfoot",
|
||||
m("tr", m("td", { colspan: labels.length }, footerElements))
|
||||
m("tr", m("td", { colspan: labels.length }, footerElements)),
|
||||
);
|
||||
|
||||
const children = [
|
||||
@@ -204,7 +206,7 @@ function renderTable(
|
||||
"table.table.highlight",
|
||||
m("thead", m("tr", labels)),
|
||||
m("tbody", rows),
|
||||
tfoot
|
||||
tfoot,
|
||||
),
|
||||
];
|
||||
|
||||
@@ -241,7 +243,7 @@ const component: ClosureComponent = (): Component => {
|
||||
const sortArray = new Set(
|
||||
Object.keys(sortAttributes)
|
||||
.map((x) => (parseInt(x) + 1) * sortAttributes[x])
|
||||
.filter((x) => x)
|
||||
.filter((x) => x),
|
||||
);
|
||||
for (const num of events) {
|
||||
if (sortArray.delete(num + 1)) sortArray.add(-(num + 1));
|
||||
@@ -263,7 +265,7 @@ const component: ClosureComponent = (): Component => {
|
||||
downloadUrl,
|
||||
valueCallback,
|
||||
actionsCallback,
|
||||
recordActionsCallback
|
||||
recordActionsCallback,
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
+2
-2
@@ -57,7 +57,7 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"div.logo",
|
||||
m("img", { src: LOGO_SVG }),
|
||||
m("span.version", "v" + VERSION)
|
||||
m("span.version", "v" + VERSION),
|
||||
),
|
||||
m(userMenu),
|
||||
m(menu, attrs),
|
||||
@@ -68,7 +68,7 @@ const component: ClosureComponent = (): Component => {
|
||||
sideMenu,
|
||||
m("#content", { class: `page-${vnode.attrs["page"]}` }, [
|
||||
vnode.children,
|
||||
])
|
||||
]),
|
||||
),
|
||||
overlay.render(),
|
||||
m(datalist),
|
||||
|
||||
+7
-7
@@ -25,7 +25,7 @@ import * as overlay from "./overlay";
|
||||
import changePasswordComponent from "./change-password-component";
|
||||
|
||||
export function init(
|
||||
args: Record<string, unknown>
|
||||
args: Record<string, unknown>,
|
||||
): Promise<Record<string, unknown>> {
|
||||
return Promise.resolve(args);
|
||||
}
|
||||
@@ -53,7 +53,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
oninput: (e) => {
|
||||
vnode.state["username"] = e.target.value;
|
||||
},
|
||||
})
|
||||
}),
|
||||
),
|
||||
m(
|
||||
"p",
|
||||
@@ -65,7 +65,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
oninput: (e) => {
|
||||
vnode.state["password"] = e.target.value;
|
||||
},
|
||||
})
|
||||
}),
|
||||
),
|
||||
m(
|
||||
"p",
|
||||
@@ -87,9 +87,9 @@ export const component: ClosureComponent = (): Component => {
|
||||
return false;
|
||||
},
|
||||
},
|
||||
"Login"
|
||||
)
|
||||
)
|
||||
"Login",
|
||||
),
|
||||
),
|
||||
),
|
||||
m(
|
||||
"a",
|
||||
@@ -107,7 +107,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
overlay.open(cb);
|
||||
},
|
||||
},
|
||||
"Change password"
|
||||
"Change password",
|
||||
),
|
||||
];
|
||||
},
|
||||
|
||||
@@ -57,7 +57,7 @@ const component: ClosureComponent = (): Component => {
|
||||
onupdate: (vnode2) => {
|
||||
if (vnode2.dom.clientWidth === vnode2.dom.scrollWidth) {
|
||||
(vnode2.dom as HTMLElement).classList.remove(
|
||||
"long-text-overflowed"
|
||||
"long-text-overflowed",
|
||||
);
|
||||
(vnode2.dom as HTMLElement).onclick = null;
|
||||
} else {
|
||||
@@ -67,7 +67,7 @@ const component: ClosureComponent = (): Component => {
|
||||
class: "long-text",
|
||||
title: text,
|
||||
},
|
||||
text
|
||||
text,
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
+8
-8
@@ -30,8 +30,8 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"li",
|
||||
{ class: active["overview"] },
|
||||
m("a", { href: "#!/overview" }, "Overview")
|
||||
)
|
||||
m("a", { href: "#!/overview" }, "Overview"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"li",
|
||||
{ class: active["devices"] },
|
||||
m("a", { href: "#!/devices" }, "Devices")
|
||||
)
|
||||
m("a", { href: "#!/devices" }, "Devices"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"li",
|
||||
{ class: active["faults"] },
|
||||
m("a", { href: "#!/faults" }, "Faults")
|
||||
)
|
||||
m("a", { href: "#!/faults" }, "Faults"),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -67,8 +67,8 @@ const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"li",
|
||||
{ class: active["admin"] },
|
||||
m("a", { href: "#!/admin" }, "Admin")
|
||||
)
|
||||
m("a", { href: "#!/admin" }, "Admin"),
|
||||
),
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ const notifications = new Set<Notification>();
|
||||
export function push(
|
||||
type: string,
|
||||
message: string,
|
||||
actions?: { [label: string]: () => void }
|
||||
actions?: { [label: string]: () => void },
|
||||
): Notification {
|
||||
const n: Notification = {
|
||||
type: type,
|
||||
|
||||
+3
-3
@@ -27,7 +27,7 @@ let closeCallback: CloseCallback = null;
|
||||
|
||||
export function open(
|
||||
callback: OverlayCallback,
|
||||
closeCb: CloseCallback = null
|
||||
closeCb: CloseCallback = null,
|
||||
): void {
|
||||
overlayCallback = callback;
|
||||
closeCallback = closeCb;
|
||||
@@ -74,8 +74,8 @@ export function render(): Children {
|
||||
e.stopPropagation();
|
||||
},
|
||||
},
|
||||
overlayCallback()
|
||||
)
|
||||
overlayCallback(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ function queryCharts(charts: Record<string, unknown>): Record<string, unknown> {
|
||||
export function init(): Promise<Record<string, unknown>> {
|
||||
if (!window.authorizer.hasAccess("devices", 1)) {
|
||||
return Promise.reject(
|
||||
new Error("You are not authorized to view this page")
|
||||
new Error("You are not authorized to view this page"),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+20
-20
@@ -129,7 +129,7 @@ function putActionHandler(action, _object, isNew): Promise<ValidationErrors> {
|
||||
.then(() => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`Permission ${exists ? "updated" : "created"}`
|
||||
`Permission ${exists ? "updated" : "created"}`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
resolve(null);
|
||||
@@ -170,11 +170,11 @@ const getDownloadUrl = memoize((filter) => {
|
||||
});
|
||||
|
||||
export function init(
|
||||
args: Record<string, unknown>
|
||||
args: Record<string, unknown>,
|
||||
): Promise<Record<string, unknown>> {
|
||||
if (!window.authorizer.hasAccess("permissions", 2)) {
|
||||
return Promise.reject(
|
||||
new Error("You are not authorized to view this page")
|
||||
new Error("You are not authorized to view this page"),
|
||||
);
|
||||
}
|
||||
const sort = args.hasOwnProperty("sort") ? "" + args["sort"] : "";
|
||||
@@ -274,13 +274,13 @@ export const component: ClosureComponent = (): Component => {
|
||||
base: permission,
|
||||
oncreate: (_vnode) => {
|
||||
_vnode.dom.querySelector(
|
||||
"input[name='role']"
|
||||
"input[name='role']",
|
||||
).disabled = true;
|
||||
_vnode.dom.querySelector(
|
||||
"select[name='access']"
|
||||
"select[name='access']",
|
||||
).disabled = true;
|
||||
_vnode.dom.querySelector(
|
||||
"select[name='resource']"
|
||||
"select[name='resource']",
|
||||
).disabled = true;
|
||||
},
|
||||
actionHandler: (action, object) => {
|
||||
@@ -305,19 +305,19 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = () => comp;
|
||||
overlay.open(
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
"Show"
|
||||
"Show",
|
||||
),
|
||||
];
|
||||
};
|
||||
@@ -356,19 +356,19 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = () => comp;
|
||||
overlay.open(
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
"New"
|
||||
"New",
|
||||
),
|
||||
m(
|
||||
"button.primary",
|
||||
@@ -378,7 +378,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
onclick: (e) => {
|
||||
if (
|
||||
!confirm(
|
||||
`Deleting ${selected.size} permissions. Are you sure?`
|
||||
`Deleting ${selected.size} permissions. Are you sure?`,
|
||||
)
|
||||
)
|
||||
return;
|
||||
@@ -387,13 +387,13 @@ export const component: ClosureComponent = (): Component => {
|
||||
e.target.disabled = true;
|
||||
Promise.all(
|
||||
Array.from(selected).map((id) =>
|
||||
store.deleteResource("permissions", id)
|
||||
)
|
||||
store.deleteResource("permissions", id),
|
||||
),
|
||||
)
|
||||
.then((res) => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`${res.length} permissions deleted`
|
||||
`${res.length} permissions deleted`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
})
|
||||
@@ -403,7 +403,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Delete"
|
||||
"Delete",
|
||||
),
|
||||
];
|
||||
};
|
||||
@@ -421,7 +421,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"loading",
|
||||
{ queries: [permissions, count] },
|
||||
m(indexTableComponent, attrs)
|
||||
m(indexTableComponent, attrs),
|
||||
),
|
||||
];
|
||||
},
|
||||
|
||||
@@ -28,7 +28,7 @@ function drawChart(chartData): Children {
|
||||
const slices = chartData.slices;
|
||||
const total: number = Array.from(Object.values(chartData.slices)).reduce(
|
||||
(a: number, s) => a + (s["count"]["value"] || 0),
|
||||
0
|
||||
0,
|
||||
);
|
||||
const legend = [];
|
||||
const paths = [];
|
||||
@@ -53,10 +53,10 @@ function drawChart(chartData): Children {
|
||||
filter: memoizedStringify(slice["filter"]),
|
||||
})}`,
|
||||
},
|
||||
slice["count"]["value"] || 0
|
||||
slice["count"]["value"] || 0,
|
||||
),
|
||||
` (${(percent * 100).toFixed(2)}%)`,
|
||||
])
|
||||
]),
|
||||
);
|
||||
|
||||
if (percent > 0) {
|
||||
@@ -77,7 +77,7 @@ function drawChart(chartData): Children {
|
||||
m("path", {
|
||||
d: sketch,
|
||||
fill: slice["color"],
|
||||
})
|
||||
}),
|
||||
);
|
||||
|
||||
const percentageX =
|
||||
@@ -106,10 +106,10 @@ function drawChart(chartData): Children {
|
||||
"dominant-baseline": "middle",
|
||||
"text-anchor": "middle",
|
||||
},
|
||||
`${(percent * 100).toFixed(2)}%`
|
||||
`${(percent * 100).toFixed(2)}%`,
|
||||
),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -132,10 +132,10 @@ function drawChart(chartData): Children {
|
||||
xmlns: "http://www.w3.org/2000/svg",
|
||||
"xmlns:xlink": "http://www.w3.org/1999/xlink",
|
||||
},
|
||||
paths.concat(links)
|
||||
paths.concat(links),
|
||||
),
|
||||
m(".legend", legend),
|
||||
])
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
+19
-19
@@ -100,7 +100,7 @@ function putActionHandler(action, _object, isNew): Promise<ValidationErrors> {
|
||||
.then(() => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`Preset ${exists ? "updated" : "created"}`
|
||||
`Preset ${exists ? "updated" : "created"}`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
resolve(null);
|
||||
@@ -141,11 +141,11 @@ const getDownloadUrl = memoize((filter) => {
|
||||
});
|
||||
|
||||
export function init(
|
||||
args: Record<string, unknown>
|
||||
args: Record<string, unknown>,
|
||||
): Promise<Record<string, unknown>> {
|
||||
if (!window.authorizer.hasAccess("presets", 2)) {
|
||||
return Promise.reject(
|
||||
new Error("You are not authorized to view this page")
|
||||
new Error("You are not authorized to view this page"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
return m(
|
||||
"a",
|
||||
{ href: devicesUrl, title: preset["precondition"] },
|
||||
preset["precondition"]
|
||||
preset["precondition"],
|
||||
);
|
||||
} else if (
|
||||
attr.id === "provision" &&
|
||||
@@ -261,7 +261,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
filter: `Q("ID", "${preset["provision"]}")`,
|
||||
})}`,
|
||||
},
|
||||
preset["provision"]
|
||||
preset["provision"],
|
||||
);
|
||||
} else {
|
||||
return preset[attr.id];
|
||||
@@ -311,15 +311,15 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = (): Children => {
|
||||
if (!preset.provision) {
|
||||
return m(
|
||||
"div",
|
||||
{ style: "margin:20px" },
|
||||
"This UI only supports presets with a single 'provision' configuration. If this preset was originally created from the old UI (genieacs-gui), you must edit it there."
|
||||
"This UI only supports presets with a single 'provision' configuration. If this preset was originally created from the old UI (genieacs-gui), you must edit it there.",
|
||||
);
|
||||
}
|
||||
return comp;
|
||||
@@ -328,11 +328,11 @@ export const component: ClosureComponent = (): Component => {
|
||||
cb,
|
||||
() =>
|
||||
!comp.state?.["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
"Show"
|
||||
"Show",
|
||||
),
|
||||
];
|
||||
};
|
||||
@@ -372,19 +372,19 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = () => comp;
|
||||
overlay.open(
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
"New"
|
||||
"New",
|
||||
),
|
||||
m(
|
||||
"button.primary",
|
||||
@@ -401,13 +401,13 @@ export const component: ClosureComponent = (): Component => {
|
||||
e.target.disabled = true;
|
||||
Promise.all(
|
||||
Array.from(selected).map((id) =>
|
||||
store.deleteResource("presets", id)
|
||||
)
|
||||
store.deleteResource("presets", id),
|
||||
),
|
||||
)
|
||||
.then((res) => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`${res.length} presets deleted`
|
||||
`${res.length} presets deleted`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
})
|
||||
@@ -417,7 +417,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Delete"
|
||||
"Delete",
|
||||
),
|
||||
];
|
||||
};
|
||||
@@ -435,7 +435,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"loading",
|
||||
{ queries: [presets, count] },
|
||||
m(indexTableComponent, attrs)
|
||||
m(indexTableComponent, attrs),
|
||||
),
|
||||
];
|
||||
},
|
||||
|
||||
+17
-17
@@ -80,7 +80,7 @@ function putActionHandler(action, _object, isNew): Promise<ValidationErrors> {
|
||||
.then(() => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`Provision ${exists ? "updated" : "created"}`
|
||||
`Provision ${exists ? "updated" : "created"}`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
resolve(null);
|
||||
@@ -127,11 +127,11 @@ const getDownloadUrl = memoize((filter) => {
|
||||
});
|
||||
|
||||
export function init(
|
||||
args: Record<string, unknown>
|
||||
args: Record<string, unknown>,
|
||||
): Promise<Record<string, unknown>> {
|
||||
if (!window.authorizer.hasAccess("provisions", 2)) {
|
||||
return Promise.reject(
|
||||
new Error("You are not authorized to view this page")
|
||||
new Error("You are not authorized to view this page"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -237,19 +237,19 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = () => comp;
|
||||
overlay.open(
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
"Show"
|
||||
"Show",
|
||||
),
|
||||
];
|
||||
};
|
||||
@@ -289,19 +289,19 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = () => comp;
|
||||
overlay.open(
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
"New"
|
||||
"New",
|
||||
),
|
||||
m(
|
||||
"button.primary",
|
||||
@@ -311,7 +311,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
onclick: (e) => {
|
||||
if (
|
||||
!confirm(
|
||||
`Deleting ${selected.size} provisions. Are you sure?`
|
||||
`Deleting ${selected.size} provisions. Are you sure?`,
|
||||
)
|
||||
)
|
||||
return;
|
||||
@@ -320,13 +320,13 @@ export const component: ClosureComponent = (): Component => {
|
||||
e.target.disabled = true;
|
||||
Promise.all(
|
||||
Array.from(selected).map((id) =>
|
||||
store.deleteResource("provisions", id)
|
||||
)
|
||||
store.deleteResource("provisions", id),
|
||||
),
|
||||
)
|
||||
.then((res) => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`${res.length} provisions deleted`
|
||||
`${res.length} provisions deleted`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
})
|
||||
@@ -336,7 +336,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Delete"
|
||||
"Delete",
|
||||
),
|
||||
];
|
||||
};
|
||||
@@ -354,7 +354,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"loading",
|
||||
{ queries: [provisions, count] },
|
||||
m(indexTableComponent, attrs)
|
||||
m(indexTableComponent, attrs),
|
||||
),
|
||||
];
|
||||
},
|
||||
|
||||
+11
-11
@@ -61,11 +61,11 @@ function createField(current, attr, focus): Children {
|
||||
e.redraw = false;
|
||||
},
|
||||
},
|
||||
options
|
||||
options,
|
||||
);
|
||||
} else if (attr.type === "multi") {
|
||||
const optionsValues = Array.from(
|
||||
new Set(attr.options.concat(current.object[attr.id] || []))
|
||||
new Set(attr.options.concat(current.object[attr.id] || [])),
|
||||
);
|
||||
const currentSelected = new Set(current.object[attr.id]);
|
||||
const options = optionsValues.map((op) => {
|
||||
@@ -216,15 +216,15 @@ const component: ClosureComponent<Attrs> = () => {
|
||||
"p",
|
||||
m("label", { for: attr.id }, attr.label || attr.id),
|
||||
m("br"),
|
||||
createField(current, attr, focus)
|
||||
)
|
||||
createField(current, attr, focus),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
const submit = m(
|
||||
"button.primary",
|
||||
{ type: "submit" },
|
||||
"Save"
|
||||
"Save",
|
||||
) as VnodeDOM;
|
||||
const buttons = [submit];
|
||||
|
||||
@@ -238,13 +238,13 @@ const component: ClosureComponent<Attrs> = () => {
|
||||
onclick: (e) => {
|
||||
e.redraw = false;
|
||||
e.target.disabled = true;
|
||||
actionHandler("delete", current.object).finally(() => {
|
||||
void actionHandler("delete", current.object).finally(() => {
|
||||
e.target.disabled = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
"Delete"
|
||||
) as VnodeDOM
|
||||
"Delete",
|
||||
) as VnodeDOM,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ const component: ClosureComponent<Attrs> = () => {
|
||||
"h1",
|
||||
`${current.isNew ? "New" : "Editing"} ${
|
||||
singular[resource] || resource
|
||||
}`
|
||||
}`,
|
||||
),
|
||||
m(
|
||||
"form",
|
||||
@@ -267,14 +267,14 @@ const component: ClosureComponent<Attrs> = () => {
|
||||
// e.target.onsubmit = null;
|
||||
(submit.dom as HTMLFormElement).disabled = true;
|
||||
// submit.dom.textContent = "Loading ...";
|
||||
actionHandler("save", current.object).finally(() => {
|
||||
void actionHandler("save", current.object).finally(() => {
|
||||
// submit.dom.textContent = "Save";
|
||||
// e.target.onsubmit = onsubmit;
|
||||
(submit.dom as HTMLFormElement).disabled = false;
|
||||
});
|
||||
},
|
||||
},
|
||||
form
|
||||
form,
|
||||
),
|
||||
];
|
||||
|
||||
|
||||
+5
-5
@@ -63,7 +63,7 @@ for (const v of Object.values(
|
||||
config.ui.filters as Record<
|
||||
string,
|
||||
{ label: string; parameter: string; type: string }
|
||||
>
|
||||
>,
|
||||
)) {
|
||||
resources.devices[v.label] = {
|
||||
parameter: v.parameter,
|
||||
@@ -114,7 +114,7 @@ function queryString(param: Expression, value: string): Expression {
|
||||
|
||||
function queryStringCaseSensitive(
|
||||
param: Expression,
|
||||
value: string
|
||||
value: string,
|
||||
): Expression {
|
||||
return ["LIKE", param, value];
|
||||
}
|
||||
@@ -205,7 +205,7 @@ export function getTip(resource: string, label: string): string {
|
||||
break;
|
||||
case "timestamp":
|
||||
tips.push(
|
||||
"Unix timestamp or string in the form YYYY-MM-DDTHH:mm:ss.sssZ"
|
||||
"Unix timestamp or string in the form YYYY-MM-DDTHH:mm:ss.sssZ",
|
||||
);
|
||||
break;
|
||||
case "mac":
|
||||
@@ -228,7 +228,7 @@ export function getTip(resource: string, label: string): string {
|
||||
export function unpack(
|
||||
resource: string,
|
||||
label: string,
|
||||
value: string
|
||||
value: string,
|
||||
): Expression {
|
||||
if (!resources[resource]) return null;
|
||||
const type = resources[resource][label].type;
|
||||
@@ -253,7 +253,7 @@ export function unpack(
|
||||
if (type.includes("string-casesensitive")) {
|
||||
const q = queryStringCaseSensitive(
|
||||
resources[resource][label].parameter,
|
||||
value
|
||||
value,
|
||||
);
|
||||
if (q) res.push(q);
|
||||
}
|
||||
|
||||
+32
-28
@@ -76,7 +76,7 @@ for (const r of [
|
||||
};
|
||||
}
|
||||
|
||||
class QueryResponse {
|
||||
export class QueryResponse {
|
||||
public get fulfilled(): number {
|
||||
queries.accessed.set(this, Date.now());
|
||||
return queries.fulfilled.get(this) || 0;
|
||||
@@ -106,7 +106,7 @@ function checkConnection(): void {
|
||||
connectionNotification = notifications.push(
|
||||
"warning",
|
||||
"Server is unreachable",
|
||||
{}
|
||||
{},
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -121,7 +121,7 @@ function checkConnection(): void {
|
||||
if (Math.abs(skew - clockSkew) > 5000 && now2 - now1 < 1000) {
|
||||
clockSkew = skew;
|
||||
console.warn(
|
||||
`System and server clocks are out of sync. Adding ${clockSkew}ms offset to any client-side time relative calculations.`
|
||||
`System and server clocks are out of sync. Adding ${clockSkew}ms offset to any client-side time relative calculations.`,
|
||||
);
|
||||
setTimestamp(now2);
|
||||
m.redraw();
|
||||
@@ -147,7 +147,7 @@ function checkConnection(): void {
|
||||
Reload: () => {
|
||||
window.location.reload();
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -164,7 +164,7 @@ function checkConnection(): void {
|
||||
Reload: () => {
|
||||
window.location.reload();
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -178,14 +178,14 @@ function checkConnection(): void {
|
||||
setInterval(checkConnection, 3000);
|
||||
|
||||
export async function xhrRequest(
|
||||
options: { url: string } & m.RequestOptions<unknown>
|
||||
options: { url: string } & m.RequestOptions<unknown>,
|
||||
): Promise<any> {
|
||||
const extract = options.extract;
|
||||
const deserialize = options.deserialize;
|
||||
|
||||
options.extract = (
|
||||
xhr: XMLHttpRequest,
|
||||
_options?: { url: string } & m.RequestOptions<unknown>
|
||||
_options?: { url: string } & m.RequestOptions<unknown>,
|
||||
): any => {
|
||||
if (typeof extract === "function") return extract(xhr, _options);
|
||||
|
||||
@@ -207,7 +207,7 @@ export async function xhrRequest(
|
||||
response = deserialize(xhr.responseText);
|
||||
} else if (
|
||||
(xhr.getResponseHeader("content-type") || "").startsWith(
|
||||
"application/json"
|
||||
"application/json",
|
||||
)
|
||||
) {
|
||||
try {
|
||||
@@ -243,7 +243,11 @@ export function count(resourceType: string, filter: Expression): QueryResponse {
|
||||
return queryResponse;
|
||||
}
|
||||
|
||||
function limitFilter(filter, sort, bookmark): Expression {
|
||||
function limitFilter(
|
||||
filter: Expression,
|
||||
sort: Record<string, number>,
|
||||
bookmark,
|
||||
): Expression {
|
||||
const sortSort = (a, b): number => Math.abs(b[1]) - Math.abs(a[1]);
|
||||
const arr = Object.entries(sort).sort(sortSort).reverse();
|
||||
return and(
|
||||
@@ -254,7 +258,7 @@ function limitFilter(filter, sort, bookmark): Expression {
|
||||
if (bookmark[param] == null) {
|
||||
return or(
|
||||
["IS NOT NULL", ["PARAM", param]],
|
||||
and(["IS NULL", ["PARAM", param]], cur)
|
||||
and(["IS NULL", ["PARAM", param]], cur),
|
||||
);
|
||||
}
|
||||
let f = null;
|
||||
@@ -266,7 +270,7 @@ function limitFilter(filter, sort, bookmark): Expression {
|
||||
f = or(f, ["<", ["PARAM", param], bookmark[param]]);
|
||||
return or(f, and(["=", ["PARAM", param], bookmark[param]], cur));
|
||||
}
|
||||
}, true as Expression)
|
||||
}, true as Expression),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -274,7 +278,7 @@ function compareFunction(sort: {
|
||||
[param: string]: number;
|
||||
}): (a: any, b: any) => number {
|
||||
const sortEntries = Object.entries(sort).sort(
|
||||
(a, b) => Math.abs(b[1]) - Math.abs(a[1])
|
||||
(a, b) => Math.abs(b[1]) - Math.abs(a[1]),
|
||||
);
|
||||
|
||||
return (a, b) => {
|
||||
@@ -335,14 +339,14 @@ function inferQuery(resourceType, queryResponse): void {
|
||||
|
||||
queries.value.set(
|
||||
queryResponse,
|
||||
findMatches(resourceType, filter, sort, limit)
|
||||
findMatches(resourceType, filter, sort, limit),
|
||||
);
|
||||
}
|
||||
|
||||
export function fetch(
|
||||
resourceType: string,
|
||||
filter: Expression,
|
||||
options: { limit?: number; sort?: { [param: string]: number } } = {}
|
||||
options: { limit?: number; sort?: { [param: string]: number } } = {},
|
||||
): QueryResponse {
|
||||
const filterStr = memoizedStringify(filter);
|
||||
const sort = Object.assign({}, options.sort);
|
||||
@@ -396,7 +400,7 @@ export function fulfill(accessTimestamp: number): void {
|
||||
throw new Error("Server is unreachable");
|
||||
} else if (xhr.status !== 200) {
|
||||
throw new Error(
|
||||
`Unexpected response status code ${xhr.status}`
|
||||
`Unexpected response status code ${xhr.status}`,
|
||||
);
|
||||
}
|
||||
return +xhr.getResponseHeader("x-total-count");
|
||||
@@ -406,7 +410,7 @@ export function fulfill(accessTimestamp: number): void {
|
||||
queries.value.set(queryResponse, c);
|
||||
queries.fulfilled.set(queryResponse, fulfillTimestamp);
|
||||
queries.fulfilling.delete(queryResponse);
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -463,7 +467,7 @@ export function fulfill(accessTimestamp: number): void {
|
||||
} else {
|
||||
queries.bookmark.delete(queryResponse);
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -488,7 +492,7 @@ export function fulfill(accessTimestamp: number): void {
|
||||
|
||||
const [union, diff] = unionDiff(
|
||||
resources[resourceType].combinedFilter,
|
||||
combinedFilter
|
||||
combinedFilter,
|
||||
);
|
||||
|
||||
if (!diff) {
|
||||
@@ -497,7 +501,7 @@ export function fulfill(accessTimestamp: number): void {
|
||||
filter = memoizedEvaluate(
|
||||
filter,
|
||||
null,
|
||||
fulfillTimestamp + clockSkew
|
||||
fulfillTimestamp + clockSkew,
|
||||
);
|
||||
const limit = queries.limit.get(queryResponse);
|
||||
const bookmark = queries.bookmark.get(queryResponse);
|
||||
@@ -506,7 +510,7 @@ export function fulfill(accessTimestamp: number): void {
|
||||
|
||||
queries.value.set(
|
||||
queryResponse,
|
||||
findMatches(resourceType, filter, sort, limit)
|
||||
findMatches(resourceType, filter, sort, limit),
|
||||
);
|
||||
queries.fulfilled.set(queryResponse, fulfillTimestamp);
|
||||
queries.fulfilling.delete(queryResponse);
|
||||
@@ -559,12 +563,12 @@ export function fulfill(accessTimestamp: number): void {
|
||||
|
||||
queries.value.set(
|
||||
queryResponse,
|
||||
findMatches(resourceType, filter, sort, limit)
|
||||
findMatches(resourceType, filter, sort, limit),
|
||||
);
|
||||
queries.fulfilled.set(queryResponse, fulfillTimestamp);
|
||||
queries.fulfilling.delete(queryResponse);
|
||||
}
|
||||
})
|
||||
}),
|
||||
);
|
||||
}
|
||||
if (updated) m.redraw();
|
||||
@@ -593,7 +597,7 @@ export function getClockSkew(): number {
|
||||
|
||||
export function postTasks(
|
||||
deviceId: string,
|
||||
tasks: QueueTask[]
|
||||
tasks: QueueTask[],
|
||||
): Promise<string> {
|
||||
const tasks2: Task[] = [];
|
||||
for (const t of tasks) {
|
||||
@@ -626,7 +630,7 @@ export function postTasks(
|
||||
|
||||
export function updateTags(
|
||||
deviceId: string,
|
||||
tags: Record<string, boolean>
|
||||
tags: Record<string, boolean>,
|
||||
): Promise<void> {
|
||||
return xhrRequest({
|
||||
method: "POST",
|
||||
@@ -637,7 +641,7 @@ export function updateTags(
|
||||
|
||||
export function deleteResource(
|
||||
resourceType: string,
|
||||
id: string
|
||||
id: string,
|
||||
): Promise<void> {
|
||||
return xhrRequest({
|
||||
method: "DELETE",
|
||||
@@ -648,7 +652,7 @@ export function deleteResource(
|
||||
export function putResource(
|
||||
resourceType: string,
|
||||
id: string,
|
||||
object: Record<string, unknown>
|
||||
object: Record<string, unknown>,
|
||||
): Promise<void> {
|
||||
for (const k in object) if (object[k] === undefined) object[k] = null;
|
||||
|
||||
@@ -691,7 +695,7 @@ export function resourceExists(resource: string, id: string): Promise<number> {
|
||||
|
||||
export function evaluateExpression(
|
||||
exp: Expression,
|
||||
obj: Record<string, unknown>
|
||||
obj: Record<string, unknown>,
|
||||
): Expression {
|
||||
if (!Array.isArray(exp)) return exp;
|
||||
return memoizedEvaluate(exp, obj, fulfillTimestamp + clockSkew);
|
||||
@@ -700,7 +704,7 @@ export function evaluateExpression(
|
||||
export function changePassword(
|
||||
username: string,
|
||||
newPassword: string,
|
||||
authPassword?: string
|
||||
authPassword?: string,
|
||||
): Promise<void> {
|
||||
const body = { newPassword };
|
||||
if (authPassword) body["authPassword"] = authPassword;
|
||||
|
||||
+2
-2
@@ -95,8 +95,8 @@ export function commit(
|
||||
deviceId: string,
|
||||
err: Error,
|
||||
conReqStatus: string,
|
||||
_tasks: QueueTask[]
|
||||
) => void
|
||||
_tasks: QueueTask[],
|
||||
) => void,
|
||||
): Promise<void> {
|
||||
const devices: { [deviceId: string]: QueueTask[] } = {};
|
||||
|
||||
|
||||
@@ -65,8 +65,8 @@ function putActionHandler(prefix: string[], dataYaml: string): Promise<any> {
|
||||
store.putResource(
|
||||
"config",
|
||||
obj._id,
|
||||
obj as unknown as Record<string, unknown>
|
||||
)
|
||||
obj as unknown as Record<string, unknown>,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ const component: ClosureComponent<Attrs> = () => {
|
||||
.catch(vnode.attrs.onError);
|
||||
},
|
||||
},
|
||||
[code, m(".actions-bar", [submit])]
|
||||
[code, m(".actions-bar", [submit])],
|
||||
),
|
||||
]);
|
||||
},
|
||||
|
||||
+4
-4
@@ -46,8 +46,8 @@ const component: ClosureComponent = (): Component => {
|
||||
return false;
|
||||
},
|
||||
},
|
||||
"Log out"
|
||||
)
|
||||
"Log out",
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return m(
|
||||
@@ -58,8 +58,8 @@ const component: ClosureComponent = (): Component => {
|
||||
href:
|
||||
"#!/login?" + m.buildQueryString({ continue: m.route.get() }),
|
||||
},
|
||||
"Log in"
|
||||
)
|
||||
"Log in",
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
+15
-15
@@ -144,11 +144,11 @@ const getDownloadUrl = memoize((filter) => {
|
||||
});
|
||||
|
||||
export function init(
|
||||
args: Record<string, unknown>
|
||||
args: Record<string, unknown>,
|
||||
): Promise<Record<string, unknown>> {
|
||||
if (!window.authorizer.hasAccess("users", 2)) {
|
||||
return Promise.reject(
|
||||
new Error("You are not authorized to view this page")
|
||||
new Error("You are not authorized to view this page"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -267,8 +267,8 @@ export const component: ClosureComponent = (): Component => {
|
||||
{
|
||||
resource: "users",
|
||||
attributes: attributes,
|
||||
}
|
||||
)
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
cb = () => {
|
||||
@@ -293,11 +293,11 @@ export const component: ClosureComponent = (): Component => {
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
"Show"
|
||||
"Show",
|
||||
),
|
||||
];
|
||||
};
|
||||
@@ -346,19 +346,19 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = () => comp;
|
||||
overlay.open(
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
"New"
|
||||
"New",
|
||||
),
|
||||
m(
|
||||
"button.primary",
|
||||
@@ -375,13 +375,13 @@ export const component: ClosureComponent = (): Component => {
|
||||
e.target.disabled = true;
|
||||
Promise.all(
|
||||
Array.from(selected).map((id) =>
|
||||
store.deleteResource("users", id)
|
||||
)
|
||||
store.deleteResource("users", id),
|
||||
),
|
||||
)
|
||||
.then((res) => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`${res.length} users deleted`
|
||||
`${res.length} users deleted`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
})
|
||||
@@ -391,7 +391,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Delete"
|
||||
"Delete",
|
||||
),
|
||||
];
|
||||
};
|
||||
@@ -409,7 +409,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"loading",
|
||||
{ queries: [users, count] },
|
||||
m(indexTableComponent, attrs)
|
||||
m(indexTableComponent, attrs),
|
||||
),
|
||||
];
|
||||
},
|
||||
|
||||
@@ -80,7 +80,7 @@ function putActionHandler(action, _object, isNew): Promise<ValidationErrors> {
|
||||
.then(() => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`Virtual parameter ${exists ? "updated" : "created"}`
|
||||
`Virtual parameter ${exists ? "updated" : "created"}`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
resolve(null);
|
||||
@@ -127,11 +127,11 @@ const getDownloadUrl = memoize((filter) => {
|
||||
});
|
||||
|
||||
export function init(
|
||||
args: Record<string, unknown>
|
||||
args: Record<string, unknown>,
|
||||
): Promise<Record<string, unknown>> {
|
||||
if (!window.authorizer.hasAccess("virtualParameters", 2)) {
|
||||
return Promise.reject(
|
||||
new Error("You are not authorized to view this page")
|
||||
new Error("You are not authorized to view this page"),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -237,19 +237,19 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = () => comp;
|
||||
overlay.open(
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
"Show"
|
||||
"Show",
|
||||
),
|
||||
];
|
||||
};
|
||||
@@ -289,19 +289,19 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
formData
|
||||
)
|
||||
formData,
|
||||
),
|
||||
);
|
||||
cb = () => comp;
|
||||
overlay.open(
|
||||
cb,
|
||||
() =>
|
||||
!comp.state["current"]["modified"] ||
|
||||
confirm("You have unsaved changes. Close anyway?")
|
||||
confirm("You have unsaved changes. Close anyway?"),
|
||||
);
|
||||
},
|
||||
},
|
||||
"New"
|
||||
"New",
|
||||
),
|
||||
m(
|
||||
"button.primary",
|
||||
@@ -311,7 +311,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
onclick: (e) => {
|
||||
if (
|
||||
!confirm(
|
||||
`Deleting ${selected.size} virtual parameters. Are you sure?`
|
||||
`Deleting ${selected.size} virtual parameters. Are you sure?`,
|
||||
)
|
||||
)
|
||||
return;
|
||||
@@ -320,13 +320,13 @@ export const component: ClosureComponent = (): Component => {
|
||||
e.target.disabled = true;
|
||||
Promise.all(
|
||||
Array.from(selected).map((id) =>
|
||||
store.deleteResource("virtualParameters", id)
|
||||
)
|
||||
store.deleteResource("virtualParameters", id),
|
||||
),
|
||||
)
|
||||
.then((res) => {
|
||||
notifications.push(
|
||||
"success",
|
||||
`${res.length} virtual parameters deleted`
|
||||
`${res.length} virtual parameters deleted`,
|
||||
);
|
||||
store.setTimestamp(Date.now());
|
||||
})
|
||||
@@ -336,7 +336,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"Delete"
|
||||
"Delete",
|
||||
),
|
||||
];
|
||||
};
|
||||
@@ -354,7 +354,7 @@ export const component: ClosureComponent = (): Component => {
|
||||
m(
|
||||
"loading",
|
||||
{ queries: [virtualParameters, count] },
|
||||
m(indexTableComponent, attrs)
|
||||
m(indexTableComponent, attrs),
|
||||
),
|
||||
];
|
||||
},
|
||||
|
||||
+5
-5
@@ -58,13 +58,13 @@ export const component: ClosureComponent = (vnode): Component => {
|
||||
m("h1", "Initialization wizard"),
|
||||
m(
|
||||
"p",
|
||||
"This wizard will seed the database with a minimal initial configuration to serve as a starting point. Select what you want to initialize and click 'ABRACADABRA!'."
|
||||
"This wizard will seed the database with a minimal initial configuration to serve as a starting point. Select what you want to initialize and click 'ABRACADABRA!'.",
|
||||
),
|
||||
m("div", m("label", checkboxes[0], "Users, roles and permissions")),
|
||||
m("div", m("label", checkboxes[1], "Presets and provisions")),
|
||||
m(
|
||||
"div",
|
||||
m("label", checkboxes[2], "Devices predefined search filters")
|
||||
m("label", checkboxes[2], "Devices predefined search filters"),
|
||||
),
|
||||
m("div", m("label", checkboxes[3], "Device details page")),
|
||||
m("div", m("label", checkboxes[4], "Devices listing page")),
|
||||
@@ -99,7 +99,7 @@ export const component: ClosureComponent = (vnode): Component => {
|
||||
m.route.set("/login");
|
||||
window.location.reload();
|
||||
},
|
||||
}
|
||||
},
|
||||
);
|
||||
})
|
||||
.catch((err) => {
|
||||
@@ -108,7 +108,7 @@ export const component: ClosureComponent = (vnode): Component => {
|
||||
}, 3000);
|
||||
if (opts["users"]) {
|
||||
alert(
|
||||
"An administrator user has been created for you. Use admin/admin to log in. Don't forget to change the default password."
|
||||
"An administrator user has been created for you. Use admin/admin to log in. Don't forget to change the default password.",
|
||||
);
|
||||
}
|
||||
})
|
||||
@@ -117,7 +117,7 @@ export const component: ClosureComponent = (vnode): Component => {
|
||||
});
|
||||
},
|
||||
},
|
||||
"ABRACADABRA!"
|
||||
"ABRACADABRA!",
|
||||
),
|
||||
]);
|
||||
},
|
||||
|
||||
Reference in new issue
Block a user