@asteby/metacore-runtime-react 39.1.0 → 39.2.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/dist/index.d.ts CHANGED
@@ -33,6 +33,8 @@ export { PermissionsProvider, useCan, usePermissionsActive, makeCan, capabilityF
33
33
  export { useDynamicRowActions, type UseDynamicRowActionsParams, type DynamicRowActions, } from './dynamic-row-actions';
34
34
  export { ColorPickerField, DEFAULT_ROLE_COLOR, normalizeHex } from './color-picker-field';
35
35
  export { PermissionsManager, moduleActionCapability, moduleCapabilities, grantedCountForModule, capabilitySetsEqual, defaultActionIcon, suggestRoleIcon, normalizeCatalogGroups, flattenGroups, filterModuleGroups, groupModuleActions, type PermissionsManagerProps, type PermissionsCatalog, type GroupedPermissionsCatalog, type FlatPermissionsCatalog, type ModuleGroup, type PermissionModuleDef, type PermissionActionDef, type GeneralPermissionDef, type RoleDef, type RoleInput, } from './permissions-manager';
36
+ export { applySidebarLayout, collectFolderKeys, folderAccessCapability, coreRefKey, addonModelRefKey, addonUrlRefKey, urlRefKey, leafRefFor, normalizeNavPath, slugifyFolderKey, isValidFolderKey, layoutTreeFromNavGroups, type CatalogLeaf, type SidebarLayoutDoc, type SidebarLayoutNode, type AppliedNavGroup, type AppliedNavItem, } from './apply-sidebar-layout';
37
+ export { SidebarLayoutManager, type SidebarLayoutManagerProps, } from './sidebar-layout-manager';
36
38
  export * from './org-runtime-context';
37
39
  export * from './org-runtime-provider';
38
40
  export * from './navigation-builder';
@@ -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
@@ -38,6 +38,8 @@ export { PermissionsProvider, useCan, usePermissionsActive, makeCan, capabilityF
38
38
  export { useDynamicRowActions, } from './dynamic-row-actions';
39
39
  export { ColorPickerField, DEFAULT_ROLE_COLOR, normalizeHex } from './color-picker-field';
40
40
  export { PermissionsManager, moduleActionCapability, moduleCapabilities, grantedCountForModule, capabilitySetsEqual, defaultActionIcon, suggestRoleIcon, normalizeCatalogGroups, flattenGroups, filterModuleGroups, groupModuleActions, } from './permissions-manager';
41
+ export { applySidebarLayout, collectFolderKeys, folderAccessCapability, coreRefKey, addonModelRefKey, addonUrlRefKey, urlRefKey, leafRefFor, normalizeNavPath, slugifyFolderKey, isValidFolderKey, layoutTreeFromNavGroups, } from './apply-sidebar-layout';
42
+ export { SidebarLayoutManager, } from './sidebar-layout-manager';
41
43
  export * from './org-runtime-context';
42
44
  export * from './org-runtime-provider';
43
45
  export * from './navigation-builder';
@@ -0,0 +1,36 @@
1
+ /**
2
+ * SidebarLayoutManager — admin editor for the org-wide sidebar overlay.
3
+ * Transport-agnostic (loaders/mutators via props), same pattern as
4
+ * PermissionsManager. Hosts wire fetchers to /api/org/sidebar-layout.
5
+ */
6
+ import * as React from 'react';
7
+ import { type CatalogLeaf, type SidebarLayoutDoc, type SidebarLayoutNode } from './apply-sidebar-layout';
8
+ export interface SidebarLayoutManagerProps {
9
+ loadLayout: () => Promise<SidebarLayoutDoc>;
10
+ saveLayout: (doc: SidebarLayoutDoc) => Promise<void>;
11
+ resetLayout: () => Promise<void>;
12
+ /** Live catalog of every leaf the shell can show (core + addons). */
13
+ catalog: CatalogLeaf[];
14
+ /**
15
+ * Optional: current live nav groups — used by "Partir del menú actual" to
16
+ * seed a tree when the org has no layout yet.
17
+ */
18
+ currentGroups?: Array<{
19
+ title: string;
20
+ items: Array<{
21
+ title: string;
22
+ url: string;
23
+ icon?: string;
24
+ items?: Array<{
25
+ title: string;
26
+ url: string;
27
+ icon?: string;
28
+ }>;
29
+ }>;
30
+ }>;
31
+ title?: string;
32
+ description?: string;
33
+ }
34
+ export declare function SidebarLayoutManager({ loadLayout, saveLayout, resetLayout, catalog, currentGroups, title, description, }: SidebarLayoutManagerProps): React.JSX.Element;
35
+ export type { CatalogLeaf, SidebarLayoutDoc, SidebarLayoutNode };
36
+ //# sourceMappingURL=sidebar-layout-manager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidebar-layout-manager.d.ts","sourceRoot":"","sources":["../src/sidebar-layout-manager.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AA2B9B,OAAO,EAML,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACvB,MAAM,wBAAwB,CAAA;AAE/B,MAAM,WAAW,yBAAyB;IACxC,UAAU,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,CAAA;IAC3C,UAAU,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACpD,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAChC,qEAAqE;IACrE,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB;;;OAGG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC;QACpB,KAAK,EAAE,MAAM,CAAA;QACb,KAAK,EAAE,KAAK,CAAC;YACX,KAAK,EAAE,MAAM,CAAA;YACb,GAAG,EAAE,MAAM,CAAA;YACX,IAAI,CAAC,EAAE,MAAM,CAAA;YACb,KAAK,CAAC,EAAE,KAAK,CAAC;gBAAE,KAAK,EAAE,MAAM,CAAC;gBAAC,GAAG,EAAE,MAAM,CAAC;gBAAC,IAAI,CAAC,EAAE,MAAM,CAAA;aAAE,CAAC,CAAA;SAC7D,CAAC,CAAA;KACH,CAAC,CAAA;IACF,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB;AAmED,wBAAgB,oBAAoB,CAAC,EACnC,UAAU,EACV,UAAU,EACV,WAAW,EACX,OAAO,EACP,aAAa,EACb,KAAsB,EACtB,WAAsI,GACvI,EAAE,yBAAyB,qBA4X3B;AAED,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,CAAA"}
@@ -0,0 +1,204 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * SidebarLayoutManager — admin editor for the org-wide sidebar overlay.
4
+ * Transport-agnostic (loaders/mutators via props), same pattern as
5
+ * PermissionsManager. Hosts wire fetchers to /api/org/sidebar-layout.
6
+ */
7
+ import * as React from 'react';
8
+ import { ChevronDown, ChevronRight, FolderPlus, GripVertical, RotateCcw, Save, Trash2, Eye, EyeOff, Folder, FileText, } from 'lucide-react';
9
+ import { toast } from 'sonner';
10
+ import { Button, Card, CardContent, CardDescription, CardHeader, CardTitle, Input, Label, ScrollArea, Badge, } from '@asteby/metacore-ui/primitives';
11
+ import { applySidebarLayout, collectFolderKeys, folderAccessCapability, layoutTreeFromNavGroups, slugifyFolderKey, } from './apply-sidebar-layout';
12
+ function collectUsedRefs(tree) {
13
+ const used = new Set();
14
+ const walk = (nodes) => {
15
+ for (const n of nodes) {
16
+ if (n.type === 'leaf' && n.ref)
17
+ used.add(n.ref);
18
+ if (n.children)
19
+ walk(n.children);
20
+ }
21
+ };
22
+ walk(tree);
23
+ return used;
24
+ }
25
+ function updateAt(tree, path, fn) {
26
+ if (path.length === 0)
27
+ return tree;
28
+ const [head, ...rest] = path;
29
+ return tree
30
+ .map((n, i) => {
31
+ if (i !== head)
32
+ return n;
33
+ if (rest.length === 0)
34
+ return fn(n);
35
+ const kids = updateAt(n.children ?? [], rest, fn);
36
+ return { ...n, children: kids };
37
+ })
38
+ .filter((n) => n != null);
39
+ }
40
+ function removeAt(tree, path) {
41
+ return updateAt(tree, path, () => null).filter(Boolean);
42
+ }
43
+ function moveSibling(tree, path, dir) {
44
+ if (path.length === 0)
45
+ return tree;
46
+ const parentPath = path.slice(0, -1);
47
+ const idx = path[path.length - 1];
48
+ const getList = (nodes, p) => {
49
+ if (p.length === 0)
50
+ return nodes;
51
+ let cur = nodes;
52
+ for (const i of p) {
53
+ cur = cur[i]?.children ?? [];
54
+ }
55
+ return cur;
56
+ };
57
+ const list = [...getList(tree, parentPath)];
58
+ const j = idx + dir;
59
+ if (j < 0 || j >= list.length)
60
+ return tree;
61
+ [list[idx], list[j]] = [list[j], list[idx]];
62
+ if (parentPath.length === 0)
63
+ return list;
64
+ return updateAt(tree, parentPath, (n) => ({ ...n, children: list }));
65
+ }
66
+ function appendChild(tree, parentPath, child) {
67
+ if (parentPath.length === 0)
68
+ return [...tree, child];
69
+ return updateAt(tree, parentPath, (n) => ({
70
+ ...n,
71
+ children: [...(n.children ?? []), child],
72
+ }));
73
+ }
74
+ export function SidebarLayoutManager({ loadLayout, saveLayout, resetLayout, catalog, currentGroups, title = 'Menú lateral', description = 'Organizá carpetas y el orden del sidebar para toda la organización. Los permisos de cada carpeta aparecen en Permisos.', }) {
75
+ const [tree, setTree] = React.useState([]);
76
+ const [baseline, setBaseline] = React.useState('[]');
77
+ const [loading, setLoading] = React.useState(true);
78
+ const [saving, setSaving] = React.useState(false);
79
+ const [newFolderTitle, setNewFolderTitle] = React.useState('');
80
+ const [expanded, setExpanded] = React.useState({});
81
+ const reload = React.useCallback(async () => {
82
+ setLoading(true);
83
+ try {
84
+ const doc = await loadLayout();
85
+ const t = doc.tree ?? [];
86
+ setTree(t);
87
+ setBaseline(JSON.stringify(t));
88
+ }
89
+ catch (e) {
90
+ toast.error(e instanceof Error ? e.message : 'No se pudo cargar el layout');
91
+ }
92
+ finally {
93
+ setLoading(false);
94
+ }
95
+ }, [loadLayout]);
96
+ React.useEffect(() => {
97
+ void reload();
98
+ }, [reload]);
99
+ const dirty = JSON.stringify(tree) !== baseline;
100
+ const used = React.useMemo(() => collectUsedRefs(tree), [tree]);
101
+ const unused = React.useMemo(() => catalog.filter((l) => !used.has(l.ref) && !(l.aliases ?? []).some((a) => used.has(a))), [catalog, used]);
102
+ const folderKeys = React.useMemo(() => collectFolderKeys(tree), [tree]);
103
+ const preview = React.useMemo(() => applySidebarLayout(catalog, tree), [catalog, tree]);
104
+ const pathKey = (path) => path.join('.');
105
+ const handleSave = async () => {
106
+ setSaving(true);
107
+ try {
108
+ await saveLayout({ version: 1, tree });
109
+ setBaseline(JSON.stringify(tree));
110
+ toast.success('Menú guardado para toda la organización');
111
+ }
112
+ catch (e) {
113
+ toast.error(e instanceof Error ? e.message : 'Error al guardar');
114
+ }
115
+ finally {
116
+ setSaving(false);
117
+ }
118
+ };
119
+ const handleReset = async () => {
120
+ setSaving(true);
121
+ try {
122
+ await resetLayout();
123
+ setTree([]);
124
+ setBaseline('[]');
125
+ toast.success('Menú restaurado al default (addons + core)');
126
+ }
127
+ catch (e) {
128
+ toast.error(e instanceof Error ? e.message : 'Error al resetear');
129
+ }
130
+ finally {
131
+ setSaving(false);
132
+ }
133
+ };
134
+ const seedFromCurrent = () => {
135
+ if (!currentGroups?.length) {
136
+ toast.message('No hay menú actual para copiar');
137
+ return;
138
+ }
139
+ const seeded = layoutTreeFromNavGroups(currentGroups);
140
+ setTree(seeded);
141
+ toast.message('Árbol partido del menú actual — guardá para aplicar');
142
+ };
143
+ const addRootFolder = () => {
144
+ const titleText = newFolderTitle.trim() || 'Nueva carpeta';
145
+ const key = slugifyFolderKey(titleText);
146
+ setTree((t) => [
147
+ ...t,
148
+ {
149
+ type: 'group',
150
+ key: `group_${key}`,
151
+ title: titleText,
152
+ children: [{ type: 'folder', key, title: titleText, icon: 'Folder', children: [] }],
153
+ },
154
+ ]);
155
+ setNewFolderTitle('');
156
+ };
157
+ const addLeafTo = (parentPath, leaf) => {
158
+ setTree((t) => appendChild(t, parentPath, {
159
+ type: 'leaf',
160
+ ref: leaf.ref,
161
+ title: leaf.title,
162
+ icon: leaf.icon,
163
+ }));
164
+ };
165
+ const renderNode = (node, path) => {
166
+ const k = pathKey(path);
167
+ const isOpen = expanded[k] ?? true;
168
+ const isFolderish = node.type === 'group' || node.type === 'folder';
169
+ return (_jsxs("div", { className: "border-border/60 rounded-md border bg-background/50", children: [_jsxs("div", { className: "flex items-center gap-1 px-2 py-1.5", children: [isFolderish ? (_jsx("button", { type: "button", className: "text-muted-foreground hover:text-foreground p-0.5", onClick: () => setExpanded((e) => ({ ...e, [k]: !isOpen })), children: isOpen ? _jsx(ChevronDown, { className: "size-4" }) : _jsx(ChevronRight, { className: "size-4" }) })) : (_jsx(GripVertical, { className: "text-muted-foreground size-4 shrink-0 opacity-40" })), node.type === 'folder' ? (_jsx(Folder, { className: "text-amber-600 size-4 shrink-0" })) : node.type === 'leaf' ? (_jsx(FileText, { className: "text-muted-foreground size-4 shrink-0" })) : null, _jsx("span", { className: "min-w-0 flex-1 truncate text-sm font-medium", children: node.title || node.key || node.ref }), node.type === 'folder' && node.key ? (_jsx(Badge, { variant: "outline", className: "font-mono text-[10px]", children: folderAccessCapability(node.key) })) : null, _jsx(Button, { type: "button", size: "icon", variant: "ghost", className: "size-7", title: node.hidden ? 'Mostrar' : 'Ocultar', onClick: () => setTree((t) => updateAt(t, path, (n) => ({ ...n, hidden: !n.hidden }))), children: node.hidden ? _jsx(EyeOff, { className: "size-3.5" }) : _jsx(Eye, { className: "size-3.5" }) }), _jsx(Button, { type: "button", size: "icon", variant: "ghost", className: "size-7", onClick: () => setTree((t) => moveSibling(t, path, -1)), children: "\u2191" }), _jsx(Button, { type: "button", size: "icon", variant: "ghost", className: "size-7", onClick: () => setTree((t) => moveSibling(t, path, 1)), children: "\u2193" }), _jsx(Button, { type: "button", size: "icon", variant: "ghost", className: "text-destructive size-7", onClick: () => setTree((t) => removeAt(t, path)), children: _jsx(Trash2, { className: "size-3.5" }) })] }), isFolderish && isOpen ? (_jsxs("div", { className: "border-border/40 space-y-1 border-t px-2 py-2 pl-6", children: [(node.children ?? []).map((child, i) => renderNode(child, [...path, i])), unused.length > 0 ? (_jsxs("select", { className: "border-input bg-background w-full rounded-md border px-2 py-1 text-xs", defaultValue: "", onChange: (e) => {
170
+ const ref = e.target.value;
171
+ e.target.value = '';
172
+ const leaf = catalog.find((l) => l.ref === ref);
173
+ if (leaf)
174
+ addLeafTo(path, leaf);
175
+ }, children: [_jsx("option", { value: "", children: "+ Agregar \u00EDtem\u2026" }), unused.map((l) => (_jsxs("option", { value: l.ref, children: [l.title, " (", l.ref, ")"] }, l.ref)))] })) : null, node.type === 'group' ? (_jsxs(Button, { type: "button", size: "sm", variant: "outline", className: "h-7 text-xs", onClick: () => {
176
+ const titleText = 'Nueva carpeta';
177
+ const key = slugifyFolderKey(`${titleText}_${path.join('')}_${Date.now() % 1000}`);
178
+ setTree((t) => appendChild(t, path, {
179
+ type: 'folder',
180
+ key,
181
+ title: titleText,
182
+ icon: 'Folder',
183
+ children: [],
184
+ }));
185
+ }, children: [_jsx(FolderPlus, { className: "mr-1 size-3.5" }), "Subcarpeta"] })) : null] })) : null] }, k));
186
+ };
187
+ return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-start justify-between gap-3", children: [_jsxs("div", { className: "space-y-1", children: [_jsx("h2", { className: "text-xl font-semibold tracking-tight", children: title }), _jsx("p", { className: "text-muted-foreground max-w-2xl text-sm", children: description })] }), _jsxs("div", { className: "flex flex-wrap gap-2", children: [_jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: seedFromCurrent, children: "Partir del men\u00FA actual" }), _jsxs(Button, { type: "button", variant: "outline", size: "sm", disabled: saving, onClick: () => void handleReset(), children: [_jsx(RotateCcw, { className: "mr-1 size-3.5" }), "Restaurar default"] }), _jsxs(Button, { type: "button", size: "sm", disabled: !dirty || saving, onClick: () => void handleSave(), children: [_jsx(Save, { className: "mr-1 size-3.5" }), saving ? 'Guardando…' : dirty ? 'Guardar' : 'Guardado'] })] })] }), loading ? (_jsx("p", { className: "text-muted-foreground text-sm", children: "Cargando\u2026" })) : (_jsxs("div", { className: "grid gap-4 lg:grid-cols-2", children: [_jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-base", children: "\u00C1rbol del men\u00FA" }), _jsxs(CardDescription, { children: ["Carpetas nuevas otorgan el permiso", ' ', _jsx("code", { className: "text-xs", children: "folder.<key>.access" }), "."] })] }), _jsxs(CardContent, { className: "space-y-3", children: [_jsxs("div", { className: "flex gap-2", children: [_jsxs("div", { className: "flex-1 space-y-1", children: [_jsx(Label, { className: "text-xs", children: "Nueva secci\u00F3n + carpeta" }), _jsx(Input, { value: newFolderTitle, onChange: (e) => setNewFolderTitle(e.target.value), placeholder: "Configuraci\u00F3n" })] }), _jsxs(Button, { type: "button", className: "mt-5", size: "sm", onClick: addRootFolder, children: [_jsx(FolderPlus, { className: "mr-1 size-3.5" }), "Crear"] })] }), _jsx(ScrollArea, { className: "h-[420px] pr-2", children: _jsx("div", { className: "space-y-2", children: tree.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-sm", children: "Sin overlay \u2014 el sidebar usa el merge default. Part\u00ED del men\u00FA actual o cre\u00E1 una carpeta." })) : (tree.map((n, i) => renderNode(n, [i]))) }) }), folderKeys.length > 0 ? (_jsxs("p", { className: "text-muted-foreground text-xs", children: ["Carpetas con permiso: ", folderKeys.map((k) => folderAccessCapability(k)).join(', ')] })) : null] })] }), _jsxs(Card, { children: [_jsxs(CardHeader, { className: "pb-3", children: [_jsx(CardTitle, { className: "text-base", children: "Cat\u00E1logo sin usar / vista previa" }), _jsx(CardDescription, { children: "\u00CDtems disponibles para colocar. La vista previa aplica el overlay sobre el cat\u00E1logo vivo." })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsx(ScrollArea, { className: "h-[200px] rounded-md border p-2", children: unused.length === 0 ? (_jsx("p", { className: "text-muted-foreground text-xs", children: "Todos los \u00EDtems est\u00E1n en el \u00E1rbol." })) : (_jsx("ul", { className: "space-y-1", children: unused.map((l) => (_jsxs("li", { className: "flex items-center justify-between gap-2 text-xs", children: [_jsxs("span", { className: "truncate", children: [l.title, ' ', _jsx("span", { className: "text-muted-foreground font-mono", children: l.ref })] }), _jsx(Button, { type: "button", size: "sm", variant: "ghost", className: "h-6 shrink-0 text-xs", onClick: () => {
188
+ if (tree.length === 0) {
189
+ setTree([
190
+ {
191
+ type: 'group',
192
+ key: 'sidebar.general',
193
+ title: 'sidebar.general',
194
+ children: [
195
+ { type: 'leaf', ref: l.ref, title: l.title, icon: l.icon },
196
+ ],
197
+ },
198
+ ]);
199
+ }
200
+ else {
201
+ addLeafTo([0], l);
202
+ }
203
+ }, children: "+" })] }, l.ref))) })) }), _jsxs("div", { children: [_jsx("p", { className: "mb-2 text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Preview" }), !preview ? (_jsx("p", { className: "text-muted-foreground text-sm", children: "Default merge (sin overlay)." })) : (_jsx("ul", { className: "space-y-2 text-sm", children: preview.map((g) => (_jsxs("li", { children: [_jsx("div", { className: "text-muted-foreground text-xs font-semibold uppercase tracking-wide", children: g.title }), _jsx("ul", { className: "mt-1 space-y-0.5 pl-2", children: g.items.map((it) => (_jsxs("li", { children: [it.folderKey ? `📁 ${it.title}` : it.title, it.items?.length ? (_jsx("ul", { className: "text-muted-foreground pl-4 text-xs", children: it.items.map((c) => (_jsx("li", { children: c.title }, c.ref || c.url))) })) : null] }, `${it.title}-${it.url}`))) })] }, g.title))) }))] })] })] })] }))] }));
204
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asteby/metacore-runtime-react",
3
- "version": "39.1.0",
3
+ "version": "39.2.0",
4
4
  "description": "React runtime for metacore hosts — renders addon contributions dynamically",
5
5
  "repository": {
6
6
  "type": "git",
@@ -26,6 +26,8 @@
26
26
  "zod": "^4.3.0"
27
27
  },
28
28
  "peerDependencies": {
29
+ "@asteby/metacore-sdk": "^3.8.0",
30
+ "@asteby/metacore-ui": "^2.18.1",
29
31
  "@tanstack/react-query": ">=5",
30
32
  "@tanstack/react-router": ">=1.100",
31
33
  "@tanstack/react-table": ">=8",
@@ -37,9 +39,7 @@
37
39
  "react-dom": ">=18",
38
40
  "react-i18next": ">=13",
39
41
  "sonner": ">=1.7",
40
- "zustand": ">=5",
41
- "@asteby/metacore-sdk": "^3.8.0",
42
- "@asteby/metacore-ui": "^2.18.1"
42
+ "zustand": ">=5"
43
43
  },
44
44
  "peerDependenciesMeta": {
45
45
  "@tanstack/react-router": {
@@ -50,6 +50,8 @@
50
50
  }
51
51
  },
52
52
  "devDependencies": {
53
+ "@asteby/metacore-sdk": "3.8.0",
54
+ "@asteby/metacore-ui": "2.18.1",
53
55
  "@tanstack/react-query": "^5.95.0",
54
56
  "@tanstack/react-router": "^1.168.0",
55
57
  "@tanstack/react-table": "^8.20.0",
@@ -67,9 +69,7 @@
67
69
  "tsx": "^4.21.0",
68
70
  "typescript": "^6.0.0",
69
71
  "vitest": "^4.0.0",
70
- "zustand": "^5.0.0",
71
- "@asteby/metacore-sdk": "3.8.0",
72
- "@asteby/metacore-ui": "2.18.1"
72
+ "zustand": "^5.0.0"
73
73
  },
74
74
  "scripts": {
75
75
  "build": "tsc -p tsconfig.json",
@@ -0,0 +1,74 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import {
3
+ applySidebarLayout,
4
+ coreRefKey,
5
+ folderAccessCapability,
6
+ leafRefFor,
7
+ slugifyFolderKey,
8
+ type CatalogLeaf,
9
+ type SidebarLayoutNode,
10
+ } from './apply-sidebar-layout'
11
+
12
+ describe('applySidebarLayout', () => {
13
+ const catalog: CatalogLeaf[] = [
14
+ { ref: coreRefKey('/'), title: 'Dashboard', url: '/' },
15
+ { ref: 'addon:crm/model:prices', title: 'Precios', url: '/m/prices', aliases: ['url:/m/prices'] },
16
+ { ref: coreRefKey('/organization'), title: 'Org', url: '/organization' },
17
+ ]
18
+
19
+ it('returns null for empty tree', () => {
20
+ expect(applySidebarLayout(catalog, [])).toBeNull()
21
+ })
22
+
23
+ it('moves prices under a configuration folder', () => {
24
+ const tree: SidebarLayoutNode[] = [
25
+ {
26
+ type: 'group',
27
+ title: 'Sistema',
28
+ children: [
29
+ {
30
+ type: 'folder',
31
+ key: 'configuracion',
32
+ title: 'Configuración',
33
+ children: [
34
+ { type: 'leaf', ref: coreRefKey('/organization') },
35
+ { type: 'leaf', ref: 'addon:crm/model:prices' },
36
+ ],
37
+ },
38
+ ],
39
+ },
40
+ ]
41
+ const groups = applySidebarLayout(catalog, tree)
42
+ expect(groups).toHaveLength(1)
43
+ expect(groups![0].items[0].folderKey).toBe('configuracion')
44
+ expect(groups![0].items[0].items?.map((i) => i.url)).toEqual([
45
+ '/organization',
46
+ '/m/prices',
47
+ ])
48
+ })
49
+
50
+ it('resolves url: alias', () => {
51
+ const tree: SidebarLayoutNode[] = [
52
+ {
53
+ type: 'group',
54
+ title: 'G',
55
+ children: [{ type: 'leaf', ref: 'url:/m/prices' }],
56
+ },
57
+ ]
58
+ const groups = applySidebarLayout(catalog, tree)
59
+ expect(groups![0].items[0].url).toBe('/m/prices')
60
+ })
61
+ })
62
+
63
+ describe('helpers', () => {
64
+ it('slugifies folder keys', () => {
65
+ expect(slugifyFolderKey('Mi Config')).toBe('mi_config')
66
+ })
67
+ it('folder capability', () => {
68
+ expect(folderAccessCapability('configuracion')).toBe('folder.configuracion.access')
69
+ })
70
+ it('leafRefFor model pages', () => {
71
+ expect(leafRefFor('/m/prices')).toBe('url:/m/prices')
72
+ expect(leafRefFor('/organization')).toBe('core:/organization')
73
+ })
74
+ })
@@ -0,0 +1,67 @@
1
+ // @vitest-environment happy-dom
2
+ //
3
+ // Un 403 en el endpoint de lista NO debe verse como "sin resultados": se
4
+ // muestra "Sin permiso para ver este módulo" y no hay bucle de refetch.
5
+ import { afterEach, describe, expect, it, vi } from 'vitest'
6
+ import { cleanup, render, screen } from '@testing-library/react'
7
+
8
+ vi.mock('@tanstack/react-router', () => ({ useNavigate: () => () => {} }))
9
+
10
+ import { ApiProvider, type ApiClient } from '../api-context'
11
+ import { useMetadataCache } from '../metadata-cache'
12
+ import { DynamicCRUDPage } from '../dynamic-crud-page'
13
+ import type { TableMetadata } from '../types'
14
+
15
+ afterEach(cleanup)
16
+
17
+ const meta = {
18
+ title: 'Ajustes',
19
+ endpoint: '/data/stock_adjustments',
20
+ columns: [],
21
+ actions: [],
22
+ perPageOptions: [10],
23
+ defaultPerPage: 10,
24
+ searchPlaceholder: 'Buscar...',
25
+ enableCRUDActions: false,
26
+ hasActions: false,
27
+ } as unknown as TableMetadata
28
+
29
+ function mount(listBehavior: 'forbidden' | 'empty', model: string) {
30
+ useMetadataCache.getState().setMetadata(model, meta)
31
+ let listCalls = 0
32
+ const client: ApiClient = {
33
+ get: vi.fn(async (url: string) => {
34
+ if (url.startsWith('/metadata/table/')) return { data: { success: true, data: meta } }
35
+ listCalls++
36
+ if (listBehavior === 'forbidden') {
37
+ throw Object.assign(new Error('403'), { response: { status: 403 } })
38
+ }
39
+ return { data: { success: true, data: [], meta: { total: 0 } } }
40
+ }),
41
+ post: vi.fn(async () => ({ data: { success: true, data: null } })),
42
+ put: vi.fn(async () => ({ data: { success: true, data: null } })),
43
+ delete: vi.fn(async () => ({ data: { success: true, data: null } })),
44
+ }
45
+ render(
46
+ <ApiProvider client={client}>
47
+ <DynamicCRUDPage model={model} />
48
+ </ApiProvider>,
49
+ )
50
+ return () => listCalls
51
+ }
52
+
53
+ describe('DynamicTable — 403 en la lista', () => {
54
+ it('muestra "Sin permiso" y no "No se encontraron resultados"', async () => {
55
+ const calls = mount('forbidden', 'forb_a')
56
+ expect((await screen.findAllByText('Sin permiso para ver este módulo')).length).toBeGreaterThan(0)
57
+ expect(screen.queryByText('No se encontraron resultados')).toBeNull()
58
+ await new Promise((r) => setTimeout(r, 200))
59
+ expect(calls()).toBeLessThanOrEqual(2) // sin bucle de refetch
60
+ })
61
+
62
+ it('lista vacía real sigue diciendo "No se encontraron resultados"', async () => {
63
+ mount('empty', 'forb_b')
64
+ expect((await screen.findAllByText('No se encontraron resultados')).length).toBeGreaterThan(0)
65
+ expect(screen.queryByText('Sin permiso para ver este módulo')).toBeNull()
66
+ })
67
+ })