Product reference attributes (#948)

* Update changelog with product reference attributes

* 2068 - Add product reference type to attributes (#949)

* 2069 - Add product reference attribute search implementation (#951)
This commit is contained in:
Dawid Tarasiuk 2021-01-20 17:37:36 +01:00 committed by GitHub
parent f0f9fe9b85
commit 11bddd3d1b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
74 changed files with 740 additions and 172 deletions

View file

@ -15,6 +15,7 @@ All notable, unreleased changes to this project will be documented in this file.
- Add shipping delivery days - #914 by @orzechdev - Add shipping delivery days - #914 by @orzechdev
- Guard against non-staff users logging in - #947 by @jwm0 - Guard against non-staff users logging in - #947 by @jwm0
- Add reference attributes - #917 by @orzechdev - Add reference attributes - #917 by @orzechdev
- Add product reference attributes - #948 by @orzechdev
# 2.11.1 # 2.11.1

View file

@ -813,6 +813,10 @@
"context": "page attribute entity type", "context": "page attribute entity type",
"string": "Pages" "string": "Pages"
}, },
"src_dot_attributes_dot_components_dot_AttributeDetails_dot_product": {
"context": "product attribute entity type",
"string": "Products"
},
"src_dot_attributes_dot_components_dot_AttributeDetails_dot_references": { "src_dot_attributes_dot_components_dot_AttributeDetails_dot_references": {
"context": "references attribute type", "context": "references attribute type",
"string": "References" "string": "References"

View file

@ -454,6 +454,7 @@ type AttributeDelete {
enum AttributeEntityTypeEnum { enum AttributeEntityTypeEnum {
PAGE PAGE
PRODUCT
} }
type AttributeError { type AttributeError {
@ -570,7 +571,6 @@ type AttributeValue implements Node {
id: ID! id: ID!
name: String name: String
slug: String slug: String
type: AttributeValueType @deprecated(reason: "Use the `inputType` field to determine the type of attribute's value. This field will be removed after 2020-07-31.")
translation(languageCode: LanguageCodeEnum!): AttributeValueTranslation translation(languageCode: LanguageCodeEnum!): AttributeValueTranslation
inputType: AttributeInputTypeEnum inputType: AttributeInputTypeEnum
reference: ID reference: ID
@ -628,13 +628,6 @@ type AttributeValueTranslation implements Node {
language: LanguageDisplay! language: LanguageDisplay!
} }
enum AttributeValueType {
COLOR
GRADIENT
URL
STRING
}
type AttributeValueUpdate { type AttributeValueUpdate {
errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.") errors: [Error!]! @deprecated(reason: "Use typed errors with error codes. This field will be removed after 2020-07-31.")
attribute: Attribute attribute: Attribute
@ -2319,10 +2312,12 @@ type Margin {
stop: Int stop: Int
} }
type Menu implements Node { type Menu implements Node & ObjectWithMetadata {
id: ID! id: ID!
name: String! name: String!
slug: String! slug: String!
privateMetadata: [MetadataItem]!
metadata: [MetadataItem]!
items: [MenuItem] items: [MenuItem]
} }
@ -2389,7 +2384,7 @@ input MenuInput {
slug: String slug: String
} }
type MenuItem implements Node { type MenuItem implements Node & ObjectWithMetadata {
id: ID! id: ID!
name: String! name: String!
menu: Menu! menu: Menu!
@ -2398,6 +2393,8 @@ type MenuItem implements Node {
collection: Collection collection: Collection
page: Page page: Page
level: Int! level: Int!
privateMetadata: [MetadataItem]!
metadata: [MetadataItem]!
children: [MenuItem] children: [MenuItem]
url: String url: String
translation(languageCode: LanguageCodeEnum!): MenuItemTranslation translation(languageCode: LanguageCodeEnum!): MenuItemTranslation
@ -2841,6 +2838,7 @@ type Order implements Node & ObjectWithMetadata {
shippingMethodName: String shippingMethodName: String
channel: Channel! channel: Channel!
shippingPrice: TaxedMoney shippingPrice: TaxedMoney
shippingTaxRate: Float!
token: String! token: String!
voucher: Voucher voucher: Voucher
giftCards: [GiftCard] giftCards: [GiftCard]
@ -2937,6 +2935,7 @@ input OrderDraftFilterInput {
customer: String customer: String
created: DateRangeInput created: DateRangeInput
search: String search: String
channels: [ID]
} }
type OrderError { type OrderError {
@ -4241,12 +4240,8 @@ type ProductVariant implements Node & ObjectWithMetadata {
weight: Weight weight: Weight
privateMetadata: [MetadataItem]! privateMetadata: [MetadataItem]!
metadata: [MetadataItem]! metadata: [MetadataItem]!
quantity: Int! @deprecated(reason: "Use the stock field instead. This field will be removed after 2020-07-31.")
quantityAllocated: Int @deprecated(reason: "Use the stock field instead. This field will be removed after 2020-07-31.")
stockQuantity: Int! @deprecated(reason: "Use the quantityAvailable field instead. This field will be removed after 2020-07-31.")
channelListings: [ProductVariantChannelListing!] channelListings: [ProductVariantChannelListing!]
pricing: VariantPricingInfo pricing: VariantPricingInfo
isAvailable: Boolean @deprecated(reason: "Use the stock field instead. This field will be removed after 2020-07-31.")
attributes(variantSelection: VariantAttributeScope): [SelectedAttribute!]! attributes(variantSelection: VariantAttributeScope): [SelectedAttribute!]!
costPrice: Money costPrice: Money
margin: Int margin: Int
@ -4484,7 +4479,7 @@ type Query {
permissionGroup(id: ID!): Group permissionGroup(id: ID!): Group
me: User me: User
staffUsers(filter: StaffUserInput, sortBy: UserSortingInput, before: String, after: String, first: Int, last: Int): UserCountableConnection staffUsers(filter: StaffUserInput, sortBy: UserSortingInput, before: String, after: String, first: Int, last: Int): UserCountableConnection
user(id: ID!): User user(id: ID, email: String): User
_entities(representations: [_Any]): [_Entity] _entities(representations: [_Any]): [_Entity]
_service: _Service _service: _Service
} }

View file

@ -71,6 +71,10 @@ const entityTypeMessages = defineMessages({
page: { page: {
defaultMessage: "Pages", defaultMessage: "Pages",
description: "page attribute entity type" description: "page attribute entity type"
},
product: {
defaultMessage: "Products",
description: "product attribute entity type"
} }
}); });
@ -122,6 +126,10 @@ const AttributeDetails: React.FC<AttributeDetailsProps> = props => {
{ {
label: intl.formatMessage(entityTypeMessages.page), label: intl.formatMessage(entityTypeMessages.page),
value: AttributeEntityTypeEnum.PAGE value: AttributeEntityTypeEnum.PAGE
},
{
label: intl.formatMessage(entityTypeMessages.product),
value: AttributeEntityTypeEnum.PRODUCT
} }
]; ];

View file

@ -10,10 +10,13 @@ import { FormsetData } from "@saleor/hooks/useFormset";
import { PageDetails_page_attributes } from "@saleor/pages/types/PageDetails"; import { PageDetails_page_attributes } from "@saleor/pages/types/PageDetails";
import { ProductDetails_product_attributes } from "@saleor/products/types/ProductDetails"; import { ProductDetails_product_attributes } from "@saleor/products/types/ProductDetails";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { import {
AttributeEntityTypeEnum,
AttributeInputTypeEnum, AttributeInputTypeEnum,
AttributeValueInput AttributeValueInput
} from "@saleor/types/globalTypes"; } from "@saleor/types/globalTypes";
import { mapNodeToChoice, mapPagesToChoices } from "@saleor/utils/maps";
import { MutationFetchResult } from "react-apollo"; import { MutationFetchResult } from "react-apollo";
import { AttributePageFormData } from "../components/AttributePage"; import { AttributePageFormData } from "../components/AttributePage";
@ -25,6 +28,11 @@ export const ATTRIBUTE_TYPES_WITH_DEDICATED_VALUES = [
AttributeInputTypeEnum.MULTISELECT AttributeInputTypeEnum.MULTISELECT
]; ];
export interface AttributeReference {
label: string;
value: string;
}
function getSimpleAttributeData( function getSimpleAttributeData(
data: AttributePageFormData, data: AttributePageFormData,
values: AttributeValueEditDialogFormData[] values: AttributeValueEditDialogFormData[]
@ -199,7 +207,7 @@ export const getFileAttributeDisplayData = (
return attribute; return attribute;
}; };
export const getReferenceAttributeDisplayData = ( export const getPageReferenceAttributeDisplayData = (
attribute: AttributeInput, attribute: AttributeInput,
referencePages: SearchPages_search_edges_node[] referencePages: SearchPages_search_edges_node[]
) => ({ ) => ({
@ -208,21 +216,67 @@ export const getReferenceAttributeDisplayData = (
...attribute.data, ...attribute.data,
references: references:
referencePages?.length > 0 && attribute.value?.length > 0 referencePages?.length > 0 && attribute.value?.length > 0
? attribute.value.map(value => ? mapPagesToChoices(
referencePages.find(reference => reference.id === value) attribute.value.map(value => {
const reference = referencePages.find(
reference => reference.id === value
);
return { ...reference };
})
) )
: [] : []
} }
}); });
export const getProductReferenceAttributeDisplayData = (
attribute: AttributeInput,
referenceProducts: SearchProducts_search_edges_node[]
) => ({
...attribute,
data: {
...attribute.data,
references:
referenceProducts?.length > 0 && attribute.value?.length > 0
? mapNodeToChoice(
attribute.value.map(value => {
const reference = referenceProducts.find(
reference => reference.id === value
);
return { ...reference };
})
)
: []
}
});
export const getReferenceAttributeDisplayData = (
attribute: AttributeInput,
referencePages: SearchPages_search_edges_node[],
referenceProducts: SearchProducts_search_edges_node[]
) => {
if (attribute.data.entityType === AttributeEntityTypeEnum.PAGE) {
return getPageReferenceAttributeDisplayData(attribute, referencePages);
} else if (attribute.data.entityType === AttributeEntityTypeEnum.PRODUCT) {
return getProductReferenceAttributeDisplayData(
attribute,
referenceProducts
);
}
};
export const getAttributesDisplayData = ( export const getAttributesDisplayData = (
attributes: AttributeInput[], attributes: AttributeInput[],
attributesWithNewFileValue: FormsetData<null, File>, attributesWithNewFileValue: FormsetData<null, File>,
referencePages: SearchPages_search_edges_node[] referencePages: SearchPages_search_edges_node[],
referenceProducts: SearchProducts_search_edges_node[]
) => ) =>
attributes.map(attribute => { attributes.map(attribute => {
if (attribute.data.inputType === AttributeInputTypeEnum.REFERENCE) { if (attribute.data.inputType === AttributeInputTypeEnum.REFERENCE) {
return getReferenceAttributeDisplayData(attribute, referencePages); return getReferenceAttributeDisplayData(
attribute,
referencePages,
referenceProducts
);
} }
if (attribute.data.inputType === AttributeInputTypeEnum.FILE) { if (attribute.data.inputType === AttributeInputTypeEnum.FILE) {
return getFileAttributeDisplayData(attribute, attributesWithNewFileValue); return getFileAttributeDisplayData(attribute, attributesWithNewFileValue);
@ -230,3 +284,34 @@ export const getAttributesDisplayData = (
return attribute; return attribute;
}); });
export const getSelectedReferencesFromAttribute = <
Node extends SearchPages_search_edges_node | SearchProducts_search_edges_node
>(
attribute?: AttributeInput,
references?: Node[]
) =>
references?.filter(
value =>
!attribute?.value?.some(selectedValue => selectedValue === value.id)
) || [];
export const getAttributeValuesFromReferences = (
attributeId: string,
attributes?: AttributeInput[],
referencePages?: SearchPages_search_edges_node[],
referenceProducts?: SearchProducts_search_edges_node[]
) => {
const attribute = attributes?.find(attribute => attribute.id === attributeId);
if (attribute?.data?.entityType === AttributeEntityTypeEnum.PAGE) {
return mapPagesToChoices(
getSelectedReferencesFromAttribute(attribute, referencePages)
);
} else if (attribute?.data?.entityType === AttributeEntityTypeEnum.PRODUCT) {
return mapNodeToChoice(
getSelectedReferencesFromAttribute(attribute, referenceProducts)
);
}
return [];
};

View file

@ -12,8 +12,9 @@ import {
FormsetData FormsetData
} from "@saleor/hooks/useFormset"; } from "@saleor/hooks/useFormset";
import { PageDetails_page_attributes } from "@saleor/pages/types/PageDetails"; import { PageDetails_page_attributes } from "@saleor/pages/types/PageDetails";
import { ReorderEvent } from "@saleor/types"; import { FetchMoreProps, ReorderEvent } from "@saleor/types";
import { import {
AttributeEntityTypeEnum,
AttributeInputTypeEnum, AttributeInputTypeEnum,
AttributeValueInput AttributeValueInput
} from "@saleor/types/globalTypes"; } from "@saleor/types/globalTypes";
@ -67,6 +68,56 @@ export function createAttributeReferenceChangeHandler(
}; };
} }
export function createFetchReferencesHandler(
attributes: FormsetData<AttributeInputData, string[]>,
assignReferencesAttributeId: string,
fetchReferencePages?: (data: string) => void,
fetchReferenceProducts?: (data: string) => void
) {
return (value: string) => {
const attribute = attributes?.find(
attribute => attribute.id === assignReferencesAttributeId
);
if (!attribute) {
return;
}
if (
attribute.data.entityType === AttributeEntityTypeEnum.PAGE &&
fetchReferencePages
) {
fetchReferencePages(value);
} else if (
attribute.data.entityType === AttributeEntityTypeEnum.PRODUCT &&
fetchReferenceProducts
) {
fetchReferenceProducts(value);
}
};
}
export function createFetchMoreReferencesHandler(
attributes: FormsetData<AttributeInputData, string[]>,
assignReferencesAttributeId: string,
fetchMoreReferencePages?: FetchMoreProps,
fetchMoreReferenceProducts?: FetchMoreProps
) {
const attribute = attributes?.find(
attribute => attribute.id === assignReferencesAttributeId
);
if (!attribute) {
return;
}
if (attribute.data.entityType === AttributeEntityTypeEnum.PAGE) {
return fetchMoreReferencePages;
} else if (attribute.data.entityType === AttributeEntityTypeEnum.PRODUCT) {
return fetchMoreReferenceProducts;
}
}
export function createAttributeFileChangeHandler( export function createAttributeFileChangeHandler(
changeAttributeData: FormsetChange<string[]>, changeAttributeData: FormsetChange<string[]>,
attributesWithNewFileValue: FormsetData<FormsetData<null, File>>, attributesWithNewFileValue: FormsetData<FormsetData<null, File>>,

View file

@ -1,4 +1,4 @@
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { AttributeReference } from "@saleor/attributes/utils/data";
import React from "react"; import React from "react";
import { defineMessages, useIntl } from "react-intl"; import { defineMessages, useIntl } from "react-intl";
@ -26,7 +26,7 @@ interface AssignAttributeValueDialogProps
AssignContainerDialogProps, AssignContainerDialogProps,
"containers" | "title" | "search" | "confirmButtonState" "containers" | "title" | "search" | "confirmButtonState"
> { > {
attributeValues: SearchPages_search_edges_node[]; attributeValues: AttributeReference[];
} }
const AssignAttributeValueDialog: React.FC<AssignAttributeValueDialogProps> = ({ const AssignAttributeValueDialog: React.FC<AssignAttributeValueDialogProps> = ({
@ -38,8 +38,8 @@ const AssignAttributeValueDialog: React.FC<AssignAttributeValueDialogProps> = ({
return ( return (
<AssignContainerDialog <AssignContainerDialog
containers={attributeValues.map(value => ({ containers={attributeValues.map(value => ({
id: value.id, id: value.value,
name: value.title name: value.label
}))} }))}
search={{ search={{
label: intl.formatMessage(messages.searchLabel), label: intl.formatMessage(messages.searchLabel),

View file

@ -4,6 +4,7 @@ import IconButton from "@material-ui/core/IconButton";
import makeStyles from "@material-ui/core/styles/makeStyles"; import makeStyles from "@material-ui/core/styles/makeStyles";
import Typography from "@material-ui/core/Typography"; import Typography from "@material-ui/core/Typography";
import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown"; import ArrowDropDownIcon from "@material-ui/icons/ArrowDropDown";
import { AttributeReference } from "@saleor/attributes/utils/data";
import CardTitle from "@saleor/components/CardTitle"; import CardTitle from "@saleor/components/CardTitle";
import Hr from "@saleor/components/Hr"; import Hr from "@saleor/components/Hr";
import MultiAutocompleteSelectField, { import MultiAutocompleteSelectField, {
@ -16,9 +17,11 @@ import { AttributeValueFragment } from "@saleor/fragments/types/AttributeValueFr
import { PageErrorWithAttributesFragment } from "@saleor/fragments/types/PageErrorWithAttributesFragment"; import { PageErrorWithAttributesFragment } from "@saleor/fragments/types/PageErrorWithAttributesFragment";
import { ProductErrorWithAttributesFragment } from "@saleor/fragments/types/ProductErrorWithAttributesFragment"; import { ProductErrorWithAttributesFragment } from "@saleor/fragments/types/ProductErrorWithAttributesFragment";
import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset"; import { FormsetAtomicData, FormsetChange } from "@saleor/hooks/useFormset";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { ReorderEvent } from "@saleor/types"; import { ReorderEvent } from "@saleor/types";
import { AttributeInputTypeEnum } from "@saleor/types/globalTypes"; import {
AttributeEntityTypeEnum,
AttributeInputTypeEnum
} from "@saleor/types/globalTypes";
import { getProductErrorMessage } from "@saleor/utils/errors"; import { getProductErrorMessage } from "@saleor/utils/errors";
import getPageErrorMessage from "@saleor/utils/errors/page"; import getPageErrorMessage from "@saleor/utils/errors/page";
import classNames from "classnames"; import classNames from "classnames";
@ -40,11 +43,12 @@ import { VariantAttributeScope } from "./types";
export interface AttributeInputData { export interface AttributeInputData {
inputType: AttributeInputTypeEnum; inputType: AttributeInputTypeEnum;
entityType?: AttributeEntityTypeEnum;
variantAttributeScope?: VariantAttributeScope; variantAttributeScope?: VariantAttributeScope;
isRequired: boolean; isRequired: boolean;
values: AttributeValueFragment[]; values: AttributeValueFragment[];
selectedValues?: AttributeValueFragment[]; selectedValues?: AttributeValueFragment[];
references?: SearchPages_search_edges_node[]; references?: AttributeReference[];
} }
export type AttributeInput = FormsetAtomicData<AttributeInputData, string[]>; export type AttributeInput = FormsetAtomicData<AttributeInputData, string[]>;
export type AttributeFileInput = FormsetAtomicData<AttributeInputData, File[]>; export type AttributeFileInput = FormsetAtomicData<AttributeInputData, File[]>;
@ -175,14 +179,11 @@ function getReferenceDisplayValue(
} }
const definedAttributeReference = attribute.data.references?.find( const definedAttributeReference = attribute.data.references?.find(
reference => reference.id === attributeValue reference => reference.value === attributeValue
); );
// If value has not been yet assigned, use data of reference // If value has not been yet assigned, use data of reference
if (!!definedAttributeReference) { if (!!definedAttributeReference) {
return { return definedAttributeReference;
label: definedAttributeReference.title,
value: definedAttributeReference.id
};
} }
return { return {

View file

@ -1,4 +1,7 @@
import { AttributeInputTypeEnum } from "@saleor/types/globalTypes"; import {
AttributeEntityTypeEnum,
AttributeInputTypeEnum
} from "@saleor/types/globalTypes";
import { AttributeInput } from "./Attributes"; import { AttributeInput } from "./Attributes";
@ -92,23 +95,21 @@ const FILE_ATTRIBUTE: AttributeInput = {
const REFERENCE_ATTRIBUTE: AttributeInput = { const REFERENCE_ATTRIBUTE: AttributeInput = {
data: { data: {
entityType: AttributeEntityTypeEnum.PAGE,
inputType: AttributeInputTypeEnum.REFERENCE, inputType: AttributeInputTypeEnum.REFERENCE,
isRequired: true, isRequired: true,
references: [ references: [
{ {
__typename: "Page", label: "References First Value",
id: "vbnhgcvjhbvhj", value: "vbnhgcvjhbvhj"
title: "References First Value"
}, },
{ {
__typename: "Page", label: "References Second Value",
id: "gucngdfdfvdvd", value: "gucngdfdfvdvd"
title: "References Second Value"
}, },
{ {
__typename: "Page", label: "References Third Value",
id: "dfdfdsfdsfdse", value: "dfdfdsfdsfdse"
title: "References Third Value"
} }
], ],
values: [ values: [

View file

@ -21,6 +21,7 @@ export const pageAttributesFragment = gql`
slug slug
name name
inputType inputType
entityType
valueRequired valueRequired
values { values {
...AttributeValueFragment ...AttributeValueFragment
@ -37,6 +38,7 @@ export const pageAttributesFragment = gql`
id id
name name
inputType inputType
entityType
valueRequired valueRequired
values { values {
...AttributeValueFragment ...AttributeValueFragment

View file

@ -123,6 +123,7 @@ export const productVariantAttributesFragment = gql`
slug slug
name name
inputType inputType
entityType
valueRequired valueRequired
values { values {
...AttributeValueFragment ...AttributeValueFragment
@ -231,6 +232,7 @@ export const variantAttributeFragment = gql`
name name
slug slug
inputType inputType
entityType
valueRequired valueRequired
values { values {
...AttributeValueFragment ...AttributeValueFragment

View file

@ -19,7 +19,7 @@ export interface MetadataFragment_privateMetadata {
} }
export interface MetadataFragment { export interface MetadataFragment {
__typename: "App" | "ShippingZone" | "ShippingMethod" | "Product" | "ProductType" | "Attribute" | "Category" | "ProductVariant" | "DigitalContent" | "Collection" | "Page" | "PageType" | "User" | "Checkout" | "Order" | "Fulfillment" | "Invoice"; __typename: "App" | "ShippingZone" | "ShippingMethod" | "Product" | "ProductType" | "Attribute" | "Category" | "ProductVariant" | "DigitalContent" | "Collection" | "Page" | "PageType" | "MenuItem" | "Menu" | "User" | "Checkout" | "Order" | "Fulfillment" | "Invoice";
metadata: (MetadataFragment_metadata | null)[]; metadata: (MetadataFragment_metadata | null)[];
privateMetadata: (MetadataFragment_privateMetadata | null)[]; privateMetadata: (MetadataFragment_privateMetadata | null)[];
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL fragment: PageAttributesFragment // GraphQL fragment: PageAttributesFragment
@ -29,6 +29,7 @@ export interface PageAttributesFragment_attributes_attribute {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (PageAttributesFragment_attributes_attribute_values | null)[] | null; values: (PageAttributesFragment_attributes_attribute_values | null)[] | null;
} }
@ -74,6 +75,7 @@ export interface PageAttributesFragment_pageType_attributes {
id: string; id: string;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (PageAttributesFragment_pageType_attributes_values | null)[] | null; values: (PageAttributesFragment_pageType_attributes_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL fragment: PageDetailsFragment // GraphQL fragment: PageDetailsFragment
@ -29,6 +29,7 @@ export interface PageDetailsFragment_attributes_attribute {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (PageDetailsFragment_attributes_attribute_values | null)[] | null; values: (PageDetailsFragment_attributes_attribute_values | null)[] | null;
} }
@ -74,6 +75,7 @@ export interface PageDetailsFragment_pageType_attributes {
id: string; id: string;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (PageDetailsFragment_pageType_attributes_values | null)[] | null; values: (PageDetailsFragment_pageType_attributes_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL fragment: Product // GraphQL fragment: Product
@ -29,6 +29,7 @@ export interface Product_attributes_attribute {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (Product_attributes_attribute_values | null)[] | null; values: (Product_attributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL fragment: ProductVariant // GraphQL fragment: ProductVariant
@ -41,6 +41,7 @@ export interface ProductVariant_selectionAttributes_attribute {
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductVariant_selectionAttributes_attribute_values | null)[] | null; values: (ProductVariant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -87,6 +88,7 @@ export interface ProductVariant_nonSelectionAttributes_attribute {
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductVariant_nonSelectionAttributes_attribute_values | null)[] | null; values: (ProductVariant_nonSelectionAttributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL fragment: ProductVariantAttributesFragment // GraphQL fragment: ProductVariantAttributesFragment
@ -29,6 +29,7 @@ export interface ProductVariantAttributesFragment_attributes_attribute {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductVariantAttributesFragment_attributes_attribute_values | null)[] | null; values: (ProductVariantAttributesFragment_attributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL fragment: SelectedVariantAttributeFragment // GraphQL fragment: SelectedVariantAttributeFragment
@ -29,6 +29,7 @@ export interface SelectedVariantAttributeFragment_attribute {
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (SelectedVariantAttributeFragment_attribute_values | null)[] | null; values: (SelectedVariantAttributeFragment_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL fragment: VariantAttributeFragment // GraphQL fragment: VariantAttributeFragment
@ -29,6 +29,7 @@ export interface VariantAttributeFragment {
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (VariantAttributeFragment_values | null)[] | null; values: (VariantAttributeFragment_values | null)[] | null;
} }

View file

@ -1,4 +1,7 @@
import { mergeAttributeValues } from "@saleor/attributes/utils/data"; import {
getAttributeValuesFromReferences,
mergeAttributeValues
} from "@saleor/attributes/utils/data";
import AppHeader from "@saleor/components/AppHeader"; import AppHeader from "@saleor/components/AppHeader";
import AssignAttributeValueDialog from "@saleor/components/AssignAttributeValueDialog"; import AssignAttributeValueDialog from "@saleor/components/AssignAttributeValueDialog";
import Attributes, { AttributeInput } from "@saleor/components/Attributes"; import Attributes, { AttributeInput } from "@saleor/components/Attributes";
@ -15,9 +18,9 @@ import { PageErrorWithAttributesFragment } from "@saleor/fragments/types/PageErr
import useDateLocalize from "@saleor/hooks/useDateLocalize"; import useDateLocalize from "@saleor/hooks/useDateLocalize";
import { SubmitPromise } from "@saleor/hooks/useForm"; import { SubmitPromise } from "@saleor/hooks/useForm";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { getAttributeValuesFromReferences } from "@saleor/pages/utils/data";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchPageTypes_search_edges_node } from "@saleor/searches/types/SearchPageTypes"; import { SearchPageTypes_search_edges_node } from "@saleor/searches/types/SearchPageTypes";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { FetchMoreProps } from "@saleor/types"; import { FetchMoreProps } from "@saleor/types";
import React from "react"; import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
@ -32,7 +35,8 @@ export interface PageDetailsPageProps {
errors: PageErrorWithAttributesFragment[]; errors: PageErrorWithAttributesFragment[];
page: PageDetails_page; page: PageDetails_page;
pageTypes?: SearchPageTypes_search_edges_node[]; pageTypes?: SearchPageTypes_search_edges_node[];
referencePages: SearchPages_search_edges_node[]; referencePages?: SearchPages_search_edges_node[];
referenceProducts?: SearchProducts_search_edges_node[];
allowEmptySlug?: boolean; allowEmptySlug?: boolean;
saveButtonBarState: ConfirmButtonTransitionState; saveButtonBarState: ConfirmButtonTransitionState;
onBack: () => void; onBack: () => void;
@ -44,6 +48,8 @@ export interface PageDetailsPageProps {
onAssignReferencesClick: (attribute: AttributeInput) => void; onAssignReferencesClick: (attribute: AttributeInput) => void;
fetchReferencePages?: (data: string) => void; fetchReferencePages?: (data: string) => void;
fetchMoreReferencePages?: FetchMoreProps; fetchMoreReferencePages?: FetchMoreProps;
fetchReferenceProducts?: (data: string) => void;
fetchMoreReferenceProducts?: FetchMoreProps;
onCloseDialog: () => void; onCloseDialog: () => void;
} }
@ -52,7 +58,8 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
errors, errors,
page, page,
pageTypes, pageTypes,
referencePages, referencePages = [],
referenceProducts = [],
saveButtonBarState, saveButtonBarState,
onBack, onBack,
onRemove, onRemove,
@ -63,6 +70,8 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
onAssignReferencesClick, onAssignReferencesClick,
fetchReferencePages, fetchReferencePages,
fetchMoreReferencePages, fetchMoreReferencePages,
fetchReferenceProducts,
fetchMoreReferenceProducts,
onCloseDialog onCloseDialog
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
@ -93,6 +102,12 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
page={page} page={page}
pageTypes={pageTypes} pageTypes={pageTypes}
referencePages={referencePages} referencePages={referencePages}
referenceProducts={referenceProducts}
fetchReferencePages={fetchReferencePages}
fetchMoreReferencePages={fetchMoreReferencePages}
fetchReferenceProducts={fetchReferenceProducts}
fetchMoreReferenceProducts={fetchMoreReferenceProducts}
assignReferencesAttributeId={assignReferencesAttributeId}
onSubmit={onSubmit} onSubmit={onSubmit}
> >
{({ change, data, pageType, handlers, hasChanged, submit }) => ( {({ change, data, pageType, handlers, hasChanged, submit }) => (
@ -208,13 +223,14 @@ const PageDetailsPage: React.FC<PageDetailsPageProps> = ({
attributeValues={getAttributeValuesFromReferences( attributeValues={getAttributeValuesFromReferences(
assignReferencesAttributeId, assignReferencesAttributeId,
data.attributes, data.attributes,
referencePages referencePages,
referenceProducts
)} )}
hasMore={fetchMoreReferencePages?.hasMore} hasMore={handlers.fetchMoreReferences?.hasMore}
open={canOpenAssignReferencesAttributeDialog} open={canOpenAssignReferencesAttributeDialog}
onFetch={fetchReferencePages} onFetch={handlers.fetchReferences}
onFetchMore={fetchMoreReferencePages?.onFetchMore} onFetchMore={handlers.fetchMoreReferences?.onFetchMore}
loading={fetchMoreReferencePages?.loading} loading={handlers.fetchMoreReferences?.loading}
onClose={onCloseDialog} onClose={onCloseDialog}
onSubmit={attributeValues => onSubmit={attributeValues =>
handleAssignReferenceAttribute(attributeValues, data, handlers) handleAssignReferenceAttribute(attributeValues, data, handlers)

View file

@ -5,7 +5,9 @@ import {
createAttributeFileChangeHandler, createAttributeFileChangeHandler,
createAttributeMultiChangeHandler, createAttributeMultiChangeHandler,
createAttributeReferenceChangeHandler, createAttributeReferenceChangeHandler,
createAttributeValueReorderHandler createAttributeValueReorderHandler,
createFetchMoreReferencesHandler,
createFetchReferencesHandler
} from "@saleor/attributes/utils/handlers"; } from "@saleor/attributes/utils/handlers";
import { AttributeInput } from "@saleor/components/Attributes"; import { AttributeInput } from "@saleor/components/Attributes";
import { MetadataFormData } from "@saleor/components/Metadata"; import { MetadataFormData } from "@saleor/components/Metadata";
@ -24,7 +26,8 @@ import {
import { getAttributeInputFromPage } from "@saleor/pages/utils/data"; import { getAttributeInputFromPage } from "@saleor/pages/utils/data";
import { createPageTypeSelectHandler } from "@saleor/pages/utils/handlers"; import { createPageTypeSelectHandler } from "@saleor/pages/utils/handlers";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { ReorderEvent } from "@saleor/types"; import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { FetchMoreProps, ReorderEvent } from "@saleor/types";
import getPublicationData from "@saleor/utils/data/getPublicationData"; import getPublicationData from "@saleor/utils/data/getPublicationData";
import handleFormSubmit from "@saleor/utils/handlers/handleFormSubmit"; import handleFormSubmit from "@saleor/utils/handlers/handleFormSubmit";
import { mapMetadataItemToInput } from "@saleor/utils/maps"; import { mapMetadataItemToInput } from "@saleor/utils/maps";
@ -62,6 +65,8 @@ export interface PageUpdateHandlers {
selectAttributeReference: FormsetChange<string[]>; selectAttributeReference: FormsetChange<string[]>;
selectAttributeFile: FormsetChange<File>; selectAttributeFile: FormsetChange<File>;
reorderAttributeValue: FormsetChange<ReorderEvent>; reorderAttributeValue: FormsetChange<ReorderEvent>;
fetchReferences: (value: string) => void;
fetchMoreReferences: FetchMoreProps;
} }
export interface UsePageUpdateFormResult { export interface UsePageUpdateFormResult {
change: FormChange; change: FormChange;
@ -72,19 +77,28 @@ export interface UsePageUpdateFormResult {
submit: () => void; submit: () => void;
} }
export interface PageFormProps { export interface UsePageFormOpts {
pageTypes?: PageDetails_page_pageType[];
referencePages: SearchPages_search_edges_node[];
referenceProducts: SearchProducts_search_edges_node[];
fetchReferencePages?: (data: string) => void;
fetchMoreReferencePages?: FetchMoreProps;
fetchReferenceProducts?: (data: string) => void;
fetchMoreReferenceProducts?: FetchMoreProps;
assignReferencesAttributeId?: string;
}
export interface PageFormProps extends UsePageFormOpts {
children: (props: UsePageUpdateFormResult) => React.ReactNode; children: (props: UsePageUpdateFormResult) => React.ReactNode;
page: PageDetails_page; page: PageDetails_page;
pageTypes?: PageDetails_page_pageType[]; pageTypes?: PageDetails_page_pageType[];
referencePages: SearchPages_search_edges_node[];
onSubmit: (data: PageData) => SubmitPromise; onSubmit: (data: PageData) => SubmitPromise;
} }
function usePageForm( function usePageForm(
page: PageDetails_page, page: PageDetails_page,
onSubmit: (data: PageData) => SubmitPromise, onSubmit: (data: PageData) => SubmitPromise,
referencePages: SearchPages_search_edges_node[], opts: UsePageFormOpts
pageTypes?: PageDetails_page_pageType[]
): UsePageUpdateFormResult { ): UsePageUpdateFormResult {
const [changed, setChanged] = React.useState(false); const [changed, setChanged] = React.useState(false);
const triggerChange = () => setChanged(true); const triggerChange = () => setChanged(true);
@ -131,7 +145,7 @@ function usePageForm(
handleChange, handleChange,
attributes.set, attributes.set,
setPageType, setPageType,
pageTypes opts.pageTypes
); );
const handleAttributeChange = createAttributeChangeHandler( const handleAttributeChange = createAttributeChangeHandler(
attributes.change, attributes.change,
@ -146,6 +160,18 @@ function usePageForm(
attributes.change, attributes.change,
triggerChange triggerChange
); );
const handleFetchReferences = createFetchReferencesHandler(
attributes.data,
opts.assignReferencesAttributeId,
opts.fetchReferencePages,
opts.fetchReferenceProducts
);
const handleFetchMoreReferences = createFetchMoreReferencesHandler(
attributes.data,
opts.assignReferencesAttributeId,
opts.fetchMoreReferencePages,
opts.fetchMoreReferenceProducts
);
const handleAttributeFileChange = createAttributeFileChangeHandler( const handleAttributeFileChange = createAttributeFileChangeHandler(
attributes.change, attributes.change,
attributesWithNewFileValue.data, attributesWithNewFileValue.data,
@ -165,7 +191,8 @@ function usePageForm(
attributes: getAttributesDisplayData( attributes: getAttributesDisplayData(
attributes.data, attributes.data,
attributesWithNewFileValue.data, attributesWithNewFileValue.data,
referencePages opts.referencePages,
opts.referenceProducts
), ),
content: content.current content: content.current
}); });
@ -198,6 +225,8 @@ function usePageForm(
handlers: { handlers: {
changeContent, changeContent,
changeMetadata, changeMetadata,
fetchMoreReferences: handleFetchMoreReferences,
fetchReferences: handleFetchReferences,
reorderAttributeValue: handleAttributeValueReorder, reorderAttributeValue: handleAttributeValueReorder,
selectAttribute: handleAttributeChange, selectAttribute: handleAttributeChange,
selectAttributeFile: handleAttributeFileChange, selectAttributeFile: handleAttributeFileChange,
@ -214,11 +243,10 @@ function usePageForm(
const PageForm: React.FC<PageFormProps> = ({ const PageForm: React.FC<PageFormProps> = ({
children, children,
page, page,
referencePages, onSubmit,
pageTypes, ...rest
onSubmit
}) => { }) => {
const props = usePageForm(page, onSubmit, referencePages, pageTypes); const props = usePageForm(page, onSubmit, rest);
return <form onSubmit={props.submit}>{children(props)}</form>; return <form onSubmit={props.submit}>{children(props)}</form>;
}; };

View file

@ -45,6 +45,7 @@ export const page: PageDetails_page = {
id: "QXR0cmlidXRlOjI3", id: "QXR0cmlidXRlOjI3",
slug: "author", slug: "author",
name: "Author", name: "Author",
entityType: null,
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false, valueRequired: false,
values: [ values: [
@ -92,6 +93,7 @@ export const page: PageDetails_page = {
id: "QXR0cmlidXRlOjI5", id: "QXR0cmlidXRlOjI5",
slug: "tag", slug: "tag",
name: "Tag", name: "Tag",
entityType: null,
inputType: AttributeInputTypeEnum.MULTISELECT, inputType: AttributeInputTypeEnum.MULTISELECT,
valueRequired: false, valueRequired: false,
values: [ values: [
@ -161,6 +163,7 @@ export const page: PageDetails_page = {
{ {
id: "QXR0cmlidXRlOjI3", id: "QXR0cmlidXRlOjI3",
name: "Author", name: "Author",
entityType: null,
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
valueRequired: false, valueRequired: false,
values: [ values: [
@ -194,6 +197,7 @@ export const page: PageDetails_page = {
{ {
id: "QXR0cmlidXRlOjI5", id: "QXR0cmlidXRlOjI5",
name: "Tag", name: "Tag",
entityType: null,
inputType: AttributeInputTypeEnum.MULTISELECT, inputType: AttributeInputTypeEnum.MULTISELECT,
valueRequired: false, valueRequired: false,
values: [ values: [

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { PageCreateInput, PageErrorCode, AttributeInputTypeEnum } from "./../../types/globalTypes"; import { PageCreateInput, PageErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: PageCreate // GraphQL mutation operation: PageCreate
@ -37,6 +37,7 @@ export interface PageCreate_pageCreate_page_attributes_attribute {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (PageCreate_pageCreate_page_attributes_attribute_values | null)[] | null; values: (PageCreate_pageCreate_page_attributes_attribute_values | null)[] | null;
} }
@ -82,6 +83,7 @@ export interface PageCreate_pageCreate_page_pageType_attributes {
id: string; id: string;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (PageCreate_pageCreate_page_pageType_attributes_values | null)[] | null; values: (PageCreate_pageCreate_page_pageType_attributes_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: PageDetails // GraphQL query operation: PageDetails
@ -29,6 +29,7 @@ export interface PageDetails_page_attributes_attribute {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (PageDetails_page_attributes_attribute_values | null)[] | null; values: (PageDetails_page_attributes_attribute_values | null)[] | null;
} }
@ -74,6 +75,7 @@ export interface PageDetails_page_pageType_attributes {
id: string; id: string;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (PageDetails_page_pageType_attributes_values | null)[] | null; values: (PageDetails_page_pageType_attributes_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { PageInput, PageErrorCode, AttributeInputTypeEnum } from "./../../types/globalTypes"; import { PageInput, PageErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: PageUpdate // GraphQL mutation operation: PageUpdate
@ -36,6 +36,7 @@ export interface PageUpdate_pageUpdate_page_attributes_attribute {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (PageUpdate_pageUpdate_page_attributes_attribute_values | null)[] | null; values: (PageUpdate_pageUpdate_page_attributes_attribute_values | null)[] | null;
} }
@ -81,6 +82,7 @@ export interface PageUpdate_pageUpdate_page_pageType_attributes {
id: string; id: string;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (PageUpdate_pageUpdate_page_pageType_attributes_values | null)[] | null; values: (PageUpdate_pageUpdate_page_pageType_attributes_values | null)[] | null;
} }

View file

@ -1,6 +1,5 @@
import { getSelectedAttributeValues } from "@saleor/attributes/utils/data"; import { getSelectedAttributeValues } from "@saleor/attributes/utils/data";
import { AttributeInput } from "@saleor/components/Attributes"; import { AttributeInput } from "@saleor/components/Attributes";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { import {
PageDetails_page, PageDetails_page,
@ -12,6 +11,7 @@ export function getAttributeInputFromPage(
): AttributeInput[] { ): AttributeInput[] {
return page?.attributes.map(attribute => ({ return page?.attributes.map(attribute => ({
data: { data: {
entityType: attribute.attribute.entityType,
inputType: attribute.attribute.inputType, inputType: attribute.attribute.inputType,
isRequired: attribute.attribute.valueRequired, isRequired: attribute.attribute.valueRequired,
selectedValues: attribute.values, selectedValues: attribute.values,
@ -28,6 +28,7 @@ export function getAttributeInputFromPageType(
): AttributeInput[] { ): AttributeInput[] {
return pageType?.attributes.map(attribute => ({ return pageType?.attributes.map(attribute => ({
data: { data: {
entityType: attribute.entityType,
inputType: attribute.inputType, inputType: attribute.inputType,
isRequired: attribute.valueRequired, isRequired: attribute.valueRequired,
values: attribute.values values: attribute.values
@ -37,18 +38,3 @@ export function getAttributeInputFromPageType(
value: [] value: []
})); }));
} }
export const getAttributeValuesFromReferences = (
attributeId: string,
attributes: AttributeInput[],
referencePages: SearchPages_search_edges_node[]
) => {
const attribute = attributes?.find(attribute => attribute.id === attributeId);
return (
referencePages?.filter(
value =>
!attribute?.value?.some(selectedValue => selectedValue === value.id)
) || []
);
};

View file

@ -11,6 +11,7 @@ import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier"; import useNotifier from "@saleor/hooks/useNotifier";
import usePageSearch from "@saleor/searches/usePageSearch"; import usePageSearch from "@saleor/searches/usePageSearch";
import usePageTypeSearch from "@saleor/searches/usePageTypeSearch"; import usePageTypeSearch from "@saleor/searches/usePageTypeSearch";
import useProductSearch from "@saleor/searches/useProductSearch";
import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler"; import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler";
import { import {
useMetadataUpdate, useMetadataUpdate,
@ -58,6 +59,14 @@ export const PageCreate: React.FC<PageCreateProps> = ({ params }) => {
variables: DEFAULT_INITIAL_SEARCH_DATA variables: DEFAULT_INITIAL_SEARCH_DATA
}); });
const {
loadMore: loadMoreProducts,
search: searchProducts,
result: searchProductsOpts
} = useProductSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const [uploadFile, uploadFileOpts] = useFileUploadMutation({}); const [uploadFile, uploadFileOpts] = useFileUploadMutation({});
const handlePageCreate = (data: PageCreateData) => { const handlePageCreate = (data: PageCreateData) => {
@ -81,17 +90,23 @@ export const PageCreate: React.FC<PageCreateProps> = ({ params }) => {
); );
const fetchMorePageTypes = { const fetchMorePageTypes = {
hasMore: searchPageTypesOpts.data?.search.pageInfo.hasNextPage, hasMore: searchPageTypesOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchPageTypesOpts.loading, loading: searchPageTypesOpts.loading,
onFetchMore: loadMorePageTypes onFetchMore: loadMorePageTypes
}; };
const fetchMoreReferencePages = { const fetchMoreReferencePages = {
hasMore: searchPagesOpts.data?.search.pageInfo.hasNextPage, hasMore: searchPagesOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchPagesOpts.loading, loading: searchPagesOpts.loading,
onFetchMore: loadMorePages onFetchMore: loadMorePages
}; };
const fetchMoreReferenceProducts = {
hasMore: searchProductsOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchProductsOpts.loading,
onFetchMore: loadMoreProducts
};
return ( return (
<TypedPageCreate onCompleted={handlePageCreate}> <TypedPageCreate onCompleted={handlePageCreate}>
{(pageCreate, pageCreateOpts) => { {(pageCreate, pageCreateOpts) => {
@ -163,8 +178,13 @@ export const PageCreate: React.FC<PageCreateProps> = ({ params }) => {
referencePages={searchPagesOpts.data?.search.edges.map( referencePages={searchPagesOpts.data?.search.edges.map(
edge => edge.node edge => edge.node
)} )}
referenceProducts={searchProductsOpts.data?.search.edges.map(
edge => edge.node
)}
fetchReferencePages={searchPages} fetchReferencePages={searchPages}
fetchMoreReferencePages={fetchMoreReferencePages} fetchMoreReferencePages={fetchMoreReferencePages}
fetchReferenceProducts={searchProducts}
fetchMoreReferenceProducts={fetchMoreReferenceProducts}
onCloseDialog={() => navigate(pageCreateUrl())} onCloseDialog={() => navigate(pageCreateUrl())}
/> />
</> </>

View file

@ -22,6 +22,7 @@ import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier"; import useNotifier from "@saleor/hooks/useNotifier";
import { commonMessages } from "@saleor/intl"; import { commonMessages } from "@saleor/intl";
import usePageSearch from "@saleor/searches/usePageSearch"; import usePageSearch from "@saleor/searches/usePageSearch";
import useProductSearch from "@saleor/searches/useProductSearch";
import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler"; import createMetadataUpdateHandler from "@saleor/utils/handlers/metadataUpdateHandler";
import { import {
useMetadataUpdate, useMetadataUpdate,
@ -158,12 +159,26 @@ export const PageDetails: React.FC<PageDetailsProps> = ({ id, params }) => {
variables: DEFAULT_INITIAL_SEARCH_DATA variables: DEFAULT_INITIAL_SEARCH_DATA
}); });
const {
loadMore: loadMoreProducts,
search: searchProducts,
result: searchProductsOpts
} = useProductSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const fetchMoreReferencePages = { const fetchMoreReferencePages = {
hasMore: searchPagesOpts.data?.search.pageInfo.hasNextPage, hasMore: searchPagesOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchPagesOpts.loading, loading: searchPagesOpts.loading,
onFetchMore: loadMorePages onFetchMore: loadMorePages
}; };
const fetchMoreReferenceProducts = {
hasMore: searchProductsOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchProductsOpts.loading,
onFetchMore: loadMoreProducts
};
return ( return (
<> <>
<WindowTitle title={maybe(() => pageDetails.data.page.title)} /> <WindowTitle title={maybe(() => pageDetails.data.page.title)} />
@ -193,8 +208,13 @@ export const PageDetails: React.FC<PageDetailsProps> = ({ id, params }) => {
referencePages={searchPagesOpts.data?.search.edges.map( referencePages={searchPagesOpts.data?.search.edges.map(
edge => edge.node edge => edge.node
)} )}
referenceProducts={searchProductsOpts.data?.search.edges.map(
edge => edge.node
)}
fetchReferencePages={searchPages} fetchReferencePages={searchPages}
fetchMoreReferencePages={fetchMoreReferencePages} fetchMoreReferencePages={fetchMoreReferencePages}
fetchReferenceProducts={searchProducts}
fetchMoreReferenceProducts={fetchMoreReferenceProducts}
onCloseDialog={() => navigate(pageUrl(id))} onCloseDialog={() => navigate(pageUrl(id))}
/> />
<ActionDialog <ActionDialog

View file

@ -15,6 +15,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZTo5", id: "UHJvZHVjdEF0dHJpYnV0ZTo5",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Author", name: "Author",
@ -49,6 +50,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZTo2", id: "UHJvZHVjdEF0dHJpYnV0ZTo2",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Box Size", name: "Box Size",
@ -105,6 +107,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZToz", id: "UHJvZHVjdEF0dHJpYnV0ZToz",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Brand", name: "Brand",
@ -128,6 +131,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZTo4", id: "UHJvZHVjdEF0dHJpYnV0ZTo4",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Candy Box Size", name: "Candy Box Size",
@ -173,6 +177,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZTo1", id: "UHJvZHVjdEF0dHJpYnV0ZTo1",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Coffee Genre", name: "Coffee Genre",
@ -207,6 +212,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZToy", id: "UHJvZHVjdEF0dHJpYnV0ZToy",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Collar", name: "Collar",
@ -252,6 +258,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZTox", id: "UHJvZHVjdEF0dHJpYnV0ZTox",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Color", name: "Color",
@ -286,6 +293,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZToxMg==", id: "UHJvZHVjdEF0dHJpYnV0ZToxMg==",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Cover", name: "Cover",
@ -364,6 +372,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZTo3", id: "UHJvZHVjdEF0dHJpYnV0ZTo3",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Flavor", name: "Flavor",
@ -398,6 +407,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZToxMQ==", id: "UHJvZHVjdEF0dHJpYnV0ZToxMQ==",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Language", name: "Language",
@ -432,6 +442,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZToxMA==", id: "UHJvZHVjdEF0dHJpYnV0ZToxMA==",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Publisher", name: "Publisher",
@ -466,6 +477,7 @@ export const attributes: SearchProductTypes_search_edges_node_productAttributes[
{ {
node: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "UHJvZHVjdEF0dHJpYnV0ZTo0", id: "UHJvZHVjdEF0dHJpYnV0ZTo0",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Size", name: "Size",

View file

@ -1,4 +1,7 @@
import { mergeAttributeValues } from "@saleor/attributes/utils/data"; import {
getAttributeValuesFromReferences,
mergeAttributeValues
} from "@saleor/attributes/utils/data";
import { ChannelData } from "@saleor/channels/utils"; import { ChannelData } from "@saleor/channels/utils";
import AppHeader from "@saleor/components/AppHeader"; import AppHeader from "@saleor/components/AppHeader";
import AssignAttributeValueDialog from "@saleor/components/AssignAttributeValueDialog"; import AssignAttributeValueDialog from "@saleor/components/AssignAttributeValueDialog";
@ -18,12 +21,12 @@ import { ProductErrorWithAttributesFragment } from "@saleor/fragments/types/Prod
import { TaxTypeFragment } from "@saleor/fragments/types/TaxTypeFragment"; import { TaxTypeFragment } from "@saleor/fragments/types/TaxTypeFragment";
import useStateFromProps from "@saleor/hooks/useStateFromProps"; import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { getAttributeValuesFromReferences } from "@saleor/pages/utils/data";
import ProductVariantPrice from "@saleor/products/components/ProductVariantPrice"; import ProductVariantPrice from "@saleor/products/components/ProductVariantPrice";
import { getChoices } from "@saleor/products/utils/data"; import { getChoices } from "@saleor/products/utils/data";
import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories"; import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories";
import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections"; import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { SearchProductTypes_search_edges_node } from "@saleor/searches/types/SearchProductTypes"; import { SearchProductTypes_search_edges_node } from "@saleor/searches/types/SearchProductTypes";
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses"; import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
import React from "react"; import React from "react";
@ -54,7 +57,8 @@ interface ProductCreatePageProps {
fetchMoreProductTypes: FetchMoreProps; fetchMoreProductTypes: FetchMoreProps;
initial?: Partial<ProductCreateFormData>; initial?: Partial<ProductCreateFormData>;
productTypes?: SearchProductTypes_search_edges_node[]; productTypes?: SearchProductTypes_search_edges_node[];
referencePages: SearchPages_search_edges_node[]; referencePages?: SearchPages_search_edges_node[];
referenceProducts?: SearchProducts_search_edges_node[];
header: string; header: string;
saveButtonBarState: ConfirmButtonTransitionState; saveButtonBarState: ConfirmButtonTransitionState;
weightUnit: string; weightUnit: string;
@ -69,7 +73,9 @@ interface ProductCreatePageProps {
assignReferencesAttributeId?: string; assignReferencesAttributeId?: string;
onAssignReferencesClick: (attribute: AttributeInput) => void; onAssignReferencesClick: (attribute: AttributeInput) => void;
fetchReferencePages?: (data: string) => void; fetchReferencePages?: (data: string) => void;
fetchReferenceProducts?: (data: string) => void;
fetchMoreReferencePages?: FetchMoreProps; fetchMoreReferencePages?: FetchMoreProps;
fetchMoreReferenceProducts?: FetchMoreProps;
onCloseDialog: () => void; onCloseDialog: () => void;
onBack?(); onBack?();
onSubmit?(data: ProductCreateData); onSubmit?(data: ProductCreateData);
@ -91,7 +97,8 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
header, header,
initial, initial,
productTypes: productTypeChoiceList, productTypes: productTypeChoiceList,
referencePages, referencePages = [],
referenceProducts = [],
saveButtonBarState, saveButtonBarState,
warehouses, warehouses,
taxTypes, taxTypes,
@ -106,6 +113,8 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
onAssignReferencesClick, onAssignReferencesClick,
fetchReferencePages, fetchReferencePages,
fetchMoreReferencePages, fetchMoreReferencePages,
fetchReferenceProducts,
fetchMoreReferenceProducts,
onCloseDialog onCloseDialog
}: ProductCreatePageProps) => { }: ProductCreatePageProps) => {
const intl = useIntl(); const intl = useIntl();
@ -158,6 +167,7 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
collections={collections} collections={collections}
productTypes={productTypeChoiceList} productTypes={productTypeChoiceList}
referencePages={referencePages} referencePages={referencePages}
referenceProducts={referenceProducts}
selectedCollections={selectedCollections} selectedCollections={selectedCollections}
setSelectedCategory={setSelectedCategory} setSelectedCategory={setSelectedCategory}
setSelectedCollections={setSelectedCollections} setSelectedCollections={setSelectedCollections}
@ -167,6 +177,11 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
warehouses={warehouses} warehouses={warehouses}
currentChannels={currentChannels} currentChannels={currentChannels}
productTypeChoiceList={productTypeChoiceList} productTypeChoiceList={productTypeChoiceList}
fetchReferencePages={fetchReferencePages}
fetchMoreReferencePages={fetchMoreReferencePages}
fetchReferenceProducts={fetchReferenceProducts}
fetchMoreReferenceProducts={fetchMoreReferenceProducts}
assignReferencesAttributeId={assignReferencesAttributeId}
> >
{({ {({
change, change,
@ -327,13 +342,14 @@ export const ProductCreatePage: React.FC<ProductCreatePageProps> = ({
attributeValues={getAttributeValuesFromReferences( attributeValues={getAttributeValuesFromReferences(
assignReferencesAttributeId, assignReferencesAttributeId,
data.attributes, data.attributes,
referencePages referencePages,
referenceProducts
)} )}
hasMore={fetchMoreReferencePages?.hasMore} hasMore={handlers.fetchMoreReferences?.hasMore}
open={canOpenAssignReferencesAttributeDialog} open={canOpenAssignReferencesAttributeDialog}
onFetch={fetchReferencePages} onFetch={handlers.fetchReferences}
onFetchMore={fetchMoreReferencePages?.onFetchMore} onFetchMore={handlers.fetchMoreReferences?.onFetchMore}
loading={fetchMoreReferencePages?.loading} loading={handlers.fetchMoreReferences?.loading}
onClose={onCloseDialog} onClose={onCloseDialog}
onSubmit={attributeValues => onSubmit={attributeValues =>
handleAssignReferenceAttribute( handleAssignReferenceAttribute(

View file

@ -5,7 +5,9 @@ import {
createAttributeFileChangeHandler, createAttributeFileChangeHandler,
createAttributeMultiChangeHandler, createAttributeMultiChangeHandler,
createAttributeReferenceChangeHandler, createAttributeReferenceChangeHandler,
createAttributeValueReorderHandler createAttributeValueReorderHandler,
createFetchMoreReferencesHandler,
createFetchReferencesHandler
} from "@saleor/attributes/utils/handlers"; } from "@saleor/attributes/utils/handlers";
import { ChannelData, ChannelPriceArgs } from "@saleor/channels/utils"; import { ChannelData, ChannelPriceArgs } from "@saleor/channels/utils";
import { import {
@ -36,9 +38,10 @@ import {
validatePrice validatePrice
} from "@saleor/products/utils/validation"; } from "@saleor/products/utils/validation";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { SearchProductTypes_search_edges_node } from "@saleor/searches/types/SearchProductTypes"; import { SearchProductTypes_search_edges_node } from "@saleor/searches/types/SearchProductTypes";
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses"; import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
import { ReorderEvent } from "@saleor/types"; import { FetchMoreProps, ReorderEvent } from "@saleor/types";
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
@ -99,6 +102,8 @@ export interface ProductCreateHandlers
Record<"reorderAttributeValue", FormsetChange<ReorderEvent>>, Record<"reorderAttributeValue", FormsetChange<ReorderEvent>>,
Record<"addStock" | "deleteStock", (id: string) => void> { Record<"addStock" | "deleteStock", (id: string) => void> {
changeDescription: RichTextEditorChange; changeDescription: RichTextEditorChange;
fetchReferences: (value: string) => void;
fetchMoreReferences: FetchMoreProps;
} }
export interface UseProductCreateFormResult { export interface UseProductCreateFormResult {
change: FormChange; change: FormChange;
@ -126,6 +131,12 @@ export interface UseProductCreateFormOpts
currentChannels: ChannelData[]; currentChannels: ChannelData[];
productTypeChoiceList: SearchProductTypes_search_edges_node[]; productTypeChoiceList: SearchProductTypes_search_edges_node[];
referencePages: SearchPages_search_edges_node[]; referencePages: SearchPages_search_edges_node[];
referenceProducts: SearchProducts_search_edges_node[];
fetchReferencePages?: (data: string) => void;
fetchMoreReferencePages?: FetchMoreProps;
fetchReferenceProducts?: (data: string) => void;
fetchMoreReferenceProducts?: FetchMoreProps;
assignReferencesAttributeId?: string;
} }
export interface ProductCreateFormProps extends UseProductCreateFormOpts { export interface ProductCreateFormProps extends UseProductCreateFormOpts {
@ -222,6 +233,18 @@ function useProductCreateForm(
attributes.change, attributes.change,
triggerChange triggerChange
); );
const handleFetchReferences = createFetchReferencesHandler(
attributes.data,
opts.assignReferencesAttributeId,
opts.fetchReferencePages,
opts.fetchReferenceProducts
);
const handleFetchMoreReferences = createFetchMoreReferencesHandler(
attributes.data,
opts.assignReferencesAttributeId,
opts.fetchMoreReferencePages,
opts.fetchMoreReferenceProducts
);
const handleAttributeFileChange = createAttributeFileChangeHandler( const handleAttributeFileChange = createAttributeFileChangeHandler(
attributes.change, attributes.change,
attributesWithNewFileValue.data, attributesWithNewFileValue.data,
@ -281,7 +304,8 @@ function useProductCreateForm(
attributes: getAttributesDisplayData( attributes: getAttributesDisplayData(
attributes.data, attributes.data,
attributesWithNewFileValue.data, attributesWithNewFileValue.data,
opts.referencePages opts.referencePages,
opts.referenceProducts
), ),
attributesWithNewFileValue: attributesWithNewFileValue.data, attributesWithNewFileValue: attributesWithNewFileValue.data,
description: description.current, description: description.current,
@ -315,6 +339,8 @@ function useProductCreateForm(
changeMetadata, changeMetadata,
changeStock: handleStockChange, changeStock: handleStockChange,
deleteStock: handleStockDelete, deleteStock: handleStockDelete,
fetchMoreReferences: handleFetchMoreReferences,
fetchReferences: handleFetchReferences,
reorderAttributeValue: handleAttributeValueReorder, reorderAttributeValue: handleAttributeValueReorder,
selectAttribute: handleAttributeChange, selectAttribute: handleAttributeChange,
selectAttributeFile: handleAttributeFileChange, selectAttributeFile: handleAttributeFileChange,

View file

@ -60,6 +60,7 @@ const props: ProductUpdatePageProps = {
placeholderImage, placeholderImage,
product, product,
referencePages: [], referencePages: [],
referenceProducts: [],
saveButtonBarState: "default", saveButtonBarState: "default",
selectedChannelId: "123", selectedChannelId: "123",
taxTypes, taxTypes,

View file

@ -1,5 +1,8 @@
import { OutputData } from "@editorjs/editorjs"; import { OutputData } from "@editorjs/editorjs";
import { mergeAttributeValues } from "@saleor/attributes/utils/data"; import {
getAttributeValuesFromReferences,
mergeAttributeValues
} from "@saleor/attributes/utils/data";
import { ChannelData } from "@saleor/channels/utils"; import { ChannelData } from "@saleor/channels/utils";
import AppHeader from "@saleor/components/AppHeader"; import AppHeader from "@saleor/components/AppHeader";
import AssignAttributeValueDialog from "@saleor/components/AssignAttributeValueDialog"; import AssignAttributeValueDialog from "@saleor/components/AssignAttributeValueDialog";
@ -23,11 +26,11 @@ import { FormsetData } from "@saleor/hooks/useFormset";
import useStateFromProps from "@saleor/hooks/useStateFromProps"; import useStateFromProps from "@saleor/hooks/useStateFromProps";
import { sectionNames } from "@saleor/intl"; import { sectionNames } from "@saleor/intl";
import { maybe } from "@saleor/misc"; import { maybe } from "@saleor/misc";
import { getAttributeValuesFromReferences } from "@saleor/pages/utils/data";
import ProductVariantPrice from "@saleor/products/components/ProductVariantPrice"; import ProductVariantPrice from "@saleor/products/components/ProductVariantPrice";
import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories"; import { SearchCategories_search_edges_node } from "@saleor/searches/types/SearchCategories";
import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections"; import { SearchCollections_search_edges_node } from "@saleor/searches/types/SearchCollections";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { import {
ChannelProps, ChannelProps,
FetchMoreProps, FetchMoreProps,
@ -76,12 +79,15 @@ export interface ProductUpdatePageProps extends ListActions, ChannelProps {
saveButtonBarState: ConfirmButtonTransitionState; saveButtonBarState: ConfirmButtonTransitionState;
warehouses: WarehouseFragment[]; warehouses: WarehouseFragment[];
taxTypes: TaxTypeFragment[]; taxTypes: TaxTypeFragment[];
referencePages: SearchPages_search_edges_node[]; referencePages?: SearchPages_search_edges_node[];
referenceProducts?: SearchProducts_search_edges_node[];
assignReferencesAttributeId?: string; assignReferencesAttributeId?: string;
fetchMoreReferencePages?: FetchMoreProps; fetchMoreReferencePages?: FetchMoreProps;
fetchMoreReferenceProducts?: FetchMoreProps;
fetchCategories: (query: string) => void; fetchCategories: (query: string) => void;
fetchCollections: (query: string) => void; fetchCollections: (query: string) => void;
fetchReferencePages?: (data: string) => void; fetchReferencePages?: (data: string) => void;
fetchReferenceProducts?: (data: string) => void;
onAssignReferencesClick: (attribute: AttributeInput) => void; onAssignReferencesClick: (attribute: AttributeInput) => void;
onCloseDialog: () => void; onCloseDialog: () => void;
onVariantsAdd: () => void; onVariantsAdd: () => void;
@ -136,7 +142,8 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
variants, variants,
warehouses, warehouses,
taxTypes, taxTypes,
referencePages, referencePages = [],
referenceProducts = [],
onBack, onBack,
onDelete, onDelete,
onImageDelete, onImageDelete,
@ -163,6 +170,8 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
onAssignReferencesClick, onAssignReferencesClick,
fetchReferencePages, fetchReferencePages,
fetchMoreReferencePages, fetchMoreReferencePages,
fetchReferenceProducts,
fetchMoreReferenceProducts,
onCloseDialog onCloseDialog
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
@ -222,6 +231,12 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
currentChannels={currentChannels} currentChannels={currentChannels}
hasVariants={hasVariants} hasVariants={hasVariants}
referencePages={referencePages} referencePages={referencePages}
referenceProducts={referenceProducts}
fetchReferencePages={fetchReferencePages}
fetchMoreReferencePages={fetchMoreReferencePages}
fetchReferenceProducts={fetchReferenceProducts}
fetchMoreReferenceProducts={fetchMoreReferenceProducts}
assignReferencesAttributeId={assignReferencesAttributeId}
> >
{({ {({
change, change,
@ -408,13 +423,14 @@ export const ProductUpdatePage: React.FC<ProductUpdatePageProps> = ({
attributeValues={getAttributeValuesFromReferences( attributeValues={getAttributeValuesFromReferences(
assignReferencesAttributeId, assignReferencesAttributeId,
data.attributes, data.attributes,
referencePages referencePages,
referenceProducts
)} )}
hasMore={fetchMoreReferencePages?.hasMore} hasMore={handlers.fetchMoreReferences?.hasMore}
open={canOpenAssignReferencesAttributeDialog} open={canOpenAssignReferencesAttributeDialog}
onFetch={fetchReferencePages} onFetch={handlers.fetchReferences}
onFetchMore={fetchMoreReferencePages?.onFetchMore} onFetchMore={handlers.fetchMoreReferences?.onFetchMore}
loading={fetchMoreReferencePages?.loading} loading={handlers.fetchMoreReferences?.loading}
onClose={onCloseDialog} onClose={onCloseDialog}
onSubmit={attributeValues => onSubmit={attributeValues =>
handleAssignReferenceAttribute( handleAssignReferenceAttribute(

View file

@ -5,7 +5,9 @@ import {
createAttributeFileChangeHandler, createAttributeFileChangeHandler,
createAttributeMultiChangeHandler, createAttributeMultiChangeHandler,
createAttributeReferenceChangeHandler, createAttributeReferenceChangeHandler,
createAttributeValueReorderHandler createAttributeValueReorderHandler,
createFetchMoreReferencesHandler,
createFetchReferencesHandler
} from "@saleor/attributes/utils/handlers"; } from "@saleor/attributes/utils/handlers";
import { ChannelData, ChannelPriceArgs } from "@saleor/channels/utils"; import { ChannelData, ChannelPriceArgs } from "@saleor/channels/utils";
import { AttributeInput } from "@saleor/components/Attributes"; import { AttributeInput } from "@saleor/components/Attributes";
@ -34,8 +36,9 @@ import {
validatePrice validatePrice
} from "@saleor/products/utils/validation"; } from "@saleor/products/utils/validation";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses"; import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
import { ReorderEvent } from "@saleor/types"; import { FetchMoreProps, ReorderEvent } from "@saleor/types";
import handleFormSubmit from "@saleor/utils/handlers/handleFormSubmit"; import handleFormSubmit from "@saleor/utils/handlers/handleFormSubmit";
import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler";
import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler";
@ -116,6 +119,8 @@ export interface ProductUpdateHandlers
Record<"reorderAttributeValue", FormsetChange<ReorderEvent>>, Record<"reorderAttributeValue", FormsetChange<ReorderEvent>>,
Record<"addStock" | "deleteStock", (id: string) => void> { Record<"addStock" | "deleteStock", (id: string) => void> {
changeDescription: RichTextEditorChange; changeDescription: RichTextEditorChange;
fetchReferences: (value: string) => void;
fetchMoreReferences: FetchMoreProps;
} }
export interface UseProductUpdateFormResult { export interface UseProductUpdateFormResult {
change: FormChange; change: FormChange;
@ -143,6 +148,12 @@ export interface UseProductUpdateFormOpts
currentChannels: ChannelData[]; currentChannels: ChannelData[];
hasVariants: boolean; hasVariants: boolean;
referencePages: SearchPages_search_edges_node[]; referencePages: SearchPages_search_edges_node[];
referenceProducts: SearchProducts_search_edges_node[];
fetchReferencePages?: (data: string) => void;
fetchMoreReferencePages?: FetchMoreProps;
fetchReferenceProducts?: (data: string) => void;
fetchMoreReferenceProducts?: FetchMoreProps;
assignReferencesAttributeId?: string;
} }
export interface ProductUpdateFormProps extends UseProductUpdateFormOpts { export interface ProductUpdateFormProps extends UseProductUpdateFormOpts {
@ -232,6 +243,18 @@ function useProductUpdateForm(
attributes.change, attributes.change,
triggerChange triggerChange
); );
const handleFetchReferences = createFetchReferencesHandler(
attributes.data,
opts.assignReferencesAttributeId,
opts.fetchReferencePages,
opts.fetchReferenceProducts
);
const handleFetchMoreReferences = createFetchMoreReferencesHandler(
attributes.data,
opts.assignReferencesAttributeId,
opts.fetchMoreReferencePages,
opts.fetchMoreReferenceProducts
);
const handleAttributeFileChange = createAttributeFileChangeHandler( const handleAttributeFileChange = createAttributeFileChangeHandler(
attributes.change, attributes.change,
attributesWithNewFileValue.data, attributesWithNewFileValue.data,
@ -283,7 +306,8 @@ function useProductUpdateForm(
attributes: getAttributesDisplayData( attributes: getAttributesDisplayData(
attributes.data, attributes.data,
attributesWithNewFileValue.data, attributesWithNewFileValue.data,
opts.referencePages opts.referencePages,
opts.referenceProducts
), ),
description: description.current, description: description.current,
stocks: stocks.data stocks: stocks.data
@ -332,6 +356,8 @@ function useProductUpdateForm(
changeMetadata, changeMetadata,
changeStock: handleStockChange, changeStock: handleStockChange,
deleteStock: handleStockDelete, deleteStock: handleStockDelete,
fetchMoreReferences: handleFetchMoreReferences,
fetchReferences: handleFetchReferences,
reorderAttributeValue: handleAttributeValueReorder, reorderAttributeValue: handleAttributeValueReorder,
selectAttribute: handleAttributeChange, selectAttribute: handleAttributeChange,
selectAttributeFile: handleAttributeFileChange, selectAttributeFile: handleAttributeFileChange,

View file

@ -1,4 +1,7 @@
import { mergeAttributeValues } from "@saleor/attributes/utils/data"; import {
getAttributeValuesFromReferences,
mergeAttributeValues
} from "@saleor/attributes/utils/data";
import { ChannelPriceData } from "@saleor/channels/utils"; import { ChannelPriceData } from "@saleor/channels/utils";
import AppHeader from "@saleor/components/AppHeader"; import AppHeader from "@saleor/components/AppHeader";
import AssignAttributeValueDialog from "@saleor/components/AssignAttributeValueDialog"; import AssignAttributeValueDialog from "@saleor/components/AssignAttributeValueDialog";
@ -15,8 +18,8 @@ import PageHeader from "@saleor/components/PageHeader";
import SaveButtonBar from "@saleor/components/SaveButtonBar"; import SaveButtonBar from "@saleor/components/SaveButtonBar";
import { ProductChannelListingErrorFragment } from "@saleor/fragments/types/ProductChannelListingErrorFragment"; import { ProductChannelListingErrorFragment } from "@saleor/fragments/types/ProductChannelListingErrorFragment";
import { ProductErrorWithAttributesFragment } from "@saleor/fragments/types/ProductErrorWithAttributesFragment"; import { ProductErrorWithAttributesFragment } from "@saleor/fragments/types/ProductErrorWithAttributesFragment";
import { getAttributeValuesFromReferences } from "@saleor/pages/utils/data";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses"; import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
import { FetchMoreProps, ReorderAction } from "@saleor/types"; import { FetchMoreProps, ReorderAction } from "@saleor/types";
import React from "react"; import React from "react";
@ -61,7 +64,8 @@ interface ProductVariantCreatePageProps {
saveButtonBarState: ConfirmButtonTransitionState; saveButtonBarState: ConfirmButtonTransitionState;
warehouses: SearchWarehouses_search_edges_node[]; warehouses: SearchWarehouses_search_edges_node[];
weightUnit: string; weightUnit: string;
referencePages: SearchPages_search_edges_node[]; referencePages?: SearchPages_search_edges_node[];
referenceProducts?: SearchProducts_search_edges_node[];
onBack: () => void; onBack: () => void;
onSubmit: (data: ProductVariantCreateData) => void; onSubmit: (data: ProductVariantCreateData) => void;
onVariantClick: (variantId: string) => void; onVariantClick: (variantId: string) => void;
@ -70,7 +74,9 @@ interface ProductVariantCreatePageProps {
assignReferencesAttributeId?: string; assignReferencesAttributeId?: string;
onAssignReferencesClick: (attribute: AttributeInput) => void; onAssignReferencesClick: (attribute: AttributeInput) => void;
fetchReferencePages?: (data: string) => void; fetchReferencePages?: (data: string) => void;
fetchReferenceProducts?: (data: string) => void;
fetchMoreReferencePages?: FetchMoreProps; fetchMoreReferencePages?: FetchMoreProps;
fetchMoreReferenceProducts?: FetchMoreProps;
onCloseDialog: () => void; onCloseDialog: () => void;
} }
@ -84,7 +90,8 @@ const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
saveButtonBarState, saveButtonBarState,
warehouses, warehouses,
weightUnit, weightUnit,
referencePages, referencePages = [],
referenceProducts = [],
onBack, onBack,
onSubmit, onSubmit,
onVariantClick, onVariantClick,
@ -93,7 +100,9 @@ const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
assignReferencesAttributeId, assignReferencesAttributeId,
onAssignReferencesClick, onAssignReferencesClick,
fetchReferencePages, fetchReferencePages,
fetchReferenceProducts,
fetchMoreReferencePages, fetchMoreReferencePages,
fetchMoreReferenceProducts,
onCloseDialog onCloseDialog
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
@ -123,6 +132,12 @@ const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
warehouses={warehouses} warehouses={warehouses}
currentChannels={channels} currentChannels={channels}
referencePages={referencePages} referencePages={referencePages}
referenceProducts={referenceProducts}
fetchReferencePages={fetchReferencePages}
fetchMoreReferencePages={fetchMoreReferencePages}
fetchReferenceProducts={fetchReferenceProducts}
fetchMoreReferenceProducts={fetchMoreReferenceProducts}
assignReferencesAttributeId={assignReferencesAttributeId}
> >
{({ {({
change, change,
@ -237,13 +252,14 @@ const ProductVariantCreatePage: React.FC<ProductVariantCreatePageProps> = ({
attributeValues={getAttributeValuesFromReferences( attributeValues={getAttributeValuesFromReferences(
assignReferencesAttributeId, assignReferencesAttributeId,
data.attributes, data.attributes,
referencePages referencePages,
referenceProducts
)} )}
hasMore={fetchMoreReferencePages?.hasMore} hasMore={handlers.fetchMoreReferences?.hasMore}
open={canOpenAssignReferencesAttributeDialog} open={canOpenAssignReferencesAttributeDialog}
onFetch={fetchReferencePages} onFetch={handlers.fetchReferences}
onFetchMore={fetchMoreReferencePages?.onFetchMore} onFetchMore={handlers.fetchMoreReferences?.onFetchMore}
loading={fetchMoreReferencePages?.loading} loading={handlers.fetchMoreReferences?.loading}
onClose={onCloseDialog} onClose={onCloseDialog}
onSubmit={attributeValues => onSubmit={attributeValues =>
handleAssignReferenceAttribute(attributeValues, data, handlers) handleAssignReferenceAttribute(attributeValues, data, handlers)

View file

@ -4,7 +4,9 @@ import {
createAttributeFileChangeHandler, createAttributeFileChangeHandler,
createAttributeMultiChangeHandler, createAttributeMultiChangeHandler,
createAttributeReferenceChangeHandler, createAttributeReferenceChangeHandler,
createAttributeValueReorderHandler createAttributeValueReorderHandler,
createFetchMoreReferencesHandler,
createFetchReferencesHandler
} from "@saleor/attributes/utils/handlers"; } from "@saleor/attributes/utils/handlers";
import { ChannelPriceData, IChannelPriceArgs } from "@saleor/channels/utils"; import { ChannelPriceData, IChannelPriceArgs } from "@saleor/channels/utils";
import { AttributeInput } from "@saleor/components/Attributes"; import { AttributeInput } from "@saleor/components/Attributes";
@ -22,8 +24,9 @@ import {
validatePrice validatePrice
} from "@saleor/products/utils/validation"; } from "@saleor/products/utils/validation";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses"; import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
import { ReorderEvent } from "@saleor/types"; import { FetchMoreProps, ReorderEvent } from "@saleor/types";
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
import React from "react"; import React from "react";
@ -45,6 +48,12 @@ export interface UseProductVariantCreateFormOpts {
warehouses: SearchWarehouses_search_edges_node[]; warehouses: SearchWarehouses_search_edges_node[];
currentChannels: ChannelPriceData[]; currentChannels: ChannelPriceData[];
referencePages: SearchPages_search_edges_node[]; referencePages: SearchPages_search_edges_node[];
referenceProducts: SearchProducts_search_edges_node[];
fetchReferencePages?: (data: string) => void;
fetchMoreReferencePages?: FetchMoreProps;
fetchReferenceProducts?: (data: string) => void;
fetchMoreReferenceProducts?: FetchMoreProps;
assignReferencesAttributeId?: string;
} }
export interface ProductVariantCreateHandlers export interface ProductVariantCreateHandlers
@ -60,6 +69,8 @@ export interface ProductVariantCreateHandlers
Record<"reorderAttributeValue", FormsetChange<ReorderEvent>>, Record<"reorderAttributeValue", FormsetChange<ReorderEvent>>,
Record<"addStock" | "deleteStock", (id: string) => void> { Record<"addStock" | "deleteStock", (id: string) => void> {
changeMetadata: FormChange; changeMetadata: FormChange;
fetchReferences: (value: string) => void;
fetchMoreReferences: FetchMoreProps;
} }
export interface UseProductVariantCreateFormResult { export interface UseProductVariantCreateFormResult {
@ -125,6 +136,18 @@ function useProductVariantCreateForm(
attributes.change, attributes.change,
triggerChange triggerChange
); );
const handleFetchReferences = createFetchReferencesHandler(
attributes.data,
opts.assignReferencesAttributeId,
opts.fetchReferencePages,
opts.fetchReferenceProducts
);
const handleFetchMoreReferences = createFetchMoreReferencesHandler(
attributes.data,
opts.assignReferencesAttributeId,
opts.fetchMoreReferencePages,
opts.fetchMoreReferenceProducts
);
const handleAttributeFileChange = createAttributeFileChangeHandler( const handleAttributeFileChange = createAttributeFileChangeHandler(
attributes.change, attributes.change,
attributesWithNewFileValue.data, attributesWithNewFileValue.data,
@ -170,7 +193,8 @@ function useProductVariantCreateForm(
attributes: getAttributesDisplayData( attributes: getAttributesDisplayData(
attributes.data, attributes.data,
attributesWithNewFileValue.data, attributesWithNewFileValue.data,
opts.referencePages opts.referencePages,
opts.referenceProducts
), ),
attributesWithNewFileValue: attributesWithNewFileValue.data, attributesWithNewFileValue: attributesWithNewFileValue.data,
channelListings: channels.data, channelListings: channels.data,
@ -189,6 +213,8 @@ function useProductVariantCreateForm(
changeMetadata, changeMetadata,
changeStock: handleStockChange, changeStock: handleStockChange,
deleteStock: handleStockDelete, deleteStock: handleStockDelete,
fetchMoreReferences: handleFetchMoreReferences,
fetchReferences: handleFetchReferences,
reorderAttributeValue: handleAttributeValueReorder, reorderAttributeValue: handleAttributeValueReorder,
selectAttribute: handleAttributeChange, selectAttribute: handleAttributeChange,
selectAttributeFile: handleAttributeFileChange, selectAttributeFile: handleAttributeFileChange,

View file

@ -1,4 +1,7 @@
import { mergeAttributeValues } from "@saleor/attributes/utils/data"; import {
getAttributeValuesFromReferences,
mergeAttributeValues
} from "@saleor/attributes/utils/data";
import { ChannelPriceData } from "@saleor/channels/utils"; import { ChannelPriceData } from "@saleor/channels/utils";
import AppHeader from "@saleor/components/AppHeader"; import AppHeader from "@saleor/components/AppHeader";
import AssignAttributeValueDialog from "@saleor/components/AssignAttributeValueDialog"; import AssignAttributeValueDialog from "@saleor/components/AssignAttributeValueDialog";
@ -18,9 +21,9 @@ import { ProductChannelListingErrorFragment } from "@saleor/fragments/types/Prod
import { ProductErrorWithAttributesFragment } from "@saleor/fragments/types/ProductErrorWithAttributesFragment"; import { ProductErrorWithAttributesFragment } from "@saleor/fragments/types/ProductErrorWithAttributesFragment";
import { ProductVariant } from "@saleor/fragments/types/ProductVariant"; import { ProductVariant } from "@saleor/fragments/types/ProductVariant";
import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment"; import { WarehouseFragment } from "@saleor/fragments/types/WarehouseFragment";
import { getAttributeValuesFromReferences } from "@saleor/pages/utils/data";
import { VariantUpdate_productVariantUpdate_errors } from "@saleor/products/types/VariantUpdate"; import { VariantUpdate_productVariantUpdate_errors } from "@saleor/products/types/VariantUpdate";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { FetchMoreProps, ReorderAction } from "@saleor/types"; import { FetchMoreProps, ReorderAction } from "@saleor/types";
import React from "react"; import React from "react";
import { defineMessages, useIntl } from "react-intl"; import { defineMessages, useIntl } from "react-intl";
@ -81,9 +84,12 @@ interface ProductVariantPageProps {
saveButtonBarState: ConfirmButtonTransitionState; saveButtonBarState: ConfirmButtonTransitionState;
variant?: ProductVariant; variant?: ProductVariant;
warehouses: WarehouseFragment[]; warehouses: WarehouseFragment[];
referencePages: SearchPages_search_edges_node[]; referencePages?: SearchPages_search_edges_node[];
referenceProducts?: SearchProducts_search_edges_node[];
fetchMoreReferencePages?: FetchMoreProps; fetchMoreReferencePages?: FetchMoreProps;
fetchMoreReferenceProducts?: FetchMoreProps;
fetchReferencePages?: (data: string) => void; fetchReferencePages?: (data: string) => void;
fetchReferenceProducts?: (data: string) => void;
onAssignReferencesClick: (attribute: AttributeInput) => void; onAssignReferencesClick: (attribute: AttributeInput) => void;
onCloseDialog: () => void; onCloseDialog: () => void;
onVariantReorder: ReorderAction; onVariantReorder: ReorderAction;
@ -109,7 +115,8 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
saveButtonBarState, saveButtonBarState,
variant, variant,
warehouses, warehouses,
referencePages, referencePages = [],
referenceProducts = [],
onAdd, onAdd,
onBack, onBack,
onDelete, onDelete,
@ -122,7 +129,9 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
assignReferencesAttributeId, assignReferencesAttributeId,
onAssignReferencesClick, onAssignReferencesClick,
fetchReferencePages, fetchReferencePages,
fetchReferenceProducts,
fetchMoreReferencePages, fetchMoreReferencePages,
fetchMoreReferenceProducts,
onCloseDialog onCloseDialog
}) => { }) => {
const intl = useIntl(); const intl = useIntl();
@ -173,6 +182,12 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
warehouses={warehouses} warehouses={warehouses}
currentChannels={channels} currentChannels={channels}
referencePages={referencePages} referencePages={referencePages}
referenceProducts={referenceProducts}
fetchReferencePages={fetchReferencePages}
fetchMoreReferencePages={fetchMoreReferencePages}
fetchReferenceProducts={fetchReferenceProducts}
fetchMoreReferenceProducts={fetchMoreReferenceProducts}
assignReferencesAttributeId={assignReferencesAttributeId}
> >
{({ {({
change, change,
@ -296,13 +311,14 @@ const ProductVariantPage: React.FC<ProductVariantPageProps> = ({
attributeValues={getAttributeValuesFromReferences( attributeValues={getAttributeValuesFromReferences(
assignReferencesAttributeId, assignReferencesAttributeId,
data.attributes, data.attributes,
referencePages referencePages,
referenceProducts
)} )}
hasMore={fetchMoreReferencePages?.hasMore} hasMore={handlers.fetchMoreReferences?.hasMore}
open={canOpenAssignReferencesAttributeDialog} open={canOpenAssignReferencesAttributeDialog}
onFetch={fetchReferencePages} onFetch={handlers.fetchReferences}
onFetchMore={fetchMoreReferencePages?.onFetchMore} onFetchMore={handlers.fetchMoreReferences?.onFetchMore}
loading={fetchMoreReferencePages?.loading} loading={handlers.fetchMoreReferences?.loading}
onClose={onCloseDialog} onClose={onCloseDialog}
onSubmit={attributeValues => onSubmit={attributeValues =>
handleAssignReferenceAttribute( handleAssignReferenceAttribute(

View file

@ -4,7 +4,9 @@ import {
createAttributeFileChangeHandler, createAttributeFileChangeHandler,
createAttributeMultiChangeHandler, createAttributeMultiChangeHandler,
createAttributeReferenceChangeHandler, createAttributeReferenceChangeHandler,
createAttributeValueReorderHandler createAttributeValueReorderHandler,
createFetchMoreReferencesHandler,
createFetchReferencesHandler
} from "@saleor/attributes/utils/handlers"; } from "@saleor/attributes/utils/handlers";
import { ChannelPriceData, IChannelPriceArgs } from "@saleor/channels/utils"; import { ChannelPriceData, IChannelPriceArgs } from "@saleor/channels/utils";
import { AttributeInput } from "@saleor/components/Attributes"; import { AttributeInput } from "@saleor/components/Attributes";
@ -25,8 +27,9 @@ import {
validatePrice validatePrice
} from "@saleor/products/utils/validation"; } from "@saleor/products/utils/validation";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages"; import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { SearchProducts_search_edges_node } from "@saleor/searches/types/SearchProducts";
import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses"; import { SearchWarehouses_search_edges_node } from "@saleor/searches/types/SearchWarehouses";
import { ReorderEvent } from "@saleor/types"; import { FetchMoreProps, ReorderEvent } from "@saleor/types";
import { mapMetadataItemToInput } from "@saleor/utils/maps"; import { mapMetadataItemToInput } from "@saleor/utils/maps";
import getMetadata from "@saleor/utils/metadata/getMetadata"; import getMetadata from "@saleor/utils/metadata/getMetadata";
import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger"; import useMetadataChangeTrigger from "@saleor/utils/metadata/useMetadataChangeTrigger";
@ -60,6 +63,12 @@ export interface UseProductVariantUpdateFormOpts {
warehouses: SearchWarehouses_search_edges_node[]; warehouses: SearchWarehouses_search_edges_node[];
currentChannels: ChannelPriceData[]; currentChannels: ChannelPriceData[];
referencePages: SearchPages_search_edges_node[]; referencePages: SearchPages_search_edges_node[];
referenceProducts: SearchProducts_search_edges_node[];
fetchReferencePages?: (data: string) => void;
fetchMoreReferencePages?: FetchMoreProps;
fetchReferenceProducts?: (data: string) => void;
fetchMoreReferenceProducts?: FetchMoreProps;
assignReferencesAttributeId?: string;
} }
export interface ProductVariantUpdateHandlers export interface ProductVariantUpdateHandlers
@ -75,6 +84,8 @@ export interface ProductVariantUpdateHandlers
Record<"reorderAttributeValue", FormsetChange<ReorderEvent>>, Record<"reorderAttributeValue", FormsetChange<ReorderEvent>>,
Record<"addStock" | "deleteStock", (id: string) => void> { Record<"addStock" | "deleteStock", (id: string) => void> {
changeMetadata: FormChange; changeMetadata: FormChange;
fetchReferences: (value: string) => void;
fetchMoreReferences: FetchMoreProps;
} }
export interface UseProductVariantUpdateFormResult { export interface UseProductVariantUpdateFormResult {
@ -142,6 +153,18 @@ function useProductVariantUpdateForm(
attributes.change, attributes.change,
triggerChange triggerChange
); );
const handleFetchReferences = createFetchReferencesHandler(
attributes.data,
opts.assignReferencesAttributeId,
opts.fetchReferencePages,
opts.fetchReferenceProducts
);
const handleFetchMoreReferences = createFetchMoreReferencesHandler(
attributes.data,
opts.assignReferencesAttributeId,
opts.fetchMoreReferencePages,
opts.fetchMoreReferenceProducts
);
const handleAttributeFileChange = createAttributeFileChangeHandler( const handleAttributeFileChange = createAttributeFileChangeHandler(
attributes.change, attributes.change,
attributesWithNewFileValue.data, attributesWithNewFileValue.data,
@ -201,7 +224,8 @@ function useProductVariantUpdateForm(
attributes: getAttributesDisplayData( attributes: getAttributesDisplayData(
attributes.data, attributes.data,
attributesWithNewFileValue.data, attributesWithNewFileValue.data,
opts.referencePages opts.referencePages,
opts.referenceProducts
), ),
channelListings: channels.data, channelListings: channels.data,
stocks: stocks.data stocks: stocks.data
@ -239,6 +263,8 @@ function useProductVariantUpdateForm(
changeMetadata, changeMetadata,
changeStock: handleStockChange, changeStock: handleStockChange,
deleteStock: handleStockDelete, deleteStock: handleStockDelete,
fetchMoreReferences: handleFetchMoreReferences,
fetchReferences: handleFetchReferences,
reorderAttributeValue: handleAttributeValueReorder, reorderAttributeValue: handleAttributeValueReorder,
selectAttribute: handleAttributeChange, selectAttribute: handleAttributeChange,
selectAttributeFile: handleAttributeFileChange, selectAttributeFile: handleAttributeFileChange,

View file

@ -22,6 +22,7 @@ export const product: (
__typename: "SelectedAttribute", __typename: "SelectedAttribute",
attribute: { attribute: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "pta18161", id: "pta18161",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Borders", name: "Borders",
@ -61,6 +62,7 @@ export const product: (
__typename: "SelectedAttribute", __typename: "SelectedAttribute",
attribute: { attribute: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "pta22785", id: "pta22785",
inputType: AttributeInputTypeEnum.MULTISELECT, inputType: AttributeInputTypeEnum.MULTISELECT,
name: "Legacy", name: "Legacy",
@ -262,6 +264,7 @@ export const product: (
nonSelectionVariantAttributes: [ nonSelectionVariantAttributes: [
{ {
__typename: "Attribute", __typename: "Attribute",
entityType: null,
id: "isdugfhud", id: "isdugfhud",
inputType: AttributeInputTypeEnum.FILE, inputType: AttributeInputTypeEnum.FILE,
name: "Attachment", name: "Attachment",
@ -286,6 +289,7 @@ export const product: (
selectionVariantAttributes: [ selectionVariantAttributes: [
{ {
__typename: "Attribute", __typename: "Attribute",
entityType: null,
id: "pta18161", id: "pta18161",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Color", name: "Color",
@ -2710,6 +2714,7 @@ export const variant = (placeholderImage: string): ProductVariant => ({
__typename: "SelectedAttribute", __typename: "SelectedAttribute",
attribute: { attribute: {
__typename: "Attribute", __typename: "Attribute",
entityType: null,
id: "nfnyffcf8eyfm", id: "nfnyffcf8eyfm",
inputType: AttributeInputTypeEnum.FILE, inputType: AttributeInputTypeEnum.FILE,
name: "Attachment", name: "Attachment",
@ -2945,6 +2950,7 @@ export const variant = (placeholderImage: string): ProductVariant => ({
__typename: "SelectedAttribute", __typename: "SelectedAttribute",
attribute: { attribute: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "pta18161", id: "pta18161",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Borders", name: "Borders",
@ -2984,6 +2990,7 @@ export const variant = (placeholderImage: string): ProductVariant => ({
__typename: "SelectedAttribute", __typename: "SelectedAttribute",
attribute: { attribute: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
entityType: null,
id: "pta22785", id: "pta22785",
inputType: AttributeInputTypeEnum.DROPDOWN, inputType: AttributeInputTypeEnum.DROPDOWN,
name: "Legacy", name: "Legacy",

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: CreateMultipleVariantsData // GraphQL query operation: CreateMultipleVariantsData
@ -29,6 +29,7 @@ export interface CreateMultipleVariantsData_product_attributes_attribute {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (CreateMultipleVariantsData_product_attributes_attribute_values | null)[] | null; values: (CreateMultipleVariantsData_product_attributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ProductChannelListingUpdateInput, AttributeInputTypeEnum, WeightUnitsEnum, ProductErrorCode } from "./../../types/globalTypes"; import { ProductChannelListingUpdateInput, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum, ProductErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductChannelListingUpdate // GraphQL mutation operation: ProductChannelListingUpdate
@ -29,6 +29,7 @@ export interface ProductChannelListingUpdate_productChannelListingUpdate_product
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductChannelListingUpdate_productChannelListingUpdate_product_attributes_attribute_values | null)[] | null; values: (ProductChannelListingUpdate_productChannelListingUpdate_product_attributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ProductCreateInput, ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { ProductCreateInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductCreate // GraphQL mutation operation: ProductCreate
@ -36,6 +36,7 @@ export interface ProductCreate_productCreate_product_attributes_attribute {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductCreate_productCreate_product_attributes_attribute_values | null)[] | null; values: (ProductCreate_productCreate_product_attributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: ProductDetails // GraphQL query operation: ProductDetails
@ -29,6 +29,7 @@ export interface ProductDetails_product_attributes_attribute {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductDetails_product_attributes_attribute_values | null)[] | null; values: (ProductDetails_product_attributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductImageCreate // GraphQL mutation operation: ProductImageCreate
@ -35,6 +35,7 @@ export interface ProductImageCreate_productImageCreate_product_attributes_attrib
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductImageCreate_productImageCreate_product_attributes_attribute_values | null)[] | null; values: (ProductImageCreate_productImageCreate_product_attributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductImageUpdate // GraphQL mutation operation: ProductImageUpdate
@ -35,6 +35,7 @@ export interface ProductImageUpdate_productImageUpdate_product_attributes_attrib
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductImageUpdate_productImageUpdate_product_attributes_attribute_values | null)[] | null; values: (ProductImageUpdate_productImageUpdate_product_attributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ProductInput, ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { ProductInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductUpdate // GraphQL mutation operation: ProductUpdate
@ -36,6 +36,7 @@ export interface ProductUpdate_productUpdate_product_attributes_attribute {
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductUpdate_productUpdate_product_attributes_attribute_values | null)[] | null; values: (ProductUpdate_productUpdate_product_attributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ProductVariantChannelListingAddInput, AttributeInputTypeEnum, WeightUnitsEnum, ProductErrorCode } from "./../../types/globalTypes"; import { ProductVariantChannelListingAddInput, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum, ProductErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductVariantChannelListingUpdate // GraphQL mutation operation: ProductVariantChannelListingUpdate
@ -41,6 +41,7 @@ export interface ProductVariantChannelListingUpdate_productVariantChannelListing
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductVariantChannelListingUpdate_productVariantChannelListingUpdate_variant_selectionAttributes_attribute_values | null)[] | null; values: (ProductVariantChannelListingUpdate_productVariantChannelListingUpdate_variant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -87,6 +88,7 @@ export interface ProductVariantChannelListingUpdate_productVariantChannelListing
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductVariantChannelListingUpdate_productVariantChannelListingUpdate_variant_nonSelectionAttributes_attribute_values | null)[] | null; values: (ProductVariantChannelListingUpdate_productVariantChannelListingUpdate_variant_nonSelectionAttributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: ProductVariantCreateData // GraphQL query operation: ProductVariantCreateData
@ -48,6 +48,7 @@ export interface ProductVariantCreateData_product_productType_selectionVariantAt
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductVariantCreateData_product_productType_selectionVariantAttributes_values | null)[] | null; values: (ProductVariantCreateData_product_productType_selectionVariantAttributes_values | null)[] | null;
} }
@ -73,6 +74,7 @@ export interface ProductVariantCreateData_product_productType_nonSelectionVarian
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductVariantCreateData_product_productType_nonSelectionVariantAttributes_values | null)[] | null; values: (ProductVariantCreateData_product_productType_nonSelectionVariantAttributes_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: ProductVariantDetails // GraphQL query operation: ProductVariantDetails
@ -41,6 +41,7 @@ export interface ProductVariantDetails_productVariant_selectionAttributes_attrib
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductVariantDetails_productVariant_selectionAttributes_attribute_values | null)[] | null; values: (ProductVariantDetails_productVariant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -87,6 +88,7 @@ export interface ProductVariantDetails_productVariant_nonSelectionAttributes_att
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductVariantDetails_productVariant_nonSelectionAttributes_attribute_values | null)[] | null; values: (ProductVariantDetails_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ReorderInput, ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { ReorderInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductVariantReorder // GraphQL mutation operation: ProductVariantReorder
@ -35,6 +35,7 @@ export interface ProductVariantReorder_productVariantReorder_product_attributes_
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductVariantReorder_productVariantReorder_product_attributes_attribute_values | null)[] | null; values: (ProductVariantReorder_productVariantReorder_product_attributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: ProductVariantSetDefault // GraphQL mutation operation: ProductVariantSetDefault
@ -35,6 +35,7 @@ export interface ProductVariantSetDefault_productVariantSetDefault_product_attri
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (ProductVariantSetDefault_productVariantSetDefault_product_attributes_attribute_values | null)[] | null; values: (ProductVariantSetDefault_productVariantSetDefault_product_attributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ProductInput, ProductVariantInput, StockInput, ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum, StockErrorCode } from "./../../types/globalTypes"; import { ProductInput, ProductVariantInput, StockInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum, StockErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: SimpleProductUpdate // GraphQL mutation operation: SimpleProductUpdate
@ -36,6 +36,7 @@ export interface SimpleProductUpdate_productUpdate_product_attributes_attribute
slug: string | null; slug: string | null;
name: string | null; name: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (SimpleProductUpdate_productUpdate_product_attributes_attribute_values | null)[] | null; values: (SimpleProductUpdate_productUpdate_product_attributes_attribute_values | null)[] | null;
} }
@ -320,6 +321,7 @@ export interface SimpleProductUpdate_productVariantUpdate_productVariant_selecti
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (SimpleProductUpdate_productVariantUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null; values: (SimpleProductUpdate_productVariantUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -366,6 +368,7 @@ export interface SimpleProductUpdate_productVariantUpdate_productVariant_nonSele
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (SimpleProductUpdate_productVariantUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null; values: (SimpleProductUpdate_productVariantUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
} }
@ -595,6 +598,7 @@ export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_s
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (SimpleProductUpdate_productVariantStocksCreate_productVariant_selectionAttributes_attribute_values | null)[] | null; values: (SimpleProductUpdate_productVariantStocksCreate_productVariant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -641,6 +645,7 @@ export interface SimpleProductUpdate_productVariantStocksCreate_productVariant_n
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (SimpleProductUpdate_productVariantStocksCreate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null; values: (SimpleProductUpdate_productVariantStocksCreate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
} }
@ -869,6 +874,7 @@ export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_s
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (SimpleProductUpdate_productVariantStocksDelete_productVariant_selectionAttributes_attribute_values | null)[] | null; values: (SimpleProductUpdate_productVariantStocksDelete_productVariant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -915,6 +921,7 @@ export interface SimpleProductUpdate_productVariantStocksDelete_productVariant_n
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (SimpleProductUpdate_productVariantStocksDelete_productVariant_nonSelectionAttributes_attribute_values | null)[] | null; values: (SimpleProductUpdate_productVariantStocksDelete_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
} }
@ -1144,6 +1151,7 @@ export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_s
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null; values: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -1190,6 +1198,7 @@ export interface SimpleProductUpdate_productVariantStocksUpdate_productVariant_n
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null; values: (SimpleProductUpdate_productVariantStocksUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ProductVariantCreateInput, ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { ProductVariantCreateInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: VariantCreate // GraphQL mutation operation: VariantCreate
@ -48,6 +48,7 @@ export interface VariantCreate_productVariantCreate_productVariant_selectionAttr
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (VariantCreate_productVariantCreate_productVariant_selectionAttributes_attribute_values | null)[] | null; values: (VariantCreate_productVariantCreate_productVariant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -94,6 +95,7 @@ export interface VariantCreate_productVariantCreate_productVariant_nonSelectionA
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (VariantCreate_productVariantCreate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null; values: (VariantCreate_productVariantCreate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: VariantImageAssign // GraphQL mutation operation: VariantImageAssign
@ -47,6 +47,7 @@ export interface VariantImageAssign_variantImageAssign_productVariant_selectionA
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (VariantImageAssign_variantImageAssign_productVariant_selectionAttributes_attribute_values | null)[] | null; values: (VariantImageAssign_variantImageAssign_productVariant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -93,6 +94,7 @@ export interface VariantImageAssign_variantImageAssign_productVariant_nonSelecti
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (VariantImageAssign_variantImageAssign_productVariant_nonSelectionAttributes_attribute_values | null)[] | null; values: (VariantImageAssign_variantImageAssign_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes"; import { ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: VariantImageUnassign // GraphQL mutation operation: VariantImageUnassign
@ -47,6 +47,7 @@ export interface VariantImageUnassign_variantImageUnassign_productVariant_select
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (VariantImageUnassign_variantImageUnassign_productVariant_selectionAttributes_attribute_values | null)[] | null; values: (VariantImageUnassign_variantImageUnassign_productVariant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -93,6 +94,7 @@ export interface VariantImageUnassign_variantImageUnassign_productVariant_nonSel
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (VariantImageUnassign_variantImageUnassign_productVariant_nonSelectionAttributes_attribute_values | null)[] | null; values: (VariantImageUnassign_variantImageUnassign_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
} }

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { StockInput, AttributeValueInput, ProductErrorCode, AttributeInputTypeEnum, WeightUnitsEnum, StockErrorCode } from "./../../types/globalTypes"; import { StockInput, AttributeValueInput, ProductErrorCode, AttributeInputTypeEnum, AttributeEntityTypeEnum, WeightUnitsEnum, StockErrorCode } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL mutation operation: VariantUpdate // GraphQL mutation operation: VariantUpdate
@ -48,6 +48,7 @@ export interface VariantUpdate_productVariantUpdate_productVariant_selectionAttr
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (VariantUpdate_productVariantUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null; values: (VariantUpdate_productVariantUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -94,6 +95,7 @@ export interface VariantUpdate_productVariantUpdate_productVariant_nonSelectionA
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (VariantUpdate_productVariantUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null; values: (VariantUpdate_productVariantUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
} }
@ -323,6 +325,7 @@ export interface VariantUpdate_productVariantStocksUpdate_productVariant_selecti
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (VariantUpdate_productVariantStocksUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null; values: (VariantUpdate_productVariantStocksUpdate_productVariant_selectionAttributes_attribute_values | null)[] | null;
} }
@ -369,6 +372,7 @@ export interface VariantUpdate_productVariantStocksUpdate_productVariant_nonSele
name: string | null; name: string | null;
slug: string | null; slug: string | null;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
valueRequired: boolean; valueRequired: boolean;
values: (VariantUpdate_productVariantStocksUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null; values: (VariantUpdate_productVariantStocksUpdate_productVariant_nonSelectionAttributes_attribute_values | null)[] | null;
} }

View file

@ -47,6 +47,7 @@ export function getAttributeInputFromProduct(
(): AttributeInput[] => (): AttributeInput[] =>
product.attributes.map(attribute => ({ product.attributes.map(attribute => ({
data: { data: {
entityType: attribute.attribute.entityType,
inputType: attribute.attribute.inputType, inputType: attribute.attribute.inputType,
isRequired: attribute.attribute.valueRequired, isRequired: attribute.attribute.valueRequired,
selectedValues: attribute.values, selectedValues: attribute.values,
@ -65,6 +66,7 @@ export function getAttributeInputFromProductType(
): AttributeInput[] { ): AttributeInput[] {
return productType.productAttributes.map(attribute => ({ return productType.productAttributes.map(attribute => ({
data: { data: {
entityType: attribute.entityType,
inputType: attribute.inputType, inputType: attribute.inputType,
isRequired: attribute.valueRequired, isRequired: attribute.valueRequired,
values: attribute.values values: attribute.values
@ -81,6 +83,7 @@ export function getAttributeInputFromAttributes(
): AttributeInput[] { ): AttributeInput[] {
return variantAttributes?.map(attribute => ({ return variantAttributes?.map(attribute => ({
data: { data: {
entityType: attribute.entityType,
inputType: attribute.inputType, inputType: attribute.inputType,
isRequired: attribute.valueRequired, isRequired: attribute.valueRequired,
values: attribute.values, values: attribute.values,
@ -98,6 +101,7 @@ export function getAttributeInputFromSelectedAttributes(
): AttributeInput[] { ): AttributeInput[] {
return variantAttributes?.map(attribute => ({ return variantAttributes?.map(attribute => ({
data: { data: {
entityType: attribute.attribute.entityType,
inputType: attribute.attribute.inputType, inputType: attribute.attribute.inputType,
isRequired: attribute.attribute.valueRequired, isRequired: attribute.attribute.valueRequired,
selectedValues: attribute.values, selectedValues: attribute.values,

View file

@ -27,6 +27,7 @@ import {
import useCategorySearch from "@saleor/searches/useCategorySearch"; import useCategorySearch from "@saleor/searches/useCategorySearch";
import useCollectionSearch from "@saleor/searches/useCollectionSearch"; import useCollectionSearch from "@saleor/searches/useCollectionSearch";
import usePageSearch from "@saleor/searches/usePageSearch"; import usePageSearch from "@saleor/searches/usePageSearch";
import useProductSearch from "@saleor/searches/useProductSearch";
import useProductTypeSearch from "@saleor/searches/useProductTypeSearch"; import useProductTypeSearch from "@saleor/searches/useProductTypeSearch";
import { useTaxTypeList } from "@saleor/taxes/queries"; import { useTaxTypeList } from "@saleor/taxes/queries";
import { getProductErrorMessage } from "@saleor/utils/errors"; import { getProductErrorMessage } from "@saleor/utils/errors";
@ -89,6 +90,13 @@ export const ProductCreateView: React.FC<ProductCreateProps> = ({ params }) => {
} = usePageSearch({ } = usePageSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA variables: DEFAULT_INITIAL_SEARCH_DATA
}); });
const {
loadMore: loadMoreProducts,
search: searchProducts,
result: searchProductsOpts
} = useProductSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const warehouses = useWarehouseList({ const warehouses = useWarehouseList({
displayLoader: true, displayLoader: true,
variables: { variables: {
@ -202,25 +210,30 @@ export const ProductCreateView: React.FC<ProductCreateProps> = ({ params }) => {
}, [productCreateComplete]); }, [productCreateComplete]);
const fetchMoreProductTypes = { const fetchMoreProductTypes = {
hasMore: searchProductTypesOpts.data?.search.pageInfo.hasNextPage, hasMore: searchProductTypesOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchProductTypesOpts.loading, loading: searchProductTypesOpts.loading,
onFetchMore: loadMoreProductTypes onFetchMore: loadMoreProductTypes
}; };
const fetchMoreCollections = { const fetchMoreCollections = {
hasMore: searchCollectionOpts.data?.search.pageInfo.hasNextPage, hasMore: searchCollectionOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchCollectionOpts.loading, loading: searchCollectionOpts.loading,
onFetchMore: loadMoreCollections onFetchMore: loadMoreCollections
}; };
const fetchMoreCategories = { const fetchMoreCategories = {
hasMore: searchCategoryOpts.data?.search.pageInfo.hasNextPage, hasMore: searchCategoryOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchCategoryOpts.loading, loading: searchCategoryOpts.loading,
onFetchMore: loadMoreCategories onFetchMore: loadMoreCategories
}; };
const fetchMoreReferencePages = { const fetchMoreReferencePages = {
hasMore: searchPagesOpts.data?.search.pageInfo.hasNextPage, hasMore: searchPagesOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchPagesOpts.loading, loading: searchPagesOpts.loading,
onFetchMore: loadMorePages onFetchMore: loadMorePages
}; };
const fetchMoreReferenceProducts = {
hasMore: searchProductsOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchProductsOpts.loading,
onFetchMore: loadMoreProducts
};
const loading = const loading =
uploadFileOpts.loading || uploadFileOpts.loading ||
@ -301,8 +314,13 @@ export const ProductCreateView: React.FC<ProductCreateProps> = ({ params }) => {
referencePages={searchPagesOpts.data?.search.edges.map( referencePages={searchPagesOpts.data?.search.edges.map(
edge => edge.node edge => edge.node
)} )}
referenceProducts={searchProductsOpts.data?.search.edges.map(
edge => edge.node
)}
fetchReferencePages={searchPages} fetchReferencePages={searchPages}
fetchMoreReferencePages={fetchMoreReferencePages} fetchMoreReferencePages={fetchMoreReferencePages}
fetchReferenceProducts={searchProducts}
fetchMoreReferenceProducts={fetchMoreReferenceProducts}
onCloseDialog={() => navigate(productAddUrl())} onCloseDialog={() => navigate(productAddUrl())}
/> />
</> </>

View file

@ -40,6 +40,7 @@ import {
import useCategorySearch from "@saleor/searches/useCategorySearch"; import useCategorySearch from "@saleor/searches/useCategorySearch";
import useCollectionSearch from "@saleor/searches/useCollectionSearch"; import useCollectionSearch from "@saleor/searches/useCollectionSearch";
import usePageSearch from "@saleor/searches/usePageSearch"; import usePageSearch from "@saleor/searches/usePageSearch";
import useProductSearch from "@saleor/searches/useProductSearch";
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 {
@ -106,6 +107,13 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
} = usePageSearch({ } = usePageSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA variables: DEFAULT_INITIAL_SEARCH_DATA
}); });
const {
loadMore: loadMoreProducts,
search: searchProducts,
result: searchProductsOpts
} = useProductSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const warehouses = useWarehouseList({ const warehouses = useWarehouseList({
displayLoader: true, displayLoader: true,
variables: { variables: {
@ -356,20 +364,25 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
]; ];
const fetchMoreCollections = { const fetchMoreCollections = {
hasMore: searchCollectionsOpts.data?.search.pageInfo.hasNextPage, hasMore: searchCollectionsOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchCollectionsOpts.loading, loading: searchCollectionsOpts.loading,
onFetchMore: loadMoreCollections onFetchMore: loadMoreCollections
}; };
const fetchMoreCategories = { const fetchMoreCategories = {
hasMore: searchCategoriesOpts.data?.search.pageInfo.hasNextPage, hasMore: searchCategoriesOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchCategoriesOpts.loading, loading: searchCategoriesOpts.loading,
onFetchMore: loadMoreCategories onFetchMore: loadMoreCategories
}; };
const fetchMoreReferencePages = { const fetchMoreReferencePages = {
hasMore: searchPagesOpts.data?.search.pageInfo.hasNextPage, hasMore: searchPagesOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchPagesOpts.loading, loading: searchPagesOpts.loading,
onFetchMore: loadMorePages onFetchMore: loadMorePages
}; };
const fetchMoreReferenceProducts = {
hasMore: searchProductsOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchProductsOpts.loading,
onFetchMore: loadMoreProducts
};
return ( return (
<> <>
@ -458,8 +471,13 @@ export const ProductUpdate: React.FC<ProductUpdateProps> = ({ id, params }) => {
referencePages={searchPagesOpts.data?.search.edges.map( referencePages={searchPagesOpts.data?.search.edges.map(
edge => edge.node edge => edge.node
)} )}
referenceProducts={searchProductsOpts.data?.search.edges.map(
edge => edge.node
)}
fetchReferencePages={searchPages} fetchReferencePages={searchPages}
fetchMoreReferencePages={fetchMoreReferencePages} fetchMoreReferencePages={fetchMoreReferencePages}
fetchReferenceProducts={searchProducts}
fetchMoreReferenceProducts={fetchMoreReferenceProducts}
onCloseDialog={() => navigate(productUrl(id))} onCloseDialog={() => navigate(productUrl(id))}
/> />
<ActionDialog <ActionDialog

View file

@ -24,6 +24,7 @@ import { commonMessages } from "@saleor/intl";
import { useProductVariantChannelListingUpdate } from "@saleor/products/mutations"; import { useProductVariantChannelListingUpdate } from "@saleor/products/mutations";
import { ProductVariantDetails_productVariant } from "@saleor/products/types/ProductVariantDetails"; import { ProductVariantDetails_productVariant } from "@saleor/products/types/ProductVariantDetails";
import usePageSearch from "@saleor/searches/usePageSearch"; import usePageSearch from "@saleor/searches/usePageSearch";
import useProductSearch from "@saleor/searches/useProductSearch";
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 {
@ -287,12 +288,24 @@ export const ProductVariant: React.FC<ProductUpdateProps> = ({
} = usePageSearch({ } = usePageSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA variables: DEFAULT_INITIAL_SEARCH_DATA
}); });
const {
loadMore: loadMoreProducts,
search: searchProducts,
result: searchProductsOpts
} = useProductSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const fetchMoreReferencePages = { const fetchMoreReferencePages = {
hasMore: searchPagesOpts.data?.search.pageInfo.hasNextPage, hasMore: searchPagesOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchPagesOpts.loading, loading: searchPagesOpts.loading,
onFetchMore: loadMorePages onFetchMore: loadMorePages
}; };
const fetchMoreReferenceProducts = {
hasMore: searchProductsOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchProductsOpts.loading,
onFetchMore: loadMoreProducts
};
return ( return (
<> <>
@ -335,8 +348,13 @@ export const ProductVariant: React.FC<ProductUpdateProps> = ({
referencePages={searchPagesOpts.data?.search.edges.map( referencePages={searchPagesOpts.data?.search.edges.map(
edge => edge.node edge => edge.node
)} )}
referenceProducts={searchProductsOpts.data?.search.edges.map(
edge => edge.node
)}
fetchReferencePages={searchPages} fetchReferencePages={searchPages}
fetchMoreReferencePages={fetchMoreReferencePages} fetchMoreReferencePages={fetchMoreReferencePages}
fetchReferenceProducts={searchProducts}
fetchMoreReferenceProducts={fetchMoreReferenceProducts}
onCloseDialog={() => onCloseDialog={() =>
navigate(productVariantEditUrl(productId, variantId)) navigate(productVariantEditUrl(productId, variantId))
} }

View file

@ -16,6 +16,7 @@ import { commonMessages } from "@saleor/intl";
import { useProductVariantChannelListingUpdate } from "@saleor/products/mutations"; import { useProductVariantChannelListingUpdate } from "@saleor/products/mutations";
import { ProductVariantChannelListingUpdate } from "@saleor/products/types/ProductVariantChannelListingUpdate"; import { ProductVariantChannelListingUpdate } from "@saleor/products/types/ProductVariantChannelListingUpdate";
import usePageSearch from "@saleor/searches/usePageSearch"; import usePageSearch from "@saleor/searches/usePageSearch";
import useProductSearch from "@saleor/searches/useProductSearch";
import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler"; import createMetadataCreateHandler from "@saleor/utils/handlers/metadataCreateHandler";
import { import {
useMetadataUpdate, useMetadataUpdate,
@ -198,12 +199,24 @@ export const ProductVariant: React.FC<ProductVariantCreateProps> = ({
} = usePageSearch({ } = usePageSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA variables: DEFAULT_INITIAL_SEARCH_DATA
}); });
const {
loadMore: loadMoreProducts,
search: searchProducts,
result: searchProductsOpts
} = useProductSearch({
variables: DEFAULT_INITIAL_SEARCH_DATA
});
const fetchMoreReferencePages = { const fetchMoreReferencePages = {
hasMore: searchPagesOpts.data?.search.pageInfo.hasNextPage, hasMore: searchPagesOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchPagesOpts.loading, loading: searchPagesOpts.loading,
onFetchMore: loadMorePages onFetchMore: loadMorePages
}; };
const fetchMoreReferenceProducts = {
hasMore: searchProductsOpts.data?.search?.pageInfo?.hasNextPage,
loading: searchProductsOpts.loading,
onFetchMore: loadMoreProducts
};
const disableForm = const disableForm =
productLoading || productLoading ||
@ -248,8 +261,13 @@ export const ProductVariant: React.FC<ProductVariantCreateProps> = ({
referencePages={searchPagesOpts.data?.search.edges.map( referencePages={searchPagesOpts.data?.search.edges.map(
edge => edge.node edge => edge.node
)} )}
referenceProducts={searchProductsOpts.data?.search.edges.map(
edge => edge.node
)}
fetchReferencePages={searchPages} fetchReferencePages={searchPages}
fetchMoreReferencePages={fetchMoreReferencePages} fetchMoreReferencePages={fetchMoreReferencePages}
fetchReferenceProducts={searchProducts}
fetchMoreReferenceProducts={fetchMoreReferenceProducts}
onCloseDialog={() => navigate(productVariantAddUrl(productId))} onCloseDialog={() => navigate(productVariantAddUrl(productId))}
/> />
</> </>

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: SearchPageTypes // GraphQL query operation: SearchPageTypes
@ -27,6 +27,7 @@ export interface SearchPageTypes_search_edges_node_attributes {
__typename: "Attribute"; __typename: "Attribute";
id: string; id: string;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
slug: string | null; slug: string | null;
name: string | null; name: string | null;
valueRequired: boolean; valueRequired: boolean;

View file

@ -2,7 +2,7 @@
/* eslint-disable */ /* eslint-disable */
// This file was automatically generated and should not be edited. // This file was automatically generated and should not be edited.
import { AttributeInputTypeEnum } from "./../../types/globalTypes"; import { AttributeInputTypeEnum, AttributeEntityTypeEnum } from "./../../types/globalTypes";
// ==================================================== // ====================================================
// GraphQL query operation: SearchProductTypes // GraphQL query operation: SearchProductTypes
@ -27,6 +27,7 @@ export interface SearchProductTypes_search_edges_node_productAttributes {
__typename: "Attribute"; __typename: "Attribute";
id: string; id: string;
inputType: AttributeInputTypeEnum | null; inputType: AttributeInputTypeEnum | null;
entityType: AttributeEntityTypeEnum | null;
slug: string | null; slug: string | null;
name: string | null; name: string | null;
valueRequired: boolean; valueRequired: boolean;

View file

@ -24,6 +24,7 @@ export const searchPageTypes = gql`
attributes { attributes {
id id
inputType inputType
entityType
slug slug
name name
valueRequired valueRequired

View file

@ -27,6 +27,7 @@ export const searchProductTypes = gql`
productAttributes { productAttributes {
id id
inputType inputType
entityType
slug slug
name name
valueRequired valueRequired

View file

@ -19,6 +19,7 @@ const props: PageDetailsPageProps = {
onSubmit: () => undefined, onSubmit: () => undefined,
page, page,
referencePages: [], referencePages: [],
referenceProducts: [],
saveButtonBarState: "default" saveButtonBarState: "default"
}; };

View file

@ -46,6 +46,7 @@ storiesOf("Views / Products / Create product", module)
taxTypes={taxTypes} taxTypes={taxTypes}
weightUnit="kg" weightUnit="kg"
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />
@ -77,6 +78,7 @@ storiesOf("Views / Products / Create product", module)
taxTypes={taxTypes} taxTypes={taxTypes}
weightUnit="kg" weightUnit="kg"
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />
@ -125,6 +127,7 @@ storiesOf("Views / Products / Create product", module)
taxTypes={taxTypes} taxTypes={taxTypes}
weightUnit="kg" weightUnit="kg"
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />

View file

@ -60,6 +60,7 @@ const props: ProductUpdatePageProps = {
placeholderImage, placeholderImage,
product, product,
referencePages: [], referencePages: [],
referenceProducts: [],
saveButtonBarState: "default", saveButtonBarState: "default",
selectedChannelId: "123", selectedChannelId: "123",
taxTypes, taxTypes,

View file

@ -36,6 +36,7 @@ storiesOf("Views / Products / Create product variant", module)
warehouses={warehouseList} warehouses={warehouseList}
onWarehouseConfigure={() => undefined} onWarehouseConfigure={() => undefined}
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />
@ -76,6 +77,7 @@ storiesOf("Views / Products / Create product variant", module)
warehouses={warehouseList} warehouses={warehouseList}
onWarehouseConfigure={() => undefined} onWarehouseConfigure={() => undefined}
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />
@ -97,6 +99,7 @@ storiesOf("Views / Products / Create product variant", module)
warehouses={warehouseList} warehouses={warehouseList}
onWarehouseConfigure={() => undefined} onWarehouseConfigure={() => undefined}
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />
@ -121,6 +124,7 @@ storiesOf("Views / Products / Create product variant", module)
warehouses={warehouseList} warehouses={warehouseList}
onWarehouseConfigure={() => undefined} onWarehouseConfigure={() => undefined}
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />
@ -142,6 +146,7 @@ storiesOf("Views / Products / Create product variant", module)
warehouses={[]} warehouses={[]}
onWarehouseConfigure={() => undefined} onWarehouseConfigure={() => undefined}
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />

View file

@ -34,6 +34,7 @@ storiesOf("Views / Products / Product variant details", module)
warehouses={warehouseList} warehouses={warehouseList}
onWarehouseConfigure={() => undefined} onWarehouseConfigure={() => undefined}
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />
@ -59,6 +60,7 @@ storiesOf("Views / Products / Product variant details", module)
warehouses={warehouseList} warehouses={warehouseList}
onWarehouseConfigure={() => undefined} onWarehouseConfigure={() => undefined}
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />
@ -83,6 +85,7 @@ storiesOf("Views / Products / Product variant details", module)
warehouses={[]} warehouses={[]}
onWarehouseConfigure={() => undefined} onWarehouseConfigure={() => undefined}
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />
@ -135,6 +138,7 @@ storiesOf("Views / Products / Product variant details", module)
warehouses={warehouseList} warehouses={warehouseList}
onWarehouseConfigure={() => undefined} onWarehouseConfigure={() => undefined}
referencePages={[]} referencePages={[]}
referenceProducts={[]}
onAssignReferencesClick={() => undefined} onAssignReferencesClick={() => undefined}
onCloseDialog={() => undefined} onCloseDialog={() => undefined}
/> />

View file

@ -72,6 +72,7 @@ export enum AppTypeEnum {
export enum AttributeEntityTypeEnum { export enum AttributeEntityTypeEnum {
PAGE = "PAGE", PAGE = "PAGE",
PRODUCT = "PRODUCT",
} }
export enum AttributeErrorCode { export enum AttributeErrorCode {
@ -1333,6 +1334,7 @@ export interface OrderDraftFilterInput {
customer?: string | null; customer?: string | null;
created?: DateRangeInput | null; created?: DateRangeInput | null;
search?: string | null; search?: string | null;
channels?: (string | null)[] | null;
} }
export interface OrderFilterInput { export interface OrderFilterInput {

View file

@ -2,6 +2,7 @@ import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocomplet
import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo"; import { ShopInfo_shop_countries } from "@saleor/components/Shop/types/ShopInfo";
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
import { MetadataItem } from "@saleor/fragments/types/MetadataItem"; import { MetadataItem } from "@saleor/fragments/types/MetadataItem";
import { SearchPages_search_edges_node } from "@saleor/searches/types/SearchPages";
import { Node } from "@saleor/types"; import { Node } from "@saleor/types";
import { MetadataInput } from "@saleor/types/globalTypes"; import { MetadataInput } from "@saleor/types/globalTypes";
@ -14,6 +15,15 @@ export function mapCountriesToChoices(
})); }));
} }
export function mapPagesToChoices(
pages: SearchPages_search_edges_node[]
): Array<SingleAutocompleteChoiceType | MultiAutocompleteChoiceType> {
return pages.map(page => ({
label: page.title,
value: page.id
}));
}
export function mapNodeToChoice( export function mapNodeToChoice(
nodes: Array<Node & Record<"name", string>> nodes: Array<Node & Record<"name", string>>
): Array<SingleAutocompleteChoiceType | MultiAutocompleteChoiceType> { ): Array<SingleAutocompleteChoiceType | MultiAutocompleteChoiceType> {

View file

@ -38,7 +38,7 @@ export interface UpdateMetadata_deleteMetadata_item_privateMetadata {
} }
export interface UpdateMetadata_deleteMetadata_item { export interface UpdateMetadata_deleteMetadata_item {
__typename: "App" | "ShippingZone" | "ShippingMethod" | "Product" | "ProductType" | "Attribute" | "Category" | "ProductVariant" | "DigitalContent" | "Collection" | "Page" | "PageType" | "User" | "Checkout" | "Order" | "Fulfillment" | "Invoice"; __typename: "App" | "ShippingZone" | "ShippingMethod" | "Product" | "ProductType" | "Attribute" | "Category" | "ProductVariant" | "DigitalContent" | "Collection" | "Page" | "PageType" | "MenuItem" | "Menu" | "User" | "Checkout" | "Order" | "Fulfillment" | "Invoice";
metadata: (UpdateMetadata_deleteMetadata_item_metadata | null)[]; metadata: (UpdateMetadata_deleteMetadata_item_metadata | null)[];
privateMetadata: (UpdateMetadata_deleteMetadata_item_privateMetadata | null)[]; privateMetadata: (UpdateMetadata_deleteMetadata_item_privateMetadata | null)[];
id: string; id: string;

View file

@ -38,7 +38,7 @@ export interface UpdatePrivateMetadata_deletePrivateMetadata_item_privateMetadat
} }
export interface UpdatePrivateMetadata_deletePrivateMetadata_item { export interface UpdatePrivateMetadata_deletePrivateMetadata_item {
__typename: "App" | "ShippingZone" | "ShippingMethod" | "Product" | "ProductType" | "Attribute" | "Category" | "ProductVariant" | "DigitalContent" | "Collection" | "Page" | "PageType" | "User" | "Checkout" | "Order" | "Fulfillment" | "Invoice"; __typename: "App" | "ShippingZone" | "ShippingMethod" | "Product" | "ProductType" | "Attribute" | "Category" | "ProductVariant" | "DigitalContent" | "Collection" | "Page" | "PageType" | "MenuItem" | "Menu" | "User" | "Checkout" | "Order" | "Fulfillment" | "Invoice";
metadata: (UpdatePrivateMetadata_deletePrivateMetadata_item_metadata | null)[]; metadata: (UpdatePrivateMetadata_deletePrivateMetadata_item_metadata | null)[];
privateMetadata: (UpdatePrivateMetadata_deletePrivateMetadata_item_privateMetadata | null)[]; privateMetadata: (UpdatePrivateMetadata_deletePrivateMetadata_item_privateMetadata | null)[];
id: string; id: string;