diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json
index 56132dd..9948681 100644
--- a/npm-shrinkwrap.json
+++ b/npm-shrinkwrap.json
@@ -492,9 +492,9 @@
"dev": true
},
"@types/mithril": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/@types/mithril/-/mithril-2.0.6.tgz",
- "integrity": "sha512-oOyFr99rKH+94uKHjIVKTL9uaUaxtXJgtZOZkjhWIAY8twr9YzxfEmYARMJkWC3aVg52We8d4wtLhqQ99+fXpw==",
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/@types/mithril/-/mithril-2.0.8.tgz",
+ "integrity": "sha512-QzVV70DqUhWfLFpMFDBI9rRxtzeUUpbhiFDpUJYSV92AePgl+Qfficgv2MOb1Ceb+lBOQU8+L+Hjf2UielQjEw==",
"dev": true
},
"@types/mongodb": {
diff --git a/package.json b/package.json
index 8fbaa4e..30a6d49 100644
--- a/package.json
+++ b/package.json
@@ -45,7 +45,7 @@
"@types/koa-compress": "^4.0.1",
"@types/koa-router": "^7.4.1",
"@types/koa-static": "^4.0.1",
- "@types/mithril": "^2.0.6",
+ "@types/mithril": "^2.0.8",
"@types/mongodb": "^3.6.9",
"@types/node": "^14.14.34",
"@types/parsimmon": "^1.10.6",
diff --git a/ui/change-password-component.ts b/ui/change-password-component.ts
index f7d0dab..da99852 100644
--- a/ui/change-password-component.ts
+++ b/ui/change-password-component.ts
@@ -17,17 +17,23 @@
* along with GenieACS. If not, see .
*/
-import { VnodeDOM, ClosureComponent, Component } from "mithril";
+import { VnodeDOM, ClosureComponent } from "mithril";
import * as notifications from "./notifications";
import { changePassword } from "./store";
import { m } from "./components";
-const component: ClosureComponent = (): Component => {
+interface Attrs {
+ noAuth?: boolean;
+ username?: string;
+ onPasswordChange: () => void;
+}
+
+const component: ClosureComponent = () => {
return {
view: (vnode) => {
- const onPasswordChange = vnode.attrs["onPasswordChange"];
- const enforceAuth = !vnode.attrs["noAuth"];
- const username = vnode.attrs["username"];
+ const onPasswordChange = vnode.attrs.onPasswordChange;
+ const enforceAuth = !vnode.attrs.noAuth;
+ const username = vnode.attrs.username;
if (username) vnode.state["username"] = username;
diff --git a/ui/code-editor-component.ts b/ui/code-editor-component.ts
index 3f0c9e9..4ab455e 100644
--- a/ui/code-editor-component.ts
+++ b/ui/code-editor-component.ts
@@ -17,44 +17,54 @@
* along with GenieACS. If not, see .
*/
-import { ClosureComponent, Component } from "mithril";
+import { Editor } from "codemirror";
+import { ClosureComponent } from "mithril";
import { m } from "./components";
import { codeMirror } from "./dynamic-loader";
-const component: ClosureComponent = (): Component => {
+interface Attrs {
+ id: string;
+ value: string;
+ mode: string;
+ readOnly?: boolean;
+ focus?: boolean;
+ onSubmit?: (dom: Element) => void;
+ onChange?: (value: string) => void;
+ onReady?: (editor: Editor) => void;
+}
+
+const component: ClosureComponent = () => {
return {
view: (vnode) => {
return m("textarea", {
- name: vnode.attrs["id"],
- value: vnode.attrs["value"],
+ name: vnode.attrs.id,
+ value: vnode.attrs.value,
oncreate: (_vnode) => {
const editor = codeMirror.fromTextArea(
_vnode.dom as HTMLTextAreaElement,
{
- mode: vnode.attrs["mode"],
+ mode: vnode.attrs.mode,
lineNumbers: true,
- readOnly: vnode.attrs["readOnly"],
+ readOnly: vnode.attrs.readOnly,
extraKeys: {
"Ctrl-Enter": () => {
- if (vnode.attrs["onSubmit"])
- vnode.attrs["onSubmit"](_vnode.dom);
+ if (vnode.attrs.onSubmit) vnode.attrs.onSubmit(_vnode.dom);
},
"Cmd-Enter": () => {
- if (vnode.attrs["onSubmit"])
- vnode.attrs["onSubmit"](_vnode.dom);
+ if (vnode.attrs.onSubmit) vnode.attrs.onSubmit(_vnode.dom);
},
},
}
);
- if (vnode.attrs["onChange"]) {
+ if (vnode.attrs.onChange) {
editor.on("change", (e) => {
- vnode.attrs["onChange"](e.getValue());
+ vnode.attrs.onChange(e.getValue());
});
}
- if (vnode.attrs["focus"]) editor.focus();
- if (vnode.attrs["onReady"]) vnode.attrs["onReady"](editor);
+ if (vnode.attrs.focus) editor.focus();
+ if (vnode.attrs.onReady) vnode.attrs.onReady(editor);
},
});
},
diff --git a/ui/components.ts b/ui/components.ts
index 3856bae..22ea558 100644
--- a/ui/components.ts
+++ b/ui/components.ts
@@ -22,7 +22,7 @@ import m, {
Attributes,
Children,
ComponentTypes,
- Lifecycle,
+ CommonAttributes,
ClosureComponent,
Vnode,
} from "mithril";
@@ -81,7 +81,7 @@ interface MC extends Static {
(
ctx: Attributes,
component: ComponentTypes,
- attributes: Attrs & Lifecycle & { key?: string | number },
+ attributes: Attrs & CommonAttributes,
...args: Children[]
): Vnode;
};
diff --git a/ui/config-page.ts b/ui/config-page.ts
index e60de5d..6f4edf2 100644
--- a/ui/config-page.ts
+++ b/ui/config-page.ts
@@ -154,7 +154,7 @@ function renderTable(confsResponse, searchString): Children {
{
base: conf,
actionHandler: (action, object) => {
- return new Promise((resolve) => {
+ return new Promise((resolve) => {
putActionHandler(action, object, false)
.then((errors) => {
const ErrorList = errors ? Object.values(errors) : [];
@@ -164,11 +164,11 @@ function renderTable(confsResponse, searchString): Children {
} else {
overlay.close(cb);
}
- resolve(null);
+ resolve();
})
.catch((err) => {
notifications.push("error", err.message);
- resolve(null);
+ resolve();
});
});
},
@@ -322,7 +322,7 @@ export const component: ClosureComponent = (): Component => {
uiConfigComponent,
Object.assign(
{
- onUpdate: (errs: string[]) => {
+ onUpdate: (errs: Record) => {
const errors = errs ? Object.values(errs) : [];
if (errors.length) {
for (const err of errors)
diff --git a/ui/put-form-component.ts b/ui/put-form-component.ts
index 0f0c786..bf88702 100644
--- a/ui/put-form-component.ts
+++ b/ui/put-form-component.ts
@@ -17,7 +17,7 @@
* along with GenieACS. If not, see .
*/
-import { VnodeDOM, ClosureComponent, Component, Children } from "mithril";
+import { VnodeDOM, ClosureComponent, Children } from "mithril";
import { m } from "./components";
import codeEditorComponent from "./code-editor-component";
import { getDatalistId } from "./datalist";
@@ -175,13 +175,25 @@ function createField(current, attr, focus): Children {
});
}
-const component: ClosureComponent = (): Component => {
+interface Attrs {
+ base?: Record;
+ actionHandler: (action: string, object: any) => Promise;
+ resource: string;
+ attributes: {
+ id: string;
+ label: string;
+ type?: string;
+ options?: string[];
+ }[];
+}
+
+const component: ClosureComponent = () => {
return {
view: (vnode) => {
- const actionHandler = vnode.attrs["actionHandler"];
- const attributes = vnode.attrs["attributes"];
- const resource = vnode.attrs["resource"];
- const base = vnode.attrs["base"] || {};
+ const actionHandler = vnode.attrs.actionHandler;
+ const attributes = vnode.attrs.attributes;
+ const resource = vnode.attrs.resource;
+ const base = vnode.attrs.base || {};
if (!vnode.state["current"]) {
vnode.state["current"] = {
isNew: !base["_id"],
@@ -226,7 +238,7 @@ const component: ClosureComponent = (): Component => {
onclick: (e) => {
e.redraw = false;
e.target.disabled = true;
- actionHandler("delete", current.object).then(() => {
+ actionHandler("delete", current.object).finally(() => {
e.target.disabled = false;
});
},
@@ -255,7 +267,7 @@ const component: ClosureComponent = (): Component => {
// e.target.onsubmit = null;
(submit.dom as HTMLFormElement).disabled = true;
// submit.dom.textContent = "Loading ...";
- actionHandler("save", current.object).then(() => {
+ actionHandler("save", current.object).finally(() => {
// submit.dom.textContent = "Save";
// e.target.onsubmit = onsubmit;
(submit.dom as HTMLFormElement).disabled = false;
diff --git a/ui/ui-config-component.ts b/ui/ui-config-component.ts
index 2116294..7bff810 100644
--- a/ui/ui-config-component.ts
+++ b/ui/ui-config-component.ts
@@ -17,7 +17,7 @@
* along with GenieACS. If not, see .
*/
-import { ClosureComponent, Component } from "mithril";
+import { ClosureComponent } from "mithril";
import { m } from "./components";
import * as store from "./store";
import { yaml } from "./dynamic-loader";
@@ -86,12 +86,20 @@ function putActionHandler(prefix: string[], dataYaml: string): Promise {
});
}
-const component: ClosureComponent = (): Component => {
+interface Attrs {
+ prefix: string;
+ name: string;
+ data: { _id: string; value: string }[];
+ onUpdate: (errs: Record) => void;
+ onError: (err: Error) => void;
+}
+
+const component: ClosureComponent = () => {
return {
view: (vnode) => {
- const prefix = vnode.attrs["prefix"].split(".");
- const name = vnode.attrs["name"];
- const data = vnode.attrs["data"];
+ const prefix = vnode.attrs.prefix.split(".");
+ const name = vnode.attrs.name;
+ const data = vnode.attrs.data;
if (prefix[prefix.length - 1] === "") prefix.pop();
@@ -135,8 +143,8 @@ const component: ClosureComponent = (): Component => {
vnode.state["updatedYaml"] = yamlString;
putActionHandler(prefix, vnode.state["updatedYaml"])
- .then(vnode.attrs["onUpdate"])
- .catch(vnode.attrs["onError"]);
+ .then(vnode.attrs.onUpdate)
+ .catch(vnode.attrs.onError);
},
},
[code, m(".actions-bar", [submit])]