@openg2p/registry-widgets 1.1.2-dev.8 → 1.1.2
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/components/SectionRenderer.d.ts.map +1 -1
- package/dist/hooks/useBaseWidget.d.ts.map +1 -1
- package/dist/hooks/useGeoWidgetCascade.d.ts.map +1 -1
- package/dist/index.d.ts +35 -15
- package/dist/index.esm.js +313 -172
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +319 -170
- package/dist/index.js.map +1 -1
- package/dist/utils/geoHierarchy.d.ts +33 -0
- package/dist/utils/geoHierarchy.d.ts.map +1 -1
- package/dist/widgets/DialogTableWidget.d.ts +0 -13
- package/dist/widgets/DialogTableWidget.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.esm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createSlice, configureStore } from '@reduxjs/toolkit';
|
|
2
|
-
import React, { useContext, createContext, useMemo, useEffect, useRef, useCallback, useState, useId } from 'react';
|
|
2
|
+
import React, { useContext, createContext, useMemo, useEffect, useRef, useCallback, useState, useId, memo } from 'react';
|
|
3
3
|
import { Provider, useDispatch, useSelector, useStore } from 'react-redux';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import { createPortal } from 'react-dom';
|
|
@@ -2243,12 +2243,145 @@ const geoHierarchyBuilder = new GeoHierarchyBuilder();
|
|
|
2243
2243
|
/** Sentinel written to Redux when a geo level is cleared by cascade (distinct from "never set"). */
|
|
2244
2244
|
const GEO_LEVEL_CLEARED = null;
|
|
2245
2245
|
const geoWidgetParentRegistry = new Map();
|
|
2246
|
+
const geoWidgetConfigRegistry = new Map();
|
|
2246
2247
|
function registerGeoWidgetParent(widgetId, parentWidgetId) {
|
|
2247
2248
|
geoWidgetParentRegistry.set(widgetId, parentWidgetId || null);
|
|
2248
2249
|
}
|
|
2249
2250
|
function unregisterGeoWidgetParent(widgetId) {
|
|
2250
2251
|
geoWidgetParentRegistry.delete(widgetId);
|
|
2251
2252
|
}
|
|
2253
|
+
function registerGeoWidget(widgetId, geoConfig, dataPath) {
|
|
2254
|
+
if (typeof dataPath !== 'string') {
|
|
2255
|
+
return;
|
|
2256
|
+
}
|
|
2257
|
+
const parentWidgetId = geoConfig.parentWidgetId?.trim() ? geoConfig.parentWidgetId : null;
|
|
2258
|
+
registerGeoWidgetParent(widgetId, parentWidgetId);
|
|
2259
|
+
geoWidgetConfigRegistry.set(widgetId, {
|
|
2260
|
+
widgetId,
|
|
2261
|
+
parentWidgetId,
|
|
2262
|
+
level: geoConfig.level,
|
|
2263
|
+
geoConfig,
|
|
2264
|
+
dataPath,
|
|
2265
|
+
groupId: getGeoGroupId(dataPath),
|
|
2266
|
+
});
|
|
2267
|
+
}
|
|
2268
|
+
function unregisterGeoWidget(widgetId) {
|
|
2269
|
+
unregisterGeoWidgetParent(widgetId);
|
|
2270
|
+
geoWidgetConfigRegistry.delete(widgetId);
|
|
2271
|
+
}
|
|
2272
|
+
function orderGeoWidgetRegistrations(registrations) {
|
|
2273
|
+
if (registrations.length <= 1) {
|
|
2274
|
+
return registrations;
|
|
2275
|
+
}
|
|
2276
|
+
const roots = registrations.filter((entry) => !entry.parentWidgetId);
|
|
2277
|
+
if (roots.length === 0) {
|
|
2278
|
+
return registrations;
|
|
2279
|
+
}
|
|
2280
|
+
const ordered = [];
|
|
2281
|
+
let current = roots[0];
|
|
2282
|
+
const visited = new Set();
|
|
2283
|
+
while (current && !visited.has(current.widgetId)) {
|
|
2284
|
+
visited.add(current.widgetId);
|
|
2285
|
+
ordered.push(current);
|
|
2286
|
+
current = registrations.find((entry) => entry.parentWidgetId === current.widgetId);
|
|
2287
|
+
}
|
|
2288
|
+
return ordered.length > 0 ? ordered : registrations;
|
|
2289
|
+
}
|
|
2290
|
+
function resolveLevelValueId(rawValue) {
|
|
2291
|
+
if (rawValue === null || rawValue === undefined || rawValue === '') {
|
|
2292
|
+
return null;
|
|
2293
|
+
}
|
|
2294
|
+
if (typeof rawValue === 'string' || typeof rawValue === 'number') {
|
|
2295
|
+
return String(rawValue);
|
|
2296
|
+
}
|
|
2297
|
+
if (typeof rawValue === 'object') {
|
|
2298
|
+
const id = rawValue.level_value_id || rawValue.id || rawValue.value;
|
|
2299
|
+
return id != null && id !== '' ? String(id) : null;
|
|
2300
|
+
}
|
|
2301
|
+
return null;
|
|
2302
|
+
}
|
|
2303
|
+
function resolveStoredMnemonic(values, registration, valueId) {
|
|
2304
|
+
const stored = getWidgetValue(values, registration.dataPath, registration.widgetId);
|
|
2305
|
+
const hierarchy = stored?.hierarchy || stored?.geo_code_hierarchy_json?.hierarchy;
|
|
2306
|
+
if (!Array.isArray(hierarchy)) {
|
|
2307
|
+
return undefined;
|
|
2308
|
+
}
|
|
2309
|
+
const levelData = hierarchy.find((entry) => entry.level === registration.level);
|
|
2310
|
+
if (levelData && String(levelData.level_value_id) === String(valueId)) {
|
|
2311
|
+
return levelData.level_value_mnemonic ? String(levelData.level_value_mnemonic) : undefined;
|
|
2312
|
+
}
|
|
2313
|
+
return undefined;
|
|
2314
|
+
}
|
|
2315
|
+
/** Resolve display mnemonic from cached dropdown options, then stored hierarchy. */
|
|
2316
|
+
function createGeoLevelMnemonicResolver(values, dataSources) {
|
|
2317
|
+
return (registration, valueId) => {
|
|
2318
|
+
const options = dataSources[registration.widgetId];
|
|
2319
|
+
const option = options?.find((entry) => String(entry.value) === String(valueId));
|
|
2320
|
+
if (option?.label) {
|
|
2321
|
+
return option.label;
|
|
2322
|
+
}
|
|
2323
|
+
return resolveStoredMnemonic(values, registration, valueId);
|
|
2324
|
+
};
|
|
2325
|
+
}
|
|
2326
|
+
/** Rebuild group hierarchy from widget values in parent→child order; stop at first missing level. */
|
|
2327
|
+
function rebuildGeoHierarchyFromRegistrations(groupId, values, registrations, resolveMnemonic) {
|
|
2328
|
+
const ordered = orderGeoWidgetRegistrations(registrations.filter((entry) => entry.groupId === groupId));
|
|
2329
|
+
geoHierarchyBuilder.clear(groupId);
|
|
2330
|
+
for (const registration of ordered) {
|
|
2331
|
+
const rawValue = resolveGeoWidgetLevelValue(values, registration.widgetId, registration.dataPath, registration.geoConfig);
|
|
2332
|
+
const valueId = resolveLevelValueId(rawValue);
|
|
2333
|
+
if (!valueId) {
|
|
2334
|
+
break;
|
|
2335
|
+
}
|
|
2336
|
+
const mnemonic = resolveMnemonic?.(registration, valueId) ??
|
|
2337
|
+
resolveStoredMnemonic(values, registration, valueId) ??
|
|
2338
|
+
valueId;
|
|
2339
|
+
geoHierarchyBuilder.addLevel(registration.level, valueId, mnemonic, groupId);
|
|
2340
|
+
}
|
|
2341
|
+
return geoHierarchyBuilder.buildHierarchyJson(groupId) !== null;
|
|
2342
|
+
}
|
|
2343
|
+
function collectGeoWidgetRegistrationsFromWidgets(widgets, namespace) {
|
|
2344
|
+
return widgets
|
|
2345
|
+
.filter((widget) => widget['widget-geo-config'] && typeof widget['widget-data-path'] === 'string')
|
|
2346
|
+
.map((widget) => {
|
|
2347
|
+
const originalWidgetId = widget['widget-id'];
|
|
2348
|
+
const originalDataPath = widget['widget-data-path'];
|
|
2349
|
+
const geoConfig = widget['widget-geo-config'];
|
|
2350
|
+
const widgetId = namespace ? `${namespace}__${originalWidgetId}` : originalWidgetId;
|
|
2351
|
+
const parentWidgetId = geoConfig.parentWidgetId?.trim()
|
|
2352
|
+
? (namespace ? `${namespace}__${geoConfig.parentWidgetId}` : geoConfig.parentWidgetId)
|
|
2353
|
+
: null;
|
|
2354
|
+
const dataPath = namespace ? `${namespace}.${originalDataPath}` : originalDataPath;
|
|
2355
|
+
return {
|
|
2356
|
+
widgetId,
|
|
2357
|
+
parentWidgetId,
|
|
2358
|
+
level: geoConfig.level,
|
|
2359
|
+
geoConfig,
|
|
2360
|
+
dataPath,
|
|
2361
|
+
groupId: getGeoGroupId(dataPath),
|
|
2362
|
+
};
|
|
2363
|
+
});
|
|
2364
|
+
}
|
|
2365
|
+
/** Reconcile all geo groups in section values before save. */
|
|
2366
|
+
function reconcileGeoHierarchiesInValues(values, registrations, dataSources = {}) {
|
|
2367
|
+
const groupIds = [...new Set(registrations.map((entry) => entry.groupId))];
|
|
2368
|
+
let updatedValues = values;
|
|
2369
|
+
const resolveMnemonic = createGeoLevelMnemonicResolver(updatedValues, dataSources);
|
|
2370
|
+
for (const groupId of groupIds) {
|
|
2371
|
+
const groupRegistrations = registrations.filter((entry) => entry.groupId === groupId);
|
|
2372
|
+
const dataPath = groupRegistrations[0]?.dataPath;
|
|
2373
|
+
const widgetId = groupRegistrations[0]?.widgetId;
|
|
2374
|
+
if (!dataPath || !widgetId) {
|
|
2375
|
+
continue;
|
|
2376
|
+
}
|
|
2377
|
+
rebuildGeoHierarchyFromRegistrations(groupId, updatedValues, groupRegistrations, resolveMnemonic);
|
|
2378
|
+
updatedValues = applySharedGeoHierarchyToValues(updatedValues, groupId, dataPath, widgetId);
|
|
2379
|
+
}
|
|
2380
|
+
return updatedValues;
|
|
2381
|
+
}
|
|
2382
|
+
function getGeoWidgetRegistrationsInGroup(groupId) {
|
|
2383
|
+
return orderGeoWidgetRegistrations([...geoWidgetConfigRegistry.values()].filter((entry) => entry.groupId === groupId));
|
|
2384
|
+
}
|
|
2252
2385
|
/** True when changedWidgetId is any upstream geo parent of widgetId (not only immediate parent). */
|
|
2253
2386
|
function isUpstreamGeoAncestor(changedWidgetId, widgetId, immediateParentWidgetId) {
|
|
2254
2387
|
if (changedWidgetId === widgetId) {
|
|
@@ -2343,7 +2476,7 @@ function resetAndSeedGeoHierarchyFromValues(values, dataPath, widgetId, groupId)
|
|
|
2343
2476
|
|
|
2344
2477
|
// Define stable empty arrays to avoid selector reference issues
|
|
2345
2478
|
const EMPTY_ERRORS = [];
|
|
2346
|
-
const EMPTY_DATA_SOURCE
|
|
2479
|
+
const EMPTY_DATA_SOURCE = [];
|
|
2347
2480
|
const useBaseWidget = (options) => {
|
|
2348
2481
|
const { config, dataSourceRequestHandler: propHandler, schemaData, onValueChange } = options;
|
|
2349
2482
|
const dispatch = useDispatch();
|
|
@@ -2358,7 +2491,7 @@ const useBaseWidget = (options) => {
|
|
|
2358
2491
|
const errors = useSelector((state) => state.widget.errors[widgetId] ?? EMPTY_ERRORS);
|
|
2359
2492
|
const touched = useSelector((state) => state.widget.touched[widgetId] || false);
|
|
2360
2493
|
const loading = useSelector((state) => state.widget.loading[widgetId] || false);
|
|
2361
|
-
const dataSourceOptions = useSelector((state) => state.widget.dataSources[widgetId] ?? EMPTY_DATA_SOURCE
|
|
2494
|
+
const dataSourceOptions = useSelector((state) => state.widget.dataSources[widgetId] ?? EMPTY_DATA_SOURCE);
|
|
2362
2495
|
// Skip value handling for layout widgets (they don't store data values)
|
|
2363
2496
|
// Infer layout from widget-type
|
|
2364
2497
|
const isLayoutWidget = config['widget-type'] === 'layout';
|
|
@@ -2680,6 +2813,8 @@ const useBaseWidget = (options) => {
|
|
|
2680
2813
|
const apiService = dataSource?.type === 'api' ? dataSource.service : '';
|
|
2681
2814
|
const apiEndpoint = dataSource?.type === 'api' ? dataSource.endpoint : '';
|
|
2682
2815
|
const configKey = `${widgetId}-${isReadonly}-${dataSource?.type || 'none'}-${apiService}-${apiEndpoint}`;
|
|
2816
|
+
// Stable key so inline schemaData objects (e.g. dialog-table fields) don't retrigger loads every render
|
|
2817
|
+
const schemaDataKey = useMemo(() => (schemaData ? JSON.stringify(schemaData) : ''), [schemaData]);
|
|
2683
2818
|
// Extract dependency value using a granular selector to prevent unnecessary re-renders
|
|
2684
2819
|
// and infinite loops when other unrelated values in the state change.
|
|
2685
2820
|
const dependencyValue = useSelector((state) => {
|
|
@@ -2797,7 +2932,7 @@ const useBaseWidget = (options) => {
|
|
|
2797
2932
|
loadDataSource();
|
|
2798
2933
|
// Use configKey and dependencyValue to ensure effect runs only when relevant state changes
|
|
2799
2934
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2800
|
-
}, [configKey, dependencyValue, dataSourceRequestHandler,
|
|
2935
|
+
}, [configKey, dependencyValue, dataSourceRequestHandler, schemaDataKey, widgetId, dispatch]);
|
|
2801
2936
|
const geoDisplayLabel = useMemo(() => {
|
|
2802
2937
|
if (!geoConfig) {
|
|
2803
2938
|
return undefined;
|
|
@@ -2886,8 +3021,6 @@ const useWidgetCascade = (options) => {
|
|
|
2886
3021
|
}, [cascadeConfig, eventBus, dataSource, widgetId, dispatch]);
|
|
2887
3022
|
};
|
|
2888
3023
|
|
|
2889
|
-
// Define stable empty array to avoid selector reference issues
|
|
2890
|
-
const EMPTY_DATA_SOURCE = [];
|
|
2891
3024
|
/**
|
|
2892
3025
|
* Hook for geo widget cascade functionality
|
|
2893
3026
|
* Handles geo hierarchy building and cascade behavior
|
|
@@ -2917,15 +3050,15 @@ const useGeoWidgetCascade = (options) => {
|
|
|
2917
3050
|
? resolveGeoWidgetLevelValue(state.widget.values, widgetId, dataPath, geoConfig)
|
|
2918
3051
|
: state.widget.values[widgetId]);
|
|
2919
3052
|
// Memoize selector to avoid returning new array reference
|
|
2920
|
-
const
|
|
3053
|
+
const allDataSources = useSelector((state) => state.widget.dataSources);
|
|
2921
3054
|
// Register parent chain for upstream-ancestor detection (grandparent → grandchild reset)
|
|
2922
3055
|
useEffect(() => {
|
|
2923
|
-
if (!geoConfig) {
|
|
3056
|
+
if (!geoConfig || typeof dataPath !== 'string') {
|
|
2924
3057
|
return;
|
|
2925
3058
|
}
|
|
2926
|
-
|
|
2927
|
-
return () =>
|
|
2928
|
-
}, [widgetId, geoConfig]);
|
|
3059
|
+
registerGeoWidget(widgetId, geoConfig, dataPath);
|
|
3060
|
+
return () => unregisterGeoWidget(widgetId);
|
|
3061
|
+
}, [widgetId, geoConfig, dataPath]);
|
|
2929
3062
|
// Keep in-memory builder in sync with persisted hierarchy (reload, cancel→re-edit, etc.)
|
|
2930
3063
|
useEffect(() => {
|
|
2931
3064
|
if (!geoConfig || typeof dataPath !== 'string') {
|
|
@@ -3017,18 +3150,20 @@ const useGeoWidgetCascade = (options) => {
|
|
|
3017
3150
|
}, [geoConfig, eventBus, dataSource, widgetId, dataPath, dispatch, groupId]);
|
|
3018
3151
|
// Handle value changes to build hierarchy
|
|
3019
3152
|
useEffect(() => {
|
|
3020
|
-
if (!geoConfig) {
|
|
3153
|
+
if (!geoConfig || typeof dataPath !== 'string') {
|
|
3021
3154
|
return;
|
|
3022
3155
|
}
|
|
3023
|
-
|
|
3156
|
+
const { level, isLastLevel } = geoConfig;
|
|
3157
|
+
const groupRegistrations = getGeoWidgetRegistrationsInGroup(groupId);
|
|
3158
|
+
const applyGroupRebuild = () => {
|
|
3159
|
+
const resolveMnemonic = createGeoLevelMnemonicResolver(valuesRef.current, allDataSources);
|
|
3160
|
+
rebuildGeoHierarchyFromRegistrations(groupId, valuesRef.current, groupRegistrations, resolveMnemonic);
|
|
3161
|
+
dispatch(setValues(applySharedGeoHierarchyToValues(valuesRef.current, groupId, dataPath, widgetId)));
|
|
3162
|
+
};
|
|
3024
3163
|
// ONLY clear hierarchy if the value is explicitly null or empty string (user action)
|
|
3025
3164
|
if (currentValue === null || currentValue === '') {
|
|
3026
|
-
const { level, isLastLevel } = geoConfig;
|
|
3027
3165
|
geoHierarchyBuilder.removeLevelAndBelow(level, groupId);
|
|
3028
|
-
|
|
3029
|
-
if (dataPath) {
|
|
3030
|
-
dispatch(setValues(applySharedGeoHierarchyToValues(valuesRef.current, groupId, dataPath, widgetId)));
|
|
3031
|
-
}
|
|
3166
|
+
applyGroupRebuild();
|
|
3032
3167
|
if (!isLastLevel && eventBus && lastCascadePublishRef.current !== GEO_LEVEL_CLEARED) {
|
|
3033
3168
|
lastCascadePublishRef.current = GEO_LEVEL_CLEARED;
|
|
3034
3169
|
eventBus.publish({
|
|
@@ -3041,56 +3176,13 @@ const useGeoWidgetCascade = (options) => {
|
|
|
3041
3176
|
return;
|
|
3042
3177
|
}
|
|
3043
3178
|
if (currentValue === undefined) {
|
|
3044
|
-
|
|
3045
|
-
|
|
3046
|
-
|
|
3047
|
-
// Check if hierarchy is already built to prevent endless loops
|
|
3048
|
-
if (dataPath) {
|
|
3049
|
-
const currentHierarchy = getWidgetValue(valuesRef.current, dataPath, widgetId);
|
|
3050
|
-
// If hierarchy JSON is already set and matches current value, skip rebuilding
|
|
3051
|
-
if (currentHierarchy && typeof currentHierarchy === 'object') {
|
|
3052
|
-
// Check if this specific level's value matches the hierarchy
|
|
3053
|
-
const hierarchyArray = currentHierarchy.hierarchy || currentHierarchy.geo_code_hierarchy_json?.hierarchy;
|
|
3054
|
-
if (Array.isArray(hierarchyArray)) {
|
|
3055
|
-
const currentLevelValue = typeof currentValue === 'object'
|
|
3056
|
-
? (currentValue.level_value_id || currentValue.id || currentValue.value)
|
|
3057
|
-
: currentValue;
|
|
3058
|
-
const levelData = hierarchyArray.find((l) => l.level === geoConfig.level);
|
|
3059
|
-
// If this level is already correctly represented in the hierarchy, skip rebuilding
|
|
3060
|
-
// String conversion ensures comparison works for mixed types
|
|
3061
|
-
if (levelData && String(levelData.level_value_id) === String(currentLevelValue)) {
|
|
3062
|
-
return;
|
|
3063
|
-
}
|
|
3064
|
-
}
|
|
3179
|
+
const hasOwnValue = Object.prototype.hasOwnProperty.call(valuesRef.current, widgetId);
|
|
3180
|
+
if (!hasOwnValue) {
|
|
3181
|
+
return;
|
|
3065
3182
|
}
|
|
3066
3183
|
}
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
let level_value_id;
|
|
3070
|
-
let level_value_mnemonic;
|
|
3071
|
-
if (typeof currentValue === 'string' || typeof currentValue === 'number') {
|
|
3072
|
-
// Value is just the ID, need to find mnemonic from data source
|
|
3073
|
-
level_value_id = String(currentValue);
|
|
3074
|
-
// Try to get mnemonic from data source options
|
|
3075
|
-
const option = dataSourceOptions.find((opt) => opt.value === currentValue);
|
|
3076
|
-
level_value_mnemonic = option?.label || String(currentValue);
|
|
3077
|
-
}
|
|
3078
|
-
else if (currentValue && typeof currentValue === 'object') {
|
|
3079
|
-
level_value_id = currentValue.level_value_id || currentValue.id || currentValue.value;
|
|
3080
|
-
level_value_mnemonic = currentValue.level_value_mnemonic || currentValue.name || currentValue.label;
|
|
3081
|
-
}
|
|
3082
|
-
else {
|
|
3083
|
-
return;
|
|
3084
|
-
}
|
|
3085
|
-
// When a widget's own value changes, remove this level and all below from hierarchy first
|
|
3086
|
-
geoHierarchyBuilder.removeLevelAndBelow(level, groupId);
|
|
3087
|
-
// Add level to hierarchy
|
|
3088
|
-
geoHierarchyBuilder.addLevel(level, level_value_id, level_value_mnemonic, groupId);
|
|
3089
|
-
// Build and store hierarchy JSON on every change
|
|
3090
|
-
if (dataPath && geoHierarchyBuilder.buildHierarchyJson(groupId)) {
|
|
3091
|
-
dispatch(setValues(applySharedGeoHierarchyToValues(valuesRef.current, groupId, dataPath, widgetId)));
|
|
3092
|
-
}
|
|
3093
|
-
}, [geoConfig, currentValue, widgetId, dataPath, dispatch, dataSourceOptions, groupId]);
|
|
3184
|
+
applyGroupRebuild();
|
|
3185
|
+
}, [geoConfig, currentValue, widgetId, dataPath, dispatch, allDataSources, groupId, eventBus]);
|
|
3094
3186
|
};
|
|
3095
3187
|
|
|
3096
3188
|
class WidgetRegistry {
|
|
@@ -4992,7 +5084,12 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4992
5084
|
// This ensures we use the original widget IDs and data paths
|
|
4993
5085
|
const sectionWidgets = collectWidgets(originalSection.panels);
|
|
4994
5086
|
const currentState = store.getState().widget;
|
|
4995
|
-
|
|
5087
|
+
let currentSchemaData = currentState.values || {};
|
|
5088
|
+
const geoRegistrations = collectGeoWidgetRegistrationsFromWidgets(sectionWidgets, namespace);
|
|
5089
|
+
if (geoRegistrations.length > 0) {
|
|
5090
|
+
currentSchemaData = reconcileGeoHierarchiesInValues(currentSchemaData, geoRegistrations, currentState.dataSources || {});
|
|
5091
|
+
dispatch(setValues(currentSchemaData));
|
|
5092
|
+
}
|
|
4996
5093
|
const isSectionValid = sectionValidate(originalSection, currentSchemaData, dispatch, true);
|
|
4997
5094
|
if (!isSectionValid) {
|
|
4998
5095
|
return;
|
|
@@ -5058,7 +5155,12 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
5058
5155
|
if (isDraft !== false && store && onSectionSave) {
|
|
5059
5156
|
const sectionWidgets = collectWidgets(originalSection.panels);
|
|
5060
5157
|
const currentState = store.getState().widget;
|
|
5061
|
-
|
|
5158
|
+
let currentSchemaData = currentState.values || {};
|
|
5159
|
+
const geoRegistrations = collectGeoWidgetRegistrationsFromWidgets(sectionWidgets, namespace);
|
|
5160
|
+
if (geoRegistrations.length > 0) {
|
|
5161
|
+
currentSchemaData = reconcileGeoHierarchiesInValues(currentSchemaData, geoRegistrations, currentState.dataSources || {});
|
|
5162
|
+
dispatch(setValues(currentSchemaData));
|
|
5163
|
+
}
|
|
5062
5164
|
const isSectionValid = sectionValidate(originalSection, currentSchemaData, dispatch, true);
|
|
5063
5165
|
if (!isSectionValid)
|
|
5064
5166
|
return;
|
|
@@ -9986,6 +10088,22 @@ const TableWidget = ({ config }) => {
|
|
|
9986
10088
|
};
|
|
9987
10089
|
|
|
9988
10090
|
const isUnsetRowValue = (value) => value === null || value === undefined || value === '';
|
|
10091
|
+
/** Match TableWidget cell styling for add / update / delete rows */
|
|
10092
|
+
const getRowCellStyle = (editAction) => {
|
|
10093
|
+
if (editAction === 'ADD') {
|
|
10094
|
+
return { color: 'var(--owt-color-success, #16A34A)' };
|
|
10095
|
+
}
|
|
10096
|
+
if (editAction === 'DELETE') {
|
|
10097
|
+
return {
|
|
10098
|
+
color: 'var(--owt-color-error, #B91C1C)',
|
|
10099
|
+
textDecoration: 'line-through',
|
|
10100
|
+
};
|
|
10101
|
+
}
|
|
10102
|
+
if (editAction === 'UPDATE') {
|
|
10103
|
+
return { color: 'var(--owt-color-warning, #F59E0B)' };
|
|
10104
|
+
}
|
|
10105
|
+
return {};
|
|
10106
|
+
};
|
|
9989
10107
|
// Display select value label in view mode
|
|
9990
10108
|
const SelectDisplayValue = ({ config, value }) => {
|
|
9991
10109
|
const { dataSourceOptions, loading } = useBaseWidget({ config });
|
|
@@ -9996,23 +10114,29 @@ const SelectDisplayValue = ({ config, value }) => {
|
|
|
9996
10114
|
const selectedOption = dataSourceOptions.find((option) => option.value === value || String(option.value) === String(value));
|
|
9997
10115
|
return jsxRuntimeExports.jsx("span", { children: selectedOption ? selectedOption.label : String(value) });
|
|
9998
10116
|
};
|
|
10117
|
+
/** Isolated dialog field — avoids re-running data-source effects when sibling fields update. */
|
|
10118
|
+
const DialogTableField = memo(function DialogTableField({ col, cellWidgetId, dialogRowValues, isReadonly, }) {
|
|
10119
|
+
const widgetType = col.widget || 'text';
|
|
10120
|
+
const fieldConfig = useMemo(() => {
|
|
10121
|
+
return {
|
|
10122
|
+
...col,
|
|
10123
|
+
widget: widgetType,
|
|
10124
|
+
'widget-type': col['widget-type'] || 'input',
|
|
10125
|
+
'widget-id': cellWidgetId,
|
|
10126
|
+
'widget-label': col['widget-label'],
|
|
10127
|
+
'widget-readonly': isReadonly || col['widget-readonly'] === true,
|
|
10128
|
+
'widget-data-path': undefined,
|
|
10129
|
+
'widget-data-default': col['widget-data-default'],
|
|
10130
|
+
'widget-data-options': undefined,
|
|
10131
|
+
'widget-required': shouldRequireWidget(col['widget-data-options'], dialogRowValues, col['widget-required']),
|
|
10132
|
+
};
|
|
10133
|
+
}, [col, cellWidgetId, dialogRowValues, isReadonly, widgetType]);
|
|
10134
|
+
return (jsxRuntimeExports.jsx("div", { className: "min-w-0", children: jsxRuntimeExports.jsx(WidgetRenderer, { config: fieldConfig }) }));
|
|
10135
|
+
});
|
|
9999
10136
|
/**
|
|
10000
10137
|
* Dialog table widget:
|
|
10001
10138
|
* - Table displays a subset of columns (n out of x)
|
|
10002
10139
|
* - Add/Edit happens in a modal dialog that shows ALL columns as a form
|
|
10003
|
-
*
|
|
10004
|
-
* Usage in schema:
|
|
10005
|
-
* {
|
|
10006
|
-
* "widget": "dialog-table",
|
|
10007
|
-
* "widget-type": "table",
|
|
10008
|
-
* "widget-label": "Household Members",
|
|
10009
|
-
* "widget-id": "householdMembers",
|
|
10010
|
-
* "widget-data-path": "household.members",
|
|
10011
|
-
* "widget-data-columns": [ ...all columns... ],
|
|
10012
|
-
* "widget-data-visible-columns": ["firstName", "lastName", "dob"], // optional override; default = by column flag
|
|
10013
|
-
* // Per-column control (recommended): set "column-visible-in-table": false to hide it in the table
|
|
10014
|
-
* "widget-data-operations": { "add": true, "edit": true, "remove": true }
|
|
10015
|
-
* }
|
|
10016
10140
|
*/
|
|
10017
10141
|
const DialogTableWidget = ({ config }) => {
|
|
10018
10142
|
const { value, error, touched, isEnabled, onChange, config: widgetConfig } = useBaseWidget({ config });
|
|
@@ -10022,23 +10146,22 @@ const DialogTableWidget = ({ config }) => {
|
|
|
10022
10146
|
const columns = widgetConfig['widget-data-columns'] || [];
|
|
10023
10147
|
const operations = widgetConfig['widget-data-operations'] || {};
|
|
10024
10148
|
const isReadonly = widgetConfig['widget-readonly'] || false;
|
|
10149
|
+
// Soft-delete (keep row, red + strikethrough) whenever remove is allowed — matches TableWidget
|
|
10150
|
+
const shouldSoftDeleteOnRemove = !isReadonly && !!operations.remove;
|
|
10025
10151
|
const visibleColumnKeys = widgetConfig['widget-data-visible-columns'];
|
|
10026
10152
|
const visibleColumns = useMemo(() => {
|
|
10027
|
-
// 1) If explicit list provided, it wins
|
|
10028
10153
|
if (Array.isArray(visibleColumnKeys) && visibleColumnKeys.length > 0) {
|
|
10029
10154
|
const keySet = new Set(visibleColumnKeys);
|
|
10030
10155
|
return columns.filter((c) => keySet.has(c['column-key']));
|
|
10031
10156
|
}
|
|
10032
|
-
// 2) Otherwise decide per column (default = visible)
|
|
10033
10157
|
return columns.filter((c) => c['column-visible-in-table'] !== false);
|
|
10034
10158
|
}, [columns, visibleColumnKeys]);
|
|
10035
10159
|
const [dialogOpen, setDialogOpen] = useState(false);
|
|
10036
10160
|
const [dialogMode, setDialogMode] = useState('add');
|
|
10037
10161
|
const [activeRowIndex, setActiveRowIndex] = useState(null);
|
|
10038
|
-
const [formData, setFormData] = useState({});
|
|
10039
|
-
/** Unique per dialog open so Redux widget ids don't reuse stale values across rows/add sessions */
|
|
10040
10162
|
const dialogSessionRef = useRef(0);
|
|
10041
10163
|
const [dialogSessionId, setDialogSessionId] = useState(0);
|
|
10164
|
+
const membersWidgetId = widgetConfig['widget-id'];
|
|
10042
10165
|
const addDialogTitle = translateConfig(widgetConfig['widget-data-dialog-title-add']) ||
|
|
10043
10166
|
translate('table.addRecordDialog') ||
|
|
10044
10167
|
'Add record';
|
|
@@ -10058,15 +10181,26 @@ const DialogTableWidget = ({ config }) => {
|
|
|
10058
10181
|
});
|
|
10059
10182
|
return emptyRow;
|
|
10060
10183
|
}, [columns]);
|
|
10061
|
-
const dialogFieldWidgetId = useCallback((columnKey) => `${
|
|
10184
|
+
const dialogFieldWidgetId = useCallback((sessionId, columnKey) => `${membersWidgetId}-dlg-${sessionId}-${columnKey}`, [membersWidgetId]);
|
|
10062
10185
|
const resetDialogWidgets = useCallback((sessionId) => {
|
|
10063
10186
|
if (sessionId <= 0)
|
|
10064
10187
|
return;
|
|
10065
10188
|
columns.forEach((col) => {
|
|
10066
|
-
|
|
10067
|
-
|
|
10189
|
+
dispatch(resetWidget(dialogFieldWidgetId(sessionId, col['column-key'])));
|
|
10190
|
+
});
|
|
10191
|
+
}, [columns, dialogFieldWidgetId, dispatch]);
|
|
10192
|
+
const seedDialogReduxValues = useCallback((sessionId, rowData) => {
|
|
10193
|
+
const seeds = {};
|
|
10194
|
+
columns.forEach((col) => {
|
|
10195
|
+
const key = col['column-key'];
|
|
10196
|
+
if (rowData[key] !== undefined) {
|
|
10197
|
+
seeds[dialogFieldWidgetId(sessionId, key)] = rowData[key];
|
|
10198
|
+
}
|
|
10068
10199
|
});
|
|
10069
|
-
|
|
10200
|
+
if (Object.keys(seeds).length > 0) {
|
|
10201
|
+
dispatch(setValues(seeds));
|
|
10202
|
+
}
|
|
10203
|
+
}, [columns, dialogFieldWidgetId, dispatch]);
|
|
10070
10204
|
const beginDialogSession = useCallback(() => {
|
|
10071
10205
|
dialogSessionRef.current += 1;
|
|
10072
10206
|
const nextSession = dialogSessionRef.current;
|
|
@@ -10075,15 +10209,21 @@ const DialogTableWidget = ({ config }) => {
|
|
|
10075
10209
|
}, []);
|
|
10076
10210
|
const openAddDialog = useCallback(() => {
|
|
10077
10211
|
resetDialogWidgets(dialogSessionId);
|
|
10078
|
-
beginDialogSession();
|
|
10212
|
+
const sessionId = beginDialogSession();
|
|
10213
|
+
seedDialogReduxValues(sessionId, buildEmptyRow());
|
|
10079
10214
|
setDialogMode('add');
|
|
10080
10215
|
setActiveRowIndex(null);
|
|
10081
|
-
setFormData(buildEmptyRow());
|
|
10082
10216
|
setDialogOpen(true);
|
|
10083
|
-
}, [
|
|
10217
|
+
}, [
|
|
10218
|
+
buildEmptyRow,
|
|
10219
|
+
beginDialogSession,
|
|
10220
|
+
resetDialogWidgets,
|
|
10221
|
+
dialogSessionId,
|
|
10222
|
+
seedDialogReduxValues,
|
|
10223
|
+
]);
|
|
10084
10224
|
const openEditDialog = useCallback((rowIndex) => {
|
|
10085
10225
|
resetDialogWidgets(dialogSessionId);
|
|
10086
|
-
beginDialogSession();
|
|
10226
|
+
const sessionId = beginDialogSession();
|
|
10087
10227
|
const row = rows[rowIndex] || {};
|
|
10088
10228
|
const nextFormData = buildEmptyRow();
|
|
10089
10229
|
columns.forEach((col) => {
|
|
@@ -10091,23 +10231,26 @@ const DialogTableWidget = ({ config }) => {
|
|
|
10091
10231
|
if (row[key] !== undefined)
|
|
10092
10232
|
nextFormData[key] = row[key];
|
|
10093
10233
|
});
|
|
10234
|
+
seedDialogReduxValues(sessionId, nextFormData);
|
|
10094
10235
|
setDialogMode('edit');
|
|
10095
10236
|
setActiveRowIndex(rowIndex);
|
|
10096
|
-
setFormData(nextFormData);
|
|
10097
10237
|
setDialogOpen(true);
|
|
10098
|
-
}, [
|
|
10238
|
+
}, [
|
|
10239
|
+
rows,
|
|
10240
|
+
columns,
|
|
10241
|
+
buildEmptyRow,
|
|
10242
|
+
resetDialogWidgets,
|
|
10243
|
+
dialogSessionId,
|
|
10244
|
+
beginDialogSession,
|
|
10245
|
+
seedDialogReduxValues,
|
|
10246
|
+
]);
|
|
10099
10247
|
const closeDialog = useCallback(() => {
|
|
10100
10248
|
const sessionToClear = dialogSessionId;
|
|
10101
10249
|
setDialogOpen(false);
|
|
10102
10250
|
setActiveRowIndex(null);
|
|
10103
|
-
setFormData({});
|
|
10104
10251
|
resetDialogWidgets(sessionToClear);
|
|
10105
10252
|
setDialogSessionId(0);
|
|
10106
10253
|
}, [dialogSessionId, resetDialogWidgets]);
|
|
10107
|
-
const updateField = useCallback((columnKey, newValue) => {
|
|
10108
|
-
setFormData((prev) => ({ ...prev, [columnKey]: newValue }));
|
|
10109
|
-
}, []);
|
|
10110
|
-
const membersWidgetId = widgetConfig['widget-id'];
|
|
10111
10254
|
const dialogStoreValues = useSelector((state) => {
|
|
10112
10255
|
if (dialogSessionId <= 0) {
|
|
10113
10256
|
return {};
|
|
@@ -10116,25 +10259,15 @@ const DialogTableWidget = ({ config }) => {
|
|
|
10116
10259
|
const row = {};
|
|
10117
10260
|
columns.forEach((col) => {
|
|
10118
10261
|
const k = col['column-key'];
|
|
10119
|
-
const wid =
|
|
10262
|
+
const wid = dialogFieldWidgetId(dialogSessionId, k);
|
|
10120
10263
|
if (values[wid] !== undefined) {
|
|
10121
10264
|
row[k] = values[wid];
|
|
10122
10265
|
}
|
|
10123
10266
|
});
|
|
10124
10267
|
return row;
|
|
10125
|
-
}
|
|
10126
|
-
const
|
|
10127
|
-
|
|
10128
|
-
columns.forEach((col) => {
|
|
10129
|
-
const k = col['column-key'];
|
|
10130
|
-
if (storeSlice[k] !== undefined) {
|
|
10131
|
-
row[k] = storeSlice[k];
|
|
10132
|
-
}
|
|
10133
|
-
});
|
|
10134
|
-
return row;
|
|
10135
|
-
}, [formData, columns]);
|
|
10136
|
-
const dialogRowValues = useMemo(() => buildDialogRowValues(dialogStoreValues), [buildDialogRowValues, dialogStoreValues]);
|
|
10137
|
-
const collectMergedRowPayload = useCallback(() => buildDialogRowValues(dialogStoreValues), [buildDialogRowValues, dialogStoreValues]);
|
|
10268
|
+
});
|
|
10269
|
+
const dialogRowValues = dialogStoreValues;
|
|
10270
|
+
const collectMergedRowPayload = useCallback(() => dialogStoreValues, [dialogStoreValues]);
|
|
10138
10271
|
const finalizeDialogRowPayload = useCallback((raw) => {
|
|
10139
10272
|
const result = {};
|
|
10140
10273
|
columns.forEach((col) => {
|
|
@@ -10154,7 +10287,7 @@ const DialogTableWidget = ({ config }) => {
|
|
|
10154
10287
|
let hasErrors = false;
|
|
10155
10288
|
columns.forEach((col) => {
|
|
10156
10289
|
const key = col['column-key'];
|
|
10157
|
-
const cellWidgetId = dialogFieldWidgetId(key);
|
|
10290
|
+
const cellWidgetId = dialogFieldWidgetId(dialogSessionId, key);
|
|
10158
10291
|
const isColReadonly = isReadonly || col['widget-readonly'] === true;
|
|
10159
10292
|
if (isColReadonly)
|
|
10160
10293
|
return;
|
|
@@ -10198,11 +10331,32 @@ const DialogTableWidget = ({ config }) => {
|
|
|
10198
10331
|
onChange(newRows);
|
|
10199
10332
|
closeDialog();
|
|
10200
10333
|
}
|
|
10201
|
-
}, [
|
|
10334
|
+
}, [
|
|
10335
|
+
collectMergedRowPayload,
|
|
10336
|
+
finalizeDialogRowPayload,
|
|
10337
|
+
dialogMode,
|
|
10338
|
+
onChange,
|
|
10339
|
+
rows,
|
|
10340
|
+
closeDialog,
|
|
10341
|
+
activeRowIndex,
|
|
10342
|
+
columns,
|
|
10343
|
+
dialogSessionId,
|
|
10344
|
+
dialogFieldWidgetId,
|
|
10345
|
+
isReadonly,
|
|
10346
|
+
dispatch,
|
|
10347
|
+
]);
|
|
10202
10348
|
const deleteRow = useCallback((rowIndex) => {
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10349
|
+
if (shouldSoftDeleteOnRemove) {
|
|
10350
|
+
const newRows = [...rows];
|
|
10351
|
+
newRows[rowIndex] = {
|
|
10352
|
+
...newRows[rowIndex],
|
|
10353
|
+
edit_action: 'DELETE',
|
|
10354
|
+
};
|
|
10355
|
+
onChange(newRows);
|
|
10356
|
+
return;
|
|
10357
|
+
}
|
|
10358
|
+
onChange(rows.filter((_, i) => i !== rowIndex));
|
|
10359
|
+
}, [rows, onChange, shouldSoftDeleteOnRemove]);
|
|
10206
10360
|
const getDisplayValue = useCallback((rowIndex, column) => {
|
|
10207
10361
|
const key = column['column-key'];
|
|
10208
10362
|
const cellValue = rows[rowIndex]?.[key];
|
|
@@ -10210,11 +10364,12 @@ const DialogTableWidget = ({ config }) => {
|
|
|
10210
10364
|
if (cellValue === null || cellValue === undefined || cellValue === '')
|
|
10211
10365
|
return '-';
|
|
10212
10366
|
if (widgetType === 'select')
|
|
10213
|
-
return null;
|
|
10367
|
+
return null;
|
|
10214
10368
|
if (column['widget-data-format'])
|
|
10215
10369
|
return formatValue(cellValue, column['widget-data-format'], column.widget);
|
|
10216
10370
|
return String(cellValue);
|
|
10217
10371
|
}, [rows]);
|
|
10372
|
+
const visibleDialogColumns = useMemo(() => columns.filter((col) => shouldShowWidget(col['widget-data-options'], dialogRowValues)), [columns, dialogRowValues]);
|
|
10218
10373
|
const tableWidgetId = `dialog-table-widget-${widgetConfig['widget-id']}`;
|
|
10219
10374
|
const columnSpan = widgetConfig['widget-column-span'] || 2;
|
|
10220
10375
|
const minWidth = columnSpan * 200;
|
|
@@ -10242,37 +10397,40 @@ const DialogTableWidget = ({ config }) => {
|
|
|
10242
10397
|
}, children: translate('table.addRecord') || 'Add New Record' }) })), jsxRuntimeExports.jsx("div", { className: "overflow-x-auto border", style: {
|
|
10243
10398
|
borderRadius: 'var(--owt-widget-table-border-radius, 15px)',
|
|
10244
10399
|
borderColor: 'var(--owt-widget-table-border-color, #C4C4C4)',
|
|
10245
|
-
}, children: jsxRuntimeExports.jsxs("table", { className: "min-w-full", style: { borderCollapse: 'separate', borderSpacing: 0 }, children: [jsxRuntimeExports.jsx("thead", { style: { backgroundColor: 'var(--owt-widget-table-header-bg, #F6F6F6)' }, children: jsxRuntimeExports.jsxs("tr", { style: { borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)' }, children: [visibleColumns.map((col) => (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translateConfig(col['widget-label']) }, col['column-key']))), ((operations.edit || operations.remove) && !isReadonly) && (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translate('common.actions') || 'Actions' }))] }) }), jsxRuntimeExports.jsxs("tbody", { style: { backgroundColor: 'var(--owt-widget-table-body-bg, #FFFFFF)' }, children: [rows.length === 0 && (jsxRuntimeExports.jsx("tr", { children: jsxRuntimeExports.jsxs("td", { colSpan: visibleColumns.length + (((operations.edit || operations.remove) && !isReadonly) ? 1 : 0), className: "px-4 py-6 text-center text-sm", style: { color: 'var(--owt-widget-table-empty-color, #727474)' }, children: [translate('table.noData') || 'No records available.', operations.add && !isReadonly && ` ${translate('table.clickToAdd') || 'Click "Add New Record" to add one.'}`] }) })), rows.map((row, rowIndex) =>
|
|
10246
|
-
|
|
10247
|
-
|
|
10248
|
-
|
|
10249
|
-
:
|
|
10250
|
-
|
|
10251
|
-
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
|
|
10255
|
-
const
|
|
10256
|
-
|
|
10257
|
-
|
|
10258
|
-
|
|
10259
|
-
|
|
10260
|
-
|
|
10261
|
-
|
|
10262
|
-
|
|
10263
|
-
|
|
10264
|
-
|
|
10265
|
-
|
|
10266
|
-
|
|
10267
|
-
|
|
10268
|
-
|
|
10269
|
-
|
|
10270
|
-
|
|
10271
|
-
|
|
10272
|
-
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
|
|
10400
|
+
}, children: jsxRuntimeExports.jsxs("table", { className: "min-w-full", style: { borderCollapse: 'separate', borderSpacing: 0 }, children: [jsxRuntimeExports.jsx("thead", { style: { backgroundColor: 'var(--owt-widget-table-header-bg, #F6F6F6)' }, children: jsxRuntimeExports.jsxs("tr", { style: { borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)' }, children: [visibleColumns.map((col) => (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translateConfig(col['widget-label']) }, col['column-key']))), ((operations.edit || operations.remove) && !isReadonly) && (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translate('common.actions') || 'Actions' }))] }) }), jsxRuntimeExports.jsxs("tbody", { style: { backgroundColor: 'var(--owt-widget-table-body-bg, #FFFFFF)' }, children: [rows.length === 0 && (jsxRuntimeExports.jsx("tr", { children: jsxRuntimeExports.jsxs("td", { colSpan: visibleColumns.length + (((operations.edit || operations.remove) && !isReadonly) ? 1 : 0), className: "px-4 py-6 text-center text-sm", style: { color: 'var(--owt-widget-table-empty-color, #727474)' }, children: [translate('table.noData') || 'No records available.', operations.add && !isReadonly && ` ${translate('table.clickToAdd') || 'Click "Add New Record" to add one.'}`] }) })), rows.map((row, rowIndex) => {
|
|
10401
|
+
const cellStyle = getRowCellStyle(row?.edit_action);
|
|
10402
|
+
return (jsxRuntimeExports.jsxs("tr", { style: {
|
|
10403
|
+
borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)',
|
|
10404
|
+
backgroundColor: row?.edit_action === 'DELETE'
|
|
10405
|
+
? 'var(--owt-widget-table-deleted-row-bg, #FEE2E2)'
|
|
10406
|
+
: undefined,
|
|
10407
|
+
}, children: [visibleColumns.map((col) => {
|
|
10408
|
+
const key = col['column-key'];
|
|
10409
|
+
const widgetType = col.widget || 'text';
|
|
10410
|
+
const displayValue = getDisplayValue(rowIndex, col);
|
|
10411
|
+
if (widgetType === 'select' && displayValue === null) {
|
|
10412
|
+
const displayConfig = {
|
|
10413
|
+
...col,
|
|
10414
|
+
'widget-id': `${widgetConfig['widget-id']}-view-row-${rowIndex}-col-${key}`,
|
|
10415
|
+
'widget-label': '',
|
|
10416
|
+
'widget-readonly': true,
|
|
10417
|
+
'widget-data-path': undefined,
|
|
10418
|
+
};
|
|
10419
|
+
return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsx("div", { className: "text-sm", style: cellStyle, children: jsxRuntimeExports.jsx(SelectDisplayValue, { config: displayConfig, value: row?.[key] }) }) }, key));
|
|
10420
|
+
}
|
|
10421
|
+
return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsx("div", { className: "text-sm", style: cellStyle, children: displayValue }) }, key));
|
|
10422
|
+
}), ((operations.edit || operations.remove) && !isReadonly) && (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", style: { minWidth: '120px' }, children: jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [operations.edit && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => openEditDialog(rowIndex), disabled: !isEnabled, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
|
|
10423
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
10424
|
+
color: 'var(--owt-color-primary-dark, #F07B1A)',
|
|
10425
|
+
backgroundColor: 'transparent',
|
|
10426
|
+
border: 'none',
|
|
10427
|
+
}, children: translate('common.edit') || 'Edit' })), operations.remove && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => deleteRow(rowIndex), disabled: !isEnabled, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
|
|
10428
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
10429
|
+
color: 'var(--owt-color-error, #B91C1C)',
|
|
10430
|
+
backgroundColor: 'transparent',
|
|
10431
|
+
border: 'none',
|
|
10432
|
+
}, children: translate('common.remove') || 'Delete' }))] }) }))] }, rowIndex));
|
|
10433
|
+
})] })] }) }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-sm mt-1", style: { color: 'var(--owt-widget-error-color, #B91C1C)' }, children: error[0] }))] }), dialogOpen && (jsxRuntimeExports.jsx("div", { className: "fixed inset-0 flex items-center justify-center z-50", style: { backgroundColor: 'rgba(0,0,0,0.5)' }, children: jsxRuntimeExports.jsxs("div", { className: "rounded-lg p-6 w-full mx-4", style: {
|
|
10276
10434
|
maxWidth: '900px',
|
|
10277
10435
|
backgroundColor: 'var(--owt-color-bg, #FFFFFF)',
|
|
10278
10436
|
borderRadius: 'var(--owt-widget-card-border-radius, 20px)',
|
|
@@ -10283,27 +10441,10 @@ const DialogTableWidget = ({ config }) => {
|
|
|
10283
10441
|
cursor: 'pointer',
|
|
10284
10442
|
fontSize: '20px',
|
|
10285
10443
|
lineHeight: 1,
|
|
10286
|
-
}, "aria-label": "Close", children: "\u00D7" })] }), jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", style: { maxHeight: '70vh', overflow: 'auto' }, children:
|
|
10444
|
+
}, "aria-label": "Close", children: "\u00D7" })] }), jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", style: { maxHeight: '70vh', overflow: 'auto' }, children: visibleDialogColumns.map((col) => {
|
|
10287
10445
|
const key = col['column-key'];
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
}
|
|
10291
|
-
const widgetType = col.widget || 'text';
|
|
10292
|
-
const cellWidgetId = dialogFieldWidgetId(key);
|
|
10293
|
-
const initialValue = formData[key] ?? col['widget-data-default'];
|
|
10294
|
-
const fieldConfig = {
|
|
10295
|
-
...col,
|
|
10296
|
-
widget: widgetType,
|
|
10297
|
-
'widget-type': col['widget-type'] || 'input',
|
|
10298
|
-
'widget-id': cellWidgetId,
|
|
10299
|
-
'widget-label': col['widget-label'],
|
|
10300
|
-
'widget-readonly': isReadonly || col['widget-readonly'] === true,
|
|
10301
|
-
'widget-data-path': undefined,
|
|
10302
|
-
'widget-data-default': initialValue,
|
|
10303
|
-
'widget-data-options': undefined,
|
|
10304
|
-
'widget-required': shouldRequireWidget(col['widget-data-options'], dialogRowValues, col['widget-required']),
|
|
10305
|
-
};
|
|
10306
|
-
return (jsxRuntimeExports.jsx("div", { className: "min-w-0", children: jsxRuntimeExports.jsx(WidgetRenderer, { config: fieldConfig, schemaData: { [cellWidgetId]: initialValue }, onValueChange: (_widgetId, newValue) => updateField(key, newValue) }) }, `${dialogSessionId}-${key}`));
|
|
10446
|
+
const cellWidgetId = dialogFieldWidgetId(dialogSessionId, key);
|
|
10447
|
+
return (jsxRuntimeExports.jsx(DialogTableField, { col: col, cellWidgetId: cellWidgetId, dialogRowValues: dialogRowValues, isReadonly: isReadonly }, `${dialogSessionId}-${key}`));
|
|
10307
10448
|
}) }, `dialog-fields-${dialogSessionId}`), jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-3 mt-6", children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: closeDialog, className: "px-4 py-2 text-sm font-medium", style: {
|
|
10308
10449
|
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
10309
10450
|
border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
|
|
@@ -12946,5 +13087,5 @@ const translateUISchema = (schema, translate) => {
|
|
|
12946
13087
|
};
|
|
12947
13088
|
};
|
|
12948
13089
|
|
|
12949
|
-
export { ArrayWidget, BooleanWidget, CheckboxWidget, CurrencyInputWidget, DateInputWidget, DateTimeInputWidget, DialogTableWidget, DisplayWidget, FileInputWidget, GEO_LEVEL_CLEARED, HeaderSectionWidget, IdAuthenticationWidget, IterableAccordionWidget, JSONEditorPanel, MultiSelectWidget, NumberInputWidget, PanelRenderer, PhoneInputWidget, ProfileWidget, PropertyEditor, RadioWidget, RegisterLookupWidget, ScoresDisplayWidget, SectionBuilder, SectionRenderer, SectionTree, SectionsContainer, SelectWidget, SimpleTableWidget, TableWidget, TextAreaWidget, TextInputWidget, VisualBuilderPanel, WidgetEventBus, WidgetProvider, WidgetRenderer, applyCaseControl, applyDecimalPrecision, applyMask, applySharedGeoHierarchyToValues, createWidgetStore, createZodSchema, defaultTheme, evaluateCondition, evaluateWidgetConditions, filterByCharacterType, formatCurrency, formatDate, formatNumber, formatPhone, formatValue, geoHierarchyBuilder, getApiDataSource, getCachedApiDataSource, getFormattedNumberLength, getGeoDescendantWidgetIds, getGeoGroupId, getSchemaDataSource, getStaticDataSource, getValueByPath, getWidgetValue, hasVisibilityRules, initI18n, isAllowedKey, isUpstreamGeoAncestor, normalizeNumericDefault, normalizeOptionRules, parseDataPath, parseNumber, registerDefaultWidgets, registerGeoWidgetParent, removeMask, resetAll, resetAndSeedGeoHierarchyFromValues, resetWidget, resolveGeoWidgetLevelLabel, resolveGeoWidgetLevelValue, resolveTheme, resolveWidgetIdValue, seedGeoHierarchyFromValues, setDataSource, setError, setLoading, setTouched, setValue, setValueByPath, setValues, setWidgetValue, shouldEnableWidget, shouldRequireWidget, shouldShowWidget, transformDataSourceOptions, translatePanelConfig, translateUISchema, translateWidgetConfig, unregisterGeoWidgetParent, useBaseWidget, useGeoWidgetCascade, useWidgetCascade, useWidgetContext, useWidgetEventBus, useWidgetTheme, useWidgetTranslation, validateNumericValue, validateWidget, widgetRegistry };
|
|
13090
|
+
export { ArrayWidget, BooleanWidget, CheckboxWidget, CurrencyInputWidget, DateInputWidget, DateTimeInputWidget, DialogTableWidget, DisplayWidget, FileInputWidget, GEO_LEVEL_CLEARED, HeaderSectionWidget, IdAuthenticationWidget, IterableAccordionWidget, JSONEditorPanel, MultiSelectWidget, NumberInputWidget, PanelRenderer, PhoneInputWidget, ProfileWidget, PropertyEditor, RadioWidget, RegisterLookupWidget, ScoresDisplayWidget, SectionBuilder, SectionRenderer, SectionTree, SectionsContainer, SelectWidget, SimpleTableWidget, TableWidget, TextAreaWidget, TextInputWidget, VisualBuilderPanel, WidgetEventBus, WidgetProvider, WidgetRenderer, applyCaseControl, applyDecimalPrecision, applyMask, applySharedGeoHierarchyToValues, collectGeoWidgetRegistrationsFromWidgets, createGeoLevelMnemonicResolver, createWidgetStore, createZodSchema, defaultTheme, evaluateCondition, evaluateWidgetConditions, filterByCharacterType, formatCurrency, formatDate, formatNumber, formatPhone, formatValue, geoHierarchyBuilder, getApiDataSource, getCachedApiDataSource, getFormattedNumberLength, getGeoDescendantWidgetIds, getGeoGroupId, getGeoWidgetRegistrationsInGroup, getSchemaDataSource, getStaticDataSource, getValueByPath, getWidgetValue, hasVisibilityRules, initI18n, isAllowedKey, isUpstreamGeoAncestor, normalizeNumericDefault, normalizeOptionRules, orderGeoWidgetRegistrations, parseDataPath, parseNumber, rebuildGeoHierarchyFromRegistrations, reconcileGeoHierarchiesInValues, registerDefaultWidgets, registerGeoWidget, registerGeoWidgetParent, removeMask, resetAll, resetAndSeedGeoHierarchyFromValues, resetWidget, resolveGeoWidgetLevelLabel, resolveGeoWidgetLevelValue, resolveTheme, resolveWidgetIdValue, seedGeoHierarchyFromValues, setDataSource, setError, setLoading, setTouched, setValue, setValueByPath, setValues, setWidgetValue, shouldEnableWidget, shouldRequireWidget, shouldShowWidget, transformDataSourceOptions, translatePanelConfig, translateUISchema, translateWidgetConfig, unregisterGeoWidget, unregisterGeoWidgetParent, useBaseWidget, useGeoWidgetCascade, useWidgetCascade, useWidgetContext, useWidgetEventBus, useWidgetTheme, useWidgetTranslation, validateNumericValue, validateWidget, widgetRegistry };
|
|
12950
13091
|
//# sourceMappingURL=index.esm.js.map
|