Merge branch 'master' of github.com:mirumee/saleor-dashboard into refactor-zip-codes-to-postal-codes
This commit is contained in:
commit
afbdf0a500
36 changed files with 2516 additions and 939 deletions
42
.github/workflows/deploy-staging.yaml
vendored
Normal file
42
.github/workflows/deploy-staging.yaml
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
name: Deploy to staging
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
env:
|
||||||
|
API_URI: https://master.staging.saleor.cloud/graphql
|
||||||
|
APP_MOUNT_URI: /dashboard/
|
||||||
|
STATIC_URL: /dashboard/static/
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Package
|
||||||
|
run: |
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
- uses: actions/upload-artifact@v2
|
||||||
|
with:
|
||||||
|
name: build
|
||||||
|
path: build
|
||||||
|
deploy:
|
||||||
|
needs:
|
||||||
|
- build
|
||||||
|
runs-on: ubuntu-20.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
name: build
|
||||||
|
path: build
|
||||||
|
- name: Configure AWS Credentials
|
||||||
|
uses: aws-actions/configure-aws-credentials@v1
|
||||||
|
with:
|
||||||
|
aws-access-key-id: ${{ secrets.AWS_STAGING_ACCESS_KEY_ID }}
|
||||||
|
aws-secret-access-key: ${{ secrets.AWS_STAGING_SECRET_ACCESS_KEY }}
|
||||||
|
aws-region: us-east-1
|
||||||
|
- name: Deploy
|
||||||
|
run: |
|
||||||
|
aws s3 sync build/dashboard s3://${{ secrets.AWS_STAGING_DEPLOYMENT_BUCKET }}/saleor-master-staging/static/
|
||||||
|
aws s3 cp build/dashboard/index.html s3://${{ secrets.AWS_STAGING_DEPLOYMENT_BUCKET }}/saleor-master-staging/
|
||||||
|
aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_STAGING_CF_DIST_ID }} --paths "/dashboard*"
|
|
@ -2200,40 +2200,48 @@
|
||||||
"context": "dialog title",
|
"context": "dialog title",
|
||||||
"string": "Add Address"
|
"string": "Add Address"
|
||||||
},
|
},
|
||||||
"src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_1090326769": {
|
"src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_addAddress": {
|
||||||
"context": "customer's address book, header",
|
|
||||||
"string": "{fullName}'s Address Book"
|
|
||||||
},
|
|
||||||
"src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_1428369222": {
|
|
||||||
"string": "This customer doesn’t have any adresses added to his address book. You can add address using the button below."
|
|
||||||
},
|
|
||||||
"src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_1484733755": {
|
|
||||||
"string": "There is no address to show for this customer"
|
|
||||||
},
|
|
||||||
"src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_3623935073": {
|
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Add address"
|
"string": "Add address"
|
||||||
},
|
},
|
||||||
"src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_489918044": {
|
"src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_doesntHaveAddresses": {
|
||||||
|
"string": "This customer doesn’t have any adresses added to his address book. You can add address using the button below."
|
||||||
|
},
|
||||||
|
"src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_fullNameAddress": {
|
||||||
|
"context": "customer's address book, header",
|
||||||
|
"string": "{fullName}'s Address Book"
|
||||||
|
},
|
||||||
|
"src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_fullNameDetail": {
|
||||||
"context": "customer details, header",
|
"context": "customer details, header",
|
||||||
"string": "{fullName} Details"
|
"string": "{fullName} Details"
|
||||||
},
|
},
|
||||||
"src_dot_customers_dot_components_dot_CustomerAddress_dot_1224809208": {
|
"src_dot_customers_dot_components_dot_CustomerAddressListPage_dot_noAddressToShow": {
|
||||||
|
"string": "There is no address to show for this customer"
|
||||||
|
},
|
||||||
|
"src_dot_customers_dot_components_dot_CustomerAddress_dot_defaultAddress": {
|
||||||
"string": "Default Address"
|
"string": "Default Address"
|
||||||
},
|
},
|
||||||
"src_dot_customers_dot_components_dot_CustomerAddress_dot_1578192486": {
|
"src_dot_customers_dot_components_dot_CustomerAddress_dot_defaultBillingAddress": {
|
||||||
"string": "Default Billing Address"
|
"string": "Default Billing Address"
|
||||||
},
|
},
|
||||||
"src_dot_customers_dot_components_dot_CustomerAddress_dot_2131178753": {
|
"src_dot_customers_dot_components_dot_CustomerAddress_dot_defaultShippingAddress": {
|
||||||
"context": "button",
|
"string": "Default Shipping Address"
|
||||||
"string": "Set as default shipping address"
|
|
||||||
},
|
},
|
||||||
"src_dot_customers_dot_components_dot_CustomerAddress_dot_3096438859": {
|
"src_dot_customers_dot_components_dot_CustomerAddress_dot_deleteAddress": {
|
||||||
|
"context": "button",
|
||||||
|
"string": "Delete Address"
|
||||||
|
},
|
||||||
|
"src_dot_customers_dot_components_dot_CustomerAddress_dot_editAddress": {
|
||||||
|
"context": "button",
|
||||||
|
"string": "Edit Address"
|
||||||
|
},
|
||||||
|
"src_dot_customers_dot_components_dot_CustomerAddress_dot_setDefaultBilling": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Set as default billing address"
|
"string": "Set as default billing address"
|
||||||
},
|
},
|
||||||
"src_dot_customers_dot_components_dot_CustomerAddress_dot_4109348993": {
|
"src_dot_customers_dot_components_dot_CustomerAddress_dot_setDefaultShipping": {
|
||||||
"string": "Default Shipping Address"
|
"context": "button",
|
||||||
|
"string": "Set as default shipping address"
|
||||||
},
|
},
|
||||||
"src_dot_customers_dot_components_dot_CustomerAddresses_dot_1967111456": {
|
"src_dot_customers_dot_components_dot_CustomerAddresses_dot_1967111456": {
|
||||||
"context": "header",
|
"context": "header",
|
||||||
|
@ -5380,6 +5388,9 @@
|
||||||
"src_dot_shipping_dot_components_dot_ShippingMethodProducts_dot_4190792473": {
|
"src_dot_shipping_dot_components_dot_ShippingMethodProducts_dot_4190792473": {
|
||||||
"string": "Actions"
|
"string": "Actions"
|
||||||
},
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingRateInfo_dot_579967655": {
|
||||||
|
"string": "Shipping rate name"
|
||||||
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingRateZipCodeRangeRemoveDialog_dot_3640694505": {
|
"src_dot_shipping_dot_components_dot_ShippingRateZipCodeRangeRemoveDialog_dot_3640694505": {
|
||||||
"string": "Are you sure you want to remove this postal code rule?"
|
"string": "Are you sure you want to remove this postal code rule?"
|
||||||
},
|
},
|
||||||
|
@ -5430,33 +5441,47 @@
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneCountriesAssignDialog_dot_3510295703": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneCountriesAssignDialog_dot_3510295703": {
|
||||||
"string": "Search Countries"
|
"string": "Search Countries"
|
||||||
},
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_2364051773": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_countries": {
|
||||||
"string": "Currently, there are no countries assigned to this shipping zone"
|
"context": "country list header",
|
||||||
},
|
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_3109712047": {
|
|
||||||
"string": "Countries"
|
"string": "Countries"
|
||||||
},
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_4049462680": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_createZone": {
|
||||||
"context": "header",
|
"context": "section header",
|
||||||
"string": "Create New Shipping Zone"
|
"string": "Create New Shipping Zone"
|
||||||
},
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_4270729636": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_defaultZone": {
|
||||||
"string": "This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones"
|
"string": "This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones"
|
||||||
},
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneDetailsPage_dot_1325966144": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneCreatePage_dot_noCountriesAssigned": {
|
||||||
"string": "Shipping"
|
|
||||||
},
|
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneDetailsPage_dot_2364051773": {
|
|
||||||
"string": "Currently, there are no countries assigned to this shipping zone"
|
"string": "Currently, there are no countries assigned to this shipping zone"
|
||||||
},
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneDetailsPage_dot_3109712047": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneDetailsPage_dot_countries": {
|
||||||
|
"context": "country list header",
|
||||||
"string": "Countries"
|
"string": "Countries"
|
||||||
},
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneDetailsPage_dot_4270729636": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneDetailsPage_dot_defaultZone": {
|
||||||
"string": "This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones"
|
"string": "This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones"
|
||||||
},
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneInfo_dot_579967655": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneDetailsPage_dot_noCountriesAssigned": {
|
||||||
"string": "Shipping rate name"
|
"string": "Currently, there are no countries assigned to this shipping zone"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingZoneDetailsPage_dot_shipping": {
|
||||||
|
"context": "shipping section header",
|
||||||
|
"string": "Shipping"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingZoneInfo_dot_1470703814": {
|
||||||
|
"context": "field placeholder",
|
||||||
|
"string": "Description of a shipping zone."
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingZoneInfo_dot_1560416099": {
|
||||||
|
"string": "Shipping zone name"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingZoneInfo_dot_3374163063": {
|
||||||
|
"string": "Description"
|
||||||
|
},
|
||||||
|
"src_dot_shipping_dot_components_dot_ShippingZoneInfo_dot_3877274856": {
|
||||||
|
"context": "character limit",
|
||||||
|
"string": "{numberOfCharacters} of {maxCharacters} characters"
|
||||||
},
|
},
|
||||||
"src_dot_shipping_dot_components_dot_ShippingZoneRatesCreatePage_dot_1161979494": {
|
"src_dot_shipping_dot_components_dot_ShippingZoneRatesCreatePage_dot_1161979494": {
|
||||||
"context": "page title",
|
"context": "page title",
|
||||||
|
|
|
@ -4782,6 +4782,7 @@ type ShippingZone implements Node & ObjectWithMetadata {
|
||||||
countries: [CountryDisplay]
|
countries: [CountryDisplay]
|
||||||
shippingMethods: [ShippingMethod]
|
shippingMethods: [ShippingMethod]
|
||||||
warehouses: [Warehouse]
|
warehouses: [Warehouse]
|
||||||
|
description: String
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShippingZoneBulkDelete {
|
type ShippingZoneBulkDelete {
|
||||||
|
@ -4809,6 +4810,7 @@ type ShippingZoneCreate {
|
||||||
|
|
||||||
input ShippingZoneCreateInput {
|
input ShippingZoneCreateInput {
|
||||||
name: String
|
name: String
|
||||||
|
description: String
|
||||||
countries: [String]
|
countries: [String]
|
||||||
default: Boolean
|
default: Boolean
|
||||||
addWarehouses: [ID]
|
addWarehouses: [ID]
|
||||||
|
@ -4828,6 +4830,7 @@ type ShippingZoneUpdate {
|
||||||
|
|
||||||
input ShippingZoneUpdateInput {
|
input ShippingZoneUpdateInput {
|
||||||
name: String
|
name: String
|
||||||
|
description: String
|
||||||
countries: [String]
|
countries: [String]
|
||||||
default: Boolean
|
default: Boolean
|
||||||
addWarehouses: [ID]
|
addWarehouses: [ID]
|
||||||
|
|
|
@ -21,6 +21,7 @@ const AddressFormatter: React.FC<AddressFormatterProps> = ({ address }) => {
|
||||||
<Typography component="p">
|
<Typography component="p">
|
||||||
{address.firstName} {address.lastName}
|
{address.firstName} {address.lastName}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Typography component="p">{address.phone}</Typography>
|
||||||
{address.companyName && (
|
{address.companyName && (
|
||||||
<Typography component="p">{address.companyName}</Typography>
|
<Typography component="p">{address.companyName}</Typography>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,15 +1,12 @@
|
||||||
import Button from "@material-ui/core/Button";
|
|
||||||
import Card from "@material-ui/core/Card";
|
import Card from "@material-ui/core/Card";
|
||||||
import CardActions from "@material-ui/core/CardActions";
|
|
||||||
import CardContent from "@material-ui/core/CardContent";
|
import CardContent from "@material-ui/core/CardContent";
|
||||||
import { makeStyles } from "@material-ui/core/styles";
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
import AddressFormatter from "@saleor/components/AddressFormatter";
|
import AddressFormatter from "@saleor/components/AddressFormatter";
|
||||||
import CardMenu from "@saleor/components/CardMenu";
|
import CardMenu from "@saleor/components/CardMenu";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import Skeleton from "@saleor/components/Skeleton";
|
import Skeleton from "@saleor/components/Skeleton";
|
||||||
import { buttonMessages } from "@saleor/intl";
|
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { defineMessages, useIntl } from "react-intl";
|
||||||
|
|
||||||
import { AddressTypeEnum } from "../../../types/globalTypes";
|
import { AddressTypeEnum } from "../../../types/globalTypes";
|
||||||
import { CustomerAddresses_user_addresses } from "../../types/CustomerAddresses";
|
import { CustomerAddresses_user_addresses } from "../../types/CustomerAddresses";
|
||||||
|
@ -25,6 +22,34 @@ export interface CustomerAddressProps {
|
||||||
onSetAsDefault: (type: AddressTypeEnum) => void;
|
onSetAsDefault: (type: AddressTypeEnum) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
defaultAddress: {
|
||||||
|
defaultMessage: "Default Address"
|
||||||
|
},
|
||||||
|
defaultShippingAddress: {
|
||||||
|
defaultMessage: "Default Shipping Address"
|
||||||
|
},
|
||||||
|
defaultBillingAddress: {
|
||||||
|
defaultMessage: "Default Billing Address"
|
||||||
|
},
|
||||||
|
setDefaultShipping: {
|
||||||
|
defaultMessage: "Set as default shipping address",
|
||||||
|
description: "button"
|
||||||
|
},
|
||||||
|
setDefaultBilling: {
|
||||||
|
defaultMessage: "Set as default billing address",
|
||||||
|
description: "button"
|
||||||
|
},
|
||||||
|
editAddress: {
|
||||||
|
defaultMessage: "Edit Address",
|
||||||
|
description: "button"
|
||||||
|
},
|
||||||
|
deleteAddress: {
|
||||||
|
defaultMessage: "Delete Address",
|
||||||
|
description: "button"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
{
|
{
|
||||||
actions: {
|
actions: {
|
||||||
|
@ -64,17 +89,11 @@ const CustomerAddress: React.FC<CustomerAddressProps> = props => {
|
||||||
address ? (
|
address ? (
|
||||||
<>
|
<>
|
||||||
{isDefaultBillingAddress && isDefaultShippingAddress
|
{isDefaultBillingAddress && isDefaultShippingAddress
|
||||||
? intl.formatMessage({
|
? intl.formatMessage(messages.defaultAddress)
|
||||||
defaultMessage: "Default Address"
|
|
||||||
})
|
|
||||||
: isDefaultShippingAddress
|
: isDefaultShippingAddress
|
||||||
? intl.formatMessage({
|
? intl.formatMessage(messages.defaultShippingAddress)
|
||||||
defaultMessage: "Default Shipping Address"
|
|
||||||
})
|
|
||||||
: isDefaultBillingAddress
|
: isDefaultBillingAddress
|
||||||
? intl.formatMessage({
|
? intl.formatMessage(messages.defaultBillingAddress)
|
||||||
defaultMessage: "Default Billing Address"
|
|
||||||
})
|
|
||||||
: null}
|
: null}
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
|
@ -87,18 +106,20 @@ const CustomerAddress: React.FC<CustomerAddressProps> = props => {
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
menuItems={[
|
menuItems={[
|
||||||
{
|
{
|
||||||
label: intl.formatMessage({
|
label: intl.formatMessage(messages.setDefaultShipping),
|
||||||
defaultMessage: "Set as default shipping address",
|
|
||||||
description: "button"
|
|
||||||
}),
|
|
||||||
onSelect: () => onSetAsDefault(AddressTypeEnum.SHIPPING)
|
onSelect: () => onSetAsDefault(AddressTypeEnum.SHIPPING)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: intl.formatMessage({
|
label: intl.formatMessage(messages.setDefaultBilling),
|
||||||
defaultMessage: "Set as default billing address",
|
|
||||||
description: "button"
|
|
||||||
}),
|
|
||||||
onSelect: () => onSetAsDefault(AddressTypeEnum.BILLING)
|
onSelect: () => onSetAsDefault(AddressTypeEnum.BILLING)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage(messages.editAddress),
|
||||||
|
onSelect: () => onEdit()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: intl.formatMessage(messages.deleteAddress),
|
||||||
|
onSelect: () => onRemove()
|
||||||
}
|
}
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
|
@ -107,16 +128,6 @@ const CustomerAddress: React.FC<CustomerAddressProps> = props => {
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<AddressFormatter address={address} />
|
<AddressFormatter address={address} />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<div className={classes.actionsContainer}>
|
|
||||||
<CardActions className={classes.actions}>
|
|
||||||
<Button color="primary" disabled={disabled} onClick={onEdit}>
|
|
||||||
<FormattedMessage {...buttonMessages.edit} />
|
|
||||||
</Button>
|
|
||||||
<Button color="primary" disabled={disabled} onClick={onRemove}>
|
|
||||||
<FormattedMessage {...buttonMessages.delete} />
|
|
||||||
</Button>
|
|
||||||
</CardActions>
|
|
||||||
</div>
|
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,6 @@ import useAddressValidation from "@saleor/hooks/useAddressValidation";
|
||||||
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
import useModalDialogErrors from "@saleor/hooks/useModalDialogErrors";
|
||||||
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
import useStateFromProps from "@saleor/hooks/useStateFromProps";
|
||||||
import { buttonMessages } from "@saleor/intl";
|
import { buttonMessages } from "@saleor/intl";
|
||||||
import { maybe } from "@saleor/misc";
|
|
||||||
import { AddressInput } from "@saleor/types/globalTypes";
|
import { AddressInput } from "@saleor/types/globalTypes";
|
||||||
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
|
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
@ -59,7 +58,7 @@ const CustomerAddressDialog = withStyles(
|
||||||
onConfirm
|
onConfirm
|
||||||
}: CustomerAddressDialogProps & WithStyles<typeof styles>) => {
|
}: CustomerAddressDialogProps & WithStyles<typeof styles>) => {
|
||||||
const [countryDisplayName, setCountryDisplayName] = useStateFromProps(
|
const [countryDisplayName, setCountryDisplayName] = useStateFromProps(
|
||||||
maybe(() => address.country.country, "")
|
address?.country.country || ""
|
||||||
);
|
);
|
||||||
const {
|
const {
|
||||||
errors: validationErrors,
|
errors: validationErrors,
|
||||||
|
@ -71,27 +70,24 @@ const CustomerAddressDialog = withStyles(
|
||||||
);
|
);
|
||||||
|
|
||||||
const initialForm: AddressTypeInput = {
|
const initialForm: AddressTypeInput = {
|
||||||
city: maybe(() => address.city, ""),
|
city: address?.city || "",
|
||||||
cityArea: maybe(() => address.cityArea, ""),
|
cityArea: address?.cityArea || "",
|
||||||
companyName: maybe(() => address.companyName, ""),
|
companyName: address?.companyName || "",
|
||||||
country: maybe(() => address.country.code, ""),
|
country: address?.country.code || "",
|
||||||
countryArea: maybe(() => address.countryArea, ""),
|
countryArea: address?.countryArea || "",
|
||||||
firstName: maybe(() => address.firstName, ""),
|
firstName: address?.firstName || "",
|
||||||
lastName: maybe(() => address.lastName, ""),
|
lastName: address?.lastName || "",
|
||||||
phone: maybe(() => address.phone, ""),
|
phone: address?.phone || "",
|
||||||
postalCode: maybe(() => address.postalCode, ""),
|
postalCode: address?.postalCode || "",
|
||||||
streetAddress1: maybe(() => address.streetAddress1, ""),
|
streetAddress1: address?.streetAddress1 || "",
|
||||||
streetAddress2: maybe(() => address.streetAddress2, "")
|
streetAddress2: address?.streetAddress2 || ""
|
||||||
};
|
};
|
||||||
|
|
||||||
const countryChoices = maybe(
|
const countryChoices =
|
||||||
() =>
|
countries?.map(country => ({
|
||||||
countries.map(country => ({
|
|
||||||
label: country.label,
|
label: country.label,
|
||||||
value: country.code
|
value: country.code
|
||||||
})),
|
})) || [];
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog
|
<Dialog
|
||||||
|
|
|
@ -4,10 +4,10 @@ import Typography from "@material-ui/core/Typography";
|
||||||
import AppHeader from "@saleor/components/AppHeader";
|
import AppHeader from "@saleor/components/AppHeader";
|
||||||
import Container from "@saleor/components/Container";
|
import Container from "@saleor/components/Container";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
|
import { renderCollection } from "@saleor/misc";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { defineMessages, useIntl } from "react-intl";
|
||||||
|
|
||||||
import { maybe, renderCollection } from "../../../misc";
|
|
||||||
import { AddressTypeEnum } from "../../../types/globalTypes";
|
import { AddressTypeEnum } from "../../../types/globalTypes";
|
||||||
import { CustomerAddresses_user } from "../../types/CustomerAddresses";
|
import { CustomerAddresses_user } from "../../types/CustomerAddresses";
|
||||||
import CustomerAddress from "../CustomerAddress/CustomerAddress";
|
import CustomerAddress from "../CustomerAddress/CustomerAddress";
|
||||||
|
@ -22,6 +22,28 @@ export interface CustomerAddressListPageProps {
|
||||||
onSetAsDefault: (id: string, type: AddressTypeEnum) => void;
|
onSetAsDefault: (id: string, type: AddressTypeEnum) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
fullNameAddress: {
|
||||||
|
defaultMessage: "{fullName}'s Address Book",
|
||||||
|
description: "customer's address book, header"
|
||||||
|
},
|
||||||
|
fullNameDetail: {
|
||||||
|
defaultMessage: "{fullName} Details",
|
||||||
|
description: "customer details, header"
|
||||||
|
},
|
||||||
|
addAddress: {
|
||||||
|
defaultMessage: "Add address",
|
||||||
|
description: "button"
|
||||||
|
},
|
||||||
|
noAddressToShow: {
|
||||||
|
defaultMessage: "There is no address to show for this customer"
|
||||||
|
},
|
||||||
|
doesntHaveAddresses: {
|
||||||
|
defaultMessage:
|
||||||
|
"This customer doesn’t have any adresses added to his address book. You can add address using the button below."
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
theme => ({
|
theme => ({
|
||||||
addButton: {
|
addButton: {
|
||||||
|
@ -36,10 +58,15 @@ const useStyles = makeStyles(
|
||||||
width: 600
|
width: 600
|
||||||
},
|
},
|
||||||
root: {
|
root: {
|
||||||
columnGap: theme.spacing(3),
|
|
||||||
display: "grid",
|
display: "grid",
|
||||||
|
gap: `${theme.spacing(3)}px`,
|
||||||
gridTemplateColumns: "repeat(3, 1fr)",
|
gridTemplateColumns: "repeat(3, 1fr)",
|
||||||
rowGap: theme.spacing(3)
|
[theme.breakpoints.down("md")]: {
|
||||||
|
gridTemplateColumns: "repeat(2, 1fr)"
|
||||||
|
},
|
||||||
|
[theme.breakpoints.down("sm")]: {
|
||||||
|
gridTemplateColumns: "repeat(1, 1fr)"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
{ name: "CustomerAddressListPage" }
|
{ name: "CustomerAddressListPage" }
|
||||||
|
@ -59,50 +86,30 @@ const CustomerAddressListPage: React.FC<CustomerAddressListPageProps> = props =>
|
||||||
|
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const isEmpty = maybe(() => customer.addresses.length) === 0;
|
const isEmpty = customer?.addresses?.length === 0;
|
||||||
const fullName = maybe(
|
const fullName = [customer?.firstName, customer?.lastName].join(" ") || "...";
|
||||||
() => [customer.firstName, customer.lastName].join(" "),
|
|
||||||
"..."
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
<FormattedMessage
|
{intl.formatMessage(messages.fullNameDetail, { fullName })}
|
||||||
defaultMessage="{fullName} Details"
|
|
||||||
description="customer details, header"
|
|
||||||
values={{
|
|
||||||
fullName
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</AppHeader>
|
</AppHeader>
|
||||||
{!isEmpty && (
|
{!isEmpty && (
|
||||||
<PageHeader
|
<PageHeader
|
||||||
title={intl.formatMessage(
|
title={intl.formatMessage(messages.fullNameAddress, { fullName })}
|
||||||
{
|
|
||||||
defaultMessage: "{fullName}'s Address Book",
|
|
||||||
description: "customer's address book, header"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fullName
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
<Button color="primary" variant="contained" onClick={onAdd}>
|
<Button color="primary" variant="contained" onClick={onAdd}>
|
||||||
<FormattedMessage
|
{intl.formatMessage(messages.addAddress)}
|
||||||
defaultMessage="Add address"
|
|
||||||
description="button"
|
|
||||||
/>
|
|
||||||
</Button>
|
</Button>
|
||||||
</PageHeader>
|
</PageHeader>
|
||||||
)}
|
)}
|
||||||
{isEmpty ? (
|
{isEmpty ? (
|
||||||
<div className={classes.empty}>
|
<div className={classes.empty}>
|
||||||
<Typography variant="h5">
|
<Typography variant="h5">
|
||||||
<FormattedMessage defaultMessage="There is no address to show for this customer" />
|
{intl.formatMessage(messages.noAddressToShow)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Typography className={classes.description}>
|
<Typography className={classes.description}>
|
||||||
<FormattedMessage defaultMessage="This customer doesn’t have any adresses added to his address book. You can add address using the button below." />
|
{intl.formatMessage(messages.doesntHaveAddresses)}
|
||||||
</Typography>
|
</Typography>
|
||||||
<Button
|
<Button
|
||||||
className={classes.addButton}
|
className={classes.addButton}
|
||||||
|
@ -110,36 +117,28 @@ const CustomerAddressListPage: React.FC<CustomerAddressListPageProps> = props =>
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={onAdd}
|
onClick={onAdd}
|
||||||
>
|
>
|
||||||
<FormattedMessage
|
{intl.formatMessage(messages.addAddress)}
|
||||||
defaultMessage="Add address"
|
|
||||||
description="button"
|
|
||||||
/>
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
{renderCollection(
|
{renderCollection(customer?.addresses, (address, addressNumber) => (
|
||||||
maybe(() => customer.addresses),
|
|
||||||
(address, addressNumber) => (
|
|
||||||
<CustomerAddress
|
<CustomerAddress
|
||||||
address={address}
|
address={address}
|
||||||
addressNumber={addressNumber + 1}
|
addressNumber={addressNumber + 1}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
isDefaultBillingAddress={
|
isDefaultBillingAddress={
|
||||||
maybe(() => customer.defaultBillingAddress.id) ===
|
customer?.defaultBillingAddress?.id === address?.id
|
||||||
maybe(() => address.id)
|
|
||||||
}
|
}
|
||||||
isDefaultShippingAddress={
|
isDefaultShippingAddress={
|
||||||
maybe(() => customer.defaultShippingAddress.id) ===
|
customer?.defaultShippingAddress?.id === address?.id
|
||||||
maybe(() => address.id)
|
|
||||||
}
|
}
|
||||||
onEdit={() => onEdit(address.id)}
|
onEdit={() => onEdit(address.id)}
|
||||||
onRemove={() => onRemove(address.id)}
|
onRemove={() => onRemove(address.id)}
|
||||||
onSetAsDefault={type => onSetAsDefault(address.id, type)}
|
onSetAsDefault={type => onSetAsDefault(address.id, type)}
|
||||||
key={maybe(() => address.id, "skeleton")}
|
key={address?.id || "skeleton"}
|
||||||
/>
|
/>
|
||||||
)
|
))}
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Container>
|
</Container>
|
||||||
|
|
|
@ -4,11 +4,15 @@ import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
|
||||||
import Container from "@saleor/components/Container";
|
import Container from "@saleor/components/Container";
|
||||||
import Form from "@saleor/components/Form";
|
import Form from "@saleor/components/Form";
|
||||||
import Grid from "@saleor/components/Grid";
|
import Grid from "@saleor/components/Grid";
|
||||||
|
import Metadata from "@saleor/components/Metadata/Metadata";
|
||||||
|
import { MetadataFormData } from "@saleor/components/Metadata/types";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||||
import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment";
|
import { AccountErrorFragment } from "@saleor/fragments/types/AccountErrorFragment";
|
||||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
|
import { mapMetadataItemToInput } from "@saleor/utils/maps";
|
||||||
|
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
@ -20,7 +24,7 @@ import CustomerInfo from "../CustomerInfo";
|
||||||
import CustomerOrders from "../CustomerOrders";
|
import CustomerOrders from "../CustomerOrders";
|
||||||
import CustomerStats from "../CustomerStats";
|
import CustomerStats from "../CustomerStats";
|
||||||
|
|
||||||
export interface CustomerDetailsPageFormData {
|
export interface CustomerDetailsPageFormData extends MetadataFormData {
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
email: string;
|
email: string;
|
||||||
|
@ -55,19 +59,26 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
|
||||||
}: CustomerDetailsPageProps) => {
|
}: CustomerDetailsPageProps) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const initialForm: CustomerDetailsPageFormData = {
|
||||||
|
email: customer?.email || "",
|
||||||
|
firstName: customer?.firstName || "",
|
||||||
|
isActive: customer?.isActive || false,
|
||||||
|
lastName: customer?.lastName || "",
|
||||||
|
note: customer?.note || "",
|
||||||
|
metadata: customer?.metadata.map(mapMetadataItemToInput),
|
||||||
|
privateMetadata: customer?.privateMetadata.map(mapMetadataItemToInput)
|
||||||
|
};
|
||||||
|
|
||||||
|
const {
|
||||||
|
makeChangeHandler: makeMetadataChangeHandler
|
||||||
|
} = useMetadataChangeTrigger();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Form initial={initialForm} onSubmit={onSubmit} confirmLeave>
|
||||||
|
{({ change, data, hasChanged, submit }) => {
|
||||||
|
const changeMetadata = makeMetadataChangeHandler(change);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
|
||||||
initial={{
|
|
||||||
email: maybe(() => customer.email, ""),
|
|
||||||
firstName: maybe(() => customer.firstName, ""),
|
|
||||||
isActive: maybe(() => customer.isActive, false),
|
|
||||||
lastName: maybe(() => customer.lastName, ""),
|
|
||||||
note: maybe(() => customer.note, "")
|
|
||||||
}}
|
|
||||||
onSubmit={onSubmit}
|
|
||||||
confirmLeave
|
|
||||||
>
|
|
||||||
{({ change, data, hasChanged, submit }) => (
|
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.customers)}
|
{intl.formatMessage(sectionNames.customers)}
|
||||||
|
@ -97,6 +108,8 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
|
||||||
onViewAllOrdersClick={onViewAllOrdersClick}
|
onViewAllOrdersClick={onViewAllOrdersClick}
|
||||||
onRowClick={onRowClick}
|
onRowClick={onRowClick}
|
||||||
/>
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<Metadata data={data} onChange={changeMetadata} />
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<CustomerAddresses
|
<CustomerAddresses
|
||||||
|
@ -116,7 +129,8 @@ const CustomerDetailsPage: React.FC<CustomerDetailsPageProps> = ({
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
)}
|
);
|
||||||
|
}}
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -946,6 +946,8 @@ export const customerList: ListCustomers_customers_edges_node[] = [
|
||||||
];
|
];
|
||||||
export const customer: CustomerDetails_user & CustomerAddresses_user = {
|
export const customer: CustomerDetails_user & CustomerAddresses_user = {
|
||||||
__typename: "User",
|
__typename: "User",
|
||||||
|
metadata: [],
|
||||||
|
privateMetadata: [],
|
||||||
addresses: [
|
addresses: [
|
||||||
{
|
{
|
||||||
__typename: "Address",
|
__typename: "Address",
|
||||||
|
|
|
@ -8,6 +8,18 @@ import { PaymentChargeStatusEnum } from "./../../types/globalTypes";
|
||||||
// GraphQL query operation: CustomerDetails
|
// GraphQL query operation: CustomerDetails
|
||||||
// ====================================================
|
// ====================================================
|
||||||
|
|
||||||
|
export interface CustomerDetails_user_metadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CustomerDetails_user_privateMetadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface CustomerDetails_user_defaultShippingAddress_country {
|
export interface CustomerDetails_user_defaultShippingAddress_country {
|
||||||
__typename: "CountryDisplay";
|
__typename: "CountryDisplay";
|
||||||
code: string;
|
code: string;
|
||||||
|
@ -104,6 +116,8 @@ export interface CustomerDetails_user {
|
||||||
email: string;
|
email: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
metadata: (CustomerDetails_user_metadata | null)[];
|
||||||
|
privateMetadata: (CustomerDetails_user_privateMetadata | null)[];
|
||||||
dateJoined: any;
|
dateJoined: any;
|
||||||
lastLogin: any | null;
|
lastLogin: any | null;
|
||||||
defaultShippingAddress: CustomerDetails_user_defaultShippingAddress | null;
|
defaultShippingAddress: CustomerDetails_user_defaultShippingAddress | null;
|
||||||
|
|
|
@ -14,6 +14,18 @@ export interface UpdateCustomer_customerUpdate_errors {
|
||||||
field: string | null;
|
field: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UpdateCustomer_customerUpdate_user_metadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateCustomer_customerUpdate_user_privateMetadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface UpdateCustomer_customerUpdate_user_defaultShippingAddress_country {
|
export interface UpdateCustomer_customerUpdate_user_defaultShippingAddress_country {
|
||||||
__typename: "CountryDisplay";
|
__typename: "CountryDisplay";
|
||||||
code: string;
|
code: string;
|
||||||
|
@ -64,6 +76,8 @@ export interface UpdateCustomer_customerUpdate_user {
|
||||||
email: string;
|
email: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
metadata: (UpdateCustomer_customerUpdate_user_metadata | null)[];
|
||||||
|
privateMetadata: (UpdateCustomer_customerUpdate_user_privateMetadata | null)[];
|
||||||
dateJoined: any;
|
dateJoined: any;
|
||||||
lastLogin: any | null;
|
lastLogin: any | null;
|
||||||
defaultShippingAddress: UpdateCustomer_customerUpdate_user_defaultShippingAddress | null;
|
defaultShippingAddress: UpdateCustomer_customerUpdate_user_defaultShippingAddress | null;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandl
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import { maybe } from "../../misc";
|
|
||||||
import CustomerAddressDialog from "../components/CustomerAddressDialog";
|
import CustomerAddressDialog from "../components/CustomerAddressDialog";
|
||||||
import CustomerAddressListPage from "../components/CustomerAddressListPage";
|
import CustomerAddressListPage from "../components/CustomerAddressListPage";
|
||||||
import {
|
import {
|
||||||
|
@ -102,23 +101,20 @@ const CustomerAddresses: React.FC<CustomerAddressesProps> = ({
|
||||||
{(removeCustomerAddress, removeCustomerAddressOpts) => (
|
{(removeCustomerAddress, removeCustomerAddressOpts) => (
|
||||||
<TypedCustomerAddressesQuery variables={{ id }}>
|
<TypedCustomerAddressesQuery variables={{ id }}>
|
||||||
{customerData => {
|
{customerData => {
|
||||||
const countryChoices = maybe(
|
const countryChoices =
|
||||||
() =>
|
shop?.countries?.map(country => ({
|
||||||
shop.countries.map(country => ({
|
|
||||||
code: country.code,
|
code: country.code,
|
||||||
label: country.country
|
label: country.country
|
||||||
})),
|
})) || [];
|
||||||
[]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WindowTitle
|
<WindowTitle
|
||||||
title={maybe(() => customerData.data.user.email)}
|
title={customerData?.data?.user.email}
|
||||||
/>
|
/>
|
||||||
<CustomerAddressListPage
|
<CustomerAddressListPage
|
||||||
customer={maybe(() => customerData.data.user)}
|
customer={customerData?.data?.user}
|
||||||
disabled={customerData.loading}
|
disabled={customerData?.loading}
|
||||||
onAdd={() => openModal("add")}
|
onAdd={() => openModal("add")}
|
||||||
onBack={() => navigate(customerUrl(id))}
|
onBack={() => navigate(customerUrl(id))}
|
||||||
onEdit={id =>
|
onEdit={id =>
|
||||||
|
@ -143,12 +139,10 @@ const CustomerAddresses: React.FC<CustomerAddressesProps> = ({
|
||||||
createCustomerAddressOpts.status
|
createCustomerAddressOpts.status
|
||||||
}
|
}
|
||||||
countries={countryChoices}
|
countries={countryChoices}
|
||||||
errors={maybe(
|
errors={
|
||||||
() =>
|
createCustomerAddressOpts?.data?.addressCreate
|
||||||
createCustomerAddressOpts.data.addressCreate
|
.errors || []
|
||||||
.errors,
|
}
|
||||||
[]
|
|
||||||
)}
|
|
||||||
open={params.action === "add"}
|
open={params.action === "add"}
|
||||||
variant="create"
|
variant="create"
|
||||||
onClose={closeModal}
|
onClose={closeModal}
|
||||||
|
@ -162,21 +156,17 @@ const CustomerAddresses: React.FC<CustomerAddressesProps> = ({
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<CustomerAddressDialog
|
<CustomerAddressDialog
|
||||||
address={maybe(() =>
|
address={customerData?.data?.user.addresses.find(
|
||||||
customerData.data.user.addresses.find(
|
|
||||||
addr => addr.id === params.id
|
addr => addr.id === params.id
|
||||||
)
|
|
||||||
)}
|
)}
|
||||||
confirmButtonState={
|
confirmButtonState={
|
||||||
updateCustomerAddressOpts.status
|
updateCustomerAddressOpts.status
|
||||||
}
|
}
|
||||||
countries={countryChoices}
|
countries={countryChoices}
|
||||||
errors={maybe(
|
errors={
|
||||||
() =>
|
updateCustomerAddressOpts?.data?.addressUpdate
|
||||||
updateCustomerAddressOpts.data.addressUpdate
|
.errors || []
|
||||||
.errors,
|
}
|
||||||
[]
|
|
||||||
)}
|
|
||||||
open={params.action === "edit"}
|
open={params.action === "edit"}
|
||||||
variant="edit"
|
variant="edit"
|
||||||
onClose={closeModal}
|
onClose={closeModal}
|
||||||
|
|
|
@ -5,6 +5,11 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
|
||||||
import useNavigator from "@saleor/hooks/useNavigator";
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
import useNotifier from "@saleor/hooks/useNotifier";
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
||||||
|
import {
|
||||||
|
useMetadataUpdate,
|
||||||
|
usePrivateMetadataUpdate
|
||||||
|
} from "@saleor/utils/metadata/updateMetadata";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
@ -78,7 +83,10 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
|
||||||
return <NotFoundPage onBack={handleBack} />;
|
return <NotFoundPage onBack={handleBack} />;
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSubmit = async (
|
const [updateMetadata] = useMetadataUpdate({});
|
||||||
|
const [updatePrivateMetadata] = usePrivateMetadataUpdate({});
|
||||||
|
|
||||||
|
const updateData = async (
|
||||||
data: CustomerDetailsPageFormData
|
data: CustomerDetailsPageFormData
|
||||||
) => {
|
) => {
|
||||||
const result = await updateCustomer({
|
const result = await updateCustomer({
|
||||||
|
@ -97,6 +105,13 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
|
||||||
return result.data.customerUpdate.errors;
|
return result.data.customerUpdate.errors;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleSubmit = createMetadataUpdateHandler(
|
||||||
|
user,
|
||||||
|
updateData,
|
||||||
|
variables => updateMetadata({ variables }),
|
||||||
|
variables => updatePrivateMetadata({ variables })
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<WindowTitle
|
<WindowTitle
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import gql from "graphql-tag";
|
import gql from "graphql-tag";
|
||||||
|
|
||||||
import { fragmentAddress } from "./address";
|
import { fragmentAddress } from "./address";
|
||||||
|
import { metadataFragment } from "./metadata";
|
||||||
|
|
||||||
export const customerFragment = gql`
|
export const customerFragment = gql`
|
||||||
fragment CustomerFragment on User {
|
fragment CustomerFragment on User {
|
||||||
|
@ -12,10 +13,12 @@ export const customerFragment = gql`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const customerDetailsFragment = gql`
|
export const customerDetailsFragment = gql`
|
||||||
|
${metadataFragment}
|
||||||
${customerFragment}
|
${customerFragment}
|
||||||
${fragmentAddress}
|
${fragmentAddress}
|
||||||
fragment CustomerDetailsFragment on User {
|
fragment CustomerDetailsFragment on User {
|
||||||
...CustomerFragment
|
...CustomerFragment
|
||||||
|
...MetadataFragment
|
||||||
dateJoined
|
dateJoined
|
||||||
lastLogin
|
lastLogin
|
||||||
defaultShippingAddress {
|
defaultShippingAddress {
|
||||||
|
|
|
@ -13,6 +13,7 @@ export const shippingZoneFragment = gql`
|
||||||
country
|
country
|
||||||
}
|
}
|
||||||
name
|
name
|
||||||
|
description
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,18 @@
|
||||||
// GraphQL fragment: CustomerDetailsFragment
|
// GraphQL fragment: CustomerDetailsFragment
|
||||||
// ====================================================
|
// ====================================================
|
||||||
|
|
||||||
|
export interface CustomerDetailsFragment_metadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CustomerDetailsFragment_privateMetadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface CustomerDetailsFragment_defaultShippingAddress_country {
|
export interface CustomerDetailsFragment_defaultShippingAddress_country {
|
||||||
__typename: "CountryDisplay";
|
__typename: "CountryDisplay";
|
||||||
code: string;
|
code: string;
|
||||||
|
@ -56,6 +68,8 @@ export interface CustomerDetailsFragment {
|
||||||
email: string;
|
email: string;
|
||||||
firstName: string;
|
firstName: string;
|
||||||
lastName: string;
|
lastName: string;
|
||||||
|
metadata: (CustomerDetailsFragment_metadata | null)[];
|
||||||
|
privateMetadata: (CustomerDetailsFragment_privateMetadata | null)[];
|
||||||
dateJoined: any;
|
dateJoined: any;
|
||||||
lastLogin: any | null;
|
lastLogin: any | null;
|
||||||
defaultShippingAddress: CustomerDetailsFragment_defaultShippingAddress | null;
|
defaultShippingAddress: CustomerDetailsFragment_defaultShippingAddress | null;
|
||||||
|
|
|
@ -117,6 +117,7 @@ export interface ShippingZoneDetailsFragment {
|
||||||
id: string;
|
id: string;
|
||||||
countries: (ShippingZoneDetailsFragment_countries | null)[] | null;
|
countries: (ShippingZoneDetailsFragment_countries | null)[] | null;
|
||||||
name: string;
|
name: string;
|
||||||
|
description: string | null;
|
||||||
default: boolean;
|
default: boolean;
|
||||||
shippingMethods: (ShippingZoneDetailsFragment_shippingMethods | null)[] | null;
|
shippingMethods: (ShippingZoneDetailsFragment_shippingMethods | null)[] | null;
|
||||||
warehouses: (ShippingZoneDetailsFragment_warehouses | null)[] | null;
|
warehouses: (ShippingZoneDetailsFragment_warehouses | null)[] | null;
|
||||||
|
|
|
@ -31,4 +31,5 @@ export interface ShippingZoneFragment {
|
||||||
id: string;
|
id: string;
|
||||||
countries: (ShippingZoneFragment_countries | null)[] | null;
|
countries: (ShippingZoneFragment_countries | null)[] | null;
|
||||||
name: string;
|
name: string;
|
||||||
|
description: string | null;
|
||||||
}
|
}
|
||||||
|
|
22
src/misc.ts
22
src/misc.ts
|
@ -197,17 +197,17 @@ export const transformOrderStatus = (
|
||||||
};
|
};
|
||||||
|
|
||||||
export const transformAddressToForm = (data: AddressType) => ({
|
export const transformAddressToForm = (data: AddressType) => ({
|
||||||
city: maybe(() => data.city, ""),
|
city: data?.city || "",
|
||||||
cityArea: maybe(() => data.cityArea, ""),
|
cityArea: data?.cityArea || "",
|
||||||
companyName: maybe(() => data.companyName, ""),
|
companyName: data?.companyName || "",
|
||||||
country: maybe(() => data.country.code, ""),
|
country: data?.country?.code || "",
|
||||||
countryArea: maybe(() => data.countryArea, ""),
|
countryArea: data?.countryArea || "",
|
||||||
firstName: maybe(() => data.firstName, ""),
|
firstName: data?.firstName || "",
|
||||||
lastName: maybe(() => data.lastName, ""),
|
lastName: data?.lastName || "",
|
||||||
phone: maybe(() => data.phone, ""),
|
phone: data?.phone || "",
|
||||||
postalCode: maybe(() => data.postalCode, ""),
|
postalCode: data?.postalCode || "",
|
||||||
streetAddress1: maybe(() => data.streetAddress1, ""),
|
streetAddress1: data?.streetAddress1 || "",
|
||||||
streetAddress2: maybe(() => data.streetAddress2, "")
|
streetAddress2: data?.streetAddress2 || ""
|
||||||
});
|
});
|
||||||
|
|
||||||
export function maybe<T>(exp: () => T): T | undefined;
|
export function maybe<T>(exp: () => T): T | undefined;
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
import Card from "@material-ui/core/Card";
|
||||||
|
import CardContent from "@material-ui/core/CardContent";
|
||||||
|
import TextField from "@material-ui/core/TextField";
|
||||||
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment";
|
||||||
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { getFormErrors } from "@saleor/utils/errors";
|
||||||
|
import getShippingErrorMessage from "@saleor/utils/errors/shipping";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
export interface ShippingRateInfoProps {
|
||||||
|
data: Record<"name", string>;
|
||||||
|
disabled: boolean;
|
||||||
|
errors: ShippingErrorFragment[];
|
||||||
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ShippingRateInfo: React.FC<ShippingRateInfoProps> = ({
|
||||||
|
data,
|
||||||
|
disabled,
|
||||||
|
errors,
|
||||||
|
onChange
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
const formErrors = getFormErrors(["name"], errors);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card>
|
||||||
|
<CardTitle
|
||||||
|
title={intl.formatMessage(commonMessages.generalInformations)}
|
||||||
|
/>
|
||||||
|
<CardContent>
|
||||||
|
<TextField
|
||||||
|
disabled={disabled}
|
||||||
|
error={!!formErrors.name}
|
||||||
|
fullWidth
|
||||||
|
helperText={getShippingErrorMessage(formErrors.name, intl)}
|
||||||
|
label={intl.formatMessage({
|
||||||
|
defaultMessage: "Shipping rate name"
|
||||||
|
})}
|
||||||
|
name="name"
|
||||||
|
value={data.name}
|
||||||
|
onChange={onChange}
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
ShippingRateInfo.displayName = "ShippingRateInfo";
|
||||||
|
export default ShippingRateInfo;
|
2
src/shipping/components/ShippingRateInfo/index.ts
Normal file
2
src/shipping/components/ShippingRateInfo/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./ShippingRateInfo";
|
||||||
|
export * from "./ShippingRateInfo";
|
|
@ -11,7 +11,7 @@ import { CountryFragment } from "@saleor/fragments/types/CountryFragment";
|
||||||
import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment";
|
import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment";
|
||||||
import { sectionNames } from "@saleor/intl";
|
import { sectionNames } from "@saleor/intl";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { defineMessages, useIntl } from "react-intl";
|
||||||
|
|
||||||
import ShippingZoneCountriesAssignDialog from "../ShippingZoneCountriesAssignDialog";
|
import ShippingZoneCountriesAssignDialog from "../ShippingZoneCountriesAssignDialog";
|
||||||
import ShippingZoneInfo from "../ShippingZoneInfo";
|
import ShippingZoneInfo from "../ShippingZoneInfo";
|
||||||
|
@ -19,9 +19,29 @@ import ShippingZoneInfo from "../ShippingZoneInfo";
|
||||||
export interface FormData {
|
export interface FormData {
|
||||||
countries: string[];
|
countries: string[];
|
||||||
default: boolean;
|
default: boolean;
|
||||||
|
description: string;
|
||||||
name: string;
|
name: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
countries: {
|
||||||
|
defaultMessage: "Countries",
|
||||||
|
description: "country list header"
|
||||||
|
},
|
||||||
|
createZone: {
|
||||||
|
defaultMessage: "Create New Shipping Zone",
|
||||||
|
description: "section header"
|
||||||
|
},
|
||||||
|
defaultZone: {
|
||||||
|
defaultMessage:
|
||||||
|
"This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones"
|
||||||
|
},
|
||||||
|
noCountriesAssigned: {
|
||||||
|
defaultMessage:
|
||||||
|
"Currently, there are no countries assigned to this shipping zone"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export interface ShippingZoneCreatePageProps {
|
export interface ShippingZoneCreatePageProps {
|
||||||
countries: CountryFragment[];
|
countries: CountryFragment[];
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
|
@ -46,6 +66,7 @@ const ShippingZoneCreatePage: React.FC<ShippingZoneCreatePageProps> = ({
|
||||||
const initialForm: FormData = {
|
const initialForm: FormData = {
|
||||||
countries: [],
|
countries: [],
|
||||||
default: false,
|
default: false,
|
||||||
|
description: "",
|
||||||
name: ""
|
name: ""
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -57,12 +78,7 @@ const ShippingZoneCreatePage: React.FC<ShippingZoneCreatePageProps> = ({
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
{intl.formatMessage(sectionNames.shipping)}
|
{intl.formatMessage(sectionNames.shipping)}
|
||||||
</AppHeader>
|
</AppHeader>
|
||||||
<PageHeader
|
<PageHeader title={intl.formatMessage(messages.createZone)} />
|
||||||
title={intl.formatMessage({
|
|
||||||
defaultMessage: "Create New Shipping Zone",
|
|
||||||
description: "header"
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
<Grid>
|
<Grid>
|
||||||
<div>
|
<div>
|
||||||
<ShippingZoneInfo
|
<ShippingZoneInfo
|
||||||
|
@ -79,14 +95,8 @@ const ShippingZoneCreatePage: React.FC<ShippingZoneCreatePageProps> = ({
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
emptyText={
|
emptyText={
|
||||||
data.default
|
data.default
|
||||||
? intl.formatMessage({
|
? intl.formatMessage(messages.defaultZone)
|
||||||
defaultMessage:
|
: intl.formatMessage(messages.noCountriesAssigned)
|
||||||
"This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones"
|
|
||||||
})
|
|
||||||
: intl.formatMessage({
|
|
||||||
defaultMessage:
|
|
||||||
"Currently, there are no countries assigned to this shipping zone"
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
onCountryAssign={toggleModal}
|
onCountryAssign={toggleModal}
|
||||||
onCountryUnassign={countryCode =>
|
onCountryUnassign={countryCode =>
|
||||||
|
@ -99,9 +109,7 @@ const ShippingZoneCreatePage: React.FC<ShippingZoneCreatePageProps> = ({
|
||||||
}
|
}
|
||||||
} as any)
|
} as any)
|
||||||
}
|
}
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage(messages.countries)}
|
||||||
defaultMessage: "Countries"
|
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
|
@ -22,7 +22,7 @@ import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAu
|
||||||
import { mapMetadataItemToInput } from "@saleor/utils/maps";
|
import { mapMetadataItemToInput } from "@saleor/utils/maps";
|
||||||
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { FormattedMessage, useIntl } from "react-intl";
|
import { defineMessages, FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
import { getStringOrPlaceholder } from "../../../misc";
|
import { getStringOrPlaceholder } from "../../../misc";
|
||||||
import { ChannelProps, FetchMoreProps, SearchProps } from "../../../types";
|
import { ChannelProps, FetchMoreProps, SearchProps } from "../../../types";
|
||||||
|
@ -33,9 +33,29 @@ import ShippingZoneWarehouses from "../ShippingZoneWarehouses";
|
||||||
|
|
||||||
export interface FormData extends MetadataFormData {
|
export interface FormData extends MetadataFormData {
|
||||||
name: string;
|
name: string;
|
||||||
|
description: string;
|
||||||
warehouses: string[];
|
warehouses: string[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const messages = defineMessages({
|
||||||
|
countries: {
|
||||||
|
defaultMessage: "Countries",
|
||||||
|
description: "country list header"
|
||||||
|
},
|
||||||
|
defaultZone: {
|
||||||
|
defaultMessage:
|
||||||
|
"This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones"
|
||||||
|
},
|
||||||
|
noCountriesAssigned: {
|
||||||
|
defaultMessage:
|
||||||
|
"Currently, there are no countries assigned to this shipping zone"
|
||||||
|
},
|
||||||
|
shipping: {
|
||||||
|
defaultMessage: "Shipping",
|
||||||
|
description: "shipping section header"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
export interface ShippingZoneDetailsPageProps
|
export interface ShippingZoneDetailsPageProps
|
||||||
extends FetchMoreProps,
|
extends FetchMoreProps,
|
||||||
SearchProps,
|
SearchProps,
|
||||||
|
@ -93,6 +113,7 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
const initialForm: FormData = {
|
const initialForm: FormData = {
|
||||||
|
description: shippingZone?.description || "",
|
||||||
metadata: shippingZone?.metadata.map(mapMetadataItemToInput),
|
metadata: shippingZone?.metadata.map(mapMetadataItemToInput),
|
||||||
name: shippingZone?.name || "",
|
name: shippingZone?.name || "",
|
||||||
privateMetadata: shippingZone?.privateMetadata.map(mapMetadataItemToInput),
|
privateMetadata: shippingZone?.privateMetadata.map(mapMetadataItemToInput),
|
||||||
|
@ -128,7 +149,7 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<AppHeader onBack={onBack}>
|
<AppHeader onBack={onBack}>
|
||||||
<FormattedMessage defaultMessage="Shipping" />
|
<FormattedMessage {...messages.shipping} />
|
||||||
</AppHeader>
|
</AppHeader>
|
||||||
<PageHeader title={shippingZone?.name} />
|
<PageHeader title={shippingZone?.name} />
|
||||||
<Grid>
|
<Grid>
|
||||||
|
@ -147,20 +168,12 @@ const ShippingZoneDetailsPage: React.FC<ShippingZoneDetailsPageProps> = ({
|
||||||
shippingZone?.default === undefined
|
shippingZone?.default === undefined
|
||||||
? undefined
|
? undefined
|
||||||
: shippingZone.default
|
: shippingZone.default
|
||||||
? intl.formatMessage({
|
? intl.formatMessage(messages.defaultZone)
|
||||||
defaultMessage:
|
: intl.formatMessage(messages.noCountriesAssigned)
|
||||||
"This is default shipping zone, which means that it covers all of the countries which are not assigned to other shipping zones"
|
|
||||||
})
|
|
||||||
: intl.formatMessage({
|
|
||||||
defaultMessage:
|
|
||||||
"Currently, there are no countries assigned to this shipping zone"
|
|
||||||
})
|
|
||||||
)}
|
)}
|
||||||
onCountryAssign={onCountryAdd}
|
onCountryAssign={onCountryAdd}
|
||||||
onCountryUnassign={onCountryRemove}
|
onCountryUnassign={onCountryRemove}
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage(messages.countries)}
|
||||||
defaultMessage: "Countries"
|
|
||||||
})}
|
|
||||||
/>
|
/>
|
||||||
<CardSpacer />
|
<CardSpacer />
|
||||||
<ShippingZoneRates
|
<ShippingZoneRates
|
||||||
|
|
|
@ -1,21 +1,40 @@
|
||||||
import Card from "@material-ui/core/Card";
|
import Card from "@material-ui/core/Card";
|
||||||
import CardContent from "@material-ui/core/CardContent";
|
import CardContent from "@material-ui/core/CardContent";
|
||||||
|
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||||
import TextField from "@material-ui/core/TextField";
|
import TextField from "@material-ui/core/TextField";
|
||||||
|
import CardSpacer from "@saleor/components/CardSpacer";
|
||||||
import CardTitle from "@saleor/components/CardTitle";
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment";
|
import { ShippingErrorFragment } from "@saleor/fragments/types/ShippingErrorFragment";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import { getFormErrors } from "@saleor/utils/errors";
|
import { getFormErrors } from "@saleor/utils/errors";
|
||||||
import getShippingErrorMessage from "@saleor/utils/errors/shipping";
|
import getShippingErrorMessage from "@saleor/utils/errors/shipping";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useIntl } from "react-intl";
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
export interface ShippingZoneInfoProps {
|
export interface ShippingZoneInfoProps {
|
||||||
data: Record<"name", string>;
|
data: Record<"name" | "description", string>;
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
errors: ShippingErrorFragment[];
|
errors: ShippingErrorFragment[];
|
||||||
onChange: (event: React.ChangeEvent<any>) => void;
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
{
|
||||||
|
label: {
|
||||||
|
flex: 1
|
||||||
|
},
|
||||||
|
labelContainer: {
|
||||||
|
"& span": {
|
||||||
|
paddingRight: 30
|
||||||
|
},
|
||||||
|
display: "flex"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ name: "ShippingZoneCreatePage" }
|
||||||
|
);
|
||||||
|
|
||||||
|
const MAX_DESCRIPTION_LENGTH = 300;
|
||||||
|
|
||||||
const ShippingZoneInfo: React.FC<ShippingZoneInfoProps> = ({
|
const ShippingZoneInfo: React.FC<ShippingZoneInfoProps> = ({
|
||||||
data,
|
data,
|
||||||
disabled,
|
disabled,
|
||||||
|
@ -23,6 +42,7 @@ const ShippingZoneInfo: React.FC<ShippingZoneInfoProps> = ({
|
||||||
onChange
|
onChange
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const classes = useStyles({});
|
||||||
|
|
||||||
const formErrors = getFormErrors(["name"], errors);
|
const formErrors = getFormErrors(["name"], errors);
|
||||||
|
|
||||||
|
@ -38,12 +58,51 @@ const ShippingZoneInfo: React.FC<ShippingZoneInfoProps> = ({
|
||||||
fullWidth
|
fullWidth
|
||||||
helperText={getShippingErrorMessage(formErrors.name, intl)}
|
helperText={getShippingErrorMessage(formErrors.name, intl)}
|
||||||
label={intl.formatMessage({
|
label={intl.formatMessage({
|
||||||
defaultMessage: "Shipping rate name"
|
defaultMessage: "Shipping zone name"
|
||||||
})}
|
})}
|
||||||
name="name"
|
name="name"
|
||||||
value={data.name}
|
value={data.name}
|
||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
/>
|
/>
|
||||||
|
<CardSpacer />
|
||||||
|
<TextField
|
||||||
|
error={data.description.length > MAX_DESCRIPTION_LENGTH}
|
||||||
|
name={"description"}
|
||||||
|
label={
|
||||||
|
<div className={classes.labelContainer}>
|
||||||
|
<div className={classes.label}>
|
||||||
|
<FormattedMessage defaultMessage="Description" />
|
||||||
|
</div>
|
||||||
|
{data.description?.length > 0 && (
|
||||||
|
<span>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="{numberOfCharacters} of {maxCharacters} characters"
|
||||||
|
description="character limit"
|
||||||
|
values={{
|
||||||
|
maxCharacters: MAX_DESCRIPTION_LENGTH,
|
||||||
|
numberOfCharacters: data.description.length
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
InputProps={{
|
||||||
|
inputProps: {
|
||||||
|
maxLength: MAX_DESCRIPTION_LENGTH
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
value={data.description}
|
||||||
|
onChange={onChange}
|
||||||
|
disabled={disabled}
|
||||||
|
fullWidth
|
||||||
|
multiline
|
||||||
|
placeholder={intl.formatMessage({
|
||||||
|
defaultMessage: "Description of a shipping zone.",
|
||||||
|
description: "field placeholder"
|
||||||
|
})}
|
||||||
|
rows={10}
|
||||||
|
/>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
@ -37,15 +37,15 @@ const useStyles = makeStyles(
|
||||||
paddingRight: 24,
|
paddingRight: 24,
|
||||||
width: ICONBUTTON_SIZE + theme.spacing(0.5)
|
width: ICONBUTTON_SIZE + theme.spacing(0.5)
|
||||||
},
|
},
|
||||||
|
buttonColumn: {
|
||||||
|
padding: "4px 0",
|
||||||
|
width: "62px"
|
||||||
|
},
|
||||||
nameColumn: {
|
nameColumn: {
|
||||||
width: "auto"
|
width: "auto"
|
||||||
},
|
},
|
||||||
valueColumn: {
|
valueColumn: {
|
||||||
width: "auto"
|
width: "auto"
|
||||||
},
|
|
||||||
buttonColumn: {
|
|
||||||
width: "62px",
|
|
||||||
padding: "4px 0"
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
{ name: "ShippingZoneRates" }
|
{ name: "ShippingZoneRates" }
|
||||||
|
|
|
@ -15,7 +15,7 @@ import { validatePrice } from "@saleor/products/utils/validation";
|
||||||
import OrderValue from "@saleor/shipping/components/OrderValue";
|
import OrderValue from "@saleor/shipping/components/OrderValue";
|
||||||
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
||||||
import PricingCard from "@saleor/shipping/components/PricingCard";
|
import PricingCard from "@saleor/shipping/components/PricingCard";
|
||||||
import ShippingZoneInfo from "@saleor/shipping/components/ShippingZoneInfo";
|
import ShippingRateInfo from "@saleor/shipping/components/ShippingRateInfo";
|
||||||
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
||||||
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
import { ShippingMethodTypeEnum } from "@saleor/types/globalTypes";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
@ -116,7 +116,7 @@ export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePagePr
|
||||||
/>
|
/>
|
||||||
<Grid>
|
<Grid>
|
||||||
<div>
|
<div>
|
||||||
<ShippingZoneInfo
|
<ShippingRateInfo
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
|
|
|
@ -17,7 +17,7 @@ import OrderValue from "@saleor/shipping/components/OrderValue";
|
||||||
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
||||||
import PricingCard from "@saleor/shipping/components/PricingCard";
|
import PricingCard from "@saleor/shipping/components/PricingCard";
|
||||||
import ShippingMethodProducts from "@saleor/shipping/components/ShippingMethodProducts";
|
import ShippingMethodProducts from "@saleor/shipping/components/ShippingMethodProducts";
|
||||||
import ShippingZoneInfo from "@saleor/shipping/components/ShippingZoneInfo";
|
import ShippingRateInfo from "@saleor/shipping/components/ShippingRateInfo";
|
||||||
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
||||||
import { ShippingZone_shippingZone_shippingMethods } from "@saleor/shipping/types/ShippingZone";
|
import { ShippingZone_shippingZone_shippingMethods } from "@saleor/shipping/types/ShippingZone";
|
||||||
import { ListActions, ListProps } from "@saleor/types";
|
import { ListActions, ListProps } from "@saleor/types";
|
||||||
|
@ -124,7 +124,7 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
||||||
<PageHeader title={rate?.name} />
|
<PageHeader title={rate?.name} />
|
||||||
<Grid>
|
<Grid>
|
||||||
<div>
|
<div>
|
||||||
<ShippingZoneInfo
|
<ShippingRateInfo
|
||||||
data={data}
|
data={data}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
errors={errors}
|
errors={errors}
|
||||||
|
|
|
@ -102,10 +102,9 @@ const ShippingZoneZipCodes: React.FC<ShippingZoneZipCodesProps> = ({
|
||||||
alignTop
|
alignTop
|
||||||
choices={[
|
choices={[
|
||||||
{
|
{
|
||||||
disabled: true,
|
|
||||||
label: (
|
label: (
|
||||||
<div className={classes.option}>
|
<div className={classes.option}>
|
||||||
<Typography color="textSecondary" variant="body1">
|
<Typography variant="body1">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Exclude postal codes"
|
defaultMessage="Exclude postal codes"
|
||||||
description="action"
|
description="action"
|
||||||
|
@ -119,9 +118,10 @@ const ShippingZoneZipCodes: React.FC<ShippingZoneZipCodesProps> = ({
|
||||||
value: ZipCodeInclusion.Exclude
|
value: ZipCodeInclusion.Exclude
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
disabled: true,
|
||||||
label: (
|
label: (
|
||||||
<div className={classes.option}>
|
<div className={classes.option}>
|
||||||
<Typography variant="body1">
|
<Typography color="textSecondary" variant="body1">
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Include postal codes"
|
defaultMessage="Include postal codes"
|
||||||
description="action"
|
description="action"
|
||||||
|
|
|
@ -264,6 +264,7 @@ export const shippingZones: ShippingZoneFragment[] = [
|
||||||
country: "Wielka Brytania"
|
country: "Wielka Brytania"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
description: "Shipping zone description",
|
||||||
id: "U2hpcHBpbmdab25lOjE=",
|
id: "U2hpcHBpbmdab25lOjE=",
|
||||||
metadata: [],
|
metadata: [],
|
||||||
name: "Europe",
|
name: "Europe",
|
||||||
|
@ -418,6 +419,7 @@ export const shippingZones: ShippingZoneFragment[] = [
|
||||||
country: "Wallis i Futuna"
|
country: "Wallis i Futuna"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
description: "Shipping zone description",
|
||||||
id: "U2hpcHBpbmdab25lOjI=",
|
id: "U2hpcHBpbmdab25lOjI=",
|
||||||
metadata: [],
|
metadata: [],
|
||||||
name: "Oceania",
|
name: "Oceania",
|
||||||
|
@ -425,7 +427,6 @@ export const shippingZones: ShippingZoneFragment[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
__typename: "ShippingZone",
|
__typename: "ShippingZone",
|
||||||
|
|
||||||
countries: [
|
countries: [
|
||||||
{
|
{
|
||||||
__typename: "CountryDisplay",
|
__typename: "CountryDisplay",
|
||||||
|
@ -683,6 +684,7 @@ export const shippingZones: ShippingZoneFragment[] = [
|
||||||
country: "Jemen"
|
country: "Jemen"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
description: "Shipping zone description",
|
||||||
id: "U2hpcHBpbmdab25lOjM=",
|
id: "U2hpcHBpbmdab25lOjM=",
|
||||||
metadata: [],
|
metadata: [],
|
||||||
name: "Asia",
|
name: "Asia",
|
||||||
|
@ -690,7 +692,6 @@ export const shippingZones: ShippingZoneFragment[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
__typename: "ShippingZone",
|
__typename: "ShippingZone",
|
||||||
|
|
||||||
countries: [
|
countries: [
|
||||||
{
|
{
|
||||||
__typename: "CountryDisplay",
|
__typename: "CountryDisplay",
|
||||||
|
@ -978,6 +979,7 @@ export const shippingZones: ShippingZoneFragment[] = [
|
||||||
country: "Wyspy Dziewicze Stanów Zjednoczonych"
|
country: "Wyspy Dziewicze Stanów Zjednoczonych"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
description: "Shipping zone description",
|
||||||
id: "U2hpcHBpbmdab25lOjQ=",
|
id: "U2hpcHBpbmdab25lOjQ=",
|
||||||
metadata: [],
|
metadata: [],
|
||||||
name: "Americas",
|
name: "Americas",
|
||||||
|
@ -985,7 +987,6 @@ export const shippingZones: ShippingZoneFragment[] = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
__typename: "ShippingZone",
|
__typename: "ShippingZone",
|
||||||
|
|
||||||
countries: [
|
countries: [
|
||||||
{
|
{
|
||||||
__typename: "CountryDisplay",
|
__typename: "CountryDisplay",
|
||||||
|
@ -1289,6 +1290,7 @@ export const shippingZones: ShippingZoneFragment[] = [
|
||||||
country: "Zimbabwe"
|
country: "Zimbabwe"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
description: "Shipping zone description",
|
||||||
id: "U2hpcHBpbmdab25lOjU=",
|
id: "U2hpcHBpbmdab25lOjU=",
|
||||||
metadata: [],
|
metadata: [],
|
||||||
name: "Africa",
|
name: "Africa",
|
||||||
|
@ -1556,6 +1558,7 @@ export const shippingZone: ShippingZone_shippingZone = {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
default: false,
|
default: false,
|
||||||
|
description: "Shipping zone description",
|
||||||
id: "U2hpcHBpbmdab25lOjE=",
|
id: "U2hpcHBpbmdab25lOjE=",
|
||||||
metadata: [],
|
metadata: [],
|
||||||
name: "Europe",
|
name: "Europe",
|
||||||
|
|
|
@ -123,6 +123,7 @@ export interface CreateShippingRate_shippingPriceCreate_shippingZone {
|
||||||
id: string;
|
id: string;
|
||||||
countries: (CreateShippingRate_shippingPriceCreate_shippingZone_countries | null)[] | null;
|
countries: (CreateShippingRate_shippingPriceCreate_shippingZone_countries | null)[] | null;
|
||||||
name: string;
|
name: string;
|
||||||
|
description: string | null;
|
||||||
default: boolean;
|
default: boolean;
|
||||||
shippingMethods: (CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods | null)[] | null;
|
shippingMethods: (CreateShippingRate_shippingPriceCreate_shippingZone_shippingMethods | null)[] | null;
|
||||||
warehouses: (CreateShippingRate_shippingPriceCreate_shippingZone_warehouses | null)[] | null;
|
warehouses: (CreateShippingRate_shippingPriceCreate_shippingZone_warehouses | null)[] | null;
|
||||||
|
|
|
@ -123,6 +123,7 @@ export interface DeleteShippingRate_shippingPriceDelete_shippingZone {
|
||||||
id: string;
|
id: string;
|
||||||
countries: (DeleteShippingRate_shippingPriceDelete_shippingZone_countries | null)[] | null;
|
countries: (DeleteShippingRate_shippingPriceDelete_shippingZone_countries | null)[] | null;
|
||||||
name: string;
|
name: string;
|
||||||
|
description: string | null;
|
||||||
default: boolean;
|
default: boolean;
|
||||||
shippingMethods: (DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods | null)[] | null;
|
shippingMethods: (DeleteShippingRate_shippingPriceDelete_shippingZone_shippingMethods | null)[] | null;
|
||||||
warehouses: (DeleteShippingRate_shippingPriceDelete_shippingZone_warehouses | null)[] | null;
|
warehouses: (DeleteShippingRate_shippingPriceDelete_shippingZone_warehouses | null)[] | null;
|
||||||
|
|
|
@ -149,6 +149,7 @@ export interface ShippingZone_shippingZone {
|
||||||
id: string;
|
id: string;
|
||||||
countries: (ShippingZone_shippingZone_countries | null)[] | null;
|
countries: (ShippingZone_shippingZone_countries | null)[] | null;
|
||||||
name: string;
|
name: string;
|
||||||
|
description: string | null;
|
||||||
default: boolean;
|
default: boolean;
|
||||||
shippingMethods: (ShippingZone_shippingZone_shippingMethods | null)[] | null;
|
shippingMethods: (ShippingZone_shippingZone_shippingMethods | null)[] | null;
|
||||||
warehouses: (ShippingZone_shippingZone_warehouses | null)[] | null;
|
warehouses: (ShippingZone_shippingZone_warehouses | null)[] | null;
|
||||||
|
|
|
@ -31,6 +31,7 @@ export interface ShippingZones_shippingZones_edges_node {
|
||||||
id: string;
|
id: string;
|
||||||
countries: (ShippingZones_shippingZones_edges_node_countries | null)[] | null;
|
countries: (ShippingZones_shippingZones_edges_node_countries | null)[] | null;
|
||||||
name: string;
|
name: string;
|
||||||
|
description: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ShippingZones_shippingZones_edges {
|
export interface ShippingZones_shippingZones_edges {
|
||||||
|
|
|
@ -144,6 +144,7 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
|
||||||
id,
|
id,
|
||||||
input: {
|
input: {
|
||||||
addWarehouses: warehouseDiff.added,
|
addWarehouses: warehouseDiff.added,
|
||||||
|
description: submitData.description,
|
||||||
name: submitData.name,
|
name: submitData.name,
|
||||||
removeWarehouses: warehouseDiff.removed
|
removeWarehouses: warehouseDiff.removed
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1710,6 +1710,7 @@ export interface ShippingZipCodeRulesCreateInputRange {
|
||||||
|
|
||||||
export interface ShippingZoneCreateInput {
|
export interface ShippingZoneCreateInput {
|
||||||
name?: string | null;
|
name?: string | null;
|
||||||
|
description?: string | null;
|
||||||
countries?: (string | null)[] | null;
|
countries?: (string | null)[] | null;
|
||||||
default?: boolean | null;
|
default?: boolean | null;
|
||||||
addWarehouses?: (string | null)[] | null;
|
addWarehouses?: (string | null)[] | null;
|
||||||
|
@ -1717,6 +1718,7 @@ export interface ShippingZoneCreateInput {
|
||||||
|
|
||||||
export interface ShippingZoneUpdateInput {
|
export interface ShippingZoneUpdateInput {
|
||||||
name?: string | null;
|
name?: string | null;
|
||||||
|
description?: string | null;
|
||||||
countries?: (string | null)[] | null;
|
countries?: (string | null)[] | null;
|
||||||
default?: boolean | null;
|
default?: boolean | null;
|
||||||
addWarehouses?: (string | null)[] | null;
|
addWarehouses?: (string | null)[] | null;
|
||||||
|
|
Loading…
Reference in a new issue