diff --git a/src/fragments/shipping.ts b/src/fragments/shipping.ts index 2a957a2e4..25a89d06c 100644 --- a/src/fragments/shipping.ts +++ b/src/fragments/shipping.ts @@ -1,8 +1,12 @@ import { fragmentMoney } from "@saleor/fragments/products"; import gql from "graphql-tag"; +import { metadataFragment } from "./metadata"; + export const shippingZoneFragment = gql` + ${metadataFragment} fragment ShippingZoneFragment on ShippingZone { + ...MetadataFragment id countries { code @@ -23,10 +27,12 @@ export const shippingMethodWithZipCodesFragment = gql` } `; export const shippingMethodFragment = gql` + ${metadataFragment} ${fragmentMoney} ${shippingMethodWithZipCodesFragment} fragment ShippingMethodFragment on ShippingMethod { ...ShippingMethodWithZipCodesFragment + ...MetadataFragment minimumOrderWeight { unit value diff --git a/src/fragments/types/ShippingMethodFragment.ts b/src/fragments/types/ShippingMethodFragment.ts index b8e968b2b..a22064bfd 100644 --- a/src/fragments/types/ShippingMethodFragment.ts +++ b/src/fragments/types/ShippingMethodFragment.ts @@ -15,6 +15,18 @@ export interface ShippingMethodFragment_zipCodeRules { end: string | null; } +export interface ShippingMethodFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ShippingMethodFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ShippingMethodFragment_minimumOrderWeight { __typename: "Weight"; unit: WeightUnitsEnum; @@ -65,6 +77,8 @@ export interface ShippingMethodFragment { __typename: "ShippingMethod"; id: string; zipCodeRules: (ShippingMethodFragment_zipCodeRules | null)[] | null; + metadata: (ShippingMethodFragment_metadata | null)[]; + privateMetadata: (ShippingMethodFragment_privateMetadata | null)[]; minimumOrderWeight: ShippingMethodFragment_minimumOrderWeight | null; maximumOrderWeight: ShippingMethodFragment_maximumOrderWeight | null; name: string; diff --git a/src/fragments/types/ShippingMethodWithExcludedProductsFragment.ts b/src/fragments/types/ShippingMethodWithExcludedProductsFragment.ts index 83a534ac2..23bd1e154 100644 --- a/src/fragments/types/ShippingMethodWithExcludedProductsFragment.ts +++ b/src/fragments/types/ShippingMethodWithExcludedProductsFragment.ts @@ -15,6 +15,18 @@ export interface ShippingMethodWithExcludedProductsFragment_zipCodeRules { end: string | null; } +export interface ShippingMethodWithExcludedProductsFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ShippingMethodWithExcludedProductsFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ShippingMethodWithExcludedProductsFragment_minimumOrderWeight { __typename: "Weight"; unit: WeightUnitsEnum; @@ -96,6 +108,8 @@ export interface ShippingMethodWithExcludedProductsFragment { __typename: "ShippingMethod"; id: string; zipCodeRules: (ShippingMethodWithExcludedProductsFragment_zipCodeRules | null)[] | null; + metadata: (ShippingMethodWithExcludedProductsFragment_metadata | null)[]; + privateMetadata: (ShippingMethodWithExcludedProductsFragment_privateMetadata | null)[]; minimumOrderWeight: ShippingMethodWithExcludedProductsFragment_minimumOrderWeight | null; maximumOrderWeight: ShippingMethodWithExcludedProductsFragment_maximumOrderWeight | null; name: string; diff --git a/src/fragments/types/ShippingZoneDetailsFragment.ts b/src/fragments/types/ShippingZoneDetailsFragment.ts index bfaf23fb1..da530e989 100644 --- a/src/fragments/types/ShippingZoneDetailsFragment.ts +++ b/src/fragments/types/ShippingZoneDetailsFragment.ts @@ -8,6 +8,18 @@ import { WeightUnitsEnum, ShippingMethodTypeEnum } from "./../../types/globalTyp // GraphQL fragment: ShippingZoneDetailsFragment // ==================================================== +export interface ShippingZoneDetailsFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ShippingZoneDetailsFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ShippingZoneDetailsFragment_countries { __typename: "CountryDisplay"; code: string; @@ -21,6 +33,18 @@ export interface ShippingZoneDetailsFragment_shippingMethods_zipCodeRules { end: string | null; } +export interface ShippingZoneDetailsFragment_shippingMethods_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ShippingZoneDetailsFragment_shippingMethods_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ShippingZoneDetailsFragment_shippingMethods_minimumOrderWeight { __typename: "Weight"; unit: WeightUnitsEnum; @@ -71,6 +95,8 @@ export interface ShippingZoneDetailsFragment_shippingMethods { __typename: "ShippingMethod"; id: string; zipCodeRules: (ShippingZoneDetailsFragment_shippingMethods_zipCodeRules | null)[] | null; + metadata: (ShippingZoneDetailsFragment_shippingMethods_metadata | null)[]; + privateMetadata: (ShippingZoneDetailsFragment_shippingMethods_privateMetadata | null)[]; minimumOrderWeight: ShippingZoneDetailsFragment_shippingMethods_minimumOrderWeight | null; maximumOrderWeight: ShippingZoneDetailsFragment_shippingMethods_maximumOrderWeight | null; name: string; @@ -86,6 +112,8 @@ export interface ShippingZoneDetailsFragment_warehouses { export interface ShippingZoneDetailsFragment { __typename: "ShippingZone"; + metadata: (ShippingZoneDetailsFragment_metadata | null)[]; + privateMetadata: (ShippingZoneDetailsFragment_privateMetadata | null)[]; id: string; countries: (ShippingZoneDetailsFragment_countries | null)[] | null; name: string; diff --git a/src/fragments/types/ShippingZoneFragment.ts b/src/fragments/types/ShippingZoneFragment.ts index c5523d418..ddbf30da6 100644 --- a/src/fragments/types/ShippingZoneFragment.ts +++ b/src/fragments/types/ShippingZoneFragment.ts @@ -6,6 +6,18 @@ // GraphQL fragment: ShippingZoneFragment // ==================================================== +export interface ShippingZoneFragment_metadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + +export interface ShippingZoneFragment_privateMetadata { + __typename: "MetadataItem"; + key: string; + value: string; +} + export interface ShippingZoneFragment_countries { __typename: "CountryDisplay"; code: string; @@ -14,6 +26,8 @@ export interface ShippingZoneFragment_countries { export interface ShippingZoneFragment { __typename: "ShippingZone"; + metadata: (ShippingZoneFragment_metadata | null)[]; + privateMetadata: (ShippingZoneFragment_privateMetadata | null)[]; id: string; countries: (ShippingZoneFragment_countries | null)[] | null; name: string; diff --git a/src/products/views/ProductUpdate/ProductUpdate.tsx b/src/products/views/ProductUpdate/ProductUpdate.tsx index 0b50ab426..983657c89 100644 --- a/src/products/views/ProductUpdate/ProductUpdate.tsx +++ b/src/products/views/ProductUpdate/ProductUpdate.tsx @@ -254,6 +254,7 @@ export const ProductUpdate: React.FC = ({ id, params }) => { deleteProductImage({ variables: { id } }); const handleImageEdit = (imageId: string) => () => navigate(productImageUrl(id, imageId)); + const handleSubmit = createMetadataUpdateHandler( product, createUpdateHandler( diff --git a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx index 8551390e3..334184769 100644 --- a/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx +++ b/src/shipping/components/ShippingZoneDetailsPage/ShippingZoneDetailsPage.tsx @@ -5,6 +5,8 @@ import Container from "@saleor/components/Container"; import CountryList from "@saleor/components/CountryList"; import Form from "@saleor/components/Form"; import Grid from "@saleor/components/Grid"; +import Metadata from "@saleor/components/Metadata/Metadata"; +import { MetadataFormData } from "@saleor/components/Metadata/types"; import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; import PageHeader from "@saleor/components/PageHeader"; import SaveButtonBar from "@saleor/components/SaveButtonBar"; @@ -17,6 +19,8 @@ import { import { SubmitPromise } from "@saleor/hooks/useForm"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; +import { mapMetadataItemToInput } from "@saleor/utils/maps"; +import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; @@ -27,7 +31,7 @@ import ShippingZoneInfo from "../ShippingZoneInfo"; import ShippingZoneRates from "../ShippingZoneRates"; import ShippingZoneWarehouses from "../ShippingZoneWarehouses"; -export interface FormData { +export interface FormData extends MetadataFormData { name: string; warehouses: string[]; } @@ -90,7 +94,9 @@ const ShippingZoneDetailsPage: React.FC = ({ const initialForm: FormData = { name: shippingZone?.name || "", - warehouses: shippingZone?.warehouses?.map(warehouse => warehouse.id) || [] + warehouses: shippingZone?.warehouses?.map(warehouse => warehouse.id) || [], + metadata: shippingZone?.metadata.map(mapMetadataItemToInput), + privateMetadata: shippingZone?.privateMetadata.map(mapMetadataItemToInput) }; const [warehouseDisplayValues, setWarehouseDisplayValues] = useStateFromProps< MultiAutocompleteChoiceType[] @@ -103,6 +109,10 @@ const ShippingZoneDetailsPage: React.FC = ({ const warehouseChoices = warehouses.map(warehouseToChoice); + const { + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); + return (
{({ change, data, hasChanged, submit, toggleValue }) => { @@ -113,6 +123,8 @@ const ShippingZoneDetailsPage: React.FC = ({ warehouseChoices ); + const changeMetadata = makeMetadataChangeHandler(change); + return ( @@ -174,6 +186,8 @@ const ShippingZoneDetailsPage: React.FC = ({ variant="weight" selectedChannelId={selectedChannelId} /> + +
= ({ minValue: rate?.minimumOrderWeight?.value.toString() || "", name: rate?.name || "", noLimits: false, - type: rate?.type || null + type: rate?.type || null, + metadata: rate?.metadata.map(mapMetadataItemToInput), + privateMetadata: rate?.privateMetadata.map(mapMetadataItemToInput) }; + const { + makeChangeHandler: makeMetadataChangeHandler + } = useMetadataChangeTrigger(); + return ( {({ change, data, hasChanged, submit, triggerChange }) => { @@ -104,6 +114,8 @@ export const ShippingZoneRatesPage: React.FC = ({ validatePrice(channel.price) ); + const changeMetadata = makeMetadataChangeHandler(change); + return ( @@ -164,6 +176,8 @@ export const ShippingZoneRatesPage: React.FC = ({ disabled={disabled} {...listProps} /> + +
= ({ } }); - const handleSubmit = async (formData: FormData) => { + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); + + const updateData = async (formData: FormData): Promise => { const response = await updateShippingRate({ variables: getUpdateShippingPriceRateVariables(formData, id, rateId) }); @@ -217,8 +225,17 @@ export const PriceRatesUpdate: React.FC = ({ ) }); } + + return errors; }; + const handleSubmit = createMetadataUpdateHandler( + rate, + updateData, + variables => updateMetadata({ variables }), + variables => updatePrivateMetadata({ variables }) + ); + const handleProductAssign = (ids: string[]) => assignProduct({ variables: { id: rateId, input: { products: ids } } diff --git a/src/shipping/views/ShippingZoneDetails/index.tsx b/src/shipping/views/ShippingZoneDetails/index.tsx index 33a66b200..1d14769f0 100644 --- a/src/shipping/views/ShippingZoneDetails/index.tsx +++ b/src/shipping/views/ShippingZoneDetails/index.tsx @@ -19,6 +19,11 @@ import { useShippingZoneUpdate } from "@saleor/shipping/mutations"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; import { useWarehouseCreate } from "@saleor/warehouses/mutations"; import { diff } from "fast-array-diff"; import React from "react"; @@ -125,7 +130,10 @@ const ShippingZoneDetails: React.FC = ({ } }); - const handleSubmit = async (submitData: FormData) => { + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); + + const updateData = async (submitData: FormData) => { const warehouseDiff = diff( data.shippingZone.warehouses.map(warehouse => warehouse.id), submitData.warehouses @@ -145,6 +153,13 @@ const ShippingZoneDetails: React.FC = ({ return result.data.shippingZoneUpdate.errors; }; + const handleSubmit = createMetadataUpdateHandler( + data?.shippingZone, + updateData, + variables => updateMetadata({ variables }), + variables => updatePrivateMetadata({ variables }) + ); + if (data?.shippingZone === null) { return navigate(shippingZonesListUrl())} />; } diff --git a/src/shipping/views/WeightRatesUpdate/WeightRatesUpdate.tsx b/src/shipping/views/WeightRatesUpdate/WeightRatesUpdate.tsx index f6fb71e0f..15153165b 100644 --- a/src/shipping/views/WeightRatesUpdate/WeightRatesUpdate.tsx +++ b/src/shipping/views/WeightRatesUpdate/WeightRatesUpdate.tsx @@ -48,6 +48,11 @@ import { } from "@saleor/shipping/urls"; import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes"; import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers"; +import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler"; +import { + useMetadataUpdate, + usePrivateMetadataUpdate +} from "@saleor/utils/metadata/updateMetadata"; import React from "react"; import { FormattedMessage, useIntl } from "react-intl"; @@ -203,7 +208,10 @@ export const WeightRatesUpdate: React.FC = ({ } }); - const handleSubmit = async (data: FormData) => { + const [updateMetadata] = useMetadataUpdate({}); + const [updatePrivateMetadata] = usePrivateMetadataUpdate({}); + + const updateData = async (data: FormData) => { const response = await updateShippingRate({ variables: getUpdateShippingWeightRateVariables(data, id, rateId) }); @@ -219,8 +227,17 @@ export const WeightRatesUpdate: React.FC = ({ ) }); } + + return errors; }; + const handleSubmit = createMetadataUpdateHandler( + rate, + updateData, + variables => updateMetadata({ variables }), + variables => updatePrivateMetadata({ variables }) + ); + const handleProductAssign = (ids: string[]) => assignProduct({ variables: { id: rateId, input: { products: ids } } diff --git a/src/storybook/__snapshots__/Stories.test.ts.snap b/src/storybook/__snapshots__/Stories.test.ts.snap index 4fd004819..4bc4c697f 100644 --- a/src/storybook/__snapshots__/Stories.test.ts.snap +++ b/src/storybook/__snapshots__/Stories.test.ts.snap @@ -200626,6 +200626,128 @@ exports[`Storyshots Views / Shipping / Shipping rate create price rate 1`] = `
+
+
+
+ + Metadata + +
+
+
+
+ +
+
+
+ + Private Metadata + +
+
+
+
+
+
+
+
+ + Metadata + +
+
+
+
+ +
+
+
+ + Private Metadata + +
+
+
+
+
+
+
+
+ + Metadata + +
+
+
+
+
+ + ‌ + +
+
+
+
+
+ + Private Metadata + +
+
+
+
+
+ + ‌ + +
+
+
+
+
+ + Metadata + +
+
+
+
+ +
+
+
+ + Private Metadata + +
+
+
+
+
+
+
+
+ + Metadata + +
+
+
+
+ +
+
+
+ + Private Metadata + +
+
+
+
+
+
+
+
+ + Metadata + +
+
+
+
+ +
+
+
+ + Private Metadata + +
+
+
+
+
+
+
+
+ + Metadata + +
+
+
+
+ +
+
+
+ + Private Metadata + +
+
+
+
+
+
+
+
+ + Metadata + +
+
+
+
+
+ + ‌ + +
+
+
+
+
+ + Private Metadata + +
+
+
+
+
+ + ‌ + +
+