Files

115 lines
3.0 KiB
TypeScript

import { ClosureComponent, Component, VnodeDOM } from "mithril";
import { m } from "../components.ts";
import * as taskQueue from "../task-queue.ts";
import * as store from "../store.ts";
import { evaluate } from "../../lib/common/expression/util.ts";
import memoize from "../../lib/common/memoize.ts";
import timeAgo from "../timeago.ts";
import { getIcon } from "../icons.ts";
const evaluateParam = memoize((exp, obj, now: number) => {
let timestamp = now;
exp = evaluate(exp, null, now, (e) => {
if (!Array.isArray(e)) return e;
for (let i = 1; i < e.length; ++i) {
if (
Array.isArray(e[i]) &&
e[i][0] === "PARAM" &&
!Array.isArray(e[i][1])
) {
let v = null;
const p = obj[e[i][1]];
if (p?.value) {
v = p.value[0];
timestamp = Math.min(timestamp, p.valueTimestamp);
}
e = e.slice();
e[i] = v;
}
}
if (e[0] === "FUNC" && e[1] === "DATE_STRING" && !Array.isArray(e[2]))
return new Date(e[2]).toLocaleString();
return e;
});
let parameter = null;
let value = null;
if (!Array.isArray(exp)) {
value = exp;
} else if (exp[0] === "PARAM") {
const p = obj[exp[1]];
if (p?.value) {
timestamp = p.valueTimestamp;
value = p.value[0];
parameter = exp[1];
if (p.value[1] === "xsd:dateTime" && typeof value === "number")
value = new Date(value).toLocaleString();
}
}
return { value, timestamp, parameter };
});
const component: ClosureComponent = (): Component => {
return {
view: (vnode) => {
const device = vnode.attrs["device"];
const { value, timestamp, parameter } = evaluateParam(
vnode.attrs["parameter"],
device,
store.getTimestamp() + store.getClockSkew(),
);
if (value == null) return null;
let edit;
if (device[parameter]?.writable) {
edit = m(
"button",
{
title: "Edit parameter value",
onclick: () => {
taskQueue.stageSpv({
name: "setParameterValues",
devices: [device["DeviceID.ID"].value[0]],
parameterValues: [
[
parameter,
device[parameter].value[0],
device[parameter].value[1],
],
],
});
},
},
getIcon("edit"),
);
}
const el = m("long-text", { text: `${value}` });
return m(
"span",
{
class: "parameter-value",
onmouseover: (e) => {
e.redraw = false;
// Don't update any child element
if (e.target === (el as VnodeDOM).dom) {
const now = Date.now() + store.getClockSkew();
const localeString = new Date(timestamp).toLocaleString();
e.target.title = `${localeString} (${timeAgo(now - timestamp)})`;
}
},
},
el,
edit,
);
},
};
};
export default component;