@snabcentr/client-core 2.63.2 → 2.64.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/esm2022/guards/catalog-seo.guard.mjs +71 -0
  2. package/esm2022/guards/index.mjs +2 -1
  3. package/esm2022/guards/sc-id-or-slug.guard.mjs +3 -3
  4. package/esm2022/pagination/services/sc-pagination.service.mjs +3 -3
  5. package/esm2022/pipes/sc-id-or-slug.pipe.mjs +2 -2
  6. package/esm2022/providers/index.mjs +2 -4
  7. package/esm2022/providers/sc-category.providers.mjs +40 -0
  8. package/esm2022/tokens/index.mjs +7 -3
  9. package/esm2022/tokens/sc-api-keys.mjs +1 -1
  10. package/esm2022/tokens/sc-cache-lifetime.mjs +1 -1
  11. package/esm2022/tokens/sc-company-info.mjs +6 -0
  12. package/esm2022/tokens/sc-configurator-components.mjs +1 -1
  13. package/esm2022/tokens/sc-configurator-settings.mjs +1 -1
  14. package/esm2022/tokens/sc-default-page-meta.mjs +5 -1
  15. package/esm2022/tokens/sc-error-handler.mjs +6 -0
  16. package/esm2022/tokens/sc-id-or-slug-in-route.mjs +8 -0
  17. package/esm2022/tokens/sc-product-pagination-options.mjs +22 -0
  18. package/esm2022/tokens/sc-release.mjs +1 -1
  19. package/esm2022/tokens/sc-update-interval.mjs +1 -1
  20. package/esm2022/tokens/sc-urls.mjs +1 -1
  21. package/fesm2022/snabcentr-client-core.mjs +729 -628
  22. package/fesm2022/snabcentr-client-core.mjs.map +1 -1
  23. package/guards/catalog-seo.guard.d.ts +14 -0
  24. package/guards/index.d.ts +1 -0
  25. package/package.json +1 -1
  26. package/pagination/services/sc-pagination.service.d.ts +4 -2
  27. package/providers/index.d.ts +1 -3
  28. package/providers/sc-category.providers.d.ts +11 -0
  29. package/tokens/index.d.ts +6 -2
  30. package/tokens/sc-api-keys.d.ts +1 -1
  31. package/tokens/sc-cache-lifetime.d.ts +1 -1
  32. package/tokens/sc-configurator-components.d.ts +2 -1
  33. package/tokens/sc-configurator-settings.d.ts +1 -1
  34. package/tokens/sc-default-page-meta.d.ts +5 -1
  35. package/tokens/sc-error-handler.d.ts +11 -0
  36. package/tokens/sc-release.d.ts +1 -1
  37. package/tokens/sc-update-interval.d.ts +1 -1
  38. package/tokens/sc-urls.d.ts +1 -1
  39. package/esm2022/providers/sc-company-info.mjs +0 -6
  40. package/esm2022/providers/sc-id-or-slug-in-route.mjs +0 -8
  41. package/esm2022/providers/sc-product-pagination-options.mjs +0 -22
  42. /package/{providers → tokens}/sc-company-info.d.ts +0 -0
  43. /package/{providers → tokens}/sc-id-or-slug-in-route.d.ts +0 -0
  44. /package/{providers → tokens}/sc-product-pagination-options.d.ts +0 -0
@@ -1,12 +1,12 @@
1
1
  import * as i0 from '@angular/core';
2
- import { InjectionToken, inject, PLATFORM_ID, Injectable, Inject, Optional, LOCALE_ID, Pipe, EventEmitter, Component, ChangeDetectionStrategy, HostBinding, Input, NgModule, RendererFactory2 } from '@angular/core';
2
+ import { InjectionToken, inject, PLATFORM_ID, Injectable, Inject, Optional, EventEmitter, LOCALE_ID, Pipe, RendererFactory2, Component, ChangeDetectionStrategy, HostBinding, Input, NgModule } from '@angular/core';
3
3
  import { WA_LOCAL_STORAGE, WA_USER_AGENT, WA_WINDOW } from '@ng-web-apis/common';
4
4
  import { filterByKey, toValue, WA_STORAGE_EVENT, StorageService } from '@ng-web-apis/storage';
5
5
  import * as i1 from 'rxjs';
6
- import { startWith, Subject, ReplaySubject, partition, combineLatest, map, debounceTime, switchMap, of, tap, filter, shareReplay, distinctUntilChanged, distinctUntilKeyChanged, skip, first, BehaviorSubject, materialize, dematerialize, expand, takeWhile, toArray, catchError, throwError, concatMap, finalize, takeUntil, interval, share, scan } from 'rxjs';
6
+ import { startWith, Subject, ReplaySubject, partition, combineLatest, map, debounceTime, switchMap, of, tap, filter, shareReplay, distinctUntilChanged, distinctUntilKeyChanged, skip, first, BehaviorSubject, materialize, dematerialize, expand, takeWhile, toArray, catchError, EMPTY, throwError, concatMap, finalize, takeUntil, interval, share, scan } from 'rxjs';
7
7
  import { isPlatformBrowser, isPlatformServer, DOCUMENT, formatDate } from '@angular/common';
8
8
  import * as i1$1 from '@angular/common/http';
9
- import { HttpContextToken, HttpContext, HttpHeaders, HttpClient, HttpParams, HttpResponse, HttpErrorResponse } from '@angular/common/http';
9
+ import { HttpContextToken, HttpContext, HttpHeaders, HttpClient, HttpParams, HttpErrorResponse, HttpResponse } from '@angular/common/http';
10
10
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
11
11
  import { tuiIsPresent, TuiDay, tuiPure, TUI_TRUE_HANDLER } from '@taiga-ui/cdk';
12
12
  import { tuiCleanObject } from '@taiga-ui/addon-doc/utils';
@@ -14,10 +14,11 @@ import { __decorate } from 'tslib';
14
14
  import * as i2 from '@angular/router';
15
15
  import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
16
16
  import { isString, isMatch, isArray } from 'lodash-es';
17
- import { objectToSnake, objectToCamel, toSnake } from 'ts-case-convert';
18
- import { parse, isValid, format } from 'date-fns';
17
+ import { filter as filter$1, tap as tap$1, map as map$1, catchError as catchError$1 } from 'rxjs/operators';
19
18
  import * as i1$2 from '@angular/platform-browser';
20
19
  import { Meta, Title } from '@angular/platform-browser';
20
+ import { objectToSnake, objectToCamel, toSnake } from 'ts-case-convert';
21
+ import { parse, isValid, format } from 'date-fns';
21
22
 
22
23
  /**
23
24
  * Базовый класс для изображений.
@@ -264,6 +265,11 @@ const SC_AUTH_AS_CLIENT_OPTIONS = new InjectionToken('SC_AUTH_AS_CLIENT_OPTIONS'
264
265
  */
265
266
  const SC_CACHE_LIFETIME = new InjectionToken('ICacheLifetime');
266
267
 
268
+ /**
269
+ * Токен для получения полной информации о компании.
270
+ */
271
+ const SC_COMPANY_INFO = new InjectionToken('SC_COMPANY_INFO');
272
+
267
273
  /**
268
274
  * Токен внедрения названия компании.
269
275
  */
@@ -275,14 +281,35 @@ const SC_COMPANY_NAME = new InjectionToken('COMPANY_NAME');
275
281
  const SC_CONFIGURATOR_COMPONENTS = new InjectionToken('SC_CONFIGURATOR_COMPONENTS');
276
282
 
277
283
  /**
278
- * Токен внедрения моделей настроек конфигураторов по их названию.
284
+ * Токен внедрения формата дат.
279
285
  */
280
- const SC_CONFIGURATOR_SETTINGS = new InjectionToken('SC_CONFIGURATOR_SETTINGS');
286
+ const SC_DATE_FORMAT = new InjectionToken('SC_DATE_FORMAT');
281
287
 
282
288
  /**
283
289
  * Токен внедрения мета-данных страницы по умолчанию.
284
290
  */
285
291
  const SC_DEFAULT_PAGE_META = new InjectionToken('SC_DEFAULT_PAGE_META');
292
+ /**
293
+ * Токен внедрения мета-данных страницы каталога.
294
+ */
295
+ const SC_CATALOG_PAGE_META = new InjectionToken('SC_CATALOG_PAGE_META');
296
+
297
+ /**
298
+ * Токен внедрения обработчика ошибок.
299
+ */
300
+ const ERROR_HANDLER = new InjectionToken('ERROR_HANDLER');
301
+
302
+ /**
303
+ * Токен внедрения моделей настроек конфигураторов по их названию.
304
+ */
305
+ const SC_CONFIGURATOR_SETTINGS = new InjectionToken('SC_CONFIGURATOR_SETTINGS');
306
+
307
+ /**
308
+ * Токен определяющий, идентификатор или символьное обозначение (slug) используется для роутинга и маршрутизации.
309
+ */
310
+ const SC_ID_OR_SLUG_IN_ROUTE = new InjectionToken('SC_ID_OR_SLUG_IN_ROUTE', {
311
+ factory: () => 'id',
312
+ });
286
313
 
287
314
  /**
288
315
  * Токен контекста запроса, указывающий на необходимость скрыть уведомление об ошибке.
@@ -309,6 +336,27 @@ const SC_LINEAR_VALUES_TOKEN = new InjectionToken('SC_LINEAR_VALUES_TOKEN', {
309
336
  */
310
337
  const SC_PATH_IMAGE_NOT_FOUND = new InjectionToken('PATH_IMAGE_NOT_FOUND');
311
338
 
339
+ /**
340
+ * Значения пагинации списка товаров категории по умолчанию.
341
+ */
342
+ const SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS = {
343
+ perPage: 20,
344
+ paginate: true,
345
+ page: 0,
346
+ };
347
+ /**
348
+ * Токен значений пагинации списка товаров в каталоге по умолчанию.
349
+ */
350
+ const SC_PRODUCT_PAGINATION_OPTIONS = new InjectionToken('SC_PRODUCT_PAGINATION_OPTIONS', {
351
+ factory: () => SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS,
352
+ });
353
+ /**
354
+ * Токен {@link EventEmitter} событие нажатия на кнопку "Показать следующие позиции категории".
355
+ */
356
+ const SC_NEXT_PAGE_PAGINATION_CLICK = new InjectionToken('SC_NEXT_PAGE_PAGINATION_CLICK', {
357
+ factory: () => new EventEmitter(),
358
+ });
359
+
312
360
  /**
313
361
  * Токен внедрения информации о релизе.
314
362
  */
@@ -329,11 +377,6 @@ const SC_URLS = new InjectionToken('IUrls');
329
377
  */
330
378
  const SC_FEEDBACK_API = new InjectionToken('SC_FEEDBACK_API');
331
379
 
332
- /**
333
- * Токен внедрения формата дат.
334
- */
335
- const SC_DATE_FORMAT = new InjectionToken('SC_DATE_FORMAT');
336
-
337
380
  /**
338
381
  * Перечисление названий целей метрики используемых для отслеживания действий пользователей.
339
382
  */
@@ -2883,13 +2926,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
2883
2926
  }]
2884
2927
  }] });
2885
2928
 
2886
- /**
2887
- * Токен определяющий, идентификатор или символьное обозначение (slug) используется для роутинга и маршрутизации.
2888
- */
2889
- const SC_ID_OR_SLUG_IN_ROUTE = new InjectionToken('SC_ID_OR_SLUG_IN_ROUTE', {
2890
- factory: () => 'id',
2891
- });
2892
-
2893
2929
  /**
2894
2930
  * Пайп, возвращающий идентификатор или символьное обозначение (slug) исходя из настроек окружения
2895
2931
  */
@@ -3769,25 +3805,36 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
3769
3805
  const SC_IS_HEADER_REQUIRED = new HttpContextToken(() => true);
3770
3806
 
3771
3807
  /**
3772
- * Значения пагинации списка товаров категории по умолчанию.
3808
+ * Токен потока данных о категории.
3773
3809
  */
3774
- const SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS = {
3775
- perPage: 20,
3776
- paginate: true,
3777
- page: 0,
3778
- };
3810
+ const CATEGORY_INFO = new InjectionToken('A stream with current category information');
3779
3811
  /**
3780
- * Токен значений пагинации списка товаров в каталоге по умолчанию.
3812
+ * Фабрика создания потока данных о категории.
3813
+ *
3814
+ * @param paramMap Параметры.
3815
+ * @param paramMap.paramMap Параметры.
3816
+ * @param catalogService Сервис для работы с каталогом.
3817
+ * @param catalogService.paramMap Параметры.
3818
+ * @param errorHandlerComponent Компонент для управления кодом ошибки отображаемой на странице.
3781
3819
  */
3782
- const SC_PRODUCT_PAGINATION_OPTIONS = new InjectionToken('SC_PRODUCT_PAGINATION_OPTIONS', {
3783
- factory: () => SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS,
3784
- });
3820
+ function categoryFactory({ paramMap }, catalogService, errorHandlerComponent) {
3821
+ return paramMap.pipe(map((parameters) => parameters.get('categoryIdOrSlug')), filter(tuiIsPresent), switchMap((categoryId) => catalogService.getCategoryCached$(categoryId).pipe(catchError((error) => {
3822
+ if (error instanceof HttpErrorResponse) {
3823
+ errorHandlerComponent(error.status);
3824
+ }
3825
+ return EMPTY;
3826
+ }), shareReplay())), takeUntilDestroyed());
3827
+ }
3785
3828
  /**
3786
- * Токен {@link EventEmitter} событие нажатия на кнопку "Показать следующие позиции категории".
3829
+ * Провайдеры потока данных о категории.
3787
3830
  */
3788
- const SC_NEXT_PAGE_PAGINATION_CLICK = new InjectionToken('SC_NEXT_PAGE_PAGINATION_CLICK', {
3789
- factory: () => new EventEmitter(),
3790
- });
3831
+ const CATEGORY_PROVIDERS = [
3832
+ {
3833
+ provide: CATEGORY_INFO,
3834
+ deps: [ActivatedRoute, ScCatalogService, ERROR_HANDLER],
3835
+ useFactory: categoryFactory,
3836
+ },
3837
+ ];
3791
3838
 
3792
3839
  /**
3793
3840
  * Сервис поиска по каталогу.
@@ -3965,11 +4012,6 @@ const SC_VIRTUAL_CATEGORY_PROVIDERS = [
3965
4012
  },
3966
4013
  ];
3967
4014
 
3968
- /**
3969
- * Токен для получения полной информации о компании.
3970
- */
3971
- const SC_COMPANY_INFO = new InjectionToken('SC_COMPANY_INFO');
3972
-
3973
4015
  /**
3974
4016
  * Сервис для работы с UTM-меткой страницы.
3975
4017
  */
@@ -4777,85 +4819,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
4777
4819
  args: [SC_URLS]
4778
4820
  }] }] });
4779
4821
 
4780
- /**
4781
- * Сервис аутентификации пользователя на основе ключей, переданных в параметрах запроса.
4782
- */
4783
- class ScAuthAsClientGuard {
4784
- /**
4785
- * Инициализирует экземпляр класса {@link AuthAsClientGuard}.
4786
- *
4787
- * @param authService Сервис аутентификации.
4788
- * @param router Сервис маршрутизации.
4789
- * @param options Параметры авторизации под клиентом.
4790
- */
4791
- constructor(authService, router, options) {
4792
- this.authService = authService;
4793
- this.router = router;
4794
- this.options = options;
4795
- }
4796
- /**
4797
- * Разрешает/запрещает доступ к маршруту.
4798
- *
4799
- * @param route Данные о текущем маршруте.
4800
- */
4801
- // eslint-disable-next-line sonarjs/function-return-type
4802
- canActivate(route) {
4803
- const expiredAt = new Date();
4804
- expiredAt.setMinutes(new Date().getMinutes() + this.options.expiredAtMinute);
4805
- return this.authService.getAuthChange().pipe(first(),
4806
- // Если пользователь авторизирован, то завершаем сеанс.
4807
- concatMap((state) => (state ? this.authService.getSignOut$(false) : of(null))),
4808
- // Обновляем полученные ключи, чтобы они перестали действовать. getRefreshTokenObservable() запишет новые ключи в систему, после чего проложение само запросит нового пользователя.
4809
- concatMap(() => this.authService.getRefreshToken$({
4810
- access: {
4811
- token: route.paramMap.get('atoken') ?? '',
4812
- expiredAt: expiredAt,
4813
- },
4814
- refresh: {
4815
- token: route.paramMap.get('rtoken') ?? '',
4816
- expiredAt: expiredAt,
4817
- },
4818
- })), first(), map(() => this.router.createUrlTree(this.options.urlTree)));
4819
- }
4820
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard, deps: [{ token: ScAuthService }, { token: i2.Router }, { token: SC_AUTH_AS_CLIENT_OPTIONS }], target: i0.ɵɵFactoryTarget.Injectable }); }
4821
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard }); }
4822
- }
4823
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard, decorators: [{
4824
- type: Injectable
4825
- }], ctorParameters: () => [{ type: ScAuthService }, { type: i2.Router }, { type: undefined, decorators: [{
4826
- type: Inject,
4827
- args: [SC_AUTH_AS_CLIENT_OPTIONS]
4828
- }] }] });
4829
-
4830
- /**
4831
- * Страж выполняющий проверку маршрута товара и категории, и редиректа в зависимости от настроек окружения.
4832
- *
4833
- * @param route Сервис предоставляющий доступ к данным о маршруте.
4834
- */
4835
- // eslint-disable-next-line sonarjs/function-return-type
4836
- const ScIdOrSlugGuard = (route) => {
4837
- const { paramMap } = route;
4838
- const categoryIdOrSlug = paramMap.get('categoryIdOrSlug');
4839
- const productIdOrSlug = paramMap.get('productIdOrSlug');
4840
- const idOrSlug = inject(SC_ID_OR_SLUG_IN_ROUTE);
4841
- const router = inject(Router);
4842
- if (categoryIdOrSlug && /^\d+$/.test(categoryIdOrSlug) !== (idOrSlug === 'id')) {
4843
- return inject(ScCatalogService)
4844
- .getCategoryCached$(categoryIdOrSlug)
4845
- .pipe(filter(tuiIsPresent),
4846
- // eslint-disable-next-line security/detect-object-injection
4847
- map((category) => router.createUrlTree(['/catalog', category[idOrSlug]])), catchError(() => of(TUI_TRUE_HANDLER())));
4848
- }
4849
- if (productIdOrSlug && /^\d+$/.test(productIdOrSlug) !== (idOrSlug === 'id')) {
4850
- return inject(ScCatalogService)
4851
- .getProductData$(productIdOrSlug)
4852
- .pipe(filter(tuiIsPresent),
4853
- // eslint-disable-next-line security/detect-object-injection
4854
- map((product) => router.createUrlTree(['/catalog', 'product', product[idOrSlug]])), catchError(() => of(TUI_TRUE_HANDLER())));
4855
- }
4856
- return true;
4857
- };
4858
-
4859
4822
  /**
4860
4823
  * Пайп для формирования полного URI изображения на media сервере.
4861
4824
  */
@@ -4888,175 +4851,576 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
4888
4851
  }] });
4889
4852
 
4890
4853
  /**
4891
- * Класс с вспомогательными методами для работы с изображениями.
4854
+ * Сервис управления SEO-параметрами.
4892
4855
  */
4893
- class ScImageHelper {
4856
+ class ScSeoService {
4857
+ /**
4858
+ * Инициализирует экземпляр класса {@link ScSeoService}.
4859
+ */
4894
4860
  constructor() {
4895
4861
  /**
4896
- * Список ссылок на разделы backend'a.
4862
+ * Событие установки meta-тегов страницы.
4897
4863
  */
4898
- this.mediaImageTransformerPipe = inject(ScMediaImageTransformerPipe);
4864
+ this.isSetMetaTagsEventEmitter = new EventEmitter();
4865
+ /**
4866
+ * Данные о мета-данных страницы по умолчанию.
4867
+ */
4868
+ this.defaultSeo = inject(SC_DEFAULT_PAGE_META);
4869
+ /**
4870
+ * Сервис маршрутизации.
4871
+ */
4872
+ this.router = inject(Router);
4873
+ /**
4874
+ * Список ссылок приложения.
4875
+ */
4876
+ this.urls = inject(SC_URLS);
4877
+ /**
4878
+ * Сервис установки метаданных страницы.
4879
+ */
4880
+ this.metaService = inject(Meta);
4881
+ /**
4882
+ * Сервис управления заголовком страницы.
4883
+ */
4884
+ this.titleService = inject(Title);
4885
+ /**
4886
+ * Селектор группы для устанавливаемых метатегов.
4887
+ */
4888
+ this.dataGroupSelector = 'seo-tags';
4889
+ /**
4890
+ * Объект {@link Document}, предоставляющий доступ к DOM страницы.
4891
+ */
4892
+ this.document = inject(DOCUMENT);
4893
+ /**
4894
+ * Фабрика для создания экземпляров {@link Renderer2}.
4895
+ */
4896
+ this.rendererFactory = inject(RendererFactory2);
4897
+ /**
4898
+ * Экземпляр {@link Renderer2} для безопасной работы с DOM.
4899
+ */
4900
+ this.renderer = this.rendererFactory.createRenderer(null, null);
4901
+ /**
4902
+ * Название компании.
4903
+ */
4904
+ this.companyName = inject(SC_COMPANY_NAME);
4905
+ this.setShareType('website');
4899
4906
  }
4900
4907
  /**
4901
- * Возвращает изображение товара по индексу.
4908
+ * Устанавливает meta-теги.
4902
4909
  *
4903
- * @param product Позиция товара/услуги.
4904
- * @param imgIndex Индекс изображения в массиве.
4905
- * @returns Возвращает изображение товара по индексу. Возвращает пути до изображения 'Товар не найден' {@link pathImageNotFound} если изображения по индексу не найдено.
4910
+ * @param title Заголовок страницы.
4911
+ * @param description Описание страницы.
4912
+ * @param keywords Ключевые слова страницы.
4913
+ * @param emitEventAfterSet Признак того, необходимо ли генерировать событие, после установки тегов. По умолчанию {@link true}.
4914
+ * @param robots Список robots тегов для страницы.
4906
4915
  */
4907
- getImage(product, imgIndex = 0) {
4908
- return {
4909
- image: this.mediaImageTransformerPipe.transform(product.getImage(imgIndex), true),
4910
- alt: `${product.name} (${imgIndex + 1})`,
4911
- imageWebp: this.mediaImageTransformerPipe.transform(product.getImageWebp(imgIndex), false),
4912
- };
4916
+ setPageMetaTags(title = this.defaultSeo.title, description = this.defaultSeo.description, keywords = this.defaultSeo.keywords, emitEventAfterSet = true, robots = ['index', 'follow']) {
4917
+ this.setPageTitle(title);
4918
+ this.setPageMetaDescription(description);
4919
+ this.setPageMetaKeywords(keywords);
4920
+ this.setPageMetaRobots(robots);
4921
+ if (emitEventAfterSet) {
4922
+ this.isSetMetaTagsEventEmitter.emit();
4923
+ }
4913
4924
  }
4914
4925
  /**
4915
- * Возвращает превью-изображение товара по индексу.
4926
+ * Устанавливает Open Graph meta-теги.
4916
4927
  *
4917
- * @param product Позиция товара/услуги.
4918
- * @param previewIndex Индекс превью-изображения в массиве.
4919
- * @returns Возвращает превью-изображение товара по индексу. Возвращает основное изображение если превью-изображения по индексу не найдено.
4928
+ * @param ogTitle Open Graph заголовок.
4929
+ * @param ogDescription Open Graph описание.
4930
+ * @param ogImg Open Graph изображение.
4931
+ * @param emitEventAfterSet Признак того, необходимо ли генерировать событие, после установки тегов. По умолчанию {@link true}.
4920
4932
  */
4921
- getImagePreview(product, previewIndex = 0) {
4933
+ setPageOpenGraphMetaTags(ogTitle = this.defaultSeo.title, ogDescription = this.defaultSeo.description, ogImg = this.urls.logoUrl, emitEventAfterSet = true) {
4934
+ this.setOpenGraphMetaTags(ogTitle, ogDescription, `${this.urls.siteUrl}${this.router.url}`, ogImg);
4935
+ if (emitEventAfterSet) {
4936
+ this.isSetMetaTagsEventEmitter.emit();
4937
+ }
4938
+ }
4939
+ /**
4940
+ * Устанавливает все meta-теги из пришедшего источника. Если какого-то тега нет, будет установлено значение по умолчанию.
4941
+ *
4942
+ * @param resource Источник meta - тегов.
4943
+ * @param img Изображение. Если не пришло, то будет установлено значение по умолчанию.
4944
+ * @param robots Список robots тегов для страницы.
4945
+ */
4946
+ setMetaTagsFromResource(resource, img = this.urls.logoUrl, robots = ['index', 'follow']) {
4947
+ this.setAllPageMetaTags(resource?.title, resource?.description, resource?.keywords, img, resource?.meta, robots);
4948
+ }
4949
+ /**
4950
+ * Устанавливает все meta-теги страницы со значением по умолчанию, внедряя туда заголовок, если он передан.
4951
+ *
4952
+ * @param title Заголовок страницы.
4953
+ * @param robots Список robots тегов для страницы.
4954
+ */
4955
+ setDefaultAllPageMetaTags(title = this.defaultSeo.title, robots = ['index', 'follow']) {
4956
+ this.setAllPageMetaTags(`${title} - ${this.companyName}`, `${title}, ${this.defaultSeo.description}`, undefined, undefined, [], robots);
4957
+ }
4958
+ /**
4959
+ * Устанавливает все meta-теги страницы со значением по умолчанию, внедряя туда заголовок, если он передан. Устанавливает значение "не индексировать" для поисковых роботов.
4960
+ *
4961
+ * @param title Заголовок страницы.
4962
+ */
4963
+ setNoIndexDefaultAllPageMetaTags(title = this.defaultSeo.title) {
4964
+ this.setAllPageMetaTags(`${title} - ${this.companyName}`, `${title}, ${this.defaultSeo.description}`, undefined, undefined, [], ['noindex', 'nofollow', 'noarchive']);
4965
+ }
4966
+ /**
4967
+ * Устанавливает все meta-теги страницы. Если какой-либо из параметров не указан, для него устанавливается значение по умолчанию.
4968
+ *
4969
+ * @param title Заголовок страницы.
4970
+ * @param description Описание страницы.
4971
+ * @param keywords Ключевые слова страницы.
4972
+ * @param img Изображение.
4973
+ * @param meta Массив дополнительных значений метатегов.
4974
+ * @param robots Список robots тегов для страницы.
4975
+ */
4976
+ setAllPageMetaTags(title = this.defaultSeo.title, description = this.defaultSeo.description, keywords = this.defaultSeo.keywords, img = this.urls.logoUrl, meta = [], robots = ['index', 'follow']) {
4977
+ this.removeMetaTags();
4978
+ this.setPageTitle(title);
4979
+ this.setPageMetaDescription(description);
4980
+ this.setPageMetaKeywords(keywords);
4981
+ this.setOpenGraphMetaTags(title, description, `${this.urls.siteUrl}${this.router.url}`, img);
4982
+ meta.forEach((tag) => {
4983
+ this.setPageMetaByName(tag.name, tag.content);
4984
+ });
4985
+ this.setPageMetaRobots(robots);
4986
+ this.isSetMetaTagsEventEmitter.emit();
4987
+ }
4988
+ /**
4989
+ * Устанавливает meta-тег robots для страницы.
4990
+ *
4991
+ * @param robots Список robots тегов для страницы.
4992
+ */
4993
+ setPageMetaRobots(robots) {
4994
+ this.setPageMetaByName('robots', robots.join(', '));
4995
+ }
4996
+ /**
4997
+ * Удаляет все установленные meta-теги.
4998
+ */
4999
+ removeMetaTags() {
5000
+ const tags = this.document.querySelectorAll(`meta[data-group="${this.dataGroupSelector}"]`);
5001
+ tags.forEach((tag) => {
5002
+ this.metaService.removeTagElement(tag);
5003
+ });
5004
+ }
5005
+ /**
5006
+ * Возвращает сгенерированный SEO-resource с указанными параметрами.
5007
+ *
5008
+ * @param seo Данные SEO ресурса.
5009
+ * @param defaultTitle Заголовок страницы используемый в случае отсутствия заголовка в SEO-ресурсе.
5010
+ * @param defaultDescription Описание страницы используемое в случае отсутствия описания в SEO-ресурсе.
5011
+ * @param defaultKeyWords Ключевые слова страницы используемые в случае отсутствия ключевых слов в SEO-ресурсе.
5012
+ */
5013
+ getGenerateSeoResource(seo, defaultTitle, defaultDescription = this.defaultSeo.description, defaultKeyWords = this.defaultSeo.keywords) {
4922
5014
  return {
4923
- image: this.mediaImageTransformerPipe.transform(product.getImagePreview(previewIndex) ?? product.getImage(previewIndex), true),
4924
- alt: `${product.name} (${previewIndex + 1})`,
4925
- imageWebp: this.mediaImageTransformerPipe.transform(product.getImagePreviewWebp(previewIndex) ?? product.getImageWebp(previewIndex), false),
5015
+ title: seo?.title ?? defaultTitle,
5016
+ description: seo?.description ?? defaultDescription,
5017
+ keywords: seo?.keywords ?? defaultKeyWords,
5018
+ meta: seo?.meta,
4926
5019
  };
4927
5020
  }
4928
- getProductImageList(product, useDefaultImage) {
4929
- const images = product.images?.filter((image) => image.image).map((_, index) => this.getImage(product, index));
4930
- if (images?.length) {
4931
- return images;
4932
- }
4933
- if (useDefaultImage) {
4934
- return [new ScImage(this.mediaImageTransformerPipe.transform(undefined, true), product.name)];
5021
+ /**
5022
+ * Устанавливает тег канонической страницы <link rel="canonical" href="..." />.
5023
+ *
5024
+ * @param url URL который необходимо использовать в качестве ссылки.
5025
+ */
5026
+ setCanonicalLink(url) {
5027
+ // Удаляем существующий link canonical.
5028
+ const existingLink = this.document.querySelector('link[rel="canonical"]');
5029
+ if (existingLink?.parentNode) {
5030
+ this.renderer.removeChild(existingLink.parentNode, existingLink);
4935
5031
  }
4936
- return undefined;
5032
+ // Создаём и устанавливаем новый тег.
5033
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
5034
+ const link = this.renderer.createElement('link');
5035
+ this.renderer.setAttribute(link, 'rel', 'canonical');
5036
+ this.renderer.setAttribute(link, 'href', url);
5037
+ this.renderer.appendChild(this.document.head, link);
4937
5038
  }
4938
- getProductImagePreviewList(product, useDefaultImage) {
4939
- const images = product.images?.filter((image) => image.preview).map((_, index) => this.getImagePreview(product, index));
4940
- if (images?.length) {
4941
- return images;
4942
- }
4943
- if (useDefaultImage) {
4944
- return [new ScImage(this.mediaImageTransformerPipe.transform(undefined, true), product.name)];
4945
- }
4946
- return undefined;
5039
+ /**
5040
+ * Устанавливает title-заголовок страницы.
5041
+ *
5042
+ * @param title Заголовок страницы.
5043
+ * @param appendDefaultTitle Флаг необходимости добавить заголовок по умолчанию в конец заголовка страницы.
5044
+ */
5045
+ setPageTitle(title, appendDefaultTitle = false) {
5046
+ this.titleService.setTitle(title + (appendDefaultTitle ? ` - ${this.defaultSeo.title}` : ''));
4947
5047
  }
4948
5048
  /**
4949
- * Возвращает признак того, что файл является изображением.
5049
+ * Устанавливает meta-описание страницы.
4950
5050
  *
4951
- * @param format Формат файла.
5051
+ * @param description Meta-описание страницы.
4952
5052
  */
4953
- // eslint-disable-next-line class-methods-use-this
4954
- isImg(format) {
4955
- return ['jpeg', 'jpg', 'png', 'gif', 'bmp', 'tiff', 'webp'].includes(format);
5053
+ setPageMetaDescription(description) {
5054
+ this.setPageMetaByName('description', description);
4956
5055
  }
4957
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScImageHelper, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
4958
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScImageHelper, providedIn: 'root' }); }
4959
- }
4960
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScImageHelper, decorators: [{
4961
- type: Injectable,
4962
- args: [{
4963
- providedIn: 'root',
4964
- }]
4965
- }] });
4966
-
4967
- /**
4968
- * Клас-помощник для работы со значениями единиц измерения товара.
4969
- */
4970
- class ScUnitsHelper {
4971
5056
  /**
4972
- * Инициирует экземпляр класса {@link ScUnitsHelper}.
5057
+ * Устанавливает meta-ключевые слова страницы.
4973
5058
  *
4974
- * @param linearValues Единицы измерения линейной величины.
5059
+ * @param keywords Meta-ключевые слова страницы.
4975
5060
  */
4976
- constructor(linearValues) {
4977
- this.linearValues = linearValues;
5061
+ setPageMetaKeywords(keywords) {
5062
+ this.setPageMetaByName('keywords', keywords);
4978
5063
  }
4979
5064
  /**
4980
- * Возвращает признак возможности продажи товара на метраж.
5065
+ * Устанавливает Open Graph meta-теги страницы для социальных сетей.
4981
5066
  *
4982
- * @param product Товар для которого нужно проверить возможность продажи на метраж.
5067
+ * @param title Заголовок страницы.
5068
+ * @param description Описание страницы.
5069
+ * @param url Ссылка на страницу.
5070
+ * @param img Изображение.
4983
5071
  */
4984
- productIsMeasurable(product) {
4985
- return this.linearValues.includes(product.unit.name);
5072
+ setOpenGraphMetaTags(title, description, url, img) {
5073
+ this.setOpenGraphMetaByProperty('og:title', title);
5074
+ this.setOpenGraphMetaByProperty('og:url', url);
5075
+ this.setOpenGraphMetaByProperty('og:image', img);
5076
+ this.setOpenGraphMetaByProperty('og:description', description);
5077
+ this.setOpenGraphMetaByProperty('og:type', 'website');
4986
5078
  }
4987
5079
  /**
4988
- * Возвращает кратность количества для товара.
5080
+ * Устанавливает meta-тег страницы с указанным именем.
5081
+ * Будет создан или обновлён заголовок вида `<meta name="{name}" content="{content}" />`
4989
5082
  *
4990
- * @param product Товар для которого нужно вернуть кратность количества.
5083
+ * @param name Название заголовка.
5084
+ * @param content Содержимое заголовка.
4991
5085
  */
4992
- productMultiplicity(product) {
4993
- return product.minCount && !this.linearValues.includes(product.unit.name) ? product.minCount : 1;
5086
+ setPageMetaByName(name, content) {
5087
+ this.metaService.updateTag({ name: name, content: content, 'data-group': this.dataGroupSelector });
4994
5088
  }
4995
5089
  /**
4996
- * Возвращает значение кратности, для проверки кратности количества товара.
5090
+ * Устанавливает Open Graph meta-тег по свойству атрибута property.
4997
5091
  *
4998
- * @param product Товар для которого нужно вернуть значение кратность.
5092
+ * @param property Свойство атрибута.
5093
+ * @param content Содержимое тега.
4999
5094
  */
5000
- productStepForValidator(product) {
5001
- return product.ignoreMinCountCheck ? 1 : this.productMultiplicity(product);
5095
+ setOpenGraphMetaByProperty(property, content) {
5096
+ this.metaService.updateTag({ property: property, content: content, 'data-group': this.dataGroupSelector });
5002
5097
  }
5003
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUnitsHelper, deps: [{ token: SC_LINEAR_VALUES_TOKEN }], target: i0.ɵɵFactoryTarget.Injectable }); }
5004
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUnitsHelper, providedIn: 'root' }); }
5098
+ /**
5099
+ * Устанавливает Open Graph мета-тег типа объекта.
5100
+ *
5101
+ * @param type Тип объекта.
5102
+ */
5103
+ setShareType(type) {
5104
+ this.setOpenGraphMetaByProperty('og:type', type);
5105
+ }
5106
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSeoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5107
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSeoService, providedIn: 'root' }); }
5005
5108
  }
5006
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUnitsHelper, decorators: [{
5109
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSeoService, decorators: [{
5007
5110
  type: Injectable,
5008
5111
  args: [{
5009
5112
  providedIn: 'root',
5010
5113
  }]
5011
- }], ctorParameters: () => [{ type: undefined, decorators: [{
5012
- type: Inject,
5013
- args: [SC_LINEAR_VALUES_TOKEN]
5014
- }] }] });
5114
+ }], ctorParameters: () => [] });
5015
5115
 
5016
5116
  /**
5017
- * Модель данных настроек кэширования запросов.
5117
+ * Устанавливает SEO-теги для страниц каталога.
5118
+ *
5119
+ * @param seoService Сервис для работы с SEO.
5120
+ * @param name Название страницы.
5121
+ * @param seo SEO-теги.
5122
+ * @param image Ссылка на основное изображение.
5123
+ */
5124
+ const setSeoTags = (seoService, name, seo, image) => {
5125
+ const companyInfo = inject(SC_COMPANY_INFO);
5126
+ const catalogMeta = inject(SC_CATALOG_PAGE_META);
5127
+ const seoResource = seoService.getGenerateSeoResource(seo, `${name} - Купить в ${companyInfo.name}`, `${name} - Купить по выгодным ценам в ${companyInfo.name}`, `${name}, ${catalogMeta.keywords}`);
5128
+ seoService.setMetaTagsFromResource(seoResource, image);
5129
+ };
5130
+ /**
5131
+ * Создает SEO-guard для указанного сервиса и метода получения данных.
5132
+ *
5133
+ * @param getDataFunction Функция для получения данных из сервиса.
5134
+ * @param setCanonical Признак необходимости установить на странице каноническую ссылку.
5135
+ * @returns Функция-guard.
5018
5136
  */
5019
- class ScCacheSettings {
5020
- /**
5021
- * Инициализирует экземпляр класса {@link ScCacheSettings}.
5022
- *
5023
- * @param isCached Признак необходимости кэшировать ответ на запрос.
5024
- * @param cacheLifeTime Время жизни закэшированного ответа.
5025
- */
5026
- constructor(isCached, cacheLifeTime) {
5027
- this.isCached = isCached;
5028
- this.cacheLifeTime = cacheLifeTime;
5029
- }
5030
- }
5031
-
5137
+ const createSeoGuard = (getDataFunction, setCanonical = false) => {
5138
+ // eslint-disable-next-line sonarjs/function-return-type
5139
+ return ({ paramMap }, state) => {
5140
+ const seoService = inject(ScSeoService);
5141
+ const mediaImageTransformerPipe = inject(ScMediaImageTransformerPipe);
5142
+ const recId = paramMap.get('productIdOrSlug') ?? paramMap.get('categoryIdOrSlug') ?? paramMap.get('categorySlug');
5143
+ if (!recId) {
5144
+ return false;
5145
+ }
5146
+ return getDataFunction(recId).pipe(filter$1(tuiIsPresent), tap$1(({ id, name, seo, image, slug }) => {
5147
+ setSeoTags(seoService, name, seo, mediaImageTransformerPipe.transform(image, true));
5148
+ const idOrSlugInRoute = inject(SC_ID_OR_SLUG_IN_ROUTE);
5149
+ // В том случае, если используется slug для формирования ссылок, то необходимо сформировать кононическую ссылку
5150
+ // на страницу в которой используется slug (а не id).
5151
+ if (setCanonical && idOrSlugInRoute === 'slug' && id && slug) {
5152
+ const canonicalPath = state.url
5153
+ .split('/')
5154
+ .map((segment) => (segment === id.toString() ? slug : segment))
5155
+ .join('/');
5156
+ const { siteUrl } = inject(SC_URLS);
5157
+ seoService.setCanonicalLink(`${siteUrl}${canonicalPath}`);
5158
+ }
5159
+ }), map$1(TUI_TRUE_HANDLER), catchError$1(() => of(true)), takeUntilDestroyed());
5160
+ };
5161
+ };
5032
5162
  /**
5033
- * Токен настроек кэширования запроса.
5163
+ * Устанавливает SEO-теги для страницы продукта.
5034
5164
  */
5035
- const SC_CACHE_SETTINGS = new HttpContextToken(() => new ScCacheSettings(false, 0));
5036
-
5165
+ const ScProductSeoGuard = createSeoGuard((recId) => inject(ScCatalogService).getProductDataCached$(recId), true);
5037
5166
  /**
5038
- * Токен списка URL, которые нужно кешировать для гостя.
5167
+ * Устанавливает SEO-теги для страницы виртуальной категории.
5039
5168
  */
5040
- const SC_GUEST_ENDPOINTS_TOKEN = new InjectionToken('SC_GUEST_ENDPOINTS_TOKEN', {
5041
- factory: () => [],
5042
- });
5043
-
5169
+ const ScVirtualCategorySeoGuard = createSeoGuard((recId) => inject(ScCatalogService).getVirtualCategoryCached$(recId));
5044
5170
  /**
5045
- * Токен имени параметра, при котором кешируются запросы у гостя.
5171
+ * Устанавливает SEO-теги для страницы категории.
5046
5172
  */
5047
- const SC_GUEST_PARAMETER_NAME_TOKEN = new InjectionToken('SC_GUEST_PARAMETER_NAME_TOKEN', {
5048
- factory: () => '',
5049
- });
5173
+ const ScCategorySeoGuard = createSeoGuard((recId) => inject(ScCatalogService).getCategoryCached$(recId), true);
5050
5174
 
5051
5175
  /**
5052
- * Перехватчик запросов для реализации аутентификации.
5176
+ * Сервис аутентификации пользователя на основе ключей, переданных в параметрах запроса.
5053
5177
  */
5054
- class ScAuthInterceptor {
5178
+ class ScAuthAsClientGuard {
5055
5179
  /**
5056
- * Инициализирует экземпляр класса {@link ScAuthInterceptor}.
5180
+ * Инициализирует экземпляр класса {@link AuthAsClientGuard}.
5057
5181
  *
5058
- * @param tokenService Сервис ключей аутентификации.
5059
- */
5182
+ * @param authService Сервис аутентификации.
5183
+ * @param router Сервис маршрутизации.
5184
+ * @param options Параметры авторизации под клиентом.
5185
+ */
5186
+ constructor(authService, router, options) {
5187
+ this.authService = authService;
5188
+ this.router = router;
5189
+ this.options = options;
5190
+ }
5191
+ /**
5192
+ * Разрешает/запрещает доступ к маршруту.
5193
+ *
5194
+ * @param route Данные о текущем маршруте.
5195
+ */
5196
+ // eslint-disable-next-line sonarjs/function-return-type
5197
+ canActivate(route) {
5198
+ const expiredAt = new Date();
5199
+ expiredAt.setMinutes(new Date().getMinutes() + this.options.expiredAtMinute);
5200
+ return this.authService.getAuthChange().pipe(first(),
5201
+ // Если пользователь авторизирован, то завершаем сеанс.
5202
+ concatMap((state) => (state ? this.authService.getSignOut$(false) : of(null))),
5203
+ // Обновляем полученные ключи, чтобы они перестали действовать. getRefreshTokenObservable() запишет новые ключи в систему, после чего проложение само запросит нового пользователя.
5204
+ concatMap(() => this.authService.getRefreshToken$({
5205
+ access: {
5206
+ token: route.paramMap.get('atoken') ?? '',
5207
+ expiredAt: expiredAt,
5208
+ },
5209
+ refresh: {
5210
+ token: route.paramMap.get('rtoken') ?? '',
5211
+ expiredAt: expiredAt,
5212
+ },
5213
+ })), first(), map(() => this.router.createUrlTree(this.options.urlTree)));
5214
+ }
5215
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard, deps: [{ token: ScAuthService }, { token: i2.Router }, { token: SC_AUTH_AS_CLIENT_OPTIONS }], target: i0.ɵɵFactoryTarget.Injectable }); }
5216
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard }); }
5217
+ }
5218
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard, decorators: [{
5219
+ type: Injectable
5220
+ }], ctorParameters: () => [{ type: ScAuthService }, { type: i2.Router }, { type: undefined, decorators: [{
5221
+ type: Inject,
5222
+ args: [SC_AUTH_AS_CLIENT_OPTIONS]
5223
+ }] }] });
5224
+
5225
+ /**
5226
+ * Страж выполняющий проверку маршрута товара и категории, и редиректа в зависимости от настроек окружения.
5227
+ *
5228
+ * @param route Сервис предоставляющий доступ к данным о маршруте.
5229
+ */
5230
+ // eslint-disable-next-line sonarjs/function-return-type
5231
+ const ScIdOrSlugGuard = (route) => {
5232
+ const { paramMap } = route;
5233
+ const categoryIdOrSlug = paramMap.get('categoryIdOrSlug');
5234
+ const productIdOrSlug = paramMap.get('productIdOrSlug');
5235
+ const idOrSlug = inject(SC_ID_OR_SLUG_IN_ROUTE);
5236
+ const router = inject(Router);
5237
+ if (categoryIdOrSlug && /^\d+$/.test(categoryIdOrSlug) !== (idOrSlug === 'id')) {
5238
+ return inject(ScCatalogService)
5239
+ .getCategoryCached$(categoryIdOrSlug)
5240
+ .pipe(filter(tuiIsPresent),
5241
+ // eslint-disable-next-line security/detect-object-injection
5242
+ map((category) => router.createUrlTree(['/catalog', category[idOrSlug]])), catchError(() => of(TUI_TRUE_HANDLER())));
5243
+ }
5244
+ if (productIdOrSlug && /^\d+$/.test(productIdOrSlug) !== (idOrSlug === 'id')) {
5245
+ return inject(ScCatalogService)
5246
+ .getProductData$(productIdOrSlug)
5247
+ .pipe(filter(tuiIsPresent),
5248
+ // eslint-disable-next-line security/detect-object-injection
5249
+ map((product) => router.createUrlTree(['/catalog', 'product', product[idOrSlug]])), catchError(() => of(TUI_TRUE_HANDLER())));
5250
+ }
5251
+ return true;
5252
+ };
5253
+
5254
+ /**
5255
+ * Класс с вспомогательными методами для работы с изображениями.
5256
+ */
5257
+ class ScImageHelper {
5258
+ constructor() {
5259
+ /**
5260
+ * Список ссылок на разделы backend'a.
5261
+ */
5262
+ this.mediaImageTransformerPipe = inject(ScMediaImageTransformerPipe);
5263
+ }
5264
+ /**
5265
+ * Возвращает изображение товара по индексу.
5266
+ *
5267
+ * @param product Позиция товара/услуги.
5268
+ * @param imgIndex Индекс изображения в массиве.
5269
+ * @returns Возвращает изображение товара по индексу. Возвращает пути до изображения 'Товар не найден' {@link pathImageNotFound} если изображения по индексу не найдено.
5270
+ */
5271
+ getImage(product, imgIndex = 0) {
5272
+ return {
5273
+ image: this.mediaImageTransformerPipe.transform(product.getImage(imgIndex), true),
5274
+ alt: `${product.name} (${imgIndex + 1})`,
5275
+ imageWebp: this.mediaImageTransformerPipe.transform(product.getImageWebp(imgIndex), false),
5276
+ };
5277
+ }
5278
+ /**
5279
+ * Возвращает превью-изображение товара по индексу.
5280
+ *
5281
+ * @param product Позиция товара/услуги.
5282
+ * @param previewIndex Индекс превью-изображения в массиве.
5283
+ * @returns Возвращает превью-изображение товара по индексу. Возвращает основное изображение если превью-изображения по индексу не найдено.
5284
+ */
5285
+ getImagePreview(product, previewIndex = 0) {
5286
+ return {
5287
+ image: this.mediaImageTransformerPipe.transform(product.getImagePreview(previewIndex) ?? product.getImage(previewIndex), true),
5288
+ alt: `${product.name} (${previewIndex + 1})`,
5289
+ imageWebp: this.mediaImageTransformerPipe.transform(product.getImagePreviewWebp(previewIndex) ?? product.getImageWebp(previewIndex), false),
5290
+ };
5291
+ }
5292
+ getProductImageList(product, useDefaultImage) {
5293
+ const images = product.images?.filter((image) => image.image).map((_, index) => this.getImage(product, index));
5294
+ if (images?.length) {
5295
+ return images;
5296
+ }
5297
+ if (useDefaultImage) {
5298
+ return [new ScImage(this.mediaImageTransformerPipe.transform(undefined, true), product.name)];
5299
+ }
5300
+ return undefined;
5301
+ }
5302
+ getProductImagePreviewList(product, useDefaultImage) {
5303
+ const images = product.images?.filter((image) => image.preview).map((_, index) => this.getImagePreview(product, index));
5304
+ if (images?.length) {
5305
+ return images;
5306
+ }
5307
+ if (useDefaultImage) {
5308
+ return [new ScImage(this.mediaImageTransformerPipe.transform(undefined, true), product.name)];
5309
+ }
5310
+ return undefined;
5311
+ }
5312
+ /**
5313
+ * Возвращает признак того, что файл является изображением.
5314
+ *
5315
+ * @param format Формат файла.
5316
+ */
5317
+ // eslint-disable-next-line class-methods-use-this
5318
+ isImg(format) {
5319
+ return ['jpeg', 'jpg', 'png', 'gif', 'bmp', 'tiff', 'webp'].includes(format);
5320
+ }
5321
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScImageHelper, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
5322
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScImageHelper, providedIn: 'root' }); }
5323
+ }
5324
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScImageHelper, decorators: [{
5325
+ type: Injectable,
5326
+ args: [{
5327
+ providedIn: 'root',
5328
+ }]
5329
+ }] });
5330
+
5331
+ /**
5332
+ * Клас-помощник для работы со значениями единиц измерения товара.
5333
+ */
5334
+ class ScUnitsHelper {
5335
+ /**
5336
+ * Инициирует экземпляр класса {@link ScUnitsHelper}.
5337
+ *
5338
+ * @param linearValues Единицы измерения линейной величины.
5339
+ */
5340
+ constructor(linearValues) {
5341
+ this.linearValues = linearValues;
5342
+ }
5343
+ /**
5344
+ * Возвращает признак возможности продажи товара на метраж.
5345
+ *
5346
+ * @param product Товар для которого нужно проверить возможность продажи на метраж.
5347
+ */
5348
+ productIsMeasurable(product) {
5349
+ return this.linearValues.includes(product.unit.name);
5350
+ }
5351
+ /**
5352
+ * Возвращает кратность количества для товара.
5353
+ *
5354
+ * @param product Товар для которого нужно вернуть кратность количества.
5355
+ */
5356
+ productMultiplicity(product) {
5357
+ return product.minCount && !this.linearValues.includes(product.unit.name) ? product.minCount : 1;
5358
+ }
5359
+ /**
5360
+ * Возвращает значение кратности, для проверки кратности количества товара.
5361
+ *
5362
+ * @param product Товар для которого нужно вернуть значение кратность.
5363
+ */
5364
+ productStepForValidator(product) {
5365
+ return product.ignoreMinCountCheck ? 1 : this.productMultiplicity(product);
5366
+ }
5367
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUnitsHelper, deps: [{ token: SC_LINEAR_VALUES_TOKEN }], target: i0.ɵɵFactoryTarget.Injectable }); }
5368
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUnitsHelper, providedIn: 'root' }); }
5369
+ }
5370
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUnitsHelper, decorators: [{
5371
+ type: Injectable,
5372
+ args: [{
5373
+ providedIn: 'root',
5374
+ }]
5375
+ }], ctorParameters: () => [{ type: undefined, decorators: [{
5376
+ type: Inject,
5377
+ args: [SC_LINEAR_VALUES_TOKEN]
5378
+ }] }] });
5379
+
5380
+ /**
5381
+ * Модель данных настроек кэширования запросов.
5382
+ */
5383
+ class ScCacheSettings {
5384
+ /**
5385
+ * Инициализирует экземпляр класса {@link ScCacheSettings}.
5386
+ *
5387
+ * @param isCached Признак необходимости кэшировать ответ на запрос.
5388
+ * @param cacheLifeTime Время жизни закэшированного ответа.
5389
+ */
5390
+ constructor(isCached, cacheLifeTime) {
5391
+ this.isCached = isCached;
5392
+ this.cacheLifeTime = cacheLifeTime;
5393
+ }
5394
+ }
5395
+
5396
+ /**
5397
+ * Токен настроек кэширования запроса.
5398
+ */
5399
+ const SC_CACHE_SETTINGS = new HttpContextToken(() => new ScCacheSettings(false, 0));
5400
+
5401
+ /**
5402
+ * Токен списка URL, которые нужно кешировать для гостя.
5403
+ */
5404
+ const SC_GUEST_ENDPOINTS_TOKEN = new InjectionToken('SC_GUEST_ENDPOINTS_TOKEN', {
5405
+ factory: () => [],
5406
+ });
5407
+
5408
+ /**
5409
+ * Токен имени параметра, при котором кешируются запросы у гостя.
5410
+ */
5411
+ const SC_GUEST_PARAMETER_NAME_TOKEN = new InjectionToken('SC_GUEST_PARAMETER_NAME_TOKEN', {
5412
+ factory: () => '',
5413
+ });
5414
+
5415
+ /**
5416
+ * Перехватчик запросов для реализации аутентификации.
5417
+ */
5418
+ class ScAuthInterceptor {
5419
+ /**
5420
+ * Инициализирует экземпляр класса {@link ScAuthInterceptor}.
5421
+ *
5422
+ * @param tokenService Сервис ключей аутентификации.
5423
+ */
5060
5424
  constructor(tokenService) {
5061
5425
  this.tokenService = tokenService;
5062
5426
  }
@@ -6685,458 +7049,195 @@ class ScReclamationService {
6685
7049
  this.urls = urls;
6686
7050
  }
6687
7051
  /**
6688
- * Создаёт запрос новую рекламацию.
6689
- *
6690
- * @param newReclamation Данные новой рекламации.
6691
- */
6692
- createReclamation$(newReclamation) {
6693
- return this.http.post(`${this.urls.apiUrl}/reclamations`, newReclamation);
6694
- }
6695
- /**
6696
- * Возвращает список рекламаций с пагинацией.
6697
- *
6698
- * @param params Параметры запроса получения рекламаций.
6699
- */
6700
- getReclamations$(params) {
6701
- return this.http.get(`${this.urls.apiUrl}/reclamations`, { params: params });
6702
- }
6703
- /**
6704
- * Возвращает полную информацию о рекламации.
6705
- *
6706
- * @param reclamationId Идентификатор рекламации.
6707
- */
6708
- getReclamation$(reclamationId) {
6709
- return this.http.get(`${this.urls.apiUrl}/reclamations/${reclamationId}`);
6710
- }
6711
- /**
6712
- * Возвращает файл рекламации в формате Blob.
6713
- *
6714
- * @param reclamationId Идентификатор рекламации.
6715
- */
6716
- downloadReclamation$(reclamationId) {
6717
- return this.http
6718
- .get(`${this.urls.apiUrl}/reclamations/${reclamationId}/download`, { responseType: 'blob' })
6719
- .pipe(map((reclamation) => new Blob([reclamation], { type: 'application/pdf' })));
6720
- }
6721
- /**
6722
- * Отправляет новое сообщение рекламации.
6723
- *
6724
- * @param reclamationId Идентификатор рекламации.
6725
- * @param newMessage Новое сообщение рекламации.
6726
- */
6727
- sendMessages$(reclamationId, newMessage) {
6728
- return this.http.post(`${this.urls.apiUrl}/reclamations/${reclamationId}/messages`, newMessage);
6729
- }
6730
- /**
6731
- * Выполняет запрос удаления рекламации.
6732
- *
6733
- * @param reclamationId Идентификатор рекламации.
6734
- */
6735
- deleteReclamation$(reclamationId) {
6736
- return this.http.delete(`${this.urls.apiUrl}/reclamations/${reclamationId}`);
6737
- }
6738
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScReclamationService, deps: [{ token: i1$1.HttpClient }, { token: SC_URLS }], target: i0.ɵɵFactoryTarget.Injectable }); }
6739
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScReclamationService, providedIn: 'root' }); }
6740
- }
6741
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScReclamationService, decorators: [{
6742
- type: Injectable,
6743
- args: [{
6744
- providedIn: 'root',
6745
- }]
6746
- }], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: undefined, decorators: [{
6747
- type: Inject,
6748
- args: [SC_URLS]
6749
- }] }] });
6750
-
6751
- /**
6752
- * Компонент структурированных данных.
6753
- */
6754
- class ScJsonLdComponent {
6755
- /**
6756
- * Инициализирует экземпляр класса {@link ScJsonLdComponent}.
6757
- *
6758
- * @param sanitizer Объект DomSanitizer для безопасной обработки HTML и стилей.
6759
- */
6760
- constructor(sanitizer) {
6761
- this.sanitizer = sanitizer;
6762
- }
6763
- /**
6764
- * Объект структурированных данных о товаре.
6765
- */
6766
- set json(currentValue) {
6767
- this.jsonLD = this.getSafeHTML(currentValue);
6768
- }
6769
- /**
6770
- * Возвращает безопасный html код.
6771
- *
6772
- * @param json JSON данные.
6773
- */
6774
- getSafeHTML(json) {
6775
- // eslint-disable-next-line sonarjs/no-angular-bypass-sanitization
6776
- return this.sanitizer.bypassSecurityTrustHtml(
6777
- // eslint-disable-next-line sonarjs/no-nested-template-literals
6778
- `<script type="application/ld+json">${json ? JSON.stringify(json, null, 2).replaceAll('</script>', String.raw `<\/script>`) : ''}</script>`);
6779
- }
6780
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdComponent, deps: [{ token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
6781
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.12", type: ScJsonLdComponent, selector: "sc-json-ld", inputs: { json: "json" }, host: { properties: { "innerHTML": "this.jsonLD" } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
6782
- }
6783
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdComponent, decorators: [{
6784
- type: Component,
6785
- args: [{
6786
- selector: 'sc-json-ld',
6787
- template: '',
6788
- changeDetection: ChangeDetectionStrategy.OnPush,
6789
- }]
6790
- }], ctorParameters: () => [{ type: i1$2.DomSanitizer }], propDecorators: { jsonLD: [{
6791
- type: HostBinding,
6792
- args: ['innerHTML']
6793
- }], json: [{
6794
- type: Input
6795
- }] } });
6796
-
6797
- /**
6798
- * Модуль структурированных данных.
6799
- */
6800
- class ScJsonLdModule {
6801
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
6802
- static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdModule, declarations: [ScJsonLdComponent], exports: [ScJsonLdComponent] }); }
6803
- static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdModule }); }
6804
- }
6805
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdModule, decorators: [{
6806
- type: NgModule,
6807
- args: [{
6808
- declarations: [ScJsonLdComponent],
6809
- exports: [ScJsonLdComponent],
6810
- }]
6811
- }] });
6812
-
6813
- /**
6814
- * Перечисление типов подсказок запросов.
6815
- */
6816
- // eslint-disable-next-line no-shadow
6817
- var ScISuggestionType;
6818
- (function (ScISuggestionType) {
6819
- /**
6820
- * Подсказки по фио.
6821
- */
6822
- ScISuggestionType["fio"] = "fio";
6823
- /**
6824
- * Подсказки по адресам.
6825
- */
6826
- ScISuggestionType["address"] = "address";
6827
- /**
6828
- * Подсказки по организациям.
6829
- */
6830
- ScISuggestionType["organization"] = "organization";
6831
- /**
6832
- * Подсказки по банкам.
6833
- */
6834
- ScISuggestionType["bank"] = "bank";
6835
- /**
6836
- * Подсказки по email.
6837
- */
6838
- ScISuggestionType["email"] = "email";
6839
- })(ScISuggestionType || (ScISuggestionType = {}));
6840
-
6841
- /**
6842
- * Сервис работы с API подсказок.
6843
- */
6844
- class ScSuggestionService {
6845
- /**
6846
- * Инициализирует экземпляр класса {@link ScSuggestionService}.
6847
- *
6848
- * @param http Сервис для выполнения HTTP-запросов.
6849
- * @param urls Список ссылок на разделы backend'a.
6850
- */
6851
- constructor(http, urls) {
6852
- this.http = http;
6853
- this.urls = urls;
6854
- }
6855
- /**
6856
- * Возвращает {@link Observable} подсказок по указанному запросу.
6857
- *
6858
- * @param query Запрос, для которого нужно получить подсказки.
6859
- * @param type Тип подсказок.
6860
- */
6861
- getData(query, type = ScISuggestionType.address) {
6862
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
6863
- return this.http.get(`${this.urls.apiUrl}/suggestions/${[type]}`, { params: { query: query } });
6864
- }
6865
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSuggestionService, deps: [{ token: i1$1.HttpClient }, { token: SC_URLS }], target: i0.ɵɵFactoryTarget.Injectable }); }
6866
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSuggestionService, providedIn: 'root' }); }
6867
- }
6868
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSuggestionService, decorators: [{
6869
- type: Injectable,
6870
- args: [{
6871
- providedIn: 'root',
6872
- }]
6873
- }], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: undefined, decorators: [{
6874
- type: Inject,
6875
- args: [SC_URLS]
6876
- }] }] });
6877
-
6878
- /**
6879
- * Сервис управления SEO-параметрами.
6880
- */
6881
- class ScSeoService {
6882
- /**
6883
- * Инициализирует экземпляр класса {@link ScSeoService}.
6884
- */
6885
- constructor() {
6886
- /**
6887
- * Событие установки meta-тегов страницы.
6888
- */
6889
- this.isSetMetaTagsEventEmitter = new EventEmitter();
6890
- /**
6891
- * Данные о мета-данных страницы по умолчанию.
6892
- */
6893
- this.defaultSeo = inject(SC_DEFAULT_PAGE_META);
6894
- /**
6895
- * Сервис маршрутизации.
6896
- */
6897
- this.router = inject(Router);
6898
- /**
6899
- * Список ссылок приложения.
6900
- */
6901
- this.urls = inject(SC_URLS);
6902
- /**
6903
- * Сервис установки метаданных страницы.
6904
- */
6905
- this.metaService = inject(Meta);
6906
- /**
6907
- * Сервис управления заголовком страницы.
6908
- */
6909
- this.titleService = inject(Title);
6910
- /**
6911
- * Селектор группы для устанавливаемых метатегов.
6912
- */
6913
- this.dataGroupSelector = 'seo-tags';
6914
- /**
6915
- * Объект {@link Document}, предоставляющий доступ к DOM страницы.
6916
- */
6917
- this.document = inject(DOCUMENT);
6918
- /**
6919
- * Фабрика для создания экземпляров {@link Renderer2}.
6920
- */
6921
- this.rendererFactory = inject(RendererFactory2);
6922
- /**
6923
- * Экземпляр {@link Renderer2} для безопасной работы с DOM.
6924
- */
6925
- this.renderer = this.rendererFactory.createRenderer(null, null);
6926
- /**
6927
- * Название компании.
6928
- */
6929
- this.companyName = inject(SC_COMPANY_NAME);
6930
- this.setShareType('website');
6931
- }
6932
- /**
6933
- * Устанавливает meta-теги.
6934
- *
6935
- * @param title Заголовок страницы.
6936
- * @param description Описание страницы.
6937
- * @param keywords Ключевые слова страницы.
6938
- * @param emitEventAfterSet Признак того, необходимо ли генерировать событие, после установки тегов. По умолчанию {@link true}.
6939
- * @param robots Список robots тегов для страницы.
6940
- */
6941
- setPageMetaTags(title = this.defaultSeo.title, description = this.defaultSeo.description, keywords = this.defaultSeo.keywords, emitEventAfterSet = true, robots = ['index', 'follow']) {
6942
- this.setPageTitle(title);
6943
- this.setPageMetaDescription(description);
6944
- this.setPageMetaKeywords(keywords);
6945
- this.setPageMetaRobots(robots);
6946
- if (emitEventAfterSet) {
6947
- this.isSetMetaTagsEventEmitter.emit();
6948
- }
6949
- }
6950
- /**
6951
- * Устанавливает Open Graph meta-теги.
6952
- *
6953
- * @param ogTitle Open Graph заголовок.
6954
- * @param ogDescription Open Graph описание.
6955
- * @param ogImg Open Graph изображение.
6956
- * @param emitEventAfterSet Признак того, необходимо ли генерировать событие, после установки тегов. По умолчанию {@link true}.
6957
- */
6958
- setPageOpenGraphMetaTags(ogTitle = this.defaultSeo.title, ogDescription = this.defaultSeo.description, ogImg = this.urls.logoUrl, emitEventAfterSet = true) {
6959
- this.setOpenGraphMetaTags(ogTitle, ogDescription, `${this.urls.siteUrl}${this.router.url}`, ogImg);
6960
- if (emitEventAfterSet) {
6961
- this.isSetMetaTagsEventEmitter.emit();
6962
- }
6963
- }
6964
- /**
6965
- * Устанавливает все meta-теги из пришедшего источника. Если какого-то тега нет, будет установлено значение по умолчанию.
7052
+ * Создаёт запрос новую рекламацию.
6966
7053
  *
6967
- * @param resource Источник meta - тегов.
6968
- * @param img Изображение. Если не пришло, то будет установлено значение по умолчанию.
6969
- * @param robots Список robots тегов для страницы.
7054
+ * @param newReclamation Данные новой рекламации.
6970
7055
  */
6971
- setMetaTagsFromResource(resource, img = this.urls.logoUrl, robots = ['index', 'follow']) {
6972
- this.setAllPageMetaTags(resource?.title, resource?.description, resource?.keywords, img, resource?.meta, robots);
7056
+ createReclamation$(newReclamation) {
7057
+ return this.http.post(`${this.urls.apiUrl}/reclamations`, newReclamation);
6973
7058
  }
6974
7059
  /**
6975
- * Устанавливает все meta-теги страницы со значением по умолчанию, внедряя туда заголовок, если он передан.
7060
+ * Возвращает список рекламаций с пагинацией.
6976
7061
  *
6977
- * @param title Заголовок страницы.
6978
- * @param robots Список robots тегов для страницы.
7062
+ * @param params Параметры запроса получения рекламаций.
6979
7063
  */
6980
- setDefaultAllPageMetaTags(title = this.defaultSeo.title, robots = ['index', 'follow']) {
6981
- this.setAllPageMetaTags(`${title} - ${this.companyName}`, `${title}, ${this.defaultSeo.description}`, undefined, undefined, [], robots);
7064
+ getReclamations$(params) {
7065
+ return this.http.get(`${this.urls.apiUrl}/reclamations`, { params: params });
6982
7066
  }
6983
7067
  /**
6984
- * Устанавливает все meta-теги страницы со значением по умолчанию, внедряя туда заголовок, если он передан. Устанавливает значение "не индексировать" для поисковых роботов.
7068
+ * Возвращает полную информацию о рекламации.
6985
7069
  *
6986
- * @param title Заголовок страницы.
7070
+ * @param reclamationId Идентификатор рекламации.
6987
7071
  */
6988
- setNoIndexDefaultAllPageMetaTags(title = this.defaultSeo.title) {
6989
- this.setAllPageMetaTags(`${title} - ${this.companyName}`, `${title}, ${this.defaultSeo.description}`, undefined, undefined, [], ['noindex', 'nofollow', 'noarchive']);
7072
+ getReclamation$(reclamationId) {
7073
+ return this.http.get(`${this.urls.apiUrl}/reclamations/${reclamationId}`);
6990
7074
  }
6991
7075
  /**
6992
- * Устанавливает все meta-теги страницы. Если какой-либо из параметров не указан, для него устанавливается значение по умолчанию.
7076
+ * Возвращает файл рекламации в формате Blob.
6993
7077
  *
6994
- * @param title Заголовок страницы.
6995
- * @param description Описание страницы.
6996
- * @param keywords Ключевые слова страницы.
6997
- * @param img Изображение.
6998
- * @param meta Массив дополнительных значений метатегов.
6999
- * @param robots Список robots тегов для страницы.
7078
+ * @param reclamationId Идентификатор рекламации.
7000
7079
  */
7001
- setAllPageMetaTags(title = this.defaultSeo.title, description = this.defaultSeo.description, keywords = this.defaultSeo.keywords, img = this.urls.logoUrl, meta = [], robots = ['index', 'follow']) {
7002
- this.removeMetaTags();
7003
- this.setPageTitle(title);
7004
- this.setPageMetaDescription(description);
7005
- this.setPageMetaKeywords(keywords);
7006
- this.setOpenGraphMetaTags(title, description, `${this.urls.siteUrl}${this.router.url}`, img);
7007
- meta.forEach((tag) => {
7008
- this.setPageMetaByName(tag.name, tag.content);
7009
- });
7010
- this.setPageMetaRobots(robots);
7011
- this.isSetMetaTagsEventEmitter.emit();
7080
+ downloadReclamation$(reclamationId) {
7081
+ return this.http
7082
+ .get(`${this.urls.apiUrl}/reclamations/${reclamationId}/download`, { responseType: 'blob' })
7083
+ .pipe(map((reclamation) => new Blob([reclamation], { type: 'application/pdf' })));
7012
7084
  }
7013
7085
  /**
7014
- * Устанавливает meta-тег robots для страницы.
7086
+ * Отправляет новое сообщение рекламации.
7015
7087
  *
7016
- * @param robots Список robots тегов для страницы.
7088
+ * @param reclamationId Идентификатор рекламации.
7089
+ * @param newMessage Новое сообщение рекламации.
7017
7090
  */
7018
- setPageMetaRobots(robots) {
7019
- this.setPageMetaByName('robots', robots.join(', '));
7091
+ sendMessages$(reclamationId, newMessage) {
7092
+ return this.http.post(`${this.urls.apiUrl}/reclamations/${reclamationId}/messages`, newMessage);
7020
7093
  }
7021
7094
  /**
7022
- * Удаляет все установленные meta-теги.
7095
+ * Выполняет запрос удаления рекламации.
7096
+ *
7097
+ * @param reclamationId Идентификатор рекламации.
7023
7098
  */
7024
- removeMetaTags() {
7025
- const tags = this.document.querySelectorAll(`meta[data-group="${this.dataGroupSelector}"]`);
7026
- tags.forEach((tag) => {
7027
- this.metaService.removeTagElement(tag);
7028
- });
7099
+ deleteReclamation$(reclamationId) {
7100
+ return this.http.delete(`${this.urls.apiUrl}/reclamations/${reclamationId}`);
7029
7101
  }
7102
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScReclamationService, deps: [{ token: i1$1.HttpClient }, { token: SC_URLS }], target: i0.ɵɵFactoryTarget.Injectable }); }
7103
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScReclamationService, providedIn: 'root' }); }
7104
+ }
7105
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScReclamationService, decorators: [{
7106
+ type: Injectable,
7107
+ args: [{
7108
+ providedIn: 'root',
7109
+ }]
7110
+ }], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: undefined, decorators: [{
7111
+ type: Inject,
7112
+ args: [SC_URLS]
7113
+ }] }] });
7114
+
7115
+ /**
7116
+ * Компонент структурированных данных.
7117
+ */
7118
+ class ScJsonLdComponent {
7030
7119
  /**
7031
- * Возвращает сгенерированный SEO-resource с указанными параметрами.
7120
+ * Инициализирует экземпляр класса {@link ScJsonLdComponent}.
7032
7121
  *
7033
- * @param seo Данные SEO ресурса.
7034
- * @param defaultTitle Заголовок страницы используемый в случае отсутствия заголовка в SEO-ресурсе.
7035
- * @param defaultDescription Описание страницы используемое в случае отсутствия описания в SEO-ресурсе.
7036
- * @param defaultKeyWords Ключевые слова страницы используемые в случае отсутствия ключевых слов в SEO-ресурсе.
7122
+ * @param sanitizer Объект DomSanitizer для безопасной обработки HTML и стилей.
7037
7123
  */
7038
- getGenerateSeoResource(seo, defaultTitle, defaultDescription = this.defaultSeo.description, defaultKeyWords = this.defaultSeo.keywords) {
7039
- return {
7040
- title: seo?.title ?? defaultTitle,
7041
- description: seo?.description ?? defaultDescription,
7042
- keywords: seo?.keywords ?? defaultKeyWords,
7043
- meta: seo?.meta,
7044
- };
7124
+ constructor(sanitizer) {
7125
+ this.sanitizer = sanitizer;
7045
7126
  }
7046
7127
  /**
7047
- * Устанавливает тег канонической страницы <link rel="canonical" href="..." />.
7048
- *
7049
- * @param url URL который необходимо использовать в качестве ссылки.
7128
+ * Объект структурированных данных о товаре.
7050
7129
  */
7051
- setCanonicalLink(url) {
7052
- // Удаляем существующий link canonical.
7053
- const existingLink = this.document.querySelector('link[rel="canonical"]');
7054
- if (existingLink?.parentNode) {
7055
- this.renderer.removeChild(existingLink.parentNode, existingLink);
7056
- }
7057
- // Создаём и устанавливаем новый тег.
7058
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
7059
- const link = this.renderer.createElement('link');
7060
- this.renderer.setAttribute(link, 'rel', 'canonical');
7061
- this.renderer.setAttribute(link, 'href', url);
7062
- this.renderer.appendChild(this.document.head, link);
7130
+ set json(currentValue) {
7131
+ this.jsonLD = this.getSafeHTML(currentValue);
7063
7132
  }
7064
7133
  /**
7065
- * Устанавливает title-заголовок страницы.
7134
+ * Возвращает безопасный html код.
7066
7135
  *
7067
- * @param title Заголовок страницы.
7068
- * @param appendDefaultTitle Флаг необходимости добавить заголовок по умолчанию в конец заголовка страницы.
7136
+ * @param json JSON данные.
7069
7137
  */
7070
- setPageTitle(title, appendDefaultTitle = false) {
7071
- this.titleService.setTitle(title + (appendDefaultTitle ? ` - ${this.defaultSeo.title}` : ''));
7138
+ getSafeHTML(json) {
7139
+ // eslint-disable-next-line sonarjs/no-angular-bypass-sanitization
7140
+ return this.sanitizer.bypassSecurityTrustHtml(
7141
+ // eslint-disable-next-line sonarjs/no-nested-template-literals
7142
+ `<script type="application/ld+json">${json ? JSON.stringify(json, null, 2).replaceAll('</script>', String.raw `<\/script>`) : ''}</script>`);
7072
7143
  }
7144
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdComponent, deps: [{ token: i1$2.DomSanitizer }], target: i0.ɵɵFactoryTarget.Component }); }
7145
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.12", type: ScJsonLdComponent, selector: "sc-json-ld", inputs: { json: "json" }, host: { properties: { "innerHTML": "this.jsonLD" } }, ngImport: i0, template: '', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
7146
+ }
7147
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdComponent, decorators: [{
7148
+ type: Component,
7149
+ args: [{
7150
+ selector: 'sc-json-ld',
7151
+ template: '',
7152
+ changeDetection: ChangeDetectionStrategy.OnPush,
7153
+ }]
7154
+ }], ctorParameters: () => [{ type: i1$2.DomSanitizer }], propDecorators: { jsonLD: [{
7155
+ type: HostBinding,
7156
+ args: ['innerHTML']
7157
+ }], json: [{
7158
+ type: Input
7159
+ }] } });
7160
+
7161
+ /**
7162
+ * Модуль структурированных данных.
7163
+ */
7164
+ class ScJsonLdModule {
7165
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
7166
+ static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdModule, declarations: [ScJsonLdComponent], exports: [ScJsonLdComponent] }); }
7167
+ static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdModule }); }
7168
+ }
7169
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScJsonLdModule, decorators: [{
7170
+ type: NgModule,
7171
+ args: [{
7172
+ declarations: [ScJsonLdComponent],
7173
+ exports: [ScJsonLdComponent],
7174
+ }]
7175
+ }] });
7176
+
7177
+ /**
7178
+ * Перечисление типов подсказок запросов.
7179
+ */
7180
+ // eslint-disable-next-line no-shadow
7181
+ var ScISuggestionType;
7182
+ (function (ScISuggestionType) {
7073
7183
  /**
7074
- * Устанавливает meta-описание страницы.
7075
- *
7076
- * @param description Meta-описание страницы.
7184
+ * Подсказки по фио.
7077
7185
  */
7078
- setPageMetaDescription(description) {
7079
- this.setPageMetaByName('description', description);
7080
- }
7186
+ ScISuggestionType["fio"] = "fio";
7081
7187
  /**
7082
- * Устанавливает meta-ключевые слова страницы.
7083
- *
7084
- * @param keywords Meta-ключевые слова страницы.
7188
+ * Подсказки по адресам.
7085
7189
  */
7086
- setPageMetaKeywords(keywords) {
7087
- this.setPageMetaByName('keywords', keywords);
7088
- }
7190
+ ScISuggestionType["address"] = "address";
7089
7191
  /**
7090
- * Устанавливает Open Graph meta-теги страницы для социальных сетей.
7091
- *
7092
- * @param title Заголовок страницы.
7093
- * @param description Описание страницы.
7094
- * @param url Ссылка на страницу.
7095
- * @param img Изображение.
7192
+ * Подсказки по организациям.
7096
7193
  */
7097
- setOpenGraphMetaTags(title, description, url, img) {
7098
- this.setOpenGraphMetaByProperty('og:title', title);
7099
- this.setOpenGraphMetaByProperty('og:url', url);
7100
- this.setOpenGraphMetaByProperty('og:image', img);
7101
- this.setOpenGraphMetaByProperty('og:description', description);
7102
- this.setOpenGraphMetaByProperty('og:type', 'website');
7103
- }
7194
+ ScISuggestionType["organization"] = "organization";
7104
7195
  /**
7105
- * Устанавливает meta-тег страницы с указанным именем.
7106
- * Будет создан или обновлён заголовок вида `<meta name="{name}" content="{content}" />`
7107
- *
7108
- * @param name Название заголовка.
7109
- * @param content Содержимое заголовка.
7196
+ * Подсказки по банкам.
7110
7197
  */
7111
- setPageMetaByName(name, content) {
7112
- this.metaService.updateTag({ name: name, content: content, 'data-group': this.dataGroupSelector });
7113
- }
7198
+ ScISuggestionType["bank"] = "bank";
7114
7199
  /**
7115
- * Устанавливает Open Graph meta-тег по свойству атрибута property.
7200
+ * Подсказки по email.
7201
+ */
7202
+ ScISuggestionType["email"] = "email";
7203
+ })(ScISuggestionType || (ScISuggestionType = {}));
7204
+
7205
+ /**
7206
+ * Сервис работы с API подсказок.
7207
+ */
7208
+ class ScSuggestionService {
7209
+ /**
7210
+ * Инициализирует экземпляр класса {@link ScSuggestionService}.
7116
7211
  *
7117
- * @param property Свойство атрибута.
7118
- * @param content Содержимое тега.
7212
+ * @param http Сервис для выполнения HTTP-запросов.
7213
+ * @param urls Список ссылок на разделы backend'a.
7119
7214
  */
7120
- setOpenGraphMetaByProperty(property, content) {
7121
- this.metaService.updateTag({ property: property, content: content, 'data-group': this.dataGroupSelector });
7215
+ constructor(http, urls) {
7216
+ this.http = http;
7217
+ this.urls = urls;
7122
7218
  }
7123
7219
  /**
7124
- * Устанавливает Open Graph мета-тег типа объекта.
7220
+ * Возвращает {@link Observable} подсказок по указанному запросу.
7125
7221
  *
7126
- * @param type Тип объекта.
7222
+ * @param query Запрос, для которого нужно получить подсказки.
7223
+ * @param type Тип подсказок.
7127
7224
  */
7128
- setShareType(type) {
7129
- this.setOpenGraphMetaByProperty('og:type', type);
7225
+ getData(query, type = ScISuggestionType.address) {
7226
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
7227
+ return this.http.get(`${this.urls.apiUrl}/suggestions/${[type]}`, { params: { query: query } });
7130
7228
  }
7131
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSeoService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
7132
- static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSeoService, providedIn: 'root' }); }
7229
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSuggestionService, deps: [{ token: i1$1.HttpClient }, { token: SC_URLS }], target: i0.ɵɵFactoryTarget.Injectable }); }
7230
+ static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSuggestionService, providedIn: 'root' }); }
7133
7231
  }
7134
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSeoService, decorators: [{
7232
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSuggestionService, decorators: [{
7135
7233
  type: Injectable,
7136
7234
  args: [{
7137
7235
  providedIn: 'root',
7138
7236
  }]
7139
- }], ctorParameters: () => [] });
7237
+ }], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: undefined, decorators: [{
7238
+ type: Inject,
7239
+ args: [SC_URLS]
7240
+ }] }] });
7140
7241
 
7141
7242
  /**
7142
7243
  * Сервис, содержащий вспомогательные методы для работы с телефонными номерами.
@@ -7456,5 +7557,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
7456
7557
  * Generated bundle index. Do not edit.
7457
7558
  */
7458
7559
 
7459
- export { EMPTY_CART, IS_BROWSER, IS_RUNNING_ON_TERMINAL, IS_SERVER, RESPONSE, SC_ACCESS_AUTH_TOKEN_STORAGE_KEY, SC_API_KEYS, SC_AUTH_ADD_HEADER_REQUIRED, SC_AUTH_AS_CLIENT_DEFAULT_OPTIONS, SC_AUTH_AS_CLIENT_OPTIONS, SC_CACHE_LIFETIME, SC_CACHE_SETTINGS, SC_COMPANY_INFO, SC_COMPANY_NAME, SC_CONFIGURATOR_COMPONENTS, SC_CONFIGURATOR_SETTINGS, SC_COUNT_FIRST_DISCOUNTED_PRODUCTS, SC_COUNT_LAST_NEWS, SC_DATE_FORMAT, SC_DEFAULT_PAGE_META, SC_FEEDBACK_API, SC_GUEST_ENDPOINTS_TOKEN, SC_GUEST_PARAMETER_NAME_TOKEN, SC_GUEST_TOKEN_STORAGE_KEY, SC_ID_OR_SLUG_IN_ROUTE, SC_IS_HEADER_REQUIRED, SC_IS_HIDDEN_ERROR_ALERT, SC_IS_HIDDEN_ERROR_ALERT_HTTP_CONTEXT, SC_IS_LOGOUT_REQUEST, SC_IS_REFRESH_REQUIRED, SC_LINEAR_VALUES, SC_LINEAR_VALUES_TOKEN, SC_MAX_LENGTH_SEARCH_TERM, SC_MIN_LENGTH_SEARCH_TERM, SC_NEXT_PAGE_PAGINATION_CLICK, SC_PATH_IMAGE_NOT_FOUND, SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS, SC_PRODUCT_PAGINATION_OPTIONS, SC_REFRESH_AUTH_TOKEN_STORAGE_KEY, SC_RELEASE, SC_UPDATE_INTERVAL, SC_URLS, SC_USER_INFO, SC_VACANCIES_DATA_SOURCE, SC_VIRTUAL_CATEGORY_INFO, SC_VIRTUAL_CATEGORY_PROVIDERS, SEARCH_TERM, SEARCH_TERM_PROVIDERS, ScAuthAsClientGuard, ScAuthInterceptor, ScAuthService, ScBanner, ScBannerService, ScCacheInterceptor, ScCacheSettings, ScCachedData, ScCachedItem, ScCart, ScCartItem, ScCartService, ScCatalogFilterService, ScCatalogFormat, ScCatalogService, ScCategory, ScClientType, ScConfiguratorService, ScContactsService, ScContragentService, ScConvertInterceptor, ScConvertersService, ScDateFormatInterceptor, ScDeliveryAddressService, ScDeliveryCost, ScDeliveryType, ScDocumentInfoNode, ScDocumentInfoTypesEnum, ScErrorsInterceptor, ScFavoriteService, ScFeedbackForms, ScFeedbackService, ScFilesService, ScFrequentlyAskedQuestionsService, ScGuestInterceptor, ScISalesDirectionCart, ScISuggestionType, ScIconTypesEnum, ScIdOrSlugGuard, ScIdOrSlugPipe, ScImage, ScImageHelper, ScJsonLdComponent, ScJsonLdModule, ScLocationsService, ScMediaImageTransformerPipe, ScMimeTypes, ScNews, ScNewsService, ScNotificationActionTypes, ScNotificationLevelNames, ScNotificationsService, ScOpfList, ScOptionsInterceptor, ScOrder, ScOrderShort, ScOrderStateStatus, ScOrdersService, ScPaginationService, ScPaymentStatus, ScPaymentType, ScPhoneService, ScProduct, ScProductTileType, ScQuestionnaireService, ScQuestionnaireStatusEnum, ScReclamationService, ScReclamationStatus, ScRecommendationService, ScReferenceName, ScReferencesService, ScRequisitesService, ScRouteKeys, ScSearchService, ScSeoResource, ScSeoService, ScSocialType, ScSuggestionService, ScSum, ScTokenService, ScUIService, ScUTMService, ScUnitsHelper, ScUploadedFile, ScUser, ScUserMetadata, ScUserMetrikaGoalsEnum, ScUserMetrikaService, ScUserService, ScUserType, ScVCardService, ScVacanciesList, ScVacanciesService, ScVacancy, ScVerificationService, ScVirtualCategory, ScWarehouseService, TERMINAL_PROVIDERS, USER_AGENT_TERMINAL, filterChangedByKey, runningOnTerminalFactory, searchTermFactory };
7560
+ export { CATEGORY_INFO, CATEGORY_PROVIDERS, EMPTY_CART, ERROR_HANDLER, IS_BROWSER, IS_RUNNING_ON_TERMINAL, IS_SERVER, RESPONSE, SC_ACCESS_AUTH_TOKEN_STORAGE_KEY, SC_API_KEYS, SC_AUTH_ADD_HEADER_REQUIRED, SC_AUTH_AS_CLIENT_DEFAULT_OPTIONS, SC_AUTH_AS_CLIENT_OPTIONS, SC_CACHE_LIFETIME, SC_CACHE_SETTINGS, SC_CATALOG_PAGE_META, SC_COMPANY_INFO, SC_COMPANY_NAME, SC_CONFIGURATOR_COMPONENTS, SC_CONFIGURATOR_SETTINGS, SC_COUNT_FIRST_DISCOUNTED_PRODUCTS, SC_COUNT_LAST_NEWS, SC_DATE_FORMAT, SC_DEFAULT_PAGE_META, SC_FEEDBACK_API, SC_GUEST_ENDPOINTS_TOKEN, SC_GUEST_PARAMETER_NAME_TOKEN, SC_GUEST_TOKEN_STORAGE_KEY, SC_ID_OR_SLUG_IN_ROUTE, SC_IS_HEADER_REQUIRED, SC_IS_HIDDEN_ERROR_ALERT, SC_IS_HIDDEN_ERROR_ALERT_HTTP_CONTEXT, SC_IS_LOGOUT_REQUEST, SC_IS_REFRESH_REQUIRED, SC_LINEAR_VALUES, SC_LINEAR_VALUES_TOKEN, SC_MAX_LENGTH_SEARCH_TERM, SC_MIN_LENGTH_SEARCH_TERM, SC_NEXT_PAGE_PAGINATION_CLICK, SC_PATH_IMAGE_NOT_FOUND, SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS, SC_PRODUCT_PAGINATION_OPTIONS, SC_REFRESH_AUTH_TOKEN_STORAGE_KEY, SC_RELEASE, SC_UPDATE_INTERVAL, SC_URLS, SC_USER_INFO, SC_VACANCIES_DATA_SOURCE, SC_VIRTUAL_CATEGORY_INFO, SC_VIRTUAL_CATEGORY_PROVIDERS, SEARCH_TERM, SEARCH_TERM_PROVIDERS, ScAuthAsClientGuard, ScAuthInterceptor, ScAuthService, ScBanner, ScBannerService, ScCacheInterceptor, ScCacheSettings, ScCachedData, ScCachedItem, ScCart, ScCartItem, ScCartService, ScCatalogFilterService, ScCatalogFormat, ScCatalogService, ScCategory, ScCategorySeoGuard, ScClientType, ScConfiguratorService, ScContactsService, ScContragentService, ScConvertInterceptor, ScConvertersService, ScDateFormatInterceptor, ScDeliveryAddressService, ScDeliveryCost, ScDeliveryType, ScDocumentInfoNode, ScDocumentInfoTypesEnum, ScErrorsInterceptor, ScFavoriteService, ScFeedbackForms, ScFeedbackService, ScFilesService, ScFrequentlyAskedQuestionsService, ScGuestInterceptor, ScISalesDirectionCart, ScISuggestionType, ScIconTypesEnum, ScIdOrSlugGuard, ScIdOrSlugPipe, ScImage, ScImageHelper, ScJsonLdComponent, ScJsonLdModule, ScLocationsService, ScMediaImageTransformerPipe, ScMimeTypes, ScNews, ScNewsService, ScNotificationActionTypes, ScNotificationLevelNames, ScNotificationsService, ScOpfList, ScOptionsInterceptor, ScOrder, ScOrderShort, ScOrderStateStatus, ScOrdersService, ScPaginationService, ScPaymentStatus, ScPaymentType, ScPhoneService, ScProduct, ScProductSeoGuard, ScProductTileType, ScQuestionnaireService, ScQuestionnaireStatusEnum, ScReclamationService, ScReclamationStatus, ScRecommendationService, ScReferenceName, ScReferencesService, ScRequisitesService, ScRouteKeys, ScSearchService, ScSeoResource, ScSeoService, ScSocialType, ScSuggestionService, ScSum, ScTokenService, ScUIService, ScUTMService, ScUnitsHelper, ScUploadedFile, ScUser, ScUserMetadata, ScUserMetrikaGoalsEnum, ScUserMetrikaService, ScUserService, ScUserType, ScVCardService, ScVacanciesList, ScVacanciesService, ScVacancy, ScVerificationService, ScVirtualCategory, ScVirtualCategorySeoGuard, ScWarehouseService, TERMINAL_PROVIDERS, USER_AGENT_TERMINAL, filterChangedByKey, runningOnTerminalFactory, searchTermFactory };
7460
7561
  //# sourceMappingURL=snabcentr-client-core.mjs.map