@openg2p/registry-widgets 1.0.2 → 1.1.0-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -1
- package/dist/components/SectionBuilder/schemas.d.ts +4 -0
- package/dist/components/SectionBuilder/schemas.d.ts.map +1 -1
- package/dist/components/SectionRenderer.d.ts +0 -1
- package/dist/components/SectionRenderer.d.ts.map +1 -1
- package/dist/components/SectionsContainer.d.ts.map +1 -1
- package/dist/components/WidgetProvider.d.ts +4 -1
- package/dist/components/WidgetProvider.d.ts.map +1 -1
- package/dist/index.d.ts +168 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +710 -338
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +713 -337
- package/dist/index.js.map +1 -1
- package/dist/registry/defaultWidgets.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/widgets/DisplayWidget.d.ts.map +1 -1
- package/dist/widgets/HeaderSectionWidget.d.ts.map +1 -1
- package/dist/widgets/ProfileWidget.d.ts +2 -2
- package/dist/widgets/ScoresDisplayWidget.d.ts +32 -0
- package/dist/widgets/ScoresDisplayWidget.d.ts.map +1 -0
- package/dist/widgets/TableWidget.d.ts.map +1 -1
- package/dist/widgets/index.d.ts +1 -0
- package/dist/widgets/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1676,6 +1676,158 @@ class WidgetEventBus {
|
|
|
1676
1676
|
}
|
|
1677
1677
|
}
|
|
1678
1678
|
|
|
1679
|
+
/**
|
|
1680
|
+
* Built-in default values (matches the original hardcoded colours).
|
|
1681
|
+
*/
|
|
1682
|
+
const defaultTheme = {
|
|
1683
|
+
colors: {
|
|
1684
|
+
primary: '#F5BB1A',
|
|
1685
|
+
primaryDark: '#F07B1A',
|
|
1686
|
+
primaryLight: '#FBE6AA',
|
|
1687
|
+
primaryAccent: '#EE7C22',
|
|
1688
|
+
border: '#C4C4C4',
|
|
1689
|
+
borderLight: '#E4E4E4',
|
|
1690
|
+
background: '#FFFFFF',
|
|
1691
|
+
backgroundAlt: '#F6F6F6',
|
|
1692
|
+
text: '#011627',
|
|
1693
|
+
textMuted: '#727474',
|
|
1694
|
+
success: '#16A34A',
|
|
1695
|
+
successDark: '#047857',
|
|
1696
|
+
successLight: '#D1FAE5',
|
|
1697
|
+
error: '#B91C1C',
|
|
1698
|
+
errorLight: '#FEE2E2',
|
|
1699
|
+
warning: '#F59E0B',
|
|
1700
|
+
info: '#2563EB',
|
|
1701
|
+
},
|
|
1702
|
+
section: {
|
|
1703
|
+
borderRadius: '8px',
|
|
1704
|
+
borderColor: '#E4E4E4',
|
|
1705
|
+
backgroundColor: '#FFFFFF',
|
|
1706
|
+
titleColor: '#011627',
|
|
1707
|
+
dividerColor: '#F5BB1A',
|
|
1708
|
+
},
|
|
1709
|
+
panel: {
|
|
1710
|
+
dividerColor: '#C4C4C4',
|
|
1711
|
+
backgroundColor: 'transparent',
|
|
1712
|
+
},
|
|
1713
|
+
button: {
|
|
1714
|
+
primaryBg: '#FFFFFF',
|
|
1715
|
+
primaryColor: '#011627',
|
|
1716
|
+
primaryBorder: '#F07B1A',
|
|
1717
|
+
secondaryBg: '#FFFFFF',
|
|
1718
|
+
secondaryColor: '#011627',
|
|
1719
|
+
secondaryBorder: '#C4C4C4',
|
|
1720
|
+
borderRadius: '6px',
|
|
1721
|
+
},
|
|
1722
|
+
widget: {
|
|
1723
|
+
labelColor: '#011627',
|
|
1724
|
+
inputBorderColor: '#C4C4C4',
|
|
1725
|
+
inputFocusBorderColor: '#F5BB1A',
|
|
1726
|
+
inputBackground: '#FFFFFF',
|
|
1727
|
+
errorColor: '#B91C1C',
|
|
1728
|
+
helpTextColor: '#727474',
|
|
1729
|
+
tableHeaderBg: '#F6F6F6',
|
|
1730
|
+
tableHeaderColor: '#727474',
|
|
1731
|
+
tableBodyBg: '#FFFFFF',
|
|
1732
|
+
tableBorderColor: '#C4C4C4',
|
|
1733
|
+
tableRowDividerColor: '#E4E4E4',
|
|
1734
|
+
tableEditingRowBg: '#FBE6AA',
|
|
1735
|
+
tableDeletedRowBg: '#FEE2E2',
|
|
1736
|
+
tableEmptyTextColor: '#727474',
|
|
1737
|
+
tableBorderRadius: '15px',
|
|
1738
|
+
},
|
|
1739
|
+
};
|
|
1740
|
+
/**
|
|
1741
|
+
* Merge a user-supplied (partial) theme with the built-in defaults.
|
|
1742
|
+
*/
|
|
1743
|
+
function resolveTheme(theme) {
|
|
1744
|
+
if (!theme)
|
|
1745
|
+
return defaultTheme;
|
|
1746
|
+
return {
|
|
1747
|
+
colors: { ...defaultTheme.colors, ...theme.colors },
|
|
1748
|
+
section: { ...defaultTheme.section, ...theme.section },
|
|
1749
|
+
panel: { ...defaultTheme.panel, ...theme.panel },
|
|
1750
|
+
button: { ...defaultTheme.button, ...theme.button },
|
|
1751
|
+
widget: { ...defaultTheme.widget, ...theme.widget },
|
|
1752
|
+
};
|
|
1753
|
+
}
|
|
1754
|
+
/**
|
|
1755
|
+
* Convert a resolved theme into a flat Record of CSS custom properties.
|
|
1756
|
+
* These are set on the provider wrapper element so every descendant can
|
|
1757
|
+
* reference them with `var(--owt-…)`.
|
|
1758
|
+
*
|
|
1759
|
+
* Prefix: `--owt-` (OpenG2P Widget Theme).
|
|
1760
|
+
*/
|
|
1761
|
+
function themeToCSSVariables(resolved) {
|
|
1762
|
+
return {
|
|
1763
|
+
// --- colors ---
|
|
1764
|
+
'--owt-color-primary': resolved.colors.primary,
|
|
1765
|
+
'--owt-color-primary-dark': resolved.colors.primaryDark,
|
|
1766
|
+
'--owt-color-primary-light': resolved.colors.primaryLight,
|
|
1767
|
+
'--owt-color-primary-accent': resolved.colors.primaryAccent,
|
|
1768
|
+
'--owt-color-border': resolved.colors.border,
|
|
1769
|
+
'--owt-color-border-light': resolved.colors.borderLight,
|
|
1770
|
+
'--owt-color-bg': resolved.colors.background,
|
|
1771
|
+
'--owt-color-bg-alt': resolved.colors.backgroundAlt,
|
|
1772
|
+
'--owt-color-text': resolved.colors.text,
|
|
1773
|
+
'--owt-color-text-muted': resolved.colors.textMuted,
|
|
1774
|
+
'--owt-color-success': resolved.colors.success,
|
|
1775
|
+
'--owt-color-success-dark': resolved.colors.successDark,
|
|
1776
|
+
'--owt-color-success-light': resolved.colors.successLight,
|
|
1777
|
+
'--owt-color-error': resolved.colors.error,
|
|
1778
|
+
'--owt-color-error-light': resolved.colors.errorLight,
|
|
1779
|
+
'--owt-color-warning': resolved.colors.warning,
|
|
1780
|
+
'--owt-color-info': resolved.colors.info,
|
|
1781
|
+
// --- section ---
|
|
1782
|
+
'--owt-section-border-radius': resolved.section.borderRadius,
|
|
1783
|
+
'--owt-section-border-color': resolved.section.borderColor,
|
|
1784
|
+
'--owt-section-bg': resolved.section.backgroundColor,
|
|
1785
|
+
'--owt-section-title-color': resolved.section.titleColor,
|
|
1786
|
+
'--owt-section-divider-color': resolved.section.dividerColor,
|
|
1787
|
+
// --- panel ---
|
|
1788
|
+
'--owt-panel-divider-color': resolved.panel.dividerColor,
|
|
1789
|
+
'--owt-panel-bg': resolved.panel.backgroundColor,
|
|
1790
|
+
// --- button ---
|
|
1791
|
+
'--owt-btn-primary-bg': resolved.button.primaryBg,
|
|
1792
|
+
'--owt-btn-primary-color': resolved.button.primaryColor,
|
|
1793
|
+
'--owt-btn-primary-border': resolved.button.primaryBorder,
|
|
1794
|
+
'--owt-btn-secondary-bg': resolved.button.secondaryBg,
|
|
1795
|
+
'--owt-btn-secondary-color': resolved.button.secondaryColor,
|
|
1796
|
+
'--owt-btn-secondary-border': resolved.button.secondaryBorder,
|
|
1797
|
+
'--owt-btn-border-radius': resolved.button.borderRadius,
|
|
1798
|
+
// --- widget ---
|
|
1799
|
+
'--owt-widget-label-color': resolved.widget.labelColor,
|
|
1800
|
+
'--owt-widget-input-border': resolved.widget.inputBorderColor,
|
|
1801
|
+
'--owt-widget-input-focus-border': resolved.widget.inputFocusBorderColor,
|
|
1802
|
+
'--owt-widget-input-bg': resolved.widget.inputBackground,
|
|
1803
|
+
'--owt-widget-error-color': resolved.widget.errorColor,
|
|
1804
|
+
'--owt-widget-helptext-color': resolved.widget.helpTextColor,
|
|
1805
|
+
// --- widget / table ---
|
|
1806
|
+
'--owt-widget-table-header-bg': resolved.widget.tableHeaderBg,
|
|
1807
|
+
'--owt-widget-table-header-color': resolved.widget.tableHeaderColor,
|
|
1808
|
+
'--owt-widget-table-body-bg': resolved.widget.tableBodyBg,
|
|
1809
|
+
'--owt-widget-table-border-color': resolved.widget.tableBorderColor,
|
|
1810
|
+
'--owt-widget-table-row-divider': resolved.widget.tableRowDividerColor,
|
|
1811
|
+
'--owt-widget-table-editing-row-bg': resolved.widget.tableEditingRowBg,
|
|
1812
|
+
'--owt-widget-table-deleted-row-bg': resolved.widget.tableDeletedRowBg,
|
|
1813
|
+
'--owt-widget-table-empty-color': resolved.widget.tableEmptyTextColor,
|
|
1814
|
+
'--owt-widget-table-border-radius': resolved.widget.tableBorderRadius,
|
|
1815
|
+
};
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
const ThemeContext = React.createContext(defaultTheme);
|
|
1819
|
+
/**
|
|
1820
|
+
* Access the resolved widget theme from any component inside `<WidgetProvider>`.
|
|
1821
|
+
*
|
|
1822
|
+
* ```tsx
|
|
1823
|
+
* const theme = useWidgetTheme();
|
|
1824
|
+
* // theme.colors.primary, theme.section.dividerColor, etc.
|
|
1825
|
+
* ```
|
|
1826
|
+
*/
|
|
1827
|
+
function useWidgetTheme() {
|
|
1828
|
+
return React.useContext(ThemeContext);
|
|
1829
|
+
}
|
|
1830
|
+
|
|
1679
1831
|
const WidgetContext = React.createContext({
|
|
1680
1832
|
dataSourceRequestHandler: undefined,
|
|
1681
1833
|
schemaData: undefined,
|
|
@@ -1684,10 +1836,13 @@ const WidgetContext = React.createContext({
|
|
|
1684
1836
|
const useWidgetContext = () => {
|
|
1685
1837
|
return React.useContext(WidgetContext);
|
|
1686
1838
|
};
|
|
1687
|
-
const WidgetProvider = ({ store, dataSourceRequestHandler, schemaData, translate, children, }) => {
|
|
1839
|
+
const WidgetProvider = ({ store, dataSourceRequestHandler, schemaData, translate, theme, children, }) => {
|
|
1688
1840
|
const widgetStore = React.useMemo(() => store || createWidgetStore(), [store]);
|
|
1689
1841
|
// Create event bus instance (one per provider)
|
|
1690
1842
|
const eventBus = React.useMemo(() => new WidgetEventBus(), []);
|
|
1843
|
+
// Resolve theme: merge user-supplied overrides with defaults
|
|
1844
|
+
const resolvedTheme = React.useMemo(() => resolveTheme(theme), [theme]);
|
|
1845
|
+
const cssVariables = React.useMemo(() => themeToCSSVariables(resolvedTheme), [resolvedTheme]);
|
|
1691
1846
|
// Memoize context value to prevent unnecessary re-renders
|
|
1692
1847
|
const contextValue = React.useMemo(() => ({
|
|
1693
1848
|
dataSourceRequestHandler,
|
|
@@ -1716,7 +1871,7 @@ const WidgetProvider = ({ store, dataSourceRequestHandler, schemaData, translate
|
|
|
1716
1871
|
}
|
|
1717
1872
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1718
1873
|
}, [schemaData, widgetStore]); // Only run on mount
|
|
1719
|
-
const content = (jsxRuntimeExports.jsx(reactRedux.Provider, { store: widgetStore, children: jsxRuntimeExports.jsx(WidgetContext.Provider, { value: contextValue, children: jsxRuntimeExports.jsx(WidgetEventBusContext.Provider, { value: eventBus, children: children }) }) }));
|
|
1874
|
+
const content = (jsxRuntimeExports.jsx(reactRedux.Provider, { store: widgetStore, children: jsxRuntimeExports.jsx(ThemeContext.Provider, { value: resolvedTheme, children: jsxRuntimeExports.jsx(WidgetContext.Provider, { value: contextValue, children: jsxRuntimeExports.jsx(WidgetEventBusContext.Provider, { value: eventBus, children: jsxRuntimeExports.jsx("div", { className: "openg2p-widget-theme-root", style: cssVariables, children: children }) }) }) }) }));
|
|
1720
1875
|
return content;
|
|
1721
1876
|
};
|
|
1722
1877
|
|
|
@@ -2736,7 +2891,7 @@ const PanelRenderer = ({ panel, dataSourceRequestHandler, schemaData, onValueCha
|
|
|
2736
2891
|
top: 0,
|
|
2737
2892
|
bottom: '5px',
|
|
2738
2893
|
width: '1px',
|
|
2739
|
-
backgroundColor: isEditMode ? '#
|
|
2894
|
+
backgroundColor: isEditMode ? 'var(--owt-color-primary, #F5BB1A)' : 'var(--owt-panel-divider-color, #C4C4C4)',
|
|
2740
2895
|
} }))] }) }, nestedPanel['panel-id'] || `panel-${index}`));
|
|
2741
2896
|
}), widgets.map((widgetConfig, index) => {
|
|
2742
2897
|
// Don't use readonly state in key - it causes remounting which resets userHasSetValueRef
|
|
@@ -3298,10 +3453,10 @@ const FileInputWidget = ({ config }) => {
|
|
|
3298
3453
|
return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("button", { type: "button", onClick: (e) => {
|
|
3299
3454
|
console.log('Button clicked!', file);
|
|
3300
3455
|
handleFileClick(file, e);
|
|
3301
|
-
}, className: "text-sm hover:underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 rounded cursor-pointer", style: { color: isSupportingDocument ? '#
|
|
3456
|
+
}, className: "text-sm hover:underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 rounded cursor-pointer", style: { color: isSupportingDocument ? 'var(--owt-color-text, #011627)' : 'var(--owt-color-info, #2563eb)' }, title: "Click to preview", children: fileName })] }));
|
|
3302
3457
|
}
|
|
3303
3458
|
else {
|
|
3304
|
-
return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("span", { className: "text-sm", style: { color: isSupportingDocument ? '#
|
|
3459
|
+
return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("span", { className: "text-sm", style: { color: isSupportingDocument ? 'var(--owt-color-text, #011627)' : '#4b5563' }, children: fileName })] }));
|
|
3305
3460
|
}
|
|
3306
3461
|
}
|
|
3307
3462
|
else {
|
|
@@ -3317,10 +3472,10 @@ const FileInputWidget = ({ config }) => {
|
|
|
3317
3472
|
flexShrink: 0
|
|
3318
3473
|
} }));
|
|
3319
3474
|
if (canPreview) {
|
|
3320
|
-
return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("button", { type: "button", onClick: (e) => handleFileClick(file, e), className: "text-sm hover:underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 rounded cursor-pointer", style: { color: isSupportingDocument ? '#
|
|
3475
|
+
return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("button", { type: "button", onClick: (e) => handleFileClick(file, e), className: "text-sm hover:underline focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-1 rounded cursor-pointer", style: { color: isSupportingDocument ? 'var(--owt-color-text, #011627)' : 'var(--owt-color-info, #2563eb)' }, title: "Click to preview", children: fileName })] }, index));
|
|
3321
3476
|
}
|
|
3322
3477
|
else {
|
|
3323
|
-
return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("span", { className: "text-sm", style: { color: isSupportingDocument ? '#
|
|
3478
|
+
return (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', alignItems: 'center' }, children: [fileIconElement, jsxRuntimeExports.jsx("span", { className: "text-sm", style: { color: isSupportingDocument ? 'var(--owt-color-text, #011627)' : '#4b5563' }, children: fileName })] }, index));
|
|
3324
3479
|
}
|
|
3325
3480
|
}) }));
|
|
3326
3481
|
}
|
|
@@ -3516,39 +3671,6 @@ const sectionValidate = (section, currentSchemaData, dispatch) => {
|
|
|
3516
3671
|
return isValid;
|
|
3517
3672
|
};
|
|
3518
3673
|
|
|
3519
|
-
/** Root class on readonly label/value rows; SectionRenderer scopes overflow/ellipsis rules here. */
|
|
3520
|
-
const READONLY_VALUE_ROW_ROOT_CLASSES = [
|
|
3521
|
-
'TextDisplayWidget',
|
|
3522
|
-
'TextAreaDisplayWidget',
|
|
3523
|
-
'SelectDisplayWidget',
|
|
3524
|
-
'PhoneDisplayWidget',
|
|
3525
|
-
'NumberDisplayWidget',
|
|
3526
|
-
'CurrencyDisplayWidget',
|
|
3527
|
-
'RadioDisplayWidget',
|
|
3528
|
-
'DateDisplayWidget',
|
|
3529
|
-
'DateTimeDisplayWidget',
|
|
3530
|
-
'CheckboxDisplayWidget',
|
|
3531
|
-
'BooleanDisplayWidget',
|
|
3532
|
-
'FileDisplayWidget',
|
|
3533
|
-
'DisplayFieldWidget',
|
|
3534
|
-
];
|
|
3535
|
-
/** Rows whose value is one line in .flex-1 > .text-gray-900 (ellipsis; full string via title on the element). */
|
|
3536
|
-
const READONLY_SINGLE_LINE_VALUE_ROW_CLASSES = [
|
|
3537
|
-
'TextDisplayWidget',
|
|
3538
|
-
'SelectDisplayWidget',
|
|
3539
|
-
'PhoneDisplayWidget',
|
|
3540
|
-
'NumberDisplayWidget',
|
|
3541
|
-
'CurrencyDisplayWidget',
|
|
3542
|
-
'RadioDisplayWidget',
|
|
3543
|
-
'DateDisplayWidget',
|
|
3544
|
-
'DateTimeDisplayWidget',
|
|
3545
|
-
'CheckboxDisplayWidget',
|
|
3546
|
-
'BooleanDisplayWidget',
|
|
3547
|
-
'DisplayFieldWidget',
|
|
3548
|
-
];
|
|
3549
|
-
function scopedClassSelectors(sectionClassId, classNames) {
|
|
3550
|
-
return classNames.map((c) => `.${sectionClassId} .${c}`).join(',\n ');
|
|
3551
|
-
}
|
|
3552
3674
|
/**
|
|
3553
3675
|
* Renders a section with its panels
|
|
3554
3676
|
*
|
|
@@ -3559,6 +3681,8 @@ function scopedClassSelectors(sectionClassId, classNames) {
|
|
|
3559
3681
|
*/
|
|
3560
3682
|
const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequestHandler, schemaData, onValueChange, gridColumnSpan, onSectionSave, hideEditButton = false, mode = 'RegistryView', namespace, changeRequestType, showChangeRequestLabel = true, dbSectionId, sectionRegisterId, onSectionDirtyChange, sectionIndex, sectionCount, expandedSectionIndex, onExpandSection, onSectionSaveSuccess, onPreviousSection, isDraft, onEditModeChange, forceExitEdit, }) => {
|
|
3561
3683
|
const { translateConfig, translate } = useWidgetTranslation();
|
|
3684
|
+
const resolvedTheme = useWidgetTheme();
|
|
3685
|
+
const portalCSSVariables = React.useMemo(() => themeToCSSVariables(resolvedTheme), [resolvedTheme]);
|
|
3562
3686
|
const { schemaData: contextSchemaData, dataSourceRequestHandler: contextDataSourceRequestHandler } = useWidgetContext();
|
|
3563
3687
|
const store = reactRedux.useStore();
|
|
3564
3688
|
const dispatch = reactRedux.useDispatch();
|
|
@@ -3575,22 +3699,41 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
3575
3699
|
}
|
|
3576
3700
|
return section;
|
|
3577
3701
|
}, [section, namespace]);
|
|
3578
|
-
// Create namespaced schemaData if namespace is provided
|
|
3579
|
-
//
|
|
3580
|
-
// need a nested object at values[namespace] so getValueByPath can traverse it.
|
|
3702
|
+
// Create namespaced schemaData if namespace is provided
|
|
3703
|
+
// This ensures widgets can read initial values from schemaData at namespaced paths
|
|
3581
3704
|
const namespacedSchemaData = React.useMemo(() => {
|
|
3582
3705
|
if (!namespace || !currentSchemaData) {
|
|
3583
3706
|
return schemaData;
|
|
3584
3707
|
}
|
|
3585
|
-
|
|
3708
|
+
// Create a namespaced version of schemaData by copying values to namespaced paths
|
|
3709
|
+
const namespaced = { ...currentSchemaData };
|
|
3710
|
+
// Copy all top-level keys to namespaced paths
|
|
3711
|
+
Object.keys(currentSchemaData).forEach(key => {
|
|
3712
|
+
const namespacedKey = `${namespace}.${key}`;
|
|
3713
|
+
if (!(namespacedKey in namespaced)) {
|
|
3714
|
+
namespaced[namespacedKey] = currentSchemaData[key];
|
|
3715
|
+
}
|
|
3716
|
+
});
|
|
3717
|
+
// Also handle nested objects - copy nested values to namespaced paths
|
|
3718
|
+
const copyNestedValues = (obj, prefix = '') => {
|
|
3719
|
+
if (obj && typeof obj === 'object' && !Array.isArray(obj)) {
|
|
3720
|
+
Object.keys(obj).forEach(key => {
|
|
3721
|
+
const fullPath = prefix ? `${prefix}.${key}` : key;
|
|
3722
|
+
const namespacedPath = `${namespace}.${fullPath}`;
|
|
3723
|
+
if (typeof obj[key] === 'object' && obj[key] !== null && !Array.isArray(obj[key])) {
|
|
3724
|
+
copyNestedValues(obj[key], fullPath);
|
|
3725
|
+
// Also set the nested object at the namespaced path
|
|
3726
|
+
setValueByPath(namespaced, namespacedPath, obj[key]);
|
|
3727
|
+
}
|
|
3728
|
+
else {
|
|
3729
|
+
setValueByPath(namespaced, namespacedPath, obj[key]);
|
|
3730
|
+
}
|
|
3731
|
+
});
|
|
3732
|
+
}
|
|
3733
|
+
};
|
|
3734
|
+
copyNestedValues(currentSchemaData);
|
|
3735
|
+
return namespaced;
|
|
3586
3736
|
}, [namespace, schemaData, currentSchemaData]);
|
|
3587
|
-
// Populate the store with namespaced schema data so that namespaced widgets
|
|
3588
|
-
// can read their initial values via getValueByPath on the namespaced paths.
|
|
3589
|
-
React.useEffect(() => {
|
|
3590
|
-
if (namespace && namespacedSchemaData) {
|
|
3591
|
-
dispatch(setValues(namespacedSchemaData));
|
|
3592
|
-
}
|
|
3593
|
-
}, [namespace, namespacedSchemaData, dispatch]);
|
|
3594
3737
|
const crViewData = React.useMemo(() => {
|
|
3595
3738
|
if (mode !== 'CRView')
|
|
3596
3739
|
return null;
|
|
@@ -3613,9 +3756,6 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
3613
3756
|
const sectionId = sectionToRender['section-id'];
|
|
3614
3757
|
const gridId = `section-panels-${sectionId}`;
|
|
3615
3758
|
const sectionClassId = `section-${sectionId}`;
|
|
3616
|
-
const readonlyValueRowRootsCss = React.useMemo(() => scopedClassSelectors(sectionClassId, READONLY_VALUE_ROW_ROOT_CLASSES), [sectionClassId]);
|
|
3617
|
-
const readonlyValueRowFlex1Css = React.useMemo(() => READONLY_VALUE_ROW_ROOT_CLASSES.map((c) => `.${sectionClassId} .${c} > .flex-1`).join(',\n '), [sectionClassId]);
|
|
3618
|
-
const readonlySingleLineValueTextCss = React.useMemo(() => READONLY_SINGLE_LINE_VALUE_ROW_CLASSES.map((c) => `.${sectionClassId} .${c} > .flex-1 > .text-gray-900`).join(',\n '), [sectionClassId]);
|
|
3619
3759
|
// IntakeForm mode: accordion expand/collapse state (supports toggle)
|
|
3620
3760
|
const [standaloneExpanded, setStandaloneExpanded] = React.useState(true); // For sectionIndex undefined (standalone use)
|
|
3621
3761
|
const isExpandedFromContainer = typeof sectionIndex === 'number' && expandedSectionIndex === sectionIndex;
|
|
@@ -3839,9 +3979,10 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
3839
3979
|
top: 0;
|
|
3840
3980
|
bottom: 5px;
|
|
3841
3981
|
width: 1px;
|
|
3842
|
-
background-color: #
|
|
3982
|
+
background-color: var(--owt-color-primary, #F5BB1A);
|
|
3843
3983
|
}
|
|
3844
3984
|
` }), jsxRuntimeExports.jsxs("div", { className: `section ${sectionClassId} ${sectionClassId}-edit px-4 sm:px-6 lg:px-8`, "data-section-id": `${sectionId}-edit`, style: {
|
|
3985
|
+
...portalCSSVariables,
|
|
3845
3986
|
position: 'absolute',
|
|
3846
3987
|
top: `${editSectionPosition.top}px`,
|
|
3847
3988
|
left: `${editSectionPosition.left}px`,
|
|
@@ -3851,10 +3992,22 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
3851
3992
|
}, children: [sectionToRender['section-title'] && (jsxRuntimeExports.jsx("h2", { className: "text-xl font-semibold mb-4", style: { fontFamily: 'Roboto, sans-serif', marginTop: '35px' }, children: translateConfig(sectionToRender['section-title']) })), jsxRuntimeExports.jsxs("div", { id: editGridId, className: "section-panels", children: [editableSection.panels.map((panel, index) => {
|
|
3852
3993
|
const isLastPanel = index === editableSection.panels.length - 1;
|
|
3853
3994
|
return (jsxRuntimeExports.jsx("div", { className: `panel-wrapper ${isLastPanel ? 'last-panel-wrapper' : ''}`, children: jsxRuntimeExports.jsx(PanelRenderer, { panel: panel, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: namespacedSchemaData, onValueChange: onValueChange, isEditMode: true }) }, panel['panel-id'] || `section-panel-${index}`));
|
|
3854
|
-
}), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: '#
|
|
3995
|
+
}), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: 'var(--owt-section-divider-color, #F5BB1A)', border: 'none', margin: '25px 0 0 0' } }), hasSupportingDocuments && (jsxRuntimeExports.jsx(jsxRuntimeExports.Fragment, { children: jsxRuntimeExports.jsxs("div", { className: "supporting-documents-container", children: [jsxRuntimeExports.jsxs("button", { type: "button", onClick: () => setIsDocumentsExpanded(!isDocumentsExpanded), className: "supporting-documents-title-button w-full flex items-center text-left", children: [jsxRuntimeExports.jsx("span", { className: "font-semibold", style: { fontFamily: 'Roboto, sans-serif', fontSize: '16px' }, children: translate('common.supportedDocuments') || 'Supported Documents' }), jsxRuntimeExports.jsx("img", { src: isDocumentsExpanded ? img$7 : img$6, alt: "Toggle Documents", className: "w-4 h-2.25 transition-transform ml-2" })] }), isDocumentsExpanded && (jsxRuntimeExports.jsx("div", { className: "supporting-documents-grid mt-4", children: supportingDocuments.map((doc, index) => {
|
|
3855
3996
|
const docConfig = createDocumentWidgetConfig(doc, sectionId, index);
|
|
3856
3997
|
return (jsxRuntimeExports.jsx("div", { className: "supporting-document-item", children: jsxRuntimeExports.jsx(FileInputWidget, { config: docConfig }) }, `${sectionId}-doc-${index}`));
|
|
3857
|
-
}) }))] }) })), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: '#
|
|
3998
|
+
}) }))] }) })), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: 'var(--owt-section-divider-color, #F5BB1A)', border: 'none', marginTop: hasSupportingDocuments ? '20px' : 0, marginBottom: '20px' } }), jsxRuntimeExports.jsx("div", { className: "edit-controls-container", style: { marginBottom: '20px' }, children: jsxRuntimeExports.jsxs("div", { className: "edit-controls-buttons", children: [jsxRuntimeExports.jsx("button", { onClick: handleCancel, className: "text-sm font-medium px-6 py-2 transition-colors", style: {
|
|
3999
|
+
fontFamily: 'Roboto, sans-serif',
|
|
4000
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
4001
|
+
border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
|
|
4002
|
+
backgroundColor: 'var(--owt-btn-secondary-bg, #FFFFFF)',
|
|
4003
|
+
color: 'var(--owt-btn-secondary-color, #011627)',
|
|
4004
|
+
}, children: translate('common.cancel') || 'Cancel' }), jsxRuntimeExports.jsx("button", { onClick: handleSave, disabled: !isDirty, className: "text-sm font-medium px-6 py-2 transition-colors disabled:opacity-50 disabled:cursor-not-allowed", style: {
|
|
4005
|
+
fontFamily: 'Roboto, sans-serif',
|
|
4006
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
4007
|
+
border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
|
|
4008
|
+
backgroundColor: 'var(--owt-color-primary, #F5BB1A)',
|
|
4009
|
+
color: 'var(--owt-color-bg, #FFFFFF)',
|
|
4010
|
+
}, children: translate('common.save') || 'Save' })] }) })] })] })] }), document.body);
|
|
3858
4011
|
};
|
|
3859
4012
|
const trackSectionChages = (widgets, sourceData, pathPrefix) => {
|
|
3860
4013
|
if (!widgets || widgets.length === 0)
|
|
@@ -3955,8 +4108,6 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
3955
4108
|
const baselineSnapshotRef = React.useRef(null);
|
|
3956
4109
|
// IntakeForm only: increment when baseline is updated after save - forces badge to update (refs don't trigger re-renders)
|
|
3957
4110
|
const [intakeFormBaselineTrigger, setIntakeFormBaselineTrigger] = React.useState(0);
|
|
3958
|
-
// IntakeForm only: tracks whether the user has actually saved this section (prevents "Saved" badge on initial load)
|
|
3959
|
-
const [hasBeenSavedByUser, setHasBeenSavedByUser] = React.useState(false);
|
|
3960
4111
|
// IntakeForm: treat as edit mode for dirty tracking when isDraft. RegistryView: use isEditMode.
|
|
3961
4112
|
const effectiveEditModeForDirty = mode === 'IntakeForm' ? (isDraft !== false) : isEditMode;
|
|
3962
4113
|
// Compute isDirty: compare current store state to baseline (only when in edit mode)
|
|
@@ -3999,68 +4150,18 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
3999
4150
|
const intakeFormSectionStatus = React.useMemo(() => {
|
|
4000
4151
|
if (mode !== 'IntakeForm' || isDraft === false)
|
|
4001
4152
|
return null;
|
|
4153
|
+
const hasValue = (v) => v !== undefined && v !== null && (typeof v !== 'string' || v.trim().length > 0);
|
|
4154
|
+
const currentSnapshot = buildSectionSnapshot(storeValues, namespace);
|
|
4155
|
+
const record = currentSnapshot.records?.[0];
|
|
4156
|
+
const hasData = record &&
|
|
4157
|
+
typeof record === 'object' &&
|
|
4158
|
+
Object.values(record).some((v) => hasValue(v));
|
|
4002
4159
|
if (isDirty)
|
|
4003
4160
|
return 'modified';
|
|
4004
|
-
if (
|
|
4161
|
+
if (hasData)
|
|
4005
4162
|
return 'saved';
|
|
4006
4163
|
return null;
|
|
4007
|
-
}, [mode, isDirty,
|
|
4008
|
-
// Revert store values to the original schemaData for this section's widgets.
|
|
4009
|
-
// Used by both handleSave (RegistryView raises a CR, so values should not persist)
|
|
4010
|
-
// and handleCancel.
|
|
4011
|
-
const revertToOriginalValues = React.useCallback(() => {
|
|
4012
|
-
const sectionWidgets = collectWidgets(originalSection.panels);
|
|
4013
|
-
const oldSchemaData = schemaData || contextSchemaData;
|
|
4014
|
-
const currentStoreValues = store.getState().widget.values;
|
|
4015
|
-
let newStoreValues = currentStoreValues;
|
|
4016
|
-
sectionWidgets.forEach(widget => {
|
|
4017
|
-
const originalWidgetId = widget['widget-id'];
|
|
4018
|
-
const namespacedWidgetId = namespace ? `${namespace}__${originalWidgetId}` : originalWidgetId;
|
|
4019
|
-
const widgetId = namespacedWidgetId;
|
|
4020
|
-
const originalDataPath = widget['widget-data-path'];
|
|
4021
|
-
const storeDataPath = namespace && originalDataPath
|
|
4022
|
-
? (typeof originalDataPath === 'string'
|
|
4023
|
-
? `${namespace}.${originalDataPath}`
|
|
4024
|
-
: Object.fromEntries(Object.entries(originalDataPath).map(([key, path]) => [key, `${namespace}.${path}`])))
|
|
4025
|
-
: originalDataPath;
|
|
4026
|
-
if (widgetId && originalDataPath) {
|
|
4027
|
-
let oldValue;
|
|
4028
|
-
if (typeof originalDataPath === 'object') {
|
|
4029
|
-
oldValue = {};
|
|
4030
|
-
Object.entries(originalDataPath).forEach(([key, path]) => {
|
|
4031
|
-
if (typeof path === 'string') {
|
|
4032
|
-
oldValue[key] = getValueByPath(oldSchemaData, path);
|
|
4033
|
-
}
|
|
4034
|
-
});
|
|
4035
|
-
}
|
|
4036
|
-
else if (typeof originalDataPath === 'string') {
|
|
4037
|
-
oldValue = getValueByPath(oldSchemaData, originalDataPath);
|
|
4038
|
-
}
|
|
4039
|
-
if (oldValue !== undefined) {
|
|
4040
|
-
newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
|
|
4041
|
-
// Also revert the widgetId-based entry — useBaseWidget.handleChange
|
|
4042
|
-
// sets values[widgetId] during editing, and useBaseWidget.currentValue
|
|
4043
|
-
// reads values[widgetId] first before falling through to the dataPath.
|
|
4044
|
-
newStoreValues = { ...newStoreValues, [widgetId]: oldValue };
|
|
4045
|
-
}
|
|
4046
|
-
}
|
|
4047
|
-
});
|
|
4048
|
-
if (hasSupportingDocuments) {
|
|
4049
|
-
const originalSupportingDocuments = originalSection['section-supporting-documents'] || [];
|
|
4050
|
-
originalSupportingDocuments.forEach((doc, index) => {
|
|
4051
|
-
const widgetId = `supporting-doc-${sectionId}-${index}`;
|
|
4052
|
-
const originalDataPath = doc['document-data-path'];
|
|
4053
|
-
const storeDataPath = namespace && originalDataPath
|
|
4054
|
-
? `${namespace}.${originalDataPath}`
|
|
4055
|
-
: originalDataPath;
|
|
4056
|
-
const oldValue = getValueByPath(oldSchemaData, originalDataPath);
|
|
4057
|
-
newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
|
|
4058
|
-
});
|
|
4059
|
-
}
|
|
4060
|
-
if (newStoreValues !== currentStoreValues) {
|
|
4061
|
-
dispatch(setValues(newStoreValues));
|
|
4062
|
-
}
|
|
4063
|
-
}, [originalSection, schemaData, contextSchemaData, store, namespace, hasSupportingDocuments, sectionId, dispatch]);
|
|
4164
|
+
}, [mode, isDirty, storeValues, namespace, buildSectionSnapshot]);
|
|
4064
4165
|
// Handle save button click
|
|
4065
4166
|
const handleSave = async () => {
|
|
4066
4167
|
if (!store || !onSectionSave) {
|
|
@@ -4097,24 +4198,12 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4097
4198
|
});
|
|
4098
4199
|
}
|
|
4099
4200
|
if (JSON.stringify(oldSchemaData) !== JSON.stringify(newSchemaData)) {
|
|
4100
|
-
let profileImage = null;
|
|
4101
|
-
for (const record of newSchemaData) {
|
|
4102
|
-
if (typeof record === 'object' && record !== null) {
|
|
4103
|
-
for (const [key, value] of Object.entries(record)) {
|
|
4104
|
-
if (value instanceof File) {
|
|
4105
|
-
profileImage = value;
|
|
4106
|
-
record[key] = '';
|
|
4107
|
-
}
|
|
4108
|
-
}
|
|
4109
|
-
}
|
|
4110
|
-
}
|
|
4111
4201
|
try {
|
|
4112
4202
|
const sectionchanges = {
|
|
4113
4203
|
section_id: dbSectionId ?? originalSection['section-id'],
|
|
4114
4204
|
section_register_id: sectionRegisterId,
|
|
4115
4205
|
records: [...newSchemaData],
|
|
4116
|
-
files: [...sectionFiles]
|
|
4117
|
-
...(profileImage ? { image: profileImage } : {}),
|
|
4206
|
+
files: [...sectionFiles]
|
|
4118
4207
|
};
|
|
4119
4208
|
await onSectionSave(sectionchanges);
|
|
4120
4209
|
}
|
|
@@ -4122,12 +4211,6 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4122
4211
|
console.error('Section Changes Save failed', error);
|
|
4123
4212
|
}
|
|
4124
4213
|
}
|
|
4125
|
-
// In RegistryView, save raises a CR — the actual data update follows a
|
|
4126
|
-
// separate approval workflow, so revert the displayed values to the
|
|
4127
|
-
// originals so the view doesn't show unapproved edits.
|
|
4128
|
-
if (mode === 'RegistryView') {
|
|
4129
|
-
revertToOriginalValues();
|
|
4130
|
-
}
|
|
4131
4214
|
setIsEditMode(false);
|
|
4132
4215
|
onEditModeChange?.(originalSectionId, false);
|
|
4133
4216
|
};
|
|
@@ -4157,24 +4240,12 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4157
4240
|
});
|
|
4158
4241
|
}
|
|
4159
4242
|
if (JSON.stringify(oldSchemaData) !== JSON.stringify(newSchemaData)) {
|
|
4160
|
-
let profileImage = null;
|
|
4161
|
-
for (const record of newSchemaData) {
|
|
4162
|
-
if (typeof record === 'object' && record !== null) {
|
|
4163
|
-
for (const [key, value] of Object.entries(record)) {
|
|
4164
|
-
if (value instanceof File) {
|
|
4165
|
-
profileImage = value;
|
|
4166
|
-
record[key] = '';
|
|
4167
|
-
}
|
|
4168
|
-
}
|
|
4169
|
-
}
|
|
4170
|
-
}
|
|
4171
4243
|
try {
|
|
4172
4244
|
await onSectionSave({
|
|
4173
4245
|
section_id: dbSectionId ?? originalSection['section-id'],
|
|
4174
4246
|
section_register_id: sectionRegisterId,
|
|
4175
4247
|
records: [...newSchemaData],
|
|
4176
4248
|
files: [...sectionFiles],
|
|
4177
|
-
...(profileImage ? { image: profileImage } : {}),
|
|
4178
4249
|
});
|
|
4179
4250
|
}
|
|
4180
4251
|
catch (error) {
|
|
@@ -4185,7 +4256,6 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4185
4256
|
if (mode === 'IntakeForm') {
|
|
4186
4257
|
baselineSnapshotRef.current = buildSectionSnapshot(currentSchemaData, namespace);
|
|
4187
4258
|
setIntakeFormBaselineTrigger((prev) => prev + 1);
|
|
4188
|
-
setHasBeenSavedByUser(true);
|
|
4189
4259
|
}
|
|
4190
4260
|
onSectionDirtyChange?.(sectionId, false);
|
|
4191
4261
|
}
|
|
@@ -4194,7 +4264,64 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4194
4264
|
}, [store, onSectionSave, onSectionSaveSuccess, sectionIndex, originalSection, schemaData, contextSchemaData, namespace, hasSupportingDocuments, dbSectionId, sectionRegisterId, dispatch, buildSectionSnapshot, sectionId, onSectionDirtyChange, mode, isDraft]);
|
|
4195
4265
|
// Handle cancel button click
|
|
4196
4266
|
const handleCancel = () => {
|
|
4197
|
-
|
|
4267
|
+
// Revert values in store to original schema data
|
|
4268
|
+
// Use original section (without namespace) for collecting widgets
|
|
4269
|
+
const sectionWidgets = collectWidgets(originalSection.panels);
|
|
4270
|
+
const oldSchemaData = schemaData || contextSchemaData;
|
|
4271
|
+
const currentStoreValues = store.getState().widget.values;
|
|
4272
|
+
let newStoreValues = currentStoreValues;
|
|
4273
|
+
sectionWidgets.forEach(widget => {
|
|
4274
|
+
const originalWidgetId = widget['widget-id'];
|
|
4275
|
+
// If namespace was used, we need to use namespaced widget ID and data path
|
|
4276
|
+
const namespacedWidgetId = namespace ? `${namespace}__${originalWidgetId}` : originalWidgetId;
|
|
4277
|
+
const widgetId = namespacedWidgetId;
|
|
4278
|
+
const originalDataPath = widget['widget-data-path'];
|
|
4279
|
+
// If namespace was used, data path in store is namespaced, but we read from original schema using original path
|
|
4280
|
+
const storeDataPath = namespace && originalDataPath
|
|
4281
|
+
? (typeof originalDataPath === 'string'
|
|
4282
|
+
? `${namespace}.${originalDataPath}`
|
|
4283
|
+
: Object.fromEntries(Object.entries(originalDataPath).map(([key, path]) => [key, `${namespace}.${path}`])))
|
|
4284
|
+
: originalDataPath;
|
|
4285
|
+
if (widgetId && originalDataPath) {
|
|
4286
|
+
// Handle multi-path (object) or single path (string)
|
|
4287
|
+
// Read from original schema data using original paths
|
|
4288
|
+
let oldValue;
|
|
4289
|
+
if (typeof originalDataPath === 'object') {
|
|
4290
|
+
// Multi-path: get values for each path
|
|
4291
|
+
oldValue = {};
|
|
4292
|
+
Object.entries(originalDataPath).forEach(([key, path]) => {
|
|
4293
|
+
if (typeof path === 'string') {
|
|
4294
|
+
oldValue[key] = getValueByPath(oldSchemaData, path);
|
|
4295
|
+
}
|
|
4296
|
+
});
|
|
4297
|
+
}
|
|
4298
|
+
else if (typeof originalDataPath === 'string') {
|
|
4299
|
+
oldValue = getValueByPath(oldSchemaData, originalDataPath);
|
|
4300
|
+
}
|
|
4301
|
+
// Set in store using namespaced data path (if namespace was used)
|
|
4302
|
+
if (oldValue !== undefined) {
|
|
4303
|
+
newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
|
|
4304
|
+
}
|
|
4305
|
+
}
|
|
4306
|
+
});
|
|
4307
|
+
// Also revert supporting documents if any
|
|
4308
|
+
if (hasSupportingDocuments) {
|
|
4309
|
+
// Use original section's supporting documents to get original data paths
|
|
4310
|
+
const originalSupportingDocuments = originalSection['section-supporting-documents'] || [];
|
|
4311
|
+
originalSupportingDocuments.forEach((doc, index) => {
|
|
4312
|
+
const widgetId = `supporting-doc-${sectionId}-${index}`;
|
|
4313
|
+
const originalDataPath = doc['document-data-path'];
|
|
4314
|
+
// If namespace was used, data path in store is namespaced
|
|
4315
|
+
const storeDataPath = namespace && originalDataPath
|
|
4316
|
+
? `${namespace}.${originalDataPath}`
|
|
4317
|
+
: originalDataPath;
|
|
4318
|
+
const oldValue = getValueByPath(oldSchemaData, originalDataPath);
|
|
4319
|
+
newStoreValues = setWidgetValue(newStoreValues, storeDataPath, widgetId, oldValue);
|
|
4320
|
+
});
|
|
4321
|
+
}
|
|
4322
|
+
if (newStoreValues !== currentStoreValues) {
|
|
4323
|
+
dispatch(setValues(newStoreValues));
|
|
4324
|
+
}
|
|
4198
4325
|
setIsEditMode(false);
|
|
4199
4326
|
onEditModeChange?.(originalSectionId, false);
|
|
4200
4327
|
};
|
|
@@ -4235,7 +4362,7 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4235
4362
|
.${sectionClassId} label.text-gray-700,
|
|
4236
4363
|
.${sectionClassId} .text-gray-600 {
|
|
4237
4364
|
font-weight: 400 !important;
|
|
4238
|
-
color:
|
|
4365
|
+
color: var(--owt-color-text-muted, #727474) !important;
|
|
4239
4366
|
width: 50% !important;
|
|
4240
4367
|
min-width: 50% !important;
|
|
4241
4368
|
max-width: 50% !important;
|
|
@@ -4245,27 +4372,20 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4245
4372
|
white-space: nowrap !important;
|
|
4246
4373
|
}
|
|
4247
4374
|
/* Readonly: prevent flex row from overflowing panel */
|
|
4248
|
-
|
|
4375
|
+
.${sectionClassId} .TextDisplayWidget {
|
|
4249
4376
|
min-width: 0 !important;
|
|
4250
4377
|
overflow: hidden !important;
|
|
4251
4378
|
}
|
|
4252
|
-
|
|
4379
|
+
.${sectionClassId} .TextDisplayWidget > .flex-1 {
|
|
4253
4380
|
min-width: 0 !important;
|
|
4254
4381
|
overflow: hidden !important;
|
|
4255
4382
|
}
|
|
4256
|
-
/* Readonly value
|
|
4257
|
-
|
|
4383
|
+
/* Readonly value text truncation */
|
|
4384
|
+
.${sectionClassId} .TextDisplayWidget > .flex-1 > .text-gray-900 {
|
|
4258
4385
|
overflow: hidden;
|
|
4259
4386
|
text-overflow: ellipsis;
|
|
4260
4387
|
white-space: nowrap;
|
|
4261
4388
|
}
|
|
4262
|
-
/* Readonly textarea: break unbroken long tokens; title on pre keeps full text on hover */
|
|
4263
|
-
.${sectionClassId} .TextAreaDisplayWidget > .flex-1 > pre {
|
|
4264
|
-
min-width: 0;
|
|
4265
|
-
max-width: 100%;
|
|
4266
|
-
overflow-wrap: anywhere;
|
|
4267
|
-
word-break: break-word;
|
|
4268
|
-
}
|
|
4269
4389
|
|
|
4270
4390
|
/* Only apply fixed height when in edit mode */
|
|
4271
4391
|
.${sectionClassId}[data-edit-mode="true"] {
|
|
@@ -4287,11 +4407,11 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4287
4407
|
.${sectionClassId}-edit {
|
|
4288
4408
|
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.2),
|
|
4289
4409
|
0 8px 10px -6px rgba(0, 0, 0, 0.1);
|
|
4290
|
-
border-color: #
|
|
4410
|
+
border-color: var(--owt-color-primary-dark, #F07B1A);
|
|
4291
4411
|
border-style: dashed;
|
|
4292
4412
|
border-width: 1px;
|
|
4293
|
-
background-color: #
|
|
4294
|
-
border-radius: 10px;
|
|
4413
|
+
background-color: var(--owt-color-primary-light, #FBE6AA);
|
|
4414
|
+
border-radius: var(--owt-section-border-radius, 10px);
|
|
4295
4415
|
z-index: 10;
|
|
4296
4416
|
position: absolute;
|
|
4297
4417
|
}
|
|
@@ -4391,23 +4511,23 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4391
4511
|
|
|
4392
4512
|
/* IntakeForm accordion */
|
|
4393
4513
|
.${sectionClassId}.intake-form-accordion-item {
|
|
4394
|
-
border-color: #
|
|
4514
|
+
border-color: var(--owt-color-border-light, #E4E4E4);
|
|
4395
4515
|
transition: box-shadow 0.2s ease, border-color 0.2s ease;
|
|
4396
4516
|
}
|
|
4397
4517
|
.${sectionClassId}.intake-form-accordion-item:hover {
|
|
4398
|
-
border-color: #
|
|
4518
|
+
border-color: var(--owt-color-border, #C4C4C4);
|
|
4399
4519
|
}
|
|
4400
4520
|
.${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header {
|
|
4401
4521
|
transition: opacity 0.2s ease, background-color 0.2s ease;
|
|
4402
4522
|
}
|
|
4403
4523
|
.${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header h2 {
|
|
4404
|
-
color: #
|
|
4524
|
+
color: var(--owt-color-primary-dark, #F07B1A);
|
|
4405
4525
|
}
|
|
4406
4526
|
.${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header:hover {
|
|
4407
4527
|
opacity: 0.85;
|
|
4408
4528
|
}
|
|
4409
4529
|
.${sectionClassId}.intake-form-accordion-item .intake-form-accordion-header:focus-visible {
|
|
4410
|
-
outline: 2px solid #
|
|
4530
|
+
outline: 2px solid var(--owt-color-primary, #F5BB1A);
|
|
4411
4531
|
outline-offset: 2px;
|
|
4412
4532
|
}
|
|
4413
4533
|
.${sectionClassId}.intake-form-accordion-item .intake-form-accordion-content {
|
|
@@ -4419,27 +4539,27 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4419
4539
|
width: 100%;
|
|
4420
4540
|
}
|
|
4421
4541
|
.${sectionClassId}.intake-form-accordion-item .intake-form-prev-btn {
|
|
4422
|
-
color:
|
|
4542
|
+
color: var(--owt-color-text-muted, #727474) !important;
|
|
4423
4543
|
}
|
|
4424
4544
|
.${sectionClassId}.intake-form-accordion-item .intake-form-prev-btn:disabled {
|
|
4425
|
-
color:
|
|
4545
|
+
color: var(--owt-color-border, #C4C4C4) !important;
|
|
4426
4546
|
}
|
|
4427
4547
|
.${sectionClassId}.intake-form-accordion-item .intake-form-prev-btn:hover:not(:disabled) {
|
|
4428
|
-
background-color: #
|
|
4429
|
-
border-color: #
|
|
4548
|
+
background-color: var(--owt-color-bg-alt, #F6F6F6);
|
|
4549
|
+
border-color: var(--owt-btn-primary-border, #F07B1A);
|
|
4430
4550
|
}
|
|
4431
4551
|
.${sectionClassId}.intake-form-accordion-item .intake-form-save-btn:hover:not(:disabled) {
|
|
4432
|
-
background-color: #
|
|
4552
|
+
background-color: var(--owt-color-border-light, #E4E4E4);
|
|
4433
4553
|
}
|
|
4434
|
-
` }), jsxRuntimeExports.jsx("div", { ref: sectionRef, className: `section ${sectionClassId} px-4 sm:px-6 lg:px-8 border-2
|
|
4554
|
+
` }), jsxRuntimeExports.jsx("div", { ref: sectionRef, className: `section ${sectionClassId} px-4 sm:px-6 lg:px-8 border-2 ${mode === 'IntakeForm' ? 'intake-form-accordion-item' : ''}`, "data-section-id": sectionId, "data-has-table": hasTableWidget ? 'true' : 'false', "data-has-explicit-span": hasExplicitTableSpan ? 'true' : 'false', "data-edit-mode": isEditMode ? 'true' : 'false', "data-section-dirty": isEditMode && isDirty ? 'true' : 'false', "data-column-span": columnSpan, "data-change-request-type": changeRequestType, "data-intake-form-expanded": mode === 'IntakeForm' ? (isExpanded ? 'true' : 'false') : undefined, style: {
|
|
4435
4555
|
gridColumn: `span ${columnSpan}`,
|
|
4436
4556
|
width: '100%',
|
|
4437
|
-
borderRadius: '10px',
|
|
4438
|
-
|
|
4557
|
+
borderRadius: 'var(--owt-section-border-radius, 10px)',
|
|
4558
|
+
borderColor: 'var(--owt-color-bg, #FFFFFF)',
|
|
4439
4559
|
...(mode === 'IntakeForm' && isExpanded
|
|
4440
|
-
? { backgroundColor: '#
|
|
4560
|
+
? { backgroundColor: 'var(--owt-color-primary-light, #FBE6AA)', border: '1px dashed var(--owt-color-primary-dark, #F07B1A)' }
|
|
4441
4561
|
: {
|
|
4442
|
-
backgroundColor: changeRequestType === 'old' ? '#
|
|
4562
|
+
backgroundColor: changeRequestType === 'old' ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-section-bg, #FFFFFF)',
|
|
4443
4563
|
opacity: changeRequestType === 'old' ? 0.95 : 1,
|
|
4444
4564
|
}),
|
|
4445
4565
|
...(isEditMode && sectionHeight ? {
|
|
@@ -4473,17 +4593,17 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4473
4593
|
borderRadius: '9999px',
|
|
4474
4594
|
fontSize: '12px',
|
|
4475
4595
|
fontWeight: 500,
|
|
4476
|
-
backgroundColor: '#D1FAE5',
|
|
4477
|
-
color: '#047857',
|
|
4596
|
+
backgroundColor: 'var(--owt-color-success-light, #D1FAE5)',
|
|
4597
|
+
color: 'var(--owt-color-success-dark, #047857)',
|
|
4478
4598
|
}, children: translate('common.sectionSaved') || 'Saved' })), intakeFormSectionStatus === 'modified' && (jsxRuntimeExports.jsx("span", { style: {
|
|
4479
4599
|
display: 'inline-block',
|
|
4480
4600
|
padding: '4px 10px',
|
|
4481
4601
|
borderRadius: '9999px',
|
|
4482
4602
|
fontSize: '12px',
|
|
4483
4603
|
fontWeight: 500,
|
|
4484
|
-
backgroundColor: '#FEE2E2',
|
|
4485
|
-
color: '#B91C1C',
|
|
4486
|
-
}, children: translate('common.sectionModified') || 'Modified and not saved' }))] }), jsxRuntimeExports.jsx("img", { src: isExpanded ? img$7 : img$6, alt: isExpanded ? 'Collapse' : 'Expand', className: "w-5 h-5 transition-transform", style: { flexShrink: 0, marginLeft: '12px' }, "aria-hidden": true })] }), isExpanded && (jsxRuntimeExports.jsx("div", { id: `intake-form-accordion-content-${sectionId}`, className: "intake-form-accordion-content", role: "region", "aria-labelledby": `intake-form-accordion-header-${sectionId}`, children: jsxRuntimeExports.jsxs("div", { id: gridId, className: "section-panels", style: { paddingTop: '8px' }, children: [editableSection.panels.map((panel, index) => (jsxRuntimeExports.jsx("div", { className: "panel-wrapper", children: jsxRuntimeExports.jsx(PanelRenderer, { panel: panel, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: namespacedSchemaData, onValueChange: onValueChange, isEditMode: isDraft !== false }) }, panel['panel-id'] || `section-panel-${index}`))), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: '#
|
|
4604
|
+
backgroundColor: 'var(--owt-color-error-light, #FEE2E2)',
|
|
4605
|
+
color: 'var(--owt-color-error, #B91C1C)',
|
|
4606
|
+
}, children: translate('common.sectionModified') || 'Modified and not saved' }))] }), jsxRuntimeExports.jsx("img", { src: isExpanded ? img$7 : img$6, alt: isExpanded ? 'Collapse' : 'Expand', className: "w-5 h-5 transition-transform", style: { flexShrink: 0, marginLeft: '12px' }, "aria-hidden": true })] }), isExpanded && (jsxRuntimeExports.jsx("div", { id: `intake-form-accordion-content-${sectionId}`, className: "intake-form-accordion-content", role: "region", "aria-labelledby": `intake-form-accordion-header-${sectionId}`, children: jsxRuntimeExports.jsxs("div", { id: gridId, className: "section-panels", style: { paddingTop: '8px' }, children: [editableSection.panels.map((panel, index) => (jsxRuntimeExports.jsx("div", { className: "panel-wrapper", children: jsxRuntimeExports.jsx(PanelRenderer, { panel: panel, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: namespacedSchemaData, onValueChange: onValueChange, isEditMode: isDraft !== false }) }, panel['panel-id'] || `section-panel-${index}`))), jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', backgroundColor: 'var(--owt-section-divider-color, #F5BB1A)', border: 'none', margin: '15px 0 0 0' } }), hasSupportingDocuments && (jsxRuntimeExports.jsxs("div", { className: "supporting-documents-container", children: [jsxRuntimeExports.jsx("span", { className: "font-semibold", style: { fontFamily: 'Roboto, sans-serif', fontSize: '16px' }, children: translate('common.supportedDocuments') || 'Supported Documents' }), jsxRuntimeExports.jsx("div", { className: "supporting-documents-grid mt-4", children: supportingDocuments.map((doc, docIndex) => {
|
|
4487
4607
|
const docConfig = createDocumentWidgetConfig(doc, sectionId, docIndex);
|
|
4488
4608
|
return (jsxRuntimeExports.jsx("div", { className: "supporting-document-item", children: jsxRuntimeExports.jsx(FileInputWidget, { config: docConfig }) }, `${sectionId}-doc-${docIndex}`));
|
|
4489
4609
|
}) })] })), jsxRuntimeExports.jsxs("div", { className: "intake-form-edit-controls", style: {
|
|
@@ -4499,10 +4619,10 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4499
4619
|
fontSize: '14px',
|
|
4500
4620
|
fontWeight: 400,
|
|
4501
4621
|
padding: '8px 24px',
|
|
4502
|
-
borderRadius: '10px',
|
|
4503
|
-
border: '1px solid #
|
|
4504
|
-
background: '#FFFFFF',
|
|
4505
|
-
color: '
|
|
4622
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
4623
|
+
border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
|
|
4624
|
+
background: 'var(--owt-btn-primary-bg, #FFFFFF)',
|
|
4625
|
+
color: 'var(--owt-color-text-muted, #727474)',
|
|
4506
4626
|
cursor: 'pointer',
|
|
4507
4627
|
display: 'inline-flex',
|
|
4508
4628
|
alignItems: 'center',
|
|
@@ -4512,10 +4632,10 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4512
4632
|
fontSize: '14px',
|
|
4513
4633
|
fontWeight: 400,
|
|
4514
4634
|
padding: '8px 24px',
|
|
4515
|
-
borderRadius: '10px',
|
|
4516
|
-
border: '1px solid #
|
|
4517
|
-
background: '#FFFFFF',
|
|
4518
|
-
color: '
|
|
4635
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
4636
|
+
border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
|
|
4637
|
+
background: 'var(--owt-btn-primary-bg, #FFFFFF)',
|
|
4638
|
+
color: 'var(--owt-color-text-muted, #727474)',
|
|
4519
4639
|
cursor: 'pointer',
|
|
4520
4640
|
display: 'inline-flex',
|
|
4521
4641
|
alignItems: 'center',
|
|
@@ -4538,11 +4658,11 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4538
4658
|
fontWeight: 600,
|
|
4539
4659
|
textTransform: 'uppercase',
|
|
4540
4660
|
letterSpacing: '0.5px',
|
|
4541
|
-
backgroundColor: changeRequestType === 'new' ? '#
|
|
4542
|
-
color: changeRequestType === 'new' ? '#FFFFFF' : '#
|
|
4661
|
+
backgroundColor: changeRequestType === 'new' ? 'var(--owt-color-success, #16A34A)' : 'var(--owt-color-error-light, #FEE2E2)',
|
|
4662
|
+
color: changeRequestType === 'new' ? 'var(--owt-color-bg, #FFFFFF)' : 'var(--owt-color-error, #B91C1C)',
|
|
4543
4663
|
whiteSpace: 'nowrap',
|
|
4544
4664
|
boxShadow: changeRequestType === 'new' ? '0 2px 4px rgba(40, 167, 69, 0.3)' : 'none',
|
|
4545
|
-
}, children: changeRequestType === 'new' ? 'New' : 'Old' }))] })), jsxRuntimeExports.jsxs("div", { id: gridId, className: "section-panels", style: mode === 'RegistryView' && hideEditButton ? { paddingBottom: '
|
|
4665
|
+
}, children: changeRequestType === 'new' ? 'New' : 'Old' }))] })), jsxRuntimeExports.jsxs("div", { id: gridId, className: "section-panels", style: mode === 'RegistryView' && hideEditButton ? { paddingBottom: '30px' } : {}, 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: "w-full", style: { height: '1px', marginTop: '20px', marginBottom: '0px', border: 'none', backgroundColor: 'var(--owt-color-border, #C4C4C4)' } }), jsxRuntimeExports.jsxs("div", { className: "cr-view-container", style: {
|
|
4546
4666
|
marginTop: '20px',
|
|
4547
4667
|
paddingBottom: '30px',
|
|
4548
4668
|
display: 'flex',
|
|
@@ -4557,17 +4677,17 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4557
4677
|
}, children: [jsxRuntimeExports.jsx("span", { style: {
|
|
4558
4678
|
fontFamily: 'Roboto, sans-serif',
|
|
4559
4679
|
fontSize: '14px',
|
|
4560
|
-
color: '#
|
|
4680
|
+
color: 'var(--owt-color-text, #011627)',
|
|
4561
4681
|
fontWeight: 'normal',
|
|
4562
4682
|
}, children: "Created by" }), jsxRuntimeExports.jsx("img", { src: img$a, alt: "Person", width: "16", height: "16", style: { filter: 'brightness(0) saturate(100%) invert(56%) sepia(45%) saturate(5139%) hue-rotate(348deg) brightness(96%) contrast(92%)' } }), crViewData?.createdBy && (jsxRuntimeExports.jsx("span", { style: {
|
|
4563
4683
|
fontFamily: 'Roboto, sans-serif',
|
|
4564
4684
|
fontSize: '14px',
|
|
4565
|
-
color: '#
|
|
4685
|
+
color: 'var(--owt-color-text, #011627)',
|
|
4566
4686
|
fontWeight: 'normal',
|
|
4567
4687
|
}, children: crViewData.createdBy })), jsxRuntimeExports.jsx("img", { src: img$9, alt: "Calendar", width: "16", height: "16", style: { marginLeft: '6px' } }), crViewData?.createdDate && (jsxRuntimeExports.jsx("span", { style: {
|
|
4568
4688
|
fontFamily: 'Roboto, sans-serif',
|
|
4569
4689
|
fontSize: '14px',
|
|
4570
|
-
color: '#
|
|
4690
|
+
color: 'var(--owt-color-text, #011627)',
|
|
4571
4691
|
fontWeight: 'normal',
|
|
4572
4692
|
}, children: crViewData.createdDate }))] }), jsxRuntimeExports.jsxs("div", { className: "approved-by-section", style: {
|
|
4573
4693
|
display: 'flex',
|
|
@@ -4578,22 +4698,22 @@ const SectionRenderer = ({ section, dataSourceRequestHandler: propDataSourceRequ
|
|
|
4578
4698
|
}, children: [jsxRuntimeExports.jsx("span", { style: {
|
|
4579
4699
|
fontFamily: 'Roboto, sans-serif',
|
|
4580
4700
|
fontSize: '14px',
|
|
4581
|
-
color: '#
|
|
4701
|
+
color: 'var(--owt-color-text, #011627)',
|
|
4582
4702
|
fontWeight: 'normal',
|
|
4583
4703
|
}, children: "Approved by" }), jsxRuntimeExports.jsx("img", { src: img$a, alt: "Person", width: "16", height: "16", style: { filter: 'brightness(0) saturate(100%) invert(56%) sepia(45%) saturate(5139%) hue-rotate(348deg) brightness(96%) contrast(92%)' } }), crViewData?.approvedBy && (jsxRuntimeExports.jsx("span", { style: {
|
|
4584
4704
|
fontFamily: 'Roboto, sans-serif',
|
|
4585
4705
|
fontSize: '14px',
|
|
4586
|
-
color: '#
|
|
4706
|
+
color: 'var(--owt-color-text, #011627)',
|
|
4587
4707
|
fontWeight: 'normal',
|
|
4588
4708
|
}, children: crViewData.approvedBy })), jsxRuntimeExports.jsx("img", { src: img$9, alt: "Calendar", width: "16", height: "16", style: { marginLeft: '6px' } }), crViewData?.approvedDate && (jsxRuntimeExports.jsx("span", { style: {
|
|
4589
4709
|
fontFamily: 'Roboto, sans-serif',
|
|
4590
4710
|
fontSize: '14px',
|
|
4591
|
-
color: '#
|
|
4711
|
+
color: 'var(--owt-color-text, #011627)',
|
|
4592
4712
|
fontWeight: 'normal',
|
|
4593
|
-
}, children: crViewData.approvedDate }))] })] })] })), mode === 'RegistryView' && !hideEditButton && (jsxRuntimeExports.jsx("hr", { className: "
|
|
4713
|
+
}, children: crViewData.approvedDate }))] })] })] })), mode === 'RegistryView' && !hideEditButton && (jsxRuntimeExports.jsx("hr", { className: "w-full", style: { height: '1px', marginTop: !isEditMode ? '10px' : 0, marginBottom: '14px', border: 'none', backgroundColor: 'var(--owt-color-border, #C4C4C4)' } })), mode === 'RegistryView' && !isEditMode && !hideEditButton && (jsxRuntimeExports.jsx("div", { className: "flex justify-center items-center", style: { marginBottom: '20px' }, children: jsxRuntimeExports.jsxs("button", { onClick: handleEdit, className: "font-normal inline-flex items-center gap-2 bg-transparent border-0 p-0 cursor-pointer hover:opacity-80", style: {
|
|
4594
4714
|
fontFamily: 'Roboto, sans-serif',
|
|
4595
4715
|
fontSize: '16px',
|
|
4596
|
-
color: '
|
|
4716
|
+
color: 'var(--owt-color-text-muted, #727474)'
|
|
4597
4717
|
}, children: [translate('common.editDetails') || 'Edit Details', jsxRuntimeExports.jsx("img", { src: img$8, alt: "right-arrow", className: "w-3.5 h-3.5 brightness-0 opacity-50" })] }) }))] })] })) })] }));
|
|
4598
4718
|
};
|
|
4599
4719
|
|
|
@@ -4767,9 +4887,6 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
4767
4887
|
}, []);
|
|
4768
4888
|
const safeSections = sections ?? [];
|
|
4769
4889
|
const prevSectionsLengthRef = React.useRef(safeSections.length);
|
|
4770
|
-
// Stable ref for namespace so formHandle useMemo doesn't depend on the (possibly inline) function identity
|
|
4771
|
-
const namespaceRef = React.useRef(namespace);
|
|
4772
|
-
namespaceRef.current = namespace;
|
|
4773
4890
|
// Track dirty (unsaved changes) per section for form handle validation
|
|
4774
4891
|
const sectionDirtyMapRef = React.useRef({});
|
|
4775
4892
|
const handleSectionDirtyChange = React.useCallback((sectionId, isDirty) => {
|
|
@@ -4815,14 +4932,11 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
4815
4932
|
// Form handle for onFormReady - allows host to validate and get all section data from its own Submit button
|
|
4816
4933
|
const formHandle = React.useMemo(() => {
|
|
4817
4934
|
const getValues = () => store.getState().widget?.values || {};
|
|
4818
|
-
const getNamespace = (section, index) =>
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
: ns(section['section-id'], index)
|
|
4824
|
-
: undefined;
|
|
4825
|
-
};
|
|
4935
|
+
const getNamespace = (section, index) => namespace
|
|
4936
|
+
? typeof namespace === 'string'
|
|
4937
|
+
? namespace
|
|
4938
|
+
: namespace(section['section-id'], index)
|
|
4939
|
+
: undefined;
|
|
4826
4940
|
const checkNoUnsavedChanges = () => {
|
|
4827
4941
|
const hasDirty = Object.values(sectionDirtyMapRef.current).some(Boolean);
|
|
4828
4942
|
if (hasDirty) {
|
|
@@ -4872,7 +4986,7 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
4872
4986
|
return results;
|
|
4873
4987
|
},
|
|
4874
4988
|
};
|
|
4875
|
-
}, [store, dispatch, safeSections]);
|
|
4989
|
+
}, [store, dispatch, safeSections, namespace]);
|
|
4876
4990
|
// Call onFormReady when form is ready (sections loaded)
|
|
4877
4991
|
React.useEffect(() => {
|
|
4878
4992
|
if (onFormReady && safeSections.length > 0) {
|
|
@@ -4945,6 +5059,7 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
4945
5059
|
const sectionNamespace = namespace
|
|
4946
5060
|
? (typeof namespace === 'string' ? namespace : namespace(section['section-id'], index))
|
|
4947
5061
|
: undefined;
|
|
5062
|
+
const hideEditForSection = hideEditButton || section['section-hide-edit-button'] === true;
|
|
4948
5063
|
// IntakeForm mode: pass accordion state and handlers
|
|
4949
5064
|
const intakeFormProps = mode === 'IntakeForm'
|
|
4950
5065
|
? {
|
|
@@ -4966,7 +5081,7 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
4966
5081
|
: {};
|
|
4967
5082
|
// Check if section has explicit column span
|
|
4968
5083
|
if (section['section-column-span']) {
|
|
4969
|
-
return (jsxRuntimeExports.jsx(SectionRenderer, { section: section, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: schemaData, onValueChange: onValueChange, gridColumnSpan: section['section-column-span'], onSectionSave: onSectionSave, hideEditButton:
|
|
5084
|
+
return (jsxRuntimeExports.jsx(SectionRenderer, { section: section, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: schemaData, onValueChange: onValueChange, gridColumnSpan: section['section-column-span'], onSectionSave: onSectionSave, hideEditButton: hideEditForSection, mode: mode, namespace: sectionNamespace, onSectionDirtyChange: handleSectionDirtyChange, ...intakeFormProps, ...registryViewEditProps }, section['section-id']));
|
|
4970
5085
|
}
|
|
4971
5086
|
const verticalPanelsCount = countVerticalPanels(section.panels);
|
|
4972
5087
|
const tableWidgetColumnSpan = getTableWidgetColumnSpan(section.panels);
|
|
@@ -4974,7 +5089,7 @@ const SectionsContainer = ({ sections, dataSourceRequestHandler: propDataSourceR
|
|
|
4974
5089
|
const columnSpan = tableWidgetColumnSpan !== null
|
|
4975
5090
|
? tableWidgetColumnSpan
|
|
4976
5091
|
: (containsTable ? Math.max(verticalPanelsCount, 2) : verticalPanelsCount);
|
|
4977
|
-
return (jsxRuntimeExports.jsx(SectionRenderer, { section: section, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: schemaData, onValueChange: onValueChange, gridColumnSpan: columnSpan, onSectionSave: onSectionSave, hideEditButton:
|
|
5092
|
+
return (jsxRuntimeExports.jsx(SectionRenderer, { section: section, dataSourceRequestHandler: dataSourceRequestHandler, schemaData: schemaData, onValueChange: onValueChange, gridColumnSpan: columnSpan, onSectionSave: onSectionSave, hideEditButton: hideEditForSection, mode: mode, namespace: sectionNamespace, onSectionDirtyChange: handleSectionDirtyChange, ...intakeFormProps, ...registryViewEditProps }, section['section-id']));
|
|
4978
5093
|
}) })] }));
|
|
4979
5094
|
};
|
|
4980
5095
|
|
|
@@ -8155,10 +8270,10 @@ const DisplayWidget = ({ config }) => {
|
|
|
8155
8270
|
const label = translateConfig(widgetConfig['widget-label']);
|
|
8156
8271
|
// If no label, render as paragraph text
|
|
8157
8272
|
if (!label || label.trim() === '') {
|
|
8158
|
-
return (jsxRuntimeExports.jsx("div", { className: "
|
|
8273
|
+
return (jsxRuntimeExports.jsx("div", { className: "mb-3 text-base text-gray-700", title: String(displayValue ?? ''), children: displayValue }));
|
|
8159
8274
|
}
|
|
8160
|
-
// With label, render as key-value pair
|
|
8161
|
-
return (jsxRuntimeExports.jsxs("div", { className: "mb-[10px]
|
|
8275
|
+
// With label, render as key-value pair
|
|
8276
|
+
return (jsxRuntimeExports.jsxs("div", { className: "mb-[10px] flex flex-col sm:flex-row sm:items-start", children: [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 text-base text-gray-900 font-medium", title: String(displayValue ?? ''), children: displayValue })] }));
|
|
8162
8277
|
};
|
|
8163
8278
|
|
|
8164
8279
|
const TableCellSelect = ({ config, value, onValueChange }) => {
|
|
@@ -8166,7 +8281,11 @@ const TableCellSelect = ({ config, value, onValueChange }) => {
|
|
|
8166
8281
|
// Use useBaseWidget to get data source options (it handles loading)
|
|
8167
8282
|
const { dataSourceOptions, loading, config: widgetConfig, } = useBaseWidget({ config });
|
|
8168
8283
|
const isReadonly = config['widget-readonly'] || false;
|
|
8169
|
-
return (jsxRuntimeExports.jsxs("select", { value: value || '', onChange: (e) => onValueChange(e.target.value), disabled: isReadonly || loading, className: `w-full h-[28px] px-2 text-sm border focus:outline-none
|
|
8284
|
+
return (jsxRuntimeExports.jsxs("select", { value: value || '', onChange: (e) => onValueChange(e.target.value), disabled: isReadonly || loading, className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly || loading ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
|
|
8285
|
+
borderRadius: '10px',
|
|
8286
|
+
borderColor: 'var(--owt-widget-input-border, #C4C4C4)',
|
|
8287
|
+
backgroundColor: isReadonly || loading ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
|
|
8288
|
+
}, children: [jsxRuntimeExports.jsx("option", { value: "", children: translate('common.select') || 'Select' }), dataSourceOptions.map((option) => (jsxRuntimeExports.jsx("option", { value: option.value, children: option.label }, option.value)))] }));
|
|
8170
8289
|
};
|
|
8171
8290
|
const SelectDisplayValue = ({ config, value }) => {
|
|
8172
8291
|
const { dataSourceOptions, loading } = useBaseWidget({ config });
|
|
@@ -8185,7 +8304,11 @@ const TableCellText = ({ config, value, onValueChange }) => {
|
|
|
8185
8304
|
config['widget-data-format'];
|
|
8186
8305
|
const maxLength = config['widget-data-validation']?.maxLength;
|
|
8187
8306
|
const displayValue = value !== null && value !== undefined ? String(value) : '';
|
|
8188
|
-
return (jsxRuntimeExports.jsx("input", { type: "text", value: displayValue, onChange: (e) => onValueChange(e.target.value), disabled: isReadonly, placeholder: placeholder, maxLength: maxLength, className: `w-full h-[28px] px-2 text-sm border focus:outline-none
|
|
8307
|
+
return (jsxRuntimeExports.jsx("input", { type: "text", value: displayValue, onChange: (e) => onValueChange(e.target.value), disabled: isReadonly, placeholder: placeholder, maxLength: maxLength, className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
|
|
8308
|
+
borderRadius: '10px',
|
|
8309
|
+
borderColor: 'var(--owt-widget-input-border, #C4C4C4)',
|
|
8310
|
+
backgroundColor: isReadonly ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
|
|
8311
|
+
} }));
|
|
8189
8312
|
};
|
|
8190
8313
|
const TableCellNumber = ({ config, value, onValueChange }) => {
|
|
8191
8314
|
const isReadonly = config['widget-readonly'] || false;
|
|
@@ -8208,14 +8331,22 @@ const TableCellNumber = ({ config, value, onValueChange }) => {
|
|
|
8208
8331
|
onValueChange(inputValue);
|
|
8209
8332
|
}
|
|
8210
8333
|
};
|
|
8211
|
-
return (jsxRuntimeExports.jsx("input", { type: "number", value: displayValue, onChange: handleChange, disabled: isReadonly, placeholder: placeholder, min: validationConfig?.min, max: validationConfig?.max, step: formatConfig?.decimalPlaces ? Math.pow(0.1, formatConfig.decimalPlaces) : undefined, className: `w-full h-[28px] px-2 text-sm border focus:outline-none
|
|
8334
|
+
return (jsxRuntimeExports.jsx("input", { type: "number", value: displayValue, onChange: handleChange, disabled: isReadonly, placeholder: placeholder, min: validationConfig?.min, max: validationConfig?.max, step: formatConfig?.decimalPlaces ? Math.pow(0.1, formatConfig.decimalPlaces) : undefined, className: `w-full h-[28px] px-2 text-sm border focus:outline-none text-right ${isReadonly ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
|
|
8335
|
+
borderRadius: '10px',
|
|
8336
|
+
borderColor: 'var(--owt-widget-input-border, #C4C4C4)',
|
|
8337
|
+
backgroundColor: isReadonly ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
|
|
8338
|
+
} }));
|
|
8212
8339
|
};
|
|
8213
8340
|
const TableCellDate = ({ config, value, onValueChange }) => {
|
|
8214
8341
|
const isReadonly = config['widget-readonly'] || false;
|
|
8215
8342
|
const placeholder = config['widget-data-placeholder'] || '';
|
|
8216
8343
|
// input type="date" requires YYYY-MM-DD format
|
|
8217
8344
|
const displayValue = value && typeof value === 'string' ? value.split('T')[0] : '';
|
|
8218
|
-
return (jsxRuntimeExports.jsx("input", { type: "date", value: displayValue, onChange: (e) => onValueChange(e.target.value), disabled: isReadonly, placeholder: placeholder, className: `w-full h-[28px] px-2 text-sm border focus:outline-none
|
|
8345
|
+
return (jsxRuntimeExports.jsx("input", { type: "date", value: displayValue, onChange: (e) => onValueChange(e.target.value), disabled: isReadonly, placeholder: placeholder, className: `w-full h-[28px] px-2 text-sm border focus:outline-none ${isReadonly ? 'cursor-not-allowed' : ''} table-cell-input`, style: {
|
|
8346
|
+
borderRadius: '10px',
|
|
8347
|
+
borderColor: 'var(--owt-widget-input-border, #C4C4C4)',
|
|
8348
|
+
backgroundColor: isReadonly ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
|
|
8349
|
+
} }));
|
|
8219
8350
|
};
|
|
8220
8351
|
const TableWidget = ({ config }) => {
|
|
8221
8352
|
const { value, error, touched, isEnabled, onChange, config: widgetConfig, } = useBaseWidget({ config });
|
|
@@ -8622,13 +8753,13 @@ const TableWidget = ({ config }) => {
|
|
|
8622
8753
|
return {}; // No special styling when editing
|
|
8623
8754
|
const editAction = row?.edit_action;
|
|
8624
8755
|
if (editAction === 'ADD') {
|
|
8625
|
-
return { color: '#
|
|
8756
|
+
return { color: 'var(--owt-color-success, #16A34A)' };
|
|
8626
8757
|
}
|
|
8627
8758
|
else if (editAction === 'DELETE') {
|
|
8628
|
-
return { color: '#
|
|
8759
|
+
return { color: 'var(--owt-color-error, #B91C1C)', textDecoration: 'line-through' };
|
|
8629
8760
|
}
|
|
8630
8761
|
else if (editAction === 'UPDATE') {
|
|
8631
|
-
return { color: '#
|
|
8762
|
+
return { color: 'var(--owt-color-warning, #F59E0B)' };
|
|
8632
8763
|
}
|
|
8633
8764
|
return {};
|
|
8634
8765
|
};
|
|
@@ -8712,27 +8843,81 @@ const TableWidget = ({ config }) => {
|
|
|
8712
8843
|
.${tableWidgetId} button {
|
|
8713
8844
|
border-radius: 10px !important;
|
|
8714
8845
|
}
|
|
8715
|
-
|
|
8846
|
+
/* Focus ring for table cell inputs */
|
|
8847
|
+
.${tableWidgetId} .table-cell-input:focus {
|
|
8848
|
+
box-shadow: 0 0 0 1px var(--owt-widget-input-focus-border, #F07B1A);
|
|
8849
|
+
border-color: var(--owt-widget-input-focus-border, #F07B1A);
|
|
8850
|
+
}
|
|
8851
|
+
` }), jsxRuntimeExports.jsxs("div", { className: `table-widget-container ${tableWidgetId}`, children: [confirmationState?.show && (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 max-w-md w-full mx-4", style: { backgroundColor: 'var(--owt-color-bg, #FFFFFF)' }, children: [jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold mb-4", style: { color: 'var(--owt-color-text, #011627)' }, children: translate('table.confirm') || 'Confirm Action' }), jsxRuntimeExports.jsx("p", { className: "mb-6", style: { color: 'var(--owt-color-text, #011627)' }, children: confirmationState.message }), jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-3", children: [jsxRuntimeExports.jsx("button", { onClick: confirmationState.onCancel, className: "px-4 py-2 text-sm font-medium", style: {
|
|
8852
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
8853
|
+
border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
|
|
8854
|
+
backgroundColor: 'var(--owt-btn-secondary-bg, #FFFFFF)',
|
|
8855
|
+
color: 'var(--owt-btn-secondary-color, #011627)',
|
|
8856
|
+
}, children: translate('common.cancel') || 'Cancel' }), jsxRuntimeExports.jsx("button", { onClick: confirmationState.onConfirm, className: "px-4 py-2 text-sm font-medium", style: {
|
|
8857
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
8858
|
+
border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
|
|
8859
|
+
backgroundColor: 'var(--owt-color-primary, #F5BB1A)',
|
|
8860
|
+
color: 'var(--owt-color-bg, #FFFFFF)',
|
|
8861
|
+
}, children: translate('table.discard') || 'Discard & Continue' })] })] }) })), operations.add && !isReadonly && isEnabled && (isSectionEditMode || !isAnyRowEditing) && (jsxRuntimeExports.jsx("div", { className: "flex justify-end mb-2", children: jsxRuntimeExports.jsx("button", { type: "button", onClick: startAdd, disabled: loadingRowIndex !== null, className: "px-3 py-1 text-sm disabled:opacity-50 disabled:cursor-not-allowed", style: {
|
|
8862
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
8863
|
+
border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
|
|
8864
|
+
backgroundColor: 'var(--owt-color-primary, #F5BB1A)',
|
|
8865
|
+
color: 'var(--owt-color-bg, #FFFFFF)',
|
|
8866
|
+
}, children: translate('table.addRecord') || 'Add New Record' }) })), jsxRuntimeExports.jsx("div", { className: "overflow-x-auto border", style: { borderRadius: 'var(--owt-widget-table-border-radius, 15px)', borderColor: 'var(--owt-widget-table-border-color, #C4C4C4)' }, 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: [columns.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) || isAnyRowEditing || isSectionEditMode ? (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' })) : null] }) }), jsxRuntimeExports.jsxs("tbody", { style: { backgroundColor: 'var(--owt-widget-table-body-bg, #FFFFFF)' }, children: [rows.length === 0 && !isAdding && (jsxRuntimeExports.jsx("tr", { children: jsxRuntimeExports.jsxs("td", { colSpan: columns.length + (((operations.edit || operations.remove) && !isReadonly) || isSectionEditMode ? 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) => {
|
|
8716
8867
|
const isEditing = isRowEditing(rowIndex);
|
|
8717
8868
|
const isLoading = loadingRowIndex === rowIndex;
|
|
8718
|
-
return (jsxRuntimeExports.jsxs("tr", { className:
|
|
8869
|
+
return (jsxRuntimeExports.jsxs("tr", { className: isLoading ? 'opacity-50' : '', style: {
|
|
8870
|
+
borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)',
|
|
8871
|
+
backgroundColor: isEditing
|
|
8872
|
+
? 'var(--owt-widget-table-editing-row-bg, #FBE6AA)'
|
|
8873
|
+
: row.edit_action === 'DELETE'
|
|
8874
|
+
? 'var(--owt-widget-table-deleted-row-bg, #FEE2E2)'
|
|
8875
|
+
: undefined,
|
|
8876
|
+
}, children: [columns.map((col) => {
|
|
8719
8877
|
return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: renderCell(rowIndex, col, row) }, col['column-key']));
|
|
8720
8878
|
}), ((operations.edit || operations.remove) && !isReadonly) || isEditing || isSectionEditMode ? (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", style: { minWidth: '120px' }, children: isEditing ? (
|
|
8721
8879
|
// Show OK (Save)/Cancel buttons when row is being edited (works in both section edit mode and normal mode)
|
|
8722
|
-
jsxRuntimeExports.jsxs("div", { className: "flex flex-row gap-2 items-center", style: { width: '100%' }, children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: saveEdit, disabled: isLoading, className: "px-3 py-1 text-xs font-medium
|
|
8880
|
+
jsxRuntimeExports.jsxs("div", { className: "flex flex-row gap-2 items-center", style: { width: '100%' }, children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: saveEdit, disabled: isLoading, className: "px-3 py-1 text-xs font-medium disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap flex-shrink-0", style: {
|
|
8723
8881
|
display: 'inline-block',
|
|
8724
8882
|
minWidth: '60px',
|
|
8725
|
-
backgroundColor: '#
|
|
8726
|
-
color: '#
|
|
8883
|
+
backgroundColor: 'var(--owt-color-success, #16A34A)',
|
|
8884
|
+
color: 'var(--owt-color-bg, #FFFFFF)',
|
|
8727
8885
|
border: 'none',
|
|
8728
|
-
borderRadius: '
|
|
8729
|
-
}, children: translate('common.ok') || 'OK' }), jsxRuntimeExports.jsx("button", { type: "button", onClick: cancelEdit, disabled: isLoading, className: "px-3 py-1 text-xs font-medium
|
|
8886
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
8887
|
+
}, children: translate('common.ok') || 'OK' }), jsxRuntimeExports.jsx("button", { type: "button", onClick: cancelEdit, disabled: isLoading, className: "px-3 py-1 text-xs font-medium disabled:opacity-50 disabled:cursor-not-allowed whitespace-nowrap flex-shrink-0", style: {
|
|
8888
|
+
display: 'inline-block',
|
|
8889
|
+
minWidth: '60px',
|
|
8890
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
8891
|
+
border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
|
|
8892
|
+
backgroundColor: 'var(--owt-btn-secondary-bg, #FFFFFF)',
|
|
8893
|
+
color: 'var(--owt-btn-secondary-color, #011627)',
|
|
8894
|
+
}, children: translate('common.cancel') || 'Cancel' })] })) : (
|
|
8730
8895
|
// Show Edit/Delete buttons when row is not being edited
|
|
8731
|
-
jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [operations.edit && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => startEdit(rowIndex), disabled: isAnyRowEditing || isLoading, className: "px-3 py-1 text-xs
|
|
8732
|
-
|
|
8896
|
+
jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [operations.edit && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => startEdit(rowIndex), disabled: isAnyRowEditing || isLoading, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
|
|
8897
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
8898
|
+
color: 'var(--owt-color-primary-dark, #F07B1A)',
|
|
8899
|
+
backgroundColor: 'transparent',
|
|
8900
|
+
border: 'none',
|
|
8901
|
+
}, children: translate('common.edit') || 'Edit' })), operations.remove && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => deleteRow(rowIndex), disabled: isAnyRowEditing || isLoading, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
|
|
8902
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
8903
|
+
color: 'var(--owt-color-error, #B91C1C)',
|
|
8904
|
+
backgroundColor: 'transparent',
|
|
8905
|
+
border: 'none',
|
|
8906
|
+
}, children: translate('common.remove') || 'Delete' }))] })) })) : null] }, rowIndex));
|
|
8907
|
+
}), isAdding && newRowData && (jsxRuntimeExports.jsxs("tr", { style: { backgroundColor: 'var(--owt-widget-table-editing-row-bg, #FBE6AA)' }, children: [columns.map((col) => (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: renderCell(rows.length, col, { ...newRowData, edit_action: 'ADD' }) }, col['column-key']))), jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: saveAdd, disabled: loadingRowIndex === -1, className: "px-3 py-1 text-xs disabled:opacity-50", style: {
|
|
8908
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
8909
|
+
backgroundColor: 'var(--owt-color-success, #16A34A)',
|
|
8910
|
+
color: 'var(--owt-color-bg, #FFFFFF)',
|
|
8911
|
+
border: 'none',
|
|
8912
|
+
}, children: translate('common.save') || 'Save' }), jsxRuntimeExports.jsx("button", { type: "button", onClick: () => {
|
|
8733
8913
|
setIsAdding(false);
|
|
8734
8914
|
setNewRowData(null);
|
|
8735
|
-
}, disabled: loadingRowIndex === -1, className: "px-3 py-1 text-xs
|
|
8915
|
+
}, disabled: loadingRowIndex === -1, className: "px-3 py-1 text-xs disabled:opacity-50", style: {
|
|
8916
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
8917
|
+
border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
|
|
8918
|
+
backgroundColor: 'var(--owt-btn-secondary-bg, #FFFFFF)',
|
|
8919
|
+
color: 'var(--owt-btn-secondary-color, #011627)',
|
|
8920
|
+
}, children: translate('common.cancel') || 'Cancel' })] }) })] }))] })] }) }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-sm mt-1", style: { color: 'var(--owt-widget-error-color, #B91C1C)' }, children: error[0] }))] })] }));
|
|
8736
8921
|
};
|
|
8737
8922
|
|
|
8738
8923
|
const ProfileWidget = ({ config }) => {
|
|
@@ -8821,7 +9006,7 @@ const ProfileWidget = ({ config }) => {
|
|
|
8821
9006
|
// Get format options (using index access for widget-specific properties)
|
|
8822
9007
|
const format = widgetConfig['widget-data-format'] || {};
|
|
8823
9008
|
const imageSize = format.imageSize || 80;
|
|
8824
|
-
const nameColor = format.nameColor || '#
|
|
9009
|
+
const nameColor = format.nameColor || 'var(--owt-color-primary-dark, #F07B1A)';
|
|
8825
9010
|
const showIdLabel = format.showIdLabel !== false; // Default to true
|
|
8826
9011
|
// Generate a unique class ID for this widget instance
|
|
8827
9012
|
const widgetClassId = `profile-widget-${config['widget-id']}`;
|
|
@@ -8844,8 +9029,8 @@ const ProfileWidget = ({ config }) => {
|
|
|
8844
9029
|
height: ${imageSize}px;
|
|
8845
9030
|
border-radius: 8px;
|
|
8846
9031
|
object-fit: cover;
|
|
8847
|
-
background-color: #e5e7eb;
|
|
8848
|
-
border: 2px solid #d1d5db;
|
|
9032
|
+
background-color: var(--owt-color-border-light, #e5e7eb);
|
|
9033
|
+
border: 2px solid var(--owt-color-border, #d1d5db);
|
|
8849
9034
|
flex-shrink: 0;
|
|
8850
9035
|
}
|
|
8851
9036
|
|
|
@@ -8853,8 +9038,8 @@ const ProfileWidget = ({ config }) => {
|
|
|
8853
9038
|
width: ${imageSize}px;
|
|
8854
9039
|
height: ${imageSize}px;
|
|
8855
9040
|
border-radius: 8px;
|
|
8856
|
-
background-color: #e5e7eb;
|
|
8857
|
-
border: 2px solid #d1d5db;
|
|
9041
|
+
background-color: var(--owt-color-border-light, #e5e7eb);
|
|
9042
|
+
border: 2px solid var(--owt-color-border, #d1d5db);
|
|
8858
9043
|
display: flex;
|
|
8859
9044
|
align-items: center;
|
|
8860
9045
|
justify-content: center;
|
|
@@ -8895,12 +9080,12 @@ const ProfileWidget = ({ config }) => {
|
|
|
8895
9080
|
}
|
|
8896
9081
|
|
|
8897
9082
|
.${widgetClassId} .profile-id-label {
|
|
8898
|
-
color: #6b7280;
|
|
9083
|
+
color: var(--owt-color-text-muted, #6b7280);
|
|
8899
9084
|
font-weight: 500;
|
|
8900
9085
|
}
|
|
8901
9086
|
|
|
8902
9087
|
.${widgetClassId} .profile-id-value {
|
|
8903
|
-
color: #111827;
|
|
9088
|
+
color: var(--owt-color-text, #111827);
|
|
8904
9089
|
font-weight: 400;
|
|
8905
9090
|
}
|
|
8906
9091
|
` }), jsxRuntimeExports.jsxs("div", { className: widgetClassId, children: [jsxRuntimeExports.jsxs("div", { className: "profile-avatar-container", children: [imageUrl ? (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: displayName || 'Profile', className: "profile-avatar", onError: (e) => {
|
|
@@ -8991,7 +9176,7 @@ const TextAreaWidget = ({ config }) => {
|
|
|
8991
9176
|
minHeight: `${rows * 1.5 * 14 + 16}px`, // Approximate height based on rows
|
|
8992
9177
|
} }), showCharCounter && (jsxRuntimeExports.jsx("div", { className: "absolute bottom-2 right-2 text-xs px-1 rounded", style: {
|
|
8993
9178
|
fontFamily: 'Roboto, sans-serif',
|
|
8994
|
-
color: maxLength && currentLength > maxLength ? '#EF4444' : '#6B7280',
|
|
9179
|
+
color: maxLength && currentLength > maxLength ? 'var(--owt-widget-error-color, #EF4444)' : 'var(--owt-widget-helptext-color, #6B7280)',
|
|
8995
9180
|
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
|
8996
9181
|
}, children: charCounterText }))] }), hasError && (jsxRuntimeExports.jsx("p", { className: "text-red-500 text-sm mt-1", children: errorMessage }))] })] }) }));
|
|
8997
9182
|
};
|
|
@@ -9126,18 +9311,7 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9126
9311
|
result = searchIn(schemaData);
|
|
9127
9312
|
return result;
|
|
9128
9313
|
}, [paths, values, schemaData]);
|
|
9129
|
-
const
|
|
9130
|
-
const imageUrlVal = findValue('imageUrl');
|
|
9131
|
-
const [previewUrl, setPreviewUrl] = React.useState(null);
|
|
9132
|
-
React.useEffect(() => {
|
|
9133
|
-
if (imageVal instanceof File) {
|
|
9134
|
-
const url = URL.createObjectURL(imageVal);
|
|
9135
|
-
setPreviewUrl(url);
|
|
9136
|
-
return () => URL.revokeObjectURL(url);
|
|
9137
|
-
}
|
|
9138
|
-
setPreviewUrl(null);
|
|
9139
|
-
}, [imageVal]);
|
|
9140
|
-
const displayImageUrl = previewUrl || (typeof imageUrlVal === 'string' && imageUrlVal ? imageUrlVal : null);
|
|
9314
|
+
const imageUrl = findValue('image') || null;
|
|
9141
9315
|
const displayName = findValue('name') || '';
|
|
9142
9316
|
const functionalId = findValue('functionalId') || '';
|
|
9143
9317
|
const statusValue = findValue('status') || '';
|
|
@@ -9149,7 +9323,7 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9149
9323
|
// ── Format options ────────────────────────────────────────────
|
|
9150
9324
|
const format = (widgetConfig['widget-data-format'] || {});
|
|
9151
9325
|
const imageSize = format.imageSize || 120;
|
|
9152
|
-
const nameColor = format.nameColor || '#
|
|
9326
|
+
const nameColor = format.nameColor || 'var(--owt-color-primary-dark, #F07B1A)';
|
|
9153
9327
|
const statusColors = {
|
|
9154
9328
|
...DEFAULT_STATUS_COLORS,
|
|
9155
9329
|
...(format.statusColors || {}),
|
|
@@ -9169,21 +9343,19 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9169
9343
|
const opt = statusOptions.find((o) => String(o.value).toLowerCase() === String(statusValue).toLowerCase());
|
|
9170
9344
|
return opt ? opt.label : String(statusValue);
|
|
9171
9345
|
}, [statusValue, statusOptions]);
|
|
9172
|
-
const statusColor = statusColors[String(statusValue).toLowerCase()] || '#6B7280';
|
|
9173
|
-
// ── Image edit helpers ───────────────────────────────────────
|
|
9174
|
-
const fileInputRef = React.useRef(null);
|
|
9175
|
-
const handleImageUpload = React.useCallback((e) => {
|
|
9176
|
-
const file = e.target.files?.[0];
|
|
9177
|
-
if (!file)
|
|
9178
|
-
return;
|
|
9179
|
-
updateFieldValue('image', file);
|
|
9180
|
-
e.target.value = '';
|
|
9181
|
-
}, [updateFieldValue]);
|
|
9182
|
-
const handleImageDelete = React.useCallback(() => {
|
|
9183
|
-
updateFieldValue('image', '');
|
|
9184
|
-
}, [updateFieldValue]);
|
|
9346
|
+
const statusColor = statusColors[String(statusValue).toLowerCase()] || 'var(--owt-color-text-muted, #6B7280)';
|
|
9185
9347
|
// ── Scoped class for CSS isolation ────────────────────────────
|
|
9186
9348
|
const cls = `header-section-widget-${widgetConfig['widget-id']}`;
|
|
9349
|
+
// ── Indicator dot component ───────────────────────────────────
|
|
9350
|
+
const Dot = ({ color }) => (jsxRuntimeExports.jsx("span", { style: {
|
|
9351
|
+
display: 'inline-block',
|
|
9352
|
+
width: 8,
|
|
9353
|
+
height: 8,
|
|
9354
|
+
borderRadius: '50%',
|
|
9355
|
+
backgroundColor: color,
|
|
9356
|
+
flexShrink: 0,
|
|
9357
|
+
marginTop: 6,
|
|
9358
|
+
} }));
|
|
9187
9359
|
// ── RENDER ────────────────────────────────────────────────────
|
|
9188
9360
|
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
|
|
9189
9361
|
.${cls} {
|
|
@@ -9217,8 +9389,8 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9217
9389
|
height: ${imageSize}px;
|
|
9218
9390
|
border-radius: 8px;
|
|
9219
9391
|
object-fit: cover;
|
|
9220
|
-
background-color: #e5e7eb;
|
|
9221
|
-
border: 2px solid #d1d5db;
|
|
9392
|
+
background-color: var(--owt-color-border-light, #e5e7eb);
|
|
9393
|
+
border: 2px solid var(--owt-color-border, #d1d5db);
|
|
9222
9394
|
flex-shrink: 0;
|
|
9223
9395
|
}
|
|
9224
9396
|
|
|
@@ -9226,8 +9398,8 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9226
9398
|
width: ${imageSize}px;
|
|
9227
9399
|
height: ${imageSize}px;
|
|
9228
9400
|
border-radius: 8px;
|
|
9229
|
-
background-color: #e5e7eb;
|
|
9230
|
-
border: 2px solid #d1d5db;
|
|
9401
|
+
background-color: var(--owt-color-border-light, #e5e7eb);
|
|
9402
|
+
border: 2px solid var(--owt-color-border, #d1d5db);
|
|
9231
9403
|
display: flex;
|
|
9232
9404
|
align-items: center;
|
|
9233
9405
|
justify-content: center;
|
|
@@ -9242,56 +9414,6 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9242
9414
|
border-radius: 8px;
|
|
9243
9415
|
}
|
|
9244
9416
|
|
|
9245
|
-
.${cls} .hdr-avatar-wrapper {
|
|
9246
|
-
position: relative;
|
|
9247
|
-
width: ${imageSize}px;
|
|
9248
|
-
height: ${imageSize}px;
|
|
9249
|
-
flex-shrink: 0;
|
|
9250
|
-
}
|
|
9251
|
-
|
|
9252
|
-
.${cls} .hdr-avatar-overlay {
|
|
9253
|
-
position: absolute;
|
|
9254
|
-
inset: 0;
|
|
9255
|
-
border-radius: 8px;
|
|
9256
|
-
background: rgba(0, 0, 0, 0.55);
|
|
9257
|
-
display: flex;
|
|
9258
|
-
flex-direction: column;
|
|
9259
|
-
align-items: center;
|
|
9260
|
-
justify-content: center;
|
|
9261
|
-
gap: 6px;
|
|
9262
|
-
opacity: 0;
|
|
9263
|
-
transition: opacity 0.2s;
|
|
9264
|
-
}
|
|
9265
|
-
|
|
9266
|
-
.${cls} .hdr-avatar-wrapper:hover .hdr-avatar-overlay {
|
|
9267
|
-
opacity: 1;
|
|
9268
|
-
}
|
|
9269
|
-
|
|
9270
|
-
.${cls} .hdr-avatar-action {
|
|
9271
|
-
display: flex;
|
|
9272
|
-
align-items: center;
|
|
9273
|
-
gap: 5px;
|
|
9274
|
-
padding: 5px 14px;
|
|
9275
|
-
border: none;
|
|
9276
|
-
border-radius: 4px;
|
|
9277
|
-
background: rgba(255, 255, 255, 0.92);
|
|
9278
|
-
color: #374151;
|
|
9279
|
-
font-size: 0.7rem;
|
|
9280
|
-
font-weight: 500;
|
|
9281
|
-
cursor: pointer;
|
|
9282
|
-
font-family: Roboto, sans-serif;
|
|
9283
|
-
transition: background 0.15s;
|
|
9284
|
-
white-space: nowrap;
|
|
9285
|
-
}
|
|
9286
|
-
|
|
9287
|
-
.${cls} .hdr-avatar-action:hover {
|
|
9288
|
-
background: #fff;
|
|
9289
|
-
}
|
|
9290
|
-
|
|
9291
|
-
.${cls} .hdr-avatar-action--delete {
|
|
9292
|
-
color: #DC2626;
|
|
9293
|
-
}
|
|
9294
|
-
|
|
9295
9417
|
.${cls} .hdr-info {
|
|
9296
9418
|
display: flex;
|
|
9297
9419
|
flex-direction: column;
|
|
@@ -9323,7 +9445,7 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9323
9445
|
}
|
|
9324
9446
|
|
|
9325
9447
|
.${cls} .hdr-field-value {
|
|
9326
|
-
color: #111827;
|
|
9448
|
+
color: var(--owt-color-text, #111827);
|
|
9327
9449
|
font-weight: 500;
|
|
9328
9450
|
}
|
|
9329
9451
|
|
|
@@ -9350,41 +9472,41 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9350
9472
|
}
|
|
9351
9473
|
|
|
9352
9474
|
.${cls} .hdr-meta-value {
|
|
9353
|
-
color: #111827;
|
|
9475
|
+
color: var(--owt-color-text, #111827);
|
|
9354
9476
|
font-weight: 500;
|
|
9355
9477
|
}
|
|
9356
9478
|
|
|
9357
9479
|
.${cls} .hdr-select {
|
|
9358
9480
|
height: 32px;
|
|
9359
9481
|
padding: 0 8px;
|
|
9360
|
-
border: 1px solid #d1d5db;
|
|
9482
|
+
border: 1px solid var(--owt-widget-input-border, #d1d5db);
|
|
9361
9483
|
border-radius: 6px;
|
|
9362
9484
|
font-size: 0.875rem;
|
|
9363
9485
|
font-family: Roboto, sans-serif;
|
|
9364
|
-
background: #fff;
|
|
9486
|
+
background: var(--owt-widget-input-bg, #fff);
|
|
9365
9487
|
min-width: 140px;
|
|
9366
|
-
color: #374151;
|
|
9488
|
+
color: var(--owt-btn-primary-color, #374151);
|
|
9367
9489
|
}
|
|
9368
9490
|
.${cls} .hdr-select:focus {
|
|
9369
9491
|
outline: none;
|
|
9370
|
-
border-color: #
|
|
9492
|
+
border-color: var(--owt-widget-input-focus-border, #F07B1A);
|
|
9371
9493
|
box-shadow: 0 0 0 2px rgba(237, 124, 34, 0.15);
|
|
9372
9494
|
}
|
|
9373
9495
|
|
|
9374
9496
|
.${cls} .hdr-input {
|
|
9375
9497
|
height: 32px;
|
|
9376
9498
|
padding: 0 8px;
|
|
9377
|
-
border: 1px solid #d1d5db;
|
|
9499
|
+
border: 1px solid var(--owt-widget-input-border, #d1d5db);
|
|
9378
9500
|
border-radius: 6px;
|
|
9379
9501
|
font-size: 0.875rem;
|
|
9380
9502
|
font-family: Roboto, sans-serif;
|
|
9381
|
-
background: #fff;
|
|
9503
|
+
background: var(--owt-widget-input-bg, #fff);
|
|
9382
9504
|
min-width: 140px;
|
|
9383
|
-
color: #374151;
|
|
9505
|
+
color: var(--owt-btn-primary-color, #374151);
|
|
9384
9506
|
}
|
|
9385
9507
|
.${cls} .hdr-input:focus {
|
|
9386
9508
|
outline: none;
|
|
9387
|
-
border-color: #
|
|
9509
|
+
border-color: var(--owt-widget-input-focus-border, #F07B1A);
|
|
9388
9510
|
box-shadow: 0 0 0 2px rgba(237, 124, 34, 0.15);
|
|
9389
9511
|
}
|
|
9390
9512
|
|
|
@@ -9396,13 +9518,261 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9396
9518
|
min-width: 0;
|
|
9397
9519
|
}
|
|
9398
9520
|
}
|
|
9399
|
-
` }), jsxRuntimeExports.jsxs("div", { className: cls, children: [jsxRuntimeExports.jsxs("div", { className: "hdr-left", children: [jsxRuntimeExports.jsxs("div", {
|
|
9521
|
+
` }), jsxRuntimeExports.jsxs("div", { className: cls, children: [jsxRuntimeExports.jsxs("div", { className: "hdr-left", children: [jsxRuntimeExports.jsxs("div", { children: [imageUrl ? (jsxRuntimeExports.jsx("img", { src: imageUrl, alt: displayName || 'Profile', className: "hdr-avatar", onError: (e) => {
|
|
9400
9522
|
e.target.style.display = 'none';
|
|
9401
9523
|
const placeholder = e.target
|
|
9402
9524
|
.parentElement?.querySelector('.hdr-avatar-placeholder');
|
|
9403
9525
|
if (placeholder)
|
|
9404
9526
|
placeholder.style.display = 'flex';
|
|
9405
|
-
} })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display:
|
|
9527
|
+
} })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display: imageUrl ? 'none' : 'flex' }, children: jsxRuntimeExports.jsx("img", { src: img$f, alt: "Profile Placeholder" }) })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-info", children: [displayName && jsxRuntimeExports.jsx("div", { className: "hdr-name", children: displayName }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: "#9CA3AF" }), jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('functionalId'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: functionalId || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: isReadonly ? statusColor : '#F59E0B' }), jsxRuntimeExports.jsx("span", { className: "hdr-field-label", children: getLabel('status') }), isReadonly ? (statusLabel ? (jsxRuntimeExports.jsx("span", { className: "hdr-status-badge", style: { backgroundColor: statusColor }, children: statusLabel })) : (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: "-" }))) : (jsxRuntimeExports.jsxs("select", { className: "hdr-select", value: statusValue, onChange: (e) => updateFieldValue('status', e.target.value), children: [jsxRuntimeExports.jsx("option", { value: "", children: getLabel('select') }), statusOptions.map((opt) => (jsxRuntimeExports.jsx("option", { value: opt.value, children: opt.label }, opt.value)))] }))] }), jsxRuntimeExports.jsxs("div", { className: "hdr-field-row", children: [jsxRuntimeExports.jsx(Dot, { color: isReadonly ? '#9CA3AF' : '#F59E0B' }), jsxRuntimeExports.jsxs("span", { className: "hdr-field-label", children: [getLabel('statusReason'), " :"] }), isReadonly ? (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: statusReason || '-' })) : (jsxRuntimeExports.jsx("input", { type: "text", className: "hdr-input", value: statusReason, placeholder: getLabel('enterReason'), onChange: (e) => updateFieldValue('statusReason', e.target.value) }))] })] })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-right", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('createdAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: createdAt || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedBy'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedBy || '-' })] }), jsxRuntimeExports.jsxs("div", { className: "hdr-meta-row", children: [jsxRuntimeExports.jsxs("span", { className: "hdr-meta-label", children: [getLabel('lastApprovedAt'), " :"] }), jsxRuntimeExports.jsx("span", { className: "hdr-meta-value", children: lastApprovedAt || '-' })] })] })] })] }));
|
|
9528
|
+
};
|
|
9529
|
+
|
|
9530
|
+
function tryFormatDateTime(value) {
|
|
9531
|
+
if (typeof value !== 'string' || !value)
|
|
9532
|
+
return value ? String(value) : '-';
|
|
9533
|
+
const d = new Date(value);
|
|
9534
|
+
if (Number.isNaN(d.getTime()))
|
|
9535
|
+
return value;
|
|
9536
|
+
try {
|
|
9537
|
+
return d.toLocaleString(undefined, {
|
|
9538
|
+
year: 'numeric',
|
|
9539
|
+
month: 'short',
|
|
9540
|
+
day: '2-digit',
|
|
9541
|
+
hour: '2-digit',
|
|
9542
|
+
minute: '2-digit',
|
|
9543
|
+
});
|
|
9544
|
+
}
|
|
9545
|
+
catch {
|
|
9546
|
+
return value;
|
|
9547
|
+
}
|
|
9548
|
+
}
|
|
9549
|
+
function pickLatestScore(scores) {
|
|
9550
|
+
if (!scores || scores.length === 0)
|
|
9551
|
+
return null;
|
|
9552
|
+
const withTime = scores
|
|
9553
|
+
.map((s) => {
|
|
9554
|
+
const t = typeof s?.computed_at === 'string' ? new Date(s.computed_at).getTime() : NaN;
|
|
9555
|
+
return { s, t };
|
|
9556
|
+
})
|
|
9557
|
+
.filter((x) => !Number.isNaN(x.t));
|
|
9558
|
+
if (withTime.length === 0)
|
|
9559
|
+
return scores[0] || null;
|
|
9560
|
+
withTime.sort((a, b) => b.t - a.t);
|
|
9561
|
+
return withTime[0]?.s || null;
|
|
9562
|
+
}
|
|
9563
|
+
/**
|
|
9564
|
+
* Scores Display Widget - full-width, view-only widget
|
|
9565
|
+
*
|
|
9566
|
+
* Expected config (reference):
|
|
9567
|
+
* {
|
|
9568
|
+
* "widget": "scores-display",
|
|
9569
|
+
* "widget-type": "group",
|
|
9570
|
+
* "widget-id": "record-scores",
|
|
9571
|
+
* "widget-data-source": {
|
|
9572
|
+
* "type": "api",
|
|
9573
|
+
* "service": "staff-portal-api",
|
|
9574
|
+
* "endpoint": "get_scores",
|
|
9575
|
+
* "method": "POST",
|
|
9576
|
+
* "params": { "internal_record_id_path": "internal_record_id" }
|
|
9577
|
+
* }
|
|
9578
|
+
* }
|
|
9579
|
+
*
|
|
9580
|
+
* The host's `dataSourceRequestHandler` is invoked with:
|
|
9581
|
+
* - service: config.widget-data-source.service
|
|
9582
|
+
* - endpoint: config.widget-data-source.endpoint
|
|
9583
|
+
* - method: config.widget-data-source.method (default POST)
|
|
9584
|
+
* - params: { internal_record_id: <resolved from internal_record_id_path> }
|
|
9585
|
+
*/
|
|
9586
|
+
const ScoresDisplayWidget = ({ config, dataSourceRequestHandler: propHandler, schemaData: propSchemaData, }) => {
|
|
9587
|
+
const { dataSourceRequestHandler: ctxHandler, schemaData: ctxSchemaData } = useWidgetContext();
|
|
9588
|
+
const handler = propHandler || ctxHandler;
|
|
9589
|
+
const schemaData = propSchemaData || ctxSchemaData || {};
|
|
9590
|
+
const values = reactRedux.useSelector((state) => state.widget.values);
|
|
9591
|
+
const api = config['widget-data-source'];
|
|
9592
|
+
const isApi = api?.type === 'api';
|
|
9593
|
+
const apiDs = isApi ? api : null;
|
|
9594
|
+
const internalIdPath = React.useMemo(() => {
|
|
9595
|
+
if (!apiDs)
|
|
9596
|
+
return undefined;
|
|
9597
|
+
const p = apiDs.params || {};
|
|
9598
|
+
const fromParams = p.internal_record_id_path || p.internalRecordIdPath;
|
|
9599
|
+
const fromConfig = typeof config.internal_record_id_path === 'string'
|
|
9600
|
+
? config.internal_record_id_path
|
|
9601
|
+
: undefined;
|
|
9602
|
+
return fromParams || fromConfig;
|
|
9603
|
+
}, [apiDs, config]);
|
|
9604
|
+
const internalRecordId = React.useMemo(() => {
|
|
9605
|
+
if (!internalIdPath)
|
|
9606
|
+
return undefined;
|
|
9607
|
+
const fromValues = getValueByPath(values || {}, internalIdPath);
|
|
9608
|
+
if (fromValues !== undefined && fromValues !== null && String(fromValues).trim() !== '') {
|
|
9609
|
+
return String(fromValues);
|
|
9610
|
+
}
|
|
9611
|
+
const fromSchema = getValueByPath(schemaData || {}, internalIdPath);
|
|
9612
|
+
if (fromSchema !== undefined && fromSchema !== null && String(fromSchema).trim() !== '') {
|
|
9613
|
+
return String(fromSchema);
|
|
9614
|
+
}
|
|
9615
|
+
return undefined;
|
|
9616
|
+
}, [internalIdPath, values, schemaData]);
|
|
9617
|
+
const [loading, setLoading] = React.useState(false);
|
|
9618
|
+
const [error, setError] = React.useState(null);
|
|
9619
|
+
const [response, setResponse] = React.useState(null);
|
|
9620
|
+
React.useEffect(() => {
|
|
9621
|
+
let cancelled = false;
|
|
9622
|
+
const load = async () => {
|
|
9623
|
+
if (!apiDs) {
|
|
9624
|
+
setError('Scores widget requires an API data source.');
|
|
9625
|
+
setResponse(null);
|
|
9626
|
+
return;
|
|
9627
|
+
}
|
|
9628
|
+
if (!handler) {
|
|
9629
|
+
setError(null);
|
|
9630
|
+
setResponse(null);
|
|
9631
|
+
return;
|
|
9632
|
+
}
|
|
9633
|
+
const service = apiDs.service;
|
|
9634
|
+
const endpoint = apiDs.endpoint;
|
|
9635
|
+
const method = apiDs.method || 'POST';
|
|
9636
|
+
if (!service || !endpoint) {
|
|
9637
|
+
setError('Scores widget API data source is missing service/endpoint.');
|
|
9638
|
+
setResponse(null);
|
|
9639
|
+
return;
|
|
9640
|
+
}
|
|
9641
|
+
if (!internalRecordId) {
|
|
9642
|
+
setError(null);
|
|
9643
|
+
setResponse(null);
|
|
9644
|
+
return;
|
|
9645
|
+
}
|
|
9646
|
+
try {
|
|
9647
|
+
setLoading(true);
|
|
9648
|
+
setError(null);
|
|
9649
|
+
const rawParams = apiDs.params || {};
|
|
9650
|
+
// Never pass the path helper through to the API.
|
|
9651
|
+
const { internal_record_id_path, internalRecordIdPath, ...rest } = rawParams;
|
|
9652
|
+
void internal_record_id_path;
|
|
9653
|
+
void internalRecordIdPath;
|
|
9654
|
+
const params = {
|
|
9655
|
+
...rest,
|
|
9656
|
+
internal_record_id: internalRecordId,
|
|
9657
|
+
};
|
|
9658
|
+
const res = await handler(service, endpoint, method, params, {
|
|
9659
|
+
headers: apiDs.headers,
|
|
9660
|
+
});
|
|
9661
|
+
if (cancelled)
|
|
9662
|
+
return;
|
|
9663
|
+
// Accept either direct payload or OpenG2P wrapper objects.
|
|
9664
|
+
const envelope = res && typeof res === 'object' ? res : null;
|
|
9665
|
+
const payload = envelope?.response_body?.response_payload ?? envelope?.data ?? res;
|
|
9666
|
+
if (payload && typeof payload === 'object' && !Array.isArray(payload)) {
|
|
9667
|
+
setResponse(payload);
|
|
9668
|
+
}
|
|
9669
|
+
else {
|
|
9670
|
+
setResponse({ scores: Array.isArray(payload) ? payload : [] });
|
|
9671
|
+
}
|
|
9672
|
+
}
|
|
9673
|
+
catch (e) {
|
|
9674
|
+
if (cancelled)
|
|
9675
|
+
return;
|
|
9676
|
+
const maybeErr = e;
|
|
9677
|
+
const msg = maybeErr && typeof maybeErr === 'object' && typeof maybeErr.message === 'string'
|
|
9678
|
+
? maybeErr.message
|
|
9679
|
+
: 'Failed to load scores.';
|
|
9680
|
+
setError(msg);
|
|
9681
|
+
setResponse(null);
|
|
9682
|
+
}
|
|
9683
|
+
finally {
|
|
9684
|
+
if (!cancelled)
|
|
9685
|
+
setLoading(false);
|
|
9686
|
+
}
|
|
9687
|
+
};
|
|
9688
|
+
load();
|
|
9689
|
+
return () => {
|
|
9690
|
+
cancelled = true;
|
|
9691
|
+
};
|
|
9692
|
+
}, [apiDs, handler, internalRecordId]);
|
|
9693
|
+
const latest = React.useMemo(() => pickLatestScore(response?.scores), [response]);
|
|
9694
|
+
const cls = `scores-display-widget-${config['widget-id']}`;
|
|
9695
|
+
const scoreType = latest?.score_type ? String(latest.score_type) : '-';
|
|
9696
|
+
const scoreValue = latest?.computed_score !== undefined && latest?.computed_score !== null && String(latest.computed_score) !== ''
|
|
9697
|
+
? String(latest.computed_score)
|
|
9698
|
+
: '-';
|
|
9699
|
+
const computedAt = tryFormatDateTime(latest?.computed_at);
|
|
9700
|
+
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
|
|
9701
|
+
.${cls} {
|
|
9702
|
+
width: 100%;
|
|
9703
|
+
font-family: Roboto, sans-serif;
|
|
9704
|
+
padding: 0;
|
|
9705
|
+
display: flex;
|
|
9706
|
+
flex-direction: column;
|
|
9707
|
+
gap: 8px;
|
|
9708
|
+
}
|
|
9709
|
+
|
|
9710
|
+
.${cls} .scores-subtle {
|
|
9711
|
+
font-size: 13px;
|
|
9712
|
+
color: var(--owt-color-text-muted, #727474);
|
|
9713
|
+
font-weight: 400;
|
|
9714
|
+
}
|
|
9715
|
+
|
|
9716
|
+
.${cls} .scores-card {
|
|
9717
|
+
width: 100%;
|
|
9718
|
+
border: none;
|
|
9719
|
+
border-radius: 0;
|
|
9720
|
+
background: transparent;
|
|
9721
|
+
padding: 0;
|
|
9722
|
+
display: grid;
|
|
9723
|
+
grid-template-columns: 1fr 1fr 1fr;
|
|
9724
|
+
gap: 16px;
|
|
9725
|
+
align-items: center;
|
|
9726
|
+
}
|
|
9727
|
+
|
|
9728
|
+
.${cls} .scores-col {
|
|
9729
|
+
min-width: 0;
|
|
9730
|
+
display: flex;
|
|
9731
|
+
flex-direction: column;
|
|
9732
|
+
gap: 6px;
|
|
9733
|
+
}
|
|
9734
|
+
|
|
9735
|
+
.${cls} .scores-label {
|
|
9736
|
+
font-size: 12px;
|
|
9737
|
+
color: var(--owt-color-text-muted, #727474);
|
|
9738
|
+
font-weight: 600;
|
|
9739
|
+
letter-spacing: 0.25px;
|
|
9740
|
+
text-transform: uppercase;
|
|
9741
|
+
}
|
|
9742
|
+
|
|
9743
|
+
.${cls} .scores-value {
|
|
9744
|
+
font-size: 16px;
|
|
9745
|
+
font-weight: 600;
|
|
9746
|
+
color: var(--owt-color-text, #011627);
|
|
9747
|
+
line-height: 1.25;
|
|
9748
|
+
word-break: break-word;
|
|
9749
|
+
}
|
|
9750
|
+
|
|
9751
|
+
.${cls} .scores-value--highlight {
|
|
9752
|
+
font-weight: 800;
|
|
9753
|
+
color: var(--owt-color-primary-dark, #F07B1A);
|
|
9754
|
+
}
|
|
9755
|
+
|
|
9756
|
+
.${cls} .scores-value-wrap {
|
|
9757
|
+
display: inline-flex;
|
|
9758
|
+
align-items: baseline;
|
|
9759
|
+
gap: 10px;
|
|
9760
|
+
flex-wrap: wrap;
|
|
9761
|
+
}
|
|
9762
|
+
|
|
9763
|
+
.${cls} .scores-value-badge { display: inline; }
|
|
9764
|
+
|
|
9765
|
+
.${cls} .scores-statusline {
|
|
9766
|
+
grid-column: 1 / -1;
|
|
9767
|
+
margin-top: 2px;
|
|
9768
|
+
}
|
|
9769
|
+
|
|
9770
|
+
@media (max-width: 768px) {
|
|
9771
|
+
.${cls} .scores-card {
|
|
9772
|
+
grid-template-columns: 1fr;
|
|
9773
|
+
}
|
|
9774
|
+
}
|
|
9775
|
+
` }), jsxRuntimeExports.jsx("div", { className: cls, children: jsxRuntimeExports.jsxs("div", { className: "scores-card", children: [jsxRuntimeExports.jsxs("div", { className: "scores-col", "aria-live": "polite", children: [jsxRuntimeExports.jsx("div", { className: "scores-label", children: "Score Type" }), jsxRuntimeExports.jsx("div", { className: "scores-value-wrap", children: jsxRuntimeExports.jsx("span", { className: "scores-value-badge", children: jsxRuntimeExports.jsx("span", { className: "scores-value scores-value--highlight", children: scoreType }) }) })] }), jsxRuntimeExports.jsxs("div", { className: "scores-col", children: [jsxRuntimeExports.jsx("div", { className: "scores-label", children: "Score" }), jsxRuntimeExports.jsx("div", { className: "scores-value-wrap", children: jsxRuntimeExports.jsx("span", { className: "scores-value-badge", children: jsxRuntimeExports.jsx("span", { className: "scores-value scores-value--highlight", children: scoreValue }) }) })] }), jsxRuntimeExports.jsxs("div", { className: "scores-col", children: [jsxRuntimeExports.jsx("div", { className: "scores-label", children: "Computed at" }), jsxRuntimeExports.jsx("div", { className: "scores-value", children: computedAt })] }), jsxRuntimeExports.jsx("div", { className: "scores-statusline", children: loading ? (jsxRuntimeExports.jsx("div", { className: "scores-subtle", children: "Loading scores\u2026" })) : error ? (jsxRuntimeExports.jsx("div", { className: "scores-subtle", style: { color: 'var(--owt-color-error, #B91C1C)' }, children: error })) : !latest ? (jsxRuntimeExports.jsx("div", { className: "scores-subtle", children: "No scores available." })) : null })] }) })] }));
|
|
9406
9776
|
};
|
|
9407
9777
|
|
|
9408
9778
|
/**
|
|
@@ -9446,6 +9816,8 @@ const registerDefaultWidgets = () => {
|
|
|
9446
9816
|
widgetRegistry.register({ widget: 'profile', component: ProfileWidget });
|
|
9447
9817
|
// Header section widget for full-width registry header with profile, status, and metadata
|
|
9448
9818
|
widgetRegistry.register({ widget: 'header-section', component: HeaderSectionWidget });
|
|
9819
|
+
// Scores display widget for full-width computed scores display (view-only)
|
|
9820
|
+
widgetRegistry.register({ widget: 'scores-display', component: ScoresDisplayWidget });
|
|
9449
9821
|
};
|
|
9450
9822
|
// Auto-register on import
|
|
9451
9823
|
registerDefaultWidgets();
|
|
@@ -9825,6 +10197,7 @@ exports.PhoneInputWidget = PhoneInputWidget;
|
|
|
9825
10197
|
exports.ProfileWidget = ProfileWidget;
|
|
9826
10198
|
exports.PropertyEditor = PropertyEditor;
|
|
9827
10199
|
exports.RadioWidget = RadioWidget;
|
|
10200
|
+
exports.ScoresDisplayWidget = ScoresDisplayWidget;
|
|
9828
10201
|
exports.SectionBuilder = SectionBuilder;
|
|
9829
10202
|
exports.SectionRenderer = SectionRenderer;
|
|
9830
10203
|
exports.SectionTree = SectionTree;
|
|
@@ -9843,6 +10216,7 @@ exports.applyDecimalPrecision = applyDecimalPrecision;
|
|
|
9843
10216
|
exports.applyMask = applyMask;
|
|
9844
10217
|
exports.createWidgetStore = createWidgetStore;
|
|
9845
10218
|
exports.createZodSchema = createZodSchema;
|
|
10219
|
+
exports.defaultTheme = defaultTheme;
|
|
9846
10220
|
exports.evaluateCondition = evaluateCondition;
|
|
9847
10221
|
exports.filterByCharacterType = filterByCharacterType;
|
|
9848
10222
|
exports.formatCurrency = formatCurrency;
|
|
@@ -9865,6 +10239,7 @@ exports.registerDefaultWidgets = registerDefaultWidgets;
|
|
|
9865
10239
|
exports.removeMask = removeMask;
|
|
9866
10240
|
exports.resetAll = resetAll;
|
|
9867
10241
|
exports.resetWidget = resetWidget;
|
|
10242
|
+
exports.resolveTheme = resolveTheme;
|
|
9868
10243
|
exports.setDataSource = setDataSource;
|
|
9869
10244
|
exports.setError = setError;
|
|
9870
10245
|
exports.setLoading = setLoading;
|
|
@@ -9884,6 +10259,7 @@ exports.useGeoWidgetCascade = useGeoWidgetCascade;
|
|
|
9884
10259
|
exports.useWidgetCascade = useWidgetCascade;
|
|
9885
10260
|
exports.useWidgetContext = useWidgetContext;
|
|
9886
10261
|
exports.useWidgetEventBus = useWidgetEventBus;
|
|
10262
|
+
exports.useWidgetTheme = useWidgetTheme;
|
|
9887
10263
|
exports.useWidgetTranslation = useWidgetTranslation;
|
|
9888
10264
|
exports.validateNumericValue = validateNumericValue;
|
|
9889
10265
|
exports.validateWidget = validateWidget;
|