Browse Source

fix(dashboard): Fix relation selector null/undefined handling (#3942)

David Höck 2 months ago
parent
commit
715b905bea

+ 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);
         }
     };