Order confirmation (#840)
* Order confirmed webhook * Add status chip component and update order details page header * refactor * refactor and update types * Remove rebase leftovers * Create order settings page * Add order setting query * Connct order settings view with api * Show order settings update error message * Popup menu routing to order settings * Fix circular import error with order settings form types * Update order settings story * Update order settings messages * wip * Add order confirm mutation and types * Add confirm order feature to order details * Update global types * refactor after review * refactor after review * update types * Revert settings menu removal * Add changelog entry Co-authored-by: Tomasz Szymanski <lime129@gmail.com> Co-authored-by: Magdalena Markusik <magdalena.markusik@mirumee.com> Co-authored-by: Dawid Tarasiuk <tarasiukdawid@gmail.com>
This commit is contained in:
parent
6456cd21d2
commit
07f8f4b0b8
38 changed files with 2040 additions and 32 deletions
|
@ -4,6 +4,7 @@ All notable, unreleased changes to this project will be documented in this file.
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
- Add Order Confirmation settings - #840 by @orzechdev and @mmarkusik
|
||||||
- Add Page Types - #807 by @orzechdev
|
- Add Page Types - #807 by @orzechdev
|
||||||
- Add shipping methods to translation section - #864 by @marekchoinski
|
- Add shipping methods to translation section - #864 by @marekchoinski
|
||||||
|
|
||||||
|
|
|
@ -3093,6 +3093,10 @@
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Cancel order"
|
"string": "Cancel order"
|
||||||
},
|
},
|
||||||
|
"src_dot_orders_dot_components_dot_OrderDetailsPage_dot_3086420445": {
|
||||||
|
"context": "save button",
|
||||||
|
"string": "confirm order"
|
||||||
|
},
|
||||||
"src_dot_orders_dot_components_dot_OrderDraftCancelDialog_dot_1961675716": {
|
"src_dot_orders_dot_components_dot_OrderDraftCancelDialog_dot_1961675716": {
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Delete Daft Order"
|
"string": "Delete Daft Order"
|
||||||
|
@ -3371,6 +3375,10 @@
|
||||||
"context": "order history message",
|
"context": "order history message",
|
||||||
"string": "Order was fully paid"
|
"string": "Order was fully paid"
|
||||||
},
|
},
|
||||||
|
"src_dot_orders_dot_components_dot_OrderHistory_dot_276183305": {
|
||||||
|
"context": "order history message",
|
||||||
|
"string": "Order was confirmed"
|
||||||
|
},
|
||||||
"src_dot_orders_dot_components_dot_OrderHistory_dot_2770854455": {
|
"src_dot_orders_dot_components_dot_OrderHistory_dot_2770854455": {
|
||||||
"context": "order history message",
|
"context": "order history message",
|
||||||
"string": "Payment was captured"
|
"string": "Payment was captured"
|
||||||
|
@ -3472,6 +3480,10 @@
|
||||||
"context": "generate invoice button",
|
"context": "generate invoice button",
|
||||||
"string": "Generate"
|
"string": "Generate"
|
||||||
},
|
},
|
||||||
|
"src_dot_orders_dot_components_dot_OrderListPage_dot_2225897825": {
|
||||||
|
"context": "button",
|
||||||
|
"string": "Order Settings"
|
||||||
|
},
|
||||||
"src_dot_orders_dot_components_dot_OrderListPage_dot_2826235371": {
|
"src_dot_orders_dot_components_dot_OrderListPage_dot_2826235371": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Create order"
|
"string": "Create order"
|
||||||
|
@ -3621,6 +3633,25 @@
|
||||||
"src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_353369701": {
|
"src_dot_orders_dot_components_dot_OrderProductAddDialog_dot_353369701": {
|
||||||
"string": "No products matching given query"
|
"string": "No products matching given query"
|
||||||
},
|
},
|
||||||
|
"src_dot_orders_dot_components_dot_OrderSettingsPage_dot_1149215359": {
|
||||||
|
"context": "header",
|
||||||
|
"string": "Order settings"
|
||||||
|
},
|
||||||
|
"src_dot_orders_dot_components_dot_OrderSettingsPage_dot_3782847217": {
|
||||||
|
"string": "General Settings"
|
||||||
|
},
|
||||||
|
"src_dot_orders_dot_components_dot_OrderSettings_dot_1391686013": {
|
||||||
|
"context": "section header",
|
||||||
|
"string": "Settings"
|
||||||
|
},
|
||||||
|
"src_dot_orders_dot_components_dot_OrderSettings_dot_3281882935": {
|
||||||
|
"context": "checkbox label description",
|
||||||
|
"string": "All orders will be automatically confirmed and all payments will be captured."
|
||||||
|
},
|
||||||
|
"src_dot_orders_dot_components_dot_OrderSettings_dot_513393066": {
|
||||||
|
"context": "checkbox label",
|
||||||
|
"string": "Automatically confirm all orders"
|
||||||
|
},
|
||||||
"src_dot_orders_dot_components_dot_OrderShippingMethodEditDialog_dot_3369240294": {
|
"src_dot_orders_dot_components_dot_OrderShippingMethodEditDialog_dot_3369240294": {
|
||||||
"context": "dialog header",
|
"context": "dialog header",
|
||||||
"string": "Edit Shipping Method"
|
"string": "Edit Shipping Method"
|
||||||
|
@ -5934,6 +5965,10 @@
|
||||||
"src_dot_translations_dot_components_dot_TranslationsVouchersPage_dot_2599922713": {
|
"src_dot_translations_dot_components_dot_TranslationsVouchersPage_dot_2599922713": {
|
||||||
"string": "Voucher Name"
|
"string": "Voucher Name"
|
||||||
},
|
},
|
||||||
|
"src_dot_unconfirmed": {
|
||||||
|
"context": "order status",
|
||||||
|
"string": "Unconfirmed"
|
||||||
|
},
|
||||||
"src_dot_undo": {
|
"src_dot_undo": {
|
||||||
"context": "button",
|
"context": "button",
|
||||||
"string": "Undo"
|
"string": "Undo"
|
||||||
|
@ -6229,6 +6264,10 @@
|
||||||
"context": "event",
|
"context": "event",
|
||||||
"string": "Checkout updated"
|
"string": "Checkout updated"
|
||||||
},
|
},
|
||||||
|
"src_dot_webhooks_dot_components_dot_WebhookEvents_dot_1366770851": {
|
||||||
|
"context": "event",
|
||||||
|
"string": "Order confirmed"
|
||||||
|
},
|
||||||
"src_dot_webhooks_dot_components_dot_WebhookEvents_dot_1368317066": {
|
"src_dot_webhooks_dot_components_dot_WebhookEvents_dot_1368317066": {
|
||||||
"context": "event",
|
"context": "event",
|
||||||
"string": "Invoice deleted"
|
"string": "Invoice deleted"
|
||||||
|
|
|
@ -2554,6 +2554,7 @@ type Mutation {
|
||||||
shopFetchTaxRates: ShopFetchTaxRates
|
shopFetchTaxRates: ShopFetchTaxRates
|
||||||
shopSettingsTranslate(input: ShopSettingsTranslationInput!, languageCode: LanguageCodeEnum!): ShopSettingsTranslate
|
shopSettingsTranslate(input: ShopSettingsTranslationInput!, languageCode: LanguageCodeEnum!): ShopSettingsTranslate
|
||||||
shopAddressUpdate(input: AddressInput): ShopAddressUpdate
|
shopAddressUpdate(input: AddressInput): ShopAddressUpdate
|
||||||
|
orderSettingsUpdate(input: OrderSettingsUpdateInput!): OrderSettingsUpdate
|
||||||
shippingMethodChannelListingUpdate(id: ID!, input: ShippingMethodChannelListingInput!): ShippingMethodChannelListingUpdate
|
shippingMethodChannelListingUpdate(id: ID!, input: ShippingMethodChannelListingInput!): ShippingMethodChannelListingUpdate
|
||||||
shippingPriceCreate(input: ShippingPriceInput!): ShippingPriceCreate
|
shippingPriceCreate(input: ShippingPriceInput!): ShippingPriceCreate
|
||||||
shippingPriceDelete(id: ID!): ShippingPriceDelete
|
shippingPriceDelete(id: ID!): ShippingPriceDelete
|
||||||
|
@ -2643,6 +2644,7 @@ type Mutation {
|
||||||
orderAddNote(order: ID!, input: OrderAddNoteInput!): OrderAddNote
|
orderAddNote(order: ID!, input: OrderAddNoteInput!): OrderAddNote
|
||||||
orderCancel(id: ID!): OrderCancel
|
orderCancel(id: ID!): OrderCancel
|
||||||
orderCapture(amount: PositiveDecimal!, id: ID!): OrderCapture
|
orderCapture(amount: PositiveDecimal!, id: ID!): OrderCapture
|
||||||
|
orderConfirm(id: ID!): OrderConfirm
|
||||||
orderFulfill(input: OrderFulfillInput!, order: ID): OrderFulfill
|
orderFulfill(input: OrderFulfillInput!, order: ID): OrderFulfill
|
||||||
orderFulfillmentCancel(id: ID!, input: FulfillmentCancelInput!): FulfillmentCancel
|
orderFulfillmentCancel(id: ID!, input: FulfillmentCancelInput!): FulfillmentCancel
|
||||||
orderFulfillmentUpdateTracking(id: ID!, input: FulfillmentUpdateTrackingInput!): FulfillmentUpdateTracking
|
orderFulfillmentUpdateTracking(id: ID!, input: FulfillmentUpdateTrackingInput!): FulfillmentUpdateTracking
|
||||||
|
@ -2882,6 +2884,12 @@ type OrderCapture {
|
||||||
orderErrors: [OrderError!]!
|
orderErrors: [OrderError!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OrderConfirm {
|
||||||
|
errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.")
|
||||||
|
order: Order
|
||||||
|
orderErrors: [OrderError!]!
|
||||||
|
}
|
||||||
|
|
||||||
type OrderCountableConnection {
|
type OrderCountableConnection {
|
||||||
pageInfo: PageInfo!
|
pageInfo: PageInfo!
|
||||||
edges: [OrderCountableEdge!]!
|
edges: [OrderCountableEdge!]!
|
||||||
|
@ -2984,6 +2992,7 @@ type OrderEventOrderLineObject {
|
||||||
|
|
||||||
enum OrderEventsEmailsEnum {
|
enum OrderEventsEmailsEnum {
|
||||||
PAYMENT_CONFIRMATION
|
PAYMENT_CONFIRMATION
|
||||||
|
CONFIRMED
|
||||||
SHIPPING_CONFIRMATION
|
SHIPPING_CONFIRMATION
|
||||||
TRACKING_UPDATED
|
TRACKING_UPDATED
|
||||||
ORDER_CONFIRMATION
|
ORDER_CONFIRMATION
|
||||||
|
@ -3005,6 +3014,7 @@ enum OrderEventsEnum {
|
||||||
ORDER_FULLY_PAID
|
ORDER_FULLY_PAID
|
||||||
UPDATED_ADDRESS
|
UPDATED_ADDRESS
|
||||||
EMAIL_SENT
|
EMAIL_SENT
|
||||||
|
CONFIRMED
|
||||||
PAYMENT_AUTHORIZED
|
PAYMENT_AUTHORIZED
|
||||||
PAYMENT_CAPTURED
|
PAYMENT_CAPTURED
|
||||||
EXTERNAL_SERVICE_NOTIFICATION
|
EXTERNAL_SERVICE_NOTIFICATION
|
||||||
|
@ -3093,6 +3103,30 @@ type OrderRefund {
|
||||||
orderErrors: [OrderError!]!
|
orderErrors: [OrderError!]!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type OrderSettings {
|
||||||
|
automaticallyConfirmAllNewOrders: Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderSettingsError {
|
||||||
|
field: String
|
||||||
|
message: String
|
||||||
|
code: OrderSettingsErrorCode!
|
||||||
|
}
|
||||||
|
|
||||||
|
enum OrderSettingsErrorCode {
|
||||||
|
INVALID
|
||||||
|
}
|
||||||
|
|
||||||
|
type OrderSettingsUpdate {
|
||||||
|
errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.")
|
||||||
|
orderSettings: OrderSettings
|
||||||
|
orderSettingsErrors: [OrderSettingsError!]!
|
||||||
|
}
|
||||||
|
|
||||||
|
input OrderSettingsUpdateInput {
|
||||||
|
automaticallyConfirmAllNewOrders: Boolean!
|
||||||
|
}
|
||||||
|
|
||||||
enum OrderSortField {
|
enum OrderSortField {
|
||||||
NUMBER
|
NUMBER
|
||||||
CREATION_DATE
|
CREATION_DATE
|
||||||
|
@ -3108,6 +3142,7 @@ input OrderSortingInput {
|
||||||
|
|
||||||
enum OrderStatus {
|
enum OrderStatus {
|
||||||
DRAFT
|
DRAFT
|
||||||
|
UNCONFIRMED
|
||||||
UNFULFILLED
|
UNFULFILLED
|
||||||
PARTIALLY_FULFILLED
|
PARTIALLY_FULFILLED
|
||||||
FULFILLED
|
FULFILLED
|
||||||
|
@ -3118,6 +3153,7 @@ enum OrderStatusFilter {
|
||||||
READY_TO_FULFILL
|
READY_TO_FULFILL
|
||||||
READY_TO_CAPTURE
|
READY_TO_CAPTURE
|
||||||
UNFULFILLED
|
UNFULFILLED
|
||||||
|
UNCONFIRMED
|
||||||
PARTIALLY_FULFILLED
|
PARTIALLY_FULFILLED
|
||||||
FULFILLED
|
FULFILLED
|
||||||
CANCELED
|
CANCELED
|
||||||
|
@ -4291,6 +4327,7 @@ type Query {
|
||||||
stock(id: ID!): Stock
|
stock(id: ID!): Stock
|
||||||
stocks(filter: StockFilterInput, before: String, after: String, first: Int, last: Int): StockCountableConnection
|
stocks(filter: StockFilterInput, before: String, after: String, first: Int, last: Int): StockCountableConnection
|
||||||
shop: Shop!
|
shop: Shop!
|
||||||
|
orderSettings: OrderSettings
|
||||||
shippingZone(id: ID!, channel: String): ShippingZone
|
shippingZone(id: ID!, channel: String): ShippingZone
|
||||||
shippingZones(channel: String, before: String, after: String, first: Int, last: Int): ShippingZoneCountableConnection
|
shippingZones(channel: String, before: String, after: String, first: Int, last: Int): ShippingZoneCountableConnection
|
||||||
digitalContent(id: ID!): DigitalContent
|
digitalContent(id: ID!): DigitalContent
|
||||||
|
@ -5598,6 +5635,7 @@ type WebhookEvent {
|
||||||
enum WebhookEventTypeEnum {
|
enum WebhookEventTypeEnum {
|
||||||
ANY_EVENTS
|
ANY_EVENTS
|
||||||
ORDER_CREATED
|
ORDER_CREATED
|
||||||
|
ORDER_CONFIRMED
|
||||||
ORDER_FULLY_PAID
|
ORDER_FULLY_PAID
|
||||||
ORDER_UPDATED
|
ORDER_UPDATED
|
||||||
ORDER_CANCELLED
|
ORDER_CANCELLED
|
||||||
|
@ -5616,6 +5654,7 @@ enum WebhookEventTypeEnum {
|
||||||
|
|
||||||
enum WebhookSampleEventTypeEnum {
|
enum WebhookSampleEventTypeEnum {
|
||||||
ORDER_CREATED
|
ORDER_CREATED
|
||||||
|
ORDER_CONFIRMED
|
||||||
ORDER_FULLY_PAID
|
ORDER_FULLY_PAID
|
||||||
ORDER_UPDATED
|
ORDER_UPDATED
|
||||||
ORDER_CANCELLED
|
ORDER_CANCELLED
|
||||||
|
|
13
src/components/StatusChip/StatusChip.stories.tsx
Normal file
13
src/components/StatusChip/StatusChip.stories.tsx
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
import Decorator from "@saleor/storybook/Decorator";
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import StatusChip from "./StatusChip";
|
||||||
|
import { StatusType } from "./types";
|
||||||
|
|
||||||
|
storiesOf("Generics / Status Chip", module)
|
||||||
|
.addDecorator(Decorator)
|
||||||
|
.add("neutral", () => <StatusChip label="label" type={StatusType.NEUTRAL} />)
|
||||||
|
.add("error", () => <StatusChip label="label" type={StatusType.ERROR} />)
|
||||||
|
.add("success", () => <StatusChip label="label" type={StatusType.SUCCESS} />)
|
||||||
|
.add("alert", () => <StatusChip label="label" type={StatusType.ALERT} />);
|
76
src/components/StatusChip/StatusChip.tsx
Normal file
76
src/components/StatusChip/StatusChip.tsx
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
|
import Typography from "@material-ui/core/Typography";
|
||||||
|
import classNames from "classnames";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import { StatusType } from "./types";
|
||||||
|
|
||||||
|
export interface StatusChipProps {
|
||||||
|
type?: StatusType;
|
||||||
|
label?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const StatusChipStyles = {
|
||||||
|
alert: {
|
||||||
|
background: "#FFF4E4"
|
||||||
|
},
|
||||||
|
alertLabel: {
|
||||||
|
color: "#FFB84E"
|
||||||
|
},
|
||||||
|
error: {
|
||||||
|
backgroundColor: "rgba(254, 110, 118, 0.15)"
|
||||||
|
},
|
||||||
|
errorLabel: {
|
||||||
|
color: "#FE6E76"
|
||||||
|
},
|
||||||
|
neutral: {
|
||||||
|
background: "rgba(40, 35, 74, 0.1)"
|
||||||
|
},
|
||||||
|
neutralLabel: {
|
||||||
|
color: "#28234A"
|
||||||
|
},
|
||||||
|
success: {
|
||||||
|
background: "rgba(93, 194, 146, 0.3)"
|
||||||
|
},
|
||||||
|
successLabel: {
|
||||||
|
color: "#5DC292"
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
label: {
|
||||||
|
fontSize: "1rem",
|
||||||
|
fontWeight: theme.typography.fontWeightBold,
|
||||||
|
textTransform: "uppercase"
|
||||||
|
},
|
||||||
|
root: {
|
||||||
|
borderRadius: 22,
|
||||||
|
display: "inline-block",
|
||||||
|
padding: "8px 24px"
|
||||||
|
},
|
||||||
|
...StatusChipStyles
|
||||||
|
}),
|
||||||
|
{ name: "StatusChip" }
|
||||||
|
);
|
||||||
|
|
||||||
|
const StatusChip: React.FC<StatusChipProps> = props => {
|
||||||
|
const { type = StatusType.NEUTRAL, label } = props;
|
||||||
|
const classes = useStyles(props);
|
||||||
|
|
||||||
|
if (!label) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classNames(classes.root, classes[type])}>
|
||||||
|
<Typography
|
||||||
|
className={classNames(classes.label, classes[`${type}Label`])}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default StatusChip;
|
1
src/components/StatusChip/index.ts
Normal file
1
src/components/StatusChip/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export { default } from "./StatusChip";
|
6
src/components/StatusChip/types.ts
Normal file
6
src/components/StatusChip/types.ts
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
export enum StatusType {
|
||||||
|
NEUTRAL = "neutral",
|
||||||
|
ERROR = "error",
|
||||||
|
ALERT = "alert",
|
||||||
|
SUCCESS = "success"
|
||||||
|
}
|
|
@ -69,6 +69,13 @@ export const orderErrorFragment = gql`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const orderSettingsErrorFragment = gql`
|
||||||
|
fragment OrderSettingsErrorFragment on OrderSettingsError {
|
||||||
|
code
|
||||||
|
field
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
export const pageErrorFragment = gql`
|
export const pageErrorFragment = gql`
|
||||||
fragment PageErrorFragment on PageError {
|
fragment PageErrorFragment on PageError {
|
||||||
code
|
code
|
||||||
|
|
|
@ -175,3 +175,9 @@ export const fragmentOrderDetails = gql`
|
||||||
isPaid
|
isPaid
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const fragmentOrderSettings = gql`
|
||||||
|
fragment OrderSettingsFragment on OrderSettings {
|
||||||
|
automaticallyConfirmAllNewOrders
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
15
src/fragments/types/OrderSettingsErrorFragment.ts
Normal file
15
src/fragments/types/OrderSettingsErrorFragment.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { OrderSettingsErrorCode } from "./../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL fragment: OrderSettingsErrorFragment
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface OrderSettingsErrorFragment {
|
||||||
|
__typename: "OrderSettingsError";
|
||||||
|
code: OrderSettingsErrorCode;
|
||||||
|
field: string | null;
|
||||||
|
}
|
12
src/fragments/types/OrderSettingsFragment.ts
Normal file
12
src/fragments/types/OrderSettingsFragment.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL fragment: OrderSettingsFragment
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface OrderSettingsFragment {
|
||||||
|
__typename: "OrderSettings";
|
||||||
|
automaticallyConfirmAllNewOrders: boolean;
|
||||||
|
}
|
27
src/misc.ts
27
src/misc.ts
|
@ -4,6 +4,7 @@ import { defineMessages, IntlShape } from "react-intl";
|
||||||
import urlJoin from "url-join";
|
import urlJoin from "url-join";
|
||||||
|
|
||||||
import { ConfirmButtonTransitionState } from "./components/ConfirmButton/ConfirmButton";
|
import { ConfirmButtonTransitionState } from "./components/ConfirmButton/ConfirmButton";
|
||||||
|
import { StatusType } from "./components/StatusChip/types";
|
||||||
import { APP_MOUNT_URI } from "./config";
|
import { APP_MOUNT_URI } from "./config";
|
||||||
import { AddressType, AddressTypeInput } from "./customers/types";
|
import { AddressType, AddressTypeInput } from "./customers/types";
|
||||||
import {
|
import {
|
||||||
|
@ -144,43 +145,55 @@ export const orderStatusMessages = defineMessages({
|
||||||
defaultMessage: "Ready to fulfill",
|
defaultMessage: "Ready to fulfill",
|
||||||
description: "order status"
|
description: "order status"
|
||||||
},
|
},
|
||||||
|
unconfirmed: {
|
||||||
|
defaultMessage: "Unconfirmed",
|
||||||
|
description: "order status"
|
||||||
|
},
|
||||||
unfulfilled: {
|
unfulfilled: {
|
||||||
defaultMessage: "Unfulfilled",
|
defaultMessage: "Unfulfilled",
|
||||||
description: "order status"
|
description: "order status"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
export const transformOrderStatus = (status: string, intl: IntlShape) => {
|
export const transformOrderStatus = (
|
||||||
|
status: string,
|
||||||
|
intl: IntlShape
|
||||||
|
): { localized: string; status: StatusType } => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case OrderStatus.FULFILLED:
|
case OrderStatus.FULFILLED:
|
||||||
return {
|
return {
|
||||||
localized: intl.formatMessage(orderStatusMessages.fulfilled),
|
localized: intl.formatMessage(orderStatusMessages.fulfilled),
|
||||||
status: "success"
|
status: StatusType.SUCCESS
|
||||||
};
|
};
|
||||||
case OrderStatus.PARTIALLY_FULFILLED:
|
case OrderStatus.PARTIALLY_FULFILLED:
|
||||||
return {
|
return {
|
||||||
localized: intl.formatMessage(orderStatusMessages.partiallyFulfilled),
|
localized: intl.formatMessage(orderStatusMessages.partiallyFulfilled),
|
||||||
status: "neutral"
|
status: StatusType.NEUTRAL
|
||||||
};
|
};
|
||||||
case OrderStatus.UNFULFILLED:
|
case OrderStatus.UNFULFILLED:
|
||||||
return {
|
return {
|
||||||
localized: intl.formatMessage(orderStatusMessages.unfulfilled),
|
localized: intl.formatMessage(orderStatusMessages.unfulfilled),
|
||||||
status: "error"
|
status: StatusType.ERROR
|
||||||
};
|
};
|
||||||
case OrderStatus.CANCELED:
|
case OrderStatus.CANCELED:
|
||||||
return {
|
return {
|
||||||
localized: intl.formatMessage(orderStatusMessages.cancelled),
|
localized: intl.formatMessage(orderStatusMessages.cancelled),
|
||||||
status: "error"
|
status: StatusType.ERROR
|
||||||
};
|
};
|
||||||
case OrderStatus.DRAFT:
|
case OrderStatus.DRAFT:
|
||||||
return {
|
return {
|
||||||
localized: intl.formatMessage(orderStatusMessages.draft),
|
localized: intl.formatMessage(orderStatusMessages.draft),
|
||||||
status: "error"
|
status: StatusType.ERROR
|
||||||
|
};
|
||||||
|
case OrderStatus.UNCONFIRMED:
|
||||||
|
return {
|
||||||
|
localized: intl.formatMessage(orderStatusMessages.unconfirmed),
|
||||||
|
status: StatusType.NEUTRAL
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
localized: status,
|
localized: status,
|
||||||
status: "error"
|
status: StatusType.ERROR
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ import OrderHistory, { FormData as HistoryFormData } from "../OrderHistory";
|
||||||
import OrderInvoiceList from "../OrderInvoiceList";
|
import OrderInvoiceList from "../OrderInvoiceList";
|
||||||
import OrderPayment from "../OrderPayment/OrderPayment";
|
import OrderPayment from "../OrderPayment/OrderPayment";
|
||||||
import OrderUnfulfilledItems from "../OrderUnfulfilledItems/OrderUnfulfilledItems";
|
import OrderUnfulfilledItems from "../OrderUnfulfilledItems/OrderUnfulfilledItems";
|
||||||
|
import Title from "./Title";
|
||||||
|
|
||||||
const useStyles = makeStyles(
|
const useStyles = makeStyles(
|
||||||
theme => ({
|
theme => ({
|
||||||
|
@ -39,6 +40,7 @@ const useStyles = makeStyles(
|
||||||
},
|
},
|
||||||
header: {
|
header: {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
marginBottom: 0
|
marginBottom: 0
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
|
@ -136,6 +138,22 @@ const OrderDetailsPage: React.FC<OrderDetailsPageProps> = props => {
|
||||||
privateMetadata: order?.privateMetadata.map(mapMetadataItemToInput)
|
privateMetadata: order?.privateMetadata.map(mapMetadataItemToInput)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const saveLabel =
|
||||||
|
order?.status === OrderStatus.UNCONFIRMED
|
||||||
|
? intl.formatMessage({
|
||||||
|
defaultMessage: "confirm order",
|
||||||
|
description: "save button"
|
||||||
|
})
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
const allowSave = (hasChanged: boolean) => {
|
||||||
|
if (order?.status !== OrderStatus.UNCONFIRMED) {
|
||||||
|
return disabled || !hasChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
return disabled;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Form initial={initial} onSubmit={handleSubmit}>
|
<Form initial={initial} onSubmit={handleSubmit}>
|
||||||
{({ change, data, hasChanged, submit }) => {
|
{({ change, data, hasChanged, submit }) => {
|
||||||
|
@ -149,7 +167,7 @@ const OrderDetailsPage: React.FC<OrderDetailsPageProps> = props => {
|
||||||
<PageHeader
|
<PageHeader
|
||||||
className={classes.header}
|
className={classes.header}
|
||||||
inline
|
inline
|
||||||
title={maybe(() => order.number) ? "#" + order.number : undefined}
|
title={<Title order={order} />}
|
||||||
>
|
>
|
||||||
{canCancel && (
|
{canCancel && (
|
||||||
<CardMenu
|
<CardMenu
|
||||||
|
@ -243,10 +261,11 @@ const OrderDetailsPage: React.FC<OrderDetailsPageProps> = props => {
|
||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
<SaveButtonBar
|
<SaveButtonBar
|
||||||
|
labels={{ save: saveLabel }}
|
||||||
onCancel={onBack}
|
onCancel={onBack}
|
||||||
onSave={submit}
|
onSave={submit}
|
||||||
state={saveButtonBarState}
|
state={saveButtonBarState}
|
||||||
disabled={disabled || !hasChanged}
|
disabled={allowSave(hasChanged)}
|
||||||
/>
|
/>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
|
46
src/orders/components/OrderDetailsPage/Title.tsx
Normal file
46
src/orders/components/OrderDetailsPage/Title.tsx
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
import { makeStyles } from "@material-ui/core/styles";
|
||||||
|
import StatusChip from "@saleor/components/StatusChip";
|
||||||
|
import { transformOrderStatus } from "@saleor/misc";
|
||||||
|
import { OrderDetails_order } from "@saleor/orders/types/OrderDetails";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
export interface TitleProps {
|
||||||
|
order?: OrderDetails_order;
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
container: {
|
||||||
|
alignItems: "center",
|
||||||
|
display: "flex"
|
||||||
|
},
|
||||||
|
statusContainer: {
|
||||||
|
marginLeft: theme.spacing(2)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ name: "OrderDetailsTitle" }
|
||||||
|
);
|
||||||
|
|
||||||
|
const Title: React.FC<TitleProps> = props => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const classes = useStyles(props);
|
||||||
|
const { order } = props;
|
||||||
|
|
||||||
|
if (!order) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { localized, status } = transformOrderStatus(order.status, intl);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.container}>
|
||||||
|
{`#${order.number}`}
|
||||||
|
<div className={classes.statusContainer}>
|
||||||
|
<StatusChip label={localized} type={status} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Title;
|
|
@ -226,6 +226,11 @@ const getEventMessage = (event: OrderDetails_order_events, intl: IntlShape) => {
|
||||||
defaultMessage: "Payment was authorized",
|
defaultMessage: "Payment was authorized",
|
||||||
description: "order history message"
|
description: "order history message"
|
||||||
});
|
});
|
||||||
|
case OrderEventsEnum.CONFIRMED:
|
||||||
|
return intl.formatMessage({
|
||||||
|
defaultMessage: "Order was confirmed",
|
||||||
|
description: "order history message"
|
||||||
|
});
|
||||||
case OrderEventsEnum.EXTERNAL_SERVICE_NOTIFICATION:
|
case OrderEventsEnum.EXTERNAL_SERVICE_NOTIFICATION:
|
||||||
return event.message;
|
return event.message;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import Button from "@material-ui/core/Button";
|
import Button from "@material-ui/core/Button";
|
||||||
import Card from "@material-ui/core/Card";
|
import Card from "@material-ui/core/Card";
|
||||||
|
import makeStyles from "@material-ui/core/styles/makeStyles";
|
||||||
|
import CardMenu from "@saleor/components/CardMenu";
|
||||||
import Container from "@saleor/components/Container";
|
import Container from "@saleor/components/Container";
|
||||||
import FilterBar from "@saleor/components/FilterBar";
|
import FilterBar from "@saleor/components/FilterBar";
|
||||||
import PageHeader from "@saleor/components/PageHeader";
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
|
@ -22,8 +24,18 @@ export interface OrderListPageProps
|
||||||
FilterPageProps<OrderFilterKeys, OrderListFilterOpts>,
|
FilterPageProps<OrderFilterKeys, OrderListFilterOpts>,
|
||||||
SortPage<OrderListUrlSortField> {
|
SortPage<OrderListUrlSortField> {
|
||||||
orders: OrderList_orders_edges_node[];
|
orders: OrderList_orders_edges_node[];
|
||||||
|
onSettingsOpen: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles(
|
||||||
|
theme => ({
|
||||||
|
settings: {
|
||||||
|
marginRight: theme.spacing(2)
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
{ name: "OrderListPage" }
|
||||||
|
);
|
||||||
|
|
||||||
const OrderListPage: React.FC<OrderListPageProps> = ({
|
const OrderListPage: React.FC<OrderListPageProps> = ({
|
||||||
currentTab,
|
currentTab,
|
||||||
initialSearch,
|
initialSearch,
|
||||||
|
@ -32,6 +44,7 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
|
||||||
onAdd,
|
onAdd,
|
||||||
onAll,
|
onAll,
|
||||||
onSearchChange,
|
onSearchChange,
|
||||||
|
onSettingsOpen,
|
||||||
onFilterChange,
|
onFilterChange,
|
||||||
onTabChange,
|
onTabChange,
|
||||||
onTabDelete,
|
onTabDelete,
|
||||||
|
@ -39,11 +52,26 @@ const OrderListPage: React.FC<OrderListPageProps> = ({
|
||||||
...listProps
|
...listProps
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
const classes = useStyles({});
|
||||||
const filterStructure = createFilterStructure(intl, filterOpts);
|
const filterStructure = createFilterStructure(intl, filterOpts);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<PageHeader title={intl.formatMessage(sectionNames.orders)}>
|
<PageHeader title={intl.formatMessage(sectionNames.orders)}>
|
||||||
|
{!!onSettingsOpen && (
|
||||||
|
<CardMenu
|
||||||
|
className={classes.settings}
|
||||||
|
menuItems={[
|
||||||
|
{
|
||||||
|
label: intl.formatMessage({
|
||||||
|
defaultMessage: "Order Settings",
|
||||||
|
description: "button"
|
||||||
|
}),
|
||||||
|
onSelect: onSettingsOpen
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<Button color="primary" variant="contained" onClick={onAdd}>
|
<Button color="primary" variant="contained" onClick={onAdd}>
|
||||||
<FormattedMessage
|
<FormattedMessage
|
||||||
defaultMessage="Create order"
|
defaultMessage="Create order"
|
||||||
|
|
61
src/orders/components/OrderSettings/OrderSettings.tsx
Normal file
61
src/orders/components/OrderSettings/OrderSettings.tsx
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
import Card from "@material-ui/core/Card";
|
||||||
|
import CardContent from "@material-ui/core/CardContent";
|
||||||
|
import Typography from "@material-ui/core/Typography";
|
||||||
|
import CardTitle from "@saleor/components/CardTitle";
|
||||||
|
import ControlledCheckbox from "@saleor/components/ControlledCheckbox";
|
||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import { OrderSettingsFormData } from "../OrderSettingsPage/form";
|
||||||
|
|
||||||
|
export interface OrderSettingsProps {
|
||||||
|
data: OrderSettingsFormData;
|
||||||
|
disabled: boolean;
|
||||||
|
onChange: (event: React.ChangeEvent<any>) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OrderSettings: React.FC<OrderSettingsProps> = ({
|
||||||
|
data,
|
||||||
|
disabled,
|
||||||
|
onChange
|
||||||
|
}) => {
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card data-test="orderSettings">
|
||||||
|
<CardTitle
|
||||||
|
title={intl.formatMessage({
|
||||||
|
defaultMessage: "Settings",
|
||||||
|
description: "section header"
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
<CardContent>
|
||||||
|
<ControlledCheckbox
|
||||||
|
name={
|
||||||
|
"automaticallyConfirmAllNewOrders" as keyof OrderSettingsFormData
|
||||||
|
}
|
||||||
|
label={
|
||||||
|
<>
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="Automatically confirm all orders"
|
||||||
|
description="checkbox label"
|
||||||
|
/>
|
||||||
|
<Typography variant="caption">
|
||||||
|
<FormattedMessage
|
||||||
|
defaultMessage="All orders will be automatically confirmed and all payments will be captured."
|
||||||
|
description="checkbox label description"
|
||||||
|
/>
|
||||||
|
</Typography>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
checked={data.automaticallyConfirmAllNewOrders}
|
||||||
|
onChange={onChange}
|
||||||
|
disabled={disabled}
|
||||||
|
data-test="automaticallyConfirmAllNewOrdersCheckbox"
|
||||||
|
/>
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
OrderSettings.displayName = "OrderSettings";
|
||||||
|
export default OrderSettings;
|
2
src/orders/components/OrderSettings/index.ts
Normal file
2
src/orders/components/OrderSettings/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./OrderSettings";
|
||||||
|
export * from "./OrderSettings";
|
|
@ -0,0 +1,21 @@
|
||||||
|
import { orderSettings as orderSettingsFixture } from "@saleor/orders/fixtures";
|
||||||
|
import { storiesOf } from "@storybook/react";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
import Decorator from "../../../storybook/Decorator";
|
||||||
|
import OrderSettings, { OrderSettingsPageProps } from ".";
|
||||||
|
|
||||||
|
const props: OrderSettingsPageProps = {
|
||||||
|
data: orderSettingsFixture,
|
||||||
|
disabled: false,
|
||||||
|
onBack: () => undefined,
|
||||||
|
onSubmit: () => undefined,
|
||||||
|
saveButtonBarState: "default"
|
||||||
|
};
|
||||||
|
|
||||||
|
storiesOf("Views / Orders / Order settings", module)
|
||||||
|
.addDecorator(Decorator)
|
||||||
|
.add("default", () => <OrderSettings {...props} />)
|
||||||
|
.add("loading", () => (
|
||||||
|
<OrderSettings {...props} disabled={true} data={undefined} />
|
||||||
|
));
|
|
@ -0,0 +1,62 @@
|
||||||
|
import Typography from "@material-ui/core/Typography";
|
||||||
|
import AppHeader from "@saleor/components/AppHeader";
|
||||||
|
import { ConfirmButtonTransitionState } from "@saleor/components/ConfirmButton";
|
||||||
|
import Container from "@saleor/components/Container";
|
||||||
|
import Grid from "@saleor/components/Grid";
|
||||||
|
import PageHeader from "@saleor/components/PageHeader";
|
||||||
|
import SaveButtonBar from "@saleor/components/SaveButtonBar";
|
||||||
|
import { OrderSettingsFragment } from "@saleor/fragments/types/OrderSettingsFragment";
|
||||||
|
import { SubmitPromise } from "@saleor/hooks/useForm";
|
||||||
|
import { sectionNames } from "@saleor/intl";
|
||||||
|
import React from "react";
|
||||||
|
import { FormattedMessage, useIntl } from "react-intl";
|
||||||
|
|
||||||
|
import OrderSettings from "../OrderSettings/OrderSettings";
|
||||||
|
import OrderSettingsForm, { OrderSettingsFormData } from "./form";
|
||||||
|
|
||||||
|
export interface OrderSettingsPageProps {
|
||||||
|
data: OrderSettingsFragment;
|
||||||
|
disabled: boolean;
|
||||||
|
saveButtonBarState: ConfirmButtonTransitionState;
|
||||||
|
onBack: () => void;
|
||||||
|
onSubmit: (data: OrderSettingsFormData) => SubmitPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
const OrderSettingsPage: React.FC<OrderSettingsPageProps> = props => {
|
||||||
|
const { data, disabled, saveButtonBarState, onBack, onSubmit } = props;
|
||||||
|
const intl = useIntl();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<OrderSettingsForm orderSettings={data} onSubmit={onSubmit}>
|
||||||
|
{({ data, submit, hasChanged, change }) => (
|
||||||
|
<Container>
|
||||||
|
<AppHeader onBack={onBack}>
|
||||||
|
{intl.formatMessage(sectionNames.orders)}
|
||||||
|
</AppHeader>
|
||||||
|
<PageHeader
|
||||||
|
title={intl.formatMessage({
|
||||||
|
defaultMessage: "Order settings",
|
||||||
|
description: "header"
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
<Grid variant="inverted">
|
||||||
|
<div>
|
||||||
|
<Typography>
|
||||||
|
<FormattedMessage defaultMessage="General Settings" />
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
<OrderSettings data={data} disabled={disabled} onChange={change} />
|
||||||
|
</Grid>
|
||||||
|
<SaveButtonBar
|
||||||
|
onCancel={onBack}
|
||||||
|
onSave={submit}
|
||||||
|
disabled={disabled || !hasChanged}
|
||||||
|
state={saveButtonBarState}
|
||||||
|
/>
|
||||||
|
</Container>
|
||||||
|
)}
|
||||||
|
</OrderSettingsForm>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
OrderSettingsPage.displayName = "OrderSettingsPage";
|
||||||
|
export default OrderSettingsPage;
|
71
src/orders/components/OrderSettingsPage/form.tsx
Normal file
71
src/orders/components/OrderSettingsPage/form.tsx
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
import { OrderSettingsFragment } from "@saleor/fragments/types/OrderSettingsFragment";
|
||||||
|
import useForm, { FormChange, SubmitPromise } from "@saleor/hooks/useForm";
|
||||||
|
import handleFormSubmit from "@saleor/utils/handlers/handleFormSubmit";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export interface OrderSettingsFormData {
|
||||||
|
automaticallyConfirmAllNewOrders: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UseOrderSettingsFormResult {
|
||||||
|
change: FormChange;
|
||||||
|
data: OrderSettingsFormData;
|
||||||
|
hasChanged: boolean;
|
||||||
|
submit: () => Promise<boolean>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderSettingsFormProps {
|
||||||
|
children: (props: UseOrderSettingsFormResult) => React.ReactNode;
|
||||||
|
orderSettings: OrderSettingsFragment;
|
||||||
|
onSubmit: (data: OrderSettingsFormData) => SubmitPromise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getOrderSeettingsFormData(
|
||||||
|
orderSettings: OrderSettingsFragment
|
||||||
|
): OrderSettingsFormData {
|
||||||
|
return {
|
||||||
|
automaticallyConfirmAllNewOrders:
|
||||||
|
orderSettings?.automaticallyConfirmAllNewOrders
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function useOrderSettingsForm(
|
||||||
|
orderSettings: OrderSettingsFragment,
|
||||||
|
onSubmit: (data: OrderSettingsFormData) => SubmitPromise
|
||||||
|
): UseOrderSettingsFormResult {
|
||||||
|
const [changed, setChanged] = React.useState(false);
|
||||||
|
const triggerChange = () => setChanged(true);
|
||||||
|
|
||||||
|
const form = useForm(getOrderSeettingsFormData(orderSettings));
|
||||||
|
|
||||||
|
const handleChange: FormChange = (event, cb) => {
|
||||||
|
form.change(event, cb);
|
||||||
|
triggerChange();
|
||||||
|
};
|
||||||
|
|
||||||
|
const data: OrderSettingsFormData = {
|
||||||
|
...form.data
|
||||||
|
};
|
||||||
|
|
||||||
|
const submit = () => handleFormSubmit(form.data, onSubmit, setChanged);
|
||||||
|
|
||||||
|
return {
|
||||||
|
change: handleChange,
|
||||||
|
data,
|
||||||
|
hasChanged: changed,
|
||||||
|
submit
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const OrderSettingsForm: React.FC<OrderSettingsFormProps> = ({
|
||||||
|
children,
|
||||||
|
orderSettings,
|
||||||
|
onSubmit
|
||||||
|
}) => {
|
||||||
|
const props = useOrderSettingsForm(orderSettings, onSubmit);
|
||||||
|
|
||||||
|
return <form onSubmit={props.submit}>{children(props)}</form>;
|
||||||
|
};
|
||||||
|
|
||||||
|
OrderSettingsForm.displayName = "OrderSettingsForm";
|
||||||
|
export default OrderSettingsForm;
|
2
src/orders/components/OrderSettingsPage/index.ts
Normal file
2
src/orders/components/OrderSettingsPage/index.ts
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
export { default } from "./OrderSettingsPage";
|
||||||
|
export * from "./OrderSettingsPage";
|
|
@ -1,4 +1,5 @@
|
||||||
import { InvoiceFragment } from "@saleor/fragments/types/InvoiceFragment";
|
import { InvoiceFragment } from "@saleor/fragments/types/InvoiceFragment";
|
||||||
|
import { OrderSettingsFragment } from "@saleor/fragments/types/OrderSettingsFragment";
|
||||||
import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers";
|
import { SearchCustomers_search_edges_node } from "@saleor/searches/types/SearchCustomers";
|
||||||
import { warehouseList } from "@saleor/warehouses/fixtures";
|
import { warehouseList } from "@saleor/warehouses/fixtures";
|
||||||
import { MessageDescriptor } from "react-intl";
|
import { MessageDescriptor } from "react-intl";
|
||||||
|
@ -1628,3 +1629,8 @@ export const invoices: InvoiceFragment[] = [
|
||||||
"http://localhost:8000/media/invoices/invoice-1/07/2020-order-20-0e449e10-ef4b-4066-bebe-361f670b6820.pdf"
|
"http://localhost:8000/media/invoices/invoice-1/07/2020-order-20-0e449e10-ef4b-4066-bebe-361f670b6820.pdf"
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const orderSettings: OrderSettingsFragment = {
|
||||||
|
__typename: "OrderSettings",
|
||||||
|
automaticallyConfirmAllNewOrders: true
|
||||||
|
};
|
||||||
|
|
|
@ -15,12 +15,14 @@ import {
|
||||||
OrderListUrlQueryParams,
|
OrderListUrlQueryParams,
|
||||||
OrderListUrlSortField,
|
OrderListUrlSortField,
|
||||||
orderPath,
|
orderPath,
|
||||||
|
orderSettingsPath,
|
||||||
OrderUrlQueryParams
|
OrderUrlQueryParams
|
||||||
} from "./urls";
|
} from "./urls";
|
||||||
import OrderDetailsComponent from "./views/OrderDetails";
|
import OrderDetailsComponent from "./views/OrderDetails";
|
||||||
import OrderDraftListComponent from "./views/OrderDraftList";
|
import OrderDraftListComponent from "./views/OrderDraftList";
|
||||||
import OrderFulfillComponent from "./views/OrderFulfill";
|
import OrderFulfillComponent from "./views/OrderFulfill";
|
||||||
import OrderListComponent from "./views/OrderList";
|
import OrderListComponent from "./views/OrderList";
|
||||||
|
import OrderSettings from "./views/OrderSettings";
|
||||||
|
|
||||||
const OrderList: React.FC<RouteComponentProps<any>> = ({ location }) => {
|
const OrderList: React.FC<RouteComponentProps<any>> = ({ location }) => {
|
||||||
const qs = parseQs(location.search.substr(1));
|
const qs = parseQs(location.search.substr(1));
|
||||||
|
@ -70,6 +72,7 @@ const Component = () => {
|
||||||
<>
|
<>
|
||||||
<WindowTitle title={intl.formatMessage(sectionNames.orders)} />
|
<WindowTitle title={intl.formatMessage(sectionNames.orders)} />
|
||||||
<Switch>
|
<Switch>
|
||||||
|
<Route exact path={orderSettingsPath} component={OrderSettings} />
|
||||||
<Route exact path={orderDraftListPath} component={OrderDraftList} />
|
<Route exact path={orderDraftListPath} component={OrderDraftList} />
|
||||||
<Route exact path={orderListPath} component={OrderList} />
|
<Route exact path={orderListPath} component={OrderList} />
|
||||||
<Route path={orderFulfillPath(":id")} component={OrderFulfill} />
|
<Route path={orderFulfillPath(":id")} component={OrderFulfill} />
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import {
|
import {
|
||||||
invoiceErrorFragment,
|
invoiceErrorFragment,
|
||||||
orderErrorFragment
|
orderErrorFragment,
|
||||||
|
orderSettingsErrorFragment
|
||||||
} from "@saleor/fragments/errors";
|
} from "@saleor/fragments/errors";
|
||||||
import {
|
import {
|
||||||
fragmentOrderDetails,
|
fragmentOrderDetails,
|
||||||
fragmentOrderEvent,
|
fragmentOrderEvent,
|
||||||
|
fragmentOrderSettings,
|
||||||
invoiceFragment
|
invoiceFragment
|
||||||
} from "@saleor/fragments/orders";
|
} from "@saleor/fragments/orders";
|
||||||
import makeMutation from "@saleor/hooks/makeMutation";
|
import makeMutation from "@saleor/hooks/makeMutation";
|
||||||
|
@ -23,6 +25,7 @@ import {
|
||||||
import { OrderAddNote, OrderAddNoteVariables } from "./types/OrderAddNote";
|
import { OrderAddNote, OrderAddNoteVariables } from "./types/OrderAddNote";
|
||||||
import { OrderCancel, OrderCancelVariables } from "./types/OrderCancel";
|
import { OrderCancel, OrderCancelVariables } from "./types/OrderCancel";
|
||||||
import { OrderCapture, OrderCaptureVariables } from "./types/OrderCapture";
|
import { OrderCapture, OrderCaptureVariables } from "./types/OrderCapture";
|
||||||
|
import { OrderConfirm, OrderConfirmVariables } from "./types/OrderConfirm";
|
||||||
import {
|
import {
|
||||||
OrderDraftBulkCancel,
|
OrderDraftBulkCancel,
|
||||||
OrderDraftBulkCancelVariables
|
OrderDraftBulkCancelVariables
|
||||||
|
@ -65,6 +68,10 @@ import {
|
||||||
OrderMarkAsPaidVariables
|
OrderMarkAsPaidVariables
|
||||||
} from "./types/OrderMarkAsPaid";
|
} from "./types/OrderMarkAsPaid";
|
||||||
import { OrderRefund, OrderRefundVariables } from "./types/OrderRefund";
|
import { OrderRefund, OrderRefundVariables } from "./types/OrderRefund";
|
||||||
|
import {
|
||||||
|
OrderSettingsUpdate,
|
||||||
|
OrderSettingsUpdateVariables
|
||||||
|
} from "./types/OrderSettingsUpdate";
|
||||||
import {
|
import {
|
||||||
OrderShippingMethodUpdate,
|
OrderShippingMethodUpdate,
|
||||||
OrderShippingMethodUpdateVariables
|
OrderShippingMethodUpdateVariables
|
||||||
|
@ -120,6 +127,27 @@ const orderDraftBulkCancelMutation = gql`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const orderConfirmMutation = gql`
|
||||||
|
${fragmentOrderDetails}
|
||||||
|
${orderErrorFragment}
|
||||||
|
mutation OrderConfirm($id: ID!) {
|
||||||
|
orderConfirm(id: $id) {
|
||||||
|
errors: orderErrors {
|
||||||
|
...OrderErrorFragment
|
||||||
|
}
|
||||||
|
order {
|
||||||
|
...OrderDetailsFragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const useOrderConfirmMutation = makeMutation<
|
||||||
|
OrderConfirm,
|
||||||
|
OrderConfirmVariables
|
||||||
|
>(orderConfirmMutation);
|
||||||
|
|
||||||
export const TypedOrderDraftBulkCancelMutation = TypedMutation<
|
export const TypedOrderDraftBulkCancelMutation = TypedMutation<
|
||||||
OrderDraftBulkCancel,
|
OrderDraftBulkCancel,
|
||||||
OrderDraftBulkCancelVariables
|
OrderDraftBulkCancelVariables
|
||||||
|
@ -500,3 +528,22 @@ export const TypedInvoiceEmailSendMutation = TypedMutation<
|
||||||
InvoiceEmailSend,
|
InvoiceEmailSend,
|
||||||
InvoiceEmailSendVariables
|
InvoiceEmailSendVariables
|
||||||
>(invoiceEmailSendMutation);
|
>(invoiceEmailSendMutation);
|
||||||
|
|
||||||
|
const orderSettingsUpdateMutation = gql`
|
||||||
|
${fragmentOrderSettings}
|
||||||
|
${orderSettingsErrorFragment}
|
||||||
|
mutation OrderSettingsUpdate($input: OrderSettingsUpdateInput!) {
|
||||||
|
orderSettingsUpdate(input: $input) {
|
||||||
|
errors: orderSettingsErrors {
|
||||||
|
...OrderSettingsErrorFragment
|
||||||
|
}
|
||||||
|
orderSettings {
|
||||||
|
...OrderSettingsFragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const useOrderSettingsUpdateMutation = makeMutation<
|
||||||
|
OrderSettingsUpdate,
|
||||||
|
OrderSettingsUpdateVariables
|
||||||
|
>(orderSettingsUpdateMutation);
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
import { fragmentAddress } from "@saleor/fragments/address";
|
import { fragmentAddress } from "@saleor/fragments/address";
|
||||||
import { fragmentOrderDetails } from "@saleor/fragments/orders";
|
import {
|
||||||
|
fragmentOrderDetails,
|
||||||
|
fragmentOrderSettings
|
||||||
|
} from "@saleor/fragments/orders";
|
||||||
import makeQuery from "@saleor/hooks/makeQuery";
|
import makeQuery from "@saleor/hooks/makeQuery";
|
||||||
import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch";
|
import makeTopLevelSearch from "@saleor/hooks/makeTopLevelSearch";
|
||||||
import gql from "graphql-tag";
|
import gql from "graphql-tag";
|
||||||
|
@ -15,6 +18,7 @@ import {
|
||||||
OrderFulfillDataVariables
|
OrderFulfillDataVariables
|
||||||
} from "./types/OrderFulfillData";
|
} from "./types/OrderFulfillData";
|
||||||
import { OrderList, OrderListVariables } from "./types/OrderList";
|
import { OrderList, OrderListVariables } from "./types/OrderList";
|
||||||
|
import { OrderSettings } from "./types/OrderSettings";
|
||||||
import {
|
import {
|
||||||
SearchOrderVariant as SearchOrderVariantType,
|
SearchOrderVariant as SearchOrderVariantType,
|
||||||
SearchOrderVariantVariables
|
SearchOrderVariantVariables
|
||||||
|
@ -238,3 +242,15 @@ export const useOrderFulfillData = makeQuery<
|
||||||
OrderFulfillData,
|
OrderFulfillData,
|
||||||
OrderFulfillDataVariables
|
OrderFulfillDataVariables
|
||||||
>(orderFulfillData);
|
>(orderFulfillData);
|
||||||
|
|
||||||
|
export const orderSettingsQuery = gql`
|
||||||
|
${fragmentOrderSettings}
|
||||||
|
query OrderSettings {
|
||||||
|
orderSettings {
|
||||||
|
...OrderSettingsFragment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
export const useOrderSettingsQuery = makeQuery<OrderSettings, never>(
|
||||||
|
orderSettingsQuery
|
||||||
|
);
|
||||||
|
|
343
src/orders/types/OrderConfirm.ts
Normal file
343
src/orders/types/OrderConfirm.ts
Normal file
|
@ -0,0 +1,343 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { OrderErrorCode, OrderEventsEmailsEnum, OrderEventsEnum, FulfillmentStatus, PaymentChargeStatusEnum, OrderStatus, OrderAction, JobStatusEnum } from "./../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL mutation operation: OrderConfirm
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_errors {
|
||||||
|
__typename: "OrderError";
|
||||||
|
code: OrderErrorCode;
|
||||||
|
field: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_metadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_privateMetadata {
|
||||||
|
__typename: "MetadataItem";
|
||||||
|
key: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_billingAddress_country {
|
||||||
|
__typename: "CountryDisplay";
|
||||||
|
code: string;
|
||||||
|
country: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_billingAddress {
|
||||||
|
__typename: "Address";
|
||||||
|
city: string;
|
||||||
|
cityArea: string;
|
||||||
|
companyName: string;
|
||||||
|
country: OrderConfirm_orderConfirm_order_billingAddress_country;
|
||||||
|
countryArea: string;
|
||||||
|
firstName: string;
|
||||||
|
id: string;
|
||||||
|
lastName: string;
|
||||||
|
phone: string | null;
|
||||||
|
postalCode: string;
|
||||||
|
streetAddress1: string;
|
||||||
|
streetAddress2: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_events_user {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_events {
|
||||||
|
__typename: "OrderEvent";
|
||||||
|
id: string;
|
||||||
|
amount: number | null;
|
||||||
|
date: any | null;
|
||||||
|
email: string | null;
|
||||||
|
emailType: OrderEventsEmailsEnum | null;
|
||||||
|
invoiceNumber: string | null;
|
||||||
|
message: string | null;
|
||||||
|
quantity: number | null;
|
||||||
|
type: OrderEventsEnum | null;
|
||||||
|
user: OrderConfirm_orderConfirm_order_events_user | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine_variant {
|
||||||
|
__typename: "ProductVariant";
|
||||||
|
id: string;
|
||||||
|
quantityAvailable: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine_unitPrice_gross {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine_unitPrice_net {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine_unitPrice {
|
||||||
|
__typename: "TaxedMoney";
|
||||||
|
gross: OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine_unitPrice_gross;
|
||||||
|
net: OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine_unitPrice_net;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine_thumbnail {
|
||||||
|
__typename: "Image";
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine {
|
||||||
|
__typename: "OrderLine";
|
||||||
|
id: string;
|
||||||
|
isShippingRequired: boolean;
|
||||||
|
variant: OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine_variant | null;
|
||||||
|
productName: string;
|
||||||
|
productSku: string;
|
||||||
|
quantity: number;
|
||||||
|
quantityFulfilled: number;
|
||||||
|
unitPrice: OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine_unitPrice | null;
|
||||||
|
thumbnail: OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine_thumbnail | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_fulfillments_lines {
|
||||||
|
__typename: "FulfillmentLine";
|
||||||
|
id: string;
|
||||||
|
quantity: number;
|
||||||
|
orderLine: OrderConfirm_orderConfirm_order_fulfillments_lines_orderLine | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_fulfillments_warehouse {
|
||||||
|
__typename: "Warehouse";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_fulfillments {
|
||||||
|
__typename: "Fulfillment";
|
||||||
|
id: string;
|
||||||
|
lines: (OrderConfirm_orderConfirm_order_fulfillments_lines | null)[] | null;
|
||||||
|
fulfillmentOrder: number;
|
||||||
|
status: FulfillmentStatus;
|
||||||
|
trackingNumber: string;
|
||||||
|
warehouse: OrderConfirm_orderConfirm_order_fulfillments_warehouse | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_lines_variant {
|
||||||
|
__typename: "ProductVariant";
|
||||||
|
id: string;
|
||||||
|
quantityAvailable: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_lines_unitPrice_gross {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_lines_unitPrice_net {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_lines_unitPrice {
|
||||||
|
__typename: "TaxedMoney";
|
||||||
|
gross: OrderConfirm_orderConfirm_order_lines_unitPrice_gross;
|
||||||
|
net: OrderConfirm_orderConfirm_order_lines_unitPrice_net;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_lines_thumbnail {
|
||||||
|
__typename: "Image";
|
||||||
|
url: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_lines {
|
||||||
|
__typename: "OrderLine";
|
||||||
|
id: string;
|
||||||
|
isShippingRequired: boolean;
|
||||||
|
variant: OrderConfirm_orderConfirm_order_lines_variant | null;
|
||||||
|
productName: string;
|
||||||
|
productSku: string;
|
||||||
|
quantity: number;
|
||||||
|
quantityFulfilled: number;
|
||||||
|
unitPrice: OrderConfirm_orderConfirm_order_lines_unitPrice | null;
|
||||||
|
thumbnail: OrderConfirm_orderConfirm_order_lines_thumbnail | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_shippingAddress_country {
|
||||||
|
__typename: "CountryDisplay";
|
||||||
|
code: string;
|
||||||
|
country: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_shippingAddress {
|
||||||
|
__typename: "Address";
|
||||||
|
city: string;
|
||||||
|
cityArea: string;
|
||||||
|
companyName: string;
|
||||||
|
country: OrderConfirm_orderConfirm_order_shippingAddress_country;
|
||||||
|
countryArea: string;
|
||||||
|
firstName: string;
|
||||||
|
id: string;
|
||||||
|
lastName: string;
|
||||||
|
phone: string | null;
|
||||||
|
postalCode: string;
|
||||||
|
streetAddress1: string;
|
||||||
|
streetAddress2: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_shippingMethod {
|
||||||
|
__typename: "ShippingMethod";
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_shippingPrice_gross {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_shippingPrice {
|
||||||
|
__typename: "TaxedMoney";
|
||||||
|
gross: OrderConfirm_orderConfirm_order_shippingPrice_gross;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_subtotal_gross {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_subtotal {
|
||||||
|
__typename: "TaxedMoney";
|
||||||
|
gross: OrderConfirm_orderConfirm_order_subtotal_gross;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_total_gross {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_total_tax {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_total {
|
||||||
|
__typename: "TaxedMoney";
|
||||||
|
gross: OrderConfirm_orderConfirm_order_total_gross;
|
||||||
|
tax: OrderConfirm_orderConfirm_order_total_tax;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_totalAuthorized {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_totalCaptured {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_user {
|
||||||
|
__typename: "User";
|
||||||
|
id: string;
|
||||||
|
email: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_availableShippingMethods_price {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_availableShippingMethods {
|
||||||
|
__typename: "ShippingMethod";
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
price: OrderConfirm_orderConfirm_order_availableShippingMethods_price | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_discount {
|
||||||
|
__typename: "Money";
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_invoices {
|
||||||
|
__typename: "Invoice";
|
||||||
|
id: string;
|
||||||
|
number: string | null;
|
||||||
|
createdAt: any;
|
||||||
|
url: string | null;
|
||||||
|
status: JobStatusEnum;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order_channel {
|
||||||
|
__typename: "Channel";
|
||||||
|
isActive: boolean;
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
currencyCode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm_order {
|
||||||
|
__typename: "Order";
|
||||||
|
id: string;
|
||||||
|
metadata: (OrderConfirm_orderConfirm_order_metadata | null)[];
|
||||||
|
privateMetadata: (OrderConfirm_orderConfirm_order_privateMetadata | null)[];
|
||||||
|
billingAddress: OrderConfirm_orderConfirm_order_billingAddress | null;
|
||||||
|
canFinalize: boolean;
|
||||||
|
created: any;
|
||||||
|
customerNote: string;
|
||||||
|
events: (OrderConfirm_orderConfirm_order_events | null)[] | null;
|
||||||
|
fulfillments: (OrderConfirm_orderConfirm_order_fulfillments | null)[];
|
||||||
|
lines: (OrderConfirm_orderConfirm_order_lines | null)[];
|
||||||
|
number: string | null;
|
||||||
|
paymentStatus: PaymentChargeStatusEnum | null;
|
||||||
|
shippingAddress: OrderConfirm_orderConfirm_order_shippingAddress | null;
|
||||||
|
shippingMethod: OrderConfirm_orderConfirm_order_shippingMethod | null;
|
||||||
|
shippingMethodName: string | null;
|
||||||
|
shippingPrice: OrderConfirm_orderConfirm_order_shippingPrice | null;
|
||||||
|
status: OrderStatus;
|
||||||
|
subtotal: OrderConfirm_orderConfirm_order_subtotal | null;
|
||||||
|
total: OrderConfirm_orderConfirm_order_total | null;
|
||||||
|
actions: (OrderAction | null)[];
|
||||||
|
totalAuthorized: OrderConfirm_orderConfirm_order_totalAuthorized | null;
|
||||||
|
totalCaptured: OrderConfirm_orderConfirm_order_totalCaptured | null;
|
||||||
|
user: OrderConfirm_orderConfirm_order_user | null;
|
||||||
|
userEmail: string | null;
|
||||||
|
availableShippingMethods: (OrderConfirm_orderConfirm_order_availableShippingMethods | null)[] | null;
|
||||||
|
discount: OrderConfirm_orderConfirm_order_discount | null;
|
||||||
|
invoices: (OrderConfirm_orderConfirm_order_invoices | null)[] | null;
|
||||||
|
channel: OrderConfirm_orderConfirm_order_channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm_orderConfirm {
|
||||||
|
__typename: "OrderConfirm";
|
||||||
|
errors: OrderConfirm_orderConfirm_errors[];
|
||||||
|
order: OrderConfirm_orderConfirm_order | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirm {
|
||||||
|
orderConfirm: OrderConfirm_orderConfirm | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderConfirmVariables {
|
||||||
|
id: string;
|
||||||
|
}
|
16
src/orders/types/OrderSettings.ts
Normal file
16
src/orders/types/OrderSettings.ts
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL query operation: OrderSettings
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface OrderSettings_orderSettings {
|
||||||
|
__typename: "OrderSettings";
|
||||||
|
automaticallyConfirmAllNewOrders: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderSettings {
|
||||||
|
orderSettings: OrderSettings_orderSettings | null;
|
||||||
|
}
|
34
src/orders/types/OrderSettingsUpdate.ts
Normal file
34
src/orders/types/OrderSettingsUpdate.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
/* tslint:disable */
|
||||||
|
/* eslint-disable */
|
||||||
|
// This file was automatically generated and should not be edited.
|
||||||
|
|
||||||
|
import { OrderSettingsUpdateInput, OrderSettingsErrorCode } from "./../../types/globalTypes";
|
||||||
|
|
||||||
|
// ====================================================
|
||||||
|
// GraphQL mutation operation: OrderSettingsUpdate
|
||||||
|
// ====================================================
|
||||||
|
|
||||||
|
export interface OrderSettingsUpdate_orderSettingsUpdate_errors {
|
||||||
|
__typename: "OrderSettingsError";
|
||||||
|
code: OrderSettingsErrorCode;
|
||||||
|
field: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderSettingsUpdate_orderSettingsUpdate_orderSettings {
|
||||||
|
__typename: "OrderSettings";
|
||||||
|
automaticallyConfirmAllNewOrders: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderSettingsUpdate_orderSettingsUpdate {
|
||||||
|
__typename: "OrderSettingsUpdate";
|
||||||
|
errors: OrderSettingsUpdate_orderSettingsUpdate_errors[];
|
||||||
|
orderSettings: OrderSettingsUpdate_orderSettingsUpdate_orderSettings | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderSettingsUpdate {
|
||||||
|
orderSettingsUpdate: OrderSettingsUpdate_orderSettingsUpdate | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OrderSettingsUpdateVariables {
|
||||||
|
input: OrderSettingsUpdateInput;
|
||||||
|
}
|
|
@ -114,3 +114,5 @@ export const orderFulfillPath = (id: string) =>
|
||||||
urlJoin(orderPath(id), "fulfill");
|
urlJoin(orderPath(id), "fulfill");
|
||||||
export const orderFulfillUrl = (id: string) =>
|
export const orderFulfillUrl = (id: string) =>
|
||||||
orderFulfillPath(encodeURIComponent(id));
|
orderFulfillPath(encodeURIComponent(id));
|
||||||
|
|
||||||
|
export const orderSettingsPath = urlJoin(orderSectionUrl, "settings");
|
||||||
|
|
|
@ -10,8 +10,10 @@ import useUser from "@saleor/hooks/useUser";
|
||||||
import { commonMessages } from "@saleor/intl";
|
import { commonMessages } from "@saleor/intl";
|
||||||
import OrderCannotCancelOrderDialog from "@saleor/orders/components/OrderCannotCancelOrderDialog";
|
import OrderCannotCancelOrderDialog from "@saleor/orders/components/OrderCannotCancelOrderDialog";
|
||||||
import OrderInvoiceEmailSendDialog from "@saleor/orders/components/OrderInvoiceEmailSendDialog";
|
import OrderInvoiceEmailSendDialog from "@saleor/orders/components/OrderInvoiceEmailSendDialog";
|
||||||
|
import { useOrderConfirmMutation } from "@saleor/orders/mutations";
|
||||||
import { InvoiceRequest } from "@saleor/orders/types/InvoiceRequest";
|
import { InvoiceRequest } from "@saleor/orders/types/InvoiceRequest";
|
||||||
import useCustomerSearch from "@saleor/searches/useCustomerSearch";
|
import useCustomerSearch from "@saleor/searches/useCustomerSearch";
|
||||||
|
import getOrderErrorMessage from "@saleor/utils/errors/order";
|
||||||
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
import createDialogActionHandlers from "@saleor/utils/handlers/dialogActionHandlers";
|
||||||
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
|
||||||
import {
|
import {
|
||||||
|
@ -70,6 +72,7 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
|
||||||
} = useCustomerSearch({
|
} = useCustomerSearch({
|
||||||
variables: DEFAULT_INITIAL_SEARCH_DATA
|
variables: DEFAULT_INITIAL_SEARCH_DATA
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
loadMore,
|
loadMore,
|
||||||
search: variantSearch,
|
search: variantSearch,
|
||||||
|
@ -100,6 +103,19 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
|
||||||
|
|
||||||
const handleBack = () => navigate(orderListUrl());
|
const handleBack = () => navigate(orderListUrl());
|
||||||
|
|
||||||
|
const [orderConfirm] = useOrderConfirmMutation({
|
||||||
|
onCompleted: ({ orderConfirm: { errors } }) => {
|
||||||
|
const isError = !!errors.length;
|
||||||
|
|
||||||
|
notify({
|
||||||
|
status: isError ? "error" : "success",
|
||||||
|
text: isError
|
||||||
|
? getOrderErrorMessage(errors[0], intl)
|
||||||
|
: "Confirmed Order"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TypedOrderDetailsQuery displayLoader variables={{ id }}>
|
<TypedOrderDetailsQuery displayLoader variables={{ id }}>
|
||||||
{({ data, loading }) => {
|
{({ data, loading }) => {
|
||||||
|
@ -109,6 +125,10 @@ export const OrderDetails: React.FC<OrderDetailsProps> = ({ id, params }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleSubmit = async (data: MetadataFormData) => {
|
const handleSubmit = async (data: MetadataFormData) => {
|
||||||
|
if (order?.status === OrderStatus.UNCONFIRMED) {
|
||||||
|
await orderConfirm({ variables: { id: order?.id } });
|
||||||
|
}
|
||||||
|
|
||||||
const update = createMetadataUpdateHandler(
|
const update = createMetadataUpdateHandler(
|
||||||
order,
|
order,
|
||||||
() => Promise.resolve([]),
|
() => Promise.resolve([]),
|
||||||
|
|
|
@ -27,6 +27,7 @@ import {
|
||||||
orderListUrl,
|
orderListUrl,
|
||||||
OrderListUrlDialog,
|
OrderListUrlDialog,
|
||||||
OrderListUrlQueryParams,
|
OrderListUrlQueryParams,
|
||||||
|
orderSettingsPath,
|
||||||
orderUrl
|
orderUrl
|
||||||
} from "../../urls";
|
} from "../../urls";
|
||||||
import {
|
import {
|
||||||
|
@ -160,6 +161,7 @@ export const OrderList: React.FC<OrderListProps> = ({ params }) => {
|
||||||
initialSearch={params.query || ""}
|
initialSearch={params.query || ""}
|
||||||
tabs={getFilterTabs().map(tab => tab.name)}
|
tabs={getFilterTabs().map(tab => tab.name)}
|
||||||
onAll={resetFilters}
|
onAll={resetFilters}
|
||||||
|
onSettingsOpen={() => navigate(orderSettingsPath)}
|
||||||
/>
|
/>
|
||||||
<SaveFilterTabDialog
|
<SaveFilterTabDialog
|
||||||
open={params.action === "save-search"}
|
open={params.action === "save-search"}
|
||||||
|
|
64
src/orders/views/OrderSettings.tsx
Normal file
64
src/orders/views/OrderSettings.tsx
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import useNavigator from "@saleor/hooks/useNavigator";
|
||||||
|
import useNotifier from "@saleor/hooks/useNotifier";
|
||||||
|
import { commonMessages } from "@saleor/intl";
|
||||||
|
import { getMutationState } from "@saleor/misc";
|
||||||
|
import OrderSettingsPage from "@saleor/orders/components/OrderSettingsPage";
|
||||||
|
import { OrderSettingsFormData } from "@saleor/orders/components/OrderSettingsPage/form";
|
||||||
|
import { useOrderSettingsUpdateMutation } from "@saleor/orders/mutations";
|
||||||
|
import { useOrderSettingsQuery } from "@saleor/orders/queries";
|
||||||
|
import { orderListUrl } from "@saleor/orders/urls";
|
||||||
|
import React from "react";
|
||||||
|
import { useIntl } from "react-intl";
|
||||||
|
|
||||||
|
export const OrderSettings: React.FC = () => {
|
||||||
|
const intl = useIntl();
|
||||||
|
const navigate = useNavigator();
|
||||||
|
const notify = useNotifier();
|
||||||
|
|
||||||
|
const { data, loading } = useOrderSettingsQuery({});
|
||||||
|
|
||||||
|
const [
|
||||||
|
orderSettingsUpdate,
|
||||||
|
orderSettingsUpdateOpts
|
||||||
|
] = useOrderSettingsUpdateMutation({});
|
||||||
|
|
||||||
|
const handleSubmit = async (data: OrderSettingsFormData) => {
|
||||||
|
const result = await orderSettingsUpdate({
|
||||||
|
variables: {
|
||||||
|
input: data
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const errors = result.data?.orderSettingsUpdate.errors;
|
||||||
|
if (errors.length) {
|
||||||
|
notify({
|
||||||
|
status: "error",
|
||||||
|
text: intl.formatMessage(commonMessages.somethingWentWrong)
|
||||||
|
});
|
||||||
|
return errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
notify({
|
||||||
|
status: "success",
|
||||||
|
text: intl.formatMessage(commonMessages.savedChanges)
|
||||||
|
});
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleBack = () => navigate(orderListUrl());
|
||||||
|
|
||||||
|
return (
|
||||||
|
<OrderSettingsPage
|
||||||
|
data={data?.orderSettings}
|
||||||
|
disabled={loading || orderSettingsUpdateOpts.loading}
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
onBack={handleBack}
|
||||||
|
saveButtonBarState={getMutationState(
|
||||||
|
orderSettingsUpdateOpts.called,
|
||||||
|
orderSettingsUpdateOpts.loading,
|
||||||
|
[...(orderSettingsUpdateOpts.data?.orderSettingsUpdate.errors || [])]
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default OrderSettings;
|
|
@ -67,6 +67,7 @@ export interface PageCreate_pageCreate_page_pageType {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
attributes: (PageCreate_pageCreate_page_pageType_attributes | null)[] | null;
|
attributes: (PageCreate_pageCreate_page_pageType_attributes | null)[] | null;
|
||||||
|
message: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PageCreate_pageCreate_page_metadata {
|
export interface PageCreate_pageCreate_page_metadata {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -37,6 +37,7 @@ const props: OrderListPageProps = {
|
||||||
value: [OrderStatusFilter.CANCELED, OrderStatusFilter.FULFILLED]
|
value: [OrderStatusFilter.CANCELED, OrderStatusFilter.FULFILLED]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onSettingsOpen: () => undefined,
|
||||||
orders,
|
orders,
|
||||||
sort: {
|
sort: {
|
||||||
...sortPageProps.sort,
|
...sortPageProps.sort,
|
||||||
|
|
|
@ -592,6 +592,7 @@ export enum OrderErrorCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum OrderEventsEmailsEnum {
|
export enum OrderEventsEmailsEnum {
|
||||||
|
CONFIRMED = "CONFIRMED",
|
||||||
DIGITAL_LINKS = "DIGITAL_LINKS",
|
DIGITAL_LINKS = "DIGITAL_LINKS",
|
||||||
FULFILLMENT_CONFIRMATION = "FULFILLMENT_CONFIRMATION",
|
FULFILLMENT_CONFIRMATION = "FULFILLMENT_CONFIRMATION",
|
||||||
ORDER_CANCEL = "ORDER_CANCEL",
|
ORDER_CANCEL = "ORDER_CANCEL",
|
||||||
|
@ -604,6 +605,7 @@ export enum OrderEventsEmailsEnum {
|
||||||
|
|
||||||
export enum OrderEventsEnum {
|
export enum OrderEventsEnum {
|
||||||
CANCELED = "CANCELED",
|
CANCELED = "CANCELED",
|
||||||
|
CONFIRMED = "CONFIRMED",
|
||||||
DRAFT_ADDED_PRODUCTS = "DRAFT_ADDED_PRODUCTS",
|
DRAFT_ADDED_PRODUCTS = "DRAFT_ADDED_PRODUCTS",
|
||||||
DRAFT_CREATED = "DRAFT_CREATED",
|
DRAFT_CREATED = "DRAFT_CREATED",
|
||||||
DRAFT_REMOVED_PRODUCTS = "DRAFT_REMOVED_PRODUCTS",
|
DRAFT_REMOVED_PRODUCTS = "DRAFT_REMOVED_PRODUCTS",
|
||||||
|
@ -632,6 +634,10 @@ export enum OrderEventsEnum {
|
||||||
UPDATED_ADDRESS = "UPDATED_ADDRESS",
|
UPDATED_ADDRESS = "UPDATED_ADDRESS",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum OrderSettingsErrorCode {
|
||||||
|
INVALID = "INVALID",
|
||||||
|
}
|
||||||
|
|
||||||
export enum OrderSortField {
|
export enum OrderSortField {
|
||||||
CREATION_DATE = "CREATION_DATE",
|
CREATION_DATE = "CREATION_DATE",
|
||||||
CUSTOMER = "CUSTOMER",
|
CUSTOMER = "CUSTOMER",
|
||||||
|
@ -645,6 +651,7 @@ export enum OrderStatus {
|
||||||
DRAFT = "DRAFT",
|
DRAFT = "DRAFT",
|
||||||
FULFILLED = "FULFILLED",
|
FULFILLED = "FULFILLED",
|
||||||
PARTIALLY_FULFILLED = "PARTIALLY_FULFILLED",
|
PARTIALLY_FULFILLED = "PARTIALLY_FULFILLED",
|
||||||
|
UNCONFIRMED = "UNCONFIRMED",
|
||||||
UNFULFILLED = "UNFULFILLED",
|
UNFULFILLED = "UNFULFILLED",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,6 +661,7 @@ export enum OrderStatusFilter {
|
||||||
PARTIALLY_FULFILLED = "PARTIALLY_FULFILLED",
|
PARTIALLY_FULFILLED = "PARTIALLY_FULFILLED",
|
||||||
READY_TO_CAPTURE = "READY_TO_CAPTURE",
|
READY_TO_CAPTURE = "READY_TO_CAPTURE",
|
||||||
READY_TO_FULFILL = "READY_TO_FULFILL",
|
READY_TO_FULFILL = "READY_TO_FULFILL",
|
||||||
|
UNCONFIRMED = "UNCONFIRMED",
|
||||||
UNFULFILLED = "UNFULFILLED",
|
UNFULFILLED = "UNFULFILLED",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -954,6 +962,7 @@ export enum WebhookEventTypeEnum {
|
||||||
INVOICE_REQUESTED = "INVOICE_REQUESTED",
|
INVOICE_REQUESTED = "INVOICE_REQUESTED",
|
||||||
INVOICE_SENT = "INVOICE_SENT",
|
INVOICE_SENT = "INVOICE_SENT",
|
||||||
ORDER_CANCELLED = "ORDER_CANCELLED",
|
ORDER_CANCELLED = "ORDER_CANCELLED",
|
||||||
|
ORDER_CONFIRMED = "ORDER_CONFIRMED",
|
||||||
ORDER_CREATED = "ORDER_CREATED",
|
ORDER_CREATED = "ORDER_CREATED",
|
||||||
ORDER_FULFILLED = "ORDER_FULFILLED",
|
ORDER_FULFILLED = "ORDER_FULFILLED",
|
||||||
ORDER_FULLY_PAID = "ORDER_FULLY_PAID",
|
ORDER_FULLY_PAID = "ORDER_FULLY_PAID",
|
||||||
|
@ -1342,6 +1351,10 @@ export interface OrderLineInput {
|
||||||
quantity: number;
|
quantity: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface OrderSettingsUpdateInput {
|
||||||
|
automaticallyConfirmAllNewOrders: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface OrderSortingInput {
|
export interface OrderSortingInput {
|
||||||
direction: OrderDirection;
|
direction: OrderDirection;
|
||||||
field: OrderSortField;
|
field: OrderSortField;
|
||||||
|
|
|
@ -60,6 +60,10 @@ const WebhookEvents: React.FC<WebhookEventsProps> = ({
|
||||||
defaultMessage: "Order created",
|
defaultMessage: "Order created",
|
||||||
description: "event"
|
description: "event"
|
||||||
}),
|
}),
|
||||||
|
[WebhookEventTypeEnum.ORDER_CONFIRMED]: intl.formatMessage({
|
||||||
|
defaultMessage: "Order confirmed",
|
||||||
|
description: "event"
|
||||||
|
}),
|
||||||
[WebhookEventTypeEnum.ORDER_FULFILLED]: intl.formatMessage({
|
[WebhookEventTypeEnum.ORDER_FULFILLED]: intl.formatMessage({
|
||||||
defaultMessage: "Order fulfilled",
|
defaultMessage: "Order fulfilled",
|
||||||
description: "event"
|
description: "event"
|
||||||
|
|
Loading…
Reference in a new issue