@flowselections/core 1.0.25 → 1.0.27
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/README.md +21 -6
- package/dist/components/layout/BrandLogo.d.ts +9 -0
- package/dist/components/layout/BrandLogo.d.ts.map +1 -0
- package/dist/components/layout/BrandLogo.js +12 -0
- package/dist/components/layout/BugsDialog.js +4 -4
- package/dist/components/layout/LoginPage.d.ts +6 -1
- package/dist/components/layout/LoginPage.d.ts.map +1 -1
- package/dist/components/layout/LoginPage.js +11 -5
- package/dist/components/layout/NotificationBell.js +1 -1
- package/dist/components/layout/ResetWachtwoordPage.js +1 -1
- package/dist/components/layout/Sidebar.d.ts +1 -1
- package/dist/components/layout/Sidebar.d.ts.map +1 -1
- package/dist/components/layout/Sidebar.js +4 -3
- package/dist/components/ui/alert.js +1 -1
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/badge.d.ts.map +1 -1
- package/dist/components/ui/badge.js +5 -2
- package/dist/components/ui/button.js +5 -5
- package/dist/components/ui/calendar.js +1 -1
- package/dist/components/ui/card.js +1 -1
- package/dist/components/ui/checkbox.js +1 -1
- package/dist/components/ui/input-otp.js +1 -1
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/menubar.js +1 -1
- package/dist/components/ui/navigation-menu.js +1 -1
- package/dist/components/ui/radio-group.js +1 -1
- package/dist/components/ui/resizable.js +1 -1
- package/dist/components/ui/select.js +1 -1
- package/dist/components/ui/sidebar.js +3 -3
- package/dist/components/ui/slider.js +1 -1
- package/dist/components/ui/sonner.js +1 -1
- package/dist/components/ui/switch.js +1 -1
- package/dist/components/ui/tabs.js +1 -1
- package/dist/components/ui/textarea.js +1 -1
- package/dist/components/ui/toggle.js +2 -2
- package/dist/extensions/ShellExtensions.d.ts +15 -4
- package/dist/extensions/ShellExtensions.d.ts.map +1 -1
- package/dist/extensions/ShellExtensions.js +6 -3
- package/dist/hooks/useLogoSrc.d.ts +3 -3
- package/dist/hooks/useLogoSrc.d.ts.map +1 -1
- package/dist/hooks/useLogoSrc.js +4 -25
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/permissions/ModuleAccessGuard.js +1 -1
- package/dist/routes/index.d.ts +63 -6
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +17 -4
- package/dist/server/permissions.server.d.ts +6 -1
- package/dist/server/permissions.server.d.ts.map +1 -1
- package/dist/server/permissions.server.js +38 -14
- package/dist/styles/brand-default.css +55 -0
- package/dist/styles.css +33 -42
- package/package.json +116 -116
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from "react";
|
|
2
2
|
import type { FlowModule } from "../types/module.js";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
export interface ModuleListTransformContext {
|
|
4
|
+
/** De ongefilterde modulelijst die de shell aan de core-layout gaf. */
|
|
5
|
+
allModules: FlowModule[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Transformeert de actuele modulelijst (filteren en/of sorteren).
|
|
9
|
+
* Het tweede argument bevat altijd de ongefilterde shell-lijst.
|
|
10
|
+
* Puur op basis van input: geen synchronisatie, schrijfacties of andere side-effects.
|
|
11
|
+
*/
|
|
12
|
+
export type ModuleListTransform = (modules: FlowModule[], context: ModuleListTransformContext) => FlowModule[];
|
|
5
13
|
export type UseModuleListTransform = () => ModuleListTransform;
|
|
6
14
|
/**
|
|
7
15
|
* Sinds 1.0.23. Footer-items van de zijbalk. Uitloggen staat bewust NIET in dit
|
|
@@ -36,9 +44,12 @@ export declare function useShellGuard(): ComponentType<{
|
|
|
36
44
|
children: ReactNode;
|
|
37
45
|
}> | undefined;
|
|
38
46
|
/**
|
|
39
|
-
* Past de geregistreerde transforms toe.
|
|
47
|
+
* Past de geregistreerde transforms toe. `allModules` is de ongefilterde
|
|
48
|
+
* shell-lijst en blijft voor de hele pipeline gelijk. Transforms zijn puur op
|
|
49
|
+
* basis van hun input: geen synchronisatie, schrijfacties of andere side-effects.
|
|
50
|
+
* Zonder provider, tijdens laden of bij
|
|
40
51
|
* een fout in een transform komt de lijst ONGEWIJZIGD terug — nooit een lege
|
|
41
52
|
* zijbalk.
|
|
42
53
|
*/
|
|
43
|
-
export declare function useModuleListTransform(modules: FlowModule[]): FlowModule[];
|
|
54
|
+
export declare function useModuleListTransform(modules: FlowModule[], allModules?: FlowModule[]): FlowModule[];
|
|
44
55
|
//# sourceMappingURL=ShellExtensions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShellExtensions.d.ts","sourceRoot":"","sources":["../../src/core/extensions/ShellExtensions.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,
|
|
1
|
+
{"version":3,"file":"ShellExtensions.d.ts","sourceRoot":"","sources":["../../src/core/extensions/ShellExtensions.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,0BAA0B;IACzC,uEAAuE;IACvE,UAAU,EAAE,UAAU,EAAE,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAChC,OAAO,EAAE,UAAU,EAAE,EACrB,OAAO,EAAE,0BAA0B,KAChC,UAAU,EAAE,CAAC;AAElB,MAAM,MAAM,sBAAsB,GAAG,MAAM,mBAAmB,CAAC;AAE/D;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB;AACD,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,WAAW,CAAC;AAClE,MAAM,MAAM,kBAAkB,GAAG,MAAM,eAAe,CAAC;AAYvD,uGAAuG;AACvG,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAc7D;AAED,MAAM,WAAW,4BAA4B;IAC3C;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,sBAAsB,GAAG,sBAAsB,EAAE,CAAC;IAClE,kFAAkF;IAClF,KAAK,CAAC,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC/C,+FAA+F;IAC/F,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,uBAAuB,CAAC,EACtC,aAAa,EACb,KAAK,EACL,SAAS,EACT,QAAQ,GACT,EAAE,4BAA4B,2CAY9B;AAED,wBAAgB,aAAa,IAAI,aAAa,CAAC;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,CAAC,GAAG,SAAS,CAElF;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,UAAU,EAAE,EACrB,UAAU,GAAE,UAAU,EAAY,GACjC,UAAU,EAAE,CAuBd"}
|
|
@@ -33,11 +33,14 @@ export function useShellGuard() {
|
|
|
33
33
|
return useContext(ShellExtensionsContext).guard;
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
|
-
* Past de geregistreerde transforms toe.
|
|
36
|
+
* Past de geregistreerde transforms toe. `allModules` is de ongefilterde
|
|
37
|
+
* shell-lijst en blijft voor de hele pipeline gelijk. Transforms zijn puur op
|
|
38
|
+
* basis van hun input: geen synchronisatie, schrijfacties of andere side-effects.
|
|
39
|
+
* Zonder provider, tijdens laden of bij
|
|
37
40
|
* een fout in een transform komt de lijst ONGEWIJZIGD terug — nooit een lege
|
|
38
41
|
* zijbalk.
|
|
39
42
|
*/
|
|
40
|
-
export function useModuleListTransform(modules) {
|
|
43
|
+
export function useModuleListTransform(modules, allModules = modules) {
|
|
41
44
|
const { transforms } = useContext(ShellExtensionsContext);
|
|
42
45
|
// Onvoorwaardelijk en in vaste volgorde: geen hook-order-problemen.
|
|
43
46
|
const applied = [];
|
|
@@ -52,7 +55,7 @@ export function useModuleListTransform(modules) {
|
|
|
52
55
|
let result = modules;
|
|
53
56
|
for (const transform of applied) {
|
|
54
57
|
try {
|
|
55
|
-
const next = transform(result);
|
|
58
|
+
const next = transform(result, { allModules });
|
|
56
59
|
if (Array.isArray(next))
|
|
57
60
|
result = next;
|
|
58
61
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export declare const DEFAULT_LOGO_SRC = "/logo.
|
|
1
|
+
export declare const DEFAULT_LOGO_SRC = "/brand/logo-wit.svg";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* `/logo.
|
|
3
|
+
* Logopad: een expliciete shell-prop wint, anders het door het dashboard
|
|
4
|
+
* beheerde `/brand/logo-wit.svg`.
|
|
5
5
|
*/
|
|
6
6
|
export declare function useLogoSrc(prop?: string): string;
|
|
7
7
|
//# sourceMappingURL=useLogoSrc.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLogoSrc.d.ts","sourceRoot":"","sources":["../../src/core/hooks/useLogoSrc.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useLogoSrc.d.ts","sourceRoot":"","sources":["../../src/core/hooks/useLogoSrc.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,wBAAwB,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD"}
|
package/dist/hooks/useLogoSrc.js
CHANGED
|
@@ -1,29 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
export const DEFAULT_LOGO_SRC = "/logo.png";
|
|
3
|
-
let huisstijlLogo = null;
|
|
4
|
-
function loadHuisstijlLogo() {
|
|
5
|
-
if (!huisstijlLogo) {
|
|
6
|
-
huisstijlLogo = fetch("/huisstijl.json")
|
|
7
|
-
.then((r) => (r.ok ? r.json() : null))
|
|
8
|
-
.then((j) => (j && typeof j.logo === "string" && j.logo ? j.logo : null))
|
|
9
|
-
.catch(() => null);
|
|
10
|
-
}
|
|
11
|
-
return huisstijlLogo;
|
|
12
|
-
}
|
|
1
|
+
export const DEFAULT_LOGO_SRC = "/brand/logo-wit.svg";
|
|
13
2
|
/**
|
|
14
|
-
*
|
|
15
|
-
* `/logo.
|
|
3
|
+
* Logopad: een expliciete shell-prop wint, anders het door het dashboard
|
|
4
|
+
* beheerde `/brand/logo-wit.svg`.
|
|
16
5
|
*/
|
|
17
6
|
export function useLogoSrc(prop) {
|
|
18
|
-
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
if (prop || typeof window === "undefined")
|
|
21
|
-
return;
|
|
22
|
-
let alive = true;
|
|
23
|
-
loadHuisstijlLogo().then((v) => alive && setFromFile(v));
|
|
24
|
-
return () => {
|
|
25
|
-
alive = false;
|
|
26
|
-
};
|
|
27
|
-
}, [prop]);
|
|
28
|
-
return prop || fromFile || DEFAULT_LOGO_SRC;
|
|
7
|
+
return prop || DEFAULT_LOGO_SRC;
|
|
29
8
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export { useHuisstijl } from "./hooks/useHuisstijl.js";
|
|
|
46
46
|
export type { FlowModule, NavItem, SettingsCard, FeatureDefinition } from "./types/module.js";
|
|
47
47
|
export { moduleKey, navKey, featureKey, moduleFeatures } from "./types/module.js";
|
|
48
48
|
export { ShellExtensionsProvider, useModuleListTransform, useFooterItems } from "./extensions/ShellExtensions.js";
|
|
49
|
-
export type { ModuleListTransform, UseModuleListTransform, ShellExtensionsProviderProps, FooterItems, FooterTransform, UseFooterTransform, } from "./extensions/ShellExtensions.js";
|
|
49
|
+
export type { ModuleListTransform, ModuleListTransformContext, UseModuleListTransform, ShellExtensionsProviderProps, FooterItems, FooterTransform, UseFooterTransform, } from "./extensions/ShellExtensions.js";
|
|
50
50
|
export { ModuleGuardSlot } from "./extensions/ModuleGuardSlot.js";
|
|
51
51
|
export { useMyModulePermissions, useModulePermission, useModulePermissionTransform, useCan, Can, usePermissionFilteredModules, } from "./permissions/useModulePermission.js";
|
|
52
52
|
export type { PermissionLevel, ModulePermissionRow, CanProps } from "./permissions/useModulePermission.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/core/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/core/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,5 +16,5 @@ export function ModuleAccessGuard({ children, fallback, moduleId, featureId, })
|
|
|
16
16
|
const { canView } = useModulePermission(key, featureId ?? null);
|
|
17
17
|
if (canView)
|
|
18
18
|
return _jsx(_Fragment, { children: children });
|
|
19
|
-
return (_jsx(_Fragment, { children: fallback ?? (_jsx("div", { className: "flex min-h-[60vh] items-center justify-center p-8", children: _jsxs("div", { className: "max-w-md text-center", children: [_jsx("h1", { className: "text-lg font-semibold text-foreground", children: "Geen toegang" }), _jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Je hebt geen rechten voor deze module. Vraag een beheerder om toegang." })] }) })) }));
|
|
19
|
+
return (_jsx(_Fragment, { children: fallback ?? (_jsx("div", { className: "flex min-h-[60vh] items-center justify-center p-8", children: _jsxs("div", { "data-empty-state": true, className: "max-w-md text-center", children: [_jsx("h1", { className: "text-lg font-semibold text-foreground", children: "Geen toegang" }), _jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Je hebt geen rechten voor deze module. Vraag een beheerder om toegang." })] }) })) }));
|
|
20
20
|
}
|
package/dist/routes/index.d.ts
CHANGED
|
@@ -15,23 +15,67 @@ export declare function loginRoute({ landing }: SystemRouteOptions): {
|
|
|
15
15
|
search: LoginSearch;
|
|
16
16
|
}) => void;
|
|
17
17
|
head: () => {
|
|
18
|
-
meta: {
|
|
18
|
+
meta: ({
|
|
19
19
|
title: string;
|
|
20
|
-
|
|
20
|
+
name?: undefined;
|
|
21
|
+
content?: undefined;
|
|
22
|
+
property?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
name: string;
|
|
25
|
+
content: string;
|
|
26
|
+
title?: undefined;
|
|
27
|
+
property?: undefined;
|
|
28
|
+
} | {
|
|
29
|
+
property: string;
|
|
30
|
+
content: string;
|
|
31
|
+
title?: undefined;
|
|
32
|
+
name?: undefined;
|
|
33
|
+
})[];
|
|
21
34
|
};
|
|
22
35
|
component: () => import("react/jsx-runtime").JSX.Element;
|
|
23
36
|
};
|
|
24
37
|
/** `/reset-wachtwoord`: de core-pagina, daarna naar `landing`. */
|
|
25
38
|
export declare function resetPasswordRoute({ landing, loginPath }: SystemRouteOptions): {
|
|
26
39
|
head: () => {
|
|
27
|
-
meta: {
|
|
40
|
+
meta: ({
|
|
28
41
|
title: string;
|
|
29
|
-
|
|
42
|
+
name?: undefined;
|
|
43
|
+
content?: undefined;
|
|
44
|
+
property?: undefined;
|
|
45
|
+
} | {
|
|
46
|
+
name: string;
|
|
47
|
+
content: string;
|
|
48
|
+
title?: undefined;
|
|
49
|
+
property?: undefined;
|
|
50
|
+
} | {
|
|
51
|
+
property: string;
|
|
52
|
+
content: string;
|
|
53
|
+
title?: undefined;
|
|
54
|
+
name?: undefined;
|
|
55
|
+
})[];
|
|
30
56
|
};
|
|
31
57
|
component: () => import("react/jsx-runtime").JSX.Element;
|
|
32
58
|
};
|
|
33
59
|
/** `/`: redirect in beforeLoad, dus er wordt niets gerenderd (geen flits). */
|
|
34
60
|
export declare function landingRoute({ landing }: Pick<SystemRouteOptions, "landing">): {
|
|
61
|
+
head: () => {
|
|
62
|
+
meta: ({
|
|
63
|
+
title: string;
|
|
64
|
+
name?: undefined;
|
|
65
|
+
content?: undefined;
|
|
66
|
+
property?: undefined;
|
|
67
|
+
} | {
|
|
68
|
+
name: string;
|
|
69
|
+
content: string;
|
|
70
|
+
title?: undefined;
|
|
71
|
+
property?: undefined;
|
|
72
|
+
} | {
|
|
73
|
+
property: string;
|
|
74
|
+
content: string;
|
|
75
|
+
title?: undefined;
|
|
76
|
+
name?: undefined;
|
|
77
|
+
})[];
|
|
78
|
+
};
|
|
35
79
|
beforeLoad: () => never;
|
|
36
80
|
component: () => null;
|
|
37
81
|
};
|
|
@@ -41,9 +85,22 @@ export declare function handoverRoute({ landing, loginPath, exchangePath, }: Sys
|
|
|
41
85
|
}): {
|
|
42
86
|
ssr: false;
|
|
43
87
|
head: () => {
|
|
44
|
-
meta: {
|
|
88
|
+
meta: ({
|
|
45
89
|
title: string;
|
|
46
|
-
|
|
90
|
+
name?: undefined;
|
|
91
|
+
content?: undefined;
|
|
92
|
+
property?: undefined;
|
|
93
|
+
} | {
|
|
94
|
+
name: string;
|
|
95
|
+
content: string;
|
|
96
|
+
title?: undefined;
|
|
97
|
+
property?: undefined;
|
|
98
|
+
} | {
|
|
99
|
+
property: string;
|
|
100
|
+
content: string;
|
|
101
|
+
title?: undefined;
|
|
102
|
+
name?: undefined;
|
|
103
|
+
})[];
|
|
47
104
|
};
|
|
48
105
|
component: () => import("react/jsx-runtime").JSX.Element;
|
|
49
106
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/routes/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/routes/index.tsx"],"names":[],"mappings":"AA4BA,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,kBAAkB;6BAE7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,WAAW;sCAE5B;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;EAU9E;AAED,kEAAkE;AAClE,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,SAAoB,EAAE,EAAE,kBAAkB;;;;;;;;;;;;;;;;;;;;EAOvF;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC;;;;;;;;;;;;;;;;;;;sBAGzD,KAAK;;EAOxB;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,SAAoB,EACpB,YAAY,GACb,EAAE,kBAAkB,GAAG;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;EAQhD"}
|
package/dist/routes/index.js
CHANGED
|
@@ -13,6 +13,18 @@ import { LoginPage } from "../components/layout/LoginPage.js";
|
|
|
13
13
|
import { ResetWachtwoordPage } from "../components/layout/ResetWachtwoordPage.js";
|
|
14
14
|
import { HandoverPage } from "../components/layout/HandoverPage.js";
|
|
15
15
|
import { safeRedirectPath } from "../auth/redirect.js";
|
|
16
|
+
function pageHead(title, description) {
|
|
17
|
+
return {
|
|
18
|
+
meta: [
|
|
19
|
+
{ title },
|
|
20
|
+
{ name: "description", content: description },
|
|
21
|
+
{ property: "og:title", content: title },
|
|
22
|
+
{ property: "og:description", content: description },
|
|
23
|
+
{ property: "og:type", content: "website" },
|
|
24
|
+
{ name: "twitter:card", content: "summary" },
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
16
28
|
function isAuthenticated(context) {
|
|
17
29
|
return Boolean(context?.auth?.isAuthenticated);
|
|
18
30
|
}
|
|
@@ -25,16 +37,16 @@ export function loginRoute({ landing }) {
|
|
|
25
37
|
throw redirect({ href: safeRedirectPath(search?.redirect, landing) });
|
|
26
38
|
}
|
|
27
39
|
},
|
|
28
|
-
head: () => (
|
|
40
|
+
head: () => pageHead("Inloggen | Flora Select", "Log veilig in bij Flora Select."),
|
|
29
41
|
component: function LoginRouteComponent() {
|
|
30
|
-
return _jsx(LoginPage, { redirectTo: landing });
|
|
42
|
+
return _jsx(LoginPage, { redirectTo: landing, routeHandlesRedirect: true });
|
|
31
43
|
},
|
|
32
44
|
};
|
|
33
45
|
}
|
|
34
46
|
/** `/reset-wachtwoord`: de core-pagina, daarna naar `landing`. */
|
|
35
47
|
export function resetPasswordRoute({ landing, loginPath = "/login" }) {
|
|
36
48
|
return {
|
|
37
|
-
head: () => (
|
|
49
|
+
head: () => pageHead("Nieuw wachtwoord | Flora Select", "Stel een nieuw wachtwoord in voor Flora Select."),
|
|
38
50
|
component: function ResetPasswordRouteComponent() {
|
|
39
51
|
return _jsx(ResetWachtwoordPage, { redirectTo: landing, loginPath: loginPath });
|
|
40
52
|
},
|
|
@@ -43,6 +55,7 @@ export function resetPasswordRoute({ landing, loginPath = "/login" }) {
|
|
|
43
55
|
/** `/`: redirect in beforeLoad, dus er wordt niets gerenderd (geen flits). */
|
|
44
56
|
export function landingRoute({ landing }) {
|
|
45
57
|
return {
|
|
58
|
+
head: () => pageHead("Flora Select", "Open de Flora Select-omgeving."),
|
|
46
59
|
beforeLoad: () => {
|
|
47
60
|
throw redirect({ href: landing });
|
|
48
61
|
},
|
|
@@ -55,7 +68,7 @@ export function landingRoute({ landing }) {
|
|
|
55
68
|
export function handoverRoute({ landing, loginPath = "/login", exchangePath, }) {
|
|
56
69
|
return {
|
|
57
70
|
ssr: false,
|
|
58
|
-
head: () => (
|
|
71
|
+
head: () => pageHead("Aanmelden | Flora Select", "Rond de veilige aanmelding bij Flora Select af."),
|
|
59
72
|
component: function HandoverRouteComponent() {
|
|
60
73
|
return _jsx(HandoverPage, { redirectTo: landing, loginPath: loginPath, exchangePath: exchangePath });
|
|
61
74
|
},
|
|
@@ -11,8 +11,13 @@ export type PermissionLevel = "none" | "view" | "edit";
|
|
|
11
11
|
*
|
|
12
12
|
* - Ontbreekt de RPC (add-on niet geïnstalleerd) → toegestaan (default-allow).
|
|
13
13
|
* - Geen geldige sessie → 401. Onvoldoende rechten → 403.
|
|
14
|
+
*
|
|
15
|
+
* `request` is optioneel: geef `getRequest()` mee (uit de code van je eigen
|
|
16
|
+
* shell, die door de Start-compiler wél getransformeerd wordt) als jouw runtime
|
|
17
|
+
* het actuele verzoek niet zelf blootgeeft. Aan het antwoord verandert niets:
|
|
18
|
+
* het token wordt hoe dan ook bij Supabase Auth gevalideerd.
|
|
14
19
|
*/
|
|
15
|
-
export declare function requireModulePermission(supabase: SupabaseClient<any, any, any>, moduleId: string, featureId?: string | null, level?: PermissionLevel): Promise<PermissionLevel>;
|
|
20
|
+
export declare function requireModulePermission(supabase: SupabaseClient<any, any, any>, moduleId: string, featureId?: string | null, level?: PermissionLevel, request?: Request | null): Promise<PermissionLevel>;
|
|
16
21
|
export { getRoleFlags };
|
|
17
22
|
/**
|
|
18
23
|
* Sinds 1.0.23. Superadmin? Claims eerst, terugval tabel `user_roles` (RLS:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permissions.server.d.ts","sourceRoot":"","sources":["../../src/core/server/permissions.server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"permissions.server.d.ts","sourceRoot":"","sources":["../../src/core/server/permissions.server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA8BhD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAuCvD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACvC,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,KAAK,GAAE,eAAwB,EAC/B,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,GACvB,OAAO,CAAC,eAAe,CAAC,CAyB1B;AAED,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACvC,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACtC,OAAO,CAAC,OAAO,CAAC,CAKlB"}
|
|
@@ -1,5 +1,28 @@
|
|
|
1
|
-
import { getRequest } from "@tanstack/react-start/server";
|
|
2
1
|
import { getRoleFlags } from "../auth/roles.js";
|
|
2
|
+
/**
|
|
3
|
+
* `@tanstack/react-start/server` mag hier **niet** statisch geïmporteerd worden
|
|
4
|
+
* (ook niet als letterlijke `import()`): het trekt `@tanstack/start-server-core`
|
|
5
|
+
* (node:async_hooks) in de bundel. Elke shell waarvan een module `./server` in
|
|
6
|
+
* zijn hoofdbarrel her-exporteert, breekt dan op de clientbuild.
|
|
7
|
+
*
|
|
8
|
+
* De specifier wordt pas ter plaatse in mekaar gezet, zodat geen enkele bundler
|
|
9
|
+
* hem statisch kan ontleden. De import draait dus uitsluitend op de server.
|
|
10
|
+
*/
|
|
11
|
+
const REACT_START_SERVER = ["@tanstack", "react-start", "server"].join("/");
|
|
12
|
+
/** Het actuele verzoek, voor zover de runtime dat prijsgeeft. */
|
|
13
|
+
async function ambientRequest() {
|
|
14
|
+
try {
|
|
15
|
+
const mod = (await import(/* @vite-ignore */ REACT_START_SERVER));
|
|
16
|
+
return mod.getRequest?.() ?? null;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async function readRequestHeader(name, request) {
|
|
23
|
+
const req = request ?? (await ambientRequest());
|
|
24
|
+
return req?.headers?.get(name) ?? null;
|
|
25
|
+
}
|
|
3
26
|
const RANK = { none: 0, view: 1, edit: 2 };
|
|
4
27
|
function isMissingRpc(error) {
|
|
5
28
|
const e = (error ?? {});
|
|
@@ -13,21 +36,17 @@ function isMissingRpc(error) {
|
|
|
13
36
|
message.includes("could not find the function"));
|
|
14
37
|
}
|
|
15
38
|
/** Bearer-token van het huidige verzoek, of null. */
|
|
16
|
-
function requestToken() {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
return header.startsWith("Bearer ") ? header.slice(7) || null : null;
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return null;
|
|
23
|
-
}
|
|
39
|
+
async function requestToken(request) {
|
|
40
|
+
const header = (await readRequestHeader("authorization", request)) ?? "";
|
|
41
|
+
return header.startsWith("Bearer ") ? header.slice(7) || null : null;
|
|
24
42
|
}
|
|
25
43
|
/**
|
|
26
44
|
* Geverifieerde user-id: uitsluitend uit het token van het verzoek, gevalideerd
|
|
27
|
-
* bij Supabase Auth (`getUser(token)`). Geen aanroeper-input
|
|
45
|
+
* bij Supabase Auth (`getUser(token)`). Geen aanroeper-input: een meegegeven
|
|
46
|
+
* `request` is het verzoek zelf, geen ingevulde user-id.
|
|
28
47
|
*/
|
|
29
|
-
async function verifiedUserId(supabase) {
|
|
30
|
-
const token = requestToken();
|
|
48
|
+
async function verifiedUserId(supabase, request) {
|
|
49
|
+
const token = await requestToken(request);
|
|
31
50
|
const { data, error } = token ? await supabase.auth.getUser(token) : await supabase.auth.getUser();
|
|
32
51
|
if (error || !data?.user?.id)
|
|
33
52
|
throw new Response("Unauthorized", { status: 401 });
|
|
@@ -43,9 +62,14 @@ async function verifiedUserId(supabase) {
|
|
|
43
62
|
*
|
|
44
63
|
* - Ontbreekt de RPC (add-on niet geïnstalleerd) → toegestaan (default-allow).
|
|
45
64
|
* - Geen geldige sessie → 401. Onvoldoende rechten → 403.
|
|
65
|
+
*
|
|
66
|
+
* `request` is optioneel: geef `getRequest()` mee (uit de code van je eigen
|
|
67
|
+
* shell, die door de Start-compiler wél getransformeerd wordt) als jouw runtime
|
|
68
|
+
* het actuele verzoek niet zelf blootgeeft. Aan het antwoord verandert niets:
|
|
69
|
+
* het token wordt hoe dan ook bij Supabase Auth gevalideerd.
|
|
46
70
|
*/
|
|
47
|
-
export async function requireModulePermission(supabase, moduleId, featureId = null, level = "view") {
|
|
48
|
-
const userId = await verifiedUserId(supabase);
|
|
71
|
+
export async function requireModulePermission(supabase, moduleId, featureId = null, level = "view", request) {
|
|
72
|
+
const userId = await verifiedUserId(supabase, request);
|
|
49
73
|
const { data, error } = await supabase.rpc("effective_module_permission", {
|
|
50
74
|
_user_id: userId,
|
|
51
75
|
_module_id: moduleId,
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* Flora Select — standaardhuisstijl van core. Afgeleid uit tokens.json.
|
|
2
|
+
Shells met src/brand.generated.css (update-dashboard) overschrijven dit. */
|
|
3
|
+
:root {
|
|
4
|
+
--radius: 8px;
|
|
5
|
+
--background: #F6F7F5; --foreground: #21221F;
|
|
6
|
+
--card: #FFFFFF; --card-foreground: #21221F;
|
|
7
|
+
--popover: #FFFFFF; --popover-foreground: #21221F;
|
|
8
|
+
--primary: #426F14; --primary-foreground: #FFFFFF;
|
|
9
|
+
--secondary: #EEEFEC; --secondary-foreground: #21221F;
|
|
10
|
+
--muted: #EEEFEC; --muted-foreground: #5F625A;
|
|
11
|
+
--accent: #F0FBE9; --accent-foreground: #426F14;
|
|
12
|
+
--destructive: #C64B36; --destructive-foreground: #FFFFFF;
|
|
13
|
+
--destructive-soft: #FFF4F2; --destructive-soft-foreground: #A23725;
|
|
14
|
+
--success: #426F14; --success-foreground: #FFFFFF;
|
|
15
|
+
--success-soft: #F0FBE9; --success-soft-foreground: #426F14;
|
|
16
|
+
--warning: #F4B854; --warning-foreground: #2F1E00;
|
|
17
|
+
--warning-soft: #FFF5E7; --warning-soft-foreground: #805800;
|
|
18
|
+
--info: #166B82; --info-foreground: #FFFFFF;
|
|
19
|
+
--info-soft: #EBFAFF; --info-soft-foreground: #166B82;
|
|
20
|
+
--brand: #6DA43F;
|
|
21
|
+
--border: #DEE0DB; --input: #90938A; --ring: #558A25;
|
|
22
|
+
--chart-1: #6DA43F; --chart-2: #449FBB; --chart-3: #E1A01D;
|
|
23
|
+
--chart-4: #D75841; --chart-5: #C7787E;
|
|
24
|
+
--sidebar: #244008; --sidebar-foreground: #F0FBE9;
|
|
25
|
+
--sidebar-primary: #426F14; --sidebar-primary-foreground: #F0FBE9;
|
|
26
|
+
--sidebar-accent: #426F14; --sidebar-accent-foreground: #F0FBE9;
|
|
27
|
+
--sidebar-border: #31560A; --sidebar-ring: #558A25;
|
|
28
|
+
--sidebar-muted: #BFD7AA;
|
|
29
|
+
}
|
|
30
|
+
.dark {
|
|
31
|
+
--background: #181A16; --foreground: #F6F7F5;
|
|
32
|
+
--card: #21221F; --card-foreground: #F6F7F5;
|
|
33
|
+
--popover: #21221F; --popover-foreground: #F6F7F5;
|
|
34
|
+
--primary: #8EC168; --primary-foreground: #142803;
|
|
35
|
+
--secondary: #121410; --secondary-foreground: #F6F7F5;
|
|
36
|
+
--muted: #121410; --muted-foreground: #ADB1A8;
|
|
37
|
+
--accent: #142803; --accent-foreground: #8EC168;
|
|
38
|
+
--destructive: #FF8972; --destructive-foreground: #3E1008;
|
|
39
|
+
--destructive-soft: #3E1008; --destructive-soft-foreground: #FFB6A6;
|
|
40
|
+
--success: #B0DA93; --success-foreground: #142803;
|
|
41
|
+
--success-soft: #142803; --success-soft-foreground: #B0DA93;
|
|
42
|
+
--warning: #F4B854; --warning-foreground: #2F1E00;
|
|
43
|
+
--warning-soft: #2F1E00; --warning-soft-foreground: #FFCF83;
|
|
44
|
+
--info: #99D5EB; --info-foreground: #142803;
|
|
45
|
+
--info-soft: #042630; --info-soft-foreground: #99D5EB;
|
|
46
|
+
--brand: #6DA43F;
|
|
47
|
+
--border: #494B45; --input: #777A72; --ring: #8EC168;
|
|
48
|
+
--chart-1: #6DA43F; --chart-2: #449FBB; --chart-3: #E1A01D;
|
|
49
|
+
--chart-4: #D75841; --chart-5: #C7787E;
|
|
50
|
+
--sidebar: #142803; --sidebar-foreground: #F0FBE9;
|
|
51
|
+
--sidebar-primary: #31560A; --sidebar-primary-foreground: #F0FBE9;
|
|
52
|
+
--sidebar-accent: #31560A; --sidebar-accent-foreground: #F0FBE9;
|
|
53
|
+
--sidebar-border: #244008; --sidebar-ring: #8EC168;
|
|
54
|
+
--sidebar-muted: #BFD7AA;
|
|
55
|
+
}
|
package/dist/styles.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
2
|
@import "tw-animate-css";
|
|
3
|
-
|
|
3
|
+
@import "./styles/brand-default.css";
|
|
4
4
|
|
|
5
5
|
@custom-variant dark (&:is(.dark *));
|
|
6
6
|
|
|
@@ -34,10 +34,21 @@
|
|
|
34
34
|
--color-accent-foreground: var(--accent-foreground);
|
|
35
35
|
--color-destructive: var(--destructive);
|
|
36
36
|
--color-destructive-foreground: var(--destructive-foreground);
|
|
37
|
+
--color-destructive-soft: var(--destructive-soft);
|
|
38
|
+
--color-destructive-soft-foreground: var(--destructive-soft-foreground);
|
|
37
39
|
--color-success: var(--success);
|
|
38
40
|
--color-success-foreground: var(--success-foreground);
|
|
41
|
+
--color-success-soft: var(--success-soft);
|
|
42
|
+
--color-success-soft-foreground: var(--success-soft-foreground);
|
|
39
43
|
--color-warning: var(--warning);
|
|
40
44
|
--color-warning-foreground: var(--warning-foreground);
|
|
45
|
+
--color-warning-soft: var(--warning-soft);
|
|
46
|
+
--color-warning-soft-foreground: var(--warning-soft-foreground);
|
|
47
|
+
--color-info: var(--info);
|
|
48
|
+
--color-info-foreground: var(--info-foreground);
|
|
49
|
+
--color-info-soft: var(--info-soft);
|
|
50
|
+
--color-info-soft-foreground: var(--info-soft-foreground);
|
|
51
|
+
--color-brand: var(--brand);
|
|
41
52
|
--color-border: var(--border);
|
|
42
53
|
--color-input: var(--input);
|
|
43
54
|
--color-ring: var(--ring);
|
|
@@ -56,47 +67,8 @@
|
|
|
56
67
|
--color-sidebar-ring: var(--sidebar-ring);
|
|
57
68
|
--color-sidebar-muted: var(--sidebar-muted);
|
|
58
69
|
--font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
:root {
|
|
62
|
-
--radius: 0.5rem;
|
|
63
|
-
--background: hsl(210 20% 98%);
|
|
64
|
-
--foreground: hsl(214 79% 15%);
|
|
65
|
-
--card: hsl(0 0% 100%);
|
|
66
|
-
--card-foreground: hsl(214 79% 15%);
|
|
67
|
-
--popover: hsl(0 0% 100%);
|
|
68
|
-
--popover-foreground: hsl(214 79% 15%);
|
|
69
|
-
--primary: hsl(214 79% 33%);
|
|
70
|
-
--primary-foreground: hsl(0 0% 100%);
|
|
71
|
-
--secondary: hsl(214 30% 93%);
|
|
72
|
-
--secondary-foreground: hsl(214 79% 33%);
|
|
73
|
-
--muted: hsl(210 20% 96%);
|
|
74
|
-
--muted-foreground: hsl(214 20% 46%);
|
|
75
|
-
--accent: hsl(214 60% 90%);
|
|
76
|
-
--accent-foreground: hsl(214 79% 25%);
|
|
77
|
-
--destructive: hsl(0 72% 51%);
|
|
78
|
-
--destructive-foreground: hsl(0 0% 100%);
|
|
79
|
-
--success: hsl(142 71% 45%);
|
|
80
|
-
--success-foreground: hsl(0 0% 100%);
|
|
81
|
-
--warning: hsl(38 92% 50%);
|
|
82
|
-
--warning-foreground: hsl(0 0% 100%);
|
|
83
|
-
--border: hsl(214 20% 88%);
|
|
84
|
-
--input: hsl(214 20% 88%);
|
|
85
|
-
--ring: hsl(214 79% 33%);
|
|
86
|
-
--chart-1: hsl(214 79% 33%);
|
|
87
|
-
--chart-2: hsl(142 71% 45%);
|
|
88
|
-
--chart-3: hsl(38 92% 50%);
|
|
89
|
-
--chart-4: hsl(0 72% 51%);
|
|
90
|
-
--chart-5: hsl(280 60% 50%);
|
|
91
|
-
--sidebar: hsl(214 79% 33%);
|
|
92
|
-
--sidebar-foreground: hsl(0 0% 100%);
|
|
93
|
-
--sidebar-primary: hsl(0 0% 100%);
|
|
94
|
-
--sidebar-primary-foreground: hsl(214 79% 33%);
|
|
95
|
-
--sidebar-accent: hsl(214 79% 40%);
|
|
96
|
-
--sidebar-accent-foreground: hsl(0 0% 100%);
|
|
97
|
-
--sidebar-border: hsl(214 79% 45%);
|
|
98
|
-
--sidebar-ring: hsl(0 0% 100%);
|
|
99
|
-
--sidebar-muted: hsl(214 60% 70%);
|
|
70
|
+
--font-display: 'Fraunces', ui-serif, Georgia, serif;
|
|
71
|
+
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
|
|
100
72
|
}
|
|
101
73
|
|
|
102
74
|
@layer base {
|
|
@@ -108,6 +80,25 @@
|
|
|
108
80
|
background-color: var(--color-background);
|
|
109
81
|
color: var(--color-foreground);
|
|
110
82
|
font-family: var(--font-sans);
|
|
83
|
+
font-size: 14px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
:focus-visible {
|
|
87
|
+
outline: 2px solid var(--color-ring) !important;
|
|
88
|
+
outline-offset: 2px !important;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
code, kbd, pre, .font-mono {
|
|
92
|
+
font-family: var(--font-mono);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.font-display, [data-empty-state] {
|
|
96
|
+
font-family: var(--font-display);
|
|
97
|
+
font-variation-settings: 'SOFT' 100;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
table td, table th {
|
|
101
|
+
font-variant-numeric: tabular-nums;
|
|
111
102
|
}
|
|
112
103
|
|
|
113
104
|
.sidebar-scroll::-webkit-scrollbar {
|