@asteby/metacore-runtime-react 29.2.16 → 30.0.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,18 @@
|
|
|
1
1
|
# @asteby/metacore-runtime-react
|
|
2
2
|
|
|
3
|
+
## 30.0.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0016511: PermissionActionDef.capability: atajos cross-módulo en el grid de permisos
|
|
8
|
+
|
|
9
|
+
## 30.0.0
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [30fe202]
|
|
14
|
+
- @asteby/metacore-ui@2.14.0
|
|
15
|
+
|
|
3
16
|
## 29.2.16
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
|
@@ -9,8 +9,17 @@ export interface PermissionActionDef {
|
|
|
9
9
|
/**
|
|
10
10
|
* `crud` for the derived CRUD set, `custom` for manifest actions,
|
|
11
11
|
* `screen` for the single `access` action of a non-model screen.
|
|
12
|
+
* `dependency` for a shortcut to another module's capability (see
|
|
13
|
+
* {@link capability}).
|
|
12
14
|
*/
|
|
13
|
-
kind?: 'crud' | 'custom' | 'screen' | string;
|
|
15
|
+
kind?: 'crud' | 'custom' | 'screen' | 'dependency' | string;
|
|
16
|
+
/**
|
|
17
|
+
* Full capability string override. When set, the grant uses this exact key
|
|
18
|
+
* instead of `${moduleKey}.${key}` — hosts use it so a screen (Terminal)
|
|
19
|
+
* can show checkboxes for other modules' caps (`product.index`, …) as
|
|
20
|
+
* shortcuts without inventing `screen….product.index`.
|
|
21
|
+
*/
|
|
22
|
+
capability?: string;
|
|
14
23
|
}
|
|
15
24
|
export interface PermissionModuleDef {
|
|
16
25
|
/**
|
|
@@ -94,8 +103,10 @@ export interface PermissionsManagerProps {
|
|
|
94
103
|
title?: string;
|
|
95
104
|
className?: string;
|
|
96
105
|
}
|
|
97
|
-
/** Capability for a catalog module action: `lowercase(moduleKey).actionKey
|
|
98
|
-
|
|
106
|
+
/** Capability for a catalog module action: `lowercase(moduleKey).actionKey`,
|
|
107
|
+
* or {@link PermissionActionDef.capability} when the action is a cross-module
|
|
108
|
+
* shortcut. */
|
|
109
|
+
export declare function moduleActionCapability(moduleKey: string, actionKey: string, capability?: string): string;
|
|
99
110
|
/** All capabilities of one module. */
|
|
100
111
|
export declare function moduleCapabilities(module: PermissionModuleDef): string[];
|
|
101
112
|
/** How many of the module's capabilities are in the granted set. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions-manager.d.ts","sourceRoot":"","sources":["../src/permissions-manager.tsx"],"names":[],"mappings":"AAyBA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAyD9B,MAAM,WAAW,mBAAmB;IAChC,kFAAkF;IAClF,GAAG,EAAE,MAAM,CAAA;IACX,sDAAsD;IACtD,KAAK,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAA;IACb
|
|
1
|
+
{"version":3,"file":"permissions-manager.d.ts","sourceRoot":"","sources":["../src/permissions-manager.tsx"],"names":[],"mappings":"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"}
|
|
@@ -33,13 +33,17 @@ import { DynamicIcon } from './dynamic-icon';
|
|
|
33
33
|
// ---------------------------------------------------------------------------
|
|
34
34
|
// Pure helpers (exported for hosts/tests)
|
|
35
35
|
// ---------------------------------------------------------------------------
|
|
36
|
-
/** Capability for a catalog module action: `lowercase(moduleKey).actionKey
|
|
37
|
-
|
|
36
|
+
/** Capability for a catalog module action: `lowercase(moduleKey).actionKey`,
|
|
37
|
+
* or {@link PermissionActionDef.capability} when the action is a cross-module
|
|
38
|
+
* shortcut. */
|
|
39
|
+
export function moduleActionCapability(moduleKey, actionKey, capability) {
|
|
40
|
+
if (capability)
|
|
41
|
+
return capability;
|
|
38
42
|
return `${moduleKey.toLowerCase()}.${actionKey}`;
|
|
39
43
|
}
|
|
40
44
|
/** All capabilities of one module. */
|
|
41
45
|
export function moduleCapabilities(module) {
|
|
42
|
-
return module.actions.map((a) => moduleActionCapability(module.key, a.key));
|
|
46
|
+
return module.actions.map((a) => moduleActionCapability(module.key, a.key, a.capability));
|
|
43
47
|
}
|
|
44
48
|
/** How many of the module's capabilities are in the granted set. */
|
|
45
49
|
export function grantedCountForModule(granted, module) {
|
|
@@ -75,6 +79,8 @@ export function defaultActionIcon(actionKey, kind) {
|
|
|
75
79
|
return 'List';
|
|
76
80
|
if (kind === 'screen')
|
|
77
81
|
return 'Eye';
|
|
82
|
+
if (kind === 'dependency')
|
|
83
|
+
return 'Link2';
|
|
78
84
|
return 'Zap';
|
|
79
85
|
}
|
|
80
86
|
}
|
|
@@ -445,8 +451,8 @@ export function PermissionsManager({ loadModules, loadRoles, loadRolePermissions
|
|
|
445
451
|
(activeModule.kind === 'screen' ? 'Eye' : 'Square'), className: "h-4 w-4 shrink-0 text-primary" })), _jsx("span", { className: "truncate", children: activeModule ? activeModule.label : 'Acciones permitidas' })] }), _jsx(CardDescription, { children: activeModule
|
|
446
452
|
? `${activeModuleGroupTitle || 'Sistema'} · configura las acciones permitidas`
|
|
447
453
|
: 'Configura los permisos del módulo seleccionado.' })] }), activeRole && activeModule && (_jsxs("div", { className: "flex items-center gap-2", children: [_jsxs(Badge, { variant: "secondary", className: "tabular-nums", children: [moduleGranted, "/", moduleTotal] }), _jsxs(Button, { variant: "outline", size: "sm", className: "h-8", disabled: checksDisabled || moduleGranted === moduleTotal, onClick: () => setModuleAll(true), children: [_jsx(CheckCheck, { className: "mr-1.5 h-3.5 w-3.5" }), " Marcar todo"] }), _jsxs(Button, { variant: "outline", size: "sm", className: "h-8", disabled: checksDisabled || moduleGranted === 0, onClick: () => setModuleAll(false), children: [_jsx(Eraser, { className: "mr-1.5 h-3.5 w-3.5" }), " Limpiar"] })] }))] }) }), _jsx(CardContent, { children: !activeRole ? (_jsx(EmptyHint, { text: "Selecciona un rol para configurar sus permisos." })) : loadingPerms ? (_jsx("div", { className: "grid gap-2 sm:grid-cols-2 xl:grid-cols-3", children: Array.from({ length: 6 }).map((_, i) => (_jsx(Skeleton, { className: "h-11 w-full" }, i))) })) : !activeModule ? (_jsx(EmptyHint, { text: "Selecciona un m\u00F3dulo de la lista para ver sus acciones." })) : (_jsx("div", { className: "grid gap-2 sm:grid-cols-2 xl:grid-cols-3", children: activeModule.actions.map((action) => {
|
|
448
|
-
const cap = moduleActionCapability(activeModule.key, action.key);
|
|
449
|
-
return (_jsx(CapabilityCheck, { checked: draft?.has(cap) ?? false, disabled: checksDisabled, onToggle: () => toggleCapability(cap), icon: action.icon || defaultActionIcon(action.key, action.kind), label: action.label }, action.key));
|
|
454
|
+
const cap = moduleActionCapability(activeModule.key, action.key, action.capability);
|
|
455
|
+
return (_jsx(CapabilityCheck, { checked: draft?.has(cap) ?? false, disabled: checksDisabled, onToggle: () => toggleCapability(cap), icon: action.icon || defaultActionIcon(action.key, action.kind), label: action.label }, action.capability ?? action.key));
|
|
450
456
|
}) })) })] })] }), _jsx(AlertDialog, { open: pendingRoleId !== null, onOpenChange: (open) => !open && setPendingRoleId(null), children: _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Cambios sin guardar" }), _jsx(AlertDialogDescription, { children: "Tienes cambios sin guardar en este rol. Si cambias de rol se descartar\u00E1n." })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { children: "Cancelar" }), _jsx(AlertDialogAction, { onClick: () => {
|
|
451
457
|
setActiveRoleId(pendingRoleId);
|
|
452
458
|
setPendingRoleId(null);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asteby/metacore-runtime-react",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "30.0.1",
|
|
4
4
|
"description": "React runtime for metacore hosts — renders addon contributions dynamically",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"sonner": ">=1.7",
|
|
39
39
|
"zustand": ">=5",
|
|
40
40
|
"@asteby/metacore-sdk": "^3.4.0",
|
|
41
|
-
"@asteby/metacore-ui": "^2.
|
|
41
|
+
"@asteby/metacore-ui": "^2.14.0"
|
|
42
42
|
},
|
|
43
43
|
"peerDependenciesMeta": {
|
|
44
44
|
"@tanstack/react-router": {
|
|
@@ -68,7 +68,7 @@
|
|
|
68
68
|
"vitest": "^4.0.0",
|
|
69
69
|
"zustand": "^5.0.0",
|
|
70
70
|
"@asteby/metacore-sdk": "3.4.0",
|
|
71
|
-
"@asteby/metacore-ui": "2.
|
|
71
|
+
"@asteby/metacore-ui": "2.14.0"
|
|
72
72
|
},
|
|
73
73
|
"scripts": {
|
|
74
74
|
"build": "tsc -p tsconfig.json",
|
|
@@ -118,6 +118,30 @@ describe('helpers puros', () => {
|
|
|
118
118
|
)
|
|
119
119
|
})
|
|
120
120
|
|
|
121
|
+
it('capability override grants the exact cross-module key', () => {
|
|
122
|
+
expect(
|
|
123
|
+
moduleActionCapability('screen.addons.pos.terminal', 'product.index', 'product.index'),
|
|
124
|
+
).toBe('product.index')
|
|
125
|
+
const mod = {
|
|
126
|
+
key: 'screen.addons.pos.terminal',
|
|
127
|
+
label: 'Terminal',
|
|
128
|
+
kind: 'screen' as const,
|
|
129
|
+
actions: [
|
|
130
|
+
{ key: 'access', label: 'Acceder', kind: 'screen' as const },
|
|
131
|
+
{
|
|
132
|
+
key: 'product.index',
|
|
133
|
+
label: 'Productos · Listar',
|
|
134
|
+
kind: 'dependency' as const,
|
|
135
|
+
capability: 'product.index',
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
}
|
|
139
|
+
expect(moduleCapabilities(mod)).toEqual([
|
|
140
|
+
'screen.addons.pos.terminal.access',
|
|
141
|
+
'product.index',
|
|
142
|
+
])
|
|
143
|
+
})
|
|
144
|
+
|
|
121
145
|
it('moduleCapabilities y grantedCountForModule', () => {
|
|
122
146
|
const mod = grouped.groups[1].modules[0] // pos_orders
|
|
123
147
|
expect(moduleCapabilities(mod)).toEqual([
|
|
@@ -90,8 +90,17 @@ export interface PermissionActionDef {
|
|
|
90
90
|
/**
|
|
91
91
|
* `crud` for the derived CRUD set, `custom` for manifest actions,
|
|
92
92
|
* `screen` for the single `access` action of a non-model screen.
|
|
93
|
+
* `dependency` for a shortcut to another module's capability (see
|
|
94
|
+
* {@link capability}).
|
|
93
95
|
*/
|
|
94
|
-
kind?: 'crud' | 'custom' | 'screen' | string
|
|
96
|
+
kind?: 'crud' | 'custom' | 'screen' | 'dependency' | string
|
|
97
|
+
/**
|
|
98
|
+
* Full capability string override. When set, the grant uses this exact key
|
|
99
|
+
* instead of `${moduleKey}.${key}` — hosts use it so a screen (Terminal)
|
|
100
|
+
* can show checkboxes for other modules' caps (`product.index`, …) as
|
|
101
|
+
* shortcuts without inventing `screen….product.index`.
|
|
102
|
+
*/
|
|
103
|
+
capability?: string
|
|
95
104
|
}
|
|
96
105
|
|
|
97
106
|
export interface PermissionModuleDef {
|
|
@@ -189,14 +198,23 @@ export interface PermissionsManagerProps {
|
|
|
189
198
|
// Pure helpers (exported for hosts/tests)
|
|
190
199
|
// ---------------------------------------------------------------------------
|
|
191
200
|
|
|
192
|
-
/** Capability for a catalog module action: `lowercase(moduleKey).actionKey
|
|
193
|
-
|
|
201
|
+
/** Capability for a catalog module action: `lowercase(moduleKey).actionKey`,
|
|
202
|
+
* or {@link PermissionActionDef.capability} when the action is a cross-module
|
|
203
|
+
* shortcut. */
|
|
204
|
+
export function moduleActionCapability(
|
|
205
|
+
moduleKey: string,
|
|
206
|
+
actionKey: string,
|
|
207
|
+
capability?: string,
|
|
208
|
+
): string {
|
|
209
|
+
if (capability) return capability
|
|
194
210
|
return `${moduleKey.toLowerCase()}.${actionKey}`
|
|
195
211
|
}
|
|
196
212
|
|
|
197
213
|
/** All capabilities of one module. */
|
|
198
214
|
export function moduleCapabilities(module: PermissionModuleDef): string[] {
|
|
199
|
-
return module.actions.map((a) =>
|
|
215
|
+
return module.actions.map((a) =>
|
|
216
|
+
moduleActionCapability(module.key, a.key, a.capability),
|
|
217
|
+
)
|
|
200
218
|
}
|
|
201
219
|
|
|
202
220
|
/** How many of the module's capabilities are in the granted set. */
|
|
@@ -233,6 +251,7 @@ export function defaultActionIcon(actionKey: string, kind?: string): string {
|
|
|
233
251
|
default:
|
|
234
252
|
if (kind === 'crud') return 'List'
|
|
235
253
|
if (kind === 'screen') return 'Eye'
|
|
254
|
+
if (kind === 'dependency') return 'Link2'
|
|
236
255
|
return 'Zap'
|
|
237
256
|
}
|
|
238
257
|
}
|
|
@@ -1051,10 +1070,14 @@ export function PermissionsManager({
|
|
|
1051
1070
|
) : (
|
|
1052
1071
|
<div className="grid gap-2 sm:grid-cols-2 xl:grid-cols-3">
|
|
1053
1072
|
{activeModule.actions.map((action) => {
|
|
1054
|
-
const cap = moduleActionCapability(
|
|
1073
|
+
const cap = moduleActionCapability(
|
|
1074
|
+
activeModule.key,
|
|
1075
|
+
action.key,
|
|
1076
|
+
action.capability,
|
|
1077
|
+
)
|
|
1055
1078
|
return (
|
|
1056
1079
|
<CapabilityCheck
|
|
1057
|
-
key={action.key}
|
|
1080
|
+
key={action.capability ?? action.key}
|
|
1058
1081
|
checked={draft?.has(cap) ?? false}
|
|
1059
1082
|
disabled={checksDisabled}
|
|
1060
1083
|
onToggle={() => toggleCapability(cap)}
|