Fix bugs in forms (#1941)
* Fix plugin config form * Add missing webhooks * Fix rate description field * Fix auth race condition * Fix customer removal * Fix staff member deletion * Fix shipping rate submitting
This commit is contained in:
parent
26659a0be7
commit
ed1c189b02
10 changed files with 844 additions and 413 deletions
File diff suppressed because it is too large
Load diff
|
@ -22,6 +22,11 @@ export const SectionRoute: React.FC<SectionRouteProps> = ({
|
|||
}) => {
|
||||
const { user } = useUser();
|
||||
|
||||
// Prevents race condition
|
||||
if (user === undefined) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const hasSectionPermissions = () => {
|
||||
if (!permissions) {
|
||||
return true;
|
||||
|
|
|
@ -137,7 +137,13 @@ const CustomerDetailsViewInner: React.FC<CustomerDetailsViewProps> = ({
|
|||
<ActionDialog
|
||||
confirmButtonState={removeCustomerOpts.status}
|
||||
onClose={() => navigate(customerUrl(id), { replace: true })}
|
||||
onConfirm={() => removeCustomer()}
|
||||
onConfirm={() =>
|
||||
removeCustomer({
|
||||
variables: {
|
||||
id
|
||||
}
|
||||
})
|
||||
}
|
||||
title={intl.formatMessage({
|
||||
defaultMessage: "Delete Customer",
|
||||
description: "dialog header"
|
||||
|
|
|
@ -2066,12 +2066,13 @@ export type ObjectWithMetadataFieldPolicy = {
|
|||
privateMetadata?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
metadata?: FieldPolicy<any> | FieldReadFunction<any>
|
||||
};
|
||||
export type OrderKeySpecifier = ('id' | 'privateMetadata' | 'metadata' | 'created' | 'status' | 'user' | 'trackingClientId' | 'billingAddress' | 'shippingAddress' | 'shippingMethodName' | 'collectionPointName' | 'channel' | 'fulfillments' | 'lines' | 'actions' | 'availableShippingMethods' | 'shippingMethods' | 'availableCollectionPoints' | 'invoices' | 'number' | 'original' | 'origin' | 'isPaid' | 'paymentStatus' | 'paymentStatusDisplay' | 'payments' | 'total' | 'undiscountedTotal' | 'shippingMethod' | 'shippingPrice' | 'shippingTaxRate' | 'token' | 'voucher' | 'giftCards' | 'displayGrossPrices' | 'customerNote' | 'weight' | 'redirectUrl' | 'subtotal' | 'statusDisplay' | 'canFinalize' | 'totalAuthorized' | 'totalCaptured' | 'events' | 'totalBalance' | 'userEmail' | 'isShippingRequired' | 'deliveryMethod' | 'languageCode' | 'languageCodeEnum' | 'discount' | 'discountName' | 'translatedDiscountName' | 'discounts' | 'errors' | OrderKeySpecifier)[];
|
||||
export type OrderKeySpecifier = ('id' | 'privateMetadata' | 'metadata' | 'created' | 'updatedAt' | 'status' | 'user' | 'trackingClientId' | 'billingAddress' | 'shippingAddress' | 'shippingMethodName' | 'collectionPointName' | 'channel' | 'fulfillments' | 'lines' | 'actions' | 'availableShippingMethods' | 'shippingMethods' | 'availableCollectionPoints' | 'invoices' | 'number' | 'original' | 'origin' | 'isPaid' | 'paymentStatus' | 'paymentStatusDisplay' | 'payments' | 'total' | 'undiscountedTotal' | 'shippingMethod' | 'shippingPrice' | 'shippingTaxRate' | 'token' | 'voucher' | 'giftCards' | 'displayGrossPrices' | 'customerNote' | 'weight' | 'redirectUrl' | 'subtotal' | 'statusDisplay' | 'canFinalize' | 'totalAuthorized' | 'totalCaptured' | 'events' | 'totalBalance' | 'userEmail' | 'isShippingRequired' | 'deliveryMethod' | 'languageCode' | 'languageCodeEnum' | 'discount' | 'discountName' | 'translatedDiscountName' | 'discounts' | 'errors' | OrderKeySpecifier)[];
|
||||
export type OrderFieldPolicy = {
|
||||
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
privateMetadata?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
metadata?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
created?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
updatedAt?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
status?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
user?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
trackingClientId?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
|
@ -2722,7 +2723,7 @@ export type PreorderThresholdFieldPolicy = {
|
|||
quantity?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
soldUnits?: FieldPolicy<any> | FieldReadFunction<any>
|
||||
};
|
||||
export type ProductKeySpecifier = ('id' | 'privateMetadata' | 'metadata' | 'seoTitle' | 'seoDescription' | 'name' | 'description' | 'productType' | 'slug' | 'category' | 'updatedAt' | 'chargeTaxes' | 'weight' | 'defaultVariant' | 'rating' | 'channel' | 'descriptionJson' | 'thumbnail' | 'pricing' | 'isAvailable' | 'taxType' | 'attributes' | 'channelListings' | 'mediaById' | 'imageById' | 'variants' | 'media' | 'images' | 'collections' | 'translation' | 'availableForPurchase' | 'isAvailableForPurchase' | ProductKeySpecifier)[];
|
||||
export type ProductKeySpecifier = ('id' | 'privateMetadata' | 'metadata' | 'seoTitle' | 'seoDescription' | 'name' | 'description' | 'productType' | 'slug' | 'category' | 'created' | 'updatedAt' | 'chargeTaxes' | 'weight' | 'defaultVariant' | 'rating' | 'channel' | 'descriptionJson' | 'thumbnail' | 'pricing' | 'isAvailable' | 'taxType' | 'attributes' | 'channelListings' | 'mediaById' | 'imageById' | 'variants' | 'media' | 'images' | 'collections' | 'translation' | 'availableForPurchase' | 'isAvailableForPurchase' | ProductKeySpecifier)[];
|
||||
export type ProductFieldPolicy = {
|
||||
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
privateMetadata?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
|
@ -2734,6 +2735,7 @@ export type ProductFieldPolicy = {
|
|||
productType?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
slug?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
category?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
created?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
updatedAt?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
chargeTaxes?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
weight?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
|
@ -3001,7 +3003,7 @@ export type ProductUpdateFieldPolicy = {
|
|||
errors?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
product?: FieldPolicy<any> | FieldReadFunction<any>
|
||||
};
|
||||
export type ProductVariantKeySpecifier = ('id' | 'privateMetadata' | 'metadata' | 'name' | 'sku' | 'product' | 'trackInventory' | 'quantityLimitPerCustomer' | 'weight' | 'channel' | 'channelListings' | 'pricing' | 'attributes' | 'margin' | 'quantityOrdered' | 'revenue' | 'images' | 'media' | 'translation' | 'digitalContent' | 'stocks' | 'quantityAvailable' | 'preorder' | ProductVariantKeySpecifier)[];
|
||||
export type ProductVariantKeySpecifier = ('id' | 'privateMetadata' | 'metadata' | 'name' | 'sku' | 'product' | 'trackInventory' | 'quantityLimitPerCustomer' | 'weight' | 'channel' | 'channelListings' | 'pricing' | 'attributes' | 'margin' | 'quantityOrdered' | 'revenue' | 'images' | 'media' | 'translation' | 'digitalContent' | 'stocks' | 'quantityAvailable' | 'preorder' | 'created' | 'updatedAt' | ProductVariantKeySpecifier)[];
|
||||
export type ProductVariantFieldPolicy = {
|
||||
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
privateMetadata?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
|
@ -3025,7 +3027,9 @@ export type ProductVariantFieldPolicy = {
|
|||
digitalContent?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
stocks?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
quantityAvailable?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
preorder?: FieldPolicy<any> | FieldReadFunction<any>
|
||||
preorder?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
created?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
updatedAt?: FieldPolicy<any> | FieldReadFunction<any>
|
||||
};
|
||||
export type ProductVariantBulkCreateKeySpecifier = ('count' | 'productVariants' | 'bulkProductErrors' | 'errors' | ProductVariantBulkCreateKeySpecifier)[];
|
||||
export type ProductVariantBulkCreateFieldPolicy = {
|
||||
|
@ -3249,7 +3253,7 @@ export type RequestPasswordResetFieldPolicy = {
|
|||
accountErrors?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
errors?: FieldPolicy<any> | FieldReadFunction<any>
|
||||
};
|
||||
export type SaleKeySpecifier = ('id' | 'privateMetadata' | 'metadata' | 'name' | 'type' | 'startDate' | 'endDate' | 'categories' | 'collections' | 'products' | 'variants' | 'translation' | 'channelListings' | 'discountValue' | 'currency' | SaleKeySpecifier)[];
|
||||
export type SaleKeySpecifier = ('id' | 'privateMetadata' | 'metadata' | 'name' | 'type' | 'startDate' | 'endDate' | 'created' | 'updatedAt' | 'categories' | 'collections' | 'products' | 'variants' | 'translation' | 'channelListings' | 'discountValue' | 'currency' | SaleKeySpecifier)[];
|
||||
export type SaleFieldPolicy = {
|
||||
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
privateMetadata?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
|
@ -3258,6 +3262,8 @@ export type SaleFieldPolicy = {
|
|||
type?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
startDate?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
endDate?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
created?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
updatedAt?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
categories?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
collections?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
products?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
|
@ -3770,7 +3776,7 @@ export type UploadErrorFieldPolicy = {
|
|||
message?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
code?: FieldPolicy<any> | FieldReadFunction<any>
|
||||
};
|
||||
export type UserKeySpecifier = ('id' | 'privateMetadata' | 'metadata' | 'email' | 'firstName' | 'lastName' | 'isStaff' | 'isActive' | 'addresses' | 'checkout' | 'checkoutTokens' | 'giftCards' | 'note' | 'orders' | 'userPermissions' | 'permissionGroups' | 'editableGroups' | 'avatar' | 'events' | 'storedPaymentSources' | 'languageCode' | 'defaultShippingAddress' | 'defaultBillingAddress' | 'lastLogin' | 'dateJoined' | UserKeySpecifier)[];
|
||||
export type UserKeySpecifier = ('id' | 'privateMetadata' | 'metadata' | 'email' | 'firstName' | 'lastName' | 'isStaff' | 'isActive' | 'addresses' | 'checkout' | 'checkoutTokens' | 'giftCards' | 'note' | 'orders' | 'userPermissions' | 'permissionGroups' | 'editableGroups' | 'avatar' | 'events' | 'storedPaymentSources' | 'languageCode' | 'defaultShippingAddress' | 'defaultBillingAddress' | 'lastLogin' | 'dateJoined' | 'updatedAt' | UserKeySpecifier)[];
|
||||
export type UserFieldPolicy = {
|
||||
id?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
privateMetadata?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
|
@ -3796,7 +3802,8 @@ export type UserFieldPolicy = {
|
|||
defaultShippingAddress?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
defaultBillingAddress?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
lastLogin?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
dateJoined?: FieldPolicy<any> | FieldReadFunction<any>
|
||||
dateJoined?: FieldPolicy<any> | FieldReadFunction<any>,
|
||||
updatedAt?: FieldPolicy<any> | FieldReadFunction<any>
|
||||
};
|
||||
export type UserAvatarDeleteKeySpecifier = ('user' | 'accountErrors' | 'errors' | UserAvatarDeleteKeySpecifier)[];
|
||||
export type UserAvatarDeleteFieldPolicy = {
|
||||
|
|
|
@ -29,12 +29,6 @@ export type Scalars = {
|
|||
* String, Boolean, Int, Float, List or Object.
|
||||
*/
|
||||
GenericScalar: any;
|
||||
/**
|
||||
* Allows use of a JSON String for input / output from the GraphQL schema.
|
||||
*
|
||||
* Use of this type is *not recommended* as you lose the benefits of having a defined, static
|
||||
* schema (one of the key benefits of GraphQL).
|
||||
*/
|
||||
JSONString: any;
|
||||
/**
|
||||
* Positive Decimal scalar implementation.
|
||||
|
@ -46,7 +40,7 @@ export type Scalars = {
|
|||
/** Variables of this type must be set to null in mutations. They will be replaced with a filename from a following multipart part containing a binary file. See: https://github.com/jaydenseric/graphql-multipart-request-spec. */
|
||||
Upload: any;
|
||||
WeightScalar: any;
|
||||
/** Anything */
|
||||
/** _Any value scalar as defined by Federation spec. */
|
||||
_Any: any;
|
||||
};
|
||||
|
||||
|
@ -1085,6 +1079,7 @@ export type CustomerFilterInput = {
|
|||
placedOrders?: InputMaybe<DateRangeInput>;
|
||||
search?: InputMaybe<Scalars['String']>;
|
||||
metadata?: InputMaybe<Array<InputMaybe<MetadataFilter>>>;
|
||||
updatedAt?: InputMaybe<DateTimeRangeInput>;
|
||||
};
|
||||
|
||||
export type CustomerInput = {
|
||||
|
@ -1292,12 +1287,10 @@ export type ExportFileFilterInput = {
|
|||
};
|
||||
|
||||
export enum ExportFileSortField {
|
||||
/** Sort export file by status. */
|
||||
STATUS = 'STATUS',
|
||||
/** Sort export file by created at. */
|
||||
CREATED_AT = 'CREATED_AT',
|
||||
/** Sort export file by updated at. */
|
||||
UPDATED_AT = 'UPDATED_AT'
|
||||
UPDATED_AT = 'UPDATED_AT',
|
||||
LAST_MODIFIED_AT = 'LAST_MODIFIED_AT'
|
||||
}
|
||||
|
||||
export type ExportFileSortingInput = {
|
||||
|
@ -1416,9 +1409,9 @@ export type GiftCardBulkCreateInput = {
|
|||
};
|
||||
|
||||
export type GiftCardCreateInput = {
|
||||
/** New in Saleor 3.1. The gift card tags to add. */
|
||||
/** New in Saleor 3.1. The gift card tags to add. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
addTags?: InputMaybe<Array<Scalars['String']>>;
|
||||
/** New in Saleor 3.1. The gift card expiry date. */
|
||||
/** New in Saleor 3.1. The gift card expiry date. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
expiryDate?: InputMaybe<Scalars['Date']>;
|
||||
/**
|
||||
* Start date of the gift card in ISO 8601 format.
|
||||
|
@ -1436,9 +1429,9 @@ export type GiftCardCreateInput = {
|
|||
balance: PriceInput;
|
||||
/** Email of the customer to whom gift card will be sent. */
|
||||
userEmail?: InputMaybe<Scalars['String']>;
|
||||
/** New in Saleor 3.1. Slug of a channel from which the email should be sent. */
|
||||
/** New in Saleor 3.1. Slug of a channel from which the email should be sent. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
channel?: InputMaybe<Scalars['String']>;
|
||||
/** New in Saleor 3.1. Determine if gift card is active. */
|
||||
/** New in Saleor 3.1. Determine if gift card is active. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
isActive: Scalars['Boolean'];
|
||||
/**
|
||||
* Code to use the gift card.
|
||||
|
@ -1446,7 +1439,7 @@ export type GiftCardCreateInput = {
|
|||
* DEPRECATED: this field will be removed in Saleor 4.0. The code is now auto generated.
|
||||
*/
|
||||
code?: InputMaybe<Scalars['String']>;
|
||||
/** New in Saleor 3.1. The gift card note from the staff member. */
|
||||
/** New in Saleor 3.1. The gift card note from the staff member. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
note?: InputMaybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
@ -1546,9 +1539,9 @@ export type GiftCardTagFilterInput = {
|
|||
};
|
||||
|
||||
export type GiftCardUpdateInput = {
|
||||
/** New in Saleor 3.1. The gift card tags to add. */
|
||||
/** New in Saleor 3.1. The gift card tags to add. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
addTags?: InputMaybe<Array<Scalars['String']>>;
|
||||
/** New in Saleor 3.1. The gift card expiry date. */
|
||||
/** New in Saleor 3.1. The gift card expiry date. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
expiryDate?: InputMaybe<Scalars['Date']>;
|
||||
/**
|
||||
* Start date of the gift card in ISO 8601 format.
|
||||
|
@ -1562,9 +1555,9 @@ export type GiftCardUpdateInput = {
|
|||
* DEPRECATED: this field will be removed in Saleor 4.0. Use `expiryDate` from `expirySettings` instead.
|
||||
*/
|
||||
endDate?: InputMaybe<Scalars['Date']>;
|
||||
/** New in Saleor 3.1. The gift card tags to remove. */
|
||||
/** New in Saleor 3.1. The gift card tags to remove. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
removeTags?: InputMaybe<Array<Scalars['String']>>;
|
||||
/** New in Saleor 3.1. The gift card balance amount. */
|
||||
/** New in Saleor 3.1. The gift card balance amount. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
balanceAmount?: InputMaybe<Scalars['PositiveDecimal']>;
|
||||
};
|
||||
|
||||
|
@ -2529,7 +2522,8 @@ export enum MetadataErrorCode {
|
|||
GRAPHQL_ERROR = 'GRAPHQL_ERROR',
|
||||
INVALID = 'INVALID',
|
||||
NOT_FOUND = 'NOT_FOUND',
|
||||
REQUIRED = 'REQUIRED'
|
||||
REQUIRED = 'REQUIRED',
|
||||
NOT_UPDATED = 'NOT_UPDATED'
|
||||
}
|
||||
|
||||
export type MetadataFilter = {
|
||||
|
@ -2719,6 +2713,7 @@ export type OrderFilterInput = {
|
|||
search?: InputMaybe<Scalars['String']>;
|
||||
metadata?: InputMaybe<Array<InputMaybe<MetadataFilter>>>;
|
||||
channels?: InputMaybe<Array<InputMaybe<Scalars['ID']>>>;
|
||||
updatedAt?: InputMaybe<DateTimeRangeInput>;
|
||||
isClickAndCollect?: InputMaybe<Scalars['Boolean']>;
|
||||
isPreorder?: InputMaybe<Scalars['Boolean']>;
|
||||
ids?: InputMaybe<Array<InputMaybe<Scalars['ID']>>>;
|
||||
|
@ -2839,8 +2834,20 @@ export type OrderSettingsUpdateInput = {
|
|||
export enum OrderSortField {
|
||||
/** Sort orders by number. */
|
||||
NUMBER = 'NUMBER',
|
||||
/** Sort orders by creation date. */
|
||||
/**
|
||||
* Sort orders by creation date.
|
||||
*
|
||||
* DEPRECATED: this field will be removed in Saleor 4.0.
|
||||
*/
|
||||
CREATION_DATE = 'CREATION_DATE',
|
||||
/**
|
||||
* Sort orders by creation date.
|
||||
*
|
||||
* DEPRECATED: this field will be removed in Saleor 4.0.
|
||||
*/
|
||||
CREATED_AT = 'CREATED_AT',
|
||||
/** Sort orders by last modified at. */
|
||||
LAST_MODIFIED_AT = 'LAST_MODIFIED_AT',
|
||||
/** Sort orders by customer. */
|
||||
CUSTOMER = 'CUSTOMER',
|
||||
/** Sort orders by payment. */
|
||||
|
@ -3343,6 +3350,7 @@ export type ProductFilterInput = {
|
|||
metadata?: InputMaybe<Array<InputMaybe<MetadataFilter>>>;
|
||||
price?: InputMaybe<PriceRangeInput>;
|
||||
minimalPrice?: InputMaybe<PriceRangeInput>;
|
||||
updatedAt?: InputMaybe<DateTimeRangeInput>;
|
||||
productTypes?: InputMaybe<Array<InputMaybe<Scalars['ID']>>>;
|
||||
giftCard?: InputMaybe<Scalars['Boolean']>;
|
||||
ids?: InputMaybe<Array<InputMaybe<Scalars['ID']>>>;
|
||||
|
@ -3430,6 +3438,8 @@ export enum ProductOrderField {
|
|||
/** Sort products by a minimal price of a product's variant. */
|
||||
MINIMAL_PRICE = 'MINIMAL_PRICE',
|
||||
/** Sort products by update date. */
|
||||
LAST_MODIFIED = 'LAST_MODIFIED',
|
||||
/** Sort products by update date. */
|
||||
DATE = 'DATE',
|
||||
/** Sort products by type. */
|
||||
TYPE = 'TYPE',
|
||||
|
@ -3437,6 +3447,10 @@ export enum ProductOrderField {
|
|||
PUBLISHED = 'PUBLISHED',
|
||||
/** Sort products by publication date. */
|
||||
PUBLICATION_DATE = 'PUBLICATION_DATE',
|
||||
/** Sort products by publication date. */
|
||||
PUBLISHED_AT = 'PUBLISHED_AT',
|
||||
/** Sort products by update date. */
|
||||
LAST_MODIFIED_AT = 'LAST_MODIFIED_AT',
|
||||
/** Sort products by collection. Note: This option is available only for the `Collection.products` query. */
|
||||
COLLECTION = 'COLLECTION',
|
||||
/** Sort products by rating. */
|
||||
|
@ -3521,9 +3535,9 @@ export type ProductVariantBulkCreateInput = {
|
|||
trackInventory?: InputMaybe<Scalars['Boolean']>;
|
||||
/** Weight of the Product Variant. */
|
||||
weight?: InputMaybe<Scalars['WeightScalar']>;
|
||||
/** New in Saleor 3.1. Determines if variant is in preorder. */
|
||||
/** New in Saleor 3.1. Determines if variant is in preorder. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
preorder?: InputMaybe<PreorderSettingsInput>;
|
||||
/** New in Saleor 3.1. Determines maximum quantity of `ProductVariant`,that can be bought in a single checkout. */
|
||||
/** New in Saleor 3.1. Determines maximum quantity of `ProductVariant`,that can be bought in a single checkout. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
quantityLimitPerCustomer?: InputMaybe<Scalars['Int']>;
|
||||
/** Stocks of a product available for sale. */
|
||||
stocks?: InputMaybe<Array<StockInput>>;
|
||||
|
@ -3538,7 +3552,7 @@ export type ProductVariantChannelListingAddInput = {
|
|||
price: Scalars['PositiveDecimal'];
|
||||
/** Cost price of the variant in channel. */
|
||||
costPrice?: InputMaybe<Scalars['PositiveDecimal']>;
|
||||
/** New in Saleor 3.1. The threshold for preorder variant in channel. */
|
||||
/** New in Saleor 3.1. The threshold for preorder variant in channel. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
preorderThreshold?: InputMaybe<Scalars['Int']>;
|
||||
};
|
||||
|
||||
|
@ -3551,9 +3565,9 @@ export type ProductVariantCreateInput = {
|
|||
trackInventory?: InputMaybe<Scalars['Boolean']>;
|
||||
/** Weight of the Product Variant. */
|
||||
weight?: InputMaybe<Scalars['WeightScalar']>;
|
||||
/** New in Saleor 3.1. Determines if variant is in preorder. */
|
||||
/** New in Saleor 3.1. Determines if variant is in preorder. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
preorder?: InputMaybe<PreorderSettingsInput>;
|
||||
/** New in Saleor 3.1. Determines maximum quantity of `ProductVariant`,that can be bought in a single checkout. */
|
||||
/** New in Saleor 3.1. Determines maximum quantity of `ProductVariant`,that can be bought in a single checkout. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
quantityLimitPerCustomer?: InputMaybe<Scalars['Int']>;
|
||||
/** Product ID of which type is the variant. */
|
||||
product: Scalars['ID'];
|
||||
|
@ -3566,6 +3580,7 @@ export type ProductVariantFilterInput = {
|
|||
sku?: InputMaybe<Array<InputMaybe<Scalars['String']>>>;
|
||||
metadata?: InputMaybe<Array<InputMaybe<MetadataFilter>>>;
|
||||
isPreorder?: InputMaybe<Scalars['Boolean']>;
|
||||
updatedAt?: InputMaybe<DateTimeRangeInput>;
|
||||
};
|
||||
|
||||
export type ProductVariantInput = {
|
||||
|
@ -3577,12 +3592,24 @@ export type ProductVariantInput = {
|
|||
trackInventory?: InputMaybe<Scalars['Boolean']>;
|
||||
/** Weight of the Product Variant. */
|
||||
weight?: InputMaybe<Scalars['WeightScalar']>;
|
||||
/** New in Saleor 3.1. Determines if variant is in preorder. */
|
||||
/** New in Saleor 3.1. Determines if variant is in preorder. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
preorder?: InputMaybe<PreorderSettingsInput>;
|
||||
/** New in Saleor 3.1. Determines maximum quantity of `ProductVariant`,that can be bought in a single checkout. */
|
||||
/** New in Saleor 3.1. Determines maximum quantity of `ProductVariant`,that can be bought in a single checkout. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
quantityLimitPerCustomer?: InputMaybe<Scalars['Int']>;
|
||||
};
|
||||
|
||||
export enum ProductVariantSortField {
|
||||
/** Sort products variants by last modified at. */
|
||||
LAST_MODIFIED_AT = 'LAST_MODIFIED_AT'
|
||||
}
|
||||
|
||||
export type ProductVariantSortingInput = {
|
||||
/** Specifies the direction in which to sort products. */
|
||||
direction: OrderDirection;
|
||||
/** Sort productVariants by the selected field. */
|
||||
field: ProductVariantSortField;
|
||||
};
|
||||
|
||||
export type PublishableChannelListingInput = {
|
||||
/** ID of a channel. */
|
||||
channelId: Scalars['ID'];
|
||||
|
@ -3624,6 +3651,7 @@ export type SaleFilterInput = {
|
|||
started?: InputMaybe<DateTimeRangeInput>;
|
||||
search?: InputMaybe<Scalars['String']>;
|
||||
metadata?: InputMaybe<Array<InputMaybe<MetadataFilter>>>;
|
||||
updatedAt?: InputMaybe<DateTimeRangeInput>;
|
||||
};
|
||||
|
||||
export type SaleInput = {
|
||||
|
@ -3656,7 +3684,11 @@ export enum SaleSortField {
|
|||
/** Sort sales by value. */
|
||||
VALUE = 'VALUE',
|
||||
/** Sort sales by type. */
|
||||
TYPE = 'TYPE'
|
||||
TYPE = 'TYPE',
|
||||
/** Sort sales by created at. */
|
||||
CREATED_AT = 'CREATED_AT',
|
||||
/** Sort sales by last modified at. */
|
||||
LAST_MODIFIED_AT = 'LAST_MODIFIED_AT'
|
||||
}
|
||||
|
||||
export type SaleSortingInput = {
|
||||
|
@ -3848,7 +3880,7 @@ export type ShopSettingsInput = {
|
|||
reserveStockDurationAnonymousUser?: InputMaybe<Scalars['Int']>;
|
||||
/** New in Saleor 3.1. Default number of minutes stock will be reserved for authenticated checkout. Enter 0 or null to disable. */
|
||||
reserveStockDurationAuthenticatedUser?: InputMaybe<Scalars['Int']>;
|
||||
/** New in Saleor 3.1. Default number of maximum line quantity in single checkout. Minimum possible value is 1, default value is 50. */
|
||||
/** New in Saleor 3.1. Default number of maximum line quantity in single checkout. Minimum possible value is 1, default value is 50. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
limitQuantityPerCheckout?: InputMaybe<Scalars['Int']>;
|
||||
};
|
||||
|
||||
|
@ -4058,7 +4090,11 @@ export enum UserSortField {
|
|||
/** Sort users by email. */
|
||||
EMAIL = 'EMAIL',
|
||||
/** Sort users by order count. */
|
||||
ORDER_COUNT = 'ORDER_COUNT'
|
||||
ORDER_COUNT = 'ORDER_COUNT',
|
||||
/** Sort users by created at. */
|
||||
CREATED_AT = 'CREATED_AT',
|
||||
/** Sort users by last modified at. */
|
||||
LAST_MODIFIED_AT = 'LAST_MODIFIED_AT'
|
||||
}
|
||||
|
||||
export type UserSortingInput = {
|
||||
|
@ -4251,9 +4287,9 @@ export type WarehouseUpdateInput = {
|
|||
name?: InputMaybe<Scalars['String']>;
|
||||
/** Address of the warehouse. */
|
||||
address?: InputMaybe<AddressInput>;
|
||||
/** New in Saleor 3.1. Click and collect options: local, all or disabled */
|
||||
/** New in Saleor 3.1. Click and collect options: local, all or disabled. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
clickAndCollectOption?: InputMaybe<WarehouseClickAndCollectOptionEnum>;
|
||||
/** New in Saleor 3.1. Visibility of warehouse stocks */
|
||||
/** New in Saleor 3.1. Visibility of warehouse stocks. Note: this feature is in a preview state and can be subject to changes at later point. */
|
||||
isPrivate?: InputMaybe<Scalars['Boolean']>;
|
||||
};
|
||||
|
||||
|
@ -4409,7 +4445,9 @@ export enum WebhookEventTypeEnum {
|
|||
PAYMENT_PROCESS = 'PAYMENT_PROCESS',
|
||||
PAYMENT_REFUND = 'PAYMENT_REFUND',
|
||||
PAYMENT_VOID = 'PAYMENT_VOID',
|
||||
SHIPPING_LIST_METHODS_FOR_CHECKOUT = 'SHIPPING_LIST_METHODS_FOR_CHECKOUT'
|
||||
SHIPPING_LIST_METHODS_FOR_CHECKOUT = 'SHIPPING_LIST_METHODS_FOR_CHECKOUT',
|
||||
ORDER_FILTER_SHIPPING_METHODS = 'ORDER_FILTER_SHIPPING_METHODS',
|
||||
CHECKOUT_FILTER_SHIPPING_METHODS = 'CHECKOUT_FILTER_SHIPPING_METHODS'
|
||||
}
|
||||
|
||||
/** Enum determining type of webhook. */
|
||||
|
@ -4421,7 +4459,9 @@ export enum WebhookEventTypeSyncEnum {
|
|||
PAYMENT_PROCESS = 'PAYMENT_PROCESS',
|
||||
PAYMENT_REFUND = 'PAYMENT_REFUND',
|
||||
PAYMENT_VOID = 'PAYMENT_VOID',
|
||||
SHIPPING_LIST_METHODS_FOR_CHECKOUT = 'SHIPPING_LIST_METHODS_FOR_CHECKOUT'
|
||||
SHIPPING_LIST_METHODS_FOR_CHECKOUT = 'SHIPPING_LIST_METHODS_FOR_CHECKOUT',
|
||||
ORDER_FILTER_SHIPPING_METHODS = 'ORDER_FILTER_SHIPPING_METHODS',
|
||||
CHECKOUT_FILTER_SHIPPING_METHODS = 'CHECKOUT_FILTER_SHIPPING_METHODS'
|
||||
}
|
||||
|
||||
/** An enumeration. */
|
||||
|
@ -6696,7 +6736,7 @@ export type ProductListQueryVariables = Exact<{
|
|||
}>;
|
||||
|
||||
|
||||
export type ProductListQuery = { __typename: 'Query', products: { __typename: 'ProductCountableConnection', totalCount: number | null, edges: Array<{ __typename: 'ProductCountableEdge', node: { __typename: 'Product', updatedAt: any | null, id: string, name: string, attributes?: Array<{ __typename: 'SelectedAttribute', attribute: { __typename: 'Attribute', id: string }, values: Array<{ __typename: 'AttributeValue', id: string, name: string | null, slug: string | null, reference: string | null, boolean: boolean | null, date: any | null, dateTime: any | null, value: string | null, file: { __typename: 'File', url: string, contentType: string | null } | null } | null> }>, thumbnail: { __typename: 'Image', url: string } | null, productType: { __typename: 'ProductType', id: string, name: string, hasVariants: boolean }, channelListings: Array<{ __typename: 'ProductChannelListing', isPublished: boolean, publicationDate: any | null, isAvailableForPurchase: boolean | null, availableForPurchase: any | null, visibleInListings: boolean, pricing?: { __typename: 'ProductPricingInfo', priceRange: { __typename: 'TaxedMoneyRange', start: { __typename: 'TaxedMoney', net: { __typename: 'Money', amount: number, currency: string } } | null, stop: { __typename: 'TaxedMoney', net: { __typename: 'Money', amount: number, currency: string } } | null } | null } | null, channel: { __typename: 'Channel', id: string, name: string, currencyCode: string } }> | null } }>, pageInfo: { __typename: 'PageInfo', hasPreviousPage: boolean, hasNextPage: boolean, startCursor: string | null, endCursor: string | null } } | null };
|
||||
export type ProductListQuery = { __typename: 'Query', products: { __typename: 'ProductCountableConnection', totalCount: number | null, edges: Array<{ __typename: 'ProductCountableEdge', node: { __typename: 'Product', updatedAt: any, id: string, name: string, attributes?: Array<{ __typename: 'SelectedAttribute', attribute: { __typename: 'Attribute', id: string }, values: Array<{ __typename: 'AttributeValue', id: string, name: string | null, slug: string | null, reference: string | null, boolean: boolean | null, date: any | null, dateTime: any | null, value: string | null, file: { __typename: 'File', url: string, contentType: string | null } | null } | null> }>, thumbnail: { __typename: 'Image', url: string } | null, productType: { __typename: 'ProductType', id: string, name: string, hasVariants: boolean }, channelListings: Array<{ __typename: 'ProductChannelListing', isPublished: boolean, publicationDate: any | null, isAvailableForPurchase: boolean | null, availableForPurchase: any | null, visibleInListings: boolean, pricing?: { __typename: 'ProductPricingInfo', priceRange: { __typename: 'TaxedMoneyRange', start: { __typename: 'TaxedMoney', net: { __typename: 'Money', amount: number, currency: string } } | null, stop: { __typename: 'TaxedMoney', net: { __typename: 'Money', amount: number, currency: string } } | null } | null } | null, channel: { __typename: 'Channel', id: string, name: string, currencyCode: string } }> | null } }>, pageInfo: { __typename: 'PageInfo', hasPreviousPage: boolean, hasNextPage: boolean, startCursor: string | null, endCursor: string | null } } | null };
|
||||
|
||||
export type ProductCountQueryVariables = Exact<{
|
||||
filter?: InputMaybe<ProductFilterInput>;
|
||||
|
|
|
@ -3,6 +3,7 @@ import CardTitle from "@saleor/components/CardTitle";
|
|||
import Hr from "@saleor/components/Hr";
|
||||
import {
|
||||
ConfigurationItemFragment,
|
||||
ConfigurationItemInput,
|
||||
ConfigurationTypeFieldEnum
|
||||
} from "@saleor/graphql";
|
||||
import { buttonMessages } from "@saleor/intl";
|
||||
|
@ -12,6 +13,7 @@ import React from "react";
|
|||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
interface PluginAuthorizationProps {
|
||||
data: ConfigurationItemInput[];
|
||||
fields: ConfigurationItemFragment[];
|
||||
onClear: (field: string) => void;
|
||||
onEdit: (field: string) => void;
|
||||
|
@ -37,7 +39,7 @@ const useStyles = makeStyles(
|
|||
);
|
||||
|
||||
const PluginAuthorization: React.FC<PluginAuthorizationProps> = props => {
|
||||
const { fields, onClear, onEdit } = props;
|
||||
const { data, fields, onClear, onEdit } = props;
|
||||
|
||||
const classes = useStyles(props);
|
||||
const intl = useIntl();
|
||||
|
@ -55,7 +57,12 @@ const PluginAuthorization: React.FC<PluginAuthorizationProps> = props => {
|
|||
})}
|
||||
/>
|
||||
<CardContent>
|
||||
{secretFields.map((field, fieldIndex) => (
|
||||
{secretFields.map((field, fieldIndex) => {
|
||||
const inputData = data.find(
|
||||
dataField => dataField.name === field.name
|
||||
);
|
||||
|
||||
return (
|
||||
<React.Fragment key={field.name}>
|
||||
<div className={classes.item} key={field.name}>
|
||||
{field.type === ConfigurationTypeFieldEnum.SECRET ||
|
||||
|
@ -63,7 +70,7 @@ const PluginAuthorization: React.FC<PluginAuthorizationProps> = props => {
|
|||
<div>
|
||||
<Typography variant="body1">{field.label}</Typography>
|
||||
{field.value !== null && (
|
||||
<Typography>**** {field.value}</Typography>
|
||||
<Typography>**** {inputData.value}</Typography>
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
|
@ -95,7 +102,8 @@ const PluginAuthorization: React.FC<PluginAuthorizationProps> = props => {
|
|||
<Hr className={classes.hr} />
|
||||
)}
|
||||
</React.Fragment>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
|
|
@ -55,7 +55,7 @@ const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = ({
|
|||
}) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const initialFormData = (): PluginDetailsPageFormData => ({
|
||||
const initialFormData: PluginDetailsPageFormData = {
|
||||
active: selectedConfig?.active,
|
||||
configuration: selectedConfig?.configuration
|
||||
?.filter(
|
||||
|
@ -65,14 +65,14 @@ const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = ({
|
|||
...field,
|
||||
value: field.value || ""
|
||||
}))
|
||||
});
|
||||
};
|
||||
|
||||
const selectedChannelId = selectedConfig?.channel?.id;
|
||||
|
||||
return (
|
||||
<Form
|
||||
confirmLeave
|
||||
initial={initialFormData()}
|
||||
initial={initialFormData}
|
||||
onSubmit={onSubmit}
|
||||
key={selectedChannelId}
|
||||
disabled={disabled}
|
||||
|
@ -82,23 +82,16 @@ const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = ({
|
|||
const { name, value } = event.target;
|
||||
const newData = {
|
||||
active: name === "active" ? value : data.active,
|
||||
configuration: data.configuration
|
||||
configuration: data.configuration.map(configItem =>
|
||||
configItem.name === name
|
||||
? {
|
||||
...configItem,
|
||||
value
|
||||
}
|
||||
: configItem
|
||||
)
|
||||
};
|
||||
|
||||
if (newData.configuration) {
|
||||
newData.configuration.map(item => {
|
||||
if (item.name === name) {
|
||||
item.value = value;
|
||||
}
|
||||
});
|
||||
|
||||
selectedConfig.configuration.map(item => {
|
||||
if (item.name === name) {
|
||||
item.value = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
set(newData);
|
||||
};
|
||||
return (
|
||||
|
@ -149,7 +142,8 @@ const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = ({
|
|||
<>
|
||||
<CardSpacer />
|
||||
<PluginAuthorization
|
||||
fields={selectedConfig?.configuration}
|
||||
data={data.configuration}
|
||||
fields={selectedConfig.configuration}
|
||||
onClear={onClear}
|
||||
onEdit={onEdit}
|
||||
/>
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import { OutputData } from "@editorjs/editorjs";
|
||||
import { ChannelShippingData } from "@saleor/channels/utils";
|
||||
import CardSpacer from "@saleor/components/CardSpacer";
|
||||
import ChannelsAvailabilityCard from "@saleor/components/ChannelsAvailabilityCard";
|
||||
import Container from "@saleor/components/Container";
|
||||
import Form, { FormDataWithOpts } from "@saleor/components/Form";
|
||||
import { WithFormId } from "@saleor/components/Form/ExitFormDialogProvider";
|
||||
import Grid from "@saleor/components/Grid";
|
||||
import PageHeader from "@saleor/components/PageHeader";
|
||||
|
@ -16,7 +14,8 @@ import {
|
|||
ShippingMethodTypeEnum,
|
||||
ShippingMethodTypeFragment
|
||||
} from "@saleor/graphql";
|
||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||
import useForm, { SubmitPromise } from "@saleor/hooks/useForm";
|
||||
import useHandleFormSubmit from "@saleor/hooks/useHandleFormSubmit";
|
||||
import { Backlink, ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
||||
import { validatePrice } from "@saleor/products/utils/validation";
|
||||
import OrderValue from "@saleor/shipping/components/OrderValue";
|
||||
|
@ -24,7 +23,8 @@ import OrderWeight from "@saleor/shipping/components/OrderWeight";
|
|||
import PricingCard from "@saleor/shipping/components/PricingCard";
|
||||
import ShippingRateInfo from "@saleor/shipping/components/ShippingRateInfo";
|
||||
import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
||||
import React from "react";
|
||||
import useRichText from "@saleor/utils/richText/useRichText";
|
||||
import React, { FormEventHandler } from "react";
|
||||
import { FormattedMessage, useIntl } from "react-intl";
|
||||
|
||||
import ShippingZonePostalCodes from "../ShippingZonePostalCodes";
|
||||
|
@ -86,36 +86,53 @@ export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePagePr
|
|||
type: null
|
||||
};
|
||||
|
||||
const checkIfSaveIsDisabled = (
|
||||
data: FormDataWithOpts<ShippingZoneRateCommonFormData>
|
||||
) => {
|
||||
const formDisabled = data.channelListings?.some(channel =>
|
||||
validatePrice(channel.price)
|
||||
);
|
||||
const {
|
||||
change,
|
||||
data: formData,
|
||||
hasChanged,
|
||||
setChanged,
|
||||
setIsSubmitDisabled,
|
||||
triggerChange
|
||||
} = useForm(initialForm, undefined, { confirmLeave: true, formId });
|
||||
|
||||
return disabled || formDisabled || (!data.hasChanged && !hasChannelChanged);
|
||||
const handleFormSubmit = useHandleFormSubmit({
|
||||
formId,
|
||||
onSubmit,
|
||||
setChanged
|
||||
});
|
||||
|
||||
const [description, changeDescription] = useRichText({
|
||||
initial: null,
|
||||
triggerChange
|
||||
});
|
||||
|
||||
// Prevents closing ref in submit functions
|
||||
const getData = () => ({
|
||||
...formData,
|
||||
description: description.current
|
||||
});
|
||||
const data = getData();
|
||||
|
||||
const handleFormElementSubmit: FormEventHandler = event => {
|
||||
event.preventDefault();
|
||||
handleFormSubmit(getData());
|
||||
};
|
||||
const handleSubmit = () => handleFormSubmit(getData());
|
||||
|
||||
return (
|
||||
<Form
|
||||
confirmLeave
|
||||
initial={initialForm}
|
||||
onSubmit={onSubmit}
|
||||
formId={formId}
|
||||
checkIfSaveIsDisabled={checkIfSaveIsDisabled}
|
||||
>
|
||||
{({ change, data, isSaveDisabled, submit, triggerChange, set }) => {
|
||||
const handleChannelsChange = createChannelsChangeHandler(
|
||||
shippingChannels,
|
||||
onChannelsChange,
|
||||
triggerChange
|
||||
);
|
||||
const onDescriptionChange = (description: OutputData) => {
|
||||
set({ description });
|
||||
triggerChange();
|
||||
};
|
||||
const formDisabled = data.channelListings?.some(channel =>
|
||||
validatePrice(channel.price)
|
||||
);
|
||||
const isSaveDisabled =
|
||||
disabled || formDisabled || (!hasChanged && !hasChannelChanged);
|
||||
setIsSubmitDisabled(isSaveDisabled);
|
||||
|
||||
return (
|
||||
<form onSubmit={handleFormElementSubmit}>
|
||||
<Container>
|
||||
<Backlink onClick={onBack}>
|
||||
<FormattedMessage defaultMessage="Shipping" />
|
||||
|
@ -140,7 +157,7 @@ export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePagePr
|
|||
disabled={disabled}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
onDescriptionChange={onDescriptionChange}
|
||||
onDescriptionChange={changeDescription}
|
||||
/>
|
||||
<CardSpacer />
|
||||
{isPriceVariant ? (
|
||||
|
@ -192,13 +209,11 @@ export const ShippingZoneRatesCreatePage: React.FC<ShippingZoneRatesCreatePagePr
|
|||
disabled={isSaveDisabled}
|
||||
onCancel={onBack}
|
||||
onDelete={onDelete}
|
||||
onSubmit={submit}
|
||||
onSubmit={handleSubmit}
|
||||
state={saveButtonBarState}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}}
|
||||
</Form>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
import { OutputData } from "@editorjs/editorjs";
|
||||
import { ChannelShippingData } from "@saleor/channels/utils";
|
||||
import CardSpacer from "@saleor/components/CardSpacer";
|
||||
import ChannelsAvailabilityCard from "@saleor/components/ChannelsAvailabilityCard";
|
||||
import Container from "@saleor/components/Container";
|
||||
import Form, { FormDataWithOpts } from "@saleor/components/Form";
|
||||
import { WithFormId } from "@saleor/components/Form/ExitFormDialogProvider";
|
||||
import Grid from "@saleor/components/Grid";
|
||||
import Metadata from "@saleor/components/Metadata/Metadata";
|
||||
|
@ -18,7 +16,8 @@ import {
|
|||
ShippingMethodTypeFragment,
|
||||
ShippingZoneQuery
|
||||
} from "@saleor/graphql";
|
||||
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||
import useForm, { SubmitPromise } from "@saleor/hooks/useForm";
|
||||
import useHandleFormSubmit from "@saleor/hooks/useHandleFormSubmit";
|
||||
import { Backlink, ConfirmButtonTransitionState } from "@saleor/macaw-ui";
|
||||
import { validatePrice } from "@saleor/products/utils/validation";
|
||||
import OrderValue from "@saleor/shipping/components/OrderValue";
|
||||
|
@ -30,7 +29,8 @@ import { createChannelsChangeHandler } from "@saleor/shipping/handlers";
|
|||
import { ListActions, ListProps } from "@saleor/types";
|
||||
import { mapEdgesToItems, mapMetadataItemToInput } from "@saleor/utils/maps";
|
||||
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
|
||||
import React from "react";
|
||||
import useRichText from "@saleor/utils/richText/useRichText";
|
||||
import React, { FormEventHandler } from "react";
|
||||
import { FormattedMessage } from "react-intl";
|
||||
|
||||
import ShippingZonePostalCodes from "../ShippingZonePostalCodes";
|
||||
|
@ -94,7 +94,7 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
|||
}) => {
|
||||
const isPriceVariant = variant === ShippingMethodTypeEnum.PRICE;
|
||||
|
||||
const initialForm: ShippingZoneRateUpdateFormData = {
|
||||
const initialForm: Omit<ShippingZoneRateUpdateFormData, "description"> = {
|
||||
channelListings: shippingChannels,
|
||||
maxDays: rate?.maximumDeliveryDays?.toString() || "",
|
||||
maxValue: rate?.maximumOrderWeight?.value.toString() || "",
|
||||
|
@ -102,50 +102,66 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
|||
minDays: rate?.minimumDeliveryDays?.toString() || "",
|
||||
minValue: rate?.minimumOrderWeight?.value.toString() || "",
|
||||
name: rate?.name || "",
|
||||
description: rate?.description && JSON.parse(rate.description),
|
||||
orderValueRestricted: !!rate?.channelListings.length,
|
||||
privateMetadata: rate?.privateMetadata.map(mapMetadataItemToInput),
|
||||
type: rate?.type || null
|
||||
};
|
||||
|
||||
const {
|
||||
change,
|
||||
data: formData,
|
||||
hasChanged,
|
||||
setChanged,
|
||||
setIsSubmitDisabled,
|
||||
triggerChange
|
||||
} = useForm(initialForm, undefined, { confirmLeave: true, formId });
|
||||
|
||||
const handleFormSubmit = useHandleFormSubmit({
|
||||
formId,
|
||||
onSubmit,
|
||||
setChanged
|
||||
});
|
||||
|
||||
const [description, changeDescription] = useRichText({
|
||||
initial: rate?.description,
|
||||
triggerChange
|
||||
});
|
||||
|
||||
const {
|
||||
makeChangeHandler: makeMetadataChangeHandler
|
||||
} = useMetadataChangeTrigger();
|
||||
|
||||
const checkIfSaveIsDisabled = (
|
||||
data: FormDataWithOpts<ShippingZoneRateUpdateFormData>
|
||||
) => {
|
||||
const formDisabled = data.channelListings?.some(channel =>
|
||||
validatePrice(channel.price)
|
||||
);
|
||||
const formIsUnchanged =
|
||||
!data.hasChanged && !hasChannelChanged && !havePostalCodesChanged;
|
||||
// Prevents closing ref in submit functions
|
||||
const getData = () => ({
|
||||
...formData,
|
||||
description: description.current
|
||||
});
|
||||
const data = getData();
|
||||
|
||||
return disabled || formDisabled || formIsUnchanged;
|
||||
const handleFormElementSubmit: FormEventHandler = event => {
|
||||
event.preventDefault();
|
||||
handleFormSubmit(getData());
|
||||
};
|
||||
const handleSubmit = () => handleFormSubmit(getData());
|
||||
|
||||
return (
|
||||
<Form
|
||||
confirmLeave
|
||||
initial={initialForm}
|
||||
onSubmit={onSubmit}
|
||||
formId={formId}
|
||||
checkIfSaveIsDisabled={checkIfSaveIsDisabled}
|
||||
>
|
||||
{({ change, data, isSaveDisabled, submit, set, triggerChange }) => {
|
||||
const handleChannelsChange = createChannelsChangeHandler(
|
||||
shippingChannels,
|
||||
onChannelsChange,
|
||||
triggerChange
|
||||
);
|
||||
const onDescriptionChange = (description: OutputData) => {
|
||||
set({ description });
|
||||
triggerChange();
|
||||
};
|
||||
const formDisabled = formData.channelListings?.some(channel =>
|
||||
validatePrice(channel.price)
|
||||
);
|
||||
|
||||
const changeMetadata = makeMetadataChangeHandler(change);
|
||||
const formIsUnchanged =
|
||||
!hasChanged && !hasChannelChanged && !havePostalCodesChanged;
|
||||
|
||||
const isSaveDisabled = disabled || formDisabled || formIsUnchanged;
|
||||
setIsSubmitDisabled(isSaveDisabled);
|
||||
|
||||
return (
|
||||
<form onSubmit={handleFormElementSubmit}>
|
||||
<Container>
|
||||
<Backlink onClick={onBack}>
|
||||
<FormattedMessage defaultMessage="Shipping" />
|
||||
|
@ -158,7 +174,7 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
|||
disabled={disabled}
|
||||
errors={errors}
|
||||
onChange={change}
|
||||
onDescriptionChange={onDescriptionChange}
|
||||
onDescriptionChange={changeDescription}
|
||||
/>
|
||||
<CardSpacer />
|
||||
{isPriceVariant ? (
|
||||
|
@ -223,13 +239,11 @@ export const ShippingZoneRatesPage: React.FC<ShippingZoneRatesPageProps> = ({
|
|||
disabled={isSaveDisabled}
|
||||
onCancel={onBack}
|
||||
onDelete={onDelete}
|
||||
onSubmit={submit}
|
||||
onSubmit={handleSubmit}
|
||||
state={saveButtonBarState}
|
||||
/>
|
||||
</Container>
|
||||
);
|
||||
}}
|
||||
</Form>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -224,7 +224,11 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
|
|||
confirmButtonState={deleteResult.status}
|
||||
variant="delete"
|
||||
onClose={closeModal}
|
||||
onConfirm={deleteStaffMember}
|
||||
onConfirm={() =>
|
||||
deleteStaffMember({
|
||||
variables: { id }
|
||||
})
|
||||
}
|
||||
>
|
||||
<DialogContentText>
|
||||
<FormattedMessage
|
||||
|
|
Loading…
Reference in a new issue