@sierra-95/svelte-scaffold 1.0.72 → 1.0.73
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/Hooks/layout_menu.d.ts +7 -0
- package/dist/Hooks/layout_menu.js +49 -1
- package/dist/Modules/Layout/Menu/menu.svelte +5 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/stores/modules/layout.d.ts +4 -0
- package/dist/stores/modules/layout.js +3 -1
- package/package.json +1 -1
|
@@ -1 +1,8 @@
|
|
|
1
|
+
import type { Section } from '../index.js';
|
|
1
2
|
export declare function validateLayoutMenuSections(sections: Array<any>): void;
|
|
3
|
+
export declare function filterSectionsByRole(sections: Section[], userRole: string): {
|
|
4
|
+
items: import("../index.js").SectionItem[];
|
|
5
|
+
label: string;
|
|
6
|
+
hidden?: boolean;
|
|
7
|
+
role?: string;
|
|
8
|
+
}[];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { get } from 'svelte/store';
|
|
2
|
+
import { setToastMessage, layoutStore } from '../index.js';
|
|
2
3
|
export function validateLayoutMenuSections(sections) {
|
|
3
4
|
const seenPaths = new Set();
|
|
4
5
|
for (const section of sections) {
|
|
@@ -22,3 +23,50 @@ export function validateLayoutMenuSections(sections) {
|
|
|
22
23
|
}
|
|
23
24
|
}
|
|
24
25
|
}
|
|
26
|
+
function getRoleLevel(role) {
|
|
27
|
+
if (!role)
|
|
28
|
+
return 0;
|
|
29
|
+
const state = get(layoutStore);
|
|
30
|
+
return role in state.ROLE_LEVELS ? state.ROLE_LEVELS[role] : 0;
|
|
31
|
+
}
|
|
32
|
+
function hasAccess(userRole, requiredRole) {
|
|
33
|
+
if (!requiredRole)
|
|
34
|
+
return true;
|
|
35
|
+
return getRoleLevel(userRole) >= getRoleLevel(requiredRole);
|
|
36
|
+
}
|
|
37
|
+
function isDefined(value) {
|
|
38
|
+
return value != null;
|
|
39
|
+
}
|
|
40
|
+
export function filterSectionsByRole(sections, userRole) {
|
|
41
|
+
return sections
|
|
42
|
+
.map(section => {
|
|
43
|
+
// No access to section → remove entirely
|
|
44
|
+
if (!hasAccess(userRole, section.role))
|
|
45
|
+
return null;
|
|
46
|
+
const items = section.items
|
|
47
|
+
.map(item => {
|
|
48
|
+
const itemRole = item.role ?? section.role;
|
|
49
|
+
// No access to item → remove
|
|
50
|
+
if (!hasAccess(userRole, itemRole))
|
|
51
|
+
return null;
|
|
52
|
+
// Handle children
|
|
53
|
+
if (item.children) {
|
|
54
|
+
const children = item.children.filter((child) => {
|
|
55
|
+
const childRole = child.role ?? itemRole;
|
|
56
|
+
return hasAccess(userRole, childRole);
|
|
57
|
+
});
|
|
58
|
+
// No visible children → remove parent
|
|
59
|
+
if (children.length === 0)
|
|
60
|
+
return null;
|
|
61
|
+
return { ...item, children };
|
|
62
|
+
}
|
|
63
|
+
return item;
|
|
64
|
+
})
|
|
65
|
+
.filter(isDefined);
|
|
66
|
+
// No visible items → remove section
|
|
67
|
+
if (items.length === 0)
|
|
68
|
+
return null;
|
|
69
|
+
return { ...section, items };
|
|
70
|
+
})
|
|
71
|
+
.filter(isDefined);
|
|
72
|
+
}
|
|
@@ -3,13 +3,16 @@
|
|
|
3
3
|
import { onMount } from 'svelte';
|
|
4
4
|
import { page } from '$app/state';
|
|
5
5
|
import { afterNavigate, beforeNavigate } from '$app/navigation';
|
|
6
|
-
import { isLoading, validateLayoutMenuSections, GlobalSearch, layoutStore } from '../../../index.js';
|
|
6
|
+
import { isLoading, validateLayoutMenuSections, GlobalSearch, layoutStore, filterSectionsByRole } from '../../../index.js';
|
|
7
7
|
|
|
8
8
|
export let toggleMenu: () => void;
|
|
9
9
|
export let closeMobileMenu: () => void;
|
|
10
10
|
export let isMenuOpen: boolean;
|
|
11
11
|
|
|
12
|
-
$: sections =
|
|
12
|
+
$: sections = filterSectionsByRole(
|
|
13
|
+
$layoutStore.sections,
|
|
14
|
+
$layoutStore.userRole ?? 'user'
|
|
15
|
+
);
|
|
13
16
|
|
|
14
17
|
function isParentActive(item: any, pathname: string) {
|
|
15
18
|
if (item.path === '/') {
|
package/dist/index.d.ts
CHANGED
|
@@ -50,7 +50,7 @@ export type { FileInputStoreMediaItem } from './stores/modules/fileInput.js';
|
|
|
50
50
|
export { toastCarrier, setToastMessage, clearToastMessage } from './stores/modules/toast.js';
|
|
51
51
|
export { layoutStore, resetLayoutStore } from './stores/modules/layout.js';
|
|
52
52
|
export { getPreviewUrlForMedia, toggleSelectForMedia, removeFileForMedia, DOCUMENT_MIME_TYPES, IMAGE_MIME_TYPES_PREVIEW } from './Hooks/preview.js';
|
|
53
|
-
export { validateLayoutMenuSections } from './Hooks/layout_menu.js';
|
|
53
|
+
export { validateLayoutMenuSections, filterSectionsByRole } from './Hooks/layout_menu.js';
|
|
54
54
|
export { buttonRipple } from './Hooks/button.js';
|
|
55
55
|
export { buildSearchIndex } from './Hooks/buildSearch.js';
|
|
56
56
|
export { isValidEmail } from './Hooks/validateForms.js';
|
package/dist/index.js
CHANGED
|
@@ -63,7 +63,7 @@ export { toastCarrier, setToastMessage, clearToastMessage } from './stores/modul
|
|
|
63
63
|
export { layoutStore, resetLayoutStore } from './stores/modules/layout.js';
|
|
64
64
|
//#######################HOOKS/UTILS########################
|
|
65
65
|
export { getPreviewUrlForMedia, toggleSelectForMedia, removeFileForMedia, DOCUMENT_MIME_TYPES, IMAGE_MIME_TYPES_PREVIEW } from './Hooks/preview.js';
|
|
66
|
-
export { validateLayoutMenuSections } from './Hooks/layout_menu.js';
|
|
66
|
+
export { validateLayoutMenuSections, filterSectionsByRole } from './Hooks/layout_menu.js';
|
|
67
67
|
export { buttonRipple } from './Hooks/button.js';
|
|
68
68
|
export { buildSearchIndex } from './Hooks/buildSearch.js';
|
|
69
69
|
export { isValidEmail } from './Hooks/validateForms.js';
|
|
@@ -4,12 +4,14 @@ export type SectionItem = {
|
|
|
4
4
|
label: string;
|
|
5
5
|
icon?: string;
|
|
6
6
|
hidden?: boolean;
|
|
7
|
+
role?: string;
|
|
7
8
|
children?: SectionItem[];
|
|
8
9
|
TOC?: Partial<Record<string, string>>;
|
|
9
10
|
};
|
|
10
11
|
export type Section = {
|
|
11
12
|
label: string;
|
|
12
13
|
hidden?: boolean;
|
|
14
|
+
role?: string;
|
|
13
15
|
items: SectionItem[];
|
|
14
16
|
};
|
|
15
17
|
export type LayoutState = {
|
|
@@ -26,6 +28,8 @@ export type LayoutState = {
|
|
|
26
28
|
toggleMenuSize: string;
|
|
27
29
|
menuActiveIconColor: string;
|
|
28
30
|
backgroundColor: string;
|
|
31
|
+
userRole?: string;
|
|
32
|
+
ROLE_LEVELS: Record<any, number>;
|
|
29
33
|
};
|
|
30
34
|
export declare const layoutStore: import("svelte/store").Writable<LayoutState>;
|
|
31
35
|
export declare function resetLayoutStore(): void;
|
|
@@ -12,7 +12,9 @@ const defaultLayoutState = {
|
|
|
12
12
|
toggleMenuColor: 'black',
|
|
13
13
|
toggleMenuSize: "25px",
|
|
14
14
|
menuActiveIconColor: 'var(--primary-bg)',
|
|
15
|
-
backgroundColor: ''
|
|
15
|
+
backgroundColor: '',
|
|
16
|
+
userRole: 'user',
|
|
17
|
+
ROLE_LEVELS: { user: 1 }
|
|
16
18
|
};
|
|
17
19
|
export const layoutStore = writable({
|
|
18
20
|
...defaultLayoutState
|