Pass promise to reset form state

This commit is contained in:
dominik-zeglen 2020-10-22 13:33:29 +02:00
parent dfb2258406
commit a27a029452
47 changed files with 484 additions and 432 deletions

View file

@ -42,7 +42,7 @@ export interface CustomAppDetailsPageProps {
onTokenDelete: (id: string) => void;
onTokenClose: () => void;
onTokenCreate: () => void;
onSubmit: (data: CustomAppDetailsPageFormData) => void;
onSubmit: (data: CustomAppDetailsPageFormData) => Promise<any>;
onWebhookCreate: () => void;
onWebhookRemove: (id: string) => void;
navigateToWebhookDetails: (id: string) => () => void;

View file

@ -130,8 +130,8 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
onCompleted: onTokenDelete
});
const handleSubmit = (data: CustomAppDetailsPageFormData) =>
updateApp({
const handleSubmit = async (data: CustomAppDetailsPageFormData) => {
const result = await updateApp({
variables: {
id,
input: {
@ -144,6 +144,9 @@ export const CustomAppDetails: React.FC<OrderListProps> = ({
}
});
return result.data.appUpdate.errors;
};
const handleTokenCreate = (name: string) =>
createToken({
variables: {

View file

@ -126,7 +126,7 @@ const AttributePage: React.FC<AttributePageProps> = ({
? data.privateMetadata
: undefined;
onSubmit({
return onSubmit({
...data,
metadata,
privateMetadata,

View file

@ -61,7 +61,7 @@ export interface CategoryUpdatePageProps
};
saveButtonBarState: ConfirmButtonTransitionState;
onImageDelete: () => void;
onSubmit: (data: FormData) => void;
onSubmit: (data: FormData) => Promise<any[]>;
onImageUpload(file: File);
onNextPage();
onPreviousPage();
@ -139,7 +139,7 @@ export const CategoryUpdatePage: React.FC<CategoryUpdatePageProps> = ({
? data.privateMetadata
: undefined;
onSubmit({
return onSubmit({
...data,
metadata,
privateMetadata

View file

@ -81,7 +81,7 @@ const CollectionDetailsPage: React.FC<CollectionDetailsPageProps> = ({
? data.privateMetadata
: undefined;
onSubmit({
return onSubmit({
...data,
isPublished: data.isPublished || !!data.publicationDate,
metadata,

View file

@ -33,7 +33,7 @@ export interface CustomerDetailsPageProps {
errors: AccountErrorFragment[];
saveButtonBar: ConfirmButtonTransitionState;
onBack: () => void;
onSubmit: (data: CustomerDetailsPageFormData) => void;
onSubmit: (data: CustomerDetailsPageFormData) => Promise<any[]>;
onViewAllOrdersClick: () => void;
onRowClick: (id: string) => void;
onAddressManageClick: () => void;

View file

@ -10,7 +10,9 @@ import { FormattedMessage, useIntl } from "react-intl";
import { maybe } from "../../misc";
import { orderListUrl, orderUrl } from "../../orders/urls";
import CustomerDetailsPage from "../components/CustomerDetailsPage/CustomerDetailsPage";
import CustomerDetailsPage, {
CustomerDetailsPageFormData
} from "../components/CustomerDetailsPage/CustomerDetailsPage";
import {
TypedRemoveCustomerMutation,
TypedUpdateCustomerMutation
@ -76,6 +78,25 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
return <NotFoundPage onBack={handleBack} />;
}
const handleSubmit = async (
data: CustomerDetailsPageFormData
) => {
const result = await updateCustomer({
variables: {
id,
input: {
email: data.email,
firstName: data.firstName,
isActive: data.isActive,
lastName: data.lastName,
note: data.note
}
}
});
return result.data.customerUpdate.errors;
};
return (
<>
<WindowTitle
@ -97,20 +118,7 @@ export const CustomerDetailsView: React.FC<CustomerDetailsViewProps> = ({
}
onBack={handleBack}
onRowClick={id => navigate(orderUrl(id))}
onSubmit={formData =>
updateCustomer({
variables: {
id,
input: {
email: formData.email,
firstName: formData.firstName,
isActive: formData.isActive,
lastName: formData.lastName,
note: formData.note
}
}
})
}
onSubmit={handleSubmit}
onDelete={() =>
navigate(
customerUrl(id, {

View file

@ -25,7 +25,7 @@ import SaleSummary from "../SaleSummary";
import SaleType from "../SaleType";
import SaleValue from "../SaleValue";
export interface FormData {
export interface SaleDetailsPageFormData {
endDate: string;
endTime: string;
hasEndDate: boolean;
@ -70,7 +70,7 @@ export interface SaleDetailsPageProps
onProductUnassign: (id: string) => void;
onProductClick: (id: string) => () => void;
onRemove: () => void;
onSubmit: (data: FormData) => void;
onSubmit: (data: SaleDetailsPageFormData) => void;
onTabClick: (index: SaleDetailsPageTab) => void;
}
@ -111,7 +111,7 @@ const SaleDetailsPage: React.FC<SaleDetailsPageProps> = ({
}) => {
const intl = useIntl();
const initialForm: FormData = {
const initialForm: SaleDetailsPageFormData = {
endDate: splitDateTime(maybe(() => sale.endDate, "")).date,
endTime: splitDateTime(maybe(() => sale.endDate, "")).time,
hasEndDate: maybe(() => !!sale.endDate),

View file

@ -9,10 +9,10 @@ import getDiscountErrorMessage from "@saleor/utils/errors/discounts";
import React from "react";
import { useIntl } from "react-intl";
import { FormData } from "../SaleDetailsPage";
import { SaleDetailsPageFormData } from "../SaleDetailsPage";
export interface SaleInfoProps {
data: FormData;
data: SaleDetailsPageFormData;
disabled: boolean;
errors: DiscountErrorFragment[];
onChange: (event: React.ChangeEvent<any>) => void;
@ -38,7 +38,7 @@ const SaleInfo: React.FC<SaleInfoProps> = ({
disabled={disabled}
error={!!formErrors.name}
helperText={getDiscountErrorMessage(formErrors.name, intl)}
name={"name" as keyof FormData}
name={"name" as keyof SaleDetailsPageFormData}
onChange={onChange}
label={intl.formatMessage({
defaultMessage: "Name",

View file

@ -10,10 +10,10 @@ import { SaleType as SaleTypeEnum } from "@saleor/types/globalTypes";
import React from "react";
import { IntlShape, useIntl } from "react-intl";
import { FormData } from "../SaleDetailsPage";
import { SaleDetailsPageFormData } from "../SaleDetailsPage";
export interface SaleTypeProps {
data: FormData;
data: SaleDetailsPageFormData;
disabled: boolean;
onChange: FormChange;
}
@ -70,7 +70,7 @@ const SaleType: React.FC<SaleTypeProps> = props => {
<RadioGroupField
choices={choices}
disabled={disabled}
name={"type" as keyof FormData}
name={"type" as keyof SaleDetailsPageFormData}
value={data.type}
onChange={onChange}
/>

View file

@ -10,11 +10,11 @@ import getDiscountErrorMessage from "@saleor/utils/errors/discounts";
import React from "react";
import { useIntl } from "react-intl";
import { FormData } from "../SaleDetailsPage";
import { SaleDetailsPageFormData } from "../SaleDetailsPage";
export interface SaleValueProps {
currencySymbol: string;
data: FormData;
data: SaleDetailsPageFormData;
disabled: boolean;
errors: DiscountErrorFragment[];
onChange: FormChange;

View file

@ -11,10 +11,10 @@ import getDiscountErrorMessage from "@saleor/utils/errors/discounts";
import React from "react";
import { useIntl } from "react-intl";
import { FormData } from "../VoucherDetailsPage";
import { VoucherDetailsPageFormData } from "../VoucherDetailsPage";
interface VoucherDatesProps {
data: FormData;
data: VoucherDetailsPageFormData;
defaultCurrency: string;
disabled: boolean;
errors: DiscountErrorFragment[];
@ -45,7 +45,7 @@ const VoucherDates = ({
disabled={disabled}
error={!!formErrors.startDate}
helperText={getDiscountErrorMessage(formErrors.startDate, intl)}
name={"startDate" as keyof FormData}
name={"startDate" as keyof VoucherDetailsPageFormData}
onChange={onChange}
label={intl.formatMessage(commonMessages.startDate)}
value={data.startDate}
@ -59,7 +59,7 @@ const VoucherDates = ({
disabled={disabled}
error={!!formErrors.startDate}
helperText={getDiscountErrorMessage(formErrors.startDate, intl)}
name={"startTime" as keyof FormData}
name={"startTime" as keyof VoucherDetailsPageFormData}
onChange={onChange}
label={intl.formatMessage(commonMessages.startHour)}
value={data.startTime}
@ -76,7 +76,7 @@ const VoucherDates = ({
defaultMessage: "Set end date",
description: "voucher end date, switch button"
})}
name={"hasEndDate" as keyof FormData}
name={"hasEndDate" as keyof VoucherDetailsPageFormData}
onChange={onChange}
/>
{data.hasEndDate && (
@ -85,7 +85,7 @@ const VoucherDates = ({
disabled={disabled}
error={!!formErrors.endDate}
helperText={getDiscountErrorMessage(formErrors.endDate, intl)}
name={"endDate" as keyof FormData}
name={"endDate" as keyof VoucherDetailsPageFormData}
onChange={onChange}
label={intl.formatMessage(commonMessages.endDate)}
value={data.endDate}
@ -99,7 +99,7 @@ const VoucherDates = ({
disabled={disabled}
error={!!formErrors.endDate}
helperText={getDiscountErrorMessage(formErrors.endDate, intl)}
name={"endTime" as keyof FormData}
name={"endTime" as keyof VoucherDetailsPageFormData}
onChange={onChange}
label={intl.formatMessage(commonMessages.endHour)}
value={data.endTime}

View file

@ -47,7 +47,7 @@ export function voucherDetailsPageTab(tab: string): VoucherDetailsPageTab {
: VoucherDetailsPageTab.categories;
}
export interface FormData {
export interface VoucherDetailsPageFormData {
applyOncePerCustomer: boolean;
applyOncePerOrder: boolean;
code: string;
@ -89,7 +89,7 @@ export interface VoucherDetailsPageProps
onProductUnassign: (id: string) => void;
onProductClick: (id: string) => () => void;
onRemove: () => void;
onSubmit: (data: FormData) => void;
onSubmit: (data: VoucherDetailsPageFormData) => void;
onTabClick: (index: VoucherDetailsPageTab) => void;
}
@ -141,7 +141,7 @@ const VoucherDetailsPage: React.FC<VoucherDetailsPageProps> = ({
requirementsPickerInitValue = RequirementsPicker.NONE;
}
const initialForm: FormData = {
const initialForm: VoucherDetailsPageFormData = {
applyOncePerCustomer: maybe(() => voucher.applyOncePerCustomer, false),
applyOncePerOrder: maybe(() => voucher.applyOncePerOrder, false),
code: maybe(() => voucher.code, ""),

View file

@ -11,10 +11,10 @@ import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import { generateCode } from "../../../misc";
import { FormData } from "../VoucherDetailsPage";
import { VoucherDetailsPageFormData } from "../VoucherDetailsPage";
interface VoucherInfoProps {
data: FormData;
data: VoucherDetailsPageFormData;
errors: DiscountErrorFragment[];
disabled: boolean;
variant: "create" | "update";
@ -61,7 +61,7 @@ const VoucherInfo = ({
error={!!formErrors.code}
fullWidth
helperText={getDiscountErrorMessage(formErrors.code, intl)}
name={"code" as keyof FormData}
name={"code" as keyof VoucherDetailsPageFormData}
label={intl.formatMessage({
defaultMessage: "Discount Code"
})}

View file

@ -9,10 +9,10 @@ import getDiscountErrorMessage from "@saleor/utils/errors/discounts";
import React from "react";
import { useIntl } from "react-intl";
import { FormData } from "../VoucherDetailsPage";
import { VoucherDetailsPageFormData } from "../VoucherDetailsPage";
interface VoucherLimitsProps {
data: FormData;
data: VoucherDetailsPageFormData;
defaultCurrency: string;
disabled: boolean;
errors: DiscountErrorFragment[];
@ -44,7 +44,7 @@ const VoucherLimits = ({
defaultMessage:
"Limit number of times this discount can be used in total"
})}
name={"hasUsageLimit" as keyof FormData}
name={"hasUsageLimit" as keyof VoucherDetailsPageFormData}
onChange={onChange}
/>
{data.hasUsageLimit && (
@ -56,7 +56,7 @@ const VoucherLimits = ({
defaultMessage: "Limit of Uses",
description: "voucher"
})}
name={"usageLimit" as keyof FormData}
name={"usageLimit" as keyof VoucherDetailsPageFormData}
value={data.usageLimit}
onChange={onChange}
type="number"
@ -72,7 +72,7 @@ const VoucherLimits = ({
defaultMessage: "Limit to one use per customer",
description: "limit voucher"
})}
name={"applyOncePerCustomer" as keyof FormData}
name={"applyOncePerCustomer" as keyof VoucherDetailsPageFormData}
onChange={onChange}
/>
</CardContent>

View file

@ -11,10 +11,10 @@ import getDiscountErrorMessage from "@saleor/utils/errors/discounts";
import React from "react";
import { useIntl } from "react-intl";
import { FormData } from "../VoucherDetailsPage";
import { VoucherDetailsPageFormData } from "../VoucherDetailsPage";
interface VoucherRequirementsProps {
data: FormData;
data: VoucherDetailsPageFormData;
defaultCurrency: string;
disabled: boolean;
errors: DiscountErrorFragment[];
@ -73,7 +73,7 @@ const VoucherRequirements = ({
<RadioGroupField
choices={requirementsPickerChoices}
disabled={disabled}
name={"requirementsPicker" as keyof FormData}
name={"requirementsPicker" as keyof VoucherDetailsPageFormData}
value={data.requirementsPicker}
onChange={onChange}
/>
@ -86,7 +86,7 @@ const VoucherRequirements = ({
error={!!formErrors.minSpent}
helperText={getDiscountErrorMessage(formErrors.minSpent, intl)}
label={minimalOrderValueText}
name={"minSpent" as keyof FormData}
name={"minSpent" as keyof VoucherDetailsPageFormData}
value={data.minSpent}
onChange={onChange}
fullWidth
@ -100,7 +100,9 @@ const VoucherRequirements = ({
intl
)}
label={minimalQuantityText}
name={"minCheckoutItemsQuantity" as keyof FormData}
name={
"minCheckoutItemsQuantity" as keyof VoucherDetailsPageFormData
}
value={data.minCheckoutItemsQuantity}
onChange={onChange}
fullWidth

View file

@ -10,10 +10,10 @@ import React from "react";
import { useIntl } from "react-intl";
import { DiscountValueTypeEnum } from "../../../types/globalTypes";
import { FormData } from "../VoucherDetailsPage";
import { VoucherDetailsPageFormData } from "../VoucherDetailsPage";
interface VoucherTypesProps {
data: FormData;
data: VoucherDetailsPageFormData;
errors: DiscountErrorFragment[];
disabled: boolean;
onChange: (event: React.ChangeEvent<any>) => void;
@ -68,7 +68,7 @@ const VoucherTypes = ({
disabled={disabled}
error={!!formErrors.discountType}
hint={getDiscountErrorMessage(formErrors.discountType, intl)}
name={"discountType" as keyof FormData}
name={"discountType" as keyof VoucherDetailsPageFormData}
value={data.discountType}
onChange={onChange}
/>

View file

@ -16,10 +16,10 @@ import { FormattedMessage, useIntl } from "react-intl";
import { DiscountValueTypeEnum } from "../../../types/globalTypes";
import { translateVoucherTypes } from "../../translations";
import { FormData } from "../VoucherDetailsPage";
import { VoucherDetailsPageFormData } from "../VoucherDetailsPage";
interface VoucherValueProps {
data: FormData;
data: VoucherDetailsPageFormData;
defaultCurrency: string;
errors: DiscountErrorFragment[];
disabled: boolean;
@ -74,11 +74,11 @@ const VoucherValue: React.FC<VoucherValueProps> = props => {
data.discountType === DiscountValueTypeEnum.FIXED
? defaultCurrency
: "%",
name: "discountType" as keyof FormData,
name: "discountType" as keyof VoucherDetailsPageFormData,
values: null
}}
helperText={getDiscountErrorMessage(formErrors.discountValue, intl)}
name={"value" as keyof FormData}
name={"value" as keyof VoucherDetailsPageFormData}
onChange={onChange}
label={intl.formatMessage({
defaultMessage: "Discount Value"
@ -102,7 +102,7 @@ const VoucherValue: React.FC<VoucherValueProps> = props => {
label={intl.formatMessage({
defaultMessage: "Voucher Specific Information"
})}
name={"type" as keyof FormData}
name={"type" as keyof VoucherDetailsPageFormData}
value={data.type}
onChange={onChange}
/>
@ -111,7 +111,7 @@ const VoucherValue: React.FC<VoucherValueProps> = props => {
<Hr className={classes.hr} />
<FormSpacer />
<ControlledCheckbox
name={"applyOncePerOrder" as keyof FormData}
name={"applyOncePerOrder" as keyof VoucherDetailsPageFormData}
label={
<>
<FormattedMessage

View file

@ -27,6 +27,7 @@ import { decimal, joinDateTime, maybe } from "../../misc";
import { productUrl } from "../../products/urls";
import { DiscountValueTypeEnum, SaleType } from "../../types/globalTypes";
import SaleDetailsPage, {
SaleDetailsPageFormData,
SaleDetailsPageTab
} from "../components/SaleDetailsPage";
import {
@ -192,6 +193,30 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
}
});
const handleSubmit = async (
data: SaleDetailsPageFormData
) => {
const result = await saleUpdate({
variables: {
id,
input: {
endDate: data.hasEndDate
? joinDateTime(data.endDate, data.endTime)
: null,
name: data.name,
startDate: joinDateTime(
data.startDate,
data.startTime
),
type: discountValueTypeEnum(data.type),
value: decimal(data.value)
}
}
});
return result.data.saleUpdate.errors;
};
const {
loadNextPage,
loadPreviousPage,
@ -244,30 +269,7 @@ export const SaleDetails: React.FC<SaleDetailsProps> = ({ id, params }) => {
activeTab={params.activeTab}
onBack={() => navigate(saleListUrl())}
onTabClick={changeTab}
onSubmit={formData =>
saleUpdate({
variables: {
id,
input: {
endDate: formData.hasEndDate
? joinDateTime(
formData.endDate,
formData.endTime
)
: null,
name: formData.name,
startDate: joinDateTime(
formData.startDate,
formData.startTime
),
type: discountValueTypeEnum(
formData.type
),
value: decimal(formData.value)
}
}
})
}
onSubmit={handleSubmit}
onRemove={() => openModal("remove")}
saveButtonBarState={saleUpdateOpts.status}
categoryListToolbar={

View file

@ -31,6 +31,7 @@ import {
} from "../../types/globalTypes";
import DiscountCountrySelectDialog from "../components/DiscountCountrySelectDialog";
import VoucherDetailsPage, {
VoucherDetailsPageFormData,
VoucherDetailsPageTab
} from "../components/VoucherDetailsPage";
import {
@ -195,6 +196,54 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
}
});
const handleSubmit = async (
data: VoucherDetailsPageFormData
) => {
const result = await voucherUpdate({
variables: {
id,
input: {
applyOncePerCustomer: data.applyOncePerCustomer,
applyOncePerOrder: data.applyOncePerOrder,
discountValue:
data.discountType.toString() === "SHIPPING"
? 100
: decimal(data.value),
discountValueType:
data.discountType.toString() === "SHIPPING"
? DiscountValueTypeEnum.PERCENTAGE
: data.discountType,
endDate: data.hasEndDate
? joinDateTime(data.endDate, data.endTime)
: null,
minAmountSpent:
data.requirementsPicker !==
RequirementsPicker.ORDER
? 0
: parseFloat(data.minSpent),
minCheckoutItemsQuantity:
data.requirementsPicker !==
RequirementsPicker.ITEM
? 0
: parseFloat(data.minCheckoutItemsQuantity),
startDate: joinDateTime(
data.startDate,
data.startTime
),
type:
data.discountType.toString() === "SHIPPING"
? VoucherTypeEnum.SHIPPING
: data.type,
usageLimit: data.hasUsageLimit
? parseInt(data.usageLimit, 10)
: null
}
}
});
return result.data.voucherUpdate.errors;
};
const {
loadNextPage,
loadPreviousPage,
@ -291,59 +340,7 @@ export const VoucherDetails: React.FC<VoucherDetailsProps> = ({
activeTab={params.activeTab}
onBack={() => navigate(voucherListUrl())}
onTabClick={changeTab}
onSubmit={formData =>
voucherUpdate({
variables: {
id,
input: {
applyOncePerCustomer:
formData.applyOncePerCustomer,
applyOncePerOrder:
formData.applyOncePerOrder,
discountValue:
formData.discountType.toString() ===
"SHIPPING"
? 100
: decimal(formData.value),
discountValueType:
formData.discountType.toString() ===
"SHIPPING"
? DiscountValueTypeEnum.PERCENTAGE
: formData.discountType,
endDate: formData.hasEndDate
? joinDateTime(
formData.endDate,
formData.endTime
)
: null,
minAmountSpent:
formData.requirementsPicker !==
RequirementsPicker.ORDER
? 0
: parseFloat(formData.minSpent),
minCheckoutItemsQuantity:
formData.requirementsPicker !==
RequirementsPicker.ITEM
? 0
: parseFloat(
formData.minCheckoutItemsQuantity
),
startDate: joinDateTime(
formData.startDate,
formData.startTime
),
type:
formData.discountType.toString() ===
"SHIPPING"
? VoucherTypeEnum.SHIPPING
: formData.type,
usageLimit: formData.hasUsageLimit
? parseInt(formData.usageLimit, 10)
: null
}
}
})
}
onSubmit={handleSubmit}
onRemove={() => openModal("remove")}
saveButtonBarState={voucherUpdateOpts.status}
categoryListToolbar={

View file

@ -5,14 +5,14 @@ import { AccountErrorCode, AddressInput } from "@saleor/types/globalTypes";
import { add, remove } from "@saleor/utils/lists";
import { useState } from "react";
interface UseAddressValidation<T> {
interface UseAddressValidation<TInput, TOutput> {
errors: AccountErrorFragment[];
submit: (data: T & AddressTypeInput) => void;
submit: (data: TInput & AddressTypeInput) => TOutput;
}
function useAddressValidation<T>(
onSubmit: (address: T & AddressInput) => void
): UseAddressValidation<T> {
function useAddressValidation<TInput, TOutput>(
onSubmit: (address: TInput & AddressInput) => TOutput
): UseAddressValidation<TInput, TOutput> {
const [validationErrors, setValidationErrors] = useState<
AccountErrorFragment[]
>([]);
@ -25,7 +25,7 @@ function useAddressValidation<T>(
return {
errors: validationErrors,
submit: (data: T & AddressTypeInput) => {
submit: (data: TInput & AddressTypeInput) => {
try {
setValidationErrors(
remove(
@ -34,7 +34,7 @@ function useAddressValidation<T>(
(a, b) => a.field === b.field
)
);
onSubmit(transformFormToAddress(data));
return onSubmit(transformFormToAddress(data));
} catch {
setValidationErrors(add(countryRequiredError, validationErrors));
}

View file

@ -51,7 +51,7 @@ function handleRefresh<T extends FormData>(
function useForm<T extends FormData>(
initial: T,
onSubmit?: (data: T) => void
onSubmit?: (data: T) => Promise<any[]> | void
): UseFormResult<T> {
const [hasChanged, setChanged] = useState(false);
const [data, setData] = useStateFromProps(initial, {
@ -106,9 +106,15 @@ function useForm<T extends FormData>(
}));
}
function submit() {
async function submit() {
if (typeof onSubmit === "function") {
onSubmit(data);
const result = onSubmit(data);
if (result) {
const errors = await result;
if (errors.length === 0) {
setChanged(false);
}
}
}
}

View file

@ -36,7 +36,7 @@ export interface MenuDetailsPageProps {
onItemAdd: () => void;
onItemClick: (id: string, type: MenuItemType) => void;
onItemEdit: (id: string) => void;
onSubmit: (data: MenuDetailsSubmitData) => Promise<boolean>;
onSubmit: (data: MenuDetailsSubmitData) => Promise<any[]>;
}
const MenuDetailsPage: React.FC<MenuDetailsPageProps> = ({
@ -62,14 +62,16 @@ const MenuDetailsPage: React.FC<MenuDetailsPageProps> = ({
);
const handleSubmit = async (data: MenuDetailsFormData) => {
if (
await onSubmit({
name: data.name,
operations: treeOperations
})
) {
const result = await onSubmit({
name: data.name,
operations: treeOperations
});
if (result) {
setTreeOperations([]);
}
return result;
};
const handleChange = (operation: TreeOperation) => {

View file

@ -141,28 +141,20 @@ const MenuDetails: React.FC<MenuDetailsProps> = ({ id, params }) => {
// that it should clean operation stack if mutations
// were successful
const handleSubmit = async (data: MenuDetailsSubmitData) => {
try {
const result = await menuUpdate({
variables: {
id,
moves: getMoves(data),
name: data.name,
removeIds: getRemoveIds(data)
}
});
if (result) {
if (
result.data.menuItemBulkDelete.errors.length > 0 ||
result.data.menuItemMove.errors.length > 0 ||
result.data.menuUpdate.errors.length > 0
) {
return false;
}
const result = await menuUpdate({
variables: {
id,
moves: getMoves(data),
name: data.name,
removeIds: getRemoveIds(data)
}
return true;
} catch {
return false;
}
});
return [
...result.data.menuItemBulkDelete.errors,
...result.data.menuItemMove.errors,
...result.data.menuUpdate.errors
];
};
return (

View file

@ -74,7 +74,7 @@ export interface OrderDetailsPageProps extends UserPermissionProps {
onInvoiceClick(invoiceId: string);
onInvoiceGenerate();
onInvoiceSend(invoiceId: string);
onSubmit(data: MetadataFormData);
onSubmit(data: MetadataFormData): Promise<any[]>;
}
const OrderDetailsPage: React.FC<OrderDetailsPageProps> = props => {
@ -123,7 +123,7 @@ const OrderDetailsPage: React.FC<OrderDetailsPageProps> = props => {
? data.privateMetadata
: undefined;
onSubmit({
return onSubmit({
metadata,
privateMetadata
});

View file

@ -127,6 +127,8 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
text: intl.formatMessage(commonMessages.savedChanges)
});
}
return result;
};
return (

View file

@ -27,7 +27,7 @@ import { maybe } from "../../../misc";
import { PageDetails_page } from "../../types/PageDetails";
import PageInfo from "../PageInfo";
export interface FormData extends MetadataFormData {
export interface PageDetailsPageFormData extends MetadataFormData {
content: RawDraftContentState;
isPublished: boolean;
publicationDate: string;
@ -45,7 +45,7 @@ export interface PageDetailsPageProps {
saveButtonBarState: ConfirmButtonTransitionState;
onBack: () => void;
onRemove: () => void;
onSubmit: (data: FormData) => void;
onSubmit: (data: PageDetailsPageFormData) => void;
}
const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
@ -67,7 +67,7 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
const pageExists = page !== null;
const initialForm: FormData = {
const initialForm: PageDetailsPageFormData = {
content: maybe(
() => JSON.parse(page.contentJson),
convertToRaw(ContentState.createFromText(""))

View file

@ -14,10 +14,10 @@ import { useIntl } from "react-intl";
import { maybe } from "../../../misc";
import { PageDetails_page } from "../../types/PageDetails";
import { FormData } from "../PageDetailsPage";
import { PageDetailsPageFormData } from "../PageDetailsPage";
export interface PageInfoProps {
data: FormData;
data: PageDetailsPageFormData;
disabled: boolean;
errors: PageErrorFragment[];
page: PageDetails_page;
@ -56,7 +56,7 @@ const PageInfo: React.FC<PageInfoProps> = props => {
defaultMessage: "Title",
description: "page title"
})}
name={"title" as keyof FormData}
name={"title" as keyof PageDetailsPageFormData}
value={data.title}
onChange={onChange}
/>
@ -70,7 +70,7 @@ const PageInfo: React.FC<PageInfoProps> = props => {
defaultMessage: "Content",
description: "page content"
})}
name={"content" as keyof FormData}
name={"content" as keyof PageDetailsPageFormData}
onChange={onChange}
/>
</CardContent>

View file

@ -14,7 +14,9 @@ import { FormattedMessage, useIntl } from "react-intl";
import { getStringOrPlaceholder, maybe } from "../../misc";
import { PageInput } from "../../types/globalTypes";
import PageDetailsPage, { FormData } from "../components/PageDetailsPage";
import PageDetailsPage, {
PageDetailsPageFormData
} from "../components/PageDetailsPage";
import { TypedPageRemove, TypedPageUpdate } from "../mutations";
import { TypedPageDetailsQuery } from "../queries";
import { PageRemove } from "../types/PageRemove";
@ -25,7 +27,7 @@ export interface PageDetailsProps {
params: PageUrlQueryParams;
}
const createPageInput = (data: FormData): PageInput => ({
const createPageInput = (data: PageDetailsPageFormData): PageInput => ({
contentJson: JSON.stringify(data.content),
isPublished: data.isPublished,
publicationDate: data.publicationDate,
@ -61,7 +63,7 @@ export const PageDetails: React.FC<PageDetailsProps> = ({ id, params }) => {
{(pageUpdate, pageUpdateOpts) => (
<TypedPageDetailsQuery variables={{ id }}>
{pageDetails => {
const handleUpdate = async (data: FormData) => {
const handleUpdate = async (data: PageDetailsPageFormData) => {
const result = await pageUpdate({
variables: {
id,

View file

@ -56,7 +56,7 @@ export interface PermissionGroupDetailsPageProps
onAssign: () => void;
onBack: () => void;
onUnassign: (ids: string[]) => void;
onSubmit(data: PermissionGroupDetailsPageFormData);
onSubmit: (data: PermissionGroupDetailsPageFormData) => Promise<any[]>;
}
const PermissionGroupDetailsPage: React.FC<PermissionGroupDetailsPageProps> = ({

View file

@ -21,7 +21,9 @@ import React, { useState } from "react";
import { useIntl } from "react-intl";
import AssignMembersDialog from "../../components/AssignMembersDialog";
import PermissionGroupDetailsPage from "../../components/PermissionGroupDetailsPage";
import PermissionGroupDetailsPage, {
PermissionGroupDetailsPageFormData
} from "../../components/PermissionGroupDetailsPage";
import UnassignMembersDialog from "../../components/UnassignMembersDialog";
import { usePermissionGroupUpdate } from "../../mutations";
import { usePermissionGroupDetailsQuery } from "../../queries";
@ -131,6 +133,21 @@ export const PermissionGroupDetails: React.FC<PermissionGroupDetailsProps> = ({
);
const disabled = loading || !isGroupEditable || permissionsExceeded;
const handleSubmit = async (formData: PermissionGroupDetailsPageFormData) => {
const result = await permissionGroupUpdate({
variables: {
id,
input: {
name: formData.name,
...permissionsDiff(data?.permissionGroup, formData),
...usersDiff(data?.permissionGroup, formData)
}
}
});
return result.data.permissionGroupUpdate.errors;
};
return (
<>
<PermissionGroupDetailsPage
@ -144,18 +161,7 @@ export const PermissionGroupDetails: React.FC<PermissionGroupDetailsProps> = ({
errors={
permissionGroupUpdateResult?.data?.permissionGroupUpdate.errors || []
}
onSubmit={formData =>
permissionGroupUpdate({
variables: {
id,
input: {
name: formData.name,
...permissionsDiff(data?.permissionGroup, formData),
...usersDiff(data?.permissionGroup, formData)
}
}
})
}
onSubmit={handleSubmit}
permissions={permissions}
saveButtonBarState={permissionGroupUpdateResult.status}
disabled={disabled}

View file

@ -13,10 +13,10 @@ import getPluginErrorMessage from "@saleor/utils/errors/plugins";
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import { FormData } from "../PluginsDetailsPage";
import { PluginDetailsPageFormData } from "../PluginsDetailsPage";
interface PluginInfoProps {
data: FormData;
data: PluginDetailsPageFormData;
description: string;
errors: PluginErrorFragment[];
name: string;
@ -83,7 +83,7 @@ const PluginInfo: React.FC<PluginInfoProps> = ({
})}
</Typography>
<ControlledCheckbox
name={"active" as keyof FormData}
name={"active" as keyof PluginDetailsPageFormData}
label={intl.formatMessage({
defaultMessage: "Set plugin as Active"
})}

View file

@ -14,10 +14,10 @@ import { getFieldError } from "@saleor/utils/errors";
import React from "react";
import { useIntl } from "react-intl";
import { FormData } from "../PluginsDetailsPage";
import { PluginDetailsPageFormData } from "../PluginsDetailsPage";
interface PluginSettingsProps {
data: FormData;
data: PluginDetailsPageFormData;
errors: UserError[];
disabled: boolean;
onChange: (event: React.ChangeEvent<any>) => void;

View file

@ -23,7 +23,7 @@ import PluginAuthorization from "../PluginAuthorization";
import PluginInfo from "../PluginInfo";
import PluginSettings from "../PluginSettings";
export interface FormData {
export interface PluginDetailsPageFormData {
active: boolean;
configuration: ConfigurationItemInput[];
}
@ -36,7 +36,7 @@ export interface PluginsDetailsPageProps {
onBack: () => void;
onClear: (field: string) => void;
onEdit: (field: string) => void;
onSubmit: (data: FormData) => void;
onSubmit: (data: PluginDetailsPageFormData) => void;
}
const useStyles = makeStyles(
@ -64,7 +64,7 @@ const PluginsDetailsPage: React.FC<PluginsDetailsPageProps> = props => {
const classes = useStyles(props);
const intl = useIntl();
const initialForm: FormData = {
const initialForm: PluginDetailsPageFormData = {
active: plugin?.active || false,
configuration: plugin?.configuration
?.filter(field => !isSecretField(plugin?.configuration || [], field.name))

View file

@ -9,7 +9,9 @@ import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandl
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import PluginsDetailsPage from "../components/PluginsDetailsPage";
import PluginsDetailsPage, {
PluginDetailsPageFormData
} from "../components/PluginsDetailsPage";
import PluginSecretFieldDialog from "../components/PluginSecretFieldDialog";
import { TypedPluginUpdate } from "../mutations";
import { TypedPluginsDetailsQuery } from "../queries";
@ -89,6 +91,25 @@ export const PluginsDetails: React.FC<PluginsDetailsProps> = ({
}
});
const handleSubmit = async (
formData: PluginDetailsPageFormData
) => {
const result = await pluginUpdate({
variables: {
id,
input: {
active: formData.active,
configuration: getConfigurationInput(
pluginDetails.data.plugin.configuration,
formData.configuration
)
}
}
});
return result.data.pluginUpdate.errors;
};
return (
<>
<WindowTitle title={pluginDetails.data?.plugin?.name} />
@ -110,20 +131,7 @@ export const PluginsDetails: React.FC<PluginsDetailsProps> = ({
id
})
}
onSubmit={formData =>
pluginUpdate({
variables: {
id,
input: {
active: formData.active,
configuration: getConfigurationInput(
pluginDetails.data.plugin.configuration,
formData.configuration
)
}
}
})
}
onSubmit={handleSubmit}
/>
{pluginDetails.data?.plugin?.configuration && (
<>

View file

@ -61,7 +61,7 @@ export interface ProductTypeDetailsPageProps {
onBack: () => void;
onDelete: () => void;
onHasVariantsToggle: (hasVariants: boolean) => void;
onSubmit: (data: ProductTypeForm) => void;
onSubmit: (data: ProductTypeForm) => Promise<any[]>;
}
function handleTaxTypeChange(
@ -141,7 +141,7 @@ const ProductTypeDetailsPage: React.FC<ProductTypeDetailsPageProps> = ({
? data.privateMetadata
: undefined;
onSubmit({
return onSubmit({
...data,
metadata,
privateMetadata

View file

@ -46,7 +46,7 @@ export interface ShippingZoneDetailsPageProps
onPriceRateAdd: () => void;
onPriceRateEdit: (id: string) => void;
onRateRemove: (rateId: string) => void;
onSubmit: (data: FormData) => void;
onSubmit: (data: FormData) => Promise<any[]>;
onWarehouseAdd: () => void;
onWeightRateAdd: () => void;
onWeightRateEdit: (id: string) => void;

View file

@ -148,13 +148,13 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
}
});
const handleSubmit = (submitData: FormData) => {
const handleSubmit = async (submitData: FormData) => {
const warehouseDiff = diff(
data.shippingZone.warehouses.map(warehouse => warehouse.id),
submitData.warehouses
);
updateShippingZone({
const result = await updateShippingZone({
variables: {
id,
input: {
@ -164,6 +164,8 @@ const ShippingZoneDetails: React.FC<ShippingZoneDetailsProps> = ({
}
}
});
return result.data.shippingZoneUpdate.errors;
};
if (data?.shippingZone === null) {

View file

@ -54,7 +54,7 @@ export interface SiteSettingsPageProps {
onBack: () => void;
onKeyAdd: () => void;
onKeyRemove: (keyType: AuthorizationKeyType) => void;
onSubmit: (data: SiteSettingsPageFormData) => void;
onSubmit: (data: SiteSettingsPageFormData) => Promise<any[]>;
}
export function areAddressInputFieldsModified(
@ -105,7 +105,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
const {
errors: validationErrors,
submit: handleSubmitWithAddress
} = useAddressValidation<SiteSettingsPageFormData>(onSubmit);
} = useAddressValidation(onSubmit);
const initialFormAddress: SiteSettingsPageAddressFormData = {
city: maybe(() => shop.companyAddress.city, ""),
@ -134,7 +134,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
const submitFunc = areAddressInputFieldsModified(data)
? handleSubmitWithAddress
: onSubmit;
submitFunc(data);
return submitFunc(data);
}}
confirmLeave
>

View file

@ -106,7 +106,7 @@ export const SiteSettings: React.FC<SiteSettingsProps> = ({ params }) => {
keyType: data.type
}
});
const handleUpdateShopSettings = (
const handleUpdateShopSettings = async (
data: SiteSettingsPageFormData
) => {
const addressInput = areAddressInputFieldsModified(data)
@ -123,7 +123,7 @@ export const SiteSettings: React.FC<SiteSettingsProps> = ({ params }) => {
: {
companyName: data.companyName
};
updateShopSettings({
const result = await updateShopSettings({
variables: {
addressInput,
shopDomainInput: {
@ -139,6 +139,12 @@ export const SiteSettings: React.FC<SiteSettingsProps> = ({ params }) => {
}
}
});
return [
result.data.shopAddressUpdate.errors,
result.data.shopDomainUpdate.errors,
result.data.shopSettingsUpdate.errors
];
};
return (

View file

@ -50,7 +50,7 @@ export interface StaffDetailsPageProps extends SearchPageProps {
onChangePassword: () => void;
onDelete: () => void;
onImageDelete: () => void;
onSubmit: (data: StaffDetailsFormData) => void;
onSubmit: (data: StaffDetailsFormData) => Promise<any[]>;
onImageUpload(file: File);
}

View file

@ -12,7 +12,9 @@ import usePermissionGroupSearch from "@saleor/searches/usePermissionGroupSearch"
import React from "react";
import { FormattedMessage, useIntl } from "react-intl";
import StaffDetailsPage from "../components/StaffDetailsPage/StaffDetailsPage";
import StaffDetailsPage, {
StaffDetailsFormData
} from "../components/StaffDetailsPage/StaffDetailsPage";
import StaffPasswordResetDialog from "../components/StaffPasswordResetDialog";
import {
TypedStaffAvatarDeleteMutation,
@ -122,168 +124,175 @@ export const StaffDetails: React.FC<OrderListProps> = ({ id, params }) => {
return (
<TypedStaffMemberUpdateMutation onCompleted={handleStaffMemberUpdate}>
{(updateStaffMember, updateResult) => (
<TypedStaffMemberDeleteMutation
variables={{ id }}
onCompleted={handleStaffMemberDelete}
>
{(deleteStaffMember, deleteResult) => (
<TypedStaffAvatarUpdateMutation
onCompleted={handleStaffMemberAvatarUpdate}
>
{updateStaffAvatar => (
<TypedStaffAvatarDeleteMutation
onCompleted={handleStaffMemberAvatarDelete}
>
{(deleteStaffAvatar, deleteAvatarResult) => {
const isUserSameAsViewer =
user.user?.id === data?.user?.id;
{(updateStaffMember, updateResult) => {
const handleSubmit = async (formData: StaffDetailsFormData) => {
const result = await updateStaffMember({
variables: {
id,
input: {
email: formData.email,
firstName: formData.firstName,
isActive: formData.isActive,
lastName: formData.lastName,
...groupsDiff(data?.user, formData)
}
}
});
return (
<>
<WindowTitle
title={getStringOrPlaceholder(
staffMember?.email
)}
/>
<StaffDetailsPage
errors={
updateResult?.data?.staffUpdate?.errors || []
}
canEditAvatar={isUserSameAsViewer}
canEditPreferences={isUserSameAsViewer}
canEditStatus={!isUserSameAsViewer}
canRemove={!isUserSameAsViewer}
disabled={loading}
onBack={handleBack}
initialSearch=""
onChangePassword={() =>
navigate(
staffMemberDetailsUrl(id, {
action: "change-password"
})
)
}
onDelete={() =>
navigate(
staffMemberDetailsUrl(id, {
action: "remove"
})
)
}
onSubmit={variables => {
updateStaffMember({
variables: {
id,
input: {
email: variables.email,
firstName: variables.firstName,
isActive: variables.isActive,
lastName: variables.lastName,
...groupsDiff(data?.user, variables)
return result.data.staffUpdate.errors;
};
return (
<TypedStaffMemberDeleteMutation
variables={{ id }}
onCompleted={handleStaffMemberDelete}
>
{(deleteStaffMember, deleteResult) => (
<TypedStaffAvatarUpdateMutation
onCompleted={handleStaffMemberAvatarUpdate}
>
{updateStaffAvatar => (
<TypedStaffAvatarDeleteMutation
onCompleted={handleStaffMemberAvatarDelete}
>
{(deleteStaffAvatar, deleteAvatarResult) => {
const isUserSameAsViewer =
user.user?.id === data?.user?.id;
return (
<>
<WindowTitle
title={getStringOrPlaceholder(
staffMember?.email
)}
/>
<StaffDetailsPage
errors={
updateResult?.data?.staffUpdate?.errors ||
[]
}
canEditAvatar={isUserSameAsViewer}
canEditPreferences={isUserSameAsViewer}
canEditStatus={!isUserSameAsViewer}
canRemove={!isUserSameAsViewer}
disabled={loading}
onBack={handleBack}
initialSearch=""
onChangePassword={() =>
navigate(
staffMemberDetailsUrl(id, {
action: "change-password"
})
)
}
onDelete={() =>
navigate(
staffMemberDetailsUrl(id, {
action: "remove"
})
)
}
onSubmit={handleSubmit}
onImageUpload={file =>
updateStaffAvatar({
variables: {
image: file
}
}
});
}}
onImageUpload={file =>
updateStaffAvatar({
variables: {
image: file
}
})
}
onImageDelete={() =>
navigate(
staffMemberDetailsUrl(id, {
action: "remove-avatar"
})
)
}
availablePermissionGroups={searchPermissionGroupsOpts.data?.search.edges.map(
edge => edge.node
)}
staffMember={staffMember}
saveButtonBarState={updateResult.status}
fetchMorePermissionGroups={{
hasMore:
searchPermissionGroupsOpts.data?.search
.pageInfo.hasNextPage,
loading: searchPermissionGroupsOpts.loading,
onFetchMore: loadMorePermissionGroups
}}
onSearchChange={searchPermissionGroups}
/>
<ActionDialog
open={params.action === "remove"}
title={intl.formatMessage({
defaultMessage: "delete Staff User",
description: "dialog header"
})}
confirmButtonState={deleteResult.status}
variant="delete"
onClose={closeModal}
onConfirm={deleteStaffMember}
>
<DialogContentText>
<FormattedMessage
defaultMessage="Are you sure you want to delete {email} from staff members?"
values={{
email: getStringOrPlaceholder(
data?.user?.email
)
}}
/>
</DialogContentText>
</ActionDialog>
<ActionDialog
open={params.action === "remove-avatar"}
title={intl.formatMessage({
defaultMessage: "Delete Staff User Avatar",
description: "dialog header"
})}
confirmButtonState={deleteAvatarResult.status}
variant="delete"
onClose={closeModal}
onConfirm={deleteStaffAvatar}
>
<DialogContentText>
<FormattedMessage
defaultMessage="Are you sure you want to remove {email} avatar?"
values={{
email: (
<strong>
{getStringOrPlaceholder(
data?.user?.email
)}
</strong>
)
}}
/>
</DialogContentText>
</ActionDialog>
<StaffPasswordResetDialog
confirmButtonState={changePasswordOpts.status}
errors={
changePasswordOpts?.data?.passwordChange
?.errors || []
}
open={params.action === "change-password"}
onClose={closeModal}
onSubmit={data =>
changePassword({
variables: data
})
}
/>
</>
);
}}
</TypedStaffAvatarDeleteMutation>
)}
</TypedStaffAvatarUpdateMutation>
)}
</TypedStaffMemberDeleteMutation>
)}
}
onImageDelete={() =>
navigate(
staffMemberDetailsUrl(id, {
action: "remove-avatar"
})
)
}
availablePermissionGroups={searchPermissionGroupsOpts.data?.search.edges.map(
edge => edge.node
)}
staffMember={staffMember}
saveButtonBarState={updateResult.status}
fetchMorePermissionGroups={{
hasMore:
searchPermissionGroupsOpts.data?.search
.pageInfo.hasNextPage,
loading: searchPermissionGroupsOpts.loading,
onFetchMore: loadMorePermissionGroups
}}
onSearchChange={searchPermissionGroups}
/>
<ActionDialog
open={params.action === "remove"}
title={intl.formatMessage({
defaultMessage: "delete Staff User",
description: "dialog header"
})}
confirmButtonState={deleteResult.status}
variant="delete"
onClose={closeModal}
onConfirm={deleteStaffMember}
>
<DialogContentText>
<FormattedMessage
defaultMessage="Are you sure you want to delete {email} from staff members?"
values={{
email: getStringOrPlaceholder(
data?.user?.email
)
}}
/>
</DialogContentText>
</ActionDialog>
<ActionDialog
open={params.action === "remove-avatar"}
title={intl.formatMessage({
defaultMessage: "Delete Staff User Avatar",
description: "dialog header"
})}
confirmButtonState={deleteAvatarResult.status}
variant="delete"
onClose={closeModal}
onConfirm={deleteStaffAvatar}
>
<DialogContentText>
<FormattedMessage
defaultMessage="Are you sure you want to remove {email} avatar?"
values={{
email: (
<strong>
{getStringOrPlaceholder(
data?.user?.email
)}
</strong>
)
}}
/>
</DialogContentText>
</ActionDialog>
<StaffPasswordResetDialog
confirmButtonState={changePasswordOpts.status}
errors={
changePasswordOpts?.data?.passwordChange
?.errors || []
}
open={params.action === "change-password"}
onClose={closeModal}
onSubmit={data =>
changePassword({
variables: data
})
}
/>
</>
);
}}
</TypedStaffAvatarDeleteMutation>
)}
</TypedStaffAvatarUpdateMutation>
)}
</TypedStaffMemberDeleteMutation>
);
}}
</TypedStaffMemberUpdateMutation>
);
}}

View file

@ -3,7 +3,7 @@ import { storiesOf } from "@storybook/react";
import React from "react";
import VoucherDetailsPage, {
FormData,
VoucherDetailsPageFormData,
VoucherDetailsPageProps,
VoucherDetailsPageTab
} from "../../../discounts/components/VoucherDetailsPage";
@ -59,7 +59,7 @@ storiesOf("Views / Discounts / Voucher details", module)
"type",
"usageLimit",
"discountValue"
] as Array<keyof FormData>).map(field => ({
] as Array<keyof VoucherDetailsPageFormData>).map(field => ({
__typename: "DiscountError",
code: DiscountErrorCode.INVALID,
field

View file

@ -3,7 +3,7 @@ import { storiesOf } from "@storybook/react";
import React from "react";
import PageDetailsPage, {
FormData,
PageDetailsPageFormData,
PageDetailsPageProps
} from "../../../pages/components/PageDetailsPage";
import { page } from "../../../pages/fixtures";
@ -36,7 +36,7 @@ storiesOf("Views / Pages / Page details", module)
"isPublished",
"seoDescription",
"seoTitle"
] as Array<keyof FormData>).map(field => ({
] as Array<keyof PageDetailsPageFormData>).map(field => ({
__typename: "PageError",
code: PageErrorCode.INVALID,
field

View file

@ -3,7 +3,7 @@ import { storiesOf } from "@storybook/react";
import React from "react";
import PluginsDetailsPage, {
FormData,
PluginDetailsPageFormData,
PluginsDetailsPageProps
} from "../../../plugins/components/PluginsDetailsPage";
import { plugin } from "../../../plugins/fixtures";
@ -31,7 +31,7 @@ storiesOf("Views / Plugins / Plugin details", module)
{...props}
errors={[
...(["active", "Username or account", "Password or license"] as Array<
keyof FormData
keyof PluginDetailsPageFormData
>).map(field => ({
__typename: "PluginError" as "PluginError",
code: PluginErrorCode.INVALID,

View file

@ -36,7 +36,7 @@ export interface WarehouseDetailsPageProps {
onBack: () => void;
onDelete: () => void;
onShippingZoneClick: (id: string) => void;
onSubmit: (data: WarehouseDetailsPageFormData) => void;
onSubmit: (data: WarehouseDetailsPageFormData) => Promise<any[]>;
}
const WarehouseDetailsPage: React.FC<WarehouseDetailsPageProps> = ({
@ -58,7 +58,7 @@ const WarehouseDetailsPage: React.FC<WarehouseDetailsPageProps> = ({
const {
errors: validationErrors,
submit: handleSubmit
} = useAddressValidation<WarehouseDetailsPageFormData>(onSubmit);
} = useAddressValidation(onSubmit);
const initialForm: WarehouseDetailsPageFormData = {
city: maybe(() => warehouse.address.city, ""),
@ -76,7 +76,7 @@ const WarehouseDetailsPage: React.FC<WarehouseDetailsPageProps> = ({
return (
<Form initial={initialForm} onSubmit={handleSubmit}>
{({ change, data, submit }) => {
{({ change, data, hasChanged, submit }) => {
const countryChoices = mapCountriesToChoices(countries);
const handleCountryChange = createSingleAutocompleteSelectHandler(
change,
@ -121,7 +121,7 @@ const WarehouseDetailsPage: React.FC<WarehouseDetailsPageProps> = ({
</div>
</Grid>
<SaveButtonBar
disabled={disabled}
disabled={disabled || !hasChanged}
onCancel={onBack}
onDelete={onDelete}
onSave={submit}

View file

@ -13,7 +13,9 @@ import { shippingZoneUrl } from "@saleor/shipping/urls";
import { CountryCode } from "@saleor/types/globalTypes";
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
import WarehouseDeleteDialog from "@saleor/warehouses/components/WarehouseDeleteDialog";
import WarehouseDetailsPage from "@saleor/warehouses/components/WarehouseDetailsPage";
import WarehouseDetailsPage, {
WarehouseDetailsPageFormData
} from "@saleor/warehouses/components/WarehouseDetailsPage";
import {
useWarehouseDelete,
useWarehouseUpdate
@ -76,6 +78,28 @@ const WarehouseDetails: React.FC<WarehouseDetailsProps> = ({ id, params }) => {
return <NotFoundPage onBack={() => navigate(warehouseListUrl())} />;
}
const handleSubmit = async (data: WarehouseDetailsPageFormData) => {
const result = await updateWarehouse({
variables: {
id,
input: {
address: {
city: data.city,
cityArea: data.cityArea,
country: findValueInEnum(data.country, CountryCode),
countryArea: data.countryArea,
phone: data.phone,
postalCode: data.postalCode,
streetAddress1: data.streetAddress1,
streetAddress2: data.streetAddress2
},
name: data.name
}
}
});
return result.data.updateWarehouse.errors;
};
return (
<>
<WindowTitle title={data?.warehouse?.name} />
@ -88,26 +112,7 @@ const WarehouseDetails: React.FC<WarehouseDetailsProps> = ({ id, params }) => {
onBack={() => navigate(warehouseListUrl())}
onDelete={() => openModal("delete")}
onShippingZoneClick={id => navigate(shippingZoneUrl(id))}
onSubmit={data =>
updateWarehouse({
variables: {
id,
input: {
address: {
city: data.city,
cityArea: data.cityArea,
country: findValueInEnum(data.country, CountryCode),
countryArea: data.countryArea,
phone: data.phone,
postalCode: data.postalCode,
streetAddress1: data.streetAddress1,
streetAddress2: data.streetAddress2
},
name: data.name
}
}
})
}
onSubmit={handleSubmit}
/>
<WarehouseDeleteDialog
confirmButtonState={deleteWarehouseTransitionState}