@deenruv/admin-dashboard 1.0.17-dev.17 → 1.0.17-dev.18
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/components/BrandLogo.js +5 -5
- package/dist/components/Menu/AccountMenu.js +58 -0
- package/dist/components/Menu/Navigation.js +56 -73
- package/dist/components/Menu/NavigationFooter.js +12 -6
- package/dist/components/Menu/SidebarContent.js +9 -0
- package/dist/components/Menu/SidebarState.js +93 -0
- package/dist/components/Menu/TopbarOverflow.js +9 -0
- package/dist/components/Menu/index.js +27 -86
- package/dist/index.css +65 -0
- package/dist/locales/en/common.json +41 -28
- package/dist/locales/pl/common.json +42 -29
- package/dist/version.js +1 -1
- package/package.json +5 -5
|
@@ -6,17 +6,17 @@ export const BrandLogo = ({ isCollapsed = false }) => {
|
|
|
6
6
|
let Logo = null;
|
|
7
7
|
if (isCollapsed) {
|
|
8
8
|
if (typeof collapsed === 'string')
|
|
9
|
-
Logo = _jsx("img", { src: collapsed, alt: "
|
|
9
|
+
Logo = _jsx("img", { src: collapsed, alt: "", className: "size-full object-contain" });
|
|
10
10
|
if (typeof collapsed === 'object')
|
|
11
|
-
Logo = React.cloneElement(collapsed, { className: 'object-contain' });
|
|
11
|
+
Logo = React.cloneElement(collapsed, { className: 'size-full object-contain' });
|
|
12
12
|
}
|
|
13
13
|
if (!isCollapsed) {
|
|
14
14
|
if (typeof full === 'string')
|
|
15
|
-
Logo = _jsx("img", { src: full, alt: "
|
|
15
|
+
Logo = _jsx("img", { src: full, alt: "", className: "size-full object-contain" });
|
|
16
16
|
if (typeof full === 'object')
|
|
17
|
-
Logo = React.cloneElement(full, { className: 'object-contain' });
|
|
17
|
+
Logo = React.cloneElement(full, { className: 'size-full object-contain' });
|
|
18
18
|
}
|
|
19
19
|
if (!Logo)
|
|
20
|
-
return (_jsxs("svg", {
|
|
20
|
+
return (_jsxs("svg", { className: "size-full", viewBox: "0 0 200 60", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: [_jsx("defs", { children: _jsxs("filter", { id: "shadow", x: "-50%", y: "-50%", width: "200%", height: "200%", children: [_jsx("feOffset", { result: "offOut", in: "SourceAlpha", dx: "2", dy: "2" }), _jsx("feGaussianBlur", { result: "blurOut", in: "offOut", stdDeviation: "2" }), _jsx("feBlend", { in: "SourceGraphic", in2: "blurOut", mode: "normal" })] }) }), _jsx("text", { x: "50%", y: "50%", textAnchor: "middle", fill: "black", fontSize: "24", fontWeight: "bold", dy: ".3em", children: isCollapsed ? name?.charAt?.(0) : name }), _jsx("text", { x: "50%", y: "50%", textAnchor: "middle", fill: "#ffffff", fontSize: "24", fontWeight: "bold", dy: ".3em", filter: "url(#shadow)", opacity: "0.9", children: isCollapsed ? name?.charAt?.(0) : name })] }));
|
|
21
21
|
return _jsx(_Fragment, { children: Logo });
|
|
22
22
|
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { apiClient, Button, cn, createDialog, DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, Tooltip, TooltipContent, TooltipTrigger, usePluginStore, useServer, useSettings, useTranslation, } from '@deenruv/react-ui-devkit';
|
|
3
|
+
import { Permission } from '@deenruv/admin-types';
|
|
4
|
+
import { LogOutIcon, RotateCwSquare } from 'lucide-react';
|
|
5
|
+
import { useNavigate } from 'react-router';
|
|
6
|
+
import { canAccessAdminItem, useAdminAccess } from "../../access/index.js";
|
|
7
|
+
const accountMenuItemClass = 'cursor-pointer gap-2 focus:bg-[var(--sidebar-hover)] focus:text-[var(--sidebar-ink)]';
|
|
8
|
+
const accountMenuSurfaceClass = 'border-[var(--sidebar-hairline)] bg-[var(--sidebar-surface)] text-[var(--sidebar-ink)] shadow-sm dark:shadow-none';
|
|
9
|
+
export const AccountMenu = ({ isCollapsed, mode, onNavigate, }) => {
|
|
10
|
+
const { t } = useTranslation('common');
|
|
11
|
+
const navigate = useNavigate();
|
|
12
|
+
const { routes } = useAdminAccess();
|
|
13
|
+
const { topNavigationActionsMenu } = usePluginStore();
|
|
14
|
+
const { logOut } = useSettings();
|
|
15
|
+
const { activeAdministrator, clearAdministratorAccess, setJobQueue, userPermissions } = useServer();
|
|
16
|
+
const administratorName = activeAdministrator
|
|
17
|
+
? `${activeAdministrator.firstName} ${activeAdministrator.lastName}`.trim()
|
|
18
|
+
: t('account');
|
|
19
|
+
const initials = activeAdministrator
|
|
20
|
+
? `${activeAdministrator.firstName.charAt(0)}${activeAdministrator.lastName.charAt(0)}`.toUpperCase()
|
|
21
|
+
: '?';
|
|
22
|
+
const reindexEnabled = canAccessAdminItem({
|
|
23
|
+
item: { requiredPermissions: [Permission.UpdateCatalog, Permission.UpdateProduct] },
|
|
24
|
+
userPermissions,
|
|
25
|
+
});
|
|
26
|
+
const allowedActions = topNavigationActionsMenu?.filter((entry) => canAccessAdminItem({ item: entry.access, userPermissions }));
|
|
27
|
+
const fastLinks = [
|
|
28
|
+
{ key: 'systemStatus', route: routes.find((route) => route.id === 'system.status') },
|
|
29
|
+
{ key: 'globalSettings', route: routes.find((route) => route.id === 'settings.global') },
|
|
30
|
+
].filter(({ route }) => route && canAccessAdminItem({ item: route, userPermissions }));
|
|
31
|
+
const rebuildSearchIndex = async () => {
|
|
32
|
+
const { reindex } = await apiClient('mutation')({ reindex: { id: true, queueName: true, state: true } });
|
|
33
|
+
setJobQueue(reindex.queueName, reindex.state === 'RUNNING');
|
|
34
|
+
};
|
|
35
|
+
const trigger = (_jsxs(Button, { variant: "ghost", className: isCollapsed
|
|
36
|
+
? 'size-8 rounded-[4px] p-0 text-[var(--sidebar-secondary)] hover:bg-[var(--sidebar-hover)] hover:text-[var(--sidebar-ink)] focus-visible:ring-[var(--sidebar-focus)]'
|
|
37
|
+
: 'sidebar-row mx-2 w-[calc(100%-1rem)] justify-start bg-transparent focus-visible:ring-[var(--sidebar-focus)]', "aria-label": t('openAccountMenu'), children: [_jsx("span", { className: "sidebar-icon-slot rounded-[4px] bg-[var(--sidebar-active)] text-[10px] font-medium text-[var(--sidebar-active-ink)]", children: initials }), !isCollapsed && (_jsxs("span", { className: "min-w-0 flex-1 text-left", children: [_jsx("span", { className: "block truncate text-sm font-medium text-[var(--sidebar-ink)]", children: administratorName }), activeAdministrator?.emailAddress && (_jsx("span", { className: "block truncate text-xs font-normal text-[var(--sidebar-tertiary)]", children: activeAdministrator.emailAddress }))] }))] }));
|
|
38
|
+
return (_jsxs(DropdownMenu, { children: [isCollapsed ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx(DropdownMenuTrigger, { asChild: true, children: trigger }) }), _jsx(TooltipContent, { side: "right", children: administratorName })] })) : (_jsx(DropdownMenuTrigger, { asChild: true, children: trigger })), _jsxs(DropdownMenuContent, { side: mode === 'mobile' ? 'top' : 'right', align: mode === 'mobile' ? 'start' : 'end', sideOffset: 6, collisionPadding: 8, className: cn('z-[150] min-w-56', accountMenuSurfaceClass), children: [activeAdministrator?.emailAddress && (_jsxs(_Fragment, { children: [_jsxs(DropdownMenuLabel, { children: [_jsx("span", { className: "block truncate", children: administratorName }), _jsx("span", { className: "block truncate text-xs font-normal text-[var(--sidebar-tertiary)]", children: activeAdministrator.emailAddress })] }), _jsx(DropdownMenuSeparator, { className: "bg-[var(--sidebar-hairline)]" })] })), reindexEnabled && (_jsxs(DropdownMenuItem, { className: accountMenuItemClass, onSelect: rebuildSearchIndex, children: [_jsx(RotateCwSquare, { className: "size-4" }), t('rebuildSerachIndex')] })), fastLinks.length > 0 && (_jsx(DropdownMenuGroup, { children: _jsxs(DropdownMenuSub, { children: [_jsx(DropdownMenuSubTrigger, { className: "focus:bg-[var(--sidebar-hover)] focus:text-[var(--sidebar-ink)]", children: t('fastLinks') }), _jsx(DropdownMenuPortal, { children: _jsx(DropdownMenuSubContent, { className: accountMenuSurfaceClass, children: fastLinks.map(({ key, route }) => (_jsxs(DropdownMenuItem, { className: accountMenuItemClass, onSelect: () => {
|
|
39
|
+
navigate(route.path, { viewTransition: true });
|
|
40
|
+
onNavigate?.();
|
|
41
|
+
}, children: [_jsx(RotateCwSquare, { className: "size-4" }), t(key)] }, key))) }) })] }) })), allowedActions?.length ? (_jsxs(_Fragment, { children: [_jsx(DropdownMenuSeparator, { className: "bg-[var(--sidebar-hairline)]" }), allowedActions.map((action) => (_jsxs(DropdownMenuItem, { className: cn(accountMenuItemClass, action.className), onSelect: () => {
|
|
42
|
+
action.onClick();
|
|
43
|
+
onNavigate?.();
|
|
44
|
+
}, children: [action.icon && _jsx(action.icon, { className: "size-4" }), action.label] }, action.label)))] })) : null, _jsx(DropdownMenuSeparator, { className: "bg-[var(--sidebar-hairline)]" }), _jsxs(DropdownMenuItem, { className: cn(accountMenuItemClass, 'text-red-500 focus:text-red-500'), onSelect: async () => {
|
|
45
|
+
const confirmed = await createDialog({
|
|
46
|
+
title: t('logOutConfirmation'),
|
|
47
|
+
description: t('logOutConfirmationDescription'),
|
|
48
|
+
buttons: [
|
|
49
|
+
{ label: t('cancel'), variant: 'secondary', returnValue: false },
|
|
50
|
+
{ label: t('logOut'), variant: 'destructive', returnValue: true },
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
if (confirmed) {
|
|
54
|
+
clearAdministratorAccess();
|
|
55
|
+
logOut();
|
|
56
|
+
}
|
|
57
|
+
}, children: [_jsx(LogOutIcon, { className: "size-4" }), t('logOut')] })] })] }));
|
|
58
|
+
};
|
|
@@ -1,38 +1,35 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo } from 'react';
|
|
2
3
|
import { NavLink, useLocation } from 'react-router';
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
export function Navigation({ isCollapsed }) {
|
|
4
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Button, cn, Skeleton, Tooltip, TooltipContent, TooltipTrigger, useNotifications, usePluginStore, useServer, useTranslation, } from '@deenruv/react-ui-devkit';
|
|
5
|
+
import { adminNavigationGroups, canAccessAdminItem, getActiveNavigationGroupIds, getActiveNavigationLinkIds, getNavigationLinkActivePaths, insertNavigationLink, useAdminAccess, } from "../../access/index.js";
|
|
6
|
+
import { mergeOpenGroupIds } from './SidebarState.js';
|
|
7
|
+
export function Navigation({ isCollapsed, manuallyOpenGroupIds, onExpand, onOpenGroupIdsChange, onNavigate, }) {
|
|
7
8
|
const { t } = useTranslation('common');
|
|
8
|
-
const { t:
|
|
9
|
+
const { t: pluginTranslation } = useTranslation();
|
|
9
10
|
const location = useLocation();
|
|
10
11
|
const { navMenuData, viewMarkers } = usePluginStore();
|
|
11
12
|
const { routes } = useAdminAccess();
|
|
12
|
-
const userPermissions = useServer((
|
|
13
|
-
const loaded = useServer((
|
|
13
|
+
const userPermissions = useServer((state) => state.userPermissions);
|
|
14
|
+
const loaded = useServer((state) => state.loaded);
|
|
14
15
|
const getNavigationNotification = useNotifications(({ getNavigationNotification }) => getNavigationNotification);
|
|
15
|
-
const pluginT = (
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
const ns = split[0] || '';
|
|
19
|
-
return _pluginT(key, { ns });
|
|
16
|
+
const pluginT = (translation) => {
|
|
17
|
+
const [namespace = '', ...keyParts] = translation.split('.');
|
|
18
|
+
return pluginTranslation(keyParts.join('.'), { ns: namespace });
|
|
20
19
|
};
|
|
21
20
|
const navigationGroups = useMemo(() => {
|
|
22
|
-
const
|
|
21
|
+
const groups = adminNavigationGroups.map((group) => ({
|
|
23
22
|
label: t(`menuGroups.${group.labelKey}`),
|
|
24
23
|
id: group.id,
|
|
25
24
|
links: [],
|
|
26
25
|
}));
|
|
27
26
|
routes.forEach((route) => {
|
|
28
|
-
if (!route.nav)
|
|
27
|
+
if (!route.nav || !canAccessAdminItem({ item: route, userPermissions }))
|
|
29
28
|
return;
|
|
30
|
-
|
|
29
|
+
const group = groups.find((candidate) => candidate.id === route.nav?.groupId);
|
|
30
|
+
if (!group)
|
|
31
31
|
return;
|
|
32
|
-
|
|
33
|
-
if (foundGroupIdx === -1)
|
|
34
|
-
return;
|
|
35
|
-
navData[foundGroupIdx].links.push({
|
|
32
|
+
group.links.push({
|
|
36
33
|
title: t(`menu.${route.nav.menuKey}`),
|
|
37
34
|
href: route.path,
|
|
38
35
|
id: route.nav.linkId,
|
|
@@ -43,68 +40,54 @@ export function Navigation({ isCollapsed }) {
|
|
|
43
40
|
activePaths: getNavigationLinkActivePaths(route, routes),
|
|
44
41
|
});
|
|
45
42
|
});
|
|
46
|
-
|
|
47
|
-
groups.forEach(({ id, labelId, placement, access }) => {
|
|
43
|
+
navMenuData.groups.forEach(({ id, labelId, placement, access }) => {
|
|
48
44
|
if (!canAccessAdminItem({ item: access, userPermissions }))
|
|
49
45
|
return;
|
|
50
|
-
|
|
51
|
-
const
|
|
52
|
-
if (
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
navData.push(newGroup);
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
59
|
-
navData.splice(foundGroupIdx + 1, 0, newGroup);
|
|
60
|
-
}
|
|
46
|
+
const nextGroup = { id, label: pluginT(labelId), links: [] };
|
|
47
|
+
const anchorIndex = placement?.groupId ? groups.findIndex((group) => group.id === placement.groupId) : -1;
|
|
48
|
+
if (anchorIndex === -1)
|
|
49
|
+
groups.push(nextGroup);
|
|
50
|
+
else
|
|
51
|
+
groups.splice(anchorIndex + 1, 0, nextGroup);
|
|
61
52
|
});
|
|
62
|
-
links.forEach(({ groupId, href, labelId, id, icon, placement, access }) => {
|
|
53
|
+
navMenuData.links.forEach(({ groupId, href, labelId, id, icon, placement, access }) => {
|
|
63
54
|
if (!canAccessAdminItem({ item: access, userPermissions }))
|
|
64
55
|
return;
|
|
65
|
-
const
|
|
66
|
-
if (
|
|
67
|
-
return;
|
|
68
|
-
const newElement = {
|
|
69
|
-
title: pluginT(labelId),
|
|
70
|
-
label: pluginT(labelId),
|
|
71
|
-
href: `/${href}`,
|
|
72
|
-
id,
|
|
73
|
-
icon,
|
|
74
|
-
access,
|
|
75
|
-
groupId,
|
|
76
|
-
};
|
|
77
|
-
if (!placement) {
|
|
78
|
-
navData[foundGroupIdx].links.push(newElement);
|
|
56
|
+
const group = groups.find((candidate) => candidate.id === groupId);
|
|
57
|
+
if (!group)
|
|
79
58
|
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
59
|
+
const link = { title: pluginT(labelId), href: `/${href}`, id, icon, access, groupId };
|
|
60
|
+
group.links = insertNavigationLink(group.links, link, placement);
|
|
82
61
|
});
|
|
83
|
-
return
|
|
84
|
-
}, [navMenuData.groups, navMenuData.links,
|
|
85
|
-
const
|
|
86
|
-
const activeGroupIds = useMemo(() => getActiveNavigationGroupIds(
|
|
87
|
-
const activeLinkIds = useMemo(() => new Set(getActiveNavigationLinkIds(
|
|
88
|
-
const
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (!hasPathnameChanged)
|
|
94
|
-
return;
|
|
95
|
-
setOpenGroupIds((currentGroupIds) => {
|
|
96
|
-
const nextGroupIds = [...new Set([...currentGroupIds, ...activeGroupIds])];
|
|
97
|
-
return nextGroupIds.length === currentGroupIds.length ? currentGroupIds : nextGroupIds;
|
|
98
|
-
});
|
|
99
|
-
}, [activeGroupIds, location.pathname]);
|
|
62
|
+
return groups.filter((group) => group.links.length > 0);
|
|
63
|
+
}, [navMenuData.groups, navMenuData.links, pluginTranslation, routes, t, userPermissions]);
|
|
64
|
+
const allLinks = useMemo(() => navigationGroups.flatMap((group) => group.links), [navigationGroups]);
|
|
65
|
+
const activeGroupIds = useMemo(() => getActiveNavigationGroupIds(allLinks, location.pathname), [allLinks, location.pathname]);
|
|
66
|
+
const activeLinkIds = useMemo(() => new Set(getActiveNavigationLinkIds(allLinks, location.pathname).map((link) => link.id)), [allLinks, location.pathname]);
|
|
67
|
+
const openGroupIds = useMemo(() => mergeOpenGroupIds(manuallyOpenGroupIds, activeGroupIds), [activeGroupIds, manuallyOpenGroupIds]);
|
|
68
|
+
const updateOpenGroups = (groupIds) => {
|
|
69
|
+
const nextGroupIds = mergeOpenGroupIds(groupIds, activeGroupIds);
|
|
70
|
+
onOpenGroupIdsChange(nextGroupIds);
|
|
71
|
+
};
|
|
100
72
|
if (!loaded) {
|
|
101
|
-
return (_jsx("div", { className: "
|
|
73
|
+
return (_jsx("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto px-2 py-3", children: Array.from({ length: 10 }).map((_, index) => (_jsxs("div", { className: cn('flex h-8 items-center gap-2 px-2', isCollapsed && 'justify-center px-0'), children: [_jsx(Skeleton, { className: "size-5 shrink-0 bg-[var(--sidebar-hairline)]" }), !isCollapsed && _jsx(Skeleton, { className: "h-3 w-24 bg-[var(--sidebar-hairline)]" })] }, index))) }));
|
|
102
74
|
}
|
|
103
|
-
return (_jsx("div", { className: "
|
|
104
|
-
|
|
75
|
+
return (_jsx("div", { className: "min-h-0 flex-1 overflow-y-auto py-2", children: _jsx(Accordion, { type: "multiple", value: openGroupIds, onValueChange: updateOpenGroups, className: "w-full", children: navigationGroups.map((group) => {
|
|
76
|
+
const firstLink = group.links[0];
|
|
77
|
+
const isGroupActive = activeGroupIds.includes(group.id);
|
|
78
|
+
if (isCollapsed) {
|
|
79
|
+
const isSingleLink = group.links.length === 1;
|
|
80
|
+
const collapsedControl = (_jsx("div", { className: "flex size-8 items-center justify-center", children: isSingleLink ? (_jsx(NavLink, { to: firstLink.href, viewTransition: true, onClick: onNavigate, "aria-current": activeLinkIds.has(firstLink.id) ? 'page' : undefined, className: "sidebar-link group/sidebar-link", children: _jsxs("span", { className: cn('flex size-8 items-center justify-center rounded-[4px] text-[var(--sidebar-secondary)] transition-colors group-focus-visible/sidebar-link:ring-2 group-focus-visible/sidebar-link:ring-[var(--sidebar-focus)] group-focus-visible/sidebar-link:outline-none hover:bg-[var(--sidebar-hover)] hover:text-[var(--sidebar-ink)]', activeLinkIds.has(firstLink.id) &&
|
|
81
|
+
'bg-[var(--sidebar-active)] text-[var(--sidebar-active-ink)] shadow-[inset_2px_0_0_var(--sidebar-active-indicator)]'), children: [_jsx(firstLink.icon, { className: "size-4" }), _jsx("span", { className: "sr-only", children: firstLink.title })] }) })) : (_jsx(Button, { variant: "ghost", size: "icon", className: cn('size-8 rounded-[4px] text-[var(--sidebar-secondary)] hover:bg-[var(--sidebar-hover)] hover:text-[var(--sidebar-ink)] focus-visible:ring-[var(--sidebar-focus)]', isGroupActive &&
|
|
82
|
+
'bg-[var(--sidebar-active)] text-[var(--sidebar-active-ink)] shadow-[inset_2px_0_0_var(--sidebar-active-indicator)]'), onClick: () => {
|
|
83
|
+
updateOpenGroups([...openGroupIds, group.id]);
|
|
84
|
+
onExpand();
|
|
85
|
+
}, "aria-label": t('expandNavigationGroup', { group: group.label }), children: _jsx(firstLink.icon, { className: "size-4" }) })) }));
|
|
86
|
+
return (_jsx("div", { className: "flex justify-center py-0.5", children: _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: collapsedControl }), _jsxs(TooltipContent, { side: "right", className: "flex items-center gap-2", children: [_jsx("span", { children: isSingleLink ? firstLink.title : group.label }), getNavigationNotification(isSingleLink ? firstLink.id : group.id), viewMarkers && _jsx("span", { className: "text-xs text-[var(--sidebar-tertiary)]", children: group.id })] })] }) }, group.id));
|
|
87
|
+
}
|
|
88
|
+
return (_jsxs(AccordionItem, { value: group.id, className: "border-none px-2", children: [_jsx(AccordionTrigger, { className: "h-8 px-2 py-0 text-xs font-medium tracking-normal text-[var(--sidebar-secondary)] hover:text-[var(--sidebar-ink)] hover:no-underline", children: _jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-2 text-left", children: [_jsx("span", { className: "truncate", children: group.label }), _jsxs("span", { className: "ml-auto flex shrink-0 items-center gap-1", children: [getNavigationNotification(group.id), viewMarkers && _jsx("span", { className: "text-[10px] font-normal", children: group.id })] })] }) }), _jsx(AccordionContent, { className: "pb-1", children: _jsx("nav", { id: group.id, "aria-label": group.label, className: "grid gap-0.5", children: group.links.map((link) => {
|
|
105
89
|
const isActive = activeLinkIds.has(link.id);
|
|
106
|
-
return (_jsx(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
}) }) })] }, group.id))) }) }) }));
|
|
90
|
+
return (_jsx(NavLink, { to: link.href, viewTransition: true, onClick: onNavigate, "aria-current": isActive ? 'page' : undefined, className: "sidebar-link group/sidebar-link", children: _jsxs("span", { className: "sidebar-row group-focus-visible/sidebar-link:ring-2 group-focus-visible/sidebar-link:ring-[var(--sidebar-focus)] group-focus-visible/sidebar-link:outline-none", "data-active": isActive, children: [_jsx("span", { className: "sidebar-icon-slot", children: _jsx(link.icon, { className: "size-4" }) }), _jsx("span", { className: "min-w-0 flex-1 truncate", children: link.title }), _jsxs("span", { className: "ml-auto flex shrink-0 items-center gap-1", children: [getNavigationNotification(link.id), viewMarkers && (_jsx("span", { className: "text-[10px] font-normal text-[var(--sidebar-tertiary)]", children: link.id }))] })] }) }, link.id));
|
|
91
|
+
}) }) })] }, group.id));
|
|
92
|
+
}) }) }));
|
|
110
93
|
}
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
-
import {
|
|
2
|
+
import { cn, Routes, Separator, Tooltip, TooltipContent, TooltipTrigger, useServer, useTranslation, } from '@deenruv/react-ui-devkit';
|
|
3
3
|
import { Puzzle } from 'lucide-react';
|
|
4
4
|
import { NavLink } from 'react-router';
|
|
5
5
|
import { canAccessAdminItem, useAdminAccess } from "../../access/index.js";
|
|
6
|
-
|
|
6
|
+
import { AccountMenu } from './AccountMenu.js';
|
|
7
|
+
export const NavigationFooter = ({ isCollapsed, mode, onNavigate }) => {
|
|
7
8
|
const { t } = useTranslation('common');
|
|
8
|
-
const userPermissions = useServer((
|
|
9
|
+
const userPermissions = useServer((state) => state.userPermissions);
|
|
9
10
|
const { routes } = useAdminAccess();
|
|
10
11
|
const extensionsRoute = routes.find((route) => route.id === 'extensions');
|
|
11
|
-
const
|
|
12
|
+
const canAccessExtensions = !!extensionsRoute && canAccessAdminItem({ item: extensionsRoute, userPermissions });
|
|
12
13
|
const extensionsPath = extensionsRoute?.path || Routes.extensions;
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
const version = window.__DEENRUV_SETTINGS__.appVersion;
|
|
15
|
+
const extensionsLink = (_jsx(NavLink, { to: extensionsPath, viewTransition: true, onClick: onNavigate, "aria-label": t('menu.extensions'), className: "sidebar-link group/sidebar-link", children: ({ isActive }) => (_jsxs("span", { className: cn(isCollapsed
|
|
16
|
+
? 'mx-auto flex size-8 items-center justify-center rounded-[4px] text-[var(--sidebar-secondary)] transition-colors hover:bg-[var(--sidebar-hover)] hover:text-[var(--sidebar-ink)]'
|
|
17
|
+
: 'sidebar-row mx-2', 'group-focus-visible/sidebar-link:ring-2 group-focus-visible/sidebar-link:ring-[var(--sidebar-focus)] group-focus-visible/sidebar-link:outline-none', isCollapsed &&
|
|
18
|
+
isActive &&
|
|
19
|
+
'bg-[var(--sidebar-active)] text-[var(--sidebar-active-ink)] shadow-[inset_2px_0_0_var(--sidebar-active-indicator)]'), "data-active": !isCollapsed && isActive, children: [isCollapsed ? (_jsx(Puzzle, { className: "size-4" })) : (_jsx("span", { className: "sidebar-icon-slot", children: _jsx(Puzzle, { className: "size-4" }) })), !isCollapsed && _jsx("span", { className: "truncate", children: t('menu.extensions') })] })) }));
|
|
20
|
+
return (_jsxs("div", { className: "shrink-0 border-t border-[var(--sidebar-hairline)] bg-[var(--sidebar-surface)] py-2 text-xs text-[var(--sidebar-secondary)]", children: [canAccessExtensions && (_jsxs(_Fragment, { children: [isCollapsed ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("div", { className: "flex h-8 items-center justify-center", children: extensionsLink }) }), _jsx(TooltipContent, { side: "right", children: t('menu.extensions') })] })) : (extensionsLink), _jsx(Separator, { className: "my-2 bg-[var(--sidebar-hairline)]" })] })), isCollapsed ? (_jsx("div", { className: "flex justify-center", children: _jsx(AccountMenu, { isCollapsed: true, mode: mode, onNavigate: onNavigate }) })) : (_jsx(AccountMenu, { isCollapsed: false, mode: mode, onNavigate: onNavigate })), isCollapsed ? (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs("div", { className: "mx-auto mt-2 max-w-10 truncate px-1 text-center text-[10px] text-[var(--sidebar-tertiary)]", children: ["v ", version] }) }), _jsxs(TooltipContent, { side: "right", children: [t('versionAbbreviation'), " ", version] })] })) : (_jsxs("div", { className: "mt-2 flex h-8 items-center gap-1 px-4 text-xs text-[var(--sidebar-tertiary)]", children: [_jsx("span", { children: "Deenruv" }), _jsxs("span", { children: [t('versionAbbreviation'), " ", version] })] }))] }));
|
|
15
21
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, cn, useTranslation } from '@deenruv/react-ui-devkit';
|
|
3
|
+
import { BrandLogo } from "../BrandLogo.js";
|
|
4
|
+
import { Navigation } from './Navigation.js';
|
|
5
|
+
import { NavigationFooter } from './NavigationFooter.js';
|
|
6
|
+
export const SidebarContent = ({ isCollapsed, manuallyOpenGroupIds, mode, onExpand, onOpenGroupIdsChange, onNavigate, onNavigateHome, }) => {
|
|
7
|
+
const { t } = useTranslation('common');
|
|
8
|
+
return (_jsxs("div", { className: "deenruv-sidebar flex h-full min-h-0 flex-col bg-[var(--sidebar-canvas)] text-[var(--sidebar-ink)]", children: [_jsx("div", { className: cn('flex h-16 shrink-0 items-center border-b border-[var(--sidebar-hairline)] px-2 lg:h-[72px]', isCollapsed ? 'justify-center' : 'pr-10'), children: _jsx(Button, { variant: "ghost", className: cn('h-12 rounded-[4px] px-2 text-[var(--sidebar-ink)] hover:bg-[var(--sidebar-hover)] hover:text-[var(--sidebar-ink)] focus-visible:ring-[var(--sidebar-focus)]', isCollapsed ? 'size-8 p-1' : 'w-full justify-start'), onClick: onNavigateHome, "aria-label": t('goToDashboard'), title: t('goToDashboard'), children: _jsx("span", { className: cn('flex shrink-0 items-center justify-center', isCollapsed ? 'size-6' : 'h-10 w-full min-w-0'), children: _jsx(BrandLogo, { isCollapsed: isCollapsed }) }) }) }), _jsx(Navigation, { isCollapsed: isCollapsed, manuallyOpenGroupIds: manuallyOpenGroupIds, onExpand: onExpand, onOpenGroupIdsChange: onOpenGroupIdsChange, onNavigate: onNavigate }), _jsx(NavigationFooter, { isCollapsed: isCollapsed, mode: mode, onNavigate: onNavigate })] }));
|
|
9
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { useCallback, useEffect, useState } from 'react';
|
|
2
|
+
export const SIDEBAR_COLLAPSED_STORAGE_KEY = 'deenruv:admin-sidebar:v1:collapsed';
|
|
3
|
+
export const SIDEBAR_GROUPS_STORAGE_KEY = 'deenruv:admin-sidebar:v1:open-groups';
|
|
4
|
+
export const parseStoredCollapsed = (value, fallback = false) => {
|
|
5
|
+
if (value === 'true')
|
|
6
|
+
return true;
|
|
7
|
+
if (value === 'false')
|
|
8
|
+
return false;
|
|
9
|
+
return fallback;
|
|
10
|
+
};
|
|
11
|
+
export const parseStoredGroupIds = (value) => {
|
|
12
|
+
if (!value)
|
|
13
|
+
return [];
|
|
14
|
+
try {
|
|
15
|
+
const parsed = JSON.parse(value);
|
|
16
|
+
return Array.isArray(parsed) ? [...new Set(parsed.filter((id) => typeof id === 'string'))] : [];
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
export const mergeOpenGroupIds = (storedGroupIds, activeGroupIds) => [
|
|
23
|
+
...new Set([...storedGroupIds, ...activeGroupIds]),
|
|
24
|
+
];
|
|
25
|
+
export const readSidebarStorage = (key) => {
|
|
26
|
+
try {
|
|
27
|
+
return window.localStorage.getItem(key);
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
export const writeSidebarStorage = (key, value) => {
|
|
34
|
+
try {
|
|
35
|
+
window.localStorage.setItem(key, value);
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Navigation remains usable when browser storage is unavailable.
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const getInitialCollapsed = () => typeof window === 'undefined' ? false : parseStoredCollapsed(readSidebarStorage(SIDEBAR_COLLAPSED_STORAGE_KEY));
|
|
42
|
+
const getInitialOpenGroupIds = () => typeof window === 'undefined' ? [] : parseStoredGroupIds(readSidebarStorage(SIDEBAR_GROUPS_STORAGE_KEY));
|
|
43
|
+
export const useSidebarState = () => {
|
|
44
|
+
const [isCollapsed, setIsCollapsedState] = useState(getInitialCollapsed);
|
|
45
|
+
const [isMobileOpen, setIsMobileOpen] = useState(false);
|
|
46
|
+
const [manuallyOpenGroupIds, setManuallyOpenGroupIdsState] = useState(getInitialOpenGroupIds);
|
|
47
|
+
const setIsCollapsed = useCallback((collapsed) => {
|
|
48
|
+
setIsCollapsedState(collapsed);
|
|
49
|
+
writeSidebarStorage(SIDEBAR_COLLAPSED_STORAGE_KEY, String(collapsed));
|
|
50
|
+
}, []);
|
|
51
|
+
const toggleDesktop = useCallback(() => {
|
|
52
|
+
setIsCollapsedState((collapsed) => {
|
|
53
|
+
const nextCollapsed = !collapsed;
|
|
54
|
+
writeSidebarStorage(SIDEBAR_COLLAPSED_STORAGE_KEY, String(nextCollapsed));
|
|
55
|
+
return nextCollapsed;
|
|
56
|
+
});
|
|
57
|
+
}, []);
|
|
58
|
+
const setManuallyOpenGroupIds = useCallback((groupIds) => {
|
|
59
|
+
const nextGroupIds = [...new Set(groupIds)];
|
|
60
|
+
setManuallyOpenGroupIdsState(nextGroupIds);
|
|
61
|
+
writeSidebarStorage(SIDEBAR_GROUPS_STORAGE_KEY, JSON.stringify(nextGroupIds));
|
|
62
|
+
}, []);
|
|
63
|
+
useEffect(() => {
|
|
64
|
+
const handleShortcut = (event) => {
|
|
65
|
+
const target = event.target;
|
|
66
|
+
const isEditable = target instanceof HTMLElement &&
|
|
67
|
+
(target.isContentEditable || ['INPUT', 'TEXTAREA', 'SELECT'].includes(target.tagName));
|
|
68
|
+
if (event.key.toLowerCase() !== 'b' ||
|
|
69
|
+
(!event.metaKey && !event.ctrlKey) ||
|
|
70
|
+
event.altKey ||
|
|
71
|
+
event.shiftKey ||
|
|
72
|
+
isEditable) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
event.preventDefault();
|
|
76
|
+
if (window.matchMedia('(min-width: 768px)').matches)
|
|
77
|
+
toggleDesktop();
|
|
78
|
+
else
|
|
79
|
+
setIsMobileOpen((open) => !open);
|
|
80
|
+
};
|
|
81
|
+
window.addEventListener('keydown', handleShortcut);
|
|
82
|
+
return () => window.removeEventListener('keydown', handleShortcut);
|
|
83
|
+
}, [toggleDesktop]);
|
|
84
|
+
return {
|
|
85
|
+
isCollapsed,
|
|
86
|
+
isMobileOpen,
|
|
87
|
+
manuallyOpenGroupIds,
|
|
88
|
+
setIsCollapsed,
|
|
89
|
+
setIsMobileOpen,
|
|
90
|
+
setManuallyOpenGroupIds,
|
|
91
|
+
toggleDesktop,
|
|
92
|
+
};
|
|
93
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Popover, PopoverContent, PopoverTrigger, useTranslation, } from '@deenruv/react-ui-devkit';
|
|
3
|
+
import { SlidersHorizontal } from 'lucide-react';
|
|
4
|
+
import { ChannelSwitcher } from './ChannelSwitcher.js';
|
|
5
|
+
import { LanguagesDropdown } from './LanguagesDropdown.js';
|
|
6
|
+
export const TopbarOverflow = ({ components }) => {
|
|
7
|
+
const { t } = useTranslation('common');
|
|
8
|
+
return (_jsxs(Popover, { children: [_jsx(PopoverTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", size: "icon", className: "size-9 shrink-0 lg:hidden", "aria-label": t('openTopbarControls'), title: t('openTopbarControls'), children: _jsx(SlidersHorizontal, { className: "size-4" }) }) }), _jsx(PopoverContent, { align: "end", className: "z-[2138] w-[min(20rem,calc(100vw-2rem))] p-3 lg:hidden", children: _jsxs("div", { className: "flex flex-col gap-3", children: [components.length > 0 && (_jsx("div", { className: "flex flex-wrap items-center gap-2 border-b pb-3", children: components.map(({ component: Component }, index) => (_jsx(Component, {}, index))) })), _jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [_jsx(LanguagesDropdown, {}), _jsx(ChannelSwitcher, { className: "min-w-0 flex-1" })] })] }) })] }));
|
|
9
|
+
};
|
|
@@ -1,102 +1,43 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
2
|
-
import React, { useMemo
|
|
3
|
-
import { Breadcrumb, BreadcrumbItem, BreadcrumbList, BreadcrumbSeparator, Button, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger, ScrollArea, TooltipProvider, Routes, useSettings, useServer, usePluginStore, cn, dashToCamelCase, apiClient, useGlobalSearch, useTranslation, DropdownMenuGroup, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuPortal, DropdownMenuSubContent, createDialog, buildURL, } from '@deenruv/react-ui-devkit';
|
|
4
|
-
import { Permission } from '@deenruv/admin-types';
|
|
5
|
-
import { useShallow } from 'zustand/react/shallow';
|
|
6
|
-
import { GripVertical, LogOutIcon, MenuIcon, Moon, Slash, Sun, SunMoon, RotateCwSquare, SearchIcon, } from 'lucide-react';
|
|
7
|
-
import * as ResizablePrimitive from 'react-resizable-panels';
|
|
8
|
-
import { Navigation } from './Navigation.js';
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import React, { useMemo } from 'react';
|
|
9
3
|
import { NavLink, useMatches, useNavigate } from 'react-router';
|
|
4
|
+
import { Breadcrumb, BreadcrumbItem, BreadcrumbList, BreadcrumbSeparator, buildURL, Button, cn, dashToCamelCase, DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, ScrollArea, Sheet, SheetContent, SheetDescription, SheetTitle, TooltipProvider, Routes, useGlobalSearch, usePluginStore, useServer, useSettings, useTranslation, } from '@deenruv/react-ui-devkit';
|
|
5
|
+
import { MenuIcon, Moon, PanelLeftClose, PanelLeftOpen, SearchIcon, Slash, Sun, SunMoon } from 'lucide-react';
|
|
6
|
+
import { canAccessAdminItem, useAdminAccess } from "../../access/index.js";
|
|
10
7
|
import { ChannelSwitcher } from './ChannelSwitcher.js';
|
|
11
|
-
import { BrandLogo } from "../BrandLogo.js";
|
|
12
8
|
import { LanguagesDropdown } from './LanguagesDropdown.js';
|
|
13
9
|
import { Notifications } from './Notifications.js';
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
const ResizablePanel = ResizablePrimitive.Panel;
|
|
18
|
-
const ResizableHandle = ({ withHandle, className, ...props }) => (_jsx(ResizablePrimitive.Separator, { className: cn('relative flex w-px items-center justify-center bg-border/70 after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:outline-none data-[orientation=vertical]:h-px data-[orientation=vertical]:w-full data-[orientation=vertical]:after:left-0 data-[orientation=vertical]:after:h-1 data-[orientation=vertical]:after:w-full data-[orientation=vertical]:after:translate-x-0 data-[orientation=vertical]:after:-translate-y-1/2 [&[data-orientation=vertical]>div]:rotate-90', className), ...props, children: withHandle && (_jsx("div", { className: "z-10 flex h-4 w-3 items-center justify-center border bg-background text-muted-foreground", children: _jsx(GripVertical, { className: "size-2.5" }) })) }));
|
|
10
|
+
import { SidebarContent } from './SidebarContent.js';
|
|
11
|
+
import { useSidebarState } from './SidebarState.js';
|
|
12
|
+
import { TopbarOverflow } from './TopbarOverflow.js';
|
|
19
13
|
const removableCrumbs = ['draft', 'admin-ui'];
|
|
20
14
|
export const Menu = ({ children }) => {
|
|
21
|
-
const openGlobalSearch = useGlobalSearch((state) => state.open);
|
|
22
|
-
const linkPath = [];
|
|
23
15
|
const { t } = useTranslation('common');
|
|
24
|
-
const { topNavigationActionsMenu, topNavigationComponents } = usePluginStore();
|
|
25
|
-
const { routes, defaultRoute } = useAdminAccess();
|
|
26
|
-
const { logOut, theme, setTheme } = useSettings(useShallow((p) => ({
|
|
27
|
-
logOut: p.logOut,
|
|
28
|
-
theme: p.theme,
|
|
29
|
-
setTheme: p.setTheme,
|
|
30
|
-
language: p.language,
|
|
31
|
-
setLanguage: p.setLanguage,
|
|
32
|
-
})));
|
|
33
16
|
const navigate = useNavigate();
|
|
34
|
-
const
|
|
35
|
-
const
|
|
17
|
+
const matches = useMatches();
|
|
18
|
+
const openGlobalSearch = useGlobalSearch((state) => state.open);
|
|
19
|
+
const { topNavigationComponents } = usePluginStore();
|
|
20
|
+
const { defaultRoute } = useAdminAccess();
|
|
21
|
+
const userPermissions = useServer((state) => state.userPermissions);
|
|
22
|
+
const { theme, setTheme } = useSettings();
|
|
23
|
+
const { isCollapsed, isMobileOpen, manuallyOpenGroupIds, setIsCollapsed, setIsMobileOpen, setManuallyOpenGroupIds, toggleDesktop, } = useSidebarState();
|
|
36
24
|
const defaultRoutePath = defaultRoute?.path || Routes.dashboard;
|
|
37
25
|
const defaultRouteMenuKey = defaultRoute?.nav?.menuKey || defaultRoute?.search?.menuKey || 'dashboard';
|
|
38
|
-
const
|
|
39
|
-
const languageSwitcherEnabled = true;
|
|
40
|
-
const channelSwitcherEnabled = true;
|
|
41
|
-
const notificationsEnabled = true;
|
|
42
|
-
const reindexEnabled = canAccessAdminItem({
|
|
43
|
-
item: { requiredPermissions: [Permission.UpdateCatalog, Permission.UpdateProduct] },
|
|
44
|
-
userPermissions,
|
|
45
|
-
});
|
|
46
|
-
const canAccessPluginSurface = (entry) => canAccessAdminItem({ item: entry.access, userPermissions });
|
|
47
|
-
const allowedTopNavigationComponents = topNavigationComponents?.filter(canAccessPluginSurface);
|
|
48
|
-
const allowedTopNavigationActions = topNavigationActionsMenu?.filter(canAccessPluginSurface);
|
|
49
|
-
const systemStatusRoute = routes.find((route) => route.id === 'system.status');
|
|
50
|
-
const globalSettingsRoute = routes.find((route) => route.id === 'settings.global');
|
|
51
|
-
const fastLinks = [
|
|
52
|
-
systemStatusRoute &&
|
|
53
|
-
canAccessAdminItem({ item: systemStatusRoute, userPermissions }) && {
|
|
54
|
-
key: 'systemStatus',
|
|
55
|
-
label: t('systemStatus'),
|
|
56
|
-
path: systemStatusRoute.path,
|
|
57
|
-
},
|
|
58
|
-
globalSettingsRoute &&
|
|
59
|
-
canAccessAdminItem({ item: globalSettingsRoute, userPermissions }) && {
|
|
60
|
-
key: 'globalSettings',
|
|
61
|
-
label: t('globalSettings'),
|
|
62
|
-
path: globalSettingsRoute.path,
|
|
63
|
-
},
|
|
64
|
-
].filter(Boolean);
|
|
65
|
-
const rebuildSearchIndex = async () => {
|
|
66
|
-
await apiClient('mutation')({ reindex: { id: true, queueName: true, state: true } }).then(({ reindex: { queueName, state } }) => {
|
|
67
|
-
setJobQueue(queueName, state === 'RUNNING');
|
|
68
|
-
});
|
|
69
|
-
};
|
|
70
|
-
const matches = useMatches();
|
|
26
|
+
const allowedTopNavigationComponents = topNavigationComponents?.filter((entry) => canAccessAdminItem({ item: entry.access, userPermissions }));
|
|
71
27
|
const crumbs = useMemo(() => matches
|
|
72
28
|
.filter((match) => !!match.pathname)
|
|
73
29
|
.map((match) => match.pathname)
|
|
74
|
-
.flatMap((
|
|
30
|
+
.flatMap((path) => path.split('/'))
|
|
75
31
|
.filter(Boolean)
|
|
76
32
|
.filter((crumb) => !removableCrumbs.includes(crumb)), [matches]);
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
})) : (_jsx(
|
|
87
|
-
? 'dashboard'
|
|
88
|
-
: `menu.${dashToCamelCase(defaultRouteMenuKey)}`) }) }) })) }) }), _jsx("div", { className: "flex items-center gap-2" })] }), _jsxs("div", { className: "flex flex-1 items-center justify-end gap-1.5", children: [allowedTopNavigationComponents && allowedTopNavigationComponents.length > 0 ? (_jsx("div", { className: "flex items-center gap-2", children: allowedTopNavigationComponents.map(({ component: Component }, index) => (_jsx(Component, {}, index))) })) : null, languageSwitcherEnabled && _jsx(LanguagesDropdown, {}), channelSwitcherEnabled && _jsx(ChannelSwitcher, { className: "min-w-44" }), globalSearchEnabled && (_jsx(Button, { onClick: openGlobalSearch, variant: "outline", size: "icon", className: "relative size-9", children: _jsx(SearchIcon, { className: "size-4" }) })), notificationsEnabled && _jsx(Notifications, {}), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "icon", className: "size-9", children: [theme === 'light' ? (_jsx(Sun, { className: "size-[1.2rem] scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90" })) : theme === 'dark' ? (_jsx(Moon, { className: "absolute size-[1.2rem] scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0" })) : (_jsx(SunMoon, { className: "absolute size-[1.2rem] rotate-90 transition-all" })), _jsx("span", { className: "sr-only", children: t('toggleTheme') })] }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsx(DropdownMenuItem, { onClick: () => setTheme('light'), children: t('themeLight') }), _jsx(DropdownMenuItem, { onClick: () => setTheme('dark'), children: t('themeDark') }), _jsx(DropdownMenuItem, { onClick: () => setTheme('system'), children: t('themeSystem') })] })] }), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "outline", size: "icon", className: "size-9", children: _jsx(MenuIcon, { className: "size-4" }) }) }), _jsxs(DropdownMenuContent, { className: "z-[150] mr-6 min-w-40", children: [activeAdministrator?.emailAddress && (_jsxs(_Fragment, { children: [_jsxs(DropdownMenuLabel, { className: "flex items-center gap-2 px-3 py-2 font-medium", children: [_jsx("div", { className: "flex size-6 items-center justify-center bg-primary/10 text-xs font-semibold text-primary", children: activeAdministrator.firstName.charAt(0).toUpperCase() }), _jsxs("div", { className: "truncate text-sm", children: [activeAdministrator.firstName, " ", activeAdministrator.lastName] })] }), _jsx(DropdownMenuSeparator, { className: "my-1" })] })), reindexEnabled && (_jsxs(DropdownMenuItem, { className: "flex cursor-pointer items-center gap-2 text-nowrap", onSelect: rebuildSearchIndex, children: [_jsx(RotateCwSquare, { className: "size-4" }), t('rebuildSerachIndex')] })), reindexEnabled && fastLinks.length > 0 && _jsx(DropdownMenuSeparator, {}), fastLinks.length > 0 && (_jsx(DropdownMenuGroup, { children: _jsxs(DropdownMenuSub, { children: [_jsx(DropdownMenuSubTrigger, { children: t('fastLinks') }), _jsx(DropdownMenuPortal, { children: _jsx(DropdownMenuSubContent, { children: fastLinks.map((link, index) => (_jsxs(React.Fragment, { children: [index > 0 && _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { className: "flex cursor-pointer items-center gap-2 text-nowrap", onSelect: () => navigate(link.path, { viewTransition: true }), children: [_jsx(RotateCwSquare, { className: "size-4" }), link.label] })] }, link.key))) }) })] }) })), allowedTopNavigationActions?.length && allowedTopNavigationActions.length > 0 ? (_jsxs(_Fragment, { children: [_jsx(DropdownMenuSeparator, {}), allowedTopNavigationActions.map((action) => (_jsxs(DropdownMenuItem, { className: "flex cursor-pointer items-center gap-2", onSelect: action.onClick, children: [action.icon && _jsx(action.icon, { className: "size-4" }), action.label] }, action.label)))] })) : null, _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuItem, { className: "flex cursor-pointer items-center gap-2 text-red-500", onSelect: async () => {
|
|
89
|
-
const result = await createDialog({
|
|
90
|
-
title: t('logOutConfirmation'),
|
|
91
|
-
description: t('logOutConfirmationDescription'),
|
|
92
|
-
buttons: [
|
|
93
|
-
{ label: t('cancel'), variant: 'secondary', returnValue: false },
|
|
94
|
-
{ label: t('logOut'), variant: 'destructive', returnValue: true },
|
|
95
|
-
],
|
|
96
|
-
});
|
|
97
|
-
if (result) {
|
|
98
|
-
clearAdministratorAccess();
|
|
99
|
-
logOut();
|
|
100
|
-
}
|
|
101
|
-
}, children: [_jsx(LogOutIcon, { className: "size-4" }), t('logOut')] })] })] })] })] }), _jsx(ScrollArea, { className: "relative h-[calc(100vh-64px)] overflow-y-hidden lg:h-[calc(100vh-72px)]", children: children })] })] }) }) }) }) }));
|
|
33
|
+
const navigateHome = () => navigate(defaultRoutePath, { viewTransition: true });
|
|
34
|
+
return (_jsx(TooltipProvider, { delayDuration: 100, children: _jsxs("div", { className: "flex h-screen w-full overflow-hidden bg-[var(--sidebar-canvas)]", children: [_jsx("aside", { "data-collapsed": isCollapsed, className: cn('hidden h-full shrink-0 border-r border-[var(--sidebar-hairline)] bg-[var(--sidebar-canvas)] transition-[width] duration-300 ease-out motion-reduce:transition-none md:block', isCollapsed ? 'w-12' : 'w-64'), "aria-label": t('mainNavigation'), children: _jsx(SidebarContent, { isCollapsed: isCollapsed, manuallyOpenGroupIds: manuallyOpenGroupIds, mode: "desktop", onExpand: () => setIsCollapsed(false), onOpenGroupIdsChange: setManuallyOpenGroupIds, onNavigate: () => undefined, onNavigateHome: navigateHome }) }), _jsx(Sheet, { open: isMobileOpen, onOpenChange: setIsMobileOpen, children: _jsxs(SheetContent, { side: "left", className: "w-72 max-w-[calc(100vw-1rem)] border-[var(--sidebar-hairline)] bg-[var(--sidebar-canvas)] p-0 sm:max-w-72 [&>button]:rounded-[4px] [&>button]:text-[var(--sidebar-secondary)] [&>button]:focus:ring-[var(--sidebar-focus)] [&>button]:data-[state=open]:bg-[var(--sidebar-hover)]", children: [_jsx(SheetTitle, { className: "sr-only", children: t('mainNavigation') }), _jsx(SheetDescription, { className: "sr-only", children: t('mobileNavigationDescription') }), _jsx(SidebarContent, { isCollapsed: false, manuallyOpenGroupIds: manuallyOpenGroupIds, mode: "mobile", onExpand: () => undefined, onOpenGroupIdsChange: setManuallyOpenGroupIds, onNavigate: () => setIsMobileOpen(false), onNavigateHome: () => {
|
|
35
|
+
navigateHome();
|
|
36
|
+
setIsMobileOpen(false);
|
|
37
|
+
} })] }) }), _jsxs("main", { className: "flex min-w-0 flex-1 flex-col bg-[var(--sidebar-canvas)]", children: [_jsxs("header", { className: "flex h-16 shrink-0 items-center gap-2 border-b border-[var(--sidebar-hairline)] bg-[var(--sidebar-canvas)] px-3 lg:h-[72px] lg:px-5", children: [_jsx(Button, { variant: "outline", size: "icon", className: "size-9 shrink-0 md:hidden", onClick: () => setIsMobileOpen(true), "aria-label": t('openSidebar'), title: t('openSidebar'), children: _jsx(MenuIcon, { className: "size-4" }) }), _jsx(Button, { variant: "outline", size: "icon", className: "hidden size-9 shrink-0 md:inline-flex", onClick: toggleDesktop, "aria-label": isCollapsed ? t('expandSidebar') : t('collapseSidebar'), title: `${isCollapsed ? t('expandSidebar') : t('collapseSidebar')} (${t('sidebarShortcut')})`, children: isCollapsed ? _jsx(PanelLeftOpen, { className: "size-4" }) : _jsx(PanelLeftClose, { className: "size-4" }) }), _jsx("div", { className: "hidden min-w-0 flex-col items-start justify-center sm:flex", children: _jsx(Breadcrumb, { children: _jsx(BreadcrumbList, { className: "flex-nowrap overflow-hidden", children: crumbs.length ? (crumbs.map((crumb, index) => {
|
|
38
|
+
const path = crumbs.slice(0, index + 1);
|
|
39
|
+
return (_jsxs(React.Fragment, { children: [_jsx(BreadcrumbItem, { className: "min-w-0", children: _jsx(NavLink, { to: buildURL(path), viewTransition: true, className: "truncate", children: _jsx("span", { className: "text-sm font-semibold tracking-tight text-foreground", children: index === 0 ? t(`menu.${dashToCamelCase(crumb)}`) : crumb }) }) }), index !== crumbs.length - 1 && (_jsx(BreadcrumbSeparator, { children: _jsx(Slash, { className: "text-muted-foreground" }) }))] }, `${crumb}-${index}`));
|
|
40
|
+
})) : (_jsx(BreadcrumbItem, { children: _jsx(NavLink, { to: defaultRoutePath, viewTransition: true, children: _jsx("span", { className: "text-lg font-semibold tracking-tight text-foreground", children: t(defaultRouteMenuKey === 'dashboard'
|
|
41
|
+
? 'dashboard'
|
|
42
|
+
: `menu.${dashToCamelCase(defaultRouteMenuKey)}`) }) }) })) }) }) }), _jsxs("div", { className: "ml-auto flex min-w-0 items-center justify-end gap-1.5", children: [_jsx(TopbarOverflow, { components: allowedTopNavigationComponents || [] }), allowedTopNavigationComponents?.length ? (_jsx("div", { className: "hidden items-center gap-2 lg:flex", children: allowedTopNavigationComponents.map(({ component: Component }, index) => (_jsx(Component, {}, index))) })) : null, _jsxs("div", { className: "hidden items-center gap-1.5 lg:flex", children: [_jsx(LanguagesDropdown, {}), _jsx(ChannelSwitcher, { className: "min-w-44" })] }), _jsx(Button, { onClick: openGlobalSearch, variant: "outline", size: "icon", className: "relative size-9 shrink-0", "aria-label": t('openGlobalSearch'), title: t('openGlobalSearch'), children: _jsx(SearchIcon, { className: "size-4" }) }), _jsx(Notifications, {}), _jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsxs(Button, { variant: "outline", size: "icon", className: "relative size-9 shrink-0", children: [theme === 'light' ? (_jsx(Sun, { className: "size-[1.2rem]" })) : theme === 'dark' ? (_jsx(Moon, { className: "size-[1.2rem]" })) : (_jsx(SunMoon, { className: "size-[1.2rem]" })), _jsx("span", { className: "sr-only", children: t('toggleTheme') })] }) }), _jsxs(DropdownMenuContent, { align: "end", children: [_jsx(DropdownMenuItem, { onClick: () => setTheme('light'), children: t('themeLight') }), _jsx(DropdownMenuItem, { onClick: () => setTheme('dark'), children: t('themeDark') }), _jsx(DropdownMenuItem, { onClick: () => setTheme('system'), children: t('themeSystem') })] })] })] })] }), _jsx(ScrollArea, { className: "relative min-h-0 flex-1 overflow-y-hidden bg-[var(--sidebar-canvas)]", children: children })] })] }) }));
|
|
102
43
|
};
|
package/dist/index.css
CHANGED
|
@@ -59,6 +59,18 @@
|
|
|
59
59
|
|
|
60
60
|
--navigation-link: hsl(228 14% 28%);
|
|
61
61
|
|
|
62
|
+
--sidebar-canvas: #fbfbf5;
|
|
63
|
+
--sidebar-surface: #ffffff;
|
|
64
|
+
--sidebar-ink: #000000;
|
|
65
|
+
--sidebar-secondary: #71717a;
|
|
66
|
+
--sidebar-tertiary: #52525b;
|
|
67
|
+
--sidebar-hairline: #e4e4e7;
|
|
68
|
+
--sidebar-hover: #ffffff;
|
|
69
|
+
--sidebar-active: #d4f9e0;
|
|
70
|
+
--sidebar-active-ink: #000000;
|
|
71
|
+
--sidebar-active-indicator: #000000;
|
|
72
|
+
--sidebar-focus: #000000;
|
|
73
|
+
|
|
62
74
|
--topbar-height: 64px;
|
|
63
75
|
--topbar-height-lg: 72px;
|
|
64
76
|
|
|
@@ -104,6 +116,18 @@
|
|
|
104
116
|
--warning-foreground: hsl(38 92% 50%);
|
|
105
117
|
|
|
106
118
|
--navigation-link: hsl(220 18% 86%);
|
|
119
|
+
|
|
120
|
+
--sidebar-canvas: #000000;
|
|
121
|
+
--sidebar-surface: #0a0a0a;
|
|
122
|
+
--sidebar-ink: #ffffff;
|
|
123
|
+
--sidebar-secondary: #a1a1aa;
|
|
124
|
+
--sidebar-tertiary: #9dabad;
|
|
125
|
+
--sidebar-hairline: #1e2c31;
|
|
126
|
+
--sidebar-hover: #0a0a0a;
|
|
127
|
+
--sidebar-active: #1e2c31;
|
|
128
|
+
--sidebar-active-ink: #ffffff;
|
|
129
|
+
--sidebar-active-indicator: #ffffff;
|
|
130
|
+
--sidebar-focus: #bdbdca;
|
|
107
131
|
}
|
|
108
132
|
|
|
109
133
|
@theme inline {
|
|
@@ -236,6 +260,47 @@ a {
|
|
|
236
260
|
text-decoration: none;
|
|
237
261
|
}
|
|
238
262
|
|
|
263
|
+
.deenruv-sidebar a.sidebar-link {
|
|
264
|
+
display: block;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
.deenruv-sidebar .sidebar-row {
|
|
268
|
+
display: flex;
|
|
269
|
+
height: 36px;
|
|
270
|
+
min-height: 36px;
|
|
271
|
+
align-items: center;
|
|
272
|
+
gap: 8px;
|
|
273
|
+
padding: 0 8px;
|
|
274
|
+
border-radius: 4px;
|
|
275
|
+
color: var(--sidebar-secondary);
|
|
276
|
+
font-size: 14px;
|
|
277
|
+
font-weight: 500;
|
|
278
|
+
line-height: 20px;
|
|
279
|
+
transition:
|
|
280
|
+
color 150ms ease,
|
|
281
|
+
background-color 150ms ease;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.deenruv-sidebar .sidebar-row:hover {
|
|
285
|
+
background-color: var(--sidebar-hover);
|
|
286
|
+
color: var(--sidebar-ink);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.deenruv-sidebar .sidebar-row[data-active="true"] {
|
|
290
|
+
background-color: var(--sidebar-active);
|
|
291
|
+
color: var(--sidebar-active-ink);
|
|
292
|
+
box-shadow: inset 2px 0 0 var(--sidebar-active-indicator);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.deenruv-sidebar .sidebar-icon-slot {
|
|
296
|
+
display: flex;
|
|
297
|
+
width: 20px;
|
|
298
|
+
height: 20px;
|
|
299
|
+
flex: 0 0 20px;
|
|
300
|
+
align-items: center;
|
|
301
|
+
justify-content: center;
|
|
302
|
+
}
|
|
303
|
+
|
|
239
304
|
.Puck > div:nth-child(1) {
|
|
240
305
|
position: relative !important;
|
|
241
306
|
}
|
|
@@ -476,6 +476,19 @@
|
|
|
476
476
|
"edit": "Edit",
|
|
477
477
|
"rebuildSerachIndex": "Rebuild search index",
|
|
478
478
|
"fastLinks": "Quick links",
|
|
479
|
+
"account": "Account",
|
|
480
|
+
"openAccountMenu": "Open account menu",
|
|
481
|
+
"mainNavigation": "Main navigation",
|
|
482
|
+
"mobileNavigationDescription": "Navigate to an administration area.",
|
|
483
|
+
"openSidebar": "Open navigation",
|
|
484
|
+
"expandSidebar": "Expand navigation",
|
|
485
|
+
"collapseSidebar": "Collapse navigation",
|
|
486
|
+
"sidebarShortcut": "Ctrl or Command + B",
|
|
487
|
+
"expandNavigationGroup": "Expand navigation and open {{group}}",
|
|
488
|
+
"goToDashboard": "Go to dashboard",
|
|
489
|
+
"openGlobalSearch": "Open global search",
|
|
490
|
+
"openTopbarControls": "Open language, channel and plugin controls",
|
|
491
|
+
"versionAbbreviation": "version",
|
|
479
492
|
"systemStatus": "System status",
|
|
480
493
|
"globalSettings": "Global settings",
|
|
481
494
|
"delete": "Delete",
|
|
@@ -568,34 +581,34 @@
|
|
|
568
581
|
"options": "Options",
|
|
569
582
|
"variants": "Variants",
|
|
570
583
|
"adminUiV2": "Admin UI",
|
|
571
|
-
"extensions": "
|
|
572
|
-
"dashboard": "
|
|
573
|
-
"status": "
|
|
574
|
-
"products": "
|
|
575
|
-
"customers": "
|
|
576
|
-
"customerGroups": "
|
|
577
|
-
"productVariants": "
|
|
578
|
-
"collections": "
|
|
579
|
-
"orders": "
|
|
580
|
-
"facets": "
|
|
581
|
-
"channels": "
|
|
582
|
-
"globalSettings": "
|
|
583
|
-
"roles": "
|
|
584
|
-
"admins": "
|
|
585
|
-
"adminProvision": "
|
|
586
|
-
"stock": "
|
|
587
|
-
"sellers": "
|
|
588
|
-
"assets": "
|
|
589
|
-
"zones": "
|
|
590
|
-
"promotions": "
|
|
591
|
-
"countries": "
|
|
592
|
-
"paymentMethods": "
|
|
593
|
-
"shippingMethods": "
|
|
594
|
-
"stockLocations": "
|
|
595
|
-
"taxCategories": "
|
|
596
|
-
"taxRates": "
|
|
597
|
-
"logOut": "
|
|
598
|
-
"systemStatus": "
|
|
584
|
+
"extensions": "Extensions",
|
|
585
|
+
"dashboard": "Dashboard",
|
|
586
|
+
"status": "Status",
|
|
587
|
+
"products": "Products",
|
|
588
|
+
"customers": "Customers",
|
|
589
|
+
"customerGroups": "Customer groups",
|
|
590
|
+
"productVariants": "Product variants",
|
|
591
|
+
"collections": "Collections",
|
|
592
|
+
"orders": "Orders",
|
|
593
|
+
"facets": "Facets",
|
|
594
|
+
"channels": "Channels",
|
|
595
|
+
"globalSettings": "Global settings",
|
|
596
|
+
"roles": "Roles",
|
|
597
|
+
"admins": "Administrators",
|
|
598
|
+
"adminProvision": "Administrator provisioning",
|
|
599
|
+
"stock": "Storage locations",
|
|
600
|
+
"sellers": "Sellers",
|
|
601
|
+
"assets": "Assets",
|
|
602
|
+
"zones": "Zones",
|
|
603
|
+
"promotions": "Promotions",
|
|
604
|
+
"countries": "Countries",
|
|
605
|
+
"paymentMethods": "Payment methods",
|
|
606
|
+
"shippingMethods": "Shipping methods",
|
|
607
|
+
"stockLocations": "Warehouse locations",
|
|
608
|
+
"taxCategories": "Tax categories",
|
|
609
|
+
"taxRates": "Tax rates",
|
|
610
|
+
"logOut": "Log out",
|
|
611
|
+
"systemStatus": "System status"
|
|
599
612
|
},
|
|
600
613
|
"noFilterField": "None",
|
|
601
614
|
"draft": "Project",
|
|
@@ -475,6 +475,19 @@
|
|
|
475
475
|
"edit": "Edytuj",
|
|
476
476
|
"rebuildSerachIndex": "Przebuduj search index",
|
|
477
477
|
"fastLinks": "Szybkie linki",
|
|
478
|
+
"account": "Konto",
|
|
479
|
+
"openAccountMenu": "Otwórz menu konta",
|
|
480
|
+
"mainNavigation": "Główna nawigacja",
|
|
481
|
+
"mobileNavigationDescription": "Przejdź do wybranego obszaru administracyjnego.",
|
|
482
|
+
"openSidebar": "Otwórz nawigację",
|
|
483
|
+
"expandSidebar": "Rozwiń nawigację",
|
|
484
|
+
"collapseSidebar": "Zwiń nawigację",
|
|
485
|
+
"sidebarShortcut": "Ctrl lub Command + B",
|
|
486
|
+
"expandNavigationGroup": "Rozwiń nawigację i otwórz grupę {{group}}",
|
|
487
|
+
"goToDashboard": "Przejdź do pulpitu",
|
|
488
|
+
"openGlobalSearch": "Otwórz wyszukiwanie globalne",
|
|
489
|
+
"openTopbarControls": "Otwórz ustawienia języka, kanału i wtyczek",
|
|
490
|
+
"versionAbbreviation": "wersja",
|
|
478
491
|
"systemStatus": "Status systemu",
|
|
479
492
|
"globalSettings": "Ustawienia globalne",
|
|
480
493
|
"delete": "Usuń",
|
|
@@ -567,34 +580,34 @@
|
|
|
567
580
|
"options": "Opcje produktu",
|
|
568
581
|
"variants": "Warianty",
|
|
569
582
|
"adminUiV2": "Admin UI",
|
|
570
|
-
"extensions": "
|
|
571
|
-
"dashboard": "
|
|
572
|
-
"status": "
|
|
573
|
-
"products": "
|
|
574
|
-
"customers": "
|
|
575
|
-
"customerGroups": "
|
|
576
|
-
"productVariants": "
|
|
577
|
-
"collections": "
|
|
578
|
-
"orders": "
|
|
579
|
-
"facets": "
|
|
580
|
-
"channels": "
|
|
581
|
-
"globalSettings": "
|
|
582
|
-
"roles": "
|
|
583
|
-
"admins": "
|
|
584
|
-
"adminProvision": "
|
|
585
|
-
"stock": "
|
|
586
|
-
"sellers": "
|
|
587
|
-
"assets": "
|
|
588
|
-
"zones": "
|
|
589
|
-
"promotions": "
|
|
590
|
-
"countries": "
|
|
591
|
-
"paymentMethods": "
|
|
592
|
-
"shippingMethods": "
|
|
593
|
-
"stockLocations": "
|
|
594
|
-
"taxCategories": "
|
|
595
|
-
"taxRates": "
|
|
596
|
-
"logOut": "
|
|
597
|
-
"systemStatus": "
|
|
583
|
+
"extensions": "Rozszerzenia",
|
|
584
|
+
"dashboard": "Pulpit",
|
|
585
|
+
"status": "Status",
|
|
586
|
+
"products": "Produkty",
|
|
587
|
+
"customers": "Klienci",
|
|
588
|
+
"customerGroups": "Grupy klientów",
|
|
589
|
+
"productVariants": "Warianty produktów",
|
|
590
|
+
"collections": "Kolekcje",
|
|
591
|
+
"orders": "Zamówienia",
|
|
592
|
+
"facets": "Aspekty",
|
|
593
|
+
"channels": "Kanały",
|
|
594
|
+
"globalSettings": "Ustawienia globalne",
|
|
595
|
+
"roles": "Role",
|
|
596
|
+
"admins": "Administratorzy",
|
|
597
|
+
"adminProvision": "Zakładanie administratora",
|
|
598
|
+
"stock": "Lokalizacje magazynowe",
|
|
599
|
+
"sellers": "Sprzedawcy",
|
|
600
|
+
"assets": "Aktywa",
|
|
601
|
+
"zones": "Strefy",
|
|
602
|
+
"promotions": "Promocje",
|
|
603
|
+
"countries": "Kraje",
|
|
604
|
+
"paymentMethods": "Metody płatności",
|
|
605
|
+
"shippingMethods": "Metody wysyłki",
|
|
606
|
+
"stockLocations": "Lokacje magazynów",
|
|
607
|
+
"taxCategories": "Kategorie podatkowe",
|
|
608
|
+
"taxRates": "Stawki podatkowe",
|
|
609
|
+
"logOut": "Wylogowanie",
|
|
610
|
+
"systemStatus": "Status systemu"
|
|
598
611
|
},
|
|
599
612
|
"noFilterField": "Brak",
|
|
600
613
|
"draft": "Projekt",
|
|
@@ -652,7 +665,7 @@
|
|
|
652
665
|
"notifications": "Powiadomienia",
|
|
653
666
|
"noNewNotifications": "Brak nowych powiadomień",
|
|
654
667
|
"toggleNotifications": "Przełącz powiadomienia",
|
|
655
|
-
"dashboard": "Pulpit
|
|
668
|
+
"dashboard": "Pulpit",
|
|
656
669
|
"search": {
|
|
657
670
|
"advanceToggle": "Wyszukiwanie zaawansowane",
|
|
658
671
|
"basicToggle": "Wyszukiwanie podstawowe",
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const ADMIN_DASHBOARD_VERSION = '1.0.17-dev.
|
|
1
|
+
export const ADMIN_DASHBOARD_VERSION = '1.0.17-dev.18';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deenruv/admin-dashboard",
|
|
3
|
-
"version": "1.0.17-dev.
|
|
3
|
+
"version": "1.0.17-dev.18",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"style": "dist/index.css",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -80,10 +80,10 @@
|
|
|
80
80
|
"yup": "^1.7.1",
|
|
81
81
|
"zod": "^4.4.3",
|
|
82
82
|
"zustand": "^5.0.14",
|
|
83
|
-
"@deenruv/
|
|
84
|
-
"@deenruv/admin-types": "1.0.17-dev.
|
|
85
|
-
"@deenruv/
|
|
86
|
-
"@deenruv/
|
|
83
|
+
"@deenruv/deenruv-examples-plugin": "1.0.17-dev.18",
|
|
84
|
+
"@deenruv/admin-types": "1.0.17-dev.18",
|
|
85
|
+
"@deenruv/react-ui-devkit": "1.0.17-dev.18",
|
|
86
|
+
"@deenruv/admin-dashboard": "1.0.17-dev.18"
|
|
87
87
|
},
|
|
88
88
|
"devDependencies": {
|
|
89
89
|
"@tailwindcss/typography": "^0.5.20",
|