From 8bf191abe0d77f7f424aa60e473be08577c7b6a5 Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Fri, 13 Dec 2024 15:55:34 +0100 Subject: [PATCH 01/19] feat(dashboard): Add UI for bulk editing inventory stock (#10556) --- .../inventory/admin/inventory.spec.ts | 69 +++++- .../components/common/thumbnail/thumbnail.tsx | 2 +- .../components/data-grid-cell-container.tsx | 2 +- .../components/data-grid-duplicate-cell.tsx | 23 ++ .../components/data-grid-readonly-cell.tsx | 22 +- .../data-grid/components/data-grid-root.tsx | 6 +- .../data-grid-toggleable-number-cell.tsx | 163 +++++++++++++ .../hooks/use-data-grid-cell-snapshot.tsx | 18 +- .../data-grid/hooks/use-data-grid-cell.tsx | 18 +- .../hooks/use-data-grid-form-handlers.tsx | 44 ++-- .../hooks/use-data-grid-keydown-event.tsx | 47 +++- .../src/components/data-grid/types.ts | 8 +- .../dashboard/src/hooks/api/inventory.tsx | 30 ++- .../dashboard/src/hooks/api/products.tsx | 9 +- .../providers/router-provider/route-map.tsx | 10 + .../src/routes/inventory/common/constants.ts | 1 + .../inventory-item-location-levels.tsx | 8 +- .../inventory-item-reservations.tsx | 6 +- .../use-location-list-table-columns.tsx | 4 +- .../components/inventory-list-table.tsx | 26 ++- .../use-inventory-table-columns.tsx | 33 ++- .../components/inventory-stock-form/index.ts | 1 + .../inventory-stock-form.tsx | 92 ++++++++ .../hooks/use-inventory-stock-columns.tsx | 66 ++++++ .../routes/inventory/inventory-stock/index.ts | 1 + .../inventory-stock/inventory-stock.tsx | 50 ++++ .../inventory/inventory-stock/schema.ts | 21 ++ .../shipping-option-price-cell.tsx | 2 +- .../hooks/use-price-list-grid-columns.tsx | 4 +- .../src/routes/products/common/constants.ts | 1 + .../product-variant-section.tsx | 32 ++- .../use-variant-table-columns.tsx | 30 ++- .../product-inventory-form/index.ts | 1 + .../product-inventory-form.tsx | 176 ++++++++++++++ .../hooks/use-product-inventory-columns.tsx | 215 ++++++++++++++++++ .../hooks/use-product-inventory-data.tsx | 38 ++++ .../products/product-inventory/index.ts | 1 + .../product-inventory/product-inventory.tsx | 26 +++ .../products/product-inventory/schema.ts | 32 +++ .../products/product-inventory/types.ts | 9 + .../products/product-inventory/utils.ts | 48 ++++ .../steps/create-inventory-levels.ts | 1 - .../workflows/batch-inventory-item-levels.ts | 57 +++++ .../workflows/bulk-create-delete-levels.ts | 2 + .../workflows/delete-inventory-levels.ts | 51 ++++- .../src/inventory/workflows/index.ts | 7 +- .../core/js-sdk/src/admin/inventory-item.ts | 142 ++++++++---- .../src/http/inventory/admin/payloads.ts | 13 ++ .../inventory/mutations/inventory-level.ts | 8 + .../location-levels/batch/route.ts | 20 ++ .../api/admin/inventory-items/middlewares.ts | 17 ++ .../api/admin/inventory-items/validators.ts | 17 ++ .../src/services/inventory-module.ts | 17 +- 53 files changed, 1611 insertions(+), 136 deletions(-) create mode 100644 packages/admin/dashboard/src/components/data-grid/components/data-grid-duplicate-cell.tsx create mode 100644 packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx create mode 100644 packages/admin/dashboard/src/routes/inventory/common/constants.ts create mode 100644 packages/admin/dashboard/src/routes/inventory/inventory-stock/components/inventory-stock-form/index.ts create mode 100644 packages/admin/dashboard/src/routes/inventory/inventory-stock/components/inventory-stock-form/inventory-stock-form.tsx create mode 100644 packages/admin/dashboard/src/routes/inventory/inventory-stock/hooks/use-inventory-stock-columns.tsx create mode 100644 packages/admin/dashboard/src/routes/inventory/inventory-stock/index.ts create mode 100644 packages/admin/dashboard/src/routes/inventory/inventory-stock/inventory-stock.tsx create mode 100644 packages/admin/dashboard/src/routes/inventory/inventory-stock/schema.ts create mode 100644 packages/admin/dashboard/src/routes/products/common/constants.ts create mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/index.ts create mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/product-inventory-form.tsx create mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-columns.tsx create mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-data.tsx create mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/index.ts create mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/product-inventory.tsx create mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/schema.ts create mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/types.ts create mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/utils.ts create mode 100644 packages/core/core-flows/src/inventory/workflows/batch-inventory-item-levels.ts create mode 100644 packages/medusa/src/api/admin/inventory-items/location-levels/batch/route.ts diff --git a/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts b/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts index 5661b45e2bc59..392d42489d0ed 100644 --- a/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts +++ b/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts @@ -12,7 +12,7 @@ medusaIntegrationTestRunner({ let inventoryItem2 let stockLocation1 let stockLocation2 - + let stockLocation3 beforeEach(async () => { await createAdminUser(dbConnection, adminHeaders, getContainer()) @@ -24,6 +24,10 @@ medusaIntegrationTestRunner({ await api.post(`/admin/stock-locations`, { name: "loc2" }, adminHeaders) ).data.stock_location + stockLocation3 = ( + await api.post(`/admin/stock-locations`, { name: "loc3" }, adminHeaders) + ).data.stock_location + inventoryItem1 = ( await api.post( `/admin/inventory-items`, @@ -122,6 +126,69 @@ medusaIntegrationTestRunner({ }) }) + describe("POST /admin/inventory-items/location-levels/batch", () => { + beforeEach(async () => { + await api.post( + `/admin/inventory-items/${inventoryItem1.id}/location-levels`, + { + location_id: stockLocation1.id, + stocked_quantity: 0, + }, + adminHeaders + ) + + await api.post( + `/admin/inventory-items/${inventoryItem1.id}/location-levels`, + { + location_id: stockLocation2.id, + stocked_quantity: 10, + }, + adminHeaders + ) + }) + + it("should batch update the inventory levels", async () => { + const result = await api.post( + `/admin/inventory-items/location-levels/batch`, + { + update: [ + { + location_id: stockLocation1.id, + inventory_item_id: inventoryItem1.id, + stocked_quantity: 10, + }, + { + location_id: stockLocation2.id, + inventory_item_id: inventoryItem1.id, + stocked_quantity: 20, + }, + ], + }, + adminHeaders + ) + + expect(result.status).toEqual(200) + }) + + it("should batch create the inventory levels", async () => { + const result = await api.post( + `/admin/inventory-items/location-levels/batch`, + { + create: [ + { + location_id: stockLocation3.id, + inventory_item_id: inventoryItem1.id, + stocked_quantity: 10, + }, + ], + }, + adminHeaders + ) + + expect(result.status).toEqual(200) + }) + }) + describe("POST /admin/inventory-items/:id/location-levels/batch", () => { beforeEach(async () => { await api.post( diff --git a/packages/admin/dashboard/src/components/common/thumbnail/thumbnail.tsx b/packages/admin/dashboard/src/components/common/thumbnail/thumbnail.tsx index ffd0002f12a7d..5e32de1cda5d3 100644 --- a/packages/admin/dashboard/src/components/common/thumbnail/thumbnail.tsx +++ b/packages/admin/dashboard/src/components/common/thumbnail/thumbnail.tsx @@ -11,7 +11,7 @@ export const Thumbnail = ({ src, alt, size = "base" }: ThumbnailProps) => { return (
)}
diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-duplicate-cell.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-duplicate-cell.tsx new file mode 100644 index 0000000000000..fc5577cd48ab0 --- /dev/null +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-duplicate-cell.tsx @@ -0,0 +1,23 @@ +import { ReactNode } from "react" +import { useWatch } from "react-hook-form" +import { useDataGridCell } from "../hooks" +import { DataGridCellProps } from "../types" + +export const DataGridDuplicateCell = ({ + context, + children, +}: DataGridCellProps & { + children?: ReactNode | ((props: { value: TValue }) => ReactNode) +}) => { + const { field, control } = useDataGridCell({ + context, + }) + + const value = useWatch({ control, name: field }) + + return ( +
+ {typeof children === "function" ? children({ value: value }) : children} +
+ ) +} diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-readonly-cell.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-readonly-cell.tsx index bc00e80f899b9..cf842684ae0cc 100644 --- a/packages/admin/dashboard/src/components/data-grid/components/data-grid-readonly-cell.tsx +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-readonly-cell.tsx @@ -1,24 +1,32 @@ import { PropsWithChildren } from "react" +import { clx } from "@medusajs/ui" import { useDataGridCellError } from "../hooks" import { DataGridCellProps } from "../types" import { DataGridRowErrorIndicator } from "./data-grid-row-error-indicator" -type DataGridReadonlyCellProps = DataGridCellProps< - TData, - TValue -> & - PropsWithChildren +type DataGridReadonlyCellProps = PropsWithChildren< + DataGridCellProps +> & { + color?: "muted" | "normal" +} export const DataGridReadonlyCell = ({ context, + color = "muted", children, }: DataGridReadonlyCellProps) => { const { rowErrors } = useDataGridCellError({ context }) return ( -
- {children} +
+
{children}
) diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx index d8d62536bb717..cd2195441a4eb 100644 --- a/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx @@ -50,7 +50,7 @@ import { isCellMatch, isSpecialFocusKey } from "../utils" import { DataGridKeyboardShortcutModal } from "./data-grid-keyboard-shortcut-modal" export interface DataGridRootProps< TData, - TFieldValues extends FieldValues = FieldValues, + TFieldValues extends FieldValues = FieldValues > { data?: TData[] columns: ColumnDef[] @@ -90,13 +90,12 @@ const getCommonPinningStyles = ( /** * TODO: - * - [Minor] Add shortcuts overview modal. * - [Minor] Extend the commands to also support modifying the anchor and rangeEnd, to restore the previous focus after undo/redo. */ export const DataGridRoot = < TData, - TFieldValues extends FieldValues = FieldValues, + TFieldValues extends FieldValues = FieldValues >({ data = [], columns, @@ -333,6 +332,7 @@ export const DataGridRoot = < setSelectionValues, onEditingChangeHandler, restoreSnapshot, + createSnapshot, setSingleRange, scrollToCoordinates, execute, diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx new file mode 100644 index 0000000000000..d131fbc01b0ed --- /dev/null +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx @@ -0,0 +1,163 @@ +import { Switch } from "@medusajs/ui" +import { useEffect, useRef, useState } from "react" +import CurrencyInput, { CurrencyInputProps } from "react-currency-input-field" +import { Controller, ControllerRenderProps } from "react-hook-form" +import { useCombinedRefs } from "../../../hooks/use-combined-refs" +import { useDataGridCell, useDataGridCellError } from "../hooks" +import { DataGridCellProps, InputProps } from "../types" +import { DataGridCellContainer } from "./data-grid-cell-container" + +export const DataGridTogglableNumberCell = ({ + context, + ...rest +}: DataGridCellProps & { + min?: number + max?: number + placeholder?: string +}) => { + const { field, control, renderProps } = useDataGridCell({ + context, + }) + const errorProps = useDataGridCellError({ context }) + + const { container, input } = renderProps + + return ( + { + return ( + + } + > + + + ) + }} + /> + ) +} + +const OuterComponent = ({ + field, + inputProps, + isAnchor, +}: { + field: ControllerRenderProps + inputProps: InputProps + isAnchor: boolean +}) => { + const buttonRef = useRef(null) + const { value } = field + const { onChange } = inputProps + + const [localValue, setLocalValue] = useState(value) + + useEffect(() => { + setLocalValue(value) + }, [value]) + + const handleCheckedChange = (update: boolean) => { + const newValue = { ...localValue, checked: update } + setLocalValue(newValue) + onChange(newValue, value) + } + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if (isAnchor && e.key.toLowerCase() === "x") { + e.preventDefault() + buttonRef.current?.click() + } + } + + document.addEventListener("keydown", handleKeyDown) + return () => document.removeEventListener("keydown", handleKeyDown) + }, [isAnchor]) + + return ( +
+ +
+ ) +} + +const Inner = ({ + field, + inputProps, + ...props +}: { + field: ControllerRenderProps + inputProps: InputProps + min?: number + max?: number + placeholder?: string +}) => { + const { ref, value, onChange: _, onBlur, ...fieldProps } = field + const { + ref: inputRef, + onChange, + onBlur: onInputBlur, + onFocus, + ...attributes + } = inputProps + + const [localValue, setLocalValue] = useState(value) + + useEffect(() => { + setLocalValue(value) + }, [value]) + + const combinedRefs = useCombinedRefs(inputRef, ref) + + const handleInputChange: CurrencyInputProps["onValueChange"] = ( + value, + _name, + _values + ) => { + const ensuredValue = value || "" + + const newValue = { ...localValue, quantity: ensuredValue } + setLocalValue(newValue) + } + + return ( +
+ { + onBlur() + onInputBlur() + + onChange(localValue, value) + }} + onFocus={onFocus} + decimalsLimit={0} + autoComplete="off" + tabIndex={-1} + /> +
+ ) +} diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell-snapshot.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell-snapshot.tsx index ffc3dcbf1a5c1..9f73327cc5509 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell-snapshot.tsx +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell-snapshot.tsx @@ -15,9 +15,8 @@ export const useDataGridCellSnapshot = < matrix, form, }: UseDataGridCellSnapshotOptions) => { - const [snapshot, setSnapshot] = useState | null>( - null - ) + const [snapshot, setSnapshot] = + useState | null>(null) const { getValues, setValue } = form @@ -38,7 +37,18 @@ export const useDataGridCellSnapshot = < const value = getValues(field as Path) - setSnapshot({ field, value }) + setSnapshot((curr) => { + /** + * If there already exists a snapshot for this field, we don't want to create a new one. + * A case where this happens is when the user presses the space key on a field. In that case + * we create a snapshot of the value before its destroyed by the space key. + */ + if (curr?.field === field) { + return curr + } + + return { field, value } + }) }, [getValues, matrix] ) diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell.tsx index 3f6ee47b2e2ad..1fa693f2e68c9 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell.tsx +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell.tsx @@ -123,16 +123,16 @@ export const useDataGridCell = ({ const validateKeyStroke = useCallback( (key: string) => { - if (type === "number") { - return numberCharacterRegex.test(key) + switch (type) { + case "togglable-number": + case "number": + return numberCharacterRegex.test(key) + case "text": + return textCharacterRegex.test(key) + default: + // KeyboardEvents should not be forwareded to other types of cells + return false } - - if (type === "text") { - return textCharacterRegex.test(key) - } - - // KeyboardEvents should not be forwareded to other types of cells - return false }, [type] ) diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx index bee8c62bac50b..f1224420cfb1a 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx @@ -1,3 +1,4 @@ +import set from "lodash/set" import { useCallback } from "react" import { FieldValues, Path, PathValue, UseFormReturn } from "react-hook-form" @@ -12,13 +13,13 @@ type UseDataGridFormHandlersOptions = { export const useDataGridFormHandlers = < TData, - TFieldValues extends FieldValues, + TFieldValues extends FieldValues >({ matrix, form, anchor, }: UseDataGridFormHandlersOptions) => { - const { getValues, setValue } = form + const { getValues, reset } = form const getSelectionValues = useCallback( (fields: string[]): PathValue>[] => { @@ -26,9 +27,10 @@ export const useDataGridFormHandlers = < return [] } + const allValues = getValues() return fields.map((field) => { - return getValues(field as Path) - }) + return field.split(".").reduce((obj, key) => obj?.[key], allValues) + }) as PathValue>[] }, [getValues] ) @@ -40,12 +42,12 @@ export const useDataGridFormHandlers = < } const type = matrix.getCellType(anchor) - if (!type) { return } const convertedValues = convertArrayToPrimitive(values, type) + const currentValues = getValues() fields.forEach((field, index) => { if (!field) { @@ -53,18 +55,18 @@ export const useDataGridFormHandlers = < } const valueIndex = index % values.length - const value = convertedValues[valueIndex] as PathValue< - TFieldValues, - Path - > - - setValue(field as Path, value, { - shouldDirty: true, - shouldTouch: true, - }) + const value = convertedValues[valueIndex] + + set(currentValues, field, value) + }) + + reset(currentValues, { + keepDirty: true, + keepTouched: true, + keepDefaultValues: true, }) }, - [matrix, anchor, setValue] + [matrix, anchor, getValues, reset] ) return { @@ -119,7 +121,17 @@ export function convertArrayToPrimitive( ): any[] { switch (type) { case "number": - return values.map((v) => (v === "" ? v : convertToNumber(v))) + return values.map((v) => { + if (v === "") { + return v + } + + if (v == null) { + return "" + } + + return convertToNumber(v) + }) case "boolean": return values.map(convertToBoolean) case "text": diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx index 3e7da7b1a2a3e..8e7030291b1a6 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx @@ -1,4 +1,4 @@ -import { useCallback } from "react" +import React, { useCallback } from "react" import type { FieldValues, Path, @@ -39,6 +39,7 @@ type UseDataGridKeydownEventOptions = { ) => PathValue>[] setSelectionValues: (fields: string[], values: string[]) => void restoreSnapshot: () => void + createSnapshot: (coords: DataGridCoordinates) => void } const ARROW_KEYS = ["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"] @@ -67,6 +68,7 @@ export const useDataGridKeydownEvent = < getSelectionValues, setSelectionValues, restoreSnapshot, + createSnapshot, }: UseDataGridKeydownEventOptions) => { const handleKeyboardNavigation = useCallback( (e: KeyboardEvent) => { @@ -218,6 +220,8 @@ export const useDataGridKeydownEvent = < return } + createSnapshot(anchor) + const current = getValues(field as Path) const next = "" @@ -236,7 +240,39 @@ export const useDataGridKeydownEvent = < input.focus() }, - [matrix, queryTool, getValues, execute, setValue] + [matrix, queryTool, getValues, execute, setValue, createSnapshot] + ) + + const handleSpaceKeyTogglableNumber = useCallback( + (anchor: DataGridCoordinates) => { + const field = matrix.getCellField(anchor) + const input = queryTool?.getInput(anchor) + + if (!field || !input) { + return + } + + createSnapshot(anchor) + + const current = getValues(field as Path) + const next = { ...current, quantity: "" } + + const command = new DataGridUpdateCommand({ + next, + prev: current, + setter: (value) => { + setValue(field as Path, value, { + shouldDirty: true, + shouldTouch: true, + }) + }, + }) + + execute(command) + + input.focus() + }, + [matrix, queryTool, getValues, execute, setValue, createSnapshot] ) const handleSpaceKey = useCallback( @@ -257,6 +293,9 @@ export const useDataGridKeydownEvent = < case "boolean": handleSpaceKeyBoolean(anchor) break + case "togglable-number": + handleSpaceKeyTogglableNumber(anchor) + break case "number": case "text": handleSpaceKeyTextOrNumber(anchor) @@ -269,6 +308,7 @@ export const useDataGridKeydownEvent = < matrix, handleSpaceKeyBoolean, handleSpaceKeyTextOrNumber, + handleSpaceKeyTogglableNumber, ] ) @@ -390,6 +430,7 @@ export const useDataGridKeydownEvent = < const type = matrix.getCellType(anchor) switch (type) { + case "togglable-number": case "text": case "number": handleEnterKeyTextOrNumber(e, anchor) @@ -518,7 +559,7 @@ export const useDataGridKeydownEvent = < break } }, - [anchor, isEditing, setTrapActive, containerRef] + [isEditing, setTrapActive, containerRef] ) const handleKeyDownEvent = useCallback( diff --git a/packages/admin/dashboard/src/components/data-grid/types.ts b/packages/admin/dashboard/src/components/data-grid/types.ts index 3f59ecbb70f45..857396584ea8a 100644 --- a/packages/admin/dashboard/src/components/data-grid/types.ts +++ b/packages/admin/dashboard/src/components/data-grid/types.ts @@ -14,7 +14,11 @@ import { PathValue, } from "react-hook-form" -export type DataGridColumnType = "text" | "number" | "boolean" +export type DataGridColumnType = + | "text" + | "number" + | "boolean" + | "togglable-number" export type DataGridCoordinates = { row: number @@ -100,7 +104,7 @@ export interface DataGridCellContainerProps extends PropsWithChildren<{}> { } export type DataGridCellSnapshot< - TFieldValues extends FieldValues = FieldValues + TFieldValues extends FieldValues = FieldValues, > = { field: string value: PathValue> diff --git a/packages/admin/dashboard/src/hooks/api/inventory.tsx b/packages/admin/dashboard/src/hooks/api/inventory.tsx index 93f7c867c8c23..8a73f4c42ebbc 100644 --- a/packages/admin/dashboard/src/hooks/api/inventory.tsx +++ b/packages/admin/dashboard/src/hooks/api/inventory.tsx @@ -1,3 +1,4 @@ +import { FetchError } from "@medusajs/js-sdk" import { HttpTypes } from "@medusajs/types" import { QueryKey, @@ -6,11 +7,11 @@ import { useMutation, useQuery, } from "@tanstack/react-query" -import { FetchError } from "@medusajs/js-sdk" import { sdk } from "../../lib/client" import { queryClient } from "../../lib/query-client" import { queryKeysFactory } from "../../lib/query-key-factory" +import { variantsQueryKeys } from "./products" const INVENTORY_ITEMS_QUERY_KEY = "inventory_items" as const export const inventoryItemsQueryKeys = queryKeysFactory( @@ -23,7 +24,7 @@ export const inventoryItemLevelsQueryKeys = queryKeysFactory( ) export const useInventoryItems = ( - query?: Record, + query?: HttpTypes.AdminInventoryItemParams, options?: Omit< UseQueryOptions< HttpTypes.AdminInventoryItemListResponse, @@ -136,7 +137,7 @@ export const useDeleteInventoryItemLevel = ( inventoryItemId: string, locationId: string, options?: UseMutationOptions< - HttpTypes.AdminInventoryItemDeleteResponse, + HttpTypes.AdminInventoryLevelDeleteResponse, FetchError, void > @@ -236,3 +237,26 @@ export const useBatchUpdateInventoryLevels = ( ...options, }) } + +export const useBatchInventoryLevels = ( + options?: UseMutationOptions< + HttpTypes.AdminInventoryItemResponse, + FetchError, + HttpTypes.AdminBatchInventoryItemLevels + > +) => { + return useMutation({ + mutationFn: (payload: HttpTypes.AdminBatchInventoryItemLevels) => + sdk.admin.inventoryItem._batchUpdateLevels(payload), + onSuccess: (data, variables, context) => { + queryClient.invalidateQueries({ + queryKey: inventoryItemsQueryKeys.all, + }) + queryClient.invalidateQueries({ + queryKey: variantsQueryKeys.lists(), + }) + options?.onSuccess?.(data, variables, context) + }, + ...options, + }) +} diff --git a/packages/admin/dashboard/src/hooks/api/products.tsx b/packages/admin/dashboard/src/hooks/api/products.tsx index edb4a68b38135..eee11f83d89c1 100644 --- a/packages/admin/dashboard/src/hooks/api/products.tsx +++ b/packages/admin/dashboard/src/hooks/api/products.tsx @@ -110,9 +110,14 @@ export const useProductVariant = ( export const useProductVariants = ( productId: string, - query?: Record, + query?: HttpTypes.AdminProductVariantParams, options?: Omit< - UseQueryOptions, + UseQueryOptions< + HttpTypes.AdminProductVariantListResponse, + FetchError, + HttpTypes.AdminProductVariantListResponse, + QueryKey + >, "queryFn" | "queryKey" > ) => { diff --git a/packages/admin/dashboard/src/providers/router-provider/route-map.tsx b/packages/admin/dashboard/src/providers/router-provider/route-map.tsx index 0862cb3371199..f622d165812e3 100644 --- a/packages/admin/dashboard/src/providers/router-provider/route-map.tsx +++ b/packages/admin/dashboard/src/providers/router-provider/route-map.tsx @@ -129,6 +129,11 @@ export const RouteMap: RouteObject[] = [ "../../routes/products/product-create-variant" ), }, + { + path: "inventory", + lazy: () => + import("../../routes/products/product-inventory"), + }, { path: "metadata/edit", lazy: () => @@ -764,6 +769,11 @@ export const RouteMap: RouteObject[] = [ lazy: () => import("../../routes/inventory/inventory-create"), }, + { + path: "stock", + lazy: () => + import("../../routes/inventory/inventory-stock"), + }, ], }, { diff --git a/packages/admin/dashboard/src/routes/inventory/common/constants.ts b/packages/admin/dashboard/src/routes/inventory/common/constants.ts new file mode 100644 index 0000000000000..81cf300172386 --- /dev/null +++ b/packages/admin/dashboard/src/routes/inventory/common/constants.ts @@ -0,0 +1 @@ +export const INVENTORY_ITEM_IDS_KEY = "inventory_item_ids" diff --git a/packages/admin/dashboard/src/routes/inventory/inventory-detail/components/inventory-item-location-levels.tsx b/packages/admin/dashboard/src/routes/inventory/inventory-detail/components/inventory-item-location-levels.tsx index 3ca7071f6586b..8904d645bbfff 100644 --- a/packages/admin/dashboard/src/routes/inventory/inventory-detail/components/inventory-item-location-levels.tsx +++ b/packages/admin/dashboard/src/routes/inventory/inventory-detail/components/inventory-item-location-levels.tsx @@ -1,8 +1,8 @@ +import { HttpTypes } from "@medusajs/types" import { Button, Container, Heading } from "@medusajs/ui" -import { ItemLocationListTable } from "./location-levels-table/location-list-table" -import { Link } from "react-router-dom" import { useTranslation } from "react-i18next" -import { HttpTypes } from "@medusajs/types" +import { Link } from "react-router-dom" +import { ItemLocationListTable } from "./location-levels-table/location-list-table" type InventoryItemLocationLevelsSectionProps = { inventoryItem: HttpTypes.AdminInventoryItemResponse["inventory_item"] @@ -13,7 +13,7 @@ export const InventoryItemLocationLevelsSection = ({ const { t } = useTranslation() return ( - +
{t("inventory.locationLevels")} + + +
+ + + + ) +} + +function getDefaultValues( + items: HttpTypes.AdminInventoryItem[], + locations: HttpTypes.AdminStockLocation[] +): DefaultValues { + return { + inventory_items: items.reduce((acc, item) => { + const locationsMap = locations.reduce((locationAcc, location) => { + const level = item.location_levels?.find( + (level) => level.location_id === location.id + ) + + locationAcc[location.id] = { + id: level?.id, + quantity: level?.stocked_quantity ?? "", + checked: !!level, + } + return locationAcc + }, {} as InventoryLocationsSchema) + + acc[item.id] = { locations: locationsMap } + return acc + }, {} as Record), + } +} diff --git a/packages/admin/dashboard/src/routes/inventory/inventory-stock/hooks/use-inventory-stock-columns.tsx b/packages/admin/dashboard/src/routes/inventory/inventory-stock/hooks/use-inventory-stock-columns.tsx new file mode 100644 index 0000000000000..654a5875ed15f --- /dev/null +++ b/packages/admin/dashboard/src/routes/inventory/inventory-stock/hooks/use-inventory-stock-columns.tsx @@ -0,0 +1,66 @@ +import { HttpTypes } from "@medusajs/types" +import { useMemo } from "react" +import { createDataGridHelper } from "../../../../components/data-grid" +import { DataGridReadOnlyCell } from "../../../../components/data-grid/components" +import { DataGridTogglableNumberCell } from "../../../../components/data-grid/components/data-grid-toggleable-number-cell" +import { InventoryStockSchema } from "../schema" + +const helper = createDataGridHelper< + HttpTypes.AdminInventoryItem, + InventoryStockSchema +>() + +export const useInventoryStockColumns = ( + locations: HttpTypes.AdminStockLocation[] = [] +) => { + return useMemo( + () => [ + helper.column({ + id: "title", + name: "Title", + header: "Title", + cell: (context) => { + const item = context.row.original + return ( + + {item.title || "-"} + + ) + }, + disableHiding: true, + }), + helper.column({ + id: "sku", + name: "SKU", + header: "SKU", + cell: (context) => { + const item = context.row.original + + return ( + + {item.sku || "-"} + + ) + }, + disableHiding: true, + }), + ...locations.map((location) => + helper.column({ + id: `location_${location.id}`, + name: location.name, + header: location.name, + field: (context) => { + const item = context.row.original + + return `inventory_items.${item.id}.locations.${location.id}` as const + }, + type: "togglable-number", + cell: (context) => { + return + }, + }) + ), + ], + [locations] + ) +} diff --git a/packages/admin/dashboard/src/routes/inventory/inventory-stock/index.ts b/packages/admin/dashboard/src/routes/inventory/inventory-stock/index.ts new file mode 100644 index 0000000000000..f629a40198ef6 --- /dev/null +++ b/packages/admin/dashboard/src/routes/inventory/inventory-stock/index.ts @@ -0,0 +1 @@ +export { InventoryStock as Component } from "./inventory-stock" diff --git a/packages/admin/dashboard/src/routes/inventory/inventory-stock/inventory-stock.tsx b/packages/admin/dashboard/src/routes/inventory/inventory-stock/inventory-stock.tsx new file mode 100644 index 0000000000000..337defe9f04fd --- /dev/null +++ b/packages/admin/dashboard/src/routes/inventory/inventory-stock/inventory-stock.tsx @@ -0,0 +1,50 @@ +import { useSearchParams } from "react-router-dom" +import { RouteFocusModal } from "../../../components/modals" +import { useInventoryItems, useStockLocations } from "../../../hooks/api" +import { INVENTORY_ITEM_IDS_KEY } from "../common/constants" +import { InventoryStockForm } from "./components/inventory-stock-form" + +export const InventoryStock = () => { + const [searchParams] = useSearchParams() + const inventoryItemIds = + searchParams.get(INVENTORY_ITEM_IDS_KEY)?.split(",") || undefined + + const { inventory_items, isPending, isError, error } = useInventoryItems({ + id: inventoryItemIds, + }) + + const { + stock_locations, + isPending: isPendingStockLocations, + isError: isErrorStockLocations, + error: errorStockLocations, + } = useStockLocations({ + limit: 9999, + fields: "id,name", + }) + + const ready = + !isPending && + !!inventory_items && + !isPendingStockLocations && + !!stock_locations + + if (isError) { + throw error + } + + if (isErrorStockLocations) { + throw errorStockLocations + } + + return ( + + {ready && ( + + )} + + ) +} diff --git a/packages/admin/dashboard/src/routes/inventory/inventory-stock/schema.ts b/packages/admin/dashboard/src/routes/inventory/inventory-stock/schema.ts new file mode 100644 index 0000000000000..ba271f65ba47f --- /dev/null +++ b/packages/admin/dashboard/src/routes/inventory/inventory-stock/schema.ts @@ -0,0 +1,21 @@ +import { z } from "zod" + +const LocationQuantitySchema = z.object({ + id: z.string().optional(), + quantity: z.union([z.number(), z.string()]), + checked: z.boolean(), +}) + +const InventoryLocationsSchema = z.record(LocationQuantitySchema) + +const InventoryItemSchema = z.object({ + locations: InventoryLocationsSchema, +}) + +export const InventoryStockSchema = z.object({ + inventory_items: z.record(InventoryItemSchema), +}) + +export type InventoryLocationsSchema = z.infer +export type InventoryItemSchema = z.infer +export type InventoryStockSchema = z.infer diff --git a/packages/admin/dashboard/src/routes/locations/common/components/shipping-option-price-cell/shipping-option-price-cell.tsx b/packages/admin/dashboard/src/routes/locations/common/components/shipping-option-price-cell/shipping-option-price-cell.tsx index 856e4ad93957b..282bfbdd3cd4c 100644 --- a/packages/admin/dashboard/src/routes/locations/common/components/shipping-option-price-cell/shipping-option-price-cell.tsx +++ b/packages/admin/dashboard/src/routes/locations/common/components/shipping-option-price-cell/shipping-option-price-cell.tsx @@ -130,7 +130,7 @@ const OuterComponent = ({ return (
- + {entity.title}
@@ -49,7 +49,7 @@ export const usePriceListGridColumns = ({ } return ( - +
{entity.title}
diff --git a/packages/admin/dashboard/src/routes/products/common/constants.ts b/packages/admin/dashboard/src/routes/products/common/constants.ts new file mode 100644 index 0000000000000..7d1a0b103f519 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/common/constants.ts @@ -0,0 +1 @@ +export const PRODUCT_VARIANT_IDS_KEY = "product_variant_ids" diff --git a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx index 2ee691533728f..c61ee42337b3e 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx +++ b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx @@ -1,13 +1,17 @@ -import { PencilSquare, Plus } from "@medusajs/icons" +import { Buildings, PencilSquare, Plus } from "@medusajs/icons" import { HttpTypes } from "@medusajs/types" import { Container, Heading } from "@medusajs/ui" import { keepPreviousData } from "@tanstack/react-query" import { useTranslation } from "react-i18next" +import { RowSelectionState } from "@tanstack/react-table" +import { useState } from "react" +import { useNavigate } from "react-router-dom" import { ActionMenu } from "../../../../../components/common/action-menu" import { DataTable } from "../../../../../components/table/data-table" import { useProductVariants } from "../../../../../hooks/api/products" import { useDataTable } from "../../../../../hooks/use-data-table" +import { PRODUCT_VARIANT_IDS_KEY } from "../../../common/constants" import { useProductVariantTableColumns } from "./use-variant-table-columns" import { useProductVariantTableFilters } from "./use-variant-table-filters" import { useProductVariantTableQuery } from "./use-variant-table-query" @@ -22,6 +26,7 @@ export const ProductVariantSection = ({ product, }: ProductVariantSectionProps) => { const { t } = useTranslation() + const navigate = useNavigate() const { searchParams, raw } = useProductVariantTableQuery({ pageSize: PAGE_SIZE, @@ -37,6 +42,8 @@ export const ProductVariantSection = ({ } ) + const [selection, setSelection] = useState({}) + const filters = useProductVariantTableFilters() const columns = useProductVariantTableColumns(product) @@ -47,6 +54,11 @@ export const ProductVariantSection = ({ enablePagination: true, getRowId: (row) => row.id, pageSize: PAGE_SIZE, + enableRowSelection: true, + rowSelection: { + state: selection, + updater: setSelection, + }, meta: { product, }, @@ -74,6 +86,11 @@ export const ProductVariantSection = ({ to: `prices`, icon: , }, + { + label: "Edit inventory items", + to: `inventory`, + icon: , + }, ], }, ]} @@ -97,6 +114,19 @@ export const ProductVariantSection = ({ pagination search queryObject={raw} + commands={[ + { + action: async (selection) => { + navigate( + `inventory?${PRODUCT_VARIANT_IDS_KEY}=${Object.keys( + selection + ).join(",")}` + ) + }, + label: "Edit inventory", + shortcut: "i", + }, + ]} /> ) diff --git a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/use-variant-table-columns.tsx b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/use-variant-table-columns.tsx index ca5fb72aa6899..e5949cb3552fc 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/use-variant-table-columns.tsx +++ b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/use-variant-table-columns.tsx @@ -1,6 +1,6 @@ import { Buildings, Component, PencilSquare, Trash } from "@medusajs/icons" import { HttpTypes, InventoryItemDTO } from "@medusajs/types" -import { Badge, clx, usePrompt } from "@medusajs/ui" +import { Badge, Checkbox, clx, usePrompt } from "@medusajs/ui" import { createColumnHelper } from "@tanstack/react-table" import { useMemo } from "react" import { useTranslation } from "react-i18next" @@ -145,6 +145,34 @@ export const useProductVariantTableColumns = ( return useMemo( () => [ + columnHelper.display({ + id: "select", + header: ({ table }) => { + return ( + + table.toggleAllPageRowsSelected(!!value) + } + /> + ) + }, + cell: ({ row }) => { + return ( + row.toggleSelected(!!value)} + onClick={(e) => { + e.stopPropagation() + }} + /> + ) + }, + }), columnHelper.accessor("title", { header: () => (
diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/index.ts b/packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/index.ts new file mode 100644 index 0000000000000..da2f5b485d5cd --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/index.ts @@ -0,0 +1 @@ +export * from "./product-inventory-form" diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/product-inventory-form.tsx b/packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/product-inventory-form.tsx new file mode 100644 index 0000000000000..b55955c0a41ab --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/product-inventory-form.tsx @@ -0,0 +1,176 @@ +import { zodResolver } from "@hookform/resolvers/zod" +import { HttpTypes } from "@medusajs/types" +import { Button, toast } from "@medusajs/ui" +import { useMemo, useRef } from "react" +import { DefaultValues, useForm } from "react-hook-form" +import { useTranslation } from "react-i18next" +import { DataGrid } from "../../../../../components/data-grid" +import { + RouteFocusModal, + useRouteModal, +} from "../../../../../components/modals" +import { KeyboundForm } from "../../../../../components/utilities/keybound-form" +import { useBatchInventoryLevels } from "../../../../../hooks/api" +import { castNumber } from "../../../../../lib/cast-number" +import { useProductInventoryColumns } from "../../hooks/use-product-inventory-columns" +import { + ProductInventoryInventoryItemSchema, + ProductInventorySchema, + ProductInventoryVariantSchema, + ProductVariantLocationSchema, +} from "../../schema" +import { ProductVariantInventoryItemLink } from "../../types" +import { + getDisabledInventoryRows, + isProductVariantWithInventoryPivot, +} from "../../utils" + +type ProductInventoryFormProps = { + variants: HttpTypes.AdminProductVariant[] + locations: HttpTypes.AdminStockLocation[] +} + +export const ProductInventoryForm = ({ + variants, + locations, +}: ProductInventoryFormProps) => { + const { t } = useTranslation() + const { setCloseOnEscape } = useRouteModal() + const { handleSuccess } = useRouteModal() + + const form = useForm({ + // TODO: Update ProductVariant type to include inventory_items + defaultValues: getDefaultValue(variants as any, locations), + resolver: zodResolver(ProductInventorySchema), + }) + + const initialValues = useRef(getDefaultValue(variants as any, locations)) + + const disabled = useMemo( + () => getDisabledInventoryRows(variants as any), + [variants] + ) + const columns = useProductInventoryColumns(locations, disabled) + + const { mutateAsync, isPending } = useBatchInventoryLevels() + + const onSubmit = form.handleSubmit(async (data) => { + const payload: HttpTypes.AdminBatchInventoryItemLevels = { + create: [], + update: [], + delete: [], + } + + for (const [variantId, variant] of Object.entries(data.variants)) { + for (const [inventory_item_id, item] of Object.entries( + variant.inventory_items + )) { + for (const [location_id, level] of Object.entries(item.locations)) { + if (level.levels_id) { + const newQuantity = + level.quantity !== "" ? castNumber(level.quantity) : undefined + const originalQuantity = + initialValues.current?.variants?.[variantId]?.inventory_items?.[ + inventory_item_id + ]?.locations?.[location_id]?.quantity + + if (newQuantity !== originalQuantity) { + payload.update.push({ + inventory_item_id, + location_id, + stocked_quantity: newQuantity, + }) + } + } + + if (!level.levels_id && level.quantity !== "") { + payload.create.push({ + inventory_item_id, + location_id, + stocked_quantity: castNumber(level.quantity), + }) + } + } + } + } + + await mutateAsync(payload, { + onSuccess: () => { + toast.success("Updated inventory levels!") + handleSuccess() + }, + onError: (error) => { + toast.error(error.message) + }, + }) + }) + + return ( + + + + + setCloseOnEscape(!editing)} + /> + + +
+ + + + +
+
+
+
+ ) +} + +function getSubRows( + row: HttpTypes.AdminProductVariant | ProductVariantInventoryItemLink +): ProductVariantInventoryItemLink[] | undefined { + if (isProductVariantWithInventoryPivot(row)) { + return row.inventory_items + } +} + +function getDefaultValue( + variants: (HttpTypes.AdminProductVariant & { + inventory_items: ProductVariantInventoryItemLink[] + })[], + locations: HttpTypes.AdminStockLocation[] +): DefaultValues { + return { + variants: variants.reduce((variantAcc, variant) => { + const inventoryItems = variant.inventory_items.reduce((itemAcc, item) => { + const locationsMap = locations.reduce((locationAcc, location) => { + const levels = item.inventory.location_levels?.find( + (level) => level.location_id === location.id + ) + + locationAcc[location.id] = { + quantity: levels?.stocked_quantity || "", + levels_id: levels?.id, + checked: !!levels, + } + return locationAcc + }, {} as ProductVariantLocationSchema) + + itemAcc[item.inventory_item_id] = { locations: locationsMap } + return itemAcc + }, {} as Record) + + variantAcc[variant.id] = { inventory_items: inventoryItems } + return variantAcc + }, {} as Record), + } +} diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-columns.tsx b/packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-columns.tsx new file mode 100644 index 0000000000000..864ee45ab1dc0 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-columns.tsx @@ -0,0 +1,215 @@ +import { InformationCircle } from "@medusajs/icons" +import { HttpTypes } from "@medusajs/types" +import { Switch, Tooltip } from "@medusajs/ui" +import { useCallback, useMemo } from "react" +import { Thumbnail } from "../../../../components/common/thumbnail" +import { createDataGridHelper } from "../../../../components/data-grid" +import { DataGridReadOnlyCell } from "../../../../components/data-grid/components" +import { DataGridDuplicateCell } from "../../../../components/data-grid/components/data-grid-duplicate-cell" +import { DataGridTogglableNumberCell } from "../../../../components/data-grid/components/data-grid-toggleable-number-cell" +import { ProductInventorySchema } from "../schema" +import { ProductVariantInventoryItemLink } from "../types" +import { isProductVariant } from "../utils" + +const helper = createDataGridHelper< + HttpTypes.AdminProductVariant | ProductVariantInventoryItemLink, + ProductInventorySchema +>() + +type DisabledItem = { id: string; title: string; sku: string } +type DisabledResult = + | { + isDisabled: true + item: DisabledItem + } + | { + isDisabled: false + item: undefined + } + +export const useProductInventoryColumns = ( + locations: HttpTypes.AdminStockLocation[] = [], + disabled: Record = {} +) => { + const getIsDisabled = useCallback( + (item: ProductVariantInventoryItemLink): DisabledResult => { + const disabledItem = disabled[item.inventory_item_id] + const isDisabled = !!disabledItem && disabledItem.id !== item.variant_id + + if (!isDisabled) { + return { + isDisabled: false, + item: undefined, + } + } + + return { + isDisabled, + item: disabledItem, + } + }, + [disabled] + ) + + return useMemo( + () => [ + helper.column({ + id: "title", + name: "Title", + header: "Title", + cell: (context) => { + const item = context.row.original + + if (isProductVariant(item)) { + return ( + +
+ + {item.title || "-"} +
+
+ ) + } + + const { isDisabled, item: disabledItem } = getIsDisabled(item) + + if (isDisabled) { + return ( + +
+ + {item.inventory.title || "-"} + + + + +
+
+ ) + } + + return ( + + {item.inventory.title || "-"} + + ) + }, + disableHiding: true, + }), + helper.column({ + id: "sku", + name: "SKU", + header: "SKU", + cell: (context) => { + const item = context.row.original + + if (isProductVariant(item)) { + return ( + + {item.sku || "-"} + + ) + } + + const { isDisabled } = getIsDisabled(item) + + if (isDisabled) { + return ( + + {item.inventory.sku || "-"} + + ) + } + + return ( + + {item.inventory.sku || "-"} + + ) + }, + disableHiding: true, + }), + ...locations.map((location) => + helper.column({ + id: `location_${location.id}`, + name: location.name, + header: location.name, + field: (context) => { + const item = context.row.original + + if (isProductVariant(item)) { + return null + } + + const { isDisabled, item: disabledItem } = getIsDisabled(item) + + if (isDisabled) { + return `variants.${disabledItem.id}.inventory_items.${item.inventory_item_id}.locations.${location.id}` as const + } + + return `variants.${item.variant_id}.inventory_items.${item.inventory_item_id}.locations.${location.id}` as const + }, + type: "togglable-number", + cell: (context) => { + const item = context.row.original + + if (isProductVariant(item)) { + return + } + + const { isDisabled } = getIsDisabled(item) + + if (isDisabled) { + return ( + + {({ value }) => { + const { checked, quantity } = value as { + checked: boolean + quantity: number | string + } + + return ( +
+ + + {quantity} + +
+ ) + }} +
+ ) + } + + // Depending on how we want to handle the checked state, we might need + // to move this to the form state. + // const locationLevel = item.inventory.location_levels?.find( + // (level) => level.location_id === location.id + // ) + + // const disableToggle = Boolean( + // locationLevel && + // (locationLevel.reserved_quantity > 0 || + // locationLevel.incoming_quantity > 0) + // ) + + return + }, + }) + ), + ], + [locations, getIsDisabled] + ) +} diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-data.tsx b/packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-data.tsx new file mode 100644 index 0000000000000..fde29b812dbad --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-data.tsx @@ -0,0 +1,38 @@ +import { useProductVariants, useStockLocations } from "../../../../hooks/api" + +export const useProductInventoryData = ( + id: string, + productVariantIds?: string[] +) => { + const variantData = useProductVariants(id, { + id: productVariantIds, + limit: !productVariantIds ? 9999 : undefined, + fields: + "id,title,sku,inventory_items,inventory_items.*,inventory_items.inventory,inventory_items.inventory.id,inventory_items.inventory.title,inventory_items.inventory.sku,*inventory_items.inventory.location_levels,product.thumbnail", + }) + + const locationData = useStockLocations({ + limit: 9999, + fields: "id,name", + }) + + const isLoaded = + !variantData.isPending && + !locationData.isPending && + !!variantData.variants && + !!locationData.stock_locations + + if (variantData.isError) { + throw variantData.error + } + + if (locationData.isError) { + throw locationData.error + } + + return { + variants: variantData.variants || [], + locations: locationData.stock_locations || [], + isLoaded, + } +} diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/index.ts b/packages/admin/dashboard/src/routes/products/product-inventory/index.ts new file mode 100644 index 0000000000000..7731a0089e863 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-inventory/index.ts @@ -0,0 +1 @@ +export { ProductInventory as Component } from "./product-inventory" diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/product-inventory.tsx b/packages/admin/dashboard/src/routes/products/product-inventory/product-inventory.tsx new file mode 100644 index 0000000000000..c8513466d4eb7 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-inventory/product-inventory.tsx @@ -0,0 +1,26 @@ +import { useParams, useSearchParams } from "react-router-dom" +import { RouteFocusModal } from "../../../components/modals" +import { PRODUCT_VARIANT_IDS_KEY } from "../common/constants" +import { ProductInventoryForm } from "./components/product-inventory-form" +import { useProductInventoryData } from "./hooks/use-product-inventory-data" + +export const ProductInventory = () => { + const { id } = useParams<{ id: string }>() + const [searchParams] = useSearchParams() + + const productVariantIds = + searchParams.get(PRODUCT_VARIANT_IDS_KEY)?.split(",") || undefined + + const { variants, locations, isLoaded } = useProductInventoryData( + id!, + productVariantIds + ) + + return ( + + {isLoaded && ( + + )} + + ) +} diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/schema.ts b/packages/admin/dashboard/src/routes/products/product-inventory/schema.ts new file mode 100644 index 0000000000000..d4aab6d5069a5 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-inventory/schema.ts @@ -0,0 +1,32 @@ +import { z } from "zod" + +const LocationQuantitySchema = z.object({ + levels_id: z.string().optional(), + quantity: z.union([z.number(), z.string()]), + checked: z.boolean(), +}) + +const ProductInventoryLocationsSchema = z.record(LocationQuantitySchema) + +const ProductInventoryInventoryItemSchema = z.object({ + locations: ProductInventoryLocationsSchema, +}) + +const ProductInventoryVariantSchema = z.object({ + inventory_items: z.record(ProductInventoryInventoryItemSchema), +}) + +export const ProductInventorySchema = z.object({ + variants: z.record(ProductInventoryVariantSchema), +}) + +export type ProductVariantLocationSchema = z.infer< + typeof ProductInventoryLocationsSchema +> +export type ProductInventoryInventoryItemSchema = z.infer< + typeof ProductInventoryInventoryItemSchema +> +export type ProductInventoryVariantSchema = z.infer< + typeof ProductInventoryVariantSchema +> +export type ProductInventorySchema = z.infer diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/types.ts b/packages/admin/dashboard/src/routes/products/product-inventory/types.ts new file mode 100644 index 0000000000000..59e3a196f9554 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-inventory/types.ts @@ -0,0 +1,9 @@ +import { HttpTypes } from "@medusajs/types" + +// TODO: Create a type in the types package +export interface ProductVariantInventoryItemLink { + id: string + variant_id: string + inventory_item_id: string + inventory: HttpTypes.AdminInventoryItem +} diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/utils.ts b/packages/admin/dashboard/src/routes/products/product-inventory/utils.ts new file mode 100644 index 0000000000000..df620eb3a1c70 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-inventory/utils.ts @@ -0,0 +1,48 @@ +import { HttpTypes } from "@medusajs/types" +import { ProductVariantInventoryItemLink } from "./types" + +export function isProductVariant( + row: HttpTypes.AdminProductVariant | ProductVariantInventoryItemLink +): row is HttpTypes.AdminProductVariant { + return row.id.startsWith("variant_") +} + +export function isProductVariantWithInventoryPivot( + row: HttpTypes.AdminProductVariant | ProductVariantInventoryItemLink +): row is HttpTypes.AdminProductVariant & { + inventory_items: ProductVariantInventoryItemLink[] +} { + return (row as any).inventory_items && (row as any).inventory_items.length > 0 +} + +export function getDisabledInventoryRows( + variants: (HttpTypes.AdminProductVariant & { + inventory_items: ProductVariantInventoryItemLink[] + })[] +) { + const seen: Record = {} + const disabled: Record = + {} + + variants.forEach((variant) => { + const inventoryItems = variant.inventory_items + + inventoryItems.forEach((item) => { + const existing = seen[item.inventory_item_id] + + if (existing) { + disabled[item.inventory_item_id] = { + id: existing.id, + title: existing.title || "", + sku: existing.sku || "", + } + + return + } + + seen[item.inventory_item_id] = variant + }) + }) + + return disabled +} diff --git a/packages/core/core-flows/src/inventory/steps/create-inventory-levels.ts b/packages/core/core-flows/src/inventory/steps/create-inventory-levels.ts index 4daccd83ee6d5..e4050c258247b 100644 --- a/packages/core/core-flows/src/inventory/steps/create-inventory-levels.ts +++ b/packages/core/core-flows/src/inventory/steps/create-inventory-levels.ts @@ -11,7 +11,6 @@ export const createInventoryLevelsStep = createStep( createInventoryLevelsStepId, async (data: InventoryTypes.CreateInventoryLevelInput[], { container }) => { const service = container.resolve(Modules.INVENTORY) - const inventoryLevels = await service.createInventoryLevels(data) return new StepResponse( inventoryLevels, diff --git a/packages/core/core-flows/src/inventory/workflows/batch-inventory-item-levels.ts b/packages/core/core-flows/src/inventory/workflows/batch-inventory-item-levels.ts new file mode 100644 index 0000000000000..6a6eeae772151 --- /dev/null +++ b/packages/core/core-flows/src/inventory/workflows/batch-inventory-item-levels.ts @@ -0,0 +1,57 @@ +import { + createWorkflow, + parallelize, + transform, + WorkflowData, + WorkflowResponse, +} from "@medusajs/framework/workflows-sdk" +import { BatchWorkflowInput, InventoryTypes } from "@medusajs/types" +import { createInventoryLevelsStep, updateInventoryLevelsStep } from "../steps" +import { deleteInventoryLevelsWorkflow } from "./delete-inventory-levels" + +export interface BatchInventoryItemLevelsWorkflowInput + extends BatchWorkflowInput< + InventoryTypes.CreateInventoryLevelInput, + InventoryTypes.UpdateInventoryLevelInput + > { + /** + * If true, the workflow will force deletion of the inventory levels, even + * if they have a non-zero stocked quantity. It false, the workflow will + * not delete the inventory levels if they have a non-zero stocked quantity. + * + * Inventory levels that have reserved or incoming items at the location + * will not be deleted even if the force flag is set to true. + * + * @default false + */ + force?: boolean +} + +export const batchInventoryItemLevelsWorkflowId = + "batch-inventory-item-levels-workflow" + +export const batchInventoryItemLevelsWorkflow = createWorkflow( + batchInventoryItemLevelsWorkflowId, + (input: WorkflowData) => { + const res = parallelize( + createInventoryLevelsStep(input.create ?? []), + updateInventoryLevelsStep(input.update ?? []), + deleteInventoryLevelsWorkflow.runAsStep({ + input: { + id: input.delete ?? [], + force: input.force ?? false, + }, + }) + ) + + return new WorkflowResponse( + transform({ res, input }, (data) => { + return { + created: data.res[0], + updated: data.res[1], + deleted: data.input.delete, + } + }) + ) + } +) diff --git a/packages/core/core-flows/src/inventory/workflows/bulk-create-delete-levels.ts b/packages/core/core-flows/src/inventory/workflows/bulk-create-delete-levels.ts index e911e8adf9465..252461074cb75 100644 --- a/packages/core/core-flows/src/inventory/workflows/bulk-create-delete-levels.ts +++ b/packages/core/core-flows/src/inventory/workflows/bulk-create-delete-levels.ts @@ -17,6 +17,8 @@ export const bulkCreateDeleteLevelsWorkflowId = "bulk-create-delete-levels-workflow" /** * This workflow creates and deletes inventory levels. + * + * @deprecated Use `batchInventoryItemLevels` instead. */ export const bulkCreateDeleteLevelsWorkflow = createWorkflow( bulkCreateDeleteLevelsWorkflowId, diff --git a/packages/core/core-flows/src/inventory/workflows/delete-inventory-levels.ts b/packages/core/core-flows/src/inventory/workflows/delete-inventory-levels.ts index 1416929e91888..5cec9319a64f1 100644 --- a/packages/core/core-flows/src/inventory/workflows/delete-inventory-levels.ts +++ b/packages/core/core-flows/src/inventory/workflows/delete-inventory-levels.ts @@ -6,7 +6,10 @@ import { WorkflowResponse, } from "@medusajs/framework/workflows-sdk" -import { FilterableInventoryLevelProps } from "@medusajs/framework/types" +import { + FilterableInventoryLevelProps, + InventoryLevelDTO, +} from "@medusajs/framework/types" import { deduplicate, MedusaError, Modules } from "@medusajs/framework/utils" import { useRemoteQueryStep } from "../../common" import { deleteEntitiesStep } from "../../common/steps/delete-entities" @@ -16,24 +19,52 @@ import { deleteEntitiesStep } from "../../common/steps/delete-entities" */ export const validateInventoryLevelsDelete = createStep( "validate-inventory-levels-delete", - async function ({ inventoryLevels }: { inventoryLevels: any[] }) { - const undeleteableItems = inventoryLevels.filter( - (i) => i.reserved_quantity > 0 || i.stocked_quantity > 0 + async function ({ + inventoryLevels, + force, + }: { + inventoryLevels: InventoryLevelDTO[] + force?: boolean + }) { + const undeleteableDueToReservation = inventoryLevels.filter( + (i) => i.reserved_quantity > 0 || i.incoming_quantity > 0 ) - if (undeleteableItems.length) { - const stockLocationIds = deduplicate( - undeleteableItems.map((item) => item.location_id) + if (undeleteableDueToReservation.length) { + const locationIds = deduplicate( + undeleteableDueToReservation.map((item) => item.location_id) ) + throw new MedusaError( + MedusaError.Types.NOT_ALLOWED, + `Cannot remove Inventory Levels for ${locationIds.join( + ", " + )} because there are reserved or incoming items at the locations` + ) + } + const undeleteableDueToStock = inventoryLevels.filter( + (i) => !force && i.stocked_quantity > 0 + ) + + if (undeleteableDueToStock.length) { + const locationIds = deduplicate( + undeleteableDueToStock.map((item) => item.location_id) + ) throw new MedusaError( MedusaError.Types.NOT_ALLOWED, - `Cannot remove Inventory Levels for ${stockLocationIds} because there are stocked or reserved items at the locations` + `Cannot remove Inventory Levels for ${locationIds.join( + ", " + )} because there are stocked items at the locations. Use force flag to delete anyway.` ) } } ) +export interface DeleteInventoryLevelsWorkflowInput + extends FilterableInventoryLevelProps { + force?: boolean +} + export const deleteInventoryLevelsWorkflowId = "delete-inventory-levels-workflow" /** @@ -41,7 +72,7 @@ export const deleteInventoryLevelsWorkflowId = */ export const deleteInventoryLevelsWorkflow = createWorkflow( deleteInventoryLevelsWorkflowId, - (input: WorkflowData) => { + (input: WorkflowData) => { const inventoryLevels = useRemoteQueryStep({ entry_point: "inventory_levels", fields: ["id", "stocked_quantity", "reserved_quantity", "location_id"], @@ -50,7 +81,7 @@ export const deleteInventoryLevelsWorkflow = createWorkflow( }, }) - validateInventoryLevelsDelete({ inventoryLevels }) + validateInventoryLevelsDelete({ inventoryLevels, force: input.force }) const idsToDelete = transform({ inventoryLevels }, ({ inventoryLevels }) => inventoryLevels.map((il) => il.id) diff --git a/packages/core/core-flows/src/inventory/workflows/index.ts b/packages/core/core-flows/src/inventory/workflows/index.ts index 5d5c413e5dba8..e5cc70b6adb2e 100644 --- a/packages/core/core-flows/src/inventory/workflows/index.ts +++ b/packages/core/core-flows/src/inventory/workflows/index.ts @@ -1,7 +1,8 @@ -export * from "./delete-inventory-items" +export * from "./batch-inventory-item-levels" +export * from "./bulk-create-delete-levels" export * from "./create-inventory-items" export * from "./create-inventory-levels" -export * from "./update-inventory-items" +export * from "./delete-inventory-items" export * from "./delete-inventory-levels" +export * from "./update-inventory-items" export * from "./update-inventory-levels" -export * from "./bulk-create-delete-levels" diff --git a/packages/core/js-sdk/src/admin/inventory-item.ts b/packages/core/js-sdk/src/admin/inventory-item.ts index 8a03c2a74b7c8..99ddf0a784e24 100644 --- a/packages/core/js-sdk/src/admin/inventory-item.ts +++ b/packages/core/js-sdk/src/admin/inventory-item.ts @@ -15,15 +15,15 @@ export class InventoryItem { } /** - * This method creates an inventory item. It sends a request to the + * This method creates an inventory item. It sends a request to the * [Create Inventory Item](https://docs.medusajs.com/api/admin#inventory-items_postinventoryitems) * API route. - * + * * @param body - The inventory item's details. * @param query - Configure the fields to retrieve in the inventory item. * @param headers - Headers to pass in the request. * @returns The inventory item's details. - * + * * @example * sdk.admin.inventoryItem.create({ * sku: "SHIRT" @@ -52,13 +52,13 @@ export class InventoryItem { * This method updates an inventory level. It sends a request to the * [Update Inventory Item](https://docs.medusajs.com/api/admin#inventory-items_postinventoryitemsid) * API route. - * + * * @param id - The inventory item's ID. * @param body - The data to update. * @param query - Configure the fields to retrieve in the inventory item. * @param headers - Headers to pass in the request. * @returns The inventory item's details. - * + * * @example * sdk.admin.inventoryItem.update("iitem_123", { * sku: "SHIRT" @@ -85,28 +85,28 @@ export class InventoryItem { } /** - * This method retrieves a paginated list of inventory items. It sends a request to the + * This method retrieves a paginated list of inventory items. It sends a request to the * [List Inventory Items](https://docs.medusajs.com/api/admin#inventory-items_getinventoryitems) * API route. - * + * * @param query - Filters and pagination configurations. * @param headers - Headers to pass in the request. * @returns The paginated list of inventory items. - * + * * @example * To retrieve the list of inventory items: - * + * * ```ts * sdk.admin.inventoryItem.list() * .then(({ inventory_items, count, limit, offset }) => { * console.log(inventory_items) * }) * ``` - * + * * To configure the pagination, pass the `limit` and `offset` query parameters. - * + * * For example, to retrieve only 10 items and skip 10 items: - * + * * ```ts * sdk.admin.inventoryItem.list({ * limit: 10, @@ -116,10 +116,10 @@ export class InventoryItem { * console.log(inventory_items) * }) * ``` - * + * * Using the `fields` query parameter, you can specify the fields and relations to retrieve * in each inventory item: - * + * * ```ts * sdk.admin.inventoryItem.list({ * fields: "id,*location_levels" @@ -128,7 +128,7 @@ export class InventoryItem { * console.log(inventory_items) * }) * ``` - * + * * Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations). */ async list( @@ -145,26 +145,26 @@ export class InventoryItem { } /** - * This method retrieves an inventory item by its ID. It sends a request to the + * This method retrieves an inventory item by its ID. It sends a request to the * [Get Inventory Item](https://docs.medusajs.com/api/admin#inventory-items_getinventoryitemsid) API route. - * + * * @param id - The inventory item's ID. * @param query - Configure the fields to retrieve in the inventory item. * @param headers - Headers to pass in the request * @returns The inventory item's details. - * + * * @example * To retrieve an inventory item by its ID: - * + * * ```ts * sdk.admin.inventoryItem.retrieve("iitem_123") * .then(({ inventory_item }) => { * console.log(inventory_item) * }) * ``` - * + * * To specify the fields and relations to retrieve: - * + * * ```ts * sdk.admin.inventoryItem.retrieve("iitem_123", { * fields: "id,*location_levels" @@ -173,7 +173,7 @@ export class InventoryItem { * console.log(inventory_item) * }) * ``` - * + * * Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations). */ async retrieve(id: string, query?: SelectParams, headers?: ClientHeaders) { @@ -190,11 +190,11 @@ export class InventoryItem { * This method deletes an inventory item. This sends a request to the * [Delete Inventory Item](https://docs.medusajs.com/api/admin#inventory-items_deleteinventoryitemsid) * API route. - * + * * @param id - The inventory item's ID. * @param headers - Headers to pass in the request * @returns The deletion's details. - * + * * @example * sdk.admin.inventoryItem.delete("iitem_123") * .then(({ deleted }) => { @@ -215,26 +215,26 @@ export class InventoryItem { * This method retrieves a paginated list of inventory levels that belong to an inventory item. * It sends a request to the [List Inventory Items](https://docs.medusajs.com/api/admin#inventory-items_getinventoryitems) * API route. - * + * * @param id - The inventory item's ID. * @param query - Filters and pagination configurations. * @param headers - Headers to pass in the request. * @returns The paginated list of inventory levels. - * + * * @example * To retrieve the list of inventory levels: - * + * * ```ts * sdk.admin.inventoryItem.listLevels("iitem_123") * .then(({ inventory_levels, count, limit, offset }) => { * console.log(inventory_levels) * }) * ``` - * + * * To configure the pagination, pass the `limit` and `offset` query parameters. - * + * * For example, to retrieve only 10 items and skip 10 items: - * + * * ```ts * sdk.admin.inventoryItem.listLevels("iitem_123", { * limit: 10, @@ -244,10 +244,10 @@ export class InventoryItem { * console.log(inventory_levels) * }) * ``` - * + * * Using the `fields` query parameter, you can specify the fields and relations to retrieve * in each inventory level: - * + * * ```ts * sdk.admin.inventoryItem.listLevels("iitem_123", { * fields: "id,*inventory_item" @@ -256,7 +256,7 @@ export class InventoryItem { * console.log(inventory_levels) * }) * ``` - * + * * Learn more about the `fields` property in the [API reference](https://docs.medusajs.com/api/store#select-fields-and-relations). */ async listLevels( @@ -276,18 +276,18 @@ export class InventoryItem { /** * This method updates the inventory level of the specified inventory item and * stock location. - * - * This method sends a request to the + * + * This method sends a request to the * [Update Inventory Level](https://docs.medusajs.com/api/admin#inventory-items_postinventoryitemsidlocationlevelslocation_id) * API route. - * + * * @param id - The inventory item's ID. * @param locationId - The stock location's ID. * @param body - The details to update. * @param query - Configure the fields to retrieve in the inventory item. * @param headers - Headers to pass in the request * @returns The inventory item's details. - * + * * @example * sdk.admin.inventoryItem.updateLevel( * "iitem_123", @@ -321,16 +321,16 @@ export class InventoryItem { /** * This method deletes an inventory level associated with an inventory item * and a stock location. - * - * This method sends a request to the + * + * This method sends a request to the * [Remove Inventory Level](https://docs.medusajs.com/api/admin#inventory-items_deleteinventoryitemsidlocationlevelslocation_id) * API route. - * + * * @param id - The inventory item's ID. * @param locationId - The stock location's ID. * @param headers - Headers to pass in the request * @returns The deletion's details. - * + * * @example * sdk.admin.inventoryItem.deleteLevel( * "iitem_123", @@ -354,13 +354,15 @@ export class InventoryItem { * This method manages the inventory levels of an inventory item. It sends a request to the * [Manage Inventory Levels](https://docs.medusajs.com/api/admin#inventory-items_postinventoryitemsidlocationlevelsbatch) * API route. - * + * + * @deprecated Use `batchInventoryItemLocationLevels` instead. + * * @param id - The inventory item's ID. * @param body - The inventory levels to create or delete. * @param query - Configure the fields to retrieve in the inventory item. * @param headers - Headers to pass in the request * @returns The inventory item's details. - * + * * @example * sdk.admin.inventoryItem.batchUpdateLevels("iitem_123", { * create: [{ @@ -389,4 +391,58 @@ export class InventoryItem { } ) } + + /** + * This method manages the inventory levels of an inventory item. It sends a request to the + * [Manage Inventory Levels](https://docs.medusajs.com/api/admin#inventory-items_postinventoryitemsidlocationlevelsbatch) + * API route. + * + * @param id - The inventory item's ID. + * @param body - The inventory levels to create or delete. + * @param query - Configure the fields to retrieve in the inventory item. + * @param headers - Headers to pass in the request + * @returns The inventory item's details. + * + * @example + * sdk.admin.inventoryItem.batchUpdateInvetoryItemLocationLevels("iitem_123", { + * create: [{ + * location_id: "sloc_123", + * stocked_quantity: 10 + * }], + * delete: ["sloc_123"] + * }) + * .then(({ inventory_item }) => { + * console.log(inventory_item) + * }) + */ + async batchInventoryItemLocationLevels( + id: string, + body: HttpTypes.AdminBatchUpdateInventoryLevelLocation, + query?: SelectParams, + headers?: ClientHeaders + ) { + return await this.client.fetch( + `/admin/inventory-items/${id}/location-levels/batch`, + { + method: "POST", + headers, + body, + query, + } + ) + } + + async batchInventoryItemsLocationLevels( + body: HttpTypes.AdminBatchInventoryItemLevels, + headers?: ClientHeaders + ) { + return await this.client.fetch( + `/admin/inventory-items/location-levels/batch`, + { + method: "POST", + headers, + body, + } + ) + } } diff --git a/packages/core/types/src/http/inventory/admin/payloads.ts b/packages/core/types/src/http/inventory/admin/payloads.ts index f8ce4c3f6eace..7ff9670c7490f 100644 --- a/packages/core/types/src/http/inventory/admin/payloads.ts +++ b/packages/core/types/src/http/inventory/admin/payloads.ts @@ -58,3 +58,16 @@ export interface AdminCreateInventoryItem { } export interface AdminUpdateInventoryItem extends AdminCreateInventoryItem {} + +export interface AdminBatchInventoryItemLevel { + location_id: string + inventory_item_id: string + stocked_quantity?: number + incoming_quantity?: number +} + +export interface AdminBatchInventoryItemLevels { + create: AdminBatchInventoryItemLevel[] + update: AdminBatchInventoryItemLevel[] + delete: string[] +} diff --git a/packages/core/types/src/inventory/mutations/inventory-level.ts b/packages/core/types/src/inventory/mutations/inventory-level.ts index 797d82ed46955..9d519c46baecc 100644 --- a/packages/core/types/src/inventory/mutations/inventory-level.ts +++ b/packages/core/types/src/inventory/mutations/inventory-level.ts @@ -29,6 +29,14 @@ export interface UpdateInventoryLevelInput { * id of the inventory level to update */ id?: string + /** + * The ID of the associated inventory item. + */ + inventory_item_id: string + /** + * The ID of the associated location. + */ + location_id: string /** * The stocked quantity of the associated inventory item in the associated location. */ diff --git a/packages/medusa/src/api/admin/inventory-items/location-levels/batch/route.ts b/packages/medusa/src/api/admin/inventory-items/location-levels/batch/route.ts new file mode 100644 index 0000000000000..8b4f1b27540e6 --- /dev/null +++ b/packages/medusa/src/api/admin/inventory-items/location-levels/batch/route.ts @@ -0,0 +1,20 @@ +import { batchInventoryItemLevelsWorkflow } from "@medusajs/core-flows" +import { MedusaRequest, MedusaResponse } from "@medusajs/framework" +import { AdminBatchInventoryItemLevelsType } from "../../validators" + +export const POST = async ( + req: MedusaRequest, + res: MedusaResponse +) => { + const body = req.validatedBody + + const output = await batchInventoryItemLevelsWorkflow(req.scope).run({ + input: body, + }) + + res.json({ + created: output.result.created, + updated: output.result.updated, + deleted: output.result.deleted, + }) +} diff --git a/packages/medusa/src/api/admin/inventory-items/middlewares.ts b/packages/medusa/src/api/admin/inventory-items/middlewares.ts index 8394289723e5a..573eedac50c36 100644 --- a/packages/medusa/src/api/admin/inventory-items/middlewares.ts +++ b/packages/medusa/src/api/admin/inventory-items/middlewares.ts @@ -7,6 +7,7 @@ import { DEFAULT_BATCH_ENDPOINTS_SIZE_LIMIT } from "../../../utils/middlewares" import { createBatchBody } from "../../utils/validators" import * as QueryConfig from "./query-config" import { + AdminBatchInventoryItemLevels, AdminCreateInventoryItem, AdminCreateInventoryLocationLevel, AdminGetInventoryItemParams, @@ -49,6 +50,22 @@ export const adminInventoryRoutesMiddlewares: MiddlewareRoute[] = [ ), ], }, + { + method: ["POST"], + matcher: "/admin/inventory-items/batch", + bodyParser: { + sizeLimit: DEFAULT_BATCH_ENDPOINTS_SIZE_LIMIT, + }, + middlewares: [validateAndTransformBody(AdminBatchInventoryItemLevels)], + }, + { + method: ["POST"], + matcher: "/admin/inventory-items/location-levels/batch", + bodyParser: { + sizeLimit: DEFAULT_BATCH_ENDPOINTS_SIZE_LIMIT, + }, + middlewares: [validateAndTransformBody(AdminBatchInventoryItemLevels)], + }, { method: ["POST"], matcher: "/admin/inventory-items/:id", diff --git a/packages/medusa/src/api/admin/inventory-items/validators.ts b/packages/medusa/src/api/admin/inventory-items/validators.ts index 2b522f15a6117..204641d760033 100644 --- a/packages/medusa/src/api/admin/inventory-items/validators.ts +++ b/packages/medusa/src/api/admin/inventory-items/validators.ts @@ -129,3 +129,20 @@ export const AdminUpdateInventoryItem = z metadata: z.record(z.unknown()).nullish(), }) .strict() + +const AdminBatchInventoryLocationLevel = z.object({ + inventory_item_id: z.string(), + location_id: z.string(), + stocked_quantity: z.number().min(0).optional(), + incoming_quantity: z.number().min(0).optional(), +}) + +export const AdminBatchInventoryItemLevels = z.object({ + create: z.array(AdminBatchInventoryLocationLevel).optional(), + update: z.array(AdminBatchInventoryLocationLevel).optional(), + delete: z.array(z.string()).optional(), +}) + +export type AdminBatchInventoryItemLevelsType = z.infer< + typeof AdminBatchInventoryItemLevels +> diff --git a/packages/modules/inventory/src/services/inventory-module.ts b/packages/modules/inventory/src/services/inventory-module.ts index e3ac99cf439f6..09fb5e3756b40 100644 --- a/packages/modules/inventory/src/services/inventory-module.ts +++ b/packages/modules/inventory/src/services/inventory-module.ts @@ -603,16 +603,13 @@ export default class InventoryModuleService return acc }, new Map()) - return await this.inventoryLevelService_.update( - updates.map((update) => { - const id = levelMap - .get(update.inventory_item_id) - .get(update.location_id) - - return { id, ...update } - }), - context - ) + const updatesWithIds = updates.map((update) => { + const id = levelMap.get(update.inventory_item_id).get(update.location_id) + + return { id, ...update } + }) + + return await this.inventoryLevelService_.update(updatesWithIds, context) } /** From ee2dc970a201e549bc05aced712e4ec81d98f6b4 Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 17 Dec 2024 11:03:46 +0100 Subject: [PATCH 02/19] progress --- .../components/data-grid-duplicate-cell.tsx | 26 +++--- .../data-grid-toggleable-number-cell.tsx | 25 ++++-- .../src/components/data-grid/hooks/index.ts | 1 + .../hooks/use-data-grid-clipboard-events.tsx | 9 +- .../hooks/use-data-grid-duplicate-cell.tsx | 18 ++++ .../hooks/use-data-grid-form-handlers.tsx | 84 ++++++++++++++++++- .../models/data-grid-bulk-update-command.ts | 16 ++-- .../src/components/data-grid/types.ts | 6 ++ .../dashboard/src/i18n/translations/en.json | 9 ++ .../providers/router-provider/route-map.tsx | 4 +- .../customer-detail/customer-detail.tsx | 2 +- .../product-variant-section.tsx | 6 +- .../use-variant-table-columns.tsx | 14 ++-- .../product-inventory-form/index.ts | 1 - .../products/product-inventory/index.ts | 1 - .../products/product-inventory/schema.ts | 32 ------- .../components/product-stock-form/index.ts | 1 + .../product-stock-form.tsx} | 37 ++++---- .../hooks/use-product-inventory-data.tsx | 0 .../hooks/use-product-stock-columns.tsx} | 46 +++++----- .../routes/products/product-stock/index.ts | 1 + .../product-stock.tsx} | 14 +++- .../routes/products/product-stock/schema.ts | 33 ++++++++ .../types.ts | 0 .../utils.ts | 0 .../inventory/mutations/inventory-level.ts | 2 +- 26 files changed, 265 insertions(+), 123 deletions(-) create mode 100644 packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-duplicate-cell.tsx delete mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/index.ts delete mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/index.ts delete mode 100644 packages/admin/dashboard/src/routes/products/product-inventory/schema.ts create mode 100644 packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/index.ts rename packages/admin/dashboard/src/routes/products/{product-inventory/components/product-inventory-form/product-inventory-form.tsx => product-stock/components/product-stock-form/product-stock-form.tsx} (84%) rename packages/admin/dashboard/src/routes/products/{product-inventory => product-stock}/hooks/use-product-inventory-data.tsx (100%) rename packages/admin/dashboard/src/routes/products/{product-inventory/hooks/use-product-inventory-columns.tsx => product-stock/hooks/use-product-stock-columns.tsx} (85%) create mode 100644 packages/admin/dashboard/src/routes/products/product-stock/index.ts rename packages/admin/dashboard/src/routes/products/{product-inventory/product-inventory.tsx => product-stock/product-stock.tsx} (54%) create mode 100644 packages/admin/dashboard/src/routes/products/product-stock/schema.ts rename packages/admin/dashboard/src/routes/products/{product-inventory => product-stock}/types.ts (100%) rename packages/admin/dashboard/src/routes/products/{product-inventory => product-stock}/utils.ts (100%) diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-duplicate-cell.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-duplicate-cell.tsx index fc5577cd48ab0..19e8218fef852 100644 --- a/packages/admin/dashboard/src/components/data-grid/components/data-grid-duplicate-cell.tsx +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-duplicate-cell.tsx @@ -1,23 +1,21 @@ import { ReactNode } from "react" -import { useWatch } from "react-hook-form" -import { useDataGridCell } from "../hooks" -import { DataGridCellProps } from "../types" +import { useDataGridDuplicateCell } from "../hooks" -export const DataGridDuplicateCell = ({ - context, - children, -}: DataGridCellProps & { +interface DataGridDuplicateCellProps { + duplicateOf: string children?: ReactNode | ((props: { value: TValue }) => ReactNode) -}) => { - const { field, control } = useDataGridCell({ - context, - }) - - const value = useWatch({ control, name: field }) +} +export const DataGridDuplicateCell = ({ + duplicateOf, + children, +}: DataGridDuplicateCellProps) => { + const { watchedValue } = useDataGridDuplicateCell({ duplicateOf }) return (
- {typeof children === "function" ? children({ value: value }) : children} + {typeof children === "function" + ? children({ value: watchedValue }) + : children}
) } diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx index d131fbc01b0ed..675d6d590db7a 100644 --- a/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx @@ -3,6 +3,7 @@ import { useEffect, useRef, useState } from "react" import CurrencyInput, { CurrencyInputProps } from "react-currency-input-field" import { Controller, ControllerRenderProps } from "react-hook-form" import { useCombinedRefs } from "../../../hooks/use-combined-refs" +import { ConditionalTooltip } from "../../common/conditional-tooltip" import { useDataGridCell, useDataGridCellError } from "../hooks" import { DataGridCellProps, InputProps } from "../types" import { DataGridCellContainer } from "./data-grid-cell-container" @@ -85,15 +86,21 @@ const OuterComponent = ({ }, [isAnchor]) return ( -
- -
+ +
+ +
+
) } diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/index.ts b/packages/admin/dashboard/src/components/data-grid/hooks/index.ts index f03d7f838ef72..2307c30c866e5 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/index.ts +++ b/packages/admin/dashboard/src/components/data-grid/hooks/index.ts @@ -5,6 +5,7 @@ export * from "./use-data-grid-cell-metadata" export * from "./use-data-grid-cell-snapshot" export * from "./use-data-grid-clipboard-events" export * from "./use-data-grid-column-visibility" +export * from "./use-data-grid-duplicate-cell" export * from "./use-data-grid-error-highlighting" export * from "./use-data-grid-form-handlers" export * from "./use-data-grid-keydown-event" diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-clipboard-events.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-clipboard-events.tsx index 301d578f66a55..d8170b48740fc 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-clipboard-events.tsx +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-clipboard-events.tsx @@ -45,7 +45,14 @@ export const useDataGridClipboardEvents = < const fields = matrix.getFieldsInSelection(anchor, rangeEnd) const values = getSelectionValues(fields) - const text = values.map((value) => `${value}` ?? "").join("\t") + const text = values + .map((value) => { + if (typeof value === "object" && value !== null) { + return JSON.stringify(value) + } + return `${value}` ?? "" + }) + .join("\t") e.clipboardData?.setData("text/plain", text) }, diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-duplicate-cell.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-duplicate-cell.tsx new file mode 100644 index 0000000000000..4244466c4aa4e --- /dev/null +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-duplicate-cell.tsx @@ -0,0 +1,18 @@ +import { useWatch } from "react-hook-form" +import { useDataGridContext } from "../context" + +interface UseDataGridDuplicateCellOptions { + duplicateOf: string +} + +export const useDataGridDuplicateCell = ({ + duplicateOf, +}: UseDataGridDuplicateCellOptions) => { + const { control } = useDataGridContext() + + const watchedValue = useWatch({ control, name: duplicateOf }) + + return { + watchedValue, + } +} diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx index f1224420cfb1a..22fb519759eb9 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx @@ -1,9 +1,14 @@ +import get from "lodash/get" import set from "lodash/set" import { useCallback } from "react" import { FieldValues, Path, PathValue, UseFormReturn } from "react-hook-form" import { DataGridMatrix } from "../models" -import { DataGridColumnType, DataGridCoordinates } from "../types" +import { + DataGridColumnType, + DataGridCoordinates, + DataGridToggleableNumber, +} from "../types" type UseDataGridFormHandlersOptions = { matrix: DataGridMatrix @@ -28,6 +33,7 @@ export const useDataGridFormHandlers = < } const allValues = getValues() + return fields.map((field) => { return field.split(".").reduce((obj, key) => obj?.[key], allValues) }) as PathValue>[] @@ -36,7 +42,7 @@ export const useDataGridFormHandlers = < ) const setSelectionValues = useCallback( - async (fields: string[], values: string[]) => { + async (fields: string[], values: string[], isHistory?: boolean) => { if (!fields.length || !anchor) { return } @@ -55,9 +61,9 @@ export const useDataGridFormHandlers = < } const valueIndex = index % values.length - const value = convertedValues[valueIndex] + const newValue = convertedValues[valueIndex] - set(currentValues, field, value) + setValue(currentValues, field, newValue, type, isHistory) }) reset(currentValues, { @@ -115,6 +121,74 @@ function covertToString(value: any): string { return String(value) } +function convertToggleableNumber(value: any): { + quantity: number + checked: boolean + disabledToggle: boolean +} { + let obj = value + + if (typeof obj === "string") { + try { + obj = JSON.parse(obj) + } catch (error) { + throw new Error(`String "${value}" cannot be converted to object.`) + } + } + + return obj +} + +function setValue< + T extends DataGridToggleableNumber = DataGridToggleableNumber +>( + currentValues: any, + field: string, + newValue: T, + type: string, + /** + * If an value is being set by a history command, we should not check + * for any conditions whether the value is allowed to be changed. + */ + isHistory?: boolean +) { + const currentValue = get(currentValues, field) + + if (type === "togglable-number") { + if (isHistory) { + set(currentValues, `${field}.quantity`, newValue.quantity) + set(currentValues, `${field}.checked`, newValue.checked) + return + } + + const currentChecked = currentValue.checked + const disabledToggle = currentValue.disabledToggle + + const newQuantityNumber = + newValue.quantity != null && newValue.quantity !== "" + ? Number(newValue.quantity) + : null + + // Determine if checked should be updated + let shouldUpdateChecked = false + if (!disabledToggle && newQuantityNumber != null) { + if (currentChecked === false && newQuantityNumber > 0) { + shouldUpdateChecked = true + } + } + + set(currentValues, field, { + ...currentValue, + quantity: newValue.quantity, + checked: shouldUpdateChecked ? true : currentChecked, + }) + + return + } + + set(currentValues, field, newValue) +} + export function convertArrayToPrimitive( values: any[], type: DataGridColumnType @@ -132,6 +206,8 @@ export function convertArrayToPrimitive( return convertToNumber(v) }) + case "togglable-number": + return values.map(convertToggleableNumber) case "boolean": return values.map(convertToBoolean) case "text": diff --git a/packages/admin/dashboard/src/components/data-grid/models/data-grid-bulk-update-command.ts b/packages/admin/dashboard/src/components/data-grid/models/data-grid-bulk-update-command.ts index 8c5355f10cf34..426b7ea4671fd 100644 --- a/packages/admin/dashboard/src/components/data-grid/models/data-grid-bulk-update-command.ts +++ b/packages/admin/dashboard/src/components/data-grid/models/data-grid-bulk-update-command.ts @@ -4,7 +4,7 @@ export type DataGridBulkUpdateCommandArgs = { fields: string[] next: any[] prev: any[] - setter: (fields: string[], values: any[]) => void + setter: (fields: string[], values: any[], isHistory?: boolean) => void } export class DataGridBulkUpdateCommand implements Command { @@ -13,7 +13,11 @@ export class DataGridBulkUpdateCommand implements Command { private _prev: any[] private _next: any[] - private _setter: (fields: string[], any: string[]) => void + private _setter: ( + fields: string[], + values: any[], + isHistory?: boolean + ) => void constructor({ fields, prev, next, setter }: DataGridBulkUpdateCommandArgs) { this._fields = fields @@ -22,13 +26,13 @@ export class DataGridBulkUpdateCommand implements Command { this._setter = setter } - execute(): void { - this._setter(this._fields, this._next) + execute(redo = false): void { + this._setter(this._fields, this._next, redo) } undo(): void { - this._setter(this._fields, this._prev) + this._setter(this._fields, this._prev, true) } redo(): void { - this.execute() + this.execute(true) } } diff --git a/packages/admin/dashboard/src/components/data-grid/types.ts b/packages/admin/dashboard/src/components/data-grid/types.ts index 857396584ea8a..8ddc4a419d2f6 100644 --- a/packages/admin/dashboard/src/components/data-grid/types.ts +++ b/packages/admin/dashboard/src/components/data-grid/types.ts @@ -164,3 +164,9 @@ export type GridColumnOption = { checked: boolean disabled: boolean } + +export type DataGridToggleableNumber = { + quantity: number | string + checked: boolean + disabledToggle: boolean +} diff --git a/packages/admin/dashboard/src/i18n/translations/en.json b/packages/admin/dashboard/src/i18n/translations/en.json index d1889efe557c7..576c7a043f4ad 100644 --- a/packages/admin/dashboard/src/i18n/translations/en.json +++ b/packages/admin/dashboard/src/i18n/translations/en.json @@ -645,6 +645,15 @@ } } }, + "stock": { + "heading": "Manage product stock levels and locations", + "description": "Update the stocked inventory levels for all of the product's variants.", + "action": "Edit stock levels", + "tooltips": { + "alreadyManaged": "This inventory item is already editable under {{title}}.", + "alreadyManagedWithSku": "This inventory item is already editable under {{title}} ({{sku}})." + } + }, "toasts": { "delete": { "success": { diff --git a/packages/admin/dashboard/src/providers/router-provider/route-map.tsx b/packages/admin/dashboard/src/providers/router-provider/route-map.tsx index f622d165812e3..0d47e75cbc5ef 100644 --- a/packages/admin/dashboard/src/providers/router-provider/route-map.tsx +++ b/packages/admin/dashboard/src/providers/router-provider/route-map.tsx @@ -130,9 +130,9 @@ export const RouteMap: RouteObject[] = [ ), }, { - path: "inventory", + path: "stock", lazy: () => - import("../../routes/products/product-inventory"), + import("../../routes/products/product-stock"), }, { path: "metadata/edit", diff --git a/packages/admin/dashboard/src/routes/customers/customer-detail/customer-detail.tsx b/packages/admin/dashboard/src/routes/customers/customer-detail/customer-detail.tsx index f0ba697228e2e..4c77a5d99cb8d 100644 --- a/packages/admin/dashboard/src/routes/customers/customer-detail/customer-detail.tsx +++ b/packages/admin/dashboard/src/routes/customers/customer-detail/customer-detail.tsx @@ -6,8 +6,8 @@ import { useDashboardExtension } from "../../../extensions" import { useCustomer } from "../../../hooks/api/customers" import { CustomerGeneralSection } from "./components/customer-general-section" import { CustomerGroupSection } from "./components/customer-group-section" -import { customerLoader } from "./loader" import { CustomerOrderSection } from "./components/customer-order-section" +import { customerLoader } from "./loader" export const CustomerDetail = () => { const { id } = useParams() diff --git a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx index c61ee42337b3e..9c0870bd7fa73 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx +++ b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx @@ -87,8 +87,8 @@ export const ProductVariantSection = ({ icon: , }, { - label: "Edit inventory items", - to: `inventory`, + label: t("products.stock.action"), + to: `stock`, icon: , }, ], @@ -123,7 +123,7 @@ export const ProductVariantSection = ({ ).join(",")}` ) }, - label: "Edit inventory", + label: t("products.stock.action"), shortcut: "i", }, ]} diff --git a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/use-variant-table-columns.tsx b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/use-variant-table-columns.tsx index e5949cb3552fc..3c6994645e796 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/use-variant-table-columns.tsx +++ b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/use-variant-table-columns.tsx @@ -73,11 +73,6 @@ const VariantActions = ({ to: `edit-variant?variant_id=${variant.id}`, icon: , }, - { - label: t("actions.delete"), - onClick: handleDelete, - icon: , - }, hasInventoryItem ? { label: t("products.variant.inventory.actions.inventoryItems"), @@ -94,6 +89,15 @@ const VariantActions = ({ : false, ].filter(Boolean) as Action[], }, + { + actions: [ + { + label: t("actions.delete"), + onClick: handleDelete, + icon: , + }, + ], + }, ]} /> ) diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/index.ts b/packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/index.ts deleted file mode 100644 index da2f5b485d5cd..0000000000000 --- a/packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./product-inventory-form" diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/index.ts b/packages/admin/dashboard/src/routes/products/product-inventory/index.ts deleted file mode 100644 index 7731a0089e863..0000000000000 --- a/packages/admin/dashboard/src/routes/products/product-inventory/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { ProductInventory as Component } from "./product-inventory" diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/schema.ts b/packages/admin/dashboard/src/routes/products/product-inventory/schema.ts deleted file mode 100644 index d4aab6d5069a5..0000000000000 --- a/packages/admin/dashboard/src/routes/products/product-inventory/schema.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { z } from "zod" - -const LocationQuantitySchema = z.object({ - levels_id: z.string().optional(), - quantity: z.union([z.number(), z.string()]), - checked: z.boolean(), -}) - -const ProductInventoryLocationsSchema = z.record(LocationQuantitySchema) - -const ProductInventoryInventoryItemSchema = z.object({ - locations: ProductInventoryLocationsSchema, -}) - -const ProductInventoryVariantSchema = z.object({ - inventory_items: z.record(ProductInventoryInventoryItemSchema), -}) - -export const ProductInventorySchema = z.object({ - variants: z.record(ProductInventoryVariantSchema), -}) - -export type ProductVariantLocationSchema = z.infer< - typeof ProductInventoryLocationsSchema -> -export type ProductInventoryInventoryItemSchema = z.infer< - typeof ProductInventoryInventoryItemSchema -> -export type ProductInventoryVariantSchema = z.infer< - typeof ProductInventoryVariantSchema -> -export type ProductInventorySchema = z.infer diff --git a/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/index.ts b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/index.ts new file mode 100644 index 0000000000000..d65f902d56e22 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/index.ts @@ -0,0 +1 @@ +export * from "./product-stock-form" diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/product-inventory-form.tsx b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx similarity index 84% rename from packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/product-inventory-form.tsx rename to packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx index b55955c0a41ab..9443a77a70e9f 100644 --- a/packages/admin/dashboard/src/routes/products/product-inventory/components/product-inventory-form/product-inventory-form.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx @@ -12,12 +12,12 @@ import { import { KeyboundForm } from "../../../../../components/utilities/keybound-form" import { useBatchInventoryLevels } from "../../../../../hooks/api" import { castNumber } from "../../../../../lib/cast-number" -import { useProductInventoryColumns } from "../../hooks/use-product-inventory-columns" +import { useProductStockColumns } from "../../hooks/use-product-stock-columns" import { - ProductInventoryInventoryItemSchema, - ProductInventorySchema, - ProductInventoryVariantSchema, - ProductVariantLocationSchema, + ProductStockInventoryItemSchema, + ProductStockLocationSchema, + ProductStockSchema, + ProductStockVariantSchema, } from "../../schema" import { ProductVariantInventoryItemLink } from "../../types" import { @@ -25,23 +25,23 @@ import { isProductVariantWithInventoryPivot, } from "../../utils" -type ProductInventoryFormProps = { +type ProductStockFormProps = { variants: HttpTypes.AdminProductVariant[] locations: HttpTypes.AdminStockLocation[] } -export const ProductInventoryForm = ({ +export const ProductStockForm = ({ variants, locations, -}: ProductInventoryFormProps) => { +}: ProductStockFormProps) => { const { t } = useTranslation() const { setCloseOnEscape } = useRouteModal() const { handleSuccess } = useRouteModal() - const form = useForm({ + const form = useForm({ // TODO: Update ProductVariant type to include inventory_items defaultValues: getDefaultValue(variants as any, locations), - resolver: zodResolver(ProductInventorySchema), + resolver: zodResolver(ProductStockSchema), }) const initialValues = useRef(getDefaultValue(variants as any, locations)) @@ -50,7 +50,7 @@ export const ProductInventoryForm = ({ () => getDisabledInventoryRows(variants as any), [variants] ) - const columns = useProductInventoryColumns(locations, disabled) + const columns = useProductStockColumns(locations, disabled) const { mutateAsync, isPending } = useBatchInventoryLevels() @@ -107,9 +107,9 @@ export const ProductInventoryForm = ({ return ( - + - + { +): DefaultValues { return { variants: variants.reduce((variantAcc, variant) => { const inventoryItems = variant.inventory_items.reduce((itemAcc, item) => { @@ -161,16 +161,19 @@ function getDefaultValue( quantity: levels?.stocked_quantity || "", levels_id: levels?.id, checked: !!levels, + disabledToggle: + (levels?.incoming_quantity || 0) > 0 || + (levels?.reserved_quantity || 0) > 0, } return locationAcc - }, {} as ProductVariantLocationSchema) + }, {} as ProductStockLocationSchema) itemAcc[item.inventory_item_id] = { locations: locationsMap } return itemAcc - }, {} as Record) + }, {} as Record) variantAcc[variant.id] = { inventory_items: inventoryItems } return variantAcc - }, {} as Record), + }, {} as Record), } } diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-data.tsx b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-inventory-data.tsx similarity index 100% rename from packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-data.tsx rename to packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-inventory-data.tsx diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-columns.tsx b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx similarity index 85% rename from packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-columns.tsx rename to packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx index 864ee45ab1dc0..c79bd98252bc4 100644 --- a/packages/admin/dashboard/src/routes/products/product-inventory/hooks/use-product-inventory-columns.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx @@ -2,18 +2,20 @@ import { InformationCircle } from "@medusajs/icons" import { HttpTypes } from "@medusajs/types" import { Switch, Tooltip } from "@medusajs/ui" import { useCallback, useMemo } from "react" + +import { useTranslation } from "react-i18next" import { Thumbnail } from "../../../../components/common/thumbnail" import { createDataGridHelper } from "../../../../components/data-grid" import { DataGridReadOnlyCell } from "../../../../components/data-grid/components" import { DataGridDuplicateCell } from "../../../../components/data-grid/components/data-grid-duplicate-cell" import { DataGridTogglableNumberCell } from "../../../../components/data-grid/components/data-grid-toggleable-number-cell" -import { ProductInventorySchema } from "../schema" +import { ProductStockSchema } from "../schema" import { ProductVariantInventoryItemLink } from "../types" import { isProductVariant } from "../utils" const helper = createDataGridHelper< HttpTypes.AdminProductVariant | ProductVariantInventoryItemLink, - ProductInventorySchema + ProductStockSchema >() type DisabledItem = { id: string; title: string; sku: string } @@ -27,10 +29,11 @@ type DisabledResult = item: undefined } -export const useProductInventoryColumns = ( +export const useProductStockColumns = ( locations: HttpTypes.AdminStockLocation[] = [], disabled: Record = {} ) => { + const { t } = useTranslation() const getIsDisabled = useCallback( (item: ProductVariantInventoryItemLink): DisabledResult => { const disabledItem = disabled[item.inventory_item_id] @@ -84,9 +87,16 @@ export const useProductInventoryColumns = ( {item.inventory.title || "-"} @@ -148,10 +158,10 @@ export const useProductInventoryColumns = ( return null } - const { isDisabled, item: disabledItem } = getIsDisabled(item) + const { isDisabled } = getIsDisabled(item) if (isDisabled) { - return `variants.${disabledItem.id}.inventory_items.${item.inventory_item_id}.locations.${location.id}` as const + return null } return `variants.${item.variant_id}.inventory_items.${item.inventory_item_id}.locations.${location.id}` as const @@ -164,11 +174,13 @@ export const useProductInventoryColumns = ( return } - const { isDisabled } = getIsDisabled(item) + const { isDisabled, item: disabledItem } = getIsDisabled(item) if (isDisabled) { return ( - + {({ value }) => { const { checked, quantity } = value as { checked: boolean @@ -193,23 +205,11 @@ export const useProductInventoryColumns = ( ) } - // Depending on how we want to handle the checked state, we might need - // to move this to the form state. - // const locationLevel = item.inventory.location_levels?.find( - // (level) => level.location_id === location.id - // ) - - // const disableToggle = Boolean( - // locationLevel && - // (locationLevel.reserved_quantity > 0 || - // locationLevel.incoming_quantity > 0) - // ) - return }, }) ), ], - [locations, getIsDisabled] + [locations, getIsDisabled, t] ) } diff --git a/packages/admin/dashboard/src/routes/products/product-stock/index.ts b/packages/admin/dashboard/src/routes/products/product-stock/index.ts new file mode 100644 index 0000000000000..cdefbb9aaeebb --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-stock/index.ts @@ -0,0 +1 @@ +export { ProductStock as Component } from "./product-stock" diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/product-inventory.tsx b/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx similarity index 54% rename from packages/admin/dashboard/src/routes/products/product-inventory/product-inventory.tsx rename to packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx index c8513466d4eb7..107365c5d31e7 100644 --- a/packages/admin/dashboard/src/routes/products/product-inventory/product-inventory.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx @@ -1,10 +1,12 @@ +import { useTranslation } from "react-i18next" import { useParams, useSearchParams } from "react-router-dom" import { RouteFocusModal } from "../../../components/modals" import { PRODUCT_VARIANT_IDS_KEY } from "../common/constants" -import { ProductInventoryForm } from "./components/product-inventory-form" +import { ProductStockForm } from "./components/product-stock-form" import { useProductInventoryData } from "./hooks/use-product-inventory-data" -export const ProductInventory = () => { +export const ProductStock = () => { + const { t } = useTranslation() const { id } = useParams<{ id: string }>() const [searchParams] = useSearchParams() @@ -18,8 +20,14 @@ export const ProductInventory = () => { return ( + + {t("products.stock.heading")} + + + {t("products.stock.description")} + {isLoaded && ( - + )} ) diff --git a/packages/admin/dashboard/src/routes/products/product-stock/schema.ts b/packages/admin/dashboard/src/routes/products/product-stock/schema.ts new file mode 100644 index 0000000000000..efd7becf47d04 --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-stock/schema.ts @@ -0,0 +1,33 @@ +import { z } from "zod" + +const LocationQuantitySchema = z.object({ + levels_id: z.string().optional(), + quantity: z.union([z.number(), z.string()]), + checked: z.boolean(), + disabledToggle: z.boolean(), +}) + +const ProductStockLocationsSchema = z.record(LocationQuantitySchema) + +const ProductStockInventoryItemSchema = z.object({ + locations: ProductStockLocationsSchema, +}) + +const ProductStockVariantSchema = z.object({ + inventory_items: z.record(ProductStockInventoryItemSchema), +}) + +export const ProductStockSchema = z.object({ + variants: z.record(ProductStockVariantSchema), +}) + +export type ProductStockLocationSchema = z.infer< + typeof ProductStockLocationsSchema +> +export type ProductStockInventoryItemSchema = z.infer< + typeof ProductStockInventoryItemSchema +> +export type ProductStockVariantSchema = z.infer< + typeof ProductStockVariantSchema +> +export type ProductStockSchema = z.infer diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/types.ts b/packages/admin/dashboard/src/routes/products/product-stock/types.ts similarity index 100% rename from packages/admin/dashboard/src/routes/products/product-inventory/types.ts rename to packages/admin/dashboard/src/routes/products/product-stock/types.ts diff --git a/packages/admin/dashboard/src/routes/products/product-inventory/utils.ts b/packages/admin/dashboard/src/routes/products/product-stock/utils.ts similarity index 100% rename from packages/admin/dashboard/src/routes/products/product-inventory/utils.ts rename to packages/admin/dashboard/src/routes/products/product-stock/utils.ts diff --git a/packages/core/types/src/inventory/mutations/inventory-level.ts b/packages/core/types/src/inventory/mutations/inventory-level.ts index 9d519c46baecc..d8a43c2d57f19 100644 --- a/packages/core/types/src/inventory/mutations/inventory-level.ts +++ b/packages/core/types/src/inventory/mutations/inventory-level.ts @@ -26,7 +26,7 @@ export interface CreateInventoryLevelInput { */ export interface UpdateInventoryLevelInput { /** - * id of the inventory level to update + * ID of the inventory level to update */ id?: string /** From 6ef581ce17612695c7b788d1e5bf9f76d126360f Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 17 Dec 2024 13:38:59 +0100 Subject: [PATCH 03/19] cleanup types --- .../data-grid-toggleable-number-cell.tsx | 13 ++- .../dashboard/src/hooks/api/inventory.tsx | 19 +++-- .../components/manage-locations-form.tsx | 4 +- .../product-stock-form/product-stock-form.tsx | 38 +++++---- .../steps/update-inventory-levels.ts | 7 +- .../workflows/bulk-create-delete-levels.ts | 2 + .../workflows/delete-inventory-levels.ts | 13 ++- .../workflows/update-inventory-levels.ts | 2 +- .../core/js-sdk/src/admin/inventory-item.ts | 33 ++++++-- .../http/inventory-level/admin/payloads.ts | 80 +++++++++++++++++-- .../src/http/inventory/admin/payloads.ts | 13 --- .../inventory/mutations/inventory-level.ts | 18 +---- packages/core/types/src/inventory/service.ts | 12 +-- .../[id]/location-levels/batch/route.ts | 42 +++++----- .../api/admin/inventory-items/validators.ts | 37 +++++++-- .../src/services/inventory-module.ts | 10 +-- 16 files changed, 226 insertions(+), 117 deletions(-) diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx index 675d6d590db7a..34887731c381e 100644 --- a/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx @@ -133,13 +133,20 @@ const Inner = ({ const combinedRefs = useCombinedRefs(inputRef, ref) const handleInputChange: CurrencyInputProps["onValueChange"] = ( - value, + updatedValue, _name, _values ) => { - const ensuredValue = value || "" - + const ensuredValue = updatedValue || "" const newValue = { ...localValue, quantity: ensuredValue } + + /** + * If the value is not empty, then the location should be enabled. + */ + if (ensuredValue !== "") { + newValue.checked = true + } + setLocalValue(newValue) } diff --git a/packages/admin/dashboard/src/hooks/api/inventory.tsx b/packages/admin/dashboard/src/hooks/api/inventory.tsx index 8a73f4c42ebbc..ca0a47cf17a3d 100644 --- a/packages/admin/dashboard/src/hooks/api/inventory.tsx +++ b/packages/admin/dashboard/src/hooks/api/inventory.tsx @@ -211,17 +211,20 @@ export const useUpdateInventoryLevel = ( }) } -export const useBatchUpdateInventoryLevels = ( +export const useBatchInventoryItemLocationLevels = ( inventoryItemId: string, options?: UseMutationOptions< HttpTypes.AdminInventoryItemResponse, FetchError, - HttpTypes.AdminBatchUpdateInventoryLevelLocation + HttpTypes.AdminBatchInventoryItemLocationLevels > ) => { return useMutation({ - mutationFn: (payload: HttpTypes.AdminBatchUpdateInventoryLevelLocation) => - sdk.admin.inventoryItem.batchUpdateLevels(inventoryItemId, payload), + mutationFn: (payload) => + sdk.admin.inventoryItem.batchInventoryItemLocationLevels( + inventoryItemId, + payload + ), onSuccess: (data, variables, context) => { queryClient.invalidateQueries({ queryKey: inventoryItemsQueryKeys.lists(), @@ -238,16 +241,16 @@ export const useBatchUpdateInventoryLevels = ( }) } -export const useBatchInventoryLevels = ( +export const useBatchInventoryItemsLocationLevels = ( options?: UseMutationOptions< HttpTypes.AdminInventoryItemResponse, FetchError, - HttpTypes.AdminBatchInventoryItemLevels + HttpTypes.AdminBatchInventoryItemsLocationLevels > ) => { return useMutation({ - mutationFn: (payload: HttpTypes.AdminBatchInventoryItemLevels) => - sdk.admin.inventoryItem._batchUpdateLevels(payload), + mutationFn: (payload) => + sdk.admin.inventoryItem.batchInventoryItemsLocationLevels(payload), onSuccess: (data, variables, context) => { queryClient.invalidateQueries({ queryKey: inventoryItemsQueryKeys.all, diff --git a/packages/admin/dashboard/src/routes/inventory/inventory-detail/components/manage-locations/components/manage-locations-form.tsx b/packages/admin/dashboard/src/routes/inventory/inventory-detail/components/manage-locations/components/manage-locations-form.tsx index cbc31818828e8..d332ca98e1c39 100644 --- a/packages/admin/dashboard/src/routes/inventory/inventory-detail/components/manage-locations/components/manage-locations-form.tsx +++ b/packages/admin/dashboard/src/routes/inventory/inventory-detail/components/manage-locations/components/manage-locations-form.tsx @@ -7,7 +7,7 @@ import { useFieldArray, useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import { z } from "zod" import { RouteDrawer, useRouteModal } from "../../../../../../components/modals" -import { useBatchUpdateInventoryLevels } from "../../../../../../hooks/api/inventory" +import { useBatchInventoryItemLocationLevels } from "../../../../../../hooks/api/inventory" import { useEffect, useMemo } from "react" import { KeyboundForm } from "../../../../../../components/utilities/keybound-form" @@ -70,7 +70,7 @@ export const ManageLocationsForm = ({ ) }, [existingLocationLevels, locations]) - const { mutateAsync } = useBatchUpdateInventoryLevels(item.id) + const { mutateAsync } = useBatchInventoryItemLocationLevels(item.id) const handleSubmit = form.handleSubmit(async ({ locations }) => { // Changes in selected locations diff --git a/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx index 9443a77a70e9f..ad6b3eb71e6de 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx @@ -10,7 +10,7 @@ import { useRouteModal, } from "../../../../../components/modals" import { KeyboundForm } from "../../../../../components/utilities/keybound-form" -import { useBatchInventoryLevels } from "../../../../../hooks/api" +import { useBatchInventoryItemsLocationLevels } from "../../../../../hooks/api" import { castNumber } from "../../../../../lib/cast-number" import { useProductStockColumns } from "../../hooks/use-product-stock-columns" import { @@ -52,13 +52,14 @@ export const ProductStockForm = ({ ) const columns = useProductStockColumns(locations, disabled) - const { mutateAsync, isPending } = useBatchInventoryLevels() + const { mutateAsync, isPending } = useBatchInventoryItemsLocationLevels() const onSubmit = form.handleSubmit(async (data) => { - const payload: HttpTypes.AdminBatchInventoryItemLevels = { + const payload: HttpTypes.AdminBatchInventoryItemsLocationLevels = { create: [], update: [], delete: [], + force: true, } for (const [variantId, variant] of Object.entries(data.variants)) { @@ -67,19 +68,28 @@ export const ProductStockForm = ({ )) { for (const [location_id, level] of Object.entries(item.locations)) { if (level.levels_id) { - const newQuantity = - level.quantity !== "" ? castNumber(level.quantity) : undefined - const originalQuantity = + const wasChecked = initialValues.current?.variants?.[variantId]?.inventory_items?.[ inventory_item_id - ]?.locations?.[location_id]?.quantity - - if (newQuantity !== originalQuantity) { - payload.update.push({ - inventory_item_id, - location_id, - stocked_quantity: newQuantity, - }) + ]?.locations?.[location_id]?.checked + + if (wasChecked && !level.checked) { + payload.delete.push(level.levels_id) + } else { + const newQuantity = + level.quantity !== "" ? castNumber(level.quantity) : undefined + const originalQuantity = + initialValues.current?.variants?.[variantId]?.inventory_items?.[ + inventory_item_id + ]?.locations?.[location_id]?.quantity + + if (newQuantity !== originalQuantity) { + payload.update.push({ + inventory_item_id, + location_id, + stocked_quantity: newQuantity, + }) + } } } diff --git a/packages/core/core-flows/src/inventory/steps/update-inventory-levels.ts b/packages/core/core-flows/src/inventory/steps/update-inventory-levels.ts index b2dc65232a88f..6233bd362502b 100644 --- a/packages/core/core-flows/src/inventory/steps/update-inventory-levels.ts +++ b/packages/core/core-flows/src/inventory/steps/update-inventory-levels.ts @@ -13,10 +13,7 @@ export const updateInventoryLevelsStepId = "update-inventory-levels-step" */ export const updateInventoryLevelsStep = createStep( updateInventoryLevelsStepId, - async ( - input: InventoryTypes.BulkUpdateInventoryLevelInput[], - { container } - ) => { + async (input: InventoryTypes.UpdateInventoryLevelInput[], { container }) => { const inventoryService: IInventoryService = container.resolve( Modules.INVENTORY ) @@ -54,7 +51,7 @@ export const updateInventoryLevelsStep = createStep( await inventoryService.updateInventoryLevels( dataBeforeUpdate.map((data) => convertItemResponseToUpdateRequest(data, selects, relations) - ) as InventoryTypes.BulkUpdateInventoryLevelInput[] + ) as InventoryTypes.UpdateInventoryLevelInput[] ) } ) diff --git a/packages/core/core-flows/src/inventory/workflows/bulk-create-delete-levels.ts b/packages/core/core-flows/src/inventory/workflows/bulk-create-delete-levels.ts index 252461074cb75..546cfdddbf866 100644 --- a/packages/core/core-flows/src/inventory/workflows/bulk-create-delete-levels.ts +++ b/packages/core/core-flows/src/inventory/workflows/bulk-create-delete-levels.ts @@ -1,3 +1,5 @@ +// TODO: Remove this workflow in a future release. + import { InventoryLevelDTO, InventoryTypes } from "@medusajs/framework/types" import { createWorkflow, diff --git a/packages/core/core-flows/src/inventory/workflows/delete-inventory-levels.ts b/packages/core/core-flows/src/inventory/workflows/delete-inventory-levels.ts index 5cec9319a64f1..8e81007f42605 100644 --- a/packages/core/core-flows/src/inventory/workflows/delete-inventory-levels.ts +++ b/packages/core/core-flows/src/inventory/workflows/delete-inventory-levels.ts @@ -73,15 +73,24 @@ export const deleteInventoryLevelsWorkflowId = export const deleteInventoryLevelsWorkflow = createWorkflow( deleteInventoryLevelsWorkflowId, (input: WorkflowData) => { + const { filters, force } = transform(input, (data) => { + const { force, ...filters } = data + + return { + filters, + force, + } + }) + const inventoryLevels = useRemoteQueryStep({ entry_point: "inventory_levels", fields: ["id", "stocked_quantity", "reserved_quantity", "location_id"], variables: { - filters: input, + filters: filters, }, }) - validateInventoryLevelsDelete({ inventoryLevels, force: input.force }) + validateInventoryLevelsDelete({ inventoryLevels, force }) const idsToDelete = transform({ inventoryLevels }, ({ inventoryLevels }) => inventoryLevels.map((il) => il.id) diff --git a/packages/core/core-flows/src/inventory/workflows/update-inventory-levels.ts b/packages/core/core-flows/src/inventory/workflows/update-inventory-levels.ts index 29a0926c67d8f..f4492f2cb7171 100644 --- a/packages/core/core-flows/src/inventory/workflows/update-inventory-levels.ts +++ b/packages/core/core-flows/src/inventory/workflows/update-inventory-levels.ts @@ -8,7 +8,7 @@ import { import { updateInventoryLevelsStep } from "../steps/update-inventory-levels" export interface UpdateInventoryLevelsWorkflowInput { - updates: InventoryTypes.BulkUpdateInventoryLevelInput[] + updates: InventoryTypes.UpdateInventoryLevelInput[] } export const updateInventoryLevelsWorkflowId = "update-inventory-levels-workflow" diff --git a/packages/core/js-sdk/src/admin/inventory-item.ts b/packages/core/js-sdk/src/admin/inventory-item.ts index 99ddf0a784e24..b7ec760ab06e0 100644 --- a/packages/core/js-sdk/src/admin/inventory-item.ts +++ b/packages/core/js-sdk/src/admin/inventory-item.ts @@ -377,7 +377,7 @@ export class InventoryItem { */ async batchUpdateLevels( id: string, - body: HttpTypes.AdminBatchUpdateInventoryLevelLocation, + body: HttpTypes.AdminBatchInventoryItemLocationLevels, query?: SelectParams, headers?: ClientHeaders ) { @@ -398,18 +398,18 @@ export class InventoryItem { * API route. * * @param id - The inventory item's ID. - * @param body - The inventory levels to create or delete. + * @param body - The inventory levels to create, update or delete. * @param query - Configure the fields to retrieve in the inventory item. * @param headers - Headers to pass in the request * @returns The inventory item's details. * * @example - * sdk.admin.inventoryItem.batchUpdateInvetoryItemLocationLevels("iitem_123", { + * sdk.admin.inventoryItem.batchInventoryItemLocationLevels("iitem_123", { * create: [{ * location_id: "sloc_123", * stocked_quantity: 10 * }], - * delete: ["sloc_123"] + * delete: ["ilvl_123"] * }) * .then(({ inventory_item }) => { * console.log(inventory_item) @@ -417,7 +417,7 @@ export class InventoryItem { */ async batchInventoryItemLocationLevels( id: string, - body: HttpTypes.AdminBatchUpdateInventoryLevelLocation, + body: HttpTypes.AdminBatchInventoryItemLocationLevels, query?: SelectParams, headers?: ClientHeaders ) { @@ -432,8 +432,29 @@ export class InventoryItem { ) } + /** + * This method manages the inventory levels of multiple inventory items. + * + * @param body - The inventory levels to create, update or delete. + * @param query - Configure the fields to retrieve in the inventory item. + * @param headers - Headers to pass in the request + * @returns The inventory item's details. + * + * @example + * sdk.admin.inventoryItem.batchInventoryItemsLocationLevels({ + * create: [{ + * inventory_item_id: "iitem_123", + * location_id: "sloc_123", + * stocked_quantity: 10 + * }], + * delete: ["ilvl_123"] + * }) + * .then(({ inventory_item }) => { + * console.log(inventory_item) + * }) + */ async batchInventoryItemsLocationLevels( - body: HttpTypes.AdminBatchInventoryItemLevels, + body: HttpTypes.AdminBatchInventoryItemsLocationLevels, headers?: ClientHeaders ) { return await this.client.fetch( diff --git a/packages/core/types/src/http/inventory-level/admin/payloads.ts b/packages/core/types/src/http/inventory-level/admin/payloads.ts index eb576aa29655e..725f80c04b787 100644 --- a/packages/core/types/src/http/inventory-level/admin/payloads.ts +++ b/packages/core/types/src/http/inventory-level/admin/payloads.ts @@ -11,7 +11,7 @@ export interface AdminUpdateInventoryLevel { incoming_quantity?: number } -export interface AdminCreateInventoryLevel { +export interface AdminBatchCreateInventoryItemLocationLevels { /** * The ID of the associated stock location. */ @@ -28,19 +28,85 @@ export interface AdminCreateInventoryLevel { incoming_quantity?: number } -export interface AdminBatchUpdateInventoryLevelLocation { +export interface AdminBatchCreateInventoryItemLocationLevels { + /** + * The ID of the associated stock location. + */ + location_id: string + /** + * The associated inventory item's stocked quantity in the + * associated stock location. + */ + stocked_quantity?: number + /** + * The associated inventory item's incoming quantity in the + * associated stock location. + */ + incoming_quantity?: number +} + +export interface AdminBatchUpdateInventoryItemLocationLevels + extends AdminBatchCreateInventoryItemLocationLevels { + /** + * The ID of the inventory level to update. + */ + id?: string +} + +export interface AdminBatchInventoryItemLocationLevels { + /** + * A list of inventory levels to update. + */ + update?: AdminBatchUpdateInventoryItemLocationLevels[] + /** + * A list of inventory levels to create. + */ + create?: AdminBatchCreateInventoryItemLocationLevels[] /** * A list of location IDs to - * delete their associated inventory + * delete their associated inventory * levels of the inventory item. */ delete?: string[] /** - * @ignore + * Whether to force the deletion of the inventory levels, + * even if the the location has stocked quantity. */ - update?: never // TODO - not implemented // AdminUpdateInventoryLevel[] + force?: boolean +} + +export interface AdminBatchCreateInventoryItemsLocationLevels { /** - * A list of inventory levels to create. + * The ID of the associated stock location. + */ + location_id: string + /** + * The ID of the associated inventory item. + */ + inventory_item_id: string + /** + * The associated inventory item's stocked quantity in the + * associated stock location. */ - create?: AdminCreateInventoryLevel[] + stocked_quantity?: number + /** + * The associated inventory item's incoming quantity in the + * associated stock location. + */ + incoming_quantity?: number +} + +export interface AdminBatchUpdateInventoryItemsLocationLevels + extends AdminBatchCreateInventoryItemsLocationLevels { + /** + * The ID of the inventory level to update. + */ + id?: string +} + +export interface AdminBatchInventoryItemsLocationLevels { + create: AdminBatchCreateInventoryItemsLocationLevels[] + update: AdminBatchUpdateInventoryItemsLocationLevels[] + delete: string[] + force?: boolean } diff --git a/packages/core/types/src/http/inventory/admin/payloads.ts b/packages/core/types/src/http/inventory/admin/payloads.ts index 7ff9670c7490f..f8ce4c3f6eace 100644 --- a/packages/core/types/src/http/inventory/admin/payloads.ts +++ b/packages/core/types/src/http/inventory/admin/payloads.ts @@ -58,16 +58,3 @@ export interface AdminCreateInventoryItem { } export interface AdminUpdateInventoryItem extends AdminCreateInventoryItem {} - -export interface AdminBatchInventoryItemLevel { - location_id: string - inventory_item_id: string - stocked_quantity?: number - incoming_quantity?: number -} - -export interface AdminBatchInventoryItemLevels { - create: AdminBatchInventoryItemLevel[] - update: AdminBatchInventoryItemLevel[] - delete: string[] -} diff --git a/packages/core/types/src/inventory/mutations/inventory-level.ts b/packages/core/types/src/inventory/mutations/inventory-level.ts index d8a43c2d57f19..1d0e38cfb790d 100644 --- a/packages/core/types/src/inventory/mutations/inventory-level.ts +++ b/packages/core/types/src/inventory/mutations/inventory-level.ts @@ -47,22 +47,6 @@ export interface UpdateInventoryLevelInput { incoming_quantity?: number } -/** - * @interface - * - * The attributes to update in an inventory level. The inventory level is identified by the IDs of its associated inventory item and location. - */ -export type BulkUpdateInventoryLevelInput = { - /** - * The ID of the associated inventory level. - */ - inventory_item_id: string - /** - * The ID of the associated location. - */ - location_id: string -} & UpdateInventoryLevelInput - export type BulkAdjustInventoryLevelInput = { /** * The ID of the associated inventory level. @@ -77,4 +61,4 @@ export type BulkAdjustInventoryLevelInput = { * The quantity to adjust the inventory level by. */ adjustment: BigNumberInput -} & UpdateInventoryLevelInput +} diff --git a/packages/core/types/src/inventory/service.ts b/packages/core/types/src/inventory/service.ts index fab3faf2f194e..4cbaca41cb6f6 100644 --- a/packages/core/types/src/inventory/service.ts +++ b/packages/core/types/src/inventory/service.ts @@ -13,11 +13,11 @@ import { ReservationItemDTO, } from "./common" import { - BulkUpdateInventoryLevelInput, CreateInventoryItemInput, CreateInventoryLevelInput, CreateReservationItemInput, UpdateInventoryItemInput, + UpdateInventoryLevelInput, UpdateReservationItemInput, } from "./mutations" @@ -610,7 +610,7 @@ export interface IInventoryService extends IModuleService { /** * This method updates existing inventory levels. * - * @param {BulkUpdateInventoryLevelInput[]} updates - The list of The attributes to update in an inventory level. The inventory level is identified by the IDs of its associated inventory item and location. + * @param {UpdateInventoryLevelInput[]} updates - The list of The attributes to update in an inventory level. The inventory level is identified by the IDs of its associated inventory item and location. * @param {Context} context - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The updated inventory levels. * @@ -626,14 +626,14 @@ export interface IInventoryService extends IModuleService { * ]) */ updateInventoryLevels( - updates: BulkUpdateInventoryLevelInput[], + updates: UpdateInventoryLevelInput[], context?: Context ): Promise /** * This method updates an existing inventory level. * - * @param {BulkUpdateInventoryLevelInput} updates - The attributes to update in an inventory level. The inventory level is identified by the IDs of its associated inventory item and location. + * @param {UpdateInventoryLevelInput} updates - The attributes to update in an inventory level. The inventory level is identified by the IDs of its associated inventory item and location. * @param {Context} context - A context used to share resources, such as transaction manager, between the application and the module. * @returns {Promise} The updated inventory level. * @@ -646,7 +646,7 @@ export interface IInventoryService extends IModuleService { * }) */ updateInventoryLevels( - updates: BulkUpdateInventoryLevelInput, + updates: UpdateInventoryLevelInput, context?: Context ): Promise @@ -1058,7 +1058,7 @@ export interface IInventoryService extends IModuleService { ): Promise /** - * + * * @param {string} inventoryItemId - The inventory item's ID. * @param {string} locationId - The location's ID. * @param {number} adjustment - the adjustment to make to the quantity. diff --git a/packages/medusa/src/api/admin/inventory-items/[id]/location-levels/batch/route.ts b/packages/medusa/src/api/admin/inventory-items/[id]/location-levels/batch/route.ts index 49c99f1a5b04c..e22a43827e34e 100644 --- a/packages/medusa/src/api/admin/inventory-items/[id]/location-levels/batch/route.ts +++ b/packages/medusa/src/api/admin/inventory-items/[id]/location-levels/batch/route.ts @@ -1,39 +1,35 @@ -import { - AdminCreateInventoryLocationLevelType, - AdminUpdateInventoryLocationLevelType, -} from "../../../validators" import { MedusaRequest, MedusaResponse } from "@medusajs/framework/http" +import { AdminBatchInventoryItemLocationsLevelType } from "../../../validators" -import { bulkCreateDeleteLevelsWorkflow } from "@medusajs/core-flows" -import { BatchMethodRequest } from "@medusajs/framework/types" +import { batchInventoryItemLevelsWorkflow } from "@medusajs/core-flows" export const POST = async ( - req: MedusaRequest< - BatchMethodRequest< - AdminCreateInventoryLocationLevelType, - AdminUpdateInventoryLocationLevelType - > - >, - res: MedusaResponse<{ inventory_item: {} }> + req: MedusaRequest, + res: MedusaResponse ) => { const { id } = req.params - // TODO: Normalize workflow and response, and add support for updates - const workflow = bulkCreateDeleteLevelsWorkflow(req.scope) - await workflow.run({ + const workflow = batchInventoryItemLevelsWorkflow(req.scope) + const output = await workflow.run({ input: { - deletes: - req.validatedBody.delete?.map((location_id) => ({ - location_id, - inventory_item_id: id, - })) ?? [], - creates: + delete: req.validatedBody.delete ?? [], + create: req.validatedBody.create?.map((c) => ({ ...c, inventory_item_id: id, })) ?? [], + update: + req.validatedBody.update?.map((u) => ({ + ...u, + inventory_item_id: id, + })) ?? [], + force: req.validatedBody.force ?? false, }, }) - res.status(200).json({ inventory_item: {} }) + res.status(200).json({ + created: output.result.created, + updated: output.result.updated, + deleted: output.result.deleted, + }) } diff --git a/packages/medusa/src/api/admin/inventory-items/validators.ts b/packages/medusa/src/api/admin/inventory-items/validators.ts index 204641d760033..8837580bbbfe9 100644 --- a/packages/medusa/src/api/admin/inventory-items/validators.ts +++ b/packages/medusa/src/api/admin/inventory-items/validators.ts @@ -75,6 +75,30 @@ export const AdminCreateInventoryLocationLevel = z }) .strict() +export type AdminUpdateInventoryLocationLevelBatchType = z.infer< + typeof AdminUpdateInventoryLocationLevelBatch +> + +export const AdminUpdateInventoryLocationLevelBatch = z + .object({ + id: z.string().optional(), + location_id: z.string(), + stocked_quantity: z.number().min(0).optional(), + incoming_quantity: z.number().min(0).optional(), + }) + .strict() + +export type AdminBatchInventoryItemLocationsLevelType = z.infer< + typeof AdminBatchInventoryItemLocationsLevel +> + +export const AdminBatchInventoryItemLocationsLevel = z.object({ + create: z.array(AdminCreateInventoryLocationLevel).optional(), + update: z.array(AdminUpdateInventoryLocationLevelBatch).optional(), + delete: z.array(z.string()).optional(), + force: z.boolean().optional(), +}) + export type AdminUpdateInventoryLocationLevelType = z.infer< typeof AdminUpdateInventoryLocationLevel > @@ -137,11 +161,14 @@ const AdminBatchInventoryLocationLevel = z.object({ incoming_quantity: z.number().min(0).optional(), }) -export const AdminBatchInventoryItemLevels = z.object({ - create: z.array(AdminBatchInventoryLocationLevel).optional(), - update: z.array(AdminBatchInventoryLocationLevel).optional(), - delete: z.array(z.string()).optional(), -}) +export const AdminBatchInventoryItemLevels = z + .object({ + create: z.array(AdminBatchInventoryLocationLevel).optional(), + update: z.array(AdminBatchInventoryLocationLevel).optional(), + delete: z.array(z.string()).optional(), + force: z.boolean().optional(), + }) + .strict() export type AdminBatchInventoryItemLevelsType = z.infer< typeof AdminBatchInventoryItemLevels diff --git a/packages/modules/inventory/src/services/inventory-module.ts b/packages/modules/inventory/src/services/inventory-module.ts index 941d963f15476..3fbac62d12c23 100644 --- a/packages/modules/inventory/src/services/inventory-module.ts +++ b/packages/modules/inventory/src/services/inventory-module.ts @@ -546,11 +546,11 @@ export default class InventoryModuleService // @ts-ignore async updateInventoryLevels( - updates: InventoryTypes.BulkUpdateInventoryLevelInput[], + updates: InventoryTypes.UpdateInventoryLevelInput[], context?: Context ): Promise async updateInventoryLevels( - updates: InventoryTypes.BulkUpdateInventoryLevelInput, + updates: InventoryTypes.UpdateInventoryLevelInput, context?: Context ): Promise @@ -558,8 +558,8 @@ export default class InventoryModuleService @EmitEvents() async updateInventoryLevels( updates: - | InventoryTypes.BulkUpdateInventoryLevelInput[] - | InventoryTypes.BulkUpdateInventoryLevelInput, + | InventoryTypes.UpdateInventoryLevelInput[] + | InventoryTypes.UpdateInventoryLevelInput, @MedusaContext() context: Context = {} ): Promise< InventoryTypes.InventoryLevelDTO | InventoryTypes.InventoryLevelDTO[] @@ -592,7 +592,7 @@ export default class InventoryModuleService @InjectTransactionManager() async updateInventoryLevels_( - updates: InventoryTypes.BulkUpdateInventoryLevelInput[], + updates: InventoryTypes.UpdateInventoryLevelInput[], @MedusaContext() context: Context = {} ) { const inventoryLevels = await this.ensureInventoryLevels( From 2a0de9f8504542d0a9f375eb99f85f1d9171b791 Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 17 Dec 2024 13:40:10 +0100 Subject: [PATCH 04/19] add changeset --- .changeset/violet-weeks-pretend.md | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .changeset/violet-weeks-pretend.md diff --git a/.changeset/violet-weeks-pretend.md b/.changeset/violet-weeks-pretend.md new file mode 100644 index 0000000000000..aa39a4123bf29 --- /dev/null +++ b/.changeset/violet-weeks-pretend.md @@ -0,0 +1,10 @@ +--- +"@medusajs/inventory": patch +"@medusajs/dashboard": patch +"@medusajs/core-flows": patch +"@medusajs/js-sdk": patch +"@medusajs/types": patch +"@medusajs/medusa": patch +--- + +feat(inventory,dashboard,core-flows,js-sdk,types,medusa): Improve inventory management UX From e796c2c4b9f9b5bd27051f466cb243ad186767ee Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:23:50 +0100 Subject: [PATCH 05/19] fix 0 values --- .../data-grid-toggleable-number-cell.tsx | 4 +- .../src/i18n/translations/$schema.json | 2035 +++++++++++++---- .../dashboard/src/i18n/translations/en.json | 9 +- .../components/inventory-list-table.tsx | 2 +- .../inventory-stock-form.tsx | 82 +- .../inventory-stock/inventory-stock.tsx | 8 + .../inventory/inventory-stock/schema.ts | 1 + .../product-stock-form/product-stock-form.tsx | 26 +- .../routes/products/product-stock/schema.ts | 2 +- 9 files changed, 1763 insertions(+), 406 deletions(-) diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx index 34887731c381e..d225ed79d1f45 100644 --- a/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx @@ -137,7 +137,7 @@ const Inner = ({ _name, _values ) => { - const ensuredValue = updatedValue || "" + const ensuredValue = updatedValue !== undefined ? updatedValue : "" const newValue = { ...localValue, quantity: ensuredValue } /** @@ -158,7 +158,7 @@ const Inner = ({ {...props} ref={combinedRefs} className="txt-compact-small w-full flex-1 cursor-default appearance-none bg-transparent pl-8 text-right outline-none" - value={localValue?.quantity || undefined} + value={localValue?.quantity} onValueChange={handleInputChange} formatValueOnBlur onBlur={() => { diff --git a/packages/admin/dashboard/src/i18n/translations/$schema.json b/packages/admin/dashboard/src/i18n/translations/$schema.json index 2579af1ee867d..63a4a6f27bc95 100644 --- a/packages/admin/dashboard/src/i18n/translations/$schema.json +++ b/packages/admin/dashboard/src/i18n/translations/$schema.json @@ -258,7 +258,11 @@ "type": "string" } }, - "required": ["header_one", "header_other", "description"], + "required": [ + "header_one", + "header_other", + "description" + ], "additionalProperties": false } }, @@ -307,7 +311,11 @@ "type": "string" } }, - "required": ["insertRowAbove", "insertRowBelow", "deleteRow"], + "required": [ + "insertRowAbove", + "insertRowBelow", + "deleteRow" + ], "additionalProperties": false }, "labels": { @@ -320,7 +328,10 @@ "type": "string" } }, - "required": ["key", "value"], + "required": [ + "key", + "value" + ], "additionalProperties": false }, "complexRow": { @@ -336,7 +347,11 @@ "type": "string" } }, - "required": ["label", "description", "tooltip"], + "required": [ + "label", + "description", + "tooltip" + ], "additionalProperties": false } }, @@ -351,7 +366,12 @@ "additionalProperties": false } }, - "required": ["header", "numberOfKeys_one", "numberOfKeys_other", "edit"], + "required": [ + "header", + "numberOfKeys_one", + "numberOfKeys_other", + "edit" + ], "additionalProperties": false }, "validation": { @@ -364,7 +384,10 @@ "type": "string" } }, - "required": ["mustBeInt", "mustBePositive"], + "required": [ + "mustBeInt", + "mustBePositive" + ], "additionalProperties": false }, "actions": { @@ -550,7 +573,9 @@ "type": "string" } }, - "required": ["in"], + "required": [ + "in" + ], "additionalProperties": false }, "app": { @@ -901,7 +926,12 @@ "type": "string" } }, - "required": ["label", "dark", "light", "system"], + "required": [ + "label", + "dark", + "light", + "system" + ], "additionalProperties": false } }, @@ -924,7 +954,10 @@ "type": "string" } }, - "required": ["label", "storeSettings"], + "required": [ + "label", + "storeSettings" + ], "additionalProperties": false }, "actions": { @@ -934,11 +967,17 @@ "type": "string" } }, - "required": ["logout"], + "required": [ + "logout" + ], "additionalProperties": false } }, - "required": ["user", "store", "actions"], + "required": [ + "user", + "store", + "actions" + ], "additionalProperties": false }, "nav": { @@ -954,7 +993,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "common": { @@ -964,7 +1006,9 @@ "type": "string" } }, - "required": ["extensions"], + "required": [ + "extensions" + ], "additionalProperties": false }, "main": { @@ -977,7 +1021,10 @@ "type": "string" } }, - "required": ["store", "storeSettings"], + "required": [ + "store", + "storeSettings" + ], "additionalProperties": false }, "settings": { @@ -996,15 +1043,30 @@ "type": "string" } }, - "required": ["header", "general", "developer", "myAccount"], + "required": [ + "header", + "general", + "developer", + "myAccount" + ], "additionalProperties": false } }, - "required": ["accessibility", "common", "main", "settings"], + "required": [ + "accessibility", + "common", + "main", + "settings" + ], "additionalProperties": false } }, - "required": ["search", "keyboardShortcuts", "menus", "nav"], + "required": [ + "search", + "keyboardShortcuts", + "menus", + "nav" + ], "additionalProperties": false }, "dataGrid": { @@ -1023,7 +1085,11 @@ "type": "string" } }, - "required": ["view", "resetToDefault", "disabled"], + "required": [ + "view", + "resetToDefault", + "disabled" + ], "additionalProperties": false }, "shortcuts": { @@ -1117,7 +1183,10 @@ "additionalProperties": false } }, - "required": ["label", "commands"], + "required": [ + "label", + "commands" + ], "additionalProperties": false }, "errors": { @@ -1133,11 +1202,19 @@ "type": "string" } }, - "required": ["fixError", "count_one", "count_other"], + "required": [ + "fixError", + "count_one", + "count_other" + ], "additionalProperties": false } }, - "required": ["columns", "shortcuts", "errors"], + "required": [ + "columns", + "shortcuts", + "errors" + ], "additionalProperties": false }, "filters": { @@ -1223,7 +1300,11 @@ "type": "string" } }, - "required": ["date", "compare", "addFilter"], + "required": [ + "date", + "compare", + "addFilter" + ], "additionalProperties": false }, "errorBoundary": { @@ -1293,7 +1374,12 @@ "type": "string" } }, - "required": ["header", "editHeader", "editLabel", "label"], + "required": [ + "header", + "editHeader", + "editLabel", + "label" + ], "additionalProperties": false }, "billingAddress": { @@ -1352,7 +1438,11 @@ "type": "string" } }, - "required": ["editHeader", "editLabel", "label"], + "required": [ + "editHeader", + "editLabel", + "label" + ], "additionalProperties": false }, "transferOwnership": { @@ -1374,7 +1464,10 @@ "type": "string" } }, - "required": ["order", "draft"], + "required": [ + "order", + "draft" + ], "additionalProperties": false }, "currentOwner": { @@ -1387,7 +1480,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "newOwner": { @@ -1400,7 +1496,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "validation": { @@ -1413,7 +1512,10 @@ "type": "string" } }, - "required": ["mustBeDifferent", "required"], + "required": [ + "mustBeDifferent", + "required" + ], "additionalProperties": false } }, @@ -1434,7 +1536,9 @@ "type": "string" } }, - "required": ["availableIn"], + "required": [ + "availableIn" + ], "additionalProperties": false }, "products": { @@ -1450,7 +1554,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "edit": { @@ -1466,7 +1572,11 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false }, "create": { @@ -1497,7 +1607,12 @@ "type": "string" } }, - "required": ["details", "organize", "variants", "inventory"], + "required": [ + "details", + "organize", + "variants", + "inventory" + ], "additionalProperties": false }, "errors": { @@ -1513,7 +1628,11 @@ "type": "string" } }, - "required": ["variants", "options", "uniqueSku"], + "required": [ + "variants", + "options", + "uniqueSku" + ], "additionalProperties": false }, "inventory": { @@ -1559,7 +1678,9 @@ "type": "string" } }, - "required": ["placeholder"], + "required": [ + "placeholder" + ], "additionalProperties": false }, "optionValues": { @@ -1569,7 +1690,9 @@ "type": "string" } }, - "required": ["placeholder"], + "required": [ + "placeholder" + ], "additionalProperties": false }, "productVariants": { @@ -1588,7 +1711,12 @@ "type": "string" } }, - "required": ["label", "hint", "alert", "tip"], + "required": [ + "label", + "hint", + "alert", + "tip" + ], "additionalProperties": false }, "productOptions": { @@ -1601,7 +1729,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false } }, @@ -1651,7 +1782,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "filters": { @@ -1664,7 +1798,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "columns": { @@ -1677,7 +1814,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -1715,7 +1855,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "upload": { @@ -1756,7 +1899,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -1850,7 +1996,11 @@ "type": "string" } }, - "required": ["header", "description", "action"], + "required": [ + "header", + "description", + "action" + ], "additionalProperties": false }, "successToast": { @@ -1909,7 +2059,12 @@ "type": "string" } }, - "required": ["draft", "published", "proposed", "rejected"], + "required": [ + "draft", + "published", + "proposed", + "rejected" + ], "additionalProperties": false }, "fields": { @@ -1925,7 +2080,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "subtitle": { @@ -1935,7 +2093,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "handle": { @@ -1948,7 +2108,10 @@ "type": "string" } }, - "required": ["label", "tooltip"], + "required": [ + "label", + "tooltip" + ], "additionalProperties": false }, "description": { @@ -1961,7 +2124,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "discountable": { @@ -1974,7 +2140,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "type": { @@ -1984,7 +2153,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "collection": { @@ -1994,7 +2165,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "categories": { @@ -2004,7 +2177,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "tags": { @@ -2014,7 +2189,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "sales_channels": { @@ -2027,7 +2204,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "countryOrigin": { @@ -2037,7 +2217,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "material": { @@ -2047,7 +2229,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "width": { @@ -2057,7 +2241,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "length": { @@ -2067,7 +2253,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "height": { @@ -2077,7 +2265,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "weight": { @@ -2087,7 +2277,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "options": { @@ -2136,7 +2328,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "mid_code": { @@ -2146,7 +2341,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "hs_code": { @@ -2156,7 +2353,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false } }, @@ -2197,7 +2396,10 @@ "type": "string" } }, - "required": ["header", "success"], + "required": [ + "header", + "success" + ], "additionalProperties": false }, "create": { @@ -2207,7 +2409,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "deleteWarning": { @@ -2253,7 +2457,10 @@ "type": "string" } }, - "required": ["inventoryItems", "inventoryKit"], + "required": [ + "inventoryItems", + "inventoryKit" + ], "additionalProperties": false }, "inventoryKit": { @@ -2272,7 +2479,10 @@ "type": "string" } }, - "required": ["itemId", "quantity"], + "required": [ + "itemId", + "quantity" + ], "additionalProperties": false }, "header": { @@ -2367,7 +2577,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "create": { @@ -2380,14 +2593,22 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "deleteWarning": { "type": "string" } }, - "required": ["header", "edit", "create", "deleteWarning"], + "required": [ + "header", + "edit", + "create", + "deleteWarning" + ], "additionalProperties": false }, "organization": { @@ -2409,15 +2630,64 @@ "type": "string" } }, - "required": ["success"], + "required": [ + "success" + ], "additionalProperties": false } }, - "required": ["header", "toasts"], + "required": [ + "header", + "toasts" + ], + "additionalProperties": false + } + }, + "required": [ + "header", + "edit" + ], + "additionalProperties": false + }, + "stock": { + "type": "object", + "properties": { + "heading": { + "type": "string" + }, + "description": { + "type": "string" + }, + "action": { + "type": "string" + }, + "tooltips": { + "type": "object", + "properties": { + "alreadyManaged": { + "type": "string" + }, + "alreadyManagedWithSku": { + "type": "string" + } + }, + "required": [ + "alreadyManaged", + "alreadyManagedWithSku" + ], "additionalProperties": false + }, + "successToast": { + "type": "string" } }, - "required": ["header", "edit"], + "required": [ + "heading", + "description", + "action", + "tooltips", + "successToast" + ], "additionalProperties": false }, "toasts": { @@ -2436,7 +2706,10 @@ "type": "string" } }, - "required": ["header", "description"], + "required": [ + "header", + "description" + ], "additionalProperties": false }, "error": { @@ -2446,15 +2719,22 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false } }, - "required": ["success", "error"], + "required": [ + "success", + "error" + ], "additionalProperties": false } }, - "required": ["delete"], + "required": [ + "delete" + ], "additionalProperties": false } }, @@ -2482,6 +2762,7 @@ "variant", "options", "organization", + "stock", "toasts" ], "additionalProperties": false @@ -2532,7 +2813,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "add": { @@ -2545,7 +2828,10 @@ "type": "string" } }, - "required": ["successToast_one", "successToast_other"], + "required": [ + "successToast_one", + "successToast_other" + ], "additionalProperties": false }, "remove": { @@ -2558,11 +2844,18 @@ "type": "string" } }, - "required": ["successToast_one", "successToast_other"], + "required": [ + "successToast_one", + "successToast_other" + ], "additionalProperties": false } }, - "required": ["list", "add", "remove"], + "required": [ + "list", + "add", + "remove" + ], "additionalProperties": false } }, @@ -2610,14 +2903,22 @@ "type": "string" } }, - "required": ["details", "organize"], + "required": [ + "details", + "organize" + ], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": ["header", "hint", "tabs", "successToast"], + "required": [ + "header", + "hint", + "tabs", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -2633,8 +2934,12 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], - "additionalProperties": false + "required": [ + "header", + "description", + "successToast" + ], + "additionalProperties": false }, "delete": { "type": "object", @@ -2646,7 +2951,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "products": { @@ -2703,11 +3011,17 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["add", "remove", "list"], + "required": [ + "add", + "remove", + "list" + ], "additionalProperties": false }, "organize": { @@ -2720,7 +3034,10 @@ "type": "string" } }, - "required": ["header", "action"], + "required": [ + "header", + "action" + ], "additionalProperties": false }, "fields": { @@ -2739,7 +3056,11 @@ "type": "string" } }, - "required": ["label", "internal", "public"], + "required": [ + "label", + "internal", + "public" + ], "additionalProperties": false }, "status": { @@ -2755,7 +3076,11 @@ "type": "string" } }, - "required": ["label", "active", "inactive"], + "required": [ + "label", + "active", + "inactive" + ], "additionalProperties": false }, "path": { @@ -2768,7 +3093,10 @@ "type": "string" } }, - "required": ["label", "tooltip"], + "required": [ + "label", + "tooltip" + ], "additionalProperties": false }, "children": { @@ -2778,7 +3106,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "new": { @@ -2788,11 +3118,19 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false } }, - "required": ["visibility", "status", "path", "children", "new"], + "required": [ + "visibility", + "status", + "path", + "children", + "new" + ], "additionalProperties": false } }, @@ -2942,7 +3280,10 @@ "type": "string" } }, - "required": ["noAvaliableQuantity", "quantityOutOfRange"], + "required": [ + "noAvaliableQuantity", + "quantityOutOfRange" + ], "additionalProperties": false } }, @@ -2978,11 +3319,15 @@ "type": "string" } }, - "required": ["stockedQuantity"], + "required": [ + "stockedQuantity" + ], "additionalProperties": false } }, - "required": ["errors"], + "required": [ + "errors" + ], "additionalProperties": false }, "toast": { @@ -2998,7 +3343,35 @@ "type": "string" } }, - "required": ["updateLocations", "updateLevel", "updateItem"], + "required": [ + "updateLocations", + "updateLevel", + "updateItem" + ], + "additionalProperties": false + }, + "stock": { + "type": "object", + "properties": { + "title": { + "type": "string" + }, + "description": { + "type": "string" + }, + "action": { + "type": "string" + }, + "successToast": { + "type": "string" + } + }, + "required": [ + "title", + "description", + "action", + "successToast" + ], "additionalProperties": false } }, @@ -3015,7 +3388,8 @@ "create", "reservation", "adjustInventory", - "toast" + "toast", + "stock" ], "additionalProperties": false }, @@ -3104,7 +3478,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "create": { @@ -3120,7 +3496,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "groups": { @@ -3145,7 +3525,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "add": { @@ -3161,11 +3543,16 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["success", "list"], + "required": [ + "success", + "list" + ], "additionalProperties": false }, "removed": { @@ -3181,11 +3568,16 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["success", "list"], + "required": [ + "success", + "list" + ], "additionalProperties": false } }, @@ -3213,7 +3605,11 @@ "type": "string" } }, - "required": ["header", "emailDisabledTooltip", "successToast"], + "required": [ + "header", + "emailDisabledTooltip", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -3229,7 +3625,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -3245,7 +3645,11 @@ "type": "string" } }, - "required": ["guest", "registered", "groups"], + "required": [ + "guest", + "registered", + "groups" + ], "additionalProperties": false }, "registered": { @@ -3294,7 +3698,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -3307,7 +3715,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -3323,7 +3734,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "customers": { @@ -3348,11 +3763,17 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["successToast_one", "successToast_other", "list"], + "required": [ + "successToast_one", + "successToast_other", + "list" + ], "additionalProperties": false }, "remove": { @@ -3386,11 +3807,18 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["alreadyAddedTooltip", "add", "remove", "list"], + "required": [ + "alreadyAddedTooltip", + "add", + "remove", + "list" + ], "additionalProperties": false } }, @@ -3432,7 +3860,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "summary": { @@ -3724,7 +4154,10 @@ "type": "string" } }, - "required": ["title", "titlePending"], + "required": [ + "title", + "titlePending" + ], "additionalProperties": false }, "toast": { @@ -3737,7 +4170,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "validation": { @@ -3747,7 +4183,9 @@ "type": "string" } }, - "required": ["quantityLowerThanFulfillment"], + "required": [ + "quantityLowerThanFulfillment" + ], "additionalProperties": false } }, @@ -3788,7 +4226,10 @@ "type": "string" } }, - "required": ["title", "requestSuccess"], + "required": [ + "title", + "requestSuccess" + ], "additionalProperties": false }, "shippingAddress": { @@ -3801,7 +4242,10 @@ "type": "string" } }, - "required": ["title", "requestSuccess"], + "required": [ + "title", + "requestSuccess" + ], "additionalProperties": false }, "billingAddress": { @@ -3814,11 +4258,18 @@ "type": "string" } }, - "required": ["title", "requestSuccess"], + "required": [ + "title", + "requestSuccess" + ], "additionalProperties": false } }, - "required": ["email", "shippingAddress", "billingAddress"], + "required": [ + "email", + "shippingAddress", + "billingAddress" + ], "additionalProperties": false }, "returns": { @@ -3924,7 +4375,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "placeholders": { @@ -3940,7 +4394,10 @@ "type": "string" } }, - "required": ["title", "hint"], + "required": [ + "title", + "hint" + ], "additionalProperties": false }, "outboundShippingOptions": { @@ -3953,7 +4410,10 @@ "type": "string" } }, - "required": ["title", "hint"], + "required": [ + "title", + "hint" + ], "additionalProperties": false } }, @@ -4038,7 +4498,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "panel": { @@ -4051,7 +4514,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -4140,11 +4606,15 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false } }, - "required": ["cancelClaim"], + "required": [ + "cancelClaim" + ], "additionalProperties": false }, "cancel": { @@ -4157,7 +4627,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "tooltips": { @@ -4167,7 +4640,9 @@ "type": "string" } }, - "required": ["onlyReturnShippingOptions"], + "required": [ + "onlyReturnShippingOptions" + ], "additionalProperties": false }, "toast": { @@ -4180,7 +4655,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "panel": { @@ -4193,7 +4671,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -4263,11 +4744,15 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false } }, - "required": ["cancelExchange"], + "required": [ + "cancelExchange" + ], "additionalProperties": false }, "cancel": { @@ -4280,7 +4765,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "tooltips": { @@ -4290,7 +4778,9 @@ "type": "string" } }, - "required": ["onlyReturnShippingOptions"], + "required": [ + "onlyReturnShippingOptions" + ], "additionalProperties": false }, "toast": { @@ -4303,7 +4793,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "panel": { @@ -4316,7 +4809,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -4350,7 +4846,10 @@ "type": "string" } }, - "required": ["allocatedLabel", "notAllocatedLabel"], + "required": [ + "allocatedLabel", + "notAllocatedLabel" + ], "additionalProperties": false }, "allocateItems": { @@ -4387,7 +4886,9 @@ "type": "string" } }, - "required": ["created"], + "required": [ + "created" + ], "additionalProperties": false }, "error": { @@ -4397,7 +4898,9 @@ "type": "string" } }, - "required": ["quantityNotAllocated"], + "required": [ + "quantityNotAllocated" + ], "additionalProperties": false } }, @@ -4520,7 +5023,11 @@ "type": "string" } }, - "required": ["wrongQuantity", "wrongQuantity_other", "noItems"], + "required": [ + "wrongQuantity", + "wrongQuantity_other", + "noItems" + ], "additionalProperties": false }, "status": { @@ -4666,7 +5173,11 @@ "type": "string" } }, - "required": ["amountToLarge", "amountNegative", "reasonRequired"], + "required": [ + "amountToLarge", + "amountNegative", + "reasonRequired" + ], "additionalProperties": false } }, @@ -4762,7 +5273,10 @@ "type": "string" } }, - "required": ["toReturn", "toSend"], + "required": [ + "toReturn", + "toSend" + ], "additionalProperties": false }, "placed": { @@ -4775,7 +5289,10 @@ "type": "string" } }, - "required": ["title", "fromSalesChannel"], + "required": [ + "title", + "fromSalesChannel" + ], "additionalProperties": false }, "canceled": { @@ -4785,7 +5302,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "payment": { @@ -4804,7 +5323,12 @@ "type": "string" } }, - "required": ["awaiting", "captured", "canceled", "refunded"], + "required": [ + "awaiting", + "captured", + "canceled", + "refunded" + ], "additionalProperties": false }, "fulfillment": { @@ -4877,7 +5401,10 @@ "type": "string" } }, - "required": ["comment", "byLine"], + "required": [ + "comment", + "byLine" + ], "additionalProperties": false }, "claim": { @@ -4938,7 +5465,10 @@ "type": "string" } }, - "required": ["requested", "confirmed"], + "required": [ + "requested", + "confirmed" + ], "additionalProperties": false }, "transfer": { @@ -4954,7 +5484,11 @@ "type": "string" } }, - "required": ["requested", "confirmed", "declined"], + "required": [ + "requested", + "confirmed", + "declined" + ], "additionalProperties": false }, "update_order": { @@ -4970,7 +5504,11 @@ "type": "string" } }, - "required": ["shipping_address", "billing_address", "email"], + "required": [ + "shipping_address", + "billing_address", + "email" + ], "additionalProperties": false } }, @@ -5015,7 +5553,11 @@ "type": "string" } }, - "required": ["displayId", "refundableAmount", "returnableQuantity"], + "required": [ + "displayId", + "refundableAmount", + "returnableQuantity" + ], "additionalProperties": false } }, @@ -5074,7 +5616,11 @@ "type": "string" } }, - "required": ["label", "warningTitle", "warningDescription"], + "required": [ + "label", + "warningTitle", + "warningDescription" + ], "additionalProperties": false }, "status": { @@ -5087,7 +5633,10 @@ "type": "string" } }, - "required": ["open", "completed"], + "required": [ + "open", + "completed" + ], "additionalProperties": false }, "create": { @@ -5228,7 +5777,9 @@ "type": "string" } }, - "required": ["description"], + "required": [ + "description" + ], "additionalProperties": false }, "create": { @@ -5244,7 +5795,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -5260,7 +5815,11 @@ "type": "string" } }, - "required": ["header", "viewInventory", "successToast"], + "required": [ + "header", + "viewInventory", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -5270,7 +5829,9 @@ "type": "string" } }, - "required": ["confirmation"], + "required": [ + "confirmation" + ], "additionalProperties": false }, "fulfillmentProviders": { @@ -5319,7 +5880,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "shipping": { @@ -5329,7 +5892,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "disable": { @@ -5345,7 +5910,11 @@ "type": "string" } }, - "required": ["confirmation", "pickup", "shipping"], + "required": [ + "confirmation", + "pickup", + "shipping" + ], "additionalProperties": false }, "enable": { @@ -5358,11 +5927,19 @@ "type": "string" } }, - "required": ["pickup", "shipping"], + "required": [ + "pickup", + "shipping" + ], "additionalProperties": false } }, - "required": ["pickup", "shipping", "disable", "enable"], + "required": [ + "pickup", + "shipping", + "disable", + "enable" + ], "additionalProperties": false }, "sidebar": { @@ -5381,11 +5958,17 @@ "type": "string" } }, - "required": ["label", "description"], + "required": [ + "label", + "description" + ], "additionalProperties": false } }, - "required": ["header", "shippingProfiles"], + "required": [ + "header", + "shippingProfiles" + ], "additionalProperties": false }, "salesChannels": { @@ -5442,7 +6025,12 @@ "type": "string" } }, - "required": ["header", "hint", "label", "successToast"], + "required": [ + "header", + "hint", + "label", + "successToast" + ], "additionalProperties": false }, "returns": { @@ -5461,7 +6049,12 @@ "type": "string" } }, - "required": ["header", "hint", "label", "successToast"], + "required": [ + "header", + "hint", + "label", + "successToast" + ], "additionalProperties": false }, "tabs": { @@ -5474,16 +6067,24 @@ "type": "string" } }, - "required": ["details", "prices"], + "required": [ + "details", + "prices" + ], "additionalProperties": false }, "action": { "type": "string" } }, - "required": ["shipping", "returns", "tabs", "action"], - "additionalProperties": false - }, + "required": [ + "shipping", + "returns", + "tabs", + "action" + ], + "additionalProperties": false + }, "delete": { "type": "object", "properties": { @@ -5494,7 +6095,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -5510,7 +6114,11 @@ "type": "string" } }, - "required": ["header", "action", "successToast"], + "required": [ + "header", + "action", + "successToast" + ], "additionalProperties": false }, "pricing": { @@ -5520,7 +6128,9 @@ "type": "string" } }, - "required": ["action"], + "required": [ + "action" + ], "additionalProperties": false }, "conditionalPrices": { @@ -5539,7 +6149,9 @@ "type": "string" } }, - "required": ["cartItemTotal"], + "required": [ + "cartItemTotal" + ], "additionalProperties": false }, "summaries": { @@ -5555,7 +6167,11 @@ "type": "string" } }, - "required": ["range", "greaterThan", "lessThan"], + "required": [ + "range", + "greaterThan", + "lessThan" + ], "additionalProperties": false }, "actions": { @@ -5568,7 +6184,10 @@ "type": "string" } }, - "required": ["addPrice", "manageConditionalPrices"], + "required": [ + "addPrice", + "manageConditionalPrices" + ], "additionalProperties": false }, "rules": { @@ -5584,7 +6203,11 @@ "type": "string" } }, - "required": ["amount", "gte", "lte"], + "required": [ + "amount", + "gte", + "lte" + ], "additionalProperties": false }, "customRules": { @@ -5606,7 +6229,13 @@ "type": "string" } }, - "required": ["label", "tooltip", "eq", "gt", "lt"], + "required": [ + "label", + "tooltip", + "eq", + "gt", + "lt" + ], "additionalProperties": false }, "errors": { @@ -5696,7 +6325,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "calculated": { @@ -5709,15 +6341,24 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false } }, - "required": ["fixed", "calculated"], + "required": [ + "fixed", + "calculated" + ], "additionalProperties": false } }, - "required": ["label", "options"], + "required": [ + "label", + "options" + ], "additionalProperties": false }, "enableInStore": { @@ -5730,7 +6371,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "provider": { @@ -5797,7 +6441,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -5810,7 +6457,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "manageAreas": { @@ -5832,7 +6482,13 @@ "type": "string" } }, - "required": ["header", "action", "label", "hint", "successToast"], + "required": [ + "header", + "action", + "label", + "hint", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -5845,11 +6501,20 @@ "type": "string" } }, - "required": ["noRecords", "tip"], + "required": [ + "noRecords", + "tip" + ], "additionalProperties": false } }, - "required": ["create", "edit", "delete", "manageAreas", "fields"], + "required": [ + "create", + "edit", + "delete", + "manageAreas", + "fields" + ], "additionalProperties": false } }, @@ -5890,7 +6555,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -5906,7 +6575,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "tooltip": { @@ -5916,11 +6589,19 @@ "type": "string" } }, - "required": ["type"], + "required": [ + "type" + ], "additionalProperties": false } }, - "required": ["domain", "subtitle", "create", "delete", "tooltip"], + "required": [ + "domain", + "subtitle", + "create", + "delete", + "tooltip" + ], "additionalProperties": false }, "taxRegions": { @@ -5936,7 +6617,9 @@ "type": "string" } }, - "required": ["hint"], + "required": [ + "hint" + ], "additionalProperties": false }, "delete": { @@ -5949,7 +6632,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "create": { @@ -5971,14 +6657,22 @@ "type": "string" } }, - "required": ["rateIsRequired", "nameIsRequired"], + "required": [ + "rateIsRequired", + "nameIsRequired" + ], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": ["header", "hint", "errors", "successToast"], + "required": [ + "header", + "hint", + "errors", + "successToast" + ], "additionalProperties": false }, "province": { @@ -5997,11 +6691,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "state": { @@ -6020,11 +6720,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "stateOrTerritory": { @@ -6043,11 +6749,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "county": { @@ -6066,11 +6778,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "region": { @@ -6089,11 +6807,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "department": { @@ -6112,11 +6836,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "territory": { @@ -6135,11 +6865,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "prefecture": { @@ -6158,11 +6894,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "district": { @@ -6181,11 +6923,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "governorate": { @@ -6204,11 +6952,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "canton": { @@ -6227,11 +6981,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "emirate": { @@ -6250,11 +7010,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "sublevel": { @@ -6273,11 +7039,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "taxOverrides": { @@ -6296,7 +7068,10 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false }, "edit": { @@ -6309,11 +7084,18 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create", "edit"], + "required": [ + "header", + "create", + "edit" + ], "additionalProperties": false }, "taxRates": { @@ -6332,7 +7114,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -6348,7 +7134,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -6361,11 +7151,18 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false } }, - "required": ["create", "edit", "delete"], + "required": [ + "create", + "edit", + "delete" + ], "additionalProperties": false }, "fields": { @@ -6387,7 +7184,12 @@ "type": "string" } }, - "required": ["label", "hint", "true", "false"], + "required": [ + "label", + "hint", + "true", + "false" + ], "additionalProperties": false }, "defaultTaxRate": { @@ -6403,7 +7205,11 @@ "type": "string" } }, - "required": ["label", "tooltip", "action"], + "required": [ + "label", + "tooltip", + "action" + ], "additionalProperties": false }, "taxRate": { @@ -6462,7 +7268,11 @@ "type": "string" } }, - "required": ["in", "on", "and"], + "required": [ + "in", + "on", + "and" + ], "additionalProperties": false }, "placeholders": { @@ -6528,7 +7338,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "values_one": { @@ -6700,7 +7512,10 @@ "type": "string" } }, - "required": ["sublevel", "notPartOfCountry"], + "required": [ + "sublevel", + "notPartOfCountry" + ], "additionalProperties": false }, "alert": { @@ -6716,11 +7531,20 @@ "type": "string" } }, - "required": ["header", "description", "action"], + "required": [ + "header", + "description", + "action" + ], "additionalProperties": false } }, - "required": ["labels", "placeholders", "tooltips", "alert"], + "required": [ + "labels", + "placeholders", + "tooltips", + "alert" + ], "additionalProperties": false }, "noDefaultRate": { @@ -6733,7 +7557,10 @@ "type": "string" } }, - "required": ["label", "tooltip"], + "required": [ + "label", + "tooltip" + ], "additionalProperties": false } }, @@ -6786,7 +7613,9 @@ "type": "string" } }, - "required": ["details"], + "required": [ + "details" + ], "additionalProperties": false }, "tabs": { @@ -6802,7 +7631,11 @@ "type": "string" } }, - "required": ["template", "details", "campaign"], + "required": [ + "template", + "details", + "campaign" + ], "additionalProperties": false }, "fields": { @@ -6839,7 +7672,9 @@ "type": "string" } }, - "required": ["tooltip"], + "required": [ + "tooltip" + ], "additionalProperties": false }, "conditions": { @@ -6855,7 +7690,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "target-rules": { @@ -6868,7 +7706,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "buy-rules": { @@ -6881,11 +7722,18 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["rules", "target-rules", "buy-rules"], + "required": [ + "rules", + "target-rules", + "buy-rules" + ], "additionalProperties": false } }, @@ -6910,7 +7758,9 @@ "type": "string" } }, - "required": ["campaignType"], + "required": [ + "campaignType" + ], "additionalProperties": false }, "errors": { @@ -6923,7 +7773,10 @@ "type": "string" } }, - "required": ["requiredField", "promotionTabError"], + "required": [ + "requiredField", + "promotionTabError" + ], "additionalProperties": false }, "toasts": { @@ -6933,7 +7786,9 @@ "type": "string" } }, - "required": ["promotionCreateSuccess"], + "required": [ + "promotionCreateSuccess" + ], "additionalProperties": false }, "create": { @@ -6955,7 +7810,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "target-rules": { @@ -6965,7 +7822,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "buy-rules": { @@ -6975,11 +7834,18 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false } }, - "required": ["title", "rules", "target-rules", "buy-rules"], + "required": [ + "title", + "rules", + "target-rules", + "buy-rules" + ], "additionalProperties": false }, "campaign": { @@ -6998,7 +7864,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "actions": { @@ -7008,11 +7877,17 @@ "type": "string" } }, - "required": ["goToCampaign"], + "required": [ + "goToCampaign" + ], "additionalProperties": false } }, - "required": ["header", "edit", "actions"], + "required": [ + "header", + "edit", + "actions" + ], "additionalProperties": false }, "campaign_currency": { @@ -7022,7 +7897,9 @@ "type": "string" } }, - "required": ["tooltip"], + "required": [ + "tooltip" + ], "additionalProperties": false }, "form": { @@ -7059,11 +7936,18 @@ "type": "string" } }, - "required": ["title", "desc"], + "required": [ + "title", + "desc" + ], "additionalProperties": false } }, - "required": ["title", "description", "placeholder"], + "required": [ + "title", + "description", + "placeholder" + ], "additionalProperties": false }, "new": { @@ -7076,7 +7960,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "none": { @@ -7089,11 +7976,18 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["existing", "new", "none"], + "required": [ + "existing", + "new", + "none" + ], "additionalProperties": false }, "status": { @@ -7103,7 +7997,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "method": { @@ -7122,7 +8018,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "automatic": { @@ -7135,11 +8034,18 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["label", "code", "automatic"], + "required": [ + "label", + "code", + "automatic" + ], "additionalProperties": false }, "max_quantity": { @@ -7152,7 +8058,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "type": { @@ -7168,7 +8077,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "buyget": { @@ -7181,11 +8093,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["standard", "buyget"], + "required": [ + "standard", + "buyget" + ], "additionalProperties": false }, "allocation": { @@ -7201,7 +8119,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "across": { @@ -7214,11 +8135,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["each", "across"], + "required": [ + "each", + "across" + ], "additionalProperties": false }, "code": { @@ -7231,7 +8158,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "value": { @@ -7241,7 +8171,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "value_type": { @@ -7257,7 +8189,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "percentage": { @@ -7270,11 +8205,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["fixed", "percentage"], + "required": [ + "fixed", + "percentage" + ], "additionalProperties": false } }, @@ -7316,11 +8257,16 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["add", "list"], + "required": [ + "add", + "list" + ], "additionalProperties": false } }, @@ -7366,7 +8312,11 @@ "type": "string" } }, - "required": ["active", "expired", "scheduled"], + "required": [ + "active", + "expired", + "scheduled" + ], "additionalProperties": false }, "delete": { @@ -7382,7 +8332,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -7398,7 +8352,11 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false }, "configuration": { @@ -7420,11 +8378,18 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false } }, - "required": ["header", "edit"], + "required": [ + "header", + "edit" + ], "additionalProperties": false }, "create": { @@ -7486,7 +8451,9 @@ "type": "string" } }, - "required": ["hint"], + "required": [ + "hint" + ], "additionalProperties": false } }, @@ -7515,7 +8482,10 @@ "type": "string" } }, - "required": ["hint", "header"], + "required": [ + "hint", + "header" + ], "additionalProperties": false }, "details": { @@ -7537,7 +8507,12 @@ "type": "string" } }, - "required": ["type", "currency", "limit", "used"], + "required": [ + "type", + "currency", + "limit", + "used" + ], "additionalProperties": false }, "type": { @@ -7553,7 +8528,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "usage": { @@ -7566,11 +8544,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["spend", "usage"], + "required": [ + "spend", + "usage" + ], "additionalProperties": false }, "edit": { @@ -7580,11 +8564,19 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false } }, - "required": ["create", "details", "fields", "type", "edit"], + "required": [ + "create", + "details", + "fields", + "type", + "edit" + ], "additionalProperties": false }, "promotions": { @@ -7600,7 +8592,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "alreadyAdded": { @@ -7619,7 +8614,9 @@ "type": "string" } }, - "required": ["success"], + "required": [ + "success" + ], "additionalProperties": false }, "add": { @@ -7632,11 +8629,15 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false }, "list": { @@ -7646,7 +8647,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, @@ -7703,7 +8706,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "create": { @@ -7728,7 +8734,11 @@ "type": "string" } }, - "required": ["details", "products", "prices"], + "required": [ + "details", + "products", + "prices" + ], "additionalProperties": false }, "successToast": { @@ -7744,11 +8754,15 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false } }, @@ -7771,7 +8785,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "configuration": { @@ -7793,11 +8810,18 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false } }, - "required": ["header", "edit"], + "required": [ + "header", + "edit" + ], "additionalProperties": false }, "products": { @@ -7816,7 +8840,10 @@ "type": "string" } }, - "required": ["addProducts", "editPrices"], + "required": [ + "addProducts", + "editPrices" + ], "additionalProperties": false }, "delete": { @@ -7850,7 +8877,9 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false }, "edit": { @@ -7860,11 +8889,19 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false } }, - "required": ["header", "actions", "delete", "add", "edit"], + "required": [ + "header", + "actions", + "delete", + "add", + "edit" + ], "additionalProperties": false }, "fields": { @@ -7880,7 +8917,10 @@ "type": "string" } }, - "required": ["label", "header"], + "required": [ + "label", + "header" + ], "additionalProperties": false }, "status": { @@ -7905,11 +8945,19 @@ "type": "string" } }, - "required": ["active", "draft", "expired", "scheduled"], + "required": [ + "active", + "draft", + "expired", + "scheduled" + ], "additionalProperties": false } }, - "required": ["label", "options"], + "required": [ + "label", + "options" + ], "additionalProperties": false }, "type": { @@ -7934,7 +8982,10 @@ "type": "string" } }, - "required": ["label", "description"], + "required": [ + "label", + "description" + ], "additionalProperties": false }, "override": { @@ -7947,15 +8998,25 @@ "type": "string" } }, - "required": ["label", "description"], + "required": [ + "label", + "description" + ], "additionalProperties": false } }, - "required": ["sale", "override"], + "required": [ + "sale", + "override" + ], "additionalProperties": false } }, - "required": ["label", "hint", "options"], + "required": [ + "label", + "hint", + "options" + ], "additionalProperties": false }, "startsAt": { @@ -7968,7 +9029,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "endsAt": { @@ -7981,7 +9045,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "customerAvailability": { @@ -8055,7 +9122,10 @@ "type": "string" } }, - "required": ["languageLabel", "usageInsightsLabel"], + "required": [ + "languageLabel", + "usageInsightsLabel" + ], "additionalProperties": false }, "edit": { @@ -8089,7 +9159,9 @@ "type": "string" } }, - "required": ["edit"], + "required": [ + "edit" + ], "additionalProperties": false } }, @@ -8154,7 +9226,11 @@ "type": "string" } }, - "required": ["accepted", "pending", "expired"], + "required": [ + "accepted", + "pending", + "expired" + ], "additionalProperties": false }, "roles": { @@ -8170,7 +9246,11 @@ "type": "string" } }, - "required": ["admin", "developer", "member"], + "required": [ + "admin", + "developer", + "member" + ], "additionalProperties": false }, "deleteUserWarning": { @@ -8255,7 +9335,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "toast": { @@ -8377,7 +9459,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "toast": { @@ -8396,7 +9480,12 @@ "type": "string" } }, - "required": ["delete", "edit", "create", "countries"], + "required": [ + "delete", + "edit", + "create", + "countries" + ], "additionalProperties": false }, "shippingOption": { @@ -8430,7 +9519,12 @@ "type": "string" } }, - "required": ["outbound", "outboundHint", "return", "returnHint"], + "required": [ + "outbound", + "outboundHint", + "return", + "returnHint" + ], "additionalProperties": false }, "priceType": { @@ -8446,7 +9540,11 @@ "type": "string" } }, - "required": ["label", "flatRate", "calculated"], + "required": [ + "label", + "flatRate", + "calculated" + ], "additionalProperties": false }, "availability": { @@ -8459,7 +9557,10 @@ "type": "string" } }, - "required": ["adminOnly", "adminOnlyHint"], + "required": [ + "adminOnly", + "adminOnlyHint" + ], "additionalProperties": false }, "taxInclusiveHint": { @@ -8475,7 +9576,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false } }, @@ -8537,7 +9641,9 @@ "type": "string" } }, - "required": ["taxCountriesHint"], + "required": [ + "taxCountriesHint" + ], "additionalProperties": false }, "settings": { @@ -8591,7 +9697,9 @@ "type": "string" } }, - "required": ["sectionTitle"], + "required": [ + "sectionTitle" + ], "additionalProperties": false }, "taxRate": { @@ -8741,7 +9849,11 @@ "type": "string" } }, - "required": ["create", "update", "removeChannel"], + "required": [ + "create", + "update", + "removeChannel" + ], "additionalProperties": false } }, @@ -8771,7 +9883,11 @@ "type": "string" } }, - "required": ["domain", "subtitle", "deleteWarning"], + "required": [ + "domain", + "subtitle", + "deleteWarning" + ], "additionalProperties": false }, "salesChannels": { @@ -8823,7 +9939,11 @@ "type": "string" } }, - "required": ["create", "update", "delete"], + "required": [ + "create", + "update", + "delete" + ], "additionalProperties": false }, "tooltip": { @@ -8833,7 +9953,9 @@ "type": "string" } }, - "required": ["cannotDeleteDefault"], + "required": [ + "cannotDeleteDefault" + ], "additionalProperties": false }, "products": { @@ -8846,7 +9968,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "add": { @@ -8859,15 +9983,22 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false } }, - "required": ["list", "add"], + "required": [ + "list", + "add" + ], "additionalProperties": false } }, @@ -8902,7 +10033,10 @@ "type": "string" } }, - "required": ["publishable", "secret"], + "required": [ + "publishable", + "secret" + ], "additionalProperties": false }, "subtitle": { @@ -8915,7 +10049,10 @@ "type": "string" } }, - "required": ["publishable", "secret"], + "required": [ + "publishable", + "secret" + ], "additionalProperties": false }, "status": { @@ -8928,7 +10065,10 @@ "type": "string" } }, - "required": ["active", "revoked"], + "required": [ + "active", + "revoked" + ], "additionalProperties": false }, "type": { @@ -8941,7 +10081,10 @@ "type": "string" } }, - "required": ["publishable", "secret"], + "required": [ + "publishable", + "secret" + ], "additionalProperties": false }, "create": { @@ -9001,7 +10144,11 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false }, "salesChannels": { @@ -9029,7 +10176,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, @@ -9053,7 +10202,10 @@ "type": "string" } }, - "required": ["warning", "successToast"], + "required": [ + "warning", + "successToast" + ], "additionalProperties": false }, "revoke": { @@ -9066,7 +10218,10 @@ "type": "string" } }, - "required": ["warning", "successToast"], + "required": [ + "warning", + "successToast" + ], "additionalProperties": false }, "addSalesChannels": { @@ -9079,11 +10234,15 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false }, "removeSalesChannel": { @@ -9131,7 +10290,11 @@ "type": "string" } }, - "required": ["revoke", "copy", "copySuccessToast"], + "required": [ + "revoke", + "copy", + "copySuccessToast" + ], "additionalProperties": false }, "table": { @@ -9144,7 +10307,10 @@ "type": "string" } }, - "required": ["lastUsedAtHeader", "createdAtHeader"], + "required": [ + "lastUsedAtHeader", + "createdAtHeader" + ], "additionalProperties": false }, "fields": { @@ -9221,7 +10387,12 @@ "type": "string" } }, - "required": ["header", "subtitle", "hint", "successToast"], + "required": [ + "header", + "subtitle", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -9237,7 +10408,11 @@ "type": "string" } }, - "required": ["header", "subtitle", "successToast"], + "required": [ + "header", + "subtitle", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -9250,7 +10425,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -9269,7 +10447,11 @@ "type": "string" } }, - "required": ["label", "placeholder", "tooltip"], + "required": [ + "label", + "placeholder", + "tooltip" + ], "additionalProperties": false }, "label": { @@ -9282,7 +10464,10 @@ "type": "string" } }, - "required": ["label", "placeholder"], + "required": [ + "label", + "placeholder" + ], "additionalProperties": false }, "description": { @@ -9295,11 +10480,18 @@ "type": "string" } }, - "required": ["label", "placeholder"], + "required": [ + "label", + "placeholder" + ], "additionalProperties": false } }, - "required": ["value", "label", "description"], + "required": [ + "value", + "label", + "description" + ], "additionalProperties": false } }, @@ -9328,7 +10520,11 @@ "type": "string" } }, - "required": ["forgotPassword", "title", "hint"], + "required": [ + "forgotPassword", + "title", + "hint" + ], "additionalProperties": false }, "invite": { @@ -9380,7 +10576,9 @@ "type": "string" } }, - "required": ["accepted"], + "required": [ + "accepted" + ], "additionalProperties": false } }, @@ -9525,7 +10723,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "history": { @@ -9622,11 +10822,15 @@ "type": "string" } }, - "required": ["waitingToCompensate"], + "required": [ + "waitingToCompensate" + ], "additionalProperties": false } }, - "required": ["state"], + "required": [ + "state" + ], "additionalProperties": false }, "step": { @@ -9648,11 +10852,18 @@ "type": "string" } }, - "required": ["skipped", "skippedFailure", "dormant", "timeout"], + "required": [ + "skipped", + "skippedFailure", + "dormant", + "timeout" + ], "additionalProperties": false } }, - "required": ["state"], + "required": [ + "state" + ], "additionalProperties": false } }, @@ -9694,7 +10905,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -9707,7 +10922,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -9720,7 +10938,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -9730,11 +10951,20 @@ "type": "string" } }, - "required": ["value"], + "required": [ + "value" + ], "additionalProperties": false } }, - "required": ["domain", "subtitle", "create", "edit", "delete", "fields"], + "required": [ + "domain", + "subtitle", + "create", + "edit", + "delete", + "fields" + ], "additionalProperties": false }, "productTags": { @@ -9756,7 +10986,11 @@ "type": "string" } }, - "required": ["header", "subtitle", "successToast"], + "required": [ + "header", + "subtitle", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -9772,7 +11006,11 @@ "type": "string" } }, - "required": ["header", "subtitle", "successToast"], + "required": [ + "header", + "subtitle", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -9785,7 +11023,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -9795,11 +11036,19 @@ "type": "string" } }, - "required": ["value"], + "required": [ + "value" + ], "additionalProperties": false } }, - "required": ["domain", "create", "edit", "delete", "fields"], + "required": [ + "domain", + "create", + "edit", + "delete", + "fields" + ], "additionalProperties": false }, "notifications": { @@ -9818,7 +11067,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "accessibility": { @@ -9828,11 +11080,17 @@ "type": "string" } }, - "required": ["description"], + "required": [ + "description" + ], "additionalProperties": false } }, - "required": ["domain", "emptyState", "accessibility"], + "required": [ + "domain", + "emptyState", + "accessibility" + ], "additionalProperties": false }, "errors": { @@ -9845,7 +11103,10 @@ "type": "string" } }, - "required": ["serverError", "invalidCredentials"], + "required": [ + "serverError", + "invalidCredentials" + ], "additionalProperties": false }, "statuses": { @@ -9867,7 +11128,13 @@ "type": "string" } }, - "required": ["scheduled", "expired", "active", "enabled", "disabled"], + "required": [ + "scheduled", + "expired", + "active", + "enabled", + "disabled" + ], "additionalProperties": false }, "labels": { @@ -10662,4 +11929,4 @@ "dateTime" ], "additionalProperties": false -} +} \ No newline at end of file diff --git a/packages/admin/dashboard/src/i18n/translations/en.json b/packages/admin/dashboard/src/i18n/translations/en.json index 576c7a043f4ad..d530031ed6a8c 100644 --- a/packages/admin/dashboard/src/i18n/translations/en.json +++ b/packages/admin/dashboard/src/i18n/translations/en.json @@ -652,7 +652,8 @@ "tooltips": { "alreadyManaged": "This inventory item is already editable under {{title}}.", "alreadyManagedWithSku": "This inventory item is already editable under {{title}} ({{sku}})." - } + }, + "successToast": "Inventory levels updated successfully." }, "toasts": { "delete": { @@ -808,6 +809,12 @@ "updateLocations": "Locations updated successfully.", "updateLevel": "Inventory level updated successfully.", "updateItem": "Inventory item updated successfully." + }, + "stock": { + "title": "Update inventory levels", + "description": "Update the stocked inventory levels for the selected inventory items.", + "action": "Edit stock levels", + "successToast": "Inventory levels updated successfully." } }, "giftCards": { diff --git a/packages/admin/dashboard/src/routes/inventory/inventory-list/components/inventory-list-table.tsx b/packages/admin/dashboard/src/routes/inventory/inventory-list/components/inventory-list-table.tsx index 561c27418f706..199fa17ee6c43 100644 --- a/packages/admin/dashboard/src/routes/inventory/inventory-list/components/inventory-list-table.tsx +++ b/packages/admin/dashboard/src/routes/inventory/inventory-list/components/inventory-list-table.tsx @@ -95,7 +95,7 @@ export const InventoryListTable = () => { )}` ) }, - label: t("actions.edit"), + label: t("inventory.stock.action"), shortcut: "i", }, ]} diff --git a/packages/admin/dashboard/src/routes/inventory/inventory-stock/components/inventory-stock-form/inventory-stock-form.tsx b/packages/admin/dashboard/src/routes/inventory/inventory-stock/components/inventory-stock-form/inventory-stock-form.tsx index a1cf9b051b6de..f86790abe7d35 100644 --- a/packages/admin/dashboard/src/routes/inventory/inventory-stock/components/inventory-stock-form/inventory-stock-form.tsx +++ b/packages/admin/dashboard/src/routes/inventory/inventory-stock/components/inventory-stock-form/inventory-stock-form.tsx @@ -1,6 +1,7 @@ import { zodResolver } from "@hookform/resolvers/zod" import { HttpTypes } from "@medusajs/types" -import { Button } from "@medusajs/ui" +import { Button, toast } from "@medusajs/ui" +import { useRef } from "react" import { DefaultValues, useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import { DataGrid } from "../../../../../components/data-grid" @@ -9,6 +10,8 @@ import { useRouteModal, } from "../../../../../components/modals" import { KeyboundForm } from "../../../../../components/utilities/keybound-form" +import { useBatchInventoryItemsLocationLevels } from "../../../../../hooks/api" +import { castNumber } from "../../../../../lib/cast-number" import { useInventoryStockColumns } from "../../hooks/use-inventory-stock-columns" import { InventoryItemSchema, @@ -26,7 +29,10 @@ export const InventoryStockForm = ({ locations, }: InventoryStockFormProps) => { const { t } = useTranslation() - const { setCloseOnEscape } = useRouteModal() + const { setCloseOnEscape, handleSuccess } = useRouteModal() + + const initialValues = useRef(getDefaultValues(items, locations)) + console.log("initialValues", initialValues.current) const form = useForm({ defaultValues: getDefaultValues(items, locations), @@ -35,9 +41,69 @@ export const InventoryStockForm = ({ const columns = useInventoryStockColumns(locations) + const { mutateAsync, isPending } = useBatchInventoryItemsLocationLevels() + + const onSubmit = form.handleSubmit(async (data) => { + const payload: HttpTypes.AdminBatchInventoryItemsLocationLevels = { + create: [], + update: [], + delete: [], + force: true, + } + + for (const [inventory_item_id, item] of Object.entries( + data.inventory_items + )) { + for (const [location_id, level] of Object.entries(item.locations)) { + if (level.id) { + const wasChecked = + initialValues.current?.inventory_items?.[inventory_item_id] + ?.locations?.[location_id]?.checked + + if (wasChecked && !level.checked) { + payload.delete.push(level.id) + } else { + const newQuantity = + level.quantity !== "" ? castNumber(level.quantity) : 0 + const originalQuantity = + initialValues.current?.inventory_items?.[inventory_item_id] + ?.locations?.[location_id]?.quantity + + if (newQuantity !== originalQuantity) { + payload.update.push({ + id: level.id, + inventory_item_id, + location_id, + stocked_quantity: newQuantity, + }) + } + } + } + + if (!level.id && level.quantity !== "") { + payload.create.push({ + inventory_item_id, + location_id, + stocked_quantity: castNumber(level.quantity), + }) + } + } + } + + await mutateAsync(payload, { + onSuccess: () => { + toast.success(t("inventory.stock.successToast")) + handleSuccess() + }, + onError: (error) => { + toast.error(error.message) + }, + }) + }) + return ( - + -
@@ -79,8 +145,14 @@ function getDefaultValues( locationAcc[location.id] = { id: level?.id, - quantity: level?.stocked_quantity ?? "", + quantity: + typeof level?.stocked_quantity === "number" + ? level?.stocked_quantity + : "", checked: !!level, + disabledToggle: + (level?.incoming_quantity || 0) > 0 || + (level?.reserved_quantity || 0) > 0, } return locationAcc }, {} as InventoryLocationsSchema) diff --git a/packages/admin/dashboard/src/routes/inventory/inventory-stock/inventory-stock.tsx b/packages/admin/dashboard/src/routes/inventory/inventory-stock/inventory-stock.tsx index 337defe9f04fd..4abc69310fac3 100644 --- a/packages/admin/dashboard/src/routes/inventory/inventory-stock/inventory-stock.tsx +++ b/packages/admin/dashboard/src/routes/inventory/inventory-stock/inventory-stock.tsx @@ -1,3 +1,4 @@ +import { useTranslation } from "react-i18next" import { useSearchParams } from "react-router-dom" import { RouteFocusModal } from "../../../components/modals" import { useInventoryItems, useStockLocations } from "../../../hooks/api" @@ -5,6 +6,7 @@ import { INVENTORY_ITEM_IDS_KEY } from "../common/constants" import { InventoryStockForm } from "./components/inventory-stock-form" export const InventoryStock = () => { + const { t } = useTranslation() const [searchParams] = useSearchParams() const inventoryItemIds = searchParams.get(INVENTORY_ITEM_IDS_KEY)?.split(",") || undefined @@ -39,6 +41,12 @@ export const InventoryStock = () => { return ( + + {t("inventory.stock.title")} + + + {t("inventory.stock.description")} + {ready && ( ({ - // TODO: Update ProductVariant type to include inventory_items defaultValues: getDefaultValue(variants as any, locations), resolver: zodResolver(ProductStockSchema), }) @@ -67,17 +66,17 @@ export const ProductStockForm = ({ variant.inventory_items )) { for (const [location_id, level] of Object.entries(item.locations)) { - if (level.levels_id) { + if (level.id) { const wasChecked = initialValues.current?.variants?.[variantId]?.inventory_items?.[ inventory_item_id ]?.locations?.[location_id]?.checked if (wasChecked && !level.checked) { - payload.delete.push(level.levels_id) + payload.delete.push(level.id) } else { const newQuantity = - level.quantity !== "" ? castNumber(level.quantity) : undefined + level.quantity !== "" ? castNumber(level.quantity) : 0 const originalQuantity = initialValues.current?.variants?.[variantId]?.inventory_items?.[ inventory_item_id @@ -93,7 +92,7 @@ export const ProductStockForm = ({ } } - if (!level.levels_id && level.quantity !== "") { + if (!level.id && level.quantity !== "") { payload.create.push({ inventory_item_id, location_id, @@ -106,7 +105,7 @@ export const ProductStockForm = ({ await mutateAsync(payload, { onSuccess: () => { - toast.success("Updated inventory levels!") + toast.success(t("products.stock.successToast")) handleSuccess() }, onError: (error) => { @@ -163,17 +162,20 @@ function getDefaultValue( variants: variants.reduce((variantAcc, variant) => { const inventoryItems = variant.inventory_items.reduce((itemAcc, item) => { const locationsMap = locations.reduce((locationAcc, location) => { - const levels = item.inventory.location_levels?.find( + const level = item.inventory.location_levels?.find( (level) => level.location_id === location.id ) locationAcc[location.id] = { - quantity: levels?.stocked_quantity || "", - levels_id: levels?.id, - checked: !!levels, + id: level?.id, + quantity: + level?.stocked_quantity !== undefined + ? level?.stocked_quantity + : "", + checked: !!level, disabledToggle: - (levels?.incoming_quantity || 0) > 0 || - (levels?.reserved_quantity || 0) > 0, + (level?.incoming_quantity || 0) > 0 || + (level?.reserved_quantity || 0) > 0, } return locationAcc }, {} as ProductStockLocationSchema) diff --git a/packages/admin/dashboard/src/routes/products/product-stock/schema.ts b/packages/admin/dashboard/src/routes/products/product-stock/schema.ts index efd7becf47d04..d8f7afd3d99a9 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/schema.ts +++ b/packages/admin/dashboard/src/routes/products/product-stock/schema.ts @@ -1,7 +1,7 @@ import { z } from "zod" const LocationQuantitySchema = z.object({ - levels_id: z.string().optional(), + id: z.string().optional(), quantity: z.union([z.number(), z.string()]), checked: z.boolean(), disabledToggle: z.boolean(), From e158c9fd8162493ed4bbd746c439481bb0dc562f Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 17 Dec 2024 14:27:11 +0100 Subject: [PATCH 06/19] format schema --- .../src/i18n/translations/$schema.json | 1974 ++++------------- 1 file changed, 383 insertions(+), 1591 deletions(-) diff --git a/packages/admin/dashboard/src/i18n/translations/$schema.json b/packages/admin/dashboard/src/i18n/translations/$schema.json index 63a4a6f27bc95..d9aaf095122b4 100644 --- a/packages/admin/dashboard/src/i18n/translations/$schema.json +++ b/packages/admin/dashboard/src/i18n/translations/$schema.json @@ -258,11 +258,7 @@ "type": "string" } }, - "required": [ - "header_one", - "header_other", - "description" - ], + "required": ["header_one", "header_other", "description"], "additionalProperties": false } }, @@ -311,11 +307,7 @@ "type": "string" } }, - "required": [ - "insertRowAbove", - "insertRowBelow", - "deleteRow" - ], + "required": ["insertRowAbove", "insertRowBelow", "deleteRow"], "additionalProperties": false }, "labels": { @@ -328,10 +320,7 @@ "type": "string" } }, - "required": [ - "key", - "value" - ], + "required": ["key", "value"], "additionalProperties": false }, "complexRow": { @@ -347,11 +336,7 @@ "type": "string" } }, - "required": [ - "label", - "description", - "tooltip" - ], + "required": ["label", "description", "tooltip"], "additionalProperties": false } }, @@ -366,12 +351,7 @@ "additionalProperties": false } }, - "required": [ - "header", - "numberOfKeys_one", - "numberOfKeys_other", - "edit" - ], + "required": ["header", "numberOfKeys_one", "numberOfKeys_other", "edit"], "additionalProperties": false }, "validation": { @@ -384,10 +364,7 @@ "type": "string" } }, - "required": [ - "mustBeInt", - "mustBePositive" - ], + "required": ["mustBeInt", "mustBePositive"], "additionalProperties": false }, "actions": { @@ -573,9 +550,7 @@ "type": "string" } }, - "required": [ - "in" - ], + "required": ["in"], "additionalProperties": false }, "app": { @@ -926,12 +901,7 @@ "type": "string" } }, - "required": [ - "label", - "dark", - "light", - "system" - ], + "required": ["label", "dark", "light", "system"], "additionalProperties": false } }, @@ -954,10 +924,7 @@ "type": "string" } }, - "required": [ - "label", - "storeSettings" - ], + "required": ["label", "storeSettings"], "additionalProperties": false }, "actions": { @@ -967,17 +934,11 @@ "type": "string" } }, - "required": [ - "logout" - ], + "required": ["logout"], "additionalProperties": false } }, - "required": [ - "user", - "store", - "actions" - ], + "required": ["user", "store", "actions"], "additionalProperties": false }, "nav": { @@ -993,10 +954,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "common": { @@ -1006,9 +964,7 @@ "type": "string" } }, - "required": [ - "extensions" - ], + "required": ["extensions"], "additionalProperties": false }, "main": { @@ -1021,10 +977,7 @@ "type": "string" } }, - "required": [ - "store", - "storeSettings" - ], + "required": ["store", "storeSettings"], "additionalProperties": false }, "settings": { @@ -1043,30 +996,15 @@ "type": "string" } }, - "required": [ - "header", - "general", - "developer", - "myAccount" - ], + "required": ["header", "general", "developer", "myAccount"], "additionalProperties": false } }, - "required": [ - "accessibility", - "common", - "main", - "settings" - ], + "required": ["accessibility", "common", "main", "settings"], "additionalProperties": false } }, - "required": [ - "search", - "keyboardShortcuts", - "menus", - "nav" - ], + "required": ["search", "keyboardShortcuts", "menus", "nav"], "additionalProperties": false }, "dataGrid": { @@ -1085,11 +1023,7 @@ "type": "string" } }, - "required": [ - "view", - "resetToDefault", - "disabled" - ], + "required": ["view", "resetToDefault", "disabled"], "additionalProperties": false }, "shortcuts": { @@ -1183,10 +1117,7 @@ "additionalProperties": false } }, - "required": [ - "label", - "commands" - ], + "required": ["label", "commands"], "additionalProperties": false }, "errors": { @@ -1202,19 +1133,11 @@ "type": "string" } }, - "required": [ - "fixError", - "count_one", - "count_other" - ], + "required": ["fixError", "count_one", "count_other"], "additionalProperties": false } }, - "required": [ - "columns", - "shortcuts", - "errors" - ], + "required": ["columns", "shortcuts", "errors"], "additionalProperties": false }, "filters": { @@ -1300,11 +1223,7 @@ "type": "string" } }, - "required": [ - "date", - "compare", - "addFilter" - ], + "required": ["date", "compare", "addFilter"], "additionalProperties": false }, "errorBoundary": { @@ -1374,12 +1293,7 @@ "type": "string" } }, - "required": [ - "header", - "editHeader", - "editLabel", - "label" - ], + "required": ["header", "editHeader", "editLabel", "label"], "additionalProperties": false }, "billingAddress": { @@ -1438,11 +1352,7 @@ "type": "string" } }, - "required": [ - "editHeader", - "editLabel", - "label" - ], + "required": ["editHeader", "editLabel", "label"], "additionalProperties": false }, "transferOwnership": { @@ -1464,10 +1374,7 @@ "type": "string" } }, - "required": [ - "order", - "draft" - ], + "required": ["order", "draft"], "additionalProperties": false }, "currentOwner": { @@ -1480,10 +1387,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "newOwner": { @@ -1496,10 +1400,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "validation": { @@ -1512,10 +1413,7 @@ "type": "string" } }, - "required": [ - "mustBeDifferent", - "required" - ], + "required": ["mustBeDifferent", "required"], "additionalProperties": false } }, @@ -1536,9 +1434,7 @@ "type": "string" } }, - "required": [ - "availableIn" - ], + "required": ["availableIn"], "additionalProperties": false }, "products": { @@ -1554,9 +1450,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "edit": { @@ -1572,11 +1466,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "create": { @@ -1607,12 +1497,7 @@ "type": "string" } }, - "required": [ - "details", - "organize", - "variants", - "inventory" - ], + "required": ["details", "organize", "variants", "inventory"], "additionalProperties": false }, "errors": { @@ -1628,11 +1513,7 @@ "type": "string" } }, - "required": [ - "variants", - "options", - "uniqueSku" - ], + "required": ["variants", "options", "uniqueSku"], "additionalProperties": false }, "inventory": { @@ -1678,9 +1559,7 @@ "type": "string" } }, - "required": [ - "placeholder" - ], + "required": ["placeholder"], "additionalProperties": false }, "optionValues": { @@ -1690,9 +1569,7 @@ "type": "string" } }, - "required": [ - "placeholder" - ], + "required": ["placeholder"], "additionalProperties": false }, "productVariants": { @@ -1711,12 +1588,7 @@ "type": "string" } }, - "required": [ - "label", - "hint", - "alert", - "tip" - ], + "required": ["label", "hint", "alert", "tip"], "additionalProperties": false }, "productOptions": { @@ -1729,10 +1601,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false } }, @@ -1782,10 +1651,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "filters": { @@ -1798,10 +1664,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "columns": { @@ -1814,10 +1677,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -1855,10 +1715,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "upload": { @@ -1899,10 +1756,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -1996,11 +1850,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "action" - ], + "required": ["header", "description", "action"], "additionalProperties": false }, "successToast": { @@ -2059,12 +1909,7 @@ "type": "string" } }, - "required": [ - "draft", - "published", - "proposed", - "rejected" - ], + "required": ["draft", "published", "proposed", "rejected"], "additionalProperties": false }, "fields": { @@ -2080,10 +1925,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "subtitle": { @@ -2093,9 +1935,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "handle": { @@ -2108,10 +1948,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip" - ], + "required": ["label", "tooltip"], "additionalProperties": false }, "description": { @@ -2124,10 +1961,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "discountable": { @@ -2140,10 +1974,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "type": { @@ -2153,9 +1984,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "collection": { @@ -2165,9 +1994,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "categories": { @@ -2177,9 +2004,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "tags": { @@ -2189,9 +2014,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "sales_channels": { @@ -2204,10 +2027,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "countryOrigin": { @@ -2217,9 +2037,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "material": { @@ -2229,9 +2047,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "width": { @@ -2241,9 +2057,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "length": { @@ -2253,9 +2067,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "height": { @@ -2265,9 +2077,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "weight": { @@ -2277,9 +2087,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "options": { @@ -2328,10 +2136,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "mid_code": { @@ -2341,9 +2146,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "hs_code": { @@ -2353,9 +2156,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false } }, @@ -2396,10 +2197,7 @@ "type": "string" } }, - "required": [ - "header", - "success" - ], + "required": ["header", "success"], "additionalProperties": false }, "create": { @@ -2409,9 +2207,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "deleteWarning": { @@ -2457,10 +2253,7 @@ "type": "string" } }, - "required": [ - "inventoryItems", - "inventoryKit" - ], + "required": ["inventoryItems", "inventoryKit"], "additionalProperties": false }, "inventoryKit": { @@ -2479,10 +2272,7 @@ "type": "string" } }, - "required": [ - "itemId", - "quantity" - ], + "required": ["itemId", "quantity"], "additionalProperties": false }, "header": { @@ -2577,10 +2367,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "create": { @@ -2593,22 +2380,14 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "deleteWarning": { "type": "string" } }, - "required": [ - "header", - "edit", - "create", - "deleteWarning" - ], + "required": ["header", "edit", "create", "deleteWarning"], "additionalProperties": false }, "organization": { @@ -2630,23 +2409,15 @@ "type": "string" } }, - "required": [ - "success" - ], + "required": ["success"], "additionalProperties": false } }, - "required": [ - "header", - "toasts" - ], + "required": ["header", "toasts"], "additionalProperties": false } }, - "required": [ - "header", - "edit" - ], + "required": ["header", "edit"], "additionalProperties": false }, "stock": { @@ -2671,10 +2442,7 @@ "type": "string" } }, - "required": [ - "alreadyManaged", - "alreadyManagedWithSku" - ], + "required": ["alreadyManaged", "alreadyManagedWithSku"], "additionalProperties": false }, "successToast": { @@ -2706,10 +2474,7 @@ "type": "string" } }, - "required": [ - "header", - "description" - ], + "required": ["header", "description"], "additionalProperties": false }, "error": { @@ -2719,22 +2484,15 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false } }, - "required": [ - "success", - "error" - ], + "required": ["success", "error"], "additionalProperties": false } }, - "required": [ - "delete" - ], + "required": ["delete"], "additionalProperties": false } }, @@ -2813,9 +2571,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "add": { @@ -2828,10 +2584,7 @@ "type": "string" } }, - "required": [ - "successToast_one", - "successToast_other" - ], + "required": ["successToast_one", "successToast_other"], "additionalProperties": false }, "remove": { @@ -2844,18 +2597,11 @@ "type": "string" } }, - "required": [ - "successToast_one", - "successToast_other" - ], + "required": ["successToast_one", "successToast_other"], "additionalProperties": false } }, - "required": [ - "list", - "add", - "remove" - ], + "required": ["list", "add", "remove"], "additionalProperties": false } }, @@ -2903,22 +2649,14 @@ "type": "string" } }, - "required": [ - "details", - "organize" - ], + "required": ["details", "organize"], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": [ - "header", - "hint", - "tabs", - "successToast" - ], + "required": ["header", "hint", "tabs", "successToast"], "additionalProperties": false }, "edit": { @@ -2934,11 +2672,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "delete": { @@ -2951,10 +2685,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "products": { @@ -3011,17 +2742,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "add", - "remove", - "list" - ], + "required": ["add", "remove", "list"], "additionalProperties": false }, "organize": { @@ -3034,10 +2759,7 @@ "type": "string" } }, - "required": [ - "header", - "action" - ], + "required": ["header", "action"], "additionalProperties": false }, "fields": { @@ -3056,11 +2778,7 @@ "type": "string" } }, - "required": [ - "label", - "internal", - "public" - ], + "required": ["label", "internal", "public"], "additionalProperties": false }, "status": { @@ -3076,11 +2794,7 @@ "type": "string" } }, - "required": [ - "label", - "active", - "inactive" - ], + "required": ["label", "active", "inactive"], "additionalProperties": false }, "path": { @@ -3093,10 +2807,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip" - ], + "required": ["label", "tooltip"], "additionalProperties": false }, "children": { @@ -3106,9 +2817,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "new": { @@ -3118,19 +2827,11 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false } }, - "required": [ - "visibility", - "status", - "path", - "children", - "new" - ], + "required": ["visibility", "status", "path", "children", "new"], "additionalProperties": false } }, @@ -3280,10 +2981,7 @@ "type": "string" } }, - "required": [ - "noAvaliableQuantity", - "quantityOutOfRange" - ], + "required": ["noAvaliableQuantity", "quantityOutOfRange"], "additionalProperties": false } }, @@ -3319,15 +3017,11 @@ "type": "string" } }, - "required": [ - "stockedQuantity" - ], + "required": ["stockedQuantity"], "additionalProperties": false } }, - "required": [ - "errors" - ], + "required": ["errors"], "additionalProperties": false }, "toast": { @@ -3343,11 +3037,7 @@ "type": "string" } }, - "required": [ - "updateLocations", - "updateLevel", - "updateItem" - ], + "required": ["updateLocations", "updateLevel", "updateItem"], "additionalProperties": false }, "stock": { @@ -3366,12 +3056,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "action", - "successToast" - ], + "required": ["title", "description", "action", "successToast"], "additionalProperties": false } }, @@ -3478,9 +3163,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "create": { @@ -3496,11 +3179,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "groups": { @@ -3525,9 +3204,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "add": { @@ -3543,16 +3220,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "success", - "list" - ], + "required": ["success", "list"], "additionalProperties": false }, "removed": { @@ -3568,16 +3240,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "success", - "list" - ], + "required": ["success", "list"], "additionalProperties": false } }, @@ -3605,11 +3272,7 @@ "type": "string" } }, - "required": [ - "header", - "emailDisabledTooltip", - "successToast" - ], + "required": ["header", "emailDisabledTooltip", "successToast"], "additionalProperties": false }, "delete": { @@ -3625,11 +3288,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "fields": { @@ -3645,11 +3304,7 @@ "type": "string" } }, - "required": [ - "guest", - "registered", - "groups" - ], + "required": ["guest", "registered", "groups"], "additionalProperties": false }, "registered": { @@ -3698,11 +3353,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -3715,10 +3366,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "delete": { @@ -3734,11 +3382,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "customers": { @@ -3763,17 +3407,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "successToast_one", - "successToast_other", - "list" - ], + "required": ["successToast_one", "successToast_other", "list"], "additionalProperties": false }, "remove": { @@ -3807,18 +3445,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "alreadyAddedTooltip", - "add", - "remove", - "list" - ], + "required": ["alreadyAddedTooltip", "add", "remove", "list"], "additionalProperties": false } }, @@ -3860,9 +3491,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "summary": { @@ -4154,10 +3783,7 @@ "type": "string" } }, - "required": [ - "title", - "titlePending" - ], + "required": ["title", "titlePending"], "additionalProperties": false }, "toast": { @@ -4170,10 +3796,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "validation": { @@ -4183,9 +3806,7 @@ "type": "string" } }, - "required": [ - "quantityLowerThanFulfillment" - ], + "required": ["quantityLowerThanFulfillment"], "additionalProperties": false } }, @@ -4226,10 +3847,7 @@ "type": "string" } }, - "required": [ - "title", - "requestSuccess" - ], + "required": ["title", "requestSuccess"], "additionalProperties": false }, "shippingAddress": { @@ -4242,10 +3860,7 @@ "type": "string" } }, - "required": [ - "title", - "requestSuccess" - ], + "required": ["title", "requestSuccess"], "additionalProperties": false }, "billingAddress": { @@ -4258,18 +3873,11 @@ "type": "string" } }, - "required": [ - "title", - "requestSuccess" - ], + "required": ["title", "requestSuccess"], "additionalProperties": false } }, - "required": [ - "email", - "shippingAddress", - "billingAddress" - ], + "required": ["email", "shippingAddress", "billingAddress"], "additionalProperties": false }, "returns": { @@ -4375,10 +3983,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "placeholders": { @@ -4394,10 +3999,7 @@ "type": "string" } }, - "required": [ - "title", - "hint" - ], + "required": ["title", "hint"], "additionalProperties": false }, "outboundShippingOptions": { @@ -4410,10 +4012,7 @@ "type": "string" } }, - "required": [ - "title", - "hint" - ], + "required": ["title", "hint"], "additionalProperties": false } }, @@ -4498,10 +4097,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "panel": { @@ -4514,10 +4110,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -4606,15 +4199,11 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false } }, - "required": [ - "cancelClaim" - ], + "required": ["cancelClaim"], "additionalProperties": false }, "cancel": { @@ -4627,10 +4216,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "tooltips": { @@ -4640,9 +4226,7 @@ "type": "string" } }, - "required": [ - "onlyReturnShippingOptions" - ], + "required": ["onlyReturnShippingOptions"], "additionalProperties": false }, "toast": { @@ -4655,10 +4239,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "panel": { @@ -4671,10 +4252,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -4744,15 +4322,11 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false } }, - "required": [ - "cancelExchange" - ], + "required": ["cancelExchange"], "additionalProperties": false }, "cancel": { @@ -4765,10 +4339,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "tooltips": { @@ -4778,9 +4349,7 @@ "type": "string" } }, - "required": [ - "onlyReturnShippingOptions" - ], + "required": ["onlyReturnShippingOptions"], "additionalProperties": false }, "toast": { @@ -4793,10 +4362,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "panel": { @@ -4809,10 +4375,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -4846,10 +4409,7 @@ "type": "string" } }, - "required": [ - "allocatedLabel", - "notAllocatedLabel" - ], + "required": ["allocatedLabel", "notAllocatedLabel"], "additionalProperties": false }, "allocateItems": { @@ -4886,9 +4446,7 @@ "type": "string" } }, - "required": [ - "created" - ], + "required": ["created"], "additionalProperties": false }, "error": { @@ -4898,9 +4456,7 @@ "type": "string" } }, - "required": [ - "quantityNotAllocated" - ], + "required": ["quantityNotAllocated"], "additionalProperties": false } }, @@ -5023,11 +4579,7 @@ "type": "string" } }, - "required": [ - "wrongQuantity", - "wrongQuantity_other", - "noItems" - ], + "required": ["wrongQuantity", "wrongQuantity_other", "noItems"], "additionalProperties": false }, "status": { @@ -5173,11 +4725,7 @@ "type": "string" } }, - "required": [ - "amountToLarge", - "amountNegative", - "reasonRequired" - ], + "required": ["amountToLarge", "amountNegative", "reasonRequired"], "additionalProperties": false } }, @@ -5273,10 +4821,7 @@ "type": "string" } }, - "required": [ - "toReturn", - "toSend" - ], + "required": ["toReturn", "toSend"], "additionalProperties": false }, "placed": { @@ -5289,10 +4834,7 @@ "type": "string" } }, - "required": [ - "title", - "fromSalesChannel" - ], + "required": ["title", "fromSalesChannel"], "additionalProperties": false }, "canceled": { @@ -5302,9 +4844,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "payment": { @@ -5323,12 +4863,7 @@ "type": "string" } }, - "required": [ - "awaiting", - "captured", - "canceled", - "refunded" - ], + "required": ["awaiting", "captured", "canceled", "refunded"], "additionalProperties": false }, "fulfillment": { @@ -5401,10 +4936,7 @@ "type": "string" } }, - "required": [ - "comment", - "byLine" - ], + "required": ["comment", "byLine"], "additionalProperties": false }, "claim": { @@ -5465,10 +4997,7 @@ "type": "string" } }, - "required": [ - "requested", - "confirmed" - ], + "required": ["requested", "confirmed"], "additionalProperties": false }, "transfer": { @@ -5484,11 +5013,7 @@ "type": "string" } }, - "required": [ - "requested", - "confirmed", - "declined" - ], + "required": ["requested", "confirmed", "declined"], "additionalProperties": false }, "update_order": { @@ -5504,11 +5029,7 @@ "type": "string" } }, - "required": [ - "shipping_address", - "billing_address", - "email" - ], + "required": ["shipping_address", "billing_address", "email"], "additionalProperties": false } }, @@ -5553,11 +5074,7 @@ "type": "string" } }, - "required": [ - "displayId", - "refundableAmount", - "returnableQuantity" - ], + "required": ["displayId", "refundableAmount", "returnableQuantity"], "additionalProperties": false } }, @@ -5616,11 +5133,7 @@ "type": "string" } }, - "required": [ - "label", - "warningTitle", - "warningDescription" - ], + "required": ["label", "warningTitle", "warningDescription"], "additionalProperties": false }, "status": { @@ -5633,10 +5146,7 @@ "type": "string" } }, - "required": [ - "open", - "completed" - ], + "required": ["open", "completed"], "additionalProperties": false }, "create": { @@ -5777,9 +5287,7 @@ "type": "string" } }, - "required": [ - "description" - ], + "required": ["description"], "additionalProperties": false }, "create": { @@ -5795,11 +5303,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -5815,11 +5319,7 @@ "type": "string" } }, - "required": [ - "header", - "viewInventory", - "successToast" - ], + "required": ["header", "viewInventory", "successToast"], "additionalProperties": false }, "delete": { @@ -5829,9 +5329,7 @@ "type": "string" } }, - "required": [ - "confirmation" - ], + "required": ["confirmation"], "additionalProperties": false }, "fulfillmentProviders": { @@ -5880,9 +5378,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "shipping": { @@ -5892,9 +5388,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "disable": { @@ -5910,11 +5404,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "pickup", - "shipping" - ], + "required": ["confirmation", "pickup", "shipping"], "additionalProperties": false }, "enable": { @@ -5927,19 +5417,11 @@ "type": "string" } }, - "required": [ - "pickup", - "shipping" - ], + "required": ["pickup", "shipping"], "additionalProperties": false } }, - "required": [ - "pickup", - "shipping", - "disable", - "enable" - ], + "required": ["pickup", "shipping", "disable", "enable"], "additionalProperties": false }, "sidebar": { @@ -5958,17 +5440,11 @@ "type": "string" } }, - "required": [ - "label", - "description" - ], + "required": ["label", "description"], "additionalProperties": false } }, - "required": [ - "header", - "shippingProfiles" - ], + "required": ["header", "shippingProfiles"], "additionalProperties": false }, "salesChannels": { @@ -6025,12 +5501,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "label", - "successToast" - ], + "required": ["header", "hint", "label", "successToast"], "additionalProperties": false }, "returns": { @@ -6049,12 +5520,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "label", - "successToast" - ], + "required": ["header", "hint", "label", "successToast"], "additionalProperties": false }, "tabs": { @@ -6067,22 +5533,14 @@ "type": "string" } }, - "required": [ - "details", - "prices" - ], + "required": ["details", "prices"], "additionalProperties": false }, "action": { "type": "string" } }, - "required": [ - "shipping", - "returns", - "tabs", - "action" - ], + "required": ["shipping", "returns", "tabs", "action"], "additionalProperties": false }, "delete": { @@ -6095,10 +5553,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "edit": { @@ -6114,11 +5569,7 @@ "type": "string" } }, - "required": [ - "header", - "action", - "successToast" - ], + "required": ["header", "action", "successToast"], "additionalProperties": false }, "pricing": { @@ -6128,9 +5579,7 @@ "type": "string" } }, - "required": [ - "action" - ], + "required": ["action"], "additionalProperties": false }, "conditionalPrices": { @@ -6149,9 +5598,7 @@ "type": "string" } }, - "required": [ - "cartItemTotal" - ], + "required": ["cartItemTotal"], "additionalProperties": false }, "summaries": { @@ -6167,11 +5614,7 @@ "type": "string" } }, - "required": [ - "range", - "greaterThan", - "lessThan" - ], + "required": ["range", "greaterThan", "lessThan"], "additionalProperties": false }, "actions": { @@ -6184,10 +5627,7 @@ "type": "string" } }, - "required": [ - "addPrice", - "manageConditionalPrices" - ], + "required": ["addPrice", "manageConditionalPrices"], "additionalProperties": false }, "rules": { @@ -6203,11 +5643,7 @@ "type": "string" } }, - "required": [ - "amount", - "gte", - "lte" - ], + "required": ["amount", "gte", "lte"], "additionalProperties": false }, "customRules": { @@ -6229,13 +5665,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip", - "eq", - "gt", - "lt" - ], + "required": ["label", "tooltip", "eq", "gt", "lt"], "additionalProperties": false }, "errors": { @@ -6325,10 +5755,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "calculated": { @@ -6341,24 +5768,15 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false } }, - "required": [ - "fixed", - "calculated" - ], + "required": ["fixed", "calculated"], "additionalProperties": false } }, - "required": [ - "label", - "options" - ], + "required": ["label", "options"], "additionalProperties": false }, "enableInStore": { @@ -6371,10 +5789,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "provider": { @@ -6441,10 +5856,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "delete": { @@ -6457,10 +5869,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "manageAreas": { @@ -6482,13 +5891,7 @@ "type": "string" } }, - "required": [ - "header", - "action", - "label", - "hint", - "successToast" - ], + "required": ["header", "action", "label", "hint", "successToast"], "additionalProperties": false }, "fields": { @@ -6501,20 +5904,11 @@ "type": "string" } }, - "required": [ - "noRecords", - "tip" - ], + "required": ["noRecords", "tip"], "additionalProperties": false } }, - "required": [ - "create", - "edit", - "delete", - "manageAreas", - "fields" - ], + "required": ["create", "edit", "delete", "manageAreas", "fields"], "additionalProperties": false } }, @@ -6555,11 +5949,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "delete": { @@ -6575,11 +5965,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "tooltip": { @@ -6589,19 +5975,11 @@ "type": "string" } }, - "required": [ - "type" - ], + "required": ["type"], "additionalProperties": false } }, - "required": [ - "domain", - "subtitle", - "create", - "delete", - "tooltip" - ], + "required": ["domain", "subtitle", "create", "delete", "tooltip"], "additionalProperties": false }, "taxRegions": { @@ -6617,9 +5995,7 @@ "type": "string" } }, - "required": [ - "hint" - ], + "required": ["hint"], "additionalProperties": false }, "delete": { @@ -6632,10 +6008,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "create": { @@ -6657,22 +6030,14 @@ "type": "string" } }, - "required": [ - "rateIsRequired", - "nameIsRequired" - ], + "required": ["rateIsRequired", "nameIsRequired"], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": [ - "header", - "hint", - "errors", - "successToast" - ], + "required": ["header", "hint", "errors", "successToast"], "additionalProperties": false }, "province": { @@ -6691,17 +6056,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "state": { @@ -6720,17 +6079,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "stateOrTerritory": { @@ -6749,17 +6102,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "county": { @@ -6778,17 +6125,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "region": { @@ -6807,17 +6148,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "department": { @@ -6836,17 +6171,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "territory": { @@ -6865,17 +6194,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "prefecture": { @@ -6894,17 +6217,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "district": { @@ -6923,17 +6240,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "governorate": { @@ -6952,17 +6263,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "canton": { @@ -6981,17 +6286,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "emirate": { @@ -7010,17 +6309,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "sublevel": { @@ -7039,17 +6332,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "taxOverrides": { @@ -7068,10 +6355,7 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false }, "edit": { @@ -7084,18 +6368,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create", - "edit" - ], + "required": ["header", "create", "edit"], "additionalProperties": false }, "taxRates": { @@ -7114,11 +6391,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -7134,11 +6407,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "delete": { @@ -7151,18 +6420,11 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false } }, - "required": [ - "create", - "edit", - "delete" - ], + "required": ["create", "edit", "delete"], "additionalProperties": false }, "fields": { @@ -7184,12 +6446,7 @@ "type": "string" } }, - "required": [ - "label", - "hint", - "true", - "false" - ], + "required": ["label", "hint", "true", "false"], "additionalProperties": false }, "defaultTaxRate": { @@ -7205,11 +6462,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip", - "action" - ], + "required": ["label", "tooltip", "action"], "additionalProperties": false }, "taxRate": { @@ -7268,11 +6521,7 @@ "type": "string" } }, - "required": [ - "in", - "on", - "and" - ], + "required": ["in", "on", "and"], "additionalProperties": false }, "placeholders": { @@ -7338,9 +6587,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "values_one": { @@ -7512,10 +6759,7 @@ "type": "string" } }, - "required": [ - "sublevel", - "notPartOfCountry" - ], + "required": ["sublevel", "notPartOfCountry"], "additionalProperties": false }, "alert": { @@ -7531,20 +6775,11 @@ "type": "string" } }, - "required": [ - "header", - "description", - "action" - ], + "required": ["header", "description", "action"], "additionalProperties": false } }, - "required": [ - "labels", - "placeholders", - "tooltips", - "alert" - ], + "required": ["labels", "placeholders", "tooltips", "alert"], "additionalProperties": false }, "noDefaultRate": { @@ -7557,10 +6792,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip" - ], + "required": ["label", "tooltip"], "additionalProperties": false } }, @@ -7613,9 +6845,7 @@ "type": "string" } }, - "required": [ - "details" - ], + "required": ["details"], "additionalProperties": false }, "tabs": { @@ -7631,11 +6861,7 @@ "type": "string" } }, - "required": [ - "template", - "details", - "campaign" - ], + "required": ["template", "details", "campaign"], "additionalProperties": false }, "fields": { @@ -7672,9 +6898,7 @@ "type": "string" } }, - "required": [ - "tooltip" - ], + "required": ["tooltip"], "additionalProperties": false }, "conditions": { @@ -7690,10 +6914,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "target-rules": { @@ -7706,10 +6927,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "buy-rules": { @@ -7722,18 +6940,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "rules", - "target-rules", - "buy-rules" - ], + "required": ["rules", "target-rules", "buy-rules"], "additionalProperties": false } }, @@ -7758,9 +6969,7 @@ "type": "string" } }, - "required": [ - "campaignType" - ], + "required": ["campaignType"], "additionalProperties": false }, "errors": { @@ -7773,10 +6982,7 @@ "type": "string" } }, - "required": [ - "requiredField", - "promotionTabError" - ], + "required": ["requiredField", "promotionTabError"], "additionalProperties": false }, "toasts": { @@ -7786,9 +6992,7 @@ "type": "string" } }, - "required": [ - "promotionCreateSuccess" - ], + "required": ["promotionCreateSuccess"], "additionalProperties": false }, "create": { @@ -7810,9 +7014,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "target-rules": { @@ -7822,9 +7024,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "buy-rules": { @@ -7834,18 +7034,11 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false } }, - "required": [ - "title", - "rules", - "target-rules", - "buy-rules" - ], + "required": ["title", "rules", "target-rules", "buy-rules"], "additionalProperties": false }, "campaign": { @@ -7864,10 +7057,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "actions": { @@ -7877,17 +7067,11 @@ "type": "string" } }, - "required": [ - "goToCampaign" - ], + "required": ["goToCampaign"], "additionalProperties": false } }, - "required": [ - "header", - "edit", - "actions" - ], + "required": ["header", "edit", "actions"], "additionalProperties": false }, "campaign_currency": { @@ -7897,9 +7081,7 @@ "type": "string" } }, - "required": [ - "tooltip" - ], + "required": ["tooltip"], "additionalProperties": false }, "form": { @@ -7936,18 +7118,11 @@ "type": "string" } }, - "required": [ - "title", - "desc" - ], + "required": ["title", "desc"], "additionalProperties": false } }, - "required": [ - "title", - "description", - "placeholder" - ], + "required": ["title", "description", "placeholder"], "additionalProperties": false }, "new": { @@ -7960,10 +7135,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "none": { @@ -7976,18 +7148,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "existing", - "new", - "none" - ], + "required": ["existing", "new", "none"], "additionalProperties": false }, "status": { @@ -7997,9 +7162,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "method": { @@ -8018,10 +7181,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "automatic": { @@ -8034,18 +7194,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "label", - "code", - "automatic" - ], + "required": ["label", "code", "automatic"], "additionalProperties": false }, "max_quantity": { @@ -8058,10 +7211,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "type": { @@ -8077,10 +7227,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "buyget": { @@ -8093,17 +7240,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "standard", - "buyget" - ], + "required": ["standard", "buyget"], "additionalProperties": false }, "allocation": { @@ -8119,10 +7260,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "across": { @@ -8135,17 +7273,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "each", - "across" - ], + "required": ["each", "across"], "additionalProperties": false }, "code": { @@ -8158,10 +7290,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "value": { @@ -8171,9 +7300,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "value_type": { @@ -8189,10 +7316,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "percentage": { @@ -8205,17 +7329,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "fixed", - "percentage" - ], + "required": ["fixed", "percentage"], "additionalProperties": false } }, @@ -8257,16 +7375,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "add", - "list" - ], + "required": ["add", "list"], "additionalProperties": false } }, @@ -8312,11 +7425,7 @@ "type": "string" } }, - "required": [ - "active", - "expired", - "scheduled" - ], + "required": ["active", "expired", "scheduled"], "additionalProperties": false }, "delete": { @@ -8332,11 +7441,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "edit": { @@ -8352,11 +7457,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "configuration": { @@ -8378,18 +7479,11 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false } }, - "required": [ - "header", - "edit" - ], + "required": ["header", "edit"], "additionalProperties": false }, "create": { @@ -8451,9 +7545,7 @@ "type": "string" } }, - "required": [ - "hint" - ], + "required": ["hint"], "additionalProperties": false } }, @@ -8482,10 +7574,7 @@ "type": "string" } }, - "required": [ - "hint", - "header" - ], + "required": ["hint", "header"], "additionalProperties": false }, "details": { @@ -8507,12 +7596,7 @@ "type": "string" } }, - "required": [ - "type", - "currency", - "limit", - "used" - ], + "required": ["type", "currency", "limit", "used"], "additionalProperties": false }, "type": { @@ -8528,10 +7612,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "usage": { @@ -8544,17 +7625,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "spend", - "usage" - ], + "required": ["spend", "usage"], "additionalProperties": false }, "edit": { @@ -8564,19 +7639,11 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false } - }, - "required": [ - "create", - "details", - "fields", - "type", - "edit" - ], + }, + "required": ["create", "details", "fields", "type", "edit"], "additionalProperties": false }, "promotions": { @@ -8592,10 +7659,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "alreadyAdded": { @@ -8614,9 +7678,7 @@ "type": "string" } }, - "required": [ - "success" - ], + "required": ["success"], "additionalProperties": false }, "add": { @@ -8629,15 +7691,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false }, "list": { @@ -8647,9 +7705,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, @@ -8706,10 +7762,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "create": { @@ -8734,11 +7787,7 @@ "type": "string" } }, - "required": [ - "details", - "products", - "prices" - ], + "required": ["details", "products", "prices"], "additionalProperties": false }, "successToast": { @@ -8754,15 +7803,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false } }, @@ -8785,10 +7830,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "configuration": { @@ -8810,18 +7852,11 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false } }, - "required": [ - "header", - "edit" - ], + "required": ["header", "edit"], "additionalProperties": false }, "products": { @@ -8840,10 +7875,7 @@ "type": "string" } }, - "required": [ - "addProducts", - "editPrices" - ], + "required": ["addProducts", "editPrices"], "additionalProperties": false }, "delete": { @@ -8877,9 +7909,7 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false }, "edit": { @@ -8889,19 +7919,11 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false } }, - "required": [ - "header", - "actions", - "delete", - "add", - "edit" - ], + "required": ["header", "actions", "delete", "add", "edit"], "additionalProperties": false }, "fields": { @@ -8917,10 +7939,7 @@ "type": "string" } }, - "required": [ - "label", - "header" - ], + "required": ["label", "header"], "additionalProperties": false }, "status": { @@ -8945,19 +7964,11 @@ "type": "string" } }, - "required": [ - "active", - "draft", - "expired", - "scheduled" - ], + "required": ["active", "draft", "expired", "scheduled"], "additionalProperties": false } }, - "required": [ - "label", - "options" - ], + "required": ["label", "options"], "additionalProperties": false }, "type": { @@ -8982,10 +7993,7 @@ "type": "string" } }, - "required": [ - "label", - "description" - ], + "required": ["label", "description"], "additionalProperties": false }, "override": { @@ -8998,25 +8006,15 @@ "type": "string" } }, - "required": [ - "label", - "description" - ], + "required": ["label", "description"], "additionalProperties": false } }, - "required": [ - "sale", - "override" - ], + "required": ["sale", "override"], "additionalProperties": false } }, - "required": [ - "label", - "hint", - "options" - ], + "required": ["label", "hint", "options"], "additionalProperties": false }, "startsAt": { @@ -9029,10 +8027,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "endsAt": { @@ -9045,10 +8040,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "customerAvailability": { @@ -9122,10 +8114,7 @@ "type": "string" } }, - "required": [ - "languageLabel", - "usageInsightsLabel" - ], + "required": ["languageLabel", "usageInsightsLabel"], "additionalProperties": false }, "edit": { @@ -9159,9 +8148,7 @@ "type": "string" } }, - "required": [ - "edit" - ], + "required": ["edit"], "additionalProperties": false } }, @@ -9226,11 +8213,7 @@ "type": "string" } }, - "required": [ - "accepted", - "pending", - "expired" - ], + "required": ["accepted", "pending", "expired"], "additionalProperties": false }, "roles": { @@ -9246,11 +8229,7 @@ "type": "string" } }, - "required": [ - "admin", - "developer", - "member" - ], + "required": ["admin", "developer", "member"], "additionalProperties": false }, "deleteUserWarning": { @@ -9335,9 +8314,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "toast": { @@ -9459,9 +8436,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "toast": { @@ -9480,12 +8455,7 @@ "type": "string" } }, - "required": [ - "delete", - "edit", - "create", - "countries" - ], + "required": ["delete", "edit", "create", "countries"], "additionalProperties": false }, "shippingOption": { @@ -9519,12 +8489,7 @@ "type": "string" } }, - "required": [ - "outbound", - "outboundHint", - "return", - "returnHint" - ], + "required": ["outbound", "outboundHint", "return", "returnHint"], "additionalProperties": false }, "priceType": { @@ -9540,11 +8505,7 @@ "type": "string" } }, - "required": [ - "label", - "flatRate", - "calculated" - ], + "required": ["label", "flatRate", "calculated"], "additionalProperties": false }, "availability": { @@ -9557,10 +8518,7 @@ "type": "string" } }, - "required": [ - "adminOnly", - "adminOnlyHint" - ], + "required": ["adminOnly", "adminOnlyHint"], "additionalProperties": false }, "taxInclusiveHint": { @@ -9576,10 +8534,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false } }, @@ -9641,9 +8596,7 @@ "type": "string" } }, - "required": [ - "taxCountriesHint" - ], + "required": ["taxCountriesHint"], "additionalProperties": false }, "settings": { @@ -9697,9 +8650,7 @@ "type": "string" } }, - "required": [ - "sectionTitle" - ], + "required": ["sectionTitle"], "additionalProperties": false }, "taxRate": { @@ -9849,11 +8800,7 @@ "type": "string" } }, - "required": [ - "create", - "update", - "removeChannel" - ], + "required": ["create", "update", "removeChannel"], "additionalProperties": false } }, @@ -9883,11 +8830,7 @@ "type": "string" } }, - "required": [ - "domain", - "subtitle", - "deleteWarning" - ], + "required": ["domain", "subtitle", "deleteWarning"], "additionalProperties": false }, "salesChannels": { @@ -9939,11 +8882,7 @@ "type": "string" } }, - "required": [ - "create", - "update", - "delete" - ], + "required": ["create", "update", "delete"], "additionalProperties": false }, "tooltip": { @@ -9953,9 +8892,7 @@ "type": "string" } }, - "required": [ - "cannotDeleteDefault" - ], + "required": ["cannotDeleteDefault"], "additionalProperties": false }, "products": { @@ -9968,9 +8905,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "add": { @@ -9983,22 +8918,15 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false } }, - "required": [ - "list", - "add" - ], + "required": ["list", "add"], "additionalProperties": false } }, @@ -10033,10 +8961,7 @@ "type": "string" } }, - "required": [ - "publishable", - "secret" - ], + "required": ["publishable", "secret"], "additionalProperties": false }, "subtitle": { @@ -10049,10 +8974,7 @@ "type": "string" } }, - "required": [ - "publishable", - "secret" - ], + "required": ["publishable", "secret"], "additionalProperties": false }, "status": { @@ -10065,10 +8987,7 @@ "type": "string" } }, - "required": [ - "active", - "revoked" - ], + "required": ["active", "revoked"], "additionalProperties": false }, "type": { @@ -10081,10 +9000,7 @@ "type": "string" } }, - "required": [ - "publishable", - "secret" - ], + "required": ["publishable", "secret"], "additionalProperties": false }, "create": { @@ -10144,11 +9060,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "salesChannels": { @@ -10176,9 +9088,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, @@ -10202,10 +9112,7 @@ "type": "string" } }, - "required": [ - "warning", - "successToast" - ], + "required": ["warning", "successToast"], "additionalProperties": false }, "revoke": { @@ -10218,10 +9125,7 @@ "type": "string" } }, - "required": [ - "warning", - "successToast" - ], + "required": ["warning", "successToast"], "additionalProperties": false }, "addSalesChannels": { @@ -10234,15 +9138,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false }, "removeSalesChannel": { @@ -10290,11 +9190,7 @@ "type": "string" } }, - "required": [ - "revoke", - "copy", - "copySuccessToast" - ], + "required": ["revoke", "copy", "copySuccessToast"], "additionalProperties": false }, "table": { @@ -10307,10 +9203,7 @@ "type": "string" } }, - "required": [ - "lastUsedAtHeader", - "createdAtHeader" - ], + "required": ["lastUsedAtHeader", "createdAtHeader"], "additionalProperties": false }, "fields": { @@ -10387,12 +9280,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "hint", - "successToast" - ], + "required": ["header", "subtitle", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -10408,11 +9296,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "successToast" - ], + "required": ["header", "subtitle", "successToast"], "additionalProperties": false }, "delete": { @@ -10425,10 +9309,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "fields": { @@ -10447,11 +9328,7 @@ "type": "string" } }, - "required": [ - "label", - "placeholder", - "tooltip" - ], + "required": ["label", "placeholder", "tooltip"], "additionalProperties": false }, "label": { @@ -10464,10 +9341,7 @@ "type": "string" } }, - "required": [ - "label", - "placeholder" - ], + "required": ["label", "placeholder"], "additionalProperties": false }, "description": { @@ -10480,18 +9354,11 @@ "type": "string" } }, - "required": [ - "label", - "placeholder" - ], + "required": ["label", "placeholder"], "additionalProperties": false } }, - "required": [ - "value", - "label", - "description" - ], + "required": ["value", "label", "description"], "additionalProperties": false } }, @@ -10520,11 +9387,7 @@ "type": "string" } }, - "required": [ - "forgotPassword", - "title", - "hint" - ], + "required": ["forgotPassword", "title", "hint"], "additionalProperties": false }, "invite": { @@ -10576,9 +9439,7 @@ "type": "string" } }, - "required": [ - "accepted" - ], + "required": ["accepted"], "additionalProperties": false } }, @@ -10723,9 +9584,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "history": { @@ -10822,15 +9681,11 @@ "type": "string" } }, - "required": [ - "waitingToCompensate" - ], + "required": ["waitingToCompensate"], "additionalProperties": false } }, - "required": [ - "state" - ], + "required": ["state"], "additionalProperties": false }, "step": { @@ -10852,18 +9707,11 @@ "type": "string" } }, - "required": [ - "skipped", - "skippedFailure", - "dormant", - "timeout" - ], + "required": ["skipped", "skippedFailure", "dormant", "timeout"], "additionalProperties": false } }, - "required": [ - "state" - ], + "required": ["state"], "additionalProperties": false } }, @@ -10905,11 +9753,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -10922,10 +9766,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "delete": { @@ -10938,10 +9779,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "fields": { @@ -10951,20 +9789,11 @@ "type": "string" } }, - "required": [ - "value" - ], + "required": ["value"], "additionalProperties": false } }, - "required": [ - "domain", - "subtitle", - "create", - "edit", - "delete", - "fields" - ], + "required": ["domain", "subtitle", "create", "edit", "delete", "fields"], "additionalProperties": false }, "productTags": { @@ -10986,11 +9815,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "successToast" - ], + "required": ["header", "subtitle", "successToast"], "additionalProperties": false }, "edit": { @@ -11006,11 +9831,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "successToast" - ], + "required": ["header", "subtitle", "successToast"], "additionalProperties": false }, "delete": { @@ -11023,10 +9844,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "fields": { @@ -11036,19 +9854,11 @@ "type": "string" } }, - "required": [ - "value" - ], + "required": ["value"], "additionalProperties": false } }, - "required": [ - "domain", - "create", - "edit", - "delete", - "fields" - ], + "required": ["domain", "create", "edit", "delete", "fields"], "additionalProperties": false }, "notifications": { @@ -11067,10 +9877,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "accessibility": { @@ -11080,17 +9887,11 @@ "type": "string" } }, - "required": [ - "description" - ], + "required": ["description"], "additionalProperties": false } }, - "required": [ - "domain", - "emptyState", - "accessibility" - ], + "required": ["domain", "emptyState", "accessibility"], "additionalProperties": false }, "errors": { @@ -11103,10 +9904,7 @@ "type": "string" } }, - "required": [ - "serverError", - "invalidCredentials" - ], + "required": ["serverError", "invalidCredentials"], "additionalProperties": false }, "statuses": { @@ -11128,13 +9926,7 @@ "type": "string" } }, - "required": [ - "scheduled", - "expired", - "active", - "enabled", - "disabled" - ], + "required": ["scheduled", "expired", "active", "enabled", "disabled"], "additionalProperties": false }, "labels": { @@ -11929,4 +10721,4 @@ "dateTime" ], "additionalProperties": false -} \ No newline at end of file +} From b9cb43e754fc57887210c972735abd6a4417a937 Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:05:23 +0100 Subject: [PATCH 07/19] add delete event and allow copy/pasting enabled for some fields --- .../hooks/use-data-grid-form-handlers.tsx | 18 +++++++++---- .../hooks/use-data-grid-keydown-event.tsx | 27 +++++++++++++++++++ 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx index 22fb519759eb9..48c17f6277196 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx @@ -170,17 +170,25 @@ function setValue< : null // Determine if checked should be updated - let shouldUpdateChecked = false - if (!disabledToggle && newQuantityNumber != null) { - if (currentChecked === false && newQuantityNumber > 0) { - shouldUpdateChecked = true + let newChecked = currentChecked + if (!disabledToggle) { + if ( + currentChecked === false && + newQuantityNumber != null && + newQuantityNumber > 0 + ) { + newChecked = true + } + + if (currentChecked === true && !newQuantityNumber) { + newChecked = false } } set(currentValues, field, { ...currentValue, quantity: newValue.quantity, - checked: shouldUpdateChecked ? true : currentChecked, + checked: newChecked, }) return diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx index 8e7030291b1a6..0a0dcce43e7a9 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx @@ -444,6 +444,29 @@ export const useDataGridKeydownEvent = < [anchor, matrix, handleEnterKeyTextOrNumber, handleEnterKeyBoolean] ) + const handleDeleteKeyTogglableNumber = useCallback( + (anchor: DataGridCoordinates, rangeEnd: DataGridCoordinates) => { + const fields = matrix.getFieldsInSelection(anchor, rangeEnd) + const prev = getSelectionValues(fields) + + const next = prev.map((value) => ({ + ...value, + quantity: "", + checked: value.disableToggle ? value.checked : false, + })) + + const command = new DataGridBulkUpdateCommand({ + fields, + next, + prev, + setter: setSelectionValues, + }) + + execute(command) + }, + [matrix, getSelectionValues, setSelectionValues, execute] + ) + const handleDeleteKeyTextOrNumber = useCallback( (anchor: DataGridCoordinates, rangeEnd: DataGridCoordinates) => { const fields = matrix.getFieldsInSelection(anchor, rangeEnd) @@ -502,6 +525,9 @@ export const useDataGridKeydownEvent = < case "boolean": handleDeleteKeyBoolean(anchor, rangeEnd) break + case "togglable-number": + handleDeleteKeyTogglableNumber(anchor, rangeEnd) + break } }, [ @@ -511,6 +537,7 @@ export const useDataGridKeydownEvent = < matrix, handleDeleteKeyTextOrNumber, handleDeleteKeyBoolean, + handleDeleteKeyTogglableNumber, ] ) From 60e0fd38dd83985d51be5299f4f4847f33c13671 Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 17 Dec 2024 15:14:29 +0100 Subject: [PATCH 08/19] add response types --- .../dashboard/src/hooks/api/inventory.tsx | 4 +-- .../core/js-sdk/src/admin/inventory-item.ts | 28 ++++++++----------- .../http/inventory-level/admin/responses.ts | 18 ++++++++++++ 3 files changed, 32 insertions(+), 18 deletions(-) diff --git a/packages/admin/dashboard/src/hooks/api/inventory.tsx b/packages/admin/dashboard/src/hooks/api/inventory.tsx index ca0a47cf17a3d..de8e7bd48c99b 100644 --- a/packages/admin/dashboard/src/hooks/api/inventory.tsx +++ b/packages/admin/dashboard/src/hooks/api/inventory.tsx @@ -214,7 +214,7 @@ export const useUpdateInventoryLevel = ( export const useBatchInventoryItemLocationLevels = ( inventoryItemId: string, options?: UseMutationOptions< - HttpTypes.AdminInventoryItemResponse, + HttpTypes.AdminBatchInventoryItemLocationLevelsResponse, FetchError, HttpTypes.AdminBatchInventoryItemLocationLevels > @@ -243,7 +243,7 @@ export const useBatchInventoryItemLocationLevels = ( export const useBatchInventoryItemsLocationLevels = ( options?: UseMutationOptions< - HttpTypes.AdminInventoryItemResponse, + HttpTypes.AdminBatchInventoryItemsLocationLevelsResponse, FetchError, HttpTypes.AdminBatchInventoryItemsLocationLevels > diff --git a/packages/core/js-sdk/src/admin/inventory-item.ts b/packages/core/js-sdk/src/admin/inventory-item.ts index b7ec760ab06e0..ffb6ebbba018e 100644 --- a/packages/core/js-sdk/src/admin/inventory-item.ts +++ b/packages/core/js-sdk/src/admin/inventory-item.ts @@ -369,10 +369,10 @@ export class InventoryItem { * location_id: "sloc_123", * stocked_quantity: 10 * }], - * delete: ["sloc_123"] + * delete: ["ilvl_123"] * }) - * .then(({ inventory_item }) => { - * console.log(inventory_item) + * .then(({ created, updated, deleted }) => { + * console.log(created, updated, deleted) * }) */ async batchUpdateLevels( @@ -381,7 +381,7 @@ export class InventoryItem { query?: SelectParams, headers?: ClientHeaders ) { - return await this.client.fetch( + return await this.client.fetch( `/admin/inventory-items/${id}/location-levels/batch`, { method: "POST", @@ -398,8 +398,7 @@ export class InventoryItem { * API route. * * @param id - The inventory item's ID. - * @param body - The inventory levels to create, update or delete. - * @param query - Configure the fields to retrieve in the inventory item. + * @param body - The inventory levels to create, update or delete, and an optional `force` flag. * @param headers - Headers to pass in the request * @returns The inventory item's details. * @@ -411,23 +410,21 @@ export class InventoryItem { * }], * delete: ["ilvl_123"] * }) - * .then(({ inventory_item }) => { - * console.log(inventory_item) + * .then(({ created, updated, deleted }) => { + * console.log(created, updated, deleted) * }) */ async batchInventoryItemLocationLevels( id: string, body: HttpTypes.AdminBatchInventoryItemLocationLevels, - query?: SelectParams, headers?: ClientHeaders ) { - return await this.client.fetch( + return await this.client.fetch( `/admin/inventory-items/${id}/location-levels/batch`, { method: "POST", headers, body, - query, } ) } @@ -435,8 +432,7 @@ export class InventoryItem { /** * This method manages the inventory levels of multiple inventory items. * - * @param body - The inventory levels to create, update or delete. - * @param query - Configure the fields to retrieve in the inventory item. + * @param body - The inventory levels to create, update or delete, and an optional `force` flag. * @param headers - Headers to pass in the request * @returns The inventory item's details. * @@ -449,15 +445,15 @@ export class InventoryItem { * }], * delete: ["ilvl_123"] * }) - * .then(({ inventory_item }) => { - * console.log(inventory_item) + * .then(({ created, updated, deleted }) => { + * console.log(created, updated, deleted) * }) */ async batchInventoryItemsLocationLevels( body: HttpTypes.AdminBatchInventoryItemsLocationLevels, headers?: ClientHeaders ) { - return await this.client.fetch( + return await this.client.fetch( `/admin/inventory-items/location-levels/batch`, { method: "POST", diff --git a/packages/core/types/src/http/inventory-level/admin/responses.ts b/packages/core/types/src/http/inventory-level/admin/responses.ts index 6a05d8e117b7e..409cd4f327615 100644 --- a/packages/core/types/src/http/inventory-level/admin/responses.ts +++ b/packages/core/types/src/http/inventory-level/admin/responses.ts @@ -14,3 +14,21 @@ export type AdminInventoryLevelListResponse = PaginatedResponse<{ */ inventory_levels: InventoryLevel[] }> + +export interface AdminBatchInventoryItemLocationLevelsResponse { + /** + * The created inventory levels. + */ + created?: InventoryLevel[] + /** + * The updated inventory levels. + */ + updated?: InventoryLevel[] + /** + * The IDs of the deleted inventory levels. + */ + deleted?: string[] +} + +export interface AdminBatchInventoryItemsLocationLevelsResponse + extends AdminBatchInventoryItemLocationLevelsResponse {} From 49468f45d4dd92fbf6fc83564958c1f1eb464258 Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 17 Dec 2024 16:58:03 +0100 Subject: [PATCH 09/19] add tests --- .../inventory/admin/inventory.spec.ts | 117 +++++++++++++++--- .../workflows/batch-inventory-item-levels.ts | 23 +++- .../api/admin/inventory-items/middlewares.ts | 9 +- 3 files changed, 119 insertions(+), 30 deletions(-) diff --git a/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts b/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts index 392d42489d0ed..9a62749b3c3af 100644 --- a/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts +++ b/integration-tests/http/__tests__/inventory/admin/inventory.spec.ts @@ -127,24 +127,29 @@ medusaIntegrationTestRunner({ }) describe("POST /admin/inventory-items/location-levels/batch", () => { + let locationLevel1 + let locationLevel2 + beforeEach(async () => { - await api.post( - `/admin/inventory-items/${inventoryItem1.id}/location-levels`, + const seed = await api.post( + `/admin/inventory-items/${inventoryItem1.id}/location-levels/batch`, { - location_id: stockLocation1.id, - stocked_quantity: 0, + create: [ + { + location_id: stockLocation1.id, + stocked_quantity: 0, + }, + { + location_id: stockLocation2.id, + stocked_quantity: 10, + }, + ], }, adminHeaders ) - await api.post( - `/admin/inventory-items/${inventoryItem1.id}/location-levels`, - { - location_id: stockLocation2.id, - stocked_quantity: 10, - }, - adminHeaders - ) + locationLevel1 = seed.data.created[0] + locationLevel2 = seed.data.created[1] }) it("should batch update the inventory levels", async () => { @@ -168,6 +173,22 @@ medusaIntegrationTestRunner({ ) expect(result.status).toEqual(200) + expect(result.data).toEqual( + expect.objectContaining({ + updated: expect.arrayContaining([ + expect.objectContaining({ + location_id: stockLocation1.id, + inventory_item_id: inventoryItem1.id, + stocked_quantity: 10, + }), + expect.objectContaining({ + location_id: stockLocation2.id, + inventory_item_id: inventoryItem1.id, + stocked_quantity: 20, + }), + ]), + }) + ) }) it("should batch create the inventory levels", async () => { @@ -186,12 +207,71 @@ medusaIntegrationTestRunner({ ) expect(result.status).toEqual(200) + expect(result.data).toEqual( + expect.objectContaining({ + created: expect.arrayContaining([ + expect.objectContaining({ + location_id: stockLocation3.id, + inventory_item_id: inventoryItem1.id, + stocked_quantity: 10, + }), + ]), + }) + ) + }) + + it("should batch delete the inventory levels when stocked quantity is 0 and force is false", async () => { + const result = await api.post( + `/admin/inventory-items/location-levels/batch`, + { delete: [locationLevel1.id] }, + adminHeaders + ) + + expect(result.status).toEqual(200) + expect(result.data).toEqual( + expect.objectContaining({ + deleted: [locationLevel1.id], + }) + ) + }) + + it("should not delete the inventory levels when stocked quantity is greater than 0 and force is false", async () => { + const error = await api + .post( + `/admin/inventory-items/location-levels/batch`, + { delete: [locationLevel2.id] }, + adminHeaders + ) + .catch((e) => e) + + expect(error.response.status).toEqual(400) + expect(error.response.data).toEqual({ + type: "not_allowed", + message: `Cannot remove Inventory Levels for ${stockLocation2.id} because there are stocked items at the locations. Use force flag to delete anyway.`, + }) + }) + + it("should delete the inventory levels when stocked quantity is greater than 0 and force is true", async () => { + const result = await api.post( + `/admin/inventory-items/location-levels/batch`, + { delete: [locationLevel2.id], force: true }, + adminHeaders + ) + + expect(result.status).toEqual(200) + expect(result.data).toEqual( + expect.objectContaining({ + deleted: [locationLevel2.id], + }) + ) }) }) describe("POST /admin/inventory-items/:id/location-levels/batch", () => { + let locationLevel1 + beforeEach(async () => { - await api.post( + const seed = await api.post( `/admin/inventory-items/${inventoryItem1.id}/location-levels`, { location_id: stockLocation1.id, @@ -199,6 +279,8 @@ medusaIntegrationTestRunner({ }, adminHeaders ) + + locationLevel1 = seed.data.inventory_item.location_levels[0] }) it("should delete an inventory location level and create a new one", async () => { @@ -206,7 +288,8 @@ medusaIntegrationTestRunner({ `/admin/inventory-items/${inventoryItem1.id}/location-levels/batch`, { create: [{ location_id: "location_2" }], - delete: [stockLocation1.id], + delete: [locationLevel1.id], + force: true, }, adminHeaders ) @@ -221,7 +304,7 @@ medusaIntegrationTestRunner({ expect(levelsListResult.data.inventory_levels).toHaveLength(1) }) - it("should not delete an inventory location level when there is stocked items", async () => { + it("should not delete an inventory location level when there is stocked items without force", async () => { await api.post( `/admin/inventory-items/${inventoryItem1.id}/location-levels/${stockLocation1.id}`, { stocked_quantity: 10 }, @@ -231,7 +314,7 @@ medusaIntegrationTestRunner({ const { response } = await api .post( `/admin/inventory-items/${inventoryItem1.id}/location-levels/batch`, - { delete: [stockLocation1.id] }, + { delete: [locationLevel1.id] }, adminHeaders ) .catch((e) => e) @@ -239,7 +322,7 @@ medusaIntegrationTestRunner({ expect(response.status).toEqual(400) expect(response.data).toEqual({ type: "not_allowed", - message: `Cannot remove Inventory Levels for ${stockLocation1.id} because there are stocked or reserved items at the locations`, + message: `Cannot remove Inventory Levels for ${stockLocation1.id} because there are stocked items at the locations. Use force flag to delete anyway.`, }) }) diff --git a/packages/core/core-flows/src/inventory/workflows/batch-inventory-item-levels.ts b/packages/core/core-flows/src/inventory/workflows/batch-inventory-item-levels.ts index 6a6eeae772151..13ae45113620d 100644 --- a/packages/core/core-flows/src/inventory/workflows/batch-inventory-item-levels.ts +++ b/packages/core/core-flows/src/inventory/workflows/batch-inventory-item-levels.ts @@ -33,14 +33,25 @@ export const batchInventoryItemLevelsWorkflowId = export const batchInventoryItemLevelsWorkflow = createWorkflow( batchInventoryItemLevelsWorkflowId, (input: WorkflowData) => { + const { createInput, updateInput, deleteInput } = transform( + input, + (data) => { + return { + createInput: data.create || [], + updateInput: data.update || [], + deleteInput: { + id: data.delete || [], + force: data.force ?? false, + }, + } + } + ) + const res = parallelize( - createInventoryLevelsStep(input.create ?? []), - updateInventoryLevelsStep(input.update ?? []), + createInventoryLevelsStep(createInput), + updateInventoryLevelsStep(updateInput), deleteInventoryLevelsWorkflow.runAsStep({ - input: { - id: input.delete ?? [], - force: input.force ?? false, - }, + input: deleteInput, }) ) diff --git a/packages/medusa/src/api/admin/inventory-items/middlewares.ts b/packages/medusa/src/api/admin/inventory-items/middlewares.ts index 573eedac50c36..89d77ddd84a05 100644 --- a/packages/medusa/src/api/admin/inventory-items/middlewares.ts +++ b/packages/medusa/src/api/admin/inventory-items/middlewares.ts @@ -4,10 +4,10 @@ import { } from "@medusajs/framework" import { MiddlewareRoute, unlessPath } from "@medusajs/framework/http" import { DEFAULT_BATCH_ENDPOINTS_SIZE_LIMIT } from "../../../utils/middlewares" -import { createBatchBody } from "../../utils/validators" import * as QueryConfig from "./query-config" import { AdminBatchInventoryItemLevels, + AdminBatchInventoryItemLocationsLevel, AdminCreateInventoryItem, AdminCreateInventoryLocationLevel, AdminGetInventoryItemParams, @@ -105,12 +105,7 @@ export const adminInventoryRoutesMiddlewares: MiddlewareRoute[] = [ sizeLimit: DEFAULT_BATCH_ENDPOINTS_SIZE_LIMIT, }, middlewares: [ - validateAndTransformBody( - createBatchBody( - AdminCreateInventoryLocationLevel, - AdminUpdateInventoryLocationLevel - ) - ), + validateAndTransformBody(AdminBatchInventoryItemLocationsLevel), validateAndTransformQuery( AdminGetInventoryLocationLevelParams, QueryConfig.retrieveLocationLevelsTransformQueryConfig From 686f3a3667f6ce99106c151936381c4c183ac5eb Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Wed, 18 Dec 2024 09:24:56 +0100 Subject: [PATCH 10/19] work on fixing setValue behaviour --- .../data-grid-toggleable-number-cell.tsx | 14 +++++++-- .../hooks/use-data-grid-form-handlers.tsx | 5 ++++ .../dashboard/src/i18n/translations/en.json | 7 +++-- .../hooks/use-inventory-stock-columns.tsx | 14 +++++++-- .../product-variant-section.tsx | 4 +-- .../product-stock-form/product-stock-form.tsx | 29 +++++++++++++++++-- .../hooks/use-product-stock-columns.tsx | 9 +++++- 7 files changed, 69 insertions(+), 13 deletions(-) diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx index d225ed79d1f45..1e9d45ce644ae 100644 --- a/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx @@ -10,11 +10,13 @@ import { DataGridCellContainer } from "./data-grid-cell-container" export const DataGridTogglableNumberCell = ({ context, + disabledToggleTooltip, ...rest }: DataGridCellProps & { min?: number max?: number placeholder?: string + disabledToggleTooltip?: string }) => { const { field, control, renderProps } = useDataGridCell({ context, @@ -37,6 +39,7 @@ export const DataGridTogglableNumberCell = ({ field={field} inputProps={input} isAnchor={container.isAnchor} + tooltip={disabledToggleTooltip} /> } > @@ -52,10 +55,12 @@ const OuterComponent = ({ field, inputProps, isAnchor, + tooltip, }: { field: ControllerRenderProps inputProps: InputProps isAnchor: boolean + tooltip?: string }) => { const buttonRef = useRef(null) const { value } = field @@ -87,8 +92,8 @@ const OuterComponent = ({ return (
{ + const { t } = useTranslation() + return useMemo( () => [ helper.column({ @@ -56,11 +59,18 @@ export const useInventoryStockColumns = ( }, type: "togglable-number", cell: (context) => { - return + return ( + + ) }, }) ), ], - [locations] + [locations, t] ) } diff --git a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx index 9c0870bd7fa73..99b0671478c4c 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx +++ b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx @@ -87,7 +87,7 @@ export const ProductVariantSection = ({ icon: , }, { - label: t("products.stock.action"), + label: t("inventory.stock.action"), to: `stock`, icon: , }, @@ -123,7 +123,7 @@ export const ProductVariantSection = ({ ).join(",")}` ) }, - label: t("products.stock.action"), + label: t("inventory.stock.action"), shortcut: "i", }, ]} diff --git a/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx index a9c105572e544..f944479679231 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx @@ -1,7 +1,7 @@ import { zodResolver } from "@hookform/resolvers/zod" import { HttpTypes } from "@medusajs/types" -import { Button, toast } from "@medusajs/ui" -import { useMemo, useRef } from "react" +import { Button, toast, usePrompt } from "@medusajs/ui" +import { useMemo, useRef, useState } from "react" import { DefaultValues, useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import { DataGrid } from "../../../../../components/data-grid" @@ -37,6 +37,9 @@ export const ProductStockForm = ({ const { t } = useTranslation() const { setCloseOnEscape } = useRouteModal() const { handleSuccess } = useRouteModal() + const prompt = usePrompt() + + const [isPromptOpen, setIsPromptOpen] = useState(false) const form = useForm({ defaultValues: getDefaultValue(variants as any, locations), @@ -103,9 +106,28 @@ export const ProductStockForm = ({ } } + if (payload.delete.length > 0) { + setIsPromptOpen(true) + const confirm = await prompt({ + title: t("general.areYouSure"), + description: t("inventory.stock.disablePrompt", { + count: payload.delete.length, + }), + confirmText: t("actions.continue"), + cancelText: t("actions.cancel"), + variant: "confirmation", + }) + + setIsPromptOpen(false) + + if (!confirm) { + return + } + } + await mutateAsync(payload, { onSuccess: () => { - toast.success(t("products.stock.successToast")) + toast.success(t("inventory.stock.successToast")) handleSuccess() }, onError: (error) => { @@ -125,6 +147,7 @@ export const ProductStockForm = ({ data={variants} getSubRows={getSubRows} onEditingChange={(editing) => setCloseOnEscape(!editing)} + disableInteractions={isPending || isPromptOpen} /> diff --git a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx index c79bd98252bc4..a38994bee1a13 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx @@ -205,7 +205,14 @@ export const useProductStockColumns = ( ) } - return + return ( + + ) }, }) ), From 219e9060ac7ee3c38358a90f7eecfd28b32a3b65 Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Wed, 18 Dec 2024 18:47:36 +0100 Subject: [PATCH 11/19] cleanup toggle logic --- .../data-grid-toggleable-number-cell.tsx | 22 ++++- .../hooks/use-data-grid-form-handlers.tsx | 81 +++++++++---------- .../hooks/use-data-grid-keydown-event.tsx | 9 ++- .../hooks/use-product-stock-columns.tsx | 1 + 4 files changed, 65 insertions(+), 48 deletions(-) diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx index 1e9d45ce644ae..a9bc51e49ac06 100644 --- a/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-toggleable-number-cell.tsx @@ -74,6 +74,15 @@ const OuterComponent = ({ const handleCheckedChange = (update: boolean) => { const newValue = { ...localValue, checked: update } + + if (!update && !newValue.disabledToggle) { + newValue.quantity = "" + } + + if (update && newValue.quantity === "") { + newValue.quantity = 0 + } + setLocalValue(newValue) onChange(newValue, value) } @@ -112,6 +121,7 @@ const OuterComponent = ({ const Inner = ({ field, inputProps, + placeholder, ...props }: { field: ControllerRenderProps @@ -160,6 +170,14 @@ const Inner = ({ setLocalValue(newValue) } + const handleOnChange = () => { + if (localValue.disabledToggle && localValue.quantity === "") { + localValue.quantity = 0 + } + + onChange(localValue, value) + } + return (
{ onBlur() onInputBlur() - - onChange(localValue, value) + handleOnChange() }} onFocus={onFocus} decimalsLimit={0} autoComplete="off" tabIndex={-1} + placeholder={!localValue.checked ? placeholder : undefined} />
) diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx index fc7356ac443c8..cf603950ab1a7 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-form-handlers.tsx @@ -146,60 +146,51 @@ function setValue< field: string, newValue: T, type: string, - /** - * If an value is being set by a history command, we should not check - * for any conditions whether the value is allowed to be changed. - */ isHistory?: boolean ) { - const currentValue = get(currentValues, field) + if (type !== "togglable-number") { + set(currentValues, field, newValue) + return + } - if (type === "togglable-number") { - if (isHistory) { - set(currentValues, `${field}.quantity`, newValue.quantity) - set(currentValues, `${field}.checked`, newValue.checked) - return - } + setValueToggleableNumber(currentValues, field, newValue, isHistory) +} - const currentChecked = currentValue.checked - const disabledToggle = currentValue.disabledToggle - - const newQuantityNumber = - newValue.quantity != null && newValue.quantity !== "" - ? Number(newValue.quantity) - : null - - // TODO: - // 1. Tag højde for den nye værdis checked felt. - // 2. Hvis et felt bliver unchecked, så burde vi fjerne quantity, og istedet vise "Not available" - // 3. Hvis du sætter quantity til "", på et felt der har disabledToggle, så bør vi rette quantity til 0. - - // Determine if checked should be updated - let newChecked = currentChecked - if (!disabledToggle) { - if ( - currentChecked === false && - newQuantityNumber != null && - newQuantityNumber > 0 - ) { - newChecked = true - } +function setValueToggleableNumber( + currentValues: any, + field: string, + newValue: DataGridToggleableNumber, + isHistory?: boolean +) { + const currentValue = get(currentValues, field) + const { disabledToggle } = currentValue - if (currentChecked === true && !newQuantityNumber) { - newChecked = false - } + const normalizeQuantity = (value: number | string | null | undefined) => { + if (disabledToggle && value === "") { + return 0 } + return value + } - set(currentValues, field, { - ...currentValue, - quantity: newValue.quantity, - checked: newChecked, - }) - - return + const determineChecked = (quantity: number | string | null | undefined) => { + if (disabledToggle) { + return true + } + return quantity !== "" && quantity != null } - set(currentValues, field, newValue) + const quantity = normalizeQuantity(newValue.quantity) + const checked = isHistory + ? disabledToggle + ? true + : newValue.checked + : determineChecked(quantity) + + set(currentValues, field, { + ...currentValue, + quantity, + checked, + }) } export function convertArrayToPrimitive( diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx index 0a0dcce43e7a9..9980db9aa5920 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-keydown-event.tsx @@ -255,7 +255,14 @@ export const useDataGridKeydownEvent = < createSnapshot(anchor) const current = getValues(field as Path) - const next = { ...current, quantity: "" } + let checked = current.checked + + // If the toggle is not disabled, then we want to uncheck the toggle. + if (!current.disabledToggle) { + checked = false + } + + const next = { ...current, quantity: "", checked } const command = new DataGridUpdateCommand({ next, diff --git a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx index a38994bee1a13..a7d0f7f0e1597 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx @@ -211,6 +211,7 @@ export const useProductStockColumns = ( disabledToggleTooltip={t( "inventory.stock.disabledToggleTooltip" )} + placeholder="Not available" /> ) }, From 89a9e823bfce9a80c04208717554aa9ff9603c9e Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Fri, 20 Dec 2024 09:54:23 +0100 Subject: [PATCH 12/19] add loading state --- .../src/i18n/translations/$schema.json | 2006 +++++++++++++---- .../dashboard/src/i18n/translations/en.json | 2 + .../hooks/use-product-inventory-data.tsx | 65 +- .../hooks/use-product-stock-columns.tsx | 2 +- .../products/product-stock/product-stock.tsx | 38 +- 5 files changed, 1702 insertions(+), 411 deletions(-) diff --git a/packages/admin/dashboard/src/i18n/translations/$schema.json b/packages/admin/dashboard/src/i18n/translations/$schema.json index d9aaf095122b4..4ec46dc7e107e 100644 --- a/packages/admin/dashboard/src/i18n/translations/$schema.json +++ b/packages/admin/dashboard/src/i18n/translations/$schema.json @@ -258,7 +258,11 @@ "type": "string" } }, - "required": ["header_one", "header_other", "description"], + "required": [ + "header_one", + "header_other", + "description" + ], "additionalProperties": false } }, @@ -307,7 +311,11 @@ "type": "string" } }, - "required": ["insertRowAbove", "insertRowBelow", "deleteRow"], + "required": [ + "insertRowAbove", + "insertRowBelow", + "deleteRow" + ], "additionalProperties": false }, "labels": { @@ -320,7 +328,10 @@ "type": "string" } }, - "required": ["key", "value"], + "required": [ + "key", + "value" + ], "additionalProperties": false }, "complexRow": { @@ -336,7 +347,11 @@ "type": "string" } }, - "required": ["label", "description", "tooltip"], + "required": [ + "label", + "description", + "tooltip" + ], "additionalProperties": false } }, @@ -351,7 +366,12 @@ "additionalProperties": false } }, - "required": ["header", "numberOfKeys_one", "numberOfKeys_other", "edit"], + "required": [ + "header", + "numberOfKeys_one", + "numberOfKeys_other", + "edit" + ], "additionalProperties": false }, "validation": { @@ -364,7 +384,10 @@ "type": "string" } }, - "required": ["mustBeInt", "mustBePositive"], + "required": [ + "mustBeInt", + "mustBePositive" + ], "additionalProperties": false }, "actions": { @@ -550,7 +573,9 @@ "type": "string" } }, - "required": ["in"], + "required": [ + "in" + ], "additionalProperties": false }, "app": { @@ -901,7 +926,12 @@ "type": "string" } }, - "required": ["label", "dark", "light", "system"], + "required": [ + "label", + "dark", + "light", + "system" + ], "additionalProperties": false } }, @@ -924,7 +954,10 @@ "type": "string" } }, - "required": ["label", "storeSettings"], + "required": [ + "label", + "storeSettings" + ], "additionalProperties": false }, "actions": { @@ -934,11 +967,17 @@ "type": "string" } }, - "required": ["logout"], + "required": [ + "logout" + ], "additionalProperties": false } }, - "required": ["user", "store", "actions"], + "required": [ + "user", + "store", + "actions" + ], "additionalProperties": false }, "nav": { @@ -954,7 +993,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "common": { @@ -964,7 +1006,9 @@ "type": "string" } }, - "required": ["extensions"], + "required": [ + "extensions" + ], "additionalProperties": false }, "main": { @@ -977,7 +1021,10 @@ "type": "string" } }, - "required": ["store", "storeSettings"], + "required": [ + "store", + "storeSettings" + ], "additionalProperties": false }, "settings": { @@ -996,15 +1043,30 @@ "type": "string" } }, - "required": ["header", "general", "developer", "myAccount"], + "required": [ + "header", + "general", + "developer", + "myAccount" + ], "additionalProperties": false } }, - "required": ["accessibility", "common", "main", "settings"], + "required": [ + "accessibility", + "common", + "main", + "settings" + ], "additionalProperties": false } }, - "required": ["search", "keyboardShortcuts", "menus", "nav"], + "required": [ + "search", + "keyboardShortcuts", + "menus", + "nav" + ], "additionalProperties": false }, "dataGrid": { @@ -1023,7 +1085,11 @@ "type": "string" } }, - "required": ["view", "resetToDefault", "disabled"], + "required": [ + "view", + "resetToDefault", + "disabled" + ], "additionalProperties": false }, "shortcuts": { @@ -1117,7 +1183,10 @@ "additionalProperties": false } }, - "required": ["label", "commands"], + "required": [ + "label", + "commands" + ], "additionalProperties": false }, "errors": { @@ -1133,11 +1202,19 @@ "type": "string" } }, - "required": ["fixError", "count_one", "count_other"], + "required": [ + "fixError", + "count_one", + "count_other" + ], "additionalProperties": false } }, - "required": ["columns", "shortcuts", "errors"], + "required": [ + "columns", + "shortcuts", + "errors" + ], "additionalProperties": false }, "filters": { @@ -1223,7 +1300,11 @@ "type": "string" } }, - "required": ["date", "compare", "addFilter"], + "required": [ + "date", + "compare", + "addFilter" + ], "additionalProperties": false }, "errorBoundary": { @@ -1293,7 +1374,12 @@ "type": "string" } }, - "required": ["header", "editHeader", "editLabel", "label"], + "required": [ + "header", + "editHeader", + "editLabel", + "label" + ], "additionalProperties": false }, "billingAddress": { @@ -1352,7 +1438,11 @@ "type": "string" } }, - "required": ["editHeader", "editLabel", "label"], + "required": [ + "editHeader", + "editLabel", + "label" + ], "additionalProperties": false }, "transferOwnership": { @@ -1374,7 +1464,10 @@ "type": "string" } }, - "required": ["order", "draft"], + "required": [ + "order", + "draft" + ], "additionalProperties": false }, "currentOwner": { @@ -1387,7 +1480,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "newOwner": { @@ -1400,7 +1496,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "validation": { @@ -1413,7 +1512,10 @@ "type": "string" } }, - "required": ["mustBeDifferent", "required"], + "required": [ + "mustBeDifferent", + "required" + ], "additionalProperties": false } }, @@ -1434,7 +1536,9 @@ "type": "string" } }, - "required": ["availableIn"], + "required": [ + "availableIn" + ], "additionalProperties": false }, "products": { @@ -1450,7 +1554,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "edit": { @@ -1466,7 +1572,11 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false }, "create": { @@ -1497,7 +1607,12 @@ "type": "string" } }, - "required": ["details", "organize", "variants", "inventory"], + "required": [ + "details", + "organize", + "variants", + "inventory" + ], "additionalProperties": false }, "errors": { @@ -1513,7 +1628,11 @@ "type": "string" } }, - "required": ["variants", "options", "uniqueSku"], + "required": [ + "variants", + "options", + "uniqueSku" + ], "additionalProperties": false }, "inventory": { @@ -1559,7 +1678,9 @@ "type": "string" } }, - "required": ["placeholder"], + "required": [ + "placeholder" + ], "additionalProperties": false }, "optionValues": { @@ -1569,7 +1690,9 @@ "type": "string" } }, - "required": ["placeholder"], + "required": [ + "placeholder" + ], "additionalProperties": false }, "productVariants": { @@ -1588,7 +1711,12 @@ "type": "string" } }, - "required": ["label", "hint", "alert", "tip"], + "required": [ + "label", + "hint", + "alert", + "tip" + ], "additionalProperties": false }, "productOptions": { @@ -1601,7 +1729,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false } }, @@ -1651,7 +1782,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "filters": { @@ -1664,7 +1798,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "columns": { @@ -1677,7 +1814,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -1715,7 +1855,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "upload": { @@ -1756,7 +1899,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -1850,7 +1996,11 @@ "type": "string" } }, - "required": ["header", "description", "action"], + "required": [ + "header", + "description", + "action" + ], "additionalProperties": false }, "successToast": { @@ -1909,7 +2059,12 @@ "type": "string" } }, - "required": ["draft", "published", "proposed", "rejected"], + "required": [ + "draft", + "published", + "proposed", + "rejected" + ], "additionalProperties": false }, "fields": { @@ -1925,7 +2080,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "subtitle": { @@ -1935,7 +2093,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "handle": { @@ -1948,7 +2108,10 @@ "type": "string" } }, - "required": ["label", "tooltip"], + "required": [ + "label", + "tooltip" + ], "additionalProperties": false }, "description": { @@ -1961,7 +2124,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "discountable": { @@ -1974,7 +2140,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "type": { @@ -1984,7 +2153,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "collection": { @@ -1994,7 +2165,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "categories": { @@ -2004,7 +2177,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "tags": { @@ -2014,7 +2189,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "sales_channels": { @@ -2027,7 +2204,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "countryOrigin": { @@ -2037,7 +2217,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "material": { @@ -2047,7 +2229,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "width": { @@ -2057,7 +2241,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "length": { @@ -2067,7 +2253,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "height": { @@ -2077,7 +2265,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "weight": { @@ -2087,7 +2277,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "options": { @@ -2136,7 +2328,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "mid_code": { @@ -2146,7 +2341,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "hs_code": { @@ -2156,7 +2353,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false } }, @@ -2197,7 +2396,10 @@ "type": "string" } }, - "required": ["header", "success"], + "required": [ + "header", + "success" + ], "additionalProperties": false }, "create": { @@ -2207,7 +2409,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "deleteWarning": { @@ -2253,7 +2457,10 @@ "type": "string" } }, - "required": ["inventoryItems", "inventoryKit"], + "required": [ + "inventoryItems", + "inventoryKit" + ], "additionalProperties": false }, "inventoryKit": { @@ -2272,7 +2479,10 @@ "type": "string" } }, - "required": ["itemId", "quantity"], + "required": [ + "itemId", + "quantity" + ], "additionalProperties": false }, "header": { @@ -2367,7 +2577,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "create": { @@ -2380,14 +2593,22 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "deleteWarning": { "type": "string" } }, - "required": ["header", "edit", "create", "deleteWarning"], + "required": [ + "header", + "edit", + "create", + "deleteWarning" + ], "additionalProperties": false }, "organization": { @@ -2409,15 +2630,23 @@ "type": "string" } }, - "required": ["success"], + "required": [ + "success" + ], "additionalProperties": false } }, - "required": ["header", "toasts"], + "required": [ + "header", + "toasts" + ], "additionalProperties": false } }, - "required": ["header", "edit"], + "required": [ + "header", + "edit" + ], "additionalProperties": false }, "stock": { @@ -2429,7 +2658,7 @@ "description": { "type": "string" }, - "action": { + "loading": { "type": "string" }, "tooltips": { @@ -2442,19 +2671,18 @@ "type": "string" } }, - "required": ["alreadyManaged", "alreadyManagedWithSku"], + "required": [ + "alreadyManaged", + "alreadyManagedWithSku" + ], "additionalProperties": false - }, - "successToast": { - "type": "string" } }, "required": [ "heading", "description", - "action", - "tooltips", - "successToast" + "loading", + "tooltips" ], "additionalProperties": false }, @@ -2474,7 +2702,10 @@ "type": "string" } }, - "required": ["header", "description"], + "required": [ + "header", + "description" + ], "additionalProperties": false }, "error": { @@ -2484,15 +2715,22 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false } }, - "required": ["success", "error"], + "required": [ + "success", + "error" + ], "additionalProperties": false } }, - "required": ["delete"], + "required": [ + "delete" + ], "additionalProperties": false } }, @@ -2571,7 +2809,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "add": { @@ -2584,7 +2824,10 @@ "type": "string" } }, - "required": ["successToast_one", "successToast_other"], + "required": [ + "successToast_one", + "successToast_other" + ], "additionalProperties": false }, "remove": { @@ -2597,11 +2840,18 @@ "type": "string" } }, - "required": ["successToast_one", "successToast_other"], + "required": [ + "successToast_one", + "successToast_other" + ], "additionalProperties": false } }, - "required": ["list", "add", "remove"], + "required": [ + "list", + "add", + "remove" + ], "additionalProperties": false } }, @@ -2649,14 +2899,22 @@ "type": "string" } }, - "required": ["details", "organize"], + "required": [ + "details", + "organize" + ], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": ["header", "hint", "tabs", "successToast"], + "required": [ + "header", + "hint", + "tabs", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -2672,7 +2930,11 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -2685,7 +2947,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "products": { @@ -2742,11 +3007,17 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["add", "remove", "list"], + "required": [ + "add", + "remove", + "list" + ], "additionalProperties": false }, "organize": { @@ -2759,7 +3030,10 @@ "type": "string" } }, - "required": ["header", "action"], + "required": [ + "header", + "action" + ], "additionalProperties": false }, "fields": { @@ -2778,7 +3052,11 @@ "type": "string" } }, - "required": ["label", "internal", "public"], + "required": [ + "label", + "internal", + "public" + ], "additionalProperties": false }, "status": { @@ -2794,7 +3072,11 @@ "type": "string" } }, - "required": ["label", "active", "inactive"], + "required": [ + "label", + "active", + "inactive" + ], "additionalProperties": false }, "path": { @@ -2807,9 +3089,12 @@ "type": "string" } }, - "required": ["label", "tooltip"], - "additionalProperties": false - }, + "required": [ + "label", + "tooltip" + ], + "additionalProperties": false + }, "children": { "type": "object", "properties": { @@ -2817,7 +3102,9 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false }, "new": { @@ -2827,11 +3114,19 @@ "type": "string" } }, - "required": ["label"], + "required": [ + "label" + ], "additionalProperties": false } }, - "required": ["visibility", "status", "path", "children", "new"], + "required": [ + "visibility", + "status", + "path", + "children", + "new" + ], "additionalProperties": false } }, @@ -2981,7 +3276,10 @@ "type": "string" } }, - "required": ["noAvaliableQuantity", "quantityOutOfRange"], + "required": [ + "noAvaliableQuantity", + "quantityOutOfRange" + ], "additionalProperties": false } }, @@ -3017,11 +3315,15 @@ "type": "string" } }, - "required": ["stockedQuantity"], + "required": [ + "stockedQuantity" + ], "additionalProperties": false } }, - "required": ["errors"], + "required": [ + "errors" + ], "additionalProperties": false }, "toast": { @@ -3037,7 +3339,11 @@ "type": "string" } }, - "required": ["updateLocations", "updateLevel", "updateItem"], + "required": [ + "updateLocations", + "updateLevel", + "updateItem" + ], "additionalProperties": false }, "stock": { @@ -3052,11 +3358,32 @@ "action": { "type": "string" }, + "placeholder": { + "type": "string" + }, + "disablePrompt_one": { + "type": "string" + }, + "disablePrompt_other": { + "type": "string" + }, + "disabledToggleTooltip": { + "type": "string" + }, "successToast": { "type": "string" } }, - "required": ["title", "description", "action", "successToast"], + "required": [ + "title", + "description", + "action", + "placeholder", + "disablePrompt_one", + "disablePrompt_other", + "disabledToggleTooltip", + "successToast" + ], "additionalProperties": false } }, @@ -3163,7 +3490,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "create": { @@ -3179,7 +3508,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "groups": { @@ -3204,7 +3537,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "add": { @@ -3220,11 +3555,16 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["success", "list"], + "required": [ + "success", + "list" + ], "additionalProperties": false }, "removed": { @@ -3240,11 +3580,16 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["success", "list"], + "required": [ + "success", + "list" + ], "additionalProperties": false } }, @@ -3272,7 +3617,11 @@ "type": "string" } }, - "required": ["header", "emailDisabledTooltip", "successToast"], + "required": [ + "header", + "emailDisabledTooltip", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -3288,7 +3637,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -3304,7 +3657,11 @@ "type": "string" } }, - "required": ["guest", "registered", "groups"], + "required": [ + "guest", + "registered", + "groups" + ], "additionalProperties": false }, "registered": { @@ -3353,7 +3710,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -3366,7 +3727,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -3382,7 +3746,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "customers": { @@ -3407,11 +3775,17 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["successToast_one", "successToast_other", "list"], + "required": [ + "successToast_one", + "successToast_other", + "list" + ], "additionalProperties": false }, "remove": { @@ -3445,11 +3819,18 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["alreadyAddedTooltip", "add", "remove", "list"], + "required": [ + "alreadyAddedTooltip", + "add", + "remove", + "list" + ], "additionalProperties": false } }, @@ -3491,7 +3872,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "summary": { @@ -3783,7 +4166,10 @@ "type": "string" } }, - "required": ["title", "titlePending"], + "required": [ + "title", + "titlePending" + ], "additionalProperties": false }, "toast": { @@ -3796,7 +4182,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "validation": { @@ -3806,7 +4195,9 @@ "type": "string" } }, - "required": ["quantityLowerThanFulfillment"], + "required": [ + "quantityLowerThanFulfillment" + ], "additionalProperties": false } }, @@ -3847,7 +4238,10 @@ "type": "string" } }, - "required": ["title", "requestSuccess"], + "required": [ + "title", + "requestSuccess" + ], "additionalProperties": false }, "shippingAddress": { @@ -3860,7 +4254,10 @@ "type": "string" } }, - "required": ["title", "requestSuccess"], + "required": [ + "title", + "requestSuccess" + ], "additionalProperties": false }, "billingAddress": { @@ -3873,11 +4270,18 @@ "type": "string" } }, - "required": ["title", "requestSuccess"], + "required": [ + "title", + "requestSuccess" + ], "additionalProperties": false } }, - "required": ["email", "shippingAddress", "billingAddress"], + "required": [ + "email", + "shippingAddress", + "billingAddress" + ], "additionalProperties": false }, "returns": { @@ -3983,7 +4387,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "placeholders": { @@ -3999,7 +4406,10 @@ "type": "string" } }, - "required": ["title", "hint"], + "required": [ + "title", + "hint" + ], "additionalProperties": false }, "outboundShippingOptions": { @@ -4012,7 +4422,10 @@ "type": "string" } }, - "required": ["title", "hint"], + "required": [ + "title", + "hint" + ], "additionalProperties": false } }, @@ -4097,7 +4510,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "panel": { @@ -4110,7 +4526,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -4199,11 +4618,15 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false } }, - "required": ["cancelClaim"], + "required": [ + "cancelClaim" + ], "additionalProperties": false }, "cancel": { @@ -4216,7 +4639,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "tooltips": { @@ -4226,7 +4652,9 @@ "type": "string" } }, - "required": ["onlyReturnShippingOptions"], + "required": [ + "onlyReturnShippingOptions" + ], "additionalProperties": false }, "toast": { @@ -4239,7 +4667,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "panel": { @@ -4252,7 +4683,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -4322,11 +4756,15 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false } }, - "required": ["cancelExchange"], + "required": [ + "cancelExchange" + ], "additionalProperties": false }, "cancel": { @@ -4339,7 +4777,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "tooltips": { @@ -4349,7 +4790,9 @@ "type": "string" } }, - "required": ["onlyReturnShippingOptions"], + "required": [ + "onlyReturnShippingOptions" + ], "additionalProperties": false }, "toast": { @@ -4362,7 +4805,10 @@ "type": "string" } }, - "required": ["canceledSuccessfully", "confirmedSuccessfully"], + "required": [ + "canceledSuccessfully", + "confirmedSuccessfully" + ], "additionalProperties": false }, "panel": { @@ -4375,7 +4821,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, @@ -4409,7 +4858,10 @@ "type": "string" } }, - "required": ["allocatedLabel", "notAllocatedLabel"], + "required": [ + "allocatedLabel", + "notAllocatedLabel" + ], "additionalProperties": false }, "allocateItems": { @@ -4446,7 +4898,9 @@ "type": "string" } }, - "required": ["created"], + "required": [ + "created" + ], "additionalProperties": false }, "error": { @@ -4456,7 +4910,9 @@ "type": "string" } }, - "required": ["quantityNotAllocated"], + "required": [ + "quantityNotAllocated" + ], "additionalProperties": false } }, @@ -4579,7 +5035,11 @@ "type": "string" } }, - "required": ["wrongQuantity", "wrongQuantity_other", "noItems"], + "required": [ + "wrongQuantity", + "wrongQuantity_other", + "noItems" + ], "additionalProperties": false }, "status": { @@ -4725,7 +5185,11 @@ "type": "string" } }, - "required": ["amountToLarge", "amountNegative", "reasonRequired"], + "required": [ + "amountToLarge", + "amountNegative", + "reasonRequired" + ], "additionalProperties": false } }, @@ -4821,7 +5285,10 @@ "type": "string" } }, - "required": ["toReturn", "toSend"], + "required": [ + "toReturn", + "toSend" + ], "additionalProperties": false }, "placed": { @@ -4834,7 +5301,10 @@ "type": "string" } }, - "required": ["title", "fromSalesChannel"], + "required": [ + "title", + "fromSalesChannel" + ], "additionalProperties": false }, "canceled": { @@ -4844,7 +5314,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "payment": { @@ -4863,7 +5335,12 @@ "type": "string" } }, - "required": ["awaiting", "captured", "canceled", "refunded"], + "required": [ + "awaiting", + "captured", + "canceled", + "refunded" + ], "additionalProperties": false }, "fulfillment": { @@ -4936,7 +5413,10 @@ "type": "string" } }, - "required": ["comment", "byLine"], + "required": [ + "comment", + "byLine" + ], "additionalProperties": false }, "claim": { @@ -4997,7 +5477,10 @@ "type": "string" } }, - "required": ["requested", "confirmed"], + "required": [ + "requested", + "confirmed" + ], "additionalProperties": false }, "transfer": { @@ -5013,7 +5496,11 @@ "type": "string" } }, - "required": ["requested", "confirmed", "declined"], + "required": [ + "requested", + "confirmed", + "declined" + ], "additionalProperties": false }, "update_order": { @@ -5029,7 +5516,11 @@ "type": "string" } }, - "required": ["shipping_address", "billing_address", "email"], + "required": [ + "shipping_address", + "billing_address", + "email" + ], "additionalProperties": false } }, @@ -5074,7 +5565,11 @@ "type": "string" } }, - "required": ["displayId", "refundableAmount", "returnableQuantity"], + "required": [ + "displayId", + "refundableAmount", + "returnableQuantity" + ], "additionalProperties": false } }, @@ -5133,7 +5628,11 @@ "type": "string" } }, - "required": ["label", "warningTitle", "warningDescription"], + "required": [ + "label", + "warningTitle", + "warningDescription" + ], "additionalProperties": false }, "status": { @@ -5146,7 +5645,10 @@ "type": "string" } }, - "required": ["open", "completed"], + "required": [ + "open", + "completed" + ], "additionalProperties": false }, "create": { @@ -5287,7 +5789,9 @@ "type": "string" } }, - "required": ["description"], + "required": [ + "description" + ], "additionalProperties": false }, "create": { @@ -5303,7 +5807,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -5319,7 +5827,11 @@ "type": "string" } }, - "required": ["header", "viewInventory", "successToast"], + "required": [ + "header", + "viewInventory", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -5329,7 +5841,9 @@ "type": "string" } }, - "required": ["confirmation"], + "required": [ + "confirmation" + ], "additionalProperties": false }, "fulfillmentProviders": { @@ -5378,7 +5892,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "shipping": { @@ -5388,7 +5904,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "disable": { @@ -5404,7 +5922,11 @@ "type": "string" } }, - "required": ["confirmation", "pickup", "shipping"], + "required": [ + "confirmation", + "pickup", + "shipping" + ], "additionalProperties": false }, "enable": { @@ -5417,11 +5939,19 @@ "type": "string" } }, - "required": ["pickup", "shipping"], + "required": [ + "pickup", + "shipping" + ], "additionalProperties": false } }, - "required": ["pickup", "shipping", "disable", "enable"], + "required": [ + "pickup", + "shipping", + "disable", + "enable" + ], "additionalProperties": false }, "sidebar": { @@ -5440,11 +5970,17 @@ "type": "string" } }, - "required": ["label", "description"], + "required": [ + "label", + "description" + ], "additionalProperties": false } }, - "required": ["header", "shippingProfiles"], + "required": [ + "header", + "shippingProfiles" + ], "additionalProperties": false }, "salesChannels": { @@ -5501,7 +6037,12 @@ "type": "string" } }, - "required": ["header", "hint", "label", "successToast"], + "required": [ + "header", + "hint", + "label", + "successToast" + ], "additionalProperties": false }, "returns": { @@ -5520,7 +6061,12 @@ "type": "string" } }, - "required": ["header", "hint", "label", "successToast"], + "required": [ + "header", + "hint", + "label", + "successToast" + ], "additionalProperties": false }, "tabs": { @@ -5533,14 +6079,22 @@ "type": "string" } }, - "required": ["details", "prices"], + "required": [ + "details", + "prices" + ], "additionalProperties": false }, "action": { "type": "string" } }, - "required": ["shipping", "returns", "tabs", "action"], + "required": [ + "shipping", + "returns", + "tabs", + "action" + ], "additionalProperties": false }, "delete": { @@ -5553,7 +6107,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -5569,7 +6126,11 @@ "type": "string" } }, - "required": ["header", "action", "successToast"], + "required": [ + "header", + "action", + "successToast" + ], "additionalProperties": false }, "pricing": { @@ -5579,7 +6140,9 @@ "type": "string" } }, - "required": ["action"], + "required": [ + "action" + ], "additionalProperties": false }, "conditionalPrices": { @@ -5598,7 +6161,9 @@ "type": "string" } }, - "required": ["cartItemTotal"], + "required": [ + "cartItemTotal" + ], "additionalProperties": false }, "summaries": { @@ -5614,7 +6179,11 @@ "type": "string" } }, - "required": ["range", "greaterThan", "lessThan"], + "required": [ + "range", + "greaterThan", + "lessThan" + ], "additionalProperties": false }, "actions": { @@ -5627,7 +6196,10 @@ "type": "string" } }, - "required": ["addPrice", "manageConditionalPrices"], + "required": [ + "addPrice", + "manageConditionalPrices" + ], "additionalProperties": false }, "rules": { @@ -5643,7 +6215,11 @@ "type": "string" } }, - "required": ["amount", "gte", "lte"], + "required": [ + "amount", + "gte", + "lte" + ], "additionalProperties": false }, "customRules": { @@ -5665,7 +6241,13 @@ "type": "string" } }, - "required": ["label", "tooltip", "eq", "gt", "lt"], + "required": [ + "label", + "tooltip", + "eq", + "gt", + "lt" + ], "additionalProperties": false }, "errors": { @@ -5755,7 +6337,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "calculated": { @@ -5768,15 +6353,24 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false } }, - "required": ["fixed", "calculated"], + "required": [ + "fixed", + "calculated" + ], "additionalProperties": false } }, - "required": ["label", "options"], + "required": [ + "label", + "options" + ], "additionalProperties": false }, "enableInStore": { @@ -5789,7 +6383,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "provider": { @@ -5856,7 +6453,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -5869,9 +6469,12 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], - "additionalProperties": false - }, + "required": [ + "confirmation", + "successToast" + ], + "additionalProperties": false + }, "manageAreas": { "type": "object", "properties": { @@ -5891,7 +6494,13 @@ "type": "string" } }, - "required": ["header", "action", "label", "hint", "successToast"], + "required": [ + "header", + "action", + "label", + "hint", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -5904,11 +6513,20 @@ "type": "string" } }, - "required": ["noRecords", "tip"], + "required": [ + "noRecords", + "tip" + ], "additionalProperties": false } }, - "required": ["create", "edit", "delete", "manageAreas", "fields"], + "required": [ + "create", + "edit", + "delete", + "manageAreas", + "fields" + ], "additionalProperties": false } }, @@ -5949,7 +6567,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -5965,7 +6587,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "tooltip": { @@ -5975,11 +6601,19 @@ "type": "string" } }, - "required": ["type"], + "required": [ + "type" + ], "additionalProperties": false } }, - "required": ["domain", "subtitle", "create", "delete", "tooltip"], + "required": [ + "domain", + "subtitle", + "create", + "delete", + "tooltip" + ], "additionalProperties": false }, "taxRegions": { @@ -5995,7 +6629,9 @@ "type": "string" } }, - "required": ["hint"], + "required": [ + "hint" + ], "additionalProperties": false }, "delete": { @@ -6008,7 +6644,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "create": { @@ -6030,14 +6669,22 @@ "type": "string" } }, - "required": ["rateIsRequired", "nameIsRequired"], + "required": [ + "rateIsRequired", + "nameIsRequired" + ], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": ["header", "hint", "errors", "successToast"], + "required": [ + "header", + "hint", + "errors", + "successToast" + ], "additionalProperties": false }, "province": { @@ -6056,11 +6703,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "state": { @@ -6079,11 +6732,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "stateOrTerritory": { @@ -6102,11 +6761,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "county": { @@ -6125,11 +6790,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "region": { @@ -6148,11 +6819,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "department": { @@ -6171,11 +6848,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "territory": { @@ -6194,11 +6877,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "prefecture": { @@ -6217,11 +6906,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "district": { @@ -6240,11 +6935,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "governorate": { @@ -6263,11 +6964,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "canton": { @@ -6286,11 +6993,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "emirate": { @@ -6309,11 +7022,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "sublevel": { @@ -6332,11 +7051,17 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create"], + "required": [ + "header", + "create" + ], "additionalProperties": false }, "taxOverrides": { @@ -6355,7 +7080,10 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false }, "edit": { @@ -6368,11 +7096,18 @@ "type": "string" } }, - "required": ["header", "hint"], + "required": [ + "header", + "hint" + ], "additionalProperties": false } }, - "required": ["header", "create", "edit"], + "required": [ + "header", + "create", + "edit" + ], "additionalProperties": false }, "taxRates": { @@ -6391,7 +7126,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -6407,7 +7146,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -6420,11 +7163,18 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false } }, - "required": ["create", "edit", "delete"], + "required": [ + "create", + "edit", + "delete" + ], "additionalProperties": false }, "fields": { @@ -6446,7 +7196,12 @@ "type": "string" } }, - "required": ["label", "hint", "true", "false"], + "required": [ + "label", + "hint", + "true", + "false" + ], "additionalProperties": false }, "defaultTaxRate": { @@ -6462,7 +7217,11 @@ "type": "string" } }, - "required": ["label", "tooltip", "action"], + "required": [ + "label", + "tooltip", + "action" + ], "additionalProperties": false }, "taxRate": { @@ -6521,7 +7280,11 @@ "type": "string" } }, - "required": ["in", "on", "and"], + "required": [ + "in", + "on", + "and" + ], "additionalProperties": false }, "placeholders": { @@ -6587,7 +7350,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "values_one": { @@ -6759,7 +7524,10 @@ "type": "string" } }, - "required": ["sublevel", "notPartOfCountry"], + "required": [ + "sublevel", + "notPartOfCountry" + ], "additionalProperties": false }, "alert": { @@ -6775,11 +7543,20 @@ "type": "string" } }, - "required": ["header", "description", "action"], + "required": [ + "header", + "description", + "action" + ], "additionalProperties": false } }, - "required": ["labels", "placeholders", "tooltips", "alert"], + "required": [ + "labels", + "placeholders", + "tooltips", + "alert" + ], "additionalProperties": false }, "noDefaultRate": { @@ -6792,7 +7569,10 @@ "type": "string" } }, - "required": ["label", "tooltip"], + "required": [ + "label", + "tooltip" + ], "additionalProperties": false } }, @@ -6845,7 +7625,9 @@ "type": "string" } }, - "required": ["details"], + "required": [ + "details" + ], "additionalProperties": false }, "tabs": { @@ -6861,7 +7643,11 @@ "type": "string" } }, - "required": ["template", "details", "campaign"], + "required": [ + "template", + "details", + "campaign" + ], "additionalProperties": false }, "fields": { @@ -6898,7 +7684,9 @@ "type": "string" } }, - "required": ["tooltip"], + "required": [ + "tooltip" + ], "additionalProperties": false }, "conditions": { @@ -6914,7 +7702,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "target-rules": { @@ -6927,7 +7718,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "buy-rules": { @@ -6940,11 +7734,18 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["rules", "target-rules", "buy-rules"], + "required": [ + "rules", + "target-rules", + "buy-rules" + ], "additionalProperties": false } }, @@ -6969,7 +7770,9 @@ "type": "string" } }, - "required": ["campaignType"], + "required": [ + "campaignType" + ], "additionalProperties": false }, "errors": { @@ -6982,7 +7785,10 @@ "type": "string" } }, - "required": ["requiredField", "promotionTabError"], + "required": [ + "requiredField", + "promotionTabError" + ], "additionalProperties": false }, "toasts": { @@ -6992,7 +7798,9 @@ "type": "string" } }, - "required": ["promotionCreateSuccess"], + "required": [ + "promotionCreateSuccess" + ], "additionalProperties": false }, "create": { @@ -7014,7 +7822,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "target-rules": { @@ -7024,7 +7834,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "buy-rules": { @@ -7034,11 +7846,18 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false } }, - "required": ["title", "rules", "target-rules", "buy-rules"], + "required": [ + "title", + "rules", + "target-rules", + "buy-rules" + ], "additionalProperties": false }, "campaign": { @@ -7057,7 +7876,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "actions": { @@ -7067,11 +7889,17 @@ "type": "string" } }, - "required": ["goToCampaign"], + "required": [ + "goToCampaign" + ], "additionalProperties": false } }, - "required": ["header", "edit", "actions"], + "required": [ + "header", + "edit", + "actions" + ], "additionalProperties": false }, "campaign_currency": { @@ -7081,7 +7909,9 @@ "type": "string" } }, - "required": ["tooltip"], + "required": [ + "tooltip" + ], "additionalProperties": false }, "form": { @@ -7118,11 +7948,18 @@ "type": "string" } }, - "required": ["title", "desc"], + "required": [ + "title", + "desc" + ], "additionalProperties": false } }, - "required": ["title", "description", "placeholder"], + "required": [ + "title", + "description", + "placeholder" + ], "additionalProperties": false }, "new": { @@ -7135,7 +7972,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "none": { @@ -7148,11 +7988,18 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["existing", "new", "none"], + "required": [ + "existing", + "new", + "none" + ], "additionalProperties": false }, "status": { @@ -7162,7 +8009,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "method": { @@ -7181,7 +8030,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "automatic": { @@ -7194,11 +8046,18 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["label", "code", "automatic"], + "required": [ + "label", + "code", + "automatic" + ], "additionalProperties": false }, "max_quantity": { @@ -7211,7 +8070,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "type": { @@ -7227,7 +8089,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "buyget": { @@ -7240,11 +8105,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["standard", "buyget"], + "required": [ + "standard", + "buyget" + ], "additionalProperties": false }, "allocation": { @@ -7260,7 +8131,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "across": { @@ -7273,11 +8147,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["each", "across"], + "required": [ + "each", + "across" + ], "additionalProperties": false }, "code": { @@ -7290,7 +8170,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "value": { @@ -7300,7 +8183,9 @@ "type": "string" } }, - "required": ["title"], + "required": [ + "title" + ], "additionalProperties": false }, "value_type": { @@ -7316,7 +8201,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "percentage": { @@ -7329,11 +8217,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["fixed", "percentage"], + "required": [ + "fixed", + "percentage" + ], "additionalProperties": false } }, @@ -7375,11 +8269,16 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["add", "list"], + "required": [ + "add", + "list" + ], "additionalProperties": false } }, @@ -7425,7 +8324,11 @@ "type": "string" } }, - "required": ["active", "expired", "scheduled"], + "required": [ + "active", + "expired", + "scheduled" + ], "additionalProperties": false }, "delete": { @@ -7441,7 +8344,11 @@ "type": "string" } }, - "required": ["title", "description", "successToast"], + "required": [ + "title", + "description", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -7457,7 +8364,11 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false }, "configuration": { @@ -7479,11 +8390,18 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false } }, - "required": ["header", "edit"], + "required": [ + "header", + "edit" + ], "additionalProperties": false }, "create": { @@ -7545,7 +8463,9 @@ "type": "string" } }, - "required": ["hint"], + "required": [ + "hint" + ], "additionalProperties": false } }, @@ -7574,7 +8494,10 @@ "type": "string" } }, - "required": ["hint", "header"], + "required": [ + "hint", + "header" + ], "additionalProperties": false }, "details": { @@ -7596,7 +8519,12 @@ "type": "string" } }, - "required": ["type", "currency", "limit", "used"], + "required": [ + "type", + "currency", + "limit", + "used" + ], "additionalProperties": false }, "type": { @@ -7612,7 +8540,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "usage": { @@ -7625,11 +8556,17 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false } }, - "required": ["spend", "usage"], + "required": [ + "spend", + "usage" + ], "additionalProperties": false }, "edit": { @@ -7639,11 +8576,19 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false } }, - "required": ["create", "details", "fields", "type", "edit"], + "required": [ + "create", + "details", + "fields", + "type", + "edit" + ], "additionalProperties": false }, "promotions": { @@ -7659,7 +8604,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "alreadyAdded": { @@ -7678,7 +8626,9 @@ "type": "string" } }, - "required": ["success"], + "required": [ + "success" + ], "additionalProperties": false }, "add": { @@ -7691,11 +8641,15 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false }, "list": { @@ -7705,7 +8659,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, @@ -7762,7 +8718,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "create": { @@ -7787,7 +8746,11 @@ "type": "string" } }, - "required": ["details", "products", "prices"], + "required": [ + "details", + "products", + "prices" + ], "additionalProperties": false }, "successToast": { @@ -7803,11 +8766,15 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false } }, @@ -7830,7 +8797,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "configuration": { @@ -7852,11 +8822,18 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false } }, - "required": ["header", "edit"], + "required": [ + "header", + "edit" + ], "additionalProperties": false }, "products": { @@ -7875,7 +8852,10 @@ "type": "string" } }, - "required": ["addProducts", "editPrices"], + "required": [ + "addProducts", + "editPrices" + ], "additionalProperties": false }, "delete": { @@ -7909,7 +8889,9 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false }, "edit": { @@ -7919,11 +8901,19 @@ "type": "string" } }, - "required": ["successToast"], + "required": [ + "successToast" + ], "additionalProperties": false } }, - "required": ["header", "actions", "delete", "add", "edit"], + "required": [ + "header", + "actions", + "delete", + "add", + "edit" + ], "additionalProperties": false }, "fields": { @@ -7939,7 +8929,10 @@ "type": "string" } }, - "required": ["label", "header"], + "required": [ + "label", + "header" + ], "additionalProperties": false }, "status": { @@ -7964,11 +8957,19 @@ "type": "string" } }, - "required": ["active", "draft", "expired", "scheduled"], + "required": [ + "active", + "draft", + "expired", + "scheduled" + ], "additionalProperties": false } }, - "required": ["label", "options"], + "required": [ + "label", + "options" + ], "additionalProperties": false }, "type": { @@ -7993,7 +8994,10 @@ "type": "string" } }, - "required": ["label", "description"], + "required": [ + "label", + "description" + ], "additionalProperties": false }, "override": { @@ -8006,15 +9010,25 @@ "type": "string" } }, - "required": ["label", "description"], + "required": [ + "label", + "description" + ], "additionalProperties": false } }, - "required": ["sale", "override"], + "required": [ + "sale", + "override" + ], "additionalProperties": false } }, - "required": ["label", "hint", "options"], + "required": [ + "label", + "hint", + "options" + ], "additionalProperties": false }, "startsAt": { @@ -8027,7 +9041,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "endsAt": { @@ -8040,7 +9057,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false }, "customerAvailability": { @@ -8114,7 +9134,10 @@ "type": "string" } }, - "required": ["languageLabel", "usageInsightsLabel"], + "required": [ + "languageLabel", + "usageInsightsLabel" + ], "additionalProperties": false }, "edit": { @@ -8148,7 +9171,9 @@ "type": "string" } }, - "required": ["edit"], + "required": [ + "edit" + ], "additionalProperties": false } }, @@ -8213,7 +9238,11 @@ "type": "string" } }, - "required": ["accepted", "pending", "expired"], + "required": [ + "accepted", + "pending", + "expired" + ], "additionalProperties": false }, "roles": { @@ -8229,7 +9258,11 @@ "type": "string" } }, - "required": ["admin", "developer", "member"], + "required": [ + "admin", + "developer", + "member" + ], "additionalProperties": false }, "deleteUserWarning": { @@ -8314,7 +9347,9 @@ "type": "string" } }, - "required": ["header"], + "required": [ + "header" + ], "additionalProperties": false }, "toast": { @@ -8436,7 +9471,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "toast": { @@ -8455,7 +9492,12 @@ "type": "string" } }, - "required": ["delete", "edit", "create", "countries"], + "required": [ + "delete", + "edit", + "create", + "countries" + ], "additionalProperties": false }, "shippingOption": { @@ -8489,7 +9531,12 @@ "type": "string" } }, - "required": ["outbound", "outboundHint", "return", "returnHint"], + "required": [ + "outbound", + "outboundHint", + "return", + "returnHint" + ], "additionalProperties": false }, "priceType": { @@ -8505,7 +9552,11 @@ "type": "string" } }, - "required": ["label", "flatRate", "calculated"], + "required": [ + "label", + "flatRate", + "calculated" + ], "additionalProperties": false }, "availability": { @@ -8518,7 +9569,10 @@ "type": "string" } }, - "required": ["adminOnly", "adminOnlyHint"], + "required": [ + "adminOnly", + "adminOnlyHint" + ], "additionalProperties": false }, "taxInclusiveHint": { @@ -8534,7 +9588,10 @@ "type": "string" } }, - "required": ["label", "hint"], + "required": [ + "label", + "hint" + ], "additionalProperties": false } }, @@ -8596,7 +9653,9 @@ "type": "string" } }, - "required": ["taxCountriesHint"], + "required": [ + "taxCountriesHint" + ], "additionalProperties": false }, "settings": { @@ -8650,7 +9709,9 @@ "type": "string" } }, - "required": ["sectionTitle"], + "required": [ + "sectionTitle" + ], "additionalProperties": false }, "taxRate": { @@ -8800,7 +9861,11 @@ "type": "string" } }, - "required": ["create", "update", "removeChannel"], + "required": [ + "create", + "update", + "removeChannel" + ], "additionalProperties": false } }, @@ -8830,7 +9895,11 @@ "type": "string" } }, - "required": ["domain", "subtitle", "deleteWarning"], + "required": [ + "domain", + "subtitle", + "deleteWarning" + ], "additionalProperties": false }, "salesChannels": { @@ -8882,7 +9951,11 @@ "type": "string" } }, - "required": ["create", "update", "delete"], + "required": [ + "create", + "update", + "delete" + ], "additionalProperties": false }, "tooltip": { @@ -8892,7 +9965,9 @@ "type": "string" } }, - "required": ["cannotDeleteDefault"], + "required": [ + "cannotDeleteDefault" + ], "additionalProperties": false }, "products": { @@ -8905,7 +9980,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "add": { @@ -8918,15 +9995,22 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false } }, - "required": ["list", "add"], + "required": [ + "list", + "add" + ], "additionalProperties": false } }, @@ -8961,7 +10045,10 @@ "type": "string" } }, - "required": ["publishable", "secret"], + "required": [ + "publishable", + "secret" + ], "additionalProperties": false }, "subtitle": { @@ -8974,7 +10061,10 @@ "type": "string" } }, - "required": ["publishable", "secret"], + "required": [ + "publishable", + "secret" + ], "additionalProperties": false }, "status": { @@ -8987,7 +10077,10 @@ "type": "string" } }, - "required": ["active", "revoked"], + "required": [ + "active", + "revoked" + ], "additionalProperties": false }, "type": { @@ -9000,7 +10093,10 @@ "type": "string" } }, - "required": ["publishable", "secret"], + "required": [ + "publishable", + "secret" + ], "additionalProperties": false }, "create": { @@ -9060,7 +10156,11 @@ "type": "string" } }, - "required": ["header", "description", "successToast"], + "required": [ + "header", + "description", + "successToast" + ], "additionalProperties": false }, "salesChannels": { @@ -9088,7 +10188,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, @@ -9112,7 +10214,10 @@ "type": "string" } }, - "required": ["warning", "successToast"], + "required": [ + "warning", + "successToast" + ], "additionalProperties": false }, "revoke": { @@ -9125,7 +10230,10 @@ "type": "string" } }, - "required": ["warning", "successToast"], + "required": [ + "warning", + "successToast" + ], "additionalProperties": false }, "addSalesChannels": { @@ -9138,11 +10246,15 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false } }, - "required": ["list"], + "required": [ + "list" + ], "additionalProperties": false }, "removeSalesChannel": { @@ -9190,7 +10302,11 @@ "type": "string" } }, - "required": ["revoke", "copy", "copySuccessToast"], + "required": [ + "revoke", + "copy", + "copySuccessToast" + ], "additionalProperties": false }, "table": { @@ -9203,7 +10319,10 @@ "type": "string" } }, - "required": ["lastUsedAtHeader", "createdAtHeader"], + "required": [ + "lastUsedAtHeader", + "createdAtHeader" + ], "additionalProperties": false }, "fields": { @@ -9280,7 +10399,12 @@ "type": "string" } }, - "required": ["header", "subtitle", "hint", "successToast"], + "required": [ + "header", + "subtitle", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -9296,7 +10420,11 @@ "type": "string" } }, - "required": ["header", "subtitle", "successToast"], + "required": [ + "header", + "subtitle", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -9309,7 +10437,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -9328,7 +10459,11 @@ "type": "string" } }, - "required": ["label", "placeholder", "tooltip"], + "required": [ + "label", + "placeholder", + "tooltip" + ], "additionalProperties": false }, "label": { @@ -9341,7 +10476,10 @@ "type": "string" } }, - "required": ["label", "placeholder"], + "required": [ + "label", + "placeholder" + ], "additionalProperties": false }, "description": { @@ -9354,11 +10492,18 @@ "type": "string" } }, - "required": ["label", "placeholder"], + "required": [ + "label", + "placeholder" + ], "additionalProperties": false } }, - "required": ["value", "label", "description"], + "required": [ + "value", + "label", + "description" + ], "additionalProperties": false } }, @@ -9387,7 +10532,11 @@ "type": "string" } }, - "required": ["forgotPassword", "title", "hint"], + "required": [ + "forgotPassword", + "title", + "hint" + ], "additionalProperties": false }, "invite": { @@ -9439,7 +10588,9 @@ "type": "string" } }, - "required": ["accepted"], + "required": [ + "accepted" + ], "additionalProperties": false } }, @@ -9584,7 +10735,9 @@ "type": "string" } }, - "required": ["noRecordsMessage"], + "required": [ + "noRecordsMessage" + ], "additionalProperties": false }, "history": { @@ -9681,11 +10834,15 @@ "type": "string" } }, - "required": ["waitingToCompensate"], + "required": [ + "waitingToCompensate" + ], "additionalProperties": false } }, - "required": ["state"], + "required": [ + "state" + ], "additionalProperties": false }, "step": { @@ -9707,11 +10864,18 @@ "type": "string" } }, - "required": ["skipped", "skippedFailure", "dormant", "timeout"], + "required": [ + "skipped", + "skippedFailure", + "dormant", + "timeout" + ], "additionalProperties": false } }, - "required": ["state"], + "required": [ + "state" + ], "additionalProperties": false } }, @@ -9753,7 +10917,11 @@ "type": "string" } }, - "required": ["header", "hint", "successToast"], + "required": [ + "header", + "hint", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -9766,7 +10934,10 @@ "type": "string" } }, - "required": ["header", "successToast"], + "required": [ + "header", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -9779,7 +10950,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -9789,11 +10963,20 @@ "type": "string" } }, - "required": ["value"], + "required": [ + "value" + ], "additionalProperties": false } }, - "required": ["domain", "subtitle", "create", "edit", "delete", "fields"], + "required": [ + "domain", + "subtitle", + "create", + "edit", + "delete", + "fields" + ], "additionalProperties": false }, "productTags": { @@ -9815,7 +10998,11 @@ "type": "string" } }, - "required": ["header", "subtitle", "successToast"], + "required": [ + "header", + "subtitle", + "successToast" + ], "additionalProperties": false }, "edit": { @@ -9831,7 +11018,11 @@ "type": "string" } }, - "required": ["header", "subtitle", "successToast"], + "required": [ + "header", + "subtitle", + "successToast" + ], "additionalProperties": false }, "delete": { @@ -9844,7 +11035,10 @@ "type": "string" } }, - "required": ["confirmation", "successToast"], + "required": [ + "confirmation", + "successToast" + ], "additionalProperties": false }, "fields": { @@ -9854,11 +11048,19 @@ "type": "string" } }, - "required": ["value"], + "required": [ + "value" + ], "additionalProperties": false } }, - "required": ["domain", "create", "edit", "delete", "fields"], + "required": [ + "domain", + "create", + "edit", + "delete", + "fields" + ], "additionalProperties": false }, "notifications": { @@ -9877,7 +11079,10 @@ "type": "string" } }, - "required": ["title", "description"], + "required": [ + "title", + "description" + ], "additionalProperties": false }, "accessibility": { @@ -9887,11 +11092,17 @@ "type": "string" } }, - "required": ["description"], + "required": [ + "description" + ], "additionalProperties": false } }, - "required": ["domain", "emptyState", "accessibility"], + "required": [ + "domain", + "emptyState", + "accessibility" + ], "additionalProperties": false }, "errors": { @@ -9904,7 +11115,10 @@ "type": "string" } }, - "required": ["serverError", "invalidCredentials"], + "required": [ + "serverError", + "invalidCredentials" + ], "additionalProperties": false }, "statuses": { @@ -9926,7 +11140,13 @@ "type": "string" } }, - "required": ["scheduled", "expired", "active", "enabled", "disabled"], + "required": [ + "scheduled", + "expired", + "active", + "enabled", + "disabled" + ], "additionalProperties": false }, "labels": { @@ -10721,4 +11941,4 @@ "dateTime" ], "additionalProperties": false -} +} \ No newline at end of file diff --git a/packages/admin/dashboard/src/i18n/translations/en.json b/packages/admin/dashboard/src/i18n/translations/en.json index ab3dcd791eb2a..ce5dddd9dd288 100644 --- a/packages/admin/dashboard/src/i18n/translations/en.json +++ b/packages/admin/dashboard/src/i18n/translations/en.json @@ -648,6 +648,7 @@ "stock": { "heading": "Manage product stock levels and locations", "description": "Update the stocked inventory levels for all of the product's variants.", + "loading": "Hang on this may take a moment...", "tooltips": { "alreadyManaged": "This inventory item is already editable under {{title}}.", "alreadyManagedWithSku": "This inventory item is already editable under {{title}} ({{sku}})." @@ -812,6 +813,7 @@ "title": "Update inventory levels", "description": "Update the stocked inventory levels for the selected inventory items.", "action": "Edit stock levels", + "placeholder": "Not enabled", "disablePrompt_one": "You are about to disable {{count}} location level. This action cannot be undone.", "disablePrompt_other": "You are about to disable {{count}} location levels. This action cannot be undone.", "disabledToggleTooltip": "Cannot disable: clear incoming and/or reserved quantity before disabling.", diff --git a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-inventory-data.tsx b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-inventory-data.tsx index fde29b812dbad..8964c36271a01 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-inventory-data.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-inventory-data.tsx @@ -1,37 +1,70 @@ -import { useProductVariants, useStockLocations } from "../../../../hooks/api" +import { HttpTypes } from "@medusajs/types" +import { useEffect, useState } from "react" +import { useStockLocations } from "../../../../hooks/api" +import { sdk } from "../../../../lib/client" export const useProductInventoryData = ( id: string, productVariantIds?: string[] ) => { - const variantData = useProductVariants(id, { - id: productVariantIds, - limit: !productVariantIds ? 9999 : undefined, - fields: - "id,title,sku,inventory_items,inventory_items.*,inventory_items.inventory,inventory_items.inventory.id,inventory_items.inventory.title,inventory_items.inventory.sku,*inventory_items.inventory.location_levels,product.thumbnail", - }) + const [variants, setVariants] = useState([]) + const [isLoadingVariants, setIsLoadingVariants] = useState(true) const locationData = useStockLocations({ limit: 9999, fields: "id,name", }) - const isLoaded = - !variantData.isPending && - !locationData.isPending && - !!variantData.variants && - !!locationData.stock_locations + /** + * Loads variants in chunks of 20. + * + * This is to avoid loading too many variants at once, which + * can cause OOM errors. + */ + useEffect(() => { + const fetchAllVariants = async () => { + setIsLoadingVariants(true) + try { + const CHUNK_SIZE = 20 + let offset = 0 + let allVariants: HttpTypes.AdminProductVariant[] = [] + let totalCount = 0 - if (variantData.isError) { - throw variantData.error - } + do { + const { variants: chunk, count } = + await sdk.admin.product.listVariants(id, { + id: productVariantIds, + offset, + limit: CHUNK_SIZE, + fields: + "id,title,sku,inventory_items,inventory_items.*,inventory_items.inventory,inventory_items.inventory.id,inventory_items.inventory.title,inventory_items.inventory.sku,*inventory_items.inventory.location_levels,product.thumbnail", + }) + + allVariants = [...allVariants, ...chunk] + totalCount = count + offset += CHUNK_SIZE + } while (allVariants.length < totalCount) + + setVariants(allVariants) + } finally { + setIsLoadingVariants(false) + } + } + + fetchAllVariants() + }, [id, productVariantIds]) if (locationData.isError) { throw locationData.error } + const isLoaded = + !isLoadingVariants && + !locationData.isPending && + !!locationData.stock_locations + return { - variants: variantData.variants || [], + variants, locations: locationData.stock_locations || [], isLoaded, } diff --git a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx index a7d0f7f0e1597..61cff72d777e6 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx @@ -211,7 +211,7 @@ export const useProductStockColumns = ( disabledToggleTooltip={t( "inventory.stock.disabledToggleTooltip" )} - placeholder="Not available" + placeholder={t("inventory.stock.placeholder")} /> ) }, diff --git a/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx b/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx index 107365c5d31e7..c0e6a5b9f70cf 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx @@ -1,5 +1,10 @@ +import { Spinner } from "@medusajs/icons" +import { Text } from "@medusajs/ui" +import { ColumnDef } from "@tanstack/react-table" import { useTranslation } from "react-i18next" import { useParams, useSearchParams } from "react-router-dom" +import { Skeleton } from "../../../components/common/skeleton" +import { DataGridSkeleton } from "../../../components/data-grid/components" import { RouteFocusModal } from "../../../components/modals" import { PRODUCT_VARIANT_IDS_KEY } from "../common/constants" import { ProductStockForm } from "./components/product-stock-form" @@ -26,9 +31,40 @@ export const ProductStock = () => { {t("products.stock.description")} - {isLoaded && ( + {isLoaded ? ( + ) : ( + )} ) } + +const ProductStockSkeleton = () => { + const { t } = useTranslation() + + return ( +
+
+ + + {t("products.stock.loading")} + +
+
+
+ +
+
+ []} + /> +
+
+ + +
+
+
+ ) +} From af946b8370862e75907c0eb8d119d75d058dc254 Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Fri, 20 Dec 2024 09:54:54 +0100 Subject: [PATCH 13/19] format schema --- .../src/i18n/translations/$schema.json | 1974 ++++------------- 1 file changed, 383 insertions(+), 1591 deletions(-) diff --git a/packages/admin/dashboard/src/i18n/translations/$schema.json b/packages/admin/dashboard/src/i18n/translations/$schema.json index 4ec46dc7e107e..7ba0bdcdb00ba 100644 --- a/packages/admin/dashboard/src/i18n/translations/$schema.json +++ b/packages/admin/dashboard/src/i18n/translations/$schema.json @@ -258,11 +258,7 @@ "type": "string" } }, - "required": [ - "header_one", - "header_other", - "description" - ], + "required": ["header_one", "header_other", "description"], "additionalProperties": false } }, @@ -311,11 +307,7 @@ "type": "string" } }, - "required": [ - "insertRowAbove", - "insertRowBelow", - "deleteRow" - ], + "required": ["insertRowAbove", "insertRowBelow", "deleteRow"], "additionalProperties": false }, "labels": { @@ -328,10 +320,7 @@ "type": "string" } }, - "required": [ - "key", - "value" - ], + "required": ["key", "value"], "additionalProperties": false }, "complexRow": { @@ -347,11 +336,7 @@ "type": "string" } }, - "required": [ - "label", - "description", - "tooltip" - ], + "required": ["label", "description", "tooltip"], "additionalProperties": false } }, @@ -366,12 +351,7 @@ "additionalProperties": false } }, - "required": [ - "header", - "numberOfKeys_one", - "numberOfKeys_other", - "edit" - ], + "required": ["header", "numberOfKeys_one", "numberOfKeys_other", "edit"], "additionalProperties": false }, "validation": { @@ -384,10 +364,7 @@ "type": "string" } }, - "required": [ - "mustBeInt", - "mustBePositive" - ], + "required": ["mustBeInt", "mustBePositive"], "additionalProperties": false }, "actions": { @@ -573,9 +550,7 @@ "type": "string" } }, - "required": [ - "in" - ], + "required": ["in"], "additionalProperties": false }, "app": { @@ -926,12 +901,7 @@ "type": "string" } }, - "required": [ - "label", - "dark", - "light", - "system" - ], + "required": ["label", "dark", "light", "system"], "additionalProperties": false } }, @@ -954,10 +924,7 @@ "type": "string" } }, - "required": [ - "label", - "storeSettings" - ], + "required": ["label", "storeSettings"], "additionalProperties": false }, "actions": { @@ -967,17 +934,11 @@ "type": "string" } }, - "required": [ - "logout" - ], + "required": ["logout"], "additionalProperties": false } }, - "required": [ - "user", - "store", - "actions" - ], + "required": ["user", "store", "actions"], "additionalProperties": false }, "nav": { @@ -993,10 +954,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "common": { @@ -1006,9 +964,7 @@ "type": "string" } }, - "required": [ - "extensions" - ], + "required": ["extensions"], "additionalProperties": false }, "main": { @@ -1021,10 +977,7 @@ "type": "string" } }, - "required": [ - "store", - "storeSettings" - ], + "required": ["store", "storeSettings"], "additionalProperties": false }, "settings": { @@ -1043,30 +996,15 @@ "type": "string" } }, - "required": [ - "header", - "general", - "developer", - "myAccount" - ], + "required": ["header", "general", "developer", "myAccount"], "additionalProperties": false } }, - "required": [ - "accessibility", - "common", - "main", - "settings" - ], + "required": ["accessibility", "common", "main", "settings"], "additionalProperties": false } }, - "required": [ - "search", - "keyboardShortcuts", - "menus", - "nav" - ], + "required": ["search", "keyboardShortcuts", "menus", "nav"], "additionalProperties": false }, "dataGrid": { @@ -1085,11 +1023,7 @@ "type": "string" } }, - "required": [ - "view", - "resetToDefault", - "disabled" - ], + "required": ["view", "resetToDefault", "disabled"], "additionalProperties": false }, "shortcuts": { @@ -1183,10 +1117,7 @@ "additionalProperties": false } }, - "required": [ - "label", - "commands" - ], + "required": ["label", "commands"], "additionalProperties": false }, "errors": { @@ -1202,19 +1133,11 @@ "type": "string" } }, - "required": [ - "fixError", - "count_one", - "count_other" - ], + "required": ["fixError", "count_one", "count_other"], "additionalProperties": false } }, - "required": [ - "columns", - "shortcuts", - "errors" - ], + "required": ["columns", "shortcuts", "errors"], "additionalProperties": false }, "filters": { @@ -1300,11 +1223,7 @@ "type": "string" } }, - "required": [ - "date", - "compare", - "addFilter" - ], + "required": ["date", "compare", "addFilter"], "additionalProperties": false }, "errorBoundary": { @@ -1374,12 +1293,7 @@ "type": "string" } }, - "required": [ - "header", - "editHeader", - "editLabel", - "label" - ], + "required": ["header", "editHeader", "editLabel", "label"], "additionalProperties": false }, "billingAddress": { @@ -1438,11 +1352,7 @@ "type": "string" } }, - "required": [ - "editHeader", - "editLabel", - "label" - ], + "required": ["editHeader", "editLabel", "label"], "additionalProperties": false }, "transferOwnership": { @@ -1464,10 +1374,7 @@ "type": "string" } }, - "required": [ - "order", - "draft" - ], + "required": ["order", "draft"], "additionalProperties": false }, "currentOwner": { @@ -1480,10 +1387,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "newOwner": { @@ -1496,10 +1400,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "validation": { @@ -1512,10 +1413,7 @@ "type": "string" } }, - "required": [ - "mustBeDifferent", - "required" - ], + "required": ["mustBeDifferent", "required"], "additionalProperties": false } }, @@ -1536,9 +1434,7 @@ "type": "string" } }, - "required": [ - "availableIn" - ], + "required": ["availableIn"], "additionalProperties": false }, "products": { @@ -1554,9 +1450,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "edit": { @@ -1572,11 +1466,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "create": { @@ -1607,12 +1497,7 @@ "type": "string" } }, - "required": [ - "details", - "organize", - "variants", - "inventory" - ], + "required": ["details", "organize", "variants", "inventory"], "additionalProperties": false }, "errors": { @@ -1628,11 +1513,7 @@ "type": "string" } }, - "required": [ - "variants", - "options", - "uniqueSku" - ], + "required": ["variants", "options", "uniqueSku"], "additionalProperties": false }, "inventory": { @@ -1678,9 +1559,7 @@ "type": "string" } }, - "required": [ - "placeholder" - ], + "required": ["placeholder"], "additionalProperties": false }, "optionValues": { @@ -1690,9 +1569,7 @@ "type": "string" } }, - "required": [ - "placeholder" - ], + "required": ["placeholder"], "additionalProperties": false }, "productVariants": { @@ -1711,12 +1588,7 @@ "type": "string" } }, - "required": [ - "label", - "hint", - "alert", - "tip" - ], + "required": ["label", "hint", "alert", "tip"], "additionalProperties": false }, "productOptions": { @@ -1729,10 +1601,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false } }, @@ -1782,10 +1651,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "filters": { @@ -1798,10 +1664,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "columns": { @@ -1814,10 +1677,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -1855,10 +1715,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "upload": { @@ -1899,10 +1756,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -1996,11 +1850,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "action" - ], + "required": ["header", "description", "action"], "additionalProperties": false }, "successToast": { @@ -2059,12 +1909,7 @@ "type": "string" } }, - "required": [ - "draft", - "published", - "proposed", - "rejected" - ], + "required": ["draft", "published", "proposed", "rejected"], "additionalProperties": false }, "fields": { @@ -2080,10 +1925,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "subtitle": { @@ -2093,9 +1935,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "handle": { @@ -2108,10 +1948,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip" - ], + "required": ["label", "tooltip"], "additionalProperties": false }, "description": { @@ -2124,10 +1961,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "discountable": { @@ -2140,10 +1974,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "type": { @@ -2153,9 +1984,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "collection": { @@ -2165,9 +1994,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "categories": { @@ -2177,9 +2004,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "tags": { @@ -2189,9 +2014,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "sales_channels": { @@ -2204,10 +2027,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "countryOrigin": { @@ -2217,9 +2037,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "material": { @@ -2229,9 +2047,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "width": { @@ -2241,9 +2057,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "length": { @@ -2253,9 +2067,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "height": { @@ -2265,9 +2077,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "weight": { @@ -2277,9 +2087,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "options": { @@ -2328,10 +2136,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "mid_code": { @@ -2341,9 +2146,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "hs_code": { @@ -2353,9 +2156,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false } }, @@ -2396,10 +2197,7 @@ "type": "string" } }, - "required": [ - "header", - "success" - ], + "required": ["header", "success"], "additionalProperties": false }, "create": { @@ -2409,9 +2207,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "deleteWarning": { @@ -2457,10 +2253,7 @@ "type": "string" } }, - "required": [ - "inventoryItems", - "inventoryKit" - ], + "required": ["inventoryItems", "inventoryKit"], "additionalProperties": false }, "inventoryKit": { @@ -2479,10 +2272,7 @@ "type": "string" } }, - "required": [ - "itemId", - "quantity" - ], + "required": ["itemId", "quantity"], "additionalProperties": false }, "header": { @@ -2577,10 +2367,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "create": { @@ -2593,22 +2380,14 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "deleteWarning": { "type": "string" } }, - "required": [ - "header", - "edit", - "create", - "deleteWarning" - ], + "required": ["header", "edit", "create", "deleteWarning"], "additionalProperties": false }, "organization": { @@ -2630,23 +2409,15 @@ "type": "string" } }, - "required": [ - "success" - ], + "required": ["success"], "additionalProperties": false } }, - "required": [ - "header", - "toasts" - ], + "required": ["header", "toasts"], "additionalProperties": false } }, - "required": [ - "header", - "edit" - ], + "required": ["header", "edit"], "additionalProperties": false }, "stock": { @@ -2671,19 +2442,11 @@ "type": "string" } }, - "required": [ - "alreadyManaged", - "alreadyManagedWithSku" - ], + "required": ["alreadyManaged", "alreadyManagedWithSku"], "additionalProperties": false } }, - "required": [ - "heading", - "description", - "loading", - "tooltips" - ], + "required": ["heading", "description", "loading", "tooltips"], "additionalProperties": false }, "toasts": { @@ -2702,10 +2465,7 @@ "type": "string" } }, - "required": [ - "header", - "description" - ], + "required": ["header", "description"], "additionalProperties": false }, "error": { @@ -2715,22 +2475,15 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false } }, - "required": [ - "success", - "error" - ], + "required": ["success", "error"], "additionalProperties": false } }, - "required": [ - "delete" - ], + "required": ["delete"], "additionalProperties": false } }, @@ -2809,9 +2562,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "add": { @@ -2824,10 +2575,7 @@ "type": "string" } }, - "required": [ - "successToast_one", - "successToast_other" - ], + "required": ["successToast_one", "successToast_other"], "additionalProperties": false }, "remove": { @@ -2840,18 +2588,11 @@ "type": "string" } }, - "required": [ - "successToast_one", - "successToast_other" - ], + "required": ["successToast_one", "successToast_other"], "additionalProperties": false } }, - "required": [ - "list", - "add", - "remove" - ], + "required": ["list", "add", "remove"], "additionalProperties": false } }, @@ -2899,22 +2640,14 @@ "type": "string" } }, - "required": [ - "details", - "organize" - ], + "required": ["details", "organize"], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": [ - "header", - "hint", - "tabs", - "successToast" - ], + "required": ["header", "hint", "tabs", "successToast"], "additionalProperties": false }, "edit": { @@ -2930,11 +2663,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "delete": { @@ -2947,10 +2676,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "products": { @@ -3007,17 +2733,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "add", - "remove", - "list" - ], + "required": ["add", "remove", "list"], "additionalProperties": false }, "organize": { @@ -3030,10 +2750,7 @@ "type": "string" } }, - "required": [ - "header", - "action" - ], + "required": ["header", "action"], "additionalProperties": false }, "fields": { @@ -3052,11 +2769,7 @@ "type": "string" } }, - "required": [ - "label", - "internal", - "public" - ], + "required": ["label", "internal", "public"], "additionalProperties": false }, "status": { @@ -3072,11 +2785,7 @@ "type": "string" } }, - "required": [ - "label", - "active", - "inactive" - ], + "required": ["label", "active", "inactive"], "additionalProperties": false }, "path": { @@ -3089,10 +2798,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip" - ], + "required": ["label", "tooltip"], "additionalProperties": false }, "children": { @@ -3102,9 +2808,7 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false }, "new": { @@ -3114,19 +2818,11 @@ "type": "string" } }, - "required": [ - "label" - ], + "required": ["label"], "additionalProperties": false } }, - "required": [ - "visibility", - "status", - "path", - "children", - "new" - ], + "required": ["visibility", "status", "path", "children", "new"], "additionalProperties": false } }, @@ -3276,10 +2972,7 @@ "type": "string" } }, - "required": [ - "noAvaliableQuantity", - "quantityOutOfRange" - ], + "required": ["noAvaliableQuantity", "quantityOutOfRange"], "additionalProperties": false } }, @@ -3315,15 +3008,11 @@ "type": "string" } }, - "required": [ - "stockedQuantity" - ], + "required": ["stockedQuantity"], "additionalProperties": false } }, - "required": [ - "errors" - ], + "required": ["errors"], "additionalProperties": false }, "toast": { @@ -3339,11 +3028,7 @@ "type": "string" } }, - "required": [ - "updateLocations", - "updateLevel", - "updateItem" - ], + "required": ["updateLocations", "updateLevel", "updateItem"], "additionalProperties": false }, "stock": { @@ -3490,9 +3175,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "create": { @@ -3508,11 +3191,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "groups": { @@ -3537,9 +3216,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "add": { @@ -3555,16 +3232,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "success", - "list" - ], + "required": ["success", "list"], "additionalProperties": false }, "removed": { @@ -3580,16 +3252,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "success", - "list" - ], + "required": ["success", "list"], "additionalProperties": false } }, @@ -3617,11 +3284,7 @@ "type": "string" } }, - "required": [ - "header", - "emailDisabledTooltip", - "successToast" - ], + "required": ["header", "emailDisabledTooltip", "successToast"], "additionalProperties": false }, "delete": { @@ -3637,11 +3300,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "fields": { @@ -3657,11 +3316,7 @@ "type": "string" } }, - "required": [ - "guest", - "registered", - "groups" - ], + "required": ["guest", "registered", "groups"], "additionalProperties": false }, "registered": { @@ -3710,11 +3365,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -3727,10 +3378,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "delete": { @@ -3746,11 +3394,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "customers": { @@ -3775,17 +3419,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "successToast_one", - "successToast_other", - "list" - ], + "required": ["successToast_one", "successToast_other", "list"], "additionalProperties": false }, "remove": { @@ -3819,18 +3457,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "alreadyAddedTooltip", - "add", - "remove", - "list" - ], + "required": ["alreadyAddedTooltip", "add", "remove", "list"], "additionalProperties": false } }, @@ -3872,9 +3503,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "summary": { @@ -4166,10 +3795,7 @@ "type": "string" } }, - "required": [ - "title", - "titlePending" - ], + "required": ["title", "titlePending"], "additionalProperties": false }, "toast": { @@ -4182,10 +3808,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "validation": { @@ -4195,9 +3818,7 @@ "type": "string" } }, - "required": [ - "quantityLowerThanFulfillment" - ], + "required": ["quantityLowerThanFulfillment"], "additionalProperties": false } }, @@ -4238,10 +3859,7 @@ "type": "string" } }, - "required": [ - "title", - "requestSuccess" - ], + "required": ["title", "requestSuccess"], "additionalProperties": false }, "shippingAddress": { @@ -4254,10 +3872,7 @@ "type": "string" } }, - "required": [ - "title", - "requestSuccess" - ], + "required": ["title", "requestSuccess"], "additionalProperties": false }, "billingAddress": { @@ -4270,18 +3885,11 @@ "type": "string" } }, - "required": [ - "title", - "requestSuccess" - ], + "required": ["title", "requestSuccess"], "additionalProperties": false } }, - "required": [ - "email", - "shippingAddress", - "billingAddress" - ], + "required": ["email", "shippingAddress", "billingAddress"], "additionalProperties": false }, "returns": { @@ -4387,10 +3995,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "placeholders": { @@ -4406,10 +4011,7 @@ "type": "string" } }, - "required": [ - "title", - "hint" - ], + "required": ["title", "hint"], "additionalProperties": false }, "outboundShippingOptions": { @@ -4422,10 +4024,7 @@ "type": "string" } }, - "required": [ - "title", - "hint" - ], + "required": ["title", "hint"], "additionalProperties": false } }, @@ -4510,10 +4109,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "panel": { @@ -4526,10 +4122,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -4618,15 +4211,11 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false } }, - "required": [ - "cancelClaim" - ], + "required": ["cancelClaim"], "additionalProperties": false }, "cancel": { @@ -4639,10 +4228,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "tooltips": { @@ -4652,9 +4238,7 @@ "type": "string" } }, - "required": [ - "onlyReturnShippingOptions" - ], + "required": ["onlyReturnShippingOptions"], "additionalProperties": false }, "toast": { @@ -4667,10 +4251,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "panel": { @@ -4683,10 +4264,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -4756,15 +4334,11 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false } }, - "required": [ - "cancelExchange" - ], + "required": ["cancelExchange"], "additionalProperties": false }, "cancel": { @@ -4777,10 +4351,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "tooltips": { @@ -4790,9 +4361,7 @@ "type": "string" } }, - "required": [ - "onlyReturnShippingOptions" - ], + "required": ["onlyReturnShippingOptions"], "additionalProperties": false }, "toast": { @@ -4805,10 +4374,7 @@ "type": "string" } }, - "required": [ - "canceledSuccessfully", - "confirmedSuccessfully" - ], + "required": ["canceledSuccessfully", "confirmedSuccessfully"], "additionalProperties": false }, "panel": { @@ -4821,10 +4387,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, @@ -4858,10 +4421,7 @@ "type": "string" } }, - "required": [ - "allocatedLabel", - "notAllocatedLabel" - ], + "required": ["allocatedLabel", "notAllocatedLabel"], "additionalProperties": false }, "allocateItems": { @@ -4898,9 +4458,7 @@ "type": "string" } }, - "required": [ - "created" - ], + "required": ["created"], "additionalProperties": false }, "error": { @@ -4910,9 +4468,7 @@ "type": "string" } }, - "required": [ - "quantityNotAllocated" - ], + "required": ["quantityNotAllocated"], "additionalProperties": false } }, @@ -5035,11 +4591,7 @@ "type": "string" } }, - "required": [ - "wrongQuantity", - "wrongQuantity_other", - "noItems" - ], + "required": ["wrongQuantity", "wrongQuantity_other", "noItems"], "additionalProperties": false }, "status": { @@ -5185,11 +4737,7 @@ "type": "string" } }, - "required": [ - "amountToLarge", - "amountNegative", - "reasonRequired" - ], + "required": ["amountToLarge", "amountNegative", "reasonRequired"], "additionalProperties": false } }, @@ -5285,10 +4833,7 @@ "type": "string" } }, - "required": [ - "toReturn", - "toSend" - ], + "required": ["toReturn", "toSend"], "additionalProperties": false }, "placed": { @@ -5301,10 +4846,7 @@ "type": "string" } }, - "required": [ - "title", - "fromSalesChannel" - ], + "required": ["title", "fromSalesChannel"], "additionalProperties": false }, "canceled": { @@ -5314,9 +4856,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "payment": { @@ -5335,12 +4875,7 @@ "type": "string" } }, - "required": [ - "awaiting", - "captured", - "canceled", - "refunded" - ], + "required": ["awaiting", "captured", "canceled", "refunded"], "additionalProperties": false }, "fulfillment": { @@ -5413,10 +4948,7 @@ "type": "string" } }, - "required": [ - "comment", - "byLine" - ], + "required": ["comment", "byLine"], "additionalProperties": false }, "claim": { @@ -5477,10 +5009,7 @@ "type": "string" } }, - "required": [ - "requested", - "confirmed" - ], + "required": ["requested", "confirmed"], "additionalProperties": false }, "transfer": { @@ -5496,11 +5025,7 @@ "type": "string" } }, - "required": [ - "requested", - "confirmed", - "declined" - ], + "required": ["requested", "confirmed", "declined"], "additionalProperties": false }, "update_order": { @@ -5516,11 +5041,7 @@ "type": "string" } }, - "required": [ - "shipping_address", - "billing_address", - "email" - ], + "required": ["shipping_address", "billing_address", "email"], "additionalProperties": false } }, @@ -5565,11 +5086,7 @@ "type": "string" } }, - "required": [ - "displayId", - "refundableAmount", - "returnableQuantity" - ], + "required": ["displayId", "refundableAmount", "returnableQuantity"], "additionalProperties": false } }, @@ -5628,11 +5145,7 @@ "type": "string" } }, - "required": [ - "label", - "warningTitle", - "warningDescription" - ], + "required": ["label", "warningTitle", "warningDescription"], "additionalProperties": false }, "status": { @@ -5645,10 +5158,7 @@ "type": "string" } }, - "required": [ - "open", - "completed" - ], + "required": ["open", "completed"], "additionalProperties": false }, "create": { @@ -5789,9 +5299,7 @@ "type": "string" } }, - "required": [ - "description" - ], + "required": ["description"], "additionalProperties": false }, "create": { @@ -5807,11 +5315,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -5827,11 +5331,7 @@ "type": "string" } }, - "required": [ - "header", - "viewInventory", - "successToast" - ], + "required": ["header", "viewInventory", "successToast"], "additionalProperties": false }, "delete": { @@ -5841,9 +5341,7 @@ "type": "string" } }, - "required": [ - "confirmation" - ], + "required": ["confirmation"], "additionalProperties": false }, "fulfillmentProviders": { @@ -5892,9 +5390,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "shipping": { @@ -5904,9 +5400,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "disable": { @@ -5922,11 +5416,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "pickup", - "shipping" - ], + "required": ["confirmation", "pickup", "shipping"], "additionalProperties": false }, "enable": { @@ -5939,19 +5429,11 @@ "type": "string" } }, - "required": [ - "pickup", - "shipping" - ], + "required": ["pickup", "shipping"], "additionalProperties": false } }, - "required": [ - "pickup", - "shipping", - "disable", - "enable" - ], + "required": ["pickup", "shipping", "disable", "enable"], "additionalProperties": false }, "sidebar": { @@ -5970,17 +5452,11 @@ "type": "string" } }, - "required": [ - "label", - "description" - ], + "required": ["label", "description"], "additionalProperties": false } }, - "required": [ - "header", - "shippingProfiles" - ], + "required": ["header", "shippingProfiles"], "additionalProperties": false }, "salesChannels": { @@ -6037,12 +5513,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "label", - "successToast" - ], + "required": ["header", "hint", "label", "successToast"], "additionalProperties": false }, "returns": { @@ -6061,12 +5532,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "label", - "successToast" - ], + "required": ["header", "hint", "label", "successToast"], "additionalProperties": false }, "tabs": { @@ -6079,22 +5545,14 @@ "type": "string" } }, - "required": [ - "details", - "prices" - ], + "required": ["details", "prices"], "additionalProperties": false }, "action": { "type": "string" } }, - "required": [ - "shipping", - "returns", - "tabs", - "action" - ], + "required": ["shipping", "returns", "tabs", "action"], "additionalProperties": false }, "delete": { @@ -6107,10 +5565,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "edit": { @@ -6126,11 +5581,7 @@ "type": "string" } }, - "required": [ - "header", - "action", - "successToast" - ], + "required": ["header", "action", "successToast"], "additionalProperties": false }, "pricing": { @@ -6140,9 +5591,7 @@ "type": "string" } }, - "required": [ - "action" - ], + "required": ["action"], "additionalProperties": false }, "conditionalPrices": { @@ -6161,9 +5610,7 @@ "type": "string" } }, - "required": [ - "cartItemTotal" - ], + "required": ["cartItemTotal"], "additionalProperties": false }, "summaries": { @@ -6179,11 +5626,7 @@ "type": "string" } }, - "required": [ - "range", - "greaterThan", - "lessThan" - ], + "required": ["range", "greaterThan", "lessThan"], "additionalProperties": false }, "actions": { @@ -6196,10 +5639,7 @@ "type": "string" } }, - "required": [ - "addPrice", - "manageConditionalPrices" - ], + "required": ["addPrice", "manageConditionalPrices"], "additionalProperties": false }, "rules": { @@ -6215,11 +5655,7 @@ "type": "string" } }, - "required": [ - "amount", - "gte", - "lte" - ], + "required": ["amount", "gte", "lte"], "additionalProperties": false }, "customRules": { @@ -6241,13 +5677,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip", - "eq", - "gt", - "lt" - ], + "required": ["label", "tooltip", "eq", "gt", "lt"], "additionalProperties": false }, "errors": { @@ -6337,10 +5767,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "calculated": { @@ -6353,24 +5780,15 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false } }, - "required": [ - "fixed", - "calculated" - ], + "required": ["fixed", "calculated"], "additionalProperties": false } }, - "required": [ - "label", - "options" - ], + "required": ["label", "options"], "additionalProperties": false }, "enableInStore": { @@ -6383,10 +5801,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "provider": { @@ -6453,10 +5868,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "delete": { @@ -6469,10 +5881,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "manageAreas": { @@ -6494,13 +5903,7 @@ "type": "string" } }, - "required": [ - "header", - "action", - "label", - "hint", - "successToast" - ], + "required": ["header", "action", "label", "hint", "successToast"], "additionalProperties": false }, "fields": { @@ -6513,20 +5916,11 @@ "type": "string" } }, - "required": [ - "noRecords", - "tip" - ], + "required": ["noRecords", "tip"], "additionalProperties": false } }, - "required": [ - "create", - "edit", - "delete", - "manageAreas", - "fields" - ], + "required": ["create", "edit", "delete", "manageAreas", "fields"], "additionalProperties": false } }, @@ -6567,11 +5961,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "delete": { @@ -6587,11 +5977,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "tooltip": { @@ -6601,19 +5987,11 @@ "type": "string" } }, - "required": [ - "type" - ], + "required": ["type"], "additionalProperties": false } }, - "required": [ - "domain", - "subtitle", - "create", - "delete", - "tooltip" - ], + "required": ["domain", "subtitle", "create", "delete", "tooltip"], "additionalProperties": false }, "taxRegions": { @@ -6629,9 +6007,7 @@ "type": "string" } }, - "required": [ - "hint" - ], + "required": ["hint"], "additionalProperties": false }, "delete": { @@ -6644,10 +6020,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "create": { @@ -6669,22 +6042,14 @@ "type": "string" } }, - "required": [ - "rateIsRequired", - "nameIsRequired" - ], + "required": ["rateIsRequired", "nameIsRequired"], "additionalProperties": false }, "successToast": { "type": "string" } }, - "required": [ - "header", - "hint", - "errors", - "successToast" - ], + "required": ["header", "hint", "errors", "successToast"], "additionalProperties": false }, "province": { @@ -6703,17 +6068,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "state": { @@ -6732,17 +6091,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "stateOrTerritory": { @@ -6761,17 +6114,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "county": { @@ -6790,17 +6137,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "region": { @@ -6819,17 +6160,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "department": { @@ -6848,17 +6183,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "territory": { @@ -6877,17 +6206,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "prefecture": { @@ -6906,17 +6229,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "district": { @@ -6935,17 +6252,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "governorate": { @@ -6964,17 +6275,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "canton": { @@ -6993,17 +6298,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "emirate": { @@ -7022,17 +6321,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "sublevel": { @@ -7051,17 +6344,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create" - ], + "required": ["header", "create"], "additionalProperties": false }, "taxOverrides": { @@ -7080,10 +6367,7 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false }, "edit": { @@ -7096,18 +6380,11 @@ "type": "string" } }, - "required": [ - "header", - "hint" - ], + "required": ["header", "hint"], "additionalProperties": false } }, - "required": [ - "header", - "create", - "edit" - ], + "required": ["header", "create", "edit"], "additionalProperties": false }, "taxRates": { @@ -7126,11 +6403,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -7146,11 +6419,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "delete": { @@ -7163,18 +6432,11 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false } }, - "required": [ - "create", - "edit", - "delete" - ], + "required": ["create", "edit", "delete"], "additionalProperties": false }, "fields": { @@ -7196,12 +6458,7 @@ "type": "string" } }, - "required": [ - "label", - "hint", - "true", - "false" - ], + "required": ["label", "hint", "true", "false"], "additionalProperties": false }, "defaultTaxRate": { @@ -7217,11 +6474,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip", - "action" - ], + "required": ["label", "tooltip", "action"], "additionalProperties": false }, "taxRate": { @@ -7280,11 +6533,7 @@ "type": "string" } }, - "required": [ - "in", - "on", - "and" - ], + "required": ["in", "on", "and"], "additionalProperties": false }, "placeholders": { @@ -7350,9 +6599,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "values_one": { @@ -7524,10 +6771,7 @@ "type": "string" } }, - "required": [ - "sublevel", - "notPartOfCountry" - ], + "required": ["sublevel", "notPartOfCountry"], "additionalProperties": false }, "alert": { @@ -7543,20 +6787,11 @@ "type": "string" } }, - "required": [ - "header", - "description", - "action" - ], + "required": ["header", "description", "action"], "additionalProperties": false } }, - "required": [ - "labels", - "placeholders", - "tooltips", - "alert" - ], + "required": ["labels", "placeholders", "tooltips", "alert"], "additionalProperties": false }, "noDefaultRate": { @@ -7569,10 +6804,7 @@ "type": "string" } }, - "required": [ - "label", - "tooltip" - ], + "required": ["label", "tooltip"], "additionalProperties": false } }, @@ -7625,9 +6857,7 @@ "type": "string" } }, - "required": [ - "details" - ], + "required": ["details"], "additionalProperties": false }, "tabs": { @@ -7643,11 +6873,7 @@ "type": "string" } }, - "required": [ - "template", - "details", - "campaign" - ], + "required": ["template", "details", "campaign"], "additionalProperties": false }, "fields": { @@ -7684,9 +6910,7 @@ "type": "string" } }, - "required": [ - "tooltip" - ], + "required": ["tooltip"], "additionalProperties": false }, "conditions": { @@ -7702,10 +6926,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "target-rules": { @@ -7718,10 +6939,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "buy-rules": { @@ -7734,18 +6952,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "rules", - "target-rules", - "buy-rules" - ], + "required": ["rules", "target-rules", "buy-rules"], "additionalProperties": false } }, @@ -7770,9 +6981,7 @@ "type": "string" } }, - "required": [ - "campaignType" - ], + "required": ["campaignType"], "additionalProperties": false }, "errors": { @@ -7785,10 +6994,7 @@ "type": "string" } }, - "required": [ - "requiredField", - "promotionTabError" - ], + "required": ["requiredField", "promotionTabError"], "additionalProperties": false }, "toasts": { @@ -7798,9 +7004,7 @@ "type": "string" } }, - "required": [ - "promotionCreateSuccess" - ], + "required": ["promotionCreateSuccess"], "additionalProperties": false }, "create": { @@ -7822,9 +7026,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "target-rules": { @@ -7834,9 +7036,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "buy-rules": { @@ -7846,18 +7046,11 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false } }, - "required": [ - "title", - "rules", - "target-rules", - "buy-rules" - ], + "required": ["title", "rules", "target-rules", "buy-rules"], "additionalProperties": false }, "campaign": { @@ -7876,10 +7069,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "actions": { @@ -7889,17 +7079,11 @@ "type": "string" } }, - "required": [ - "goToCampaign" - ], + "required": ["goToCampaign"], "additionalProperties": false } }, - "required": [ - "header", - "edit", - "actions" - ], + "required": ["header", "edit", "actions"], "additionalProperties": false }, "campaign_currency": { @@ -7909,9 +7093,7 @@ "type": "string" } }, - "required": [ - "tooltip" - ], + "required": ["tooltip"], "additionalProperties": false }, "form": { @@ -7948,18 +7130,11 @@ "type": "string" } }, - "required": [ - "title", - "desc" - ], + "required": ["title", "desc"], "additionalProperties": false } }, - "required": [ - "title", - "description", - "placeholder" - ], + "required": ["title", "description", "placeholder"], "additionalProperties": false }, "new": { @@ -7972,10 +7147,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "none": { @@ -7988,18 +7160,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "existing", - "new", - "none" - ], + "required": ["existing", "new", "none"], "additionalProperties": false }, "status": { @@ -8009,9 +7174,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "method": { @@ -8030,10 +7193,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "automatic": { @@ -8046,18 +7206,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "label", - "code", - "automatic" - ], + "required": ["label", "code", "automatic"], "additionalProperties": false }, "max_quantity": { @@ -8070,10 +7223,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "type": { @@ -8089,10 +7239,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "buyget": { @@ -8105,17 +7252,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "standard", - "buyget" - ], + "required": ["standard", "buyget"], "additionalProperties": false }, "allocation": { @@ -8131,10 +7272,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "across": { @@ -8147,17 +7285,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "each", - "across" - ], + "required": ["each", "across"], "additionalProperties": false }, "code": { @@ -8170,10 +7302,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "value": { @@ -8183,9 +7312,7 @@ "type": "string" } }, - "required": [ - "title" - ], + "required": ["title"], "additionalProperties": false }, "value_type": { @@ -8201,10 +7328,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "percentage": { @@ -8217,17 +7341,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "fixed", - "percentage" - ], + "required": ["fixed", "percentage"], "additionalProperties": false } }, @@ -8269,16 +7387,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "add", - "list" - ], + "required": ["add", "list"], "additionalProperties": false } }, @@ -8324,11 +7437,7 @@ "type": "string" } }, - "required": [ - "active", - "expired", - "scheduled" - ], + "required": ["active", "expired", "scheduled"], "additionalProperties": false }, "delete": { @@ -8344,11 +7453,7 @@ "type": "string" } }, - "required": [ - "title", - "description", - "successToast" - ], + "required": ["title", "description", "successToast"], "additionalProperties": false }, "edit": { @@ -8364,11 +7469,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "configuration": { @@ -8390,18 +7491,11 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false } }, - "required": [ - "header", - "edit" - ], + "required": ["header", "edit"], "additionalProperties": false }, "create": { @@ -8463,9 +7557,7 @@ "type": "string" } }, - "required": [ - "hint" - ], + "required": ["hint"], "additionalProperties": false } }, @@ -8494,10 +7586,7 @@ "type": "string" } }, - "required": [ - "hint", - "header" - ], + "required": ["hint", "header"], "additionalProperties": false }, "details": { @@ -8519,12 +7608,7 @@ "type": "string" } }, - "required": [ - "type", - "currency", - "limit", - "used" - ], + "required": ["type", "currency", "limit", "used"], "additionalProperties": false }, "type": { @@ -8540,10 +7624,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "usage": { @@ -8556,17 +7637,11 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false } }, - "required": [ - "spend", - "usage" - ], + "required": ["spend", "usage"], "additionalProperties": false }, "edit": { @@ -8576,19 +7651,11 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false } - }, - "required": [ - "create", - "details", - "fields", - "type", - "edit" - ], + }, + "required": ["create", "details", "fields", "type", "edit"], "additionalProperties": false }, "promotions": { @@ -8604,10 +7671,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "alreadyAdded": { @@ -8626,9 +7690,7 @@ "type": "string" } }, - "required": [ - "success" - ], + "required": ["success"], "additionalProperties": false }, "add": { @@ -8641,15 +7703,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false }, "list": { @@ -8659,9 +7717,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, @@ -8718,10 +7774,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "create": { @@ -8746,11 +7799,7 @@ "type": "string" } }, - "required": [ - "details", - "products", - "prices" - ], + "required": ["details", "products", "prices"], "additionalProperties": false }, "successToast": { @@ -8766,15 +7815,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false } }, @@ -8797,10 +7842,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "configuration": { @@ -8822,18 +7864,11 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false } }, - "required": [ - "header", - "edit" - ], + "required": ["header", "edit"], "additionalProperties": false }, "products": { @@ -8852,10 +7887,7 @@ "type": "string" } }, - "required": [ - "addProducts", - "editPrices" - ], + "required": ["addProducts", "editPrices"], "additionalProperties": false }, "delete": { @@ -8889,9 +7921,7 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false }, "edit": { @@ -8901,19 +7931,11 @@ "type": "string" } }, - "required": [ - "successToast" - ], + "required": ["successToast"], "additionalProperties": false } }, - "required": [ - "header", - "actions", - "delete", - "add", - "edit" - ], + "required": ["header", "actions", "delete", "add", "edit"], "additionalProperties": false }, "fields": { @@ -8929,10 +7951,7 @@ "type": "string" } }, - "required": [ - "label", - "header" - ], + "required": ["label", "header"], "additionalProperties": false }, "status": { @@ -8957,19 +7976,11 @@ "type": "string" } }, - "required": [ - "active", - "draft", - "expired", - "scheduled" - ], + "required": ["active", "draft", "expired", "scheduled"], "additionalProperties": false } }, - "required": [ - "label", - "options" - ], + "required": ["label", "options"], "additionalProperties": false }, "type": { @@ -8994,10 +8005,7 @@ "type": "string" } }, - "required": [ - "label", - "description" - ], + "required": ["label", "description"], "additionalProperties": false }, "override": { @@ -9010,25 +8018,15 @@ "type": "string" } }, - "required": [ - "label", - "description" - ], + "required": ["label", "description"], "additionalProperties": false } }, - "required": [ - "sale", - "override" - ], + "required": ["sale", "override"], "additionalProperties": false } }, - "required": [ - "label", - "hint", - "options" - ], + "required": ["label", "hint", "options"], "additionalProperties": false }, "startsAt": { @@ -9041,10 +8039,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "endsAt": { @@ -9057,10 +8052,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false }, "customerAvailability": { @@ -9134,10 +8126,7 @@ "type": "string" } }, - "required": [ - "languageLabel", - "usageInsightsLabel" - ], + "required": ["languageLabel", "usageInsightsLabel"], "additionalProperties": false }, "edit": { @@ -9171,9 +8160,7 @@ "type": "string" } }, - "required": [ - "edit" - ], + "required": ["edit"], "additionalProperties": false } }, @@ -9238,11 +8225,7 @@ "type": "string" } }, - "required": [ - "accepted", - "pending", - "expired" - ], + "required": ["accepted", "pending", "expired"], "additionalProperties": false }, "roles": { @@ -9258,11 +8241,7 @@ "type": "string" } }, - "required": [ - "admin", - "developer", - "member" - ], + "required": ["admin", "developer", "member"], "additionalProperties": false }, "deleteUserWarning": { @@ -9347,9 +8326,7 @@ "type": "string" } }, - "required": [ - "header" - ], + "required": ["header"], "additionalProperties": false }, "toast": { @@ -9471,9 +8448,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "toast": { @@ -9492,12 +8467,7 @@ "type": "string" } }, - "required": [ - "delete", - "edit", - "create", - "countries" - ], + "required": ["delete", "edit", "create", "countries"], "additionalProperties": false }, "shippingOption": { @@ -9531,12 +8501,7 @@ "type": "string" } }, - "required": [ - "outbound", - "outboundHint", - "return", - "returnHint" - ], + "required": ["outbound", "outboundHint", "return", "returnHint"], "additionalProperties": false }, "priceType": { @@ -9552,11 +8517,7 @@ "type": "string" } }, - "required": [ - "label", - "flatRate", - "calculated" - ], + "required": ["label", "flatRate", "calculated"], "additionalProperties": false }, "availability": { @@ -9569,10 +8530,7 @@ "type": "string" } }, - "required": [ - "adminOnly", - "adminOnlyHint" - ], + "required": ["adminOnly", "adminOnlyHint"], "additionalProperties": false }, "taxInclusiveHint": { @@ -9588,10 +8546,7 @@ "type": "string" } }, - "required": [ - "label", - "hint" - ], + "required": ["label", "hint"], "additionalProperties": false } }, @@ -9653,9 +8608,7 @@ "type": "string" } }, - "required": [ - "taxCountriesHint" - ], + "required": ["taxCountriesHint"], "additionalProperties": false }, "settings": { @@ -9709,9 +8662,7 @@ "type": "string" } }, - "required": [ - "sectionTitle" - ], + "required": ["sectionTitle"], "additionalProperties": false }, "taxRate": { @@ -9861,11 +8812,7 @@ "type": "string" } }, - "required": [ - "create", - "update", - "removeChannel" - ], + "required": ["create", "update", "removeChannel"], "additionalProperties": false } }, @@ -9895,11 +8842,7 @@ "type": "string" } }, - "required": [ - "domain", - "subtitle", - "deleteWarning" - ], + "required": ["domain", "subtitle", "deleteWarning"], "additionalProperties": false }, "salesChannels": { @@ -9951,11 +8894,7 @@ "type": "string" } }, - "required": [ - "create", - "update", - "delete" - ], + "required": ["create", "update", "delete"], "additionalProperties": false }, "tooltip": { @@ -9965,9 +8904,7 @@ "type": "string" } }, - "required": [ - "cannotDeleteDefault" - ], + "required": ["cannotDeleteDefault"], "additionalProperties": false }, "products": { @@ -9980,9 +8917,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "add": { @@ -9995,22 +8930,15 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false } }, - "required": [ - "list", - "add" - ], + "required": ["list", "add"], "additionalProperties": false } }, @@ -10045,10 +8973,7 @@ "type": "string" } }, - "required": [ - "publishable", - "secret" - ], + "required": ["publishable", "secret"], "additionalProperties": false }, "subtitle": { @@ -10061,10 +8986,7 @@ "type": "string" } }, - "required": [ - "publishable", - "secret" - ], + "required": ["publishable", "secret"], "additionalProperties": false }, "status": { @@ -10077,10 +8999,7 @@ "type": "string" } }, - "required": [ - "active", - "revoked" - ], + "required": ["active", "revoked"], "additionalProperties": false }, "type": { @@ -10093,10 +9012,7 @@ "type": "string" } }, - "required": [ - "publishable", - "secret" - ], + "required": ["publishable", "secret"], "additionalProperties": false }, "create": { @@ -10156,11 +9072,7 @@ "type": "string" } }, - "required": [ - "header", - "description", - "successToast" - ], + "required": ["header", "description", "successToast"], "additionalProperties": false }, "salesChannels": { @@ -10188,9 +9100,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, @@ -10214,10 +9124,7 @@ "type": "string" } }, - "required": [ - "warning", - "successToast" - ], + "required": ["warning", "successToast"], "additionalProperties": false }, "revoke": { @@ -10230,10 +9137,7 @@ "type": "string" } }, - "required": [ - "warning", - "successToast" - ], + "required": ["warning", "successToast"], "additionalProperties": false }, "addSalesChannels": { @@ -10246,15 +9150,11 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false } }, - "required": [ - "list" - ], + "required": ["list"], "additionalProperties": false }, "removeSalesChannel": { @@ -10302,11 +9202,7 @@ "type": "string" } }, - "required": [ - "revoke", - "copy", - "copySuccessToast" - ], + "required": ["revoke", "copy", "copySuccessToast"], "additionalProperties": false }, "table": { @@ -10319,10 +9215,7 @@ "type": "string" } }, - "required": [ - "lastUsedAtHeader", - "createdAtHeader" - ], + "required": ["lastUsedAtHeader", "createdAtHeader"], "additionalProperties": false }, "fields": { @@ -10399,12 +9292,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "hint", - "successToast" - ], + "required": ["header", "subtitle", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -10420,11 +9308,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "successToast" - ], + "required": ["header", "subtitle", "successToast"], "additionalProperties": false }, "delete": { @@ -10437,10 +9321,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "fields": { @@ -10459,11 +9340,7 @@ "type": "string" } }, - "required": [ - "label", - "placeholder", - "tooltip" - ], + "required": ["label", "placeholder", "tooltip"], "additionalProperties": false }, "label": { @@ -10476,10 +9353,7 @@ "type": "string" } }, - "required": [ - "label", - "placeholder" - ], + "required": ["label", "placeholder"], "additionalProperties": false }, "description": { @@ -10492,18 +9366,11 @@ "type": "string" } }, - "required": [ - "label", - "placeholder" - ], + "required": ["label", "placeholder"], "additionalProperties": false } }, - "required": [ - "value", - "label", - "description" - ], + "required": ["value", "label", "description"], "additionalProperties": false } }, @@ -10532,11 +9399,7 @@ "type": "string" } }, - "required": [ - "forgotPassword", - "title", - "hint" - ], + "required": ["forgotPassword", "title", "hint"], "additionalProperties": false }, "invite": { @@ -10588,9 +9451,7 @@ "type": "string" } }, - "required": [ - "accepted" - ], + "required": ["accepted"], "additionalProperties": false } }, @@ -10735,9 +9596,7 @@ "type": "string" } }, - "required": [ - "noRecordsMessage" - ], + "required": ["noRecordsMessage"], "additionalProperties": false }, "history": { @@ -10834,15 +9693,11 @@ "type": "string" } }, - "required": [ - "waitingToCompensate" - ], + "required": ["waitingToCompensate"], "additionalProperties": false } }, - "required": [ - "state" - ], + "required": ["state"], "additionalProperties": false }, "step": { @@ -10864,18 +9719,11 @@ "type": "string" } }, - "required": [ - "skipped", - "skippedFailure", - "dormant", - "timeout" - ], + "required": ["skipped", "skippedFailure", "dormant", "timeout"], "additionalProperties": false } }, - "required": [ - "state" - ], + "required": ["state"], "additionalProperties": false } }, @@ -10917,11 +9765,7 @@ "type": "string" } }, - "required": [ - "header", - "hint", - "successToast" - ], + "required": ["header", "hint", "successToast"], "additionalProperties": false }, "edit": { @@ -10934,10 +9778,7 @@ "type": "string" } }, - "required": [ - "header", - "successToast" - ], + "required": ["header", "successToast"], "additionalProperties": false }, "delete": { @@ -10950,10 +9791,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "fields": { @@ -10963,20 +9801,11 @@ "type": "string" } }, - "required": [ - "value" - ], + "required": ["value"], "additionalProperties": false } }, - "required": [ - "domain", - "subtitle", - "create", - "edit", - "delete", - "fields" - ], + "required": ["domain", "subtitle", "create", "edit", "delete", "fields"], "additionalProperties": false }, "productTags": { @@ -10998,11 +9827,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "successToast" - ], + "required": ["header", "subtitle", "successToast"], "additionalProperties": false }, "edit": { @@ -11018,11 +9843,7 @@ "type": "string" } }, - "required": [ - "header", - "subtitle", - "successToast" - ], + "required": ["header", "subtitle", "successToast"], "additionalProperties": false }, "delete": { @@ -11035,10 +9856,7 @@ "type": "string" } }, - "required": [ - "confirmation", - "successToast" - ], + "required": ["confirmation", "successToast"], "additionalProperties": false }, "fields": { @@ -11048,19 +9866,11 @@ "type": "string" } }, - "required": [ - "value" - ], + "required": ["value"], "additionalProperties": false } }, - "required": [ - "domain", - "create", - "edit", - "delete", - "fields" - ], + "required": ["domain", "create", "edit", "delete", "fields"], "additionalProperties": false }, "notifications": { @@ -11079,10 +9889,7 @@ "type": "string" } }, - "required": [ - "title", - "description" - ], + "required": ["title", "description"], "additionalProperties": false }, "accessibility": { @@ -11092,17 +9899,11 @@ "type": "string" } }, - "required": [ - "description" - ], + "required": ["description"], "additionalProperties": false } }, - "required": [ - "domain", - "emptyState", - "accessibility" - ], + "required": ["domain", "emptyState", "accessibility"], "additionalProperties": false }, "errors": { @@ -11115,10 +9916,7 @@ "type": "string" } }, - "required": [ - "serverError", - "invalidCredentials" - ], + "required": ["serverError", "invalidCredentials"], "additionalProperties": false }, "statuses": { @@ -11140,13 +9938,7 @@ "type": "string" } }, - "required": [ - "scheduled", - "expired", - "active", - "enabled", - "disabled" - ], + "required": ["scheduled", "expired", "active", "enabled", "disabled"], "additionalProperties": false }, "labels": { @@ -11941,4 +10733,4 @@ "dateTime" ], "additionalProperties": false -} \ No newline at end of file +} From 4d6e39e860ca60843ed64cff237c9a6efda24bf5 Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 7 Jan 2025 12:27:20 +0100 Subject: [PATCH 14/19] add support for bidirectional actions in DataGrid and update Checkbox and RadioGroup --- packages/admin/dashboard/package.json | 2 +- .../components/common/logo-box/avatar-box.tsx | 4 +- .../components/common/logo-box/logo-box.tsx | 2 +- .../components/common/progress-bar/index.ts | 1 + .../common/progress-bar/progress-bar.tsx | 33 ++++++ .../data-grid/components/data-grid-root.tsx | 12 +- .../hooks/use-data-grid-cell-handlers.tsx | 15 ++- .../data-grid/models/data-grid-matrix.ts | 59 +++++++--- .../inputs/chip-input/chip-input.tsx | 2 +- .../src/components/layout/shell/shell.tsx | 57 +++++++++- .../dashboard/src/routes/invite/invite.tsx | 2 +- .../product-stock-form/product-stock-form.tsx | 12 +- .../hooks/use-product-inventory-data.tsx | 71 ------------ .../hooks/use-product-stock-columns.tsx | 11 +- .../routes/products/product-stock/index.ts | 1 + .../routes/products/product-stock/loader.ts | 55 +++++++++ .../products/product-stock/product-stock.tsx | 107 ++++++++++++------ .../workflow-execution-timeline-section.tsx | 4 +- .../ui/src/components/checkbox/checkbox.tsx | 11 +- .../components/radio-group/radio-group.tsx | 20 +++- .../ui/src/components/switch/switch.tsx | 4 +- yarn.lock | 58 ++++++++++ 22 files changed, 390 insertions(+), 153 deletions(-) create mode 100644 packages/admin/dashboard/src/components/common/progress-bar/index.ts create mode 100644 packages/admin/dashboard/src/components/common/progress-bar/progress-bar.tsx delete mode 100644 packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-inventory-data.tsx create mode 100644 packages/admin/dashboard/src/routes/products/product-stock/loader.ts diff --git a/packages/admin/dashboard/package.json b/packages/admin/dashboard/package.json index c7431e4760064..1651ca832c5b3 100644 --- a/packages/admin/dashboard/package.json +++ b/packages/admin/dashboard/package.json @@ -56,12 +56,12 @@ "@uiw/react-json-view": "^2.0.0-alpha.17", "cmdk": "^0.2.0", "date-fns": "^3.6.0", - "framer-motion": "^11.0.3", "i18next": "23.7.11", "i18next-browser-languagedetector": "7.2.0", "i18next-http-backend": "2.4.2", "lodash": "^4.17.21", "match-sorter": "^6.3.4", + "motion": "^11.15.0", "qs": "^6.12.0", "react": "^18.2.0", "react-country-flag": "^3.1.0", diff --git a/packages/admin/dashboard/src/components/common/logo-box/avatar-box.tsx b/packages/admin/dashboard/src/components/common/logo-box/avatar-box.tsx index ab4c7fff93275..a9c4cfb62f652 100644 --- a/packages/admin/dashboard/src/components/common/logo-box/avatar-box.tsx +++ b/packages/admin/dashboard/src/components/common/logo-box/avatar-box.tsx @@ -1,4 +1,4 @@ -import { motion } from "framer-motion" +import { motion } from "motion/react" import { IconAvatar } from "../icon-avatar" @@ -6,7 +6,7 @@ export default function AvatarBox({ checked }: { checked?: boolean }) { return ( {checked && ( { + return ( + + ) +} diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx index cd2195441a4eb..c9d6d9cc209a7 100644 --- a/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx @@ -58,6 +58,7 @@ export interface DataGridRootProps< getSubRows?: (row: TData) => TData[] | undefined onEditingChange?: (isEditing: boolean) => void disableInteractions?: boolean + multiColumnSelection?: boolean } const ROW_HEIGHT = 40 @@ -103,6 +104,7 @@ export const DataGridRoot = < getSubRows, onEditingChange, disableInteractions, + multiColumnSelection = false, }: DataGridRootProps) => { const containerRef = useRef(null) @@ -230,8 +232,13 @@ export const DataGridRoot = < } const matrix = useMemo( - () => new DataGridMatrix(flatRows, columns), - [flatRows, columns] + () => + new DataGridMatrix( + flatRows, + columns, + multiColumnSelection + ), + [flatRows, columns, multiColumnSelection] ) const queryTool = useDataGridQueryTool(containerRef) @@ -390,6 +397,7 @@ export const DataGridRoot = < setDragEnd, setValue, execute, + multiColumnSelection, }) const { getCellErrorMetadata, getCellMetadata } = useDataGridCellMetadata< diff --git a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell-handlers.tsx b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell-handlers.tsx index 3d9fd48e16c1a..1aee1dc2e2613 100644 --- a/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell-handlers.tsx +++ b/packages/admin/dashboard/src/components/data-grid/hooks/use-data-grid-cell-handlers.tsx @@ -17,6 +17,7 @@ type UseDataGridCellHandlersOptions = { setDragEnd: (coords: DataGridCoordinates | null) => void setValue: UseFormSetValue execute: (command: DataGridUpdateCommand) => void + multiColumnSelection?: boolean } export const useDataGridCellHandlers = < @@ -36,6 +37,7 @@ export const useDataGridCellHandlers = < setDragEnd, setValue, execute, + multiColumnSelection, }: UseDataGridCellHandlersOptions) => { const getWrapperFocusHandler = useCallback( (coords: DataGridCoordinates) => { @@ -74,9 +76,9 @@ export const useDataGridCellHandlers = < return (_e: MouseEvent) => { /** * If the column is not the same as the anchor col, - * we don't want to select the cell. + * we don't want to select the cell. Unless multiColumnSelection is true. */ - if (anchor?.col !== coords.col) { + if (anchor?.col !== coords.col && !multiColumnSelection) { return } @@ -87,7 +89,14 @@ export const useDataGridCellHandlers = < } } }, - [anchor?.col, isDragging, isSelecting, setDragEnd, setRangeEnd] + [ + anchor?.col, + isDragging, + isSelecting, + setDragEnd, + setRangeEnd, + multiColumnSelection, + ] ) const getInputChangeHandler = useCallback( diff --git a/packages/admin/dashboard/src/components/data-grid/models/data-grid-matrix.ts b/packages/admin/dashboard/src/components/data-grid/models/data-grid-matrix.ts index 24e0d4d276fe8..bfaf31bda5387 100644 --- a/packages/admin/dashboard/src/components/data-grid/models/data-grid-matrix.ts +++ b/packages/admin/dashboard/src/components/data-grid/models/data-grid-matrix.ts @@ -1,13 +1,25 @@ import { ColumnDef, Row } from "@tanstack/react-table" import { FieldValues } from "react-hook-form" -import { DataGridColumnType, DataGridCoordinates, Grid, GridCell, InternalColumnMeta } from "../types" +import { + DataGridColumnType, + DataGridCoordinates, + Grid, + GridCell, + InternalColumnMeta, +} from "../types" export class DataGridMatrix { + private multiColumnSelection: boolean private cells: Grid public rowAccessors: (string | null)[] = [] public columnAccessors: (string | null)[] = [] - constructor(data: Row[], columns: ColumnDef[]) { + constructor( + data: Row[], + columns: ColumnDef[], + multiColumnSelection: boolean = false + ) { + this.multiColumnSelection = multiColumnSelection this.cells = this._populateCells(data, columns) this.rowAccessors = this._computeRowAccessors() @@ -64,17 +76,26 @@ export class DataGridMatrix { return keys } - if (start.col !== end.col) { - throw new Error("Selection must be in the same column") + if (!this.multiColumnSelection && start.col !== end.col) { + throw new Error( + "Selection must be in the same column when multiColumnSelection is disabled" + ) } const startRow = Math.min(start.row, end.row) const endRow = Math.max(start.row, end.row) - const col = start.col + const startCol = this.multiColumnSelection + ? Math.min(start.col, end.col) + : start.col + const endCol = this.multiColumnSelection + ? Math.max(start.col, end.col) + : start.col for (let row = startRow; row <= endRow; row++) { - if (this._isValidPosition(row, col) && this.cells[row][col] !== null) { - keys.push(this.cells[row][col]?.field as string) + for (let col = startCol; col <= endCol; col++) { + if (this._isValidPosition(row, col) && this.cells[row][col] !== null) { + keys.push(this.cells[row][col]?.field as string) + } } } @@ -106,15 +127,27 @@ export class DataGridMatrix { return false } - if (start.col !== end.col) { - throw new Error("Selection must be in the same column") + if (!this.multiColumnSelection && start.col !== end.col) { + throw new Error( + "Selection must be in the same column when multiColumnSelection is disabled" + ) } const startRow = Math.min(start.row, end.row) const endRow = Math.max(start.row, end.row) - const col = start.col - - return cell.col === col && cell.row >= startRow && cell.row <= endRow + const startCol = this.multiColumnSelection + ? Math.min(start.col, end.col) + : start.col + const endCol = this.multiColumnSelection + ? Math.max(start.col, end.col) + : start.col + + return ( + cell.row >= startRow && + cell.row <= endRow && + cell.col >= startCol && + cell.col <= endCol + ) } toggleColumn(col: number, enabled: boolean) { @@ -385,4 +418,4 @@ export class DataGridMatrix { return cells } -} \ No newline at end of file +} diff --git a/packages/admin/dashboard/src/components/inputs/chip-input/chip-input.tsx b/packages/admin/dashboard/src/components/inputs/chip-input/chip-input.tsx index cd3e21a278faf..ce942d4fe6340 100644 --- a/packages/admin/dashboard/src/components/inputs/chip-input/chip-input.tsx +++ b/packages/admin/dashboard/src/components/inputs/chip-input/chip-input.tsx @@ -1,6 +1,6 @@ import { XMarkMini } from "@medusajs/icons" import { Badge, clx } from "@medusajs/ui" -import { AnimatePresence, motion } from "framer-motion" +import { AnimatePresence, motion } from "motion/react" import { FocusEvent, KeyboardEvent, diff --git a/packages/admin/dashboard/src/components/layout/shell/shell.tsx b/packages/admin/dashboard/src/components/layout/shell/shell.tsx index 26c7603cb570c..df53453061051 100644 --- a/packages/admin/dashboard/src/components/layout/shell/shell.tsx +++ b/packages/admin/dashboard/src/components/layout/shell/shell.tsx @@ -2,28 +2,47 @@ import * as Dialog from "@radix-ui/react-dialog" import { SidebarLeft, TriangleRightMini, XMark } from "@medusajs/icons" import { IconButton, clx } from "@medusajs/ui" -import { PropsWithChildren, ReactNode } from "react" +import { AnimatePresence } from "motion/react" +import { PropsWithChildren, ReactNode, useEffect, useState } from "react" import { useTranslation } from "react-i18next" -import { Link, Outlet, UIMatch, useMatches } from "react-router-dom" +import { + Link, + Outlet, + UIMatch, + useMatches, + useNavigation, +} from "react-router-dom" import { KeybindProvider } from "../../../providers/keybind-provider" import { useGlobalShortcuts } from "../../../providers/keybind-provider/hooks" import { useSidebar } from "../../../providers/sidebar-provider" +import { ProgressBar } from "../../common/progress-bar" import { Notifications } from "../notifications" export const Shell = ({ children }: PropsWithChildren) => { const globalShortcuts = useGlobalShortcuts() + const navigation = useNavigation() + + const loading = navigation.state === "loading" return ( -
+
+
{children} {children}
-
+
@@ -34,6 +53,36 @@ export const Shell = ({ children }: PropsWithChildren) => { ) } +const NavigationBar = ({ loading }: { loading: boolean }) => { + const [showBar, setShowBar] = useState(false) + + /** + * If the loading state is true, we want to show the bar after a short delay. + * The delay is used to prevent the bar from flashing on quick navigations. + */ + useEffect(() => { + let timeout: ReturnType + + if (loading) { + timeout = setTimeout(() => { + setShowBar(true) + }, 200) + } else { + setShowBar(false) + } + + return () => { + clearTimeout(timeout) + } + }, [loading]) + + return ( +
+ {showBar ? : null} +
+ ) +} + const Gutter = ({ children }: PropsWithChildren) => { return (
diff --git a/packages/admin/dashboard/src/routes/invite/invite.tsx b/packages/admin/dashboard/src/routes/invite/invite.tsx index 5535a0ae568a6..69152d6c7a462 100644 --- a/packages/admin/dashboard/src/routes/invite/invite.tsx +++ b/packages/admin/dashboard/src/routes/invite/invite.tsx @@ -1,7 +1,7 @@ import { zodResolver } from "@hookform/resolvers/zod" import { Alert, Button, Heading, Hint, Input, Text, toast } from "@medusajs/ui" -import { AnimatePresence, motion } from "framer-motion" import i18n from "i18next" +import { AnimatePresence, motion } from "motion/react" import { useState } from "react" import { useForm } from "react-hook-form" import { useTranslation } from "react-i18next" diff --git a/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx index f944479679231..655d3a65c8681 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx @@ -1,7 +1,7 @@ import { zodResolver } from "@hookform/resolvers/zod" import { HttpTypes } from "@medusajs/types" import { Button, toast, usePrompt } from "@medusajs/ui" -import { useMemo, useRef, useState } from "react" +import { useEffect, useMemo, useRef, useState } from "react" import { DefaultValues, useForm } from "react-hook-form" import { useTranslation } from "react-i18next" import { DataGrid } from "../../../../../components/data-grid" @@ -28,17 +28,22 @@ import { type ProductStockFormProps = { variants: HttpTypes.AdminProductVariant[] locations: HttpTypes.AdminStockLocation[] + onLoaded: () => void } export const ProductStockForm = ({ variants, locations, + onLoaded, }: ProductStockFormProps) => { const { t } = useTranslation() - const { setCloseOnEscape } = useRouteModal() - const { handleSuccess } = useRouteModal() + const { handleSuccess, setCloseOnEscape } = useRouteModal() const prompt = usePrompt() + useEffect(() => { + onLoaded() + }, [onLoaded]) + const [isPromptOpen, setIsPromptOpen] = useState(false) const form = useForm({ @@ -148,6 +153,7 @@ export const ProductStockForm = ({ getSubRows={getSubRows} onEditingChange={(editing) => setCloseOnEscape(!editing)} disableInteractions={isPending || isPromptOpen} + multiColumnSelection={true} /> diff --git a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-inventory-data.tsx b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-inventory-data.tsx deleted file mode 100644 index 8964c36271a01..0000000000000 --- a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-inventory-data.tsx +++ /dev/null @@ -1,71 +0,0 @@ -import { HttpTypes } from "@medusajs/types" -import { useEffect, useState } from "react" -import { useStockLocations } from "../../../../hooks/api" -import { sdk } from "../../../../lib/client" - -export const useProductInventoryData = ( - id: string, - productVariantIds?: string[] -) => { - const [variants, setVariants] = useState([]) - const [isLoadingVariants, setIsLoadingVariants] = useState(true) - - const locationData = useStockLocations({ - limit: 9999, - fields: "id,name", - }) - - /** - * Loads variants in chunks of 20. - * - * This is to avoid loading too many variants at once, which - * can cause OOM errors. - */ - useEffect(() => { - const fetchAllVariants = async () => { - setIsLoadingVariants(true) - try { - const CHUNK_SIZE = 20 - let offset = 0 - let allVariants: HttpTypes.AdminProductVariant[] = [] - let totalCount = 0 - - do { - const { variants: chunk, count } = - await sdk.admin.product.listVariants(id, { - id: productVariantIds, - offset, - limit: CHUNK_SIZE, - fields: - "id,title,sku,inventory_items,inventory_items.*,inventory_items.inventory,inventory_items.inventory.id,inventory_items.inventory.title,inventory_items.inventory.sku,*inventory_items.inventory.location_levels,product.thumbnail", - }) - - allVariants = [...allVariants, ...chunk] - totalCount = count - offset += CHUNK_SIZE - } while (allVariants.length < totalCount) - - setVariants(allVariants) - } finally { - setIsLoadingVariants(false) - } - } - - fetchAllVariants() - }, [id, productVariantIds]) - - if (locationData.isError) { - throw locationData.error - } - - const isLoaded = - !isLoadingVariants && - !locationData.isPending && - !!locationData.stock_locations - - return { - variants, - locations: locationData.stock_locations || [], - isLoaded, - } -} diff --git a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx index 61cff72d777e6..ee77ec8fe4b1c 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx @@ -82,7 +82,7 @@ export const useProductStockColumns = (
{item.inventory.title || "-"} @@ -133,7 +133,9 @@ export const useProductStockColumns = ( if (isDisabled) { return ( - {item.inventory.sku || "-"} + + {item.inventory.sku || "-"} + ) } @@ -188,14 +190,15 @@ export const useProductStockColumns = ( } return ( -
+
- + {quantity}
diff --git a/packages/admin/dashboard/src/routes/products/product-stock/index.ts b/packages/admin/dashboard/src/routes/products/product-stock/index.ts index cdefbb9aaeebb..ddae1ead0def1 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/index.ts +++ b/packages/admin/dashboard/src/routes/products/product-stock/index.ts @@ -1 +1,2 @@ +export { productStockLoader as loader } from "./loader" export { ProductStock as Component } from "./product-stock" diff --git a/packages/admin/dashboard/src/routes/products/product-stock/loader.ts b/packages/admin/dashboard/src/routes/products/product-stock/loader.ts new file mode 100644 index 0000000000000..d64c9e349974b --- /dev/null +++ b/packages/admin/dashboard/src/routes/products/product-stock/loader.ts @@ -0,0 +1,55 @@ +import { HttpTypes } from "@medusajs/types" +import { defer, LoaderFunctionArgs } from "react-router-dom" +import { sdk } from "../../../lib/client" +import { PRODUCT_VARIANT_IDS_KEY } from "../common/constants" + +async function getProductStockData(id: string, productVariantIds?: string[]) { + const CHUNK_SIZE = 20 + let offset = 0 + let totalCount = 0 + + let allVariants: HttpTypes.AdminProductVariant[] = [] + + do { + const { variants: chunk, count } = await sdk.admin.product.listVariants( + id, + { + id: productVariantIds, + offset, + limit: CHUNK_SIZE, + fields: + "id,title,sku,inventory_items,inventory_items.*,inventory_items.inventory,inventory_items.inventory.id,inventory_items.inventory.title,inventory_items.inventory.sku,*inventory_items.inventory.location_levels,product.thumbnail", + } + ) + + allVariants = [...allVariants, ...chunk] + totalCount = count + offset += CHUNK_SIZE + } while (allVariants.length < totalCount) + + const { stock_locations } = await sdk.admin.stockLocation.list({ + limit: 9999, + fields: "id,name", + }) + + return { + variants: allVariants, + locations: stock_locations, + } +} + +export const productStockLoader = async ({ + params, + request, +}: LoaderFunctionArgs) => { + const id = params.id! + const searchParams = new URLSearchParams(request.url) + const productVariantIds = + searchParams.get(PRODUCT_VARIANT_IDS_KEY)?.split(",") || undefined + + const dataPromise = getProductStockData(id, productVariantIds) + + return defer({ + data: dataPromise, + }) +} diff --git a/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx b/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx index c0e6a5b9f70cf..2f6bb3641175b 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx @@ -1,56 +1,91 @@ -import { Spinner } from "@medusajs/icons" -import { Text } from "@medusajs/ui" -import { ColumnDef } from "@tanstack/react-table" +import { HttpTypes } from "@medusajs/types" +import { AnimatePresence } from "motion/react" +import { Suspense, useEffect, useRef, useState } from "react" import { useTranslation } from "react-i18next" -import { useParams, useSearchParams } from "react-router-dom" +import { Await, useLoaderData } from "react-router-dom" + +import { ColumnDef } from "@tanstack/react-table" +import { ProgressBar } from "../../../components/common/progress-bar" import { Skeleton } from "../../../components/common/skeleton" import { DataGridSkeleton } from "../../../components/data-grid/components" import { RouteFocusModal } from "../../../components/modals" -import { PRODUCT_VARIANT_IDS_KEY } from "../common/constants" import { ProductStockForm } from "./components/product-stock-form" -import { useProductInventoryData } from "./hooks/use-product-inventory-data" +import { productStockLoader } from "./loader" export const ProductStock = () => { const { t } = useTranslation() - const { id } = useParams<{ id: string }>() - const [searchParams] = useSearchParams() + const data = useLoaderData() as Awaited> - const productVariantIds = - searchParams.get(PRODUCT_VARIANT_IDS_KEY)?.split(",") || undefined + /** + * We render a local ProgressBar, as we cannot rely on the global NavigationBar. + * This is because we are deferring the data, meaning that the navigation is + * instant, and the data is loaded in parallel with the navigation. This will + * result in the data loading after the navigation has completed most of the + * time for this route, as we chunk the data into multiple queries. + * + * Here we instead render a local ProgressBar, which is animated, and exit + * the animation when the data is loaded, and the form is rendered. + */ + const [isLoading, setIsLoading] = useState(false) + const timeoutRef = useRef>() - const { variants, locations, isLoaded } = useProductInventoryData( - id!, - productVariantIds - ) + useEffect(() => { + timeoutRef.current = setTimeout(() => { + setIsLoading(true) + }, 200) + + return () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current) + } + } + }, []) + + const onLoaded = () => { + if (timeoutRef.current) { + clearTimeout(timeoutRef.current) + } + setIsLoading(false) + } return ( - - - {t("products.stock.heading")} - - - {t("products.stock.description")} - - {isLoaded ? ( - - ) : ( - - )} - +
+
+ + {isLoading ? : null} + +
+ + + {t("products.stock.heading")} + + + {t("products.stock.description")} + + }> + + {(data: { + variants: HttpTypes.AdminProductVariant[] + locations: HttpTypes.AdminStockLocation[] + }) => { + return ( + + ) + }} + + + +
) } -const ProductStockSkeleton = () => { - const { t } = useTranslation() - +const ProductStockFallback = () => { return (
-
- - - {t("products.stock.loading")} - -
diff --git a/packages/admin/dashboard/src/routes/workflow-executions/workflow-execution-detail/components/workflow-execution-timeline-section/workflow-execution-timeline-section.tsx b/packages/admin/dashboard/src/routes/workflow-executions/workflow-execution-detail/components/workflow-execution-timeline-section/workflow-execution-timeline-section.tsx index 8fab0fc8591d3..e0c3fe5cf6816 100644 --- a/packages/admin/dashboard/src/routes/workflow-executions/workflow-execution-detail/components/workflow-execution-timeline-section/workflow-execution-timeline-section.tsx +++ b/packages/admin/dashboard/src/routes/workflow-executions/workflow-execution-detail/components/workflow-execution-timeline-section/workflow-execution-timeline-section.tsx @@ -5,11 +5,12 @@ import { useAnimationControls, useDragControls, useMotionValue, -} from "framer-motion" +} from "motion/react" import { useEffect, useRef, useState } from "react" import { useTranslation } from "react-i18next" import { Link } from "react-router-dom" +import { HttpTypes } from "@medusajs/types" import { STEP_ERROR_STATES, STEP_INACTIVE_STATES, @@ -17,7 +18,6 @@ import { STEP_OK_STATES, STEP_SKIPPED_STATES, } from "../../../constants" -import { HttpTypes } from "@medusajs/types" type WorkflowExecutionTimelineSectionProps = { execution: HttpTypes.AdminWorkflowExecutionResponse["workflow_execution"] diff --git a/packages/design-system/ui/src/components/checkbox/checkbox.tsx b/packages/design-system/ui/src/components/checkbox/checkbox.tsx index a26d2e9626f90..ebccfc9f887d9 100644 --- a/packages/design-system/ui/src/components/checkbox/checkbox.tsx +++ b/packages/design-system/ui/src/components/checkbox/checkbox.tsx @@ -23,7 +23,16 @@ const Checkbox = React.forwardRef< className )} > -
+
{checked === "indeterminate" ? : } diff --git a/packages/design-system/ui/src/components/radio-group/radio-group.tsx b/packages/design-system/ui/src/components/radio-group/radio-group.tsx index 1133e9b11f133..e996cc712dafc 100644 --- a/packages/design-system/ui/src/components/radio-group/radio-group.tsx +++ b/packages/design-system/ui/src/components/radio-group/radio-group.tsx @@ -36,7 +36,7 @@ const Indicator = React.forwardRef< >
@@ -60,10 +60,10 @@ const Item = React.forwardRef<
@@ -95,7 +95,10 @@ const ChoiceBox = React.forwardRef<
-
+
@@ -117,7 +125,7 @@ const ChoiceBox = React.forwardRef< {label} {description} diff --git a/packages/design-system/ui/src/components/switch/switch.tsx b/packages/design-system/ui/src/components/switch/switch.tsx index 2a682023719b7..539c5d4e3af06 100644 --- a/packages/design-system/ui/src/components/switch/switch.tsx +++ b/packages/design-system/ui/src/components/switch/switch.tsx @@ -7,7 +7,7 @@ import * as React from "react" import { clx } from "@/utils/clx" const switchVariants = cva({ - base: "bg-ui-bg-switch-off hover:bg-ui-bg-switch-off-hover data-[state=unchecked]:hover:after:bg-switch-off-hover-gradient before:shadow-details-switch-background focus-visible:shadow-details-switch-background-focus data-[state=checked]:bg-ui-bg-interactive disabled:!bg-ui-bg-disabled group relative inline-flex items-center rounded-full outline-none transition-all before:absolute before:inset-0 before:rounded-full before:content-[''] after:absolute after:inset-0 after:rounded-full after:content-[''] disabled:cursor-not-allowed", + base: "bg-ui-bg-switch-off hover:bg-ui-bg-switch-off-hover data-[state=unchecked]:hover:after:bg-switch-off-hover-gradient before:shadow-details-switch-background focus-visible:shadow-details-switch-background-focus data-[state=checked]:bg-ui-bg-interactive disabled:opacity-50 group relative inline-flex items-center rounded-full outline-none transition-all before:absolute before:inset-0 before:rounded-full before:content-[''] after:absolute after:inset-0 after:rounded-full after:content-[''] disabled:cursor-not-allowed", variants: { size: { small: "h-[16px] w-[28px]", @@ -20,7 +20,7 @@ const switchVariants = cva({ }) const thumbVariants = cva({ - base: "bg-ui-fg-on-color shadow-details-switch-handle group-disabled:bg-ui-fg-disabled pointer-events-none h-[14px] w-[14px] rounded-full transition-all group-disabled:shadow-none", + base: "bg-ui-fg-on-color shadow-details-switch-handle pointer-events-none h-[14px] w-[14px] rounded-full transition-all", variants: { size: { small: diff --git a/yarn.lock b/yarn.lock index 876e0ace3602c..7d0425ba52014 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5623,6 +5623,7 @@ __metadata: i18next-http-backend: 2.4.2 lodash: ^4.17.21 match-sorter: ^6.3.4 + motion: ^11.15.0 postcss: ^8.4.33 prettier: ^3.1.1 qs: ^6.12.0 @@ -20732,6 +20733,28 @@ __metadata: languageName: node linkType: hard +"framer-motion@npm:^11.15.0": + version: 11.15.0 + resolution: "framer-motion@npm:11.15.0" + dependencies: + motion-dom: ^11.14.3 + motion-utils: ^11.14.3 + tslib: ^2.4.0 + peerDependencies: + "@emotion/is-prop-valid": "*" + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@emotion/is-prop-valid": + optional: true + react: + optional: true + react-dom: + optional: true + checksum: 59f1c1eea09a5cbda346624a7d700bdb1ccff8a8528ed145009db974283064c3a4e55ca9eaaf4950494f254f6233c37634735b9bd8463b25ffeef624030894d6 + languageName: node + linkType: hard + "fresh@npm:0.5.2": version: 0.5.2 resolution: "fresh@npm:0.5.2" @@ -25290,6 +25313,41 @@ __metadata: languageName: node linkType: hard +"motion-dom@npm:^11.14.3": + version: 11.14.3 + resolution: "motion-dom@npm:11.14.3" + checksum: 14989aba2981dcf618dc77d202ac35325366e645fd9e57c6942d88d0696263bbe7d0680da2e5f84e93339a67255bdbfebb8a4994a46584a661dd9a1e136fa7a1 + languageName: node + linkType: hard + +"motion-utils@npm:^11.14.3": + version: 11.14.3 + resolution: "motion-utils@npm:11.14.3" + checksum: 7459bcb27311b72b416b2618cbfd56bad7d0fbec27736529e3f45a561fa78c43bf82e05338d9d9b765649b57d1c693821e83b30c6ba449d6f7f66c5245f072fb + languageName: node + linkType: hard + +"motion@npm:^11.15.0": + version: 11.15.0 + resolution: "motion@npm:11.15.0" + dependencies: + framer-motion: ^11.15.0 + tslib: ^2.4.0 + peerDependencies: + "@emotion/is-prop-valid": "*" + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + "@emotion/is-prop-valid": + optional: true + react: + optional: true + react-dom: + optional: true + checksum: fe10db69ad3ca7cb3fd2896d4cd6a79ca8080de16f5fdfcf82a6decd474423f4207b7a924dc7bfb405cffb36d7de0e13780f1a623287be354ced65c78a612c99 + languageName: node + linkType: hard + "mri@npm:^1.1.0": version: 1.2.0 resolution: "mri@npm:1.2.0" From 1cf5a712c017d8d939994d8ac5a1cb26892c146c Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 7 Jan 2025 12:28:34 +0100 Subject: [PATCH 15/19] update lock --- yarn.lock | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7d0425ba52014..24622e13a9821 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5617,7 +5617,6 @@ __metadata: autoprefixer: ^10.4.17 cmdk: ^0.2.0 date-fns: ^3.6.0 - framer-motion: ^11.0.3 i18next: 23.7.11 i18next-browser-languagedetector: 7.2.0 i18next-http-backend: 2.4.2 @@ -20713,26 +20712,6 @@ __metadata: languageName: node linkType: hard -"framer-motion@npm:^11.0.3": - version: 11.1.8 - resolution: "framer-motion@npm:11.1.8" - dependencies: - tslib: ^2.4.0 - peerDependencies: - "@emotion/is-prop-valid": "*" - react: ^18.0.0 - react-dom: ^18.0.0 - peerDependenciesMeta: - "@emotion/is-prop-valid": - optional: true - react: - optional: true - react-dom: - optional: true - checksum: ff7073ca011936fcf0e4af54ff93824609cf03b556def5a69d21f44674c44ec0429a450b419bb4ae89d5b7af9d7b0e88ed57d3eff1ff668ed2a52b42a60375dd - languageName: node - linkType: hard - "framer-motion@npm:^11.15.0": version: 11.15.0 resolution: "framer-motion@npm:11.15.0" From f46a3db2a8a7b6c2ceb59ddd003cf5fbbf0a37db Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Tue, 7 Jan 2025 12:38:54 +0100 Subject: [PATCH 16/19] lint --- packages/design-system/ui/src/components/checkbox/checkbox.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/design-system/ui/src/components/checkbox/checkbox.tsx b/packages/design-system/ui/src/components/checkbox/checkbox.tsx index ebccfc9f887d9..2136906986112 100644 --- a/packages/design-system/ui/src/components/checkbox/checkbox.tsx +++ b/packages/design-system/ui/src/components/checkbox/checkbox.tsx @@ -26,7 +26,7 @@ const Checkbox = React.forwardRef<
Date: Wed, 8 Jan 2025 11:16:54 +0100 Subject: [PATCH 17/19] fix 404 --- .../product-variant-section/product-variant-section.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx index 99b0671478c4c..4d0a89a0b08ee 100644 --- a/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx +++ b/packages/admin/dashboard/src/routes/products/product-detail/components/product-variant-section/product-variant-section.tsx @@ -118,9 +118,9 @@ export const ProductVariantSection = ({ { action: async (selection) => { navigate( - `inventory?${PRODUCT_VARIANT_IDS_KEY}=${Object.keys( - selection - ).join(",")}` + `stock?${PRODUCT_VARIANT_IDS_KEY}=${Object.keys(selection).join( + "," + )}` ) }, label: t("inventory.stock.action"), From 7059698ddab329aaed711ecef00cbe062d5dede8 Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Fri, 10 Jan 2025 09:23:52 +0100 Subject: [PATCH 18/19] address feedback --- .../product-stock-form/product-stock-form.tsx | 70 +++++++++---------- .../hooks/use-product-stock-columns.tsx | 16 ++--- .../products/product-stock/product-stock.tsx | 7 +- .../routes/products/product-stock/types.ts | 9 --- .../routes/products/product-stock/utils.ts | 19 +++-- .../types/src/http/product/admin/entitites.ts | 28 ++++++++ 6 files changed, 87 insertions(+), 62 deletions(-) delete mode 100644 packages/admin/dashboard/src/routes/products/product-stock/types.ts diff --git a/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx index 655d3a65c8681..f3f83c3c90dab 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/components/product-stock-form/product-stock-form.tsx @@ -4,6 +4,7 @@ import { Button, toast, usePrompt } from "@medusajs/ui" import { useEffect, useMemo, useRef, useState } from "react" import { DefaultValues, useForm } from "react-hook-form" import { useTranslation } from "react-i18next" + import { DataGrid } from "../../../../../components/data-grid" import { RouteFocusModal, @@ -19,7 +20,6 @@ import { ProductStockSchema, ProductStockVariantSchema, } from "../../schema" -import { ProductVariantInventoryItemLink } from "../../types" import { getDisabledInventoryRows, isProductVariantWithInventoryPivot, @@ -47,16 +47,13 @@ export const ProductStockForm = ({ const [isPromptOpen, setIsPromptOpen] = useState(false) const form = useForm({ - defaultValues: getDefaultValue(variants as any, locations), + defaultValues: getDefaultValue(variants, locations), resolver: zodResolver(ProductStockSchema), }) - const initialValues = useRef(getDefaultValue(variants as any, locations)) + const initialValues = useRef(getDefaultValue(variants, locations)) - const disabled = useMemo( - () => getDisabledInventoryRows(variants as any), - [variants] - ) + const disabled = useMemo(() => getDisabledInventoryRows(variants), [variants]) const columns = useProductStockColumns(locations, disabled) const { mutateAsync, isPending } = useBatchInventoryItemsLocationLevels() @@ -174,46 +171,49 @@ export const ProductStockForm = ({ } function getSubRows( - row: HttpTypes.AdminProductVariant | ProductVariantInventoryItemLink -): ProductVariantInventoryItemLink[] | undefined { + row: + | HttpTypes.AdminProductVariant + | HttpTypes.AdminProductVariantInventoryItemLink +): HttpTypes.AdminProductVariantInventoryItemLink[] | undefined { if (isProductVariantWithInventoryPivot(row)) { return row.inventory_items } } function getDefaultValue( - variants: (HttpTypes.AdminProductVariant & { - inventory_items: ProductVariantInventoryItemLink[] - })[], + variants: HttpTypes.AdminProductVariant[], locations: HttpTypes.AdminStockLocation[] ): DefaultValues { return { variants: variants.reduce((variantAcc, variant) => { - const inventoryItems = variant.inventory_items.reduce((itemAcc, item) => { - const locationsMap = locations.reduce((locationAcc, location) => { - const level = item.inventory.location_levels?.find( - (level) => level.location_id === location.id - ) - - locationAcc[location.id] = { - id: level?.id, - quantity: - level?.stocked_quantity !== undefined - ? level?.stocked_quantity - : "", - checked: !!level, - disabledToggle: - (level?.incoming_quantity || 0) > 0 || - (level?.reserved_quantity || 0) > 0, - } - return locationAcc - }, {} as ProductStockLocationSchema) + const inventoryItems = variant.inventory_items?.reduce( + (itemAcc, item) => { + const locationsMap = locations.reduce((locationAcc, location) => { + const level = item.inventory?.location_levels?.find( + (level) => level.location_id === location.id + ) + + locationAcc[location.id] = { + id: level?.id, + quantity: + level?.stocked_quantity !== undefined + ? level?.stocked_quantity + : "", + checked: !!level, + disabledToggle: + (level?.incoming_quantity || 0) > 0 || + (level?.reserved_quantity || 0) > 0, + } + return locationAcc + }, {} as ProductStockLocationSchema) - itemAcc[item.inventory_item_id] = { locations: locationsMap } - return itemAcc - }, {} as Record) + itemAcc[item.inventory_item_id] = { locations: locationsMap } + return itemAcc + }, + {} as Record + ) - variantAcc[variant.id] = { inventory_items: inventoryItems } + variantAcc[variant.id] = { inventory_items: inventoryItems || {} } return variantAcc }, {} as Record), } diff --git a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx index ee77ec8fe4b1c..31515dbe2d8a3 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/hooks/use-product-stock-columns.tsx @@ -10,11 +10,11 @@ import { DataGridReadOnlyCell } from "../../../../components/data-grid/component import { DataGridDuplicateCell } from "../../../../components/data-grid/components/data-grid-duplicate-cell" import { DataGridTogglableNumberCell } from "../../../../components/data-grid/components/data-grid-toggleable-number-cell" import { ProductStockSchema } from "../schema" -import { ProductVariantInventoryItemLink } from "../types" import { isProductVariant } from "../utils" const helper = createDataGridHelper< - HttpTypes.AdminProductVariant | ProductVariantInventoryItemLink, + | HttpTypes.AdminProductVariant + | HttpTypes.AdminProductVariantInventoryItemLink, ProductStockSchema >() @@ -35,7 +35,7 @@ export const useProductStockColumns = ( ) => { const { t } = useTranslation() const getIsDisabled = useCallback( - (item: ProductVariantInventoryItemLink): DisabledResult => { + (item: HttpTypes.AdminProductVariantInventoryItemLink): DisabledResult => { const disabledItem = disabled[item.inventory_item_id] const isDisabled = !!disabledItem && disabledItem.id !== item.variant_id @@ -81,10 +81,10 @@ export const useProductStockColumns = (
- {item.inventory.title || "-"} + {item.inventory?.title || "-"} - {item.inventory.title || "-"} + {item.inventory?.title || "-"} ) }, @@ -134,7 +134,7 @@ export const useProductStockColumns = ( return ( - {item.inventory.sku || "-"} + {item.inventory?.sku || "-"} ) @@ -142,7 +142,7 @@ export const useProductStockColumns = ( return ( - {item.inventory.sku || "-"} + {item.inventory?.sku || "-"} ) }, diff --git a/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx b/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx index 2f6bb3641175b..f3b3f1ac4add1 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx +++ b/packages/admin/dashboard/src/routes/products/product-stock/product-stock.tsx @@ -19,9 +19,10 @@ export const ProductStock = () => { /** * We render a local ProgressBar, as we cannot rely on the global NavigationBar. * This is because we are deferring the data, meaning that the navigation is - * instant, and the data is loaded in parallel with the navigation. This will - * result in the data loading after the navigation has completed most of the - * time for this route, as we chunk the data into multiple queries. + * instant, and the data is loaded in parallel with the navigation, but may resolve + * after the navigation has completed. This will result in the data loading after the + * navigation has completed most of the time for this route, as we chunk the data into + * multiple queries. * * Here we instead render a local ProgressBar, which is animated, and exit * the animation when the data is loaded, and the form is rendered. diff --git a/packages/admin/dashboard/src/routes/products/product-stock/types.ts b/packages/admin/dashboard/src/routes/products/product-stock/types.ts deleted file mode 100644 index 59e3a196f9554..0000000000000 --- a/packages/admin/dashboard/src/routes/products/product-stock/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { HttpTypes } from "@medusajs/types" - -// TODO: Create a type in the types package -export interface ProductVariantInventoryItemLink { - id: string - variant_id: string - inventory_item_id: string - inventory: HttpTypes.AdminInventoryItem -} diff --git a/packages/admin/dashboard/src/routes/products/product-stock/utils.ts b/packages/admin/dashboard/src/routes/products/product-stock/utils.ts index df620eb3a1c70..0a0ea3fe621e3 100644 --- a/packages/admin/dashboard/src/routes/products/product-stock/utils.ts +++ b/packages/admin/dashboard/src/routes/products/product-stock/utils.ts @@ -1,24 +1,25 @@ import { HttpTypes } from "@medusajs/types" -import { ProductVariantInventoryItemLink } from "./types" export function isProductVariant( - row: HttpTypes.AdminProductVariant | ProductVariantInventoryItemLink + row: + | HttpTypes.AdminProductVariant + | HttpTypes.AdminProductVariantInventoryItemLink ): row is HttpTypes.AdminProductVariant { return row.id.startsWith("variant_") } export function isProductVariantWithInventoryPivot( - row: HttpTypes.AdminProductVariant | ProductVariantInventoryItemLink + row: + | HttpTypes.AdminProductVariant + | HttpTypes.AdminProductVariantInventoryItemLink ): row is HttpTypes.AdminProductVariant & { - inventory_items: ProductVariantInventoryItemLink[] + inventory_items: HttpTypes.AdminProductVariantInventoryItemLink[] } { return (row as any).inventory_items && (row as any).inventory_items.length > 0 } export function getDisabledInventoryRows( - variants: (HttpTypes.AdminProductVariant & { - inventory_items: ProductVariantInventoryItemLink[] - })[] + variants: HttpTypes.AdminProductVariant[] ) { const seen: Record = {} const disabled: Record = @@ -27,6 +28,10 @@ export function getDisabledInventoryRows( variants.forEach((variant) => { const inventoryItems = variant.inventory_items + if (!inventoryItems) { + return + } + inventoryItems.forEach((item) => { const existing = seen[item.inventory_item_id] diff --git a/packages/core/types/src/http/product/admin/entitites.ts b/packages/core/types/src/http/product/admin/entitites.ts index 53e07b5506b46..c6533552ecab1 100644 --- a/packages/core/types/src/http/product/admin/entitites.ts +++ b/packages/core/types/src/http/product/admin/entitites.ts @@ -1,4 +1,5 @@ import { AdminCollection } from "../../collection" +import { AdminInventoryItem } from "../../inventory" import { AdminPrice } from "../../pricing" import { AdminProductCategory } from "../../product-category" import { AdminProductTag } from "../../product-tag" @@ -13,6 +14,29 @@ import { ProductStatus, } from "../common" +export interface AdminProductVariantInventoryItemLink { + /** + * The ID of the pivot record. + */ + id: string + /** + * The ID of the variant. + */ + variant_id: string + /** + * The variant that the inventory item is linked to. + */ + variant?: AdminProductVariant + /** + * The ID of the inventory item. + */ + inventory_item_id: string + /** + * The inventory item that is linked to the variant. + */ + inventory?: AdminInventoryItem +} + export interface AdminProductVariant extends BaseProductVariant { /** * The product variant's prices. @@ -26,6 +50,10 @@ export interface AdminProductVariant extends BaseProductVariant { * The product that this variant belongs to. */ product?: AdminProduct | null + /** + * The variant's inventory items. + */ + inventory_items?: AdminProductVariantInventoryItemLink[] | null } export interface AdminProductOption extends BaseProductOption { /** From 940ba4833a1462675bdba2c580812226dfe2ca2f Mon Sep 17 00:00:00 2001 From: Kasper Fabricius Kristensen <45367945+kasperkristensen@users.noreply.github.com> Date: Fri, 10 Jan 2025 09:36:55 +0100 Subject: [PATCH 19/19] update cursor on bidirectional select --- .../data-grid/components/data-grid-root.tsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx b/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx index c9d6d9cc209a7..9dea7779b9f89 100644 --- a/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx +++ b/packages/admin/dashboard/src/components/data-grid/components/data-grid-root.tsx @@ -663,6 +663,7 @@ export const DataGridRoot = < virtualPaddingLeft={virtualPaddingLeft} virtualPaddingRight={virtualPaddingRight} onDragToFillStart={onDragToFillStart} + multiColumnSelection={multiColumnSelection} /> ) })} @@ -795,6 +796,7 @@ type DataGridCellProps = { rowIndex: number anchor: DataGridCoordinates | null onDragToFillStart: (e: React.MouseEvent) => void + multiColumnSelection: boolean } const DataGridCell = ({ @@ -803,6 +805,7 @@ const DataGridCell = ({ rowIndex, anchor, onDragToFillStart, + multiColumnSelection, }: DataGridCellProps) => { const coords: DataGridCoordinates = { row: rowIndex, @@ -836,7 +839,12 @@ const DataGridCell = ({ {isAnchor && (
)}
@@ -854,6 +862,7 @@ type DataGridRowProps = { flatColumns: Column[] anchor: DataGridCoordinates | null onDragToFillStart: (e: React.MouseEvent) => void + multiColumnSelection: boolean } const DataGridRow = ({ @@ -866,6 +875,7 @@ const DataGridRow = ({ flatColumns, anchor, onDragToFillStart, + multiColumnSelection, }: DataGridRowProps) => { const visibleCells = row.getVisibleCells() @@ -912,6 +922,7 @@ const DataGridRow = ({ rowIndex={rowIndex} anchor={anchor} onDragToFillStart={onDragToFillStart} + multiColumnSelection={multiColumnSelection} /> )