Procházet zdrojové kódy

feat(core): Add "enabled" field to Product & ProductVariant

Relates to #62
Michael Bromley před 6 roky
rodič
revize
a8778539d4

+ 1 - 0
packages/common/package.json

@@ -4,6 +4,7 @@
   "main": "index.js",
   "main": "index.js",
   "license": "MIT",
   "license": "MIT",
   "scripts": {
   "scripts": {
+    "watch": "tsc -p ./tsconfig.build.json -w",
     "build": "rimraf dist && tsc -p ./tsconfig.build.json"
     "build": "rimraf dist && tsc -p ./tsconfig.build.json"
   },
   },
   "publishConfig": {
   "publishConfig": {

+ 3 - 3
packages/common/src/generated-shop-types.ts

@@ -1,5 +1,5 @@
 // tslint:disable
 // tslint:disable
-// Generated in 2019-04-09T14:28:32+02:00
+// Generated in 2019-04-24T10:46:04+02:00
 export type Maybe<T> = T | null;
 export type Maybe<T> = T | null;
 
 
 export interface OrderListOptions {
 export interface OrderListOptions {
@@ -1626,9 +1626,9 @@ export interface Mutation {
     verifyCustomerAccount: LoginResult;
     verifyCustomerAccount: LoginResult;
     /** Update the password of the active Customer */
     /** Update the password of the active Customer */
     updateCustomerPassword?: Maybe<boolean>;
     updateCustomerPassword?: Maybe<boolean>;
-    /** Request to update the emailAddress of the active Customer */
+    /** Request to update the emailAddress of the active Customer. If `authOptions.requireVerification` is enabled (as is the default), then the `identifierChangeToken` will be assigned to the current User and a IdentifierChangeRequestEvent will be raised. This can then be used e.g. by the EmailPlugin to email that verification token to the Customer, which is then used to verify the change of email address. */
     requestUpdateCustomerEmailAddress?: Maybe<boolean>;
     requestUpdateCustomerEmailAddress?: Maybe<boolean>;
-    /** Confirm the update of the emailAddress with the provided token */
+    /** Confirm the update of the emailAddress with the provided token, which has been generated by the `requestUpdateCustomerEmailAddress` mutation. */
     updateCustomerEmailAddress?: Maybe<boolean>;
     updateCustomerEmailAddress?: Maybe<boolean>;
     /** Requests a password reset email to be sent */
     /** Requests a password reset email to be sent */
     requestPasswordReset?: Maybe<boolean>;
     requestPasswordReset?: Maybe<boolean>;

+ 280 - 262
packages/common/src/generated-types.ts

@@ -1,5 +1,5 @@
 // tslint:disable
 // tslint:disable
-// Generated in 2019-04-09T14:28:32+02:00
+// Generated in 2019-04-24T10:46:05+02:00
 export type Maybe<T> = T | null;
 export type Maybe<T> = T | null;
 
 
 
 
@@ -220,6 +220,8 @@ export interface ProductVariantFilterParameter {
   priceIncludesTax?: Maybe<BooleanOperators>;
   priceIncludesTax?: Maybe<BooleanOperators>;
   
   
   priceWithTax?: Maybe<NumberOperators>;
   priceWithTax?: Maybe<NumberOperators>;
+  
+  enabled?: Maybe<BooleanOperators>;
 }
 }
 
 
 export interface BooleanOperators {
 export interface BooleanOperators {
@@ -258,43 +260,6 @@ export interface CountryFilterParameter {
   enabled?: Maybe<BooleanOperators>;
   enabled?: Maybe<BooleanOperators>;
 }
 }
 
 
-export interface FacetListOptions {
-  
-  skip?: Maybe<number>;
-  
-  take?: Maybe<number>;
-  
-  sort?: Maybe<FacetSortParameter>;
-  
-  filter?: Maybe<FacetFilterParameter>;
-}
-
-export interface FacetSortParameter {
-  
-  id?: Maybe<SortOrder>;
-  
-  createdAt?: Maybe<SortOrder>;
-  
-  updatedAt?: Maybe<SortOrder>;
-  
-  name?: Maybe<SortOrder>;
-  
-  code?: Maybe<SortOrder>;
-}
-
-export interface FacetFilterParameter {
-  
-  createdAt?: Maybe<DateOperators>;
-  
-  updatedAt?: Maybe<DateOperators>;
-  
-  languageCode?: Maybe<StringOperators>;
-  
-  name?: Maybe<StringOperators>;
-  
-  code?: Maybe<StringOperators>;
-}
-
 export interface CustomerListOptions {
 export interface CustomerListOptions {
   
   
   skip?: Maybe<number>;
   skip?: Maybe<number>;
@@ -401,18 +366,18 @@ export interface OrderFilterParameter {
   total?: Maybe<NumberOperators>;
   total?: Maybe<NumberOperators>;
 }
 }
 
 
-export interface PaymentMethodListOptions {
+export interface FacetListOptions {
   
   
   skip?: Maybe<number>;
   skip?: Maybe<number>;
   
   
   take?: Maybe<number>;
   take?: Maybe<number>;
   
   
-  sort?: Maybe<PaymentMethodSortParameter>;
+  sort?: Maybe<FacetSortParameter>;
   
   
-  filter?: Maybe<PaymentMethodFilterParameter>;
+  filter?: Maybe<FacetFilterParameter>;
 }
 }
 
 
-export interface PaymentMethodSortParameter {
+export interface FacetSortParameter {
   
   
   id?: Maybe<SortOrder>;
   id?: Maybe<SortOrder>;
   
   
@@ -420,32 +385,36 @@ export interface PaymentMethodSortParameter {
   
   
   updatedAt?: Maybe<SortOrder>;
   updatedAt?: Maybe<SortOrder>;
   
   
+  name?: Maybe<SortOrder>;
+  
   code?: Maybe<SortOrder>;
   code?: Maybe<SortOrder>;
 }
 }
 
 
-export interface PaymentMethodFilterParameter {
+export interface FacetFilterParameter {
   
   
   createdAt?: Maybe<DateOperators>;
   createdAt?: Maybe<DateOperators>;
   
   
   updatedAt?: Maybe<DateOperators>;
   updatedAt?: Maybe<DateOperators>;
   
   
-  code?: Maybe<StringOperators>;
+  languageCode?: Maybe<StringOperators>;
   
   
-  enabled?: Maybe<BooleanOperators>;
+  name?: Maybe<StringOperators>;
+  
+  code?: Maybe<StringOperators>;
 }
 }
 
 
-export interface ProductListOptions {
+export interface PaymentMethodListOptions {
   
   
   skip?: Maybe<number>;
   skip?: Maybe<number>;
   
   
   take?: Maybe<number>;
   take?: Maybe<number>;
   
   
-  sort?: Maybe<ProductSortParameter>;
+  sort?: Maybe<PaymentMethodSortParameter>;
   
   
-  filter?: Maybe<ProductFilterParameter>;
+  filter?: Maybe<PaymentMethodFilterParameter>;
 }
 }
 
 
-export interface ProductSortParameter {
+export interface PaymentMethodSortParameter {
   
   
   id?: Maybe<SortOrder>;
   id?: Maybe<SortOrder>;
   
   
@@ -453,26 +422,18 @@ export interface ProductSortParameter {
   
   
   updatedAt?: Maybe<SortOrder>;
   updatedAt?: Maybe<SortOrder>;
   
   
-  name?: Maybe<SortOrder>;
-  
-  slug?: Maybe<SortOrder>;
-  
-  description?: Maybe<SortOrder>;
+  code?: Maybe<SortOrder>;
 }
 }
 
 
-export interface ProductFilterParameter {
+export interface PaymentMethodFilterParameter {
   
   
   createdAt?: Maybe<DateOperators>;
   createdAt?: Maybe<DateOperators>;
   
   
   updatedAt?: Maybe<DateOperators>;
   updatedAt?: Maybe<DateOperators>;
   
   
-  languageCode?: Maybe<StringOperators>;
-  
-  name?: Maybe<StringOperators>;
-  
-  slug?: Maybe<StringOperators>;
+  code?: Maybe<StringOperators>;
   
   
-  description?: Maybe<StringOperators>;
+  enabled?: Maybe<BooleanOperators>;
 }
 }
 
 
 export interface SearchInput {
 export interface SearchInput {
@@ -499,6 +460,49 @@ export interface SearchResultSortParameter {
   price?: Maybe<SortOrder>;
   price?: Maybe<SortOrder>;
 }
 }
 
 
+export interface ProductListOptions {
+  
+  skip?: Maybe<number>;
+  
+  take?: Maybe<number>;
+  
+  sort?: Maybe<ProductSortParameter>;
+  
+  filter?: Maybe<ProductFilterParameter>;
+}
+
+export interface ProductSortParameter {
+  
+  id?: Maybe<SortOrder>;
+  
+  createdAt?: Maybe<SortOrder>;
+  
+  updatedAt?: Maybe<SortOrder>;
+  
+  name?: Maybe<SortOrder>;
+  
+  slug?: Maybe<SortOrder>;
+  
+  description?: Maybe<SortOrder>;
+}
+
+export interface ProductFilterParameter {
+  
+  createdAt?: Maybe<DateOperators>;
+  
+  updatedAt?: Maybe<DateOperators>;
+  
+  languageCode?: Maybe<StringOperators>;
+  
+  name?: Maybe<StringOperators>;
+  
+  slug?: Maybe<StringOperators>;
+  
+  description?: Maybe<StringOperators>;
+  
+  enabled?: Maybe<BooleanOperators>;
+}
+
 export interface PromotionListOptions {
 export interface PromotionListOptions {
   
   
   skip?: Maybe<number>;
   skip?: Maybe<number>;
@@ -821,79 +825,6 @@ export interface UpdateCustomerGroupInput {
   name?: Maybe<string>;
   name?: Maybe<string>;
 }
 }
 
 
-export interface CreateFacetInput {
-  
-  code: string;
-  
-  translations: FacetTranslationInput[];
-  
-  values?: Maybe<CreateFacetValueWithFacetInput[]>;
-  
-  customFields?: Maybe<Json>;
-}
-
-export interface FacetTranslationInput {
-  
-  id?: Maybe<string>;
-  
-  languageCode: LanguageCode;
-  
-  name?: Maybe<string>;
-  
-  customFields?: Maybe<Json>;
-}
-
-export interface CreateFacetValueWithFacetInput {
-  
-  code: string;
-  
-  translations: FacetValueTranslationInput[];
-}
-
-export interface FacetValueTranslationInput {
-  
-  id?: Maybe<string>;
-  
-  languageCode: LanguageCode;
-  
-  name?: Maybe<string>;
-  
-  customFields?: Maybe<Json>;
-}
-
-export interface UpdateFacetInput {
-  
-  id: string;
-  
-  code?: Maybe<string>;
-  
-  translations?: Maybe<FacetTranslationInput[]>;
-  
-  customFields?: Maybe<Json>;
-}
-
-export interface CreateFacetValueInput {
-  
-  facetId: string;
-  
-  code: string;
-  
-  translations: FacetValueTranslationInput[];
-  
-  customFields?: Maybe<Json>;
-}
-
-export interface UpdateFacetValueInput {
-  
-  id: string;
-  
-  code?: Maybe<string>;
-  
-  translations?: Maybe<FacetValueTranslationInput[]>;
-  
-  customFields?: Maybe<Json>;
-}
-
 export interface CreateCustomerInput {
 export interface CreateCustomerInput {
   
   
   title?: Maybe<string>;
   title?: Maybe<string>;
@@ -982,6 +913,79 @@ export interface UpdateAddressInput {
   customFields?: Maybe<Json>;
   customFields?: Maybe<Json>;
 }
 }
 
 
+export interface CreateFacetInput {
+  
+  code: string;
+  
+  translations: FacetTranslationInput[];
+  
+  values?: Maybe<CreateFacetValueWithFacetInput[]>;
+  
+  customFields?: Maybe<Json>;
+}
+
+export interface FacetTranslationInput {
+  
+  id?: Maybe<string>;
+  
+  languageCode: LanguageCode;
+  
+  name?: Maybe<string>;
+  
+  customFields?: Maybe<Json>;
+}
+
+export interface CreateFacetValueWithFacetInput {
+  
+  code: string;
+  
+  translations: FacetValueTranslationInput[];
+}
+
+export interface FacetValueTranslationInput {
+  
+  id?: Maybe<string>;
+  
+  languageCode: LanguageCode;
+  
+  name?: Maybe<string>;
+  
+  customFields?: Maybe<Json>;
+}
+
+export interface UpdateFacetInput {
+  
+  id: string;
+  
+  code?: Maybe<string>;
+  
+  translations?: Maybe<FacetTranslationInput[]>;
+  
+  customFields?: Maybe<Json>;
+}
+
+export interface CreateFacetValueInput {
+  
+  facetId: string;
+  
+  code: string;
+  
+  translations: FacetValueTranslationInput[];
+  
+  customFields?: Maybe<Json>;
+}
+
+export interface UpdateFacetValueInput {
+  
+  id: string;
+  
+  code?: Maybe<string>;
+  
+  translations?: Maybe<FacetValueTranslationInput[]>;
+  
+  customFields?: Maybe<Json>;
+}
+
 export interface UpdateGlobalSettingsInput {
 export interface UpdateGlobalSettingsInput {
   
   
   availableLanguages?: Maybe<LanguageCode[]>;
   availableLanguages?: Maybe<LanguageCode[]>;
@@ -1074,6 +1078,8 @@ export interface UpdateProductInput {
   
   
   id: string;
   id: string;
   
   
+  enabled?: Maybe<boolean>;
+  
   featuredAssetId?: Maybe<string>;
   featuredAssetId?: Maybe<string>;
   
   
   assetIds?: Maybe<string[]>;
   assetIds?: Maybe<string[]>;
@@ -1089,6 +1095,8 @@ export interface UpdateProductVariantInput {
   
   
   id: string;
   id: string;
   
   
+  enabled?: Maybe<boolean>;
+  
   translations?: Maybe<ProductVariantTranslationInput[]>;
   translations?: Maybe<ProductVariantTranslationInput[]>;
   
   
   facetValueIds?: Maybe<string[]>;
   facetValueIds?: Maybe<string[]>;
@@ -2705,6 +2713,8 @@ export namespace GetProductList {
     
     
     id: string;
     id: string;
     
     
+    enabled: boolean;
+    
     languageCode: LanguageCode;
     languageCode: LanguageCode;
     
     
     name: string;
     name: string;
@@ -4125,6 +4135,8 @@ export namespace ProductWithVariants {
     
     
     id: string;
     id: string;
     
     
+    enabled: boolean;
+    
     languageCode: LanguageCode;
     languageCode: LanguageCode;
     
     
     name: string;
     name: string;
@@ -4546,13 +4558,13 @@ export interface Query {
   
   
   customerGroup?: Maybe<CustomerGroup>;
   customerGroup?: Maybe<CustomerGroup>;
   
   
-  facets: FacetList;
+  customers: CustomerList;
   
   
-  facet?: Maybe<Facet>;
+  customer?: Maybe<Customer>;
   
   
-  customers: CustomerList;
+  facets: FacetList;
   
   
-  customer?: Maybe<Customer>;
+  facet?: Maybe<Facet>;
   
   
   globalSettings: GlobalSettings;
   globalSettings: GlobalSettings;
   
   
@@ -4568,12 +4580,12 @@ export interface Query {
   
   
   productOptionGroup?: Maybe<ProductOptionGroup>;
   productOptionGroup?: Maybe<ProductOptionGroup>;
   
   
+  search: SearchResponse;
+  
   products: ProductList;
   products: ProductList;
   
   
   product?: Maybe<Product>;
   product?: Maybe<Product>;
   
   
-  search: SearchResponse;
-  
   promotion?: Maybe<Promotion>;
   promotion?: Maybe<Promotion>;
   
   
   promotions: PromotionList;
   promotions: PromotionList;
@@ -4916,6 +4928,8 @@ export interface ProductVariant extends Node {
   
   
   translations: ProductVariantTranslation[];
   translations: ProductVariantTranslation[];
   
   
+  enabled: boolean;
+  
   customFields?: Maybe<Json>;
   customFields?: Maybe<Json>;
 }
 }
 
 
@@ -5094,14 +5108,6 @@ export interface CountryList extends PaginatedList {
 }
 }
 
 
 
 
-export interface FacetList extends PaginatedList {
-  
-  items: Facet[];
-  
-  totalItems: number;
-}
-
-
 export interface CustomerList extends PaginatedList {
 export interface CustomerList extends PaginatedList {
   
   
   items: Customer[];
   items: Customer[];
@@ -5344,6 +5350,14 @@ export interface ShippingMethod extends Node {
 }
 }
 
 
 
 
+export interface FacetList extends PaginatedList {
+  
+  items: Facet[];
+  
+  totalItems: number;
+}
+
+
 export interface GlobalSettings {
 export interface GlobalSettings {
   
   
   id: string;
   id: string;
@@ -5426,66 +5440,6 @@ export interface ProductOptionGroupTranslation {
 }
 }
 
 
 
 
-export interface ProductList extends PaginatedList {
-  
-  items: Product[];
-  
-  totalItems: number;
-}
-
-
-export interface Product extends Node {
-  
-  id: string;
-  
-  createdAt: DateTime;
-  
-  updatedAt: DateTime;
-  
-  languageCode: LanguageCode;
-  
-  name: string;
-  
-  slug: string;
-  
-  description: string;
-  
-  featuredAsset?: Maybe<Asset>;
-  
-  assets: Asset[];
-  
-  variants: ProductVariant[];
-  
-  optionGroups: ProductOptionGroup[];
-  
-  facetValues: FacetValue[];
-  
-  translations: ProductTranslation[];
-  
-  collections: Collection[];
-  
-  customFields?: Maybe<Json>;
-}
-
-
-export interface ProductTranslation {
-  
-  id: string;
-  
-  createdAt: DateTime;
-  
-  updatedAt: DateTime;
-  
-  languageCode: LanguageCode;
-  
-  name: string;
-  
-  slug: string;
-  
-  description: string;
-}
-
-
 export interface SearchResponse {
 export interface SearchResponse {
   
   
   items: SearchResult[];
   items: SearchResult[];
@@ -5529,6 +5483,8 @@ export interface SearchResult {
   collectionIds: string[];
   collectionIds: string[];
   /** A relevence score for the result. Differs between database implementations */
   /** A relevence score for the result. Differs between database implementations */
   score: number;
   score: number;
+  
+  enabled: boolean;
 }
 }
 
 
 /** The price range where the result has more than one price */
 /** The price range where the result has more than one price */
@@ -5554,6 +5510,68 @@ export interface FacetValueResult {
 }
 }
 
 
 
 
+export interface ProductList extends PaginatedList {
+  
+  items: Product[];
+  
+  totalItems: number;
+}
+
+
+export interface Product extends Node {
+  
+  id: string;
+  
+  createdAt: DateTime;
+  
+  updatedAt: DateTime;
+  
+  languageCode: LanguageCode;
+  
+  name: string;
+  
+  slug: string;
+  
+  description: string;
+  
+  featuredAsset?: Maybe<Asset>;
+  
+  assets: Asset[];
+  
+  variants: ProductVariant[];
+  
+  optionGroups: ProductOptionGroup[];
+  
+  facetValues: FacetValue[];
+  
+  translations: ProductTranslation[];
+  
+  collections: Collection[];
+  
+  enabled: boolean;
+  
+  customFields?: Maybe<Json>;
+}
+
+
+export interface ProductTranslation {
+  
+  id: string;
+  
+  createdAt: DateTime;
+  
+  updatedAt: DateTime;
+  
+  languageCode: LanguageCode;
+  
+  name: string;
+  
+  slug: string;
+  
+  description: string;
+}
+
+
 export interface Promotion extends Node {
 export interface Promotion extends Node {
   
   
   id: string;
   id: string;
@@ -5671,18 +5689,6 @@ export interface Mutation {
   addCustomersToGroup: CustomerGroup;
   addCustomersToGroup: CustomerGroup;
   /** Remove Customers from a CustomerGroup */
   /** Remove Customers from a CustomerGroup */
   removeCustomersFromGroup: CustomerGroup;
   removeCustomersFromGroup: CustomerGroup;
-  /** Create a new Facet */
-  createFacet: Facet;
-  /** Update an existing Facet */
-  updateFacet: Facet;
-  /** Delete an existing Facet */
-  deleteFacet: DeletionResponse;
-  /** Create one or more FacetValues */
-  createFacetValues: FacetValue[];
-  /** Update one or more FacetValues */
-  updateFacetValues: FacetValue[];
-  /** Delete one or more FacetValues */
-  deleteFacetValues: DeletionResponse[];
   /** Create a new Customer. If a password is provided, a new User will also be created an linked to the Customer. */
   /** Create a new Customer. If a password is provided, a new User will also be created an linked to the Customer. */
   createCustomer: Customer;
   createCustomer: Customer;
   /** Update an existing Customer */
   /** Update an existing Customer */
@@ -5695,6 +5701,18 @@ export interface Mutation {
   updateCustomerAddress: Address;
   updateCustomerAddress: Address;
   /** Update an existing Address */
   /** Update an existing Address */
   deleteCustomerAddress: boolean;
   deleteCustomerAddress: boolean;
+  /** Create a new Facet */
+  createFacet: Facet;
+  /** Update an existing Facet */
+  updateFacet: Facet;
+  /** Delete an existing Facet */
+  deleteFacet: DeletionResponse;
+  /** Create one or more FacetValues */
+  createFacetValues: FacetValue[];
+  /** Update one or more FacetValues */
+  updateFacetValues: FacetValue[];
+  /** Delete one or more FacetValues */
+  deleteFacetValues: DeletionResponse[];
   
   
   updateGlobalSettings: GlobalSettings;
   updateGlobalSettings: GlobalSettings;
   
   
@@ -5705,6 +5723,8 @@ export interface Mutation {
   createProductOptionGroup: ProductOptionGroup;
   createProductOptionGroup: ProductOptionGroup;
   /** Update an existing ProductOptionGroup */
   /** Update an existing ProductOptionGroup */
   updateProductOptionGroup: ProductOptionGroup;
   updateProductOptionGroup: ProductOptionGroup;
+  
+  reindex: SearchReindexResponse;
   /** Create a new Product */
   /** Create a new Product */
   createProduct: Product;
   createProduct: Product;
   /** Update an existing Product */
   /** Update an existing Product */
@@ -5720,8 +5740,6 @@ export interface Mutation {
   /** Update existing ProductVariants */
   /** Update existing ProductVariants */
   updateProductVariants: (Maybe<ProductVariant>)[];
   updateProductVariants: (Maybe<ProductVariant>)[];
   
   
-  reindex: SearchReindexResponse;
-  
   createPromotion: Promotion;
   createPromotion: Promotion;
   
   
   updatePromotion: Promotion;
   updatePromotion: Promotion;
@@ -5859,6 +5877,14 @@ export interface CustomerGroupQueryArgs {
   
   
   id: string;
   id: string;
 }
 }
+export interface CustomersQueryArgs {
+  
+  options?: Maybe<CustomerListOptions>;
+}
+export interface CustomerQueryArgs {
+  
+  id: string;
+}
 export interface FacetsQueryArgs {
 export interface FacetsQueryArgs {
   
   
   languageCode?: Maybe<LanguageCode>;
   languageCode?: Maybe<LanguageCode>;
@@ -5871,14 +5897,6 @@ export interface FacetQueryArgs {
   
   
   languageCode?: Maybe<LanguageCode>;
   languageCode?: Maybe<LanguageCode>;
 }
 }
-export interface CustomersQueryArgs {
-  
-  options?: Maybe<CustomerListOptions>;
-}
-export interface CustomerQueryArgs {
-  
-  id: string;
-}
 export interface OrderQueryArgs {
 export interface OrderQueryArgs {
   
   
   id: string;
   id: string;
@@ -5907,6 +5925,10 @@ export interface ProductOptionGroupQueryArgs {
   
   
   languageCode?: Maybe<LanguageCode>;
   languageCode?: Maybe<LanguageCode>;
 }
 }
+export interface SearchQueryArgs {
+  
+  input: SearchInput;
+}
 export interface ProductsQueryArgs {
 export interface ProductsQueryArgs {
   
   
   languageCode?: Maybe<LanguageCode>;
   languageCode?: Maybe<LanguageCode>;
@@ -5919,10 +5941,6 @@ export interface ProductQueryArgs {
   
   
   languageCode?: Maybe<LanguageCode>;
   languageCode?: Maybe<LanguageCode>;
 }
 }
-export interface SearchQueryArgs {
-  
-  input: SearchInput;
-}
 export interface PromotionQueryArgs {
 export interface PromotionQueryArgs {
   
   
   id: string;
   id: string;
@@ -6049,34 +6067,6 @@ export interface RemoveCustomersFromGroupMutationArgs {
   
   
   customerIds: string[];
   customerIds: string[];
 }
 }
-export interface CreateFacetMutationArgs {
-  
-  input: CreateFacetInput;
-}
-export interface UpdateFacetMutationArgs {
-  
-  input: UpdateFacetInput;
-}
-export interface DeleteFacetMutationArgs {
-  
-  id: string;
-  
-  force?: Maybe<boolean>;
-}
-export interface CreateFacetValuesMutationArgs {
-  
-  input: CreateFacetValueInput[];
-}
-export interface UpdateFacetValuesMutationArgs {
-  
-  input: UpdateFacetValueInput[];
-}
-export interface DeleteFacetValuesMutationArgs {
-  
-  ids: string[];
-  
-  force?: Maybe<boolean>;
-}
 export interface CreateCustomerMutationArgs {
 export interface CreateCustomerMutationArgs {
   
   
   input: CreateCustomerInput;
   input: CreateCustomerInput;
@@ -6105,6 +6095,34 @@ export interface DeleteCustomerAddressMutationArgs {
   
   
   id: string;
   id: string;
 }
 }
+export interface CreateFacetMutationArgs {
+  
+  input: CreateFacetInput;
+}
+export interface UpdateFacetMutationArgs {
+  
+  input: UpdateFacetInput;
+}
+export interface DeleteFacetMutationArgs {
+  
+  id: string;
+  
+  force?: Maybe<boolean>;
+}
+export interface CreateFacetValuesMutationArgs {
+  
+  input: CreateFacetValueInput[];
+}
+export interface UpdateFacetValuesMutationArgs {
+  
+  input: UpdateFacetValueInput[];
+}
+export interface DeleteFacetValuesMutationArgs {
+  
+  ids: string[];
+  
+  force?: Maybe<boolean>;
+}
 export interface UpdateGlobalSettingsMutationArgs {
 export interface UpdateGlobalSettingsMutationArgs {
   
   
   input: UpdateGlobalSettingsInput;
   input: UpdateGlobalSettingsInput;

+ 203 - 0
packages/core/e2e/shop-catalog.e2e-spec.ts

@@ -0,0 +1,203 @@
+/* tslint:disable:no-non-null-assertion */
+import gql from 'graphql-tag';
+import path from 'path';
+
+import { CREATE_COLLECTION } from '../../../admin-ui/src/app/data/definitions/collection-definitions';
+import { GET_PRODUCT_WITH_VARIANTS, UPDATE_PRODUCT_VARIANTS } from '../../../admin-ui/src/app/data/definitions/product-definitions';
+import { ConfigArgType, CreateCollection, LanguageCode } from '../../common/lib/generated-types';
+import { GetProductWithVariants, UpdateProductVariants } from '../../common/src/generated-types';
+import { facetValueCollectionFilter } from '../src/config/collection/default-collection-filters';
+
+import { TEST_SETUP_TIMEOUT_MS } from './config/test-config';
+import { TestAdminClient, TestShopClient } from './test-client';
+import { TestServer } from './test-server';
+
+describe('Shop catalog', () => {
+    const shopClient = new TestShopClient();
+    const adminClient = new TestAdminClient();
+    const server = new TestServer();
+
+    beforeAll(async () => {
+        const token = await server.init({
+            productsCsvPath: path.join(__dirname, 'fixtures/e2e-products-full.csv'),
+            customerCount: 1,
+        });
+        await shopClient.init();
+        await adminClient.init();
+    }, TEST_SETUP_TIMEOUT_MS);
+
+    afterAll(async () => {
+        await server.destroy();
+    });
+
+    describe('products', () => {
+
+        beforeAll(async () => {
+            // disable the first product
+            await adminClient.query(DISABLE_PRODUCT, { id: 'T_1' });
+
+            const monitorProduct = await adminClient
+                .query<GetProductWithVariants.Query, GetProductWithVariants.Variables>(GET_PRODUCT_WITH_VARIANTS, {
+                    id: 'T_2',
+                });
+            if (monitorProduct.product) {
+                await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(UPDATE_PRODUCT_VARIANTS, {
+                    input: [
+                        {
+                            id: monitorProduct.product.variants[0].id,
+                            enabled: false,
+                        },
+                    ],
+                });
+            }
+        });
+
+        it('products list omits disabled products', async () => {
+            const result = await shopClient.query(gql`{
+                products(options: { take: 3 }) {
+                    items { id }
+                }
+            }`);
+
+            expect(result.products.items.map((item: any) => item.id)).toEqual([ 'T_2', 'T_3', 'T_4']);
+        });
+
+        it('product returns null for disabled product', async () => {
+            const result = await shopClient.query(gql`{
+                product(id: "T_1") { id }
+            }`);
+
+            expect(result.product).toBeNull();
+        });
+
+        it('omits disabled variants from product response', async () => {
+            const result = await shopClient.query(gql`{
+                product(id: "T_2") {
+                    id
+                    variants {
+                        id
+                        name
+                    }
+                }
+            }`);
+
+            expect(result.product.variants).toEqual([
+                { id: 'T_6', name: 'Curvy Monitor 27 inch'},
+            ]);
+        });
+    });
+
+    describe('collections', () => {
+
+        let collection: CreateCollection.CreateCollection;
+
+        beforeAll(async () => {
+            const result = await adminClient.query(gql`{
+                facets {
+                    items {
+                        id
+                        name
+                        values {
+                            id
+                        }
+                    }
+                }
+            }`);
+            const category = result.facets.items[0];
+            const { createCollection } = await adminClient.query<CreateCollection.Mutation, CreateCollection.Variables>(
+                CREATE_COLLECTION,
+                {
+                    input: {
+                        filters: [
+                            {
+                                code: facetValueCollectionFilter.code,
+                                arguments: [
+                                    {
+                                        name: 'facetValueIds',
+                                        value: `["${category.values[3].id}"]`,
+                                        type: ConfigArgType.FACET_VALUE_IDS,
+                                    },
+                                ],
+                            },
+                        ],
+                        translations: [
+                            { languageCode: LanguageCode.en, name: 'My Collection', description: '' },
+                        ],
+                    },
+                },
+            );
+            collection = createCollection;
+        });
+
+        it('returns collection with variants', async () => {
+            const result = await shopClient.query(GET_COLLECTION_VARIANTS, { id: collection.id });
+            expect(result.collection.productVariants.items).toEqual([
+                { id: 'T_22', name: 'Road Bike' },
+                { id: 'T_23', name: 'Skipping Rope' },
+                { id: 'T_24', name: 'Boxing Gloves' },
+                { id: 'T_25', name: 'Tent' },
+                { id: 'T_26', name: 'Cruiser Skateboard' },
+                { id: 'T_27', name: 'Football' },
+                { id: 'T_28', name: 'Running Shoe Size 40' },
+                { id: 'T_29', name: 'Running Shoe Size 42' },
+                { id: 'T_30', name: 'Running Shoe Size 44' },
+                { id: 'T_31', name: 'Running Shoe Size 46' },
+            ]);
+        });
+
+        it('omits variants from disabled products', async () => {
+            await adminClient.query(DISABLE_PRODUCT, { id: 'T_17' });
+
+            const result = await shopClient.query(GET_COLLECTION_VARIANTS, { id: collection.id });
+            expect(result.collection.productVariants.items).toEqual([
+                { id: 'T_22', name: 'Road Bike' },
+                { id: 'T_23', name: 'Skipping Rope' },
+                { id: 'T_24', name: 'Boxing Gloves' },
+                { id: 'T_25', name: 'Tent' },
+                { id: 'T_26', name: 'Cruiser Skateboard' },
+                { id: 'T_27', name: 'Football' },
+            ]);
+        });
+
+        it('omits variants from disabled products', async () => {
+            await adminClient.query<UpdateProductVariants.Mutation, UpdateProductVariants.Variables>(UPDATE_PRODUCT_VARIANTS, {
+                input: [
+                    { id: 'T_22', enabled: false },
+                ],
+            });
+
+            const result = await shopClient.query(GET_COLLECTION_VARIANTS, { id: collection.id });
+            expect(result.collection.productVariants.items).toEqual([
+                { id: 'T_23', name: 'Skipping Rope' },
+                { id: 'T_24', name: 'Boxing Gloves' },
+                { id: 'T_25', name: 'Tent' },
+                { id: 'T_26', name: 'Cruiser Skateboard' },
+                { id: 'T_27', name: 'Football' },
+            ]);
+        });
+    });
+});
+
+const DISABLE_PRODUCT = gql`
+    mutation DisableProduct($id: ID!) {
+        updateProduct(input: {
+            id: $id
+            enabled: false
+        }) {
+            id
+        }
+    }
+`;
+
+const GET_COLLECTION_VARIANTS = gql`
+    query GetCollectionVariants($id: ID!) {
+        collection(id: $id) {
+            productVariants {
+                items {
+                    id
+                    name
+                }
+            }
+        }
+    }
+`;

+ 17 - 0
packages/core/src/api/decorators/api.decorator.ts

@@ -0,0 +1,17 @@
+import { createParamDecorator } from '@nestjs/common';
+import { GraphQLResolveInfo } from 'graphql';
+
+export type ApiType = 'admin' | 'shop';
+
+/**
+ * Resolver param decorator which returns which Api the request came though.
+ * This is useful because sometimes the same resolver will have different behaviour
+ * depending whether it is being called from the shop API or the admin API.
+ */
+export const Api = createParamDecorator((data, [root, args, ctx, info]) => {
+    const query = (info as GraphQLResolveInfo).schema.getQueryType();
+    if (query) {
+        return !!query.getFields().administrators ? 'admin' : 'shop';
+    }
+    return 'shop';
+});

+ 15 - 2
packages/core/src/api/resolvers/entity/collection-entity.resolver.ts

@@ -2,11 +2,13 @@ import { Args, Parent, ResolveProperty, Resolver } from '@nestjs/graphql';
 import { CollectionBreadcrumb, ProductVariantListOptions } from '@vendure/common/lib/generated-types';
 import { CollectionBreadcrumb, ProductVariantListOptions } from '@vendure/common/lib/generated-types';
 import { PaginatedList } from '@vendure/common/lib/shared-types';
 import { PaginatedList } from '@vendure/common/lib/shared-types';
 
 
+import { ListQueryOptions } from '../../../common/types/common-types';
 import { Translated } from '../../../common/types/locale-types';
 import { Translated } from '../../../common/types/locale-types';
-import { Collection, ProductVariant } from '../../../entity';
+import { Collection, Product, ProductVariant } from '../../../entity';
 import { CollectionService } from '../../../service/services/collection.service';
 import { CollectionService } from '../../../service/services/collection.service';
 import { ProductVariantService } from '../../../service/services/product-variant.service';
 import { ProductVariantService } from '../../../service/services/product-variant.service';
 import { RequestContext } from '../../common/request-context';
 import { RequestContext } from '../../common/request-context';
+import { Api, ApiType } from '../../decorators/api.decorator';
 import { Ctx } from '../../decorators/request-context.decorator';
 import { Ctx } from '../../decorators/request-context.decorator';
 
 
 @Resolver('Collection')
 @Resolver('Collection')
@@ -21,8 +23,19 @@ export class CollectionEntityResolver {
         @Ctx() ctx: RequestContext,
         @Ctx() ctx: RequestContext,
         @Parent() collection: Collection,
         @Parent() collection: Collection,
         @Args() args: { options: ProductVariantListOptions },
         @Args() args: { options: ProductVariantListOptions },
+        @Api() apiType: ApiType,
     ): Promise<PaginatedList<Translated<ProductVariant>>> {
     ): Promise<PaginatedList<Translated<ProductVariant>>> {
-        return this.productVariantService.getVariantsByCollectionId(ctx, collection.id, args.options);
+        let options: ListQueryOptions<Product> = args.options;
+        if (apiType === 'shop') {
+            options = {
+                ...args.options,
+                filter: {
+                    ...(args.options ? args.options.filter : {}),
+                    enabled: { eq: true },
+                },
+            };
+        }
+        return this.productVariantService.getVariantsByCollectionId(ctx, collection.id, options);
     }
     }
 
 
     @ResolveProperty()
     @ResolveProperty()

+ 6 - 1
packages/core/src/api/resolvers/entity/product-entity.resolver.ts

@@ -7,6 +7,7 @@ import { Product } from '../../../entity/product/product.entity';
 import { CollectionService } from '../../../service/services/collection.service';
 import { CollectionService } from '../../../service/services/collection.service';
 import { ProductVariantService } from '../../../service/services/product-variant.service';
 import { ProductVariantService } from '../../../service/services/product-variant.service';
 import { RequestContext } from '../../common/request-context';
 import { RequestContext } from '../../common/request-context';
+import { Api, ApiType } from '../../decorators/api.decorator';
 import { Ctx } from '../../decorators/request-context.decorator';
 import { Ctx } from '../../decorators/request-context.decorator';
 
 
 @Resolver('Product')
 @Resolver('Product')
@@ -20,8 +21,12 @@ export class ProductEntityResolver {
     async variants(
     async variants(
         @Ctx() ctx: RequestContext,
         @Ctx() ctx: RequestContext,
         @Parent() product: Product,
         @Parent() product: Product,
+        @Api() apiType: ApiType,
     ): Promise<Array<Translated<ProductVariant>>> {
     ): Promise<Array<Translated<ProductVariant>>> {
-        return this.productVariantService.getVariantsByProductId(ctx, product.id);
+        // In the shop URL, the parent (Product type) does not have the "enabled"
+        // field, in which case we should filter out any non-enabled variants too.
+        const variants = await this.productVariantService.getVariantsByProductId(ctx, product.id);
+        return variants.filter(v => apiType === 'admin' ? true : v.enabled);
     }
     }
 
 
     @ResolveProperty()
     @ResolveProperty()

+ 23 - 2
packages/core/src/api/resolvers/shop/shop-products.resolver.ts

@@ -10,6 +10,7 @@ import { Omit } from '@vendure/common/lib/omit';
 import { PaginatedList } from '@vendure/common/lib/shared-types';
 import { PaginatedList } from '@vendure/common/lib/shared-types';
 
 
 import { InternalServerError } from '../../../common/error/errors';
 import { InternalServerError } from '../../../common/error/errors';
+import { ListQueryOptions } from '../../../common/types/common-types';
 import { Translated } from '../../../common/types/locale-types';
 import { Translated } from '../../../common/types/locale-types';
 import { Collection } from '../../../entity/collection/collection.entity';
 import { Collection } from '../../../entity/collection/collection.entity';
 import { Product } from '../../../entity/product/product.entity';
 import { Product } from '../../../entity/product/product.entity';
@@ -34,7 +35,20 @@ export class ShopProductsResolver {
         @Ctx() ctx: RequestContext,
         @Ctx() ctx: RequestContext,
         @Args() args: ProductsQueryArgs,
         @Args() args: ProductsQueryArgs,
     ): Promise<PaginatedList<Translated<Product>>> {
     ): Promise<PaginatedList<Translated<Product>>> {
-        return this.productService.findAll(ctx, args.options || undefined);
+
+        let options: ListQueryOptions<Product>;
+        if (args.options) {
+            options = {
+                ...args.options,
+                filter: {
+                    ...args.options.filter,
+                    enabled: { eq: true },
+                },
+            };
+        } else {
+            options = {};
+        }
+        return this.productService.findAll(ctx, options);
     }
     }
 
 
     @Query()
     @Query()
@@ -42,7 +56,14 @@ export class ShopProductsResolver {
         @Ctx() ctx: RequestContext,
         @Ctx() ctx: RequestContext,
         @Args() args: ProductQueryArgs,
         @Args() args: ProductQueryArgs,
     ): Promise<Translated<Product> | undefined> {
     ): Promise<Translated<Product> | undefined> {
-        return this.productService.findOne(ctx, args.id);
+        const result = await this.productService.findOne(ctx, args.id);
+        if (!result) {
+            return;
+        }
+        if (result.enabled === false) {
+            return;
+        }
+        return result;
     }
     }
 
 
     @Query()
     @Query()

+ 4 - 0
packages/core/src/api/schema/admin-api/product-search.api.graphql

@@ -5,3 +5,7 @@ type Query {
 type Mutation {
 type Mutation {
     reindex: SearchReindexResponse!
     reindex: SearchReindexResponse!
 }
 }
+
+type SearchResult {
+    enabled: Boolean!
+}

+ 10 - 0
packages/core/src/api/schema/admin-api/product.api.graphql

@@ -26,6 +26,14 @@ type Mutation {
     updateProductVariants(input: [UpdateProductVariantInput!]!): [ProductVariant]!
     updateProductVariants(input: [UpdateProductVariantInput!]!): [ProductVariant]!
 }
 }
 
 
+type Product {
+    enabled: Boolean!
+}
+
+type ProductVariant {
+    enabled: Boolean!
+}
+
 # generated by generateListOptions function
 # generated by generateListOptions function
 input ProductListOptions
 input ProductListOptions
 
 
@@ -46,6 +54,7 @@ input CreateProductInput {
 
 
 input UpdateProductInput {
 input UpdateProductInput {
     id: ID!
     id: ID!
+    enabled: Boolean
     featuredAssetId: ID
     featuredAssetId: ID
     assetIds: [ID!]
     assetIds: [ID!]
     facetValueIds: [ID!]
     facetValueIds: [ID!]
@@ -71,6 +80,7 @@ input CreateProductVariantInput {
 
 
 input UpdateProductVariantInput {
 input UpdateProductVariantInput {
     id: ID!
     id: ID!
+    enabled: Boolean
     translations: [ProductVariantTranslationInput!]
     translations: [ProductVariantTranslationInput!]
     facetValueIds: [ID!]
     facetValueIds: [ID!]
     sku: String
     sku: String

+ 5 - 1
packages/core/src/entity/product-variant/product-variant.entity.ts

@@ -33,7 +33,11 @@ export class ProductVariant extends VendureEntity implements Translatable, HasCu
 
 
     name: LocaleString;
     name: LocaleString;
 
 
-    @Column() sku: string;
+    @Column({ default: true })
+    enabled: boolean;
+
+    @Column()
+    sku: string;
 
 
     /**
     /**
      * A synthetic property which is populated with data from a ProductVariantPrice entity.
      * A synthetic property which is populated with data from a ProductVariantPrice entity.

+ 3 - 0
packages/core/src/entity/product/product.entity.ts

@@ -36,6 +36,9 @@ export class Product extends VendureEntity
 
 
     description: LocaleString;
     description: LocaleString;
 
 
+    @Column({ default: true })
+    enabled: boolean;
+
     @ManyToOne(type => Asset)
     @ManyToOne(type => Asset)
     featuredAsset: Asset;
     featuredAsset: Asset;
 
 

+ 9 - 3
packages/core/src/service/services/product-variant.service.ts

@@ -93,14 +93,20 @@ export class ProductVariantService {
         collectionId: ID,
         collectionId: ID,
         options: ListQueryOptions<ProductVariant>,
         options: ListQueryOptions<ProductVariant>,
     ): Promise<PaginatedList<Translated<ProductVariant>>> {
     ): Promise<PaginatedList<Translated<ProductVariant>>> {
-        return this.listQueryBuilder
+        const qb = this.listQueryBuilder
             .build(ProductVariant, options, {
             .build(ProductVariant, options, {
                 relations: ['taxCategory'],
                 relations: ['taxCategory'],
                 channelId: ctx.channelId,
                 channelId: ctx.channelId,
             })
             })
             .leftJoin('productvariant.collections', 'collection')
             .leftJoin('productvariant.collections', 'collection')
-            .andWhere('collection.id = :collectionId', { collectionId })
-            .getManyAndCount()
+            .andWhere('collection.id = :collectionId', { collectionId });
+
+        if (options.filter && options.filter.enabled && options.filter.enabled.eq === true) {
+            qb.leftJoin('productvariant.product', 'product')
+                .andWhere('product.enabled = :enabled', { enabled: true });
+        }
+
+        return qb.getManyAndCount()
             .then(async ([variants, totalItems]) => {
             .then(async ([variants, totalItems]) => {
                 const items = variants.map(variant => {
                 const items = variants.map(variant => {
                     const variantWithPrices = this.applyChannelPriceAndTax(variant, ctx);
                     const variantWithPrices = this.applyChannelPriceAndTax(variant, ctx);

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
schema-admin.json


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 0 - 0
schema-shop.json


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 420 - 453
schema.json


Některé soubory nejsou zobrazeny, neboť je v těchto rozdílových datech změněno mnoho souborů