@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 CHANGED
@@ -1,5 +1,30 @@
1
1
  # @asteby/metacore-runtime-react
2
2
 
3
+ ## 23.7.1
4
+
5
+ ### Patch Changes
6
+
7
+ - a3538da: fix(runtime-react): translate addon action labels at render (toolbar + modal)
8
+
9
+ `ModelActionToolbar` and `ActionModalDispatcher` rendered an action's `label`
10
+ (and each field's `label`) verbatim. For an addon's custom action these are i18n
11
+ keys (e.g. `integration_github.action.create_issue.label`) whose locale bundle
12
+ loads asynchronously, so the create button, the modal title/submit, and the
13
+ field labels showed the raw key — and never re-derived once the bundle landed.
14
+ They now translate at render with `t(label, { defaultValue: label })`, so the
15
+ label resolves the moment the addon i18n arrives (via the i18next store `added`
16
+ event) and an already-localized string passes through unchanged.
17
+
18
+ ## 23.7.0
19
+
20
+ ### Minor Changes
21
+
22
+ - 7611284: DynamicKanban: etapas personalizadas estilo Bitrix. Columna fantasma "+ Agregar etapa", diálogo de nombre/color/tipo y constructor de condiciones para etapas inteligentes (lanes virtuales por filtros, solo lectura), menú Editar/Eliminar en lanes custom, e integración con las automatizaciones de etapa. No intrusivo: sin el endpoint `/custom-stages` la UI no se renderiza y el tablero queda intacto.
23
+
24
+ Alineado al contrato del backend (ops #704): las lanes se pintan desde la metadata (`stages[]` con `custom: true` y `smart_lanes[]`), con el CRUD `/custom-stages` como fuente del diálogo de gestión. Los filtros de las etapas inteligentes se serializan como `f_<field>=OP:valor` (`EQ`, `NEQ`, `HAS` para membresía en arrays jsonb, `IN` para listas). En edición, `model`/`type`/`key` son inmutables. El borrado de una etapa real con tarjetas responde 409 con `meta.cards`; el diálogo muestra el conteo y ofrece reasignar las tarjetas a otra columna vía `?reassign_to=<key>`.
25
+
26
+ - 20cb58f: Pule el layout de los modales de create/acción: grid responsivo de dos columnas compartido (`FieldGrid`/`FieldCell`/`FieldLabel`) para el modal de `placement:create` (p. ej. "Crear Issue" del addon github) y el create/edit automático (CRUD). Los campos escalares fluyen en dos columnas (una sola en móvil), textareas/line-items ocupan el ancho completo, y cada celda lleva `min-w-0` para que un valor largo de select/input no reviente las columnas ni genere scroll horizontal. Ancho del dialog de acción a `sm:max-w-xl`, labels con estilo consistente y asterisco de requerido unificado.
27
+
3
28
  ## 23.6.0
4
29
 
5
30
  ### Minor Changes
@@ -9,7 +9,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
9
9
  // depend on a bundler alias to `@/lib/api`.
10
10
  import { useState, useEffect, useMemo } from 'react';
11
11
  import { useTranslation } from 'react-i18next';
12
- import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, Button, Input, Textarea, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Switch, } from '@asteby/metacore-ui/primitives';
12
+ 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';
13
13
  import { Loader2 } from 'lucide-react';
14
14
  import { toast } from 'sonner';
15
15
  import { useApi } from './api-context';
@@ -20,6 +20,7 @@ import { DynamicSelectField } from './dynamic-select-field';
20
20
  import { DynamicDateField } from './dynamic-date-field';
21
21
  import { UploadField } from './upload-field';
22
22
  import { isLineItemsField, resolveWidget, resolveDependsValue, getDependsOn } from './dynamic-form-schema';
23
+ import { FieldGrid, FieldCell, FieldLabel } from './field-grid';
23
24
  // Canonical registry lives in @asteby/metacore-sdk
24
25
  import { getActionComponent, } from '@asteby/metacore-sdk';
25
26
  function isPrefillSpec(v) {
@@ -110,6 +111,10 @@ function ConfirmActionDialog({ open, onOpenChange, action, model, record, endpoi
110
111
  const { t } = useTranslation();
111
112
  const api = useApi();
112
113
  const [executing, setExecuting] = useState(false);
114
+ // `action.label` is an addon-contributed i18n key; its locale bundle loads
115
+ // asynchronously, so translate at render (defaultValue keeps an already
116
+ // localized label unchanged).
117
+ const label = t(action.label, { defaultValue: action.label });
113
118
  const execute = async () => {
114
119
  setExecuting(true);
115
120
  try {
@@ -131,10 +136,14 @@ function ConfirmActionDialog({ open, onOpenChange, action, model, record, endpoi
131
136
  setExecuting(false);
132
137
  }
133
138
  };
134
- 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" }), action.label] }), _jsx(AlertDialogDescription, { children: action.confirmMessage || `${action.label}?` })] }), _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" }), action.label] })] })] }) }));
139
+ 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}?` })] }), _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] })] })] }) }));
135
140
  }
136
141
  function GenericActionModal({ open, onOpenChange, action, model, record, endpoint, onSuccess }) {
137
142
  const { t } = useTranslation();
143
+ // Addon-contributed labels (action + fields) are i18n keys whose locale
144
+ // bundle loads asynchronously; translate at render so they don't render raw.
145
+ // defaultValue keeps an already-localized string unchanged.
146
+ const tl = (s) => t(s, { defaultValue: s });
138
147
  const api = useApi();
139
148
  const [formData, setFormData] = useState({});
140
149
  const [executing, setExecuting] = useState(false);
@@ -193,13 +202,13 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
193
202
  if (isLineItemsField(field)) {
194
203
  const rows = formData[field.key];
195
204
  if (!Array.isArray(rows) || rows.length === 0) {
196
- toast.error(`${field.label} requiere al menos un renglón`);
205
+ toast.error(`${tl(field.label)} requiere al menos un renglón`);
197
206
  return;
198
207
  }
199
208
  continue;
200
209
  }
201
210
  if (!formData[field.key] && formData[field.key] !== false) {
202
- toast.error(`${field.label} es requerido`);
211
+ toast.error(`${tl(field.label)} es requerido`);
203
212
  return;
204
213
  }
205
214
  }
@@ -238,12 +247,12 @@ function GenericActionModal({ open, onOpenChange, action, model, record, endpoin
238
247
  : hasLineItems
239
248
  ? '820px'
240
249
  : undefined;
241
- return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: 'flex max-h-[90vh] flex-col overflow-hidden ' + (widthPx ? '' : 'sm:max-w-lg'), style: { maxHeight: '90vh', ...(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" }), action.label] }), action.confirmMessage && _jsx(DialogDescription, { children: action.confirmMessage })] }), _jsxs("div", { className: "-mx-1 grid min-h-0 flex-1 gap-4 overflow-y-auto px-1 py-4 sm:grid-cols-2", children: [action.fields?.map((field) => {
242
- const fullWidth = isLineItemsField(field) ||
243
- resolveWidget(field) === 'textarea' ||
244
- resolveWidget(field) === 'richtext';
245
- return (_jsxs("div", { className: 'grid gap-2 ' + (fullWidth ? 'sm:col-span-2' : ''), children: [_jsxs(Label, { htmlFor: field.key, children: [field.label, field.required && _jsx("span", { className: "text-red-500 ml-1", children: "*" })] }), renderField(field, formData[field.key], (v) => updateField(field.key, v), formData)] }, field.key));
246
- }), relations.length > 0 && (_jsx("div", { className: "sm:col-span-2", children: _jsx(DynamicRelations, { record: record, relations: relations }) }))] }), _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" }), action.label] })] })] }) }));
250
+ return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: 'flex max-h-[90vh] flex-col overflow-hidden ' + (widthPx ? '' : 'sm:max-w-xl'), style: { maxHeight: '90vh', ...(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) => {
251
+ const fullWidth = isLineItemsField(field) ||
252
+ resolveWidget(field) === 'textarea' ||
253
+ resolveWidget(field) === 'richtext';
254
+ 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));
255
+ }), relations.length > 0 && (_jsx(FieldCell, { fullWidth: true, children: _jsx(DynamicRelations, { record: record, relations: relations }) }))] }) }), _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)] })] })] }) }));
247
256
  }
248
257
  function renderField(field, value, onChange,
249
258
  // Full current form values — lets a line-items grid (and any cascading
@@ -0,0 +1,171 @@
1
+ import React from 'react';
2
+ import type { ApiClient } from './api-context';
3
+ import type { ColumnDefinition, StageMeta, SmartLaneMeta } from './types';
4
+ export type CustomStageType = 'stage' | 'smart';
5
+ export type CustomStageFilterOp = 'eq' | 'neq' | 'contains' | 'in';
6
+ export interface CustomStageFilter {
7
+ field: string;
8
+ op: CustomStageFilterOp;
9
+ value: string;
10
+ }
11
+ export interface CustomStage {
12
+ id: string | number;
13
+ model: string;
14
+ /** Stable lane key (also the value stored on a card for `type: "stage"`). */
15
+ key: string;
16
+ label: string;
17
+ /** Semantic palette name ('slate', 'blue', …) or a hex literal. */
18
+ color: string;
19
+ /** Board position (lane order). */
20
+ position: number;
21
+ type: CustomStageType;
22
+ /** Only meaningful for `type: "smart"` — the virtual lane's funnel. */
23
+ filters: CustomStageFilter[];
24
+ enabled: boolean;
25
+ }
26
+ /** Draft for a new custom stage (no server id yet). */
27
+ export type NewCustomStage = Omit<CustomStage, 'id'>;
28
+ export declare const CUSTOM_STAGE_COLORS: readonly ["slate", "blue", "green", "amber", "red", "purple", "pink", "cyan"];
29
+ export declare const CUSTOM_STAGE_FILTER_OPS: CustomStageFilterOp[];
30
+ /** A blank filter row for the smart-lane condition builder. */
31
+ export declare function emptyCustomStageFilter(field?: string): CustomStageFilter;
32
+ /** Enabled custom stages split by flavor (disabled ones are dropped). */
33
+ export declare function splitCustomStages(stages: CustomStage[] | undefined): {
34
+ laneStages: CustomStage[];
35
+ smartStages: CustomStage[];
36
+ };
37
+ /**
38
+ * Merges `type: "stage"` custom stages into the model's declared lanes. A
39
+ * custom stage whose key the metadata ALREADY carries (the backend surfaced it
40
+ * in `metadata.stages`) is not duplicated — it's just tagged as custom so the
41
+ * lane grows an edit/delete menu. Unknown-key custom stages are appended.
42
+ * Returns the merged lanes (sorted by order) plus a `key → CustomStage` map so
43
+ * the board can decorate the custom lanes.
44
+ */
45
+ export declare function mergeLaneStages(declared: StageMeta[], customLaneStages: CustomStage[]): {
46
+ lanes: StageMeta[];
47
+ customByKey: Map<string, CustomStage>;
48
+ };
49
+ /**
50
+ * Serializes a smart lane's filters into the board's list query params. The ops
51
+ * list endpoint (ops #704) takes a SINGLE `f_<field>` param whose value carries
52
+ * the operator as a `OP:value` prefix:
53
+ * - eq → `f_<field>=EQ:value`
54
+ * - neq → `f_<field>=NEQ:value`
55
+ * - contains → `f_<field>=HAS:value` (membership in a jsonb array — NOT the
56
+ * text-substring ILIKE; that's why it's HAS, not CONTAINS)
57
+ * - in → `f_<field>=IN:v1,v2,...` (comma-separated after `IN:`)
58
+ * Empty fields/values are skipped.
59
+ */
60
+ export declare function smartLaneParams(filters: CustomStageFilter[] | undefined): Record<string, string>;
61
+ /**
62
+ * Resolves the smart lanes to paint. The kernel's `metadata.smart_lanes` is the
63
+ * source of truth for rendering (ops #704); the CRUD list only backs the
64
+ * management dialog. So when metadata carries smart lanes we map those, folding
65
+ * in the CRUD entry's `id` (matched by key) so the Editar menu can PUT/DELETE.
66
+ * When metadata omits them (older host / metadata lag) we tolerate the gap and
67
+ * fall back to the CRUD smart stages. Returns `CustomStage[]` either way.
68
+ */
69
+ export declare function resolveSmartLanes(metaSmartLanes: SmartLaneMeta[] | undefined, crudSmartStages: CustomStage[], model: string): CustomStage[];
70
+ /** Columns offered in the condition builder: visible, non-id model columns. */
71
+ export declare function customStageFilterFields(columns: ColumnDefinition[]): ColumnDefinition[];
72
+ /** Whether a draft is complete enough to save. */
73
+ export declare function isCustomStageDraftValid(draft: {
74
+ label: string;
75
+ type: CustomStageType;
76
+ filters: CustomStageFilter[];
77
+ }): boolean;
78
+ /** Slugify a label into a stable-ish lane key (used only when creating). */
79
+ export declare function slugifyStageKey(label: string): string;
80
+ export interface UseCustomStagesResult {
81
+ /** False when the endpoint is missing/errored — hide the whole feature. */
82
+ available: boolean;
83
+ loading: boolean;
84
+ stages: CustomStage[];
85
+ create: (draft: NewCustomStage) => Promise<void>;
86
+ update: (id: CustomStage['id'], patch: Partial<CustomStage>) => Promise<void>;
87
+ /**
88
+ * Deletes a stage. Pass `reassignTo` (a target lane key) to move a real
89
+ * stage's cards first. Throws on 409 (cards still present, no reassign) so
90
+ * the caller can read `meta.cards` and offer a reassignment target.
91
+ */
92
+ remove: (id: CustomStage['id'], reassignTo?: string) => Promise<void>;
93
+ }
94
+ /**
95
+ * Loads a model's custom stages and exposes CRUD. A missing endpoint (404 /
96
+ * network error) degrades to `available: false` so the kanban never breaks;
97
+ * real mutation failures surface a toast and re-throw so the dialog keeps its
98
+ * draft. A 409 on delete (existing cards) is re-thrown WITHOUT a generic toast
99
+ * so the delete flow can show a targeted message.
100
+ */
101
+ export declare function useCustomStages(model: string): UseCustomStagesResult;
102
+ export interface AddStageColumnProps {
103
+ onClick: () => void;
104
+ }
105
+ /** The dotted phantom lane at the end of the board (Bitrix/Trello pattern). */
106
+ export declare function AddStageColumn({ onClick }: AddStageColumnProps): React.JSX.Element;
107
+ export interface CustomStageLaneMenuProps {
108
+ stage: CustomStage;
109
+ onEdit: (stage: CustomStage) => void;
110
+ onDelete: (stage: CustomStage) => void;
111
+ }
112
+ /** The ⋮ menu shown in a custom lane's header. */
113
+ export declare function CustomStageLaneMenu({ stage, onEdit, onDelete, }: CustomStageLaneMenuProps): React.JSX.Element;
114
+ export interface CustomStageDialogProps {
115
+ open: boolean;
116
+ onOpenChange: (open: boolean) => void;
117
+ model: string;
118
+ /** Columns for the smart-lane condition builder. */
119
+ columns: ColumnDefinition[];
120
+ /** Editing an existing stage, or null to create a new one. */
121
+ initial: CustomStage | null;
122
+ /** Next board position for a newly created stage (appended at the end). */
123
+ nextPosition: number;
124
+ onCreate: (draft: NewCustomStage) => Promise<void>;
125
+ onUpdate: (id: CustomStage['id'], patch: Partial<CustomStage>) => Promise<void>;
126
+ }
127
+ export declare function CustomStageDialog({ open, onOpenChange, model, columns, initial, nextPosition, onCreate, onUpdate, }: CustomStageDialogProps): React.JSX.Element;
128
+ export interface CustomStageDeleteDialogProps {
129
+ open: boolean;
130
+ onOpenChange: (open: boolean) => void;
131
+ stage: CustomStage | null;
132
+ /** Other lanes a real stage's cards can be reassigned to (key excluded). */
133
+ reassignTargets?: {
134
+ key: string;
135
+ label: string;
136
+ }[];
137
+ /** `reassignTo` is set on retry after a 409 (real stage with cards). */
138
+ onConfirm: (stage: CustomStage, reassignTo?: string) => Promise<void>;
139
+ }
140
+ /**
141
+ * Confirms deleting a custom lane. A 409 (the backend rejected because cards
142
+ * still sit on a real stage) doesn't close the dialog — it reads `meta.cards`
143
+ * from the response, shows the count, and offers a target lane to reassign the
144
+ * cards to; confirming again retries the delete with `reassign_to`.
145
+ */
146
+ export declare function CustomStageDeleteDialog({ open, onOpenChange, stage, reassignTargets, onConfirm, }: CustomStageDeleteDialogProps): React.JSX.Element | null;
147
+ export interface SmartLaneProps {
148
+ stage: CustomStage;
149
+ model: string;
150
+ /** Org-scoped list endpoint base (same as the kanban's). */
151
+ endpoint?: string;
152
+ /** Board-wide static filters always applied (never shown as a chip). */
153
+ defaultFilters?: Record<string, any>;
154
+ pageSize?: number;
155
+ isDark: boolean;
156
+ /** Renders one card the same way the board's real lanes do (read-only). */
157
+ renderCard: (card: any) => React.ReactNode;
158
+ /** Refetch trigger — bump to re-run the lane's query. */
159
+ refreshTrigger?: any;
160
+ onEdit: (stage: CustomStage) => void;
161
+ onDelete: (stage: CustomStage) => void;
162
+ }
163
+ /**
164
+ * A virtual lane defined by `filters`. It runs its OWN list query (the board's
165
+ * shared records don't include it), so it stays correct regardless of what the
166
+ * main board page loaded. Cards render read-only — a smart lane is a saved view,
167
+ * not a drop target — and the header carries a funnel glyph + the custom menu.
168
+ */
169
+ export declare function SmartLane({ stage, model, endpoint, defaultFilters, pageSize, isDark, renderCard, refreshTrigger, onEdit, onDelete, }: SmartLaneProps): React.JSX.Element;
170
+ export type { ApiClient };
171
+ //# sourceMappingURL=custom-stages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"custom-stages.d.ts","sourceRoot":"","sources":["../src/custom-stages.tsx"],"names":[],"mappings":"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"}