@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.
- package/esm2022/guards/catalog-seo.guard.mjs +71 -0
- package/esm2022/guards/index.mjs +2 -1
- package/esm2022/guards/sc-id-or-slug.guard.mjs +3 -3
- package/esm2022/pagination/services/sc-pagination.service.mjs +3 -3
- package/esm2022/pipes/sc-id-or-slug.pipe.mjs +2 -2
- package/esm2022/providers/index.mjs +2 -4
- package/esm2022/providers/sc-category.providers.mjs +40 -0
- package/esm2022/tokens/index.mjs +7 -3
- package/esm2022/tokens/sc-api-keys.mjs +1 -1
- package/esm2022/tokens/sc-cache-lifetime.mjs +1 -1
- package/esm2022/tokens/sc-company-info.mjs +6 -0
- package/esm2022/tokens/sc-configurator-components.mjs +1 -1
- package/esm2022/tokens/sc-configurator-settings.mjs +1 -1
- package/esm2022/tokens/sc-default-page-meta.mjs +5 -1
- package/esm2022/tokens/sc-error-handler.mjs +6 -0
- package/esm2022/tokens/sc-id-or-slug-in-route.mjs +8 -0
- package/esm2022/tokens/sc-product-pagination-options.mjs +22 -0
- package/esm2022/tokens/sc-release.mjs +1 -1
- package/esm2022/tokens/sc-update-interval.mjs +1 -1
- package/esm2022/tokens/sc-urls.mjs +1 -1
- package/fesm2022/snabcentr-client-core.mjs +729 -628
- package/fesm2022/snabcentr-client-core.mjs.map +1 -1
- package/guards/catalog-seo.guard.d.ts +14 -0
- package/guards/index.d.ts +1 -0
- package/package.json +1 -1
- package/pagination/services/sc-pagination.service.d.ts +4 -2
- package/providers/index.d.ts +1 -3
- package/providers/sc-category.providers.d.ts +11 -0
- package/tokens/index.d.ts +6 -2
- package/tokens/sc-api-keys.d.ts +1 -1
- package/tokens/sc-cache-lifetime.d.ts +1 -1
- package/tokens/sc-configurator-components.d.ts +2 -1
- package/tokens/sc-configurator-settings.d.ts +1 -1
- package/tokens/sc-default-page-meta.d.ts +5 -1
- package/tokens/sc-error-handler.d.ts +11 -0
- package/tokens/sc-release.d.ts +1 -1
- package/tokens/sc-update-interval.d.ts +1 -1
- package/tokens/sc-urls.d.ts +1 -1
- package/esm2022/providers/sc-company-info.mjs +0 -6
- package/esm2022/providers/sc-id-or-slug-in-route.mjs +0 -8
- package/esm2022/providers/sc-product-pagination-options.mjs +0 -22
- /package/{providers → tokens}/sc-company-info.d.ts +0 -0
- /package/{providers → tokens}/sc-id-or-slug-in-route.d.ts +0 -0
- /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,
|
|
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,
|
|
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 {
|
|
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
|
|
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
|
|
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
|
-
|
|
3783
|
-
|
|
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
|
-
*
|
|
3829
|
+
* Провайдеры потока данных о категории.
|
|
3787
3830
|
*/
|
|
3788
|
-
const
|
|
3789
|
-
|
|
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
|
|
4856
|
+
class ScSeoService {
|
|
4857
|
+
/**
|
|
4858
|
+
* Инициализирует экземпляр класса {@link ScSeoService}.
|
|
4859
|
+
*/
|
|
4894
4860
|
constructor() {
|
|
4895
4861
|
/**
|
|
4896
|
-
*
|
|
4862
|
+
* Событие установки meta-тегов страницы.
|
|
4897
4863
|
*/
|
|
4898
|
-
this.
|
|
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
|
|
4904
|
-
* @param
|
|
4905
|
-
* @
|
|
4910
|
+
* @param title Заголовок страницы.
|
|
4911
|
+
* @param description Описание страницы.
|
|
4912
|
+
* @param keywords Ключевые слова страницы.
|
|
4913
|
+
* @param emitEventAfterSet Признак того, необходимо ли генерировать событие, после установки тегов. По умолчанию {@link true}.
|
|
4914
|
+
* @param robots Список robots тегов для страницы.
|
|
4906
4915
|
*/
|
|
4907
|
-
|
|
4908
|
-
|
|
4909
|
-
|
|
4910
|
-
|
|
4911
|
-
|
|
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
|
|
4918
|
-
* @param
|
|
4919
|
-
* @
|
|
4928
|
+
* @param ogTitle Open Graph заголовок.
|
|
4929
|
+
* @param ogDescription Open Graph описание.
|
|
4930
|
+
* @param ogImg Open Graph изображение.
|
|
4931
|
+
* @param emitEventAfterSet Признак того, необходимо ли генерировать событие, после установки тегов. По умолчанию {@link true}.
|
|
4920
4932
|
*/
|
|
4921
|
-
|
|
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
|
-
|
|
4924
|
-
|
|
4925
|
-
|
|
5015
|
+
title: seo?.title ?? defaultTitle,
|
|
5016
|
+
description: seo?.description ?? defaultDescription,
|
|
5017
|
+
keywords: seo?.keywords ?? defaultKeyWords,
|
|
5018
|
+
meta: seo?.meta,
|
|
4926
5019
|
};
|
|
4927
5020
|
}
|
|
4928
|
-
|
|
4929
|
-
|
|
4930
|
-
|
|
4931
|
-
|
|
4932
|
-
|
|
4933
|
-
|
|
4934
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4939
|
-
|
|
4940
|
-
|
|
4941
|
-
|
|
4942
|
-
|
|
4943
|
-
|
|
4944
|
-
|
|
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
|
|
5051
|
+
* @param description Meta-описание страницы.
|
|
4952
5052
|
*/
|
|
4953
|
-
|
|
4954
|
-
|
|
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
|
-
*
|
|
5057
|
+
* Устанавливает meta-ключевые слова страницы.
|
|
4973
5058
|
*
|
|
4974
|
-
* @param
|
|
5059
|
+
* @param keywords Meta-ключевые слова страницы.
|
|
4975
5060
|
*/
|
|
4976
|
-
|
|
4977
|
-
this.
|
|
5061
|
+
setPageMetaKeywords(keywords) {
|
|
5062
|
+
this.setPageMetaByName('keywords', keywords);
|
|
4978
5063
|
}
|
|
4979
5064
|
/**
|
|
4980
|
-
*
|
|
5065
|
+
* Устанавливает Open Graph meta-теги страницы для социальных сетей.
|
|
4981
5066
|
*
|
|
4982
|
-
* @param
|
|
5067
|
+
* @param title Заголовок страницы.
|
|
5068
|
+
* @param description Описание страницы.
|
|
5069
|
+
* @param url Ссылка на страницу.
|
|
5070
|
+
* @param img Изображение.
|
|
4983
5071
|
*/
|
|
4984
|
-
|
|
4985
|
-
|
|
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
|
|
5083
|
+
* @param name Название заголовка.
|
|
5084
|
+
* @param content Содержимое заголовка.
|
|
4991
5085
|
*/
|
|
4992
|
-
|
|
4993
|
-
|
|
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
|
|
5092
|
+
* @param property Свойство атрибута.
|
|
5093
|
+
* @param content Содержимое тега.
|
|
4999
5094
|
*/
|
|
5000
|
-
|
|
5001
|
-
|
|
5095
|
+
setOpenGraphMetaByProperty(property, content) {
|
|
5096
|
+
this.metaService.updateTag({ property: property, content: content, 'data-group': this.dataGroupSelector });
|
|
5002
5097
|
}
|
|
5003
|
-
|
|
5004
|
-
|
|
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:
|
|
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: () => [
|
|
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
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
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
|
|
5036
|
-
|
|
5165
|
+
const ScProductSeoGuard = createSeoGuard((recId) => inject(ScCatalogService).getProductDataCached$(recId), true);
|
|
5037
5166
|
/**
|
|
5038
|
-
*
|
|
5167
|
+
* Устанавливает SEO-теги для страницы виртуальной категории.
|
|
5039
5168
|
*/
|
|
5040
|
-
const
|
|
5041
|
-
factory: () => [],
|
|
5042
|
-
});
|
|
5043
|
-
|
|
5169
|
+
const ScVirtualCategorySeoGuard = createSeoGuard((recId) => inject(ScCatalogService).getVirtualCategoryCached$(recId));
|
|
5044
5170
|
/**
|
|
5045
|
-
*
|
|
5171
|
+
* Устанавливает SEO-теги для страницы категории.
|
|
5046
5172
|
*/
|
|
5047
|
-
const
|
|
5048
|
-
factory: () => '',
|
|
5049
|
-
});
|
|
5173
|
+
const ScCategorySeoGuard = createSeoGuard((recId) => inject(ScCatalogService).getCategoryCached$(recId), true);
|
|
5050
5174
|
|
|
5051
5175
|
/**
|
|
5052
|
-
*
|
|
5176
|
+
* Сервис аутентификации пользователя на основе ключей, переданных в параметрах запроса.
|
|
5053
5177
|
*/
|
|
5054
|
-
class
|
|
5178
|
+
class ScAuthAsClientGuard {
|
|
5055
5179
|
/**
|
|
5056
|
-
* Инициализирует экземпляр класса {@link
|
|
5180
|
+
* Инициализирует экземпляр класса {@link AuthAsClientGuard}.
|
|
5057
5181
|
*
|
|
5058
|
-
* @param
|
|
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
|
|
6968
|
-
* @param img Изображение. Если не пришло, то будет установлено значение по умолчанию.
|
|
6969
|
-
* @param robots Список robots тегов для страницы.
|
|
7054
|
+
* @param newReclamation Данные новой рекламации.
|
|
6970
7055
|
*/
|
|
6971
|
-
|
|
6972
|
-
this.
|
|
7056
|
+
createReclamation$(newReclamation) {
|
|
7057
|
+
return this.http.post(`${this.urls.apiUrl}/reclamations`, newReclamation);
|
|
6973
7058
|
}
|
|
6974
7059
|
/**
|
|
6975
|
-
*
|
|
7060
|
+
* Возвращает список рекламаций с пагинацией.
|
|
6976
7061
|
*
|
|
6977
|
-
* @param
|
|
6978
|
-
* @param robots Список robots тегов для страницы.
|
|
7062
|
+
* @param params Параметры запроса получения рекламаций.
|
|
6979
7063
|
*/
|
|
6980
|
-
|
|
6981
|
-
this.
|
|
7064
|
+
getReclamations$(params) {
|
|
7065
|
+
return this.http.get(`${this.urls.apiUrl}/reclamations`, { params: params });
|
|
6982
7066
|
}
|
|
6983
7067
|
/**
|
|
6984
|
-
*
|
|
7068
|
+
* Возвращает полную информацию о рекламации.
|
|
6985
7069
|
*
|
|
6986
|
-
* @param
|
|
7070
|
+
* @param reclamationId Идентификатор рекламации.
|
|
6987
7071
|
*/
|
|
6988
|
-
|
|
6989
|
-
this.
|
|
7072
|
+
getReclamation$(reclamationId) {
|
|
7073
|
+
return this.http.get(`${this.urls.apiUrl}/reclamations/${reclamationId}`);
|
|
6990
7074
|
}
|
|
6991
7075
|
/**
|
|
6992
|
-
*
|
|
7076
|
+
* Возвращает файл рекламации в формате Blob.
|
|
6993
7077
|
*
|
|
6994
|
-
* @param
|
|
6995
|
-
* @param description Описание страницы.
|
|
6996
|
-
* @param keywords Ключевые слова страницы.
|
|
6997
|
-
* @param img Изображение.
|
|
6998
|
-
* @param meta Массив дополнительных значений метатегов.
|
|
6999
|
-
* @param robots Список robots тегов для страницы.
|
|
7078
|
+
* @param reclamationId Идентификатор рекламации.
|
|
7000
7079
|
*/
|
|
7001
|
-
|
|
7002
|
-
this.
|
|
7003
|
-
|
|
7004
|
-
|
|
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
|
-
*
|
|
7086
|
+
* Отправляет новое сообщение рекламации.
|
|
7015
7087
|
*
|
|
7016
|
-
* @param
|
|
7088
|
+
* @param reclamationId Идентификатор рекламации.
|
|
7089
|
+
* @param newMessage Новое сообщение рекламации.
|
|
7017
7090
|
*/
|
|
7018
|
-
|
|
7019
|
-
this.
|
|
7091
|
+
sendMessages$(reclamationId, newMessage) {
|
|
7092
|
+
return this.http.post(`${this.urls.apiUrl}/reclamations/${reclamationId}/messages`, newMessage);
|
|
7020
7093
|
}
|
|
7021
7094
|
/**
|
|
7022
|
-
*
|
|
7095
|
+
* Выполняет запрос удаления рекламации.
|
|
7096
|
+
*
|
|
7097
|
+
* @param reclamationId Идентификатор рекламации.
|
|
7023
7098
|
*/
|
|
7024
|
-
|
|
7025
|
-
|
|
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
|
-
*
|
|
7120
|
+
* Инициализирует экземпляр класса {@link ScJsonLdComponent}.
|
|
7032
7121
|
*
|
|
7033
|
-
* @param
|
|
7034
|
-
* @param defaultTitle Заголовок страницы используемый в случае отсутствия заголовка в SEO-ресурсе.
|
|
7035
|
-
* @param defaultDescription Описание страницы используемое в случае отсутствия описания в SEO-ресурсе.
|
|
7036
|
-
* @param defaultKeyWords Ключевые слова страницы используемые в случае отсутствия ключевых слов в SEO-ресурсе.
|
|
7122
|
+
* @param sanitizer Объект DomSanitizer для безопасной обработки HTML и стилей.
|
|
7037
7123
|
*/
|
|
7038
|
-
|
|
7039
|
-
|
|
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
|
-
*
|
|
7048
|
-
*
|
|
7049
|
-
* @param url URL который необходимо использовать в качестве ссылки.
|
|
7128
|
+
* Объект структурированных данных о товаре.
|
|
7050
7129
|
*/
|
|
7051
|
-
|
|
7052
|
-
|
|
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
|
-
*
|
|
7134
|
+
* Возвращает безопасный html код.
|
|
7066
7135
|
*
|
|
7067
|
-
* @param
|
|
7068
|
-
* @param appendDefaultTitle Флаг необходимости добавить заголовок по умолчанию в конец заголовка страницы.
|
|
7136
|
+
* @param json JSON данные.
|
|
7069
7137
|
*/
|
|
7070
|
-
|
|
7071
|
-
|
|
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
|
-
*
|
|
7075
|
-
*
|
|
7076
|
-
* @param description Meta-описание страницы.
|
|
7184
|
+
* Подсказки по фио.
|
|
7077
7185
|
*/
|
|
7078
|
-
|
|
7079
|
-
this.setPageMetaByName('description', description);
|
|
7080
|
-
}
|
|
7186
|
+
ScISuggestionType["fio"] = "fio";
|
|
7081
7187
|
/**
|
|
7082
|
-
*
|
|
7083
|
-
*
|
|
7084
|
-
* @param keywords Meta-ключевые слова страницы.
|
|
7188
|
+
* Подсказки по адресам.
|
|
7085
7189
|
*/
|
|
7086
|
-
|
|
7087
|
-
this.setPageMetaByName('keywords', keywords);
|
|
7088
|
-
}
|
|
7190
|
+
ScISuggestionType["address"] = "address";
|
|
7089
7191
|
/**
|
|
7090
|
-
*
|
|
7091
|
-
*
|
|
7092
|
-
* @param title Заголовок страницы.
|
|
7093
|
-
* @param description Описание страницы.
|
|
7094
|
-
* @param url Ссылка на страницу.
|
|
7095
|
-
* @param img Изображение.
|
|
7192
|
+
* Подсказки по организациям.
|
|
7096
7193
|
*/
|
|
7097
|
-
|
|
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
|
-
*
|
|
7106
|
-
* Будет создан или обновлён заголовок вида `<meta name="{name}" content="{content}" />`
|
|
7107
|
-
*
|
|
7108
|
-
* @param name Название заголовка.
|
|
7109
|
-
* @param content Содержимое заголовка.
|
|
7196
|
+
* Подсказки по банкам.
|
|
7110
7197
|
*/
|
|
7111
|
-
|
|
7112
|
-
this.metaService.updateTag({ name: name, content: content, 'data-group': this.dataGroupSelector });
|
|
7113
|
-
}
|
|
7198
|
+
ScISuggestionType["bank"] = "bank";
|
|
7114
7199
|
/**
|
|
7115
|
-
*
|
|
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
|
|
7118
|
-
* @param
|
|
7212
|
+
* @param http Сервис для выполнения HTTP-запросов.
|
|
7213
|
+
* @param urls Список ссылок на разделы backend'a.
|
|
7119
7214
|
*/
|
|
7120
|
-
|
|
7121
|
-
this.
|
|
7215
|
+
constructor(http, urls) {
|
|
7216
|
+
this.http = http;
|
|
7217
|
+
this.urls = urls;
|
|
7122
7218
|
}
|
|
7123
7219
|
/**
|
|
7124
|
-
*
|
|
7220
|
+
* Возвращает {@link Observable} подсказок по указанному запросу.
|
|
7125
7221
|
*
|
|
7126
|
-
* @param
|
|
7222
|
+
* @param query Запрос, для которого нужно получить подсказки.
|
|
7223
|
+
* @param type Тип подсказок.
|
|
7127
7224
|
*/
|
|
7128
|
-
|
|
7129
|
-
|
|
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:
|
|
7132
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type:
|
|
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:
|
|
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
|