@richardmcquiston01/dashboard-widgets-toolkit 0.13.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 +1089 -347
- 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 +1061 -348
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +1089 -347
- 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 +1061 -348
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +1173 -121
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +57 -4
- package/dist/react.d.ts +57 -4
- package/dist/react.js +1173 -122
- package/dist/react.js.map +1 -1
- package/dist/{storage-DNB7gjvT.d.cts → storage-DwJ-vGJg.d.cts} +264 -3
- package/dist/{storage-DNB7gjvT.d.ts → storage-DwJ-vGJg.d.ts} +264 -3
- package/dist/styles.css +146 -0
- package/package.json +1 -1
package/dist/core.cjs
CHANGED
|
@@ -89,12 +89,14 @@ var WIDGET_FILLS = ["height", "width", "both"];
|
|
|
89
89
|
var NOT_LOCKED = Object.freeze({
|
|
90
90
|
move: false,
|
|
91
91
|
hide: false,
|
|
92
|
-
minimize: false
|
|
92
|
+
minimize: false,
|
|
93
|
+
options: false
|
|
93
94
|
});
|
|
94
95
|
var FULLY_LOCKED = Object.freeze({
|
|
95
96
|
move: true,
|
|
96
97
|
hide: true,
|
|
97
|
-
minimize: true
|
|
98
|
+
minimize: true,
|
|
99
|
+
options: true
|
|
98
100
|
});
|
|
99
101
|
function resolveWidgetLock(definition) {
|
|
100
102
|
const setting = definition.locked;
|
|
@@ -103,7 +105,8 @@ function resolveWidgetLock(definition) {
|
|
|
103
105
|
return {
|
|
104
106
|
move: setting.move === true,
|
|
105
107
|
hide: setting.hide === true,
|
|
106
|
-
minimize: setting.minimize === true
|
|
108
|
+
minimize: setting.minimize === true,
|
|
109
|
+
options: setting.options === true
|
|
107
110
|
};
|
|
108
111
|
}
|
|
109
112
|
function defineWidget(definition) {
|
|
@@ -685,261 +688,261 @@ function placeAndFillRows(items, columns, spanOf) {
|
|
|
685
688
|
return { spans, rows };
|
|
686
689
|
}
|
|
687
690
|
|
|
688
|
-
// src/core/
|
|
689
|
-
var
|
|
690
|
-
var
|
|
691
|
-
var
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
value = JSON.parse(raw);
|
|
710
|
-
} catch {
|
|
711
|
-
return EMPTY_LAYOUT;
|
|
712
|
-
}
|
|
713
|
-
}
|
|
714
|
-
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
715
|
-
return EMPTY_LAYOUT;
|
|
716
|
-
}
|
|
717
|
-
const record = value;
|
|
718
|
-
const order = uniqueStrings(record["order"]);
|
|
719
|
-
const hidden = uniqueStrings(record["hidden"]);
|
|
720
|
-
const minimized = uniqueStrings(record["minimized"]);
|
|
721
|
-
const pages = parsePages(record["pages"]);
|
|
722
|
-
if (pages.length > 0) {
|
|
723
|
-
return {
|
|
724
|
-
order: EMPTY_LAYOUT.order,
|
|
725
|
-
hidden: EMPTY_LAYOUT.hidden,
|
|
726
|
-
minimized: EMPTY_LAYOUT.minimized,
|
|
727
|
-
pages
|
|
728
|
-
};
|
|
729
|
-
}
|
|
730
|
-
if (order.length === 0 && hidden.length === 0 && minimized.length === 0) {
|
|
731
|
-
return EMPTY_LAYOUT;
|
|
732
|
-
}
|
|
733
|
-
return { order, hidden, minimized };
|
|
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];
|
|
734
712
|
}
|
|
735
|
-
function
|
|
736
|
-
|
|
737
|
-
const pages = [];
|
|
738
|
-
const keys = /* @__PURE__ */ new Set();
|
|
739
|
-
for (const entry of value.slice(0, MAX_PARSED_PAGES)) {
|
|
740
|
-
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
741
|
-
continue;
|
|
742
|
-
}
|
|
743
|
-
const record = entry;
|
|
744
|
-
const key = record["key"];
|
|
745
|
-
if (typeof key !== "string" || key === "" || keys.has(key)) continue;
|
|
746
|
-
keys.add(key);
|
|
747
|
-
const rawTitle = record["title"];
|
|
748
|
-
const title = typeof rawTitle === "string" && rawTitle.trim() !== "" ? rawTitle.trim().slice(0, MAX_PAGE_TITLE_LENGTH) : `Page ${pages.length + 1}`;
|
|
749
|
-
const maxRows = record["maxRows"];
|
|
750
|
-
const held = /* @__PURE__ */ new Set();
|
|
751
|
-
for (const earlier of pages) {
|
|
752
|
-
for (const k of [...earlier.order, ...earlier.hidden]) held.add(k);
|
|
753
|
-
}
|
|
754
|
-
const keep = (list) => uniqueStrings(list).filter((k) => !held.has(k));
|
|
755
|
-
pages.push({
|
|
756
|
-
key,
|
|
757
|
-
title,
|
|
758
|
-
order: keep(record["order"]),
|
|
759
|
-
hidden: keep(record["hidden"]),
|
|
760
|
-
minimized: keep(record["minimized"]),
|
|
761
|
-
...typeof maxRows === "number" && Number.isInteger(maxRows) && maxRows >= 1 && maxRows <= MAX_PAGE_ROWS ? { maxRows } : {}
|
|
762
|
-
});
|
|
763
|
-
}
|
|
764
|
-
return pages;
|
|
713
|
+
function hasViews(item) {
|
|
714
|
+
return item.views !== void 0 && item.views.length > 0;
|
|
765
715
|
}
|
|
766
|
-
function
|
|
767
|
-
return
|
|
768
|
-
order: [...layout.order],
|
|
769
|
-
hidden: [...layout.hidden],
|
|
770
|
-
minimized: [...layout.minimized],
|
|
771
|
-
...layout.pages === void 0 || layout.pages.length === 0 ? {} : {
|
|
772
|
-
pages: layout.pages.map((page) => ({
|
|
773
|
-
key: page.key,
|
|
774
|
-
title: page.title,
|
|
775
|
-
order: [...page.order],
|
|
776
|
-
hidden: [...page.hidden],
|
|
777
|
-
minimized: [...page.minimized],
|
|
778
|
-
...page.maxRows === void 0 ? {} : { maxRows: page.maxRows }
|
|
779
|
-
}))
|
|
780
|
-
}
|
|
781
|
-
});
|
|
716
|
+
function findView(item, key) {
|
|
717
|
+
return item.views?.find((view) => view.key === key);
|
|
782
718
|
}
|
|
783
|
-
function
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
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
|
+
];
|
|
787
733
|
}
|
|
788
|
-
function
|
|
789
|
-
return
|
|
734
|
+
function isKnownView(item, key) {
|
|
735
|
+
return key !== void 0 && (key === BASE_VIEW_KEY || findView(item, key) !== void 0);
|
|
790
736
|
}
|
|
791
|
-
function
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
if (definition !== void 0) {
|
|
797
|
-
ordered.push(definition);
|
|
798
|
-
byKey.delete(key);
|
|
799
|
-
}
|
|
800
|
-
}
|
|
801
|
-
for (const definition of bySortOrder(visible)) {
|
|
802
|
-
if (byKey.has(definition.key)) ordered.push(definition);
|
|
803
|
-
}
|
|
804
|
-
return ordered;
|
|
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;
|
|
805
742
|
}
|
|
806
|
-
function
|
|
807
|
-
|
|
808
|
-
(item) => isPinned(item) ? item : void 0
|
|
809
|
-
);
|
|
810
|
-
let next = 0;
|
|
811
|
-
return slots.map((pinned) => pinned ?? free[next++]);
|
|
743
|
+
function viewKind(item, chosen) {
|
|
744
|
+
return findView(item, effectiveViewKey(item, chosen))?.kind ?? item.kind;
|
|
812
745
|
}
|
|
813
|
-
function
|
|
814
|
-
const
|
|
815
|
-
|
|
816
|
-
const ordered = viewerOrder(visible, layout);
|
|
817
|
-
if (!visible.some(isPinned)) return ordered;
|
|
818
|
-
return placeAroundPinned(
|
|
819
|
-
visible,
|
|
820
|
-
ordered.filter((item) => !isPinned(item))
|
|
821
|
-
);
|
|
746
|
+
function cellValue2(cell) {
|
|
747
|
+
const value = cell?.value;
|
|
748
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
822
749
|
}
|
|
823
|
-
function
|
|
824
|
-
|
|
825
|
-
return bySortOrder(definitions.filter((d) => hidden.has(d.key)));
|
|
750
|
+
function columnName(table, index) {
|
|
751
|
+
return table.columns[index]?.label ?? `#${index + 1}`;
|
|
826
752
|
}
|
|
827
|
-
function
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
const mover = current[fromIndex];
|
|
831
|
-
if (mover === void 0 || !Number.isInteger(toIndex) || toIndex < 0 || toIndex >= current.length || toIndex === fromIndex || isPinned(mover) || isPinned(current[toIndex])) {
|
|
832
|
-
return layout;
|
|
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).`;
|
|
833
756
|
}
|
|
834
|
-
|
|
835
|
-
const free = current.filter((item) => !isPinned(item));
|
|
836
|
-
const fromFree = freeSlots.indexOf(fromIndex);
|
|
837
|
-
const toFree = freeSlots.indexOf(toIndex);
|
|
838
|
-
free.splice(fromFree, 1);
|
|
839
|
-
free.splice(toFree, 0, mover);
|
|
840
|
-
const next = placeAroundPinned(current, free);
|
|
841
|
-
return { ...layout, order: next.map((d) => d.key) };
|
|
757
|
+
return void 0;
|
|
842
758
|
}
|
|
843
|
-
function
|
|
844
|
-
const
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
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 });
|
|
849
783
|
}
|
|
850
|
-
function
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
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
|
|
860
795
|
);
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
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
|
+
});
|
|
874
820
|
}
|
|
875
|
-
function
|
|
876
|
-
|
|
877
|
-
|
|
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
|
+
});
|
|
878
833
|
}
|
|
879
|
-
function
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
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 }
|
|
885
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
|
+
});
|
|
886
856
|
}
|
|
887
|
-
function
|
|
888
|
-
return
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
}
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
const known = new Set(definitions.map((d) => d.key));
|
|
903
|
-
const keep = (keys) => keys.every((k) => known.has(k)) ? keys : keys.filter((k) => known.has(k));
|
|
904
|
-
return mapLayoutLists(layout, (lists) => ({
|
|
905
|
-
order: keep(lists.order),
|
|
906
|
-
hidden: keep(lists.hidden),
|
|
907
|
-
minimized: keep(lists.minimized)
|
|
908
|
-
}));
|
|
909
|
-
}
|
|
910
|
-
function mapLayoutLists(layout, change) {
|
|
911
|
-
const top = change(layout);
|
|
912
|
-
const pages = layout.pages?.map((page) => {
|
|
913
|
-
const next = change(page);
|
|
914
|
-
return next.order === page.order && next.hidden === page.hidden && next.minimized === page.minimized ? page : { ...page, ...next };
|
|
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 }
|
|
915
872
|
});
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
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
|
+
);
|
|
919
885
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
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
|
|
924
927
|
};
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
if (
|
|
928
|
-
const
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
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
|
+
};
|
|
936
944
|
}
|
|
937
|
-
|
|
938
|
-
return mapLayoutLists(layout, (lists) => ({
|
|
939
|
-
order: without2(lists.order, noMove),
|
|
940
|
-
hidden: without2(lists.hidden, noHide),
|
|
941
|
-
minimized: without2(lists.minimized, noMinimize)
|
|
942
|
-
}));
|
|
945
|
+
return { ...widget, definition, data: converted.value };
|
|
943
946
|
}
|
|
944
947
|
|
|
945
948
|
// src/core/options.ts
|
|
@@ -1116,107 +1119,644 @@ function coerceOptionValue(option, value, context = {}) {
|
|
|
1116
1119
|
}
|
|
1117
1120
|
}
|
|
1118
1121
|
}
|
|
1119
|
-
function defaultOptionValue(option, context = {}) {
|
|
1120
|
-
switch (option.type) {
|
|
1121
|
-
case "dateRange":
|
|
1122
|
-
return resolveDateRange(option.default, context);
|
|
1123
|
-
case "sort":
|
|
1124
|
-
return option.default;
|
|
1125
|
-
case "columns":
|
|
1126
|
-
return [...option.default];
|
|
1127
|
-
default:
|
|
1128
|
-
return option.default;
|
|
1129
|
-
}
|
|
1122
|
+
function defaultOptionValue(option, context = {}) {
|
|
1123
|
+
switch (option.type) {
|
|
1124
|
+
case "dateRange":
|
|
1125
|
+
return resolveDateRange(option.default, context);
|
|
1126
|
+
case "sort":
|
|
1127
|
+
return option.default;
|
|
1128
|
+
case "columns":
|
|
1129
|
+
return [...option.default];
|
|
1130
|
+
default:
|
|
1131
|
+
return option.default;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
var NO_VALUES = Object.freeze({});
|
|
1135
|
+
function resolveOptionValues(definition, chosen, context = {}) {
|
|
1136
|
+
const options = definition.options;
|
|
1137
|
+
if (options === void 0 || options.length === 0) return NO_VALUES;
|
|
1138
|
+
const values = {};
|
|
1139
|
+
for (const option of options) {
|
|
1140
|
+
const picked = chosen?.[option.key];
|
|
1141
|
+
const value = (picked === void 0 ? void 0 : coerceOptionValue(option, picked, context)) ?? defaultOptionValue(option, context);
|
|
1142
|
+
if (value !== void 0) values[option.key] = value;
|
|
1143
|
+
}
|
|
1144
|
+
return values;
|
|
1145
|
+
}
|
|
1146
|
+
function sameValue(a, b) {
|
|
1147
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
1148
|
+
return a.length === b.length && a.every((item, i) => item === b[i]);
|
|
1149
|
+
}
|
|
1150
|
+
return a === b;
|
|
1151
|
+
}
|
|
1152
|
+
function sameOptionValues(a, b) {
|
|
1153
|
+
const keys = Object.keys({ ...a, ...b });
|
|
1154
|
+
return keys.every((key) => sameValue(a[key], b[key]));
|
|
1155
|
+
}
|
|
1156
|
+
function optionsCacheSuffix(definition, values, context = {}) {
|
|
1157
|
+
const parts = [];
|
|
1158
|
+
for (const option of definition.options ?? []) {
|
|
1159
|
+
if (isClientApplied(option)) continue;
|
|
1160
|
+
const value = values[option.key];
|
|
1161
|
+
if (sameValue(value, defaultOptionValue(option, context))) continue;
|
|
1162
|
+
parts.push(
|
|
1163
|
+
`${option.key}=${encodeURIComponent(JSON.stringify(value ?? null))}`
|
|
1164
|
+
);
|
|
1165
|
+
}
|
|
1166
|
+
parts.sort();
|
|
1167
|
+
return parts.length === 0 ? "" : `?${parts.join("&")}`;
|
|
1168
|
+
}
|
|
1169
|
+
function tableColumnIndex(key) {
|
|
1170
|
+
const match = /^c(\d+)$/.exec(key);
|
|
1171
|
+
return match === null ? void 0 : Number(match[1]);
|
|
1172
|
+
}
|
|
1173
|
+
function sortBarItems(items, sort) {
|
|
1174
|
+
const sign = sort.direction === "desc" ? -1 : 1;
|
|
1175
|
+
return items.map((item, index) => ({ item, index })).sort((a, b) => {
|
|
1176
|
+
const order = sort.column === "value" ? a.item.value - b.item.value : a.item.label.localeCompare(b.item.label);
|
|
1177
|
+
return order * sign || a.index - b.index;
|
|
1178
|
+
}).map(({ item }) => item);
|
|
1179
|
+
}
|
|
1180
|
+
function applyClientOptions(definition, data, values) {
|
|
1181
|
+
const options = definition.options ?? [];
|
|
1182
|
+
const sortOption = options.find(
|
|
1183
|
+
(o) => o.type === "sort" && o.apply === "client"
|
|
1184
|
+
);
|
|
1185
|
+
const columnsOption = options.find(
|
|
1186
|
+
(o) => o.type === "columns" && o.apply === "client"
|
|
1187
|
+
);
|
|
1188
|
+
const sortValue = sortOption === void 0 ? void 0 : values[sortOption.key];
|
|
1189
|
+
const columnsValue = columnsOption === void 0 ? void 0 : values[columnsOption.key];
|
|
1190
|
+
let next = data;
|
|
1191
|
+
if (typeof sortValue === "string") {
|
|
1192
|
+
const sort = parseSortValue(sortValue);
|
|
1193
|
+
if (sort !== void 0 && next.kind === "BAR_LIST") {
|
|
1194
|
+
if (sort.column === "label" || sort.column === "value") {
|
|
1195
|
+
next = { ...next, items: sortBarItems(next.items, sort) };
|
|
1196
|
+
}
|
|
1197
|
+
} else if (sort !== void 0 && next.kind === "TABLE") {
|
|
1198
|
+
const index = tableColumnIndex(sort.column);
|
|
1199
|
+
if (index !== void 0 && index < next.columns.length) {
|
|
1200
|
+
const sorted = queryRows(tableDetailData(next), {
|
|
1201
|
+
page: 1,
|
|
1202
|
+
pageSize: Math.max(1, next.rows.length),
|
|
1203
|
+
sort
|
|
1204
|
+
});
|
|
1205
|
+
if (sorted.ok) next = { ...next, rows: sorted.value.rows };
|
|
1206
|
+
}
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
if (Array.isArray(columnsValue) && next.kind === "TABLE") {
|
|
1210
|
+
const table = next;
|
|
1211
|
+
const indexes = columnsValue.map(tableColumnIndex).filter(
|
|
1212
|
+
(index) => index !== void 0 && index < table.columns.length
|
|
1213
|
+
);
|
|
1214
|
+
if (indexes.length > 0) {
|
|
1215
|
+
next = {
|
|
1216
|
+
...table,
|
|
1217
|
+
columns: indexes.map((i) => table.columns[i]),
|
|
1218
|
+
rows: table.rows.map((row) => indexes.map((i) => row[i]))
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
return next;
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
// src/core/settings.ts
|
|
1226
|
+
var MAX_WIDGET_TITLE_LENGTH = 80;
|
|
1227
|
+
var MAX_PARSED_SETTINGS = 500;
|
|
1228
|
+
var MAX_COLUMN_LIST = 100;
|
|
1229
|
+
var MAX_VALUE_LENGTH = 500;
|
|
1230
|
+
function isRecord(value) {
|
|
1231
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1232
|
+
}
|
|
1233
|
+
function parseOptionValue(value) {
|
|
1234
|
+
if (typeof value === "string") {
|
|
1235
|
+
return value.length <= MAX_VALUE_LENGTH ? value : void 0;
|
|
1236
|
+
}
|
|
1237
|
+
if (typeof value === "number")
|
|
1238
|
+
return Number.isFinite(value) ? value : void 0;
|
|
1239
|
+
if (typeof value === "boolean") return value;
|
|
1240
|
+
if (Array.isArray(value) && value.length <= MAX_COLUMN_LIST) {
|
|
1241
|
+
return value.every(
|
|
1242
|
+
(entry) => typeof entry === "string" && entry.length <= MAX_VALUE_LENGTH
|
|
1243
|
+
) ? value : void 0;
|
|
1244
|
+
}
|
|
1245
|
+
return void 0;
|
|
1246
|
+
}
|
|
1247
|
+
function parseOne(raw) {
|
|
1248
|
+
if (!isRecord(raw)) return void 0;
|
|
1249
|
+
const title = raw["title"];
|
|
1250
|
+
const width = raw["width"];
|
|
1251
|
+
const flexible = raw["flexible"];
|
|
1252
|
+
const options = raw["options"];
|
|
1253
|
+
const view = raw["view"];
|
|
1254
|
+
const cleanTitle = typeof title === "string" ? title.trim().slice(0, MAX_WIDGET_TITLE_LENGTH) : "";
|
|
1255
|
+
const chosen = {};
|
|
1256
|
+
if (isRecord(options)) {
|
|
1257
|
+
for (const [key, value] of Object.entries(options)) {
|
|
1258
|
+
const parsed = parseOptionValue(value);
|
|
1259
|
+
if (parsed !== void 0) chosen[key] = parsed;
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
const settings = {
|
|
1263
|
+
...cleanTitle === "" ? {} : { title: cleanTitle },
|
|
1264
|
+
...isWidgetWidth(width) ? { width } : {},
|
|
1265
|
+
...typeof flexible === "boolean" ? { flexible } : {},
|
|
1266
|
+
...Object.keys(chosen).length === 0 ? {} : { options: chosen },
|
|
1267
|
+
...typeof view === "string" && view !== "" && view.length <= 80 ? { view } : {}
|
|
1268
|
+
};
|
|
1269
|
+
return Object.keys(settings).length === 0 ? void 0 : settings;
|
|
1270
|
+
}
|
|
1271
|
+
function parseSettings(raw) {
|
|
1272
|
+
if (!isRecord(raw)) return void 0;
|
|
1273
|
+
const parsed = {};
|
|
1274
|
+
for (const [key, value] of Object.entries(raw).slice(
|
|
1275
|
+
0,
|
|
1276
|
+
MAX_PARSED_SETTINGS
|
|
1277
|
+
)) {
|
|
1278
|
+
if (key === "") continue;
|
|
1279
|
+
const one = parseOne(value);
|
|
1280
|
+
if (one !== void 0) parsed[key] = one;
|
|
1281
|
+
}
|
|
1282
|
+
return Object.keys(parsed).length === 0 ? void 0 : parsed;
|
|
1283
|
+
}
|
|
1284
|
+
function serializeSettings(settings) {
|
|
1285
|
+
if (settings === void 0) return void 0;
|
|
1286
|
+
const out = {};
|
|
1287
|
+
for (const key of Object.keys(settings)) {
|
|
1288
|
+
const one = settings[key];
|
|
1289
|
+
if (one === void 0) continue;
|
|
1290
|
+
const piece = {
|
|
1291
|
+
...one.title === void 0 ? {} : { title: one.title },
|
|
1292
|
+
...one.width === void 0 ? {} : { width: one.width },
|
|
1293
|
+
...one.flexible === void 0 ? {} : { flexible: one.flexible },
|
|
1294
|
+
...one.options === void 0 || Object.keys(one.options).length === 0 ? {} : { options: { ...one.options } },
|
|
1295
|
+
...one.view === void 0 ? {} : { view: one.view }
|
|
1296
|
+
};
|
|
1297
|
+
if (Object.keys(piece).length > 0) out[key] = piece;
|
|
1298
|
+
}
|
|
1299
|
+
return Object.keys(out).length === 0 ? void 0 : out;
|
|
1300
|
+
}
|
|
1301
|
+
function widthRange(item) {
|
|
1302
|
+
const min = isWidgetWidth(item.minWidth) ? item.minWidth : MIN_WIDGET_WIDTH;
|
|
1303
|
+
const max = isWidgetWidth(item.maxWidth) ? item.maxWidth : MAX_WIDGET_WIDTH;
|
|
1304
|
+
return { min, max: Math.max(min, max) };
|
|
1305
|
+
}
|
|
1306
|
+
var WIDTH_SHARES = {
|
|
1307
|
+
2: "1/6",
|
|
1308
|
+
3: "1/4",
|
|
1309
|
+
4: "1/3",
|
|
1310
|
+
5: "5/12",
|
|
1311
|
+
6: "1/2",
|
|
1312
|
+
7: "7/12",
|
|
1313
|
+
8: "2/3",
|
|
1314
|
+
9: "3/4",
|
|
1315
|
+
10: "5/6",
|
|
1316
|
+
11: "11/12",
|
|
1317
|
+
12: "Full"
|
|
1318
|
+
};
|
|
1319
|
+
function widthShareLabel(width) {
|
|
1320
|
+
return WIDTH_SHARES[width] ?? `${width}/12`;
|
|
1321
|
+
}
|
|
1322
|
+
function isOptionsLocked(item) {
|
|
1323
|
+
return resolveWidgetLock(item).options;
|
|
1324
|
+
}
|
|
1325
|
+
function fillWith(fill, flexible) {
|
|
1326
|
+
const heightToo = fill === "height" || fill === "both";
|
|
1327
|
+
if (flexible) return heightToo ? "both" : "width";
|
|
1328
|
+
return heightToo ? "height" : void 0;
|
|
1329
|
+
}
|
|
1330
|
+
function isFlexible(item, settings) {
|
|
1331
|
+
if (settings?.flexible !== void 0) return settings.flexible;
|
|
1332
|
+
return item.fill === "width" || item.fill === "both";
|
|
1333
|
+
}
|
|
1334
|
+
function applySettings(definition, settings) {
|
|
1335
|
+
if (settings === void 0) return definition;
|
|
1336
|
+
const range = widthRange(definition);
|
|
1337
|
+
const width = settings.width === void 0 ? void 0 : Math.min(range.max, Math.max(range.min, settings.width));
|
|
1338
|
+
const title = settings.title === void 0 || settings.title.trim() === "" ? void 0 : settings.title;
|
|
1339
|
+
const flexibleChanged = settings.flexible !== void 0 && settings.flexible !== isFlexible(definition, void 0);
|
|
1340
|
+
if (title === void 0 && width === void 0 && !flexibleChanged) {
|
|
1341
|
+
return definition;
|
|
1342
|
+
}
|
|
1343
|
+
const next = { ...definition };
|
|
1344
|
+
if (title !== void 0) next.title = title;
|
|
1345
|
+
if (width !== void 0) next.width = width;
|
|
1346
|
+
if (flexibleChanged) {
|
|
1347
|
+
const fill = fillWith(
|
|
1348
|
+
definition.fill,
|
|
1349
|
+
settings.flexible === true
|
|
1350
|
+
);
|
|
1351
|
+
if (fill === void 0) {
|
|
1352
|
+
delete next.fill;
|
|
1353
|
+
} else {
|
|
1354
|
+
next.fill = fill;
|
|
1355
|
+
}
|
|
1356
|
+
}
|
|
1357
|
+
return next;
|
|
1358
|
+
}
|
|
1359
|
+
function effectiveDefinitions(definitions, layout, options = {}) {
|
|
1360
|
+
return definitions.map(
|
|
1361
|
+
(definition) => options.overrideLocks !== true && isOptionsLocked(definition) ? definition : applySettings(definition, layout.settings?.[definition.key])
|
|
1362
|
+
);
|
|
1363
|
+
}
|
|
1364
|
+
function widgetOptionValues(definition, settings) {
|
|
1365
|
+
const declared = definition.options ?? [];
|
|
1366
|
+
const values = {};
|
|
1367
|
+
for (const option of declared) {
|
|
1368
|
+
const picked = settings?.options?.[option.key];
|
|
1369
|
+
const value = (picked === void 0 ? void 0 : coerceOptionValue(option, picked)) ?? defaultOptionValue(option);
|
|
1370
|
+
if (value !== void 0) values[option.key] = value;
|
|
1371
|
+
}
|
|
1372
|
+
return values;
|
|
1373
|
+
}
|
|
1374
|
+
function optionValuesFromLayout(definitions, layout, options = {}) {
|
|
1375
|
+
const out = {};
|
|
1376
|
+
for (const definition of definitions) {
|
|
1377
|
+
if (definition.options === void 0 || definition.options.length === 0) {
|
|
1378
|
+
continue;
|
|
1379
|
+
}
|
|
1380
|
+
const locked = options.overrideLocks !== true && isOptionsLocked(definition);
|
|
1381
|
+
out[definition.key] = locked ? {} : layout.settings?.[definition.key]?.options ?? {};
|
|
1382
|
+
}
|
|
1383
|
+
return out;
|
|
1384
|
+
}
|
|
1385
|
+
function sameSettings(a, b) {
|
|
1386
|
+
if (a === b) return true;
|
|
1387
|
+
return a?.title === b?.title && a?.width === b?.width && a?.flexible === b?.flexible && a?.view === b?.view && sameOptionValues(a?.options ?? {}, b?.options ?? {});
|
|
1388
|
+
}
|
|
1389
|
+
function setWidgetSettings(layout, key, patch) {
|
|
1390
|
+
const before = layout.settings?.[key];
|
|
1391
|
+
const draft = { ...before };
|
|
1392
|
+
for (const field of [
|
|
1393
|
+
"title",
|
|
1394
|
+
"width",
|
|
1395
|
+
"flexible",
|
|
1396
|
+
"options",
|
|
1397
|
+
"view"
|
|
1398
|
+
]) {
|
|
1399
|
+
if (!(field in patch)) continue;
|
|
1400
|
+
const value = patch[field];
|
|
1401
|
+
if (value === void 0) {
|
|
1402
|
+
delete draft[field];
|
|
1403
|
+
} else {
|
|
1404
|
+
draft[field] = value;
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
const merged = parseOne(draft);
|
|
1408
|
+
if (sameSettings(before, merged)) return layout;
|
|
1409
|
+
const rest = { ...layout.settings };
|
|
1410
|
+
if (merged === void 0) {
|
|
1411
|
+
delete rest[key];
|
|
1412
|
+
} else {
|
|
1413
|
+
rest[key] = merged;
|
|
1414
|
+
}
|
|
1415
|
+
const { settings: _previous, ...others } = layout;
|
|
1416
|
+
return Object.keys(rest).length === 0 ? others : { ...others, settings: rest };
|
|
1417
|
+
}
|
|
1418
|
+
function clearWidgetSettings(layout, key) {
|
|
1419
|
+
if (layout.settings?.[key] === void 0) return layout;
|
|
1420
|
+
return setWidgetSettings(layout, key, {
|
|
1421
|
+
title: void 0,
|
|
1422
|
+
width: void 0,
|
|
1423
|
+
flexible: void 0,
|
|
1424
|
+
options: void 0,
|
|
1425
|
+
view: void 0
|
|
1426
|
+
});
|
|
1427
|
+
}
|
|
1428
|
+
function normalizeTitle(title) {
|
|
1429
|
+
return title.normalize("NFKC").trim().toLowerCase();
|
|
1430
|
+
}
|
|
1431
|
+
function isTitleInUse(definitions, layout, key, title) {
|
|
1432
|
+
const wanted = normalizeTitle(title);
|
|
1433
|
+
if (wanted === "") return false;
|
|
1434
|
+
return effectiveDefinitions(definitions, layout, {
|
|
1435
|
+
overrideLocks: true
|
|
1436
|
+
}).some(
|
|
1437
|
+
(other) => other.key !== key && normalizeTitle(other.title ?? other.key) === wanted
|
|
1438
|
+
);
|
|
1439
|
+
}
|
|
1440
|
+
function uniqueTitle(taken, title) {
|
|
1441
|
+
if (!taken.has(normalizeTitle(title))) return title;
|
|
1442
|
+
for (let n = 2; ; n += 1) {
|
|
1443
|
+
const suffix = ` (#${n})`;
|
|
1444
|
+
const candidate = `${title.slice(0, MAX_WIDGET_TITLE_LENGTH - suffix.length)}${suffix}`;
|
|
1445
|
+
if (!taken.has(normalizeTitle(candidate))) return candidate;
|
|
1446
|
+
}
|
|
1447
|
+
}
|
|
1448
|
+
function normalizeSettings(definitions, layout, options = {}) {
|
|
1449
|
+
const settings = layout.settings;
|
|
1450
|
+
if (settings === void 0) return layout;
|
|
1451
|
+
const cleaned = {};
|
|
1452
|
+
const taken = /* @__PURE__ */ new Set();
|
|
1453
|
+
for (const definition of definitions) {
|
|
1454
|
+
const renamed = settings[definition.key]?.title !== void 0 && (options.overrideLocks === true || !isOptionsLocked(definition));
|
|
1455
|
+
if (!renamed) taken.add(normalizeTitle(definition.title ?? definition.key));
|
|
1456
|
+
}
|
|
1457
|
+
for (const definition of definitions) {
|
|
1458
|
+
const one = settings[definition.key];
|
|
1459
|
+
if (one === void 0) continue;
|
|
1460
|
+
if (options.overrideLocks !== true && isOptionsLocked(definition)) continue;
|
|
1461
|
+
const range = widthRange(definition);
|
|
1462
|
+
const chosen = {};
|
|
1463
|
+
for (const option of definition.options ?? []) {
|
|
1464
|
+
const picked = one.options?.[option.key];
|
|
1465
|
+
if (picked === void 0) continue;
|
|
1466
|
+
const value = coerceOptionValue(option, picked);
|
|
1467
|
+
if (value !== void 0) {
|
|
1468
|
+
chosen[option.key] = option.type === "dateRange" ? picked : value;
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
let title = one.title;
|
|
1472
|
+
if (title !== void 0) {
|
|
1473
|
+
title = title.trim().slice(0, MAX_WIDGET_TITLE_LENGTH);
|
|
1474
|
+
if (title === "") {
|
|
1475
|
+
title = void 0;
|
|
1476
|
+
} else {
|
|
1477
|
+
title = uniqueTitle(taken, title);
|
|
1478
|
+
taken.add(normalizeTitle(title));
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
const next = {
|
|
1482
|
+
...title === void 0 ? {} : { title },
|
|
1483
|
+
...one.width === void 0 ? {} : { width: Math.min(range.max, Math.max(range.min, one.width)) },
|
|
1484
|
+
...one.flexible === void 0 ? {} : { flexible: one.flexible },
|
|
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 } : {}
|
|
1487
|
+
};
|
|
1488
|
+
if (Object.keys(next).length > 0) {
|
|
1489
|
+
cleaned[definition.key] = sameSettings(one, next) ? one : next;
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
const keys = Object.keys(cleaned);
|
|
1493
|
+
const unchanged = keys.length === Object.keys(settings).length && keys.every((key) => cleaned[key] === settings[key]);
|
|
1494
|
+
if (unchanged) return layout;
|
|
1495
|
+
const { settings: _previous, ...others } = layout;
|
|
1496
|
+
return keys.length === 0 ? others : { ...others, settings: cleaned };
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
// src/core/layout.ts
|
|
1500
|
+
var MAX_PAGE_TITLE_LENGTH = 30;
|
|
1501
|
+
var MAX_PARSED_PAGES = 50;
|
|
1502
|
+
var MAX_PAGE_ROWS = 20;
|
|
1503
|
+
var EMPTY_LAYOUT = Object.freeze({
|
|
1504
|
+
order: Object.freeze([]),
|
|
1505
|
+
hidden: Object.freeze([]),
|
|
1506
|
+
minimized: Object.freeze([])
|
|
1507
|
+
});
|
|
1508
|
+
function uniqueStrings(value) {
|
|
1509
|
+
if (!Array.isArray(value)) return [];
|
|
1510
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1511
|
+
for (const entry of value) {
|
|
1512
|
+
if (typeof entry === "string" && entry !== "") seen.add(entry);
|
|
1513
|
+
}
|
|
1514
|
+
return [...seen];
|
|
1515
|
+
}
|
|
1516
|
+
function parseLayout(raw) {
|
|
1517
|
+
let value = raw;
|
|
1518
|
+
if (typeof raw === "string") {
|
|
1519
|
+
try {
|
|
1520
|
+
value = JSON.parse(raw);
|
|
1521
|
+
} catch {
|
|
1522
|
+
return EMPTY_LAYOUT;
|
|
1523
|
+
}
|
|
1524
|
+
}
|
|
1525
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1526
|
+
return EMPTY_LAYOUT;
|
|
1527
|
+
}
|
|
1528
|
+
const record = value;
|
|
1529
|
+
const order = uniqueStrings(record["order"]);
|
|
1530
|
+
const hidden = uniqueStrings(record["hidden"]);
|
|
1531
|
+
const minimized = uniqueStrings(record["minimized"]);
|
|
1532
|
+
const pages = parsePages(record["pages"]);
|
|
1533
|
+
const settings = parseSettings(
|
|
1534
|
+
record["settings"]
|
|
1535
|
+
);
|
|
1536
|
+
const withSettings = settings === void 0 ? {} : { settings };
|
|
1537
|
+
if (pages.length > 0) {
|
|
1538
|
+
return {
|
|
1539
|
+
order: EMPTY_LAYOUT.order,
|
|
1540
|
+
hidden: EMPTY_LAYOUT.hidden,
|
|
1541
|
+
minimized: EMPTY_LAYOUT.minimized,
|
|
1542
|
+
pages,
|
|
1543
|
+
...withSettings
|
|
1544
|
+
};
|
|
1545
|
+
}
|
|
1546
|
+
if (order.length === 0 && hidden.length === 0 && minimized.length === 0) {
|
|
1547
|
+
return settings === void 0 ? EMPTY_LAYOUT : { ...EMPTY_LAYOUT, settings };
|
|
1548
|
+
}
|
|
1549
|
+
return { order, hidden, minimized, ...withSettings };
|
|
1550
|
+
}
|
|
1551
|
+
function parsePages(value) {
|
|
1552
|
+
if (!Array.isArray(value)) return [];
|
|
1553
|
+
const pages = [];
|
|
1554
|
+
const keys = /* @__PURE__ */ new Set();
|
|
1555
|
+
for (const entry of value.slice(0, MAX_PARSED_PAGES)) {
|
|
1556
|
+
if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
|
|
1557
|
+
continue;
|
|
1558
|
+
}
|
|
1559
|
+
const record = entry;
|
|
1560
|
+
const key = record["key"];
|
|
1561
|
+
if (typeof key !== "string" || key === "" || keys.has(key)) continue;
|
|
1562
|
+
keys.add(key);
|
|
1563
|
+
const rawTitle = record["title"];
|
|
1564
|
+
const title = typeof rawTitle === "string" && rawTitle.trim() !== "" ? rawTitle.trim().slice(0, MAX_PAGE_TITLE_LENGTH) : `Page ${pages.length + 1}`;
|
|
1565
|
+
const maxRows = record["maxRows"];
|
|
1566
|
+
const held = /* @__PURE__ */ new Set();
|
|
1567
|
+
for (const earlier of pages) {
|
|
1568
|
+
for (const k of [...earlier.order, ...earlier.hidden]) held.add(k);
|
|
1569
|
+
}
|
|
1570
|
+
const keep = (list) => uniqueStrings(list).filter((k) => !held.has(k));
|
|
1571
|
+
pages.push({
|
|
1572
|
+
key,
|
|
1573
|
+
title,
|
|
1574
|
+
order: keep(record["order"]),
|
|
1575
|
+
hidden: keep(record["hidden"]),
|
|
1576
|
+
minimized: keep(record["minimized"]),
|
|
1577
|
+
...typeof maxRows === "number" && Number.isInteger(maxRows) && maxRows >= 1 && maxRows <= MAX_PAGE_ROWS ? { maxRows } : {}
|
|
1578
|
+
});
|
|
1579
|
+
}
|
|
1580
|
+
return pages;
|
|
1581
|
+
}
|
|
1582
|
+
function serializeLayout(layout) {
|
|
1583
|
+
return JSON.stringify({
|
|
1584
|
+
order: [...layout.order],
|
|
1585
|
+
hidden: [...layout.hidden],
|
|
1586
|
+
minimized: [...layout.minimized],
|
|
1587
|
+
...layout.pages === void 0 || layout.pages.length === 0 ? {} : {
|
|
1588
|
+
pages: layout.pages.map((page) => ({
|
|
1589
|
+
key: page.key,
|
|
1590
|
+
title: page.title,
|
|
1591
|
+
order: [...page.order],
|
|
1592
|
+
hidden: [...page.hidden],
|
|
1593
|
+
minimized: [...page.minimized],
|
|
1594
|
+
...page.maxRows === void 0 ? {} : { maxRows: page.maxRows }
|
|
1595
|
+
}))
|
|
1596
|
+
},
|
|
1597
|
+
...serializeSettings(layout.settings) === void 0 ? {} : { settings: serializeSettings(layout.settings) }
|
|
1598
|
+
});
|
|
1599
|
+
}
|
|
1600
|
+
function bySortOrder(items) {
|
|
1601
|
+
return items.map((item, index) => ({ item, index })).sort(
|
|
1602
|
+
(a, b) => (a.item.sortOrder ?? 0) - (b.item.sortOrder ?? 0) || a.index - b.index
|
|
1603
|
+
).map(({ item }) => item);
|
|
1604
|
+
}
|
|
1605
|
+
function isPinned(item) {
|
|
1606
|
+
return resolveWidgetLock(item).move;
|
|
1607
|
+
}
|
|
1608
|
+
function viewerOrder(visible, layout) {
|
|
1609
|
+
const byKey = new Map(visible.map((d) => [d.key, d]));
|
|
1610
|
+
const ordered = [];
|
|
1611
|
+
for (const key of layout.order) {
|
|
1612
|
+
const definition = byKey.get(key);
|
|
1613
|
+
if (definition !== void 0) {
|
|
1614
|
+
ordered.push(definition);
|
|
1615
|
+
byKey.delete(key);
|
|
1616
|
+
}
|
|
1617
|
+
}
|
|
1618
|
+
for (const definition of bySortOrder(visible)) {
|
|
1619
|
+
if (byKey.has(definition.key)) ordered.push(definition);
|
|
1620
|
+
}
|
|
1621
|
+
return ordered;
|
|
1622
|
+
}
|
|
1623
|
+
function placeAroundPinned(visible, free) {
|
|
1624
|
+
const slots = bySortOrder(visible).map(
|
|
1625
|
+
(item) => isPinned(item) ? item : void 0
|
|
1626
|
+
);
|
|
1627
|
+
let next = 0;
|
|
1628
|
+
return slots.map((pinned) => pinned ?? free[next++]);
|
|
1629
|
+
}
|
|
1630
|
+
function visibleWidgets(definitions, layout) {
|
|
1631
|
+
const hidden = new Set(layout.hidden);
|
|
1632
|
+
const visible = definitions.filter((d) => !hidden.has(d.key));
|
|
1633
|
+
const ordered = viewerOrder(visible, layout);
|
|
1634
|
+
if (!visible.some(isPinned)) return ordered;
|
|
1635
|
+
return placeAroundPinned(
|
|
1636
|
+
visible,
|
|
1637
|
+
ordered.filter((item) => !isPinned(item))
|
|
1638
|
+
);
|
|
1639
|
+
}
|
|
1640
|
+
function hiddenWidgets(definitions, layout) {
|
|
1641
|
+
const hidden = new Set(layout.hidden);
|
|
1642
|
+
return bySortOrder(definitions.filter((d) => hidden.has(d.key)));
|
|
1643
|
+
}
|
|
1644
|
+
function moveWidget(definitions, layout, key, toIndex) {
|
|
1645
|
+
const current = visibleWidgets(definitions, layout);
|
|
1646
|
+
const fromIndex = current.findIndex((d) => d.key === key);
|
|
1647
|
+
const mover = current[fromIndex];
|
|
1648
|
+
if (mover === void 0 || !Number.isInteger(toIndex) || toIndex < 0 || toIndex >= current.length || toIndex === fromIndex || isPinned(mover) || isPinned(current[toIndex])) {
|
|
1649
|
+
return layout;
|
|
1650
|
+
}
|
|
1651
|
+
const freeSlots = freeSlotIndexes(current);
|
|
1652
|
+
const free = current.filter((item) => !isPinned(item));
|
|
1653
|
+
const fromFree = freeSlots.indexOf(fromIndex);
|
|
1654
|
+
const toFree = freeSlots.indexOf(toIndex);
|
|
1655
|
+
free.splice(fromFree, 1);
|
|
1656
|
+
free.splice(toFree, 0, mover);
|
|
1657
|
+
const next = placeAroundPinned(current, free);
|
|
1658
|
+
return { ...layout, order: next.map((d) => d.key) };
|
|
1659
|
+
}
|
|
1660
|
+
function freeSlotIndexes(ordered) {
|
|
1661
|
+
const slots = [];
|
|
1662
|
+
ordered.forEach((item, index) => {
|
|
1663
|
+
if (!isPinned(item)) slots.push(index);
|
|
1664
|
+
});
|
|
1665
|
+
return slots;
|
|
1666
|
+
}
|
|
1667
|
+
function moveWidgetBy(definitions, layout, key, offset) {
|
|
1668
|
+
const current = visibleWidgets(definitions, layout);
|
|
1669
|
+
const fromIndex = current.findIndex((d) => d.key === key);
|
|
1670
|
+
if (fromIndex === -1) return layout;
|
|
1671
|
+
const freeSlots = freeSlotIndexes(current);
|
|
1672
|
+
const fromFree = freeSlots.indexOf(fromIndex);
|
|
1673
|
+
if (fromFree === -1) return layout;
|
|
1674
|
+
const toFree = Math.max(
|
|
1675
|
+
0,
|
|
1676
|
+
Math.min(freeSlots.length - 1, fromFree + Math.trunc(offset))
|
|
1677
|
+
);
|
|
1678
|
+
return moveWidget(definitions, layout, key, freeSlots[toFree]);
|
|
1679
|
+
}
|
|
1680
|
+
function moveWidgetUp(definitions, layout, key) {
|
|
1681
|
+
return moveWidgetBy(definitions, layout, key, -1);
|
|
1130
1682
|
}
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
const options = definition.options;
|
|
1134
|
-
if (options === void 0 || options.length === 0) return NO_VALUES;
|
|
1135
|
-
const values = {};
|
|
1136
|
-
for (const option of options) {
|
|
1137
|
-
const picked = chosen?.[option.key];
|
|
1138
|
-
const value = (picked === void 0 ? void 0 : coerceOptionValue(option, picked, context)) ?? defaultOptionValue(option, context);
|
|
1139
|
-
if (value !== void 0) values[option.key] = value;
|
|
1140
|
-
}
|
|
1141
|
-
return values;
|
|
1683
|
+
function moveWidgetDown(definitions, layout, key) {
|
|
1684
|
+
return moveWidgetBy(definitions, layout, key, 1);
|
|
1142
1685
|
}
|
|
1143
|
-
function
|
|
1144
|
-
|
|
1145
|
-
return a.length === b.length && a.every((item, i) => item === b[i]);
|
|
1146
|
-
}
|
|
1147
|
-
return a === b;
|
|
1686
|
+
function isHidden(layout, key) {
|
|
1687
|
+
return layout.hidden.includes(key);
|
|
1148
1688
|
}
|
|
1149
|
-
function
|
|
1150
|
-
|
|
1151
|
-
return keys.every((key) => sameValue(a[key], b[key]));
|
|
1689
|
+
function isMinimized(layout, key) {
|
|
1690
|
+
return layout.minimized.includes(key);
|
|
1152
1691
|
}
|
|
1153
|
-
function
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
if (isClientApplied(option)) continue;
|
|
1157
|
-
const value = values[option.key];
|
|
1158
|
-
if (sameValue(value, defaultOptionValue(option, context))) continue;
|
|
1159
|
-
parts.push(
|
|
1160
|
-
`${option.key}=${encodeURIComponent(JSON.stringify(value ?? null))}`
|
|
1161
|
-
);
|
|
1162
|
-
}
|
|
1163
|
-
parts.sort();
|
|
1164
|
-
return parts.length === 0 ? "" : `?${parts.join("&")}`;
|
|
1692
|
+
function hideWidget(layout, key) {
|
|
1693
|
+
if (isHidden(layout, key)) return layout;
|
|
1694
|
+
return { ...layout, hidden: [...layout.hidden, key] };
|
|
1165
1695
|
}
|
|
1166
|
-
function
|
|
1167
|
-
|
|
1168
|
-
return
|
|
1696
|
+
function showWidget(layout, key) {
|
|
1697
|
+
if (!isHidden(layout, key)) return layout;
|
|
1698
|
+
return {
|
|
1699
|
+
...layout,
|
|
1700
|
+
hidden: layout.hidden.filter((k) => k !== key),
|
|
1701
|
+
minimized: layout.minimized.filter((k) => k !== key)
|
|
1702
|
+
};
|
|
1169
1703
|
}
|
|
1170
|
-
function
|
|
1171
|
-
|
|
1172
|
-
return items.map((item, index) => ({ item, index })).sort((a, b) => {
|
|
1173
|
-
const order = sort.column === "value" ? a.item.value - b.item.value : a.item.label.localeCompare(b.item.label);
|
|
1174
|
-
return order * sign || a.index - b.index;
|
|
1175
|
-
}).map(({ item }) => item);
|
|
1704
|
+
function toggleHidden(layout, key) {
|
|
1705
|
+
return isHidden(layout, key) ? showWidget(layout, key) : hideWidget(layout, key);
|
|
1176
1706
|
}
|
|
1177
|
-
function
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1707
|
+
function minimizeWidget(layout, key) {
|
|
1708
|
+
if (isMinimized(layout, key)) return layout;
|
|
1709
|
+
return { ...layout, minimized: [...layout.minimized, key] };
|
|
1710
|
+
}
|
|
1711
|
+
function restoreWidget(layout, key) {
|
|
1712
|
+
if (!isMinimized(layout, key)) return layout;
|
|
1713
|
+
return { ...layout, minimized: layout.minimized.filter((k) => k !== key) };
|
|
1714
|
+
}
|
|
1715
|
+
function toggleMinimized(layout, key) {
|
|
1716
|
+
return isMinimized(layout, key) ? restoreWidget(layout, key) : minimizeWidget(layout, key);
|
|
1717
|
+
}
|
|
1718
|
+
function pruneLayout(definitions, layout) {
|
|
1719
|
+
const known = new Set(definitions.map((d) => d.key));
|
|
1720
|
+
const keep = (keys) => keys.every((k) => known.has(k)) ? keys : keys.filter((k) => known.has(k));
|
|
1721
|
+
return mapLayoutLists(layout, (lists) => ({
|
|
1722
|
+
order: keep(lists.order),
|
|
1723
|
+
hidden: keep(lists.hidden),
|
|
1724
|
+
minimized: keep(lists.minimized)
|
|
1725
|
+
}));
|
|
1726
|
+
}
|
|
1727
|
+
function mapLayoutLists(layout, change) {
|
|
1728
|
+
const top = change(layout);
|
|
1729
|
+
const pages = layout.pages?.map((page) => {
|
|
1730
|
+
const next = change(page);
|
|
1731
|
+
return next.order === page.order && next.hidden === page.hidden && next.minimized === page.minimized ? page : { ...page, ...next };
|
|
1732
|
+
});
|
|
1733
|
+
const pagesChanged = pages !== void 0 && pages.some((page, i) => page !== layout.pages?.[i]);
|
|
1734
|
+
if (top.order === layout.order && top.hidden === layout.hidden && top.minimized === layout.minimized && !pagesChanged) {
|
|
1735
|
+
return layout;
|
|
1205
1736
|
}
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1737
|
+
return {
|
|
1738
|
+
...layout,
|
|
1739
|
+
...top,
|
|
1740
|
+
...pages === void 0 ? {} : { pages }
|
|
1741
|
+
};
|
|
1742
|
+
}
|
|
1743
|
+
function enforceLocks(definitions, layout, options = {}) {
|
|
1744
|
+
if (options.overrideLocks === true) return layout;
|
|
1745
|
+
const noMove = /* @__PURE__ */ new Set();
|
|
1746
|
+
const noHide = /* @__PURE__ */ new Set();
|
|
1747
|
+
const noMinimize = /* @__PURE__ */ new Set();
|
|
1748
|
+
for (const definition of definitions) {
|
|
1749
|
+
const lock = resolveWidgetLock(definition);
|
|
1750
|
+
if (lock.move) noMove.add(definition.key);
|
|
1751
|
+
if (lock.hide) noHide.add(definition.key);
|
|
1752
|
+
if (lock.minimize) noMinimize.add(definition.key);
|
|
1218
1753
|
}
|
|
1219
|
-
|
|
1754
|
+
const without2 = (keys, drop) => keys.some((key) => drop.has(key)) ? keys.filter((key) => !drop.has(key)) : keys;
|
|
1755
|
+
return mapLayoutLists(layout, (lists) => ({
|
|
1756
|
+
order: without2(lists.order, noMove),
|
|
1757
|
+
hidden: without2(lists.hidden, noHide),
|
|
1758
|
+
minimized: without2(lists.minimized, noMinimize)
|
|
1759
|
+
}));
|
|
1220
1760
|
}
|
|
1221
1761
|
|
|
1222
1762
|
// src/core/validate.ts
|
|
@@ -1229,7 +1769,7 @@ function describeType2(value) {
|
|
|
1229
1769
|
}
|
|
1230
1770
|
return typeof value;
|
|
1231
1771
|
}
|
|
1232
|
-
function
|
|
1772
|
+
function isRecord2(value) {
|
|
1233
1773
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1234
1774
|
}
|
|
1235
1775
|
function join(path, field) {
|
|
@@ -1311,7 +1851,7 @@ function requireOneOf(record, field, options, path, problems) {
|
|
|
1311
1851
|
function eachRecord(items, path, problems, check) {
|
|
1312
1852
|
items.forEach((item, index) => {
|
|
1313
1853
|
const itemPath = `${path}[${index}]`;
|
|
1314
|
-
if (
|
|
1854
|
+
if (isRecord2(item)) {
|
|
1315
1855
|
check(item, itemPath);
|
|
1316
1856
|
} else {
|
|
1317
1857
|
problems.push(
|
|
@@ -1460,7 +2000,7 @@ function checkPayloadFields(kind, data, problems) {
|
|
|
1460
2000
|
}
|
|
1461
2001
|
function checkDetailOption(detail, problems) {
|
|
1462
2002
|
if (detail === void 0 || typeof detail === "boolean") return;
|
|
1463
|
-
if (!
|
|
2003
|
+
if (!isRecord2(detail)) {
|
|
1464
2004
|
problems.push(
|
|
1465
2005
|
`detail must be true, false or an options object, got ${describeType2(detail)}.`
|
|
1466
2006
|
);
|
|
@@ -1479,13 +2019,13 @@ function checkDetailOption(detail, problems) {
|
|
|
1479
2019
|
}
|
|
1480
2020
|
function checkTableControlsOption(controls, kind, problems) {
|
|
1481
2021
|
if (controls === void 0 || controls === false) return;
|
|
1482
|
-
if (typeof controls !== "boolean" && !
|
|
2022
|
+
if (typeof controls !== "boolean" && !isRecord2(controls)) {
|
|
1483
2023
|
problems.push(
|
|
1484
2024
|
`tableControls must be true, false or an options object, got ${describeType2(controls)}.`
|
|
1485
2025
|
);
|
|
1486
2026
|
return;
|
|
1487
2027
|
}
|
|
1488
|
-
if (
|
|
2028
|
+
if (isRecord2(controls)) {
|
|
1489
2029
|
optionalBoolean(controls, "search", "tableControls", problems);
|
|
1490
2030
|
optionalBoolean(controls, "sort", "tableControls", problems);
|
|
1491
2031
|
}
|
|
@@ -1495,9 +2035,39 @@ function checkTableControlsOption(controls, kind, problems) {
|
|
|
1495
2035
|
);
|
|
1496
2036
|
}
|
|
1497
2037
|
}
|
|
2038
|
+
function checkWidthLimits(value, problems) {
|
|
2039
|
+
for (const field of ["minWidth", "maxWidth"]) {
|
|
2040
|
+
const limit = value[field];
|
|
2041
|
+
if (limit !== void 0 && !isWidgetWidth(limit)) {
|
|
2042
|
+
problems.push(
|
|
2043
|
+
`${field} must be an integer from ${MIN_WIDGET_WIDTH} to ${MAX_WIDGET_WIDTH} (twelfths of the row), got ${typeof limit === "number" ? String(limit) : describeType2(limit)}.`
|
|
2044
|
+
);
|
|
2045
|
+
return;
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
const { minWidth, maxWidth, width } = value;
|
|
2049
|
+
if (isWidgetWidth(minWidth) && isWidgetWidth(maxWidth) && minWidth > maxWidth) {
|
|
2050
|
+
problems.push(
|
|
2051
|
+
`minWidth (${minWidth}) must not be more than maxWidth (${maxWidth}).`
|
|
2052
|
+
);
|
|
2053
|
+
return;
|
|
2054
|
+
}
|
|
2055
|
+
if (isWidgetWidth(width)) {
|
|
2056
|
+
if (isWidgetWidth(minWidth) && width < minWidth) {
|
|
2057
|
+
problems.push(
|
|
2058
|
+
`width (${width}) must not be less than minWidth (${minWidth}).`
|
|
2059
|
+
);
|
|
2060
|
+
}
|
|
2061
|
+
if (isWidgetWidth(maxWidth) && width > maxWidth) {
|
|
2062
|
+
problems.push(
|
|
2063
|
+
`width (${width}) must not be more than maxWidth (${maxWidth}).`
|
|
2064
|
+
);
|
|
2065
|
+
}
|
|
2066
|
+
}
|
|
2067
|
+
}
|
|
1498
2068
|
function checkLockedOption(locked, problems) {
|
|
1499
2069
|
if (locked === void 0 || typeof locked === "boolean") return;
|
|
1500
|
-
if (!
|
|
2070
|
+
if (!isRecord2(locked)) {
|
|
1501
2071
|
problems.push(
|
|
1502
2072
|
`locked must be true, false or an object, got ${describeType2(locked)}.`
|
|
1503
2073
|
);
|
|
@@ -1506,6 +2076,7 @@ function checkLockedOption(locked, problems) {
|
|
|
1506
2076
|
optionalBoolean(locked, "move", "locked", problems);
|
|
1507
2077
|
optionalBoolean(locked, "hide", "locked", problems);
|
|
1508
2078
|
optionalBoolean(locked, "minimize", "locked", problems);
|
|
2079
|
+
optionalBoolean(locked, "options", "locked", problems);
|
|
1509
2080
|
}
|
|
1510
2081
|
function checkOptionColumns(option, path, kind, problems) {
|
|
1511
2082
|
const columns = option["columns"];
|
|
@@ -1518,7 +2089,7 @@ function checkOptionColumns(option, path, kind, problems) {
|
|
|
1518
2089
|
const keys = [];
|
|
1519
2090
|
columns.forEach((entry, index) => {
|
|
1520
2091
|
const entryPath = `${path}.columns[${index}]`;
|
|
1521
|
-
if (!
|
|
2092
|
+
if (!isRecord2(entry)) {
|
|
1522
2093
|
problems.push(
|
|
1523
2094
|
`${entryPath} must be an object, got ${describeType2(entry)}.`
|
|
1524
2095
|
);
|
|
@@ -1543,7 +2114,7 @@ function checkOptionColumns(option, path, kind, problems) {
|
|
|
1543
2114
|
return keys;
|
|
1544
2115
|
}
|
|
1545
2116
|
function checkOption(option, path, kind, seenKeys, seenTypes, problems) {
|
|
1546
|
-
if (!
|
|
2117
|
+
if (!isRecord2(option)) {
|
|
1547
2118
|
problems.push(`${path} must be an object, got ${describeType2(option)}.`);
|
|
1548
2119
|
return;
|
|
1549
2120
|
}
|
|
@@ -1575,7 +2146,7 @@ function checkOption(option, path, kind, seenKeys, seenTypes, problems) {
|
|
|
1575
2146
|
} else {
|
|
1576
2147
|
choices.forEach((choice, index) => {
|
|
1577
2148
|
const choicePath = `${path}.choices[${index}]`;
|
|
1578
|
-
if (!
|
|
2149
|
+
if (!isRecord2(choice)) {
|
|
1579
2150
|
problems.push(
|
|
1580
2151
|
`${choicePath} must be an object, got ${describeType2(choice)}.`
|
|
1581
2152
|
);
|
|
@@ -1665,7 +2236,7 @@ function checkOption(option, path, kind, seenKeys, seenTypes, problems) {
|
|
|
1665
2236
|
} else {
|
|
1666
2237
|
presets.forEach((preset, index) => {
|
|
1667
2238
|
const presetPath = `${path}.presets[${index}]`;
|
|
1668
|
-
if (!
|
|
2239
|
+
if (!isRecord2(preset)) {
|
|
1669
2240
|
problems.push(
|
|
1670
2241
|
`${presetPath} must be an object, got ${describeType2(preset)}.`
|
|
1671
2242
|
);
|
|
@@ -1785,6 +2356,137 @@ function checkOptions(options, kind, problems) {
|
|
|
1785
2356
|
);
|
|
1786
2357
|
});
|
|
1787
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
|
+
}
|
|
1788
2490
|
function formatProblems(prefix, problems) {
|
|
1789
2491
|
const shown = problems.slice(0, MAX_REPORTED_PROBLEMS);
|
|
1790
2492
|
const more = problems.length - shown.length;
|
|
@@ -1792,7 +2494,7 @@ function formatProblems(prefix, problems) {
|
|
|
1792
2494
|
}
|
|
1793
2495
|
function validateWidgetData(value, options = {}) {
|
|
1794
2496
|
const subject = options.widgetKey === void 0 ? "Widget data" : `Widget ${JSON.stringify(options.widgetKey)}`;
|
|
1795
|
-
if (!
|
|
2497
|
+
if (!isRecord2(value)) {
|
|
1796
2498
|
return err(`${subject}: must be an object, got ${describeType2(value)}.`);
|
|
1797
2499
|
}
|
|
1798
2500
|
if (value["empty"] === true) {
|
|
@@ -1822,7 +2524,7 @@ function validateWidgetData(value, options = {}) {
|
|
|
1822
2524
|
return ok(value);
|
|
1823
2525
|
}
|
|
1824
2526
|
function validateWidgetDefinition(value) {
|
|
1825
|
-
if (!
|
|
2527
|
+
if (!isRecord2(value)) {
|
|
1826
2528
|
return err(
|
|
1827
2529
|
`Widget definition: must be an object, got ${describeType2(value)}.`
|
|
1828
2530
|
);
|
|
@@ -1856,10 +2558,12 @@ function validateWidgetDefinition(value) {
|
|
|
1856
2558
|
`width must be an integer from ${MIN_WIDGET_WIDTH} to ${MAX_WIDGET_WIDTH} (twelfths of the row), got ${typeof value["width"] === "number" ? String(value["width"]) : describeType2(value["width"])}.`
|
|
1857
2559
|
);
|
|
1858
2560
|
}
|
|
2561
|
+
checkWidthLimits(value, problems);
|
|
1859
2562
|
checkDetailOption(value["detail"], problems);
|
|
1860
2563
|
checkTableControlsOption(value["tableControls"], value["kind"], problems);
|
|
1861
2564
|
checkLockedOption(value["locked"], problems);
|
|
1862
2565
|
checkOptions(value["options"], value["kind"], problems);
|
|
2566
|
+
checkViews(value, problems);
|
|
1863
2567
|
if (value["page"] !== void 0) {
|
|
1864
2568
|
if (typeof value["page"] !== "string" || value["page"].trim() === "") {
|
|
1865
2569
|
problems.push(
|
|
@@ -2517,7 +3221,7 @@ function withoutLockField(definition) {
|
|
|
2517
3221
|
delete copy.locked;
|
|
2518
3222
|
return copy;
|
|
2519
3223
|
}
|
|
2520
|
-
function
|
|
3224
|
+
function uniqueTitle2(taken, title, index) {
|
|
2521
3225
|
let base = title.trim().slice(0, MAX_PAGE_TITLE_LENGTH);
|
|
2522
3226
|
if (base === "") base = `Page ${index + 1}`;
|
|
2523
3227
|
let candidate = base;
|
|
@@ -2538,9 +3242,18 @@ function samePages(a, b) {
|
|
|
2538
3242
|
}
|
|
2539
3243
|
function normalizeLayout(definitions, layout, options = {}) {
|
|
2540
3244
|
const known = pruneLayout(definitions, layout);
|
|
2541
|
-
const
|
|
3245
|
+
const enforced = enforceLocks(definitions, known, options);
|
|
3246
|
+
const locked = normalizeSettings(
|
|
3247
|
+
definitions,
|
|
3248
|
+
enforced,
|
|
3249
|
+
options
|
|
3250
|
+
);
|
|
2542
3251
|
if (!hasPages(locked)) return locked === layout ? layout : locked;
|
|
2543
|
-
const defs =
|
|
3252
|
+
const defs = effectiveDefinitions(
|
|
3253
|
+
options.overrideLocks === true ? definitions.map(withoutLockField) : definitions,
|
|
3254
|
+
locked,
|
|
3255
|
+
options
|
|
3256
|
+
);
|
|
2544
3257
|
const taken = /* @__PURE__ */ new Set();
|
|
2545
3258
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
2546
3259
|
const held = /* @__PURE__ */ new Set();
|
|
@@ -2553,7 +3266,7 @@ function normalizeLayout(definitions, layout, options = {}) {
|
|
|
2553
3266
|
];
|
|
2554
3267
|
const next = {
|
|
2555
3268
|
...page,
|
|
2556
|
-
title:
|
|
3269
|
+
title: uniqueTitle2(taken, page.title, index),
|
|
2557
3270
|
order: keep(page.order),
|
|
2558
3271
|
hidden: keep(page.hidden),
|
|
2559
3272
|
minimized: keep(page.minimized)
|
|
@@ -2641,7 +3354,7 @@ function normalizeLayout(definitions, layout, options = {}) {
|
|
|
2641
3354
|
}
|
|
2642
3355
|
if (!placed) {
|
|
2643
3356
|
const key = nextPageKey(work());
|
|
2644
|
-
const title =
|
|
3357
|
+
const title = uniqueTitle2(
|
|
2645
3358
|
new Set(pages.map((p) => normalizedTitle(p.title))),
|
|
2646
3359
|
`Page ${pages.length + 1}`,
|
|
2647
3360
|
pages.length
|
|
@@ -2653,7 +3366,7 @@ function normalizeLayout(definitions, layout, options = {}) {
|
|
|
2653
3366
|
}
|
|
2654
3367
|
}
|
|
2655
3368
|
const result = work();
|
|
2656
|
-
return samePages(layout.pages ?? [], pages) && sameKeys(layout.order, result.order) ? layout : result;
|
|
3369
|
+
return samePages(layout.pages ?? [], pages) && sameKeys(layout.order, result.order) && locked.settings === layout.settings ? layout : result;
|
|
2657
3370
|
}
|
|
2658
3371
|
|
|
2659
3372
|
// src/core/scale.ts
|
|
@@ -3485,6 +4198,7 @@ function indent(block) {
|
|
|
3485
4198
|
return block.split("\n").map((line) => ` ${line}`).join("\n");
|
|
3486
4199
|
}
|
|
3487
4200
|
|
|
4201
|
+
exports.BASE_VIEW_KEY = BASE_VIEW_KEY;
|
|
3488
4202
|
exports.DATE_RANGE_PRESETS = DATE_RANGE_PRESETS;
|
|
3489
4203
|
exports.DEFAULT_COMPARISON_LABEL = DEFAULT_COMPARISON_LABEL;
|
|
3490
4204
|
exports.DEFAULT_CURRENCY = DEFAULT_CURRENCY;
|
|
@@ -3501,14 +4215,18 @@ exports.MAX_GRAPH_SERIES = MAX_GRAPH_SERIES;
|
|
|
3501
4215
|
exports.MAX_PAGE_ROWS = MAX_PAGE_ROWS;
|
|
3502
4216
|
exports.MAX_PAGE_TITLE_LENGTH = MAX_PAGE_TITLE_LENGTH;
|
|
3503
4217
|
exports.MAX_PARSED_PAGES = MAX_PARSED_PAGES;
|
|
4218
|
+
exports.MAX_PARSED_SETTINGS = MAX_PARSED_SETTINGS;
|
|
3504
4219
|
exports.MAX_REPORTED_PROBLEMS = MAX_REPORTED_PROBLEMS;
|
|
3505
4220
|
exports.MAX_TEXT_OPTION_LENGTH = MAX_TEXT_OPTION_LENGTH;
|
|
3506
4221
|
exports.MAX_WIDGET_OPTIONS = MAX_WIDGET_OPTIONS;
|
|
4222
|
+
exports.MAX_WIDGET_TITLE_LENGTH = MAX_WIDGET_TITLE_LENGTH;
|
|
4223
|
+
exports.MAX_WIDGET_VIEWS = MAX_WIDGET_VIEWS;
|
|
3507
4224
|
exports.MAX_WIDGET_WIDTH = MAX_WIDGET_WIDTH;
|
|
3508
4225
|
exports.MIN_WIDGET_WIDTH = MIN_WIDGET_WIDTH;
|
|
3509
4226
|
exports.OPTION_KEY_PATTERN = OPTION_KEY_PATTERN;
|
|
3510
4227
|
exports.THEME_TOKEN_VARIABLES = THEME_TOKEN_VARIABLES;
|
|
3511
4228
|
exports.VALUE_FORMATS = VALUE_FORMATS;
|
|
4229
|
+
exports.VIEW_CONVERSIONS = VIEW_CONVERSIONS;
|
|
3512
4230
|
exports.WIDGET_FILLS = WIDGET_FILLS;
|
|
3513
4231
|
exports.WIDGET_KINDS = WIDGET_KINDS;
|
|
3514
4232
|
exports.WIDGET_OPTION_TYPES = WIDGET_OPTION_TYPES;
|
|
@@ -3516,10 +4234,14 @@ exports.WIDGET_SIZES = WIDGET_SIZES;
|
|
|
3516
4234
|
exports.WIDTH_COLUMNS = WIDTH_COLUMNS;
|
|
3517
4235
|
exports.addPage = addPage;
|
|
3518
4236
|
exports.applyClientOptions = applyClientOptions;
|
|
4237
|
+
exports.applySettings = applySettings;
|
|
4238
|
+
exports.applyView = applyView;
|
|
3519
4239
|
exports.assignPages = assignPages;
|
|
3520
4240
|
exports.baseColumnSpan = baseColumnSpan;
|
|
3521
4241
|
exports.cacheKeyFor = cacheKeyFor;
|
|
4242
|
+
exports.clearWidgetSettings = clearWidgetSettings;
|
|
3522
4243
|
exports.coerceOptionValue = coerceOptionValue;
|
|
4244
|
+
exports.convertView = convertView;
|
|
3523
4245
|
exports.createLayoutPersistence = createLayoutPersistence;
|
|
3524
4246
|
exports.createTheme = createTheme;
|
|
3525
4247
|
exports.createWidgetLoader = createWidgetLoader;
|
|
@@ -3528,6 +4250,8 @@ exports.defaultOptionValue = defaultOptionValue;
|
|
|
3528
4250
|
exports.defineWidget = defineWidget;
|
|
3529
4251
|
exports.deriveDetailData = deriveDetailData;
|
|
3530
4252
|
exports.describeUnknownError = describeUnknownError;
|
|
4253
|
+
exports.effectiveDefinitions = effectiveDefinitions;
|
|
4254
|
+
exports.effectiveViewKey = effectiveViewKey;
|
|
3531
4255
|
exports.emptyTextFor = emptyTextFor;
|
|
3532
4256
|
exports.emptyWidget = emptyWidget;
|
|
3533
4257
|
exports.enforceLocks = enforceLocks;
|
|
@@ -3538,26 +4262,32 @@ exports.fillWidthSpans = fillWidthSpans;
|
|
|
3538
4262
|
exports.fillsHeight = fillsHeight;
|
|
3539
4263
|
exports.fillsWidth = fillsWidth;
|
|
3540
4264
|
exports.finalizeWidget = finalizeWidget;
|
|
4265
|
+
exports.findView = findView;
|
|
3541
4266
|
exports.fitCount = fitCount;
|
|
3542
4267
|
exports.formatCount = formatCount;
|
|
3543
4268
|
exports.formatPercentChange = formatPercentChange;
|
|
3544
4269
|
exports.formatValue = formatValue;
|
|
3545
4270
|
exports.fromLegacyDefinition = fromLegacyDefinition;
|
|
3546
4271
|
exports.hasPages = hasPages;
|
|
4272
|
+
exports.hasViews = hasViews;
|
|
3547
4273
|
exports.hiddenWidgets = hiddenWidgets;
|
|
3548
4274
|
exports.hideWidget = hideWidget;
|
|
3549
4275
|
exports.isClientApplied = isClientApplied;
|
|
3550
4276
|
exports.isColumnKeyFor = isColumnKeyFor;
|
|
4277
|
+
exports.isFlexible = isFlexible;
|
|
3551
4278
|
exports.isHidden = isHidden;
|
|
3552
4279
|
exports.isIsoInterval = isIsoInterval;
|
|
3553
4280
|
exports.isMinimized = isMinimized;
|
|
4281
|
+
exports.isOptionsLocked = isOptionsLocked;
|
|
3554
4282
|
exports.isSafeHref = isSafeHref;
|
|
3555
4283
|
exports.isSafeImageUrl = isSafeImageUrl;
|
|
4284
|
+
exports.isTitleInUse = isTitleInUse;
|
|
3556
4285
|
exports.isWidgetEmptyState = isWidgetEmptyState;
|
|
3557
4286
|
exports.isWidgetKind = isWidgetKind;
|
|
3558
4287
|
exports.isWidgetVisibleTo = isWidgetVisibleTo;
|
|
3559
4288
|
exports.isWidgetWidth = isWidgetWidth;
|
|
3560
4289
|
exports.itemWidth = itemWidth;
|
|
4290
|
+
exports.kindLabel = kindLabel;
|
|
3561
4291
|
exports.kpiDelta = kpiDelta;
|
|
3562
4292
|
exports.labelStride = labelStride;
|
|
3563
4293
|
exports.loadingWidgets = loadingWidgets;
|
|
@@ -3573,8 +4303,11 @@ exports.nextPageKey = nextPageKey;
|
|
|
3573
4303
|
exports.niceDomain = niceDomain;
|
|
3574
4304
|
exports.niceStep = niceStep;
|
|
3575
4305
|
exports.normalizeLayout = normalizeLayout;
|
|
4306
|
+
exports.normalizeSettings = normalizeSettings;
|
|
4307
|
+
exports.normalizeTitle = normalizeTitle;
|
|
3576
4308
|
exports.ok = ok;
|
|
3577
4309
|
exports.optionValuesFor = optionValuesFor;
|
|
4310
|
+
exports.optionValuesFromLayout = optionValuesFromLayout;
|
|
3578
4311
|
exports.optionsCacheSuffix = optionsCacheSuffix;
|
|
3579
4312
|
exports.pageLayout = pageLayout;
|
|
3580
4313
|
exports.pageList = pageList;
|
|
@@ -3583,6 +4316,7 @@ exports.pageRoom = pageRoom;
|
|
|
3583
4316
|
exports.pageWidgets = pageWidgets;
|
|
3584
4317
|
exports.parseDetailQuery = parseDetailQuery;
|
|
3585
4318
|
exports.parseLayout = parseLayout;
|
|
4319
|
+
exports.parseSettings = parseSettings;
|
|
3586
4320
|
exports.parseSortValue = parseSortValue;
|
|
3587
4321
|
exports.percentChange = percentChange;
|
|
3588
4322
|
exports.placeRows = placeRows;
|
|
@@ -3605,6 +4339,8 @@ exports.restoreWidget = restoreWidget;
|
|
|
3605
4339
|
exports.sameOptionValues = sameOptionValues;
|
|
3606
4340
|
exports.serializeDetailQuery = serializeDetailQuery;
|
|
3607
4341
|
exports.serializeLayout = serializeLayout;
|
|
4342
|
+
exports.serializeSettings = serializeSettings;
|
|
4343
|
+
exports.setWidgetSettings = setWidgetSettings;
|
|
3608
4344
|
exports.shareOf = shareOf;
|
|
3609
4345
|
exports.showWidget = showWidget;
|
|
3610
4346
|
exports.sortDefinitions = sortDefinitions;
|
|
@@ -3618,9 +4354,15 @@ exports.utf8Length = utf8Length;
|
|
|
3618
4354
|
exports.validateDetailData = validateDetailData;
|
|
3619
4355
|
exports.validateWidgetData = validateWidgetData;
|
|
3620
4356
|
exports.validateWidgetDefinition = validateWidgetDefinition;
|
|
4357
|
+
exports.viewChoices = viewChoices;
|
|
4358
|
+
exports.viewKind = viewKind;
|
|
4359
|
+
exports.viewNote = viewNote;
|
|
3621
4360
|
exports.visibleWidgets = visibleWidgets;
|
|
4361
|
+
exports.widgetOptionValues = widgetOptionValues;
|
|
3622
4362
|
exports.widgetsFor = widgetsFor;
|
|
3623
4363
|
exports.widthForSize = widthForSize;
|
|
4364
|
+
exports.widthRange = widthRange;
|
|
4365
|
+
exports.widthShareLabel = widthShareLabel;
|
|
3624
4366
|
exports.withEncoding = withEncoding;
|
|
3625
4367
|
exports.withFallback = withFallback;
|
|
3626
4368
|
exports.withLogging = withLogging;
|