@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/react.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode, ReactElement, RefObject } from 'react';
|
|
2
|
-
import { D as DashboardWidget, W as WidgetSize, a as WidgetFill, G as GraphWidgetData, N as NiceDomain, b as WidgetDefinition, c as DetailProviderOptions, d as DetailData, e as DetailQuery, O as OptionValues, L as Locale, f as DashboardLayout, g as WidgetViewerSettings, h as WidgetSettingsPatch, A as AlertListWidgetData, B as BarListWidgetData, i as GaugeWidgetData, K as KpiWidgetData, T as TableWidgetData, R as ResolvedTableControls, j as DetailSort, k as TextWidgetData, l as WidgetData, m as LayoutPersistence, S as StoreScope, P as PageItem, n as NormalizeOptions, o as ResolveOptions, p as WidgetContext, q as WidgetProviders } from './storage-
|
|
2
|
+
import { D as DashboardWidget, W as WidgetSize, a as WidgetFill, G as GraphWidgetData, N as NiceDomain, b as WidgetDefinition, c as DetailProviderOptions, d as DetailData, e as DetailQuery, O as OptionValues, L as Locale, f as DashboardLayout, g as WidgetViewerSettings, h as WidgetSettingsPatch, A as AlertListWidgetData, B as BarListWidgetData, i as GaugeWidgetData, K as KpiWidgetData, T as TableWidgetData, R as ResolvedTableControls, j as DetailSort, k as TextWidgetData, l as WidgetData, m as LayoutPersistence, S as StoreScope, P as PageItem, n as NormalizeOptions, o as ResolveOptions, p as WidgetContext, q as WidgetProviders } from './storage-DwJ-vGJg.cjs';
|
|
3
3
|
|
|
4
4
|
interface WidgetCardProps {
|
|
5
5
|
readonly title: string;
|
|
@@ -225,6 +225,10 @@ interface DashboardLabels {
|
|
|
225
225
|
/** e.g. "6 of 12 (1/2)". */
|
|
226
226
|
readonly widthOption: (width: number, share: string) => string;
|
|
227
227
|
readonly optionsFlexible: string;
|
|
228
|
+
/** Label of the View field in the Options dialog. */
|
|
229
|
+
readonly optionsViewField: string;
|
|
230
|
+
/** A view's name when it is the one shown until the viewer picks, e.g. "Table (default)". */
|
|
231
|
+
readonly viewDefault: (viewLabel: string) => string;
|
|
228
232
|
readonly optionsDeclared: string;
|
|
229
233
|
readonly apply: string;
|
|
230
234
|
readonly cancel: string;
|
package/dist/react.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode, ReactElement, RefObject } from 'react';
|
|
2
|
-
import { D as DashboardWidget, W as WidgetSize, a as WidgetFill, G as GraphWidgetData, N as NiceDomain, b as WidgetDefinition, c as DetailProviderOptions, d as DetailData, e as DetailQuery, O as OptionValues, L as Locale, f as DashboardLayout, g as WidgetViewerSettings, h as WidgetSettingsPatch, A as AlertListWidgetData, B as BarListWidgetData, i as GaugeWidgetData, K as KpiWidgetData, T as TableWidgetData, R as ResolvedTableControls, j as DetailSort, k as TextWidgetData, l as WidgetData, m as LayoutPersistence, S as StoreScope, P as PageItem, n as NormalizeOptions, o as ResolveOptions, p as WidgetContext, q as WidgetProviders } from './storage-
|
|
2
|
+
import { D as DashboardWidget, W as WidgetSize, a as WidgetFill, G as GraphWidgetData, N as NiceDomain, b as WidgetDefinition, c as DetailProviderOptions, d as DetailData, e as DetailQuery, O as OptionValues, L as Locale, f as DashboardLayout, g as WidgetViewerSettings, h as WidgetSettingsPatch, A as AlertListWidgetData, B as BarListWidgetData, i as GaugeWidgetData, K as KpiWidgetData, T as TableWidgetData, R as ResolvedTableControls, j as DetailSort, k as TextWidgetData, l as WidgetData, m as LayoutPersistence, S as StoreScope, P as PageItem, n as NormalizeOptions, o as ResolveOptions, p as WidgetContext, q as WidgetProviders } from './storage-DwJ-vGJg.js';
|
|
3
3
|
|
|
4
4
|
interface WidgetCardProps {
|
|
5
5
|
readonly title: string;
|
|
@@ -225,6 +225,10 @@ interface DashboardLabels {
|
|
|
225
225
|
/** e.g. "6 of 12 (1/2)". */
|
|
226
226
|
readonly widthOption: (width: number, share: string) => string;
|
|
227
227
|
readonly optionsFlexible: string;
|
|
228
|
+
/** Label of the View field in the Options dialog. */
|
|
229
|
+
readonly optionsViewField: string;
|
|
230
|
+
/** A view's name when it is the one shown until the viewer picks, e.g. "Table (default)". */
|
|
231
|
+
readonly viewDefault: (viewLabel: string) => string;
|
|
228
232
|
readonly optionsDeclared: string;
|
|
229
233
|
readonly apply: string;
|
|
230
234
|
readonly cancel: string;
|
package/dist/react.js
CHANGED
|
@@ -835,6 +835,8 @@ var DEFAULT_LABELS = {
|
|
|
835
835
|
widthDefault: "Default",
|
|
836
836
|
widthOption: (width, share) => `${width} of 12 (${share})`,
|
|
837
837
|
optionsFlexible: "Grow to fill empty space in the row",
|
|
838
|
+
optionsViewField: "View",
|
|
839
|
+
viewDefault: (viewLabel) => `${viewLabel} (default)`,
|
|
838
840
|
optionsDeclared: "Data",
|
|
839
841
|
apply: "Apply",
|
|
840
842
|
cancel: "Cancel",
|
|
@@ -1972,6 +1974,282 @@ function isWidgetVisibleTo(definition, roles) {
|
|
|
1972
1974
|
return definition.roles.some((role) => roles.includes(role));
|
|
1973
1975
|
}
|
|
1974
1976
|
|
|
1977
|
+
// src/core/payload.ts
|
|
1978
|
+
var WIDGET_KINDS = [
|
|
1979
|
+
"TEXT",
|
|
1980
|
+
"KPI",
|
|
1981
|
+
"GAUGE",
|
|
1982
|
+
"TABLE",
|
|
1983
|
+
"BAR_LIST",
|
|
1984
|
+
"ALERT_LIST",
|
|
1985
|
+
"GRAPH"
|
|
1986
|
+
];
|
|
1987
|
+
function isWidgetKind(value) {
|
|
1988
|
+
return typeof value === "string" && WIDGET_KINDS.includes(value);
|
|
1989
|
+
}
|
|
1990
|
+
var VALUE_FORMATS = ["number", "currency", "percent"];
|
|
1991
|
+
var MAX_GRAPH_SERIES = 8;
|
|
1992
|
+
var DEFAULT_EMPTY_TEXT = "Nothing to show yet.";
|
|
1993
|
+
function isWidgetEmptyState(payload) {
|
|
1994
|
+
return "empty" in payload && payload.empty === true;
|
|
1995
|
+
}
|
|
1996
|
+
function emptyTextFor(payload) {
|
|
1997
|
+
if (isWidgetEmptyState(payload)) {
|
|
1998
|
+
return payload.text;
|
|
1999
|
+
}
|
|
2000
|
+
switch (payload.kind) {
|
|
2001
|
+
case "TABLE":
|
|
2002
|
+
return payload.rows.length === 0 ? DEFAULT_EMPTY_TEXT : null;
|
|
2003
|
+
case "BAR_LIST":
|
|
2004
|
+
return payload.items.length === 0 ? DEFAULT_EMPTY_TEXT : null;
|
|
2005
|
+
case "ALERT_LIST":
|
|
2006
|
+
return payload.items.length === 0 ? payload.emptyText : null;
|
|
2007
|
+
case "GRAPH":
|
|
2008
|
+
return payload.series.every((series) => series.points.length === 0) ? DEFAULT_EMPTY_TEXT : null;
|
|
2009
|
+
case "TEXT":
|
|
2010
|
+
case "KPI":
|
|
2011
|
+
case "GAUGE":
|
|
2012
|
+
return null;
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2016
|
+
// src/core/views.ts
|
|
2017
|
+
var BASE_VIEW_KEY = "base";
|
|
2018
|
+
var VIEW_CONVERSIONS = {
|
|
2019
|
+
tableToBarList: { from: "TABLE", to: "BAR_LIST" },
|
|
2020
|
+
tableToGraph: { from: "TABLE", to: "GRAPH" },
|
|
2021
|
+
barListToTable: { from: "BAR_LIST", to: "TABLE" },
|
|
2022
|
+
graphToTable: { from: "GRAPH", to: "TABLE" },
|
|
2023
|
+
barListToGraph: { from: "BAR_LIST", to: "GRAPH" }
|
|
2024
|
+
};
|
|
2025
|
+
var KIND_LABELS = {
|
|
2026
|
+
TEXT: "Text",
|
|
2027
|
+
KPI: "Number",
|
|
2028
|
+
GAUGE: "Gauge",
|
|
2029
|
+
TABLE: "Table",
|
|
2030
|
+
BAR_LIST: "Bars",
|
|
2031
|
+
ALERT_LIST: "List",
|
|
2032
|
+
GRAPH: "Chart"
|
|
2033
|
+
};
|
|
2034
|
+
function kindLabel(kind) {
|
|
2035
|
+
return KIND_LABELS[kind];
|
|
2036
|
+
}
|
|
2037
|
+
function hasViews(item) {
|
|
2038
|
+
return item.views !== void 0 && item.views.length > 0;
|
|
2039
|
+
}
|
|
2040
|
+
function findView(item, key) {
|
|
2041
|
+
return item.views?.find((view) => view.key === key);
|
|
2042
|
+
}
|
|
2043
|
+
function viewChoices(item) {
|
|
2044
|
+
if (!hasViews(item)) return [];
|
|
2045
|
+
return [
|
|
2046
|
+
{
|
|
2047
|
+
key: BASE_VIEW_KEY,
|
|
2048
|
+
label: item.baseViewLabel ?? kindLabel(item.kind),
|
|
2049
|
+
kind: item.kind
|
|
2050
|
+
},
|
|
2051
|
+
...(item.views ?? []).map(({ key, label, kind }) => ({
|
|
2052
|
+
key,
|
|
2053
|
+
label,
|
|
2054
|
+
kind
|
|
2055
|
+
}))
|
|
2056
|
+
];
|
|
2057
|
+
}
|
|
2058
|
+
function isKnownView(item, key) {
|
|
2059
|
+
return key !== void 0 && (key === BASE_VIEW_KEY || findView(item, key) !== void 0);
|
|
2060
|
+
}
|
|
2061
|
+
function effectiveViewKey(item, chosen) {
|
|
2062
|
+
if (!hasViews(item)) return BASE_VIEW_KEY;
|
|
2063
|
+
if (isKnownView(item, chosen)) return chosen;
|
|
2064
|
+
if (isKnownView(item, item.defaultView)) return item.defaultView;
|
|
2065
|
+
return BASE_VIEW_KEY;
|
|
2066
|
+
}
|
|
2067
|
+
function cellValue2(cell) {
|
|
2068
|
+
const value = cell?.value;
|
|
2069
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
2070
|
+
}
|
|
2071
|
+
function columnName(table, index) {
|
|
2072
|
+
return table.columns[index]?.label ?? `#${index + 1}`;
|
|
2073
|
+
}
|
|
2074
|
+
function checkColumn(table, index, field, context) {
|
|
2075
|
+
if (!Number.isInteger(index) || index < 0 || index >= table.columns.length) {
|
|
2076
|
+
return `${context.where}: ${field} column ${index} does not exist (the table has ${table.columns.length} columns, numbered from 0).`;
|
|
2077
|
+
}
|
|
2078
|
+
return void 0;
|
|
2079
|
+
}
|
|
2080
|
+
function numericColumn(table, index, context) {
|
|
2081
|
+
const numbers = [];
|
|
2082
|
+
for (const [rowIndex, row] of table.rows.entries()) {
|
|
2083
|
+
const value = cellValue2(row[index]);
|
|
2084
|
+
if (value === void 0) {
|
|
2085
|
+
return err(
|
|
2086
|
+
`${context.where}: row ${rowIndex + 1}, column ${index + 1} ("${columnName(table, index)}") has no numeric value. Add value to the cells.`
|
|
2087
|
+
);
|
|
2088
|
+
}
|
|
2089
|
+
numbers.push(value);
|
|
2090
|
+
}
|
|
2091
|
+
return ok(numbers);
|
|
2092
|
+
}
|
|
2093
|
+
function tableToBarList(table, conversion, context) {
|
|
2094
|
+
const bad = checkColumn(table, conversion.label, "label", context) ?? checkColumn(table, conversion.value, "value", context);
|
|
2095
|
+
if (bad !== void 0) return err(bad);
|
|
2096
|
+
const numbers = numericColumn(table, conversion.value, context);
|
|
2097
|
+
if (!numbers.ok) return numbers;
|
|
2098
|
+
const items = table.rows.map((row, index) => ({
|
|
2099
|
+
label: row[conversion.label]?.text ?? "",
|
|
2100
|
+
value: numbers.value[index],
|
|
2101
|
+
display: row[conversion.value]?.text ?? String(numbers.value[index])
|
|
2102
|
+
}));
|
|
2103
|
+
return ok({ kind: "BAR_LIST", items });
|
|
2104
|
+
}
|
|
2105
|
+
function tableToGraph(table, conversion, context) {
|
|
2106
|
+
if (conversion.values.length === 0 || conversion.values.length > MAX_GRAPH_SERIES) {
|
|
2107
|
+
return err(
|
|
2108
|
+
`${context.where}: a chart needs 1 to ${MAX_GRAPH_SERIES} series columns, got ${conversion.values.length}.`
|
|
2109
|
+
);
|
|
2110
|
+
}
|
|
2111
|
+
let bad = checkColumn(
|
|
2112
|
+
table,
|
|
2113
|
+
conversion.label,
|
|
2114
|
+
"label",
|
|
2115
|
+
context
|
|
2116
|
+
);
|
|
2117
|
+
for (const index of conversion.values) {
|
|
2118
|
+
bad ??= checkColumn(table, index, "series", context);
|
|
2119
|
+
}
|
|
2120
|
+
if (bad !== void 0) return err(bad);
|
|
2121
|
+
const series = [];
|
|
2122
|
+
for (const index of conversion.values) {
|
|
2123
|
+
const numbers = numericColumn(table, index, context);
|
|
2124
|
+
if (!numbers.ok) return numbers;
|
|
2125
|
+
series.push({
|
|
2126
|
+
name: columnName(table, index),
|
|
2127
|
+
points: table.rows.map((row, rowIndex) => ({
|
|
2128
|
+
label: row[conversion.label]?.text ?? "",
|
|
2129
|
+
value: numbers.value[rowIndex]
|
|
2130
|
+
}))
|
|
2131
|
+
});
|
|
2132
|
+
}
|
|
2133
|
+
return ok({
|
|
2134
|
+
kind: "GRAPH",
|
|
2135
|
+
series,
|
|
2136
|
+
chartType: conversion.chartType,
|
|
2137
|
+
valueFormat: conversion.valueFormat ?? "number",
|
|
2138
|
+
...conversion.currency === void 0 ? {} : { currency: conversion.currency },
|
|
2139
|
+
xLabel: columnName(table, conversion.label)
|
|
2140
|
+
});
|
|
2141
|
+
}
|
|
2142
|
+
function barListToTable(list, conversion) {
|
|
2143
|
+
return ok({
|
|
2144
|
+
kind: "TABLE",
|
|
2145
|
+
columns: [
|
|
2146
|
+
{ label: conversion.labelHeading ?? "Name" },
|
|
2147
|
+
{ label: conversion.valueHeading ?? "Value", numeric: true }
|
|
2148
|
+
],
|
|
2149
|
+
rows: list.items.map((item) => [
|
|
2150
|
+
{ text: item.label },
|
|
2151
|
+
{ text: item.display ?? String(item.value), value: item.value }
|
|
2152
|
+
])
|
|
2153
|
+
});
|
|
2154
|
+
}
|
|
2155
|
+
function graphToTable(graph, context) {
|
|
2156
|
+
const first = graph.series[0];
|
|
2157
|
+
if (first === void 0)
|
|
2158
|
+
return err(`${context.where}: the chart has no series.`);
|
|
2159
|
+
const format = {
|
|
2160
|
+
...graph.currency === void 0 ? {} : { currency: graph.currency },
|
|
2161
|
+
...context.locale === void 0 ? {} : { locale: context.locale }
|
|
2162
|
+
};
|
|
2163
|
+
return ok({
|
|
2164
|
+
kind: "TABLE",
|
|
2165
|
+
columns: [
|
|
2166
|
+
{ label: graph.xLabel ?? "Label" },
|
|
2167
|
+
...graph.series.map((series) => ({ label: series.name, numeric: true }))
|
|
2168
|
+
],
|
|
2169
|
+
rows: first.points.map((point, index) => [
|
|
2170
|
+
{ text: point.label },
|
|
2171
|
+
...graph.series.map((series) => {
|
|
2172
|
+
const value = series.points[index]?.value;
|
|
2173
|
+
return value === void 0 ? { text: "\u2014" } : { text: formatValue(value, graph.valueFormat, format), value };
|
|
2174
|
+
})
|
|
2175
|
+
])
|
|
2176
|
+
});
|
|
2177
|
+
}
|
|
2178
|
+
function barListToGraph(list, conversion) {
|
|
2179
|
+
return ok({
|
|
2180
|
+
kind: "GRAPH",
|
|
2181
|
+
series: [
|
|
2182
|
+
{
|
|
2183
|
+
name: conversion.seriesName ?? "Value",
|
|
2184
|
+
points: list.items.map((item) => ({
|
|
2185
|
+
label: item.label,
|
|
2186
|
+
value: item.value
|
|
2187
|
+
}))
|
|
2188
|
+
}
|
|
2189
|
+
],
|
|
2190
|
+
chartType: conversion.chartType,
|
|
2191
|
+
valueFormat: conversion.valueFormat ?? "number",
|
|
2192
|
+
...conversion.currency === void 0 ? {} : { currency: conversion.currency }
|
|
2193
|
+
});
|
|
2194
|
+
}
|
|
2195
|
+
function convertView(widgetKey, view, data, options = {}) {
|
|
2196
|
+
const conversion = view.convert;
|
|
2197
|
+
const context = {
|
|
2198
|
+
where: `Widget ${JSON.stringify(widgetKey)} view ${JSON.stringify(view.key)}`,
|
|
2199
|
+
...options.locale === void 0 ? {} : { locale: options.locale }
|
|
2200
|
+
};
|
|
2201
|
+
const expected = VIEW_CONVERSIONS[conversion.type]?.from;
|
|
2202
|
+
if (expected === void 0) {
|
|
2203
|
+
return err(
|
|
2204
|
+
`${context.where}: unknown conversion type ${JSON.stringify(conversion.type)}.`
|
|
2205
|
+
);
|
|
2206
|
+
}
|
|
2207
|
+
if (data.kind !== expected) {
|
|
2208
|
+
return err(
|
|
2209
|
+
`${context.where}: ${conversion.type} reads a ${expected} payload, but the widget returned ${data.kind}.`
|
|
2210
|
+
);
|
|
2211
|
+
}
|
|
2212
|
+
switch (conversion.type) {
|
|
2213
|
+
case "tableToBarList":
|
|
2214
|
+
return tableToBarList(data, conversion, context);
|
|
2215
|
+
case "tableToGraph":
|
|
2216
|
+
return tableToGraph(data, conversion, context);
|
|
2217
|
+
case "barListToTable":
|
|
2218
|
+
return barListToTable(data, conversion);
|
|
2219
|
+
case "graphToTable":
|
|
2220
|
+
return graphToTable(data, context);
|
|
2221
|
+
case "barListToGraph":
|
|
2222
|
+
return barListToGraph(data, conversion);
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
function applyView(widget, chosen, options = {}) {
|
|
2226
|
+
const key = effectiveViewKey(widget.definition, chosen);
|
|
2227
|
+
const view = findView(widget.definition, key);
|
|
2228
|
+
if (view === void 0) return widget;
|
|
2229
|
+
const definition = {
|
|
2230
|
+
...widget.definition,
|
|
2231
|
+
kind: view.kind
|
|
2232
|
+
};
|
|
2233
|
+
if (widget.status === "loading") return { ...widget, definition };
|
|
2234
|
+
if (widget.status === "empty") return { ...widget, definition };
|
|
2235
|
+
if (widget.status === "error") return { ...widget, definition };
|
|
2236
|
+
const converted = convertView(
|
|
2237
|
+
widget.definition.key,
|
|
2238
|
+
view,
|
|
2239
|
+
widget.data,
|
|
2240
|
+
options
|
|
2241
|
+
);
|
|
2242
|
+
if (!converted.ok) {
|
|
2243
|
+
return {
|
|
2244
|
+
definition,
|
|
2245
|
+
status: "error",
|
|
2246
|
+
error: converted.error,
|
|
2247
|
+
...widget.options === void 0 ? {} : { options: widget.options }
|
|
2248
|
+
};
|
|
2249
|
+
}
|
|
2250
|
+
return { ...widget, definition, data: converted.value };
|
|
2251
|
+
}
|
|
2252
|
+
|
|
1975
2253
|
// src/core/settings.ts
|
|
1976
2254
|
var MAX_WIDGET_TITLE_LENGTH = 80;
|
|
1977
2255
|
var MAX_COLUMN_LIST = 100;
|
|
@@ -1999,6 +2277,7 @@ function parseOne(raw) {
|
|
|
1999
2277
|
const width = raw["width"];
|
|
2000
2278
|
const flexible = raw["flexible"];
|
|
2001
2279
|
const options = raw["options"];
|
|
2280
|
+
const view = raw["view"];
|
|
2002
2281
|
const cleanTitle = typeof title === "string" ? title.trim().slice(0, MAX_WIDGET_TITLE_LENGTH) : "";
|
|
2003
2282
|
const chosen = {};
|
|
2004
2283
|
if (isRecord(options)) {
|
|
@@ -2011,7 +2290,8 @@ function parseOne(raw) {
|
|
|
2011
2290
|
...cleanTitle === "" ? {} : { title: cleanTitle },
|
|
2012
2291
|
...isWidgetWidth(width) ? { width } : {},
|
|
2013
2292
|
...typeof flexible === "boolean" ? { flexible } : {},
|
|
2014
|
-
...Object.keys(chosen).length === 0 ? {} : { options: chosen }
|
|
2293
|
+
...Object.keys(chosen).length === 0 ? {} : { options: chosen },
|
|
2294
|
+
...typeof view === "string" && view !== "" && view.length <= 80 ? { view } : {}
|
|
2015
2295
|
};
|
|
2016
2296
|
return Object.keys(settings).length === 0 ? void 0 : settings;
|
|
2017
2297
|
}
|
|
@@ -2079,12 +2359,18 @@ function effectiveDefinitions(definitions, layout, options = {}) {
|
|
|
2079
2359
|
}
|
|
2080
2360
|
function sameSettings(a, b) {
|
|
2081
2361
|
if (a === b) return true;
|
|
2082
|
-
return a?.title === b?.title && a?.width === b?.width && a?.flexible === b?.flexible && sameOptionValues(a?.options ?? {}, b?.options ?? {});
|
|
2362
|
+
return a?.title === b?.title && a?.width === b?.width && a?.flexible === b?.flexible && a?.view === b?.view && sameOptionValues(a?.options ?? {}, b?.options ?? {});
|
|
2083
2363
|
}
|
|
2084
2364
|
function setWidgetSettings(layout, key, patch) {
|
|
2085
2365
|
const before = layout.settings?.[key];
|
|
2086
2366
|
const draft = { ...before };
|
|
2087
|
-
for (const field of [
|
|
2367
|
+
for (const field of [
|
|
2368
|
+
"title",
|
|
2369
|
+
"width",
|
|
2370
|
+
"flexible",
|
|
2371
|
+
"options",
|
|
2372
|
+
"view"
|
|
2373
|
+
]) {
|
|
2088
2374
|
if (!(field in patch)) continue;
|
|
2089
2375
|
const value = patch[field];
|
|
2090
2376
|
if (value === void 0) {
|
|
@@ -2788,7 +3074,8 @@ function draftFrom(settings) {
|
|
|
2788
3074
|
title: settings?.title ?? "",
|
|
2789
3075
|
width: settings?.width,
|
|
2790
3076
|
flexible: settings?.flexible,
|
|
2791
|
-
options: settings?.options ?? {}
|
|
3077
|
+
options: settings?.options ?? {},
|
|
3078
|
+
view: settings?.view
|
|
2792
3079
|
};
|
|
2793
3080
|
}
|
|
2794
3081
|
function storedDefault(option) {
|
|
@@ -2813,7 +3100,9 @@ function patchFrom(definition, draft) {
|
|
|
2813
3100
|
title: title === "" ? void 0 : title,
|
|
2814
3101
|
width: draft.width,
|
|
2815
3102
|
flexible: draft.flexible === void 0 || draft.flexible === isFlexible(definition) ? void 0 : draft.flexible,
|
|
2816
|
-
options: Object.keys(options).length === 0 ? void 0 : options
|
|
3103
|
+
options: Object.keys(options).length === 0 ? void 0 : options,
|
|
3104
|
+
// Choosing the author's own default view again clears the setting.
|
|
3105
|
+
view: draft.view === void 0 || draft.view === effectiveViewKey(definition, void 0) ? void 0 : draft.view
|
|
2817
3106
|
};
|
|
2818
3107
|
}
|
|
2819
3108
|
function patchKey(patch) {
|
|
@@ -2821,13 +3110,20 @@ function patchKey(patch) {
|
|
|
2821
3110
|
for (const key of Object.keys(patch.options ?? {}).sort()) {
|
|
2822
3111
|
options[key] = patch.options[key];
|
|
2823
3112
|
}
|
|
2824
|
-
return JSON.stringify([
|
|
3113
|
+
return JSON.stringify([
|
|
3114
|
+
patch.title,
|
|
3115
|
+
patch.width,
|
|
3116
|
+
patch.flexible,
|
|
3117
|
+
options,
|
|
3118
|
+
patch.view
|
|
3119
|
+
]);
|
|
2825
3120
|
}
|
|
2826
3121
|
var EMPTY_PATCH = {
|
|
2827
3122
|
title: void 0,
|
|
2828
3123
|
width: void 0,
|
|
2829
3124
|
flexible: void 0,
|
|
2830
|
-
options: void 0
|
|
3125
|
+
options: void 0,
|
|
3126
|
+
view: void 0
|
|
2831
3127
|
};
|
|
2832
3128
|
function WidgetOptionsDialog({
|
|
2833
3129
|
definition,
|
|
@@ -2865,6 +3161,7 @@ function WidgetOptionsDialog({
|
|
|
2865
3161
|
const canRevert = baselineKey !== void 0 && baselineKey !== savedKey;
|
|
2866
3162
|
const canReset = savedKey !== patchKey(EMPTY_PATCH);
|
|
2867
3163
|
const range = widthRange(definition);
|
|
3164
|
+
const views = viewChoices(definition);
|
|
2868
3165
|
const effectiveFlexible = draft.flexible ?? isFlexible(definition);
|
|
2869
3166
|
function requestClose() {
|
|
2870
3167
|
if (confirming !== void 0) {
|
|
@@ -2990,6 +3287,21 @@ function WidgetOptionsDialog({
|
|
|
2990
3287
|
),
|
|
2991
3288
|
labels.optionsFlexible
|
|
2992
3289
|
] }),
|
|
3290
|
+
views.length > 0 && /* @__PURE__ */ jsxs("div", { className: "dwt-options-field", children: [
|
|
3291
|
+
/* @__PURE__ */ jsx("label", { htmlFor: `${baseId}-view`, children: labels.optionsViewField }),
|
|
3292
|
+
/* @__PURE__ */ jsx(
|
|
3293
|
+
"select",
|
|
3294
|
+
{
|
|
3295
|
+
id: `${baseId}-view`,
|
|
3296
|
+
value: effectiveViewKey(definition, draft.view),
|
|
3297
|
+
onChange: (event) => {
|
|
3298
|
+
const value = event.target.value;
|
|
3299
|
+
setDraft((current) => ({ ...current, view: value }));
|
|
3300
|
+
},
|
|
3301
|
+
children: views.map((view) => /* @__PURE__ */ jsx("option", { value: view.key, children: view.key === effectiveViewKey(definition, void 0) ? labels.viewDefault(view.label) : view.label }, view.key))
|
|
3302
|
+
}
|
|
3303
|
+
)
|
|
3304
|
+
] }),
|
|
2993
3305
|
(definition.options?.length ?? 0) > 0 && /* @__PURE__ */ jsxs("fieldset", { className: "dwt-options-group", children: [
|
|
2994
3306
|
/* @__PURE__ */ jsx("legend", { children: labels.optionsDeclared }),
|
|
2995
3307
|
(definition.options ?? []).map((option) => /* @__PURE__ */ jsx(
|
|
@@ -3969,10 +4281,13 @@ function DashboardInner({
|
|
|
3969
4281
|
className
|
|
3970
4282
|
}) {
|
|
3971
4283
|
const slot = useSlotClassName();
|
|
3972
|
-
const { labels } = useWidgetSettings();
|
|
4284
|
+
const { labels, locale } = useWidgetSettings();
|
|
3973
4285
|
const effectiveWidgets = widgets.map((w) => {
|
|
3974
|
-
const settings = savedLayout.settings?.[w.definition.key];
|
|
3975
|
-
|
|
4286
|
+
const settings = !overrideLocks && isOptionsLocked(w.definition) ? void 0 : savedLayout.settings?.[w.definition.key];
|
|
4287
|
+
const styled = settings === void 0 ? w : { ...w, definition: applySettings(w.definition, settings) };
|
|
4288
|
+
return applyView(styled, settings?.view, {
|
|
4289
|
+
...locale === void 0 ? {} : { locale }
|
|
4290
|
+
});
|
|
3976
4291
|
});
|
|
3977
4292
|
const definitions = effectiveWidgets.map(
|
|
3978
4293
|
(w) => overrideLocks ? withoutLock(w.definition) : w.definition
|
|
@@ -4817,45 +5132,6 @@ function useStoredLayout(options) {
|
|
|
4817
5132
|
};
|
|
4818
5133
|
}
|
|
4819
5134
|
|
|
4820
|
-
// src/core/payload.ts
|
|
4821
|
-
var WIDGET_KINDS = [
|
|
4822
|
-
"TEXT",
|
|
4823
|
-
"KPI",
|
|
4824
|
-
"GAUGE",
|
|
4825
|
-
"TABLE",
|
|
4826
|
-
"BAR_LIST",
|
|
4827
|
-
"ALERT_LIST",
|
|
4828
|
-
"GRAPH"
|
|
4829
|
-
];
|
|
4830
|
-
function isWidgetKind(value) {
|
|
4831
|
-
return typeof value === "string" && WIDGET_KINDS.includes(value);
|
|
4832
|
-
}
|
|
4833
|
-
var VALUE_FORMATS = ["number", "currency", "percent"];
|
|
4834
|
-
var MAX_GRAPH_SERIES = 8;
|
|
4835
|
-
var DEFAULT_EMPTY_TEXT = "Nothing to show yet.";
|
|
4836
|
-
function isWidgetEmptyState(payload) {
|
|
4837
|
-
return "empty" in payload && payload.empty === true;
|
|
4838
|
-
}
|
|
4839
|
-
function emptyTextFor(payload) {
|
|
4840
|
-
if (isWidgetEmptyState(payload)) {
|
|
4841
|
-
return payload.text;
|
|
4842
|
-
}
|
|
4843
|
-
switch (payload.kind) {
|
|
4844
|
-
case "TABLE":
|
|
4845
|
-
return payload.rows.length === 0 ? DEFAULT_EMPTY_TEXT : null;
|
|
4846
|
-
case "BAR_LIST":
|
|
4847
|
-
return payload.items.length === 0 ? DEFAULT_EMPTY_TEXT : null;
|
|
4848
|
-
case "ALERT_LIST":
|
|
4849
|
-
return payload.items.length === 0 ? payload.emptyText : null;
|
|
4850
|
-
case "GRAPH":
|
|
4851
|
-
return payload.series.every((series) => series.points.length === 0) ? DEFAULT_EMPTY_TEXT : null;
|
|
4852
|
-
case "TEXT":
|
|
4853
|
-
case "KPI":
|
|
4854
|
-
case "GAUGE":
|
|
4855
|
-
return null;
|
|
4856
|
-
}
|
|
4857
|
-
}
|
|
4858
|
-
|
|
4859
5135
|
// src/core/validate.ts
|
|
4860
5136
|
var MAX_REPORTED_PROBLEMS = 10;
|
|
4861
5137
|
function describeType2(value) {
|