diff --git a/src/structures/components/MenuDetailsPage/MenuDetailsPage.tsx b/src/structures/components/MenuDetailsPage/MenuDetailsPage.tsx index 5525588fd00..b8f8981c256 100644 --- a/src/structures/components/MenuDetailsPage/MenuDetailsPage.tsx +++ b/src/structures/components/MenuDetailsPage/MenuDetailsPage.tsx @@ -1,4 +1,3 @@ -// @ts-strict-ignore import { TopNav } from "@dashboard/components/AppLayout"; import { ConfirmButtonTransitionState } from "@dashboard/components/ConfirmButton"; import Form from "@dashboard/components/Form"; @@ -11,12 +10,13 @@ import { MenuDetailsFragment, MenuErrorFragment } from "@dashboard/graphql"; import { SubmitPromise } from "@dashboard/hooks/useForm"; import useNavigator from "@dashboard/hooks/useNavigator"; import { menuListUrl } from "@dashboard/structures/urls"; +import { UniqueIdentifier } from "@dnd-kit/core"; import { useState } from "react"; import { MenuItemType } from "../MenuItemDialog"; import MenuItems, { TreeOperation } from "../MenuItems"; import MenuProperties from "../MenuProperties"; -import { computeRelativeTree } from "./tree"; +import { computeRelativeTree, normalizeMenuItems } from "./tree"; export interface MenuDetailsFormData { name: string; @@ -33,10 +33,10 @@ interface MenuDetailsPageProps { menu: MenuDetailsFragment; onDelete: () => void; onItemAdd: () => void; - onItemClick: (id: string, type: MenuItemType) => void; - onItemEdit: (id: string) => void; + onItemClick: (id: UniqueIdentifier, type: MenuItemType) => void; + onItemEdit: (id: UniqueIdentifier) => void; // If not passed, it will not render the button. Use to control permissions - onTranslate?: (id: string) => void; + onTranslate?: (id: UniqueIdentifier) => void; onSubmit: (data: MenuDetailsSubmitData) => SubmitPromise; } @@ -96,7 +96,11 @@ const MenuDetailsPage = ({ 0} - items={menu?.items ? computeRelativeTree(menu.items, treeOperations) : []} + items={ + menu?.items + ? computeRelativeTree(normalizeMenuItems(menu.items), treeOperations) + : [] + } onChange={handleChange} onItemAdd={onItemAdd} onItemClick={onItemClick} diff --git a/src/structures/components/MenuDetailsPage/tree.test.ts b/src/structures/components/MenuDetailsPage/tree.test.ts index 811585d99c9..3b1ebd54f52 100644 --- a/src/structures/components/MenuDetailsPage/tree.test.ts +++ b/src/structures/components/MenuDetailsPage/tree.test.ts @@ -1,9 +1,11 @@ -// @ts-strict-ignore import { RecursiveMenuItem } from "@dashboard/structures/types"; import { menu } from "../../fixtures"; import { TreeOperation } from "../MenuItems"; -import { computeRelativeTree } from "./tree"; +import { computeRelativeTree, normalizeMenuItems } from "./tree"; + +// Normalize menu items for testing +const normalizedMenuItems = normalizeMenuItems(menu.items); const relativeOutput: RecursiveMenuItem[][] = [ // no moves @@ -1156,7 +1158,7 @@ function innerTreeToString(tree: RecursiveMenuItem, level: number): string { "\n" + "ยทยท".repeat(level) + tree.name + - tree.children.reduce((acc, node) => acc + innerTreeToString(node, level + 1), "") + tree.children?.reduce((acc, node) => acc + innerTreeToString(node, level + 1), "") ); } @@ -1167,7 +1169,7 @@ function treeToString(tree: RecursiveMenuItem[]): string { describe("Properly computes trees", () => { testTable.forEach(testData => it("#", () => { - const computedTree = computeRelativeTree(menu.items, testData); + const computedTree = computeRelativeTree(normalizedMenuItems, testData); expect(treeToString(computedTree)).toMatchSnapshot(); }), @@ -1175,58 +1177,86 @@ describe("Properly computes trees", () => { }); describe("Properly computes relative trees", () => { it("doesn't move anything", () => { - const computedTree = computeRelativeTree(menu.items, secondTestTable[0]); + const computedTree = computeRelativeTree(normalizedMenuItems, secondTestTable[0]); expect(computedTree).toEqual(relativeOutput[0]); }); it("moves one root element", () => { - const computedTree = computeRelativeTree(menu.items, secondTestTable[1]); + const computedTree = computeRelativeTree(normalizedMenuItems, secondTestTable[1]); expect(computedTree).toEqual(relativeOutput[1]); }); it("moves two root element", () => { - const computedTree = computeRelativeTree(menu.items, secondTestTable[2]); + const computedTree = computeRelativeTree(normalizedMenuItems, secondTestTable[2]); expect(computedTree).toEqual(relativeOutput[2]); }); it("empty moves", () => { - const computedTree = computeRelativeTree(menu.items, secondTestTable[3]); + const computedTree = computeRelativeTree(normalizedMenuItems, secondTestTable[3]); expect(computedTree).toEqual(relativeOutput[3]); }); it("moves every element", () => { - const computedTree = computeRelativeTree(menu.items, secondTestTable[4]); + const computedTree = computeRelativeTree(normalizedMenuItems, secondTestTable[4]); expect(computedTree).toEqual(relativeOutput[4]); }); it("moves children", () => { - const computedTree = computeRelativeTree(menu.items, secondTestTable[5]); + const computedTree = computeRelativeTree(normalizedMenuItems, secondTestTable[5]); expect(computedTree).toEqual(relativeOutput[5]); }); it("moves child outside", () => { - const computedTree = computeRelativeTree(menu.items, secondTestTable[6]); + const computedTree = computeRelativeTree(normalizedMenuItems, secondTestTable[6]); expect(computedTree).toEqual(relativeOutput[6]); }); it("moves child outside and puts it in a location", () => { - const computedTree = computeRelativeTree(menu.items, secondTestTable[7]); + const computedTree = computeRelativeTree(normalizedMenuItems, secondTestTable[7]); expect(computedTree).toEqual(relativeOutput[7]); }); it("moves child inside", () => { - const computedTree = computeRelativeTree(menu.items, secondTestTable[8]); + const computedTree = computeRelativeTree(normalizedMenuItems, secondTestTable[8]); expect(computedTree).toEqual(relativeOutput[8]); }); it("moves child inside then outside then changes index", () => { - const computedTree = computeRelativeTree(menu.items, secondTestTable[9]); + const computedTree = computeRelativeTree(normalizedMenuItems, secondTestTable[9]); expect(computedTree).toEqual(relativeOutput[9]); }); it("moves item as last child and moves it up", () => { - const computedTree = computeRelativeTree(menu.items, secondTestTable[10]); + const computedTree = computeRelativeTree(normalizedMenuItems, secondTestTable[10]); expect(computedTree).toEqual(relativeOutput[10]); }); }); +describe("Error handling for invalid paths", () => { + it("throws error when trying to move non-existent node", () => { + // Arrange + const invalidOperation: TreeOperation = { + id: "non-existent-id", + type: "move", + sortOrder: 0, + }; + + // Act & Assert + expect(() => { + computeRelativeTree(normalizedMenuItems, [invalidOperation]); + }).toThrow("Cannot get node with null path"); + }); + + it("throws error when trying to remove non-existent node", () => { + // Arrange + const invalidOperation: TreeOperation = { + id: "non-existent-id", + type: "remove", + }; + + // Act & Assert + expect(() => { + computeRelativeTree(normalizedMenuItems, [invalidOperation]); + }).toThrow("Cannot get node with null path"); + }); +}); diff --git a/src/structures/components/MenuDetailsPage/tree.ts b/src/structures/components/MenuDetailsPage/tree.ts index 7c489af81fa..9c017ffdf4f 100644 --- a/src/structures/components/MenuDetailsPage/tree.ts +++ b/src/structures/components/MenuDetailsPage/tree.ts @@ -1,9 +1,21 @@ -// @ts-strict-ignore import { RecursiveMenuItem } from "@dashboard/structures/types"; import { TreeOperation } from "../MenuItems"; -export function findNode(tree: RecursiveMenuItem[], id: string): number[] { +// Normalizes GraphQL menu items to ensure children is always an array + +export function normalizeMenuItems(items: any): RecursiveMenuItem[] { + if (!items) return []; + + return items.map( + (item: any): RecursiveMenuItem => ({ + ...item, + children: normalizeMenuItems(item.children), + }), + ); +} + +export function findNode(tree: RecursiveMenuItem[], id: string): (number | null)[] { const foundNodeIndex = tree.findIndex(node => node.id === id); if (tree.length === 0) { @@ -14,22 +26,32 @@ export function findNode(tree: RecursiveMenuItem[], id: string): number[] { return [foundNodeIndex]; } - const nodeMap = tree.map((node, nodeIndex) => [nodeIndex, ...findNode(node.children, id)]); + const nodeMap = tree.map((node, nodeIndex) => [nodeIndex, ...findNode(node.children ?? [], id)]); return nodeMap.find(path => path[path.length - 1] !== null) || [null]; } -export function getNode(tree: RecursiveMenuItem[], path: number[]): RecursiveMenuItem { +export function getNode(tree: RecursiveMenuItem[], path: (number | null)[]): RecursiveMenuItem { + const index = path[0]; + + if (index === null) { + throw new Error("Cannot get node with null path"); + } + if (path.length === 1) { - return tree[path[0]]; + return tree[index]; } - return getNode([...tree[path[0]].children], path.slice(1)); + return getNode(tree[index].children ?? [], path.slice(1)); } -function removeNode(tree: RecursiveMenuItem[], path: number[]): RecursiveMenuItem[] { +function removeNode(tree: RecursiveMenuItem[], path: (number | null)[]): RecursiveMenuItem[] { const removeIndex = path[0]; + if (removeIndex === null) { + throw new Error("Cannot remove node with null path"); + } + if (path.length === 1) { return [...tree.slice(0, removeIndex), ...tree.slice(removeIndex + 1)]; } @@ -37,8 +59,8 @@ function removeNode(tree: RecursiveMenuItem[], path: number[]): RecursiveMenuIte const newTree = [...tree]; newTree[removeIndex] = { - ...tree[path[0]], - children: removeNode(tree[path[0]].children, path.slice(1)), + ...tree[removeIndex], + children: removeNode(tree[removeIndex].children ?? [], path.slice(1)), }; return newTree; @@ -46,7 +68,7 @@ function removeNode(tree: RecursiveMenuItem[], path: number[]): RecursiveMenuIte interface InsertNodeInput { tree: RecursiveMenuItem[]; - path: number[]; + path: (number | null)[]; node: RecursiveMenuItem; position: number; } @@ -56,9 +78,15 @@ function insertNode({ tree, path, node, position }: InsertNodeInput): RecursiveM return [...tree.slice(0, position), node, ...tree.slice(position)]; } - if (path[0] in tree) { - tree[path[0]].children = insertNode({ - tree: tree[path[0]].children, + const index = path[0]; + + if (index === null) { + throw new Error("Cannot insert node with null path"); + } + + if (index in tree) { + tree[index].children = insertNode({ + tree: tree[index].children ?? [], path: path.slice(1), node, position, @@ -99,13 +127,18 @@ function permuteRelativeNode( const node = getNode(tree, sourcePath); const hasParent = !!permutation.parentId; const treeAfterRemoval = removeNode(tree, sourcePath); - const targetPath = hasParent ? findNode(treeAfterRemoval, permutation.parentId) : []; + const targetPath = hasParent ? findNode(treeAfterRemoval, permutation.parentId ?? "") : []; const position = sourcePath[sourcePath.length - 1]; + + if (position === null) { + throw new Error("Cannot permute node with null position"); + } + const treeAfterInsertion = insertNode({ tree: treeAfterRemoval, path: targetPath, node, - position: position + permutation.sortOrder, + position: position + (permutation.sortOrder ?? 0), }); return treeAfterInsertion; diff --git a/src/structures/components/MenuItemDialog/MenuItemDialog.tsx b/src/structures/components/MenuItemDialog/MenuItemDialog.tsx index 5e70bca3bbf..588e42a74ac 100644 --- a/src/structures/components/MenuItemDialog/MenuItemDialog.tsx +++ b/src/structures/components/MenuItemDialog/MenuItemDialog.tsx @@ -1,4 +1,3 @@ -// @ts-strict-ignore import BackButton from "@dashboard/components/BackButton"; import { Combobox } from "@dashboard/components/Combobox"; import { ConfirmButton, ConfirmButtonTransitionState } from "@dashboard/components/ConfirmButton"; diff --git a/src/structures/components/MenuItemDialog/MenuItemDialogLinkValue/useLinkValue.ts b/src/structures/components/MenuItemDialog/MenuItemDialogLinkValue/useLinkValue.ts index 27e3cdda14e..d1670781ffc 100644 --- a/src/structures/components/MenuItemDialog/MenuItemDialogLinkValue/useLinkValue.ts +++ b/src/structures/components/MenuItemDialog/MenuItemDialogLinkValue/useLinkValue.ts @@ -46,16 +46,16 @@ export const useLinkValue = (linkType: MenuItemTypeWithOptions) => { const pages = mapEdgesToItems(pageSearch?.result?.data?.search) || []; const categoriesOptions = categories?.map(category => ({ - value: category.id, - label: category.name, + value: (category as { id: string }).id, + label: (category as { name: string }).name, })); const collectionsOptions = collections?.map(collection => ({ - value: collection.id, - label: collection.name, + value: (collection as { id: string }).id, + label: (collection as { name: string }).name, })); const pagesOptions = pages?.map(page => ({ - value: page.id, - label: page.title, + value: (page as { id: string }).id, + label: (page as { title: string }).title, })); const options = { diff --git a/src/structures/components/MenuItems/MenuItems.tsx b/src/structures/components/MenuItems/MenuItems.tsx index 7feaf5b0c16..979a9bc1b46 100644 --- a/src/structures/components/MenuItems/MenuItems.tsx +++ b/src/structures/components/MenuItems/MenuItems.tsx @@ -1,7 +1,7 @@ -// @ts-strict-ignore import { DashboardCard } from "@dashboard/components/Card"; import { buttonMessages } from "@dashboard/intl"; import { RecursiveMenuItem } from "@dashboard/structures/types"; +import { UniqueIdentifier } from "@dnd-kit/core"; import { Box, Button, Skeleton } from "@saleor/macaw-ui-next"; import { useMemo } from "react"; import { FormattedMessage, useIntl } from "react-intl"; @@ -16,10 +16,10 @@ interface MenuItemsProps { items: RecursiveMenuItem[]; onChange: (operations: TreeOperation[]) => void; onItemAdd: () => void; - onItemClick: (id: string, type: MenuItemType) => void; - onItemEdit: (id: string) => void; + onItemClick: (id: UniqueIdentifier, type: MenuItemType) => void; + onItemEdit: (id: UniqueIdentifier) => void; // If not passed, it will not render the button. Use to control permissions - onTranslate?: (id: string) => void; + onTranslate?: (id: UniqueIdentifier) => void; onUndo: () => void; } diff --git a/src/structures/components/MenuItems/tree.test.ts b/src/structures/components/MenuItems/tree.test.ts index 6e532369731..d8236e4e109 100644 --- a/src/structures/components/MenuItems/tree.test.ts +++ b/src/structures/components/MenuItems/tree.test.ts @@ -1,4 +1,3 @@ -// @ts-strict-ignore import { MenuItemFragment } from "@dashboard/graphql"; import { MenuTreeItem } from "@dashboard/structures/types"; diff --git a/src/structures/components/MenuItems/tree.ts b/src/structures/components/MenuItems/tree.ts index ef3e12aea60..a56adb14075 100644 --- a/src/structures/components/MenuItems/tree.ts +++ b/src/structures/components/MenuItems/tree.ts @@ -1,5 +1,3 @@ -// @ts-strict-ignore - import { MenuTreeItem } from "@dashboard/structures/types"; import { getPatch } from "fast-array-diff"; diff --git a/src/structures/components/MenuList/MenuList.tsx b/src/structures/components/MenuList/MenuList.tsx index 70bd97e0e4c..c93862d975a 100644 --- a/src/structures/components/MenuList/MenuList.tsx +++ b/src/structures/components/MenuList/MenuList.tsx @@ -1,4 +1,3 @@ -// @ts-strict-ignore import { DashboardCard } from "@dashboard/components/Card"; import Checkbox from "@dashboard/components/Checkbox"; import IconButtonTableCell from "@dashboard/components/IconButtonTableCell"; @@ -9,7 +8,7 @@ import TableHead from "@dashboard/components/TableHead"; import { TablePaginationWithContext } from "@dashboard/components/TablePagination"; import TableRowLink from "@dashboard/components/TableRowLink"; import { MenuFragment } from "@dashboard/graphql"; -import { maybe, renderCollection } from "@dashboard/misc"; +import { renderCollection } from "@dashboard/misc"; import { MenuListUrlSortField, menuUrl } from "@dashboard/structures/urls"; import { ListActions, ListProps, SortPage } from "@dashboard/types"; import { getArrowDirection } from "@dashboard/utils/sort"; @@ -77,7 +76,9 @@ const MenuList = (props: MenuListProps) => { > onSort(MenuListUrlSortField.name)} @@ -87,7 +88,9 @@ const MenuList = (props: MenuListProps) => { onSort(MenuListUrlSortField.items)} @@ -130,20 +133,20 @@ const MenuList = (props: MenuListProps) => { checked={isSelected} disabled={disabled} disableClickPropagation - onChange={() => toggle(menu.id)} + onChange={() => toggle(menu?.id ?? "")} /> - {maybe(() => menu.name, )} + {menu?.name ?? } - {maybe(() => menu.items.length, )} + {menu?.items?.length ?? } onDelete(menu.id)} + onClick={() => onDelete(menu?.id ?? "")} > { }, }), ); - const menuItem = maybe(() => getNode(data.menu.items, findNode(data.menu.items, params.id))); + const normalizedItems = data?.menu?.items ? normalizeMenuItems(data.menu.items) : []; + const menuItem = + normalizedItems.length > 0 && params.id + ? getNode(normalizedItems, findNode(normalizedItems, params.id)) + : undefined; const initialMenuItemUpdateFormData: MenuItemDialogFormData = { - id: maybe(() => getItemId(menuItem)), - name: maybe(() => menuItem.name, "..."), - linkType: maybe(() => getItemType(menuItem), "category"), - linkValue: getInitialMenuItemValue(menuItem), + id: menuItem ? getItemId(menuItem as MenuItemFragment) : "", + name: menuItem?.name ?? "...", + linkType: menuItem ? getItemType(menuItem as MenuItemFragment) : "category", + linkValue: getInitialMenuItemValue(menuItem as MenuItemFragment | undefined), }; // This is a workaround to let know // that it should clean operation stack if mutations @@ -137,10 +140,14 @@ const MenuDetails = ({ id, params }: MenuDetailsProps) => { }, }); + if (!result.data) { + return []; + } + return [ - ...result.data.menuItemBulkDelete.errors, - ...result.data.menuItemMove.errors, - ...result.data.menuUpdate.errors, + ...(result.data.menuItemBulkDelete?.errors ?? []), + ...(result.data.menuItemMove?.errors ?? []), + ...(result.data.menuUpdate?.errors ?? []), ]; }; @@ -149,11 +156,10 @@ const MenuDetails = ({ id, params }: MenuDetailsProps) => { data.menu)} + menu={data?.menu ?? undefined} onDelete={() => navigate( menuUrl(id, { @@ -208,14 +214,14 @@ const MenuDetails = ({ id, params }: MenuDetailsProps) => { id="U2DyeR" defaultMessage="Are you sure you want to delete structure {menuName}?" values={{ - menuName: {maybe(() => data.menu.name, "...")}, + menuName: {data?.menu?.name ?? "..."}, }} /> menuItemCreateOpts.data.menuItemCreate.errors, [])} + errors={menuItemCreateOpts.data?.menuItemCreate?.errors ?? []} confirmButtonState={menuItemCreateOpts.status} disabled={menuItemCreateOpts.loading} onClose={closeModal} @@ -223,9 +229,9 @@ const MenuDetails = ({ id, params }: MenuDetailsProps) => { /> menuItemUpdateOpts.data.menuItemUpdate.errors, [])} + errors={menuItemUpdateOpts.data?.menuItemUpdate?.errors ?? []} initial={initialMenuItemUpdateFormData} - initialDisplayValue={getInitialMenuItemLabel(menuItem)} + initialDisplayValue={getInitialMenuItemLabel(menuItem as MenuItemFragment | undefined)} confirmButtonState={menuItemUpdateOpts.status} disabled={menuItemUpdateOpts.loading} onClose={closeModal} diff --git a/src/structures/views/MenuDetails/successHandlers.ts b/src/structures/views/MenuDetails/successHandlers.ts index 1906e699b27..88268cf328a 100644 --- a/src/structures/views/MenuDetails/successHandlers.ts +++ b/src/structures/views/MenuDetails/successHandlers.ts @@ -1,4 +1,3 @@ -// @ts-strict-ignore import { MenuDeleteMutation, MenuItemCreateMutation, @@ -18,7 +17,7 @@ export function handleItemCreate( closeModal: () => void, intl: IntlShape, ) { - if (data.menuItemCreate.errors.length === 0) { + if (data.menuItemCreate?.errors.length === 0) { closeModal(); notify({ status: "success", @@ -34,7 +33,7 @@ export function handleItemUpdate( notify: UseNotifierResult, intl: IntlShape, ) { - if (data.menuItemUpdate.errors.length === 0) { + if (data.menuItemUpdate?.errors.length === 0) { notify({ status: "success", text: intl.formatMessage(commonMessages.savedChanges), @@ -54,7 +53,7 @@ export function handleDelete( notify: UseNotifierResult, intl: IntlShape, ) { - if (data.menuDelete.errors.length === 0) { + if (data.menuDelete?.errors.length === 0) { notify({ status: "success", text: intl.formatMessage(commonMessages.savedChanges), @@ -70,9 +69,9 @@ export function handleUpdate( intl: IntlShape, ) { if ( - data.menuItemBulkDelete.errors.length === 0 && - data.menuItemMove.errors.length === 0 && - data.menuUpdate.errors.length === 0 + data.menuItemBulkDelete?.errors.length === 0 && + data.menuItemMove?.errors.length === 0 && + data.menuUpdate?.errors.length === 0 ) { notify({ status: "success", diff --git a/src/structures/views/MenuList/MenuList.tsx b/src/structures/views/MenuList/MenuList.tsx index 03bf534afe5..c40145bbe4b 100644 --- a/src/structures/views/MenuList/MenuList.tsx +++ b/src/structures/views/MenuList/MenuList.tsx @@ -1,7 +1,7 @@ -// @ts-strict-ignore import ActionDialog from "@dashboard/components/ActionDialog"; import { Button } from "@dashboard/components/Button"; import { + MenuFragment, useMenuBulkDeleteMutation, useMenuCreateMutation, useMenuDeleteMutation, @@ -66,13 +66,13 @@ const MenuList = ({ params }: MenuListProps) => { variables: queryVariables, }); const paginationValues = usePaginator({ - pageInfo: maybe(() => data.menus.pageInfo), + pageInfo: data?.menus?.pageInfo, paginationState, queryString: params, }); const [menuCreate, menuCreateOpts] = useMenuCreateMutation({ onCompleted: data => { - if (data.menuCreate.errors.length === 0) { + if (data.menuCreate?.errors.length === 0) { notify({ status: "success", text: intl.formatMessage({ @@ -80,13 +80,13 @@ const MenuList = ({ params }: MenuListProps) => { defaultMessage: "Created structure", }), }); - navigate(menuUrl(data.menuCreate.menu.id)); + navigate(menuUrl(data.menuCreate?.menu?.id ?? "")); } }, }); const [menuDelete, menuDeleteOpts] = useMenuDeleteMutation({ onCompleted: data => { - if (data.menuDelete.errors.length === 0) { + if (data.menuDelete?.errors.length === 0) { notify({ status: "success", text: intl.formatMessage({ @@ -101,7 +101,7 @@ const MenuList = ({ params }: MenuListProps) => { }); const [menuBulkDelete, menuBulkDeleteOpts] = useMenuBulkDeleteMutation({ onCompleted: data => { - if (data.menuBulkDelete.errors.length === 0) { + if (data.menuBulkDelete?.errors.length === 0) { notify({ status: "success", text: intl.formatMessage(commonMessages.savedChanges), @@ -118,7 +118,7 @@ const MenuList = ({ params }: MenuListProps) => { navigate( @@ -187,13 +187,14 @@ const MenuList = ({ params }: MenuListProps) => { defaultMessage="Are you sure you want to delete {menuName}?" values={{ menuName: getStringOrPlaceholder( - mapEdgesToItems(data?.menus)?.find(getById(params.id))?.name, + (mapEdgesToItems(data?.menus)?.find(getById(params.id)) as MenuFragment | undefined) + ?.name, ), }} /> params.ids.length > 0)} + open={params.action === "remove-many" && (params.ids?.length ?? 0) > 0} onClose={closeModal} confirmButtonState={menuBulkDeleteOpts.status} onConfirm={() => diff --git a/src/structures/views/MenuList/sort.ts b/src/structures/views/MenuList/sort.ts index bb07f45da7f..0cf16c32874 100644 --- a/src/structures/views/MenuList/sort.ts +++ b/src/structures/views/MenuList/sort.ts @@ -1,9 +1,8 @@ -// @ts-strict-ignore import { MenuSortField } from "@dashboard/graphql"; import { MenuListUrlSortField } from "@dashboard/structures/urls"; import { createGetSortQueryVariables } from "@dashboard/utils/sort"; -function getSortQueryField(sort: MenuListUrlSortField): MenuSortField { +function getSortQueryField(sort: MenuListUrlSortField): MenuSortField | undefined { switch (sort) { case MenuListUrlSortField.name: return MenuSortField.NAME;