@juicemantics/veloiq-ui 0.8.5 → 0.9.1
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 +1040 -816
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +303 -81
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var React6 = require('react');
|
|
4
4
|
var antd$1 = require('@refinedev/antd');
|
|
5
5
|
var core = require('@refinedev/core');
|
|
6
6
|
var antd = require('antd');
|
|
@@ -32,7 +32,7 @@ function _interopNamespace(e) {
|
|
|
32
32
|
return Object.freeze(n);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
var
|
|
35
|
+
var React6__default = /*#__PURE__*/_interopDefault(React6);
|
|
36
36
|
var AntDIcons2__namespace = /*#__PURE__*/_interopNamespace(AntDIcons2);
|
|
37
37
|
var dayjs9__default = /*#__PURE__*/_interopDefault(dayjs9);
|
|
38
38
|
var relativeTime2__default = /*#__PURE__*/_interopDefault(relativeTime2);
|
|
@@ -45,10 +45,8 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
|
|
|
45
45
|
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
46
46
|
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
47
47
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), member.set(obj, value), value);
|
|
48
|
-
var ColorModeContext =
|
|
48
|
+
var ColorModeContext = React6.createContext({ mode: "light", setMode: () => {
|
|
49
49
|
}, schemaVersion: 0 });
|
|
50
|
-
|
|
51
|
-
// src/utils/modelTone.ts
|
|
52
50
|
var MODEL_TONES_LIGHT = [
|
|
53
51
|
{ solid: "#2563eb", soft: "#dbeafe", softer: "#eff6ff", text: "#1e3a8a", border: "#93c5fd", shadow: "rgba(37, 99, 235, 0.22)" },
|
|
54
52
|
{ solid: "#0f766e", soft: "#ccfbf1", softer: "#f0fdfa", text: "#115e59", border: "#5eead4", shadow: "rgba(15, 118, 110, 0.22)" },
|
|
@@ -165,6 +163,10 @@ var setColorSchemas = (schemas) => {
|
|
|
165
163
|
const darkBgContent = `rgb(${shade(r, 0.06)}, ${shade(g, 0.06)}, ${shade(b, 0.06)})`;
|
|
166
164
|
const darkBgElements = `rgb(${shade(r, 0.11)}, ${shade(g, 0.11)}, ${shade(b, 0.11)})`;
|
|
167
165
|
const darkBgHover = `rgb(${shade(r, 0.16)}, ${shade(g, 0.16)}, ${shade(b, 0.16)})`;
|
|
166
|
+
const sidebarLightBg = hex;
|
|
167
|
+
const sidebarLightText = isDarkColor(hex) ? "#ffffff" : "#0f172a";
|
|
168
|
+
const sidebarDarkBg = lightBgElements;
|
|
169
|
+
const sidebarDarkText = "#0f172a";
|
|
168
170
|
styleEl.innerHTML = `
|
|
169
171
|
/* --- LIGHT MODE OVERRIDES --- */
|
|
170
172
|
body.jm-light .ant-layout,
|
|
@@ -178,7 +180,31 @@ var setColorSchemas = (schemas) => {
|
|
|
178
180
|
body.jm-light .ant-menu,
|
|
179
181
|
body.jm-light .ant-menu-submenu,
|
|
180
182
|
body.jm-light .ant-menu-submenu-title,
|
|
181
|
-
body.jm-light .ant-layout-header
|
|
183
|
+
body.jm-light .ant-layout-header {
|
|
184
|
+
background-color: ${sidebarLightBg} !important;
|
|
185
|
+
color: ${sidebarLightText} !important;
|
|
186
|
+
}
|
|
187
|
+
body.jm-light .ant-layout-sider *:not(input):not(textarea):not(.ant-input):not(.ant-select-selector):not(.ant-select-selection-item):not(.ant-select-selection-search-input),
|
|
188
|
+
body.jm-light .ant-layout-header *:not(input):not(textarea):not(.ant-input):not(.ant-select-selector):not(.ant-select-selection-item):not(.ant-select-selection-search-input) {
|
|
189
|
+
color: ${sidebarLightText} !important;
|
|
190
|
+
}
|
|
191
|
+
body.jm-light .ant-layout-sider .ant-menu-item-selected,
|
|
192
|
+
body.jm-light .ant-layout-sider .ant-menu-item-selected *,
|
|
193
|
+
body.jm-light .ant-layout-sider .ant-menu-item:hover,
|
|
194
|
+
body.jm-light .ant-layout-sider .ant-menu-item:hover *,
|
|
195
|
+
body.jm-light .ant-layout-header .ant-menu-item-selected,
|
|
196
|
+
body.jm-light .ant-layout-header .ant-menu-item-selected *,
|
|
197
|
+
body.jm-light .ant-layout-header .ant-menu-item:hover,
|
|
198
|
+
body.jm-light .ant-layout-header .ant-menu-item:hover * {
|
|
199
|
+
color: revert !important;
|
|
200
|
+
}
|
|
201
|
+
body.jm-light .ant-menu-submenu-popup {
|
|
202
|
+
background-color: ${sidebarLightBg} !important;
|
|
203
|
+
}
|
|
204
|
+
body.jm-light .ant-menu-submenu-popup .ant-menu-item:not(.ant-menu-item-selected),
|
|
205
|
+
body.jm-light .ant-menu-submenu-popup .ant-menu-submenu-title:not(.ant-menu-submenu-selected) {
|
|
206
|
+
color: ${sidebarLightText} !important;
|
|
207
|
+
}
|
|
182
208
|
body.jm-light .ant-card,
|
|
183
209
|
body.jm-light .ant-table-wrapper .ant-table,
|
|
184
210
|
body.jm-light .ant-table-thead > tr > th,
|
|
@@ -208,7 +234,31 @@ var setColorSchemas = (schemas) => {
|
|
|
208
234
|
body.jm-dark .ant-menu,
|
|
209
235
|
body.jm-dark .ant-menu-submenu,
|
|
210
236
|
body.jm-dark .ant-menu-submenu-title,
|
|
211
|
-
body.jm-dark .ant-layout-header
|
|
237
|
+
body.jm-dark .ant-layout-header {
|
|
238
|
+
background-color: ${sidebarDarkBg} !important;
|
|
239
|
+
color: ${sidebarDarkText} !important;
|
|
240
|
+
}
|
|
241
|
+
body.jm-dark .ant-layout-sider *:not(input):not(textarea):not(.ant-input):not(.ant-select-selector):not(.ant-select-selection-item):not(.ant-select-selection-search-input),
|
|
242
|
+
body.jm-dark .ant-layout-header *:not(input):not(textarea):not(.ant-input):not(.ant-select-selector):not(.ant-select-selection-item):not(.ant-select-selection-search-input) {
|
|
243
|
+
color: ${sidebarDarkText} !important;
|
|
244
|
+
}
|
|
245
|
+
body.jm-dark .ant-layout-sider .ant-menu-item-selected,
|
|
246
|
+
body.jm-dark .ant-layout-sider .ant-menu-item-selected *,
|
|
247
|
+
body.jm-dark .ant-layout-sider .ant-menu-item:hover,
|
|
248
|
+
body.jm-dark .ant-layout-sider .ant-menu-item:hover *,
|
|
249
|
+
body.jm-dark .ant-layout-header .ant-menu-item-selected,
|
|
250
|
+
body.jm-dark .ant-layout-header .ant-menu-item-selected *,
|
|
251
|
+
body.jm-dark .ant-layout-header .ant-menu-item:hover,
|
|
252
|
+
body.jm-dark .ant-layout-header .ant-menu-item:hover * {
|
|
253
|
+
color: revert !important;
|
|
254
|
+
}
|
|
255
|
+
body.jm-dark .ant-menu-submenu-popup {
|
|
256
|
+
background-color: ${sidebarDarkBg} !important;
|
|
257
|
+
}
|
|
258
|
+
body.jm-dark .ant-menu-submenu-popup .ant-menu-item:not(.ant-menu-item-selected),
|
|
259
|
+
body.jm-dark .ant-menu-submenu-popup .ant-menu-submenu-title:not(.ant-menu-submenu-selected) {
|
|
260
|
+
color: ${sidebarDarkText} !important;
|
|
261
|
+
}
|
|
212
262
|
body.jm-dark .ant-card,
|
|
213
263
|
body.jm-dark .ant-table-wrapper .ant-table,
|
|
214
264
|
body.jm-dark .ant-table-thead > tr > th,
|
|
@@ -259,7 +309,7 @@ var getModelTone = (modelLike, darkMode) => {
|
|
|
259
309
|
return tones[hashString(seed) % tones.length];
|
|
260
310
|
};
|
|
261
311
|
var useModelTone = (modelLike) => {
|
|
262
|
-
const { mode, schemaVersion } =
|
|
312
|
+
const { mode, schemaVersion } = React6.useContext(ColorModeContext);
|
|
263
313
|
return getModelTone(modelLike, mode === "dark");
|
|
264
314
|
};
|
|
265
315
|
var getContrastingTextColor = (background) => isDarkColor(background) ? "#f8fafc" : "#0f172a";
|
|
@@ -308,7 +358,7 @@ function guessIcon(text, isModule = false) {
|
|
|
308
358
|
function resolveIcon(iconName) {
|
|
309
359
|
const registry = AntDIcons2__namespace;
|
|
310
360
|
const IconCls = registry[iconName];
|
|
311
|
-
return IconCls ?
|
|
361
|
+
return IconCls ? React6__default.default.createElement(IconCls) : React6__default.default.createElement(registry["TableOutlined"]);
|
|
312
362
|
}
|
|
313
363
|
function getNavEntry(navConfig, key) {
|
|
314
364
|
return navConfig.find((e) => e.key === key);
|
|
@@ -339,8 +389,8 @@ var authenticatedFetch = (url, options = {}) => {
|
|
|
339
389
|
var API_URL = "/api";
|
|
340
390
|
var JOURNEY_ICON_NAME = "NodeIndexOutlined";
|
|
341
391
|
function useJourneyMenuItems() {
|
|
342
|
-
const [byModule, setByModule] =
|
|
343
|
-
|
|
392
|
+
const [byModule, setByModule] = React6.useState({});
|
|
393
|
+
React6.useEffect(() => {
|
|
344
394
|
let cancelled = false;
|
|
345
395
|
(async () => {
|
|
346
396
|
var _a;
|
|
@@ -396,6 +446,7 @@ function injectJourneyMenuItems(items, byModule) {
|
|
|
396
446
|
return walk(items);
|
|
397
447
|
}
|
|
398
448
|
var HorizontalMenu = ({ navConfig = [] }) => {
|
|
449
|
+
const { mode } = React6.useContext(ColorModeContext);
|
|
399
450
|
const { menuItems, selectedKey } = core.useMenu();
|
|
400
451
|
const go = core.useGo();
|
|
401
452
|
const journeysByModule = useJourneyMenuItems();
|
|
@@ -421,7 +472,7 @@ var HorizontalMenu = ({ navConfig = [] }) => {
|
|
|
421
472
|
const renderLabel = (item, depth, hasChildren) => {
|
|
422
473
|
const label = String(item?.label || item?.name || item?.key || "");
|
|
423
474
|
const isModule = depth === 0 || hasChildren;
|
|
424
|
-
|
|
475
|
+
isModule ? getModelTone(`module:${item?.key || label}`) : getModelTone(resolveModelSeed(item));
|
|
425
476
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
426
477
|
"span",
|
|
427
478
|
{
|
|
@@ -431,7 +482,7 @@ var HorizontalMenu = ({ navConfig = [] }) => {
|
|
|
431
482
|
padding: isModule ? "2px 5px" : "1px 5px",
|
|
432
483
|
borderRadius: 8,
|
|
433
484
|
background: "transparent",
|
|
434
|
-
color:
|
|
485
|
+
color: "inherit",
|
|
435
486
|
fontWeight: 400
|
|
436
487
|
},
|
|
437
488
|
children: label
|
|
@@ -457,6 +508,7 @@ var HorizontalMenu = ({ navConfig = [] }) => {
|
|
|
457
508
|
antd.Menu,
|
|
458
509
|
{
|
|
459
510
|
mode: "horizontal",
|
|
511
|
+
theme: mode === "dark" ? "light" : "dark",
|
|
460
512
|
selectedKeys: [selectedKey],
|
|
461
513
|
items,
|
|
462
514
|
style: {
|
|
@@ -469,7 +521,7 @@ var HorizontalMenu = ({ navConfig = [] }) => {
|
|
|
469
521
|
};
|
|
470
522
|
var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
|
|
471
523
|
const { token } = antd.theme.useToken();
|
|
472
|
-
const { mode } =
|
|
524
|
+
const { mode } = React6.useContext(ColorModeContext);
|
|
473
525
|
const { menuItems, selectedKey } = core.useMenu();
|
|
474
526
|
const go = core.useGo();
|
|
475
527
|
const journeysByModule = useJourneyMenuItems();
|
|
@@ -495,7 +547,7 @@ var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
|
|
|
495
547
|
const renderLabel = (item, depth, hasChildren) => {
|
|
496
548
|
const label = String(item?.label || item?.name || item?.key || "");
|
|
497
549
|
const isModule = depth === 0 || hasChildren;
|
|
498
|
-
|
|
550
|
+
isModule ? getModelTone(`module:${item?.key || label}`) : getModelTone(resolveModelSeed(item));
|
|
499
551
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
500
552
|
"span",
|
|
501
553
|
{
|
|
@@ -505,7 +557,7 @@ var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
|
|
|
505
557
|
padding: isModule ? "3px 8px" : "2px 8px",
|
|
506
558
|
borderRadius: 8,
|
|
507
559
|
background: "transparent",
|
|
508
|
-
color:
|
|
560
|
+
color: "inherit",
|
|
509
561
|
fontWeight: 400
|
|
510
562
|
},
|
|
511
563
|
children: label
|
|
@@ -526,15 +578,15 @@ var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
|
|
|
526
578
|
};
|
|
527
579
|
});
|
|
528
580
|
};
|
|
529
|
-
const sortedMenuItems =
|
|
581
|
+
const sortedMenuItems = React6.useMemo(
|
|
530
582
|
() => navConfig.length > 0 ? sortItemsByNavConfig(menuItems, navConfig) : menuItems,
|
|
531
583
|
[menuItems, navConfig]
|
|
532
584
|
);
|
|
533
|
-
const withJourneys =
|
|
585
|
+
const withJourneys = React6.useMemo(
|
|
534
586
|
() => injectJourneyMenuItems(sortedMenuItems, journeysByModule),
|
|
535
587
|
[sortedMenuItems, journeysByModule]
|
|
536
588
|
);
|
|
537
|
-
const items =
|
|
589
|
+
const items = React6.useMemo(() => transformItems(withJourneys), [withJourneys, mode, navConfig]);
|
|
538
590
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
539
591
|
antd.Layout.Sider,
|
|
540
592
|
{
|
|
@@ -611,30 +663,30 @@ var CustomSider = ({ collapsed, logo, appTitle, navConfig = [] }) => {
|
|
|
611
663
|
}
|
|
612
664
|
);
|
|
613
665
|
};
|
|
614
|
-
var AllModelsContext =
|
|
666
|
+
var AllModelsContext = React6.createContext([]);
|
|
615
667
|
var AllModelsProvider = ({
|
|
616
668
|
models,
|
|
617
669
|
children
|
|
618
670
|
}) => /* @__PURE__ */ jsxRuntime.jsx(AllModelsContext.Provider, { value: models, children });
|
|
619
|
-
var useAllModels = () =>
|
|
671
|
+
var useAllModels = () => React6.useContext(AllModelsContext);
|
|
620
672
|
|
|
621
673
|
// src/hooks/useRecordSearch.ts
|
|
622
674
|
var API_URL2 = "/api";
|
|
623
675
|
function useRecordSearch() {
|
|
624
676
|
const allSystemModels = useAllModels();
|
|
625
|
-
const [searchConfig, setSearchConfig] =
|
|
626
|
-
const [results, setResults] =
|
|
627
|
-
const [searching, setSearching] =
|
|
628
|
-
const debounceRef =
|
|
629
|
-
const abortRef =
|
|
630
|
-
|
|
677
|
+
const [searchConfig, setSearchConfig] = React6.useState(null);
|
|
678
|
+
const [results, setResults] = React6.useState([]);
|
|
679
|
+
const [searching, setSearching] = React6.useState(false);
|
|
680
|
+
const debounceRef = React6.useRef(null);
|
|
681
|
+
const abortRef = React6.useRef(null);
|
|
682
|
+
React6.useEffect(() => {
|
|
631
683
|
authenticatedFetch(`${API_URL2}/config/search`).then((r) => {
|
|
632
684
|
if (!r.ok) throw new Error("unavailable");
|
|
633
685
|
return r.json();
|
|
634
686
|
}).then((d) => setSearchConfig(d)).catch(() => {
|
|
635
687
|
});
|
|
636
688
|
}, []);
|
|
637
|
-
const searchableModels =
|
|
689
|
+
const searchableModels = React6.useMemo(() => {
|
|
638
690
|
if (!searchConfig) return [];
|
|
639
691
|
const entityTypesLower = searchConfig.entity_types.map((e) => e.toLowerCase());
|
|
640
692
|
const preferredFields = searchConfig.attribute_types;
|
|
@@ -667,7 +719,7 @@ function useRecordSearch() {
|
|
|
667
719
|
};
|
|
668
720
|
}).filter((m) => m.searchFields.length > 0);
|
|
669
721
|
}, [allSystemModels, searchConfig]);
|
|
670
|
-
const search =
|
|
722
|
+
const search = React6.useCallback(
|
|
671
723
|
(query) => {
|
|
672
724
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
673
725
|
if (abortRef.current) abortRef.current.abort();
|
|
@@ -728,7 +780,7 @@ function useRecordSearch() {
|
|
|
728
780
|
},
|
|
729
781
|
[searchableModels]
|
|
730
782
|
);
|
|
731
|
-
const clear =
|
|
783
|
+
const clear = React6.useCallback(() => {
|
|
732
784
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
733
785
|
if (abortRef.current) abortRef.current.abort();
|
|
734
786
|
setResults([]);
|
|
@@ -756,10 +808,11 @@ var flattenMenuItems = (items, parentLabel = "") => {
|
|
|
756
808
|
var GlobalSearch = () => {
|
|
757
809
|
const { menuItems } = core.useMenu();
|
|
758
810
|
const navigate = reactRouterDom.useNavigate();
|
|
759
|
-
const [searchText, setSearchText] =
|
|
811
|
+
const [searchText, setSearchText] = React6.useState("");
|
|
760
812
|
const { results: backendResults, searching, search, clear } = useRecordSearch();
|
|
761
|
-
const
|
|
762
|
-
const
|
|
813
|
+
const { token } = antd.theme.useToken();
|
|
814
|
+
const searchableResources = React6.useMemo(() => flattenMenuItems(menuItems), [menuItems]);
|
|
815
|
+
const resourceResults = React6.useMemo(() => {
|
|
763
816
|
const q2 = searchText.toLowerCase().trim();
|
|
764
817
|
if (!q2) return [];
|
|
765
818
|
const matches = searchableResources.filter(
|
|
@@ -780,7 +833,7 @@ var GlobalSearch = () => {
|
|
|
780
833
|
}
|
|
781
834
|
];
|
|
782
835
|
}, [searchText, searchableResources]);
|
|
783
|
-
const backendGroups =
|
|
836
|
+
const backendGroups = React6.useMemo(
|
|
784
837
|
() => backendResults.map((result) => ({
|
|
785
838
|
label: /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Text, { type: "secondary", strong: true, style: { fontSize: 11 }, children: result.modelLabel }),
|
|
786
839
|
options: result.records.map((record) => ({
|
|
@@ -791,14 +844,14 @@ var GlobalSearch = () => {
|
|
|
791
844
|
})),
|
|
792
845
|
[backendResults]
|
|
793
846
|
);
|
|
794
|
-
const onSearch =
|
|
847
|
+
const onSearch = React6.useCallback(
|
|
795
848
|
(value) => {
|
|
796
849
|
setSearchText(value);
|
|
797
850
|
search(value);
|
|
798
851
|
},
|
|
799
852
|
[search]
|
|
800
853
|
);
|
|
801
|
-
const onSelect =
|
|
854
|
+
const onSelect = React6.useCallback(
|
|
802
855
|
(value) => {
|
|
803
856
|
const path = value.replace(/^(nav:|record:)/, "");
|
|
804
857
|
navigate(path);
|
|
@@ -807,13 +860,13 @@ var GlobalSearch = () => {
|
|
|
807
860
|
},
|
|
808
861
|
[navigate, clear]
|
|
809
862
|
);
|
|
810
|
-
const options =
|
|
863
|
+
const options = React6.useMemo(
|
|
811
864
|
() => [...resourceResults, ...backendGroups],
|
|
812
865
|
[resourceResults, backendGroups]
|
|
813
866
|
);
|
|
814
|
-
const [focused, setFocused] =
|
|
815
|
-
const inputRef =
|
|
816
|
-
|
|
867
|
+
const [focused, setFocused] = React6.useState(false);
|
|
868
|
+
const inputRef = React6.useRef(null);
|
|
869
|
+
React6.useEffect(() => {
|
|
817
870
|
const handler = (e) => {
|
|
818
871
|
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "k") {
|
|
819
872
|
e.preventDefault();
|
|
@@ -847,7 +900,7 @@ var GlobalSearch = () => {
|
|
|
847
900
|
suffix: !focused ? /* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Text, { type: "secondary", style: { fontSize: 9 }, children: "\u2303K" }) : void 0,
|
|
848
901
|
allowClear: true,
|
|
849
902
|
size: "small",
|
|
850
|
-
style: !focused ? { paddingInline: 2 } :
|
|
903
|
+
style: !focused ? { paddingInline: 2, color: token.colorText } : { color: token.colorText }
|
|
851
904
|
}
|
|
852
905
|
)
|
|
853
906
|
}
|
|
@@ -859,9 +912,9 @@ var API_URL3 = "/api";
|
|
|
859
912
|
|
|
860
913
|
// src/pages/dashboard/hooks/useRecentActivity.ts
|
|
861
914
|
function useRecentActivity(days) {
|
|
862
|
-
const [data, setData] =
|
|
863
|
-
const [loading, setLoading] =
|
|
864
|
-
const load =
|
|
915
|
+
const [data, setData] = React6.useState(null);
|
|
916
|
+
const [loading, setLoading] = React6.useState(true);
|
|
917
|
+
const load = React6.useCallback(async () => {
|
|
865
918
|
setLoading(true);
|
|
866
919
|
try {
|
|
867
920
|
const params = days !== void 0 ? `?days=${days}` : "";
|
|
@@ -872,7 +925,7 @@ function useRecentActivity(days) {
|
|
|
872
925
|
setLoading(false);
|
|
873
926
|
}
|
|
874
927
|
}, [days]);
|
|
875
|
-
|
|
928
|
+
React6.useEffect(() => {
|
|
876
929
|
load();
|
|
877
930
|
}, [load]);
|
|
878
931
|
return { data, loading, reload: load };
|
|
@@ -903,9 +956,9 @@ function relativeTime(iso) {
|
|
|
903
956
|
return d < 30 ? `${d}d ago` : new Date(iso).toLocaleDateString();
|
|
904
957
|
}
|
|
905
958
|
function usePinnedGroups() {
|
|
906
|
-
const [groups, setGroups] =
|
|
907
|
-
const [loading, setLoading] =
|
|
908
|
-
const load =
|
|
959
|
+
const [groups, setGroups] = React6.useState([]);
|
|
960
|
+
const [loading, setLoading] = React6.useState(false);
|
|
961
|
+
const load = React6.useCallback(async () => {
|
|
909
962
|
setLoading(true);
|
|
910
963
|
try {
|
|
911
964
|
const res = await authenticatedFetch(`${API_URL3}/dashboard/pinned-records`);
|
|
@@ -974,22 +1027,22 @@ var CommandCenterPortal = ({
|
|
|
974
1027
|
}) => {
|
|
975
1028
|
const { menuItems: rawMenuItems } = core.useMenu();
|
|
976
1029
|
const journeysByModule = useJourneyMenuItems();
|
|
977
|
-
const menuItems =
|
|
1030
|
+
const menuItems = React6.useMemo(
|
|
978
1031
|
() => injectJourneyMenuItems(rawMenuItems, journeysByModule),
|
|
979
1032
|
[rawMenuItems, journeysByModule]
|
|
980
1033
|
);
|
|
981
1034
|
const go = core.useGo();
|
|
982
|
-
const searchRef =
|
|
983
|
-
const [query, setQuery] =
|
|
984
|
-
const [activeIdx, setActiveIdx] =
|
|
985
|
-
const [colW, setColW] =
|
|
986
|
-
const colWRef =
|
|
1035
|
+
const searchRef = React6.useRef(null);
|
|
1036
|
+
const [query, setQuery] = React6.useState("");
|
|
1037
|
+
const [activeIdx, setActiveIdx] = React6.useState(-1);
|
|
1038
|
+
const [colW, setColW] = React6.useState([220, 220]);
|
|
1039
|
+
const colWRef = React6.useRef([220, 220]);
|
|
987
1040
|
colWRef.current = colW;
|
|
988
|
-
const dragRef =
|
|
1041
|
+
const dragRef = React6.useRef(null);
|
|
989
1042
|
const { results: backendResults, searching, search, clear } = useRecordSearch();
|
|
990
1043
|
const { groups: pinnedGroups, loading: pinnedLoading, load: loadPinned } = usePinnedGroups();
|
|
991
1044
|
const { data: recentData, reload: reloadRecent } = useRecentActivity(30);
|
|
992
|
-
|
|
1045
|
+
React6.useEffect(() => {
|
|
993
1046
|
if (open) {
|
|
994
1047
|
setQuery("");
|
|
995
1048
|
setActiveIdx(-1);
|
|
@@ -1000,9 +1053,9 @@ var CommandCenterPortal = ({
|
|
|
1000
1053
|
return () => clearTimeout(t);
|
|
1001
1054
|
}
|
|
1002
1055
|
}, [open, clear, loadPinned, reloadRecent]);
|
|
1003
|
-
const navItemIdsRef =
|
|
1004
|
-
const activeIdxRef =
|
|
1005
|
-
|
|
1056
|
+
const navItemIdsRef = React6.useRef([]);
|
|
1057
|
+
const activeIdxRef = React6.useRef(-1);
|
|
1058
|
+
React6.useEffect(() => {
|
|
1006
1059
|
if (!open) return;
|
|
1007
1060
|
const handler = (e) => {
|
|
1008
1061
|
if (e.key === "Escape") {
|
|
@@ -1030,33 +1083,33 @@ var CommandCenterPortal = ({
|
|
|
1030
1083
|
window.addEventListener("keydown", handler);
|
|
1031
1084
|
return () => window.removeEventListener("keydown", handler);
|
|
1032
1085
|
}, [open, onClose]);
|
|
1033
|
-
const parsedCommand =
|
|
1034
|
-
|
|
1086
|
+
const parsedCommand = React6.useMemo(() => parseCommand(query.toLowerCase().trim()), [query]);
|
|
1087
|
+
React6.useEffect(() => {
|
|
1035
1088
|
if (parsedCommand) {
|
|
1036
1089
|
clear();
|
|
1037
1090
|
} else {
|
|
1038
1091
|
search(query.toLowerCase().trim());
|
|
1039
1092
|
}
|
|
1040
1093
|
}, [query, parsedCommand, search, clear]);
|
|
1041
|
-
const allModelChildren =
|
|
1094
|
+
const allModelChildren = React6.useMemo(
|
|
1042
1095
|
() => menuItems.flatMap(
|
|
1043
1096
|
(m) => (m.children || []).filter((c) => !c.meta?.hide).map((c) => ({ ...c, moduleLabel: String(m.label || m.name || "") }))
|
|
1044
1097
|
),
|
|
1045
1098
|
[menuItems]
|
|
1046
1099
|
);
|
|
1047
|
-
const commandSuggestions =
|
|
1100
|
+
const commandSuggestions = React6.useMemo(() => {
|
|
1048
1101
|
if (!parsedCommand) return [];
|
|
1049
1102
|
const mq = parsedCommand.modelQuery;
|
|
1050
1103
|
const children = mq ? allModelChildren.filter((c) => (c.label || "").toLowerCase().includes(mq) || (c.name || "").toLowerCase().includes(mq)) : allModelChildren;
|
|
1051
1104
|
return (navConfig.length > 0 ? sortItemsByNavConfig(children, navConfig) : children).slice(0, 8);
|
|
1052
1105
|
}, [parsedCommand, allModelChildren, navConfig]);
|
|
1053
|
-
const searchPlaceholder =
|
|
1106
|
+
const searchPlaceholder = React6.useMemo(() => {
|
|
1054
1107
|
const labels = allModelChildren.slice(0, 2).map((c) => String(c.label || c.name || "").toLowerCase()).filter(Boolean);
|
|
1055
1108
|
if (labels.length === 0) return `Search modules, models, records\u2026`;
|
|
1056
1109
|
const [a, b] = labels;
|
|
1057
1110
|
return b && b !== a ? `Search modules, models, records\u2026 or "list ${a}", "create ${b}"` : `Search modules, models, records\u2026 or "list ${a}", "create ${a}"`;
|
|
1058
1111
|
}, [allModelChildren]);
|
|
1059
|
-
const modules =
|
|
1112
|
+
const modules = React6.useMemo(() => {
|
|
1060
1113
|
const q2 = parsedCommand ? parsedCommand.modelQuery : query.toLowerCase().trim();
|
|
1061
1114
|
const visibleModules = menuItems.filter((item) => item.children && item.children.length > 0).map((item) => ({ ...item, children: (item.children || []).filter((c) => !c.meta?.hide) })).filter((item) => item.children && item.children.length > 0);
|
|
1062
1115
|
const sorted = navConfig.length > 0 ? sortItemsByNavConfig(visibleModules, navConfig) : visibleModules;
|
|
@@ -1070,7 +1123,7 @@ var CommandCenterPortal = ({
|
|
|
1070
1123
|
return moduleMatch ? module : { ...module, children: filteredChildren };
|
|
1071
1124
|
}).filter((m) => m !== null);
|
|
1072
1125
|
}, [menuItems, query, parsedCommand, navConfig]);
|
|
1073
|
-
const pinnedItems =
|
|
1126
|
+
const pinnedItems = React6.useMemo(
|
|
1074
1127
|
() => pinnedGroups.flatMap((g) => g.records.map((r) => ({
|
|
1075
1128
|
resource: g.resource,
|
|
1076
1129
|
modelName: g.model_name,
|
|
@@ -1079,7 +1132,7 @@ var CommandCenterPortal = ({
|
|
|
1079
1132
|
}))),
|
|
1080
1133
|
[pinnedGroups]
|
|
1081
1134
|
);
|
|
1082
|
-
const recentItems =
|
|
1135
|
+
const recentItems = React6.useMemo(() => {
|
|
1083
1136
|
if (!recentData?.groups) return [];
|
|
1084
1137
|
return recentData.groups.flatMap((g) => g.records.map((r) => ({
|
|
1085
1138
|
resource: g.resource,
|
|
@@ -1090,7 +1143,7 @@ var CommandCenterPortal = ({
|
|
|
1090
1143
|
isNew: Boolean(r.created_at && (!r.updated_at || r.updated_at === r.created_at))
|
|
1091
1144
|
}))).sort((a, b) => b.timestamp.localeCompare(a.timestamp));
|
|
1092
1145
|
}, [recentData]);
|
|
1093
|
-
const navItemIds =
|
|
1146
|
+
const navItemIds = React6.useMemo(() => {
|
|
1094
1147
|
const ids = [];
|
|
1095
1148
|
if (parsedCommand) {
|
|
1096
1149
|
for (const child of commandSuggestions)
|
|
@@ -1111,10 +1164,10 @@ var CommandCenterPortal = ({
|
|
|
1111
1164
|
}, [parsedCommand, commandSuggestions, query, pinnedItems, recentItems, backendResults, modules, navConfig]);
|
|
1112
1165
|
navItemIdsRef.current = navItemIds;
|
|
1113
1166
|
activeIdxRef.current = activeIdx;
|
|
1114
|
-
|
|
1167
|
+
React6.useEffect(() => {
|
|
1115
1168
|
setActiveIdx(-1);
|
|
1116
1169
|
}, [navItemIds]);
|
|
1117
|
-
|
|
1170
|
+
React6.useEffect(() => {
|
|
1118
1171
|
if (activeIdx < 0) return;
|
|
1119
1172
|
const id = navItemIds[activeIdx];
|
|
1120
1173
|
if (id) document.querySelector(`[data-navid="${id}"]`)?.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
@@ -1303,7 +1356,7 @@ var CommandCenterPortal = ({
|
|
|
1303
1356
|
/* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Text, { style: SECTION_LABEL_STYLE, children: "Pinned" }),
|
|
1304
1357
|
pinnedLoading && /* @__PURE__ */ jsxRuntime.jsx(antd.Spin, { size: "small", style: { marginLeft: "auto" } })
|
|
1305
1358
|
] }),
|
|
1306
|
-
pinnedItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px 10px", overflowY: "auto", maxHeight: 400 }, children: pinnedItems.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1359
|
+
pinnedItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px 10px", overflowY: "auto", maxHeight: 400 }, children: pinnedItems.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
|
|
1307
1360
|
idx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.04)" } }),
|
|
1308
1361
|
renderRow(
|
|
1309
1362
|
`pin-${item.resource}-${item.id}`,
|
|
@@ -1326,7 +1379,7 @@ var CommandCenterPortal = ({
|
|
|
1326
1379
|
/* @__PURE__ */ jsxRuntime.jsx(AntDIcons2.ClockCircleOutlined, { style: { color: "rgba(255,255,255,0.45)", fontSize: 12 } }),
|
|
1327
1380
|
/* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Text, { style: SECTION_LABEL_STYLE, children: "Recent" })
|
|
1328
1381
|
] }),
|
|
1329
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px 10px", overflowY: "auto", maxHeight: 400 }, children: recentItems.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1382
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px 10px", overflowY: "auto", maxHeight: 400 }, children: recentItems.map((item, idx) => /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
|
|
1330
1383
|
idx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.04)" } }),
|
|
1331
1384
|
renderRow(
|
|
1332
1385
|
`recent-${item.resource}-${item.id}`,
|
|
@@ -1355,7 +1408,7 @@ var CommandCenterPortal = ({
|
|
|
1355
1408
|
const moduleLabel = String(module.label || module.name || "");
|
|
1356
1409
|
const tone = getModelTone(moduleKey);
|
|
1357
1410
|
const children = navConfig.length > 0 ? sortItemsByNavConfig(module.children || [], navConfig) : module.children || [];
|
|
1358
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1411
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
|
|
1359
1412
|
modIdx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "5px 0", borderColor: "rgba(255,255,255,0.06)" } }),
|
|
1360
1413
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6, padding: "4px 8px 2px" }, children: [
|
|
1361
1414
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: tone.solid, fontSize: 12, display: "flex", alignItems: "center" }, children: getItemIcon(moduleKey, moduleLabel, true) }),
|
|
@@ -1366,7 +1419,7 @@ var CommandCenterPortal = ({
|
|
|
1366
1419
|
const childLabel = String(child.label || child.name || "");
|
|
1367
1420
|
const childTone = getModelTone(childKey);
|
|
1368
1421
|
const childIcon = getItemIcon(childKey, childLabel, false, child.icon);
|
|
1369
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1422
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
|
|
1370
1423
|
idx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.04)" } }),
|
|
1371
1424
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1372
1425
|
"div",
|
|
@@ -1418,7 +1471,7 @@ var CommandCenterPortal = ({
|
|
|
1418
1471
|
const moduleLabel = child.moduleLabel || "";
|
|
1419
1472
|
const navId = `cmd-${childKey}`;
|
|
1420
1473
|
const active = isActive(navId);
|
|
1421
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1474
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
|
|
1422
1475
|
idx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.05)" } }),
|
|
1423
1476
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1424
1477
|
"div",
|
|
@@ -1462,13 +1515,13 @@ var CommandCenterPortal = ({
|
|
|
1462
1515
|
] }),
|
|
1463
1516
|
backendResults.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "6px 10px" }, children: backendResults.map((modelResult, modelIdx) => {
|
|
1464
1517
|
const tone = getModelTone(modelResult.resource);
|
|
1465
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1518
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
|
|
1466
1519
|
modelIdx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "4px 0", borderColor: "rgba(255,255,255,0.05)" } }),
|
|
1467
1520
|
/* @__PURE__ */ jsxRuntime.jsx(antd.Typography.Text, { style: { color: "rgba(255,255,255,0.35)", fontSize: 10, textTransform: "uppercase", letterSpacing: "0.07em", display: "block", padding: "4px 10px 2px" }, children: modelResult.modelLabel }),
|
|
1468
1521
|
modelResult.records.map((record, recIdx) => {
|
|
1469
1522
|
const navId = `record-${modelResult.resource}-${record.id}`;
|
|
1470
1523
|
const active = isActive(navId);
|
|
1471
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1524
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
|
|
1472
1525
|
recIdx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.04)" } }),
|
|
1473
1526
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1474
1527
|
"div",
|
|
@@ -1550,7 +1603,7 @@ var CommandCenterPortal = ({
|
|
|
1550
1603
|
const childLabel = String(child.label || child.name || "");
|
|
1551
1604
|
const childTone = getModelTone(childKey);
|
|
1552
1605
|
const childIcon = getItemIcon(childKey, childLabel, false, child.icon);
|
|
1553
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1606
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React6__default.default.Fragment, { children: [
|
|
1554
1607
|
idx > 0 && /* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { style: { margin: "2px 0", borderColor: "rgba(255,255,255,0.05)" } }),
|
|
1555
1608
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1556
1609
|
"div",
|
|
@@ -1584,8 +1637,8 @@ var CommandCenterPortal = ({
|
|
|
1584
1637
|
}
|
|
1585
1638
|
) });
|
|
1586
1639
|
};
|
|
1587
|
-
var NavConfigContext =
|
|
1588
|
-
var useNavConfig = () =>
|
|
1640
|
+
var NavConfigContext = React6.createContext([]);
|
|
1641
|
+
var useNavConfig = () => React6.useContext(NavConfigContext);
|
|
1589
1642
|
function useNavModules() {
|
|
1590
1643
|
const navConfig = useNavConfig();
|
|
1591
1644
|
return (navConfig || []).filter((e) => e.type === "module" && String(e.key || "").startsWith("module:")).map((e) => ({ value: String(e.key).slice("module:".length), label: e.label || String(e.key).slice("module:".length) }));
|
|
@@ -1630,24 +1683,24 @@ var LayoutWrapper = ({
|
|
|
1630
1683
|
extraUserMenuItems = [],
|
|
1631
1684
|
navConfig = []
|
|
1632
1685
|
}) => {
|
|
1633
|
-
const [layoutMode, setLayoutMode] =
|
|
1686
|
+
const [layoutMode, setLayoutMode] = React6.useState(
|
|
1634
1687
|
() => localStorage.getItem("layoutMode") || "vertical"
|
|
1635
1688
|
);
|
|
1636
1689
|
const screens = antd.Grid.useBreakpoint();
|
|
1637
1690
|
const isMobile = !screens.md;
|
|
1638
|
-
const { mode, setMode } =
|
|
1691
|
+
const { mode, setMode } = React6.useContext(ColorModeContext);
|
|
1639
1692
|
const { token } = antd.theme.useToken();
|
|
1640
1693
|
const { data: identity } = core.useGetIdentity();
|
|
1641
1694
|
const { mutate: logout } = core.useLogout();
|
|
1642
1695
|
core.useGo();
|
|
1643
1696
|
const displayName = identity ? [identity.first_name, identity.last_name].filter(Boolean).join(" ") || identity.username || "User" : "User";
|
|
1644
|
-
const [siderCollapsed, setSiderCollapsed] =
|
|
1645
|
-
const [pwdModalOpen, setPwdModalOpen] =
|
|
1646
|
-
const [pwdLoading, setPwdLoading] =
|
|
1697
|
+
const [siderCollapsed, setSiderCollapsed] = React6.useState(() => localStorage.getItem("siderCollapsed") === "true");
|
|
1698
|
+
const [pwdModalOpen, setPwdModalOpen] = React6.useState(false);
|
|
1699
|
+
const [pwdLoading, setPwdLoading] = React6.useState(false);
|
|
1647
1700
|
const [pwdForm] = antd.Form.useForm();
|
|
1648
|
-
const [drawerOpen, setDrawerOpen] =
|
|
1649
|
-
const [portalOpen, setPortalOpen] =
|
|
1650
|
-
|
|
1701
|
+
const [drawerOpen, setDrawerOpen] = React6.useState(false);
|
|
1702
|
+
const [portalOpen, setPortalOpen] = React6.useState(false);
|
|
1703
|
+
React6.useEffect(() => {
|
|
1651
1704
|
const handler = (e) => {
|
|
1652
1705
|
if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === "g") {
|
|
1653
1706
|
e.preventDefault();
|
|
@@ -1833,8 +1886,8 @@ var LayoutWrapper = ({
|
|
|
1833
1886
|
] });
|
|
1834
1887
|
};
|
|
1835
1888
|
var PANE_TOOLBAR_HEIGHT = 28;
|
|
1836
|
-
var PaneNavigationContext =
|
|
1837
|
-
var usePaneNavigation = () =>
|
|
1889
|
+
var PaneNavigationContext = React6.createContext(null);
|
|
1890
|
+
var usePaneNavigation = () => React6.useContext(PaneNavigationContext);
|
|
1838
1891
|
function gt(e, t) {
|
|
1839
1892
|
const n = getComputedStyle(e), o = parseFloat(n.fontSize);
|
|
1840
1893
|
return t * o;
|
|
@@ -3350,19 +3403,19 @@ function Vt(e) {
|
|
|
3350
3403
|
};
|
|
3351
3404
|
}
|
|
3352
3405
|
function Bt() {
|
|
3353
|
-
const [e, t] =
|
|
3406
|
+
const [e, t] = React6.useState({}), n = React6.useCallback(() => t({}), []);
|
|
3354
3407
|
return [e, n];
|
|
3355
3408
|
}
|
|
3356
3409
|
function Le(e) {
|
|
3357
|
-
const t =
|
|
3410
|
+
const t = React6.useId();
|
|
3358
3411
|
return `${e ?? t}`;
|
|
3359
3412
|
}
|
|
3360
|
-
var q = typeof window < "u" ?
|
|
3413
|
+
var q = typeof window < "u" ? React6.useLayoutEffect : React6.useEffect;
|
|
3361
3414
|
function se(e) {
|
|
3362
|
-
const t =
|
|
3415
|
+
const t = React6.useRef(e);
|
|
3363
3416
|
return q(() => {
|
|
3364
3417
|
t.current = e;
|
|
3365
|
-
}, [e]),
|
|
3418
|
+
}, [e]), React6.useCallback(
|
|
3366
3419
|
(...n) => t.current?.(...n),
|
|
3367
3420
|
[t]
|
|
3368
3421
|
);
|
|
@@ -3385,19 +3438,19 @@ function Ce(...e) {
|
|
|
3385
3438
|
});
|
|
3386
3439
|
}
|
|
3387
3440
|
function Re(e) {
|
|
3388
|
-
const t =
|
|
3441
|
+
const t = React6.useRef({ ...e });
|
|
3389
3442
|
return q(() => {
|
|
3390
3443
|
for (const n in e)
|
|
3391
3444
|
t.current[n] = e[n];
|
|
3392
3445
|
}, [e]), t.current;
|
|
3393
3446
|
}
|
|
3394
|
-
var lt =
|
|
3447
|
+
var lt = React6.createContext(null);
|
|
3395
3448
|
function Wt(e, t) {
|
|
3396
|
-
const n =
|
|
3449
|
+
const n = React6.useRef({
|
|
3397
3450
|
getLayout: () => ({}),
|
|
3398
3451
|
setLayout: Ft
|
|
3399
3452
|
});
|
|
3400
|
-
|
|
3453
|
+
React6.useImperativeHandle(t, () => n.current, []), q(() => {
|
|
3401
3454
|
Object.assign(
|
|
3402
3455
|
n.current,
|
|
3403
3456
|
nt({ groupId: e })
|
|
@@ -3423,14 +3476,14 @@ function Ut({
|
|
|
3423
3476
|
style: d,
|
|
3424
3477
|
...S
|
|
3425
3478
|
}) {
|
|
3426
|
-
const z =
|
|
3479
|
+
const z = React6.useRef({
|
|
3427
3480
|
onLayoutChange: {},
|
|
3428
3481
|
onLayoutChanged: {}
|
|
3429
3482
|
}), c = se((x) => {
|
|
3430
3483
|
W(z.current.onLayoutChange, x) || (z.current.onLayoutChange = x, s?.(x));
|
|
3431
3484
|
}), p = se((x) => {
|
|
3432
3485
|
W(z.current.onLayoutChanged, x) || (z.current.onLayoutChanged = x, l?.(x));
|
|
3433
|
-
}), m = Le(a), v =
|
|
3486
|
+
}), m = Le(a), v = React6.useRef(null), [b, y] = Bt(), g = React6.useRef({
|
|
3434
3487
|
lastExpandedPanelSizes: {},
|
|
3435
3488
|
layouts: {},
|
|
3436
3489
|
panels: [],
|
|
@@ -3464,7 +3517,7 @@ function Ut({
|
|
|
3464
3517
|
), w = Re({
|
|
3465
3518
|
defaultLayout: n,
|
|
3466
3519
|
disableCursor: o
|
|
3467
|
-
}), G =
|
|
3520
|
+
}), G = React6.useMemo(
|
|
3468
3521
|
() => ({
|
|
3469
3522
|
get disableCursor() {
|
|
3470
3523
|
return !!w.disableCursor;
|
|
@@ -3516,7 +3569,7 @@ function Ut({
|
|
|
3516
3569
|
}
|
|
3517
3570
|
}),
|
|
3518
3571
|
[M, m, y, u, w]
|
|
3519
|
-
), N =
|
|
3572
|
+
), N = React6.useRef(null);
|
|
3520
3573
|
return q(() => {
|
|
3521
3574
|
const x = v.current;
|
|
3522
3575
|
if (x === null)
|
|
@@ -3582,7 +3635,7 @@ function Ut({
|
|
|
3582
3635
|
u,
|
|
3583
3636
|
b,
|
|
3584
3637
|
w
|
|
3585
|
-
]),
|
|
3638
|
+
]), React6.useEffect(() => {
|
|
3586
3639
|
const x = N.current;
|
|
3587
3640
|
x && (x.mutableState.defaultLayout = n, x.mutableState.disableCursor = !!o);
|
|
3588
3641
|
}), /* @__PURE__ */ jsxRuntime.jsx(lt.Provider, { value: G, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3614,14 +3667,14 @@ function Ut({
|
|
|
3614
3667
|
}
|
|
3615
3668
|
Ut.displayName = "Group";
|
|
3616
3669
|
function Me() {
|
|
3617
|
-
const e =
|
|
3670
|
+
const e = React6.useContext(lt);
|
|
3618
3671
|
return C(
|
|
3619
3672
|
e,
|
|
3620
3673
|
"Group Context not found; did you render a Panel or Separator outside of a Group?"
|
|
3621
3674
|
), e;
|
|
3622
3675
|
}
|
|
3623
3676
|
function qt(e, t) {
|
|
3624
|
-
const { id: n } = Me(), o =
|
|
3677
|
+
const { id: n } = Me(), o = React6.useRef({
|
|
3625
3678
|
collapse: ye,
|
|
3626
3679
|
expand: ye,
|
|
3627
3680
|
getSize: () => ({
|
|
@@ -3631,7 +3684,7 @@ function qt(e, t) {
|
|
|
3631
3684
|
isCollapsed: () => false,
|
|
3632
3685
|
resize: ye
|
|
3633
3686
|
});
|
|
3634
|
-
|
|
3687
|
+
React6.useImperativeHandle(t, () => o.current, []), q(() => {
|
|
3635
3688
|
Object.assign(
|
|
3636
3689
|
o.current,
|
|
3637
3690
|
tt({ groupId: n, panelId: e })
|
|
@@ -3657,7 +3710,7 @@ function Yt({
|
|
|
3657
3710
|
}) {
|
|
3658
3711
|
const c = !!s, p = Le(s), m = Re({
|
|
3659
3712
|
disabled: r
|
|
3660
|
-
}), v =
|
|
3713
|
+
}), v = React6.useRef(null), b = Ce(v, f), {
|
|
3661
3714
|
getPanelStyles: y,
|
|
3662
3715
|
id: g,
|
|
3663
3716
|
orientation: P,
|
|
@@ -3705,14 +3758,14 @@ function Yt({
|
|
|
3705
3758
|
N,
|
|
3706
3759
|
M,
|
|
3707
3760
|
m
|
|
3708
|
-
]),
|
|
3761
|
+
]), React6.useEffect(() => {
|
|
3709
3762
|
w(p, { disabled: r });
|
|
3710
3763
|
}, [r, p, w]), qt(p, d);
|
|
3711
3764
|
const x = () => {
|
|
3712
3765
|
const R = y(g, p);
|
|
3713
3766
|
if (R)
|
|
3714
3767
|
return JSON.stringify(R);
|
|
3715
|
-
}, L =
|
|
3768
|
+
}, L = React6.useSyncExternalStore(
|
|
3716
3769
|
(R) => ze(g, R),
|
|
3717
3770
|
x,
|
|
3718
3771
|
x
|
|
@@ -3826,7 +3879,7 @@ function Qt({
|
|
|
3826
3879
|
const s = Le(r), l = Re({
|
|
3827
3880
|
disabled: n,
|
|
3828
3881
|
disableDoubleClick: o
|
|
3829
|
-
}), [u, h] =
|
|
3882
|
+
}), [u, h] = React6.useState({}), [d, S] = React6.useState("inactive"), [z, c] = React6.useState(false), p = React6.useRef(null), m = Ce(p, i), {
|
|
3830
3883
|
disableCursor: v,
|
|
3831
3884
|
id: b,
|
|
3832
3885
|
orientation: y,
|
|
@@ -3870,7 +3923,7 @@ function Qt({
|
|
|
3870
3923
|
k(), R(), L();
|
|
3871
3924
|
};
|
|
3872
3925
|
}
|
|
3873
|
-
}, [b, s, g, l]),
|
|
3926
|
+
}, [b, s, g, l]), React6.useEffect(() => {
|
|
3874
3927
|
P(s, { disabled: n, disableDoubleClick: o });
|
|
3875
3928
|
}, [n, o, s, P]);
|
|
3876
3929
|
let w;
|
|
@@ -3924,10 +3977,10 @@ Qt.displayName = "Separator";
|
|
|
3924
3977
|
var _3 = window._ || ((text) => text);
|
|
3925
3978
|
var NARROW_BREAKPOINT = 768;
|
|
3926
3979
|
var useIsNarrow = (breakpoint = NARROW_BREAKPOINT) => {
|
|
3927
|
-
const [narrow, setNarrow] =
|
|
3980
|
+
const [narrow, setNarrow] = React6.useState(
|
|
3928
3981
|
() => typeof window !== "undefined" ? window.innerWidth < breakpoint : false
|
|
3929
3982
|
);
|
|
3930
|
-
|
|
3983
|
+
React6.useEffect(() => {
|
|
3931
3984
|
const handler = () => setNarrow(window.innerWidth < breakpoint);
|
|
3932
3985
|
window.addEventListener("resize", handler);
|
|
3933
3986
|
return () => window.removeEventListener("resize", handler);
|
|
@@ -3950,8 +4003,8 @@ var ActionsButtonStack = ({ direction, children }) => /* @__PURE__ */ jsxRuntime
|
|
|
3950
4003
|
var VerticalActionsLayout = ({ position, onBarMount, children }) => {
|
|
3951
4004
|
const { token } = antd.theme.useToken();
|
|
3952
4005
|
const narrow = useIsNarrow();
|
|
3953
|
-
const [drawerOpen, setDrawerOpen] =
|
|
3954
|
-
const mountRef =
|
|
4006
|
+
const [drawerOpen, setDrawerOpen] = React6.useState(false);
|
|
4007
|
+
const mountRef = React6.useCallback(
|
|
3955
4008
|
(el) => onBarMount(el),
|
|
3956
4009
|
[onBarMount]
|
|
3957
4010
|
);
|
|
@@ -4280,9 +4333,9 @@ var splitRelations = (relations = []) => {
|
|
|
4280
4333
|
};
|
|
4281
4334
|
var useViewConfigurations = (modelName, viewType) => {
|
|
4282
4335
|
const apiUrl = core.useApiUrl();
|
|
4283
|
-
const [rows, setRows] =
|
|
4284
|
-
const [loading, setLoading] =
|
|
4285
|
-
|
|
4336
|
+
const [rows, setRows] = React6.useState([]);
|
|
4337
|
+
const [loading, setLoading] = React6.useState(!!modelName);
|
|
4338
|
+
React6.useEffect(() => {
|
|
4286
4339
|
if (!modelName) {
|
|
4287
4340
|
setLoading(false);
|
|
4288
4341
|
return;
|
|
@@ -4318,9 +4371,9 @@ var normalizeActionsPosition = (raw) => {
|
|
|
4318
4371
|
};
|
|
4319
4372
|
var useViewSettings = () => {
|
|
4320
4373
|
const apiUrl = core.useApiUrl();
|
|
4321
|
-
const [settings, setSettings] =
|
|
4322
|
-
const [loading, setLoading] =
|
|
4323
|
-
|
|
4374
|
+
const [settings, setSettings] = React6.useState(null);
|
|
4375
|
+
const [loading, setLoading] = React6.useState(true);
|
|
4376
|
+
React6.useEffect(() => {
|
|
4324
4377
|
let cancelled = false;
|
|
4325
4378
|
const fetchSettings = async () => {
|
|
4326
4379
|
try {
|
|
@@ -4675,7 +4728,7 @@ var extractButtonLabel = (node) => {
|
|
|
4675
4728
|
}
|
|
4676
4729
|
return null;
|
|
4677
4730
|
}
|
|
4678
|
-
if (
|
|
4731
|
+
if (React6__default.default.isValidElement(node)) {
|
|
4679
4732
|
return extractButtonLabel(node.props?.children);
|
|
4680
4733
|
}
|
|
4681
4734
|
return null;
|
|
@@ -4692,14 +4745,14 @@ var renderIconOnlyButtons = (nodes) => {
|
|
|
4692
4745
|
const enhanceNode = (node, index) => {
|
|
4693
4746
|
if (node === null || node === void 0 || typeof node === "boolean") return node;
|
|
4694
4747
|
if (Array.isArray(node)) return node.map((child, childIndex) => enhanceNode(child, childIndex));
|
|
4695
|
-
if (!
|
|
4748
|
+
if (!React6__default.default.isValidElement(node)) return node;
|
|
4696
4749
|
const componentName = node.type?.displayName || node.type?.name;
|
|
4697
4750
|
if (componentName === "RefreshButton") return null;
|
|
4698
4751
|
const fallbackLabel = componentName ? fallbackLabels[componentName] : null;
|
|
4699
4752
|
const nodeProps = node.props;
|
|
4700
4753
|
if (fallbackLabel) {
|
|
4701
4754
|
const label = extractButtonLabel(nodeProps?.children) || fallbackLabel;
|
|
4702
|
-
const element =
|
|
4755
|
+
const element = React6__default.default.cloneElement(node, {
|
|
4703
4756
|
...nodeProps,
|
|
4704
4757
|
hideText: true,
|
|
4705
4758
|
children: null
|
|
@@ -4710,7 +4763,7 @@ var renderIconOnlyButtons = (nodes) => {
|
|
|
4710
4763
|
if (nodeProps?.icon) {
|
|
4711
4764
|
const label = extractButtonLabel(nodeProps?.children);
|
|
4712
4765
|
if (label) {
|
|
4713
|
-
const element =
|
|
4766
|
+
const element = React6__default.default.cloneElement(node, {
|
|
4714
4767
|
...nodeProps,
|
|
4715
4768
|
children: null
|
|
4716
4769
|
});
|
|
@@ -4718,15 +4771,15 @@ var renderIconOnlyButtons = (nodes) => {
|
|
|
4718
4771
|
}
|
|
4719
4772
|
}
|
|
4720
4773
|
if (nodeProps?.children) {
|
|
4721
|
-
const mappedChildren =
|
|
4722
|
-
return
|
|
4774
|
+
const mappedChildren = React6__default.default.Children.map(nodeProps.children, (child, childIndex) => enhanceNode(child, childIndex));
|
|
4775
|
+
return React6__default.default.cloneElement(node, {
|
|
4723
4776
|
...nodeProps,
|
|
4724
4777
|
children: mappedChildren
|
|
4725
4778
|
});
|
|
4726
4779
|
}
|
|
4727
4780
|
return node;
|
|
4728
4781
|
};
|
|
4729
|
-
return
|
|
4782
|
+
return React6__default.default.Children.map(nodes, (child, index) => enhanceNode(child, index));
|
|
4730
4783
|
};
|
|
4731
4784
|
var ResponsiveHeaderButtons = ({ children }) => {
|
|
4732
4785
|
const screens = antd.Grid.useBreakpoint();
|
|
@@ -4777,7 +4830,7 @@ var extractButtonLabel2 = (node) => {
|
|
|
4777
4830
|
}
|
|
4778
4831
|
return null;
|
|
4779
4832
|
}
|
|
4780
|
-
if (
|
|
4833
|
+
if (React6__default.default.isValidElement(node)) {
|
|
4781
4834
|
return extractButtonLabel2(node.props?.children);
|
|
4782
4835
|
}
|
|
4783
4836
|
return null;
|
|
@@ -4795,12 +4848,12 @@ var renderIconOnlyButtons2 = (nodes) => {
|
|
|
4795
4848
|
const enhanceNode = (node, index) => {
|
|
4796
4849
|
if (node === null || node === void 0 || typeof node === "boolean") return node;
|
|
4797
4850
|
if (Array.isArray(node)) return node.map((child, childIndex) => enhanceNode(child, childIndex));
|
|
4798
|
-
if (!
|
|
4851
|
+
if (!React6__default.default.isValidElement(node)) return node;
|
|
4799
4852
|
const componentName = node.type?.displayName || node.type?.name;
|
|
4800
4853
|
const fallbackLabel = componentName ? fallbackLabels[componentName] : null;
|
|
4801
4854
|
if (fallbackLabel) {
|
|
4802
4855
|
const label = extractButtonLabel2(node.props?.children) || fallbackLabel;
|
|
4803
|
-
const element =
|
|
4856
|
+
const element = React6__default.default.cloneElement(node, {
|
|
4804
4857
|
...node.props,
|
|
4805
4858
|
hideText: true,
|
|
4806
4859
|
children: null
|
|
@@ -4811,7 +4864,7 @@ var renderIconOnlyButtons2 = (nodes) => {
|
|
|
4811
4864
|
if (node.props?.icon) {
|
|
4812
4865
|
const label = extractButtonLabel2(node.props?.children);
|
|
4813
4866
|
if (label) {
|
|
4814
|
-
const element =
|
|
4867
|
+
const element = React6__default.default.cloneElement(node, {
|
|
4815
4868
|
...node.props,
|
|
4816
4869
|
children: null
|
|
4817
4870
|
});
|
|
@@ -4819,15 +4872,15 @@ var renderIconOnlyButtons2 = (nodes) => {
|
|
|
4819
4872
|
}
|
|
4820
4873
|
}
|
|
4821
4874
|
if (node.props?.children) {
|
|
4822
|
-
const mappedChildren =
|
|
4823
|
-
return
|
|
4875
|
+
const mappedChildren = React6__default.default.Children.map(node.props.children, (child, childIndex) => enhanceNode(child, childIndex));
|
|
4876
|
+
return React6__default.default.cloneElement(node, {
|
|
4824
4877
|
...node.props,
|
|
4825
4878
|
children: mappedChildren
|
|
4826
4879
|
});
|
|
4827
4880
|
}
|
|
4828
4881
|
return node;
|
|
4829
4882
|
};
|
|
4830
|
-
return
|
|
4883
|
+
return React6__default.default.Children.map(nodes, (child, index) => enhanceNode(child, index));
|
|
4831
4884
|
};
|
|
4832
4885
|
var renderStandardShowHeaderButtons = ({
|
|
4833
4886
|
listButtonProps,
|
|
@@ -4848,8 +4901,8 @@ var useActionsWrapping = (headerButtons) => {
|
|
|
4848
4901
|
const isInMultiPane = Boolean(paneNav);
|
|
4849
4902
|
const isDetailPane = Boolean(paneNav && paneNav.paneIndex > 0);
|
|
4850
4903
|
const actionsPosition = viewSettings?.generalActionsButtonPosition || "top-right";
|
|
4851
|
-
const [verticalBarEl, setVerticalBarEl] =
|
|
4852
|
-
const [topRightEl, setTopRightEl] =
|
|
4904
|
+
const [verticalBarEl, setVerticalBarEl] = React6.useState(null);
|
|
4905
|
+
const [topRightEl, setTopRightEl] = React6.useState(null);
|
|
4853
4906
|
const wrappedHeaderButtons = (ctx) => {
|
|
4854
4907
|
const raw = typeof headerButtons === "function" ? headerButtons(ctx) : headerButtons;
|
|
4855
4908
|
if (actionsPosition === "top-right") {
|
|
@@ -4955,7 +5008,7 @@ var StandardCreate = ({ headerButtons, ...props }) => {
|
|
|
4955
5008
|
] });
|
|
4956
5009
|
};
|
|
4957
5010
|
function useKeyboardShortcuts(shortcuts) {
|
|
4958
|
-
|
|
5011
|
+
React6.useEffect(() => {
|
|
4959
5012
|
const handler = (e) => {
|
|
4960
5013
|
for (const shortcut of shortcuts) {
|
|
4961
5014
|
const keyMatch = e.key.toLowerCase() === shortcut.key.toLowerCase();
|
|
@@ -4991,7 +5044,7 @@ var wrappedPageTitleStyle2 = {
|
|
|
4991
5044
|
};
|
|
4992
5045
|
var renderWrappedPageTitle = (title) => {
|
|
4993
5046
|
if (title === null || title === void 0 || title === false) return title;
|
|
4994
|
-
return
|
|
5047
|
+
return React6__default.default.createElement("div", { style: wrappedPageTitleStyle2 }, title);
|
|
4995
5048
|
};
|
|
4996
5049
|
var numberFormatter = new Intl.NumberFormat(void 0, { maximumFractionDigits: 0 });
|
|
4997
5050
|
var decimalFormatter = new Intl.NumberFormat(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
@@ -5107,6 +5160,39 @@ var getSortPriority = (columnSort, fieldKey) => {
|
|
|
5107
5160
|
const index = columnSort.findIndex((item) => item.fieldKey === fieldKey);
|
|
5108
5161
|
return index === -1 ? 1 : columnSort.length - index + 1;
|
|
5109
5162
|
};
|
|
5163
|
+
var _TOKEN_KEY = "jm_access_token";
|
|
5164
|
+
function useAuthenticatedFileUrl(rawUrl) {
|
|
5165
|
+
const [src, setSrc] = React6.useState("");
|
|
5166
|
+
React6.useEffect(() => {
|
|
5167
|
+
if (!rawUrl) {
|
|
5168
|
+
setSrc("");
|
|
5169
|
+
return;
|
|
5170
|
+
}
|
|
5171
|
+
if (!rawUrl.includes("/api/file/")) {
|
|
5172
|
+
setSrc(rawUrl);
|
|
5173
|
+
return;
|
|
5174
|
+
}
|
|
5175
|
+
const token = localStorage.getItem(_TOKEN_KEY) || "";
|
|
5176
|
+
const controller = new AbortController();
|
|
5177
|
+
let objectUrl = "";
|
|
5178
|
+
fetch(rawUrl, {
|
|
5179
|
+
headers: token ? { Authorization: `Bearer ${token}` } : {},
|
|
5180
|
+
signal: controller.signal
|
|
5181
|
+
}).then((r) => r.ok ? r.blob() : Promise.reject()).then((blob) => {
|
|
5182
|
+
objectUrl = URL.createObjectURL(blob);
|
|
5183
|
+
setSrc(objectUrl);
|
|
5184
|
+
}).catch(() => setSrc(""));
|
|
5185
|
+
return () => {
|
|
5186
|
+
controller.abort();
|
|
5187
|
+
if (objectUrl) URL.revokeObjectURL(objectUrl);
|
|
5188
|
+
};
|
|
5189
|
+
}, [rawUrl]);
|
|
5190
|
+
return src;
|
|
5191
|
+
}
|
|
5192
|
+
var AuthenticatedImage = ({ url, alt, style }) => {
|
|
5193
|
+
const src = useAuthenticatedFileUrl(url);
|
|
5194
|
+
return src ? /* @__PURE__ */ jsxRuntime.jsx("img", { src, alt: alt ?? "", style }) : null;
|
|
5195
|
+
};
|
|
5110
5196
|
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set(["png", "jpg", "jpeg", "gif", "bmp", "webp", "svg", "tif", "tiff"]);
|
|
5111
5197
|
var isImageRecord = (record) => {
|
|
5112
5198
|
if (record?.avatar_url || record?.image_url || record?.photo_url) return true;
|
|
@@ -5164,7 +5250,7 @@ var renderSharedGalleryCard = ({
|
|
|
5164
5250
|
style: { width: imageWidth, display: "grid", gap: 6, cursor: onClick ? "pointer" : "default" },
|
|
5165
5251
|
onClick,
|
|
5166
5252
|
children: [
|
|
5167
|
-
contentUrl ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
5253
|
+
contentUrl ? /* @__PURE__ */ jsxRuntime.jsx(AuthenticatedImage, { url: contentUrl, alt: label, style: imageStyle }) : /* @__PURE__ */ jsxRuntime.jsx("div", { style: { ...imageStyle, display: "flex", alignItems: "center", justifyContent: "center", color: "#8c8c8c" }, children: /* @__PURE__ */ jsxRuntime.jsx(AntDIcons2.FileTextOutlined, { style: { fontSize: 24 } }) }),
|
|
5168
5254
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { fontSize: 12, color: textColor, whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }, children: label })
|
|
5169
5255
|
]
|
|
5170
5256
|
},
|
|
@@ -5538,7 +5624,7 @@ var ReferenceField = ({ id, resource, onLabel }) => {
|
|
|
5538
5624
|
const go = core.useGo();
|
|
5539
5625
|
const paneNav = usePaneNavigation();
|
|
5540
5626
|
const { token } = antd.theme.useToken();
|
|
5541
|
-
|
|
5627
|
+
React6.useEffect(() => {
|
|
5542
5628
|
if (onLabel && !isLoading && label !== void 0 && label !== null) {
|
|
5543
5629
|
onLabel(String(label));
|
|
5544
5630
|
}
|
|
@@ -5565,8 +5651,8 @@ var ReferenceField = ({ id, resource, onLabel }) => {
|
|
|
5565
5651
|
};
|
|
5566
5652
|
dayjs9__default.default.extend(relativeTime2__default.default);
|
|
5567
5653
|
var _8 = window._ || ((text) => text);
|
|
5568
|
-
var ReactMarkdown =
|
|
5569
|
-
var QRCodeSVG =
|
|
5654
|
+
var ReactMarkdown = React6.lazy(() => import('react-markdown').then((m) => ({ default: m.default })));
|
|
5655
|
+
var QRCodeSVG = React6.lazy(() => import('qrcode.react').then((m) => ({ default: m.QRCodeSVG })));
|
|
5570
5656
|
function formatDuration(totalSeconds) {
|
|
5571
5657
|
const h = Math.floor(totalSeconds / 3600);
|
|
5572
5658
|
const m = Math.floor(totalSeconds % 3600 / 60);
|
|
@@ -5602,7 +5688,7 @@ var renderFieldViewTypeReadOnly = (token, value, inTable) => {
|
|
|
5602
5688
|
}
|
|
5603
5689
|
);
|
|
5604
5690
|
case "read-only-markdown":
|
|
5605
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5691
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React6.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(antd.Skeleton.Input, { active: true, size: "small", style: { width: 200 } }), children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown, { children: str }) });
|
|
5606
5692
|
case "read-only-json": {
|
|
5607
5693
|
let formatted = str;
|
|
5608
5694
|
try {
|
|
@@ -5649,7 +5735,7 @@ var renderFieldViewTypeReadOnly = (token, value, inTable) => {
|
|
|
5649
5735
|
case "read-only-image-url":
|
|
5650
5736
|
return /* @__PURE__ */ jsxRuntime.jsx("a", { href: str, target: "_blank", rel: "noopener noreferrer", children: /* @__PURE__ */ jsxRuntime.jsx("img", { src: str, alt: "", style: { maxWidth: "100%", maxHeight: 200, objectFit: "contain", borderRadius: 4, display: "block" } }) });
|
|
5651
5737
|
case "read-only-qrcode":
|
|
5652
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
5738
|
+
return /* @__PURE__ */ jsxRuntime.jsx(React6.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(antd.Skeleton.Input, { active: true, size: "small", style: { width: 128 } }), children: /* @__PURE__ */ jsxRuntime.jsx(QRCodeSVG, { value: str, size: 128 }) });
|
|
5653
5739
|
case "read-only-relative": {
|
|
5654
5740
|
const parsed = dayjs9__default.default(str);
|
|
5655
5741
|
if (!parsed.isValid()) return str || "-";
|
|
@@ -5723,23 +5809,23 @@ var CrosstabTable = ({
|
|
|
5723
5809
|
editable
|
|
5724
5810
|
}) => {
|
|
5725
5811
|
const { token } = antd.theme.useToken();
|
|
5726
|
-
const modelField =
|
|
5812
|
+
const modelField = React6.useCallback(
|
|
5727
5813
|
(key) => key ? allFields.find((field) => field.key === key) : void 0,
|
|
5728
5814
|
[allFields]
|
|
5729
5815
|
);
|
|
5730
5816
|
const activeSeriesKeys = cellFieldKeys.length > 0 ? cellFieldKeys : [COUNT_KEY];
|
|
5731
|
-
const seriesLabel =
|
|
5817
|
+
const seriesLabel = React6.useCallback(
|
|
5732
5818
|
(seriesKey) => {
|
|
5733
5819
|
if (seriesKey === COUNT_KEY) return _9("Count");
|
|
5734
5820
|
return cellFieldLabels?.[seriesKey] || modelField(seriesKey)?.label || seriesKey;
|
|
5735
5821
|
},
|
|
5736
5822
|
[cellFieldLabels, modelField]
|
|
5737
5823
|
);
|
|
5738
|
-
const recordId =
|
|
5824
|
+
const recordId = React6.useCallback(
|
|
5739
5825
|
(record) => record?.[editable?.pkField || "eid"] ?? record?.eid ?? record?.id,
|
|
5740
5826
|
[editable?.pkField]
|
|
5741
5827
|
);
|
|
5742
|
-
const effectiveValue =
|
|
5828
|
+
const effectiveValue = React6.useCallback(
|
|
5743
5829
|
(record, fieldKey) => {
|
|
5744
5830
|
if (fieldKey === COUNT_KEY) return 1;
|
|
5745
5831
|
const staged = editable?.getStagedValue?.(recordId(record), fieldKey);
|
|
@@ -5750,7 +5836,7 @@ var CrosstabTable = ({
|
|
|
5750
5836
|
},
|
|
5751
5837
|
[editable, recordId]
|
|
5752
5838
|
);
|
|
5753
|
-
const summarize =
|
|
5839
|
+
const summarize = React6.useCallback(
|
|
5754
5840
|
(values) => {
|
|
5755
5841
|
if (values.length === 0) return 0;
|
|
5756
5842
|
switch (summaryFn) {
|
|
@@ -5778,7 +5864,7 @@ var CrosstabTable = ({
|
|
|
5778
5864
|
const rowFieldDef = modelField(rowField);
|
|
5779
5865
|
const hasColDimension = Boolean(colField);
|
|
5780
5866
|
const hasRowDimension = Boolean(rowField);
|
|
5781
|
-
const pivot =
|
|
5867
|
+
const pivot = React6.useMemo(() => {
|
|
5782
5868
|
const rowLabels2 = [];
|
|
5783
5869
|
const colLabels2 = [];
|
|
5784
5870
|
const cellRecords2 = /* @__PURE__ */ new Map();
|
|
@@ -5798,32 +5884,32 @@ var CrosstabTable = ({
|
|
|
5798
5884
|
return { rowLabels: rowLabels2, colLabels: colLabels2, cellRecords: cellRecords2 };
|
|
5799
5885
|
}, [rows, rowFieldDef, colFieldDef, hasColDimension, formatCategoryValue, activeSeriesKeys]);
|
|
5800
5886
|
const { rowLabels, colLabels, cellRecords } = pivot;
|
|
5801
|
-
const isAggregatedField =
|
|
5887
|
+
const isAggregatedField = React6.useCallback((seriesKey) => {
|
|
5802
5888
|
if (seriesKey === COUNT_KEY) return true;
|
|
5803
5889
|
const field = modelField(seriesKey);
|
|
5804
5890
|
return Boolean(field && field.type === "number" && !field.reference);
|
|
5805
5891
|
}, [modelField]);
|
|
5806
|
-
const cellAllRecords =
|
|
5892
|
+
const cellAllRecords = React6.useCallback(
|
|
5807
5893
|
(rowLabel, colLabel, seriesKey) => {
|
|
5808
5894
|
return cellRecords.get(`${rowLabel}::${colLabel}`)?.get(seriesKey) || [];
|
|
5809
5895
|
},
|
|
5810
5896
|
[cellRecords]
|
|
5811
5897
|
);
|
|
5812
|
-
const contributingRecords =
|
|
5898
|
+
const contributingRecords = React6.useCallback(
|
|
5813
5899
|
(rowLabel, colLabel, seriesKey) => {
|
|
5814
5900
|
const records = cellRecords.get(`${rowLabel}::${colLabel}`)?.get(seriesKey) || [];
|
|
5815
5901
|
return records.filter((rec) => effectiveValue(rec, seriesKey) !== null);
|
|
5816
5902
|
},
|
|
5817
5903
|
[cellRecords, effectiveValue]
|
|
5818
5904
|
);
|
|
5819
|
-
const cellAggregate =
|
|
5905
|
+
const cellAggregate = React6.useCallback(
|
|
5820
5906
|
(rowLabel, colLabel, seriesKey) => {
|
|
5821
5907
|
const values = contributingRecords(rowLabel, colLabel, seriesKey).map((rec) => effectiveValue(rec, seriesKey));
|
|
5822
5908
|
return values.length > 0 ? summarize(values) : null;
|
|
5823
5909
|
},
|
|
5824
5910
|
[contributingRecords, effectiveValue, summarize]
|
|
5825
5911
|
);
|
|
5826
|
-
const seriesMaxes =
|
|
5912
|
+
const seriesMaxes = React6.useMemo(() => {
|
|
5827
5913
|
return activeSeriesKeys.reduce((acc, seriesKey) => {
|
|
5828
5914
|
let maxForSeries = 0;
|
|
5829
5915
|
rowLabels.forEach((rowLabel) => {
|
|
@@ -5836,10 +5922,10 @@ var CrosstabTable = ({
|
|
|
5836
5922
|
return acc;
|
|
5837
5923
|
}, {});
|
|
5838
5924
|
}, [activeSeriesKeys, rowLabels, colLabels, cellAggregate]);
|
|
5839
|
-
const inputRefs =
|
|
5925
|
+
const inputRefs = React6.useRef(/* @__PURE__ */ new Map());
|
|
5840
5926
|
const cellAddr = (r, c) => `${r}:${c}`;
|
|
5841
5927
|
const editableColumns = colLabels.length * activeSeriesKeys.length;
|
|
5842
|
-
const focusCell =
|
|
5928
|
+
const focusCell = React6.useCallback((r, c) => {
|
|
5843
5929
|
if (r < 0 || c < 0 || r >= rowLabels.length || c >= editableColumns) return;
|
|
5844
5930
|
const el = inputRefs.current.get(cellAddr(r, c));
|
|
5845
5931
|
if (el) {
|
|
@@ -5847,7 +5933,7 @@ var CrosstabTable = ({
|
|
|
5847
5933
|
el.select?.();
|
|
5848
5934
|
}
|
|
5849
5935
|
}, [rowLabels.length, editableColumns]);
|
|
5850
|
-
const isSeriesEditable =
|
|
5936
|
+
const isSeriesEditable = React6.useCallback(
|
|
5851
5937
|
(rowLabel, colLabel, seriesKey) => {
|
|
5852
5938
|
if (!editable || seriesKey === COUNT_KEY || !isAggregatedField(seriesKey)) return false;
|
|
5853
5939
|
const n = contributingRecords(rowLabel, colLabel, seriesKey).length;
|
|
@@ -5857,7 +5943,7 @@ var CrosstabTable = ({
|
|
|
5857
5943
|
},
|
|
5858
5944
|
[editable, contributingRecords, summaryFn, isAggregatedField]
|
|
5859
5945
|
);
|
|
5860
|
-
const computeProration =
|
|
5946
|
+
const computeProration = React6.useCallback(
|
|
5861
5947
|
(records, seriesKey, newAggregate) => {
|
|
5862
5948
|
const round2 = (v) => Math.round((v + Number.EPSILON) * 100) / 100;
|
|
5863
5949
|
const n = records.length;
|
|
@@ -5889,7 +5975,7 @@ var CrosstabTable = ({
|
|
|
5889
5975
|
},
|
|
5890
5976
|
[recordId, effectiveValue, summaryFn]
|
|
5891
5977
|
);
|
|
5892
|
-
const commitCellEdit =
|
|
5978
|
+
const commitCellEdit = React6.useCallback(
|
|
5893
5979
|
(rowLabel, colLabel, seriesKey, newAggregate) => {
|
|
5894
5980
|
if (!editable || newAggregate === null || Number.isNaN(newAggregate)) return;
|
|
5895
5981
|
const records = contributingRecords(rowLabel, colLabel, seriesKey);
|
|
@@ -6109,6 +6195,8 @@ var AnalysisChart = ({
|
|
|
6109
6195
|
};
|
|
6110
6196
|
const primarySeriesKey = seriesKeys[0] || "__count__";
|
|
6111
6197
|
const secondarySeriesKey = seriesKeys[1];
|
|
6198
|
+
const resolveNumericField = (fields, n) => fields[Math.min(n, fields.length - 1)] ?? { key: "__count__", label: _10("Count") };
|
|
6199
|
+
const resolveCategoryField = (field1, field2) => field2 ?? field1;
|
|
6112
6200
|
const getNumericValue = (record, key) => {
|
|
6113
6201
|
if (key === "__count__") return 1;
|
|
6114
6202
|
const value = Number(record?.[key]);
|
|
@@ -6525,11 +6613,11 @@ var AnalysisChart = ({
|
|
|
6525
6613
|
] });
|
|
6526
6614
|
};
|
|
6527
6615
|
const renderScatter = (isBubble) => {
|
|
6528
|
-
if (numericFields.length
|
|
6529
|
-
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Scatter needs at least
|
|
6616
|
+
if (numericFields.length === 0) {
|
|
6617
|
+
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Scatter needs at least one numeric field." });
|
|
6530
6618
|
}
|
|
6531
|
-
const xField = numericFields
|
|
6532
|
-
const yField = numericFields
|
|
6619
|
+
const xField = resolveNumericField(numericFields, 0);
|
|
6620
|
+
const yField = resolveNumericField(numericFields, 1);
|
|
6533
6621
|
const points = rawRows.map((row) => {
|
|
6534
6622
|
const x = getNumericValue(row, xField.key);
|
|
6535
6623
|
const y = getNumericValue(row, yField.key);
|
|
@@ -6807,11 +6895,12 @@ var AnalysisChart = ({
|
|
|
6807
6895
|
] });
|
|
6808
6896
|
};
|
|
6809
6897
|
const renderHeatmap = () => {
|
|
6810
|
-
if (!categoryField1
|
|
6811
|
-
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Heatmap needs
|
|
6898
|
+
if (!categoryField1) {
|
|
6899
|
+
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Heatmap needs a category field." });
|
|
6812
6900
|
}
|
|
6901
|
+
const effectiveCat2 = resolveCategoryField(categoryField1, categoryField2);
|
|
6813
6902
|
const cat1Field = modelField(categoryField1);
|
|
6814
|
-
const cat2Field = modelField(
|
|
6903
|
+
const cat2Field = modelField(effectiveCat2);
|
|
6815
6904
|
const rowLabels = [];
|
|
6816
6905
|
const colLabels = [];
|
|
6817
6906
|
const grid = /* @__PURE__ */ new Map();
|
|
@@ -6889,43 +6978,45 @@ var AnalysisChart = ({
|
|
|
6889
6978
|
] });
|
|
6890
6979
|
};
|
|
6891
6980
|
const renderCrosstab = () => {
|
|
6892
|
-
if (!categoryField1
|
|
6893
|
-
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Crosstab needs
|
|
6981
|
+
if (!categoryField1) {
|
|
6982
|
+
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Crosstab needs a category field." });
|
|
6894
6983
|
}
|
|
6984
|
+
const effectiveCat2 = resolveCategoryField(categoryField1, categoryField2);
|
|
6895
6985
|
const cat1Field = modelField(categoryField1);
|
|
6896
|
-
const cat2Field = modelField(
|
|
6986
|
+
const cat2Field = modelField(effectiveCat2);
|
|
6897
6987
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
6898
6988
|
CrosstabTable,
|
|
6899
6989
|
{
|
|
6900
6990
|
rows: rawRows,
|
|
6901
6991
|
rowField: categoryField1,
|
|
6902
|
-
colField:
|
|
6992
|
+
colField: effectiveCat2 ?? categoryField1,
|
|
6903
6993
|
cellFieldKeys: seriesKeys,
|
|
6904
6994
|
cellFieldLabels: seriesLabels,
|
|
6905
6995
|
allFields,
|
|
6906
6996
|
summaryFn,
|
|
6907
6997
|
formatCategoryValue,
|
|
6908
6998
|
numericBarColor,
|
|
6909
|
-
caption: `${_10("Crosstab")}: ${cat1Field?.label || categoryField1} \xD7 ${cat2Field?.label ||
|
|
6999
|
+
caption: `${_10("Crosstab")}: ${cat1Field?.label || categoryField1} \xD7 ${cat2Field?.label || effectiveCat2} (${summaryFn})`
|
|
6910
7000
|
}
|
|
6911
7001
|
);
|
|
6912
7002
|
};
|
|
6913
7003
|
const renderRadar = () => {
|
|
6914
|
-
if (seriesKeys.length
|
|
6915
|
-
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Radar needs at least
|
|
7004
|
+
if (seriesKeys.length === 0) {
|
|
7005
|
+
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "Radar needs at least one series." });
|
|
6916
7006
|
}
|
|
7007
|
+
const effectiveSeriesKeys = seriesKeys.length >= 3 ? seriesKeys : Array.from({ length: 3 }, (_43, i) => seriesKeys[i % seriesKeys.length]);
|
|
6917
7008
|
const centerX = paddingLeft + chartWidth / 2;
|
|
6918
7009
|
const centerY = paddingTop + chartHeight / 2;
|
|
6919
7010
|
const radius = Math.min(chartWidth, chartHeight) * 0.35;
|
|
6920
|
-
const maxBySeries =
|
|
7011
|
+
const maxBySeries = effectiveSeriesKeys.reduce((acc, key) => {
|
|
6921
7012
|
acc[key] = Math.max(...data.map((group) => group.values[key] || 0), 1);
|
|
6922
7013
|
return acc;
|
|
6923
7014
|
}, {});
|
|
6924
|
-
const angleStep = Math.PI * 2 /
|
|
7015
|
+
const angleStep = Math.PI * 2 / effectiveSeriesKeys.length;
|
|
6925
7016
|
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
|
|
6926
7017
|
renderTitle(),
|
|
6927
7018
|
renderCaption("Radar chart"),
|
|
6928
|
-
|
|
7019
|
+
effectiveSeriesKeys.map((seriesKey, index) => {
|
|
6929
7020
|
const angle = -Math.PI / 2 + index * angleStep;
|
|
6930
7021
|
const x = centerX + radius * Math.cos(angle);
|
|
6931
7022
|
const y = centerY + radius * Math.sin(angle);
|
|
@@ -6935,7 +7026,7 @@ var AnalysisChart = ({
|
|
|
6935
7026
|
] }, `radar-axis-${seriesKey}`);
|
|
6936
7027
|
}),
|
|
6937
7028
|
data.map((group, groupIndex) => {
|
|
6938
|
-
const points =
|
|
7029
|
+
const points = effectiveSeriesKeys.map((seriesKey, index) => {
|
|
6939
7030
|
const value = group.values[seriesKey] || 0;
|
|
6940
7031
|
const ratio = value / Math.max(1, maxBySeries[seriesKey]);
|
|
6941
7032
|
const angle = -Math.PI / 2 + index * angleStep;
|
|
@@ -6960,13 +7051,74 @@ var AnalysisChart = ({
|
|
|
6960
7051
|
})
|
|
6961
7052
|
] });
|
|
6962
7053
|
};
|
|
6963
|
-
const
|
|
6964
|
-
if (
|
|
6965
|
-
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "
|
|
7054
|
+
const render3D = () => {
|
|
7055
|
+
if (numericFields.length === 0) {
|
|
7056
|
+
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "3D scatter needs at least one numeric field." });
|
|
6966
7057
|
}
|
|
7058
|
+
const xField = resolveNumericField(numericFields, 0);
|
|
7059
|
+
const yField = resolveNumericField(numericFields, 1);
|
|
7060
|
+
const zField = resolveNumericField(numericFields, 2);
|
|
7061
|
+
const points = rawRows.map((row) => {
|
|
7062
|
+
const x = getNumericValue(row, xField.key);
|
|
7063
|
+
const y = getNumericValue(row, yField.key);
|
|
7064
|
+
const z = getNumericValue(row, zField.key);
|
|
7065
|
+
if (x === null || y === null || z === null) return null;
|
|
7066
|
+
return { x, y, z };
|
|
7067
|
+
}).filter((p) => !!p);
|
|
7068
|
+
if (points.length === 0) return renderNoChartDataMessage();
|
|
7069
|
+
const xs = points.map((p) => p.x);
|
|
7070
|
+
const ys = points.map((p) => p.y);
|
|
7071
|
+
const zs = points.map((p) => p.z);
|
|
7072
|
+
const xMin = Math.min(...xs), xMax = Math.max(...xs);
|
|
7073
|
+
const yMin = Math.min(...ys), yMax = Math.max(...ys);
|
|
7074
|
+
const zMin = Math.min(...zs), zMax = Math.max(...zs);
|
|
7075
|
+
const norm = (v, lo, hi) => hi === lo ? 0.5 : (v - lo) / (hi - lo);
|
|
7076
|
+
const isoScale = Math.min(chartWidth, chartHeight) * 0.38;
|
|
7077
|
+
const cx = paddingLeft + chartWidth * 0.5;
|
|
7078
|
+
const cy = paddingTop + chartHeight * 0.55;
|
|
7079
|
+
const cos30 = Math.cos(Math.PI / 6);
|
|
7080
|
+
const sin30 = Math.sin(Math.PI / 6);
|
|
7081
|
+
const project = (nx, ny, nz) => ({
|
|
7082
|
+
sx: cx + (nx - nz) * cos30 * isoScale,
|
|
7083
|
+
sy: cy - ny * isoScale + (nx + nz) * sin30 * isoScale
|
|
7084
|
+
});
|
|
7085
|
+
const axisEnd = (nx, ny, nz) => project(nx, ny, nz);
|
|
7086
|
+
const origin = project(0, 0, 0);
|
|
7087
|
+
const xTip = axisEnd(1, 0, 0);
|
|
7088
|
+
const yTip = axisEnd(0, 1, 0);
|
|
7089
|
+
const zTip = axisEnd(0, 0, 1);
|
|
7090
|
+
const projected = points.map(
|
|
7091
|
+
(p) => project(norm(p.x, xMin, xMax), norm(p.y, yMin, yMax), norm(p.z, zMin, zMax))
|
|
7092
|
+
);
|
|
7093
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
|
|
7094
|
+
renderTitle(),
|
|
7095
|
+
renderCaption(`3D: ${xField.label} \xD7 ${yField.label} \xD7 ${zField.label}`),
|
|
7096
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: origin.sx, y1: origin.sy, x2: xTip.sx, y2: xTip.sy, stroke: colors[0], strokeWidth: 1.5, opacity: 0.6 }),
|
|
7097
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: origin.sx, y1: origin.sy, x2: yTip.sx, y2: yTip.sy, stroke: colors[1], strokeWidth: 1.5, opacity: 0.6 }),
|
|
7098
|
+
/* @__PURE__ */ jsxRuntime.jsx("line", { x1: origin.sx, y1: origin.sy, x2: zTip.sx, y2: zTip.sy, stroke: colors[2], strokeWidth: 1.5, opacity: 0.6 }),
|
|
7099
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: xTip.sx + 4, y: xTip.sy + 4, fontSize: "11", fill: colors[0], children: xField.label }),
|
|
7100
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: yTip.sx + 4, y: yTip.sy, fontSize: "11", fill: colors[1], children: yField.label }),
|
|
7101
|
+
/* @__PURE__ */ jsxRuntime.jsx("text", { x: zTip.sx + 4, y: zTip.sy + 4, fontSize: "11", fill: colors[2], children: zField.label }),
|
|
7102
|
+
projected.map((p, i) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
7103
|
+
"circle",
|
|
7104
|
+
{
|
|
7105
|
+
className: "chart-item chart-point",
|
|
7106
|
+
style: { "--delay": `${i * 8}ms` },
|
|
7107
|
+
cx: p.sx,
|
|
7108
|
+
cy: p.sy,
|
|
7109
|
+
r: 4,
|
|
7110
|
+
fill: colors[0],
|
|
7111
|
+
opacity: 0.7
|
|
7112
|
+
},
|
|
7113
|
+
`3d-${i}`
|
|
7114
|
+
))
|
|
7115
|
+
] });
|
|
7116
|
+
};
|
|
7117
|
+
const renderCombo = () => {
|
|
7118
|
+
const effectiveSecondaryKey = secondarySeriesKey ?? primarySeriesKey;
|
|
6967
7119
|
const valuesCombo = data.flatMap((group) => [
|
|
6968
7120
|
group.values[primarySeriesKey] || 0,
|
|
6969
|
-
group.values[
|
|
7121
|
+
group.values[effectiveSecondaryKey] || 0
|
|
6970
7122
|
]);
|
|
6971
7123
|
const maxCombo = Math.max(...valuesCombo, 1);
|
|
6972
7124
|
const minCombo = Math.min(...valuesCombo, 0);
|
|
@@ -6975,7 +7127,7 @@ var AnalysisChart = ({
|
|
|
6975
7127
|
const barWidth2 = groupWidth2 * 0.6;
|
|
6976
7128
|
const points = data.map((group, index) => {
|
|
6977
7129
|
const x = paddingLeft + index * groupWidth2 + groupWidth2 / 2;
|
|
6978
|
-
const y = scaleYCombo(group.values[
|
|
7130
|
+
const y = scaleYCombo(group.values[effectiveSecondaryKey] || 0);
|
|
6979
7131
|
return `${x},${y}`;
|
|
6980
7132
|
}).join(" ");
|
|
6981
7133
|
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
|
|
@@ -6983,7 +7135,7 @@ var AnalysisChart = ({
|
|
|
6983
7135
|
renderLegendItems(
|
|
6984
7136
|
[
|
|
6985
7137
|
{ label: seriesLabels[primarySeriesKey] || primarySeriesKey, color: colors[0] },
|
|
6986
|
-
{ label: seriesLabels[
|
|
7138
|
+
{ label: seriesLabels[effectiveSecondaryKey] || effectiveSecondaryKey, color: colors[2] }
|
|
6987
7139
|
],
|
|
6988
7140
|
8
|
|
6989
7141
|
),
|
|
@@ -7034,13 +7186,14 @@ var AnalysisChart = ({
|
|
|
7034
7186
|
chartType === "histogram" && renderHistogram(),
|
|
7035
7187
|
chartType === "scatter" && renderScatter(false),
|
|
7036
7188
|
chartType === "bubble" && renderScatter(true),
|
|
7037
|
-
chartType === "box" && renderBoxPlot(),
|
|
7189
|
+
(chartType === "box" || chartType === "boxplot") && renderBoxPlot(),
|
|
7038
7190
|
chartType === "waterfall" && renderWaterfall(),
|
|
7039
7191
|
chartType === "heatmap" && renderHeatmap(),
|
|
7040
7192
|
chartType === "crosstab" && renderCrosstab(),
|
|
7041
7193
|
chartType === "radar" && renderRadar(),
|
|
7042
7194
|
chartType === "combo" && renderCombo(),
|
|
7043
|
-
chartType
|
|
7195
|
+
chartType === "3d" && render3D(),
|
|
7196
|
+
(chartType === "bar" || chartType === "line" || chartType === "area" || chartType === "stacked" || chartType === "bar-horizontal" || chartType === "stacked-horizontal" || chartType === "area-horizontal") && /* @__PURE__ */ jsxRuntime.jsxs("svg", { ref: svgRef, className: "chart-plot", viewBox: `0 0 ${width} ${height}`, width: "100%", height, role: "img", children: [
|
|
7044
7197
|
renderTitle(),
|
|
7045
7198
|
renderLegendItems(
|
|
7046
7199
|
seriesKeys.map((seriesKey, index) => ({
|
|
@@ -7278,25 +7431,25 @@ var ExecutableHtml = ({
|
|
|
7278
7431
|
inheritTabRowBackground = false,
|
|
7279
7432
|
fontSizeOverride
|
|
7280
7433
|
}) => {
|
|
7281
|
-
const htmlRef =
|
|
7282
|
-
const iframeRef =
|
|
7283
|
-
const observerRef =
|
|
7284
|
-
const appendedChunksRef =
|
|
7285
|
-
const scriptIdRef =
|
|
7286
|
-
const syncHeightTimerRef =
|
|
7287
|
-
const lastSetHeightRef =
|
|
7288
|
-
const [fontFamily, setFontFamily] =
|
|
7289
|
-
const [fontSize, setFontSize] =
|
|
7290
|
-
const [lineHeight, setLineHeight] =
|
|
7291
|
-
const [tabRowBackground, setTabRowBackground] =
|
|
7292
|
-
const { mode: colorMode } =
|
|
7434
|
+
const htmlRef = React6.useRef(null);
|
|
7435
|
+
const iframeRef = React6.useRef(null);
|
|
7436
|
+
const observerRef = React6.useRef(null);
|
|
7437
|
+
const appendedChunksRef = React6.useRef(0);
|
|
7438
|
+
const scriptIdRef = React6.useRef(0);
|
|
7439
|
+
const syncHeightTimerRef = React6.useRef(null);
|
|
7440
|
+
const lastSetHeightRef = React6.useRef(0);
|
|
7441
|
+
const [fontFamily, setFontFamily] = React6.useState("Arial, sans-serif");
|
|
7442
|
+
const [fontSize, setFontSize] = React6.useState("14px");
|
|
7443
|
+
const [lineHeight, setLineHeight] = React6.useState("1.5715");
|
|
7444
|
+
const [tabRowBackground, setTabRowBackground] = React6.useState("#fafafa");
|
|
7445
|
+
const { mode: colorMode } = React6.useContext(ColorModeContext);
|
|
7293
7446
|
const isDark = colorMode === "dark";
|
|
7294
|
-
|
|
7295
|
-
const instanceId =
|
|
7296
|
-
const htmlRefForEffect =
|
|
7447
|
+
React6.useRef(performance.now());
|
|
7448
|
+
const instanceId = React6.useRef(Math.random().toString(36).slice(2, 6));
|
|
7449
|
+
const htmlRefForEffect = React6.useRef(html);
|
|
7297
7450
|
htmlRefForEffect.current = html;
|
|
7298
7451
|
traceLog("ExecutableHtml", `[${instanceId.current}] mount mode=${mode} title=${title} htmlLen=${(html || "").length}`);
|
|
7299
|
-
const executeScriptNodesSequentially =
|
|
7452
|
+
const executeScriptNodesSequentially = React6.useCallback(async (doc, scriptNodes, isCancelled) => {
|
|
7300
7453
|
for (const oldScript of scriptNodes) {
|
|
7301
7454
|
if (isCancelled?.()) return;
|
|
7302
7455
|
const newScript = doc.createElement("script");
|
|
@@ -7318,7 +7471,7 @@ var ExecutableHtml = ({
|
|
|
7318
7471
|
});
|
|
7319
7472
|
}
|
|
7320
7473
|
}, []);
|
|
7321
|
-
|
|
7474
|
+
React6.useEffect(() => {
|
|
7322
7475
|
if (mode !== "inline") return;
|
|
7323
7476
|
const container = htmlRef.current;
|
|
7324
7477
|
if (!container || !html) return;
|
|
@@ -7329,7 +7482,7 @@ var ExecutableHtml = ({
|
|
|
7329
7482
|
cancelled = true;
|
|
7330
7483
|
};
|
|
7331
7484
|
}, [html, mode, executeScriptNodesSequentially]);
|
|
7332
|
-
|
|
7485
|
+
React6.useEffect(() => {
|
|
7333
7486
|
if (mode !== "iframe") return;
|
|
7334
7487
|
if (!inheritTypography && !inheritTabRowBackground) return;
|
|
7335
7488
|
if (typeof window === "undefined") return;
|
|
@@ -7355,7 +7508,7 @@ var ExecutableHtml = ({
|
|
|
7355
7508
|
if (resolvedBg) setTabRowBackground(resolvedBg);
|
|
7356
7509
|
}
|
|
7357
7510
|
}, [inheritTabRowBackground, inheritTypography, mode]);
|
|
7358
|
-
const htmlShell =
|
|
7511
|
+
const htmlShell = React6.useMemo(() => `<!doctype html>
|
|
7359
7512
|
<html>
|
|
7360
7513
|
<head>
|
|
7361
7514
|
<meta charset="utf-8" />
|
|
@@ -7386,7 +7539,7 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
|
|
|
7386
7539
|
</head>
|
|
7387
7540
|
<body></body>
|
|
7388
7541
|
</html>`, [fontFamily, fontSize, lineHeight, tabRowBackground, isDark]);
|
|
7389
|
-
const syncHeight =
|
|
7542
|
+
const syncHeight = React6.useCallback(() => {
|
|
7390
7543
|
if (syncHeightTimerRef.current) clearTimeout(syncHeightTimerRef.current);
|
|
7391
7544
|
syncHeightTimerRef.current = setTimeout(() => {
|
|
7392
7545
|
syncHeightTimerRef.current = null;
|
|
@@ -7404,7 +7557,7 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
|
|
|
7404
7557
|
iframe.style.height = `${nextHeight}px`;
|
|
7405
7558
|
}, 100);
|
|
7406
7559
|
}, [minHeight]);
|
|
7407
|
-
const appendHtmlChunk =
|
|
7560
|
+
const appendHtmlChunk = React6.useCallback(async (chunk) => {
|
|
7408
7561
|
const doc = iframeRef.current?.contentDocument;
|
|
7409
7562
|
if (!doc || !doc.body || !chunk) return false;
|
|
7410
7563
|
const host = doc.createElement("div");
|
|
@@ -7425,7 +7578,7 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
|
|
|
7425
7578
|
syncHeight();
|
|
7426
7579
|
return true;
|
|
7427
7580
|
}, [syncHeight, executeScriptNodesSequentially]);
|
|
7428
|
-
|
|
7581
|
+
React6.useEffect(() => {
|
|
7429
7582
|
if (mode !== "iframe") return;
|
|
7430
7583
|
const iframe = iframeRef.current;
|
|
7431
7584
|
if (!iframe) return;
|
|
@@ -7468,7 +7621,7 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
|
|
|
7468
7621
|
iframe.removeEventListener("load", onLoad);
|
|
7469
7622
|
};
|
|
7470
7623
|
}, [htmlShell, resetToken, appendHtmlChunk, syncHeight, mode]);
|
|
7471
|
-
|
|
7624
|
+
React6.useEffect(() => {
|
|
7472
7625
|
if (mode !== "iframe") return;
|
|
7473
7626
|
if (!htmlChunks || htmlChunks.length <= appendedChunksRef.current) return;
|
|
7474
7627
|
const nextChunks = htmlChunks.slice(appendedChunksRef.current);
|
|
@@ -7480,13 +7633,20 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
|
|
|
7480
7633
|
appendedChunksRef.current += appendedCount;
|
|
7481
7634
|
})();
|
|
7482
7635
|
}, [htmlChunks, appendHtmlChunk, mode]);
|
|
7483
|
-
|
|
7636
|
+
React6.useEffect(() => {
|
|
7484
7637
|
return () => {
|
|
7485
7638
|
if (observerRef.current) observerRef.current.disconnect();
|
|
7486
7639
|
observerRef.current = null;
|
|
7487
7640
|
if (syncHeightTimerRef.current) clearTimeout(syncHeightTimerRef.current);
|
|
7488
7641
|
};
|
|
7489
7642
|
}, []);
|
|
7643
|
+
const inlineHtml = React6.useMemo(
|
|
7644
|
+
() => (html || "").replace(
|
|
7645
|
+
/<script\b[^>]*\bsrc=["']?[^"'>]*cdn\.plot\.ly[^"'>]*["']?[^>]*><\/script>/gi,
|
|
7646
|
+
""
|
|
7647
|
+
),
|
|
7648
|
+
[html]
|
|
7649
|
+
);
|
|
7490
7650
|
if (mode === "iframe") {
|
|
7491
7651
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7492
7652
|
"iframe",
|
|
@@ -7497,7 +7657,7 @@ body, table, th, td, input, button, select, textarea, div, span, p, li, ul, ol {
|
|
|
7497
7657
|
}
|
|
7498
7658
|
);
|
|
7499
7659
|
}
|
|
7500
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: htmlRef, dangerouslySetInnerHTML: { __html:
|
|
7660
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { ref: htmlRef, dangerouslySetInnerHTML: { __html: inlineHtml }, style });
|
|
7501
7661
|
};
|
|
7502
7662
|
|
|
7503
7663
|
// src/components/DynamicResource/relations/helpers.ts
|
|
@@ -7564,23 +7724,23 @@ var MetadataModal = ({ model, allModels, open, onClose }) => {
|
|
|
7564
7724
|
const apiUrl = core.useApiUrl();
|
|
7565
7725
|
const tone = useModelTone(model);
|
|
7566
7726
|
const modelLabel = getModelLabel(model);
|
|
7567
|
-
const [nestedModel, setNestedModel] =
|
|
7568
|
-
const [activeTab, setActiveTab] =
|
|
7569
|
-
const [graphHtml, setGraphHtml] =
|
|
7570
|
-
const [graphLoading, setGraphLoading] =
|
|
7571
|
-
const [graphError, setGraphError] =
|
|
7572
|
-
|
|
7727
|
+
const [nestedModel, setNestedModel] = React6.useState(null);
|
|
7728
|
+
const [activeTab, setActiveTab] = React6.useState("fields");
|
|
7729
|
+
const [graphHtml, setGraphHtml] = React6.useState(null);
|
|
7730
|
+
const [graphLoading, setGraphLoading] = React6.useState(false);
|
|
7731
|
+
const [graphError, setGraphError] = React6.useState(null);
|
|
7732
|
+
React6.useEffect(() => {
|
|
7573
7733
|
setGraphHtml(null);
|
|
7574
7734
|
setGraphError(null);
|
|
7575
7735
|
}, [model.name]);
|
|
7576
|
-
const findRelatedModel =
|
|
7736
|
+
const findRelatedModel = React6.useCallback((name) => {
|
|
7577
7737
|
if (!name || !allModels) return void 0;
|
|
7578
7738
|
const lower = name.toLowerCase();
|
|
7579
7739
|
return allModels.find(
|
|
7580
7740
|
(m) => (m.name || "").toLowerCase() === lower || (m.resource || "").toLowerCase() === lower
|
|
7581
7741
|
);
|
|
7582
7742
|
}, [allModels]);
|
|
7583
|
-
const loadGraph =
|
|
7743
|
+
const loadGraph = React6.useCallback(async () => {
|
|
7584
7744
|
if (graphHtml !== null || graphLoading) return;
|
|
7585
7745
|
setGraphLoading(true);
|
|
7586
7746
|
setGraphError(null);
|
|
@@ -7616,13 +7776,13 @@ var MetadataModal = ({ model, allModels, open, onClose }) => {
|
|
|
7616
7776
|
setGraphLoading(false);
|
|
7617
7777
|
}
|
|
7618
7778
|
}, [apiUrl, model, modelLabel, graphHtml, graphLoading, findRelatedModel]);
|
|
7619
|
-
|
|
7779
|
+
React6.useEffect(() => {
|
|
7620
7780
|
if (activeTab === "knowledge_graph") {
|
|
7621
7781
|
loadGraph();
|
|
7622
7782
|
}
|
|
7623
7783
|
}, [activeTab, loadGraph]);
|
|
7624
7784
|
const navigate = reactRouterDom.useNavigate();
|
|
7625
|
-
|
|
7785
|
+
React6.useEffect(() => {
|
|
7626
7786
|
const handler = (e) => {
|
|
7627
7787
|
if (e.data?.action === "metadata_graph_navigate" && e.data?.url) {
|
|
7628
7788
|
onClose();
|
|
@@ -7862,7 +8022,7 @@ var MetadataModal = ({ model, allModels, open, onClose }) => {
|
|
|
7862
8022
|
};
|
|
7863
8023
|
var _13 = window._ || ((text) => text);
|
|
7864
8024
|
var useMetadataModal = (model, allModels) => {
|
|
7865
|
-
const [metadataOpen, setMetadataOpen] =
|
|
8025
|
+
const [metadataOpen, setMetadataOpen] = React6.useState(false);
|
|
7866
8026
|
const metadataButton = /* @__PURE__ */ jsxRuntime.jsx(antd.Tooltip, { title: _13("Metadata"), children: /* @__PURE__ */ jsxRuntime.jsx(antd.Button, { size: "small", icon: /* @__PURE__ */ jsxRuntime.jsx(AntDIcons2.InfoCircleOutlined, {}), onClick: () => setMetadataOpen(true) }) });
|
|
7867
8027
|
const metadataModal = /* @__PURE__ */ jsxRuntime.jsx(MetadataModal, { model, allModels, open: metadataOpen, onClose: () => setMetadataOpen(false) });
|
|
7868
8028
|
return { metadataButton, metadataModal };
|
|
@@ -7882,7 +8042,7 @@ var useShowEditableForm = (resource, id) => {
|
|
|
7882
8042
|
});
|
|
7883
8043
|
const record = queryResult?.data?.data;
|
|
7884
8044
|
const recordId = record?.eid ?? record?.id ?? id;
|
|
7885
|
-
useKeyboardShortcuts(
|
|
8045
|
+
useKeyboardShortcuts(React6.useMemo(() => [
|
|
7886
8046
|
{ key: "s", ctrl: true, handler: () => formProps?.form?.submit() },
|
|
7887
8047
|
{ key: "Escape", handler: () => navigate(-1) }
|
|
7888
8048
|
], [formProps?.form, navigate]));
|
|
@@ -7950,7 +8110,7 @@ var renderModelHeading = ({
|
|
|
7950
8110
|
paddingLeft: 10,
|
|
7951
8111
|
paddingRight: 10
|
|
7952
8112
|
},
|
|
7953
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minWidth: 0, fontSize:
|
|
8113
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minWidth: 0, fontSize: 18, fontWeight: 700, color: tone.solid, padding: "2px 8px" }, children: title })
|
|
7954
8114
|
}
|
|
7955
8115
|
);
|
|
7956
8116
|
};
|
|
@@ -8091,14 +8251,14 @@ var RelationsExplorer = ({ model, record, allModels, isActive = true }) => {
|
|
|
8091
8251
|
const apiUrl = core.useApiUrl();
|
|
8092
8252
|
const go = core.useGo();
|
|
8093
8253
|
const paneNav = usePaneNavigation();
|
|
8094
|
-
const [reverseTreeData, setReverseTreeData] =
|
|
8095
|
-
const [forwardTreeData, setForwardTreeData] =
|
|
8096
|
-
const [loading, setLoading] =
|
|
8254
|
+
const [reverseTreeData, setReverseTreeData] = React6.useState([]);
|
|
8255
|
+
const [forwardTreeData, setForwardTreeData] = React6.useState([]);
|
|
8256
|
+
const [loading, setLoading] = React6.useState(true);
|
|
8097
8257
|
const isReverse = (rel) => {
|
|
8098
8258
|
if (rel.relationName && rel.relationName.endsWith("_reverse")) return true;
|
|
8099
8259
|
return !rel.otherResource;
|
|
8100
8260
|
};
|
|
8101
|
-
|
|
8261
|
+
React6.useEffect(() => {
|
|
8102
8262
|
if (!isActive) {
|
|
8103
8263
|
setLoading(false);
|
|
8104
8264
|
return;
|
|
@@ -8268,9 +8428,9 @@ var RelationsExplorer = ({ model, record, allModels, isActive = true }) => {
|
|
|
8268
8428
|
] });
|
|
8269
8429
|
};
|
|
8270
8430
|
function usePinRecord(resource, recordId) {
|
|
8271
|
-
const [pinned, setPinned] =
|
|
8272
|
-
const [loading, setLoading] =
|
|
8273
|
-
|
|
8431
|
+
const [pinned, setPinned] = React6.useState(null);
|
|
8432
|
+
const [loading, setLoading] = React6.useState(false);
|
|
8433
|
+
React6.useEffect(() => {
|
|
8274
8434
|
if (!resource || recordId === void 0 || recordId === null || recordId === "") return;
|
|
8275
8435
|
let cancelled = false;
|
|
8276
8436
|
authenticatedFetch(
|
|
@@ -8284,7 +8444,7 @@ function usePinRecord(resource, recordId) {
|
|
|
8284
8444
|
cancelled = true;
|
|
8285
8445
|
};
|
|
8286
8446
|
}, [resource, recordId]);
|
|
8287
|
-
const pin =
|
|
8447
|
+
const pin = React6.useCallback(async () => {
|
|
8288
8448
|
if (!resource || recordId === void 0) return;
|
|
8289
8449
|
setLoading(true);
|
|
8290
8450
|
try {
|
|
@@ -8298,7 +8458,7 @@ function usePinRecord(resource, recordId) {
|
|
|
8298
8458
|
setLoading(false);
|
|
8299
8459
|
}
|
|
8300
8460
|
}, [resource, recordId]);
|
|
8301
|
-
const unpin =
|
|
8461
|
+
const unpin = React6.useCallback(async () => {
|
|
8302
8462
|
if (!resource || recordId === void 0) return;
|
|
8303
8463
|
setLoading(true);
|
|
8304
8464
|
try {
|
|
@@ -8311,7 +8471,7 @@ function usePinRecord(resource, recordId) {
|
|
|
8311
8471
|
setLoading(false);
|
|
8312
8472
|
}
|
|
8313
8473
|
}, [resource, recordId]);
|
|
8314
|
-
const toggle =
|
|
8474
|
+
const toggle = React6.useCallback(() => pinned ? unpin() : pin(), [pinned, pin, unpin]);
|
|
8315
8475
|
return { pinned, loading, pin, unpin, toggle };
|
|
8316
8476
|
}
|
|
8317
8477
|
async function unpinRecords(resource, recordIds) {
|
|
@@ -8327,17 +8487,17 @@ async function unpinRecords(resource, recordIds) {
|
|
|
8327
8487
|
var _17 = window._ || ((text) => text);
|
|
8328
8488
|
var useShowActionsPreferences = (model, allModels, record, saveButtonProps, configureLayoutButtonRef, saveLayoutRef) => {
|
|
8329
8489
|
const apiUrl = core.useApiUrl();
|
|
8330
|
-
const allModelsList =
|
|
8331
|
-
const [showRelationActions, setShowRelationActions] =
|
|
8332
|
-
const [showRelationCreate, setShowRelationCreate] =
|
|
8333
|
-
const [isSavingActionsPrefs, setIsSavingActionsPrefs] =
|
|
8334
|
-
const actionsPrefsTouchedRef =
|
|
8335
|
-
const actionsPrefsLoadedRef =
|
|
8336
|
-
const actionsPrefsResourceRef =
|
|
8337
|
-
const markActionsPrefsTouched =
|
|
8490
|
+
const allModelsList = React6.useMemo(() => allModels || [], [allModels]);
|
|
8491
|
+
const [showRelationActions, setShowRelationActions] = React6.useState(DEFAULT_SHOW_RELATION_ROW_ACTIONS);
|
|
8492
|
+
const [showRelationCreate, setShowRelationCreate] = React6.useState(DEFAULT_RELATION_CREATE_ACTIONS);
|
|
8493
|
+
const [isSavingActionsPrefs, setIsSavingActionsPrefs] = React6.useState(false);
|
|
8494
|
+
const actionsPrefsTouchedRef = React6.useRef(false);
|
|
8495
|
+
const actionsPrefsLoadedRef = React6.useRef(false);
|
|
8496
|
+
const actionsPrefsResourceRef = React6.useRef(null);
|
|
8497
|
+
const markActionsPrefsTouched = React6.useCallback(() => {
|
|
8338
8498
|
actionsPrefsTouchedRef.current = true;
|
|
8339
8499
|
}, []);
|
|
8340
|
-
const saveActionsPreferences =
|
|
8500
|
+
const saveActionsPreferences = React6.useCallback(async () => {
|
|
8341
8501
|
const resourceKey = resolveResourcePath(model.resource || model.name, allModelsList);
|
|
8342
8502
|
const preferences = {
|
|
8343
8503
|
showActions: showRelationActions,
|
|
@@ -8360,7 +8520,7 @@ var useShowActionsPreferences = (model, allModels, record, saveButtonProps, conf
|
|
|
8360
8520
|
setIsSavingActionsPrefs(false);
|
|
8361
8521
|
}
|
|
8362
8522
|
}, [apiUrl, allModelsList, model.name, model.resource, showRelationActions, showRelationCreate]);
|
|
8363
|
-
|
|
8523
|
+
React6.useEffect(() => {
|
|
8364
8524
|
const resourceKey = resolveResourcePath(model.resource || model.name, allModelsList);
|
|
8365
8525
|
if (actionsPrefsResourceRef.current !== resourceKey) {
|
|
8366
8526
|
actionsPrefsLoadedRef.current = false;
|
|
@@ -8445,7 +8605,7 @@ var useShowActionsPreferences = (model, allModels, record, saveButtonProps, conf
|
|
|
8445
8605
|
const resource = model.resource || model.name;
|
|
8446
8606
|
const { pinned, loading: pinLoading, toggle: togglePin } = usePinRecord(resource, recordId);
|
|
8447
8607
|
const { metadataButton, metadataModal } = useMetadataModal(model, allModels);
|
|
8448
|
-
const [exploreOpen, setExploreOpen] =
|
|
8608
|
+
const [exploreOpen, setExploreOpen] = React6.useState(false);
|
|
8449
8609
|
const headerButtons = ({ defaultButtons }) => /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8450
8610
|
metadataButton,
|
|
8451
8611
|
metadataModal,
|
|
@@ -8482,7 +8642,7 @@ var useShowActionsPreferences = (model, allModels, record, saveButtonProps, conf
|
|
|
8482
8642
|
headerButtons
|
|
8483
8643
|
};
|
|
8484
8644
|
};
|
|
8485
|
-
var PrimaryShowContext =
|
|
8645
|
+
var PrimaryShowContext = React6__default.default.createContext(null);
|
|
8486
8646
|
|
|
8487
8647
|
// src/components/DynamicResource/utils/columnFilters.ts
|
|
8488
8648
|
var truncateLabel = (s) => s.length > 15 ? s.substring(0, 15) + "\u2026" : s;
|
|
@@ -8705,19 +8865,19 @@ function filterFieldsByRole(fields, userRoles) {
|
|
|
8705
8865
|
});
|
|
8706
8866
|
}
|
|
8707
8867
|
function useRoleFilteredModel(model) {
|
|
8708
|
-
const userRoles =
|
|
8709
|
-
return
|
|
8868
|
+
const userRoles = React6.useMemo(() => getCurrentUserRoles(), []);
|
|
8869
|
+
return React6.useMemo(() => {
|
|
8710
8870
|
const filtered = filterFieldsByRole(model.fields, userRoles);
|
|
8711
8871
|
if (filtered.length === model.fields.length) return model;
|
|
8712
8872
|
return { ...model, fields: filtered };
|
|
8713
8873
|
}, [model, userRoles]);
|
|
8714
8874
|
}
|
|
8715
8875
|
var _19 = window._ || ((text) => text);
|
|
8716
|
-
var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
|
|
8876
|
+
var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded, beforeTabs }) => {
|
|
8717
8877
|
const model = useRoleFilteredModel(modelProp);
|
|
8718
8878
|
applyI18nLabelsToModel(model);
|
|
8719
8879
|
applyI18nLabelsToModels(allModels);
|
|
8720
|
-
const allModelsList =
|
|
8880
|
+
const allModelsList = React6.useMemo(() => allModels || [], [allModels]);
|
|
8721
8881
|
const modelTone = useModelTone(model);
|
|
8722
8882
|
const modelDisplayLabel = asDisplayText(model.label, asDisplayText(model.name, "Record"));
|
|
8723
8883
|
const { id: routeId } = reactRouterDom.useParams();
|
|
@@ -8725,9 +8885,9 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
|
|
|
8725
8885
|
const { formProps, saveButtonProps, record, recordId } = useShowEditableForm(model.resource || model.name, id);
|
|
8726
8886
|
const { formProps: showFormProps, effectiveFields } = buildShowTabFormOptions(formProps, model, allModels);
|
|
8727
8887
|
const pageTitle = record?._label ? asDisplayText(record._label, `${_19("Show")} ${modelDisplayLabel}`) : `${_19("Show")} ${modelDisplayLabel}`;
|
|
8728
|
-
const saveLayoutRef =
|
|
8888
|
+
const saveLayoutRef = React6.useRef(() => {
|
|
8729
8889
|
});
|
|
8730
|
-
const configureLayoutButtonRef =
|
|
8890
|
+
const configureLayoutButtonRef = React6.useRef(null);
|
|
8731
8891
|
const wrappedSaveButtonProps = saveButtonProps ? {
|
|
8732
8892
|
...saveButtonProps,
|
|
8733
8893
|
onClick: (e) => {
|
|
@@ -8738,7 +8898,7 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
|
|
|
8738
8898
|
const { data: canLayoutData } = core.useCan({ resource: "veloiq_layout", action: "configure_layout" });
|
|
8739
8899
|
const canConfigureLayout = canLayoutData?.can !== false;
|
|
8740
8900
|
const { actionsState, headerButtons } = useShowActionsPreferences(model, allModels, record, wrappedSaveButtonProps, configureLayoutButtonRef, saveLayoutRef);
|
|
8741
|
-
const [activeTabKey, setActiveTabKey] =
|
|
8901
|
+
const [activeTabKey, setActiveTabKey] = React6.useState("details");
|
|
8742
8902
|
const { tabs: items, layoutConfig } = useStandardShowTabs(
|
|
8743
8903
|
model,
|
|
8744
8904
|
record,
|
|
@@ -8759,12 +8919,12 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
|
|
|
8759
8919
|
}
|
|
8760
8920
|
)
|
|
8761
8921
|
] }) : null;
|
|
8762
|
-
|
|
8922
|
+
React6.useEffect(() => {
|
|
8763
8923
|
if (!items.find((item) => item.key === activeTabKey)) {
|
|
8764
8924
|
setActiveTabKey(items[0]?.key || "details");
|
|
8765
8925
|
}
|
|
8766
8926
|
}, [activeTabKey, items]);
|
|
8767
|
-
const lazyItems =
|
|
8927
|
+
const lazyItems = React6.useMemo(
|
|
8768
8928
|
() => items.map((item) => ({
|
|
8769
8929
|
...item,
|
|
8770
8930
|
children: item.key === activeTabKey ? item.children : null
|
|
@@ -8775,6 +8935,7 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
|
|
|
8775
8935
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "jm-tone-scope", style: toneScopeStyle(modelTone), children: [
|
|
8776
8936
|
/* @__PURE__ */ jsxRuntime.jsx(ToneSharedStyles, {}),
|
|
8777
8937
|
!record ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "center", padding: 32 }, children: /* @__PURE__ */ jsxRuntime.jsx(antd.Spin, {}) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
8938
|
+
beforeTabs,
|
|
8778
8939
|
/* @__PURE__ */ jsxRuntime.jsx(antd.Tabs, { activeKey: activeTabKey, onChange: setActiveTabKey, items: lazyItems, destroyInactiveTabPane: true }),
|
|
8779
8940
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8780
8941
|
ShowFooterButtons,
|
|
@@ -8802,6 +8963,7 @@ var DynamicShow = ({ model: modelProp, allModels, idOverride, embedded }) => {
|
|
|
8802
8963
|
})),
|
|
8803
8964
|
headerButtons,
|
|
8804
8965
|
children: [
|
|
8966
|
+
beforeTabs,
|
|
8805
8967
|
/* @__PURE__ */ jsxRuntime.jsx(antd.Tabs, { activeKey: activeTabKey, onChange: setActiveTabKey, items: lazyItems, destroyInactiveTabPane: true }),
|
|
8806
8968
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8807
8969
|
ShowFooterButtons,
|
|
@@ -8825,7 +8987,7 @@ var RelationSelect = ({ field, value, onChange, allModels, multiple, serverSearc
|
|
|
8825
8987
|
const resolvedResource = resourceName && allModels ? resolveResourcePath(resourceName, allModels) : resourceName;
|
|
8826
8988
|
const referencedModel = resourceName ? findModelByName(allModels, resourceName) : void 0;
|
|
8827
8989
|
const resolvedOptionValue = field.optionValue || referencedModel?.pkField || "eid";
|
|
8828
|
-
const [loadAll, setLoadAll] =
|
|
8990
|
+
const [loadAll, setLoadAll] = React6__default.default.useState(false);
|
|
8829
8991
|
const pageSize = loadAll ? 999999 : RELATION_SELECT_DEFAULT_PAGE_SIZE;
|
|
8830
8992
|
const { selectProps, queryResult } = antd$1.useSelect({
|
|
8831
8993
|
resource: resolvedResource,
|
|
@@ -8842,8 +9004,8 @@ var RelationSelect = ({ field, value, onChange, allModels, multiple, serverSearc
|
|
|
8842
9004
|
const loadedCount = filteredOptions?.length ?? 0;
|
|
8843
9005
|
const isCapped = !loadAll && serverTotal > loadedCount && loadedCount > 0;
|
|
8844
9006
|
const normalizeSearch = (val) => String(val ?? "").toLowerCase();
|
|
8845
|
-
const selectedSet =
|
|
8846
|
-
const [searchValue, setSearchValue] =
|
|
9007
|
+
const selectedSet = React6__default.default.useMemo(() => new Set(Array.isArray(value) ? value : value !== void 0 && value !== null ? [value] : []), [value]);
|
|
9008
|
+
const [searchValue, setSearchValue] = React6__default.default.useState("");
|
|
8847
9009
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
8848
9010
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8849
9011
|
antd.Select,
|
|
@@ -8890,8 +9052,8 @@ var RelationSelect = ({ field, value, onChange, allModels, multiple, serverSearc
|
|
|
8890
9052
|
var _21 = window._ || ((text) => text);
|
|
8891
9053
|
var FileUploadInput = ({ value: _value, onChange: _onChange }) => {
|
|
8892
9054
|
const form = antd.Form.useFormInstance();
|
|
8893
|
-
const [uploading, setUploading] =
|
|
8894
|
-
const [fileName, setFileName] =
|
|
9055
|
+
const [uploading, setUploading] = React6.useState(false);
|
|
9056
|
+
const [fileName, setFileName] = React6.useState(null);
|
|
8895
9057
|
const currentDataName = antd.Form.useWatch("data_name", form);
|
|
8896
9058
|
const handleUpload = async (file) => {
|
|
8897
9059
|
const recordId = form.getFieldValue("eid") ?? form.getFieldValue("id");
|
|
@@ -8957,9 +9119,9 @@ var AsyncSelectInput = ({
|
|
|
8957
9119
|
onChange
|
|
8958
9120
|
}) => {
|
|
8959
9121
|
const apiUrl = core.useApiUrl();
|
|
8960
|
-
const [options, setOptions] =
|
|
8961
|
-
const [loading, setLoading] =
|
|
8962
|
-
|
|
9122
|
+
const [options, setOptions] = React6.useState([]);
|
|
9123
|
+
const [loading, setLoading] = React6.useState(false);
|
|
9124
|
+
React6.useEffect(() => {
|
|
8963
9125
|
let cancelled = false;
|
|
8964
9126
|
setLoading(true);
|
|
8965
9127
|
const fetchOptions = async () => {
|
|
@@ -9016,9 +9178,9 @@ var AsyncSelectInput = ({
|
|
|
9016
9178
|
);
|
|
9017
9179
|
};
|
|
9018
9180
|
var _23 = window._ || ((text) => text);
|
|
9019
|
-
var ReactMarkdown2 =
|
|
9181
|
+
var ReactMarkdown2 = React6.lazy(() => import('react-markdown').then((m) => ({ default: m.default })));
|
|
9020
9182
|
var MarkdownEditor = ({ value = "", onChange }) => {
|
|
9021
|
-
const [activeTab, setActiveTab] =
|
|
9183
|
+
const [activeTab, setActiveTab] = React6.useState("edit");
|
|
9022
9184
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9023
9185
|
antd.Tabs,
|
|
9024
9186
|
{
|
|
@@ -9043,14 +9205,14 @@ var MarkdownEditor = ({ value = "", onChange }) => {
|
|
|
9043
9205
|
{
|
|
9044
9206
|
key: "preview",
|
|
9045
9207
|
label: _23("Preview"),
|
|
9046
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minHeight: 60, padding: "4px 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9208
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { minHeight: 60, padding: "4px 0" }, children: /* @__PURE__ */ jsxRuntime.jsx(React6.Suspense, { fallback: /* @__PURE__ */ jsxRuntime.jsx(antd.Skeleton.Input, { active: true, size: "small", style: { width: 200 } }), children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown2, { children: value }) }) })
|
|
9047
9209
|
}
|
|
9048
9210
|
]
|
|
9049
9211
|
}
|
|
9050
9212
|
);
|
|
9051
9213
|
};
|
|
9052
9214
|
var JsonEditor = ({ value = "", onChange }) => {
|
|
9053
|
-
const [error, setError] =
|
|
9215
|
+
const [error, setError] = React6.useState(null);
|
|
9054
9216
|
const handleChange = (e) => {
|
|
9055
9217
|
const raw = e.target.value;
|
|
9056
9218
|
onChange?.(raw);
|
|
@@ -9217,7 +9379,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
|
|
|
9217
9379
|
const { token } = antd.theme.useToken();
|
|
9218
9380
|
const modelTone = useModelTone(model);
|
|
9219
9381
|
const { settings: viewSettings, loading: viewSettingsLoading } = useViewSettings();
|
|
9220
|
-
const allModelsList =
|
|
9382
|
+
const allModelsList = React6.useMemo(() => allModels || [], [allModels]);
|
|
9221
9383
|
const { rows: editConfigRows, loading: editConfigLoading } = useViewConfigurations(model.name, "AutomaticEntityForm");
|
|
9222
9384
|
const { rows: fallbackConfigRows, loading: fallbackConfigLoading } = useViewConfigurations(model.name, "PrimaryView");
|
|
9223
9385
|
const valueBackground = isDarkColor2(token.colorBgBase || token.colorBgContainer) ? token.colorFillQuaternary : "#F9FFFF";
|
|
@@ -9231,12 +9393,12 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
|
|
|
9231
9393
|
const relateOtherKey = searchParams.get("relate_other_key");
|
|
9232
9394
|
const relateTargetId = searchParams.get("relate_target_id");
|
|
9233
9395
|
const canAutoRelate = Boolean(relateResource && relateTargetKey && relateOtherKey && relateTargetId);
|
|
9234
|
-
const [createdRecord, setCreatedRecord] =
|
|
9235
|
-
const [showRelationActions, setShowRelationActions] =
|
|
9236
|
-
const [showRelationCreate, setShowRelationCreate] =
|
|
9237
|
-
const [activeTabKey, setActiveTabKey] =
|
|
9396
|
+
const [createdRecord, setCreatedRecord] = React6.useState(null);
|
|
9397
|
+
const [showRelationActions, setShowRelationActions] = React6.useState(DEFAULT_EDIT_RELATION_ROW_ACTIONS);
|
|
9398
|
+
const [showRelationCreate, setShowRelationCreate] = React6.useState(DEFAULT_RELATION_CREATE_ACTIONS);
|
|
9399
|
+
const [activeTabKey, setActiveTabKey] = React6.useState("main_data");
|
|
9238
9400
|
const isPostCreate = createdRecord !== null;
|
|
9239
|
-
const relationViewTypeDefaults =
|
|
9401
|
+
const relationViewTypeDefaults = React6.useMemo(
|
|
9240
9402
|
() => ({
|
|
9241
9403
|
show: normalizeRelationViewType(viewSettings?.showViewType || "") || "totals-details",
|
|
9242
9404
|
edit: normalizeRelationViewType(viewSettings?.editViewType || "") || "editable-table"
|
|
@@ -9244,11 +9406,11 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
|
|
|
9244
9406
|
[viewSettings?.showViewType, viewSettings?.editViewType]
|
|
9245
9407
|
);
|
|
9246
9408
|
const modelDisplayLabel = asDisplayText(model.label, asDisplayText(model.name, "Record"));
|
|
9247
|
-
const isLinkModel =
|
|
9409
|
+
const isLinkModel = React6.useMemo(() => {
|
|
9248
9410
|
const fieldKeys = model.fields.map((f) => f.key);
|
|
9249
9411
|
return fieldKeys.includes("eid_from") && fieldKeys.includes("eid_to") && searchParams.has("eid_from");
|
|
9250
9412
|
}, [model.fields, searchParams]);
|
|
9251
|
-
const [serverDefaults, setServerDefaults] =
|
|
9413
|
+
const [serverDefaults, setServerDefaults] = React6.useState({});
|
|
9252
9414
|
const { formProps, saveButtonProps } = antd$1.useForm({
|
|
9253
9415
|
resource: formResource,
|
|
9254
9416
|
redirect: false,
|
|
@@ -9297,14 +9459,14 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
|
|
|
9297
9459
|
type: "success"
|
|
9298
9460
|
})
|
|
9299
9461
|
});
|
|
9300
|
-
useKeyboardShortcuts(
|
|
9462
|
+
useKeyboardShortcuts(React6.useMemo(() => [
|
|
9301
9463
|
{ key: "s", ctrl: true, handler: () => {
|
|
9302
9464
|
if (!isPostCreate) formProps?.form?.submit();
|
|
9303
9465
|
} },
|
|
9304
9466
|
{ key: "Escape", handler: () => journeyCallbacks?.onCancel ? journeyCallbacks.onCancel() : navigate(-1) }
|
|
9305
9467
|
], [formProps?.form, navigate, isPostCreate, journeyCallbacks]));
|
|
9306
|
-
const effectiveFields =
|
|
9307
|
-
const fieldByKey =
|
|
9468
|
+
const effectiveFields = React6.useMemo(() => applyRelationFieldOverrides(model, allModelsList), [model, allModelsList]);
|
|
9469
|
+
const fieldByKey = React6.useMemo(
|
|
9308
9470
|
() => new Map(effectiveFields.map((field) => [field.key, field])),
|
|
9309
9471
|
[effectiveFields]
|
|
9310
9472
|
);
|
|
@@ -9316,7 +9478,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
|
|
|
9316
9478
|
if (["false", "0", "no", "n", "off"].includes(normalized)) return false;
|
|
9317
9479
|
return value;
|
|
9318
9480
|
};
|
|
9319
|
-
const normalizeFieldValue =
|
|
9481
|
+
const normalizeFieldValue = React6.useCallback((field, rawValue) => {
|
|
9320
9482
|
if (rawValue === void 0 || rawValue === null || rawValue === "") return rawValue;
|
|
9321
9483
|
if (field.type === "number") {
|
|
9322
9484
|
const parsed = Number(rawValue);
|
|
@@ -9325,7 +9487,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
|
|
|
9325
9487
|
if (field.type === "boolean") return parseBooleanValue(rawValue);
|
|
9326
9488
|
return rawValue;
|
|
9327
9489
|
}, []);
|
|
9328
|
-
|
|
9490
|
+
React6.useEffect(() => {
|
|
9329
9491
|
let cancelled = false;
|
|
9330
9492
|
const loadDefaults = async () => {
|
|
9331
9493
|
try {
|
|
@@ -9348,7 +9510,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
|
|
|
9348
9510
|
cancelled = true;
|
|
9349
9511
|
};
|
|
9350
9512
|
}, [apiUrl, effectiveFields, formResource, normalizeFieldValue]);
|
|
9351
|
-
const { initialValues, hiddenFields } =
|
|
9513
|
+
const { initialValues, hiddenFields } = React6.useMemo(() => {
|
|
9352
9514
|
const defaults = {};
|
|
9353
9515
|
const fromQuery = {};
|
|
9354
9516
|
const hidden = [];
|
|
@@ -9389,13 +9551,13 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
|
|
|
9389
9551
|
const configLoading = editConfigLoading || fallbackConfigLoading || viewSettingsLoading;
|
|
9390
9552
|
const hasConfig = configRows.length > 0;
|
|
9391
9553
|
const configSections = groupConfigRowsBySection(configRows);
|
|
9392
|
-
const { embedded, tabbed } =
|
|
9393
|
-
const allRelations =
|
|
9394
|
-
const configuredRelationKeys =
|
|
9395
|
-
const configuredResolvedRelationKeys =
|
|
9396
|
-
const configuredRelationDisplayKeys =
|
|
9554
|
+
const { embedded, tabbed } = React6.useMemo(() => splitRelations(model.relations), [model.relations]);
|
|
9555
|
+
const allRelations = React6.useMemo(() => [...embedded, ...tabbed], [embedded, tabbed]);
|
|
9556
|
+
const configuredRelationKeys = React6.useMemo(() => buildConfiguredRelationKeys(configRows), [configRows]);
|
|
9557
|
+
const configuredResolvedRelationKeys = React6.useMemo(() => buildConfiguredResolvedRelationKeys(model.relations, configRows), [model.relations, configRows]);
|
|
9558
|
+
const configuredRelationDisplayKeys = React6.useMemo(() => buildConfiguredRelationDisplayKeys(model.relations, configRows), [model.relations, configRows]);
|
|
9397
9559
|
const hasConfiguredDetailRelations = configuredResolvedRelationKeys.size > 0 || configuredRelationKeys.size > 0;
|
|
9398
|
-
|
|
9560
|
+
React6.useEffect(() => {
|
|
9399
9561
|
const formInstance = formProps?.form;
|
|
9400
9562
|
if (!formInstance) return;
|
|
9401
9563
|
const untouchedDefaults = Object.fromEntries(
|
|
@@ -9404,7 +9566,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
|
|
|
9404
9566
|
if (Object.keys(untouchedDefaults).length === 0) return;
|
|
9405
9567
|
formInstance.setFieldsValue(untouchedDefaults);
|
|
9406
9568
|
}, [formProps, initialValues]);
|
|
9407
|
-
const handleDone =
|
|
9569
|
+
const handleDone = React6.useCallback(() => {
|
|
9408
9570
|
const createdId = getRecordId(createdRecord, model.fields);
|
|
9409
9571
|
if (returnTo) {
|
|
9410
9572
|
navigate(returnTo);
|
|
@@ -9414,7 +9576,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
|
|
|
9414
9576
|
navigate(-1);
|
|
9415
9577
|
}
|
|
9416
9578
|
}, [createdRecord, returnTo, navigate, formResource]);
|
|
9417
|
-
const handleGoToEdit =
|
|
9579
|
+
const handleGoToEdit = React6.useCallback(() => {
|
|
9418
9580
|
const createdId = getRecordId(createdRecord, model.fields);
|
|
9419
9581
|
if (createdId != null) {
|
|
9420
9582
|
go({ to: { resource: model.resource || model.name, action: "edit", id: createdId } });
|
|
@@ -9426,7 +9588,7 @@ var DynamicCreate = ({ model: modelProp, allModels, journeyCallbacks, injectedVa
|
|
|
9426
9588
|
/* @__PURE__ */ jsxRuntime.jsx(antd.Button, { size: "small", type: "primary", icon: /* @__PURE__ */ jsxRuntime.jsx(AntDIcons2.CheckCircleOutlined, {}), onClick: handleDone, children: _24("Done") })
|
|
9427
9589
|
] });
|
|
9428
9590
|
const addTabsForNonConfiguredRelations = viewSettings?.addTabsForNonConfiguredRelations !== false;
|
|
9429
|
-
const relationTabEntries =
|
|
9591
|
+
const relationTabEntries = React6.useMemo(() => {
|
|
9430
9592
|
if (!allModels) return [];
|
|
9431
9593
|
const groups = /* @__PURE__ */ new Map();
|
|
9432
9594
|
allRelations.forEach((rel) => {
|
|
@@ -9767,7 +9929,7 @@ var nextGridPosition = (cells) => {
|
|
|
9767
9929
|
};
|
|
9768
9930
|
var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
|
|
9769
9931
|
const [form] = antd.Form.useForm();
|
|
9770
|
-
|
|
9932
|
+
React6.useEffect(() => {
|
|
9771
9933
|
if (!cell || !tabId) return;
|
|
9772
9934
|
const tab = config.tabs.find((t) => t.id === tabId);
|
|
9773
9935
|
form.setFieldsValue({
|
|
@@ -9779,7 +9941,9 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
|
|
|
9779
9941
|
min_width: cell.min_width ?? "",
|
|
9780
9942
|
max_width: cell.max_width ?? "",
|
|
9781
9943
|
min_height: cell.min_height ?? "",
|
|
9782
|
-
max_height: cell.max_height ?? ""
|
|
9944
|
+
max_height: cell.max_height ?? "",
|
|
9945
|
+
chart_url: cell.chart_url ?? "",
|
|
9946
|
+
chart_title: cell.chart_title ?? ""
|
|
9783
9947
|
});
|
|
9784
9948
|
}, [cell, tabId, config, form]);
|
|
9785
9949
|
const handleSave = () => {
|
|
@@ -9795,7 +9959,9 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
|
|
|
9795
9959
|
min_width: values.min_width || null,
|
|
9796
9960
|
max_width: values.max_width || null,
|
|
9797
9961
|
min_height: values.min_height || null,
|
|
9798
|
-
max_height: values.max_height || null
|
|
9962
|
+
max_height: values.max_height || null,
|
|
9963
|
+
chart_url: values.chart_url || void 0,
|
|
9964
|
+
chart_title: values.chart_title || void 0
|
|
9799
9965
|
};
|
|
9800
9966
|
const currentTab = config.tabs.find((t) => t.id === tabId);
|
|
9801
9967
|
const nameUnchanged = currentTab?.name.trim().toLowerCase() === newTabName.toLowerCase();
|
|
@@ -9842,7 +10008,7 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
|
|
|
9842
10008
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
9843
10009
|
antd.Drawer,
|
|
9844
10010
|
{
|
|
9845
|
-
title: cell?.source_type !== "model" ? `Configure section: ${cell?.section_name ?? cell?.model ?? ""}` : `Configure cell: ${cell?.model ?? ""}`,
|
|
10011
|
+
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 ?? ""}`,
|
|
9846
10012
|
placement: "right",
|
|
9847
10013
|
width: 380,
|
|
9848
10014
|
open,
|
|
@@ -9870,6 +10036,11 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
|
|
|
9870
10036
|
/* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { orientation: "left", children: "View" }),
|
|
9871
10037
|
/* @__PURE__ */ jsxRuntime.jsx(antd.Form.Item, { name: "view_type", label: "View type", children: /* @__PURE__ */ jsxRuntime.jsx(antd.Select, { options: VIEW_TYPE_OPTIONS }) })
|
|
9872
10038
|
] }),
|
|
10039
|
+
cell?.source_type === "plotly_chart" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
10040
|
+
/* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { orientation: "left", children: "Chart" }),
|
|
10041
|
+
/* @__PURE__ */ jsxRuntime.jsx(antd.Form.Item, { name: "chart_title", label: "Chart title", children: /* @__PURE__ */ jsxRuntime.jsx(antd.Input, { placeholder: "e.g. Confidence by Month" }) }),
|
|
10042
|
+
/* @__PURE__ */ jsxRuntime.jsx(antd.Form.Item, { name: "chart_url", label: "Chart URL", children: /* @__PURE__ */ jsxRuntime.jsx(antd.Input, { placeholder: "/api/nl-answers-confidence-by-month-chart" }) })
|
|
10043
|
+
] }),
|
|
9873
10044
|
/* @__PURE__ */ jsxRuntime.jsx(antd.Divider, { orientation: "left", children: "Size" }),
|
|
9874
10045
|
/* @__PURE__ */ jsxRuntime.jsxs(antd.Space, { wrap: true, children: [
|
|
9875
10046
|
/* @__PURE__ */ jsxRuntime.jsx(antd.Form.Item, { name: "min_width", label: "Min width", style: { marginBottom: 0 }, children: /* @__PURE__ */ jsxRuntime.jsx(antd.Input, { placeholder: "e.g. 320px", style: { width: 130 } }) }),
|
|
@@ -9904,7 +10075,7 @@ var CellConfigDrawer = ({ open, cell, tabId, config, onClose, onSave }) => {
|
|
|
9904
10075
|
};
|
|
9905
10076
|
var SectionCell = ({ cell, isConfiguring, isMaximized, isMinimized, onConfigure, onMaximize, onMinimize, onMove, onResize, children }) => {
|
|
9906
10077
|
const { token } = antd.theme.useToken();
|
|
9907
|
-
const cellRef =
|
|
10078
|
+
const cellRef = React6.useRef(null);
|
|
9908
10079
|
const cellStyle = {
|
|
9909
10080
|
position: "relative",
|
|
9910
10081
|
border: `1px solid ${token.colorBorderSecondary}`,
|
|
@@ -9933,7 +10104,7 @@ var SectionCell = ({ cell, isConfiguring, isMaximized, isMinimized, onConfigure,
|
|
|
9933
10104
|
minHeight: 32,
|
|
9934
10105
|
position: "relative"
|
|
9935
10106
|
};
|
|
9936
|
-
const startResize =
|
|
10107
|
+
const startResize = React6.useCallback((e, dir) => {
|
|
9937
10108
|
e.preventDefault();
|
|
9938
10109
|
e.stopPropagation();
|
|
9939
10110
|
const el = cellRef.current;
|
|
@@ -10013,20 +10184,20 @@ var SectionCell = ({ cell, isConfiguring, isMaximized, isMinimized, onConfigure,
|
|
|
10013
10184
|
] });
|
|
10014
10185
|
};
|
|
10015
10186
|
var SectionsGrid = ({ cells, config, tabId, renderContent, onConfigChange, isConfiguring = false }) => {
|
|
10016
|
-
const [maximizedCellId, setMaximizedCellId] =
|
|
10017
|
-
const [minimizedCellIds, setMinimizedCellIds] =
|
|
10018
|
-
const [drawerCellId, setDrawerCellId] =
|
|
10019
|
-
const handleMaximize =
|
|
10187
|
+
const [maximizedCellId, setMaximizedCellId] = React6.useState(null);
|
|
10188
|
+
const [minimizedCellIds, setMinimizedCellIds] = React6.useState(/* @__PURE__ */ new Set());
|
|
10189
|
+
const [drawerCellId, setDrawerCellId] = React6.useState(null);
|
|
10190
|
+
const handleMaximize = React6.useCallback((cellId) => {
|
|
10020
10191
|
setMaximizedCellId((prev) => prev === cellId ? null : cellId);
|
|
10021
10192
|
}, []);
|
|
10022
|
-
const handleMinimize =
|
|
10193
|
+
const handleMinimize = React6.useCallback((cellId) => {
|
|
10023
10194
|
setMinimizedCellIds((prev) => {
|
|
10024
10195
|
const next = new Set(prev);
|
|
10025
10196
|
next.has(cellId) ? next.delete(cellId) : next.add(cellId);
|
|
10026
10197
|
return next;
|
|
10027
10198
|
});
|
|
10028
10199
|
}, []);
|
|
10029
|
-
const handleMove =
|
|
10200
|
+
const handleMove = React6.useCallback((cellId, direction) => {
|
|
10030
10201
|
const nextTabs = config.tabs.map((tab) => {
|
|
10031
10202
|
if (tab.id !== tabId) return tab;
|
|
10032
10203
|
const cell = tab.cells.find((c) => c.id === cellId);
|
|
@@ -10049,7 +10220,7 @@ var SectionsGrid = ({ cells, config, tabId, renderContent, onConfigChange, isCon
|
|
|
10049
10220
|
});
|
|
10050
10221
|
onConfigChange({ ...config, tabs: nextTabs });
|
|
10051
10222
|
}, [config, tabId, onConfigChange]);
|
|
10052
|
-
const handleResize =
|
|
10223
|
+
const handleResize = React6.useCallback((cellId, minWidth, minHeight) => {
|
|
10053
10224
|
const nextTabs = config.tabs.map((tab) => {
|
|
10054
10225
|
if (tab.id !== tabId) return tab;
|
|
10055
10226
|
return {
|
|
@@ -10066,14 +10237,21 @@ var SectionsGrid = ({ cells, config, tabId, renderContent, onConfigChange, isCon
|
|
|
10066
10237
|
});
|
|
10067
10238
|
onConfigChange({ ...config, tabs: nextTabs });
|
|
10068
10239
|
}, [config, tabId, onConfigChange]);
|
|
10069
|
-
const numCols =
|
|
10240
|
+
const numCols = React6.useMemo(() => {
|
|
10070
10241
|
if (!cells.length) return 1;
|
|
10071
10242
|
return Math.max(...cells.map((c) => c.col)) + 1;
|
|
10072
10243
|
}, [cells]);
|
|
10073
|
-
const numRows =
|
|
10244
|
+
const numRows = React6.useMemo(() => {
|
|
10074
10245
|
if (!cells.length) return 1;
|
|
10075
10246
|
return Math.max(...cells.map((c) => c.row)) + 1;
|
|
10076
10247
|
}, [cells]);
|
|
10248
|
+
const soloRows = React6.useMemo(() => {
|
|
10249
|
+
const counts = /* @__PURE__ */ new Map();
|
|
10250
|
+
for (const c of cells) counts.set(c.row, (counts.get(c.row) ?? 0) + 1);
|
|
10251
|
+
const solo = /* @__PURE__ */ new Set();
|
|
10252
|
+
for (const [row, count] of counts) if (count === 1) solo.add(row);
|
|
10253
|
+
return solo;
|
|
10254
|
+
}, [cells]);
|
|
10077
10255
|
const visibleCells = maximizedCellId ? cells.filter((c) => c.id === maximizedCellId) : cells;
|
|
10078
10256
|
const gridStyle = {
|
|
10079
10257
|
display: "grid",
|
|
@@ -10092,7 +10270,7 @@ var SectionsGrid = ({ cells, config, tabId, renderContent, onConfigChange, isCon
|
|
|
10092
10270
|
"div",
|
|
10093
10271
|
{
|
|
10094
10272
|
style: {
|
|
10095
|
-
gridColumn: maximizedCellId ? "1 / -1" : `${cell.col + 1}`,
|
|
10273
|
+
gridColumn: maximizedCellId || soloRows.has(cell.row) ? "1 / -1" : `${cell.col + 1}`,
|
|
10096
10274
|
gridRow: maximizedCellId ? "1 / -1" : `${cell.row + 1}`
|
|
10097
10275
|
},
|
|
10098
10276
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -10144,8 +10322,8 @@ function parseInlineStyle2(cssText) {
|
|
|
10144
10322
|
}
|
|
10145
10323
|
var _25 = window._ || ((text) => text);
|
|
10146
10324
|
var ReadAndEditReference = ({ value, onChange, field, allModels, model, currentId }) => {
|
|
10147
|
-
const [editing, setEditing] =
|
|
10148
|
-
const [draft, setDraft] =
|
|
10325
|
+
const [editing, setEditing] = React6.useState(false);
|
|
10326
|
+
const [draft, setDraft] = React6.useState(void 0);
|
|
10149
10327
|
const form = antd.Form.useFormInstance();
|
|
10150
10328
|
const resource = field.referencePath ? field.referencePath : field.reference ? resolveResourcePath(field.reference, allModels) : "";
|
|
10151
10329
|
const modelResource = model ? resolveResourcePath(model.resource || model.name, allModels) : void 0;
|
|
@@ -10194,11 +10372,11 @@ var ReadAndEditReference = ({ value, onChange, field, allModels, model, currentI
|
|
|
10194
10372
|
var NLSentenceBlock = ({ eid, title: titleProp, showLabel }) => {
|
|
10195
10373
|
const { token } = antd.theme.useToken();
|
|
10196
10374
|
const apiUrl = core.useApiUrl();
|
|
10197
|
-
const [html, setHtml] =
|
|
10198
|
-
const [loading, setLoading] =
|
|
10199
|
-
const [error, setError] =
|
|
10200
|
-
const [fetchedTitle, setFetchedTitle] =
|
|
10201
|
-
|
|
10375
|
+
const [html, setHtml] = React6.useState(null);
|
|
10376
|
+
const [loading, setLoading] = React6.useState(true);
|
|
10377
|
+
const [error, setError] = React6.useState(null);
|
|
10378
|
+
const [fetchedTitle, setFetchedTitle] = React6.useState(null);
|
|
10379
|
+
React6.useEffect(() => {
|
|
10202
10380
|
let cancelled = false;
|
|
10203
10381
|
setLoading(true);
|
|
10204
10382
|
setHtml(null);
|
|
@@ -10379,7 +10557,6 @@ var SectionCellContent = ({
|
|
|
10379
10557
|
borderRadius: 6,
|
|
10380
10558
|
overflowWrap: "anywhere",
|
|
10381
10559
|
maxWidth: "100%",
|
|
10382
|
-
border: `1px solid ${token.colorBorder}`,
|
|
10383
10560
|
...parseInlineStyle(item.html_format)
|
|
10384
10561
|
};
|
|
10385
10562
|
const relationLabelStyle = {
|
|
@@ -10414,7 +10591,6 @@ var SectionCellContent = ({
|
|
|
10414
10591
|
lineHeight: 1.15,
|
|
10415
10592
|
background: valueBackground,
|
|
10416
10593
|
borderRadius: 6,
|
|
10417
|
-
border: `1px solid ${token.colorBorder}`,
|
|
10418
10594
|
maxWidth: "100%",
|
|
10419
10595
|
overflowWrap: "anywhere",
|
|
10420
10596
|
textAlign: field.type === "number" && !field.reference ? "right" : "left",
|
|
@@ -10515,10 +10691,10 @@ function buildConfig(configRows, overrides) {
|
|
|
10515
10691
|
function usePageSectionsConfig(configRows, resourceKey, mode) {
|
|
10516
10692
|
const apiUrl = core.useApiUrl();
|
|
10517
10693
|
const preferenceType = mode === "show" ? "ShowLayoutGrid" : "EditLayoutGrid";
|
|
10518
|
-
const [overrides, setOverrides] =
|
|
10519
|
-
const [loading, setLoading] =
|
|
10520
|
-
const loadedKeyRef =
|
|
10521
|
-
|
|
10694
|
+
const [overrides, setOverrides] = React6.useState({});
|
|
10695
|
+
const [loading, setLoading] = React6.useState(true);
|
|
10696
|
+
const loadedKeyRef = React6.useRef(null);
|
|
10697
|
+
React6.useEffect(() => {
|
|
10522
10698
|
if (!resourceKey) {
|
|
10523
10699
|
setLoading(false);
|
|
10524
10700
|
return;
|
|
@@ -10537,17 +10713,17 @@ function usePageSectionsConfig(configRows, resourceKey, mode) {
|
|
|
10537
10713
|
}).catch(() => {
|
|
10538
10714
|
}).finally(() => setLoading(false));
|
|
10539
10715
|
}, [apiUrl, resourceKey, preferenceType]);
|
|
10540
|
-
const savedConfig =
|
|
10716
|
+
const savedConfig = React6.useMemo(
|
|
10541
10717
|
() => buildConfig(configRows, overrides),
|
|
10542
10718
|
[configRows, overrides]
|
|
10543
10719
|
);
|
|
10544
|
-
const [isConfiguring, setIsConfiguring] =
|
|
10545
|
-
const [pendingConfig, setPendingConfig] =
|
|
10546
|
-
const config =
|
|
10720
|
+
const [isConfiguring, setIsConfiguring] = React6.useState(false);
|
|
10721
|
+
const [pendingConfig, setPendingConfig] = React6.useState(null);
|
|
10722
|
+
const config = React6.useMemo(
|
|
10547
10723
|
() => isConfiguring && pendingConfig ? pendingConfig : savedConfig,
|
|
10548
10724
|
[isConfiguring, pendingConfig, savedConfig]
|
|
10549
10725
|
);
|
|
10550
|
-
const save =
|
|
10726
|
+
const save = React6.useCallback((nextConfig) => {
|
|
10551
10727
|
const allCells = nextConfig.tabs.flatMap((t) => t.cells);
|
|
10552
10728
|
const nextOverrides = {};
|
|
10553
10729
|
const cells = allCells.map((c) => {
|
|
@@ -10572,24 +10748,24 @@ function usePageSectionsConfig(configRows, resourceKey, mode) {
|
|
|
10572
10748
|
}).catch(() => {
|
|
10573
10749
|
});
|
|
10574
10750
|
}, [apiUrl, resourceKey, preferenceType]);
|
|
10575
|
-
const getSectionRows =
|
|
10751
|
+
const getSectionRows = React6.useCallback((sectionId) => {
|
|
10576
10752
|
return configRows.filter((r) => (r.section_id || r.section || DETAILS_TAB_NAME) === sectionId);
|
|
10577
10753
|
}, [configRows]);
|
|
10578
|
-
const enterConfigMode =
|
|
10754
|
+
const enterConfigMode = React6.useCallback(() => {
|
|
10579
10755
|
setPendingConfig(savedConfig);
|
|
10580
10756
|
setIsConfiguring(true);
|
|
10581
10757
|
}, [savedConfig]);
|
|
10582
|
-
const cancelLayout =
|
|
10758
|
+
const cancelLayout = React6.useCallback(() => {
|
|
10583
10759
|
setPendingConfig(null);
|
|
10584
10760
|
setIsConfiguring(false);
|
|
10585
10761
|
}, []);
|
|
10586
|
-
const saveLayout =
|
|
10762
|
+
const saveLayout = React6.useCallback(() => {
|
|
10587
10763
|
const toSave = pendingConfig ?? savedConfig;
|
|
10588
10764
|
save(toSave);
|
|
10589
10765
|
setPendingConfig(null);
|
|
10590
10766
|
setIsConfiguring(false);
|
|
10591
10767
|
}, [pendingConfig, savedConfig, save]);
|
|
10592
|
-
const onLayoutChange =
|
|
10768
|
+
const onLayoutChange = React6.useCallback((next) => {
|
|
10593
10769
|
if (isConfiguring) setPendingConfig(next);
|
|
10594
10770
|
}, [isConfiguring]);
|
|
10595
10771
|
return { config, loading, save, getSectionRows, isConfiguring, enterConfigMode, saveLayout, cancelLayout, onLayoutChange };
|
|
@@ -10608,7 +10784,7 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
|
|
|
10608
10784
|
const { token } = antd.theme.useToken();
|
|
10609
10785
|
const modelTone = useModelTone(model);
|
|
10610
10786
|
const { settings: viewSettings, loading: viewSettingsLoading } = useViewSettings();
|
|
10611
|
-
const relationViewTypeDefaults =
|
|
10787
|
+
const relationViewTypeDefaults = React6.useMemo(
|
|
10612
10788
|
() => ({
|
|
10613
10789
|
show: normalizeRelationViewType(viewSettings?.showViewType || "") || "totals-details",
|
|
10614
10790
|
edit: normalizeRelationViewType(viewSettings?.editViewType || "") || "editable-table"
|
|
@@ -10616,7 +10792,7 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
|
|
|
10616
10792
|
[viewSettings?.showViewType, viewSettings?.editViewType]
|
|
10617
10793
|
);
|
|
10618
10794
|
const apiUrl = core.useApiUrl();
|
|
10619
|
-
const allModelsList =
|
|
10795
|
+
const allModelsList = React6.useMemo(() => allModels || [], [allModels]);
|
|
10620
10796
|
const { rows: editConfigRows, loading: editConfigLoading } = useViewConfigurations(model.name, "AutomaticEntityForm");
|
|
10621
10797
|
const { rows: fallbackConfigRows, loading: fallbackConfigLoading } = useViewConfigurations(model.name, "PrimaryView");
|
|
10622
10798
|
const valueBackground = isDarkColor2(token.colorBgBase || token.colorBgContainer) ? token.colorFillQuaternary : "#F9FFFF";
|
|
@@ -10647,7 +10823,7 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
|
|
|
10647
10823
|
})
|
|
10648
10824
|
});
|
|
10649
10825
|
const record = queryResult?.data?.data;
|
|
10650
|
-
const editFormProps =
|
|
10826
|
+
const editFormProps = React6.useMemo(() => {
|
|
10651
10827
|
if (!isFileModel(model)) return formProps;
|
|
10652
10828
|
const originalOnFinish = formProps.onFinish;
|
|
10653
10829
|
return {
|
|
@@ -10658,24 +10834,24 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
|
|
|
10658
10834
|
}
|
|
10659
10835
|
};
|
|
10660
10836
|
}, [formProps, model]);
|
|
10661
|
-
useKeyboardShortcuts(
|
|
10837
|
+
useKeyboardShortcuts(React6.useMemo(() => [
|
|
10662
10838
|
{ key: "s", ctrl: true, handler: () => formProps?.form?.submit() },
|
|
10663
10839
|
{ key: "Escape", handler: () => journeyCallbacks?.onCancel ? journeyCallbacks.onCancel() : navigate(-1) }
|
|
10664
10840
|
], [formProps?.form, navigate, journeyCallbacks]));
|
|
10665
10841
|
const pageTitle = record?._label ? asDisplayText(record._label, `${_27("Edit")} ${modelDisplayLabel}`) : `${_27("Edit")} ${modelDisplayLabel}`;
|
|
10666
10842
|
const recordId = getRecordId(record, model.fields);
|
|
10667
|
-
const effectiveFields =
|
|
10843
|
+
const effectiveFields = React6.useMemo(() => applyRelationFieldOverrides(model, allModelsList), [model, allModelsList]);
|
|
10668
10844
|
const { metadataButton: editMetadataButton, metadataModal: editMetadataModal } = useMetadataModal(model, allModels);
|
|
10669
|
-
const [showRelationActions, setShowRelationActions] =
|
|
10670
|
-
const [showRelationCreate, setShowRelationCreate] =
|
|
10671
|
-
const [isSavingActionsPrefs, setIsSavingActionsPrefs] =
|
|
10672
|
-
const actionsPrefsTouchedRef =
|
|
10673
|
-
const actionsPrefsLoadedRef =
|
|
10674
|
-
const actionsPrefsResourceRef =
|
|
10675
|
-
const markActionsPrefsTouched =
|
|
10845
|
+
const [showRelationActions, setShowRelationActions] = React6.useState(DEFAULT_EDIT_RELATION_ROW_ACTIONS);
|
|
10846
|
+
const [showRelationCreate, setShowRelationCreate] = React6.useState(DEFAULT_RELATION_CREATE_ACTIONS);
|
|
10847
|
+
const [isSavingActionsPrefs, setIsSavingActionsPrefs] = React6.useState(false);
|
|
10848
|
+
const actionsPrefsTouchedRef = React6.useRef(false);
|
|
10849
|
+
const actionsPrefsLoadedRef = React6.useRef(false);
|
|
10850
|
+
const actionsPrefsResourceRef = React6.useRef(null);
|
|
10851
|
+
const markActionsPrefsTouched = React6.useCallback(() => {
|
|
10676
10852
|
actionsPrefsTouchedRef.current = true;
|
|
10677
10853
|
}, []);
|
|
10678
|
-
const saveActionsPreferences =
|
|
10854
|
+
const saveActionsPreferences = React6.useCallback(async () => {
|
|
10679
10855
|
const resourceKey2 = resolveResourcePath(model.resource || model.name, allModelsList);
|
|
10680
10856
|
const preferences = {
|
|
10681
10857
|
showActions: showRelationActions,
|
|
@@ -10699,8 +10875,8 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
|
|
|
10699
10875
|
setIsSavingActionsPrefs(false);
|
|
10700
10876
|
}
|
|
10701
10877
|
}, [apiUrl, allModelsList, model.name, model.resource, showRelationActions, showRelationCreate]);
|
|
10702
|
-
const [isDuplicating, setIsDuplicating] =
|
|
10703
|
-
const duplicateRecord =
|
|
10878
|
+
const [isDuplicating, setIsDuplicating] = React6.useState(false);
|
|
10879
|
+
const duplicateRecord = React6.useCallback(async (withRelations) => {
|
|
10704
10880
|
if (!record) return;
|
|
10705
10881
|
setIsDuplicating(true);
|
|
10706
10882
|
try {
|
|
@@ -10768,7 +10944,7 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
|
|
|
10768
10944
|
setIsDuplicating(false);
|
|
10769
10945
|
}
|
|
10770
10946
|
}, [record, model, allModelsList, apiUrl, go]);
|
|
10771
|
-
|
|
10947
|
+
React6.useEffect(() => {
|
|
10772
10948
|
const resourceKey2 = resolveResourcePath(model.resource || model.name, allModelsList);
|
|
10773
10949
|
if (actionsPrefsResourceRef.current !== resourceKey2) {
|
|
10774
10950
|
actionsPrefsLoadedRef.current = false;
|
|
@@ -11048,13 +11224,13 @@ var DynamicEdit = ({ model: modelProp, allModels, topContent, extraHeaderButtons
|
|
|
11048
11224
|
});
|
|
11049
11225
|
items.push(...customConfigTabs);
|
|
11050
11226
|
items.push(...relationTabs);
|
|
11051
|
-
const [activeTabKey, setActiveTabKey] =
|
|
11052
|
-
|
|
11227
|
+
const [activeTabKey, setActiveTabKey] = React6.useState("main_data");
|
|
11228
|
+
React6.useEffect(() => {
|
|
11053
11229
|
if (!items.find((item) => item.key === activeTabKey)) {
|
|
11054
11230
|
setActiveTabKey(items[0]?.key || "main_data");
|
|
11055
11231
|
}
|
|
11056
11232
|
}, [activeTabKey, items]);
|
|
11057
|
-
const lazyItems =
|
|
11233
|
+
const lazyItems = React6.useMemo(
|
|
11058
11234
|
() => items.map((item) => ({
|
|
11059
11235
|
...item,
|
|
11060
11236
|
children: item.key === activeTabKey ? item.children : null
|
|
@@ -11151,7 +11327,7 @@ var useStandardShowTabs = (model, record, allModels, actionsState, editForm, ove
|
|
|
11151
11327
|
const { token } = antd.theme.useToken();
|
|
11152
11328
|
const { settings: viewSettings, loading: viewSettingsLoading } = useViewSettings();
|
|
11153
11329
|
const modelTone = useModelTone(model);
|
|
11154
|
-
const relationViewTypeDefaults =
|
|
11330
|
+
const relationViewTypeDefaults = React6.useMemo(
|
|
11155
11331
|
() => ({
|
|
11156
11332
|
show: normalizeRelationViewType(viewSettings?.showViewType || "") || "totals-details",
|
|
11157
11333
|
edit: normalizeRelationViewType(viewSettings?.editViewType || "") || "editable-table"
|
|
@@ -11460,11 +11636,11 @@ var useRelatedInlineItems = ({
|
|
|
11460
11636
|
pageSize = INLINE_DEFAULT_PAGE_SIZE
|
|
11461
11637
|
}) => {
|
|
11462
11638
|
const apiUrl = core.useApiUrl();
|
|
11463
|
-
const [items, setItems] =
|
|
11464
|
-
const [loading, setLoading] =
|
|
11465
|
-
const [error, setError] =
|
|
11466
|
-
const [total, setTotal] =
|
|
11467
|
-
|
|
11639
|
+
const [items, setItems] = React6.useState([]);
|
|
11640
|
+
const [loading, setLoading] = React6.useState(false);
|
|
11641
|
+
const [error, setError] = React6.useState(null);
|
|
11642
|
+
const [total, setTotal] = React6.useState(0);
|
|
11643
|
+
React6.useEffect(() => {
|
|
11468
11644
|
const recordId = record?.eid ?? record?.id;
|
|
11469
11645
|
if (!recordId || !rel.resource || !rel.targetKey) {
|
|
11470
11646
|
setItems([]);
|
|
@@ -11605,10 +11781,10 @@ var useRelatedGalleryRecords = ({
|
|
|
11605
11781
|
allModels
|
|
11606
11782
|
}) => {
|
|
11607
11783
|
const apiUrl = core.useApiUrl();
|
|
11608
|
-
const [records, setRecords] =
|
|
11609
|
-
const [loading, setLoading] =
|
|
11610
|
-
const [error, setError] =
|
|
11611
|
-
|
|
11784
|
+
const [records, setRecords] = React6.useState([]);
|
|
11785
|
+
const [loading, setLoading] = React6.useState(false);
|
|
11786
|
+
const [error, setError] = React6.useState(null);
|
|
11787
|
+
React6.useEffect(() => {
|
|
11612
11788
|
const recordId = record?.eid ?? record?.id;
|
|
11613
11789
|
if (!recordId || !rel.resource || !rel.targetKey) {
|
|
11614
11790
|
setRecords([]);
|
|
@@ -11706,10 +11882,10 @@ var RelatedObjectsInlineValues = ({ rel, record, viewType, allowedRelatedIds, al
|
|
|
11706
11882
|
const go = core.useGo();
|
|
11707
11883
|
const paneNav = usePaneNavigation();
|
|
11708
11884
|
const { token } = antd.theme.useToken();
|
|
11709
|
-
const [page, setPage] =
|
|
11710
|
-
const [pageSize, setPageSize] =
|
|
11885
|
+
const [page, setPage] = React6.useState(1);
|
|
11886
|
+
const [pageSize, setPageSize] = React6.useState(INLINE_DEFAULT_PAGE_SIZE);
|
|
11711
11887
|
const { items, loading, error, total } = useRelatedInlineItems({ rel, record, allowedRelatedIds, allModels, page, pageSize });
|
|
11712
|
-
const handlePageChange =
|
|
11888
|
+
const handlePageChange = React6.useCallback((newPage, newPageSize) => {
|
|
11713
11889
|
if (newPageSize && newPageSize !== pageSize) {
|
|
11714
11890
|
setPageSize(newPageSize);
|
|
11715
11891
|
setPage(1);
|
|
@@ -11771,17 +11947,17 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
|
|
|
11771
11947
|
const { token } = antd.theme.useToken();
|
|
11772
11948
|
const { records, loading, error } = useRelatedGalleryRecords({ rel, record, allModels });
|
|
11773
11949
|
const resource = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
|
|
11774
|
-
const dateFieldOptions =
|
|
11775
|
-
const [calendarMode, setCalendarMode] =
|
|
11776
|
-
const [calendarDateField, setCalendarDateField] =
|
|
11777
|
-
const [calendarAnchorDate, setCalendarAnchorDate] =
|
|
11778
|
-
const dateFieldKeySet =
|
|
11779
|
-
|
|
11950
|
+
const dateFieldOptions = React6.useMemo(() => getCalendarDateFieldOptions(relatedModel.fields), [relatedModel.fields]);
|
|
11951
|
+
const [calendarMode, setCalendarMode] = React6.useState("month");
|
|
11952
|
+
const [calendarDateField, setCalendarDateField] = React6.useState(() => dateFieldOptions[0]?.key || "");
|
|
11953
|
+
const [calendarAnchorDate, setCalendarAnchorDate] = React6.useState(() => dayjs9__default.default().startOf("month"));
|
|
11954
|
+
const dateFieldKeySet = React6.useMemo(() => new Set(dateFieldOptions.map((field) => field.key)), [dateFieldOptions]);
|
|
11955
|
+
React6.useEffect(() => {
|
|
11780
11956
|
if (calendarDateField && dateFieldKeySet.has(calendarDateField)) return;
|
|
11781
11957
|
const fallback = dateFieldOptions[0]?.key || "";
|
|
11782
11958
|
if (fallback !== calendarDateField) setCalendarDateField(fallback);
|
|
11783
11959
|
}, [calendarDateField, dateFieldKeySet, dateFieldOptions]);
|
|
11784
|
-
const calendarEntries =
|
|
11960
|
+
const calendarEntries = React6.useMemo(() => {
|
|
11785
11961
|
if (!calendarDateField) return [];
|
|
11786
11962
|
const entries = [];
|
|
11787
11963
|
records.forEach((item) => {
|
|
@@ -11797,7 +11973,7 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
|
|
|
11797
11973
|
});
|
|
11798
11974
|
return entries;
|
|
11799
11975
|
}, [calendarDateField, records]);
|
|
11800
|
-
const earliestDateTs =
|
|
11976
|
+
const earliestDateTs = React6.useMemo(() => {
|
|
11801
11977
|
if (calendarEntries.length === 0) return null;
|
|
11802
11978
|
let earliest = calendarEntries[0].date.valueOf();
|
|
11803
11979
|
for (let index = 1; index < calendarEntries.length; index += 1) {
|
|
@@ -11806,8 +11982,8 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
|
|
|
11806
11982
|
}
|
|
11807
11983
|
return earliest;
|
|
11808
11984
|
}, [calendarEntries]);
|
|
11809
|
-
const initSignatureRef =
|
|
11810
|
-
|
|
11985
|
+
const initSignatureRef = React6.useRef("");
|
|
11986
|
+
React6.useEffect(() => {
|
|
11811
11987
|
const signature = `${calendarDateField}|${calendarMode}|${earliestDateTs ?? "none"}`;
|
|
11812
11988
|
if (initSignatureRef.current === signature) return;
|
|
11813
11989
|
initSignatureRef.current = signature;
|
|
@@ -11817,7 +11993,7 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
|
|
|
11817
11993
|
}
|
|
11818
11994
|
setCalendarAnchorDate(dayjs9__default.default(earliestDateTs).startOf(calendarMode));
|
|
11819
11995
|
}, [calendarDateField, calendarMode, earliestDateTs]);
|
|
11820
|
-
const entriesByDate =
|
|
11996
|
+
const entriesByDate = React6.useMemo(() => {
|
|
11821
11997
|
const grouped = /* @__PURE__ */ new Map();
|
|
11822
11998
|
calendarEntries.forEach((entry) => {
|
|
11823
11999
|
const key = entry.date.format("YYYY-MM-DD");
|
|
@@ -11827,7 +12003,7 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
|
|
|
11827
12003
|
});
|
|
11828
12004
|
return grouped;
|
|
11829
12005
|
}, [calendarEntries]);
|
|
11830
|
-
const rangeDays =
|
|
12006
|
+
const rangeDays = React6.useMemo(() => {
|
|
11831
12007
|
const current = calendarAnchorDate.startOf(calendarMode);
|
|
11832
12008
|
if (calendarMode === "week") {
|
|
11833
12009
|
const start2 = current.startOf("week");
|
|
@@ -11838,7 +12014,7 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
|
|
|
11838
12014
|
const totalDays = end.diff(start, "day") + 1;
|
|
11839
12015
|
return Array.from({ length: totalDays }, (_unused, offset) => start.add(offset, "day"));
|
|
11840
12016
|
}, [calendarAnchorDate, calendarMode]);
|
|
11841
|
-
const periodLabel =
|
|
12017
|
+
const periodLabel = React6.useMemo(() => {
|
|
11842
12018
|
if (calendarMode === "week") {
|
|
11843
12019
|
const weekStart = calendarAnchorDate.startOf("week");
|
|
11844
12020
|
const weekEnd = weekStart.endOf("week");
|
|
@@ -11998,9 +12174,9 @@ var RelatedObjectsCalendar = ({ rel, record, relatedModel, allModels }) => {
|
|
|
11998
12174
|
] });
|
|
11999
12175
|
};
|
|
12000
12176
|
var RelatedObjectPrimaryCard = ({ record, model, allModels, customPageName }) => {
|
|
12001
|
-
const allModelsList =
|
|
12177
|
+
const allModelsList = React6.useMemo(() => allModels || [], [allModels]);
|
|
12002
12178
|
const tone = useModelTone(model);
|
|
12003
|
-
const PrimaryShowRenderer =
|
|
12179
|
+
const PrimaryShowRenderer = React6.useContext(PrimaryShowContext);
|
|
12004
12180
|
const label = getRecordDisplayLabel(record);
|
|
12005
12181
|
const id = record?.eid ?? record?.id;
|
|
12006
12182
|
const resource = resolveResourcePath(model.resource || model.name, allModelsList);
|
|
@@ -12090,22 +12266,22 @@ var RelatedObjectsEditableList = ({ rel, record, allModels }) => {
|
|
|
12090
12266
|
const location = reactRouterDom.useLocation();
|
|
12091
12267
|
const apiUrl = core.useApiUrl();
|
|
12092
12268
|
const { token } = antd.theme.useToken();
|
|
12093
|
-
const [page, setPage] =
|
|
12094
|
-
const [pageSize, setPageSize] =
|
|
12269
|
+
const [page, setPage] = React6.useState(1);
|
|
12270
|
+
const [pageSize, setPageSize] = React6.useState(INLINE_DEFAULT_PAGE_SIZE);
|
|
12095
12271
|
const { items: fetchedItems, loading, error, total } = useRelatedInlineItems({ rel, record, allModels, page, pageSize });
|
|
12096
|
-
const [localItems, setLocalItems] =
|
|
12097
|
-
|
|
12272
|
+
const [localItems, setLocalItems] = React6.useState(null);
|
|
12273
|
+
React6.useEffect(() => {
|
|
12098
12274
|
setLocalItems(null);
|
|
12099
12275
|
}, [fetchedItems]);
|
|
12100
12276
|
const items = localItems ?? fetchedItems;
|
|
12101
|
-
const [editing, setEditing] =
|
|
12102
|
-
const [saving, setSaving] =
|
|
12103
|
-
const [allOptions, setAllOptions] =
|
|
12104
|
-
const [optionsLoading, setOptionsLoading] =
|
|
12105
|
-
const [selectedIds, setSelectedIds] =
|
|
12106
|
-
const [baselineIds, setBaselineIds] =
|
|
12107
|
-
const [searchText, setSearchText] =
|
|
12108
|
-
|
|
12277
|
+
const [editing, setEditing] = React6.useState(false);
|
|
12278
|
+
const [saving, setSaving] = React6.useState(false);
|
|
12279
|
+
const [allOptions, setAllOptions] = React6.useState([]);
|
|
12280
|
+
const [optionsLoading, setOptionsLoading] = React6.useState(false);
|
|
12281
|
+
const [selectedIds, setSelectedIds] = React6.useState(/* @__PURE__ */ new Set());
|
|
12282
|
+
const [baselineIds, setBaselineIds] = React6.useState(/* @__PURE__ */ new Set());
|
|
12283
|
+
const [searchText, setSearchText] = React6.useState("");
|
|
12284
|
+
React6.useEffect(() => {
|
|
12109
12285
|
if (!editing) return;
|
|
12110
12286
|
const snapshot = new Set(items.map((item) => Number(item.id)));
|
|
12111
12287
|
setBaselineIds(snapshot);
|
|
@@ -12139,7 +12315,7 @@ var RelatedObjectsEditableList = ({ rel, record, allModels }) => {
|
|
|
12139
12315
|
cancelled = true;
|
|
12140
12316
|
};
|
|
12141
12317
|
}, [editing]);
|
|
12142
|
-
const handleSave =
|
|
12318
|
+
const handleSave = React6.useCallback(async () => {
|
|
12143
12319
|
if (!rel.otherKey || !rel.targetKey) return;
|
|
12144
12320
|
const recordId = record?.eid ?? record?.id;
|
|
12145
12321
|
if (recordId === void 0 || recordId === null) return;
|
|
@@ -12215,12 +12391,12 @@ var RelatedObjectsEditableList = ({ rel, record, allModels }) => {
|
|
|
12215
12391
|
setSaving(false);
|
|
12216
12392
|
}
|
|
12217
12393
|
}, [apiUrl, allModels, allOptions, rel, record, selectedIds, baselineIds]);
|
|
12218
|
-
const handleCancel =
|
|
12394
|
+
const handleCancel = React6.useCallback(() => {
|
|
12219
12395
|
setEditing(false);
|
|
12220
12396
|
setSelectedIds(new Set(baselineIds));
|
|
12221
12397
|
setSearchText("");
|
|
12222
12398
|
}, [baselineIds]);
|
|
12223
|
-
const handleCreateNewAndRelate =
|
|
12399
|
+
const handleCreateNewAndRelate = React6.useCallback(() => {
|
|
12224
12400
|
const otherKey = rel.otherKey;
|
|
12225
12401
|
if (!otherKey || !rel.targetKey) return;
|
|
12226
12402
|
const recordId = record?.eid ?? record?.id;
|
|
@@ -12376,17 +12552,17 @@ var _33 = window._ || ((text) => text);
|
|
|
12376
12552
|
var RelatedObjectsEditableCsv = ({ rel, record, allModels }) => {
|
|
12377
12553
|
const apiUrl = core.useApiUrl();
|
|
12378
12554
|
const { items: fetchedItems, loading, error } = useRelatedInlineItems({ rel, record, allModels });
|
|
12379
|
-
const [saving, setSaving] =
|
|
12380
|
-
const [allOptions, setAllOptions] =
|
|
12381
|
-
const [optionsLoading, setOptionsLoading] =
|
|
12382
|
-
const [selectedIds, setSelectedIds] =
|
|
12383
|
-
const [baselineIds, setBaselineIds] =
|
|
12384
|
-
|
|
12555
|
+
const [saving, setSaving] = React6.useState(false);
|
|
12556
|
+
const [allOptions, setAllOptions] = React6.useState([]);
|
|
12557
|
+
const [optionsLoading, setOptionsLoading] = React6.useState(false);
|
|
12558
|
+
const [selectedIds, setSelectedIds] = React6.useState([]);
|
|
12559
|
+
const [baselineIds, setBaselineIds] = React6.useState(/* @__PURE__ */ new Set());
|
|
12560
|
+
React6.useEffect(() => {
|
|
12385
12561
|
const ids = fetchedItems.map((item) => Number(item.id));
|
|
12386
12562
|
setSelectedIds(ids);
|
|
12387
12563
|
setBaselineIds(new Set(ids));
|
|
12388
12564
|
}, [fetchedItems]);
|
|
12389
|
-
|
|
12565
|
+
React6.useEffect(() => {
|
|
12390
12566
|
if (!rel.otherResource) return;
|
|
12391
12567
|
let cancelled = false;
|
|
12392
12568
|
const fetchOptions = async () => {
|
|
@@ -12413,7 +12589,7 @@ var RelatedObjectsEditableCsv = ({ rel, record, allModels }) => {
|
|
|
12413
12589
|
cancelled = true;
|
|
12414
12590
|
};
|
|
12415
12591
|
}, [apiUrl, rel.otherResource]);
|
|
12416
|
-
const handleChange =
|
|
12592
|
+
const handleChange = React6.useCallback(async (newIds) => {
|
|
12417
12593
|
if (!rel.otherKey || !rel.targetKey) return;
|
|
12418
12594
|
const recordId = record?.eid ?? record?.id;
|
|
12419
12595
|
if (recordId === void 0 || recordId === null) return;
|
|
@@ -12475,15 +12651,15 @@ var { Title: Title4 } = antd.Typography;
|
|
|
12475
12651
|
var PolymorphicRelatedObjectsTable = ({ rel, record, relationModel, parentModel, allModels, showActions = false, showCreate = false, allowInlineEdit = false, layoutPreferenceType, viewVariant = "default", viewMode = "table" }) => {
|
|
12476
12652
|
const recordId = record?.[parentModel?.pkField ?? "eid"] ?? record?.eid ?? record?.id;
|
|
12477
12653
|
const apiUrl = core.useApiUrl();
|
|
12478
|
-
const [loading, setLoading] =
|
|
12479
|
-
const [error, setError] =
|
|
12480
|
-
const [groupedIds, setGroupedIds] =
|
|
12481
|
-
const [unresolvedIds, setUnresolvedIds] =
|
|
12482
|
-
const polyInfo =
|
|
12654
|
+
const [loading, setLoading] = React6.useState(false);
|
|
12655
|
+
const [error, setError] = React6.useState(null);
|
|
12656
|
+
const [groupedIds, setGroupedIds] = React6.useState(/* @__PURE__ */ new Map());
|
|
12657
|
+
const [unresolvedIds, setUnresolvedIds] = React6.useState([]);
|
|
12658
|
+
const polyInfo = React6.useMemo(
|
|
12483
12659
|
() => getPolymorphicReferenceInfo(rel, relationModel, allModels),
|
|
12484
12660
|
[rel.otherKey, rel.otherResource, relationModel, allModels]
|
|
12485
12661
|
);
|
|
12486
|
-
|
|
12662
|
+
React6.useEffect(() => {
|
|
12487
12663
|
if (!recordId || !rel.otherKey || !polyInfo) {
|
|
12488
12664
|
setGroupedIds(/* @__PURE__ */ new Map());
|
|
12489
12665
|
setUnresolvedIds([]);
|
|
@@ -12602,96 +12778,96 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12602
12778
|
color: relatedModelTone.solid,
|
|
12603
12779
|
margin: 0
|
|
12604
12780
|
};
|
|
12605
|
-
const chartSvgRef =
|
|
12606
|
-
const skipNextAnimationRef =
|
|
12607
|
-
const [rows, setRows] =
|
|
12608
|
-
const [localSearch, setLocalSearch] =
|
|
12609
|
-
const [filterRules, setFilterRules] =
|
|
12610
|
-
const [filtersCollapsed, setFiltersCollapsed] =
|
|
12611
|
-
const [columnsSelectorOpen, setColumnsSelectorOpen] =
|
|
12612
|
-
const [selectedColumnKeys, setSelectedColumnKeys] =
|
|
12613
|
-
const [columnOrder, setColumnOrder] =
|
|
12614
|
-
const [totalsSummaryFunctions, setTotalsSummaryFunctions] =
|
|
12615
|
-
const [columnFiltersSelected, setColumnFiltersSelected] =
|
|
12616
|
-
const [columnSort, setColumnSort] =
|
|
12617
|
-
const [currentViewName, setCurrentViewName] =
|
|
12618
|
-
const [selectedViewNames, setSelectedViewNames] =
|
|
12619
|
-
const [availableViewNames, setAvailableViewNames] =
|
|
12620
|
-
const [viewNamesLoaded, setViewNamesLoaded] =
|
|
12621
|
-
const [isLoadingViewNames, setIsLoadingViewNames] =
|
|
12622
|
-
const [saveViewModalOpen, setSaveViewModalOpen] =
|
|
12623
|
-
const [saveViewName, setSaveViewName] =
|
|
12624
|
-
const [saveViewAsNew, setSaveViewAsNew] =
|
|
12625
|
-
const [pendingSaveTarget, setPendingSaveTarget] =
|
|
12626
|
-
const [renameViewModalOpen, setRenameViewModalOpen] =
|
|
12627
|
-
const [renameViewName, setRenameViewName] =
|
|
12628
|
-
const [pageSize, setPageSize] =
|
|
12629
|
-
const [currentPage, setCurrentPage] =
|
|
12630
|
-
const [serverTotalRows, setServerTotalRows] =
|
|
12631
|
-
const [fullDataLoaded, setFullDataLoaded] =
|
|
12632
|
-
const [relationRowsCapped, setRelationRowsCapped] =
|
|
12633
|
-
const [loadedRowsCount, setLoadedRowsCount] =
|
|
12634
|
-
const [loadAllRelatedRequested, setLoadAllRelatedRequested] =
|
|
12635
|
-
const [loading, setLoading] =
|
|
12636
|
-
const [error, setError] =
|
|
12637
|
-
const [listVisible, setListVisible] =
|
|
12638
|
-
const [isAnalyzeVertical, setIsAnalyzeVertical] =
|
|
12639
|
-
const [isAnalyzeFirst, setIsAnalyzeFirst] =
|
|
12640
|
-
const [labelCache, setLabelCache] =
|
|
12641
|
-
const [analyzeOpen, setAnalyzeOpen] =
|
|
12642
|
-
const analyzeTouchedRef =
|
|
12643
|
-
const analyzePrefsTouchedRef =
|
|
12644
|
-
const analyzePrefsLoadedRef =
|
|
12645
|
-
const [analyzePrefsReady, setAnalyzePrefsReady] =
|
|
12646
|
-
const analyzePrefsResourceRef =
|
|
12647
|
-
const [categoryField1, setCategoryField1] =
|
|
12648
|
-
const [categoryField2, setCategoryField2] =
|
|
12649
|
-
const [crosstabFilterFields, setCrosstabFilterFields] =
|
|
12650
|
-
const [crosstabStaged, setCrosstabStaged] =
|
|
12651
|
-
const [chartType, setChartType] =
|
|
12652
|
-
const [summaryFn, setSummaryFn] =
|
|
12653
|
-
const [selectedSeriesKeys, setSelectedSeriesKeys] =
|
|
12654
|
-
const [rankingMode, setRankingMode] =
|
|
12655
|
-
const [rankingFieldKey, setRankingFieldKey] =
|
|
12656
|
-
const [rankingN, setRankingN] =
|
|
12657
|
-
const [exportRequested, setExportRequested] =
|
|
12658
|
-
const [isStatsFlipped, setIsStatsFlipped] =
|
|
12659
|
-
const [isSavingAnalyzePrefs, setIsSavingAnalyzePrefs] =
|
|
12660
|
-
const [chartAnimationKey, setChartAnimationKey] =
|
|
12661
|
-
const [chartAnimationStage, setChartAnimationStage] =
|
|
12662
|
-
const [isTotalsDetailsFlipped, setIsTotalsDetailsFlipped] =
|
|
12663
|
-
const defaultDisplayFields =
|
|
12664
|
-
const orderedColumnKeys =
|
|
12781
|
+
const chartSvgRef = React6.useRef(null);
|
|
12782
|
+
const skipNextAnimationRef = React6.useRef(false);
|
|
12783
|
+
const [rows, setRows] = React6.useState([]);
|
|
12784
|
+
const [localSearch, setLocalSearch] = React6.useState("");
|
|
12785
|
+
const [filterRules, setFilterRules] = React6.useState([]);
|
|
12786
|
+
const [filtersCollapsed, setFiltersCollapsed] = React6.useState(true);
|
|
12787
|
+
const [columnsSelectorOpen, setColumnsSelectorOpen] = React6.useState(false);
|
|
12788
|
+
const [selectedColumnKeys, setSelectedColumnKeys] = React6.useState(null);
|
|
12789
|
+
const [columnOrder, setColumnOrder] = React6.useState(null);
|
|
12790
|
+
const [totalsSummaryFunctions, setTotalsSummaryFunctions] = React6.useState({});
|
|
12791
|
+
const [columnFiltersSelected, setColumnFiltersSelected] = React6.useState({});
|
|
12792
|
+
const [columnSort, setColumnSort] = React6.useState([]);
|
|
12793
|
+
const [currentViewName, setCurrentViewName] = React6.useState(getDefaultViewName());
|
|
12794
|
+
const [selectedViewNames, setSelectedViewNames] = React6.useState([]);
|
|
12795
|
+
const [availableViewNames, setAvailableViewNames] = React6.useState([]);
|
|
12796
|
+
const [viewNamesLoaded, setViewNamesLoaded] = React6.useState(false);
|
|
12797
|
+
const [isLoadingViewNames, setIsLoadingViewNames] = React6.useState(false);
|
|
12798
|
+
const [saveViewModalOpen, setSaveViewModalOpen] = React6.useState(false);
|
|
12799
|
+
const [saveViewName, setSaveViewName] = React6.useState(getDefaultViewName());
|
|
12800
|
+
const [saveViewAsNew, setSaveViewAsNew] = React6.useState(false);
|
|
12801
|
+
const [pendingSaveTarget, setPendingSaveTarget] = React6.useState(null);
|
|
12802
|
+
const [renameViewModalOpen, setRenameViewModalOpen] = React6.useState(false);
|
|
12803
|
+
const [renameViewName, setRenameViewName] = React6.useState("");
|
|
12804
|
+
const [pageSize, setPageSize] = React6.useState(10);
|
|
12805
|
+
const [currentPage, setCurrentPage] = React6.useState(1);
|
|
12806
|
+
const [serverTotalRows, setServerTotalRows] = React6.useState(0);
|
|
12807
|
+
const [fullDataLoaded, setFullDataLoaded] = React6.useState(false);
|
|
12808
|
+
const [relationRowsCapped, setRelationRowsCapped] = React6.useState(false);
|
|
12809
|
+
const [loadedRowsCount, setLoadedRowsCount] = React6.useState(0);
|
|
12810
|
+
const [loadAllRelatedRequested, setLoadAllRelatedRequested] = React6.useState(false);
|
|
12811
|
+
const [loading, setLoading] = React6.useState(false);
|
|
12812
|
+
const [error, setError] = React6.useState(null);
|
|
12813
|
+
const [listVisible, setListVisible] = React6.useState(true);
|
|
12814
|
+
const [isAnalyzeVertical, setIsAnalyzeVertical] = React6.useState(false);
|
|
12815
|
+
const [isAnalyzeFirst, setIsAnalyzeFirst] = React6.useState(false);
|
|
12816
|
+
const [labelCache, setLabelCache] = React6.useState({});
|
|
12817
|
+
const [analyzeOpen, setAnalyzeOpen] = React6.useState(false);
|
|
12818
|
+
const analyzeTouchedRef = React6.useRef(false);
|
|
12819
|
+
const analyzePrefsTouchedRef = React6.useRef(false);
|
|
12820
|
+
const analyzePrefsLoadedRef = React6.useRef(false);
|
|
12821
|
+
const [analyzePrefsReady, setAnalyzePrefsReady] = React6.useState(false);
|
|
12822
|
+
const analyzePrefsResourceRef = React6.useRef(null);
|
|
12823
|
+
const [categoryField1, setCategoryField1] = React6.useState(null);
|
|
12824
|
+
const [categoryField2, setCategoryField2] = React6.useState(void 0);
|
|
12825
|
+
const [crosstabFilterFields, setCrosstabFilterFields] = React6.useState([]);
|
|
12826
|
+
const [crosstabStaged, setCrosstabStaged] = React6.useState({});
|
|
12827
|
+
const [chartType, setChartType] = React6.useState("area");
|
|
12828
|
+
const [summaryFn, setSummaryFn] = React6.useState("sum");
|
|
12829
|
+
const [selectedSeriesKeys, setSelectedSeriesKeys] = React6.useState(null);
|
|
12830
|
+
const [rankingMode, setRankingMode] = React6.useState("none");
|
|
12831
|
+
const [rankingFieldKey, setRankingFieldKey] = React6.useState(null);
|
|
12832
|
+
const [rankingN, setRankingN] = React6.useState(10);
|
|
12833
|
+
const [exportRequested, setExportRequested] = React6.useState(false);
|
|
12834
|
+
const [isStatsFlipped, setIsStatsFlipped] = React6.useState(false);
|
|
12835
|
+
const [isSavingAnalyzePrefs, setIsSavingAnalyzePrefs] = React6.useState(false);
|
|
12836
|
+
const [chartAnimationKey, setChartAnimationKey] = React6.useState(0);
|
|
12837
|
+
const [chartAnimationStage, setChartAnimationStage] = React6.useState("enter");
|
|
12838
|
+
const [isTotalsDetailsFlipped, setIsTotalsDetailsFlipped] = React6.useState(false);
|
|
12839
|
+
const defaultDisplayFields = React6.useMemo(() => getListViewFields(relatedModel), [relatedModel]);
|
|
12840
|
+
const orderedColumnKeys = React6.useMemo(() => {
|
|
12665
12841
|
if (!selectedColumnKeys || selectedColumnKeys.length === 0) return null;
|
|
12666
12842
|
const order = columnOrder && columnOrder.length > 0 ? columnOrder : selectedColumnKeys;
|
|
12667
12843
|
const selectedSet = new Set(selectedColumnKeys);
|
|
12668
12844
|
const availableKeys = new Set(relatedModel.fields.map((field) => field.key));
|
|
12669
12845
|
return order.filter((key) => selectedSet.has(key) && availableKeys.has(key));
|
|
12670
12846
|
}, [columnOrder, relatedModel.fields, selectedColumnKeys]);
|
|
12671
|
-
const displayFields =
|
|
12847
|
+
const displayFields = React6.useMemo(() => {
|
|
12672
12848
|
if (!orderedColumnKeys) return defaultDisplayFields;
|
|
12673
12849
|
const fieldMap = new Map(relatedModel.fields.map((field) => [field.key, field]));
|
|
12674
12850
|
return orderedColumnKeys.map((key) => fieldMap.get(key)).filter((field) => Boolean(field));
|
|
12675
12851
|
}, [defaultDisplayFields, orderedColumnKeys, relatedModel.fields]);
|
|
12676
12852
|
const numericBarColor = relatedModelTone.soft || token.colorPrimaryBg || "rgba(22, 119, 255, 0.16)";
|
|
12677
12853
|
const [form] = antd.Form.useForm();
|
|
12678
|
-
const [savingAll, setSavingAll] =
|
|
12679
|
-
const [hasPendingEdits, setHasPendingEdits] =
|
|
12854
|
+
const [savingAll, setSavingAll] = React6.useState(false);
|
|
12855
|
+
const [hasPendingEdits, setHasPendingEdits] = React6.useState(false);
|
|
12680
12856
|
const { setWarnWhen } = core.useWarnAboutChange();
|
|
12681
|
-
const [isSavingLayoutPrefs, setIsSavingLayoutPrefs] =
|
|
12682
|
-
const layoutPrefsTouchedRef =
|
|
12683
|
-
const layoutPrefsLoadedRef =
|
|
12684
|
-
const layoutPrefsResourceRef =
|
|
12685
|
-
const sortIntentRef =
|
|
12857
|
+
const [isSavingLayoutPrefs, setIsSavingLayoutPrefs] = React6.useState(false);
|
|
12858
|
+
const layoutPrefsTouchedRef = React6.useRef(false);
|
|
12859
|
+
const layoutPrefsLoadedRef = React6.useRef(false);
|
|
12860
|
+
const layoutPrefsResourceRef = React6.useRef(null);
|
|
12861
|
+
const sortIntentRef = React6.useRef(null);
|
|
12686
12862
|
const { settings: viewSettings } = useViewSettings();
|
|
12687
12863
|
const relationsMaxRowsToLoad = Math.max(0, Number(viewSettings?.relationsMaxRowsToLoad ?? 1e3));
|
|
12688
|
-
const markAnalyzePrefsTouched =
|
|
12864
|
+
const markAnalyzePrefsTouched = React6.useCallback(() => {
|
|
12689
12865
|
analyzePrefsTouchedRef.current = true;
|
|
12690
12866
|
}, []);
|
|
12691
|
-
const markLayoutPrefsTouched =
|
|
12867
|
+
const markLayoutPrefsTouched = React6.useCallback(() => {
|
|
12692
12868
|
layoutPrefsTouchedRef.current = true;
|
|
12693
12869
|
}, []);
|
|
12694
|
-
const persistLayoutPreferences =
|
|
12870
|
+
const persistLayoutPreferences = React6.useCallback(async (viewName) => {
|
|
12695
12871
|
if (!layoutPreferenceType) return;
|
|
12696
12872
|
const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
|
|
12697
12873
|
const resolvedViewName = normalizeViewName(viewName);
|
|
@@ -12735,7 +12911,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12735
12911
|
setIsSavingLayoutPrefs(false);
|
|
12736
12912
|
}
|
|
12737
12913
|
}, [apiUrl, analyzeOpen, columnFiltersSelected, columnOrder, columnSort, filtersCollapsed, filterRules, isAnalyzeFirst, isAnalyzeVertical, layoutPreferenceType, listVisible, pageSize, selectedColumnKeys, relatedModel.name, relatedModel.resource, totalsSummaryFunctions, allModels]);
|
|
12738
|
-
const persistAnalyzePreferences =
|
|
12914
|
+
const persistAnalyzePreferences = React6.useCallback(async (viewName) => {
|
|
12739
12915
|
const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
|
|
12740
12916
|
const resolvedViewName = normalizeViewName(viewName);
|
|
12741
12917
|
const preferences = {
|
|
@@ -12767,13 +12943,13 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12767
12943
|
setIsSavingAnalyzePrefs(false);
|
|
12768
12944
|
}
|
|
12769
12945
|
}, [apiUrl, categoryField1, categoryField2, chartType, selectedSeriesKeys, summaryFn, rankingMode, rankingFieldKey, rankingN, crosstabFilterFields, relatedModel.name, relatedModel.resource, allModels]);
|
|
12770
|
-
const categoricalFields =
|
|
12946
|
+
const categoricalFields = React6.useMemo(() => {
|
|
12771
12947
|
return relatedModel.fields.filter((field) => isPkField(field, relatedModel) || (field.type !== "number" || field.reference));
|
|
12772
12948
|
}, [relatedModel]);
|
|
12773
|
-
const numericFields =
|
|
12949
|
+
const numericFields = React6.useMemo(() => {
|
|
12774
12950
|
return relatedModel.fields.filter((field) => !isPkField(field, relatedModel) && field.type === "number" && !field.reference);
|
|
12775
12951
|
}, [relatedModel]);
|
|
12776
|
-
const resetLayoutDefaults =
|
|
12952
|
+
const resetLayoutDefaults = React6.useCallback(() => {
|
|
12777
12953
|
setListVisible(true);
|
|
12778
12954
|
setAnalyzeOpen(false);
|
|
12779
12955
|
setIsAnalyzeVertical(false);
|
|
@@ -12783,7 +12959,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12783
12959
|
setSelectedColumnKeys(null);
|
|
12784
12960
|
setColumnOrder(null);
|
|
12785
12961
|
}, []);
|
|
12786
|
-
const resetAnalyzeDefaults =
|
|
12962
|
+
const resetAnalyzeDefaults = React6.useCallback(() => {
|
|
12787
12963
|
setCategoryField1(categoricalFields[0]?.key ?? null);
|
|
12788
12964
|
setCategoryField2(categoricalFields.length > 1 ? categoricalFields[1].key : null);
|
|
12789
12965
|
setChartType("area");
|
|
@@ -12794,7 +12970,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12794
12970
|
setRankingN(10);
|
|
12795
12971
|
setCrosstabFilterFields([]);
|
|
12796
12972
|
}, [categoricalFields, numericFields]);
|
|
12797
|
-
const persistCurrentViewNames =
|
|
12973
|
+
const persistCurrentViewNames = React6.useCallback(async (nextSelected, nextCurrent) => {
|
|
12798
12974
|
try {
|
|
12799
12975
|
const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
|
|
12800
12976
|
await authenticatedFetch(`${apiUrl}/views/preferences/view`, {
|
|
@@ -12810,7 +12986,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12810
12986
|
} catch {
|
|
12811
12987
|
}
|
|
12812
12988
|
}, [apiUrl, relatedModel.name, relatedModel.resource, allModels]);
|
|
12813
|
-
const loadViewNames =
|
|
12989
|
+
const loadViewNames = React6.useCallback(async () => {
|
|
12814
12990
|
const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
|
|
12815
12991
|
setIsLoadingViewNames(true);
|
|
12816
12992
|
try {
|
|
@@ -12855,13 +13031,13 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12855
13031
|
setIsLoadingViewNames(false);
|
|
12856
13032
|
}
|
|
12857
13033
|
}, [apiUrl, relatedModel.name, relatedModel.resource, allModels]);
|
|
12858
|
-
const openSaveViewModalFor =
|
|
13034
|
+
const openSaveViewModalFor = React6.useCallback((target) => {
|
|
12859
13035
|
setSaveViewName(currentViewName || getDefaultViewName());
|
|
12860
13036
|
setSaveViewAsNew(false);
|
|
12861
13037
|
setPendingSaveTarget(target);
|
|
12862
13038
|
setSaveViewModalOpen(true);
|
|
12863
13039
|
}, [currentViewName]);
|
|
12864
|
-
const handleConfirmSaveView =
|
|
13040
|
+
const handleConfirmSaveView = React6.useCallback(async () => {
|
|
12865
13041
|
if (!pendingSaveTarget) return;
|
|
12866
13042
|
const viewName = normalizeViewName(saveViewName || currentViewName);
|
|
12867
13043
|
const viewExists = availableViewNames.includes(viewName);
|
|
@@ -12888,14 +13064,14 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12888
13064
|
await persistCurrentViewNames(nextSelected, viewName);
|
|
12889
13065
|
await loadViewNames();
|
|
12890
13066
|
}, [availableViewNames, currentViewName, loadViewNames, pendingSaveTarget, persistAnalyzePreferences, persistCurrentViewNames, persistLayoutPreferences, saveViewAsNew, saveViewName, selectedViewNames]);
|
|
12891
|
-
const handleChangeViewName =
|
|
13067
|
+
const handleChangeViewName = React6.useCallback(async (nextView) => {
|
|
12892
13068
|
const resolvedName = normalizeViewName(nextView);
|
|
12893
13069
|
setCurrentViewName(resolvedName);
|
|
12894
13070
|
setSaveViewName(resolvedName);
|
|
12895
13071
|
const nextSelected = selectedViewNames.length > 0 ? selectedViewNames : [resolvedName];
|
|
12896
13072
|
await persistCurrentViewNames(nextSelected, resolvedName);
|
|
12897
13073
|
}, [persistCurrentViewNames, selectedViewNames]);
|
|
12898
|
-
const updateSelectedViewNames =
|
|
13074
|
+
const updateSelectedViewNames = React6.useCallback(async (nextSelected) => {
|
|
12899
13075
|
if (nextSelected.length === 0) {
|
|
12900
13076
|
nextSelected = [getDefaultViewName()];
|
|
12901
13077
|
}
|
|
@@ -12907,7 +13083,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12907
13083
|
}
|
|
12908
13084
|
await persistCurrentViewNames(nextSelected, nextCurrent);
|
|
12909
13085
|
}, [currentViewName, persistCurrentViewNames]);
|
|
12910
|
-
const moveSelectedView =
|
|
13086
|
+
const moveSelectedView = React6.useCallback((name, direction) => {
|
|
12911
13087
|
setSelectedViewNames((prev) => {
|
|
12912
13088
|
const idx = prev.indexOf(name);
|
|
12913
13089
|
if (idx < 0) return prev;
|
|
@@ -12919,7 +13095,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12919
13095
|
return next;
|
|
12920
13096
|
});
|
|
12921
13097
|
}, [currentViewName, persistCurrentViewNames]);
|
|
12922
|
-
const handleRenameView =
|
|
13098
|
+
const handleRenameView = React6.useCallback(async () => {
|
|
12923
13099
|
const newName = normalizeViewName(renameViewName);
|
|
12924
13100
|
if (!newName || newName === currentViewName) {
|
|
12925
13101
|
setRenameViewModalOpen(false);
|
|
@@ -12946,7 +13122,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12946
13122
|
antd.message.error(error2 instanceof Error ? error2.message : _34("Failed to rename view."));
|
|
12947
13123
|
}
|
|
12948
13124
|
}, [apiUrl, availableViewNames, currentViewName, relatedModel.name, relatedModel.resource, renameViewName, allModels, loadViewNames]);
|
|
12949
|
-
const confirmDeleteView =
|
|
13125
|
+
const confirmDeleteView = React6.useCallback(() => {
|
|
12950
13126
|
antd.Modal.confirm({
|
|
12951
13127
|
title: _34(_34("Delete view")),
|
|
12952
13128
|
content: `Delete "${currentViewName}" and all its saved preferences?`,
|
|
@@ -12991,10 +13167,10 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
12991
13167
|
items: selectedViewNames.map((name) => ({ key: name, label: renderToneTabLabel(name, relatedModelTone) }))
|
|
12992
13168
|
}
|
|
12993
13169
|
) : null;
|
|
12994
|
-
|
|
13170
|
+
React6.useEffect(() => {
|
|
12995
13171
|
loadViewNames();
|
|
12996
13172
|
}, [loadViewNames]);
|
|
12997
|
-
|
|
13173
|
+
React6.useEffect(() => {
|
|
12998
13174
|
if (!viewNamesLoaded) return;
|
|
12999
13175
|
analyzePrefsTouchedRef.current = false;
|
|
13000
13176
|
layoutPrefsTouchedRef.current = false;
|
|
@@ -13006,7 +13182,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13006
13182
|
resetLayoutDefaults();
|
|
13007
13183
|
resetAnalyzeDefaults();
|
|
13008
13184
|
}, [currentViewName, resetAnalyzeDefaults, resetLayoutDefaults, viewNamesLoaded]);
|
|
13009
|
-
|
|
13185
|
+
React6.useEffect(() => {
|
|
13010
13186
|
const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
|
|
13011
13187
|
const viewKey = `${resourceKey}::${currentViewName}`;
|
|
13012
13188
|
if (analyzePrefsResourceRef.current !== viewKey) {
|
|
@@ -13059,7 +13235,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13059
13235
|
cancelled = true;
|
|
13060
13236
|
};
|
|
13061
13237
|
}, [apiUrl, currentViewName, relatedModel.name, relatedModel.resource, allModels]);
|
|
13062
|
-
|
|
13238
|
+
React6.useEffect(() => {
|
|
13063
13239
|
if (!layoutPreferenceType) return;
|
|
13064
13240
|
const resourceKey = resolveResourcePath(relatedModel.resource || relatedModel.name, allModels);
|
|
13065
13241
|
const viewKey = `${resourceKey}::${layoutPreferenceType}::${currentViewName}`;
|
|
@@ -13138,17 +13314,17 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13138
13314
|
cancelled = true;
|
|
13139
13315
|
};
|
|
13140
13316
|
}, [apiUrl, currentViewName, layoutPreferenceType, relatedModel.name, relatedModel.resource, allModels, viewNamesLoaded]);
|
|
13141
|
-
const normalizeFieldValue =
|
|
13317
|
+
const normalizeFieldValue = React6.useCallback((field, value) => {
|
|
13142
13318
|
if (field.type === "date" && value) {
|
|
13143
13319
|
if (typeof value?.toISOString === "function") return value.toISOString();
|
|
13144
13320
|
if (typeof value?.format === "function") return value.format("YYYY-MM-DD");
|
|
13145
13321
|
}
|
|
13146
13322
|
return value;
|
|
13147
13323
|
}, []);
|
|
13148
|
-
const hasActiveFilterRules =
|
|
13324
|
+
const hasActiveFilterRules = React6.useMemo(() => {
|
|
13149
13325
|
return filterRules.some((rule) => rule.fieldKey && rule.operator && (rule.value !== void 0 && rule.value !== null && rule.value !== ""));
|
|
13150
13326
|
}, [filterRules]);
|
|
13151
|
-
const resolveRelativeDate =
|
|
13327
|
+
const resolveRelativeDate = React6.useCallback((value, asRange) => {
|
|
13152
13328
|
const count = Number(value?.count ?? 1);
|
|
13153
13329
|
const direction = value?.direction || "next";
|
|
13154
13330
|
const unit = value?.unit || "weeks";
|
|
@@ -13174,7 +13350,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13174
13350
|
}
|
|
13175
13351
|
return { date: target.startOf(unit) };
|
|
13176
13352
|
}, []);
|
|
13177
|
-
const getFieldValueForFilter =
|
|
13353
|
+
const getFieldValueForFilter = React6.useCallback((field, recordRow) => {
|
|
13178
13354
|
const raw = recordRow?.[field.key];
|
|
13179
13355
|
if (raw === void 0 || raw === null) return raw;
|
|
13180
13356
|
if (field.reference) {
|
|
@@ -13186,7 +13362,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13186
13362
|
}
|
|
13187
13363
|
return raw;
|
|
13188
13364
|
}, [labelCache]);
|
|
13189
|
-
const matchesRule =
|
|
13365
|
+
const matchesRule = React6.useCallback((recordRow, rule) => {
|
|
13190
13366
|
const field = relatedModel.fields.find((f) => f.key === rule.fieldKey);
|
|
13191
13367
|
if (!field || !rule.operator) return true;
|
|
13192
13368
|
const rawValue = getFieldValueForFilter(field, recordRow);
|
|
@@ -13266,7 +13442,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13266
13442
|
}
|
|
13267
13443
|
return true;
|
|
13268
13444
|
}, [getFieldValueForFilter, relatedModel.fields, resolveRelativeDate]);
|
|
13269
|
-
const applyGlobalSearch =
|
|
13445
|
+
const applyGlobalSearch = React6.useCallback((data) => {
|
|
13270
13446
|
const query = localSearch.trim().toLowerCase();
|
|
13271
13447
|
if (!query) return data;
|
|
13272
13448
|
return data.filter((recordRow) => {
|
|
@@ -13285,14 +13461,14 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13285
13461
|
return candidates.some((value) => value !== void 0 && value !== null && String(value).toLowerCase().includes(query));
|
|
13286
13462
|
});
|
|
13287
13463
|
}, [labelCache, localSearch, relatedModel.fields]);
|
|
13288
|
-
const applyFilterRules =
|
|
13464
|
+
const applyFilterRules = React6.useCallback((data) => {
|
|
13289
13465
|
if (!hasActiveFilterRules) return data;
|
|
13290
13466
|
return data.filter((recordRow) => filterRules.every((rule) => matchesRule(recordRow, rule)));
|
|
13291
13467
|
}, [filterRules, hasActiveFilterRules, matchesRule]);
|
|
13292
|
-
const filteredRows =
|
|
13468
|
+
const filteredRows = React6.useMemo(() => {
|
|
13293
13469
|
return applyFilterRules(applyGlobalSearch(rows || []));
|
|
13294
13470
|
}, [applyFilterRules, applyGlobalSearch, rows]);
|
|
13295
|
-
const columnFilteredRows =
|
|
13471
|
+
const columnFilteredRows = React6.useMemo(() => {
|
|
13296
13472
|
const activeEntries = Object.entries(columnFiltersSelected).filter(([, values]) => values && values.length > 0);
|
|
13297
13473
|
if (activeEntries.length === 0) return filteredRows;
|
|
13298
13474
|
return filteredRows.filter(
|
|
@@ -13303,10 +13479,10 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13303
13479
|
})
|
|
13304
13480
|
);
|
|
13305
13481
|
}, [filteredRows, columnFiltersSelected, relatedModel.fields]);
|
|
13306
|
-
|
|
13482
|
+
React6.useEffect(() => {
|
|
13307
13483
|
setCurrentPage(1);
|
|
13308
13484
|
}, [localSearch, filterRules]);
|
|
13309
|
-
|
|
13485
|
+
React6.useEffect(() => {
|
|
13310
13486
|
if (!allowInlineEdit) return;
|
|
13311
13487
|
if (form.isFieldsTouched()) return;
|
|
13312
13488
|
const initialValues = {};
|
|
@@ -13320,7 +13496,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13320
13496
|
});
|
|
13321
13497
|
form.setFieldsValue(initialValues);
|
|
13322
13498
|
}, [allowInlineEdit, form, relatedModel.fields, filteredRows]);
|
|
13323
|
-
|
|
13499
|
+
React6.useEffect(() => {
|
|
13324
13500
|
if (!allowInlineEdit) {
|
|
13325
13501
|
setWarnWhen(false);
|
|
13326
13502
|
return;
|
|
@@ -13328,7 +13504,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13328
13504
|
setWarnWhen(hasPendingEdits);
|
|
13329
13505
|
return () => setWarnWhen(false);
|
|
13330
13506
|
}, [allowInlineEdit, hasPendingEdits, setWarnWhen]);
|
|
13331
|
-
const saveAllEdits =
|
|
13507
|
+
const saveAllEdits = React6.useCallback(async () => {
|
|
13332
13508
|
if (!allowInlineEdit) return;
|
|
13333
13509
|
setSavingAll(true);
|
|
13334
13510
|
try {
|
|
@@ -13382,7 +13558,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13382
13558
|
setSavingAll(false);
|
|
13383
13559
|
}
|
|
13384
13560
|
}, [allowInlineEdit, apiUrl, form, normalizeFieldValue, relatedModel.fields, relatedModel.name, relatedModel.resource, allModels, rows]);
|
|
13385
|
-
const handleDeleteRelationRow =
|
|
13561
|
+
const handleDeleteRelationRow = React6.useCallback((row) => {
|
|
13386
13562
|
const relationRow = row?.__relationRow;
|
|
13387
13563
|
const deleteId = relationRow && rel.targetKey && rel.otherKey ? `${relationRow["eid_from"]}:${relationRow["eid_to"]}` : relationRow?.id ?? relationRow?.eid;
|
|
13388
13564
|
if (deleteId === void 0 || deleteId === null) return;
|
|
@@ -13439,7 +13615,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13439
13615
|
overflow: "visible",
|
|
13440
13616
|
order: isAnalyzeFirst ? 1 : 2
|
|
13441
13617
|
};
|
|
13442
|
-
const getSortValue =
|
|
13618
|
+
const getSortValue = React6.useCallback((field, recordRow) => {
|
|
13443
13619
|
const raw = recordRow?.[field.key];
|
|
13444
13620
|
if (raw === void 0 || raw === null) return null;
|
|
13445
13621
|
if (isPkField(field, relatedModel) && recordRow?._label) return recordRow._label;
|
|
@@ -13458,7 +13634,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13458
13634
|
if (field.type === "boolean") return raw ? 1 : 0;
|
|
13459
13635
|
return raw;
|
|
13460
13636
|
}, [labelCache]);
|
|
13461
|
-
const compareSortValues =
|
|
13637
|
+
const compareSortValues = React6.useCallback((field, a, b) => {
|
|
13462
13638
|
const aVal = getSortValue(field, a);
|
|
13463
13639
|
const bVal = getSortValue(field, b);
|
|
13464
13640
|
if (aVal === null && bVal === null) return 0;
|
|
@@ -13467,11 +13643,11 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13467
13643
|
if (typeof aVal === "number" && typeof bVal === "number") return aVal - bVal;
|
|
13468
13644
|
return String(aVal).localeCompare(String(bVal));
|
|
13469
13645
|
}, [getSortValue]);
|
|
13470
|
-
const shouldUseFullDataMode =
|
|
13646
|
+
const shouldUseFullDataMode = React6.useMemo(() => {
|
|
13471
13647
|
if (loadAllRelatedRequested) return true;
|
|
13472
13648
|
return false;
|
|
13473
13649
|
}, [loadAllRelatedRequested]);
|
|
13474
|
-
const fetchRelatedDetailsByIds =
|
|
13650
|
+
const fetchRelatedDetailsByIds = React6.useCallback(async (ids, signal) => {
|
|
13475
13651
|
const uniqueIds = Array.from(new Set(ids.filter((value) => value !== void 0 && value !== null)));
|
|
13476
13652
|
if (!rel.otherResource || uniqueIds.length === 0) return [];
|
|
13477
13653
|
const relatedResource = rel.otherResourcePath || resolveResourcePath(rel.otherResource, allModels);
|
|
@@ -13522,7 +13698,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13522
13698
|
const now = performance.now();
|
|
13523
13699
|
console.log(`[JM_TRACE ${now.toFixed(1)}ms] ${label}${detail ? " | " + detail : ""}`);
|
|
13524
13700
|
};
|
|
13525
|
-
|
|
13701
|
+
React6.useEffect(() => {
|
|
13526
13702
|
if (!recordId || !rel.otherResource || !rel.otherKey) {
|
|
13527
13703
|
setRows([]);
|
|
13528
13704
|
setServerTotalRows(0);
|
|
@@ -13669,26 +13845,26 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13669
13845
|
controller.abort();
|
|
13670
13846
|
};
|
|
13671
13847
|
}, [apiUrl, currentPage, pageSize, recordId, rel.label, rel.otherKey, rel.otherResource, rel.resource, rel.targetKey, allowedRelatedIds, allModels, rel.resourcePath, rel.otherResourcePath, shouldUseFullDataMode, fetchRelatedDetailsByIds, fullDataLoaded, relationsMaxRowsToLoad, rows.length]);
|
|
13672
|
-
|
|
13848
|
+
React6.useEffect(() => {
|
|
13673
13849
|
if (!shouldUseFullDataMode && fullDataLoaded) {
|
|
13674
13850
|
setFullDataLoaded(false);
|
|
13675
13851
|
}
|
|
13676
13852
|
}, [fullDataLoaded, shouldUseFullDataMode]);
|
|
13677
|
-
|
|
13853
|
+
React6.useEffect(() => {
|
|
13678
13854
|
if (loading) return;
|
|
13679
13855
|
if (analyzeTouchedRef.current) return;
|
|
13680
13856
|
if (filteredRows.length <= 1 && analyzeOpen) {
|
|
13681
13857
|
setAnalyzeOpen(false);
|
|
13682
13858
|
}
|
|
13683
13859
|
}, [analyzeOpen, filteredRows.length, loading]);
|
|
13684
|
-
|
|
13860
|
+
React6.useEffect(() => {
|
|
13685
13861
|
if (loading) return;
|
|
13686
13862
|
if (analyzeTouchedRef.current) return;
|
|
13687
13863
|
if (filteredRows.length > 1 && !analyzeOpen) {
|
|
13688
13864
|
setAnalyzeOpen(true);
|
|
13689
13865
|
}
|
|
13690
13866
|
}, [analyzeOpen, filteredRows.length, loading]);
|
|
13691
|
-
|
|
13867
|
+
React6.useEffect(() => {
|
|
13692
13868
|
if (!categoryField1 && categoricalFields.length > 0) {
|
|
13693
13869
|
setCategoryField1(categoricalFields[0].key);
|
|
13694
13870
|
}
|
|
@@ -13696,7 +13872,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13696
13872
|
setCategoryField2(categoricalFields[1].key);
|
|
13697
13873
|
}
|
|
13698
13874
|
}, [categoricalFields, categoryField1, categoryField2]);
|
|
13699
|
-
|
|
13875
|
+
React6.useEffect(() => {
|
|
13700
13876
|
if (selectedSeriesKeys !== null) return;
|
|
13701
13877
|
if (numericFields.length > 0) {
|
|
13702
13878
|
setSelectedSeriesKeys(numericFields.map((field) => field.key));
|
|
@@ -13704,7 +13880,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13704
13880
|
setSelectedSeriesKeys(["__count__"]);
|
|
13705
13881
|
}
|
|
13706
13882
|
}, [numericFields, selectedSeriesKeys]);
|
|
13707
|
-
|
|
13883
|
+
React6.useEffect(() => {
|
|
13708
13884
|
if (numericFields.length === 0) {
|
|
13709
13885
|
if (rankingFieldKey !== null) setRankingFieldKey(null);
|
|
13710
13886
|
if (rankingMode !== "none") setRankingMode("none");
|
|
@@ -13714,7 +13890,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13714
13890
|
setRankingFieldKey(numericFields[0].key);
|
|
13715
13891
|
}
|
|
13716
13892
|
}, [numericFields, rankingFieldKey, rankingMode]);
|
|
13717
|
-
const formatCategoryValue =
|
|
13893
|
+
const formatCategoryValue = React6.useCallback((field, recordRow) => {
|
|
13718
13894
|
if (!field) return _34("All");
|
|
13719
13895
|
const raw = recordRow?.[field.key];
|
|
13720
13896
|
if (raw === void 0 || raw === null) return "-";
|
|
@@ -13730,14 +13906,14 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13730
13906
|
if (field.type === "date") return formatDateValue(raw);
|
|
13731
13907
|
return String(raw);
|
|
13732
13908
|
}, [labelCache]);
|
|
13733
|
-
const chartTitle =
|
|
13909
|
+
const chartTitle = React6.useMemo(() => {
|
|
13734
13910
|
const cat1Label = categoryField1 ? relatedModel.fields.find((field) => field.key === categoryField1)?.label : "All";
|
|
13735
13911
|
const cat2Label = categoryField2 ? relatedModel.fields.find((field) => field.key === categoryField2)?.label : null;
|
|
13736
13912
|
const parts = [relatedModel.label || relatedModel.name, cat1Label];
|
|
13737
13913
|
if (cat2Label) parts.push(cat2Label);
|
|
13738
13914
|
return parts.filter(Boolean).join(" \u2022 ");
|
|
13739
13915
|
}, [categoryField1, categoryField2, relatedModel.fields, relatedModel.label, relatedModel.name]);
|
|
13740
|
-
const chartData =
|
|
13916
|
+
const chartData = React6.useMemo(() => {
|
|
13741
13917
|
const data = Array.isArray(columnFilteredRows) ? columnFilteredRows : [];
|
|
13742
13918
|
const cat1Field = categoryField1 ? relatedModel.fields.find((field) => field.key === categoryField1) : void 0;
|
|
13743
13919
|
const cat2Field = categoryField2 ? relatedModel.fields.find((field) => field.key === categoryField2) : void 0;
|
|
@@ -13845,7 +14021,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13845
14021
|
};
|
|
13846
14022
|
}, [columnFilteredRows, categoryField1, categoryField2, relatedModel.fields, numericFields, formatCategoryValue, summaryFn, selectedSeriesKeys, rankingMode, rankingFieldKey, rankingN]);
|
|
13847
14023
|
const editableCrosstab = isCrosstabView && allowInlineEdit;
|
|
13848
|
-
const stageCrosstabCellEdits =
|
|
14024
|
+
const stageCrosstabCellEdits = React6.useCallback((updates) => {
|
|
13849
14025
|
if (updates.length === 0) return;
|
|
13850
14026
|
setCrosstabStaged((prev) => {
|
|
13851
14027
|
const next = { ...prev };
|
|
@@ -13860,11 +14036,11 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13860
14036
|
});
|
|
13861
14037
|
setHasPendingEdits(true);
|
|
13862
14038
|
}, [form]);
|
|
13863
|
-
const getCrosstabStagedValue =
|
|
14039
|
+
const getCrosstabStagedValue = React6.useCallback((recordId2, fieldKey) => {
|
|
13864
14040
|
return crosstabStaged[String(recordId2)]?.[fieldKey];
|
|
13865
14041
|
}, [crosstabStaged]);
|
|
13866
|
-
const crosstabResolvedRefIdsRef =
|
|
13867
|
-
|
|
14042
|
+
const crosstabResolvedRefIdsRef = React6.useRef(/* @__PURE__ */ new Set());
|
|
14043
|
+
React6.useEffect(() => {
|
|
13868
14044
|
if (!isCrosstabView) return;
|
|
13869
14045
|
const refFields = [categoryField1, categoryField2, ...crosstabFilterFields].filter((k) => Boolean(k)).map((k) => relatedModel.fields.find((f) => f.key === k)).filter((f) => Boolean(f && f.reference));
|
|
13870
14046
|
if (refFields.length === 0) return;
|
|
@@ -13900,7 +14076,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
13900
14076
|
cancelled = true;
|
|
13901
14077
|
};
|
|
13902
14078
|
}, [isCrosstabView, categoryField1, categoryField2, crosstabFilterFields, columnFilteredRows, relatedModel.fields, allModels, apiUrl]);
|
|
13903
|
-
const crosstabFilterOptions =
|
|
14079
|
+
const crosstabFilterOptions = React6.useMemo(() => {
|
|
13904
14080
|
if (crosstabFilterFields.length === 0) return /* @__PURE__ */ new Map();
|
|
13905
14081
|
const rangeCount = viewSettings?.maxDistinctColumnFilterValuesToRanges ?? 20;
|
|
13906
14082
|
const fields = crosstabFilterFields.map((k) => relatedModel.fields.find((f) => f.key === k)).filter((f) => Boolean(f));
|
|
@@ -14070,7 +14246,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14070
14246
|
}
|
|
14071
14247
|
)
|
|
14072
14248
|
] });
|
|
14073
|
-
const numericColumnMaxes =
|
|
14249
|
+
const numericColumnMaxes = React6.useMemo(() => {
|
|
14074
14250
|
const maxes = {};
|
|
14075
14251
|
const data = filteredRows || [];
|
|
14076
14252
|
displayFields.forEach((field) => {
|
|
@@ -14084,7 +14260,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14084
14260
|
});
|
|
14085
14261
|
return maxes;
|
|
14086
14262
|
}, [filteredRows, displayFields]);
|
|
14087
|
-
const chartSignature =
|
|
14263
|
+
const chartSignature = React6.useMemo(() => {
|
|
14088
14264
|
return JSON.stringify({
|
|
14089
14265
|
chartType,
|
|
14090
14266
|
summaryFn,
|
|
@@ -14097,13 +14273,13 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14097
14273
|
groups: chartData.groups
|
|
14098
14274
|
});
|
|
14099
14275
|
}, [chartType, summaryFn, categoryField1, categoryField2, rankingMode, rankingFieldKey, rankingN, chartData]);
|
|
14100
|
-
|
|
14276
|
+
React6.useEffect(() => {
|
|
14101
14277
|
if (!analyzeOpen) return;
|
|
14102
14278
|
skipNextAnimationRef.current = true;
|
|
14103
14279
|
setChartAnimationStage("enter");
|
|
14104
14280
|
setChartAnimationKey((key) => key + 1);
|
|
14105
14281
|
}, [analyzeOpen]);
|
|
14106
|
-
|
|
14282
|
+
React6.useEffect(() => {
|
|
14107
14283
|
if (!analyzeOpen) return;
|
|
14108
14284
|
if (skipNextAnimationRef.current) {
|
|
14109
14285
|
skipNextAnimationRef.current = false;
|
|
@@ -14112,7 +14288,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14112
14288
|
setChartAnimationStage("update");
|
|
14113
14289
|
setChartAnimationKey((key) => key + 1);
|
|
14114
14290
|
}, [analyzeOpen, chartSignature]);
|
|
14115
|
-
const formatValueForExport =
|
|
14291
|
+
const formatValueForExport = React6.useCallback((field, recordRow) => {
|
|
14116
14292
|
const raw = recordRow?.[field.key];
|
|
14117
14293
|
if (raw === void 0 || raw === null) return "";
|
|
14118
14294
|
if (field.reference) {
|
|
@@ -14126,7 +14302,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14126
14302
|
if (field.type === "date") return formatDateValue(raw);
|
|
14127
14303
|
return String(raw);
|
|
14128
14304
|
}, [labelCache]);
|
|
14129
|
-
|
|
14305
|
+
React6.useEffect(() => {
|
|
14130
14306
|
if (!exportRequested) return;
|
|
14131
14307
|
const escapeCsv = (value) => {
|
|
14132
14308
|
if (value.includes('"') || value.includes(",") || value.includes("\n")) {
|
|
@@ -14212,31 +14388,31 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14212
14388
|
const exportStatsPdf = () => {
|
|
14213
14389
|
openPdfWindow(`${relatedModel.name}-stats`, buildStatsHtml(statsSummary));
|
|
14214
14390
|
};
|
|
14215
|
-
const columnFilters =
|
|
14391
|
+
const columnFilters = React6.useMemo(() => {
|
|
14216
14392
|
const rangeCount = viewSettings?.maxDistinctColumnFilterValuesToRanges ?? 20;
|
|
14217
14393
|
return buildColumnFilterOptions({ fields: displayFields, data: filteredRows || [], rangeCount });
|
|
14218
14394
|
}, [displayFields, filteredRows, viewSettings]);
|
|
14219
|
-
const allFieldOptions =
|
|
14395
|
+
const allFieldOptions = React6.useMemo(() => {
|
|
14220
14396
|
return relatedModel.fields.map((field) => ({ label: field.label, value: field.key }));
|
|
14221
14397
|
}, [relatedModel.fields]);
|
|
14222
|
-
const orderedSelectedColumns =
|
|
14398
|
+
const orderedSelectedColumns = React6.useMemo(() => {
|
|
14223
14399
|
if (!selectedColumnKeys || selectedColumnKeys.length === 0) return [];
|
|
14224
14400
|
return orderedColumnKeys && orderedColumnKeys.length > 0 ? orderedColumnKeys : selectedColumnKeys;
|
|
14225
14401
|
}, [orderedColumnKeys, selectedColumnKeys]);
|
|
14226
|
-
const syncColumnsSelectionToDisplay =
|
|
14402
|
+
const syncColumnsSelectionToDisplay = React6.useCallback(() => {
|
|
14227
14403
|
const keys = displayFields.map((field) => field.key);
|
|
14228
14404
|
if (keys.length === 0) return;
|
|
14229
14405
|
setSelectedColumnKeys(keys);
|
|
14230
14406
|
setColumnOrder(columnOrder && columnOrder.length > 0 ? columnOrder : keys);
|
|
14231
14407
|
}, [columnOrder, displayFields]);
|
|
14232
|
-
|
|
14408
|
+
React6.useEffect(() => {
|
|
14233
14409
|
if (selectedColumnKeys !== null) return;
|
|
14234
14410
|
const defaults = defaultDisplayFields.map((field) => field.key);
|
|
14235
14411
|
if (defaults.length === 0) return;
|
|
14236
14412
|
setSelectedColumnKeys(defaults);
|
|
14237
14413
|
setColumnOrder(defaults);
|
|
14238
14414
|
}, [defaultDisplayFields, selectedColumnKeys]);
|
|
14239
|
-
const handleColumnSelectionChange =
|
|
14415
|
+
const handleColumnSelectionChange = React6.useCallback((values) => {
|
|
14240
14416
|
markLayoutPrefsTouched();
|
|
14241
14417
|
if (!values || values.length === 0) {
|
|
14242
14418
|
setSelectedColumnKeys(null);
|
|
@@ -14250,7 +14426,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14250
14426
|
return [...baseOrder, ...missing];
|
|
14251
14427
|
});
|
|
14252
14428
|
}, [markLayoutPrefsTouched]);
|
|
14253
|
-
const moveColumnOrder =
|
|
14429
|
+
const moveColumnOrder = React6.useCallback((key, direction) => {
|
|
14254
14430
|
setColumnOrder((prev) => {
|
|
14255
14431
|
const base = prev && prev.length > 0 ? [...prev] : selectedColumnKeys ? [...selectedColumnKeys] : [];
|
|
14256
14432
|
const index = base.indexOf(key);
|
|
@@ -14261,18 +14437,18 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14261
14437
|
return base;
|
|
14262
14438
|
});
|
|
14263
14439
|
}, [selectedColumnKeys]);
|
|
14264
|
-
const statsSummary =
|
|
14440
|
+
const statsSummary = React6.useMemo(() => {
|
|
14265
14441
|
return buildStatsSummary(columnFilteredRows, displayFields, labelCache);
|
|
14266
14442
|
}, [columnFilteredRows, displayFields, labelCache]);
|
|
14267
14443
|
const isTotalsDetailsVariant = viewVariant === "totals-details";
|
|
14268
|
-
const getDefaultTotalsSummaryFn =
|
|
14444
|
+
const getDefaultTotalsSummaryFn = React6.useCallback((field) => {
|
|
14269
14445
|
if (isPkField(field, relatedModel)) return "count";
|
|
14270
14446
|
return "sum";
|
|
14271
14447
|
}, [relatedModel]);
|
|
14272
|
-
const resolveTotalsSummaryFn =
|
|
14448
|
+
const resolveTotalsSummaryFn = React6.useCallback((field) => {
|
|
14273
14449
|
return totalsSummaryFunctions[field.key] || getDefaultTotalsSummaryFn(field);
|
|
14274
14450
|
}, [getDefaultTotalsSummaryFn, totalsSummaryFunctions]);
|
|
14275
|
-
const computeTotalsSummaryValue =
|
|
14451
|
+
const computeTotalsSummaryValue = React6.useCallback((field) => {
|
|
14276
14452
|
const fn = resolveTotalsSummaryFn(field);
|
|
14277
14453
|
const rawValues = filteredRows.map((row) => row?.[field.key]);
|
|
14278
14454
|
if (field.type === "number" && !field.reference) {
|
|
@@ -14295,7 +14471,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14295
14471
|
}
|
|
14296
14472
|
return rawValues.length;
|
|
14297
14473
|
}, [filteredRows, resolveTotalsSummaryFn]);
|
|
14298
|
-
const formatCategoricalBoxValue =
|
|
14474
|
+
const formatCategoricalBoxValue = React6.useCallback((field, raw) => {
|
|
14299
14475
|
if (raw === void 0 || raw === null) return "-";
|
|
14300
14476
|
if (field.reference) {
|
|
14301
14477
|
const cacheKey = `${field.reference}:${raw}`;
|
|
@@ -14308,7 +14484,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14308
14484
|
if (field.type === "date") return formatDateValue(raw);
|
|
14309
14485
|
return String(raw);
|
|
14310
14486
|
}, [labelCache]);
|
|
14311
|
-
const totalsDetailsCategoricalBoxes =
|
|
14487
|
+
const totalsDetailsCategoricalBoxes = React6.useMemo(() => {
|
|
14312
14488
|
return displayFields.filter((field) => field.type !== "number" || Boolean(field.reference)).map((field) => {
|
|
14313
14489
|
const counts = /* @__PURE__ */ new Map();
|
|
14314
14490
|
filteredRows.forEach((row) => {
|
|
@@ -14326,7 +14502,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14326
14502
|
};
|
|
14327
14503
|
});
|
|
14328
14504
|
}, [displayFields, filteredRows, formatCategoricalBoxValue]);
|
|
14329
|
-
const totalsDetailsNumericBoxes =
|
|
14505
|
+
const totalsDetailsNumericBoxes = React6.useMemo(() => {
|
|
14330
14506
|
return displayFields.filter((field) => field.type === "number" && !field.reference).map((field) => {
|
|
14331
14507
|
return {
|
|
14332
14508
|
key: field.key,
|
|
@@ -14336,10 +14512,10 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14336
14512
|
};
|
|
14337
14513
|
});
|
|
14338
14514
|
}, [computeTotalsSummaryValue, displayFields, resolveTotalsSummaryFn]);
|
|
14339
|
-
const totalsSummaryConfigFields =
|
|
14515
|
+
const totalsSummaryConfigFields = React6.useMemo(() => {
|
|
14340
14516
|
return displayFields.filter((field) => field.type === "number" && !field.reference);
|
|
14341
14517
|
}, [displayFields]);
|
|
14342
|
-
|
|
14518
|
+
React6.useEffect(() => {
|
|
14343
14519
|
setTotalsSummaryFunctions((prev) => {
|
|
14344
14520
|
const next = { ...prev };
|
|
14345
14521
|
let changed = false;
|
|
@@ -14352,7 +14528,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14352
14528
|
return changed ? next : prev;
|
|
14353
14529
|
});
|
|
14354
14530
|
}, [getDefaultTotalsSummaryFn, totalsSummaryConfigFields]);
|
|
14355
|
-
const statsNumericMaxes =
|
|
14531
|
+
const statsNumericMaxes = React6.useMemo(() => {
|
|
14356
14532
|
const stats = statsSummary.numericStats;
|
|
14357
14533
|
const maxAbs = (values) => {
|
|
14358
14534
|
const absValues = values.filter((val) => typeof val === "number").map((val) => Math.abs(val));
|
|
@@ -14366,7 +14542,7 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
14366
14542
|
stddev: maxAbs(stats.map((row) => row.stddev))
|
|
14367
14543
|
};
|
|
14368
14544
|
}, [statsSummary.numericStats]);
|
|
14369
|
-
|
|
14545
|
+
React6.useEffect(() => {
|
|
14370
14546
|
if (isTotalsDetailsVariant) {
|
|
14371
14547
|
setIsTotalsDetailsFlipped(false);
|
|
14372
14548
|
}
|
|
@@ -15413,7 +15589,8 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
15413
15589
|
{ label: _34("Heatmap"), value: "heatmap" },
|
|
15414
15590
|
{ label: _34("Crosstab"), value: "crosstab" },
|
|
15415
15591
|
{ label: _34("Radar"), value: "radar" },
|
|
15416
|
-
{ label: _34("Combo (Bar + Line)"), value: "combo" }
|
|
15592
|
+
{ label: _34("Combo (Bar + Line)"), value: "combo" },
|
|
15593
|
+
{ label: _34("3D Scatter"), value: "3d" }
|
|
15417
15594
|
]
|
|
15418
15595
|
}
|
|
15419
15596
|
)
|
|
@@ -15628,15 +15805,15 @@ var RelatedObjectsTable = ({ rel, record, relatedModel, parentModel, showActions
|
|
|
15628
15805
|
};
|
|
15629
15806
|
var RelatedObjectSingleSelect = ({ rel, record, allModels, required }) => {
|
|
15630
15807
|
const apiUrl = core.useApiUrl();
|
|
15631
|
-
const [currentLinkRow, setCurrentLinkRow] =
|
|
15632
|
-
const [currentValue, setCurrentValue] =
|
|
15633
|
-
const [loadingCurrent, setLoadingCurrent] =
|
|
15634
|
-
const [saving, setSaving] =
|
|
15808
|
+
const [currentLinkRow, setCurrentLinkRow] = React6.useState(null);
|
|
15809
|
+
const [currentValue, setCurrentValue] = React6.useState(null);
|
|
15810
|
+
const [loadingCurrent, setLoadingCurrent] = React6.useState(true);
|
|
15811
|
+
const [saving, setSaving] = React6.useState(false);
|
|
15635
15812
|
const relatedResource = rel.otherResourcePath || resolveResourcePath(rel.otherResource || "", allModels);
|
|
15636
15813
|
const linkResource = rel.resourcePath || resolveResourcePath(rel.resource, allModels);
|
|
15637
15814
|
const relatedModel = allModels?.find((m) => m.name === rel.otherResource);
|
|
15638
15815
|
const relatedPkField = relatedModel?.fields.find((f) => f.isPk)?.key ?? "id";
|
|
15639
|
-
|
|
15816
|
+
React6.useEffect(() => {
|
|
15640
15817
|
const recordId = getRecordId(record);
|
|
15641
15818
|
if (!recordId || !rel.targetKey || !rel.otherKey) {
|
|
15642
15819
|
setLoadingCurrent(false);
|
|
@@ -15678,7 +15855,7 @@ var RelatedObjectSingleSelect = ({ rel, record, allModels, required }) => {
|
|
|
15678
15855
|
filters: [],
|
|
15679
15856
|
pagination: { current: 1, pageSize: 2e3, mode: "server" }
|
|
15680
15857
|
});
|
|
15681
|
-
const handleChange =
|
|
15858
|
+
const handleChange = React6.useCallback(async (newValue) => {
|
|
15682
15859
|
const recordId = getRecordId(record);
|
|
15683
15860
|
if (!recordId || !rel.otherKey) return;
|
|
15684
15861
|
setSaving(true);
|
|
@@ -15734,11 +15911,11 @@ function useMillerColumnItems({
|
|
|
15734
15911
|
allModels,
|
|
15735
15912
|
apiUrl
|
|
15736
15913
|
}) {
|
|
15737
|
-
const [branches, setBranches] =
|
|
15738
|
-
const [leaves, setLeaves] =
|
|
15739
|
-
const [loading, setLoading] =
|
|
15740
|
-
const [error, setError] =
|
|
15741
|
-
|
|
15914
|
+
const [branches, setBranches] = React6.useState([]);
|
|
15915
|
+
const [leaves, setLeaves] = React6.useState([]);
|
|
15916
|
+
const [loading, setLoading] = React6.useState(false);
|
|
15917
|
+
const [error, setError] = React6.useState(null);
|
|
15918
|
+
React6.useEffect(() => {
|
|
15742
15919
|
if (!parentId || !rel.resourcePath || !rel.targetKey || !rel.otherKey || !rel.otherResource) {
|
|
15743
15920
|
setBranches([]);
|
|
15744
15921
|
setLeaves([]);
|
|
@@ -16003,16 +16180,16 @@ var MillerBrowserLayout = ({
|
|
|
16003
16180
|
const screens = antd.Grid.useBreakpoint();
|
|
16004
16181
|
const { token } = antd.theme.useToken();
|
|
16005
16182
|
const isDesktop = !!screens.md;
|
|
16006
|
-
const columnsRef =
|
|
16183
|
+
const columnsRef = React6.useRef(null);
|
|
16007
16184
|
const rootId = record?.eid ?? record?.id;
|
|
16008
|
-
const [columns, setColumns] =
|
|
16009
|
-
const [selectedIds, setSelectedIds] =
|
|
16010
|
-
const [detailNode, setDetailNode] =
|
|
16011
|
-
const [drawerOpen, setDrawerOpen] =
|
|
16012
|
-
const [containerHeight, setContainerHeight] =
|
|
16013
|
-
const [columnsWidth, setColumnsWidth] =
|
|
16014
|
-
const [columnWidths, setColumnWidths] =
|
|
16015
|
-
const [draggingDir, setDraggingDir] =
|
|
16185
|
+
const [columns, setColumns] = React6.useState([{ parentId: rootId }]);
|
|
16186
|
+
const [selectedIds, setSelectedIds] = React6.useState([null]);
|
|
16187
|
+
const [detailNode, setDetailNode] = React6.useState(null);
|
|
16188
|
+
const [drawerOpen, setDrawerOpen] = React6.useState(false);
|
|
16189
|
+
const [containerHeight, setContainerHeight] = React6.useState(INITIAL_HEIGHT);
|
|
16190
|
+
const [columnsWidth, setColumnsWidth] = React6.useState(null);
|
|
16191
|
+
const [columnWidths, setColumnWidths] = React6.useState([]);
|
|
16192
|
+
const [draggingDir, setDraggingDir] = React6.useState(null);
|
|
16016
16193
|
const DEFAULT_COL_WIDTH = 240;
|
|
16017
16194
|
const getColWidth = (i) => columnWidths[i] ?? DEFAULT_COL_WIDTH;
|
|
16018
16195
|
const handleResizeV = (e) => {
|
|
@@ -16494,7 +16671,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16494
16671
|
const canBulkEdit = canEditData?.can !== false;
|
|
16495
16672
|
const { settings: viewSettings } = useViewSettings();
|
|
16496
16673
|
viewSettings?.generalActionsButtonPosition || "top-right";
|
|
16497
|
-
const [actionsBarEl, setActionsBarEl] =
|
|
16674
|
+
const [actionsBarEl, setActionsBarEl] = React6.useState(null);
|
|
16498
16675
|
const resolvedLayoutPreferenceType = layoutPreferenceType ?? "ShowLayout";
|
|
16499
16676
|
const [searchParams] = reactRouterDom.useSearchParams();
|
|
16500
16677
|
const selectMode = searchParams.get("select_mode") === "1";
|
|
@@ -16504,7 +16681,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16504
16681
|
const selectModeRelateOtherKey = searchParams.get("relate_other_key");
|
|
16505
16682
|
const selectModeRelateTargetId = searchParams.get("relate_target_id");
|
|
16506
16683
|
const selectModeReturnTo = searchParams.get("returnTo");
|
|
16507
|
-
useKeyboardShortcuts(
|
|
16684
|
+
useKeyboardShortcuts(React6.useMemo(() => isEmbedded ? [] : [
|
|
16508
16685
|
{ key: "n", ctrl: true, handler: () => go({ to: { resource: model.resource || model.name, action: "create" } }) }
|
|
16509
16686
|
], [model.name, model.resource, go, isEmbedded]));
|
|
16510
16687
|
const { token } = antd.theme.useToken();
|
|
@@ -16538,89 +16715,89 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16538
16715
|
const editableCrosstab = resolvedListViewType === "editable-crosstab" || resolvedListViewType === "editablecrosstab";
|
|
16539
16716
|
const galleryImageWidth = viewSettings?.galleryImageWidth ?? 180;
|
|
16540
16717
|
const galleryImageHeight = viewSettings?.galleryImageHeight ?? 140;
|
|
16541
|
-
const calendarDateFieldOptions =
|
|
16542
|
-
const [localSearch, setLocalSearch] =
|
|
16543
|
-
const [listVisible, setListVisible] =
|
|
16544
|
-
const [isTdFlipped, setIsTdFlipped] =
|
|
16545
|
-
const [pageSize, setPageSize] =
|
|
16546
|
-
const [galleryPage, setGalleryPage] =
|
|
16547
|
-
const [calendarMode, setCalendarMode] =
|
|
16548
|
-
const [calendarDateField, setCalendarDateField] =
|
|
16549
|
-
const [calendarAnchorDate, setCalendarAnchorDate] =
|
|
16550
|
-
const [isAnalyzeVertical, setIsAnalyzeVertical] =
|
|
16551
|
-
const [isAnalyzeFirst, setIsAnalyzeFirst] =
|
|
16552
|
-
const [filterRules, setFilterRules] =
|
|
16553
|
-
const [filtersCollapsed, setFiltersCollapsed] =
|
|
16554
|
-
const [layoutPrefsReady, setLayoutPrefsReady] =
|
|
16555
|
-
const [columnsSelectorOpen, setColumnsSelectorOpen] =
|
|
16556
|
-
const [selectedColumnKeys, setSelectedColumnKeys] =
|
|
16557
|
-
const [columnOrder, setColumnOrder] =
|
|
16558
|
-
const [columnFiltersSelected, setColumnFiltersSelected] =
|
|
16559
|
-
const [columnSort, setColumnSort] =
|
|
16718
|
+
const calendarDateFieldOptions = React6.useMemo(() => getCalendarDateFieldOptions(model.fields), [model.fields]);
|
|
16719
|
+
const [localSearch, setLocalSearch] = React6.useState("");
|
|
16720
|
+
const [listVisible, setListVisible] = React6.useState(defaultListVisible ?? true);
|
|
16721
|
+
const [isTdFlipped, setIsTdFlipped] = React6.useState(false);
|
|
16722
|
+
const [pageSize, setPageSize] = React6.useState(10);
|
|
16723
|
+
const [galleryPage, setGalleryPage] = React6.useState(1);
|
|
16724
|
+
const [calendarMode, setCalendarMode] = React6.useState("month");
|
|
16725
|
+
const [calendarDateField, setCalendarDateField] = React6.useState(() => calendarDateFieldOptions[0]?.key || "");
|
|
16726
|
+
const [calendarAnchorDate, setCalendarAnchorDate] = React6.useState(() => dayjs9__default.default().startOf("month"));
|
|
16727
|
+
const [isAnalyzeVertical, setIsAnalyzeVertical] = React6.useState(false);
|
|
16728
|
+
const [isAnalyzeFirst, setIsAnalyzeFirst] = React6.useState(false);
|
|
16729
|
+
const [filterRules, setFilterRules] = React6.useState([]);
|
|
16730
|
+
const [filtersCollapsed, setFiltersCollapsed] = React6.useState(isEmbedded);
|
|
16731
|
+
const [layoutPrefsReady, setLayoutPrefsReady] = React6.useState(false);
|
|
16732
|
+
const [columnsSelectorOpen, setColumnsSelectorOpen] = React6.useState(false);
|
|
16733
|
+
const [selectedColumnKeys, setSelectedColumnKeys] = React6.useState(null);
|
|
16734
|
+
const [columnOrder, setColumnOrder] = React6.useState(null);
|
|
16735
|
+
const [columnFiltersSelected, setColumnFiltersSelected] = React6.useState({});
|
|
16736
|
+
const [columnSort, setColumnSort] = React6.useState(
|
|
16560
16737
|
model.defaultSort ? [{ fieldKey: model.defaultSort.field, order: model.defaultSort.order === "desc" ? "descend" : "ascend" }] : []
|
|
16561
16738
|
);
|
|
16562
|
-
const [totalsSummaryFunctions, setTotalsSummaryFunctions] =
|
|
16563
|
-
const [currentViewName, setCurrentViewName] =
|
|
16564
|
-
const [selectedViewNames, setSelectedViewNames] =
|
|
16565
|
-
const [availableViewNames, setAvailableViewNames] =
|
|
16566
|
-
const [viewNamesLoaded, setViewNamesLoaded] =
|
|
16567
|
-
const [isLoadingViewNames, setIsLoadingViewNames] =
|
|
16568
|
-
const [saveViewModalOpen, setSaveViewModalOpen] =
|
|
16569
|
-
const [saveViewName, setSaveViewName] =
|
|
16570
|
-
const [saveViewAsNew, setSaveViewAsNew] =
|
|
16571
|
-
const [pendingSaveTarget, setPendingSaveTarget] =
|
|
16572
|
-
const [renameViewModalOpen, setRenameViewModalOpen] =
|
|
16573
|
-
const [renameViewName, setRenameViewName] =
|
|
16574
|
-
const [labelCache, setLabelCache] =
|
|
16575
|
-
const [analyzeOpen, setAnalyzeOpen] =
|
|
16576
|
-
const analyzeTouchedRef =
|
|
16577
|
-
const analyzePrefsTouchedRef =
|
|
16578
|
-
const analyzePrefsLoadedRef =
|
|
16579
|
-
const [analyzePrefsReady, setAnalyzePrefsReady] =
|
|
16580
|
-
const analyzePrefsResourceRef =
|
|
16739
|
+
const [totalsSummaryFunctions, setTotalsSummaryFunctions] = React6.useState({});
|
|
16740
|
+
const [currentViewName, setCurrentViewName] = React6.useState(getDefaultViewName());
|
|
16741
|
+
const [selectedViewNames, setSelectedViewNames] = React6.useState([]);
|
|
16742
|
+
const [availableViewNames, setAvailableViewNames] = React6.useState([]);
|
|
16743
|
+
const [viewNamesLoaded, setViewNamesLoaded] = React6.useState(false);
|
|
16744
|
+
const [isLoadingViewNames, setIsLoadingViewNames] = React6.useState(false);
|
|
16745
|
+
const [saveViewModalOpen, setSaveViewModalOpen] = React6.useState(false);
|
|
16746
|
+
const [saveViewName, setSaveViewName] = React6.useState(getDefaultViewName());
|
|
16747
|
+
const [saveViewAsNew, setSaveViewAsNew] = React6.useState(false);
|
|
16748
|
+
const [pendingSaveTarget, setPendingSaveTarget] = React6.useState(null);
|
|
16749
|
+
const [renameViewModalOpen, setRenameViewModalOpen] = React6.useState(false);
|
|
16750
|
+
const [renameViewName, setRenameViewName] = React6.useState("");
|
|
16751
|
+
const [labelCache, setLabelCache] = React6.useState({});
|
|
16752
|
+
const [analyzeOpen, setAnalyzeOpen] = React6.useState(isEmbedded);
|
|
16753
|
+
const analyzeTouchedRef = React6.useRef(false);
|
|
16754
|
+
const analyzePrefsTouchedRef = React6.useRef(false);
|
|
16755
|
+
const analyzePrefsLoadedRef = React6.useRef(false);
|
|
16756
|
+
const [analyzePrefsReady, setAnalyzePrefsReady] = React6.useState(false);
|
|
16757
|
+
const analyzePrefsResourceRef = React6.useRef(null);
|
|
16581
16758
|
const { metadataButton, metadataModal } = useMetadataModal(model, allModels);
|
|
16582
|
-
const defaultDisplayFields =
|
|
16583
|
-
const orderedColumnKeys =
|
|
16759
|
+
const defaultDisplayFields = React6.useMemo(() => getListViewFields(model, filter?.field), [model, filter?.field]);
|
|
16760
|
+
const orderedColumnKeys = React6.useMemo(() => {
|
|
16584
16761
|
if (!selectedColumnKeys || selectedColumnKeys.length === 0) return null;
|
|
16585
16762
|
const order = columnOrder && columnOrder.length > 0 ? columnOrder : selectedColumnKeys;
|
|
16586
16763
|
const selectedSet = new Set(selectedColumnKeys);
|
|
16587
16764
|
const availableKeys = new Set(model.fields.map((field) => field.key));
|
|
16588
16765
|
return order.filter((key) => selectedSet.has(key) && availableKeys.has(key));
|
|
16589
16766
|
}, [columnOrder, model.fields, selectedColumnKeys]);
|
|
16590
|
-
const displayFields =
|
|
16767
|
+
const displayFields = React6.useMemo(() => {
|
|
16591
16768
|
if (!orderedColumnKeys) return defaultDisplayFields;
|
|
16592
16769
|
const fieldMap = new Map(model.fields.map((field) => [field.key, field]));
|
|
16593
16770
|
return orderedColumnKeys.map((key) => fieldMap.get(key)).filter((field) => Boolean(field));
|
|
16594
16771
|
}, [defaultDisplayFields, model.fields, orderedColumnKeys]);
|
|
16595
16772
|
const useLocalSearch = true;
|
|
16596
|
-
const [categoryField1, setCategoryField1] =
|
|
16597
|
-
const [categoryField2, setCategoryField2] =
|
|
16598
|
-
const [crosstabFilterFields, setCrosstabFilterFields] =
|
|
16599
|
-
const [crosstabStaged, setCrosstabStaged] =
|
|
16600
|
-
const [crosstabSaving, setCrosstabSaving] =
|
|
16601
|
-
const [chartType, setChartType] =
|
|
16602
|
-
const [summaryFn, setSummaryFn] =
|
|
16603
|
-
const [selectedSeriesKeys, setSelectedSeriesKeys] =
|
|
16604
|
-
const [rankingMode, setRankingMode] =
|
|
16605
|
-
const [rankingFieldKey, setRankingFieldKey] =
|
|
16606
|
-
const [rankingN, setRankingN] =
|
|
16607
|
-
const [exportRequested, setExportRequested] =
|
|
16608
|
-
const [isStatsFlipped, setIsStatsFlipped] =
|
|
16609
|
-
const [isSavingAnalyzePrefs, setIsSavingAnalyzePrefs] =
|
|
16610
|
-
const chartSvgRef =
|
|
16611
|
-
const [chartAnimationKey, setChartAnimationKey] =
|
|
16612
|
-
const [chartAnimationStage, setChartAnimationStage] =
|
|
16613
|
-
const skipNextAnimationRef =
|
|
16614
|
-
const [isSavingLayoutPrefs, setIsSavingLayoutPrefs] =
|
|
16615
|
-
const layoutPrefsTouchedRef =
|
|
16616
|
-
const layoutPrefsLoadedRef =
|
|
16617
|
-
const layoutPrefsResourceRef =
|
|
16618
|
-
const sortIntentRef =
|
|
16619
|
-
const prevViewNameForResetRef =
|
|
16620
|
-
const [bulkSelectedRowKeys, setBulkSelectedRowKeys] =
|
|
16621
|
-
const bulkSelectedRowsMapRef =
|
|
16622
|
-
const [selectModeAssociating, setSelectModeAssociating] =
|
|
16623
|
-
const handleAssociateSelected =
|
|
16773
|
+
const [categoryField1, setCategoryField1] = React6.useState(null);
|
|
16774
|
+
const [categoryField2, setCategoryField2] = React6.useState(void 0);
|
|
16775
|
+
const [crosstabFilterFields, setCrosstabFilterFields] = React6.useState([]);
|
|
16776
|
+
const [crosstabStaged, setCrosstabStaged] = React6.useState({});
|
|
16777
|
+
const [crosstabSaving, setCrosstabSaving] = React6.useState(false);
|
|
16778
|
+
const [chartType, setChartType] = React6.useState("area");
|
|
16779
|
+
const [summaryFn, setSummaryFn] = React6.useState("sum");
|
|
16780
|
+
const [selectedSeriesKeys, setSelectedSeriesKeys] = React6.useState(null);
|
|
16781
|
+
const [rankingMode, setRankingMode] = React6.useState("none");
|
|
16782
|
+
const [rankingFieldKey, setRankingFieldKey] = React6.useState(null);
|
|
16783
|
+
const [rankingN, setRankingN] = React6.useState(10);
|
|
16784
|
+
const [exportRequested, setExportRequested] = React6.useState(false);
|
|
16785
|
+
const [isStatsFlipped, setIsStatsFlipped] = React6.useState(false);
|
|
16786
|
+
const [isSavingAnalyzePrefs, setIsSavingAnalyzePrefs] = React6.useState(false);
|
|
16787
|
+
const chartSvgRef = React6.useRef(null);
|
|
16788
|
+
const [chartAnimationKey, setChartAnimationKey] = React6.useState(0);
|
|
16789
|
+
const [chartAnimationStage, setChartAnimationStage] = React6.useState("enter");
|
|
16790
|
+
const skipNextAnimationRef = React6.useRef(false);
|
|
16791
|
+
const [isSavingLayoutPrefs, setIsSavingLayoutPrefs] = React6.useState(false);
|
|
16792
|
+
const layoutPrefsTouchedRef = React6.useRef(false);
|
|
16793
|
+
const layoutPrefsLoadedRef = React6.useRef(false);
|
|
16794
|
+
const layoutPrefsResourceRef = React6.useRef(null);
|
|
16795
|
+
const sortIntentRef = React6.useRef(null);
|
|
16796
|
+
const prevViewNameForResetRef = React6.useRef(null);
|
|
16797
|
+
const [bulkSelectedRowKeys, setBulkSelectedRowKeys] = React6.useState([]);
|
|
16798
|
+
const bulkSelectedRowsMapRef = React6.useRef(/* @__PURE__ */ new Map());
|
|
16799
|
+
const [selectModeAssociating, setSelectModeAssociating] = React6.useState(false);
|
|
16800
|
+
const handleAssociateSelected = React6.useCallback(async () => {
|
|
16624
16801
|
if (!selectModeRelateResource || !selectModeRelateTargetKey || !selectModeRelateTargetId) return;
|
|
16625
16802
|
if (!selectModeFk && !selectModeRelateOtherKey) return;
|
|
16626
16803
|
setSelectModeAssociating(true);
|
|
@@ -16655,18 +16832,18 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16655
16832
|
setSelectModeAssociating(false);
|
|
16656
16833
|
}
|
|
16657
16834
|
}, [apiUrl, bulkSelectedRowKeys, selectModeFk, selectModeRelateResource, selectModeRelateTargetKey, selectModeRelateOtherKey, selectModeRelateTargetId, selectModeReturnTo, navigate]);
|
|
16658
|
-
const [bulkActionModalOpen, setBulkActionModalOpen] =
|
|
16659
|
-
const [bulkActionsToApply, setBulkActionsToApply] =
|
|
16660
|
-
const [bulkChangeFieldKey, setBulkChangeFieldKey] =
|
|
16661
|
-
const [bulkChangeFieldValue, setBulkChangeFieldValue] =
|
|
16662
|
-
const [isBulkExecuting, setIsBulkExecuting] =
|
|
16663
|
-
const [selectAllFilteredPending, setSelectAllFilteredPending] =
|
|
16664
|
-
const [columnFilterDropdownEverOpened, setColumnFilterDropdownEverOpened] =
|
|
16665
|
-
const handleReferenceLabel =
|
|
16835
|
+
const [bulkActionModalOpen, setBulkActionModalOpen] = React6.useState(false);
|
|
16836
|
+
const [bulkActionsToApply, setBulkActionsToApply] = React6.useState([]);
|
|
16837
|
+
const [bulkChangeFieldKey, setBulkChangeFieldKey] = React6.useState(null);
|
|
16838
|
+
const [bulkChangeFieldValue, setBulkChangeFieldValue] = React6.useState(null);
|
|
16839
|
+
const [isBulkExecuting, setIsBulkExecuting] = React6.useState(false);
|
|
16840
|
+
const [selectAllFilteredPending, setSelectAllFilteredPending] = React6.useState(false);
|
|
16841
|
+
const [columnFilterDropdownEverOpened, setColumnFilterDropdownEverOpened] = React6.useState(false);
|
|
16842
|
+
const handleReferenceLabel = React6.useCallback((resource, id, label) => {
|
|
16666
16843
|
const key = `${resource}:${id}`;
|
|
16667
16844
|
setLabelCache((prev) => prev[key] === label ? prev : { ...prev, [key]: label });
|
|
16668
16845
|
}, []);
|
|
16669
|
-
const tableFilters =
|
|
16846
|
+
const tableFilters = React6.useMemo(() => {
|
|
16670
16847
|
if (!filter) return [];
|
|
16671
16848
|
if (filter.value === void 0 || filter.value === null) return [];
|
|
16672
16849
|
return [filter];
|
|
@@ -16688,19 +16865,19 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16688
16865
|
if (["true", "1", "t", "yes", "y"].includes(normalized)) value = true;
|
|
16689
16866
|
if (["false", "0", "f", "no", "n"].includes(normalized)) value = false;
|
|
16690
16867
|
}
|
|
16691
|
-
return [{ field: searchField.key, operator: "
|
|
16868
|
+
return [{ field: searchField.key, operator: "contains", value }];
|
|
16692
16869
|
}
|
|
16693
16870
|
});
|
|
16694
|
-
const [allRowsData, setAllRowsData] =
|
|
16695
|
-
const [isAllRowsLoading, setIsAllRowsLoading] =
|
|
16696
|
-
const [allRowsError, setAllRowsError] =
|
|
16697
|
-
const lastAllRowsSignature =
|
|
16698
|
-
const [allRowsLoaded, setAllRowsLoaded] =
|
|
16871
|
+
const [allRowsData, setAllRowsData] = React6.useState([]);
|
|
16872
|
+
const [isAllRowsLoading, setIsAllRowsLoading] = React6.useState(false);
|
|
16873
|
+
const [allRowsError, setAllRowsError] = React6.useState(null);
|
|
16874
|
+
const lastAllRowsSignature = React6.useRef("");
|
|
16875
|
+
const [allRowsLoaded, setAllRowsLoaded] = React6.useState(false);
|
|
16699
16876
|
const isRelationView = !!filter;
|
|
16700
|
-
const hasActiveFilterRules =
|
|
16877
|
+
const hasActiveFilterRules = React6.useMemo(() => {
|
|
16701
16878
|
return filterRules.some((rule) => rule.fieldKey && rule.operator && (rule.value !== void 0 && rule.value !== null && rule.value !== ""));
|
|
16702
16879
|
}, [filterRules]);
|
|
16703
|
-
const getFieldValueForFilter =
|
|
16880
|
+
const getFieldValueForFilter = React6.useCallback((field, record) => {
|
|
16704
16881
|
const raw = record?.[field.key];
|
|
16705
16882
|
if (raw === void 0 || raw === null) return raw;
|
|
16706
16883
|
if (field.reference) {
|
|
@@ -16712,7 +16889,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16712
16889
|
}
|
|
16713
16890
|
return raw;
|
|
16714
16891
|
}, [labelCache]);
|
|
16715
|
-
const getSortValue =
|
|
16892
|
+
const getSortValue = React6.useCallback((field, record) => {
|
|
16716
16893
|
const raw = record?.[field.key];
|
|
16717
16894
|
if (raw === void 0 || raw === null) return null;
|
|
16718
16895
|
if (isPkField(field, model) && record?._label) return record._label;
|
|
@@ -16734,7 +16911,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16734
16911
|
if (field.type === "boolean") return raw ? 1 : 0;
|
|
16735
16912
|
return raw;
|
|
16736
16913
|
}, [labelCache]);
|
|
16737
|
-
const compareSortValues =
|
|
16914
|
+
const compareSortValues = React6.useCallback((field, a, b) => {
|
|
16738
16915
|
const aVal = getSortValue(field, a);
|
|
16739
16916
|
const bVal = getSortValue(field, b);
|
|
16740
16917
|
if (aVal === null && bVal === null) return 0;
|
|
@@ -16743,7 +16920,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16743
16920
|
if (typeof aVal === "number" && typeof bVal === "number") return aVal - bVal;
|
|
16744
16921
|
return String(aVal).localeCompare(String(bVal));
|
|
16745
16922
|
}, [getSortValue]);
|
|
16746
|
-
const resolveRelativeDate =
|
|
16923
|
+
const resolveRelativeDate = React6.useCallback((value, asRange) => {
|
|
16747
16924
|
const count = Number(value?.count ?? 1);
|
|
16748
16925
|
const direction = value?.direction || "next";
|
|
16749
16926
|
const unit = value?.unit || "weeks";
|
|
@@ -16769,7 +16946,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16769
16946
|
}
|
|
16770
16947
|
return { date: target.startOf(unit) };
|
|
16771
16948
|
}, []);
|
|
16772
|
-
const matchesRule =
|
|
16949
|
+
const matchesRule = React6.useCallback((record, rule) => {
|
|
16773
16950
|
const field = model.fields.find((f) => f.key === rule.fieldKey);
|
|
16774
16951
|
if (!field || !rule.operator) return true;
|
|
16775
16952
|
const rawValue = getFieldValueForFilter(field, record);
|
|
@@ -16849,7 +17026,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16849
17026
|
}
|
|
16850
17027
|
return true;
|
|
16851
17028
|
}, [getFieldValueForFilter, model.fields, resolveRelativeDate]);
|
|
16852
|
-
const applyGlobalSearch =
|
|
17029
|
+
const applyGlobalSearch = React6.useCallback((rows) => {
|
|
16853
17030
|
const query = localSearch.trim().toLowerCase();
|
|
16854
17031
|
if (!query) return rows;
|
|
16855
17032
|
return rows.filter((record) => {
|
|
@@ -16868,11 +17045,11 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16868
17045
|
return candidates.some((value) => value !== void 0 && value !== null && String(value).toLowerCase().includes(query));
|
|
16869
17046
|
});
|
|
16870
17047
|
}, [labelCache, localSearch, model.fields, useLocalSearch]);
|
|
16871
|
-
const applyFilterRules =
|
|
17048
|
+
const applyFilterRules = React6.useCallback((rows) => {
|
|
16872
17049
|
if (!hasActiveFilterRules) return rows;
|
|
16873
17050
|
return rows.filter((record) => filterRules.every((rule) => matchesRule(record, rule)));
|
|
16874
17051
|
}, [filterRules, hasActiveFilterRules, matchesRule]);
|
|
16875
|
-
const allRows =
|
|
17052
|
+
const allRows = React6.useMemo(() => {
|
|
16876
17053
|
const data = allRowsData || [];
|
|
16877
17054
|
const query = localSearch.trim().toLowerCase();
|
|
16878
17055
|
if (!query) return data;
|
|
@@ -16893,12 +17070,12 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16893
17070
|
});
|
|
16894
17071
|
}, [allRowsData, useLocalSearch, localSearch, model.fields, labelCache]);
|
|
16895
17072
|
const isClientFiltering = allRowsLoaded && !allRowsError;
|
|
16896
|
-
const filteredDataSource =
|
|
17073
|
+
const filteredDataSource = React6.useMemo(() => {
|
|
16897
17074
|
if (!isClientFiltering) return Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
|
|
16898
17075
|
const baseRows = allRows || [];
|
|
16899
17076
|
return applyFilterRules(applyGlobalSearch(baseRows));
|
|
16900
17077
|
}, [allRows, applyFilterRules, applyGlobalSearch, isClientFiltering, tableProps.dataSource]);
|
|
16901
|
-
const columnFilteredDataSource =
|
|
17078
|
+
const columnFilteredDataSource = React6.useMemo(() => {
|
|
16902
17079
|
const activeEntries = Object.entries(columnFiltersSelected).filter(([, values]) => values && values.length > 0);
|
|
16903
17080
|
if (activeEntries.length === 0) return filteredDataSource;
|
|
16904
17081
|
return filteredDataSource.filter(
|
|
@@ -16909,41 +17086,41 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16909
17086
|
})
|
|
16910
17087
|
);
|
|
16911
17088
|
}, [filteredDataSource, columnFiltersSelected, model.fields]);
|
|
16912
|
-
|
|
17089
|
+
React6.useEffect(() => {
|
|
16913
17090
|
setGalleryPage(1);
|
|
16914
17091
|
}, [localSearch, filterRules, resolvedListViewType]);
|
|
16915
|
-
const columnFilters =
|
|
17092
|
+
const columnFilters = React6.useMemo(() => {
|
|
16916
17093
|
const data = allRowsData.length > 0 ? allRowsData : Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
|
|
16917
17094
|
const rangeCount = viewSettings?.maxDistinctColumnFilterValuesToRanges ?? 20;
|
|
16918
17095
|
return buildColumnFilterOptions({ fields: displayFields, data, rangeCount });
|
|
16919
17096
|
}, [allRowsData, displayFields, tableProps.dataSource, viewSettings]);
|
|
16920
|
-
const allFieldOptions =
|
|
17097
|
+
const allFieldOptions = React6.useMemo(() => {
|
|
16921
17098
|
return model.fields.map((field) => ({ label: field.label, value: field.key }));
|
|
16922
17099
|
}, [model.fields]);
|
|
16923
|
-
const orderedSelectedColumns =
|
|
17100
|
+
const orderedSelectedColumns = React6.useMemo(() => {
|
|
16924
17101
|
if (!selectedColumnKeys || selectedColumnKeys.length === 0) return [];
|
|
16925
17102
|
return orderedColumnKeys && orderedColumnKeys.length > 0 ? orderedColumnKeys : selectedColumnKeys;
|
|
16926
17103
|
}, [orderedColumnKeys, selectedColumnKeys]);
|
|
16927
|
-
const syncColumnsSelectionToDisplay =
|
|
17104
|
+
const syncColumnsSelectionToDisplay = React6.useCallback(() => {
|
|
16928
17105
|
const keys = displayFields.map((field) => field.key);
|
|
16929
17106
|
if (keys.length === 0) return;
|
|
16930
17107
|
setSelectedColumnKeys(keys);
|
|
16931
17108
|
setColumnOrder(orderedColumnKeys && orderedColumnKeys.length > 0 ? orderedColumnKeys : keys);
|
|
16932
17109
|
}, [displayFields, orderedColumnKeys]);
|
|
16933
|
-
|
|
17110
|
+
React6.useEffect(() => {
|
|
16934
17111
|
if (selectedColumnKeys !== null) return;
|
|
16935
17112
|
const defaults = defaultDisplayFields.map((field) => field.key);
|
|
16936
17113
|
if (defaults.length === 0) return;
|
|
16937
17114
|
setSelectedColumnKeys(defaults);
|
|
16938
17115
|
setColumnOrder(defaults);
|
|
16939
17116
|
}, [defaultDisplayFields, selectedColumnKeys]);
|
|
16940
|
-
const markAnalyzePrefsTouched =
|
|
17117
|
+
const markAnalyzePrefsTouched = React6.useCallback(() => {
|
|
16941
17118
|
analyzePrefsTouchedRef.current = true;
|
|
16942
17119
|
}, []);
|
|
16943
|
-
const markLayoutPrefsTouched =
|
|
17120
|
+
const markLayoutPrefsTouched = React6.useCallback(() => {
|
|
16944
17121
|
layoutPrefsTouchedRef.current = true;
|
|
16945
17122
|
}, []);
|
|
16946
|
-
const handleColumnSelectionChange =
|
|
17123
|
+
const handleColumnSelectionChange = React6.useCallback((values) => {
|
|
16947
17124
|
markLayoutPrefsTouched();
|
|
16948
17125
|
if (!values || values.length === 0) {
|
|
16949
17126
|
setSelectedColumnKeys(null);
|
|
@@ -16957,7 +17134,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16957
17134
|
return [...baseOrder, ...missing];
|
|
16958
17135
|
});
|
|
16959
17136
|
}, [markLayoutPrefsTouched]);
|
|
16960
|
-
const moveColumnOrder =
|
|
17137
|
+
const moveColumnOrder = React6.useCallback((key, direction) => {
|
|
16961
17138
|
setColumnOrder((prev) => {
|
|
16962
17139
|
const base = prev && prev.length > 0 ? [...prev] : selectedColumnKeys ? [...selectedColumnKeys] : [];
|
|
16963
17140
|
const index = base.indexOf(key);
|
|
@@ -16968,7 +17145,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16968
17145
|
return base;
|
|
16969
17146
|
});
|
|
16970
17147
|
}, [selectedColumnKeys]);
|
|
16971
|
-
const handleTablePageChange =
|
|
17148
|
+
const handleTablePageChange = React6.useCallback((page, newPageSize) => {
|
|
16972
17149
|
if (newPageSize && newPageSize !== pageSize) {
|
|
16973
17150
|
setPageSize(newPageSize);
|
|
16974
17151
|
setGalleryPage(1);
|
|
@@ -16978,7 +17155,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16978
17155
|
pagination.onChange(page, newPageSize ?? pageSize);
|
|
16979
17156
|
}
|
|
16980
17157
|
}, [pageSize, tableProps.pagination]);
|
|
16981
|
-
const tablePagination =
|
|
17158
|
+
const tablePagination = React6.useMemo(() => {
|
|
16982
17159
|
if (!isClientFiltering) {
|
|
16983
17160
|
if (!tableProps.pagination || typeof tableProps.pagination !== "object") return tableProps.pagination;
|
|
16984
17161
|
return {
|
|
@@ -16999,23 +17176,23 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
16999
17176
|
onShowSizeChange: handleTablePageChange
|
|
17000
17177
|
};
|
|
17001
17178
|
}, [handleTablePageChange, isClientFiltering, pageSize, tableProps.pagination]);
|
|
17002
|
-
const categoricalFields =
|
|
17179
|
+
const categoricalFields = React6.useMemo(() => {
|
|
17003
17180
|
return model.fields.filter((field) => isPkField(field, model) || (field.type !== "number" || field.reference));
|
|
17004
17181
|
}, [model.fields]);
|
|
17005
|
-
const numericFields =
|
|
17182
|
+
const numericFields = React6.useMemo(() => {
|
|
17006
17183
|
return model.fields.filter((field) => !isPkField(field, model) && field.type === "number" && !field.reference);
|
|
17007
17184
|
}, [model.fields]);
|
|
17008
|
-
const hasActiveRangeColumnFilter =
|
|
17185
|
+
const hasActiveRangeColumnFilter = React6.useMemo(() => {
|
|
17009
17186
|
return Object.values(columnFiltersSelected).some(
|
|
17010
17187
|
(vals) => vals.some((v) => v.startsWith("__range__:"))
|
|
17011
17188
|
);
|
|
17012
17189
|
}, [columnFiltersSelected]);
|
|
17013
|
-
const shouldLoadAllRows =
|
|
17190
|
+
const shouldLoadAllRows = React6.useMemo(() => {
|
|
17014
17191
|
return Boolean(
|
|
17015
17192
|
localSearch.trim().length > 0 || hasActiveFilterRules || analyzeOpen || exportRequested || isTotalsDetailsView || isCrosstabView || columnFilterDropdownEverOpened || hasActiveRangeColumnFilter
|
|
17016
17193
|
);
|
|
17017
17194
|
}, [analyzeOpen, columnFilterDropdownEverOpened, exportRequested, hasActiveFilterRules, hasActiveRangeColumnFilter, isTotalsDetailsView, isCrosstabView, localSearch]);
|
|
17018
|
-
|
|
17195
|
+
React6.useEffect(() => {
|
|
17019
17196
|
if (!categoryField1 && categoricalFields.length > 0) {
|
|
17020
17197
|
setCategoryField1(categoricalFields[0].key);
|
|
17021
17198
|
}
|
|
@@ -17023,7 +17200,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17023
17200
|
setCategoryField2(categoricalFields[1].key);
|
|
17024
17201
|
}
|
|
17025
17202
|
}, [categoricalFields, categoryField1, categoryField2]);
|
|
17026
|
-
|
|
17203
|
+
React6.useEffect(() => {
|
|
17027
17204
|
if (selectedSeriesKeys !== null) return;
|
|
17028
17205
|
if (numericFields.length > 0) {
|
|
17029
17206
|
setSelectedSeriesKeys(numericFields.map((field) => field.key));
|
|
@@ -17031,7 +17208,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17031
17208
|
setSelectedSeriesKeys(["__count__"]);
|
|
17032
17209
|
}
|
|
17033
17210
|
}, [numericFields, selectedSeriesKeys]);
|
|
17034
|
-
|
|
17211
|
+
React6.useEffect(() => {
|
|
17035
17212
|
if (numericFields.length === 0) {
|
|
17036
17213
|
if (rankingFieldKey !== null) setRankingFieldKey(null);
|
|
17037
17214
|
if (rankingMode !== "none") setRankingMode("none");
|
|
@@ -17041,7 +17218,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17041
17218
|
setRankingFieldKey(numericFields[0].key);
|
|
17042
17219
|
}
|
|
17043
17220
|
}, [numericFields, rankingFieldKey, rankingMode]);
|
|
17044
|
-
const resetLayoutDefaults =
|
|
17221
|
+
const resetLayoutDefaults = React6.useCallback(() => {
|
|
17045
17222
|
setListVisible(defaultListVisible ?? true);
|
|
17046
17223
|
setAnalyzeOpen(isEmbedded);
|
|
17047
17224
|
setIsAnalyzeVertical(false);
|
|
@@ -17052,7 +17229,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17052
17229
|
setColumnOrder(null);
|
|
17053
17230
|
setTotalsSummaryFunctions({});
|
|
17054
17231
|
}, [isEmbedded, defaultListVisible]);
|
|
17055
|
-
const resetAnalyzeDefaults =
|
|
17232
|
+
const resetAnalyzeDefaults = React6.useCallback(() => {
|
|
17056
17233
|
setCategoryField1(categoricalFields[0]?.key ?? null);
|
|
17057
17234
|
setCategoryField2(categoricalFields.length > 1 ? categoricalFields[1].key : null);
|
|
17058
17235
|
setChartType("area");
|
|
@@ -17063,7 +17240,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17063
17240
|
setRankingN(10);
|
|
17064
17241
|
setCrosstabFilterFields([]);
|
|
17065
17242
|
}, [categoricalFields, numericFields]);
|
|
17066
|
-
const persistCurrentViewNames =
|
|
17243
|
+
const persistCurrentViewNames = React6.useCallback(async (nextSelected, nextCurrent) => {
|
|
17067
17244
|
try {
|
|
17068
17245
|
const resourceKey = prefsKey;
|
|
17069
17246
|
await authenticatedFetch(`${apiUrl}/views/preferences/view`, {
|
|
@@ -17079,7 +17256,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17079
17256
|
} catch {
|
|
17080
17257
|
}
|
|
17081
17258
|
}, [apiUrl, model.name, model.resource, allModels, preferencesResourceOverride]);
|
|
17082
|
-
const loadViewNames =
|
|
17259
|
+
const loadViewNames = React6.useCallback(async () => {
|
|
17083
17260
|
const resourceKey = prefsKey;
|
|
17084
17261
|
setIsLoadingViewNames(true);
|
|
17085
17262
|
try {
|
|
@@ -17124,20 +17301,20 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17124
17301
|
setIsLoadingViewNames(false);
|
|
17125
17302
|
}
|
|
17126
17303
|
}, [apiUrl, model.name, model.resource, allModels, preferencesResourceOverride]);
|
|
17127
|
-
const openSaveViewModalFor =
|
|
17304
|
+
const openSaveViewModalFor = React6.useCallback((target) => {
|
|
17128
17305
|
setSaveViewName(currentViewName || getDefaultViewName());
|
|
17129
17306
|
setSaveViewAsNew(false);
|
|
17130
17307
|
setPendingSaveTarget(target);
|
|
17131
17308
|
setSaveViewModalOpen(true);
|
|
17132
17309
|
}, [currentViewName]);
|
|
17133
|
-
const handleChangeViewName =
|
|
17310
|
+
const handleChangeViewName = React6.useCallback(async (nextView) => {
|
|
17134
17311
|
const resolvedName = normalizeViewName(nextView);
|
|
17135
17312
|
setCurrentViewName(resolvedName);
|
|
17136
17313
|
setSaveViewName(resolvedName);
|
|
17137
17314
|
const nextSelected = selectedViewNames.length > 0 ? selectedViewNames : [resolvedName];
|
|
17138
17315
|
await persistCurrentViewNames(nextSelected, resolvedName);
|
|
17139
17316
|
}, [persistCurrentViewNames, selectedViewNames]);
|
|
17140
|
-
const updateSelectedViewNames =
|
|
17317
|
+
const updateSelectedViewNames = React6.useCallback(async (nextSelected) => {
|
|
17141
17318
|
if (nextSelected.length === 0) {
|
|
17142
17319
|
nextSelected = [getDefaultViewName()];
|
|
17143
17320
|
}
|
|
@@ -17149,7 +17326,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17149
17326
|
}
|
|
17150
17327
|
await persistCurrentViewNames(nextSelected, nextCurrent);
|
|
17151
17328
|
}, [currentViewName, persistCurrentViewNames]);
|
|
17152
|
-
const moveSelectedView =
|
|
17329
|
+
const moveSelectedView = React6.useCallback((name, direction) => {
|
|
17153
17330
|
setSelectedViewNames((prev) => {
|
|
17154
17331
|
const idx = prev.indexOf(name);
|
|
17155
17332
|
if (idx < 0) return prev;
|
|
@@ -17161,7 +17338,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17161
17338
|
return next;
|
|
17162
17339
|
});
|
|
17163
17340
|
}, [currentViewName, persistCurrentViewNames]);
|
|
17164
|
-
const handleRenameView =
|
|
17341
|
+
const handleRenameView = React6.useCallback(async () => {
|
|
17165
17342
|
const newName = normalizeViewName(renameViewName);
|
|
17166
17343
|
if (!newName || newName === currentViewName) {
|
|
17167
17344
|
setRenameViewModalOpen(false);
|
|
@@ -17188,7 +17365,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17188
17365
|
antd.message.error(error instanceof Error ? error.message : _36("Failed to rename view."));
|
|
17189
17366
|
}
|
|
17190
17367
|
}, [apiUrl, availableViewNames, currentViewName, model.name, model.resource, renameViewName, allModels, loadViewNames]);
|
|
17191
|
-
const confirmDeleteView =
|
|
17368
|
+
const confirmDeleteView = React6.useCallback(() => {
|
|
17192
17369
|
antd.Modal.confirm({
|
|
17193
17370
|
title: _36(_36("Delete view")),
|
|
17194
17371
|
content: `Delete "${currentViewName}" and all its saved preferences?`,
|
|
@@ -17213,7 +17390,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17213
17390
|
}
|
|
17214
17391
|
});
|
|
17215
17392
|
}, [apiUrl, currentViewName, model.name, model.resource, allModels, loadViewNames]);
|
|
17216
|
-
const persistLayoutPreferences =
|
|
17393
|
+
const persistLayoutPreferences = React6.useCallback(async (viewName) => {
|
|
17217
17394
|
if (!resolvedLayoutPreferenceType) return;
|
|
17218
17395
|
const resourceKey = prefsKey;
|
|
17219
17396
|
const resolvedViewName = normalizeViewName(viewName);
|
|
@@ -17257,7 +17434,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17257
17434
|
setIsSavingLayoutPrefs(false);
|
|
17258
17435
|
}
|
|
17259
17436
|
}, [apiUrl, analyzeOpen, columnFiltersSelected, columnOrder, columnSort, filtersCollapsed, filterRules, isAnalyzeFirst, isAnalyzeVertical, resolvedLayoutPreferenceType, listVisible, pageSize, selectedColumnKeys, totalsSummaryFunctions, model.name, model.resource, allModels, preferencesResourceOverride]);
|
|
17260
|
-
const persistAnalyzePreferences =
|
|
17437
|
+
const persistAnalyzePreferences = React6.useCallback(async (viewName) => {
|
|
17261
17438
|
const resourceKey = prefsKey;
|
|
17262
17439
|
const resolvedViewName = normalizeViewName(viewName);
|
|
17263
17440
|
const preferences = {
|
|
@@ -17289,7 +17466,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17289
17466
|
setIsSavingAnalyzePrefs(false);
|
|
17290
17467
|
}
|
|
17291
17468
|
}, [apiUrl, categoryField1, categoryField2, chartType, selectedSeriesKeys, summaryFn, rankingMode, rankingFieldKey, rankingN, crosstabFilterFields, model.name, model.resource, allModels, preferencesResourceOverride]);
|
|
17292
|
-
const handleConfirmSaveView =
|
|
17469
|
+
const handleConfirmSaveView = React6.useCallback(async () => {
|
|
17293
17470
|
if (!pendingSaveTarget) return;
|
|
17294
17471
|
const viewName = normalizeViewName(saveViewName || currentViewName);
|
|
17295
17472
|
const viewExists = availableViewNames.includes(viewName);
|
|
@@ -17316,10 +17493,10 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17316
17493
|
await persistCurrentViewNames(nextSelected, viewName);
|
|
17317
17494
|
await loadViewNames();
|
|
17318
17495
|
}, [availableViewNames, currentViewName, loadViewNames, pendingSaveTarget, persistAnalyzePreferences, persistCurrentViewNames, persistLayoutPreferences, saveViewAsNew, saveViewName, selectedViewNames]);
|
|
17319
|
-
|
|
17496
|
+
React6.useEffect(() => {
|
|
17320
17497
|
loadViewNames();
|
|
17321
17498
|
}, [loadViewNames]);
|
|
17322
|
-
|
|
17499
|
+
React6.useEffect(() => {
|
|
17323
17500
|
if (!viewNamesLoaded) return;
|
|
17324
17501
|
const viewChanged = prevViewNameForResetRef.current !== null && prevViewNameForResetRef.current !== currentViewName;
|
|
17325
17502
|
prevViewNameForResetRef.current = currentViewName;
|
|
@@ -17336,7 +17513,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17336
17513
|
resetAnalyzeDefaults();
|
|
17337
17514
|
}
|
|
17338
17515
|
}, [currentViewName, resetAnalyzeDefaults, resetLayoutDefaults, viewNamesLoaded]);
|
|
17339
|
-
|
|
17516
|
+
React6.useEffect(() => {
|
|
17340
17517
|
const resourceKey = prefsKey;
|
|
17341
17518
|
const viewKey = `${resourceKey}::${currentViewName}`;
|
|
17342
17519
|
if (analyzePrefsResourceRef.current !== viewKey) {
|
|
@@ -17389,7 +17566,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17389
17566
|
cancelled = true;
|
|
17390
17567
|
};
|
|
17391
17568
|
}, [apiUrl, currentViewName, model.name, model.resource, allModels, preferencesResourceOverride]);
|
|
17392
|
-
|
|
17569
|
+
React6.useEffect(() => {
|
|
17393
17570
|
if (!resolvedLayoutPreferenceType) return;
|
|
17394
17571
|
const resourceKey = prefsKey;
|
|
17395
17572
|
const viewKey = `${resourceKey}::${resolvedLayoutPreferenceType}::${currentViewName}`;
|
|
@@ -17474,7 +17651,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17474
17651
|
cancelled = true;
|
|
17475
17652
|
};
|
|
17476
17653
|
}, [apiUrl, currentViewName, resolvedLayoutPreferenceType, model.name, model.resource, allModels, preferencesResourceOverride]);
|
|
17477
|
-
const fetchAllRows =
|
|
17654
|
+
const fetchAllRows = React6.useCallback(async () => {
|
|
17478
17655
|
setIsAllRowsLoading(true);
|
|
17479
17656
|
setAllRowsError(null);
|
|
17480
17657
|
const filtersToApply = activeFilters && activeFilters.length > 0 ? activeFilters : tableFilters;
|
|
@@ -17510,7 +17687,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17510
17687
|
setAllRowsLoaded(true);
|
|
17511
17688
|
}
|
|
17512
17689
|
}, [activeFilters, apiUrl, model.name, model.resource, tableFilters, allModels]);
|
|
17513
|
-
|
|
17690
|
+
React6.useEffect(() => {
|
|
17514
17691
|
if (!shouldLoadAllRows) return;
|
|
17515
17692
|
const filtersToApply = activeFilters && activeFilters.length > 0 ? activeFilters : tableFilters;
|
|
17516
17693
|
const signature = JSON.stringify({
|
|
@@ -17525,7 +17702,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17525
17702
|
lastAllRowsSignature.current = signature;
|
|
17526
17703
|
fetchAllRows();
|
|
17527
17704
|
}, [activeFilters, analyzeOpen, exportRequested, fetchAllRows, model.name, shouldLoadAllRows, tableFilters]);
|
|
17528
|
-
|
|
17705
|
+
React6.useEffect(() => {
|
|
17529
17706
|
if (!allRowsLoaded) return;
|
|
17530
17707
|
if (analyzeTouchedRef.current) return;
|
|
17531
17708
|
if (isTotalsDetailsView) return;
|
|
@@ -17535,7 +17712,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17535
17712
|
setAnalyzeOpen(true);
|
|
17536
17713
|
}
|
|
17537
17714
|
}, [allRows?.length, allRowsLoaded, isTotalsDetailsView]);
|
|
17538
|
-
|
|
17715
|
+
React6.useEffect(() => {
|
|
17539
17716
|
if (!hasActiveFilterRules || isClientFiltering) return;
|
|
17540
17717
|
const resolveServerDate = (val, forRange) => {
|
|
17541
17718
|
if (val?.mode === "relative") {
|
|
@@ -17598,7 +17775,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17598
17775
|
const combined = [...tableFilters, ...serverFilters];
|
|
17599
17776
|
setFilters(combined, "replace");
|
|
17600
17777
|
}, [filterRules, hasActiveFilterRules, isClientFiltering, model.fields, setFilters, tableFilters]);
|
|
17601
|
-
const formatCategoryValue =
|
|
17778
|
+
const formatCategoryValue = React6.useCallback((field, record) => {
|
|
17602
17779
|
if (!field) return _36("All");
|
|
17603
17780
|
const raw = record?.[field.key];
|
|
17604
17781
|
if (raw === void 0 || raw === null) return "-";
|
|
@@ -17616,7 +17793,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17616
17793
|
if (field.type === "time") return formatTimeValue(raw);
|
|
17617
17794
|
return String(raw);
|
|
17618
17795
|
}, [labelCache]);
|
|
17619
|
-
const chartData =
|
|
17796
|
+
const chartData = React6.useMemo(() => {
|
|
17620
17797
|
const data = Array.isArray(columnFilteredDataSource) ? columnFilteredDataSource : [];
|
|
17621
17798
|
const cat1Field = categoryField1 ? model.fields.find((field) => field.key === categoryField1) : void 0;
|
|
17622
17799
|
const cat2Field = categoryField2 ? model.fields.find((field) => field.key === categoryField2) : void 0;
|
|
@@ -17723,7 +17900,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17723
17900
|
};
|
|
17724
17901
|
}, [columnFilteredDataSource, categoryField1, categoryField2, model.fields, numericFields, formatCategoryValue, summaryFn, selectedSeriesKeys, rankingMode, rankingFieldKey, rankingN]);
|
|
17725
17902
|
const crosstabBarColor = modelTone.soft || token.colorPrimaryBg || "rgba(22, 119, 255, 0.16)";
|
|
17726
|
-
const stageCrosstabCellEdits =
|
|
17903
|
+
const stageCrosstabCellEdits = React6.useCallback((updates) => {
|
|
17727
17904
|
if (updates.length === 0) return;
|
|
17728
17905
|
setCrosstabStaged((prev) => {
|
|
17729
17906
|
const next = { ...prev };
|
|
@@ -17734,11 +17911,11 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17734
17911
|
return next;
|
|
17735
17912
|
});
|
|
17736
17913
|
}, []);
|
|
17737
|
-
const getCrosstabStagedValue =
|
|
17914
|
+
const getCrosstabStagedValue = React6.useCallback((recordId, fieldKey) => {
|
|
17738
17915
|
return crosstabStaged[String(recordId)]?.[fieldKey];
|
|
17739
17916
|
}, [crosstabStaged]);
|
|
17740
17917
|
const crosstabHasPendingEdits = Object.keys(crosstabStaged).length > 0;
|
|
17741
|
-
const saveCrosstabEdits =
|
|
17918
|
+
const saveCrosstabEdits = React6.useCallback(async () => {
|
|
17742
17919
|
const entries = Object.entries(crosstabStaged);
|
|
17743
17920
|
if (entries.length === 0) return;
|
|
17744
17921
|
setCrosstabSaving(true);
|
|
@@ -17761,8 +17938,8 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17761
17938
|
setCrosstabSaving(false);
|
|
17762
17939
|
}
|
|
17763
17940
|
}, [crosstabStaged, apiUrl, allModels, model.resource, model.name, invalidate]);
|
|
17764
|
-
const crosstabResolvedRefIdsRef =
|
|
17765
|
-
|
|
17941
|
+
const crosstabResolvedRefIdsRef = React6.useRef(/* @__PURE__ */ new Set());
|
|
17942
|
+
React6.useEffect(() => {
|
|
17766
17943
|
if (!isCrosstabView) return;
|
|
17767
17944
|
const refFields = [categoryField1, categoryField2, ...crosstabFilterFields].filter((k) => Boolean(k)).map((k) => model.fields.find((f) => f.key === k)).filter((f) => Boolean(f && f.reference));
|
|
17768
17945
|
if (refFields.length === 0) return;
|
|
@@ -17797,7 +17974,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17797
17974
|
cancelled = true;
|
|
17798
17975
|
};
|
|
17799
17976
|
}, [isCrosstabView, categoryField1, categoryField2, crosstabFilterFields, allRowsData, columnFilteredDataSource, model.fields, allModels, apiUrl, handleReferenceLabel]);
|
|
17800
|
-
const crosstabFilterOptions =
|
|
17977
|
+
const crosstabFilterOptions = React6.useMemo(() => {
|
|
17801
17978
|
if (crosstabFilterFields.length === 0) return /* @__PURE__ */ new Map();
|
|
17802
17979
|
const data = allRowsData.length > 0 ? allRowsData : Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
|
|
17803
17980
|
const rangeCount = viewSettings?.maxDistinctColumnFilterValuesToRanges ?? 20;
|
|
@@ -17969,7 +18146,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17969
18146
|
}
|
|
17970
18147
|
)
|
|
17971
18148
|
] });
|
|
17972
|
-
const chartSignature =
|
|
18149
|
+
const chartSignature = React6.useMemo(() => {
|
|
17973
18150
|
return JSON.stringify({
|
|
17974
18151
|
chartType,
|
|
17975
18152
|
summaryFn,
|
|
@@ -17982,10 +18159,10 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
17982
18159
|
groups: chartData.groups
|
|
17983
18160
|
});
|
|
17984
18161
|
}, [chartType, summaryFn, categoryField1, categoryField2, rankingMode, rankingFieldKey, rankingN, chartData]);
|
|
17985
|
-
const statsSummary =
|
|
18162
|
+
const statsSummary = React6.useMemo(() => {
|
|
17986
18163
|
return buildStatsSummary(columnFilteredDataSource, displayFields, labelCache);
|
|
17987
18164
|
}, [columnFilteredDataSource, displayFields, labelCache]);
|
|
17988
|
-
const tdCategoricalBoxes =
|
|
18165
|
+
const tdCategoricalBoxes = React6.useMemo(() => {
|
|
17989
18166
|
if (!isTotalsDetailsView) return [];
|
|
17990
18167
|
return displayFields.filter((field) => field.type !== "number" || Boolean(field.reference)).map((field) => {
|
|
17991
18168
|
const counts = /* @__PURE__ */ new Map();
|
|
@@ -18022,14 +18199,14 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18022
18199
|
};
|
|
18023
18200
|
});
|
|
18024
18201
|
}, [isTotalsDetailsView, allRows, displayFields, labelCache]);
|
|
18025
|
-
const getDefaultTotalsSummaryFn =
|
|
18202
|
+
const getDefaultTotalsSummaryFn = React6.useCallback((field) => {
|
|
18026
18203
|
if (isPkField(field, model) || isReferenceField(field)) return "count";
|
|
18027
18204
|
return "sum";
|
|
18028
18205
|
}, []);
|
|
18029
|
-
const resolveTotalsSummaryFn =
|
|
18206
|
+
const resolveTotalsSummaryFn = React6.useCallback((field) => {
|
|
18030
18207
|
return totalsSummaryFunctions[field.key] || getDefaultTotalsSummaryFn(field);
|
|
18031
18208
|
}, [getDefaultTotalsSummaryFn, totalsSummaryFunctions]);
|
|
18032
|
-
const computeTotalsSummaryValue =
|
|
18209
|
+
const computeTotalsSummaryValue = React6.useCallback((field) => {
|
|
18033
18210
|
const fn = resolveTotalsSummaryFn(field);
|
|
18034
18211
|
if (field.type === "number" && !field.reference) {
|
|
18035
18212
|
const values = (allRows || []).map((row) => Number(row?.[field.key])).filter((v) => !Number.isNaN(v) && Number.isFinite(v));
|
|
@@ -18058,7 +18235,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18058
18235
|
if (fn === "distinct") return new Set(rawValues.map((v) => String(v ?? "-"))).size;
|
|
18059
18236
|
return rawValues.length;
|
|
18060
18237
|
}, [allRows, resolveTotalsSummaryFn]);
|
|
18061
|
-
const getSummaryFunctionDisplayText =
|
|
18238
|
+
const getSummaryFunctionDisplayText = React6.useCallback((fn) => {
|
|
18062
18239
|
if (!fn) return "";
|
|
18063
18240
|
const labels = {
|
|
18064
18241
|
sum: _36("Sum"),
|
|
@@ -18071,7 +18248,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18071
18248
|
};
|
|
18072
18249
|
return labels[fn] || fn;
|
|
18073
18250
|
}, []);
|
|
18074
|
-
const tdNumericBoxes =
|
|
18251
|
+
const tdNumericBoxes = React6.useMemo(() => {
|
|
18075
18252
|
if (!isTotalsDetailsView) return [];
|
|
18076
18253
|
return displayFields.filter((field) => field.type === "number" && !field.reference).map((field) => {
|
|
18077
18254
|
const summaryFnVal = resolveTotalsSummaryFn(field);
|
|
@@ -18080,7 +18257,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18080
18257
|
return { key: field.key, label, value, summaryFn: summaryFnVal };
|
|
18081
18258
|
});
|
|
18082
18259
|
}, [isTotalsDetailsView, displayFields, resolveTotalsSummaryFn, computeTotalsSummaryValue]);
|
|
18083
|
-
const totalsSummaryConfigFields =
|
|
18260
|
+
const totalsSummaryConfigFields = React6.useMemo(() => {
|
|
18084
18261
|
return displayFields.filter((field) => field.type === "number" && !field.reference);
|
|
18085
18262
|
}, [displayFields]);
|
|
18086
18263
|
const renderDynamicListTotalsBoxes = () => {
|
|
@@ -18145,7 +18322,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18145
18322
|
) })
|
|
18146
18323
|
] }) });
|
|
18147
18324
|
};
|
|
18148
|
-
const numericColumnMaxes =
|
|
18325
|
+
const numericColumnMaxes = React6.useMemo(() => {
|
|
18149
18326
|
const maxes = {};
|
|
18150
18327
|
const rows = allRows || [];
|
|
18151
18328
|
displayFields.forEach((field) => {
|
|
@@ -18159,7 +18336,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18159
18336
|
});
|
|
18160
18337
|
return maxes;
|
|
18161
18338
|
}, [allRows, displayFields]);
|
|
18162
|
-
const statsNumericMaxes =
|
|
18339
|
+
const statsNumericMaxes = React6.useMemo(() => {
|
|
18163
18340
|
const stats = statsSummary.numericStats;
|
|
18164
18341
|
const maxAbs = (values) => {
|
|
18165
18342
|
const absValues = values.filter((val) => typeof val === "number").map((val) => Math.abs(val));
|
|
@@ -18173,13 +18350,13 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18173
18350
|
stddev: maxAbs(stats.map((row) => row.stddev))
|
|
18174
18351
|
};
|
|
18175
18352
|
}, [statsSummary.numericStats]);
|
|
18176
|
-
|
|
18353
|
+
React6.useEffect(() => {
|
|
18177
18354
|
if (!analyzeOpen) return;
|
|
18178
18355
|
skipNextAnimationRef.current = true;
|
|
18179
18356
|
setChartAnimationStage("enter");
|
|
18180
18357
|
setChartAnimationKey((key) => key + 1);
|
|
18181
18358
|
}, [analyzeOpen]);
|
|
18182
|
-
|
|
18359
|
+
React6.useEffect(() => {
|
|
18183
18360
|
if (!analyzeOpen) return;
|
|
18184
18361
|
if (skipNextAnimationRef.current) {
|
|
18185
18362
|
skipNextAnimationRef.current = false;
|
|
@@ -18188,17 +18365,17 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18188
18365
|
setChartAnimationStage("update");
|
|
18189
18366
|
setChartAnimationKey((key) => key + 1);
|
|
18190
18367
|
}, [analyzeOpen, chartSignature]);
|
|
18191
|
-
const fieldByKey =
|
|
18368
|
+
const fieldByKey = React6.useMemo(() => {
|
|
18192
18369
|
return new Map(model.fields.map((field) => [field.key, field]));
|
|
18193
18370
|
}, [model.fields]);
|
|
18194
|
-
const chartTitle =
|
|
18371
|
+
const chartTitle = React6.useMemo(() => {
|
|
18195
18372
|
const cat1Label = categoryField1 ? fieldByKey.get(categoryField1)?.label : "All";
|
|
18196
18373
|
const cat2Label = categoryField2 ? fieldByKey.get(categoryField2)?.label : null;
|
|
18197
18374
|
const parts = [model.label || model.name, cat1Label];
|
|
18198
18375
|
if (cat2Label) parts.push(cat2Label);
|
|
18199
18376
|
return parts.filter(Boolean).join(" \u2022 ");
|
|
18200
18377
|
}, [categoryField1, categoryField2, fieldByKey, model.label, model.name]);
|
|
18201
|
-
const formatValueForExport =
|
|
18378
|
+
const formatValueForExport = React6.useCallback((field, record) => {
|
|
18202
18379
|
const raw = record?.[field.key];
|
|
18203
18380
|
if (raw === void 0 || raw === null) return "";
|
|
18204
18381
|
if (field.reference) {
|
|
@@ -18214,7 +18391,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18214
18391
|
if (field.type === "time") return formatTimeValue(raw);
|
|
18215
18392
|
return String(raw);
|
|
18216
18393
|
}, [labelCache]);
|
|
18217
|
-
|
|
18394
|
+
React6.useEffect(() => {
|
|
18218
18395
|
if (!exportRequested || isAllRowsLoading) return;
|
|
18219
18396
|
const escapeCsv = (value) => {
|
|
18220
18397
|
if (value.includes('"') || value.includes(",") || value.includes("\n")) {
|
|
@@ -18327,11 +18504,11 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18327
18504
|
}
|
|
18328
18505
|
return { resource: null, id: null, isLinkRow: false };
|
|
18329
18506
|
};
|
|
18330
|
-
const clearBulkSelection =
|
|
18507
|
+
const clearBulkSelection = React6.useCallback(() => {
|
|
18331
18508
|
setBulkSelectedRowKeys([]);
|
|
18332
18509
|
bulkSelectedRowsMapRef.current.clear();
|
|
18333
18510
|
}, []);
|
|
18334
|
-
|
|
18511
|
+
React6.useEffect(() => {
|
|
18335
18512
|
if (!selectAllFilteredPending || !allRowsLoaded) return;
|
|
18336
18513
|
setSelectAllFilteredPending(false);
|
|
18337
18514
|
const keys = filteredDataSource.map((r) => getRowKey(r));
|
|
@@ -18339,7 +18516,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18339
18516
|
filteredDataSource.forEach((r) => bulkSelectedRowsMapRef.current.set(getRowKey(r), r));
|
|
18340
18517
|
setBulkSelectedRowKeys(keys);
|
|
18341
18518
|
}, [selectAllFilteredPending, allRowsLoaded, filteredDataSource]);
|
|
18342
|
-
const handleSelectAllFiltered =
|
|
18519
|
+
const handleSelectAllFiltered = React6.useCallback(() => {
|
|
18343
18520
|
if (!allRowsLoaded) {
|
|
18344
18521
|
setSelectAllFilteredPending(true);
|
|
18345
18522
|
fetchAllRows();
|
|
@@ -18350,7 +18527,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18350
18527
|
setBulkSelectedRowKeys(keys);
|
|
18351
18528
|
}
|
|
18352
18529
|
}, [allRowsLoaded, fetchAllRows, filteredDataSource]);
|
|
18353
|
-
const executeBulkActions =
|
|
18530
|
+
const executeBulkActions = React6.useCallback(async () => {
|
|
18354
18531
|
const records = bulkSelectedRowKeys.map((k) => bulkSelectedRowsMapRef.current.get(k)).filter(Boolean);
|
|
18355
18532
|
if (records.length === 0) return;
|
|
18356
18533
|
const resource = resolveResourcePath(model.resource || model.name, allModels);
|
|
@@ -18462,9 +18639,9 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18462
18639
|
}
|
|
18463
18640
|
};
|
|
18464
18641
|
const isEmptyTable = (filteredDataSource?.length ?? 0) === 0;
|
|
18465
|
-
const getRowKeyRef =
|
|
18642
|
+
const getRowKeyRef = React6.useRef(getRowKey);
|
|
18466
18643
|
getRowKeyRef.current = getRowKey;
|
|
18467
|
-
const handleBulkRowSelectionChange =
|
|
18644
|
+
const handleBulkRowSelectionChange = React6.useCallback(
|
|
18468
18645
|
(newKeys, newRowsOnPage) => {
|
|
18469
18646
|
const currentPageData = isClientFiltering ? filteredDataSource : Array.isArray(tableProps.dataSource) ? tableProps.dataSource : [];
|
|
18470
18647
|
const currentPageKeys = new Set(currentPageData.map((r) => String(getRowKeyRef.current(r))));
|
|
@@ -18493,7 +18670,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18493
18670
|
]
|
|
18494
18671
|
};
|
|
18495
18672
|
const filteredTotalCount = isClientFiltering ? filteredDataSource.length : typeof tableProps.pagination === "object" ? tableProps.pagination?.total ?? filteredDataSource.length : filteredDataSource.length;
|
|
18496
|
-
const bulkActionsAvailable =
|
|
18673
|
+
const bulkActionsAvailable = React6.useMemo(() => {
|
|
18497
18674
|
const opts = [];
|
|
18498
18675
|
if (canBulkEdit) {
|
|
18499
18676
|
opts.push({ label: _36("Change field value"), value: "__change_field__" });
|
|
@@ -18923,7 +19100,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18923
19100
|
});
|
|
18924
19101
|
};
|
|
18925
19102
|
const galleryPageSize = typeof tablePagination === "object" && tablePagination?.pageSize ? tablePagination.pageSize : 10;
|
|
18926
|
-
const handleGalleryPageChange =
|
|
19103
|
+
const handleGalleryPageChange = React6.useCallback((page, nextPageSize) => {
|
|
18927
19104
|
setGalleryPage(page);
|
|
18928
19105
|
if (nextPageSize && nextPageSize !== pageSize) {
|
|
18929
19106
|
setPageSize(nextPageSize);
|
|
@@ -18941,19 +19118,19 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18941
19118
|
}, [isClientFiltering, pageSize, tableProps]);
|
|
18942
19119
|
const serverCurrentPage = !isClientFiltering && typeof tableProps.pagination === "object" ? Number(tableProps.pagination.current || 1) : 1;
|
|
18943
19120
|
const serverTotal = !isClientFiltering && typeof tableProps.pagination === "object" ? Number(tableProps.pagination.total || 0) : 0;
|
|
18944
|
-
|
|
19121
|
+
React6.useEffect(() => {
|
|
18945
19122
|
if (isClientFiltering) return;
|
|
18946
19123
|
if (Number.isFinite(serverCurrentPage) && serverCurrentPage > 0 && serverCurrentPage !== galleryPage) {
|
|
18947
19124
|
setGalleryPage(serverCurrentPage);
|
|
18948
19125
|
}
|
|
18949
19126
|
}, [galleryPage, isClientFiltering, serverCurrentPage]);
|
|
18950
|
-
const galleryRows =
|
|
19127
|
+
const galleryRows = React6.useMemo(() => {
|
|
18951
19128
|
if (!isGalleryView) return [];
|
|
18952
19129
|
if (!isClientFiltering) return filteredDataSource;
|
|
18953
19130
|
const start = (galleryPage - 1) * galleryPageSize;
|
|
18954
19131
|
return filteredDataSource.slice(start, start + galleryPageSize);
|
|
18955
19132
|
}, [filteredDataSource, galleryPage, galleryPageSize, isClientFiltering, isGalleryView]);
|
|
18956
|
-
const galleryPaginationProps =
|
|
19133
|
+
const galleryPaginationProps = React6.useMemo(() => {
|
|
18957
19134
|
if (!isGalleryView) return void 0;
|
|
18958
19135
|
if (!isClientFiltering) {
|
|
18959
19136
|
return {
|
|
@@ -18978,17 +19155,17 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
18978
19155
|
onShowSizeChange: handleGalleryPageChange
|
|
18979
19156
|
};
|
|
18980
19157
|
}, [filteredDataSource.length, galleryPage, galleryPageSize, handleGalleryPageChange, isClientFiltering, isGalleryView, serverTotal, tablePagination]);
|
|
18981
|
-
const calendarDateFieldKeySet =
|
|
19158
|
+
const calendarDateFieldKeySet = React6.useMemo(
|
|
18982
19159
|
() => new Set(calendarDateFieldOptions.map((field) => field.key)),
|
|
18983
19160
|
[calendarDateFieldOptions]
|
|
18984
19161
|
);
|
|
18985
|
-
|
|
19162
|
+
React6.useEffect(() => {
|
|
18986
19163
|
if (!isCalendarView) return;
|
|
18987
19164
|
if (calendarDateField && calendarDateFieldKeySet.has(calendarDateField)) return;
|
|
18988
19165
|
const fallback = calendarDateFieldOptions[0]?.key || "";
|
|
18989
19166
|
if (fallback !== calendarDateField) setCalendarDateField(fallback);
|
|
18990
19167
|
}, [calendarDateField, calendarDateFieldKeySet, calendarDateFieldOptions, isCalendarView]);
|
|
18991
|
-
const calendarEntries =
|
|
19168
|
+
const calendarEntries = React6.useMemo(() => {
|
|
18992
19169
|
if (!isCalendarView || !calendarDateField) return [];
|
|
18993
19170
|
const entries = [];
|
|
18994
19171
|
filteredDataSource.forEach((record) => {
|
|
@@ -19006,7 +19183,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
19006
19183
|
});
|
|
19007
19184
|
return entries;
|
|
19008
19185
|
}, [calendarDateField, filteredDataSource, isCalendarView]);
|
|
19009
|
-
const calendarEarliestDateTs =
|
|
19186
|
+
const calendarEarliestDateTs = React6.useMemo(() => {
|
|
19010
19187
|
if (calendarEntries.length === 0) return null;
|
|
19011
19188
|
let earliest = calendarEntries[0].date.valueOf();
|
|
19012
19189
|
for (let index = 1; index < calendarEntries.length; index += 1) {
|
|
@@ -19015,8 +19192,8 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
19015
19192
|
}
|
|
19016
19193
|
return earliest;
|
|
19017
19194
|
}, [calendarEntries]);
|
|
19018
|
-
const calendarInitSignatureRef =
|
|
19019
|
-
|
|
19195
|
+
const calendarInitSignatureRef = React6.useRef("");
|
|
19196
|
+
React6.useEffect(() => {
|
|
19020
19197
|
if (!isCalendarView) return;
|
|
19021
19198
|
const signature = `${calendarDateField}|${calendarMode}|${calendarEarliestDateTs ?? "none"}`;
|
|
19022
19199
|
if (calendarInitSignatureRef.current === signature) return;
|
|
@@ -19027,7 +19204,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
19027
19204
|
}
|
|
19028
19205
|
setCalendarAnchorDate(dayjs9__default.default(calendarEarliestDateTs).startOf(calendarMode));
|
|
19029
19206
|
}, [calendarDateField, calendarEarliestDateTs, calendarMode, isCalendarView]);
|
|
19030
|
-
const calendarEntriesByDate =
|
|
19207
|
+
const calendarEntriesByDate = React6.useMemo(() => {
|
|
19031
19208
|
const grouped = /* @__PURE__ */ new Map();
|
|
19032
19209
|
calendarEntries.forEach((entry) => {
|
|
19033
19210
|
const key = entry.date.format("YYYY-MM-DD");
|
|
@@ -19037,7 +19214,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
19037
19214
|
});
|
|
19038
19215
|
return grouped;
|
|
19039
19216
|
}, [calendarEntries]);
|
|
19040
|
-
const calendarRangeDays =
|
|
19217
|
+
const calendarRangeDays = React6.useMemo(() => {
|
|
19041
19218
|
const current = calendarAnchorDate.startOf(calendarMode);
|
|
19042
19219
|
if (calendarMode === "week") {
|
|
19043
19220
|
const start2 = current.startOf("week");
|
|
@@ -19048,7 +19225,7 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
19048
19225
|
const totalDays = end.diff(start, "day") + 1;
|
|
19049
19226
|
return Array.from({ length: totalDays }, (_unused, offset) => start.add(offset, "day"));
|
|
19050
19227
|
}, [calendarAnchorDate, calendarMode]);
|
|
19051
|
-
const calendarPeriodLabel =
|
|
19228
|
+
const calendarPeriodLabel = React6.useMemo(() => {
|
|
19052
19229
|
if (calendarMode === "week") {
|
|
19053
19230
|
const weekStart = calendarAnchorDate.startOf("week");
|
|
19054
19231
|
const weekEnd = weekStart.endOf("week");
|
|
@@ -19944,7 +20121,8 @@ var DynamicList = ({ model: modelProp, allModels, filter, relationConfig, isEmbe
|
|
|
19944
20121
|
{ label: _36("Heatmap"), value: "heatmap" },
|
|
19945
20122
|
{ label: _36("Crosstab"), value: "crosstab" },
|
|
19946
20123
|
{ label: _36("Radar"), value: "radar" },
|
|
19947
|
-
{ label: _36("Combo (Bar + Line)"), value: "combo" }
|
|
20124
|
+
{ label: _36("Combo (Bar + Line)"), value: "combo" },
|
|
20125
|
+
{ label: _36("3D Scatter"), value: "3d" }
|
|
19948
20126
|
]
|
|
19949
20127
|
}
|
|
19950
20128
|
)
|
|
@@ -20236,8 +20414,8 @@ var LIST_PANEL_ID = "list-panel";
|
|
|
20236
20414
|
var detailPanelId = (idx) => `detail-panel-${idx}`;
|
|
20237
20415
|
var COLLAPSED_SIZE = 10;
|
|
20238
20416
|
var FakeRouteProvider = ({ model, id, children }) => {
|
|
20239
|
-
const existingRouteContext =
|
|
20240
|
-
const fakeRouteContext =
|
|
20417
|
+
const existingRouteContext = React6.useContext(reactRouterDom.UNSAFE_RouteContext);
|
|
20418
|
+
const fakeRouteContext = React6.useMemo(() => ({
|
|
20241
20419
|
...existingRouteContext,
|
|
20242
20420
|
matches: [
|
|
20243
20421
|
...existingRouteContext.matches,
|
|
@@ -20357,9 +20535,9 @@ var ResizeHandle = () => {
|
|
|
20357
20535
|
);
|
|
20358
20536
|
};
|
|
20359
20537
|
var MultiPaneLayout = ({ children }) => {
|
|
20360
|
-
const containerRef =
|
|
20361
|
-
const [panelHeight, setPanelHeight] =
|
|
20362
|
-
|
|
20538
|
+
const containerRef = React6.useRef(null);
|
|
20539
|
+
const [panelHeight, setPanelHeight] = React6.useState("100vh");
|
|
20540
|
+
React6.useLayoutEffect(() => {
|
|
20363
20541
|
const measure = () => {
|
|
20364
20542
|
if (!containerRef.current) return;
|
|
20365
20543
|
const top = containerRef.current.getBoundingClientRect().top;
|
|
@@ -20371,13 +20549,13 @@ var MultiPaneLayout = ({ children }) => {
|
|
|
20371
20549
|
}, []);
|
|
20372
20550
|
const [searchParams, setSearchParams] = reactRouterDom.useSearchParams();
|
|
20373
20551
|
const allModels = useAllModels();
|
|
20374
|
-
const PrimaryShowRenderer =
|
|
20552
|
+
const PrimaryShowRenderer = React6.useContext(PrimaryShowContext);
|
|
20375
20553
|
const { token } = antd.theme.useToken();
|
|
20376
|
-
const panes =
|
|
20377
|
-
const groupRef =
|
|
20378
|
-
const pendingLayoutRef =
|
|
20379
|
-
const prevPaneCountRef =
|
|
20380
|
-
|
|
20554
|
+
const panes = React6.useMemo(() => parsePanes(searchParams), [searchParams]);
|
|
20555
|
+
const groupRef = React6.useRef(null);
|
|
20556
|
+
const pendingLayoutRef = React6.useRef(null);
|
|
20557
|
+
const prevPaneCountRef = React6.useRef(0);
|
|
20558
|
+
React6.useEffect(() => {
|
|
20381
20559
|
const newCount = panes.length;
|
|
20382
20560
|
const prevCount = prevPaneCountRef.current;
|
|
20383
20561
|
if (!pendingLayoutRef.current || !groupRef.current) {
|
|
@@ -20404,7 +20582,7 @@ var MultiPaneLayout = ({ children }) => {
|
|
|
20404
20582
|
});
|
|
20405
20583
|
return () => cancelAnimationFrame(frameId);
|
|
20406
20584
|
}, [panes.length]);
|
|
20407
|
-
const openDetail =
|
|
20585
|
+
const openDetail = React6.useCallback(
|
|
20408
20586
|
(fromPaneIndex, resource, id) => {
|
|
20409
20587
|
if (groupRef.current) {
|
|
20410
20588
|
pendingLayoutRef.current = { ...groupRef.current.getLayout() };
|
|
@@ -20424,7 +20602,7 @@ var MultiPaneLayout = ({ children }) => {
|
|
|
20424
20602
|
},
|
|
20425
20603
|
[allModels, setSearchParams]
|
|
20426
20604
|
);
|
|
20427
|
-
const closePane =
|
|
20605
|
+
const closePane = React6.useCallback(
|
|
20428
20606
|
(fromArrayIndex) => {
|
|
20429
20607
|
setSearchParams(
|
|
20430
20608
|
(prev) => {
|
|
@@ -20436,7 +20614,7 @@ var MultiPaneLayout = ({ children }) => {
|
|
|
20436
20614
|
},
|
|
20437
20615
|
[setSearchParams]
|
|
20438
20616
|
);
|
|
20439
|
-
const minimizePane =
|
|
20617
|
+
const minimizePane = React6.useCallback((panelId) => {
|
|
20440
20618
|
if (!groupRef.current) return;
|
|
20441
20619
|
const layout = groupRef.current.getLayout();
|
|
20442
20620
|
const currentSize = layout[panelId] ?? COLLAPSED_SIZE;
|
|
@@ -20451,7 +20629,7 @@ var MultiPaneLayout = ({ children }) => {
|
|
|
20451
20629
|
});
|
|
20452
20630
|
groupRef.current.setLayout(newLayout);
|
|
20453
20631
|
}, []);
|
|
20454
|
-
const maximizePane =
|
|
20632
|
+
const maximizePane = React6.useCallback((panelId) => {
|
|
20455
20633
|
if (!groupRef.current) return;
|
|
20456
20634
|
const layout = groupRef.current.getLayout();
|
|
20457
20635
|
const panelIds = Object.keys(layout);
|
|
@@ -20463,7 +20641,7 @@ var MultiPaneLayout = ({ children }) => {
|
|
|
20463
20641
|
});
|
|
20464
20642
|
groupRef.current.setLayout(newLayout);
|
|
20465
20643
|
}, []);
|
|
20466
|
-
const listPaneContext =
|
|
20644
|
+
const listPaneContext = React6.useMemo(
|
|
20467
20645
|
() => ({
|
|
20468
20646
|
isInMultiPane: true,
|
|
20469
20647
|
paneIndex: 0,
|
|
@@ -20471,7 +20649,7 @@ var MultiPaneLayout = ({ children }) => {
|
|
|
20471
20649
|
}),
|
|
20472
20650
|
[openDetail]
|
|
20473
20651
|
);
|
|
20474
|
-
const detailPaneContexts =
|
|
20652
|
+
const detailPaneContexts = React6.useMemo(
|
|
20475
20653
|
() => panes.map((_43, idx) => ({
|
|
20476
20654
|
isInMultiPane: true,
|
|
20477
20655
|
paneIndex: idx + 1,
|
|
@@ -20479,7 +20657,7 @@ var MultiPaneLayout = ({ children }) => {
|
|
|
20479
20657
|
})),
|
|
20480
20658
|
[panes, openDetail]
|
|
20481
20659
|
);
|
|
20482
|
-
const panelChildren =
|
|
20660
|
+
const panelChildren = React6.useMemo(() => {
|
|
20483
20661
|
const result = [
|
|
20484
20662
|
/* @__PURE__ */ jsxRuntime.jsx(Yt, { id: LIST_PANEL_ID, minSize: 10, style: { overflow: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsx(PaneNavigationContext.Provider, { value: listPaneContext, children }) }, "master-list")
|
|
20485
20663
|
];
|
|
@@ -20610,8 +20788,8 @@ var HierarchyView = ({ resource, recordId, fallback }) => {
|
|
|
20610
20788
|
};
|
|
20611
20789
|
var instanceCounter = 0;
|
|
20612
20790
|
var InlinePlotlyHtml = ({ html, style }) => {
|
|
20613
|
-
const containerRef =
|
|
20614
|
-
const instanceIdRef =
|
|
20791
|
+
const containerRef = React6.useRef(null);
|
|
20792
|
+
const instanceIdRef = React6.useRef("");
|
|
20615
20793
|
if (!instanceIdRef.current) {
|
|
20616
20794
|
instanceCounter += 1;
|
|
20617
20795
|
instanceIdRef.current = `iph-${instanceCounter}-${Date.now()}`;
|
|
@@ -20637,7 +20815,7 @@ var InlinePlotlyHtml = ({ html, style }) => {
|
|
|
20637
20815
|
/((?:reduceCardWidth|increaseCardWidth|optimizeCardSizeInViewPort|maximizeCardSize|minimizeCardSize|flipCard)\()(\d+)\)/g,
|
|
20638
20816
|
(match, func, suffix) => `${func}'${suffix}-${instanceId}')`
|
|
20639
20817
|
);
|
|
20640
|
-
|
|
20818
|
+
React6.useEffect(() => {
|
|
20641
20819
|
const container = containerRef.current;
|
|
20642
20820
|
if (!container) return;
|
|
20643
20821
|
const scripts = Array.from(container.querySelectorAll("script"));
|
|
@@ -20901,15 +21079,15 @@ var ColorModeContextProvider = ({
|
|
|
20901
21079
|
"(prefers-color-scheme: dark)"
|
|
20902
21080
|
).matches;
|
|
20903
21081
|
const systemPreference = isSystemPreferenceDark ? "dark" : "light";
|
|
20904
|
-
const [mode, setMode] =
|
|
21082
|
+
const [mode, setMode] = React6.useState(
|
|
20905
21083
|
colorModeFromLocalStorage === "dark" || colorModeFromLocalStorage === "light" ? colorModeFromLocalStorage : systemPreference
|
|
20906
21084
|
);
|
|
20907
|
-
const initializedFromServer =
|
|
20908
|
-
const [schemaVersion, setSchemaVersion] =
|
|
20909
|
-
|
|
21085
|
+
const initializedFromServer = React6.useRef(false);
|
|
21086
|
+
const [schemaVersion, setSchemaVersion] = React6.useState(0);
|
|
21087
|
+
React6.useEffect(() => {
|
|
20910
21088
|
return onColorSchemaChange(() => setSchemaVersion((v) => v + 1));
|
|
20911
21089
|
}, []);
|
|
20912
|
-
|
|
21090
|
+
React6.useEffect(() => {
|
|
20913
21091
|
let cancelled = false;
|
|
20914
21092
|
const load = async () => {
|
|
20915
21093
|
try {
|
|
@@ -20930,12 +21108,12 @@ var ColorModeContextProvider = ({
|
|
|
20930
21108
|
cancelled = true;
|
|
20931
21109
|
};
|
|
20932
21110
|
}, []);
|
|
20933
|
-
|
|
21111
|
+
React6.useEffect(() => {
|
|
20934
21112
|
window.localStorage.setItem("colorMode", mode);
|
|
20935
21113
|
document.body.classList.toggle("jm-dark", mode === "dark");
|
|
20936
21114
|
document.body.classList.toggle("jm-light", mode === "light");
|
|
20937
21115
|
}, [mode]);
|
|
20938
|
-
const saveToServer =
|
|
21116
|
+
const saveToServer = React6.useCallback(async (newMode) => {
|
|
20939
21117
|
try {
|
|
20940
21118
|
await authenticatedFetch(`${API_BASE_URL}/views/preferences/color-mode`, {
|
|
20941
21119
|
method: "POST",
|
|
@@ -20945,7 +21123,7 @@ var ColorModeContextProvider = ({
|
|
|
20945
21123
|
} catch (_e3) {
|
|
20946
21124
|
}
|
|
20947
21125
|
}, []);
|
|
20948
|
-
const setColorMode =
|
|
21126
|
+
const setColorMode = React6.useCallback((newMode) => {
|
|
20949
21127
|
setMode(newMode);
|
|
20950
21128
|
void saveToServer(newMode);
|
|
20951
21129
|
}, [saveToServer]);
|
|
@@ -20961,7 +21139,7 @@ var ColorModeContextProvider = ({
|
|
|
20961
21139
|
}
|
|
20962
21140
|
) });
|
|
20963
21141
|
};
|
|
20964
|
-
var ResourceContext =
|
|
21142
|
+
var ResourceContext = React6.createContext({
|
|
20965
21143
|
allResources: [],
|
|
20966
21144
|
allSystemModels: []
|
|
20967
21145
|
});
|
|
@@ -21067,10 +21245,10 @@ var LoginPage = ({ appTitle = "VeloIQ", logo }) => {
|
|
|
21067
21245
|
};
|
|
21068
21246
|
function useDashboardConfig() {
|
|
21069
21247
|
const apiUrl = core.useApiUrl();
|
|
21070
|
-
const [config, setConfig] =
|
|
21071
|
-
const [enabled, setEnabled] =
|
|
21072
|
-
const [loading, setLoading] =
|
|
21073
|
-
const load =
|
|
21248
|
+
const [config, setConfig] = React6.useState(null);
|
|
21249
|
+
const [enabled, setEnabled] = React6.useState(false);
|
|
21250
|
+
const [loading, setLoading] = React6.useState(true);
|
|
21251
|
+
const load = React6.useCallback(async () => {
|
|
21074
21252
|
setLoading(true);
|
|
21075
21253
|
try {
|
|
21076
21254
|
const res = await authenticatedFetch(`${apiUrl}/dashboard/config`);
|
|
@@ -21088,10 +21266,10 @@ function useDashboardConfig() {
|
|
|
21088
21266
|
setLoading(false);
|
|
21089
21267
|
}
|
|
21090
21268
|
}, [apiUrl]);
|
|
21091
|
-
|
|
21269
|
+
React6.useEffect(() => {
|
|
21092
21270
|
load();
|
|
21093
21271
|
}, [load]);
|
|
21094
|
-
const save =
|
|
21272
|
+
const save = React6.useCallback(async (next) => {
|
|
21095
21273
|
setConfig(next);
|
|
21096
21274
|
try {
|
|
21097
21275
|
await authenticatedFetch(`${apiUrl}/dashboard/config`, {
|
|
@@ -21104,10 +21282,52 @@ function useDashboardConfig() {
|
|
|
21104
21282
|
}, [apiUrl]);
|
|
21105
21283
|
return { config, enabled, loading, save, reload: load };
|
|
21106
21284
|
}
|
|
21285
|
+
var PlotlyChartContent = ({ chartUrl, refreshNonce }) => {
|
|
21286
|
+
const [chartHtml, setChartHtml] = React6.useState("");
|
|
21287
|
+
const [loading, setLoading] = React6.useState(true);
|
|
21288
|
+
const [error, setError] = React6.useState("");
|
|
21289
|
+
const fetchChart = React6.useCallback(async () => {
|
|
21290
|
+
setLoading(true);
|
|
21291
|
+
setError("");
|
|
21292
|
+
try {
|
|
21293
|
+
const apiUrl = typeof API_URL3 === "string" ? API_URL3 : "";
|
|
21294
|
+
const fullUrl = chartUrl.startsWith("http") ? chartUrl : `${apiUrl}${chartUrl}`;
|
|
21295
|
+
const sep = fullUrl.includes("?") ? "&" : "?";
|
|
21296
|
+
const lang = (() => {
|
|
21297
|
+
try {
|
|
21298
|
+
return (localStorage.getItem("locale") || navigator.language || "en").split("-")[0].toLowerCase();
|
|
21299
|
+
} catch {
|
|
21300
|
+
return "en";
|
|
21301
|
+
}
|
|
21302
|
+
})();
|
|
21303
|
+
const res = await authenticatedFetch(`${fullUrl}${sep}lang=${encodeURIComponent(lang)}`);
|
|
21304
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
21305
|
+
const data = await res.json();
|
|
21306
|
+
setChartHtml(data.chart_html || "");
|
|
21307
|
+
} catch (e) {
|
|
21308
|
+
setError(e?.message ?? String(e));
|
|
21309
|
+
} finally {
|
|
21310
|
+
setLoading(false);
|
|
21311
|
+
}
|
|
21312
|
+
}, [chartUrl]);
|
|
21313
|
+
React6.useEffect(() => {
|
|
21314
|
+
fetchChart();
|
|
21315
|
+
}, [fetchChart, refreshNonce]);
|
|
21316
|
+
if (loading) {
|
|
21317
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100%", minHeight: 200 }, children: /* @__PURE__ */ jsxRuntime.jsx(antd.Spin, {}) });
|
|
21318
|
+
}
|
|
21319
|
+
if (error) {
|
|
21320
|
+
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: `Chart error: ${error}`, style: { padding: 20 }, image: antd.Empty.PRESENTED_IMAGE_SIMPLE });
|
|
21321
|
+
}
|
|
21322
|
+
if (!chartHtml) {
|
|
21323
|
+
return /* @__PURE__ */ jsxRuntime.jsx(antd.Empty, { description: "No chart data", style: { padding: 20 }, image: antd.Empty.PRESENTED_IMAGE_SIMPLE });
|
|
21324
|
+
}
|
|
21325
|
+
return /* @__PURE__ */ jsxRuntime.jsx(InlinePlotlyHtml, { html: chartHtml, style: { padding: 8, height: "100%", overflow: "auto" } });
|
|
21326
|
+
};
|
|
21107
21327
|
var DashboardGridCell = ({ cell, allModels, isMaximized, isMinimized, canConfigureLayout, onConfigure, onMaximize, onMinimize, onResize, onMove }) => {
|
|
21108
21328
|
const { token } = antd.theme.useToken();
|
|
21109
21329
|
const model = findModelByName(allModels, cell.model);
|
|
21110
|
-
const cellRef =
|
|
21330
|
+
const cellRef = React6.useRef(null);
|
|
21111
21331
|
const cellStyle = {
|
|
21112
21332
|
position: "relative",
|
|
21113
21333
|
border: `1px solid ${token.colorBorderSecondary}`,
|
|
@@ -21136,11 +21356,13 @@ var DashboardGridCell = ({ cell, allModels, isMaximized, isMinimized, canConfigu
|
|
|
21136
21356
|
minHeight: 32,
|
|
21137
21357
|
position: "relative"
|
|
21138
21358
|
};
|
|
21359
|
+
const isPlotlyChart = cell.source_type === "plotly_chart";
|
|
21139
21360
|
const resource = model?.resource || cell.model;
|
|
21140
21361
|
const isModelLike = cell.source_type === "model" || cell.source_type === "named_query";
|
|
21141
|
-
const cellTitle = isModelLike ? model?.label || cell.model : cell.section_name || cell.model;
|
|
21362
|
+
const cellTitle = isPlotlyChart ? cell.chart_title || cell.model : isModelLike ? model?.label || cell.model : cell.section_name || cell.model;
|
|
21142
21363
|
const tone = isModelLike && model ? getModelTone(model) : null;
|
|
21143
|
-
const
|
|
21364
|
+
const [chartRefreshNonce, setChartRefreshNonce] = React6.useState(0);
|
|
21365
|
+
const startResize = React6.useCallback((e, dir) => {
|
|
21144
21366
|
e.preventDefault();
|
|
21145
21367
|
e.stopPropagation();
|
|
21146
21368
|
const el = cellRef.current;
|
|
@@ -21293,7 +21515,7 @@ var DashboardGridCell = ({ cell, allModels, isMaximized, isMinimized, canConfigu
|
|
|
21293
21515
|
) })
|
|
21294
21516
|
] })
|
|
21295
21517
|
] }),
|
|
21296
|
-
!isMinimized && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, overflow: "auto", minHeight: 0 }, children: model ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
21518
|
+
!isMinimized && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { flex: 1, overflow: "auto", minHeight: 0 }, children: isPlotlyChart && cell.chart_url ? /* @__PURE__ */ jsxRuntime.jsx(PlotlyChartContent, { chartUrl: cell.chart_url, refreshNonce: chartRefreshNonce }) : model ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
21297
21519
|
DynamicList,
|
|
21298
21520
|
{
|
|
21299
21521
|
model,
|
|
@@ -21316,11 +21538,11 @@ var DashboardGridCell = ({ cell, allModels, isMaximized, isMinimized, canConfigu
|
|
|
21316
21538
|
};
|
|
21317
21539
|
var DashboardTabContent = ({ tab, allModels, maximizedCellId, minimizedCellIds, canConfigureLayout, onMaximize, onMinimize, onConfigure, onResize, onMove }) => {
|
|
21318
21540
|
const cells = tab.cells;
|
|
21319
|
-
const numCols =
|
|
21541
|
+
const numCols = React6.useMemo(() => {
|
|
21320
21542
|
if (!cells.length) return 2;
|
|
21321
21543
|
return Math.max(...cells.map((c) => c.col)) + 1;
|
|
21322
21544
|
}, [cells]);
|
|
21323
|
-
const numRows =
|
|
21545
|
+
const numRows = React6.useMemo(() => {
|
|
21324
21546
|
if (!cells.length) return 1;
|
|
21325
21547
|
return Math.max(...cells.map((c) => c.row)) + 1;
|
|
21326
21548
|
}, [cells]);
|
|
@@ -21366,13 +21588,13 @@ var DashboardTabContent = ({ tab, allModels, maximizedCellId, minimizedCellIds,
|
|
|
21366
21588
|
var ViewsGrid = ({ config, allModels, onConfigChange }) => {
|
|
21367
21589
|
const { data: canLayoutData } = core.useCan({ resource: "veloiq_layout", action: "configure_layout" });
|
|
21368
21590
|
const canConfigureLayout = canLayoutData?.can !== false;
|
|
21369
|
-
const [maximizedCellId, setMaximizedCellId] =
|
|
21370
|
-
const [minimizedCellIds, setMinimizedCellIds] =
|
|
21371
|
-
const [drawerSelection, setDrawerSelection] =
|
|
21372
|
-
const handleMaximize =
|
|
21591
|
+
const [maximizedCellId, setMaximizedCellId] = React6.useState(null);
|
|
21592
|
+
const [minimizedCellIds, setMinimizedCellIds] = React6.useState(/* @__PURE__ */ new Set());
|
|
21593
|
+
const [drawerSelection, setDrawerSelection] = React6.useState(null);
|
|
21594
|
+
const handleMaximize = React6.useCallback((cellId) => {
|
|
21373
21595
|
setMaximizedCellId((prev) => prev === cellId ? null : cellId);
|
|
21374
21596
|
}, []);
|
|
21375
|
-
const handleMinimize =
|
|
21597
|
+
const handleMinimize = React6.useCallback((cellId) => {
|
|
21376
21598
|
setMinimizedCellIds((prev) => {
|
|
21377
21599
|
const next = new Set(prev);
|
|
21378
21600
|
if (next.has(cellId)) {
|
|
@@ -21383,14 +21605,14 @@ var ViewsGrid = ({ config, allModels, onConfigChange }) => {
|
|
|
21383
21605
|
return next;
|
|
21384
21606
|
});
|
|
21385
21607
|
}, []);
|
|
21386
|
-
const handleOpenDrawer =
|
|
21608
|
+
const handleOpenDrawer = React6.useCallback((tabId, cell) => {
|
|
21387
21609
|
setDrawerSelection({ tabId, cell });
|
|
21388
21610
|
}, []);
|
|
21389
|
-
const handleSaveConfig =
|
|
21611
|
+
const handleSaveConfig = React6.useCallback((nextConfig) => {
|
|
21390
21612
|
onConfigChange(nextConfig);
|
|
21391
21613
|
setDrawerSelection(null);
|
|
21392
21614
|
}, [onConfigChange]);
|
|
21393
|
-
const handleMoveCell =
|
|
21615
|
+
const handleMoveCell = React6.useCallback((tabId, cellId, direction) => {
|
|
21394
21616
|
const nextTabs = config.tabs.map((tab) => {
|
|
21395
21617
|
if (tab.id !== tabId) return tab;
|
|
21396
21618
|
const cell = tab.cells.find((c) => c.id === cellId);
|
|
@@ -21411,7 +21633,7 @@ var ViewsGrid = ({ config, allModels, onConfigChange }) => {
|
|
|
21411
21633
|
});
|
|
21412
21634
|
onConfigChange({ ...config, tabs: nextTabs });
|
|
21413
21635
|
}, [config, onConfigChange]);
|
|
21414
|
-
const handleResizeCell =
|
|
21636
|
+
const handleResizeCell = React6.useCallback((tabId, cellId, minWidth, minHeight) => {
|
|
21415
21637
|
const nextTabs = config.tabs.map((tab) => {
|
|
21416
21638
|
if (tab.id !== tabId) return tab;
|
|
21417
21639
|
return {
|
|
@@ -21428,7 +21650,7 @@ var ViewsGrid = ({ config, allModels, onConfigChange }) => {
|
|
|
21428
21650
|
});
|
|
21429
21651
|
onConfigChange({ ...config, tabs: nextTabs });
|
|
21430
21652
|
}, [config, onConfigChange]);
|
|
21431
|
-
const tabItems =
|
|
21653
|
+
const tabItems = React6.useMemo(
|
|
21432
21654
|
() => config.tabs.map((tab) => ({
|
|
21433
21655
|
key: tab.id,
|
|
21434
21656
|
label: tab.name,
|
|
@@ -21508,7 +21730,7 @@ function relativeTime3(iso) {
|
|
|
21508
21730
|
var RecentActivityPanel = () => {
|
|
21509
21731
|
const { token } = antd.theme.useToken();
|
|
21510
21732
|
const allModels = useAllModels();
|
|
21511
|
-
const [days, setDays] =
|
|
21733
|
+
const [days, setDays] = React6.useState(30);
|
|
21512
21734
|
const { data, loading, reload } = useRecentActivity(days);
|
|
21513
21735
|
const groups = data?.groups ?? [];
|
|
21514
21736
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "16px 0" }, children: [
|
|
@@ -21616,9 +21838,9 @@ var RecentActivityPanel = () => {
|
|
|
21616
21838
|
};
|
|
21617
21839
|
var { Text: AntText, Title: AntTitle } = antd.Typography;
|
|
21618
21840
|
function usePinnedRecords() {
|
|
21619
|
-
const [groups, setGroups] =
|
|
21620
|
-
const [loading, setLoading] =
|
|
21621
|
-
const load =
|
|
21841
|
+
const [groups, setGroups] = React6.useState([]);
|
|
21842
|
+
const [loading, setLoading] = React6.useState(true);
|
|
21843
|
+
const load = React6.useCallback(async () => {
|
|
21622
21844
|
setLoading(true);
|
|
21623
21845
|
try {
|
|
21624
21846
|
const res = await authenticatedFetch(`${API_URL3}/dashboard/pinned-records`);
|
|
@@ -21631,7 +21853,7 @@ function usePinnedRecords() {
|
|
|
21631
21853
|
setLoading(false);
|
|
21632
21854
|
}
|
|
21633
21855
|
}, []);
|
|
21634
|
-
|
|
21856
|
+
React6__default.default.useEffect(() => {
|
|
21635
21857
|
load();
|
|
21636
21858
|
}, [load]);
|
|
21637
21859
|
return { groups, loading, reload: load };
|
|
@@ -21640,9 +21862,9 @@ var PinnedRecordsPanel = () => {
|
|
|
21640
21862
|
const { token } = antd.theme.useToken();
|
|
21641
21863
|
const allModels = useAllModels();
|
|
21642
21864
|
const { groups, loading, reload } = usePinnedRecords();
|
|
21643
|
-
const [unpinning, setUnpinning] =
|
|
21865
|
+
const [unpinning, setUnpinning] = React6.useState(/* @__PURE__ */ new Set());
|
|
21644
21866
|
const visibleGroups = groups.filter((g) => findModelByName(allModels, g.resource));
|
|
21645
|
-
const handleUnpin =
|
|
21867
|
+
const handleUnpin = React6.useCallback(async (resource, recordId) => {
|
|
21646
21868
|
const key = `${resource}:${recordId}`;
|
|
21647
21869
|
setUnpinning((prev) => new Set(prev).add(key));
|
|
21648
21870
|
try {
|
|
@@ -21971,6 +22193,7 @@ var authSystemModels = [
|
|
|
21971
22193
|
|
|
21972
22194
|
exports.API_URL = API_URL3;
|
|
21973
22195
|
exports.AllModelsProvider = AllModelsProvider;
|
|
22196
|
+
exports.AuthenticatedImage = AuthenticatedImage;
|
|
21974
22197
|
exports.ColorModeContext = ColorModeContext;
|
|
21975
22198
|
exports.ColorModeContextProvider = ColorModeContextProvider;
|
|
21976
22199
|
exports.CommandCenterPortal = CommandCenterPortal;
|
|
@@ -22017,6 +22240,7 @@ exports.resolveIcon = resolveIcon;
|
|
|
22017
22240
|
exports.setColorSchemas = setColorSchemas;
|
|
22018
22241
|
exports.sortItemsByNavConfig = sortItemsByNavConfig;
|
|
22019
22242
|
exports.useAllModels = useAllModels;
|
|
22243
|
+
exports.useAuthenticatedFileUrl = useAuthenticatedFileUrl;
|
|
22020
22244
|
exports.useKeyboardShortcuts = useKeyboardShortcuts;
|
|
22021
22245
|
exports.useMetadataModal = useMetadataModal;
|
|
22022
22246
|
exports.useNavConfig = useNavConfig;
|