Update product and page default availability settings (#2165)
* Update product and page default settings * Update product and page test snapshots * Update product create errors handling * Fix preselected publication info of product with variant without any channel listing * Update package lock file * Fix page publication state and its date on page view * Update page tests
This commit is contained in:
parent
e9eba95f90
commit
df55dba571
12 changed files with 268 additions and 214 deletions
|
@ -303,9 +303,6 @@
|
|||
"context": "menu item name",
|
||||
"string": "Name"
|
||||
},
|
||||
"0cVk9I": {
|
||||
"string": "Show in product listings"
|
||||
},
|
||||
"0dPP8O": {
|
||||
"string": "Order #{orderId} was placed"
|
||||
},
|
||||
|
@ -699,6 +696,10 @@
|
|||
"context": "gift card export type label",
|
||||
"string": "gift cards"
|
||||
},
|
||||
"3oQzWR": {
|
||||
"context": "product availability",
|
||||
"string": "Set publication date"
|
||||
},
|
||||
"3psvRS": {
|
||||
"context": "attribute values list: slug column header",
|
||||
"string": "Admin"
|
||||
|
@ -787,6 +788,10 @@
|
|||
"context": "tracking number",
|
||||
"string": "Tracking Number: {trackingNumber}"
|
||||
},
|
||||
"4VOIum": {
|
||||
"context": "product availability",
|
||||
"string": "Enabling this checkbox will remove product from search and category pages. It will be available on collection pages."
|
||||
},
|
||||
"4W/CKn": {
|
||||
"context": "modal button",
|
||||
"string": "Upload URL"
|
||||
|
@ -976,9 +981,6 @@
|
|||
"context": "voucher is active from date",
|
||||
"string": "Starts"
|
||||
},
|
||||
"5ukAFZ": {
|
||||
"string": "Disabling this checkbox will remove product from search and category pages. It will be available on collection pages."
|
||||
},
|
||||
"5x6yT9": {
|
||||
"context": "weight",
|
||||
"string": "{fromValue} {fromUnit} - {toValue} {toUnit}"
|
||||
|
@ -2750,6 +2752,10 @@
|
|||
"context": "input description",
|
||||
"string": "{unitsLeft} units left"
|
||||
},
|
||||
"JmdBa3": {
|
||||
"context": "product availability publish date",
|
||||
"string": "Publish on"
|
||||
},
|
||||
"JnzDrI": {
|
||||
"context": "discount type",
|
||||
"string": "Fixed Amount"
|
||||
|
@ -2769,10 +2775,6 @@
|
|||
"context": "product type is digital or physical",
|
||||
"string": "Type"
|
||||
},
|
||||
"Jt3DwJ": {
|
||||
"context": "publish on date",
|
||||
"string": "Publish on"
|
||||
},
|
||||
"JtZ71e": {
|
||||
"context": "filtering option",
|
||||
"string": "All Warehouses"
|
||||
|
@ -3920,6 +3922,10 @@
|
|||
"TGX4T1": {
|
||||
"string": "Search Engine Preview"
|
||||
},
|
||||
"THpf1b": {
|
||||
"context": "product availability available date",
|
||||
"string": "Set available on"
|
||||
},
|
||||
"TKmub+": {
|
||||
"string": "This field is required"
|
||||
},
|
||||
|
@ -4001,9 +4007,6 @@
|
|||
"U2mOqA": {
|
||||
"string": "No vouchers found"
|
||||
},
|
||||
"U3BQKA": {
|
||||
"string": "Set publication date"
|
||||
},
|
||||
"U5aVd8": {
|
||||
"context": "product",
|
||||
"string": "Shippable"
|
||||
|
@ -4609,10 +4612,6 @@
|
|||
"context": "app extensions subsection",
|
||||
"string": "Apps"
|
||||
},
|
||||
"Y7Vy19": {
|
||||
"context": "available on date",
|
||||
"string": "Set available on"
|
||||
},
|
||||
"Y9lv8z": {
|
||||
"context": "product unavailability",
|
||||
"string": "Unavailable for purchase"
|
||||
|
@ -5848,6 +5847,10 @@
|
|||
"jWna9Q": {
|
||||
"string": "Content Type Name"
|
||||
},
|
||||
"jXf/9p": {
|
||||
"context": "product availability",
|
||||
"string": "Hide in product listings"
|
||||
},
|
||||
"jZbT0O": {
|
||||
"string": "Add search engine title and description to make this page easier to find"
|
||||
},
|
||||
|
|
10
package-lock.json
generated
10
package-lock.json
generated
|
@ -10091,7 +10091,7 @@
|
|||
"buffer-crc32": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
|
||||
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
|
||||
"integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=",
|
||||
"dev": true
|
||||
},
|
||||
"buffer-equal-constant-time": {
|
||||
|
@ -14970,7 +14970,7 @@
|
|||
"pify": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
|
||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
|
@ -15453,7 +15453,7 @@
|
|||
"fd-slicer": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
|
||||
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
|
||||
"integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"pend": "~1.2.0"
|
||||
|
@ -23602,7 +23602,7 @@
|
|||
"ospath": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz",
|
||||
"integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==",
|
||||
"integrity": "sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs=",
|
||||
"dev": true
|
||||
},
|
||||
"p-cancelable": {
|
||||
|
@ -24155,7 +24155,7 @@
|
|||
"pend": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
|
||||
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==",
|
||||
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
|
||||
"dev": true
|
||||
},
|
||||
"performance-now": {
|
||||
|
|
|
@ -181,13 +181,13 @@ export const createChannelsData = (data?: ChannelFragment[]): ChannelData[] =>
|
|||
costPrice: "",
|
||||
currency: channel.currencyCode,
|
||||
id: channel.id,
|
||||
isAvailableForPurchase: false,
|
||||
isAvailableForPurchase: true,
|
||||
variantsIds: [],
|
||||
isPublished: false,
|
||||
isPublished: true,
|
||||
name: channel.name,
|
||||
price: "",
|
||||
publicationDate: null,
|
||||
visibleInListings: false,
|
||||
visibleInListings: true,
|
||||
})) || [];
|
||||
|
||||
export const createChannelsDataWithPrice = (
|
||||
|
@ -196,8 +196,8 @@ export const createChannelsDataWithPrice = (
|
|||
): ChannelData[] => {
|
||||
if (data && productData?.channelListings) {
|
||||
const dataArr = createChannelsData(data);
|
||||
|
||||
const productDataArr = createChannelsDataFromProduct(productData);
|
||||
|
||||
return uniqBy([...productDataArr, ...dataArr], obj => obj.id);
|
||||
}
|
||||
return [];
|
||||
|
@ -294,6 +294,13 @@ export const createChannelsDataFromProduct = (productData?: ProductFragment) =>
|
|||
const variantChannel = productData.variants[0]?.channelListings.find(
|
||||
listing => listing.channel.id === channel.id,
|
||||
);
|
||||
// Comparing explicitly to false because `hasVariants` can be undefined
|
||||
const isSimpleProduct = productData.productType?.hasVariants === false;
|
||||
const haveVariantsChannelListings = productData.variants.some(variant =>
|
||||
variant.channelListings.some(
|
||||
listing => listing.channel.id === channel.id,
|
||||
),
|
||||
);
|
||||
const price = variantChannel?.price;
|
||||
const costPrice = variantChannel?.costPrice;
|
||||
const variantsIds = extractVariantsIdsForChannel(
|
||||
|
@ -302,10 +309,13 @@ export const createChannelsDataFromProduct = (productData?: ProductFragment) =>
|
|||
);
|
||||
const soldUnits = variantChannel?.preorderThreshold?.soldUnits;
|
||||
const preorderThreshold = variantChannel?.preorderThreshold?.quantity;
|
||||
// Published defaults to true if none of variants have set channel listing yet
|
||||
const isProductPublished =
|
||||
!isSimpleProduct && !haveVariantsChannelListings ? true : isPublished;
|
||||
|
||||
return {
|
||||
availableForPurchase,
|
||||
isPublished,
|
||||
isPublished: isProductPublished,
|
||||
publicationDate,
|
||||
variantsIds,
|
||||
costPrice: costPrice?.amount.toString() ?? "",
|
||||
|
|
|
@ -12,6 +12,8 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import { useStyles } from "../styles";
|
||||
import { ChannelOpts, ChannelsAvailabilityError, Messages } from "../types";
|
||||
import { availabilityItemMessages } from "./messages";
|
||||
|
||||
export interface ChannelContentProps {
|
||||
disabled?: boolean;
|
||||
data: ChannelData;
|
||||
|
@ -19,6 +21,7 @@ export interface ChannelContentProps {
|
|||
messages: Messages;
|
||||
onChange: (id: string, data: ChannelOpts) => void;
|
||||
}
|
||||
|
||||
const ChannelContent: React.FC<ChannelContentProps> = ({
|
||||
data,
|
||||
disabled,
|
||||
|
@ -58,20 +61,14 @@ const ChannelContent: React.FC<ChannelContentProps> = ({
|
|||
const todayDateUTC = parsedDate.toISOString().slice(0, 10);
|
||||
|
||||
const visibleMessage = (date: string) =>
|
||||
intl.formatMessage(
|
||||
{
|
||||
id: "UjsI4o",
|
||||
defaultMessage: "since {date}",
|
||||
description: "date",
|
||||
},
|
||||
{
|
||||
intl.formatMessage(availabilityItemMessages.sinceDate, {
|
||||
date: localizeDate(date),
|
||||
},
|
||||
);
|
||||
});
|
||||
const formErrors = getFormErrors(
|
||||
["availableForPurchaseDate", "publicationDate"],
|
||||
errors,
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={classes.container}>
|
||||
<RadioSwitchField
|
||||
|
@ -122,20 +119,13 @@ const ChannelContent: React.FC<ChannelContentProps> = ({
|
|||
className={classes.setPublicationDate}
|
||||
onClick={() => setPublicationDate(!isPublicationDate)}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "U3BQKA",
|
||||
defaultMessage: "Set publication date",
|
||||
})}
|
||||
{intl.formatMessage(availabilityItemMessages.setPublicationDate)}
|
||||
</Typography>
|
||||
{isPublicationDate && (
|
||||
<TextField
|
||||
error={!!formErrors.publicationDate}
|
||||
disabled={disabled}
|
||||
label={intl.formatMessage({
|
||||
id: "Jt3DwJ",
|
||||
defaultMessage: "Publish on",
|
||||
description: "publish on date",
|
||||
})}
|
||||
label={intl.formatMessage(availabilityItemMessages.publishOn)}
|
||||
name={`channel:publicationDate:${id}`}
|
||||
type="date"
|
||||
fullWidth={true}
|
||||
|
@ -213,11 +203,9 @@ const ChannelContent: React.FC<ChannelContentProps> = ({
|
|||
<TextField
|
||||
error={!!formErrors.availableForPurchaseDate}
|
||||
disabled={disabled}
|
||||
label={intl.formatMessage({
|
||||
id: "Y7Vy19",
|
||||
defaultMessage: "Set available on",
|
||||
description: "available on date",
|
||||
})}
|
||||
label={intl.formatMessage(
|
||||
availabilityItemMessages.setAvailableOn,
|
||||
)}
|
||||
name={`channel:availableForPurchase:${id}`}
|
||||
type="date"
|
||||
fullWidth={true}
|
||||
|
@ -252,29 +240,24 @@ const ChannelContent: React.FC<ChannelContentProps> = ({
|
|||
<ControlledCheckbox
|
||||
className={classes.checkbox}
|
||||
name={`channel:visibleInListings:${id}`}
|
||||
checked={visibleInListings}
|
||||
checked={!visibleInListings}
|
||||
disabled={disabled}
|
||||
label={
|
||||
<>
|
||||
<p className={classNames(classes.label, classes.listingLabel)}>
|
||||
{intl.formatMessage({
|
||||
id: "0cVk9I",
|
||||
defaultMessage: "Show in product listings",
|
||||
})}
|
||||
{intl.formatMessage(availabilityItemMessages.hideInListings)}
|
||||
</p>
|
||||
<span className={classes.secondLabel}>
|
||||
{intl.formatMessage({
|
||||
id: "5ukAFZ",
|
||||
defaultMessage:
|
||||
"Disabling this checkbox will remove product from search and category pages. It will be available on collection pages.",
|
||||
})}
|
||||
{intl.formatMessage(
|
||||
availabilityItemMessages.hideInListingsDescription,
|
||||
)}
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
onChange={e =>
|
||||
onChange(id, {
|
||||
...formData,
|
||||
visibleInListings: e.target.value,
|
||||
visibleInListings: !e.target.value,
|
||||
})
|
||||
}
|
||||
/>
|
||||
|
|
35
src/components/ChannelsAvailabilityCard/Channel/messages.ts
Normal file
35
src/components/ChannelsAvailabilityCard/Channel/messages.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { defineMessages } from "react-intl";
|
||||
|
||||
export const availabilityItemMessages = defineMessages({
|
||||
sinceDate: {
|
||||
id: "UjsI4o",
|
||||
defaultMessage: "since {date}",
|
||||
description: "date",
|
||||
},
|
||||
setPublicationDate: {
|
||||
id: "3oQzWR",
|
||||
defaultMessage: "Set publication date",
|
||||
description: "product availability",
|
||||
},
|
||||
publishOn: {
|
||||
id: "JmdBa3",
|
||||
defaultMessage: "Publish on",
|
||||
description: "product availability publish date",
|
||||
},
|
||||
setAvailableOn: {
|
||||
id: "THpf1b",
|
||||
defaultMessage: "Set available on",
|
||||
description: "product availability available date",
|
||||
},
|
||||
hideInListings: {
|
||||
id: "jXf/9p",
|
||||
defaultMessage: "Hide in product listings",
|
||||
description: "product availability",
|
||||
},
|
||||
hideInListingsDescription: {
|
||||
id: "4VOIum",
|
||||
defaultMessage:
|
||||
"Enabling this checkbox will remove product from search and category pages. It will be available on collection pages.",
|
||||
description: "product availability",
|
||||
},
|
||||
});
|
|
@ -15,6 +15,7 @@ import { useIntl } from "react-intl";
|
|||
|
||||
import FormSpacer from "../FormSpacer";
|
||||
import DateVisibilitySelector from "./DateVisibilitySelector";
|
||||
import { visibilityCardMessages } from "./messages";
|
||||
|
||||
const useStyles = makeStyles(
|
||||
theme => ({
|
||||
|
@ -108,16 +109,9 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
|||
isAvailable !== undefined && availableForPurchase !== undefined;
|
||||
|
||||
const visibleMessage = (date: string) =>
|
||||
intl.formatMessage(
|
||||
{
|
||||
id: "UjsI4o",
|
||||
defaultMessage: "since {date}",
|
||||
description: "date",
|
||||
},
|
||||
{
|
||||
intl.formatMessage(visibilityCardMessages.sinceDate, {
|
||||
date: localizeDate(date),
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
const handleRadioFieldChange = (type: keyof DateFields) => (
|
||||
e: ChangeEvent,
|
||||
|
@ -136,13 +130,7 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
|||
|
||||
return (
|
||||
<Card>
|
||||
<CardTitle
|
||||
title={intl.formatMessage({
|
||||
id: "akXDST",
|
||||
defaultMessage: "Visibility",
|
||||
description: "section header",
|
||||
})}
|
||||
/>
|
||||
<CardTitle title={intl.formatMessage(visibilityCardMessages.title)} />
|
||||
<CardContent>
|
||||
<RadioSwitchField
|
||||
disabled={disabled}
|
||||
|
@ -178,10 +166,9 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
|||
/>
|
||||
{!isPublished && (
|
||||
<DateVisibilitySelector
|
||||
buttonText={intl.formatMessage({
|
||||
id: "U3BQKA",
|
||||
defaultMessage: "Set publication date",
|
||||
})}
|
||||
buttonText={intl.formatMessage(
|
||||
visibilityCardMessages.setPublicationDate,
|
||||
)}
|
||||
onInputClose={() =>
|
||||
onChange({ target: { name: "publicationDate", value: null } })
|
||||
}
|
||||
|
@ -189,11 +176,7 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
|||
<TextField
|
||||
error={!!getFieldError(errors, "publicationDate")}
|
||||
disabled={disabled}
|
||||
label={intl.formatMessage({
|
||||
id: "Jt3DwJ",
|
||||
defaultMessage: "Publish on",
|
||||
description: "publish on date",
|
||||
})}
|
||||
label={intl.formatMessage(visibilityCardMessages.publishOn)}
|
||||
name="publicationDate"
|
||||
type="date"
|
||||
fullWidth={true}
|
||||
|
@ -260,11 +243,9 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
|||
<TextField
|
||||
error={!!getFieldError(errors, "startDate")}
|
||||
disabled={disabled}
|
||||
label={intl.formatMessage({
|
||||
id: "Y7Vy19",
|
||||
defaultMessage: "Set available on",
|
||||
description: "available on date",
|
||||
})}
|
||||
label={intl.formatMessage(
|
||||
visibilityCardMessages.setAvailableOn,
|
||||
)}
|
||||
name="availableForPurchase"
|
||||
type="date"
|
||||
fullWidth={true}
|
||||
|
@ -294,29 +275,32 @@ export const VisibilityCard: React.FC<VisibilityCardProps> = props => {
|
|||
<ControlledCheckbox
|
||||
className={classes.checkbox}
|
||||
name="visibleInListings"
|
||||
checked={visibleInListings}
|
||||
checked={!visibleInListings}
|
||||
disabled={disabled}
|
||||
label={
|
||||
<>
|
||||
<p
|
||||
className={classNames(classes.label, classes.listingLabel)}
|
||||
>
|
||||
{intl.formatMessage({
|
||||
id: "0cVk9I",
|
||||
defaultMessage: "Show in product listings",
|
||||
})}
|
||||
{intl.formatMessage(visibilityCardMessages.hideInListings)}
|
||||
</p>
|
||||
|
||||
<span className={classes.secondLabel}>
|
||||
{intl.formatMessage({
|
||||
id: "5ukAFZ",
|
||||
defaultMessage:
|
||||
"Disabling this checkbox will remove product from search and category pages. It will be available on collection pages.",
|
||||
})}
|
||||
{intl.formatMessage(
|
||||
visibilityCardMessages.hideInListingsDescription,
|
||||
)}
|
||||
</span>
|
||||
</>
|
||||
}
|
||||
onChange={onChange}
|
||||
onChange={event =>
|
||||
onChange({
|
||||
...event,
|
||||
target: {
|
||||
...event.target,
|
||||
value: !event.target.value,
|
||||
},
|
||||
})
|
||||
}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
|
40
src/components/VisibilityCard/messages.ts
Normal file
40
src/components/VisibilityCard/messages.ts
Normal file
|
@ -0,0 +1,40 @@
|
|||
import { defineMessages } from "react-intl";
|
||||
|
||||
export const visibilityCardMessages = defineMessages({
|
||||
title: {
|
||||
id: "akXDST",
|
||||
defaultMessage: "Visibility",
|
||||
description: "section header",
|
||||
},
|
||||
sinceDate: {
|
||||
id: "UjsI4o",
|
||||
defaultMessage: "since {date}",
|
||||
description: "date",
|
||||
},
|
||||
setPublicationDate: {
|
||||
id: "3oQzWR",
|
||||
defaultMessage: "Set publication date",
|
||||
description: "product availability",
|
||||
},
|
||||
publishOn: {
|
||||
id: "JmdBa3",
|
||||
defaultMessage: "Publish on",
|
||||
description: "product availability publish date",
|
||||
},
|
||||
setAvailableOn: {
|
||||
id: "THpf1b",
|
||||
defaultMessage: "Set available on",
|
||||
description: "product availability available date",
|
||||
},
|
||||
hideInListings: {
|
||||
id: "jXf/9p",
|
||||
defaultMessage: "Hide in product listings",
|
||||
description: "product availability",
|
||||
},
|
||||
hideInListingsDescription: {
|
||||
id: "4VOIum",
|
||||
defaultMessage:
|
||||
"Enabling this checkbox will remove product from search and category pages. It will be available on collection pages.",
|
||||
description: "product availability",
|
||||
},
|
||||
});
|
|
@ -212,7 +212,6 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
|
|||
<Metadata data={data} onChange={handlers.changeMetadata} />
|
||||
</div>
|
||||
<div>
|
||||
<CardSpacer />
|
||||
<VisibilityCard
|
||||
data={data}
|
||||
errors={errors}
|
||||
|
|
|
@ -112,12 +112,15 @@ export interface PageFormProps extends UsePageFormOpts {
|
|||
disabled: boolean;
|
||||
}
|
||||
|
||||
const getInitialFormData = (page?: PageDetailsFragment): PageFormData => ({
|
||||
isPublished: page?.isPublished,
|
||||
const getInitialFormData = (
|
||||
pageExists: boolean,
|
||||
page?: PageDetailsFragment,
|
||||
): PageFormData => ({
|
||||
isPublished: pageExists ? page?.isPublished : true,
|
||||
metadata: page?.metadata?.map(mapMetadataItemToInput) || [],
|
||||
pageType: null,
|
||||
privateMetadata: page?.privateMetadata?.map(mapMetadataItemToInput) || [],
|
||||
publicationDate: page?.publicationDate || "",
|
||||
publicationDate: pageExists ? page?.publicationDate : "",
|
||||
seoDescription: page?.seoDescription || "",
|
||||
seoTitle: page?.seoTitle || "",
|
||||
slug: page?.slug || "",
|
||||
|
@ -133,7 +136,7 @@ function usePageForm(
|
|||
const pageExists = page !== null;
|
||||
|
||||
const { handleChange, triggerChange, data: formData, formId } = useForm(
|
||||
getInitialFormData(page),
|
||||
getInitialFormData(pageExists, page),
|
||||
undefined,
|
||||
{
|
||||
confirmLeave: true,
|
||||
|
|
|
@ -12,12 +12,14 @@ import {
|
|||
AttributeErrorFragment,
|
||||
FileUploadMutation,
|
||||
FileUploadMutationVariables,
|
||||
ProductChannelListingErrorFragment,
|
||||
ProductChannelListingUpdateMutation,
|
||||
ProductChannelListingUpdateMutationVariables,
|
||||
ProductCreateMutation,
|
||||
ProductCreateMutationVariables,
|
||||
ProductDeleteMutation,
|
||||
ProductDeleteMutationVariables,
|
||||
ProductErrorFragment,
|
||||
ProductTypeQuery,
|
||||
ProductVariantChannelListingUpdateMutation,
|
||||
ProductVariantChannelListingUpdateMutationVariables,
|
||||
|
@ -85,7 +87,12 @@ export function createHandler(
|
|||
}) => Promise<FetchResult<ProductDeleteMutation>>,
|
||||
) {
|
||||
return async (formData: ProductCreateData) => {
|
||||
let errors: Array<AttributeErrorFragment | UploadErrorFragment> = [];
|
||||
let errors: Array<
|
||||
| AttributeErrorFragment
|
||||
| UploadErrorFragment
|
||||
| ProductErrorFragment
|
||||
| ProductChannelListingErrorFragment
|
||||
> = [];
|
||||
|
||||
const uploadFilesResult = await handleUploadMultipleFiles(
|
||||
formData.attributesWithNewFileValue,
|
||||
|
@ -123,8 +130,9 @@ export function createHandler(
|
|||
};
|
||||
|
||||
const result = await productCreate(productVariables);
|
||||
const productErrors = result.data.productCreate.errors || [];
|
||||
|
||||
let hasErrors = errors.length > 0;
|
||||
errors = [...errors, ...productErrors];
|
||||
|
||||
const hasVariants = productType?.hasVariants;
|
||||
const productId = result?.data?.productCreate?.product?.id;
|
||||
|
@ -140,12 +148,10 @@ export function createHandler(
|
|||
),
|
||||
productVariantCreate(getSimpleProductVariables(formData, productId)),
|
||||
]);
|
||||
const channelErrors = result[0].data?.productChannelListingUpdate?.errors;
|
||||
const variantErrors = result[1].data?.productVariantCreate?.errors;
|
||||
|
||||
if ([...(channelErrors || []), ...(variantErrors || [])].length > 0) {
|
||||
hasErrors = true;
|
||||
}
|
||||
const channelErrors =
|
||||
result[0].data?.productChannelListingUpdate?.errors || [];
|
||||
const variantErrors = result[1].data?.productVariantCreate?.errors || [];
|
||||
errors = [...errors, ...channelErrors, ...variantErrors];
|
||||
|
||||
const variantId = result[1].data.productVariantCreate.productVariant?.id;
|
||||
if (variantErrors.length === 0 && variantId) {
|
||||
|
@ -164,17 +170,17 @@ export function createHandler(
|
|||
const result = await updateChannels(
|
||||
getChannelsVariables(productId, formData.channelListings),
|
||||
);
|
||||
const channelErrors =
|
||||
result.data?.productChannelListingUpdate?.errors || [];
|
||||
|
||||
if (result.data?.productChannelListingUpdate?.errors.length > 0) {
|
||||
hasErrors = true;
|
||||
}
|
||||
errors = [...errors, ...channelErrors];
|
||||
}
|
||||
|
||||
/*
|
||||
INFO: This is a stop-gap solution, where we delete products that didn't meet all required data in the create form
|
||||
A more robust solution would require merging create and update form into one to persist form state across redirects
|
||||
*/
|
||||
if (productId && hasErrors) {
|
||||
if (productId && errors.length > 0) {
|
||||
await productDelete({ variables: { id: productId } });
|
||||
|
||||
return { errors };
|
||||
|
|
|
@ -3013,12 +3013,13 @@ exports[`Storyshots Channels / Channels with variants availability card default
|
|||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
|
||||
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id PrivateSwitchBase-checked-id MuiCheckbox-checked-id MuiIconButton-colorPrimary-id"
|
||||
>
|
||||
<span
|
||||
class="MuiIconButton-label-id"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="PrivateSwitchBase-input-id"
|
||||
data-indeterminate="false"
|
||||
name="channel:visibleInListings:1"
|
||||
|
@ -3029,19 +3030,29 @@ exports[`Storyshots Channels / Channels with variants availability card default
|
|||
class="MuiSvgIcon-root-id"
|
||||
focusable="false"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
fill="transparent"
|
||||
height="22"
|
||||
rx="2"
|
||||
ry="2"
|
||||
stroke="currentColor"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
width="22"
|
||||
x="1"
|
||||
y="1"
|
||||
fill="currentColor"
|
||||
height="23"
|
||||
rx="1.5"
|
||||
width="23"
|
||||
x="0.5"
|
||||
y="0.5"
|
||||
/>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M17.5711 4.7629C17.9653 4.34801 18.6267 4.34801 19.0209 4.7629L20.3455 6.1568C20.7122 6.54279 20.7122 7.14848 20.3455 7.53447L9.45066 19L3.65454 12.9002C3.28777 12.5143 3.28777 11.9086 3.65454 11.5226L4.97906 10.1287C5.3733 9.71378 6.03466 9.71378 6.4289 10.1287L9.45066 13.3087L17.5711 4.7629Z"
|
||||
fill="var(--background-paper)"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
|
@ -3051,12 +3062,12 @@ exports[`Storyshots Channels / Channels with variants availability card default
|
|||
<p
|
||||
class="ChannelsAvailabilityCard-label-id ChannelsAvailabilityCard-listingLabel-id"
|
||||
>
|
||||
Show in product listings
|
||||
Hide in product listings
|
||||
</p>
|
||||
<span
|
||||
class="ChannelsAvailabilityCard-secondLabel-id"
|
||||
>
|
||||
Disabling this checkbox will remove product from search and category pages. It will be available on collection pages.
|
||||
Enabling this checkbox will remove product from search and category pages. It will be available on collection pages.
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -3361,12 +3372,13 @@ exports[`Storyshots Channels / Channels with variants availability card default
|
|||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
|
||||
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id PrivateSwitchBase-checked-id MuiCheckbox-checked-id MuiIconButton-colorPrimary-id"
|
||||
>
|
||||
<span
|
||||
class="MuiIconButton-label-id"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="PrivateSwitchBase-input-id"
|
||||
data-indeterminate="false"
|
||||
name="channel:visibleInListings:2"
|
||||
|
@ -3377,19 +3389,29 @@ exports[`Storyshots Channels / Channels with variants availability card default
|
|||
class="MuiSvgIcon-root-id"
|
||||
focusable="false"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
fill="transparent"
|
||||
height="22"
|
||||
rx="2"
|
||||
ry="2"
|
||||
stroke="currentColor"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
width="22"
|
||||
x="1"
|
||||
y="1"
|
||||
fill="currentColor"
|
||||
height="23"
|
||||
rx="1.5"
|
||||
width="23"
|
||||
x="0.5"
|
||||
y="0.5"
|
||||
/>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M17.5711 4.7629C17.9653 4.34801 18.6267 4.34801 19.0209 4.7629L20.3455 6.1568C20.7122 6.54279 20.7122 7.14848 20.3455 7.53447L9.45066 19L3.65454 12.9002C3.28777 12.5143 3.28777 11.9086 3.65454 11.5226L4.97906 10.1287C5.3733 9.71378 6.03466 9.71378 6.4289 10.1287L9.45066 13.3087L17.5711 4.7629Z"
|
||||
fill="var(--background-paper)"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
|
@ -3399,12 +3421,12 @@ exports[`Storyshots Channels / Channels with variants availability card default
|
|||
<p
|
||||
class="ChannelsAvailabilityCard-label-id ChannelsAvailabilityCard-listingLabel-id"
|
||||
>
|
||||
Show in product listings
|
||||
Hide in product listings
|
||||
</p>
|
||||
<span
|
||||
class="ChannelsAvailabilityCard-secondLabel-id"
|
||||
>
|
||||
Disabling this checkbox will remove product from search and category pages. It will be available on collection pages.
|
||||
Enabling this checkbox will remove product from search and category pages. It will be available on collection pages.
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -5141,13 +5163,12 @@ exports[`Storyshots Generics / Channels availability card with onChange 1`] = `
|
|||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id PrivateSwitchBase-checked-id MuiCheckbox-checked-id MuiIconButton-colorPrimary-id"
|
||||
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
|
||||
>
|
||||
<span
|
||||
class="MuiIconButton-label-id"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="PrivateSwitchBase-input-id"
|
||||
data-indeterminate="false"
|
||||
name="channel:visibleInListings:123"
|
||||
|
@ -5158,29 +5179,19 @@ exports[`Storyshots Generics / Channels availability card with onChange 1`] = `
|
|||
class="MuiSvgIcon-root-id"
|
||||
focusable="false"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
fill="currentColor"
|
||||
height="23"
|
||||
rx="1.5"
|
||||
width="23"
|
||||
x="0.5"
|
||||
y="0.5"
|
||||
fill="transparent"
|
||||
height="22"
|
||||
rx="2"
|
||||
ry="2"
|
||||
stroke="currentColor"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
width="22"
|
||||
x="1"
|
||||
y="1"
|
||||
/>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M17.5711 4.7629C17.9653 4.34801 18.6267 4.34801 19.0209 4.7629L20.3455 6.1568C20.7122 6.54279 20.7122 7.14848 20.3455 7.53447L9.45066 19L3.65454 12.9002C3.28777 12.5143 3.28777 11.9086 3.65454 11.5226L4.97906 10.1287C5.3733 9.71378 6.03466 9.71378 6.4289 10.1287L9.45066 13.3087L17.5711 4.7629Z"
|
||||
fill="var(--background-paper)"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
|
@ -5190,12 +5201,12 @@ exports[`Storyshots Generics / Channels availability card with onChange 1`] = `
|
|||
<p
|
||||
class="ChannelsAvailabilityCard-label-id ChannelsAvailabilityCard-listingLabel-id"
|
||||
>
|
||||
Show in product listings
|
||||
Hide in product listings
|
||||
</p>
|
||||
<span
|
||||
class="ChannelsAvailabilityCard-secondLabel-id"
|
||||
>
|
||||
Disabling this checkbox will remove product from search and category pages. It will be available on collection pages.
|
||||
Enabling this checkbox will remove product from search and category pages. It will be available on collection pages.
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -5505,13 +5516,12 @@ exports[`Storyshots Generics / Channels availability card with onChange 1`] = `
|
|||
>
|
||||
<span
|
||||
aria-disabled="false"
|
||||
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id PrivateSwitchBase-checked-id MuiCheckbox-checked-id MuiIconButton-colorPrimary-id"
|
||||
class="MuiButtonBase-root-id MuiIconButton-root-id PrivateSwitchBase-root-id MuiCheckbox-root-id MuiCheckbox-colorPrimary-id MuiIconButton-colorPrimary-id"
|
||||
>
|
||||
<span
|
||||
class="MuiIconButton-label-id"
|
||||
>
|
||||
<input
|
||||
checked=""
|
||||
class="PrivateSwitchBase-input-id"
|
||||
data-indeterminate="false"
|
||||
name="channel:visibleInListings:124"
|
||||
|
@ -5522,29 +5532,19 @@ exports[`Storyshots Generics / Channels availability card with onChange 1`] = `
|
|||
class="MuiSvgIcon-root-id"
|
||||
focusable="false"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<svg
|
||||
fill="none"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
width="24"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect
|
||||
fill="currentColor"
|
||||
height="23"
|
||||
rx="1.5"
|
||||
width="23"
|
||||
x="0.5"
|
||||
y="0.5"
|
||||
fill="transparent"
|
||||
height="22"
|
||||
rx="2"
|
||||
ry="2"
|
||||
stroke="currentColor"
|
||||
stroke-linejoin="round"
|
||||
stroke-width="2"
|
||||
width="22"
|
||||
x="1"
|
||||
y="1"
|
||||
/>
|
||||
<path
|
||||
clip-rule="evenodd"
|
||||
d="M17.5711 4.7629C17.9653 4.34801 18.6267 4.34801 19.0209 4.7629L20.3455 6.1568C20.7122 6.54279 20.7122 7.14848 20.3455 7.53447L9.45066 19L3.65454 12.9002C3.28777 12.5143 3.28777 11.9086 3.65454 11.5226L4.97906 10.1287C5.3733 9.71378 6.03466 9.71378 6.4289 10.1287L9.45066 13.3087L17.5711 4.7629Z"
|
||||
fill="var(--background-paper)"
|
||||
fill-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
|
@ -5554,12 +5554,12 @@ exports[`Storyshots Generics / Channels availability card with onChange 1`] = `
|
|||
<p
|
||||
class="ChannelsAvailabilityCard-label-id ChannelsAvailabilityCard-listingLabel-id"
|
||||
>
|
||||
Show in product listings
|
||||
Hide in product listings
|
||||
</p>
|
||||
<span
|
||||
class="ChannelsAvailabilityCard-secondLabel-id"
|
||||
>
|
||||
Disabling this checkbox will remove product from search and category pages. It will be available on collection pages.
|
||||
Enabling this checkbox will remove product from search and category pages. It will be available on collection pages.
|
||||
</span>
|
||||
</span>
|
||||
</label>
|
||||
|
@ -158197,9 +158197,6 @@ exports[`Storyshots Views / Pages / Page details default 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="CardSpacer-spacer-id"
|
||||
/>
|
||||
<div
|
||||
class="MuiPaper-root-id MuiCard-root-id MuiPaper-elevation0-id MuiPaper-rounded-id"
|
||||
>
|
||||
|
@ -159109,9 +159106,6 @@ exports[`Storyshots Views / Pages / Page details form errors 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="CardSpacer-spacer-id"
|
||||
/>
|
||||
<div
|
||||
class="MuiPaper-root-id MuiCard-root-id MuiPaper-elevation0-id MuiPaper-rounded-id"
|
||||
>
|
||||
|
@ -159618,9 +159612,6 @@ exports[`Storyshots Views / Pages / Page details loading 1`] = `
|
|||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div
|
||||
class="CardSpacer-spacer-id"
|
||||
/>
|
||||
<div
|
||||
class="MuiPaper-root-id MuiCard-root-id MuiPaper-elevation0-id MuiPaper-rounded-id"
|
||||
>
|
||||
|
|
|
@ -8,7 +8,7 @@ function getPublicationData({
|
|||
isPublished,
|
||||
}: PublicationData): PublicationData {
|
||||
return {
|
||||
isPublished: !!publicationDate || isPublished,
|
||||
isPublished,
|
||||
publicationDate: publicationDate || null,
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue