Add warehouse create action button

This commit is contained in:
dominik-zeglen 2020-02-10 17:07:17 +01:00
parent 3d838d8428
commit 60ec16961c
9 changed files with 108 additions and 9 deletions

View file

@ -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<FetchMoreProps> {
add: MultiAutocompleteActionType;
allowCustomValues?: boolean;
displayValues: MultiAutocompleteChoiceType[];
error?: boolean;
@ -166,6 +168,13 @@ const MultiAutocompleteSelectFieldComponent: React.FC<MultiAutocompleteSelectFie
/>
{isOpen && (!!inputValue || !!choices.length) && (
<MultiAutocompleteSelectFieldContent
add={{
...add,
onClick: () => {
add.onClick();
closeMenu();
}
}}
choices={choices.filter(
choice => !value.includes(choice.value)
)}

View file

@ -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<FetchMoreProps> {
add: MultiAutocompleteActionType;
choices: MultiAutocompleteChoiceType[];
displayCustomValue: boolean;
displayValues: MultiAutocompleteChoiceType[];
@ -145,6 +151,7 @@ function getChoiceIndex(
const MultiAutocompleteSelectFieldContent: React.FC<MultiAutocompleteSelectFieldContentProps> = props => {
const {
add,
choices,
displayCustomValue,
displayValues,
@ -156,6 +163,10 @@ const MultiAutocompleteSelectFieldContent: React.FC<MultiAutocompleteSelectField
onFetchMore
} = props;
if (!!add && !!displayCustomValue) {
throw new Error("Add and custom value cannot be displayed simultaneously");
}
const classes = useStyles(props);
const anchor = React.useRef<HTMLDivElement>();
const scrollPosition = useElementScroll(anchor);
@ -183,6 +194,20 @@ const MultiAutocompleteSelectFieldContent: React.FC<MultiAutocompleteSelectField
displayValues.length > 0 ||
displayCustomValue ? (
<>
{add && (
<MenuItem
className={classes.menuItem}
component="div"
{...getItemProps({
item: inputValue
})}
data-tc="multiautocomplete-select-option-add"
onClick={add.onClick}
>
<AddIcon color="primary" className={classes.addIcon} />
<Typography color="primary">{add.label}</Typography>
</MenuItem>
)}
{displayCustomValue && (
<MenuItem
className={classes.menuItem}

View file

@ -69,6 +69,7 @@ const Story: React.FC<Partial<
};
const contentProps: SingleAutocompleteSelectFieldContentProps = {
add: undefined,
choices: suggestions.slice(0, 10),
displayCustomValue: false,
emptyOption: false,
@ -88,6 +89,15 @@ storiesOf("Generics / Select with autocomplete", module)
.add("default", () => (
<SingleAutocompleteSelectFieldContent {...contentProps} />
))
.add("with add", () => (
<SingleAutocompleteSelectFieldContent
{...contentProps}
add={{
label: "Add New Collection",
onClick: () => undefined
}}
/>
))
.add("can load more", () => (
<SingleAutocompleteSelectFieldContent {...contentProps} hasMore={true} />
))

View file

@ -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<FetchMoreProps> {
add: SingleAutocompleteActionType;
error?: boolean;
name: string;
displayValue: string;
@ -47,6 +49,7 @@ const DebounceAutocomplete: React.ComponentType<DebounceProps<
const SingleAutocompleteSelectFieldComponent: React.FC<SingleAutocompleteSelectFieldProps> = props => {
const {
add,
allowCustomValues,
choices,
disabled,
@ -144,6 +147,13 @@ const SingleAutocompleteSelectFieldComponent: React.FC<SingleAutocompleteSelectF
/>
{isOpen && (!!inputValue || !!choices.length) && (
<SingleAutocompleteSelectFieldContent
add={{
...add,
onClick: () => {
add.onClick();
closeMenu();
}
}}
choices={choices}
displayCustomValue={displayCustomValue}
emptyOption={emptyOption}

View file

@ -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<FetchMoreProps> {
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<SingleAutocompleteSelectFieldContentProps> = 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<HTMLDivElement>();
const scrollPosition = useElementScroll(anchor);
@ -164,6 +181,20 @@ const SingleAutocompleteSelectFieldContent: React.FC<
</Typography>
</MenuItem>
)}
{add && (
<MenuItem
className={classes.menuItem}
component="div"
{...getItemProps({
item: inputValue
})}
data-tc="singleautocomplete-select-option-add"
onClick={add.onClick}
>
<Add color="primary" className={classes.add} />
<Typography color="primary">{add.label}</Typography>
</MenuItem>
)}
{displayCustomValue && (
<MenuItem
className={classes.menuItem}
@ -184,14 +215,14 @@ const SingleAutocompleteSelectFieldContent: React.FC<
/>
</MenuItem>
)}
{choices.length > 0 && displayCustomValue && (
{choices.length > 0 && (!!add || displayCustomValue) && (
<Hr className={classes.hr} />
)}
{choices.map((suggestion, index) => {
const choiceIndex = getChoiceIndex(
index,
emptyOption,
displayCustomValue
!!add || displayCustomValue
);
return (

View file

@ -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<ShippingZoneDetailsPageProps> = ({
onPriceRateEdit,
onRateRemove,
onSubmit,
onWarehouseAdd,
onWeightRateAdd,
onWeightRateEdit,
saveButtonBarState,
@ -165,9 +167,10 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
displayValue={warehouseDisplayValues}
hasMore={false}
loading={false}
warehouses={warehouseChoices}
onChange={handleWarehouseChange}
onFetchMore={() => undefined}
warehouses={warehouseChoices}
onWarehouseAdd={onWarehouseAdd}
/>
</div>
</Grid>

View file

@ -18,6 +18,7 @@ interface ShippingZonewWarehousesProps extends FetchMoreProps {
displayValue: MultiAutocompleteChoiceType[];
warehouses: MultiAutocompleteChoiceType[];
onChange: FormChange;
onWarehouseAdd: () => void;
}
export const ShippingZoneWarehouses: React.FC<ShippingZonewWarehousesProps> = props => {
@ -26,9 +27,10 @@ export const ShippingZoneWarehouses: React.FC<ShippingZonewWarehousesProps> = pr
displayValue,
hasMore,
loading,
warehouses,
onChange,
onFetchMore,
warehouses
onWarehouseAdd
} = props;
const intl = useIntl();
@ -42,6 +44,13 @@ export const ShippingZoneWarehouses: React.FC<ShippingZonewWarehousesProps> = pr
/>
<CardContent>
<MultiAutocompleteSelectField
add={{
label: intl.formatMessage({
defaultMessage: "Add New Warehouse",
description: "button"
}),
onClick: onWarehouseAdd
}}
choices={warehouses}
displayValues={displayValue}
fetchChoices={() => undefined}

View file

@ -20,6 +20,7 @@ export const shippingZonePath = (id: string) =>
urlJoin(shippingZonesListPath, id);
export type ShippingZoneUrlDialog =
| "add-rate"
| "add-warehouse"
| "assign-country"
| "edit-rate"
| "remove"

View file

@ -176,6 +176,7 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
})
}
onSubmit={handleSubmit}
onWarehouseAdd={() => openModal("add-warehouse")}
onWeightRateAdd={() =>
openModal("add-rate", {
type: ShippingMethodTypeEnum.WEIGHT