@snabcentr/client-core 2.50.0 → 2.52.0
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/catalog/services/sc-catalog.service.d.ts +7 -42
- package/contacts/services/sc-feedback.service.d.ts +4 -0
- package/esm2022/catalog/services/sc-catalog.service.mjs +27 -80
- package/esm2022/contacts/enums/sc-feedback-forms.mjs +31 -2
- package/esm2022/contacts/services/sc-feedback.service.mjs +10 -7
- package/esm2022/guards/sc-id-or-slug.guard.mjs +2 -2
- package/esm2022/utm/services/sc-utm.service.mjs +23 -12
- package/fesm2022/snabcentr-client-core.mjs +565 -574
- package/fesm2022/snabcentr-client-core.mjs.map +1 -1
- package/package.json +1 -1
- package/release_notes.tmp +4 -3
- package/utm/services/sc-utm.service.d.ts +10 -0
|
@@ -3,7 +3,7 @@ import { InjectionToken, inject, PLATFORM_ID, Injectable, Inject, Optional, LOCA
|
|
|
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, shareReplay, BehaviorSubject, distinctUntilKeyChanged, skip, first, distinctUntilChanged, filter, expand, takeWhile, toArray, catchError,
|
|
6
|
+
import { startWith, Subject, ReplaySubject, partition, combineLatest, map, debounceTime, switchMap, of, tap, shareReplay, BehaviorSubject, distinctUntilKeyChanged, skip, first, distinctUntilChanged, filter, expand, takeWhile, toArray, catchError, throwError, concatMap, finalize, takeUntil, interval, share, scan } from 'rxjs';
|
|
7
7
|
import { isPlatformBrowser, isPlatformServer, DOCUMENT, formatDate } from '@angular/common';
|
|
8
8
|
import { tuiCreateTokenFromFactory, tuiCreateToken, TuiDay, tuiIsPresent, tuiPure } from '@taiga-ui/cdk';
|
|
9
9
|
import * as i1$1 from '@angular/common/http';
|
|
@@ -12,9 +12,9 @@ import { tuiCleanObject } from '@taiga-ui/addon-doc/utils';
|
|
|
12
12
|
import { __decorate } from 'tslib';
|
|
13
13
|
import * as i2 from '@angular/router';
|
|
14
14
|
import { ActivatedRoute, Router, NavigationEnd } from '@angular/router';
|
|
15
|
+
import { isString, isMatch } from 'lodash-es';
|
|
15
16
|
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
|
16
17
|
import { objectToSnake, objectToCamel, toSnake } from 'ts-case-convert';
|
|
17
|
-
import { isString, isMatch } from 'lodash-es';
|
|
18
18
|
import { format, parse } from 'date-fns';
|
|
19
19
|
import * as i1$2 from '@angular/platform-browser';
|
|
20
20
|
import { Meta, Title } from '@angular/platform-browser';
|
|
@@ -2957,18 +2957,6 @@ class ScCatalogService {
|
|
|
2957
2957
|
* {@link Map} коллекция пар ключ-значение для кэшированных товаров категории каталога.
|
|
2958
2958
|
*/
|
|
2959
2959
|
this.categoryProductsMap = new Map();
|
|
2960
|
-
/**
|
|
2961
|
-
* {@link Map} коллекция пар ключ-значение для кэшированных рекомендуемых товаров категории.
|
|
2962
|
-
*
|
|
2963
|
-
* @deprecated
|
|
2964
|
-
*/
|
|
2965
|
-
this.recommendedProductsByCategoryMap = new Map();
|
|
2966
|
-
/**
|
|
2967
|
-
* {@link Map} коллекция пар ключ-значение для кэшированных рекомендуемых товаров товара.
|
|
2968
|
-
*
|
|
2969
|
-
* @deprecated
|
|
2970
|
-
*/
|
|
2971
|
-
this.recommendedProductsByProductMap = new Map();
|
|
2972
2960
|
/**
|
|
2973
2961
|
* {@link Map} коллекция пар ключ-значение для кэширования истории цен.
|
|
2974
2962
|
*/
|
|
@@ -2978,9 +2966,13 @@ class ScCatalogService {
|
|
|
2978
2966
|
*/
|
|
2979
2967
|
this.idOrSlugPipe = inject(ScIdOrSlugPipe);
|
|
2980
2968
|
/**
|
|
2981
|
-
* {@link Map} коллекция пар ключ-значение для сопоставления slug и id категорий при
|
|
2969
|
+
* {@link Map} коллекция пар ключ-значение для сопоставления slug и id категорий при кешировании запросов, если идентификатор отличается от установленного в проекте (slug/id).
|
|
2982
2970
|
*/
|
|
2983
2971
|
this.categoryIdOrSlugMap = new Map();
|
|
2972
|
+
/**
|
|
2973
|
+
* {@link Map} коллекция пар ключ-значение для сопоставления slug и id товаров при кешировании запросов, если идентификатор отличается от установленного в проекте (slug/id).
|
|
2974
|
+
*/
|
|
2975
|
+
this.productIdOrSlugMap = new Map();
|
|
2984
2976
|
/**
|
|
2985
2977
|
* Число первых записей товаров со скидкой.
|
|
2986
2978
|
*/
|
|
@@ -3009,7 +3001,6 @@ class ScCatalogService {
|
|
|
3009
3001
|
.subscribe(() => {
|
|
3010
3002
|
this.idCategoryMap.clear();
|
|
3011
3003
|
this.categoryMap.clear();
|
|
3012
|
-
this.productMap.clear();
|
|
3013
3004
|
this.productHistoryMap.clear();
|
|
3014
3005
|
});
|
|
3015
3006
|
}
|
|
@@ -3028,21 +3019,6 @@ class ScCatalogService {
|
|
|
3028
3019
|
this.idCategoryMap.delete(categoryIdOrSlug?.toString());
|
|
3029
3020
|
return undefined;
|
|
3030
3021
|
}
|
|
3031
|
-
/**
|
|
3032
|
-
* Возвращает товар из коллекции каталога.
|
|
3033
|
-
*
|
|
3034
|
-
* @deprecated Удалить в рамках задачи TASK[#10153].
|
|
3035
|
-
*
|
|
3036
|
-
* @param productIdOrSlug Идентификатор или slug товара/услуги.
|
|
3037
|
-
*/
|
|
3038
|
-
getProductFromMap(productIdOrSlug) {
|
|
3039
|
-
const product = this.productMap.get(productIdOrSlug.toString());
|
|
3040
|
-
if (product) {
|
|
3041
|
-
return product;
|
|
3042
|
-
}
|
|
3043
|
-
this.productMap.delete(productIdOrSlug.toString());
|
|
3044
|
-
return undefined;
|
|
3045
|
-
}
|
|
3046
3022
|
/**
|
|
3047
3023
|
* Создает запрос получения списка категорий товаров или список корневых категорий, если идентификатор категории не указан.
|
|
3048
3024
|
*
|
|
@@ -3192,12 +3168,28 @@ class ScCatalogService {
|
|
|
3192
3168
|
*
|
|
3193
3169
|
* @param productIdOrSlug Идентификатор или slug товара/услуги.
|
|
3194
3170
|
*/
|
|
3195
|
-
|
|
3196
|
-
|
|
3197
|
-
|
|
3198
|
-
|
|
3171
|
+
getProductData$(productIdOrSlug) {
|
|
3172
|
+
return this.http.get(`${this.urls.apiUrl}/catalog/products/${productIdOrSlug}`).pipe(map((productDTO) => new ScProduct(productDTO)), tap((product) => {
|
|
3173
|
+
if (productIdOrSlug && typeof this.idOrSlugPipe.transform(product) !== typeof productIdOrSlug) {
|
|
3174
|
+
this.productIdOrSlugMap.set(this.idOrSlugPipe.transform(product), productIdOrSlug);
|
|
3175
|
+
}
|
|
3176
|
+
}));
|
|
3177
|
+
}
|
|
3178
|
+
getProductDataCached$(productIdOrSlug) {
|
|
3179
|
+
const valueFromMap = this.productIdOrSlugMap.get(productIdOrSlug);
|
|
3180
|
+
if (valueFromMap) {
|
|
3181
|
+
// eslint-disable-next-line no-param-reassign
|
|
3182
|
+
productIdOrSlug = valueFromMap;
|
|
3183
|
+
}
|
|
3184
|
+
let cachedItem = this.productMap.get(productIdOrSlug.toString());
|
|
3185
|
+
if (!cachedItem) {
|
|
3186
|
+
cachedItem = new ScCachedItem(this.cacheLifeTime.categoryData, this.getProductData$(productIdOrSlug));
|
|
3187
|
+
this.productMap.set(productIdOrSlug.toString(), cachedItem);
|
|
3188
|
+
}
|
|
3189
|
+
if (!cachedItem.cachedDataIsActual()) {
|
|
3190
|
+
cachedItem.update();
|
|
3199
3191
|
}
|
|
3200
|
-
return
|
|
3192
|
+
return cachedItem.item$;
|
|
3201
3193
|
}
|
|
3202
3194
|
/**
|
|
3203
3195
|
* Создаёт запрос на получение генерируемого файла прайс-листа в формате {@link Blob}, и выгружает пользователю в браузер.
|
|
@@ -3220,51 +3212,6 @@ class ScCatalogService {
|
|
|
3220
3212
|
});
|
|
3221
3213
|
}));
|
|
3222
3214
|
}
|
|
3223
|
-
/**
|
|
3224
|
-
* Создает запрос получения списка ранее заказанных товаров.
|
|
3225
|
-
*
|
|
3226
|
-
* @deprecated Удалить в рамках задачи TASK[#10155].
|
|
3227
|
-
*/
|
|
3228
|
-
getPreviouslyOrderedProducts$() {
|
|
3229
|
-
if (!this.currentUserPreviouslyOrdered.cachedDataIsActual()) {
|
|
3230
|
-
this.currentUserPreviouslyOrdered.update();
|
|
3231
|
-
}
|
|
3232
|
-
return this.currentUserPreviouslyOrdered.item$;
|
|
3233
|
-
}
|
|
3234
|
-
/**
|
|
3235
|
-
* Создает запрос на получение списка рекомендованных товаров для категории.
|
|
3236
|
-
*
|
|
3237
|
-
* @param categoryIdOrSlug Идентификатор или slug категории товаров.
|
|
3238
|
-
* @deprecated
|
|
3239
|
-
*/
|
|
3240
|
-
getRecommendedProductsByCategory$(categoryIdOrSlug) {
|
|
3241
|
-
let cachedItem = this.recommendedProductsByCategoryMap.get(categoryIdOrSlug.toString());
|
|
3242
|
-
if (!cachedItem) {
|
|
3243
|
-
// Устанавливаем время жизни cachedItem равное, потому что нам не важно время жизни. Нам нужен функционал update().
|
|
3244
|
-
cachedItem = new ScCachedItem(0, this.http
|
|
3245
|
-
.get(`${this.urls.apiUrl}/catalog/categories/${categoryIdOrSlug}/recommendations`)
|
|
3246
|
-
.pipe(map((productsDTO) => productsDTO.map((product) => new ScProduct(product)))));
|
|
3247
|
-
this.recommendedProductsByCategoryMap.set(categoryIdOrSlug.toString(), cachedItem);
|
|
3248
|
-
}
|
|
3249
|
-
return cachedItem.item$;
|
|
3250
|
-
}
|
|
3251
|
-
/**
|
|
3252
|
-
* Создает запрос на получение списка рекомендованных товаров для продукта.
|
|
3253
|
-
*
|
|
3254
|
-
* @param productIdOrSlug Идентификатор или slug товара/услуги.
|
|
3255
|
-
* @deprecated
|
|
3256
|
-
*/
|
|
3257
|
-
getRecommendedProductsByProduct$(productIdOrSlug) {
|
|
3258
|
-
let cachedItem = this.recommendedProductsByProductMap.get(productIdOrSlug.toString());
|
|
3259
|
-
if (!cachedItem) {
|
|
3260
|
-
// Устанавливаем время жизни cachedItem равное, потому что нам не важно время жизни. Нам нужен функционал update().
|
|
3261
|
-
cachedItem = new ScCachedItem(0, this.http
|
|
3262
|
-
.get(`${this.urls.apiUrl}/catalog/products/${productIdOrSlug}/recommendations`)
|
|
3263
|
-
.pipe(map((productsDTO) => productsDTO.map((product) => new ScProduct(product)))));
|
|
3264
|
-
this.recommendedProductsByProductMap.set(productIdOrSlug.toString(), cachedItem);
|
|
3265
|
-
}
|
|
3266
|
-
return cachedItem.item$;
|
|
3267
|
-
}
|
|
3268
3215
|
/**
|
|
3269
3216
|
* Запрос на уведомление пользователя о поступлении продукта.
|
|
3270
3217
|
*
|
|
@@ -3587,6 +3534,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
|
|
|
3587
3534
|
args: [SC_URLS]
|
|
3588
3535
|
}] }, { type: ScCatalogService }] });
|
|
3589
3536
|
|
|
3537
|
+
/**
|
|
3538
|
+
* Перечисление, представляющее различные формы обратной связи.
|
|
3539
|
+
*/
|
|
3540
|
+
var ScFeedbackForms;
|
|
3541
|
+
(function (ScFeedbackForms) {
|
|
3542
|
+
/**
|
|
3543
|
+
* Пожелания и предложения по улучшению сайта.
|
|
3544
|
+
*/
|
|
3545
|
+
ScFeedbackForms["suggest"] = "suggest";
|
|
3546
|
+
/**
|
|
3547
|
+
* Оставить заявку на получение бесплатных образцов.
|
|
3548
|
+
*/
|
|
3549
|
+
ScFeedbackForms["samples"] = "samples";
|
|
3550
|
+
/**
|
|
3551
|
+
* Форма обратной связи со страницы контактов.
|
|
3552
|
+
*/
|
|
3553
|
+
ScFeedbackForms["contacts"] = "contacts";
|
|
3554
|
+
/**
|
|
3555
|
+
* Форма обратной связи со страницы вакансий.
|
|
3556
|
+
*/
|
|
3557
|
+
ScFeedbackForms["vacancies"] = "vacancies";
|
|
3558
|
+
/**
|
|
3559
|
+
* Задать вопрос.
|
|
3560
|
+
*/
|
|
3561
|
+
ScFeedbackForms["questions"] = "questions";
|
|
3562
|
+
/**
|
|
3563
|
+
* Заказать изготовление москитной сетки.
|
|
3564
|
+
*/
|
|
3565
|
+
ScFeedbackForms["mosquitoes"] = "mosquitoes";
|
|
3566
|
+
})(ScFeedbackForms || (ScFeedbackForms = {}));
|
|
3567
|
+
|
|
3590
3568
|
/**
|
|
3591
3569
|
* Перечисление типов контактов по социальным сетям.
|
|
3592
3570
|
*/
|
|
@@ -3633,119 +3611,107 @@ class ScUploadedFile {
|
|
|
3633
3611
|
const SC_IS_HEADER_REQUIRED = new HttpContextToken(() => true);
|
|
3634
3612
|
|
|
3635
3613
|
/**
|
|
3636
|
-
*
|
|
3614
|
+
* Значения пагинации списка товаров категории по умолчанию.
|
|
3637
3615
|
*/
|
|
3638
|
-
|
|
3616
|
+
const SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS = {
|
|
3617
|
+
perPage: 20,
|
|
3618
|
+
page: 0,
|
|
3619
|
+
};
|
|
3620
|
+
/**
|
|
3621
|
+
* Токен значений пагинации списка товаров в каталоге по умолчанию.
|
|
3622
|
+
*/
|
|
3623
|
+
const SC_PRODUCT_PAGINATION_OPTIONS = tuiCreateToken(SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS);
|
|
3624
|
+
/**
|
|
3625
|
+
* Токен {@link EventEmitter} событие нажатия на кнопку "Показать следующие позиции категории".
|
|
3626
|
+
*/
|
|
3627
|
+
const SC_NEXT_PAGE_PAGINATION_CLICK = tuiCreateToken(new EventEmitter());
|
|
3628
|
+
|
|
3629
|
+
/**
|
|
3630
|
+
* Сервис поиска по каталогу.
|
|
3631
|
+
*/
|
|
3632
|
+
class ScSearchService {
|
|
3639
3633
|
/**
|
|
3640
|
-
* Инициализирует экземпляр класса {@link
|
|
3634
|
+
* Инициализирует экземпляр класса {@link ScSearchService}.
|
|
3641
3635
|
*
|
|
3642
3636
|
* @param http HTTP-клиент.
|
|
3637
|
+
* @param urls Список ссылок на разделы backend'a.
|
|
3643
3638
|
* @param userMetrikaService Сервис для сбора метрик о действиях пользователей.
|
|
3644
|
-
* @param feedbackApi Данные для взаимодействия с API обратной связи.
|
|
3645
3639
|
*/
|
|
3646
|
-
constructor(http,
|
|
3640
|
+
constructor(http, urls, userMetrikaService) {
|
|
3647
3641
|
this.http = http;
|
|
3642
|
+
this.urls = urls;
|
|
3648
3643
|
this.userMetrikaService = userMetrikaService;
|
|
3649
|
-
this.feedbackApi = feedbackApi;
|
|
3650
3644
|
/**
|
|
3651
|
-
*
|
|
3645
|
+
* {@link BehaviorSubject} поискового запрос.
|
|
3652
3646
|
*/
|
|
3653
|
-
this.
|
|
3654
|
-
.get(`${this.feedbackApi.apiUrl}/feedback/forms`, {
|
|
3655
|
-
context: new HttpContext().set(SC_AUTH_ADD_HEADER_REQUIRED, false).set(SC_IS_HEADER_REQUIRED, false),
|
|
3656
|
-
headers: {
|
|
3657
|
-
[this.feedbackApi.authTokenName]: this.feedbackApi.authToken,
|
|
3658
|
-
},
|
|
3659
|
-
})
|
|
3660
|
-
.pipe(shareReplay(1));
|
|
3647
|
+
this.searchTerm$ = new BehaviorSubject(null);
|
|
3661
3648
|
}
|
|
3662
3649
|
/**
|
|
3663
|
-
*
|
|
3650
|
+
* Выполняет упрощенный поиск товаров и категорий. Возвращает ограниченное количество записей.
|
|
3664
3651
|
*
|
|
3665
|
-
* @param
|
|
3666
|
-
* @param feedbackMessage Объект сообщения обратной связи.
|
|
3652
|
+
* @param term Поисковый запрос.
|
|
3667
3653
|
*/
|
|
3668
|
-
|
|
3669
|
-
return this.http
|
|
3670
|
-
.post(`${this.feedbackApi.apiUrl}/feedback/${formSlug}`, feedbackMessage, {
|
|
3671
|
-
context: new HttpContext().set(SC_AUTH_ADD_HEADER_REQUIRED, false).set(SC_IS_HEADER_REQUIRED, false),
|
|
3672
|
-
headers: {
|
|
3673
|
-
[this.feedbackApi.authTokenName]: this.feedbackApi.authToken,
|
|
3674
|
-
},
|
|
3675
|
-
})
|
|
3676
|
-
.pipe(tap(() => {
|
|
3654
|
+
simple$(term) {
|
|
3655
|
+
return this.http.get(`${this.urls.apiUrl}/catalog/search/simple`, { params: { term: term } }).pipe(tap(() => {
|
|
3677
3656
|
this.userMetrikaService.emitUserMetrikaEvent({
|
|
3678
|
-
target: ScUserMetrikaGoalsEnum.
|
|
3657
|
+
target: ScUserMetrikaGoalsEnum.catalogSearch,
|
|
3658
|
+
params: {
|
|
3659
|
+
search_type: 'simple',
|
|
3660
|
+
term: term,
|
|
3661
|
+
},
|
|
3679
3662
|
});
|
|
3680
3663
|
}));
|
|
3681
3664
|
}
|
|
3682
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFeedbackService, deps: [{ token: i1$1.HttpClient }, { token: ScUserMetrikaService }, { token: SC_FEEDBACK_API }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3683
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFeedbackService, providedIn: 'root' }); }
|
|
3684
|
-
}
|
|
3685
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFeedbackService, decorators: [{
|
|
3686
|
-
type: Injectable,
|
|
3687
|
-
args: [{
|
|
3688
|
-
providedIn: 'root',
|
|
3689
|
-
}]
|
|
3690
|
-
}], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: ScUserMetrikaService }, { type: undefined, decorators: [{
|
|
3691
|
-
type: Inject,
|
|
3692
|
-
args: [SC_FEEDBACK_API]
|
|
3693
|
-
}] }] });
|
|
3694
|
-
|
|
3695
|
-
/**
|
|
3696
|
-
* Сервис для работы с реквизитами и с обойной связью.
|
|
3697
|
-
*/
|
|
3698
|
-
class ScRequisitesService {
|
|
3699
3665
|
/**
|
|
3700
|
-
*
|
|
3666
|
+
* Выполняет поиск категорий в каталоге.
|
|
3701
3667
|
*
|
|
3702
|
-
* @param
|
|
3703
|
-
* @param urls Список ссылок на разделы backend'a.
|
|
3704
|
-
* @param authService Сервис аутентификации.
|
|
3668
|
+
* @param term Поисковый запрос.
|
|
3705
3669
|
*/
|
|
3706
|
-
|
|
3707
|
-
this.http
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3670
|
+
categories$(term) {
|
|
3671
|
+
return this.http.get(`${this.urls.apiUrl}/catalog/search/categories`, { params: { term: term } }).pipe(tap(() => {
|
|
3672
|
+
this.userMetrikaService.emitUserMetrikaEvent({
|
|
3673
|
+
target: ScUserMetrikaGoalsEnum.catalogSearch,
|
|
3674
|
+
params: {
|
|
3675
|
+
search_type: 'categories',
|
|
3676
|
+
term: term,
|
|
3677
|
+
},
|
|
3678
|
+
});
|
|
3679
|
+
}), map((categories) => categories.map((item) => new ScCategory(item))));
|
|
3680
|
+
}
|
|
3681
|
+
/**
|
|
3682
|
+
* Выполняет полный поиск по всему прайс-листу.
|
|
3683
|
+
*
|
|
3684
|
+
* @param term Поисковый запрос.
|
|
3685
|
+
* @param showOrderedProducts Признак того, что необходимо вернуть ранее заказанные продукты.
|
|
3686
|
+
* @param showFavoriteProducts Признак того, что необходимо вернуть избранные продукты.
|
|
3687
|
+
* @param showDiscountedProducts Признак того, что необходимо вернуть продукты со скидкой.
|
|
3688
|
+
*/
|
|
3689
|
+
full$(term, showOrderedProducts, showFavoriteProducts, showDiscountedProducts) {
|
|
3690
|
+
const params = {};
|
|
3691
|
+
if (term) {
|
|
3692
|
+
params['term'] = term;
|
|
3693
|
+
}
|
|
3694
|
+
if (showOrderedProducts) {
|
|
3695
|
+
params['show_ordered_products'] = Number(showOrderedProducts);
|
|
3696
|
+
}
|
|
3697
|
+
if (showFavoriteProducts) {
|
|
3698
|
+
params['show_favorite_products'] = Number(showFavoriteProducts);
|
|
3699
|
+
}
|
|
3700
|
+
if (showDiscountedProducts) {
|
|
3701
|
+
params['show_discounted_products'] = Number(showDiscountedProducts);
|
|
3702
|
+
}
|
|
3703
|
+
if (Object.keys(params).length > 0) {
|
|
3704
|
+
return this.http.get(`${this.urls.apiUrl}/catalog/search/full`, { params: params }).pipe(tap(() => {
|
|
3705
|
+
this.userMetrikaService.emitUserMetrikaEvent({
|
|
3706
|
+
target: ScUserMetrikaGoalsEnum.catalogSearch,
|
|
3707
|
+
params: {
|
|
3708
|
+
search_type: 'full',
|
|
3709
|
+
term: term,
|
|
3710
|
+
},
|
|
3742
3711
|
});
|
|
3743
|
-
}
|
|
3744
|
-
}
|
|
3745
|
-
|
|
3746
|
-
* Создаёт запрос получения списка реквизитов компании.
|
|
3747
|
-
*/
|
|
3748
|
-
this.requisites$ = this.http.get(`${this.urls.apiUrl}/requisites`).pipe(shareReplay(1));
|
|
3712
|
+
}));
|
|
3713
|
+
}
|
|
3714
|
+
return throwError(() => new Error('Необходимо указать хотя бы один параметр.'));
|
|
3749
3715
|
}
|
|
3750
3716
|
/**
|
|
3751
3717
|
* Устанавливает поисковый запрос в {@link BehaviorSubject}.
|
|
@@ -3761,16 +3727,373 @@ class ScRequisitesService {
|
|
|
3761
3727
|
getSearchTermChange$() {
|
|
3762
3728
|
return this.searchTerm$.asObservable();
|
|
3763
3729
|
}
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3770
|
-
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3730
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSearchService, deps: [{ token: i1$1.HttpClient }, { token: SC_URLS }, { token: ScUserMetrikaService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3731
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSearchService, providedIn: 'root' }); }
|
|
3732
|
+
}
|
|
3733
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScSearchService, decorators: [{
|
|
3734
|
+
type: Injectable,
|
|
3735
|
+
args: [{
|
|
3736
|
+
providedIn: 'root',
|
|
3737
|
+
}]
|
|
3738
|
+
}], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: undefined, decorators: [{
|
|
3739
|
+
type: Inject,
|
|
3740
|
+
args: [SC_URLS]
|
|
3741
|
+
}] }, { type: ScUserMetrikaService }] });
|
|
3742
|
+
|
|
3743
|
+
/**
|
|
3744
|
+
* Токен поиска введенного терма.
|
|
3745
|
+
*/
|
|
3746
|
+
const SEARCH_TERM = new InjectionToken('SEARCH_TERM');
|
|
3747
|
+
/**
|
|
3748
|
+
* Токен минимального количества введенных символов в поле поиска.
|
|
3749
|
+
*/
|
|
3750
|
+
const SC_MIN_LENGTH_SEARCH_TERM = new InjectionToken('SC_MIN_LENGTH_SEARCH_TERM');
|
|
3751
|
+
/**
|
|
3752
|
+
* Токен максимального количества введенных символов в поле поиска.
|
|
3753
|
+
*/
|
|
3754
|
+
const SC_MAX_LENGTH_SEARCH_TERM = new InjectionToken('SC_MAX_LENGTH_SEARCH_TERM');
|
|
3755
|
+
/**
|
|
3756
|
+
* Возвращает введенный терм для поиска.
|
|
3757
|
+
*
|
|
3758
|
+
* @param searchService Сервис поиска по каталогу.
|
|
3759
|
+
* @param minLengthSearchTerm Минимальное количество введенных символов в поле поиска.
|
|
3760
|
+
* @param maxLengthSearchTerm Максимальное количество введенных символов в поле поиска.
|
|
3761
|
+
*/
|
|
3762
|
+
function searchTermFactory(searchService, minLengthSearchTerm, maxLengthSearchTerm) {
|
|
3763
|
+
return searchService
|
|
3764
|
+
.getSearchTermChange$()
|
|
3765
|
+
.pipe(map((searchTerm) => (searchTerm && searchTerm.length >= minLengthSearchTerm && searchTerm.length <= maxLengthSearchTerm ? searchTerm : '')));
|
|
3766
|
+
}
|
|
3767
|
+
/**
|
|
3768
|
+
* Провайдеры данных о поиске введенного терма.
|
|
3769
|
+
*/
|
|
3770
|
+
const SEARCH_TERM_PROVIDERS = [
|
|
3771
|
+
{
|
|
3772
|
+
provide: SEARCH_TERM,
|
|
3773
|
+
deps: [ScSearchService, SC_MIN_LENGTH_SEARCH_TERM, SC_MAX_LENGTH_SEARCH_TERM],
|
|
3774
|
+
useFactory: searchTermFactory,
|
|
3775
|
+
},
|
|
3776
|
+
];
|
|
3777
|
+
|
|
3778
|
+
/* eslint-disable no-param-reassign,no-return-assign,jsdoc/check-param-names */
|
|
3779
|
+
/**
|
|
3780
|
+
* Токен потока данных о виртуальной категории.
|
|
3781
|
+
*/
|
|
3782
|
+
const SC_VIRTUAL_CATEGORY_INFO = new InjectionToken('A stream with current virtual category information');
|
|
3783
|
+
/**
|
|
3784
|
+
* Фабрика создания потока данных виртуальной категории.
|
|
3785
|
+
*
|
|
3786
|
+
* @param paramMap Параметры.
|
|
3787
|
+
* @param paramMap.paramMap Параметры.
|
|
3788
|
+
* @param catalogService.paramMap Параметры маршрута.
|
|
3789
|
+
* @param catalogService Сервис для работы с каталогом.
|
|
3790
|
+
*/
|
|
3791
|
+
function virtualCategoryFactory({ paramMap }, catalogService) {
|
|
3792
|
+
return paramMap.pipe(map((params) => params.get('categorySlug')), filter(tuiIsPresent), switchMap((categorySlug) => catalogService.getVirtualCategoryCached$(categorySlug).pipe(shareReplay())), takeUntilDestroyed());
|
|
3793
|
+
}
|
|
3794
|
+
/**
|
|
3795
|
+
* Провайдеры потока данных о виртуальной категории.
|
|
3796
|
+
*/
|
|
3797
|
+
const SC_VIRTUAL_CATEGORY_PROVIDERS = [
|
|
3798
|
+
{
|
|
3799
|
+
provide: SC_VIRTUAL_CATEGORY_INFO,
|
|
3800
|
+
deps: [ActivatedRoute, ScCatalogService],
|
|
3801
|
+
useFactory: virtualCategoryFactory,
|
|
3802
|
+
},
|
|
3803
|
+
];
|
|
3804
|
+
|
|
3805
|
+
/**
|
|
3806
|
+
* Сервис для работы с UTM-меткой страницы.
|
|
3807
|
+
*/
|
|
3808
|
+
class ScUTMService {
|
|
3809
|
+
/**
|
|
3810
|
+
* Инициализирует экземпляр класса {@link ScUTMService}.
|
|
3811
|
+
*/
|
|
3812
|
+
constructor() {
|
|
3813
|
+
/**
|
|
3814
|
+
* Список ссылок на разделы backend.
|
|
3815
|
+
*/
|
|
3816
|
+
this.urls = inject(SC_URLS);
|
|
3817
|
+
/**
|
|
3818
|
+
* Сервис для выполнения HTTP-запросов.
|
|
3819
|
+
*/
|
|
3820
|
+
this.http = inject(HttpClient);
|
|
3821
|
+
/**
|
|
3822
|
+
* Сервис аутентификации пользователей.
|
|
3823
|
+
*/
|
|
3824
|
+
this.authService = inject(ScAuthService);
|
|
3825
|
+
/**
|
|
3826
|
+
* Сервис предоставляющий доступ к данным о маршруте.
|
|
3827
|
+
*/
|
|
3828
|
+
this.activatedRoute = inject(ActivatedRoute);
|
|
3829
|
+
/**
|
|
3830
|
+
* Сервис маршрутизации.
|
|
3831
|
+
*/
|
|
3832
|
+
this.router = inject(Router);
|
|
3833
|
+
/**
|
|
3834
|
+
* Сервис для работы с {@link Storage} и внедрению его через DI.
|
|
3835
|
+
*/
|
|
3836
|
+
this.storageService = inject(StorageService);
|
|
3837
|
+
/**
|
|
3838
|
+
* Признак, что скрипт выполняется в браузере.
|
|
3839
|
+
*/
|
|
3840
|
+
this.isBrowser = inject(IS_BROWSER);
|
|
3841
|
+
/**
|
|
3842
|
+
* Хранилище {@link Storage}.
|
|
3843
|
+
*/
|
|
3844
|
+
this.storage = inject(WA_LOCAL_STORAGE, { optional: true });
|
|
3845
|
+
/**
|
|
3846
|
+
* Время жизни UTM метки (ms).
|
|
3847
|
+
*/
|
|
3848
|
+
this.utmLifeTime = inject(SC_CACHE_LIFETIME).utm;
|
|
3849
|
+
/**
|
|
3850
|
+
* {@link Observable} UTM-метка страницы.
|
|
3851
|
+
*/
|
|
3852
|
+
this.utm$ = inject(WA_STORAGE_EVENT).pipe(filterByKey('utm'), toValue(), startWith(this.getUTMParams()), map((utmString) => (utmString === null ? utmString : JSON.parse(utmString))));
|
|
3853
|
+
/**
|
|
3854
|
+
* {@link Observable} timestamp сохранения UTM в {@link Storage}.
|
|
3855
|
+
*/
|
|
3856
|
+
this.utmTimestamp$ = inject(WA_STORAGE_EVENT).pipe(filterByKey('utmTimestamp'), toValue(), startWith(this.getUTMTimestamp()), map((timestamp) => (isString(timestamp) ? Number(timestamp) : timestamp)));
|
|
3857
|
+
/**
|
|
3858
|
+
* {@link Observable} UTM-метки страницы из параметров роутинга.
|
|
3859
|
+
*/
|
|
3860
|
+
this.utmParamsFromRoute$ = this.router.events.pipe(filter((event) => Boolean(this.storage) && this.isBrowser && event instanceof NavigationEnd), map(() => this.activatedRoute), startWith(this.activatedRoute), map((route) => route.snapshot.queryParams),
|
|
3861
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
3862
|
+
filter((params) => params['utm_source'] && params['utm_medium'] && params['utm_campaign']), map((params) => {
|
|
3863
|
+
return {
|
|
3864
|
+
source: params.utm_source,
|
|
3865
|
+
medium: params.utm_medium,
|
|
3866
|
+
campaign: params.utm_campaign,
|
|
3867
|
+
content: params.utm_content,
|
|
3868
|
+
term: params.utm_term,
|
|
3869
|
+
};
|
|
3870
|
+
}));
|
|
3871
|
+
// При получении UTM-метки сохраняем ее в Storage и создаём запрос сохранения метки за клиентом.
|
|
3872
|
+
this.authService
|
|
3873
|
+
.getAuthChange()
|
|
3874
|
+
.pipe(switchMap(() => this.utmParamsFromRoute$), tap(() => {
|
|
3875
|
+
this.updateTimestamp();
|
|
3876
|
+
}), filter((utm) => !this.isExistingUTM(utm)), tap((utm) => {
|
|
3877
|
+
this.setUTM(utm);
|
|
3878
|
+
}), switchMap((utm) => this.saveUTM$(utm)))
|
|
3879
|
+
.subscribe();
|
|
3880
|
+
}
|
|
3881
|
+
/**
|
|
3882
|
+
* Возвращает строчное представление параметров UTM из {@link Storage}.
|
|
3883
|
+
*/
|
|
3884
|
+
getUTMParams() {
|
|
3885
|
+
return Boolean(this.storage) && this.isBrowser ? this.storageService.getItem('utm') : null;
|
|
3886
|
+
}
|
|
3887
|
+
/**
|
|
3888
|
+
* Возвращает строчное представление timestamp сохранения UTM из {@link Storage}.
|
|
3889
|
+
*/
|
|
3890
|
+
getUTMTimestamp() {
|
|
3891
|
+
return Boolean(this.storage) && this.isBrowser ? this.storageService.getItem('utmTimestamp') : null;
|
|
3892
|
+
}
|
|
3893
|
+
/**
|
|
3894
|
+
* Устанавливает UTM-метку страницы в {@link Storage}.
|
|
3895
|
+
*
|
|
3896
|
+
* @param utm Данные о UTM-метке.
|
|
3897
|
+
*/
|
|
3898
|
+
setUTM(utm) {
|
|
3899
|
+
if (this.storage && this.isBrowser && !this.isExistingUTM(utm)) {
|
|
3900
|
+
this.storageService.setItem('utm', JSON.stringify(utm));
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
/**
|
|
3904
|
+
* Удаляет UTM-метку страницы из {@link Storage}.
|
|
3905
|
+
*/
|
|
3906
|
+
removeUTM() {
|
|
3907
|
+
if (this.storage && this.isBrowser) {
|
|
3908
|
+
this.storageService.removeItem('utm');
|
|
3909
|
+
this.storageService.removeItem('utmTimestamp');
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
/**
|
|
3913
|
+
* Возвращает {@link Observable} данных о UTM-метке.
|
|
3914
|
+
*/
|
|
3915
|
+
getUTM$() {
|
|
3916
|
+
return combineLatest({
|
|
3917
|
+
utm: this.utm$,
|
|
3918
|
+
timestamp: this.utmTimestamp$,
|
|
3919
|
+
}).pipe(map(({ utm, timestamp }) => (!this.utmLifeTime || (timestamp && timestamp + this.utmLifeTime > Date.now()) ? utm : null)));
|
|
3920
|
+
}
|
|
3921
|
+
/**
|
|
3922
|
+
* Возвращает {@link Observable} сохранения {@link ScUTM}.
|
|
3923
|
+
*
|
|
3924
|
+
* @param utm Данные о UTM-метке.
|
|
3925
|
+
*/
|
|
3926
|
+
saveUTM$(utm) {
|
|
3927
|
+
return this.http.post(`${this.urls.apiUrl}/utm`, utm);
|
|
3928
|
+
}
|
|
3929
|
+
/**
|
|
3930
|
+
* Проверяет, существует ли уже сохраненная UTM-метка.
|
|
3931
|
+
*
|
|
3932
|
+
* @param utm Данные о UTM-метке.
|
|
3933
|
+
*/
|
|
3934
|
+
isExistingUTM(utm) {
|
|
3935
|
+
const existingUTM = this.getUTMParams();
|
|
3936
|
+
return existingUTM ? isMatch(utm, JSON.parse(existingUTM)) : false;
|
|
3937
|
+
}
|
|
3938
|
+
/**
|
|
3939
|
+
* Обновляет timestamp сохранения UTM в {@link Storage}.
|
|
3940
|
+
*/
|
|
3941
|
+
updateTimestamp() {
|
|
3942
|
+
if (this.getUTMParams()) {
|
|
3943
|
+
this.storageService.setItem('utmTimestamp', JSON.stringify(Date.now()));
|
|
3944
|
+
}
|
|
3945
|
+
}
|
|
3946
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUTMService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
3947
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUTMService, providedIn: 'root' }); }
|
|
3948
|
+
}
|
|
3949
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUTMService, decorators: [{
|
|
3950
|
+
type: Injectable,
|
|
3951
|
+
args: [{
|
|
3952
|
+
providedIn: 'root',
|
|
3953
|
+
}]
|
|
3954
|
+
}], ctorParameters: () => [] });
|
|
3955
|
+
|
|
3956
|
+
/**
|
|
3957
|
+
* Сервис обратной связи.
|
|
3958
|
+
*/
|
|
3959
|
+
class ScFeedbackService {
|
|
3960
|
+
/**
|
|
3961
|
+
* Инициализирует экземпляр класса {@link ScFeedbackService}.
|
|
3962
|
+
*
|
|
3963
|
+
* @param http HTTP-клиент.
|
|
3964
|
+
* @param userMetrikaService Сервис для сбора метрик о действиях пользователей.
|
|
3965
|
+
* @param feedbackApi Данные для взаимодействия с API обратной связи.
|
|
3966
|
+
*/
|
|
3967
|
+
constructor(http, userMetrikaService, feedbackApi) {
|
|
3968
|
+
this.http = http;
|
|
3969
|
+
this.userMetrikaService = userMetrikaService;
|
|
3970
|
+
this.feedbackApi = feedbackApi;
|
|
3971
|
+
/**
|
|
3972
|
+
* Сервис для работы с UTM-метками.
|
|
3973
|
+
*/
|
|
3974
|
+
this.utmService = inject(ScUTMService);
|
|
3975
|
+
/**
|
|
3976
|
+
* Список форм обратной связи.
|
|
3977
|
+
*/
|
|
3978
|
+
this.feedbackForms$ = this.http
|
|
3979
|
+
.get(`${this.feedbackApi.apiUrl}/feedback/forms`, {
|
|
3980
|
+
context: new HttpContext().set(SC_AUTH_ADD_HEADER_REQUIRED, false).set(SC_IS_HEADER_REQUIRED, false),
|
|
3981
|
+
headers: {
|
|
3982
|
+
[this.feedbackApi.authTokenName]: this.feedbackApi.authToken,
|
|
3983
|
+
},
|
|
3984
|
+
})
|
|
3985
|
+
.pipe(shareReplay(1));
|
|
3986
|
+
}
|
|
3987
|
+
/**
|
|
3988
|
+
* Отправляет сообщение обратной связи.
|
|
3989
|
+
*
|
|
3990
|
+
* @param formSlug Символьное обозначение (slug) формы.
|
|
3991
|
+
* @param feedbackMessage Объект сообщения обратной связи.
|
|
3992
|
+
*/
|
|
3993
|
+
sendFeedback(formSlug, feedbackMessage) {
|
|
3994
|
+
return this.utmService.getUTM$().pipe(first(), map((utm) => (utm ? { ...feedbackMessage, utm } : feedbackMessage)), switchMap((data) => this.http.post(`${this.feedbackApi.apiUrl}/feedback/${formSlug}`, data, {
|
|
3995
|
+
context: new HttpContext().set(SC_AUTH_ADD_HEADER_REQUIRED, false).set(SC_IS_HEADER_REQUIRED, false),
|
|
3996
|
+
headers: {
|
|
3997
|
+
[this.feedbackApi.authTokenName]: this.feedbackApi.authToken,
|
|
3998
|
+
},
|
|
3999
|
+
})), tap(() => {
|
|
4000
|
+
this.userMetrikaService.emitUserMetrikaEvent({
|
|
4001
|
+
target: ScUserMetrikaGoalsEnum.feedbackSent,
|
|
4002
|
+
});
|
|
4003
|
+
}));
|
|
4004
|
+
}
|
|
4005
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFeedbackService, deps: [{ token: i1$1.HttpClient }, { token: ScUserMetrikaService }, { token: SC_FEEDBACK_API }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4006
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFeedbackService, providedIn: 'root' }); }
|
|
4007
|
+
}
|
|
4008
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFeedbackService, decorators: [{
|
|
4009
|
+
type: Injectable,
|
|
4010
|
+
args: [{
|
|
4011
|
+
providedIn: 'root',
|
|
4012
|
+
}]
|
|
4013
|
+
}], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: ScUserMetrikaService }, { type: undefined, decorators: [{
|
|
4014
|
+
type: Inject,
|
|
4015
|
+
args: [SC_FEEDBACK_API]
|
|
4016
|
+
}] }] });
|
|
4017
|
+
|
|
4018
|
+
/**
|
|
4019
|
+
* Сервис для работы с реквизитами и с обойной связью.
|
|
4020
|
+
*/
|
|
4021
|
+
class ScRequisitesService {
|
|
4022
|
+
/**
|
|
4023
|
+
* Инициализирует экземпляр класса {@link ScRequisitesService}.
|
|
4024
|
+
*
|
|
4025
|
+
* @param http HTTP-клиент.
|
|
4026
|
+
* @param urls Список ссылок на разделы backend'a.
|
|
4027
|
+
* @param authService Сервис аутентификации.
|
|
4028
|
+
*/
|
|
4029
|
+
constructor(http, urls, authService) {
|
|
4030
|
+
this.http = http;
|
|
4031
|
+
this.urls = urls;
|
|
4032
|
+
this.authService = authService;
|
|
4033
|
+
/**
|
|
4034
|
+
* {@link BehaviorSubject} поискового запроса на странице контактов.
|
|
4035
|
+
*/
|
|
4036
|
+
this.searchTerm$ = new BehaviorSubject(null);
|
|
4037
|
+
/**
|
|
4038
|
+
* {@link Map} коллекция пар ключ-значение для контактов менеджера по направлению продаж.
|
|
4039
|
+
*/
|
|
4040
|
+
this.idManagerMap = new Map();
|
|
4041
|
+
/**
|
|
4042
|
+
* Создаёт запрос получения списка всех контактов.
|
|
4043
|
+
*/
|
|
4044
|
+
this.contacts$ = this.authService.getAuthChange().pipe(switchMap(() => this.http.get(`${this.urls.apiUrl}/contacts`)), shareReplay(1));
|
|
4045
|
+
/**
|
|
4046
|
+
* Создаёт запрос получения списка контактов для решения возникающих вопросов.
|
|
4047
|
+
*/
|
|
4048
|
+
this.personal$ = this.contacts$.pipe(map((contacts) => contacts.personal));
|
|
4049
|
+
/**
|
|
4050
|
+
* Создаёт запрос получения списка контактов розничных магазинов.
|
|
4051
|
+
*/
|
|
4052
|
+
this.retail$ = this.contacts$.pipe(map((contacts) => contacts.retail), first(), shareReplay(1));
|
|
4053
|
+
/**
|
|
4054
|
+
* Создаёт запрос получения списка ссылок на социальные сети и другие каналы коммуникации.
|
|
4055
|
+
*/
|
|
4056
|
+
this.socialMedia$ = this.contacts$.pipe(map((contacts) => contacts.socialMedia), first(), shareReplay(1));
|
|
4057
|
+
/**
|
|
4058
|
+
* Создаёт запрос получения списка контактов менеджеров по направлениям продаж.
|
|
4059
|
+
*/
|
|
4060
|
+
this.directions$ = this.contacts$.pipe(map((contacts) => contacts.directions), tap((directions) => {
|
|
4061
|
+
// eslint-disable-next-line guard-for-in,no-restricted-syntax
|
|
4062
|
+
for (const key in directions) {
|
|
4063
|
+
directions[Number.parseFloat(key)]?.forEach((manager) => {
|
|
4064
|
+
this.mapManagers(Number.parseFloat(key), manager);
|
|
4065
|
+
});
|
|
4066
|
+
}
|
|
4067
|
+
}), first(), shareReplay(1));
|
|
4068
|
+
/**
|
|
4069
|
+
* Создаёт запрос получения списка реквизитов компании.
|
|
4070
|
+
*/
|
|
4071
|
+
this.requisites$ = this.http.get(`${this.urls.apiUrl}/requisites`).pipe(shareReplay(1));
|
|
4072
|
+
}
|
|
4073
|
+
/**
|
|
4074
|
+
* Устанавливает поисковый запрос в {@link BehaviorSubject}.
|
|
4075
|
+
*
|
|
4076
|
+
* @param term Поисковый запрос.
|
|
4077
|
+
*/
|
|
4078
|
+
setSearchTermChange(term) {
|
|
4079
|
+
this.searchTerm$.next(term);
|
|
4080
|
+
}
|
|
4081
|
+
/**
|
|
4082
|
+
* Возвращает {@link Observable} поискового запроса.
|
|
4083
|
+
*/
|
|
4084
|
+
getSearchTermChange$() {
|
|
4085
|
+
return this.searchTerm$.asObservable();
|
|
4086
|
+
}
|
|
4087
|
+
/**
|
|
4088
|
+
* Возвращает поисковый запрос.
|
|
4089
|
+
*/
|
|
4090
|
+
getCurrentSearchTerm() {
|
|
4091
|
+
return this.searchTerm$.getValue();
|
|
4092
|
+
}
|
|
4093
|
+
/**
|
|
4094
|
+
* Проходит по древовидному представлению контактов менеджеров и записывает каждого менеджера в {@link Map} по ключу идентификатора.
|
|
4095
|
+
*
|
|
4096
|
+
* @param directionId Идентификатор направления продаж.
|
|
3774
4097
|
* @param manager Контакты менеджера по направлению продаж.
|
|
3775
4098
|
*/
|
|
3776
4099
|
mapManagers(directionId, manager) {
|
|
@@ -4262,199 +4585,19 @@ class ScFilesService {
|
|
|
4262
4585
|
case 'jpg':
|
|
4263
4586
|
case 'png':
|
|
4264
4587
|
case 'gif':
|
|
4265
|
-
case 'bmp':
|
|
4266
|
-
case 'tiff':
|
|
4267
|
-
document.icon = ScIconTypesEnum.iconImage;
|
|
4268
|
-
break;
|
|
4269
|
-
default:
|
|
4270
|
-
document.icon = ScIconTypesEnum.iconFile;
|
|
4271
|
-
break;
|
|
4272
|
-
}
|
|
4273
|
-
}
|
|
4274
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFilesService, deps: [{ token: i1$1.HttpClient }, { token: SC_URLS }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4275
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFilesService, providedIn: 'root' }); }
|
|
4276
|
-
}
|
|
4277
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFilesService, decorators: [{
|
|
4278
|
-
type: Injectable,
|
|
4279
|
-
args: [{
|
|
4280
|
-
providedIn: 'root',
|
|
4281
|
-
}]
|
|
4282
|
-
}], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: undefined, decorators: [{
|
|
4283
|
-
type: Inject,
|
|
4284
|
-
args: [SC_URLS]
|
|
4285
|
-
}] }] });
|
|
4286
|
-
|
|
4287
|
-
/**
|
|
4288
|
-
* Сервис аутентификации пользователя на основе ключей, переданных в параметрах запроса.
|
|
4289
|
-
*/
|
|
4290
|
-
class ScAuthAsClientGuard {
|
|
4291
|
-
/**
|
|
4292
|
-
* Инициализирует экземпляр класса {@link AuthAsClientGuard}.
|
|
4293
|
-
*
|
|
4294
|
-
* @param authService Сервис аутентификации.
|
|
4295
|
-
* @param router Сервис маршрутизации.
|
|
4296
|
-
* @param options Параметры авторизации под клиентом.
|
|
4297
|
-
*/
|
|
4298
|
-
constructor(authService, router, options) {
|
|
4299
|
-
this.authService = authService;
|
|
4300
|
-
this.router = router;
|
|
4301
|
-
this.options = options;
|
|
4302
|
-
}
|
|
4303
|
-
/**
|
|
4304
|
-
* Разрешает/запрещает доступ к маршруту.
|
|
4305
|
-
*
|
|
4306
|
-
* @param route Данные о текущем маршруте.
|
|
4307
|
-
*/
|
|
4308
|
-
// eslint-disable-next-line sonarjs/function-return-type
|
|
4309
|
-
canActivate(route) {
|
|
4310
|
-
const expiredAt = new Date();
|
|
4311
|
-
expiredAt.setMinutes(new Date().getMinutes() + this.options.expiredAtMinute);
|
|
4312
|
-
return this.authService.getAuthChange().pipe(first(),
|
|
4313
|
-
// Если пользователь авторизирован, то завершаем сеанс.
|
|
4314
|
-
concatMap((state) => (state ? this.authService.getSignOut$(false) : of(null))),
|
|
4315
|
-
// Обновляем полученные ключи, чтобы они перестали действовать. getRefreshTokenObservable() запишет новые ключи в систему, после чего проложение само запросит нового пользователя.
|
|
4316
|
-
concatMap(() => this.authService.getRefreshToken$({
|
|
4317
|
-
access: {
|
|
4318
|
-
token: route.paramMap.get('atoken') ?? '',
|
|
4319
|
-
expiredAt: expiredAt,
|
|
4320
|
-
},
|
|
4321
|
-
refresh: {
|
|
4322
|
-
token: route.paramMap.get('rtoken') ?? '',
|
|
4323
|
-
expiredAt: expiredAt,
|
|
4324
|
-
},
|
|
4325
|
-
})), first(), map(() => this.router.createUrlTree(this.options.urlTree)));
|
|
4326
|
-
}
|
|
4327
|
-
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 }); }
|
|
4328
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard }); }
|
|
4329
|
-
}
|
|
4330
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard, decorators: [{
|
|
4331
|
-
type: Injectable
|
|
4332
|
-
}], ctorParameters: () => [{ type: ScAuthService }, { type: i2.Router }, { type: undefined, decorators: [{
|
|
4333
|
-
type: Inject,
|
|
4334
|
-
args: [SC_AUTH_AS_CLIENT_OPTIONS]
|
|
4335
|
-
}] }] });
|
|
4336
|
-
|
|
4337
|
-
/**
|
|
4338
|
-
* Значения пагинации списка товаров категории по умолчанию.
|
|
4339
|
-
*/
|
|
4340
|
-
const SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS = {
|
|
4341
|
-
perPage: 20,
|
|
4342
|
-
page: 0,
|
|
4343
|
-
};
|
|
4344
|
-
/**
|
|
4345
|
-
* Токен значений пагинации списка товаров в каталоге по умолчанию.
|
|
4346
|
-
*/
|
|
4347
|
-
const SC_PRODUCT_PAGINATION_OPTIONS = tuiCreateToken(SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS);
|
|
4348
|
-
/**
|
|
4349
|
-
* Токен {@link EventEmitter} событие нажатия на кнопку "Показать следующие позиции категории".
|
|
4350
|
-
*/
|
|
4351
|
-
const SC_NEXT_PAGE_PAGINATION_CLICK = tuiCreateToken(new EventEmitter());
|
|
4352
|
-
|
|
4353
|
-
/**
|
|
4354
|
-
* Сервис поиска по каталогу.
|
|
4355
|
-
*/
|
|
4356
|
-
class ScSearchService {
|
|
4357
|
-
/**
|
|
4358
|
-
* Инициализирует экземпляр класса {@link ScSearchService}.
|
|
4359
|
-
*
|
|
4360
|
-
* @param http HTTP-клиент.
|
|
4361
|
-
* @param urls Список ссылок на разделы backend'a.
|
|
4362
|
-
* @param userMetrikaService Сервис для сбора метрик о действиях пользователей.
|
|
4363
|
-
*/
|
|
4364
|
-
constructor(http, urls, userMetrikaService) {
|
|
4365
|
-
this.http = http;
|
|
4366
|
-
this.urls = urls;
|
|
4367
|
-
this.userMetrikaService = userMetrikaService;
|
|
4368
|
-
/**
|
|
4369
|
-
* {@link BehaviorSubject} поискового запрос.
|
|
4370
|
-
*/
|
|
4371
|
-
this.searchTerm$ = new BehaviorSubject(null);
|
|
4372
|
-
}
|
|
4373
|
-
/**
|
|
4374
|
-
* Выполняет упрощенный поиск товаров и категорий. Возвращает ограниченное количество записей.
|
|
4375
|
-
*
|
|
4376
|
-
* @param term Поисковый запрос.
|
|
4377
|
-
*/
|
|
4378
|
-
simple$(term) {
|
|
4379
|
-
return this.http.get(`${this.urls.apiUrl}/catalog/search/simple`, { params: { term: term } }).pipe(tap(() => {
|
|
4380
|
-
this.userMetrikaService.emitUserMetrikaEvent({
|
|
4381
|
-
target: ScUserMetrikaGoalsEnum.catalogSearch,
|
|
4382
|
-
params: {
|
|
4383
|
-
search_type: 'simple',
|
|
4384
|
-
term: term,
|
|
4385
|
-
},
|
|
4386
|
-
});
|
|
4387
|
-
}));
|
|
4388
|
-
}
|
|
4389
|
-
/**
|
|
4390
|
-
* Выполняет поиск категорий в каталоге.
|
|
4391
|
-
*
|
|
4392
|
-
* @param term Поисковый запрос.
|
|
4393
|
-
*/
|
|
4394
|
-
categories$(term) {
|
|
4395
|
-
return this.http.get(`${this.urls.apiUrl}/catalog/search/categories`, { params: { term: term } }).pipe(tap(() => {
|
|
4396
|
-
this.userMetrikaService.emitUserMetrikaEvent({
|
|
4397
|
-
target: ScUserMetrikaGoalsEnum.catalogSearch,
|
|
4398
|
-
params: {
|
|
4399
|
-
search_type: 'categories',
|
|
4400
|
-
term: term,
|
|
4401
|
-
},
|
|
4402
|
-
});
|
|
4403
|
-
}), map((categories) => categories.map((item) => new ScCategory(item))));
|
|
4404
|
-
}
|
|
4405
|
-
/**
|
|
4406
|
-
* Выполняет полный поиск по всему прайс-листу.
|
|
4407
|
-
*
|
|
4408
|
-
* @param term Поисковый запрос.
|
|
4409
|
-
* @param showOrderedProducts Признак того, что необходимо вернуть ранее заказанные продукты.
|
|
4410
|
-
* @param showFavoriteProducts Признак того, что необходимо вернуть избранные продукты.
|
|
4411
|
-
* @param showDiscountedProducts Признак того, что необходимо вернуть продукты со скидкой.
|
|
4412
|
-
*/
|
|
4413
|
-
full$(term, showOrderedProducts, showFavoriteProducts, showDiscountedProducts) {
|
|
4414
|
-
const params = {};
|
|
4415
|
-
if (term) {
|
|
4416
|
-
params['term'] = term;
|
|
4417
|
-
}
|
|
4418
|
-
if (showOrderedProducts) {
|
|
4419
|
-
params['show_ordered_products'] = Number(showOrderedProducts);
|
|
4420
|
-
}
|
|
4421
|
-
if (showFavoriteProducts) {
|
|
4422
|
-
params['show_favorite_products'] = Number(showFavoriteProducts);
|
|
4423
|
-
}
|
|
4424
|
-
if (showDiscountedProducts) {
|
|
4425
|
-
params['show_discounted_products'] = Number(showDiscountedProducts);
|
|
4426
|
-
}
|
|
4427
|
-
if (Object.keys(params).length > 0) {
|
|
4428
|
-
return this.http.get(`${this.urls.apiUrl}/catalog/search/full`, { params: params }).pipe(tap(() => {
|
|
4429
|
-
this.userMetrikaService.emitUserMetrikaEvent({
|
|
4430
|
-
target: ScUserMetrikaGoalsEnum.catalogSearch,
|
|
4431
|
-
params: {
|
|
4432
|
-
search_type: 'full',
|
|
4433
|
-
term: term,
|
|
4434
|
-
},
|
|
4435
|
-
});
|
|
4436
|
-
}));
|
|
4437
|
-
}
|
|
4438
|
-
return throwError(() => new Error('Необходимо указать хотя бы один параметр.'));
|
|
4439
|
-
}
|
|
4440
|
-
/**
|
|
4441
|
-
* Устанавливает поисковый запрос в {@link BehaviorSubject}.
|
|
4442
|
-
*
|
|
4443
|
-
* @param term Поисковый запрос.
|
|
4444
|
-
*/
|
|
4445
|
-
setSearchTermChange(term) {
|
|
4446
|
-
this.searchTerm$.next(term);
|
|
4447
|
-
}
|
|
4448
|
-
/**
|
|
4449
|
-
* Возвращает {@link Observable} поискового запроса.
|
|
4450
|
-
*/
|
|
4451
|
-
getSearchTermChange$() {
|
|
4452
|
-
return this.searchTerm$.asObservable();
|
|
4588
|
+
case 'bmp':
|
|
4589
|
+
case 'tiff':
|
|
4590
|
+
document.icon = ScIconTypesEnum.iconImage;
|
|
4591
|
+
break;
|
|
4592
|
+
default:
|
|
4593
|
+
document.icon = ScIconTypesEnum.iconFile;
|
|
4594
|
+
break;
|
|
4595
|
+
}
|
|
4453
4596
|
}
|
|
4454
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type:
|
|
4455
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type:
|
|
4597
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFilesService, deps: [{ token: i1$1.HttpClient }, { token: SC_URLS }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
4598
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFilesService, providedIn: 'root' }); }
|
|
4456
4599
|
}
|
|
4457
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type:
|
|
4600
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFilesService, decorators: [{
|
|
4458
4601
|
type: Injectable,
|
|
4459
4602
|
args: [{
|
|
4460
4603
|
providedIn: 'root',
|
|
@@ -4462,69 +4605,57 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
|
|
|
4462
4605
|
}], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: undefined, decorators: [{
|
|
4463
4606
|
type: Inject,
|
|
4464
4607
|
args: [SC_URLS]
|
|
4465
|
-
}] }
|
|
4466
|
-
|
|
4467
|
-
/**
|
|
4468
|
-
* Токен поиска введенного терма.
|
|
4469
|
-
*/
|
|
4470
|
-
const SEARCH_TERM = new InjectionToken('SEARCH_TERM');
|
|
4471
|
-
/**
|
|
4472
|
-
* Токен минимального количества введенных символов в поле поиска.
|
|
4473
|
-
*/
|
|
4474
|
-
const SC_MIN_LENGTH_SEARCH_TERM = new InjectionToken('SC_MIN_LENGTH_SEARCH_TERM');
|
|
4475
|
-
/**
|
|
4476
|
-
* Токен максимального количества введенных символов в поле поиска.
|
|
4477
|
-
*/
|
|
4478
|
-
const SC_MAX_LENGTH_SEARCH_TERM = new InjectionToken('SC_MAX_LENGTH_SEARCH_TERM');
|
|
4479
|
-
/**
|
|
4480
|
-
* Возвращает введенный терм для поиска.
|
|
4481
|
-
*
|
|
4482
|
-
* @param searchService Сервис поиска по каталогу.
|
|
4483
|
-
* @param minLengthSearchTerm Минимальное количество введенных символов в поле поиска.
|
|
4484
|
-
* @param maxLengthSearchTerm Максимальное количество введенных символов в поле поиска.
|
|
4485
|
-
*/
|
|
4486
|
-
function searchTermFactory(searchService, minLengthSearchTerm, maxLengthSearchTerm) {
|
|
4487
|
-
return searchService
|
|
4488
|
-
.getSearchTermChange$()
|
|
4489
|
-
.pipe(map((searchTerm) => (searchTerm && searchTerm.length >= minLengthSearchTerm && searchTerm.length <= maxLengthSearchTerm ? searchTerm : '')));
|
|
4490
|
-
}
|
|
4491
|
-
/**
|
|
4492
|
-
* Провайдеры данных о поиске введенного терма.
|
|
4493
|
-
*/
|
|
4494
|
-
const SEARCH_TERM_PROVIDERS = [
|
|
4495
|
-
{
|
|
4496
|
-
provide: SEARCH_TERM,
|
|
4497
|
-
deps: [ScSearchService, SC_MIN_LENGTH_SEARCH_TERM, SC_MAX_LENGTH_SEARCH_TERM],
|
|
4498
|
-
useFactory: searchTermFactory,
|
|
4499
|
-
},
|
|
4500
|
-
];
|
|
4608
|
+
}] }] });
|
|
4501
4609
|
|
|
4502
|
-
/* eslint-disable no-param-reassign,no-return-assign,jsdoc/check-param-names */
|
|
4503
|
-
/**
|
|
4504
|
-
* Токен потока данных о виртуальной категории.
|
|
4505
|
-
*/
|
|
4506
|
-
const SC_VIRTUAL_CATEGORY_INFO = new InjectionToken('A stream with current virtual category information');
|
|
4507
4610
|
/**
|
|
4508
|
-
*
|
|
4509
|
-
*
|
|
4510
|
-
* @param paramMap Параметры.
|
|
4511
|
-
* @param paramMap.paramMap Параметры.
|
|
4512
|
-
* @param catalogService.paramMap Параметры маршрута.
|
|
4513
|
-
* @param catalogService Сервис для работы с каталогом.
|
|
4611
|
+
* Сервис аутентификации пользователя на основе ключей, переданных в параметрах запроса.
|
|
4514
4612
|
*/
|
|
4515
|
-
|
|
4516
|
-
|
|
4613
|
+
class ScAuthAsClientGuard {
|
|
4614
|
+
/**
|
|
4615
|
+
* Инициализирует экземпляр класса {@link AuthAsClientGuard}.
|
|
4616
|
+
*
|
|
4617
|
+
* @param authService Сервис аутентификации.
|
|
4618
|
+
* @param router Сервис маршрутизации.
|
|
4619
|
+
* @param options Параметры авторизации под клиентом.
|
|
4620
|
+
*/
|
|
4621
|
+
constructor(authService, router, options) {
|
|
4622
|
+
this.authService = authService;
|
|
4623
|
+
this.router = router;
|
|
4624
|
+
this.options = options;
|
|
4625
|
+
}
|
|
4626
|
+
/**
|
|
4627
|
+
* Разрешает/запрещает доступ к маршруту.
|
|
4628
|
+
*
|
|
4629
|
+
* @param route Данные о текущем маршруте.
|
|
4630
|
+
*/
|
|
4631
|
+
// eslint-disable-next-line sonarjs/function-return-type
|
|
4632
|
+
canActivate(route) {
|
|
4633
|
+
const expiredAt = new Date();
|
|
4634
|
+
expiredAt.setMinutes(new Date().getMinutes() + this.options.expiredAtMinute);
|
|
4635
|
+
return this.authService.getAuthChange().pipe(first(),
|
|
4636
|
+
// Если пользователь авторизирован, то завершаем сеанс.
|
|
4637
|
+
concatMap((state) => (state ? this.authService.getSignOut$(false) : of(null))),
|
|
4638
|
+
// Обновляем полученные ключи, чтобы они перестали действовать. getRefreshTokenObservable() запишет новые ключи в систему, после чего проложение само запросит нового пользователя.
|
|
4639
|
+
concatMap(() => this.authService.getRefreshToken$({
|
|
4640
|
+
access: {
|
|
4641
|
+
token: route.paramMap.get('atoken') ?? '',
|
|
4642
|
+
expiredAt: expiredAt,
|
|
4643
|
+
},
|
|
4644
|
+
refresh: {
|
|
4645
|
+
token: route.paramMap.get('rtoken') ?? '',
|
|
4646
|
+
expiredAt: expiredAt,
|
|
4647
|
+
},
|
|
4648
|
+
})), first(), map(() => this.router.createUrlTree(this.options.urlTree)));
|
|
4649
|
+
}
|
|
4650
|
+
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 }); }
|
|
4651
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard }); }
|
|
4517
4652
|
}
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
deps: [ActivatedRoute, ScCatalogService],
|
|
4525
|
-
useFactory: virtualCategoryFactory,
|
|
4526
|
-
},
|
|
4527
|
-
];
|
|
4653
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard, decorators: [{
|
|
4654
|
+
type: Injectable
|
|
4655
|
+
}], ctorParameters: () => [{ type: ScAuthService }, { type: i2.Router }, { type: undefined, decorators: [{
|
|
4656
|
+
type: Inject,
|
|
4657
|
+
args: [SC_AUTH_AS_CLIENT_OPTIONS]
|
|
4658
|
+
}] }] });
|
|
4528
4659
|
|
|
4529
4660
|
/**
|
|
4530
4661
|
* Страж выполняющий проверку маршрута товара и категории, и редиректа в зависимости от настроек окружения.
|
|
@@ -4547,7 +4678,7 @@ const ScIdOrSlugGuard = (route) => {
|
|
|
4547
4678
|
}
|
|
4548
4679
|
if (productIdOrSlug && /^\d+$/.test(productIdOrSlug) !== (idOrSlug === 'id')) {
|
|
4549
4680
|
return inject(ScCatalogService)
|
|
4550
|
-
.
|
|
4681
|
+
.getProductData$(productIdOrSlug)
|
|
4551
4682
|
.pipe(filter(tuiIsPresent),
|
|
4552
4683
|
// eslint-disable-next-line security/detect-object-injection
|
|
4553
4684
|
map((product) => router.createUrlTree(['/catalog', 'product', product[idOrSlug]])));
|
|
@@ -5575,146 +5706,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
|
|
|
5575
5706
|
args: [SC_UPDATE_INTERVAL]
|
|
5576
5707
|
}] }] });
|
|
5577
5708
|
|
|
5578
|
-
/**
|
|
5579
|
-
* Сервис для работы с UTM-меткой страницы.
|
|
5580
|
-
*/
|
|
5581
|
-
class ScUTMService {
|
|
5582
|
-
/**
|
|
5583
|
-
* Инициализирует экземпляр класса {@link ScUTMService}.
|
|
5584
|
-
*/
|
|
5585
|
-
constructor() {
|
|
5586
|
-
/**
|
|
5587
|
-
* Список ссылок на разделы backend.
|
|
5588
|
-
*/
|
|
5589
|
-
this.urls = inject(SC_URLS);
|
|
5590
|
-
/**
|
|
5591
|
-
* Сервис для выполнения HTTP-запросов.
|
|
5592
|
-
*/
|
|
5593
|
-
this.http = inject(HttpClient);
|
|
5594
|
-
/**
|
|
5595
|
-
* Сервис аутентификации пользователей.
|
|
5596
|
-
*/
|
|
5597
|
-
this.authService = inject(ScAuthService);
|
|
5598
|
-
/**
|
|
5599
|
-
* Сервис предоставляющий доступ к данным о маршруте.
|
|
5600
|
-
*/
|
|
5601
|
-
this.activatedRoute = inject(ActivatedRoute);
|
|
5602
|
-
/**
|
|
5603
|
-
* Сервис маршрутизации.
|
|
5604
|
-
*/
|
|
5605
|
-
this.router = inject(Router);
|
|
5606
|
-
/**
|
|
5607
|
-
* Сервис для работы с {@link Storage} и внедрению его через DI.
|
|
5608
|
-
*/
|
|
5609
|
-
this.storageService = inject(StorageService);
|
|
5610
|
-
/**
|
|
5611
|
-
* Признак, что скрипт выполняется в браузере.
|
|
5612
|
-
*/
|
|
5613
|
-
this.isBrowser = inject(IS_BROWSER);
|
|
5614
|
-
/**
|
|
5615
|
-
* Хранилище {@link Storage}.
|
|
5616
|
-
*/
|
|
5617
|
-
this.storage = inject(WA_LOCAL_STORAGE, { optional: true });
|
|
5618
|
-
/**
|
|
5619
|
-
* Время жизни UTM метки (ms).
|
|
5620
|
-
*/
|
|
5621
|
-
this.utmLifeTime = inject(SC_CACHE_LIFETIME).utm;
|
|
5622
|
-
/**
|
|
5623
|
-
* {@link Observable} UTM-метка страницы.
|
|
5624
|
-
*/
|
|
5625
|
-
this.utm$ = inject(WA_STORAGE_EVENT).pipe(filterByKey('utm'), toValue(), startWith(this.getUTMParams()), map((utmString) => (utmString === null ? utmString : JSON.parse(utmString))));
|
|
5626
|
-
/**
|
|
5627
|
-
* {@link Observable} timestamp сохранения UTM в {@link Storage}.
|
|
5628
|
-
*/
|
|
5629
|
-
this.utmTimestamp$ = inject(WA_STORAGE_EVENT).pipe(filterByKey('utmTimestamp'), toValue(), startWith(this.getUTMTimestamp()), map((timestamp) => (isString(timestamp) ? Number(timestamp) : timestamp)));
|
|
5630
|
-
/**
|
|
5631
|
-
* {@link Observable} UTM-метки страницы из параметров роутинга.
|
|
5632
|
-
*/
|
|
5633
|
-
this.utmParamsFromRoute$ = this.router.events.pipe(filter((event) => Boolean(this.storage) && this.isBrowser && event instanceof NavigationEnd), map(() => this.activatedRoute), startWith(this.activatedRoute), map((route) => route.snapshot.queryParams),
|
|
5634
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
5635
|
-
filter((params) => params['utm_source'] && params['utm_medium'] && params['utm_campaign']), map((params) => {
|
|
5636
|
-
return {
|
|
5637
|
-
source: params.utm_source,
|
|
5638
|
-
medium: params.utm_medium,
|
|
5639
|
-
campaign: params.utm_campaign,
|
|
5640
|
-
content: params.utm_content,
|
|
5641
|
-
term: params.utm_term,
|
|
5642
|
-
};
|
|
5643
|
-
}));
|
|
5644
|
-
// При получении UTM-метки сохраняем ее в Storage и создаём запрос сохранения метки за клиентом.
|
|
5645
|
-
this.authService
|
|
5646
|
-
.getAuthChange()
|
|
5647
|
-
.pipe(switchMap(() => this.utmParamsFromRoute$.pipe(distinctUntilChanged((previous, current) => isMatch(previous, current)))), tap((utm) => {
|
|
5648
|
-
this.setUTM(utm);
|
|
5649
|
-
}), switchMap((utm) => this.saveUTM$(utm)))
|
|
5650
|
-
.subscribe();
|
|
5651
|
-
// Удаляем UTM при выходе из аккаунта.
|
|
5652
|
-
this.authService
|
|
5653
|
-
.getAuthChange()
|
|
5654
|
-
.pipe(skip(1), filter((state) => !state))
|
|
5655
|
-
.subscribe(() => {
|
|
5656
|
-
this.removeUTM();
|
|
5657
|
-
});
|
|
5658
|
-
}
|
|
5659
|
-
/**
|
|
5660
|
-
* Возвращает строчное представление параметров UTM из {@link Storage}.
|
|
5661
|
-
*/
|
|
5662
|
-
getUTMParams() {
|
|
5663
|
-
return Boolean(this.storage) && this.isBrowser ? this.storageService.getItem('utm') : null;
|
|
5664
|
-
}
|
|
5665
|
-
/**
|
|
5666
|
-
* Возвращает строчное представление timestamp сохранения UTM из {@link Storage}.
|
|
5667
|
-
*/
|
|
5668
|
-
getUTMTimestamp() {
|
|
5669
|
-
return Boolean(this.storage) && this.isBrowser ? this.storageService.getItem('utmTimestamp') : null;
|
|
5670
|
-
}
|
|
5671
|
-
/**
|
|
5672
|
-
* Устанавливает UTM-метку страницы в {@link Storage}.
|
|
5673
|
-
*
|
|
5674
|
-
* @param utm Данные о UTM-метке.
|
|
5675
|
-
*/
|
|
5676
|
-
setUTM(utm) {
|
|
5677
|
-
if (this.storage && this.isBrowser) {
|
|
5678
|
-
this.storageService.setItem('utm', JSON.stringify(utm));
|
|
5679
|
-
this.storageService.setItem('utmTimestamp', JSON.stringify(Date.now()));
|
|
5680
|
-
}
|
|
5681
|
-
}
|
|
5682
|
-
/**
|
|
5683
|
-
* Удаляет UTM-метку страницы из {@link Storage}.
|
|
5684
|
-
*/
|
|
5685
|
-
removeUTM() {
|
|
5686
|
-
if (this.storage && this.isBrowser) {
|
|
5687
|
-
this.storageService.removeItem('utm');
|
|
5688
|
-
this.storageService.removeItem('utmTimestamp');
|
|
5689
|
-
}
|
|
5690
|
-
}
|
|
5691
|
-
/**
|
|
5692
|
-
* Возвращает {@link Observable} данных о UTM-метке.
|
|
5693
|
-
*/
|
|
5694
|
-
getUTM$() {
|
|
5695
|
-
return combineLatest({
|
|
5696
|
-
utm: this.utm$,
|
|
5697
|
-
timestamp: this.utmTimestamp$,
|
|
5698
|
-
}).pipe(map(({ utm, timestamp }) => (!this.utmLifeTime || (timestamp && timestamp + this.utmLifeTime > Date.now()) ? utm : null)));
|
|
5699
|
-
}
|
|
5700
|
-
/**
|
|
5701
|
-
* Возвращает {@link Observable} сохранения {@link ScUTM}.
|
|
5702
|
-
*
|
|
5703
|
-
* @param utm Данные о UTM-метке.
|
|
5704
|
-
*/
|
|
5705
|
-
saveUTM$(utm) {
|
|
5706
|
-
return this.http.post(`${this.urls.apiUrl}/utm`, utm);
|
|
5707
|
-
}
|
|
5708
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUTMService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5709
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUTMService, providedIn: 'root' }); }
|
|
5710
|
-
}
|
|
5711
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUTMService, decorators: [{
|
|
5712
|
-
type: Injectable,
|
|
5713
|
-
args: [{
|
|
5714
|
-
providedIn: 'root',
|
|
5715
|
-
}]
|
|
5716
|
-
}], ctorParameters: () => [] });
|
|
5717
|
-
|
|
5718
5709
|
/**
|
|
5719
5710
|
* Модель данных о бесплатной доставке.
|
|
5720
5711
|
*/
|
|
@@ -7159,5 +7150,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
|
|
|
7159
7150
|
* Generated bundle index. Do not edit.
|
|
7160
7151
|
*/
|
|
7161
7152
|
|
|
7162
|
-
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_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_VACANCIES_DATA_SOURCE, SC_VIRTUAL_CATEGORY_INFO, SC_VIRTUAL_CATEGORY_PROVIDERS, SEARCH_TERM, SEARCH_TERM_PROVIDERS, ScAuthAsClientGuard, ScAuthInterceptor, ScAuthService, ScBannerService, ScCacheInterceptor, ScCacheSettings, ScCachedData, ScCachedItem, ScCart, ScCartItem, ScCartService, ScCatalogFormat, ScCatalogService, ScCategory, ScClientType, ScConfiguratorService, ScContactsService, ScContragentService, ScConvertInterceptor, ScConvertersService, ScDeliveryAddressService, ScDeliveryCost, ScDeliveryType, ScDocumentInfoNode, ScDocumentInfoTypesEnum, ScErrorsInterceptor, ScFavoriteService, ScFeedbackService, ScFilesService, ScFrequentlyAskedQuestionsService, ScGuestInterceptor, ScISalesDirectionCart, ScISuggestionType, ScIconTypesEnum, ScIdOrSlugGuard, ScIdOrSlugPipe, ScImageHelper, ScJsonLdComponent, ScJsonLdModule, ScLocationsService, 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, 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 };
|
|
7153
|
+
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_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_VACANCIES_DATA_SOURCE, SC_VIRTUAL_CATEGORY_INFO, SC_VIRTUAL_CATEGORY_PROVIDERS, SEARCH_TERM, SEARCH_TERM_PROVIDERS, ScAuthAsClientGuard, ScAuthInterceptor, ScAuthService, ScBannerService, ScCacheInterceptor, ScCacheSettings, ScCachedData, ScCachedItem, ScCart, ScCartItem, ScCartService, ScCatalogFormat, ScCatalogService, ScCategory, ScClientType, ScConfiguratorService, ScContactsService, ScContragentService, ScConvertInterceptor, ScConvertersService, ScDeliveryAddressService, ScDeliveryCost, ScDeliveryType, ScDocumentInfoNode, ScDocumentInfoTypesEnum, ScErrorsInterceptor, ScFavoriteService, ScFeedbackForms, ScFeedbackService, ScFilesService, ScFrequentlyAskedQuestionsService, ScGuestInterceptor, ScISalesDirectionCart, ScISuggestionType, ScIconTypesEnum, ScIdOrSlugGuard, ScIdOrSlugPipe, ScImageHelper, ScJsonLdComponent, ScJsonLdModule, ScLocationsService, 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, 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 };
|
|
7163
7154
|
//# sourceMappingURL=snabcentr-client-core.mjs.map
|