From 931467a73ae3451f765e7b046b32f798aa6662c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Dro=C5=84?= Date: Wed, 18 Jan 2023 10:23:24 +0100 Subject: [PATCH] Fix strict null checks in warehouses (#2945) * Fix strict nulls in warehouse details * Fix strict null check in warehouse list * Fix stcit null checks in warehouse create view * Fix overlapping label in textfields * Improve labels in warehouse details * Improve function description --- locale/defaultMessages.json | 8 ++-- src/hooks/usePaginator.ts | 13 ++----- src/misc.ts | 4 +- src/utils/handlers/filterHandlers.ts | 2 +- src/utils/limits.ts | 18 +++++++-- src/utils/maps.ts | 2 +- .../WarehouseCreatePage.stories.tsx | 2 +- .../WarehouseDetailsPage.stories.tsx | 2 +- .../WarehouseDetailsPage.tsx | 28 ++++++-------- .../WarehouseList/WarehouseList.tsx | 12 +++--- .../WarehouseListPage/WarehouseListPage.tsx | 29 ++++++++------- .../WarehouseSettings/WarehouseSettings.tsx | 23 +++++++----- .../components/WarehouseSettings/messages.ts | 8 ++-- .../views/WarehouseCreate/WarehouseCreate.tsx | 9 +++-- .../WarehouseDetails/WarehouseDetails.tsx | 8 ++-- .../views/WarehouseList/WarehouseList.tsx | 37 +++++++++++-------- src/warehouses/views/WarehouseList/sort.ts | 2 +- 17 files changed, 110 insertions(+), 97 deletions(-) diff --git a/locale/defaultMessages.json b/locale/defaultMessages.json index 7e71b98ca..9c2e92cb6 100644 --- a/locale/defaultMessages.json +++ b/locale/defaultMessages.json @@ -137,10 +137,6 @@ "+xTpT1": { "string": "Attributes" }, - "//iaFx": { - "context": "WarehouseSettings title", - "string": "Settings" - }, "//k1GX": { "context": "expired on label", "string": "Expired on {date}" @@ -1441,6 +1437,10 @@ "context": "bulk issue menu item", "string": "Bulk Issue" }, + "9kzIFd": { + "context": "WarehouseSettings stock title", + "string": "Stock settings" + }, "9mGA/Q": { "context": "button linking to dashboard", "string": "Dashboard" diff --git a/src/hooks/usePaginator.ts b/src/hooks/usePaginator.ts index 9e89b76f2..1b3682ecd 100644 --- a/src/hooks/usePaginator.ts +++ b/src/hooks/usePaginator.ts @@ -4,10 +4,10 @@ import { createContext, useContext, useMemo } from "react"; import { Pagination } from "../types"; export interface PageInfo { - endCursor: string; + endCursor: string | null; hasNextPage: boolean; hasPreviousPage: boolean; - startCursor: string; + startCursor: string | null; } export interface PaginationState { @@ -37,7 +37,7 @@ export function createPaginationState( } interface UsePaginatorArgs { - pageInfo: PageInfo; + pageInfo: PageInfo | undefined; paginationState: PaginationState; queryString: Pagination; } @@ -99,12 +99,7 @@ function usePaginator({ export default usePaginator; -export interface PaginatorContextValuesCommon { - hasNextPage?: boolean; - hasPreviousPage?: boolean; - endCursor?: string | null; - startCursor?: string | null; -} +export type PaginatorContextValuesCommon = Partial; export type PaginatorContextValues = PaginatorContextValuesCommon & ( diff --git a/src/misc.ts b/src/misc.ts index f50f78c5a..decc1f82a 100644 --- a/src/misc.ts +++ b/src/misc.ts @@ -43,11 +43,11 @@ export type RequireOnlyOne = Pick< }[Keys]; export function renderCollection( - collection: T[], + collection: T[] | undefined, renderItem: ( item: T | undefined, index: number | undefined, - collection: T[], + collection: T[] | undefined, ) => any, renderEmpty?: (collection: T[]) => any, ) { diff --git a/src/utils/handlers/filterHandlers.ts b/src/utils/handlers/filterHandlers.ts index aa7e3f3dc..0ba1cb8d0 100644 --- a/src/utils/handlers/filterHandlers.ts +++ b/src/utils/handlers/filterHandlers.ts @@ -4,7 +4,7 @@ import { ActiveTab, Pagination, Search, Sort } from "@dashboard/types"; import { GetFilterQueryParam, getFilterQueryParams } from "../filters"; -type RequiredParams = ActiveTab & Search & Sort & Pagination; +type RequiredParams = ActiveTab & Search & Sort & Pagination; type CreateUrl = (params: RequiredParams) => string; type CreateFilterHandlers = [ (filter: IFilter) => void, diff --git a/src/utils/limits.ts b/src/utils/limits.ts index 68c65671f..f41ec7db7 100644 --- a/src/utils/limits.ts +++ b/src/utils/limits.ts @@ -1,7 +1,7 @@ import { LimitInfoFragment, RefreshLimitsQuery } from "@dashboard/graphql"; export function hasLimits( - limits: RefreshLimitsQuery["shop"]["limits"], + limits: RefreshLimitsQuery["shop"]["limits"] | undefined, key: keyof LimitInfoFragment, ): boolean { if (limits === undefined) { @@ -10,14 +10,24 @@ export function hasLimits( return limits.allowedUsage[key] !== null; } - +/** + * Returns whether or not limit has been reached. + * If limits are undefined, returns false. + * */ export function isLimitReached( - limits: RefreshLimitsQuery["shop"]["limits"], + limits: RefreshLimitsQuery["shop"]["limits"] | undefined, key: keyof LimitInfoFragment, ): boolean { if (!hasLimits(limits, key)) { return false; } - return limits.currentUsage[key] >= limits.allowedUsage[key]; + const currentUsage = limits?.currentUsage[key]; + const allowedUsage = limits?.allowedUsage[key]; + + if (!currentUsage || !allowedUsage) { + return false; + } + + return currentUsage >= allowedUsage!; } diff --git a/src/utils/maps.ts b/src/utils/maps.ts index bd76db268..198bbf11b 100644 --- a/src/utils/maps.ts +++ b/src/utils/maps.ts @@ -17,7 +17,7 @@ interface Edge { node: T; } interface Connection { - edges: Array> | undefined; + edges: Array> | undefined | null; } export function mapEdgesToItems( diff --git a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx index c15c46f2e..6e0185459 100644 --- a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx +++ b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx @@ -17,7 +17,7 @@ const props: WarehouseCreatePageProps = { })), disabled: false, errors: [], - onSubmit: () => undefined, + onSubmit: async () => undefined, saveButtonBarState: "default", }; storiesOf("Warehouses / Create warehouse", module) diff --git a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.stories.tsx b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.stories.tsx index f12e5f146..942014a11 100644 --- a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.stories.tsx +++ b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.stories.tsx @@ -19,7 +19,7 @@ const props: WarehouseDetailsPageProps = { disabled: false, errors: [], onDelete: () => undefined, - onSubmit: () => undefined, + onSubmit: async () => undefined, saveButtonBarState: "default", warehouse, }; diff --git a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx index 3880c4f28..aecebc79a 100644 --- a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx +++ b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx @@ -9,7 +9,6 @@ import PageHeader from "@dashboard/components/PageHeader"; import Savebar from "@dashboard/components/Savebar"; import { AddressTypeInput } from "@dashboard/customers/types"; import { - CountryCode, CountryWithCodeFragment, WarehouseClickAndCollectOptionEnum, WarehouseDetailsFragment, @@ -20,7 +19,6 @@ import { SubmitPromise } from "@dashboard/hooks/useForm"; import useNavigator from "@dashboard/hooks/useNavigator"; import useStateFromProps from "@dashboard/hooks/useStateFromProps"; import { sectionNames } from "@dashboard/intl"; -import { findValueInEnum, maybe } from "@dashboard/misc"; import createSingleAutocompleteSelectHandler from "@dashboard/utils/handlers/singleAutocompleteSelectChangeHandler"; import { mapCountriesToChoices, mapEdgesToItems } from "@dashboard/utils/maps"; import { warehouseListUrl } from "@dashboard/warehouses/urls"; @@ -41,7 +39,7 @@ export interface WarehouseDetailsPageProps { disabled: boolean; errors: WarehouseErrorFragment[]; saveButtonBarState: ConfirmButtonTransitionState; - warehouse: WarehouseDetailsFragment; + warehouse: WarehouseDetailsFragment | undefined; onDelete: () => void; onSubmit: (data: WarehouseDetailsPageFormData) => SubmitPromise; } @@ -68,21 +66,19 @@ const WarehouseDetailsPage: React.FC = ({ } = useAddressValidation(onSubmit); const initialForm: WarehouseDetailsPageFormData = { - city: maybe(() => warehouse.address.city, ""), - companyName: maybe(() => warehouse.address.companyName, ""), - country: maybe(() => - findValueInEnum(warehouse.address.country.code, CountryCode), - ), + city: warehouse?.address.city ?? "", + companyName: warehouse?.address.companyName ?? "", + country: warehouse?.address.country.code ?? "", isPrivate: !!warehouse?.isPrivate, clickAndCollectOption: warehouse?.clickAndCollectOption || WarehouseClickAndCollectOptionEnum.DISABLED, - countryArea: maybe(() => warehouse.address.countryArea, ""), - name: maybe(() => warehouse.name, ""), - phone: maybe(() => warehouse.address.phone, ""), - postalCode: maybe(() => warehouse.address.postalCode, ""), - streetAddress1: maybe(() => warehouse.address.streetAddress1, ""), - streetAddress2: maybe(() => warehouse.address.streetAddress2, ""), + countryArea: warehouse?.address.countryArea ?? "", + name: warehouse?.name ?? "", + phone: warehouse?.address.phone ?? "", + postalCode: warehouse?.address.postalCode ?? "", + streetAddress1: warehouse?.address.streetAddress1 ?? "", + streetAddress2: warehouse?.address.streetAddress2 ?? "", }; return ( @@ -133,7 +129,7 @@ const WarehouseDetailsPage: React.FC = ({
= ({
navigate(warehouseListUrl())} onDelete={onDelete} onSubmit={submit} diff --git a/src/warehouses/components/WarehouseList/WarehouseList.tsx b/src/warehouses/components/WarehouseList/WarehouseList.tsx index cd7a1d2f3..5faef07eb 100644 --- a/src/warehouses/components/WarehouseList/WarehouseList.tsx +++ b/src/warehouses/components/WarehouseList/WarehouseList.tsx @@ -5,7 +5,7 @@ import TableCellHeader from "@dashboard/components/TableCellHeader"; import { TablePaginationWithContext } from "@dashboard/components/TablePagination"; import TableRowLink from "@dashboard/components/TableRowLink"; import { WarehouseWithShippingFragment } from "@dashboard/graphql"; -import { maybe, renderCollection, stopPropagation } from "@dashboard/misc"; +import { renderCollection, stopPropagation } from "@dashboard/misc"; import { ListProps, SortPage } from "@dashboard/types"; import { mapEdgesToItems } from "@dashboard/utils/maps"; import { getArrowDirection } from "@dashboard/utils/sort"; @@ -64,8 +64,8 @@ const useStyles = makeStyles( interface WarehouseListProps extends ListProps, SortPage { - warehouses: WarehouseWithShippingFragment[]; - onRemove: (id: string) => void; + warehouses: WarehouseWithShippingFragment[] | undefined; + onRemove: (id: string | undefined) => void; } const numberOfColumns = 3; @@ -90,7 +90,7 @@ const WarehouseList: React.FC = props => { = props => { } > - {maybe(() => warehouse.name, )} + {warehouse?.name ?? } {warehouse?.shippingZones === undefined ? ( @@ -160,7 +160,7 @@ const WarehouseList: React.FC = props => { onRemove(warehouse.id))} + onClick={stopPropagation(() => onRemove(warehouse?.id))} > diff --git a/src/warehouses/components/WarehouseListPage/WarehouseListPage.tsx b/src/warehouses/components/WarehouseListPage/WarehouseListPage.tsx index 1ee34223b..829780514 100644 --- a/src/warehouses/components/WarehouseListPage/WarehouseListPage.tsx +++ b/src/warehouses/components/WarehouseListPage/WarehouseListPage.tsx @@ -32,8 +32,8 @@ export interface WarehouseListPageProps SearchPageProps, SortPage, TabPageProps { - limits: RefreshLimitsQuery["shop"]["limits"]; - warehouses: WarehouseWithShippingFragment[]; + limits: RefreshLimitsQuery["shop"]["limits"] | undefined; + warehouses: WarehouseWithShippingFragment[] | undefined; onRemove: (id: string) => void; } @@ -66,18 +66,19 @@ export const WarehouseListPage: React.FC = ({