@juicemantics/veloiq-ui 0.8.4 → 0.9.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/index.d.mts +16 -2
- package/dist/index.d.ts +16 -2
- package/dist/index.js +211 -38
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +210 -39
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -5080,6 +5080,39 @@ var getSortPriority = (columnSort, fieldKey) => {
|
|
|
5080
5080
|
const index = columnSort.findIndex((item) => item.fieldKey === fieldKey);
|
|
5081
5081
|
return index === -1 ? 1 : columnSort.length - index + 1;
|
|
5082
5082
|
};
|
|
5083
|
+
var _TOKEN_KEY = "jm_access_token";
|
|
5084
|
+
function useAuthenticatedFileUrl(rawUrl) {
|
|
5085
|
+
const [src, setSrc] = useState("");
|
|
5086
|
+
useEffect(() => {
|
|
5087
|
+
if (!rawUrl) {
|
|
5088
|
+
setSrc("");
|
|
5089
|
+
return;
|
|
5090
|
+
}
|
|
5091
|
+
if (!rawUrl.includes("/api/file/")) {
|
|
5092
|
+
setSrc(rawUrl);
|
|
5093
|
+
return;
|
|
5094
|
+
}
|
|
5095
|
+
const token = localStorage.getItem(_TOKEN_KEY) || "";
|
|
5096
|
+
const controller = new AbortController();
|
|
5097
|
+
let objectUrl = "";
|
|
5098
|
+
fetch(rawUrl, {
|
|
5099
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
|
5100
|
+
signal: controller.signal
|
|
5101
|
+
}).then((r) => r.ok ? r.blob() : Promise.reject()).then((blob) => {
|
|
5102
|
+
objectUrl = URL.createObjectURL(blob);
|
|
5103
|
+
setSrc(objectUrl);
|
|
5104
|
+
}).catch(() => setSrc(""));
|
|
5105
|
+
return () => {
|
|
5106
|
+
controller.abort();
|
|
5107
|
+
if (objectUrl) URL.revokeObjectURL(objectUrl);
|
|
5108
|
+
};
|
|
5109
|
+
}, [rawUrl]);
|
|
5110
|
+
return src;
|
|
5111
|
+
}
|
|
5112
|
+
var AuthenticatedImage = ({ url, alt, style }) => {
|
|
5113
|
+
const src = useAuthenticatedFileUrl(url);
|
|
5114
|
+
return src ? /* @__PURE__ */ jsx("img", { src, alt: alt ?? "", style }) : null;
|
|
5115
|
+
};
|
|
5083
5116
|
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "bmp", "webp", "svg", "tif", "tiff"]);
|
|
5084
5117
|
var isImageRecord = (record) => {
|
|
5085
5118
|
if (record?.avatar_url || record?.image_url || record?.photo_url) return true;
|
|
@@ -5137,7 +5170,7 @@ var renderSharedGalleryCard = ({
|
|
|
5137
5170
|
style: { width: imageWidth, display: "grid", gap: 6, cursor: onClick ? "pointer" : "default" },
|
|
5138
5171
|
onClick,
|
|
5139
5172
|
children: [
|
|
5140
|
-
contentUrl ? /* @__PURE__ */ jsx(
|
|
5173
|
+
contentUrl ? /* @__PURE__ */ jsx(AuthenticatedImage, { url: contentUrl, alt: label, style: imageStyle }) : /* @__PURE__ */ jsx("div", { style: { ...imageStyle, display: "flex", alignItems: "center", justifyContent: "center", color: "#8c8c8c" }, children: /* @__PURE__ */ jsx(FileTextOutlined, { style: { fontSize: 24 } }) }),
|
|
5141
5174
|
/* @__PURE__ */ jsx("div", { style: { fontSize: 12, color: textColor, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: label })
|
|
5142
5175
|
]
|
|
5143
5176
|
},
|
|
@@ -6082,6 +6115,8 @@ var AnalysisChart = ({
|
|
|
6082
6115
|
};
|
|
6083
6116
|
const primarySeriesKey = seriesKeys[0] || "__count__";
|
|
6084
6117
|
const secondarySeriesKey = seriesKeys[1];
|
|
6118
|
+
const resolveNumericField = (fields, n) => fields[Math.min(n, fields.length - 1)] ?? { key: "__count__", label: _10("Count") };
|
|
6119
|
+
const resolveCategoryField = (field1, field2) => field2 ?? field1;
|
|
6085
6120
|
const getNumericValue = (record, key) => {
|
|
6086
6121
|
if (key === "__count__") return 1;
|
|
6087
6122
|
const value = Number(record?.[key]);
|
|
@@ -6498,11 +6533,11 @@ var AnalysisChart = ({
|
|
|
6498
6533
|
] });
|
|
6499
6534
|
};
|
|
6500
6535
|
const renderScatter = (isBubble) => {
|
|
6501
|
-
if (numericFields.length
|
|
6502
|
-
return /* @__PURE__ */ jsx(Empty, { description: "Scatter needs at least
|
|
6536
|
+
if (numericFields.length === 0) {
|
|
6537
|
+
return /* @__PURE__ */ jsx(Empty, { description: "Scatter needs at least one numeric field." });
|
|
6503
6538
|
}
|
|
6504
|
-
const xField = numericFields
|
|
6505
|
-
const yField = numericFields
|
|
6539
|
+
const xField = resolveNumericField(numericFields, 0);
|
|
6540
|
+
const yField = resolveNumericField(numericFields, 1);
|
|
6506
6541
|
const points = rawRows.map((row) => {
|
|
6507
6542
|
const x = getNumericValue(row, xField.key);
|
|
6508
6543
|
const y = getNumericValue(row, yField.key);
|
|
@@ -6780,11 +6815,12 @@ var AnalysisChart = ({
|
|
|
6780
6815
|
] });
|
|
6781
6816
|
};
|
|
6782
6817
|
const renderHeatmap = () => {
|
|
6783
|
-
if (!categoryField1
|
|
6784
|
-
return /* @__PURE__ */ jsx(Empty, { description: "Heatmap needs
|
|
6818
|
+
if (!categoryField1) {
|
|
6819
|
+
return /* @__PURE__ */ jsx(Empty, { description: "Heatmap needs a category field." });
|
|
6785
6820
|
}
|
|
6821
|
+
const effectiveCat2 = resolveCategoryField(categoryField1, categoryField2);
|
|
6786
6822
|
const cat1Field = modelField(categoryField1);
|
|
6787
|
-
const cat2Field = modelField(
|
|
6823
|
+
const cat2Field = modelField(effectiveCat2);
|
|
6788
6824
|
const rowLabels = [];
|
|
6789
6825
|
const colLabels = [];
|
|
6790
6826
|
const grid = /* @__PURE__ */ new Map();
|
|
@@ -6862,43 +6898,45 @@ var AnalysisChart = ({
|
|
|
6862
6898
|
] });
|
|
6863
6899
|
};
|
|
6864
6900
|
const renderCrosstab = () => {
|
|
6865
|
-
if (!categoryField1
|
|
6866
|
-
return /* @__PURE__ */ jsx(Empty, { description: "Crosstab needs
|
|
6901
|
+
if (!categoryField1) {
|
|
6902
|
+
return /* @__PURE__ */ jsx(Empty, { description: "Crosstab needs a category field." });
|
|
6867
6903
|
}
|
|
6904
|
+
const effectiveCat2 = resolveCategoryField(categoryField1, categoryField2);
|
|
6868
6905
|
const cat1Field = modelField(categoryField1);
|
|
6869
|
-
const cat2Field = modelField(
|
|
6906
|
+
const cat2Field = modelField(effectiveCat2);
|
|
6870
6907
|
return /* @__PURE__ */ jsx(
|
|
6871
6908
|
CrosstabTable,
|
|
6872
6909
|
{
|
|
6873
6910
|
rows: rawRows,
|
|
6874
6911
|
rowField: categoryField1,
|
|
6875
|
-
colField:
|
|
6912
|
+
colField: effectiveCat2 ?? categoryField1,
|
|
6876
6913
|
cellFieldKeys: seriesKeys,
|
|
6877
6914
|
cellFieldLabels: seriesLabels,
|
|
6878
6915
|
allFields,
|
|
6879
6916
|
summaryFn,
|
|
6880
6917
|
formatCategoryValue,
|
|
6881
6918
|
numericBarColor,
|
|
6882
|
-
caption: `${_10("Crosstab")}: ${cat1Field?.label || categoryField1} \xD7 ${cat2Field?.label ||
|
|
6919
|
+
caption: `${_10("Crosstab")}: ${cat1Field?.label || categoryField1} \xD7 ${cat2Field?.label || effectiveCat2} (${summaryFn})`
|
|
6883
6920
|
}
|
|
6884
6921
|
);
|
|
6885
6922
|
};
|
|
6886
6923
|
const renderRadar = () => {
|
|
6887
|
-
if (seriesKeys.length
|
|
6888
|
-
return /* @__PURE__ */ jsx(Empty, { description: "Radar needs at least
|
|
6924
|
+
if (seriesKeys.length === 0) {
|
|
6925
|
+
return /* @__PURE__ */ jsx(Empty, { description: "Radar needs at least one series." });
|
|
6889
6926
|
}
|
|
6927
|
+
const effectiveSeriesKeys = seriesKeys.length >= 3 ? seriesKeys : Array.from({ length: 3 }, (_43, i) => seriesKeys[i % seriesKeys.length]);
|
|
6890
6928
|
const centerX = paddingLeft + chartWidth / 2;
|
|
6891
6929
|
const centerY = paddingTop + chartHeight / 2;
|
|
6892
6930
|
const radius = Math.min(chartWidth, chartHeight) * 0.35;
|
|
6893
|
-
const maxBySeries =
|
|
6931
|
+
const maxBySeries = effectiveSeriesKeys.reduce((acc, key) => {
|
|
6894
6932
|
acc[key] = Math.max(...data.map((group) => group.values[key] || 0), 1);
|
|
6895
6933
|
return acc;
|
|
6896
6934
|
}, {});
|
|
6897
|
-
const angleStep = Math.PI * 2 /
|
|
6935
|
+
const angleStep = Math.PI * 2 / effectiveSeriesKeys.length;
|
|
6898
6936
|
return /* @__PURE__ */ jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
|
|
6899
6937
|
renderTitle(),
|
|
6900
6938
|
renderCaption("Radar chart"),
|
|
6901
|
-
|
|
6939
|
+
effectiveSeriesKeys.map((seriesKey, index) => {
|
|
6902
6940
|
const angle = -Math.PI / 2 + index * angleStep;
|
|
6903
6941
|
const x = centerX + radius * Math.cos(angle);
|
|
6904
6942
|
const y = centerY + radius * Math.sin(angle);
|
|
@@ -6908,7 +6946,7 @@ var AnalysisChart = ({
|
|
|
6908
6946
|
] }, `radar-axis-${seriesKey}`);
|
|
6909
6947
|
}),
|
|
6910
6948
|
data.map((group, groupIndex) => {
|
|
6911
|
-
const points =
|
|
6949
|
+
const points = effectiveSeriesKeys.map((seriesKey, index) => {
|
|
6912
6950
|
const value = group.values[seriesKey] || 0;
|
|
6913
6951
|
const ratio = value / Math.max(1, maxBySeries[seriesKey]);
|
|
6914
6952
|
const angle = -Math.PI / 2 + index * angleStep;
|
|
@@ -6933,13 +6971,74 @@ var AnalysisChart = ({
|
|
|
6933
6971
|
})
|
|
6934
6972
|
] });
|
|
6935
6973
|
};
|
|
6936
|
-
const
|
|
6937
|
-
if (
|
|
6938
|
-
return /* @__PURE__ */ jsx(Empty, { description: "
|
|
6974
|
+
const render3D = () => {
|
|
6975
|
+
if (numericFields.length === 0) {
|
|
6976
|
+
return /* @__PURE__ */ jsx(Empty, { description: "3D scatter needs at least one numeric field." });
|
|
6939
6977
|
}
|
|
6978
|
+
const xField = resolveNumericField(numericFields, 0);
|
|
6979
|
+
const yField = resolveNumericField(numericFields, 1);
|
|
6980
|
+
const zField = resolveNumericField(numericFields, 2);
|
|
6981
|
+
const points = rawRows.map((row) => {
|
|
6982
|
+
const x = getNumericValue(row, xField.key);
|
|
6983
|
+
const y = getNumericValue(row, yField.key);
|
|
6984
|
+
const z = getNumericValue(row, zField.key);
|
|
6985
|
+
if (x === null || y === null || z === null) return null;
|
|
6986
|
+
return { x, y, z };
|
|
6987
|
+
}).filter((p) => !!p);
|
|
6988
|
+
if (points.length === 0) return renderNoChartDataMessage();
|
|
6989
|
+
const xs = points.map((p) => p.x);
|
|
6990
|
+
const ys = points.map((p) => p.y);
|
|
6991
|
+
const zs = points.map((p) => p.z);
|
|
6992
|
+
const xMin = Math.min(...xs), xMax = Math.max(...xs);
|
|
6993
|
+
const yMin = Math.min(...ys), yMax = Math.max(...ys);
|
|
6994
|
+
const zMin = Math.min(...zs), zMax = Math.max(...zs);
|
|
6995
|
+
const norm = (v, lo, hi) => hi === lo ? 0.5 : (v - lo) / (hi - lo);
|
|
6996
|
+
const isoScale = Math.min(chartWidth, chartHeight) * 0.38;
|
|
6997
|
+
const cx = paddingLeft + chartWidth * 0.5;
|
|
6998
|
+
const cy = paddingTop + chartHeight * 0.55;
|
|
6999
|
+
const cos30 = Math.cos(Math.PI / 6);
|
|
7000
|
+
const sin30 = Math.sin(Math.PI / 6);
|
|
7001
|
+
const project = (nx, ny, nz) => ({
|
|
7002
|
+
sx: cx + (nx - nz) * cos30 * isoScale,
|
|
7003
|
+
sy: cy - ny * isoScale + (nx + nz) * sin30 * isoScale
|
|
7004
|
+
});
|
|
7005
|
+
const axisEnd = (nx, ny, nz) => project(nx, ny, nz);
|
|
7006
|
+
const origin = project(0, 0, 0);
|
|
7007
|
+
const xTip = axisEnd(1, 0, 0);
|
|
7008
|
+
const yTip = axisEnd(0, 1, 0);
|
|
7009
|
+
const zTip = axisEnd(0, 0, 1);
|
|
7010
|
+
const projected = points.map(
|
|
7011
|
+
(p) => project(norm(p.x, xMin, xMax), norm(p.y, yMin, yMax), norm(p.z, zMin, zMax))
|
|
7012
|
+
);
|
|
7013
|
+
return /* @__PURE__ */ jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
|
|
7014
|
+
renderTitle(),
|
|
7015
|
+
renderCaption(`3D: ${xField.label} \xD7 ${yField.label} \xD7 ${zField.label}`),
|
|
7016
|
+
/* @__PURE__ */ jsx("line", { x1: origin.sx, y1: origin.sy, x2: xTip.sx, y2: xTip.sy, stroke: colors[0], strokeWidth: 1.5, opacity: 0.6 }),
|
|
7017
|
+
/* @__PURE__ */ jsx("line", { x1: origin.sx, y1: origin.sy, x2: yTip.sx, y2: yTip.sy, stroke: colors[1], strokeWidth: 1.5, opacity: 0.6 }),
|
|
7018
|
+
/* @__PURE__ */ jsx("line", { x1: origin.sx, y1: origin.sy, x2: zTip.sx, y2: zTip.sy, stroke: colors[2], strokeWidth: 1.5, opacity: 0.6 }),
|
|
7019
|
+
/* @__PURE__ */ jsx("text", { x: xTip.sx + 4, y: xTip.sy + 4, fontSize: "11", fill: colors[0], children: xField.label }),
|
|
7020
|
+
/* @__PURE__ */ jsx("text", { x: yTip.sx + 4, y: yTip.sy, fontSize: "11", fill: colors[1], children: yField.label }),
|
|
7021
|
+
/* @__PURE__ */ jsx("text", { x: zTip.sx + 4, y: zTip.sy + 4, fontSize: "11", fill: colors[2], children: zField.label }),
|
|
7022
|
+
projected.map((p, i) => /* @__PURE__ */ jsx(
|
|
7023
|
+
"circle",
|
|
7024
|
+
{
|
|
7025
|
+
className: "chart-item chart-point",
|
|
7026
|
+
style: { "--delay": `${i * 8}ms` },
|
|
7027
|
+
cx: p.sx,
|
|
7028
|
+
cy: p.sy,
|
|
7029
|
+
r: 4,
|
|
7030
|
+
fill: colors[0],
|
|
7031
|
+
opacity: 0.7
|
|
7032
|
+
},
|
|
7033
|
+
`3d-${i}`
|
|
7034
|
+
))
|
|
7035
|
+
] });
|
|
7036
|
+
};
|
|
7037
|
+
const renderCombo = () => {
|
|
7038
|
+
const effectiveSecondaryKey = secondarySeriesKey ?? primarySeriesKey;
|
|
6940
7039
|
const valuesCombo = data.flatMap((group) => [
|
|
6941
7040
|
group.values[primarySeriesKey] || 0,
|
|
6942
|
-
group.values[
|
|
7041
|
+
group.values[effectiveSecondaryKey] || 0
|
|
6943
7042
|
]);
|
|
6944
7043
|
const maxCombo = Math.max(...valuesCombo, 1);
|
|
6945
7044
|
const minCombo = Math.min(...valuesCombo, 0);
|
|
@@ -6948,7 +7047,7 @@ var AnalysisChart = ({
|
|
|
6948
7047
|
const barWidth2 = groupWidth2 * 0.6;
|
|
6949
7048
|
const points = data.map((group, index) => {
|
|
6950
7049
|
const x = paddingLeft + index * groupWidth2 + groupWidth2 / 2;
|
|
6951
|
-
const y = scaleYCombo(group.values[
|
|
7050
|
+
const y = scaleYCombo(group.values[effectiveSecondaryKey] || 0);
|
|
6952
7051
|
return `${x},${y}`;
|
|
6953
7052
|
}).join(" ");
|
|
6954
7053
|
return /* @__PURE__ */ jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
|
|
@@ -6956,7 +7055,7 @@ var AnalysisChart = ({
|
|
|
6956
7055
|
renderLegendItems(
|
|
6957
7056
|
[
|
|
6958
7057
|
{ label: seriesLabels[primarySeriesKey] || primarySeriesKey, color: colors[0] },
|
|
6959
|
-
{ label: seriesLabels[
|
|
7058
|
+
{ label: seriesLabels[effectiveSecondaryKey] || effectiveSecondaryKey, color: colors[2] }
|
|
6960
7059
|
],
|
|
6961
7060
|
8
|
|
6962
7061
|
),
|
|
@@ -7007,13 +7106,14 @@ var AnalysisChart = ({
|
|
|
7007
7106
|
chartType === "histogram" && renderHistogram(),
|
|
7008
7107
|
chartType === "scatter" && renderScatter(false),
|
|
7009
7108
|
chartType === "bubble" && renderScatter(true),
|
|
7010
|
-
chartType === "box" && renderBoxPlot(),
|
|
7109
|
+
(chartType === "box" || chartType === "boxplot") && renderBoxPlot(),
|
|
7011
7110
|
chartType === "waterfall" && renderWaterfall(),
|
|
7012
7111
|
chartType === "heatmap" && renderHeatmap(),
|
|
7013
7112
|
chartType === "crosstab" && renderCrosstab(),
|
|
7014
7113
|
chartType === "radar" && renderRadar(),
|
|
7015
7114
|
chartType === "combo" && renderCombo(),
|
|
7016
|
-
chartType
|
|
7115
|
+
chartType === "3d" && render3D(),
|
|
7116
|
+
(chartType === "bar" || chartType === "line" || chartType === "area" || chartType === "stacked" || chartType === "bar-horizontal" || chartType === "stacked-horizontal" || chartType === "area-horizontal") && /* @__PURE__ */ jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
|
|
7017
7117
|
renderTitle(),
|
|
7018
7118
|
renderLegendItems(
|
|
7019
7119
|
seriesKeys.map((seriesKey, index) => ({
|
|
@@ -7460,6 +7560,13 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
|
|
|
7460
7560
|
if (syncHeightTimerRef.current) clearTimeout(syncHeightTimerRef.current);
|
|
7461
7561
|
};
|
|
7462
7562
|
}, []);
|
|
7563
|
+
const inlineHtml = useMemo(
|
|
7564
|
+
() => (html || "").replace(
|
|
7565
|
+
/<script\b[^>]*\bsrc=["']?[^"'>]*cdn\.plot\.ly[^"'>]*["']?[^>]*><\/script>/gi,
|
|
7566
|
+
""
|
|
7567
|
+
),
|
|
7568
|
+
[html]
|
|
7569
|
+
);
|
|
7463
7570
|
if (mode === "iframe") {
|
|
7464
7571
|
return /* @__PURE__ */ jsx(
|
|
7465
7572
|
"iframe",
|
|
@@ -7470,7 +7577,7 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
|
|
|
7470
7577
|
}
|
|
7471
7578
|
);
|
|
7472
7579
|
}
|
|
7473
|
-
return /* @__PURE__ */ jsx("div", { ref: htmlRef, dangerouslySetInnerHTML: { __html:
|
|
7580
|
+
return /* @__PURE__ */ jsx("div", { ref: htmlRef, dangerouslySetInnerHTML: { __html: inlineHtml }, style });
|
|
7474
7581
|
};
|
|
7475
7582
|
|
|
7476
7583
|
// src/components/DynamicResource/relations/helpers.ts
|
|
@@ -8686,7 +8793,7 @@ function useRoleFilteredModel(model) {
|
|
|
8686
8793
|
}, [model, userRoles]);
|
|
8687
8794
|
}
|
|
8688
8795
|
var _19 = window._ || ((text) => text);
|
|
8689
|
-
var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
|
|
8796
|
+
var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded, beforeTabs }) => {
|
|
8690
8797
|
const model = useRoleFilteredModel(modelProp);
|
|
8691
8798
|
applyI18nLabelsToModel(model);
|
|
8692
8799
|
applyI18nLabelsToModels(allModels);
|
|
@@ -8748,6 +8855,7 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
|
|
|
8748
8855
|
return /* @__PURE__ */ jsxs("div", { className: "jm-tone-scope", style: toneScopeStyle(modelTone), children: [
|
|
8749
8856
|
/* @__PURE__ */ jsx(ToneSharedStyles, {}),
|
|
8750
8857
|
!record ? /* @__PURE__ */ jsx("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: /* @__PURE__ */ jsx(Spin, {}) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
8858
|
+
beforeTabs,
|
|
8751
8859
|
/* @__PURE__ */ jsx(Tabs, { activeKey: activeTabKey, onChange: setActiveTabKey, items: lazyItems, destroyInactiveTabPane: true }),
|
|
8752
8860
|
/* @__PURE__ */ jsx(
|
|
8753
8861
|
ShowFooterButtons,
|
|
@@ -8775,6 +8883,7 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
|
|
|
8775
8883
|
})),
|
|
8776
8884
|
headerButtons,
|
|
8777
8885
|
children: [
|
|
8886
|
+
beforeTabs,
|
|
8778
8887
|
/* @__PURE__ */ jsx(Tabs, { activeKey: activeTabKey, onChange: setActiveTabKey, items: lazyItems, destroyInactiveTabPane: true }),
|
|
8779
8888
|
/* @__PURE__ */ jsx(
|
|
8780
8889
|
ShowFooterButtons,
|
|
@@ -9752,7 +9861,9 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
|
|
|
9752
9861
|
min_width: cell.min_width ?? "",
|
|
9753
9862
|
max_width: cell.max_width ?? "",
|
|
9754
9863
|
min_height: cell.min_height ?? "",
|
|
9755
|
-
max_height: cell.max_height ?? ""
|
|
9864
|
+
max_height: cell.max_height ?? "",
|
|
9865
|
+
chart_url: cell.chart_url ?? "",
|
|
9866
|
+
chart_title: cell.chart_title ?? ""
|
|
9756
9867
|
});
|
|
9757
9868
|
}, [cell, tabId, config, form]);
|
|
9758
9869
|
const handleSave = () => {
|
|
@@ -9768,7 +9879,9 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
|
|
|
9768
9879
|
min_width: values.min_width || null,
|
|
9769
9880
|
max_width: values.max_width || null,
|
|
9770
9881
|
min_height: values.min_height || null,
|
|
9771
|
-
max_height: values.max_height || null
|
|
9882
|
+
max_height: values.max_height || null,
|
|
9883
|
+
chart_url: values.chart_url || void 0,
|
|
9884
|
+
chart_title: values.chart_title || void 0
|
|
9772
9885
|
};
|
|
9773
9886
|
const currentTab = config.tabs.find((t) => t.id === tabId);
|
|
9774
9887
|
const nameUnchanged = currentTab?.name.trim().toLowerCase() === newTabName.toLowerCase();
|
|
@@ -9815,7 +9928,7 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
|
|
|
9815
9928
|
return /* @__PURE__ */ jsx(
|
|
9816
9929
|
Drawer,
|
|
9817
9930
|
{
|
|
9818
|
-
title: cell?.source_type !== "model" ? `Configure section: ${cell?.section_name ?? cell?.model ?? ""}` : `Configure cell: ${cell?.model ?? ""}`,
|
|
9931
|
+
title: cell?.source_type === "plotly_chart" ? `Configure chart: ${cell?.chart_title ?? cell?.model ?? ""}` : cell?.source_type !== "model" ? `Configure section: ${cell?.section_name ?? cell?.model ?? ""}` : `Configure cell: ${cell?.model ?? ""}`,
|
|
9819
9932
|
placement: "right",
|
|
9820
9933
|
width: 380,
|
|
9821
9934
|
open,
|
|
@@ -9843,6 +9956,11 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
|
|
|
9843
9956
|
/* @__PURE__ */ jsx(Divider, { orientation: "left", children: "View" }),
|
|
9844
9957
|
/* @__PURE__ */ jsx(Form.Item, { name: "view_type", label: "View type", children: /* @__PURE__ */ jsx(Select, { options: VIEW_TYPE_OPTIONS }) })
|
|
9845
9958
|
] }),
|
|
9959
|
+
cell?.source_type === "plotly_chart" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9960
|
+
/* @__PURE__ */ jsx(Divider, { orientation: "left", children: "Chart" }),
|
|
9961
|
+
/* @__PURE__ */ jsx(Form.Item, { name: "chart_title", label: "Chart title", children: /* @__PURE__ */ jsx(Input, { placeholder: "e.g. Confidence by Month" }) }),
|
|
9962
|
+
/* @__PURE__ */ jsx(Form.Item, { name: "chart_url", label: "Chart URL", children: /* @__PURE__ */ jsx(Input, { placeholder: "/api/nl-answers-confidence-by-month-chart" }) })
|
|
9963
|
+
] }),
|
|
9846
9964
|
/* @__PURE__ */ jsx(Divider, { orientation: "left", children: "Size" }),
|
|
9847
9965
|
/* @__PURE__ */ jsxs(Space, { wrap: true, children: [
|
|
9848
9966
|
/* @__PURE__ */ jsx(Form.Item, { name: "min_width", label: "Min width", style: { marginBottom: 0 }, children: /* @__PURE__ */ jsx(Input, { placeholder: "e.g. 320px", style: { width: 130 } }) }),
|
|
@@ -10047,6 +10165,13 @@ var SectionsGrid = ({ cells, config, tabId, renderContent, onConfigChange, isCon
|
|
|
10047
10165
|
if (!cells.length) return 1;
|
|
10048
10166
|
return Math.max(...cells.map((c) => c.row)) + 1;
|
|
10049
10167
|
}, [cells]);
|
|
10168
|
+
const soloRows = useMemo(() => {
|
|
10169
|
+
const counts = /* @__PURE__ */ new Map();
|
|
10170
|
+
for (const c of cells) counts.set(c.row, (counts.get(c.row) ?? 0) + 1);
|
|
10171
|
+
const solo = /* @__PURE__ */ new Set();
|
|
10172
|
+
for (const [row, count] of counts) if (count === 1) solo.add(row);
|
|
10173
|
+
return solo;
|
|
10174
|
+
}, [cells]);
|
|
10050
10175
|
const visibleCells = maximizedCellId ? cells.filter((c) => c.id === maximizedCellId) : cells;
|
|
10051
10176
|
const gridStyle = {
|
|
10052
10177
|
display: "grid",
|
|
@@ -10065,7 +10190,7 @@ var SectionsGrid = ({ cells, config, tabId, renderContent, onConfigChange, isCon
|
|
|
10065
10190
|
"div",
|
|
10066
10191
|
{
|
|
10067
10192
|
style: {
|
|
10068
|
-
gridColumn: maximizedCellId ? "1 / -1" : `${cell.col + 1}`,
|
|
10193
|
+
gridColumn: maximizedCellId || soloRows.has(cell.row) ? "1 / -1" : `${cell.col + 1}`,
|
|
10069
10194
|
gridRow: maximizedCellId ? "1 / -1" : `${cell.row + 1}`
|
|
10070
10195
|
},
|
|
10071
10196
|
children: /* @__PURE__ */ jsx(
|
|
@@ -15386,7 +15511,8 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
15386
15511
|
{ label: _34("Heatmap"), value: "heatmap" },
|
|
15387
15512
|
{ label: _34("Crosstab"), value: "crosstab" },
|
|
15388
15513
|
{ label: _34("Radar"), value: "radar" },
|
|
15389
|
-
{ label: _34("Combo (Bar + Line)"), value: "combo" }
|
|
15514
|
+
{ label: _34("Combo (Bar + Line)"), value: "combo" },
|
|
15515
|
+
{ label: _34("3D Scatter"), value: "3d" }
|
|
15390
15516
|
]
|
|
15391
15517
|
}
|
|
15392
15518
|
)
|
|
@@ -16661,7 +16787,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16661
16787
|
if (["true", "1", "t", "yes", "y"].includes(normalized)) value = true;
|
|
16662
16788
|
if (["false", "0", "f", "no", "n"].includes(normalized)) value = false;
|
|
16663
16789
|
}
|
|
16664
|
-
return [{ field: searchField.key, operator: "
|
|
16790
|
+
return [{ field: searchField.key, operator: "contains", value }];
|
|
16665
16791
|
}
|
|
16666
16792
|
});
|
|
16667
16793
|
const [allRowsData, setAllRowsData] = useState([]);
|
|
@@ -19917,7 +20043,8 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
19917
20043
|
{ label: _36("Heatmap"), value: "heatmap" },
|
|
19918
20044
|
{ label: _36("Crosstab"), value: "crosstab" },
|
|
19919
20045
|
{ label: _36("Radar"), value: "radar" },
|
|
19920
|
-
{ label: _36("Combo (Bar + Line)"), value: "combo" }
|
|
20046
|
+
{ label: _36("Combo (Bar + Line)"), value: "combo" },
|
|
20047
|
+
{ label: _36("3D Scatter"), value: "3d" }
|
|
19921
20048
|
]
|
|
19922
20049
|
}
|
|
19923
20050
|
)
|
|
@@ -21077,6 +21204,48 @@ function useDashboardConfig() {
|
|
|
21077
21204
|
}, [apiUrl]);
|
|
21078
21205
|
return { config, enabled, loading, save, reload: load };
|
|
21079
21206
|
}
|
|
21207
|
+
var PlotlyChartContent = ({ chartUrl, refreshNonce }) => {
|
|
21208
|
+
const [chartHtml, setChartHtml] = useState("");
|
|
21209
|
+
const [loading, setLoading] = useState(true);
|
|
21210
|
+
const [error, setError] = useState("");
|
|
21211
|
+
const fetchChart = useCallback(async () => {
|
|
21212
|
+
setLoading(true);
|
|
21213
|
+
setError("");
|
|
21214
|
+
try {
|
|
21215
|
+
const apiUrl = typeof API_URL3 === "string" ? API_URL3 : "";
|
|
21216
|
+
const fullUrl = chartUrl.startsWith("http") ? chartUrl : `${apiUrl}${chartUrl}`;
|
|
21217
|
+
const sep = fullUrl.includes("?") ? "&" : "?";
|
|
21218
|
+
const lang = (() => {
|
|
21219
|
+
try {
|
|
21220
|
+
return (localStorage.getItem("locale") || navigator.language || "en").split("-")[0].toLowerCase();
|
|
21221
|
+
} catch {
|
|
21222
|
+
return "en";
|
|
21223
|
+
}
|
|
21224
|
+
})();
|
|
21225
|
+
const res = await authenticatedFetch(`${fullUrl}${sep}lang=${encodeURIComponent(lang)}`);
|
|
21226
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
21227
|
+
const data = await res.json();
|
|
21228
|
+
setChartHtml(data.chart_html || "");
|
|
21229
|
+
} catch (e) {
|
|
21230
|
+
setError(e?.message ?? String(e));
|
|
21231
|
+
} finally {
|
|
21232
|
+
setLoading(false);
|
|
21233
|
+
}
|
|
21234
|
+
}, [chartUrl]);
|
|
21235
|
+
useEffect(() => {
|
|
21236
|
+
fetchChart();
|
|
21237
|
+
}, [fetchChart, refreshNonce]);
|
|
21238
|
+
if (loading) {
|
|
21239
|
+
return /* @__PURE__ */ jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100%", minHeight: 200 }, children: /* @__PURE__ */ jsx(Spin, {}) });
|
|
21240
|
+
}
|
|
21241
|
+
if (error) {
|
|
21242
|
+
return /* @__PURE__ */ jsx(Empty, { description: `Chart error: ${error}`, style: { padding: 20 }, image: Empty.PRESENTED_IMAGE_SIMPLE });
|
|
21243
|
+
}
|
|
21244
|
+
if (!chartHtml) {
|
|
21245
|
+
return /* @__PURE__ */ jsx(Empty, { description: "No chart data", style: { padding: 20 }, image: Empty.PRESENTED_IMAGE_SIMPLE });
|
|
21246
|
+
}
|
|
21247
|
+
return /* @__PURE__ */ jsx(InlinePlotlyHtml, { html: chartHtml, style: { padding: 8, height: "100%", overflow: "auto" } });
|
|
21248
|
+
};
|
|
21080
21249
|
var DashboardGridCell = ({ cell, allModels, isMaximized, isMinimized, canConfigureLayout, onConfigure, onMaximize, onMinimize, onResize, onMove }) => {
|
|
21081
21250
|
const { token } = theme.useToken();
|
|
21082
21251
|
const model = findModelByName(allModels, cell.model);
|
|
@@ -21109,10 +21278,12 @@ var DashboardGridCell = ({ cell, allModels, isMaximized, isMinimized, canConfigu
|
|
|
21109
21278
|
minHeight: 32,
|
|
21110
21279
|
position: "relative"
|
|
21111
21280
|
};
|
|
21281
|
+
const isPlotlyChart = cell.source_type === "plotly_chart";
|
|
21112
21282
|
const resource = model?.resource || cell.model;
|
|
21113
21283
|
const isModelLike = cell.source_type === "model" || cell.source_type === "named_query";
|
|
21114
|
-
const cellTitle = isModelLike ? model?.label || cell.model : cell.section_name || cell.model;
|
|
21284
|
+
const cellTitle = isPlotlyChart ? cell.chart_title || cell.model : isModelLike ? model?.label || cell.model : cell.section_name || cell.model;
|
|
21115
21285
|
const tone = isModelLike && model ? getModelTone(model) : null;
|
|
21286
|
+
const [chartRefreshNonce, setChartRefreshNonce] = useState(0);
|
|
21116
21287
|
const startResize = useCallback((e, dir) => {
|
|
21117
21288
|
e.preventDefault();
|
|
21118
21289
|
e.stopPropagation();
|
|
@@ -21266,7 +21437,7 @@ var DashboardGridCell = ({ cell, allModels, isMaximized, isMinimized, canConfigu
|
|
|
21266
21437
|
) })
|
|
21267
21438
|
] })
|
|
21268
21439
|
] }),
|
|
21269
|
-
!isMinimized && /* @__PURE__ */ jsx("div", { style: { flex: 1, overflow: "auto", minHeight: 0 }, children: model ? /* @__PURE__ */ jsx(
|
|
21440
|
+
!isMinimized && /* @__PURE__ */ jsx("div", { style: { flex: 1, overflow: "auto", minHeight: 0 }, children: isPlotlyChart && cell.chart_url ? /* @__PURE__ */ jsx(PlotlyChartContent, { chartUrl: cell.chart_url, refreshNonce: chartRefreshNonce }) : model ? /* @__PURE__ */ jsx(
|
|
21270
21441
|
DynamicList,
|
|
21271
21442
|
{
|
|
21272
21443
|
model,
|
|
@@ -21942,6 +22113,6 @@ var authSystemModels = [
|
|
|
21942
22113
|
}
|
|
21943
22114
|
];
|
|
21944
22115
|
|
|
21945
|
-
export { API_URL3 as API_URL, AllModelsProvider, ColorModeContext, ColorModeContextProvider, CommandCenterPortal, CustomSider, DashboardPage, DynamicCreate, DynamicEdit, DynamicList, DynamicShow, ExecutableHtml, GlobalSearch, HierarchyView, HorizontalMenu, InlinePlotlyHtml, LayoutWrapper, LoginPage, ModelHeading, MultiPaneLayout, NavConfigContext, PaneNavigationContext, PinnedRecordsPanel, PrimaryShowContext, RecentActivityPanel, ReferenceField, ResourceContext, SectionsGrid, ShowFooterButtons, StandardList, StandardShow, ViewsGrid, accessControlProvider, authProvider, authSystemModels, authenticatedFetch, buildShowTabFormOptions, generateResources, getModelTone, getNavEntry, guessIcon, httpClient, normalizeToneKey, renderRelationBlock, resolveIcon, setColorSchemas, sortItemsByNavConfig, useAllModels, useKeyboardShortcuts, useMetadataModal, useNavConfig, useNavModules, usePaneNavigation, useRecordSearch, useShowActionsPreferences, useShowEditableForm, useStandardShowTabs };
|
|
22116
|
+
export { API_URL3 as API_URL, AllModelsProvider, AuthenticatedImage, ColorModeContext, ColorModeContextProvider, CommandCenterPortal, CustomSider, DashboardPage, DynamicCreate, DynamicEdit, DynamicList, DynamicShow, ExecutableHtml, GlobalSearch, HierarchyView, HorizontalMenu, InlinePlotlyHtml, LayoutWrapper, LoginPage, ModelHeading, MultiPaneLayout, NavConfigContext, PaneNavigationContext, PinnedRecordsPanel, PrimaryShowContext, RecentActivityPanel, ReferenceField, ResourceContext, SectionsGrid, ShowFooterButtons, StandardList, StandardShow, ViewsGrid, accessControlProvider, authProvider, authSystemModels, authenticatedFetch, buildShowTabFormOptions, generateResources, getModelTone, getNavEntry, guessIcon, httpClient, normalizeToneKey, renderRelationBlock, resolveIcon, setColorSchemas, sortItemsByNavConfig, useAllModels, useAuthenticatedFileUrl, useKeyboardShortcuts, useMetadataModal, useNavConfig, useNavModules, usePaneNavigation, useRecordSearch, useShowActionsPreferences, useShowEditableForm, useStandardShowTabs };
|
|
21946
22117
|
//# sourceMappingURL=index.mjs.map
|
|
21947
22118
|
//# sourceMappingURL=index.mjs.map
|