Merge pull request #1066 from mirumee/SALEOR-2547/update-adding-draft-order-products-per-channel (#1070)

Update adding draft order products per channel
This commit is contained in:
mmarkusik 2021-04-20 16:06:39 +02:00 committed by GitHub
parent bddfa2c4af
commit 9d6cc99103
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 807 additions and 1677 deletions

View file

@ -3938,8 +3938,8 @@
"src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_2850255786": {
"string": "Search Products"
},
"src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_353369701": {
"string": "No products matching given query"
"src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_3284796469": {
"string": "No products available in order channel matching given query"
},
"src_dot_orders_dot_components_dot_OrderProductsCardElements_dot_1134347598": {
"context": "product price",
@ -5310,6 +5310,10 @@
"context": "button",
"string": "Delete Variant"
},
"src_dot_products_dot_components_dot_ProductVariantCreatePage_dot_pricingCardSubtitle": {
"context": "variant pricing section subtitle",
"string": "There is no channel to define prices for. You need to first add variant to channels to define prices."
},
"src_dot_products_dot_components_dot_ProductVariantCreatePage_dot_saveVariant": {
"context": "button",
"string": "Save variant"
@ -5462,6 +5466,18 @@
"context": "variant name",
"string": "New Variant"
},
"src_dot_products_dot_components_dot_ProductVariantPage_dot_itemSubtitleHidden": {
"context": "VariantDetailsChannelsAvailabilityCard item subtitle hidden",
"string": "Hidden"
},
"src_dot_products_dot_components_dot_ProductVariantPage_dot_itemSubtitlePublished": {
"context": "VariantDetailsChannelsAvailabilityCard item subtitle published",
"string": "Published since {publicationDate}"
},
"src_dot_products_dot_components_dot_ProductVariantPage_dot_noItemsAvailable": {
"context": "VariantDetailsChannelsAvailabilityCard no items available",
"string": "This variant is not available at any of the channels"
},
"src_dot_products_dot_components_dot_ProductVariantPage_dot_nonSelectionAttributes": {
"context": "attributes, section header",
"string": "Variant Attributes"
@ -5470,6 +5486,14 @@
"context": "attributes, section header",
"string": "Variant Selection Attributes"
},
"src_dot_products_dot_components_dot_ProductVariantPage_dot_subtitle": {
"context": "VariantDetailsChannelsAvailabilityCard subtitle",
"string": "Available in {publishedInChannelsCount} out of {availableChannelsCount}"
},
"src_dot_products_dot_components_dot_ProductVariantPage_dot_title": {
"context": "VariantDetailsChannelsAvailabilityCard title",
"string": "Availability"
},
"src_dot_products_dot_components_dot_ProductVariantPrice_dot_1099355007": {
"context": "product pricing, section header",
"string": "Pricing"

View file

@ -272,6 +272,7 @@ export const fragmentOrderDetails = gql`
id
name
currencyCode
slug
}
isPaid
}

View file

@ -298,6 +298,8 @@ export const fragmentVariant = gql`
url
}
channelListings {
publicationDate
isPublished
channel {
id
name

View file

@ -471,6 +471,7 @@ export interface OrderDetailsFragment_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderDetailsFragment {

View file

@ -189,6 +189,8 @@ export interface ProductVariant_product_channelListings_pricing {
export interface ProductVariant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: ProductVariant_product_channelListings_channel;
pricing: ProductVariant_product_channelListings_pricing | null;
}

View file

@ -363,7 +363,7 @@ const OrderProductAddDialog: React.FC<OrderProductAddDialogProps> = props => {
() => (
<TableRow>
<TableCell colSpan={4}>
<FormattedMessage defaultMessage="No products matching given query" />
<FormattedMessage defaultMessage="No products available in order channel matching given query" />
</TableCell>
</TableRow>
)

View file

@ -814,6 +814,7 @@ export const order = (placeholder: string): OrderDetails_order => ({
canFinalize: true,
channel: {
__typename: "Channel",
slug: "channel-default",
currencyCode: "USD",
id: "123454",
isActive: true,
@ -1371,6 +1372,7 @@ export const draftOrder = (placeholder: string): OrderDetails_order => ({
canFinalize: true,
channel: {
__typename: "Channel",
slug: "channel-default",
currencyCode: "USD",
id: "123454",
isActive: true,

View file

@ -164,8 +164,18 @@ export const useOrderQuery = makeQuery<OrderDetails, OrderDetailsVariables>(
);
export const searchOrderVariant = gql`
query SearchOrderVariant($first: Int!, $query: String!, $after: String) {
search: products(first: $first, after: $after, filter: { search: $query }) {
query SearchOrderVariant(
$channel: String!
$first: Int!
$query: String!
$after: String
) {
search: products(
first: $first
after: $after
filter: { search: $query }
channel: $channel
) {
edges {
node {
id

View file

@ -479,6 +479,7 @@ export interface FulfillOrder_orderFulfill_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface FulfillOrder_orderFulfill_order {

View file

@ -477,6 +477,7 @@ export interface OrderCancel_orderCancel_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderCancel_orderCancel_order {

View file

@ -477,6 +477,7 @@ export interface OrderCapture_orderCapture_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderCapture_orderCapture_order {

View file

@ -477,6 +477,7 @@ export interface OrderConfirm_orderConfirm_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderConfirm_orderConfirm_order {

View file

@ -471,6 +471,7 @@ export interface OrderDetails_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderDetails_order {

View file

@ -477,6 +477,7 @@ export interface OrderDiscountAdd_orderDiscountAdd_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderDiscountAdd_orderDiscountAdd_order {

View file

@ -477,6 +477,7 @@ export interface OrderDiscountDelete_orderDiscountDelete_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderDiscountDelete_orderDiscountDelete_order {

View file

@ -477,6 +477,7 @@ export interface OrderDiscountUpdate_orderDiscountUpdate_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderDiscountUpdate_orderDiscountUpdate_order {

View file

@ -477,6 +477,7 @@ export interface OrderDraftCancel_draftOrderDelete_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderDraftCancel_draftOrderDelete_order {

View file

@ -477,6 +477,7 @@ export interface OrderDraftFinalize_draftOrderComplete_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderDraftFinalize_draftOrderComplete_order {

View file

@ -477,6 +477,7 @@ export interface OrderDraftUpdate_draftOrderUpdate_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderDraftUpdate_draftOrderUpdate_order {

View file

@ -477,6 +477,7 @@ export interface OrderFulfillmentCancel_orderFulfillmentCancel_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderFulfillmentCancel_orderFulfillmentCancel_order {

View file

@ -572,6 +572,7 @@ export interface OrderFulfillmentRefundProducts_orderFulfillmentRefundProducts_o
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderFulfillmentRefundProducts_orderFulfillmentRefundProducts_order {

View file

@ -477,6 +477,7 @@ export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_o
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderFulfillmentUpdateTracking_orderFulfillmentUpdateTracking_order {

View file

@ -477,6 +477,7 @@ export interface OrderLineDelete_orderLineDelete_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderLineDelete_orderLineDelete_order {

View file

@ -477,6 +477,7 @@ export interface OrderLineDiscountRemove_orderLineDiscountRemove_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderLineDiscountRemove_orderLineDiscountRemove_order {

View file

@ -477,6 +477,7 @@ export interface OrderLineDiscountUpdate_orderLineDiscountUpdate_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderLineDiscountUpdate_orderLineDiscountUpdate_order {

View file

@ -477,6 +477,7 @@ export interface OrderLineUpdate_orderLineUpdate_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderLineUpdate_orderLineUpdate_order {

View file

@ -477,6 +477,7 @@ export interface OrderLinesAdd_orderLinesCreate_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderLinesAdd_orderLinesCreate_order {

View file

@ -477,6 +477,7 @@ export interface OrderMarkAsPaid_orderMarkAsPaid_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderMarkAsPaid_orderMarkAsPaid_order {

View file

@ -477,6 +477,7 @@ export interface OrderRefund_orderRefund_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderRefund_orderRefund_order {

View file

@ -485,6 +485,7 @@ export interface OrderShippingMethodUpdate_orderUpdateShipping_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderShippingMethodUpdate_orderUpdateShipping_order {

View file

@ -477,6 +477,7 @@ export interface OrderUpdate_orderUpdate_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderUpdate_orderUpdate_order {

View file

@ -477,6 +477,7 @@ export interface OrderVoid_orderVoid_order_channel {
id: string;
name: string;
currencyCode: string;
slug: string;
}
export interface OrderVoid_orderVoid_order {

View file

@ -72,6 +72,7 @@ export interface SearchOrderVariant {
}
export interface SearchOrderVariantVariables {
channel: string;
first: number;
query: string;
after?: string | null;

View file

@ -61,7 +61,7 @@ export const OrderDraftDetails: React.FC<OrderDraftDetailsProps> = ({
search: variantSearch,
result: variantSearchOpts
} = useOrderVariantSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
variables: { ...DEFAULT_INITIAL_SEARCH_DATA, channel: order.channel.slug }
});
const {

View file

@ -89,7 +89,7 @@ export const OrderUnconfirmedDetails: React.FC<OrderUnconfirmedDetailsProps> = (
search: variantSearch,
result: variantSearchOpts
} = useOrderVariantSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
variables: { ...DEFAULT_INITIAL_SEARCH_DATA, channel: order.channel.slug }
});
const warehouses = useWarehouseList({
displayLoader: true,

View file

@ -16,7 +16,6 @@ import Grid from "@saleor/components/Grid";
import Metadata from "@saleor/components/Metadata";
import PageHeader from "@saleor/components/PageHeader";
import SaveButtonBar from "@saleor/components/SaveButtonBar";
import { ProductChannelListingErrorFragment } from "@saleor/fragments/types/ProductChannelListingErrorFragment";
import { ProductErrorWithAttributesFragment } from "@saleor/fragments/types/ProductErrorWithAttributesFragment";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
@ -51,12 +50,16 @@ const messages = defineMessages({
saveVariant: {
defaultMessage: "Save variant",
description: "button"
},
pricingCardSubtitle: {
defaultMessage:
"There is no channel to define prices for. You need to first add variant to channels to define prices.",
description: "variant pricing section subtitle"
}
});
interface ProductVariantCreatePageProps {
channels: ChannelPriceData[];
channelErrors: ProductChannelListingErrorFragment[] | undefined;
disabled: boolean;
errors: ProductErrorWithAttributesFragment[];
header: string;
@ -82,7 +85,6 @@ interface ProductVariantCreatePageProps {
const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
channels,
channelErrors = [],
disabled,
errors,
header,
@ -209,15 +211,7 @@ const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
/>
<CardSpacer />
<ProductVariantPrice
ProductVariantChannelListings={data.channelListings.map(
channel => ({
...channel.data,
...channel.value
})
)}
errors={channelErrors}
loading={disabled}
onChange={handlers.changeChannels}
disabledMessage={messages.pricingCardSubtitle}
/>
<CardSpacer />
<ProductStocks

View file

@ -8,7 +8,7 @@ import {
createFetchMoreReferencesHandler,
createFetchReferencesHandler
} from "@saleor/attributes/utils/handlers";
import { ChannelPriceData, IChannelPriceArgs } from "@saleor/channels/utils";
import { ChannelPriceData } from "@saleor/channels/utils";
import { AttributeInput } from "@saleor/components/Attributes";
import { MetadataFormData } from "@saleor/components/Metadata";
import useForm, { FormChange } from "@saleor/hooks/useForm";
@ -18,11 +18,6 @@ import useFormset, {
} from "@saleor/hooks/useFormset";
import { ProductVariantCreateData_product } from "@saleor/products/types/ProductVariantCreateData";
import { getVariantAttributeInputFromProduct } from "@saleor/products/utils/data";
import { getChannelsInput } from "@saleor/products/utils/handlers";
import {
validateCostPrice,
validatePrice
} from "@saleor/products/utils/validation";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
@ -38,7 +33,6 @@ export interface ProductVariantCreateFormData extends MetadataFormData {
weight: string;
}
export interface ProductVariantCreateData extends ProductVariantCreateFormData {
channelListings: FormsetData<ChannelPriceData, IChannelPriceArgs>;
attributes: AttributeInput[];
attributesWithNewFileValue: FormsetData<null, File>;
stocks: ProductStockInput[];
@ -58,10 +52,7 @@ export interface UseProductVariantCreateFormOpts {
export interface ProductVariantCreateHandlers
extends Record<
| "changeStock"
| "selectAttribute"
| "selectAttributeMultiple"
| "changeChannels",
"changeStock" | "selectAttribute" | "selectAttributeMultiple",
FormsetChange
>,
Record<"selectAttributeReference", FormsetChange<string[]>>,
@ -107,13 +98,11 @@ function useProductVariantCreateForm(
const triggerChange = () => setChanged(true);
const attributeInput = getVariantAttributeInputFromProduct(product);
const channelsInput = getChannelsInput(opts.currentChannels);
const form = useForm(initial);
const attributes = useFormset(attributeInput);
const attributesWithNewFileValue = useFormset<null, File>([]);
const stocks = useFormset<ProductStockFormsetData, string>([]);
const channels = useFormset(channelsInput);
const {
makeChangeHandler: makeMetadataChangeHandler
} = useMetadataChangeTrigger();
@ -179,16 +168,6 @@ function useProductVariantCreateForm(
triggerChange();
stocks.remove(id);
};
const handleChannelChange: FormsetChange = (id, value) => {
channels.change(id, value);
triggerChange();
};
const disabled = channels?.data.some(
channelData =>
validatePrice(channelData.value.price) ||
validateCostPrice(channelData.value.costPrice)
);
const data: ProductVariantCreateData = {
...form.data,
@ -199,7 +178,6 @@ function useProductVariantCreateForm(
opts.referenceProducts
),
attributesWithNewFileValue: attributesWithNewFileValue.data,
channelListings: channels.data,
stocks: stocks.data
};
@ -208,10 +186,9 @@ function useProductVariantCreateForm(
return {
change: handleChange,
data,
disabled,
disabled: false,
handlers: {
addStock: handleStockAdd,
changeChannels: handleChannelChange,
changeMetadata,
changeStock: handleStockChange,
deleteStock: handleStockDelete,

View file

@ -41,6 +41,7 @@ import ProductVariantUpdateForm, {
ProductVariantUpdateHandlers,
ProductVariantUpdateSubmitData
} from "./form";
import VariantDetailsChannelsAvailabilityCard from "./VariantDetailsChannelsAvailabilityCard";
const messages = defineMessages({
nonSelectionAttributes: {
@ -217,6 +218,7 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
/>
</div>
<div>
<VariantDetailsChannelsAvailabilityCard variant={variant} />
<Attributes
title={intl.formatMessage(messages.nonSelectionAttributes)}
attributes={data.attributes.filter(
@ -263,6 +265,7 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
/>
<CardSpacer />
<ProductVariantPrice
disabled={!variant}
ProductVariantChannelListings={data.channelListings.map(
channel => ({
...channel.data,

View file

@ -0,0 +1,25 @@
import { Card } from "@material-ui/core";
import CardSpacer from "@saleor/components/CardSpacer";
import CardTitle from "@saleor/components/CardTitle";
import React from "react";
import { FormattedMessage } from "react-intl";
import { variantDetailsChannelsAvailabilityCardMessages as messages } from "../messages";
interface VariantDetailsChannelsAvailabilityCardContainerProps {
children: React.ReactNode;
}
const VariantDetailsChannelsAvailabilityCardContainer: React.FC<VariantDetailsChannelsAvailabilityCardContainerProps> = ({
children
}) => (
<>
<Card>
<CardTitle title={<FormattedMessage {...messages.title} />} />
{children}
</Card>
<CardSpacer />
</>
);
export default VariantDetailsChannelsAvailabilityCardContainer;

View file

@ -0,0 +1,180 @@
import {
CardContent,
Divider,
ExpansionPanel,
ExpansionPanelSummary,
makeStyles,
Typography
} from "@material-ui/core";
import Skeleton from "@saleor/components/Skeleton";
import { ProductVariant } from "@saleor/fragments/types/ProductVariant";
import useDateLocalize from "@saleor/hooks/useDateLocalize";
import IconChevronDown from "@saleor/icons/ChevronDown";
import React from "react";
import { useIntl } from "react-intl";
import { variantDetailsChannelsAvailabilityCardMessages as messages } from "../messages";
import CardContainer from "./VariantDetailsChannelsAvailabilityCardContainer";
const useExpanderStyles = makeStyles(
() => ({
expanded: {},
root: {
boxShadow: "none",
margin: 0,
padding: 0,
"&:before": {
content: "none"
},
"&$expanded": {
margin: 0,
border: "none"
}
}
}),
{ name: "VariantDetailsChannelsAvailabilityCardExpander" }
);
const useSummaryStyles = makeStyles(
theme => ({
expanded: {},
root: {
width: "100%",
border: "none",
margin: 0,
padding: 0,
minHeight: 0,
paddingTop: theme.spacing(2),
paddingLeft: theme.spacing(3),
paddingRight: theme.spacing(5.5),
paddingBottom: theme.spacing(2),
"&$expanded": {
minHeight: 0
}
},
content: {
margin: 0,
"&$expanded": {
margin: 0
}
}
}),
{ name: "VariantDetailsChannelsAvailabilityCardExpanderSummary" }
);
interface VariantDetailsChannelsAvailabilityCardProps {
variant: ProductVariant;
}
const VariantDetailsChannelsAvailabilityCard: React.FC<VariantDetailsChannelsAvailabilityCardProps> = ({
variant
}) => {
const expanderClasses = useExpanderStyles({});
const summaryClasses = useSummaryStyles({});
const localizeDate = useDateLocalize();
const intl = useIntl();
const getProductChannelListingByChannelId = (channelId: string) =>
variant?.product.channelListings.find(
({ channel }) => channel.id === channelId
);
const getItemSubtitle = (channelId: string) => {
const {
isPublished,
publicationDate
} = getProductChannelListingByChannelId(channelId);
if (!isPublished) {
return intl.formatMessage(messages.itemSubtitleHidden);
}
return intl.formatMessage(messages.itemSubtitlePublished, {
publicationDate: localizeDate(publicationDate)
});
};
if (!variant) {
return (
<CardContainer>
<CardContent>
<Skeleton />
</CardContent>
</CardContainer>
);
}
const { channelListings } = variant;
const isAvailableInAnyChannels = !!channelListings.length;
const variantChannelListingsChannelsIds = channelListings.map(
({ channel: { id } }) => id
);
const allAvailableChannelsListings = variant.product.channelListings.filter(
({ channel }) => variantChannelListingsChannelsIds.includes(channel.id)
);
const publishedInChannelsListings = allAvailableChannelsListings.filter(
({ isPublished }) => isPublished
);
if (!isAvailableInAnyChannels) {
return (
<CardContainer>
<CardContent>
<Typography variant="caption">
{intl.formatMessage(messages.noItemsAvailable)}
</Typography>
</CardContent>
</CardContainer>
);
}
return (
<CardContainer>
<ExpansionPanel classes={expanderClasses}>
<ExpansionPanelSummary
expandIcon={<IconChevronDown />}
classes={summaryClasses}
data-test-id="channels-variant-availability-summary"
>
<>
<Typography variant="caption">
{intl.formatMessage(messages.subtitle, {
publishedInChannelsCount: publishedInChannelsListings.length,
availableChannelsCount: allAvailableChannelsListings.length
})}
</Typography>
</>
</ExpansionPanelSummary>
{channelListings.map(({ channel }) => (
<>
<Divider />
<CardContent>
<Typography
data-test-id={`channels-variant-availability-item-title-${channel.id}`}
>
{channel.name}
</Typography>
<Typography
variant="caption"
data-test-id={`channels-variant-availability-item-subtitle-${channel.id}`}
>
{getItemSubtitle(channel.id)}
</Typography>
</CardContent>
</>
))}
</ExpansionPanel>
</CardContainer>
);
};
export default VariantDetailsChannelsAvailabilityCard;

View file

@ -0,0 +1,26 @@
import { defineMessages } from "react-intl";
export const variantDetailsChannelsAvailabilityCardMessages = defineMessages({
title: {
defaultMessage: "Availability",
description: "VariantDetailsChannelsAvailabilityCard title"
},
subtitle: {
defaultMessage:
"Available in {publishedInChannelsCount} out of {availableChannelsCount}",
description: "VariantDetailsChannelsAvailabilityCard subtitle"
},
itemSubtitlePublished: {
defaultMessage: "Published since {publicationDate}",
description:
"VariantDetailsChannelsAvailabilityCard item subtitle published"
},
itemSubtitleHidden: {
defaultMessage: "Hidden",
description: "VariantDetailsChannelsAvailabilityCard item subtitle hidden"
},
noItemsAvailable: {
defaultMessage: "This variant is not available at any of the channels",
description: "VariantDetailsChannelsAvailabilityCard no items available"
}
});

View file

@ -21,7 +21,7 @@ import {
} from "@saleor/utils/errors";
import getProductErrorMessage from "@saleor/utils/errors/product";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import { FormattedMessage, MessageDescriptor, useIntl } from "react-intl";
const useStyles = makeStyles(
theme => ({
@ -62,25 +62,53 @@ const useStyles = makeStyles(
);
interface ProductVariantPriceProps {
ProductVariantChannelListings: ChannelData[];
errors: ProductChannelListingErrorFragment[];
ProductVariantChannelListings?: ChannelData[];
errors?: ProductChannelListingErrorFragment[];
loading?: boolean;
onChange: (id: string, data: ChannelPriceArgs) => void;
disabled?: boolean;
onChange?: (id: string, data: ChannelPriceArgs) => void;
disabledMessage?: MessageDescriptor;
}
const numberOfColumns = 2;
const ProductVariantPrice: React.FC<ProductVariantPriceProps> = props => {
const {
disabled = false,
errors = [],
ProductVariantChannelListings,
ProductVariantChannelListings = [],
loading,
onChange
onChange,
disabledMessage
} = props;
const classes = useStyles(props);
const intl = useIntl();
const formErrors = getFormChannelErrors(["price", "costPrice"], errors);
if (disabled || !ProductVariantChannelListings.length) {
return (
<Card>
<CardTitle
title={intl.formatMessage({
defaultMessage: "Pricing",
description: "product pricing, section header"
})}
/>
<CardContent>
<Typography variant="caption">
{intl.formatMessage(
disabledMessage || {
defaultMessage: "There is no channel to define prices for",
description: "variant pricing section subtitle",
id: "product variant pricing card disabled subtitle"
}
)}
</Typography>
</CardContent>
</Card>
);
}
return (
<Card>
<CardTitle

View file

@ -2817,6 +2817,8 @@ export const variant = (placeholderImage: string): ProductVariant => ({
channelListings: [
{
__typename: "ProductChannelListing",
isPublished: false,
publicationDate: null,
channel: {
__typename: "Channel",
currencyCode: "USD",
@ -2848,6 +2850,8 @@ export const variant = (placeholderImage: string): ProductVariant => ({
},
{
__typename: "ProductChannelListing",
isPublished: true,
publicationDate: "2022-01-21",
channel: {
__typename: "Channel",
currencyCode: "USD",

View file

@ -189,6 +189,8 @@ export interface ProductVariantChannelListingUpdate_productVariantChannelListing
export interface ProductVariantChannelListingUpdate_productVariantChannelListingUpdate_variant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: ProductVariantChannelListingUpdate_productVariantChannelListingUpdate_variant_product_channelListings_channel;
pricing: ProductVariantChannelListingUpdate_productVariantChannelListingUpdate_variant_product_channelListings_pricing | null;
}

View file

@ -189,6 +189,8 @@ export interface ProductVariantDetails_productVariant_product_channelListings_pr
export interface ProductVariantDetails_productVariant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: ProductVariantDetails_productVariant_product_channelListings_channel;
pricing: ProductVariantDetails_productVariant_product_channelListings_pricing | null;
}

View file

@ -480,6 +480,8 @@ export interface SimpleProductUpdate_productVariantUpdate_productVariant_product
export interface SimpleProductUpdate_productVariantUpdate_productVariant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: SimpleProductUpdate_productVariantUpdate_productVariant_product_channelListings_channel;
pricing: SimpleProductUpdate_productVariantUpdate_productVariant_product_channelListings_pricing | null;
}
@ -767,6 +769,8 @@ export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_p
export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: SimpleProductUpdate_productVariantStocksCreate_productVariant_product_channelListings_channel;
pricing: SimpleProductUpdate_productVariantStocksCreate_productVariant_product_channelListings_pricing | null;
}
@ -1053,6 +1057,8 @@ export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_p
export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: SimpleProductUpdate_productVariantStocksDelete_productVariant_product_channelListings_channel;
pricing: SimpleProductUpdate_productVariantStocksDelete_productVariant_product_channelListings_pricing | null;
}
@ -1340,6 +1346,8 @@ export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_p
export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: SimpleProductUpdate_productVariantStocksUpdate_productVariant_product_channelListings_channel;
pricing: SimpleProductUpdate_productVariantStocksUpdate_productVariant_product_channelListings_pricing | null;
}

View file

@ -196,6 +196,8 @@ export interface VariantCreate_productVariantCreate_productVariant_product_chann
export interface VariantCreate_productVariantCreate_productVariant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: VariantCreate_productVariantCreate_productVariant_product_channelListings_channel;
pricing: VariantCreate_productVariantCreate_productVariant_product_channelListings_pricing | null;
}

View file

@ -195,6 +195,8 @@ export interface VariantMediaAssign_variantMediaAssign_productVariant_product_ch
export interface VariantMediaAssign_variantMediaAssign_productVariant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: VariantMediaAssign_variantMediaAssign_productVariant_product_channelListings_channel;
pricing: VariantMediaAssign_variantMediaAssign_productVariant_product_channelListings_pricing | null;
}

View file

@ -195,6 +195,8 @@ export interface VariantMediaUnassign_variantMediaUnassign_productVariant_produc
export interface VariantMediaUnassign_variantMediaUnassign_productVariant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: VariantMediaUnassign_variantMediaUnassign_productVariant_product_channelListings_channel;
pricing: VariantMediaUnassign_variantMediaUnassign_productVariant_product_channelListings_pricing | null;
}

View file

@ -196,6 +196,8 @@ export interface VariantUpdate_productVariantUpdate_productVariant_product_chann
export interface VariantUpdate_productVariantUpdate_productVariant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: VariantUpdate_productVariantUpdate_productVariant_product_channelListings_channel;
pricing: VariantUpdate_productVariantUpdate_productVariant_product_channelListings_pricing | null;
}
@ -483,6 +485,8 @@ export interface VariantUpdate_productVariantStocksUpdate_productVariant_product
export interface VariantUpdate_productVariantStocksUpdate_productVariant_product_channelListings {
__typename: "ProductChannelListing";
publicationDate: any | null;
isPublished: boolean;
channel: VariantUpdate_productVariantStocksUpdate_productVariant_product_channelListings_channel;
pricing: VariantUpdate_productVariantStocksUpdate_productVariant_product_channelListings_pricing | null;
}

View file

@ -10,11 +10,7 @@ import { WindowTitle } from "@saleor/components/WindowTitle";
import { DEFAULT_INITIAL_SEARCH_DATA } from "@saleor/config";
import { useFileUploadMutation } from "@saleor/files/mutations";
import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier";
import useShop from "@saleor/hooks/useShop";
import { commonMessages } from "@saleor/intl";
import { useProductVariantChannelListingUpdate } from "@saleor/products/mutations";
import { ProductVariantChannelListingUpdate } from "@saleor/products/types/ProductVariantChannelListingUpdate";
import usePageSearch from "@saleor/searches/usePageSearch";
import useProductSearch from "@saleor/searches/useProductSearch";
import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler";
@ -54,7 +50,6 @@ export const ProductVariant: React.FC<ProductVariantCreateProps> = ({
params
}) => {
const navigate = useNavigator();
const notify = useNotifier();
const shop = useShop();
const intl = useIntl();
const warehouses = useWarehouseList({
@ -63,20 +58,6 @@ export const ProductVariant: React.FC<ProductVariantCreateProps> = ({
first: 50
}
});
const handleCreateSuccess = (data: ProductVariantChannelListingUpdate) => {
if (data.productVariantChannelListingUpdate.errors.length === 0) {
notify({
status: "success",
text: intl.formatMessage(commonMessages.savedChanges)
});
navigate(
productVariantEditUrl(
productId,
data.productVariantChannelListingUpdate.variant.id
)
);
}
};
const { data, loading: productLoading } = useProductVariantCreateQuery({
displayLoader: true,
@ -85,13 +66,6 @@ export const ProductVariant: React.FC<ProductVariantCreateProps> = ({
const [uploadFile, uploadFileOpts] = useFileUploadMutation({});
const [
updateChannels,
updateChannelsOpts
] = useProductVariantChannelListingUpdate({
onCompleted: handleCreateSuccess
});
const product = data?.product;
const channels: ChannelPriceData[] = product?.channelListings.map(
@ -104,21 +78,6 @@ export const ProductVariant: React.FC<ProductVariantCreateProps> = ({
})
);
const handleSubmitChannels = (
data: ProductVariantCreateData,
variantId: string
) =>
updateChannels({
variables: {
id: variantId,
input: data.channelListings.map(listing => ({
channelId: listing.id,
costPrice: listing.value.costPrice || null,
price: listing.value.price
}))
}
});
const [variantCreate, variantCreateResult] = useVariantCreateMutation({});
const [updateMetadata] = useMetadataUpdate({});
@ -170,9 +129,6 @@ export const ProductVariant: React.FC<ProductVariantCreateProps> = ({
}
});
const id = result.data?.productVariantCreate?.productVariant?.id;
if (id) {
await handleSubmitChannels(formData, id);
}
return id || null;
};
@ -234,9 +190,6 @@ export const ProductVariant: React.FC<ProductVariantCreateProps> = ({
/>
<ProductVariantCreatePage
channels={channels}
channelErrors={
updateChannelsOpts?.data?.productVariantChannelListingUpdate?.errors
}
disabled={disableForm}
errors={variantCreateResult.data?.productVariantCreate.errors || []}
header={intl.formatMessage({

File diff suppressed because it is too large Load diff

View file

@ -22,7 +22,6 @@ storiesOf("Views / Products / Create product variant", module)
.add("default", () => (
<ProductVariantCreatePage
channels={channels}
channelErrors={[]}
weightUnit="kg"
disabled={false}
errors={[]}
@ -44,7 +43,6 @@ storiesOf("Views / Products / Create product variant", module)
.add("with errors", () => (
<ProductVariantCreatePage
channels={channels}
channelErrors={[]}
weightUnit="kg"
disabled={false}
errors={[
@ -85,7 +83,6 @@ storiesOf("Views / Products / Create product variant", module)
.add("when loading data", () => (
<ProductVariantCreatePage
channels={channels}
channelErrors={[]}
weightUnit="kg"
disabled={true}
errors={[]}
@ -107,7 +104,6 @@ storiesOf("Views / Products / Create product variant", module)
.add("add first variant", () => (
<ProductVariantCreatePage
channels={channels}
channelErrors={[]}
weightUnit="kg"
disabled={false}
errors={[]}
@ -132,7 +128,6 @@ storiesOf("Views / Products / Create product variant", module)
.add("no warehouses", () => (
<ProductVariantCreatePage
channels={channels}
channelErrors={[]}
weightUnit="kg"
disabled={false}
errors={[]}