From 60ec16961cae70e17fe75d5e9817ec0005a9b218 Mon Sep 17 00:00:00 2001 From: dominik-zeglen Date: Mon, 10 Feb 2020 17:07:17 +0100 Subject: [PATCH] Add warehouse create action button --- .../MultiAutocompleteSelectField.tsx | 11 ++++- .../MultiAutocompleteSelectFieldContent.tsx | 25 +++++++++++ .../SingleAutocompleteSelectField.stories.tsx | 10 +++++ .../SingleAutocompleteSelectField.tsx | 12 +++++- .../SingleAutocompleteSelectFieldContent.tsx | 41 ++++++++++++++++--- .../ShippingZoneDetailsPage.tsx | 5 ++- .../ShippingZoneWarehouses.tsx | 11 ++++- src/shipping/urls.ts | 1 + .../views/ShippingZoneDetails/index.tsx | 1 + 9 files changed, 108 insertions(+), 9 deletions(-) diff --git a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx index 31f07ccd6..27cb334c1 100644 --- a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx +++ b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectField.tsx @@ -12,7 +12,8 @@ import Debounce, { DebounceProps } from "@saleor/components/Debounce"; import ArrowDropdownIcon from "@saleor/icons/ArrowDropdown"; import { FetchMoreProps } from "@saleor/types"; import MultiAutocompleteSelectFieldContent, { - MultiAutocompleteChoiceType + MultiAutocompleteChoiceType, + MultiAutocompleteActionType } from "./MultiAutocompleteSelectFieldContent"; const useStyles = makeStyles( @@ -71,6 +72,7 @@ const useStyles = makeStyles( export interface MultiAutocompleteSelectFieldProps extends Partial { + add: MultiAutocompleteActionType; allowCustomValues?: boolean; displayValues: MultiAutocompleteChoiceType[]; error?: boolean; @@ -166,6 +168,13 @@ const MultiAutocompleteSelectFieldComponent: React.FC {isOpen && (!!inputValue || !!choices.length) && ( { + add.onClick(); + closeMenu(); + } + }} choices={choices.filter( choice => !value.includes(choice.value) )} diff --git a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx index f58e680dd..d414b8f3f 100644 --- a/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx +++ b/src/components/MultiAutocompleteSelectField/MultiAutocompleteSelectFieldContent.tsx @@ -7,6 +7,7 @@ import { FormattedMessage } from "react-intl"; import chevronDown from "@assets/images/ChevronDown.svg"; import CircularProgress from "@material-ui/core/CircularProgress"; import MenuItem from "@material-ui/core/MenuItem"; +import Typography from "@material-ui/core/Typography"; import Paper from "@material-ui/core/Paper"; import { makeStyles } from "@material-ui/core/styles"; import AddIcon from "@material-ui/icons/Add"; @@ -22,6 +23,10 @@ const menuItemHeight = 46; const maxMenuItems = 5; const offset = 24; +export interface MultiAutocompleteActionType { + label: string; + onClick: () => void; +} export interface MultiAutocompleteChoiceType { label: string; value: any; @@ -29,6 +34,7 @@ export interface MultiAutocompleteChoiceType { } export interface MultiAutocompleteSelectFieldContentProps extends Partial { + add: MultiAutocompleteActionType; choices: MultiAutocompleteChoiceType[]; displayCustomValue: boolean; displayValues: MultiAutocompleteChoiceType[]; @@ -145,6 +151,7 @@ function getChoiceIndex( const MultiAutocompleteSelectFieldContent: React.FC = props => { const { + add, choices, displayCustomValue, displayValues, @@ -156,6 +163,10 @@ const MultiAutocompleteSelectFieldContent: React.FC(); const scrollPosition = useElementScroll(anchor); @@ -183,6 +194,20 @@ const MultiAutocompleteSelectFieldContent: React.FC 0 || displayCustomValue ? ( <> + {add && ( + + + {add.label} + + )} {displayCustomValue && ( ( )) + .add("with add", () => ( + undefined + }} + /> + )) .add("can load more", () => ( )) diff --git a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx index 48b6e0692..4df5b02e6 100644 --- a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx +++ b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx @@ -10,7 +10,8 @@ import { FetchMoreProps } from "@saleor/types"; import ArrowDropdownIcon from "../../icons/ArrowDropdown"; import Debounce, { DebounceProps } from "../Debounce"; import SingleAutocompleteSelectFieldContent, { - SingleAutocompleteChoiceType + SingleAutocompleteChoiceType, + SingleAutocompleteActionType } from "./SingleAutocompleteSelectFieldContent"; const useStyles = makeStyles( @@ -25,6 +26,7 @@ const useStyles = makeStyles( export interface SingleAutocompleteSelectFieldProps extends Partial { + add: SingleAutocompleteActionType; error?: boolean; name: string; displayValue: string; @@ -47,6 +49,7 @@ const DebounceAutocomplete: React.ComponentType = props => { const { + add, allowCustomValues, choices, disabled, @@ -144,6 +147,13 @@ const SingleAutocompleteSelectFieldComponent: React.FC {isOpen && (!!inputValue || !!choices.length) && ( { + add.onClick(); + closeMenu(); + } + }} choices={choices} displayCustomValue={displayCustomValue} emptyOption={emptyOption} diff --git a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx index 602a24b47..4e19e204d 100644 --- a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx +++ b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectFieldContent.tsx @@ -1,5 +1,6 @@ import CircularProgress from "@material-ui/core/CircularProgress"; import MenuItem from "@material-ui/core/MenuItem"; +import Add from "@material-ui/icons/Add"; import Paper from "@material-ui/core/Paper"; import { makeStyles } from "@material-ui/core/styles"; import Typography from "@material-ui/core/Typography"; @@ -24,8 +25,13 @@ export interface SingleAutocompleteChoiceType { label: string; value: any; } +export interface SingleAutocompleteActionType { + label: string; + onClick: () => void; +} export interface SingleAutocompleteSelectFieldContentProps extends Partial { + add: SingleAutocompleteActionType; choices: SingleAutocompleteChoiceType[]; displayCustomValue: boolean; emptyOption: boolean; @@ -38,6 +44,14 @@ export interface SingleAutocompleteSelectFieldContentProps const useStyles = makeStyles( theme => ({ + add: { + background: theme.palette.background.default, + border: `1px solid ${theme.palette.divider}`, + borderRadius: "100%", + height: 24, + marginRight: theme.spacing(), + width: 24 + }, arrowContainer: { position: "relative" }, @@ -109,10 +123,9 @@ function getChoiceIndex( return choiceIndex; } -const SingleAutocompleteSelectFieldContent: React.FC< - SingleAutocompleteSelectFieldContentProps -> = props => { +const SingleAutocompleteSelectFieldContent: React.FC = props => { const { + add, choices, displayCustomValue, emptyOption, @@ -125,6 +138,10 @@ const SingleAutocompleteSelectFieldContent: React.FC< onFetchMore } = props; + if (!!add && !!displayCustomValue) { + throw new Error("Add and custom value cannot be displayed simultaneously"); + } + const classes = useStyles(props); const anchor = React.useRef(); const scrollPosition = useElementScroll(anchor); @@ -164,6 +181,20 @@ const SingleAutocompleteSelectFieldContent: React.FC< )} + {add && ( + + + {add.label} + + )} {displayCustomValue && ( )} - {choices.length > 0 && displayCustomValue && ( + {choices.length > 0 && (!!add || displayCustomValue) && (
)} {choices.map((suggestion, index) => { const choiceIndex = getChoiceIndex( index, emptyOption, - displayCustomValue + !!add || displayCustomValue ); return ( diff --git a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx index 0fab0ae87..19805372b 100644 --- a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx +++ b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx @@ -43,6 +43,7 @@ export interface ShippingZoneDetailsPageProps { onPriceRateEdit: (id: string) => void; onRateRemove: (rateId: string) => void; onSubmit: (data: FormData) => void; + onWarehouseAdd: () => void; onWeightRateAdd: () => void; onWeightRateEdit: (id: string) => void; } @@ -67,6 +68,7 @@ const ShippingZoneDetailsPage: React.FC = ({ onPriceRateEdit, onRateRemove, onSubmit, + onWarehouseAdd, onWeightRateAdd, onWeightRateEdit, saveButtonBarState, @@ -165,9 +167,10 @@ const ShippingZoneDetailsPage: React.FC = ({ displayValue={warehouseDisplayValues} hasMore={false} loading={false} + warehouses={warehouseChoices} onChange={handleWarehouseChange} onFetchMore={() => undefined} - warehouses={warehouseChoices} + onWarehouseAdd={onWarehouseAdd} /> diff --git a/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx b/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx index 0b0390667..f0580afde 100644 --- a/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx +++ b/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx @@ -18,6 +18,7 @@ interface ShippingZonewWarehousesProps extends FetchMoreProps { displayValue: MultiAutocompleteChoiceType[]; warehouses: MultiAutocompleteChoiceType[]; onChange: FormChange; + onWarehouseAdd: () => void; } export const ShippingZoneWarehouses: React.FC = props => { @@ -26,9 +27,10 @@ export const ShippingZoneWarehouses: React.FC = pr displayValue, hasMore, loading, + warehouses, onChange, onFetchMore, - warehouses + onWarehouseAdd } = props; const intl = useIntl(); @@ -42,6 +44,13 @@ export const ShippingZoneWarehouses: React.FC = pr /> undefined} diff --git a/src/shipping/urls.ts b/src/shipping/urls.ts index be4d3d316..c9dc4d062 100644 --- a/src/shipping/urls.ts +++ b/src/shipping/urls.ts @@ -20,6 +20,7 @@ export const shippingZonePath = (id: string) => urlJoin(shippingZonesListPath, id); export type ShippingZoneUrlDialog = | "add-rate" + | "add-warehouse" | "assign-country" | "edit-rate" | "remove" diff --git a/src/shipping/views/ShippingZoneDetails/index.tsx b/src/shipping/views/ShippingZoneDetails/index.tsx index 451760a84..9350e8165 100644 --- a/src/shipping/views/ShippingZoneDetails/index.tsx +++ b/src/shipping/views/ShippingZoneDetails/index.tsx @@ -176,6 +176,7 @@ const ShippingZoneDetails: React.FC = ({ }) } onSubmit={handleSubmit} + onWarehouseAdd={() => openModal("add-warehouse")} onWeightRateAdd={() => openModal("add-rate", { type: ShippingMethodTypeEnum.WEIGHT