Refactor components

Implement context mechanism to pass default attributes to descendant
components.
This commit is contained in:
Zaid Abdulla committed 2019-02-12 23:11:27 -08:00
1 parent d46d133878
commit ee8c43747e
35 files changed
+302 -230

No files matched your search

+3 -3
View File
@@ -2,7 +2,8 @@
import m from "mithril"; import m from "mithril";
const menu = { export default function menu() {
return {
view: vnode => { view: vnode => {
const active = { [vnode.attrs.page]: "active" }; const active = { [vnode.attrs.page]: "active" };
const tabs = []; const tabs = [];
@@ -60,5 +61,4 @@ const menu = {
return m("nav#side-menu", m("ul", tabs)); return m("nav#side-menu", m("ul", tabs));
} }
}; };
}
export default menu;
+2 -1
View File
@@ -17,6 +17,7 @@ import * as filesPage from "./files-page";
import * as configPage from "./config-page"; import * as configPage from "./config-page";
import Authorizer from "../lib//common/authorizer"; import Authorizer from "../lib//common/authorizer";
import * as notifications from "./notifications"; import * as notifications from "./notifications";
import { contextifyComponent } from "./components";
window.authorizer = new Authorizer(window.permissionSets); window.authorizer = new Authorizer(window.permissionSets);
@@ -49,7 +50,7 @@ function pagify(pageName, page) {
lastRenderTimestamp = Date.now(); lastRenderTimestamp = Date.now();
let p; let p;
if (state && state.error) p = m(errorPage.component, state); if (state && state.error) p = m(errorPage.component, state);
else p = m(page.component, state); else p = m(contextifyComponent(page.component), state);
fulfill(); fulfill();
return m(layout, { page: pageName }, p); return m(layout, { page: pageName }, p);
} }
+71 -4
View File
@@ -1,5 +1,6 @@
"use strict"; "use strict";
import m from "mithril";
import parameter from "./components/parameter"; import parameter from "./components/parameter";
import parameterList from "./components/parameter-list"; import parameterList from "./components/parameter-list";
import parameterTable from "./components/parameter-table"; import parameterTable from "./components/parameter-table";
@@ -12,6 +13,7 @@ import deviceActions from "./components/device-actions";
import tags from "./components/tags"; import tags from "./components/tags";
import ping from "./components/ping"; import ping from "./components/ping";
import deviceLink from "./components/device-link"; import deviceLink from "./components/device-link";
import longTextComponent from "./long-text-component";
const comps = { const comps = {
parameter, parameter,
@@ -25,11 +27,76 @@ const comps = {
"device-actions": deviceActions, "device-actions": deviceActions,
tags, tags,
ping, ping,
"device-link": deviceLink "device-link": deviceLink,
"long-text": longTextComponent
}; };
export function get(name) { const contextifiedComponents = new WeakMap();
const c = comps[name]; const vnodeContext = new WeakMap();
if (!c) throw new Error(`No such component '${name}'`);
function contextFn(context, ...argumentsList) {
const vnode = Reflect.apply(M, undefined, argumentsList);
vnodeContext.set(vnode, context);
return vnode;
}
const M = new Proxy(m, {
apply: (target, thisArg, argumentsList) => {
const c = argumentsList[0];
if (typeof c !== "string") argumentsList[0] = contextifyComponent(c);
else if (comps[c]) argumentsList[0] = contextifyComponent(comps[c]);
return Reflect.apply(target, undefined, argumentsList);
},
get: (target, prop) => {
if (prop === "context") return contextFn;
else return Reflect.get(target, prop);
}
});
function applyContext(vnode, parentContext) {
if (Array.isArray(vnode)) {
for (const c of vnode) applyContext(c, parentContext);
} else if (vnode && typeof vnode === "object" && vnode.tag) {
const vc = Object.assign({}, parentContext, vnodeContext.get(vnode));
vnodeContext.set(vnode, vc);
vnode.attrs = Object.assign({}, vc, vnode.attrs);
if (vnode.children && vnode.children.length)
for (const c of vnode.children) applyContext(c, vc);
}
}
export function contextifyComponent(component) {
let c = contextifiedComponents.get(component);
if (!c) {
if (typeof component !== "function") {
c = Object.assign({}, component);
const view = component.view;
c.view = vnode => {
const context = vnodeContext.get(vnode) || {};
const res = view(vnode, M);
applyContext(res, context);
return res;
};
} else if (!component.prototype.view) {
c = initialNode => {
const state = component(initialNode);
const view = state.view;
state.view = vnode => {
const context = vnodeContext.get(vnode) || {};
const res = view(vnode, M);
applyContext(res, context);
return res;
};
return state;
};
} else {
// TODO support class components
throw new Error("Class components not supported");
}
contextifiedComponents.set(component, c);
}
return c; return c;
} }
export { M as m };
+6 -8
View File
@@ -1,9 +1,7 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import * as components from "../components";
import * as taskQueue from "../task-queue"; import * as taskQueue from "../task-queue";
import longTextComponent from "../long-text-component";
import { parse } from "../../lib/common/expression-parser"; import { parse } from "../../lib/common/expression-parser";
import memoize from "../../lib/common/memoize"; import memoize from "../../lib/common/memoize";
@@ -13,7 +11,8 @@ function escapeRegExp(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&"); return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&");
} }
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
const device = vnode.attrs.device; const device = vnode.attrs.device;
@@ -50,7 +49,7 @@ const component = {
if (p.object === false) { if (p.object === false) {
val.push( val.push(
m( m(
components.get("parameter"), "parameter",
Object.assign({ device: device, parameter: memoizedParse(k) }) Object.assign({ device: device, parameter: memoizedParse(k) })
) )
); );
@@ -112,7 +111,7 @@ const component = {
return m( return m(
"tr", "tr",
attrs, attrs,
m("td.left", m(longTextComponent, { text: k })), m("td.left", m("long-text", { text: k })),
m("td.right", val) m("td.right", val)
); );
}); });
@@ -133,5 +132,4 @@ const component = {
); );
} }
}; };
}
export default component;
+5 -7
View File
@@ -1,10 +1,10 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import * as components from "../components";
import * as store from "../store"; import * as store from "../store";
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
if (vnode.attrs.filter) { if (vnode.attrs.filter) {
if (!store.evaluateExpression(vnode.attrs.filter, vnode.attrs.device)) if (!store.evaluateExpression(vnode.attrs.filter, vnode.attrs.device))
@@ -13,12 +13,10 @@ const component = {
const children = Object.values(vnode.attrs.components).map(c => { const children = Object.values(vnode.attrs.components).map(c => {
if (typeof c !== "object") return `${c}`; if (typeof c !== "object") return `${c}`;
const attrs = Object.assign({}, vnode.attrs, c); return m(c.type, c);
return m(components.get(attrs.type), attrs);
}); });
if (vnode.attrs.element) return m(vnode.attrs.element, children); if (vnode.attrs.element) return m(vnode.attrs.element, children);
else return children; else return children;
} }
}; };
}
export default component;
+4 -4
View File
@@ -1,11 +1,12 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import * as taskQueue from "../task-queue"; import * as taskQueue from "../task-queue";
import * as notifications from "../notifications"; import * as notifications from "../notifications";
import * as store from "../store"; import * as store from "../store";
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
const device = vnode.attrs.device; const device = vnode.attrs.device;
@@ -86,5 +87,4 @@ const component = {
return m(".actions-bar", buttons); return m(".actions-bar", buttons);
} }
}; };
}
export default component;
+11 -7
View File
@@ -1,10 +1,11 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import * as store from "../store"; import * as store from "../store";
import * as notifications from "../notifications"; import * as notifications from "../notifications";
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
const device = vnode.attrs.device; const device = vnode.attrs.device;
const deviceId = device["DeviceID.ID"].value[0]; const deviceId = device["DeviceID.ID"].value[0];
@@ -14,9 +15,13 @@ const component = {
["<", ["PARAM", "_id"], `${deviceId}:zzzz`] ["<", ["PARAM", "_id"], `${deviceId}:zzzz`]
]); ]);
const headers = ["Channel", "Code", "Message", "Retries", "Timestamp"].map( const headers = [
l => m("th", l) "Channel",
); "Code",
"Message",
"Retries",
"Timestamp"
].map(l => m("th", l));
const thead = m("thead", m("tr", headers)); const thead = m("thead", m("tr", headers));
const rows = []; const rows = [];
@@ -67,5 +72,4 @@ const component = {
return m("table.table", thead, tbody); return m("table.table", thead, tbody);
} }
}; };
}
export default component;
+5 -6
View File
@@ -1,9 +1,9 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import * as components from "../components";
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
let deviceId; let deviceId;
if (vnode.attrs.device) if (vnode.attrs.device)
@@ -12,7 +12,7 @@ const component = {
const children = Object.values(vnode.attrs.components).map(c => { const children = Object.values(vnode.attrs.components).map(c => {
if (typeof c !== "object") return `${c}`; if (typeof c !== "object") return `${c}`;
const attrs = Object.assign({}, vnode.attrs, c); const attrs = Object.assign({}, vnode.attrs, c);
return m(components.get(attrs.type), attrs); return m(attrs.type, attrs);
}); });
if (deviceId) { if (deviceId) {
return m( return m(
@@ -25,5 +25,4 @@ const component = {
} }
} }
}; };
}
export default component;
+4 -4
View File
@@ -1,12 +1,13 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import config from "../config"; import config from "../config";
import * as store from "../store"; import * as store from "../store";
const CHARTS = config.ui.overview.charts; const CHARTS = config.ui.overview.charts;
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
const device = vnode.attrs.device; const device = vnode.attrs.device;
const chart = CHARTS[vnode.attrs.chart]; const chart = CHARTS[vnode.attrs.chart];
@@ -34,5 +35,4 @@ const component = {
return null; return null;
} }
}; };
}
export default component;
+11 -11
View File
@@ -1,21 +1,20 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import { get } from "../components";
import memoize from "../../lib/common/memoize";
const getChildAttrs = memoize((attrs, device) => export default function component() {
Object.assign({}, attrs, { device: device }) return {
);
export default {
view: vnode => { view: vnode => {
const device = vnode.attrs.device; const device = vnode.attrs.device;
const rows = Object.values(vnode.attrs.parameters).map(parameter => { const rows = Object.values(vnode.attrs.parameters).map(parameter => {
const p = m( const p = m.context(
get(parameter.type || "parameter"), {
getChildAttrs(parameter, device) device: device,
parameter: parameter.parameter
},
parameter.type || "parameter",
parameter
); );
return m( return m(
@@ -33,3 +32,4 @@ export default {
return m("table.parameter-list", rows); return m("table.parameter-list", rows);
} }
}; };
}
+11 -9
View File
@@ -1,12 +1,12 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import * as components from "../components";
import * as taskQueue from "../task-queue"; import * as taskQueue from "../task-queue";
import * as store from "../store"; import * as store from "../store";
import * as expressionParser from "../../lib/common/expression-parser"; import * as expressionParser from "../../lib/common/expression-parser";
const component = { export default function component() {
return {
oninit: vnode => { oninit: vnode => {
const obj = vnode.attrs.parameter; const obj = vnode.attrs.parameter;
if (!Array.isArray(obj) || !obj[0] === "PARAM") if (!Array.isArray(obj) || !obj[0] === "PARAM")
@@ -55,12 +55,15 @@ const component = {
}); });
return m( return m(
"td", "td",
m( m.context(
components.get(p.type || "parameter"), {
device: device,
parameter: param
},
p.type || "parameter",
Object.assign({}, p, { Object.assign({}, p, {
device: device, device: device,
parameter: param, parameter: param
label: ""
}) })
) )
); );
@@ -128,5 +131,4 @@ const component = {
return [label, m("table.table", thead, m("tbody", rows))]; return [label, m("table.table", thead, m("tbody", rows))];
} }
}; };
}
export default component;
+5 -6
View File
@@ -1,12 +1,11 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import * as taskQueue from "../task-queue"; import * as taskQueue from "../task-queue";
import * as store from "../store"; import * as store from "../store";
import * as expression from "../../lib/common/expression"; import * as expression from "../../lib/common/expression";
import memoize from "../../lib/common/memoize"; import memoize from "../../lib/common/memoize";
import timeAgo from "../timeago"; import timeAgo from "../timeago";
import longTextComponent from "../long-text-component";
const evaluateParam = memoize((exp, obj, now) => { const evaluateParam = memoize((exp, obj, now) => {
let timestamp = now; let timestamp = now;
@@ -32,7 +31,8 @@ const evaluateParam = memoize((exp, obj, now) => {
return { value, timestamp, parameter }; return { value, timestamp, parameter };
}); });
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
const device = vnode.attrs.device; const device = vnode.attrs.device;
@@ -68,7 +68,7 @@ const component = {
); );
} }
const el = m(longTextComponent, { text: `${value}` }); const el = m("long-text", { text: `${value}` });
return m( return m(
"span", "span",
@@ -89,5 +89,4 @@ const component = {
); );
} }
}; };
}
export default component;
+4 -4
View File
@@ -1,11 +1,12 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import * as store from "../store"; import * as store from "../store";
const REFRESH_INTERVAL = 3000; const REFRESH_INTERVAL = 3000;
const component = { export default function component() {
return {
oninit: vnode => { oninit: vnode => {
vnode.state.timestamp = 0; vnode.state.timestamp = 0;
vnode.state.ping = null; vnode.state.ping = null;
@@ -52,5 +53,4 @@ const component = {
return null; return null;
} }
}; };
}
export default component;
+4 -4
View File
@@ -1,11 +1,12 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import * as taskQueue from "../task-queue"; import * as taskQueue from "../task-queue";
import * as store from "../store"; import * as store from "../store";
import * as notifications from "../notifications"; import * as notifications from "../notifications";
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
const device = vnode.attrs.device; const device = vnode.attrs.device;
@@ -67,5 +68,4 @@ const component = {
); );
} }
}; };
}
export default component;
+12 -6
View File
@@ -1,10 +1,11 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "../components";
import * as notifications from "../notifications"; import * as notifications from "../notifications";
import * as store from "../store"; import * as store from "../store";
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
const device = vnode.attrs.device; const device = vnode.attrs.device;
let writable = true; let writable = true;
@@ -34,12 +35,18 @@ const component = {
.updateTags(deviceId, { [tag]: false }) .updateTags(deviceId, { [tag]: false })
.then(() => { .then(() => {
e.target.disabled = false; e.target.disabled = false;
notifications.push("success", `${deviceId}: Tags updated`); notifications.push(
"success",
`${deviceId}: Tags updated`
);
store.fulfill(0, Date.now()); store.fulfill(0, Date.now());
}) })
.catch(err => { .catch(err => {
e.target.disabled = false; e.target.disabled = false;
notifications.push("error", `${deviceId}: ${err.message}`); notifications.push(
"error",
`${deviceId}: ${err.message}`
);
}); });
} }
}, },
@@ -80,5 +87,4 @@ const component = {
); );
} }
}; };
}
export default component;
+7 -13
View File
@@ -1,12 +1,10 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import * as store from "./store"; import * as store from "./store";
import * as notifications from "./notifications"; import * as notifications from "./notifications";
import putFormComponent from "./put-form-component"; import putFormComponent from "./put-form-component";
import * as overlay from "./overlay"; import * as overlay from "./overlay";
import longTextComponent from "./long-text-component";
import * as expressionParser from "../lib/common/expression-parser"; import * as expressionParser from "../lib/common/expression-parser";
import { loadCodeMirror } from "./dynamic-loader"; import { loadCodeMirror } from "./dynamic-loader";
@@ -84,7 +82,7 @@ function escapeRegExp(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&"); return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&");
} }
function init() { export function init() {
if (!window.authorizer.hasAccess("config", 2)) { if (!window.authorizer.hasAccess("config", 2)) {
return Promise.reject( return Promise.reject(
new Error("You are not authorized to view this page") new Error("You are not authorized to view this page")
@@ -177,14 +175,10 @@ function renderTable(confsResponse, searchString) {
m( m(
"tr", "tr",
attrs, attrs,
m("td.left", m(longTextComponent, { text: conf._id })), m("td.left", m("long-text", { text: conf._id })),
m( m(
"td.right", "td.right",
m("span", [ m("span", [m("long-text", { text: `${conf.value}` }), edit, del])
m(longTextComponent, { text: `${conf.value}` }),
edit,
del
])
) )
) )
); );
@@ -196,7 +190,8 @@ function renderTable(confsResponse, searchString) {
return m("table", m("tbody", rows)); return m("table", m("tbody", rows));
} }
const component = { export function component() {
return {
view: vnode => { view: vnode => {
document.title = "Config - GenieACS"; document.title = "Config - GenieACS";
@@ -271,5 +266,4 @@ const component = {
]; ];
} }
}; };
}
export { init, component };
+8 -17
View File
@@ -1,12 +1,10 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import config from "./config"; import config from "./config";
import * as store from "./store"; import * as store from "./store";
import * as components from "./components";
function init(args) { export function init(args) {
if (!window.authorizer.hasAccess("devices", 2)) { if (!window.authorizer.hasAccess("devices", 2)) {
return Promise.reject( return Promise.reject(
new Error("You are not authorized to view this page") new Error("You are not authorized to view this page")
@@ -19,7 +17,8 @@ function init(args) {
}); });
} }
const component = { export function component() {
return {
view: vnode => { view: vnode => {
document.title = `${vnode.attrs.deviceId} - Devices - GenieACS`; document.title = `${vnode.attrs.deviceId} - Devices - GenieACS`;
@@ -28,18 +27,10 @@ const component = {
const conf = config.ui.device; const conf = config.ui.device;
const cmps = []; const cmps = [];
for (const c of Object.values(conf)) { for (const c of Object.values(conf))
cmps.push( cmps.push(m.context({ device: dev[0] }, c["type"], c));
m(components.get(c["type"]), Object.assign({ device: dev[0] }, c))
);
}
return [ return [m("h1", vnode.attrs.deviceId), cmps];
m("h1", vnode.attrs.deviceId),
m("span", dev[0]["InternetGatewayDevice.DeviceInfo.SerialNumber"]),
cmps
];
} }
}; };
}
export { init, component };
+15 -15
View File
@@ -1,11 +1,9 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import config from "./config"; import config from "./config";
import filterComponent from "./filter-component"; import filterComponent from "./filter-component";
import * as store from "./store"; import * as store from "./store";
import * as components from "./components";
import * as taskQueue from "./task-queue"; import * as taskQueue from "./task-queue";
import * as notifications from "./notifications"; import * as notifications from "./notifications";
import { evaluate, extractParams } from "../lib/common/expression"; import { evaluate, extractParams } from "../lib/common/expression";
@@ -36,10 +34,6 @@ const getDownloadUrl = memoize((filter, indexParameters) => {
})}`; })}`;
}); });
const getChildAttrs = memoize((attrs, device) =>
Object.assign({}, attrs, { device: device })
);
const unpackSmartQuery = memoize(query => { const unpackSmartQuery = memoize(query => {
return expressionParser.map(query, e => { return expressionParser.map(query, e => {
if (Array.isArray(e) && e[0] === "FUNC" && e[1] === "Q") if (Array.isArray(e) && e[0] === "FUNC" && e[1] === "Q")
@@ -48,7 +42,7 @@ const unpackSmartQuery = memoize(query => {
}); });
}); });
function init(args) { export function init(args) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!window.authorizer.hasAccess("devices", 2)) if (!window.authorizer.hasAccess("devices", 2))
return void reject(new Error("You are not authorized to view this page")); return void reject(new Error("You are not authorized to view this page"));
@@ -138,8 +132,11 @@ function renderTable(
}, },
m("td", checkbox), m("td", checkbox),
parameters.map(p => { parameters.map(p => {
const attrs = getChildAttrs(p, device); const comp = m.context(
const comp = m(components.get(attrs.type || "parameter"), attrs); { device: device, parameter: p.parameter },
p.type || "parameter",
p
);
return m("td", comp); return m("td", comp);
}), }),
m( m(
@@ -339,12 +336,14 @@ function renderActions(selected) {
return m(".actions-bar", buttons); return m(".actions-bar", buttons);
} }
const component = { export function component() {
return {
view: vnode => { view: vnode => {
document.title = "Devices - GenieACS"; document.title = "Devices - GenieACS";
function showMore() { function showMore() {
vnode.state.showCount = (vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE; vnode.state.showCount =
(vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE;
m.redraw(); m.redraw();
} }
@@ -361,7 +360,9 @@ const component = {
} }
const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {}; const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {};
let filter = vnode.attrs.filter ? memoizedParse(vnode.attrs.filter) : true; let filter = vnode.attrs.filter
? memoizedParse(vnode.attrs.filter)
: true;
filter = unpackSmartQuery(filter); filter = unpackSmartQuery(filter);
const devs = store.fetch("devices", filter, { const devs = store.fetch("devices", filter, {
@@ -405,5 +406,4 @@ const component = {
]; ];
} }
}; };
}
export { init, component };
+5 -4
View File
@@ -312,7 +312,8 @@ function renderNotifications(notifs) {
return notificationElements; return notificationElements;
} }
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
const queue = taskQueue.getQueue(); const queue = taskQueue.getQueue();
const staging = taskQueue.getStaging(); const staging = taskQueue.getStaging();
@@ -332,7 +333,8 @@ const component = {
} }
function resizeDrawer() { function resizeDrawer() {
let height = statusElement.dom.offsetTop + statusElement.dom.offsetHeight; let height =
statusElement.dom.offsetTop + statusElement.dom.offsetHeight;
if (stagingElements.length) { if (stagingElements.length) {
for (const s of stagingElements) for (const s of stagingElements)
height = Math.max(height, s.dom.offsetTop + s.dom.offsetHeight); height = Math.max(height, s.dom.offsetTop + s.dom.offsetHeight);
@@ -494,5 +496,4 @@ const component = {
); );
} }
}; };
}
export default component;
+4 -4
View File
@@ -1,12 +1,12 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
const component = { export function component() {
return {
view: function(vnode) { view: function(vnode) {
document.title = "Error! - GenieACS"; document.title = "Error! - GenieACS";
return m("p.error", vnode.attrs.error); return m("p.error", vnode.attrs.error);
} }
}; };
}
export { component };
+15 -17
View File
@@ -1,6 +1,6 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import config from "./config"; import config from "./config";
import filterComponent from "./filter-component"; import filterComponent from "./filter-component";
import * as store from "./store"; import * as store from "./store";
@@ -9,7 +9,6 @@ import memoize from "../lib/common/memoize";
import * as smartQuery from "./smart-query"; import * as smartQuery from "./smart-query";
import { map, parse } from "../lib/common/expression-parser"; import { map, parse } from "../lib/common/expression-parser";
import { loadYaml, yaml } from "./dynamic-loader"; import { loadYaml, yaml } from "./dynamic-loader";
import longTextComponent from "./long-text-component";
const PAGE_SIZE = config.ui.pageSize || 10; const PAGE_SIZE = config.ui.pageSize || 10;
@@ -47,7 +46,7 @@ const unpackSmartQuery = memoize(query => {
}); });
}); });
function init(args) { export function init(args) {
if (!window.authorizer.hasAccess("faults", 2)) { if (!window.authorizer.hasAccess("faults", 2)) {
return Promise.reject( return Promise.reject(
new Error("You are not authorized to view this page") new Error("You are not authorized to view this page")
@@ -136,17 +135,13 @@ function renderTable(
const tds = [m("td", checkbox)]; const tds = [m("td", checkbox)];
for (const attr of attributes) { for (const attr of attributes) {
if (attr.id === "device") { if (attr.id === "device")
tds.push(m("td", m("a", { href: deviceHref }, f[attr.id]))); tds.push(m("td", m("a", { href: deviceHref }, f[attr.id])));
} else if (attr.id === "timestamp") { else if (attr.id === "timestamp")
tds.push(m("td", new Date(f[attr.id]).toLocaleString())); tds.push(m("td", new Date(f[attr.id]).toLocaleString()));
} else if (attr.id === "detail") { else if (attr.id === "detail")
tds.push( tds.push(m("td", m("long-text", { text: yaml.stringify(f[attr.id]) })));
m("td", m(longTextComponent, { text: yaml.stringify(f[attr.id]) })) else tds.push(m("td", f[attr.id]));
);
} else {
tds.push(m("td", f[attr.id]));
}
} }
rows.push( rows.push(
@@ -234,12 +229,14 @@ function renderTable(
]; ];
} }
const component = { export function component() {
return {
view: vnode => { view: vnode => {
document.title = "Faults - GenieACS"; document.title = "Faults - GenieACS";
function showMore() { function showMore() {
vnode.state.showCount = (vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE; vnode.state.showCount =
(vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE;
m.redraw(); m.redraw();
} }
@@ -256,7 +253,9 @@ const component = {
} }
const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {}; const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {};
let filter = vnode.attrs.filter ? memoizedParse(vnode.attrs.filter) : true; let filter = vnode.attrs.filter
? memoizedParse(vnode.attrs.filter)
: true;
filter = unpackSmartQuery(filter); filter = unpackSmartQuery(filter);
const faults = store.fetch("faults", filter, { const faults = store.fetch("faults", filter, {
@@ -293,5 +292,4 @@ const component = {
]; ];
} }
}; };
}
export { init, component };
+10 -8
View File
@@ -1,7 +1,6 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import config from "./config"; import config from "./config";
import filterComponent from "./filter-component"; import filterComponent from "./filter-component";
import * as store from "./store"; import * as store from "./store";
@@ -110,7 +109,7 @@ const getDownloadUrl = memoize(filter => {
})}`; })}`;
}); });
function init(args) { export function init(args) {
if (!window.authorizer.hasAccess("files", 2)) { if (!window.authorizer.hasAccess("files", 2)) {
return Promise.reject( return Promise.reject(
new Error("You are not authorized to view this page") new Error("You are not authorized to view this page")
@@ -319,12 +318,14 @@ function renderTable(
]; ];
} }
const component = { export function component() {
return {
view: vnode => { view: vnode => {
document.title = "Files - GenieACS"; document.title = "Files - GenieACS";
function showMore() { function showMore() {
vnode.state.showCount = (vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE; vnode.state.showCount =
(vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE;
m.redraw(); m.redraw();
} }
@@ -341,7 +342,9 @@ const component = {
} }
const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {}; const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {};
let filter = vnode.attrs.filter ? memoizedParse(vnode.attrs.filter) : true; let filter = vnode.attrs.filter
? memoizedParse(vnode.attrs.filter)
: true;
filter = unpackSmartQuery(filter); filter = unpackSmartQuery(filter);
const files = store.fetch("files", filter, { const files = store.fetch("files", filter, {
@@ -379,5 +382,4 @@ const component = {
]; ];
} }
}; };
}
export { init, component };
+7 -4
View File
@@ -56,9 +56,13 @@ const splitFilter = memoize(filter => {
return list; return list;
}); });
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
if (!vnode.state.filterList || vnode.attrs.filter !== vnode.state.filter) { if (
!vnode.state.filterList ||
vnode.attrs.filter !== vnode.state.filter
) {
vnode.state.filterInvalid = 0; vnode.state.filterInvalid = 0;
vnode.state.filter = vnode.attrs.filter; vnode.state.filter = vnode.attrs.filter;
vnode.state.filterList = splitFilter(vnode.attrs.filter); vnode.state.filterList = splitFilter(vnode.attrs.filter);
@@ -111,5 +115,4 @@ const component = {
); );
} }
}; };
}
export default component;
+3 -4
View File
@@ -1,7 +1,6 @@
"use strict"; "use strict";
import m from "mithril"; import m from "mithril";
import menu from "./menu"; import menu from "./menu";
import drawerComponent from "./drawer-component"; import drawerComponent from "./drawer-component";
import userMenu from "./user-menu"; import userMenu from "./user-menu";
@@ -16,7 +15,8 @@ const adminPages = [
"config" "config"
]; ];
const layout = { export default function layout() {
return {
view: vnode => { view: vnode => {
let sideMenu, group; let sideMenu, group;
if (adminPages.includes(vnode.attrs.page)) { if (adminPages.includes(vnode.attrs.page)) {
@@ -40,5 +40,4 @@ const layout = {
]; ];
} }
}; };
}
export default layout;
+5 -6
View File
@@ -1,15 +1,15 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import * as store from "./store"; import * as store from "./store";
import * as notifications from "./notifications"; import * as notifications from "./notifications";
function init(args) { export function init(args) {
return Promise.resolve(args); return Promise.resolve(args);
} }
const component = { export function component() {
return {
view: vnode => { view: vnode => {
if (window.username) m.route.set(vnode.attrs.continue || "/"); if (window.username) m.route.set(vnode.attrs.continue || "/");
@@ -68,5 +68,4 @@ const component = {
]; ];
} }
}; };
}
export { init, component };
+3 -3
View File
@@ -3,7 +3,8 @@
import m from "mithril"; import m from "mithril";
import * as overlay from "./overlay"; import * as overlay from "./overlay";
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
const text = vnode.attrs.text; const text = vnode.attrs.text;
const element = vnode.attrs.element || "span"; const element = vnode.attrs.element || "span";
@@ -52,5 +53,4 @@ const component = {
); );
} }
}; };
}
export default component;
+9 -4
View File
@@ -2,7 +2,8 @@
import m from "mithril"; import m from "mithril";
const menu = { export default function menu() {
return {
view: vnode => { view: vnode => {
const active = { [vnode.attrs.page]: "active" }; const active = { [vnode.attrs.page]: "active" };
@@ -37,7 +38,12 @@ const menu = {
); );
} }
const adminPages = ["presets", "provisions", "virtualParameters", "files"]; const adminPages = [
"presets",
"provisions",
"virtualParameters",
"files"
];
for (const page of adminPages) { for (const page of adminPages) {
if (window.authorizer.hasAccess(page, 2)) { if (window.authorizer.hasAccess(page, 2)) {
tabs.push( tabs.push(
@@ -54,5 +60,4 @@ const menu = {
return m("nav", m("ul", tabs)); return m("nav", m("ul", tabs));
} }
}; };
}
export default menu;
+2 -4
View File
@@ -4,7 +4,7 @@ import m from "mithril";
const notifications = new Set(); const notifications = new Set();
function push(type, message) { export function push(type, message) {
const n = { type: type, message: message, timestamp: Date.now() }; const n = { type: type, message: message, timestamp: Date.now() };
notifications.add(n); notifications.add(n);
m.redraw(); m.redraw();
@@ -14,8 +14,6 @@ function push(type, message) {
}, 4000); }, 4000);
} }
function getNotifications() { export function getNotifications() {
return notifications; return notifications;
} }
export { push, getNotifications };
+6 -6
View File
@@ -1,6 +1,6 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import config from "./config"; import config from "./config";
import * as store from "./store"; import * as store from "./store";
import pieChartComponent from "./pie-chart-component"; import pieChartComponent from "./pie-chart-component";
@@ -26,7 +26,7 @@ function queryCharts(charts) {
return charts; return charts;
} }
const init = function() { export function init() {
if (!window.authorizer.hasAccess("devices", 1)) { if (!window.authorizer.hasAccess("devices", 1)) {
return Promise.reject( return Promise.reject(
new Error("You are not authorized to view this page") new Error("You are not authorized to view this page")
@@ -34,9 +34,10 @@ const init = function() {
} }
return Promise.resolve({ charts: queryCharts(CHARTS) }); return Promise.resolve({ charts: queryCharts(CHARTS) });
}; }
const component = { export function component() {
return {
view: vnode => { view: vnode => {
document.title = "Overview - GenieACS"; document.title = "Overview - GenieACS";
const children = []; const children = [];
@@ -60,5 +61,4 @@ const component = {
return children; return children;
} }
}; };
}
export { init, component };
+4 -4
View File
@@ -1,6 +1,6 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import { stringify } from "../lib/common/expression-parser"; import { stringify } from "../lib/common/expression-parser";
import memoize from "../lib/common/memoize"; import memoize from "../lib/common/memoize";
@@ -115,10 +115,10 @@ const drawChart = function(chartData) {
]); ]);
}; };
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
return drawChart(vnode.attrs.chart); return drawChart(vnode.attrs.chart);
} }
}; };
}
export default component;
+10 -8
View File
@@ -1,7 +1,6 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import config from "./config"; import config from "./config";
import filterComponent from "./filter-component"; import filterComponent from "./filter-component";
import * as overlay from "./overlay"; import * as overlay from "./overlay";
@@ -108,7 +107,7 @@ const getDownloadUrl = memoize(filter => {
})}`; })}`;
}); });
function init(args) { export function init(args) {
if (!window.authorizer.hasAccess("presets", 2)) { if (!window.authorizer.hasAccess("presets", 2)) {
return Promise.reject( return Promise.reject(
new Error("You are not authorized to view this page") new Error("You are not authorized to view this page")
@@ -383,12 +382,14 @@ function renderTable(
]; ];
} }
const component = { export function component() {
return {
view: vnode => { view: vnode => {
document.title = "Presets - GenieACS"; document.title = "Presets - GenieACS";
function showMore() { function showMore() {
vnode.state.showCount = (vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE; vnode.state.showCount =
(vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE;
m.redraw(); m.redraw();
} }
@@ -405,7 +406,9 @@ const component = {
} }
const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {}; const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {};
let filter = vnode.attrs.filter ? memoizedParse(vnode.attrs.filter) : true; let filter = vnode.attrs.filter
? memoizedParse(vnode.attrs.filter)
: true;
filter = unpackSmartQuery(filter); filter = unpackSmartQuery(filter);
const presets = store.fetch("presets", filter, { const presets = store.fetch("presets", filter, {
@@ -465,5 +468,4 @@ const component = {
]; ];
} }
}; };
}
export { init, component };
+10 -8
View File
@@ -1,7 +1,6 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import config from "./config"; import config from "./config";
import filterComponent from "./filter-component"; import filterComponent from "./filter-component";
import * as store from "./store"; import * as store from "./store";
@@ -98,7 +97,7 @@ const getDownloadUrl = memoize(filter => {
})}`; })}`;
}); });
function init(args) { export function init(args) {
if (!window.authorizer.hasAccess("provisions", 2)) { if (!window.authorizer.hasAccess("provisions", 2)) {
return Promise.reject( return Promise.reject(
new Error("You are not authorized to view this page") new Error("You are not authorized to view this page")
@@ -371,12 +370,14 @@ function renderTable(
]; ];
} }
const component = { export function component() {
return {
view: vnode => { view: vnode => {
document.title = "Provisions - GenieACS"; document.title = "Provisions - GenieACS";
function showMore() { function showMore() {
vnode.state.showCount = (vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE; vnode.state.showCount =
(vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE;
m.redraw(); m.redraw();
} }
@@ -393,7 +394,9 @@ const component = {
} }
const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {}; const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {};
let filter = vnode.attrs.filter ? memoizedParse(vnode.attrs.filter) : true; let filter = vnode.attrs.filter
? memoizedParse(vnode.attrs.filter)
: true;
filter = unpackSmartQuery(filter); filter = unpackSmartQuery(filter);
const provisions = store.fetch("provisions", filter, { const provisions = store.fetch("provisions", filter, {
@@ -433,5 +436,4 @@ const component = {
]; ];
} }
}; };
}
export { init, component };
+6 -5
View File
@@ -1,6 +1,6 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import { codeMirror } from "./dynamic-loader"; import { codeMirror } from "./dynamic-loader";
const singular = { const singular = {
@@ -93,7 +93,8 @@ function createField(current, attr, focus) {
}); });
} }
const component = { export default function component() {
return {
view: vnode => { view: vnode => {
const actionHandler = vnode.attrs.actionHandler; const actionHandler = vnode.attrs.actionHandler;
const attributes = vnode.attrs.attributes; const attributes = vnode.attrs.attributes;
@@ -153,7 +154,8 @@ const component = {
const children = [ const children = [
m( m(
"h1", "h1",
`${current.isNew ? "New" : "Editing"} ${singular[resource] || resource}` `${current.isNew ? "New" : "Editing"} ${singular[resource] ||
resource}`
), ),
m( m(
"form", "form",
@@ -179,5 +181,4 @@ const component = {
return m("div.put-form", children); return m("div.put-form", children);
} }
}; };
}
export default component;
+5 -4
View File
@@ -5,7 +5,8 @@ import m from "mithril";
import * as store from "./store"; import * as store from "./store";
import * as notifications from "./notifications"; import * as notifications from "./notifications";
const userMenu = { export default function userMenu() {
return {
view: () => { view: () => {
if (window.username) { if (window.username) {
return m( return m(
@@ -38,7 +39,8 @@ const userMenu = {
m( m(
"a", "a",
{ {
href: "#!/login?" + m.buildQueryString({ continue: m.route.get() }) href:
"#!/login?" + m.buildQueryString({ continue: m.route.get() })
}, },
"Log in" "Log in"
) )
@@ -46,5 +48,4 @@ const userMenu = {
} }
} }
}; };
}
export default userMenu;
+10 -8
View File
@@ -1,7 +1,6 @@
"use strict"; "use strict";
import m from "mithril"; import { m } from "./components";
import config from "./config"; import config from "./config";
import filterComponent from "./filter-component"; import filterComponent from "./filter-component";
import * as store from "./store"; import * as store from "./store";
@@ -98,7 +97,7 @@ const getDownloadUrl = memoize(filter => {
})}`; })}`;
}); });
function init(args) { export function init(args) {
if (!window.authorizer.hasAccess("virtualParameters", 2)) { if (!window.authorizer.hasAccess("virtualParameters", 2)) {
return Promise.reject( return Promise.reject(
new Error("You are not authorized to view this page") new Error("You are not authorized to view this page")
@@ -381,12 +380,14 @@ function renderTable(
]; ];
} }
const component = { export function component() {
return {
view: vnode => { view: vnode => {
document.title = "Virtual Parameters - GenieACS"; document.title = "Virtual Parameters - GenieACS";
function showMore() { function showMore() {
vnode.state.showCount = (vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE; vnode.state.showCount =
(vnode.state.showCount || PAGE_SIZE) + PAGE_SIZE;
m.redraw(); m.redraw();
} }
@@ -403,7 +404,9 @@ const component = {
} }
const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {}; const sort = vnode.attrs.sort ? memoizedJsonParse(vnode.attrs.sort) : {};
let filter = vnode.attrs.filter ? memoizedParse(vnode.attrs.filter) : true; let filter = vnode.attrs.filter
? memoizedParse(vnode.attrs.filter)
: true;
filter = unpackSmartQuery(filter); filter = unpackSmartQuery(filter);
const virtualParameters = store.fetch("virtualParameters", filter, { const virtualParameters = store.fetch("virtualParameters", filter, {
@@ -443,5 +446,4 @@ const component = {
]; ];
} }
}; };
}
export { init, component };