@deenruv/admin-dashboard 1.0.16 → 1.0.17-dev.14

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.
Files changed (74) hide show
  1. package/dist/DeenruvAdminPanel.js +35 -46
  2. package/dist/access/access-context.js +10 -0
  3. package/dist/access/built-in-routes.js +300 -0
  4. package/dist/access/index.js +6 -0
  5. package/dist/access/navigation.js +33 -0
  6. package/dist/access/permission-access.js +9 -0
  7. package/dist/access/permission-routes.js +3 -0
  8. package/dist/access/types.js +1 -0
  9. package/dist/components/GlobalSearch.js +37 -62
  10. package/dist/components/Menu/ActiveAdmins.js +1 -1
  11. package/dist/components/Menu/ChannelSwitcher.js +1 -1
  12. package/dist/components/Menu/LanguagesDropdown.js +1 -1
  13. package/dist/components/Menu/Navigation.js +68 -229
  14. package/dist/components/Menu/NavigationFooter.js +7 -4
  15. package/dist/components/Menu/Notifications.js +1 -1
  16. package/dist/components/Menu/index.js +50 -16
  17. package/dist/index.css +54 -44
  18. package/dist/locales/en/admins.json +62 -0
  19. package/dist/locales/en/collections.json +7 -0
  20. package/dist/locales/en/common.json +2 -0
  21. package/dist/locales/en/orders.json +8 -0
  22. package/dist/locales/en/products.json +14 -2
  23. package/dist/locales/en/promotions.json +4 -0
  24. package/dist/locales/pl/admins.json +62 -0
  25. package/dist/locales/pl/collections.json +7 -0
  26. package/dist/locales/pl/common.json +2 -0
  27. package/dist/locales/pl/orders.json +8 -0
  28. package/dist/locales/pl/products.json +14 -2
  29. package/dist/locales/pl/promotions.json +4 -0
  30. package/dist/pages/Root.js +31 -15
  31. package/dist/pages/admins/Detail.js +1 -1
  32. package/dist/pages/admins/List.js +8 -3
  33. package/dist/pages/admins/Provision.js +173 -0
  34. package/dist/pages/admins/Provision.logic.js +53 -0
  35. package/dist/pages/admins/index.js +1 -0
  36. package/dist/pages/assets/List.js +3 -3
  37. package/dist/pages/channels/Detail.js +1 -1
  38. package/dist/pages/collections/Detail.js +21 -6
  39. package/dist/pages/collections/List.js +87 -20
  40. package/dist/pages/collections/_components/CollectionDetailView.js +15 -2
  41. package/dist/pages/collections/_components/FiltersCard.js +51 -11
  42. package/dist/pages/countries/Detail.js +1 -1
  43. package/dist/pages/customers/_components/PersonalDataCard.js +2 -1
  44. package/dist/pages/extensions/Extensions.js +3 -7
  45. package/dist/pages/facets/Detail.js +1 -1
  46. package/dist/pages/orders/Detail.js +38 -5
  47. package/dist/pages/orders/List.js +1 -16
  48. package/dist/pages/orders/_components/CancelAndRefundDialog.js +1 -2
  49. package/dist/pages/orders/_components/OrderLineCustomFields.js +1 -1
  50. package/dist/pages/orders/_components/ProductsTable.js +1 -2
  51. package/dist/pages/orders/_components/RefundPaymentCard.js +1 -2
  52. package/dist/pages/payment-methods/Detail.js +1 -1
  53. package/dist/pages/product-variants/List.js +3 -3
  54. package/dist/pages/products/Detail.js +58 -4
  55. package/dist/pages/products/_components/AssetsCard.js +15 -2
  56. package/dist/pages/products/_components/OptionsCard.js +7 -5
  57. package/dist/pages/products/_components/PriceCard.js +21 -8
  58. package/dist/pages/products/_components/ProductDetailView.js +7 -3
  59. package/dist/pages/products/_components/Variant.js +53 -26
  60. package/dist/pages/products/_components/VariantsTab.js +1 -1
  61. package/dist/pages/promotions/Detail.js +34 -3
  62. package/dist/pages/promotions/_components/EnabledCard.js +2 -2
  63. package/dist/pages/promotions/_components/PromotionDetailSidebar.js +2 -1
  64. package/dist/pages/roles/Detail.js +1 -1
  65. package/dist/pages/roles/_components/PermissionsTable.js +0 -1
  66. package/dist/pages/sellers/Detail.js +1 -1
  67. package/dist/pages/shipping-methods/Detail.js +10 -6
  68. package/dist/pages/shipping-methods/_components/CalculatorCard.js +27 -11
  69. package/dist/pages/shipping-methods/_components/CheckerCard.js +28 -12
  70. package/dist/pages/stock-locations/Detail.js +1 -1
  71. package/dist/pages/tax-rates/Detail.js +1 -1
  72. package/dist/pages/zones/Detail.js +1 -1
  73. package/dist/version.js +1 -1
  74. package/package.json +68 -68
@@ -1,52 +1,22 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // eslint-disable-next-line no-restricted-imports
3
3
  import { I18nextProvider } from 'react-i18next';
4
- import { useEffect } from 'react';
5
- import { createBrowserRouter, RouterProvider } from 'react-router';
4
+ import { useEffect, useMemo } from 'react';
5
+ import { createBrowserRouter, Navigate, RouterProvider } from 'react-router';
6
6
  import { AnimatePresence } from 'framer-motion';
7
7
  import { Toaster } from 'sonner';
8
8
  import i18n from './i18.js';
9
- import { Routes, PluginProvider, PluginStore, useSettings, GlobalStoreProvider, DEFAULT_CHANNEL_CODE, NotificationProvider, } from '@deenruv/react-ui-devkit';
9
+ import { Routes, PluginProvider, PluginStore, useServer, useSettings, GlobalStoreProvider, DEFAULT_CHANNEL_CODE, NotificationProvider, } from '@deenruv/react-ui-devkit';
10
10
  import { useShallow } from 'zustand/react/shallow';
11
11
  import { LanguageCode } from '@deenruv/admin-types';
12
12
  import { Root } from "./pages/Root.js";
13
13
  import { LoginScreen } from "./pages/LoginScreen.js";
14
14
  import { ErrorPage } from "./pages/Custom404.js";
15
- import * as Pages from "./pages/index.js";
16
15
  import * as resources from "./locales/index.js";
17
16
  import { ADMIN_DASHBOARD_VERSION } from "./version.js";
18
17
  import { ORDER_STATUS_NOTIFICATION } from "./notifications/OrderStatusNotification.js";
19
18
  import { SYSTEM_STATUS_NOTIFICATION } from "./notifications/SystemStatusNotification.js";
20
- const firstLetterToLowerCase = (str) => str.charAt(0).toLowerCase() + str.slice(1);
21
- const getRoute = (name, key) => {
22
- const route = Routes[name];
23
- if (typeof route !== 'object')
24
- return route;
25
- if (key.includes('DetailPage') && 'route' in route)
26
- return route.route;
27
- if (key.includes('ListPage') && 'list' in route)
28
- return route.list;
29
- return null;
30
- };
31
- const getName = (key) => {
32
- if (key.includes('DetailPage'))
33
- return firstLetterToLowerCase(key.replace('DetailPage', ''));
34
- if (key.includes('ListPage'))
35
- return firstLetterToLowerCase(key.replace('ListPage', ''));
36
- return firstLetterToLowerCase(key);
37
- };
38
- const DeenruvPaths = Object.entries(Pages).flatMap(([key, Component]) => {
39
- const name = getName(key);
40
- const path = getRoute(name, key);
41
- const paths = [];
42
- if (path)
43
- paths.push({ path, element: _jsx(Component, {}) });
44
- const route = Routes[name];
45
- if (key.includes('DetailPage') && typeof route === 'object' && 'new' in route) {
46
- paths.push({ path: route.new, element: _jsx(Component, {}) });
47
- }
48
- return paths;
49
- });
19
+ import { AdminAccessProvider, builtInAdminRoutes, getDefaultAdminRoute, getPermittedAdminRoutes, } from "./access/index.js";
50
20
  const loadTranslations = () => {
51
21
  Object.entries(resources).forEach(([lang, value]) => {
52
22
  Object.entries(value).forEach(([, translations]) => {
@@ -76,13 +46,6 @@ export const DeenruvAdminPanel = ({ plugins, settings }) => {
76
46
  };
77
47
  pluginsStore.install(plugins, i18n);
78
48
  loadTranslations();
79
- const router = createBrowserRouter([
80
- {
81
- element: _jsx(Root, { allPaths: [...DeenruvPaths].map((path) => path.path).filter(Boolean) }),
82
- errorElement: _jsx(ErrorPage, {}),
83
- children: [...DeenruvPaths, ...pluginsStore.routes],
84
- },
85
- ]);
86
49
  const { theme, isLoggedIn, ...context } = useSettings(useShallow((p) => ({
87
50
  theme: p.theme,
88
51
  isLoggedIn: p.isLoggedIn,
@@ -90,6 +53,32 @@ export const DeenruvAdminPanel = ({ plugins, settings }) => {
90
53
  language: p.language,
91
54
  translationsLanguage: p.translationsLanguage,
92
55
  })));
56
+ const userPermissions = useServer((p) => p.userPermissions);
57
+ const pluginRoutes = useMemo(() => pluginsStore.routes.map((route) => ({
58
+ id: `plugin.${route.plugin.name}.${route.path}`,
59
+ path: route.path,
60
+ element: route.element,
61
+ ...route.access,
62
+ search: { menuKey: `${route.plugin.name} - ${route.path}`, type: 'plugin' },
63
+ })), [plugins]);
64
+ const permittedRoutes = useMemo(() => getPermittedAdminRoutes([...builtInAdminRoutes, ...pluginRoutes], userPermissions), [pluginRoutes, userPermissions]);
65
+ const defaultRoute = getDefaultAdminRoute(permittedRoutes);
66
+ const router = useMemo(() => {
67
+ const routerChildren = permittedRoutes.map(({ path, element }) => ({ path, element }));
68
+ if (defaultRoute && !permittedRoutes.some((route) => route.path === Routes.dashboard)) {
69
+ routerChildren.push({ path: Routes.dashboard, element: _jsx(Navigate, { to: defaultRoute.path, replace: true }) });
70
+ }
71
+ if (defaultRoute) {
72
+ routerChildren.push({ path: '*', element: _jsx(Navigate, { to: defaultRoute.path, replace: true }) });
73
+ }
74
+ return createBrowserRouter([
75
+ {
76
+ element: _jsx(Root, { allPaths: permittedRoutes.map((route) => route.path).filter(Boolean) }),
77
+ errorElement: _jsx(ErrorPage, {}),
78
+ children: routerChildren,
79
+ },
80
+ ]);
81
+ }, [defaultRoute, permittedRoutes]);
93
82
  useEffect(() => {
94
83
  const root = window.document.documentElement;
95
84
  root.classList.remove('light', 'dark');
@@ -101,14 +90,14 @@ export const DeenruvAdminPanel = ({ plugins, settings }) => {
101
90
  root.classList.add(theme);
102
91
  }
103
92
  }, [theme]);
104
- return (_jsx(GlobalStoreProvider, { ...settings, children: _jsxs(I18nextProvider, { i18n: i18n, defaultNS: 'common', children: [_jsx(AnimatePresence, { children: isLoggedIn ? (_jsx(PluginProvider, { plugins: pluginsStore, context: context, children: _jsx(NotificationProvider, { notifications: [ORDER_STATUS_NOTIFICATION, SYSTEM_STATUS_NOTIFICATION].concat(pluginsStore.notifications), children: _jsx(RouterProvider, { router: router }) }) })) : (_jsx(LoginScreen, {})) }), _jsx(Toaster, { theme: theme, className: "toaster group", richColors: true, expand: true, position: "bottom-right", toastOptions: {
93
+ return (_jsx(GlobalStoreProvider, { ...settings, children: _jsxs(I18nextProvider, { i18n: i18n, defaultNS: 'common', children: [_jsx(AnimatePresence, { children: isLoggedIn ? (_jsx(AdminAccessProvider, { value: { routes: permittedRoutes, defaultRoute }, children: _jsx(PluginProvider, { plugins: pluginsStore, context: context, children: _jsx(NotificationProvider, { notifications: [ORDER_STATUS_NOTIFICATION, SYSTEM_STATUS_NOTIFICATION].concat(pluginsStore.notifications), children: _jsx(RouterProvider, { router: router }) }) }) })) : (_jsx(LoginScreen, {})) }), _jsx(Toaster, { theme: theme, className: "toaster group", richColors: true, expand: true, position: "bottom-right", toastOptions: {
105
94
  classNames: {
106
- toast: 'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg group-[.toaster]:rounded-lg group-[.toaster]:p-4',
95
+ toast: 'group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg group-[.toaster]:p-4',
107
96
  title: 'group-[.toast]:font-semibold group-[.toast]:text-foreground',
108
97
  description: 'group-[.toast]:text-muted-foreground group-[.toast]:text-sm',
109
- actionButton: 'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground group-[.toast]:rounded-md group-[.toast]:px-3 group-[.toast]:text-xs group-[.toast]:h-8 group-[.toast]:font-medium',
110
- cancelButton: 'group-[.toast]:bg-muted group-[.toast]:text-muted-foreground group-[.toast]:rounded-md group-[.toast]:px-3 group-[.toast]:text-xs group-[.toast]:h-8 group-[.toast]:font-medium',
111
- closeButton: 'group-[.toast]:text-foreground/50 group-[.toast]:hover:text-foreground group-[.toast]:rounded-md',
98
+ actionButton: 'group-[.toast]:bg-primary group-[.toast]:text-primary-foreground group-[.toast]:px-3 group-[.toast]:text-xs group-[.toast]:h-8 group-[.toast]:font-medium',
99
+ cancelButton: 'group-[.toast]:bg-muted group-[.toast]:text-muted-foreground group-[.toast]:px-3 group-[.toast]:text-xs group-[.toast]:h-8 group-[.toast]:font-medium',
100
+ closeButton: 'group-[.toast]:text-foreground/50 group-[.toast]:hover:text-foreground',
112
101
  success: 'group-[.toast]:border-l-4 group-[.toast]:border-l-green-500',
113
102
  error: 'group-[.toast]:border-l-4 group-[.toast]:border-l-red-500',
114
103
  warning: 'group-[.toast]:border-l-4 group-[.toast]:border-l-yellow-500',
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from 'react';
3
+ const AdminAccessContext = createContext(null);
4
+ export const AdminAccessProvider = ({ children, value, }) => (_jsx(AdminAccessContext.Provider, { value: value, children: children }));
5
+ export const useAdminAccess = () => {
6
+ const context = useContext(AdminAccessContext);
7
+ if (!context)
8
+ throw new Error('useAdminAccess must be used within AdminAccessProvider');
9
+ return context;
10
+ };
@@ -0,0 +1,300 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Permission } from '@deenruv/admin-types';
3
+ import { Routes } from '@deenruv/react-ui-devkit';
4
+ import { BarChart, Barcode, BadgePercent, Coins, Cog, CreditCard, Flag, Folder, Globe, Globe2, Images, MapPin, Percent, ScanBarcode, Server, ShoppingCart, Store, Tag, Truck, UserCog, UserRoundSearch, Users, UsersRound, } from 'lucide-react';
5
+ import { AdminsDetailPage, AdminsListPage, AdminsProvisionPage, AssetsListPage, ChannelsDetailPage, ChannelsListPage, CollectionsDetailPage, CollectionsListPage, CountriesDetailPage, CountriesListPage, CustomerGroupsDetailPage, CustomerGroupsListPage, CustomersDetailPage, CustomersListPage, Dashboard, Extensions, FacetsDetailPage, FacetsListPage, GlobalSettings, OrdersDetailPage, OrdersListPage, PaymentMethodsDetailPage, PaymentMethodsListPage, ProductVariantDetailPage, ProductVariantsListPage, ProductsDetailPage, ProductsListPage, PromotionsDetailPage, PromotionsListPage, RolesDetailPage, RolesListPage, SellersDetailPage, SellersListPage, ShippingMethodsDetailPage, ShippingMethodsListPage, Status, StockLocationsDetailPage, StockLocationsListPage, TaxCategoriesDetailPage, TaxCategoriesListPage, TaxRatesDetailPage, TaxRatesListPage, ZonesDetailPage, ZonesListPage, } from "../pages/index.js";
6
+ export const adminNavigationGroups = [
7
+ { id: 'shop-group', labelKey: 'shop' },
8
+ { id: 'assortment-group', labelKey: 'assortment' },
9
+ { id: 'users-group', labelKey: 'users' },
10
+ { id: 'promotions-group', labelKey: 'promotions' },
11
+ { id: 'shipping-group', labelKey: 'shipping' },
12
+ { id: 'settings-group', labelKey: 'settings' },
13
+ ];
14
+ const createCrudRouteDefinitions = ({ id, menuKey, routes, listElement, detailElement, readPermissions, createPermissions, nav, }) => {
15
+ const definitions = [
16
+ {
17
+ id: `${id}.list`,
18
+ path: routes.list,
19
+ element: listElement(),
20
+ requiredPermissions: readPermissions,
21
+ nav,
22
+ search: { menuKey, type: 'list' },
23
+ },
24
+ ];
25
+ if (routes.route && detailElement) {
26
+ definitions.push({
27
+ id: `${id}.detail`,
28
+ path: routes.route,
29
+ element: detailElement(),
30
+ requiredPermissions: readPermissions,
31
+ });
32
+ }
33
+ if (routes.new && detailElement) {
34
+ definitions.push({
35
+ id: `${id}.create`,
36
+ path: routes.new,
37
+ element: detailElement(),
38
+ requiredPermissions: createPermissions,
39
+ search: { menuKey, type: 'new' },
40
+ });
41
+ }
42
+ return definitions;
43
+ };
44
+ export const builtInAdminRoutes = [
45
+ {
46
+ id: 'dashboard',
47
+ path: Routes.dashboard,
48
+ element: _jsx(Dashboard, {}),
49
+ nav: { groupId: 'shop-group', linkId: 'link-dashboard', menuKey: 'dashboard', icon: BarChart },
50
+ search: { menuKey: 'dashboard', type: 'default' },
51
+ },
52
+ ...createCrudRouteDefinitions({
53
+ id: 'orders',
54
+ menuKey: 'orders',
55
+ routes: Routes.orders,
56
+ listElement: () => _jsx(OrdersListPage, {}),
57
+ detailElement: () => _jsx(OrdersDetailPage, {}),
58
+ readPermissions: [Permission.ReadOrder],
59
+ createPermissions: [Permission.CreateOrder],
60
+ nav: { groupId: 'shop-group', linkId: 'link-orders', menuKey: 'orders', icon: ShoppingCart },
61
+ }),
62
+ ...createCrudRouteDefinitions({
63
+ id: 'customers',
64
+ menuKey: 'customers',
65
+ routes: Routes.customers,
66
+ listElement: () => _jsx(CustomersListPage, {}),
67
+ detailElement: () => _jsx(CustomersDetailPage, {}),
68
+ readPermissions: [Permission.ReadCustomer],
69
+ createPermissions: [Permission.CreateCustomer],
70
+ nav: { groupId: 'shop-group', linkId: 'link-customers', menuKey: 'customers', icon: UserRoundSearch },
71
+ }),
72
+ ...createCrudRouteDefinitions({
73
+ id: 'customerGroups',
74
+ menuKey: 'customerGroups',
75
+ routes: Routes.customerGroups,
76
+ listElement: () => _jsx(CustomerGroupsListPage, {}),
77
+ detailElement: () => _jsx(CustomerGroupsDetailPage, {}),
78
+ readPermissions: [Permission.ReadCustomerGroup],
79
+ createPermissions: [Permission.CreateCustomerGroup],
80
+ nav: { groupId: 'shop-group', linkId: 'link-customerGroups', menuKey: 'customerGroups', icon: UsersRound },
81
+ }),
82
+ ...createCrudRouteDefinitions({
83
+ id: 'products',
84
+ menuKey: 'products',
85
+ routes: Routes.products,
86
+ listElement: () => _jsx(ProductsListPage, {}),
87
+ detailElement: () => _jsx(ProductsDetailPage, {}),
88
+ readPermissions: [Permission.ReadProduct, Permission.ReadCatalog],
89
+ createPermissions: [Permission.CreateProduct],
90
+ nav: { groupId: 'assortment-group', linkId: 'link-products', menuKey: 'products', icon: Barcode },
91
+ }),
92
+ ...createCrudRouteDefinitions({
93
+ id: 'productVariants',
94
+ menuKey: 'productVariants',
95
+ routes: Routes.productVariants,
96
+ listElement: () => _jsx(ProductVariantsListPage, {}),
97
+ detailElement: () => _jsx(ProductVariantDetailPage, {}),
98
+ readPermissions: [Permission.ReadProduct, Permission.ReadCatalog],
99
+ createPermissions: [Permission.CreateProduct],
100
+ nav: {
101
+ groupId: 'assortment-group',
102
+ linkId: 'link-product-variants',
103
+ menuKey: 'productVariants',
104
+ icon: ScanBarcode,
105
+ },
106
+ }),
107
+ ...createCrudRouteDefinitions({
108
+ id: 'collections',
109
+ menuKey: 'collections',
110
+ routes: Routes.collections,
111
+ listElement: () => _jsx(CollectionsListPage, {}),
112
+ detailElement: () => _jsx(CollectionsDetailPage, {}),
113
+ readPermissions: [Permission.ReadCollection, Permission.ReadCatalog],
114
+ createPermissions: [Permission.CreateCollection],
115
+ nav: { groupId: 'assortment-group', linkId: 'link-collections', menuKey: 'collections', icon: Folder },
116
+ }),
117
+ ...createCrudRouteDefinitions({
118
+ id: 'facets',
119
+ menuKey: 'facets',
120
+ routes: Routes.facets,
121
+ listElement: () => _jsx(FacetsListPage, {}),
122
+ detailElement: () => _jsx(FacetsDetailPage, {}),
123
+ readPermissions: [Permission.ReadFacet, Permission.ReadCatalog],
124
+ createPermissions: [Permission.CreateFacet],
125
+ nav: { groupId: 'assortment-group', linkId: 'link-facets', menuKey: 'facets', icon: Tag },
126
+ }),
127
+ {
128
+ id: 'assets.list',
129
+ path: Routes.assets.list,
130
+ element: _jsx(AssetsListPage, {}),
131
+ requiredPermissions: [Permission.ReadAsset, Permission.ReadCatalog],
132
+ nav: { groupId: 'assortment-group', linkId: 'link-assets', menuKey: 'assets', icon: Images },
133
+ search: { menuKey: 'assets', type: 'list' },
134
+ },
135
+ ...createCrudRouteDefinitions({
136
+ id: 'admins',
137
+ menuKey: 'admins',
138
+ routes: Routes.admins,
139
+ listElement: () => _jsx(AdminsListPage, {}),
140
+ detailElement: () => _jsx(AdminsDetailPage, {}),
141
+ readPermissions: [Permission.ReadAdministrator],
142
+ createPermissions: [Permission.CreateAdministrator],
143
+ nav: { groupId: 'users-group', linkId: 'link-admins', menuKey: 'admins', icon: UserCog },
144
+ }),
145
+ {
146
+ id: 'admins.provision',
147
+ path: Routes.admins.provision,
148
+ element: _jsx(AdminsProvisionPage, {}),
149
+ requiredPermissions: [Permission.CreateAdministrator],
150
+ search: { menuKey: 'adminProvision', type: 'new' },
151
+ },
152
+ ...createCrudRouteDefinitions({
153
+ id: 'roles',
154
+ menuKey: 'roles',
155
+ routes: Routes.roles,
156
+ listElement: () => _jsx(RolesListPage, {}),
157
+ detailElement: () => _jsx(RolesDetailPage, {}),
158
+ readPermissions: [Permission.ReadAdministrator],
159
+ createPermissions: [Permission.CreateAdministrator],
160
+ nav: { groupId: 'users-group', linkId: 'link-roles', menuKey: 'roles', icon: Users },
161
+ }),
162
+ ...createCrudRouteDefinitions({
163
+ id: 'sellers',
164
+ menuKey: 'sellers',
165
+ routes: Routes.sellers,
166
+ listElement: () => _jsx(SellersListPage, {}),
167
+ detailElement: () => _jsx(SellersDetailPage, {}),
168
+ readPermissions: [Permission.ReadSeller],
169
+ createPermissions: [Permission.CreateSeller],
170
+ nav: { groupId: 'users-group', linkId: 'link-sellers', menuKey: 'sellers', icon: Store },
171
+ }),
172
+ ...createCrudRouteDefinitions({
173
+ id: 'promotions',
174
+ menuKey: 'promotions',
175
+ routes: Routes.promotions,
176
+ listElement: () => _jsx(PromotionsListPage, {}),
177
+ detailElement: () => _jsx(PromotionsDetailPage, {}),
178
+ readPermissions: [Permission.ReadPromotion],
179
+ createPermissions: [Permission.CreatePromotion],
180
+ nav: { groupId: 'promotions-group', linkId: 'link-promotions', menuKey: 'promotions', icon: BadgePercent },
181
+ }),
182
+ ...createCrudRouteDefinitions({
183
+ id: 'paymentMethods',
184
+ menuKey: 'paymentMethods',
185
+ routes: Routes.paymentMethods,
186
+ listElement: () => _jsx(PaymentMethodsListPage, {}),
187
+ detailElement: () => _jsx(PaymentMethodsDetailPage, {}),
188
+ readPermissions: [Permission.ReadPaymentMethod],
189
+ createPermissions: [Permission.CreatePaymentMethod],
190
+ nav: {
191
+ groupId: 'shipping-group',
192
+ linkId: 'link-payment-methods',
193
+ menuKey: 'paymentMethods',
194
+ icon: CreditCard,
195
+ },
196
+ }),
197
+ ...createCrudRouteDefinitions({
198
+ id: 'shippingMethods',
199
+ menuKey: 'shippingMethods',
200
+ routes: Routes.shippingMethods,
201
+ listElement: () => _jsx(ShippingMethodsListPage, {}),
202
+ detailElement: () => _jsx(ShippingMethodsDetailPage, {}),
203
+ readPermissions: [Permission.ReadShippingMethod],
204
+ createPermissions: [Permission.CreateShippingMethod],
205
+ nav: {
206
+ groupId: 'shipping-group',
207
+ linkId: 'link-shipping-methods',
208
+ menuKey: 'shippingMethods',
209
+ icon: Truck,
210
+ },
211
+ }),
212
+ ...createCrudRouteDefinitions({
213
+ id: 'stockLocations',
214
+ menuKey: 'stock',
215
+ routes: Routes.stockLocations,
216
+ listElement: () => _jsx(StockLocationsListPage, {}),
217
+ detailElement: () => _jsx(StockLocationsDetailPage, {}),
218
+ readPermissions: [Permission.ReadStockLocation],
219
+ createPermissions: [Permission.CreateStockLocation],
220
+ nav: { groupId: 'shipping-group', linkId: 'link-stock', menuKey: 'stock', icon: MapPin },
221
+ }),
222
+ ...createCrudRouteDefinitions({
223
+ id: 'channels',
224
+ menuKey: 'channels',
225
+ routes: Routes.channels,
226
+ listElement: () => _jsx(ChannelsListPage, {}),
227
+ detailElement: () => _jsx(ChannelsDetailPage, {}),
228
+ readPermissions: [Permission.ReadChannel],
229
+ createPermissions: [Permission.CreateChannel],
230
+ nav: { groupId: 'settings-group', linkId: 'link-channels', menuKey: 'channels', icon: Globe2 },
231
+ }),
232
+ ...createCrudRouteDefinitions({
233
+ id: 'zones',
234
+ menuKey: 'zones',
235
+ routes: Routes.zones,
236
+ listElement: () => _jsx(ZonesListPage, {}),
237
+ detailElement: () => _jsx(ZonesDetailPage, {}),
238
+ readPermissions: [Permission.ReadZone],
239
+ createPermissions: [Permission.CreateZone],
240
+ nav: { groupId: 'settings-group', linkId: 'link-zones', menuKey: 'zones', icon: Globe },
241
+ }),
242
+ ...createCrudRouteDefinitions({
243
+ id: 'countries',
244
+ menuKey: 'countries',
245
+ routes: Routes.countries,
246
+ listElement: () => _jsx(CountriesListPage, {}),
247
+ detailElement: () => _jsx(CountriesDetailPage, {}),
248
+ readPermissions: [Permission.ReadCountry],
249
+ createPermissions: [Permission.CreateCountry],
250
+ nav: { groupId: 'settings-group', linkId: 'link-countries', menuKey: 'countries', icon: Flag },
251
+ }),
252
+ ...createCrudRouteDefinitions({
253
+ id: 'taxCategories',
254
+ menuKey: 'taxCategories',
255
+ routes: Routes.taxCategories,
256
+ listElement: () => _jsx(TaxCategoriesListPage, {}),
257
+ detailElement: () => _jsx(TaxCategoriesDetailPage, {}),
258
+ readPermissions: [Permission.ReadTaxCategory],
259
+ createPermissions: [Permission.CreateTaxCategory],
260
+ nav: {
261
+ groupId: 'settings-group',
262
+ linkId: 'link-tax-categories',
263
+ menuKey: 'taxCategories',
264
+ icon: Coins,
265
+ },
266
+ }),
267
+ ...createCrudRouteDefinitions({
268
+ id: 'taxRates',
269
+ menuKey: 'taxRates',
270
+ routes: Routes.taxRates,
271
+ listElement: () => _jsx(TaxRatesListPage, {}),
272
+ detailElement: () => _jsx(TaxRatesDetailPage, {}),
273
+ readPermissions: [Permission.ReadTaxRate],
274
+ createPermissions: [Permission.CreateTaxRate],
275
+ nav: { groupId: 'settings-group', linkId: 'link-tax-rates', menuKey: 'taxRates', icon: Percent },
276
+ }),
277
+ {
278
+ id: 'settings.global',
279
+ path: Routes.globalSettings,
280
+ element: _jsx(GlobalSettings, {}),
281
+ requiredPermissions: [Permission.ReadSettings],
282
+ nav: { groupId: 'settings-group', linkId: 'link-global-settings', menuKey: 'globalSettings', icon: Cog },
283
+ search: { menuKey: 'globalSettings', type: 'default' },
284
+ },
285
+ {
286
+ id: 'system.status',
287
+ path: Routes.status,
288
+ element: _jsx(Status, {}),
289
+ requiredPermissions: [Permission.ReadSystem],
290
+ nav: { groupId: 'settings-group', linkId: 'link-system-status', menuKey: 'systemStatus', icon: Server },
291
+ search: { menuKey: 'systemStatus', type: 'default' },
292
+ },
293
+ {
294
+ id: 'extensions',
295
+ path: Routes.extensions,
296
+ element: _jsx(Extensions, {}),
297
+ requiredPermissions: [Permission.ReadSettings],
298
+ search: { menuKey: 'extensions', type: 'default' },
299
+ },
300
+ ];
@@ -0,0 +1,6 @@
1
+ export * from './access-context.js';
2
+ export * from './built-in-routes.js';
3
+ export * from './navigation.js';
4
+ export * from './permission-access.js';
5
+ export * from './permission-routes.js';
6
+ export * from './types.js';
@@ -0,0 +1,33 @@
1
+ export const matchesNavigationPath = (pathname, routePath) => {
2
+ const pathnameSegments = pathname.split('/').filter(Boolean);
3
+ const routeSegments = routePath.split('/').filter(Boolean);
4
+ return (pathnameSegments.length === routeSegments.length &&
5
+ routeSegments.every((segment, index) => segment.startsWith(':') || segment === pathnameSegments[index]));
6
+ };
7
+ export const getRouteFamilyId = (routeId) => routeId.split('.')[0];
8
+ export const getNavigationLinkActivePaths = (route, routes) => {
9
+ const routeFamilyId = getRouteFamilyId(route.id);
10
+ const relatedPaths = routes
11
+ .filter((candidate) => getRouteFamilyId(candidate.id) === routeFamilyId)
12
+ .map((candidate) => candidate.path);
13
+ return [...relatedPaths.filter((path) => !path.includes(':')), ...relatedPaths.filter((path) => path.includes(':'))];
14
+ };
15
+ export const isNavigationLinkActive = (link, pathname) => (link.activePaths?.length ? link.activePaths : [link.href]).some((path) => matchesNavigationPath(pathname, path));
16
+ export const getActiveNavigationLinkIds = (links, pathname) => {
17
+ const exactPathMatches = links.filter((link) => link.href === pathname);
18
+ return exactPathMatches.length > 0
19
+ ? exactPathMatches
20
+ : links.filter((link) => isNavigationLinkActive(link, pathname));
21
+ };
22
+ export const getActiveNavigationGroupIds = (links, pathname) => [
23
+ ...new Set(getActiveNavigationLinkIds(links, pathname).map((link) => link.groupId)),
24
+ ];
25
+ export const insertNavigationLink = (links, link, placement) => {
26
+ if (!placement)
27
+ return [...links, link];
28
+ const index = links.findIndex((item) => item.id === placement.linkId);
29
+ if (index === -1)
30
+ return [...links, link];
31
+ const insertionIndex = placement.where === 'above' ? index : index + 1;
32
+ return [...links.slice(0, insertionIndex), link, ...links.slice(insertionIndex)];
33
+ };
@@ -0,0 +1,9 @@
1
+ export const hasRequiredPermissions = ({ requiredPermissions, permissionMatch = 'any', userPermissions, }) => {
2
+ if (!requiredPermissions?.length)
3
+ return true;
4
+ if (permissionMatch === 'all') {
5
+ return requiredPermissions.every((permission) => userPermissions.includes(permission));
6
+ }
7
+ return requiredPermissions.some((permission) => userPermissions.includes(permission));
8
+ };
9
+ export const canAccessAdminItem = ({ item, userPermissions, }) => hasRequiredPermissions({ ...item, userPermissions });
@@ -0,0 +1,3 @@
1
+ import { canAccessAdminItem } from './permission-access.js';
2
+ export const getPermittedAdminRoutes = (routes, userPermissions) => routes.filter((route) => canAccessAdminItem({ item: route, userPermissions }));
3
+ export const getDefaultAdminRoute = (routes) => routes.find((route) => route.id === 'dashboard') || routes.find((route) => route.nav) || routes[0];
@@ -0,0 +1 @@
1
+ export {};