refactor: replace array-based expressions with typed class hierarchy
Replace the old Lisp-like array expression representation (["AND", ["PARAM", ...], ...]) with a class hierarchy rooted in an abstract Expression class (Literal, Parameter, Binary, Unary, FunctionCall, Conditional). This gives compile-time type safety to expression construction, evaluation, and pattern matching. Key changes: - New lib/common/expression.ts defines the class hierarchy with map/evaluate/toString methods - Rewrite parser as hand-rolled recursive descent, removing the parsimmon dependency - Extend Path with a colon separator to unify parameter identity and attributes into a single address space (e.g. "Device.WiFi.SSID.1.Name:writable"). The colon field tracks how many trailing segments are attribute qualifiers. PathSet rewritten with separate param/attr segment indexes - Flatten device attribute representation in the UI to colon-delimited keys mirroring the new path syntax
This commit is contained in:
1 parent
75908e624f
commit
6f3ce6f7c8
71 files changed
+4045
-3449
No files matched your search
+111
-1
@@ -1,3 +1,113 @@
|
||||
export default window.clientConfig;
|
||||
import Expression from "../lib/common/expression.ts";
|
||||
export const configSnapshot = window.configSnapshot;
|
||||
export const genieacsVersion = window.genieacsVersion;
|
||||
|
||||
type Filters = { label: string; parameter: Expression; type: string }[];
|
||||
type pageSize = number;
|
||||
type overview = {
|
||||
charts: {
|
||||
[name: string]: {
|
||||
label: string;
|
||||
slices: {
|
||||
label: string;
|
||||
filter: Expression;
|
||||
color: string;
|
||||
}[];
|
||||
};
|
||||
};
|
||||
groups: {
|
||||
label: string;
|
||||
charts: string[];
|
||||
}[];
|
||||
};
|
||||
|
||||
type Index = {
|
||||
label: string;
|
||||
type?: string;
|
||||
parameter: Expression;
|
||||
unsortable: boolean;
|
||||
raw: NestedRecord;
|
||||
}[];
|
||||
|
||||
type NestedRecord = { [k: string]: Expression | NestedRecord };
|
||||
|
||||
const conf: NestedRecord = {};
|
||||
for (const [key, value] of Object.entries(window.clientConfig)) {
|
||||
const exp = Expression.parse(value).evaluate((e) => e);
|
||||
let ref = conf;
|
||||
const keyParts = key.split(".");
|
||||
while (keyParts.length > 1) {
|
||||
const k = keyParts.shift();
|
||||
if (ref[k] == null || typeof ref[k] !== "object") ref[k] = {};
|
||||
ref = ref[k] as NestedRecord;
|
||||
}
|
||||
ref[keyParts[0]] = exp;
|
||||
}
|
||||
|
||||
export const filters: Filters = [];
|
||||
export let pageSize: number = 10;
|
||||
export const overview: overview = { charts: {}, groups: [] };
|
||||
export const index: Index = [];
|
||||
export let device: NestedRecord = {};
|
||||
|
||||
for (const obj of Object.values(conf["filters"] || {})) {
|
||||
let label = "";
|
||||
let parameter: Expression = new Expression.Literal(false);
|
||||
let type = "string";
|
||||
if (obj["label"] instanceof Expression.Literal)
|
||||
label = obj["label"].value as string;
|
||||
if (obj["parameter"] instanceof Expression) parameter = obj["parameter"];
|
||||
if (obj["type"] instanceof Expression.Literal)
|
||||
type = obj["type"].value as string;
|
||||
filters.push({ label, parameter, type });
|
||||
}
|
||||
|
||||
for (const obj of Object.values(conf["index"] || {})) {
|
||||
let label = "";
|
||||
let parameter: Expression = new Expression.Literal(null);
|
||||
let unsortable = false;
|
||||
let type = "";
|
||||
if (obj["label"] instanceof Expression.Literal)
|
||||
label = obj["label"].value as string;
|
||||
if (obj["type"] instanceof Expression.Literal)
|
||||
type = obj["type"].value as string;
|
||||
if (obj["parameter"] instanceof Expression) parameter = obj["parameter"];
|
||||
if (obj["unsortable"] instanceof Expression.Literal)
|
||||
unsortable = obj["unsortable"].value as boolean;
|
||||
index.push({ label, type, parameter, unsortable, raw: obj });
|
||||
}
|
||||
|
||||
for (const obj of Object.values(conf["overview"]?.["groups"] || {})) {
|
||||
let label = "";
|
||||
const charts: string[] = [];
|
||||
if (obj["label"] instanceof Expression.Literal)
|
||||
label = obj["label"].value as string;
|
||||
for (const chart of Object.values(obj["charts"] || {})) {
|
||||
if (chart instanceof Expression.Literal) charts.push(chart.value as string);
|
||||
}
|
||||
overview.groups.push({ label, charts });
|
||||
}
|
||||
|
||||
for (const [name, obj] of Object.entries(conf["overview"]?.["charts"] || {})) {
|
||||
const slices: { label: string; filter: Expression; color: string }[] = [];
|
||||
for (const slice of Object.values(obj["slices"] || {})) {
|
||||
let label = "";
|
||||
let filter: Expression = new Expression.Literal(false);
|
||||
let color = "";
|
||||
if (slice["label"] instanceof Expression.Literal)
|
||||
label = slice["label"].value as string;
|
||||
if (slice["filter"] instanceof Expression) filter = slice["filter"];
|
||||
if (slice["color"] instanceof Expression.Literal)
|
||||
color = slice["color"].value as string;
|
||||
slices.push({ label, filter, color });
|
||||
}
|
||||
let label = "";
|
||||
if (obj["label"] instanceof Expression.Literal)
|
||||
label = obj["label"].value as string;
|
||||
overview.charts[name] = { label, slices };
|
||||
}
|
||||
|
||||
if (conf["pageSize"] instanceof Expression.Literal)
|
||||
pageSize = +conf["pageSize"].value || 10;
|
||||
|
||||
device = conf["device"] as NestedRecord;
|
||||
Reference in new issue
Block a user