Files
genieacs/ui/config-page.js
T
2019-02-04 23:47:54 -08:00

276 lines
7.1 KiB
JavaScript

"use strict";
import m from "mithril";
import * as store from "./store";
import * as notifications from "./notifications";
import putFormComponent from "./put-form-component";
import * as overlay from "./overlay";
import longTextComponent from "./long-text-component";
import * as expressionParser from "../lib/common/expression-parser";
import { loadCodeMirror } from "./dynamic-loader";
const attributes = [
{ id: "_id", label: "Key" },
{ id: "value", label: "Value" }
];
function putActionHandler(action, _object, isNew) {
return new Promise((resolve, reject) => {
const object = Object.assign({}, _object);
if (action === "save") {
const id = object["_id"];
delete object["_id"];
if (!id) return void resolve({ _id: "ID can not be empty" });
try {
expressionParser.parse(object.value);
} catch (err) {
return void resolve({
value: "Config value must be valid expression"
});
}
store
.resourceExists("config", id)
.then(exists => {
if (exists && isNew) {
store.fulfill(0, Date.now());
return void resolve({ _id: "Config already exists" });
}
if (!exists && !isNew) {
store.fulfill(0, Date.now());
return void resolve({ _id: "Config does not exist" });
}
store
.putResource("config", id, object)
.then(() => {
notifications.push(
"success",
`Config ${exists ? "updated" : "created"}`
);
store.fulfill(0, Date.now());
resolve();
})
.catch(reject);
})
.catch(reject);
} else if (action === "delete") {
store
.deleteResource("config", object["_id"])
.then(() => {
notifications.push("success", "Config deleted");
store.fulfill(0, Date.now());
resolve();
})
.catch(err => {
store.fulfill(0, Date.now());
reject(err);
});
} else {
reject(new Error("Undefined action"));
}
});
}
const formData = {
resource: "config",
attributes: attributes
};
function escapeRegExp(str) {
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, "\\$&");
}
function init() {
if (!window.authorizer.hasAccess("config", 2)) {
return Promise.reject(
new Error("You are not authorized to view this page")
);
}
return new Promise((resolve, reject) => {
loadCodeMirror()
.then(() => {
resolve({});
})
.catch(reject);
});
}
function renderTable(confsResponse, searchString) {
const confs = confsResponse.value.sort((a, b) => {
return a._id < b._id ? -1 : 1;
});
let regex;
if (searchString) {
const keywords = searchString.split(" ").filter(s => s);
if (keywords.length)
regex = new RegExp(keywords.map(s => escapeRegExp(s)).join(".*"), "i");
}
const rows = [];
for (const conf of confs) {
const attrs = {};
if (regex && !regex.test(conf._id) && !regex.test(conf.value))
attrs.style = "display: none;";
const edit = m(
"button",
{
title: "Edit config value",
onclick: () => {
const cb = () => {
return m(
putFormComponent,
Object.assign(
{
base: conf,
actionHandler: (action, object) => {
return new Promise(resolve => {
putActionHandler(action, object, false)
.then(errors => {
errors = errors ? Object.values(errors) : [];
if (errors.length) {
for (const err of errors)
notifications.push("error", err);
} else {
overlay.close(cb);
}
resolve();
})
.catch(err => {
notifications.push("error", err.message);
resolve();
});
});
}
},
formData
)
);
};
overlay.open(cb);
}
},
"✎"
);
const del = m(
"button",
{
title: "Delete config",
onclick: () => {
if (!confirm(`Deleting ${conf._id} config. Are you sure?`)) return;
putActionHandler("delete", conf).catch(err => {
throw err;
});
}
},
"✕"
);
rows.push(
m(
"tr",
attrs,
m("td.left", m(longTextComponent, { text: conf._id })),
m(
"td.right",
m("span", [
m(longTextComponent, { text: `${conf.value}` }),
edit,
del
])
)
)
);
}
if (!rows.length)
rows.push(m("tr.empty", m("td", { colspan: 2 }, "No config")));
return m("table", m("tbody", rows));
}
const component = {
view: vnode => {
document.title = "Config - GenieACS";
const search = m("input", {
type: "text",
placeholder: "Search config",
oninput: e => {
vnode.state.searchString = e.target.value;
e.redraw = false;
clearTimeout(vnode.state.timeout);
vnode.state.timeout = setTimeout(m.redraw, 250);
}
});
let newConfig;
if (window.authorizer.hasAccess("config", 3)) {
newConfig = m(
"button.primary",
{
title: "Create new config",
onclick: () => {
const cb = () => {
return m(
putFormComponent,
Object.assign(
{
actionHandler: (action, object) => {
return new Promise(resolve => {
putActionHandler(action, object, true)
.then(errors => {
errors = errors ? Object.values(errors) : [];
if (errors.length) {
for (const err of errors)
notifications.push("error", err);
} else {
overlay.close(cb);
}
resolve();
})
.catch(err => {
notifications.push("error", err.message);
resolve();
});
});
}
},
formData
)
);
};
overlay.open(cb);
}
},
"New"
);
}
const confs = store.fetch("config", true);
return [
m("h1", "Listing config"),
m(
".all-parameters",
search,
m(
".parameter-list",
{ style: "height: 400px" },
renderTable(confs, vnode.state.searchString)
),
m(".actions-bar", newConfig)
)
];
}
};
export { init, component };