@openg2p/registry-widgets 0.1.3 → 0.1.5
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/SectionBuilder/JSONEditorPanel.d.ts +0 -1
- package/dist/components/SectionBuilder/JSONEditorPanel.d.ts.map +1 -1
- package/dist/components/SectionBuilder/PropertyEditor.d.ts.map +1 -1
- package/dist/components/SectionBuilder/SectionBuilder.d.ts.map +1 -1
- package/dist/components/SectionBuilder/VisualBuilderPanel.d.ts.map +1 -1
- package/dist/components/SectionRenderer.d.ts +3 -1
- package/dist/components/SectionRenderer.d.ts.map +1 -1
- package/dist/components/WidgetRenderer.d.ts.map +1 -1
- package/dist/hooks/useBaseWidget.d.ts.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.esm.js +169 -199
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +169 -199
- package/dist/index.js.map +1 -1
- package/dist/widgets/DisplayWidget.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -951,32 +951,63 @@ const useBaseWidget = (options) => {
|
|
|
951
951
|
if (isLayoutWidget) {
|
|
952
952
|
return undefined; // Layout widgets don't have values
|
|
953
953
|
}
|
|
954
|
+
// Helper to extract displayable value from object (especially geo hierarchy objects)
|
|
955
|
+
const extractValueFromObject = (obj) => {
|
|
956
|
+
if (!obj || typeof obj !== 'object' || Array.isArray(obj)) {
|
|
957
|
+
return obj;
|
|
958
|
+
}
|
|
959
|
+
// Check for geo hierarchy structure first
|
|
960
|
+
if ('geo_code_hierarchy_json' in obj || 'geo_lowest_level_value_id' in obj) {
|
|
961
|
+
if ('geo_lowest_level_value_id' in obj) {
|
|
962
|
+
return obj.geo_lowest_level_value_id;
|
|
963
|
+
}
|
|
964
|
+
// If it's a geo hierarchy object but no extractable ID, return undefined to avoid rendering object
|
|
965
|
+
return undefined;
|
|
966
|
+
}
|
|
967
|
+
// Try common value fields
|
|
968
|
+
if ('value' in obj) {
|
|
969
|
+
return obj.value;
|
|
970
|
+
}
|
|
971
|
+
if ('id' in obj) {
|
|
972
|
+
return obj.id;
|
|
973
|
+
}
|
|
974
|
+
if ('label' in obj) {
|
|
975
|
+
return obj.label;
|
|
976
|
+
}
|
|
977
|
+
if ('name' in obj) {
|
|
978
|
+
return obj.name;
|
|
979
|
+
}
|
|
980
|
+
// If no extractable value found, return undefined to avoid rendering object as React child
|
|
981
|
+
// This prevents "Objects are not valid as a React child" errors
|
|
982
|
+
return undefined;
|
|
983
|
+
};
|
|
954
984
|
// Try to get value from widgetId first (this should have the actual selected value)
|
|
955
985
|
// For geo widgets with dataPath, widgetId stores the actual ID, while dataPath stores the hierarchy object
|
|
956
986
|
let value = values[widgetId];
|
|
987
|
+
// Extract value if it's an object (handles geo hierarchy objects stored in widgetId)
|
|
988
|
+
if (value !== null && value !== undefined && typeof value === 'object' && !Array.isArray(value)) {
|
|
989
|
+
value = extractValueFromObject(value);
|
|
990
|
+
}
|
|
957
991
|
// If widgetId doesn't have a value, try dataPath
|
|
958
992
|
if (value === undefined && config['widget-data-path']) {
|
|
959
993
|
value = getWidgetValue(values, config['widget-data-path'], widgetId);
|
|
960
|
-
//
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
if (geoConfig?.isLastLevel && value && typeof value === 'object' && !Array.isArray(value)) {
|
|
964
|
-
// If it's a geo hierarchy object, extract the actual value
|
|
965
|
-
if ('geo_lowest_level_value_id' in value) {
|
|
966
|
-
value = value.geo_lowest_level_value_id;
|
|
967
|
-
}
|
|
968
|
-
else if ('value' in value) {
|
|
969
|
-
value = value.value;
|
|
970
|
-
}
|
|
971
|
-
else if ('id' in value) {
|
|
972
|
-
value = value.id;
|
|
973
|
-
}
|
|
994
|
+
// Extract value if it's an object (handles geo hierarchy objects from dataPath)
|
|
995
|
+
if (value !== null && value !== undefined && typeof value === 'object' && !Array.isArray(value)) {
|
|
996
|
+
value = extractValueFromObject(value);
|
|
974
997
|
}
|
|
975
998
|
}
|
|
976
999
|
// If value is still undefined and user has set a value, try reading from widgetId as backup
|
|
977
1000
|
// This handles cases where dataPath lookup might fail temporarily
|
|
978
1001
|
if (value === undefined && userHasSetValueRef.current && values[widgetId] !== undefined) {
|
|
979
1002
|
value = values[widgetId];
|
|
1003
|
+
// Extract value if it's an object (handles geo hierarchy objects)
|
|
1004
|
+
if (value !== null && value !== undefined && typeof value === 'object' && !Array.isArray(value)) {
|
|
1005
|
+
value = extractValueFromObject(value);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
// Final safety check: if value is still an object, extract displayable value
|
|
1009
|
+
if (value !== null && value !== undefined && typeof value === 'object' && !Array.isArray(value)) {
|
|
1010
|
+
value = extractValueFromObject(value);
|
|
980
1011
|
}
|
|
981
1012
|
// If user has explicitly set a value, always return it (even if undefined/null)
|
|
982
1013
|
// This prevents the default from overwriting user selections
|
|
@@ -2246,7 +2277,7 @@ const WidgetProvider = ({ store, dataSourceRequestHandler, schemaData, translate
|
|
|
2246
2277
|
widgetStore.dispatch(setValues(schemaData));
|
|
2247
2278
|
}
|
|
2248
2279
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2249
|
-
}, []); // Only run on mount
|
|
2280
|
+
}, [schemaData, widgetStore]); // Only run on mount
|
|
2250
2281
|
const content = (jsxRuntimeExports.jsx(reactRedux.Provider, { store: widgetStore, children: jsxRuntimeExports.jsx(WidgetContext.Provider, { value: contextValue, children: jsxRuntimeExports.jsx(WidgetEventBusContext.Provider, { value: eventBus, children: children }) }) }));
|
|
2251
2282
|
return content;
|
|
2252
2283
|
};
|
|
@@ -2256,8 +2287,11 @@ const WidgetRenderer = ({ config, dataSourceRequestHandler: propDataSourceReques
|
|
|
2256
2287
|
const context = useWidgetContext();
|
|
2257
2288
|
const dataSourceRequestHandler = propDataSourceRequestHandler || context.dataSourceRequestHandler;
|
|
2258
2289
|
const schemaData = propSchemaData || context.schemaData;
|
|
2290
|
+
// Warn if dataSourceRequestHandler is missing for API data sources, but don't break rendering
|
|
2291
|
+
// This allows widgets to render in read-only or static modes (e.g., CRView)
|
|
2259
2292
|
if (!dataSourceRequestHandler && config['widget-data-source']?.type === 'api') {
|
|
2260
|
-
console.
|
|
2293
|
+
console.warn(`[WidgetRenderer] dataSourceRequestHandler is not provided for widget ${config['widget-id']} with API data source. ` +
|
|
2294
|
+
`The widget will render but API data source functionality will be disabled.`);
|
|
2261
2295
|
}
|
|
2262
2296
|
// Get values from Redux for cascade hooks
|
|
2263
2297
|
const values = reactRedux.useSelector((state) => state.widget.values);
|
|
@@ -3193,7 +3227,7 @@ const namespaceSectionConfig = (section, namespace) => {
|
|
|
3193
3227
|
* - Panels wrap when they exceed available width
|
|
3194
3228
|
* - Sections can sit side-by-side if there's space
|
|
3195
3229
|
*/
|
|
3196
|
-
const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequestHandler, schemaData, onValueChange, gridColumnSpan, onSectionSave, hideEditButton = false, mode = 'RegistryView', namespace, }) => {
|
|
3230
|
+
const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequestHandler, schemaData, onValueChange, gridColumnSpan, onSectionSave, hideEditButton = false, mode = 'RegistryView', namespace, changeRequestType, showChangeRequestLabel = true, }) => {
|
|
3197
3231
|
const { translateConfig, translate } = useWidgetTranslation();
|
|
3198
3232
|
const { schemaData: contextSchemaData, dataSourceRequestHandler: contextDataSourceRequestHandler } = useWidgetContext();
|
|
3199
3233
|
const store = reactRedux.useStore();
|
|
@@ -3811,11 +3845,12 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
3811
3845
|
align-items: center;
|
|
3812
3846
|
gap: 0.5rem;
|
|
3813
3847
|
}
|
|
3814
|
-
` }), jsxRuntimeExports.jsxs("div", { ref: sectionRef, className: `section ${sectionClassId} px-4 sm:px-6 lg:px-8 border-2 border-
|
|
3848
|
+
` }), jsxRuntimeExports.jsxs("div", { ref: sectionRef, className: `section ${sectionClassId} px-4 sm:px-6 lg:px-8 border-2 border-white `, "data-section-id": sectionId, "data-has-table": hasTableWidget ? 'true' : 'false', "data-has-explicit-span": hasExplicitTableSpan ? 'true' : 'false', "data-edit-mode": isEditMode ? 'true' : 'false', "data-column-span": columnSpan, "data-change-request-type": changeRequestType, style: {
|
|
3815
3849
|
gridColumn: `span ${columnSpan}`,
|
|
3816
3850
|
width: '100%',
|
|
3817
3851
|
borderRadius: '10px',
|
|
3818
|
-
backgroundColor: '#FFFFFF',
|
|
3852
|
+
backgroundColor: changeRequestType === 'old' ? '#F9F9F9' : '#FFFFFF', // Faded background for old change requests
|
|
3853
|
+
opacity: changeRequestType === 'old' ? 0.95 : 1, // Slight opacity reduction for old sections
|
|
3819
3854
|
...(isEditMode && sectionHeight ? {
|
|
3820
3855
|
height: `${sectionHeight}px`,
|
|
3821
3856
|
minHeight: `${sectionHeight}px`
|
|
@@ -3824,7 +3859,27 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
3824
3859
|
minHeight: 'auto',
|
|
3825
3860
|
height: 'auto'
|
|
3826
3861
|
}),
|
|
3827
|
-
}, children: [sectionToRender['section-title'] && (jsxRuntimeExports.
|
|
3862
|
+
}, children: [sectionToRender['section-title'] && (jsxRuntimeExports.jsxs("div", { style: {
|
|
3863
|
+
marginTop: '35px',
|
|
3864
|
+
marginBottom: '16px',
|
|
3865
|
+
display: 'flex',
|
|
3866
|
+
alignItems: 'center',
|
|
3867
|
+
gap: '12px',
|
|
3868
|
+
flexWrap: 'wrap',
|
|
3869
|
+
}, children: [jsxRuntimeExports.jsx("h2", { className: "text-xl font-semibold", style: { margin: 0 }, children: translateConfig(sectionToRender['section-title']) }), mode === 'CRView' && changeRequestType && showChangeRequestLabel && (jsxRuntimeExports.jsx("span", { style: {
|
|
3870
|
+
display: 'inline-flex',
|
|
3871
|
+
alignItems: 'center',
|
|
3872
|
+
padding: '4px 12px',
|
|
3873
|
+
borderRadius: '4px',
|
|
3874
|
+
fontSize: '12px',
|
|
3875
|
+
fontWeight: 600,
|
|
3876
|
+
textTransform: 'uppercase',
|
|
3877
|
+
letterSpacing: '0.5px',
|
|
3878
|
+
backgroundColor: changeRequestType === 'new' ? '#28a745' : '#ffcccc', // Green for new, faded red for old
|
|
3879
|
+
color: changeRequestType === 'new' ? '#FFFFFF' : '#cc0000',
|
|
3880
|
+
whiteSpace: 'nowrap',
|
|
3881
|
+
boxShadow: changeRequestType === 'new' ? '0 2px 4px rgba(40, 167, 69, 0.3)' : 'none',
|
|
3882
|
+
}, children: changeRequestType === 'new' ? 'New' : 'Old' }))] })), jsxRuntimeExports.jsxs("div", { id: gridId, className: "section-panels", style: mode === 'RegistryView' && hideEditButton ? { paddingBottom: '40px' } : {}, children: [editableSection.panels.map((panel, index) => (jsxRuntimeExports.jsx("div", { className: "panel-wrapper", children: jsxRuntimeExports.jsx(PanelRenderer, { panel: panel, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: namespacedSchemaData, onValueChange: onValueChange }) }, panel['panel-id'] || `section-panel-${index}`))), mode === 'CRView' && crViewData && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("hr", { className: "border-gray-300 w-full", style: { height: '1px', marginTop: '20px', marginBottom: '0px' } }), jsxRuntimeExports.jsxs("div", { className: "cr-view-container", style: {
|
|
3828
3883
|
marginTop: '20px',
|
|
3829
3884
|
paddingBottom: '30px',
|
|
3830
3885
|
display: 'flex',
|
|
@@ -4117,7 +4172,7 @@ if (typeof document !== 'undefined') {
|
|
|
4117
4172
|
/**
|
|
4118
4173
|
* JSON Editor Panel - Left side of Section Builder
|
|
4119
4174
|
*/
|
|
4120
|
-
const JSONEditorPanel = ({ section, onChange, onReset,
|
|
4175
|
+
const JSONEditorPanel = ({ section, onChange, onReset, context = 'section', }) => {
|
|
4121
4176
|
const [jsonData, setJsonData] = React.useState(section);
|
|
4122
4177
|
const [validationErrors, setValidationErrors] = React.useState([]);
|
|
4123
4178
|
const [rawJsonView, setRawJsonView] = React.useState(false);
|
|
@@ -4189,96 +4244,6 @@ const JSONEditorPanel = ({ section, onChange, onReset, onSelectNode, context = '
|
|
|
4189
4244
|
window.addEventListener('keydown', handleEscape);
|
|
4190
4245
|
return () => window.removeEventListener('keydown', handleEscape);
|
|
4191
4246
|
}, [showPreview]);
|
|
4192
|
-
// Handle clicks in JSON editor to select corresponding node in visual builder
|
|
4193
|
-
React.useEffect(() => {
|
|
4194
|
-
if (!onSelectNode || rawJsonView)
|
|
4195
|
-
return; // Only work in tree view, not raw JSON view
|
|
4196
|
-
const handleJsonEditorClick = (e) => {
|
|
4197
|
-
const mouseEvent = e;
|
|
4198
|
-
const target = mouseEvent.target;
|
|
4199
|
-
// Find the key text element (json-edit-react uses .jer-key-text class)
|
|
4200
|
-
const keyElement = target.closest('.jer-key-text') ||
|
|
4201
|
-
target.querySelector('.jer-key-text') ||
|
|
4202
|
-
(target.classList.contains('jer-key-text') ? target : null);
|
|
4203
|
-
if (!keyElement)
|
|
4204
|
-
return;
|
|
4205
|
-
const keyText = keyElement.textContent?.trim();
|
|
4206
|
-
if (!keyText)
|
|
4207
|
-
return;
|
|
4208
|
-
// Remove colon if present
|
|
4209
|
-
const keyName = keyText.replace(':', '').trim();
|
|
4210
|
-
// Map key names to node types and find the corresponding node
|
|
4211
|
-
let nodeId = null;
|
|
4212
|
-
let nodeType = null;
|
|
4213
|
-
if (keyName === 'section-id') {
|
|
4214
|
-
// Find the section-id value
|
|
4215
|
-
const keyRow = keyElement.closest('.jer-collection-header-row, .jer-value-row');
|
|
4216
|
-
if (keyRow) {
|
|
4217
|
-
const valueElement = keyRow.querySelector('.jer-value-text, .jer-string-value');
|
|
4218
|
-
if (valueElement) {
|
|
4219
|
-
nodeId = valueElement.textContent?.replace(/^"|"$/g, '').trim() || section['section-id'];
|
|
4220
|
-
nodeType = 'section';
|
|
4221
|
-
}
|
|
4222
|
-
}
|
|
4223
|
-
}
|
|
4224
|
-
else if (keyName === 'panel-id') {
|
|
4225
|
-
// Find the panel-id value in the current panel object
|
|
4226
|
-
const panelContainer = keyElement.closest('.jer-collection-component');
|
|
4227
|
-
if (panelContainer) {
|
|
4228
|
-
const valueElement = panelContainer.querySelector('.jer-value-text, .jer-string-value');
|
|
4229
|
-
if (valueElement) {
|
|
4230
|
-
// Try to find panel-id value in this panel
|
|
4231
|
-
const allKeys = panelContainer.querySelectorAll('.jer-key-text');
|
|
4232
|
-
for (const key of Array.from(allKeys)) {
|
|
4233
|
-
if (key.textContent?.includes('panel-id')) {
|
|
4234
|
-
const keyRow = key.closest('.jer-collection-header-row, .jer-value-row');
|
|
4235
|
-
if (keyRow) {
|
|
4236
|
-
const valElement = keyRow.querySelector('.jer-value-text, .jer-string-value');
|
|
4237
|
-
if (valElement) {
|
|
4238
|
-
nodeId = valElement.textContent?.replace(/^"|"$/g, '').trim() || null;
|
|
4239
|
-
nodeType = 'panel';
|
|
4240
|
-
break;
|
|
4241
|
-
}
|
|
4242
|
-
}
|
|
4243
|
-
}
|
|
4244
|
-
}
|
|
4245
|
-
}
|
|
4246
|
-
}
|
|
4247
|
-
}
|
|
4248
|
-
else if (keyName === 'widget-id') {
|
|
4249
|
-
// Find the widget-id value in the current widget object
|
|
4250
|
-
const widgetContainer = keyElement.closest('.jer-collection-component');
|
|
4251
|
-
if (widgetContainer) {
|
|
4252
|
-
const allKeys = widgetContainer.querySelectorAll('.jer-key-text');
|
|
4253
|
-
for (const key of Array.from(allKeys)) {
|
|
4254
|
-
if (key.textContent?.includes('widget-id')) {
|
|
4255
|
-
const keyRow = key.closest('.jer-collection-header-row, .jer-value-row');
|
|
4256
|
-
if (keyRow) {
|
|
4257
|
-
const valElement = keyRow.querySelector('.jer-value-text, .jer-string-value');
|
|
4258
|
-
if (valElement) {
|
|
4259
|
-
nodeId = valElement.textContent?.replace(/^"|"$/g, '').trim() || null;
|
|
4260
|
-
nodeType = 'widget';
|
|
4261
|
-
break;
|
|
4262
|
-
}
|
|
4263
|
-
}
|
|
4264
|
-
}
|
|
4265
|
-
}
|
|
4266
|
-
}
|
|
4267
|
-
}
|
|
4268
|
-
// If we found a node, select it in the visual builder
|
|
4269
|
-
if (nodeId && nodeType) {
|
|
4270
|
-
onSelectNode(nodeId, nodeType);
|
|
4271
|
-
}
|
|
4272
|
-
};
|
|
4273
|
-
// Add click listener to the JSON editor container
|
|
4274
|
-
const editorContainer = document.querySelector('.json-editor-scroll-container');
|
|
4275
|
-
if (editorContainer) {
|
|
4276
|
-
editorContainer.addEventListener('click', handleJsonEditorClick);
|
|
4277
|
-
return () => {
|
|
4278
|
-
editorContainer.removeEventListener('click', handleJsonEditorClick);
|
|
4279
|
-
};
|
|
4280
|
-
}
|
|
4281
|
-
}, [onSelectNode, rawJsonView, section]);
|
|
4282
4247
|
// Make section editable for preview - remove readonly flags from widgets
|
|
4283
4248
|
const makeSectionEditable = React.useCallback((section) => {
|
|
4284
4249
|
const processWidget = (widget) => {
|
|
@@ -4523,7 +4488,7 @@ const JSONEditorPanel = ({ section, onChange, onReset, onSelectNode, context = '
|
|
|
4523
4488
|
minHeight: 0,
|
|
4524
4489
|
borderRight: '0px',
|
|
4525
4490
|
}, children: [jsxRuntimeExports.jsxs("div", { style: {
|
|
4526
|
-
padding: '
|
|
4491
|
+
padding: '16px 20px',
|
|
4527
4492
|
background: '#ffffff',
|
|
4528
4493
|
display: 'flex',
|
|
4529
4494
|
justifyContent: 'space-between',
|
|
@@ -4545,8 +4510,8 @@ const JSONEditorPanel = ({ section, onChange, onReset, onSelectNode, context = '
|
|
|
4545
4510
|
}, children: [jsxRuntimeExports.jsxs("button", { onClick: handleReset, style: {
|
|
4546
4511
|
padding: '6px 12px',
|
|
4547
4512
|
border: '1px solid #ddd',
|
|
4548
|
-
borderRadius: '
|
|
4549
|
-
background: '
|
|
4513
|
+
borderRadius: '10px',
|
|
4514
|
+
background: '#f3f3f3',
|
|
4550
4515
|
color: '#666',
|
|
4551
4516
|
cursor: 'pointer',
|
|
4552
4517
|
display: 'flex',
|
|
@@ -4564,8 +4529,8 @@ const JSONEditorPanel = ({ section, onChange, onReset, onSelectNode, context = '
|
|
|
4564
4529
|
}, title: "Reset to original JSON", children: [jsxRuntimeExports.jsxs("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8" }), jsxRuntimeExports.jsx("path", { d: "M21 3v5h-5" }), jsxRuntimeExports.jsx("path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16" }), jsxRuntimeExports.jsx("path", { d: "M3 21v-5h5" })] }), "Reset"] }), jsxRuntimeExports.jsxs("button", { onClick: () => setShowPreview(true), style: {
|
|
4565
4530
|
padding: '6px 12px',
|
|
4566
4531
|
border: '1px solid #ddd',
|
|
4567
|
-
borderRadius: '
|
|
4568
|
-
background: '
|
|
4532
|
+
borderRadius: '10px',
|
|
4533
|
+
background: '#f3f3f3',
|
|
4569
4534
|
color: '#666',
|
|
4570
4535
|
cursor: 'pointer',
|
|
4571
4536
|
display: 'flex',
|
|
@@ -4921,18 +4886,24 @@ const PropertyEditor = ({ node, onChange, onDelete, onDuplicate, }) => {
|
|
|
4921
4886
|
border: '1px solid #ccc',
|
|
4922
4887
|
borderRadius: '4px',
|
|
4923
4888
|
fontSize: '12px',
|
|
4889
|
+
background: 'white',
|
|
4890
|
+
color: '#333',
|
|
4924
4891
|
} })] }), jsxRuntimeExports.jsxs("div", { style: { marginBottom: '20px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '12px', fontWeight: 500 }, children: "Section Title" }), jsxRuntimeExports.jsx("input", { type: "text", value: section['section-title'] || '', onChange: (e) => handleChange('section-title', e.target.value), style: {
|
|
4925
4892
|
width: '100%',
|
|
4926
4893
|
padding: '8px 12px',
|
|
4927
4894
|
border: '1px solid #ccc',
|
|
4928
4895
|
borderRadius: '4px',
|
|
4929
4896
|
fontSize: '12px',
|
|
4897
|
+
background: 'white',
|
|
4898
|
+
color: '#333',
|
|
4930
4899
|
} })] }), jsxRuntimeExports.jsx("div", { style: { marginBottom: '20px' }, children: jsxRuntimeExports.jsxs("label", { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '12px' }, children: [jsxRuntimeExports.jsx("input", { type: "checkbox", checked: section['section-editable'] || false, onChange: (e) => handleChange('section-editable', e.target.checked) }), jsxRuntimeExports.jsx("span", { children: "Editable" })] }) }), jsxRuntimeExports.jsxs("div", { style: { marginBottom: '20px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '12px', fontWeight: 500 }, children: "Column Span" }), jsxRuntimeExports.jsx("input", { type: "number", value: section['section-column-span'] || 1, onChange: (e) => handleChange('section-column-span', parseInt(e.target.value) || 1), min: "1", style: {
|
|
4931
4900
|
width: '100%',
|
|
4932
4901
|
padding: '8px 12px',
|
|
4933
4902
|
border: '1px solid #ccc',
|
|
4934
4903
|
borderRadius: '4px',
|
|
4935
4904
|
fontSize: '12px',
|
|
4905
|
+
background: 'white',
|
|
4906
|
+
color: '#333',
|
|
4936
4907
|
} })] })] }));
|
|
4937
4908
|
};
|
|
4938
4909
|
const renderPanelProperties = () => {
|
|
@@ -4943,6 +4914,8 @@ const PropertyEditor = ({ node, onChange, onDelete, onDuplicate, }) => {
|
|
|
4943
4914
|
border: '1px solid #ccc',
|
|
4944
4915
|
borderRadius: '4px',
|
|
4945
4916
|
fontSize: '12px',
|
|
4917
|
+
background: 'white',
|
|
4918
|
+
color: '#333',
|
|
4946
4919
|
} })] }), jsxRuntimeExports.jsxs("div", { style: { marginBottom: '20px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '12px', fontWeight: 500 }, children: "Orientation" }), jsxRuntimeExports.jsx("select", { value: panel['panel-orientation'] || 'vertical', onChange: (e) => handleChange('panel-orientation', e.target.value), style: {
|
|
4947
4920
|
width: '100%',
|
|
4948
4921
|
padding: '8px 12px',
|
|
@@ -4956,6 +4929,8 @@ const PropertyEditor = ({ node, onChange, onDelete, onDuplicate, }) => {
|
|
|
4956
4929
|
border: '1px solid #ccc',
|
|
4957
4930
|
borderRadius: '4px',
|
|
4958
4931
|
fontSize: '12px',
|
|
4932
|
+
background: 'white',
|
|
4933
|
+
color: '#333',
|
|
4959
4934
|
} })] })] }));
|
|
4960
4935
|
};
|
|
4961
4936
|
const renderWidgetProperties = () => {
|
|
@@ -4989,24 +4964,32 @@ const PropertyEditor = ({ node, onChange, onDelete, onDuplicate, }) => {
|
|
|
4989
4964
|
border: '1px solid #ccc',
|
|
4990
4965
|
borderRadius: '4px',
|
|
4991
4966
|
fontSize: '12px',
|
|
4967
|
+
background: 'white',
|
|
4968
|
+
color: '#333',
|
|
4992
4969
|
} })] }), jsxRuntimeExports.jsxs("div", { style: { marginBottom: '20px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '12px', fontWeight: 500 }, children: "Widget Label" }), jsxRuntimeExports.jsx("input", { type: "text", value: widget['widget-label'] || '', onChange: (e) => handleChange('widget-label', e.target.value), style: {
|
|
4993
4970
|
width: '100%',
|
|
4994
4971
|
padding: '8px 12px',
|
|
4995
4972
|
border: '1px solid #ccc',
|
|
4996
4973
|
borderRadius: '4px',
|
|
4997
4974
|
fontSize: '12px',
|
|
4975
|
+
background: 'white',
|
|
4976
|
+
color: '#333',
|
|
4998
4977
|
}, placeholder: "Enter label..." })] }), jsxRuntimeExports.jsxs("div", { style: { marginBottom: '20px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '12px', fontWeight: 500 }, children: "Data Path" }), jsxRuntimeExports.jsx("input", { type: "text", value: typeof widget['widget-data-path'] === 'string' ? widget['widget-data-path'] : '', onChange: (e) => handleChange('widget-data-path', e.target.value), style: {
|
|
4999
4978
|
width: '100%',
|
|
5000
4979
|
padding: '8px 12px',
|
|
5001
4980
|
border: '1px solid #ccc',
|
|
5002
4981
|
borderRadius: '4px',
|
|
5003
4982
|
fontSize: '12px',
|
|
4983
|
+
background: 'white',
|
|
4984
|
+
color: '#333',
|
|
5004
4985
|
}, placeholder: "person.name" })] }), jsxRuntimeExports.jsxs("div", { style: { marginBottom: '20px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '12px', fontWeight: 500 }, children: "Placeholder" }), jsxRuntimeExports.jsx("input", { type: "text", value: widget['widget-data-placeholder'] || '', onChange: (e) => handleChange('widget-data-placeholder', e.target.value), style: {
|
|
5005
4986
|
width: '100%',
|
|
5006
4987
|
padding: '8px 12px',
|
|
5007
4988
|
border: '1px solid #ccc',
|
|
5008
4989
|
borderRadius: '4px',
|
|
5009
4990
|
fontSize: '12px',
|
|
4991
|
+
background: 'white',
|
|
4992
|
+
color: '#333',
|
|
5010
4993
|
}, placeholder: "Enter placeholder..." })] }), jsxRuntimeExports.jsx("div", { style: { marginBottom: '20px' }, children: jsxRuntimeExports.jsxs("label", { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '12px' }, children: [jsxRuntimeExports.jsx("input", { type: "checkbox", checked: widget['widget-required'] || false, onChange: (e) => handleChange('widget-required', e.target.checked) }), jsxRuntimeExports.jsx("span", { children: "Required" })] }) }), jsxRuntimeExports.jsx("div", { style: { marginBottom: '20px' }, children: jsxRuntimeExports.jsxs("label", { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '12px' }, children: [jsxRuntimeExports.jsx("input", { type: "checkbox", checked: widget['widget-readonly'] || false, onChange: (e) => handleChange('widget-readonly', e.target.checked) }), jsxRuntimeExports.jsx("span", { children: "Readonly" })] }) }), ['select', 'radio', 'checkbox'].includes(widget.widget) && (jsxRuntimeExports.jsxs("div", { style: { marginBottom: '20px', padding: '10px', background: '#e3f2fd', borderRadius: '4px' }, children: [jsxRuntimeExports.jsxs("label", { style: { display: 'block', marginBottom: '8px', fontSize: '12px', fontWeight: 600 }, children: ["Data Source (Required for ", widget.widget, ")"] }), jsxRuntimeExports.jsxs("div", { style: { marginBottom: '10px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '11px' }, children: "Source Type" }), jsxRuntimeExports.jsxs("select", { value: widget['widget-data-source']?.type || 'static', onChange: (e) => {
|
|
5011
4994
|
ensureNestedObject('widget-data-source');
|
|
5012
4995
|
handleNestedChange('widget-data-source', 'type', e.target.value);
|
|
@@ -5033,6 +5016,8 @@ const PropertyEditor = ({ node, onChange, onDelete, onDuplicate, }) => {
|
|
|
5033
5016
|
fontSize: '11px',
|
|
5034
5017
|
fontFamily: 'monospace',
|
|
5035
5018
|
minHeight: '80px',
|
|
5019
|
+
background: 'white',
|
|
5020
|
+
color: '#333',
|
|
5036
5021
|
}, placeholder: '[{"value": "opt1", "label": "Option 1"}]' })] })), widget['widget-data-source']?.type === 'api' && (() => {
|
|
5037
5022
|
const apiSource = widget['widget-data-source'];
|
|
5038
5023
|
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { style: { marginBottom: '10px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '11px' }, children: "API URL" }), jsxRuntimeExports.jsx("input", { type: "text", value: apiSource.url || '', onChange: (e) => handleNestedChange('widget-data-source', 'url', e.target.value), style: {
|
|
@@ -5041,18 +5026,24 @@ const PropertyEditor = ({ node, onChange, onDelete, onDuplicate, }) => {
|
|
|
5041
5026
|
border: '1px solid #ccc',
|
|
5042
5027
|
borderRadius: '4px',
|
|
5043
5028
|
fontSize: '11px',
|
|
5029
|
+
background: 'white',
|
|
5030
|
+
color: '#333',
|
|
5044
5031
|
}, placeholder: "https://api.example.com/options" })] }), jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '11px' }, children: "Value/Label Keys (e.g., \"id\"/\"name\")" }), jsxRuntimeExports.jsxs("div", { style: { display: 'flex', gap: '8px' }, children: [jsxRuntimeExports.jsx("input", { type: "text", value: apiSource.valueKey || '', onChange: (e) => handleNestedChange('widget-data-source', 'valueKey', e.target.value), style: {
|
|
5045
5032
|
flex: 1,
|
|
5046
5033
|
padding: '6px 8px',
|
|
5047
5034
|
border: '1px solid #ccc',
|
|
5048
5035
|
borderRadius: '4px',
|
|
5049
5036
|
fontSize: '11px',
|
|
5037
|
+
background: 'white',
|
|
5038
|
+
color: '#333',
|
|
5050
5039
|
}, placeholder: "value key" }), jsxRuntimeExports.jsx("input", { type: "text", value: apiSource.labelKey || '', onChange: (e) => handleNestedChange('widget-data-source', 'labelKey', e.target.value), style: {
|
|
5051
5040
|
flex: 1,
|
|
5052
5041
|
padding: '6px 8px',
|
|
5053
5042
|
border: '1px solid #ccc',
|
|
5054
5043
|
borderRadius: '4px',
|
|
5055
5044
|
fontSize: '11px',
|
|
5045
|
+
background: 'white',
|
|
5046
|
+
color: '#333',
|
|
5056
5047
|
}, placeholder: "label key" })] })] })] }));
|
|
5057
5048
|
})()] })), widget.widget === 'table' && (jsxRuntimeExports.jsxs("div", { style: { marginBottom: '20px', padding: '10px', background: '#fff3e0', borderRadius: '4px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '8px', fontSize: '12px', fontWeight: 600 }, children: "Table Columns" }), jsxRuntimeExports.jsx("div", { style: { fontSize: '11px', color: '#666', marginBottom: '10px' }, children: "Configure columns in JSON editor or add via code" }), jsxRuntimeExports.jsx("textarea", { value: JSON.stringify(widget['widget-data-columns'] || [], null, 2), onChange: (e) => {
|
|
5058
5049
|
try {
|
|
@@ -5070,30 +5061,40 @@ const PropertyEditor = ({ node, onChange, onDelete, onDuplicate, }) => {
|
|
|
5070
5061
|
fontSize: '11px',
|
|
5071
5062
|
fontFamily: 'monospace',
|
|
5072
5063
|
minHeight: '100px',
|
|
5064
|
+
background: 'white',
|
|
5065
|
+
color: '#333',
|
|
5073
5066
|
}, placeholder: '[{"column-key": "col1", "widget-label": "Column 1", "widget": "text"}]' })] })), widget.widget === 'number' && (jsxRuntimeExports.jsxs("div", { style: { marginBottom: '20px', padding: '10px', background: '#f3e5f5', borderRadius: '4px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '8px', fontSize: '12px', fontWeight: 600 }, children: "Number Validation" }), jsxRuntimeExports.jsxs("div", { style: { display: 'flex', gap: '10px', marginBottom: '10px' }, children: [jsxRuntimeExports.jsxs("div", { style: { flex: 1 }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '11px' }, children: "Min Value" }), jsxRuntimeExports.jsx("input", { type: "number", value: widget['widget-data-validation']?.min ?? '', onChange: (e) => handleNestedChange('widget-data-validation', 'min', e.target.value ? parseFloat(e.target.value) : undefined), style: {
|
|
5074
5067
|
width: '100%',
|
|
5075
5068
|
padding: '6px 8px',
|
|
5076
5069
|
border: '1px solid #ccc',
|
|
5077
5070
|
borderRadius: '4px',
|
|
5078
5071
|
fontSize: '11px',
|
|
5072
|
+
background: 'white',
|
|
5073
|
+
color: '#333',
|
|
5079
5074
|
} })] }), jsxRuntimeExports.jsxs("div", { style: { flex: 1 }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '11px' }, children: "Max Value" }), jsxRuntimeExports.jsx("input", { type: "number", value: widget['widget-data-validation']?.max ?? '', onChange: (e) => handleNestedChange('widget-data-validation', 'max', e.target.value ? parseFloat(e.target.value) : undefined), style: {
|
|
5080
5075
|
width: '100%',
|
|
5081
5076
|
padding: '6px 8px',
|
|
5082
5077
|
border: '1px solid #ccc',
|
|
5083
5078
|
borderRadius: '4px',
|
|
5084
5079
|
fontSize: '11px',
|
|
5080
|
+
background: 'white',
|
|
5081
|
+
color: '#333',
|
|
5085
5082
|
} })] })] })] })), ['date', 'datetime'].includes(widget.widget) && (jsxRuntimeExports.jsxs("div", { style: { marginBottom: '20px', padding: '10px', background: '#e8f5e9', borderRadius: '4px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '8px', fontSize: '12px', fontWeight: 600 }, children: "Date Range Options" }), jsxRuntimeExports.jsxs("div", { style: { display: 'flex', gap: '10px', marginBottom: '10px' }, children: [jsxRuntimeExports.jsxs("div", { style: { flex: 1 }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '11px' }, children: "Min Date" }), jsxRuntimeExports.jsx("input", { type: "date", value: widget['widget-data-options']?.minDate || '', onChange: (e) => handleNestedChange('widget-data-options', 'minDate', e.target.value || undefined), style: {
|
|
5086
5083
|
width: '100%',
|
|
5087
5084
|
padding: '6px 8px',
|
|
5088
5085
|
border: '1px solid #ccc',
|
|
5089
5086
|
borderRadius: '4px',
|
|
5090
5087
|
fontSize: '11px',
|
|
5088
|
+
background: 'white',
|
|
5089
|
+
color: '#333',
|
|
5091
5090
|
} })] }), jsxRuntimeExports.jsxs("div", { style: { flex: 1 }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '11px' }, children: "Max Date" }), jsxRuntimeExports.jsx("input", { type: "date", value: widget['widget-data-options']?.maxDate || '', onChange: (e) => handleNestedChange('widget-data-options', 'maxDate', e.target.value || undefined), style: {
|
|
5092
5091
|
width: '100%',
|
|
5093
5092
|
padding: '6px 8px',
|
|
5094
5093
|
border: '1px solid #ccc',
|
|
5095
5094
|
borderRadius: '4px',
|
|
5096
5095
|
fontSize: '11px',
|
|
5096
|
+
background: 'white',
|
|
5097
|
+
color: '#333',
|
|
5097
5098
|
} })] })] }), jsxRuntimeExports.jsxs("label", { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '11px' }, children: [jsxRuntimeExports.jsx("input", { type: "checkbox", checked: widget['widget-data-options']?.showCalendar || false, onChange: (e) => handleNestedChange('widget-data-options', 'showCalendar', e.target.checked) }), jsxRuntimeExports.jsx("span", { children: "Show Calendar" })] })] })), jsxRuntimeExports.jsxs("div", { style: { marginBottom: '20px', padding: '10px', background: '#f0f0f0', borderRadius: '4px' }, children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '8px', fontSize: '12px', fontWeight: 600 }, children: "Validation" }), jsxRuntimeExports.jsx("div", { style: { marginBottom: '10px' }, children: jsxRuntimeExports.jsxs("label", { style: { display: 'flex', alignItems: 'center', gap: '8px', fontSize: '12px' }, children: [jsxRuntimeExports.jsx("input", { type: "checkbox", checked: widget['widget-data-validation']?.required || false, onChange: (e) => {
|
|
5098
5099
|
if (!widget['widget-data-validation']) {
|
|
5099
5100
|
handleChange('widget-data-validation', { required: e.target.checked });
|
|
@@ -5113,6 +5114,8 @@ const PropertyEditor = ({ node, onChange, onDelete, onDuplicate, }) => {
|
|
|
5113
5114
|
border: '1px solid #ccc',
|
|
5114
5115
|
borderRadius: '4px',
|
|
5115
5116
|
fontSize: '11px',
|
|
5117
|
+
background: 'white',
|
|
5118
|
+
color: '#333',
|
|
5116
5119
|
} })] }), jsxRuntimeExports.jsxs("div", { children: [jsxRuntimeExports.jsx("label", { style: { display: 'block', marginBottom: '5px', fontSize: '11px' }, children: "Max Length" }), jsxRuntimeExports.jsx("input", { type: "number", value: widget['widget-data-validation']?.maxLength || '', onChange: (e) => {
|
|
5117
5120
|
const validation = widget['widget-data-validation'] || {};
|
|
5118
5121
|
handleChange('widget-data-validation', {
|
|
@@ -5125,6 +5128,8 @@ const PropertyEditor = ({ node, onChange, onDelete, onDuplicate, }) => {
|
|
|
5125
5128
|
border: '1px solid #ccc',
|
|
5126
5129
|
borderRadius: '4px',
|
|
5127
5130
|
fontSize: '11px',
|
|
5131
|
+
background: 'white',
|
|
5132
|
+
color: '#333',
|
|
5128
5133
|
} })] })] }))] })] }));
|
|
5129
5134
|
};
|
|
5130
5135
|
const getHeaderColor = () => {
|
|
@@ -5154,7 +5159,7 @@ const PropertyEditor = ({ node, onChange, onDelete, onDuplicate, }) => {
|
|
|
5154
5159
|
flex: 1,
|
|
5155
5160
|
padding: '10px',
|
|
5156
5161
|
border: 'none',
|
|
5157
|
-
borderRadius: '
|
|
5162
|
+
borderRadius: '10px',
|
|
5158
5163
|
background: '#f44336',
|
|
5159
5164
|
color: 'white',
|
|
5160
5165
|
fontWeight: 600,
|
|
@@ -5164,7 +5169,7 @@ const PropertyEditor = ({ node, onChange, onDelete, onDuplicate, }) => {
|
|
|
5164
5169
|
flex: 1,
|
|
5165
5170
|
padding: '10px',
|
|
5166
5171
|
border: 'none',
|
|
5167
|
-
borderRadius: '
|
|
5172
|
+
borderRadius: '10px',
|
|
5168
5173
|
background: '#ff9800',
|
|
5169
5174
|
color: 'white',
|
|
5170
5175
|
fontWeight: 600,
|
|
@@ -5323,17 +5328,18 @@ const VisualBuilderPanel = ({ section, selectedNode, onSelectNode, onSectionChan
|
|
|
5323
5328
|
height: '100%',
|
|
5324
5329
|
width: '100%',
|
|
5325
5330
|
minHeight: 0,
|
|
5331
|
+
paddingBottom: '10px',
|
|
5332
|
+
borderRight: '0px',
|
|
5326
5333
|
}, children: [jsxRuntimeExports.jsxs("div", { style: {
|
|
5327
|
-
padding: '
|
|
5334
|
+
padding: '20px 20px 20px 20px',
|
|
5328
5335
|
background: '#ffffff',
|
|
5329
|
-
borderBottom: '1px solid #ddd',
|
|
5330
5336
|
display: 'flex',
|
|
5331
5337
|
justifyContent: 'space-between',
|
|
5332
5338
|
alignItems: 'center',
|
|
5333
|
-
}, children: [jsxRuntimeExports.jsx("div", { style: { fontWeight: 600, fontSize: '16px', color: '#2c3e50' }, children: "Visual Builder" }), jsxRuntimeExports.jsxs("div", { style: { display: 'flex', gap: '10px' }, children: [jsxRuntimeExports.jsx("button", { onClick: handleAddPanel, style: {
|
|
5339
|
+
}, children: [jsxRuntimeExports.jsx("div", { style: { fontWeight: 600, fontSize: '16px', color: '#2c3e50', paddingTop: '5px' }, children: "Visual Builder" }), jsxRuntimeExports.jsxs("div", { style: { display: 'flex', gap: '10px' }, children: [jsxRuntimeExports.jsx("button", { onClick: handleAddPanel, style: {
|
|
5334
5340
|
padding: '8px 16px',
|
|
5335
5341
|
border: 'none',
|
|
5336
|
-
borderRadius: '
|
|
5342
|
+
borderRadius: '10px',
|
|
5337
5343
|
background: '#2196f3',
|
|
5338
5344
|
color: 'white',
|
|
5339
5345
|
fontWeight: 600,
|
|
@@ -5343,7 +5349,7 @@ const VisualBuilderPanel = ({ section, selectedNode, onSelectNode, onSectionChan
|
|
|
5343
5349
|
}, children: "+ Add Panel" }), jsxRuntimeExports.jsx("button", { onClick: handleAddWidget, style: {
|
|
5344
5350
|
padding: '8px 16px',
|
|
5345
5351
|
border: 'none',
|
|
5346
|
-
borderRadius: '
|
|
5352
|
+
borderRadius: '10px',
|
|
5347
5353
|
background: '#4caf50',
|
|
5348
5354
|
color: 'white',
|
|
5349
5355
|
fontWeight: 600,
|
|
@@ -5353,8 +5359,8 @@ const VisualBuilderPanel = ({ section, selectedNode, onSelectNode, onSectionChan
|
|
|
5353
5359
|
}, children: "+ Add Widget" }), onSave && (jsxRuntimeExports.jsx("button", { onClick: handleSave, style: {
|
|
5354
5360
|
padding: '8px 16px',
|
|
5355
5361
|
border: 'none',
|
|
5356
|
-
borderRadius: '
|
|
5357
|
-
background: '#
|
|
5362
|
+
borderRadius: '10px',
|
|
5363
|
+
background: '#000000',
|
|
5358
5364
|
color: 'white',
|
|
5359
5365
|
fontWeight: 600,
|
|
5360
5366
|
cursor: 'pointer',
|
|
@@ -5376,6 +5382,8 @@ const VisualBuilderPanel = ({ section, selectedNode, onSelectNode, onSectionChan
|
|
|
5376
5382
|
flex: 1,
|
|
5377
5383
|
display: 'flex',
|
|
5378
5384
|
overflow: 'hidden',
|
|
5385
|
+
border: '1px solid #ddd',
|
|
5386
|
+
borderRadius: '10px',
|
|
5379
5387
|
minHeight: 0, // Important for flex children to respect overflow
|
|
5380
5388
|
}, children: [jsxRuntimeExports.jsx("div", { style: {
|
|
5381
5389
|
width: '45%',
|
|
@@ -5435,77 +5443,6 @@ const SectionBuilder = ({ initialSection, onChange, onSave, }) => {
|
|
|
5435
5443
|
onChange(original);
|
|
5436
5444
|
}
|
|
5437
5445
|
}, [onChange]);
|
|
5438
|
-
// Handle node selection from JSON editor
|
|
5439
|
-
const handleSelectNodeFromJson = React.useCallback((nodeId, nodeType) => {
|
|
5440
|
-
// Find the corresponding node in the section structure
|
|
5441
|
-
const findNode = () => {
|
|
5442
|
-
if (nodeType === 'section') {
|
|
5443
|
-
return {
|
|
5444
|
-
type: 'section',
|
|
5445
|
-
id: section['section-id'],
|
|
5446
|
-
label: `Section: ${section['section-id']}`,
|
|
5447
|
-
data: section,
|
|
5448
|
-
};
|
|
5449
|
-
}
|
|
5450
|
-
// Recursively search for panel or widget
|
|
5451
|
-
const searchInPanels = (panels, parent) => {
|
|
5452
|
-
for (const panel of panels) {
|
|
5453
|
-
if (nodeType === 'panel' && panel['panel-id'] === nodeId) {
|
|
5454
|
-
return {
|
|
5455
|
-
type: 'panel',
|
|
5456
|
-
id: panel['panel-id'],
|
|
5457
|
-
label: `Panel: ${panel['panel-id']}`,
|
|
5458
|
-
data: panel,
|
|
5459
|
-
parent: parent,
|
|
5460
|
-
};
|
|
5461
|
-
}
|
|
5462
|
-
// Check nested panels
|
|
5463
|
-
if (panel.panels) {
|
|
5464
|
-
const panelNode = {
|
|
5465
|
-
type: 'panel',
|
|
5466
|
-
id: panel['panel-id'],
|
|
5467
|
-
label: `Panel: ${panel['panel-id']}`,
|
|
5468
|
-
data: panel,
|
|
5469
|
-
parent: parent,
|
|
5470
|
-
};
|
|
5471
|
-
const found = searchInPanels(panel.panels, panelNode);
|
|
5472
|
-
if (found)
|
|
5473
|
-
return found;
|
|
5474
|
-
}
|
|
5475
|
-
// Check widgets
|
|
5476
|
-
if (panel.widgets) {
|
|
5477
|
-
const panelNode = {
|
|
5478
|
-
type: 'panel',
|
|
5479
|
-
id: panel['panel-id'],
|
|
5480
|
-
label: `Panel: ${panel['panel-id']}`,
|
|
5481
|
-
data: panel,
|
|
5482
|
-
parent: parent,
|
|
5483
|
-
};
|
|
5484
|
-
for (const widget of panel.widgets) {
|
|
5485
|
-
if (nodeType === 'widget' && widget['widget-id'] === nodeId) {
|
|
5486
|
-
return {
|
|
5487
|
-
type: 'widget',
|
|
5488
|
-
id: widget['widget-id'],
|
|
5489
|
-
label: `Widget: ${widget['widget-id']} (${widget.widget})`,
|
|
5490
|
-
data: widget,
|
|
5491
|
-
parent: panelNode,
|
|
5492
|
-
};
|
|
5493
|
-
}
|
|
5494
|
-
}
|
|
5495
|
-
}
|
|
5496
|
-
}
|
|
5497
|
-
return null;
|
|
5498
|
-
};
|
|
5499
|
-
if (section.panels) {
|
|
5500
|
-
return searchInPanels(section.panels);
|
|
5501
|
-
}
|
|
5502
|
-
return null;
|
|
5503
|
-
};
|
|
5504
|
-
const node = findNode();
|
|
5505
|
-
if (node) {
|
|
5506
|
-
setSelectedNode(node);
|
|
5507
|
-
}
|
|
5508
|
-
}, [section]);
|
|
5509
5446
|
const handleAddPanel = React.useCallback((parentId, parentType) => {
|
|
5510
5447
|
const updatedSection = JSON.parse(JSON.stringify(section));
|
|
5511
5448
|
const newPanel = {
|
|
@@ -5685,7 +5622,7 @@ const SectionBuilder = ({ initialSection, onChange, onSave, }) => {
|
|
|
5685
5622
|
padding: '10px 10px 10px 10px',
|
|
5686
5623
|
flexDirection: 'column',
|
|
5687
5624
|
borderRight: '0px',
|
|
5688
|
-
}, children: jsxRuntimeExports.jsx(JSONEditorPanel, { section: section, onChange: handleSectionChange, onReset: handleReset
|
|
5625
|
+
}, children: jsxRuntimeExports.jsx(JSONEditorPanel, { section: section, onChange: handleSectionChange, onReset: handleReset }) }), jsxRuntimeExports.jsx("div", { style: {
|
|
5689
5626
|
width: '50%',
|
|
5690
5627
|
height: '100%',
|
|
5691
5628
|
minHeight: 0,
|
|
@@ -7515,8 +7452,41 @@ const CurrencyInputWidget = ({ config }) => {
|
|
|
7515
7452
|
const DisplayWidget = ({ config }) => {
|
|
7516
7453
|
const { value, formattedValue, config: widgetConfig, } = useBaseWidget({ config });
|
|
7517
7454
|
const { translateConfig } = useWidgetTranslation();
|
|
7518
|
-
//
|
|
7519
|
-
const
|
|
7455
|
+
// Helper to safely convert value to display string
|
|
7456
|
+
const getDisplayValue = (val) => {
|
|
7457
|
+
if (val === null || val === undefined) {
|
|
7458
|
+
return '';
|
|
7459
|
+
}
|
|
7460
|
+
// If it's already a string or number, return as string
|
|
7461
|
+
if (typeof val === 'string' || typeof val === 'number') {
|
|
7462
|
+
return String(val);
|
|
7463
|
+
}
|
|
7464
|
+
// If it's an object (like geo hierarchy), try to extract a meaningful value
|
|
7465
|
+
if (typeof val === 'object' && !Array.isArray(val)) {
|
|
7466
|
+
// For geo hierarchy objects, try to extract the actual value
|
|
7467
|
+
if ('geo_lowest_level_value_id' in val) {
|
|
7468
|
+
return String(val.geo_lowest_level_value_id || '');
|
|
7469
|
+
}
|
|
7470
|
+
if ('value' in val) {
|
|
7471
|
+
return String(val.value || '');
|
|
7472
|
+
}
|
|
7473
|
+
if ('id' in val) {
|
|
7474
|
+
return String(val.id || '');
|
|
7475
|
+
}
|
|
7476
|
+
// If no extractable value, return empty string to avoid rendering object
|
|
7477
|
+
return '';
|
|
7478
|
+
}
|
|
7479
|
+
// For arrays, join them or return empty
|
|
7480
|
+
if (Array.isArray(val)) {
|
|
7481
|
+
return val.length > 0 ? val.map(String).join(', ') : '';
|
|
7482
|
+
}
|
|
7483
|
+
// Fallback: convert to string
|
|
7484
|
+
return String(val);
|
|
7485
|
+
};
|
|
7486
|
+
// Use formatted value if available, otherwise safely convert raw value
|
|
7487
|
+
const displayValue = formattedValue !== undefined
|
|
7488
|
+
? (typeof formattedValue === 'object' ? getDisplayValue(formattedValue) : String(formattedValue))
|
|
7489
|
+
: getDisplayValue(value);
|
|
7520
7490
|
const label = translateConfig(widgetConfig['widget-label']);
|
|
7521
7491
|
// If no label, render as paragraph text
|
|
7522
7492
|
if (!label || label.trim() === '') {
|