Merge pull request #189 from mirumee/fix/product-type-search

Fix product type selection
This commit is contained in:
Marcin Gębala 2019-09-30 14:41:04 +02:00 committed by GitHub
commit 7b0b99fbcd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 123 additions and 96 deletions

View file

@ -27,5 +27,6 @@ All notable, unreleased changes to this project will be documented in this file.
- Fix navigation - #182 by @benekex2 - Fix navigation - #182 by @benekex2
- Add testcafe tags to attributes, categories, collections and product types - #178 by @dominik-zeglen - Add testcafe tags to attributes, categories, collections and product types - #178 by @dominik-zeglen
- Fix input error style - #183 by @benekex2 - Fix input error style - #183 by @benekex2
- Fix product type selection - #189 by @dominik-zeglen
- Fix staff return link - #190 by @dominik-zeglen - Fix staff return link - #190 by @dominik-zeglen
- Allow sorting products by attribute - #180 by @dominik-zeglen - Allow sorting products by attribute - #180 by @dominik-zeglen

View file

@ -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, SearchProductTypesVariables>(
searchProductTypes
);

View file

@ -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;
}

View file

@ -1,12 +1,12 @@
import { import {
ProductCreateData_productTypes_edges_node, SearchProductTypes_productTypes_edges_node,
ProductCreateData_productTypes_edges_node_productAttributes SearchProductTypes_productTypes_edges_node_productAttributes
} from "../products/types/ProductCreateData"; } from "@saleor/containers/SearchProductTypes/types/SearchProductTypes";
import { AttributeInputTypeEnum } from "../types/globalTypes"; import { AttributeInputTypeEnum } from "../types/globalTypes";
import { ProductTypeDetails_productType } from "./types/ProductTypeDetails"; import { ProductTypeDetails_productType } from "./types/ProductTypeDetails";
import { ProductTypeList_productTypes_edges_node } from "./types/ProductTypeList"; 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: { node: {
__typename: "Attribute" as "Attribute", __typename: "Attribute" as "Attribute",
@ -469,7 +469,7 @@ export const attributes: ProductCreateData_productTypes_edges_node_productAttrib
].map(edge => edge.node); ].map(edge => edge.node);
export const productTypes: Array< export const productTypes: Array<
ProductCreateData_productTypes_edges_node & SearchProductTypes_productTypes_edges_node &
ProductTypeList_productTypes_edges_node ProductTypeList_productTypes_edges_node
> = [ > = [
{ {

View file

@ -15,6 +15,7 @@ import SeoForm from "@saleor/components/SeoForm";
import VisibilityCard from "@saleor/components/VisibilityCard"; import VisibilityCard from "@saleor/components/VisibilityCard";
import { SearchCategories_categories_edges_node } from "@saleor/containers/SearchCategories/types/SearchCategories"; import { SearchCategories_categories_edges_node } from "@saleor/containers/SearchCategories/types/SearchCategories";
import { SearchCollections_collections_edges_node } from "@saleor/containers/SearchCollections/types/SearchCollections"; 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 useDateLocalize from "@saleor/hooks/useDateLocalize";
import useFormset from "@saleor/hooks/useFormset"; import useFormset from "@saleor/hooks/useFormset";
import useStateFromProps from "@saleor/hooks/useStateFromProps"; import useStateFromProps from "@saleor/hooks/useStateFromProps";
@ -27,7 +28,6 @@ import {
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 { UserError } from "../../../types"; import { UserError } from "../../../types";
import { ProductCreateData_productTypes_edges_node_productAttributes } from "../../types/ProductCreateData";
import { import {
createAttributeChangeHandler, createAttributeChangeHandler,
createAttributeMultiChangeHandler, createAttributeMultiChangeHandler,
@ -71,12 +71,13 @@ interface ProductCreatePageProps {
id: string; id: string;
name: string; name: string;
hasVariants: boolean; hasVariants: boolean;
productAttributes: ProductCreateData_productTypes_edges_node_productAttributes[]; productAttributes: SearchProductTypes_productTypes_edges_node_productAttributes[];
}>; }>;
header: string; header: string;
saveButtonBarState: ConfirmButtonTransitionState; saveButtonBarState: ConfirmButtonTransitionState;
fetchCategories: (data: string) => void; fetchCategories: (data: string) => void;
fetchCollections: (data: string) => void; fetchCollections: (data: string) => void;
fetchProductTypes: (data: string) => void;
onAttributesEdit: () => void; onAttributesEdit: () => void;
onBack?(); onBack?();
onSubmit?(data: ProductCreatePageSubmitData); onSubmit?(data: ProductCreatePageSubmitData);
@ -96,6 +97,7 @@ export const ProductCreatePage: React.StatelessComponent<
productTypes: productTypeChoiceList, productTypes: productTypeChoiceList,
saveButtonBarState, saveButtonBarState,
onBack, onBack,
fetchProductTypes,
onSubmit onSubmit
}: ProductCreatePageProps) => { }: ProductCreatePageProps) => {
const intl = useIntl(); const intl = useIntl();
@ -139,7 +141,7 @@ export const ProductCreatePage: React.StatelessComponent<
hasVariants: false, hasVariants: false,
id: "", id: "",
name: "", name: "",
productAttributes: [] as ProductCreateData_productTypes_edges_node_productAttributes[] productAttributes: []
}); });
const categories = getChoices(categoryChoiceList); const categories = getChoices(categoryChoiceList);
@ -268,6 +270,7 @@ export const ProductCreatePage: React.StatelessComponent<
errors={errors} errors={errors}
fetchCategories={fetchCategories} fetchCategories={fetchCategories}
fetchCollections={fetchCollections} fetchCollections={fetchCollections}
fetchProductTypes={fetchProductTypes}
productType={productType} productType={productType}
productTypeInputDisplayValue={productType.name} productTypeInputDisplayValue={productType.name}
productTypes={productTypes} productTypes={productTypes}

View file

@ -62,6 +62,7 @@ interface ProductOrganizationProps extends WithStyles<typeof styles> {
productTypes?: SingleAutocompleteChoiceType[]; productTypes?: SingleAutocompleteChoiceType[];
fetchCategories: (query: string) => void; fetchCategories: (query: string) => void;
fetchCollections: (query: string) => void; fetchCollections: (query: string) => void;
fetchProductTypes?: (data: string) => void;
onCategoryChange: (event: ChangeEvent) => void; onCategoryChange: (event: ChangeEvent) => void;
onCollectionChange: (event: ChangeEvent) => void; onCollectionChange: (event: ChangeEvent) => void;
onProductTypeChange?: (event: ChangeEvent) => void; onProductTypeChange?: (event: ChangeEvent) => void;
@ -80,6 +81,7 @@ const ProductOrganization = withStyles(styles, { name: "ProductOrganization" })(
errors, errors,
fetchCategories, fetchCategories,
fetchCollections, fetchCollections,
fetchProductTypes,
productType, productType,
productTypeInputDisplayValue, productTypeInputDisplayValue,
productTypes, productTypes,
@ -111,6 +113,7 @@ const ProductOrganization = withStyles(styles, { name: "ProductOrganization" })(
choices={productTypes} choices={productTypes}
value={data.productType} value={data.productType}
onChange={onProductTypeChange} onChange={onProductTypeChange}
fetchChoices={fetchProductTypes}
data-tc="product-type" data-tc="product-type"
/> />
) : ( ) : (

View file

@ -5,7 +5,6 @@ import {
AvailableInGridAttributes, AvailableInGridAttributes,
AvailableInGridAttributesVariables AvailableInGridAttributesVariables
} from "./types/AvailableInGridAttributes"; } from "./types/AvailableInGridAttributes";
import { ProductCreateData } from "./types/ProductCreateData";
import { import {
ProductDetails, ProductDetails,
ProductDetailsVariables ProductDetailsVariables
@ -282,35 +281,6 @@ export const TypedProductVariantQuery = TypedQuery<
ProductVariantDetailsVariables ProductVariantDetailsVariables
>(productVariantQuery); >(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<ProductCreateData, {}>(
productCreateQuery
);
const productVariantCreateQuery = gql` const productVariantCreateQuery = gql`
query ProductVariantCreateData($id: ID!) { query ProductVariantCreateData($id: ID!) {
product(id: $id) { product(id: $id) {

View file

@ -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;
}

View file

@ -2,6 +2,7 @@ import { RawDraftContentState } from "draft-js";
import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField"; import { MultiAutocompleteChoiceType } from "@saleor/components/MultiAutocompleteSelectField";
import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField"; import { SingleAutocompleteChoiceType } from "@saleor/components/SingleAutocompleteSelectField";
import { SearchProductTypes_productTypes_edges_node_productAttributes } from "@saleor/containers/SearchProductTypes/types/SearchProductTypes";
import { maybe } from "@saleor/misc"; import { maybe } from "@saleor/misc";
import { import {
ProductDetails_product, ProductDetails_product,
@ -11,7 +12,6 @@ import {
import { UserError } from "@saleor/types"; import { UserError } from "@saleor/types";
import { ProductAttributeInput } from "../components/ProductAttributes"; import { ProductAttributeInput } from "../components/ProductAttributes";
import { VariantAttributeInput } from "../components/ProductVariantAttributes"; import { VariantAttributeInput } from "../components/ProductVariantAttributes";
import { ProductCreateData_productTypes_edges_node_productAttributes } from "../types/ProductCreateData";
import { import {
ProductVariant, ProductVariant,
ProductVariant_attributes_attribute ProductVariant_attributes_attribute
@ -35,7 +35,7 @@ export interface ProductType {
hasVariants: boolean; hasVariants: boolean;
id: string; id: string;
name: string; name: string;
productAttributes: ProductCreateData_productTypes_edges_node_productAttributes[]; productAttributes: SearchProductTypes_productTypes_edges_node_productAttributes[];
} }
export function getAttributeInputFromProduct( export function getAttributeInputFromProduct(

View file

@ -2,6 +2,7 @@ import React from "react";
import { useIntl } from "react-intl"; import { useIntl } from "react-intl";
import { WindowTitle } from "@saleor/components/WindowTitle"; import { WindowTitle } from "@saleor/components/WindowTitle";
import SearchProductTypes from "@saleor/containers/SearchProductTypes";
import useNavigator from "@saleor/hooks/useNavigator"; import useNavigator from "@saleor/hooks/useNavigator";
import useNotifier from "@saleor/hooks/useNotifier"; import useNotifier from "@saleor/hooks/useNotifier";
import useShop from "@saleor/hooks/useShop"; import useShop from "@saleor/hooks/useShop";
@ -13,7 +14,6 @@ import ProductCreatePage, {
ProductCreatePageSubmitData ProductCreatePageSubmitData
} from "../components/ProductCreatePage"; } from "../components/ProductCreatePage";
import { TypedProductCreateMutation } from "../mutations"; import { TypedProductCreateMutation } from "../mutations";
import { TypedProductCreateQuery } from "../queries";
import { ProductCreate } from "../types/ProductCreate"; import { ProductCreate } from "../types/ProductCreate";
import { productListUrl, productUrl } from "../urls"; import { productListUrl, productUrl } from "../urls";
@ -37,8 +37,11 @@ export const ProductUpdate: React.StatelessComponent<
{({ search: searchCategory, result: searchCategoryOpts }) => ( {({ search: searchCategory, result: searchCategoryOpts }) => (
<SearchCollections variables={DEFAULT_INITIAL_SEARCH_DATA}> <SearchCollections variables={DEFAULT_INITIAL_SEARCH_DATA}>
{({ search: searchCollection, result: searchCollectionOpts }) => ( {({ search: searchCollection, result: searchCollectionOpts }) => (
<TypedProductCreateQuery displayLoader> <SearchProductTypes variables={DEFAULT_INITIAL_SEARCH_DATA}>
{({ data, loading }) => { {({
search: searchProductTypes,
result: searchProductTypesOpts
}) => {
const handleSuccess = (data: ProductCreate) => { const handleSuccess = (data: ProductCreate) => {
if (data.productCreate.errors.length === 0) { if (data.productCreate.errors.length === 0) {
notify({ notify({
@ -103,8 +106,6 @@ export const ProductUpdate: React.StatelessComponent<
}); });
}; };
const disabled = loading || productCreateDataLoading;
const formTransitionState = getMutationState( const formTransitionState = getMutationState(
productCreateCalled, productCreateCalled,
productCreateDataLoading, productCreateDataLoading,
@ -128,19 +129,22 @@ export const ProductUpdate: React.StatelessComponent<
() => searchCollectionOpts.data.collections.edges, () => searchCollectionOpts.data.collections.edges,
[] []
).map(edge => edge.node)} ).map(edge => edge.node)}
disabled={disabled} disabled={productCreateDataLoading}
errors={maybe( errors={maybe(
() => productCreateData.productCreate.errors, () => productCreateData.productCreate.errors,
[] []
)} )}
fetchCategories={searchCategory} fetchCategories={searchCategory}
fetchCollections={searchCollection} fetchCollections={searchCollection}
fetchProductTypes={searchProductTypes}
header={intl.formatMessage({ header={intl.formatMessage({
defaultMessage: "New Product", defaultMessage: "New Product",
description: "page header" description: "page header"
})} })}
productTypes={maybe(() => productTypes={maybe(() =>
data.productTypes.edges.map(edge => edge.node) searchProductTypesOpts.data.productTypes.edges.map(
edge => edge.node
)
)} )}
onAttributesEdit={handleAttributesEdit} onAttributesEdit={handleAttributesEdit}
onBack={handleBack} onBack={handleBack}
@ -153,7 +157,7 @@ export const ProductUpdate: React.StatelessComponent<
</TypedProductCreateMutation> </TypedProductCreateMutation>
); );
}} }}
</TypedProductCreateQuery> </SearchProductTypes>
)} )}
</SearchCollections> </SearchCollections>
)} )}

View file

@ -24,6 +24,7 @@ storiesOf("Views / Products / Create product", module)
collections={product.collections} collections={product.collections}
fetchCategories={() => undefined} fetchCategories={() => undefined}
fetchCollections={() => undefined} fetchCollections={() => undefined}
fetchProductTypes={() => undefined}
productTypes={productTypes} productTypes={productTypes}
categories={[product.category]} categories={[product.category]}
onAttributesEdit={undefined} onAttributesEdit={undefined}
@ -41,6 +42,7 @@ storiesOf("Views / Products / Create product", module)
collections={product.collections} collections={product.collections}
fetchCategories={() => undefined} fetchCategories={() => undefined}
fetchCollections={() => undefined} fetchCollections={() => undefined}
fetchProductTypes={() => undefined}
productTypes={productTypes} productTypes={productTypes}
categories={[product.category]} categories={[product.category]}
onAttributesEdit={undefined} onAttributesEdit={undefined}
@ -60,6 +62,7 @@ storiesOf("Views / Products / Create product", module)
collections={product.collections} collections={product.collections}
fetchCategories={() => undefined} fetchCategories={() => undefined}
fetchCollections={() => undefined} fetchCollections={() => undefined}
fetchProductTypes={() => undefined}
productTypes={productTypes} productTypes={productTypes}
categories={[product.category]} categories={[product.category]}
onAttributesEdit={undefined} onAttributesEdit={undefined}