@richardmcquiston01/dashboard-widgets-toolkit 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core.cjs +418 -6
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +2 -2
- package/dist/core.d.ts +2 -2
- package/dist/core.js +407 -7
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +418 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +407 -7
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +325 -49
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +5 -1
- package/dist/react.d.ts +5 -1
- package/dist/react.js +325 -49
- package/dist/react.js.map +1 -1
- package/dist/{storage-_Eb8Y98-.d.cts → storage-DwJ-vGJg.d.cts} +122 -2
- package/dist/{storage-_Eb8Y98-.d.ts → storage-DwJ-vGJg.d.ts} +122 -2
- package/package.json +1 -1
package/dist/core.cjs
CHANGED
|
@@ -688,6 +688,263 @@ function placeAndFillRows(items, columns, spanOf) {
|
|
|
688
688
|
return { spans, rows };
|
|
689
689
|
}
|
|
690
690
|
|
|
691
|
+
// src/core/views.ts
|
|
692
|
+
var BASE_VIEW_KEY = "base";
|
|
693
|
+
var MAX_WIDGET_VIEWS = 8;
|
|
694
|
+
var VIEW_CONVERSIONS = {
|
|
695
|
+
tableToBarList: { from: "TABLE", to: "BAR_LIST" },
|
|
696
|
+
tableToGraph: { from: "TABLE", to: "GRAPH" },
|
|
697
|
+
barListToTable: { from: "BAR_LIST", to: "TABLE" },
|
|
698
|
+
graphToTable: { from: "GRAPH", to: "TABLE" },
|
|
699
|
+
barListToGraph: { from: "BAR_LIST", to: "GRAPH" }
|
|
700
|
+
};
|
|
701
|
+
var KIND_LABELS = {
|
|
702
|
+
TEXT: "Text",
|
|
703
|
+
KPI: "Number",
|
|
704
|
+
GAUGE: "Gauge",
|
|
705
|
+
TABLE: "Table",
|
|
706
|
+
BAR_LIST: "Bars",
|
|
707
|
+
ALERT_LIST: "List",
|
|
708
|
+
GRAPH: "Chart"
|
|
709
|
+
};
|
|
710
|
+
function kindLabel(kind) {
|
|
711
|
+
return KIND_LABELS[kind];
|
|
712
|
+
}
|
|
713
|
+
function hasViews(item) {
|
|
714
|
+
return item.views !== void 0 && item.views.length > 0;
|
|
715
|
+
}
|
|
716
|
+
function findView(item, key) {
|
|
717
|
+
return item.views?.find((view) => view.key === key);
|
|
718
|
+
}
|
|
719
|
+
function viewChoices(item) {
|
|
720
|
+
if (!hasViews(item)) return [];
|
|
721
|
+
return [
|
|
722
|
+
{
|
|
723
|
+
key: BASE_VIEW_KEY,
|
|
724
|
+
label: item.baseViewLabel ?? kindLabel(item.kind),
|
|
725
|
+
kind: item.kind
|
|
726
|
+
},
|
|
727
|
+
...(item.views ?? []).map(({ key, label, kind }) => ({
|
|
728
|
+
key,
|
|
729
|
+
label,
|
|
730
|
+
kind
|
|
731
|
+
}))
|
|
732
|
+
];
|
|
733
|
+
}
|
|
734
|
+
function isKnownView(item, key) {
|
|
735
|
+
return key !== void 0 && (key === BASE_VIEW_KEY || findView(item, key) !== void 0);
|
|
736
|
+
}
|
|
737
|
+
function effectiveViewKey(item, chosen) {
|
|
738
|
+
if (!hasViews(item)) return BASE_VIEW_KEY;
|
|
739
|
+
if (isKnownView(item, chosen)) return chosen;
|
|
740
|
+
if (isKnownView(item, item.defaultView)) return item.defaultView;
|
|
741
|
+
return BASE_VIEW_KEY;
|
|
742
|
+
}
|
|
743
|
+
function viewKind(item, chosen) {
|
|
744
|
+
return findView(item, effectiveViewKey(item, chosen))?.kind ?? item.kind;
|
|
745
|
+
}
|
|
746
|
+
function cellValue2(cell) {
|
|
747
|
+
const value = cell?.value;
|
|
748
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
749
|
+
}
|
|
750
|
+
function columnName(table, index) {
|
|
751
|
+
return table.columns[index]?.label ?? `#${index + 1}`;
|
|
752
|
+
}
|
|
753
|
+
function checkColumn(table, index, field, context) {
|
|
754
|
+
if (!Number.isInteger(index) || index < 0 || index >= table.columns.length) {
|
|
755
|
+
return `${context.where}: ${field} column ${index} does not exist (the table has ${table.columns.length} columns, numbered from 0).`;
|
|
756
|
+
}
|
|
757
|
+
return void 0;
|
|
758
|
+
}
|
|
759
|
+
function numericColumn(table, index, context) {
|
|
760
|
+
const numbers = [];
|
|
761
|
+
for (const [rowIndex, row] of table.rows.entries()) {
|
|
762
|
+
const value = cellValue2(row[index]);
|
|
763
|
+
if (value === void 0) {
|
|
764
|
+
return err(
|
|
765
|
+
`${context.where}: row ${rowIndex + 1}, column ${index + 1} ("${columnName(table, index)}") has no numeric value. Add value to the cells.`
|
|
766
|
+
);
|
|
767
|
+
}
|
|
768
|
+
numbers.push(value);
|
|
769
|
+
}
|
|
770
|
+
return ok(numbers);
|
|
771
|
+
}
|
|
772
|
+
function tableToBarList(table, conversion, context) {
|
|
773
|
+
const bad = checkColumn(table, conversion.label, "label", context) ?? checkColumn(table, conversion.value, "value", context);
|
|
774
|
+
if (bad !== void 0) return err(bad);
|
|
775
|
+
const numbers = numericColumn(table, conversion.value, context);
|
|
776
|
+
if (!numbers.ok) return numbers;
|
|
777
|
+
const items = table.rows.map((row, index) => ({
|
|
778
|
+
label: row[conversion.label]?.text ?? "",
|
|
779
|
+
value: numbers.value[index],
|
|
780
|
+
display: row[conversion.value]?.text ?? String(numbers.value[index])
|
|
781
|
+
}));
|
|
782
|
+
return ok({ kind: "BAR_LIST", items });
|
|
783
|
+
}
|
|
784
|
+
function tableToGraph(table, conversion, context) {
|
|
785
|
+
if (conversion.values.length === 0 || conversion.values.length > MAX_GRAPH_SERIES) {
|
|
786
|
+
return err(
|
|
787
|
+
`${context.where}: a chart needs 1 to ${MAX_GRAPH_SERIES} series columns, got ${conversion.values.length}.`
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
let bad = checkColumn(
|
|
791
|
+
table,
|
|
792
|
+
conversion.label,
|
|
793
|
+
"label",
|
|
794
|
+
context
|
|
795
|
+
);
|
|
796
|
+
for (const index of conversion.values) {
|
|
797
|
+
bad ??= checkColumn(table, index, "series", context);
|
|
798
|
+
}
|
|
799
|
+
if (bad !== void 0) return err(bad);
|
|
800
|
+
const series = [];
|
|
801
|
+
for (const index of conversion.values) {
|
|
802
|
+
const numbers = numericColumn(table, index, context);
|
|
803
|
+
if (!numbers.ok) return numbers;
|
|
804
|
+
series.push({
|
|
805
|
+
name: columnName(table, index),
|
|
806
|
+
points: table.rows.map((row, rowIndex) => ({
|
|
807
|
+
label: row[conversion.label]?.text ?? "",
|
|
808
|
+
value: numbers.value[rowIndex]
|
|
809
|
+
}))
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
return ok({
|
|
813
|
+
kind: "GRAPH",
|
|
814
|
+
series,
|
|
815
|
+
chartType: conversion.chartType,
|
|
816
|
+
valueFormat: conversion.valueFormat ?? "number",
|
|
817
|
+
...conversion.currency === void 0 ? {} : { currency: conversion.currency },
|
|
818
|
+
xLabel: columnName(table, conversion.label)
|
|
819
|
+
});
|
|
820
|
+
}
|
|
821
|
+
function barListToTable(list, conversion) {
|
|
822
|
+
return ok({
|
|
823
|
+
kind: "TABLE",
|
|
824
|
+
columns: [
|
|
825
|
+
{ label: conversion.labelHeading ?? "Name" },
|
|
826
|
+
{ label: conversion.valueHeading ?? "Value", numeric: true }
|
|
827
|
+
],
|
|
828
|
+
rows: list.items.map((item) => [
|
|
829
|
+
{ text: item.label },
|
|
830
|
+
{ text: item.display ?? String(item.value), value: item.value }
|
|
831
|
+
])
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
function graphToTable(graph, context) {
|
|
835
|
+
const first = graph.series[0];
|
|
836
|
+
if (first === void 0)
|
|
837
|
+
return err(`${context.where}: the chart has no series.`);
|
|
838
|
+
const format = {
|
|
839
|
+
...graph.currency === void 0 ? {} : { currency: graph.currency },
|
|
840
|
+
...context.locale === void 0 ? {} : { locale: context.locale }
|
|
841
|
+
};
|
|
842
|
+
return ok({
|
|
843
|
+
kind: "TABLE",
|
|
844
|
+
columns: [
|
|
845
|
+
{ label: graph.xLabel ?? "Label" },
|
|
846
|
+
...graph.series.map((series) => ({ label: series.name, numeric: true }))
|
|
847
|
+
],
|
|
848
|
+
rows: first.points.map((point, index) => [
|
|
849
|
+
{ text: point.label },
|
|
850
|
+
...graph.series.map((series) => {
|
|
851
|
+
const value = series.points[index]?.value;
|
|
852
|
+
return value === void 0 ? { text: "\u2014" } : { text: formatValue(value, graph.valueFormat, format), value };
|
|
853
|
+
})
|
|
854
|
+
])
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
function barListToGraph(list, conversion) {
|
|
858
|
+
return ok({
|
|
859
|
+
kind: "GRAPH",
|
|
860
|
+
series: [
|
|
861
|
+
{
|
|
862
|
+
name: conversion.seriesName ?? "Value",
|
|
863
|
+
points: list.items.map((item) => ({
|
|
864
|
+
label: item.label,
|
|
865
|
+
value: item.value
|
|
866
|
+
}))
|
|
867
|
+
}
|
|
868
|
+
],
|
|
869
|
+
chartType: conversion.chartType,
|
|
870
|
+
valueFormat: conversion.valueFormat ?? "number",
|
|
871
|
+
...conversion.currency === void 0 ? {} : { currency: conversion.currency }
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
function convertView(widgetKey, view, data, options = {}) {
|
|
875
|
+
const conversion = view.convert;
|
|
876
|
+
const context = {
|
|
877
|
+
where: `Widget ${JSON.stringify(widgetKey)} view ${JSON.stringify(view.key)}`,
|
|
878
|
+
...options.locale === void 0 ? {} : { locale: options.locale }
|
|
879
|
+
};
|
|
880
|
+
const expected = VIEW_CONVERSIONS[conversion.type]?.from;
|
|
881
|
+
if (expected === void 0) {
|
|
882
|
+
return err(
|
|
883
|
+
`${context.where}: unknown conversion type ${JSON.stringify(conversion.type)}.`
|
|
884
|
+
);
|
|
885
|
+
}
|
|
886
|
+
if (data.kind !== expected) {
|
|
887
|
+
return err(
|
|
888
|
+
`${context.where}: ${conversion.type} reads a ${expected} payload, but the widget returned ${data.kind}.`
|
|
889
|
+
);
|
|
890
|
+
}
|
|
891
|
+
switch (conversion.type) {
|
|
892
|
+
case "tableToBarList":
|
|
893
|
+
return tableToBarList(data, conversion, context);
|
|
894
|
+
case "tableToGraph":
|
|
895
|
+
return tableToGraph(data, conversion, context);
|
|
896
|
+
case "barListToTable":
|
|
897
|
+
return barListToTable(data, conversion);
|
|
898
|
+
case "graphToTable":
|
|
899
|
+
return graphToTable(data, context);
|
|
900
|
+
case "barListToGraph":
|
|
901
|
+
return barListToGraph(data, conversion);
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
function viewNote(view, data) {
|
|
905
|
+
if (data?.kind !== "TABLE") return "";
|
|
906
|
+
const conversion = view.convert;
|
|
907
|
+
let indexes;
|
|
908
|
+
if (conversion.type === "tableToBarList") {
|
|
909
|
+
indexes = [conversion.label, conversion.value];
|
|
910
|
+
} else if (conversion.type === "tableToGraph") {
|
|
911
|
+
indexes = [conversion.label, ...conversion.values];
|
|
912
|
+
} else {
|
|
913
|
+
return "";
|
|
914
|
+
}
|
|
915
|
+
const names = indexes.map(
|
|
916
|
+
(index) => data.columns[index]?.label ?? `#${index + 1}`
|
|
917
|
+
);
|
|
918
|
+
return `Shows ${names.join(", ")} only.`;
|
|
919
|
+
}
|
|
920
|
+
function applyView(widget, chosen, options = {}) {
|
|
921
|
+
const key = effectiveViewKey(widget.definition, chosen);
|
|
922
|
+
const view = findView(widget.definition, key);
|
|
923
|
+
if (view === void 0) return widget;
|
|
924
|
+
const definition = {
|
|
925
|
+
...widget.definition,
|
|
926
|
+
kind: view.kind
|
|
927
|
+
};
|
|
928
|
+
if (widget.status === "loading") return { ...widget, definition };
|
|
929
|
+
if (widget.status === "empty") return { ...widget, definition };
|
|
930
|
+
if (widget.status === "error") return { ...widget, definition };
|
|
931
|
+
const converted = convertView(
|
|
932
|
+
widget.definition.key,
|
|
933
|
+
view,
|
|
934
|
+
widget.data,
|
|
935
|
+
options
|
|
936
|
+
);
|
|
937
|
+
if (!converted.ok) {
|
|
938
|
+
return {
|
|
939
|
+
definition,
|
|
940
|
+
status: "error",
|
|
941
|
+
error: converted.error,
|
|
942
|
+
...widget.options === void 0 ? {} : { options: widget.options }
|
|
943
|
+
};
|
|
944
|
+
}
|
|
945
|
+
return { ...widget, definition, data: converted.value };
|
|
946
|
+
}
|
|
947
|
+
|
|
691
948
|
// src/core/options.ts
|
|
692
949
|
var DATE_RANGE_PRESETS = [
|
|
693
950
|
"today",
|
|
@@ -993,6 +1250,7 @@ function parseOne(raw) {
|
|
|
993
1250
|
const width = raw["width"];
|
|
994
1251
|
const flexible = raw["flexible"];
|
|
995
1252
|
const options = raw["options"];
|
|
1253
|
+
const view = raw["view"];
|
|
996
1254
|
const cleanTitle = typeof title === "string" ? title.trim().slice(0, MAX_WIDGET_TITLE_LENGTH) : "";
|
|
997
1255
|
const chosen = {};
|
|
998
1256
|
if (isRecord(options)) {
|
|
@@ -1005,7 +1263,8 @@ function parseOne(raw) {
|
|
|
1005
1263
|
...cleanTitle === "" ? {} : { title: cleanTitle },
|
|
1006
1264
|
...isWidgetWidth(width) ? { width } : {},
|
|
1007
1265
|
...typeof flexible === "boolean" ? { flexible } : {},
|
|
1008
|
-
...Object.keys(chosen).length === 0 ? {} : { options: chosen }
|
|
1266
|
+
...Object.keys(chosen).length === 0 ? {} : { options: chosen },
|
|
1267
|
+
...typeof view === "string" && view !== "" && view.length <= 80 ? { view } : {}
|
|
1009
1268
|
};
|
|
1010
1269
|
return Object.keys(settings).length === 0 ? void 0 : settings;
|
|
1011
1270
|
}
|
|
@@ -1032,7 +1291,8 @@ function serializeSettings(settings) {
|
|
|
1032
1291
|
...one.title === void 0 ? {} : { title: one.title },
|
|
1033
1292
|
...one.width === void 0 ? {} : { width: one.width },
|
|
1034
1293
|
...one.flexible === void 0 ? {} : { flexible: one.flexible },
|
|
1035
|
-
...one.options === void 0 || Object.keys(one.options).length === 0 ? {} : { options: { ...one.options } }
|
|
1294
|
+
...one.options === void 0 || Object.keys(one.options).length === 0 ? {} : { options: { ...one.options } },
|
|
1295
|
+
...one.view === void 0 ? {} : { view: one.view }
|
|
1036
1296
|
};
|
|
1037
1297
|
if (Object.keys(piece).length > 0) out[key] = piece;
|
|
1038
1298
|
}
|
|
@@ -1124,12 +1384,18 @@ function optionValuesFromLayout(definitions, layout, options = {}) {
|
|
|
1124
1384
|
}
|
|
1125
1385
|
function sameSettings(a, b) {
|
|
1126
1386
|
if (a === b) return true;
|
|
1127
|
-
return a?.title === b?.title && a?.width === b?.width && a?.flexible === b?.flexible && sameOptionValues(a?.options ?? {}, b?.options ?? {});
|
|
1387
|
+
return a?.title === b?.title && a?.width === b?.width && a?.flexible === b?.flexible && a?.view === b?.view && sameOptionValues(a?.options ?? {}, b?.options ?? {});
|
|
1128
1388
|
}
|
|
1129
1389
|
function setWidgetSettings(layout, key, patch) {
|
|
1130
1390
|
const before = layout.settings?.[key];
|
|
1131
1391
|
const draft = { ...before };
|
|
1132
|
-
for (const field of [
|
|
1392
|
+
for (const field of [
|
|
1393
|
+
"title",
|
|
1394
|
+
"width",
|
|
1395
|
+
"flexible",
|
|
1396
|
+
"options",
|
|
1397
|
+
"view"
|
|
1398
|
+
]) {
|
|
1133
1399
|
if (!(field in patch)) continue;
|
|
1134
1400
|
const value = patch[field];
|
|
1135
1401
|
if (value === void 0) {
|
|
@@ -1155,7 +1421,8 @@ function clearWidgetSettings(layout, key) {
|
|
|
1155
1421
|
title: void 0,
|
|
1156
1422
|
width: void 0,
|
|
1157
1423
|
flexible: void 0,
|
|
1158
|
-
options: void 0
|
|
1424
|
+
options: void 0,
|
|
1425
|
+
view: void 0
|
|
1159
1426
|
});
|
|
1160
1427
|
}
|
|
1161
1428
|
function normalizeTitle(title) {
|
|
@@ -1215,7 +1482,8 @@ function normalizeSettings(definitions, layout, options = {}) {
|
|
|
1215
1482
|
...title === void 0 ? {} : { title },
|
|
1216
1483
|
...one.width === void 0 ? {} : { width: Math.min(range.max, Math.max(range.min, one.width)) },
|
|
1217
1484
|
...one.flexible === void 0 ? {} : { flexible: one.flexible },
|
|
1218
|
-
...Object.keys(chosen).length === 0 ? {} : { options: chosen }
|
|
1485
|
+
...Object.keys(chosen).length === 0 ? {} : { options: chosen },
|
|
1486
|
+
...one.view !== void 0 && (one.view === BASE_VIEW_KEY || findView(definition, one.view) !== void 0) ? { view: one.view } : {}
|
|
1219
1487
|
};
|
|
1220
1488
|
if (Object.keys(next).length > 0) {
|
|
1221
1489
|
cleaned[definition.key] = sameSettings(one, next) ? one : next;
|
|
@@ -2088,6 +2356,137 @@ function checkOptions(options, kind, problems) {
|
|
|
2088
2356
|
);
|
|
2089
2357
|
});
|
|
2090
2358
|
}
|
|
2359
|
+
var MAX_VIEW_COLUMN = 1e3;
|
|
2360
|
+
function checkColumnIndex(value, path, problems) {
|
|
2361
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < 0 || value > MAX_VIEW_COLUMN) {
|
|
2362
|
+
problems.push(
|
|
2363
|
+
`${path} must be a column index (a whole number from 0), got ${typeof value === "number" ? String(value) : describeType2(value)}.`
|
|
2364
|
+
);
|
|
2365
|
+
}
|
|
2366
|
+
}
|
|
2367
|
+
function checkConversion(conversion, path, baseKind, viewKind2, problems) {
|
|
2368
|
+
if (!isRecord2(conversion)) {
|
|
2369
|
+
problems.push(
|
|
2370
|
+
`${path} must be an object with a type, got ${describeType2(conversion)}.`
|
|
2371
|
+
);
|
|
2372
|
+
return;
|
|
2373
|
+
}
|
|
2374
|
+
const type = conversion["type"];
|
|
2375
|
+
const known = typeof type === "string" && Object.hasOwn(VIEW_CONVERSIONS, type) ? VIEW_CONVERSIONS[type] : void 0;
|
|
2376
|
+
if (known === void 0) {
|
|
2377
|
+
problems.push(
|
|
2378
|
+
`${path}.type must be one of ${Object.keys(VIEW_CONVERSIONS).map((name) => `"${name}"`).join(", ")}, got ${describeType2(type)}.`
|
|
2379
|
+
);
|
|
2380
|
+
return;
|
|
2381
|
+
}
|
|
2382
|
+
if (baseKind !== known.from) {
|
|
2383
|
+
problems.push(
|
|
2384
|
+
`${path}.type "${String(type)}" reads a ${known.from} widget, but this one is ${String(baseKind)}.`
|
|
2385
|
+
);
|
|
2386
|
+
}
|
|
2387
|
+
if (viewKind2 !== known.to) {
|
|
2388
|
+
problems.push(
|
|
2389
|
+
`${path}.type "${String(type)}" produces ${known.to}, but the view's kind is ${String(viewKind2)}.`
|
|
2390
|
+
);
|
|
2391
|
+
}
|
|
2392
|
+
switch (type) {
|
|
2393
|
+
case "tableToBarList":
|
|
2394
|
+
checkColumnIndex(conversion["label"], `${path}.label`, problems);
|
|
2395
|
+
checkColumnIndex(conversion["value"], `${path}.value`, problems);
|
|
2396
|
+
break;
|
|
2397
|
+
case "tableToGraph": {
|
|
2398
|
+
checkColumnIndex(conversion["label"], `${path}.label`, problems);
|
|
2399
|
+
const values = conversion["values"];
|
|
2400
|
+
if (!Array.isArray(values) || values.length === 0) {
|
|
2401
|
+
problems.push(`${path}.values must list 1 or more column indexes.`);
|
|
2402
|
+
} else if (values.length > MAX_GRAPH_SERIES) {
|
|
2403
|
+
problems.push(
|
|
2404
|
+
`${path}.values lists ${values.length} series; a chart carries at most ${MAX_GRAPH_SERIES}.`
|
|
2405
|
+
);
|
|
2406
|
+
} else {
|
|
2407
|
+
values.forEach(
|
|
2408
|
+
(index, at) => checkColumnIndex(index, `${path}.values[${at}]`, problems)
|
|
2409
|
+
);
|
|
2410
|
+
}
|
|
2411
|
+
if (conversion["chartType"] !== "bar" && conversion["chartType"] !== "line") {
|
|
2412
|
+
problems.push(`${path}.chartType must be "bar" or "line".`);
|
|
2413
|
+
}
|
|
2414
|
+
break;
|
|
2415
|
+
}
|
|
2416
|
+
case "barListToGraph":
|
|
2417
|
+
if (conversion["chartType"] !== "bar" && conversion["chartType"] !== "line") {
|
|
2418
|
+
problems.push(`${path}.chartType must be "bar" or "line".`);
|
|
2419
|
+
}
|
|
2420
|
+
break;
|
|
2421
|
+
}
|
|
2422
|
+
if (conversion["valueFormat"] !== void 0 && !VALUE_FORMATS.includes(conversion["valueFormat"])) {
|
|
2423
|
+
problems.push(
|
|
2424
|
+
`${path}.valueFormat must be one of ${VALUE_FORMATS.map((f) => `"${f}"`).join(", ")}.`
|
|
2425
|
+
);
|
|
2426
|
+
}
|
|
2427
|
+
}
|
|
2428
|
+
function checkViews(value, problems) {
|
|
2429
|
+
const views = value["views"];
|
|
2430
|
+
const defaultView = value["defaultView"];
|
|
2431
|
+
optionalString(value, "baseViewLabel", "", problems);
|
|
2432
|
+
if (value["baseViewLabel"] === "") {
|
|
2433
|
+
problems.push("baseViewLabel must not be empty.");
|
|
2434
|
+
}
|
|
2435
|
+
const declared = /* @__PURE__ */ new Set([BASE_VIEW_KEY]);
|
|
2436
|
+
if (views !== void 0) {
|
|
2437
|
+
if (!Array.isArray(views)) {
|
|
2438
|
+
problems.push(`views must be an array, got ${describeType2(views)}.`);
|
|
2439
|
+
} else if (views.length > MAX_WIDGET_VIEWS) {
|
|
2440
|
+
problems.push(
|
|
2441
|
+
`views lists ${views.length} views; the most a widget may declare is ${MAX_WIDGET_VIEWS}.`
|
|
2442
|
+
);
|
|
2443
|
+
} else {
|
|
2444
|
+
views.forEach((view, index) => {
|
|
2445
|
+
const path = `views[${index}]`;
|
|
2446
|
+
if (!isRecord2(view)) {
|
|
2447
|
+
problems.push(
|
|
2448
|
+
`${path} must be an object, got ${describeType2(view)}.`
|
|
2449
|
+
);
|
|
2450
|
+
return;
|
|
2451
|
+
}
|
|
2452
|
+
const key = view["key"];
|
|
2453
|
+
if (typeof key !== "string" || key.trim() === "") {
|
|
2454
|
+
problems.push(`${path}.key must be a non-empty string.`);
|
|
2455
|
+
} else if (declared.has(key)) {
|
|
2456
|
+
problems.push(
|
|
2457
|
+
key === BASE_VIEW_KEY ? `${path}.key "${BASE_VIEW_KEY}" is reserved for the widget's own kind.` : `${path}.key "${key}" is used twice.`
|
|
2458
|
+
);
|
|
2459
|
+
} else {
|
|
2460
|
+
declared.add(key);
|
|
2461
|
+
}
|
|
2462
|
+
if (typeof view["label"] !== "string" || view["label"].trim() === "") {
|
|
2463
|
+
problems.push(`${path}.label must be a non-empty string.`);
|
|
2464
|
+
}
|
|
2465
|
+
requireOneOf(view, "kind", WIDGET_KINDS, path, problems);
|
|
2466
|
+
if (view["convert"] === void 0) {
|
|
2467
|
+
problems.push(
|
|
2468
|
+
`${path}.convert is required: views supplied by a provider are not supported yet.`
|
|
2469
|
+
);
|
|
2470
|
+
} else {
|
|
2471
|
+
checkConversion(
|
|
2472
|
+
view["convert"],
|
|
2473
|
+
`${path}.convert`,
|
|
2474
|
+
value["kind"],
|
|
2475
|
+
view["kind"],
|
|
2476
|
+
problems
|
|
2477
|
+
);
|
|
2478
|
+
}
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2481
|
+
}
|
|
2482
|
+
if (defaultView !== void 0) {
|
|
2483
|
+
if (typeof defaultView !== "string" || !declared.has(defaultView)) {
|
|
2484
|
+
problems.push(
|
|
2485
|
+
`defaultView must be "${BASE_VIEW_KEY}" or the key of a declared view, got ${typeof defaultView === "string" ? JSON.stringify(defaultView) : describeType2(defaultView)}.`
|
|
2486
|
+
);
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2489
|
+
}
|
|
2091
2490
|
function formatProblems(prefix, problems) {
|
|
2092
2491
|
const shown = problems.slice(0, MAX_REPORTED_PROBLEMS);
|
|
2093
2492
|
const more = problems.length - shown.length;
|
|
@@ -2164,6 +2563,7 @@ function validateWidgetDefinition(value) {
|
|
|
2164
2563
|
checkTableControlsOption(value["tableControls"], value["kind"], problems);
|
|
2165
2564
|
checkLockedOption(value["locked"], problems);
|
|
2166
2565
|
checkOptions(value["options"], value["kind"], problems);
|
|
2566
|
+
checkViews(value, problems);
|
|
2167
2567
|
if (value["page"] !== void 0) {
|
|
2168
2568
|
if (typeof value["page"] !== "string" || value["page"].trim() === "") {
|
|
2169
2569
|
problems.push(
|
|
@@ -3798,6 +4198,7 @@ function indent(block) {
|
|
|
3798
4198
|
return block.split("\n").map((line) => ` ${line}`).join("\n");
|
|
3799
4199
|
}
|
|
3800
4200
|
|
|
4201
|
+
exports.BASE_VIEW_KEY = BASE_VIEW_KEY;
|
|
3801
4202
|
exports.DATE_RANGE_PRESETS = DATE_RANGE_PRESETS;
|
|
3802
4203
|
exports.DEFAULT_COMPARISON_LABEL = DEFAULT_COMPARISON_LABEL;
|
|
3803
4204
|
exports.DEFAULT_CURRENCY = DEFAULT_CURRENCY;
|
|
@@ -3819,11 +4220,13 @@ exports.MAX_REPORTED_PROBLEMS = MAX_REPORTED_PROBLEMS;
|
|
|
3819
4220
|
exports.MAX_TEXT_OPTION_LENGTH = MAX_TEXT_OPTION_LENGTH;
|
|
3820
4221
|
exports.MAX_WIDGET_OPTIONS = MAX_WIDGET_OPTIONS;
|
|
3821
4222
|
exports.MAX_WIDGET_TITLE_LENGTH = MAX_WIDGET_TITLE_LENGTH;
|
|
4223
|
+
exports.MAX_WIDGET_VIEWS = MAX_WIDGET_VIEWS;
|
|
3822
4224
|
exports.MAX_WIDGET_WIDTH = MAX_WIDGET_WIDTH;
|
|
3823
4225
|
exports.MIN_WIDGET_WIDTH = MIN_WIDGET_WIDTH;
|
|
3824
4226
|
exports.OPTION_KEY_PATTERN = OPTION_KEY_PATTERN;
|
|
3825
4227
|
exports.THEME_TOKEN_VARIABLES = THEME_TOKEN_VARIABLES;
|
|
3826
4228
|
exports.VALUE_FORMATS = VALUE_FORMATS;
|
|
4229
|
+
exports.VIEW_CONVERSIONS = VIEW_CONVERSIONS;
|
|
3827
4230
|
exports.WIDGET_FILLS = WIDGET_FILLS;
|
|
3828
4231
|
exports.WIDGET_KINDS = WIDGET_KINDS;
|
|
3829
4232
|
exports.WIDGET_OPTION_TYPES = WIDGET_OPTION_TYPES;
|
|
@@ -3832,11 +4235,13 @@ exports.WIDTH_COLUMNS = WIDTH_COLUMNS;
|
|
|
3832
4235
|
exports.addPage = addPage;
|
|
3833
4236
|
exports.applyClientOptions = applyClientOptions;
|
|
3834
4237
|
exports.applySettings = applySettings;
|
|
4238
|
+
exports.applyView = applyView;
|
|
3835
4239
|
exports.assignPages = assignPages;
|
|
3836
4240
|
exports.baseColumnSpan = baseColumnSpan;
|
|
3837
4241
|
exports.cacheKeyFor = cacheKeyFor;
|
|
3838
4242
|
exports.clearWidgetSettings = clearWidgetSettings;
|
|
3839
4243
|
exports.coerceOptionValue = coerceOptionValue;
|
|
4244
|
+
exports.convertView = convertView;
|
|
3840
4245
|
exports.createLayoutPersistence = createLayoutPersistence;
|
|
3841
4246
|
exports.createTheme = createTheme;
|
|
3842
4247
|
exports.createWidgetLoader = createWidgetLoader;
|
|
@@ -3846,6 +4251,7 @@ exports.defineWidget = defineWidget;
|
|
|
3846
4251
|
exports.deriveDetailData = deriveDetailData;
|
|
3847
4252
|
exports.describeUnknownError = describeUnknownError;
|
|
3848
4253
|
exports.effectiveDefinitions = effectiveDefinitions;
|
|
4254
|
+
exports.effectiveViewKey = effectiveViewKey;
|
|
3849
4255
|
exports.emptyTextFor = emptyTextFor;
|
|
3850
4256
|
exports.emptyWidget = emptyWidget;
|
|
3851
4257
|
exports.enforceLocks = enforceLocks;
|
|
@@ -3856,12 +4262,14 @@ exports.fillWidthSpans = fillWidthSpans;
|
|
|
3856
4262
|
exports.fillsHeight = fillsHeight;
|
|
3857
4263
|
exports.fillsWidth = fillsWidth;
|
|
3858
4264
|
exports.finalizeWidget = finalizeWidget;
|
|
4265
|
+
exports.findView = findView;
|
|
3859
4266
|
exports.fitCount = fitCount;
|
|
3860
4267
|
exports.formatCount = formatCount;
|
|
3861
4268
|
exports.formatPercentChange = formatPercentChange;
|
|
3862
4269
|
exports.formatValue = formatValue;
|
|
3863
4270
|
exports.fromLegacyDefinition = fromLegacyDefinition;
|
|
3864
4271
|
exports.hasPages = hasPages;
|
|
4272
|
+
exports.hasViews = hasViews;
|
|
3865
4273
|
exports.hiddenWidgets = hiddenWidgets;
|
|
3866
4274
|
exports.hideWidget = hideWidget;
|
|
3867
4275
|
exports.isClientApplied = isClientApplied;
|
|
@@ -3879,6 +4287,7 @@ exports.isWidgetKind = isWidgetKind;
|
|
|
3879
4287
|
exports.isWidgetVisibleTo = isWidgetVisibleTo;
|
|
3880
4288
|
exports.isWidgetWidth = isWidgetWidth;
|
|
3881
4289
|
exports.itemWidth = itemWidth;
|
|
4290
|
+
exports.kindLabel = kindLabel;
|
|
3882
4291
|
exports.kpiDelta = kpiDelta;
|
|
3883
4292
|
exports.labelStride = labelStride;
|
|
3884
4293
|
exports.loadingWidgets = loadingWidgets;
|
|
@@ -3945,6 +4354,9 @@ exports.utf8Length = utf8Length;
|
|
|
3945
4354
|
exports.validateDetailData = validateDetailData;
|
|
3946
4355
|
exports.validateWidgetData = validateWidgetData;
|
|
3947
4356
|
exports.validateWidgetDefinition = validateWidgetDefinition;
|
|
4357
|
+
exports.viewChoices = viewChoices;
|
|
4358
|
+
exports.viewKind = viewKind;
|
|
4359
|
+
exports.viewNote = viewNote;
|
|
3948
4360
|
exports.visibleWidgets = visibleWidgets;
|
|
3949
4361
|
exports.widgetOptionValues = widgetOptionValues;
|
|
3950
4362
|
exports.widgetsFor = widgetsFor;
|