@energycap/components 0.44.8 → 0.44.9-Angular19Upgrade.20260217-1620
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/fesm2022/energycap-components.mjs +379 -354
- package/fesm2022/energycap-components.mjs.map +1 -1
- package/lib/controls/button/copy-button-base.directive.d.ts +1 -1
- package/lib/controls/date-input/date-input.component.d.ts +1 -1
- package/lib/controls/form-control-base.d.ts +1 -1
- package/lib/core/date-time-helper.d.ts +2 -2
- package/lib/display/hierarchy/hierarchy-base.d.ts +1 -1
- package/lib/display/hierarchy/hierarchy-mocks.spec.d.ts +1 -1
- package/lib/display/resizable/resizable-base.d.ts +1 -1
- package/lib/shared/display/pipes/date-display.pipe.d.ts +1 -1
- package/lib/shared/page/page-base/page-base.component.d.ts +1 -1
- package/lib/shared/testing/public-mocks.spec.d.ts +1 -1
- package/lib/shared/wizard/wizard-base/wizard-base.component.d.ts +1 -1
- package/package.json +1 -3
- package/schematics/utilities/typescript.js +3 -4
- package/schematics/utilities/typescript.js.map +1 -1
- package/schematics/utilities/workspace.d.ts +0 -8
- package/schematics/utilities/workspace.js +48 -71
- package/schematics/utilities/workspace.js.map +1 -1
- package/esm2022/energycap-components.mjs +0 -5
- package/esm2022/lib/components.module.mjs +0 -425
- package/esm2022/lib/controls/banner/banner.component.mjs +0 -112
- package/esm2022/lib/controls/button/button.component.mjs +0 -114
- package/esm2022/lib/controls/button/copy-button-base.directive.mjs +0 -67
- package/esm2022/lib/controls/button/copy-button.directive.mjs +0 -28
- package/esm2022/lib/controls/button/copy-table-button.directive.mjs +0 -43
- package/esm2022/lib/controls/calendar/calendar-item.component.mjs +0 -91
- package/esm2022/lib/controls/calendar/calendar.component.mjs +0 -251
- package/esm2022/lib/controls/calendar/calendar.types.mjs +0 -2
- package/esm2022/lib/controls/checkbox/checkbox.component.mjs +0 -140
- package/esm2022/lib/controls/collapsible-toggle/collapsible-toggle.component.mjs +0 -38
- package/esm2022/lib/controls/combobox/combobox.component.mjs +0 -879
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/date-input-selection-strategy-base.mjs +0 -57
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/day-selection-strategy.mjs +0 -62
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/last-28-days-selection-strategy.mjs +0 -100
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/last-7-days-selection-strategy.mjs +0 -101
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/month-selection-strategy.mjs +0 -76
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/quarter-selection-strategy.mjs +0 -79
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/range-selection-strategy.mjs +0 -210
- package/esm2022/lib/controls/date-input/date-input-selection-strategies/year-selection-strategy.mjs +0 -81
- package/esm2022/lib/controls/date-input/date-input.component.mjs +0 -466
- package/esm2022/lib/controls/date-input/date-input.types.mjs +0 -44
- package/esm2022/lib/controls/dropdown/dropdown.component.mjs +0 -243
- package/esm2022/lib/controls/file-upload/file-upload.component.mjs +0 -261
- package/esm2022/lib/controls/form-control/form-control.component.mjs +0 -110
- package/esm2022/lib/controls/form-control-base.mjs +0 -151
- package/esm2022/lib/controls/form-control-label/form-control-label.component.mjs +0 -136
- package/esm2022/lib/controls/form-group/form-group.component.mjs +0 -261
- package/esm2022/lib/controls/help-popover/help-popover.component.mjs +0 -31
- package/esm2022/lib/controls/item-picker/item-picker.component.mjs +0 -329
- package/esm2022/lib/controls/link-button/link-button.component.mjs +0 -11
- package/esm2022/lib/controls/menu/menu.component.mjs +0 -485
- package/esm2022/lib/controls/navigation/link-item.mjs +0 -2
- package/esm2022/lib/controls/navigation/nav-group.mjs +0 -39
- package/esm2022/lib/controls/navigation/nav-item-active.directive.mjs +0 -92
- package/esm2022/lib/controls/navigation/nav-item.mjs +0 -2
- package/esm2022/lib/controls/numericbox/numericbox.component.mjs +0 -372
- package/esm2022/lib/controls/popover/popover.component.mjs +0 -117
- package/esm2022/lib/controls/radio-button/radio-button-option.mjs +0 -3
- package/esm2022/lib/controls/radio-button/radio-button.component.mjs +0 -82
- package/esm2022/lib/controls/select/select.component.mjs +0 -88
- package/esm2022/lib/controls/tabs/tabs.component.mjs +0 -47
- package/esm2022/lib/controls/textbox/textbox.component.mjs +0 -155
- package/esm2022/lib/core/cache.service.mjs +0 -105
- package/esm2022/lib/core/custom-validators.mjs +0 -29
- package/esm2022/lib/core/date-time-helper.mjs +0 -228
- package/esm2022/lib/core/error.service.mjs +0 -61
- package/esm2022/lib/core/router-helper.service.mjs +0 -111
- package/esm2022/lib/core/scroll.service.mjs +0 -89
- package/esm2022/lib/core/telemetry-tracker.service.mjs +0 -16
- package/esm2022/lib/core/telemetry.service.mjs +0 -38
- package/esm2022/lib/core/validation-message.service.mjs +0 -185
- package/esm2022/lib/core/validation-patterns.mjs +0 -31
- package/esm2022/lib/core/window.service.mjs +0 -186
- package/esm2022/lib/display/app-bar/app-bar.component.mjs +0 -49
- package/esm2022/lib/display/avatar/avatar.component.mjs +0 -67
- package/esm2022/lib/display/avatar/avatar.service.mjs +0 -64
- package/esm2022/lib/display/confirm/confirm.component.mjs +0 -168
- package/esm2022/lib/display/dialog/dialog-content.mjs +0 -2
- package/esm2022/lib/display/dialog/dialog-group/dialog-group.component.mjs +0 -63
- package/esm2022/lib/display/dialog/dialog-types.mjs +0 -77
- package/esm2022/lib/display/dialog/dialog.component.mjs +0 -287
- package/esm2022/lib/display/dialog/dialog.service.mjs +0 -71
- package/esm2022/lib/display/help/help-types.mjs +0 -2
- package/esm2022/lib/display/hierarchy/hierarchy-base.mjs +0 -111
- package/esm2022/lib/display/hierarchy/hierarchy-mocks.spec.mjs +0 -54
- package/esm2022/lib/display/hierarchy/hierarchy-tree/hierarchy-tree.component.mjs +0 -65
- package/esm2022/lib/display/item-display/item-display.component.mjs +0 -83
- package/esm2022/lib/display/json-display/json-display.component.mjs +0 -47
- package/esm2022/lib/display/resizable/resizable-base.mjs +0 -120
- package/esm2022/lib/display/resizable/resizable.component.mjs +0 -57
- package/esm2022/lib/display/spinner/spinner.component.mjs +0 -12
- package/esm2022/lib/display/splash/splash.component.mjs +0 -61
- package/esm2022/lib/display/splash/splash.service.mjs +0 -35
- package/esm2022/lib/display/table/resizable-column.component.mjs +0 -20
- package/esm2022/lib/display/table/resizable-table.directive.mjs +0 -227
- package/esm2022/lib/display/table/searchable-table.component.mjs +0 -344
- package/esm2022/lib/display/table/table-detail-row.component.mjs +0 -28
- package/esm2022/lib/display/table/table-locked-column.component.mjs +0 -58
- package/esm2022/lib/display/table/table-master-header-row.component.mjs +0 -14
- package/esm2022/lib/display/table/table-master-row.component.mjs +0 -163
- package/esm2022/lib/display/table/table-pagination.component.mjs +0 -155
- package/esm2022/lib/display/table/table-selectable-row.component.mjs +0 -235
- package/esm2022/lib/display/table/table.component.mjs +0 -257
- package/esm2022/lib/display/tags/tag.mjs +0 -18
- package/esm2022/lib/display/tags/tags.component.mjs +0 -82
- package/esm2022/lib/display/toast/toast/toast.component.mjs +0 -77
- package/esm2022/lib/display/toast/toast-types.mjs +0 -8
- package/esm2022/lib/display/toast/toast.service.mjs +0 -35
- package/esm2022/lib/display/toast/toaster/toaster.component.mjs +0 -114
- package/esm2022/lib/display/tooltip/tooltip.component.mjs +0 -28
- package/esm2022/lib/display/tooltip/tooltip.service.mjs +0 -78
- package/esm2022/lib/display/tooltip-directive/tooltip.directive.mjs +0 -173
- package/esm2022/lib/display/tree/tree.component.mjs +0 -139
- package/esm2022/lib/display/view-overlay/view-overlay.component.mjs +0 -58
- package/esm2022/lib/shared/directives/click-area-for/click-area-for.directive.mjs +0 -32
- package/esm2022/lib/shared/directives/if-viewport-width/if-viewport-width.directive.mjs +0 -111
- package/esm2022/lib/shared/directives/keyboard-nav-container/keyboard-nav-container.directive.mjs +0 -103
- package/esm2022/lib/shared/directives/popup/popup-container.directive.mjs +0 -166
- package/esm2022/lib/shared/display/pipes/date-display-2.pipe.mjs +0 -39
- package/esm2022/lib/shared/display/pipes/date-display.pipe.mjs +0 -51
- package/esm2022/lib/shared/display/pipes/highlight-text.pipe.mjs +0 -30
- package/esm2022/lib/shared/display/pipes/relative-date.pipe.mjs +0 -62
- package/esm2022/lib/shared/display/pipes/row-count.pipe.mjs +0 -48
- package/esm2022/lib/shared/display/pipes/time-display.pipe.mjs +0 -41
- package/esm2022/lib/shared/display.mjs +0 -6
- package/esm2022/lib/shared/form-group.helper.mjs +0 -67
- package/esm2022/lib/shared/json-helper.mjs +0 -19
- package/esm2022/lib/shared/lodash-helper.mjs +0 -52
- package/esm2022/lib/shared/page/page-base/page-base.component.mjs +0 -387
- package/esm2022/lib/shared/page/page-statuses.mjs +0 -23
- package/esm2022/lib/shared/page/page-title/page-title.component.mjs +0 -23
- package/esm2022/lib/shared/page/page-view/page-view.component.mjs +0 -147
- package/esm2022/lib/shared/testing/copy-button-base-test-injector-factory.spec.mjs +0 -17
- package/esm2022/lib/shared/testing/hierarchy-base-test-injector-factory.spec.mjs +0 -17
- package/esm2022/lib/shared/testing/page-base-component-test-helper.spec.mjs +0 -38
- package/esm2022/lib/shared/testing/page-base-component-test-injector-factory.spec.mjs +0 -98
- package/esm2022/lib/shared/testing/public-mocks.spec.mjs +0 -148
- package/esm2022/lib/shared/testing/spy-factory.spec.mjs +0 -40
- package/esm2022/lib/shared/testing/translation-mocks.spec.mjs +0 -57
- package/esm2022/lib/shared/user-preference.service.mjs +0 -17
- package/esm2022/lib/shared/wizard/wizard-base/wizard-base.component.mjs +0 -246
- package/esm2022/lib/shared/wizard/wizard-buttons/wizard-buttons.component.mjs +0 -68
- package/esm2022/lib/shared/wizard/wizard-progress/wizard-progress.component.mjs +0 -18
- package/esm2022/public-api.mjs +0 -115
|
@@ -1,466 +0,0 @@
|
|
|
1
|
-
import { Component, HostBinding, Input, ViewChild } from '@angular/core';
|
|
2
|
-
import { FormControl, FormGroup } from '@angular/forms';
|
|
3
|
-
import moment from 'moment';
|
|
4
|
-
import { lastValueFrom } from 'rxjs';
|
|
5
|
-
import { debounceTime, distinctUntilChanged, takeUntil } from 'rxjs/operators';
|
|
6
|
-
import { DateTimeHelper } from '../../core/date-time-helper';
|
|
7
|
-
import { FormControlBase } from '../form-control-base';
|
|
8
|
-
import { DateInput } from './date-input.types';
|
|
9
|
-
import * as i0 from "@angular/core";
|
|
10
|
-
import * as i1 from "../../core/validation-message.service";
|
|
11
|
-
import * as i2 from "../../shared/form-group.helper";
|
|
12
|
-
import * as i3 from "../../shared/user-preference.service";
|
|
13
|
-
import * as i4 from "@angular/cdk/overlay";
|
|
14
|
-
import * as i5 from "./date-input.types";
|
|
15
|
-
import * as i6 from "@angular/common";
|
|
16
|
-
import * as i7 from "@angular/forms";
|
|
17
|
-
import * as i8 from "../button/button.component";
|
|
18
|
-
import * as i9 from "../form-control/form-control.component";
|
|
19
|
-
import * as i10 from "../help-popover/help-popover.component";
|
|
20
|
-
import * as i11 from "../calendar/calendar.component";
|
|
21
|
-
import * as i12 from "../../shared/directives/keyboard-nav-container/keyboard-nav-container.directive";
|
|
22
|
-
import * as i13 from "@ngx-translate/core";
|
|
23
|
-
export class DateInputComponent extends FormControlBase {
|
|
24
|
-
constructor(validationMessageService, formGroupHelper, userPreferenceService, el, overlayService, selectionStrategies) {
|
|
25
|
-
super(validationMessageService, formGroupHelper);
|
|
26
|
-
this.validationMessageService = validationMessageService;
|
|
27
|
-
this.formGroupHelper = formGroupHelper;
|
|
28
|
-
this.userPreferenceService = userPreferenceService;
|
|
29
|
-
this.el = el;
|
|
30
|
-
this.overlayService = overlayService;
|
|
31
|
-
this.selectionStrategies = selectionStrategies;
|
|
32
|
-
this.id = '';
|
|
33
|
-
/** The form control provided by the hosting form. */
|
|
34
|
-
// @Input() public formModel: DateInput.FormModel = new FormControl(null);
|
|
35
|
-
// Copilot keeps claiming this formModel is being overwritten in the constructor.
|
|
36
|
-
this.formModel = new FormControl(null);
|
|
37
|
-
this.minDate = DateTimeHelper.minDatePickerDate;
|
|
38
|
-
this.maxDate = DateTimeHelper.maxDatePickerDate;
|
|
39
|
-
/** The initial selection mode for the calendar. Defaults to day if not provided */
|
|
40
|
-
this.selectionMode = 'day';
|
|
41
|
-
/** The available selection modes for the calendar. Defaults to only the initial selection mode if not provided. */
|
|
42
|
-
this.selectionModeOptions = ['day'];
|
|
43
|
-
/** Enables the next/previous selection buttons. */
|
|
44
|
-
this.enableSteppers = false;
|
|
45
|
-
/** The form group for the internal textboxes. Textbox2 is only used for ranges. */
|
|
46
|
-
this.textboxGroup = new FormGroup({
|
|
47
|
-
textbox: new FormControl(null),
|
|
48
|
-
textbox2: new FormControl(null)
|
|
49
|
-
});
|
|
50
|
-
/**
|
|
51
|
-
* The current calendar selection.
|
|
52
|
-
* Updated when the user clicks on a calendar item or when the date entered into the textbox is parsed.
|
|
53
|
-
*/
|
|
54
|
-
this.calendarSelection = null;
|
|
55
|
-
/** Controls whether the calendar overlay is open or not. */
|
|
56
|
-
this.isCalendarOpen = false;
|
|
57
|
-
/** Placeholder for the textbox. Updated to reflect the user's date display preference. */
|
|
58
|
-
this.placeholder = 'MM/DD/YYYY';
|
|
59
|
-
/** Overlay scroll strategy for the calendar overlay. Closes the calendar on scroll. */
|
|
60
|
-
this.overlayScrollStrategy = this.overlayService.scrollStrategies.close();
|
|
61
|
-
this.primaryCalendarView = { mode: 'day', date: new Date() };
|
|
62
|
-
this.secondaryCalendarView = { mode: 'day', date: new Date() };
|
|
63
|
-
this.primaryCalendarMaxDate = DateTimeHelper.maxDatePickerDate;
|
|
64
|
-
this.secondaryCalendarMinDate = DateTimeHelper.minDatePickerDate;
|
|
65
|
-
this.disableSteppers = false;
|
|
66
|
-
/**
|
|
67
|
-
* Date parsing formats for user-entered dates. Defaults to month-first formats, but is updated in onInit
|
|
68
|
-
* to use the user's preferred date format.
|
|
69
|
-
*/
|
|
70
|
-
this.parseFormats = DateTimeHelper.getMomentParseFormats();
|
|
71
|
-
}
|
|
72
|
-
ngOnChanges(changes) {
|
|
73
|
-
if (changes.selectionMode && !changes.selectionMode.isFirstChange()) {
|
|
74
|
-
this.onSelectionModeChange(this.selectionMode);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
ngOnInit() {
|
|
78
|
-
// Setup
|
|
79
|
-
super.ngOnInit();
|
|
80
|
-
this.setDateFormats();
|
|
81
|
-
this.setSelectionMode(this.selectionMode);
|
|
82
|
-
// Subscriptions
|
|
83
|
-
this.onFormModelStatusChanges();
|
|
84
|
-
this.onFormModelValueChanges();
|
|
85
|
-
this.onTextboxValueChanges();
|
|
86
|
-
// Sync the initial disabled status and value of the textbox
|
|
87
|
-
this.syncTextboxControlDisabledStatus(this.formModel.status);
|
|
88
|
-
const initialDisplayValue = this.selectionStrategy.formatSelection(this.formModel.value);
|
|
89
|
-
this.textboxGroup.patchValue(initialDisplayValue, { emitEvent: false });
|
|
90
|
-
// Update the calendar selection and view based on the initial form model value
|
|
91
|
-
this.calendarSelection = this.formModel.value;
|
|
92
|
-
this.updateCalendars(this.calendarSelection);
|
|
93
|
-
this.updateSteppers(this.calendarSelection);
|
|
94
|
-
}
|
|
95
|
-
closeCalendarAndFocusInput() {
|
|
96
|
-
this.isCalendarOpen = false;
|
|
97
|
-
this.focusInput();
|
|
98
|
-
}
|
|
99
|
-
/** Focuses the input whenever the calendar is shift-tabbed out of. */
|
|
100
|
-
onCalendarFocusOutStart() {
|
|
101
|
-
this.focusInput();
|
|
102
|
-
}
|
|
103
|
-
/** Closes the calendar and focuses the input whenever the calendar is tabbed out of. */
|
|
104
|
-
onCalendarFocusOutEnd() {
|
|
105
|
-
this.closeCalendarAndFocusInput();
|
|
106
|
-
}
|
|
107
|
-
/** Closes the calendar if the user clicks outside of the calendar and date input. */
|
|
108
|
-
onOverlayOutsideClick(event) {
|
|
109
|
-
// Do not close the calendar if the click was within the date input or action button
|
|
110
|
-
const rect = this.el.nativeElement.getBoundingClientRect();
|
|
111
|
-
const clickedOutsideControl = event.clientY < rect.top ||
|
|
112
|
-
event.clientY > rect.bottom ||
|
|
113
|
-
event.clientX < rect.left ||
|
|
114
|
-
event.clientX > rect.right;
|
|
115
|
-
// It's possible that the user hit enter on the action button instead of clicking with the mouse.
|
|
116
|
-
// In this case the "click" event will be outside of the component because the clientx and y are 0,
|
|
117
|
-
// but we don't want to close in this case because button clicks trigger calendar open/close separately.
|
|
118
|
-
const targetId = event.target.id;
|
|
119
|
-
const isActionClick = targetId === `${this.id}_action` || targetId === `${this.id}_control2_action`;
|
|
120
|
-
if (!isActionClick && clickedOutsideControl) {
|
|
121
|
-
this.isCalendarOpen = false;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
/** If the user tabs out of the form control's action button and the calendar is open, focus the first item in the calendar overlay */
|
|
125
|
-
onControlsFocusOutEnd() {
|
|
126
|
-
if (this.isCalendarOpen) {
|
|
127
|
-
this.calendar?.focus();
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
onTextboxBlur() {
|
|
131
|
-
// We want to prevent the fixed date range modes from re-autocompleting the first textbox when it is explicitly cleared.
|
|
132
|
-
const previousValue = DateInput.isSelectionRange(this.formModel.value) ? this.formModel.value.start : this.formModel.value;
|
|
133
|
-
const currentValue = this.textboxGroup.value.textbox;
|
|
134
|
-
const cleared = !!previousValue && !currentValue;
|
|
135
|
-
const options = { preventAutoComplete: cleared };
|
|
136
|
-
// Parse the textbox values into a selection and update the form model
|
|
137
|
-
const parsedSelection = this.selectionStrategy.parseTextboxValues(this.textboxGroup.value, this.parseFormats, options);
|
|
138
|
-
this.updateFormModel(parsedSelection);
|
|
139
|
-
}
|
|
140
|
-
onTextbox2Blur() {
|
|
141
|
-
// We want to prevent the fixed date range modes from re-autocompleting the second textbox when it is explicitly cleared.
|
|
142
|
-
const previousValue = DateInput.isSelectionRange(this.formModel.value) ? this.formModel.value.end : null;
|
|
143
|
-
const currentValue = this.textboxGroup.value.textbox2;
|
|
144
|
-
const cleared = !!previousValue && !currentValue;
|
|
145
|
-
const options = { parseFromEnd: true, preventAutoComplete: cleared };
|
|
146
|
-
// Parse the textbox values into a selection and update the form model,
|
|
147
|
-
// For the second box we're keying the parse from the end date in the selection.
|
|
148
|
-
const parsedSelection = this.selectionStrategy.parseTextboxValues(this.textboxGroup.value, this.parseFormats, options);
|
|
149
|
-
this.updateFormModel(parsedSelection);
|
|
150
|
-
}
|
|
151
|
-
onSelectionModeChange(mode) {
|
|
152
|
-
this.setSelectionMode(mode);
|
|
153
|
-
const newSelection = this.selectionStrategy.getNewSelectionFromExisting(this.calendarSelection);
|
|
154
|
-
this.updateFormModel(newSelection);
|
|
155
|
-
// On selection mode change, we want to force the calendars to show the right view mode for the new selection.
|
|
156
|
-
// This prevents the user from seeing a view mode that doesn't make sense for the new selection,
|
|
157
|
-
// Like when swiching from year mode to last 7 days mode.
|
|
158
|
-
this.primaryCalendarView = { mode: this.selectionStrategy.selectionViewMode, date: this.primaryCalendarView.date };
|
|
159
|
-
this.secondaryCalendarView = { mode: this.selectionStrategy.selectionViewMode, date: this.secondaryCalendarView.date };
|
|
160
|
-
this.updateCalendarMinMaxDates();
|
|
161
|
-
}
|
|
162
|
-
onCalendarDateSelected(date) {
|
|
163
|
-
const newSelection = this.selectionStrategy.getSelectionFromDate(date, this.calendarSelection);
|
|
164
|
-
const displayValue = this.selectionStrategy.formatSelection(newSelection);
|
|
165
|
-
// Don't emit events when patching values here. We don't want to trigger the calendar updates since the calendar is already
|
|
166
|
-
// showing the selected date. We also don't want to trigger the textbox parsing logic since the date was selected from the calendar.
|
|
167
|
-
this.textboxGroup.patchValue(displayValue, { emitEvent: false });
|
|
168
|
-
this.updateFormModel(newSelection);
|
|
169
|
-
this.calendarSelection = newSelection;
|
|
170
|
-
// Close the calendar if the selection mode is not a range mode where either the start or the end date can be changed.
|
|
171
|
-
if (!this.selectionStrategy.showSecondaryTextbox) {
|
|
172
|
-
this.closeCalendarAndFocusInput();
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
onPrimaryCalendarViewChange(view) {
|
|
176
|
-
this.primaryCalendarView = view;
|
|
177
|
-
this.updateCalendarMinMaxDates();
|
|
178
|
-
}
|
|
179
|
-
onSecondaryCalendarViewChange(view) {
|
|
180
|
-
this.secondaryCalendarView = view;
|
|
181
|
-
this.updateCalendarMinMaxDates();
|
|
182
|
-
}
|
|
183
|
-
/** Shifts the calendar views to display today. Does not update the calendar selection. */
|
|
184
|
-
goToToday() {
|
|
185
|
-
// If both calendars are visible, show today in the secondary calendar and the month before in the primary calendar.
|
|
186
|
-
if (this.selectionStrategy.showSecondaryCalendar) {
|
|
187
|
-
this.primaryCalendarView = { mode: 'day', date: moment().subtract(1, 'month').toDate() };
|
|
188
|
-
this.secondaryCalendarView = { mode: 'day', date: new Date() };
|
|
189
|
-
// If we're in a single date mode, show today in the primary calendar.
|
|
190
|
-
}
|
|
191
|
-
else {
|
|
192
|
-
this.primaryCalendarView = { mode: 'day', date: new Date() };
|
|
193
|
-
}
|
|
194
|
-
this.updateCalendarMinMaxDates();
|
|
195
|
-
}
|
|
196
|
-
goToQuickSelectDate() {
|
|
197
|
-
if (this.quickSelectDate) {
|
|
198
|
-
const newSelection = this.selectionStrategy.getSelectionForQuickSelectDate(this.quickSelectDate, this.calendarSelection);
|
|
199
|
-
this.updateFormModel(newSelection);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
nextSelection() {
|
|
203
|
-
const newSelection = this.selectionStrategy.getNextSelection(this.calendarSelection);
|
|
204
|
-
this.updateFormModel(newSelection);
|
|
205
|
-
}
|
|
206
|
-
previousSelection() {
|
|
207
|
-
const newSelection = this.selectionStrategy.getPreviousSelection(this.calendarSelection);
|
|
208
|
-
this.updateFormModel(newSelection);
|
|
209
|
-
}
|
|
210
|
-
updateFormModel(value) {
|
|
211
|
-
this.formModel.patchValue(value);
|
|
212
|
-
// Validate the textboxes and sync the form errors
|
|
213
|
-
// We do this after patching the form model because the form model patch will trigger
|
|
214
|
-
// the date formatting logic and overwrite any errors on the controls from before.
|
|
215
|
-
this.validateTextboxes();
|
|
216
|
-
this.syncFormErrors();
|
|
217
|
-
}
|
|
218
|
-
onFormModelStatusChanges() {
|
|
219
|
-
// Keep the textboxControl disabled status in sync with the formModel
|
|
220
|
-
this.formModel.statusChanges.pipe(distinctUntilChanged(), takeUntil(this.componentDestroyed)).subscribe(status => {
|
|
221
|
-
this.syncTextboxControlDisabledStatus(status);
|
|
222
|
-
if (this.isCalendarOpen) {
|
|
223
|
-
// As validation messages appear/disappear, the date input may have shifted up or down on the page.
|
|
224
|
-
// Update the overlay position to ensure it's still aligned with the textbox and not blocking it.
|
|
225
|
-
// Settimeout is needed to ensure the overlay is being updated after the message is rendered.
|
|
226
|
-
setTimeout(() => {
|
|
227
|
-
this.overlay?.overlayRef?.updatePosition();
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
});
|
|
231
|
-
}
|
|
232
|
-
onFormModelValueChanges() {
|
|
233
|
-
// Update the calendar selection textbox value with a formatted date when the form model changes.
|
|
234
|
-
// This is triggered by the user selecting a date from the calendar or when the textbox is blurred.
|
|
235
|
-
this.formModel.valueChanges.pipe(takeUntil(this.componentDestroyed)).subscribe(value => {
|
|
236
|
-
const displayValue = this.selectionStrategy.formatSelection(value);
|
|
237
|
-
// Don't emit an event when setting the textbox value to avoid circular updates between the textbox and form model.
|
|
238
|
-
this.textboxGroup.patchValue(displayValue, { emitEvent: false });
|
|
239
|
-
this.updateCalendars(value);
|
|
240
|
-
this.updateSteppers(value);
|
|
241
|
-
});
|
|
242
|
-
}
|
|
243
|
-
onTextboxValueChanges() {
|
|
244
|
-
// Update the calendar selection when the textbox value changes to update the calendar.
|
|
245
|
-
// We don't patch the formModel here because we don't want to trigger the
|
|
246
|
-
// date formatting logic and overwrite the user's input.
|
|
247
|
-
// We'll do that when the user blurs out of the textbox. See onTextboxBlur()
|
|
248
|
-
this.textboxGroup.controls.textbox.valueChanges.pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this.componentDestroyed)).subscribe(() => {
|
|
249
|
-
const options = { shiftToCurrentYearIfBelow: this.minDate };
|
|
250
|
-
const newSelection = this.selectionStrategy.parseTextboxValues(this.textboxGroup.value, this.parseFormats, options);
|
|
251
|
-
// Calendar selection will be null if the dates are invalid. Don't update the calendars in this case.
|
|
252
|
-
if (newSelection) {
|
|
253
|
-
this.calendarSelection = newSelection;
|
|
254
|
-
this.updatePrimaryCalendar(this.calendarSelection, this.selectionStrategy.showSecondaryCalendar);
|
|
255
|
-
this.updateCalendarMinMaxDates();
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
// The second textbox is only used in last7Days, last28Days, and range modes.
|
|
259
|
-
this.textboxGroup.controls.textbox2.valueChanges.pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this.componentDestroyed)).subscribe(() => {
|
|
260
|
-
const options = { shiftToCurrentYearIfBelow: this.minDate, parseFromEnd: true };
|
|
261
|
-
const newSelection = this.selectionStrategy.parseTextboxValues(this.textboxGroup.value, this.parseFormats, options);
|
|
262
|
-
// Calendar selection will be null if the dates are invalid. Don't update the calendars in this case.
|
|
263
|
-
if (newSelection) {
|
|
264
|
-
this.calendarSelection = newSelection;
|
|
265
|
-
// The secondary calendar is only shown in range mode. Update the primary calendar if we're not in range mode.
|
|
266
|
-
if (this.selectionStrategy.showSecondaryCalendar) {
|
|
267
|
-
this.updateSecondaryCalendar(this.calendarSelection, true);
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
270
|
-
this.updatePrimaryCalendar(this.calendarSelection);
|
|
271
|
-
}
|
|
272
|
-
this.updateCalendarMinMaxDates();
|
|
273
|
-
}
|
|
274
|
-
});
|
|
275
|
-
}
|
|
276
|
-
syncTextboxControlDisabledStatus(status) {
|
|
277
|
-
// The textbox should only be disabled if the form model is disabled.
|
|
278
|
-
// All other statuses are considered enabled.
|
|
279
|
-
if (status === 'DISABLED' && this.textboxGroup.enabled) {
|
|
280
|
-
this.textboxGroup.disable();
|
|
281
|
-
}
|
|
282
|
-
else if (status !== 'DISABLED' && this.textboxGroup.disabled) {
|
|
283
|
-
this.textboxGroup.enable();
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
;
|
|
287
|
-
syncFormErrors() {
|
|
288
|
-
// Start with the existing form model errors
|
|
289
|
-
let errors = this.formModel.errors;
|
|
290
|
-
// Add the errors from the textboxes if they exist
|
|
291
|
-
if (this.textboxGroup.controls.textbox.errors) {
|
|
292
|
-
errors = { ...errors, ...this.textboxGroup.controls.textbox.errors };
|
|
293
|
-
}
|
|
294
|
-
if (this.textboxGroup.controls.textbox2.errors) {
|
|
295
|
-
errors = { ...errors, ...this.textboxGroup.controls.textbox2.errors };
|
|
296
|
-
}
|
|
297
|
-
// Update the form model's errors with the combined errors
|
|
298
|
-
this.formModel.setErrors(errors);
|
|
299
|
-
// Update the form model's touched and dirty status based on the textbox's status.
|
|
300
|
-
// Since the user interacts with a control that is internal to this component, the
|
|
301
|
-
// form model's status won't be updated automatically.
|
|
302
|
-
if (this.textboxGroup.touched && !this.formModel.touched) {
|
|
303
|
-
this.formModel.markAsTouched();
|
|
304
|
-
}
|
|
305
|
-
if (this.textboxGroup.dirty && !this.formModel.dirty) {
|
|
306
|
-
this.formModel.markAsDirty();
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
/**
|
|
310
|
-
* Updates the date parsing formats and placeholder based on the user's display preference.
|
|
311
|
-
* NOTE: This is async because we're retrieving the user's preferences. We're not awaiting the result
|
|
312
|
-
* because the only logic that depends on this is the text box date parsing logic and placeholder.
|
|
313
|
-
* Our forms should always be behind a pending overlay, so the user won't be able to interact with the
|
|
314
|
-
* form until the user is loaded anyway.
|
|
315
|
-
*/
|
|
316
|
-
async setDateFormats() {
|
|
317
|
-
const { preference } = await lastValueFrom(this.userPreferenceService.getPreferences());
|
|
318
|
-
const dateFormat = preference?.dateFormat;
|
|
319
|
-
this.placeholder = dateFormat ?? this.placeholder;
|
|
320
|
-
this.parseFormats = DateTimeHelper.getMomentParseFormats(dateFormat);
|
|
321
|
-
}
|
|
322
|
-
/** Focuses the date input. */
|
|
323
|
-
focusInput() {
|
|
324
|
-
this.controls?.focus();
|
|
325
|
-
}
|
|
326
|
-
setSelectionMode(mode) {
|
|
327
|
-
this.selectionMode = mode;
|
|
328
|
-
this.selectionStrategy = this.selectionStrategies[mode];
|
|
329
|
-
}
|
|
330
|
-
/**
|
|
331
|
-
* Sets the max date for the primary calendar and the min date for the secondary calendar based
|
|
332
|
-
* on the current views in each. This prevents the user from moving the calendars out of order.
|
|
333
|
-
*/
|
|
334
|
-
updateCalendarMinMaxDates() {
|
|
335
|
-
// Only update the min/max dates when the view mode is 'day'.
|
|
336
|
-
// When a calendar is in a month or year view mode, the view dates at the beginning of the year.
|
|
337
|
-
// This would cause the dates in the other calendar to be unselectable if we were to
|
|
338
|
-
// update the min/max dates in these cases.
|
|
339
|
-
if (this.primaryCalendarView?.mode === 'day') {
|
|
340
|
-
this.secondaryCalendarMinDate = moment(this.primaryCalendarView?.date).add(1, 'month').startOf('month').toDate();
|
|
341
|
-
}
|
|
342
|
-
if (this.secondaryCalendarView?.mode === 'day') {
|
|
343
|
-
this.primaryCalendarMaxDate = moment(this.secondaryCalendarView?.date).subtract(1, 'month').endOf('month').toDate();
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
updateCalendars(selection) {
|
|
347
|
-
this.calendarSelection = selection;
|
|
348
|
-
this.updatePrimaryCalendar(selection);
|
|
349
|
-
// Only shift the primary calendar if we're showing the secondary calendar
|
|
350
|
-
this.updateSecondaryCalendar(selection, this.selectionStrategy.showSecondaryCalendar);
|
|
351
|
-
this.updateCalendarMinMaxDates();
|
|
352
|
-
}
|
|
353
|
-
updatePrimaryCalendar(selection, shiftSecondary = false) {
|
|
354
|
-
this.primaryCalendarView = this.selectionStrategy.getPrimaryCalendarView(selection, this.minDate, this.maxDate, this.primaryCalendarView);
|
|
355
|
-
// When entering a date into the first textbox, we really only want to update the primary calendar.
|
|
356
|
-
// However, it's possible that the new date is after the secondary calendar's date. In this case,
|
|
357
|
-
// We want to shift the secondary calendar so the calendars stay in order.
|
|
358
|
-
if (shiftSecondary && this.secondaryCalendarView) {
|
|
359
|
-
if (moment(this.primaryCalendarView.date).isSameOrAfter(this.secondaryCalendarView.date, 'month')) {
|
|
360
|
-
let newSecondaryDate = moment(this.primaryCalendarView.date).add(1, 'month').toDate();
|
|
361
|
-
this.secondaryCalendarView = { mode: this.selectionStrategy.selectionViewMode, date: newSecondaryDate };
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
}
|
|
365
|
-
updateSecondaryCalendar(selection, shiftPrimary = false) {
|
|
366
|
-
this.secondaryCalendarView = this.selectionStrategy.getSecondaryCalendarView(selection, this.minDate, this.maxDate, this.secondaryCalendarView);
|
|
367
|
-
// When entering a date into the second textbox, we really only want to update the secondary calendar.
|
|
368
|
-
// However, it's possible that the new date is before the primary calendar's date. In this case,
|
|
369
|
-
// We want to shift the primary calendar so the calendars stay in order.
|
|
370
|
-
if (shiftPrimary && this.primaryCalendarView) {
|
|
371
|
-
if (moment(this.primaryCalendarView.date).isSameOrAfter(this.secondaryCalendarView.date, 'month')) {
|
|
372
|
-
let newPrimaryDate = moment(this.secondaryCalendarView.date).subtract(1, 'month').toDate();
|
|
373
|
-
this.primaryCalendarView = { mode: this.selectionStrategy.selectionViewMode, date: newPrimaryDate };
|
|
374
|
-
}
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
updateSteppers(value) {
|
|
378
|
-
// Disable the steppers if we either don't have a selection or only have one date in the selection.
|
|
379
|
-
if (!value ||
|
|
380
|
-
(DateInput.isSelectionSingleDate(value) && this.selectionMode !== 'day') ||
|
|
381
|
-
(DateInput.isSelectionRange(value) && (!value.start || !value.end))) {
|
|
382
|
-
this.disableSteppers = true;
|
|
383
|
-
}
|
|
384
|
-
else {
|
|
385
|
-
this.disableSteppers = false;
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
validateTextboxes() {
|
|
389
|
-
const control = this.textboxGroup.controls.textbox;
|
|
390
|
-
const control2 = this.textboxGroup.controls.textbox2;
|
|
391
|
-
// The first textbox should only have the required error if it's empty and the date input is required,
|
|
392
|
-
// or if the date input is not required and the second control is visible and has a value (meaning a partial range)
|
|
393
|
-
if (!control.value &&
|
|
394
|
-
(this.required || (control2.value && this.selectionStrategy.showSecondaryTextbox))) {
|
|
395
|
-
control.setErrors({ required: true });
|
|
396
|
-
}
|
|
397
|
-
// The same idea applies to the second textbox, but only if it's visible
|
|
398
|
-
if (this.selectionStrategy.showSecondaryTextbox &&
|
|
399
|
-
!control2.value &&
|
|
400
|
-
(this.required || control.value)) {
|
|
401
|
-
control2.setErrors({ required: true });
|
|
402
|
-
}
|
|
403
|
-
if (control.value) {
|
|
404
|
-
const errors = this.validateDateString(control.value);
|
|
405
|
-
if (errors) {
|
|
406
|
-
control.setErrors(errors);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
if (control2.value && this.selectionStrategy.showSecondaryTextbox) {
|
|
410
|
-
const errors = this.validateDateString(control2.value);
|
|
411
|
-
if (errors) {
|
|
412
|
-
control2.setErrors(errors);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
}
|
|
416
|
-
validateDateString(date) {
|
|
417
|
-
const value = this.selectionStrategy.parseString(date, this.parseFormats);
|
|
418
|
-
if (value) {
|
|
419
|
-
// We're using the view mode as the granularity. We don't want to invalidate
|
|
420
|
-
// the date in the case where you have a month/quarter/year selected and the min
|
|
421
|
-
// or max date is somewhere within that month/quarter/year.
|
|
422
|
-
if (moment(value).isBefore(this.minDate, this.selectionStrategy.selectionViewMode)) {
|
|
423
|
-
return { minDate: { minValue: this.minDate } };
|
|
424
|
-
}
|
|
425
|
-
else if (moment(value).isAfter(this.maxDate, this.selectionStrategy.selectionViewMode)) {
|
|
426
|
-
return { maxDate: { maxValue: this.maxDate } };
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
return null;
|
|
430
|
-
}
|
|
431
|
-
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DateInputComponent, deps: [{ token: i1.ValidationMessageService }, { token: i2.FormGroupHelper }, { token: i3.UserPreferenceService }, { token: i0.ElementRef }, { token: i4.Overlay }, { token: i5.DateInput.SelectionStrategies }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
432
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: DateInputComponent, selector: "ec-date-input", inputs: { id: "id", formModel: "formModel", minDate: "minDate", maxDate: "maxDate", selectionMode: "selectionMode", selectionModeOptions: "selectionModeOptions", quickSelectDate: "quickSelectDate", enableSteppers: "enableSteppers" }, host: { properties: { "attr.id": "this.id" } }, providers: [DateInput.SelectionStrategies], viewQueries: [{ propertyName: "calendar", first: true, predicate: ["calendar"], descendants: true }, { propertyName: "controls", first: true, predicate: ["controls"], descendants: true }, { propertyName: "overlay", first: true, predicate: ["overlay"], descendants: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0, template: "<label *ngIf=\"label\">\n <span>{{label | translate}}</span>\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors}}</span>\n <ec-help-popover id=\"{{id}}_helpPopover\"\n *ngIf=\"helpPopover\"\n class=\"d-inline-block my-n3 mx-n1\"\n text=\"{{helpPopover | translate}}\"\n contentPosition=\"{{helpPopoverPosition}}\">\n </ec-help-popover>\n</label>\n\n<div class=\"d-flex align-items-center\"\n [ecKeyboardNavContainer]=\"isCalendarOpen\"\n [tabindex]=\"tabindex\"\n #controls=\"ecKeyboardNavContainer\"\n (focusOutEnd)=\"onControlsFocusOutEnd()\">\n <ec-form-control id=\"{{id}}\"\n [required]=\"required\"\n [autofocus]=\"autofocus\"\n [pending]=\"pending\"\n [readonly]=\"readonly\"\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\n [showClear]=\"false\"\n [tabindex]=\"tabindex\"\n actionIcon=\"icon-date\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n class=\"flex-grow\"\n style=\"height: 2rem;\">\n <input id=\"{{id}}_input\"\n type=\"text\"\n placeholder=\"{{placeholder}}\"\n tabindex=\"{{tabindex}}\"\n [formControl]=\"textboxGroup.get('textbox')\"\n (blur)=\"onTextboxBlur()\">\n </ec-form-control>\n\n <ng-container *ngIf=\"selectionStrategy.showSecondaryTextbox\">\n <span class=\"flex-shrink mx-1\">–</span>\n <ec-form-control id=\"{{id}}_control2\"\n [required]=\"required\"\n [autofocus]=\"autofocus\"\n [pending]=\"pending\"\n [readonly]=\"readonly\"\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\n [showClear]=\"false\"\n [tabindex]=\"tabindex\"\n actionIcon=\"icon-date\"\n class=\"flex-grow\"\n style=\"height: 2rem;\">\n <input id=\"{{id}}_input2\"\n type=\"text\"\n placeholder=\"{{placeholder}}\"\n tabindex=\"{{tabindex}}\"\n [formControl]=\"textboxGroup.get('textbox2')\"\n (blur)=\"onTextbox2Blur()\">\n </ec-form-control>\n </ng-container>\n\n <div *ngIf=\"enableSteppers\"\n class=\"control-group ml-2\">\n <ec-button id=\"{{id}}_previousSelection\"\n type=\"secondary\"\n icon=\"icon-angle-down rotate-90\"\n (clicked)=\"previousSelection()\"\n [disabled]=\"isCalendarOpen || disableSteppers || formModel?.disabled\"\n [tabindex]=\"tabindex\">\n </ec-button>\n <ec-button id=\"{{id}}_nextSelection\"\n type=\"secondary\"\n icon=\"icon-angle-down rotate-270\"\n (clicked)=\"nextSelection()\"\n [disabled]=\"isCalendarOpen || disableSteppers || formModel?.disabled\"\n [tabindex]=\"tabindex\">\n </ec-button>\n </div>\n\n <ec-button *ngIf=\"quickSelectDate\"\n id=\"{{id}}_quickSelect\"\n icon=\"icon-day\"\n type=\"secondary\"\n title=\"{{'DateInput_LatestDataAvailableTitle' | translate}}\"\n (clicked)=\"goToQuickSelectDate()\"\n [tabindex]=\"tabindex\"\n class=\"ml-2\">\n </ec-button>\n</div>\n\n<ng-template cdkConnectedOverlay\n #overlay=\"cdkConnectedOverlay\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"isCalendarOpen\"\n [cdkConnectedOverlayScrollStrategy]=\"overlayScrollStrategy\"\n cdkConnectedOverlayPanelClass=\"my-1\"\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\n (detach)=\"isCalendarOpen = false\">\n <article id=\"{{id}}_datePicker\"\n class=\"card d-flex\"\n [ecKeyboardNavContainer]=\"isCalendarOpen\"\n [tabindex]=\"tabindex\"\n #calendar=\"ecKeyboardNavContainer\"\n (focusOutStart)=\"onCalendarFocusOutStart()\"\n (focusOutEnd)=\"onCalendarFocusOutEnd()\">\n <ul *ngIf=\"selectionModeOptions.length > 1\"\n class=\"selection-mode-menu border-right p-1\">\n <li *ngFor=\"let option of selectionModeOptions\">\n <button id=\"{{id}}_selectionMode_{{option}}\"\n class=\"text-body-1\"\n [class.is-selected]=\"option === selectionMode\"\n (click)=\"onSelectionModeChange(option)\"\n tabindex=\"{{tabindex}}\">\n {{'DateInputSelectionMode_' + option | translate}}\n </button>\n </li>\n </ul>\n\n <div>\n <div class=\"d-flex\">\n <ec-calendar id=\"{{id}}_calendar\"\n [view]=\"primaryCalendarView\"\n (viewChange)=\"onPrimaryCalendarViewChange($event)\"\n [selectionMode]=\"selectionMode\"\n [selection]=\"calendarSelection\"\n (dateSelected)=\"onCalendarDateSelected($event)\"\n [minDate]=\"minDate\"\n [maxDate]=\"selectionStrategy.showSecondaryCalendar ? primaryCalendarMaxDate : maxDate\"\n [tabindex]=\"tabindex\">\n </ec-calendar>\n\n <ec-calendar *ngIf=\"selectionStrategy.showSecondaryCalendar\"\n id=\"{{id}}_secondaryCalendar\"\n [view]=\"secondaryCalendarView\"\n (viewChange)=\"onSecondaryCalendarViewChange($event)\"\n [selectionMode]=\"selectionMode\"\n [selection]=\"calendarSelection\"\n (dateSelected)=\"onCalendarDateSelected($event)\"\n [minDate]=\"secondaryCalendarMinDate\"\n [maxDate]=\"maxDate\"\n [tabindex]=\"tabindex\">\n </ec-calendar>\n </div>\n\n <footer *ngIf=\"selectionStrategy.selectionViewMode === 'day'\"\n class=\"px-2 my-2 d-flex\">\n <ec-button id=\"{{id}}_today_button\"\n label=\"{{'DateInput_CalendarTodayButton_Label' | translate}}\"\n class=\"ml-auto\"\n (clicked)=\"goToToday()\"\n tabindex=\"{{tabindex}}\"\n type=\"text\">\n </ec-button>\n <ec-button *ngIf=\"selectionStrategy.showSecondaryTextbox\"\n id=\"{{id}}_close_button\"\n label=\"{{'DateInput_CalendarCloseButton_Label' | translate}}\"\n class=\"ml-2\"\n (clicked)=\"closeCalendarAndFocusInput()\"\n tabindex=\"{{tabindex}}\"\n type=\"primary\">\n </ec-button>\n </footer>\n </div>\n </article>\n</ng-template>\n", styles: [":host{display:block}label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}.date-picker{display:grid;grid-template-areas:\"menu calendar calendar\" \"menu footer footer\"}.date-picker footer{grid-area:footer}ul.selection-mode-menu{grid-area:menu;list-style:none;padding:0;margin:0;min-width:7rem}ul.selection-mode-menu li{margin-bottom:.25rem}ul.selection-mode-menu li button{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border:0;border-radius:var(--ec-border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;background-color:transparent;width:100%;height:1.75rem}ul.selection-mode-menu li button .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}ul.selection-mode-menu li button .ec-icon{flex:none}ul.selection-mode-menu li button .ec-icon+.label{flex:none;margin-left:.25rem}ul.selection-mode-menu li button.has-badge{padding-right:.0625rem}ul.selection-mode-menu li button:focus{outline:none;position:relative;z-index:1}ul.selection-mode-menu li button:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}ul.selection-mode-menu li button:disabled .ec-icon{color:var(--ec-color-disabled-dark)}ul.selection-mode-menu li button:disabled{background-color:transparent;border-color:transparent;color:var(--ec-color-hint-dark);--ec-color-icon: var(--ec-color-hint-dark)}ul.selection-mode-menu li button:hover:not(:disabled){background-color:var(--ec-background-color-hover)}ul.selection-mode-menu li button:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}ul.selection-mode-menu li button:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}ul.selection-mode-menu li button.is-selected{background-color:var(--ec-background-color-selected);font-weight:700}ec-button{--ec-button-border-color-secondary: var(--ec-border-color-control)}.control-group ec-button:has(+ec-button) ::ng-deep button{border-right:0}.control-group ec-button+ec-button ::ng-deep button{border-left:0}\n"], dependencies: [{ kind: "directive", type: i6.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i6.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i4.CdkConnectedOverlay, selector: "[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]", inputs: ["cdkConnectedOverlayOrigin", "cdkConnectedOverlayPositions", "cdkConnectedOverlayPositionStrategy", "cdkConnectedOverlayOffsetX", "cdkConnectedOverlayOffsetY", "cdkConnectedOverlayWidth", "cdkConnectedOverlayHeight", "cdkConnectedOverlayMinWidth", "cdkConnectedOverlayMinHeight", "cdkConnectedOverlayBackdropClass", "cdkConnectedOverlayPanelClass", "cdkConnectedOverlayViewportMargin", "cdkConnectedOverlayScrollStrategy", "cdkConnectedOverlayOpen", "cdkConnectedOverlayDisableClose", "cdkConnectedOverlayTransformOriginOn", "cdkConnectedOverlayHasBackdrop", "cdkConnectedOverlayLockPosition", "cdkConnectedOverlayFlexibleDimensions", "cdkConnectedOverlayGrowAfterOpen", "cdkConnectedOverlayPush", "cdkConnectedOverlayDisposeOnNavigation"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i4.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: i8.ButtonComponent, selector: "ec-button", inputs: ["id", "disabled", "lockButton", "icon", "iconColor", "label", "badge", "tabindex", "type", "pending", "pendingIcon", "customTemplate", "isSubmit", "autofocus"], outputs: ["clicked"] }, { kind: "component", type: i9.FormControlComponent, selector: "ec-form-control", inputs: ["id", "icon", "actionIcon", "showClear", "formModel", "autofocus", "tabindex", "pending", "required", "readonly"], outputs: ["actionClicked"] }, { kind: "component", type: i10.HelpPopoverComponent, selector: "ec-help-popover", inputs: ["id", "text", "contentPosition", "maxWidth"] }, { kind: "component", type: i11.CalendarComponent, selector: "ec-calendar", inputs: ["id", "selection", "selectionMode", "minDate", "maxDate", "tabindex", "view"], outputs: ["dateSelected", "viewChange"] }, { kind: "directive", type: i12.KeyboardNavContainerDirective, selector: "[ecKeyboardNavContainer]", inputs: ["ecKeyboardNavContainer", "tabindex"], outputs: ["focusOutStart", "focusOutEnd"], exportAs: ["ecKeyboardNavContainer"] }, { kind: "pipe", type: i13.TranslatePipe, name: "translate" }] }); }
|
|
433
|
-
}
|
|
434
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DateInputComponent, decorators: [{
|
|
435
|
-
type: Component,
|
|
436
|
-
args: [{ selector: 'ec-date-input', providers: [DateInput.SelectionStrategies], template: "<label *ngIf=\"label\">\n <span>{{label | translate}}</span>\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors}}</span>\n <ec-help-popover id=\"{{id}}_helpPopover\"\n *ngIf=\"helpPopover\"\n class=\"d-inline-block my-n3 mx-n1\"\n text=\"{{helpPopover | translate}}\"\n contentPosition=\"{{helpPopoverPosition}}\">\n </ec-help-popover>\n</label>\n\n<div class=\"d-flex align-items-center\"\n [ecKeyboardNavContainer]=\"isCalendarOpen\"\n [tabindex]=\"tabindex\"\n #controls=\"ecKeyboardNavContainer\"\n (focusOutEnd)=\"onControlsFocusOutEnd()\">\n <ec-form-control id=\"{{id}}\"\n [required]=\"required\"\n [autofocus]=\"autofocus\"\n [pending]=\"pending\"\n [readonly]=\"readonly\"\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\n [showClear]=\"false\"\n [tabindex]=\"tabindex\"\n actionIcon=\"icon-date\"\n cdkOverlayOrigin\n #overlayOrigin=\"cdkOverlayOrigin\"\n class=\"flex-grow\"\n style=\"height: 2rem;\">\n <input id=\"{{id}}_input\"\n type=\"text\"\n placeholder=\"{{placeholder}}\"\n tabindex=\"{{tabindex}}\"\n [formControl]=\"textboxGroup.get('textbox')\"\n (blur)=\"onTextboxBlur()\">\n </ec-form-control>\n\n <ng-container *ngIf=\"selectionStrategy.showSecondaryTextbox\">\n <span class=\"flex-shrink mx-1\">–</span>\n <ec-form-control id=\"{{id}}_control2\"\n [required]=\"required\"\n [autofocus]=\"autofocus\"\n [pending]=\"pending\"\n [readonly]=\"readonly\"\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\n [showClear]=\"false\"\n [tabindex]=\"tabindex\"\n actionIcon=\"icon-date\"\n class=\"flex-grow\"\n style=\"height: 2rem;\">\n <input id=\"{{id}}_input2\"\n type=\"text\"\n placeholder=\"{{placeholder}}\"\n tabindex=\"{{tabindex}}\"\n [formControl]=\"textboxGroup.get('textbox2')\"\n (blur)=\"onTextbox2Blur()\">\n </ec-form-control>\n </ng-container>\n\n <div *ngIf=\"enableSteppers\"\n class=\"control-group ml-2\">\n <ec-button id=\"{{id}}_previousSelection\"\n type=\"secondary\"\n icon=\"icon-angle-down rotate-90\"\n (clicked)=\"previousSelection()\"\n [disabled]=\"isCalendarOpen || disableSteppers || formModel?.disabled\"\n [tabindex]=\"tabindex\">\n </ec-button>\n <ec-button id=\"{{id}}_nextSelection\"\n type=\"secondary\"\n icon=\"icon-angle-down rotate-270\"\n (clicked)=\"nextSelection()\"\n [disabled]=\"isCalendarOpen || disableSteppers || formModel?.disabled\"\n [tabindex]=\"tabindex\">\n </ec-button>\n </div>\n\n <ec-button *ngIf=\"quickSelectDate\"\n id=\"{{id}}_quickSelect\"\n icon=\"icon-day\"\n type=\"secondary\"\n title=\"{{'DateInput_LatestDataAvailableTitle' | translate}}\"\n (clicked)=\"goToQuickSelectDate()\"\n [tabindex]=\"tabindex\"\n class=\"ml-2\">\n </ec-button>\n</div>\n\n<ng-template cdkConnectedOverlay\n #overlay=\"cdkConnectedOverlay\"\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\n [cdkConnectedOverlayOpen]=\"isCalendarOpen\"\n [cdkConnectedOverlayScrollStrategy]=\"overlayScrollStrategy\"\n cdkConnectedOverlayPanelClass=\"my-1\"\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\n (detach)=\"isCalendarOpen = false\">\n <article id=\"{{id}}_datePicker\"\n class=\"card d-flex\"\n [ecKeyboardNavContainer]=\"isCalendarOpen\"\n [tabindex]=\"tabindex\"\n #calendar=\"ecKeyboardNavContainer\"\n (focusOutStart)=\"onCalendarFocusOutStart()\"\n (focusOutEnd)=\"onCalendarFocusOutEnd()\">\n <ul *ngIf=\"selectionModeOptions.length > 1\"\n class=\"selection-mode-menu border-right p-1\">\n <li *ngFor=\"let option of selectionModeOptions\">\n <button id=\"{{id}}_selectionMode_{{option}}\"\n class=\"text-body-1\"\n [class.is-selected]=\"option === selectionMode\"\n (click)=\"onSelectionModeChange(option)\"\n tabindex=\"{{tabindex}}\">\n {{'DateInputSelectionMode_' + option | translate}}\n </button>\n </li>\n </ul>\n\n <div>\n <div class=\"d-flex\">\n <ec-calendar id=\"{{id}}_calendar\"\n [view]=\"primaryCalendarView\"\n (viewChange)=\"onPrimaryCalendarViewChange($event)\"\n [selectionMode]=\"selectionMode\"\n [selection]=\"calendarSelection\"\n (dateSelected)=\"onCalendarDateSelected($event)\"\n [minDate]=\"minDate\"\n [maxDate]=\"selectionStrategy.showSecondaryCalendar ? primaryCalendarMaxDate : maxDate\"\n [tabindex]=\"tabindex\">\n </ec-calendar>\n\n <ec-calendar *ngIf=\"selectionStrategy.showSecondaryCalendar\"\n id=\"{{id}}_secondaryCalendar\"\n [view]=\"secondaryCalendarView\"\n (viewChange)=\"onSecondaryCalendarViewChange($event)\"\n [selectionMode]=\"selectionMode\"\n [selection]=\"calendarSelection\"\n (dateSelected)=\"onCalendarDateSelected($event)\"\n [minDate]=\"secondaryCalendarMinDate\"\n [maxDate]=\"maxDate\"\n [tabindex]=\"tabindex\">\n </ec-calendar>\n </div>\n\n <footer *ngIf=\"selectionStrategy.selectionViewMode === 'day'\"\n class=\"px-2 my-2 d-flex\">\n <ec-button id=\"{{id}}_today_button\"\n label=\"{{'DateInput_CalendarTodayButton_Label' | translate}}\"\n class=\"ml-auto\"\n (clicked)=\"goToToday()\"\n tabindex=\"{{tabindex}}\"\n type=\"text\">\n </ec-button>\n <ec-button *ngIf=\"selectionStrategy.showSecondaryTextbox\"\n id=\"{{id}}_close_button\"\n label=\"{{'DateInput_CalendarCloseButton_Label' | translate}}\"\n class=\"ml-2\"\n (clicked)=\"closeCalendarAndFocusInput()\"\n tabindex=\"{{tabindex}}\"\n type=\"primary\">\n </ec-button>\n </footer>\n </div>\n </article>\n</ng-template>\n", styles: [":host{display:block}label{color:var(--ec-form-control-label-color, var(--ec-color-secondary-dark));display:block;font-size:var(--ec-font-size-label);line-height:1;margin:calc(var(--ec-font-size-label) / 2) 0}.date-picker{display:grid;grid-template-areas:\"menu calendar calendar\" \"menu footer footer\"}.date-picker footer{grid-area:footer}ul.selection-mode-menu{grid-area:menu;list-style:none;padding:0;margin:0;min-width:7rem}ul.selection-mode-menu li{margin-bottom:.25rem}ul.selection-mode-menu li button{font-size:var(--ec-font-size-action);height:2rem;line-height:1.25rem;padding:.3125rem .5rem;border:0;border-radius:var(--ec-border-radius);display:flex;align-items:center;justify-content:center;cursor:pointer;background-color:transparent;width:100%;height:1.75rem}ul.selection-mode-menu li button .label{display:flex;align-items:center;justify-content:center;white-space:nowrap;flex:auto}ul.selection-mode-menu li button .ec-icon{flex:none}ul.selection-mode-menu li button .ec-icon+.label{flex:none;margin-left:.25rem}ul.selection-mode-menu li button.has-badge{padding-right:.0625rem}ul.selection-mode-menu li button:focus{outline:none;position:relative;z-index:1}ul.selection-mode-menu li button:disabled{background-color:var(--ec-background-color-disabled);border:1px solid var(--ec-form-control-border-color-disabled);color:var(--ec-color-disabled-dark);opacity:var(--ec-form-control-opacity-disabled);cursor:default}ul.selection-mode-menu li button:disabled .ec-icon{color:var(--ec-color-disabled-dark)}ul.selection-mode-menu li button:disabled{background-color:transparent;border-color:transparent;color:var(--ec-color-hint-dark);--ec-color-icon: var(--ec-color-hint-dark)}ul.selection-mode-menu li button:hover:not(:disabled){background-color:var(--ec-background-color-hover)}ul.selection-mode-menu li button:active:not(:disabled){background-color:var(--ec-background-color-selected);font-weight:700}ul.selection-mode-menu li button:focus:not(:disabled){box-shadow:var(--ec-button-box-shadow-active, 0 0 0 2px var(--ec-border-color-focus))}ul.selection-mode-menu li button.is-selected{background-color:var(--ec-background-color-selected);font-weight:700}ec-button{--ec-button-border-color-secondary: var(--ec-border-color-control)}.control-group ec-button:has(+ec-button) ::ng-deep button{border-right:0}.control-group ec-button+ec-button ::ng-deep button{border-left:0}\n"] }]
|
|
437
|
-
}], ctorParameters: () => [{ type: i1.ValidationMessageService }, { type: i2.FormGroupHelper }, { type: i3.UserPreferenceService }, { type: i0.ElementRef }, { type: i4.Overlay }, { type: i5.DateInput.SelectionStrategies }], propDecorators: { id: [{
|
|
438
|
-
type: HostBinding,
|
|
439
|
-
args: ['attr.id']
|
|
440
|
-
}, {
|
|
441
|
-
type: Input
|
|
442
|
-
}], formModel: [{
|
|
443
|
-
type: Input
|
|
444
|
-
}], minDate: [{
|
|
445
|
-
type: Input
|
|
446
|
-
}], maxDate: [{
|
|
447
|
-
type: Input
|
|
448
|
-
}], selectionMode: [{
|
|
449
|
-
type: Input
|
|
450
|
-
}], selectionModeOptions: [{
|
|
451
|
-
type: Input
|
|
452
|
-
}], quickSelectDate: [{
|
|
453
|
-
type: Input
|
|
454
|
-
}], enableSteppers: [{
|
|
455
|
-
type: Input
|
|
456
|
-
}], calendar: [{
|
|
457
|
-
type: ViewChild,
|
|
458
|
-
args: ['calendar']
|
|
459
|
-
}], controls: [{
|
|
460
|
-
type: ViewChild,
|
|
461
|
-
args: ['controls']
|
|
462
|
-
}], overlay: [{
|
|
463
|
-
type: ViewChild,
|
|
464
|
-
args: ['overlay']
|
|
465
|
-
}] } });
|
|
466
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS1pbnB1dC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL3NyYy9saWIvY29udHJvbHMvZGF0ZS1pbnB1dC9kYXRlLWlucHV0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbXBvbmVudHMvc3JjL2xpYi9jb250cm9scy9kYXRlLWlucHV0L2RhdGUtaW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFNBQVMsRUFBYyxXQUFXLEVBQUUsS0FBSyxFQUFvQyxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDdkgsT0FBTyxFQUFFLFdBQVcsRUFBcUIsU0FBUyxFQUFvQixNQUFNLGdCQUFnQixDQUFDO0FBQzdGLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUM1QixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3JDLE9BQU8sRUFBRSxZQUFZLEVBQUUsb0JBQW9CLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFL0UsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBSzdELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUV2RCxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7Ozs7Ozs7Ozs7Ozs7OztBQVEvQyxNQUFNLE9BQU8sa0JBQW1CLFNBQVEsZUFBZTtJQXVFckQsWUFDWSx3QkFBa0QsRUFDbEQsZUFBZ0MsRUFDbEMscUJBQTRDLEVBQzVDLEVBQWMsRUFDZCxjQUF1QixFQUN2QixtQkFBa0Q7UUFFMUQsS0FBSyxDQUFDLHdCQUF3QixFQUFFLGVBQWUsQ0FBQyxDQUFDO1FBUHZDLDZCQUF3QixHQUF4Qix3QkFBd0IsQ0FBMEI7UUFDbEQsb0JBQWUsR0FBZixlQUFlLENB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LFNBQVM7K0JBQ0UsZUFBZSxhQUdkLENBQUMsU0FBUyxDQUFDLG1CQUFtQixDQUFDOzBQQUsxQixFQUFFO3NCQURqQixXQUFXO3VCQUFDLFNBQVM7O3NCQUNyQixLQUFLO2dCQUtVLFNBQVM7c0JBQXhCLEtBQUs7Z0JBRVUsT0FBTztzQkFBdEIsS0FBSztnQkFDVSxPQUFPO3NCQUF0QixLQUFLO2dCQUdHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBR0csb0JBQW9CO3NCQUE1QixLQUFLO2dCQU1HLGVBQWU7c0JBQXZCLEtBQUs7Z0JBR0csY0FBYztzQkFBdEIsS0FBSztnQkF1Q2lCLFFBQVE7c0JBQTlCLFNBQVM7dUJBQUMsVUFBVTtnQkFDRSxRQUFRO3NCQUE5QixTQUFTO3VCQUFDLFVBQVU7Z0JBR0MsT0FBTztzQkFBNUIsU0FBUzt1QkFBQyxTQUFTIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2RrQ29ubmVjdGVkT3ZlcmxheSwgT3ZlcmxheSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9vdmVybGF5JztcbmltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgSG9zdEJpbmRpbmcsIElucHV0LCBPbkNoYW5nZXMsIE9uSW5pdCwgU2ltcGxlQ2hhbmdlcywgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBGb3JtQ29udHJvbCwgRm9ybUNvbnRyb2xTdGF0dXMsIEZvcm1Hcm91cCwgVmFsaWRhdGlvbkVycm9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCBtb21lbnQgZnJvbSAnbW9tZW50JztcbmltcG9ydCB7IGxhc3RWYWx1ZUZyb20gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGRlYm91bmNlVGltZSwgZGlzdGluY3RVbnRpbENoYW5nZWQsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7IEtleWJvYXJkTmF2Q29udGFpbmVyRGlyZWN0aXZlIH0gZnJvbSAnLi4vLi4vLi4vcHVibGljLWFwaSc7XG5pbXBvcnQgeyBEYXRlVGltZUhlbHBlciB9IGZyb20gJy4uLy4uL2NvcmUvZGF0ZS10aW1lLWhlbHBlcic7XG5pbXBvcnQgeyBWYWxpZGF0aW9uTWVzc2FnZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9jb3JlL3ZhbGlkYXRpb24tbWVzc2FnZS5zZXJ2aWNlJztcbmltcG9ydCB7IEZvcm1Hcm91cEhlbHBlciB9IGZyb20gJy4uLy4uL3NoYXJlZC9mb3JtLWdyb3VwLmhlbHBlcic7XG5pbXBvcnQgeyBVc2VyUHJlZmVyZW5jZVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zaGFyZWQvdXNlci1wcmVmZXJlbmNlLnNlcnZpY2UnO1xuaW1wb3J0IHsgQ2FsZW5kYXIgfSBmcm9tICcuLi9jYWxlbmRhci9jYWxlbmRhci50eXBlcyc7XG5pbXBvcnQgeyBGb3JtQ29udHJvbEJhc2UgfSBmcm9tICcuLi9mb3JtLWNvbnRyb2wtYmFzZSc7XG5pbXBvcnQgeyBEYXRlSW5wdXRTZWxlY3Rpb25TdHJhdGVneUJhc2UgfSBmcm9tICcuL2RhdGUtaW5wdXQtc2VsZWN0aW9uLXN0cmF0ZWdpZXMvZGF0ZS1pbnB1dC1zZWxlY3Rpb24tc3RyYXRlZ3ktYmFzZSc7XG5pbXBvcnQgeyBEYXRlSW5wdXQgfSBmcm9tICcuL2RhdGUtaW5wdXQudHlwZXMnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdlYy1kYXRlLWlucHV0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2RhdGUtaW5wdXQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9kYXRlLWlucHV0LmNvbXBvbmVudC5zY3NzJ10sXG4gIHByb3ZpZGVyczogW0RhdGVJbnB1dC5TZWxlY3Rpb25TdHJhdGVnaWVzXVxufSlcbmV4cG9ydCBjbGFzcyBEYXRlSW5wdXRDb21wb25lbnQgZXh0ZW5kcyBGb3JtQ29udHJvbEJhc2UgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcyB7XG5cbiAgQEhvc3RCaW5kaW5nKCdhdHRyLmlkJylcbiAgQElucHV0KCkgcHVibGljIGlkOiBzdHJpbmcgPSAnJztcblxuICAvKiogVGhlIGZvcm0gY29udHJvbCBwcm92aWRlZCBieSB0aGUgaG9zdGluZyBmb3JtLiAqL1xuICAvLyBASW5wdXQoKSBwdWJsaWMgZm9ybU1vZGVsOiBEYXRlSW5wdXQuRm9ybU1vZGVsID0gbmV3IEZvcm1Db250cm9sKG51bGwpO1xuICAvLyBDb3BpbG90IGtlZXBzIGNsYWltaW5nIHRoaXMgZm9ybU1vZGVsIGlzIGJlaW5nIG92ZXJ3cml0dGVuIGluIHRoZSBjb25zdHJ1Y3Rvci5cbiAgQElucHV0KCkgcHVibGljIGZvcm1Nb2RlbDogRGF0ZUlucHV0LkZvcm1Nb2RlbCA9IG5ldyBGb3JtQ29udHJvbChudWxsKTtcblxuICBASW5wdXQoKSBwdWJsaWMgbWluRGF0ZTogRGF0ZSA9IERhdGVUaW1lSGVscGVyLm1pbkRhdGVQaWNrZXJEYXRlO1xuICBASW5wdXQoKSBwdWJsaWMgbWF4RGF0ZTogRGF0ZSA9IERhdGVUaW1lSGVscGVyLm1heERhdGVQaWNrZXJEYXRlO1xuXG4gIC8qKiBUaGUgaW5pdGlhbCBzZWxlY3Rpb24gbW9kZSBmb3IgdGhlIGNhbGVuZGFyLiBEZWZhdWx0cyB0byBkYXkgaWYgbm90IHByb3ZpZGVkICovXG4gIEBJbnB1dCgpIHNlbGVjdGlvbk1vZGU6IERhdGVJbnB1dC5TZWxlY3Rpb25Nb2RlID0gJ2RheSc7XG5cbiAgLyoqIFRoZSBhdmFpbGFibGUgc2VsZWN0aW9uIG1vZGVzIGZvciB0aGUgY2FsZW5kYXIuIERlZmF1bHRzIHRvIG9ubHkgdGhlIGluaXRpYWwgc2VsZWN0aW9uIG1vZGUgaWYgbm90IHByb3ZpZGVkLiAgKi9cbiAgQElucHV0KCkgc2VsZWN0aW9uTW9kZU9wdGlvbnM6IERhdGVJbnB1dC5TZWxlY3Rpb25Nb2RlW10gPSBbJ2RheSddO1xuXG4gIC8qKiBcbiAgICogV2hlbiBhIGRhdGUgaXMgcHJvdmlkZWQsIGVuYWJsZXMgdGhlICdxdWljayBzZWxlY3QnIGJ1dHRvbi5cbiAgICogQ2xpY2tpbmcgdGhlIGJ1dHRvbiB3aWxsIHNoaWZ0IHRoZSBzZWxlY3RlZCBkYXRlIHJhbmdlIHRvIHRoZSBwcm92aWRlZCBkYXRlLlxuICAgKi9cbiAgQElucHV0KCkgcXVpY2tTZWxlY3REYXRlPzogRGF0ZTtcblxuICAvKiogRW5hYmxlcyB0aGUgbmV4dC9wcmV2aW91cyBzZWxlY3Rpb24gYnV0dG9ucy4gKi9cbiAgQElucHV0KCkgZW5hYmxlU3RlcHBlcnM6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvKiogVGhlIGZvcm0gZ3JvdXAgZm9yIHRoZSBpbnRlcm5hbCB0ZXh0Ym94ZXMuIFRleHRib3gyIGlzIG9ubHkgdXNlZCBmb3IgcmFuZ2VzLiAqL1xuICBwdWJsaWMgdGV4dGJveEdyb3VwOiBEYXRlSW5wdXQuVGV4dGJveEdyb3VwID0gbmV3IEZvcm1Hcm91cCh7XG4gICAgdGV4dGJveDogbmV3IEZvcm1Db250cm9sPHN0cmluZyB8IG51bGw+KG51bGwpLFxuICAgIHRleHRib3gyOiBuZXcgRm9ybUNvbnRyb2w8c3RyaW5nIHwgbnVsbD4obnVsbClcbiAgfSk7XG5cbiAgLyoqXG4gICAqIFRoZSBjdXJyZW50IGNhbGVuZGFyIHNlbGVjdGlvbi5cbiAgICogVXBkYXRlZCB3aGVuIHRoZSB1c2VyIGNsaWNrcyBvbiBhIGNhbGVuZGFyIGl0ZW0gb3Igd2hlbiB0aGUgZGF0ZSBlbnRlcmVkIGludG8gdGhlIHRleHRib3ggaXMgcGFyc2VkLlxuICAgKi9cbiAgcHVibGljIGNhbGVuZGFyU2VsZWN0aW9uOiBEYXRlSW5wdXQuU2VsZWN0aW9uIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqIENvbnRyb2xzIHdoZXRoZXIgdGhlIGNhbGVuZGFyIG92ZXJsYXkgaXMgb3BlbiBvciBub3QuICovXG4gIHB1YmxpYyBpc0NhbGVuZGFyT3BlbiA9IGZhbHNlO1xuXG4gIC8qKiBQbGFjZWhvbGRlciBmb3IgdGhlIHRleHRib3guIFVwZGF0ZWQgdG8gcmVmbGVjdCB0aGUgdXNlcidzIGRhdGUgZGlzcGxheSBwcmVmZXJlbmNlLiAqL1xuICBwdWJsaWMgcGxhY2Vob2xkZXI6IHN0cmluZyA9ICdNTS9ERC9ZWVlZJztcblxuICAvKiogT3ZlcmxheSBzY3JvbGwgc3RyYXRlZ3kgZm9yIHRoZSBjYWxlbmRhciBvdmVybGF5LiBDbG9zZXMgdGhlIGNhbGVuZGFyIG9uIHNjcm9sbC4gKi9cbiAgcHVibGljIG92ZXJsYXlTY3JvbGxTdHJhdGVneSA9IHRoaXMub3ZlcmxheVNlcnZpY2Uuc2Nyb2xsU3RyYXRlZ2llcy5jbG9zZSgpO1xuXG4gIHB1YmxpYyBwcmltYXJ5Q2FsZW5kYXJWaWV3OiBDYWxlbmRhci5WaWV3ID0geyBtb2RlOiAnZGF5JywgZGF0ZTogbmV3IERhdGUoKSB9O1xuICBwdWJsaWMgc2Vjb25kYXJ5Q2FsZW5kYXJWaWV3OiBDYWxlbmRhci5WaWV3ID0geyBtb2RlOiAnZGF5JywgZGF0ZTogbmV3IERhdGUoKSB9O1xuXG4gIHB1YmxpYyBwcmltYXJ5Q2FsZW5kYXJNYXhEYXRlOiBEYXRlID0gRGF0ZVRpbWVIZWxwZXIubWF4RGF0ZVBpY2tlckRhdGU7XG4gIHB1YmxpYyBzZWNvbmRhcnlDYWxlbmRhck1pbkRhdGU6IERhdGUgPSBEYXRlVGltZUhlbHBlci5taW5EYXRlUGlja2VyRGF0ZTtcblxuICBwdWJsaWMgZGlzYWJsZVN0ZXBwZXJzOiBib29sZWFuID0gZmFsc2U7XG5cbiAgcHVibGljIHNlbGVjdGlvblN0cmF0ZWd5ITogRGF0ZUlucHV0U2VsZWN0aW9uU3RyYXRlZ3lCYXNlO1xuXG4gIC8qKiBcbiAgICogRGF0ZSBwYXJzaW5nIGZvcm1hdHMgZm9yIHVzZXItZW50ZXJlZCBkYXRlcy4gRGVmYXVsdHMgdG8gbW9udGgtZmlyc3QgZm9ybWF0cywgYnV0IGlzIHVwZGF0ZWQgaW4gb25Jbml0XG4gICAqIHRvIHVzZSB0aGUgdXNlcidzIHByZWZlcnJlZCBkYXRlIGZvcm1hdC5cbiAgICovXG4gIHByaXZhdGUgcGFyc2VGb3JtYXRzOiBzdHJpbmdbXSA9IERhdGVUaW1lSGVscGVyLmdldE1vbWVudFBhcnNlRm9ybWF0cygpO1xuXG4gIEBWaWV3Q2hpbGQoJ2NhbGVuZGFyJykgY2FsZW5kYXI/OiBLZXlib2FyZE5hdkNvbnRhaW5lckRpcmVjdGl2ZTtcbiAgQFZpZXdDaGlsZCgnY29udHJvbHMnKSBjb250cm9scz86IEtleWJvYXJkTmF2Q29udGFpbmVyRGlyZWN0aXZlO1xuXG4gIC8qKiBSZWZlcmVuY2UgdG8gdGhlIG92ZXJsYXkgZGlyZWN0aXZlIChzZWUgdGVtcGxhdGUpLiBVc2VkIHRvIHVwZGF0ZSB0aGUgb3ZlcmxheSBwb3NpdGlvbiBvbiB2YWxpZGF0aW9uIGNoYW5nZXMuICovXG4gIEBWaWV3Q2hpbGQoJ292ZXJsYXknKSBvdmVybGF5PzogQ2RrQ29ubmVjdGVkT3ZlcmxheTtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcm90ZWN0ZWQgdmFsaWRhdGlvbk1lc3NhZ2VTZXJ2aWNlOiBWYWxpZGF0aW9uTWVzc2FnZVNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGZvcm1Hcm91cEhlbHBlcjogRm9ybUdyb3VwSGVscGVyLFxuICAgIHByaXZhdGUgdXNlclByZWZlcmVuY2VTZXJ2aWNlOiBVc2VyUHJlZmVyZW5jZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBlbDogRWxlbWVudFJlZixcbiAgICBwcml2YXRlIG92ZXJsYXlTZXJ2aWNlOiBPdmVybGF5LFxuICAgIHByaXZhdGUgc2VsZWN0aW9uU3RyYXRlZ2llczogRGF0ZUlucHV0LlNlbGVjdGlvblN0cmF0ZWdpZXNcbiAgKSB7XG4gICAgc3VwZXIodmFsaWRhdGlvbk1lc3NhZ2VTZXJ2aWNlLCBmb3JtR3JvdXBIZWxwZXIpO1xuICB9XG5cbiAgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcykge1xuICAgIGlmIChjaGFuZ2VzLnNlbGVjdGlvbk1vZGUgJiYgIWNoYW5nZXMuc2VsZWN0aW9uTW9kZS5pc0ZpcnN0Q2hhbmdlKCkpIHtcbiAgICAgIHRoaXMub25TZWxlY3Rpb25Nb2RlQ2hhbmdlKHRoaXMuc2VsZWN0aW9uTW9kZSk7XG4gICAgfVxuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgLy8gU2V0dXBcbiAgICBzdXBlci5uZ09uSW5pdCgpO1xuICAgIHRoaXMuc2V0RGF0ZUZvcm1hdHMoKTtcbiAgICB0aGlzLnNldFNlbGVjdGlvbk1vZGUodGhpcy5zZWxlY3Rpb25Nb2RlKTtcblxuICAgIC8vIFN1YnNjcmlwdGlvbnNcbiAgICB0aGlzLm9uRm9ybU1vZGVsU3RhdHVzQ2hhbmdlcygpO1xuICAgIHRoaXMub25Gb3JtTW9kZWxWYWx1ZUNoYW5nZXMoKTtcbiAgICB0aGlzLm9uVGV4dGJveFZhbHVlQ2hhbmdlcygpO1xuXG4gICAgLy8gU3luYyB0aGUgaW5pdGlhbCBkaXNhYmxlZCBzdGF0dXMgYW5kIHZhbHVlIG9mIHRoZSB0ZXh0Ym94XG4gICAgdGhpcy5zeW5jVGV4dGJveENvbnRyb2xEaXNhYmxlZFN0YXR1cyh0aGlzLmZvcm1Nb2RlbC5zdGF0dXMpO1xuICAgIGNvbnN0IGluaXRpYWxEaXNwbGF5VmFsdWUgPSB0aGlzLnNlbGVjdGlvblN0cmF0ZWd5LmZvcm1hdFNlbGVjdGlvbih0aGlzLmZvcm1Nb2RlbC52YWx1ZSk7XG4gICAgdGhpcy50ZXh0Ym94R3JvdXAucGF0Y2hWYWx1ZShpbml0aWFsRGlzcGxheVZhbHVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG5cbiAgICAvLyBVcGRhdGUgdGhlIGNhbGVuZGFyIHNlbGVjdGlvbiBhbmQgdmlldyBiYXNlZCBvbiB0aGUgaW5pdGlhbCBmb3JtIG1vZGVsIHZhbHVlXG4gICAgdGhpcy5jYWxlbmRhclNlbGVjdGlvbiA9IHRoaXMuZm9ybU1vZGVsLnZhbHVlO1xuICAgIHRoaXMudXBkYXRlQ2FsZW5kYXJzKHRoaXMuY2FsZW5kYXJTZWxlY3Rpb24pO1xuICAgIHRoaXMudXBkYXRlU3RlcHBlcnModGhpcy5jYWxlbmRhclNlbGVjdGlvbik7XG4gIH1cblxuICBwdWJsaWMgY2xvc2VDYWxlbmRhckFuZEZvY3VzSW5wdXQoKSB7XG4gICAgdGhpcy5pc0NhbGVuZGFyT3BlbiA9IGZhbHNlO1xuICAgIHRoaXMuZm9jdXNJbnB1dCgpO1xuICB9XG5cbiAgLyoqIEZvY3VzZXMgdGhlIGlucHV0IHdoZW5ldmVyIHRoZSBjYWxlbmRhciBpcyBzaGlmdC10YWJiZWQgb3V0IG9mLiAqL1xuICBwdWJsaWMgb25DYWxlbmRhckZvY3VzT3V0U3RhcnQoKSB7XG4gICAgdGhpcy5mb2N1c0lucHV0KCk7XG4gIH1cblxuICAvKiogQ2xvc2VzIHRoZSBjYWxlbmRhciBhbmQgZm9jdXNlcyB0aGUgaW5wdXQgd2hlbmV2ZXIgdGhlIGNhbGVuZGFyIGlzIHRhYmJlZCBvdXQgb2YuICovXG4gIHB1YmxpYyBvbkNhbGVuZGFyRm9jdXNPdXRFbmQoKSB7XG4gICAgdGhpcy5jbG9zZUNhbGVuZGFyQW5kRm9jdXNJbnB1dCgpO1xuICB9XG5cbiAgLyoqIENsb3NlcyB0aGUgY2FsZW5kYXIgaWYgdGhlIHVzZXIgY2xpY2tzIG91dHNpZGUgb2YgdGhlIGNhbGVuZGFyIGFuZCBkYXRlIGlucHV0LiAqL1xuICBwdWJsaWMgb25PdmVybGF5T3V0c2lkZUNsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgLy8gRG8gbm90IGNsb3NlIHRoZSBjYWxlbmRhciBpZiB0aGUgY2xpY2sgd2FzIHdpdGhpbiB0aGUgZGF0ZSBpbnB1dCBvciBhY3Rpb24gYnV0dG9uXG4gICAgY29uc3QgcmVjdCA9IHRoaXMuZWwubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBjbGlja2VkT3V0c2lkZUNvbnRyb2wgPSBldmVudC5jbGllbnRZIDwgcmVjdC50b3AgfHxcbiAgICAgIGV2ZW50LmNsaWVudFkgPiByZWN0LmJvdHRvbSB8fFxuICAgICAgZXZlbnQuY2xpZW50WCA8IHJlY3QubGVmdCB8fFxuICAgICAgZXZlbnQuY2xpZW50WCA+IHJlY3QucmlnaHQ7XG4gICAgLy8gSXQncyBwb3NzaWJsZSB0aGF0IHRoZSB1c2VyIGhpdCBlbnRlciBvbiB0aGUgYWN0aW9uIGJ1dHRvbiBpbnN0ZWFkIG9mIGNsaWNraW5nIHdpdGggdGhlIG1vdXNlLlxuICAgIC8vIEluIHRoaXMgY2FzZSB0aGUgXCJjbGlja1wiIGV2ZW50IHdpbGwgYmUgb3V0c2lkZSBvZiB0aGUgY29tcG9uZW50IGJlY2F1c2UgdGhlIGNsaWVudHggYW5kIHkgYXJlIDAsXG4gICAgLy8gYnV0IHdlIGRvbid0IHdhbnQgdG8gY2xvc2UgaW4gdGhpcyBjYXNlIGJlY2F1c2UgYnV0dG9uIGNsaWNrcyB0cmlnZ2VyIGNhbGVuZGFyIG9wZW4vY2xvc2Ugc2VwYXJhdGVseS5cbiAgICBjb25zdCB0YXJnZXRJZCA9ICg8SFRNTEVsZW1lbnQ+ZXZlbnQudGFyZ2V0KS5pZDtcbiAgICBjb25zdCBpc0FjdGlvbkNsaWNrID0gdGFyZ2V0SWQgPT09IGAke3RoaXMuaWR9X2FjdGlvbmAgfHwgdGFyZ2V0SWQgPT09IGAke3RoaXMuaWR9X2NvbnRyb2wyX2FjdGlvbmA7XG5cbiAgICBpZiAoIWlzQWN0aW9uQ2xpY2sgJiYgY2xpY2tlZE91dHNpZGVDb250cm9sKSB7XG4gICAgICB0aGlzLmlzQ2FsZW5kYXJPcGVuID0gZmFsc2U7XG4gICAgfVxuICB9XG5cbiAgLyoqIElmIHRoZSB1c2VyIHRhYnMgb3V0IG9mIHRoZSBmb3JtIGNvbnRyb2wncyBhY3Rpb24gYnV0dG9uIGFuZCB0aGUgY2FsZW5kYXIgaXMgb3BlbiwgZm9jdXMgdGhlIGZpcnN0IGl0ZW0gaW4gdGhlIGNhbGVuZGFyIG92ZXJsYXkgKi9cbiAgcHVibGljIG9uQ29udHJvbHNGb2N1c091dEVuZCgpIHtcbiAgICBpZiAodGhpcy5pc0NhbGVuZGFyT3Blbikge1xuICAgICAgdGhpcy5jYWxlbmRhcj8uZm9jdXMoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgb25UZXh0Ym94Qmx1cigpIHtcbiAgICAvLyBXZSB3YW50IHRvIHByZXZlbnQgdGhlIGZpeGVkIGRhdGUgcmFuZ2UgbW9kZXMgZnJvbSByZS1hdXRvY29tcGxldGluZyB0aGUgZmlyc3QgdGV4dGJveCB3aGVuIGl0IGlzIGV4cGxpY2l0bHkgY2xlYXJlZC5cbiAgICBjb25zdCBwcmV2aW91c1ZhbHVlID0gRGF0ZUlucHV0LmlzU2VsZWN0aW9uUmFuZ2UodGhpcy5mb3JtTW9kZWwudmFsdWUpID8gdGhpcy5mb3JtTW9kZWwudmFsdWUuc3RhcnQgOiB0aGlzLmZvcm1Nb2RlbC52YWx1ZTtcbiAgICBjb25zdCBjdXJyZW50VmFsdWUgPSB0aGlzLnRleHRib3hHcm91cC52YWx1ZS50ZXh0Ym94O1xuICAgIGNvbnN0IGNsZWFyZWQgPSAhIXByZXZpb3VzVmFsdWUgJiYgIWN1cnJlbnRWYWx1ZTtcbiAgICBjb25zdCBvcHRpb25zOiBEYXRlSW5wdXQuUGFyc2luZ09wdGlvbnMgPSB7IHByZXZlbnRBdXRvQ29tcGxldGU6IGNsZWFyZWQgfTtcblxuICAgIC8vIFBhcnNlIHRoZSB0ZXh0Ym94IHZhbHVlcyBpbnRvIGEgc2VsZWN0aW9uIGFuZCB1cGRhdGUgdGhlIGZvcm0gbW9kZWxcbiAgICBjb25zdCBwYXJzZWRTZWxlY3Rpb24gPSB0aGlzLnNlbGVjdGlvblN0cmF0ZWd5LnBhcnNlVGV4dGJveFZhbHVlcyh0aGlzLnRleHRib3hHcm91cC52YWx1ZSwgdGhpcy5wYXJzZUZvcm1hdHMsIG9wdGlvbnMpO1xuICAgIHRoaXMudXBkYXRlRm9ybU1vZGVsKHBhcnNlZFNlbGVjdGlvbik7XG4gIH1cblxuICBwdWJsaWMgb25UZXh0Ym94MkJsdXIoKSB7XG4gICAgLy8gV2Ugd2FudCB0byBwcmV2ZW50IHRoZSBmaXhlZCBkYXRlIHJhbmdlIG1vZGVzIGZyb20gcmUtYXV0b2NvbXBsZXRpbmcgdGhlIHNlY29uZCB0ZXh0Ym94IHdoZW4gaXQgaXMgZXhwbGljaXRseSBjbGVhcmVkLlxuICAgIGNvbnN0IHByZXZpb3VzVmFsdWUgPSBEYXRlSW5wdXQuaXNTZWxlY3Rpb25SYW5nZSh0aGlzLmZvcm1Nb2RlbC52YWx1ZSkgPyB0aGlzLmZvcm1Nb2RlbC52YWx1ZS5lbmQgOiBudWxsO1xuICAgIGNvbnN0IGN1cnJlbnRWYWx1ZSA9IHRoaXMudGV4dGJveEdyb3VwLnZhbHVlLnRleHRib3gyO1xuICAgIGNvbnN0IGNsZWFyZWQgPSAhIXByZXZpb3VzVmFsdWUgJiYgIWN1cnJlbnRWYWx1ZTtcbiAgICBjb25zdCBvcHRpb25zOiBEYXRlSW5wdXQuUGFyc2luZ09wdGlvbnMgPSB7IHBhcnNlRnJvbUVuZDogdHJ1ZSwgcHJldmVudEF1dG9Db21wbGV0ZTogY2xlYXJlZCB9O1xuXG4gICAgLy8gUGFyc2UgdGhlIHRleHRib3ggdmFsdWVzIGludG8gYSBzZWxlY3Rpb24gYW5kIHVwZGF0ZSB0aGUgZm9ybSBtb2RlbCxcbiAgICAvLyBGb3IgdGhlIHNlY29uZCBib3ggd2UncmUga2V5aW5nIHRoZSBwYXJzZSBmcm9tIHRoZSBlbmQgZGF0ZSBpbiB0aGUgc2VsZWN0aW9uLlxuICAgIGNvbnN0IHBhcnNlZFNlbGVjdGlvbiA9IHRoaXMuc2VsZWN0aW9uU3RyYXRlZ3kucGFyc2VUZXh0Ym94VmFsdWVzKHRoaXMudGV4dGJveEdyb3VwLnZhbHVlLCB0aGlzLnBhcnNlRm9ybWF0cywgb3B0aW9ucyk7XG4gICAgdGhpcy51cGRhdGVGb3JtTW9kZWwocGFyc2VkU2VsZWN0aW9uKTtcbiAgfVxuXG4gIHB1YmxpYyBvblNlbGVjdGlvbk1vZGVDaGFuZ2UobW9kZTogRGF0ZUlucHV0LlNlbGVjdGlvbk1vZGUpIHtcbiAgICB0aGlzLnNldFNlbGVjdGlvbk1vZGUobW9kZSk7XG4gICAgY29uc3QgbmV3U2VsZWN0aW9uID0gdGhpcy5zZWxlY3Rpb25TdHJhdGVneS5nZXROZXdTZWxlY3Rpb25Gcm9tRXhpc3RpbmcodGhpcy5jYWxlbmRhclNlbGVjdGlvbik7XG4gICAgdGhpcy51cGRhdGVGb3JtTW9kZWwobmV3U2VsZWN0aW9uKTtcblxuICAgIC8vIE9uIHNlbGVjdGlvbiBtb2RlIGNoYW5nZSwgd2Ugd2FudCB0byBmb3JjZSB0aGUgY2FsZW5kYXJzIHRvIHNob3cgdGhlIHJpZ2h0IHZpZXcgbW9kZSBmb3IgdGhlIG5ldyBzZWxlY3Rpb24uXG4gICAgLy8gVGhpcyBwcmV2ZW50cyB0aGUgdXNlciBmcm9tIHNlZWluZyBhIHZpZXcgbW9kZSB0aGF0IGRvZXNuJ3QgbWFrZSBzZW5zZSBmb3IgdGhlIG5ldyBzZWxlY3Rpb24sXG4gICAgLy8gTGlrZSB3aGVuIHN3aWNoaW5nIGZyb20geWVhciBtb2RlIHRvIGxhc3QgNyBkYXlzIG1vZGUuXG4gICAgdGhpcy5wcmltYXJ5Q2FsZW5kYXJWaWV3ID0geyBtb2RlOiB0aGlzLnNlbGVjdGlvblN0cmF0ZWd5LnNlbGVjdGlvblZpZXdNb2RlLCBkYXRlOiB0aGlzLnByaW1hcnlDYWxlbmRhclZpZXcuZGF0ZSB9O1xuICAgIHRoaXMuc2Vjb25kYXJ5Q2FsZW5kYXJWaWV3ID0geyBtb2RlOiB0aGlzLnNlbGVjdGlvblN0cmF0ZWd5LnNlbGVjdGlvblZpZXdNb2RlLCBkYXRlOiB0aGlzLnNlY29uZGFyeUNhbGVuZGFyVmlldy5kYXRlIH07XG4gICAgdGhpcy51cGRhdGVDYWxlbmRhck1pbk1heERhdGVzKCk7XG4gIH1cblxuICBwdWJsaWMgb25DYWxlbmRhckRhdGVTZWxlY3RlZChkYXRlOiBEYXRlKSB7XG4gICAgY29uc3QgbmV3U2VsZWN0aW9uID0gdGhpcy5zZWxlY3Rpb25TdHJhdGVneS5nZXRTZWxlY3Rpb25Gcm9tRGF0ZShkYXRlLCB0aGlzLmNhbGVuZGFyU2VsZWN0aW9uKTtcbiAgICBjb25zdCBkaXNwbGF5VmFsdWUgPSB0aGlzLnNlbGVjdGlvblN0cmF0ZWd5LmZvcm1hdFNlbGVjdGlvbihuZXdTZWxlY3Rpb24pO1xuICAgIC8vIERvbid0IGVtaXQgZXZlbnRzIHdoZW4gcGF0Y2hpbmcgdmFsdWVzIGhlcmUuIFdlIGRvbid0IHdhbnQgdG8gdHJpZ2dlciB0aGUgY2FsZW5kYXIgdXBkYXRlcyBzaW5jZSB0aGUgY2FsZW5kYXIgaXMgYWxyZWFkeVxuICAgIC8vIHNob3dpbmcgdGhlIHNlbGVjdGVkIGRhdGUuIFdlIGFsc28gZG9uJ3Qgd2FudCB0byB0cmlnZ2VyIHRoZSB0ZXh0Ym94IHBhcnNpbmcgbG9naWMgc2luY2UgdGhlIGRhdGUgd2FzIHNlbGVjdGVkIGZyb20gdGhlIGNhbGVuZGFyLlxuICAgIHRoaXMudGV4dGJveEdyb3VwLnBhdGNoVmFsdWUoZGlzcGxheVZhbHVlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XG4gICAgdGhpcy51cGRhdGVGb3JtTW9kZWwobmV3U2VsZWN0aW9uKTtcbiAgICB0aGlzLmNhbGVuZGFyU2VsZWN0aW9uID0gbmV3U2VsZWN0aW9uO1xuXG4gICAgLy8gQ2xvc2UgdGhlIGNhbGVuZGFyIGlmIHRoZSBzZWxlY3Rpb24gbW9kZSBpcyBub3QgYSByYW5nZSBtb2RlIHdoZXJlIGVpdGhlciB0aGUgc3RhcnQgb3IgdGhlIGVuZCBkYXRlIGNhbiBiZSBjaGFuZ2VkLlxuICAgIGlmICghdGhpcy5zZWxlY3Rpb25TdHJhdGVneS5zaG93U2Vjb25kYXJ5VGV4dGJveCkge1xuICAgICAgdGhpcy5jbG9zZUNhbGVuZGFyQW5kRm9jdXNJbnB1dCgpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBvblByaW1hcnlDYWxlbmRhclZpZXdDaGFuZ2UodmlldzogQ2FsZW5kYXIuVmlldykge1xuICAgIHRoaXMucHJpbWFyeUNhbGVuZGFyVmlldyA9IHZpZXc7XG4gICAgdGhpcy51cGRhdGVDYWxlbmRhck1pbk1heERhdGVzKCk7XG4gIH1cblxuICBwdWJsaWMgb25TZWNvbmRhcnlDYWxlbmRhclZpZXdDaGFuZ2UodmlldzogQ2FsZW5kYXIuVmlldykge1xuICAgIHRoaXMuc2Vjb25kYXJ5Q2FsZW5kYXJWaWV3ID0gdmlldztcbiAgICB0aGlzLnVwZGF0ZUNhbGVuZGFyTWluTWF4RGF0ZXMoKTtcbiAgfVxuXG4gIC8qKiBTaGlmdHMgdGhlIGNhbGVuZGFyIHZpZXdzIHRvIGRpc3BsYXkgdG9kYXkuIERvZXMgbm90IHVwZGF0ZSB0aGUgY2FsZW5kYXIgc2VsZWN0aW9uLiAqL1xuICBwdWJsaWMgZ29Ub1RvZGF5KCkge1xuICAgIC8vIElmIGJvdGggY2FsZW5kYXJzIGFyZSB2aXNpYmxlLCBzaG93IHRvZGF5IGluIHRoZSBzZWNvbmRhcnkgY2FsZW5kYXIgYW5kIHRoZSBtb250aCBiZWZvcmUgaW4gdGhlIHByaW1hcnkgY2FsZW5kYXIuXG4gICAgaWYgKHRoaXMuc2VsZWN0aW9uU3RyYXRlZ3kuc2hvd1NlY29uZGFyeUNhbGVuZGFyKSB7XG4gICAgICB0aGlzLnByaW1hcnlDYWxlbmRhclZpZXcgPSB7IG1vZGU6ICdkYXknLCBkYXRlOiBtb21lbnQoKS5zdWJ0cmFjdCgxLCAnbW9udGgnKS50b0RhdGUoKSB9O1xuICAgICAgdGhpcy5zZWNvbmRhcnlDYWxlbmRhclZpZXcgPSB7IG1vZGU6ICdkYXknLCBkYXRlOiBuZXcgRGF0ZSgpIH07XG4gICAgICAvLyBJZiB3ZSdyZSBpbiBhIHNpbmdsZSBkYXRlIG1vZGUsIHNob3cgdG9kYXkgaW4gdGhlIHByaW1hcnkgY2FsZW5kYXIuXG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucHJpbWFyeUNhbGVuZGFyVmlldyA9IHsgbW9kZTogJ2RheScsIGRhdGU6IG5ldyBEYXRlKCkgfTtcbiAgICB9XG4gICAgdGhpcy51cGRhdGVDYWxlbmRhck1pbk1heERhdGVzKCk7XG4gIH1cblxuICBwdWJsaWMgZ29Ub1F1aWNrU2VsZWN0RGF0ZSgpIHtcbiAgICBpZiAodGhpcy5xdWlja1NlbGVjdERhdGUpIHtcbiAgICAgIGNvbnN0IG5ld1NlbGVjdGlvbiA9IHRoaXMuc2VsZWN0aW9uU3RyYXRlZ3kuZ2V0U2VsZWN0aW9uRm9yUXVpY2tTZWxlY3REYXRlKHRoaXMucXVpY2tTZWxlY3REYXRlLCB0aGlzLmNhbGVuZGFyU2VsZWN0aW9uKTtcbiAgICAgIHRoaXMudXBkYXRlRm9ybU1vZGVsKG5ld1NlbGVjdGlvbik7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIG5leHRTZWxlY3Rpb24oKSB7XG4gICAgY29uc3QgbmV3U2VsZWN0aW9uID0gdGhpcy5zZWxlY3Rpb25TdHJhdGVneS5nZXROZXh0U2VsZWN0aW9uKHRoaXMuY2FsZW5kYXJTZWxlY3Rpb24pO1xuICAgIHRoaXMudXBkYXRlRm9ybU1vZGVsKG5ld1NlbGVjdGlvbik7XG4gIH1cblxuICBwdWJsaWMgcHJldmlvdXNTZWxlY3Rpb24oKSB7XG4gICAgY29uc3QgbmV3U2VsZWN0aW9uID0gdGhpcy5zZWxlY3Rpb25TdHJhdGVneS5nZXRQcmV2aW91c1NlbGVjdGlvbih0aGlzLmNhbGVuZGFyU2VsZWN0aW9uKTtcbiAgICB0aGlzLnVwZGF0ZUZvcm1Nb2RlbChuZXdTZWxlY3Rpb24pO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVGb3JtTW9kZWwodmFsdWU6IERhdGVJbnB1dC5TZWxlY3Rpb24gfCBudWxsKSB7XG4gICAgdGhpcy5mb3JtTW9kZWwucGF0Y2hWYWx1ZSh2YWx1ZSk7XG5cbiAgICAvLyBWYWxpZGF0ZSB0aGUgdGV4dGJveGVzIGFuZCBzeW5jIHRoZSBmb3JtIGVycm9yc1xuICAgIC8vIFdlIGRvIHRoaXMgYWZ0ZXIgcGF0Y2hpbmcgdGhlIGZvcm0gbW9kZWwgYmVjYXVzZSB0aGUgZm9ybSBtb2RlbCBwYXRjaCB3aWxsIHRyaWdnZXJcbiAgICAvLyB0aGUgZGF0ZSBmb3JtYXR0aW5nIGxvZ2ljIGFuZCBvdmVyd3JpdGUgYW55IGVycm9ycyBvbiB0aGUgY29udHJvbHMgZnJvbSBiZWZvcmUuXG4gICAgdGhpcy52YWxpZGF0ZVRleHRib3hlcygpO1xuICAgIHRoaXMuc3luY0Zvcm1FcnJvcnMoKTtcbiAgfVxuXG4gIHByaXZhdGUgb25Gb3JtTW9kZWxTdGF0dXNDaGFuZ2VzKCkge1xuICAgIC8vIEtlZXAgdGhlIHRleHRib3hDb250cm9sIGRpc2FibGVkIHN0YXR1cyBpbiBzeW5jIHdpdGggdGhlIGZvcm1Nb2RlbFxuICAgIHRoaXMuZm9ybU1vZGVsLnN0YXR1c0NoYW5nZXMucGlwZShcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXG4gICAgICB0YWtlVW50aWwodGhpcy5jb21wb25lbnREZXN0cm95ZWQpXG4gICAgKS5zdWJzY3JpYmUoc3RhdHVzID0+IHtcbiAgICAgIHRoaXMuc3luY1RleHRib3hDb250cm9sRGlzYWJsZWRTdGF0dXMoc3RhdHVzKTtcblxuICAgICAgaWYgKHRoaXMuaXNDYWxlbmRhck9wZW4pIHtcbiAgICAgICAgLy8gQXMgdmFsaWRhdGlvbiBtZXNzYWdlcyBhcHBlYXIvZGlzYXBwZWFyLCB0aGUgZGF0ZSBpbnB1dCBtYXkgaGF2ZSBzaGlmdGVkIHVwIG9yIGRvd24gb24gdGhlIHBhZ2UuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgb3ZlcmxheSBwb3NpdGlvbiB0byBlbnN1cmUgaXQncyBzdGlsbCBhbGlnbmVkIHdpdGggdGhlIHRleHRib3ggYW5kIG5vdCBibG9ja2luZyBpdC5cbiAgICAgICAgLy8gU2V0dGltZW91dCBpcyBuZWVkZWQgdG8gZW5zdXJlIHRoZSBvdmVybGF5IGlzIGJlaW5nIHVwZGF0ZWQgYWZ0ZXIgdGhlIG1lc3NhZ2UgaXMgcmVuZGVyZWQuXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICAgIHRoaXMub3ZlcmxheT8ub3ZlcmxheVJlZj8udXBkYXRlUG9zaXRpb24oKTtcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIG9uRm9ybU1vZGVsVmFsdWVDaGFuZ2VzKCkge1xuICAgIC8vIFVwZGF0ZSB0aGUgY2FsZW5kYXIgc2VsZWN0aW9uIHRleHRib3ggdmFsdWUgd2l0aCBhIGZvcm1hdHRlZCBkYXRlIHdoZW4gdGhlIGZvcm0gbW9kZWwgY2hhbmdlcy5cbiAgICAvLyBUaGlzIGlzIHRyaWdnZXJlZCBieSB0aGUgdXNlciBzZWxlY3RpbmcgYSBkYXRlIGZyb20gdGhlIGNhbGVuZGFyIG9yIHdoZW4gdGhlIHRleHRib3ggaXMgYmx1cnJlZC5cbiAgICB0aGlzLmZvcm1Nb2RlbC52YWx1ZUNoYW5nZXMucGlwZShcbiAgICAgIHRha2VVbnRpbCh0aGlzLmNvbXBvbmVudERlc3Ryb3llZClcbiAgICApLnN1YnNjcmliZSh2YWx1ZSA9PiB7XG4gICAgICBjb25zdCBkaXNwbGF5VmFsdWUgPSB0aGlzLnNlbGVjdGlvblN0cmF0ZWd5LmZvcm1hdFNlbGVjdGlvbih2YWx1ZSk7XG4gICAgICAvLyBEb24ndCBlbWl0IGFuIGV2ZW50IHdoZW4gc2V0dGluZyB0aGUgdGV4dGJveCB2YWx1ZSB0byBhdm9pZCBjaXJjdWxhciB1cGRhdGVzIGJldHdlZW4gdGhlIHRleHRib3ggYW5kIGZvcm0gbW9kZWwuXG4gICAgICB0aGlzLnRleHRib3hHcm91cC5wYXRjaFZhbHVlKGRpc3BsYXlWYWx1ZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xuICAgICAgdGhpcy51cGRhdGVDYWxlbmRhcnModmFsdWUpO1xuICAgICAgdGhpcy51cGRhdGVTdGVwcGVycyh2YWx1ZSk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIG9uVGV4dGJveFZhbHVlQ2hhbmdlcygpIHtcbiAgICAvLyBVcGRhdGUgdGhlIGNhbGVuZGFyIHNlbGVjdGlvbiB3aGVuIHRoZSB0ZXh0Ym94IHZhbHVlIGNoYW5nZXMgdG8gdXBkYXRlIHRoZSBjYWxlbmRhci5cbiAgICAvLyBXZSBkb24ndCBwYXRjaCB0aGUgZm9ybU1vZGVsIGhlcmUgYmVjYXVzZSB3ZSBkb24ndCB3YW50IHRvIHRyaWdnZXIgdGhlXG4gICAgLy8gZGF0ZSBmb3JtYXR0aW5nIGxvZ2ljIGFuZCBvdmVyd3JpdGUgdGhlIHVzZXIncyBpbnB1dC5cbiAgICAvLyBXZSdsbCBkbyB0aGF0IHdoZW4gdGhlIHVzZXIgYmx1cnMgb3V0IG9mIHRoZSB0ZXh0Ym94LiBTZWUgb25UZXh0Ym94Qmx1cigpXG4gICAgdGhpcy50ZXh0Ym94R3JvdXAuY29udHJvbHMudGV4dGJveC52YWx1ZUNoYW5nZXMucGlwZShcbiAgICAgIGRlYm91bmNlVGltZSgzMDApLFxuICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSxcbiAgICAgIHRha2VVbnRpbCh0aGlzLmNvbXBvbmVudERlc3Ryb3llZClcbiAgICApLnN1YnNjcmliZSgoKSA9PiB7XG4gICAgICBjb25zdCBvcHRpb25zOiBEYXRlSW5wdXQuUGFyc2luZ09wdGlvbnMgPSB7IHNoaWZ0VG9DdXJyZW50WWVhcklmQmVsb3c6IHRoaXMubWluRGF0ZSB9O1xuICAgICAgY29uc3QgbmV3U2VsZWN0aW9uID0gdGhpcy5zZWxlY3Rpb25TdHJhdGVneS5wYXJzZVRleHRib3hWYWx1ZXModGhpcy50ZXh0Ym94R3JvdXAudmFsdWUsIHRoaXMucGFyc2VGb3JtYXRzLCBvcHRpb25zKTtcblxuICAgICAgLy8gQ2FsZW5kYXIgc2VsZWN0aW9uIHdpbGwgYmUgbnVsbCBpZiB0aGUgZGF0ZXMgYXJlIGludmFsaWQuIERvbid0IHVwZGF0ZSB0aGUgY2FsZW5kYXJzIGluIHRoaXMgY2FzZS5cbiAgICAgIGlmIChuZXdTZWxlY3Rpb24pIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhclNlbGVjdGlvbiA9IG5ld1NlbGVjdGlvbjtcbiAgICAgICAgdGhpcy51cGRhdGVQcmltYXJ5Q2FsZW5kYXIodGhpcy5jYWxlbmRhclNlbGVjdGlvbiwgdGhpcy5zZWxlY3Rpb25TdHJhdGVneS5zaG93U2Vjb25kYXJ5Q2FsZW5kYXIpO1xuICAgICAgICB0aGlzLnVwZGF0ZUNhbGVuZGFyTWluTWF4RGF0ZXMoKTtcbiAgICAgIH1cbiAgICB9KTtcblxuICAgIC8vIFRoZSBzZWNvbmQgdGV4dGJveCBpcyBvbmx5IHVzZWQgaW4gbGFzdDdEYXlzLCBsYXN0MjhEYXlzLCBhbmQgcmFuZ2UgbW9kZXMuXG4gICAgdGhpcy50ZXh0Ym94R3JvdXAuY29udHJvbHMudGV4dGJveDIudmFsdWVDaGFuZ2VzLnBpcGUoXG4gICAgICBkZWJvdW5jZVRpbWUoMzAwKSxcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXG4gICAgICB0YWtlVW50aWwodGhpcy5jb21wb25lbnREZXN0cm95ZWQpXG4gICAgKS5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgY29uc3Qgb3B0aW9uczogRGF0ZUlucHV0LlBhcnNpbmdPcHRpb25zID0geyBzaGlmdFRvQ3VycmVudFllYXJJZkJlbG93OiB0aGlzLm1pbkRhdGUsIHBhcnNlRnJvbUVuZDogdHJ1ZSB9O1xuICAgICAgY29uc3QgbmV3U2VsZWN0aW9uID0gdGhpcy5zZWxlY3Rpb25TdHJhdGVneS5wYXJzZVRleHRib3hWYWx1ZXModGhpcy50ZXh0Ym94R3JvdXAudmFsdWUsIHRoaXMucGFyc2VGb3JtYXRzLCBvcHRpb25zKTtcblxuICAgICAgLy8gQ2FsZW5kYXIgc2VsZWN0aW9uIHdpbGwgYmUgbnVsbCBpZiB0aGUgZGF0ZXMgYXJlIGludmFsaWQuIERvbid0IHVwZGF0ZSB0aGUgY2FsZW5kYXJzIGluIHRoaXMgY2FzZS5cbiAgICAgIGlmIChuZXdTZWxlY3Rpb24pIHtcbiAgICAgICAgdGhpcy5jYWxlbmRhclNlbGVjdGlvbiA9IG5ld1NlbGVjdGlvbjtcbiAgICAgICAgLy8gVGhlIHNlY29uZGFyeSBjYWxlbmRhciBpcyBvbmx5IHNob3duIGluIHJhbmdlIG1vZGUuIFVwZGF0ZSB0aGUgcHJpbWFyeSBjYWxlbmRhciBpZiB3ZSdyZSBub3QgaW4gcmFuZ2UgbW9kZS5cbiAgICAgICAgaWYgKHRoaXMuc2VsZWN0aW9uU3RyYXRlZ3kuc2hvd1NlY29uZGFyeUNhbGVuZGFyKSB7XG4gICAgICAgICAgdGhpcy51cGRhdGVTZWNvbmRhcnlDYWxlbmRhcih0aGlzLmNhbGVuZGFyU2VsZWN0aW9uLCB0cnVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aGlzLnVwZGF0ZVByaW1hcnlDYWxlbmRhcih0aGlzLmNhbGVuZGFyU2VsZWN0aW9uKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnVwZGF0ZUNhbGVuZGFyTWluTWF4RGF0ZXMoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgc3luY1RleHRib3hDb250cm9sRGlzYWJsZWRTdGF0dXMoc3RhdHVzOiBGb3JtQ29udHJvbFN0YXR1cykge1xuICAgIC8vIFRoZSB0ZXh0Ym94IHNob3VsZCBvbmx5IGJlIGRpc2FibGVkIGlmIHRoZSBmb3JtIG1vZGVsIGlzIGRpc2FibGVkLlxuICAgIC8vIEFsbCBvdGhlciBzdGF0dXNlcyBhcmUgY29uc2lkZXJlZCBlbmFibGVkLlxuICAgIGlmIChzdGF0dXMgPT09ICdESVNBQkxFRCcgJiYgdGhpcy50ZXh0Ym94R3JvdXAuZW5hYmxlZCkge1xuICAgICAgdGhpcy50ZXh0Ym94R3JvdXAuZGlzYWJsZSgpO1xuICAgIH0gZWxzZSBpZiAoc3RhdHVzICE9PSAnRElTQUJMRUQnICYmIHRoaXMudGV4dGJveEdyb3VwLmRpc2FibGVkKSB7XG4gICAgICB0aGlzLnRleHRib3hHcm91cC5lbmFibGUoKTtcbiAgICB9XG4gIH07XG5cbiAgcHJpdmF0ZSBzeW5jRm9ybUVycm9ycygpIHtcbiAgICAvLyBTdGFydCB3aXRoIHRoZSBleGlzdGluZyBmb3JtIG1vZGVsIGVycm9yc1xuICAgIGxldCBlcnJvcnMgPSB0aGlzLmZvcm1Nb2RlbC5lcnJvcnM7XG5cbiAgICAvLyBBZGQgdGhlIGVycm9ycyBmcm9tIHRoZSB0ZXh0Ym94ZXMgaWYgdGhleSBleGlzdFxuICAgIGlmICh0aGlzLnRleHRib3hHcm91cC5jb250cm9scy50ZXh0Ym94LmVycm9ycykge1xuICAgICAgZXJyb3JzID0geyAuLi5lcnJvcnMsIC4uLnRoaXMudGV4dGJveEdyb3VwLmNvbnRyb2xzLnRleHRib3guZXJyb3JzIH07XG4gICAgfVxuICAgIGlmICh0aGlzLnRleHRib3hHcm91cC5jb250cm9scy50ZXh0Ym94Mi5lcnJvcnMpIHtcbiAgICAgIGVycm9ycyA9IHsgLi4uZXJyb3JzLCAuLi50aGlzLnRleHRib3hHcm91cC5jb250cm9scy50ZXh0Ym94Mi5lcnJvcnMgfTtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgdGhlIGZvcm0gbW9kZWwncyBlcnJvcnMgd2l0aCB0aGUgY29tYmluZWQgZXJyb3JzXG4gICAgdGhpcy5mb3JtTW9kZWwuc2V0RXJyb3JzKGVycm9ycyk7XG5cbiAgICAvLyBVcGRhdGUgdGhlIGZvcm0gbW9kZWwncyB0b3VjaGVkIGFuZCBkaXJ0eSBzdGF0dXMgYmFzZWQgb24gdGhlIHRleHRib3gncyBzdGF0dXMuXG4gICAgLy8gU2luY2UgdGhlIHVzZXIgaW50ZXJhY3RzIHdpdGggYSBjb250cm9sIHRoYXQgaXMgaW50ZXJuYWwgdG8gdGhpcyBjb21wb25lbnQsIHRoZVxuICAgIC8vIGZvcm0gbW9kZWwncyBzdGF0dXMgd29uJ3QgYmUgdXBkYXRlZCBhdXRvbWF0aWNhbGx5LlxuICAgIGlmICh0aGlzLnRleHRib3hHcm91cC50b3VjaGVkICYmICF0aGlzLmZvcm1Nb2RlbC50b3VjaGVkKSB7XG4gICAgICB0aGlzLmZvcm1Nb2RlbC5tYXJrQXNUb3VjaGVkKCk7XG4gICAgfVxuICAgIGlmICh0aGlzLnRleHRib3hHcm91cC5kaXJ0eSAmJiAhdGhpcy5mb3JtTW9kZWwuZGlydHkpIHtcbiAgICAgIHRoaXMuZm9ybU1vZGVsLm1hcmtBc0RpcnR5KCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFxuICAgKiBVcGRhdGVzIHRoZSBkYXRlIHBhcnNpbmcgZm9ybWF0cyBhbmQgcGxhY2Vob2xkZXIgYmFzZWQgb24gdGhlIHVzZXIncyBkaXNwbGF5IHByZWZlcmVuY2UuXG4gICAqIE5PVEU6IFRoaXMgaXMgYXN5bmMgYmVjYXVzZSB3ZSdyZSByZXRyaWV2aW5nIHRoZSB1c2VyJ3MgcHJlZmVyZW5jZXMuIFdlJ3JlIG5vdCBhd2FpdGluZyB0aGUgcmVzdWx0XG4gICAqIGJlY2F1c2UgdGhlIG9ubHkgbG9naWMgdGhhdCBkZXBlbmRzIG9uIHRoaXMgaXMgdGhlIHRleHQgYm94IGRhdGUgcGFyc2luZyBsb2dpYyBhbmQgcGxhY2Vob2xkZXIuXG4gICAqIE91ciBmb3JtcyBzaG91bGQgYWx3YXlzIGJlIGJlaGluZCBhIHBlbmRpbmcgb3ZlcmxheSwgc28gdGhlIHVzZXIgd29uJ3QgYmUgYWJsZSB0byBpbnRlcmFjdCB3aXRoIHRoZVxuICAgKiBmb3JtIHVudGlsIHRoZSB1c2VyIGlzIGxvYWRlZCBhbnl3YXkuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIHNldERhdGVGb3JtYXRzKCkge1xuICAgIGNvbnN0IHsgcHJlZmVyZW5jZSB9ID0gYXdhaXQgbGFzdFZhbHVlRnJvbSh0aGlzLnVzZXJQcmVmZXJlbmNlU2VydmljZS5nZXRQcmVmZXJlbmNlcygpKTtcbiAgICBjb25zdCBkYXRlRm9ybWF0ID0gcHJlZmVyZW5jZT8uZGF0ZUZvcm1hdDtcbiAgICB0aGlzLnBsYWNlaG9sZGVyID0gZGF0ZUZvcm1hdCA/PyB0aGlzLnBsYWNlaG9sZGVyO1xuICAgIHRoaXMucGFyc2VGb3JtYXRzID0gRGF0ZVRpbWVIZWxwZXIuZ2V0TW9tZW50UGFyc2VGb3JtYXRzKGRhdGVGb3JtYXQpO1xuICB9XG5cbiAgLyoqIEZvY3VzZXMgdGhlIGRhdGUgaW5wdXQuICovXG4gIHByaXZhdGUgZm9jdXNJbnB1dCgpIHtcbiAgICB0aGlzLmNvbnRyb2xzPy5mb2N1cygpO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRTZWxlY3Rpb25Nb2RlKG1vZGU6IERhdGVJbnB1dC5TZWxlY3Rpb25Nb2RlKSB7XG4gICAgdGhpcy5zZWxlY3Rpb25Nb2RlID0gbW9kZTtcbiAgICB0aGlzLnNlbGVjdGlvblN0cmF0ZWd5ID0gdGhpcy5zZWxlY3Rpb25TdHJhdGVnaWVzW21vZGVdO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldHMgdGhlIG1heCBkYXRlIGZvciB0aGUgcHJpbWFyeSBjYWxlbmRhciBhbmQgdGhlIG1pbiBkYXRlIGZvciB0aGUgc2Vjb25kYXJ5IGNhbGVuZGFyIGJhc2VkXG4gICAqIG9uIHRoZSBjdXJyZW50IHZpZXdzIGluIGVhY2guIFRoaXMgcHJldmVudHMgdGhlIHVzZXIgZnJvbSBtb3ZpbmcgdGhlIGNhbGVuZGFycyBvdXQgb2Ygb3JkZXIuXG4gICAqL1xuICBwcml2YXRlIHVwZGF0ZUNhbGVuZGFyTWluTWF4RGF0ZXMoKSB7XG4gICAgLy8gT25seSB1cGRhdGUgdGhlIG1pbi9tYXggZGF0ZXMgd2hlbiB0aGUgdmlldyBtb2RlIGlzICdkYXknLlxuICAgIC8vIFdoZW4gYSBjYWxlbmRhciBpcyBpbiBhIG1vbnRoIG9yIHllYXIgdmlldyBtb2RlLCB0aGUgdmlldyBkYXRlcyBhdCB0aGUgYmVnaW5uaW5nIG9mIHRoZSB5ZWFyLlxuICAgIC8vIFRoaXMgd291bGQgY2F1c2UgdGhlIGRhdGVzIGluIHRoZSBvdGhlciBjYWxlbmRhciB0byBiZSB1bnNlbGVjdGFibGUgaWYgd2Ugd2VyZSB0b1xuICAgIC8vIHVwZGF0ZSB0aGUgbWluL21heCBkYXRlcyBpbiB0aGVzZSBjYXNlcy5cbiAgICBpZiAodGhpcy5wcmltYXJ5Q2FsZW5kYXJWaWV3Py5tb2RlID09PSAnZGF5Jykge1xuICAgICAgdGhpcy5zZWNvbmRhcnlDYWxlbmRhck1pbkRhdGUgPSBtb21lbnQodGhpcy5wcmltYXJ5Q2FsZW5kYXJWaWV3Py5kYXRlKS5hZGQoMSwgJ21vbnRoJykuc3RhcnRPZignbW9udGgnKS50b0RhdGUoKTtcbiAgICB9XG4gICAgaWYgKHRoaXMuc2Vjb25kYXJ5Q2FsZW5kYXJWaWV3Py5tb2RlID09PSAnZGF5Jykge1xuICAgICAgdGhpcy5wcmltYXJ5Q2FsZW5kYXJNYXhEYXRlID0gbW9tZW50KHRoaXMuc2Vjb25kYXJ5Q2FsZW5kYXJWaWV3Py5kYXRlKS5zdWJ0cmFjdCgxLCAnbW9udGgnKS5lbmRPZignbW9udGgnKS50b0RhdGUoKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZUNhbGVuZGFycyhzZWxlY3Rpb246IERhdGVJbnB1dC5TZWxlY3Rpb24gfCBudWxsKSB7XG4gICAgdGhpcy5jYWxlbmRhclNlbGVjdGlvbiA9IHNlbGVjdGlvbjtcbiAgICB0aGlzLnVwZGF0ZVByaW1hcnlDYWxlbmRhcihzZWxlY3Rpb24pO1xuICAgIC8vIE9ubHkgc2hpZnQgdGhlIHByaW1hcnkgY2FsZW5kYXIgaWYgd2UncmUgc2hvd2luZyB0aGUgc2Vjb25kYXJ5IGNhbGVuZGFyXG4gICAgdGhpcy51cGRhdGVTZWNvbmRhcnlDYWxlbmRhcihzZWxlY3Rpb24sIHRoaXMuc2VsZWN0aW9uU3RyYXRlZ3kuc2hvd1NlY29uZGFyeUNhbGVuZGFyKTtcblxuICAgIHRoaXMudXBkYXRlQ2FsZW5kYXJNaW5NYXhEYXRlcygpO1xuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVQcmltYXJ5Q2FsZW5kYXIoc2VsZWN0aW9uOiBEYXRlSW5wdXQuU2VsZWN0aW9uIHwgbnVsbCwgc2hpZnRTZWNvbmRhcnk6IGJvb2xlYW4gPSBmYWxzZSkge1xuICAgIHRoaXMucHJpbWFyeUNhbGVuZGFyVmlldyA9IHRoaXMuc2VsZWN0aW9uU3RyYXRlZ3kuZ2V0UHJpbWFyeUNhbGVuZGFyVmlldyhzZWxlY3Rpb24sIHRoaXMubWluRGF0ZSwgdGhpcy5tYXhEYXRlLCB0aGlzLnByaW1hcnlDYWxlbmRhclZpZXcpO1xuXG4gICAgLy8gV2hlbiBlbnRlcmluZyBhIGRhdGUgaW50byB0aGUgZmlyc3QgdGV4dGJveCwgd2UgcmVhbGx5IG9ubHkgd2FudCB0byB1cGRhdGUgdGhlIHByaW1hcnkgY2FsZW5kYXIuXG4gICAgLy8gSG93ZXZlciwgaXQncyBwb3NzaWJsZSB0aGF0IHRoZSBuZXcgZGF0ZSBpcyBhZnRlciB0aGUgc2Vjb25kYXJ5IGNhbGVuZGFyJ3MgZGF0ZS4gSW4gdGhpcyBjYXNlLFxuICAgIC8vIFdlIHdhbnQgdG8gc2hpZnQgdGhlIHNlY29uZGFyeSBjYWxlbmRhciBzbyB0aGUgY2FsZW5kYXJzIHN0YXkgaW4gb3JkZXIuXG4gICAgaWYgKHNoaWZ0U2Vjb25kYXJ5ICYmIHRoaXMuc2Vjb25kYXJ5Q2FsZW5kYXJWaWV3KSB7XG4gICAgICBpZiAobW9tZW50KHRoaXMucHJpbWFyeUNhbGVuZGFyVmlldy5kYXRlKS5pc1NhbWVPckFmdGVyKHRoaXMuc2Vjb25kYXJ5Q2FsZW5kYXJWaWV3LmRhdGUsICdtb250aCcpKSB7XG4gICAgICAgIGxldCBuZXdTZWNvbmRhcnlEYXRlID0gbW9tZW50KHRoaXMucHJpbWFyeUNhbGVuZGFyVmlldy5kYXRlKS5hZGQoMSwgJ21vbnRoJykudG9EYXRlKCk7XG4gICAgICAgIHRoaXMuc2Vjb25kYXJ5Q2FsZW5kYXJWaWV3ID0geyBtb2RlOiB0aGlzLnNlbGVjdGlvblN0cmF0ZWd5LnNlbGVjdGlvblZpZXdNb2RlLCBkYXRlOiBuZXdTZWNvbmRhcnlEYXRlIH07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVTZWNvbmRhcnlDYWxlbmRhcihzZWxlY3Rpb246IERhdGVJbnB1dC5TZWxlY3Rpb24gfCBudWxsLCBzaGlmdFByaW1hcnk6IGJvb2xlYW4gPSBmYWxzZSkge1xuICAgIHRoaXMuc2Vjb25kYXJ5Q2FsZW5kYXJWaWV3ID0gdGhpcy5zZWxlY3Rpb25TdHJhdGVneS5nZXRTZWNvbmRhcnlDYWxlbmRhclZpZXcoc2VsZWN0aW9uLCB0aGlzLm1pbkRhdGUsIHRoaXMubWF4RGF0ZSwgdGhpcy5zZWNvbmRhcnlDYWxlbmRhclZpZXcpO1xuXG4gICAgLy8gV2hlbiBlbnRlcmluZyBhIGRhdGUgaW50byB0aGUgc2Vjb25kIHRleHRib3gsIHdlIHJlYWxseSBvbmx5IHdhbnQgdG8gdXBkYXRlIHRoZSBzZWNvbmRhcnkgY2FsZW5kYXIuXG4gICAgLy8gSG93ZXZlciwgaXQncyBwb3NzaWJsZSB0aGF0IHRoZSBuZXcgZGF0ZSBpcyBiZWZvcmUgdGhlIHByaW1hcnkgY2FsZW5kYXIncyBkYXRlLiBJbiB0aGlzIGNhc2UsXG4gICAgLy8gV2Ugd2FudCB0byBzaGlmdCB0aGUgcHJpbWFyeSBjYWxlbmRhciBzbyB0aGUgY2FsZW5kYXJzIHN0YXkgaW4gb3JkZXIuXG4gICAgaWYgKHNoaWZ0UHJpbWFyeSAmJiB0aGlzLnByaW1hcnlDYWxlbmRhclZpZXcpIHtcbiAgICAgIGlmIChtb21lbnQodGhpcy5wcmltYXJ5Q2FsZW5kYXJWaWV3LmRhdGUpLmlzU2FtZU9yQWZ0ZXIodGhpcy5zZWNvbmRhcnlDYWxlbmRhclZpZXcuZGF0ZSwgJ21vbnRoJykpIHtcbiAgICAgICAgbGV0IG5ld1ByaW1hcnlEYXRlID0gbW9tZW50KHRoaXMuc2Vjb25kYXJ5Q2FsZW5kYXJWaWV3LmRhdGUpLnN1YnRyYWN0KDEsICdtb250aCcpLnRvRGF0ZSgpO1xuICAgICAgICB0aGlzLnByaW1hcnlDYWxlbmRhclZpZXcgPSB7IG1vZGU6IHRoaXMuc2VsZWN0aW9uU3RyYXRlZ3kuc2VsZWN0aW9uVmlld01vZGUsIGRhdGU6IG5ld1ByaW1hcnlEYXRlIH07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB1cGRhdGVTdGVwcGVycyh2YWx1ZTogRGF0ZUlucHV0LlNlbGVjdGlvbiB8IG51bGwpIHtcbiAgICAvLyBEaXNhYmxlIHRoZSBzdGVwcGVycyBpZiB3ZSBlaXRoZXIgZG9uJ3QgaGF2ZSBhIHNlbGVjdGlvbiBvciBvbmx5IGhhdmUgb25lIGRhdGUgaW4gdGhlIHNlbGVjdGlvbi5cbiAgICBpZiAoXG4gICAgICAhdmFsdWUgfHxcbiAgICAgIChEYXRlSW5wdXQuaXNTZWxlY3Rpb25TaW5nbGVEYXRlKHZhbHVlKSAmJiB0aGlzLnNlbGVjdGlvbk1vZGUgIT09ICdkYXknKSB8fFxuICAgICAgKERhdGVJbnB1dC5pc1NlbGVjdGlvblJhbmdlKHZhbHVlKSAmJiAoIXZhbHVlLnN0YXJ0IHx8ICF2YWx1ZS5lbmQpKVxuICAgICkge1xuICAgICAgdGhpcy5kaXNhYmxlU3RlcHBlcnMgPSB0cnVlO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmRpc2FibGVTdGVwcGVycyA9IGZhbHNlO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVUZXh0Ym94ZXMoKSB7XG4gICAgY29uc3QgY29udHJvbCA9IHRoaXMudGV4dGJveEdyb3VwLmNvbnRyb2xzLnRleHRib3g7XG4gICAgY29uc3QgY29udHJvbDIgPSB0aGlzLnRleHRib3hHcm91cC5jb250cm9scy50ZXh0Ym94MjtcblxuICAgIC8vIFRoZSBmaXJzdCB0ZXh0Ym94IHNob3VsZCBvbmx5IGhhdmUgdGhlIHJlcXVpcmVkIGVycm9yIGlmIGl0J3MgZW1wdHkgYW5kIHRoZSBkYXRlIGlucHV0IGlzIHJlcXVpcmVkLFxuICAgIC8vIG9yIGlmIHRoZSBkYXRlIGlucHV0IGlzIG5vdCByZXF1aXJlZCBhbmQgdGhlIHNlY29uZCBjb250cm9sIGlzIHZpc2libGUgYW5kIGhhcyBhIHZhbHVlIChtZWFuaW5nIGEgcGFydGlhbCByYW5nZSlcbiAgICBpZiAoXG4gICAgICAhY29udHJvbC52YWx1ZSAmJlxuICAgICAgKHRoaXMucmVxdWlyZWQgfHwgKGNvbnRyb2wyLnZhbHVlICYmIHRoaXMuc2VsZWN0aW9uU3RyYXRlZ3kuc2hvd1NlY29uZGFyeVRleHRib3gpKVxuICAgICkge1xuICAgICAgY29udHJvbC5zZXRFcnJvcnMoeyByZXF1aXJlZDogdHJ1ZSB9KTtcbiAgICB9XG4gICAgLy8gVGhlIHNhbWUgaWRlYSBhcHBsaWVzIHRvIHRoZSBzZWNvbmQgdGV4dGJveCwgYnV0IG9ubHkgaWYgaXQncyB2aXNpYmxlXG4gICAgaWYgKFxuICAgICAgdGhpcy5zZWxlY3Rpb25TdHJhdGVneS5zaG93U2Vjb25kYXJ5VGV4dGJveCAmJlxuICAgICAgIWNvbnRyb2wyLnZhbHVlICYmXG4gICAgICAodGhpcy5yZXF1aXJlZCB8fCBjb250cm9sLnZhbHVlKVxuICAgICkge1xuICAgICAgY29udHJvbDIuc2V0RXJyb3JzKHsgcmVxdWlyZWQ6IHRydWUgfSk7XG4gICAgfVxuXG4gICAgaWYgKGNvbnRyb2wudmFsdWUpIHtcbiAgICAgIGNvbnN0IGVycm9ycyA9IHRoaXMudmFsaWRhdGVEYXRlU3RyaW5nKGNvbnRyb2wudmFsdWUpO1xuICAgICAgaWYgKGVycm9ycykge1xuICAgICAgICBjb250cm9sLnNldEVycm9ycyhlcnJvcnMpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChjb250cm9sMi52YWx1ZSAmJiB0aGlzLnNlbGVjdGlvblN0cmF0ZWd5LnNob3dTZWNvbmRhcnlUZXh0Ym94KSB7XG4gICAgICBjb25zdCBlcnJvcnMgPSB0aGlzLnZhbGlkYXRlRGF0ZVN0cmluZyhjb250cm9sMi52YWx1ZSk7XG4gICAgICBpZiAoZXJyb3JzKSB7XG4gICAgICAgIGNvbnRyb2wyLnNldEVycm9ycyhlcnJvcnMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgdmFsaWRhdGVEYXRlU3RyaW5nKGRhdGU6IHN0cmluZyk6IFZhbGlkYXRpb25FcnJvcnMgfCBudWxsIHtcbiAgICBjb25zdCB2YWx1ZSA9IHRoaXMuc2VsZWN0aW9uU3RyYXRlZ3kucGFyc2VTdHJpbmcoZGF0ZSwgdGhpcy5wYXJzZUZvcm1hdHMpO1xuICAgIGlmICh2YWx1ZSkge1xuICAgICAgLy8gV2UncmUgdXNpbmcgdGhlIHZpZXcgbW9kZSBhcyB0aGUgZ3JhbnVsYXJpdHkuIFdlIGRvbid0IHdhbnQgdG8gaW52YWxpZGF0ZVxuICAgICAgLy8gdGhlIGRhdGUgaW4gdGhlIGNhc2Ugd2hlcmUgeW91IGhhdmUgYSBtb250aC9xdWFydGVyL3llYXIgc2VsZWN0ZWQgYW5kIHRoZSBtaW5cbiAgICAgIC8vIG9yIG1heCBkYXRlIGlzIHNvbWV3aGVyZSB3aXRoaW4gdGhhdCBtb250aC9xdWFydGVyL3llYXIuXG4gICAgICBpZiAobW9tZW50KHZhbHVlKS5pc0JlZm9yZSh0aGlzLm1pbkRhdGUsIHRoaXMuc2VsZWN0aW9uU3RyYXRlZ3kuc2VsZWN0aW9uVmlld01vZGUpKSB7XG4gICAgICAgIHJldHVybiB7IG1pbkRhdGU6IHsgbWluVmFsdWU6IHRoaXMubWluRGF0ZSB9IH07XG4gICAgICB9IGVsc2UgaWYgKG1vbWVudCh2YWx1ZSkuaXNBZnRlcih0aGlzLm1heERhdGUsIHRoaXMuc2VsZWN0aW9uU3RyYXRlZ3kuc2VsZWN0aW9uVmlld01vZGUpKSB7XG4gICAgICAgIHJldHVybiB7IG1heERhdGU6IHsgbWF4VmFsdWU6IHRoaXMubWF4RGF0ZSB9IH07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cbn1cbiIsIjxsYWJlbCAqbmdJZj1cImxhYmVsXCI+XG4gIDxzcGFuPnt7bGFiZWwgfCB0cmFuc2xhdGV9fTwvc3Bhbj5cbiAgPHNwYW4gKm5nSWY9XCJ2YWxpZGF0aW9uRXJyb3JzLmxlbmd0aCA+IDAgJiYgZm9ybU1vZGVsLnRvdWNoZWQgJiYgZm9ybU1vZGVsLmludmFsaWRcIj4mbmJzcDt7e3ZhbGlkYXRpb25FcnJvcnN9fTwvc3Bhbj5cbiAgPGVjLWhlbHAtcG9wb3ZlciBpZD1cInt7aWR9fV9oZWxwUG9wb3ZlclwiXG4gICAgICAgICAgICAgICAgICAgKm5nSWY9XCJoZWxwUG9wb3ZlclwiXG4gICAgICAgICAgICAgICAgICAgY2xhc3M9XCJkLWlubGluZS1ibG9jayBteS1uMyBteC1uMVwiXG4gICAgICAgICAgICAgICAgICAgdGV4dD1cInt7aGVscFBvcG92ZXIgfCB0cmFuc2xhdGV9fVwiXG4gICAgICAgICAgICAgICAgICAgY29udGVudFBvc2l0aW9uPVwie3toZWxwUG9wb3ZlclBvc2l0aW9ufX1cIj5cbiAgPC9lYy1oZWxwLXBvcG92ZXI+XG48L2xhYmVsPlxuXG48ZGl2IGNsYXNzPVwiZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlclwiXG4gICAgIFtlY0tleWJvYXJkTmF2Q29udGFpbmVyXT1cImlzQ2FsZW5kYXJPcGVuXCJcbiAgICAgW3RhYmluZGV4XT1cInRhYmluZGV4XCJcbiAgICAgI2NvbnRyb2xzPVwiZWNLZXlib2FyZE5hdkNvbnRhaW5lclwiXG4gICAgIChmb2N1c091dEVuZCk9XCJvbkNvbnRyb2xzRm9jdXNPdXRFbmQoKVwiPlxuICA8ZWMtZm9ybS1jb250cm9sIGlkPVwie3tpZH19XCJcbiAgICAgICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwicmVxdWlyZWRcIlxuICAgICAgICAgICAgICAgICAgIFthdXRvZm9jdXNdPVwiYXV0b2ZvY3VzXCJcbiAgICAgICAgICAgICAgICAgICBbcGVuZGluZ109XCJwZW5kaW5nXCJcbiAgICAgICAgICAgICAgICAgICBbcmVhZG9ubHldPVwicmVhZG9ubHlcIlxuICAgICAgICAgICAgICAgICAgIChhY3Rpb25DbGlja2VkKT1cImlzQ2FsZW5kYXJPcGVuID0gIWlzQ2FsZW5kYXJPcGVuXCJcbiAgICAgICAgICAgICAgICAgICBbc2hvd0NsZWFyXT1cImZhbHNlXCJcbiAgICAgICAgICAgICAgICAgICBbdGFiaW5kZXhdPVwidGFiaW5kZXhcIlxuICAgICAgICAgICAgICAgICAgIGFjdGlvbkljb249XCJpY29uLWRhdGVcIlxuICAgICAgICAgICAgICAgICAgIGNka092ZXJsYXlPcmlnaW5cbiAgICAgICAgICAgICAgICAgICAjb3ZlcmxheU9yaWdpbj1cImNka092ZXJsYXlPcmlnaW5cIlxuICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZmxleC1ncm93XCJcbiAgICAgICAgICAgICAgICAgICBzdHlsZT1cImhlaWdodDogMnJlbTtcIj5cbiAgICA8aW5wdXQgaWQ9XCJ7e2lkfX1faW5wdXRcIlxuICAgICAgICAgICB0eXBlPVwidGV4dFwiXG4gICAgICAgICAgIHBsYWNlaG9sZGVyPVwie3twbGFjZWhvbGRlcn19XCJcbiAgICAgICAgICAgdGFiaW5kZXg9XCJ7e3RhYmluZGV4fX1cIlxuICAgICAgICAgICBbZm9ybUNvbnRyb2xdPVwidGV4dGJveEdyb3VwLmdldCgndGV4dGJveCcpXCJcbiAgICAgICAgICAgKGJsdXIpPVwib25UZXh0Ym94Qmx1cigpXCI+XG4gIDwvZWMtZm9ybS1jb250cm9sPlxuXG4gIDxuZy1jb250YWluZXIgKm5nSWY9XCJzZWxlY3Rpb25TdHJhdGVneS5zaG93U2Vjb25kYXJ5VGV4dGJveFwiPlxuICAgIDxzcGFuIGNsYXNzPVwiZmxleC1zaHJpbmsgbXgtMVwiPiZuZGFzaDs8L3NwYW4+XG4gICAgPGVjLWZvcm0tY29udHJvbCBpZD1cInt7aWR9fV9jb250cm9sMlwiXG4gICAgICAgICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwicmVxdWlyZWRcIlxuICAgICAgICAgICAgICAgICAgICAgW2F1dG9mb2N1c109XCJhdXRvZm9jdXNcIlxuICAgICAgICAgICAgICAgICAgICAgW3BlbmRpbmddPVwicGVuZGluZ1wiXG4gICAgICAgICAgICAgICAgICAgICBbcmVhZG9ubHldPVwicmVhZG9ubHlcIlxuICAgICAgICAgICAgICAgICAgICAgKGFjdGlvbkNsaWNrZWQpPVwiaXNDYWxlbmRhck9wZW4gPSAhaXNDYWxlbmRhck9wZW5cIlxuICAgICAgICAgICAgICAgICAgICAgW3Nob3dDbGVhcl09XCJmYWxzZVwiXG4gICAgICAgICAgICAgICAgICAgICBbdGFiaW5kZXhdPVwidGFiaW5kZXhcIlxuICAgICAgICAgICAgICAgICAgICAgYWN0aW9uSWNvbj1cImljb24tZGF0ZVwiXG4gICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZsZXgtZ3Jvd1wiXG4gICAgICAgICAgICAgICAgICAgICBzdHlsZT1cImhlaWdodDogMnJlbTtcIj5cbiAgICAgIDxpbnB1dCBpZD1cInt7aWR9fV9pbnB1dDJcIlxuICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCJcbiAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cInt7cGxhY2Vob2xkZXJ9fVwiXG4gICAgICAgICAgICAgdGFiaW5kZXg9XCJ7e3RhYmluZGV4fX1cIlxuICAgICAgICAgICAgIFtmb3JtQ29udHJvbF09XCJ0ZXh0Ym94R3JvdXAuZ2V0KCd0ZXh0Ym94MicpXCJcbiAgICAgICAgICAgICAoYmx1cik9XCJvblRleHRib3gyQmx1cigpXCI+XG4gICAgPC9lYy1mb3JtLWNvbnRyb2w+XG4gIDwvbmctY29udGFpbmVyPlxuXG4gIDxkaXYgKm5nSWY9XCJlbmFibGVTdGVwcGVyc1wiXG4gICAgICAgY2xhc3M9XCJjb250cm9sLWdyb3VwIG1sLTJcIj5cbiAgICA8ZWMtYnV0dG9uIGlkPVwie3tpZH19X3ByZXZpb3VzU2VsZWN0aW9uXCJcbiAgICAgICAgICAgICAgIHR5cGU9XCJzZWNvbmRhcnlcIlxuICAgICAgICAgICAgICAgaWNvbj1cImljb24tYW5nbGUtZG93biByb3RhdGUtOTBcIlxuICAgICAgICAgICAgICAgKGNsaWNrZWQpPVwicHJldmlvdXNTZWxlY3Rpb24oKVwiXG4gICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaXNDYWxlbmRhck9wZW4gfHwgZGlzYWJsZVN0ZXBwZXJzIHx8IGZvcm1Nb2RlbD8uZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgW3RhYmluZGV4XT1cInRhYmluZGV4XCI+XG4gICAgPC9lYy1idXR0b24+XG4gICAgPGVjLWJ1dHRvbiBpZD1cInt7aWR9fV9uZXh0U2VsZWN0aW9uXCJcbiAgICAgICAgICAgICAgIHR5cGU9XCJzZWNvbmRhcnlcIlxuICAgICAgICAgICAgICAgaWNvbj1cImljb24tYW5nbGUtZG93biByb3RhdGUtMjcwXCJcbiAgICAgICAgICAgICAgIChjbGlja2VkKT1cIm5leHRTZWxlY3Rpb24oKVwiXG4gICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiaXNDYWxlbmRhck9wZW4gfHwgZGlzYWJsZVN0ZXBwZXJzIHx8IGZvcm1Nb2RlbD8uZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgW3RhYmluZGV4XT1cInRhYmluZGV4XCI+XG4gICAgPC9lYy1idXR0b24+XG4gIDwvZGl2PlxuXG4gIDxlYy1idXR0b24gKm5nSWY9XCJxdWlja1NlbGVjdERhdGVcIlxuICAgICAgICAgICAgIGlkPVwie3tpZH19X3F1aWNrU2VsZWN0XCJcbiAgICAgICAgICAgICBpY29uPVwiaWNvbi1kYXlcIlxuICAgICAgICAgICAgIHR5cGU9XCJzZWNvbmRhcnlcIlxuICAgICAgICAgICAgIHRpdGxlPVwie3snRGF0ZUlucHV0X0xhdGVzdERhdGFBdmFpbGFibGVUaXRsZScgfCB0cmFuc2xhdGV9fVwiXG4gICAgICAgICAgICAgKGNsaWNrZWQpPVwiZ29Ub1F1aWNrU2VsZWN0RGF0ZSgpXCJcbiAgICAgICAgICAgICBbdGFiaW5kZXhdPVwidGFiaW5kZXhcIlxuICAgICAgICAgICAgIGNsYXNzPVwibWwtMlwiPlxuICA8L2VjLWJ1dHRvbj5cbjwvZGl2PlxuXG48bmctdGVtcGxhdGUgY2RrQ29ubmVjdGVkT3ZlcmxheVxuICAgICAgICAgICAgICNvdmVybGF5PVwiY2RrQ29ubmVjdGVkT3ZlcmxheVwiXG4gICAgICAgICAgICAgW2Nka0Nvbm5lY3RlZE92ZXJsYXlPcmlnaW5dPVwib3ZlcmxheU9yaWdpblwiXG4gICAgICAgICAgICAgW2Nka0Nvbm5lY3RlZE92ZXJsYXlPcGVuXT1cImlzQ2FsZW5kYXJPcGVuXCJcbiAgICAgICAgICAgICBbY2RrQ29ubmVjdGVkT3ZlcmxheVNjcm9sbFN0cmF0ZWd5XT1cIm92ZXJsYXlTY3JvbGxTdHJhdGVneVwiXG4gICAgICAgICAgICAgY2RrQ29ubmVjdGVkT3ZlcmxheVBhbmVsQ2xhc3M9XCJteS0xXCJcbiAgICAgICAgICAgICAob3ZlcmxheU91dHNpZGVDbGljayk9XCJvbk92ZXJsYXlPdXRzaWRlQ2xpY2soJGV2ZW50KVwiXG4gICAgICAgICAgICAgKGRldGFjaCk9XCJpc0NhbGVuZGFyT3BlbiA9IGZhbHNlXCI+XG4gIDxhcnRpY2xlIGlkPVwie3tpZH19X2RhdGVQaWNrZXJcIlxuICAgICAgICAgICBjbGFzcz1cImNhcmQgZC1mbGV4XCJcbiAgICAgICAgICAgW2VjS2V5Ym9hcmROYXZDb250YWluZXJdPVwiaXNDYWxlbmRhck9wZW5cIlxuICAgICAgICAgICBbdGFiaW5kZXhdPVwidGFiaW5kZXhcIlxuICAgICAgICAgICAjY2FsZW5kYXI9XCJlY0tleWJvYXJkTmF2Q29udGFpbmVyXCJcbiAgICAgICAgICAgKGZvY3VzT3V0U3RhcnQpPVwib25DYWxlbmRhckZvY3VzT3V0U3RhcnQoKVwiXG4gICAgICAgICAgIChmb2N1c091dEVuZCk9XCJvbkNhbGVuZGFyRm9jdXNPdXRFbmQoKVwiPlxuICAgIDx1bCAqbmdJZj1cInNlbGVjdGlvbk1vZGVPcHRpb25zLmxlbmd0aCA+IDFcIlxuICAgICAgICBjbGFzcz1cInNlbGVjdGlvbi1tb2RlLW1lbnUgYm9yZGVyLXJpZ2h0IHAtMVwiPlxuICAgICAgPGxpICpuZ0Zvcj1cImxldCBvcHRpb24gb2Ygc2VsZWN0aW9uTW9kZU9wdGlvbnNcIj5cbiAgICAgICAgPGJ1dHRvbiBpZD1cInt7aWR9fV9zZWxlY3Rpb25Nb2RlX3t7b3B0aW9ufX1cIlxuICAgICAgICAgICAgICAgIGNsYXNzPVwidGV4dC1ib2R5LTFcIlxuICAgICAgICAgICAgICAgIFtjbGFzcy5pcy1zZWxlY3RlZF09XCJvcHRpb24gPT09IHNlbGVjdGlvbk1vZGVcIlxuICAgICAgICAgICAgICAgIChjbGljayk9XCJvblNlbGVjdGlvbk1vZGVDaGFuZ2Uob3B0aW9uKVwiXG4gICAgICAgICAgICAgICAgdGFiaW5kZXg9XCJ7e3RhYmluZGV4fX1cIj5cbiAgICAgICAgICB7eydEYXRlSW5wdXRTZWxlY3Rpb25Nb2RlXycgKyBvcHRpb24gfCB0cmFuc2xhdGV9fVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvbGk+XG4gICAgPC91bD5cblxuICAgIDxkaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4XCI+XG4gICAgICAgIDxlYy1jYWxlbmRhciBpZD1cInt7aWR9fV9jYWxlbmRhclwiXG4gICAgICAgICAgICAgICAgICAgICBbdmlld109XCJwcmltYXJ5Q2FsZW5kYXJWaWV3XCJcbiAgICAgICAgICAgICAgICAgICAgICh2aWV3Q2hhbmdlKT1cIm9uUHJpbWFyeUNhbGVuZGFyVmlld0NoYW5nZSgkZXZlbnQpXCJcbiAgICAgICAgICAgICAgICAgICAgIFtzZWxlY3Rpb25Nb2RlXT1cInNlbGVjdGlvbk1vZGVcIlxuICAgICAgICAgICAgICAgICAgICAgW3NlbGVjdGlvbl09XCJjYWxlbmRhclNlbGVjdGlvblwiXG4gICAgICAgICAgICAgICAgICAgICAoZGF0ZVNlbGVjdGVkKT1cIm9uQ2FsZW5kYXJEYXRlU2VsZWN0ZWQoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICBbbWluRGF0ZV09XCJtaW5EYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgIFttYXhEYXRlXT1cInNlbGVjdGlvblN0cmF0ZWd5LnNob3dTZWNvbmRhcnlDYWxlbmRhciA/IHByaW1hcnlDYWxlbmRhck1heERhdGUgOiBtYXhEYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgIFt0YWJpbmRleF09XCJ0YWJpbmRleFwiPlxuICAgICAgICA8L2VjLWNhbGVuZGFyPlxuXG4gICAgICAgIDxlYy1jYWxlbmRhciAqbmdJZj1cInNlbGVjdGlvblN0cmF0ZWd5LnNob3dTZWNvbmRhcnlDYWxlbmRhclwiXG4gICAgICAgICAgICAgICAgICAgICBpZD1cInt7aWR9fV9zZWNvbmRhcnlDYWxlbmRhclwiXG4gICAgICAgICAgICAgICAgICAgICBbdmlld109XCJzZWNvbmRhcnlDYWxlbmRhclZpZXdcIlxuICAgICAgICAgICAgICAgICAgICAgKHZpZXdDaGFuZ2UpPVwib25TZWNvbmRhcnlDYWxlbmRhclZpZXdDaGFuZ2UoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICBbc2VsZWN0aW9uTW9kZV09XCJzZWxlY3Rpb25Nb2RlXCJcbiAgICAgICAgICAgICAgICAgICAgIFtzZWxlY3Rpb25dPVwiY2FsZW5kYXJTZWxlY3Rpb25cIlxuICAgICAgICAgICAgICAgICAgICAgKGRhdGVTZWxlY3RlZCk9XCJvbkNhbGVuZGFyRGF0ZVNlbGVjdGVkKCRldmVudClcIlxuICAgICAgICAgICAgICAgICAgICAgW21pbkRhdGVdPVwic2Vjb25kYXJ5Q2FsZW5kYXJNaW5EYXRlXCJcbiAgICAgICAgICAgICAgICAgICAgIFttYXhEYXRlXT1cIm1heERhdGVcIlxuICAgICAgICAgICAgICAgICAgICAgW3RhYmluZGV4XT1cInRhYmluZGV4XCI+XG4gICAgICAgIDwvZWMtY2FsZW5kYXI+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGZvb3RlciAqbmdJZj1cInNlbGVjdGlvblN0cmF0ZWd5LnNlbGVjdGlvblZpZXdNb2RlID09PSAnZGF5J1wiXG4gICAgICAgICAgICAgIGNsYXNzPVwicHgtMiBteS0yIGQtZmxleFwiPlxuICAgICAgICA8ZWMtYnV0dG9uIGlkPVwie3tpZH19X3RvZGF5X2J1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgbGFiZWw9XCJ7eydEYXRlSW5wdXRfQ2FsZW5kYXJUb2RheUJ1dHRvbl9MYWJlbCcgfCB0cmFuc2xhdGV9fVwiXG4gICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtbC1hdXRvXCJcbiAgICAgICAgICAgICAgICAgICAoY2xpY2tlZCk9XCJnb1RvVG9kYXkoKVwiXG4gICAgICAgICAgICAgICAgICAgdGFiaW5kZXg9XCJ7e3RhYmluZGV4fX1cIlxuICAgICAgICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCI+XG4gICAgICAgIDwvZWMtYnV0dG9uPlxuICAgICAgICA8ZWMtYnV0dG9uICpuZ0lmPVwic2VsZWN0aW9uU3RyYXRlZ3kuc2hvd1NlY29uZGFyeVRleHRib3hcIlxuICAgICAgICAgICAgICAgICAgIGlkPVwie3tpZH19X2Nsb3NlX2J1dHRvblwiXG4gICAgICAgICAgICAgICAgICAgbGFiZWw9XCJ7eydEYXRlSW5wdXRfQ2FsZW5kYXJDbG9zZUJ1dHRvbl9MYWJlbCcgfCB0cmFuc2xhdGV9fVwiXG4gICAgICAgICAgICAgICAgICAgY2xhc3M9XCJtbC0yXCJcbiAgICAgICAgICAgICAgICAgICAoY2xpY2tlZCk9XCJjbG9zZUNhbGVuZGFyQW5kRm9jdXNJbnB1dCgpXCJcbiAgICAgICAgICAgICAgICAgICB0YWJpbmRleD1cInt7dGFiaW5kZXh9fVwiXG4gICAgICAgICAgICAgICAgICAgdHlwZT1cInByaW1hcnlcIj5cbiAgICAgICAgPC9lYy1idXR0b24+XG4gICAgICA8L2Zvb3Rlcj5cbiAgICA8L2Rpdj5cbiAgPC9hcnRpY2xlPlxuPC9uZy10ZW1wbGF0ZT5cbiJdfQ==
|