Browse Source

feat(admin-ui): Reindex search index from product list

Michael Bromley 6 years ago
parent
commit
de7f22d641

+ 10 - 1
admin-ui/src/app/catalog/components/product-list/product-list.component.html

@@ -7,6 +7,16 @@
                 (searchTermChange)="setSearchTerm($event)"
                 (searchTermChange)="setSearchTerm($event)"
                 (facetValueChange)="setFacetValueIds($event)"
                 (facetValueChange)="setFacetValueIds($event)"
             ></vdr-product-search-input>
             ></vdr-product-search-input>
+            <clr-dropdown class="search-settings-menu">
+                <button type="button" clrDropdownTrigger>
+                    <clr-icon shape="cog"></clr-icon>
+                </button>
+                <clr-dropdown-menu *clrIfOpen clrPosition="bottom-right">
+                    <button type="button" clrDropdownItem (click)="rebuildSearchIndex()">
+                        {{ 'catalog.rebuild-search-index' | translate }}
+                    </button>
+                </clr-dropdown-menu>
+            </clr-dropdown>
         </div>
         </div>
         <clr-checkbox-wrapper>
         <clr-checkbox-wrapper>
             <input type="checkbox" clrCheckbox [(ngModel)]="groupByProduct" />
             <input type="checkbox" clrCheckbox [(ngModel)]="groupByProduct" />
@@ -17,7 +27,6 @@
         <a class="btn btn-primary" [routerLink]="['./create']">
         <a class="btn btn-primary" [routerLink]="['./create']">
             <clr-icon shape="plus"></clr-icon>
             <clr-icon shape="plus"></clr-icon>
             <span class="full-label">{{ 'catalog.create-new-product' | translate }}</span>
             <span class="full-label">{{ 'catalog.create-new-product' | translate }}</span>
-            <span class="compact-label">{{ 'common.create' | translate }}</span>
         </a>
         </a>
     </vdr-ab-right>
     </vdr-ab-right>
 </vdr-action-bar>
 </vdr-action-bar>

+ 3 - 0
admin-ui/src/app/catalog/components/product-list/product-list.component.scss

@@ -21,3 +21,6 @@
         min-width: 100px;
         min-width: 100px;
     }
     }
 }
 }
+.search-settings-menu {
+    margin: 0 12px;
+}

+ 15 - 0
admin-ui/src/app/catalog/components/product-list/product-list.component.ts

@@ -89,6 +89,21 @@ export class ProductListComponent
         this.refresh();
         this.refresh();
     }
     }
 
 
+    rebuildSearchIndex() {
+        this.dataService.product.reindex().subscribe(({ reindex }) => {
+            if (reindex.success) {
+                const time = new Intl.NumberFormat().format(reindex.timeTaken);
+                this.notificationService.success(_('catalog.reindex-successful'), {
+                    count: reindex.indexedItemCount,
+                    time,
+                });
+                this.refresh();
+            } else {
+                this.notificationService.error(_('catalog.reindex-error'));
+            }
+        });
+    }
+
     deleteProduct(productId: string) {
     deleteProduct(productId: string) {
         this.modalService
         this.modalService
             .dialog({
             .dialog({

+ 0 - 1
admin-ui/src/app/catalog/components/product-search-input/product-search-input.component.scss

@@ -4,7 +4,6 @@
     margin-top: 6px;
     margin-top: 6px;
     display: block;
     display: block;
     width: 100%;
     width: 100%;
-    margin-right: 24px;
 
 
     ::ng-deep {
     ::ng-deep {
 
 

+ 135 - 124
admin-ui/src/app/common/generated-types.ts

@@ -1412,26 +1412,26 @@ export type Mutation = {
   updateAdministrator: Administrator,
   updateAdministrator: Administrator,
   /** Assign a Role to an Administrator */
   /** Assign a Role to an Administrator */
   assignRoleToAdministrator: Administrator,
   assignRoleToAdministrator: Administrator,
-  login: LoginResult,
-  logout: Scalars['Boolean'],
   /** Create a new Asset */
   /** Create a new Asset */
   createAssets: Array<Asset>,
   createAssets: Array<Asset>,
+  login: LoginResult,
+  logout: Scalars['Boolean'],
   /** Create a new Channel */
   /** Create a new Channel */
   createChannel: Channel,
   createChannel: Channel,
   /** Update an existing Channel */
   /** Update an existing Channel */
   updateChannel: Channel,
   updateChannel: Channel,
-  /** Create a new Country */
-  createCountry: Country,
-  /** Update an existing Country */
-  updateCountry: Country,
-  /** Delete a Country */
-  deleteCountry: DeletionResponse,
   /** Create a new Collection */
   /** Create a new Collection */
   createCollection: Collection,
   createCollection: Collection,
   /** Update an existing Collection */
   /** Update an existing Collection */
   updateCollection: Collection,
   updateCollection: Collection,
   /** Move a Collection to a different parent or index */
   /** Move a Collection to a different parent or index */
   moveCollection: Collection,
   moveCollection: Collection,
+  /** Create a new Country */
+  createCountry: Country,
+  /** Update an existing Country */
+  updateCountry: Country,
+  /** Delete a Country */
+  deleteCountry: DeletionResponse,
   /** Create a new CustomerGroup */
   /** Create a new CustomerGroup */
   createCustomerGroup: CustomerGroup,
   createCustomerGroup: CustomerGroup,
   /** Update an existing CustomerGroup */
   /** Update an existing CustomerGroup */
@@ -1452,7 +1452,6 @@ export type Mutation = {
   updateCustomerAddress: Address,
   updateCustomerAddress: Address,
   /** Update an existing Address */
   /** Update an existing Address */
   deleteCustomerAddress: Scalars['Boolean'],
   deleteCustomerAddress: Scalars['Boolean'],
-  updateGlobalSettings: GlobalSettings,
   /** Create a new Facet */
   /** Create a new Facet */
   createFacet: Facet,
   createFacet: Facet,
   /** Update an existing Facet */
   /** Update an existing Facet */
@@ -1465,21 +1464,15 @@ export type Mutation = {
   updateFacetValues: Array<FacetValue>,
   updateFacetValues: Array<FacetValue>,
   /** Delete one or more FacetValues */
   /** Delete one or more FacetValues */
   deleteFacetValues: Array<DeletionResponse>,
   deleteFacetValues: Array<DeletionResponse>,
+  updateGlobalSettings: GlobalSettings,
   importProducts?: Maybe<ImportInfo>,
   importProducts?: Maybe<ImportInfo>,
+  /** Update an existing PaymentMethod */
+  updatePaymentMethod: PaymentMethod,
   /** Create a new ProductOptionGroup */
   /** Create a new ProductOptionGroup */
   createProductOptionGroup: ProductOptionGroup,
   createProductOptionGroup: ProductOptionGroup,
   /** Update an existing ProductOptionGroup */
   /** Update an existing ProductOptionGroup */
   updateProductOptionGroup: ProductOptionGroup,
   updateProductOptionGroup: ProductOptionGroup,
   reindex: SearchReindexResponse,
   reindex: SearchReindexResponse,
-  /** Update an existing PaymentMethod */
-  updatePaymentMethod: PaymentMethod,
-  createPromotion: Promotion,
-  updatePromotion: Promotion,
-  deletePromotion: DeletionResponse,
-  /** Create a new ShippingMethod */
-  createShippingMethod: ShippingMethod,
-  /** Update an existing ShippingMethod */
-  updateShippingMethod: ShippingMethod,
   /** Create a new Product */
   /** Create a new Product */
   createProduct: Product,
   createProduct: Product,
   /** Update an existing Product */
   /** Update an existing Product */
@@ -1494,18 +1487,25 @@ export type Mutation = {
   generateVariantsForProduct: Product,
   generateVariantsForProduct: Product,
   /** Update existing ProductVariants */
   /** Update existing ProductVariants */
   updateProductVariants: Array<Maybe<ProductVariant>>,
   updateProductVariants: Array<Maybe<ProductVariant>>,
+  createPromotion: Promotion,
+  updatePromotion: Promotion,
+  deletePromotion: DeletionResponse,
   /** Create a new Role */
   /** Create a new Role */
   createRole: Role,
   createRole: Role,
   /** Update an existing Role */
   /** Update an existing Role */
   updateRole: Role,
   updateRole: Role,
-  /** Create a new TaxCategory */
-  createTaxCategory: TaxCategory,
-  /** Update an existing TaxCategory */
-  updateTaxCategory: TaxCategory,
+  /** Create a new ShippingMethod */
+  createShippingMethod: ShippingMethod,
+  /** Update an existing ShippingMethod */
+  updateShippingMethod: ShippingMethod,
   /** Create a new TaxRate */
   /** Create a new TaxRate */
   createTaxRate: TaxRate,
   createTaxRate: TaxRate,
   /** Update an existing TaxRate */
   /** Update an existing TaxRate */
   updateTaxRate: TaxRate,
   updateTaxRate: TaxRate,
+  /** Create a new TaxCategory */
+  createTaxCategory: TaxCategory,
+  /** Update an existing TaxCategory */
+  updateTaxCategory: TaxCategory,
   /** Create a new Zone */
   /** Create a new Zone */
   createZone: Zone,
   createZone: Zone,
   /** Update an existing Zone */
   /** Update an existing Zone */
@@ -1540,6 +1540,11 @@ export type MutationAssignRoleToAdministratorArgs = {
 };
 };
 
 
 
 
+export type MutationCreateAssetsArgs = {
+  input: Array<CreateAssetInput>
+};
+
+
 export type MutationLoginArgs = {
 export type MutationLoginArgs = {
   username: Scalars['String'],
   username: Scalars['String'],
   password: Scalars['String'],
   password: Scalars['String'],
@@ -1547,11 +1552,6 @@ export type MutationLoginArgs = {
 };
 };
 
 
 
 
-export type MutationCreateAssetsArgs = {
-  input: Array<CreateAssetInput>
-};
-
-
 export type MutationCreateChannelArgs = {
 export type MutationCreateChannelArgs = {
   input: CreateChannelInput
   input: CreateChannelInput
 };
 };
@@ -1562,33 +1562,33 @@ export type MutationUpdateChannelArgs = {
 };
 };
 
 
 
 
-export type MutationCreateCountryArgs = {
-  input: CreateCountryInput
+export type MutationCreateCollectionArgs = {
+  input: CreateCollectionInput
 };
 };
 
 
 
 
-export type MutationUpdateCountryArgs = {
-  input: UpdateCountryInput
+export type MutationUpdateCollectionArgs = {
+  input: UpdateCollectionInput
 };
 };
 
 
 
 
-export type MutationDeleteCountryArgs = {
-  id: Scalars['ID']
+export type MutationMoveCollectionArgs = {
+  input: MoveCollectionInput
 };
 };
 
 
 
 
-export type MutationCreateCollectionArgs = {
-  input: CreateCollectionInput
+export type MutationCreateCountryArgs = {
+  input: CreateCountryInput
 };
 };
 
 
 
 
-export type MutationUpdateCollectionArgs = {
-  input: UpdateCollectionInput
+export type MutationUpdateCountryArgs = {
+  input: UpdateCountryInput
 };
 };
 
 
 
 
-export type MutationMoveCollectionArgs = {
-  input: MoveCollectionInput
+export type MutationDeleteCountryArgs = {
+  id: Scalars['ID']
 };
 };
 
 
 
 
@@ -1646,11 +1646,6 @@ export type MutationDeleteCustomerAddressArgs = {
 };
 };
 
 
 
 
-export type MutationUpdateGlobalSettingsArgs = {
-  input: UpdateGlobalSettingsInput
-};
-
-
 export type MutationCreateFacetArgs = {
 export type MutationCreateFacetArgs = {
   input: CreateFacetInput
   input: CreateFacetInput
 };
 };
@@ -1683,18 +1678,13 @@ export type MutationDeleteFacetValuesArgs = {
 };
 };
 
 
 
 
-export type MutationImportProductsArgs = {
-  csvFile: Scalars['Upload']
-};
-
-
-export type MutationCreateProductOptionGroupArgs = {
-  input: CreateProductOptionGroupInput
+export type MutationUpdateGlobalSettingsArgs = {
+  input: UpdateGlobalSettingsInput
 };
 };
 
 
 
 
-export type MutationUpdateProductOptionGroupArgs = {
-  input: UpdateProductOptionGroupInput
+export type MutationImportProductsArgs = {
+  csvFile: Scalars['Upload']
 };
 };
 
 
 
 
@@ -1703,28 +1693,13 @@ export type MutationUpdatePaymentMethodArgs = {
 };
 };
 
 
 
 
-export type MutationCreatePromotionArgs = {
-  input: CreatePromotionInput
-};
-
-
-export type MutationUpdatePromotionArgs = {
-  input: UpdatePromotionInput
-};
-
-
-export type MutationDeletePromotionArgs = {
-  id: Scalars['ID']
-};
-
-
-export type MutationCreateShippingMethodArgs = {
-  input: CreateShippingMethodInput
+export type MutationCreateProductOptionGroupArgs = {
+  input: CreateProductOptionGroupInput
 };
 };
 
 
 
 
-export type MutationUpdateShippingMethodArgs = {
-  input: UpdateShippingMethodInput
+export type MutationUpdateProductOptionGroupArgs = {
+  input: UpdateProductOptionGroupInput
 };
 };
 
 
 
 
@@ -1768,6 +1743,21 @@ export type MutationUpdateProductVariantsArgs = {
 };
 };
 
 
 
 
+export type MutationCreatePromotionArgs = {
+  input: CreatePromotionInput
+};
+
+
+export type MutationUpdatePromotionArgs = {
+  input: UpdatePromotionInput
+};
+
+
+export type MutationDeletePromotionArgs = {
+  id: Scalars['ID']
+};
+
+
 export type MutationCreateRoleArgs = {
 export type MutationCreateRoleArgs = {
   input: CreateRoleInput
   input: CreateRoleInput
 };
 };
@@ -1778,13 +1768,13 @@ export type MutationUpdateRoleArgs = {
 };
 };
 
 
 
 
-export type MutationCreateTaxCategoryArgs = {
-  input: CreateTaxCategoryInput
+export type MutationCreateShippingMethodArgs = {
+  input: CreateShippingMethodInput
 };
 };
 
 
 
 
-export type MutationUpdateTaxCategoryArgs = {
-  input: UpdateTaxCategoryInput
+export type MutationUpdateShippingMethodArgs = {
+  input: UpdateShippingMethodInput
 };
 };
 
 
 
 
@@ -1798,6 +1788,16 @@ export type MutationUpdateTaxRateArgs = {
 };
 };
 
 
 
 
+export type MutationCreateTaxCategoryArgs = {
+  input: CreateTaxCategoryInput
+};
+
+
+export type MutationUpdateTaxCategoryArgs = {
+  input: UpdateTaxCategoryInput
+};
+
+
 export type MutationCreateZoneArgs = {
 export type MutationCreateZoneArgs = {
   input: CreateZoneInput
   input: CreateZoneInput
 };
 };
@@ -2295,46 +2295,46 @@ export type PromotionSortParameter = {
 export type Query = {
 export type Query = {
   administrators: AdministratorList,
   administrators: AdministratorList,
   administrator?: Maybe<Administrator>,
   administrator?: Maybe<Administrator>,
-  me?: Maybe<CurrentUser>,
   assets: AssetList,
   assets: AssetList,
   asset?: Maybe<Asset>,
   asset?: Maybe<Asset>,
+  me?: Maybe<CurrentUser>,
   channels: Array<Channel>,
   channels: Array<Channel>,
   channel?: Maybe<Channel>,
   channel?: Maybe<Channel>,
   activeChannel: Channel,
   activeChannel: Channel,
-  countries: CountryList,
-  country?: Maybe<Country>,
   collections: CollectionList,
   collections: CollectionList,
   collection?: Maybe<Collection>,
   collection?: Maybe<Collection>,
   collectionFilters: Array<ConfigurableOperation>,
   collectionFilters: Array<ConfigurableOperation>,
+  countries: CountryList,
+  country?: Maybe<Country>,
   customerGroups: Array<CustomerGroup>,
   customerGroups: Array<CustomerGroup>,
   customerGroup?: Maybe<CustomerGroup>,
   customerGroup?: Maybe<CustomerGroup>,
   customers: CustomerList,
   customers: CustomerList,
   customer?: Maybe<Customer>,
   customer?: Maybe<Customer>,
-  globalSettings: GlobalSettings,
   facets: FacetList,
   facets: FacetList,
   facet?: Maybe<Facet>,
   facet?: Maybe<Facet>,
+  globalSettings: GlobalSettings,
   order?: Maybe<Order>,
   order?: Maybe<Order>,
   orders: OrderList,
   orders: OrderList,
+  paymentMethods: PaymentMethodList,
+  paymentMethod?: Maybe<PaymentMethod>,
   productOptionGroups: Array<ProductOptionGroup>,
   productOptionGroups: Array<ProductOptionGroup>,
   productOptionGroup?: Maybe<ProductOptionGroup>,
   productOptionGroup?: Maybe<ProductOptionGroup>,
   search: SearchResponse,
   search: SearchResponse,
-  paymentMethods: PaymentMethodList,
-  paymentMethod?: Maybe<PaymentMethod>,
+  products: ProductList,
+  product?: Maybe<Product>,
   promotion?: Maybe<Promotion>,
   promotion?: Maybe<Promotion>,
   promotions: PromotionList,
   promotions: PromotionList,
   adjustmentOperations: AdjustmentOperations,
   adjustmentOperations: AdjustmentOperations,
+  roles: RoleList,
+  role?: Maybe<Role>,
   shippingMethods: ShippingMethodList,
   shippingMethods: ShippingMethodList,
   shippingMethod?: Maybe<ShippingMethod>,
   shippingMethod?: Maybe<ShippingMethod>,
   shippingEligibilityCheckers: Array<ConfigurableOperation>,
   shippingEligibilityCheckers: Array<ConfigurableOperation>,
   shippingCalculators: Array<ConfigurableOperation>,
   shippingCalculators: Array<ConfigurableOperation>,
-  products: ProductList,
-  product?: Maybe<Product>,
-  roles: RoleList,
-  role?: Maybe<Role>,
-  taxCategories: Array<TaxCategory>,
-  taxCategory?: Maybe<TaxCategory>,
   taxRates: TaxRateList,
   taxRates: TaxRateList,
   taxRate?: Maybe<TaxRate>,
   taxRate?: Maybe<TaxRate>,
+  taxCategories: Array<TaxCategory>,
+  taxCategory?: Maybe<TaxCategory>,
   zones: Array<Zone>,
   zones: Array<Zone>,
   zone?: Maybe<Zone>,
   zone?: Maybe<Zone>,
   temp__?: Maybe<Scalars['Boolean']>,
   temp__?: Maybe<Scalars['Boolean']>,
@@ -2369,16 +2369,6 @@ export type QueryChannelArgs = {
 };
 };
 
 
 
 
-export type QueryCountriesArgs = {
-  options?: Maybe<CountryListOptions>
-};
-
-
-export type QueryCountryArgs = {
-  id: Scalars['ID']
-};
-
-
 export type QueryCollectionsArgs = {
 export type QueryCollectionsArgs = {
   languageCode?: Maybe<LanguageCode>,
   languageCode?: Maybe<LanguageCode>,
   options?: Maybe<CollectionListOptions>
   options?: Maybe<CollectionListOptions>
@@ -2391,6 +2381,16 @@ export type QueryCollectionArgs = {
 };
 };
 
 
 
 
+export type QueryCountriesArgs = {
+  options?: Maybe<CountryListOptions>
+};
+
+
+export type QueryCountryArgs = {
+  id: Scalars['ID']
+};
+
+
 export type QueryCustomerGroupArgs = {
 export type QueryCustomerGroupArgs = {
   id: Scalars['ID']
   id: Scalars['ID']
 };
 };
@@ -2428,6 +2428,16 @@ export type QueryOrdersArgs = {
 };
 };
 
 
 
 
+export type QueryPaymentMethodsArgs = {
+  options?: Maybe<PaymentMethodListOptions>
+};
+
+
+export type QueryPaymentMethodArgs = {
+  id: Scalars['ID']
+};
+
+
 export type QueryProductOptionGroupsArgs = {
 export type QueryProductOptionGroupsArgs = {
   languageCode?: Maybe<LanguageCode>,
   languageCode?: Maybe<LanguageCode>,
   filterTerm?: Maybe<Scalars['String']>
   filterTerm?: Maybe<Scalars['String']>
@@ -2445,13 +2455,15 @@ export type QuerySearchArgs = {
 };
 };
 
 
 
 
-export type QueryPaymentMethodsArgs = {
-  options?: Maybe<PaymentMethodListOptions>
+export type QueryProductsArgs = {
+  languageCode?: Maybe<LanguageCode>,
+  options?: Maybe<ProductListOptions>
 };
 };
 
 
 
 
-export type QueryPaymentMethodArgs = {
-  id: Scalars['ID']
+export type QueryProductArgs = {
+  id: Scalars['ID'],
+  languageCode?: Maybe<LanguageCode>
 };
 };
 
 
 
 
@@ -2465,34 +2477,32 @@ export type QueryPromotionsArgs = {
 };
 };
 
 
 
 
-export type QueryShippingMethodsArgs = {
-  options?: Maybe<ShippingMethodListOptions>
+export type QueryRolesArgs = {
+  options?: Maybe<RoleListOptions>
 };
 };
 
 
 
 
-export type QueryShippingMethodArgs = {
+export type QueryRoleArgs = {
   id: Scalars['ID']
   id: Scalars['ID']
 };
 };
 
 
 
 
-export type QueryProductsArgs = {
-  languageCode?: Maybe<LanguageCode>,
-  options?: Maybe<ProductListOptions>
+export type QueryShippingMethodsArgs = {
+  options?: Maybe<ShippingMethodListOptions>
 };
 };
 
 
 
 
-export type QueryProductArgs = {
-  id: Scalars['ID'],
-  languageCode?: Maybe<LanguageCode>
+export type QueryShippingMethodArgs = {
+  id: Scalars['ID']
 };
 };
 
 
 
 
-export type QueryRolesArgs = {
-  options?: Maybe<RoleListOptions>
+export type QueryTaxRatesArgs = {
+  options?: Maybe<TaxRateListOptions>
 };
 };
 
 
 
 
-export type QueryRoleArgs = {
+export type QueryTaxRateArgs = {
   id: Scalars['ID']
   id: Scalars['ID']
 };
 };
 
 
@@ -2502,16 +2512,6 @@ export type QueryTaxCategoryArgs = {
 };
 };
 
 
 
 
-export type QueryTaxRatesArgs = {
-  options?: Maybe<TaxRateListOptions>
-};
-
-
-export type QueryTaxRateArgs = {
-  id: Scalars['ID']
-};
-
-
 export type QueryZoneArgs = {
 export type QueryZoneArgs = {
   id: Scalars['ID']
   id: Scalars['ID']
 };
 };
@@ -3409,6 +3409,11 @@ export type SearchProductsQueryVariables = {
 
 
 export type SearchProductsQuery = ({ __typename?: 'Query' } & { search: ({ __typename?: 'SearchResponse' } & Pick<SearchResponse, 'totalItems'> & { items: Array<({ __typename?: 'SearchResult' } & Pick<SearchResult, 'enabled' | 'productId' | 'productName' | 'productPreview' | 'productVariantId' | 'productVariantName' | 'productVariantPreview' | 'sku'>)>, facetValues: Array<({ __typename?: 'FacetValueResult' } & Pick<FacetValueResult, 'count'> & { facetValue: ({ __typename?: 'FacetValue' } & Pick<FacetValue, 'id' | 'name'> & { facet: ({ __typename?: 'Facet' } & Pick<Facet, 'id' | 'name'>) }) })> }) });
 export type SearchProductsQuery = ({ __typename?: 'Query' } & { search: ({ __typename?: 'SearchResponse' } & Pick<SearchResponse, 'totalItems'> & { items: Array<({ __typename?: 'SearchResult' } & Pick<SearchResult, 'enabled' | 'productId' | 'productName' | 'productPreview' | 'productVariantId' | 'productVariantName' | 'productVariantPreview' | 'sku'>)>, facetValues: Array<({ __typename?: 'FacetValueResult' } & Pick<FacetValueResult, 'count'> & { facetValue: ({ __typename?: 'FacetValue' } & Pick<FacetValue, 'id' | 'name'> & { facet: ({ __typename?: 'Facet' } & Pick<Facet, 'id' | 'name'>) }) })> }) });
 
 
+export type ReindexMutationVariables = {};
+
+
+export type ReindexMutation = ({ __typename?: 'Mutation' } & { reindex: ({ __typename?: 'SearchReindexResponse' } & Pick<SearchReindexResponse, 'indexedItemCount' | 'success' | 'timeTaken'>) });
+
 export type ConfigurableOperationFragment = ({ __typename?: 'ConfigurableOperation' } & Pick<ConfigurableOperation, 'code' | 'description'> & { args: Array<({ __typename?: 'ConfigArg' } & Pick<ConfigArg, 'name' | 'type' | 'value'>)> });
 export type ConfigurableOperationFragment = ({ __typename?: 'ConfigurableOperation' } & Pick<ConfigurableOperation, 'code' | 'description'> & { args: Array<({ __typename?: 'ConfigArg' } & Pick<ConfigArg, 'name' | 'type' | 'value'>)> });
 
 
 export type PromotionFragment = ({ __typename?: 'Promotion' } & Pick<Promotion, 'id' | 'createdAt' | 'updatedAt' | 'name' | 'enabled'> & { conditions: Array<({ __typename?: 'ConfigurableOperation' } & ConfigurableOperationFragment)>, actions: Array<({ __typename?: 'ConfigurableOperation' } & ConfigurableOperationFragment)> });
 export type PromotionFragment = ({ __typename?: 'Promotion' } & Pick<Promotion, 'id' | 'createdAt' | 'updatedAt' | 'name' | 'enabled'> & { conditions: Array<({ __typename?: 'ConfigurableOperation' } & ConfigurableOperationFragment)>, actions: Array<({ __typename?: 'ConfigurableOperation' } & ConfigurableOperationFragment)> });
@@ -4171,6 +4176,12 @@ export namespace SearchProducts {
   export type Facet = (NonNullable<SearchProductsQuery['search']['facetValues'][0]>)['facetValue']['facet'];
   export type Facet = (NonNullable<SearchProductsQuery['search']['facetValues'][0]>)['facetValue']['facet'];
 }
 }
 
 
+export namespace Reindex {
+  export type Variables = ReindexMutationVariables;
+  export type Mutation = ReindexMutation;
+  export type Reindex = ReindexMutation['reindex'];
+}
+
 export namespace ConfigurableOperation {
 export namespace ConfigurableOperation {
   export type Fragment = ConfigurableOperationFragment;
   export type Fragment = ConfigurableOperationFragment;
   export type Args = (NonNullable<ConfigurableOperationFragment['args'][0]>);
   export type Args = (NonNullable<ConfigurableOperationFragment['args'][0]>);

+ 10 - 0
admin-ui/src/app/data/definitions/product-definitions.ts

@@ -319,3 +319,13 @@ export const SEARCH_PRODUCTS = gql`
         }
         }
     }
     }
 `;
 `;
+
+export const REINDEX = gql`
+    mutation Reindex {
+        reindex {
+            indexedItemCount
+            success
+            timeTaken
+        }
+    }
+`;

+ 6 - 0
admin-ui/src/app/data/providers/product-data.service.ts

@@ -13,6 +13,7 @@ import {
     GetProductList,
     GetProductList,
     GetProductOptionGroups,
     GetProductOptionGroups,
     GetProductWithVariants,
     GetProductWithVariants,
+    Reindex,
     RemoveOptionGroupFromProduct,
     RemoveOptionGroupFromProduct,
     SearchProducts,
     SearchProducts,
     SortOrder,
     SortOrder,
@@ -33,6 +34,7 @@ import {
     GET_PRODUCT_LIST,
     GET_PRODUCT_LIST,
     GET_PRODUCT_OPTION_GROUPS,
     GET_PRODUCT_OPTION_GROUPS,
     GET_PRODUCT_WITH_VARIANTS,
     GET_PRODUCT_WITH_VARIANTS,
+    REINDEX,
     REMOVE_OPTION_GROUP_FROM_PRODUCT,
     REMOVE_OPTION_GROUP_FROM_PRODUCT,
     SEARCH_PRODUCTS,
     SEARCH_PRODUCTS,
     UPDATE_PRODUCT,
     UPDATE_PRODUCT,
@@ -55,6 +57,10 @@ export class ProductDataService {
         });
         });
     }
     }
 
 
+    reindex() {
+        return this.baseDataService.mutate<Reindex.Mutation>(REINDEX);
+    }
+
     getProducts(take: number = 10, skip: number = 0) {
     getProducts(take: number = 10, skip: number = 0) {
         return this.baseDataService.query<GetProductList.Query, GetProductList.Variables>(GET_PRODUCT_LIST, {
         return this.baseDataService.query<GetProductList.Query, GetProductList.Variables>(GET_PRODUCT_LIST, {
             options: {
             options: {

+ 4 - 1
admin-ui/src/i18n-messages/en.json

@@ -37,7 +37,7 @@
     "create-new-collection": "Create new collection",
     "create-new-collection": "Create new collection",
     "create-new-facet": "Create new facet",
     "create-new-facet": "Create new facet",
     "create-new-option-group": "Create new option group",
     "create-new-option-group": "Create new option group",
-    "create-new-product": "Create new product",
+    "create-new-product": "New product",
     "display-variant-cards": "View details",
     "display-variant-cards": "View details",
     "display-variant-table": "View as table",
     "display-variant-table": "View as table",
     "drop-files-to-upload": "Drop files to upload",
     "drop-files-to-upload": "Drop files to upload",
@@ -73,6 +73,9 @@
     "product-name": "Product name",
     "product-name": "Product name",
     "product-variants": "Product variants",
     "product-variants": "Product variants",
     "public": "Public",
     "public": "Public",
+    "rebuild-search-index": "Rebuild search index",
+    "reindex-error": "An error occurred while rebuilding search index",
+    "reindex-successful": "Indexed {count, plural, one {product variant} other {{count} product variants}} in {time}ms",
     "remove-asset": "Remove asset",
     "remove-asset": "Remove asset",
     "search-asset-name": "Search assets by name",
     "search-asset-name": "Search assets by name",
     "search-for-term": "Search for term",
     "search-for-term": "Search for term",