@asteby/metacore-runtime-react 23.6.0 → 23.7.1
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 +25 -0
- package/dist/action-modal-dispatcher.js +19 -10
- package/dist/custom-stages.d.ts +171 -0
- package/dist/custom-stages.d.ts.map +1 -0
- package/dist/custom-stages.js +535 -0
- package/dist/dialogs/dynamic-record.d.ts.map +1 -1
- package/dist/dialogs/dynamic-record.js +7 -4
- package/dist/dynamic-kanban.d.ts.map +1 -1
- package/dist/dynamic-kanban.js +77 -32
- package/dist/field-grid.d.ts +17 -0
- package/dist/field-grid.d.ts.map +1 -0
- package/dist/field-grid.js +12 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/model-action-toolbar.d.ts.map +1 -1
- package/dist/model-action-toolbar.js +3 -1
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/action-modal-grid-layout.test.tsx +86 -0
- package/src/__tests__/custom-stages.test.tsx +480 -0
- package/src/__tests__/model-action-toolbar-i18n.test.tsx +101 -0
- package/src/action-modal-dispatcher.tsx +44 -37
- package/src/custom-stages.tsx +1113 -0
- package/src/dialogs/dynamic-record.tsx +14 -8
- package/src/dynamic-kanban.tsx +153 -5
- package/src/field-grid.tsx +57 -0
- package/src/index.ts +25 -0
- package/src/model-action-toolbar.tsx +9 -1
- package/src/types.ts +26 -0
|
@@ -26,7 +26,6 @@ import {
|
|
|
26
26
|
Button,
|
|
27
27
|
Input,
|
|
28
28
|
Textarea,
|
|
29
|
-
Label,
|
|
30
29
|
Select,
|
|
31
30
|
SelectContent,
|
|
32
31
|
SelectItem,
|
|
@@ -44,6 +43,7 @@ import { DynamicSelectField } from './dynamic-select-field'
|
|
|
44
43
|
import { DynamicDateField } from './dynamic-date-field'
|
|
45
44
|
import { UploadField } from './upload-field'
|
|
46
45
|
import { isLineItemsField, resolveWidget, resolveDependsValue, getDependsOn } from './dynamic-form-schema'
|
|
46
|
+
import { FieldGrid, FieldCell, FieldLabel } from './field-grid'
|
|
47
47
|
import type { ActionFieldDef } from './types'
|
|
48
48
|
// Canonical registry lives in @asteby/metacore-sdk
|
|
49
49
|
import {
|
|
@@ -218,6 +218,10 @@ function ConfirmActionDialog({ open, onOpenChange, action, model, record, endpoi
|
|
|
218
218
|
const { t } = useTranslation()
|
|
219
219
|
const api = useApi()
|
|
220
220
|
const [executing, setExecuting] = useState(false)
|
|
221
|
+
// `action.label` is an addon-contributed i18n key; its locale bundle loads
|
|
222
|
+
// asynchronously, so translate at render (defaultValue keeps an already
|
|
223
|
+
// localized label unchanged).
|
|
224
|
+
const label = t(action.label, { defaultValue: action.label })
|
|
221
225
|
|
|
222
226
|
const execute = async () => {
|
|
223
227
|
setExecuting(true)
|
|
@@ -244,10 +248,10 @@ function ConfirmActionDialog({ open, onOpenChange, action, model, record, endpoi
|
|
|
244
248
|
<AlertDialogHeader>
|
|
245
249
|
<AlertDialogTitle className="flex items-center gap-2">
|
|
246
250
|
<DynamicIcon name={action.icon} className="h-5 w-5" />
|
|
247
|
-
{
|
|
251
|
+
{label}
|
|
248
252
|
</AlertDialogTitle>
|
|
249
253
|
<AlertDialogDescription>
|
|
250
|
-
{action.confirmMessage || `${
|
|
254
|
+
{action.confirmMessage || `${label}?`}
|
|
251
255
|
</AlertDialogDescription>
|
|
252
256
|
</AlertDialogHeader>
|
|
253
257
|
<AlertDialogFooter>
|
|
@@ -258,7 +262,7 @@ function ConfirmActionDialog({ open, onOpenChange, action, model, record, endpoi
|
|
|
258
262
|
style={action.color ? { backgroundColor: action.color } : undefined}
|
|
259
263
|
>
|
|
260
264
|
{executing ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <DynamicIcon name={action.icon} className="mr-2 h-4 w-4" />}
|
|
261
|
-
{
|
|
265
|
+
{label}
|
|
262
266
|
</AlertDialogAction>
|
|
263
267
|
</AlertDialogFooter>
|
|
264
268
|
</AlertDialogContent>
|
|
@@ -268,6 +272,10 @@ function ConfirmActionDialog({ open, onOpenChange, action, model, record, endpoi
|
|
|
268
272
|
|
|
269
273
|
function GenericActionModal({ open, onOpenChange, action, model, record, endpoint, onSuccess }: ActionModalProps) {
|
|
270
274
|
const { t } = useTranslation()
|
|
275
|
+
// Addon-contributed labels (action + fields) are i18n keys whose locale
|
|
276
|
+
// bundle loads asynchronously; translate at render so they don't render raw.
|
|
277
|
+
// defaultValue keeps an already-localized string unchanged.
|
|
278
|
+
const tl = (s: string) => t(s, { defaultValue: s })
|
|
271
279
|
const api = useApi()
|
|
272
280
|
const [formData, setFormData] = useState<Record<string, any>>({})
|
|
273
281
|
const [executing, setExecuting] = useState(false)
|
|
@@ -326,13 +334,13 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
|
|
|
326
334
|
if (isLineItemsField(field)) {
|
|
327
335
|
const rows = formData[field.key]
|
|
328
336
|
if (!Array.isArray(rows) || rows.length === 0) {
|
|
329
|
-
toast.error(`${field.label} requiere al menos un renglón`)
|
|
337
|
+
toast.error(`${tl(field.label)} requiere al menos un renglón`)
|
|
330
338
|
return
|
|
331
339
|
}
|
|
332
340
|
continue
|
|
333
341
|
}
|
|
334
342
|
if (!formData[field.key] && formData[field.key] !== false) {
|
|
335
|
-
toast.error(`${field.label} es requerido`)
|
|
343
|
+
toast.error(`${tl(field.label)} es requerido`)
|
|
336
344
|
return
|
|
337
345
|
}
|
|
338
346
|
}
|
|
@@ -383,44 +391,43 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
|
|
|
383
391
|
is inline (guaranteed) since an arbitrary max-h-[90vh] class may be
|
|
384
392
|
dropped by a consuming app's Tailwind scan. */}
|
|
385
393
|
<DialogContent
|
|
386
|
-
className={'flex max-h-[90vh] flex-col overflow-hidden ' + (widthPx ? '' : 'sm:max-w-
|
|
394
|
+
className={'flex max-h-[90vh] flex-col overflow-hidden ' + (widthPx ? '' : 'sm:max-w-xl')}
|
|
387
395
|
style={{ maxHeight: '90vh', ...(widthPx ? { maxWidth: widthPx, width: '95vw' } : {}) }}
|
|
388
396
|
>
|
|
389
397
|
<DialogHeader className="shrink-0">
|
|
390
398
|
<DialogTitle className="flex items-center gap-2">
|
|
391
399
|
<DynamicIcon name={action.icon} className="h-5 w-5" />
|
|
392
|
-
{action.label}
|
|
400
|
+
{tl(action.label)}
|
|
393
401
|
</DialogTitle>
|
|
394
402
|
{action.confirmMessage && <DialogDescription>{action.confirmMessage}</DialogDescription>}
|
|
395
403
|
</DialogHeader>
|
|
396
|
-
{/* Scrollable body.
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
{field.
|
|
414
|
-
</
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
)}
|
|
404
|
+
{/* Scrollable body. The shared FieldGrid lays scalar fields out
|
|
405
|
+
in two responsive columns (single column on phones); line-items
|
|
406
|
+
grids and textareas span the full width. `min-w-0` on each cell
|
|
407
|
+
(in FieldCell) keeps a long select/input value from blowing the
|
|
408
|
+
grid past the dialog and spawning a horizontal scrollbar. */}
|
|
409
|
+
<div className="-mx-1 min-h-0 flex-1 overflow-y-auto px-1 py-4">
|
|
410
|
+
<FieldGrid>
|
|
411
|
+
{action.fields?.map((field) => {
|
|
412
|
+
const fullWidth =
|
|
413
|
+
isLineItemsField(field) ||
|
|
414
|
+
resolveWidget(field) === 'textarea' ||
|
|
415
|
+
resolveWidget(field) === 'richtext'
|
|
416
|
+
return (
|
|
417
|
+
<FieldCell key={field.key} fullWidth={fullWidth}>
|
|
418
|
+
<FieldLabel htmlFor={field.key} required={field.required}>
|
|
419
|
+
{tl(field.label)}
|
|
420
|
+
</FieldLabel>
|
|
421
|
+
{renderField(field, formData[field.key], (v: any) => updateField(field.key, v), formData)}
|
|
422
|
+
</FieldCell>
|
|
423
|
+
)
|
|
424
|
+
})}
|
|
425
|
+
{relations.length > 0 && (
|
|
426
|
+
<FieldCell fullWidth>
|
|
427
|
+
<DynamicRelations record={record} relations={relations} />
|
|
428
|
+
</FieldCell>
|
|
429
|
+
)}
|
|
430
|
+
</FieldGrid>
|
|
424
431
|
</div>
|
|
425
432
|
<DialogFooter className="shrink-0">
|
|
426
433
|
<Button variant="outline" onClick={() => onOpenChange(false)} disabled={executing}>
|
|
@@ -432,7 +439,7 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
|
|
|
432
439
|
style={action.color ? { backgroundColor: action.color, color: 'white' } : undefined}
|
|
433
440
|
>
|
|
434
441
|
{executing ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <DynamicIcon name={action.icon} className="mr-2 h-4 w-4" />}
|
|
435
|
-
{action.label}
|
|
442
|
+
{tl(action.label)}
|
|
436
443
|
</Button>
|
|
437
444
|
</DialogFooter>
|
|
438
445
|
</DialogContent>
|