@openg2p/registry-widgets 1.1.0-dev.2 → 1.1.0-dev.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +24 -1
- package/dist/index.esm.js +441 -104
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +441 -103
- package/dist/index.js.map +1 -1
- package/dist/registry/defaultWidgets.d.ts.map +1 -1
- package/dist/widgets/DialogTableWidget.d.ts +25 -0
- package/dist/widgets/DialogTableWidget.d.ts.map +1 -0
- package/dist/widgets/HeaderSectionWidget.d.ts.map +1 -1
- package/dist/widgets/IdAuthenticationWidget.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.esm.js
CHANGED
|
@@ -8524,7 +8524,7 @@ const TableCellSelect = ({ config, value, onValueChange }) => {
|
|
|
8524
8524
|
backgroundColor: isReadonly || loading ? 'var(--owt-color-bg-alt, #F6F6F6)' : 'var(--owt-color-bg, #FFFFFF)',
|
|
8525
8525
|
}, children: [jsxRuntimeExports.jsx("option", { value: "", children: translate('common.select') || 'Select' }), dataSourceOptions.map((option) => (jsxRuntimeExports.jsx("option", { value: option.value, children: option.label }, option.value)))] }));
|
|
8526
8526
|
};
|
|
8527
|
-
const SelectDisplayValue = ({ config, value }) => {
|
|
8527
|
+
const SelectDisplayValue$1 = ({ config, value }) => {
|
|
8528
8528
|
const { dataSourceOptions, loading } = useBaseWidget({ config });
|
|
8529
8529
|
if (loading) {
|
|
8530
8530
|
return jsxRuntimeExports.jsx("span", { children: "-" });
|
|
@@ -9018,7 +9018,7 @@ const TableWidget = ({ config }) => {
|
|
|
9018
9018
|
'widget-readonly': true,
|
|
9019
9019
|
'widget-data-path': undefined,
|
|
9020
9020
|
};
|
|
9021
|
-
return (jsxRuntimeExports.jsx("div", { className: "text-sm", style: getCellStyle(), children: jsxRuntimeExports.jsx(SelectDisplayValue, { config: cellConfig, value: cellValue }) }));
|
|
9021
|
+
return (jsxRuntimeExports.jsx("div", { className: "text-sm", style: getCellStyle(), children: jsxRuntimeExports.jsx(SelectDisplayValue$1, { config: cellConfig, value: cellValue }) }));
|
|
9022
9022
|
}
|
|
9023
9023
|
return (jsxRuntimeExports.jsx("div", { className: "text-sm", style: getCellStyle(), children: displayValue }));
|
|
9024
9024
|
}
|
|
@@ -9157,6 +9157,225 @@ const TableWidget = ({ config }) => {
|
|
|
9157
9157
|
}, 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] }))] })] }));
|
|
9158
9158
|
};
|
|
9159
9159
|
|
|
9160
|
+
// Display select value label in view mode
|
|
9161
|
+
const SelectDisplayValue = ({ config, value }) => {
|
|
9162
|
+
const { dataSourceOptions, loading } = useBaseWidget({ config });
|
|
9163
|
+
if (loading)
|
|
9164
|
+
return jsxRuntimeExports.jsx("span", { children: "-" });
|
|
9165
|
+
if (value === null || value === undefined || value === '')
|
|
9166
|
+
return jsxRuntimeExports.jsx("span", { children: "-" });
|
|
9167
|
+
const selectedOption = dataSourceOptions.find((option) => option.value === value);
|
|
9168
|
+
return jsxRuntimeExports.jsx("span", { children: selectedOption ? selectedOption.label : String(value) });
|
|
9169
|
+
};
|
|
9170
|
+
/**
|
|
9171
|
+
* Dialog table widget:
|
|
9172
|
+
* - Table displays a subset of columns (n out of x)
|
|
9173
|
+
* - Add/Edit happens in a modal dialog that shows ALL columns as a form
|
|
9174
|
+
*
|
|
9175
|
+
* Usage in schema:
|
|
9176
|
+
* {
|
|
9177
|
+
* "widget": "dialog-table",
|
|
9178
|
+
* "widget-type": "table",
|
|
9179
|
+
* "widget-label": "Household Members",
|
|
9180
|
+
* "widget-id": "householdMembers",
|
|
9181
|
+
* "widget-data-path": "household.members",
|
|
9182
|
+
* "widget-data-columns": [ ...all columns... ],
|
|
9183
|
+
* "widget-data-visible-columns": ["firstName", "lastName", "dob"], // optional override; default = by column flag
|
|
9184
|
+
* // Per-column control (recommended): set "column-visible-in-table": false to hide it in the table
|
|
9185
|
+
* "widget-data-operations": { "add": true, "edit": true, "remove": true }
|
|
9186
|
+
* }
|
|
9187
|
+
*/
|
|
9188
|
+
const DialogTableWidget = ({ config }) => {
|
|
9189
|
+
const { value, error, touched, isEnabled, onChange, config: widgetConfig } = useBaseWidget({ config });
|
|
9190
|
+
const { translate, translateConfig } = useWidgetTranslation();
|
|
9191
|
+
const rows = Array.isArray(value) ? value : [];
|
|
9192
|
+
const columns = widgetConfig['widget-data-columns'] || [];
|
|
9193
|
+
const operations = widgetConfig['widget-data-operations'] || {};
|
|
9194
|
+
const isReadonly = widgetConfig['widget-readonly'] || false;
|
|
9195
|
+
const visibleColumnKeys = widgetConfig['widget-data-visible-columns'];
|
|
9196
|
+
const visibleColumns = useMemo(() => {
|
|
9197
|
+
// 1) If explicit list provided, it wins
|
|
9198
|
+
if (Array.isArray(visibleColumnKeys) && visibleColumnKeys.length > 0) {
|
|
9199
|
+
const keySet = new Set(visibleColumnKeys);
|
|
9200
|
+
return columns.filter((c) => keySet.has(c['column-key']));
|
|
9201
|
+
}
|
|
9202
|
+
// 2) Otherwise decide per column (default = visible)
|
|
9203
|
+
return columns.filter((c) => c['column-visible-in-table'] !== false);
|
|
9204
|
+
}, [columns, visibleColumnKeys]);
|
|
9205
|
+
const [dialogOpen, setDialogOpen] = useState(false);
|
|
9206
|
+
const [dialogMode, setDialogMode] = useState('add');
|
|
9207
|
+
const [activeRowIndex, setActiveRowIndex] = useState(null);
|
|
9208
|
+
const [formData, setFormData] = useState({});
|
|
9209
|
+
const addDialogTitle = translateConfig(widgetConfig['widget-data-dialog-title-add']) ||
|
|
9210
|
+
translate('table.addRecordDialog') ||
|
|
9211
|
+
'Add record';
|
|
9212
|
+
const editDialogTitle = translateConfig(widgetConfig['widget-data-dialog-title-edit']) ||
|
|
9213
|
+
translate('table.editRecordDialog') ||
|
|
9214
|
+
'Edit record';
|
|
9215
|
+
const buildEmptyRow = useCallback(() => {
|
|
9216
|
+
const emptyRow = {};
|
|
9217
|
+
columns.forEach((col) => {
|
|
9218
|
+
const key = col['column-key'];
|
|
9219
|
+
emptyRow[key] = col['widget-data-default'] ?? '';
|
|
9220
|
+
});
|
|
9221
|
+
return emptyRow;
|
|
9222
|
+
}, [columns]);
|
|
9223
|
+
const openAddDialog = useCallback(() => {
|
|
9224
|
+
setDialogMode('add');
|
|
9225
|
+
setActiveRowIndex(null);
|
|
9226
|
+
setFormData(buildEmptyRow());
|
|
9227
|
+
setDialogOpen(true);
|
|
9228
|
+
}, [buildEmptyRow]);
|
|
9229
|
+
const openEditDialog = useCallback((rowIndex) => {
|
|
9230
|
+
const row = rows[rowIndex] || {};
|
|
9231
|
+
const nextFormData = buildEmptyRow();
|
|
9232
|
+
columns.forEach((col) => {
|
|
9233
|
+
const key = col['column-key'];
|
|
9234
|
+
if (row[key] !== undefined)
|
|
9235
|
+
nextFormData[key] = row[key];
|
|
9236
|
+
});
|
|
9237
|
+
setDialogMode('edit');
|
|
9238
|
+
setActiveRowIndex(rowIndex);
|
|
9239
|
+
setFormData(nextFormData);
|
|
9240
|
+
setDialogOpen(true);
|
|
9241
|
+
}, [rows, columns, buildEmptyRow]);
|
|
9242
|
+
const closeDialog = useCallback(() => {
|
|
9243
|
+
setDialogOpen(false);
|
|
9244
|
+
setActiveRowIndex(null);
|
|
9245
|
+
setFormData({});
|
|
9246
|
+
}, []);
|
|
9247
|
+
const updateField = useCallback((columnKey, newValue) => {
|
|
9248
|
+
setFormData((prev) => ({ ...prev, [columnKey]: newValue }));
|
|
9249
|
+
}, []);
|
|
9250
|
+
const saveDialog = useCallback(() => {
|
|
9251
|
+
if (dialogMode === 'add') {
|
|
9252
|
+
const savedRow = { ...formData, edit_action: 'ADD' };
|
|
9253
|
+
onChange([...rows, savedRow]);
|
|
9254
|
+
closeDialog();
|
|
9255
|
+
return;
|
|
9256
|
+
}
|
|
9257
|
+
if (dialogMode === 'edit' && activeRowIndex !== null) {
|
|
9258
|
+
const newRows = [...rows];
|
|
9259
|
+
const currentRow = newRows[activeRowIndex] || {};
|
|
9260
|
+
const wasDeleted = currentRow.edit_action === 'DELETE';
|
|
9261
|
+
const editAction = wasDeleted ? 'UPDATE' : (currentRow.edit_action ?? 'UPDATE');
|
|
9262
|
+
newRows[activeRowIndex] = { ...currentRow, ...formData, edit_action: editAction };
|
|
9263
|
+
onChange(newRows);
|
|
9264
|
+
closeDialog();
|
|
9265
|
+
}
|
|
9266
|
+
}, [dialogMode, formData, onChange, rows, closeDialog, activeRowIndex]);
|
|
9267
|
+
const deleteRow = useCallback((rowIndex) => {
|
|
9268
|
+
const newRows = rows.filter((_, i) => i !== rowIndex);
|
|
9269
|
+
onChange(newRows);
|
|
9270
|
+
}, [rows, onChange]);
|
|
9271
|
+
const getDisplayValue = useCallback((rowIndex, column) => {
|
|
9272
|
+
const key = column['column-key'];
|
|
9273
|
+
const cellValue = rows[rowIndex]?.[key];
|
|
9274
|
+
const widgetType = column.widget || 'text';
|
|
9275
|
+
if (cellValue === null || cellValue === undefined || cellValue === '')
|
|
9276
|
+
return '-';
|
|
9277
|
+
if (widgetType === 'select')
|
|
9278
|
+
return null; // handled by SelectDisplayValue
|
|
9279
|
+
if (column['widget-data-format'])
|
|
9280
|
+
return formatValue(cellValue, column['widget-data-format'], column.widget);
|
|
9281
|
+
return String(cellValue);
|
|
9282
|
+
}, [rows]);
|
|
9283
|
+
const tableWidgetId = `dialog-table-widget-${widgetConfig['widget-id']}`;
|
|
9284
|
+
const columnSpan = widgetConfig['widget-column-span'] || 2;
|
|
9285
|
+
const minWidth = columnSpan * 200;
|
|
9286
|
+
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
|
|
9287
|
+
.${tableWidgetId} {
|
|
9288
|
+
width: 100%;
|
|
9289
|
+
min-width: ${minWidth}px;
|
|
9290
|
+
}
|
|
9291
|
+
|
|
9292
|
+
.widget-container[data-widget-id="${widgetConfig['widget-id']}"] {
|
|
9293
|
+
min-width: ${minWidth}px;
|
|
9294
|
+
width: 100%;
|
|
9295
|
+
flex: none;
|
|
9296
|
+
}
|
|
9297
|
+
|
|
9298
|
+
.panel-horizontal .widget-container[data-widget-id="${widgetConfig['widget-id']}"],
|
|
9299
|
+
[data-panel-orientation="horizontal"] .widget-container[data-widget-id="${widgetConfig['widget-id']}"] {
|
|
9300
|
+
grid-column: span ${columnSpan};
|
|
9301
|
+
}
|
|
9302
|
+
` }), jsxRuntimeExports.jsxs("div", { className: `table-widget-container ${tableWidgetId}`, children: [operations.add && !isReadonly && isEnabled && (jsxRuntimeExports.jsx("div", { className: "flex justify-end mb-2", children: jsxRuntimeExports.jsx("button", { type: "button", onClick: openAddDialog, className: "px-3 py-1 text-sm disabled:opacity-50 disabled:cursor-not-allowed", style: {
|
|
9303
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
9304
|
+
border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
|
|
9305
|
+
backgroundColor: 'var(--owt-color-primary, #F5BB1A)',
|
|
9306
|
+
color: 'var(--owt-color-bg, #FFFFFF)',
|
|
9307
|
+
}, children: translate('table.addRecord') || 'Add New Record' }) })), jsxRuntimeExports.jsx("div", { className: "overflow-x-auto border", style: {
|
|
9308
|
+
borderRadius: 'var(--owt-widget-table-border-radius, 15px)',
|
|
9309
|
+
borderColor: 'var(--owt-widget-table-border-color, #C4C4C4)',
|
|
9310
|
+
}, children: jsxRuntimeExports.jsxs("table", { className: "min-w-full", style: { borderCollapse: 'separate', borderSpacing: 0 }, children: [jsxRuntimeExports.jsx("thead", { style: { backgroundColor: 'var(--owt-widget-table-header-bg, #F6F6F6)' }, children: jsxRuntimeExports.jsxs("tr", { style: { borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)' }, children: [visibleColumns.map((col) => (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translateConfig(col['widget-label']) }, col['column-key']))), ((operations.edit || operations.remove) && !isReadonly) && (jsxRuntimeExports.jsx("th", { className: "px-4 py-3 text-left text-xs font-medium uppercase tracking-wider", style: { color: 'var(--owt-widget-table-header-color, #727474)' }, children: translate('common.actions') || 'Actions' }))] }) }), jsxRuntimeExports.jsxs("tbody", { style: { backgroundColor: 'var(--owt-widget-table-body-bg, #FFFFFF)' }, children: [rows.length === 0 && (jsxRuntimeExports.jsx("tr", { children: jsxRuntimeExports.jsxs("td", { colSpan: visibleColumns.length + (((operations.edit || operations.remove) && !isReadonly) ? 1 : 0), className: "px-4 py-6 text-center text-sm", style: { color: 'var(--owt-widget-table-empty-color, #727474)' }, children: [translate('table.noData') || 'No records available.', operations.add && !isReadonly && ` ${translate('table.clickToAdd') || 'Click "Add New Record" to add one.'}`] }) })), rows.map((row, rowIndex) => (jsxRuntimeExports.jsxs("tr", { style: {
|
|
9311
|
+
borderBottom: '1px solid var(--owt-widget-table-row-divider, #E4E4E4)',
|
|
9312
|
+
backgroundColor: row?.edit_action === 'DELETE'
|
|
9313
|
+
? 'var(--owt-widget-table-deleted-row-bg, #FEE2E2)'
|
|
9314
|
+
: undefined,
|
|
9315
|
+
}, children: [visibleColumns.map((col) => {
|
|
9316
|
+
const key = col['column-key'];
|
|
9317
|
+
const widgetType = col.widget || 'text';
|
|
9318
|
+
const displayValue = getDisplayValue(rowIndex, col);
|
|
9319
|
+
if (widgetType === 'select' && displayValue === null) {
|
|
9320
|
+
const displayConfig = {
|
|
9321
|
+
...col,
|
|
9322
|
+
'widget-id': `${widgetConfig['widget-id']}-view-row-${rowIndex}-col-${key}`,
|
|
9323
|
+
'widget-label': '',
|
|
9324
|
+
'widget-readonly': true,
|
|
9325
|
+
'widget-data-path': undefined,
|
|
9326
|
+
};
|
|
9327
|
+
return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsx("div", { className: "text-sm", children: jsxRuntimeExports.jsx(SelectDisplayValue, { config: displayConfig, value: row?.[key] }) }) }, key));
|
|
9328
|
+
}
|
|
9329
|
+
return (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", children: jsxRuntimeExports.jsx("div", { className: "text-sm", children: displayValue }) }, key));
|
|
9330
|
+
}), ((operations.edit || operations.remove) && !isReadonly) && (jsxRuntimeExports.jsx("td", { className: "px-4 py-3 whitespace-nowrap", style: { minWidth: '120px' }, children: jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [operations.edit && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => openEditDialog(rowIndex), disabled: !isEnabled, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
|
|
9331
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
9332
|
+
color: 'var(--owt-color-primary-dark, #F07B1A)',
|
|
9333
|
+
backgroundColor: 'transparent',
|
|
9334
|
+
border: 'none',
|
|
9335
|
+
}, children: translate('common.edit') || 'Edit' })), operations.remove && (jsxRuntimeExports.jsx("button", { type: "button", onClick: () => deleteRow(rowIndex), disabled: !isEnabled, className: "px-3 py-1 text-xs disabled:opacity-50 disabled:cursor-not-allowed", style: {
|
|
9336
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
9337
|
+
color: 'var(--owt-color-error, #B91C1C)',
|
|
9338
|
+
backgroundColor: 'transparent',
|
|
9339
|
+
border: 'none',
|
|
9340
|
+
}, children: translate('common.remove') || 'Delete' }))] }) }))] }, rowIndex)))] })] }) }), touched && error.length > 0 && (jsxRuntimeExports.jsx("p", { className: "text-sm mt-1", style: { color: 'var(--owt-widget-error-color, #B91C1C)' }, children: error[0] }))] }), dialogOpen && (jsxRuntimeExports.jsx("div", { className: "fixed inset-0 flex items-center justify-center z-50", style: { backgroundColor: 'rgba(0,0,0,0.5)' }, children: jsxRuntimeExports.jsxs("div", { className: "rounded-lg p-6 w-full mx-4", style: {
|
|
9341
|
+
maxWidth: '900px',
|
|
9342
|
+
backgroundColor: 'var(--owt-color-bg, #FFFFFF)',
|
|
9343
|
+
borderRadius: 'var(--owt-widget-card-border-radius, 20px)',
|
|
9344
|
+
}, children: [jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-4 mb-4", children: [jsxRuntimeExports.jsx("h3", { className: "text-lg font-semibold", style: { color: 'var(--owt-color-text, #011627)' }, children: dialogMode === 'add' ? addDialogTitle : editDialogTitle }), jsxRuntimeExports.jsx("button", { type: "button", onClick: closeDialog, style: {
|
|
9345
|
+
border: 'none',
|
|
9346
|
+
background: 'transparent',
|
|
9347
|
+
color: 'var(--owt-color-text-muted, #727474)',
|
|
9348
|
+
cursor: 'pointer',
|
|
9349
|
+
fontSize: '20px',
|
|
9350
|
+
lineHeight: 1,
|
|
9351
|
+
}, "aria-label": "Close", children: "\u00D7" })] }), jsxRuntimeExports.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 gap-4", style: { maxHeight: '70vh', overflow: 'auto' }, children: columns.map((col) => {
|
|
9352
|
+
const key = col['column-key'];
|
|
9353
|
+
const widgetType = col.widget || 'text';
|
|
9354
|
+
const cellWidgetId = `${widgetConfig['widget-id']}-dialog-${dialogMode}-${key}`;
|
|
9355
|
+
const fieldConfig = {
|
|
9356
|
+
...col,
|
|
9357
|
+
widget: widgetType,
|
|
9358
|
+
'widget-type': col['widget-type'] || 'input',
|
|
9359
|
+
'widget-id': cellWidgetId,
|
|
9360
|
+
'widget-label': col['widget-label'],
|
|
9361
|
+
'widget-readonly': isReadonly || col['widget-readonly'] === true,
|
|
9362
|
+
'widget-data-path': undefined,
|
|
9363
|
+
'widget-data-default': formData[key] ?? col['widget-data-default'] ?? '',
|
|
9364
|
+
};
|
|
9365
|
+
return (jsxRuntimeExports.jsx("div", { className: "min-w-0", children: jsxRuntimeExports.jsx(WidgetRenderer, { config: fieldConfig, schemaData: { [cellWidgetId]: formData[key] ?? col['widget-data-default'] ?? '' }, onValueChange: (_widgetId, newValue) => updateField(key, newValue) }) }, key));
|
|
9366
|
+
}) }), jsxRuntimeExports.jsxs("div", { className: "flex justify-end gap-3 mt-6", children: [jsxRuntimeExports.jsx("button", { type: "button", onClick: closeDialog, className: "px-4 py-2 text-sm font-medium", style: {
|
|
9367
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
9368
|
+
border: '1px solid var(--owt-btn-secondary-border, #C4C4C4)',
|
|
9369
|
+
backgroundColor: 'var(--owt-btn-secondary-bg, #FFFFFF)',
|
|
9370
|
+
color: 'var(--owt-btn-secondary-color, #011627)',
|
|
9371
|
+
}, children: translate('common.cancel') || 'Cancel' }), jsxRuntimeExports.jsx("button", { type: "button", onClick: saveDialog, disabled: isReadonly || !isEnabled, className: "px-4 py-2 text-sm font-medium disabled:opacity-50 disabled:cursor-not-allowed", style: {
|
|
9372
|
+
borderRadius: 'var(--owt-btn-border-radius, 10px)',
|
|
9373
|
+
border: '1px solid var(--owt-btn-primary-border, #F07B1A)',
|
|
9374
|
+
backgroundColor: 'var(--owt-color-primary, #F5BB1A)',
|
|
9375
|
+
color: 'var(--owt-color-bg, #FFFFFF)',
|
|
9376
|
+
}, children: translate('common.save') || 'Save' })] })] }) }))] }));
|
|
9377
|
+
};
|
|
9378
|
+
|
|
9160
9379
|
const ProfileWidget = ({ config }) => {
|
|
9161
9380
|
const { value, config: widgetConfig, getFieldValue, } = useBaseWidget({ config });
|
|
9162
9381
|
const { translateConfig } = useWidgetTranslation();
|
|
@@ -9570,6 +9789,68 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9570
9789
|
const createdAt = findValue('createdAt') || '';
|
|
9571
9790
|
const lastApprovedBy = findValue('lastApprovedBy') || '';
|
|
9572
9791
|
const lastApprovedAt = findValue('lastApprovedAt') || '';
|
|
9792
|
+
// ── Validation: status change requires reason ──────────────────
|
|
9793
|
+
// Behavior:
|
|
9794
|
+
// - When status changes away from its initial value, clear reason and require it.
|
|
9795
|
+
// - When status returns to initial value (or a parent "Cancel" restores it), restore initial reason.
|
|
9796
|
+
const initialStatusRef = useRef(null);
|
|
9797
|
+
const initialReasonRef = useRef(null);
|
|
9798
|
+
const prevStatusRef = useRef(null);
|
|
9799
|
+
const [showReasonRequired, setShowReasonRequired] = useState(false);
|
|
9800
|
+
useEffect(() => {
|
|
9801
|
+
// Capture initial status once when it becomes available.
|
|
9802
|
+
if (initialStatusRef.current === null) {
|
|
9803
|
+
const v = statusValue === undefined || statusValue === null ? '' : String(statusValue);
|
|
9804
|
+
initialStatusRef.current = v;
|
|
9805
|
+
}
|
|
9806
|
+
}, [statusValue]);
|
|
9807
|
+
useEffect(() => {
|
|
9808
|
+
// Capture initial reason once when it becomes available.
|
|
9809
|
+
if (initialReasonRef.current === null) {
|
|
9810
|
+
const v = statusReason === undefined || statusReason === null ? '' : String(statusReason);
|
|
9811
|
+
initialReasonRef.current = v;
|
|
9812
|
+
}
|
|
9813
|
+
}, [statusReason]);
|
|
9814
|
+
const isStatusChanged = useMemo(() => {
|
|
9815
|
+
const initial = initialStatusRef.current;
|
|
9816
|
+
if (initial === null)
|
|
9817
|
+
return false;
|
|
9818
|
+
return String(statusValue) !== initial;
|
|
9819
|
+
}, [statusValue]);
|
|
9820
|
+
const isReasonMissing = useMemo(() => {
|
|
9821
|
+
if (!isStatusChanged)
|
|
9822
|
+
return false;
|
|
9823
|
+
return String(statusReason || '').trim().length === 0;
|
|
9824
|
+
}, [isStatusChanged, statusReason]);
|
|
9825
|
+
useEffect(() => {
|
|
9826
|
+
// When status changes:
|
|
9827
|
+
// - If moved away from initial → clear reason.
|
|
9828
|
+
// - If returned to initial → restore initial reason.
|
|
9829
|
+
if (isReadonly)
|
|
9830
|
+
return;
|
|
9831
|
+
if (initialStatusRef.current === null)
|
|
9832
|
+
return;
|
|
9833
|
+
const currentStatus = String(statusValue || '');
|
|
9834
|
+
if (prevStatusRef.current === currentStatus)
|
|
9835
|
+
return;
|
|
9836
|
+
prevStatusRef.current = currentStatus;
|
|
9837
|
+
const initialStatus = initialStatusRef.current;
|
|
9838
|
+
const initialReason = initialReasonRef.current ?? '';
|
|
9839
|
+
if (currentStatus === initialStatus) {
|
|
9840
|
+
// Reverted / cancelled back to original
|
|
9841
|
+
if (String(statusReason || '') !== String(initialReason || '')) {
|
|
9842
|
+
updateFieldValue('statusReason', initialReason);
|
|
9843
|
+
}
|
|
9844
|
+
setShowReasonRequired(false);
|
|
9845
|
+
return;
|
|
9846
|
+
}
|
|
9847
|
+
// Status changed to a new value: clear reason (so user must re-enter)
|
|
9848
|
+
if (String(statusReason || '').trim().length > 0) {
|
|
9849
|
+
updateFieldValue('statusReason', '');
|
|
9850
|
+
}
|
|
9851
|
+
setShowReasonRequired(true);
|
|
9852
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
9853
|
+
}, [statusValue, isReadonly]);
|
|
9573
9854
|
const score = useMemo(() => {
|
|
9574
9855
|
const toNum = (v) => {
|
|
9575
9856
|
if (v === null || v === undefined || String(v).trim() === '')
|
|
@@ -9583,7 +9864,9 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9583
9864
|
return null;
|
|
9584
9865
|
const ratio = completion / ideal;
|
|
9585
9866
|
const percent = Math.max(0, Math.min(100, Math.round(ratio * 100)));
|
|
9586
|
-
|
|
9867
|
+
const completionDisplay = Number.isInteger(completion) ? completion : Math.round(completion);
|
|
9868
|
+
const idealDisplay = Number.isInteger(ideal) ? ideal : Math.round(ideal);
|
|
9869
|
+
return { completion, ideal, completionDisplay, idealDisplay, percent };
|
|
9587
9870
|
}, [completionScoreRaw, idealScoreRaw]);
|
|
9588
9871
|
// ── Format options ────────────────────────────────────────────
|
|
9589
9872
|
const format = (widgetConfig['widget-data-format'] || {});
|
|
@@ -9879,6 +10162,19 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9879
10162
|
box-shadow: 0 0 0 2px rgba(237, 124, 34, 0.15);
|
|
9880
10163
|
}
|
|
9881
10164
|
|
|
10165
|
+
.${cls} .hdr-input--error {
|
|
10166
|
+
border-color: var(--owt-color-danger, #DC2626);
|
|
10167
|
+
box-shadow: 0 0 0 2px rgba(220, 38, 38, 0.12);
|
|
10168
|
+
}
|
|
10169
|
+
|
|
10170
|
+
.${cls} .hdr-error-text {
|
|
10171
|
+
margin-left: calc(0px);
|
|
10172
|
+
color: var(--owt-color-danger, #DC2626);
|
|
10173
|
+
font-size: 0.75rem;
|
|
10174
|
+
line-height: 1.2;
|
|
10175
|
+
font-weight: 500;
|
|
10176
|
+
}
|
|
10177
|
+
|
|
9882
10178
|
@media (max-width: 768px) {
|
|
9883
10179
|
.${cls} {
|
|
9884
10180
|
flex-direction: column;
|
|
@@ -9893,7 +10189,15 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9893
10189
|
.parentElement?.querySelector('.hdr-avatar-placeholder');
|
|
9894
10190
|
if (placeholder)
|
|
9895
10191
|
placeholder.style.display = 'flex';
|
|
9896
|
-
} })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display: displayImageUrl ? 'none' : 'flex' }, children: jsxRuntimeExports.jsx("img", { src: img$f, alt: "Profile Placeholder" }) }), !isReadonly && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "hdr-avatar-overlay", children: [jsxRuntimeExports.jsxs("button", { type: "button", className: "hdr-avatar-action", onClick: () => fileInputRef.current?.click(), children: [jsxRuntimeExports.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), jsxRuntimeExports.jsx("polyline", { points: "17 8 12 3 7 8" }), jsxRuntimeExports.jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })] }), "Upload"] }), jsxRuntimeExports.jsxs("button", { type: "button", className: "hdr-avatar-action hdr-avatar-action--delete", onClick: handleImageDelete, children: [jsxRuntimeExports.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("polyline", { points: "3 6 5 6 21 6" }), jsxRuntimeExports.jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })] }), "Delete"] })] }), jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", style: { display: 'none' }, onChange: handleImageUpload })] }))] }), 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.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("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.jsxs("span", { className: "hdr-field-label", children: [getLabel('statusReason'), " :"] }), isReadonly ? (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: statusReason || '-' })) : (jsxRuntimeExports.
|
|
10192
|
+
} })) : null, jsxRuntimeExports.jsx("div", { className: "hdr-avatar-placeholder", style: { display: displayImageUrl ? 'none' : 'flex' }, children: jsxRuntimeExports.jsx("img", { src: img$f, alt: "Profile Placeholder" }) }), !isReadonly && (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsxs("div", { className: "hdr-avatar-overlay", children: [jsxRuntimeExports.jsxs("button", { type: "button", className: "hdr-avatar-action", onClick: () => fileInputRef.current?.click(), children: [jsxRuntimeExports.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }), jsxRuntimeExports.jsx("polyline", { points: "17 8 12 3 7 8" }), jsxRuntimeExports.jsx("line", { x1: "12", y1: "3", x2: "12", y2: "15" })] }), "Upload"] }), jsxRuntimeExports.jsxs("button", { type: "button", className: "hdr-avatar-action hdr-avatar-action--delete", onClick: handleImageDelete, children: [jsxRuntimeExports.jsxs("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [jsxRuntimeExports.jsx("polyline", { points: "3 6 5 6 21 6" }), jsxRuntimeExports.jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })] }), "Delete"] })] }), jsxRuntimeExports.jsx("input", { ref: fileInputRef, type: "file", accept: "image/*", style: { display: 'none' }, onChange: handleImageUpload })] }))] }), 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.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("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.jsxs("span", { className: "hdr-field-label", children: [getLabel('statusReason'), " :"] }), isReadonly ? (jsxRuntimeExports.jsx("span", { className: "hdr-field-value", children: statusReason || '-' })) : (jsxRuntimeExports.jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: 4 }, children: [jsxRuntimeExports.jsx("input", { type: "text", className: `hdr-input ${(!isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing) ? 'hdr-input--error' : ''}`, value: statusReason, placeholder: getLabel('enterReason'), required: isStatusChanged, "aria-required": isStatusChanged, "aria-invalid": !isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing, onBlur: () => {
|
|
10193
|
+
if (isReasonMissing)
|
|
10194
|
+
setShowReasonRequired(true);
|
|
10195
|
+
}, onChange: (e) => {
|
|
10196
|
+
updateFieldValue('statusReason', e.target.value);
|
|
10197
|
+
if (showReasonRequired && String(e.target.value || '').trim().length > 0) {
|
|
10198
|
+
setShowReasonRequired(false);
|
|
10199
|
+
}
|
|
10200
|
+
} }), !isReadonly && (showReasonRequired || isReasonMissing) && isReasonMissing ? (jsxRuntimeExports.jsx("div", { className: "hdr-error-text", children: getLabel('enterReason') })) : null] }))] })] })] }), jsxRuntimeExports.jsx("div", { className: "hdr-right", children: jsxRuntimeExports.jsxs("div", { className: "hdr-right-top", children: [jsxRuntimeExports.jsxs("div", { className: "hdr-meta-col", 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 || '-' })] })] }), score ? (jsxRuntimeExports.jsx("div", { className: "hdr-score-ring", style: { ['--pct']: score.percent }, "aria-label": `Completion score ${score.completionDisplay} of ${score.idealDisplay} (${score.percent}%)`, title: `${score.completionDisplay} / ${score.idealDisplay} (${score.percent}%)`, children: jsxRuntimeExports.jsx("div", { className: "hdr-score-value", children: String(score.completionDisplay) }) })) : null] }) })] })] }));
|
|
9897
10201
|
};
|
|
9898
10202
|
|
|
9899
10203
|
function getValueByPathOrKey(obj, path) {
|
|
@@ -10194,7 +10498,8 @@ function pickAuthorizationUrl(resp, explicitKey) {
|
|
|
10194
10498
|
if (v)
|
|
10195
10499
|
return v;
|
|
10196
10500
|
}
|
|
10197
|
-
return (tryKey('
|
|
10501
|
+
return (tryKey('authentication_url') ||
|
|
10502
|
+
tryKey('authorization_url') ||
|
|
10198
10503
|
tryKey('authorizationUrl') ||
|
|
10199
10504
|
tryKey('auth_url') ||
|
|
10200
10505
|
tryKey('authUrl') ||
|
|
@@ -10209,12 +10514,14 @@ function resolveValueFromSources(path, values, schemaData) {
|
|
|
10209
10514
|
return fromValues;
|
|
10210
10515
|
return getValueByPath(schemaData, path);
|
|
10211
10516
|
}
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10517
|
+
function unwrapPayload(response) {
|
|
10518
|
+
if (response && typeof response === 'object') {
|
|
10519
|
+
if (response.response_body?.response_payload !== undefined)
|
|
10520
|
+
return response.response_body.response_payload;
|
|
10521
|
+
if (response.response_payload !== undefined)
|
|
10522
|
+
return response.response_payload;
|
|
10523
|
+
}
|
|
10524
|
+
return response;
|
|
10218
10525
|
}
|
|
10219
10526
|
const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
10220
10527
|
const { dataSourceRequestHandler, schemaData: ctxSchemaData } = useWidgetContext();
|
|
@@ -10228,6 +10535,11 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10228
10535
|
return dataPath;
|
|
10229
10536
|
}, [dataPath]);
|
|
10230
10537
|
const authConfig = config['widget-auth-config'];
|
|
10538
|
+
const registerId = resolveValueFromSources(paths.registerId, values, schemaData);
|
|
10539
|
+
const internalRecordId = resolveValueFromSources(paths.internalRecordId, values, schemaData);
|
|
10540
|
+
const initiatedByStaffId = resolveValueFromSources(paths.initiatedByStaffId, values, schemaData);
|
|
10541
|
+
const providerId = authConfig?.providerId;
|
|
10542
|
+
const providerName = authConfig?.providerName;
|
|
10231
10543
|
const foundationalId = resolveValueFromSources(paths.foundationalId, values, schemaData);
|
|
10232
10544
|
const lastAuthenticatedOn = resolveValueFromSources(paths.lastAuthenticatedOn, values, schemaData);
|
|
10233
10545
|
const lastAuthStatusRaw = resolveValueFromSources(paths.lastAuthenticationStatus, values, schemaData);
|
|
@@ -10236,11 +10548,11 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10236
10548
|
const status = useMemo(() => normalizeStatus(lastAuthStatusRaw), [lastAuthStatusRaw]);
|
|
10237
10549
|
/** URL from prefetch (or default); used when opening the OIDC / eSignet popup */
|
|
10238
10550
|
const [resolvedAuthUrl, setResolvedAuthUrl] = useState(null);
|
|
10239
|
-
const [providerLoading, setProviderLoading] = useState(false);
|
|
10240
10551
|
const [authActionLoading, setAuthActionLoading] = useState(false);
|
|
10241
10552
|
const [authError, setAuthError] = useState(null);
|
|
10242
10553
|
const popupRef = useRef(null);
|
|
10243
10554
|
const pollTimerRef = useRef(null);
|
|
10555
|
+
const [overlayUrl, setOverlayUrl] = useState(null);
|
|
10244
10556
|
const emitHostEvent = useCallback((detail) => {
|
|
10245
10557
|
if (typeof window === 'undefined')
|
|
10246
10558
|
return;
|
|
@@ -10269,72 +10581,16 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10269
10581
|
}
|
|
10270
10582
|
};
|
|
10271
10583
|
}, [cleanupPopup]);
|
|
10272
|
-
|
|
10273
|
-
if (!authConfig)
|
|
10274
|
-
return 'no-config';
|
|
10275
|
-
return JSON.stringify({
|
|
10276
|
-
s: authConfig.service,
|
|
10277
|
-
e: authConfig.endpoint,
|
|
10278
|
-
m: authConfig.method,
|
|
10279
|
-
def: authConfig.defaultAuthorizationUrl,
|
|
10280
|
-
prefetch: authConfig.prefetchOnMount,
|
|
10281
|
-
});
|
|
10282
|
-
}, [authConfig]);
|
|
10283
|
-
// Prefetch provider login URL on mount (and when params / config change)
|
|
10584
|
+
// Provider details are supplied by host; clear any previous resolved URL on provider change.
|
|
10284
10585
|
useEffect(() => {
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
|
|
10291
|
-
setResolvedAuthUrl(authConfig.defaultAuthorizationUrl || null);
|
|
10292
|
-
setProviderLoading(false);
|
|
10293
|
-
return;
|
|
10294
|
-
}
|
|
10295
|
-
const def = authConfig.defaultAuthorizationUrl;
|
|
10296
|
-
if (def) {
|
|
10297
|
-
setResolvedAuthUrl(def);
|
|
10298
|
-
}
|
|
10299
|
-
const canCallApi = Boolean(dataSourceRequestHandler && authConfig.service && authConfig.endpoint);
|
|
10300
|
-
if (!canCallApi) {
|
|
10301
|
-
setProviderLoading(false);
|
|
10302
|
-
if (!def) {
|
|
10303
|
-
setResolvedAuthUrl(null);
|
|
10304
|
-
}
|
|
10586
|
+
setResolvedAuthUrl(null);
|
|
10587
|
+
}, [providerId, providerName]);
|
|
10588
|
+
const openAuthPopup = useCallback((authUrl) => {
|
|
10589
|
+
if (authConfig?.useIframeOverlay !== false) {
|
|
10590
|
+
setOverlayUrl(authUrl);
|
|
10591
|
+
emitHostEvent({ type: 'overlay_opened' });
|
|
10305
10592
|
return;
|
|
10306
10593
|
}
|
|
10307
|
-
let cancelled = false;
|
|
10308
|
-
setProviderLoading(true);
|
|
10309
|
-
(async () => {
|
|
10310
|
-
try {
|
|
10311
|
-
const url = await fetchProviderAuthorizationUrl(authConfig, dataSourceRequestHandler, values, schemaData);
|
|
10312
|
-
if (cancelled)
|
|
10313
|
-
return;
|
|
10314
|
-
if (url) {
|
|
10315
|
-
setResolvedAuthUrl(url);
|
|
10316
|
-
}
|
|
10317
|
-
else if (!def) {
|
|
10318
|
-
setResolvedAuthUrl(null);
|
|
10319
|
-
}
|
|
10320
|
-
}
|
|
10321
|
-
catch {
|
|
10322
|
-
if (cancelled)
|
|
10323
|
-
return;
|
|
10324
|
-
if (!def) {
|
|
10325
|
-
setResolvedAuthUrl(null);
|
|
10326
|
-
}
|
|
10327
|
-
}
|
|
10328
|
-
finally {
|
|
10329
|
-
if (!cancelled)
|
|
10330
|
-
setProviderLoading(false);
|
|
10331
|
-
}
|
|
10332
|
-
})();
|
|
10333
|
-
return () => {
|
|
10334
|
-
cancelled = true;
|
|
10335
|
-
};
|
|
10336
|
-
}, [authConfig, dataSourceRequestHandler, prefetchKey, values, schemaData]);
|
|
10337
|
-
const openAuthPopup = useCallback((authUrl) => {
|
|
10338
10594
|
const pw = authConfig?.popupWidth ?? 1024;
|
|
10339
10595
|
const ph = authConfig?.popupHeight ?? 800;
|
|
10340
10596
|
const features = getCenteredPopupFeatures(pw, ph);
|
|
@@ -10370,20 +10626,24 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10370
10626
|
setAuthError('Missing widget-auth-config.');
|
|
10371
10627
|
return;
|
|
10372
10628
|
}
|
|
10373
|
-
const
|
|
10374
|
-
const canCallApi = Boolean(dataSourceRequestHandler && authConfig.service && authConfig.endpoint);
|
|
10629
|
+
const canCallAuthApi = Boolean(dataSourceRequestHandler && authConfig.service && authConfig.authenticateEndpoint);
|
|
10375
10630
|
let url = resolvedAuthUrl;
|
|
10376
|
-
if (!url &&
|
|
10631
|
+
if (!url && canCallAuthApi) {
|
|
10377
10632
|
setAuthActionLoading(true);
|
|
10378
10633
|
try {
|
|
10379
|
-
const
|
|
10380
|
-
|
|
10381
|
-
|
|
10382
|
-
|
|
10383
|
-
|
|
10634
|
+
const resp = await dataSourceRequestHandler(authConfig.service, authConfig.authenticateEndpoint, authConfig.authenticateMethod || 'POST', {
|
|
10635
|
+
register_id: registerId,
|
|
10636
|
+
internal_record_id: internalRecordId,
|
|
10637
|
+
provider_id: authConfig.providerId,
|
|
10638
|
+
initiated_by_staff_id: initiatedByStaffId,
|
|
10639
|
+
});
|
|
10640
|
+
const payload = unwrapPayload(resp);
|
|
10641
|
+
const authUrl = pickAuthorizationUrl(payload, authConfig.authorizationUrlKey);
|
|
10642
|
+
url = authUrl || null;
|
|
10643
|
+
if (authUrl)
|
|
10644
|
+
setResolvedAuthUrl(authUrl);
|
|
10384
10645
|
}
|
|
10385
10646
|
catch (e) {
|
|
10386
|
-
url = def || null;
|
|
10387
10647
|
if (!url) {
|
|
10388
10648
|
setAuthError(e?.message || 'Could not load provider URL.');
|
|
10389
10649
|
return;
|
|
@@ -10393,15 +10653,20 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10393
10653
|
setAuthActionLoading(false);
|
|
10394
10654
|
}
|
|
10395
10655
|
}
|
|
10396
|
-
else if (!url) {
|
|
10397
|
-
url = def || null;
|
|
10398
|
-
}
|
|
10399
10656
|
if (!url) {
|
|
10400
|
-
setAuthError('No authorization URL
|
|
10657
|
+
setAuthError('No authorization URL returned from authenticate_registrant.');
|
|
10401
10658
|
return;
|
|
10402
10659
|
}
|
|
10403
10660
|
openAuthPopup(url);
|
|
10404
|
-
}, [
|
|
10661
|
+
}, [
|
|
10662
|
+
authConfig,
|
|
10663
|
+
dataSourceRequestHandler,
|
|
10664
|
+
openAuthPopup,
|
|
10665
|
+
registerId,
|
|
10666
|
+
internalRecordId,
|
|
10667
|
+
initiatedByStaffId,
|
|
10668
|
+
resolvedAuthUrl,
|
|
10669
|
+
]);
|
|
10405
10670
|
useEffect(() => {
|
|
10406
10671
|
const successType = authConfig?.successMessageType || 'openg2p:oidc:success';
|
|
10407
10672
|
const handler = (event) => {
|
|
@@ -10446,8 +10711,7 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10446
10711
|
return 'var(--owt-color-warning, #D97706)';
|
|
10447
10712
|
return 'var(--owt-color-text-muted, #6B7280)';
|
|
10448
10713
|
}, [status]);
|
|
10449
|
-
const buttonBusy = authActionLoading
|
|
10450
|
-
(providerLoading && !resolvedAuthUrl && !authConfig?.defaultAuthorizationUrl);
|
|
10714
|
+
const buttonBusy = authActionLoading;
|
|
10451
10715
|
const buttonDisabled = !authConfig || buttonBusy;
|
|
10452
10716
|
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
|
|
10453
10717
|
.${cls} {
|
|
@@ -10483,6 +10747,14 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10483
10747
|
grid-column: 1 / -1;
|
|
10484
10748
|
}
|
|
10485
10749
|
|
|
10750
|
+
/* Action cell: no left label spacer, align button to column start */
|
|
10751
|
+
.${cls} .auth-cell.auth-cell--action .auth-label {
|
|
10752
|
+
display: none;
|
|
10753
|
+
}
|
|
10754
|
+
.${cls} .auth-cell.auth-cell--action .auth-value {
|
|
10755
|
+
flex: 1 1 auto;
|
|
10756
|
+
}
|
|
10757
|
+
|
|
10486
10758
|
.${cls} .auth-label {
|
|
10487
10759
|
flex: 0 0 auto;
|
|
10488
10760
|
min-width: 200px;
|
|
@@ -10505,17 +10777,15 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10505
10777
|
word-break: break-word;
|
|
10506
10778
|
}
|
|
10507
10779
|
|
|
10508
|
-
.${cls} .auth-
|
|
10509
|
-
|
|
10510
|
-
|
|
10511
|
-
|
|
10512
|
-
|
|
10513
|
-
gap: 8px;
|
|
10514
|
-
width: 100%;
|
|
10515
|
-
margin-top: 20px;
|
|
10516
|
-
margin-bottom: 0;
|
|
10780
|
+
.${cls} .auth-value--foundational {
|
|
10781
|
+
font-size: 18px;
|
|
10782
|
+
font-weight: 700;
|
|
10783
|
+
color: var(--owt-color-primary-dark, #F07B1A);
|
|
10784
|
+
letter-spacing: 0.1px;
|
|
10517
10785
|
}
|
|
10518
10786
|
|
|
10787
|
+
/* Button is placed inside the grid (next to PSUT) */
|
|
10788
|
+
|
|
10519
10789
|
.${cls} .auth-status {
|
|
10520
10790
|
display: inline-flex;
|
|
10521
10791
|
align-items: center;
|
|
@@ -10556,8 +10826,8 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10556
10826
|
padding: 8px 24px;
|
|
10557
10827
|
line-height: 1.5;
|
|
10558
10828
|
border-radius: var(--owt-btn-border-radius, 10px);
|
|
10559
|
-
border: 1px solid
|
|
10560
|
-
background-color:
|
|
10829
|
+
border: 1px solid rgb(237, 124, 34);
|
|
10830
|
+
background-color: rgb(237, 124, 34);
|
|
10561
10831
|
color: var(--owt-color-bg, #FFFFFF);
|
|
10562
10832
|
font-family: Roboto, sans-serif;
|
|
10563
10833
|
cursor: pointer;
|
|
@@ -10578,6 +10848,63 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10578
10848
|
max-width: 100%;
|
|
10579
10849
|
}
|
|
10580
10850
|
|
|
10851
|
+
.${cls} .overlay-backdrop {
|
|
10852
|
+
position: fixed;
|
|
10853
|
+
inset: 0;
|
|
10854
|
+
background: rgba(17, 24, 39, 0.55);
|
|
10855
|
+
z-index: 9999;
|
|
10856
|
+
display: flex;
|
|
10857
|
+
align-items: center;
|
|
10858
|
+
justify-content: center;
|
|
10859
|
+
padding: 24px;
|
|
10860
|
+
}
|
|
10861
|
+
|
|
10862
|
+
.${cls} .overlay-panel {
|
|
10863
|
+
width: min(1100px, 92vw);
|
|
10864
|
+
height: min(820px, 92vh);
|
|
10865
|
+
background: var(--owt-color-bg, #FFFFFF);
|
|
10866
|
+
border-radius: 12px;
|
|
10867
|
+
box-shadow: 0 10px 30px rgba(0,0,0,0.25);
|
|
10868
|
+
overflow: hidden;
|
|
10869
|
+
display: flex;
|
|
10870
|
+
flex-direction: column;
|
|
10871
|
+
}
|
|
10872
|
+
|
|
10873
|
+
.${cls} .overlay-header {
|
|
10874
|
+
display: flex;
|
|
10875
|
+
align-items: center;
|
|
10876
|
+
justify-content: space-between;
|
|
10877
|
+
padding: 10px 14px;
|
|
10878
|
+
border-bottom: 1px solid var(--owt-color-border-light, #E4E4E4);
|
|
10879
|
+
font-family: Roboto, sans-serif;
|
|
10880
|
+
}
|
|
10881
|
+
|
|
10882
|
+
.${cls} .overlay-title {
|
|
10883
|
+
font-size: 14px;
|
|
10884
|
+
color: var(--owt-color-text, #011627);
|
|
10885
|
+
font-weight: 600;
|
|
10886
|
+
min-width: 0;
|
|
10887
|
+
overflow: hidden;
|
|
10888
|
+
text-overflow: ellipsis;
|
|
10889
|
+
white-space: nowrap;
|
|
10890
|
+
}
|
|
10891
|
+
|
|
10892
|
+
.${cls} .overlay-close {
|
|
10893
|
+
border: 1px solid var(--owt-btn-secondary-border, #C4C4C4);
|
|
10894
|
+
background: var(--owt-btn-secondary-bg, #FFFFFF);
|
|
10895
|
+
color: var(--owt-btn-secondary-color, #011627);
|
|
10896
|
+
border-radius: var(--owt-btn-border-radius, 10px);
|
|
10897
|
+
padding: 6px 10px;
|
|
10898
|
+
font-size: 12px;
|
|
10899
|
+
cursor: pointer;
|
|
10900
|
+
}
|
|
10901
|
+
|
|
10902
|
+
.${cls} .overlay-iframe {
|
|
10903
|
+
flex: 1 1 auto;
|
|
10904
|
+
width: 100%;
|
|
10905
|
+
border: none;
|
|
10906
|
+
}
|
|
10907
|
+
|
|
10581
10908
|
@media (max-width: 640px) {
|
|
10582
10909
|
.${cls} .auth-grid {
|
|
10583
10910
|
grid-template-columns: 1fr;
|
|
@@ -10592,7 +10919,15 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10592
10919
|
max-width: none;
|
|
10593
10920
|
}
|
|
10594
10921
|
}
|
|
10595
|
-
` }), jsxRuntimeExports.
|
|
10922
|
+
` }), jsxRuntimeExports.jsxs("div", { className: cls, children: [overlayUrl ? (jsxRuntimeExports.jsx("div", { className: "overlay-backdrop", role: "dialog", "aria-modal": "true", "aria-label": "Authentication", onClick: (e) => {
|
|
10923
|
+
if (e.target === e.currentTarget) {
|
|
10924
|
+
setOverlayUrl(null);
|
|
10925
|
+
emitHostEvent({ type: 'overlay_closed' });
|
|
10926
|
+
}
|
|
10927
|
+
}, children: jsxRuntimeExports.jsxs("div", { className: "overlay-panel", children: [jsxRuntimeExports.jsxs("div", { className: "overlay-header", children: [jsxRuntimeExports.jsx("div", { className: "overlay-title", children: providerName ? `Authenticate via ${providerName}` : 'Authenticate' }), jsxRuntimeExports.jsx("button", { type: "button", className: "overlay-close", onClick: () => {
|
|
10928
|
+
setOverlayUrl(null);
|
|
10929
|
+
emitHostEvent({ type: 'overlay_closed' });
|
|
10930
|
+
}, children: "Close" })] }), jsxRuntimeExports.jsx("iframe", { className: "overlay-iframe", src: overlayUrl, title: "Authentication" })] }) })) : null, jsxRuntimeExports.jsx("div", { className: "auth-content", children: jsxRuntimeExports.jsxs("div", { className: "auth-grid", children: [jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Foundational ID:" }), jsxRuntimeExports.jsx("div", { className: "auth-value auth-value--foundational", children: displayText(foundationalId) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Last authenticated on:" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: tryFormatDateTime(lastAuthenticatedOn) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Expiry date:" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: tryFormatDate(expiryDate) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Last authentication status:" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: jsxRuntimeExports.jsxs("div", { className: "auth-status", "aria-label": `Authentication status: ${statusLabel}`, children: [jsxRuntimeExports.jsx("span", { className: "auth-dot" }), jsxRuntimeExports.jsx("span", { children: statusLabel })] }) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", children: "Authentication token (PSUT):" }), jsxRuntimeExports.jsx("div", { className: "auth-value", children: jsxRuntimeExports.jsx("div", { className: "auth-token", children: psut ? String(psut) : '-' }) })] }), jsxRuntimeExports.jsxs("div", { className: "auth-cell auth-cell--action", children: [jsxRuntimeExports.jsx("div", { className: "auth-label", "aria-hidden": true }), jsxRuntimeExports.jsxs("div", { className: "auth-value", children: [jsxRuntimeExports.jsx("button", { type: "button", className: "auth-button", onClick: onAuthenticate, disabled: buttonDisabled, children: buttonBusy ? 'Loading…' : 'Authenticate' }), authError ? (jsxRuntimeExports.jsx("div", { className: "auth-error", style: { marginTop: 8 }, children: authError })) : null] })] })] }) })] })] }));
|
|
10596
10931
|
};
|
|
10597
10932
|
|
|
10598
10933
|
/**
|
|
@@ -10624,6 +10959,8 @@ const registerDefaultWidgets = () => {
|
|
|
10624
10959
|
widgetRegistry.register({ widget: 'simple-table', component: SimpleTableWidget });
|
|
10625
10960
|
// Table widget with record-level editing
|
|
10626
10961
|
widgetRegistry.register({ widget: 'table', component: TableWidget });
|
|
10962
|
+
// Table widget with add/edit popup dialog
|
|
10963
|
+
widgetRegistry.register({ widget: 'dialog-table', component: DialogTableWidget });
|
|
10627
10964
|
// Group widgets
|
|
10628
10965
|
widgetRegistry.register({ widget: 'array-widget', component: ArrayWidget });
|
|
10629
10966
|
widgetRegistry.register({ widget: 'iterable-accordion', component: IterableAccordionWidget });
|
|
@@ -11001,5 +11338,5 @@ const translateUISchema = (schema, translate) => {
|
|
|
11001
11338
|
};
|
|
11002
11339
|
};
|
|
11003
11340
|
|
|
11004
|
-
export { ArrayWidget, BooleanWidget, CheckboxWidget, CurrencyInputWidget, DateInputWidget, DateTimeInputWidget, DisplayWidget, FileInputWidget, HeaderSectionWidget, IdAuthenticationWidget, IterableAccordionWidget, JSONEditorPanel, NumberInputWidget, PanelRenderer, PhoneInputWidget, ProfileWidget, PropertyEditor, RadioWidget, ScoresDisplayWidget, SectionBuilder, SectionRenderer, SectionTree, SectionsContainer, SelectWidget, SimpleTableWidget, TableWidget, TextAreaWidget, TextInputWidget, VisualBuilderPanel, WidgetEventBus, WidgetProvider, WidgetRenderer, applyCaseControl, applyDecimalPrecision, applyMask, createWidgetStore, createZodSchema, defaultTheme, evaluateCondition, filterByCharacterType, formatCurrency, formatDate, formatNumber, formatPhone, formatValue, geoHierarchyBuilder, getApiDataSource, getFormattedNumberLength, getSchemaDataSource, getStaticDataSource, getValueByPath, getWidgetValue, initI18n, isAllowedKey, parseDataPath, parseNumber, registerDefaultWidgets, removeMask, resetAll, resetWidget, resolveTheme, setDataSource, setError, setLoading, setTouched, setValue, setValueByPath, setValues, setWidgetValue, shouldEnableWidget, shouldShowWidget, transformDataSourceOptions, translatePanelConfig, translateUISchema, translateWidgetConfig, useBaseWidget, useGeoWidgetCascade, useWidgetCascade, useWidgetContext, useWidgetEventBus, useWidgetTheme, useWidgetTranslation, validateNumericValue, validateWidget, widgetRegistry };
|
|
11341
|
+
export { ArrayWidget, BooleanWidget, CheckboxWidget, CurrencyInputWidget, DateInputWidget, DateTimeInputWidget, DialogTableWidget, DisplayWidget, FileInputWidget, HeaderSectionWidget, IdAuthenticationWidget, IterableAccordionWidget, JSONEditorPanel, NumberInputWidget, PanelRenderer, PhoneInputWidget, ProfileWidget, PropertyEditor, RadioWidget, ScoresDisplayWidget, SectionBuilder, SectionRenderer, SectionTree, SectionsContainer, SelectWidget, SimpleTableWidget, TableWidget, TextAreaWidget, TextInputWidget, VisualBuilderPanel, WidgetEventBus, WidgetProvider, WidgetRenderer, applyCaseControl, applyDecimalPrecision, applyMask, createWidgetStore, createZodSchema, defaultTheme, evaluateCondition, filterByCharacterType, formatCurrency, formatDate, formatNumber, formatPhone, formatValue, geoHierarchyBuilder, getApiDataSource, getFormattedNumberLength, getSchemaDataSource, getStaticDataSource, getValueByPath, getWidgetValue, initI18n, isAllowedKey, parseDataPath, parseNumber, registerDefaultWidgets, removeMask, resetAll, resetWidget, resolveTheme, setDataSource, setError, setLoading, setTouched, setValue, setValueByPath, setValues, setWidgetValue, shouldEnableWidget, shouldShowWidget, transformDataSourceOptions, translatePanelConfig, translateUISchema, translateWidgetConfig, useBaseWidget, useGeoWidgetCascade, useWidgetCascade, useWidgetContext, useWidgetEventBus, useWidgetTheme, useWidgetTranslation, validateNumericValue, validateWidget, widgetRegistry };
|
|
11005
11342
|
//# sourceMappingURL=index.esm.js.map
|