@asteby/metacore-runtime-react 34.1.0 → 35.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +5 -90
- package/dist/action-modal-dispatcher.d.ts +4 -0
- package/dist/action-modal-dispatcher.d.ts.map +1 -1
- package/dist/action-modal-dispatcher.js +102 -23
- package/dist/addon-loader.d.ts +1 -1
- package/dist/addon-loader.d.ts.map +1 -1
- package/dist/addon-loader.js +8 -1
- package/dist/dialogs/dynamic-record.d.ts.map +1 -1
- package/dist/dialogs/dynamic-record.js +99 -61
- package/dist/dynamic-columns.d.ts.map +1 -1
- package/dist/dynamic-columns.js +23 -8
- package/dist/dynamic-select-field.d.ts.map +1 -1
- package/dist/dynamic-select-field.js +6 -3
- package/dist/use-print-document.d.ts +10 -1
- package/dist/use-print-document.d.ts.map +1 -1
- package/dist/use-print-document.js +28 -1
- package/package.json +1 -1
- package/src/__tests__/filename-from-disposition.test.ts +30 -0
- package/src/__tests__/prefill-scalar-from-record.test.ts +37 -0
- package/src/__tests__/record-detail-display.test.tsx +30 -0
- package/src/action-modal-dispatcher.tsx +110 -22
- package/src/addon-loader.tsx +7 -1
- package/src/dialogs/dynamic-record.tsx +139 -65
- package/src/dynamic-columns.tsx +28 -12
- package/src/dynamic-select-field.tsx +7 -3
- package/src/use-print-document.ts +38 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,88 +1,10 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## 35.0.0
|
|
4
4
|
|
|
5
5
|
### Minor Changes
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
|
|
9
|
-
## 34.0.2
|
|
10
|
-
|
|
11
|
-
### Patch Changes
|
|
12
|
-
|
|
13
|
-
- 7bff072: Locale-aware FilePickButton: hide native file chrome so labels follow app language (es/en). UploadField and ImportDialog use it.
|
|
14
|
-
|
|
15
|
-
## 34.0.1
|
|
16
|
-
|
|
17
|
-
### Patch Changes
|
|
18
|
-
|
|
19
|
-
- 45b5f91: Fix relation/brand thumbnails (RelationCell) being cropped: switch from
|
|
20
|
-
`object-cover` to `object-contain` on a padded neutral background so
|
|
21
|
-
wide/rectangular logos (brand, supplier, category images) render in full
|
|
22
|
-
instead of clipped to a square.
|
|
23
|
-
|
|
24
|
-
## 34.0.0
|
|
25
|
-
|
|
26
|
-
### Patch Changes
|
|
27
|
-
|
|
28
|
-
- Updated dependencies [5c51b7f]
|
|
29
|
-
- @asteby/metacore-ui@2.16.0
|
|
30
|
-
|
|
31
|
-
## 33.1.1
|
|
32
|
-
|
|
33
|
-
### Patch Changes
|
|
34
|
-
|
|
35
|
-
- 921a74c: Crear una categoría (u otro registro) desde el "+" de un modal ya no
|
|
36
|
-
valida el formulario de atrás. Cada diálogo tiene su propio `form` id, y
|
|
37
|
-
el toast de validación lista los mensajes del validator.
|
|
38
|
-
|
|
39
|
-
## 33.1.0
|
|
40
|
-
|
|
41
|
-
### Minor Changes
|
|
42
|
-
|
|
43
|
-
- 9eab4e0: `EntitySelect` now accepts `createDefaults` and `lockedCreateFields` to seed
|
|
44
|
-
and lock fields in its inline "+" create dialog. Motivating case: the POS
|
|
45
|
-
vehicle picker creating a vehicle for an already-selected customer — the
|
|
46
|
-
customer field should come pre-filled and not be changeable from that
|
|
47
|
-
context, instead of the user having to search/select it again (and risking
|
|
48
|
-
attaching the vehicle to the wrong customer).
|
|
49
|
-
|
|
50
|
-
- `createDefaults?: Record<string, unknown>` — seeds the create dialog's
|
|
51
|
-
form (passed through as `CreateRecordDialog.defaults`).
|
|
52
|
-
- `lockedCreateFields?: string[]` — keys from `createDefaults` that render
|
|
53
|
-
visible-but-disabled on create instead of editable (passed through as the
|
|
54
|
-
new `CreateRecordDialog.lockedFields` / `DynamicRecordDialog.lockedFields`).
|
|
55
|
-
|
|
56
|
-
New `lockedFields` support in `DynamicRecordDialog`/`CreateRecordDialog`:
|
|
57
|
-
unlike a `readonly` field (excluded entirely on create), a locked field stays
|
|
58
|
-
visible so the user sees what value is being submitted, rendered through the
|
|
59
|
-
same `ReadonlyEditField` used for edit-mode readonly fields. Also fixes
|
|
60
|
-
`ReadonlyEditField` for relation/`Ref` fields (readonly-on-edit and now
|
|
61
|
-
locked-on-create): it previously rendered the raw foreign id, and now
|
|
62
|
-
resolves and shows the related record's label like `RelationViewValue`
|
|
63
|
-
already does in view mode.
|
|
64
|
-
|
|
65
|
-
## 33.0.0
|
|
66
|
-
|
|
67
|
-
### Patch Changes
|
|
68
|
-
|
|
69
|
-
- Updated dependencies [e74975a]
|
|
70
|
-
- @asteby/metacore-sdk@3.6.0
|
|
71
|
-
|
|
72
|
-
## 32.1.0
|
|
73
|
-
|
|
74
|
-
### Minor Changes
|
|
75
|
-
|
|
76
|
-
- fa25f99: Laravel-style field validator: localize 422 `{errors:{field:[{code,params}]}}`
|
|
77
|
-
into the operator's language (es/en catalogs, overridable via `validation.*`),
|
|
78
|
-
map keys to translated labels, and pre-flight the same regex/min/max/custom
|
|
79
|
-
rules the kernel enforces — no more generic "validation failed" / `[object Object]`.
|
|
80
|
-
|
|
81
|
-
## 32.0.0
|
|
82
|
-
|
|
83
|
-
### Minor Changes
|
|
84
|
-
|
|
85
|
-
- 5a932ed: Addon fiber hot-swap without a page reload: Registry.scope/unbind, Plugin.register
|
|
7
|
+
- Addon fiber hot-swap without a page reload: Registry.scope/unbind, Plugin.register
|
|
86
8
|
may return a Disposable, AddonLoader re-registers federation remotes when `?v=`
|
|
87
9
|
changes, and purgeAddonFrontendCache drops only that addon's SW cache (L1).
|
|
88
10
|
Hosts call acknowledgeRunningVersion after a successful swap instead of
|
|
@@ -90,18 +12,11 @@
|
|
|
90
12
|
|
|
91
13
|
### Patch Changes
|
|
92
14
|
|
|
93
|
-
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
- Updated dependencies [5a932ed]
|
|
15
|
+
- 7Leguas wave: registry action bridge, dynamic record/columns display, addon-loader error UX, notifications dropdown polish.
|
|
16
|
+
- Updated dependencies
|
|
17
|
+
- Updated dependencies
|
|
97
18
|
- @asteby/metacore-sdk@3.5.0
|
|
98
19
|
|
|
99
|
-
## 31.1.1
|
|
100
|
-
|
|
101
|
-
### Patch Changes
|
|
102
|
-
|
|
103
|
-
- 00caf65: PermissionsManager: add "Otorgar todo"/"Quitar todo" buttons (all modules, not just the open one) and a "Otorgar todos los permisos" checkbox when creating a role — grants full catalog access immediately instead of requiring every module to be checked one by one.
|
|
104
|
-
|
|
105
20
|
## 31.1.0
|
|
106
21
|
|
|
107
22
|
### Minor Changes
|
|
@@ -20,5 +20,9 @@ export interface PrefillSpec {
|
|
|
20
20
|
export declare function isPrefillSpec(v: unknown): v is PrefillSpec;
|
|
21
21
|
export declare function applyPrefillLock(field: ActionFieldDef): ActionFieldDef;
|
|
22
22
|
export declare function buildPrefillRows(spec: PrefillSpec, record: any): Array<Record<string, any>>;
|
|
23
|
+
export declare function unwrapRecordScalar(value: unknown): unknown;
|
|
24
|
+
export declare function readRecordPath(record: any, path: string): unknown;
|
|
25
|
+
/** Scalar seed for one action field from the row being acted on. */
|
|
26
|
+
export declare function scalarDefaultFromRecord(field: ActionFieldDef, record: any): unknown;
|
|
23
27
|
export declare function ActionModalDispatcher({ open, onOpenChange, action, model, record, endpoint, onSuccess, }: ActionModalProps): import("react").JSX.Element | null;
|
|
24
28
|
//# sourceMappingURL=action-modal-dispatcher.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-modal-dispatcher.d.ts","sourceRoot":"","sources":["../src/action-modal-dispatcher.tsx"],"names":[],"mappings":"AA4DA,OAAO,KAAK,EAAE,cAAc,EAAmC,MAAM,SAAS,CAAA;AAE9E,OAAO,EACH,KAAK,cAAc,EACnB,KAAK,gBAAgB,EAExB,MAAM,sBAAsB,CAAA;AAE7B,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAA;AAiBhD,MAAM,WAAW,WAAW;IACxB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,SAAS,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1D;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAM1D;AAsBD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAStE;AAGD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAkB3F;AAED,wBAAgB,qBAAqB,CAAC,EAClC,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,MAAM,EACN,QAAQ,EACR,SAAS,GACZ,EAAE,gBAAgB,sCAoElB"}
|
|
1
|
+
{"version":3,"file":"action-modal-dispatcher.d.ts","sourceRoot":"","sources":["../src/action-modal-dispatcher.tsx"],"names":[],"mappings":"AA4DA,OAAO,KAAK,EAAE,cAAc,EAAmC,MAAM,SAAS,CAAA;AAE9E,OAAO,EACH,KAAK,cAAc,EACnB,KAAK,gBAAgB,EAExB,MAAM,sBAAsB,CAAA;AAE7B,YAAY,EAAE,cAAc,EAAE,gBAAgB,EAAE,CAAA;AAiBhD,MAAM,WAAW,WAAW;IACxB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC5B,SAAS,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IAC1D;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,CAAC,IAAI,WAAW,CAM1D;AAsBD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,cAAc,GAAG,cAAc,CAStE;AAGD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAkB3F;AASD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAY1D;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CASjE;AAUD,oEAAoE;AACpE,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,GAAG,OAAO,CAgBnF;AAED,wBAAgB,qBAAqB,CAAC,EAClC,IAAI,EACJ,YAAY,EACZ,MAAM,EACN,KAAK,EACL,MAAM,EACN,QAAQ,EACR,SAAS,GACZ,EAAE,gBAAgB,sCAoElB"}
|
|
@@ -89,6 +89,68 @@ export function buildPrefillRows(spec, record) {
|
|
|
89
89
|
}
|
|
90
90
|
return rows;
|
|
91
91
|
}
|
|
92
|
+
// ---- scalar prefill from the acted-on record --------------------------------
|
|
93
|
+
//
|
|
94
|
+
// Row actions (stamp / refactura / cancel-with-reason) should open with the
|
|
95
|
+
// current record's values, not empty selects. Manifest declares explicit paths
|
|
96
|
+
// via `defaultFromRecord` (string or string[] fallback chain). When omitted,
|
|
97
|
+
// the field seeds from record[field.key] if present.
|
|
98
|
+
export function unwrapRecordScalar(value) {
|
|
99
|
+
if (value === null || value === undefined)
|
|
100
|
+
return value;
|
|
101
|
+
if (typeof value !== 'object' || value instanceof Date)
|
|
102
|
+
return value;
|
|
103
|
+
if (Array.isArray(value))
|
|
104
|
+
return value;
|
|
105
|
+
const o = value;
|
|
106
|
+
if ('value' in o && (typeof o.value === 'string' || typeof o.value === 'number')) {
|
|
107
|
+
return o.value;
|
|
108
|
+
}
|
|
109
|
+
if ('id' in o && (typeof o.id === 'string' || typeof o.id === 'number')) {
|
|
110
|
+
return o.id;
|
|
111
|
+
}
|
|
112
|
+
return value;
|
|
113
|
+
}
|
|
114
|
+
export function readRecordPath(record, path) {
|
|
115
|
+
if (!record || !path)
|
|
116
|
+
return undefined;
|
|
117
|
+
const parts = path.split('.');
|
|
118
|
+
let cur = record;
|
|
119
|
+
for (const p of parts) {
|
|
120
|
+
if (cur == null || typeof cur !== 'object')
|
|
121
|
+
return undefined;
|
|
122
|
+
cur = cur[p];
|
|
123
|
+
}
|
|
124
|
+
return unwrapRecordScalar(cur);
|
|
125
|
+
}
|
|
126
|
+
function defaultFromRecordSpec(field) {
|
|
127
|
+
const f = field;
|
|
128
|
+
return f.defaultFromRecord ?? f.default_from_record;
|
|
129
|
+
}
|
|
130
|
+
/** Scalar seed for one action field from the row being acted on. */
|
|
131
|
+
export function scalarDefaultFromRecord(field, record) {
|
|
132
|
+
if (!record)
|
|
133
|
+
return undefined;
|
|
134
|
+
const spec = defaultFromRecordSpec(field);
|
|
135
|
+
if (typeof spec === 'string') {
|
|
136
|
+
const v = readRecordPath(record, spec);
|
|
137
|
+
if (v !== undefined && v !== null && v !== '')
|
|
138
|
+
return v;
|
|
139
|
+
}
|
|
140
|
+
else if (Array.isArray(spec)) {
|
|
141
|
+
for (const path of spec) {
|
|
142
|
+
const v = readRecordPath(record, path);
|
|
143
|
+
if (v !== undefined && v !== null && v !== '')
|
|
144
|
+
return v;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
else if (field.key) {
|
|
148
|
+
const v = readRecordPath(record, field.key);
|
|
149
|
+
if (v !== undefined && v !== null && v !== '')
|
|
150
|
+
return v;
|
|
151
|
+
}
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
92
154
|
export function ActionModalDispatcher({ open, onOpenChange, action, model, record, endpoint, onSuccess, }) {
|
|
93
155
|
const CustomComponent = useMemo(() => getActionComponent(model, action.key), [model, action.key]);
|
|
94
156
|
if (CustomComponent) {
|
|
@@ -191,13 +253,16 @@ function selectPreviewColumns(columns, record) {
|
|
|
191
253
|
lineItemRows.push({ col, value, lineItems: true });
|
|
192
254
|
continue;
|
|
193
255
|
}
|
|
194
|
-
// Relación (ref / search / dynamic_select / *_id): solo si el sibling
|
|
195
|
-
// resolvió a un label legible;
|
|
256
|
+
// Relación (ref / search / dynamic_select / uuid *_id): solo si el sibling
|
|
257
|
+
// resolvió a un label legible; text `*_id` (external_id) no es FK.
|
|
258
|
+
const t = String(col.type || '').toLowerCase();
|
|
196
259
|
const isRelation = !!getFieldRef(col) ||
|
|
197
260
|
col.type === 'search' ||
|
|
198
261
|
col.type === 'relation' ||
|
|
199
262
|
col.widget === 'dynamic_select' ||
|
|
200
|
-
(typeof col.key === 'string' &&
|
|
263
|
+
(typeof col.key === 'string' &&
|
|
264
|
+
col.key.endsWith('_id') &&
|
|
265
|
+
(t === 'uuid' || t === 'search' || t === 'relation' || t === 'dynamic_select' || t === 'belongs_to'));
|
|
201
266
|
if (isRelation) {
|
|
202
267
|
const sib = relationSiblingValue(col, record);
|
|
203
268
|
const label = typeof sib === 'string' ? sib : objectLabel(sib);
|
|
@@ -361,20 +426,7 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
|
|
|
361
426
|
}, [open, model, recordId, api]);
|
|
362
427
|
useEffect(() => {
|
|
363
428
|
if (open && action.fields) {
|
|
364
|
-
|
|
365
|
-
for (const field of action.fields) {
|
|
366
|
-
if (isLineItemsField(field)) {
|
|
367
|
-
const dv = lineItemsDefault(field);
|
|
368
|
-
defaults[field.key] = isPrefillSpec(dv)
|
|
369
|
-
? buildPrefillRows(dv, record)
|
|
370
|
-
: Array.isArray(dv)
|
|
371
|
-
? dv
|
|
372
|
-
: [];
|
|
373
|
-
continue;
|
|
374
|
-
}
|
|
375
|
-
defaults[field.key] = field.defaultValue ?? (field.type === 'boolean' ? false : '');
|
|
376
|
-
}
|
|
377
|
-
setFormData(defaults);
|
|
429
|
+
setFormData(buildFieldDefaults(action.fields, record));
|
|
378
430
|
setFieldErrors({});
|
|
379
431
|
}
|
|
380
432
|
}, [open, action.fields, record]);
|
|
@@ -439,18 +491,19 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
|
|
|
439
491
|
// unlike an arbitrary Tailwind class that the host's scan may drop), capped
|
|
440
492
|
// to the viewport so it stays responsive on phones.
|
|
441
493
|
const hasLineItems = useMemo(() => (action.fields ?? []).some(isLineItemsField), [action.fields]);
|
|
494
|
+
const embedRelations = hasLineItems || !!action.embedRelations;
|
|
442
495
|
const explicitWidth = action.modalWidth;
|
|
443
496
|
const widthPx = explicitWidth != null
|
|
444
497
|
? (typeof explicitWidth === 'number' ? `${explicitWidth}px` : explicitWidth)
|
|
445
498
|
: hasLineItems
|
|
446
499
|
? '820px'
|
|
447
500
|
: undefined;
|
|
448
|
-
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: 'flex max-h-[90dvh] flex-col overflow-hidden ' + (widthPx ? '' : 'sm:max-w-xl'), style: { maxHeight: '90dvh', ...(widthPx ? { maxWidth: widthPx, width: '95vw' } : {}) }, children: [_jsxs(DialogHeader, { className: "shrink-0", children: [_jsxs(DialogTitle, { className: "flex items-center gap-2", children: [_jsx(DynamicIcon, { name: action.icon, className: "h-5 w-5" }), tl(action.label)] }), action.confirmMessage && _jsx(DialogDescription, { children: action.confirmMessage })] }), _jsx("div", { className: "-mx-1 min-h-0 flex-1 overflow-y-auto px-1 py-4", children: _jsxs(FieldGrid, { children: [action.fields?.map((field) => {
|
|
501
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: 'flex max-h-[90dvh] flex-col overflow-hidden ' + (widthPx ? '' : 'sm:max-w-xl'), style: { maxHeight: '90dvh', ...(widthPx ? { maxWidth: widthPx, width: '95vw' } : {}) }, children: [_jsxs(DialogHeader, { className: "shrink-0", children: [_jsxs(DialogTitle, { className: "flex items-center gap-2", children: [_jsx(DynamicIcon, { name: action.icon, className: "h-5 w-5" }), tl(action.label)] }), action.confirmMessage && _jsx(DialogDescription, { children: tl(action.confirmMessage) })] }), _jsx("div", { className: "-mx-1 min-h-0 flex-1 overflow-y-auto px-1 py-4", children: _jsxs(FieldGrid, { children: [action.fields?.map((field) => {
|
|
449
502
|
const fullWidth = isLineItemsField(field) ||
|
|
450
503
|
resolveWidget(field) === 'textarea' ||
|
|
451
504
|
resolveWidget(field) === 'richtext';
|
|
452
|
-
return (_jsxs(FieldCell, { fullWidth: fullWidth, children: [_jsx(FieldLabel, { htmlFor: field.key, required: field.required, children: tl(field.label) }), renderField(field, formData[field.key], (v) => updateField(field.key, v), formData), fieldErrors[field.key] && (_jsx("p", { className: "text-destructive text-xs mt-1", children: fieldErrors[field.key] }))] }, field.key));
|
|
453
|
-
}), relations.length > 0 && (_jsx(FieldCell, { fullWidth: true, children: _jsx(DynamicRelations, { record: record, relations: relations, lineSubtable: true, embedOnly: true }) }))] }) }), _jsxs(DialogFooter, { className: "shrink-0", children: [_jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: executing, children: t('common.cancel') }), _jsxs(Button, { onClick: execute, disabled: executing, style: action.color ? { backgroundColor: action.color, color: 'white' } : undefined, children: [executing ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(DynamicIcon, { name: action.icon, className: "mr-2 h-4 w-4" }), tl(action.label)] })] })] }) }));
|
|
505
|
+
return (_jsxs(FieldCell, { fullWidth: fullWidth, children: [_jsx(FieldLabel, { htmlFor: field.key, required: field.required, children: tl(field.label) }), renderField(field, formData[field.key], (v) => updateField(field.key, v), formData, record), fieldErrors[field.key] && (_jsx("p", { className: "text-destructive text-xs mt-1", children: fieldErrors[field.key] }))] }, field.key));
|
|
506
|
+
}), embedRelations && relations.length > 0 && (_jsx(FieldCell, { fullWidth: true, children: _jsx(DynamicRelations, { record: record, relations: relations, lineSubtable: true, embedOnly: true }) }))] }) }), _jsxs(DialogFooter, { className: "shrink-0", children: [_jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: executing, children: t('common.cancel') }), _jsxs(Button, { onClick: execute, disabled: executing, style: action.color ? { backgroundColor: action.color, color: 'white' } : undefined, children: [executing ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(DynamicIcon, { name: action.icon, className: "mr-2 h-4 w-4" }), tl(action.label)] })] })] }) }));
|
|
454
507
|
}
|
|
455
508
|
// buildFieldDefaults seeds formData for a set of action fields, honoring the
|
|
456
509
|
// same line-items prefill spec + boolean/empty rules GenericActionModal uses, so
|
|
@@ -467,6 +520,11 @@ function buildFieldDefaults(fields, record) {
|
|
|
467
520
|
: [];
|
|
468
521
|
continue;
|
|
469
522
|
}
|
|
523
|
+
const fromRecord = scalarDefaultFromRecord(field, record);
|
|
524
|
+
if (fromRecord !== undefined && fromRecord !== null && fromRecord !== '') {
|
|
525
|
+
defaults[field.key] = fromRecord;
|
|
526
|
+
continue;
|
|
527
|
+
}
|
|
470
528
|
defaults[field.key] = field.defaultValue ?? (field.type === 'boolean' ? false : '');
|
|
471
529
|
}
|
|
472
530
|
return defaults;
|
|
@@ -561,15 +619,36 @@ function WizardActionModal({ open, onOpenChange, action, model, record, endpoint
|
|
|
561
619
|
const fullWidth = isLineItemsField(field) ||
|
|
562
620
|
resolveWidget(field) === 'textarea' ||
|
|
563
621
|
resolveWidget(field) === 'richtext';
|
|
564
|
-
return (_jsxs(FieldCell, { fullWidth: fullWidth, children: [_jsx(FieldLabel, { htmlFor: field.key, required: field.required, children: tl(field.label) }), renderField(field, formData[field.key], (v) => updateField(field.key, v), formData)] }, field.key));
|
|
622
|
+
return (_jsxs(FieldCell, { fullWidth: fullWidth, children: [_jsx(FieldLabel, { htmlFor: field.key, required: field.required, children: tl(field.label) }), renderField(field, formData[field.key], (v) => updateField(field.key, v), formData, record)] }, field.key));
|
|
565
623
|
}) }) }), _jsxs(DialogFooter, { className: "shrink-0", children: [stepIndex > 0 ? (_jsx(Button, { variant: "outline", onClick: goBack, disabled: executing, children: t('common.back', { defaultValue: 'Atrás' }) })) : (_jsx(Button, { variant: "outline", onClick: () => onOpenChange(false), disabled: executing, children: t('common.cancel') })), isLast ? (_jsxs(Button, { onClick: submit, disabled: executing, style: action.color ? { backgroundColor: action.color, color: 'white' } : undefined, children: [executing ? _jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }) : _jsx(DynamicIcon, { name: action.icon, className: "mr-2 h-4 w-4" }), tl(action.label)] })) : (_jsx(Button, { onClick: goNext, disabled: executing, style: action.color ? { backgroundColor: action.color, color: 'white' } : undefined, children: t('common.next', { defaultValue: 'Siguiente' }) }))] })] }) }));
|
|
566
624
|
}
|
|
625
|
+
function seedOptionFromRecord(field, value, record) {
|
|
626
|
+
if (!record || !field.key.endsWith('_id'))
|
|
627
|
+
return undefined;
|
|
628
|
+
const siblingKey = field.key.replace(/_id$/, '');
|
|
629
|
+
const sib = record[siblingKey];
|
|
630
|
+
if (!sib || typeof sib !== 'object')
|
|
631
|
+
return undefined;
|
|
632
|
+
const label = sib.label ?? sib.name ?? '';
|
|
633
|
+
if (!label && !sib.image)
|
|
634
|
+
return undefined;
|
|
635
|
+
const id = String(sib.value ?? sib.id ?? value ?? '');
|
|
636
|
+
return {
|
|
637
|
+
id,
|
|
638
|
+
value: id,
|
|
639
|
+
label: String(label),
|
|
640
|
+
name: String(label),
|
|
641
|
+
image: sib.image,
|
|
642
|
+
color: sib.color,
|
|
643
|
+
icon: sib.icon,
|
|
644
|
+
};
|
|
645
|
+
}
|
|
567
646
|
function renderField(field, value, onChange,
|
|
568
647
|
// Full current form values — lets a line-items grid (and any cascading
|
|
569
648
|
// header picker) resolve a `dependsOn` reference against sibling header
|
|
570
649
|
// fields. Omitted by callers that have no surrounding form (the field is
|
|
571
650
|
// then treated as having no resolvable dependency).
|
|
572
|
-
formValues) {
|
|
651
|
+
formValues, record) {
|
|
573
652
|
// Repeatable line-items group → row grid (value is an array of row objects).
|
|
574
653
|
// The header form values flow in so a cell can depend on a header field.
|
|
575
654
|
if (isLineItemsField(field)) {
|
|
@@ -586,7 +665,7 @@ formValues) {
|
|
|
586
665
|
const dependsValue = getDependsOn(field)
|
|
587
666
|
? resolveDependsValue(field, formValues)
|
|
588
667
|
: undefined;
|
|
589
|
-
return _jsx(DynamicSelectField, { field: field, value: value, onChange: onChange, dependsValue: dependsValue });
|
|
668
|
+
return (_jsx(DynamicSelectField, { field: field, value: value, onChange: onChange, dependsValue: dependsValue, seedOption: seedOptionFromRecord(field, value, record) }));
|
|
590
669
|
}
|
|
591
670
|
// File upload → themed picker that POSTs the file to the host upload
|
|
592
671
|
// endpoint and stores the returned url/path. Kept in sync with DynamicForm.
|
package/dist/addon-loader.d.ts
CHANGED
|
@@ -44,5 +44,5 @@ export interface AddonLoaderProps {
|
|
|
44
44
|
layout?: AddonLayout;
|
|
45
45
|
children?: React.ReactNode;
|
|
46
46
|
}
|
|
47
|
-
export declare function AddonLoader({ scope, url, module, api, hostRegistry, addonKey, unbindKey, fallback, onReady, onError, layout, children, }: AddonLoaderProps): import("react").JSX.Element;
|
|
47
|
+
export declare function AddonLoader({ scope, url, module, api, hostRegistry, addonKey, unbindKey, fallback, onReady, onError, layout, children, }: AddonLoaderProps): import("react").JSX.Element | null;
|
|
48
48
|
//# sourceMappingURL=addon-loader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"addon-loader.d.ts","sourceRoot":"","sources":["../src/addon-loader.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAc3E,MAAM,WAAW,gBAAgB;IAC7B,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAA;IACb,+EAA+E;IAC/E,GAAG,EAAE,MAAM,CAAA;IACX,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,GAAG,EAAE,QAAQ,CAAA;IACb;;;;OAIG;IACH,YAAY,CAAC,EAAE,QAAQ,CAAA;IACvB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;IAC9B;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC7B;AA4DD,wBAAgB,WAAW,CAAC,EACxB,KAAK,EACL,GAAG,EACH,MAAqB,EACrB,GAAG,EACH,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,QAAe,EACf,OAAO,EACP,OAAO,EACP,MAAM,EACN,QAAQ,GACX,EAAE,gBAAgB
|
|
1
|
+
{"version":3,"file":"addon-loader.d.ts","sourceRoot":"","sources":["../src/addon-loader.tsx"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAc3E,MAAM,WAAW,gBAAgB;IAC7B,uEAAuE;IACvE,KAAK,EAAE,MAAM,CAAA;IACb,+EAA+E;IAC/E,GAAG,EAAE,MAAM,CAAA;IACX,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,+DAA+D;IAC/D,GAAG,EAAE,QAAQ,CAAA;IACb;;;;OAIG;IACH,YAAY,CAAC,EAAE,QAAQ,CAAA;IACvB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,iFAAiF;IACjF,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAA;IAC9B;;;;;;;;;;OAUG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;CAC7B;AA4DD,wBAAgB,WAAW,CAAC,EACxB,KAAK,EACL,GAAG,EACH,MAAqB,EACrB,GAAG,EACH,YAAY,EACZ,QAAQ,EACR,SAAS,EACT,QAAe,EACf,OAAO,EACP,OAAO,EACP,MAAM,EACN,QAAQ,GACX,EAAE,gBAAgB,sCAmElB"}
|
package/dist/addon-loader.js
CHANGED
|
@@ -117,7 +117,14 @@ export function AddonLoader({ scope, url, module = './register', api, hostRegist
|
|
|
117
117
|
}, [scope, url, module, addonKey, unbindKey, hostRegistry]);
|
|
118
118
|
if (status === 'loading')
|
|
119
119
|
return _jsx(_Fragment, { children: fallback });
|
|
120
|
-
if (status === 'error')
|
|
120
|
+
if (status === 'error') {
|
|
121
|
+
// Hosts that pass `onError` (toast + telemetry) should not also paint
|
|
122
|
+
// a second, persistent inline banner — DynamicAddonLoaders mounts one
|
|
123
|
+
// fiber per installed addon and a visible error stack reads as a broken
|
|
124
|
+
// shell even when only one remote failed transiently.
|
|
125
|
+
if (onError)
|
|
126
|
+
return null;
|
|
121
127
|
return _jsxs("div", { className: "text-sm text-red-500", children: ["Addon load error: ", error?.message] });
|
|
128
|
+
}
|
|
122
129
|
return _jsx(_Fragment, { children: children });
|
|
123
130
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"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"}
|