@asteby/metacore-runtime-react 33.0.0 → 33.1.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 +26 -0
- package/dist/dialogs/create-record-dialog.d.ts +1 -1
- package/dist/dialogs/create-record-dialog.d.ts.map +1 -1
- package/dist/dialogs/create-record-dialog.js +2 -2
- package/dist/dialogs/dynamic-record.d.ts +7 -1
- package/dist/dialogs/dynamic-record.d.ts.map +1 -1
- package/dist/dialogs/dynamic-record.js +32 -5
- package/dist/dialogs/types.d.ts +9 -0
- package/dist/dialogs/types.d.ts.map +1 -1
- package/dist/entity-select.d.ts +14 -1
- package/dist/entity-select.d.ts.map +1 -1
- package/dist/entity-select.js +2 -2
- package/package.json +1 -1
- package/src/dialogs/create-record-dialog.tsx +2 -0
- package/src/dialogs/dynamic-record.tsx +54 -3
- package/src/dialogs/types.ts +9 -0
- package/src/entity-select.tsx +18 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 33.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9eab4e0: `EntitySelect` now accepts `createDefaults` and `lockedCreateFields` to seed
|
|
8
|
+
and lock fields in its inline "+" create dialog. Motivating case: the POS
|
|
9
|
+
vehicle picker creating a vehicle for an already-selected customer — the
|
|
10
|
+
customer field should come pre-filled and not be changeable from that
|
|
11
|
+
context, instead of the user having to search/select it again (and risking
|
|
12
|
+
attaching the vehicle to the wrong customer).
|
|
13
|
+
|
|
14
|
+
- `createDefaults?: Record<string, unknown>` — seeds the create dialog's
|
|
15
|
+
form (passed through as `CreateRecordDialog.defaults`).
|
|
16
|
+
- `lockedCreateFields?: string[]` — keys from `createDefaults` that render
|
|
17
|
+
visible-but-disabled on create instead of editable (passed through as the
|
|
18
|
+
new `CreateRecordDialog.lockedFields` / `DynamicRecordDialog.lockedFields`).
|
|
19
|
+
|
|
20
|
+
New `lockedFields` support in `DynamicRecordDialog`/`CreateRecordDialog`:
|
|
21
|
+
unlike a `readonly` field (excluded entirely on create), a locked field stays
|
|
22
|
+
visible so the user sees what value is being submitted, rendered through the
|
|
23
|
+
same `ReadonlyEditField` used for edit-mode readonly fields. Also fixes
|
|
24
|
+
`ReadonlyEditField` for relation/`Ref` fields (readonly-on-edit and now
|
|
25
|
+
locked-on-create): it previously rendered the raw foreign id, and now
|
|
26
|
+
resolves and shows the related record's label like `RelationViewValue`
|
|
27
|
+
already does in view mode.
|
|
28
|
+
|
|
3
29
|
## 33.0.0
|
|
4
30
|
|
|
5
31
|
### Patch Changes
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { CreateRecordDialogProps } from './types';
|
|
2
|
-
export declare function CreateRecordDialog({ modelKey, open, onOpenChange, recordId, endpoint, schema, defaults, onCreate, onUpdate, onSaved, }: CreateRecordDialogProps): import("react").JSX.Element;
|
|
2
|
+
export declare function CreateRecordDialog({ modelKey, open, onOpenChange, recordId, endpoint, schema, defaults, lockedFields, onCreate, onUpdate, onSaved, }: CreateRecordDialogProps): import("react").JSX.Element;
|
|
3
3
|
//# sourceMappingURL=create-record-dialog.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-record-dialog.d.ts","sourceRoot":"","sources":["../../src/dialogs/create-record-dialog.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAEtD,wBAAgB,kBAAkB,CAAC,EAC/B,QAAQ,EACR,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,QAAQ,EACR,OAAO,GACV,EAAE,uBAAuB,+
|
|
1
|
+
{"version":3,"file":"create-record-dialog.d.ts","sourceRoot":"","sources":["../../src/dialogs/create-record-dialog.tsx"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAEtD,wBAAgB,kBAAkB,CAAC,EAC/B,QAAQ,EACR,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,OAAO,GACV,EAAE,uBAAuB,+BAkBzB"}
|
|
@@ -14,7 +14,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
14
14
|
* with the default `/dynamic/${modelKey}` endpoint convention.
|
|
15
15
|
*/
|
|
16
16
|
import { DynamicRecordDialog } from './dynamic-record';
|
|
17
|
-
export function CreateRecordDialog({ modelKey, open, onOpenChange, recordId, endpoint, schema, defaults, onCreate, onUpdate, onSaved, }) {
|
|
17
|
+
export function CreateRecordDialog({ modelKey, open, onOpenChange, recordId, endpoint, schema, defaults, lockedFields, onCreate, onUpdate, onSaved, }) {
|
|
18
18
|
const mode = recordId ? 'edit' : 'create';
|
|
19
|
-
return (_jsx(DynamicRecordDialog, { open: open, onOpenChange: onOpenChange, mode: mode, model: modelKey, recordId: recordId, endpoint: endpoint, schema: schema, defaults: defaults, onCreate: onCreate, onUpdate: onUpdate, onSaved: onSaved }));
|
|
19
|
+
return (_jsx(DynamicRecordDialog, { open: open, onOpenChange: onOpenChange, mode: mode, model: modelKey, recordId: recordId, endpoint: endpoint, schema: schema, defaults: defaults, lockedFields: lockedFields, onCreate: onCreate, onUpdate: onUpdate, onSaved: onSaved }));
|
|
20
20
|
}
|
|
@@ -122,6 +122,12 @@ export interface DynamicRecordDialogProps {
|
|
|
122
122
|
* `mode` is `'edit'` or `'view'` (those fetch from the record endpoint).
|
|
123
123
|
*/
|
|
124
124
|
defaults?: Record<string, any>;
|
|
125
|
+
/**
|
|
126
|
+
* Field keys that render locked (visible, disabled, seeded from
|
|
127
|
+
* `defaults`) on create instead of editable. Ignored outside create mode.
|
|
128
|
+
* See `CreateRecordDialogProps.lockedFields` for the rationale.
|
|
129
|
+
*/
|
|
130
|
+
lockedFields?: string[];
|
|
125
131
|
/**
|
|
126
132
|
* Optional pre-fetched metadata. When provided the dialog skips the
|
|
127
133
|
* `/metadata/modal/:model` request and uses this shape directly.
|
|
@@ -185,7 +191,7 @@ export declare function fkSeedOption(field: FieldDef, value: any, record: any):
|
|
|
185
191
|
export declare function isMoneyField(field: FieldDef, value: any): boolean;
|
|
186
192
|
export declare function filterVisibleFields(fields: FieldDef[] | undefined, mode: 'view' | 'edit' | 'create', formValues?: Record<string, any>): FieldDef[];
|
|
187
193
|
export declare function stripHiddenFieldValues(values: Record<string, any>, fields: FieldDef[] | undefined, mode: 'view' | 'edit' | 'create'): Record<string, any>;
|
|
188
|
-
export declare function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId, endpoint, onSaved, onCreate, onUpdate, defaults, schema, onDelete, onEdit, onOpenFullPage, initialRecord, getImageUrl, timeZone, currency, onChange, }: DynamicRecordDialogProps): import("react").JSX.Element;
|
|
194
|
+
export declare function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId, endpoint, onSaved, onCreate, onUpdate, defaults, lockedFields, schema, onDelete, onEdit, onOpenFullPage, initialRecord, getImageUrl, timeZone, currency, onChange, }: DynamicRecordDialogProps): import("react").JSX.Element;
|
|
189
195
|
export declare function ReadonlyEditField({ field, value }: {
|
|
190
196
|
field: FieldDef;
|
|
191
197
|
value: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"dynamic-record.d.ts","sourceRoot":"","sources":["../../src/dialogs/dynamic-record.tsx"],"names":[],"mappings":"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"}
|
|
@@ -284,7 +284,7 @@ export function stripHiddenFieldValues(values, fields, mode) {
|
|
|
284
284
|
}
|
|
285
285
|
return out;
|
|
286
286
|
}
|
|
287
|
-
export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId, endpoint, onSaved, onCreate, onUpdate, defaults, schema, onDelete, onEdit, onOpenFullPage, initialRecord, getImageUrl = identityImageUrl, timeZone, currency, onChange, }) {
|
|
287
|
+
export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId, endpoint, onSaved, onCreate, onUpdate, defaults, lockedFields, schema, onDelete, onEdit, onOpenFullPage, initialRecord, getImageUrl = identityImageUrl, timeZone, currency, onChange, }) {
|
|
288
288
|
const api = useApi();
|
|
289
289
|
const { t, i18n } = useTranslation();
|
|
290
290
|
const [modalMeta, setModalMeta] = useState(schema ? schema : null);
|
|
@@ -622,7 +622,7 @@ export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId,
|
|
|
622
622
|
const isFullWidth = field.type === 'textarea' ||
|
|
623
623
|
field.widget === 'textarea' ||
|
|
624
624
|
field.widget === 'richtext';
|
|
625
|
-
return (_jsx(FieldCell, { fullWidth: isFullWidth, children: _jsx(FieldRow, { field: field, record: record, value: formValues[field.key] ?? '', mode: mode, error: fieldErrors[field.key], onChange: val => {
|
|
625
|
+
return (_jsx(FieldCell, { fullWidth: isFullWidth, children: _jsx(FieldRow, { field: field, record: record, value: formValues[field.key] ?? '', mode: mode, locked: isCreate && !!lockedFields?.includes(field.key), error: fieldErrors[field.key], onChange: val => {
|
|
626
626
|
setFormValues((prev) => ({ ...prev, [field.key]: val }));
|
|
627
627
|
setFieldErrors(prev => {
|
|
628
628
|
if (!prev[field.key])
|
|
@@ -655,14 +655,15 @@ export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId,
|
|
|
655
655
|
function LoadingSkeleton() {
|
|
656
656
|
return (_jsx("div", { className: "grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-4", children: Array.from({ length: 6 }).map((_, i) => (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Skeleton, { className: "h-3.5 w-24" }), _jsx(Skeleton, { className: "h-9 w-full" })] }, i))) }));
|
|
657
657
|
}
|
|
658
|
-
function FieldRow({ field, record, value, mode, onChange, error }) {
|
|
658
|
+
function FieldRow({ field, record, value, mode, onChange, error, locked }) {
|
|
659
659
|
// A `readonly` field is server/system-generated (e.g. the GitHub addon's
|
|
660
660
|
// `number`/`github_url`, filled by the API after the outbound create). On
|
|
661
661
|
// CREATE it is excluded from the form entirely (see `visibleFields`); on EDIT
|
|
662
662
|
// it stays visible but is NOT editable — rendered as a disabled, muted input
|
|
663
663
|
// so the user sees its value without being able to change it. View mode keeps
|
|
664
|
-
// the rich read-only renderer.
|
|
665
|
-
|
|
664
|
+
// the rich read-only renderer. `locked` forces the same disabled rendering on
|
|
665
|
+
// CREATE for a caller-specified field (see `lockedFields`).
|
|
666
|
+
const isEditReadonly = (mode === 'edit' && !!field.readonly) || !!locked;
|
|
666
667
|
return (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsxs(Label, { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide", children: [field.label, field.required && mode !== 'view' && !isEditReadonly && (_jsx("span", { className: "text-destructive ml-0.5", children: "*" }))] }), mode === 'view' ? (_jsx(ViewValue, { field: field, value: value, record: record })) : isEditReadonly ? (_jsx(ReadonlyEditField, { field: field, value: value })) : (_jsx(EditField, { field: field, value: value, onChange: onChange, record: record })), error && mode !== 'view' && (_jsx("p", { className: "text-destructive text-xs mt-1", children: error }))] }));
|
|
667
668
|
}
|
|
668
669
|
// ReadonlyEditField — the edit-mode rendering of a `readonly` (system-generated)
|
|
@@ -674,9 +675,35 @@ export function ReadonlyEditField({ field, value }) {
|
|
|
674
675
|
if (field.type === 'boolean' || typeof value === 'boolean') {
|
|
675
676
|
return (_jsxs("div", { className: "flex items-center gap-2 py-1", children: [_jsx(Switch, { checked: !!value, disabled: true }), _jsx("span", { className: "text-sm text-muted-foreground", children: value ? 'Sí' : 'No' })] }));
|
|
676
677
|
}
|
|
678
|
+
const fieldRef = getFieldRef(field);
|
|
679
|
+
if (fieldRef || field.searchEndpoint) {
|
|
680
|
+
return _jsx(ReadonlyRelationField, { field: field, value: value, fieldRef: fieldRef });
|
|
681
|
+
}
|
|
677
682
|
const display = formatDisplayValue(value, field);
|
|
678
683
|
return _jsx(Input, { value: display === '—' ? '' : display, disabled: true, readOnly: true, className: "text-muted-foreground" });
|
|
679
684
|
}
|
|
685
|
+
// ReadonlyRelationField — a locked/readonly FK field (customer_id, category_id…)
|
|
686
|
+
// resolves the record's label instead of showing the raw id, mirroring
|
|
687
|
+
// RelationViewValue's lookup but rendered as a disabled input to match the rest
|
|
688
|
+
// of ReadonlyEditField. Without this, a locked relation field (e.g. `lockedFields`
|
|
689
|
+
// seeding a POS-selected customer into a vehicle create modal) would show a bare
|
|
690
|
+
// UUID — the exact readability bug this dialog otherwise avoids elsewhere.
|
|
691
|
+
function ReadonlyRelationField({ field, value, fieldRef, }) {
|
|
692
|
+
const rawVal = value && typeof value === 'object' ? (value.value ?? value.id) : value;
|
|
693
|
+
const needResolve = fieldRef != null || !!field.searchEndpoint;
|
|
694
|
+
const { options } = useOptionsResolver({
|
|
695
|
+
modelKey: '',
|
|
696
|
+
fieldKey: 'id',
|
|
697
|
+
ref: fieldRef,
|
|
698
|
+
endpoint: fieldRef ? undefined : field.searchEndpoint,
|
|
699
|
+
query: '',
|
|
700
|
+
limit: 50,
|
|
701
|
+
enabled: needResolve && rawVal != null && rawVal !== '',
|
|
702
|
+
});
|
|
703
|
+
const resolved = options.find(o => String(o.id) === String(rawVal));
|
|
704
|
+
const display = resolved?.label ?? (rawVal != null && rawVal !== '' ? String(rawVal) : '');
|
|
705
|
+
return _jsx(Input, { value: display, disabled: true, readOnly: true, className: "text-muted-foreground" });
|
|
706
|
+
}
|
|
680
707
|
// RelationViewValue — read-only FK lead. Resolves the relation's label + image
|
|
681
708
|
// from (1) the sibling object the table served, then (2) the canonical options
|
|
682
709
|
// endpoint, and renders an OptionLead (thumbnail / icon / color dot) + label.
|
package/dist/dialogs/types.d.ts
CHANGED
|
@@ -95,6 +95,15 @@ export interface CreateRecordDialogProps extends RecordDialogProps {
|
|
|
95
95
|
onUpdate?: (recordId: string, data: Record<string, unknown>) => Promise<CreateResult>;
|
|
96
96
|
/** Default values seeded into the form on create. */
|
|
97
97
|
defaults?: Record<string, unknown>;
|
|
98
|
+
/**
|
|
99
|
+
* Field keys that must render locked (visible, disabled, seeded from
|
|
100
|
+
* `defaults`) on create instead of editable — e.g. a parent id the caller
|
|
101
|
+
* already knows and does not want the user to change. Unlike a `readonly`
|
|
102
|
+
* field (which is excluded entirely on create, see `filterVisibleFields`),
|
|
103
|
+
* a locked field stays visible so the user sees what value is being sent.
|
|
104
|
+
* Ignored outside create mode.
|
|
105
|
+
*/
|
|
106
|
+
lockedFields?: string[];
|
|
98
107
|
/** Notification when a create or update succeeds. */
|
|
99
108
|
onSaved?: () => void;
|
|
100
109
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dialogs/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAA;AAE7B;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,KAAK,CAAC;QACX,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,YAAY,CAAC,EAAE,OAAO,CAAA;QACtB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,MAAM,CAAC,EAAE,OAAO,CAAA;QAEhB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;KAC3B,CAAC,CAAA;CACL;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAA;AAEhD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,uEAAuE;IACvE,QAAQ,EAAE,QAAQ,CAAA;IAClB,6BAA6B;IAC7B,IAAI,EAAE,OAAO,CAAA;IACb,6BAA6B;IAC7B,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAC9D,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;IACnE;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;IACrF,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAClC,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC5D,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAA;IAChB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACjC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dialogs/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAA;AAE7B;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IACxB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,KAAK,CAAC;QACX,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,EAAE,MAAM,CAAA;QACb,IAAI,EAAE,MAAM,CAAA;QACZ,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,YAAY,CAAC,EAAE,OAAO,CAAA;QACtB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;QAClB,MAAM,CAAC,EAAE,OAAO,CAAA;QAEhB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAA;KAC3B,CAAC,CAAA;CACL;AAED;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAA;AAEhD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,uEAAuE;IACvE,QAAQ,EAAE,QAAQ,CAAA;IAClB,6BAA6B;IAC7B,IAAI,EAAE,OAAO,CAAA;IACb,6BAA6B;IAC7B,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACrC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB;;;OAGG;IACH,MAAM,CAAC,EAAE,WAAW,CAAA;CACvB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAC9D,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;IACnE;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;IACrF,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAClC;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,EAAE,CAAA;IACvB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAsB,SAAQ,iBAAiB;IAC5D,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAA;IAChB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CACjC"}
|
package/dist/entity-select.d.ts
CHANGED
|
@@ -38,6 +38,19 @@ export interface EntitySelectProps {
|
|
|
38
38
|
labelField?: string;
|
|
39
39
|
/** Disable the whole control. */
|
|
40
40
|
disabled?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Values seeded into the create dialog's form (e.g. a parent id the caller
|
|
43
|
+
* already knows — a POS sale's selected customer, when creating a vehicle
|
|
44
|
+
* from the vehicle picker). Passed through to `CreateRecordDialog.defaults`.
|
|
45
|
+
*/
|
|
46
|
+
createDefaults?: Record<string, unknown>;
|
|
47
|
+
/**
|
|
48
|
+
* Field keys from `createDefaults` that must also render locked (visible,
|
|
49
|
+
* disabled) on create instead of editable — e.g. don't let the user swap
|
|
50
|
+
* the customer while creating their vehicle from this picker. Passed
|
|
51
|
+
* through to `CreateRecordDialog.lockedFields`.
|
|
52
|
+
*/
|
|
53
|
+
lockedCreateFields?: string[];
|
|
41
54
|
}
|
|
42
|
-
export declare function EntitySelect({ model, value, label, onSelect, fetcher, icon: Icon, placeholder, searchPlaceholder, emptyText, preload, canCreate, canEdit, endpoint, labelField, disabled, }: EntitySelectProps): import("react").JSX.Element;
|
|
55
|
+
export declare function EntitySelect({ model, value, label, onSelect, fetcher, icon: Icon, placeholder, searchPlaceholder, emptyText, preload, canCreate, canEdit, endpoint, labelField, disabled, createDefaults, lockedCreateFields, }: EntitySelectProps): import("react").JSX.Element;
|
|
43
56
|
//# sourceMappingURL=entity-select.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entity-select.d.ts","sourceRoot":"","sources":["../src/entity-select.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAA2B,KAAK,UAAU,EAAE,MAAM,cAAc,CAAA;AAiBvE,0EAA0E;AAC1E,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,iBAAiB;IAC9B,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAA;IACb,uCAAuC;IACvC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,kEAAkE;IAClE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,sDAAsD;IACtD,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAC3D,sFAAsF;IACtF,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAA;IAE1E,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"entity-select.d.ts","sourceRoot":"","sources":["../src/entity-select.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAA2B,KAAK,UAAU,EAAE,MAAM,cAAc,CAAA;AAiBvE,0EAA0E;AAC1E,MAAM,WAAW,kBAAkB;IAC/B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,iBAAiB;IAC9B,mEAAmE;IACnE,KAAK,EAAE,MAAM,CAAA;IACb,uCAAuC;IACvC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,kEAAkE;IAClE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,sDAAsD;IACtD,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IAC3D,sFAAsF;IACtF,OAAO,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAA;IAE1E,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;;OAIG;IACH,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,OAAO,CAAC,EAAE,OAAO,CAAA;IAEjB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,iCAAiC;IACjC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACxC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAA;CAChC;AAOD,wBAAgB,YAAY,CAAC,EACzB,KAAK,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,OAAO,EACP,IAAI,EAAE,IAAI,EACV,WAA4B,EAC5B,iBAA6B,EAC7B,SAA4B,EAC5B,OAAe,EACf,SAAS,EACT,OAAO,EACP,QAAQ,EACR,UAAmB,EACnB,QAAgB,EAChB,cAAc,EACd,kBAAkB,GACrB,EAAE,iBAAiB,+BAyNnB"}
|
package/dist/entity-select.js
CHANGED
|
@@ -25,7 +25,7 @@ import { useApi } from './api-context';
|
|
|
25
25
|
function capabilityNamespace(model) {
|
|
26
26
|
return model.replace(/([a-z0-9])([A-Z])/g, '$1_$2').toLowerCase();
|
|
27
27
|
}
|
|
28
|
-
export function EntitySelect({ model, value, label, onSelect, fetcher, icon: Icon, placeholder = 'Seleccionar…', searchPlaceholder = 'Buscar…', emptyText = 'Sin resultados', preload = false, canCreate, canEdit, endpoint, labelField = 'name', disabled = false, }) {
|
|
28
|
+
export function EntitySelect({ model, value, label, onSelect, fetcher, icon: Icon, placeholder = 'Seleccionar…', searchPlaceholder = 'Buscar…', emptyText = 'Sin resultados', preload = false, canCreate, canEdit, endpoint, labelField = 'name', disabled = false, createDefaults, lockedCreateFields, }) {
|
|
29
29
|
const can = useCan();
|
|
30
30
|
const api = useApi();
|
|
31
31
|
const ns = capabilityNamespace(model);
|
|
@@ -110,7 +110,7 @@ export function EntitySelect({ model, value, label, onSelect, fetcher, icon: Ico
|
|
|
110
110
|
searchTerm.length >= minChars &&
|
|
111
111
|
results.length === 0 && _jsx(CommandEmpty, { children: emptyText }), !isLoading && results.length > 0 && (_jsx(CommandGroup, { className: "max-h-64 overflow-auto", children: results.map((row) => (_jsxs(CommandItem, { value: row.value, onSelect: () => pick(row), className: "flex flex-col items-start gap-0.5", children: [_jsx("span", { className: "text-sm font-medium", children: row.label }), row.description && (_jsx("span", { className: "text-muted-foreground text-xs", children: row.description }))] }, row.value))) })), !isLoading && !preload && searchTerm.length < minChars && (_jsxs("div", { className: "text-muted-foreground flex flex-col items-center gap-1 py-6", children: [_jsx(Search, { className: "size-5" }), _jsx("span", { className: "text-xs", children: "Escribe al menos 2 caracteres" })] }))] })] }) })] }), value
|
|
112
112
|
? mayEdit && (_jsx(Button, { type: "button", variant: "outline", size: "icon", disabled: disabled, onClick: openEdit, "aria-label": "Editar", title: "Editar", className: "shrink-0", children: _jsx(Pencil, { className: "size-4" }) }))
|
|
113
|
-
: mayCreate && (_jsx(Button, { type: "button", variant: "outline", size: "icon", disabled: disabled, onClick: openCreate, "aria-label": "Crear", title: "Crear", className: "shrink-0", children: _jsx(Plus, { className: "size-4" }) })), dialogOpen && (_jsx(CreateRecordDialog, { modelKey: model, open: dialogOpen, onOpenChange: setDialogOpen, recordId: dialogRecordId, endpoint: base, onCreate: async (data) => {
|
|
113
|
+
: mayCreate && (_jsx(Button, { type: "button", variant: "outline", size: "icon", disabled: disabled, onClick: openCreate, "aria-label": "Crear", title: "Crear", className: "shrink-0", children: _jsx(Plus, { className: "size-4" }) })), dialogOpen && (_jsx(CreateRecordDialog, { modelKey: model, open: dialogOpen, onOpenChange: setDialogOpen, recordId: dialogRecordId, endpoint: base, defaults: dialogRecordId ? undefined : createDefaults, lockedFields: dialogRecordId ? undefined : lockedCreateFields, onCreate: async (data) => {
|
|
114
114
|
const res = await api.post(base, data);
|
|
115
115
|
const rec = (res.data?.data ?? res.data);
|
|
116
116
|
selectSaved(rec);
|
package/package.json
CHANGED
|
@@ -23,6 +23,7 @@ export function CreateRecordDialog({
|
|
|
23
23
|
endpoint,
|
|
24
24
|
schema,
|
|
25
25
|
defaults,
|
|
26
|
+
lockedFields,
|
|
26
27
|
onCreate,
|
|
27
28
|
onUpdate,
|
|
28
29
|
onSaved,
|
|
@@ -38,6 +39,7 @@ export function CreateRecordDialog({
|
|
|
38
39
|
endpoint={endpoint}
|
|
39
40
|
schema={schema}
|
|
40
41
|
defaults={defaults}
|
|
42
|
+
lockedFields={lockedFields}
|
|
41
43
|
onCreate={onCreate}
|
|
42
44
|
onUpdate={onUpdate}
|
|
43
45
|
onSaved={onSaved}
|
|
@@ -243,6 +243,12 @@ export interface DynamicRecordDialogProps {
|
|
|
243
243
|
* `mode` is `'edit'` or `'view'` (those fetch from the record endpoint).
|
|
244
244
|
*/
|
|
245
245
|
defaults?: Record<string, any>
|
|
246
|
+
/**
|
|
247
|
+
* Field keys that render locked (visible, disabled, seeded from
|
|
248
|
+
* `defaults`) on create instead of editable. Ignored outside create mode.
|
|
249
|
+
* See `CreateRecordDialogProps.lockedFields` for the rationale.
|
|
250
|
+
*/
|
|
251
|
+
lockedFields?: string[]
|
|
246
252
|
/**
|
|
247
253
|
* Optional pre-fetched metadata. When provided the dialog skips the
|
|
248
254
|
* `/metadata/modal/:model` request and uses this shape directly.
|
|
@@ -548,6 +554,7 @@ export function DynamicRecordDialog({
|
|
|
548
554
|
onCreate,
|
|
549
555
|
onUpdate,
|
|
550
556
|
defaults,
|
|
557
|
+
lockedFields,
|
|
551
558
|
schema,
|
|
552
559
|
onDelete,
|
|
553
560
|
onEdit,
|
|
@@ -919,6 +926,7 @@ export function DynamicRecordDialog({
|
|
|
919
926
|
record={record}
|
|
920
927
|
value={formValues[field.key] ?? ''}
|
|
921
928
|
mode={mode}
|
|
929
|
+
locked={isCreate && !!lockedFields?.includes(field.key)}
|
|
922
930
|
error={fieldErrors[field.key]}
|
|
923
931
|
onChange={val => {
|
|
924
932
|
setFormValues((prev: Record<string, any>) => ({ ...prev, [field.key]: val }))
|
|
@@ -1122,16 +1130,24 @@ interface FieldRowProps {
|
|
|
1122
1130
|
onChange: (val: any) => void
|
|
1123
1131
|
/** Localized validation error for this field, shown in red under the input. */
|
|
1124
1132
|
error?: string
|
|
1133
|
+
/**
|
|
1134
|
+
* Caller-forced lock (via `lockedFields`), independent of `field.readonly`.
|
|
1135
|
+
* Renders the same disabled/muted input as an edit-mode readonly field, but
|
|
1136
|
+
* applies on CREATE — where a plain `readonly` field would be excluded
|
|
1137
|
+
* instead. The seeded `value` (from `defaults`) still submits.
|
|
1138
|
+
*/
|
|
1139
|
+
locked?: boolean
|
|
1125
1140
|
}
|
|
1126
1141
|
|
|
1127
|
-
function FieldRow({ field, record, value, mode, onChange, error }: FieldRowProps) {
|
|
1142
|
+
function FieldRow({ field, record, value, mode, onChange, error, locked }: FieldRowProps) {
|
|
1128
1143
|
// A `readonly` field is server/system-generated (e.g. the GitHub addon's
|
|
1129
1144
|
// `number`/`github_url`, filled by the API after the outbound create). On
|
|
1130
1145
|
// CREATE it is excluded from the form entirely (see `visibleFields`); on EDIT
|
|
1131
1146
|
// it stays visible but is NOT editable — rendered as a disabled, muted input
|
|
1132
1147
|
// so the user sees its value without being able to change it. View mode keeps
|
|
1133
|
-
// the rich read-only renderer.
|
|
1134
|
-
|
|
1148
|
+
// the rich read-only renderer. `locked` forces the same disabled rendering on
|
|
1149
|
+
// CREATE for a caller-specified field (see `lockedFields`).
|
|
1150
|
+
const isEditReadonly = (mode === 'edit' && !!field.readonly) || !!locked
|
|
1135
1151
|
|
|
1136
1152
|
return (
|
|
1137
1153
|
<div className="flex flex-col gap-1.5">
|
|
@@ -1171,10 +1187,45 @@ export function ReadonlyEditField({ field, value }: { field: FieldDef; value: an
|
|
|
1171
1187
|
</div>
|
|
1172
1188
|
)
|
|
1173
1189
|
}
|
|
1190
|
+
const fieldRef = getFieldRef(field as ActionFieldDef)
|
|
1191
|
+
if (fieldRef || field.searchEndpoint) {
|
|
1192
|
+
return <ReadonlyRelationField field={field} value={value} fieldRef={fieldRef} />
|
|
1193
|
+
}
|
|
1174
1194
|
const display = formatDisplayValue(value, field)
|
|
1175
1195
|
return <Input value={display === '—' ? '' : display} disabled readOnly className="text-muted-foreground" />
|
|
1176
1196
|
}
|
|
1177
1197
|
|
|
1198
|
+
// ReadonlyRelationField — a locked/readonly FK field (customer_id, category_id…)
|
|
1199
|
+
// resolves the record's label instead of showing the raw id, mirroring
|
|
1200
|
+
// RelationViewValue's lookup but rendered as a disabled input to match the rest
|
|
1201
|
+
// of ReadonlyEditField. Without this, a locked relation field (e.g. `lockedFields`
|
|
1202
|
+
// seeding a POS-selected customer into a vehicle create modal) would show a bare
|
|
1203
|
+
// UUID — the exact readability bug this dialog otherwise avoids elsewhere.
|
|
1204
|
+
function ReadonlyRelationField({
|
|
1205
|
+
field,
|
|
1206
|
+
value,
|
|
1207
|
+
fieldRef,
|
|
1208
|
+
}: {
|
|
1209
|
+
field: FieldDef
|
|
1210
|
+
value: any
|
|
1211
|
+
fieldRef?: string
|
|
1212
|
+
}) {
|
|
1213
|
+
const rawVal = value && typeof value === 'object' ? (value.value ?? value.id) : value
|
|
1214
|
+
const needResolve = fieldRef != null || !!field.searchEndpoint
|
|
1215
|
+
const { options } = useOptionsResolver({
|
|
1216
|
+
modelKey: '',
|
|
1217
|
+
fieldKey: 'id',
|
|
1218
|
+
ref: fieldRef,
|
|
1219
|
+
endpoint: fieldRef ? undefined : field.searchEndpoint,
|
|
1220
|
+
query: '',
|
|
1221
|
+
limit: 50,
|
|
1222
|
+
enabled: needResolve && rawVal != null && rawVal !== '',
|
|
1223
|
+
})
|
|
1224
|
+
const resolved = options.find(o => String(o.id) === String(rawVal))
|
|
1225
|
+
const display = resolved?.label ?? (rawVal != null && rawVal !== '' ? String(rawVal) : '')
|
|
1226
|
+
return <Input value={display} disabled readOnly className="text-muted-foreground" />
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1178
1229
|
// RelationViewValue — read-only FK lead. Resolves the relation's label + image
|
|
1179
1230
|
// from (1) the sibling object the table served, then (2) the canonical options
|
|
1180
1231
|
// endpoint, and renders an OptionLead (thumbnail / icon / color dot) + label.
|
package/src/dialogs/types.ts
CHANGED
|
@@ -99,6 +99,15 @@ export interface CreateRecordDialogProps extends RecordDialogProps {
|
|
|
99
99
|
onUpdate?: (recordId: string, data: Record<string, unknown>) => Promise<CreateResult>
|
|
100
100
|
/** Default values seeded into the form on create. */
|
|
101
101
|
defaults?: Record<string, unknown>
|
|
102
|
+
/**
|
|
103
|
+
* Field keys that must render locked (visible, disabled, seeded from
|
|
104
|
+
* `defaults`) on create instead of editable — e.g. a parent id the caller
|
|
105
|
+
* already knows and does not want the user to change. Unlike a `readonly`
|
|
106
|
+
* field (which is excluded entirely on create, see `filterVisibleFields`),
|
|
107
|
+
* a locked field stays visible so the user sees what value is being sent.
|
|
108
|
+
* Ignored outside create mode.
|
|
109
|
+
*/
|
|
110
|
+
lockedFields?: string[]
|
|
102
111
|
/** Notification when a create or update succeeds. */
|
|
103
112
|
onSaved?: () => void
|
|
104
113
|
}
|
package/src/entity-select.tsx
CHANGED
|
@@ -75,6 +75,20 @@ export interface EntitySelectProps {
|
|
|
75
75
|
labelField?: string
|
|
76
76
|
/** Disable the whole control. */
|
|
77
77
|
disabled?: boolean
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Values seeded into the create dialog's form (e.g. a parent id the caller
|
|
81
|
+
* already knows — a POS sale's selected customer, when creating a vehicle
|
|
82
|
+
* from the vehicle picker). Passed through to `CreateRecordDialog.defaults`.
|
|
83
|
+
*/
|
|
84
|
+
createDefaults?: Record<string, unknown>
|
|
85
|
+
/**
|
|
86
|
+
* Field keys from `createDefaults` that must also render locked (visible,
|
|
87
|
+
* disabled) on create instead of editable — e.g. don't let the user swap
|
|
88
|
+
* the customer while creating their vehicle from this picker. Passed
|
|
89
|
+
* through to `CreateRecordDialog.lockedFields`.
|
|
90
|
+
*/
|
|
91
|
+
lockedCreateFields?: string[]
|
|
78
92
|
}
|
|
79
93
|
|
|
80
94
|
/** Lowercase model → permission capability namespace (Supplier → supplier). */
|
|
@@ -98,6 +112,8 @@ export function EntitySelect({
|
|
|
98
112
|
endpoint,
|
|
99
113
|
labelField = 'name',
|
|
100
114
|
disabled = false,
|
|
115
|
+
createDefaults,
|
|
116
|
+
lockedCreateFields,
|
|
101
117
|
}: EntitySelectProps) {
|
|
102
118
|
const can = useCan()
|
|
103
119
|
const api = useApi()
|
|
@@ -297,6 +313,8 @@ export function EntitySelect({
|
|
|
297
313
|
onOpenChange={setDialogOpen}
|
|
298
314
|
recordId={dialogRecordId}
|
|
299
315
|
endpoint={base}
|
|
316
|
+
defaults={dialogRecordId ? undefined : createDefaults}
|
|
317
|
+
lockedFields={dialogRecordId ? undefined : lockedCreateFields}
|
|
300
318
|
onCreate={async (data) => {
|
|
301
319
|
const res = await api.post(base, data)
|
|
302
320
|
const rec = (res.data?.data ?? res.data) as Record<string, unknown>
|