diff --git a/CHANGELOG.md b/CHANGELOG.md index 3459d114e..e5117f796 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,5 +27,6 @@ All notable, unreleased changes to this project will be documented in this file. - Fix navigation - #182 by @benekex2 - Add testcafe tags to attributes, categories, collections and product types - #178 by @dominik-zeglen - Fix input error style - #183 by @benekex2 +- Fix product type selection - #189 by @dominik-zeglen - Fix staff return link - #190 by @dominik-zeglen - Allow sorting products by attribute - #180 by @dominik-zeglen diff --git a/src/containers/SearchProductTypes/index.tsx b/src/containers/SearchProductTypes/index.tsx new file mode 100644 index 000000000..6cc389137 --- /dev/null +++ b/src/containers/SearchProductTypes/index.tsx @@ -0,0 +1,37 @@ +import gql from "graphql-tag"; + +import BaseSearch from "../BaseSearch"; +import { + SearchProductTypes, + SearchProductTypesVariables +} from "./types/SearchProductTypes"; + +export const searchProductTypes = gql` + query SearchProductTypes($after: String, $first: Int!, $query: String!) { + productTypes(after: $after, first: $first, filter: { search: $query }) { + edges { + node { + id + name + hasVariants + productAttributes { + id + inputType + slug + name + valueRequired + values { + id + name + slug + } + } + } + } + } + } +`; + +export default BaseSearch( + searchProductTypes +); diff --git a/src/containers/SearchProductTypes/types/SearchProductTypes.ts b/src/containers/SearchProductTypes/types/SearchProductTypes.ts new file mode 100644 index 000000000..f242be391 --- /dev/null +++ b/src/containers/SearchProductTypes/types/SearchProductTypes.ts @@ -0,0 +1,54 @@ +/* tslint:disable */ +/* eslint-disable */ +// This file was automatically generated and should not be edited. + +import { AttributeInputTypeEnum } from "./../../../types/globalTypes"; + +// ==================================================== +// GraphQL query operation: SearchProductTypes +// ==================================================== + +export interface SearchProductTypes_productTypes_edges_node_productAttributes_values { + __typename: "AttributeValue"; + id: string; + name: string | null; + slug: string | null; +} + +export interface SearchProductTypes_productTypes_edges_node_productAttributes { + __typename: "Attribute"; + id: string; + inputType: AttributeInputTypeEnum | null; + slug: string | null; + name: string | null; + valueRequired: boolean; + values: (SearchProductTypes_productTypes_edges_node_productAttributes_values | null)[] | null; +} + +export interface SearchProductTypes_productTypes_edges_node { + __typename: "ProductType"; + id: string; + name: string; + hasVariants: boolean; + productAttributes: (SearchProductTypes_productTypes_edges_node_productAttributes | null)[] | null; +} + +export interface SearchProductTypes_productTypes_edges { + __typename: "ProductTypeCountableEdge"; + node: SearchProductTypes_productTypes_edges_node; +} + +export interface SearchProductTypes_productTypes { + __typename: "ProductTypeCountableConnection"; + edges: SearchProductTypes_productTypes_edges[]; +} + +export interface SearchProductTypes { + productTypes: SearchProductTypes_productTypes | null; +} + +export interface SearchProductTypesVariables { + after?: string | null; + first: number; + query: string; +} diff --git a/src/productTypes/fixtures.ts b/src/productTypes/fixtures.ts index fe214f7bd..375f1b751 100644 --- a/src/productTypes/fixtures.ts +++ b/src/productTypes/fixtures.ts @@ -1,12 +1,12 @@ import { - ProductCreateData_productTypes_edges_node, - ProductCreateData_productTypes_edges_node_productAttributes -} from "../products/types/ProductCreateData"; + SearchProductTypes_productTypes_edges_node, + SearchProductTypes_productTypes_edges_node_productAttributes +} from "@saleor/containers/SearchProductTypes/types/SearchProductTypes"; import { AttributeInputTypeEnum } from "../types/globalTypes"; import { ProductTypeDetails_productType } from "./types/ProductTypeDetails"; import { ProductTypeList_productTypes_edges_node } from "./types/ProductTypeList"; -export const attributes: ProductCreateData_productTypes_edges_node_productAttributes[] = [ +export const attributes: SearchProductTypes_productTypes_edges_node_productAttributes[] = [ { node: { __typename: "Attribute" as "Attribute", @@ -469,7 +469,7 @@ export const attributes: ProductCreateData_productTypes_edges_node_productAttrib ].map(edge => edge.node); export const productTypes: Array< - ProductCreateData_productTypes_edges_node & + SearchProductTypes_productTypes_edges_node & ProductTypeList_productTypes_edges_node > = [ { diff --git a/src/products/components/ProductCreatePage/ProductCreatePage.tsx b/src/products/components/ProductCreatePage/ProductCreatePage.tsx index 4ac375c21..97cbb189a 100644 --- a/src/products/components/ProductCreatePage/ProductCreatePage.tsx +++ b/src/products/components/ProductCreatePage/ProductCreatePage.tsx @@ -15,6 +15,7 @@ import SeoForm from "@saleor/components/SeoForm"; import VisibilityCard from "@saleor/components/VisibilityCard"; import { SearchCategories_categories_edges_node } from "@saleor/containers/SearchCategories/types/SearchCategories"; import { SearchCollections_collections_edges_node } from "@saleor/containers/SearchCollections/types/SearchCollections"; +import { SearchProductTypes_productTypes_edges_node_productAttributes } from "@saleor/containers/SearchProductTypes/types/SearchProductTypes"; import useDateLocalize from "@saleor/hooks/useDateLocalize"; import useFormset from "@saleor/hooks/useFormset"; import useStateFromProps from "@saleor/hooks/useStateFromProps"; @@ -27,7 +28,6 @@ import { import createMultiAutocompleteSelectHandler from "@saleor/utils/handlers/multiAutocompleteSelectChangeHandler"; import createSingleAutocompleteSelectHandler from "@saleor/utils/handlers/singleAutocompleteSelectChangeHandler"; import { UserError } from "../../../types"; -import { ProductCreateData_productTypes_edges_node_productAttributes } from "../../types/ProductCreateData"; import { createAttributeChangeHandler, createAttributeMultiChangeHandler, @@ -71,12 +71,13 @@ interface ProductCreatePageProps { id: string; name: string; hasVariants: boolean; - productAttributes: ProductCreateData_productTypes_edges_node_productAttributes[]; + productAttributes: SearchProductTypes_productTypes_edges_node_productAttributes[]; }>; header: string; saveButtonBarState: ConfirmButtonTransitionState; fetchCategories: (data: string) => void; fetchCollections: (data: string) => void; + fetchProductTypes: (data: string) => void; onAttributesEdit: () => void; onBack?(); onSubmit?(data: ProductCreatePageSubmitData); @@ -96,6 +97,7 @@ export const ProductCreatePage: React.StatelessComponent< productTypes: productTypeChoiceList, saveButtonBarState, onBack, + fetchProductTypes, onSubmit }: ProductCreatePageProps) => { const intl = useIntl(); @@ -139,7 +141,7 @@ export const ProductCreatePage: React.StatelessComponent< hasVariants: false, id: "", name: "", - productAttributes: [] as ProductCreateData_productTypes_edges_node_productAttributes[] + productAttributes: [] }); const categories = getChoices(categoryChoiceList); @@ -268,6 +270,7 @@ export const ProductCreatePage: React.StatelessComponent< errors={errors} fetchCategories={fetchCategories} fetchCollections={fetchCollections} + fetchProductTypes={fetchProductTypes} productType={productType} productTypeInputDisplayValue={productType.name} productTypes={productTypes} diff --git a/src/products/components/ProductOrganization/ProductOrganization.tsx b/src/products/components/ProductOrganization/ProductOrganization.tsx index c833cf2dc..21b3932b9 100644 --- a/src/products/components/ProductOrganization/ProductOrganization.tsx +++ b/src/products/components/ProductOrganization/ProductOrganization.tsx @@ -62,6 +62,7 @@ interface ProductOrganizationProps extends WithStyles { productTypes?: SingleAutocompleteChoiceType[]; fetchCategories: (query: string) => void; fetchCollections: (query: string) => void; + fetchProductTypes?: (data: string) => void; onCategoryChange: (event: ChangeEvent) => void; onCollectionChange: (event: ChangeEvent) => void; onProductTypeChange?: (event: ChangeEvent) => void; @@ -80,6 +81,7 @@ const ProductOrganization = withStyles(styles, { name: "ProductOrganization" })( errors, fetchCategories, fetchCollections, + fetchProductTypes, productType, productTypeInputDisplayValue, productTypes, @@ -111,6 +113,7 @@ const ProductOrganization = withStyles(styles, { name: "ProductOrganization" })( choices={productTypes} value={data.productType} onChange={onProductTypeChange} + fetchChoices={fetchProductTypes} data-tc="product-type" /> ) : ( diff --git a/src/products/queries.ts b/src/products/queries.ts index 65c5948d7..fa60db7cb 100644 --- a/src/products/queries.ts +++ b/src/products/queries.ts @@ -5,7 +5,6 @@ import { AvailableInGridAttributes, AvailableInGridAttributesVariables } from "./types/AvailableInGridAttributes"; -import { ProductCreateData } from "./types/ProductCreateData"; import { ProductDetails, ProductDetailsVariables @@ -282,35 +281,6 @@ export const TypedProductVariantQuery = TypedQuery< ProductVariantDetailsVariables >(productVariantQuery); -const productCreateQuery = gql` - query ProductCreateData { - productTypes(first: 20) { - edges { - node { - id - name - hasVariants - productAttributes { - id - inputType - slug - name - valueRequired - values { - id - name - slug - } - } - } - } - } - } -`; -export const TypedProductCreateQuery = TypedQuery( - productCreateQuery -); - const productVariantCreateQuery = gql` query ProductVariantCreateData($id: ID!) { product(id: $id) { diff --git a/src/products/types/ProductCreateData.ts b/src/products/types/ProductCreateData.ts deleted file mode 100644 index 4e6513b86..000000000 --- a/src/products/types/ProductCreateData.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// This file was automatically generated and should not be edited. - -import { AttributeInputTypeEnum } from "./../../types/globalTypes"; - -// ==================================================== -// GraphQL query operation: ProductCreateData -// ==================================================== - -export interface ProductCreateData_productTypes_edges_node_productAttributes_values { - __typename: "AttributeValue"; - id: string; - name: string | null; - slug: string | null; -} - -export interface ProductCreateData_productTypes_edges_node_productAttributes { - __typename: "Attribute"; - id: string; - inputType: AttributeInputTypeEnum | null; - slug: string | null; - name: string | null; - valueRequired: boolean; - values: (ProductCreateData_productTypes_edges_node_productAttributes_values | null)[] | null; -} - -export interface ProductCreateData_productTypes_edges_node { - __typename: "ProductType"; - id: string; - name: string; - hasVariants: boolean; - productAttributes: (ProductCreateData_productTypes_edges_node_productAttributes | null)[] | null; -} - -export interface ProductCreateData_productTypes_edges { - __typename: "ProductTypeCountableEdge"; - node: ProductCreateData_productTypes_edges_node; -} - -export interface ProductCreateData_productTypes { - __typename: "ProductTypeCountableConnection"; - edges: ProductCreateData_productTypes_edges[]; -} - -export interface ProductCreateData { - productTypes: ProductCreateData_productTypes | null; -} diff --git a/src/products/utils/data.ts b/src/products/utils/data.ts index 05cc7bad1..56d48658b 100644 --- a/src/products/utils/data.ts +++ b/src/products/utils/data.ts @@ -2,6 +2,7 @@ import { RawDraftContentState } from "draft-js"; import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; +import { SearchProductTypes_productTypes_edges_node_productAttributes } from "@saleor/containers/SearchProductTypes/types/SearchProductTypes"; import { maybe } from "@saleor/misc"; import { ProductDetails_product, @@ -11,7 +12,6 @@ import { import { UserError } from "@saleor/types"; import { ProductAttributeInput } from "../components/ProductAttributes"; import { VariantAttributeInput } from "../components/ProductVariantAttributes"; -import { ProductCreateData_productTypes_edges_node_productAttributes } from "../types/ProductCreateData"; import { ProductVariant, ProductVariant_attributes_attribute @@ -35,7 +35,7 @@ export interface ProductType { hasVariants: boolean; id: string; name: string; - productAttributes: ProductCreateData_productTypes_edges_node_productAttributes[]; + productAttributes: SearchProductTypes_productTypes_edges_node_productAttributes[]; } export function getAttributeInputFromProduct( diff --git a/src/products/views/ProductCreate.tsx b/src/products/views/ProductCreate.tsx index e3528a3b3..f9ee3af0b 100644 --- a/src/products/views/ProductCreate.tsx +++ b/src/products/views/ProductCreate.tsx @@ -2,6 +2,7 @@ import React from "react"; import { useIntl } from "react-intl"; import { WindowTitle } from "@saleor/components/WindowTitle"; +import SearchProductTypes from "@saleor/containers/SearchProductTypes"; import useNavigator from "@saleor/hooks/useNavigator"; import useNotifier from "@saleor/hooks/useNotifier"; import useShop from "@saleor/hooks/useShop"; @@ -13,7 +14,6 @@ import ProductCreatePage, { ProductCreatePageSubmitData } from "../components/ProductCreatePage"; import { TypedProductCreateMutation } from "../mutations"; -import { TypedProductCreateQuery } from "../queries"; import { ProductCreate } from "../types/ProductCreate"; import { productListUrl, productUrl } from "../urls"; @@ -37,8 +37,11 @@ export const ProductUpdate: React.StatelessComponent< {({ search: searchCategory, result: searchCategoryOpts }) => ( {({ search: searchCollection, result: searchCollectionOpts }) => ( - - {({ data, loading }) => { + + {({ + search: searchProductTypes, + result: searchProductTypesOpts + }) => { const handleSuccess = (data: ProductCreate) => { if (data.productCreate.errors.length === 0) { notify({ @@ -103,8 +106,6 @@ export const ProductUpdate: React.StatelessComponent< }); }; - const disabled = loading || productCreateDataLoading; - const formTransitionState = getMutationState( productCreateCalled, productCreateDataLoading, @@ -128,19 +129,22 @@ export const ProductUpdate: React.StatelessComponent< () => searchCollectionOpts.data.collections.edges, [] ).map(edge => edge.node)} - disabled={disabled} + disabled={productCreateDataLoading} errors={maybe( () => productCreateData.productCreate.errors, [] )} fetchCategories={searchCategory} fetchCollections={searchCollection} + fetchProductTypes={searchProductTypes} header={intl.formatMessage({ defaultMessage: "New Product", description: "page header" })} productTypes={maybe(() => - data.productTypes.edges.map(edge => edge.node) + searchProductTypesOpts.data.productTypes.edges.map( + edge => edge.node + ) )} onAttributesEdit={handleAttributesEdit} onBack={handleBack} @@ -153,7 +157,7 @@ export const ProductUpdate: React.StatelessComponent< ); }} - + )} )} diff --git a/src/storybook/stories/products/ProductCreatePage.tsx b/src/storybook/stories/products/ProductCreatePage.tsx index f7706fb9b..d5a2d81fb 100644 --- a/src/storybook/stories/products/ProductCreatePage.tsx +++ b/src/storybook/stories/products/ProductCreatePage.tsx @@ -24,6 +24,7 @@ storiesOf("Views / Products / Create product", module) collections={product.collections} fetchCategories={() => undefined} fetchCollections={() => undefined} + fetchProductTypes={() => undefined} productTypes={productTypes} categories={[product.category]} onAttributesEdit={undefined} @@ -41,6 +42,7 @@ storiesOf("Views / Products / Create product", module) collections={product.collections} fetchCategories={() => undefined} fetchCollections={() => undefined} + fetchProductTypes={() => undefined} productTypes={productTypes} categories={[product.category]} onAttributesEdit={undefined} @@ -60,6 +62,7 @@ storiesOf("Views / Products / Create product", module) collections={product.collections} fetchCategories={() => undefined} fetchCollections={() => undefined} + fetchProductTypes={() => undefined} productTypes={productTypes} categories={[product.category]} onAttributesEdit={undefined}