Преглед изворни кода

feat(admin-ui): Display pending search index updates in product list

Relates to #1137
Michael Bromley пре 4 година
родитељ
комит
6f4a89f0ec
22 измењених фајлова са 200 додато и 34 уклоњено
  1. 26 26
      packages/admin-ui/i18n-coverage.json
  2. 26 4
      packages/admin-ui/src/lib/catalog/src/components/product-list/product-list.component.html
  3. 14 0
      packages/admin-ui/src/lib/catalog/src/components/product-list/product-list.component.scss
  4. 16 0
      packages/admin-ui/src/lib/catalog/src/components/product-list/product-list.component.ts
  5. 24 0
      packages/admin-ui/src/lib/core/src/common/generated-types.ts
  6. 14 0
      packages/admin-ui/src/lib/core/src/data/definitions/settings-definitions.ts
  7. 19 1
      packages/admin-ui/src/lib/core/src/data/providers/product-data.service.ts
  8. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/cs.json
  9. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/de.json
  10. 5 1
      packages/admin-ui/src/lib/static/i18n-messages/en.json
  11. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/es.json
  12. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/fr.json
  13. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/it.json
  14. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/pl.json
  15. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/pt_BR.json
  16. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/pt_PT.json
  17. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/ru.json
  18. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/uk.json
  19. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/zh_Hans.json
  20. 4 0
      packages/admin-ui/src/lib/static/i18n-messages/zh_Hant.json
  21. 6 1
      packages/core/src/job-queue/job-queue.ts
  22. 2 1
      packages/core/src/plugin/default-search-plugin/fulltext-search.resolver.ts

+ 26 - 26
packages/admin-ui/i18n-coverage.json

@@ -1,71 +1,71 @@
 {
-  "generatedOn": "2021-09-02T21:51:05.244Z",
-  "lastCommit": "76547940282ffb44ab9430d1b7d29c2d3fc3c2ee",
+  "generatedOn": "2021-10-07T12:23:24.068Z",
+  "lastCommit": "0eadedef0bfaacd2838befc67f75c14a5e7a6606",
   "translationStatus": {
     "cs": {
-      "tokenCount": 623,
+      "tokenCount": 627,
       "translatedCount": 591,
-      "percentage": 95
+      "percentage": 94
     },
     "de": {
-      "tokenCount": 623,
+      "tokenCount": 627,
       "translatedCount": 570,
       "percentage": 91
     },
     "en": {
-      "tokenCount": 623,
-      "translatedCount": 623,
+      "tokenCount": 627,
+      "translatedCount": 626,
       "percentage": 100
     },
     "es": {
-      "tokenCount": 623,
-      "translatedCount": 309,
-      "percentage": 50
+      "tokenCount": 627,
+      "translatedCount": 623,
+      "percentage": 99
     },
     "fr": {
-      "tokenCount": 623,
+      "tokenCount": 627,
       "translatedCount": 613,
       "percentage": 98
     },
     "it": {
-      "tokenCount": 623,
+      "tokenCount": 627,
       "translatedCount": 621,
-      "percentage": 100
+      "percentage": 99
     },
     "pl": {
-      "tokenCount": 623,
+      "tokenCount": 627,
       "translatedCount": 405,
       "percentage": 65
     },
     "pt_BR": {
-      "tokenCount": 623,
+      "tokenCount": 627,
       "translatedCount": 588,
       "percentage": 94
     },
     "pt_PT": {
-      "tokenCount": 623,
-      "translatedCount": 0,
-      "percentage": 0
+      "tokenCount": 627,
+      "translatedCount": 622,
+      "percentage": 99
     },
     "ru": {
-      "tokenCount": 623,
+      "tokenCount": 627,
       "translatedCount": 621,
-      "percentage": 100
+      "percentage": 99
     },
     "uk": {
-      "tokenCount": 623,
+      "tokenCount": 627,
       "translatedCount": 621,
-      "percentage": 100
+      "percentage": 99
     },
     "zh_Hans": {
-      "tokenCount": 623,
+      "tokenCount": 627,
       "translatedCount": 558,
-      "percentage": 90
+      "percentage": 89
     },
     "zh_Hant": {
-      "tokenCount": 623,
+      "tokenCount": 627,
       "translatedCount": 385,
-      "percentage": 62
+      "percentage": 61
     }
   }
 }

+ 26 - 4
packages/admin-ui/src/lib/catalog/src/components/product-list/product-list.component.html

@@ -8,10 +8,28 @@
                 (facetValueChange)="setFacetValueIds($event)"
             ></vdr-product-search-input>
             <vdr-dropdown class="search-settings-menu mr3">
-                <button type="button" class="icon-button" vdrDropdownTrigger>
+                <button type="button"
+                        class="icon-button search-index-button"
+                        [title]="(pendingSearchIndexUpdates ? 'catalog.pending-search-index-updates' : 'catalog.search-index-controls') | translate "
+                        vdrDropdownTrigger>
                     <clr-icon shape="cog"></clr-icon>
+                    <vdr-status-badge *ngIf="pendingSearchIndexUpdates" type="warning"> </vdr-status-badge>
                 </button>
                 <vdr-dropdown-menu vdrPosition="bottom-right">
+                    <h4 class="dropdown-header">{{ 'catalog.search-index-controls' | translate }}</h4>
+                    <ng-container *ngIf="pendingSearchIndexUpdates">
+                        <button
+                            type="button"
+                            class="run-updates-button"
+                            vdrDropdownItem
+                            (click)="runPendingSearchIndexUpdates()"
+                            [disabled]="!(['UpdateCatalog', 'UpdateProduct'] | hasPermission)"
+                        >
+                            <vdr-status-badge type="warning"> </vdr-status-badge>
+                            {{ 'catalog.run-pending-search-index-updates' | translate: { count: pendingSearchIndexUpdates } }}
+                        </button>
+                        <div class="dropdown-divider"></div>
+                    </ng-container>
                     <button
                         type="button"
                         vdrDropdownItem
@@ -25,7 +43,7 @@
         </div>
         <div class="flex wrap">
             <clr-checkbox-wrapper class="mt2">
-                <input type="checkbox" clrCheckbox [(ngModel)]="groupByProduct"/>
+                <input type="checkbox" clrCheckbox [(ngModel)]="groupByProduct" />
                 <label>{{ 'catalog.group-by-product' | translate }}</label>
             </clr-checkbox-wrapper>
             <vdr-language-selector
@@ -37,7 +55,11 @@
     </vdr-ab-left>
     <vdr-ab-right>
         <vdr-action-bar-items locationId="product-list"></vdr-action-bar-items>
-        <a class="btn btn-primary" [routerLink]="['./create']" *vdrIfPermissions="['CreateCatalog', 'CreateProduct']">
+        <a
+            class="btn btn-primary"
+            [routerLink]="['./create']"
+            *vdrIfPermissions="['CreateCatalog', 'CreateProduct']"
+        >
             <clr-icon shape="plus"></clr-icon>
             <span class="full-label">{{ 'catalog.create-new-product' | translate }}</span>
         </a>
@@ -62,7 +84,7 @@
                             : result.productVariantAsset || result.productAsset as asset;
                         else imagePlaceholder
                     "
-                    [src]="asset | assetPreview:'tiny'"
+                    [src]="asset | assetPreview: 'tiny'"
                 />
                 <ng-template #imagePlaceholder>
                     <div class="placeholder">

+ 14 - 0
packages/admin-ui/src/lib/catalog/src/components/product-list/product-list.component.scss

@@ -27,3 +27,17 @@
 td.disabled {
     background-color: var(--color-component-bg-200);
 }
+.search-index-button {
+    position: relative;
+    vdr-status-badge {
+        right: 0;
+        top: 0;
+    }
+}
+.run-updates-button {
+    position: relative;
+    vdr-status-badge {
+        left: 10px;
+        top: 10px;
+    }
+}

+ 16 - 0
packages/admin-ui/src/lib/catalog/src/components/product-list/product-list.component.ts

@@ -45,6 +45,8 @@ export class ProductListComponent
     facetValues$: Observable<SearchProducts.FacetValues[]>;
     availableLanguages$: Observable<LanguageCode[]>;
     contentLanguage$: Observable<LanguageCode>;
+    pendingSearchIndexUpdates = 0;
+
     @ViewChild('productSearchInputComponent', { static: true })
     private productSearchInput: ProductSearchInputComponent;
     constructor(
@@ -109,6 +111,11 @@ export class ProductListComponent
             .uiState()
             .mapStream(({ uiState }) => uiState.contentLanguage)
             .pipe(tap(() => this.refresh()));
+
+        this.dataService.product
+            .getPendingSearchIndexUpdates()
+            .mapSingle(({ pendingSearchIndexUpdates }) => pendingSearchIndexUpdates)
+            .subscribe(value => (this.pendingSearchIndexUpdates = value));
     }
 
     ngAfterViewInit() {
@@ -147,6 +154,15 @@ export class ProductListComponent
         });
     }
 
+    runPendingSearchIndexUpdates() {
+        this.dataService.product.runPendingSearchIndexUpdates().subscribe(value => {
+            this.notificationService.info(_('catalog.running-search-index-updates'), {
+                count: this.pendingSearchIndexUpdates,
+            });
+            this.pendingSearchIndexUpdates = 0;
+        });
+    }
+
     deleteProduct(productId: string) {
         this.modalService
             .dialog({

+ 24 - 0
packages/admin-ui/src/lib/core/src/common/generated-types.ts

@@ -8296,6 +8296,19 @@ export type ReindexMutation = { reindex: (
     & JobInfoFragment
   ) };
 
+export type GetPendingSearchIndexUpdatesQueryVariables = Exact<{ [key: string]: never; }>;
+
+
+export type GetPendingSearchIndexUpdatesQuery = Pick<Query, 'pendingSearchIndexUpdates'>;
+
+export type RunPendingSearchIndexUpdatesMutationVariables = Exact<{ [key: string]: never; }>;
+
+
+export type RunPendingSearchIndexUpdatesMutation = { runPendingSearchIndexUpdates: (
+    { __typename?: 'Success' }
+    & Pick<Success, 'success'>
+  ) };
+
 export type ConfigurableOperationFragment = (
   { __typename?: 'ConfigurableOperation' }
   & Pick<ConfigurableOperation, 'code'>
@@ -9980,6 +9993,17 @@ export namespace Reindex {
   export type Reindex = (NonNullable<ReindexMutation['reindex']>);
 }
 
+export namespace GetPendingSearchIndexUpdates {
+  export type Variables = GetPendingSearchIndexUpdatesQueryVariables;
+  export type Query = GetPendingSearchIndexUpdatesQuery;
+}
+
+export namespace RunPendingSearchIndexUpdates {
+  export type Variables = RunPendingSearchIndexUpdatesMutationVariables;
+  export type Mutation = RunPendingSearchIndexUpdatesMutation;
+  export type RunPendingSearchIndexUpdates = (NonNullable<RunPendingSearchIndexUpdatesMutation['runPendingSearchIndexUpdates']>);
+}
+
 export namespace ConfigurableOperation {
   export type Fragment = ConfigurableOperationFragment;
   export type Args = NonNullable<(NonNullable<ConfigurableOperationFragment['args']>)[number]>;

+ 14 - 0
packages/admin-ui/src/lib/core/src/data/definitions/settings-definitions.ts

@@ -768,3 +768,17 @@ export const REINDEX = gql`
     }
     ${JOB_INFO_FRAGMENT}
 `;
+
+export const GET_PENDING_SEARCH_INDEX_UPDATES = gql`
+    query GetPendingSearchIndexUpdates {
+        pendingSearchIndexUpdates
+    }
+`;
+
+export const RUN_PENDING_SEARCH_INDEX_UPDATES = gql`
+    mutation RunPendingSearchIndexUpdates {
+        runPendingSearchIndexUpdates {
+            success
+        }
+    }
+`;

+ 19 - 1
packages/admin-ui/src/lib/core/src/data/providers/product-data.service.ts

@@ -23,6 +23,7 @@ import {
     DeleteTag,
     GetAsset,
     GetAssetList,
+    GetPendingSearchIndexUpdates,
     GetProductList,
     GetProductOptionGroup,
     GetProductOptionGroups,
@@ -43,6 +44,7 @@ import {
     RemoveProductsFromChannelInput,
     RemoveProductVariantsFromChannelInput,
     RemoveVariantsFromChannel,
+    RunPendingSearchIndexUpdates,
     SearchProducts,
     SortOrder,
     TagListOptions,
@@ -98,7 +100,11 @@ import {
     UPDATE_PRODUCT_VARIANTS,
     UPDATE_TAG,
 } from '../definitions/product-definitions';
-import { REINDEX } from '../definitions/settings-definitions';
+import {
+    GET_PENDING_SEARCH_INDEX_UPDATES,
+    REINDEX,
+    RUN_PENDING_SEARCH_INDEX_UPDATES,
+} from '../definitions/settings-definitions';
 
 import { BaseDataService } from './base-data.service';
 
@@ -130,6 +136,18 @@ export class ProductDataService {
         return this.baseDataService.mutate<Reindex.Mutation>(REINDEX);
     }
 
+    getPendingSearchIndexUpdates() {
+        return this.baseDataService.query<GetPendingSearchIndexUpdates.Query>(
+            GET_PENDING_SEARCH_INDEX_UPDATES,
+        );
+    }
+
+    runPendingSearchIndexUpdates() {
+        return this.baseDataService.mutate<RunPendingSearchIndexUpdates.Mutation>(
+            RUN_PENDING_SEARCH_INDEX_UPDATES,
+        );
+    }
+
     getProducts(options: ProductListOptions) {
         return this.baseDataService.query<GetProductList.Query, GetProductList.Variables>(GET_PRODUCT_LIST, {
             options,

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/cs.json

@@ -113,6 +113,7 @@
     "option-values": "Hodnoty volby",
     "out-of-stock-threshold": "Prahová hodnota pro vyprodání zásob",
     "out-of-stock-threshold-tooltip": "Nastaví hodnotu skladu, při které je tato varianta považována za vyprodanou. Použití záporné hodnoty umožňuje objednávat \"na objednávku\".",
+    "pending-search-index-updates": "",
     "price": "Cena",
     "price-conversion-factor": "Přepočítávací koeficient ceny",
     "price-in-channel": "Cena v { channel }",
@@ -131,8 +132,11 @@
     "remove-option": "Odebrat volbu",
     "remove-product-from-channel": "Odebrat produkt z kanálu",
     "remove-product-variant-from-channel": "Odebrat variantu z kanálu",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "",
     "search-for-term": "Hledat výraz",
+    "search-index-controls": "",
     "search-product-name-or-code": "Hledat produkt dle jména, nebo kódu",
     "select-product": "",
     "select-product-variant": "",

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/de.json

@@ -113,6 +113,7 @@
     "option-values": "Optionswerte",
     "out-of-stock-threshold": "Ausverkauft-Grenze",
     "out-of-stock-threshold-tooltip": "Legt fest, ab welcher Untergrenze ein Produkt als ausverkauft angezeigt wird. Ein negativer Wert kann verwendet werden, um mit einer Fehlmenge zu arbeiten.",
+    "pending-search-index-updates": "",
     "price": "Preis",
     "price-conversion-factor": "Preisumwandlungsfaktor",
     "price-in-channel": "Preis in { channel }",
@@ -131,8 +132,11 @@
     "remove-option": "Option entfernen",
     "remove-product-from-channel": "Produkt aus dem Kanal entfernen",
     "remove-product-variant-from-channel": "",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "",
     "search-for-term": "Suche nach Begriff",
+    "search-index-controls": "",
     "search-product-name-or-code": "Suche nach Produktname oder Artikelnummer",
     "select-product": "Produkt auswählen",
     "select-product-variant": "Produktvariante auswählen",

+ 5 - 1
packages/admin-ui/src/lib/static/i18n-messages/en.json

@@ -113,6 +113,7 @@
     "option-values": "Option values",
     "out-of-stock-threshold": "Out-of-stock threshold",
     "out-of-stock-threshold-tooltip": "Sets the stock level at which this variant is considered to be out of stock. Using a negative value enables backorder support.",
+    "pending-search-index-updates": "Search index has pending updates to run",
     "price": "Price",
     "price-conversion-factor": "Price conversion factor",
     "price-in-channel": "Price in { channel }",
@@ -131,8 +132,11 @@
     "remove-option": "Remove option",
     "remove-product-from-channel": "Remove product from channel",
     "remove-product-variant-from-channel": "Remove product variant from channel",
+    "run-pending-search-index-updates": "Run {count, plural, one {1 pending update} other {{count} pending updates}}",
+    "running-search-index-updates": "Running {count, plural, one {1 update} other {{count} updates}} to search index",
     "search-asset-name-or-tag": "Search by asset name or tags",
     "search-for-term": "Search for term",
+    "search-index-controls": "Search index controls",
     "search-product-name-or-code": "Search by product name or code",
     "select-product": "Select product",
     "select-product-variant": "Select product variant",
@@ -654,4 +658,4 @@
     "job-result": "Job result",
     "job-state": "Job state"
   }
-}
+}

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/es.json

@@ -113,6 +113,7 @@
     "option-values": "Valores de la opción",
     "out-of-stock-threshold": "Límite de agotamiento de existencias",
     "out-of-stock-threshold-tooltip": "Fija el nivel de existencias a partir del cual se considera que esta variante está agotada. El uso de un valor negativo activa el soporte de pedidos pendientes.",
+    "pending-search-index-updates": "",
     "price": "Precio",
     "price-conversion-factor": "Factor de conversión de precio",
     "price-in-channel": "Precio en { channel }",
@@ -131,8 +132,11 @@
     "remove-option": "Eliminar opción",
     "remove-product-from-channel": "Eliminar producto del canal de ventas",
     "remove-product-variant-from-channel": "Eliminar variante de producto del canal de ventas ",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "Buscar por nombre de recurso o faceta",
     "search-for-term": "Buscar por término",
+    "search-index-controls": "",
     "search-product-name-or-code": "Buscar por nombre o código de producto",
     "select-product": "Seleccionar producto",
     "select-product-variant": "Seleccionar variante de producto",

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/fr.json

@@ -113,6 +113,7 @@
     "option-values": "Valeurs de l'option",
     "out-of-stock-threshold": "Limite de la rupture de stock",
     "out-of-stock-threshold-tooltip": "Régler le niveau de stock à partir duquel la variante est considéré en rupture de stock. Renseigner une valeur négative permet d'accepter des commandes en attente.",
+    "pending-search-index-updates": "",
     "price": "Prix",
     "price-conversion-factor": "Facteur de conversion du prix",
     "price-in-channel": "Prix dans { channel }",
@@ -131,8 +132,11 @@
     "remove-option": "Retirer l'option",
     "remove-product-from-channel": "Retirer le produit du canal",
     "remove-product-variant-from-channel": "Retirer la variante du produit du canal",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "Rechercher par nom de fichier ou mot-clé",
     "search-for-term": "Chercher le terme",
+    "search-index-controls": "",
     "search-product-name-or-code": "Chercher par nom de produit ou code",
     "select-product": "Sélectionner un produit",
     "select-product-variant": "Sélectionner une variation produit",

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/it.json

@@ -113,6 +113,7 @@
     "option-values": "Valori opzione",
     "out-of-stock-threshold": "Soglia prodotto esaurito",
     "out-of-stock-threshold-tooltip": "Imposta la soglia di scorte alla quale il prodotto è considerato non disponibile alla vendita. Utilizzando un valore negativo si abilitano gli ordini anche fuori scorta.",
+    "pending-search-index-updates": "",
     "price": "Prezzo",
     "price-conversion-factor": "Fattore di conversione del prezzo",
     "price-in-channel": "Prezzo in { channel }",
@@ -131,8 +132,11 @@
     "remove-option": "Rimuovi opzione",
     "remove-product-from-channel": "Rimuovi prodotto dal canale",
     "remove-product-variant-from-channel": "Rimuovi variante dal canale",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "Cerca per nome o tag del media",
     "search-for-term": "Ricerca termine",
+    "search-index-controls": "",
     "search-product-name-or-code": "Ricerca per nome o codice prodotto",
     "select-product": "Seleziona prodotto",
     "select-product-variant": "Seleziona variante",

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/pl.json

@@ -113,6 +113,7 @@
     "option-values": "Wartość opcji",
     "out-of-stock-threshold": "",
     "out-of-stock-threshold-tooltip": "",
+    "pending-search-index-updates": "",
     "price": "Cena",
     "price-conversion-factor": "Przelicznik cen",
     "price-in-channel": "Cena w { channel }",
@@ -131,8 +132,11 @@
     "remove-option": "Usuń opcje",
     "remove-product-from-channel": "Usuń produkt z kanału",
     "remove-product-variant-from-channel": "",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "",
     "search-for-term": "Szukaj frazy",
+    "search-index-controls": "",
     "search-product-name-or-code": "Szukaj produktu po nazwie lub kodzie",
     "select-product": "",
     "select-product-variant": "",

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/pt_BR.json

@@ -113,6 +113,7 @@
     "option-values": "Valor da opção",
     "out-of-stock-threshold": "Limite reserva de fora de estoque",
     "out-of-stock-threshold-tooltip": "Define o nível de estoque no qual essa variação é considerada sem estoque. Usar um valor negativo ativa o suporte a pedidos em espera.",
+    "pending-search-index-updates": "",
     "price": "Preço",
     "price-conversion-factor": "Fator de conversão de preço",
     "price-in-channel": "Preço em { channel }",
@@ -131,8 +132,11 @@
     "remove-option": "Excluir opção",
     "remove-product-from-channel": "Excluir produto do canal",
     "remove-product-variant-from-channel": "",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "",
     "search-for-term": "Pesquisar termo",
+    "search-index-controls": "",
     "search-product-name-or-code": "Pesquisar por nome ou código do produto",
     "select-product": "",
     "select-product-variant": "",

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/pt_PT.json

@@ -113,6 +113,7 @@
     "option-values": "Valor da opção",
     "out-of-stock-threshold": "Limite para fora de estoque",
     "out-of-stock-threshold-tooltip": "Define o limite para a variante ser considerada sem estoque. Usar um valor negativo activa o suporte a pedidos pendentes.",
+    "pending-search-index-updates": "",
     "price": "Preço",
     "price-conversion-factor": "Factor de conversão de preço",
     "price-in-channel": "Preço no canal { channel }",
@@ -131,8 +132,11 @@
     "remove-option": "Eliminar opção",
     "remove-product-from-channel": "Eliminar produto do canal",
     "remove-product-variant-from-channel": "Remover variante do canal?",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "Pesquisar pelo nome ou tag",
     "search-for-term": "Pesquisar termo",
+    "search-index-controls": "",
     "search-product-name-or-code": "Pesquisar por nome ou código do produto",
     "select-product": "Seleccione o produto",
     "select-product-variant": "Seleccione a variante do produto",

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/ru.json

@@ -113,6 +113,7 @@
     "option-values": "Значение опции",
     "out-of-stock-threshold": "Порог «нет в наличии»",
     "out-of-stock-threshold-tooltip": "Установите порог остатков на складе, после которого будет считаться, что варианта товара нет в наличии. При использовании отрицательного значения порога, включается поддержка предзаказа.",
+    "pending-search-index-updates": "",
     "price": "Цена",
     "price-conversion-factor": "Коэффициент пересчета цены",
     "price-in-channel": "Цена в { channel }",
@@ -131,8 +132,11 @@
     "remove-option": "Удалить опции",
     "remove-product-from-channel": "Удалить товар из канала",
     "remove-product-variant-from-channel": "Удалить вариант товара из канала",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "Поиск по названию медиа-объект или тегам",
     "search-for-term": "Искать по фразе",
+    "search-index-controls": "",
     "search-product-name-or-code": "Поиск по названию товара или коду",
     "select-product": "Выбрать товара",
     "select-product-variant": "Выберите вариант товара",

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/uk.json

@@ -113,6 +113,7 @@
     "option-values": "Значення опції",
     "out-of-stock-threshold": "Поріг «немає в наявності»",
     "out-of-stock-threshold-tooltip": "Встановіть поріг залишків на складі, після якого буде вважатися, що варіанту товару немає в наявності. При використанні від'ємного значення порога, включається підтримка попереднього замовлення.",
+    "pending-search-index-updates": "",
     "price": "Ціна",
     "price-conversion-factor": "Коефіцієнт перерахунку ціни",
     "price-in-channel": "Ціна в { channel }",
@@ -131,8 +132,11 @@
     "remove-option": "Видалити опції",
     "remove-product-from-channel": "Видалити товар з каналу",
     "remove-product-variant-from-channel": "Видалити варіант товару з каналу",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "Пошук за назвою медіа-об'єкта або тегами",
     "search-for-term": "Шукати по фразі",
+    "search-index-controls": "",
     "search-product-name-or-code": "Пошук за назвою товару або кодом",
     "select-product": "Вибрати товар",
     "select-product-variant": "Виберіть варіант товару",

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/zh_Hans.json

@@ -113,6 +113,7 @@
     "option-values": "规格列表(按回车键添加)",
     "out-of-stock-threshold": "售空限制",
     "out-of-stock-threshold-tooltip": "当此规格产品库存值低于此限制时,产品将为售空状态。设置为负数设置此规格产品为缺货状态。",
+    "pending-search-index-updates": "",
     "price": "价格",
     "price-conversion-factor": "价格换算因数",
     "price-in-channel": "渠道{ channel }价格",
@@ -131,8 +132,11 @@
     "remove-option": "移除选项",
     "remove-product-from-channel": "从销售渠道移除商品",
     "remove-product-variant-from-channel": "从销售渠道移除商品变体",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "输入要搜索的资源名称或标签",
     "search-for-term": "输入搜索条目",
+    "search-index-controls": "",
     "search-product-name-or-code": "输入要搜索的商品名称或商品编码",
     "select-product": "选择商品",
     "select-product-variant": "选择商品变体",

+ 4 - 0
packages/admin-ui/src/lib/static/i18n-messages/zh_Hant.json

@@ -113,6 +113,7 @@
     "option-values": "規格列表(按輸入鍵新增)",
     "out-of-stock-threshold": "",
     "out-of-stock-threshold-tooltip": "",
+    "pending-search-index-updates": "",
     "price": "價格",
     "price-conversion-factor": "價格轉換係數",
     "price-in-channel": "渠道{ channel }價格",
@@ -131,8 +132,11 @@
     "remove-option": "移除選項",
     "remove-product-from-channel": "從渠道移除商品",
     "remove-product-variant-from-channel": "",
+    "run-pending-search-index-updates": "",
+    "running-search-index-updates": "",
     "search-asset-name-or-tag": "",
     "search-for-term": "輸入搜索條目",
+    "search-index-controls": "",
     "search-product-name-or-code": "輸入要搜索的商品名稱或商品編碼",
     "select-product": "",
     "select-product-variant": "",

+ 6 - 1
packages/core/src/job-queue/job-queue.ts

@@ -107,7 +107,12 @@ export class JobQueue<Data extends JobData<Data> = {}> {
                 return new SubscribableJob(job, this.jobQueueStrategy);
             }
         } else {
-            return new SubscribableJob(job, this.jobQueueStrategy);
+            const bufferedJob = new Job({
+                ...job,
+                data: job.data,
+                id: 'buffered',
+            });
+            return new SubscribableJob(bufferedJob, this.jobQueueStrategy);
         }
     }
 }

+ 2 - 1
packages/core/src/plugin/default-search-plugin/fulltext-search.resolver.ts

@@ -104,7 +104,8 @@ export class AdminFulltextSearchResolver implements BaseSearchResolver {
     @Mutation()
     @Allow(Permission.UpdateCatalog, Permission.UpdateProduct)
     async runPendingSearchIndexUpdates(...args: any[]): Promise<any> {
-        await this.searchJobBufferService.runPendingSearchUpdates();
+        // Intentionally not awaiting this method call
+        this.searchJobBufferService.runPendingSearchUpdates();
         return { success: true };
     }
 }