Email confirmation checkbox (#3680)

* Email confirmation

* Email confimrmation form

* Email confimrmation form

* Copy, padding adjustments

* Messages
This commit is contained in:
Patryk Andrzejewski 2023-05-31 10:27:10 +02:00 committed by GitHub
parent 2505012746
commit f5cb534d12
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 1944 additions and 105 deletions

File diff suppressed because it is too large Load diff

View file

@ -302,6 +302,10 @@
"context": "OrderCustomer Fulfillment from Local Warehouse",
"string": "Fulfill from Local Stock"
},
"/xJSe8": {
"context": "When users confirm their email account, all previous anonymous orders placed under the same email would be added to their order history.",
"string": "When users confirm their email account, all previous anonymous orders placed under the same email would be added to their order history."
},
"/xXvjF": {
"context": "section header",
"string": "Unfulfilled"
@ -6684,6 +6688,10 @@
"context": "option",
"string": "Gift card product type"
},
"kpRxSA": {
"context": "Require email confirmation link",
"string": "Require email confirmation link"
},
"kuo4fW": {
"context": "dialog title",
"string": "Capture manual transaction"
@ -7389,6 +7397,10 @@
"context": "notes about customer header",
"string": "Notes"
},
"qNeXG1": {
"context": "User registration",
"string": "User registration"
},
"qT6YYk": {
"context": "order line total price",
"string": "Total"
@ -7930,6 +7942,10 @@
"context": "error message",
"string": "Invoice not found"
},
"uRfta0": {
"context": "Enable email confirmation",
"string": "Enable email confirmation"
},
"uT5L4h": {
"context": "cancel button label",
"string": "Cancel"

View file

@ -121,6 +121,13 @@ input AccountInput {
"""Shipping address of the customer."""
defaultShippingAddress: AddressInput
"""
Fields required to update the user metadata.
Added in Saleor 3.14.
"""
metadata: [MetadataInput!]
}
"""Register a new user."""
@ -3575,6 +3582,68 @@ type CheckoutCreate {
checkout: Checkout
}
"""
Create new checkout from existing order.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
type CheckoutCreateFromOrder {
"""Variants that were not attached to the checkout."""
unavailableVariants: [CheckoutCreateFromOrderUnavailableVariant!]
"""Created checkout."""
checkout: Checkout
errors: [CheckoutCreateFromOrderError!]!
}
type CheckoutCreateFromOrderError {
"""
Name of a field that caused the error. A value of `null` indicates that the error isn't associated with a particular field.
"""
field: String
"""The error message."""
message: String
"""The error code."""
code: CheckoutCreateFromOrderErrorCode!
}
"""An enumeration."""
enum CheckoutCreateFromOrderErrorCode {
GRAPHQL_ERROR
INVALID
ORDER_NOT_FOUND
CHANNEL_INACTIVE
TAX_ERROR
}
type CheckoutCreateFromOrderUnavailableVariant {
"""The error message."""
message: String!
"""The error code."""
code: CheckoutCreateFromOrderUnavailableVariantErrorCode!
"""Variant ID that is unavailable."""
variantId: ID!
"""Order line ID that is unavailable."""
lineId: ID!
}
"""An enumeration."""
enum CheckoutCreateFromOrderUnavailableVariantErrorCode {
NOT_FOUND
PRODUCT_UNAVAILABLE_FOR_PURCHASE
UNAVAILABLE_VARIANT_IN_CHANNEL
PRODUCT_NOT_PUBLISHED
QUANTITY_GREATER_THAN_LIMIT
INSUFFICIENT_STOCK
}
input CheckoutCreateInput {
"""Slug of a channel in which to create a checkout."""
channel: String
@ -5321,6 +5390,20 @@ input CustomerInput {
"""A note about the user."""
note: String
"""
Fields required to update the user metadata.
Added in Saleor 3.14.
"""
metadata: [MetadataInput!]
"""
Fields required to update the user private metadata.
Added in Saleor 3.14.
"""
privateMetadata: [MetadataInput!]
"""User language code."""
languageCode: LanguageCodeEnum
@ -7626,6 +7709,24 @@ type Group implements Node {
True, if the currently authenticated user has rights to manage a group.
"""
userCanManage: Boolean!
"""
List of channels the group has access to.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
accessibleChannels: [Channel!]
"""
Determine if the group have restricted access to channels.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
restrictedAccessToChannels: Boolean!
}
type GroupCountableConnection {
@ -7749,6 +7850,20 @@ input InvoiceCreateInput {
"""URL of an invoice to download."""
url: String!
"""
Fields required to update the invoice metadata.
Added in Saleor 3.14.
"""
metadata: [MetadataInput!]
"""
Fields required to update the invoice private metadata.
Added in Saleor 3.14.
"""
privateMetadata: [MetadataInput!]
}
"""
@ -9613,7 +9728,7 @@ type Mutation {
"""
Updates a webhook subscription.
Requires one of the following permissions: MANAGE_APPS.
Requires one of the following permissions: MANAGE_APPS, AUTHENTICATED_APP.
"""
webhookUpdate(
"""ID of a webhook to update."""
@ -10332,7 +10447,7 @@ type Mutation {
Requires one of the following permissions: MANAGE_PRODUCTS.
"""
productBulkCreate(
"""Policies of error handling."""
"""Policies of error handling. DEFAULT: REJECT_EVERYTHING"""
errorPolicy: ErrorPolicyEnum
"""Input list of products to create."""
@ -12397,6 +12512,18 @@ type Mutation {
input: CheckoutCreateInput!
): CheckoutCreate
"""
Create new checkout from existing order.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
checkoutCreateFromOrder(
"""ID of a order that will be used to create the checkout."""
id: ID!
): CheckoutCreateFromOrder
"""
Sets the customer as the owner of the checkout.
@ -13148,11 +13275,11 @@ type Mutation {
): CreateToken
"""
Refresh JWT token. Mutation tries to take refreshToken from the input.If it fails it will try to take refreshToken from the http-only cookie -refreshToken. csrfToken is required when refreshToken is provided as a cookie.
Refresh JWT token. Mutation tries to take refreshToken from the input. If it fails it will try to take `refreshToken` from the http-only cookie `refreshToken`. `csrfToken` is required when `refreshToken` is provided as a cookie.
"""
tokenRefresh(
"""
CSRF token required to refresh token. This argument is required when refreshToken is provided as a cookie.
CSRF token required to refresh token. This argument is required when `refreshToken` is provided as a cookie.
"""
csrfToken: String
@ -14401,6 +14528,7 @@ type OrderDiscountDelete {
"""An enumeration."""
enum OrderDiscountType {
SALE
VOUCHER
MANUAL
}
@ -14860,6 +14988,30 @@ type OrderFullyPaid implements Event {
order: Order
}
"""
The order is fully refunded.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
type OrderFullyRefunded implements Event {
"""Time of the event."""
issuedAt: DateTime
"""Saleor version that triggered the event."""
version: String
"""The user or application that triggered the event."""
issuingPrincipal: IssuingPrincipal
"""The application receiving the webhook."""
recipient: App
"""The order the event relates to."""
order: Order
}
"""
Adds granted refund to the order.
@ -15280,6 +15432,30 @@ enum OrderOriginEnum {
REISSUE
}
"""
Payment has been made. The order may be partially or fully paid.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
type OrderPaid implements Event {
"""Time of the event."""
issuedAt: DateTime
"""Saleor version that triggered the event."""
version: String
"""The user or application that triggered the event."""
issuingPrincipal: IssuingPrincipal
"""The application receiving the webhook."""
recipient: App
"""The order the event relates to."""
order: Order
}
"""
Refund an order.
@ -15324,6 +15500,30 @@ input OrderRefundProductsInput {
includeShippingCosts: Boolean = false
}
"""
The order received a refund. The order may be partially or fully refunded.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
type OrderRefunded implements Event {
"""Time of the event."""
issuedAt: DateTime
"""Saleor version that triggered the event."""
version: String
"""The user or application that triggered the event."""
issuingPrincipal: IssuingPrincipal
"""The application receiving the webhook."""
recipient: App
"""The order the event relates to."""
order: Order
}
input OrderReturnFulfillmentLineInput {
"""The ID of the fulfillment line to return."""
fulfillmentLineId: ID!
@ -17101,8 +17301,26 @@ input PermissionGroupCreateInput {
"""List of users to assign to this group."""
addUsers: [ID!]
"""
List of channels to assign to this group.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
addChannels: [ID!]
"""Group name."""
name: String!
"""
Determine if the group has restricted access to channels. DEFAULT: False
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
restrictedAccessToChannels: Boolean = false
}
"""
@ -17177,18 +17395,22 @@ type PermissionGroupError {
"""List of user IDs which causes the error."""
users: [ID!]
"""List of chnnels IDs which causes the error."""
channels: [ID!]
}
"""An enumeration."""
enum PermissionGroupErrorCode {
REQUIRED
UNIQUE
ASSIGN_NON_STAFF_MEMBER
DUPLICATED_INPUT_ITEM
CANNOT_REMOVE_FROM_LAST_GROUP
LEFT_NOT_MANAGEABLE_PERMISSION
OUT_OF_SCOPE_PERMISSION
OUT_OF_SCOPE_USER
REQUIRED
UNIQUE
OUT_OF_SCOPE_CHANNEL
}
input PermissionGroupFilterInput {
@ -17228,6 +17450,15 @@ input PermissionGroupUpdateInput {
"""List of users to assign to this group."""
addUsers: [ID!]
"""
List of channels to assign to this group.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
addChannels: [ID!]
"""Group name."""
name: String
@ -17236,6 +17467,24 @@ input PermissionGroupUpdateInput {
"""List of users to unassign from this group."""
removeUsers: [ID!]
"""
List of channels to unassign from this group.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
removeChannels: [ID!]
"""
Determine if the group has restricted access to channels.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
restrictedAccessToChannels: Boolean
}
"""
@ -19572,6 +19821,13 @@ type ProductVariantBulkError {
"""The error code."""
code: ProductVariantBulkErrorCode!
"""
Path to field that caused the error. A value of `null` indicates that the error isn't associated with a particular field.
Added in Saleor 3.14.
"""
path: String
"""List of attributes IDs which causes the error."""
attributes: [ID!]
@ -21705,7 +21961,11 @@ type Query {
cityArea: String
): AddressValidationData
"""Look up an address by ID."""
"""
Look up an address by ID.
Requires one of the following permissions: MANAGE_USERS, OWNER.
"""
address(
"""ID of an address."""
id: ID!
@ -21844,7 +22104,7 @@ type ReducedRate {
}
"""
Refresh JWT token. Mutation tries to take refreshToken from the input.If it fails it will try to take refreshToken from the http-only cookie -refreshToken. csrfToken is required when refreshToken is provided as a cookie.
Refresh JWT token. Mutation tries to take refreshToken from the input. If it fails it will try to take `refreshToken` from the http-only cookie `refreshToken`. `csrfToken` is required when `refreshToken` is provided as a cookie.
"""
type RefreshToken {
"""JWT token, required to authenticate."""
@ -23546,6 +23806,15 @@ type Shop {
"""
staffNotificationRecipients: [StaffNotificationRecipient!]
"""
Determines if account confirmation by email is enabled.
Added in Saleor 3.14.
Requires one of the following permissions: MANAGE_SETTINGS.
"""
enableAccountConfirmationByEmail: Boolean
"""
Resource limitations and current usage if any set for a shop
@ -23703,6 +23972,13 @@ input ShopSettingsInput {
"""
limitQuantityPerCheckout: Int
"""
Enable automatic account confirmation by email.
Added in Saleor 3.14.
"""
enableAccountConfirmationByEmail: Boolean
"""
Include taxes in prices.
@ -23811,6 +24087,20 @@ input StaffCreateInput {
"""A note about the user."""
note: String
"""
Fields required to update the user metadata.
Added in Saleor 3.14.
"""
metadata: [MetadataInput!]
"""
Fields required to update the user private metadata.
Added in Saleor 3.14.
"""
privateMetadata: [MetadataInput!]
"""List of permission group IDs to which user should be assigned."""
addGroups: [ID!]
@ -23997,6 +24287,20 @@ input StaffUpdateInput {
"""A note about the user."""
note: String
"""
Fields required to update the user metadata.
Added in Saleor 3.14.
"""
metadata: [MetadataInput!]
"""
Fields required to update the user private metadata.
Added in Saleor 3.14.
"""
privateMetadata: [MetadataInput!]
"""List of permission group IDs to which user should be assigned."""
addGroups: [ID!]
@ -26124,6 +26428,20 @@ input UpdateInvoiceInput {
"""URL of an invoice to download."""
url: String
"""
Fields required to update the invoice metadata.
Added in Saleor 3.14.
"""
metadata: [MetadataInput!]
"""
Fields required to update the invoice private metadata.
Added in Saleor 3.14.
"""
privateMetadata: [MetadataInput!]
}
"""
@ -26321,6 +26639,24 @@ type User implements Node & ObjectWithMetadata {
"""List of user's permission groups which user can manage."""
editableGroups: [Group!]
"""
List of channels the user has access to. The sum of channels from all user groups. If at least one group has `restrictedAccessToChannels` set to False - all channels are returned.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
accessibleChannels: [Channel!]
"""
Determine if user have restricted access to channels. False if at least one user group has `restrictedAccessToChannels` set to False.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
restrictedAccessToChannels: Boolean!
avatar(
"""
Desired longest side the image in pixels. Defaults to 4096. Images are never cropped. Pass 0 to retrieve the original size (not recommended).
@ -26439,6 +26775,20 @@ input UserCreateInput {
"""A note about the user."""
note: String
"""
Fields required to update the user metadata.
Added in Saleor 3.14.
"""
metadata: [MetadataInput!]
"""
Fields required to update the user private metadata.
Added in Saleor 3.14.
"""
privateMetadata: [MetadataInput!]
"""User language code."""
languageCode: LanguageCodeEnum
@ -27885,9 +28235,36 @@ enum WebhookEventTypeAsyncEnum {
"""
ORDER_CONFIRMED
"""
Payment has been made. The order may be partially or fully paid.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
ORDER_PAID
"""Payment is made and an order is fully paid."""
ORDER_FULLY_PAID
"""
The order received a refund. The order may be partially or fully refunded.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
ORDER_REFUNDED
"""
The order is fully refunded.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
ORDER_FULLY_REFUNDED
"""
An order is updated; triggered for all changes related to an order; covers all other order webhooks, except for ORDER_CREATED.
"""
@ -28311,9 +28688,36 @@ enum WebhookEventTypeEnum {
"""
ORDER_CONFIRMED
"""
Payment has been made. The order may be partially or fully paid.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
ORDER_PAID
"""Payment is made and an order is fully paid."""
ORDER_FULLY_PAID
"""
The order received a refund. The order may be partially or fully refunded.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
ORDER_REFUNDED
"""
The order is fully refunded.
Added in Saleor 3.14.
Note: this API is currently in Feature Preview and can be subject to changes at later point.
"""
ORDER_FULLY_REFUNDED
"""
An order is updated; triggered for all changes related to an order; covers all other order webhooks, except for ORDER_CREATED.
"""
@ -28805,7 +29209,10 @@ enum WebhookSampleEventTypeEnum {
MENU_ITEM_DELETED
ORDER_CREATED
ORDER_CONFIRMED
ORDER_PAID
ORDER_FULLY_PAID
ORDER_REFUNDED
ORDER_FULLY_REFUNDED
ORDER_UPDATED
ORDER_CANCELLED
ORDER_EXPIRED
@ -28931,7 +29338,7 @@ enum WebhookTriggerErrorCode {
"""
Updates a webhook subscription.
Requires one of the following permissions: MANAGE_APPS.
Requires one of the following permissions: MANAGE_APPS, AUTHENTICATED_APP.
"""
type WebhookUpdate {
webhookErrors: [WebhookError!]! @deprecated(reason: "This field will be removed in Saleor 4.0. Use `errors` field instead.")

View file

@ -1,38 +1,24 @@
import { Card, CardContent } from "@material-ui/core";
import { makeStyles } from "@saleor/macaw-ui";
import clsx from "clsx";
import React from "react";
import CardTitle from "../CardTitle";
import { DashboardCard } from "../Card";
import CompanyAddressForm, {
CompanyAddressFormProps,
} from "./CompanyAddressForm";
interface CompanyAddressInputProps extends CompanyAddressFormProps {
className?: string;
header: string;
}
const useStyles = makeStyles(
{
root: {
overflow: "visible",
},
},
{ name: "CompanyAddressInput" },
);
const CompanyAddressInput: React.FC<CompanyAddressInputProps> = props => {
const { className, header, ...formProps } = props;
const classes = useStyles(props);
const { header, ...formProps } = props;
return (
<Card className={clsx(classes.root, className)}>
<CardTitle title={header} />
<CardContent>
<DashboardCard>
<DashboardCard.Title>{header}</DashboardCard.Title>
<DashboardCard.Content>
<CompanyAddressForm {...formProps} />
</CardContent>
</Card>
</DashboardCard.Content>
</DashboardCard>
);
};
CompanyAddressInput.displayName = "CompanyAddressInput";

View file

@ -55,5 +55,6 @@ export const shopFragment = gql`
reserveStockDurationAnonymousUser
reserveStockDurationAuthenticatedUser
limitQuantityPerCheckout
enableAccountConfirmationByEmail
}
`;

View file

@ -74,7 +74,10 @@
"OrderFilterShippingMethods",
"OrderFulfilled",
"OrderFullyPaid",
"OrderFullyRefunded",
"OrderMetadataUpdated",
"OrderPaid",
"OrderRefunded",
"OrderUpdated",
"PageCreated",
"PageDeleted",

View file

@ -2701,6 +2701,7 @@ export const ShopFragmentDoc = gql`
reserveStockDurationAnonymousUser
reserveStockDurationAuthenticatedUser
limitQuantityPerCheckout
enableAccountConfirmationByEmail
}
${AddressFragmentDoc}`;
export const StaffMemberDetailsFragmentDoc = gql`

File diff suppressed because one or more lines are too long

View file

@ -116,6 +116,12 @@ export type AccountInput = {
defaultBillingAddress?: InputMaybe<AddressInput>;
/** Shipping address of the customer. */
defaultShippingAddress?: InputMaybe<AddressInput>;
/**
* Fields required to update the user metadata.
*
* Added in Saleor 3.14.
*/
metadata?: InputMaybe<Array<MetadataInput>>;
};
/** Fields required to create a user. */
@ -1021,6 +1027,25 @@ export enum CheckoutChargeStatusEnum {
OVERCHARGED = 'OVERCHARGED'
}
/** An enumeration. */
export enum CheckoutCreateFromOrderErrorCode {
GRAPHQL_ERROR = 'GRAPHQL_ERROR',
INVALID = 'INVALID',
ORDER_NOT_FOUND = 'ORDER_NOT_FOUND',
CHANNEL_INACTIVE = 'CHANNEL_INACTIVE',
TAX_ERROR = 'TAX_ERROR'
}
/** An enumeration. */
export enum CheckoutCreateFromOrderUnavailableVariantErrorCode {
NOT_FOUND = 'NOT_FOUND',
PRODUCT_UNAVAILABLE_FOR_PURCHASE = 'PRODUCT_UNAVAILABLE_FOR_PURCHASE',
UNAVAILABLE_VARIANT_IN_CHANNEL = 'UNAVAILABLE_VARIANT_IN_CHANNEL',
PRODUCT_NOT_PUBLISHED = 'PRODUCT_NOT_PUBLISHED',
QUANTITY_GREATER_THAN_LIMIT = 'QUANTITY_GREATER_THAN_LIMIT',
INSUFFICIENT_STOCK = 'INSUFFICIENT_STOCK'
}
export type CheckoutCreateInput = {
/** Slug of a channel in which to create a checkout. */
channel?: InputMaybe<Scalars['String']>;
@ -1672,6 +1697,18 @@ export type CustomerInput = {
isActive?: InputMaybe<Scalars['Boolean']>;
/** A note about the user. */
note?: InputMaybe<Scalars['String']>;
/**
* Fields required to update the user metadata.
*
* Added in Saleor 3.14.
*/
metadata?: InputMaybe<Array<MetadataInput>>;
/**
* Fields required to update the user private metadata.
*
* Added in Saleor 3.14.
*/
privateMetadata?: InputMaybe<Array<MetadataInput>>;
/** User language code. */
languageCode?: InputMaybe<LanguageCodeEnum>;
/**
@ -2241,6 +2278,18 @@ export type InvoiceCreateInput = {
number: Scalars['String'];
/** URL of an invoice to download. */
url: Scalars['String'];
/**
* Fields required to update the invoice metadata.
*
* Added in Saleor 3.14.
*/
metadata?: InputMaybe<Array<MetadataInput>>;
/**
* Fields required to update the invoice private metadata.
*
* Added in Saleor 3.14.
*/
privateMetadata?: InputMaybe<Array<MetadataInput>>;
};
/** An enumeration. */
@ -3381,6 +3430,7 @@ export type OrderDiscountCommonInput = {
/** An enumeration. */
export enum OrderDiscountType {
SALE = 'SALE',
VOUCHER = 'VOUCHER',
MANUAL = 'MANUAL'
}
@ -4081,20 +4131,37 @@ export type PermissionGroupCreateInput = {
addPermissions?: InputMaybe<Array<PermissionEnum>>;
/** List of users to assign to this group. */
addUsers?: InputMaybe<Array<Scalars['ID']>>;
/**
* List of channels to assign to this group.
*
* Added in Saleor 3.14.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
addChannels?: InputMaybe<Array<Scalars['ID']>>;
/** Group name. */
name: Scalars['String'];
/**
* Determine if the group has restricted access to channels. DEFAULT: False
*
* Added in Saleor 3.14.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
restrictedAccessToChannels?: InputMaybe<Scalars['Boolean']>;
};
/** An enumeration. */
export enum PermissionGroupErrorCode {
REQUIRED = 'REQUIRED',
UNIQUE = 'UNIQUE',
ASSIGN_NON_STAFF_MEMBER = 'ASSIGN_NON_STAFF_MEMBER',
DUPLICATED_INPUT_ITEM = 'DUPLICATED_INPUT_ITEM',
CANNOT_REMOVE_FROM_LAST_GROUP = 'CANNOT_REMOVE_FROM_LAST_GROUP',
LEFT_NOT_MANAGEABLE_PERMISSION = 'LEFT_NOT_MANAGEABLE_PERMISSION',
OUT_OF_SCOPE_PERMISSION = 'OUT_OF_SCOPE_PERMISSION',
OUT_OF_SCOPE_USER = 'OUT_OF_SCOPE_USER',
REQUIRED = 'REQUIRED',
UNIQUE = 'UNIQUE'
OUT_OF_SCOPE_CHANNEL = 'OUT_OF_SCOPE_CHANNEL'
}
export type PermissionGroupFilterInput = {
@ -4120,12 +4187,36 @@ export type PermissionGroupUpdateInput = {
addPermissions?: InputMaybe<Array<PermissionEnum>>;
/** List of users to assign to this group. */
addUsers?: InputMaybe<Array<Scalars['ID']>>;
/**
* List of channels to assign to this group.
*
* Added in Saleor 3.14.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
addChannels?: InputMaybe<Array<Scalars['ID']>>;
/** Group name. */
name?: InputMaybe<Scalars['String']>;
/** List of permission code names to unassign from this group. */
removePermissions?: InputMaybe<Array<PermissionEnum>>;
/** List of users to unassign from this group. */
removeUsers?: InputMaybe<Array<Scalars['ID']>>;
/**
* List of channels to unassign from this group.
*
* Added in Saleor 3.14.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
removeChannels?: InputMaybe<Array<Scalars['ID']>>;
/**
* Determine if the group has restricted access to channels.
*
* Added in Saleor 3.14.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
restrictedAccessToChannels?: InputMaybe<Scalars['Boolean']>;
};
export enum PluginConfigurationType {
@ -5324,6 +5415,12 @@ export type ShopSettingsInput = {
* Added in Saleor 3.1.
*/
limitQuantityPerCheckout?: InputMaybe<Scalars['Int']>;
/**
* Enable automatic account confirmation by email.
*
* Added in Saleor 3.14.
*/
enableAccountConfirmationByEmail?: InputMaybe<Scalars['Boolean']>;
/**
* Include taxes in prices.
*
@ -5368,6 +5465,18 @@ export type StaffCreateInput = {
isActive?: InputMaybe<Scalars['Boolean']>;
/** A note about the user. */
note?: InputMaybe<Scalars['String']>;
/**
* Fields required to update the user metadata.
*
* Added in Saleor 3.14.
*/
metadata?: InputMaybe<Array<MetadataInput>>;
/**
* Fields required to update the user private metadata.
*
* Added in Saleor 3.14.
*/
privateMetadata?: InputMaybe<Array<MetadataInput>>;
/** List of permission group IDs to which user should be assigned. */
addGroups?: InputMaybe<Array<Scalars['ID']>>;
/** URL of a view where users should be redirected to set the password. URL in RFC 1808 format. */
@ -5403,6 +5512,18 @@ export type StaffUpdateInput = {
isActive?: InputMaybe<Scalars['Boolean']>;
/** A note about the user. */
note?: InputMaybe<Scalars['String']>;
/**
* Fields required to update the user metadata.
*
* Added in Saleor 3.14.
*/
metadata?: InputMaybe<Array<MetadataInput>>;
/**
* Fields required to update the user private metadata.
*
* Added in Saleor 3.14.
*/
privateMetadata?: InputMaybe<Array<MetadataInput>>;
/** List of permission group IDs to which user should be assigned. */
addGroups?: InputMaybe<Array<Scalars['ID']>>;
/** List of permission group IDs from which user should be unassigned. */
@ -6024,6 +6145,18 @@ export type UpdateInvoiceInput = {
number?: InputMaybe<Scalars['String']>;
/** URL of an invoice to download. */
url?: InputMaybe<Scalars['String']>;
/**
* Fields required to update the invoice metadata.
*
* Added in Saleor 3.14.
*/
metadata?: InputMaybe<Array<MetadataInput>>;
/**
* Fields required to update the invoice private metadata.
*
* Added in Saleor 3.14.
*/
privateMetadata?: InputMaybe<Array<MetadataInput>>;
};
/** An enumeration. */
@ -6046,6 +6179,18 @@ export type UserCreateInput = {
isActive?: InputMaybe<Scalars['Boolean']>;
/** A note about the user. */
note?: InputMaybe<Scalars['String']>;
/**
* Fields required to update the user metadata.
*
* Added in Saleor 3.14.
*/
metadata?: InputMaybe<Array<MetadataInput>>;
/**
* Fields required to update the user private metadata.
*
* Added in Saleor 3.14.
*/
privateMetadata?: InputMaybe<Array<MetadataInput>>;
/** User language code. */
languageCode?: InputMaybe<LanguageCodeEnum>;
/**
@ -6461,8 +6606,32 @@ export enum WebhookEventTypeAsyncEnum {
ORDER_CREATED = 'ORDER_CREATED',
/** An order is confirmed (status change unconfirmed -> unfulfilled) by a staff user using the OrderConfirm mutation. It also triggers when the user completes the checkout and the shop setting `automatically_confirm_all_new_orders` is enabled. */
ORDER_CONFIRMED = 'ORDER_CONFIRMED',
/**
* Payment has been made. The order may be partially or fully paid.
*
* Added in Saleor 3.14.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
ORDER_PAID = 'ORDER_PAID',
/** Payment is made and an order is fully paid. */
ORDER_FULLY_PAID = 'ORDER_FULLY_PAID',
/**
* The order received a refund. The order may be partially or fully refunded.
*
* Added in Saleor 3.14.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
ORDER_REFUNDED = 'ORDER_REFUNDED',
/**
* The order is fully refunded.
*
* Added in Saleor 3.14.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
ORDER_FULLY_REFUNDED = 'ORDER_FULLY_REFUNDED',
/** An order is updated; triggered for all changes related to an order; covers all other order webhooks, except for ORDER_CREATED. */
ORDER_UPDATED = 'ORDER_UPDATED',
/** An order is cancelled. */
@ -6768,8 +6937,32 @@ export enum WebhookEventTypeEnum {
ORDER_CREATED = 'ORDER_CREATED',
/** An order is confirmed (status change unconfirmed -> unfulfilled) by a staff user using the OrderConfirm mutation. It also triggers when the user completes the checkout and the shop setting `automatically_confirm_all_new_orders` is enabled. */
ORDER_CONFIRMED = 'ORDER_CONFIRMED',
/**
* Payment has been made. The order may be partially or fully paid.
*
* Added in Saleor 3.14.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
ORDER_PAID = 'ORDER_PAID',
/** Payment is made and an order is fully paid. */
ORDER_FULLY_PAID = 'ORDER_FULLY_PAID',
/**
* The order received a refund. The order may be partially or fully refunded.
*
* Added in Saleor 3.14.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
ORDER_REFUNDED = 'ORDER_REFUNDED',
/**
* The order is fully refunded.
*
* Added in Saleor 3.14.
*
* Note: this API is currently in Feature Preview and can be subject to changes at later point.
*/
ORDER_FULLY_REFUNDED = 'ORDER_FULLY_REFUNDED',
/** An order is updated; triggered for all changes related to an order; covers all other order webhooks, except for ORDER_CREATED. */
ORDER_UPDATED = 'ORDER_UPDATED',
/** An order is cancelled. */
@ -7151,7 +7344,10 @@ export enum WebhookSampleEventTypeEnum {
MENU_ITEM_DELETED = 'MENU_ITEM_DELETED',
ORDER_CREATED = 'ORDER_CREATED',
ORDER_CONFIRMED = 'ORDER_CONFIRMED',
ORDER_PAID = 'ORDER_PAID',
ORDER_FULLY_PAID = 'ORDER_FULLY_PAID',
ORDER_REFUNDED = 'ORDER_REFUNDED',
ORDER_FULLY_REFUNDED = 'ORDER_FULLY_REFUNDED',
ORDER_UPDATED = 'ORDER_UPDATED',
ORDER_CANCELLED = 'ORDER_CANCELLED',
ORDER_EXPIRED = 'ORDER_EXPIRED',
@ -8543,7 +8739,7 @@ export type LimitInfoFragment = { __typename: 'Limits', channels?: number | null
export type ShopLimitFragment = { __typename: 'Shop', limits: { __typename: 'LimitInfo', currentUsage: { __typename: 'Limits', channels?: number | null, orders?: number | null, productVariants?: number | null, staffUsers?: number | null, warehouses?: number | null }, allowedUsage: { __typename: 'Limits', channels?: number | null, orders?: number | null, productVariants?: number | null, staffUsers?: number | null, warehouses?: number | null } } };
export type ShopFragment = { __typename: 'Shop', customerSetPasswordUrl: string | null, defaultMailSenderAddress: string | null, defaultMailSenderName: string | null, description: string | null, name: string, reserveStockDurationAnonymousUser: number | null, reserveStockDurationAuthenticatedUser: number | null, limitQuantityPerCheckout: number | null, companyAddress: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null, countries: Array<{ __typename: 'CountryDisplay', code: string, country: string }>, domain: { __typename: 'Domain', host: string } };
export type ShopFragment = { __typename: 'Shop', customerSetPasswordUrl: string | null, defaultMailSenderAddress: string | null, defaultMailSenderName: string | null, description: string | null, name: string, reserveStockDurationAnonymousUser: number | null, reserveStockDurationAuthenticatedUser: number | null, limitQuantityPerCheckout: number | null, enableAccountConfirmationByEmail: boolean | null, companyAddress: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null, countries: Array<{ __typename: 'CountryDisplay', code: string, country: string }>, domain: { __typename: 'Domain', host: string } };
export type StaffMemberFragment = { __typename: 'User', id: string, email: string, firstName: string, isActive: boolean, lastName: string };
@ -10129,12 +10325,12 @@ export type ShopSettingsUpdateMutationVariables = Exact<{
}>;
export type ShopSettingsUpdateMutation = { __typename: 'Mutation', shopSettingsUpdate: { __typename: 'ShopSettingsUpdate', errors: Array<{ __typename: 'ShopError', code: ShopErrorCode, field: string | null, message: string | null }>, shop: { __typename: 'Shop', customerSetPasswordUrl: string | null, defaultMailSenderAddress: string | null, defaultMailSenderName: string | null, description: string | null, name: string, reserveStockDurationAnonymousUser: number | null, reserveStockDurationAuthenticatedUser: number | null, limitQuantityPerCheckout: number | null, companyAddress: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null, countries: Array<{ __typename: 'CountryDisplay', code: string, country: string }>, domain: { __typename: 'Domain', host: string } } | null } | null, shopAddressUpdate: { __typename: 'ShopAddressUpdate', errors: Array<{ __typename: 'ShopError', code: ShopErrorCode, field: string | null, message: string | null }>, shop: { __typename: 'Shop', companyAddress: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null } | null } | null };
export type ShopSettingsUpdateMutation = { __typename: 'Mutation', shopSettingsUpdate: { __typename: 'ShopSettingsUpdate', errors: Array<{ __typename: 'ShopError', code: ShopErrorCode, field: string | null, message: string | null }>, shop: { __typename: 'Shop', customerSetPasswordUrl: string | null, defaultMailSenderAddress: string | null, defaultMailSenderName: string | null, description: string | null, name: string, reserveStockDurationAnonymousUser: number | null, reserveStockDurationAuthenticatedUser: number | null, limitQuantityPerCheckout: number | null, enableAccountConfirmationByEmail: boolean | null, companyAddress: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null, countries: Array<{ __typename: 'CountryDisplay', code: string, country: string }>, domain: { __typename: 'Domain', host: string } } | null } | null, shopAddressUpdate: { __typename: 'ShopAddressUpdate', errors: Array<{ __typename: 'ShopError', code: ShopErrorCode, field: string | null, message: string | null }>, shop: { __typename: 'Shop', companyAddress: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null } | null } | null };
export type SiteSettingsQueryVariables = Exact<{ [key: string]: never; }>;
export type SiteSettingsQuery = { __typename: 'Query', shop: { __typename: 'Shop', customerSetPasswordUrl: string | null, defaultMailSenderAddress: string | null, defaultMailSenderName: string | null, description: string | null, name: string, reserveStockDurationAnonymousUser: number | null, reserveStockDurationAuthenticatedUser: number | null, limitQuantityPerCheckout: number | null, companyAddress: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null, countries: Array<{ __typename: 'CountryDisplay', code: string, country: string }>, domain: { __typename: 'Domain', host: string } } };
export type SiteSettingsQuery = { __typename: 'Query', shop: { __typename: 'Shop', customerSetPasswordUrl: string | null, defaultMailSenderAddress: string | null, defaultMailSenderName: string | null, description: string | null, name: string, reserveStockDurationAnonymousUser: number | null, reserveStockDurationAuthenticatedUser: number | null, limitQuantityPerCheckout: number | null, enableAccountConfirmationByEmail: boolean | null, companyAddress: { __typename: 'Address', city: string, cityArea: string, companyName: string, countryArea: string, firstName: string, id: string, lastName: string, phone: string | null, postalCode: string, streetAddress1: string, streetAddress2: string, country: { __typename: 'CountryDisplay', code: string, country: string } } | null, countries: Array<{ __typename: 'CountryDisplay', code: string, country: string }>, domain: { __typename: 'Domain', host: string } } };
export type StaffMemberAddMutationVariables = Exact<{
input: StaffCreateInput;

View file

@ -1,9 +1,9 @@
import { createCountryHandler } from "@dashboard/components/AddressEdit/createCountryHandler";
import { TopNav } from "@dashboard/components/AppLayout/TopNav";
import { DashboardCard } from "@dashboard/components/Card";
import CompanyAddressInput from "@dashboard/components/CompanyAddressInput";
import { ConfirmButtonTransitionState } from "@dashboard/components/ConfirmButton";
import Form from "@dashboard/components/Form";
import Hr from "@dashboard/components/Hr";
import { DetailPageLayout } from "@dashboard/components/Layouts";
import PageSectionHeader from "@dashboard/components/PageSectionHeader";
import Savebar from "@dashboard/components/Savebar";
@ -16,8 +16,7 @@ import useStateFromProps from "@dashboard/hooks/useStateFromProps";
import { commonMessages } from "@dashboard/intl";
import createSingleAutocompleteSelectHandler from "@dashboard/utils/handlers/singleAutocompleteSelectChangeHandler";
import { mapCountriesToChoices } from "@dashboard/utils/maps";
import { makeStyles } from "@saleor/macaw-ui";
import { Box } from "@saleor/macaw-ui/next";
import { Box, Checkbox, Divider, Text } from "@saleor/macaw-ui/next";
import React from "react";
import { useIntl } from "react-intl";
@ -41,6 +40,7 @@ export interface SiteSettingsPageFormData
reserveStockDurationAnonymousUser: number;
reserveStockDurationAuthenticatedUser: number;
limitQuantityPerCheckout: number;
emailConfirmation: boolean;
}
export interface SiteSettingsPageProps {
@ -69,22 +69,8 @@ export function areAddressInputFieldsModified(
.some(field => field !== "");
}
const useStyles = makeStyles(
theme => ({
hr: {
gridColumnEnd: "span 2",
margin: theme.spacing(1, 0),
},
}),
{
name: "SiteSettingsPage",
},
);
const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
const { disabled, errors, saveButtonBarState, shop, onSubmit } = props;
const classes = useStyles(props);
const intl = useIntl();
const navigate = useNavigator();
@ -105,6 +91,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
streetAddress1: shop?.companyAddress?.streetAddress1 || "",
streetAddress2: shop?.companyAddress?.streetAddress2 || "",
};
const initialForm: SiteSettingsPageFormData = {
...initialFormAddress,
description: shop?.description || "",
@ -113,6 +100,7 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
reserveStockDurationAuthenticatedUser:
shop?.reserveStockDurationAuthenticatedUser ?? 0,
limitQuantityPerCheckout: shop?.limitQuantityPerCheckout ?? 0,
emailConfirmation: shop?.enableAccountConfirmationByEmail ?? false,
};
return (
@ -137,6 +125,10 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
const handleCountrySelect = createCountryHandler(countrySelect, set);
const handleEmailConfirmationChange = isEnabled => {
change({ target: { name: "emailConfirmation", value: isEnabled } });
};
return (
<DetailPageLayout gridTemplateColumns={1}>
<TopNav
@ -144,8 +136,12 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
title={intl.formatMessage(commonMessages.generalInformations)}
/>
<DetailPageLayout.Content>
<Box gap={2} paddingLeft={6}>
<Box display="grid" __gridTemplateColumns="1fr 3fr">
<Box gap={2}>
<Box
display="grid"
__gridTemplateColumns="1fr 3fr"
paddingLeft={6}
>
<PageSectionHeader
title={intl.formatMessage(messages.sectionCheckoutTitle)}
description={intl.formatMessage(
@ -160,9 +156,14 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
/>
</Box>
<Hr className={classes.hr} />
<Divider />
<Box display="grid" __gridTemplateColumns="1fr 3fr">
<Box
display="grid"
__gridTemplateColumns="1fr 3fr"
paddingLeft={6}
paddingBottom={8}
>
<PageSectionHeader
title={intl.formatMessage(messages.sectionCompanyTitle)}
description={intl.formatMessage(
@ -184,6 +185,43 @@ const SiteSettingsPage: React.FC<SiteSettingsPageProps> = props => {
onCountryChange={handleCountrySelect}
/>
</Box>
<Divider />
<Box
display="grid"
__gridTemplateColumns="1fr 3fr"
paddingLeft={6}
paddingBottom={8}
>
<PageSectionHeader
title={intl.formatMessage(
messages.sectionEmailConfirmationTitle,
)}
description={intl.formatMessage(
messages.sectionEmailConfirmationDescription,
)}
/>
<DashboardCard>
<DashboardCard.Title>
{intl.formatMessage(
messages.sectionEmailConfirmationHeader,
)}
</DashboardCard.Title>
<DashboardCard.Content>
<Checkbox
checked={data.emailConfirmation}
onCheckedChange={handleEmailConfirmationChange}
>
<Text variant="body">
{intl.formatMessage(
messages.sectionEmailConfirmationHeader,
)}
</Text>
</Checkbox>
</DashboardCard.Content>
</DashboardCard>
</Box>
</Box>
<Savebar

View file

@ -23,4 +23,26 @@ export const messages = defineMessages({
"This address will be used to generate invoices and calculate shipping rates. Email address you provide here will be used as a contact address for your customers.",
description: "section description",
},
sectionEmailConfirmationTitle: {
id: "qNeXG1",
defaultMessage: "User registration",
description: "User registration",
},
sectionEmailConfirmationHeader: {
id: "kpRxSA",
defaultMessage: "Require email confirmation link",
description: "Require email confirmation link",
},
sectionEmailConfirmationOption: {
id: "uRfta0",
defaultMessage: "Enable email confirmation",
description: "Enable email confirmation",
},
sectionEmailConfirmationDescription: {
id: "/xJSe8",
defaultMessage:
"When users confirm their email account, all previous anonymous orders placed under the same email would be added to their order history.",
description:
"When users confirm their email account, all previous anonymous orders placed under the same email would be added to their order history.",
},
});

View file

@ -40,4 +40,5 @@ export const shop: SiteSettingsQuery["shop"] = {
reserveStockDurationAnonymousUser: 10,
reserveStockDurationAuthenticatedUser: 10,
limitQuantityPerCheckout: 50,
enableAccountConfirmationByEmail: true,
};

View file

@ -28,24 +28,22 @@ export const SiteSettings: React.FC<SiteSettingsProps> = () => {
displayLoader: true,
});
const [
updateShopSettings,
updateShopSettingsOpts,
] = useShopSettingsUpdateMutation({
onCompleted: data => {
if (
[
...(data?.shopAddressUpdate?.errors || []),
...(data?.shopSettingsUpdate?.errors || []),
].length === 0
) {
notify({
status: "success",
text: intl.formatMessage(commonMessages.savedChanges),
});
}
},
});
const [updateShopSettings, updateShopSettingsOpts] =
useShopSettingsUpdateMutation({
onCompleted: data => {
if (
[
...(data?.shopAddressUpdate?.errors || []),
...(data?.shopSettingsUpdate?.errors || []),
].length === 0
) {
notify({
status: "success",
text: intl.formatMessage(commonMessages.savedChanges),
});
}
},
});
const errors = [
...(updateShopSettingsOpts.data?.shopSettingsUpdate?.errors || []),
@ -79,6 +77,7 @@ export const SiteSettings: React.FC<SiteSettingsProps> = () => {
data.reserveStockDurationAnonymousUser || null,
reserveStockDurationAuthenticatedUser:
data.reserveStockDurationAuthenticatedUser || null,
enableAccountConfirmationByEmail: data.emailConfirmation,
},
},
}),

View file

@ -1,10 +1,10 @@
import CardTitle from "@dashboard/components/CardTitle";
import { DashboardCard } from "@dashboard/components/Card";
import { WarehouseErrorFragment } from "@dashboard/graphql";
import { FormChange } from "@dashboard/hooks/useForm";
import { commonMessages } from "@dashboard/intl";
import { getFormErrors } from "@dashboard/utils/errors";
import getWarehouseErrorMessage from "@dashboard/utils/errors/warehouse";
import { Card, CardContent, TextField } from "@material-ui/core";
import { TextField } from "@material-ui/core";
import React from "react";
import { useIntl } from "react-intl";
@ -26,11 +26,11 @@ const WarehouseInfo: React.FC<WarehouseInfoProps> = ({
const formErrors = getFormErrors(["name"], errors);
return (
<Card data-test-id="general-information-section">
<CardTitle
title={intl.formatMessage(commonMessages.generalInformations)}
/>
<CardContent>
<DashboardCard data-test-id="general-information-section" paddingTop={9}>
<DashboardCard.Title>
{intl.formatMessage(commonMessages.generalInformations)}
</DashboardCard.Title>
<DashboardCard.Content>
<TextField
disabled={disabled}
error={!!formErrors.name}
@ -49,8 +49,8 @@ const WarehouseInfo: React.FC<WarehouseInfoProps> = ({
},
}}
/>
</CardContent>
</Card>
</DashboardCard.Content>
</DashboardCard>
);
};