From 414f6d7a3d87283eb0700692587f4bbd136b310c Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Thu, 30 Jan 2020 12:46:35 +0100
Subject: [PATCH 01/88] Add warehouse list view
---
.../Navigator/modes/default/views.ts | 5 +
src/config.ts | 4 +
src/configuration/index.tsx | 39 +++-
src/hooks/useListSettings.ts | 10 +
src/icons/Warehouses.tsx | 16 ++
src/index.tsx | 7 +
src/intl.ts | 4 +
src/products/types/StockFragment.ts | 22 +++
src/types.ts | 1 +
src/types/globalTypes.ts | 13 ++
.../WarehouseList/WarehouseList.tsx | 178 ++++++++++++++++++
.../components/WarehouseList/index.ts | 2 +
.../WarehouseListPage.stories.tsx | 36 ++++
.../WarehouseListPage/WarehouseListPage.tsx | 104 ++++++++++
.../components/WarehouseListPage/index.ts | 2 +
src/warehouses/fixtures.ts | 53 ++++++
src/warehouses/index.tsx | 66 +++++++
src/warehouses/queries.ts | 55 ++++++
src/warehouses/types/WarehouseFragment.ts | 30 +++
src/warehouses/types/WarehouseList.ts | 64 +++++++
src/warehouses/urls.ts | 42 +++++
.../views/WarehouseList/WarehouseList.tsx | 160 ++++++++++++++++
src/warehouses/views/WarehouseList/filters.ts | 31 +++
src/warehouses/views/WarehouseList/index.ts | 2 +
src/warehouses/views/WarehouseList/sort.ts | 18 ++
25 files changed, 954 insertions(+), 10 deletions(-)
create mode 100644 src/icons/Warehouses.tsx
create mode 100644 src/products/types/StockFragment.ts
create mode 100644 src/warehouses/components/WarehouseList/WarehouseList.tsx
create mode 100644 src/warehouses/components/WarehouseList/index.ts
create mode 100644 src/warehouses/components/WarehouseListPage/WarehouseListPage.stories.tsx
create mode 100644 src/warehouses/components/WarehouseListPage/WarehouseListPage.tsx
create mode 100644 src/warehouses/components/WarehouseListPage/index.ts
create mode 100644 src/warehouses/fixtures.ts
create mode 100644 src/warehouses/index.tsx
create mode 100644 src/warehouses/queries.ts
create mode 100644 src/warehouses/types/WarehouseFragment.ts
create mode 100644 src/warehouses/types/WarehouseList.ts
create mode 100644 src/warehouses/urls.ts
create mode 100644 src/warehouses/views/WarehouseList/WarehouseList.tsx
create mode 100644 src/warehouses/views/WarehouseList/filters.ts
create mode 100644 src/warehouses/views/WarehouseList/index.ts
create mode 100644 src/warehouses/views/WarehouseList/sort.ts
diff --git a/src/components/Navigator/modes/default/views.ts b/src/components/Navigator/modes/default/views.ts
index c2cea32c5..c489ce6fb 100644
--- a/src/components/Navigator/modes/default/views.ts
+++ b/src/components/Navigator/modes/default/views.ts
@@ -21,6 +21,7 @@ import { staffListUrl } from "@saleor/staff/urls";
import { countryListUrl } from "@saleor/taxes/urls";
import { languageListUrl } from "@saleor/translations/urls";
import { webhookListUrl } from "@saleor/webhooks/urls";
+import { warehouseListUrl } from "@saleor/warehouses/urls";
import { QuickSearchActionInput } from "../../types";
interface View {
@@ -116,6 +117,10 @@ function searchInViews(
{
label: intl.formatMessage(sectionNames.webhooks),
url: webhookListUrl()
+ },
+ {
+ label: intl.formatMessage(sectionNames.warehouses),
+ url: warehouseListUrl()
}
];
diff --git a/src/config.ts b/src/config.ts
index 83d7fcd5a..90b81e7c8 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -34,6 +34,7 @@ export interface AppListViewSettings {
[ListViews.STAFF_MEMBERS_LIST]: ListSettings;
[ListViews.PERMISSION_GROUP_LIST]: ListSettings;
[ListViews.VOUCHER_LIST]: ListSettings;
+ [ListViews.WAREHOUSE_LIST]: ListSettings;
[ListViews.WEBHOOK_LIST]: ListSettings;
}
export const defaultListSettings: AppListViewSettings = {
@@ -80,6 +81,9 @@ export const defaultListSettings: AppListViewSettings = {
[ListViews.VOUCHER_LIST]: {
rowNumber: PAGINATE_BY
},
+ [ListViews.WAREHOUSE_LIST]: {
+ rowNumber: PAGINATE_BY
+ },
[ListViews.WEBHOOK_LIST]: {
rowNumber: PAGINATE_BY
}
diff --git a/src/configuration/index.tsx b/src/configuration/index.tsx
index 6b1c17a84..e597ad17c 100644
--- a/src/configuration/index.tsx
+++ b/src/configuration/index.tsx
@@ -31,6 +31,8 @@ import { permissionGroupListUrl } from "@saleor/permissionGroups/urls";
import { taxSection } from "@saleor/taxes/urls";
import { PermissionEnum } from "@saleor/types/globalTypes";
import { webhookListUrl } from "@saleor/webhooks/urls";
+import Warehouses from "@saleor/icons/Warehouses";
+import { warehouseSection } from "@saleor/warehouses/urls";
import ConfigurationPage, { MenuSection } from "./ConfigurationPage";
export function createConfigurationMenu(intl: IntlShape): MenuSection[] {
@@ -67,16 +69,6 @@ export function createConfigurationMenu(intl: IntlShape): MenuSection[] {
defaultMessage: "Product Settings"
}),
menuItems: [
- {
- description: intl.formatMessage({
- defaultMessage: "Manage how you ship out orders",
- id: "configurationMenuShipping"
- }),
- icon: ,
- permission: PermissionEnum.MANAGE_SHIPPING,
- title: intl.formatMessage(sectionNames.shipping),
- url: shippingZonesListUrl()
- },
{
description: intl.formatMessage({
defaultMessage: "Manage how your store charges tax",
@@ -117,6 +109,33 @@ export function createConfigurationMenu(intl: IntlShape): MenuSection[] {
}
]
},
+ {
+ label: intl.formatMessage({
+ defaultMessage: "Product Settings"
+ }),
+ menuItems: [
+ {
+ description: intl.formatMessage({
+ defaultMessage: "Manage how you ship out orders",
+ id: "configurationMenuShipping"
+ }),
+ icon: ,
+ permission: PermissionEnum.MANAGE_SHIPPING,
+ title: intl.formatMessage(sectionNames.shipping),
+ url: shippingZonesListUrl()
+ },
+ {
+ description: intl.formatMessage({
+ defaultMessage: "Manage and update your warehouse information",
+ id: "configurationMenuWarehouses"
+ }),
+ icon: ,
+ permission: PermissionEnum.MANAGE_PRODUCTS,
+ title: intl.formatMessage(sectionNames.warehouses),
+ url: warehouseSection
+ }
+ ]
+ },
{
label: intl.formatMessage({
defaultMessage: "Miscellaneous"
diff --git a/src/hooks/useListSettings.ts b/src/hooks/useListSettings.ts
index 75c1afd86..cac29fca9 100644
--- a/src/hooks/useListSettings.ts
+++ b/src/hooks/useListSettings.ts
@@ -1,3 +1,4 @@
+import { useEffect } from "react";
import useLocalStorage from "@saleor/hooks/useLocalStorage";
import { AppListViewSettings, defaultListSettings } from "./../config";
import { ListSettings, ListViews } from "./../types";
@@ -14,6 +15,15 @@ export default function useListSettings(
defaultListSettings
);
+ useEffect(() => {
+ if (settings[listName] === undefined) {
+ setListSettings(settings => ({
+ ...settings,
+ [listName]: defaultListSettings[listName]
+ }));
+ }
+ }, []);
+
const updateListSettings = (key: keyof ListSettings, value: any) =>
setListSettings(settings => ({
...settings,
diff --git a/src/icons/Warehouses.tsx b/src/icons/Warehouses.tsx
new file mode 100644
index 000000000..56170523f
--- /dev/null
+++ b/src/icons/Warehouses.tsx
@@ -0,0 +1,16 @@
+import createSvgIcon from "@material-ui/icons/utils/createSvgIcon";
+import React from "react";
+
+const Warehouses = createSvgIcon(
+ <>
+
+ >,
+ "Warehouses"
+);
+
+export default Warehouses;
diff --git a/src/index.tsx b/src/index.tsx
index db050df08..12279e63b 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -55,6 +55,8 @@ import TaxesSection from "./taxes";
import TranslationsSection from "./translations";
import { PermissionEnum } from "./types/globalTypes";
import WebhooksSection from "./webhooks";
+import { warehouseSection } from "./warehouses/urls";
+import WarehouseSection from "./warehouses";
interface ResponseError extends ErrorResponse {
networkError?: Error & {
@@ -263,6 +265,11 @@ const Routes: React.FC = () => {
path={serviceSection}
component={ServiceSection}
/>
+
{createConfigurationMenu(intl).filter(menu =>
menu.menuItems.map(item =>
hasPermission(item.permission, user)
diff --git a/src/intl.ts b/src/intl.ts
index 8b7328cff..2f8841205 100644
--- a/src/intl.ts
+++ b/src/intl.ts
@@ -224,6 +224,10 @@ export const sectionNames = defineMessages({
defaultMessage: "Vouchers",
description: "vouchers section name"
},
+ warehouses: {
+ defaultMessage: "Warehouses",
+ description: "warehouses section name"
+ },
webhooks: {
defaultMessage: "Webhooks",
description: "webhooks section name"
diff --git a/src/products/types/StockFragment.ts b/src/products/types/StockFragment.ts
new file mode 100644
index 000000000..7aba2f87d
--- /dev/null
+++ b/src/products/types/StockFragment.ts
@@ -0,0 +1,22 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+// ====================================================
+// GraphQL fragment: StockFragment
+// ====================================================
+
+export interface StockFragment_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
+export interface StockFragment {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+ quantityAllocated: number;
+ stockQuantity: number;
+ warehouse: StockFragment_warehouse;
+}
diff --git a/src/types.ts b/src/types.ts
index 3db6bcc62..e3f2014a8 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -37,6 +37,7 @@ export enum ListViews {
SHIPPING_METHODS_LIST = "SHIPPING_METHODS_LIST",
STAFF_MEMBERS_LIST = "STAFF_MEMBERS_LIST",
VOUCHER_LIST = "VOUCHER_LIST",
+ WAREHOUSE_LIST = "WAREHOUSE_LIST",
WEBHOOK_LIST = "WEBHOOK_LIST"
}
diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts
index 72cec5cbe..48507817e 100644
--- a/src/types/globalTypes.ts
+++ b/src/types/globalTypes.ts
@@ -746,6 +746,10 @@ export enum VoucherTypeEnum {
SPECIFIC_PRODUCT = "SPECIFIC_PRODUCT",
}
+export enum WarehouseSortField {
+ NAME = "NAME",
+}
+
export enum WebhookErrorCode {
GRAPHQL_ERROR = "GRAPHQL_ERROR",
INVALID = "INVALID",
@@ -1415,6 +1419,15 @@ export interface VoucherSortingInput {
field: VoucherSortField;
}
+export interface WarehouseFilterInput {
+ search?: string | null;
+}
+
+export interface WarehouseSortingInput {
+ direction: OrderDirection;
+ field: WarehouseSortField;
+}
+
export interface WebhookCreateInput {
name?: string | null;
targetUrl?: string | null;
diff --git a/src/warehouses/components/WarehouseList/WarehouseList.tsx b/src/warehouses/components/WarehouseList/WarehouseList.tsx
new file mode 100644
index 000000000..6220a8951
--- /dev/null
+++ b/src/warehouses/components/WarehouseList/WarehouseList.tsx
@@ -0,0 +1,178 @@
+import { makeStyles } from "@material-ui/core/styles";
+import TableBody from "@material-ui/core/TableBody";
+import TableCell from "@material-ui/core/TableCell";
+import TableFooter from "@material-ui/core/TableFooter";
+import TableRow from "@material-ui/core/TableRow";
+import TableHead from "@material-ui/core/TableHead";
+import React from "react";
+import { FormattedMessage } from "react-intl";
+import IconButton from "@material-ui/core/IconButton";
+import DeleteIcon from "@material-ui/icons/Delete";
+import EditIcon from "@material-ui/icons/Edit";
+
+import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment";
+import ResponsiveTable from "@saleor/components/ResponsiveTable";
+import Skeleton from "@saleor/components/Skeleton";
+import TablePagination from "@saleor/components/TablePagination";
+import { maybe, renderCollection } from "@saleor/misc";
+import { ListProps, SortPage } from "@saleor/types";
+import { WarehouseListUrlSortField } from "@saleor/warehouses/urls";
+import TableCellHeader from "@saleor/components/TableCellHeader";
+import { getArrowDirection } from "@saleor/utils/sort";
+
+const useStyles = makeStyles(
+ theme => ({
+ [theme.breakpoints.up("lg")]: {
+ colActions: {
+ width: 160
+ },
+ colName: {
+ width: 400
+ },
+ colZones: {
+ width: "auto"
+ }
+ },
+ actions: {
+ alignItems: "center",
+ display: "flex",
+ justifyContent: "flex-end",
+ position: "relative",
+ right: -theme.spacing(2)
+ },
+ colActions: {
+ textAlign: "right"
+ },
+ colName: {
+ paddingLeft: 0
+ },
+ colZones: {
+ paddingLeft: 0
+ },
+ tableRow: {
+ cursor: "pointer"
+ }
+ }),
+ { name: "WarehouseList" }
+);
+
+interface WarehouseListProps
+ extends ListProps,
+ SortPage {
+ warehouses: WarehouseFragment[];
+ onAdd: () => void;
+ onRemove: (id: string) => void;
+}
+
+const numberOfColumns = 3;
+
+const WarehouseList: React.FC = props => {
+ const {
+ warehouses,
+ disabled,
+ settings,
+ sort,
+ pageInfo,
+ onNextPage,
+ onPreviousPage,
+ onUpdateListSettings,
+ onRemove,
+ onRowClick,
+ onSort
+ } = props;
+
+ const classes = useStyles(props);
+
+ return (
+
+
+
+ onSort(WarehouseListUrlSortField.name)}
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {renderCollection(
+ warehouses,
+ warehouse => (
+ warehouse.id)}
+ >
+
+ {maybe(() => warehouse.name, )}
+
+
+ {maybe(
+ () =>
+ warehouse.shippingZones.edges
+ .map(edge => edge.node.name)
+ .join(", "),
+
+ )}
+
+
+
+
+
+
+ onRemove(warehouse.id)}
+ >
+
+
+
+
+
+ ),
+ () => (
+
+
+
+
+
+ )
+ )}
+
+
+ );
+};
+
+WarehouseList.displayName = "WarehouseList";
+export default WarehouseList;
diff --git a/src/warehouses/components/WarehouseList/index.ts b/src/warehouses/components/WarehouseList/index.ts
new file mode 100644
index 000000000..4c64e0c2c
--- /dev/null
+++ b/src/warehouses/components/WarehouseList/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseList";
+export * from "./WarehouseList";
diff --git a/src/warehouses/components/WarehouseListPage/WarehouseListPage.stories.tsx b/src/warehouses/components/WarehouseListPage/WarehouseListPage.stories.tsx
new file mode 100644
index 000000000..7b163fd66
--- /dev/null
+++ b/src/warehouses/components/WarehouseListPage/WarehouseListPage.stories.tsx
@@ -0,0 +1,36 @@
+import { storiesOf } from "@storybook/react";
+import React from "react";
+
+import {
+ pageListProps,
+ tabPageProps,
+ sortPageProps,
+ searchPageProps
+} from "@saleor/fixtures";
+import WarehouseListPage, {
+ WarehouseListPageProps
+} from "@saleor/warehouses/components/WarehouseListPage";
+import Decorator from "@saleor/storybook/Decorator";
+import { WarehouseListUrlSortField } from "@saleor/warehouses/urls";
+import { warehouseList } from "../../fixtures";
+
+const props: WarehouseListPageProps = {
+ ...pageListProps.default,
+ ...searchPageProps,
+ ...sortPageProps,
+ ...tabPageProps,
+ onBack: () => undefined,
+ sort: {
+ ...sortPageProps.sort,
+ sort: WarehouseListUrlSortField.name
+ },
+ warehouses: warehouseList
+};
+
+storiesOf("Views / Warehouses / Warehouse list", module)
+ .addDecorator(Decorator)
+ .add("default", () => )
+ .add("loading", () => (
+
+ ))
+ .add("no data", () => );
diff --git a/src/warehouses/components/WarehouseListPage/WarehouseListPage.tsx b/src/warehouses/components/WarehouseListPage/WarehouseListPage.tsx
new file mode 100644
index 000000000..05c66b060
--- /dev/null
+++ b/src/warehouses/components/WarehouseListPage/WarehouseListPage.tsx
@@ -0,0 +1,104 @@
+import Button from "@material-ui/core/Button";
+import Card from "@material-ui/core/Card";
+import React from "react";
+import { FormattedMessage, useIntl } from "react-intl";
+
+import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment";
+import Container from "@saleor/components/Container";
+import PageHeader from "@saleor/components/PageHeader";
+import SearchBar from "@saleor/components/SearchBar";
+import { sectionNames } from "@saleor/intl";
+import {
+ PageListProps,
+ SearchPageProps,
+ TabPageProps,
+ SortPage
+} from "@saleor/types";
+import { WarehouseListUrlSortField } from "@saleor/warehouses/urls";
+import AppHeader from "@saleor/components/AppHeader";
+import WarehouseList from "../WarehouseList";
+
+export interface WarehouseListPageProps
+ extends PageListProps,
+ SearchPageProps,
+ SortPage,
+ TabPageProps {
+ warehouses: WarehouseFragment[];
+ onBack: () => void;
+ onRemove: (id: string) => void;
+}
+
+export const WarehouseListPage: React.FC = ({
+ warehouses,
+ currentTab,
+ disabled,
+ initialSearch,
+ pageInfo,
+ settings,
+ tabs,
+ onAdd,
+ onAll,
+ onBack,
+ onNextPage,
+ onPreviousPage,
+ onRemove,
+ onRowClick,
+ onSearchChange,
+ onTabChange,
+ onTabDelete,
+ onTabSave,
+ onUpdateListSettings,
+ ...listProps
+}) => {
+ const intl = useIntl();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+WarehouseListPage.displayName = "WarehouseListPage";
+export default WarehouseListPage;
diff --git a/src/warehouses/components/WarehouseListPage/index.ts b/src/warehouses/components/WarehouseListPage/index.ts
new file mode 100644
index 000000000..1bce1dd38
--- /dev/null
+++ b/src/warehouses/components/WarehouseListPage/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseListPage";
+export * from "./WarehouseListPage";
diff --git a/src/warehouses/fixtures.ts b/src/warehouses/fixtures.ts
new file mode 100644
index 000000000..e393c9c11
--- /dev/null
+++ b/src/warehouses/fixtures.ts
@@ -0,0 +1,53 @@
+import { shippingZones } from "../shipping/fixtures";
+import { WarehouseList_warehouses_edges_node } from "./types/WarehouseList";
+
+export const warehouseList: WarehouseList_warehouses_edges_node[] = [
+ {
+ __typename: "Warehouse",
+ id: "V2FyZWhvdXNlOmEzMThmMGZlLTcwMmYtNDNjYy1hYmFjLWZmZmMzN2Y3ZTliYw==",
+ name: "C our wares",
+ shippingZones: {
+ __typename: "ShippingZoneCountableConnection",
+ edges: shippingZones.map(node => ({
+ __typename: "ShippingZoneCountableEdge",
+ node
+ }))
+ }
+ },
+ {
+ __typename: "Warehouse",
+ id: "V2FyZWhvdXNlOjJmN2UyOTlmLWEwMzMtNDhjZS1iYmM5LTFkZDM4NjU2ZjMwYw==",
+ name: "Be stocked",
+ shippingZones: {
+ __typename: "ShippingZoneCountableConnection",
+ edges: shippingZones.map(node => ({
+ __typename: "ShippingZoneCountableEdge",
+ node
+ }))
+ }
+ },
+ {
+ __typename: "Warehouse",
+ id: "V2FyZWhvdXNlOmM0ZmQ3Nzc0LWZlMjYtNDE1YS1hYjk1LWFlYTFjMjI0NTgwNg==",
+ name: "A Warehouse",
+ shippingZones: {
+ __typename: "ShippingZoneCountableConnection",
+ edges: shippingZones.map(node => ({
+ __typename: "ShippingZoneCountableEdge",
+ node
+ }))
+ }
+ },
+ {
+ __typename: "Warehouse",
+ id: "V2FyZWhvdXNlOmNlMmNiZDhhLWRkYmQtNDhiNS1hM2UxLTNmZGVkZGI5MWZkMg==",
+ name: "Darkwares",
+ shippingZones: {
+ __typename: "ShippingZoneCountableConnection",
+ edges: shippingZones.map(node => ({
+ __typename: "ShippingZoneCountableEdge",
+ node
+ }))
+ }
+ }
+];
diff --git a/src/warehouses/index.tsx b/src/warehouses/index.tsx
new file mode 100644
index 000000000..8d06f0040
--- /dev/null
+++ b/src/warehouses/index.tsx
@@ -0,0 +1,66 @@
+import { parse as parseQs } from "qs";
+import React from "react";
+import { Route, RouteComponentProps, Switch } from "react-router-dom";
+
+import { sectionNames } from "@saleor/intl";
+import { useIntl } from "react-intl";
+import { asSortParams } from "@saleor/utils/sort";
+import { WindowTitle } from "../components/WindowTitle";
+import {
+ // warehouseAddPath,
+ // WarehouseAddUrlQueryParams,
+ warehouseListPath,
+ WarehouseListUrlQueryParams,
+ // warehousePath,
+ // WarehouseUrlQueryParams,
+ WarehouseListUrlSortField
+} from "./urls";
+// import WarehouseCreateComponent from "./views/WarehouseCreate";
+// import WarehouseDetailsComponent from "./views/WarehouseDetails";
+import WarehouseListComponent from "./views/WarehouseList";
+
+const WarehouseList: React.FC = ({ location }) => {
+ const qs = parseQs(location.search.substr(1));
+ const params: WarehouseListUrlQueryParams = asSortParams(
+ qs,
+ WarehouseListUrlSortField
+ );
+
+ return ;
+};
+
+// const WarehouseCreate: React.FC> = ({ location }) => {
+// const qs = parseQs(location.search.substr(1));
+// const params: WarehouseAddUrlQueryParams = qs;
+// return ;
+// };
+
+// const WarehouseDetails: React.FC> = ({
+// location,
+// match
+// }) => {
+// const qs = parseQs(location.search.substr(1));
+// const params: WarehouseUrlQueryParams = qs;
+// return (
+//
+// );
+// };
+
+export const WarehouseSection: React.FC = () => {
+ const intl = useIntl();
+
+ return (
+ <>
+
+
+
+ {/*
+ */}
+
+ >
+ );
+};
+export default WarehouseSection;
diff --git a/src/warehouses/queries.ts b/src/warehouses/queries.ts
new file mode 100644
index 000000000..1cfd8b5ac
--- /dev/null
+++ b/src/warehouses/queries.ts
@@ -0,0 +1,55 @@
+import gql from "graphql-tag";
+
+import makeQuery from "@saleor/hooks/makeQuery";
+import { pageInfoFragment } from "@saleor/queries";
+import { WarehouseList, WarehouseListVariables } from "./types/WarehouseList";
+
+export const warehouseFragment = gql`
+ fragment WarehouseFragment on Warehouse {
+ id
+ name
+ shippingZones(first: 100) {
+ edges {
+ node {
+ id
+ name
+ }
+ }
+ }
+ }
+`;
+
+const warehouseList = gql`
+ ${warehouseFragment}
+ ${pageInfoFragment}
+ query WarehouseList(
+ $first: Int
+ $after: String
+ $last: Int
+ $before: String
+ $filter: WarehouseFilterInput
+ $sort: WarehouseSortingInput
+ ) {
+ warehouses(
+ before: $before
+ after: $after
+ first: $first
+ last: $last
+ filter: $filter
+ sortBy: $sort
+ ) {
+ edges {
+ node {
+ ...WarehouseFragment
+ }
+ }
+ pageInfo {
+ ...PageInfoFragment
+ }
+ }
+ }
+`;
+export const useWarehouseList = makeQuery<
+ WarehouseList,
+ WarehouseListVariables
+>(warehouseList);
diff --git a/src/warehouses/types/WarehouseFragment.ts b/src/warehouses/types/WarehouseFragment.ts
new file mode 100644
index 000000000..1f6e19e37
--- /dev/null
+++ b/src/warehouses/types/WarehouseFragment.ts
@@ -0,0 +1,30 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+// ====================================================
+// GraphQL fragment: WarehouseFragment
+// ====================================================
+
+export interface WarehouseFragment_shippingZones_edges_node {
+ __typename: "ShippingZone";
+ id: string;
+ name: string;
+}
+
+export interface WarehouseFragment_shippingZones_edges {
+ __typename: "ShippingZoneCountableEdge";
+ node: WarehouseFragment_shippingZones_edges_node;
+}
+
+export interface WarehouseFragment_shippingZones {
+ __typename: "ShippingZoneCountableConnection";
+ edges: WarehouseFragment_shippingZones_edges[];
+}
+
+export interface WarehouseFragment {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+ shippingZones: WarehouseFragment_shippingZones;
+}
diff --git a/src/warehouses/types/WarehouseList.ts b/src/warehouses/types/WarehouseList.ts
new file mode 100644
index 000000000..00e3b29e4
--- /dev/null
+++ b/src/warehouses/types/WarehouseList.ts
@@ -0,0 +1,64 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+import { WarehouseFilterInput, WarehouseSortingInput } from "./../../types/globalTypes";
+
+// ====================================================
+// GraphQL query operation: WarehouseList
+// ====================================================
+
+export interface WarehouseList_warehouses_edges_node_shippingZones_edges_node {
+ __typename: "ShippingZone";
+ id: string;
+ name: string;
+}
+
+export interface WarehouseList_warehouses_edges_node_shippingZones_edges {
+ __typename: "ShippingZoneCountableEdge";
+ node: WarehouseList_warehouses_edges_node_shippingZones_edges_node;
+}
+
+export interface WarehouseList_warehouses_edges_node_shippingZones {
+ __typename: "ShippingZoneCountableConnection";
+ edges: WarehouseList_warehouses_edges_node_shippingZones_edges[];
+}
+
+export interface WarehouseList_warehouses_edges_node {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+ shippingZones: WarehouseList_warehouses_edges_node_shippingZones;
+}
+
+export interface WarehouseList_warehouses_edges {
+ __typename: "WarehouseCountableEdge";
+ node: WarehouseList_warehouses_edges_node;
+}
+
+export interface WarehouseList_warehouses_pageInfo {
+ __typename: "PageInfo";
+ endCursor: string | null;
+ hasNextPage: boolean;
+ hasPreviousPage: boolean;
+ startCursor: string | null;
+}
+
+export interface WarehouseList_warehouses {
+ __typename: "WarehouseCountableConnection";
+ edges: WarehouseList_warehouses_edges[];
+ pageInfo: WarehouseList_warehouses_pageInfo;
+}
+
+export interface WarehouseList {
+ warehouses: WarehouseList_warehouses | null;
+}
+
+export interface WarehouseListVariables {
+ first?: number | null;
+ after?: string | null;
+ last?: number | null;
+ before?: string | null;
+ filter?: WarehouseFilterInput | null;
+ sort?: WarehouseSortingInput | null;
+}
diff --git a/src/warehouses/urls.ts b/src/warehouses/urls.ts
new file mode 100644
index 000000000..9864e5077
--- /dev/null
+++ b/src/warehouses/urls.ts
@@ -0,0 +1,42 @@
+import { stringify as stringifyQs } from "qs";
+import urlJoin from "url-join";
+
+import {
+ ActiveTab,
+ Dialog,
+ Filters,
+ Pagination,
+ SingleAction,
+ TabActionDialog,
+ Sort
+} from "../types";
+
+export const warehouseSection = "/warehouses/";
+
+export const warehouseListPath = warehouseSection;
+export enum WarehouseListUrlFiltersEnum {
+ query = "query"
+}
+export type WarehouseListUrlFilters = Filters;
+export type WarehouseListUrlDialog = "remove" | TabActionDialog;
+export enum WarehouseListUrlSortField {
+ name = "name"
+}
+export type WarehouseListUrlSort = Sort;
+export type WarehouseListUrlQueryParams = ActiveTab &
+ Dialog &
+ Pagination &
+ WarehouseListUrlFilters &
+ WarehouseListUrlSort &
+ SingleAction;
+export const warehouseListUrl = (params?: WarehouseListUrlQueryParams) =>
+ warehouseListPath + "?" + stringifyQs(params);
+
+export const warehousePath = (id: string) => urlJoin(warehouseSection, id);
+export type WarehouseUrlDialog = "remove";
+export type WarehouseUrlQueryParams = Dialog & SingleAction;
+export const warehouseUrl = (id: string, params?: WarehouseUrlQueryParams) =>
+ warehousePath(encodeURIComponent(id)) + "?" + stringifyQs(params);
+
+export const warehouseAddPath = urlJoin(warehouseSection, "add");
+export const warehouseAddUrl = warehouseAddPath;
diff --git a/src/warehouses/views/WarehouseList/WarehouseList.tsx b/src/warehouses/views/WarehouseList/WarehouseList.tsx
new file mode 100644
index 000000000..bc119d669
--- /dev/null
+++ b/src/warehouses/views/WarehouseList/WarehouseList.tsx
@@ -0,0 +1,160 @@
+import React from "react";
+import { useIntl } from "react-intl";
+
+import {
+ WarehouseListUrlQueryParams,
+ warehouseUrl,
+ WarehouseListUrlDialog,
+ warehouseListUrl,
+ warehouseAddUrl
+} from "@saleor/warehouses/urls";
+import useNavigator from "@saleor/hooks/useNavigator";
+import { useWarehouseList } from "@saleor/warehouses/queries";
+import usePaginator, {
+ createPaginationState
+} from "@saleor/hooks/usePaginator";
+import useNotifier from "@saleor/hooks/useNotifier";
+import useListSettings from "@saleor/hooks/useListSettings";
+import { ListViews } from "@saleor/types";
+import { WindowTitle } from "@saleor/components/WindowTitle";
+import { sectionNames } from "@saleor/intl";
+import WarehouseListPage from "@saleor/warehouses/components/WarehouseListPage";
+import SaveFilterTabDialog, {
+ SaveFilterTabDialogFormData
+} from "@saleor/components/SaveFilterTabDialog";
+import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog";
+import { maybe } from "@saleor/misc";
+import { getSortParams } from "@saleor/utils/sort";
+import createSortHandler from "@saleor/utils/handlers/sortHandler";
+import createFilterHandlers from "@saleor/utils/handlers/filterHandlers";
+import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
+import { configurationMenuUrl } from "@saleor/configuration";
+import { getSortQueryVariables } from "./sort";
+import {
+ getFilterVariables,
+ getFilterTabs,
+ areFiltersApplied,
+ deleteFilterTab,
+ saveFilterTab,
+ getActiveFilters
+} from "./filters";
+
+export interface WarehouseListProps {
+ params: WarehouseListUrlQueryParams;
+}
+
+const WarehouseList: React.FC = ({ params }) => {
+ const navigate = useNavigator();
+ const notify = useNotifier();
+ const paginate = usePaginator();
+ const { updateListSettings, settings } = useListSettings(
+ ListViews.SALES_LIST
+ );
+ const intl = useIntl();
+
+ const paginationState = createPaginationState(settings.rowNumber, params);
+ const queryVariables = React.useMemo(
+ () => ({
+ ...paginationState,
+ filter: getFilterVariables(params),
+ sort: getSortQueryVariables(params)
+ }),
+ [params]
+ );
+ const { data, loading, refetch } = useWarehouseList({
+ displayLoader: true,
+ variables: queryVariables
+ });
+
+ const tabs = getFilterTabs();
+
+ const currentTab =
+ params.activeTab === undefined
+ ? areFiltersApplied(params)
+ ? tabs.length + 1
+ : 0
+ : parseInt(params.activeTab, 0);
+
+ const [, resetFilters, handleSearchChange] = createFilterHandlers({
+ createUrl: warehouseListUrl,
+ getFilterQueryParam: () => undefined,
+ navigate,
+ params
+ });
+
+ const [openModal, closeModal] = createDialogActionHandlers<
+ WarehouseListUrlDialog,
+ WarehouseListUrlQueryParams
+ >(navigate, warehouseListUrl, params);
+
+ const handleTabChange = (tab: number) =>
+ navigate(
+ warehouseListUrl({
+ activeTab: tab.toString(),
+ ...getFilterTabs()[tab - 1].data
+ })
+ );
+
+ const handleTabDelete = () => {
+ deleteFilterTab(currentTab);
+ navigate(warehouseListUrl());
+ };
+
+ const handleTabSave = (data: SaveFilterTabDialogFormData) => {
+ saveFilterTab(data.name, getActiveFilters(params));
+ handleTabChange(tabs.length + 1);
+ };
+
+ const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
+ maybe(() => data.warehouses.pageInfo),
+ paginationState,
+ params
+ );
+
+ const handleSort = createSortHandler(navigate, warehouseListUrl, params);
+
+ return (
+ <>
+
+ navigate(configurationMenuUrl)}
+ onTabChange={handleTabChange}
+ onTabDelete={() => openModal("delete-search")}
+ onTabSave={() => openModal("save-search")}
+ tabs={tabs.map(tab => tab.name)}
+ warehouses={maybe(() => data.warehouses.edges.map(edge => edge.node))}
+ settings={settings}
+ disabled={loading}
+ pageInfo={pageInfo}
+ onAdd={() => navigate(warehouseAddUrl)}
+ onNextPage={loadNextPage}
+ onPreviousPage={loadPreviousPage}
+ onRemove={() => undefined}
+ onSort={handleSort}
+ onUpdateListSettings={updateListSettings}
+ onRowClick={id => () => navigate(warehouseUrl(id))}
+ sort={getSortParams(params)}
+ />
+
+ tabs[currentTab - 1].name, "...")}
+ />
+ >
+ );
+};
+
+WarehouseList.displayName = "WarehouseList";
+export default WarehouseList;
diff --git a/src/warehouses/views/WarehouseList/filters.ts b/src/warehouses/views/WarehouseList/filters.ts
new file mode 100644
index 000000000..f0e6a19f3
--- /dev/null
+++ b/src/warehouses/views/WarehouseList/filters.ts
@@ -0,0 +1,31 @@
+import { WarehouseFilterInput } from "@saleor/types/globalTypes";
+import {
+ createFilterTabUtils,
+ createFilterUtils
+} from "../../../utils/filters";
+import {
+ WarehouseListUrlFilters,
+ WarehouseListUrlFiltersEnum,
+ WarehouseListUrlQueryParams
+} from "../../urls";
+
+export const WAREHOUSE_FILTERS_KEY = "warehouseFilters";
+
+export function getFilterVariables(
+ params: WarehouseListUrlFilters
+): WarehouseFilterInput {
+ return {
+ search: params.query
+ };
+}
+
+export const {
+ deleteFilterTab,
+ getFilterTabs,
+ saveFilterTab
+} = createFilterTabUtils(WAREHOUSE_FILTERS_KEY);
+
+export const { areFiltersApplied, getActiveFilters } = createFilterUtils<
+ WarehouseListUrlQueryParams,
+ WarehouseListUrlFilters
+>(WarehouseListUrlFiltersEnum);
diff --git a/src/warehouses/views/WarehouseList/index.ts b/src/warehouses/views/WarehouseList/index.ts
new file mode 100644
index 000000000..4c64e0c2c
--- /dev/null
+++ b/src/warehouses/views/WarehouseList/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseList";
+export * from "./WarehouseList";
diff --git a/src/warehouses/views/WarehouseList/sort.ts b/src/warehouses/views/WarehouseList/sort.ts
new file mode 100644
index 000000000..ccf74b0fb
--- /dev/null
+++ b/src/warehouses/views/WarehouseList/sort.ts
@@ -0,0 +1,18 @@
+import { WarehouseListUrlSortField } from "@saleor/warehouses/urls";
+import { WarehouseSortField } from "@saleor/types/globalTypes";
+import { createGetSortQueryVariables } from "@saleor/utils/sort";
+
+export function getSortQueryField(
+ sort: WarehouseListUrlSortField
+): WarehouseSortField {
+ switch (sort) {
+ case WarehouseListUrlSortField.name:
+ return WarehouseSortField.NAME;
+ default:
+ return undefined;
+ }
+}
+
+export const getSortQueryVariables = createGetSortQueryVariables(
+ getSortQueryField
+);
From fd1f728415a4cd2258edb1a4b458b5b3c6c81ae3 Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Thu, 30 Jan 2020 13:06:24 +0100
Subject: [PATCH 02/88] Add warehouse delete action
---
.../WarehouseDeleteDialog.tsx | 51 +++++++++++++++++++
.../components/WarehouseDeleteDialog/index.ts | 2 +
.../WarehouseList/WarehouseList.tsx | 4 +-
src/warehouses/mutations.ts | 22 ++++++++
src/warehouses/types/WarehouseDelete.ts | 26 ++++++++++
src/warehouses/urls.ts | 4 +-
.../views/WarehouseList/WarehouseList.tsx | 38 ++++++++++++--
7 files changed, 140 insertions(+), 7 deletions(-)
create mode 100644 src/warehouses/components/WarehouseDeleteDialog/WarehouseDeleteDialog.tsx
create mode 100644 src/warehouses/components/WarehouseDeleteDialog/index.ts
create mode 100644 src/warehouses/mutations.ts
create mode 100644 src/warehouses/types/WarehouseDelete.ts
diff --git a/src/warehouses/components/WarehouseDeleteDialog/WarehouseDeleteDialog.tsx b/src/warehouses/components/WarehouseDeleteDialog/WarehouseDeleteDialog.tsx
new file mode 100644
index 000000000..224a2c36e
--- /dev/null
+++ b/src/warehouses/components/WarehouseDeleteDialog/WarehouseDeleteDialog.tsx
@@ -0,0 +1,51 @@
+import DialogContentText from "@material-ui/core/DialogContentText";
+import React from "react";
+import { FormattedMessage, useIntl } from "react-intl";
+
+import ActionDialog from "@saleor/components/ActionDialog";
+import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
+
+export interface WarehouseDeleteDialogProps {
+ confirmButtonState: ConfirmButtonTransitionState;
+ open: boolean;
+ onConfirm: () => void;
+ onClose: () => void;
+ name: string;
+}
+
+const WarehouseDeleteDialog: React.FC = ({
+ name,
+ confirmButtonState,
+ onClose,
+ onConfirm,
+ open
+}) => {
+ const intl = useIntl();
+
+ return (
+
+
+ {name}
+ }}
+ />
+
+
+ );
+};
+
+WarehouseDeleteDialog.displayName = "WarehouseDeleteDialog";
+export default WarehouseDeleteDialog;
diff --git a/src/warehouses/components/WarehouseDeleteDialog/index.ts b/src/warehouses/components/WarehouseDeleteDialog/index.ts
new file mode 100644
index 000000000..f8f68537d
--- /dev/null
+++ b/src/warehouses/components/WarehouseDeleteDialog/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseDeleteDialog";
+export * from "./WarehouseDeleteDialog";
diff --git a/src/warehouses/components/WarehouseList/WarehouseList.tsx b/src/warehouses/components/WarehouseList/WarehouseList.tsx
index 6220a8951..c8e7c4e3a 100644
--- a/src/warehouses/components/WarehouseList/WarehouseList.tsx
+++ b/src/warehouses/components/WarehouseList/WarehouseList.tsx
@@ -14,7 +14,7 @@ import { WarehouseFragment } from "@saleor/warehouses/types/WarehouseFragment";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
import TablePagination from "@saleor/components/TablePagination";
-import { maybe, renderCollection } from "@saleor/misc";
+import { maybe, renderCollection, stopPropagation } from "@saleor/misc";
import { ListProps, SortPage } from "@saleor/types";
import { WarehouseListUrlSortField } from "@saleor/warehouses/urls";
import TableCellHeader from "@saleor/components/TableCellHeader";
@@ -153,7 +153,7 @@ const WarehouseList: React.FC = props => {
onRemove(warehouse.id)}
+ onClick={stopPropagation(() => onRemove(warehouse.id))}
>
diff --git a/src/warehouses/mutations.ts b/src/warehouses/mutations.ts
new file mode 100644
index 000000000..fa1da647b
--- /dev/null
+++ b/src/warehouses/mutations.ts
@@ -0,0 +1,22 @@
+import gql from "graphql-tag";
+
+import makeMutation from "@saleor/hooks/makeMutation";
+import {
+ WarehouseDelete,
+ WarehouseDeleteVariables
+} from "./types/WarehouseDelete";
+
+const deleteWarehouse = gql`
+ mutation WarehouseDelete($id: ID!) {
+ deleteWarehouse(id: $id) {
+ errors {
+ field
+ message
+ }
+ }
+ }
+`;
+export const useWarehouseDelete = makeMutation<
+ WarehouseDelete,
+ WarehouseDeleteVariables
+>(deleteWarehouse);
diff --git a/src/warehouses/types/WarehouseDelete.ts b/src/warehouses/types/WarehouseDelete.ts
new file mode 100644
index 000000000..0e2aa5efa
--- /dev/null
+++ b/src/warehouses/types/WarehouseDelete.ts
@@ -0,0 +1,26 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+// ====================================================
+// GraphQL mutation operation: WarehouseDelete
+// ====================================================
+
+export interface WarehouseDelete_deleteWarehouse_errors {
+ __typename: "Error";
+ field: string | null;
+ message: string | null;
+}
+
+export interface WarehouseDelete_deleteWarehouse {
+ __typename: "WarehouseDelete";
+ errors: WarehouseDelete_deleteWarehouse_errors[] | null;
+}
+
+export interface WarehouseDelete {
+ deleteWarehouse: WarehouseDelete_deleteWarehouse | null;
+}
+
+export interface WarehouseDeleteVariables {
+ id: string;
+}
diff --git a/src/warehouses/urls.ts b/src/warehouses/urls.ts
index 9864e5077..d84d2266a 100644
--- a/src/warehouses/urls.ts
+++ b/src/warehouses/urls.ts
@@ -18,7 +18,7 @@ export enum WarehouseListUrlFiltersEnum {
query = "query"
}
export type WarehouseListUrlFilters = Filters;
-export type WarehouseListUrlDialog = "remove" | TabActionDialog;
+export type WarehouseListUrlDialog = "delete" | TabActionDialog;
export enum WarehouseListUrlSortField {
name = "name"
}
@@ -33,7 +33,7 @@ export const warehouseListUrl = (params?: WarehouseListUrlQueryParams) =>
warehouseListPath + "?" + stringifyQs(params);
export const warehousePath = (id: string) => urlJoin(warehouseSection, id);
-export type WarehouseUrlDialog = "remove";
+export type WarehouseUrlDialog = "delete";
export type WarehouseUrlQueryParams = Dialog & SingleAction;
export const warehouseUrl = (id: string, params?: WarehouseUrlQueryParams) =>
warehousePath(encodeURIComponent(id)) + "?" + stringifyQs(params);
diff --git a/src/warehouses/views/WarehouseList/WarehouseList.tsx b/src/warehouses/views/WarehouseList/WarehouseList.tsx
index bc119d669..4609456a6 100644
--- a/src/warehouses/views/WarehouseList/WarehouseList.tsx
+++ b/src/warehouses/views/WarehouseList/WarehouseList.tsx
@@ -17,18 +17,20 @@ import useNotifier from "@saleor/hooks/useNotifier";
import useListSettings from "@saleor/hooks/useListSettings";
import { ListViews } from "@saleor/types";
import { WindowTitle } from "@saleor/components/WindowTitle";
-import { sectionNames } from "@saleor/intl";
+import { sectionNames, commonMessages } from "@saleor/intl";
import WarehouseListPage from "@saleor/warehouses/components/WarehouseListPage";
import SaveFilterTabDialog, {
SaveFilterTabDialogFormData
} from "@saleor/components/SaveFilterTabDialog";
import DeleteFilterTabDialog from "@saleor/components/DeleteFilterTabDialog";
-import { maybe } from "@saleor/misc";
+import { maybe, getMutationStatus } from "@saleor/misc";
import { getSortParams } from "@saleor/utils/sort";
import createSortHandler from "@saleor/utils/handlers/sortHandler";
import createFilterHandlers from "@saleor/utils/handlers/filterHandlers";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import { configurationMenuUrl } from "@saleor/configuration";
+import WarehouseDeleteDialog from "@saleor/warehouses/components/WarehouseDeleteDialog";
+import { useWarehouseDelete } from "@saleor/warehouses/mutations";
import { getSortQueryVariables } from "./sort";
import {
getFilterVariables,
@@ -65,6 +67,17 @@ const WarehouseList: React.FC = ({ params }) => {
displayLoader: true,
variables: queryVariables
});
+ const [deleteWarehouse, deleteWarehouseOpts] = useWarehouseDelete({
+ onCompleted: data => {
+ if (data.deleteWarehouse.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ refetch();
+ closeModal();
+ }
+ }
+ });
const tabs = getFilterTabs();
@@ -113,6 +126,8 @@ const WarehouseList: React.FC = ({ params }) => {
const handleSort = createSortHandler(navigate, warehouseListUrl, params);
+ const deleteTransitionState = getMutationStatus(deleteWarehouseOpts);
+
return (
<>
@@ -133,12 +148,29 @@ const WarehouseList: React.FC = ({ params }) => {
onAdd={() => navigate(warehouseAddUrl)}
onNextPage={loadNextPage}
onPreviousPage={loadPreviousPage}
- onRemove={() => undefined}
+ onRemove={id => openModal("delete", { id })}
onSort={handleSort}
onUpdateListSettings={updateListSettings}
onRowClick={id => () => navigate(warehouseUrl(id))}
sort={getSortParams(params)}
/>
+
+ data.warehouses.edges.find(edge => edge.node.id === params.id).node
+ .name
+ )}
+ open={params.action === "delete"}
+ onClose={closeModal}
+ onConfirm={() =>
+ deleteWarehouse({
+ variables: {
+ id: params.id
+ }
+ })
+ }
+ />
Date: Thu, 30 Jan 2020 13:11:21 +0100
Subject: [PATCH 03/88] Fix stories
---
.../components/WarehouseListPage/WarehouseListPage.stories.tsx | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/warehouses/components/WarehouseListPage/WarehouseListPage.stories.tsx b/src/warehouses/components/WarehouseListPage/WarehouseListPage.stories.tsx
index 7b163fd66..6fbaaeac5 100644
--- a/src/warehouses/components/WarehouseListPage/WarehouseListPage.stories.tsx
+++ b/src/warehouses/components/WarehouseListPage/WarehouseListPage.stories.tsx
@@ -20,6 +20,7 @@ const props: WarehouseListPageProps = {
...sortPageProps,
...tabPageProps,
onBack: () => undefined,
+ onRemove: () => undefined,
sort: {
...sortPageProps.sort,
sort: WarehouseListUrlSortField.name
From 74ea0998249cf0629d53775dc242696557f89d0e Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Thu, 30 Jan 2020 14:17:29 +0100
Subject: [PATCH 04/88] Make company address shared component
---
.../CompanyAddressInput.tsx} | 39 +++++++++----------
src/components/CompanyAddressInput/index.ts | 2 +
.../components/SiteSettingsAddress/index.ts | 2 -
.../SiteSettingsPage/SiteSettingsPage.tsx | 8 +++-
4 files changed, 26 insertions(+), 25 deletions(-)
rename src/{siteSettings/components/SiteSettingsAddress/SiteSettingsAddress.tsx => components/CompanyAddressInput/CompanyAddressInput.tsx} (84%)
create mode 100644 src/components/CompanyAddressInput/index.ts
delete mode 100644 src/siteSettings/components/SiteSettingsAddress/index.ts
diff --git a/src/siteSettings/components/SiteSettingsAddress/SiteSettingsAddress.tsx b/src/components/CompanyAddressInput/CompanyAddressInput.tsx
similarity index 84%
rename from src/siteSettings/components/SiteSettingsAddress/SiteSettingsAddress.tsx
rename to src/components/CompanyAddressInput/CompanyAddressInput.tsx
index bbf07bee7..927a12d25 100644
--- a/src/siteSettings/components/SiteSettingsAddress/SiteSettingsAddress.tsx
+++ b/src/components/CompanyAddressInput/CompanyAddressInput.tsx
@@ -17,14 +17,15 @@ import { ShopErrorFragment } from "@saleor/siteSettings/types/ShopErrorFragment"
import getShopErrorMessage from "@saleor/utils/errors/shop";
import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
import getAccountErrorMessage from "@saleor/utils/errors/account";
-import { SiteSettingsPageFormData } from "../SiteSettingsPage";
+import { AddressTypeInput } from "@saleor/customers/types";
-interface SiteSettingsAddressProps {
+interface CompanyAddressInputProps {
countries: SingleAutocompleteChoiceType[];
- data: SiteSettingsPageFormData;
+ data: AddressTypeInput;
displayCountry: string;
errors: Array;
disabled: boolean;
+ header: string;
onChange: (event: ChangeEvent) => void;
onCountryChange: (event: ChangeEvent) => void;
}
@@ -35,7 +36,7 @@ const useStyles = makeStyles(
overflow: "visible"
}
},
- { name: "SiteSettingsAddress" }
+ { name: "CompanyAddressInput" }
);
function getErrorMessage(
@@ -49,13 +50,14 @@ function getErrorMessage(
return getShopErrorMessage(err, intl);
}
-const SiteSettingsAddress: React.FC = props => {
+const CompanyAddressInput: React.FC = props => {
const {
countries,
data,
disabled,
displayCountry,
errors,
+ header,
onChange,
onCountryChange
} = props;
@@ -77,12 +79,7 @@ const SiteSettingsAddress: React.FC = props => {
return (
-
+
= props => {
label={intl.formatMessage({
defaultMessage: "Company"
})}
- name={"companyName" as keyof SiteSettingsPageFormData}
+ name={"companyName" as keyof AddressTypeInput}
onChange={onChange}
value={data.companyName}
fullWidth
@@ -104,7 +101,7 @@ const SiteSettingsAddress: React.FC = props => {
label={intl.formatMessage({
defaultMessage: "Address line 1"
})}
- name={"streetAddress1" as keyof SiteSettingsPageFormData}
+ name={"streetAddress1" as keyof AddressTypeInput}
onChange={onChange}
value={data.streetAddress1}
fullWidth
@@ -117,7 +114,7 @@ const SiteSettingsAddress: React.FC = props => {
label={intl.formatMessage({
defaultMessage: "Address line 2"
})}
- name={"streetAddress2" as keyof SiteSettingsPageFormData}
+ name={"streetAddress2" as keyof AddressTypeInput}
onChange={onChange}
value={data.streetAddress2}
fullWidth
@@ -131,7 +128,7 @@ const SiteSettingsAddress: React.FC = props => {
label={intl.formatMessage({
defaultMessage: "City"
})}
- name={"city" as keyof SiteSettingsPageFormData}
+ name={"city" as keyof AddressTypeInput}
onChange={onChange}
value={data.city}
fullWidth
@@ -143,7 +140,7 @@ const SiteSettingsAddress: React.FC = props => {
label={intl.formatMessage({
defaultMessage: "ZIP / Postal code"
})}
- name={"postalCode" as keyof SiteSettingsPageFormData}
+ name={"postalCode" as keyof AddressTypeInput}
onChange={onChange}
value={data.postalCode}
fullWidth
@@ -159,7 +156,7 @@ const SiteSettingsAddress: React.FC = props => {
label={intl.formatMessage({
defaultMessage: "Country"
})}
- name={"country" as keyof SiteSettingsPageFormData}
+ name={"country" as keyof AddressTypeInput}
onChange={onCountryChange}
value={data.country}
choices={countries}
@@ -174,7 +171,7 @@ const SiteSettingsAddress: React.FC = props => {
label={intl.formatMessage({
defaultMessage: "Country area"
})}
- name={"countryArea" as keyof SiteSettingsPageFormData}
+ name={"countryArea" as keyof AddressTypeInput}
onChange={onChange}
value={data.countryArea}
fullWidth
@@ -189,7 +186,7 @@ const SiteSettingsAddress: React.FC = props => {
label={intl.formatMessage({
defaultMessage: "Phone"
})}
- name={"phone" as keyof SiteSettingsPageFormData}
+ name={"phone" as keyof AddressTypeInput}
value={data.phone}
onChange={onChange}
/>
@@ -197,5 +194,5 @@ const SiteSettingsAddress: React.FC = props => {
);
};
-SiteSettingsAddress.displayName = "SiteSettingsAddress";
-export default SiteSettingsAddress;
+CompanyAddressInput.displayName = "CompanyAddressInput";
+export default CompanyAddressInput;
diff --git a/src/components/CompanyAddressInput/index.ts b/src/components/CompanyAddressInput/index.ts
new file mode 100644
index 000000000..9abca5b78
--- /dev/null
+++ b/src/components/CompanyAddressInput/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./CompanyAddressInput";
+export * from "./CompanyAddressInput";
diff --git a/src/siteSettings/components/SiteSettingsAddress/index.ts b/src/siteSettings/components/SiteSettingsAddress/index.ts
deleted file mode 100644
index b15a23918..000000000
--- a/src/siteSettings/components/SiteSettingsAddress/index.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { default } from "./SiteSettingsAddress";
-export * from "./SiteSettingsAddress";
diff --git a/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx b/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx
index dab35c263..7fa681fa7 100644
--- a/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx
+++ b/src/siteSettings/components/SiteSettingsPage/SiteSettingsPage.tsx
@@ -17,10 +17,10 @@ import { commonMessages, sectionNames } from "@saleor/intl";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import { mapCountriesToChoices } from "@saleor/utils/maps";
import { ShopErrorFragment } from "@saleor/siteSettings/types/ShopErrorFragment";
+import CompanyAddressInput from "@saleor/components/CompanyAddressInput";
import { maybe } from "../../../misc";
import { AuthorizationKeyType } from "../../../types/globalTypes";
import { SiteSettings_shop } from "../../types/SiteSettings";
-import SiteSettingsAddress from "../SiteSettingsAddress/SiteSettingsAddress";
import SiteSettingsDetails from "../SiteSettingsDetails/SiteSettingsDetails";
import SiteSettingsKeys from "../SiteSettingsKeys/SiteSettingsKeys";
import SiteSettingsMailing, {
@@ -200,12 +200,16 @@ const SiteSettingsPage: React.FC = props => {
-
From 2a7829c0f76de998d8ae45190c2cc835e0a27126 Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Thu, 30 Jan 2020 15:34:27 +0100
Subject: [PATCH 05/88] Add warehouse create
---
src/fixtures.ts | 20 +++
src/types/globalTypes.ts | 19 +++
.../WarehouseCreatePage.stories.tsx | 48 +++++++
.../WarehouseCreatePage.tsx | 119 ++++++++++++++++++
.../components/WarehouseCreatePage/index.ts | 2 +
.../WarehouseInfo/WarehouseInfo.tsx | 50 ++++++++
.../components/WarehouseInfo/index.ts | 2 +
src/warehouses/index.tsx | 14 +--
src/warehouses/mutations.ts | 24 ++++
src/warehouses/queries.ts | 12 ++
src/warehouses/types/WarehouseCreate.ts | 75 +++++++++++
.../types/WarehouseDetailsFragment.ts | 53 ++++++++
.../views/WarehouseCreate/WarehouseCreate.tsx | 60 +++++++++
src/warehouses/views/WarehouseCreate/index.ts | 2 +
14 files changed, 491 insertions(+), 9 deletions(-)
create mode 100644 src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx
create mode 100644 src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx
create mode 100644 src/warehouses/components/WarehouseCreatePage/index.ts
create mode 100644 src/warehouses/components/WarehouseInfo/WarehouseInfo.tsx
create mode 100644 src/warehouses/components/WarehouseInfo/index.ts
create mode 100644 src/warehouses/types/WarehouseCreate.ts
create mode 100644 src/warehouses/types/WarehouseDetailsFragment.ts
create mode 100644 src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx
create mode 100644 src/warehouses/views/WarehouseCreate/index.ts
diff --git a/src/fixtures.ts b/src/fixtures.ts
index ebb678030..3394f4a92 100644
--- a/src/fixtures.ts
+++ b/src/fixtures.ts
@@ -485,3 +485,23 @@ export const adminUserPermissions: User_userPermissions[] = [
name: "Manage customers."
}
];
+
+export const address = {
+ __typename: "Address",
+ city: "Port Danielshire",
+ cityArea: "",
+ companyName: "",
+ country: {
+ __typename: "CountryDisplay",
+ code: "SE",
+ country: "Szwecja"
+ },
+ countryArea: "",
+ firstName: "Elizabeth",
+ id: "QWRkcmVzczoy",
+ lastName: "Vaughn",
+ phone: "",
+ postalCode: "52203",
+ streetAddress1: "419 Ruiz Orchard Apt. 199",
+ streetAddress2: "0238 Cremin Freeway"
+};
diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts
index 48507817e..53faacc0a 100644
--- a/src/types/globalTypes.ts
+++ b/src/types/globalTypes.ts
@@ -1419,6 +1419,25 @@ export interface VoucherSortingInput {
field: VoucherSortField;
}
+export interface WarehouseAddressInput {
+ streetAddress1: string;
+ streetAddress2?: string | null;
+ city: string;
+ cityArea?: string | null;
+ postalCode?: string | null;
+ country: CountryCode;
+ countryArea?: string | null;
+ phone?: string | null;
+}
+
+export interface WarehouseCreateInput {
+ name: string;
+ companyName?: string | null;
+ shippingZones?: (string | null)[] | null;
+ email?: string | null;
+ address: WarehouseAddressInput;
+}
+
export interface WarehouseFilterInput {
search?: string | null;
}
diff --git a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx
new file mode 100644
index 000000000..9f25b855b
--- /dev/null
+++ b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx
@@ -0,0 +1,48 @@
+import { storiesOf } from "@storybook/react";
+import React from "react";
+
+import { address, permissions } from "@saleor/fixtures";
+import Decorator from "@saleor/storybook/Decorator";
+import { formError } from "@saleor/storybook/misc";
+import { warehouseList } from "../../fixtures";
+import WarehouseCreatePage, {
+ WarehouseCreatePageProps,
+ WarehouseCreatePageFormData
+} from "./WarehouseCreatePage";
+
+const props: WarehouseCreatePageProps = {
+ disabled: false,
+ errors: [],
+ saveButtonBarState: "default",
+ onBack: () => undefined,
+ onSubmit: () => undefined,
+ warehouse: {
+ ...warehouseList[0],
+ address
+ }
+};
+storiesOf("Views / Warehouses / Create warehouse", module)
+ .addDecorator(Decorator)
+ .add("default", () => )
+ .add("loading", () => (
+
+ ))
+ .add("form errors", () => (
+ ).map(field =>
+ formError(field)
+ )}
+ />
+ ));
diff --git a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx
new file mode 100644
index 000000000..2024cca42
--- /dev/null
+++ b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx
@@ -0,0 +1,119 @@
+import React from "react";
+import { useIntl } from "react-intl";
+
+import Container from "@saleor/components/Container";
+import Form from "@saleor/components/Form";
+import SaveButtonBar from "@saleor/components/SaveButtonBar";
+import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
+import { UserError } from "@saleor/types";
+import Grid from "@saleor/components/Grid";
+import CardSpacer from "@saleor/components/CardSpacer";
+import CompanyAddressInput from "@saleor/components/CompanyAddressInput";
+import { AddressTypeInput } from "@saleor/customers/types";
+import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
+import { mapCountriesToChoices } from "@saleor/utils/maps";
+import useAddressValidation from "@saleor/hooks/useAddressValidation";
+import useStateFromProps from "@saleor/hooks/useStateFromProps";
+import { maybe } from "@saleor/misc";
+import { ShopInfo_shop } from "@saleor/components/Shop/types/ShopInfo";
+import WarehouseInfo from "../WarehouseInfo";
+
+export interface WarehouseCreatePageFormData extends AddressTypeInput {
+ name: string;
+}
+export interface WarehouseCreatePageProps {
+ disabled: boolean;
+ errors: UserError[];
+ saveButtonBarState: ConfirmButtonTransitionState;
+ shop: ShopInfo_shop;
+ onBack: () => void;
+ onSubmit: (data: WarehouseCreatePageFormData) => void;
+}
+
+const initialForm: WarehouseCreatePageFormData = {
+ city: "",
+ companyName: "",
+ country: "",
+ countryArea: "",
+ name: "",
+ phone: "",
+ postalCode: "",
+ streetAddress1: "",
+ streetAddress2: ""
+};
+
+const WarehouseCreatePage: React.FC = ({
+ disabled,
+ errors: apiErrors,
+ saveButtonBarState,
+ shop,
+ onBack,
+ onSubmit
+}) => {
+ const intl = useIntl();
+ const [displayCountry, setDisplayCountry] = useStateFromProps(
+ maybe(() => shop.companyAddress.country.code, "")
+ );
+
+ const {
+ errors: validationErrors,
+ submit: handleSubmit
+ } = useAddressValidation(onSubmit);
+
+ return (
+
+ );
+};
+
+WarehouseCreatePage.displayName = "WarehouseCreatePage";
+export default WarehouseCreatePage;
diff --git a/src/warehouses/components/WarehouseCreatePage/index.ts b/src/warehouses/components/WarehouseCreatePage/index.ts
new file mode 100644
index 000000000..b9bd23b20
--- /dev/null
+++ b/src/warehouses/components/WarehouseCreatePage/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseCreatePage";
+export * from "./WarehouseCreatePage";
diff --git a/src/warehouses/components/WarehouseInfo/WarehouseInfo.tsx b/src/warehouses/components/WarehouseInfo/WarehouseInfo.tsx
new file mode 100644
index 000000000..56b402e08
--- /dev/null
+++ b/src/warehouses/components/WarehouseInfo/WarehouseInfo.tsx
@@ -0,0 +1,50 @@
+import React from "react";
+import Card from "@material-ui/core/Card";
+import CardContent from "@material-ui/core/CardContent";
+import TextField from "@material-ui/core/TextField";
+import { useIntl } from "react-intl";
+import CardTitle from "@saleor/components/CardTitle";
+import { commonMessages } from "@saleor/intl";
+import { FormChange } from "@saleor/hooks/useForm";
+import { FormErrors } from "@saleor/types";
+
+export interface WarehouseInfoProps {
+ data: Record<"name", string>;
+ disabled: boolean;
+ errors: FormErrors<"name">;
+ onChange: FormChange;
+}
+
+const WarehouseInfo: React.FC = ({
+ data,
+ disabled,
+ errors,
+ onChange
+}) => {
+ const intl = useIntl();
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+WarehouseInfo.displayName = "WarehouseInfo";
+export default WarehouseInfo;
diff --git a/src/warehouses/components/WarehouseInfo/index.ts b/src/warehouses/components/WarehouseInfo/index.ts
new file mode 100644
index 000000000..3296772d7
--- /dev/null
+++ b/src/warehouses/components/WarehouseInfo/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseInfo";
+export * from "./WarehouseInfo";
diff --git a/src/warehouses/index.tsx b/src/warehouses/index.tsx
index 8d06f0040..0b37a9da5 100644
--- a/src/warehouses/index.tsx
+++ b/src/warehouses/index.tsx
@@ -13,11 +13,13 @@ import {
WarehouseListUrlQueryParams,
// warehousePath,
// WarehouseUrlQueryParams,
- WarehouseListUrlSortField
+ WarehouseListUrlSortField,
+ warehouseAddPath
} from "./urls";
// import WarehouseCreateComponent from "./views/WarehouseCreate";
// import WarehouseDetailsComponent from "./views/WarehouseDetails";
import WarehouseListComponent from "./views/WarehouseList";
+import WarehouseCreate from "./views/WarehouseCreate";
const WarehouseList: React.FC = ({ location }) => {
const qs = parseQs(location.search.substr(1));
@@ -29,12 +31,6 @@ const WarehouseList: React.FC = ({ location }) => {
return ;
};
-// const WarehouseCreate: React.FC> = ({ location }) => {
-// const qs = parseQs(location.search.substr(1));
-// const params: WarehouseAddUrlQueryParams = qs;
-// return ;
-// };
-
// const WarehouseDetails: React.FC> = ({
// location,
// match
@@ -57,8 +53,8 @@ export const WarehouseSection: React.FC = () => {
- {/*
- */}
+
+ {/* */}
>
);
diff --git a/src/warehouses/mutations.ts b/src/warehouses/mutations.ts
index fa1da647b..9611cac88 100644
--- a/src/warehouses/mutations.ts
+++ b/src/warehouses/mutations.ts
@@ -1,10 +1,15 @@
import gql from "graphql-tag";
import makeMutation from "@saleor/hooks/makeMutation";
+import {
+ WarehouseCreate,
+ WarehouseCreateVariables
+} from "./types/WarehouseCreate";
import {
WarehouseDelete,
WarehouseDeleteVariables
} from "./types/WarehouseDelete";
+import { warehouseDetailsFragment } from "./queries";
const deleteWarehouse = gql`
mutation WarehouseDelete($id: ID!) {
@@ -20,3 +25,22 @@ export const useWarehouseDelete = makeMutation<
WarehouseDelete,
WarehouseDeleteVariables
>(deleteWarehouse);
+
+const createWarehouse = gql`
+ ${warehouseDetailsFragment}
+ mutation WarehouseCreate($input: WarehouseCreateInput!) {
+ createWarehouse(input: $input) {
+ errors {
+ field
+ message
+ }
+ warehouse {
+ ...WarehouseDetailsFragment
+ }
+ }
+ }
+`;
+export const useWarehouseCreate = makeMutation<
+ WarehouseCreate,
+ WarehouseCreateVariables
+>(createWarehouse);
diff --git a/src/warehouses/queries.ts b/src/warehouses/queries.ts
index 1cfd8b5ac..d75984c68 100644
--- a/src/warehouses/queries.ts
+++ b/src/warehouses/queries.ts
@@ -2,6 +2,7 @@ import gql from "graphql-tag";
import makeQuery from "@saleor/hooks/makeQuery";
import { pageInfoFragment } from "@saleor/queries";
+import { fragmentAddress } from "@saleor/orders/queries";
import { WarehouseList, WarehouseListVariables } from "./types/WarehouseList";
export const warehouseFragment = gql`
@@ -19,6 +20,17 @@ export const warehouseFragment = gql`
}
`;
+export const warehouseDetailsFragment = gql`
+ ${fragmentAddress}
+ ${warehouseFragment}
+ fragment WarehouseDetailsFragment on Warehouse {
+ ...WarehouseFragment
+ address {
+ ...AddressFragment
+ }
+ }
+`;
+
const warehouseList = gql`
${warehouseFragment}
${pageInfoFragment}
diff --git a/src/warehouses/types/WarehouseCreate.ts b/src/warehouses/types/WarehouseCreate.ts
new file mode 100644
index 000000000..5caeb87b9
--- /dev/null
+++ b/src/warehouses/types/WarehouseCreate.ts
@@ -0,0 +1,75 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+import { WarehouseCreateInput } from "./../../types/globalTypes";
+
+// ====================================================
+// GraphQL mutation operation: WarehouseCreate
+// ====================================================
+
+export interface WarehouseCreate_createWarehouse_errors {
+ __typename: "Error";
+ field: string | null;
+ message: string | null;
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse_shippingZones_edges_node {
+ __typename: "ShippingZone";
+ id: string;
+ name: string;
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse_shippingZones_edges {
+ __typename: "ShippingZoneCountableEdge";
+ node: WarehouseCreate_createWarehouse_warehouse_shippingZones_edges_node;
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse_shippingZones {
+ __typename: "ShippingZoneCountableConnection";
+ edges: WarehouseCreate_createWarehouse_warehouse_shippingZones_edges[];
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse_address_country {
+ __typename: "CountryDisplay";
+ code: string;
+ country: string;
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse_address {
+ __typename: "Address";
+ city: string;
+ cityArea: string;
+ companyName: string;
+ country: WarehouseCreate_createWarehouse_warehouse_address_country;
+ countryArea: string;
+ firstName: string;
+ id: string;
+ lastName: string;
+ phone: string | null;
+ postalCode: string;
+ streetAddress1: string;
+ streetAddress2: string;
+}
+
+export interface WarehouseCreate_createWarehouse_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+ shippingZones: WarehouseCreate_createWarehouse_warehouse_shippingZones;
+ address: WarehouseCreate_createWarehouse_warehouse_address;
+}
+
+export interface WarehouseCreate_createWarehouse {
+ __typename: "WarehouseCreate";
+ errors: WarehouseCreate_createWarehouse_errors[] | null;
+ warehouse: WarehouseCreate_createWarehouse_warehouse | null;
+}
+
+export interface WarehouseCreate {
+ createWarehouse: WarehouseCreate_createWarehouse | null;
+}
+
+export interface WarehouseCreateVariables {
+ input: WarehouseCreateInput;
+}
diff --git a/src/warehouses/types/WarehouseDetailsFragment.ts b/src/warehouses/types/WarehouseDetailsFragment.ts
new file mode 100644
index 000000000..fae00ac31
--- /dev/null
+++ b/src/warehouses/types/WarehouseDetailsFragment.ts
@@ -0,0 +1,53 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+// ====================================================
+// GraphQL fragment: WarehouseDetailsFragment
+// ====================================================
+
+export interface WarehouseDetailsFragment_shippingZones_edges_node {
+ __typename: "ShippingZone";
+ id: string;
+ name: string;
+}
+
+export interface WarehouseDetailsFragment_shippingZones_edges {
+ __typename: "ShippingZoneCountableEdge";
+ node: WarehouseDetailsFragment_shippingZones_edges_node;
+}
+
+export interface WarehouseDetailsFragment_shippingZones {
+ __typename: "ShippingZoneCountableConnection";
+ edges: WarehouseDetailsFragment_shippingZones_edges[];
+}
+
+export interface WarehouseDetailsFragment_address_country {
+ __typename: "CountryDisplay";
+ code: string;
+ country: string;
+}
+
+export interface WarehouseDetailsFragment_address {
+ __typename: "Address";
+ city: string;
+ cityArea: string;
+ companyName: string;
+ country: WarehouseDetailsFragment_address_country;
+ countryArea: string;
+ firstName: string;
+ id: string;
+ lastName: string;
+ phone: string | null;
+ postalCode: string;
+ streetAddress1: string;
+ streetAddress2: string;
+}
+
+export interface WarehouseDetailsFragment {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+ shippingZones: WarehouseDetailsFragment_shippingZones;
+ address: WarehouseDetailsFragment_address;
+}
diff --git a/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx b/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx
new file mode 100644
index 000000000..921a0ee8f
--- /dev/null
+++ b/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx
@@ -0,0 +1,60 @@
+import React from "react";
+import { useIntl } from "react-intl";
+
+import WarehouseCreatePage from "@saleor/warehouses/components/WarehouseCreatePage";
+import useNavigator from "@saleor/hooks/useNavigator";
+import { warehouseListUrl, warehouseUrl } from "@saleor/warehouses/urls";
+import { useWarehouseCreate } from "@saleor/warehouses/mutations";
+import { commonMessages } from "@saleor/intl";
+import useNotifier from "@saleor/hooks/useNotifier";
+import { maybe, findValueInEnum, getMutationStatus } from "@saleor/misc";
+import { CountryCode } from "@saleor/types/globalTypes";
+import useShop from "@saleor/hooks/useShop";
+
+const WarehouseCreate: React.FC = () => {
+ const intl = useIntl();
+ const navigate = useNavigator();
+ const notify = useNotifier();
+ const shop = useShop();
+ const [createWarehouse, createWarehouseOpts] = useWarehouseCreate({
+ onCompleted: data => {
+ if (data.createWarehouse.errors.length === 0) {
+ navigate(warehouseUrl(data.createWarehouse.warehouse.id));
+ notify({ text: intl.formatMessage(commonMessages.savedChanges) });
+ }
+ }
+ });
+ const createWarehouseTransitionState = getMutationStatus(createWarehouseOpts);
+
+ return (
+ navigate(warehouseListUrl())}
+ disabled={createWarehouseOpts.loading}
+ errors={maybe(() => createWarehouseOpts.data.createWarehouse.errors, [])}
+ shop={shop}
+ onSubmit={data =>
+ createWarehouse({
+ variables: {
+ input: {
+ address: {
+ city: data.city,
+ cityArea: data.cityArea,
+ country: findValueInEnum(data.country, CountryCode),
+ countryArea: data.countryArea,
+ phone: data.phone,
+ postalCode: data.postalCode,
+ streetAddress1: data.streetAddress1,
+ streetAddress2: data.streetAddress2
+ },
+ name: data.name
+ }
+ }
+ })
+ }
+ saveButtonBarState={createWarehouseTransitionState}
+ />
+ );
+};
+
+WarehouseCreate.displayName = "WarehouseCreate";
+export default WarehouseCreate;
diff --git a/src/warehouses/views/WarehouseCreate/index.ts b/src/warehouses/views/WarehouseCreate/index.ts
new file mode 100644
index 000000000..d73de272c
--- /dev/null
+++ b/src/warehouses/views/WarehouseCreate/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseCreate";
+export * from "./WarehouseCreate";
From c9afddd050f11979bf6de3df946fb4800312d811 Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Thu, 30 Jan 2020 15:39:55 +0100
Subject: [PATCH 06/88] Improve headers
---
.../WarehouseCreatePage.tsx | 18 ++++--
.../views/WarehouseCreate/WarehouseCreate.tsx | 62 +++++++++++--------
2 files changed, 51 insertions(+), 29 deletions(-)
diff --git a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx
index 2024cca42..64bde0713 100644
--- a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx
+++ b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx
@@ -1,5 +1,5 @@
import React from "react";
-import { useIntl } from "react-intl";
+import { useIntl, FormattedMessage } from "react-intl";
import Container from "@saleor/components/Container";
import Form from "@saleor/components/Form";
@@ -16,6 +16,9 @@ import useAddressValidation from "@saleor/hooks/useAddressValidation";
import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { maybe } from "@saleor/misc";
import { ShopInfo_shop } from "@saleor/components/Shop/types/ShopInfo";
+import AppHeader from "@saleor/components/AppHeader";
+import PageHeader from "@saleor/components/PageHeader";
+import { sectionNames } from "@saleor/intl";
import WarehouseInfo from "../WarehouseInfo";
export interface WarehouseCreatePageFormData extends AddressTypeInput {
@@ -51,9 +54,7 @@ const WarehouseCreatePage: React.FC = ({
onSubmit
}) => {
const intl = useIntl();
- const [displayCountry, setDisplayCountry] = useStateFromProps(
- maybe(() => shop.companyAddress.country.code, "")
- );
+ const [displayCountry, setDisplayCountry] = useStateFromProps("");
const {
errors: validationErrors,
@@ -78,6 +79,15 @@ const WarehouseCreatePage: React.FC = ({
return (
+
+
+
+
{
const intl = useIntl();
@@ -27,32 +28,43 @@ const WarehouseCreate: React.FC = () => {
const createWarehouseTransitionState = getMutationStatus(createWarehouseOpts);
return (
- navigate(warehouseListUrl())}
- disabled={createWarehouseOpts.loading}
- errors={maybe(() => createWarehouseOpts.data.createWarehouse.errors, [])}
- shop={shop}
- onSubmit={data =>
- createWarehouse({
- variables: {
- input: {
- address: {
- city: data.city,
- cityArea: data.cityArea,
- country: findValueInEnum(data.country, CountryCode),
- countryArea: data.countryArea,
- phone: data.phone,
- postalCode: data.postalCode,
- streetAddress1: data.streetAddress1,
- streetAddress2: data.streetAddress2
- },
- name: data.name
+ <>
+
+ navigate(warehouseListUrl())}
+ disabled={createWarehouseOpts.loading}
+ errors={maybe(
+ () => createWarehouseOpts.data.createWarehouse.errors,
+ []
+ )}
+ shop={shop}
+ onSubmit={data =>
+ createWarehouse({
+ variables: {
+ input: {
+ address: {
+ city: data.city,
+ cityArea: data.cityArea,
+ country: findValueInEnum(data.country, CountryCode),
+ countryArea: data.countryArea,
+ phone: data.phone,
+ postalCode: data.postalCode,
+ streetAddress1: data.streetAddress1,
+ streetAddress2: data.streetAddress2
+ },
+ name: data.name
+ }
}
- }
- })
- }
- saveButtonBarState={createWarehouseTransitionState}
- />
+ })
+ }
+ saveButtonBarState={createWarehouseTransitionState}
+ />
+ >
);
};
From 8445d2d815a3fbb988dab660d24b8672f0d5f5ee Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Thu, 30 Jan 2020 16:37:22 +0100
Subject: [PATCH 07/88] Add warehouse details
---
src/fixtures.ts | 4 +-
src/types/globalTypes.ts | 8 +
.../WarehouseCreatePage.stories.tsx | 14 +-
.../WarehouseDetailsPage.stories.tsx | 48 ++++++
.../WarehouseDetailsPage.tsx | 141 ++++++++++++++++++
.../components/WarehouseDetailsPage/index.ts | 2 +
.../WarehouseInfo/WarehouseInfo.tsx | 1 +
.../WarehouseZones/WarehouseZones.tsx | 73 +++++++++
.../components/WarehouseZones/index.ts | 2 +
src/warehouses/index.tsx | 37 +++--
src/warehouses/mutations.ts | 23 +++
src/warehouses/queries.ts | 17 +++
src/warehouses/types/WarehouseDetails.ts | 61 ++++++++
src/warehouses/types/WarehouseUpdate.ts | 76 ++++++++++
.../WarehouseDetails/WarehouseDetails.tsx | 84 +++++++++++
.../views/WarehouseDetails/index.ts | 2 +
16 files changed, 561 insertions(+), 32 deletions(-)
create mode 100644 src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.stories.tsx
create mode 100644 src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx
create mode 100644 src/warehouses/components/WarehouseDetailsPage/index.ts
create mode 100644 src/warehouses/components/WarehouseZones/WarehouseZones.tsx
create mode 100644 src/warehouses/components/WarehouseZones/index.ts
create mode 100644 src/warehouses/types/WarehouseDetails.ts
create mode 100644 src/warehouses/types/WarehouseUpdate.ts
create mode 100644 src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx
create mode 100644 src/warehouses/views/WarehouseDetails/index.ts
diff --git a/src/fixtures.ts b/src/fixtures.ts
index 3394f4a92..037506378 100644
--- a/src/fixtures.ts
+++ b/src/fixtures.ts
@@ -487,12 +487,12 @@ export const adminUserPermissions: User_userPermissions[] = [
];
export const address = {
- __typename: "Address",
+ __typename: "Address" as "Address",
city: "Port Danielshire",
cityArea: "",
companyName: "",
country: {
- __typename: "CountryDisplay",
+ __typename: "CountryDisplay" as "CountryDisplay",
code: "SE",
country: "Szwecja"
},
diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts
index 53faacc0a..e6066af22 100644
--- a/src/types/globalTypes.ts
+++ b/src/types/globalTypes.ts
@@ -1447,6 +1447,14 @@ export interface WarehouseSortingInput {
field: WarehouseSortField;
}
+export interface WarehouseUpdateInput {
+ name: string;
+ companyName?: string | null;
+ shippingZones?: (string | null)[] | null;
+ email?: string | null;
+ address?: WarehouseAddressInput | null;
+}
+
export interface WebhookCreateInput {
name?: string | null;
targetUrl?: string | null;
diff --git a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx
index 9f25b855b..87ef6f4d4 100644
--- a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx
+++ b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.stories.tsx
@@ -1,10 +1,9 @@
import { storiesOf } from "@storybook/react";
import React from "react";
-import { address, permissions } from "@saleor/fixtures";
import Decorator from "@saleor/storybook/Decorator";
import { formError } from "@saleor/storybook/misc";
-import { warehouseList } from "../../fixtures";
+import { shop } from "@saleor/siteSettings/fixtures";
import WarehouseCreatePage, {
WarehouseCreatePageProps,
WarehouseCreatePageFormData
@@ -13,20 +12,15 @@ import WarehouseCreatePage, {
const props: WarehouseCreatePageProps = {
disabled: false,
errors: [],
- saveButtonBarState: "default",
onBack: () => undefined,
onSubmit: () => undefined,
- warehouse: {
- ...warehouseList[0],
- address
- }
+ saveButtonBarState: "default",
+ shop
};
storiesOf("Views / Warehouses / Create warehouse", module)
.addDecorator(Decorator)
.add("default", () => )
- .add("loading", () => (
-
- ))
+ .add("loading", () => )
.add("form errors", () => (
undefined,
+ onSubmit: () => undefined,
+ saveButtonBarState: "default",
+ warehouse: {
+ ...warehouseList[0],
+ address
+ }
+};
+storiesOf("Views / Warehouses / Warehouse details", module)
+ .addDecorator(Decorator)
+ .add("default", () => )
+ .add("loading", () => (
+
+ ))
+ .add("form errors", () => (
+ ).map(field =>
+ formError(field)
+ )}
+ />
+ ));
diff --git a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx
new file mode 100644
index 000000000..1d6b02689
--- /dev/null
+++ b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx
@@ -0,0 +1,141 @@
+import React from "react";
+import { useIntl, FormattedMessage } from "react-intl";
+
+import Container from "@saleor/components/Container";
+import Form from "@saleor/components/Form";
+import SaveButtonBar from "@saleor/components/SaveButtonBar";
+import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
+import { UserError } from "@saleor/types";
+import Grid from "@saleor/components/Grid";
+import CardSpacer from "@saleor/components/CardSpacer";
+import CompanyAddressInput from "@saleor/components/CompanyAddressInput";
+import { AddressTypeInput } from "@saleor/customers/types";
+import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
+import { mapCountriesToChoices } from "@saleor/utils/maps";
+import useAddressValidation from "@saleor/hooks/useAddressValidation";
+import useStateFromProps from "@saleor/hooks/useStateFromProps";
+import { maybe, findValueInEnum } from "@saleor/misc";
+import { ShopInfo_shop } from "@saleor/components/Shop/types/ShopInfo";
+import AppHeader from "@saleor/components/AppHeader";
+import PageHeader from "@saleor/components/PageHeader";
+import { sectionNames } from "@saleor/intl";
+import { CountryCode } from "@saleor/types/globalTypes";
+import WarehouseInfo from "../WarehouseInfo";
+import WarehouseZones from "../WarehouseZones";
+import { WarehouseDetails_warehouse } from "../../types/WarehouseDetails";
+
+export interface WarehouseDetailsPageFormData extends AddressTypeInput {
+ name: string;
+}
+export interface WarehouseDetailsPageProps {
+ disabled: boolean;
+ errors: UserError[];
+ saveButtonBarState: ConfirmButtonTransitionState;
+ shop: ShopInfo_shop;
+ warehouse: WarehouseDetails_warehouse;
+ onBack: () => void;
+ onShippingZoneClick: (id: string) => void;
+ onSubmit: (data: WarehouseDetailsPageFormData) => void;
+}
+
+const WarehouseDetailsPage: React.FC = ({
+ disabled,
+ errors: apiErrors,
+ saveButtonBarState,
+ shop,
+ warehouse,
+ onBack,
+ onShippingZoneClick,
+ onSubmit
+}) => {
+ const intl = useIntl();
+ const [displayCountry, setDisplayCountry] = useStateFromProps("");
+
+ const {
+ errors: validationErrors,
+ submit: handleSubmit
+ } = useAddressValidation(onSubmit);
+
+ const initialForm: WarehouseDetailsPageFormData = {
+ city: maybe(() => warehouse.address.city, ""),
+ companyName: maybe(() => warehouse.address.companyName, ""),
+ country: maybe(() =>
+ findValueInEnum(warehouse.address.country.code, CountryCode)
+ ),
+ 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, "")
+ };
+
+ return (
+
+ );
+};
+
+WarehouseDetailsPage.displayName = "WarehouseDetailsPage";
+export default WarehouseDetailsPage;
diff --git a/src/warehouses/components/WarehouseDetailsPage/index.ts b/src/warehouses/components/WarehouseDetailsPage/index.ts
new file mode 100644
index 000000000..c5fea07a8
--- /dev/null
+++ b/src/warehouses/components/WarehouseDetailsPage/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseDetailsPage";
+export * from "./WarehouseDetailsPage";
diff --git a/src/warehouses/components/WarehouseInfo/WarehouseInfo.tsx b/src/warehouses/components/WarehouseInfo/WarehouseInfo.tsx
index 56b402e08..7b31cc2ea 100644
--- a/src/warehouses/components/WarehouseInfo/WarehouseInfo.tsx
+++ b/src/warehouses/components/WarehouseInfo/WarehouseInfo.tsx
@@ -3,6 +3,7 @@ import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import TextField from "@material-ui/core/TextField";
import { useIntl } from "react-intl";
+
import CardTitle from "@saleor/components/CardTitle";
import { commonMessages } from "@saleor/intl";
import { FormChange } from "@saleor/hooks/useForm";
diff --git a/src/warehouses/components/WarehouseZones/WarehouseZones.tsx b/src/warehouses/components/WarehouseZones/WarehouseZones.tsx
new file mode 100644
index 000000000..b4fe1cb2d
--- /dev/null
+++ b/src/warehouses/components/WarehouseZones/WarehouseZones.tsx
@@ -0,0 +1,73 @@
+import React from "react";
+import Card from "@material-ui/core/Card";
+import CardContent from "@material-ui/core/CardContent";
+import Typography from "@material-ui/core/Typography";
+import { useIntl, FormattedMessage } from "react-intl";
+import makeStyles from "@material-ui/core/styles/makeStyles";
+
+import CardTitle from "@saleor/components/CardTitle";
+import { WarehouseDetails_warehouse_shippingZones_edges_node } from "@saleor/warehouses/types/WarehouseDetails";
+import { renderCollection, maybe } from "@saleor/misc";
+import Link from "@saleor/components/Link";
+import Skeleton from "@saleor/components/Skeleton";
+
+export interface WarehouseInfoProps {
+ zones: WarehouseDetails_warehouse_shippingZones_edges_node[];
+ onShippingZoneClick: (id: string) => void;
+}
+
+const useStyles = makeStyles(
+ theme => ({
+ link: {
+ "&:not(:last-of-type)": {
+ marginBottom: theme.spacing()
+ }
+ }
+ }),
+ {
+ name: "WarehouseInfoProps"
+ }
+);
+
+const WarehouseInfo: React.FC = ({
+ zones,
+ onShippingZoneClick
+}) => {
+ const classes = useStyles({});
+ const intl = useIntl();
+
+ return (
+
+
+
+ {renderCollection(
+ zones,
+ zone =>
+ maybe(
+ () => (
+
+ onShippingZoneClick(zone.id)}>
+ {zone.name}
+
+
+ ),
+
+ ),
+ () => (
+
+
+
+ )
+ )}
+
+
+ );
+};
+
+WarehouseInfo.displayName = "WarehouseInfo";
+export default WarehouseInfo;
diff --git a/src/warehouses/components/WarehouseZones/index.ts b/src/warehouses/components/WarehouseZones/index.ts
new file mode 100644
index 000000000..c0a280252
--- /dev/null
+++ b/src/warehouses/components/WarehouseZones/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseZones";
+export * from "./WarehouseZones";
diff --git a/src/warehouses/index.tsx b/src/warehouses/index.tsx
index 0b37a9da5..b94af8c1a 100644
--- a/src/warehouses/index.tsx
+++ b/src/warehouses/index.tsx
@@ -7,17 +7,14 @@ import { useIntl } from "react-intl";
import { asSortParams } from "@saleor/utils/sort";
import { WindowTitle } from "../components/WindowTitle";
import {
- // warehouseAddPath,
- // WarehouseAddUrlQueryParams,
warehouseListPath,
WarehouseListUrlQueryParams,
- // warehousePath,
- // WarehouseUrlQueryParams,
+ warehousePath,
+ WarehouseUrlQueryParams,
WarehouseListUrlSortField,
warehouseAddPath
} from "./urls";
-// import WarehouseCreateComponent from "./views/WarehouseCreate";
-// import WarehouseDetailsComponent from "./views/WarehouseDetails";
+import WarehouseDetailsComponent from "./views/WarehouseDetails";
import WarehouseListComponent from "./views/WarehouseList";
import WarehouseCreate from "./views/WarehouseCreate";
@@ -31,19 +28,19 @@ const WarehouseList: React.FC = ({ location }) => {
return ;
};
-// const WarehouseDetails: React.FC> = ({
-// location,
-// match
-// }) => {
-// const qs = parseQs(location.search.substr(1));
-// const params: WarehouseUrlQueryParams = qs;
-// return (
-//
-// );
-// };
+const WarehouseDetails: React.FC> = ({
+ location,
+ match
+}) => {
+ const qs = parseQs(location.search.substr(1));
+ const params: WarehouseUrlQueryParams = qs;
+ return (
+
+ );
+};
export const WarehouseSection: React.FC = () => {
const intl = useIntl();
@@ -54,7 +51,7 @@ export const WarehouseSection: React.FC = () => {
- {/* */}
+
>
);
diff --git a/src/warehouses/mutations.ts b/src/warehouses/mutations.ts
index 9611cac88..26a9b2805 100644
--- a/src/warehouses/mutations.ts
+++ b/src/warehouses/mutations.ts
@@ -5,6 +5,10 @@ import {
WarehouseCreate,
WarehouseCreateVariables
} from "./types/WarehouseCreate";
+import {
+ WarehouseUpdate,
+ WarehouseUpdateVariables
+} from "./types/WarehouseUpdate";
import {
WarehouseDelete,
WarehouseDeleteVariables
@@ -44,3 +48,22 @@ export const useWarehouseCreate = makeMutation<
WarehouseCreate,
WarehouseCreateVariables
>(createWarehouse);
+
+const updateWarehouse = gql`
+ ${warehouseDetailsFragment}
+ mutation WarehouseUpdate($id: ID!, $input: WarehouseUpdateInput!) {
+ updateWarehouse(id: $id, input: $input) {
+ errors {
+ field
+ message
+ }
+ warehouse {
+ ...WarehouseDetailsFragment
+ }
+ }
+ }
+`;
+export const useWarehouseUpdate = makeMutation<
+ WarehouseUpdate,
+ WarehouseUpdateVariables
+>(updateWarehouse);
diff --git a/src/warehouses/queries.ts b/src/warehouses/queries.ts
index d75984c68..6eeefdeb4 100644
--- a/src/warehouses/queries.ts
+++ b/src/warehouses/queries.ts
@@ -4,6 +4,10 @@ import makeQuery from "@saleor/hooks/makeQuery";
import { pageInfoFragment } from "@saleor/queries";
import { fragmentAddress } from "@saleor/orders/queries";
import { WarehouseList, WarehouseListVariables } from "./types/WarehouseList";
+import {
+ WarehouseDetails,
+ WarehouseDetailsVariables
+} from "./types/WarehouseDetails";
export const warehouseFragment = gql`
fragment WarehouseFragment on Warehouse {
@@ -65,3 +69,16 @@ export const useWarehouseList = makeQuery<
WarehouseList,
WarehouseListVariables
>(warehouseList);
+
+const warehouseDetails = gql`
+ ${warehouseDetailsFragment}
+ query WarehouseDetails($id: ID!) {
+ warehouse(id: $id) {
+ ...WarehouseDetailsFragment
+ }
+ }
+`;
+export const useWarehouseDetails = makeQuery<
+ WarehouseDetails,
+ WarehouseDetailsVariables
+>(warehouseDetails);
diff --git a/src/warehouses/types/WarehouseDetails.ts b/src/warehouses/types/WarehouseDetails.ts
new file mode 100644
index 000000000..b48eb255a
--- /dev/null
+++ b/src/warehouses/types/WarehouseDetails.ts
@@ -0,0 +1,61 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+// ====================================================
+// GraphQL query operation: WarehouseDetails
+// ====================================================
+
+export interface WarehouseDetails_warehouse_shippingZones_edges_node {
+ __typename: "ShippingZone";
+ id: string;
+ name: string;
+}
+
+export interface WarehouseDetails_warehouse_shippingZones_edges {
+ __typename: "ShippingZoneCountableEdge";
+ node: WarehouseDetails_warehouse_shippingZones_edges_node;
+}
+
+export interface WarehouseDetails_warehouse_shippingZones {
+ __typename: "ShippingZoneCountableConnection";
+ edges: WarehouseDetails_warehouse_shippingZones_edges[];
+}
+
+export interface WarehouseDetails_warehouse_address_country {
+ __typename: "CountryDisplay";
+ code: string;
+ country: string;
+}
+
+export interface WarehouseDetails_warehouse_address {
+ __typename: "Address";
+ city: string;
+ cityArea: string;
+ companyName: string;
+ country: WarehouseDetails_warehouse_address_country;
+ countryArea: string;
+ firstName: string;
+ id: string;
+ lastName: string;
+ phone: string | null;
+ postalCode: string;
+ streetAddress1: string;
+ streetAddress2: string;
+}
+
+export interface WarehouseDetails_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+ shippingZones: WarehouseDetails_warehouse_shippingZones;
+ address: WarehouseDetails_warehouse_address;
+}
+
+export interface WarehouseDetails {
+ warehouse: WarehouseDetails_warehouse | null;
+}
+
+export interface WarehouseDetailsVariables {
+ id: string;
+}
diff --git a/src/warehouses/types/WarehouseUpdate.ts b/src/warehouses/types/WarehouseUpdate.ts
new file mode 100644
index 000000000..345f6f9fb
--- /dev/null
+++ b/src/warehouses/types/WarehouseUpdate.ts
@@ -0,0 +1,76 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+import { WarehouseUpdateInput } from "./../../types/globalTypes";
+
+// ====================================================
+// GraphQL mutation operation: WarehouseUpdate
+// ====================================================
+
+export interface WarehouseUpdate_updateWarehouse_errors {
+ __typename: "Error";
+ field: string | null;
+ message: string | null;
+}
+
+export interface WarehouseUpdate_updateWarehouse_warehouse_shippingZones_edges_node {
+ __typename: "ShippingZone";
+ id: string;
+ name: string;
+}
+
+export interface WarehouseUpdate_updateWarehouse_warehouse_shippingZones_edges {
+ __typename: "ShippingZoneCountableEdge";
+ node: WarehouseUpdate_updateWarehouse_warehouse_shippingZones_edges_node;
+}
+
+export interface WarehouseUpdate_updateWarehouse_warehouse_shippingZones {
+ __typename: "ShippingZoneCountableConnection";
+ edges: WarehouseUpdate_updateWarehouse_warehouse_shippingZones_edges[];
+}
+
+export interface WarehouseUpdate_updateWarehouse_warehouse_address_country {
+ __typename: "CountryDisplay";
+ code: string;
+ country: string;
+}
+
+export interface WarehouseUpdate_updateWarehouse_warehouse_address {
+ __typename: "Address";
+ city: string;
+ cityArea: string;
+ companyName: string;
+ country: WarehouseUpdate_updateWarehouse_warehouse_address_country;
+ countryArea: string;
+ firstName: string;
+ id: string;
+ lastName: string;
+ phone: string | null;
+ postalCode: string;
+ streetAddress1: string;
+ streetAddress2: string;
+}
+
+export interface WarehouseUpdate_updateWarehouse_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+ shippingZones: WarehouseUpdate_updateWarehouse_warehouse_shippingZones;
+ address: WarehouseUpdate_updateWarehouse_warehouse_address;
+}
+
+export interface WarehouseUpdate_updateWarehouse {
+ __typename: "WarehouseUpdate";
+ errors: WarehouseUpdate_updateWarehouse_errors[] | null;
+ warehouse: WarehouseUpdate_updateWarehouse_warehouse | null;
+}
+
+export interface WarehouseUpdate {
+ updateWarehouse: WarehouseUpdate_updateWarehouse | null;
+}
+
+export interface WarehouseUpdateVariables {
+ id: string;
+ input: WarehouseUpdateInput;
+}
diff --git a/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx b/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx
new file mode 100644
index 000000000..792ee6715
--- /dev/null
+++ b/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx
@@ -0,0 +1,84 @@
+import React from "react";
+import { useIntl } from "react-intl";
+
+import WarehouseDetailsPage from "@saleor/warehouses/components/WarehouseDetailsPage";
+import useNavigator from "@saleor/hooks/useNavigator";
+import {
+ warehouseListUrl,
+ WarehouseUrlQueryParams
+} from "@saleor/warehouses/urls";
+import { useWarehouseDetails } from "@saleor/warehouses/queries";
+import { commonMessages } from "@saleor/intl";
+import useNotifier from "@saleor/hooks/useNotifier";
+import { maybe, findValueInEnum, getMutationStatus } from "@saleor/misc";
+import { CountryCode } from "@saleor/types/globalTypes";
+import useShop from "@saleor/hooks/useShop";
+import { WindowTitle } from "@saleor/components/WindowTitle";
+import { useWarehouseUpdate } from "@saleor/warehouses/mutations";
+import { shippingZoneUrl } from "@saleor/shipping/urls";
+
+export interface WarehouseDetailsProps {
+ id: string;
+ params: WarehouseUrlQueryParams;
+}
+
+const WarehouseDetails: React.FC = ({ id, params }) => {
+ const intl = useIntl();
+ const navigate = useNavigator();
+ const notify = useNotifier();
+ const shop = useShop();
+ const { data, loading } = useWarehouseDetails({
+ displayLoader: true,
+ require: ["warehouse"],
+ variables: { id }
+ });
+ const [updateWarehouse, updateWarehouseOpts] = useWarehouseUpdate({
+ onCompleted: data => {
+ if (data.updateWarehouse.errors.length === 0) {
+ notify({ text: intl.formatMessage(commonMessages.savedChanges) });
+ }
+ }
+ });
+ const updateWarehouseTransitionState = getMutationStatus(updateWarehouseOpts);
+
+ return (
+ <>
+ data.warehouse.name)} />
+ navigate(warehouseListUrl())}
+ disabled={loading || updateWarehouseOpts.loading}
+ errors={maybe(
+ () => updateWarehouseOpts.data.updateWarehouse.errors,
+ []
+ )}
+ saveButtonBarState={updateWarehouseTransitionState}
+ shop={shop}
+ warehouse={maybe(() => data.warehouse)}
+ onShippingZoneClick={id => navigate(shippingZoneUrl(id))}
+ onSubmit={data =>
+ updateWarehouse({
+ variables: {
+ id,
+ input: {
+ address: {
+ city: data.city,
+ cityArea: data.cityArea,
+ country: findValueInEnum(data.country, CountryCode),
+ countryArea: data.countryArea,
+ phone: data.phone,
+ postalCode: data.postalCode,
+ streetAddress1: data.streetAddress1,
+ streetAddress2: data.streetAddress2
+ },
+ name: data.name
+ }
+ }
+ })
+ }
+ />
+ >
+ );
+};
+
+WarehouseDetails.displayName = "WarehouseDetails";
+export default WarehouseDetails;
diff --git a/src/warehouses/views/WarehouseDetails/index.ts b/src/warehouses/views/WarehouseDetails/index.ts
new file mode 100644
index 000000000..a8e1f03bc
--- /dev/null
+++ b/src/warehouses/views/WarehouseDetails/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./WarehouseDetails";
+export * from "./WarehouseDetails";
From e5274afa6420c86295c8db3b57e45f557bd5f554 Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Thu, 30 Jan 2020 16:43:55 +0100
Subject: [PATCH 08/88] Add warehouse deleting
---
.../WarehouseDetailsPage.tsx | 3 ++
.../WarehouseDetails/WarehouseDetails.tsx | 40 ++++++++++++++++++-
2 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx
index 1d6b02689..97e09ee5c 100644
--- a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx
+++ b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx
@@ -34,6 +34,7 @@ export interface WarehouseDetailsPageProps {
shop: ShopInfo_shop;
warehouse: WarehouseDetails_warehouse;
onBack: () => void;
+ onDelete: () => void;
onShippingZoneClick: (id: string) => void;
onSubmit: (data: WarehouseDetailsPageFormData) => void;
}
@@ -45,6 +46,7 @@ const WarehouseDetailsPage: React.FC = ({
shop,
warehouse,
onBack,
+ onDelete,
onShippingZoneClick,
onSubmit
}) => {
@@ -127,6 +129,7 @@ const WarehouseDetailsPage: React.FC = ({
diff --git a/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx b/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx
index 792ee6715..a59481e35 100644
--- a/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx
+++ b/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx
@@ -5,7 +5,8 @@ import WarehouseDetailsPage from "@saleor/warehouses/components/WarehouseDetails
import useNavigator from "@saleor/hooks/useNavigator";
import {
warehouseListUrl,
- WarehouseUrlQueryParams
+ WarehouseUrlQueryParams,
+ warehouseUrl
} from "@saleor/warehouses/urls";
import { useWarehouseDetails } from "@saleor/warehouses/queries";
import { commonMessages } from "@saleor/intl";
@@ -14,8 +15,13 @@ import { maybe, findValueInEnum, getMutationStatus } from "@saleor/misc";
import { CountryCode } from "@saleor/types/globalTypes";
import useShop from "@saleor/hooks/useShop";
import { WindowTitle } from "@saleor/components/WindowTitle";
-import { useWarehouseUpdate } from "@saleor/warehouses/mutations";
+import {
+ useWarehouseUpdate,
+ useWarehouseDelete
+} from "@saleor/warehouses/mutations";
import { shippingZoneUrl } from "@saleor/shipping/urls";
+import WarehouseDeleteDialog from "@saleor/warehouses/components/WarehouseDeleteDialog";
+import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
export interface WarehouseDetailsProps {
id: string;
@@ -41,6 +47,24 @@ const WarehouseDetails: React.FC = ({ id, params }) => {
});
const updateWarehouseTransitionState = getMutationStatus(updateWarehouseOpts);
+ const [deleteWarehouse, deleteWarehouseOpts] = useWarehouseDelete({
+ onCompleted: data => {
+ if (data.deleteWarehouse.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ navigate(warehouseListUrl());
+ }
+ }
+ });
+ const deleteWarehouseTransitionState = getMutationStatus(deleteWarehouseOpts);
+
+ const [openModal, closeModal] = createDialogActionHandlers(
+ navigate,
+ params => warehouseUrl(id, params),
+ params
+ );
+
return (
<>
data.warehouse.name)} />
@@ -54,6 +78,7 @@ const WarehouseDetails: React.FC = ({ id, params }) => {
saveButtonBarState={updateWarehouseTransitionState}
shop={shop}
warehouse={maybe(() => data.warehouse)}
+ onDelete={() => openModal("delete")}
onShippingZoneClick={id => navigate(shippingZoneUrl(id))}
onSubmit={data =>
updateWarehouse({
@@ -76,6 +101,17 @@ const WarehouseDetails: React.FC = ({ id, params }) => {
})
}
/>
+ data.warehouse.name)}
+ onClose={closeModal}
+ onConfirm={() =>
+ deleteWarehouse({
+ variables: { id }
+ })
+ }
+ open={params.action === "delete"}
+ />
>
);
};
From 34698b7d6fab453e12a7b06dca99389b198db6fd Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Thu, 30 Jan 2020 17:11:34 +0100
Subject: [PATCH 09/88] Fix rtypes
---
.../CompanyAddressInput/CompanyAddressInput.tsx | 4 +++-
.../WarehouseCreatePage.stories.tsx | 10 +++++++---
.../WarehouseCreatePage/WarehouseCreatePage.tsx | 11 ++++-------
.../WarehouseDetailsPage.stories.tsx | 9 ++++++++-
.../WarehouseDetailsPage/WarehouseDetailsPage.tsx | 10 ++++------
.../views/WarehouseCreate/WarehouseCreate.tsx | 6 +++---
.../views/WarehouseDetails/WarehouseDetails.tsx | 4 ++--
7 files changed, 31 insertions(+), 23 deletions(-)
diff --git a/src/components/CompanyAddressInput/CompanyAddressInput.tsx b/src/components/CompanyAddressInput/CompanyAddressInput.tsx
index 927a12d25..bdd2374a4 100644
--- a/src/components/CompanyAddressInput/CompanyAddressInput.tsx
+++ b/src/components/CompanyAddressInput/CompanyAddressInput.tsx
@@ -161,7 +161,9 @@ const CompanyAddressInput: React.FC = props => {
value={data.country}
choices={countries}
InputProps={{
- autoComplete: "off"
+ inputProps: {
+ autocomplete: "plsdontautocomplete" // Somehow it shuts it down
+ }
}}
/>
({
+ __typename: "CountryDisplay",
+ code: c.code,
+ country: c.name
+ })),
disabled: false,
errors: [],
onBack: () => undefined,
onSubmit: () => undefined,
- saveButtonBarState: "default",
- shop
+ saveButtonBarState: "default"
};
storiesOf("Views / Warehouses / Create warehouse", module)
.addDecorator(Decorator)
diff --git a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx
index 64bde0713..ec50f6a61 100644
--- a/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx
+++ b/src/warehouses/components/WarehouseCreatePage/WarehouseCreatePage.tsx
@@ -14,8 +14,7 @@ import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/single
import { mapCountriesToChoices } from "@saleor/utils/maps";
import useAddressValidation from "@saleor/hooks/useAddressValidation";
import useStateFromProps from "@saleor/hooks/useStateFromProps";
-import { maybe } from "@saleor/misc";
-import { ShopInfo_shop } from "@saleor/components/Shop/types/ShopInfo";
+import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo";
import AppHeader from "@saleor/components/AppHeader";
import PageHeader from "@saleor/components/PageHeader";
import { sectionNames } from "@saleor/intl";
@@ -25,10 +24,10 @@ export interface WarehouseCreatePageFormData extends AddressTypeInput {
name: string;
}
export interface WarehouseCreatePageProps {
+ countries: ShopInfo_shop_countries[];
disabled: boolean;
errors: UserError[];
saveButtonBarState: ConfirmButtonTransitionState;
- shop: ShopInfo_shop;
onBack: () => void;
onSubmit: (data: WarehouseCreatePageFormData) => void;
}
@@ -46,10 +45,10 @@ const initialForm: WarehouseCreatePageFormData = {
};
const WarehouseCreatePage: React.FC = ({
+ countries,
disabled,
errors: apiErrors,
saveButtonBarState,
- shop,
onBack,
onSubmit
}) => {
@@ -68,9 +67,7 @@ const WarehouseCreatePage: React.FC = ({
onSubmit={handleSubmit}
>
{({ change, data, errors, submit }) => {
- const countryChoices = mapCountriesToChoices(
- maybe(() => shop.countries, [])
- );
+ const countryChoices = mapCountriesToChoices(countries);
const handleCountryChange = createSingleAutocompleteSelectHandler(
change,
setDisplayCountry,
diff --git a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.stories.tsx b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.stories.tsx
index e42d88ad7..5a3dd646b 100644
--- a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.stories.tsx
+++ b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.stories.tsx
@@ -1,7 +1,7 @@
import { storiesOf } from "@storybook/react";
import React from "react";
-import { address } from "@saleor/fixtures";
+import { address, countries } from "@saleor/fixtures";
import Decorator from "@saleor/storybook/Decorator";
import { formError } from "@saleor/storybook/misc";
import { warehouseList } from "../../fixtures";
@@ -11,9 +11,16 @@ import WarehouseDetailsPage, {
} from "./WarehouseDetailsPage";
const props: WarehouseDetailsPageProps = {
+ countries: countries.map(c => ({
+ __typename: "CountryDisplay",
+ code: c.code,
+ country: c.name
+ })),
disabled: false,
errors: [],
onBack: () => undefined,
+ onDelete: () => undefined,
+ onShippingZoneClick: () => undefined,
onSubmit: () => undefined,
saveButtonBarState: "default",
warehouse: {
diff --git a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx
index 97e09ee5c..148dda244 100644
--- a/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx
+++ b/src/warehouses/components/WarehouseDetailsPage/WarehouseDetailsPage.tsx
@@ -15,7 +15,7 @@ import { mapCountriesToChoices } from "@saleor/utils/maps";
import useAddressValidation from "@saleor/hooks/useAddressValidation";
import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { maybe, findValueInEnum } from "@saleor/misc";
-import { ShopInfo_shop } from "@saleor/components/Shop/types/ShopInfo";
+import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo";
import AppHeader from "@saleor/components/AppHeader";
import PageHeader from "@saleor/components/PageHeader";
import { sectionNames } from "@saleor/intl";
@@ -28,10 +28,10 @@ export interface WarehouseDetailsPageFormData extends AddressTypeInput {
name: string;
}
export interface WarehouseDetailsPageProps {
+ countries: ShopInfo_shop_countries[];
disabled: boolean;
errors: UserError[];
saveButtonBarState: ConfirmButtonTransitionState;
- shop: ShopInfo_shop;
warehouse: WarehouseDetails_warehouse;
onBack: () => void;
onDelete: () => void;
@@ -40,10 +40,10 @@ export interface WarehouseDetailsPageProps {
}
const WarehouseDetailsPage: React.FC = ({
+ countries,
disabled,
errors: apiErrors,
saveButtonBarState,
- shop,
warehouse,
onBack,
onDelete,
@@ -79,9 +79,7 @@ const WarehouseDetailsPage: React.FC = ({
onSubmit={handleSubmit}
>
{({ change, data, errors, submit }) => {
- const countryChoices = mapCountriesToChoices(
- maybe(() => shop.countries, [])
- );
+ const countryChoices = mapCountriesToChoices(countries);
const handleCountryChange = createSingleAutocompleteSelectHandler(
change,
setDisplayCountry,
diff --git a/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx b/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx
index 758592db0..4698713ce 100644
--- a/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx
+++ b/src/warehouses/views/WarehouseCreate/WarehouseCreate.tsx
@@ -36,13 +36,14 @@ const WarehouseCreate: React.FC = () => {
})}
/>
navigate(warehouseListUrl())}
+ countries={maybe(() => shop.countries, [])}
disabled={createWarehouseOpts.loading}
errors={maybe(
() => createWarehouseOpts.data.createWarehouse.errors,
[]
)}
- shop={shop}
+ saveButtonBarState={createWarehouseTransitionState}
+ onBack={() => navigate(warehouseListUrl())}
onSubmit={data =>
createWarehouse({
variables: {
@@ -62,7 +63,6 @@ const WarehouseCreate: React.FC = () => {
}
})
}
- saveButtonBarState={createWarehouseTransitionState}
/>
>
);
diff --git a/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx b/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx
index a59481e35..5cd0ec2f4 100644
--- a/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx
+++ b/src/warehouses/views/WarehouseDetails/WarehouseDetails.tsx
@@ -69,15 +69,15 @@ const WarehouseDetails: React.FC = ({ id, params }) => {
<>
data.warehouse.name)} />
navigate(warehouseListUrl())}
+ countries={maybe(() => shop.countries, [])}
disabled={loading || updateWarehouseOpts.loading}
errors={maybe(
() => updateWarehouseOpts.data.updateWarehouse.errors,
[]
)}
saveButtonBarState={updateWarehouseTransitionState}
- shop={shop}
warehouse={maybe(() => data.warehouse)}
+ onBack={() => navigate(warehouseListUrl())}
onDelete={() => openModal("delete")}
onShippingZoneClick={id => navigate(shippingZoneUrl(id))}
onSubmit={data =>
From ed3e9fbc45d83f3abca3ba45fc6da219ea8d13e6 Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Mon, 3 Feb 2020 12:01:18 +0100
Subject: [PATCH 10/88] wip
---
src/searches/types/SearchWarehouses.ts | 42 ++++
src/searches/useWarehouseSearch.ts | 33 +++
.../ShippingZoneDetailsPage.tsx | 198 +++++++++++-------
.../ShippingZoneWarehouses.tsx | 60 ++++++
.../ShippingZoneWarehouses/index.ts | 2 +
src/shipping/queries.ts | 4 +
src/shipping/types/CreateShippingRate.ts | 7 +
src/shipping/types/DeleteShippingRate.ts | 7 +
src/shipping/types/ShippingZone.ts | 7 +
.../types/ShippingZoneDetailsFragment.ts | 7 +
.../views/ShippingZoneDetails/index.tsx | 29 ++-
11 files changed, 316 insertions(+), 80 deletions(-)
create mode 100644 src/searches/types/SearchWarehouses.ts
create mode 100644 src/searches/useWarehouseSearch.ts
create mode 100644 src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx
create mode 100644 src/shipping/components/ShippingZoneWarehouses/index.ts
diff --git a/src/searches/types/SearchWarehouses.ts b/src/searches/types/SearchWarehouses.ts
new file mode 100644
index 000000000..beab7185b
--- /dev/null
+++ b/src/searches/types/SearchWarehouses.ts
@@ -0,0 +1,42 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+// ====================================================
+// GraphQL query operation: SearchWarehouses
+// ====================================================
+
+export interface SearchWarehouses_search_edges_node {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
+export interface SearchWarehouses_search_edges {
+ __typename: "WarehouseCountableEdge";
+ node: SearchWarehouses_search_edges_node;
+}
+
+export interface SearchWarehouses_search_pageInfo {
+ __typename: "PageInfo";
+ endCursor: string | null;
+ hasNextPage: boolean;
+ hasPreviousPage: boolean;
+ startCursor: string | null;
+}
+
+export interface SearchWarehouses_search {
+ __typename: "WarehouseCountableConnection";
+ edges: SearchWarehouses_search_edges[];
+ pageInfo: SearchWarehouses_search_pageInfo;
+}
+
+export interface SearchWarehouses {
+ search: SearchWarehouses_search | null;
+}
+
+export interface SearchWarehousesVariables {
+ after?: string | null;
+ first: number;
+ query: string;
+}
diff --git a/src/searches/useWarehouseSearch.ts b/src/searches/useWarehouseSearch.ts
new file mode 100644
index 000000000..b5b0e6048
--- /dev/null
+++ b/src/searches/useWarehouseSearch.ts
@@ -0,0 +1,33 @@
+import gql from "graphql-tag";
+
+import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch";
+import { pageInfoFragment } from "@saleor/queries";
+import {
+ SearchWarehouses,
+ SearchWarehousesVariables
+} from "./types/SearchWarehouses";
+
+export const searchWarehouses = gql`
+ ${pageInfoFragment}
+ query SearchWarehouses($after: String, $first: Int!, $query: String!) {
+ search: warehouses(
+ after: $after
+ first: $first
+ filter: { search: $query }
+ ) {
+ edges {
+ node {
+ id
+ name
+ }
+ }
+ pageInfo {
+ ...PageInfoFragment
+ }
+ }
+ }
+`;
+
+export default makeTopLevelSearch(
+ searchWarehouses
+);
diff --git a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx
index fa48d8624..f08002d62 100644
--- a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx
+++ b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx
@@ -11,14 +11,21 @@ import Grid from "@saleor/components/Grid";
import PageHeader from "@saleor/components/PageHeader";
import SaveButtonBar from "@saleor/components/SaveButtonBar";
import { ShippingErrorFragment } from "@saleor/shipping/types/ShippingErrorFragment";
+import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
+import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
import { maybe, getStringOrPlaceholder } from "../../../misc";
import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
-import { ShippingZoneDetailsFragment } from "../../types/ShippingZoneDetailsFragment";
+import {
+ ShippingZoneDetailsFragment,
+ ShippingZoneDetailsFragment_warehouses
+} from "../../types/ShippingZoneDetailsFragment";
import ShippingZoneInfo from "../ShippingZoneInfo";
import ShippingZoneRates from "../ShippingZoneRates";
+import ShippingZoneWarehouses from "../ShippingZoneWarehouses";
export interface FormData {
name: string;
+ warehouses: string[];
}
export interface ShippingZoneDetailsPageProps {
@@ -26,6 +33,7 @@ export interface ShippingZoneDetailsPageProps {
errors: ShippingErrorFragment[];
saveButtonBarState: ConfirmButtonTransitionState;
shippingZone: ShippingZoneDetailsFragment;
+ warehouses: ShippingZoneDetailsFragment_warehouses[];
onBack: () => void;
onCountryAdd: () => void;
onCountryRemove: (code: string) => void;
@@ -38,6 +46,15 @@ export interface ShippingZoneDetailsPageProps {
onWeightRateEdit: (id: string) => void;
}
+function warehouseToChoice(
+ warehouse: Record<"id" | "name", string>
+): MultiAutocompleteChoiceType {
+ return {
+ label: warehouse.name,
+ value: warehouse.id
+ };
+}
+
const ShippingZoneDetailsPage: React.FC = ({
disabled,
errors,
@@ -52,90 +69,117 @@ const ShippingZoneDetailsPage: React.FC = ({
onWeightRateAdd,
onWeightRateEdit,
saveButtonBarState,
- shippingZone
+ shippingZone,
+ warehouses
}) => {
const intl = useIntl();
const initialForm: FormData = {
- name: shippingZone?.name || ""
+ name: shippingZone?.name || "",
+ warehouses: shippingZone?.warehouses.map(warehouse => warehouse.id) || []
};
+ const [warehouseDisplayValues, setWarehouseDisplayValues] = React.useState(
+ shippingZone?.warehouses.map(warehouseToChoice)
+ );
+
+ const warehouseChoices = warehouses.map(warehouseToChoice);
return (
);
};
diff --git a/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx b/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx
new file mode 100644
index 000000000..6e1eeffcb
--- /dev/null
+++ b/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx
@@ -0,0 +1,60 @@
+import Card from "@material-ui/core/Card";
+import CardContent from "@material-ui/core/CardContent";
+import React from "react";
+import { useIntl } from "react-intl";
+
+import CardTitle from "@saleor/components/CardTitle";
+import { FetchMoreProps } from "@saleor/types";
+import { FormChange } from "@saleor/hooks/useForm";
+import MultiAutocompleteSelectField, {
+ MultiAutocompleteChoiceType
+} from "@saleor/components/MultiAutocompleteSelectField";
+
+interface ShippingZoneWarehousesFormData {
+ warehouses: string[];
+}
+interface ShippingZonewWarehousesProps extends FetchMoreProps {
+ data: ShippingZoneWarehousesFormData;
+ displayValue: MultiAutocompleteChoiceType[];
+ warehouses: MultiAutocompleteChoiceType[];
+ onChange: FormChange;
+}
+
+export const ShippingZoneWarehouses: React.FC = props => {
+ const {
+ data,
+ displayValue,
+ hasMore,
+ loading,
+ onChange,
+ onFetchMore,
+ warehouses
+ } = props;
+ const intl = useIntl();
+
+ return (
+
+
+
+ undefined}
+ hasMore={hasMore}
+ loading={loading}
+ name="warehouse"
+ onChange={onChange}
+ onFetchMore={onFetchMore}
+ value={data.warehouses}
+ />
+
+
+ );
+};
+ShippingZoneWarehouses.displayName = "ShippingZoneWarehouses";
+export default ShippingZoneWarehouses;
diff --git a/src/shipping/components/ShippingZoneWarehouses/index.ts b/src/shipping/components/ShippingZoneWarehouses/index.ts
new file mode 100644
index 000000000..9719aa5e7
--- /dev/null
+++ b/src/shipping/components/ShippingZoneWarehouses/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./ShippingZoneWarehouses";
+export * from "./ShippingZoneWarehouses";
diff --git a/src/shipping/queries.ts b/src/shipping/queries.ts
index 9a4a1b4e9..8215a50bb 100644
--- a/src/shipping/queries.ts
+++ b/src/shipping/queries.ts
@@ -50,6 +50,10 @@ export const shippingZoneDetailsFragment = gql`
shippingMethods {
...ShippingMethodFragment
}
+ warehouses {
+ id
+ name
+ }
}
`;
diff --git a/src/shipping/types/CreateShippingRate.ts b/src/shipping/types/CreateShippingRate.ts
index c0d3a1e4a..7a29f3395 100644
--- a/src/shipping/types/CreateShippingRate.ts
+++ b/src/shipping/types/CreateShippingRate.ts
@@ -62,6 +62,12 @@ export interface CreateShippingRate_shippingPriceCreate_shippingZone_shippingMet
type: ShippingMethodTypeEnum | null;
}
+export interface CreateShippingRate_shippingPriceCreate_shippingZone_warehouses {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
export interface CreateShippingRate_shippingPriceCreate_shippingZone {
__typename: "ShippingZone";
id: string;
@@ -69,6 +75,7 @@ export interface CreateShippingRate_shippingPriceCreate_shippingZone {
name: string;
default: boolean;
shippingMethods: (CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods | null)[] | null;
+ warehouses: (CreateShippingRate_shippingPriceCreate_shippingZone_warehouses | null)[] | null;
}
export interface CreateShippingRate_shippingPriceCreate {
diff --git a/src/shipping/types/DeleteShippingRate.ts b/src/shipping/types/DeleteShippingRate.ts
index b4ffa0352..d3fafa9b6 100644
--- a/src/shipping/types/DeleteShippingRate.ts
+++ b/src/shipping/types/DeleteShippingRate.ts
@@ -62,6 +62,12 @@ export interface DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMet
type: ShippingMethodTypeEnum | null;
}
+export interface DeleteShippingRate_shippingPriceDelete_shippingZone_warehouses {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
export interface DeleteShippingRate_shippingPriceDelete_shippingZone {
__typename: "ShippingZone";
id: string;
@@ -69,6 +75,7 @@ export interface DeleteShippingRate_shippingPriceDelete_shippingZone {
name: string;
default: boolean;
shippingMethods: (DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods | null)[] | null;
+ warehouses: (DeleteShippingRate_shippingPriceDelete_shippingZone_warehouses | null)[] | null;
}
export interface DeleteShippingRate_shippingPriceDelete {
diff --git a/src/shipping/types/ShippingZone.ts b/src/shipping/types/ShippingZone.ts
index 7b8dc090b..091776cd3 100644
--- a/src/shipping/types/ShippingZone.ts
+++ b/src/shipping/types/ShippingZone.ts
@@ -56,6 +56,12 @@ export interface ShippingZone_shippingZone_shippingMethods {
type: ShippingMethodTypeEnum | null;
}
+export interface ShippingZone_shippingZone_warehouses {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
export interface ShippingZone_shippingZone {
__typename: "ShippingZone";
id: string;
@@ -63,6 +69,7 @@ export interface ShippingZone_shippingZone {
name: string;
default: boolean;
shippingMethods: (ShippingZone_shippingZone_shippingMethods | null)[] | null;
+ warehouses: (ShippingZone_shippingZone_warehouses | null)[] | null;
}
export interface ShippingZone {
diff --git a/src/shipping/types/ShippingZoneDetailsFragment.ts b/src/shipping/types/ShippingZoneDetailsFragment.ts
index 981e085a9..13bf1a398 100644
--- a/src/shipping/types/ShippingZoneDetailsFragment.ts
+++ b/src/shipping/types/ShippingZoneDetailsFragment.ts
@@ -56,6 +56,12 @@ export interface ShippingZoneDetailsFragment_shippingMethods {
type: ShippingMethodTypeEnum | null;
}
+export interface ShippingZoneDetailsFragment_warehouses {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
export interface ShippingZoneDetailsFragment {
__typename: "ShippingZone";
id: string;
@@ -63,4 +69,5 @@ export interface ShippingZoneDetailsFragment {
name: string;
default: boolean;
shippingMethods: (ShippingZoneDetailsFragment_shippingMethods | null)[] | null;
+ warehouses: (ShippingZoneDetailsFragment_warehouses | null)[] | null;
}
diff --git a/src/shipping/views/ShippingZoneDetails/index.tsx b/src/shipping/views/ShippingZoneDetails/index.tsx
index bf03ddef6..ec889f9bc 100644
--- a/src/shipping/views/ShippingZoneDetails/index.tsx
+++ b/src/shipping/views/ShippingZoneDetails/index.tsx
@@ -4,6 +4,9 @@ import { useIntl } from "react-intl";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import { commonMessages } from "@saleor/intl";
+import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
+import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
+import { useWarehouseUpdate } from "@saleor/warehouses/mutations";
import { maybe } from "../../../misc";
import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
import ShippingZoneDetailsPage from "../../components/ShippingZoneDetailsPage";
@@ -33,6 +36,14 @@ const ShippingZoneDetails: React.FC = ({
const navigate = useNavigator();
const notify = useNotifier();
const intl = useIntl();
+ const [updateWarehouse, updateWarehouseOpts] = useWarehouseUpdate({});
+
+ const {
+ search: searchWarehouses,
+ result: searchWarehousesOpts
+ } = useWarehouseSearch({
+ variables: DEFAULT_INITIAL_SEARCH_DATA
+ });
const closeModal = () => navigate(shippingZoneUrl(id), true);
@@ -146,14 +157,19 @@ const ShippingZoneDetails: React.FC = ({
})
)
}
- onSubmit={formData =>
+ onSubmit={formData => {
ops.shippingZoneUpdate.mutate({
id,
input: {
name: formData.name
}
- })
- }
+ });
+ updateWarehouse({
+ variables: {
+ id: formData.warehouse
+ }
+ });
+ }}
onWeightRateAdd={() =>
navigate(
shippingZoneUrl(id, {
@@ -172,6 +188,13 @@ const ShippingZoneDetails: React.FC = ({
}
saveButtonBarState={ops.shippingZoneUpdate.opts.status}
shippingZone={maybe(() => data.shippingZone)}
+ warehouses={maybe(
+ () =>
+ searchWarehousesOpts.data.search.edges.map(
+ edge => edge.node
+ ),
+ []
+ )}
/>
Date: Wed, 5 Feb 2020 15:11:37 +0100
Subject: [PATCH 11/88] Use apollo hooks
---
.../ShippingZoneDetailsPage.tsx | 2 +-
src/shipping/mutations.ts | 70 ++-
src/shipping/queries.ts | 8 +-
.../types/AssignShippingZoneToWarehouse.ts | 29 ++
.../types/UnassignShippingZoneToWarehouse.ts | 29 ++
.../ShippingZoneDetailsDialogs.tsx | 244 ---------
.../views/ShippingZoneDetails/data.ts | 62 +++
.../views/ShippingZoneDetails/index.tsx | 488 +++++++++++-------
src/types/globalTypes.ts | 18 +-
9 files changed, 503 insertions(+), 447 deletions(-)
create mode 100644 src/shipping/types/AssignShippingZoneToWarehouse.ts
create mode 100644 src/shipping/types/UnassignShippingZoneToWarehouse.ts
delete mode 100644 src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx
create mode 100644 src/shipping/views/ShippingZoneDetails/data.ts
diff --git a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx
index f08002d62..afaa9a798 100644
--- a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx
+++ b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx
@@ -13,7 +13,7 @@ import SaveButtonBar from "@saleor/components/SaveButtonBar";
import { ShippingErrorFragment } from "@saleor/shipping/types/ShippingErrorFragment";
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
-import { maybe, getStringOrPlaceholder } from "../../../misc";
+import { maybe } from "../../../misc";
import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
import {
ShippingZoneDetailsFragment,
diff --git a/src/shipping/mutations.ts b/src/shipping/mutations.ts
index ab550e936..6408f1a3d 100644
--- a/src/shipping/mutations.ts
+++ b/src/shipping/mutations.ts
@@ -1,6 +1,6 @@
import gql from "graphql-tag";
-import { TypedMutation } from "../mutations";
+import makeMutation from "@saleor/hooks/makeMutation";
import { countryFragment } from "../taxes/queries";
import { shippingMethodFragment, shippingZoneDetailsFragment } from "./queries";
import {
@@ -39,6 +39,14 @@ import {
UpdateShippingZone,
UpdateShippingZoneVariables
} from "./types/UpdateShippingZone";
+import {
+ AssignShippingZoneToWarehouse,
+ AssignShippingZoneToWarehouseVariables
+} from "./types/AssignShippingZoneToWarehouse";
+import {
+ UnassignShippingZoneToWarehouse,
+ UnassignShippingZoneToWarehouseVariables
+} from "./types/UnassignShippingZoneToWarehouse";
export const shippingErrorFragment = gql`
fragment ShippingErrorFragment on ShippingError {
@@ -57,7 +65,7 @@ const deleteShippingZone = gql`
}
}
`;
-export const TypedDeleteShippingZone = TypedMutation<
+export const useShippingZoneDelete = makeMutation<
DeleteShippingZone,
DeleteShippingZoneVariables
>(deleteShippingZone);
@@ -72,7 +80,7 @@ const bulkDeleteShippingZone = gql`
}
}
`;
-export const TypedBulkDeleteShippingZone = TypedMutation<
+export const useShippingZoneBulkDelete = makeMutation<
BulkDeleteShippingZone,
BulkDeleteShippingZoneVariables
>(bulkDeleteShippingZone);
@@ -90,7 +98,7 @@ const updateDefaultWeightUnit = gql`
}
}
`;
-export const TypedUpdateDefaultWeightUnit = TypedMutation<
+export const useDefaultWeightUnitUpdate = makeMutation<
UpdateDefaultWeightUnit,
UpdateDefaultWeightUnitVariables
>(updateDefaultWeightUnit);
@@ -114,7 +122,7 @@ const createShippingZone = gql`
}
}
`;
-export const TypedCreateShippingZone = TypedMutation<
+export const useShippingZoneCreate = makeMutation<
CreateShippingZone,
CreateShippingZoneVariables
>(createShippingZone);
@@ -138,7 +146,7 @@ const updateShippingZone = gql`
}
}
`;
-export const TypedUpdateShippingZone = TypedMutation<
+export const useShippingZoneUpdate = makeMutation<
UpdateShippingZone,
UpdateShippingZoneVariables
>(updateShippingZone);
@@ -157,7 +165,7 @@ const updateShippingRate = gql`
}
}
`;
-export const TypedUpdateShippingRate = TypedMutation<
+export const useShippingRateUpdate = makeMutation<
UpdateShippingRate,
UpdateShippingRateVariables
>(updateShippingRate);
@@ -176,7 +184,7 @@ const createShippingRate = gql`
}
}
`;
-export const TypedCreateShippingRate = TypedMutation<
+export const useShippingRateCreate = makeMutation<
CreateShippingRate,
CreateShippingRateVariables
>(createShippingRate);
@@ -195,7 +203,7 @@ const deleteShippingRate = gql`
}
}
`;
-export const TypedDeleteShippingRate = TypedMutation<
+export const useShippingRateDelete = makeMutation<
DeleteShippingRate,
DeleteShippingRateVariables
>(deleteShippingRate);
@@ -210,7 +218,49 @@ const bulkDeleteShippingRate = gql`
}
}
`;
-export const TypedBulkDeleteShippingRate = TypedMutation<
+export const useShippingRateBulkDelete = makeMutation<
BulkDeleteShippingRate,
BulkDeleteShippingRateVariables
>(bulkDeleteShippingRate);
+
+const assignShippingZoneToWarehouse = gql`
+ mutation AssignShippingZoneToWarehouse(
+ $warehouseId: ID!
+ $shippingZoneId: ID!
+ ) {
+ assignWarehouseShippingZone(
+ id: $warehouseId
+ shippingZoneIds: [$shippingZoneId]
+ ) {
+ warehouseErrors {
+ code
+ field
+ }
+ }
+ }
+`;
+export const useAassignShippingZoneToWarehouse = makeMutation<
+ AssignShippingZoneToWarehouse,
+ AssignShippingZoneToWarehouseVariables
+>(assignShippingZoneToWarehouse);
+
+const unassignShippingZoneToWarehouse = gql`
+ mutation UnassignShippingZoneToWarehouse(
+ $warehouseId: ID!
+ $shippingZoneId: ID!
+ ) {
+ unassignWarehouseShippingZone(
+ id: $warehouseId
+ shippingZoneIds: [$shippingZoneId]
+ ) {
+ warehouseErrors {
+ code
+ field
+ }
+ }
+ }
+`;
+export const useUnassignShippingZoneToWarehouse = makeMutation<
+ UnassignShippingZoneToWarehouse,
+ UnassignShippingZoneToWarehouseVariables
+>(unassignShippingZoneToWarehouse);
diff --git a/src/shipping/queries.ts b/src/shipping/queries.ts
index 8215a50bb..9779655e2 100644
--- a/src/shipping/queries.ts
+++ b/src/shipping/queries.ts
@@ -1,5 +1,6 @@
import gql from "graphql-tag";
+import makeQuery from "@saleor/hooks/makeQuery";
import { pageInfoFragment, TypedQuery } from "../queries";
import { ShippingZone, ShippingZoneVariables } from "./types/ShippingZone";
import { ShippingZones, ShippingZonesVariables } from "./types/ShippingZones";
@@ -91,7 +92,6 @@ const shippingZone = gql`
}
}
`;
-export const TypedShippingZone = TypedQuery<
- ShippingZone,
- ShippingZoneVariables
->(shippingZone);
+export const useShippingZone = makeQuery(
+ shippingZone
+);
diff --git a/src/shipping/types/AssignShippingZoneToWarehouse.ts b/src/shipping/types/AssignShippingZoneToWarehouse.ts
new file mode 100644
index 000000000..378d365c7
--- /dev/null
+++ b/src/shipping/types/AssignShippingZoneToWarehouse.ts
@@ -0,0 +1,29 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+import { WarehouseErrorCode } from "./../../types/globalTypes";
+
+// ====================================================
+// GraphQL mutation operation: AssignShippingZoneToWarehouse
+// ====================================================
+
+export interface AssignShippingZoneToWarehouse_assignWarehouseShippingZone_warehouseErrors {
+ __typename: "WarehouseError";
+ code: WarehouseErrorCode | null;
+ field: string | null;
+}
+
+export interface AssignShippingZoneToWarehouse_assignWarehouseShippingZone {
+ __typename: "WarehouseShippingZoneAssign";
+ warehouseErrors: AssignShippingZoneToWarehouse_assignWarehouseShippingZone_warehouseErrors[] | null;
+}
+
+export interface AssignShippingZoneToWarehouse {
+ assignWarehouseShippingZone: AssignShippingZoneToWarehouse_assignWarehouseShippingZone | null;
+}
+
+export interface AssignShippingZoneToWarehouseVariables {
+ warehouseId: string;
+ shippingZoneId: string;
+}
diff --git a/src/shipping/types/UnassignShippingZoneToWarehouse.ts b/src/shipping/types/UnassignShippingZoneToWarehouse.ts
new file mode 100644
index 000000000..a8f8e1721
--- /dev/null
+++ b/src/shipping/types/UnassignShippingZoneToWarehouse.ts
@@ -0,0 +1,29 @@
+/* tslint:disable */
+/* eslint-disable */
+// This file was automatically generated and should not be edited.
+
+import { WarehouseErrorCode } from "./../../types/globalTypes";
+
+// ====================================================
+// GraphQL mutation operation: UnassignShippingZoneToWarehouse
+// ====================================================
+
+export interface UnassignShippingZoneToWarehouse_unassignWarehouseShippingZone_warehouseErrors {
+ __typename: "WarehouseError";
+ code: WarehouseErrorCode | null;
+ field: string | null;
+}
+
+export interface UnassignShippingZoneToWarehouse_unassignWarehouseShippingZone {
+ __typename: "WarehouseShippingZoneUnassign";
+ warehouseErrors: UnassignShippingZoneToWarehouse_unassignWarehouseShippingZone_warehouseErrors[] | null;
+}
+
+export interface UnassignShippingZoneToWarehouse {
+ unassignWarehouseShippingZone: UnassignShippingZoneToWarehouse_unassignWarehouseShippingZone | null;
+}
+
+export interface UnassignShippingZoneToWarehouseVariables {
+ warehouseId: string;
+ shippingZoneId: string;
+}
diff --git a/src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx b/src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx
deleted file mode 100644
index 36f346b39..000000000
--- a/src/shipping/views/ShippingZoneDetails/ShippingZoneDetailsDialogs.tsx
+++ /dev/null
@@ -1,244 +0,0 @@
-import DialogContentText from "@material-ui/core/DialogContentText";
-import React from "react";
-import { FormattedMessage, useIntl } from "react-intl";
-
-import ActionDialog from "@saleor/components/ActionDialog";
-import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
-import useNavigator from "@saleor/hooks/useNavigator";
-import useShop from "@saleor/hooks/useShop";
-import { getStringOrPlaceholder } from "../../../misc";
-import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
-import ShippingZoneCountriesAssignDialog from "../../components/ShippingZoneCountriesAssignDialog";
-import ShippingZoneRateDialog from "../../components/ShippingZoneRateDialog";
-import { ShippingZoneDetailsFragment } from "../../types/ShippingZoneDetailsFragment";
-import { shippingZoneUrl, ShippingZoneUrlQueryParams } from "../../urls";
-import { ShippingZoneOperationsOutput } from "./ShippingZoneOperations";
-
-export interface ShippingZoneDetailsDialogsProps {
- assignCountryTransitionState: ConfirmButtonTransitionState;
- createRateTransitionState: ConfirmButtonTransitionState;
- deleteRateTransitionState: ConfirmButtonTransitionState;
- deleteZoneTransitionState: ConfirmButtonTransitionState;
- id: string;
- ops: ShippingZoneOperationsOutput;
- params: ShippingZoneUrlQueryParams;
- shippingZone: ShippingZoneDetailsFragment;
- unassignCountryTransitionState: ConfirmButtonTransitionState;
- updateRateTransitionState: ConfirmButtonTransitionState;
-}
-
-const ShippingZoneDetailsDialogs: React.FC = ({
- assignCountryTransitionState,
- createRateTransitionState,
- deleteRateTransitionState,
- deleteZoneTransitionState,
- id,
- ops,
- params,
- shippingZone,
- unassignCountryTransitionState,
- updateRateTransitionState
-}) => {
- const navigate = useNavigator();
- const shop = useShop();
- const intl = useIntl();
-
- const closeModal = () => navigate(shippingZoneUrl(id), true);
-
- const rate = shippingZone?.shippingMethods?.find(
- rate => rate.id === params.id
- );
-
- return (
- <>
-
- ops.shippingRateUpdate.mutate({
- id: params.id,
- input: {
- maximumOrderPrice: formData.noLimits
- ? null
- : parseFloat(formData.maxValue),
- minimumOrderPrice: formData.noLimits
- ? null
- : parseFloat(formData.minValue),
- name: formData.name,
- price: formData.isFree ? 0 : parseFloat(formData.price),
- shippingZone: id,
- type: rate?.type
- }
- })
- }
- open={params.action === "edit-rate"}
- rate={rate}
- variant={rate?.type}
- />
-
- ops.shippingRateDelete.mutate({
- id: params.id
- })
- }
- open={params.action === "remove-rate"}
- title={intl.formatMessage({
- defaultMessage: "Delete Shipping Method",
- description: "dialog header"
- })}
- variant="delete"
- >
-
-
-
-
-
- ops.shippingRateCreate.mutate({
- input: {
- maximumOrderPrice:
- params.type === ShippingMethodTypeEnum.PRICE
- ? formData.noLimits
- ? null
- : parseFloat(formData.maxValue)
- : null,
- maximumOrderWeight:
- params.type === ShippingMethodTypeEnum.WEIGHT
- ? formData.noLimits
- ? null
- : parseFloat(formData.maxValue)
- : null,
-
- minimumOrderPrice:
- params.type === ShippingMethodTypeEnum.PRICE
- ? formData.noLimits
- ? null
- : parseFloat(formData.minValue)
- : null,
- minimumOrderWeight:
- params.type === ShippingMethodTypeEnum.WEIGHT
- ? formData.noLimits
- ? null
- : parseFloat(formData.minValue)
- : null,
- name: formData.name,
- price: formData.isFree ? 0 : parseFloat(formData.price),
- shippingZone: id,
- type: params.type
- }
- })
- }
- open={params.action === "add-rate"}
- rate={undefined}
- variant={params.type}
- />
-
- ops.shippingZoneDelete.mutate({
- id
- })
- }
- open={params.action === "remove"}
- title={intl.formatMessage({
- defaultMessage: "Delete Shipping Zone",
- description: "dialog header"
- })}
- variant="delete"
- >
-
- {getStringOrPlaceholder(shippingZone?.name)}
- )
- }}
- />
-
-
- country.code) || []}
- isDefault={!!shippingZone?.default}
- onClose={closeModal}
- onConfirm={formData =>
- ops.shippingZoneUpdate.mutate({
- id,
- input: {
- countries: formData.countries,
- default: formData.restOfTheWorld
- }
- })
- }
- open={params.action === "assign-country"}
- />
-
- ops.shippingZoneUpdate.mutate({
- id,
- input: {
- countries: shippingZone.countries
- .filter(country => country.code !== params.id)
- .map(country => country.code)
- }
- })
- }
- open={params.action === "unassign-country"}
- title={intl.formatMessage({
- defaultMessage: "Delete from Shipping Zone",
- description: "unassign country, dialog header"
- })}
- variant="delete"
- >
-
-
- {getStringOrPlaceholder(
- shippingZone?.countries.find(
- country => country.code === params.id
- )?.country
- )}
-
- )
- }}
- />
-
-
- >
- );
-};
-export default ShippingZoneDetailsDialogs;
diff --git a/src/shipping/views/ShippingZoneDetails/data.ts b/src/shipping/views/ShippingZoneDetails/data.ts
new file mode 100644
index 000000000..0aadca15c
--- /dev/null
+++ b/src/shipping/views/ShippingZoneDetails/data.ts
@@ -0,0 +1,62 @@
+import { ShippingZoneUrlQueryParams } from "@saleor/shipping/urls";
+import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
+import { UpdateShippingRateVariables } from "@saleor/shipping/types/UpdateShippingRate";
+import { CreateShippingRateVariables } from "@saleor/shipping/types/CreateShippingRate";
+import { FormData as ShippingZoneRateDialogFormData } from "../../components/ShippingZoneRateDialog";
+
+export function getCreateShippingRateVariables(
+ data: ShippingZoneRateDialogFormData,
+ params: ShippingZoneUrlQueryParams,
+ id: string
+): CreateShippingRateVariables {
+ return {
+ input: {
+ maximumOrderPrice:
+ params.type === ShippingMethodTypeEnum.PRICE
+ ? data.noLimits
+ ? null
+ : parseFloat(data.maxValue)
+ : null,
+ maximumOrderWeight:
+ params.type === ShippingMethodTypeEnum.WEIGHT
+ ? data.noLimits
+ ? null
+ : parseFloat(data.maxValue)
+ : null,
+
+ minimumOrderPrice:
+ params.type === ShippingMethodTypeEnum.PRICE
+ ? data.noLimits
+ ? null
+ : parseFloat(data.minValue)
+ : null,
+ minimumOrderWeight:
+ params.type === ShippingMethodTypeEnum.WEIGHT
+ ? data.noLimits
+ ? null
+ : parseFloat(data.minValue)
+ : null,
+ name: data.name,
+ price: data.isFree ? 0 : parseFloat(data.price),
+ shippingZone: id,
+ type: params.type
+ }
+ };
+}
+
+export function getUpdateShippingRateVariables(
+ data: ShippingZoneRateDialogFormData,
+ params: ShippingZoneUrlQueryParams,
+ id: string
+): UpdateShippingRateVariables {
+ return {
+ id: params.id,
+ input: {
+ maximumOrderPrice: data.noLimits ? null : parseFloat(data.maxValue),
+ minimumOrderPrice: data.noLimits ? null : parseFloat(data.minValue),
+ name: data.name,
+ price: data.isFree ? 0 : parseFloat(data.price),
+ shippingZone: id
+ }
+ };
+}
diff --git a/src/shipping/views/ShippingZoneDetails/index.tsx b/src/shipping/views/ShippingZoneDetails/index.tsx
index ec889f9bc..b5cb55b7d 100644
--- a/src/shipping/views/ShippingZoneDetails/index.tsx
+++ b/src/shipping/views/ShippingZoneDetails/index.tsx
@@ -1,28 +1,41 @@
+import DialogContentText from "@material-ui/core/DialogContentText";
import React from "react";
-import { useIntl } from "react-intl";
+import { FormattedMessage, useIntl } from "react-intl";
+import ActionDialog from "@saleor/components/ActionDialog";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import { commonMessages } from "@saleor/intl";
import useWarehouseSearch from "@saleor/searches/useWarehouseSearch";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
-import { useWarehouseUpdate } from "@saleor/warehouses/mutations";
-import { maybe } from "../../../misc";
+import {
+ useShippingRateCreate,
+ useShippingRateUpdate,
+ useShippingRateDelete,
+ useShippingZoneDelete,
+ useShippingZoneUpdate
+} from "@saleor/shipping/mutations";
+import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
+import ShippingZoneRateDialog from "@saleor/shipping/components/ShippingZoneRateDialog";
+import useShop from "@saleor/hooks/useShop";
+import ShippingZoneCountriesAssignDialog from "@saleor/shipping/components/ShippingZoneCountriesAssignDialog";
+import NotFoundPage from "@saleor/components/NotFoundPage";
+import { getStringOrPlaceholder } from "../../../misc";
import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
-import ShippingZoneDetailsPage from "../../components/ShippingZoneDetailsPage";
-import { TypedShippingZone } from "../../queries";
-import { CreateShippingRate } from "../../types/CreateShippingRate";
-import { DeleteShippingRate } from "../../types/DeleteShippingRate";
-import { DeleteShippingZone } from "../../types/DeleteShippingZone";
-import { UpdateShippingRate } from "../../types/UpdateShippingRate";
-import { UpdateShippingZone } from "../../types/UpdateShippingZone";
+import ShippingZoneDetailsPage, {
+ FormData
+} from "../../components/ShippingZoneDetailsPage";
+import { useShippingZone } from "../../queries";
import {
shippingZonesListUrl,
shippingZoneUrl,
- ShippingZoneUrlQueryParams
+ ShippingZoneUrlQueryParams,
+ ShippingZoneUrlDialog
} from "../../urls";
-import ShippingZoneDetailsDialogs from "./ShippingZoneDetailsDialogs";
-import ShippingZoneOperations from "./ShippingZoneOperations";
+import {
+ getCreateShippingRateVariables,
+ getUpdateShippingRateVariables
+} from "./data";
export interface ShippingZoneDetailsProps {
id: string;
@@ -36,187 +49,294 @@ const ShippingZoneDetails: React.FC = ({
const navigate = useNavigator();
const notify = useNotifier();
const intl = useIntl();
- const [updateWarehouse, updateWarehouseOpts] = useWarehouseUpdate({});
+ const shop = useShop();
- const {
- search: searchWarehouses,
- result: searchWarehousesOpts
- } = useWarehouseSearch({
+ const { result: searchWarehousesOpts } = useWarehouseSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
- const closeModal = () => navigate(shippingZoneUrl(id), true);
+ const { data, loading } = useShippingZone({
+ displayLoader: true,
+ variables: { id }
+ });
- const onShippingRateCreate = (data: CreateShippingRate) => {
- if (data.shippingPriceCreate.errors.length === 0) {
- notify({
- text: intl.formatMessage(commonMessages.savedChanges)
- });
- closeModal();
+ const [openModal, closeModal] = createDialogActionHandlers<
+ ShippingZoneUrlDialog,
+ ShippingZoneUrlQueryParams
+ >(navigate, params => shippingZoneUrl(id, params), params);
+ const rate = data?.shippingZone?.shippingMethods.find(
+ rate => rate.id === params.id
+ );
+
+ const [createShippingRate, createShippingRateOpts] = useShippingRateCreate({
+ onCompleted: data => {
+ if (data.shippingPriceCreate.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ closeModal();
+ }
}
+ });
+
+ const [updateShippingRate, updateShippingRateOpts] = useShippingRateUpdate({
+ onCompleted: data => {
+ if (data.shippingPriceUpdate.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ closeModal();
+ }
+ }
+ });
+
+ const [deleteShippingRate, deleteShippingRateOpts] = useShippingRateDelete({
+ onCompleted: data => {
+ if (data.shippingPriceDelete.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ closeModal();
+ }
+ }
+ });
+
+ const [deleteShippingZone, deleteShippingZoneOpts] = useShippingZoneDelete({
+ onCompleted: data => {
+ if (data.shippingZoneDelete.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ navigate(shippingZonesListUrl(), true);
+ }
+ }
+ });
+
+ const [updateShippingZone, updateShippingZoneOpts] = useShippingZoneUpdate({
+ onCompleted: data => {
+ if (data.shippingZoneUpdate.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ closeModal();
+ }
+ }
+ });
+
+ const handleSubmit = (data: FormData) => {
+ updateShippingZone({
+ variables: {
+ id,
+ input: {
+ name: data.name
+ }
+ }
+ });
};
- const onShippingRateUpdate = (data: UpdateShippingRate) => {
- if (data.shippingPriceUpdate.errors.length === 0) {
- notify({
- text: intl.formatMessage(commonMessages.savedChanges)
- });
- closeModal();
- }
- };
-
- const onShippingRateDelete = (data: DeleteShippingRate) => {
- if (data.shippingPriceDelete.errors.length === 0) {
- notify({
- text: intl.formatMessage(commonMessages.savedChanges)
- });
- closeModal();
- }
- };
-
- const onShippingZoneDelete = (data: DeleteShippingZone) => {
- if (data.shippingZoneDelete.errors.length === 0) {
- notify({
- text: intl.formatMessage(commonMessages.savedChanges)
- });
- navigate(shippingZonesListUrl(), true);
- }
- };
-
- const onShippingZoneUpdate = (data: UpdateShippingZone) => {
- if (data.shippingZoneUpdate.errors.length === 0) {
- notify({
- text: intl.formatMessage(commonMessages.savedChanges)
- });
- closeModal();
- }
- };
+ if (data?.shippingZone === null) {
+ return navigate(shippingZonesListUrl())} />;
+ }
return (
-
- {ops => (
-
- {({ data, loading }) => (
- <>
- navigate(shippingZonesListUrl())}
- onCountryAdd={() =>
- navigate(
- shippingZoneUrl(id, {
- action: "assign-country"
- })
- )
- }
- onCountryRemove={code =>
- navigate(
- shippingZoneUrl(id, {
- action: "unassign-country",
- id: code
- })
- )
- }
- onDelete={() =>
- navigate(
- shippingZoneUrl(id, {
- action: "remove"
- })
- )
- }
- onPriceRateAdd={() =>
- navigate(
- shippingZoneUrl(id, {
- action: "add-rate",
- type: ShippingMethodTypeEnum.PRICE
- })
- )
- }
- onPriceRateEdit={rateId =>
- navigate(
- shippingZoneUrl(id, {
- action: "edit-rate",
- id: rateId
- })
- )
- }
- onRateRemove={rateId =>
- navigate(
- shippingZoneUrl(id, {
- action: "remove-rate",
- id: rateId
- })
- )
- }
- onSubmit={formData => {
- ops.shippingZoneUpdate.mutate({
- id,
- input: {
- name: formData.name
- }
- });
- updateWarehouse({
- variables: {
- id: formData.warehouse
- }
- });
- }}
- onWeightRateAdd={() =>
- navigate(
- shippingZoneUrl(id, {
- action: "add-rate",
- type: ShippingMethodTypeEnum.WEIGHT
- })
- )
- }
- onWeightRateEdit={rateId =>
- navigate(
- shippingZoneUrl(id, {
- action: "edit-rate",
- id: rateId
- })
- )
- }
- saveButtonBarState={ops.shippingZoneUpdate.opts.status}
- shippingZone={maybe(() => data.shippingZone)}
- warehouses={maybe(
- () =>
- searchWarehousesOpts.data.search.edges.map(
- edge => edge.node
- ),
- []
- )}
- />
-
- >
- )}
-
- )}
-
+ <>
+ navigate(shippingZonesListUrl())}
+ onCountryAdd={() => openModal("assign-country")}
+ onCountryRemove={code =>
+ openModal("unassign-country", {
+ id: code
+ })
+ }
+ onDelete={() => openModal("remove")}
+ onPriceRateAdd={() =>
+ openModal("add-rate", {
+ type: ShippingMethodTypeEnum.PRICE
+ })
+ }
+ onPriceRateEdit={rateId =>
+ openModal("edit-rate", {
+ id: rateId
+ })
+ }
+ onRateRemove={rateId =>
+ openModal("remove-rate", {
+ id: rateId
+ })
+ }
+ onSubmit={handleSubmit}
+ onWeightRateAdd={() =>
+ openModal("add-rate", {
+ type: ShippingMethodTypeEnum.WEIGHT
+ })
+ }
+ onWeightRateEdit={rateId =>
+ openModal("edit-rate", {
+ id: rateId
+ })
+ }
+ saveButtonBarState={updateShippingZoneOpts.status}
+ shippingZone={data?.shippingZone}
+ warehouses={
+ searchWarehousesOpts.data?.search.edges.map(edge => edge.node) || []
+ }
+ />
+
+ updateShippingRate({
+ variables: getUpdateShippingRateVariables(data, params, id)
+ })
+ }
+ open={params.action === "edit-rate"}
+ rate={rate}
+ variant={rate?.type}
+ />
+
+ deleteShippingRate({
+ variables: {
+ id: params.id
+ }
+ })
+ }
+ open={params.action === "remove-rate"}
+ title={intl.formatMessage({
+ defaultMessage: "Delete Shipping Method",
+ description: "dialog header"
+ })}
+ variant="delete"
+ >
+
+
+
+
+
+ createShippingRate({
+ variables: getCreateShippingRateVariables(data, params, id)
+ })
+ }
+ open={params.action === "add-rate"}
+ rate={undefined}
+ variant={params.type}
+ />
+
+ deleteShippingZone({
+ variables: {
+ id
+ }
+ })
+ }
+ open={params.action === "remove"}
+ title={intl.formatMessage({
+ defaultMessage: "Delete Shipping Zone",
+ description: "dialog header"
+ })}
+ variant="delete"
+ >
+
+
+ {getStringOrPlaceholder(data?.shippingZone.name)}
+
+ )
+ }}
+ />
+
+
+ country.code) || []
+ }
+ isDefault={data?.shippingZone?.default}
+ onClose={closeModal}
+ onConfirm={formData =>
+ updateShippingZone({
+ variables: {
+ id,
+ input: {
+ countries: formData.countries,
+ default: formData.restOfTheWorld
+ }
+ }
+ })
+ }
+ open={params.action === "assign-country"}
+ />
+
+ updateShippingZone({
+ variables: {
+ id,
+ input: {
+ countries: data.shippingZone.countries
+ .filter(country => country.code !== params.id)
+ .map(country => country.code)
+ }
+ }
+ })
+ }
+ open={params.action === "unassign-country"}
+ title={intl.formatMessage({
+ defaultMessage: "Delete from Shipping Zone",
+ description: "unassign country, dialog header"
+ })}
+ variant="delete"
+ >
+
+
+ {getStringOrPlaceholder(
+ data?.shippingZone?.countries.find(
+ country => country.code === params.id
+ )?.country
+ )}
+
+ )
+ }}
+ />
+
+
+ >
);
};
export default ShippingZoneDetails;
diff --git a/src/types/globalTypes.ts b/src/types/globalTypes.ts
index e6066af22..4f0b0a325 100644
--- a/src/types/globalTypes.ts
+++ b/src/types/globalTypes.ts
@@ -746,6 +746,15 @@ export enum VoucherTypeEnum {
SPECIFIC_PRODUCT = "SPECIFIC_PRODUCT",
}
+export enum WarehouseErrorCode {
+ ALREADY_EXISTS = "ALREADY_EXISTS",
+ GRAPHQL_ERROR = "GRAPHQL_ERROR",
+ INVALID = "INVALID",
+ NOT_FOUND = "NOT_FOUND",
+ REQUIRED = "REQUIRED",
+ UNIQUE = "UNIQUE",
+}
+
export enum WarehouseSortField {
NAME = "NAME",
}
@@ -1431,11 +1440,12 @@ export interface WarehouseAddressInput {
}
export interface WarehouseCreateInput {
- name: string;
+ slug?: string | null;
companyName?: string | null;
- shippingZones?: (string | null)[] | null;
email?: string | null;
+ name: string;
address: WarehouseAddressInput;
+ shippingZones?: (string | null)[] | null;
}
export interface WarehouseFilterInput {
@@ -1448,10 +1458,10 @@ export interface WarehouseSortingInput {
}
export interface WarehouseUpdateInput {
- name: string;
+ slug?: string | null;
companyName?: string | null;
- shippingZones?: (string | null)[] | null;
email?: string | null;
+ name?: string | null;
address?: WarehouseAddressInput | null;
}
From 8f021178654d766c5da07f8174ea655755a50947 Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Thu, 6 Feb 2020 16:19:08 +0100
Subject: [PATCH 12/88] Add warehouse select
---
.../ShippingZoneDetailsPage.tsx | 3 ++-
.../ShippingZoneWarehouses/ShippingZoneWarehouses.tsx | 9 ++++++++-
src/shipping/views/ShippingZoneDetails/index.tsx | 11 ++++++++++-
3 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx
index afaa9a798..0fab0ae87 100644
--- a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx
+++ b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx
@@ -13,6 +13,7 @@ import SaveButtonBar from "@saleor/components/SaveButtonBar";
import { ShippingErrorFragment } from "@saleor/shipping/types/ShippingErrorFragment";
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
+import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { maybe } from "../../../misc";
import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
import {
@@ -78,7 +79,7 @@ const ShippingZoneDetailsPage: React.FC = ({
name: shippingZone?.name || "",
warehouses: shippingZone?.warehouses.map(warehouse => warehouse.id) || []
};
- const [warehouseDisplayValues, setWarehouseDisplayValues] = React.useState(
+ const [warehouseDisplayValues, setWarehouseDisplayValues] = useStateFromProps(
shippingZone?.warehouses.map(warehouseToChoice)
);
diff --git a/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx b/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx
index 6e1eeffcb..0b0390667 100644
--- a/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx
+++ b/src/shipping/components/ShippingZoneWarehouses/ShippingZoneWarehouses.tsx
@@ -36,7 +36,7 @@ export const ShippingZoneWarehouses: React.FC = pr
@@ -46,10 +46,17 @@ export const ShippingZoneWarehouses: React.FC = pr
displayValues={displayValue}
fetchChoices={() => undefined}
hasMore={hasMore}
+ label={intl.formatMessage({
+ defaultMessage: "Warehouse"
+ })}
loading={loading}
name="warehouse"
onChange={onChange}
onFetchMore={onFetchMore}
+ placeholder={intl.formatMessage({
+ defaultMessage: "Select Warehouse",
+ description: "input placeholder"
+ })}
value={data.warehouses}
/>
diff --git a/src/shipping/views/ShippingZoneDetails/index.tsx b/src/shipping/views/ShippingZoneDetails/index.tsx
index b5cb55b7d..451760a84 100644
--- a/src/shipping/views/ShippingZoneDetails/index.tsx
+++ b/src/shipping/views/ShippingZoneDetails/index.tsx
@@ -13,7 +13,8 @@ import {
useShippingRateUpdate,
useShippingRateDelete,
useShippingZoneDelete,
- useShippingZoneUpdate
+ useShippingZoneUpdate,
+ useAassignShippingZoneToWarehouse
} from "@saleor/shipping/mutations";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import ShippingZoneRateDialog from "@saleor/shipping/components/ShippingZoneRateDialog";
@@ -55,6 +56,8 @@ const ShippingZoneDetails: React.FC = ({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
+ const [assignToWarehouse] = useAassignShippingZoneToWarehouse({});
+
const { data, loading } = useShippingZone({
displayLoader: true,
variables: { id }
@@ -132,6 +135,12 @@ const ShippingZoneDetails: React.FC = ({
}
}
});
+ assignToWarehouse({
+ variables: {
+ shippingZoneId: id,
+ warehouseId: data.warehouse
+ }
+ });
};
if (data?.shippingZone === null) {
From 92d16effb309fc58688a52372b2951e5615791d5 Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Thu, 6 Feb 2020 17:51:01 +0100
Subject: [PATCH 13/88] Add inventory status to variant list
---
.../ProductVariants/ProductVariants.tsx | 76 ++++++++++---------
src/products/queries.ts | 8 ++
src/products/types/Product.ts | 7 ++
src/products/types/ProductCreate.ts | 7 ++
src/products/types/ProductDetails.ts | 7 ++
src/products/types/ProductImageCreate.ts | 7 ++
src/products/types/ProductImageUpdate.ts | 7 ++
src/products/types/ProductUpdate.ts | 7 ++
src/products/types/ProductVariant.ts | 7 ++
src/products/types/ProductVariantDetails.ts | 7 ++
src/products/types/SimpleProductUpdate.ts | 14 ++++
src/products/types/VariantCreate.ts | 7 ++
src/products/types/VariantImageAssign.ts | 7 ++
src/products/types/VariantImageUnassign.ts | 7 ++
src/products/types/VariantUpdate.ts | 7 ++
15 files changed, 145 insertions(+), 37 deletions(-)
diff --git a/src/products/components/ProductVariants/ProductVariants.tsx b/src/products/components/ProductVariants/ProductVariants.tsx
index 6e46489a9..1146b9045 100644
--- a/src/products/components/ProductVariants/ProductVariants.tsx
+++ b/src/products/components/ProductVariants/ProductVariants.tsx
@@ -15,7 +15,6 @@ import Checkbox from "@saleor/components/Checkbox";
import Money from "@saleor/components/Money";
import ResponsiveTable from "@saleor/components/ResponsiveTable";
import Skeleton from "@saleor/components/Skeleton";
-import StatusLabel from "@saleor/components/StatusLabel";
import TableHead from "@saleor/components/TableHead";
import { maybe, renderCollection } from "../../../misc";
import { ListActions } from "../../../types";
@@ -25,17 +24,20 @@ import { ProductVariant_costPrice } from "../../types/ProductVariant";
const useStyles = makeStyles(
theme => ({
[theme.breakpoints.up("lg")]: {
+ colInventory: {
+ width: 300
+ },
colName: {},
colPrice: {
- width: 200
+ width: 150
},
colSku: {
- width: 250
- },
- colStatus: {
width: 200
}
},
+ colInventory: {
+ textAlign: "right"
+ },
colName: {},
colPrice: {
textAlign: "right"
@@ -148,12 +150,6 @@ export const ProductVariants: React.FC = props => {
description="product variant name"
/>
-
-
-
@@ -165,10 +161,20 @@ export const ProductVariants: React.FC = props => {
/>
+
+
+
{renderCollection(variants, variant => {
const isSelected = variant ? isChecked(variant.id) : false;
+ const numAvailable =
+ variant && variant.stock
+ ? variant.stock.reduce((acc, s) => acc + s.quantity, 0)
+ : null;
return (
= props => {
{variant ? variant.name || variant.sku : }
- variant.stockQuantity > 0
- )}
- >
- {variant ? (
- 0 ? "success" : "error"}
- label={
- variant.stockQuantity > 0
- ? intl.formatMessage({
- defaultMessage: "Available",
- description: "product variant status"
- })
- : intl.formatMessage({
- defaultMessage: "Unavailable",
- description: "product variant status"
- })
- }
- />
- ) : (
-
- )}
-
{variant ? variant.sku : }
@@ -233,6 +213,28 @@ export const ProductVariants: React.FC = props => {
)}
+
+ {numAvailable === null ? (
+
+ ) : numAvailable === 0 ? (
+
+ ) : (
+
+ )}
+
);
})}
diff --git a/src/products/queries.ts b/src/products/queries.ts
index dbed486ce..5e5f58977 100644
--- a/src/products/queries.ts
+++ b/src/products/queries.ts
@@ -146,6 +146,10 @@ export const productFragmentDetails = gql`
quantity
quantityAllocated
stockQuantity
+ stock {
+ id
+ quantity
+ }
}
productType {
id
@@ -212,6 +216,10 @@ export const fragmentVariant = gql`
sku
quantity
quantityAllocated
+ stock {
+ id
+ quantity
+ }
}
`;
diff --git a/src/products/types/Product.ts b/src/products/types/Product.ts
index 1b7426fc4..e0cafa652 100644
--- a/src/products/types/Product.ts
+++ b/src/products/types/Product.ts
@@ -127,6 +127,12 @@ export interface Product_variants_priceOverride {
currency: string;
}
+export interface Product_variants_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface Product_variants {
__typename: "ProductVariant";
id: string;
@@ -137,6 +143,7 @@ export interface Product_variants {
quantity: number;
quantityAllocated: number | null;
stockQuantity: number;
+ stock: (Product_variants_stock | null)[] | null;
}
export interface Product_productType {
diff --git a/src/products/types/ProductCreate.ts b/src/products/types/ProductCreate.ts
index c265fd69f..b1409b4d8 100644
--- a/src/products/types/ProductCreate.ts
+++ b/src/products/types/ProductCreate.ts
@@ -133,6 +133,12 @@ export interface ProductCreate_productCreate_product_variants_priceOverride {
currency: string;
}
+export interface ProductCreate_productCreate_product_variants_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface ProductCreate_productCreate_product_variants {
__typename: "ProductVariant";
id: string;
@@ -143,6 +149,7 @@ export interface ProductCreate_productCreate_product_variants {
quantity: number;
quantityAllocated: number | null;
stockQuantity: number;
+ stock: (ProductCreate_productCreate_product_variants_stock | null)[] | null;
}
export interface ProductCreate_productCreate_product_productType {
diff --git a/src/products/types/ProductDetails.ts b/src/products/types/ProductDetails.ts
index 2ebf1cfcc..78013430e 100644
--- a/src/products/types/ProductDetails.ts
+++ b/src/products/types/ProductDetails.ts
@@ -127,6 +127,12 @@ export interface ProductDetails_product_variants_priceOverride {
currency: string;
}
+export interface ProductDetails_product_variants_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface ProductDetails_product_variants {
__typename: "ProductVariant";
id: string;
@@ -137,6 +143,7 @@ export interface ProductDetails_product_variants {
quantity: number;
quantityAllocated: number | null;
stockQuantity: number;
+ stock: (ProductDetails_product_variants_stock | null)[] | null;
}
export interface ProductDetails_product_productType_variantAttributes_values {
diff --git a/src/products/types/ProductImageCreate.ts b/src/products/types/ProductImageCreate.ts
index c481ea341..45f62c860 100644
--- a/src/products/types/ProductImageCreate.ts
+++ b/src/products/types/ProductImageCreate.ts
@@ -133,6 +133,12 @@ export interface ProductImageCreate_productImageCreate_product_variants_priceOve
currency: string;
}
+export interface ProductImageCreate_productImageCreate_product_variants_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface ProductImageCreate_productImageCreate_product_variants {
__typename: "ProductVariant";
id: string;
@@ -143,6 +149,7 @@ export interface ProductImageCreate_productImageCreate_product_variants {
quantity: number;
quantityAllocated: number | null;
stockQuantity: number;
+ stock: (ProductImageCreate_productImageCreate_product_variants_stock | null)[] | null;
}
export interface ProductImageCreate_productImageCreate_product_productType {
diff --git a/src/products/types/ProductImageUpdate.ts b/src/products/types/ProductImageUpdate.ts
index 23687fe07..0be498717 100644
--- a/src/products/types/ProductImageUpdate.ts
+++ b/src/products/types/ProductImageUpdate.ts
@@ -133,6 +133,12 @@ export interface ProductImageUpdate_productImageUpdate_product_variants_priceOve
currency: string;
}
+export interface ProductImageUpdate_productImageUpdate_product_variants_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface ProductImageUpdate_productImageUpdate_product_variants {
__typename: "ProductVariant";
id: string;
@@ -143,6 +149,7 @@ export interface ProductImageUpdate_productImageUpdate_product_variants {
quantity: number;
quantityAllocated: number | null;
stockQuantity: number;
+ stock: (ProductImageUpdate_productImageUpdate_product_variants_stock | null)[] | null;
}
export interface ProductImageUpdate_productImageUpdate_product_productType {
diff --git a/src/products/types/ProductUpdate.ts b/src/products/types/ProductUpdate.ts
index 20c745df8..7fce89379 100644
--- a/src/products/types/ProductUpdate.ts
+++ b/src/products/types/ProductUpdate.ts
@@ -133,6 +133,12 @@ export interface ProductUpdate_productUpdate_product_variants_priceOverride {
currency: string;
}
+export interface ProductUpdate_productUpdate_product_variants_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface ProductUpdate_productUpdate_product_variants {
__typename: "ProductVariant";
id: string;
@@ -143,6 +149,7 @@ export interface ProductUpdate_productUpdate_product_variants {
quantity: number;
quantityAllocated: number | null;
stockQuantity: number;
+ stock: (ProductUpdate_productUpdate_product_variants_stock | null)[] | null;
}
export interface ProductUpdate_productUpdate_product_productType {
diff --git a/src/products/types/ProductVariant.ts b/src/products/types/ProductVariant.ts
index 2d8091000..14f5aa54f 100644
--- a/src/products/types/ProductVariant.ts
+++ b/src/products/types/ProductVariant.ts
@@ -89,6 +89,12 @@ export interface ProductVariant_product {
variants: (ProductVariant_product_variants | null)[] | null;
}
+export interface ProductVariant_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface ProductVariant {
__typename: "ProductVariant";
id: string;
@@ -101,4 +107,5 @@ export interface ProductVariant {
sku: string;
quantity: number;
quantityAllocated: number | null;
+ stock: (ProductVariant_stock | null)[] | null;
}
diff --git a/src/products/types/ProductVariantDetails.ts b/src/products/types/ProductVariantDetails.ts
index 0f948a9cc..e4c98a234 100644
--- a/src/products/types/ProductVariantDetails.ts
+++ b/src/products/types/ProductVariantDetails.ts
@@ -89,6 +89,12 @@ export interface ProductVariantDetails_productVariant_product {
variants: (ProductVariantDetails_productVariant_product_variants | null)[] | null;
}
+export interface ProductVariantDetails_productVariant_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface ProductVariantDetails_productVariant {
__typename: "ProductVariant";
id: string;
@@ -101,6 +107,7 @@ export interface ProductVariantDetails_productVariant {
sku: string;
quantity: number;
quantityAllocated: number | null;
+ stock: (ProductVariantDetails_productVariant_stock | null)[] | null;
}
export interface ProductVariantDetails {
diff --git a/src/products/types/SimpleProductUpdate.ts b/src/products/types/SimpleProductUpdate.ts
index 51c33a7e3..c49bd09a6 100644
--- a/src/products/types/SimpleProductUpdate.ts
+++ b/src/products/types/SimpleProductUpdate.ts
@@ -133,6 +133,12 @@ export interface SimpleProductUpdate_productUpdate_product_variants_priceOverrid
currency: string;
}
+export interface SimpleProductUpdate_productUpdate_product_variants_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface SimpleProductUpdate_productUpdate_product_variants {
__typename: "ProductVariant";
id: string;
@@ -143,6 +149,7 @@ export interface SimpleProductUpdate_productUpdate_product_variants {
quantity: number;
quantityAllocated: number | null;
stockQuantity: number;
+ stock: (SimpleProductUpdate_productUpdate_product_variants_stock | null)[] | null;
}
export interface SimpleProductUpdate_productUpdate_product_productType {
@@ -271,6 +278,12 @@ export interface SimpleProductUpdate_productVariantUpdate_productVariant_product
variants: (SimpleProductUpdate_productVariantUpdate_productVariant_product_variants | null)[] | null;
}
+export interface SimpleProductUpdate_productVariantUpdate_productVariant_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface SimpleProductUpdate_productVariantUpdate_productVariant {
__typename: "ProductVariant";
id: string;
@@ -283,6 +296,7 @@ export interface SimpleProductUpdate_productVariantUpdate_productVariant {
sku: string;
quantity: number;
quantityAllocated: number | null;
+ stock: (SimpleProductUpdate_productVariantUpdate_productVariant_stock | null)[] | null;
}
export interface SimpleProductUpdate_productVariantUpdate {
diff --git a/src/products/types/VariantCreate.ts b/src/products/types/VariantCreate.ts
index da6dd3939..ae04aee61 100644
--- a/src/products/types/VariantCreate.ts
+++ b/src/products/types/VariantCreate.ts
@@ -97,6 +97,12 @@ export interface VariantCreate_productVariantCreate_productVariant_product {
variants: (VariantCreate_productVariantCreate_productVariant_product_variants | null)[] | null;
}
+export interface VariantCreate_productVariantCreate_productVariant_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface VariantCreate_productVariantCreate_productVariant {
__typename: "ProductVariant";
id: string;
@@ -109,6 +115,7 @@ export interface VariantCreate_productVariantCreate_productVariant {
sku: string;
quantity: number;
quantityAllocated: number | null;
+ stock: (VariantCreate_productVariantCreate_productVariant_stock | null)[] | null;
}
export interface VariantCreate_productVariantCreate {
diff --git a/src/products/types/VariantImageAssign.ts b/src/products/types/VariantImageAssign.ts
index 5a5c8ad0a..da34c19e2 100644
--- a/src/products/types/VariantImageAssign.ts
+++ b/src/products/types/VariantImageAssign.ts
@@ -97,6 +97,12 @@ export interface VariantImageAssign_variantImageAssign_productVariant_product {
variants: (VariantImageAssign_variantImageAssign_productVariant_product_variants | null)[] | null;
}
+export interface VariantImageAssign_variantImageAssign_productVariant_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface VariantImageAssign_variantImageAssign_productVariant {
__typename: "ProductVariant";
id: string;
@@ -109,6 +115,7 @@ export interface VariantImageAssign_variantImageAssign_productVariant {
sku: string;
quantity: number;
quantityAllocated: number | null;
+ stock: (VariantImageAssign_variantImageAssign_productVariant_stock | null)[] | null;
}
export interface VariantImageAssign_variantImageAssign {
diff --git a/src/products/types/VariantImageUnassign.ts b/src/products/types/VariantImageUnassign.ts
index 4978ee18b..46a910dd3 100644
--- a/src/products/types/VariantImageUnassign.ts
+++ b/src/products/types/VariantImageUnassign.ts
@@ -97,6 +97,12 @@ export interface VariantImageUnassign_variantImageUnassign_productVariant_produc
variants: (VariantImageUnassign_variantImageUnassign_productVariant_product_variants | null)[] | null;
}
+export interface VariantImageUnassign_variantImageUnassign_productVariant_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface VariantImageUnassign_variantImageUnassign_productVariant {
__typename: "ProductVariant";
id: string;
@@ -109,6 +115,7 @@ export interface VariantImageUnassign_variantImageUnassign_productVariant {
sku: string;
quantity: number;
quantityAllocated: number | null;
+ stock: (VariantImageUnassign_variantImageUnassign_productVariant_stock | null)[] | null;
}
export interface VariantImageUnassign_variantImageUnassign {
diff --git a/src/products/types/VariantUpdate.ts b/src/products/types/VariantUpdate.ts
index 0028a0887..e2e98e600 100644
--- a/src/products/types/VariantUpdate.ts
+++ b/src/products/types/VariantUpdate.ts
@@ -97,6 +97,12 @@ export interface VariantUpdate_productVariantUpdate_productVariant_product {
variants: (VariantUpdate_productVariantUpdate_productVariant_product_variants | null)[] | null;
}
+export interface VariantUpdate_productVariantUpdate_productVariant_stock {
+ __typename: "Stock";
+ id: string;
+ quantity: number;
+}
+
export interface VariantUpdate_productVariantUpdate_productVariant {
__typename: "ProductVariant";
id: string;
@@ -109,6 +115,7 @@ export interface VariantUpdate_productVariantUpdate_productVariant {
sku: string;
quantity: number;
quantityAllocated: number | null;
+ stock: (VariantUpdate_productVariantUpdate_productVariant_stock | null)[] | null;
}
export interface VariantUpdate_productVariantUpdate {
From ccc51b1243fc5eada169ec2e0c1a27ef52ac9df2 Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Fri, 7 Feb 2020 17:12:01 +0100
Subject: [PATCH 14/88] Add link with choices component
---
.../LinkChoice/LinkChoice.stories.tsx | 26 +++
src/components/LinkChoice/LinkChoice.tsx | 157 ++++++++++++++++++
src/components/LinkChoice/index.ts | 2 +
3 files changed, 185 insertions(+)
create mode 100644 src/components/LinkChoice/LinkChoice.stories.tsx
create mode 100644 src/components/LinkChoice/LinkChoice.tsx
create mode 100644 src/components/LinkChoice/index.ts
diff --git a/src/components/LinkChoice/LinkChoice.stories.tsx b/src/components/LinkChoice/LinkChoice.stories.tsx
new file mode 100644
index 000000000..0b7f17610
--- /dev/null
+++ b/src/components/LinkChoice/LinkChoice.stories.tsx
@@ -0,0 +1,26 @@
+import { storiesOf } from "@storybook/react";
+import React from "react";
+
+import { countries } from "@saleor/fixtures";
+import CardDecorator from "@saleor/storybook/CardDecorator";
+import Decorator from "@saleor/storybook/Decorator";
+import Form from "../Form";
+import LinkChoice, { LinkChoiceProps } from "./LinkChoice";
+
+const suggestions = countries.map(c => ({ label: c.name, value: c.code }));
+
+const props: Omit = {
+ choices: suggestions.slice(0, 10),
+ name: "country"
+};
+
+storiesOf("Generics / Link with choices", module)
+ .addDecorator(CardDecorator)
+ .addDecorator(Decorator)
+ .add("default", () => (
+
+ ));
diff --git a/src/components/LinkChoice/LinkChoice.tsx b/src/components/LinkChoice/LinkChoice.tsx
new file mode 100644
index 000000000..9cfe19663
--- /dev/null
+++ b/src/components/LinkChoice/LinkChoice.tsx
@@ -0,0 +1,157 @@
+import React from "react";
+import ClickAwayListener from "@material-ui/core/ClickAwayListener";
+import Paper from "@material-ui/core/Paper";
+import MenuItem from "@material-ui/core/MenuItem";
+import makeStyles from "@material-ui/core/styles/makeStyles";
+import Popper from "@material-ui/core/Popper";
+import { fade } from "@material-ui/core/styles/colorManipulator";
+import classNames from "classnames";
+import { codes } from "keycode";
+
+import ArrowDropdown from "@saleor/icons/ArrowDropdown";
+import { FormChange } from "@saleor/hooks/useForm";
+import { SingleAutocompleteChoiceType } from "../SingleAutocompleteSelectField";
+import Link from "../Link";
+
+const useStyles = makeStyles(
+ theme => ({
+ arrow: {
+ position: "relative",
+ top: 6,
+ transition: theme.transitions.duration.short + "ms"
+ },
+ highlighted: {
+ background: theme.palette.background.default
+ },
+ menuItem: {
+ "&:not(:last-of-type)": {
+ marginBottom: theme.spacing()
+ }
+ },
+ paper: {
+ padding: theme.spacing()
+ },
+ popper: {
+ boxShadow: `0px 5px 10px 0 ${fade(theme.palette.common.black, 0.05)}`,
+ marginTop: theme.spacing(1),
+ zIndex: 2
+ },
+ root: {
+ "&:focus": {
+ textDecoration: "underline"
+ },
+ outline: 0,
+ position: "relative"
+ },
+ rotate: {
+ transform: "rotate(180deg)"
+ }
+ }),
+ {
+ name: "LinkChoice"
+ }
+);
+
+export interface LinkChoiceProps {
+ choices: SingleAutocompleteChoiceType[];
+ name: "country";
+ value: string;
+ onChange: FormChange;
+}
+
+const LinkChoice: React.FC = ({
+ choices,
+ name,
+ value,
+ onChange
+}) => {
+ const classes = useStyles({});
+ const [open, setOpen] = React.useState(false);
+ const anchor = React.useRef(null);
+ const current = choices.find(c => c.value === value);
+ const [highlightedIndex, setHighlightedIndex] = React.useState(0);
+
+ const handleChange = (value: string) => {
+ setOpen(false);
+ onChange({
+ target: {
+ name,
+ value
+ }
+ });
+ };
+
+ const handleKeyPress = (event: React.KeyboardEvent) => {
+ switch (event.keyCode) {
+ case codes.down:
+ setHighlightedIndex(
+ highlightedIndex => (highlightedIndex + 1) % choices.length
+ );
+ break;
+ case codes.up:
+ setHighlightedIndex(highlightedIndex =>
+ highlightedIndex === 0
+ ? choices.length - 1
+ : (highlightedIndex - 1) % choices.length
+ );
+ break;
+ case codes.enter:
+ if (open) {
+ handleChange(choices[highlightedIndex].value);
+ } else {
+ setOpen(true);
+ }
+ break;
+ }
+ };
+
+ return (
+
+ setOpen(open => !open)}>{current.label}
+
+
+
+ setOpen(false)}
+ mouseEvent="onClick"
+ >
+
+ {choices.map((choice, choiceIndex) => (
+
+ ))}
+
+
+
+
+ );
+};
+
+LinkChoice.displayName = "LinkChoice";
+export default LinkChoice;
diff --git a/src/components/LinkChoice/index.ts b/src/components/LinkChoice/index.ts
new file mode 100644
index 000000000..9c927a90f
--- /dev/null
+++ b/src/components/LinkChoice/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./LinkChoice";
+export * from "./LinkChoice";
From ee36d6046c7c88b32980f31593f20b87a51dd72e Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Fri, 7 Feb 2020 17:44:42 +0100
Subject: [PATCH 15/88] Add variant stock filtering by warehouse
---
src/components/LinkChoice/LinkChoice.tsx | 6 +-
.../ProductVariants/ProductVariants.tsx | 117 +++++++++++++++---
src/products/queries.ts | 4 +
src/products/types/Product.ts | 7 ++
src/products/types/ProductCreate.ts | 7 ++
src/products/types/ProductDetails.ts | 7 ++
src/products/types/ProductImageCreate.ts | 7 ++
src/products/types/ProductImageUpdate.ts | 7 ++
src/products/types/ProductUpdate.ts | 7 ++
src/products/types/SimpleProductUpdate.ts | 7 ++
10 files changed, 160 insertions(+), 16 deletions(-)
diff --git a/src/components/LinkChoice/LinkChoice.tsx b/src/components/LinkChoice/LinkChoice.tsx
index 9cfe19663..8916ea2fa 100644
--- a/src/components/LinkChoice/LinkChoice.tsx
+++ b/src/components/LinkChoice/LinkChoice.tsx
@@ -53,13 +53,15 @@ const useStyles = makeStyles(
);
export interface LinkChoiceProps {
+ className?: string;
choices: SingleAutocompleteChoiceType[];
- name: "country";
+ name?: string;
value: string;
onChange: FormChange;
}
const LinkChoice: React.FC = ({
+ className,
choices,
name,
value,
@@ -107,7 +109,7 @@ const LinkChoice: React.FC = ({
return (
(
+ (warehouses, variant) => [
+ ...warehouses,
+ ...variant.stock.reduce<
+ ProductDetails_product_variants_stock_warehouse[]
+ >((variantStocks, stock) => {
+ if (!!warehouses.find(w => w.id === stock.warehouse.id)) {
+ return variantStocks;
+ }
+
+ return [...variantStocks, stock.warehouse];
+ }, [])
+ ],
+ []
+ )
+ .map(w => ({
+ label: w.name,
+ value: w.id
+ }))
+ ];
+}
+
const useStyles = makeStyles(
theme => ({
[theme.breakpoints.up("lg")]: {
@@ -57,6 +97,13 @@ const useStyles = makeStyles(
},
textRight: {
textAlign: "right" as "right"
+ },
+ warehouseLabel: {
+ display: "inline-block",
+ marginRight: theme.spacing()
+ },
+ warehouseSelectContainer: {
+ paddingTop: theme.spacing(2)
}
}),
{ name: "ProductVariants" }
@@ -90,6 +137,7 @@ export const ProductVariants: React.FC = props => {
const classes = useStyles(props);
const intl = useIntl();
+ const [warehouse, setWarehouse] = React.useState(null);
const hasVariants = maybe(() => variants.length > 0, true);
return (
@@ -127,7 +175,23 @@ export const ProductVariants: React.FC = props => {
)
}
/>
- {!variants.length && (
+
+ {variants.length > 0 ? (
+
+
+
+
+ setWarehouse(event.target.value)}
+ />
+
+ ) : (
@@ -146,7 +210,7 @@ export const ProductVariants: React.FC = props => {
>
@@ -175,6 +239,9 @@ export const ProductVariants: React.FC = props => {
variant && variant.stock
? variant.stock.reduce((acc, s) => acc + s.quantity, 0)
: null;
+ const variantStock = variant.stock.find(
+ s => s.warehouse.id === warehouse
+ );
return (
= props => {
>
{numAvailable === null ? (
- ) : numAvailable === 0 ? (
-
+ ) : warehouse === null ? (
+ numAvailable === 0 ? (
+
+ ) : (
+
+ )
+ ) : !!variantStock ? (
+ variantStock.quantity > 0 ? (
+
+ ) : (
+
+ )
) : (
)}
diff --git a/src/products/queries.ts b/src/products/queries.ts
index 5e5f58977..1e292428b 100644
--- a/src/products/queries.ts
+++ b/src/products/queries.ts
@@ -149,6 +149,10 @@ export const productFragmentDetails = gql`
stock {
id
quantity
+ warehouse {
+ id
+ name
+ }
}
}
productType {
diff --git a/src/products/types/Product.ts b/src/products/types/Product.ts
index e0cafa652..0dfd6a748 100644
--- a/src/products/types/Product.ts
+++ b/src/products/types/Product.ts
@@ -127,10 +127,17 @@ export interface Product_variants_priceOverride {
currency: string;
}
+export interface Product_variants_stock_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
export interface Product_variants_stock {
__typename: "Stock";
id: string;
quantity: number;
+ warehouse: Product_variants_stock_warehouse;
}
export interface Product_variants {
diff --git a/src/products/types/ProductCreate.ts b/src/products/types/ProductCreate.ts
index b1409b4d8..e22239d5a 100644
--- a/src/products/types/ProductCreate.ts
+++ b/src/products/types/ProductCreate.ts
@@ -133,10 +133,17 @@ export interface ProductCreate_productCreate_product_variants_priceOverride {
currency: string;
}
+export interface ProductCreate_productCreate_product_variants_stock_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
export interface ProductCreate_productCreate_product_variants_stock {
__typename: "Stock";
id: string;
quantity: number;
+ warehouse: ProductCreate_productCreate_product_variants_stock_warehouse;
}
export interface ProductCreate_productCreate_product_variants {
diff --git a/src/products/types/ProductDetails.ts b/src/products/types/ProductDetails.ts
index 78013430e..a880cdccc 100644
--- a/src/products/types/ProductDetails.ts
+++ b/src/products/types/ProductDetails.ts
@@ -127,10 +127,17 @@ export interface ProductDetails_product_variants_priceOverride {
currency: string;
}
+export interface ProductDetails_product_variants_stock_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
export interface ProductDetails_product_variants_stock {
__typename: "Stock";
id: string;
quantity: number;
+ warehouse: ProductDetails_product_variants_stock_warehouse;
}
export interface ProductDetails_product_variants {
diff --git a/src/products/types/ProductImageCreate.ts b/src/products/types/ProductImageCreate.ts
index 45f62c860..8efec0618 100644
--- a/src/products/types/ProductImageCreate.ts
+++ b/src/products/types/ProductImageCreate.ts
@@ -133,10 +133,17 @@ export interface ProductImageCreate_productImageCreate_product_variants_priceOve
currency: string;
}
+export interface ProductImageCreate_productImageCreate_product_variants_stock_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
export interface ProductImageCreate_productImageCreate_product_variants_stock {
__typename: "Stock";
id: string;
quantity: number;
+ warehouse: ProductImageCreate_productImageCreate_product_variants_stock_warehouse;
}
export interface ProductImageCreate_productImageCreate_product_variants {
diff --git a/src/products/types/ProductImageUpdate.ts b/src/products/types/ProductImageUpdate.ts
index 0be498717..c98fe2909 100644
--- a/src/products/types/ProductImageUpdate.ts
+++ b/src/products/types/ProductImageUpdate.ts
@@ -133,10 +133,17 @@ export interface ProductImageUpdate_productImageUpdate_product_variants_priceOve
currency: string;
}
+export interface ProductImageUpdate_productImageUpdate_product_variants_stock_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
export interface ProductImageUpdate_productImageUpdate_product_variants_stock {
__typename: "Stock";
id: string;
quantity: number;
+ warehouse: ProductImageUpdate_productImageUpdate_product_variants_stock_warehouse;
}
export interface ProductImageUpdate_productImageUpdate_product_variants {
diff --git a/src/products/types/ProductUpdate.ts b/src/products/types/ProductUpdate.ts
index 7fce89379..3fab87f99 100644
--- a/src/products/types/ProductUpdate.ts
+++ b/src/products/types/ProductUpdate.ts
@@ -133,10 +133,17 @@ export interface ProductUpdate_productUpdate_product_variants_priceOverride {
currency: string;
}
+export interface ProductUpdate_productUpdate_product_variants_stock_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
export interface ProductUpdate_productUpdate_product_variants_stock {
__typename: "Stock";
id: string;
quantity: number;
+ warehouse: ProductUpdate_productUpdate_product_variants_stock_warehouse;
}
export interface ProductUpdate_productUpdate_product_variants {
diff --git a/src/products/types/SimpleProductUpdate.ts b/src/products/types/SimpleProductUpdate.ts
index c49bd09a6..c7ffb7b9f 100644
--- a/src/products/types/SimpleProductUpdate.ts
+++ b/src/products/types/SimpleProductUpdate.ts
@@ -133,10 +133,17 @@ export interface SimpleProductUpdate_productUpdate_product_variants_priceOverrid
currency: string;
}
+export interface SimpleProductUpdate_productUpdate_product_variants_stock_warehouse {
+ __typename: "Warehouse";
+ id: string;
+ name: string;
+}
+
export interface SimpleProductUpdate_productUpdate_product_variants_stock {
__typename: "Stock";
id: string;
quantity: number;
+ warehouse: SimpleProductUpdate_productUpdate_product_variants_stock_warehouse;
}
export interface SimpleProductUpdate_productUpdate_product_variants {
From 12c5e406465699db8662e3ca21aec127727cf265 Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Fri, 7 Feb 2020 17:50:32 +0100
Subject: [PATCH 16/88] Fix dropdown position
---
src/products/components/ProductVariants/ProductVariants.tsx | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/products/components/ProductVariants/ProductVariants.tsx b/src/products/components/ProductVariants/ProductVariants.tsx
index a266ec46a..fe6b79765 100644
--- a/src/products/components/ProductVariants/ProductVariants.tsx
+++ b/src/products/components/ProductVariants/ProductVariants.tsx
@@ -92,6 +92,9 @@ const useStyles = makeStyles(
link: {
cursor: "pointer"
},
+ select: {
+ display: "inline-block"
+ },
textLeft: {
textAlign: "left" as "left"
},
@@ -185,6 +188,7 @@ export const ProductVariants: React.FC = props => {
/>
Date: Mon, 10 Feb 2020 13:50:08 +0100
Subject: [PATCH 17/88] Simplify code
---
src/shipping/queries.ts | 4 +-
src/shipping/views/ShippingZonesList.tsx | 383 +++++++++++------------
2 files changed, 178 insertions(+), 209 deletions(-)
diff --git a/src/shipping/queries.ts b/src/shipping/queries.ts
index 9779655e2..771a32b3f 100644
--- a/src/shipping/queries.ts
+++ b/src/shipping/queries.ts
@@ -1,7 +1,7 @@
import gql from "graphql-tag";
import makeQuery from "@saleor/hooks/makeQuery";
-import { pageInfoFragment, TypedQuery } from "../queries";
+import { pageInfoFragment } from "../queries";
import { ShippingZone, ShippingZoneVariables } from "./types/ShippingZone";
import { ShippingZones, ShippingZonesVariables } from "./types/ShippingZones";
@@ -79,7 +79,7 @@ const shippingZones = gql`
}
}
`;
-export const TypedShippingZones = TypedQuery<
+export const useShippingZoneList = makeQuery<
ShippingZones,
ShippingZonesVariables
>(shippingZones);
diff --git a/src/shipping/views/ShippingZonesList.tsx b/src/shipping/views/ShippingZonesList.tsx
index 488e629ae..dd2ab2241 100644
--- a/src/shipping/views/ShippingZonesList.tsx
+++ b/src/shipping/views/ShippingZonesList.tsx
@@ -16,23 +16,22 @@ import usePaginator, {
import useShop from "@saleor/hooks/useShop";
import useUser from "@saleor/hooks/useUser";
import { commonMessages } from "@saleor/intl";
-import { maybe } from "@saleor/misc";
+import { maybe, getStringOrPlaceholder } from "@saleor/misc";
import { ListViews } from "@saleor/types";
+import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import ShippingZonesListPage from "../components/ShippingZonesListPage";
import {
- TypedBulkDeleteShippingZone,
- TypedDeleteShippingZone,
- TypedUpdateDefaultWeightUnit
+ useShippingZoneBulkDelete,
+ useShippingZoneDelete,
+ useDefaultWeightUnitUpdate
} from "../mutations";
-import { TypedShippingZones } from "../queries";
-import { BulkDeleteShippingZone } from "../types/BulkDeleteShippingZone";
-import { DeleteShippingZone } from "../types/DeleteShippingZone";
-import { UpdateDefaultWeightUnit } from "../types/UpdateDefaultWeightUnit";
+import { useShippingZoneList } from "../queries";
import {
shippingZoneAddUrl,
shippingZonesListUrl,
ShippingZonesListUrlQueryParams,
- shippingZoneUrl
+ shippingZoneUrl,
+ ShippingZonesListUrlDialog
} from "../urls";
interface ShippingZonesListProps {
@@ -57,206 +56,176 @@ export const ShippingZonesList: React.FC = ({
const paginationState = createPaginationState(settings.rowNumber, params);
+ const [openModal, closeModal] = createDialogActionHandlers<
+ ShippingZonesListUrlDialog,
+ ShippingZonesListUrlQueryParams
+ >(navigate, shippingZonesListUrl, params);
+
+ const { data, loading, refetch } = useShippingZoneList({
+ displayLoader: true,
+ variables: paginationState
+ });
+
+ const [deleteShippingZone, deleteShippingZoneOpts] = useShippingZoneDelete({
+ onCompleted: data => {
+ if (data.shippingZoneDelete.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ closeModal();
+ refetch();
+ }
+ }
+ });
+
+ const [
+ updateDefaultWeightUnit,
+ updateDefaultWeightUnitOpts
+ ] = useDefaultWeightUnitUpdate({
+ onCompleted: data => {
+ if (data.shopSettingsUpdate.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ }
+ }
+ });
+
+ const [
+ bulkDeleteShippingZone,
+ bulkDeleteShippingZoneOpts
+ ] = useShippingZoneBulkDelete({
+ onCompleted: data => {
+ if (data.shippingZoneBulkDelete.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ closeModal();
+ reset();
+ refetch();
+ }
+ }
+ });
+
+ const { loadNextPage, loadPreviousPage, pageInfo } = paginate(
+ maybe(() => data.shippingZones.pageInfo),
+ paginationState,
+ params
+ );
return (
-
- {({ data, loading, refetch }) => {
- const handleUpdateDefaultWeightUnit = (
- data: UpdateDefaultWeightUnit
- ) => {
- if (data.shopSettingsUpdate.errors.length === 0) {
- notify({
- text: intl.formatMessage(commonMessages.savedChanges)
- });
- }
- };
+ <>
+ shop.defaultWeightUnit)}
+ settings={settings}
+ disabled={
+ loading ||
+ deleteShippingZoneOpts.loading ||
+ updateDefaultWeightUnitOpts.loading
+ }
+ shippingZones={maybe(() =>
+ data.shippingZones.edges.map(edge => edge.node)
+ )}
+ pageInfo={pageInfo}
+ onAdd={() => navigate(shippingZoneAddUrl)}
+ onBack={() => navigate(configurationMenuUrl)}
+ onUpdateListSettings={updateListSettings}
+ onNextPage={loadNextPage}
+ onPreviousPage={loadPreviousPage}
+ onRemove={id =>
+ openModal("remove", {
+ id
+ })
+ }
+ onRowClick={id => () => navigate(shippingZoneUrl(id))}
+ onSubmit={unit =>
+ updateDefaultWeightUnit({
+ variables: { unit }
+ })
+ }
+ isChecked={isSelected}
+ selected={listElements.length}
+ toggle={toggle}
+ toggleAll={toggleAll}
+ toolbar={
+
+ openModal("remove-many", {
+ ids: listElements
+ })
+ }
+ >
+
+
+ }
+ userPermissions={user?.userPermissions || []}
+ />
- const closeModal = () =>
- navigate(
- shippingZonesListUrl({
- ...params,
- action: undefined,
- ids: undefined
- }),
- true
- );
-
- const handleShippingZoneDelete = (data: DeleteShippingZone) => {
- if (data.shippingZoneDelete.errors.length === 0) {
- notify({
- text: intl.formatMessage(commonMessages.savedChanges)
- });
- closeModal();
- refetch();
- }
- };
-
- const handleBulkDeleteShippingZone = (data: BulkDeleteShippingZone) => {
- if (data.shippingZoneBulkDelete.errors.length === 0) {
- notify({
- text: intl.formatMessage(commonMessages.savedChanges)
- });
- closeModal();
- reset();
- refetch();
- }
- };
- return (
-
- {(deleteShippingZone, deleteShippingZoneOpts) => (
-
- {(updateDefaultWeightUnit, updateDefaultWeightUnitOpts) => (
-
- {(bulkDeleteShippingZone, bulkDeleteShippingZoneOpts) => {
- const {
- loadNextPage,
- loadPreviousPage,
- pageInfo
- } = paginate(
- maybe(() => data.shippingZones.pageInfo),
- paginationState,
- params
- );
-
- return (
- <>
- shop.defaultWeightUnit
- )}
- settings={settings}
- disabled={
- loading ||
- deleteShippingZoneOpts.loading ||
- updateDefaultWeightUnitOpts.loading
- }
- shippingZones={maybe(() =>
- data.shippingZones.edges.map(edge => edge.node)
- )}
- pageInfo={pageInfo}
- onAdd={() => navigate(shippingZoneAddUrl)}
- onBack={() => navigate(configurationMenuUrl)}
- onUpdateListSettings={updateListSettings}
- onNextPage={loadNextPage}
- onPreviousPage={loadPreviousPage}
- onRemove={id =>
- navigate(
- shippingZonesListUrl({
- ...params,
- action: "remove",
- id
- })
- )
- }
- onRowClick={id => () =>
- navigate(shippingZoneUrl(id))}
- onSubmit={unit =>
- updateDefaultWeightUnit({
- variables: { unit }
- })
- }
- isChecked={isSelected}
- selected={listElements.length}
- toggle={toggle}
- toggleAll={toggleAll}
- toolbar={
-
- navigate(
- shippingZonesListUrl({
- action: "remove-many",
- ids: listElements
- })
- )
- }
- >
-
-
- }
- userPermissions={user?.userPermissions || []}
- />
-
-
- deleteShippingZone({
- variables: { id: params.id }
- })
- }
- >
-
-
- {maybe(
- () =>
- data.shippingZones.edges.find(
- edge => edge.node.id === params.id
- ).node.name,
- "..."
- )}
-
- )
- }}
- />
-
-
-
- bulkDeleteShippingZone({
- variables: { ids: params.ids }
- })
- }
- >
-
- params.ids.length),
- displayQuantity: (
-
- {maybe(() => params.ids.length)}
-
- )
- }}
- />
-
-
- >
- );
- }}
-
- )}
-
- )}
-
- );
- }}
-
+
+ deleteShippingZone({
+ variables: { id: params.id }
+ })
+ }
+ >
+
+
+ {maybe(
+ () =>
+ data.shippingZones.edges.find(
+ edge => edge.node.id === params.id
+ ).node.name,
+ "..."
+ )}
+
+ )
+ }}
+ />
+
+
+
+ bulkDeleteShippingZone({
+ variables: { ids: params.ids }
+ })
+ }
+ >
+
+
+ {getStringOrPlaceholder(params.ids?.length.toString())}
+
+ )
+ }}
+ />
+
+
+ >
);
};
ShippingZonesList.displayName = "ShippingZonesList";
From 60ec16961cae70e17fe75d5e9817ec0005a9b218 Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Mon, 10 Feb 2020 17:07:17 +0100
Subject: [PATCH 18/88] 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 && (
+
+ )}
{displayCustomValue && (
)}
+ {add && (
+
+ )}
{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
From 93d1d74230c9f5b774750c451035b77d7ddd753d Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Tue, 11 Feb 2020 15:41:56 +0100
Subject: [PATCH 19/88] Allow creating warehouse from shipping zone view
---
.../CompanyAddressForm.tsx | 190 ++++++++++++++++++
.../CompanyAddressInput.tsx | 180 +----------------
.../SingleAutocompleteSelectField.tsx | 16 +-
.../ShippingZoneAddWarehouseDialog.tsx | 162 +++++++++++++++
.../ShippingZoneAddWarehouseDialog/index.ts | 2 +
.../views/ShippingZoneDetails/index.tsx | 50 ++++-
6 files changed, 420 insertions(+), 180 deletions(-)
create mode 100644 src/components/CompanyAddressInput/CompanyAddressForm.tsx
create mode 100644 src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx
create mode 100644 src/shipping/components/ShippingZoneAddWarehouseDialog/index.ts
diff --git a/src/components/CompanyAddressInput/CompanyAddressForm.tsx b/src/components/CompanyAddressInput/CompanyAddressForm.tsx
new file mode 100644
index 000000000..b94b87aac
--- /dev/null
+++ b/src/components/CompanyAddressInput/CompanyAddressForm.tsx
@@ -0,0 +1,190 @@
+import { makeStyles } from "@material-ui/core/styles";
+import TextField from "@material-ui/core/TextField";
+import React from "react";
+import { useIntl, IntlShape } from "react-intl";
+
+import FormSpacer from "@saleor/components/FormSpacer";
+import Grid from "@saleor/components/Grid";
+import SingleAutocompleteSelectField, {
+ SingleAutocompleteChoiceType
+} from "@saleor/components/SingleAutocompleteSelectField";
+import { AddressTypeInput } from "@saleor/customers/types";
+import { ChangeEvent } from "@saleor/hooks/useForm";
+import getShopErrorMessage from "@saleor/utils/errors/shop";
+import { getFormErrors } from "@saleor/utils/errors";
+import { ShopErrorFragment } from "@saleor/siteSettings/types/ShopErrorFragment";
+import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
+import getAccountErrorMessage from "@saleor/utils/errors/account";
+
+export interface CompanyAddressFormProps {
+ countries: SingleAutocompleteChoiceType[];
+ data: AddressTypeInput;
+ displayCountry: string;
+ errors: Array;
+ disabled: boolean;
+ onChange: (event: ChangeEvent) => void;
+ onCountryChange: (event: ChangeEvent) => void;
+}
+
+const useStyles = makeStyles(
+ {
+ root: {}
+ },
+ { name: "CompanyAddressForm" }
+);
+
+function getErrorMessage(
+ err: AccountErrorFragment | ShopErrorFragment,
+ intl: IntlShape
+): string {
+ if (err?.__typename === "AccountError") {
+ return getAccountErrorMessage(err, intl);
+ }
+
+ return getShopErrorMessage(err, intl);
+}
+
+const CompanyAddressForm: React.FC = props => {
+ const {
+ countries,
+ data,
+ disabled,
+ displayCountry,
+ errors,
+ onChange,
+ onCountryChange
+ } = props;
+
+ const classes = useStyles(props);
+ const intl = useIntl();
+
+ const formFields = [
+ "companyName",
+ "streetAddress1",
+ "streetAddress2",
+ "city",
+ "postalCode",
+ "country",
+ "companyArea",
+ "phone"
+ ];
+ const formErrors = getFormErrors(formFields, errors);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+CompanyAddressForm.displayName = "CompanyAddressForm";
+export default CompanyAddressForm;
diff --git a/src/components/CompanyAddressInput/CompanyAddressInput.tsx b/src/components/CompanyAddressInput/CompanyAddressInput.tsx
index bdd2374a4..a064b4c25 100644
--- a/src/components/CompanyAddressInput/CompanyAddressInput.tsx
+++ b/src/components/CompanyAddressInput/CompanyAddressInput.tsx
@@ -1,33 +1,17 @@
import Card from "@material-ui/core/Card";
import CardContent from "@material-ui/core/CardContent";
import { makeStyles } from "@material-ui/core/styles";
-import TextField from "@material-ui/core/TextField";
import React from "react";
-import { useIntl, IntlShape } from "react-intl";
+import classNames from "classnames";
-import CardTitle from "@saleor/components/CardTitle";
-import FormSpacer from "@saleor/components/FormSpacer";
-import Grid from "@saleor/components/Grid";
-import SingleAutocompleteSelectField, {
- SingleAutocompleteChoiceType
-} from "@saleor/components/SingleAutocompleteSelectField";
-import { ChangeEvent } from "@saleor/hooks/useForm";
-import { getFormErrors } from "@saleor/utils/errors";
-import { ShopErrorFragment } from "@saleor/siteSettings/types/ShopErrorFragment";
-import getShopErrorMessage from "@saleor/utils/errors/shop";
-import { AccountErrorFragment } from "@saleor/customers/types/AccountErrorFragment";
-import getAccountErrorMessage from "@saleor/utils/errors/account";
-import { AddressTypeInput } from "@saleor/customers/types";
+import CardTitle from "../CardTitle";
+import CompanyAddressForm, {
+ CompanyAddressFormProps
+} from "./CompanyAddressForm";
-interface CompanyAddressInputProps {
- countries: SingleAutocompleteChoiceType[];
- data: AddressTypeInput;
- displayCountry: string;
- errors: Array;
- disabled: boolean;
+interface CompanyAddressInputProps extends CompanyAddressFormProps {
+ className: string;
header: string;
- onChange: (event: ChangeEvent) => void;
- onCountryChange: (event: ChangeEvent) => void;
}
const useStyles = makeStyles(
@@ -39,159 +23,15 @@ const useStyles = makeStyles(
{ name: "CompanyAddressInput" }
);
-function getErrorMessage(
- err: AccountErrorFragment | ShopErrorFragment,
- intl: IntlShape
-): string {
- if (err?.__typename === "AccountError") {
- return getAccountErrorMessage(err, intl);
- }
-
- return getShopErrorMessage(err, intl);
-}
-
const CompanyAddressInput: React.FC = props => {
- const {
- countries,
- data,
- disabled,
- displayCountry,
- errors,
- header,
- onChange,
- onCountryChange
- } = props;
-
+ const { className, header, ...formProps } = props;
const classes = useStyles(props);
- const intl = useIntl();
-
- const formFields = [
- "companyName",
- "streetAddress1",
- "streetAddress2",
- "city",
- "postalCode",
- "country",
- "companyArea",
- "phone"
- ];
- const formErrors = getFormErrors(formFields, errors);
return (
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
);
diff --git a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx
index 4df5b02e6..f140d4c05 100644
--- a/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx
+++ b/src/components/SingleAutocompleteSelectField/SingleAutocompleteSelectField.tsx
@@ -26,7 +26,7 @@ const useStyles = makeStyles(
export interface SingleAutocompleteSelectFieldProps
extends Partial {
- add: SingleAutocompleteActionType;
+ add?: SingleAutocompleteActionType;
error?: boolean;
name: string;
displayValue: string;
@@ -147,13 +147,15 @@ const SingleAutocompleteSelectFieldComponent: React.FC
{isOpen && (!!inputValue || !!choices.length) && (
{
- add.onClick();
- closeMenu();
+ add={
+ !!add && {
+ ...add,
+ onClick: () => {
+ add.onClick();
+ closeMenu();
+ }
}
- }}
+ }
choices={choices}
displayCustomValue={displayCustomValue}
emptyOption={emptyOption}
diff --git a/src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx b/src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx
new file mode 100644
index 000000000..4e2f3e806
--- /dev/null
+++ b/src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx
@@ -0,0 +1,162 @@
+import Button from "@material-ui/core/Button";
+import Dialog from "@material-ui/core/Dialog";
+import DialogActions from "@material-ui/core/DialogActions";
+import DialogContent from "@material-ui/core/DialogContent";
+import DialogTitle from "@material-ui/core/DialogTitle";
+import TextField from "@material-ui/core/TextField";
+import React from "react";
+import { FormattedMessage, useIntl } from "react-intl";
+import makeStyles from "@material-ui/core/styles/makeStyles";
+
+import ConfirmButton, {
+ ConfirmButtonTransitionState
+} from "@saleor/components/ConfirmButton";
+import { DialogProps, UserError } from "@saleor/types";
+import { AddressTypeInput } from "@saleor/customers/types";
+import useModalDialogOpen from "@saleor/hooks/useModalDialogOpen";
+import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
+import CompanyAddressForm from "@saleor/components/CompanyAddressInput/CompanyAddressForm";
+import { buttonMessages } from "@saleor/intl";
+import Hr from "@saleor/components/Hr";
+import Form from "@saleor/components/Form";
+import useAddressValidation from "@saleor/hooks/useAddressValidation";
+import useStateFromProps from "@saleor/hooks/useStateFromProps";
+import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo";
+import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
+import FormSpacer from "@saleor/components/FormSpacer";
+
+export interface ShippingZoneAddWarehouseDialogSubmitData
+ extends AddressTypeInput {
+ name: string;
+}
+export interface ShippingZoneAddWarehouseDialogProps extends DialogProps {
+ confirmButtonState: ConfirmButtonTransitionState;
+ countries: ShopInfo_shop_countries[];
+ disabled: boolean;
+ errors: UserError[];
+ onSubmit: (data: ShippingZoneAddWarehouseDialogSubmitData) => void;
+}
+
+const initialForm: ShippingZoneAddWarehouseDialogSubmitData = {
+ city: "",
+ cityArea: "",
+ companyName: "",
+ country: "",
+ countryArea: "",
+ firstName: "",
+ lastName: "",
+ name: "",
+ phone: "",
+ postalCode: "",
+ streetAddress1: "",
+ streetAddress2: ""
+};
+
+const useStyles = makeStyles(
+ {
+ overflow: {
+ overflowY: "visible"
+ }
+ },
+ {
+ name: "ShippingZoneAddWarehouseDialog"
+ }
+);
+
+const ShippingZoneAddWarehouseDialog: React.FC = ({
+ confirmButtonState,
+ countries,
+ disabled,
+ errors: apiErrors,
+ open,
+ onClose,
+ onSubmit
+}) => {
+ const classes = useStyles({});
+ const [countryDisplayName, setCountryDisplayName] = useStateFromProps("");
+ const {
+ errors: validationErrors,
+ submit: handleSubmit
+ } = useAddressValidation(onSubmit);
+ const errors = useModalDialogErrors(
+ [...apiErrors, ...validationErrors],
+ open
+ );
+ useModalDialogOpen(open, {});
+ const intl = useIntl();
+
+ const countryChoices = countries.map(country => ({
+ label: country.country,
+ value: country.code
+ }));
+
+ return (
+
+ );
+};
+
+ShippingZoneAddWarehouseDialog.displayName = "ShippingZoneAddWarehouseDialog";
+export default ShippingZoneAddWarehouseDialog;
diff --git a/src/shipping/components/ShippingZoneAddWarehouseDialog/index.ts b/src/shipping/components/ShippingZoneAddWarehouseDialog/index.ts
new file mode 100644
index 000000000..3d5129332
--- /dev/null
+++ b/src/shipping/components/ShippingZoneAddWarehouseDialog/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./ShippingZoneAddWarehouseDialog";
+export * from "./ShippingZoneAddWarehouseDialog";
diff --git a/src/shipping/views/ShippingZoneDetails/index.tsx b/src/shipping/views/ShippingZoneDetails/index.tsx
index 9350e8165..ea22654e4 100644
--- a/src/shipping/views/ShippingZoneDetails/index.tsx
+++ b/src/shipping/views/ShippingZoneDetails/index.tsx
@@ -21,8 +21,13 @@ import ShippingZoneRateDialog from "@saleor/shipping/components/ShippingZoneRate
import useShop from "@saleor/hooks/useShop";
import ShippingZoneCountriesAssignDialog from "@saleor/shipping/components/ShippingZoneCountriesAssignDialog";
import NotFoundPage from "@saleor/components/NotFoundPage";
-import { getStringOrPlaceholder } from "../../../misc";
-import { ShippingMethodTypeEnum } from "../../../types/globalTypes";
+import ShippingZoneAddWarehouseDialog from "@saleor/shipping/components/ShippingZoneAddWarehouseDialog";
+import { useWarehouseCreate } from "@saleor/warehouses/mutations";
+import { getStringOrPlaceholder, findValueInEnum } from "../../../misc";
+import {
+ ShippingMethodTypeEnum,
+ CountryCode
+} from "../../../types/globalTypes";
import ShippingZoneDetailsPage, {
FormData
} from "../../components/ShippingZoneDetailsPage";
@@ -126,6 +131,17 @@ const ShippingZoneDetails: React.FC = ({
}
});
+ const [createWarehouse, createWarehouseOpts] = useWarehouseCreate({
+ onCompleted: data => {
+ if (data.createWarehouse.errors.length === 0) {
+ notify({
+ text: intl.formatMessage(commonMessages.savedChanges)
+ });
+ closeModal();
+ }
+ }
+ });
+
const handleSubmit = (data: FormData) => {
updateShippingZone({
variables: {
@@ -138,7 +154,7 @@ const ShippingZoneDetails: React.FC = ({
assignToWarehouse({
variables: {
shippingZoneId: id,
- warehouseId: data.warehouse
+ warehouseId: data.warehouses[0]
}
});
};
@@ -346,6 +362,34 @@ const ShippingZoneDetails: React.FC = ({
/>
+
+ createWarehouse({
+ variables: {
+ input: {
+ address: {
+ city: data.city,
+ cityArea: data.cityArea,
+ country: findValueInEnum(data.country, CountryCode),
+ countryArea: data.countryArea,
+ phone: data.phone,
+ postalCode: data.postalCode,
+ streetAddress1: data.streetAddress1,
+ streetAddress2: data.streetAddress2
+ },
+ companyName: data.companyName,
+ name: data.name
+ }
+ }
+ })
+ }
+ />
>
);
};
From fbc809879f29839c48bbfe62ed881be0943eecc4 Mon Sep 17 00:00:00 2001
From: dominik-zeglen
Date: Tue, 11 Feb 2020 16:05:09 +0100
Subject: [PATCH 20/88] Add warehouse search
---
.../ShippingZoneAddWarehouseDialog.tsx | 2 +-
.../ShippingZoneDetailsPage.tsx | 30 +++++++++++--------
.../ShippingZoneWarehouses.tsx | 11 +++++--
.../views/ShippingZoneDetails/index.tsx | 12 ++++++--
src/types.ts | 6 ++--
5 files changed, 39 insertions(+), 22 deletions(-)
diff --git a/src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx b/src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx
index 4e2f3e806..632fe73fc 100644
--- a/src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx
+++ b/src/shipping/components/ShippingZoneAddWarehouseDialog/ShippingZoneAddWarehouseDialog.tsx
@@ -105,7 +105,7 @@ const ShippingZoneAddWarehouseDialog: React.FC
diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap
index 256772bbf..f6535eb25 100644
--- a/src/storybook/__snapshots__/Stories.test.ts.snap
+++ b/src/storybook/__snapshots__/Stories.test.ts.snap
@@ -2640,6 +2640,49 @@ exports[`Storyshots Generics / Global messages with undo action 1`] = `
`;
+exports[`Storyshots Generics / Link with choices default 1`] = `
+
+`;
+
exports[`Storyshots Generics / Money formatting default 1`] = `
`;
+exports[`Storyshots Generics / Select with autocomplete with add 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
+
exports[`Storyshots Generics / SingleSelectField with error hint 1`] = `
+
+
+
+
+
+ Warehouses
+
+
+ Manage and update your warehouse information
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Warehouses
+
+
+ Manage and update your warehouse information
+
+
+
+
+
+
+
+
+
+ Permission Groups
+
+
+ Manage your permission groups and their permissions
+
+
+
+
+
+
+
+
+
@@ -34546,44 +34889,6 @@ exports[`Storyshots Views / Configuration default 1`] = `
-
-
-
-
-
- Permission Groups
-
-
- Manage your permission groups and their permissions
-
-
-
-
+
+
+ Available inventoty at:
+
+
+
+ All Warehouses
+
+
+
+
@@ -102715,6 +103054,40 @@ exports[`Storyshots Views / Products / Create product variant add first variant
+
+
+ Available inventoty at:
+
+
+
+ All Warehouses
+
+
+
+
@@ -103172,6 +103545,40 @@ exports[`Storyshots Views / Products / Create product variant default 1`] = `
+
+
+ Available inventoty at:
+
+
+
+ All Warehouses
+
+
+
+
@@ -104124,6 +104531,40 @@ exports[`Storyshots Views / Products / Create product variant with errors 1`] =
+
+
+ Available inventoty at:
+
+
+
+ All Warehouses
+
+
+
+
@@ -105850,13 +106291,7 @@ Ctrl + K"
class="MuiTableCell-root-id MuiTableCell-head-id ProductVariants-colName-id"
scope="col"
>
- Name
-
-
- Status
+ Variant
|
SKU
|
+
+ Inventory
+ |
Cordoba Oro
-
-
- Available
-
- |
87192-94370
|
+
+ 5 available at 2 locations
+ |
silver
-
-
- Available
-
- |
69055-15190
|
+
+ 13 available at 1 location
+ |
@@ -107387,13 +107818,7 @@ Ctrl + K"
class="MuiTableCell-root-id MuiTableCell-head-id ProductVariants-colName-id"
scope="col"
>
- Name
-
-
- Status
+ Variant
|
SKU
|
+
+ Inventory
+ |
Cordoba Oro
-
-
- Available
-
- |
87192-94370
|
+
+ 5 available at 2 locations
+ |
silver
-
-
- Available
-
- |
69055-15190
|
+
+ 13 available at 1 location
+ |
@@ -109172,13 +109593,7 @@ Ctrl + K"
class="MuiTableCell-root-id MuiTableCell-head-id ProductVariants-colName-id"
scope="col"
>
- Name
-
-
- Status
+ Variant
|
SKU
|
+
+ Inventory
+ |
Cordoba Oro
-
-
- Available
-
- |
87192-94370
|
+
+ 5 available at 2 locations
+ |
silver
-
-
- Available
-
- |
69055-15190
|
+
+ 13 available at 1 location
+ |
@@ -110957,13 +111368,7 @@ Ctrl + K"
class="MuiTableCell-root-id MuiTableCell-head-id ProductVariants-colName-id"
scope="col"
>
- Name
-
-
- Status
+ Variant
|
SKU
|
+
+ Inventory
+ |
Cordoba Oro
-
-
- Available
-
- |
87192-94370
|
+
+ 5 available at 2 locations
+ |
silver
-
-
- Available
-
- |
69055-15190
|
+
+ 13 available at 1 location
+ |
@@ -116006,6 +116407,99 @@ Ctrl + K"
+
+
+
+
+
+
+
+
+
+
+
+ Select warehouse from which you will ship products for this shipping zone. This warehouse address will also be used to calculate taxes.
+
+
+
+
+
+
@@ -116192,7 +116686,7 @@ exports[`Storyshots Views / Products / Product image details when loaded data 1`
>
@@ -142623,7 +146051,7 @@ exports[`Storyshots Views / Warehouses / Create warehouse form errors 1`] = `
- Generic form error
+ Invalid value
- Generic form error
+ Invalid value
- Generic form error
+ Invalid value
- Generic form error
+ Invalid value
- Generic form error
+ Invalid value
@@ -142825,7 +146253,7 @@ exports[`Storyshots Views / Warehouses / Create warehouse form errors 1`] = `
>
- Generic form error
+ Invalid value
@@ -142873,16 +146301,16 @@ exports[`Storyshots Views / Warehouses / Create warehouse form errors 1`] = `
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
>
-
- Generic form error
-
- Generic form error
+ Invalid value
@@ -143302,7 +146725,7 @@ exports[`Storyshots Views / Warehouses / Create warehouse loading 1`] = `
>
- Generic form error
+ Invalid value
@@ -144118,7 +147541,7 @@ exports[`Storyshots Views / Warehouses / Warehouse details form errors 1`] = `
- Generic form error
+ Invalid value
- Generic form error
+ Invalid value
- Generic form error
+ Invalid value
- Generic form error
+ Invalid value
- Generic form error
+ Invalid value
@@ -144320,7 +147743,7 @@ exports[`Storyshots Views / Warehouses / Warehouse details form errors 1`] = `
>
- Generic form error
+ Invalid value
@@ -144368,16 +147791,16 @@ exports[`Storyshots Views / Warehouses / Warehouse details form errors 1`] = `
class="MuiFormControl-root-id MuiTextField-root-id MuiFormControl-fullWidth-id"
>
-
- Generic form error
-
- Generic form error
+ Invalid value
@@ -144875,7 +148293,7 @@ exports[`Storyshots Views / Warehouses / Warehouse details loading 1`] = `
>
Date: Thu, 2 Apr 2020 11:52:15 +0200
Subject: [PATCH 46/88] Improve code readability
---
.../ProductVariantCreatorPage.tsx | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPage.tsx b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPage.tsx
index aaf03a9b2..dca44165f 100644
--- a/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPage.tsx
+++ b/src/products/components/ProductVariantCreatorPage/ProductVariantCreatorPage.tsx
@@ -105,7 +105,7 @@ const ProductVariantCreatePage: React.FC = props
const { attributes, defaultPrice, errors, onSubmit, ...contentProps } = props;
const classes = useStyles(props);
const intl = useIntl();
- const [step, { next, prev, set: setStep }] = useWizard<
+ const [step, { next: nextStep, prev: prevStep, set: setStep }] = useWizard<
ProductVariantCreatorStep
>(ProductVariantCreatorStep.values, [
ProductVariantCreatorStep.values,
@@ -113,7 +113,7 @@ const ProductVariantCreatePage: React.FC = props
ProductVariantCreatorStep.summary
]);
- const [data, dispatchFormDataAction] = React.useReducer(
+ const [wizardData, dispatchFormDataAction] = React.useReducer(
reduceProductVariantCreateFormData,
createInitialForm(attributes, defaultPrice)
);
@@ -131,7 +131,7 @@ const ProductVariantCreatePage: React.FC = props
{step !== ProductVariantCreatorStep.values && (
-