@openg2p/registry-widgets 1.1.2-dev.7 → 1.1.2-dev.8
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/hooks/useBaseWidget.d.ts.map +1 -1
- package/dist/index.d.ts +9 -4
- package/dist/index.esm.js +119 -115
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +119 -114
- package/dist/index.js.map +1 -1
- package/dist/utils/dataSource.d.ts +6 -0
- package/dist/utils/dataSource.d.ts.map +1 -1
- package/dist/widgets/DialogTableWidget.d.ts.map +1 -1
- package/dist/widgets/SelectWidget.d.ts.map +1 -1
- package/dist/widgets/TableWidget.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1083,6 +1083,67 @@ const formatValue = (value, format, widgetType) => {
|
|
|
1083
1083
|
return value?.toString() || '';
|
|
1084
1084
|
};
|
|
1085
1085
|
|
|
1086
|
+
const apiDataSourceCache = new Map();
|
|
1087
|
+
const apiDataSourceInflight = new Map();
|
|
1088
|
+
function buildApiRequestContext(dataSource, allValues, levelId) {
|
|
1089
|
+
let depValue = null;
|
|
1090
|
+
if (dataSource.dependsOn) {
|
|
1091
|
+
if (dataSource.dependsOn.includes('.')) {
|
|
1092
|
+
depValue = getValueByPath(allValues, dataSource.dependsOn);
|
|
1093
|
+
}
|
|
1094
|
+
else {
|
|
1095
|
+
depValue = resolveWidgetIdValue(allValues, dataSource.dependsOn);
|
|
1096
|
+
}
|
|
1097
|
+
if (depValue === null || depValue === undefined || depValue === '') {
|
|
1098
|
+
return null;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
const method = dataSource.method || 'GET';
|
|
1102
|
+
const staticParams = { ...dataSource.params };
|
|
1103
|
+
const standardFields = ['type', 'service', 'endpoint', 'url', 'method', 'dependsOn', 'valueKey', 'labelKey', 'headers', 'body', 'params', 'level_id'];
|
|
1104
|
+
for (const [key, value] of Object.entries(dataSource)) {
|
|
1105
|
+
if (!standardFields.includes(key) && value !== undefined && value !== null) {
|
|
1106
|
+
staticParams[key] = value;
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
if (levelId) {
|
|
1110
|
+
staticParams.level_id = levelId;
|
|
1111
|
+
}
|
|
1112
|
+
const requestParams = { ...staticParams };
|
|
1113
|
+
if (dataSource.dependsOn && depValue !== null && depValue !== undefined) {
|
|
1114
|
+
const parentValueId = typeof depValue === 'object' && depValue !== null
|
|
1115
|
+
? (depValue.level_value_id || depValue.id || depValue.value || depValue)
|
|
1116
|
+
: depValue;
|
|
1117
|
+
if (staticParams.level_id) {
|
|
1118
|
+
requestParams.parent_level_value_id = parentValueId;
|
|
1119
|
+
}
|
|
1120
|
+
else {
|
|
1121
|
+
const paramKey = dataSource.dependsOn.split('.').pop() || 'filter';
|
|
1122
|
+
requestParams[paramKey] = parentValueId;
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
else if (staticParams.level_id) {
|
|
1126
|
+
requestParams.parent_level_value_id = '';
|
|
1127
|
+
}
|
|
1128
|
+
const service = dataSource.service;
|
|
1129
|
+
const endpoint = dataSource.endpoint;
|
|
1130
|
+
if (!service || !endpoint) {
|
|
1131
|
+
return null;
|
|
1132
|
+
}
|
|
1133
|
+
return { service, endpoint, method, requestParams };
|
|
1134
|
+
}
|
|
1135
|
+
function buildApiDataSourceCacheKey(service, endpoint, method, requestParams) {
|
|
1136
|
+
return `${service}|${endpoint}|${method}|${JSON.stringify(requestParams)}`;
|
|
1137
|
+
}
|
|
1138
|
+
/** Return cached API options when already fetched (e.g. duplicate table cells). */
|
|
1139
|
+
function getCachedApiDataSource(dataSource, allValues, levelId) {
|
|
1140
|
+
const context = buildApiRequestContext(dataSource, allValues, levelId);
|
|
1141
|
+
if (!context) {
|
|
1142
|
+
return undefined;
|
|
1143
|
+
}
|
|
1144
|
+
const cacheKey = buildApiDataSourceCacheKey(context.service, context.endpoint, context.method, context.requestParams);
|
|
1145
|
+
return apiDataSourceCache.get(cacheKey);
|
|
1146
|
+
}
|
|
1086
1147
|
/**
|
|
1087
1148
|
* Get static data source options
|
|
1088
1149
|
*/
|
|
@@ -1100,98 +1161,33 @@ const getApiDataSource = async (dataSource, allValues, dataSourceRequestHandler,
|
|
|
1100
1161
|
return [];
|
|
1101
1162
|
}
|
|
1102
1163
|
try {
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
let depValue = null;
|
|
1106
|
-
if (dataSource.dependsOn) {
|
|
1107
|
-
if (dataSource.dependsOn.includes('.')) {
|
|
1108
|
-
depValue = getValueByPath(allValues, dataSource.dependsOn);
|
|
1109
|
-
}
|
|
1110
|
-
else {
|
|
1111
|
-
depValue = resolveWidgetIdValue(allValues, dataSource.dependsOn);
|
|
1112
|
-
}
|
|
1113
|
-
if (depValue === null || depValue === undefined || depValue === '') {
|
|
1114
|
-
// If dependency is empty, return empty array
|
|
1115
|
-
return [];
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
// Build request parameters
|
|
1119
|
-
const method = dataSource.method || 'GET';
|
|
1120
|
-
// Extract static params from dataSource
|
|
1121
|
-
// Include explicit params object and any additional fields (like level_id)
|
|
1122
|
-
const staticParams = { ...dataSource.params };
|
|
1123
|
-
// Extract additional fields that aren't part of the standard ApiDataSource interface
|
|
1124
|
-
// These are fields like level_id that might be directly on the dataSource
|
|
1125
|
-
// BUT: level_id should come from widget-geo-config.level, not from dataSource
|
|
1126
|
-
const standardFields = ['type', 'service', 'endpoint', 'url', 'method', 'dependsOn', 'valueKey', 'labelKey', 'headers', 'body', 'params', 'level_id'];
|
|
1127
|
-
for (const [key, value] of Object.entries(dataSource)) {
|
|
1128
|
-
if (!standardFields.includes(key) && value !== undefined && value !== null) {
|
|
1129
|
-
staticParams[key] = value;
|
|
1130
|
-
}
|
|
1131
|
-
}
|
|
1132
|
-
// If levelId is provided (from widget-geo-config.level), use it instead of any level_id in dataSource
|
|
1133
|
-
if (levelId) {
|
|
1134
|
-
staticParams.level_id = levelId;
|
|
1135
|
-
}
|
|
1136
|
-
// Build request params object
|
|
1137
|
-
const requestParams = { ...staticParams };
|
|
1138
|
-
// Add dependency value to params
|
|
1139
|
-
if (dataSource.dependsOn && depValue !== null && depValue !== undefined) {
|
|
1140
|
-
// Extract the actual value ID if depValue is an object
|
|
1141
|
-
const parentValueId = typeof depValue === 'object' && depValue !== null
|
|
1142
|
-
? (depValue.level_value_id || depValue.id || depValue.value || depValue)
|
|
1143
|
-
: depValue;
|
|
1144
|
-
// For geo APIs, use parent_level_value_id
|
|
1145
|
-
if (staticParams.level_id) {
|
|
1146
|
-
requestParams.parent_level_value_id = parentValueId;
|
|
1147
|
-
}
|
|
1148
|
-
else {
|
|
1149
|
-
// For other APIs, use the dependency field name as param key
|
|
1150
|
-
const paramKey = dataSource.dependsOn.split('.').pop() || 'filter';
|
|
1151
|
-
requestParams[paramKey] = parentValueId;
|
|
1152
|
-
}
|
|
1153
|
-
}
|
|
1154
|
-
else if (staticParams.level_id) {
|
|
1155
|
-
// First level has no parent, send empty string as many OpenG2P APIs expect it
|
|
1156
|
-
requestParams.parent_level_value_id = "";
|
|
1157
|
-
}
|
|
1158
|
-
// Get service mnemonic and endpoint (required)
|
|
1159
|
-
const service = dataSource.service;
|
|
1160
|
-
const endpoint = dataSource.endpoint;
|
|
1161
|
-
if (!service) {
|
|
1162
|
-
console.error('[getApiDataSource] API data source missing service mnemonic. Use "service" field instead of "url"');
|
|
1163
|
-
return [];
|
|
1164
|
-
}
|
|
1165
|
-
if (!endpoint) {
|
|
1166
|
-
console.error('[getApiDataSource] API data source missing endpoint. Use "endpoint" field to specify the operation (e.g., "get_g2p_geo_level_values")');
|
|
1164
|
+
const context = buildApiRequestContext(dataSource, allValues, levelId);
|
|
1165
|
+
if (!context) {
|
|
1167
1166
|
return [];
|
|
1168
1167
|
}
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
}
|
|
1175
|
-
|
|
1176
|
-
if (
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
return
|
|
1168
|
+
const { service, endpoint, method, requestParams } = context;
|
|
1169
|
+
const cacheKey = buildApiDataSourceCacheKey(service, endpoint, method, requestParams);
|
|
1170
|
+
const cached = apiDataSourceCache.get(cacheKey);
|
|
1171
|
+
if (cached) {
|
|
1172
|
+
return cached;
|
|
1173
|
+
}
|
|
1174
|
+
const inflight = apiDataSourceInflight.get(cacheKey);
|
|
1175
|
+
if (inflight) {
|
|
1176
|
+
return inflight;
|
|
1177
|
+
}
|
|
1178
|
+
const fetchPromise = (async () => {
|
|
1179
|
+
const response = await dataSourceRequestHandler(service, endpoint, method, requestParams, { headers: dataSource.headers });
|
|
1180
|
+
const parsed = Array.isArray(response) ? response : [];
|
|
1181
|
+
apiDataSourceCache.set(cacheKey, parsed);
|
|
1182
|
+
return parsed;
|
|
1183
|
+
})();
|
|
1184
|
+
apiDataSourceInflight.set(cacheKey, fetchPromise);
|
|
1185
|
+
try {
|
|
1186
|
+
return await fetchPromise;
|
|
1184
1187
|
}
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
if (response.data && Array.isArray(response.data)) {
|
|
1188
|
-
return response.data;
|
|
1189
|
-
}
|
|
1190
|
-
if (response.results && Array.isArray(response.results)) {
|
|
1191
|
-
return response.results;
|
|
1192
|
-
}
|
|
1188
|
+
finally {
|
|
1189
|
+
apiDataSourceInflight.delete(cacheKey);
|
|
1193
1190
|
}
|
|
1194
|
-
return [];
|
|
1195
1191
|
}
|
|
1196
1192
|
catch (error) {
|
|
1197
1193
|
// Rethrow so useBaseWidget's catch can log it with full widget context
|
|
@@ -2701,9 +2697,9 @@ const useBaseWidget = (options) => {
|
|
|
2701
2697
|
if (!dataSource) {
|
|
2702
2698
|
return;
|
|
2703
2699
|
}
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
if (dataSource.type === 'api' && isReadonly && !
|
|
2700
|
+
const loadApiInReadonly = !!geoConfig ||
|
|
2701
|
+
['select', 'radio', 'checkbox', 'multi-select'].includes(config.widget);
|
|
2702
|
+
if (dataSource.type === 'api' && isReadonly && !loadApiInReadonly) {
|
|
2707
2703
|
return;
|
|
2708
2704
|
}
|
|
2709
2705
|
// For widgets with dependencies, check if dependency value exists
|
|
@@ -2745,6 +2741,30 @@ const useBaseWidget = (options) => {
|
|
|
2745
2741
|
// React will call this effect again when the handler is ready
|
|
2746
2742
|
return;
|
|
2747
2743
|
}
|
|
2744
|
+
const resolveOptionKeys = () => {
|
|
2745
|
+
if (dataSource.type === 'static') {
|
|
2746
|
+
return { valueKey: undefined, labelKey: undefined };
|
|
2747
|
+
}
|
|
2748
|
+
if (geoConfig) {
|
|
2749
|
+
return {
|
|
2750
|
+
valueKey: dataSource.valueKey || 'level_value_id',
|
|
2751
|
+
labelKey: dataSource.labelKey || 'level_value_mnemonic',
|
|
2752
|
+
};
|
|
2753
|
+
}
|
|
2754
|
+
return { valueKey: dataSource.valueKey, labelKey: dataSource.labelKey };
|
|
2755
|
+
};
|
|
2756
|
+
if (dataSource.type === 'api') {
|
|
2757
|
+
const levelId = geoConfig?.level;
|
|
2758
|
+
const cached = getCachedApiDataSource(dataSource, valuesRef.current, levelId);
|
|
2759
|
+
if (cached) {
|
|
2760
|
+
const { valueKey, labelKey } = resolveOptionKeys();
|
|
2761
|
+
dispatch(setDataSource({
|
|
2762
|
+
widgetId,
|
|
2763
|
+
data: transformDataSourceOptions(cached, valueKey, labelKey),
|
|
2764
|
+
}));
|
|
2765
|
+
return;
|
|
2766
|
+
}
|
|
2767
|
+
}
|
|
2748
2768
|
dispatch(setLoading({ widgetId, loading: true }));
|
|
2749
2769
|
let data = [];
|
|
2750
2770
|
if (dataSource.type === 'static') {
|
|
@@ -2757,31 +2777,13 @@ const useBaseWidget = (options) => {
|
|
|
2757
2777
|
dispatch(setDataSource({ widgetId, data: [] }));
|
|
2758
2778
|
return;
|
|
2759
2779
|
}
|
|
2760
|
-
// Extract level_id from widget-geo-config.level if available
|
|
2761
2780
|
const levelId = geoConfig?.level;
|
|
2762
2781
|
data = await getApiDataSource(dataSource, valuesRef.current, currentHandler, levelId);
|
|
2763
2782
|
}
|
|
2764
2783
|
else if (dataSource.type === 'schema') {
|
|
2765
2784
|
data = getSchemaDataSource(dataSource, schemaData || {});
|
|
2766
2785
|
}
|
|
2767
|
-
|
|
2768
|
-
// For geo widgets, default to level_value_id and level_value_mnemonic
|
|
2769
|
-
let valueKey;
|
|
2770
|
-
let labelKey;
|
|
2771
|
-
if (dataSource.type === 'static') {
|
|
2772
|
-
valueKey = undefined;
|
|
2773
|
-
labelKey = undefined;
|
|
2774
|
-
}
|
|
2775
|
-
else if (geoConfig) {
|
|
2776
|
-
// Geo widgets: default to level_value_id and level_value_mnemonic
|
|
2777
|
-
valueKey = dataSource.valueKey || 'level_value_id';
|
|
2778
|
-
labelKey = dataSource.labelKey || 'level_value_mnemonic';
|
|
2779
|
-
}
|
|
2780
|
-
else {
|
|
2781
|
-
// Non-geo widgets: use specified keys or undefined
|
|
2782
|
-
valueKey = dataSource.valueKey;
|
|
2783
|
-
labelKey = dataSource.labelKey;
|
|
2784
|
-
}
|
|
2786
|
+
const { valueKey, labelKey } = resolveOptionKeys();
|
|
2785
2787
|
const transformed = transformDataSourceOptions(data, valueKey, labelKey);
|
|
2786
2788
|
dispatch(setDataSource({ widgetId, data: transformed }));
|
|
2787
2789
|
}
|
|
@@ -8757,10 +8759,12 @@ const SelectWidget = ({ config }) => {
|
|
|
8757
8759
|
if (widgetConfig['widget-readonly']) {
|
|
8758
8760
|
const label = translateConfig(widgetConfig['widget-label']);
|
|
8759
8761
|
// Find the selected option's label
|
|
8760
|
-
const selectedOption = dataSourceOptions.find((option) => option.value === value);
|
|
8762
|
+
const selectedOption = dataSourceOptions.find((option) => option.value === value || String(option.value) === String(value));
|
|
8761
8763
|
const displayValue = selectedOption
|
|
8762
8764
|
? translateConfig(selectedOption.label)
|
|
8763
|
-
:
|
|
8765
|
+
: loading
|
|
8766
|
+
? (geoDisplayLabel || '-')
|
|
8767
|
+
: (geoDisplayLabel || (value != null && value !== '' ? translateConfig(String(value)) : '-'));
|
|
8764
8768
|
return (jsxRuntimeExports.jsxs("div", { className: "mb-[10px] SelectDisplayWidget flex flex-col sm:flex-row sm:items-start", children: [label && (jsxRuntimeExports.jsxs("div", { className: "text-base text-gray-600 font-medium md:min-w-[120px] sm:pr-4 mb-1 sm:mb-0", style: { fontFamily: 'Roboto, sans-serif' }, title: label, children: [label, ":"] })), jsxRuntimeExports.jsx("div", { className: "flex-1", children: jsxRuntimeExports.jsx("div", { className: "text-base text-gray-900 font-medium", title: String(displayValue ?? ''), children: displayValue }) })] }));
|
|
8765
8769
|
}
|
|
8766
8770
|
return (jsxRuntimeExports.jsx("div", { className: "mb-[10px]", children: jsxRuntimeExports.jsxs("div", { className: "flex flex-col sm:flex-row sm:items-start", children: [jsxRuntimeExports.jsx(WidgetFieldLabel, { className: "text-base font-medium text-gray-700 md:min-w-[120px] sm:pr-4 sm:pt-1 mb-1 sm:mb-0", label: translateConfig(widgetConfig['widget-label']), required: isRequired }), jsxRuntimeExports.jsxs("div", { className: "flex-1 min-w-0", children: [jsxRuntimeExports.jsxs("select", { value: value || '', onChange: (e) => onChange(e.target.value === '' ? undefined : e.target.value), onBlur: onBlur, disabled: !isEnabled || loading || widgetConfig['widget-readonly'], className: `w-full sm:w-[180px] max-w-full h-[30px] px-3 border shadow-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${(touched && error.length > 0) || (widgetConfig['widget-required'] && (!value || value === ''))
|
|
@@ -9259,7 +9263,7 @@ const SelectDisplayValue$1 = ({ config, value }) => {
|
|
|
9259
9263
|
if (value === null || value === undefined || value === '') {
|
|
9260
9264
|
return jsxRuntimeExports.jsx("span", { children: "-" });
|
|
9261
9265
|
}
|
|
9262
|
-
const selectedOption = dataSourceOptions.find((option) => option.value === value);
|
|
9266
|
+
const selectedOption = dataSourceOptions.find((option) => option.value === value || String(option.value) === String(value));
|
|
9263
9267
|
return jsxRuntimeExports.jsx("span", { children: selectedOption ? selectedOption.label : String(value) });
|
|
9264
9268
|
};
|
|
9265
9269
|
const TableCellText = ({ config, value, onValueChange }) => {
|
|
@@ -9990,7 +9994,7 @@ const SelectDisplayValue = ({ config, value }) => {
|
|
|
9990
9994
|
return jsxRuntimeExports.jsx("span", { children: "-" });
|
|
9991
9995
|
if (value === null || value === undefined || value === '')
|
|
9992
9996
|
return jsxRuntimeExports.jsx("span", { children: "-" });
|
|
9993
|
-
const selectedOption = dataSourceOptions.find((option) => option.value === value);
|
|
9997
|
+
const selectedOption = dataSourceOptions.find((option) => option.value === value || String(option.value) === String(value));
|
|
9994
9998
|
return jsxRuntimeExports.jsx("span", { children: selectedOption ? selectedOption.label : String(value) });
|
|
9995
9999
|
};
|
|
9996
10000
|
/**
|
|
@@ -12997,6 +13001,7 @@ exports.formatPhone = formatPhone;
|
|
|
12997
13001
|
exports.formatValue = formatValue;
|
|
12998
13002
|
exports.geoHierarchyBuilder = geoHierarchyBuilder;
|
|
12999
13003
|
exports.getApiDataSource = getApiDataSource;
|
|
13004
|
+
exports.getCachedApiDataSource = getCachedApiDataSource;
|
|
13000
13005
|
exports.getFormattedNumberLength = getFormattedNumberLength;
|
|
13001
13006
|
exports.getGeoDescendantWidgetIds = getGeoDescendantWidgetIds;
|
|
13002
13007
|
exports.getGeoGroupId = getGeoGroupId;
|