@openg2p/registry-widgets 1.1.0-dev.2 → 1.1.0-dev.3
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 +438 -103
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +438 -102
- 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() === '')
|
|
@@ -9879,6 +10160,19 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9879
10160
|
box-shadow: 0 0 0 2px rgba(237, 124, 34, 0.15);
|
|
9880
10161
|
}
|
|
9881
10162
|
|
|
10163
|
+
.${cls} .hdr-input--error {
|
|
10164
|
+
border-color: var(--owt-color-danger, #DC2626);
|
|
10165
|
+
box-shadow: 0 0 0 2px rgba(220, 38, 38, 0.12);
|
|
10166
|
+
}
|
|
10167
|
+
|
|
10168
|
+
.${cls} .hdr-error-text {
|
|
10169
|
+
margin-left: calc(0px);
|
|
10170
|
+
color: var(--owt-color-danger, #DC2626);
|
|
10171
|
+
font-size: 0.75rem;
|
|
10172
|
+
line-height: 1.2;
|
|
10173
|
+
font-weight: 500;
|
|
10174
|
+
}
|
|
10175
|
+
|
|
9882
10176
|
@media (max-width: 768px) {
|
|
9883
10177
|
.${cls} {
|
|
9884
10178
|
flex-direction: column;
|
|
@@ -9893,7 +10187,15 @@ const HeaderSectionWidget = ({ config }) => {
|
|
|
9893
10187
|
.parentElement?.querySelector('.hdr-avatar-placeholder');
|
|
9894
10188
|
if (placeholder)
|
|
9895
10189
|
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.
|
|
10190
|
+
} })) : 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: () => {
|
|
10191
|
+
if (isReasonMissing)
|
|
10192
|
+
setShowReasonRequired(true);
|
|
10193
|
+
}, onChange: (e) => {
|
|
10194
|
+
updateFieldValue('statusReason', e.target.value);
|
|
10195
|
+
if (showReasonRequired && String(e.target.value || '').trim().length > 0) {
|
|
10196
|
+
setShowReasonRequired(false);
|
|
10197
|
+
}
|
|
10198
|
+
} }), !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.completion} of ${score.ideal} (${score.percent}%)`, title: `${score.completion} / ${score.ideal} (${score.percent}%)`, children: jsxRuntimeExports.jsx("div", { className: "hdr-score-value", children: String(score.completion) }) })) : null] }) })] })] }));
|
|
9897
10199
|
};
|
|
9898
10200
|
|
|
9899
10201
|
function getValueByPathOrKey(obj, path) {
|
|
@@ -10194,7 +10496,8 @@ function pickAuthorizationUrl(resp, explicitKey) {
|
|
|
10194
10496
|
if (v)
|
|
10195
10497
|
return v;
|
|
10196
10498
|
}
|
|
10197
|
-
return (tryKey('
|
|
10499
|
+
return (tryKey('authentication_url') ||
|
|
10500
|
+
tryKey('authorization_url') ||
|
|
10198
10501
|
tryKey('authorizationUrl') ||
|
|
10199
10502
|
tryKey('auth_url') ||
|
|
10200
10503
|
tryKey('authUrl') ||
|
|
@@ -10209,12 +10512,14 @@ function resolveValueFromSources(path, values, schemaData) {
|
|
|
10209
10512
|
return fromValues;
|
|
10210
10513
|
return getValueByPath(schemaData, path);
|
|
10211
10514
|
}
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10515
|
+
function unwrapPayload(response) {
|
|
10516
|
+
if (response && typeof response === 'object') {
|
|
10517
|
+
if (response.response_body?.response_payload !== undefined)
|
|
10518
|
+
return response.response_body.response_payload;
|
|
10519
|
+
if (response.response_payload !== undefined)
|
|
10520
|
+
return response.response_payload;
|
|
10521
|
+
}
|
|
10522
|
+
return response;
|
|
10218
10523
|
}
|
|
10219
10524
|
const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
10220
10525
|
const { dataSourceRequestHandler, schemaData: ctxSchemaData } = useWidgetContext();
|
|
@@ -10228,6 +10533,11 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10228
10533
|
return dataPath;
|
|
10229
10534
|
}, [dataPath]);
|
|
10230
10535
|
const authConfig = config['widget-auth-config'];
|
|
10536
|
+
const registerId = resolveValueFromSources(paths.registerId, values, schemaData);
|
|
10537
|
+
const internalRecordId = resolveValueFromSources(paths.internalRecordId, values, schemaData);
|
|
10538
|
+
const initiatedByStaffId = resolveValueFromSources(paths.initiatedByStaffId, values, schemaData);
|
|
10539
|
+
const providerId = authConfig?.providerId;
|
|
10540
|
+
const providerName = authConfig?.providerName;
|
|
10231
10541
|
const foundationalId = resolveValueFromSources(paths.foundationalId, values, schemaData);
|
|
10232
10542
|
const lastAuthenticatedOn = resolveValueFromSources(paths.lastAuthenticatedOn, values, schemaData);
|
|
10233
10543
|
const lastAuthStatusRaw = resolveValueFromSources(paths.lastAuthenticationStatus, values, schemaData);
|
|
@@ -10236,11 +10546,11 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10236
10546
|
const status = useMemo(() => normalizeStatus(lastAuthStatusRaw), [lastAuthStatusRaw]);
|
|
10237
10547
|
/** URL from prefetch (or default); used when opening the OIDC / eSignet popup */
|
|
10238
10548
|
const [resolvedAuthUrl, setResolvedAuthUrl] = useState(null);
|
|
10239
|
-
const [providerLoading, setProviderLoading] = useState(false);
|
|
10240
10549
|
const [authActionLoading, setAuthActionLoading] = useState(false);
|
|
10241
10550
|
const [authError, setAuthError] = useState(null);
|
|
10242
10551
|
const popupRef = useRef(null);
|
|
10243
10552
|
const pollTimerRef = useRef(null);
|
|
10553
|
+
const [overlayUrl, setOverlayUrl] = useState(null);
|
|
10244
10554
|
const emitHostEvent = useCallback((detail) => {
|
|
10245
10555
|
if (typeof window === 'undefined')
|
|
10246
10556
|
return;
|
|
@@ -10269,72 +10579,16 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10269
10579
|
}
|
|
10270
10580
|
};
|
|
10271
10581
|
}, [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)
|
|
10582
|
+
// Provider details are supplied by host; clear any previous resolved URL on provider change.
|
|
10284
10583
|
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
|
-
}
|
|
10584
|
+
setResolvedAuthUrl(null);
|
|
10585
|
+
}, [providerId, providerName]);
|
|
10586
|
+
const openAuthPopup = useCallback((authUrl) => {
|
|
10587
|
+
if (authConfig?.useIframeOverlay !== false) {
|
|
10588
|
+
setOverlayUrl(authUrl);
|
|
10589
|
+
emitHostEvent({ type: 'overlay_opened' });
|
|
10305
10590
|
return;
|
|
10306
10591
|
}
|
|
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
10592
|
const pw = authConfig?.popupWidth ?? 1024;
|
|
10339
10593
|
const ph = authConfig?.popupHeight ?? 800;
|
|
10340
10594
|
const features = getCenteredPopupFeatures(pw, ph);
|
|
@@ -10370,20 +10624,24 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10370
10624
|
setAuthError('Missing widget-auth-config.');
|
|
10371
10625
|
return;
|
|
10372
10626
|
}
|
|
10373
|
-
const
|
|
10374
|
-
const canCallApi = Boolean(dataSourceRequestHandler && authConfig.service && authConfig.endpoint);
|
|
10627
|
+
const canCallAuthApi = Boolean(dataSourceRequestHandler && authConfig.service && authConfig.authenticateEndpoint);
|
|
10375
10628
|
let url = resolvedAuthUrl;
|
|
10376
|
-
if (!url &&
|
|
10629
|
+
if (!url && canCallAuthApi) {
|
|
10377
10630
|
setAuthActionLoading(true);
|
|
10378
10631
|
try {
|
|
10379
|
-
const
|
|
10380
|
-
|
|
10381
|
-
|
|
10382
|
-
|
|
10383
|
-
|
|
10632
|
+
const resp = await dataSourceRequestHandler(authConfig.service, authConfig.authenticateEndpoint, authConfig.authenticateMethod || 'POST', {
|
|
10633
|
+
register_id: registerId,
|
|
10634
|
+
internal_record_id: internalRecordId,
|
|
10635
|
+
provider_id: authConfig.providerId,
|
|
10636
|
+
initiated_by_staff_id: initiatedByStaffId,
|
|
10637
|
+
});
|
|
10638
|
+
const payload = unwrapPayload(resp);
|
|
10639
|
+
const authUrl = pickAuthorizationUrl(payload, authConfig.authorizationUrlKey);
|
|
10640
|
+
url = authUrl || null;
|
|
10641
|
+
if (authUrl)
|
|
10642
|
+
setResolvedAuthUrl(authUrl);
|
|
10384
10643
|
}
|
|
10385
10644
|
catch (e) {
|
|
10386
|
-
url = def || null;
|
|
10387
10645
|
if (!url) {
|
|
10388
10646
|
setAuthError(e?.message || 'Could not load provider URL.');
|
|
10389
10647
|
return;
|
|
@@ -10393,15 +10651,20 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10393
10651
|
setAuthActionLoading(false);
|
|
10394
10652
|
}
|
|
10395
10653
|
}
|
|
10396
|
-
else if (!url) {
|
|
10397
|
-
url = def || null;
|
|
10398
|
-
}
|
|
10399
10654
|
if (!url) {
|
|
10400
|
-
setAuthError('No authorization URL
|
|
10655
|
+
setAuthError('No authorization URL returned from authenticate_registrant.');
|
|
10401
10656
|
return;
|
|
10402
10657
|
}
|
|
10403
10658
|
openAuthPopup(url);
|
|
10404
|
-
}, [
|
|
10659
|
+
}, [
|
|
10660
|
+
authConfig,
|
|
10661
|
+
dataSourceRequestHandler,
|
|
10662
|
+
openAuthPopup,
|
|
10663
|
+
registerId,
|
|
10664
|
+
internalRecordId,
|
|
10665
|
+
initiatedByStaffId,
|
|
10666
|
+
resolvedAuthUrl,
|
|
10667
|
+
]);
|
|
10405
10668
|
useEffect(() => {
|
|
10406
10669
|
const successType = authConfig?.successMessageType || 'openg2p:oidc:success';
|
|
10407
10670
|
const handler = (event) => {
|
|
@@ -10446,8 +10709,7 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10446
10709
|
return 'var(--owt-color-warning, #D97706)';
|
|
10447
10710
|
return 'var(--owt-color-text-muted, #6B7280)';
|
|
10448
10711
|
}, [status]);
|
|
10449
|
-
const buttonBusy = authActionLoading
|
|
10450
|
-
(providerLoading && !resolvedAuthUrl && !authConfig?.defaultAuthorizationUrl);
|
|
10712
|
+
const buttonBusy = authActionLoading;
|
|
10451
10713
|
const buttonDisabled = !authConfig || buttonBusy;
|
|
10452
10714
|
return (jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [jsxRuntimeExports.jsx("style", { children: `
|
|
10453
10715
|
.${cls} {
|
|
@@ -10483,6 +10745,14 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10483
10745
|
grid-column: 1 / -1;
|
|
10484
10746
|
}
|
|
10485
10747
|
|
|
10748
|
+
/* Action cell: no left label spacer, align button to column start */
|
|
10749
|
+
.${cls} .auth-cell.auth-cell--action .auth-label {
|
|
10750
|
+
display: none;
|
|
10751
|
+
}
|
|
10752
|
+
.${cls} .auth-cell.auth-cell--action .auth-value {
|
|
10753
|
+
flex: 1 1 auto;
|
|
10754
|
+
}
|
|
10755
|
+
|
|
10486
10756
|
.${cls} .auth-label {
|
|
10487
10757
|
flex: 0 0 auto;
|
|
10488
10758
|
min-width: 200px;
|
|
@@ -10505,17 +10775,15 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10505
10775
|
word-break: break-word;
|
|
10506
10776
|
}
|
|
10507
10777
|
|
|
10508
|
-
.${cls} .auth-
|
|
10509
|
-
|
|
10510
|
-
|
|
10511
|
-
|
|
10512
|
-
|
|
10513
|
-
gap: 8px;
|
|
10514
|
-
width: 100%;
|
|
10515
|
-
margin-top: 20px;
|
|
10516
|
-
margin-bottom: 0;
|
|
10778
|
+
.${cls} .auth-value--foundational {
|
|
10779
|
+
font-size: 18px;
|
|
10780
|
+
font-weight: 700;
|
|
10781
|
+
color: var(--owt-color-primary-dark, #F07B1A);
|
|
10782
|
+
letter-spacing: 0.1px;
|
|
10517
10783
|
}
|
|
10518
10784
|
|
|
10785
|
+
/* Button is placed inside the grid (next to PSUT) */
|
|
10786
|
+
|
|
10519
10787
|
.${cls} .auth-status {
|
|
10520
10788
|
display: inline-flex;
|
|
10521
10789
|
align-items: center;
|
|
@@ -10556,8 +10824,8 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10556
10824
|
padding: 8px 24px;
|
|
10557
10825
|
line-height: 1.5;
|
|
10558
10826
|
border-radius: var(--owt-btn-border-radius, 10px);
|
|
10559
|
-
border: 1px solid
|
|
10560
|
-
background-color:
|
|
10827
|
+
border: 1px solid rgb(237, 124, 34);
|
|
10828
|
+
background-color: rgb(237, 124, 34);
|
|
10561
10829
|
color: var(--owt-color-bg, #FFFFFF);
|
|
10562
10830
|
font-family: Roboto, sans-serif;
|
|
10563
10831
|
cursor: pointer;
|
|
@@ -10578,6 +10846,63 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10578
10846
|
max-width: 100%;
|
|
10579
10847
|
}
|
|
10580
10848
|
|
|
10849
|
+
.${cls} .overlay-backdrop {
|
|
10850
|
+
position: fixed;
|
|
10851
|
+
inset: 0;
|
|
10852
|
+
background: rgba(17, 24, 39, 0.55);
|
|
10853
|
+
z-index: 9999;
|
|
10854
|
+
display: flex;
|
|
10855
|
+
align-items: center;
|
|
10856
|
+
justify-content: center;
|
|
10857
|
+
padding: 24px;
|
|
10858
|
+
}
|
|
10859
|
+
|
|
10860
|
+
.${cls} .overlay-panel {
|
|
10861
|
+
width: min(1100px, 92vw);
|
|
10862
|
+
height: min(820px, 92vh);
|
|
10863
|
+
background: var(--owt-color-bg, #FFFFFF);
|
|
10864
|
+
border-radius: 12px;
|
|
10865
|
+
box-shadow: 0 10px 30px rgba(0,0,0,0.25);
|
|
10866
|
+
overflow: hidden;
|
|
10867
|
+
display: flex;
|
|
10868
|
+
flex-direction: column;
|
|
10869
|
+
}
|
|
10870
|
+
|
|
10871
|
+
.${cls} .overlay-header {
|
|
10872
|
+
display: flex;
|
|
10873
|
+
align-items: center;
|
|
10874
|
+
justify-content: space-between;
|
|
10875
|
+
padding: 10px 14px;
|
|
10876
|
+
border-bottom: 1px solid var(--owt-color-border-light, #E4E4E4);
|
|
10877
|
+
font-family: Roboto, sans-serif;
|
|
10878
|
+
}
|
|
10879
|
+
|
|
10880
|
+
.${cls} .overlay-title {
|
|
10881
|
+
font-size: 14px;
|
|
10882
|
+
color: var(--owt-color-text, #011627);
|
|
10883
|
+
font-weight: 600;
|
|
10884
|
+
min-width: 0;
|
|
10885
|
+
overflow: hidden;
|
|
10886
|
+
text-overflow: ellipsis;
|
|
10887
|
+
white-space: nowrap;
|
|
10888
|
+
}
|
|
10889
|
+
|
|
10890
|
+
.${cls} .overlay-close {
|
|
10891
|
+
border: 1px solid var(--owt-btn-secondary-border, #C4C4C4);
|
|
10892
|
+
background: var(--owt-btn-secondary-bg, #FFFFFF);
|
|
10893
|
+
color: var(--owt-btn-secondary-color, #011627);
|
|
10894
|
+
border-radius: var(--owt-btn-border-radius, 10px);
|
|
10895
|
+
padding: 6px 10px;
|
|
10896
|
+
font-size: 12px;
|
|
10897
|
+
cursor: pointer;
|
|
10898
|
+
}
|
|
10899
|
+
|
|
10900
|
+
.${cls} .overlay-iframe {
|
|
10901
|
+
flex: 1 1 auto;
|
|
10902
|
+
width: 100%;
|
|
10903
|
+
border: none;
|
|
10904
|
+
}
|
|
10905
|
+
|
|
10581
10906
|
@media (max-width: 640px) {
|
|
10582
10907
|
.${cls} .auth-grid {
|
|
10583
10908
|
grid-template-columns: 1fr;
|
|
@@ -10592,7 +10917,15 @@ const IdAuthenticationWidget = ({ config, schemaData: propSchemaData }) => {
|
|
|
10592
10917
|
max-width: none;
|
|
10593
10918
|
}
|
|
10594
10919
|
}
|
|
10595
|
-
` }), jsxRuntimeExports.
|
|
10920
|
+
` }), jsxRuntimeExports.jsxs("div", { className: cls, children: [overlayUrl ? (jsxRuntimeExports.jsx("div", { className: "overlay-backdrop", role: "dialog", "aria-modal": "true", "aria-label": "Authentication", onClick: (e) => {
|
|
10921
|
+
if (e.target === e.currentTarget) {
|
|
10922
|
+
setOverlayUrl(null);
|
|
10923
|
+
emitHostEvent({ type: 'overlay_closed' });
|
|
10924
|
+
}
|
|
10925
|
+
}, 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: () => {
|
|
10926
|
+
setOverlayUrl(null);
|
|
10927
|
+
emitHostEvent({ type: 'overlay_closed' });
|
|
10928
|
+
}, 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
10929
|
};
|
|
10597
10930
|
|
|
10598
10931
|
/**
|
|
@@ -10624,6 +10957,8 @@ const registerDefaultWidgets = () => {
|
|
|
10624
10957
|
widgetRegistry.register({ widget: 'simple-table', component: SimpleTableWidget });
|
|
10625
10958
|
// Table widget with record-level editing
|
|
10626
10959
|
widgetRegistry.register({ widget: 'table', component: TableWidget });
|
|
10960
|
+
// Table widget with add/edit popup dialog
|
|
10961
|
+
widgetRegistry.register({ widget: 'dialog-table', component: DialogTableWidget });
|
|
10627
10962
|
// Group widgets
|
|
10628
10963
|
widgetRegistry.register({ widget: 'array-widget', component: ArrayWidget });
|
|
10629
10964
|
widgetRegistry.register({ widget: 'iterable-accordion', component: IterableAccordionWidget });
|
|
@@ -11001,5 +11336,5 @@ const translateUISchema = (schema, translate) => {
|
|
|
11001
11336
|
};
|
|
11002
11337
|
};
|
|
11003
11338
|
|
|
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 };
|
|
11339
|
+
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
11340
|
//# sourceMappingURL=index.esm.js.map
|