@asteby/metacore-runtime-react 23.7.1 → 23.8.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 +6 -0
- package/dist/custom-stages.d.ts +13 -1
- package/dist/custom-stages.d.ts.map +1 -1
- package/dist/custom-stages.js +3 -3
- package/dist/dynamic-kanban.d.ts.map +1 -1
- package/dist/dynamic-kanban.js +259 -43
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/stage-layout.d.ts +23 -0
- package/dist/stage-layout.d.ts.map +1 -0
- package/dist/stage-layout.js +70 -0
- package/package.json +1 -1
- package/src/__tests__/dynamic-kanban-lane-reorder.test.tsx +228 -0
- package/src/__tests__/stage-layout.test.tsx +210 -0
- package/src/custom-stages.tsx +30 -3
- package/src/dynamic-kanban.tsx +474 -144
- package/src/index.ts +5 -0
- package/src/stage-layout.ts +93 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 23.8.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- a3d3fdf: DynamicKanban: reordenar las columnas del tablero arrastrándolas por su encabezado (estilo Trello/Bitrix). Aplica a todas las lanes —etapas declaradas, etapas custom y smart lanes— con reorden optimista y persistencia por organización vía el endpoint `/stage-layout` del host (`GET`/`PUT` orden completo/`DELETE` restablece). Si el host no expone el endpoint, el drag de columnas queda deshabilitado en silencio y el tablero funciona igual. Se agrega el hook `useStageLayout` y un affordance "Restablecer orden" cuando existe un orden custom.
|
|
8
|
+
|
|
3
9
|
## 23.7.1
|
|
4
10
|
|
|
5
11
|
### Patch Changes
|
package/dist/custom-stages.d.ts
CHANGED
|
@@ -159,6 +159,18 @@ export interface SmartLaneProps {
|
|
|
159
159
|
refreshTrigger?: any;
|
|
160
160
|
onEdit: (stage: CustomStage) => void;
|
|
161
161
|
onDelete: (stage: CustomStage) => void;
|
|
162
|
+
/**
|
|
163
|
+
* Optional drag-and-drop wiring (from the kanban's sortable wrapper) so a
|
|
164
|
+
* smart lane can be reordered by its header like a real stage. Absent → the
|
|
165
|
+
* lane is static.
|
|
166
|
+
*/
|
|
167
|
+
dnd?: {
|
|
168
|
+
setNodeRef: (el: HTMLElement | null) => void;
|
|
169
|
+
style?: React.CSSProperties;
|
|
170
|
+
isDragging?: boolean;
|
|
171
|
+
handleRef?: (el: HTMLElement | null) => void;
|
|
172
|
+
handleProps?: Record<string, any>;
|
|
173
|
+
};
|
|
162
174
|
}
|
|
163
175
|
/**
|
|
164
176
|
* A virtual lane defined by `filters`. It runs its OWN list query (the board's
|
|
@@ -166,6 +178,6 @@ export interface SmartLaneProps {
|
|
|
166
178
|
* main board page loaded. Cards render read-only — a smart lane is a saved view,
|
|
167
179
|
* not a drop target — and the header carries a funnel glyph + the custom menu.
|
|
168
180
|
*/
|
|
169
|
-
export declare function SmartLane({ stage, model, endpoint, defaultFilters, pageSize, isDark, renderCard, refreshTrigger, onEdit, onDelete, }: SmartLaneProps): React.JSX.Element;
|
|
181
|
+
export declare function SmartLane({ stage, model, endpoint, defaultFilters, pageSize, isDark, renderCard, refreshTrigger, onEdit, onDelete, dnd, }: SmartLaneProps): React.JSX.Element;
|
|
170
182
|
export type { ApiClient };
|
|
171
183
|
//# sourceMappingURL=custom-stages.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"custom-stages.d.ts","sourceRoot":"","sources":["../src/custom-stages.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"custom-stages.d.ts","sourceRoot":"","sources":["../src/custom-stages.tsx"],"names":[],"mappings":"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"}
|
package/dist/custom-stages.js
CHANGED
|
@@ -20,7 +20,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
20
20
|
// All UI text goes through t() with a Spanish defaultValue.
|
|
21
21
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
22
22
|
import { useTranslation } from 'react-i18next';
|
|
23
|
-
import { Plus, Trash2, Pencil, MoreVertical, Filter, X } from 'lucide-react';
|
|
23
|
+
import { Plus, Trash2, Pencil, MoreVertical, Filter, GripVertical, X } from 'lucide-react';
|
|
24
24
|
import { toast } from 'sonner';
|
|
25
25
|
import { Badge, Button, Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Input, Label, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Skeleton, } from '@asteby/metacore-ui/primitives';
|
|
26
26
|
import { generateBadgeStyles, optionColor } from '@asteby/metacore-ui/lib';
|
|
@@ -484,7 +484,7 @@ export function CustomStageDeleteDialog({ open, onOpenChange, stage, reassignTar
|
|
|
484
484
|
* main board page loaded. Cards render read-only — a smart lane is a saved view,
|
|
485
485
|
* not a drop target — and the header carries a funnel glyph + the custom menu.
|
|
486
486
|
*/
|
|
487
|
-
export function SmartLane({ stage, model, endpoint, defaultFilters, pageSize = 50, isDark, renderCard, refreshTrigger, onEdit, onDelete, }) {
|
|
487
|
+
export function SmartLane({ stage, model, endpoint, defaultFilters, pageSize = 50, isDark, renderCard, refreshTrigger, onEdit, onDelete, dnd, }) {
|
|
488
488
|
const { t } = useTranslation();
|
|
489
489
|
const api = useApi();
|
|
490
490
|
const [records, setRecords] = useState([]);
|
|
@@ -527,7 +527,7 @@ export function SmartLane({ stage, model, endpoint, defaultFilters, pageSize = 5
|
|
|
527
527
|
isDark,
|
|
528
528
|
});
|
|
529
529
|
const count = total ?? records.length;
|
|
530
|
-
return (_jsxs("div", { className: "flex min-w-[280px] max-w-[420px] flex-1 shrink-0 flex-col rounded-xl border border-dashed bg-muted/20", "data-smart-stage": stage.key, "data-testid": `smart-lane-${stage.key}`, children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2.5", children: [_jsxs("div", { className:
|
|
530
|
+
return (_jsxs("div", { ref: dnd?.setNodeRef, className: "group/lane flex min-w-[280px] max-w-[420px] flex-1 shrink-0 flex-col rounded-xl border border-dashed bg-muted/20", style: { opacity: dnd?.isDragging ? 0.6 : 1, ...dnd?.style }, "data-smart-stage": stage.key, "data-testid": `smart-lane-${stage.key}`, children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2.5", children: [_jsxs("div", { ref: dnd ? dnd.handleRef : undefined, ...(dnd ? dnd.handleProps : {}), className: `flex min-w-0 items-center gap-1.5 ${dnd ? 'cursor-grab active:cursor-grabbing' : ''}`, children: [dnd && (_jsx(GripVertical, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/40 opacity-0 transition-opacity group-hover/lane:opacity-70", "aria-hidden": true })), _jsx(Badge, { variant: "outline", className: "border-0 text-xs font-semibold", style: headerStyle, children: t(stage.label, { defaultValue: stage.label }) }), _jsx("span", { className: "text-muted-foreground", title: t('dynamic.custom_stages.smart_hint', {
|
|
531
531
|
defaultValue: 'Etapa inteligente (por condiciones)',
|
|
532
532
|
}), children: _jsx(Filter, { className: "h-3 w-3" }) }), _jsx("span", { className: "text-xs font-medium tabular-nums text-muted-foreground", children: count })] }), _jsx(CustomStageLaneMenu, { stage: stage, onEdit: onEdit, onDelete: onDelete })] }), _jsx("div", { className: "flex min-h-[55vh] max-h-[70vh] min-w-0 flex-col gap-2 overflow-y-auto px-2 pb-3", children: loading && records.length === 0 ? (_jsxs(_Fragment, { children: [_jsx(Skeleton, { className: "h-20 w-full" }), _jsx(Skeleton, { className: "h-20 w-full" })] })) : records.length === 0 ? (_jsx("p", { className: "px-1 py-6 text-center text-xs text-muted-foreground", children: t('dynamic.custom_stages.smart_empty', {
|
|
533
533
|
defaultValue: 'Sin tarjetas que cumplan las condiciones',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dynamic-kanban.d.ts","sourceRoot":"","sources":["../src/dynamic-kanban.tsx"],"names":[],"mappings":"AA0BA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"dynamic-kanban.d.ts","sourceRoot":"","sources":["../src/dynamic-kanban.tsx"],"names":[],"mappings":"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"}
|
package/dist/dynamic-kanban.js
CHANGED
|
@@ -2,7 +2,10 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { useTranslation } from 'react-i18next';
|
|
4
4
|
import { DndContext, DragOverlay, PointerSensor, useSensor, useSensors, useDraggable, useDroppable, } from '@dnd-kit/core';
|
|
5
|
-
import {
|
|
5
|
+
import { SortableContext, horizontalListSortingStrategy, useSortable, } from '@dnd-kit/sortable';
|
|
6
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
7
|
+
import { arrayMove } from '@dnd-kit/sortable';
|
|
8
|
+
import { Calendar, CircleDot, GripVertical, Hash, ListFilter, MoreHorizontal, RotateCcw, Search, Tag, ToggleLeft, Type, X, } from 'lucide-react';
|
|
6
9
|
import { toast } from 'sonner';
|
|
7
10
|
import { Badge, Button, Card, CardContent, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, Input, Popover, PopoverContent, PopoverTrigger, Select, SelectContent, SelectItem, SelectTrigger, SelectValue, Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger, Skeleton, } from '@asteby/metacore-ui/primitives';
|
|
8
11
|
import { ColumnFilterControl, FilterValueCombobox } from '@asteby/metacore-ui/data-table';
|
|
@@ -20,6 +23,7 @@ import { isColumnVisibleInTable } from './column-visibility';
|
|
|
20
23
|
import { isRowActionVisible } from './dynamic-columns';
|
|
21
24
|
import { useCan, usePermissionsActive, resolveRowActions } from './permissions-context';
|
|
22
25
|
import { useDynamicRowActions } from './dynamic-row-actions';
|
|
26
|
+
import { useStageLayout } from './stage-layout';
|
|
23
27
|
// Re-exported for tests + backward-compat: these live in ./filter-chips now
|
|
24
28
|
// (shared with DynamicTable) but were historically imported from here.
|
|
25
29
|
export { summarizeFilterValues, translateOptionLabels };
|
|
@@ -274,6 +278,18 @@ export function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, on
|
|
|
274
278
|
const [lanePagination, setLanePagination] = useState({});
|
|
275
279
|
// Active drag card id (for the DragOverlay + drop-zone highlighting).
|
|
276
280
|
const [activeId, setActiveId] = useState(null);
|
|
281
|
+
// Active drag LANE id — a header drag reorders columns (Trello/Bitrix-style)
|
|
282
|
+
// rather than moving a card. Kept apart so onDragEnd routes by draggable type.
|
|
283
|
+
const [activeLaneId, setActiveLaneId] = useState(null);
|
|
284
|
+
// Per-org lane order. `useStageLayout` reports whether the host wired the
|
|
285
|
+
// `/stage-layout` endpoint (→ lane drag turns on) and persists the chosen
|
|
286
|
+
// order. `laneOrderOverride` is the OPTIMISTIC session order applied on top of
|
|
287
|
+
// the metadata (the backend also stamps `stages[]/smart_lanes[].order`, so the
|
|
288
|
+
// board already paints ordered on load — this only backs the live drag + the
|
|
289
|
+
// revert-on-failure). Null → follow the metadata order.
|
|
290
|
+
const stageLayout = useStageLayout(model);
|
|
291
|
+
const [laneOrderOverride, setLaneOrderOverride] = useState(null);
|
|
292
|
+
const laneReorderEnabled = stageLayout.available;
|
|
277
293
|
// Monotonic token for the current board load. Bumped on every fetchData so a
|
|
278
294
|
// slow eager-totals response from a superseded filter set can't inject stale
|
|
279
295
|
// stage totals into the fresh board.
|
|
@@ -541,6 +557,44 @@ export function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, on
|
|
|
541
557
|
return Math.max(base, ...positions, 0) + 1;
|
|
542
558
|
}, [customStages.stages, stages.length, smartStages.length]);
|
|
543
559
|
const transitions = metadata?.transitions;
|
|
560
|
+
// Unified, ordered list of the DRAGGABLE lanes (real stages + smart lanes) —
|
|
561
|
+
// the sortable sequence the header drag reorders. Real stages and smart lanes
|
|
562
|
+
// are merged by their `order` (the backend stamps a global sequence once a
|
|
563
|
+
// custom order exists); a `laneOrderOverride` from the live drag wins. Ties
|
|
564
|
+
// (the default, un-customized case where both sets start at 0) keep stages
|
|
565
|
+
// before smart lanes, matching the pre-reorder layout.
|
|
566
|
+
const renderLanes = useMemo(() => {
|
|
567
|
+
const arr = [
|
|
568
|
+
...stages.map((s, i) => ({
|
|
569
|
+
kind: 'stage',
|
|
570
|
+
stage: s,
|
|
571
|
+
order: s.order ?? i,
|
|
572
|
+
})),
|
|
573
|
+
...smartStages.map((s, i) => ({
|
|
574
|
+
kind: 'smart',
|
|
575
|
+
stage: s,
|
|
576
|
+
order: s.position ?? 1000 + i,
|
|
577
|
+
})),
|
|
578
|
+
];
|
|
579
|
+
if (laneOrderOverride) {
|
|
580
|
+
const idx = new Map(laneOrderOverride.map((k, i) => [k, i]));
|
|
581
|
+
arr.sort((a, b) => (idx.get(a.stage.key) ?? Number.MAX_SAFE_INTEGER) -
|
|
582
|
+
(idx.get(b.stage.key) ?? Number.MAX_SAFE_INTEGER));
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
arr.sort((a, b) => a.order - b.order ||
|
|
586
|
+
(a.kind === b.kind ? 0 : a.kind === 'stage' ? -1 : 1));
|
|
587
|
+
}
|
|
588
|
+
return arr.map(({ kind, stage: s }) => kind === 'stage'
|
|
589
|
+
? { kind: 'stage', stage: s }
|
|
590
|
+
: { kind: 'smart', stage: s });
|
|
591
|
+
}, [stages, smartStages, laneOrderOverride]);
|
|
592
|
+
// The sortable ids, in current visual order — SortableContext items + the
|
|
593
|
+
// basis for the arrayMove the drop computes.
|
|
594
|
+
const boardLaneKeys = useMemo(() => renderLanes.map((l) => l.stage.key), [renderLanes]);
|
|
595
|
+
// Real (card-droppable) stage keys — guards a card drop from ever landing on
|
|
596
|
+
// a smart lane (a saved view, never a stored stage value).
|
|
597
|
+
const realStageKeys = useMemo(() => new Set(stages.map((s) => s.key)), [stages]);
|
|
544
598
|
const grouped = useMemo(() => groupByStage(records, groupByKey, stages), [records, groupByKey, stages]);
|
|
545
599
|
const { title: titleCol, fields: fieldCols } = useMemo(() => (metadata ? selectCardColumns(metadata) : { title: null, fields: [] }), [metadata]);
|
|
546
600
|
// Columns the lane search scans: the card title + its visible field cells.
|
|
@@ -576,15 +630,51 @@ export function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, on
|
|
|
576
630
|
return raw === null || raw === undefined ? '' : String(raw);
|
|
577
631
|
}, [cardById, groupByKey]);
|
|
578
632
|
const onDragStart = useCallback((e) => {
|
|
579
|
-
|
|
633
|
+
if (e.active.data.current?.type === 'lane') {
|
|
634
|
+
setActiveLaneId(String(e.active.id));
|
|
635
|
+
}
|
|
636
|
+
else {
|
|
637
|
+
setActiveId(String(e.active.id));
|
|
638
|
+
}
|
|
580
639
|
}, []);
|
|
640
|
+
// Optimistic lane reorder: reorder the columns in local state immediately,
|
|
641
|
+
// PUT the full new order, and revert + toast on failure. Keys mix real
|
|
642
|
+
// stages and smart lanes (the backend applies the order to both).
|
|
643
|
+
const reorderLanes = useCallback(async (activeKey, overKey) => {
|
|
644
|
+
const from = boardLaneKeys.indexOf(activeKey);
|
|
645
|
+
const to = boardLaneKeys.indexOf(overKey);
|
|
646
|
+
if (from === -1 || to === -1 || from === to)
|
|
647
|
+
return;
|
|
648
|
+
const next = arrayMove(boardLaneKeys, from, to);
|
|
649
|
+
const prev = laneOrderOverride;
|
|
650
|
+
setLaneOrderOverride(next);
|
|
651
|
+
try {
|
|
652
|
+
await stageLayout.save(next);
|
|
653
|
+
}
|
|
654
|
+
catch {
|
|
655
|
+
setLaneOrderOverride(prev);
|
|
656
|
+
toast.error(t('dynamic.stage_layout.save_error', {
|
|
657
|
+
defaultValue: 'No se pudo guardar el orden',
|
|
658
|
+
}));
|
|
659
|
+
}
|
|
660
|
+
}, [boardLaneKeys, laneOrderOverride, stageLayout, t]);
|
|
581
661
|
const onDragEnd = useCallback(async (e) => {
|
|
582
662
|
setActiveId(null);
|
|
663
|
+
setActiveLaneId(null);
|
|
583
664
|
const { active, over } = e;
|
|
665
|
+
// A header drag reorders columns rather than moving a card.
|
|
666
|
+
if (active.data.current?.type === 'lane') {
|
|
667
|
+
if (over)
|
|
668
|
+
await reorderLanes(String(active.id), String(over.id));
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
584
671
|
if (!over)
|
|
585
672
|
return;
|
|
586
673
|
const cardId = String(active.id);
|
|
587
674
|
const destStage = String(over.id);
|
|
675
|
+
// Never drop a card onto a smart lane (a saved view, not a stage).
|
|
676
|
+
if (!realStageKeys.has(destStage) && destStage !== UNASSIGNED_LANE)
|
|
677
|
+
return;
|
|
588
678
|
const srcStage = stageOfCard(cardId);
|
|
589
679
|
if (srcStage === destStage)
|
|
590
680
|
return;
|
|
@@ -626,7 +716,29 @@ export function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, on
|
|
|
626
716
|
? `: ${err.response.data.message}`
|
|
627
717
|
: ''));
|
|
628
718
|
}
|
|
629
|
-
}, [api, endpoint, groupByKey, lanePagination, model, records, stageOfCard, t, transitions]);
|
|
719
|
+
}, [api, endpoint, groupByKey, lanePagination, model, records, stageOfCard, t, transitions, realStageKeys, reorderLanes]);
|
|
720
|
+
// Board-level "Restablecer orden": drop the stored order and refetch the
|
|
721
|
+
// metadata so the lanes fall back to the DECLARED order. Optimistic — reverts
|
|
722
|
+
// its local override on failure.
|
|
723
|
+
const resetLaneOrder = useCallback(async () => {
|
|
724
|
+
const prev = laneOrderOverride;
|
|
725
|
+
setLaneOrderOverride(null);
|
|
726
|
+
try {
|
|
727
|
+
await stageLayout.reset();
|
|
728
|
+
const res = await api.get(`/metadata/table/${model}`);
|
|
729
|
+
const body = res.data;
|
|
730
|
+
if (body.success) {
|
|
731
|
+
setMetadata(body.data);
|
|
732
|
+
cacheMetadata(model, body.data);
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
catch {
|
|
736
|
+
setLaneOrderOverride(prev);
|
|
737
|
+
toast.error(t('dynamic.stage_layout.reset_error', {
|
|
738
|
+
defaultValue: 'No se pudo restablecer el orden',
|
|
739
|
+
}));
|
|
740
|
+
}
|
|
741
|
+
}, [api, cacheMetadata, laneOrderOverride, model, stageLayout, t]);
|
|
630
742
|
if (loading) {
|
|
631
743
|
return (_jsx("div", { className: "flex w-full gap-4 overflow-x-auto p-1", children: [0, 1, 2, 3].map((i) => (_jsxs("div", { className: "min-w-[280px] max-w-[420px] flex-1 shrink-0 space-y-3", children: [_jsx(Skeleton, { className: "h-8 w-full" }), _jsx(Skeleton, { className: "h-24 w-full" }), _jsx(Skeleton, { className: "h-24 w-full" })] }, i))) }));
|
|
632
744
|
}
|
|
@@ -637,15 +749,85 @@ export function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, on
|
|
|
637
749
|
}
|
|
638
750
|
const activeCard = activeId ? cardById.get(activeId) : null;
|
|
639
751
|
const activeStage = activeId ? stageOfCard(activeId) : '';
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
752
|
+
// The synthetic "Sin etapa" lane (only when some record's stage matches no
|
|
753
|
+
// declared lane). Rendered after the sortable lanes, never draggable itself.
|
|
754
|
+
const unassignedStage = grouped.has(UNASSIGNED_LANE)
|
|
755
|
+
? {
|
|
643
756
|
key: UNASSIGNED_LANE,
|
|
644
757
|
label: t('kanban.unassigned', { defaultValue: 'Sin etapa' }),
|
|
645
758
|
color: 'slate',
|
|
646
759
|
order: Number.MAX_SAFE_INTEGER,
|
|
647
|
-
}
|
|
648
|
-
|
|
760
|
+
}
|
|
761
|
+
: null;
|
|
762
|
+
// Whether a card may drop into a lane given the active card's stage + the
|
|
763
|
+
// declared transitions (a same-stage or unrestricted move always passes).
|
|
764
|
+
const droppableAllowedFor = (stageKey) => !activeId ||
|
|
765
|
+
stageKey === activeStage ||
|
|
766
|
+
isTransitionAllowed(transitions, activeStage, stageKey);
|
|
767
|
+
// Builds every `KanbanLane` prop (minus the dnd wiring) for one stage —
|
|
768
|
+
// shared by the sortable real stages and the plain-droppable unassigned lane.
|
|
769
|
+
const buildLaneProps = (stage) => {
|
|
770
|
+
const allCards = grouped.get(stage.key) ?? [];
|
|
771
|
+
// Per-lane client-side narrowing (instant, scoped to this stage). The
|
|
772
|
+
// funnel (field/value) and the lane search (query) are AND-combined.
|
|
773
|
+
const laneFilter = laneFilters[stage.key];
|
|
774
|
+
let cards = allCards;
|
|
775
|
+
if (laneFilter?.field) {
|
|
776
|
+
cards = cards.filter((c) => cardMatchesLaneFunnel(c, laneFilter));
|
|
777
|
+
}
|
|
778
|
+
if (laneFilter?.query?.trim()) {
|
|
779
|
+
cards = cards.filter((c) => cardMatchesLaneQuery(c, searchCols, laneFilter.query));
|
|
780
|
+
}
|
|
781
|
+
const laneState = lanePagination[stage.key];
|
|
782
|
+
const isUnassigned = stage.key === UNASSIGNED_LANE;
|
|
783
|
+
const laneHasMore = !isUnassigned && !laneState?.done;
|
|
784
|
+
return {
|
|
785
|
+
stage,
|
|
786
|
+
count: cards.length,
|
|
787
|
+
totalCount: allCards.length,
|
|
788
|
+
serverTotal: laneState?.total ?? null,
|
|
789
|
+
hasMore: laneHasMore,
|
|
790
|
+
loadingMore: !!laneState?.loading,
|
|
791
|
+
onLoadMore: () => loadMoreLane(stage.key),
|
|
792
|
+
filterFields,
|
|
793
|
+
laneFilter,
|
|
794
|
+
onFunnelChange: (f) => updateLaneFilter(stage.key, {
|
|
795
|
+
field: f?.field,
|
|
796
|
+
values: f?.values,
|
|
797
|
+
text: f?.text,
|
|
798
|
+
}),
|
|
799
|
+
onQueryChange: (q) => updateLaneFilter(stage.key, { query: q }),
|
|
800
|
+
isDark,
|
|
801
|
+
dimmed: !!activeId && !droppableAllowedFor(stage.key),
|
|
802
|
+
model,
|
|
803
|
+
columns: metadata?.columns ?? [],
|
|
804
|
+
automationsAvailable: automations.available && stage.key !== UNASSIGNED_LANE,
|
|
805
|
+
automationRules: automations.byStage.get(stage.key) ?? [],
|
|
806
|
+
onAutomationCreate: automations.create,
|
|
807
|
+
onAutomationUpdate: automations.update,
|
|
808
|
+
onAutomationRemove: automations.remove,
|
|
809
|
+
customStage: customStages.available
|
|
810
|
+
? customByKey.get(stage.key)
|
|
811
|
+
: undefined,
|
|
812
|
+
onEditStage: openEditStage,
|
|
813
|
+
onDeleteStage: openDeleteStage,
|
|
814
|
+
children: loadingData && cards.length === 0 ? (_jsxs(_Fragment, { children: [_jsx(Skeleton, { className: "h-20 w-full" }), _jsx(Skeleton, { className: "h-20 w-full" })] })) : cards.length === 0 ? (_jsx("p", { className: "px-1 py-6 text-center text-xs text-muted-foreground", children: t('kanban.emptyLane', { defaultValue: 'Sin tarjetas' }) })) : (cards.map((card) => (_jsx(KanbanCard, { card: card, titleCol: titleCol, fieldCols: fieldCols, actions: rowActions, locale: i18n.language, timeZone: timeZone, currency: currency, onClick: onCardClick, onAction: handleInternalAction }, String(card.id))))),
|
|
815
|
+
};
|
|
816
|
+
};
|
|
817
|
+
// Props for one smart (virtual) lane — a read-only, filter-defined column.
|
|
818
|
+
const buildSmartProps = (smart) => ({
|
|
819
|
+
stage: smart,
|
|
820
|
+
model,
|
|
821
|
+
endpoint,
|
|
822
|
+
defaultFilters,
|
|
823
|
+
pageSize,
|
|
824
|
+
isDark,
|
|
825
|
+
refreshTrigger,
|
|
826
|
+
onEdit: openEditStage,
|
|
827
|
+
onDelete: openDeleteStage,
|
|
828
|
+
renderCard: (card) => (_jsx(KanbanCard, { card: card, titleCol: titleCol, fieldCols: fieldCols, actions: rowActions, locale: i18n.language, timeZone: timeZone, currency: currency, onClick: onCardClick, onAction: handleInternalAction, draggable: false })),
|
|
829
|
+
});
|
|
830
|
+
const showResetOrder = laneReorderEnabled && (stageLayout.hasCustomLayout || !!laneOrderOverride);
|
|
649
831
|
return (_jsxs("div", { className: "flex flex-col gap-3", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-2", "data-testid": "kanban-filters", children: [_jsxs("div", { className: "relative", children: [_jsx(Search, { className: "pointer-events-none absolute left-2.5 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { value: globalFilter, onChange: (e) => setGlobalFilter(e.target.value), placeholder: t('kanban.searchPlaceholder', { defaultValue: 'Buscar...' }), className: "h-8 w-52 pl-8 text-sm" })] }), filterFields.length > 0 && (_jsxs(Sheet, { open: filtersOpen, onOpenChange: setFiltersOpen, children: [_jsx(SheetTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "sm", className: "h-8 gap-1.5", children: [_jsx(ListFilter, { className: "h-3.5 w-3.5" }), t('kanban.filters', { defaultValue: 'Filtros' }), activeFilterCount > 0 && (_jsx(Badge, { variant: "secondary", className: "ml-0.5 h-4 min-w-4 justify-center rounded-full px-1 text-[10px] tabular-nums", children: activeFilterCount }))] }) }), _jsxs(SheetContent, { side: "right", className: "flex w-80 flex-col gap-0 p-0 sm:max-w-sm", children: [_jsx(SheetHeader, { className: "space-y-0 border-b px-4 py-3", children: _jsx(SheetTitle, { className: "text-sm", children: t('kanban.filters', { defaultValue: 'Filtros' }) }) }), _jsxs("div", { className: "flex flex-1 flex-col gap-1 overflow-y-auto px-4 py-3", children: [activeFields.length > 0 && (_jsxs(_Fragment, { children: [_jsx("p", { className: "px-0.5 pb-1 text-[11px] font-medium uppercase tracking-wide text-muted-foreground", children: t('kanban.activeFilters', {
|
|
650
832
|
defaultValue: 'Con filtros activos',
|
|
651
833
|
}) }), activeFields.map((field) => (_jsx(SheetFilterRow, { field: field, isStage: field.key === groupByKey }, field.key))), inactiveFields.length > 0 && (_jsx("div", { className: "my-2 border-t" }))] })), inactiveFields.map((field) => (_jsx(SheetFilterRow, { field: field, isStage: field.key === groupByKey }, field.key)))] }), _jsxs("div", { className: "sticky bottom-0 flex items-center justify-between gap-2 border-t bg-background px-4 py-3", children: [_jsx("span", { className: "text-xs text-muted-foreground tabular-nums", children: activeFilterCount > 0
|
|
@@ -655,35 +837,9 @@ export function DynamicKanban({ model, endpoint, refreshTrigger, onCardClick, on
|
|
|
655
837
|
})
|
|
656
838
|
: t('kanban.noActiveFilters', {
|
|
657
839
|
defaultValue: 'Sin filtros',
|
|
658
|
-
}) }), _jsxs(Button, { variant: "ghost", size: "sm", className: "h-7 gap-1 text-xs", onClick: clearAll, disabled: activeFilterCount === 0, children: [_jsx(X, { className: "h-3.5 w-3.5" }), t('kanban.clearAll', { defaultValue: 'Limpiar todo' }), activeFilterCount > 0 ? ` (${activeFilterCount})` : ''] })] })] })] }))
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
// stage). The funnel (field/value) and the lane search
|
|
662
|
-
// (query) are AND-combined.
|
|
663
|
-
const laneFilter = laneFilters[stage.key];
|
|
664
|
-
let cards = allCards;
|
|
665
|
-
if (laneFilter?.field) {
|
|
666
|
-
cards = cards.filter((c) => cardMatchesLaneFunnel(c, laneFilter));
|
|
667
|
-
}
|
|
668
|
-
if (laneFilter?.query?.trim()) {
|
|
669
|
-
cards = cards.filter((c) => cardMatchesLaneQuery(c, searchCols, laneFilter.query));
|
|
670
|
-
}
|
|
671
|
-
const droppableAllowed = !activeId ||
|
|
672
|
-
stage.key === activeStage ||
|
|
673
|
-
isTransitionAllowed(transitions, activeStage, stage.key);
|
|
674
|
-
// Infinite scroll is per declared stage; the synthetic
|
|
675
|
-
// "unassigned" lane can't be stage-scoped, so it never tops up.
|
|
676
|
-
const laneState = lanePagination[stage.key];
|
|
677
|
-
const isUnassigned = stage.key === UNASSIGNED_LANE;
|
|
678
|
-
const laneHasMore = !isUnassigned && !laneState?.done;
|
|
679
|
-
return (_jsx(KanbanLane, { stage: stage, count: cards.length, totalCount: allCards.length, serverTotal: laneState?.total ?? null, hasMore: laneHasMore, loadingMore: !!laneState?.loading, onLoadMore: () => loadMoreLane(stage.key), filterFields: filterFields, laneFilter: laneFilter, onFunnelChange: (f) => updateLaneFilter(stage.key, {
|
|
680
|
-
field: f?.field,
|
|
681
|
-
values: f?.values,
|
|
682
|
-
text: f?.text,
|
|
683
|
-
}), onQueryChange: (q) => updateLaneFilter(stage.key, { query: q }), isDark: isDark, dimmed: !!activeId && !droppableAllowed, disabled: !!activeId && !droppableAllowed, model: model, columns: metadata?.columns ?? [], automationsAvailable: automations.available && stage.key !== UNASSIGNED_LANE, automationRules: automations.byStage.get(stage.key) ?? [], onAutomationCreate: automations.create, onAutomationUpdate: automations.update, onAutomationRemove: automations.remove, customStage: customStages.available
|
|
684
|
-
? customByKey.get(stage.key)
|
|
685
|
-
: undefined, onEditStage: openEditStage, onDeleteStage: openDeleteStage, children: loadingData && cards.length === 0 ? (_jsxs(_Fragment, { children: [_jsx(Skeleton, { className: "h-20 w-full" }), _jsx(Skeleton, { className: "h-20 w-full" })] })) : cards.length === 0 ? (_jsx("p", { className: "px-1 py-6 text-center text-xs text-muted-foreground", children: t('kanban.emptyLane', { defaultValue: 'Sin tarjetas' }) })) : (cards.map((card) => (_jsx(KanbanCard, { card: card, titleCol: titleCol, fieldCols: fieldCols, actions: rowActions, locale: i18n.language, timeZone: timeZone, currency: currency, onClick: onCardClick, onAction: handleInternalAction }, String(card.id))))) }, stage.key));
|
|
686
|
-
}), smartStages.map((smart) => (_jsx(SmartLane, { stage: smart, model: model, endpoint: endpoint, defaultFilters: defaultFilters, pageSize: pageSize, isDark: isDark, refreshTrigger: refreshTrigger, onEdit: openEditStage, onDelete: openDeleteStage, renderCard: (card) => (_jsx(KanbanCard, { card: card, titleCol: titleCol, fieldCols: fieldCols, actions: rowActions, locale: i18n.language, timeZone: timeZone, currency: currency, onClick: onCardClick, onAction: handleInternalAction, draggable: false })) }, `smart-${smart.key}`))), customStages.available && (_jsx(AddStageColumn, { onClick: openCreateStage }))] }), _jsx(DragOverlay, { children: activeCard ? (_jsx(CardPreview, { card: activeCard, titleCol: titleCol, fieldCols: fieldCols, locale: i18n.language, timeZone: timeZone, currency: currency })) : null }), rowActionDialogs] }), customStages.available && (_jsxs(_Fragment, { children: [_jsx(CustomStageDialog, { open: stageDialogOpen, onOpenChange: setStageDialogOpen, model: model, columns: metadata?.columns ?? [], initial: editingStage, nextPosition: nextStagePosition, onCreate: customStages.create, onUpdate: customStages.update }), _jsx(CustomStageDeleteDialog, { open: !!deletingStage, onOpenChange: (o) => {
|
|
840
|
+
}) }), _jsxs(Button, { variant: "ghost", size: "sm", className: "h-7 gap-1 text-xs", onClick: clearAll, disabled: activeFilterCount === 0, children: [_jsx(X, { className: "h-3.5 w-3.5" }), t('kanban.clearAll', { defaultValue: 'Limpiar todo' }), activeFilterCount > 0 ? ` (${activeFilterCount})` : ''] })] })] })] })), showResetOrder && (_jsxs(Button, { variant: "ghost", size: "sm", className: "h-8 gap-1.5 text-xs text-muted-foreground", onClick: () => void resetLaneOrder(), "data-testid": "kanban-reset-order", children: [_jsx(RotateCcw, { className: "h-3.5 w-3.5" }), t('dynamic.stage_layout.reset', {
|
|
841
|
+
defaultValue: 'Restablecer orden',
|
|
842
|
+
})] }))] }), _jsx(FilterChipsRow, { fields: activeFields, onClearAll: clearAll, "data-testid": "kanban-filter-chips" }), _jsxs(DndContext, { sensors: sensors, onDragStart: onDragStart, onDragEnd: onDragEnd, children: [_jsx(SortableContext, { items: boardLaneKeys, strategy: horizontalListSortingStrategy, children: _jsxs("div", { className: "flex w-full min-w-0 gap-4 overflow-x-auto p-1", "data-testid": "kanban-board", children: [renderLanes.map((lane) => lane.kind === 'stage' ? (_jsx(SortableStageLane, { reorderEnabled: laneReorderEnabled, droppableDisabled: !!activeId && !droppableAllowedFor(lane.stage.key), laneProps: buildLaneProps(lane.stage) }, lane.stage.key)) : laneReorderEnabled ? (_jsx(SortableSmartLane, { droppableDisabled: !!activeId, smartProps: buildSmartProps(lane.stage) }, `smart-${lane.stage.key}`)) : (_jsx(SmartLane, { ...buildSmartProps(lane.stage) }, `smart-${lane.stage.key}`))), unassignedStage && (_jsx(DroppableStageLane, { droppableDisabled: !!activeId && !droppableAllowedFor(UNASSIGNED_LANE), laneProps: buildLaneProps(unassignedStage) }, UNASSIGNED_LANE)), customStages.available && (_jsx(AddStageColumn, { onClick: openCreateStage }))] }) }), _jsx(DragOverlay, { children: activeCard ? (_jsx(CardPreview, { card: activeCard, titleCol: titleCol, fieldCols: fieldCols, locale: i18n.language, timeZone: timeZone, currency: currency })) : null }), rowActionDialogs] }), customStages.available && (_jsxs(_Fragment, { children: [_jsx(CustomStageDialog, { open: stageDialogOpen, onOpenChange: setStageDialogOpen, model: model, columns: metadata?.columns ?? [], initial: editingStage, nextPosition: nextStagePosition, onCreate: customStages.create, onUpdate: customStages.update }), _jsx(CustomStageDeleteDialog, { open: !!deletingStage, onOpenChange: (o) => {
|
|
687
843
|
if (!o)
|
|
688
844
|
setDeletingStage(null);
|
|
689
845
|
}, stage: deletingStage, reassignTargets: stages.map((s) => ({
|
|
@@ -718,9 +874,67 @@ function SheetFilterRow({ field, isStage, }) {
|
|
|
718
874
|
const summary = summarizeFilterValues(field.config.selectedValues, field.config.options);
|
|
719
875
|
return (_jsx(ColumnFilterControl, { variant: "row", align: "end", icon: filterTypeIcon(field.config.filterType, isStage), label: field.label, valueSummary: summary, filterKey: field.config.filterKey, filterType: field.config.filterType, filterOptions: field.config.options, filterLoading: field.config.loading, filterSearchEndpoint: field.config.searchEndpoint, selectedValues: field.config.selectedValues, onFilterChange: field.config.onFilterChange, loadOptions: field.config.loadOptions }));
|
|
720
876
|
}
|
|
721
|
-
|
|
877
|
+
// A real stage lane: sortable (header drag reorders) AND a card drop target.
|
|
878
|
+
// One `useSortable` provides both roles; `disabled.draggable` follows whether
|
|
879
|
+
// lane reordering is available, `disabled.droppable` follows the per-card
|
|
880
|
+
// transition gate.
|
|
881
|
+
function SortableStageLane({ reorderEnabled, droppableDisabled, laneProps, }) {
|
|
882
|
+
const { setNodeRef, setActivatorNodeRef, attributes, listeners, transform, transition, isDragging, isOver, } = useSortable({
|
|
883
|
+
id: laneProps.stage.key,
|
|
884
|
+
data: { type: 'lane' },
|
|
885
|
+
disabled: { draggable: !reorderEnabled, droppable: droppableDisabled },
|
|
886
|
+
});
|
|
887
|
+
const dnd = {
|
|
888
|
+
setNodeRef,
|
|
889
|
+
isOver,
|
|
890
|
+
isDragging,
|
|
891
|
+
draggable: reorderEnabled,
|
|
892
|
+
handleRef: setActivatorNodeRef,
|
|
893
|
+
handleProps: { ...attributes, ...listeners },
|
|
894
|
+
style: {
|
|
895
|
+
transform: CSS.Translate.toString(transform),
|
|
896
|
+
transition,
|
|
897
|
+
zIndex: isDragging ? 30 : undefined,
|
|
898
|
+
position: isDragging ? 'relative' : undefined,
|
|
899
|
+
},
|
|
900
|
+
};
|
|
901
|
+
return _jsx(KanbanLane, { ...laneProps, dnd: dnd });
|
|
902
|
+
}
|
|
903
|
+
// The synthetic "Sin etapa" lane: a card drop target, never draggable.
|
|
904
|
+
function DroppableStageLane({ droppableDisabled, laneProps, }) {
|
|
905
|
+
const { setNodeRef, isOver } = useDroppable({
|
|
906
|
+
id: laneProps.stage.key,
|
|
907
|
+
disabled: droppableDisabled,
|
|
908
|
+
});
|
|
909
|
+
return (_jsx(KanbanLane, { ...laneProps, dnd: { setNodeRef, isOver, draggable: false } }));
|
|
910
|
+
}
|
|
911
|
+
// A smart lane: sortable (header drag reorders) but NOT a card drop target — its
|
|
912
|
+
// droppable is disabled while a card is dragged, enabled while a lane is dragged
|
|
913
|
+
// (so a stage/smart lane can be reordered relative to it).
|
|
914
|
+
function SortableSmartLane({ droppableDisabled, smartProps, }) {
|
|
915
|
+
const { setNodeRef, setActivatorNodeRef, attributes, listeners, transform, transition, isDragging, } = useSortable({
|
|
916
|
+
id: smartProps.stage.key,
|
|
917
|
+
data: { type: 'lane' },
|
|
918
|
+
disabled: { draggable: false, droppable: droppableDisabled },
|
|
919
|
+
});
|
|
920
|
+
const dnd = {
|
|
921
|
+
setNodeRef,
|
|
922
|
+
isOver: false,
|
|
923
|
+
isDragging,
|
|
924
|
+
draggable: true,
|
|
925
|
+
handleRef: setActivatorNodeRef,
|
|
926
|
+
handleProps: { ...attributes, ...listeners },
|
|
927
|
+
style: {
|
|
928
|
+
transform: CSS.Translate.toString(transform),
|
|
929
|
+
transition,
|
|
930
|
+
zIndex: isDragging ? 30 : undefined,
|
|
931
|
+
position: isDragging ? 'relative' : undefined,
|
|
932
|
+
},
|
|
933
|
+
};
|
|
934
|
+
return _jsx(SmartLane, { ...smartProps, dnd: dnd });
|
|
935
|
+
}
|
|
936
|
+
function KanbanLane({ stage, count, totalCount, serverTotal, hasMore, loadingMore, onLoadMore, filterFields, laneFilter, onFunnelChange, onQueryChange, isDark, dimmed, dnd, model, columns, automationsAvailable, automationRules, onAutomationCreate, onAutomationUpdate, onAutomationRemove, customStage, onEditStage, onDeleteStage, children, }) {
|
|
722
937
|
const { t } = useTranslation();
|
|
723
|
-
const { setNodeRef, isOver } = useDroppable({ id: stage.key, disabled });
|
|
724
938
|
// Infinite scroll: the sentinel lives at the bottom of the lane's own scroll
|
|
725
939
|
// container; a load in flight or an exhausted stage disables it.
|
|
726
940
|
const { rootRef, sentinelRef } = useInfiniteScrollSentinel({
|
|
@@ -758,16 +972,17 @@ function KanbanLane({ stage, count, totalCount, serverTotal, hasMore, loadingMor
|
|
|
758
972
|
text: laneFilter.text,
|
|
759
973
|
}
|
|
760
974
|
: undefined;
|
|
761
|
-
return (_jsxs("div", { ref: setNodeRef,
|
|
975
|
+
return (_jsxs("div", { ref: dnd.setNodeRef,
|
|
762
976
|
// Fluid width: lanes grow (flex-1) to fill the board when they all
|
|
763
977
|
// fit, capped at max-w so a couple of lanes don't stretch absurdly
|
|
764
978
|
// wide. Below min-w the board's overflow-x-auto takes over and the
|
|
765
979
|
// lanes scroll horizontally at their minimum width.
|
|
766
980
|
className: "group/lane flex min-w-[280px] max-w-[420px] flex-1 shrink-0 flex-col rounded-xl border bg-muted/30 transition-opacity", style: {
|
|
767
|
-
opacity: dimmed ? 0.45 : 1,
|
|
768
|
-
outline: isOver
|
|
981
|
+
opacity: dnd.isDragging ? 0.6 : dimmed ? 0.45 : 1,
|
|
982
|
+
outline: dnd.isOver ? '2px solid var(--ring, #3b82f6)' : 'none',
|
|
769
983
|
outlineOffset: 2,
|
|
770
|
-
|
|
984
|
+
...dnd.style,
|
|
985
|
+
}, "data-stage": stage.key, children: [_jsxs("div", { className: "flex items-center justify-between gap-2 px-3 py-2.5", children: [_jsxs("div", { ref: dnd.draggable ? dnd.handleRef : undefined, ...(dnd.draggable ? dnd.handleProps : {}), className: `flex min-w-0 items-center gap-1.5 ${dnd.draggable ? 'cursor-grab active:cursor-grabbing' : ''}`, children: [dnd.draggable && (_jsx(GripVertical, { className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/40 opacity-0 transition-opacity group-hover/lane:opacity-70", "aria-hidden": true })), _jsx(Badge, { variant: "outline", className: "border-0 text-xs font-semibold", style: headerStyle, children: t(stage.label, { defaultValue: stage.label }) }), _jsx("span", { className: "text-xs font-medium tabular-nums text-muted-foreground", children: formatLaneCount(count, totalCount, serverTotal, laneActive) })] }), _jsxs("div", { className: "flex items-center gap-0.5", children: [_jsxs("button", { type: "button", onClick: () => setSearchOpen((o) => !o), className: `relative flex size-6 items-center justify-center rounded-md transition-colors hover:bg-accent hover:text-foreground ${queryActive ? 'text-primary' : 'text-muted-foreground'}`, "aria-label": t('kanban.searchLane', {
|
|
771
986
|
defaultValue: 'Buscar en la columna',
|
|
772
987
|
}), children: [_jsx(Search, { className: "h-3.5 w-3.5" }), queryActive && (_jsx("span", { className: "absolute -right-0.5 -top-0.5 size-1.5 rounded-full bg-primary" }))] }), _jsx(LaneFilterButton, { fields: filterFields, value: funnelValue, onChange: onFunnelChange }), automationsAvailable && (_jsx(StageAutomationsButton, { model: model, stageKey: stage.key, stageLabel: stage.label, columns: columns, rules: automationRules, onCreate: onAutomationCreate, onUpdate: onAutomationUpdate, onRemove: onAutomationRemove })), customStage && onEditStage && onDeleteStage && (_jsx(CustomStageLaneMenu, { stage: customStage, onEdit: onEditStage, onDelete: onDeleteStage }))] })] }), searchOpen && (_jsx("div", { className: "px-3 pb-1.5", children: _jsxs("div", { className: "relative", children: [_jsx(Search, { className: "pointer-events-none absolute left-2 top-1/2 h-3 w-3 -translate-y-1/2 text-muted-foreground" }), _jsx(Input, { ref: searchRef, value: laneFilter?.query ?? '', onChange: (e) => onQueryChange(e.target.value), onKeyDown: (e) => {
|
|
773
988
|
if (e.key === 'Escape') {
|
|
@@ -844,6 +1059,7 @@ function LaneFilterButton({ fields, value, onChange, }) {
|
|
|
844
1059
|
function KanbanCard({ card, titleCol, fieldCols, actions, locale, timeZone, currency, onClick, onAction, draggable = true, }) {
|
|
845
1060
|
const { attributes, listeners, setNodeRef, isDragging } = useDraggable({
|
|
846
1061
|
id: String(card.id),
|
|
1062
|
+
data: { type: 'card' },
|
|
847
1063
|
disabled: !draggable,
|
|
848
1064
|
});
|
|
849
1065
|
const visibleActions = actions.filter((a) => isRowActionVisible(a, card));
|
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export * from './dynamic-table';
|
|
|
4
4
|
export { DynamicKanban, type DynamicKanbanProps, deriveStages, groupByStage, isTransitionAllowed, applyOptimisticMove, selectCardColumns, UNASSIGNED_LANE, } from './dynamic-kanban';
|
|
5
5
|
export { useStageAutomations, StageAutomationsButton, isTagColumn, automationFieldOptions, groupAutomationsByStage, activeAutomationCount, type StageAutomation, type StageAutomationAction, type StageAutomationActionType, type NewStageAutomation, type UseStageAutomationsResult, type StageAutomationsButtonProps, } from './stage-automations';
|
|
6
6
|
export { useCustomStages, splitCustomStages, mergeLaneStages, resolveSmartLanes, smartLaneParams, customStageFilterFields, isCustomStageDraftValid, slugifyStageKey, emptyCustomStageFilter, AddStageColumn, CustomStageLaneMenu, CustomStageDialog, CustomStageDeleteDialog, SmartLane, CUSTOM_STAGE_COLORS, CUSTOM_STAGE_FILTER_OPS, type CustomStage, type NewCustomStage, type CustomStageType, type CustomStageFilter, type CustomStageFilterOp, type UseCustomStagesResult, } from './custom-stages';
|
|
7
|
+
export { useStageLayout, type StageLayout, type UseStageLayoutResult, } from './stage-layout';
|
|
7
8
|
export { DynamicView, resolveViewRenderer, readViewFromSearch, resolveActiveView, type DynamicViewProps, } from './dynamic-view';
|
|
8
9
|
export { useDynamicFilters, type UseDynamicFiltersOptions, type UseDynamicFiltersResult, } from './use-dynamic-filters';
|
|
9
10
|
export * from './dynamic-form';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -9,6 +9,7 @@ export * from './dynamic-table';
|
|
|
9
9
|
export { DynamicKanban, deriveStages, groupByStage, isTransitionAllowed, applyOptimisticMove, selectCardColumns, UNASSIGNED_LANE, } from './dynamic-kanban';
|
|
10
10
|
export { useStageAutomations, StageAutomationsButton, isTagColumn, automationFieldOptions, groupAutomationsByStage, activeAutomationCount, } from './stage-automations';
|
|
11
11
|
export { useCustomStages, splitCustomStages, mergeLaneStages, resolveSmartLanes, smartLaneParams, customStageFilterFields, isCustomStageDraftValid, slugifyStageKey, emptyCustomStageFilter, AddStageColumn, CustomStageLaneMenu, CustomStageDialog, CustomStageDeleteDialog, SmartLane, CUSTOM_STAGE_COLORS, CUSTOM_STAGE_FILTER_OPS, } from './custom-stages';
|
|
12
|
+
export { useStageLayout, } from './stage-layout';
|
|
12
13
|
export { DynamicView, resolveViewRenderer, readViewFromSearch, resolveActiveView, } from './dynamic-view';
|
|
13
14
|
export { useDynamicFilters, } from './use-dynamic-filters';
|
|
14
15
|
export * from './dynamic-form';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface StageLayout {
|
|
2
|
+
model: string;
|
|
3
|
+
/** The full lane order — every lane key (stages + smart lanes) in order. */
|
|
4
|
+
stage_order: string[];
|
|
5
|
+
}
|
|
6
|
+
export interface UseStageLayoutResult {
|
|
7
|
+
/** True only after a successful GET — gates the lane drag + reset affordance. */
|
|
8
|
+
available: boolean;
|
|
9
|
+
/** True when a custom order is stored server-side (drives the reset affordance). */
|
|
10
|
+
hasCustomLayout: boolean;
|
|
11
|
+
/** Persist the full lane order (the new order of every lane key). Throws on failure. */
|
|
12
|
+
save: (order: string[]) => Promise<void>;
|
|
13
|
+
/** Drop the stored order, reverting to the declared stage order. */
|
|
14
|
+
reset: () => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Loads a model's saved lane order (only to learn availability + whether a
|
|
18
|
+
* custom order exists) and exposes save/reset. A missing endpoint degrades to
|
|
19
|
+
* `available: false` so the board's lane drag stays off; a real save failure
|
|
20
|
+
* re-throws so the caller can revert its optimistic reorder.
|
|
21
|
+
*/
|
|
22
|
+
export declare function useStageLayout(model: string): UseStageLayoutResult;
|
|
23
|
+
//# sourceMappingURL=stage-layout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage-layout.d.ts","sourceRoot":"","sources":["../src/stage-layout.ts"],"names":[],"mappings":"AAkBA,MAAM,WAAW,WAAW;IACxB,KAAK,EAAE,MAAM,CAAA;IACb,4EAA4E;IAC5E,WAAW,EAAE,MAAM,EAAE,CAAA;CACxB;AAED,MAAM,WAAW,oBAAoB;IACjC,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAA;IAClB,oFAAoF;IACpF,eAAe,EAAE,OAAO,CAAA;IACxB,wFAAwF;IACxF,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxC,oEAAoE;IACpE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAC7B;AAQD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,oBAAoB,CA6ClE"}
|