@firestitch/form 14.0.0 → 14.0.2
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/app/components/confirm-unsaved/confirm-unsaved.component.d.ts +21 -21
- package/app/components/confirm-unsaved/index.d.ts +1 -1
- package/app/components/form-dialog-actions/form-dialog-actions.component.d.ts +22 -22
- package/app/components/form-dialog-actions/index.d.ts +1 -1
- package/app/components/form-template/form-template.component.d.ts +13 -13
- package/app/components/form-template/index.d.ts +1 -1
- package/app/components/form-template-outlet/form-template-outlet.component.d.ts +13 -13
- package/app/components/form-template-outlet/index.d.ts +1 -1
- package/app/components/index.d.ts +4 -4
- package/app/consts/error-messages.const.d.ts +21 -21
- package/app/directives/button.directive.d.ts +35 -35
- package/app/directives/form/form.directive.d.ts +122 -122
- package/app/directives/form/index.d.ts +1 -1
- package/app/directives/form-dialog-close.directive.d.ts +16 -16
- package/app/directives/form-template.directive.d.ts +10 -10
- package/app/directives/index.d.ts +6 -6
- package/app/directives/submit-button.directive.d.ts +6 -6
- package/app/directives/validators/compare.directive.d.ts +15 -15
- package/app/directives/validators/control.directive.d.ts +49 -49
- package/app/directives/validators/daterange.directive.d.ts +13 -13
- package/app/directives/validators/email.directive.d.ts +13 -13
- package/app/directives/validators/emails.directive.d.ts +13 -13
- package/app/directives/validators/function.directive.d.ts +15 -15
- package/app/directives/validators/greater-equal.directive.d.ts +13 -13
- package/app/directives/validators/greater.directive.d.ts +13 -13
- package/app/directives/validators/index.d.ts +22 -22
- package/app/directives/validators/integer.directive.d.ts +13 -13
- package/app/directives/validators/lesser-equal.directive.d.ts +13 -13
- package/app/directives/validators/lesser.directive.d.ts +13 -13
- package/app/directives/validators/max.directive.d.ts +13 -13
- package/app/directives/validators/maxlength.directive.d.ts +13 -13
- package/app/directives/validators/min.directive.d.ts +13 -13
- package/app/directives/validators/minlength.directive.d.ts +13 -13
- package/app/directives/validators/no-fs-validators.directive.d.ts +14 -14
- package/app/directives/validators/numeric.directive.d.ts +13 -13
- package/app/directives/validators/pattern.directive.d.ts +13 -13
- package/app/directives/validators/phone.directive.d.ts +13 -13
- package/app/directives/validators/required.directive.d.ts +16 -16
- package/app/directives/validators/url.directive.d.ts +14 -14
- package/app/directives/validators/validate.directive.d.ts +15 -15
- package/app/enums/confirm-result.d.ts +7 -7
- package/app/enums/form-status.d.ts +10 -10
- package/app/enums/index.d.ts +2 -2
- package/app/fs-form.module.d.ts +44 -44
- package/app/guards/form-deactivate.guard.d.ts +12 -12
- package/app/helpers/confirm-result-continue.d.ts +1 -1
- package/app/helpers/get-active-route.d.ts +2 -2
- package/app/helpers/get-form-errors.d.ts +2 -2
- package/app/helpers/index.d.ts +1 -1
- package/app/helpers/is-enabled.d.ts +1 -1
- package/app/interfaces/async-validator.d.ts +14 -14
- package/app/interfaces/confirm-config.d.ts +7 -7
- package/app/interfaces/confirm-tab-group.d.ts +10 -10
- package/app/interfaces/index.d.ts +4 -4
- package/app/interfaces/submit-event.d.ts +6 -6
- package/app/interfaces/submitted-event.d.ts +7 -7
- package/app/interfaces/validator.d.ts +13 -13
- package/app/providers/validate-messages.provider.d.ts +27 -27
- package/app/services/fsform.service.d.ts +20 -20
- package/app/validators/validators.d.ts +12 -12
- package/esm2020/app/components/confirm-unsaved/confirm-unsaved.component.mjs +43 -43
- package/esm2020/app/components/confirm-unsaved/index.mjs +1 -1
- package/esm2020/app/components/form-dialog-actions/form-dialog-actions.component.mjs +74 -74
- package/esm2020/app/components/form-dialog-actions/index.mjs +1 -1
- package/esm2020/app/components/form-template/form-template.component.mjs +31 -31
- package/esm2020/app/components/form-template/index.mjs +2 -2
- package/esm2020/app/components/form-template-outlet/form-template-outlet.component.mjs +30 -30
- package/esm2020/app/components/form-template-outlet/index.mjs +2 -2
- package/esm2020/app/components/index.mjs +4 -4
- package/esm2020/app/consts/error-messages.const.mjs +21 -21
- package/esm2020/app/directives/button.directive.mjs +151 -151
- package/esm2020/app/directives/form/form.directive.mjs +688 -688
- package/esm2020/app/directives/form/index.mjs +1 -1
- package/esm2020/app/directives/form-dialog-close.directive.mjs +53 -53
- package/esm2020/app/directives/form-template.directive.mjs +19 -19
- package/esm2020/app/directives/index.mjs +6 -6
- package/esm2020/app/directives/submit-button.directive.mjs +13 -13
- package/esm2020/app/directives/validators/compare.directive.mjs +46 -46
- package/esm2020/app/directives/validators/control.directive.mjs +257 -257
- package/esm2020/app/directives/validators/daterange.directive.mjs +40 -40
- package/esm2020/app/directives/validators/email.directive.mjs +40 -40
- package/esm2020/app/directives/validators/emails.directive.mjs +40 -40
- package/esm2020/app/directives/validators/function.directive.mjs +40 -40
- package/esm2020/app/directives/validators/greater-equal.directive.mjs +39 -39
- package/esm2020/app/directives/validators/greater.directive.mjs +39 -39
- package/esm2020/app/directives/validators/index.mjs +22 -22
- package/esm2020/app/directives/validators/integer.directive.mjs +38 -38
- package/esm2020/app/directives/validators/lesser-equal.directive.mjs +39 -39
- package/esm2020/app/directives/validators/lesser.directive.mjs +39 -39
- package/esm2020/app/directives/validators/max.directive.mjs +35 -35
- package/esm2020/app/directives/validators/maxlength.directive.mjs +34 -34
- package/esm2020/app/directives/validators/min.directive.mjs +35 -35
- package/esm2020/app/directives/validators/minlength.directive.mjs +34 -34
- package/esm2020/app/directives/validators/no-fs-validators.directive.mjs +52 -52
- package/esm2020/app/directives/validators/numeric.directive.mjs +40 -40
- package/esm2020/app/directives/validators/pattern.directive.mjs +34 -34
- package/esm2020/app/directives/validators/phone.directive.mjs +40 -40
- package/esm2020/app/directives/validators/required.directive.mjs +68 -68
- package/esm2020/app/directives/validators/url.directive.mjs +44 -44
- package/esm2020/app/directives/validators/validate.directive.mjs +42 -42
- package/esm2020/app/enums/confirm-result.mjs +8 -8
- package/esm2020/app/enums/form-status.mjs +11 -11
- package/esm2020/app/enums/index.mjs +2 -2
- package/esm2020/app/fs-form.module.mjs +208 -208
- package/esm2020/app/guards/form-deactivate.guard.mjs +41 -41
- package/esm2020/app/helpers/confirm-result-continue.mjs +4 -4
- package/esm2020/app/helpers/get-active-route.mjs +6 -6
- package/esm2020/app/helpers/get-form-errors.mjs +24 -24
- package/esm2020/app/helpers/index.mjs +1 -1
- package/esm2020/app/helpers/is-enabled.mjs +3 -3
- package/esm2020/app/interfaces/async-validator.mjs +1 -1
- package/esm2020/app/interfaces/confirm-config.mjs +1 -1
- package/esm2020/app/interfaces/confirm-tab-group.mjs +1 -1
- package/esm2020/app/interfaces/index.mjs +4 -4
- package/esm2020/app/interfaces/submit-event.mjs +1 -1
- package/esm2020/app/interfaces/submitted-event.mjs +1 -1
- package/esm2020/app/interfaces/validator.mjs +1 -1
- package/esm2020/app/providers/validate-messages.provider.mjs +10 -10
- package/esm2020/app/services/fsform.service.mjs +91 -91
- package/esm2020/app/validators/validators.mjs +92 -92
- package/esm2020/firestitch-form.mjs +4 -4
- package/esm2020/public_api.mjs +36 -36
- package/fesm2015/firestitch-form.mjs +2448 -2448
- package/fesm2015/firestitch-form.mjs.map +1 -1
- package/fesm2020/firestitch-form.mjs +2434 -2434
- package/fesm2020/firestitch-form.mjs.map +1 -1
- package/index.d.ts +5 -5
- package/package.json +1 -1
- package/public_api.d.ts +34 -34
|
@@ -1,689 +1,689 @@
|
|
|
1
|
-
import { ChangeDetectorRef, ContentChildren, Directive, ElementRef, EventEmitter, HostBinding, Inject, Input, NgZone, Optional, Output, QueryList, } from '@angular/core';
|
|
2
|
-
import { NgForm } from '@angular/forms';
|
|
3
|
-
import { ActivatedRoute } from '@angular/router';
|
|
4
|
-
import { MatDialogRef } from '@angular/material/dialog';
|
|
5
|
-
import { MatTabGroup } from '@angular/material/tabs';
|
|
6
|
-
import { guid } from '@firestitch/common';
|
|
7
|
-
import { DrawerRef } from '@firestitch/drawer';
|
|
8
|
-
import { FsMessage, MessageMode } from '@firestitch/message';
|
|
9
|
-
import { BehaviorSubject, defer, fromEvent, iif, of, Subject, throwError, } from 'rxjs';
|
|
10
|
-
import { catchError, delay, filter, first, map, mapTo, mergeMap, startWith, switchMap, take, takeUntil, tap, } from 'rxjs/operators';
|
|
11
|
-
import { FormDeactivateGuard } from '../../guards/form-deactivate.guard';
|
|
12
|
-
import { confirmResultContinue } from '../../helpers/confirm-result-continue';
|
|
13
|
-
import { getActiveRoute } from '../../helpers/get-active-route';
|
|
14
|
-
import { getFormErrors } from '../../helpers/get-form-errors';
|
|
15
|
-
import { FsForm } from '../../services/fsform.service';
|
|
16
|
-
import { ConfirmResult } from './../../enums/confirm-result';
|
|
17
|
-
import { FormStatus } from './../../enums/form-status';
|
|
18
|
-
import * as i0 from "@angular/core";
|
|
19
|
-
import * as i1 from "../../services/fsform.service";
|
|
20
|
-
import * as i2 from "@firestitch/message";
|
|
21
|
-
import * as i3 from "@angular/router";
|
|
22
|
-
import * as i4 from "@angular/forms";
|
|
23
|
-
import * as i5 from "@angular/material/dialog";
|
|
24
|
-
import * as i6 from "@firestitch/drawer";
|
|
25
|
-
export class FsFormDirective {
|
|
26
|
-
constructor(ngForm, _form, _element, _message, _ngZone, _cdRef, _dialogRef, _drawerRef, _route) {
|
|
27
|
-
this.ngForm = ngForm;
|
|
28
|
-
this._form = _form;
|
|
29
|
-
this._element = _element;
|
|
30
|
-
this._message = _message;
|
|
31
|
-
this._ngZone = _ngZone;
|
|
32
|
-
this._cdRef = _cdRef;
|
|
33
|
-
this._dialogRef = _dialogRef;
|
|
34
|
-
this._drawerRef = _drawerRef;
|
|
35
|
-
this._route = _route;
|
|
36
|
-
this.wrapperSelector = '.fs-form-wrapper,.mat-form-field';
|
|
37
|
-
this.messageSelector = '.fs-form-message,.mat-form-field-subscript-wrapper';
|
|
38
|
-
this.hintSelector = '.fs-form-hint,.mat-form-field-hint-wrapper';
|
|
39
|
-
this.labelSelector = '.fs-form-label,.mat-form-field-label';
|
|
40
|
-
this.autocomplete = false;
|
|
41
|
-
this.shortcuts = true; // Ctrl + s
|
|
42
|
-
this.confirm = true;
|
|
43
|
-
this.confirmDialog = true;
|
|
44
|
-
this.confirmDrawer = true;
|
|
45
|
-
this.confirmBrowser = true;
|
|
46
|
-
this.confirmTabs = true;
|
|
47
|
-
this.dirtySubmitButton = true;
|
|
48
|
-
this.successDelay = 0;
|
|
49
|
-
this.errorDelay = 1000;
|
|
50
|
-
this.deactivationGuard = true;
|
|
51
|
-
this.submitEvent = new EventEmitter();
|
|
52
|
-
this.invalid = new EventEmitter();
|
|
53
|
-
this.valid = new EventEmitter();
|
|
54
|
-
this.submitted = new EventEmitter();
|
|
55
|
-
this.reseted = new EventEmitter();
|
|
56
|
-
this.cleared = new EventEmitter();
|
|
57
|
-
this.fsFormClass = true;
|
|
58
|
-
this._tabGroups = new QueryList();
|
|
59
|
-
this._buttons = new QueryList();
|
|
60
|
-
this._dialogBackdropEscape = false;
|
|
61
|
-
this._snapshot = {};
|
|
62
|
-
this._status$ = new BehaviorSubject(FormStatus.Valid);
|
|
63
|
-
this._destroy$ = new Subject();
|
|
64
|
-
this._confirmed = false;
|
|
65
|
-
this._submit$ = null;
|
|
66
|
-
}
|
|
67
|
-
set submit(submit$) {
|
|
68
|
-
this._submit$ = submit$;
|
|
69
|
-
}
|
|
70
|
-
get submit() {
|
|
71
|
-
return this._submit$;
|
|
72
|
-
}
|
|
73
|
-
get submitting() {
|
|
74
|
-
return this._status$.getValue() === FormStatus.Submitting;
|
|
75
|
-
}
|
|
76
|
-
get validating() {
|
|
77
|
-
return this._status$.getValue() === FormStatus.Validating;
|
|
78
|
-
}
|
|
79
|
-
get completing() {
|
|
80
|
-
return this._status$.getValue() === FormStatus.Completing;
|
|
81
|
-
}
|
|
82
|
-
get _submitEvent() {
|
|
83
|
-
return {
|
|
84
|
-
ngForm: this.ngForm,
|
|
85
|
-
submitter: this._submitter,
|
|
86
|
-
};
|
|
87
|
-
}
|
|
88
|
-
get _formValidState$() {
|
|
89
|
-
this._form.broadcast('valid', this._submitEvent);
|
|
90
|
-
this.submitEvent.emit(this._submitEvent);
|
|
91
|
-
this.valid.emit(this._submitEvent);
|
|
92
|
-
const submittedEvent = {
|
|
93
|
-
ngForm: this.ngForm,
|
|
94
|
-
submitter: this._submitter,
|
|
95
|
-
response: null,
|
|
96
|
-
};
|
|
97
|
-
const submit$ = this._submit$ ?
|
|
98
|
-
this._submit$(this._submitEvent) : of(submittedEvent);
|
|
99
|
-
return submit$
|
|
100
|
-
.pipe(map((response) => {
|
|
101
|
-
submittedEvent.response = response;
|
|
102
|
-
return submittedEvent;
|
|
103
|
-
}), takeUntil(this._destroy$));
|
|
104
|
-
}
|
|
105
|
-
get _formInvalidState$() {
|
|
106
|
-
this._form.broadcast('invalid', this._submitEvent);
|
|
107
|
-
if (this.invalid) {
|
|
108
|
-
this.invalid.emit(this._submitEvent);
|
|
109
|
-
}
|
|
110
|
-
const message = 'Please review errors highlighted in red';
|
|
111
|
-
this._message.error(message, { mode: MessageMode.Toast });
|
|
112
|
-
const el = this._element.nativeElement.querySelector('.ng-invalid');
|
|
113
|
-
if (el) {
|
|
114
|
-
el.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
115
|
-
}
|
|
116
|
-
return throwError('Form validation error');
|
|
117
|
-
}
|
|
118
|
-
get _submitter() {
|
|
119
|
-
return this._activeSubmitButton
|
|
120
|
-
? this._activeSubmitButton.name
|
|
121
|
-
: null;
|
|
122
|
-
}
|
|
123
|
-
ngOnInit() {
|
|
124
|
-
if (this.deactivationGuard) {
|
|
125
|
-
this._registerCanDeactivateGuard();
|
|
126
|
-
}
|
|
127
|
-
this._registerConfirmDialogBackdropEscape();
|
|
128
|
-
this._listenHotKeys();
|
|
129
|
-
this._listenWindowClose();
|
|
130
|
-
this._listenSubmit();
|
|
131
|
-
this._listenFormStatus();
|
|
132
|
-
if (!this.autocomplete) {
|
|
133
|
-
this._registerAutocomplete();
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
ngOnChanges(changes) {
|
|
137
|
-
if (changes.confirm) {
|
|
138
|
-
this._updateDirtySubmitButtons();
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
clearSubmit() {
|
|
142
|
-
this._submit$ = null;
|
|
143
|
-
setTimeout(() => {
|
|
144
|
-
this._cdRef.markForCheck();
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
registerSubmit(submit$) {
|
|
148
|
-
this._submit$ = submit$;
|
|
149
|
-
setTimeout(() => {
|
|
150
|
-
this._cdRef.markForCheck();
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
ngAfterContentInit() {
|
|
154
|
-
this._registerConfirm();
|
|
155
|
-
this._registerConfirmDrawerClose();
|
|
156
|
-
this._registerConfirmTabs();
|
|
157
|
-
this._registerDrawerClose();
|
|
158
|
-
this._registerDirtySubmitButton();
|
|
159
|
-
}
|
|
160
|
-
ngOnDestroy() {
|
|
161
|
-
this._cleanupCanDeactivate();
|
|
162
|
-
this._destroy$.next();
|
|
163
|
-
this._destroy$.complete();
|
|
164
|
-
}
|
|
165
|
-
createSnapshot() {
|
|
166
|
-
this._snapshot = this.ngForm.value;
|
|
167
|
-
}
|
|
168
|
-
getSnapshot() {
|
|
169
|
-
return this._snapshot || {};
|
|
170
|
-
}
|
|
171
|
-
reset() {
|
|
172
|
-
this.ngForm.resetForm();
|
|
173
|
-
Object.keys(this.ngForm.controls)
|
|
174
|
-
.forEach((name) => {
|
|
175
|
-
const control = this.ngForm.controls[name];
|
|
176
|
-
control.reset(this._snapshot[name]);
|
|
177
|
-
});
|
|
178
|
-
this.reseted.emit();
|
|
179
|
-
}
|
|
180
|
-
clear() {
|
|
181
|
-
this.ngForm.resetForm();
|
|
182
|
-
this.cleared.emit();
|
|
183
|
-
}
|
|
184
|
-
dirty() {
|
|
185
|
-
this.ngForm.form.markAsDirty();
|
|
186
|
-
this._updateDirtySubmitButtons();
|
|
187
|
-
}
|
|
188
|
-
triggerSubmit(options) {
|
|
189
|
-
this._confirmed = options?.confirmed;
|
|
190
|
-
this.ngForm.ngSubmit.emit();
|
|
191
|
-
}
|
|
192
|
-
triggerConfirm() {
|
|
193
|
-
const submitted = this.submitting ? this.submitted.asObservable() : of({});
|
|
194
|
-
return submitted
|
|
195
|
-
.pipe(take(1), mergeMap(() => this._form.confirmUnsaved([this])));
|
|
196
|
-
}
|
|
197
|
-
enable() {
|
|
198
|
-
this.ngForm.control.enable();
|
|
199
|
-
this._updateDirtySubmitButtons();
|
|
200
|
-
}
|
|
201
|
-
disable() {
|
|
202
|
-
this.ngForm.control.disable();
|
|
203
|
-
this._buttons.forEach((button) => {
|
|
204
|
-
button.disable();
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
addButton(button) {
|
|
208
|
-
this._buttons.reset([
|
|
209
|
-
...this._buttons.toArray(),
|
|
210
|
-
button,
|
|
211
|
-
]);
|
|
212
|
-
}
|
|
213
|
-
removeButton(button) {
|
|
214
|
-
this._buttons.reset([
|
|
215
|
-
...this._buttons.toArray()
|
|
216
|
-
.filter((item) => (button !== item)),
|
|
217
|
-
]);
|
|
218
|
-
}
|
|
219
|
-
validate() {
|
|
220
|
-
Object.values(this.ngForm.controls)
|
|
221
|
-
.forEach((control) => {
|
|
222
|
-
control.markAsDirty();
|
|
223
|
-
control.markAsTouched();
|
|
224
|
-
control.updateValueAndValidity();
|
|
225
|
-
});
|
|
226
|
-
}
|
|
227
|
-
_listenSubmit() {
|
|
228
|
-
this.ngForm
|
|
229
|
-
.ngSubmit
|
|
230
|
-
.pipe(tap((event) => {
|
|
231
|
-
event?.preventDefault();
|
|
232
|
-
}), map((event) => {
|
|
233
|
-
return { event, confirmed: this._confirmed };
|
|
234
|
-
}), tap(() => this._confirmed = false), filter(() => {
|
|
235
|
-
return [FormStatus.Valid, FormStatus.Invalid]
|
|
236
|
-
.includes(this._status$.getValue());
|
|
237
|
-
}), tap(() => this._broadcasValidatingEvents()), tap(() => this.validate()), tap(() => this._broadcastSubmittingEvents()), switchMap((data) => this._waitUntilStatusPending()
|
|
238
|
-
.pipe(mapTo(data))), tap(() => this._setupActiveSubmitButton()), tap(() => this._disableButtons()), mergeMap((data) => {
|
|
239
|
-
if (this.ngForm.status === 'INVALID') {
|
|
240
|
-
return this._formInvalidState$;
|
|
241
|
-
}
|
|
242
|
-
return this._formValidState$
|
|
243
|
-
.pipe(map((submitEvent) => ({
|
|
244
|
-
...submitEvent,
|
|
245
|
-
confirmed: data.confirmed,
|
|
246
|
-
})));
|
|
247
|
-
}), catchError((e, source$) => {
|
|
248
|
-
this._handleError(e);
|
|
249
|
-
return source$;
|
|
250
|
-
}), tap((submittedEvent) => {
|
|
251
|
-
this._completeSubmit(true, submittedEvent);
|
|
252
|
-
}), takeUntil(this._destroy$))
|
|
253
|
-
.subscribe();
|
|
254
|
-
}
|
|
255
|
-
_listenFormStatus() {
|
|
256
|
-
this._status$
|
|
257
|
-
.pipe(takeUntil(this._destroy$))
|
|
258
|
-
.subscribe((formStatus) => {
|
|
259
|
-
const cls = [FormStatus.Submitting, FormStatus.Validating];
|
|
260
|
-
const classList = this._element.nativeElement.classList;
|
|
261
|
-
classList.remove(...cls);
|
|
262
|
-
if (cls.indexOf(formStatus) !== -1) {
|
|
263
|
-
classList.add(formStatus);
|
|
264
|
-
}
|
|
265
|
-
});
|
|
266
|
-
}
|
|
267
|
-
_listenWindowClose() {
|
|
268
|
-
fromEvent(window, 'beforeunload')
|
|
269
|
-
.pipe(takeUntil(this._destroy$))
|
|
270
|
-
.subscribe((event) => {
|
|
271
|
-
if (this.confirm && this.confirmBrowser && this.ngForm.dirty) {
|
|
272
|
-
event.returnValue = false;
|
|
273
|
-
}
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
_activeDialog(el, dialog) {
|
|
277
|
-
if (el.isSameNode(dialog)) {
|
|
278
|
-
return true;
|
|
279
|
-
}
|
|
280
|
-
else if (el.parentElement) {
|
|
281
|
-
return this._activeDialog(el.parentElement, dialog);
|
|
282
|
-
}
|
|
283
|
-
return false;
|
|
284
|
-
}
|
|
285
|
-
_listenHotKeys() {
|
|
286
|
-
this._ngZone.runOutsideAngular(() => {
|
|
287
|
-
fromEvent(document, 'keydown')
|
|
288
|
-
.pipe(takeUntil(this._destroy$))
|
|
289
|
-
.subscribe((event) => {
|
|
290
|
-
if (this._dialogBackdropEscape && event.code === 'Escape') {
|
|
291
|
-
const cdkOverlayPane = Array
|
|
292
|
-
.from(document.querySelectorAll('.cdk-overlay-pane')).pop();
|
|
293
|
-
const activeDialog = this
|
|
294
|
-
._activeDialog(document.getElementById(this._dialogRef.id), cdkOverlayPane);
|
|
295
|
-
if (activeDialog) {
|
|
296
|
-
this._ngZone.run(() => {
|
|
297
|
-
this._formClose();
|
|
298
|
-
});
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
if ((event.ctrlKey || event.metaKey) && event.code === 'KeyS') {
|
|
302
|
-
event.preventDefault();
|
|
303
|
-
if (this.shortcuts) {
|
|
304
|
-
if (this._elementInForm(document.activeElement)) {
|
|
305
|
-
this.ngForm.ngSubmit.next();
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
});
|
|
310
|
-
});
|
|
311
|
-
}
|
|
312
|
-
_formClose() {
|
|
313
|
-
if (this.confirm && this.confirmDialog) {
|
|
314
|
-
this.triggerConfirm()
|
|
315
|
-
.pipe(filter((result) => confirmResultContinue(result)), switchMap((result) => {
|
|
316
|
-
return result === ConfirmResult.Pristine || result === ConfirmResult.Discard
|
|
317
|
-
? of(null)
|
|
318
|
-
: this.submitted.asObservable();
|
|
319
|
-
}), takeUntil(this._destroy$))
|
|
320
|
-
.subscribe((result) => {
|
|
321
|
-
this._dialogRef.close(result?.response);
|
|
322
|
-
});
|
|
323
|
-
}
|
|
324
|
-
else {
|
|
325
|
-
this._dialogRef.close(null);
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
_getActiveSubmitButton() {
|
|
329
|
-
const submitButtons = this._buttons
|
|
330
|
-
.filter((button) => button.submit);
|
|
331
|
-
const activeButton = submitButtons
|
|
332
|
-
.find((button) => {
|
|
333
|
-
return button.active;
|
|
334
|
-
});
|
|
335
|
-
return activeButton ? activeButton : submitButtons[0];
|
|
336
|
-
}
|
|
337
|
-
_elementInForm(el) {
|
|
338
|
-
if (el.isSameNode(this._element.nativeElement)) {
|
|
339
|
-
return true;
|
|
340
|
-
}
|
|
341
|
-
else if (el.parentElement) {
|
|
342
|
-
return this._elementInForm(el.parentElement);
|
|
343
|
-
}
|
|
344
|
-
return false;
|
|
345
|
-
}
|
|
346
|
-
_completeSubmit(success, submitEvent) {
|
|
347
|
-
if (success) {
|
|
348
|
-
this.ngForm.control.markAsPristine();
|
|
349
|
-
this.createSnapshot();
|
|
350
|
-
this.submitted.emit(submitEvent);
|
|
351
|
-
}
|
|
352
|
-
else {
|
|
353
|
-
this._resetButtons();
|
|
354
|
-
}
|
|
355
|
-
if (this._activeSubmitButton) {
|
|
356
|
-
if (success) {
|
|
357
|
-
this._activeSubmitButton.success();
|
|
358
|
-
}
|
|
359
|
-
else {
|
|
360
|
-
this._activeSubmitButton.error();
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
this._status$.next(FormStatus.Submitted);
|
|
364
|
-
if (success) {
|
|
365
|
-
this._status$.next(FormStatus.Success);
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
this._status$.next(FormStatus.Error);
|
|
369
|
-
}
|
|
370
|
-
this._status$.next(FormStatus.Completing);
|
|
371
|
-
const resetDelay = success ? this.successDelay : this.errorDelay;
|
|
372
|
-
of(true)
|
|
373
|
-
.pipe(delay(resetDelay), first(), takeUntil(this._destroy$)).subscribe(() => {
|
|
374
|
-
if (this.ngForm.form.status === 'VALID') {
|
|
375
|
-
this._status$.next(FormStatus.Valid);
|
|
376
|
-
}
|
|
377
|
-
else {
|
|
378
|
-
this._status$.next(FormStatus.Invalid);
|
|
379
|
-
}
|
|
380
|
-
this._resetButtons();
|
|
381
|
-
this._resetActiveButtons();
|
|
382
|
-
this._updateDirtySubmitButtons();
|
|
383
|
-
});
|
|
384
|
-
}
|
|
385
|
-
_resetButtons() {
|
|
386
|
-
this._buttons.forEach((button) => {
|
|
387
|
-
button.reset();
|
|
388
|
-
});
|
|
389
|
-
}
|
|
390
|
-
_resetActiveButtons() {
|
|
391
|
-
this._buttons.forEach((button) => {
|
|
392
|
-
button.resetActive();
|
|
393
|
-
});
|
|
394
|
-
}
|
|
395
|
-
_registerConfirm() {
|
|
396
|
-
this.ngForm.form.valueChanges
|
|
397
|
-
.pipe(takeUntil(this._destroy$))
|
|
398
|
-
.subscribe((changes) => {
|
|
399
|
-
if (this._dialogBackdropEscape && this._dialogRef) {
|
|
400
|
-
this._dialogRef.disableClose = true;
|
|
401
|
-
}
|
|
402
|
-
if (this.confirm) {
|
|
403
|
-
const existing = Object.keys(this._snapshot);
|
|
404
|
-
Object.keys(changes)
|
|
405
|
-
.forEach((name) => {
|
|
406
|
-
if (existing.indexOf(name) === -1) {
|
|
407
|
-
this._snapshot[name] = changes[name];
|
|
408
|
-
}
|
|
409
|
-
});
|
|
410
|
-
}
|
|
411
|
-
});
|
|
412
|
-
}
|
|
413
|
-
_registerDrawerClose() {
|
|
414
|
-
if (this._drawerRef) {
|
|
415
|
-
this._drawerRef.closeStart$
|
|
416
|
-
.pipe(takeUntil(this._destroy$))
|
|
417
|
-
.subscribe((subscriber) => {
|
|
418
|
-
if (this.submitting) {
|
|
419
|
-
this._status$
|
|
420
|
-
.pipe(filter((status) => status === FormStatus.Success || status === FormStatus.Error), takeUntil(this._destroy$))
|
|
421
|
-
.subscribe((status) => {
|
|
422
|
-
if (status === FormStatus.Success) {
|
|
423
|
-
subscriber.next();
|
|
424
|
-
subscriber.complete();
|
|
425
|
-
}
|
|
426
|
-
else {
|
|
427
|
-
subscriber.error();
|
|
428
|
-
}
|
|
429
|
-
});
|
|
430
|
-
}
|
|
431
|
-
else {
|
|
432
|
-
subscriber.next();
|
|
433
|
-
subscriber.complete();
|
|
434
|
-
}
|
|
435
|
-
});
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
_registerConfirmDrawerClose() {
|
|
439
|
-
if (this._drawerRef) {
|
|
440
|
-
this._drawerRef.closeStart$
|
|
441
|
-
.pipe(switchMap((subscriber) => {
|
|
442
|
-
return iif(() => this.confirm && this.confirmDrawer, this.triggerConfirm()
|
|
443
|
-
.pipe(map((result) => confirmResultContinue(result)), tap((result) => {
|
|
444
|
-
if (result) {
|
|
445
|
-
subscriber.next();
|
|
446
|
-
subscriber.complete();
|
|
447
|
-
}
|
|
448
|
-
})), defer(() => {
|
|
449
|
-
subscriber.next();
|
|
450
|
-
subscriber.complete();
|
|
451
|
-
}));
|
|
452
|
-
}), takeUntil(this._destroy$))
|
|
453
|
-
.subscribe();
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
_registerConfirmTabs() {
|
|
457
|
-
if (this.tabGroup) {
|
|
458
|
-
this._registerConfirmTabGroup(this.tabGroup);
|
|
459
|
-
}
|
|
460
|
-
this._registerConfirmTabGroups(this._tabGroups.toArray());
|
|
461
|
-
this._tabGroups.changes
|
|
462
|
-
.pipe(takeUntil(this._destroy$))
|
|
463
|
-
.subscribe(() => {
|
|
464
|
-
this._registerConfirmTabGroups(this._tabGroups.toArray());
|
|
465
|
-
});
|
|
466
|
-
}
|
|
467
|
-
_registerConfirmTabGroups(tabGroups) {
|
|
468
|
-
tabGroups.forEach((tabGroup) => {
|
|
469
|
-
this._registerConfirmTabGroup(tabGroup);
|
|
470
|
-
});
|
|
471
|
-
}
|
|
472
|
-
_registerConfirmTabGroup(tabGroup) {
|
|
473
|
-
const confirmTabGroup = tabGroup;
|
|
474
|
-
if (!confirmTabGroup._originalHandleClick) {
|
|
475
|
-
confirmTabGroup._originalHandleClick = tabGroup._handleClick;
|
|
476
|
-
confirmTabGroup._handlClick$ = new Subject();
|
|
477
|
-
confirmTabGroup._handleClick = (tab, tabHeader, idx) => {
|
|
478
|
-
if (confirmTabGroup._handlClick$.observers.length) {
|
|
479
|
-
confirmTabGroup._handlClick$.next({ tab, tabHeader, idx });
|
|
480
|
-
}
|
|
481
|
-
else {
|
|
482
|
-
confirmTabGroup._originalHandleClick(tab, tabHeader, idx);
|
|
483
|
-
}
|
|
484
|
-
};
|
|
485
|
-
}
|
|
486
|
-
confirmTabGroup._handlClick$
|
|
487
|
-
.pipe(filter(() => !this.submitting), switchMap((event) => {
|
|
488
|
-
if (this.confirm && this.confirmTabs) {
|
|
489
|
-
return this.triggerConfirm()
|
|
490
|
-
.pipe(tap((result) => {
|
|
491
|
-
if (confirmResultContinue(result)) {
|
|
492
|
-
confirmTabGroup.selectedIndex = event.idx;
|
|
493
|
-
}
|
|
494
|
-
}));
|
|
495
|
-
}
|
|
496
|
-
confirmTabGroup._originalHandleClick(event.tab, event.tabHeader, event.idx);
|
|
497
|
-
return of(null);
|
|
498
|
-
}), takeUntil(this._destroy$))
|
|
499
|
-
.subscribe();
|
|
500
|
-
}
|
|
501
|
-
_registerConfirmDialogBackdropEscape() {
|
|
502
|
-
if (this._dialogRef) {
|
|
503
|
-
this._dialogBackdropEscape = !this._dialogRef?.disableClose;
|
|
504
|
-
if (this._dialogBackdropEscape) {
|
|
505
|
-
this._dialogRef.backdropClick()
|
|
506
|
-
.pipe(takeUntil(this._destroy$))
|
|
507
|
-
.subscribe(() => {
|
|
508
|
-
this._formClose();
|
|
509
|
-
});
|
|
510
|
-
this._destroy$
|
|
511
|
-
.subscribe(() => {
|
|
512
|
-
this._dialogRef.disableClose = false;
|
|
513
|
-
});
|
|
514
|
-
}
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
_registerAutocomplete() {
|
|
518
|
-
this._registerControl = this.ngForm.form.registerControl.bind(this.ngForm.form);
|
|
519
|
-
this.ngForm.form.registerControl = (name, control) => {
|
|
520
|
-
const el = this._element.nativeElement.querySelector(`input[name='${name}']`);
|
|
521
|
-
if (el) {
|
|
522
|
-
if (!el.getAttribute('autocomplete')) {
|
|
523
|
-
el.setAttribute('autocomplete', 'none');
|
|
524
|
-
el.setAttribute('name', `${name}-${guid()}`);
|
|
525
|
-
}
|
|
526
|
-
}
|
|
527
|
-
return this._registerControl(name, control);
|
|
528
|
-
};
|
|
529
|
-
}
|
|
530
|
-
_registerDirtySubmitButton() {
|
|
531
|
-
if (!this.ngForm) {
|
|
532
|
-
return;
|
|
533
|
-
}
|
|
534
|
-
this.ngForm.form.valueChanges
|
|
535
|
-
.pipe(takeUntil(this._destroy$))
|
|
536
|
-
.subscribe(() => {
|
|
537
|
-
this._updateDirtySubmitButtons();
|
|
538
|
-
});
|
|
539
|
-
this._buttons.changes
|
|
540
|
-
.pipe(takeUntil(this._destroy$))
|
|
541
|
-
.subscribe(() => {
|
|
542
|
-
this._updateDirtySubmitButtons();
|
|
543
|
-
});
|
|
544
|
-
}
|
|
545
|
-
_updateDirtySubmitButtons() {
|
|
546
|
-
this._buttons
|
|
547
|
-
.filter((button) => button.submit)
|
|
548
|
-
.forEach((submitButton) => {
|
|
549
|
-
if (!this.confirm || !this.dirtySubmitButton || this.ngForm.dirty || !submitButton.dirtySubmit) {
|
|
550
|
-
submitButton.enable();
|
|
551
|
-
}
|
|
552
|
-
else {
|
|
553
|
-
submitButton.disable();
|
|
554
|
-
}
|
|
555
|
-
});
|
|
556
|
-
}
|
|
557
|
-
_broadcastSubmittingEvents() {
|
|
558
|
-
this._status$.next(FormStatus.Submitting);
|
|
559
|
-
this._form.broadcast('submit', this.ngForm);
|
|
560
|
-
}
|
|
561
|
-
_broadcasValidatingEvents() {
|
|
562
|
-
this._status$.next(FormStatus.Validating);
|
|
563
|
-
}
|
|
564
|
-
_setupActiveSubmitButton() {
|
|
565
|
-
this._activeSubmitButton = this._getActiveSubmitButton();
|
|
566
|
-
this._resetButtons();
|
|
567
|
-
if (this._activeSubmitButton) {
|
|
568
|
-
this._activeSubmitButton.process();
|
|
569
|
-
}
|
|
570
|
-
}
|
|
571
|
-
_disableButtons() {
|
|
572
|
-
this._buttons.forEach((button) => {
|
|
573
|
-
button.disable();
|
|
574
|
-
});
|
|
575
|
-
}
|
|
576
|
-
_waitUntilStatusPending() {
|
|
577
|
-
return this.ngForm.statusChanges
|
|
578
|
-
.pipe(startWith(this.ngForm.status), first((state) => state !== 'PENDING'));
|
|
579
|
-
}
|
|
580
|
-
_handleError(e) {
|
|
581
|
-
console.log('%c Form Submit ', 'color: white; background-color: #D33F49', 'Error occured');
|
|
582
|
-
console.group('Error Details:');
|
|
583
|
-
console.log('Message: ', e);
|
|
584
|
-
console.log('FormRef: ', this);
|
|
585
|
-
if (this.ngForm.invalid) {
|
|
586
|
-
const errors = getFormErrors(this.ngForm.control, null);
|
|
587
|
-
console.log('Validation Errors: ', errors);
|
|
588
|
-
}
|
|
589
|
-
console.groupEnd();
|
|
590
|
-
this._completeSubmit(false, null);
|
|
591
|
-
}
|
|
592
|
-
_registerCanDeactivateGuard() {
|
|
593
|
-
this._activatedRouteConfig = getActiveRoute(this._route).routeConfig;
|
|
594
|
-
if (!this._activatedRouteConfig) {
|
|
595
|
-
return;
|
|
596
|
-
}
|
|
597
|
-
this._form.registerFormDirective(this._activatedRouteConfig.component, this);
|
|
598
|
-
if (!Array.isArray(this._activatedRouteConfig.canDeactivate)) {
|
|
599
|
-
this._activatedRouteConfig.canDeactivate = [];
|
|
600
|
-
}
|
|
601
|
-
if (this._activatedRouteConfig.canDeactivate.indexOf(FormDeactivateGuard) === -1) {
|
|
602
|
-
this._activatedRouteConfig.canDeactivate.push(FormDeactivateGuard);
|
|
603
|
-
}
|
|
604
|
-
}
|
|
605
|
-
_cleanupCanDeactivate() {
|
|
606
|
-
if (!this._activatedRouteConfig) {
|
|
607
|
-
return;
|
|
608
|
-
}
|
|
609
|
-
const guardIndex = this._activatedRouteConfig.canDeactivate.indexOf(FormDeactivateGuard);
|
|
610
|
-
this._activatedRouteConfig.canDeactivate.splice(guardIndex, 1);
|
|
611
|
-
this._form.removeFormDirective(this._activatedRouteConfig.component);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
FsFormDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsFormDirective, deps: [{ token: NgForm }, { token: i1.FsForm }, { token: i0.ElementRef }, { token: i2.FsMessage }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: MatDialogRef, optional: true }, { token: DrawerRef, optional: true }, { token: i3.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Directive });
|
|
615
|
-
FsFormDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", type: FsFormDirective, selector: "[fsForm]", inputs: { wrapperSelector: "wrapperSelector", messageSelector: "messageSelector", hintSelector: "hintSelector", labelSelector: "labelSelector", autocomplete: "autocomplete", shortcuts: "shortcuts", confirm: "confirm", confirmDialog: "confirmDialog", confirmDrawer: "confirmDrawer", confirmBrowser: "confirmBrowser", confirmTabs: "confirmTabs", dirtySubmitButton: "dirtySubmitButton", submit: "submit", successDelay: "successDelay", errorDelay: "errorDelay", tabGroup: "tabGroup", deactivationGuard: "deactivationGuard" }, outputs: { submitEvent: "fsForm", invalid: "invalid", valid: "valid", submitted: "submitted", reseted: "reseted", cleared: "cleared" }, host: { properties: { "class.fs-form": "this.fsFormClass" } }, queries: [{ propertyName: "_tabGroups", predicate: MatTabGroup, descendants: true }], exportAs: ["fsForm"], usesOnChanges: true, ngImport: i0 });
|
|
616
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsFormDirective, decorators: [{
|
|
617
|
-
type: Directive,
|
|
618
|
-
args: [{
|
|
619
|
-
selector: '[fsForm]',
|
|
620
|
-
exportAs: 'fsForm',
|
|
621
|
-
}]
|
|
622
|
-
}], ctorParameters: function () { return [{ type: i4.NgForm, decorators: [{
|
|
623
|
-
type: Inject,
|
|
624
|
-
args: [NgForm]
|
|
625
|
-
}] }, { type: i1.FsForm }, { type: i0.ElementRef }, { type: i2.FsMessage }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i5.MatDialogRef, decorators: [{
|
|
626
|
-
type: Optional
|
|
627
|
-
}, {
|
|
628
|
-
type: Inject,
|
|
629
|
-
args: [MatDialogRef]
|
|
630
|
-
}] }, { type: i6.DrawerRef, decorators: [{
|
|
631
|
-
type: Optional
|
|
632
|
-
}, {
|
|
633
|
-
type: Inject,
|
|
634
|
-
args: [DrawerRef]
|
|
635
|
-
}] }, { type: i3.ActivatedRoute }]; }, propDecorators: { wrapperSelector: [{
|
|
636
|
-
type: Input
|
|
637
|
-
}], messageSelector: [{
|
|
638
|
-
type: Input
|
|
639
|
-
}], hintSelector: [{
|
|
640
|
-
type: Input
|
|
641
|
-
}], labelSelector: [{
|
|
642
|
-
type: Input
|
|
643
|
-
}], autocomplete: [{
|
|
644
|
-
type: Input
|
|
645
|
-
}], shortcuts: [{
|
|
646
|
-
type: Input
|
|
647
|
-
}], confirm: [{
|
|
648
|
-
type: Input
|
|
649
|
-
}], confirmDialog: [{
|
|
650
|
-
type: Input
|
|
651
|
-
}], confirmDrawer: [{
|
|
652
|
-
type: Input
|
|
653
|
-
}], confirmBrowser: [{
|
|
654
|
-
type: Input
|
|
655
|
-
}], confirmTabs: [{
|
|
656
|
-
type: Input
|
|
657
|
-
}], dirtySubmitButton: [{
|
|
658
|
-
type: Input
|
|
659
|
-
}], submit: [{
|
|
660
|
-
type: Input
|
|
661
|
-
}], successDelay: [{
|
|
662
|
-
type: Input
|
|
663
|
-
}], errorDelay: [{
|
|
664
|
-
type: Input
|
|
665
|
-
}], tabGroup: [{
|
|
666
|
-
type: Input
|
|
667
|
-
}], deactivationGuard: [{
|
|
668
|
-
type: Input
|
|
669
|
-
}], submitEvent: [{
|
|
670
|
-
type: Output,
|
|
671
|
-
args: ['fsForm']
|
|
672
|
-
}], invalid: [{
|
|
673
|
-
type: Output
|
|
674
|
-
}], valid: [{
|
|
675
|
-
type: Output
|
|
676
|
-
}], submitted: [{
|
|
677
|
-
type: Output
|
|
678
|
-
}], reseted: [{
|
|
679
|
-
type: Output
|
|
680
|
-
}], cleared: [{
|
|
681
|
-
type: Output
|
|
682
|
-
}], fsFormClass: [{
|
|
683
|
-
type: HostBinding,
|
|
684
|
-
args: ['class.fs-form']
|
|
685
|
-
}], _tabGroups: [{
|
|
686
|
-
type: ContentChildren,
|
|
687
|
-
args: [MatTabGroup, { descendants: true }]
|
|
688
|
-
}] } });
|
|
1
|
+
import { ChangeDetectorRef, ContentChildren, Directive, ElementRef, EventEmitter, HostBinding, Inject, Input, NgZone, Optional, Output, QueryList, } from '@angular/core';
|
|
2
|
+
import { NgForm } from '@angular/forms';
|
|
3
|
+
import { ActivatedRoute } from '@angular/router';
|
|
4
|
+
import { MatDialogRef } from '@angular/material/dialog';
|
|
5
|
+
import { MatTabGroup } from '@angular/material/tabs';
|
|
6
|
+
import { guid } from '@firestitch/common';
|
|
7
|
+
import { DrawerRef } from '@firestitch/drawer';
|
|
8
|
+
import { FsMessage, MessageMode } from '@firestitch/message';
|
|
9
|
+
import { BehaviorSubject, defer, fromEvent, iif, of, Subject, throwError, } from 'rxjs';
|
|
10
|
+
import { catchError, delay, filter, first, map, mapTo, mergeMap, startWith, switchMap, take, takeUntil, tap, } from 'rxjs/operators';
|
|
11
|
+
import { FormDeactivateGuard } from '../../guards/form-deactivate.guard';
|
|
12
|
+
import { confirmResultContinue } from '../../helpers/confirm-result-continue';
|
|
13
|
+
import { getActiveRoute } from '../../helpers/get-active-route';
|
|
14
|
+
import { getFormErrors } from '../../helpers/get-form-errors';
|
|
15
|
+
import { FsForm } from '../../services/fsform.service';
|
|
16
|
+
import { ConfirmResult } from './../../enums/confirm-result';
|
|
17
|
+
import { FormStatus } from './../../enums/form-status';
|
|
18
|
+
import * as i0 from "@angular/core";
|
|
19
|
+
import * as i1 from "../../services/fsform.service";
|
|
20
|
+
import * as i2 from "@firestitch/message";
|
|
21
|
+
import * as i3 from "@angular/router";
|
|
22
|
+
import * as i4 from "@angular/forms";
|
|
23
|
+
import * as i5 from "@angular/material/dialog";
|
|
24
|
+
import * as i6 from "@firestitch/drawer";
|
|
25
|
+
export class FsFormDirective {
|
|
26
|
+
constructor(ngForm, _form, _element, _message, _ngZone, _cdRef, _dialogRef, _drawerRef, _route) {
|
|
27
|
+
this.ngForm = ngForm;
|
|
28
|
+
this._form = _form;
|
|
29
|
+
this._element = _element;
|
|
30
|
+
this._message = _message;
|
|
31
|
+
this._ngZone = _ngZone;
|
|
32
|
+
this._cdRef = _cdRef;
|
|
33
|
+
this._dialogRef = _dialogRef;
|
|
34
|
+
this._drawerRef = _drawerRef;
|
|
35
|
+
this._route = _route;
|
|
36
|
+
this.wrapperSelector = '.fs-form-wrapper,.mat-form-field';
|
|
37
|
+
this.messageSelector = '.fs-form-message,.mat-form-field-subscript-wrapper';
|
|
38
|
+
this.hintSelector = '.fs-form-hint,.mat-form-field-hint-wrapper';
|
|
39
|
+
this.labelSelector = '.fs-form-label,.mat-form-field-label';
|
|
40
|
+
this.autocomplete = false;
|
|
41
|
+
this.shortcuts = true; // Ctrl + s
|
|
42
|
+
this.confirm = true;
|
|
43
|
+
this.confirmDialog = true;
|
|
44
|
+
this.confirmDrawer = true;
|
|
45
|
+
this.confirmBrowser = true;
|
|
46
|
+
this.confirmTabs = true;
|
|
47
|
+
this.dirtySubmitButton = true;
|
|
48
|
+
this.successDelay = 0;
|
|
49
|
+
this.errorDelay = 1000;
|
|
50
|
+
this.deactivationGuard = true;
|
|
51
|
+
this.submitEvent = new EventEmitter();
|
|
52
|
+
this.invalid = new EventEmitter();
|
|
53
|
+
this.valid = new EventEmitter();
|
|
54
|
+
this.submitted = new EventEmitter();
|
|
55
|
+
this.reseted = new EventEmitter();
|
|
56
|
+
this.cleared = new EventEmitter();
|
|
57
|
+
this.fsFormClass = true;
|
|
58
|
+
this._tabGroups = new QueryList();
|
|
59
|
+
this._buttons = new QueryList();
|
|
60
|
+
this._dialogBackdropEscape = false;
|
|
61
|
+
this._snapshot = {};
|
|
62
|
+
this._status$ = new BehaviorSubject(FormStatus.Valid);
|
|
63
|
+
this._destroy$ = new Subject();
|
|
64
|
+
this._confirmed = false;
|
|
65
|
+
this._submit$ = null;
|
|
66
|
+
}
|
|
67
|
+
set submit(submit$) {
|
|
68
|
+
this._submit$ = submit$;
|
|
69
|
+
}
|
|
70
|
+
get submit() {
|
|
71
|
+
return this._submit$;
|
|
72
|
+
}
|
|
73
|
+
get submitting() {
|
|
74
|
+
return this._status$.getValue() === FormStatus.Submitting;
|
|
75
|
+
}
|
|
76
|
+
get validating() {
|
|
77
|
+
return this._status$.getValue() === FormStatus.Validating;
|
|
78
|
+
}
|
|
79
|
+
get completing() {
|
|
80
|
+
return this._status$.getValue() === FormStatus.Completing;
|
|
81
|
+
}
|
|
82
|
+
get _submitEvent() {
|
|
83
|
+
return {
|
|
84
|
+
ngForm: this.ngForm,
|
|
85
|
+
submitter: this._submitter,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
get _formValidState$() {
|
|
89
|
+
this._form.broadcast('valid', this._submitEvent);
|
|
90
|
+
this.submitEvent.emit(this._submitEvent);
|
|
91
|
+
this.valid.emit(this._submitEvent);
|
|
92
|
+
const submittedEvent = {
|
|
93
|
+
ngForm: this.ngForm,
|
|
94
|
+
submitter: this._submitter,
|
|
95
|
+
response: null,
|
|
96
|
+
};
|
|
97
|
+
const submit$ = this._submit$ ?
|
|
98
|
+
this._submit$(this._submitEvent) : of(submittedEvent);
|
|
99
|
+
return submit$
|
|
100
|
+
.pipe(map((response) => {
|
|
101
|
+
submittedEvent.response = response;
|
|
102
|
+
return submittedEvent;
|
|
103
|
+
}), takeUntil(this._destroy$));
|
|
104
|
+
}
|
|
105
|
+
get _formInvalidState$() {
|
|
106
|
+
this._form.broadcast('invalid', this._submitEvent);
|
|
107
|
+
if (this.invalid) {
|
|
108
|
+
this.invalid.emit(this._submitEvent);
|
|
109
|
+
}
|
|
110
|
+
const message = 'Please review errors highlighted in red';
|
|
111
|
+
this._message.error(message, { mode: MessageMode.Toast });
|
|
112
|
+
const el = this._element.nativeElement.querySelector('.ng-invalid');
|
|
113
|
+
if (el) {
|
|
114
|
+
el.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
|
|
115
|
+
}
|
|
116
|
+
return throwError('Form validation error');
|
|
117
|
+
}
|
|
118
|
+
get _submitter() {
|
|
119
|
+
return this._activeSubmitButton
|
|
120
|
+
? this._activeSubmitButton.name
|
|
121
|
+
: null;
|
|
122
|
+
}
|
|
123
|
+
ngOnInit() {
|
|
124
|
+
if (this.deactivationGuard) {
|
|
125
|
+
this._registerCanDeactivateGuard();
|
|
126
|
+
}
|
|
127
|
+
this._registerConfirmDialogBackdropEscape();
|
|
128
|
+
this._listenHotKeys();
|
|
129
|
+
this._listenWindowClose();
|
|
130
|
+
this._listenSubmit();
|
|
131
|
+
this._listenFormStatus();
|
|
132
|
+
if (!this.autocomplete) {
|
|
133
|
+
this._registerAutocomplete();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
ngOnChanges(changes) {
|
|
137
|
+
if (changes.confirm) {
|
|
138
|
+
this._updateDirtySubmitButtons();
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
clearSubmit() {
|
|
142
|
+
this._submit$ = null;
|
|
143
|
+
setTimeout(() => {
|
|
144
|
+
this._cdRef.markForCheck();
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
registerSubmit(submit$) {
|
|
148
|
+
this._submit$ = submit$;
|
|
149
|
+
setTimeout(() => {
|
|
150
|
+
this._cdRef.markForCheck();
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
ngAfterContentInit() {
|
|
154
|
+
this._registerConfirm();
|
|
155
|
+
this._registerConfirmDrawerClose();
|
|
156
|
+
this._registerConfirmTabs();
|
|
157
|
+
this._registerDrawerClose();
|
|
158
|
+
this._registerDirtySubmitButton();
|
|
159
|
+
}
|
|
160
|
+
ngOnDestroy() {
|
|
161
|
+
this._cleanupCanDeactivate();
|
|
162
|
+
this._destroy$.next();
|
|
163
|
+
this._destroy$.complete();
|
|
164
|
+
}
|
|
165
|
+
createSnapshot() {
|
|
166
|
+
this._snapshot = this.ngForm.value;
|
|
167
|
+
}
|
|
168
|
+
getSnapshot() {
|
|
169
|
+
return this._snapshot || {};
|
|
170
|
+
}
|
|
171
|
+
reset() {
|
|
172
|
+
this.ngForm.resetForm();
|
|
173
|
+
Object.keys(this.ngForm.controls)
|
|
174
|
+
.forEach((name) => {
|
|
175
|
+
const control = this.ngForm.controls[name];
|
|
176
|
+
control.reset(this._snapshot[name]);
|
|
177
|
+
});
|
|
178
|
+
this.reseted.emit();
|
|
179
|
+
}
|
|
180
|
+
clear() {
|
|
181
|
+
this.ngForm.resetForm();
|
|
182
|
+
this.cleared.emit();
|
|
183
|
+
}
|
|
184
|
+
dirty() {
|
|
185
|
+
this.ngForm.form.markAsDirty();
|
|
186
|
+
this._updateDirtySubmitButtons();
|
|
187
|
+
}
|
|
188
|
+
triggerSubmit(options) {
|
|
189
|
+
this._confirmed = options?.confirmed;
|
|
190
|
+
this.ngForm.ngSubmit.emit();
|
|
191
|
+
}
|
|
192
|
+
triggerConfirm() {
|
|
193
|
+
const submitted = this.submitting ? this.submitted.asObservable() : of({});
|
|
194
|
+
return submitted
|
|
195
|
+
.pipe(take(1), mergeMap(() => this._form.confirmUnsaved([this])));
|
|
196
|
+
}
|
|
197
|
+
enable() {
|
|
198
|
+
this.ngForm.control.enable();
|
|
199
|
+
this._updateDirtySubmitButtons();
|
|
200
|
+
}
|
|
201
|
+
disable() {
|
|
202
|
+
this.ngForm.control.disable();
|
|
203
|
+
this._buttons.forEach((button) => {
|
|
204
|
+
button.disable();
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
addButton(button) {
|
|
208
|
+
this._buttons.reset([
|
|
209
|
+
...this._buttons.toArray(),
|
|
210
|
+
button,
|
|
211
|
+
]);
|
|
212
|
+
}
|
|
213
|
+
removeButton(button) {
|
|
214
|
+
this._buttons.reset([
|
|
215
|
+
...this._buttons.toArray()
|
|
216
|
+
.filter((item) => (button !== item)),
|
|
217
|
+
]);
|
|
218
|
+
}
|
|
219
|
+
validate() {
|
|
220
|
+
Object.values(this.ngForm.controls)
|
|
221
|
+
.forEach((control) => {
|
|
222
|
+
control.markAsDirty();
|
|
223
|
+
control.markAsTouched();
|
|
224
|
+
control.updateValueAndValidity();
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
_listenSubmit() {
|
|
228
|
+
this.ngForm
|
|
229
|
+
.ngSubmit
|
|
230
|
+
.pipe(tap((event) => {
|
|
231
|
+
event?.preventDefault();
|
|
232
|
+
}), map((event) => {
|
|
233
|
+
return { event, confirmed: this._confirmed };
|
|
234
|
+
}), tap(() => this._confirmed = false), filter(() => {
|
|
235
|
+
return [FormStatus.Valid, FormStatus.Invalid]
|
|
236
|
+
.includes(this._status$.getValue());
|
|
237
|
+
}), tap(() => this._broadcasValidatingEvents()), tap(() => this.validate()), tap(() => this._broadcastSubmittingEvents()), switchMap((data) => this._waitUntilStatusPending()
|
|
238
|
+
.pipe(mapTo(data))), tap(() => this._setupActiveSubmitButton()), tap(() => this._disableButtons()), mergeMap((data) => {
|
|
239
|
+
if (this.ngForm.status === 'INVALID') {
|
|
240
|
+
return this._formInvalidState$;
|
|
241
|
+
}
|
|
242
|
+
return this._formValidState$
|
|
243
|
+
.pipe(map((submitEvent) => ({
|
|
244
|
+
...submitEvent,
|
|
245
|
+
confirmed: data.confirmed,
|
|
246
|
+
})));
|
|
247
|
+
}), catchError((e, source$) => {
|
|
248
|
+
this._handleError(e);
|
|
249
|
+
return source$;
|
|
250
|
+
}), tap((submittedEvent) => {
|
|
251
|
+
this._completeSubmit(true, submittedEvent);
|
|
252
|
+
}), takeUntil(this._destroy$))
|
|
253
|
+
.subscribe();
|
|
254
|
+
}
|
|
255
|
+
_listenFormStatus() {
|
|
256
|
+
this._status$
|
|
257
|
+
.pipe(takeUntil(this._destroy$))
|
|
258
|
+
.subscribe((formStatus) => {
|
|
259
|
+
const cls = [FormStatus.Submitting, FormStatus.Validating];
|
|
260
|
+
const classList = this._element.nativeElement.classList;
|
|
261
|
+
classList.remove(...cls);
|
|
262
|
+
if (cls.indexOf(formStatus) !== -1) {
|
|
263
|
+
classList.add(formStatus);
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
_listenWindowClose() {
|
|
268
|
+
fromEvent(window, 'beforeunload')
|
|
269
|
+
.pipe(takeUntil(this._destroy$))
|
|
270
|
+
.subscribe((event) => {
|
|
271
|
+
if (this.confirm && this.confirmBrowser && this.ngForm.dirty) {
|
|
272
|
+
event.returnValue = false;
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
_activeDialog(el, dialog) {
|
|
277
|
+
if (el.isSameNode(dialog)) {
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
else if (el.parentElement) {
|
|
281
|
+
return this._activeDialog(el.parentElement, dialog);
|
|
282
|
+
}
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
_listenHotKeys() {
|
|
286
|
+
this._ngZone.runOutsideAngular(() => {
|
|
287
|
+
fromEvent(document, 'keydown')
|
|
288
|
+
.pipe(takeUntil(this._destroy$))
|
|
289
|
+
.subscribe((event) => {
|
|
290
|
+
if (this._dialogBackdropEscape && event.code === 'Escape') {
|
|
291
|
+
const cdkOverlayPane = Array
|
|
292
|
+
.from(document.querySelectorAll('.cdk-overlay-pane')).pop();
|
|
293
|
+
const activeDialog = this
|
|
294
|
+
._activeDialog(document.getElementById(this._dialogRef.id), cdkOverlayPane);
|
|
295
|
+
if (activeDialog) {
|
|
296
|
+
this._ngZone.run(() => {
|
|
297
|
+
this._formClose();
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
if ((event.ctrlKey || event.metaKey) && event.code === 'KeyS') {
|
|
302
|
+
event.preventDefault();
|
|
303
|
+
if (this.shortcuts) {
|
|
304
|
+
if (this._elementInForm(document.activeElement)) {
|
|
305
|
+
this.ngForm.ngSubmit.next();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
_formClose() {
|
|
313
|
+
if (this.confirm && this.confirmDialog) {
|
|
314
|
+
this.triggerConfirm()
|
|
315
|
+
.pipe(filter((result) => confirmResultContinue(result)), switchMap((result) => {
|
|
316
|
+
return result === ConfirmResult.Pristine || result === ConfirmResult.Discard
|
|
317
|
+
? of(null)
|
|
318
|
+
: this.submitted.asObservable();
|
|
319
|
+
}), takeUntil(this._destroy$))
|
|
320
|
+
.subscribe((result) => {
|
|
321
|
+
this._dialogRef.close(result?.response);
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
else {
|
|
325
|
+
this._dialogRef.close(null);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
_getActiveSubmitButton() {
|
|
329
|
+
const submitButtons = this._buttons
|
|
330
|
+
.filter((button) => button.submit);
|
|
331
|
+
const activeButton = submitButtons
|
|
332
|
+
.find((button) => {
|
|
333
|
+
return button.active;
|
|
334
|
+
});
|
|
335
|
+
return activeButton ? activeButton : submitButtons[0];
|
|
336
|
+
}
|
|
337
|
+
_elementInForm(el) {
|
|
338
|
+
if (el.isSameNode(this._element.nativeElement)) {
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
else if (el.parentElement) {
|
|
342
|
+
return this._elementInForm(el.parentElement);
|
|
343
|
+
}
|
|
344
|
+
return false;
|
|
345
|
+
}
|
|
346
|
+
_completeSubmit(success, submitEvent) {
|
|
347
|
+
if (success) {
|
|
348
|
+
this.ngForm.control.markAsPristine();
|
|
349
|
+
this.createSnapshot();
|
|
350
|
+
this.submitted.emit(submitEvent);
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
this._resetButtons();
|
|
354
|
+
}
|
|
355
|
+
if (this._activeSubmitButton) {
|
|
356
|
+
if (success) {
|
|
357
|
+
this._activeSubmitButton.success();
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
this._activeSubmitButton.error();
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
this._status$.next(FormStatus.Submitted);
|
|
364
|
+
if (success) {
|
|
365
|
+
this._status$.next(FormStatus.Success);
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
this._status$.next(FormStatus.Error);
|
|
369
|
+
}
|
|
370
|
+
this._status$.next(FormStatus.Completing);
|
|
371
|
+
const resetDelay = success ? this.successDelay : this.errorDelay;
|
|
372
|
+
of(true)
|
|
373
|
+
.pipe(delay(resetDelay), first(), takeUntil(this._destroy$)).subscribe(() => {
|
|
374
|
+
if (this.ngForm.form.status === 'VALID') {
|
|
375
|
+
this._status$.next(FormStatus.Valid);
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
this._status$.next(FormStatus.Invalid);
|
|
379
|
+
}
|
|
380
|
+
this._resetButtons();
|
|
381
|
+
this._resetActiveButtons();
|
|
382
|
+
this._updateDirtySubmitButtons();
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
_resetButtons() {
|
|
386
|
+
this._buttons.forEach((button) => {
|
|
387
|
+
button.reset();
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
_resetActiveButtons() {
|
|
391
|
+
this._buttons.forEach((button) => {
|
|
392
|
+
button.resetActive();
|
|
393
|
+
});
|
|
394
|
+
}
|
|
395
|
+
_registerConfirm() {
|
|
396
|
+
this.ngForm.form.valueChanges
|
|
397
|
+
.pipe(takeUntil(this._destroy$))
|
|
398
|
+
.subscribe((changes) => {
|
|
399
|
+
if (this._dialogBackdropEscape && this._dialogRef) {
|
|
400
|
+
this._dialogRef.disableClose = true;
|
|
401
|
+
}
|
|
402
|
+
if (this.confirm) {
|
|
403
|
+
const existing = Object.keys(this._snapshot);
|
|
404
|
+
Object.keys(changes)
|
|
405
|
+
.forEach((name) => {
|
|
406
|
+
if (existing.indexOf(name) === -1) {
|
|
407
|
+
this._snapshot[name] = changes[name];
|
|
408
|
+
}
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
_registerDrawerClose() {
|
|
414
|
+
if (this._drawerRef) {
|
|
415
|
+
this._drawerRef.closeStart$
|
|
416
|
+
.pipe(takeUntil(this._destroy$))
|
|
417
|
+
.subscribe((subscriber) => {
|
|
418
|
+
if (this.submitting) {
|
|
419
|
+
this._status$
|
|
420
|
+
.pipe(filter((status) => status === FormStatus.Success || status === FormStatus.Error), takeUntil(this._destroy$))
|
|
421
|
+
.subscribe((status) => {
|
|
422
|
+
if (status === FormStatus.Success) {
|
|
423
|
+
subscriber.next();
|
|
424
|
+
subscriber.complete();
|
|
425
|
+
}
|
|
426
|
+
else {
|
|
427
|
+
subscriber.error();
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
else {
|
|
432
|
+
subscriber.next();
|
|
433
|
+
subscriber.complete();
|
|
434
|
+
}
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
_registerConfirmDrawerClose() {
|
|
439
|
+
if (this._drawerRef) {
|
|
440
|
+
this._drawerRef.closeStart$
|
|
441
|
+
.pipe(switchMap((subscriber) => {
|
|
442
|
+
return iif(() => this.confirm && this.confirmDrawer, this.triggerConfirm()
|
|
443
|
+
.pipe(map((result) => confirmResultContinue(result)), tap((result) => {
|
|
444
|
+
if (result) {
|
|
445
|
+
subscriber.next();
|
|
446
|
+
subscriber.complete();
|
|
447
|
+
}
|
|
448
|
+
})), defer(() => {
|
|
449
|
+
subscriber.next();
|
|
450
|
+
subscriber.complete();
|
|
451
|
+
}));
|
|
452
|
+
}), takeUntil(this._destroy$))
|
|
453
|
+
.subscribe();
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
_registerConfirmTabs() {
|
|
457
|
+
if (this.tabGroup) {
|
|
458
|
+
this._registerConfirmTabGroup(this.tabGroup);
|
|
459
|
+
}
|
|
460
|
+
this._registerConfirmTabGroups(this._tabGroups.toArray());
|
|
461
|
+
this._tabGroups.changes
|
|
462
|
+
.pipe(takeUntil(this._destroy$))
|
|
463
|
+
.subscribe(() => {
|
|
464
|
+
this._registerConfirmTabGroups(this._tabGroups.toArray());
|
|
465
|
+
});
|
|
466
|
+
}
|
|
467
|
+
_registerConfirmTabGroups(tabGroups) {
|
|
468
|
+
tabGroups.forEach((tabGroup) => {
|
|
469
|
+
this._registerConfirmTabGroup(tabGroup);
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
_registerConfirmTabGroup(tabGroup) {
|
|
473
|
+
const confirmTabGroup = tabGroup;
|
|
474
|
+
if (!confirmTabGroup._originalHandleClick) {
|
|
475
|
+
confirmTabGroup._originalHandleClick = tabGroup._handleClick;
|
|
476
|
+
confirmTabGroup._handlClick$ = new Subject();
|
|
477
|
+
confirmTabGroup._handleClick = (tab, tabHeader, idx) => {
|
|
478
|
+
if (confirmTabGroup._handlClick$.observers.length) {
|
|
479
|
+
confirmTabGroup._handlClick$.next({ tab, tabHeader, idx });
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
confirmTabGroup._originalHandleClick(tab, tabHeader, idx);
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
confirmTabGroup._handlClick$
|
|
487
|
+
.pipe(filter(() => !this.submitting), switchMap((event) => {
|
|
488
|
+
if (this.confirm && this.confirmTabs) {
|
|
489
|
+
return this.triggerConfirm()
|
|
490
|
+
.pipe(tap((result) => {
|
|
491
|
+
if (confirmResultContinue(result)) {
|
|
492
|
+
confirmTabGroup.selectedIndex = event.idx;
|
|
493
|
+
}
|
|
494
|
+
}));
|
|
495
|
+
}
|
|
496
|
+
confirmTabGroup._originalHandleClick(event.tab, event.tabHeader, event.idx);
|
|
497
|
+
return of(null);
|
|
498
|
+
}), takeUntil(this._destroy$))
|
|
499
|
+
.subscribe();
|
|
500
|
+
}
|
|
501
|
+
_registerConfirmDialogBackdropEscape() {
|
|
502
|
+
if (this._dialogRef) {
|
|
503
|
+
this._dialogBackdropEscape = !this._dialogRef?.disableClose;
|
|
504
|
+
if (this._dialogBackdropEscape) {
|
|
505
|
+
this._dialogRef.backdropClick()
|
|
506
|
+
.pipe(takeUntil(this._destroy$))
|
|
507
|
+
.subscribe(() => {
|
|
508
|
+
this._formClose();
|
|
509
|
+
});
|
|
510
|
+
this._destroy$
|
|
511
|
+
.subscribe(() => {
|
|
512
|
+
this._dialogRef.disableClose = false;
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
_registerAutocomplete() {
|
|
518
|
+
this._registerControl = this.ngForm.form.registerControl.bind(this.ngForm.form);
|
|
519
|
+
this.ngForm.form.registerControl = (name, control) => {
|
|
520
|
+
const el = this._element.nativeElement.querySelector(`input[name='${name}']`);
|
|
521
|
+
if (el) {
|
|
522
|
+
if (!el.getAttribute('autocomplete')) {
|
|
523
|
+
el.setAttribute('autocomplete', 'none');
|
|
524
|
+
el.setAttribute('name', `${name}-${guid()}`);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
return this._registerControl(name, control);
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
_registerDirtySubmitButton() {
|
|
531
|
+
if (!this.ngForm) {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
this.ngForm.form.valueChanges
|
|
535
|
+
.pipe(takeUntil(this._destroy$))
|
|
536
|
+
.subscribe(() => {
|
|
537
|
+
this._updateDirtySubmitButtons();
|
|
538
|
+
});
|
|
539
|
+
this._buttons.changes
|
|
540
|
+
.pipe(takeUntil(this._destroy$))
|
|
541
|
+
.subscribe(() => {
|
|
542
|
+
this._updateDirtySubmitButtons();
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
_updateDirtySubmitButtons() {
|
|
546
|
+
this._buttons
|
|
547
|
+
.filter((button) => button.submit)
|
|
548
|
+
.forEach((submitButton) => {
|
|
549
|
+
if (!this.confirm || !this.dirtySubmitButton || this.ngForm.dirty || !submitButton.dirtySubmit) {
|
|
550
|
+
submitButton.enable();
|
|
551
|
+
}
|
|
552
|
+
else {
|
|
553
|
+
submitButton.disable();
|
|
554
|
+
}
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
_broadcastSubmittingEvents() {
|
|
558
|
+
this._status$.next(FormStatus.Submitting);
|
|
559
|
+
this._form.broadcast('submit', this.ngForm);
|
|
560
|
+
}
|
|
561
|
+
_broadcasValidatingEvents() {
|
|
562
|
+
this._status$.next(FormStatus.Validating);
|
|
563
|
+
}
|
|
564
|
+
_setupActiveSubmitButton() {
|
|
565
|
+
this._activeSubmitButton = this._getActiveSubmitButton();
|
|
566
|
+
this._resetButtons();
|
|
567
|
+
if (this._activeSubmitButton) {
|
|
568
|
+
this._activeSubmitButton.process();
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
_disableButtons() {
|
|
572
|
+
this._buttons.forEach((button) => {
|
|
573
|
+
button.disable();
|
|
574
|
+
});
|
|
575
|
+
}
|
|
576
|
+
_waitUntilStatusPending() {
|
|
577
|
+
return this.ngForm.statusChanges
|
|
578
|
+
.pipe(startWith(this.ngForm.status), first((state) => state !== 'PENDING'));
|
|
579
|
+
}
|
|
580
|
+
_handleError(e) {
|
|
581
|
+
console.log('%c Form Submit ', 'color: white; background-color: #D33F49', 'Error occured');
|
|
582
|
+
console.group('Error Details:');
|
|
583
|
+
console.log('Message: ', e);
|
|
584
|
+
console.log('FormRef: ', this);
|
|
585
|
+
if (this.ngForm.invalid) {
|
|
586
|
+
const errors = getFormErrors(this.ngForm.control, null);
|
|
587
|
+
console.log('Validation Errors: ', errors);
|
|
588
|
+
}
|
|
589
|
+
console.groupEnd();
|
|
590
|
+
this._completeSubmit(false, null);
|
|
591
|
+
}
|
|
592
|
+
_registerCanDeactivateGuard() {
|
|
593
|
+
this._activatedRouteConfig = getActiveRoute(this._route).routeConfig;
|
|
594
|
+
if (!this._activatedRouteConfig) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
this._form.registerFormDirective(this._activatedRouteConfig.component, this);
|
|
598
|
+
if (!Array.isArray(this._activatedRouteConfig.canDeactivate)) {
|
|
599
|
+
this._activatedRouteConfig.canDeactivate = [];
|
|
600
|
+
}
|
|
601
|
+
if (this._activatedRouteConfig.canDeactivate.indexOf(FormDeactivateGuard) === -1) {
|
|
602
|
+
this._activatedRouteConfig.canDeactivate.push(FormDeactivateGuard);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
_cleanupCanDeactivate() {
|
|
606
|
+
if (!this._activatedRouteConfig) {
|
|
607
|
+
return;
|
|
608
|
+
}
|
|
609
|
+
const guardIndex = this._activatedRouteConfig.canDeactivate.indexOf(FormDeactivateGuard);
|
|
610
|
+
this._activatedRouteConfig.canDeactivate.splice(guardIndex, 1);
|
|
611
|
+
this._form.removeFormDirective(this._activatedRouteConfig.component);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
FsFormDirective.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsFormDirective, deps: [{ token: NgForm }, { token: i1.FsForm }, { token: i0.ElementRef }, { token: i2.FsMessage }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: MatDialogRef, optional: true }, { token: DrawerRef, optional: true }, { token: i3.ActivatedRoute }], target: i0.ɵɵFactoryTarget.Directive });
|
|
615
|
+
FsFormDirective.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.3.0", type: FsFormDirective, selector: "[fsForm]", inputs: { wrapperSelector: "wrapperSelector", messageSelector: "messageSelector", hintSelector: "hintSelector", labelSelector: "labelSelector", autocomplete: "autocomplete", shortcuts: "shortcuts", confirm: "confirm", confirmDialog: "confirmDialog", confirmDrawer: "confirmDrawer", confirmBrowser: "confirmBrowser", confirmTabs: "confirmTabs", dirtySubmitButton: "dirtySubmitButton", submit: "submit", successDelay: "successDelay", errorDelay: "errorDelay", tabGroup: "tabGroup", deactivationGuard: "deactivationGuard" }, outputs: { submitEvent: "fsForm", invalid: "invalid", valid: "valid", submitted: "submitted", reseted: "reseted", cleared: "cleared" }, host: { properties: { "class.fs-form": "this.fsFormClass" } }, queries: [{ propertyName: "_tabGroups", predicate: MatTabGroup, descendants: true }], exportAs: ["fsForm"], usesOnChanges: true, ngImport: i0 });
|
|
616
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: FsFormDirective, decorators: [{
|
|
617
|
+
type: Directive,
|
|
618
|
+
args: [{
|
|
619
|
+
selector: '[fsForm]',
|
|
620
|
+
exportAs: 'fsForm',
|
|
621
|
+
}]
|
|
622
|
+
}], ctorParameters: function () { return [{ type: i4.NgForm, decorators: [{
|
|
623
|
+
type: Inject,
|
|
624
|
+
args: [NgForm]
|
|
625
|
+
}] }, { type: i1.FsForm }, { type: i0.ElementRef }, { type: i2.FsMessage }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i5.MatDialogRef, decorators: [{
|
|
626
|
+
type: Optional
|
|
627
|
+
}, {
|
|
628
|
+
type: Inject,
|
|
629
|
+
args: [MatDialogRef]
|
|
630
|
+
}] }, { type: i6.DrawerRef, decorators: [{
|
|
631
|
+
type: Optional
|
|
632
|
+
}, {
|
|
633
|
+
type: Inject,
|
|
634
|
+
args: [DrawerRef]
|
|
635
|
+
}] }, { type: i3.ActivatedRoute }]; }, propDecorators: { wrapperSelector: [{
|
|
636
|
+
type: Input
|
|
637
|
+
}], messageSelector: [{
|
|
638
|
+
type: Input
|
|
639
|
+
}], hintSelector: [{
|
|
640
|
+
type: Input
|
|
641
|
+
}], labelSelector: [{
|
|
642
|
+
type: Input
|
|
643
|
+
}], autocomplete: [{
|
|
644
|
+
type: Input
|
|
645
|
+
}], shortcuts: [{
|
|
646
|
+
type: Input
|
|
647
|
+
}], confirm: [{
|
|
648
|
+
type: Input
|
|
649
|
+
}], confirmDialog: [{
|
|
650
|
+
type: Input
|
|
651
|
+
}], confirmDrawer: [{
|
|
652
|
+
type: Input
|
|
653
|
+
}], confirmBrowser: [{
|
|
654
|
+
type: Input
|
|
655
|
+
}], confirmTabs: [{
|
|
656
|
+
type: Input
|
|
657
|
+
}], dirtySubmitButton: [{
|
|
658
|
+
type: Input
|
|
659
|
+
}], submit: [{
|
|
660
|
+
type: Input
|
|
661
|
+
}], successDelay: [{
|
|
662
|
+
type: Input
|
|
663
|
+
}], errorDelay: [{
|
|
664
|
+
type: Input
|
|
665
|
+
}], tabGroup: [{
|
|
666
|
+
type: Input
|
|
667
|
+
}], deactivationGuard: [{
|
|
668
|
+
type: Input
|
|
669
|
+
}], submitEvent: [{
|
|
670
|
+
type: Output,
|
|
671
|
+
args: ['fsForm']
|
|
672
|
+
}], invalid: [{
|
|
673
|
+
type: Output
|
|
674
|
+
}], valid: [{
|
|
675
|
+
type: Output
|
|
676
|
+
}], submitted: [{
|
|
677
|
+
type: Output
|
|
678
|
+
}], reseted: [{
|
|
679
|
+
type: Output
|
|
680
|
+
}], cleared: [{
|
|
681
|
+
type: Output
|
|
682
|
+
}], fsFormClass: [{
|
|
683
|
+
type: HostBinding,
|
|
684
|
+
args: ['class.fs-form']
|
|
685
|
+
}], _tabGroups: [{
|
|
686
|
+
type: ContentChildren,
|
|
687
|
+
args: [MatTabGroup, { descendants: true }]
|
|
688
|
+
}] } });
|
|
689
689
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZm9ybS5kaXJlY3RpdmUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvYXBwL2RpcmVjdGl2ZXMvZm9ybS9mb3JtLmRpcmVjdGl2ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBRUwsaUJBQWlCLEVBQ2pCLGVBQWUsRUFDZixTQUFTLEVBQ1QsVUFBVSxFQUNWLFlBQVksRUFDWixXQUFXLEVBQ1gsTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBSU4sUUFBUSxFQUNSLE1BQU0sRUFDTixTQUFTLEdBRVYsTUFBTSxlQUFlLENBQUM7QUFDdkIsT0FBTyxFQUFtQixNQUFNLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUN6RCxPQUFPLEVBQUUsY0FBYyxFQUFTLE1BQU0saUJBQWlCLENBQUM7QUFFeEQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3hELE9BQU8sRUFBVSxXQUFXLEVBQWdCLE1BQU0sd0JBQXdCLENBQUM7QUFFM0UsT0FBTyxFQUFFLElBQUksRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQzFDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUMvQyxPQUFPLEVBQUUsU0FBUyxFQUFFLFdBQVcsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBRTdELE9BQU8sRUFDTCxlQUFlLEVBQ2YsS0FBSyxFQUNMLFNBQVMsRUFDVCxHQUFHLEVBRUgsRUFBRSxFQUNGLE9BQU8sRUFDUCxVQUFVLEdBQ1gsTUFBTSxNQUFNLENBQUM7QUFDZCxPQUFPLEVBQ0wsVUFBVSxFQUNWLEtBQUssRUFDTCxNQUFNLEVBQ04sS0FBSyxFQUNMLEdBQUcsRUFDSCxLQUFLLEVBQ0wsUUFBUSxFQUNSLFNBQVMsRUFDVCxTQUFTLEVBQ1QsSUFBSSxFQUNKLFNBQVMsRUFDVCxHQUFHLEdBQ0osTUFBTSxnQkFBZ0IsQ0FBQztBQUV4QixPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFB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VyxFQUFFLElBQUksRUFBRSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIEFmdGVyQ29udGVudEluaXQsXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBDb250ZW50Q2hpbGRyZW4sXG4gIERpcmVjdGl2ZSxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0QmluZGluZyxcbiAgSW5qZWN0LFxuICBJbnB1dCxcbiAgTmdab25lLFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPcHRpb25hbCxcbiAgT3V0cHV0LFxuICBRdWVyeUxpc3QsXG4gIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBOZ0Zvcm0gfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuXG5pbXBvcnQgeyBNYXREaWFsb2dSZWYgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2cnO1xuaW1wb3J0IHsgTWF0VGFiLCBNYXRUYWJHcm91cCwgTWF0VGFiSGVhZGVyIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdGFicyc7XG5cbmltcG9ydCB7IGd1aWQgfSBmcm9tICdAZmlyZXN0aXRjaC9jb21tb24nO1xuaW1wb3J0IHsgRHJhd2VyUmVmIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZHJhd2VyJztcbmltcG9ydCB7IEZzTWVzc2FnZSwgTWVzc2FnZU1vZGUgfSBmcm9tICdAZmlyZXN0aXRjaC9tZXNzYWdlJztcblxuaW1wb3J0IHtcbiAgQmVoYXZpb3JTdWJqZWN0LFxuICBkZWZlcixcbiAgZnJvbUV2ZW50LFxuICBpaWYsXG4gIE9ic2VydmFibGUsXG4gIG9mLFxuICBTdWJqZWN0LFxuICB0aHJvd0Vycm9yLFxufSBmcm9tICdyeGpzJztcbmltcG9ydCB7XG4gIGNhdGNoRXJyb3IsXG4gIGRlbGF5LFxuICBmaWx0ZXIsXG4gIGZpcnN0LFxuICBtYXAsXG4gIG1hcFRvLFxuICBtZXJnZU1hcCxcbiAgc3RhcnRXaXRoLFxuICBzd2l0Y2hNYXAsXG4gIHRha2UsXG4gIHRha2VVbnRpbCxcbiAgdGFwLFxufSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IEZvcm1EZWFjdGl2YXRlR3VhcmQgfSBmcm9tICcuLi8uLi9ndWFyZHMvZm9ybS1kZWFjdGl2YXRlLmd1YXJkJztcbmltcG9ydCB7IGNvbmZpcm1SZXN1bHRDb250aW51ZSB9IGZyb20gJy4uLy4uL2hlbHBlcnMvY29uZmlybS1yZXN1bHQtY29udGludWUnO1xuaW1wb3J0IHsgZ2V0QWN0aXZlUm91dGUgfSBmcm9tICcuLi8uLi9oZWxwZXJzL2dldC1hY3RpdmUtcm91dGUnO1xuaW1wb3J0IHsgZ2V0Rm9ybUVycm9ycyB9IGZyb20gJy4uLy4uL2hlbHBlcnMvZ2V0LWZvcm0tZXJyb3JzJztcbmltcG9ydCB7IEZzRm9ybSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL2ZzZm9ybS5zZXJ2aWNlJztcbmltcG9ydCB7IEZzQnV0dG9uRGlyZWN0aXZlIH0gZnJvbSAnLi4vYnV0dG9uLmRpcmVjdGl2ZSc7XG5cbmltcG9ydCB7IENvbmZpcm1SZXN1bHQgfSBmcm9tICcuLy4uLy4uL2VudW1zL2NvbmZpcm0tcmVzdWx0JztcbmltcG9ydCB7IEZvcm1TdGF0dXMgfSBmcm9tICcuLy4uLy4uL2VudW1zL2Zvcm0tc3RhdHVzJztcbmltcG9ydCB7IENvbmZpcm1Db25maWcsIENvbmZpcm1UYWJHcm91cCwgU3VibWl0dGVkRXZlbnQgfSBmcm9tICcuLy4uLy4uL2ludGVyZmFjZXMnO1xuaW1wb3J0IHsgU3VibWl0RXZlbnQgfSBmcm9tICcuLy4uLy4uL2ludGVyZmFjZXMvc3VibWl0LWV2ZW50JztcblxuXG5ARGlyZWN0aXZlKHtcbiAgc2VsZWN0b3I6ICdbZnNGb3JtXScsXG4gIGV4cG9ydEFzOiAnZnNGb3JtJyxcbn0pXG5leHBvcnQgY2xhc3MgRnNGb3JtRGlyZWN0aXZlIGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyQ29udGVudEluaXQsIE9uQ2hhbmdlcyB7XG5cbiAgQElucHV0KClcbiAgcHVibGljIHdyYXBwZXJTZWxlY3RvciA9ICcuZnMtZm9ybS13cmFwcGVyLC5tYXQtZm9ybS1maWVsZCc7XG5cbiAgQElucHV0KClcbiAgcHVibGljIG1lc3NhZ2VTZWxlY3RvciA9ICcuZnMtZm9ybS1tZXNzYWdlLC5tYXQtZm9ybS1maWVsZC1zdWJzY3JpcHQtd3JhcHBlcic7XG5cbiAgQElucHV0KClcbiAgcHVibGljIGhpbnRTZWxlY3RvciA9ICcuZnMtZm9ybS1oaW50LC5tYXQtZm9ybS1maWVsZC1oaW50LXdyYXBwZXInO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBsYWJlbFNlbGVjdG9yID0gJy5mcy1mb3JtLWxhYmVsLC5tYXQtZm9ybS1maWVsZC1sYWJlbCc7XG5cbiAgQElucHV0KClcbiAgcHVibGljIGF1dG9jb21wbGV0ZSA9IGZhbHNlO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBzaG9ydGN1dHMgPSB0cnVlOyAvLyBDdHJsICsgc1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjb25maXJtOiBDb25maXJtQ29uZmlnIHwgYm9vbGVhbiA9IHRydWU7XG5cbiAgQElucHV0KClcbiAgcHVibGljIGNvbmZpcm1EaWFsb2cgPSB0cnVlO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjb25maXJtRHJhd2VyID0gdHJ1ZTtcblxuICBASW5wdXQoKVxuICBwdWJsaWMgY29uZmlybUJyb3dzZXIgPSB0cnVlO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjb25maXJtVGFicyA9IHRydWU7XG5cbiAgQElucHV0KClcbiAgcHVibGljIGRpcnR5U3VibWl0QnV0dG9uID0gdHJ1ZTtcblxuICBASW5wdXQoKVxuICBwdWJsaWMgc2V0IHN1Ym1pdChzdWJtaXQkOiAoZXZlbnQ6IFN1Ym1pdEV2ZW50KSA9PiBPYnNlcnZhYmxlPGFueT4pIHtcbiAgICB0aGlzLl9zdWJtaXQkID0gc3VibWl0JDtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgc3VibWl0KCk6IChldmVudDogU3VibWl0RXZlbnQpID0+IE9ic2VydmFibGU8YW55PiB7XG4gICAgcmV0dXJuIHRoaXMuX3N1Ym1pdCQ7XG4gIH1cblxuICBASW5wdXQoKVxuICBwdWJsaWMgc3VjY2Vzc0RlbGF5ID0gMDtcblxuICBASW5wdXQoKVxuICBwdWJsaWMgZXJyb3JEZWxheSA9IDEwMDA7XG5cbiAgQElucHV0KClcbiAgcHVibGljIHRhYkdyb3VwOiBNYXRUYWJHcm91cDtcblxuICBASW5wdXQoKVxuICBwdWJsaWMgZGVhY3RpdmF0aW9uR3VhcmQgPSB0cnVlO1xuXG4gIEBPdXRwdXQoJ2ZzRm9ybScpXG4gIHB1YmxpYyBzdWJtaXRFdmVudDogRXZlbnRFbWl0dGVyPFN1Ym1pdEV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KClcbiAgcHVibGljIGludmFsaWQ6IEV2ZW50RW1pdHRlcjxTdWJtaXRFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpXG4gIHB1YmxpYyB2YWxpZDogRXZlbnRFbWl0dGVyPFN1Ym1pdEV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KClcbiAgcHVibGljIHN1Ym1pdHRlZDogRXZlbnRFbWl0dGVyPFN1Ym1pdEV2ZW50PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBAT3V0cHV0KClcbiAgcHVibGljIHJlc2V0ZWQ6IEV2ZW50RW1pdHRlcjxTdWJtaXRFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQE91dHB1dCgpXG4gIHB1YmxpYyBjbGVhcmVkOiBFdmVudEVtaXR0ZXI8U3VibWl0RXZlbnQ+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIEBIb3N0QmluZGluZygnY2xhc3MuZnMtZm9ybScpXG4gIHB1YmxpYyBmc0Zvcm1DbGFzcyA9IHRydWU7XG5cbiAgQENvbnRlbnRDaGlsZHJlbihNYXRUYWJHcm91cCwgeyBkZXNjZW5kYW50czogdHJ1ZSB9KVxuICBwcml2YXRlIF90YWJHcm91cHM6IFF1ZXJ5TGlzdDxNYXRUYWJHcm91cD4gPSBuZXcgUXVlcnlMaXN0KCk7XG5cbiAgcHJpdmF0ZSBfYnV0dG9ucyA9IG5ldyBRdWVyeUxpc3Q8RnNCdXR0b25EaXJlY3RpdmU+KCk7XG4gIHByaXZhdGUgX3JlZ2lzdGVyQ29udHJvbDtcbiAgcHJpdmF0ZSBfYWN0aXZlU3VibWl0QnV0dG9uOiBGc0J1dHRvbkRpcmVjdGl2ZTtcbiAgcHJpdmF0ZSBfZGlhbG9nQmFja2Ryb3BFc2NhcGUgPSBmYWxzZTtcbiAgcHJpdmF0ZSBfc25hcHNob3Q6IHsgW2tleTogc3RyaW5nXTogYW55IH0gPSB7fTtcbiAgcHJpdmF0ZSBfYWN0aXZhdGVkUm91dGVDb25maWc6IFJvdXRlIHwgbnVsbDtcbiAgcHJpdmF0ZSBfc3RhdHVzJCA9IG5ldyBCZWhhdmlvclN1YmplY3QoRm9ybVN0YXR1cy5WYWxpZCk7XG4gIHByaXZhdGUgX2Rlc3Ryb3kkID0gbmV3IFN1YmplY3QoKTtcbiAgcHJpdmF0ZSBfY29uZmlybWVkID0gZmFsc2U7XG4gIHByaXZhdGUgX3N1Ym1pdCQ6IChldmVudDogU3VibWl0RXZlbnQpID0+IE9ic2VydmFibGU8YW55PiA9IG51bGw7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgQEluamVjdChOZ0Zvcm0pXG4gICAgcHVibGljIG5nRm9ybTogTmdGb3JtLFxuICAgIHByaXZhdGUgX2Zvcm06IEZzRm9ybSxcbiAgICBwcml2YXRlIF9lbGVtZW50OiBFbGVtZW50UmVmLFxuICAgIHByaXZhdGUgX21lc3NhZ2U6IEZzTWVzc2FnZSxcbiAgICBwcml2YXRlIF9uZ1pvbmU6IE5nWm9uZSxcbiAgICBwcml2YXRlIF9jZFJlZjogQ2hhbmdlRGV0ZWN0b3JSZWYsXG5cbiAgICBAT3B0aW9uYWwoKSBASW5qZWN0KE1hdERpYWxvZ1JlZilcbiAgICBwcml2YXRlIF9kaWFsb2dSZWY6IE1hdERpYWxvZ1JlZjxhbnk+LFxuXG4gICAgQE9wdGlvbmFsKCkgQEluamVjdChEcmF3ZXJSZWYpXG4gICAgcHJpdmF0ZSBfZHJhd2VyUmVmOiBEcmF3ZXJSZWY8YW55PixcblxuICAgIHByaXZhdGUgX3JvdXRlOiBBY3RpdmF0ZWRSb3V0ZSxcbiAgKSB7IH1cblxuICBwdWJsaWMgZ2V0IHN1Ym1pdHRpbmcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX3N0YXR1cyQuZ2V0VmFsdWUoKSA9PT0gRm9ybVN0YXR1cy5TdWJtaXR0aW5nO1xuICB9XG5cbiAgcHVibGljIGdldCB2YWxpZGF0aW5nKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9zdGF0dXMkLmdldFZhbHVlKCkgPT09IEZvcm1TdGF0dXMuVmFsaWRhdGluZztcbiAgfVxuXG4gIHB1YmxpYyBnZXQgY29tcGxldGluZygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5fc3RhdHVzJC5nZXRWYWx1ZSgpID09PSBGb3JtU3RhdHVzLkNvbXBsZXRpbmc7XG4gIH1cblxuICBwcml2YXRlIGdldCBfc3VibWl0RXZlbnQoKTogU3VibWl0RXZlbnQge1xuICAgIHJldHVybiB7XG4gICAgICBuZ0Zvcm06IHRoaXMubmdGb3JtLFxuICAgICAgc3VibWl0dGVyOiB0aGlzLl9zdWJtaXR0ZXIsXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IF9mb3JtVmFsaWRTdGF0ZSQoKTogT2JzZXJ2YWJsZTxTdWJtaXR0ZWRFdmVudD4ge1xuICAgIHRoaXMuX2Zvcm0uYnJvYWRjYXN0KCd2YWxpZCcsIHRoaXMuX3N1Ym1pdEV2ZW50KTtcbiAgICB0aGlzLnN1Ym1pdEV2ZW50LmVtaXQodGhpcy5fc3VibWl0RXZlbnQpO1xuICAgIHRoaXMudmFsaWQuZW1pdCh0aGlzLl9zdWJtaXRFdmVudCk7XG5cbiAgICBjb25zdCBzdWJtaXR0ZWRFdmVudDogU3VibWl0dGVkRXZlbnQgPSB7XG4gICAgICBuZ0Zvcm06IHRoaXMubmdGb3JtLFxuICAgICAgc3VibWl0dGVyOiB0aGlzLl9zdWJtaXR0ZXIsXG4gICAgICByZXNwb25zZTogbnVsbCxcbiAgICB9O1xuXG4gICAgY29uc3Qgc3VibWl0JDogT2JzZXJ2YWJsZTxhbnk+ID0gdGhpcy5fc3VibWl0JCA/XG4gICAgICB0aGlzLl9zdWJtaXQkKHRoaXMuX3N1Ym1pdEV2ZW50KSA6IG9mKHN1Ym1pdHRlZEV2ZW50KTtcblxuICAgIHJldHVybiBzdWJtaXQkXG4gICAgICAucGlwZShcbiAgICAgICAgbWFwKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIHN1Ym1pdHRlZEV2ZW50LnJlc3BvbnNlID0gcmVzcG9uc2U7XG5cbiAgICAgICAgICByZXR1cm4gc3VibWl0dGVkRXZlbnQ7XG4gICAgICAgIH0pLFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IF9mb3JtSW52YWxpZFN0YXRlJCgpOiBPYnNlcnZhYmxlPG5ldmVyPiB7XG4gICAgdGhpcy5fZm9ybS5icm9hZGNhc3QoJ2ludmFsaWQnLCB0aGlzLl9zdWJtaXRFdmVudCk7XG5cbiAgICBpZiAodGhpcy5pbnZhbGlkKSB7XG4gICAgICB0aGlzLmludmFsaWQuZW1pdCh0aGlzLl9zdWJtaXRFdmVudCk7XG4gICAgfVxuXG4gICAgY29uc3QgbWVzc2FnZSA9ICdQbGVhc2UgcmV2aWV3IGVycm9ycyBoaWdobGlnaHRlZCBpbiByZWQnO1xuICAgIHRoaXMuX21lc3NhZ2UuZXJyb3IobWVzc2FnZSwgeyBtb2RlOiBNZXNzYWdlTW9kZS5Ub2FzdCB9KTtcblxuICAgIGNvbnN0IGVsID0gdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LnF1ZXJ5U2VsZWN0b3IoJy5uZy1pbnZhbGlkJyk7XG5cbiAgICBpZiAoZWwpIHtcbiAgICAgIGVsLnNjcm9sbEludG9WaWV3KHsgYmVoYXZpb3I6ICdzbW9vdGgnLCBibG9jazogJ25lYXJlc3QnIH0pO1xuICAgIH1cblxuICAgIHJldHVybiB0aHJvd0Vycm9yKCdGb3JtIHZhbGlkYXRpb24gZXJyb3InKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IF9zdWJtaXR0ZXIoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5fYWN0aXZlU3VibWl0QnV0dG9uXG4gICAgICA/IHRoaXMuX2FjdGl2ZVN1Ym1pdEJ1dHRvbi5uYW1lXG4gICAgICA6IG51bGw7XG4gIH1cblxuICBwdWJsaWMgbmdPbkluaXQoKSB7XG4gICAgaWYgKHRoaXMuZGVhY3RpdmF0aW9uR3VhcmQpIHtcbiAgICAgIHRoaXMuX3JlZ2lzdGVyQ2FuRGVhY3RpdmF0ZUd1YXJkKCk7XG4gICAgfVxuXG4gICAgdGhpcy5fcmVnaXN0ZXJDb25maXJtRGlhbG9nQmFja2Ryb3BFc2NhcGUoKTtcbiAgICB0aGlzLl9saXN0ZW5Ib3RLZXlzKCk7XG4gICAgdGhpcy5fbGlzdGVuV2luZG93Q2xvc2UoKTtcbiAgICB0aGlzLl9saXN0ZW5TdWJtaXQoKTtcbiAgICB0aGlzLl9saXN0ZW5Gb3JtU3RhdHVzKCk7XG5cbiAgICBpZiAoIXRoaXMuYXV0b2NvbXBsZXRlKSB7XG4gICAgICB0aGlzLl9yZWdpc3RlckF1dG9jb21wbGV0ZSgpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgaWYgKGNoYW5nZXMuY29uZmlybSkge1xuICAgICAgdGhpcy5fdXBkYXRlRGlydHlTdWJtaXRCdXR0b25zKCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGNsZWFyU3VibWl0KCk6IHZvaWQge1xuICAgIHRoaXMuX3N1Ym1pdCQgPSBudWxsO1xuXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLl9jZFJlZi5tYXJrRm9yQ2hlY2soKTtcbiAgICB9KTtcbiAgfVxuXG4gIHB1YmxpYyByZWdpc3RlclN1Ym1pdChzdWJtaXQkOiAoKSA9PiBPYnNlcnZhYmxlPGFueT4pOiB2b2lkIHtcbiAgICB0aGlzLl9zdWJtaXQkID0gc3VibWl0JDtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5fY2RSZWYubWFya0ZvckNoZWNrKCk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgIHRoaXMuX3JlZ2lzdGVyQ29uZmlybSgpO1xuICAgIHRoaXMuX3JlZ2lzdGVyQ29uZmlybURyYXdlckNsb3NlKCk7XG4gICAgdGhpcy5fcmVnaXN0ZXJDb25maXJtVGFicygpO1xuICAgIHRoaXMuX3JlZ2lzdGVyRHJhd2VyQ2xvc2UoKTtcbiAgICB0aGlzLl9yZWdpc3RlckRpcnR5U3VibWl0QnV0dG9uKCk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5fY2xlYW51cENhbkRlYWN0aXZhdGUoKTtcbiAgICB0aGlzLl9kZXN0cm95JC5uZXh0KCk7XG4gICAgdGhpcy5fZGVzdHJveSQuY29tcGxldGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBjcmVhdGVTbmFwc2hvdCgpOiB2b2lkIHtcbiAgICB0aGlzLl9zbmFwc2hvdCA9IHRoaXMubmdGb3JtLnZhbHVlO1xuICB9XG5cbiAgcHVibGljIGdldFNuYXBzaG90KCk6IHsgW2tleTogc3RyaW5nXTogYW55IH0ge1xuICAgIHJldHVybiB0aGlzLl9zbmFwc2hvdCB8fCB7fTtcbiAgfVxuXG4gIHB1YmxpYyByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLm5nRm9ybS5yZXNldEZvcm0oKTtcblxuICAgIE9iamVjdC5rZXlzKHRoaXMubmdGb3JtLmNvbnRyb2xzKVxuICAgICAgLmZvckVhY2goKG5hbWU6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBjb250cm9sID0gdGhpcy5uZ0Zvcm0uY29udHJvbHNbbmFtZV07XG4gICAgICAgIGNvbnRyb2wucmVzZXQodGhpcy5fc25hcHNob3RbbmFtZV0pO1xuICAgICAgfSk7XG5cbiAgICB0aGlzLnJlc2V0ZWQuZW1pdCgpO1xuICB9XG5cbiAgcHVibGljIGNsZWFyKCk6IHZvaWQge1xuICAgIHRoaXMubmdGb3JtLnJlc2V0Rm9ybSgpO1xuICAgIHRoaXMuY2xlYXJlZC5lbWl0KCk7XG4gIH1cblxuICBwdWJsaWMgZGlydHkoKTogdm9pZCB7XG4gICAgdGhpcy5uZ0Zvcm0uZm9ybS5tYXJrQXNEaXJ0eSgpO1xuICAgIHRoaXMuX3VwZGF0ZURpcnR5U3VibWl0QnV0dG9ucygpO1xuICB9XG5cbiAgcHVibGljIHRyaWdnZXJTdWJtaXQob3B0aW9ucz86IHsgY29uZmlybWVkOiBib29sZWFuIH0pOiB2b2lkIHtcbiAgICB0aGlzLl9jb25maXJtZWQgPSBvcHRpb25zPy5jb25maXJtZWQ7XG4gICAgdGhpcy5uZ0Zvcm0ubmdTdWJtaXQuZW1pdCgpO1xuICB9XG5cbiAgcHVibGljIHRyaWdnZXJDb25maXJtKCk6IE9ic2VydmFibGU8Q29uZmlybVJlc3VsdD4ge1xuICAgIGNvbnN0IHN1Ym1pdHRlZCA9IHRoaXMuc3VibWl0dGluZyA/IHRoaXMuc3VibWl0dGVkLmFzT2JzZXJ2YWJsZSgpIDogb2Yoe30pO1xuXG4gICAgcmV0dXJuIHN1Ym1pdHRlZFxuICAgICAgLnBpcGUoXG4gICAgICAgIHRha2UoMSksXG4gICAgICAgIG1lcmdlTWFwKCgpID0+IHRoaXMuX2Zvcm0uY29uZmlybVVuc2F2ZWQoW3RoaXNdKSksXG4gICAgICApO1xuICB9XG5cbiAgcHVibGljIGVuYWJsZSgpOiB2b2lkIHtcbiAgICB0aGlzLm5nRm9ybS5jb250cm9sLmVuYWJsZSgpO1xuXG4gICAgdGhpcy5fdXBkYXRlRGlydHlTdWJtaXRCdXR0b25zKCk7XG4gIH1cblxuICBwdWJsaWMgZGlzYWJsZSgpOiB2b2lkIHtcbiAgICB0aGlzLm5nRm9ybS5jb250cm9sLmRpc2FibGUoKTtcblxuICAgIHRoaXMuX2J1dHRvbnMuZm9yRWFjaCgoYnV0dG9uKSA9PiB7XG4gICAgICBidXR0b24uZGlzYWJsZSgpO1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGFkZEJ1dHRvbihidXR0b246IEZzQnV0dG9uRGlyZWN0aXZlKTogdm9pZCB7XG4gICAgdGhpcy5fYnV0dG9ucy5yZXNldChcbiAgICAgIFtcbiAgICAgICAgLi4udGhpcy5fYnV0dG9ucy50b0FycmF5KCksXG4gICAgICAgIGJ1dHRvbixcbiAgICAgIF0pO1xuICB9XG5cbiAgcHVibGljIHJlbW92ZUJ1dHRvbihidXR0b246IEZzQnV0dG9uRGlyZWN0aXZlKTogdm9pZCB7XG4gICAgdGhpcy5fYnV0dG9ucy5yZXNldChcbiAgICAgIFtcbiAgICAgICAgLi4udGhpcy5fYnV0dG9ucy50b0FycmF5KClcbiAgICAgICAgICAuZmlsdGVyKChpdGVtKSA9PiAoYnV0dG9uICE9PSBpdGVtKSksXG4gICAgICBdKTtcbiAgfVxuXG4gIHB1YmxpYyB2YWxpZGF0ZSgpOiB2b2lkIHtcbiAgICBPYmplY3QudmFsdWVzKHRoaXMubmdGb3JtLmNvbnRyb2xzKVxuICAgICAgLmZvckVhY2goKGNvbnRyb2wpID0+IHtcbiAgICAgICAgY29udHJvbC5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICBjb250cm9sLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgY29udHJvbC51cGRhdGVWYWx1ZUFuZFZhbGlkaXR5KCk7XG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2xpc3RlblN1Ym1pdCgpOiB2b2lkIHtcbiAgICB0aGlzLm5nRm9ybVxuICAgICAgLm5nU3VibWl0XG4gICAgICAucGlwZShcbiAgICAgICAgdGFwKChldmVudCkgPT4ge1xuICAgICAgICAgIGV2ZW50Py5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9KSxcbiAgICAgICAgbWFwKChldmVudCkgPT4ge1xuICAgICAgICAgIHJldHVybiB7IGV2ZW50LCBjb25maXJtZWQ6IHRoaXMuX2NvbmZpcm1lZCB9O1xuICAgICAgICB9KSxcbiAgICAgICAgdGFwKCgpID0+IHRoaXMuX2NvbmZpcm1lZCA9IGZhbHNlKSxcbiAgICAgICAgZmlsdGVyKCgpID0+IHtcbiAgICAgICAgICByZXR1cm4gW0Zvcm1TdGF0dXMuVmFsaWQsIEZvcm1TdGF0dXMuSW52YWxpZF1cbiAgICAgICAgICAgIC5pbmNsdWRlcyh0aGlzLl9zdGF0dXMkLmdldFZhbHVlKCkpO1xuICAgICAgICB9KSxcbiAgICAgICAgdGFwKCgpID0+IHRoaXMuX2Jyb2FkY2FzVmFsaWRhdGluZ0V2ZW50cygpKSxcbiAgICAgICAgdGFwKCgpID0+IHRoaXMudmFsaWRhdGUoKSksXG4gICAgICAgIHRhcCgoKSA9PiB0aGlzLl9icm9hZGNhc3RTdWJtaXR0aW5nRXZlbnRzKCkpLFxuICAgICAgICBzd2l0Y2hNYXAoKGRhdGEpID0+IHRoaXMuX3dhaXRVbnRpbFN0YXR1c1BlbmRpbmcoKVxuICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgbWFwVG8oZGF0YSksXG4gICAgICAgICAgKSksXG4gICAgICAgIHRhcCgoKSA9PiB0aGlzLl9zZXR1cEFjdGl2ZVN1Ym1pdEJ1dHRvbigpKSxcbiAgICAgICAgdGFwKCgpID0+IHRoaXMuX2Rpc2FibGVCdXR0b25zKCkpLFxuICAgICAgICBtZXJnZU1hcCgoZGF0YSkgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLm5nRm9ybS5zdGF0dXMgPT09ICdJTlZBTElEJykge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2Zvcm1JbnZhbGlkU3RhdGUkO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB0aGlzLl9mb3JtVmFsaWRTdGF0ZSRcbiAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICBtYXAoKHN1Ym1pdEV2ZW50KSA9PiAoe1xuICAgICAgICAgICAgICAgIC4uLnN1Ym1pdEV2ZW50LFxuICAgICAgICAgICAgICAgIGNvbmZpcm1lZDogZGF0YS5jb25maXJtZWQsXG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICApLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSksXG4gICAgICAgIGNhdGNoRXJyb3IoKGUsIHNvdXJjZSQpID0+IHtcbiAgICAgICAgICB0aGlzLl9oYW5kbGVFcnJvcihlKTtcblxuICAgICAgICAgIHJldHVybiBzb3VyY2UkO1xuICAgICAgICB9KSxcbiAgICAgICAgdGFwKChzdWJtaXR0ZWRFdmVudDogU3VibWl0dGVkRXZlbnQpID0+IHtcbiAgICAgICAgICB0aGlzLl9jb21wbGV0ZVN1Ym1pdCh0cnVlLCBzdWJtaXR0ZWRFdmVudCk7XG4gICAgICAgIH0pLFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBfbGlzdGVuRm9ybVN0YXR1cygpOiB2b2lkIHtcbiAgICB0aGlzLl9zdGF0dXMkXG4gICAgICAucGlwZShcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kkKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKGZvcm1TdGF0dXM6IEZvcm1TdGF0dXMpID0+IHtcbiAgICAgICAgY29uc3QgY2xzID0gW0Zvcm1TdGF0dXMuU3VibWl0dGluZywgRm9ybVN0YXR1cy5WYWxpZGF0aW5nXTtcbiAgICAgICAgY29uc3QgY2xhc3NMaXN0ID0gdGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50LmNsYXNzTGlzdDtcbiAgICAgICAgY2xhc3NMaXN0LnJlbW92ZSguLi5jbHMpO1xuICAgICAgICBpZiAoY2xzLmluZGV4T2YoZm9ybVN0YXR1cykgIT09IC0xKSB7XG4gICAgICAgICAgY2xhc3NMaXN0LmFkZChmb3JtU3RhdHVzKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgfVxuXG4gIHByaXZhdGUgX2xpc3RlbldpbmRvd0Nsb3NlKCk6IHZvaWQge1xuICAgIGZyb21FdmVudCh3aW5kb3csICdiZWZvcmV1bmxvYWQnKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHRha2VVbnRpbCh0aGlzLl9kZXN0cm95JCksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKChldmVudDogRXZlbnQpID0+IHtcbiAgICAgICAgaWYgKHRoaXMuY29uZmlybSAmJiB0aGlzLmNvbmZpcm1Ccm93c2VyICYmIHRoaXMubmdGb3JtLmRpcnR5KSB7XG4gICAgICAgICAgZXZlbnQucmV0dXJuVmFsdWUgPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9hY3RpdmVEaWFsb2coZWwsIGRpYWxvZzogSFRNTEVsZW1lbnQpOiBib29sZWFuIHtcbiAgICBpZiAoZWwuaXNTYW1lTm9kZShkaWFsb2cpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9IGVsc2UgaWYgKGVsLnBhcmVudEVsZW1lbnQpIHtcbiAgICAgIHJldHVybiB0aGlzLl9hY3RpdmVEaWFsb2coZWwucGFyZW50RWxlbWVudCwgZGlhbG9nKTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIF9saXN0ZW5Ib3RLZXlzKCk6IHZvaWQge1xuICAgIHRoaXMuX25nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICBmcm9tRXZlbnQoZG9jdW1lbnQsICdrZXlkb3duJylcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kkKSxcbiAgICAgICAgKVxuICAgICAgICAuc3Vic2NyaWJlKChldmVudDogS2V5Ym9hcmRFdmVudCkgPT4ge1xuICAgICAgICAgIGlmICh0aGlzLl9kaWFsb2dCYWNrZHJvcEVzY2FwZSAmJiBldmVudC5jb2RlID09PSAnRXNjYXBlJykge1xuICAgICAgICAgICAgY29uc3QgY2RrT3ZlcmxheVBhbmUgPSBBcnJheVxuICAgICAgICAgICAgICAuZnJvbShkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsPEhUTUxFbGVtZW50PignLmNkay1vdmVybGF5LXBhbmUnKSkucG9wKCk7XG4gICAgXG4gICAgICAgICAgICBjb25zdCBhY3RpdmVEaWFsb2cgPSB0aGlzXG4gICAgICAgICAgICAgIC5fYWN0aXZlRGlhbG9nKGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuX2RpYWxvZ1JlZi5pZCksIGNka092ZXJsYXlQYW5lKTtcblxuICAgICAgICAgICAgaWYgKGFjdGl2ZURpYWxvZykge1xuICAgICAgICAgICAgICB0aGlzLl9uZ1pvbmUucnVuKCgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLl9mb3JtQ2xvc2UoKTtcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKChldmVudC5jdHJsS2V5IHx8IGV2ZW50Lm1ldGFLZXkpICYmIGV2ZW50LmNvZGUgPT09ICdLZXlTJykge1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuc2hvcnRjdXRzKSB7XG4gICAgICAgICAgICAgIGlmICh0aGlzLl9lbGVtZW50SW5Gb3JtKGRvY3VtZW50LmFjdGl2ZUVsZW1lbnQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5uZ0Zvcm0ubmdTdWJtaXQubmV4dCgpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2Zvcm1DbG9zZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jb25maXJtICYmIHRoaXMuY29uZmlybURpYWxvZykge1xuICAgICAgdGhpcy50cmlnZ2VyQ29uZmlybSgpXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIGZpbHRlcigocmVzdWx0KSA9PiBjb25maXJtUmVzdWx0Q29udGludWUocmVzdWx0KSksXG4gICAgICAgICAgc3dpdGNoTWFwKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHQgPT09IENvbmZpcm1SZXN1bHQuUHJpc3RpbmUgfHwgcmVzdWx0ID09PSBDb25maXJtUmVzdWx0LkRpc2NhcmRcbiAgICAgICAgICAgICAgPyBvZihudWxsKVxuICAgICAgICAgICAgICA6IHRoaXMuc3VibWl0dGVkLmFzT2JzZXJ2YWJsZSgpO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIHRha2VVbnRpbCh0aGlzLl9kZXN0cm95JCksXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSgocmVzdWx0OiBTdWJtaXR0ZWRFdmVudCkgPT4ge1xuICAgICAgICAgIHRoaXMuX2RpYWxvZ1JlZi5jbG9zZShyZXN1bHQ/LnJlc3BvbnNlKTtcbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2RpYWxvZ1JlZi5jbG9zZShudWxsKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9nZXRBY3RpdmVTdWJtaXRCdXR0b24oKTogRnNCdXR0b25EaXJlY3RpdmUge1xuICAgIGNvbnN0IHN1Ym1pdEJ1dHRvbnMgPSB0aGlzLl9idXR0b25zXG4gICAgICAuZmlsdGVyKChidXR0b24pID0+IGJ1dHRvbi5zdWJtaXQpO1xuXG4gICAgY29uc3QgYWN0aXZlQnV0dG9uID0gc3VibWl0QnV0dG9uc1xuICAgICAgLmZpbmQoKGJ1dHRvbikgPT4ge1xuICAgICAgICByZXR1cm4gYnV0dG9uLmFjdGl2ZTtcbiAgICAgIH0pO1xuXG4gICAgcmV0dXJuIGFjdGl2ZUJ1dHRvbiA/IGFjdGl2ZUJ1dHRvbiA6IHN1Ym1pdEJ1dHRvbnNbMF07XG4gIH1cblxuICBwcml2YXRlIF9lbGVtZW50SW5Gb3JtKGVsOiBFbGVtZW50KTogYm9vbGVhbiB7XG4gICAgaWYgKGVsLmlzU2FtZU5vZGUodGhpcy5fZWxlbWVudC5uYXRpdmVFbGVtZW50KSkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBlbHNlIGlmIChlbC5wYXJlbnRFbGVtZW50KSB7XG4gICAgICByZXR1cm4gdGhpcy5fZWxlbWVudEluRm9ybShlbC5wYXJlbnRFbGVtZW50KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBwcml2YXRlIF9jb21wbGV0ZVN1Ym1pdChzdWNjZXNzLCBzdWJtaXRFdmVudDogU3VibWl0dGVkRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAoc3VjY2Vzcykge1xuICAgICAgdGhpcy5uZ0Zvcm0uY29udHJvbC5tYXJrQXNQcmlzdGluZSgpO1xuICAgICAgdGhpcy5jcmVhdGVTbmFwc2hvdCgpO1xuICAgICAgdGhpcy5zdWJtaXR0ZWQuZW1pdChzdWJtaXRFdmVudCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX3Jlc2V0QnV0dG9ucygpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLl9hY3RpdmVTdWJtaXRCdXR0b24pIHtcbiAgICAgIGlmIChzdWNjZXNzKSB7XG4gICAgICAgIHRoaXMuX2FjdGl2ZVN1Ym1pdEJ1dHRvbi5zdWNjZXNzKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLl9hY3RpdmVTdWJtaXRCdXR0b24uZXJyb3IoKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0aGlzLl9zdGF0dXMkLm5leHQoRm9ybVN0YXR1cy5TdWJtaXR0ZWQpO1xuXG4gICAgaWYgKHN1Y2Nlc3MpIHtcbiAgICAgIHRoaXMuX3N0YXR1cyQubmV4dChGb3JtU3RhdHVzLlN1Y2Nlc3MpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl9zdGF0dXMkLm5leHQoRm9ybVN0YXR1cy5FcnJvcik7XG4gICAgfVxuXG4gICAgdGhpcy5fc3RhdHVzJC5uZXh0KEZvcm1TdGF0dXMuQ29tcGxldGluZyk7XG5cbiAgICBjb25zdCByZXNldERlbGF5ID0gc3VjY2VzcyA/IHRoaXMuc3VjY2Vzc0RlbGF5IDogdGhpcy5lcnJvckRlbGF5O1xuXG4gICAgb2YodHJ1ZSlcbiAgICAgIC5waXBlKFxuICAgICAgICBkZWxheShyZXNldERlbGF5KSxcbiAgICAgICAgZmlyc3QoKSxcbiAgICAgICAgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kkKSxcbiAgICAgICkuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgaWYgKHRoaXMubmdGb3JtLmZvcm0uc3RhdHVzID09PSAnVkFMSUQnKSB7XG4gICAgICAgICAgdGhpcy5fc3RhdHVzJC5uZXh0KEZvcm1TdGF0dXMuVmFsaWQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRoaXMuX3N0YXR1cyQubmV4dChGb3JtU3RhdHVzLkludmFsaWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcmVzZXRCdXR0b25zKCk7XG4gICAgICAgIHRoaXMuX3Jlc2V0QWN0aXZlQnV0dG9ucygpO1xuICAgICAgICB0aGlzLl91cGRhdGVEaXJ0eVN1Ym1pdEJ1dHRvbnMoKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVzZXRCdXR0b25zKCk6IHZvaWQge1xuICAgIHRoaXMuX2J1dHRvbnMuZm9yRWFjaCgoYnV0dG9uKSA9PiB7XG4gICAgICBidXR0b24ucmVzZXQoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX3Jlc2V0QWN0aXZlQnV0dG9ucygpOiB2b2lkIHtcbiAgICB0aGlzLl9idXR0b25zLmZvckVhY2goKGJ1dHRvbikgPT4ge1xuICAgICAgYnV0dG9uLnJlc2V0QWN0aXZlKCk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9yZWdpc3RlckNvbmZpcm0oKTogdm9pZCB7XG4gICAgdGhpcy5uZ0Zvcm0uZm9ybS52YWx1ZUNoYW5nZXNcbiAgICAgIC5waXBlKFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoY2hhbmdlcykgPT4ge1xuICAgICAgICBpZih0aGlzLl9kaWFsb2dCYWNrZHJvcEVzY2FwZSAmJiB0aGlzLl9kaWFsb2dSZWYpIHtcbiAgICAgICAgICB0aGlzLl9kaWFsb2dSZWYuZGlzYWJsZUNsb3NlID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmNvbmZpcm0pIHtcbiAgICAgICAgICBjb25zdCBleGlzdGluZyA9IE9iamVjdC5rZXlzKHRoaXMuX3NuYXBzaG90KTtcblxuICAgICAgICAgIE9iamVjdC5rZXlzKGNoYW5nZXMpXG4gICAgICAgICAgICAuZm9yRWFjaCgobmFtZTogc3RyaW5nKSA9PiB7XG4gICAgICAgICAgICAgIGlmIChleGlzdGluZy5pbmRleE9mKG5hbWUpID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX3NuYXBzaG90W25hbWVdID0gY2hhbmdlc1tuYW1lXTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVnaXN0ZXJEcmF3ZXJDbG9zZSgpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5fZHJhd2VyUmVmKSB7XG4gICAgICB0aGlzLl9kcmF3ZXJSZWYuY2xvc2VTdGFydCRcbiAgICAgICAgLnBpcGUoXG4gICAgICAgICAgdGFrZVVudGlsKHRoaXMuX2Rlc3Ryb3kkKSxcbiAgICAgICAgKVxuICAgICAgICAuc3Vic2NyaWJlKChzdWJzY3JpYmVyKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuc3VibWl0dGluZykge1xuICAgICAgICAgICAgdGhpcy5fc3RhdHVzJFxuICAgICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICBmaWx0ZXIoKHN0YXR1cykgPT4gc3RhdHVzID09PSBGb3JtU3RhdHVzLlN1Y2Nlc3MgfHwgc3RhdHVzID09PSBGb3JtU3RhdHVzLkVycm9yKSxcbiAgICAgICAgICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgIC5zdWJzY3JpYmUoKHN0YXR1cykgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChzdGF0dXMgPT09IEZvcm1TdGF0dXMuU3VjY2Vzcykge1xuICAgICAgICAgICAgICAgICAgc3Vic2NyaWJlci5uZXh0KCk7XG4gICAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgIHN1YnNjcmliZXIuZXJyb3IoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdWJzY3JpYmVyLm5leHQoKTtcbiAgICAgICAgICAgIHN1YnNjcmliZXIuY29tcGxldGUoKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3JlZ2lzdGVyQ29uZmlybURyYXdlckNsb3NlKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLl9kcmF3ZXJSZWYpIHtcbiAgICAgIHRoaXMuX2RyYXdlclJlZi5jbG9zZVN0YXJ0JFxuICAgICAgICAucGlwZShcbiAgICAgICAgICBzd2l0Y2hNYXAoKHN1YnNjcmliZXIpID0+IHtcbiAgICAgICAgICAgIHJldHVybiBpaWYoXG4gICAgICAgICAgICAgICgpID0+IHRoaXMuY29uZmlybSAmJiB0aGlzLmNvbmZpcm1EcmF3ZXIsXG4gICAgICAgICAgICAgIHRoaXMudHJpZ2dlckNvbmZpcm0oKVxuICAgICAgICAgICAgICAgIC5waXBlKFxuICAgICAgICAgICAgICAgICAgbWFwKChyZXN1bHQpID0+IGNvbmZpcm1SZXN1bHRDb250aW51ZShyZXN1bHQpKSxcbiAgICAgICAgICAgICAgICAgIHRhcCgocmVzdWx0KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLm5leHQoKTtcbiAgICAgICAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIGRlZmVyKCgpID0+IHtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLm5leHQoKTtcbiAgICAgICAgICAgICAgICBzdWJzY3JpYmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9KSxcbiAgICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgICApXG4gICAgICAgIC5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9yZWdpc3RlckNvbmZpcm1UYWJzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnRhYkdyb3VwKSB7XG4gICAgICB0aGlzLl9yZWdpc3RlckNvbmZpcm1UYWJHcm91cCh0aGlzLnRhYkdyb3VwKTtcbiAgICB9XG5cbiAgICB0aGlzLl9yZWdpc3RlckNvbmZpcm1UYWJHcm91cHModGhpcy5fdGFiR3JvdXBzLnRvQXJyYXkoKSk7XG4gICAgdGhpcy5fdGFiR3JvdXBzLmNoYW5nZXNcbiAgICAgIC5waXBlKFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuX3JlZ2lzdGVyQ29uZmlybVRhYkdyb3Vwcyh0aGlzLl90YWJHcm91cHMudG9BcnJheSgpKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVnaXN0ZXJDb25maXJtVGFiR3JvdXBzKHRhYkdyb3VwczogTWF0VGFiR3JvdXBbXSk6IHZvaWQge1xuICAgIHRhYkdyb3Vwcy5mb3JFYWNoKCh0YWJHcm91cDogTWF0VGFiR3JvdXApID0+IHtcbiAgICAgIHRoaXMuX3JlZ2lzdGVyQ29uZmlybVRhYkdyb3VwKHRhYkdyb3VwKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX3JlZ2lzdGVyQ29uZmlybVRhYkdyb3VwKHRhYkdyb3VwOiBNYXRUYWJHcm91cCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpcm1UYWJHcm91cCA9IHRhYkdyb3VwIGFzIENvbmZpcm1UYWJHcm91cDtcbiAgICBpZiAoIWNvbmZpcm1UYWJHcm91cC5fb3JpZ2luYWxIYW5kbGVDbGljaykge1xuICAgICAgY29uZmlybVRhYkdyb3VwLl9vcmlnaW5hbEhhbmRsZUNsaWNrID0gdGFiR3JvdXAuX2hhbmRsZUNsaWNrO1xuICAgICAgY29uZmlybVRhYkdyb3VwLl9oYW5kbENsaWNrJCA9IG5ldyBTdWJqZWN0PHtcbiAgICAgICAgIHRhYjogTWF0VGFiOyBcbiAgICAgICAgIHRhYkhlYWRlcjogTWF0VGFiSGVhZGVyOyBcbiAgICAgICAgIGlkeDogbnVtYmVyIFxuICAgICAgICB9PigpO1xuICAgICAgY29uZmlybVRhYkdyb3VwLl9oYW5kbGVDbGljayA9ICh0YWI6IE1hdFRhYiwgdGFiSGVhZGVyOiBNYXRUYWJIZWFkZXIsIGlkeDogbnVtYmVyKSA9PiB7XG4gICAgICAgIGlmIChjb25maXJtVGFiR3JvdXAuX2hhbmRsQ2xpY2skLm9ic2VydmVycy5sZW5ndGgpIHtcbiAgICAgICAgICBjb25maXJtVGFiR3JvdXAuX2hhbmRsQ2xpY2skLm5leHQoeyB0YWIsIHRhYkhlYWRlciwgaWR4IH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbmZpcm1UYWJHcm91cC5fb3JpZ2luYWxIYW5kbGVDbGljayh0YWIsIHRhYkhlYWRlciwgaWR4KTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG5cbiAgICBjb25maXJtVGFiR3JvdXAuX2hhbmRsQ2xpY2skXG4gICAgICAucGlwZShcbiAgICAgICAgZmlsdGVyKCgpID0+ICF0aGlzLnN1Ym1pdHRpbmcpLFxuICAgICAgICBzd2l0Y2hNYXAoKGV2ZW50KSA9PiB7XG4gICAgICAgICAgaWYodGhpcy5jb25maXJtICYmIHRoaXMuY29uZmlybVRhYnMpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRyaWdnZXJDb25maXJtKClcbiAgICAgICAgICAgICAgLnBpcGUoXG4gICAgICAgICAgICAgICAgdGFwKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICAgIGlmIChjb25maXJtUmVzdWx0Q29udGludWUocmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICBjb25maXJtVGFiR3JvdXAuc2VsZWN0ZWRJbmRleCA9IGV2ZW50LmlkeDtcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KSxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25maXJtVGFiR3JvdXAuX29yaWdpbmFsSGFuZGxlQ2xpY2soZXZlbnQudGFiLCBldmVudC50YWJIZWFkZXIsIGV2ZW50LmlkeCk7XG5cbiAgICAgICAgICByZXR1cm4gb2YobnVsbCk7XG4gICAgICAgIH0pLFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVnaXN0ZXJDb25maXJtRGlhbG9nQmFja2Ryb3BFc2NhcGUoKTogdm9pZCB7XG4gICAgaWYodGhpcy5fZGlhbG9nUmVmKSB7XG4gICAgICB0aGlzLl9kaWFsb2dCYWNrZHJvcEVzY2FwZSA9ICF0aGlzLl9kaWFsb2dSZWY/LmRpc2FibGVDbG9zZTtcblxuICAgICAgaWYgKHRoaXMuX2RpYWxvZ0JhY2tkcm9wRXNjYXBlKSB7XG4gICAgICAgIHRoaXMuX2RpYWxvZ1JlZi5iYWNrZHJvcENsaWNrKClcbiAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgIHRha2VVbnRpbCh0aGlzLl9kZXN0cm95JCksXG4gICAgICAgICAgKVxuICAgICAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAgICAgdGhpcy5fZm9ybUNsb3NlKCk7XG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgdGhpcy5fZGVzdHJveSRcbiAgICAgICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuX2RpYWxvZ1JlZi5kaXNhYmxlQ2xvc2UgPSBmYWxzZTtcbiAgICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9yZWdpc3RlckF1dG9jb21wbGV0ZSgpOiB2b2lkIHtcbiAgICB0aGlzLl9yZWdpc3RlckNvbnRyb2wgPSB0aGlzLm5nRm9ybS5mb3JtLnJlZ2lzdGVyQ29udHJvbC5iaW5kKHRoaXMubmdGb3JtLmZvcm0pO1xuXG4gICAgdGhpcy5uZ0Zvcm0uZm9ybS5yZWdpc3RlckNvbnRyb2wgPSAobmFtZTogc3RyaW5nLCBjb250cm9sOiBBYnN0cmFjdENvbnRyb2wpID0+IHtcblxuICAgICAgY29uc3QgZWw6IEVsZW1lbnQgPSB0aGlzLl9lbGVtZW50Lm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcihgaW5wdXRbbmFtZT0nJHtuYW1lfSddYCk7XG5cbiAgICAgIGlmIChlbCkge1xuICAgICAgICBpZiAoIWVsLmdldEF0dHJpYnV0ZSgnYXV0b2NvbXBsZXRlJykpIHtcbiAgICAgICAgICBlbC5zZXRBdHRyaWJ1dGUoJ2F1dG9jb21wbGV0ZScsICdub25lJyk7XG4gICAgICAgICAgZWwuc2V0QXR0cmlidXRlKCduYW1lJywgYCR7bmFtZX0tJHtndWlkKCl9YCk7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuX3JlZ2lzdGVyQ29udHJvbChuYW1lLCBjb250cm9sKTtcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSBfcmVnaXN0ZXJEaXJ0eVN1Ym1pdEJ1dHRvbigpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMubmdGb3JtKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5uZ0Zvcm0uZm9ybS52YWx1ZUNoYW5nZXNcbiAgICAgIC5waXBlKFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZURpcnR5U3VibWl0QnV0dG9ucygpO1xuICAgICAgfSk7XG5cbiAgICB0aGlzLl9idXR0b25zLmNoYW5nZXNcbiAgICAgIC5waXBlKFxuICAgICAgICB0YWtlVW50aWwodGhpcy5fZGVzdHJveSQpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZURpcnR5U3VibWl0QnV0dG9ucygpO1xuICAgICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF91cGRhdGVEaXJ0eVN1Ym1pdEJ1dHRvbnMoKTogdm9pZCB7XG4gICAgdGhpcy5fYnV0dG9uc1xuICAgICAgLmZpbHRlcigoYnV0dG9uKSA9PiBidXR0b24uc3VibWl0KVxuICAgICAgLmZvckVhY2goKHN1Ym1pdEJ1dHRvbjogRnNCdXR0b25EaXJlY3RpdmUpID0+IHtcbiAgICAgICAgaWYgKCF0aGlzLmNvbmZpcm0gfHwgIXRoaXMuZGlydHlTdWJtaXRCdXR0b24gfHwgdGhpcy5uZ0Zvcm0uZGlydHkgfHwgIXN1Ym1pdEJ1dHRvbi5kaXJ0eVN1Ym1pdCkge1xuICAgICAgICAgIHN1Ym1pdEJ1dHRvbi5lbmFibGUoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBzdWJtaXRCdXR0b24uZGlzYWJsZSgpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2Jyb2FkY2FzdFN1Ym1pdHRpbmdFdmVudHMoKTogdm9pZCB7XG4gICAgdGhpcy5fc3RhdHVzJC5uZXh0KEZvcm1TdGF0dXMuU3VibWl0dGluZyk7XG4gICAgdGhpcy5fZm9ybS5icm9hZGNhc3QoJ3N1Ym1pdCcsIHRoaXMubmdGb3JtKTtcbiAgfVxuXG4gIHByaXZhdGUgX2Jyb2FkY2FzVmFsaWRhdGluZ0V2ZW50cygpOiB2b2lkIHtcbiAgICB0aGlzLl9zdGF0dXMkLm5leHQoRm9ybVN0YXR1cy5WYWxpZGF0aW5nKTtcbiAgfVxuXG4gIHByaXZhdGUgX3NldHVwQWN0aXZlU3VibWl0QnV0dG9uKCk6IHZvaWQge1xuICAgIHRoaXMuX2FjdGl2ZVN1Ym1pdEJ1dHRvbiA9IHRoaXMuX2dldEFjdGl2ZVN1Ym1pdEJ1dHRvbigpO1xuICAgIHRoaXMuX3Jlc2V0QnV0dG9ucygpO1xuXG4gICAgaWYgKHRoaXMuX2FjdGl2ZVN1Ym1pdEJ1dHRvbikge1xuICAgICAgdGhpcy5fYWN0aXZlU3VibWl0QnV0dG9uLnByb2Nlc3MoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9kaXNhYmxlQnV0dG9ucygpOiB2b2lkIHtcbiAgICB0aGlzLl9idXR0b25zLmZvckVhY2goKGJ1dHRvbikgPT4ge1xuICAgICAgYnV0dG9uLmRpc2FibGUoKTtcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX3dhaXRVbnRpbFN0YXR1c1BlbmRpbmcoKTogT2JzZXJ2YWJsZTxzdHJpbmc+IHtcbiAgICByZXR1cm4gdGhpcy5uZ0Zvcm0uc3RhdHVzQ2hhbmdlc1xuICAgICAgLnBpcGUoXG4gICAgICAgIHN0YXJ0V2l0aCh0aGlzLm5nRm9ybS5zdGF0dXMpLFxuICAgICAgICBmaXJzdCgoc3RhdGUpID0+IHN0YXRlICE9PSAnUEVORElORycpLFxuICAgICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgX2hhbmRsZUVycm9yKGU6IFN1Ym1pdHRlZEV2ZW50KSB7XG4gICAgY29uc29sZS5sb2coJyVjIEZvcm0gU3VibWl0ICcsICdjb2xvcjogd2hpdGU7IGJhY2tncm91bmQtY29sb3I6ICNEMzNGNDknLCAnRXJyb3Igb2NjdXJlZCcpO1xuICAgIGNvbnNvbGUuZ3JvdXAoJ0Vycm9yIERldGFpbHM6Jyk7XG4gICAgY29uc29sZS5sb2coJ01lc3NhZ2U6ICcsIGUpO1xuICAgIGNvbnNvbGUubG9nKCdGb3JtUmVmOiAnLCB0aGlzKTtcblxuICAgIGlmICh0aGlzLm5nRm9ybS5pbnZhbGlkKSB7XG4gICAgICBjb25zdCBlcnJvcnMgPSBnZXRGb3JtRXJyb3JzKHRoaXMubmdGb3JtLmNvbnRyb2wsIG51bGwpO1xuICAgICAgY29uc29sZS5sb2coJ1ZhbGlkYXRpb24gRXJyb3JzOiAnLCBlcnJvcnMpO1xuICAgIH1cblxuICAgIGNvbnNvbGUuZ3JvdXBFbmQoKTtcbiAgICB0aGlzLl9jb21wbGV0ZVN1Ym1pdChmYWxzZSwgbnVsbCk7XG4gIH1cblxuICBwcml2YXRlIF9yZWdpc3RlckNhbkRlYWN0aXZhdGVHdWFyZCgpOiB2b2lkIHtcbiAgICB0aGlzLl9hY3RpdmF0ZWRSb3V0ZUNvbmZpZyA9IGdldEFjdGl2ZVJvdXRlKHRoaXMuX3JvdXRlKS5yb3V0ZUNvbmZpZztcblxuICAgIGlmICghdGhpcy5fYWN0aXZhdGVkUm91dGVDb25maWcpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9mb3JtLnJlZ2lzdGVyRm9ybURpcmVjdGl2ZSh0aGlzLl9hY3RpdmF0ZWRSb3V0ZUNvbmZpZy5jb21wb25lbnQsIHRoaXMpO1xuXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KHRoaXMuX2FjdGl2YXRlZFJvdXRlQ29uZmlnLmNhbkRlYWN0aXZhdGUpKSB7XG4gICAgICB0aGlzLl9hY3RpdmF0ZWRSb3V0ZUNvbmZpZy5jYW5EZWFjdGl2YXRlID0gW107XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuX2FjdGl2YXRlZFJvdXRlQ29uZmlnLmNhbkRlYWN0aXZhdGUuaW5kZXhPZihGb3JtRGVhY3RpdmF0ZUd1YXJkKSA9PT0gLTEpIHtcbiAgICAgIHRoaXMuX2FjdGl2YXRlZFJvdXRlQ29uZmlnLmNhbkRlYWN0aXZhdGUucHVzaChGb3JtRGVhY3RpdmF0ZUd1YXJkKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9jbGVhbnVwQ2FuRGVhY3RpdmF0ZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuX2FjdGl2YXRlZFJvdXRlQ29uZmlnKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZ3VhcmRJbmRleCA9IHRoaXMuX2FjdGl2YXRlZFJvdXRlQ29uZmlnLmNhbkRlYWN0aXZhdGUuaW5kZXhPZihGb3JtRGVhY3RpdmF0ZUd1YXJkKTtcbiAgICB0aGlzLl9hY3RpdmF0ZWRSb3V0ZUNvbmZpZy5jYW5EZWFjdGl2YXRlLnNwbGljZShndWFyZEluZGV4LCAxKTtcblxuICAgIHRoaXMuX2Zvcm0ucmVtb3ZlRm9ybURpcmVjdGl2ZSh0aGlzLl9hY3RpdmF0ZWRSb3V0ZUNvbmZpZy5jb21wb25lbnQpO1xuICB9XG5cbn1cbiJdfQ==
|