@vendure/dashboard 3.3.8 → 3.4.0
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 +62 -0
- package/dist/plugin/api/api-extensions.d.ts +1 -0
- package/dist/plugin/api/api-extensions.js +38 -0
- package/dist/plugin/api/metrics.resolver.d.ts +8 -0
- package/dist/plugin/api/metrics.resolver.js +40 -0
- package/dist/plugin/config/metrics-strategies.d.ts +39 -0
- package/dist/plugin/config/metrics-strategies.js +74 -0
- package/dist/plugin/constants.d.ts +4 -3
- package/dist/plugin/constants.js +10 -277
- package/dist/plugin/dashboard.plugin.d.ts +95 -0
- package/dist/plugin/dashboard.plugin.js +168 -0
- package/dist/plugin/index.d.ts +2 -1
- package/dist/plugin/index.js +18 -1
- package/dist/plugin/package.json +3 -0
- package/dist/plugin/service/metrics.service.d.ts +15 -0
- package/dist/plugin/service/metrics.service.js +145 -0
- package/dist/plugin/types.d.ts +20 -37
- package/dist/plugin/types.js +13 -1
- package/dist/vite/constants.d.ts +5 -0
- package/dist/vite/constants.js +277 -0
- package/dist/vite/index.d.ts +1 -0
- package/dist/vite/index.js +1 -0
- package/dist/vite/types.d.ts +40 -0
- package/dist/vite/utils/config-loader.js +1 -0
- package/dist/{plugin → vite}/utils/plugin-discovery.js +1 -1
- package/dist/vite/utils/ui-config.d.ts +3 -0
- package/dist/vite/utils/ui-config.js +30 -0
- package/dist/vite/vite-plugin-ui-config.d.ts +123 -0
- package/dist/{plugin → vite}/vite-plugin-ui-config.js +3 -11
- package/dist/{plugin → vite}/vite-plugin-vendure-dashboard.js +1 -1
- package/index.html +1 -1
- package/package.json +16 -7
- package/src/app/app-providers.tsx +1 -1
- package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +20 -35
- package/src/app/routes/_authenticated/_facets/facets.graphql.ts +40 -0
- package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +147 -0
- package/src/app/routes/_authenticated/_orders/components/order-history/order-history.tsx +380 -33
- package/src/app/routes/_authenticated/_products/components/option-value-input.tsx +1 -1
- package/src/app/routes/_authenticated/_system/healthchecks.tsx +1 -1
- package/src/app/routes/_authenticated/_system/job-queue.tsx +1 -0
- package/src/app/routes/_authenticated/index.tsx +2 -2
- package/src/app/routes/_authenticated.tsx +1 -1
- package/src/lib/components/data-input/rich-text-input.tsx +14 -8
- package/src/lib/components/data-table/data-table-bulk-actions.tsx +17 -4
- package/src/lib/components/layout/app-layout.tsx +2 -7
- package/src/lib/components/layout/channel-switcher.tsx +166 -57
- package/src/lib/components/layout/dev-mode-indicator.tsx +18 -0
- package/src/lib/components/layout/language-dialog.tsx +2 -1
- package/src/lib/components/layout/manage-languages-dialog.tsx +77 -40
- package/src/lib/components/layout/nav-item-wrapper.tsx +107 -0
- package/src/lib/components/layout/nav-main.tsx +196 -107
- package/src/lib/components/login/login-form.tsx +80 -45
- package/src/lib/components/shared/asset/asset-bulk-actions.tsx +19 -4
- package/src/lib/components/shared/asset/asset-gallery.tsx +2 -2
- package/src/lib/components/shared/detail-page-button.tsx +42 -0
- package/src/lib/components/shared/history-timeline/history-entry-date.tsx +37 -0
- package/src/lib/components/shared/history-timeline/history-entry.tsx +135 -65
- package/src/lib/components/shared/history-timeline/history-note-input.tsx +4 -4
- package/src/lib/components/shared/history-timeline/history-timeline.tsx +7 -54
- package/src/lib/components/shared/translatable-form-field.tsx +16 -2
- package/src/lib/framework/defaults.ts +4 -10
- package/src/lib/framework/extension-api/define-dashboard-extension.ts +4 -0
- package/src/lib/framework/extension-api/extension-api-types.ts +11 -2
- package/src/lib/framework/extension-api/logic/index.ts +1 -0
- package/src/lib/framework/extension-api/logic/login.ts +17 -0
- package/src/lib/framework/extension-api/logic/navigation.ts +1 -0
- package/src/lib/framework/extension-api/types/data-table.ts +12 -3
- package/src/lib/framework/extension-api/types/detail-forms.ts +13 -0
- package/src/lib/framework/extension-api/types/form-components.ts +11 -0
- package/src/lib/framework/extension-api/types/index.ts +1 -0
- package/src/lib/framework/extension-api/types/layout.ts +3 -6
- package/src/lib/framework/extension-api/types/login.ts +96 -0
- package/src/lib/framework/extension-api/types/navigation.ts +57 -0
- package/src/lib/framework/extension-api/types/widgets.ts +0 -4
- package/src/lib/framework/extension-api/use-login-extensions.ts +26 -0
- package/src/lib/framework/layout-engine/dev-mode-button.tsx +24 -0
- package/src/lib/framework/layout-engine/location-wrapper.tsx +5 -12
- package/src/lib/framework/registry/global-registry.ts +4 -0
- package/src/lib/framework/registry/registry-types.ts +2 -0
- package/src/lib/graphql/api.ts +25 -3
- package/src/lib/graphql/graphql-env.d.ts +28 -28
- package/src/lib/graphql/settings-store-operations.ts +17 -0
- package/src/lib/hooks/use-floating-bulk-actions.ts +82 -0
- package/src/lib/hooks/use-local-format.ts +20 -5
- package/src/lib/index.ts +2 -1
- package/src/lib/providers/channel-provider.tsx +13 -11
- package/src/lib/providers/user-settings.tsx +78 -3
- package/src/lib/virtual.d.ts +26 -2
- package/src/vite-env.d.ts +2 -0
- package/vite/utils/plugin-discovery.ts +1 -1
- package/vite/utils/ui-config.ts +30 -42
- package/vite/vite-plugin-ui-config.ts +119 -17
- package/vite/vite-plugin-vendure-dashboard.ts +1 -1
- package/dist/plugin/utils/ui-config.d.ts +0 -3
- package/dist/plugin/utils/ui-config.js +0 -34
- package/dist/plugin/vite-plugin-ui-config.d.ts +0 -15
- package/src/app/routes/_authenticated/_facets/components/add-facet-value-dialog.tsx +0 -146
- package/src/lib/components/shared/rich-text-editor.tsx +0 -0
- /package/dist/{plugin/utils/ast-utils.spec.d.ts → vite/types.js} +0 -0
- /package/dist/{plugin → vite}/utils/ast-utils.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/ast-utils.js +0 -0
- /package/dist/{plugin/utils/config-loader.d.ts → vite/utils/ast-utils.spec.d.ts} +0 -0
- /package/dist/{plugin → vite}/utils/ast-utils.spec.js +0 -0
- /package/dist/{plugin → vite}/utils/compiler.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/compiler.js +0 -0
- /package/dist/{plugin/utils/config-loader.js → vite/utils/config-loader.d.ts} +0 -0
- /package/dist/{plugin → vite}/utils/logger.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/logger.js +0 -0
- /package/dist/{plugin → vite}/utils/plugin-discovery.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/schema-generator.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/schema-generator.js +0 -0
- /package/dist/{plugin → vite}/utils/tsconfig-utils.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/tsconfig-utils.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-admin-api-schema.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-admin-api-schema.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-config-loader.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-config-loader.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-config.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-config.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-dashboard-metadata.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-dashboard-metadata.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-gql-tada.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-gql-tada.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-tailwind-source.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-tailwind-source.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-theme.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-theme.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-transform-index.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-transform-index.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-vendure-dashboard.d.ts +0 -0
|
@@ -7,6 +7,7 @@ import { DocumentNode } from 'graphql';
|
|
|
7
7
|
* The pageId is already defined in the data table extension, so only the column name is needed.
|
|
8
8
|
*
|
|
9
9
|
* @docsCategory extensions
|
|
10
|
+
* @docsPage DataTable
|
|
10
11
|
* @since 3.4.0
|
|
11
12
|
*/
|
|
12
13
|
export interface DashboardDataTableDisplayComponent {
|
|
@@ -39,21 +40,29 @@ export type BulkActionComponent<Item extends { id: string } & Record<string, any
|
|
|
39
40
|
* A bulk action is a component that will be rendered in the bulk actions dropdown.
|
|
40
41
|
*
|
|
41
42
|
* @docsCategory components
|
|
42
|
-
* @docsPage
|
|
43
|
+
* @docsPage DataTable
|
|
43
44
|
* @since 3.4.0
|
|
44
45
|
*/
|
|
45
46
|
export type BulkAction = {
|
|
47
|
+
/**
|
|
48
|
+
* @description
|
|
49
|
+
* Optional order number to control the position of this bulk action in the dropdown.
|
|
50
|
+
* A larger number will appear lower in the list.
|
|
51
|
+
*/
|
|
46
52
|
order?: number;
|
|
53
|
+
/**
|
|
54
|
+
* @description
|
|
55
|
+
* The React component that will be rendered as the bulk action item.
|
|
56
|
+
*/
|
|
47
57
|
component: BulkActionComponent<any>;
|
|
48
58
|
};
|
|
49
59
|
|
|
50
60
|
/**
|
|
51
61
|
* @description
|
|
52
|
-
* **Status: Developer Preview**
|
|
53
|
-
*
|
|
54
62
|
* This allows you to customize aspects of existing data tables in the dashboard.
|
|
55
63
|
*
|
|
56
64
|
* @docsCategory extensions
|
|
65
|
+
* @docsPage DataTable
|
|
57
66
|
* @since 3.4.0
|
|
58
67
|
*/
|
|
59
68
|
export interface DashboardDataTableExtensionDefinition {
|
|
@@ -10,6 +10,7 @@ import { DocumentNode } from 'graphql';
|
|
|
10
10
|
* The pageId is already defined in the detail form extension, so only the blockId and field are needed.
|
|
11
11
|
*
|
|
12
12
|
* @docsCategory extensions
|
|
13
|
+
* @docsPage DetailForms
|
|
13
14
|
* @since 3.4.0
|
|
14
15
|
*/
|
|
15
16
|
export interface DashboardDetailFormInputComponent {
|
|
@@ -37,6 +38,7 @@ export interface DashboardDetailFormInputComponent {
|
|
|
37
38
|
* The pageId is already defined in the detail form extension, so only the blockId and field are needed.
|
|
38
39
|
*
|
|
39
40
|
* @docsCategory extensions
|
|
41
|
+
* @docsPage DetailForms
|
|
40
42
|
* @since 3.4.0
|
|
41
43
|
*/
|
|
42
44
|
export interface DashboardDetailFormDisplayComponent {
|
|
@@ -58,6 +60,15 @@ export interface DashboardDetailFormDisplayComponent {
|
|
|
58
60
|
component: DataDisplayComponent;
|
|
59
61
|
}
|
|
60
62
|
|
|
63
|
+
/**
|
|
64
|
+
* @description
|
|
65
|
+
* Allows you to extend existing detail forms (e.g. on the product detail or customer detail pages)
|
|
66
|
+
* with custom GraphQL queries, input components, and display components.
|
|
67
|
+
*
|
|
68
|
+
* @since 3.4.0
|
|
69
|
+
* @docsPage DetailForms
|
|
70
|
+
* @docsCategory extensions
|
|
71
|
+
*/
|
|
61
72
|
export interface DashboardDetailFormExtensionDefinition {
|
|
62
73
|
/**
|
|
63
74
|
* @description
|
|
@@ -66,6 +77,8 @@ export interface DashboardDetailFormExtensionDefinition {
|
|
|
66
77
|
pageId: string;
|
|
67
78
|
/**
|
|
68
79
|
* @description
|
|
80
|
+
* Extends the GraphQL query used to fetch data for the detail page, allowing you to add additional
|
|
81
|
+
* fields that can be used by custom input or display components.
|
|
69
82
|
*/
|
|
70
83
|
extendDetailDocument?: string | DocumentNode | (() => DocumentNode | string);
|
|
71
84
|
/**
|
|
@@ -7,10 +7,20 @@ import { CustomFormComponentInputProps } from '../../form-engine/custom-form-com
|
|
|
7
7
|
* Allows you to define custom form components for custom fields in the dashboard.
|
|
8
8
|
*
|
|
9
9
|
* @docsCategory extensions
|
|
10
|
+
* @docsPage FormComponents
|
|
10
11
|
* @since 3.4.0
|
|
11
12
|
*/
|
|
12
13
|
export interface DashboardCustomFormComponent {
|
|
14
|
+
/**
|
|
15
|
+
* @description
|
|
16
|
+
* A unique identifier for the custom form component. It is a good practice to namespace
|
|
17
|
+
* these IDs to avoid naming collisions, for example `"my-plugin.markdown-editor"`.
|
|
18
|
+
*/
|
|
13
19
|
id: string;
|
|
20
|
+
/**
|
|
21
|
+
* @description
|
|
22
|
+
* The React component that will be rendered as the custom form input.
|
|
23
|
+
*/
|
|
14
24
|
component: React.FunctionComponent<CustomFormComponentInputProps>;
|
|
15
25
|
}
|
|
16
26
|
|
|
@@ -20,6 +30,7 @@ export interface DashboardCustomFormComponent {
|
|
|
20
30
|
* For input and display components, use the co-located approach with detailForms.
|
|
21
31
|
*
|
|
22
32
|
* @docsCategory extensions
|
|
33
|
+
* @docsPage FormComponents
|
|
23
34
|
* @since 3.4.0
|
|
24
35
|
*/
|
|
25
36
|
export interface DashboardCustomFormComponents {
|
|
@@ -9,11 +9,10 @@ export interface ActionBarButtonState {
|
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @description
|
|
12
|
-
* **Status: Developer Preview**
|
|
13
|
-
*
|
|
14
12
|
* Allows you to define custom action bar items for any page in the dashboard.
|
|
15
13
|
*
|
|
16
14
|
* @docsCategory extensions
|
|
15
|
+
* @docsPage Layout
|
|
17
16
|
* @since 3.3.0
|
|
18
17
|
*/
|
|
19
18
|
export interface DashboardActionBarItem {
|
|
@@ -59,13 +58,12 @@ export type PageBlockPosition = { blockId: string; order: 'before' | 'after' | '
|
|
|
59
58
|
|
|
60
59
|
/**
|
|
61
60
|
* @description
|
|
62
|
-
* **Status: Developer Preview**
|
|
63
|
-
*
|
|
64
61
|
* The location of a page block in the dashboard. The location can be found by turning on
|
|
65
62
|
* "developer mode" in the dashboard user menu (bottom left corner) and then
|
|
66
63
|
* clicking the `< />` icon when hovering over a page block.
|
|
67
64
|
*
|
|
68
65
|
* @docsCategory extensions
|
|
66
|
+
* @docsPage Layout
|
|
69
67
|
* @since 3.3.0
|
|
70
68
|
*/
|
|
71
69
|
export type PageBlockLocation = {
|
|
@@ -76,12 +74,11 @@ export type PageBlockLocation = {
|
|
|
76
74
|
|
|
77
75
|
/**
|
|
78
76
|
* @description
|
|
79
|
-
* **Status: Developer Preview**
|
|
80
|
-
*
|
|
81
77
|
* This allows you to insert a custom component into a specific location
|
|
82
78
|
* on any page in the dashboard.
|
|
83
79
|
*
|
|
84
80
|
* @docsCategory extensions
|
|
81
|
+
* @docsPage Layout
|
|
85
82
|
* @since 3.3.0
|
|
86
83
|
*/
|
|
87
84
|
export interface DashboardPageBlockDefinition {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @description
|
|
5
|
+
* Defines a custom logo component for the login page.
|
|
6
|
+
*
|
|
7
|
+
* @docsCategory extensions
|
|
8
|
+
* @docsPage Login
|
|
9
|
+
* @since 3.4.0
|
|
10
|
+
*/
|
|
11
|
+
export interface LoginLogoExtension {
|
|
12
|
+
/**
|
|
13
|
+
* @description
|
|
14
|
+
* A React component that will replace the default Vendure logo.
|
|
15
|
+
*/
|
|
16
|
+
component: React.ComponentType;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @description
|
|
21
|
+
* Defines content to display before the login form.
|
|
22
|
+
*
|
|
23
|
+
* @docsCategory extensions
|
|
24
|
+
* @docsPage Login
|
|
25
|
+
* @since 3.4.0
|
|
26
|
+
*/
|
|
27
|
+
export interface LoginBeforeFormExtension {
|
|
28
|
+
/**
|
|
29
|
+
* @description
|
|
30
|
+
* A React component that will be rendered before the login form.
|
|
31
|
+
*/
|
|
32
|
+
component: React.ComponentType;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @description
|
|
37
|
+
* Defines content to display after the login form.
|
|
38
|
+
*
|
|
39
|
+
* @docsCategory extensions
|
|
40
|
+
* @docsPage Login
|
|
41
|
+
* @since 3.4.0
|
|
42
|
+
*/
|
|
43
|
+
export interface LoginAfterFormExtension {
|
|
44
|
+
/**
|
|
45
|
+
* @description
|
|
46
|
+
* A React component that will be rendered after the login form.
|
|
47
|
+
*/
|
|
48
|
+
component: React.ComponentType;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @description
|
|
53
|
+
* Defines a custom login image component that replaces the default image panel.
|
|
54
|
+
*
|
|
55
|
+
* @docsCategory extensions
|
|
56
|
+
* @docsPage Login
|
|
57
|
+
* @since 3.4.0
|
|
58
|
+
*/
|
|
59
|
+
export interface LoginImageExtension {
|
|
60
|
+
/**
|
|
61
|
+
* @description
|
|
62
|
+
* A React component that will replace the default login image panel.
|
|
63
|
+
*/
|
|
64
|
+
component: React.ComponentType;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* @description
|
|
69
|
+
* Defines all available login page extensions.
|
|
70
|
+
*
|
|
71
|
+
* @docsCategory extensions
|
|
72
|
+
* @docsPage Login
|
|
73
|
+
* @since 3.4.0
|
|
74
|
+
*/
|
|
75
|
+
export interface DashboardLoginExtensions {
|
|
76
|
+
/**
|
|
77
|
+
* @description
|
|
78
|
+
* Custom logo component to replace the default Vendure logo.
|
|
79
|
+
*/
|
|
80
|
+
logo?: LoginLogoExtension;
|
|
81
|
+
/**
|
|
82
|
+
* @description
|
|
83
|
+
* Component to render before the login form.
|
|
84
|
+
*/
|
|
85
|
+
beforeForm?: LoginBeforeFormExtension;
|
|
86
|
+
/**
|
|
87
|
+
* @description
|
|
88
|
+
* Component to render after the login form.
|
|
89
|
+
*/
|
|
90
|
+
afterForm?: LoginAfterFormExtension;
|
|
91
|
+
/**
|
|
92
|
+
* @description
|
|
93
|
+
* Custom login image component to replace the default image panel.
|
|
94
|
+
*/
|
|
95
|
+
loginImage?: LoginImageExtension;
|
|
96
|
+
}
|
|
@@ -4,16 +4,73 @@ import type React from 'react';
|
|
|
4
4
|
|
|
5
5
|
import { NavMenuItem } from '../../nav-menu/nav-menu-extensions.js';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* @description
|
|
9
|
+
* Defines a custom route for the dashboard with optional navigation menu integration.
|
|
10
|
+
*
|
|
11
|
+
* @docsCategory extensions
|
|
12
|
+
* @docsPage Navigation
|
|
13
|
+
* @since 3.4.0
|
|
14
|
+
*/
|
|
7
15
|
export interface DashboardRouteDefinition {
|
|
16
|
+
/**
|
|
17
|
+
* @description
|
|
18
|
+
* The React component that will be rendered for this route.
|
|
19
|
+
*/
|
|
8
20
|
component: (route: AnyRoute) => React.ReactNode;
|
|
21
|
+
/**
|
|
22
|
+
* @description
|
|
23
|
+
* The URL path for this route, e.g. '/my-custom-page'.
|
|
24
|
+
*/
|
|
9
25
|
path: string;
|
|
26
|
+
/**
|
|
27
|
+
* @description
|
|
28
|
+
* Optional navigation menu item configuration to add this route to the nav menu
|
|
29
|
+
* on the left side of the dashboard.
|
|
30
|
+
*/
|
|
10
31
|
navMenuItem?: Partial<NavMenuItem> & { sectionId: string };
|
|
32
|
+
/**
|
|
33
|
+
* @description
|
|
34
|
+
* Optional loader function to fetch data before the route renders.
|
|
35
|
+
* The value is a Tanstack Router
|
|
36
|
+
* [loader function](https://tanstack.com/router/latest/docs/framework/react/guide/data-loading#route-loaders)
|
|
37
|
+
*/
|
|
11
38
|
loader?: RouteOptions['loader'];
|
|
12
39
|
}
|
|
13
40
|
|
|
41
|
+
/**
|
|
42
|
+
* @description
|
|
43
|
+
* Defines a custom navigation section in the dashboard sidebar.
|
|
44
|
+
*
|
|
45
|
+
* @docsCategory extensions
|
|
46
|
+
* @docsPage Navigation
|
|
47
|
+
* @since 3.4.0
|
|
48
|
+
*/
|
|
14
49
|
export interface DashboardNavSectionDefinition {
|
|
50
|
+
/**
|
|
51
|
+
* @description
|
|
52
|
+
* A unique identifier for the navigation section.
|
|
53
|
+
*/
|
|
15
54
|
id: string;
|
|
55
|
+
/**
|
|
56
|
+
* @description
|
|
57
|
+
* The display title for the navigation section.
|
|
58
|
+
*/
|
|
16
59
|
title: string;
|
|
60
|
+
/**
|
|
61
|
+
* @description
|
|
62
|
+
* Optional icon to display next to the section title. The icons should
|
|
63
|
+
* be imported from `'lucide-react'`.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* import { PlusIcon } from 'lucide-react';
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
17
70
|
icon?: LucideIcon;
|
|
71
|
+
/**
|
|
72
|
+
* @description
|
|
73
|
+
* Optional order number to control the position of this section in the sidebar.
|
|
74
|
+
*/
|
|
18
75
|
order?: number;
|
|
19
76
|
}
|
|
@@ -2,8 +2,6 @@ import React, { PropsWithChildren } from 'react';
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @description
|
|
5
|
-
* **Status: Developer Preview**
|
|
6
|
-
*
|
|
7
5
|
* Base props interface for dashboard widgets.
|
|
8
6
|
*
|
|
9
7
|
* @docsCategory extensions
|
|
@@ -19,8 +17,6 @@ export type DashboardBaseWidgetProps = PropsWithChildren<{
|
|
|
19
17
|
|
|
20
18
|
/**
|
|
21
19
|
* @description
|
|
22
|
-
* **Status: Developer Preview**
|
|
23
|
-
*
|
|
24
20
|
* Represents an instance of a dashboard widget with its layout and configuration.
|
|
25
21
|
*
|
|
26
22
|
* @docsCategory extensions
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { useEffect, useState } from 'react';
|
|
2
|
+
|
|
3
|
+
import { globalRegistry } from '../registry/global-registry.js';
|
|
4
|
+
|
|
5
|
+
import { onExtensionSourceChange } from './define-dashboard-extension.js';
|
|
6
|
+
import { DashboardLoginExtensions } from './types/login.js';
|
|
7
|
+
|
|
8
|
+
export function useLoginExtensions(): DashboardLoginExtensions {
|
|
9
|
+
const [extensions, setExtensions] = useState<DashboardLoginExtensions>(() => {
|
|
10
|
+
return globalRegistry.get('loginExtensions') || {};
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
const updateExtensions = () => {
|
|
15
|
+
setExtensions(globalRegistry.get('loginExtensions') || {});
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
// Subscribe to extension changes
|
|
19
|
+
onExtensionSourceChange(updateExtensions);
|
|
20
|
+
|
|
21
|
+
// Update immediately in case extensions were registered before this hook was called
|
|
22
|
+
updateExtensions();
|
|
23
|
+
}, []);
|
|
24
|
+
|
|
25
|
+
return extensions;
|
|
26
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Button } from '@/vdb/components/ui/button.js';
|
|
2
|
+
import { cn } from '@/vdb/lib/utils.js';
|
|
3
|
+
import { CodeXmlIcon } from 'lucide-react';
|
|
4
|
+
import { forwardRef } from 'react';
|
|
5
|
+
|
|
6
|
+
export const DevModeButton = forwardRef<HTMLButtonElement, React.ComponentProps<typeof Button>>(
|
|
7
|
+
(props, ref) => {
|
|
8
|
+
const { className, ...rest } = props;
|
|
9
|
+
return (
|
|
10
|
+
<Button
|
|
11
|
+
ref={ref}
|
|
12
|
+
variant="secondary"
|
|
13
|
+
size="icon"
|
|
14
|
+
className={cn(
|
|
15
|
+
'h-8 w-8 rounded-full bg-dev-mode/20 hover:bg-dev-mode/30 border border-dev-mode/20 shadow-sm',
|
|
16
|
+
className,
|
|
17
|
+
)}
|
|
18
|
+
{...rest}
|
|
19
|
+
>
|
|
20
|
+
<CodeXmlIcon className="text-dev-mode w-4 h-4" />
|
|
21
|
+
</Button>
|
|
22
|
+
);
|
|
23
|
+
},
|
|
24
|
+
);
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { CopyableText } from '@/vdb/components/shared/copyable-text.js';
|
|
2
|
-
import { Button } from '@/vdb/components/ui/button.js';
|
|
3
2
|
import { Popover, PopoverContent, PopoverTrigger } from '@/vdb/components/ui/popover.js';
|
|
4
3
|
import { usePageBlock } from '@/vdb/hooks/use-page-block.js';
|
|
5
4
|
import { usePage } from '@/vdb/hooks/use-page.js';
|
|
6
5
|
import { useUserSettings } from '@/vdb/hooks/use-user-settings.js';
|
|
7
6
|
import { cn } from '@/vdb/lib/utils.js';
|
|
8
|
-
import { CodeXmlIcon } from 'lucide-react';
|
|
9
7
|
import React, { useEffect, useState } from 'react';
|
|
8
|
+
import { DevModeButton } from './dev-mode-button.js';
|
|
10
9
|
|
|
11
10
|
// Singleton state for hover tracking
|
|
12
11
|
let globalHoveredId: string | null = null;
|
|
@@ -74,10 +73,10 @@ export function LocationWrapper({ children, identifier }: Readonly<LocationWrapp
|
|
|
74
73
|
return (
|
|
75
74
|
<div
|
|
76
75
|
className={cn(
|
|
77
|
-
`ring-2 transition-all delay-50 relative`,
|
|
76
|
+
`ring-2 transition-all ring-offset-4 ring-offset-background delay-50 relative`,
|
|
78
77
|
isHovered || isPopoverOpen ? 'ring-dev-mode' : 'ring-transparent',
|
|
79
|
-
isPageWrapper ? 'ring-
|
|
80
|
-
identifier ? 'rounded-md' : 'rounded
|
|
78
|
+
isPageWrapper ? 'ring-offset-8' : '',
|
|
79
|
+
identifier ? 'rounded-md' : 'rounded',
|
|
81
80
|
)}
|
|
82
81
|
onMouseEnter={handleMouseEnter}
|
|
83
82
|
onMouseLeave={handleMouseLeave}
|
|
@@ -87,13 +86,7 @@ export function LocationWrapper({ children, identifier }: Readonly<LocationWrapp
|
|
|
87
86
|
>
|
|
88
87
|
<Popover open={isPopoverOpen} onOpenChange={setIsPopoverOpen}>
|
|
89
88
|
<PopoverTrigger asChild>
|
|
90
|
-
<
|
|
91
|
-
variant="secondary"
|
|
92
|
-
size="icon"
|
|
93
|
-
className="h-8 w-8 rounded-full bg-dev-mode/10 hover:bg-dev-mode/20 border border-dev-mode/20 shadow-sm"
|
|
94
|
-
>
|
|
95
|
-
<CodeXmlIcon className="text-dev-mode w-4 h-4" />
|
|
96
|
-
</Button>
|
|
89
|
+
<DevModeButton />
|
|
97
90
|
</PopoverTrigger>
|
|
98
91
|
<PopoverContent className="w-48 p-3">
|
|
99
92
|
<div className="space-y-2">
|
|
@@ -36,6 +36,10 @@ class GlobalRegistry {
|
|
|
36
36
|
const oldValue = this.get(key);
|
|
37
37
|
this.registry.set(key, updater(oldValue));
|
|
38
38
|
}
|
|
39
|
+
|
|
40
|
+
public has(key: string): boolean {
|
|
41
|
+
return this.registry.has(key);
|
|
42
|
+
}
|
|
39
43
|
}
|
|
40
44
|
|
|
41
45
|
export type GlobalRegistryKey = keyof GlobalRegistryContents;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
BulkAction,
|
|
3
3
|
DashboardActionBarItem,
|
|
4
|
+
DashboardLoginExtensions,
|
|
4
5
|
DashboardPageBlockDefinition,
|
|
5
6
|
DashboardWidgetDefinition,
|
|
6
7
|
} from '@/vdb/framework/extension-api/types/index.js';
|
|
@@ -26,4 +27,5 @@ export interface GlobalRegistryContents {
|
|
|
26
27
|
bulkActionsRegistry: Map<string, BulkAction[]>;
|
|
27
28
|
listQueryDocumentRegistry: Map<string, DocumentNode[]>;
|
|
28
29
|
detailQueryDocumentRegistry: Map<string, DocumentNode[]>;
|
|
30
|
+
loginExtensions: DashboardLoginExtensions;
|
|
29
31
|
}
|
package/src/lib/graphql/api.ts
CHANGED
|
@@ -3,7 +3,10 @@ import { AwesomeGraphQLClient } from 'awesome-graphql-client';
|
|
|
3
3
|
import { DocumentNode, print } from 'graphql';
|
|
4
4
|
import { uiConfig } from 'virtual:vendure-ui-config';
|
|
5
5
|
|
|
6
|
-
const API_URL =
|
|
6
|
+
const API_URL =
|
|
7
|
+
uiConfig.api.host +
|
|
8
|
+
(uiConfig.api.port !== 'auto' ? `:${uiConfig.api.port}` : '') +
|
|
9
|
+
`/${uiConfig.api.adminApiPath}`;
|
|
7
10
|
|
|
8
11
|
export type Variables = object;
|
|
9
12
|
export type RequestDocument = string | DocumentNode;
|
|
@@ -16,10 +19,29 @@ const awesomeClient = new AwesomeGraphQLClient({
|
|
|
16
19
|
const headers = new Headers(options.headers);
|
|
17
20
|
|
|
18
21
|
if (channelToken) {
|
|
19
|
-
headers.set(
|
|
22
|
+
headers.set(uiConfig.api.channelTokenKey, channelToken);
|
|
20
23
|
}
|
|
21
24
|
|
|
22
|
-
|
|
25
|
+
// Get the content language from user settings and add as query parameter
|
|
26
|
+
let finalUrl = url;
|
|
27
|
+
try {
|
|
28
|
+
const userSettings = localStorage.getItem('vendure-user-settings');
|
|
29
|
+
if (userSettings) {
|
|
30
|
+
const settings = JSON.parse(userSettings);
|
|
31
|
+
const contentLanguage = settings.contentLanguage;
|
|
32
|
+
|
|
33
|
+
if (contentLanguage) {
|
|
34
|
+
const urlObj = new URL(finalUrl);
|
|
35
|
+
urlObj.searchParams.set('languageCode', contentLanguage);
|
|
36
|
+
finalUrl = urlObj.toString();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
} catch (error) {
|
|
40
|
+
// eslint-disable-next-line no-console
|
|
41
|
+
console.warn('Failed to read content language from user settings:', error);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return fetch(finalUrl, {
|
|
23
45
|
...options,
|
|
24
46
|
headers,
|
|
25
47
|
credentials: 'include',
|