@vendure/dashboard 3.2.4 → 3.3.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.
Files changed (53) hide show
  1. package/dist/plugin/utils/ast-utils.spec.js +2 -2
  2. package/dist/plugin/utils/schema-generator.js +1 -1
  3. package/dist/plugin/utils/ui-config.js +2 -3
  4. package/dist/plugin/vite-plugin-config.js +4 -6
  5. package/package.json +13 -9
  6. package/src/app/app-providers.tsx +1 -1
  7. package/src/app/routes/_authenticated/_orders/orders.graphql.ts +0 -1
  8. package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +8 -2
  9. package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +6 -0
  10. package/src/app/routes/_authenticated/_system/job-queue.tsx +7 -8
  11. package/src/app/routes/_authenticated/_system/scheduled-tasks.tsx +241 -0
  12. package/src/app/styles.css +15 -0
  13. package/src/lib/components/data-table/data-table-view-options.tsx +1 -1
  14. package/src/lib/components/data-table/data-table.tsx +32 -26
  15. package/src/lib/components/data-table/refresh-button.tsx +25 -0
  16. package/src/lib/components/layout/nav-user.tsx +16 -11
  17. package/src/lib/components/layout/prerelease-popup.tsx +1 -5
  18. package/src/lib/components/shared/alerts.tsx +19 -1
  19. package/src/lib/components/shared/error-page.tsx +2 -2
  20. package/src/lib/components/shared/navigation-confirmation.tsx +20 -10
  21. package/src/lib/components/shared/paginated-list-data-table.tsx +1 -0
  22. package/src/lib/framework/alert/alert-extensions.tsx +31 -0
  23. package/src/lib/framework/alert/alert-item.tsx +47 -0
  24. package/src/lib/framework/alert/alerts-indicator.tsx +23 -0
  25. package/src/lib/framework/alert/types.ts +13 -0
  26. package/src/lib/framework/dashboard-widget/base-widget.tsx +1 -0
  27. package/src/lib/framework/defaults.ts +34 -0
  28. package/src/lib/framework/document-introspection/get-document-structure.ts +1 -2
  29. package/src/lib/framework/extension-api/define-dashboard-extension.ts +15 -5
  30. package/src/lib/framework/extension-api/extension-api-types.ts +81 -12
  31. package/src/lib/framework/layout-engine/layout-extensions.ts +3 -3
  32. package/src/lib/framework/layout-engine/page-layout.tsx +192 -35
  33. package/src/lib/framework/layout-engine/page-provider.tsx +10 -0
  34. package/src/lib/framework/page/detail-page.tsx +62 -9
  35. package/src/lib/framework/page/list-page.tsx +19 -0
  36. package/src/lib/framework/page/page-api.ts +1 -1
  37. package/src/lib/framework/page/use-detail-page.ts +81 -0
  38. package/src/lib/framework/registry/registry-types.ts +6 -2
  39. package/src/lib/graphql/graphql-env.d.ts +25 -9
  40. package/src/lib/hooks/use-auth.tsx +13 -1
  41. package/src/lib/hooks/use-channel.ts +13 -0
  42. package/src/lib/hooks/use-local-format.ts +28 -1
  43. package/src/lib/hooks/use-page.tsx +2 -3
  44. package/src/lib/hooks/use-permissions.ts +13 -0
  45. package/src/lib/index.ts +3 -4
  46. package/src/lib/providers/auth.tsx +11 -1
  47. package/src/lib/providers/channel-provider.tsx +8 -1
  48. package/vite/utils/ast-utils.spec.ts +2 -2
  49. package/vite/utils/schema-generator.ts +4 -5
  50. package/vite/utils/ui-config.ts +7 -3
  51. package/vite/vite-plugin-admin-api-schema.ts +0 -10
  52. package/vite/vite-plugin-config.ts +1 -0
  53. package/src/lib/components/ui/avatar.tsx +0 -38
@@ -1,7 +1,19 @@
1
1
  import * as React from 'react';
2
2
  import { AuthContext } from '../providers/auth.js';
3
3
 
4
-
4
+ /**
5
+ * @description
6
+ * **Status: Developer Preview**
7
+ *
8
+ * Provides access to the {@link ChannelContext} which contains information
9
+ * about the active channel.
10
+ *
11
+ *
12
+ * @docsCategory hooks
13
+ * @docsPage useAuth
14
+ * @docsWeight 0
15
+ * @since 3.3.0
16
+ */
5
17
  export function useAuth() {
6
18
  const context = React.useContext(AuthContext);
7
19
  if (!context) {
@@ -3,6 +3,19 @@ import * as React from 'react';
3
3
 
4
4
  // Hook to use the channel context
5
5
 
6
+ /**
7
+ * @description
8
+ * **Status: Developer Preview**
9
+ *
10
+ * Provides access to the {@link ChannelContext} which contains information
11
+ * about the active channel.
12
+ *
13
+ *
14
+ * @docsCategory hooks
15
+ * @docsPage useChannel
16
+ * @docsWeight 0
17
+ * @since 3.3.0
18
+ */
6
19
  export function useChannel() {
7
20
  const context = React.useContext(ChannelContext);
8
21
  if (context === undefined) {
@@ -1,4 +1,3 @@
1
- import { useLingui } from '@lingui/react';
2
1
  import { useCallback, useMemo } from 'react';
3
2
 
4
3
  import { useServerConfig } from './use-server-config.js';
@@ -19,6 +18,10 @@ import { useServerConfig } from './use-server-config.js';
19
18
  * toMajorUnits,
20
19
  * } = useLocalFormat();
21
20
  * ```
21
+ *
22
+ * @docsCategory hooks
23
+ * @docsPage useLocalFormat
24
+ * @docsWeight 0
22
25
  */
23
26
  export function useLocalFormat() {
24
27
  const { moneyStrategyPrecision } = useServerConfig() ?? { moneyStrategyPrecision: 2 };
@@ -65,6 +68,29 @@ export function useLocalFormat() {
65
68
  [locale],
66
69
  );
67
70
 
71
+ const formatRelativeDate = useCallback(
72
+ (value: string | Date, options?: Intl.RelativeTimeFormatOptions) => {
73
+ const now = new Date();
74
+ const date = new Date(value);
75
+ const diffSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
76
+ // if less than 1 minute, use seconds. Else use minutes, hours, days, months, years
77
+ if (diffSeconds < 60) {
78
+ return new Intl.RelativeTimeFormat(locale, options).format(diffSeconds * -1, 'seconds');
79
+ } else if (diffSeconds < 3600) {
80
+ return new Intl.RelativeTimeFormat(locale, options).format(diffSeconds * -1, 'minutes');
81
+ } else if (diffSeconds < 86400) {
82
+ return new Intl.RelativeTimeFormat(locale, options).format(diffSeconds * -1, 'hours');
83
+ } else if (diffSeconds < 2592000) {
84
+ return new Intl.RelativeTimeFormat(locale, options).format(diffSeconds * -1, 'days');
85
+ } else if (diffSeconds < 31536000) {
86
+ return new Intl.RelativeTimeFormat(locale, options).format(diffSeconds * -1, 'months');
87
+ } else {
88
+ return new Intl.RelativeTimeFormat(locale, options).format(diffSeconds * -1, 'years');
89
+ }
90
+ },
91
+ [locale],
92
+ );
93
+
68
94
  const formatLanguageName = useCallback(
69
95
  (value: string): string => {
70
96
  try {
@@ -111,6 +137,7 @@ export function useLocalFormat() {
111
137
  formatCurrency,
112
138
  formatNumber,
113
139
  formatDate,
140
+ formatRelativeDate,
114
141
  formatLanguageName,
115
142
  formatCurrencyName,
116
143
  toMajorUnits,
@@ -1,11 +1,10 @@
1
- import { PageProvider } from "@/framework/layout-engine/page-layout.js";
2
1
  import { useContext } from "react";
2
+ import { PageContext } from '@/framework/layout-engine/page-provider.js';
3
3
 
4
4
  export function usePage() {
5
- const page = useContext(PageProvider);
5
+ const page = useContext(PageContext);
6
6
  if (!page) {
7
7
  throw new Error('PageProvider not found');
8
8
  }
9
9
  return page;
10
10
  }
11
-
@@ -3,6 +3,19 @@ import { Permission } from '@vendure/common/lib/generated-types';
3
3
 
4
4
  import { useUserSettings } from './use-user-settings.js';
5
5
 
6
+ /**
7
+ * @description
8
+ * **Status: Developer Preview**
9
+ *
10
+ * Returns a `hasPermissions` function that can be used to determine whether the active user
11
+ * has the given permissions on the active channel.
12
+ *
13
+ *
14
+ * @docsCategory hooks
15
+ * @docsPage usePermissions
16
+ * @docsWeight 0
17
+ * @since 3.3.0
18
+ */
6
19
  export function usePermissions() {
7
20
  const { channels } = useAuth();
8
21
  const { settings } = useUserSettings();
package/src/lib/index.ts CHANGED
@@ -32,6 +32,7 @@ export * from './components/shared/asset/asset-gallery.js';
32
32
  export * from './components/shared/asset/asset-picker-dialog.js';
33
33
  export * from './components/shared/asset/asset-preview-dialog.js';
34
34
  export * from './components/shared/asset/asset-preview.js';
35
+ export * from './components/shared/asset/focal-point-control.js';
35
36
  export * from './components/shared/assigned-facet-values.js';
36
37
  export * from './components/shared/channel-code-label.js';
37
38
  export * from './components/shared/channel-selector.js';
@@ -50,7 +51,6 @@ export * from './components/shared/entity-assets.js';
50
51
  export * from './components/shared/error-page.js';
51
52
  export * from './components/shared/facet-value-chip.js';
52
53
  export * from './components/shared/facet-value-selector.js';
53
- export * from './components/shared/asset/focal-point-control.js';
54
54
  export * from './components/shared/form-field-wrapper.js';
55
55
  export * from './components/shared/history-timeline/history-entry.js';
56
56
  export * from './components/shared/history-timeline/history-note-checkbox.js';
@@ -74,7 +74,6 @@ export * from './components/shared/zone-selector.js';
74
74
  export * from './components/ui/accordion.js';
75
75
  export * from './components/ui/alert-dialog.js';
76
76
  export * from './components/ui/alert.js';
77
- export * from './components/ui/avatar.js';
78
77
  export * from './components/ui/badge.js';
79
78
  export * from './components/ui/breadcrumb.js';
80
79
  export * from './components/ui/button.js';
@@ -113,8 +112,8 @@ export * from './framework/dashboard-widget/metrics-widget/index.js';
113
112
  export * from './framework/dashboard-widget/metrics-widget/metrics-widget.graphql.js';
114
113
  export * from './framework/dashboard-widget/orders-summary/index.js';
115
114
  export * from './framework/dashboard-widget/orders-summary/order-summary-widget.graphql.js';
116
- export * from './framework/dashboard-widget/widget-extensions.js';
117
115
  export * from './framework/dashboard-widget/types.js';
116
+ export * from './framework/dashboard-widget/widget-extensions.js';
118
117
  export * from './framework/defaults.js';
119
118
  export * from './framework/document-introspection/add-custom-fields.js';
120
119
  export * from './framework/document-introspection/get-document-structure.js';
@@ -124,9 +123,9 @@ export * from './framework/extension-api/extension-api-types.js';
124
123
  export * from './framework/extension-api/use-dashboard-extensions.js';
125
124
  export * from './framework/form-engine/form-schema-tools.js';
126
125
  export * from './framework/form-engine/use-generated-form.js';
126
+ export * from './framework/layout-engine/layout-extensions.js';
127
127
  export * from './framework/layout-engine/location-wrapper.js';
128
128
  export * from './framework/layout-engine/page-layout.js';
129
- export * from './framework/layout-engine/layout-extensions.js';
130
129
  export * from './framework/nav-menu/nav-menu-extensions.js';
131
130
  export * from './framework/page/detail-page-route-loader.js';
132
131
  export * from './framework/page/detail-page.js';
@@ -3,7 +3,17 @@ import { ResultOf, graphql } from '@/graphql/graphql.js';
3
3
  import { useUserSettings } from '@/hooks/use-user-settings.js';
4
4
  import { useMutation, useQuery } from '@tanstack/react-query';
5
5
  import * as React from 'react';
6
-
6
+ import { useAuth } from '@/hooks/use-auth.js';
7
+
8
+ /**
9
+ * @description
10
+ * **Status: Developer Preview**
11
+ *
12
+ * @docsCategory hooks
13
+ * @docsPage useAuth
14
+ * @docsWeight 0
15
+ * @since 3.3.0
16
+ */
7
17
  export interface AuthContext {
8
18
  status: 'authenticated' | 'verifying' | 'unauthenticated';
9
19
  authenticationError?: string;
@@ -41,7 +41,14 @@ const ChannelsQuery = graphql(
41
41
  type ActiveChannel = ResultOf<typeof ChannelsQuery>['activeChannel'];
42
42
  type Channel = ResultOf<typeof channelFragment>;
43
43
 
44
- // Define the context interface
44
+ /**
45
+ * @description
46
+ * **Status: Developer Preview**
47
+ *
48
+ * @docsCategory hooks
49
+ * @docsPage useChannel
50
+ * @since 3.3.0
51
+ */
45
52
  export interface ChannelContext {
46
53
  activeChannel: ActiveChannel | undefined;
47
54
  channels: Channel[];
@@ -1,7 +1,7 @@
1
1
  import ts from 'typescript';
2
- import { describe, it, expect } from 'vitest';
2
+ import { describe, expect, it } from 'vitest';
3
3
 
4
- import { getPluginInfo, findConfigExport } from './ast-utils.js';
4
+ import { findConfigExport, getPluginInfo } from './ast-utils.js';
5
5
 
6
6
  describe('getPluginInfo', () => {
7
7
  it('should return undefined when no plugin class is found', () => {
@@ -1,15 +1,14 @@
1
1
  import { GraphQLTypesLoader } from '@nestjs/graphql';
2
2
  import {
3
- resetConfig,
4
- setConfig,
5
3
  getConfig,
6
- runPluginConfigurations,
7
4
  getFinalVendureSchema,
5
+ resetConfig,
6
+ runPluginConfigurations,
7
+ setConfig,
8
8
  VENDURE_ADMIN_API_TYPE_PATHS,
9
9
  VendureConfig,
10
10
  } from '@vendure/core';
11
- import { buildSchema } from 'graphql';
12
- import { GraphQLSchema } from 'graphql';
11
+ import { buildSchema, GraphQLSchema } from 'graphql';
13
12
 
14
13
  let schemaPromise: Promise<GraphQLSchema> | undefined;
15
14
 
@@ -1,13 +1,17 @@
1
1
  import {
2
+ ADMIN_API_PATH,
2
3
  DEFAULT_AUTH_TOKEN_HEADER_KEY,
3
4
  DEFAULT_CHANNEL_TOKEN_KEY,
4
- ADMIN_API_PATH,
5
5
  } from '@vendure/common/lib/shared-constants';
6
6
  import { AdminUiConfig } from '@vendure/common/lib/shared-types';
7
7
  import { VendureConfig } from '@vendure/core';
8
8
 
9
- import { defaultAvailableLocales } from '../constants.js';
10
- import { defaultLocale, defaultLanguage, defaultAvailableLanguages } from '../constants.js';
9
+ import {
10
+ defaultAvailableLanguages,
11
+ defaultAvailableLocales,
12
+ defaultLanguage,
13
+ defaultLocale,
14
+ } from '../constants.js';
11
15
 
12
16
  export function getAdminUiConfig(
13
17
  config: VendureConfig,
@@ -1,14 +1,4 @@
1
- import { GraphQLTypesLoader } from '@nestjs/graphql';
2
1
  import {
3
- getConfig,
4
- getFinalVendureSchema,
5
- resetConfig,
6
- runPluginConfigurations,
7
- setConfig,
8
- VENDURE_ADMIN_API_TYPE_PATHS,
9
- } from '@vendure/core';
10
- import {
11
- buildSchema,
12
2
  GraphQLList,
13
3
  GraphQLNonNull,
14
4
  GraphQLObjectType,
@@ -8,6 +8,7 @@ export function viteConfigPlugin({ packageRoot }: { packageRoot: string }): Plug
8
8
  config.root = packageRoot;
9
9
  config.resolve = {
10
10
  alias: {
11
+ ...(config.resolve?.alias ?? {}),
11
12
  '@': path.resolve(packageRoot, './src/lib'),
12
13
  },
13
14
  };
@@ -1,38 +0,0 @@
1
- 'use client';
2
-
3
- import * as React from 'react';
4
- import * as AvatarPrimitive from '@radix-ui/react-avatar';
5
-
6
- import { cn } from '@/lib/utils.js';
7
-
8
- function Avatar({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Root>) {
9
- return (
10
- <AvatarPrimitive.Root
11
- data-slot="avatar"
12
- className={cn('relative flex size-8 shrink-0 overflow-hidden rounded-full', className)}
13
- {...props}
14
- />
15
- );
16
- }
17
-
18
- function AvatarImage({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
19
- return (
20
- <AvatarPrimitive.Image
21
- data-slot="avatar-image"
22
- className={cn('aspect-square size-full', className)}
23
- {...props}
24
- />
25
- );
26
- }
27
-
28
- function AvatarFallback({ className, ...props }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
29
- return (
30
- <AvatarPrimitive.Fallback
31
- data-slot="avatar-fallback"
32
- className={cn('bg-muted flex size-full items-center justify-center rounded-full', className)}
33
- {...props}
34
- />
35
- );
36
- }
37
-
38
- export { Avatar, AvatarImage, AvatarFallback };