57 lines
2.3 KiB
TypeScript
57 lines
2.3 KiB
TypeScript
import { type MenuModule, isPathAllowed } from '@basic-erp/sap-types';
|
|
|
|
/** Lo que el administrador marca en pantalla para un usuario. */
|
|
export interface Selection {
|
|
/** Acceso total (`*`). */
|
|
all: boolean;
|
|
/** Rutas de menú marcadas (incluye las cubiertas por un patrón `/modulo/*`). */
|
|
paths: ReadonlySet<string>;
|
|
/** Patrones que no corresponden a ninguna pantalla actual (ej. de una versión futura): se conservan tal cual. */
|
|
extras: readonly string[];
|
|
}
|
|
|
|
/** Módulos que se otorgan con casillas; "Administración" solo llega con acceso total. */
|
|
export const grantableModules = (menu: readonly MenuModule[]): readonly MenuModule[] => menu.filter((m) => m.id !== 'admin');
|
|
|
|
export function toSelection(patterns: readonly string[], menu: readonly MenuModule[]): Selection {
|
|
const all = patterns.includes('*');
|
|
const known = menu.flatMap((m) => m.items.map((i) => i.path));
|
|
const paths = new Set(known.filter((p) => !all && isPathAllowed(patterns, p)));
|
|
const extras = patterns.filter((p) => p !== '*' && !known.some((k) => isPathAllowed([p], k)));
|
|
return { all, paths, extras };
|
|
}
|
|
|
|
/**
|
|
* Patrones a guardar: `*` si es acceso total; si no, `/modulo/*` cuando están todas las pantallas
|
|
* del módulo y rutas sueltas en otro caso, más los patrones desconocidos conservados.
|
|
*/
|
|
export function toPatterns(sel: Selection, menu: readonly MenuModule[]): string[] {
|
|
if (sel.all) return ['*'];
|
|
const out: string[] = [];
|
|
for (const m of grantableModules(menu)) {
|
|
const checked = m.items.filter((i) => sel.paths.has(i.path));
|
|
if (checked.length === m.items.length && m.items.length > 0) out.push(`/${m.id}/*`);
|
|
else out.push(...checked.map((i) => i.path));
|
|
}
|
|
return [...out, ...sel.extras];
|
|
}
|
|
|
|
export function togglePath(sel: Selection, path: string, on: boolean): Selection {
|
|
const paths = new Set(sel.paths);
|
|
if (on) paths.add(path);
|
|
else paths.delete(path);
|
|
return { ...sel, paths };
|
|
}
|
|
|
|
export function toggleModule(sel: Selection, module: MenuModule, on: boolean): Selection {
|
|
const paths = new Set(sel.paths);
|
|
for (const i of module.items) {
|
|
if (on) paths.add(i.path);
|
|
else paths.delete(i.path);
|
|
}
|
|
return { ...sel, paths };
|
|
}
|
|
|
|
export const samePatterns = (a: readonly string[], b: readonly string[]): boolean =>
|
|
a.length === b.length && [...a].sort().every((p, i) => p === [...b].sort()[i]);
|