@snabcentr/client-ui 0.10.0 → 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of @snabcentr/client-ui might be problematic. Click here for more details.

package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snabcentr/client-ui",
3
- "version": "0.10.0",
3
+ "version": "0.11.1",
4
4
  "author": "Snabcentr Ltd.",
5
5
  "repository": "https://gitlab.snabcentr.met/web/angular/snabcentr-client-ui-lib",
6
6
  "license": "Commercial",
@@ -14,7 +14,7 @@
14
14
  "@angular/platform-browser": ">=14.2.12",
15
15
  "@angular/platform-browser-dynamic": ">=14.2.12",
16
16
  "@angular/material": ">=14.2.7",
17
- "@snabcentr/client-core": ">=^0.8.0",
17
+ "@snabcentr/client-core": ">=0.9.0",
18
18
  "@maskito/angular": ">=1.7.0",
19
19
  "@maskito/core": ">=1.7.0",
20
20
  "@taiga-ui/addon-charts": ">=3.42.1",
package/user/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export * from './reset-user-password/sc-reset-user-password.component';
2
- export * from './update-user-info-form/sc-update-user-info-form.component';
2
+ export * from './update-user-info-dialog/sc-update-user-info-dialog.component';
3
3
  export * from './user-phone-approve-dialog/sc-user-phone-approve-dialog.component';
4
4
  export * from './sc-user.module';
@@ -1,6 +1,6 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import * as i1 from "./reset-user-password/sc-reset-user-password.component";
3
- import * as i2 from "./update-user-info-form/sc-update-user-info-form.component";
3
+ import * as i2 from "./update-user-info-dialog/sc-update-user-info-dialog.component";
4
4
  import * as i3 from "./user-phone-approve-dialog/sc-user-phone-approve-dialog.component";
5
5
  import * as i4 from "@angular/common";
6
6
  import * as i5 from "@angular/forms";
@@ -14,6 +14,6 @@ import * as i10 from "../form-fields/form-fields.module";
14
14
  */
15
15
  export declare class ScUserModule {
16
16
  static ɵfac: i0.ɵɵFactoryDeclaration<ScUserModule, never>;
17
- static ɵmod: i0.ɵɵNgModuleDeclaration<ScUserModule, [typeof i1.ScResetUserPasswordComponent, typeof i2.ScUpdateUserInfoFormComponent, typeof i3.ScUserPhoneApproveDialogComponent], [typeof i4.CommonModule, typeof i5.FormsModule, typeof i5.ReactiveFormsModule, typeof i6.TuiFieldErrorPipeModule, typeof i6.TuiInputPasswordModule, typeof i7.TuiButtonModule, typeof i7.TuiErrorModule, typeof i7.TuiLabelModule, typeof i7.TuiTextfieldControllerModule, typeof i8.TuiLetModule, typeof i9.ScVerificationModule, typeof i10.ScFormFieldsModule, typeof i7.TuiLoaderModule, typeof i6.TuiInputModule, typeof i6.TuiInputPhoneModule, typeof i6.TuiCheckboxModule, typeof i6.TuiCheckboxLabeledModule, typeof i7.TuiDataListModule, typeof i6.TuiSelectModule, typeof i7.TuiModeModule], [typeof i1.ScResetUserPasswordComponent, typeof i2.ScUpdateUserInfoFormComponent, typeof i3.ScUserPhoneApproveDialogComponent]>;
17
+ static ɵmod: i0.ɵɵNgModuleDeclaration<ScUserModule, [typeof i1.ScResetUserPasswordComponent, typeof i2.ScUpdateUserInfoDialogComponent, typeof i3.ScUserPhoneApproveDialogComponent], [typeof i4.CommonModule, typeof i5.FormsModule, typeof i5.ReactiveFormsModule, typeof i6.TuiFieldErrorPipeModule, typeof i6.TuiInputPasswordModule, typeof i7.TuiButtonModule, typeof i7.TuiErrorModule, typeof i7.TuiLabelModule, typeof i7.TuiTextfieldControllerModule, typeof i8.TuiLetModule, typeof i9.ScVerificationModule, typeof i10.ScFormFieldsModule, typeof i7.TuiLoaderModule, typeof i6.TuiInputModule, typeof i6.TuiInputPhoneModule, typeof i6.TuiCheckboxModule, typeof i6.TuiCheckboxLabeledModule, typeof i7.TuiDataListModule, typeof i6.TuiSelectModule, typeof i7.TuiModeModule], [typeof i1.ScResetUserPasswordComponent, typeof i2.ScUpdateUserInfoDialogComponent, typeof i3.ScUserPhoneApproveDialogComponent]>;
18
18
  static ɵinj: i0.ɵɵInjectorDeclaration<ScUserModule>;
19
19
  }
@@ -2,13 +2,15 @@ import { EventEmitter } from '@angular/core';
2
2
  import { FormGroup, FormControl } from '@angular/forms';
3
3
  import { ScISuggestionType, ScUser, ScUserService } from '@snabcentr/client-core';
4
4
  import { Observable, Subject } from 'rxjs';
5
+ import { TuiDialogContext } from '@taiga-ui/core';
5
6
  import * as i0 from "@angular/core";
6
7
  /**
7
- * Компонент формы изменения данных пользователя.
8
+ * Диалоговое окно изменения данных пользователя.
8
9
  */
9
- export declare class ScUpdateUserInfoFormComponent {
10
+ export declare class ScUpdateUserInfoDialogComponent {
10
11
  readonly user$: Observable<ScUser>;
11
12
  private readonly userService;
13
+ readonly context?: TuiDialogContext<ScUser, ScUpdateUserInfoDialogComponent> | undefined;
12
14
  /**
13
15
  * Перечисление типов подсказок.
14
16
  */
@@ -45,12 +47,13 @@ export declare class ScUpdateUserInfoFormComponent {
45
47
  */
46
48
  readonly loading$: Observable<boolean>;
47
49
  /**
48
- * Инициализирует экземпляр класса {@link ScUpdateUserInfoFormComponent}.
50
+ * Инициализирует экземпляр класса {@link ScUpdateUserInfoDialogComponent}.
49
51
  *
50
52
  * @param user$ Поток информации о текущем пользователе.
51
53
  * @param userService Сервис информации о пользователе.
54
+ * @param context Контекст диалогового окна, в котором открыт компонент.
52
55
  */
53
- constructor(user$: Observable<ScUser>, userService: ScUserService);
54
- static ɵfac: i0.ɵɵFactoryDeclaration<ScUpdateUserInfoFormComponent, never>;
55
- static ɵcmp: i0.ɵɵComponentDeclaration<ScUpdateUserInfoFormComponent, "sc-update-user-info-form", never, {}, { "cancelButtonClick": "cancelButtonClick"; "successUpdateDate": "successUpdateDate"; }, never, never, false>;
56
+ constructor(user$: Observable<ScUser>, userService: ScUserService, context?: TuiDialogContext<ScUser, ScUpdateUserInfoDialogComponent> | undefined);
57
+ static ɵfac: i0.ɵɵFactoryDeclaration<ScUpdateUserInfoDialogComponent, [null, null, { optional: true; }]>;
58
+ static ɵcmp: i0.ɵɵComponentDeclaration<ScUpdateUserInfoDialogComponent, "sc-update-user-info-dialog", never, {}, { "cancelButtonClick": "cancelButtonClick"; "successUpdateDate": "successUpdateDate"; }, never, never, false>;
56
59
  }
@@ -1,97 +0,0 @@
1
- import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Output } from '@angular/core';
2
- import { FormGroup, FormControl, Validators } from '@angular/forms';
3
- import { ScISuggestionType } from '@snabcentr/client-core';
4
- import { SC_USER_INFO, SC_USER_PROVIDERS } from '../../providers/scUserProviders';
5
- import { Subject, catchError, filter, map, of, skip, startWith, switchMap } from 'rxjs';
6
- import { tuiIsFalsy } from '@taiga-ui/cdk';
7
- import * as i0 from "@angular/core";
8
- import * as i1 from "@snabcentr/client-core";
9
- import * as i2 from "@angular/common";
10
- import * as i3 from "@angular/forms";
11
- import * as i4 from "@taiga-ui/core";
12
- import * as i5 from "@taiga-ui/cdk";
13
- import * as i6 from "../../verification/verification-phone-check-form/sc-verification-phone-check-form.component";
14
- import * as i7 from "../../form-fields/addresses-selection-field/sc-addresses-selection-field.component";
15
- import * as i8 from "../../form-fields/suggestion-field/sc-suggestion-field.component";
16
- import * as i9 from "@taiga-ui/kit";
17
- import * as i10 from "rxjs";
18
- /**
19
- * Компонент формы изменения данных пользователя.
20
- */
21
- export class ScUpdateUserInfoFormComponent {
22
- /**
23
- * Инициализирует экземпляр класса {@link ScUpdateUserInfoFormComponent}.
24
- *
25
- * @param user$ Поток информации о текущем пользователе.
26
- * @param userService Сервис информации о пользователе.
27
- */
28
- constructor(user$, userService) {
29
- this.user$ = user$;
30
- this.userService = userService;
31
- /**
32
- * Перечисление типов подсказок.
33
- */
34
- this.suggestionType = ScISuggestionType;
35
- /**
36
- * Группа полей ввода формы общих данных пользователя для их редактирования.
37
- */
38
- this.form = new FormGroup({
39
- name: new FormControl(null, [Validators.required, Validators.minLength(3)]),
40
- email: new FormControl(null, [Validators.required, Validators.email]),
41
- phone: new FormControl(null, [Validators.required, Validators.minLength(12)]),
42
- verificationCode: new FormControl(null, [Validators.required, Validators.minLength(6)]),
43
- cityId: new FormControl(null, Validators.required),
44
- getNews: new FormControl(false),
45
- });
46
- /**
47
- * Сигнал нажатия на кнопку "Отмена".
48
- */
49
- this.cancelButtonClick = new EventEmitter();
50
- /**
51
- * Сигнал события успешного обновления данных пользователя.
52
- */
53
- this.successUpdateDate = this.user$.pipe(skip(1));
54
- /**
55
- * {@link Subject} события отправки формы.
56
- */
57
- this.onSubmit = new Subject();
58
- /**
59
- * {@link Observable} запроса обновления данных пользователя.
60
- */
61
- this.request$ = this.onSubmit.pipe(filter(() => this.form.valid), map(() => this.form.value), switchMap((value) => this.userService.updateUserInfo$(value).pipe(switchMap(() => this.userService.updateUserChange$()), catchError((error) => {
62
- const errorResponse = error.error;
63
- for (const key in errorResponse.errors) {
64
- this.form.get(key)?.setErrors({ serverResponse: errorResponse.errors[`${key}`] });
65
- }
66
- if (!errorResponse.errors && errorResponse.message) {
67
- this.form.setErrors({ serverResponse: [errorResponse.message] });
68
- }
69
- return of({});
70
- }), startWith(null))));
71
- /**
72
- * {@link Observable} изменения состояния загрузки данных аутентификации по email.
73
- */
74
- this.loading$ = this.request$.pipe(map(tuiIsFalsy));
75
- this.user$.subscribe((user) => this.form.patchValue({
76
- name: user.name,
77
- email: user.contacts.email.value,
78
- phone: user.contacts.phone.value,
79
- cityId: user.city,
80
- getNews: user.getNews,
81
- }, { emitEvent: false }));
82
- }
83
- }
84
- ScUpdateUserInfoFormComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ScUpdateUserInfoFormComponent, deps: [{ token: SC_USER_INFO }, { token: i1.ScUserService }], target: i0.ɵɵFactoryTarget.Component });
85
- ScUpdateUserInfoFormComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: ScUpdateUserInfoFormComponent, selector: "sc-update-user-info-form", outputs: { cancelButtonClick: "cancelButtonClick", successUpdateDate: "successUpdateDate" }, providers: [SC_USER_PROVIDERS], ngImport: i0, template: "<form [formGroup]=\"form\" *ngIf=\"user$ | async as user\" (ngSubmit)=\"onSubmit.next()\" class=\"flex flex-col gap-4\">\n <label [tuiLabel]=\"user.isOrg ? '\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0440\u0433\u0430\u043D\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043B\u0438 \u0418\u041F' : '\u0424.\u0418.\u041E.'\">\n <tui-input formControlName=\"name\">\n {{ user.isOrg ? '\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0440\u0433\u0430\u043D\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043B\u0438 \u0418\u041F' : '\u0424.\u0418.\u041E.' }}\n <ng-container *ngIf=\"user.isOrg\">\n <sc-suggestion-field *tuiDataList [type]=\"suggestionType.organization\"></sc-suggestion-field>\n </ng-container>\n </tui-input>\n <tui-error formControlName=\"name\" [error]=\"[] | tuiFieldError | async\"></tui-error>\n </label>\n <sc-verification-phone-check-form\n *tuiLet=\"user.contacts.phone.value === form.value.phone as phoneIsChange\"\n [showCodeFields]=\"!phoneIsChange\"\n [shouldBeBusy]=\"phoneIsChange\"\n class=\"w-full\"\n ></sc-verification-phone-check-form>\n <label tuiLabel=\"\u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\" class=\"w-full\">\n <tui-input formControlName=\"email\">\n \u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\n <sc-suggestion-field *tuiDataList [type]=\"suggestionType.email\"></sc-suggestion-field>\n </tui-input>\n <tui-error formControlName=\"email\" [error]=\"[] | tuiFieldError | async\"></tui-error>\n </label>\n <sc-addresses-selection-field></sc-addresses-selection-field>\n <tui-checkbox-labeled formControlName=\"getNews\" class=\"w-full\"> \u042F \u0445\u043E\u0447\u0443 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u044C \u0440\u0430\u0441\u0441\u044B\u043B\u043A\u0443 \u0421\u043D\u0430\u0431\u0446\u0435\u043D\u0442\u0440 \u043E \u0441\u043A\u0438\u0434\u043A\u0430\u0445 \u0438 \u043D\u043E\u0432\u043E\u0441\u0442\u044F\u0445 \u043F\u043E \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u0435. </tui-checkbox-labeled>\n <div class=\"flex gap-4 justify-center\">\n <button tuiButton (click)=\"cancelButtonClick.emit\" type=\"button\" icon=\"tuiIconXLarge\" appearance=\"secondary\">\u041E\u0442\u043C\u0435\u043D\u0430</button>\n <button tuiButton tuiMode=\"onLight\" [disabled]=\"form.invalid\" [showLoader]=\"!!(loading$ | async)\" type=\"submit\" icon=\"scIconSave\">\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C</button>\n </div>\n</form>\n", dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i4.TuiButtonComponent, selector: "button[tuiButton], button[tuiIconButton], a[tuiButton], a[tuiIconButton]", inputs: ["appearance", "disabled", "icon", "iconRight", "shape", "showLoader", "size"] }, { kind: "component", type: i4.TuiErrorComponent, selector: "tui-error", inputs: ["error"] }, { kind: "component", type: i4.TuiLabelComponent, selector: "label[tuiLabel]", inputs: ["tuiLabel", "context"] }, { kind: "directive", type: i5.TuiLetDirective, selector: "[tuiLet]", inputs: ["tuiLet"] }, { kind: "component", type: i6.ScVerificationPhoneCheckFormComponent, selector: "sc-verification-phone-check-form", inputs: ["showCodeFields", "readOnly", "shouldBeBusy", "shouldBeConfirmed", "haveCode"], outputs: ["haveCodeChange"] }, { kind: "component", type: i7.ScAddressesSelectionFieldComponent, selector: "sc-addresses-selection-field" }, { kind: "component", type: i8.ScSuggestionFieldComponent, selector: "sc-suggestion-field", inputs: ["type"] }, { kind: "component", type: i9.TuiInputComponent, selector: "tui-input" }, { kind: "directive", type: i9.TuiInputDirective, selector: "tui-input" }, { kind: "component", type: i9.TuiCheckboxLabeledComponent, selector: "tui-checkbox-labeled", inputs: ["size"] }, { kind: "directive", type: i4.TuiDataListDirective, selector: "ng-template[tuiDataList]" }, { kind: "directive", type: i4.TuiModeDirective, selector: "[tuiMode]", inputs: ["tuiMode"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i9.TuiFieldErrorPipe, name: "tuiFieldError" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
86
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: ScUpdateUserInfoFormComponent, decorators: [{
87
- type: Component,
88
- args: [{ selector: 'sc-update-user-info-form', providers: [SC_USER_PROVIDERS], changeDetection: ChangeDetectionStrategy.OnPush, template: "<form [formGroup]=\"form\" *ngIf=\"user$ | async as user\" (ngSubmit)=\"onSubmit.next()\" class=\"flex flex-col gap-4\">\n <label [tuiLabel]=\"user.isOrg ? '\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0440\u0433\u0430\u043D\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043B\u0438 \u0418\u041F' : '\u0424.\u0418.\u041E.'\">\n <tui-input formControlName=\"name\">\n {{ user.isOrg ? '\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435 \u043E\u0440\u0433\u0430\u043D\u0438\u0437\u0430\u0446\u0438\u0438 \u0438\u043B\u0438 \u0418\u041F' : '\u0424.\u0418.\u041E.' }}\n <ng-container *ngIf=\"user.isOrg\">\n <sc-suggestion-field *tuiDataList [type]=\"suggestionType.organization\"></sc-suggestion-field>\n </ng-container>\n </tui-input>\n <tui-error formControlName=\"name\" [error]=\"[] | tuiFieldError | async\"></tui-error>\n </label>\n <sc-verification-phone-check-form\n *tuiLet=\"user.contacts.phone.value === form.value.phone as phoneIsChange\"\n [showCodeFields]=\"!phoneIsChange\"\n [shouldBeBusy]=\"phoneIsChange\"\n class=\"w-full\"\n ></sc-verification-phone-check-form>\n <label tuiLabel=\"\u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\" class=\"w-full\">\n <tui-input formControlName=\"email\">\n \u0410\u0434\u0440\u0435\u0441 \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u044B\n <sc-suggestion-field *tuiDataList [type]=\"suggestionType.email\"></sc-suggestion-field>\n </tui-input>\n <tui-error formControlName=\"email\" [error]=\"[] | tuiFieldError | async\"></tui-error>\n </label>\n <sc-addresses-selection-field></sc-addresses-selection-field>\n <tui-checkbox-labeled formControlName=\"getNews\" class=\"w-full\"> \u042F \u0445\u043E\u0447\u0443 \u043F\u043E\u043B\u0443\u0447\u0430\u0442\u044C \u0440\u0430\u0441\u0441\u044B\u043B\u043A\u0443 \u0421\u043D\u0430\u0431\u0446\u0435\u043D\u0442\u0440 \u043E \u0441\u043A\u0438\u0434\u043A\u0430\u0445 \u0438 \u043D\u043E\u0432\u043E\u0441\u0442\u044F\u0445 \u043F\u043E \u044D\u043B\u0435\u043A\u0442\u0440\u043E\u043D\u043D\u043E\u0439 \u043F\u043E\u0447\u0442\u0435. </tui-checkbox-labeled>\n <div class=\"flex gap-4 justify-center\">\n <button tuiButton (click)=\"cancelButtonClick.emit\" type=\"button\" icon=\"tuiIconXLarge\" appearance=\"secondary\">\u041E\u0442\u043C\u0435\u043D\u0430</button>\n <button tuiButton tuiMode=\"onLight\" [disabled]=\"form.invalid\" [showLoader]=\"!!(loading$ | async)\" type=\"submit\" icon=\"scIconSave\">\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C</button>\n </div>\n</form>\n" }]
89
- }], ctorParameters: function () { return [{ type: i10.Observable, decorators: [{
90
- type: Inject,
91
- args: [SC_USER_INFO]
92
- }] }, { type: i1.ScUserService }]; }, propDecorators: { cancelButtonClick: [{
93
- type: Output
94
- }], successUpdateDate: [{
95
- type: Output
96
- }] } });
97
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2MtdXBkYXRlLXVzZXItaW5mby1mb3JtLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NsaWVudC11aS91c2VyL3VwZGF0ZS11c2VyLWluZm8tZm9ybS9zYy11cGRhdGUtdXNlci1pbmZvLWZvcm0uY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvY2xpZW50LXVpL3VzZXIvdXBkYXRlLXVzZXItaW5mby1mb3JtL3NjLXVwZGF0ZS11c2VyLWluZm8tZm9ybS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pHLE9BQU8sRUFBRSxTQUFTLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3BFLE9BQU8sRUFBeUIsaUJBQWlCLEVBQThDLE1BQU0sd0JBQXdCLENBQUM7QUFDOUgsT0FBTyxFQUFFLFlBQVksRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ2xGLE9BQU8sRUFBYyxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRXBHLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxlQUFlLENBQUM7Ozs7Ozs7Ozs7OztBQUczQzs7R0FFRztBQU9ILE1BQU0sT0FBTyw2QkFBNkI7SUFrRXRDOzs7OztPQUtHO0lBQ0gsWUFBeUQsS0FBeUIsRUFBbUIsV0FBMEI7UUFBdEUsVUFBSyxHQUFMLEtBQUssQ0FBb0I7UUFBbUIsZ0JBQVcsR0FBWCxXQUFXLENBQWU7UUF2RS9IOztXQUVHO1FBQ2EsbUJBQWMsR0FBNkIsaUJBQWlCLENBQUM7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LEVBQUUsSUFBSSxDQUFDLElBQUk7WUFDZixLQUFLLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsS0FBSztZQUNoQyxLQUFLLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsS0FBSztZQUNoQyxNQUFNLEVBQUUsSUFBSSxDQUFDLElBQUk7WUFDakIsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPO1NBQ3hCLEVBQ0QsRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLENBQ3ZCLENBQ0osQ0FBQztJQUNOLENBQUM7OzBIQXJGUSw2QkFBNkIsa0JBd0VYLFlBQVk7OEdBeEU5Qiw2QkFBNkIsZ0pBSDNCLENBQUMsaUJBQWlCLENBQUMsMEJDZmxDLCt2RkE4QkE7MkZEWmEsNkJBQTZCO2tCQU56QyxTQUFTOytCQUNJLDBCQUEwQixhQUV6QixDQUFDLGlCQUFpQixDQUFDLG1CQUNiLHVCQUF1QixDQUFDLE1BQU07OzBCQTBFM0IsTUFBTTsyQkFBQyxZQUFZO3dFQWxEdkIsaUJBQWlCO3NCQURoQyxNQUFNO2dCQU9TLGlCQUFpQjtzQkFEaEMsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIEV2ZW50RW1pdHRlciwgSW5qZWN0LCBPdXRwdXQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEZvcm1Hcm91cCwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBTY0lQaG9uZU9uRGF0YUFwcHJvdmUsIFNjSVN1Z2dlc3Rpb25UeXBlLCBTY0lVc2VyT25EYXRhVXBkYXRlLCBTY1VzZXIsIFNjVXNlclNlcnZpY2UgfSBmcm9tICdAc25hYmNlbnRyL2NsaWVudC1jb3JlJztcbmltcG9ydCB7IFNDX1VTRVJfSU5GTywgU0NfVVNFUl9QUk9WSURFUlMgfSBmcm9tICcuLi8uLi9wcm92aWRlcnMvc2NVc2VyUHJvdmlkZXJzJztcbmltcG9ydCB7IE9ic2VydmFibGUsIFN1YmplY3QsIGNhdGNoRXJyb3IsIGZpbHRlciwgbWFwLCBvZiwgc2tpcCwgc3RhcnRXaXRoLCBzd2l0Y2hNYXAgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEh0dHBFcnJvclJlc3BvbnNlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgdHVpSXNGYWxzeSB9IGZyb20gJ0B0YWlnYS11aS9jZGsnO1xuaW1wb3J0IHsgQXBpRXJyb3JSZXNwb25zZSB9IGZyb20gJy4uLy4uL2F1dGgnO1xuXG4vKipcbiAqINCa0L7QvNC/0L7QvdC10L3RgiDRhNC+0YDQvNGLINC40LfQvNC10L3QtdC90LjRjyDQtNCw0L3QvdGL0YUg0L/QvtC70YzQt9C+0LLQsNGC0LXQu9GPLlxuICovXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ3NjLXVwZGF0ZS11c2VyLWluZm8tZm9ybScsXG4gICAgdGVtcGxhdGVVcmw6ICcuL3NjLXVwZGF0ZS11c2VyLWluZm8tZm9ybS5jb21wb25lbnQuaHRtbCcsXG4gICAgcHJvdmlkZXJzOiBbU0NfVVNFUl9QUk9WSURFUlNdLFxuICAgIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBTY1VwZGF0ZVVzZXJJbmZvRm9ybUNvbXBvbmVudCB7XG4gICAgLyoqXG4gICAgICog0J/QtdGA0LXRh9C40YHQu9C10L3QuNC1INGC0LjQv9C+0LIg0L/QvtC00YHQutCw0LfQvtC6LlxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSBzdWdnZXN0aW9uVHlwZTogdHlwZW9mIFNjSVN1Z2dlc3Rpb25UeXBlID0gU2NJU3VnZ2VzdGlvblR5cGU7XG5cbiAgICAvKipcbiAgICAgKiDQk9GA0YPQv9C/0LAg0L/QvtC70LXQuSDQstCy0L7QtNCwINGE0L7RgNC80Ysg0L7QsdGJ0LjRhSDQtNCw0L3QvdGL0YUg0L/QvtC70YzQt9C+0LLQsNGC0LXQu9GPINC00LvRjyDQuNGFINGA0LXQtNCw0LrRgtC40YDQvtCy0LDQvdC40Y8uXG4gICAgICovXG4gICAgcHVibGljIHJlYWRvbmx5IGZvcm0gPSBuZXcgRm9ybUdyb3VwKHtcbiAgICAgICAgbmFtZTogbmV3IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+KG51bGwsIFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLm1pbkxlbmd0aCgzKV0pLFxuICAgICAgICBlbWFpbDogbmV3IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+KG51bGwsIFtWYWxpZGF0b3JzLnJlcXVpcmVkLCBWYWxpZGF0b3JzLmVtYWlsXSksXG4gICAgICAgIHBob25lOiBuZXcgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4obnVsbCwgW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMubWluTGVuZ3RoKDEyKV0pLFxuICAgICAgICB2ZXJpZmljYXRpb25Db2RlOiBuZXcgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4obnVsbCwgW1ZhbGlkYXRvcnMucmVxdWlyZWQsIFZhbGlkYXRvcnMubWluTGVuZ3RoKDYpXSksXG4gICAgICAgIGNpdHlJZDogbmV3IEZvcm1Db250cm9sPG51bWJlciB8IG51bGw+KG51bGwsIFZhbGlkYXRvcnMucmVxdWlyZWQpLFxuICAgICAgICBnZXROZXdzOiBuZXcgRm9ybUNvbnRyb2w8Ym9vbGVhbj4oZmFsc2UpLFxuICAgIH0pO1xuXG4gICAgLyoqXG4gICAgICog0KHQuNCz0L3QsNC7INC90LDQttCw0YLQuNGPINC90LAg0LrQvdC+0L/QutGDIFwi0J7RgtC80LXQvdCwXCIuXG4gICAgICovXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIHJlYWRvbmx5IGNhbmNlbEJ1dHRvbkNsaWNrOiBFdmVudEVtaXR0ZXI8dm9pZD4gPSBuZXcgRXZlbnRFbWl0dGVyPHZvaWQ+KCk7XG5cbiAgICAvKipcbiAgICAgKiDQodC40LPQvdCw0Lsg0YHQvtCx0YvRgtC40Y8g0YPRgdC/0LXRiNC90L7Qs9C+INC+0LHQvdC+0LLQu9C10L3QuNGPINC00LDQvdC90YvRhSDQv9C+0LvRjNC30L7QstCw0YLQtdC70Y8uXG4gICAgICovXG4gICAgQE91dHB1dCgpXG4gICAgcHVibGljIHJlYWRvbmx5IHN1Y2Nlc3NVcGRhdGVEYXRlOiBPYnNlcnZhYmxlPFNjVXNlcj4gPSB0aGlzLnVzZXIkLnBpcGUoc2tpcCgxKSk7XG5cbiAgICAvKipcbiAgICAgKiB7QGxpbmsgU3ViamVjdH0g0YHQvtCx0YvRgtC40Y8g0L7RgtC/0YDQsNCy0LrQuCDRhNC+0YDQvNGLLlxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSBvblN1Ym1pdDogU3ViamVjdDx2b2lkPiA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG5cbiAgICAvKipcbiAgICAgKiB7QGxpbmsgT2JzZXJ2YWJsZX0g0LfQsNC/0YDQvtGB0LAg0L7QsdC90L7QstC70LXQvdC40Y8g0LTQsNC90L3Ri9GFINC/0L7Qu9GM0LfQvtCy0LDRgtC10LvRjy5cbiAgICAgKi9cbiAgICBwcml2YXRlIHJlYWRvbmx5IHJlcXVlc3QkID0gdGhpcy5vblN1Ym1pdC5waXBlKFxuICAgICAgICBmaWx0ZXIoKCkgPT4gdGhpcy5mb3JtLnZhbGlkKSxcbiAgICAgICAgbWFwKCgpID0+IHRoaXMuZm9ybS52YWx1ZSBhcyBTY0lVc2VyT25EYXRhVXBkYXRlIHwgU2NJUGhvbmVPbkRhdGFBcHByb3ZlKSxcbiAgICAgICAgc3dpdGNoTWFwKCh2YWx1ZSkgPT5cbiAgICAgICAgICAgIHRoaXMudXNlclNlcnZpY2UudXBkYXRlVXNlckluZm8kKHZhbHVlKS5waXBlKFxuICAgICAgICAgICAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLnVzZXJTZXJ2aWNlLnVwZGF0ZVVzZXJDaGFuZ2UkKCkpLFxuICAgICAgICAgICAgICAgIGNhdGNoRXJyb3IoKGVycm9yOiBIdHRwRXJyb3JSZXNwb25zZSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBlcnJvclJlc3BvbnNlID0gZXJyb3IuZXJyb3IgYXMgQXBpRXJyb3JSZXNwb25zZTtcblxuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBlcnJvclJlc3BvbnNlLmVycm9ycykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5mb3JtLmdldChrZXkpPy5zZXRFcnJvcnMoeyBzZXJ2ZXJSZXNwb25zZTogZXJyb3JSZXNwb25zZS5lcnJvcnNbYCR7a2V5fWBdIH0pO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKCFlcnJvclJlc3BvbnNlLmVycm9ycyAmJiBlcnJvclJlc3BvbnNlLm1lc3NhZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZm9ybS5zZXRFcnJvcnMoeyBzZXJ2ZXJSZXNwb25zZTogW2Vycm9yUmVzcG9uc2UubWVzc2FnZV0gfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG9mKHt9IGFzIFNjVXNlcik7XG4gICAgICAgICAgICAgICAgfSksXG4gICAgICAgICAgICAgICAgc3RhcnRXaXRoKG51bGwpXG4gICAgICAgICAgICApXG4gICAgICAgIClcbiAgICApO1xuXG4gICAgLyoqXG4gICAgICoge0BsaW5rIE9ic2VydmFibGV9INC40LfQvNC10L3QtdC90LjRjyDRgdC+0YHRgtC+0Y/QvdC40Y8g0LfQsNCz0YDRg9C30LrQuCDQtNCw0L3QvdGL0YUg0LDRg9GC0LXQvdGC0LjRhNC40LrQsNGG0LjQuCDQv9C+IGVtYWlsLlxuICAgICAqL1xuICAgIHB1YmxpYyByZWFkb25seSBsb2FkaW5nJDogT2JzZXJ2YWJsZTxib29sZWFuPiA9IHRoaXMucmVxdWVzdCQucGlwZShtYXAodHVpSXNGYWxzeSkpO1xuXG4gICAgLyoqXG4gICAgICog0JjQvdC40YbQuNCw0LvQuNC30LjRgNGD0LXRgiDRjdC60LfQtdC80L/Qu9GP0YAg0LrQu9Cw0YHRgdCwIHtAbGluayBTY1VwZGF0ZVVzZXJJbmZvRm9ybUNvbXBvbmVudH0uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gdXNlciQg0J/QvtGC0L7QuiDQuNC90YTQvtGA0LzQsNGG0LjQuCDQviDRgtC10LrRg9GJ0LXQvCDQv9C+0LvRjNC30L7QstCw0YLQtdC70LUuXG4gICAgICogQHBhcmFtIHVzZXJTZXJ2aWNlINCh0LXRgNCy0LjRgSDQuNC90YTQvtGA0LzQsNGG0LjQuCDQviDQv9C+0LvRjNC30L7QstCw0YLQtdC70LUuXG4gICAgICovXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKEBJbmplY3QoU0NfVVNFUl9JTkZPKSBwdWJsaWMgcmVhZG9ubHkgdXNlciQ6IE9ic2VydmFibGU8U2NVc2VyPiwgcHJpdmF0ZSByZWFkb25seSB1c2VyU2VydmljZTogU2NVc2VyU2VydmljZSkge1xuICAgICAgICB0aGlzLnVzZXIkLnN1YnNjcmliZSgodXNlcikgPT5cbiAgICAgICAgICAgIHRoaXMuZm9ybS5wYXRjaFZhbHVlKFxuICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogdXNlci5uYW1lLFxuICAgICAgICAgICAgICAgICAgICBlbWFpbDogdXNlci5jb250YWN0cy5lbWFpbC52YWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgcGhvbmU6IHVzZXIuY29udGFjdHMucGhvbmUudmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIGNpdHlJZDogdXNlci5jaXR5LFxuICAgICAgICAgICAgICAgICAgICBnZXROZXdzOiB1c2VyLmdldE5ld3MsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB7IGVtaXRFdmVudDogZmFsc2UgfVxuICAgICAgICAgICAgKVxuICAgICAgICApO1xuICAgIH1cbn1cbiIsIjxmb3JtIFtmb3JtR3JvdXBdPVwiZm9ybVwiICpuZ0lmPVwidXNlciQgfCBhc3luYyBhcyB1c2VyXCIgKG5nU3VibWl0KT1cIm9uU3VibWl0Lm5leHQoKVwiIGNsYXNzPVwiZmxleCBmbGV4LWNvbCBnYXAtNFwiPlxuICAgIDxsYWJlbCBbdHVpTGFiZWxdPVwidXNlci5pc09yZyA/ICfQndCw0LfQstCw0L3QuNC1INC+0YDQs9Cw0L3QuNC30LDRhtC40Lgg0LjQu9C4INCY0J8nIDogJ9CkLtCYLtCeLidcIj5cbiAgICAgICAgPHR1aS1pbnB1dCBmb3JtQ29udHJvbE5hbWU9XCJuYW1lXCI+XG4gICAgICAgICAgICB7eyB1c2VyLmlzT3JnID8gJ9Cd0LDQt9Cy0LDQvdC40LUg0L7RgNCz0LDQvdC40LfQsNGG0LjQuCDQuNC70Lgg0JjQnycgOiAn0KQu0Jgu0J4uJyB9fVxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInVzZXIuaXNPcmdcIj5cbiAgICAgICAgICAgICAgICA8c2Mtc3VnZ2VzdGlvbi1maWVsZCAqdHVpRGF0YUxpc3QgW3R5cGVdPVwic3VnZ2VzdGlvblR5cGUub3JnYW5pemF0aW9uXCI+PC9zYy1zdWdnZXN0aW9uLWZpZWxkPlxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgIDwvdHVpLWlucHV0PlxuICAgICAgICA8dHVpLWVycm9yIGZvcm1Db250cm9sTmFtZT1cIm5hbWVcIiBbZXJyb3JdPVwiW10gfCB0dWlGaWVsZEVycm9yIHwgYXN5bmNcIj48L3R1aS1lcnJvcj5cbiAgICA8L2xhYmVsPlxuICAgIDxzYy12ZXJpZmljYXRpb24tcGhvbmUtY2hlY2stZm9ybVxuICAgICAgICAqdHVpTGV0PVwidXNlci5jb250YWN0cy5waG9uZS52YWx1ZSA9PT0gZm9ybS52YWx1ZS5waG9uZSBhcyBwaG9uZUlzQ2hhbmdlXCJcbiAgICAgICAgW3Nob3dDb2RlRmllbGRzXT1cIiFwaG9uZUlzQ2hhbmdlXCJcbiAgICAgICAgW3Nob3VsZEJlQnVzeV09XCJwaG9uZUlzQ2hhbmdlXCJcbiAgICAgICAgY2xhc3M9XCJ3LWZ1bGxcIlxuICAgID48L3NjLXZlcmlmaWNhdGlvbi1waG9uZS1jaGVjay1mb3JtPlxuICAgIDxsYWJlbCB0dWlMYWJlbD1cItCQ0LTRgNC10YEg0Y3Qu9C10LrRgtGA0L7QvdC90L7QuSDQv9C+0YfRgtGLXCIgY2xhc3M9XCJ3LWZ1bGxcIj5cbiAgICAgICAgPHR1aS1pbnB1dCBmb3JtQ29udHJvbE5hbWU9XCJlbWFpbFwiPlxuICAgICAgICAgICAg0JDQtNGA0LXRgSDRjdC70LXQutGC0YDQvtC90L3QvtC5INC/0L7Rh9GC0YtcbiAgICAgICAgICAgIDxzYy1zdWdnZXN0aW9uLWZpZWxkICp0dWlEYXRhTGlzdCBbdHlwZV09XCJzdWdnZXN0aW9uVHlwZS5lbWFpbFwiPjwvc2Mtc3VnZ2VzdGlvbi1maWVsZD5cbiAgICAgICAgPC90dWktaW5wdXQ+XG4gICAgICAgIDx0dWktZXJyb3IgZm9ybUNvbnRyb2xOYW1lPVwiZW1haWxcIiBbZXJyb3JdPVwiW10gfCB0dWlGaWVsZEVycm9yIHwgYXN5bmNcIj48L3R1aS1lcnJvcj5cbiAgICA8L2xhYmVsPlxuICAgIDxzYy1hZGRyZXNzZXMtc2VsZWN0aW9uLWZpZWxkPjwvc2MtYWRkcmVzc2VzLXNlbGVjdGlvbi1maWVsZD5cbiAgICA8dHVpLWNoZWNrYm94LWxhYmVsZWQgZm9ybUNvbnRyb2xOYW1lPVwiZ2V0TmV3c1wiIGNsYXNzPVwidy1mdWxsXCI+INCvINGF0L7Rh9GDINC/0L7Qu9GD0YfQsNGC0Ywg0YDQsNGB0YHRi9C70LrRgyDQodC90LDQsdGG0LXQvdGC0YAg0L4g0YHQutC40LTQutCw0YUg0Lgg0L3QvtCy0L7RgdGC0Y/RhSDQv9C+INGN0LvQtdC60YLRgNC+0L3QvdC+0Lkg0L/QvtGH0YLQtS4gPC90dWktY2hlY2tib3gtbGFiZWxlZD5cbiAgICA8ZGl2IGNsYXNzPVwiZmxleCBnYXAtNCBqdXN0aWZ5LWNlbnRlclwiPlxuICAgICAgICA8YnV0dG9uIHR1aUJ1dHRvbiAoY2xpY2spPVwiY2FuY2VsQnV0dG9uQ2xpY2suZW1pdFwiIHR5cGU9XCJidXR0b25cIiBpY29uPVwidHVpSWNvblhMYXJnZVwiIGFwcGVhcmFuY2U9XCJzZWNvbmRhcnlcIj7QntGC0LzQtdC90LA8L2J1dHRvbj5cbiAgICAgICAgPGJ1dHRvbiB0dWlCdXR0b24gdHVpTW9kZT1cIm9uTGlnaHRcIiBbZGlzYWJsZWRdPVwiZm9ybS5pbnZhbGlkXCIgW3Nob3dMb2FkZXJdPVwiISEobG9hZGluZyQgfCBhc3luYylcIiB0eXBlPVwic3VibWl0XCIgaWNvbj1cInNjSWNvblNhdmVcIj7QodC+0YXRgNCw0L3QuNGC0Yw8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbjwvZm9ybT5cbiJdfQ==