@snabcentr/client-core 2.49.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/config/index.d.ts +1 -0
- package/config/sc-i-date-format.d.ts +17 -0
- package/contacts/services/sc-feedback.service.d.ts +4 -0
- package/esm2022/catalog/services/sc-catalog.service.mjs +27 -80
- package/esm2022/config/index.mjs +2 -1
- package/esm2022/config/sc-i-date-format.mjs +2 -0
- 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/order/services/sc-orders.service.mjs +12 -4
- package/esm2022/tokens/index.mjs +2 -1
- package/esm2022/tokens/sc-date-format.mjs +6 -0
- package/esm2022/utm/services/sc-utm.service.mjs +23 -12
- package/fesm2022/snabcentr-client-core.mjs +573 -569
- package/fesm2022/snabcentr-client-core.mjs.map +1 -1
- package/order/services/sc-orders.service.d.ts +4 -0
- package/package.json +3 -2
- package/release_notes.tmp +4 -3
- package/tokens/index.d.ts +1 -0
- package/tokens/sc-date-format.d.ts +6 -0
- 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,10 @@ 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 {
|
|
18
|
+
import { format, parse } from 'date-fns';
|
|
18
19
|
import * as i1$2 from '@angular/platform-browser';
|
|
19
20
|
import { Meta, Title } from '@angular/platform-browser';
|
|
20
21
|
|
|
@@ -302,6 +303,11 @@ const SC_URLS = new InjectionToken('IUrls');
|
|
|
302
303
|
*/
|
|
303
304
|
const SC_FEEDBACK_API = tuiCreateToken();
|
|
304
305
|
|
|
306
|
+
/**
|
|
307
|
+
* Токен внедрения формата дат.
|
|
308
|
+
*/
|
|
309
|
+
const SC_DATE_FORMAT = tuiCreateToken();
|
|
310
|
+
|
|
305
311
|
/**
|
|
306
312
|
* Перечисление названий целей метрики используемых для отслеживания действий пользователей.
|
|
307
313
|
*/
|
|
@@ -2951,18 +2957,6 @@ class ScCatalogService {
|
|
|
2951
2957
|
* {@link Map} коллекция пар ключ-значение для кэшированных товаров категории каталога.
|
|
2952
2958
|
*/
|
|
2953
2959
|
this.categoryProductsMap = new Map();
|
|
2954
|
-
/**
|
|
2955
|
-
* {@link Map} коллекция пар ключ-значение для кэшированных рекомендуемых товаров категории.
|
|
2956
|
-
*
|
|
2957
|
-
* @deprecated
|
|
2958
|
-
*/
|
|
2959
|
-
this.recommendedProductsByCategoryMap = new Map();
|
|
2960
|
-
/**
|
|
2961
|
-
* {@link Map} коллекция пар ключ-значение для кэшированных рекомендуемых товаров товара.
|
|
2962
|
-
*
|
|
2963
|
-
* @deprecated
|
|
2964
|
-
*/
|
|
2965
|
-
this.recommendedProductsByProductMap = new Map();
|
|
2966
2960
|
/**
|
|
2967
2961
|
* {@link Map} коллекция пар ключ-значение для кэширования истории цен.
|
|
2968
2962
|
*/
|
|
@@ -2972,9 +2966,13 @@ class ScCatalogService {
|
|
|
2972
2966
|
*/
|
|
2973
2967
|
this.idOrSlugPipe = inject(ScIdOrSlugPipe);
|
|
2974
2968
|
/**
|
|
2975
|
-
* {@link Map} коллекция пар ключ-значение для сопоставления slug и id категорий при
|
|
2969
|
+
* {@link Map} коллекция пар ключ-значение для сопоставления slug и id категорий при кешировании запросов, если идентификатор отличается от установленного в проекте (slug/id).
|
|
2976
2970
|
*/
|
|
2977
2971
|
this.categoryIdOrSlugMap = new Map();
|
|
2972
|
+
/**
|
|
2973
|
+
* {@link Map} коллекция пар ключ-значение для сопоставления slug и id товаров при кешировании запросов, если идентификатор отличается от установленного в проекте (slug/id).
|
|
2974
|
+
*/
|
|
2975
|
+
this.productIdOrSlugMap = new Map();
|
|
2978
2976
|
/**
|
|
2979
2977
|
* Число первых записей товаров со скидкой.
|
|
2980
2978
|
*/
|
|
@@ -3003,7 +3001,6 @@ class ScCatalogService {
|
|
|
3003
3001
|
.subscribe(() => {
|
|
3004
3002
|
this.idCategoryMap.clear();
|
|
3005
3003
|
this.categoryMap.clear();
|
|
3006
|
-
this.productMap.clear();
|
|
3007
3004
|
this.productHistoryMap.clear();
|
|
3008
3005
|
});
|
|
3009
3006
|
}
|
|
@@ -3022,21 +3019,6 @@ class ScCatalogService {
|
|
|
3022
3019
|
this.idCategoryMap.delete(categoryIdOrSlug?.toString());
|
|
3023
3020
|
return undefined;
|
|
3024
3021
|
}
|
|
3025
|
-
/**
|
|
3026
|
-
* Возвращает товар из коллекции каталога.
|
|
3027
|
-
*
|
|
3028
|
-
* @deprecated Удалить в рамках задачи TASK[#10153].
|
|
3029
|
-
*
|
|
3030
|
-
* @param productIdOrSlug Идентификатор или slug товара/услуги.
|
|
3031
|
-
*/
|
|
3032
|
-
getProductFromMap(productIdOrSlug) {
|
|
3033
|
-
const product = this.productMap.get(productIdOrSlug.toString());
|
|
3034
|
-
if (product) {
|
|
3035
|
-
return product;
|
|
3036
|
-
}
|
|
3037
|
-
this.productMap.delete(productIdOrSlug.toString());
|
|
3038
|
-
return undefined;
|
|
3039
|
-
}
|
|
3040
3022
|
/**
|
|
3041
3023
|
* Создает запрос получения списка категорий товаров или список корневых категорий, если идентификатор категории не указан.
|
|
3042
3024
|
*
|
|
@@ -3186,12 +3168,28 @@ class ScCatalogService {
|
|
|
3186
3168
|
*
|
|
3187
3169
|
* @param productIdOrSlug Идентификатор или slug товара/услуги.
|
|
3188
3170
|
*/
|
|
3189
|
-
|
|
3190
|
-
|
|
3191
|
-
|
|
3192
|
-
|
|
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);
|
|
3193
3188
|
}
|
|
3194
|
-
|
|
3189
|
+
if (!cachedItem.cachedDataIsActual()) {
|
|
3190
|
+
cachedItem.update();
|
|
3191
|
+
}
|
|
3192
|
+
return cachedItem.item$;
|
|
3195
3193
|
}
|
|
3196
3194
|
/**
|
|
3197
3195
|
* Создаёт запрос на получение генерируемого файла прайс-листа в формате {@link Blob}, и выгружает пользователю в браузер.
|
|
@@ -3214,51 +3212,6 @@ class ScCatalogService {
|
|
|
3214
3212
|
});
|
|
3215
3213
|
}));
|
|
3216
3214
|
}
|
|
3217
|
-
/**
|
|
3218
|
-
* Создает запрос получения списка ранее заказанных товаров.
|
|
3219
|
-
*
|
|
3220
|
-
* @deprecated Удалить в рамках задачи TASK[#10155].
|
|
3221
|
-
*/
|
|
3222
|
-
getPreviouslyOrderedProducts$() {
|
|
3223
|
-
if (!this.currentUserPreviouslyOrdered.cachedDataIsActual()) {
|
|
3224
|
-
this.currentUserPreviouslyOrdered.update();
|
|
3225
|
-
}
|
|
3226
|
-
return this.currentUserPreviouslyOrdered.item$;
|
|
3227
|
-
}
|
|
3228
|
-
/**
|
|
3229
|
-
* Создает запрос на получение списка рекомендованных товаров для категории.
|
|
3230
|
-
*
|
|
3231
|
-
* @param categoryIdOrSlug Идентификатор или slug категории товаров.
|
|
3232
|
-
* @deprecated
|
|
3233
|
-
*/
|
|
3234
|
-
getRecommendedProductsByCategory$(categoryIdOrSlug) {
|
|
3235
|
-
let cachedItem = this.recommendedProductsByCategoryMap.get(categoryIdOrSlug.toString());
|
|
3236
|
-
if (!cachedItem) {
|
|
3237
|
-
// Устанавливаем время жизни cachedItem равное, потому что нам не важно время жизни. Нам нужен функционал update().
|
|
3238
|
-
cachedItem = new ScCachedItem(0, this.http
|
|
3239
|
-
.get(`${this.urls.apiUrl}/catalog/categories/${categoryIdOrSlug}/recommendations`)
|
|
3240
|
-
.pipe(map((productsDTO) => productsDTO.map((product) => new ScProduct(product)))));
|
|
3241
|
-
this.recommendedProductsByCategoryMap.set(categoryIdOrSlug.toString(), cachedItem);
|
|
3242
|
-
}
|
|
3243
|
-
return cachedItem.item$;
|
|
3244
|
-
}
|
|
3245
|
-
/**
|
|
3246
|
-
* Создает запрос на получение списка рекомендованных товаров для продукта.
|
|
3247
|
-
*
|
|
3248
|
-
* @param productIdOrSlug Идентификатор или slug товара/услуги.
|
|
3249
|
-
* @deprecated
|
|
3250
|
-
*/
|
|
3251
|
-
getRecommendedProductsByProduct$(productIdOrSlug) {
|
|
3252
|
-
let cachedItem = this.recommendedProductsByProductMap.get(productIdOrSlug.toString());
|
|
3253
|
-
if (!cachedItem) {
|
|
3254
|
-
// Устанавливаем время жизни cachedItem равное, потому что нам не важно время жизни. Нам нужен функционал update().
|
|
3255
|
-
cachedItem = new ScCachedItem(0, this.http
|
|
3256
|
-
.get(`${this.urls.apiUrl}/catalog/products/${productIdOrSlug}/recommendations`)
|
|
3257
|
-
.pipe(map((productsDTO) => productsDTO.map((product) => new ScProduct(product)))));
|
|
3258
|
-
this.recommendedProductsByProductMap.set(productIdOrSlug.toString(), cachedItem);
|
|
3259
|
-
}
|
|
3260
|
-
return cachedItem.item$;
|
|
3261
|
-
}
|
|
3262
3215
|
/**
|
|
3263
3216
|
* Запрос на уведомление пользователя о поступлении продукта.
|
|
3264
3217
|
*
|
|
@@ -3581,6 +3534,37 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
|
|
|
3581
3534
|
args: [SC_URLS]
|
|
3582
3535
|
}] }, { type: ScCatalogService }] });
|
|
3583
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
|
+
|
|
3584
3568
|
/**
|
|
3585
3569
|
* Перечисление типов контактов по социальным сетям.
|
|
3586
3570
|
*/
|
|
@@ -3627,119 +3611,107 @@ class ScUploadedFile {
|
|
|
3627
3611
|
const SC_IS_HEADER_REQUIRED = new HttpContextToken(() => true);
|
|
3628
3612
|
|
|
3629
3613
|
/**
|
|
3630
|
-
*
|
|
3614
|
+
* Значения пагинации списка товаров категории по умолчанию.
|
|
3631
3615
|
*/
|
|
3632
|
-
|
|
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 {
|
|
3633
3633
|
/**
|
|
3634
|
-
* Инициализирует экземпляр класса {@link
|
|
3634
|
+
* Инициализирует экземпляр класса {@link ScSearchService}.
|
|
3635
3635
|
*
|
|
3636
3636
|
* @param http HTTP-клиент.
|
|
3637
|
+
* @param urls Список ссылок на разделы backend'a.
|
|
3637
3638
|
* @param userMetrikaService Сервис для сбора метрик о действиях пользователей.
|
|
3638
|
-
* @param feedbackApi Данные для взаимодействия с API обратной связи.
|
|
3639
3639
|
*/
|
|
3640
|
-
constructor(http,
|
|
3640
|
+
constructor(http, urls, userMetrikaService) {
|
|
3641
3641
|
this.http = http;
|
|
3642
|
+
this.urls = urls;
|
|
3642
3643
|
this.userMetrikaService = userMetrikaService;
|
|
3643
|
-
this.feedbackApi = feedbackApi;
|
|
3644
3644
|
/**
|
|
3645
|
-
*
|
|
3645
|
+
* {@link BehaviorSubject} поискового запрос.
|
|
3646
3646
|
*/
|
|
3647
|
-
this.
|
|
3648
|
-
.get(`${this.feedbackApi.apiUrl}/feedback/forms`, {
|
|
3649
|
-
context: new HttpContext().set(SC_AUTH_ADD_HEADER_REQUIRED, false).set(SC_IS_HEADER_REQUIRED, false),
|
|
3650
|
-
headers: {
|
|
3651
|
-
[this.feedbackApi.authTokenName]: this.feedbackApi.authToken,
|
|
3652
|
-
},
|
|
3653
|
-
})
|
|
3654
|
-
.pipe(shareReplay(1));
|
|
3647
|
+
this.searchTerm$ = new BehaviorSubject(null);
|
|
3655
3648
|
}
|
|
3656
3649
|
/**
|
|
3657
|
-
*
|
|
3650
|
+
* Выполняет упрощенный поиск товаров и категорий. Возвращает ограниченное количество записей.
|
|
3658
3651
|
*
|
|
3659
|
-
* @param
|
|
3660
|
-
* @param feedbackMessage Объект сообщения обратной связи.
|
|
3652
|
+
* @param term Поисковый запрос.
|
|
3661
3653
|
*/
|
|
3662
|
-
|
|
3663
|
-
return this.http
|
|
3664
|
-
.post(`${this.feedbackApi.apiUrl}/feedback/${formSlug}`, feedbackMessage, {
|
|
3665
|
-
context: new HttpContext().set(SC_AUTH_ADD_HEADER_REQUIRED, false).set(SC_IS_HEADER_REQUIRED, false),
|
|
3666
|
-
headers: {
|
|
3667
|
-
[this.feedbackApi.authTokenName]: this.feedbackApi.authToken,
|
|
3668
|
-
},
|
|
3669
|
-
})
|
|
3670
|
-
.pipe(tap(() => {
|
|
3654
|
+
simple$(term) {
|
|
3655
|
+
return this.http.get(`${this.urls.apiUrl}/catalog/search/simple`, { params: { term: term } }).pipe(tap(() => {
|
|
3671
3656
|
this.userMetrikaService.emitUserMetrikaEvent({
|
|
3672
|
-
target: ScUserMetrikaGoalsEnum.
|
|
3657
|
+
target: ScUserMetrikaGoalsEnum.catalogSearch,
|
|
3658
|
+
params: {
|
|
3659
|
+
search_type: 'simple',
|
|
3660
|
+
term: term,
|
|
3661
|
+
},
|
|
3673
3662
|
});
|
|
3674
3663
|
}));
|
|
3675
3664
|
}
|
|
3676
|
-
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 }); }
|
|
3677
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFeedbackService, providedIn: 'root' }); }
|
|
3678
|
-
}
|
|
3679
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFeedbackService, decorators: [{
|
|
3680
|
-
type: Injectable,
|
|
3681
|
-
args: [{
|
|
3682
|
-
providedIn: 'root',
|
|
3683
|
-
}]
|
|
3684
|
-
}], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: ScUserMetrikaService }, { type: undefined, decorators: [{
|
|
3685
|
-
type: Inject,
|
|
3686
|
-
args: [SC_FEEDBACK_API]
|
|
3687
|
-
}] }] });
|
|
3688
|
-
|
|
3689
|
-
/**
|
|
3690
|
-
* Сервис для работы с реквизитами и с обойной связью.
|
|
3691
|
-
*/
|
|
3692
|
-
class ScRequisitesService {
|
|
3693
3665
|
/**
|
|
3694
|
-
*
|
|
3666
|
+
* Выполняет поиск категорий в каталоге.
|
|
3695
3667
|
*
|
|
3696
|
-
* @param
|
|
3697
|
-
* @param urls Список ссылок на разделы backend'a.
|
|
3698
|
-
* @param authService Сервис аутентификации.
|
|
3668
|
+
* @param term Поисковый запрос.
|
|
3699
3669
|
*/
|
|
3700
|
-
|
|
3701
|
-
this.http
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
|
|
3705
|
-
|
|
3706
|
-
|
|
3707
|
-
|
|
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
|
-
|
|
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
|
+
},
|
|
3736
3711
|
});
|
|
3737
|
-
}
|
|
3738
|
-
}
|
|
3739
|
-
|
|
3740
|
-
* Создаёт запрос получения списка реквизитов компании.
|
|
3741
|
-
*/
|
|
3742
|
-
this.requisites$ = this.http.get(`${this.urls.apiUrl}/requisites`).pipe(shareReplay(1));
|
|
3712
|
+
}));
|
|
3713
|
+
}
|
|
3714
|
+
return throwError(() => new Error('Необходимо указать хотя бы один параметр.'));
|
|
3743
3715
|
}
|
|
3744
3716
|
/**
|
|
3745
3717
|
* Устанавливает поисковый запрос в {@link BehaviorSubject}.
|
|
@@ -3755,13 +3727,370 @@ class ScRequisitesService {
|
|
|
3755
3727
|
getSearchTermChange$() {
|
|
3756
3728
|
return this.searchTerm$.asObservable();
|
|
3757
3729
|
}
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
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
|
+
/**
|
|
3765
4094
|
* Проходит по древовидному представлению контактов менеджеров и записывает каждого менеджера в {@link Map} по ключу идентификатора.
|
|
3766
4095
|
*
|
|
3767
4096
|
* @param directionId Идентификатор направления продаж.
|
|
@@ -4259,196 +4588,16 @@ class ScFilesService {
|
|
|
4259
4588
|
case 'bmp':
|
|
4260
4589
|
case 'tiff':
|
|
4261
4590
|
document.icon = ScIconTypesEnum.iconImage;
|
|
4262
|
-
break;
|
|
4263
|
-
default:
|
|
4264
|
-
document.icon = ScIconTypesEnum.iconFile;
|
|
4265
|
-
break;
|
|
4266
|
-
}
|
|
4267
|
-
}
|
|
4268
|
-
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 }); }
|
|
4269
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFilesService, providedIn: 'root' }); }
|
|
4270
|
-
}
|
|
4271
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScFilesService, decorators: [{
|
|
4272
|
-
type: Injectable,
|
|
4273
|
-
args: [{
|
|
4274
|
-
providedIn: 'root',
|
|
4275
|
-
}]
|
|
4276
|
-
}], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: undefined, decorators: [{
|
|
4277
|
-
type: Inject,
|
|
4278
|
-
args: [SC_URLS]
|
|
4279
|
-
}] }] });
|
|
4280
|
-
|
|
4281
|
-
/**
|
|
4282
|
-
* Сервис аутентификации пользователя на основе ключей, переданных в параметрах запроса.
|
|
4283
|
-
*/
|
|
4284
|
-
class ScAuthAsClientGuard {
|
|
4285
|
-
/**
|
|
4286
|
-
* Инициализирует экземпляр класса {@link AuthAsClientGuard}.
|
|
4287
|
-
*
|
|
4288
|
-
* @param authService Сервис аутентификации.
|
|
4289
|
-
* @param router Сервис маршрутизации.
|
|
4290
|
-
* @param options Параметры авторизации под клиентом.
|
|
4291
|
-
*/
|
|
4292
|
-
constructor(authService, router, options) {
|
|
4293
|
-
this.authService = authService;
|
|
4294
|
-
this.router = router;
|
|
4295
|
-
this.options = options;
|
|
4296
|
-
}
|
|
4297
|
-
/**
|
|
4298
|
-
* Разрешает/запрещает доступ к маршруту.
|
|
4299
|
-
*
|
|
4300
|
-
* @param route Данные о текущем маршруте.
|
|
4301
|
-
*/
|
|
4302
|
-
// eslint-disable-next-line sonarjs/function-return-type
|
|
4303
|
-
canActivate(route) {
|
|
4304
|
-
const expiredAt = new Date();
|
|
4305
|
-
expiredAt.setMinutes(new Date().getMinutes() + this.options.expiredAtMinute);
|
|
4306
|
-
return this.authService.getAuthChange().pipe(first(),
|
|
4307
|
-
// Если пользователь авторизирован, то завершаем сеанс.
|
|
4308
|
-
concatMap((state) => (state ? this.authService.getSignOut$(false) : of(null))),
|
|
4309
|
-
// Обновляем полученные ключи, чтобы они перестали действовать. getRefreshTokenObservable() запишет новые ключи в систему, после чего проложение само запросит нового пользователя.
|
|
4310
|
-
concatMap(() => this.authService.getRefreshToken$({
|
|
4311
|
-
access: {
|
|
4312
|
-
token: route.paramMap.get('atoken') ?? '',
|
|
4313
|
-
expiredAt: expiredAt,
|
|
4314
|
-
},
|
|
4315
|
-
refresh: {
|
|
4316
|
-
token: route.paramMap.get('rtoken') ?? '',
|
|
4317
|
-
expiredAt: expiredAt,
|
|
4318
|
-
},
|
|
4319
|
-
})), first(), map(() => this.router.createUrlTree(this.options.urlTree)));
|
|
4320
|
-
}
|
|
4321
|
-
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 }); }
|
|
4322
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard }); }
|
|
4323
|
-
}
|
|
4324
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScAuthAsClientGuard, decorators: [{
|
|
4325
|
-
type: Injectable
|
|
4326
|
-
}], ctorParameters: () => [{ type: ScAuthService }, { type: i2.Router }, { type: undefined, decorators: [{
|
|
4327
|
-
type: Inject,
|
|
4328
|
-
args: [SC_AUTH_AS_CLIENT_OPTIONS]
|
|
4329
|
-
}] }] });
|
|
4330
|
-
|
|
4331
|
-
/**
|
|
4332
|
-
* Значения пагинации списка товаров категории по умолчанию.
|
|
4333
|
-
*/
|
|
4334
|
-
const SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS = {
|
|
4335
|
-
perPage: 20,
|
|
4336
|
-
page: 0,
|
|
4337
|
-
};
|
|
4338
|
-
/**
|
|
4339
|
-
* Токен значений пагинации списка товаров в каталоге по умолчанию.
|
|
4340
|
-
*/
|
|
4341
|
-
const SC_PRODUCT_PAGINATION_OPTIONS = tuiCreateToken(SC_PRODUCT_PAGINATION_DEFAULT_OPTIONS);
|
|
4342
|
-
/**
|
|
4343
|
-
* Токен {@link EventEmitter} событие нажатия на кнопку "Показать следующие позиции категории".
|
|
4344
|
-
*/
|
|
4345
|
-
const SC_NEXT_PAGE_PAGINATION_CLICK = tuiCreateToken(new EventEmitter());
|
|
4346
|
-
|
|
4347
|
-
/**
|
|
4348
|
-
* Сервис поиска по каталогу.
|
|
4349
|
-
*/
|
|
4350
|
-
class ScSearchService {
|
|
4351
|
-
/**
|
|
4352
|
-
* Инициализирует экземпляр класса {@link ScSearchService}.
|
|
4353
|
-
*
|
|
4354
|
-
* @param http HTTP-клиент.
|
|
4355
|
-
* @param urls Список ссылок на разделы backend'a.
|
|
4356
|
-
* @param userMetrikaService Сервис для сбора метрик о действиях пользователей.
|
|
4357
|
-
*/
|
|
4358
|
-
constructor(http, urls, userMetrikaService) {
|
|
4359
|
-
this.http = http;
|
|
4360
|
-
this.urls = urls;
|
|
4361
|
-
this.userMetrikaService = userMetrikaService;
|
|
4362
|
-
/**
|
|
4363
|
-
* {@link BehaviorSubject} поискового запрос.
|
|
4364
|
-
*/
|
|
4365
|
-
this.searchTerm$ = new BehaviorSubject(null);
|
|
4366
|
-
}
|
|
4367
|
-
/**
|
|
4368
|
-
* Выполняет упрощенный поиск товаров и категорий. Возвращает ограниченное количество записей.
|
|
4369
|
-
*
|
|
4370
|
-
* @param term Поисковый запрос.
|
|
4371
|
-
*/
|
|
4372
|
-
simple$(term) {
|
|
4373
|
-
return this.http.get(`${this.urls.apiUrl}/catalog/search/simple`, { params: { term: term } }).pipe(tap(() => {
|
|
4374
|
-
this.userMetrikaService.emitUserMetrikaEvent({
|
|
4375
|
-
target: ScUserMetrikaGoalsEnum.catalogSearch,
|
|
4376
|
-
params: {
|
|
4377
|
-
search_type: 'simple',
|
|
4378
|
-
term: term,
|
|
4379
|
-
},
|
|
4380
|
-
});
|
|
4381
|
-
}));
|
|
4382
|
-
}
|
|
4383
|
-
/**
|
|
4384
|
-
* Выполняет поиск категорий в каталоге.
|
|
4385
|
-
*
|
|
4386
|
-
* @param term Поисковый запрос.
|
|
4387
|
-
*/
|
|
4388
|
-
categories$(term) {
|
|
4389
|
-
return this.http.get(`${this.urls.apiUrl}/catalog/search/categories`, { params: { term: term } }).pipe(tap(() => {
|
|
4390
|
-
this.userMetrikaService.emitUserMetrikaEvent({
|
|
4391
|
-
target: ScUserMetrikaGoalsEnum.catalogSearch,
|
|
4392
|
-
params: {
|
|
4393
|
-
search_type: 'categories',
|
|
4394
|
-
term: term,
|
|
4395
|
-
},
|
|
4396
|
-
});
|
|
4397
|
-
}), map((categories) => categories.map((item) => new ScCategory(item))));
|
|
4398
|
-
}
|
|
4399
|
-
/**
|
|
4400
|
-
* Выполняет полный поиск по всему прайс-листу.
|
|
4401
|
-
*
|
|
4402
|
-
* @param term Поисковый запрос.
|
|
4403
|
-
* @param showOrderedProducts Признак того, что необходимо вернуть ранее заказанные продукты.
|
|
4404
|
-
* @param showFavoriteProducts Признак того, что необходимо вернуть избранные продукты.
|
|
4405
|
-
* @param showDiscountedProducts Признак того, что необходимо вернуть продукты со скидкой.
|
|
4406
|
-
*/
|
|
4407
|
-
full$(term, showOrderedProducts, showFavoriteProducts, showDiscountedProducts) {
|
|
4408
|
-
const params = {};
|
|
4409
|
-
if (term) {
|
|
4410
|
-
params['term'] = term;
|
|
4411
|
-
}
|
|
4412
|
-
if (showOrderedProducts) {
|
|
4413
|
-
params['show_ordered_products'] = Number(showOrderedProducts);
|
|
4414
|
-
}
|
|
4415
|
-
if (showFavoriteProducts) {
|
|
4416
|
-
params['show_favorite_products'] = Number(showFavoriteProducts);
|
|
4417
|
-
}
|
|
4418
|
-
if (showDiscountedProducts) {
|
|
4419
|
-
params['show_discounted_products'] = Number(showDiscountedProducts);
|
|
4420
|
-
}
|
|
4421
|
-
if (Object.keys(params).length > 0) {
|
|
4422
|
-
return this.http.get(`${this.urls.apiUrl}/catalog/search/full`, { params: params }).pipe(tap(() => {
|
|
4423
|
-
this.userMetrikaService.emitUserMetrikaEvent({
|
|
4424
|
-
target: ScUserMetrikaGoalsEnum.catalogSearch,
|
|
4425
|
-
params: {
|
|
4426
|
-
search_type: 'full',
|
|
4427
|
-
term: term,
|
|
4428
|
-
},
|
|
4429
|
-
});
|
|
4430
|
-
}));
|
|
4431
|
-
}
|
|
4432
|
-
return throwError(() => new Error('Необходимо указать хотя бы один параметр.'));
|
|
4433
|
-
}
|
|
4434
|
-
/**
|
|
4435
|
-
* Устанавливает поисковый запрос в {@link BehaviorSubject}.
|
|
4436
|
-
*
|
|
4437
|
-
* @param term Поисковый запрос.
|
|
4438
|
-
*/
|
|
4439
|
-
setSearchTermChange(term) {
|
|
4440
|
-
this.searchTerm$.next(term);
|
|
4441
|
-
}
|
|
4442
|
-
/**
|
|
4443
|
-
* Возвращает {@link Observable} поискового запроса.
|
|
4444
|
-
*/
|
|
4445
|
-
getSearchTermChange$() {
|
|
4446
|
-
return this.searchTerm$.asObservable();
|
|
4591
|
+
break;
|
|
4592
|
+
default:
|
|
4593
|
+
document.icon = ScIconTypesEnum.iconFile;
|
|
4594
|
+
break;
|
|
4595
|
+
}
|
|
4447
4596
|
}
|
|
4448
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type:
|
|
4449
|
-
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' }); }
|
|
4450
4599
|
}
|
|
4451
|
-
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: [{
|
|
4452
4601
|
type: Injectable,
|
|
4453
4602
|
args: [{
|
|
4454
4603
|
providedIn: 'root',
|
|
@@ -4456,69 +4605,57 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
|
|
|
4456
4605
|
}], ctorParameters: () => [{ type: i1$1.HttpClient }, { type: undefined, decorators: [{
|
|
4457
4606
|
type: Inject,
|
|
4458
4607
|
args: [SC_URLS]
|
|
4459
|
-
}] }
|
|
4460
|
-
|
|
4461
|
-
/**
|
|
4462
|
-
* Токен поиска введенного терма.
|
|
4463
|
-
*/
|
|
4464
|
-
const SEARCH_TERM = new InjectionToken('SEARCH_TERM');
|
|
4465
|
-
/**
|
|
4466
|
-
* Токен минимального количества введенных символов в поле поиска.
|
|
4467
|
-
*/
|
|
4468
|
-
const SC_MIN_LENGTH_SEARCH_TERM = new InjectionToken('SC_MIN_LENGTH_SEARCH_TERM');
|
|
4469
|
-
/**
|
|
4470
|
-
* Токен максимального количества введенных символов в поле поиска.
|
|
4471
|
-
*/
|
|
4472
|
-
const SC_MAX_LENGTH_SEARCH_TERM = new InjectionToken('SC_MAX_LENGTH_SEARCH_TERM');
|
|
4473
|
-
/**
|
|
4474
|
-
* Возвращает введенный терм для поиска.
|
|
4475
|
-
*
|
|
4476
|
-
* @param searchService Сервис поиска по каталогу.
|
|
4477
|
-
* @param minLengthSearchTerm Минимальное количество введенных символов в поле поиска.
|
|
4478
|
-
* @param maxLengthSearchTerm Максимальное количество введенных символов в поле поиска.
|
|
4479
|
-
*/
|
|
4480
|
-
function searchTermFactory(searchService, minLengthSearchTerm, maxLengthSearchTerm) {
|
|
4481
|
-
return searchService
|
|
4482
|
-
.getSearchTermChange$()
|
|
4483
|
-
.pipe(map((searchTerm) => (searchTerm && searchTerm.length >= minLengthSearchTerm && searchTerm.length <= maxLengthSearchTerm ? searchTerm : '')));
|
|
4484
|
-
}
|
|
4485
|
-
/**
|
|
4486
|
-
* Провайдеры данных о поиске введенного терма.
|
|
4487
|
-
*/
|
|
4488
|
-
const SEARCH_TERM_PROVIDERS = [
|
|
4489
|
-
{
|
|
4490
|
-
provide: SEARCH_TERM,
|
|
4491
|
-
deps: [ScSearchService, SC_MIN_LENGTH_SEARCH_TERM, SC_MAX_LENGTH_SEARCH_TERM],
|
|
4492
|
-
useFactory: searchTermFactory,
|
|
4493
|
-
},
|
|
4494
|
-
];
|
|
4608
|
+
}] }] });
|
|
4495
4609
|
|
|
4496
|
-
/* eslint-disable no-param-reassign,no-return-assign,jsdoc/check-param-names */
|
|
4497
|
-
/**
|
|
4498
|
-
* Токен потока данных о виртуальной категории.
|
|
4499
|
-
*/
|
|
4500
|
-
const SC_VIRTUAL_CATEGORY_INFO = new InjectionToken('A stream with current virtual category information');
|
|
4501
4610
|
/**
|
|
4502
|
-
*
|
|
4503
|
-
*
|
|
4504
|
-
* @param paramMap Параметры.
|
|
4505
|
-
* @param paramMap.paramMap Параметры.
|
|
4506
|
-
* @param catalogService.paramMap Параметры маршрута.
|
|
4507
|
-
* @param catalogService Сервис для работы с каталогом.
|
|
4611
|
+
* Сервис аутентификации пользователя на основе ключей, переданных в параметрах запроса.
|
|
4508
4612
|
*/
|
|
4509
|
-
|
|
4510
|
-
|
|
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 }); }
|
|
4511
4652
|
}
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
deps: [ActivatedRoute, ScCatalogService],
|
|
4519
|
-
useFactory: virtualCategoryFactory,
|
|
4520
|
-
},
|
|
4521
|
-
];
|
|
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
|
+
}] }] });
|
|
4522
4659
|
|
|
4523
4660
|
/**
|
|
4524
4661
|
* Страж выполняющий проверку маршрута товара и категории, и редиректа в зависимости от настроек окружения.
|
|
@@ -4541,7 +4678,7 @@ const ScIdOrSlugGuard = (route) => {
|
|
|
4541
4678
|
}
|
|
4542
4679
|
if (productIdOrSlug && /^\d+$/.test(productIdOrSlug) !== (idOrSlug === 'id')) {
|
|
4543
4680
|
return inject(ScCatalogService)
|
|
4544
|
-
.
|
|
4681
|
+
.getProductData$(productIdOrSlug)
|
|
4545
4682
|
.pipe(filter(tuiIsPresent),
|
|
4546
4683
|
// eslint-disable-next-line security/detect-object-injection
|
|
4547
4684
|
map((product) => router.createUrlTree(['/catalog', 'product', product[idOrSlug]])));
|
|
@@ -5569,146 +5706,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
|
|
|
5569
5706
|
args: [SC_UPDATE_INTERVAL]
|
|
5570
5707
|
}] }] });
|
|
5571
5708
|
|
|
5572
|
-
/**
|
|
5573
|
-
* Сервис для работы с UTM-меткой страницы.
|
|
5574
|
-
*/
|
|
5575
|
-
class ScUTMService {
|
|
5576
|
-
/**
|
|
5577
|
-
* Инициализирует экземпляр класса {@link ScUTMService}.
|
|
5578
|
-
*/
|
|
5579
|
-
constructor() {
|
|
5580
|
-
/**
|
|
5581
|
-
* Список ссылок на разделы backend.
|
|
5582
|
-
*/
|
|
5583
|
-
this.urls = inject(SC_URLS);
|
|
5584
|
-
/**
|
|
5585
|
-
* Сервис для выполнения HTTP-запросов.
|
|
5586
|
-
*/
|
|
5587
|
-
this.http = inject(HttpClient);
|
|
5588
|
-
/**
|
|
5589
|
-
* Сервис аутентификации пользователей.
|
|
5590
|
-
*/
|
|
5591
|
-
this.authService = inject(ScAuthService);
|
|
5592
|
-
/**
|
|
5593
|
-
* Сервис предоставляющий доступ к данным о маршруте.
|
|
5594
|
-
*/
|
|
5595
|
-
this.activatedRoute = inject(ActivatedRoute);
|
|
5596
|
-
/**
|
|
5597
|
-
* Сервис маршрутизации.
|
|
5598
|
-
*/
|
|
5599
|
-
this.router = inject(Router);
|
|
5600
|
-
/**
|
|
5601
|
-
* Сервис для работы с {@link Storage} и внедрению его через DI.
|
|
5602
|
-
*/
|
|
5603
|
-
this.storageService = inject(StorageService);
|
|
5604
|
-
/**
|
|
5605
|
-
* Признак, что скрипт выполняется в браузере.
|
|
5606
|
-
*/
|
|
5607
|
-
this.isBrowser = inject(IS_BROWSER);
|
|
5608
|
-
/**
|
|
5609
|
-
* Хранилище {@link Storage}.
|
|
5610
|
-
*/
|
|
5611
|
-
this.storage = inject(WA_LOCAL_STORAGE, { optional: true });
|
|
5612
|
-
/**
|
|
5613
|
-
* Время жизни UTM метки (ms).
|
|
5614
|
-
*/
|
|
5615
|
-
this.utmLifeTime = inject(SC_CACHE_LIFETIME).utm;
|
|
5616
|
-
/**
|
|
5617
|
-
* {@link Observable} UTM-метка страницы.
|
|
5618
|
-
*/
|
|
5619
|
-
this.utm$ = inject(WA_STORAGE_EVENT).pipe(filterByKey('utm'), toValue(), startWith(this.getUTMParams()), map((utmString) => (utmString === null ? utmString : JSON.parse(utmString))));
|
|
5620
|
-
/**
|
|
5621
|
-
* {@link Observable} timestamp сохранения UTM в {@link Storage}.
|
|
5622
|
-
*/
|
|
5623
|
-
this.utmTimestamp$ = inject(WA_STORAGE_EVENT).pipe(filterByKey('utmTimestamp'), toValue(), startWith(this.getUTMTimestamp()), map((timestamp) => (isString(timestamp) ? Number(timestamp) : timestamp)));
|
|
5624
|
-
/**
|
|
5625
|
-
* {@link Observable} UTM-метки страницы из параметров роутинга.
|
|
5626
|
-
*/
|
|
5627
|
-
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),
|
|
5628
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
|
|
5629
|
-
filter((params) => params['utm_source'] && params['utm_medium'] && params['utm_campaign']), map((params) => {
|
|
5630
|
-
return {
|
|
5631
|
-
source: params.utm_source,
|
|
5632
|
-
medium: params.utm_medium,
|
|
5633
|
-
campaign: params.utm_campaign,
|
|
5634
|
-
content: params.utm_content,
|
|
5635
|
-
term: params.utm_term,
|
|
5636
|
-
};
|
|
5637
|
-
}));
|
|
5638
|
-
// При получении UTM-метки сохраняем ее в Storage и создаём запрос сохранения метки за клиентом.
|
|
5639
|
-
this.authService
|
|
5640
|
-
.getAuthChange()
|
|
5641
|
-
.pipe(switchMap(() => this.utmParamsFromRoute$.pipe(distinctUntilChanged((previous, current) => isMatch(previous, current)))), tap((utm) => {
|
|
5642
|
-
this.setUTM(utm);
|
|
5643
|
-
}), switchMap((utm) => this.saveUTM$(utm)))
|
|
5644
|
-
.subscribe();
|
|
5645
|
-
// Удаляем UTM при выходе из аккаунта.
|
|
5646
|
-
this.authService
|
|
5647
|
-
.getAuthChange()
|
|
5648
|
-
.pipe(skip(1), filter((state) => !state))
|
|
5649
|
-
.subscribe(() => {
|
|
5650
|
-
this.removeUTM();
|
|
5651
|
-
});
|
|
5652
|
-
}
|
|
5653
|
-
/**
|
|
5654
|
-
* Возвращает строчное представление параметров UTM из {@link Storage}.
|
|
5655
|
-
*/
|
|
5656
|
-
getUTMParams() {
|
|
5657
|
-
return Boolean(this.storage) && this.isBrowser ? this.storageService.getItem('utm') : null;
|
|
5658
|
-
}
|
|
5659
|
-
/**
|
|
5660
|
-
* Возвращает строчное представление timestamp сохранения UTM из {@link Storage}.
|
|
5661
|
-
*/
|
|
5662
|
-
getUTMTimestamp() {
|
|
5663
|
-
return Boolean(this.storage) && this.isBrowser ? this.storageService.getItem('utmTimestamp') : null;
|
|
5664
|
-
}
|
|
5665
|
-
/**
|
|
5666
|
-
* Устанавливает UTM-метку страницы в {@link Storage}.
|
|
5667
|
-
*
|
|
5668
|
-
* @param utm Данные о UTM-метке.
|
|
5669
|
-
*/
|
|
5670
|
-
setUTM(utm) {
|
|
5671
|
-
if (this.storage && this.isBrowser) {
|
|
5672
|
-
this.storageService.setItem('utm', JSON.stringify(utm));
|
|
5673
|
-
this.storageService.setItem('utmTimestamp', JSON.stringify(Date.now()));
|
|
5674
|
-
}
|
|
5675
|
-
}
|
|
5676
|
-
/**
|
|
5677
|
-
* Удаляет UTM-метку страницы из {@link Storage}.
|
|
5678
|
-
*/
|
|
5679
|
-
removeUTM() {
|
|
5680
|
-
if (this.storage && this.isBrowser) {
|
|
5681
|
-
this.storageService.removeItem('utm');
|
|
5682
|
-
this.storageService.removeItem('utmTimestamp');
|
|
5683
|
-
}
|
|
5684
|
-
}
|
|
5685
|
-
/**
|
|
5686
|
-
* Возвращает {@link Observable} данных о UTM-метке.
|
|
5687
|
-
*/
|
|
5688
|
-
getUTM$() {
|
|
5689
|
-
return combineLatest({
|
|
5690
|
-
utm: this.utm$,
|
|
5691
|
-
timestamp: this.utmTimestamp$,
|
|
5692
|
-
}).pipe(map(({ utm, timestamp }) => (!this.utmLifeTime || (timestamp && timestamp + this.utmLifeTime > Date.now()) ? utm : null)));
|
|
5693
|
-
}
|
|
5694
|
-
/**
|
|
5695
|
-
* Возвращает {@link Observable} сохранения {@link ScUTM}.
|
|
5696
|
-
*
|
|
5697
|
-
* @param utm Данные о UTM-метке.
|
|
5698
|
-
*/
|
|
5699
|
-
saveUTM$(utm) {
|
|
5700
|
-
return this.http.post(`${this.urls.apiUrl}/utm`, utm);
|
|
5701
|
-
}
|
|
5702
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUTMService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
5703
|
-
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUTMService, providedIn: 'root' }); }
|
|
5704
|
-
}
|
|
5705
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScUTMService, decorators: [{
|
|
5706
|
-
type: Injectable,
|
|
5707
|
-
args: [{
|
|
5708
|
-
providedIn: 'root',
|
|
5709
|
-
}]
|
|
5710
|
-
}], ctorParameters: () => [] });
|
|
5711
|
-
|
|
5712
5709
|
/**
|
|
5713
5710
|
* Модель данных о бесплатной доставке.
|
|
5714
5711
|
*/
|
|
@@ -5979,6 +5976,10 @@ class ScOrdersService {
|
|
|
5979
5976
|
* Коллекция пар ключ-значение для заказов пользователя.
|
|
5980
5977
|
*/
|
|
5981
5978
|
this.idOrderMap = new Map();
|
|
5979
|
+
/**
|
|
5980
|
+
* Формат дат.
|
|
5981
|
+
*/
|
|
5982
|
+
this.dateFormats = inject(SC_DATE_FORMAT);
|
|
5982
5983
|
authService
|
|
5983
5984
|
.getAuthChange()
|
|
5984
5985
|
.pipe(filter((state) => !state))
|
|
@@ -6127,7 +6128,10 @@ class ScOrdersService {
|
|
|
6127
6128
|
date: date,
|
|
6128
6129
|
},
|
|
6129
6130
|
})
|
|
6130
|
-
.pipe(map((ordersPaginateDTO) =>
|
|
6131
|
+
.pipe(map((ordersPaginateDTO) => {
|
|
6132
|
+
const formattedDate = format(parse(date, this.dateFormats.api, new Date()), this.dateFormats.uiDate);
|
|
6133
|
+
return new ScDeliveryCost(ordersPaginateDTO, formattedDate);
|
|
6134
|
+
}));
|
|
6131
6135
|
}
|
|
6132
6136
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScOrdersService, deps: [{ token: i1$1.HttpClient }, { token: ScAuthService }, { token: SC_URLS }, { token: SC_UPDATE_INTERVAL }, { token: ScCartService }, { token: ScUIService }, { token: ScUserMetrikaService }], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
6133
6137
|
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.12", ngImport: i0, type: ScOrdersService, providedIn: 'root' }); }
|
|
@@ -7146,5 +7150,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.12", ngImpo
|
|
|
7146
7150
|
* Generated bundle index. Do not edit.
|
|
7147
7151
|
*/
|
|
7148
7152
|
|
|
7149
|
-
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_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 };
|
|
7150
7154
|
//# sourceMappingURL=snabcentr-client-core.mjs.map
|