@wilshop/dashboard 3.5.6 → 3.5.7
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/plugin/dashboard.plugin.d.ts +1 -1
- package/dist/plugin/dashboard.plugin.js +1 -1
- package/dist/vite/utils/compiler.js +50 -24
- package/dist/vite/utils/path-transformer.d.ts +20 -0
- package/dist/vite/utils/path-transformer.js +116 -0
- package/dist/vite/utils/plugin-discovery.js +3 -2
- package/dist/vite/utils/ui-config.js +15 -1
- package/dist/vite/vite-plugin-lingui-babel.d.ts +15 -2
- package/dist/vite/vite-plugin-lingui-babel.js +90 -8
- package/dist/vite/vite-plugin-translations.js +2 -2
- package/dist/vite/vite-plugin-ui-config.d.ts +31 -0
- package/package.json +10 -6
- package/src/app/common/delete-bulk-action.tsx +1 -1
- package/src/app/common/duplicate-bulk-action.tsx +1 -1
- package/src/app/routes/_authenticated/_collections/collections.graphql.ts +1 -3
- package/src/app/routes/_authenticated/_collections/collections.tsx +169 -48
- package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +36 -5
- package/src/app/routes/_authenticated/_collections/components/collection-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_collections/components/collection-filters-selector.tsx +7 -1
- package/src/app/routes/_authenticated/_customers/components/customer-history/default-customer-history-components.tsx +31 -29
- package/src/app/routes/_authenticated/_customers/customers.graphql.ts +1 -0
- package/src/app/routes/_authenticated/_customers/customers.tsx +3 -0
- package/src/app/routes/_authenticated/_global-settings/global-settings.tsx +1 -1
- package/src/app/routes/_authenticated/_orders/components/draft-order-status.tsx +48 -0
- package/src/app/routes/_authenticated/_orders/components/fulfill-order-dialog.tsx +8 -5
- package/src/app/routes/_authenticated/_orders/components/order-detail-shared.tsx +79 -54
- package/src/app/routes/_authenticated/_orders/components/order-history/default-order-history-components.tsx +43 -3
- package/src/app/routes/_authenticated/_orders/components/order-history/order-history-utils.tsx +19 -3
- package/src/app/routes/_authenticated/_orders/components/order-table.tsx +1 -0
- package/src/app/routes/_authenticated/_orders/components/refund-order-dialog.tsx +372 -0
- package/src/app/routes/_authenticated/_orders/hooks/use-refund-order.ts +345 -0
- package/src/app/routes/_authenticated/_orders/orders.graphql.ts +41 -0
- package/src/app/routes/_authenticated/_orders/orders_.draft.$id.tsx +22 -6
- package/src/app/routes/_authenticated/_orders/utils/order-utils.ts +51 -0
- package/src/app/routes/_authenticated/_orders/utils/refund-utils.ts +100 -0
- package/src/app/routes/_authenticated/_orders/utils/use-modify-order.ts +1 -1
- package/src/app/routes/_authenticated/_payment-methods/components/payment-eligibility-checker-selector.tsx +4 -1
- package/src/app/routes/_authenticated/_payment-methods/components/payment-handler-selector.tsx +7 -1
- package/src/app/routes/_authenticated/_payment-methods/payment-methods_.$id.tsx +18 -2
- package/src/app/routes/_authenticated/_product-variants/components/product-variant-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_product-variants/components/variant-price-detail.tsx +6 -2
- package/src/app/routes/_authenticated/_product-variants/product-variants.graphql.ts +9 -3
- package/src/app/routes/_authenticated/_product-variants/product-variants_.$id.tsx +49 -30
- package/src/app/routes/_authenticated/_products/components/product-bulk-actions.tsx +1 -1
- package/src/app/routes/_authenticated/_profile/profile.graphql.ts +7 -0
- package/src/app/routes/_authenticated/_profile/profile.tsx +25 -1
- package/src/app/routes/_authenticated/_promotions/components/promotion-actions-selector.tsx +7 -1
- package/src/app/routes/_authenticated/_promotions/components/promotion-conditions-selector.tsx +7 -1
- package/src/app/routes/_authenticated/_promotions/promotions_.$id.tsx +18 -2
- package/src/app/routes/_authenticated/_shipping-methods/components/shipping-calculator-selector.tsx +7 -1
- package/src/app/routes/_authenticated/_shipping-methods/components/shipping-eligibility-checker-selector.tsx +4 -1
- package/src/app/routes/_authenticated/_shipping-methods/shipping-methods_.$id.tsx +14 -2
- package/src/i18n/common-strings.ts +7 -0
- package/src/i18n/locales/ar.po +669 -399
- package/src/i18n/locales/bg.po +1889 -46
- package/src/i18n/locales/cs.po +676 -406
- package/src/i18n/locales/de.po +676 -406
- package/src/i18n/locales/en.po +669 -399
- package/src/i18n/locales/es.po +676 -406
- package/src/i18n/locales/fa.po +676 -406
- package/src/i18n/locales/fr.po +676 -406
- package/src/i18n/locales/he.po +676 -406
- package/src/i18n/locales/hr.po +676 -406
- package/src/i18n/locales/it.po +676 -406
- package/src/i18n/locales/ja.po +676 -406
- package/src/i18n/locales/nb.po +676 -406
- package/src/i18n/locales/ne.po +676 -406
- package/src/i18n/locales/pl.po +676 -406
- package/src/i18n/locales/pt_BR.po +676 -406
- package/src/i18n/locales/pt_PT.po +676 -406
- package/src/i18n/locales/ru.po +676 -406
- package/src/i18n/locales/sv.po +676 -406
- package/src/i18n/locales/tr.po +676 -406
- package/src/i18n/locales/uk.po +676 -406
- package/src/i18n/locales/zh_Hans.po +676 -406
- package/src/i18n/locales/zh_Hant.po +676 -406
- package/src/lib/components/data-input/facet-value-input.tsx +2 -2
- package/src/lib/components/data-input/index.ts +1 -0
- package/src/lib/components/data-input/select-with-options.tsx +23 -7
- package/src/lib/components/data-input/struct-form-input.tsx +53 -21
- package/src/lib/components/data-input/text-input.tsx +1 -1
- package/src/lib/components/data-table/data-table-bulk-actions.tsx +2 -1
- package/src/lib/components/data-table/data-table-context.tsx +2 -10
- package/src/lib/components/data-table/data-table-utils.ts +34 -12
- package/src/lib/components/data-table/data-table.tsx +68 -30
- package/src/lib/components/data-table/global-views-bar.tsx +1 -1
- package/src/lib/components/data-table/my-views-button.tsx +1 -1
- package/src/lib/components/data-table/save-view-button.tsx +1 -1
- package/src/lib/components/data-table/use-generated-columns.tsx +9 -2
- package/src/lib/components/data-table/views-sheet.tsx +1 -1
- package/src/lib/components/layout/channel-switcher.tsx +16 -17
- package/src/lib/components/layout/manage-languages-dialog.tsx +1 -1
- package/src/lib/components/shared/assign-to-channel-bulk-action.tsx +1 -1
- package/src/lib/components/shared/configurable-operation-input.tsx +23 -0
- package/src/lib/components/shared/configurable-operation-multi-selector.tsx +45 -0
- package/src/lib/components/shared/configurable-operation-selector.tsx +5 -0
- package/src/lib/components/shared/paginated-list-context.ts +10 -0
- package/src/lib/components/shared/paginated-list-data-table.tsx +6 -32
- package/src/lib/components/shared/remove-from-channel-bulk-action.tsx +1 -1
- package/src/lib/components/ui/alert.tsx +2 -0
- package/src/lib/constants.ts +7 -319
- package/src/lib/framework/dashboard-widget/base-widget.tsx +3 -12
- package/src/lib/framework/dashboard-widget/latest-orders-widget/index.tsx +1 -1
- package/src/lib/framework/dashboard-widget/metrics-widget/chart.tsx +1 -1
- package/src/lib/framework/dashboard-widget/metrics-widget/index.tsx +1 -1
- package/src/lib/framework/dashboard-widget/orders-summary/index.tsx +1 -1
- package/src/lib/framework/dashboard-widget/widget-filters-context.tsx +2 -20
- package/src/lib/framework/extension-api/input-component-extensions.tsx +4 -0
- package/src/lib/framework/form-engine/custom-form-component.tsx +13 -3
- package/src/lib/framework/form-engine/form-engine-types.ts +3 -5
- package/src/lib/framework/form-engine/form-schema-tools.ts +4 -1
- package/src/lib/framework/form-engine/use-generated-form.tsx +6 -2
- package/src/lib/framework/form-engine/utils.spec.ts +129 -2
- package/src/lib/framework/form-engine/utils.ts +36 -9
- package/src/lib/framework/form-engine/value-transformers.ts +6 -0
- package/src/lib/framework/page/detail-page-route-loader.tsx +6 -4
- package/src/lib/framework/page/detail-page.tsx +22 -37
- package/src/lib/framework/page/list-page.stories.tsx +41 -2
- package/src/lib/framework/page/list-page.tsx +8 -0
- package/src/lib/graphql/graphql-env.d.ts +33 -16
- package/src/lib/graphql/schema-enums.ts +13 -0
- package/src/lib/hooks/use-alerts-context.ts +10 -0
- package/src/lib/hooks/use-alerts.ts +1 -1
- package/src/lib/hooks/use-data-table-context.ts +11 -0
- package/src/lib/hooks/use-dynamic-translations.ts +7 -0
- package/src/lib/hooks/use-job-queue-polling.ts +160 -0
- package/src/lib/hooks/use-paginated-list.ts +28 -0
- package/src/lib/hooks/use-widget-dimensions.ts +12 -0
- package/src/lib/hooks/use-widget-filters.ts +21 -0
- package/src/lib/index.ts +12 -0
- package/src/lib/providers/alerts-provider.tsx +3 -11
- package/src/lib/virtual.d.ts +5 -0
- package/src/lib/utils/global-languages.ts +0 -268
|
@@ -42,7 +42,7 @@ export interface DashboardPluginOptions {
|
|
|
42
42
|
* ## Usage
|
|
43
43
|
*
|
|
44
44
|
* First you need to set up compilation of the Dashboard, using the Vite configuration
|
|
45
|
-
* described in the [Dashboard Getting Started Guide](/
|
|
45
|
+
* described in the [Dashboard Getting Started Guide](/extending-the-dashboard/getting-started/)
|
|
46
46
|
*
|
|
47
47
|
* ## Development vs Production
|
|
48
48
|
*
|
|
@@ -69,7 +69,7 @@ const metrics_service_js_1 = require("./service/metrics.service.js");
|
|
|
69
69
|
* ## Usage
|
|
70
70
|
*
|
|
71
71
|
* First you need to set up compilation of the Dashboard, using the Vite configuration
|
|
72
|
-
* described in the [Dashboard Getting Started Guide](/
|
|
72
|
+
* described in the [Dashboard Getting Started Guide](/extending-the-dashboard/getting-started/)
|
|
73
73
|
*
|
|
74
74
|
* ## Development vs Production
|
|
75
75
|
*
|
|
@@ -5,6 +5,7 @@ import * as ts from 'typescript';
|
|
|
5
5
|
import { pathToFileURL } from 'url';
|
|
6
6
|
import { findConfigExport } from './ast-utils.js';
|
|
7
7
|
import { noopLogger } from './logger.js';
|
|
8
|
+
import { createPathTransformer } from './path-transformer.js';
|
|
8
9
|
import { discoverPlugins } from './plugin-discovery.js';
|
|
9
10
|
import { findTsConfigPaths } from './tsconfig-utils.js';
|
|
10
11
|
const defaultPathAdapter = {
|
|
@@ -16,7 +17,7 @@ const defaultPathAdapter = {
|
|
|
16
17
|
* and in node_modules.
|
|
17
18
|
*/
|
|
18
19
|
export async function compile(options) {
|
|
19
|
-
var _a, _b, _c;
|
|
20
|
+
var _a, _b, _c, _d;
|
|
20
21
|
const { vendureConfigPath, outputPath, pathAdapter, logger = noopLogger, pluginPackageScanner } = options;
|
|
21
22
|
const getCompiledConfigPath = (_a = pathAdapter === null || pathAdapter === void 0 ? void 0 : pathAdapter.getCompiledConfigPath) !== null && _a !== void 0 ? _a : defaultPathAdapter.getCompiledConfigPath;
|
|
22
23
|
const transformTsConfigPathMappings = (_b = pathAdapter === null || pathAdapter === void 0 ? void 0 : pathAdapter.transformTsConfigPathMappings) !== null && _b !== void 0 ? _b : defaultPathAdapter.transformTsConfigPathMappings;
|
|
@@ -70,7 +71,8 @@ export async function compile(options) {
|
|
|
70
71
|
config = await import(compiledConfigFilePath).then(m => m[exportedSymbolName]);
|
|
71
72
|
}
|
|
72
73
|
catch (e) {
|
|
73
|
-
|
|
74
|
+
const errorMessage = e instanceof Error ? `${e.message}\n${(_d = e.stack) !== null && _d !== void 0 ? _d : ''}` : JSON.stringify(e, null, 2);
|
|
75
|
+
logger.error(`Error loading config: ${errorMessage}`);
|
|
74
76
|
}
|
|
75
77
|
if (!config) {
|
|
76
78
|
throw new Error(`Could not find a variable exported as VendureConfig with the name "${exportedSymbolName}".`);
|
|
@@ -84,8 +86,11 @@ export async function compile(options) {
|
|
|
84
86
|
async function compileTypeScript({ inputPath, outputPath, logger, transformTsConfigPathMappings, module, }) {
|
|
85
87
|
var _a;
|
|
86
88
|
await fs.ensureDir(outputPath);
|
|
87
|
-
// Find tsconfig paths
|
|
88
|
-
|
|
89
|
+
// Find tsconfig paths - we need BOTH original and transformed versions
|
|
90
|
+
// Original paths: Used by TypeScript for module resolution during compilation
|
|
91
|
+
// Transformed paths: Used by the path transformer for rewriting output imports
|
|
92
|
+
const originalTsConfigInfo = await findTsConfigPaths(inputPath, logger, 'compiling', ({ patterns }) => patterns);
|
|
93
|
+
const transformedTsConfigInfo = await findTsConfigPaths(inputPath, logger, 'compiling', transformTsConfigPathMappings);
|
|
89
94
|
const compilerOptions = {
|
|
90
95
|
target: ts.ScriptTarget.ES2020,
|
|
91
96
|
module: module === 'esm' ? ts.ModuleKind.ESNext : ts.ModuleKind.CommonJS,
|
|
@@ -110,30 +115,51 @@ async function compileTypeScript({ inputPath, outputPath, logger, transformTsCon
|
|
|
110
115
|
outDir: outputPath,
|
|
111
116
|
};
|
|
112
117
|
logger.debug(`Compiling ${inputPath} to ${outputPath} using TypeScript...`);
|
|
113
|
-
// Add path mappings if found
|
|
114
|
-
if (
|
|
118
|
+
// Add path mappings if found - use ORIGINAL paths for TypeScript module resolution
|
|
119
|
+
if (originalTsConfigInfo) {
|
|
115
120
|
// We need to set baseUrl and paths for TypeScript to resolve the imports
|
|
116
|
-
compilerOptions.baseUrl =
|
|
117
|
-
compilerOptions.paths =
|
|
121
|
+
compilerOptions.baseUrl = originalTsConfigInfo.baseUrl;
|
|
122
|
+
compilerOptions.paths = originalTsConfigInfo.paths;
|
|
118
123
|
// This is critical - it tells TypeScript to preserve the paths in the output
|
|
119
|
-
// compilerOptions.rootDir =
|
|
124
|
+
// compilerOptions.rootDir = originalTsConfigInfo.baseUrl;
|
|
125
|
+
}
|
|
126
|
+
logger.debug(`tsConfig original paths: ${JSON.stringify(originalTsConfigInfo === null || originalTsConfigInfo === void 0 ? void 0 : originalTsConfigInfo.paths, null, 2)}`);
|
|
127
|
+
logger.debug(`tsConfig transformed paths: ${JSON.stringify(transformedTsConfigInfo === null || transformedTsConfigInfo === void 0 ? void 0 : transformedTsConfigInfo.paths, null, 2)}`);
|
|
128
|
+
logger.debug(`tsConfig baseUrl: ${(_a = originalTsConfigInfo === null || originalTsConfigInfo === void 0 ? void 0 : originalTsConfigInfo.baseUrl) !== null && _a !== void 0 ? _a : 'UNKNOWN'}`);
|
|
129
|
+
// Build custom transformers
|
|
130
|
+
const afterTransformers = [];
|
|
131
|
+
// Add path transformer for ESM mode when there are path mappings
|
|
132
|
+
// This is necessary because tsconfig-paths.register() only works for CommonJS require(),
|
|
133
|
+
// not for ESM import(). We need to transform the import paths during compilation.
|
|
134
|
+
//
|
|
135
|
+
// IMPORTANT: We use 'after' transformers because:
|
|
136
|
+
// 1. 'before' runs before TypeScript resolves modules - changing paths there breaks resolution
|
|
137
|
+
// 2. 'after' runs after module resolution but before emit - paths are transformed in output only
|
|
138
|
+
//
|
|
139
|
+
// We use ORIGINAL (untransformed) paths here because the transformer resolves aliases
|
|
140
|
+
// relative to the source file's directory using path.relative(). Since TypeScript preserves
|
|
141
|
+
// directory nesting in output, the relative relationships between source files are the same
|
|
142
|
+
// in both the source and output trees.
|
|
143
|
+
if (module === 'esm' && originalTsConfigInfo) {
|
|
144
|
+
logger.debug('Adding path transformer for ESM mode');
|
|
145
|
+
afterTransformers.push(createPathTransformer({
|
|
146
|
+
baseUrl: originalTsConfigInfo.baseUrl,
|
|
147
|
+
paths: originalTsConfigInfo.paths,
|
|
148
|
+
}));
|
|
120
149
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
150
|
+
// Add the existing transformer for non-entry-point files
|
|
151
|
+
afterTransformers.push(context => {
|
|
152
|
+
return sourceFile => {
|
|
153
|
+
// Only transform files that are not the entry point
|
|
154
|
+
if (sourceFile.fileName === inputPath) {
|
|
155
|
+
return sourceFile;
|
|
156
|
+
}
|
|
157
|
+
sourceFile.fileName = path.join(outputPath, path.basename(sourceFile.fileName));
|
|
158
|
+
return sourceFile;
|
|
159
|
+
};
|
|
160
|
+
});
|
|
124
161
|
const customTransformers = {
|
|
125
|
-
after:
|
|
126
|
-
context => {
|
|
127
|
-
return sourceFile => {
|
|
128
|
-
// Only transform files that are not the entry point
|
|
129
|
-
if (sourceFile.fileName === inputPath) {
|
|
130
|
-
return sourceFile;
|
|
131
|
-
}
|
|
132
|
-
sourceFile.fileName = path.join(outputPath, path.basename(sourceFile.fileName));
|
|
133
|
-
return sourceFile;
|
|
134
|
-
};
|
|
135
|
-
},
|
|
136
|
-
],
|
|
162
|
+
after: afterTransformers,
|
|
137
163
|
};
|
|
138
164
|
const program = ts.createProgram([inputPath], compilerOptions);
|
|
139
165
|
const emitResult = program.emit(undefined, undefined, undefined, undefined, customTransformers);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as ts from 'typescript';
|
|
2
|
+
export interface PathTransformerOptions {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
paths: Record<string, string[]>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Creates a TypeScript custom transformer that rewrites import/export paths
|
|
8
|
+
* from tsconfig path aliases to their resolved relative paths.
|
|
9
|
+
*
|
|
10
|
+
* This is necessary for ESM mode where tsconfig-paths.register() doesn't work
|
|
11
|
+
* because it only hooks into CommonJS require(), not ESM import().
|
|
12
|
+
*
|
|
13
|
+
* The transformer uses the source file's location and the tsconfig baseUrl to
|
|
14
|
+
* compute correct relative paths, even for files in nested directories.
|
|
15
|
+
*
|
|
16
|
+
* Known limitations:
|
|
17
|
+
* - Only the first path target is used when multiple fallbacks are configured
|
|
18
|
+
* - `require()` calls via `createRequire` are not transformed
|
|
19
|
+
*/
|
|
20
|
+
export declare function createPathTransformer(options: PathTransformerOptions): ts.TransformerFactory<ts.SourceFile>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as ts from 'typescript';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a TypeScript custom transformer that rewrites import/export paths
|
|
5
|
+
* from tsconfig path aliases to their resolved relative paths.
|
|
6
|
+
*
|
|
7
|
+
* This is necessary for ESM mode where tsconfig-paths.register() doesn't work
|
|
8
|
+
* because it only hooks into CommonJS require(), not ESM import().
|
|
9
|
+
*
|
|
10
|
+
* The transformer uses the source file's location and the tsconfig baseUrl to
|
|
11
|
+
* compute correct relative paths, even for files in nested directories.
|
|
12
|
+
*
|
|
13
|
+
* Known limitations:
|
|
14
|
+
* - Only the first path target is used when multiple fallbacks are configured
|
|
15
|
+
* - `require()` calls via `createRequire` are not transformed
|
|
16
|
+
*/
|
|
17
|
+
export function createPathTransformer(options) {
|
|
18
|
+
const { baseUrl, paths } = options;
|
|
19
|
+
// Compile the path patterns into matchers
|
|
20
|
+
const pathMatchers = Object.entries(paths).map(([pattern, targets]) => {
|
|
21
|
+
const hasWildcard = pattern.includes('*');
|
|
22
|
+
// Escape special regex chars, then replace * with capture group
|
|
23
|
+
const regexStr = pattern
|
|
24
|
+
.replace(/[.+?^${}()|[\]\\]/g, String.raw `\$&`)
|
|
25
|
+
.split('*')
|
|
26
|
+
.join('(.*)');
|
|
27
|
+
const regex = new RegExp('^' + regexStr + '$');
|
|
28
|
+
return { pattern, regex, targets, hasWildcard };
|
|
29
|
+
});
|
|
30
|
+
return context => {
|
|
31
|
+
return sourceFile => {
|
|
32
|
+
const sourceDir = path.dirname(sourceFile.fileName);
|
|
33
|
+
const visitor = node => {
|
|
34
|
+
// Handle import declarations: import { X } from 'module';
|
|
35
|
+
if (ts.isImportDeclaration(node) &&
|
|
36
|
+
node.moduleSpecifier &&
|
|
37
|
+
ts.isStringLiteral(node.moduleSpecifier)) {
|
|
38
|
+
const resolvedPath = resolvePathAlias(node.moduleSpecifier.text, pathMatchers, baseUrl, sourceDir);
|
|
39
|
+
if (resolvedPath) {
|
|
40
|
+
return context.factory.updateImportDeclaration(node, node.modifiers, node.importClause, context.factory.createStringLiteral(resolvedPath), node.attributes);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Handle export declarations: export { X } from 'module';
|
|
44
|
+
if (ts.isExportDeclaration(node) &&
|
|
45
|
+
node.moduleSpecifier &&
|
|
46
|
+
ts.isStringLiteral(node.moduleSpecifier)) {
|
|
47
|
+
const resolvedPath = resolvePathAlias(node.moduleSpecifier.text, pathMatchers, baseUrl, sourceDir);
|
|
48
|
+
if (resolvedPath) {
|
|
49
|
+
return context.factory.updateExportDeclaration(node, node.modifiers, node.isTypeOnly, node.exportClause, context.factory.createStringLiteral(resolvedPath), node.attributes);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Handle dynamic imports: import('module')
|
|
53
|
+
if (ts.isCallExpression(node) &&
|
|
54
|
+
node.expression.kind === ts.SyntaxKind.ImportKeyword &&
|
|
55
|
+
node.arguments.length > 0 &&
|
|
56
|
+
ts.isStringLiteral(node.arguments[0])) {
|
|
57
|
+
const resolvedPath = resolvePathAlias(node.arguments[0].text, pathMatchers, baseUrl, sourceDir);
|
|
58
|
+
if (resolvedPath) {
|
|
59
|
+
return context.factory.updateCallExpression(node, node.expression, node.typeArguments, [context.factory.createStringLiteral(resolvedPath), ...node.arguments.slice(1)]);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return ts.visitEachChild(node, visitor, context);
|
|
63
|
+
};
|
|
64
|
+
return ts.visitNode(sourceFile, visitor);
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Resolves a path alias to its actual path, computed relative to the source file's directory.
|
|
70
|
+
* Returns undefined if the module specifier doesn't match any path alias.
|
|
71
|
+
*/
|
|
72
|
+
function resolvePathAlias(moduleSpecifier, pathMatchers, baseUrl, sourceDir) {
|
|
73
|
+
if (moduleSpecifier.startsWith('.') || moduleSpecifier.startsWith('/')) {
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
for (const { regex, targets, hasWildcard } of pathMatchers) {
|
|
77
|
+
const match = regex.exec(moduleSpecifier);
|
|
78
|
+
if (match) {
|
|
79
|
+
const target = targets[0];
|
|
80
|
+
const resolved = hasWildcard && match[1] ? target.split('*').join(match[1]) : target;
|
|
81
|
+
// Compute absolute target path from baseUrl, then get relative path from source dir
|
|
82
|
+
const absoluteTarget = path.resolve(baseUrl, resolved);
|
|
83
|
+
let relativePath = path.relative(sourceDir, absoluteTarget);
|
|
84
|
+
// Normalize path separators to forward slashes
|
|
85
|
+
relativePath = relativePath.split('\\').join('/');
|
|
86
|
+
// Ensure relative path has ./ or ../ prefix
|
|
87
|
+
if (!relativePath.startsWith('.')) {
|
|
88
|
+
relativePath = './' + relativePath;
|
|
89
|
+
}
|
|
90
|
+
// Convert TypeScript extensions to JavaScript equivalents for ESM
|
|
91
|
+
return convertExtension(relativePath);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Converts TypeScript extensions to JavaScript equivalents for ESM.
|
|
98
|
+
* .ts -> .js, .tsx -> .js, .mts -> .mjs, .cts -> .cjs
|
|
99
|
+
*/
|
|
100
|
+
function convertExtension(filePath) {
|
|
101
|
+
if (filePath.endsWith('.ts') || filePath.endsWith('.tsx')) {
|
|
102
|
+
return filePath.replace(/\.tsx?$/, '.js');
|
|
103
|
+
}
|
|
104
|
+
if (filePath.endsWith('.mts')) {
|
|
105
|
+
return filePath.replace(/\.mts$/, '.mjs');
|
|
106
|
+
}
|
|
107
|
+
if (filePath.endsWith('.cts')) {
|
|
108
|
+
return filePath.replace(/\.cts$/, '.cjs');
|
|
109
|
+
}
|
|
110
|
+
// No extension - assume directory import, add /index.js
|
|
111
|
+
if (!/\.\w+$/.test(filePath)) {
|
|
112
|
+
return `${filePath}/index.js`;
|
|
113
|
+
}
|
|
114
|
+
// Files with other extensions (.json, .js, etc.) are left as-is
|
|
115
|
+
return filePath;
|
|
116
|
+
}
|
|
@@ -323,8 +323,9 @@ export async function findVendurePluginFiles({ outputPath, vendureConfigPath, lo
|
|
|
323
323
|
const globStart = Date.now();
|
|
324
324
|
const files = await glob(patterns, {
|
|
325
325
|
ignore: [
|
|
326
|
-
//
|
|
327
|
-
|
|
326
|
+
// Skip nested node_modules (transitive deps) but not .pnpm or .bun directories.
|
|
327
|
+
// [!.] excludes paths starting with . since pnpm and bun store packages there.
|
|
328
|
+
'**/node_modules/[!.]*/**/node_modules/**',
|
|
328
329
|
'**/*.spec.js',
|
|
329
330
|
'**/*.test.js',
|
|
330
331
|
],
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ADMIN_API_PATH, DEFAULT_AUTH_TOKEN_HEADER_KEY, DEFAULT_CHANNEL_TOKEN_KEY, } from '@vendure/common/lib/shared-constants';
|
|
2
2
|
import { defaultAvailableLanguages, defaultAvailableLocales, defaultLanguage, defaultLocale, } from '../constants.js';
|
|
3
3
|
export function getUiConfig(config, pluginOptions) {
|
|
4
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
|
4
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x;
|
|
5
5
|
const { authOptions, apiOptions } = config;
|
|
6
6
|
// Merge API configuration with defaults
|
|
7
7
|
const api = {
|
|
@@ -23,8 +23,22 @@ export function getUiConfig(config, pluginOptions) {
|
|
|
23
23
|
? pluginOptions.i18n.availableLocales
|
|
24
24
|
: defaultAvailableLocales,
|
|
25
25
|
};
|
|
26
|
+
// Merge orders configuration with defaults
|
|
27
|
+
// Default labels are identifiers that get translated via getTranslatedRefundReason()
|
|
28
|
+
const orders = {
|
|
29
|
+
refundReasons: ((_x = pluginOptions.orders) === null || _x === void 0 ? void 0 : _x.refundReasons) && pluginOptions.orders.refundReasons.length > 0
|
|
30
|
+
? pluginOptions.orders.refundReasons
|
|
31
|
+
: [
|
|
32
|
+
{ value: 'customer-request', label: 'CustomerRequest' },
|
|
33
|
+
{ value: 'not-available', label: 'NotAvailable' },
|
|
34
|
+
{ value: 'damaged-shipping', label: 'DamagedInShipping' },
|
|
35
|
+
{ value: 'wrong-item', label: 'WrongItem' },
|
|
36
|
+
{ value: 'other', label: 'Other' },
|
|
37
|
+
],
|
|
38
|
+
};
|
|
26
39
|
return {
|
|
27
40
|
api,
|
|
28
41
|
i18n,
|
|
42
|
+
orders,
|
|
29
43
|
};
|
|
30
44
|
}
|
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import type { Plugin } from 'vite';
|
|
2
|
+
/**
|
|
3
|
+
* Options for the linguiBabelPlugin.
|
|
4
|
+
*/
|
|
5
|
+
export interface LinguiBabelPluginOptions {
|
|
6
|
+
/**
|
|
7
|
+
* For testing: manually specify package paths that should have Lingui macros transformed.
|
|
8
|
+
* In production, these are automatically discovered from the VendureConfig plugins.
|
|
9
|
+
*/
|
|
10
|
+
additionalPackagePaths?: string[];
|
|
11
|
+
}
|
|
2
12
|
/**
|
|
3
13
|
* @description
|
|
4
14
|
* A custom Vite plugin that transforms Lingui macros in files using Babel instead of SWC.
|
|
@@ -17,11 +27,14 @@ import type { Plugin } from 'vite';
|
|
|
17
27
|
* - `@vendure/dashboard/src` files (in node_modules for external projects)
|
|
18
28
|
* - `packages/dashboard/src` files (in monorepo development)
|
|
19
29
|
* - User's dashboard extension files (e.g., custom plugins using Lingui)
|
|
30
|
+
* - Third-party npm packages that provide dashboard extensions (discovered automatically)
|
|
20
31
|
*
|
|
21
32
|
* Files NOT processed:
|
|
22
|
-
* -
|
|
33
|
+
* - Files that don't contain Lingui macro imports (fast check via string matching)
|
|
34
|
+
* - Non-JS/TS files
|
|
35
|
+
* - node_modules packages that are not discovered as Vendure plugins
|
|
23
36
|
*
|
|
24
37
|
* @see https://github.com/vendurehq/vendure/issues/3929
|
|
25
38
|
* @see https://github.com/lingui/swc-plugin/issues/179
|
|
26
39
|
*/
|
|
27
|
-
export declare function linguiBabelPlugin(): Plugin;
|
|
40
|
+
export declare function linguiBabelPlugin(options?: LinguiBabelPluginOptions): Plugin;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as babel from '@babel/core';
|
|
2
|
+
import { getConfigLoaderApi } from './vite-plugin-config-loader.js';
|
|
2
3
|
/**
|
|
3
4
|
* @description
|
|
4
5
|
* A custom Vite plugin that transforms Lingui macros in files using Babel instead of SWC.
|
|
@@ -17,19 +18,40 @@ import * as babel from '@babel/core';
|
|
|
17
18
|
* - `@vendure/dashboard/src` files (in node_modules for external projects)
|
|
18
19
|
* - `packages/dashboard/src` files (in monorepo development)
|
|
19
20
|
* - User's dashboard extension files (e.g., custom plugins using Lingui)
|
|
21
|
+
* - Third-party npm packages that provide dashboard extensions (discovered automatically)
|
|
20
22
|
*
|
|
21
23
|
* Files NOT processed:
|
|
22
|
-
* -
|
|
24
|
+
* - Files that don't contain Lingui macro imports (fast check via string matching)
|
|
25
|
+
* - Non-JS/TS files
|
|
26
|
+
* - node_modules packages that are not discovered as Vendure plugins
|
|
23
27
|
*
|
|
24
28
|
* @see https://github.com/vendurehq/vendure/issues/3929
|
|
25
29
|
* @see https://github.com/lingui/swc-plugin/issues/179
|
|
26
30
|
*/
|
|
27
|
-
export function linguiBabelPlugin() {
|
|
31
|
+
export function linguiBabelPlugin(options) {
|
|
32
|
+
var _a;
|
|
33
|
+
// Paths of npm packages that should have Lingui macros transformed.
|
|
34
|
+
// This is populated from plugin discovery when transform is first called.
|
|
35
|
+
const allowedNodeModulesPackages = new Set((_a = options === null || options === void 0 ? void 0 : options.additionalPackagePaths) !== null && _a !== void 0 ? _a : []);
|
|
36
|
+
// API reference to the config loader plugin (set in configResolved)
|
|
37
|
+
let configLoaderApi;
|
|
38
|
+
// Cached result from config loader (set on first transform that needs it)
|
|
39
|
+
let configResult;
|
|
28
40
|
return {
|
|
29
41
|
name: 'vendure:lingui-babel',
|
|
30
42
|
// Run BEFORE @vitejs/plugin-react so the macros are already transformed
|
|
31
43
|
// when the react plugin processes the file
|
|
32
44
|
enforce: 'pre',
|
|
45
|
+
configResolved({ plugins }) {
|
|
46
|
+
// Get reference to the config loader API.
|
|
47
|
+
// This doesn't load the config yet - that happens lazily in transform.
|
|
48
|
+
try {
|
|
49
|
+
configLoaderApi = getConfigLoaderApi(plugins);
|
|
50
|
+
}
|
|
51
|
+
catch (_a) {
|
|
52
|
+
// configLoaderPlugin not available (e.g., plugin used standalone for testing)
|
|
53
|
+
}
|
|
54
|
+
},
|
|
33
55
|
async transform(code, id) {
|
|
34
56
|
// Strip query params for path matching (Vite adds ?v=xxx for cache busting)
|
|
35
57
|
const cleanId = id.split('?')[0];
|
|
@@ -42,15 +64,42 @@ export function linguiBabelPlugin() {
|
|
|
42
64
|
if (!code.includes('@lingui/') || !code.includes('/macro')) {
|
|
43
65
|
return null;
|
|
44
66
|
}
|
|
45
|
-
//
|
|
46
|
-
// This ensures:
|
|
47
|
-
// 1. Dashboard source files get transformed (both in monorepo and external projects)
|
|
48
|
-
// 2. User's extension files get transformed (not in node_modules)
|
|
49
|
-
// 3. Other node_modules packages are left alone
|
|
67
|
+
// Check if this file should be transformed
|
|
50
68
|
if (cleanId.includes('node_modules')) {
|
|
69
|
+
// Always allow @vendure/dashboard source files
|
|
51
70
|
const isVendureDashboard = cleanId.includes('@vendure/dashboard/src') || cleanId.includes('packages/dashboard/src');
|
|
52
71
|
if (!isVendureDashboard) {
|
|
53
|
-
|
|
72
|
+
// Load discovered plugins on first need (lazy loading with caching)
|
|
73
|
+
if (configLoaderApi && !configResult) {
|
|
74
|
+
try {
|
|
75
|
+
configResult = await configLoaderApi.getVendureConfig();
|
|
76
|
+
// Extract package paths from discovered npm plugins
|
|
77
|
+
for (const plugin of configResult.pluginInfo) {
|
|
78
|
+
if (!plugin.sourcePluginPath && plugin.pluginPath.includes('node_modules')) {
|
|
79
|
+
const packagePath = extractPackagePath(plugin.pluginPath);
|
|
80
|
+
if (packagePath) {
|
|
81
|
+
allowedNodeModulesPackages.add(packagePath);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
// Log but continue - will use only manually specified paths
|
|
88
|
+
// eslint-disable-next-line no-console
|
|
89
|
+
console.warn('[vendure:lingui-babel] Failed to load plugin config:', error);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
// Check if this is from a discovered Vendure plugin package
|
|
93
|
+
let isDiscoveredPlugin = false;
|
|
94
|
+
for (const pkgPath of allowedNodeModulesPackages) {
|
|
95
|
+
if (cleanId.includes(pkgPath)) {
|
|
96
|
+
isDiscoveredPlugin = true;
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
if (!isDiscoveredPlugin) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
54
103
|
}
|
|
55
104
|
}
|
|
56
105
|
try {
|
|
@@ -84,3 +133,36 @@ export function linguiBabelPlugin() {
|
|
|
84
133
|
},
|
|
85
134
|
};
|
|
86
135
|
}
|
|
136
|
+
/**
|
|
137
|
+
* Extracts the npm package name from a full file path.
|
|
138
|
+
*
|
|
139
|
+
* Examples:
|
|
140
|
+
* - /path/to/node_modules/@vendure-ee/plugin/dist/index.js -> @vendure-ee/plugin
|
|
141
|
+
* - /path/to/node_modules/some-plugin/lib/index.js -> some-plugin
|
|
142
|
+
* - /path/to/node_modules/.pnpm/@vendure-ee+plugin@1.0.0/node_modules/@vendure-ee/plugin/dist/index.js -> @vendure-ee/plugin
|
|
143
|
+
*/
|
|
144
|
+
function extractPackagePath(filePath) {
|
|
145
|
+
// Normalize path separators
|
|
146
|
+
const normalizedPath = filePath.replace(/\\/g, '/');
|
|
147
|
+
// Find the last occurrence of node_modules (handles pnpm structure)
|
|
148
|
+
const lastNodeModulesIndex = normalizedPath.lastIndexOf('node_modules/');
|
|
149
|
+
if (lastNodeModulesIndex === -1) {
|
|
150
|
+
return undefined;
|
|
151
|
+
}
|
|
152
|
+
const afterNodeModules = normalizedPath.slice(lastNodeModulesIndex + 'node_modules/'.length);
|
|
153
|
+
// Handle scoped packages (@scope/package)
|
|
154
|
+
if (afterNodeModules.startsWith('@')) {
|
|
155
|
+
const parts = afterNodeModules.split('/');
|
|
156
|
+
if (parts.length >= 2) {
|
|
157
|
+
return `${parts[0]}/${parts[1]}`;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// Unscoped package
|
|
162
|
+
const parts = afterNodeModules.split('/');
|
|
163
|
+
if (parts.length >= 1) {
|
|
164
|
+
return parts[0];
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
@@ -91,8 +91,8 @@ async function getPluginTranslations(pluginInfo) {
|
|
|
91
91
|
const poPatterns = path.join(dashboardPath, '**/*.po');
|
|
92
92
|
const translations = await glob(poPatterns, {
|
|
93
93
|
ignore: [
|
|
94
|
-
//
|
|
95
|
-
'**/node_modules
|
|
94
|
+
// Skip nested node_modules (transitive deps) but not .pnpm or .bun directories.
|
|
95
|
+
'**/node_modules/[!.]*/**/node_modules/**',
|
|
96
96
|
'**/*.spec.js',
|
|
97
97
|
'**/*.test.js',
|
|
98
98
|
],
|
|
@@ -103,6 +103,27 @@ export interface I18nConfig {
|
|
|
103
103
|
*/
|
|
104
104
|
availableLocales?: string[];
|
|
105
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* @description
|
|
108
|
+
* Options used by the {@link vendureDashboardPlugin} to configure order-related
|
|
109
|
+
* Dashboard UI behaviour.
|
|
110
|
+
*
|
|
111
|
+
* @docsCategory vite-plugin
|
|
112
|
+
* @docsPage vendureDashboardPlugin
|
|
113
|
+
* @since 3.4.0
|
|
114
|
+
*/
|
|
115
|
+
export interface OrdersConfig {
|
|
116
|
+
/**
|
|
117
|
+
* @description
|
|
118
|
+
* An array of refund reasons to display in the refund order dialog.
|
|
119
|
+
* Each reason has a `value` (used as the identifier) and a `label` (displayed to the user).
|
|
120
|
+
* If not provided, default reasons will be used.
|
|
121
|
+
*/
|
|
122
|
+
refundReasons?: Array<{
|
|
123
|
+
value: string;
|
|
124
|
+
label: string;
|
|
125
|
+
}>;
|
|
126
|
+
}
|
|
106
127
|
/**
|
|
107
128
|
* @description
|
|
108
129
|
* Options used by the {@link vendureDashboardPlugin} to configure aspects of the
|
|
@@ -123,6 +144,11 @@ export interface UiConfigPluginOptions {
|
|
|
123
144
|
* Configuration for internationalization settings
|
|
124
145
|
*/
|
|
125
146
|
i18n?: I18nConfig;
|
|
147
|
+
/**
|
|
148
|
+
* @description
|
|
149
|
+
* Configuration for order-related settings
|
|
150
|
+
*/
|
|
151
|
+
orders?: OrdersConfig;
|
|
126
152
|
}
|
|
127
153
|
/**
|
|
128
154
|
* @description
|
|
@@ -141,6 +167,11 @@ export interface ResolvedUiConfig {
|
|
|
141
167
|
* Note: defaultLocale remains optional as it can be undefined.
|
|
142
168
|
*/
|
|
143
169
|
i18n: Required<Omit<I18nConfig, 'defaultLocale'>> & Pick<I18nConfig, 'defaultLocale'>;
|
|
170
|
+
/**
|
|
171
|
+
* @description
|
|
172
|
+
* Order-related settings with all defaults applied
|
|
173
|
+
*/
|
|
174
|
+
orders: Required<OrdersConfig>;
|
|
144
175
|
}
|
|
145
176
|
/**
|
|
146
177
|
* This Vite plugin scans the configured plugins for any dashboard extensions and dynamically
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wilshop/dashboard",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "3.5.
|
|
4
|
+
"version": "3.5.7",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
7
7
|
"type": "git",
|
|
@@ -26,7 +26,10 @@
|
|
|
26
26
|
"generate-index": "node scripts/generate-index.js",
|
|
27
27
|
"i18n:extract": "lingui extract && node ./scripts/translate/i18n-tool.js extract",
|
|
28
28
|
"i18n:apply": "node ./scripts/translate/i18n-tool.js apply",
|
|
29
|
+
"i18n:check": "node ./scripts/translate/check-translations.js",
|
|
29
30
|
"storybook": "storybook dev -p 6006",
|
|
31
|
+
"e2e:pw": "playwright test --config e2e/playwright.config.ts",
|
|
32
|
+
"e2e:ui": "playwright test --config e2e/playwright.config.ts --ui",
|
|
30
33
|
"storybook:build": "storybook build",
|
|
31
34
|
"storybook:deploy": "npm run build --prefix ../common && npm run build --prefix ../core && npm run build:vite && storybook build"
|
|
32
35
|
},
|
|
@@ -99,10 +102,10 @@
|
|
|
99
102
|
"@tanstack/eslint-plugin-query": "^5.66.1",
|
|
100
103
|
"@tanstack/react-query": "^5.66.7",
|
|
101
104
|
"@tanstack/react-query-devtools": "^5.68.0",
|
|
102
|
-
"@tanstack/react-router": "^1.
|
|
105
|
+
"@tanstack/react-router": "^1.154.0",
|
|
103
106
|
"@tanstack/react-table": "^8.21.2",
|
|
104
|
-
"@tanstack/router-devtools": "^1.
|
|
105
|
-
"@tanstack/router-plugin": "^1.
|
|
107
|
+
"@tanstack/router-devtools": "^1.154.0",
|
|
108
|
+
"@tanstack/router-plugin": "^1.154.0",
|
|
106
109
|
"@tiptap/extension-floating-menu": "^3.4.4",
|
|
107
110
|
"@tiptap/extension-image": "^3.4.4",
|
|
108
111
|
"@tiptap/extension-table": "^3.4.4",
|
|
@@ -152,13 +155,14 @@
|
|
|
152
155
|
},
|
|
153
156
|
"devDependencies": {
|
|
154
157
|
"@eslint/js": "^9.19.0",
|
|
158
|
+
"@playwright/test": "^1.58.2",
|
|
155
159
|
"@storybook/addon-a11y": "^10.0.0-beta.9",
|
|
156
160
|
"@storybook/addon-docs": "^10.0.0-beta.9",
|
|
157
161
|
"@storybook/addon-vitest": "^10.0.0-beta.9",
|
|
158
162
|
"@storybook/react-vite": "^10.0.0-beta.9",
|
|
159
163
|
"@types/node": "^22.13.4",
|
|
160
|
-
"@vendure/common": "3.5.
|
|
161
|
-
"@vendure/core": "3.5.
|
|
164
|
+
"@vendure/common": "3.5.3",
|
|
165
|
+
"@vendure/core": "3.5.3",
|
|
162
166
|
"@vitest/browser": "^3.2.4",
|
|
163
167
|
"@vitest/coverage-v8": "^3.2.4",
|
|
164
168
|
"eslint": "^9.19.0",
|
|
@@ -3,7 +3,7 @@ import { TrashIcon } from 'lucide-react';
|
|
|
3
3
|
import { toast } from 'sonner';
|
|
4
4
|
|
|
5
5
|
import { DataTableBulkActionItem } from '@/vdb/components/data-table/data-table-bulk-action-item.js';
|
|
6
|
-
import { usePaginatedList } from '@/vdb/
|
|
6
|
+
import { usePaginatedList } from '@/vdb/hooks/use-paginated-list.js';
|
|
7
7
|
import { getMutationName } from '@/vdb/framework/document-introspection/get-document-structure.js';
|
|
8
8
|
import { api } from '@/vdb/graphql/api.js';
|
|
9
9
|
import { Trans, useLingui } from '@lingui/react/macro';
|
|
@@ -5,7 +5,7 @@ import { useState } from 'react';
|
|
|
5
5
|
import { toast } from 'sonner';
|
|
6
6
|
|
|
7
7
|
import { DataTableBulkActionItem } from '@/vdb/components/data-table/data-table-bulk-action-item.js';
|
|
8
|
-
import { usePaginatedList } from '@/vdb/
|
|
8
|
+
import { usePaginatedList } from '@/vdb/hooks/use-paginated-list.js';
|
|
9
9
|
import { api } from '@/vdb/graphql/api.js';
|
|
10
10
|
import { duplicateEntityDocument } from '@/vdb/graphql/common-operations.js';
|
|
11
11
|
import { Trans, useLingui } from '@lingui/react/macro';
|