Forráskód Böngészése

Merge branch 'master' into minor

David Höck 2 hónapja
szülő
commit
3df453bcee

+ 0 - 153
.github/workflows/build_test_dashboard.yml

@@ -1,153 +0,0 @@
-name: 'Build & Test Dashboard'
-
-on:
-    push:
-        branches:
-            - minor
-            - major
-            - master
-        paths:
-            - 'packages/dashboard/**'
-            - 'package.json'
-            - 'package-lock.json'
-    pull_request:
-        branches:
-            - master
-            - major
-            - minor
-        paths:
-            - 'packages/dashboard/**'
-            - 'package.json'
-            - 'package-lock.json'
-    workflow_dispatch:
-
-permissions:
-    contents: read
-    packages: write
-
-env:
-    NODE_OPTIONS: '--max_old_space_size=4096'
-
-defaults:
-    run:
-        shell: bash
-
-concurrency:
-    group: ${{ github.workflow }}-${{ github.ref }}
-    cancel-in-progress: true
-
-jobs:
-    publish_install:
-        runs-on: ${{ matrix.os }}
-        strategy:
-            matrix:
-                os: [ubuntu-latest, windows-latest]
-                node-version: [22.x, 24.x]
-            fail-fast: false
-        steps:
-            - uses: actions/checkout@v4
-            - name: Use Node.js ${{ matrix.node-version }}
-              uses: actions/setup-node@v4
-              with:
-                  node-version: ${{ matrix.node-version }}
-            - name: Install Verdaccio
-              run: |
-                  npm install -g verdaccio
-                  npm install -g wait-on
-                  tmp_registry_log=`mktemp`
-                  mkdir -p $HOME/.config/verdaccio
-                  cp -v ./.github/workflows/verdaccio/config.yaml $HOME/.config/verdaccio/config.yaml
-                  nohup verdaccio --config $HOME/.config/verdaccio/config.yaml &
-                  wait-on http://localhost:4873
-                  TOKEN_RES=$(curl -XPUT \
-                    -H "Content-type: application/json" \
-                    -d '{ "name": "test", "password": "test" }' \
-                    'http://localhost:4873/-/user/org.couchdb.user:test')
-                  TOKEN=$(echo "$TOKEN_RES" | jq -r '.token')
-                  npm set //localhost:4873/:_authToken $TOKEN
-            - name: npm install
-              run: |
-                  npm install
-              env:
-                  CI: true
-            - name: Check for banned imports
-              run: |
-                  cd $GITHUB_WORKSPACE/packages/dashboard
-                  node scripts/check-lib-imports.js
-            - name: Build & publish dashboard
-              run: |
-                  nohup verdaccio --config $HOME/.config/verdaccio/config.yaml &
-                  wait-on http://localhost:4873
-                  npx lerna run build --scope @vendure/common --scope @vendure/core
-                  cd packages/dashboard
-                  npm run build:standalone
-                  npm run build
-                  npm version prepatch --preid ci --no-git-tag-version --no-commit-hooks
-                  npm publish --no-push --yes --tag ci --registry http://localhost:4873
-            - name: Set up new Vendure app
-              run: |
-                  mkdir -p ~/install
-                  cd ~/install
-                  nohup verdaccio --config ~/.config/verdaccio/config.yaml &
-                  wait-on http://localhost:4873
-                  npx @vendure/create@latest test-app --ci --use-npm --log-level info
-            - name: Install dashboard
-              run: |
-                  nohup verdaccio --config ~/.config/verdaccio/config.yaml &
-                  wait-on http://localhost:4873
-                  cd ~/install/test-app
-                  npm install @vendure/dashboard@ci --registry=http://localhost:4873
-            - name: Copy files (Windows)
-              if: runner.os == 'Windows'
-              shell: pwsh
-              run: |
-                  cd ~/install/test-app
-                  New-Item -ItemType Directory -Force -Path src/plugins/test-plugin
-                  Copy-Item "$env:GITHUB_WORKSPACE/.github/workflows/scripts/vite.config.mts" -Destination "./vite.config.mts"
-                  Copy-Item "$env:GITHUB_WORKSPACE/.github/workflows/scripts/test-plugin/*" -Destination "src/plugins/test-plugin/" -Recurse -Force
-                  Copy-Item "$env:GITHUB_WORKSPACE/.github/workflows/scripts/setup-test-plugin.js" -Destination "./setup-test-plugin.js"
-            - name: Copy files (Unix)  
-              if: runner.os != 'Windows'
-              run: |
-                  cd ~/install/test-app
-                  mkdir -p src/plugins/test-plugin
-                  cp "$GITHUB_WORKSPACE/.github/workflows/scripts/vite.config.mts" ./vite.config.mts
-                  cp -r "$GITHUB_WORKSPACE/.github/workflows/scripts/test-plugin/." src/plugins/test-plugin/
-                  cp "$GITHUB_WORKSPACE/.github/workflows/scripts/setup-test-plugin.js" ./setup-test-plugin.js
-            - name: Run setup script
-              shell: bash
-              run: |
-                  cd ~/install/test-app
-                  node setup-test-plugin.js
-            - name: Install Playwright
-              run: |
-                  cd $GITHUB_WORKSPACE
-                  npm install playwright
-                  npx playwright install-deps
-                  npx playwright install chromium
-            - name: Start dashboard and run tests
-              run: |
-                  cd ~/install/test-app
-                  # start the dev server in the background
-                  npm run dev &
-                  DEV_PID=$!
-                  # Wait a moment for it to start
-                  sleep 5
-                  # Start the dashboard in the background
-                  npx vite --port 5173 &
-                  DASHBOARD_PID=$!
-                  # Wait a moment for it to start
-                  sleep 5
-                  # Run the dashboard tests
-                  node $GITHUB_WORKSPACE/.github/workflows/scripts/dashboard-tests.js
-                  # Clean up dashboard process
-                  kill $DASHBOARD_PID 2>/dev/null || true
-                  # Clean up dev server process
-                  kill $DEV_PID 2>/dev/null || true
-            - name: Upload dashboard test screenshots
-              if: always()
-              uses: actions/upload-artifact@v4
-              with:
-                  name: dashboard-test-screenshots-${{ matrix.os }}-${{ matrix.node-version }}
-                  path: /tmp/dashboard-test-*.png
-                  retention-days: 28

+ 59 - 0
.github/workflows/publish_and_install.yml

@@ -86,3 +86,62 @@ jobs:
                   cd $HOME/install/test-app
                   npm run dev &
                   node $GITHUB_WORKSPACE/.github/workflows/scripts/smoke-tests
+            - name: Copy files (Windows)
+              if: runner.os == 'Windows'
+              shell: pwsh
+              run: |
+                cd ~/install/test-app
+                New-Item -ItemType Directory -Force -Path src/plugins/test-plugin
+                Copy-Item "$env:GITHUB_WORKSPACE/.github/workflows/scripts/vite.config.mts" -Destination "./vite.config.mts"
+                Copy-Item "$env:GITHUB_WORKSPACE/.github/workflows/scripts/test-plugin/*" -Destination "src/plugins/test-plugin/" -Recurse -Force
+                Copy-Item "$env:GITHUB_WORKSPACE/.github/workflows/scripts/setup-test-plugin.js" -Destination "./setup-test-plugin.js"
+            - name: Copy files (Unix)
+              if: runner.os != 'Windows'
+              run: |
+                cd ~/install/test-app
+                mkdir -p src/plugins/test-plugin
+                cp "$GITHUB_WORKSPACE/.github/workflows/scripts/vite.config.mts" ./vite.config.mts
+                cp -r "$GITHUB_WORKSPACE/.github/workflows/scripts/test-plugin/." src/plugins/test-plugin/
+                cp "$GITHUB_WORKSPACE/.github/workflows/scripts/setup-test-plugin.js" ./setup-test-plugin.js
+            - name: Run setup script
+              shell: bash
+              run: |
+                cd ~/install/test-app
+                node setup-test-plugin.js
+            - name: Check SWC version
+              shell: bash
+              run: |
+                cd ~/install/test-app
+                npm ls @swc/core
+            - name: Install Playwright
+              run: |
+                cd $GITHUB_WORKSPACE
+                npm install playwright
+                npx playwright install-deps
+                npx playwright install chromium
+            - name: Start dashboard and run tests
+              run: |
+                cd ~/install/test-app
+                # start the dev server in the background
+                npm run dev &
+                DEV_PID=$!
+                # Wait a moment for it to start
+                sleep 5
+                # Start the dashboard in the background
+                npx vite --port 5173 &
+                DASHBOARD_PID=$!
+                # Wait a moment for it to start
+                sleep 5
+                # Run the dashboard tests
+                node $GITHUB_WORKSPACE/.github/workflows/scripts/dashboard-tests.js
+                # Clean up dashboard process
+                kill $DASHBOARD_PID 2>/dev/null || true
+                # Clean up dev server process
+                kill $DEV_PID 2>/dev/null || true
+            - name: Upload dashboard test screenshots
+              if: always()
+              uses: actions/upload-artifact@v4
+              with:
+                name: dashboard-test-screenshots-${{ matrix.os }}-${{ matrix.node-version }}
+                path: /tmp/dashboard-test-*.png
+                retention-days: 28

+ 3 - 2
docs/docs/reference/dashboard/list-views/bulk-actions.md

@@ -71,14 +71,15 @@ interface DataTableBulkActionItemProps {
 
 ## DataTableBulkActionItem
 
-<GenerationInfo sourceFile="packages/dashboard/src/lib/components/data-table/data-table-bulk-action-item.tsx" sourceLine="66" packageName="@vendure/dashboard" since="3.4.0" />
+<GenerationInfo sourceFile="packages/dashboard/src/lib/components/data-table/data-table-bulk-action-item.tsx" sourceLine="67" packageName="@vendure/dashboard" since="3.4.0" />
 
 A component that should be used to implement any bulk actions for list pages & data tables.
 
 *Example*
 
 ```tsx
-import { DataTableBulkActionItem, Trans } from '@vendure/dashboard';
+import { Trans } from '@lingui/react/macro';
+import { DataTableBulkActionItem, BulkActionComponent } from '@vendure/dashboard';
 import { Check } from 'lucide-react';
 
 export const MyBulkAction: BulkActionComponent<any> = ({ selection, table }) => {

+ 1 - 1
package-lock.json

@@ -5097,7 +5097,6 @@
     },
     "node_modules/@clack/prompts/node_modules/is-unicode-supported": {
       "version": "1.3.0",
-      "extraneous": true,
       "inBundle": true,
       "license": "MIT",
       "engines": {
@@ -52133,6 +52132,7 @@
         "@radix-ui/react-toggle": "^1.1.9",
         "@radix-ui/react-toggle-group": "^1.1.10",
         "@radix-ui/react-tooltip": "^1.2.7",
+        "@swc/core": "^1.13.5",
         "@tailwindcss/vite": "^4.1.5",
         "@tanstack/eslint-plugin-query": "^5.66.1",
         "@tanstack/react-query": "^5.66.7",

+ 1 - 0
packages/dashboard/package.json

@@ -91,6 +91,7 @@
         "@radix-ui/react-toggle": "^1.1.9",
         "@radix-ui/react-toggle-group": "^1.1.10",
         "@radix-ui/react-tooltip": "^1.2.7",
+        "@swc/core": "1.13.5",
         "@tailwindcss/vite": "^4.1.5",
         "@tanstack/eslint-plugin-query": "^5.66.1",
         "@tanstack/react-query": "^5.66.7",

+ 3 - 0
packages/dashboard/src/app/routes/_authenticated/_customers/components/customer-address-form.tsx

@@ -1,3 +1,4 @@
+import { CustomFieldsForm } from '@/vdb/components/shared/custom-fields-form.js';
 import { Button } from '@/vdb/components/ui/button.js';
 import { Checkbox } from '@/vdb/components/ui/checkbox.js';
 import {
@@ -284,6 +285,8 @@ export function CustomerAddressForm({ address, onSubmit, onCancel }: Readonly<Cu
                     />
                 </div>
 
+                {/* Custom Fields */}
+                <CustomFieldsForm entityType="Address" control={form.control} />
                 {/* Default Address Checkboxes */}
                 <div className="grid grid-cols-1 md:grid-cols-2 gap-4 pt-2">
                     <FormField

+ 1 - 1
packages/dashboard/src/lib/components/data-input/default-relation-input.tsx

@@ -611,7 +611,7 @@ export function DefaultRelationInput({
                 onBlur={onBlur}
                 name={name}
                 ref={ref}
-                value={value ?? ''}
+                value={value}
                 onChange={onChange}
                 config={config}
                 disabled={disabled}

+ 18 - 21
packages/dashboard/src/lib/components/data-input/product-multi-selector-input.tsx

@@ -93,13 +93,13 @@ function EmptyState() {
 }
 
 function ProductList({
-                         items,
-                         mode,
-                         selectedIds,
-                         getItemId,
-                         getItemName,
-                         toggleSelection,
-                     }: Readonly<{
+    items,
+    mode,
+    selectedIds,
+    getItemId,
+    getItemName,
+    toggleSelection,
+}: Readonly<{
     items: SearchItem[];
     mode: 'product' | 'variant';
     selectedIds: Set<string>;
@@ -163,12 +163,12 @@ function ProductList({
 }
 
 function ProductMultiSelectorDialog({
-                                        mode,
-                                        initialSelectionIds = [],
-                                        onSelectionChange,
-                                        open,
-                                        onOpenChange,
-                                    }: Readonly<ProductMultiSelectorProps>) {
+    mode,
+    initialSelectionIds = [],
+    onSelectionChange,
+    open,
+    onOpenChange,
+}: Readonly<ProductMultiSelectorProps>) {
     const [searchTerm, setSearchTerm] = useState('');
     const [selectedItems, setSelectedItems] = useState<SearchItem[]>([]);
     const [selectedIds, setSelectedIds] = useState<Set<string>>(new Set());
@@ -221,7 +221,7 @@ function ProductMultiSelectorDialog({
 
             if (selectedIds.has(itemId)) {
                 newSelectedIds.delete(itemId);
-                const index = selectedItems.findIndex(selected => getItemId(selected) === itemId);
+                const index = newSelectedItems.findIndex(selected => getItemId(selected) === itemId);
                 if (index >= 0) {
                     newSelectedItems.splice(index, 1);
                 }
@@ -363,7 +363,7 @@ function ProductMultiSelectorDialog({
                     <Button variant="outline" onClick={() => onOpenChange(false)}>
                         <Trans>Cancel</Trans>
                     </Button>
-                    <Button onClick={handleSelect} disabled={selectedItems.length === 0}>
+                    <Button onClick={handleSelect}>
                         <Trans>Select {selectedItems.length} Items</Trans>
                     </Button>
                 </DialogFooter>
@@ -374,20 +374,17 @@ function ProductMultiSelectorDialog({
 
 export const ProductMultiInput: DashboardFormComponent = ({ value, onChange, ...props }) => {
     const [open, setOpen] = useState(false);
-    // Parse the configuration from the field definition
     const mode = props.fieldDef?.ui?.selectionMode === 'variant' ? 'variant' : 'product';
-    // Parse the current value (JSON array of IDs)
-    const selectedIds = value;
+    const selectedIds = value || [];
 
     const handleSelectionChange = useCallback(
         (newSelectedIds: string[]) => {
-            onChange(JSON.stringify(newSelectedIds));
+            onChange(newSelectedIds);
         },
         [onChange],
     );
     const itemType = mode === 'product' ? 'products' : 'variants';
-    const buttonText =
-        selectedIds.length > 0 ? `Selected ${selectedIds.length} ${itemType}` : `Select ${itemType}`;
+    const buttonText = selectedIds.length > 0 ? `Change selected ${itemType}` : `Select ${itemType}`;
     return (
         <>
             <div className="space-y-2">

+ 3 - 3
packages/dashboard/src/lib/components/data-input/relation-selector.tsx

@@ -10,8 +10,8 @@ import {
 import { Popover, PopoverContent, PopoverTrigger } from '@/vdb/components/ui/popover.js';
 import { getQueryName } from '@/vdb/framework/document-introspection/get-document-structure.js';
 import { api } from '@/vdb/graphql/api.js';
-import { Trans } from '@lingui/react/macro';
 import { cn } from '@/vdb/lib/utils.js';
+import { Trans } from '@lingui/react/macro';
 import { useInfiniteQuery } from '@tanstack/react-query';
 import { useDebounce } from '@uidotdev/usehooks';
 import type { DocumentNode } from 'graphql';
@@ -48,7 +48,7 @@ export interface RelationSelectorProps<T = any> {
      */
     selectorLabel?: React.ReactNode;
     value?: string | string[];
-    onChange: (value: string | string[]) => void;
+    onChange: (value: string | string[] | undefined) => void;
     disabled?: boolean;
     className?: string;
 }
@@ -344,7 +344,7 @@ export function RelationSelector<T>({
         } else {
             // Clear cache for single select
             setSelectedItemsCache([]);
-            onChange('');
+            onChange(undefined);
         }
     };
 

+ 2 - 1
packages/dashboard/src/lib/components/data-table/data-table-bulk-action-item.tsx

@@ -39,7 +39,8 @@ export interface DataTableBulkActionItemProps {
  *
  * @example
  * ```tsx
- * import { DataTableBulkActionItem, Trans } from '\@vendure/dashboard';
+ * import { Trans } from '@lingui/react/macro';
+ * import { DataTableBulkActionItem, BulkActionComponent } from '\@vendure/dashboard';
  * import { Check } from 'lucide-react';
  *
  * export const MyBulkAction: BulkActionComponent<any> = ({ selection, table }) => {

+ 3 - 0
packages/dashboard/src/lib/components/shared/customer-address-form.tsx

@@ -18,6 +18,7 @@ import {
 } from '../ui/form.js';
 import { Input } from '../ui/input.js';
 import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select.js';
+import { CustomFieldsForm } from './custom-fields-form.js';
 
 // Query document to fetch available countries
 const getAvailableCountriesDocument = graphql(`
@@ -275,6 +276,8 @@ export function CustomerAddressForm<T>({
                     />
                 </div>
 
+                {/* Custom Fields */}
+                <CustomFieldsForm entityType="Address" control={form.control} />
                 {/* Default Address Checkboxes */}
                 <div className="grid grid-cols-1 md:grid-cols-2 gap-4 pt-2">
                     <FormField

+ 0 - 0
packages/dashboard/vite/utils/config-loader.ts