@asteby/metacore-runtime-react 32.0.0 → 33.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 +16 -0
- package/dist/action-modal-dispatcher.d.ts.map +1 -1
- package/dist/action-modal-dispatcher.js +49 -71
- package/dist/dialogs/dynamic-record.d.ts.map +1 -1
- package/dist/dialogs/dynamic-record.js +27 -28
- package/dist/dynamic-form-schema.d.ts.map +1 -1
- package/dist/dynamic-form-schema.js +2 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/server-error.d.ts +17 -8
- package/dist/server-error.d.ts.map +1 -1
- package/dist/server-error.js +75 -28
- package/dist/types.d.ts +4 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/validation-catalog.d.ts +8 -0
- package/dist/validation-catalog.d.ts.map +1 -0
- package/dist/validation-catalog.js +59 -0
- package/dist/validator.d.ts +22 -0
- package/dist/validator.d.ts.map +1 -0
- package/dist/validator.js +261 -0
- package/package.json +3 -3
- package/src/__tests__/extract-field-errors.test.ts +25 -1
- package/src/__tests__/validator.test.ts +70 -0
- package/src/action-modal-dispatcher.tsx +53 -68
- package/src/dialogs/dynamic-record.tsx +25 -28
- package/src/dynamic-form-schema.ts +3 -2
- package/src/index.ts +13 -0
- package/src/server-error.ts +85 -30
- package/src/types.ts +9 -12
- package/src/validation-catalog.ts +60 -0
- package/src/validator.ts +275 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 33.0.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [e74975a]
|
|
8
|
+
- @asteby/metacore-sdk@3.6.0
|
|
9
|
+
|
|
10
|
+
## 32.1.0
|
|
11
|
+
|
|
12
|
+
### Minor Changes
|
|
13
|
+
|
|
14
|
+
- fa25f99: Laravel-style field validator: localize 422 `{errors:{field:[{code,params}]}}`
|
|
15
|
+
into the operator's language (es/en catalogs, overridable via `validation.*`),
|
|
16
|
+
map keys to translated labels, and pre-flight the same regex/min/max/custom
|
|
17
|
+
rules the kernel enforces — no more generic "validation failed" / `[object Object]`.
|
|
18
|
+
|
|
3
19
|
## 32.0.0
|
|
4
20
|
|
|
5
21
|
### Minor Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"action-modal-dispatcher.d.ts","sourceRoot":"","sources":["../src/action-modal-dispatcher.tsx"],"names":[],"mappings":"
|
|
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"}
|
|
@@ -14,7 +14,9 @@ import { useTranslation } from 'react-i18next';
|
|
|
14
14
|
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Button, Input, Textarea, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Switch, } from '@asteby/metacore-ui/primitives';
|
|
15
15
|
import { Loader2 } from 'lucide-react';
|
|
16
16
|
import { toast } from 'sonner';
|
|
17
|
-
import { toastServerError, toastServerSuccess, extractFieldErrors,
|
|
17
|
+
import { toastServerError, toastServerSuccess, extractFieldErrors, localizeFieldErrorMap } from './server-error';
|
|
18
|
+
import { validateValues, bagHasErrors } from './validator';
|
|
19
|
+
import { validationCatalog } from './validation-catalog';
|
|
18
20
|
import { useApi } from './api-context';
|
|
19
21
|
import { DynamicIcon } from './dynamic-icon';
|
|
20
22
|
import { DynamicLineItems } from './dynamic-line-items';
|
|
@@ -264,34 +266,31 @@ function humanizeKey(k) {
|
|
|
264
266
|
/** Localize a failed action submit's per-field `errors` (422 map or `{errors}`
|
|
265
267
|
* body) into `{ [fieldKey]: localizedMessage }`, using each field's label.
|
|
266
268
|
* Returns undefined when there is no usable per-field map. */
|
|
267
|
-
function localizeActionFieldErrors(err, fields, t) {
|
|
269
|
+
function localizeActionFieldErrors(err, fields, t, language) {
|
|
268
270
|
const map = extractFieldErrors(err);
|
|
269
271
|
if (!map)
|
|
270
272
|
return undefined;
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
for (const [k, issues] of Object.entries(map))
|
|
277
|
-
out[k] = localizeFieldIssue(issues[0], labelFor(k), t);
|
|
278
|
-
return out;
|
|
273
|
+
const labels = {};
|
|
274
|
+
for (const f of fields ?? []) {
|
|
275
|
+
labels[f.key] = f.label ? t(f.label, { defaultValue: f.label }) : humanizeKey(f.key);
|
|
276
|
+
}
|
|
277
|
+
return localizeFieldErrorMap(map, t, { labels, language });
|
|
279
278
|
}
|
|
280
279
|
/** Toast a failed action: a summary + localized per-field lines when the server
|
|
281
280
|
* returned a per-field `errors` map, else the standard cause-carrying toast.
|
|
282
281
|
* Used where inline rendering isn't wired (confirm / multi-step wizard). */
|
|
283
|
-
function toastActionError(err, fields, t) {
|
|
284
|
-
const localized = localizeActionFieldErrors(err, fields, t);
|
|
282
|
+
function toastActionError(err, fields, t, language) {
|
|
283
|
+
const localized = localizeActionFieldErrors(err, fields, t, language);
|
|
285
284
|
if (localized) {
|
|
286
|
-
toast.error(t('
|
|
285
|
+
toast.error(t('validation.failed', { defaultValue: validationCatalog(language).failed }), {
|
|
287
286
|
description: Object.values(localized).join('\n'),
|
|
288
287
|
});
|
|
289
288
|
return;
|
|
290
289
|
}
|
|
291
|
-
toastServerError(err, { t });
|
|
290
|
+
toastServerError(err, { t, language });
|
|
292
291
|
}
|
|
293
292
|
function ConfirmActionDialog({ open, onOpenChange, action, model, record, endpoint, onSuccess }) {
|
|
294
|
-
const { t } = useTranslation();
|
|
293
|
+
const { t, i18n } = useTranslation();
|
|
295
294
|
const api = useApi();
|
|
296
295
|
const [executing, setExecuting] = useState(false);
|
|
297
296
|
// `action.label` is an addon-contributed i18n key; its locale bundle loads
|
|
@@ -309,11 +308,11 @@ function ConfirmActionDialog({ open, onOpenChange, action, model, record, endpoi
|
|
|
309
308
|
onSuccess();
|
|
310
309
|
}
|
|
311
310
|
else {
|
|
312
|
-
toastActionError({ response: { data: res.data } }, action.fields, t);
|
|
311
|
+
toastActionError({ response: { data: res.data } }, action.fields, t, i18n.language);
|
|
313
312
|
}
|
|
314
313
|
}
|
|
315
314
|
catch (err) {
|
|
316
|
-
toastActionError(err, action.fields, t);
|
|
315
|
+
toastActionError(err, action.fields, t, i18n.language);
|
|
317
316
|
}
|
|
318
317
|
finally {
|
|
319
318
|
setExecuting(false);
|
|
@@ -322,7 +321,7 @@ function ConfirmActionDialog({ open, onOpenChange, action, model, record, endpoi
|
|
|
322
321
|
return (_jsx(AlertDialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsxs(AlertDialogTitle, { className: "flex items-center gap-2", children: [_jsx(DynamicIcon, { name: action.icon, className: "h-5 w-5" }), label] }), _jsx(AlertDialogDescription, { children: action.confirmMessage || `${label}?` })] }), record ? _jsx(RecordPreview, { model: model, record: record }) : null, _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: executing, children: t('common.cancel') }), _jsxs(AlertDialogAction, { onClick: (e) => { e.preventDefault(); execute(); }, disabled: executing, style: action.color ? { backgroundColor: action.color } : 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" }), label] })] })] }) }));
|
|
323
322
|
}
|
|
324
323
|
function GenericActionModal({ open, onOpenChange, action, model, record, endpoint, onSuccess }) {
|
|
325
|
-
const { t } = useTranslation();
|
|
324
|
+
const { t, i18n } = useTranslation();
|
|
326
325
|
// Addon-contributed labels (action + fields) are i18n keys whose locale
|
|
327
326
|
// bundle loads asynchronously; translate at render so they don't render raw.
|
|
328
327
|
// defaultValue keeps an already-localized string unchanged.
|
|
@@ -389,39 +388,25 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
|
|
|
389
388
|
return next;
|
|
390
389
|
});
|
|
391
390
|
};
|
|
391
|
+
const lang = i18n.language;
|
|
392
392
|
const handleActionError = (err) => {
|
|
393
|
-
const localized = localizeActionFieldErrors(err, action.fields, t);
|
|
393
|
+
const localized = localizeActionFieldErrors(err, action.fields, t, lang);
|
|
394
394
|
if (localized) {
|
|
395
395
|
setFieldErrors(localized);
|
|
396
|
-
toast.error(t('
|
|
396
|
+
toast.error(t('validation.failed', { defaultValue: validationCatalog(lang).failed }));
|
|
397
397
|
return;
|
|
398
398
|
}
|
|
399
|
-
toastServerError(err, { t });
|
|
399
|
+
toastServerError(err, { t, language: lang });
|
|
400
400
|
};
|
|
401
401
|
const execute = async () => {
|
|
402
402
|
if (action.fields) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
if (!Array.isArray(rows) || rows.length === 0) {
|
|
411
|
-
missing[field.key] = t('validation.line_items_required', {
|
|
412
|
-
defaultValue: '{{label}} requiere al menos un renglón',
|
|
413
|
-
label: tl(field.label),
|
|
414
|
-
});
|
|
415
|
-
}
|
|
416
|
-
continue;
|
|
417
|
-
}
|
|
418
|
-
if (!formData[field.key] && formData[field.key] !== false) {
|
|
419
|
-
missing[field.key] = localizeFieldIssue({ code: 'required' }, tl(field.label), t);
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
if (Object.keys(missing).length) {
|
|
423
|
-
setFieldErrors(missing);
|
|
424
|
-
toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }));
|
|
403
|
+
const bag = validateValues(action.fields, formData);
|
|
404
|
+
if (bagHasErrors(bag)) {
|
|
405
|
+
const labels = {};
|
|
406
|
+
for (const f of action.fields)
|
|
407
|
+
labels[f.key] = tl(f.label);
|
|
408
|
+
setFieldErrors(localizeFieldErrorMap(bag, t, { labels, language: lang }));
|
|
409
|
+
toast.error(t('validation.failed', { defaultValue: validationCatalog(lang).failed }));
|
|
425
410
|
return;
|
|
426
411
|
}
|
|
427
412
|
}
|
|
@@ -486,25 +471,14 @@ function buildFieldDefaults(fields, record) {
|
|
|
486
471
|
}
|
|
487
472
|
return defaults;
|
|
488
473
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
const rows = formData[field.key];
|
|
498
|
-
if (!Array.isArray(rows) || rows.length === 0) {
|
|
499
|
-
return `${tl(field.label)} requiere al menos un renglón`;
|
|
500
|
-
}
|
|
501
|
-
continue;
|
|
502
|
-
}
|
|
503
|
-
if (!formData[field.key] && formData[field.key] !== false) {
|
|
504
|
-
return `${tl(field.label)} es requerido`;
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
return null;
|
|
474
|
+
function wizardStepErrors(fields, formData, t, language) {
|
|
475
|
+
const bag = validateValues(fields, formData);
|
|
476
|
+
if (!bagHasErrors(bag))
|
|
477
|
+
return undefined;
|
|
478
|
+
const labels = {};
|
|
479
|
+
for (const f of fields)
|
|
480
|
+
labels[f.key] = t(f.label, { defaultValue: f.label });
|
|
481
|
+
return localizeFieldErrorMap(bag, t, { labels, language });
|
|
508
482
|
}
|
|
509
483
|
// WizardActionModal — the third render-path: a multi-step form. It accumulates
|
|
510
484
|
// every step's fields into ONE formData object and, on the final step, POSTs all
|
|
@@ -514,7 +488,7 @@ function validateFields(fields, formData, tl) {
|
|
|
514
488
|
// so line-items, dynamic_select, uploads and dates behave identically to a
|
|
515
489
|
// single-page action form — no widget is duplicated.
|
|
516
490
|
function WizardActionModal({ open, onOpenChange, action, model, record, endpoint, onSuccess }) {
|
|
517
|
-
const { t } = useTranslation();
|
|
491
|
+
const { t, i18n } = useTranslation();
|
|
518
492
|
const tl = (s) => t(s, { defaultValue: s });
|
|
519
493
|
const api = useApi();
|
|
520
494
|
const steps = action.steps ?? [];
|
|
@@ -537,9 +511,11 @@ function WizardActionModal({ open, onOpenChange, action, model, record, endpoint
|
|
|
537
511
|
const hasLineItems = useMemo(() => stepFields.some(isLineItemsField), [stepFields]);
|
|
538
512
|
const widthPx = hasLineItems ? '820px' : undefined;
|
|
539
513
|
const goNext = () => {
|
|
540
|
-
const
|
|
541
|
-
if (
|
|
542
|
-
toast.error(
|
|
514
|
+
const localized = wizardStepErrors(stepFields, formData, t, i18n.language);
|
|
515
|
+
if (localized) {
|
|
516
|
+
toast.error(t('validation.failed', { defaultValue: validationCatalog(i18n.language).failed }), {
|
|
517
|
+
description: Object.values(localized).join('\n'),
|
|
518
|
+
});
|
|
543
519
|
return;
|
|
544
520
|
}
|
|
545
521
|
setStepIndex((i) => Math.min(i + 1, steps.length - 1));
|
|
@@ -549,9 +525,11 @@ function WizardActionModal({ open, onOpenChange, action, model, record, endpoint
|
|
|
549
525
|
// Guard every step's required fields on final submit (a user could reach
|
|
550
526
|
// the last step with an untouched earlier line-items grid otherwise).
|
|
551
527
|
for (const s of steps) {
|
|
552
|
-
const
|
|
553
|
-
if (
|
|
554
|
-
toast.error(
|
|
528
|
+
const localized = wizardStepErrors(s.fields ?? [], formData, t, i18n.language);
|
|
529
|
+
if (localized) {
|
|
530
|
+
toast.error(t('validation.failed', { defaultValue: validationCatalog(i18n.language).failed }), {
|
|
531
|
+
description: Object.values(localized).join('\n'),
|
|
532
|
+
});
|
|
555
533
|
return;
|
|
556
534
|
}
|
|
557
535
|
}
|
|
@@ -565,11 +543,11 @@ function WizardActionModal({ open, onOpenChange, action, model, record, endpoint
|
|
|
565
543
|
onSuccess();
|
|
566
544
|
}
|
|
567
545
|
else {
|
|
568
|
-
toastActionError({ response: { data: res.data } }, steps.flatMap(s => s.fields ?? []), t);
|
|
546
|
+
toastActionError({ response: { data: res.data } }, steps.flatMap(s => s.fields ?? []), t, i18n.language);
|
|
569
547
|
}
|
|
570
548
|
}
|
|
571
549
|
catch (err) {
|
|
572
|
-
toastActionError(err, steps.flatMap(s => s.fields ?? []), t);
|
|
550
|
+
toastActionError(err, steps.flatMap(s => s.fields ?? []), t, i18n.language);
|
|
573
551
|
}
|
|
574
552
|
finally {
|
|
575
553
|
setExecuting(false);
|
|
@@ -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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"}
|
|
@@ -23,7 +23,9 @@ import { es } from 'date-fns/locale';
|
|
|
23
23
|
import { ExternalLink, Loader2, CalendarIcon, ChevronDown, Check, Upload, X as XIcon, ScanLine } from 'lucide-react';
|
|
24
24
|
import { BarcodeScanner } from '../barcode-scanner';
|
|
25
25
|
import { useApi } from '../api-context';
|
|
26
|
-
import { toastServerError, extractFieldErrors,
|
|
26
|
+
import { toastServerError, extractFieldErrors, localizeFieldErrorMap } from '../server-error';
|
|
27
|
+
import { validateValues, bagHasErrors } from '../validator';
|
|
28
|
+
import { validationCatalog } from '../validation-catalog';
|
|
27
29
|
import { DynamicSelectField, OptionLead, OptionThumb } from '../dynamic-select-field';
|
|
28
30
|
import { DynamicRelations } from '../dynamic-relations';
|
|
29
31
|
import { useOptionsResolver } from '../use-options-resolver';
|
|
@@ -284,7 +286,7 @@ export function stripHiddenFieldValues(values, fields, mode) {
|
|
|
284
286
|
}
|
|
285
287
|
export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId, endpoint, onSaved, onCreate, onUpdate, defaults, schema, onDelete, onEdit, onOpenFullPage, initialRecord, getImageUrl = identityImageUrl, timeZone, currency, onChange, }) {
|
|
286
288
|
const api = useApi();
|
|
287
|
-
const { t } = useTranslation();
|
|
289
|
+
const { t, i18n } = useTranslation();
|
|
288
290
|
const [modalMeta, setModalMeta] = useState(schema ? schema : null);
|
|
289
291
|
const [relations, setRelations] = useState([]);
|
|
290
292
|
const [record, setRecord] = useState(null);
|
|
@@ -478,24 +480,24 @@ export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId,
|
|
|
478
480
|
const labelForKey = (key) => {
|
|
479
481
|
const f = (modalMeta?.fields ?? []).find(x => x.key === key);
|
|
480
482
|
if (f?.label)
|
|
481
|
-
return f.label;
|
|
483
|
+
return t(f.label, { defaultValue: f.label });
|
|
482
484
|
return key.replace(/[._-]+/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
|
|
483
485
|
};
|
|
486
|
+
const lang = i18n.language;
|
|
484
487
|
// Turn a failed submit (422 `errors` map, or a bare `{errors}` body) into
|
|
485
488
|
// inline field errors + a summary toast. When there is no field map, fall
|
|
486
489
|
// back to the existing single cause-carrying toast.
|
|
487
490
|
const handleSubmitError = (err) => {
|
|
488
491
|
const map = extractFieldErrors(err);
|
|
489
492
|
if (map) {
|
|
490
|
-
const
|
|
491
|
-
for (const
|
|
492
|
-
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }));
|
|
493
|
+
const labels = {};
|
|
494
|
+
for (const f of modalMeta?.fields ?? [])
|
|
495
|
+
labels[f.key] = labelForKey(f.key);
|
|
496
|
+
setFieldErrors(localizeFieldErrorMap(map, t, { labels, language: lang }));
|
|
497
|
+
toast.error(t('validation.failed', { defaultValue: validationCatalog(lang).failed }));
|
|
496
498
|
return;
|
|
497
499
|
}
|
|
498
|
-
toastServerError(err, { t, fallback: t('dynamic.save_error', { defaultValue: 'No se pudo guardar' }) });
|
|
500
|
+
toastServerError(err, { t, language: lang, fallback: t('dynamic.save_error', { defaultValue: 'No se pudo guardar' }) });
|
|
499
501
|
};
|
|
500
502
|
const handleSubmit = async (e) => {
|
|
501
503
|
e?.preventDefault();
|
|
@@ -507,15 +509,14 @@ export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId,
|
|
|
507
509
|
// fields are gated: a field hidden by its `visible_when` predicate
|
|
508
510
|
// must not block submit even when it is declared required (matching
|
|
509
511
|
// the render, which drops it via the same filter).
|
|
510
|
-
const
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }));
|
|
512
|
+
const visible = filterVisibleFields(modalMeta.fields, mode, formValues);
|
|
513
|
+
const bag = validateValues(visible, formValues);
|
|
514
|
+
if (bagHasErrors(bag)) {
|
|
515
|
+
const labels = {};
|
|
516
|
+
for (const f of visible)
|
|
517
|
+
labels[f.key] = t(f.label, { defaultValue: f.label });
|
|
518
|
+
setFieldErrors(localizeFieldErrorMap(bag, t, { labels, language: lang }));
|
|
519
|
+
toast.error(t('validation.failed', { defaultValue: validationCatalog(lang).failed }));
|
|
519
520
|
return;
|
|
520
521
|
}
|
|
521
522
|
}
|
|
@@ -636,15 +637,13 @@ export function DynamicRecordDialog({ open, onOpenChange, mode, model, recordId,
|
|
|
636
637
|
// then advance. Mirrors handleSubmit's required check but scoped to the step.
|
|
637
638
|
const goNextStep = () => {
|
|
638
639
|
const step = groups[clampedStep];
|
|
639
|
-
const
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
setFieldErrors(missing);
|
|
647
|
-
toast.error(t('dynamic.validation_failed', { defaultValue: 'Revisa los campos marcados' }));
|
|
640
|
+
const bag = validateValues((step?.fields ?? []), formValues);
|
|
641
|
+
if (bagHasErrors(bag)) {
|
|
642
|
+
const labels = {};
|
|
643
|
+
for (const f of step?.fields ?? [])
|
|
644
|
+
labels[f.key] = t(f.label, { defaultValue: f.label });
|
|
645
|
+
setFieldErrors(localizeFieldErrorMap(bag, t, { labels, language: lang }));
|
|
646
|
+
toast.error(t('validation.failed', { defaultValue: validationCatalog(lang).failed }));
|
|
648
647
|
return;
|
|
649
648
|
}
|
|
650
649
|
setFieldErrors({});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-form-schema.d.ts","sourceRoot":"","sources":["../src/dynamic-form-schema.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,CAAC,EAAmB,MAAM,KAAK,CAAA;AACxC,OAAO,KAAK,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"dynamic-form-schema.d.ts","sourceRoot":"","sources":["../src/dynamic-form-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// callers (and unit tests) can use the zod schema without pulling in React or
|
|
3
3
|
// metacore-ui primitives.
|
|
4
4
|
import { z } from 'zod';
|
|
5
|
+
import { fieldValidationOf } from './validator';
|
|
5
6
|
import { resolveValidatorToken } from './use-org-config-bridge';
|
|
6
7
|
/**
|
|
7
8
|
* Built-in validators the SDK knows how to apply by symbolic name. Apps
|
|
@@ -143,7 +144,7 @@ function fieldToZod(field) {
|
|
|
143
144
|
const arr = z.array(row);
|
|
144
145
|
return field.required ? arr.min(1, `${field.label} requiere al menos un renglón`) : arr;
|
|
145
146
|
}
|
|
146
|
-
const v = field
|
|
147
|
+
const v = fieldValidationOf(field);
|
|
147
148
|
const isNumeric = field.type === 'number';
|
|
148
149
|
const isBool = field.type === 'boolean';
|
|
149
150
|
if (isBool) {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export * from './types';
|
|
2
2
|
export { LicenseGate, LicenseExpiryBanner, LicenseStatusBadge, isLicenseOperable, isLicenseBlocking, isPresetEntitled, isTrialExpired, type LicenseGateProps, type LicenseExpiryBannerProps, type LicenseStatusBadgeProps, type LicenseState, type LicenseStatus, type LicenseBranding, } from './license';
|
|
3
3
|
export * from './options-context';
|
|
4
|
-
export { extractServerError, toastServerError, toastServerSuccess, type ExtractedError, type Translate, } from './server-error';
|
|
4
|
+
export { extractServerError, extractFieldErrors, localizeFieldIssue, localizeFieldErrorMap, toastServerError, toastServerSuccess, type ExtractedError, type Translate, type FieldIssue, } from './server-error';
|
|
5
|
+
export { parseRuleString, fieldValidationOf, checkValue, validateValues, bagHasErrors, type ValidationSpec, } from './validator';
|
|
6
|
+
export { VALIDATION_CATALOGS, validationCatalog, validationMessageKey } from './validation-catalog';
|
|
5
7
|
export * from './dynamic-table';
|
|
6
8
|
export { DynamicKanban, type DynamicKanbanProps, deriveStages, groupByStage, isTransitionAllowed, applyOptimisticMove, selectCardColumns, UNASSIGNED_LANE, } from './dynamic-kanban';
|
|
7
9
|
export { useStageAutomations, StageAutomationsButton, isTagColumn, automationFieldOptions, groupAutomationsByStage, activeAutomationCount, type StageAutomation, type StageAutomationAction, type StageAutomationActionType, type NewStageAutomation, type UseStageAutomationsResult, type StageAutomationsButtonProps, } from './stage-automations';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,SAAS,CAAA;AACvB,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,eAAe,GACvB,MAAM,WAAW,CAAA;AAClB,cAAc,mBAAmB,CAAA;AACjC,OAAO,EACH,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
export * from './types';
|
|
7
7
|
export { LicenseGate, LicenseExpiryBanner, LicenseStatusBadge, isLicenseOperable, isLicenseBlocking, isPresetEntitled, isTrialExpired, } from './license';
|
|
8
8
|
export * from './options-context';
|
|
9
|
-
export { extractServerError, toastServerError, toastServerSuccess, } from './server-error';
|
|
9
|
+
export { extractServerError, extractFieldErrors, localizeFieldIssue, localizeFieldErrorMap, toastServerError, toastServerSuccess, } from './server-error';
|
|
10
|
+
export { parseRuleString, fieldValidationOf, checkValue, validateValues, bagHasErrors, } from './validator';
|
|
11
|
+
export { VALIDATION_CATALOGS, validationCatalog, validationMessageKey } from './validation-catalog';
|
|
10
12
|
export * from './dynamic-table';
|
|
11
13
|
export { DynamicKanban, deriveStages, groupByStage, isTransitionAllowed, applyOptimisticMove, selectCardColumns, UNASSIGNED_LANE, } from './dynamic-kanban';
|
|
12
14
|
export { useStageAutomations, StageAutomationsButton, isTagColumn, automationFieldOptions, groupAutomationsByStage, activeAutomationCount, } from './stage-automations';
|
package/dist/server-error.d.ts
CHANGED
|
@@ -41,12 +41,18 @@ export interface FieldIssue {
|
|
|
41
41
|
*/
|
|
42
42
|
export declare function extractFieldErrors(err: unknown): Record<string, FieldIssue[]> | undefined;
|
|
43
43
|
/**
|
|
44
|
-
* Localize a single `FieldIssue` to a human
|
|
45
|
-
*
|
|
46
|
-
* `code` is translated via `t('validation.'+
|
|
47
|
-
*
|
|
44
|
+
* Localize a single `FieldIssue` to a human string using the field `label` and
|
|
45
|
+
* the operator's language. A pre-localized `message` passes through verbatim.
|
|
46
|
+
* Otherwise `code` is translated via `t('validation.'+key)` with a catalog
|
|
47
|
+
* default (es unless `language` is `en` / `en-*`).
|
|
48
48
|
*/
|
|
49
|
-
export declare function localizeFieldIssue(issue: FieldIssue, label: string, t: Translate): string;
|
|
49
|
+
export declare function localizeFieldIssue(issue: FieldIssue, label: string, t: Translate, language?: string): string;
|
|
50
|
+
/** Localize a whole 422 `errors` map into `{ [field]: firstMessage }` using
|
|
51
|
+
* optional per-key labels (already translated) and the current language. */
|
|
52
|
+
export declare function localizeFieldErrorMap(map: Record<string, FieldIssue[]>, t: Translate, opts?: {
|
|
53
|
+
labels?: Record<string, string>;
|
|
54
|
+
language?: string;
|
|
55
|
+
}): Record<string, string>;
|
|
50
56
|
/**
|
|
51
57
|
* Toast a successful mutation/action response, LOCALIZED. The kernel/host often
|
|
52
58
|
* returns a hardcoded English `message` ("Record created successfully"); echoing
|
|
@@ -61,12 +67,15 @@ export declare function toastServerSuccess(data: unknown, opts?: {
|
|
|
61
67
|
}): void;
|
|
62
68
|
/**
|
|
63
69
|
* Toast a server/network error, surfacing the REAL cause as the description
|
|
64
|
-
* instead of a bare generic line.
|
|
65
|
-
*
|
|
66
|
-
*
|
|
70
|
+
* instead of a bare generic line. A 422 `{errors:{field:[{code}]}}` bag is
|
|
71
|
+
* localized per-field (never `[object Object]` / English "validation failed").
|
|
72
|
+
* Pass `language` (i18n.language) so catalogs match the operator's lang;
|
|
73
|
+
* pass `labels` so field keys map to translated headers.
|
|
67
74
|
*/
|
|
68
75
|
export declare function toastServerError(err: unknown, opts?: {
|
|
69
76
|
t?: Translate;
|
|
70
77
|
fallback?: string;
|
|
78
|
+
language?: string;
|
|
79
|
+
labels?: Record<string, string>;
|
|
71
80
|
}): void;
|
|
72
81
|
//# sourceMappingURL=server-error.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-error.d.ts","sourceRoot":"","sources":["../src/server-error.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server-error.d.ts","sourceRoot":"","sources":["../src/server-error.ts"],"names":[],"mappings":"AAcA,kFAAkF;AAClF,MAAM,WAAW,cAAc;IAC3B,gFAAgF;IAChF,KAAK,EAAE,MAAM,CAAA;IACb;;gDAE4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAA;CACvB;AA8BD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,GAAG,cAAc,CAuBtF;AAED;;gFAEgF;AAChF,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,KAAK,MAAM,CAAA;AAUvG;8EAC8E;AAC9E,MAAM,WAAW,UAAU;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAA;CACnB;AA6BD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,GAAG,SAAS,CAazF;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,MAAM,EACb,CAAC,EAAE,SAAS,EACZ,QAAQ,CAAC,EAAE,MAAM,GAClB,MAAM,CAMR;AAED;6EAC6E;AAC7E,wBAAgB,qBAAqB,CACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,CAAC,EACjC,CAAC,EAAE,SAAS,EACZ,IAAI,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAC9D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAOxB;AAUD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAC9B,IAAI,EAAE,OAAO,EACb,IAAI,CAAC,EAAE;IAAE,CAAC,CAAC,EAAE,SAAS,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAC/C,IAAI,CAUN;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC5B,GAAG,EAAE,OAAO,EACZ,IAAI,CAAC,EAAE;IAAE,CAAC,CAAC,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,GAChG,IAAI,CA4BN"}
|