@energycap/components 0.40.2-rxjs-7-upgrade.20241219-1425 → 0.41.1-ECAP-27592-angular-17.20241219-1718
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/{esm2020 → esm2022}/energycap-components.mjs +4 -4
- package/{esm2020 → esm2022}/lib/components.module.mjs +418 -418
- package/{esm2020 → esm2022}/lib/controls/banner/banner.component.mjs +109 -109
- package/{esm2020 → esm2022}/lib/controls/button/button.component.mjs +106 -106
- package/{esm2020 → esm2022}/lib/controls/button/copy-button-base.directive.mjs +67 -67
- package/{esm2020 → esm2022}/lib/controls/button/copy-button.directive.mjs +28 -28
- package/{esm2020 → esm2022}/lib/controls/button/copy-table-button.directive.mjs +43 -43
- package/{esm2020 → esm2022}/lib/controls/calendar/calendar-item.component.mjs +59 -59
- package/{esm2020 → esm2022}/lib/controls/calendar/calendar.component.mjs +200 -200
- package/{esm2020 → esm2022}/lib/controls/calendar/calendar.types.mjs +3 -3
- package/{esm2020 → esm2022}/lib/controls/checkbox/checkbox.component.mjs +140 -140
- package/{esm2020 → esm2022}/lib/controls/collapsible-toggle/collapsible-toggle.component.mjs +38 -38
- package/{esm2020 → esm2022}/lib/controls/combobox/combobox.component.mjs +879 -879
- package/{esm2020 → esm2022}/lib/controls/date-input/date-input.component.mjs +256 -256
- package/{esm2020 → esm2022}/lib/controls/dropdown/dropdown.component.mjs +243 -243
- package/{esm2020 → esm2022}/lib/controls/file-upload/file-upload.component.mjs +261 -261
- package/{esm2020 → esm2022}/lib/controls/form-control/form-control.component.mjs +104 -104
- package/{esm2020 → esm2022}/lib/controls/form-control-base.mjs +151 -151
- package/{esm2020 → esm2022}/lib/controls/form-control-label/form-control-label.component.mjs +136 -136
- package/{esm2020 → esm2022}/lib/controls/form-group/form-group.component.mjs +261 -261
- package/{esm2020 → esm2022}/lib/controls/help-popover/help-popover.component.mjs +31 -31
- package/{esm2020 → esm2022}/lib/controls/item-picker/item-picker.component.mjs +329 -329
- package/{esm2020 → esm2022}/lib/controls/link-button/link-button.component.mjs +11 -11
- package/{esm2020 → esm2022}/lib/controls/menu/menu.component.mjs +485 -485
- package/{esm2020 → esm2022}/lib/controls/navigation/link-item.mjs +1 -1
- package/{esm2020 → esm2022}/lib/controls/navigation/nav-group.mjs +38 -38
- package/{esm2020 → esm2022}/lib/controls/navigation/nav-item-active.directive.mjs +92 -92
- package/{esm2020 → esm2022}/lib/controls/navigation/nav-item.mjs +1 -1
- package/{esm2020 → esm2022}/lib/controls/numericbox/numericbox.component.mjs +372 -372
- package/{esm2020 → esm2022}/lib/controls/popover/popover.component.mjs +117 -117
- package/{esm2020 → esm2022}/lib/controls/radio-button/radio-button-option.mjs +2 -2
- package/{esm2020 → esm2022}/lib/controls/radio-button/radio-button.component.mjs +82 -82
- package/{esm2020 → esm2022}/lib/controls/select/select.component.mjs +88 -88
- package/{esm2020 → esm2022}/lib/controls/tabs/tabs.component.mjs +47 -47
- package/{esm2020 → esm2022}/lib/controls/textbox/textbox.component.mjs +155 -155
- package/{esm2020 → esm2022}/lib/core/cache.service.mjs +105 -105
- package/esm2022/lib/core/custom-validators.mjs +29 -0
- package/esm2022/lib/core/date-time-helper.mjs +220 -0
- package/{esm2020 → esm2022}/lib/core/error.service.mjs +61 -61
- package/{esm2020 → esm2022}/lib/core/router-helper.service.mjs +111 -111
- package/{esm2020 → esm2022}/lib/core/scroll.service.mjs +89 -89
- package/{esm2020 → esm2022}/lib/core/telemetry-tracker.service.mjs +16 -16
- package/{esm2020 → esm2022}/lib/core/telemetry.service.mjs +38 -38
- package/{esm2020 → esm2022}/lib/core/validation-message.service.mjs +185 -185
- package/{esm2020 → esm2022}/lib/core/validation-patterns.mjs +30 -30
- package/{esm2020 → esm2022}/lib/core/window.service.mjs +186 -186
- package/{esm2020 → esm2022}/lib/display/app-bar/app-bar.component.mjs +46 -46
- package/esm2022/lib/display/avatar/avatar.component.mjs +67 -0
- package/{esm2020 → esm2022}/lib/display/avatar/avatar.service.mjs +64 -64
- package/{esm2020 → esm2022}/lib/display/confirm/confirm.component.mjs +168 -168
- package/{esm2020 → esm2022}/lib/display/dialog/dialog-content.mjs +1 -1
- package/{esm2020 → esm2022}/lib/display/dialog/dialog-group/dialog-group.component.mjs +63 -63
- package/{esm2020 → esm2022}/lib/display/dialog/dialog-types.mjs +76 -76
- package/{esm2020 → esm2022}/lib/display/dialog/dialog.component.mjs +281 -281
- package/{esm2020 → esm2022}/lib/display/dialog/dialog.service.mjs +71 -71
- package/{esm2020 → esm2022}/lib/display/help/help-types.mjs +1 -1
- package/{esm2020 → esm2022}/lib/display/hierarchy/hierarchy-base.mjs +111 -111
- package/{esm2020 → esm2022}/lib/display/hierarchy/hierarchy-mocks.spec.mjs +53 -53
- package/{esm2020 → esm2022}/lib/display/hierarchy/hierarchy-tree/hierarchy-tree.component.mjs +61 -61
- package/{esm2020 → esm2022}/lib/display/item-display/item-display.component.mjs +81 -81
- package/{esm2020 → esm2022}/lib/display/json-display/json-display.component.mjs +47 -47
- package/{esm2020 → esm2022}/lib/display/resizable/resizable-base.mjs +120 -120
- package/{esm2020 → esm2022}/lib/display/resizable/resizable.component.mjs +52 -52
- package/{esm2020 → esm2022}/lib/display/spinner/spinner.component.mjs +12 -12
- package/{esm2020 → esm2022}/lib/display/splash/splash.component.mjs +42 -42
- package/{esm2020 → esm2022}/lib/display/splash/splash.service.mjs +35 -35
- package/{esm2020 → esm2022}/lib/display/table/resizable-column.component.mjs +20 -20
- package/{esm2020 → esm2022}/lib/display/table/resizable-table.directive.mjs +227 -227
- package/{esm2020 → esm2022}/lib/display/table/searchable-table.component.mjs +342 -342
- package/{esm2020 → esm2022}/lib/display/table/table-detail-row.component.mjs +19 -19
- package/{esm2020 → esm2022}/lib/display/table/table-locked-column.component.mjs +58 -58
- package/{esm2020 → esm2022}/lib/display/table/table-master-header-row.component.mjs +14 -14
- package/{esm2020 → esm2022}/lib/display/table/table-master-row.component.mjs +163 -163
- package/{esm2020 → esm2022}/lib/display/table/table-pagination.component.mjs +155 -155
- package/{esm2020 → esm2022}/lib/display/table/table-selectable-row.component.mjs +235 -235
- package/{esm2020 → esm2022}/lib/display/table/table.component.mjs +249 -249
- package/{esm2020 → esm2022}/lib/display/tags/tag.mjs +17 -17
- package/{esm2020 → esm2022}/lib/display/tags/tags.component.mjs +77 -77
- package/{esm2020 → esm2022}/lib/display/toast/toast/toast.component.mjs +77 -77
- package/{esm2020 → esm2022}/lib/display/toast/toast-types.mjs +7 -7
- package/{esm2020 → esm2022}/lib/display/toast/toast.service.mjs +35 -35
- package/{esm2020 → esm2022}/lib/display/toast/toaster/toaster.component.mjs +114 -114
- package/{esm2020 → esm2022}/lib/display/tooltip/tooltip.component.mjs +28 -28
- package/{esm2020 → esm2022}/lib/display/tooltip/tooltip.service.mjs +78 -78
- package/{esm2020 → esm2022}/lib/display/tooltip-directive/tooltip.directive.mjs +173 -173
- package/{esm2020 → esm2022}/lib/display/tour/tour-types.mjs +33 -33
- package/{esm2020 → esm2022}/lib/display/tour/tour.component.mjs +398 -398
- package/{esm2020 → esm2022}/lib/display/tour/tour.service.mjs +75 -75
- package/{esm2020 → esm2022}/lib/display/tree/tree.component.mjs +135 -135
- package/{esm2020 → esm2022}/lib/display/view-overlay/view-overlay.component.mjs +58 -58
- package/{esm2020 → esm2022}/lib/shared/directives/click-area-for/click-area-for.directive.mjs +32 -32
- package/{esm2020 → esm2022}/lib/shared/directives/if-viewport-width/if-viewport-width.directive.mjs +111 -111
- package/esm2022/lib/shared/directives/popup/popup-container.directive.mjs +166 -0
- package/{esm2020 → esm2022}/lib/shared/display/pipes/date-display.pipe.mjs +50 -50
- package/{esm2020 → esm2022}/lib/shared/display/pipes/highlight-text.pipe.mjs +30 -30
- package/{esm2020 → esm2022}/lib/shared/display/pipes/relative-date.pipe.mjs +62 -62
- package/{esm2020 → esm2022}/lib/shared/display/pipes/row-count.pipe.mjs +48 -48
- package/{esm2020 → esm2022}/lib/shared/display/pipes/time-display.pipe.mjs +41 -41
- package/esm2022/lib/shared/display.mjs +6 -0
- package/esm2022/lib/shared/form-group.helper.mjs +67 -0
- package/{esm2020 → esm2022}/lib/shared/json-helper.mjs +18 -18
- package/esm2022/lib/shared/lodash-helper.mjs +52 -0
- package/{esm2020 → esm2022}/lib/shared/page/page-base/page-base.component.mjs +387 -387
- package/{esm2020 → esm2022}/lib/shared/page/page-statuses.mjs +22 -22
- package/{esm2020 → esm2022}/lib/shared/page/page-title/page-title.component.mjs +23 -23
- package/{esm2020 → esm2022}/lib/shared/page/page-view/page-view.component.mjs +147 -147
- package/{esm2020 → esm2022}/lib/shared/testing/copy-button-base-test-injector-factory.spec.mjs +16 -16
- package/{esm2020 → esm2022}/lib/shared/testing/hierarchy-base-test-injector-factory.spec.mjs +16 -16
- package/{esm2020 → esm2022}/lib/shared/testing/page-base-component-test-helper.spec.mjs +37 -37
- package/esm2022/lib/shared/testing/page-base-component-test-injector-factory.spec.mjs +98 -0
- package/{esm2020 → esm2022}/lib/shared/testing/public-mocks.spec.mjs +148 -148
- package/{esm2020 → esm2022}/lib/shared/testing/spy-factory.spec.mjs +39 -39
- package/{esm2020 → esm2022}/lib/shared/testing/translation-mocks.spec.mjs +56 -56
- package/{esm2020 → esm2022}/lib/shared/user-preference.service.mjs +17 -17
- package/{esm2020 → esm2022}/lib/shared/wizard/wizard-base/wizard-base.component.mjs +246 -246
- package/{esm2020 → esm2022}/lib/shared/wizard/wizard-buttons/wizard-buttons.component.mjs +68 -68
- package/{esm2020 → esm2022}/lib/shared/wizard/wizard-progress/wizard-progress.component.mjs +18 -18
- package/{esm2020 → esm2022}/public-api.mjs +114 -114
- package/{fesm2020 → fesm2022}/energycap-components.mjs +11797 -11793
- package/fesm2022/energycap-components.mjs.map +1 -0
- package/index.d.ts +5 -5
- package/lib/components.module.d.ts +91 -91
- package/lib/controls/banner/banner.component.d.ts +50 -50
- package/lib/controls/button/button.component.d.ts +78 -78
- package/lib/controls/button/copy-button-base.directive.d.ts +20 -20
- package/lib/controls/button/copy-button.directive.d.ts +14 -14
- package/lib/controls/button/copy-table-button.directive.d.ts +19 -19
- package/lib/controls/calendar/calendar-item.component.d.ts +17 -17
- package/lib/controls/calendar/calendar.component.d.ts +54 -54
- package/lib/controls/calendar/calendar.types.d.ts +7 -7
- package/lib/controls/checkbox/checkbox.component.d.ts +65 -65
- package/lib/controls/collapsible-toggle/collapsible-toggle.component.d.ts +25 -25
- package/lib/controls/combobox/combobox.component.d.ts +418 -418
- package/lib/controls/date-input/date-input.component.d.ts +80 -80
- package/lib/controls/dropdown/dropdown.component.d.ts +161 -161
- package/lib/controls/file-upload/file-upload.component.d.ts +124 -124
- package/lib/controls/form-control/form-control.component.d.ts +30 -30
- package/lib/controls/form-control-base.d.ts +110 -110
- package/lib/controls/form-control-label/form-control-label.component.d.ts +73 -73
- package/lib/controls/form-group/form-group.component.d.ts +105 -105
- package/lib/controls/help-popover/help-popover.component.d.ts +11 -11
- package/lib/controls/item-picker/item-picker.component.d.ts +164 -164
- package/lib/controls/link-button/link-button.component.d.ts +5 -5
- package/lib/controls/menu/menu.component.d.ts +255 -255
- package/lib/controls/navigation/link-item.d.ts +32 -32
- package/lib/controls/navigation/nav-group.d.ts +18 -18
- package/lib/controls/navigation/nav-item-active.directive.d.ts +42 -42
- package/lib/controls/navigation/nav-item.d.ts +31 -31
- package/lib/controls/numericbox/numericbox.component.d.ts +148 -148
- package/lib/controls/popover/popover.component.d.ts +51 -51
- package/lib/controls/radio-button/radio-button-option.d.ts +19 -19
- package/lib/controls/radio-button/radio-button.component.d.ts +53 -53
- package/lib/controls/select/select.component.d.ts +44 -44
- package/lib/controls/tabs/tabs.component.d.ts +30 -30
- package/lib/controls/textbox/textbox.component.d.ts +107 -107
- package/lib/core/cache.service.d.ts +33 -33
- package/lib/core/custom-validators.d.ts +20 -20
- package/lib/core/date-time-helper.d.ts +101 -101
- package/lib/core/error.service.d.ts +20 -20
- package/lib/core/router-helper.service.d.ts +48 -48
- package/lib/core/scroll.service.d.ts +36 -36
- package/lib/core/telemetry-tracker.service.d.ts +13 -13
- package/lib/core/telemetry.service.d.ts +31 -31
- package/lib/core/validation-message.service.d.ts +26 -26
- package/lib/core/validation-patterns.d.ts +22 -22
- package/lib/core/window.service.d.ts +116 -116
- package/lib/display/app-bar/app-bar.component.d.ts +20 -20
- package/lib/display/avatar/avatar.component.d.ts +35 -35
- package/lib/display/avatar/avatar.service.d.ts +24 -24
- package/lib/display/confirm/confirm.component.d.ts +123 -123
- package/lib/display/dialog/dialog-content.d.ts +19 -19
- package/lib/display/dialog/dialog-group/dialog-group.component.d.ts +32 -32
- package/lib/display/dialog/dialog-types.d.ts +130 -130
- package/lib/display/dialog/dialog.component.d.ts +120 -120
- package/lib/display/dialog/dialog.service.d.ts +48 -48
- package/lib/display/help/help-types.d.ts +33 -33
- package/lib/display/hierarchy/hierarchy-base.d.ts +97 -97
- package/lib/display/hierarchy/hierarchy-mocks.spec.d.ts +53 -53
- package/lib/display/hierarchy/hierarchy-tree/hierarchy-tree.component.d.ts +34 -34
- package/lib/display/item-display/item-display.component.d.ts +43 -43
- package/lib/display/json-display/json-display.component.d.ts +16 -16
- package/lib/display/resizable/resizable-base.d.ts +67 -67
- package/lib/display/resizable/resizable.component.d.ts +31 -31
- package/lib/display/spinner/spinner.component.d.ts +5 -5
- package/lib/display/splash/splash.component.d.ts +16 -16
- package/lib/display/splash/splash.service.d.ts +22 -22
- package/lib/display/table/resizable-column.component.d.ts +10 -10
- package/lib/display/table/resizable-table.directive.d.ts +93 -93
- package/lib/display/table/searchable-table.component.d.ts +206 -206
- package/lib/display/table/table-detail-row.component.d.ts +8 -8
- package/lib/display/table/table-locked-column.component.d.ts +20 -20
- package/lib/display/table/table-master-header-row.component.d.ts +9 -9
- package/lib/display/table/table-master-row.component.d.ts +113 -113
- package/lib/display/table/table-pagination.component.d.ts +91 -91
- package/lib/display/table/table-selectable-row.component.d.ts +102 -102
- package/lib/display/table/table.component.d.ts +121 -121
- package/lib/display/tags/tag.d.ts +18 -18
- package/lib/display/tags/tags.component.d.ts +48 -48
- package/lib/display/toast/toast/toast.component.d.ts +23 -23
- package/lib/display/toast/toast-types.d.ts +24 -24
- package/lib/display/toast/toast.service.d.ts +20 -20
- package/lib/display/toast/toaster/toaster.component.d.ts +35 -35
- package/lib/display/tooltip/tooltip.component.d.ts +70 -70
- package/lib/display/tooltip/tooltip.service.d.ts +16 -16
- package/lib/display/tooltip-directive/tooltip.directive.d.ts +44 -44
- package/lib/display/tour/tour-types.d.ts +70 -70
- package/lib/display/tour/tour.component.d.ts +147 -147
- package/lib/display/tour/tour.service.d.ts +38 -38
- package/lib/display/tree/tree.component.d.ts +75 -75
- package/lib/display/view-overlay/view-overlay.component.d.ts +38 -38
- package/lib/shared/directives/click-area-for/click-area-for.directive.d.ts +14 -14
- package/lib/shared/directives/if-viewport-width/if-viewport-width.directive.d.ts +60 -60
- package/lib/shared/directives/popup/popup-container.directive.d.ts +101 -101
- package/lib/shared/display/pipes/date-display.pipe.d.ts +21 -21
- package/lib/shared/display/pipes/highlight-text.pipe.d.ts +9 -9
- package/lib/shared/display/pipes/relative-date.pipe.d.ts +36 -36
- package/lib/shared/display/pipes/row-count.pipe.d.ts +23 -23
- package/lib/shared/display/pipes/time-display.pipe.d.ts +18 -18
- package/lib/shared/display.d.ts +42 -42
- package/lib/shared/form-group.helper.d.ts +31 -31
- package/lib/shared/json-helper.d.ts +7 -7
- package/lib/shared/lodash-helper.d.ts +18 -18
- package/lib/shared/page/page-base/page-base.component.d.ts +259 -259
- package/lib/shared/page/page-statuses.d.ts +13 -13
- package/lib/shared/page/page-title/page-title.component.d.ts +9 -9
- package/lib/shared/page/page-view/page-view.component.d.ts +102 -102
- package/lib/shared/testing/copy-button-base-test-injector-factory.spec.d.ts +4 -4
- package/lib/shared/testing/hierarchy-base-test-injector-factory.spec.d.ts +4 -4
- package/lib/shared/testing/page-base-component-test-helper.spec.d.ts +30 -30
- package/lib/shared/testing/page-base-component-test-injector-factory.spec.d.ts +28 -28
- package/lib/shared/testing/public-mocks.spec.d.ts +90 -90
- package/lib/shared/testing/spy-factory.spec.d.ts +27 -27
- package/lib/shared/testing/translation-mocks.spec.d.ts +30 -30
- package/lib/shared/user-preference.service.d.ts +13 -13
- package/lib/shared/wizard/wizard-base/wizard-base.component.d.ts +134 -134
- package/lib/shared/wizard/wizard-buttons/wizard-buttons.component.d.ts +27 -27
- package/lib/shared/wizard/wizard-progress/wizard-progress.component.d.ts +10 -10
- package/package.json +12 -18
- package/public-api.d.ts +111 -111
- package/schematics/rxjs-7-upgrade/index.d.ts +3 -3
- package/schematics/rxjs-7-upgrade/index.js +67 -67
- package/schematics/rxjs-7-upgrade/schema.d.ts +4 -4
- package/schematics/rxjs-7-upgrade/schema.js +2 -2
- package/schematics/utilities/typescript.d.ts +7 -7
- package/schematics/utilities/typescript.js +41 -41
- package/schematics/utilities/workspace.d.ts +8 -8
- package/schematics/utilities/workspace.js +71 -71
- package/esm2020/lib/core/custom-validators.mjs +0 -29
- package/esm2020/lib/core/date-time-helper.mjs +0 -220
- package/esm2020/lib/display/avatar/avatar.component.mjs +0 -67
- package/esm2020/lib/shared/directives/popup/popup-container.directive.mjs +0 -163
- package/esm2020/lib/shared/display.mjs +0 -6
- package/esm2020/lib/shared/form-group.helper.mjs +0 -67
- package/esm2020/lib/shared/lodash-helper.mjs +0 -51
- package/esm2020/lib/shared/testing/page-base-component-test-injector-factory.spec.mjs +0 -98
- package/fesm2015/energycap-components.mjs +0 -12211
- package/fesm2015/energycap-components.mjs.map +0 -1
- package/fesm2020/energycap-components.mjs.map +0 -1
@@ -1,256 +1,256 @@
|
|
1
|
-
import { Component, HostBinding, Input, ViewChild } from '@angular/core';
|
2
|
-
import { FormControl } 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 { isCalendarSelectionSingleDate } from '../calendar/calendar.types';
|
8
|
-
import { FormControlBase } from '../form-control-base';
|
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 "../../shared/display/pipes/date-display.pipe";
|
14
|
-
import * as i5 from "@angular/cdk/overlay";
|
15
|
-
import * as i6 from "@angular/common";
|
16
|
-
import * as i7 from "@angular/forms";
|
17
|
-
import * as i8 from "../form-control/form-control.component";
|
18
|
-
import * as i9 from "../help-popover/help-popover.component";
|
19
|
-
import * as i10 from "../calendar/calendar.component";
|
20
|
-
import * as i11 from "@ngx-translate/core";
|
21
|
-
export class DateInputComponent extends FormControlBase {
|
22
|
-
constructor(validationMessageService, formGroupHelper, userPreferenceService, dateDisplayPipe, el, overlayService) {
|
23
|
-
super(validationMessageService, formGroupHelper);
|
24
|
-
this.validationMessageService = validationMessageService;
|
25
|
-
this.formGroupHelper = formGroupHelper;
|
26
|
-
this.userPreferenceService = userPreferenceService;
|
27
|
-
this.dateDisplayPipe = dateDisplayPipe;
|
28
|
-
this.el = el;
|
29
|
-
this.overlayService = overlayService;
|
30
|
-
this.id = '';
|
31
|
-
/** The form control provided by the hosting form. */
|
32
|
-
this.formModel = new FormControl(null);
|
33
|
-
this.minDate = DateTimeHelper.minDatePickerDate;
|
34
|
-
this.maxDate = DateTimeHelper.maxDatePickerDate;
|
35
|
-
/** The internal textbox's form control. */
|
36
|
-
this.textboxControl = new FormControl(null);
|
37
|
-
/**
|
38
|
-
* The current calendar selection.
|
39
|
-
* Updated when the user clicks on a calendar item or when the date entered into the textbox is parsed.
|
40
|
-
*/
|
41
|
-
this.calendarSelection = null;
|
42
|
-
/** Controls whether the calendar overlay is open or not. */
|
43
|
-
this.isCalendarOpen = false;
|
44
|
-
/** Placeholder for the textbox. Updated to reflect the user's date display preference. */
|
45
|
-
this.placeholder = 'MM/DD/YYYY';
|
46
|
-
/** Overlay scroll strategy for the calendar overlay. Closes the calendar on scroll. */
|
47
|
-
this.overlayScrollStrategy = this.overlayService.scrollStrategies.close();
|
48
|
-
/**
|
49
|
-
* Date parsing formats for user-entered dates. Defaults to month-first formats, but is updated in onInit
|
50
|
-
* to use the user's preferred date format.
|
51
|
-
*/
|
52
|
-
this.parseFormats = DateTimeHelper.getParseFormats();
|
53
|
-
/**
|
54
|
-
* Validator that checks if the date is within the min and max date range.
|
55
|
-
* If the date is outside of the range, the validator returns an error that
|
56
|
-
* triggers the validation message service to show the error in the label.
|
57
|
-
*/
|
58
|
-
this.dateValidator = (control) => {
|
59
|
-
if (control.value) {
|
60
|
-
if (control.value < this.minDate) {
|
61
|
-
return { minDate: { minValue: this.minDate } };
|
62
|
-
}
|
63
|
-
else if (control.value > this.maxDate) {
|
64
|
-
return { maxDate: { maxValue: this.maxDate } };
|
65
|
-
}
|
66
|
-
}
|
67
|
-
return null;
|
68
|
-
};
|
69
|
-
}
|
70
|
-
/** Focuses the input whenever the calendar is shift-tabbed out of. */
|
71
|
-
onCalendarFocusOutStart(event) {
|
72
|
-
event.preventDefault();
|
73
|
-
this.focusInput();
|
74
|
-
}
|
75
|
-
/** Closes the calendar and focuses the input whenever the calendar is tabbed out of. */
|
76
|
-
onCalendarFocusOutEnd(event) {
|
77
|
-
event.preventDefault();
|
78
|
-
this.isCalendarOpen = false;
|
79
|
-
this.focusInput();
|
80
|
-
}
|
81
|
-
/** Close the calendar if the user clicks outside of the calendar and date input. */
|
82
|
-
onOverlayOutsideClick(event) {
|
83
|
-
// Do not close the calendar if the click was within the date input or action button
|
84
|
-
const rect = this.el.nativeElement.getBoundingClientRect();
|
85
|
-
const clickedOutsideControl = event.clientY < rect.top ||
|
86
|
-
event.clientY > rect.bottom ||
|
87
|
-
event.clientX < rect.left ||
|
88
|
-
event.clientX > rect.right;
|
89
|
-
// It's possible that the user hit enter on the action button instead of clicking with the mouse.
|
90
|
-
// In this case the "click" event will be outside of the component because the clientx and y are 0,
|
91
|
-
// but we don't want to close in this case because button clicks trigger calendar open/close separately.
|
92
|
-
const isActionClick = event.target.id === `${this.id}_action`;
|
93
|
-
if (!isActionClick && clickedOutsideControl) {
|
94
|
-
this.isCalendarOpen = false;
|
95
|
-
}
|
96
|
-
}
|
97
|
-
/** 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 */
|
98
|
-
onActionKeydown(event) {
|
99
|
-
if (event.key === 'Tab' && !event.shiftKey && this.isCalendarOpen) {
|
100
|
-
// Prevent the default tab action so the focus doesn't move to the next element in the tab order after we manually focus the calendar button.
|
101
|
-
event.preventDefault();
|
102
|
-
// Focus the first button in the calendar overlay
|
103
|
-
const firstButton = this.overlay?.overlayRef.hostElement.querySelector('button:not(:disabled)');
|
104
|
-
firstButton?.focus();
|
105
|
-
}
|
106
|
-
}
|
107
|
-
onTextboxKeydown(event) {
|
108
|
-
if (event.key === 'Tab' && event.shiftKey) {
|
109
|
-
// If the user is tabbing backwards from the textbox, close the calendar.
|
110
|
-
this.isCalendarOpen = false;
|
111
|
-
}
|
112
|
-
}
|
113
|
-
/** Whenever the user selects a date from the calendar, update the formModel with the selection */
|
114
|
-
onSelectionChange(selection) {
|
115
|
-
this.calendarSelection = selection;
|
116
|
-
if (isCalendarSelectionSingleDate(selection)) {
|
117
|
-
this.formModel.setValue(selection);
|
118
|
-
this.isCalendarOpen = false;
|
119
|
-
this.focusInput();
|
120
|
-
}
|
121
|
-
}
|
122
|
-
onTextboxBlur() {
|
123
|
-
// Parse the textbox value into a date and update the form model
|
124
|
-
const value = this.textboxControl.value;
|
125
|
-
if (value) {
|
126
|
-
const parsedDate = moment(value, this.parseFormats);
|
127
|
-
if (parsedDate.isValid()) {
|
128
|
-
this.formModel.setValue(parsedDate.toDate());
|
129
|
-
}
|
130
|
-
else {
|
131
|
-
this.formModel.setValue(null);
|
132
|
-
}
|
133
|
-
}
|
134
|
-
else {
|
135
|
-
this.formModel.setValue(null);
|
136
|
-
}
|
137
|
-
// Update the form model's touched and dirty status based on the textbox's status.
|
138
|
-
// Since the user interacts with a control that is internal to this component, the
|
139
|
-
// form model's status won't be updated automatically.
|
140
|
-
if (this.textboxControl.touched && !this.formModel.touched) {
|
141
|
-
this.formModel.markAsTouched();
|
142
|
-
}
|
143
|
-
if (this.textboxControl.dirty && !this.formModel.dirty) {
|
144
|
-
this.formModel.markAsDirty();
|
145
|
-
}
|
146
|
-
}
|
147
|
-
ngOnInit() {
|
148
|
-
// Setup
|
149
|
-
super.ngOnInit();
|
150
|
-
this.setDateFormats();
|
151
|
-
this.formModel.addValidators(this.dateValidator);
|
152
|
-
// Subscriptions
|
153
|
-
this.onFormModelStatusChanges();
|
154
|
-
this.onFormModelValueChanges();
|
155
|
-
this.onTextboxValueChanges();
|
156
|
-
// Sync the initial disabled status and value of the textbox
|
157
|
-
this.syncTextboxControlDisabledStatus(this.formModel.status);
|
158
|
-
this.textboxControl.setValue(this.dateDisplayPipe.transform(this.formModel.value, true), { emitEvent: false });
|
159
|
-
this.calendarSelection = this.formModel.value;
|
160
|
-
}
|
161
|
-
onFormModelStatusChanges() {
|
162
|
-
// Keep the textboxControl disabled status in sync with the formModel
|
163
|
-
this.formModel.statusChanges.pipe(distinctUntilChanged(), takeUntil(this.componentDestroyed)).subscribe(status => {
|
164
|
-
this.syncTextboxControlDisabledStatus(status);
|
165
|
-
if (this.isCalendarOpen) {
|
166
|
-
// As validation messages appear/disappear, the date input may have shifted up or down on the page.
|
167
|
-
// Update the overlay position to ensure it's still aligned with the textbox and not blocking it.
|
168
|
-
// Settimeout is needed to ensure the overlay is being updated after the message is rendered.
|
169
|
-
setTimeout(() => {
|
170
|
-
this.overlay?.overlayRef?.updatePosition();
|
171
|
-
});
|
172
|
-
}
|
173
|
-
});
|
174
|
-
}
|
175
|
-
onFormModelValueChanges() {
|
176
|
-
// Update the calendar selection textbox value with a formatted date when the form model changes.
|
177
|
-
// This is usually triggered by programmatic changes to the form model by a parent component.
|
178
|
-
this.formModel.valueChanges.pipe(distinctUntilChanged((a, b) => moment(a).isSame(b, 'day')), takeUntil(this.componentDestroyed)).subscribe(value => {
|
179
|
-
const displayValue = this.dateDisplayPipe.transform(value, true);
|
180
|
-
// Don't emit an event when setting the textbox value to avoid circular updates between the textbox and form model.
|
181
|
-
this.textboxControl.setValue(displayValue, { emitEvent: false });
|
182
|
-
this.calendarSelection = value;
|
183
|
-
});
|
184
|
-
}
|
185
|
-
onTextboxValueChanges() {
|
186
|
-
// Update the calendar selection when the textbox value changes to update the calendar.
|
187
|
-
// We don't patch the formModel here because we don't want to trigger the
|
188
|
-
// date formatting logic and overwrite the user's input.
|
189
|
-
// We'll do that when the user blurs out of the textbox. See onTextboxBlur()
|
190
|
-
this.textboxControl.valueChanges.pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this.componentDestroyed)).subscribe(value => {
|
191
|
-
if (value) {
|
192
|
-
const parsedDate = moment(value, this.parseFormats);
|
193
|
-
if (parsedDate.isValid()) {
|
194
|
-
// If the parsed date is before the minDate, set the year to the current year.
|
195
|
-
// This prevents the calendar from showing unhelpful dates in the distant past as the user types
|
196
|
-
if (parsedDate.year() < this.minDate.getFullYear()) {
|
197
|
-
parsedDate.set('year', moment().year());
|
198
|
-
}
|
199
|
-
this.calendarSelection = parsedDate.toDate();
|
200
|
-
}
|
201
|
-
}
|
202
|
-
else {
|
203
|
-
this.calendarSelection = null;
|
204
|
-
}
|
205
|
-
});
|
206
|
-
}
|
207
|
-
syncTextboxControlDisabledStatus(status) {
|
208
|
-
// The textbox should only be disabled if the form model is disabled.
|
209
|
-
// All other statuses are considered enabled.
|
210
|
-
if (status === 'DISABLED' && this.textboxControl.enabled) {
|
211
|
-
this.textboxControl.disable();
|
212
|
-
}
|
213
|
-
else if (status !== 'DISABLED' && this.textboxControl.disabled) {
|
214
|
-
this.textboxControl.enable();
|
215
|
-
}
|
216
|
-
}
|
217
|
-
;
|
218
|
-
/**
|
219
|
-
* Updates the date parsing formats and placeholder based on the user's display preference.
|
220
|
-
* NOTE: This is async because we're retrieving the user's preferences. We're not awaiting the result
|
221
|
-
* because the only logic that depends on this is the text box date parsing logic and placeholder.
|
222
|
-
* Our forms should always be behind a pending overlay, so the user won't be able to interact with the
|
223
|
-
* form until the user is loaded anyway.
|
224
|
-
*/
|
225
|
-
async setDateFormats() {
|
226
|
-
const { preference } = await lastValueFrom(this.userPreferenceService.getPreferences());
|
227
|
-
const dateFormat = preference?.dateFormat;
|
228
|
-
this.placeholder = dateFormat ?? this.placeholder;
|
229
|
-
this.parseFormats = DateTimeHelper.getMomentParseFormats(dateFormat);
|
230
|
-
}
|
231
|
-
/** Focuses the date input. */
|
232
|
-
focusInput() {
|
233
|
-
this.el.nativeElement.querySelector('input')?.focus();
|
234
|
-
}
|
235
|
-
}
|
236
|
-
|
237
|
-
|
238
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
239
|
-
type: Component,
|
240
|
-
args: [{ selector: 'ec-date-input', template: "<label *ngIf=\"label\">\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors}}</span>\r\n <ec-help-popover id=\"{{id}}_helpPopover\"\r\n *ngIf=\"helpPopover\"\r\n class=\"d-inline-block my-n3 mx-n1\"\r\n text=\"{{helpPopover | translate}}\"\r\n contentPosition=\"{{helpPopoverPosition}}\">\r\n </ec-help-popover>\r\n</label>\r\n\r\n<ec-form-control id=\"{{id}}\"\r\n [required]=\"required\"\r\n [autofocus]=\"autofocus\"\r\n [pending]=\"pending\"\r\n [readonly]=\"readonly\"\r\n [formModel]=\"formModel\"\r\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\r\n (actionKeydown)=\"onActionKeydown($event)\"\r\n [showClear]=\"false\"\r\n actionIcon=\"icon-date\"\r\n cdkOverlayOrigin\r\n #overlayOrigin=\"cdkOverlayOrigin\">\r\n <input id=\"{{id}}_input\"\r\n type=\"text\"\r\n placeholder=\"{{placeholder}}\"\r\n [formControl]=\"textboxControl\"\r\n (blur)=\"onTextboxBlur()\"\r\n (keydown)=\"onTextboxKeydown($event)\">\r\n</ec-form-control>\r\n\r\n<ng-template cdkConnectedOverlay\r\n #overlay=\"cdkConnectedOverlay\"\r\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\r\n [cdkConnectedOverlayOpen]=\"isCalendarOpen\"\r\n [cdkConnectedOverlayScrollStrategy]=\"overlayScrollStrategy\"\r\n cdkConnectedOverlayPanelClass=\"my-1\"\r\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\r\n (detach)=\"isCalendarOpen = false\">\r\n <ec-calendar [id]=\"id + '_calendar'\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"\r\n [selection]=\"calendarSelection\"\r\n (selectionChange)=\"onSelectionChange($event)\"\r\n class=\"card px-1 pt-1 pb-2\"\r\n (focusOutStart)=\"onCalendarFocusOutStart($event)\"\r\n (focusOutEnd)=\"onCalendarFocusOutEnd($event)\">\r\n </ec-calendar>\r\n</ng-template>\r\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}\n"] }]
|
241
|
-
}], ctorParameters: function () { return [{ type: i1.ValidationMessageService }, { type: i2.FormGroupHelper }, { type: i3.UserPreferenceService }, { type: i4.DateDisplayPipe }, { type: i0.ElementRef }, { type: i5.Overlay }]; }, propDecorators: { id: [{
|
242
|
-
type: HostBinding,
|
243
|
-
args: ['attr.id']
|
244
|
-
}, {
|
245
|
-
type: Input
|
246
|
-
}], formModel: [{
|
247
|
-
type: Input
|
248
|
-
}], minDate: [{
|
249
|
-
type: Input
|
250
|
-
}], maxDate: [{
|
251
|
-
type: Input
|
252
|
-
}], overlay: [{
|
253
|
-
type: ViewChild,
|
254
|
-
args: ['overlay']
|
255
|
-
}] } });
|
256
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS1pbnB1dC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL3NyYy9saWIvY29udHJvbHMvZGF0ZS1pbnB1dC9kYXRlLWlucHV0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbXBvbmVudHMvc3JjL2xpYi9jb250cm9scy9kYXRlLWlucHV0L2RhdGUtaW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFNBQVMsRUFBYyxXQUFXLEVBQUUsS0FBSyxFQUFVLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3RixPQUFPLEVBQW1CLFdBQVcsRUFBa0MsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5RixPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyQyxPQUFPLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUs3RCxPQUFPLEVBQXFCLDZCQUE2QixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDOUYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDOzs7Ozs7Ozs7Ozs7O0FBU3ZELE1BQU0sT0FBTyxrQkFBbUIsU0FBUSxlQUFlO0lBc0NyRCxZQUNZLHdCQUFrRCxFQUNsRCxlQUFnQyxFQUNsQyxxQkFBNEMsRUFDNUMsZUFBZ0MsRUFDaEMsRUFBYyxFQUNkLGNBQXVCO1FBRS9CLEtBQUssQ0FBQyx3QkFBd0IsRUFBRSxlQUFlLENBQUMsQ0FBQztRQVB2Qyw2QkFBd0IsR0FBeEIsd0JBQXdCLENBQTBCO1FBQ2xELG9CQUFlLEdBQWYsZUFBZSxDQUFpQjtRQUNsQyww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LGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUMvQjthQUFNLElBQUksTUFBTSxLQUFLLFVBQVUsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRTtZQUNoRSxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQzlCO0lBQ0gsQ0FBQztJQUFBLENBQUM7SUFFRjs7Ozs7O09BTUc7SUFDSyxLQUFLLENBQUMsY0FBYztRQUMxQixNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsTUFBTSxhQUFhLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7UUFDeEYsTUFBTSxVQUFVLEdBQUcsVUFBVSxFQUFFLFVBQVUsQ0FBQztRQUMxQyxJQUFJLENBQUMsV0FBVyxHQUFHLFVBQVUsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDO1FBQ2xELElBQUksQ0FBQyxZQUFZLEdBQUcsY0FBYyxDQUFDLHFCQUFxQixDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFtQkQsOEJBQThCO0lBQ3RCLFVBQVU7UUFDaEIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQ3hELENBQUM7OytHQTlQVSxrQkFBa0I7bUdBQWxCLGtCQUFrQixzVENyQi9CLHd1RUFpREE7MkZENUJhLGtCQUFrQjtrQkFMOUIsU0FBUzsrQkFDRSxlQUFlOzhQQU9ULEVBQUU7c0JBRGpCLFdBQVc7dUJBQUMsU0FBUzs7c0JBQ3JCLEtBQUs7Z0JBR1UsU0FBUztzQkFBeEIsS0FBSztnQkFFVSxPQUFPO3NCQUF0QixLQUFLO2dCQUNVLE9BQU87c0JBQXRCLEtBQUs7Z0JBMkJnQixPQUFPO3NCQUE1QixTQUFTO3VCQUFDLFNBQVMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDZGtDb25uZWN0ZWRPdmVybGF5LCBPdmVybGF5IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL292ZXJsYXknO1xyXG5pbXBvcnQgeyBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEhvc3RCaW5kaW5nLCBJbnB1dCwgT25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBGb3JtQ29udHJvbCwgRm9ybUNvbnRyb2xTdGF0dXMsIFZhbGlkYXRvckZuIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XHJcbmltcG9ydCB7IGxhc3RWYWx1ZUZyb20gfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBEYXRlVGltZUhlbHBlciB9IGZyb20gJy4uLy4uL2NvcmUvZGF0ZS10aW1lLWhlbHBlcic7XHJcbmltcG9ydCB7IFZhbGlkYXRpb25NZXNzYWdlU2VydmljZSB9IGZyb20gJy4uLy4uL2NvcmUvdmFsaWRhdGlvbi1tZXNzYWdlLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBEYXRlRGlzcGxheVBpcGUgfSBmcm9tICcuLi8uLi9zaGFyZWQvZGlzcGxheS9waXBlcy9kYXRlLWRpc3BsYXkucGlwZSc7XHJcbmltcG9ydCB7IEZvcm1Hcm91cEhlbHBlciB9IGZyb20gJy4uLy4uL3NoYXJlZC9mb3JtLWdyb3VwLmhlbHBlcic7XHJcbmltcG9ydCB7IFVzZXJQcmVmZXJlbmNlU2VydmljZSB9IGZyb20gJy4uLy4uL3NoYXJlZC91c2VyLXByZWZlcmVuY2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IENhbGVuZGFyU2VsZWN0aW9uLCBpc0NhbGVuZGFyU2VsZWN0aW9uU2luZ2xlRGF0ZSB9IGZyb20gJy4uL2NhbGVuZGFyL2NhbGVuZGFyLnR5cGVzJztcclxuaW1wb3J0IHsgRm9ybUNvbnRyb2xCYXNlIH0gZnJvbSAnLi4vZm9ybS1jb250cm9sLWJhc2UnO1xyXG5cclxuZXhwb3J0IHR5cGUgRGF0ZUlucHV0Rm9ybUNvbnRyb2wgPSBGb3JtQ29udHJvbDxEYXRlIHwgbnVsbD47XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2VjLWRhdGUtaW5wdXQnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9kYXRlLWlucHV0LmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9kYXRlLWlucHV0LmNvbXBvbmVudC5zY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIERhdGVJbnB1dENvbXBvbmVudCBleHRlbmRzIEZvcm1Db250cm9sQmFzZSBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcblxyXG4gIEBIb3N0QmluZGluZygnYXR0ci5pZCcpXHJcbiAgQElucHV0KCkgcHVibGljIGlkOiBzdHJpbmcgPSAnJztcclxuXHJcbiAgLyoqIFRoZSBmb3JtIGNvbnRyb2wgcHJvdmlkZWQgYnkgdGhlIGhvc3RpbmcgZm9ybS4gKi9cclxuICBASW5wdXQoKSBwdWJsaWMgZm9ybU1vZGVsOiBEYXRlSW5wdXRGb3JtQ29udHJvbCA9IG5ldyBGb3JtQ29udHJvbDxEYXRlIHwgbnVsbD4obnVsbCk7XHJcblxyXG4gIEBJbnB1dCgpIHB1YmxpYyBtaW5EYXRlOiBEYXRlID0gRGF0ZVRpbWVIZWxwZXIubWluRGF0ZVBpY2tlckRhdGU7XHJcbiAgQElucHV0KCkgcHVibGljIG1heERhdGU6IERhdGUgPSBEYXRlVGltZUhlbHBlci5tYXhEYXRlUGlja2VyRGF0ZTtcclxuXHJcbiAgLyoqIFRoZSBpbnRlcm5hbCB0ZXh0Ym94J3MgZm9ybSBjb250cm9sLiAqL1xyXG4gIHB1YmxpYyB0ZXh0Ym94Q29udHJvbCA9IG5ldyBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPihudWxsKTtcclxuXHJcbiAgLyoqXHJcbiAgICogVGhlIGN1cnJlbnQgY2FsZW5kYXIgc2VsZWN0aW9uLlxyXG4gICAqIFVwZGF0ZWQgd2hlbiB0aGUgdXNlciBjbGlja3Mgb24gYSBjYWxlbmRhciBpdGVtIG9yIHdoZW4gdGhlIGRhdGUgZW50ZXJlZCBpbnRvIHRoZSB0ZXh0Ym94IGlzIHBhcnNlZC5cclxuICAgKi9cclxuICBwdWJsaWMgY2FsZW5kYXJTZWxlY3Rpb246IENhbGVuZGFyU2VsZWN0aW9uIHwgbnVsbCA9IG51bGw7XHJcblxyXG4gIC8qKiBDb250cm9scyB3aGV0aGVyIHRoZSBjYWxlbmRhciBvdmVybGF5IGlzIG9wZW4gb3Igbm90LiAqL1xyXG4gIHB1YmxpYyBpc0NhbGVuZGFyT3BlbiA9IGZhbHNlO1xyXG5cclxuICAvKiogUGxhY2Vob2xkZXIgZm9yIHRoZSB0ZXh0Ym94LiBVcGRhdGVkIHRvIHJlZmxlY3QgdGhlIHVzZXIncyBkYXRlIGRpc3BsYXkgcHJlZmVyZW5jZS4gKi9cclxuICBwdWJsaWMgcGxhY2Vob2xkZXI6IHN0cmluZyA9ICdNTS9ERC9ZWVlZJztcclxuXHJcbiAgLyoqIE92ZXJsYXkgc2Nyb2xsIHN0cmF0ZWd5IGZvciB0aGUgY2FsZW5kYXIgb3ZlcmxheS4gQ2xvc2VzIHRoZSBjYWxlbmRhciBvbiBzY3JvbGwuICovXHJcbiAgcHVibGljIG92ZXJsYXlTY3JvbGxTdHJhdGVneSA9IHRoaXMub3ZlcmxheVNlcnZpY2Uuc2Nyb2xsU3RyYXRlZ2llcy5jbG9zZSgpO1xyXG5cclxuICAvKiogXHJcbiAgICogRGF0ZSBwYXJzaW5nIGZvcm1hdHMgZm9yIHVzZXItZW50ZXJlZCBkYXRlcy4gRGVmYXVsdHMgdG8gbW9udGgtZmlyc3QgZm9ybWF0cywgYnV0IGlzIHVwZGF0ZWQgaW4gb25Jbml0XHJcbiAgICogdG8gdXNlIHRoZSB1c2VyJ3MgcHJlZmVycmVkIGRhdGUgZm9ybWF0LlxyXG4gICAqL1xyXG4gIHByaXZhdGUgcGFyc2VGb3JtYXRzOiBzdHJpbmdbXSA9IERhdGVUaW1lSGVscGVyLmdldFBhcnNlRm9ybWF0cygpO1xyXG5cclxuICAvKiogUmVmZXJlbmNlIHRvIHRoZSBvdmVybGF5IGRpcmVjdGl2ZSAoc2VlIHRlbXBsYXRlKS4gVXNlZCB0byBhY2Nlc3MgdGhlIG92ZXJsYXkncyBob3N0IGVsZW1lbnQgdG8gY29udHJvbCBmb2N1cy4gKi9cclxuICBAVmlld0NoaWxkKCdvdmVybGF5Jykgb3ZlcmxheT86IENka0Nvbm5lY3RlZE92ZXJsYXk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJvdGVjdGVkIHZhbGlkYXRpb25NZXNzYWdlU2VydmljZTogVmFsaWRhdGlvbk1lc3NhZ2VTZXJ2aWNlLFxyXG4gICAgcHJvdGVjdGVkIGZvcm1Hcm91cEhlbHBlcjogRm9ybUdyb3VwSGVscGVyLFxyXG4gICAgcHJpdmF0ZSB1c2VyUHJlZmVyZW5jZVNlcnZpY2U6IFVzZXJQcmVmZXJlbmNlU2VydmljZSxcclxuICAgIHByaXZhdGUgZGF0ZURpc3BsYXlQaXBlOiBEYXRlRGlzcGxheVBpcGUsXHJcbiAgICBwcml2YXRlIGVsOiBFbGVtZW50UmVmLFxyXG4gICAgcHJpdmF0ZSBvdmVybGF5U2VydmljZTogT3ZlcmxheVxyXG4gICkge1xyXG4gICAgc3VwZXIodmFsaWRhdGlvbk1lc3NhZ2VTZXJ2aWNlLCBmb3JtR3JvdXBIZWxwZXIpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEZvY3VzZXMgdGhlIGlucHV0IHdoZW5ldmVyIHRoZSBjYWxlbmRhciBpcyBzaGlmdC10YWJiZWQgb3V0IG9mLiAqL1xyXG4gIHB1YmxpYyBvbkNhbGVuZGFyRm9jdXNPdXRTdGFydChldmVudDogS2V5Ym9hcmRFdmVudCkge1xyXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgIHRoaXMuZm9jdXNJbnB1dCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqIENsb3NlcyB0aGUgY2FsZW5kYXIgYW5kIGZvY3VzZXMgdGhlIGlucHV0IHdoZW5ldmVyIHRoZSBjYWxlbmRhciBpcyB0YWJiZWQgb3V0IG9mLiAqL1xyXG4gIHB1YmxpYyBvbkNhbGVuZGFyRm9jdXNPdXRFbmQoZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcclxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICB0aGlzLmlzQ2FsZW5kYXJPcGVuID0gZmFsc2U7XHJcbiAgICB0aGlzLmZvY3VzSW5wdXQoKTtcclxuICB9XHJcblxyXG4gIC8qKiBDbG9zZSB0aGUgY2FsZW5kYXIgaWYgdGhlIHVzZXIgY2xpY2tzIG91dHNpZGUgb2YgdGhlIGNhbGVuZGFyIGFuZCBkYXRlIGlucHV0LiAqL1xyXG4gIHB1YmxpYyBvbk92ZXJsYXlPdXRzaWRlQ2xpY2soZXZlbnQ6IE1vdXNlRXZlbnQpIHtcclxuICAgIC8vIERvIG5vdCBjbG9zZSB0aGUgY2FsZW5kYXIgaWYgdGhlIGNsaWNrIHdhcyB3aXRoaW4gdGhlIGRhdGUgaW5wdXQgb3IgYWN0aW9uIGJ1dHRvblxyXG4gICAgY29uc3QgcmVjdCA9IHRoaXMuZWwubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICAgIGNvbnN0IGNsaWNrZWRPdXRzaWRlQ29udHJvbCA9IGV2ZW50LmNsaWVudFkgPCByZWN0LnRvcCB8fFxyXG4gICAgICBldmVudC5jbGllbnRZID4gcmVjdC5ib3R0b20gfHxcclxuICAgICAgZXZlbnQuY2xpZW50WCA8IHJlY3QubGVmdCB8fFxyXG4gICAgICBldmVudC5jbGllbnRYID4gcmVjdC5yaWdodDtcclxuICAgIC8vIEl0J3MgcG9zc2libGUgdGhhdCB0aGUgdXNlciBoaXQgZW50ZXIgb24gdGhlIGFjdGlvbiBidXR0b24gaW5zdGVhZCBvZiBjbGlja2luZyB3aXRoIHRoZSBtb3VzZS5cclxuICAgIC8vIEluIHRoaXMgY2FzZSB0aGUgXCJjbGlja1wiIGV2ZW50IHdpbGwgYmUgb3V0c2lkZSBvZiB0aGUgY29tcG9uZW50IGJlY2F1c2UgdGhlIGNsaWVudHggYW5kIHkgYXJlIDAsXHJcbiAgICAvLyBidXQgd2UgZG9uJ3Qgd2FudCB0byBjbG9zZSBpbiB0aGlzIGNhc2UgYmVjYXVzZSBidXR0b24gY2xpY2tzIHRyaWdnZXIgY2FsZW5kYXIgb3Blbi9jbG9zZSBzZXBhcmF0ZWx5LlxyXG4gICAgY29uc3QgaXNBY3Rpb25DbGljayA9ICg8SFRNTEVsZW1lbnQ+ZXZlbnQudGFyZ2V0KS5pZCA9PT0gYCR7dGhpcy5pZH1fYWN0aW9uYDtcclxuXHJcbiAgICBpZiAoIWlzQWN0aW9uQ2xpY2sgJiYgY2xpY2tlZE91dHNpZGVDb250cm9sKSB7XHJcbiAgICAgIHRoaXMuaXNDYWxlbmRhck9wZW4gPSBmYWxzZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBJZiB0aGUgdXNlciB0YWJzIG91dCBvZiB0aGUgZm9ybSBjb250cm9sJ3MgYWN0aW9uIGJ1dHRvbiBhbmQgdGhlIGNhbGVuZGFyIGlzIG9wZW4sIGZvY3VzIHRoZSBmaXJzdCBpdGVtIGluIHRoZSBjYWxlbmRhciBvdmVybGF5ICovXHJcbiAgcHVibGljIG9uQWN0aW9uS2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCkge1xyXG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ1RhYicgJiYgIWV2ZW50LnNoaWZ0S2V5ICYmIHRoaXMuaXNDYWxlbmRhck9wZW4pIHtcclxuICAgICAgLy8gUHJldmVudCB0aGUgZGVmYXVsdCB0YWIgYWN0aW9uIHNvIHRoZSBmb2N1cyBkb2Vzbid0IG1vdmUgdG8gdGhlIG5leHQgZWxlbWVudCBpbiB0aGUgdGFiIG9yZGVyIGFmdGVyIHdlIG1hbnVhbGx5IGZvY3VzIHRoZSBjYWxlbmRhciBidXR0b24uXHJcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgIC8vIEZvY3VzIHRoZSBmaXJzdCBidXR0b24gaW4gdGhlIGNhbGVuZGFyIG92ZXJsYXlcclxuICAgICAgY29uc3QgZmlyc3RCdXR0b246IEhUTUxCdXR0b25FbGVtZW50IHwgbnVsbCB8IHVuZGVmaW5lZCA9IHRoaXMub3ZlcmxheT8ub3ZlcmxheVJlZi5ob3N0RWxlbWVudC5xdWVyeVNlbGVjdG9yKCdidXR0b246bm90KDpkaXNhYmxlZCknKTtcclxuICAgICAgZmlyc3RCdXR0b24/LmZvY3VzKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25UZXh0Ym94S2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCkge1xyXG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ1RhYicgJiYgZXZlbnQuc2hpZnRLZXkpIHtcclxuICAgICAgLy8gSWYgdGhlIHVzZXIgaXMgdGFiYmluZyBiYWNrd2FyZHMgZnJvbSB0aGUgdGV4dGJveCwgY2xvc2UgdGhlIGNhbGVuZGFyLlxyXG4gICAgICB0aGlzLmlzQ2FsZW5kYXJPcGVuID0gZmFsc2U7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogV2hlbmV2ZXIgdGhlIHVzZXIgc2VsZWN0cyBhIGRhdGUgZnJvbSB0aGUgY2FsZW5kYXIsIHVwZGF0ZSB0aGUgZm9ybU1vZGVsIHdpdGggdGhlIHNlbGVjdGlvbiAqL1xyXG4gIHB1YmxpYyBvblNlbGVjdGlvbkNoYW5nZShzZWxlY3Rpb246IENhbGVuZGFyU2VsZWN0aW9uIHwgbnVsbCkge1xyXG4gICAgdGhpcy5jYWxlbmRhclNlbGVjdGlvbiA9IHNlbGVjdGlvbjtcclxuICAgIGlmIChpc0NhbGVuZGFyU2VsZWN0aW9uU2luZ2xlRGF0ZShzZWxlY3Rpb24pKSB7XHJcbiAgICAgIHRoaXMuZm9ybU1vZGVsLnNldFZhbHVlKHNlbGVjdGlvbik7XHJcbiAgICAgIHRoaXMuaXNDYWxlbmRhck9wZW4gPSBmYWxzZTtcclxuICAgICAgdGhpcy5mb2N1c0lucHV0KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25UZXh0Ym94Qmx1cigpIHtcclxuICAgIC8vIFBhcnNlIHRoZSB0ZXh0Ym94IHZhbHVlIGludG8gYSBkYXRlIGFuZCB1cGRhdGUgdGhlIGZvcm0gbW9kZWxcclxuICAgIGNvbnN0IHZhbHVlID0gdGhpcy50ZXh0Ym94Q29udHJvbC52YWx1ZTtcclxuICAgIGlmICh2YWx1ZSkge1xyXG4gICAgICBjb25zdCBwYXJzZWREYXRlID0gbW9tZW50KHZhbHVlLCB0aGlzLnBhcnNlRm9ybWF0cyk7XHJcbiAgICAgIGlmIChwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xyXG4gICAgICAgIHRoaXMuZm9ybU1vZGVsLnNldFZhbHVlKHBhcnNlZERhdGUudG9EYXRlKCkpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuZm9ybU1vZGVsLnNldFZhbHVlKG51bGwpO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmZvcm1Nb2RlbC5zZXRWYWx1ZShudWxsKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBVcGRhdGUgdGhlIGZvcm0gbW9kZWwncyB0b3VjaGVkIGFuZCBkaXJ0eSBzdGF0dXMgYmFzZWQgb24gdGhlIHRleHRib3gncyBzdGF0dXMuXHJcbiAgICAvLyBTaW5jZSB0aGUgdXNlciBpbnRlcmFjdHMgd2l0aCBhIGNvbnRyb2wgdGhhdCBpcyBpbnRlcm5hbCB0byB0aGlzIGNvbXBvbmVudCwgdGhlXHJcbiAgICAvLyBmb3JtIG1vZGVsJ3Mgc3RhdHVzIHdvbid0IGJlIHVwZGF0ZWQgYXV0b21hdGljYWxseS5cclxuICAgIGlmICh0aGlzLnRleHRib3hDb250cm9sLnRvdWNoZWQgJiYgIXRoaXMuZm9ybU1vZGVsLnRvdWNoZWQpIHtcclxuICAgICAgdGhpcy5mb3JtTW9kZWwubWFya0FzVG91Y2hlZCgpO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMudGV4dGJveENvbnRyb2wuZGlydHkgJiYgIXRoaXMuZm9ybU1vZGVsLmRpcnR5KSB7XHJcbiAgICAgIHRoaXMuZm9ybU1vZGVsLm1hcmtBc0RpcnR5KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIC8vIFNldHVwXHJcbiAgICBzdXBlci5uZ09uSW5pdCgpO1xyXG4gICAgdGhpcy5zZXREYXRlRm9ybWF0cygpO1xyXG5cclxuICAgIHRoaXMuZm9ybU1vZGVsLmFkZFZhbGlkYXRvcnModGhpcy5kYXRlVmFsaWRhdG9yKTtcclxuXHJcbiAgICAvLyBTdWJzY3JpcHRpb25zXHJcbiAgICB0aGlzLm9uRm9ybU1vZGVsU3RhdHVzQ2hhbmdlcygpO1xyXG4gICAgdGhpcy5vbkZvcm1Nb2RlbFZhbHVlQ2hhbmdlcygpO1xyXG4gICAgdGhpcy5vblRleHRib3hWYWx1ZUNoYW5nZXMoKTtcclxuXHJcbiAgICAvLyBTeW5jIHRoZSBpbml0aWFsIGRpc2FibGVkIHN0YXR1cyBhbmQgdmFsdWUgb2YgdGhlIHRleHRib3hcclxuICAgIHRoaXMuc3luY1RleHRib3hDb250cm9sRGlzYWJsZWRTdGF0dXModGhpcy5mb3JtTW9kZWwuc3RhdHVzKTtcclxuICAgIHRoaXMudGV4dGJveENvbnRyb2wuc2V0VmFsdWUodGhpcy5kYXRlRGlzcGxheVBpcGUudHJhbnNmb3JtKHRoaXMuZm9ybU1vZGVsLnZhbHVlLCB0cnVlKSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xyXG4gICAgdGhpcy5jYWxlbmRhclNlbGVjdGlvbiA9IHRoaXMuZm9ybU1vZGVsLnZhbHVlO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBvbkZvcm1Nb2RlbFN0YXR1c0NoYW5nZXMoKSB7XHJcbiAgICAvLyBLZWVwIHRoZSB0ZXh0Ym94Q29udHJvbCBkaXNhYmxlZCBzdGF0dXMgaW4gc3luYyB3aXRoIHRoZSBmb3JtTW9kZWxcclxuICAgIHRoaXMuZm9ybU1vZGVsLnN0YXR1c0NoYW5nZXMucGlwZShcclxuICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSxcclxuICAgICAgdGFrZVVudGlsKHRoaXMuY29tcG9uZW50RGVzdHJveWVkKVxyXG4gICAgKS5zdWJzY3JpYmUoc3RhdHVzID0+IHtcclxuICAgICAgdGhpcy5zeW5jVGV4dGJveENvbnRyb2xEaXNhYmxlZFN0YXR1cyhzdGF0dXMpO1xyXG5cclxuICAgICAgaWYgKHRoaXMuaXNDYWxlbmRhck9wZW4pIHtcclxuICAgICAgICAvLyBBcyB2YWxpZGF0aW9uIG1lc3NhZ2VzIGFwcGVhci9kaXNhcHBlYXIsIHRoZSBkYXRlIGlucHV0IG1heSBoYXZlIHNoaWZ0ZWQgdXAgb3IgZG93biBvbiB0aGUgcGFnZS5cclxuICAgICAgICAvLyBVcGRhdGUgdGhlIG92ZXJsYXkgcG9zaXRpb24gdG8gZW5zdXJlIGl0J3Mgc3RpbGwgYWxpZ25lZCB3aXRoIHRoZSB0ZXh0Ym94IGFuZCBub3QgYmxvY2tpbmcgaXQuXHJcbiAgICAgICAgLy8gU2V0dGltZW91dCBpcyBuZWVkZWQgdG8gZW5zdXJlIHRoZSBvdmVybGF5IGlzIGJlaW5nIHVwZGF0ZWQgYWZ0ZXIgdGhlIG1lc3NhZ2UgaXMgcmVuZGVyZWQuXHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLm92ZXJsYXk/Lm92ZXJsYXlSZWY/LnVwZGF0ZVBvc2l0aW9uKCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBvbkZvcm1Nb2RlbFZhbHVlQ2hhbmdlcygpIHtcclxuICAgIC8vIFVwZGF0ZSB0aGUgY2FsZW5kYXIgc2VsZWN0aW9uIHRleHRib3ggdmFsdWUgd2l0aCBhIGZvcm1hdHRlZCBkYXRlIHdoZW4gdGhlIGZvcm0gbW9kZWwgY2hhbmdlcy5cclxuICAgIC8vIFRoaXMgaXMgdXN1YWxseSB0cmlnZ2VyZWQgYnkgcHJvZ3JhbW1hdGljIGNoYW5nZXMgdG8gdGhlIGZvcm0gbW9kZWwgYnkgYSBwYXJlbnQgY29tcG9uZW50LlxyXG4gICAgdGhpcy5mb3JtTW9kZWwudmFsdWVDaGFuZ2VzLnBpcGUoXHJcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKChhLCBiKSA9PiBtb21lbnQoYSkuaXNTYW1lKGIsICdkYXknKSksXHJcbiAgICAgIHRha2VVbnRpbCh0aGlzLmNvbXBvbmVudERlc3Ryb3llZClcclxuICAgICkuc3Vic2NyaWJlKHZhbHVlID0+IHtcclxuICAgICAgY29uc3QgZGlzcGxheVZhbHVlID0gdGhpcy5kYXRlRGlzcGxheVBpcGUudHJhbnNmb3JtKHZhbHVlLCB0cnVlKTtcclxuICAgICAgLy8gRG9uJ3QgZW1pdCBhbiBldmVudCB3aGVuIHNldHRpbmcgdGhlIHRleHRib3ggdmFsdWUgdG8gYXZvaWQgY2lyY3VsYXIgdXBkYXRlcyBiZXR3ZWVuIHRoZSB0ZXh0Ym94IGFuZCBmb3JtIG1vZGVsLlxyXG4gICAgICB0aGlzLnRleHRib3hDb250cm9sLnNldFZhbHVlKGRpc3BsYXlWYWx1ZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xyXG4gICAgICB0aGlzLmNhbGVuZGFyU2VsZWN0aW9uID0gdmFsdWU7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgb25UZXh0Ym94VmFsdWVDaGFuZ2VzKCkge1xyXG4gICAgLy8gVXBkYXRlIHRoZSBjYWxlbmRhciBzZWxlY3Rpb24gd2hlbiB0aGUgdGV4dGJveCB2YWx1ZSBjaGFuZ2VzIHRvIHVwZGF0ZSB0aGUgY2FsZW5kYXIuXHJcbiAgICAvLyBXZSBkb24ndCBwYXRjaCB0aGUgZm9ybU1vZGVsIGhlcmUgYmVjYXVzZSB3ZSBkb24ndCB3YW50IHRvIHRyaWdnZXIgdGhlXHJcbiAgICAvLyBkYXRlIGZvcm1hdHRpbmcgbG9naWMgYW5kIG92ZXJ3cml0ZSB0aGUgdXNlcidzIGlucHV0LlxyXG4gICAgLy8gV2UnbGwgZG8gdGhhdCB3aGVuIHRoZSB1c2VyIGJsdXJzIG91dCBvZiB0aGUgdGV4dGJveC4gU2VlIG9uVGV4dGJveEJsdXIoKVxyXG4gICAgdGhpcy50ZXh0Ym94Q29udHJvbC52YWx1ZUNoYW5nZXMucGlwZShcclxuICAgICAgZGVib3VuY2VUaW1lKDMwMCksXHJcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXHJcbiAgICAgIHRha2VVbnRpbCh0aGlzLmNvbXBvbmVudERlc3Ryb3llZClcclxuICAgICkuc3Vic2NyaWJlKHZhbHVlID0+IHtcclxuICAgICAgaWYgKHZhbHVlKSB7XHJcbiAgICAgICAgY29uc3QgcGFyc2VkRGF0ZSA9IG1vbWVudCh2YWx1ZSwgdGhpcy5wYXJzZUZvcm1hdHMpO1xyXG4gICAgICAgIGlmIChwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xyXG4gICAgICAgICAgLy8gSWYgdGhlIHBhcnNlZCBkYXRlIGlzIGJlZm9yZSB0aGUgbWluRGF0ZSwgc2V0IHRoZSB5ZWFyIHRvIHRoZSBjdXJyZW50IHllYXIuXHJcbiAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBjYWxlbmRhciBmcm9tIHNob3dpbmcgdW5oZWxwZnVsIGRhdGVzIGluIHRoZSBkaXN0YW50IHBhc3QgYXMgdGhlIHVzZXIgdHlwZXNcclxuICAgICAgICAgIGlmIChwYXJzZWREYXRlLnllYXIoKSA8IHRoaXMubWluRGF0ZS5nZXRGdWxsWWVhcigpKSB7XHJcbiAgICAgICAgICAgIHBhcnNlZERhdGUuc2V0KCd5ZWFyJywgbW9tZW50KCkueWVhcigpKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHRoaXMuY2FsZW5kYXJTZWxlY3Rpb24gPSBwYXJzZWREYXRlLnRvRGF0ZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLmNhbGVuZGFyU2VsZWN0aW9uID0gbnVsbDtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN5bmNUZXh0Ym94Q29udHJvbERpc2FibGVkU3RhdHVzKHN0YXR1czogRm9ybUNvbnRyb2xTdGF0dXMpIHtcclxuICAgIC8vIFRoZSB0ZXh0Ym94IHNob3VsZCBvbmx5IGJlIGRpc2FibGVkIGlmIHRoZSBmb3JtIG1vZGVsIGlzIGRpc2FibGVkLlxyXG4gICAgLy8gQWxsIG90aGVyIHN0YXR1c2VzIGFyZSBjb25zaWRlcmVkIGVuYWJsZWQuXHJcbiAgICBpZiAoc3RhdHVzID09PSAnRElTQUJMRUQnICYmIHRoaXMudGV4dGJveENvbnRyb2wuZW5hYmxlZCkge1xyXG4gICAgICB0aGlzLnRleHRib3hDb250cm9sLmRpc2FibGUoKTtcclxuICAgIH0gZWxzZSBpZiAoc3RhdHVzICE9PSAnRElTQUJMRUQnICYmIHRoaXMudGV4dGJveENvbnRyb2wuZGlzYWJsZWQpIHtcclxuICAgICAgdGhpcy50ZXh0Ym94Q29udHJvbC5lbmFibGUoKTtcclxuICAgIH1cclxuICB9O1xyXG5cclxuICAvKiogXHJcbiAgICogVXBkYXRlcyB0aGUgZGF0ZSBwYXJzaW5nIGZvcm1hdHMgYW5kIHBsYWNlaG9sZGVyIGJhc2VkIG9uIHRoZSB1c2VyJ3MgZGlzcGxheSBwcmVmZXJlbmNlLlxyXG4gICAqIE5PVEU6IFRoaXMgaXMgYXN5bmMgYmVjYXVzZSB3ZSdyZSByZXRyaWV2aW5nIHRoZSB1c2VyJ3MgcHJlZmVyZW5jZXMuIFdlJ3JlIG5vdCBhd2FpdGluZyB0aGUgcmVzdWx0XHJcbiAgICogYmVjYXVzZSB0aGUgb25seSBsb2dpYyB0aGF0IGRlcGVuZHMgb24gdGhpcyBpcyB0aGUgdGV4dCBib3ggZGF0ZSBwYXJzaW5nIGxvZ2ljIGFuZCBwbGFjZWhvbGRlci5cclxuICAgKiBPdXIgZm9ybXMgc2hvdWxkIGFsd2F5cyBiZSBiZWhpbmQgYSBwZW5kaW5nIG92ZXJsYXksIHNvIHRoZSB1c2VyIHdvbid0IGJlIGFibGUgdG8gaW50ZXJhY3Qgd2l0aCB0aGVcclxuICAgKiBmb3JtIHVudGlsIHRoZSB1c2VyIGlzIGxvYWRlZCBhbnl3YXkuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhc3luYyBzZXREYXRlRm9ybWF0cygpIHtcclxuICAgIGNvbnN0IHsgcHJlZmVyZW5jZSB9ID0gYXdhaXQgbGFzdFZhbHVlRnJvbSh0aGlzLnVzZXJQcmVmZXJlbmNlU2VydmljZS5nZXRQcmVmZXJlbmNlcygpKTtcclxuICAgIGNvbnN0IGRhdGVGb3JtYXQgPSBwcmVmZXJlbmNlPy5kYXRlRm9ybWF0O1xyXG4gICAgdGhpcy5wbGFjZWhvbGRlciA9IGRhdGVGb3JtYXQgPz8gdGhpcy5wbGFjZWhvbGRlcjtcclxuICAgIHRoaXMucGFyc2VGb3JtYXRzID0gRGF0ZVRpbWVIZWxwZXIuZ2V0TW9tZW50UGFyc2VGb3JtYXRzKGRhdGVGb3JtYXQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVmFsaWRhdG9yIHRoYXQgY2hlY2tzIGlmIHRoZSBkYXRlIGlzIHdpdGhpbiB0aGUgbWluIGFuZCBtYXggZGF0ZSByYW5nZS5cclxuICAgKiBJZiB0aGUgZGF0ZSBpcyBvdXRzaWRlIG9mIHRoZSByYW5nZSwgdGhlIHZhbGlkYXRvciByZXR1cm5zIGFuIGVycm9yIHRoYXRcclxuICAgKiB0cmlnZ2VycyB0aGUgdmFsaWRhdGlvbiBtZXNzYWdlIHNlcnZpY2UgdG8gc2hvdyB0aGUgZXJyb3IgaW4gdGhlIGxhYmVsLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgZGF0ZVZhbGlkYXRvcjogVmFsaWRhdG9yRm4gPSAoY29udHJvbDogQWJzdHJhY3RDb250cm9sKSA9PiB7XHJcbiAgICBpZiAoY29udHJvbC52YWx1ZSkge1xyXG4gICAgICBpZiAoY29udHJvbC52YWx1ZSA8IHRoaXMubWluRGF0ZSkge1xyXG4gICAgICAgIHJldHVybiB7IG1pbkRhdGU6IHsgbWluVmFsdWU6IHRoaXMubWluRGF0ZSB9IH07XHJcbiAgICAgIH0gZWxzZSBpZiAoY29udHJvbC52YWx1ZSA+IHRoaXMubWF4RGF0ZSkge1xyXG4gICAgICAgIHJldHVybiB7IG1heERhdGU6IHsgbWF4VmFsdWU6IHRoaXMubWF4RGF0ZSB9IH07XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9O1xyXG5cclxuICAvKiogRm9jdXNlcyB0aGUgZGF0ZSBpbnB1dC4gKi9cclxuICBwcml2YXRlIGZvY3VzSW5wdXQoKSB7XHJcbiAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignaW5wdXQnKT8uZm9jdXMoKTtcclxuICB9XHJcbn1cclxuIiwiPGxhYmVsICpuZ0lmPVwibGFiZWxcIj5cclxuICA8c3Bhbj57e2xhYmVsIHwgdHJhbnNsYXRlfX08L3NwYW4+XHJcbiAgPHNwYW4gKm5nSWY9XCJ2YWxpZGF0aW9uRXJyb3JzLmxlbmd0aCA+IDAgJiYgZm9ybU1vZGVsLnRvdWNoZWQgJiYgZm9ybU1vZGVsLmludmFsaWRcIj4mbmJzcDt7e3ZhbGlkYXRpb25FcnJvcnN9fTwvc3Bhbj5cclxuICA8ZWMtaGVscC1wb3BvdmVyIGlkPVwie3tpZH19X2hlbHBQb3BvdmVyXCJcclxuICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiaGVscFBvcG92ZXJcIlxyXG4gICAgICAgICAgICAgICAgICAgY2xhc3M9XCJkLWlubGluZS1ibG9jayBteS1uMyBteC1uMVwiXHJcbiAgICAgICAgICAgICAgICAgICB0ZXh0PVwie3toZWxwUG9wb3ZlciB8IHRyYW5zbGF0ZX19XCJcclxuICAgICAgICAgICAgICAgICAgIGNvbnRlbnRQb3NpdGlvbj1cInt7aGVscFBvcG92ZXJQb3NpdGlvbn19XCI+XHJcbiAgPC9lYy1oZWxwLXBvcG92ZXI+XHJcbjwvbGFiZWw+XHJcblxyXG48ZWMtZm9ybS1jb250cm9sIGlkPVwie3tpZH19XCJcclxuICAgICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwicmVxdWlyZWRcIlxyXG4gICAgICAgICAgICAgICAgIFthdXRvZm9jdXNdPVwiYXV0b2ZvY3VzXCJcclxuICAgICAgICAgICAgICAgICBbcGVuZGluZ109XCJwZW5kaW5nXCJcclxuICAgICAgICAgICAgICAgICBbcmVhZG9ubHldPVwicmVhZG9ubHlcIlxyXG4gICAgICAgICAgICAgICAgIFtmb3JtTW9kZWxdPVwiZm9ybU1vZGVsXCJcclxuICAgICAgICAgICAgICAgICAoYWN0aW9uQ2xpY2tlZCk9XCJpc0NhbGVuZGFyT3BlbiA9ICFpc0NhbGVuZGFyT3BlblwiXHJcbiAgICAgICAgICAgICAgICAgKGFjdGlvbktleWRvd24pPVwib25BY3Rpb25LZXlkb3duKCRldmVudClcIlxyXG4gICAgICAgICAgICAgICAgIFtzaG93Q2xlYXJdPVwiZmFsc2VcIlxyXG4gICAgICAgICAgICAgICAgIGFjdGlvbkljb249XCJpY29uLWRhdGVcIlxyXG4gICAgICAgICAgICAgICAgIGNka092ZXJsYXlPcmlnaW5cclxuICAgICAgICAgICAgICAgICAjb3ZlcmxheU9yaWdpbj1cImNka092ZXJsYXlPcmlnaW5cIj5cclxuICA8aW5wdXQgaWQ9XCJ7e2lkfX1faW5wdXRcIlxyXG4gICAgICAgICB0eXBlPVwidGV4dFwiXHJcbiAgICAgICAgIHBsYWNlaG9sZGVyPVwie3twbGFjZWhvbGRlcn19XCJcclxuICAgICAgICAgW2Zvcm1Db250cm9sXT1cInRleHRib3hDb250cm9sXCJcclxuICAgICAgICAgKGJsdXIpPVwib25UZXh0Ym94Qmx1cigpXCJcclxuICAgICAgICAgKGtleWRvd24pPVwib25UZXh0Ym94S2V5ZG93bigkZXZlbnQpXCI+XHJcbjwvZWMtZm9ybS1jb250cm9sPlxyXG5cclxuPG5nLXRlbXBsYXRlIGNka0Nvbm5lY3RlZE92ZXJsYXlcclxuICAgICAgICAgICAgICNvdmVybGF5PVwiY2RrQ29ubmVjdGVkT3ZlcmxheVwiXHJcbiAgICAgICAgICAgICBbY2RrQ29ubmVjdGVkT3ZlcmxheU9yaWdpbl09XCJvdmVybGF5T3JpZ2luXCJcclxuICAgICAgICAgICAgIFtjZGtDb25uZWN0ZWRPdmVybGF5T3Blbl09XCJpc0NhbGVuZGFyT3BlblwiXHJcbiAgICAgICAgICAgICBbY2RrQ29ubmVjdGVkT3ZlcmxheVNjcm9sbFN0cmF0ZWd5XT1cIm92ZXJsYXlTY3JvbGxTdHJhdGVneVwiXHJcbiAgICAgICAgICAgICBjZGtDb25uZWN0ZWRPdmVybGF5UGFuZWxDbGFzcz1cIm15LTFcIlxyXG4gICAgICAgICAgICAgKG92ZXJsYXlPdXRzaWRlQ2xpY2spPVwib25PdmVybGF5T3V0c2lkZUNsaWNrKCRldmVudClcIlxyXG4gICAgICAgICAgICAgKGRldGFjaCk9XCJpc0NhbGVuZGFyT3BlbiA9IGZhbHNlXCI+XHJcbiAgPGVjLWNhbGVuZGFyIFtpZF09XCJpZCArICdfY2FsZW5kYXInXCJcclxuICAgICAgICAgICAgICAgW21pbkRhdGVdPVwibWluRGF0ZVwiXHJcbiAgICAgICAgICAgICAgIFttYXhEYXRlXT1cIm1heERhdGVcIlxyXG4gICAgICAgICAgICAgICBbc2VsZWN0aW9uXT1cImNhbGVuZGFyU2VsZWN0aW9uXCJcclxuICAgICAgICAgICAgICAgKHNlbGVjdGlvbkNoYW5nZSk9XCJvblNlbGVjdGlvbkNoYW5nZSgkZXZlbnQpXCJcclxuICAgICAgICAgICAgICAgY2xhc3M9XCJjYXJkIHB4LTEgcHQtMSBwYi0yXCJcclxuICAgICAgICAgICAgICAgKGZvY3VzT3V0U3RhcnQpPVwib25DYWxlbmRhckZvY3VzT3V0U3RhcnQoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgIChmb2N1c091dEVuZCk9XCJvbkNhbGVuZGFyRm9jdXNPdXRFbmQoJGV2ZW50KVwiPlxyXG4gIDwvZWMtY2FsZW5kYXI+XHJcbjwvbmctdGVtcGxhdGU+XHJcbiJdfQ==
|
1
|
+
import { Component, HostBinding, Input, ViewChild } from '@angular/core';
|
2
|
+
import { FormControl } 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 { isCalendarSelectionSingleDate } from '../calendar/calendar.types';
|
8
|
+
import { FormControlBase } from '../form-control-base';
|
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 "../../shared/display/pipes/date-display.pipe";
|
14
|
+
import * as i5 from "@angular/cdk/overlay";
|
15
|
+
import * as i6 from "@angular/common";
|
16
|
+
import * as i7 from "@angular/forms";
|
17
|
+
import * as i8 from "../form-control/form-control.component";
|
18
|
+
import * as i9 from "../help-popover/help-popover.component";
|
19
|
+
import * as i10 from "../calendar/calendar.component";
|
20
|
+
import * as i11 from "@ngx-translate/core";
|
21
|
+
export class DateInputComponent extends FormControlBase {
|
22
|
+
constructor(validationMessageService, formGroupHelper, userPreferenceService, dateDisplayPipe, el, overlayService) {
|
23
|
+
super(validationMessageService, formGroupHelper);
|
24
|
+
this.validationMessageService = validationMessageService;
|
25
|
+
this.formGroupHelper = formGroupHelper;
|
26
|
+
this.userPreferenceService = userPreferenceService;
|
27
|
+
this.dateDisplayPipe = dateDisplayPipe;
|
28
|
+
this.el = el;
|
29
|
+
this.overlayService = overlayService;
|
30
|
+
this.id = '';
|
31
|
+
/** The form control provided by the hosting form. */
|
32
|
+
this.formModel = new FormControl(null);
|
33
|
+
this.minDate = DateTimeHelper.minDatePickerDate;
|
34
|
+
this.maxDate = DateTimeHelper.maxDatePickerDate;
|
35
|
+
/** The internal textbox's form control. */
|
36
|
+
this.textboxControl = new FormControl(null);
|
37
|
+
/**
|
38
|
+
* The current calendar selection.
|
39
|
+
* Updated when the user clicks on a calendar item or when the date entered into the textbox is parsed.
|
40
|
+
*/
|
41
|
+
this.calendarSelection = null;
|
42
|
+
/** Controls whether the calendar overlay is open or not. */
|
43
|
+
this.isCalendarOpen = false;
|
44
|
+
/** Placeholder for the textbox. Updated to reflect the user's date display preference. */
|
45
|
+
this.placeholder = 'MM/DD/YYYY';
|
46
|
+
/** Overlay scroll strategy for the calendar overlay. Closes the calendar on scroll. */
|
47
|
+
this.overlayScrollStrategy = this.overlayService.scrollStrategies.close();
|
48
|
+
/**
|
49
|
+
* Date parsing formats for user-entered dates. Defaults to month-first formats, but is updated in onInit
|
50
|
+
* to use the user's preferred date format.
|
51
|
+
*/
|
52
|
+
this.parseFormats = DateTimeHelper.getParseFormats();
|
53
|
+
/**
|
54
|
+
* Validator that checks if the date is within the min and max date range.
|
55
|
+
* If the date is outside of the range, the validator returns an error that
|
56
|
+
* triggers the validation message service to show the error in the label.
|
57
|
+
*/
|
58
|
+
this.dateValidator = (control) => {
|
59
|
+
if (control.value) {
|
60
|
+
if (control.value < this.minDate) {
|
61
|
+
return { minDate: { minValue: this.minDate } };
|
62
|
+
}
|
63
|
+
else if (control.value > this.maxDate) {
|
64
|
+
return { maxDate: { maxValue: this.maxDate } };
|
65
|
+
}
|
66
|
+
}
|
67
|
+
return null;
|
68
|
+
};
|
69
|
+
}
|
70
|
+
/** Focuses the input whenever the calendar is shift-tabbed out of. */
|
71
|
+
onCalendarFocusOutStart(event) {
|
72
|
+
event.preventDefault();
|
73
|
+
this.focusInput();
|
74
|
+
}
|
75
|
+
/** Closes the calendar and focuses the input whenever the calendar is tabbed out of. */
|
76
|
+
onCalendarFocusOutEnd(event) {
|
77
|
+
event.preventDefault();
|
78
|
+
this.isCalendarOpen = false;
|
79
|
+
this.focusInput();
|
80
|
+
}
|
81
|
+
/** Close the calendar if the user clicks outside of the calendar and date input. */
|
82
|
+
onOverlayOutsideClick(event) {
|
83
|
+
// Do not close the calendar if the click was within the date input or action button
|
84
|
+
const rect = this.el.nativeElement.getBoundingClientRect();
|
85
|
+
const clickedOutsideControl = event.clientY < rect.top ||
|
86
|
+
event.clientY > rect.bottom ||
|
87
|
+
event.clientX < rect.left ||
|
88
|
+
event.clientX > rect.right;
|
89
|
+
// It's possible that the user hit enter on the action button instead of clicking with the mouse.
|
90
|
+
// In this case the "click" event will be outside of the component because the clientx and y are 0,
|
91
|
+
// but we don't want to close in this case because button clicks trigger calendar open/close separately.
|
92
|
+
const isActionClick = event.target.id === `${this.id}_action`;
|
93
|
+
if (!isActionClick && clickedOutsideControl) {
|
94
|
+
this.isCalendarOpen = false;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
/** 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 */
|
98
|
+
onActionKeydown(event) {
|
99
|
+
if (event.key === 'Tab' && !event.shiftKey && this.isCalendarOpen) {
|
100
|
+
// Prevent the default tab action so the focus doesn't move to the next element in the tab order after we manually focus the calendar button.
|
101
|
+
event.preventDefault();
|
102
|
+
// Focus the first button in the calendar overlay
|
103
|
+
const firstButton = this.overlay?.overlayRef.hostElement.querySelector('button:not(:disabled)');
|
104
|
+
firstButton?.focus();
|
105
|
+
}
|
106
|
+
}
|
107
|
+
onTextboxKeydown(event) {
|
108
|
+
if (event.key === 'Tab' && event.shiftKey) {
|
109
|
+
// If the user is tabbing backwards from the textbox, close the calendar.
|
110
|
+
this.isCalendarOpen = false;
|
111
|
+
}
|
112
|
+
}
|
113
|
+
/** Whenever the user selects a date from the calendar, update the formModel with the selection */
|
114
|
+
onSelectionChange(selection) {
|
115
|
+
this.calendarSelection = selection;
|
116
|
+
if (isCalendarSelectionSingleDate(selection)) {
|
117
|
+
this.formModel.setValue(selection);
|
118
|
+
this.isCalendarOpen = false;
|
119
|
+
this.focusInput();
|
120
|
+
}
|
121
|
+
}
|
122
|
+
onTextboxBlur() {
|
123
|
+
// Parse the textbox value into a date and update the form model
|
124
|
+
const value = this.textboxControl.value;
|
125
|
+
if (value) {
|
126
|
+
const parsedDate = moment(value, this.parseFormats);
|
127
|
+
if (parsedDate.isValid()) {
|
128
|
+
this.formModel.setValue(parsedDate.toDate());
|
129
|
+
}
|
130
|
+
else {
|
131
|
+
this.formModel.setValue(null);
|
132
|
+
}
|
133
|
+
}
|
134
|
+
else {
|
135
|
+
this.formModel.setValue(null);
|
136
|
+
}
|
137
|
+
// Update the form model's touched and dirty status based on the textbox's status.
|
138
|
+
// Since the user interacts with a control that is internal to this component, the
|
139
|
+
// form model's status won't be updated automatically.
|
140
|
+
if (this.textboxControl.touched && !this.formModel.touched) {
|
141
|
+
this.formModel.markAsTouched();
|
142
|
+
}
|
143
|
+
if (this.textboxControl.dirty && !this.formModel.dirty) {
|
144
|
+
this.formModel.markAsDirty();
|
145
|
+
}
|
146
|
+
}
|
147
|
+
ngOnInit() {
|
148
|
+
// Setup
|
149
|
+
super.ngOnInit();
|
150
|
+
this.setDateFormats();
|
151
|
+
this.formModel.addValidators(this.dateValidator);
|
152
|
+
// Subscriptions
|
153
|
+
this.onFormModelStatusChanges();
|
154
|
+
this.onFormModelValueChanges();
|
155
|
+
this.onTextboxValueChanges();
|
156
|
+
// Sync the initial disabled status and value of the textbox
|
157
|
+
this.syncTextboxControlDisabledStatus(this.formModel.status);
|
158
|
+
this.textboxControl.setValue(this.dateDisplayPipe.transform(this.formModel.value, true), { emitEvent: false });
|
159
|
+
this.calendarSelection = this.formModel.value;
|
160
|
+
}
|
161
|
+
onFormModelStatusChanges() {
|
162
|
+
// Keep the textboxControl disabled status in sync with the formModel
|
163
|
+
this.formModel.statusChanges.pipe(distinctUntilChanged(), takeUntil(this.componentDestroyed)).subscribe(status => {
|
164
|
+
this.syncTextboxControlDisabledStatus(status);
|
165
|
+
if (this.isCalendarOpen) {
|
166
|
+
// As validation messages appear/disappear, the date input may have shifted up or down on the page.
|
167
|
+
// Update the overlay position to ensure it's still aligned with the textbox and not blocking it.
|
168
|
+
// Settimeout is needed to ensure the overlay is being updated after the message is rendered.
|
169
|
+
setTimeout(() => {
|
170
|
+
this.overlay?.overlayRef?.updatePosition();
|
171
|
+
});
|
172
|
+
}
|
173
|
+
});
|
174
|
+
}
|
175
|
+
onFormModelValueChanges() {
|
176
|
+
// Update the calendar selection textbox value with a formatted date when the form model changes.
|
177
|
+
// This is usually triggered by programmatic changes to the form model by a parent component.
|
178
|
+
this.formModel.valueChanges.pipe(distinctUntilChanged((a, b) => moment(a).isSame(b, 'day')), takeUntil(this.componentDestroyed)).subscribe(value => {
|
179
|
+
const displayValue = this.dateDisplayPipe.transform(value, true);
|
180
|
+
// Don't emit an event when setting the textbox value to avoid circular updates between the textbox and form model.
|
181
|
+
this.textboxControl.setValue(displayValue, { emitEvent: false });
|
182
|
+
this.calendarSelection = value;
|
183
|
+
});
|
184
|
+
}
|
185
|
+
onTextboxValueChanges() {
|
186
|
+
// Update the calendar selection when the textbox value changes to update the calendar.
|
187
|
+
// We don't patch the formModel here because we don't want to trigger the
|
188
|
+
// date formatting logic and overwrite the user's input.
|
189
|
+
// We'll do that when the user blurs out of the textbox. See onTextboxBlur()
|
190
|
+
this.textboxControl.valueChanges.pipe(debounceTime(300), distinctUntilChanged(), takeUntil(this.componentDestroyed)).subscribe(value => {
|
191
|
+
if (value) {
|
192
|
+
const parsedDate = moment(value, this.parseFormats);
|
193
|
+
if (parsedDate.isValid()) {
|
194
|
+
// If the parsed date is before the minDate, set the year to the current year.
|
195
|
+
// This prevents the calendar from showing unhelpful dates in the distant past as the user types
|
196
|
+
if (parsedDate.year() < this.minDate.getFullYear()) {
|
197
|
+
parsedDate.set('year', moment().year());
|
198
|
+
}
|
199
|
+
this.calendarSelection = parsedDate.toDate();
|
200
|
+
}
|
201
|
+
}
|
202
|
+
else {
|
203
|
+
this.calendarSelection = null;
|
204
|
+
}
|
205
|
+
});
|
206
|
+
}
|
207
|
+
syncTextboxControlDisabledStatus(status) {
|
208
|
+
// The textbox should only be disabled if the form model is disabled.
|
209
|
+
// All other statuses are considered enabled.
|
210
|
+
if (status === 'DISABLED' && this.textboxControl.enabled) {
|
211
|
+
this.textboxControl.disable();
|
212
|
+
}
|
213
|
+
else if (status !== 'DISABLED' && this.textboxControl.disabled) {
|
214
|
+
this.textboxControl.enable();
|
215
|
+
}
|
216
|
+
}
|
217
|
+
;
|
218
|
+
/**
|
219
|
+
* Updates the date parsing formats and placeholder based on the user's display preference.
|
220
|
+
* NOTE: This is async because we're retrieving the user's preferences. We're not awaiting the result
|
221
|
+
* because the only logic that depends on this is the text box date parsing logic and placeholder.
|
222
|
+
* Our forms should always be behind a pending overlay, so the user won't be able to interact with the
|
223
|
+
* form until the user is loaded anyway.
|
224
|
+
*/
|
225
|
+
async setDateFormats() {
|
226
|
+
const { preference } = await lastValueFrom(this.userPreferenceService.getPreferences());
|
227
|
+
const dateFormat = preference?.dateFormat;
|
228
|
+
this.placeholder = dateFormat ?? this.placeholder;
|
229
|
+
this.parseFormats = DateTimeHelper.getMomentParseFormats(dateFormat);
|
230
|
+
}
|
231
|
+
/** Focuses the date input. */
|
232
|
+
focusInput() {
|
233
|
+
this.el.nativeElement.querySelector('input')?.focus();
|
234
|
+
}
|
235
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DateInputComponent, deps: [{ token: i1.ValidationMessageService }, { token: i2.FormGroupHelper }, { token: i3.UserPreferenceService }, { token: i4.DateDisplayPipe }, { token: i0.ElementRef }, { token: i5.Overlay }], target: i0.ɵɵFactoryTarget.Component }); }
|
236
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: DateInputComponent, selector: "ec-date-input", inputs: { id: "id", formModel: "formModel", minDate: "minDate", maxDate: "maxDate" }, host: { properties: { "attr.id": "this.id" } }, viewQueries: [{ propertyName: "overlay", first: true, predicate: ["overlay"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<label *ngIf=\"label\">\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors}}</span>\r\n <ec-help-popover id=\"{{id}}_helpPopover\"\r\n *ngIf=\"helpPopover\"\r\n class=\"d-inline-block my-n3 mx-n1\"\r\n text=\"{{helpPopover | translate}}\"\r\n contentPosition=\"{{helpPopoverPosition}}\">\r\n </ec-help-popover>\r\n</label>\r\n\r\n<ec-form-control id=\"{{id}}\"\r\n [required]=\"required\"\r\n [autofocus]=\"autofocus\"\r\n [pending]=\"pending\"\r\n [readonly]=\"readonly\"\r\n [formModel]=\"formModel\"\r\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\r\n (actionKeydown)=\"onActionKeydown($event)\"\r\n [showClear]=\"false\"\r\n actionIcon=\"icon-date\"\r\n cdkOverlayOrigin\r\n #overlayOrigin=\"cdkOverlayOrigin\">\r\n <input id=\"{{id}}_input\"\r\n type=\"text\"\r\n placeholder=\"{{placeholder}}\"\r\n [formControl]=\"textboxControl\"\r\n (blur)=\"onTextboxBlur()\"\r\n (keydown)=\"onTextboxKeydown($event)\">\r\n</ec-form-control>\r\n\r\n<ng-template cdkConnectedOverlay\r\n #overlay=\"cdkConnectedOverlay\"\r\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\r\n [cdkConnectedOverlayOpen]=\"isCalendarOpen\"\r\n [cdkConnectedOverlayScrollStrategy]=\"overlayScrollStrategy\"\r\n cdkConnectedOverlayPanelClass=\"my-1\"\r\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\r\n (detach)=\"isCalendarOpen = false\">\r\n <ec-calendar [id]=\"id + '_calendar'\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"\r\n [selection]=\"calendarSelection\"\r\n (selectionChange)=\"onSelectionChange($event)\"\r\n class=\"card px-1 pt-1 pb-2\"\r\n (focusOutStart)=\"onCalendarFocusOutStart($event)\"\r\n (focusOutEnd)=\"onCalendarFocusOutEnd($event)\">\r\n </ec-calendar>\r\n</ng-template>\r\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}\n"], dependencies: [{ 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: i5.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"], outputs: ["backdropClick", "positionChange", "attach", "detach", "overlayKeydown", "overlayOutsideClick"], exportAs: ["cdkConnectedOverlay"] }, { kind: "directive", type: i5.CdkOverlayOrigin, selector: "[cdk-overlay-origin], [overlay-origin], [cdkOverlayOrigin]", exportAs: ["cdkOverlayOrigin"] }, { kind: "component", type: i8.FormControlComponent, selector: "ec-form-control", inputs: ["id", "icon", "actionIcon", "showClear", "formModel", "autofocus", "pending", "required", "readonly"], outputs: ["actionClicked", "actionKeydown"] }, { kind: "component", type: i9.HelpPopoverComponent, selector: "ec-help-popover", inputs: ["id", "text", "contentPosition", "maxWidth"] }, { kind: "component", type: i10.CalendarComponent, selector: "ec-calendar", inputs: ["id", "selection", "minDate", "maxDate"], outputs: ["selectionChange", "focusOutStart", "focusOutEnd"] }, { kind: "pipe", type: i11.TranslatePipe, name: "translate" }] }); }
|
237
|
+
}
|
238
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: DateInputComponent, decorators: [{
|
239
|
+
type: Component,
|
240
|
+
args: [{ selector: 'ec-date-input', template: "<label *ngIf=\"label\">\r\n <span>{{label | translate}}</span>\r\n <span *ngIf=\"validationErrors.length > 0 && formModel.touched && formModel.invalid\"> {{validationErrors}}</span>\r\n <ec-help-popover id=\"{{id}}_helpPopover\"\r\n *ngIf=\"helpPopover\"\r\n class=\"d-inline-block my-n3 mx-n1\"\r\n text=\"{{helpPopover | translate}}\"\r\n contentPosition=\"{{helpPopoverPosition}}\">\r\n </ec-help-popover>\r\n</label>\r\n\r\n<ec-form-control id=\"{{id}}\"\r\n [required]=\"required\"\r\n [autofocus]=\"autofocus\"\r\n [pending]=\"pending\"\r\n [readonly]=\"readonly\"\r\n [formModel]=\"formModel\"\r\n (actionClicked)=\"isCalendarOpen = !isCalendarOpen\"\r\n (actionKeydown)=\"onActionKeydown($event)\"\r\n [showClear]=\"false\"\r\n actionIcon=\"icon-date\"\r\n cdkOverlayOrigin\r\n #overlayOrigin=\"cdkOverlayOrigin\">\r\n <input id=\"{{id}}_input\"\r\n type=\"text\"\r\n placeholder=\"{{placeholder}}\"\r\n [formControl]=\"textboxControl\"\r\n (blur)=\"onTextboxBlur()\"\r\n (keydown)=\"onTextboxKeydown($event)\">\r\n</ec-form-control>\r\n\r\n<ng-template cdkConnectedOverlay\r\n #overlay=\"cdkConnectedOverlay\"\r\n [cdkConnectedOverlayOrigin]=\"overlayOrigin\"\r\n [cdkConnectedOverlayOpen]=\"isCalendarOpen\"\r\n [cdkConnectedOverlayScrollStrategy]=\"overlayScrollStrategy\"\r\n cdkConnectedOverlayPanelClass=\"my-1\"\r\n (overlayOutsideClick)=\"onOverlayOutsideClick($event)\"\r\n (detach)=\"isCalendarOpen = false\">\r\n <ec-calendar [id]=\"id + '_calendar'\"\r\n [minDate]=\"minDate\"\r\n [maxDate]=\"maxDate\"\r\n [selection]=\"calendarSelection\"\r\n (selectionChange)=\"onSelectionChange($event)\"\r\n class=\"card px-1 pt-1 pb-2\"\r\n (focusOutStart)=\"onCalendarFocusOutStart($event)\"\r\n (focusOutEnd)=\"onCalendarFocusOutEnd($event)\">\r\n </ec-calendar>\r\n</ng-template>\r\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}\n"] }]
|
241
|
+
}], ctorParameters: function () { return [{ type: i1.ValidationMessageService }, { type: i2.FormGroupHelper }, { type: i3.UserPreferenceService }, { type: i4.DateDisplayPipe }, { type: i0.ElementRef }, { type: i5.Overlay }]; }, propDecorators: { id: [{
|
242
|
+
type: HostBinding,
|
243
|
+
args: ['attr.id']
|
244
|
+
}, {
|
245
|
+
type: Input
|
246
|
+
}], formModel: [{
|
247
|
+
type: Input
|
248
|
+
}], minDate: [{
|
249
|
+
type: Input
|
250
|
+
}], maxDate: [{
|
251
|
+
type: Input
|
252
|
+
}], overlay: [{
|
253
|
+
type: ViewChild,
|
254
|
+
args: ['overlay']
|
255
|
+
}] } });
|
256
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGF0ZS1pbnB1dC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9jb21wb25lbnRzL3NyYy9saWIvY29udHJvbHMvZGF0ZS1pbnB1dC9kYXRlLWlucHV0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2NvbXBvbmVudHMvc3JjL2xpYi9jb250cm9scy9kYXRlLWlucHV0L2RhdGUtaW5wdXQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLFNBQVMsRUFBYyxXQUFXLEVBQUUsS0FBSyxFQUFVLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3RixPQUFPLEVBQW1CLFdBQVcsRUFBa0MsTUFBTSxnQkFBZ0IsQ0FBQztBQUM5RixPQUFPLE1BQU0sTUFBTSxRQUFRLENBQUM7QUFDNUIsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUNyQyxPQUFPLEVBQUUsWUFBWSxFQUFFLG9CQUFvQixFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQy9FLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUs3RCxPQUFPLEVBQXFCLDZCQUE2QixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDOUYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHNCQUFzQixDQUFDOzs7Ozs7Ozs7Ozs7O0FBU3ZELE1BQU0sT0FBTyxrQkFBbUIsU0FBUSxlQUFlO0lBc0NyRCxZQUNZLHdCQUFrRCxFQUNsRCxlQUFnQyxFQUNsQyxxQkFBNEMsRUFDNUMsZUFBZ0MsRUFDaEMsRUFBYyxFQUNkLGNBQXVCO1FBRS9CLEtBQUssQ0FBQyx3QkFBd0IsRUFBRSxlQUFlLENBQUMsQ0FBQztRQVB2Qyw2QkFBd0IsR0FBeEIsd0JBQXdCLENBQTBCO1FBQ2xELG9CQUFlLEdBQWYsZUFBZSxDQUFpQjtRQUNsQyww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LGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUMvQjthQUFNLElBQUksTUFBTSxLQUFLLFVBQVUsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLFFBQVEsRUFBRTtZQUNoRSxJQUFJLENBQUMsY0FBYyxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQzlCO0lBQ0gsQ0FBQztJQUFBLENBQUM7SUFFRjs7Ozs7O09BTUc7SUFDSyxLQUFLLENBQUMsY0FBYztRQUMxQixNQUFNLEVBQUUsVUFBVSxFQUFFLEdBQUcsTUFBTSxhQUFhLENBQUMsSUFBSSxDQUFDLHFCQUFxQixDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUM7UUFDeEYsTUFBTSxVQUFVLEdBQUcsVUFBVSxFQUFFLFVBQVUsQ0FBQztRQUMxQyxJQUFJLENBQUMsV0FBVyxHQUFHLFVBQVUsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDO1FBQ2xELElBQUksQ0FBQyxZQUFZLEdBQUcsY0FBYyxDQUFDLHFCQUFxQixDQUFDLFVBQVUsQ0FBQyxDQUFDO0lBQ3ZFLENBQUM7SUFtQkQsOEJBQThCO0lBQ3RCLFVBQVU7UUFDaEIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsYUFBYSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDO0lBQ3hELENBQUM7K0dBOVBVLGtCQUFrQjttR0FBbEIsa0JBQWtCLHNUQ3JCL0Isd3VFQWlEQTs7NEZENUJhLGtCQUFrQjtrQkFMOUIsU0FBUzsrQkFDRSxlQUFlOzhQQU9ULEVBQUU7c0JBRGpCLFdBQVc7dUJBQUMsU0FBUzs7c0JBQ3JCLEtBQUs7Z0JBR1UsU0FBUztzQkFBeEIsS0FBSztnQkFFVSxPQUFPO3NCQUF0QixLQUFLO2dCQUNVLE9BQU87c0JBQXRCLEtBQUs7Z0JBMkJnQixPQUFPO3NCQUE1QixTQUFTO3VCQUFDLFNBQVMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDZGtDb25uZWN0ZWRPdmVybGF5LCBPdmVybGF5IH0gZnJvbSAnQGFuZ3VsYXIvY2RrL292ZXJsYXknO1xyXG5pbXBvcnQgeyBDb21wb25lbnQsIEVsZW1lbnRSZWYsIEhvc3RCaW5kaW5nLCBJbnB1dCwgT25Jbml0LCBWaWV3Q2hpbGQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQWJzdHJhY3RDb250cm9sLCBGb3JtQ29udHJvbCwgRm9ybUNvbnRyb2xTdGF0dXMsIFZhbGlkYXRvckZuIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XHJcbmltcG9ydCB7IGxhc3RWYWx1ZUZyb20gfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgZGVib3VuY2VUaW1lLCBkaXN0aW5jdFVudGlsQ2hhbmdlZCwgdGFrZVVudGlsIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xyXG5pbXBvcnQgeyBEYXRlVGltZUhlbHBlciB9IGZyb20gJy4uLy4uL2NvcmUvZGF0ZS10aW1lLWhlbHBlcic7XHJcbmltcG9ydCB7IFZhbGlkYXRpb25NZXNzYWdlU2VydmljZSB9IGZyb20gJy4uLy4uL2NvcmUvdmFsaWRhdGlvbi1tZXNzYWdlLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBEYXRlRGlzcGxheVBpcGUgfSBmcm9tICcuLi8uLi9zaGFyZWQvZGlzcGxheS9waXBlcy9kYXRlLWRpc3BsYXkucGlwZSc7XHJcbmltcG9ydCB7IEZvcm1Hcm91cEhlbHBlciB9IGZyb20gJy4uLy4uL3NoYXJlZC9mb3JtLWdyb3VwLmhlbHBlcic7XHJcbmltcG9ydCB7IFVzZXJQcmVmZXJlbmNlU2VydmljZSB9IGZyb20gJy4uLy4uL3NoYXJlZC91c2VyLXByZWZlcmVuY2Uuc2VydmljZSc7XHJcbmltcG9ydCB7IENhbGVuZGFyU2VsZWN0aW9uLCBpc0NhbGVuZGFyU2VsZWN0aW9uU2luZ2xlRGF0ZSB9IGZyb20gJy4uL2NhbGVuZGFyL2NhbGVuZGFyLnR5cGVzJztcclxuaW1wb3J0IHsgRm9ybUNvbnRyb2xCYXNlIH0gZnJvbSAnLi4vZm9ybS1jb250cm9sLWJhc2UnO1xyXG5cclxuZXhwb3J0IHR5cGUgRGF0ZUlucHV0Rm9ybUNvbnRyb2wgPSBGb3JtQ29udHJvbDxEYXRlIHwgbnVsbD47XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2VjLWRhdGUtaW5wdXQnLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9kYXRlLWlucHV0LmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9kYXRlLWlucHV0LmNvbXBvbmVudC5zY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIERhdGVJbnB1dENvbXBvbmVudCBleHRlbmRzIEZvcm1Db250cm9sQmFzZSBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcblxyXG4gIEBIb3N0QmluZGluZygnYXR0ci5pZCcpXHJcbiAgQElucHV0KCkgcHVibGljIGlkOiBzdHJpbmcgPSAnJztcclxuXHJcbiAgLyoqIFRoZSBmb3JtIGNvbnRyb2wgcHJvdmlkZWQgYnkgdGhlIGhvc3RpbmcgZm9ybS4gKi9cclxuICBASW5wdXQoKSBwdWJsaWMgZm9ybU1vZGVsOiBEYXRlSW5wdXRGb3JtQ29udHJvbCA9IG5ldyBGb3JtQ29udHJvbDxEYXRlIHwgbnVsbD4obnVsbCk7XHJcblxyXG4gIEBJbnB1dCgpIHB1YmxpYyBtaW5EYXRlOiBEYXRlID0gRGF0ZVRpbWVIZWxwZXIubWluRGF0ZVBpY2tlckRhdGU7XHJcbiAgQElucHV0KCkgcHVibGljIG1heERhdGU6IERhdGUgPSBEYXRlVGltZUhlbHBlci5tYXhEYXRlUGlja2VyRGF0ZTtcclxuXHJcbiAgLyoqIFRoZSBpbnRlcm5hbCB0ZXh0Ym94J3MgZm9ybSBjb250cm9sLiAqL1xyXG4gIHB1YmxpYyB0ZXh0Ym94Q29udHJvbCA9IG5ldyBGb3JtQ29udHJvbDxzdHJpbmcgfCBudWxsPihudWxsKTtcclxuXHJcbiAgLyoqXHJcbiAgICogVGhlIGN1cnJlbnQgY2FsZW5kYXIgc2VsZWN0aW9uLlxyXG4gICAqIFVwZGF0ZWQgd2hlbiB0aGUgdXNlciBjbGlja3Mgb24gYSBjYWxlbmRhciBpdGVtIG9yIHdoZW4gdGhlIGRhdGUgZW50ZXJlZCBpbnRvIHRoZSB0ZXh0Ym94IGlzIHBhcnNlZC5cclxuICAgKi9cclxuICBwdWJsaWMgY2FsZW5kYXJTZWxlY3Rpb246IENhbGVuZGFyU2VsZWN0aW9uIHwgbnVsbCA9IG51bGw7XHJcblxyXG4gIC8qKiBDb250cm9scyB3aGV0aGVyIHRoZSBjYWxlbmRhciBvdmVybGF5IGlzIG9wZW4gb3Igbm90LiAqL1xyXG4gIHB1YmxpYyBpc0NhbGVuZGFyT3BlbiA9IGZhbHNlO1xyXG5cclxuICAvKiogUGxhY2Vob2xkZXIgZm9yIHRoZSB0ZXh0Ym94LiBVcGRhdGVkIHRvIHJlZmxlY3QgdGhlIHVzZXIncyBkYXRlIGRpc3BsYXkgcHJlZmVyZW5jZS4gKi9cclxuICBwdWJsaWMgcGxhY2Vob2xkZXI6IHN0cmluZyA9ICdNTS9ERC9ZWVlZJztcclxuXHJcbiAgLyoqIE92ZXJsYXkgc2Nyb2xsIHN0cmF0ZWd5IGZvciB0aGUgY2FsZW5kYXIgb3ZlcmxheS4gQ2xvc2VzIHRoZSBjYWxlbmRhciBvbiBzY3JvbGwuICovXHJcbiAgcHVibGljIG92ZXJsYXlTY3JvbGxTdHJhdGVneSA9IHRoaXMub3ZlcmxheVNlcnZpY2Uuc2Nyb2xsU3RyYXRlZ2llcy5jbG9zZSgpO1xyXG5cclxuICAvKiogXHJcbiAgICogRGF0ZSBwYXJzaW5nIGZvcm1hdHMgZm9yIHVzZXItZW50ZXJlZCBkYXRlcy4gRGVmYXVsdHMgdG8gbW9udGgtZmlyc3QgZm9ybWF0cywgYnV0IGlzIHVwZGF0ZWQgaW4gb25Jbml0XHJcbiAgICogdG8gdXNlIHRoZSB1c2VyJ3MgcHJlZmVycmVkIGRhdGUgZm9ybWF0LlxyXG4gICAqL1xyXG4gIHByaXZhdGUgcGFyc2VGb3JtYXRzOiBzdHJpbmdbXSA9IERhdGVUaW1lSGVscGVyLmdldFBhcnNlRm9ybWF0cygpO1xyXG5cclxuICAvKiogUmVmZXJlbmNlIHRvIHRoZSBvdmVybGF5IGRpcmVjdGl2ZSAoc2VlIHRlbXBsYXRlKS4gVXNlZCB0byBhY2Nlc3MgdGhlIG92ZXJsYXkncyBob3N0IGVsZW1lbnQgdG8gY29udHJvbCBmb2N1cy4gKi9cclxuICBAVmlld0NoaWxkKCdvdmVybGF5Jykgb3ZlcmxheT86IENka0Nvbm5lY3RlZE92ZXJsYXk7XHJcblxyXG4gIGNvbnN0cnVjdG9yKFxyXG4gICAgcHJvdGVjdGVkIHZhbGlkYXRpb25NZXNzYWdlU2VydmljZTogVmFsaWRhdGlvbk1lc3NhZ2VTZXJ2aWNlLFxyXG4gICAgcHJvdGVjdGVkIGZvcm1Hcm91cEhlbHBlcjogRm9ybUdyb3VwSGVscGVyLFxyXG4gICAgcHJpdmF0ZSB1c2VyUHJlZmVyZW5jZVNlcnZpY2U6IFVzZXJQcmVmZXJlbmNlU2VydmljZSxcclxuICAgIHByaXZhdGUgZGF0ZURpc3BsYXlQaXBlOiBEYXRlRGlzcGxheVBpcGUsXHJcbiAgICBwcml2YXRlIGVsOiBFbGVtZW50UmVmLFxyXG4gICAgcHJpdmF0ZSBvdmVybGF5U2VydmljZTogT3ZlcmxheVxyXG4gICkge1xyXG4gICAgc3VwZXIodmFsaWRhdGlvbk1lc3NhZ2VTZXJ2aWNlLCBmb3JtR3JvdXBIZWxwZXIpO1xyXG4gIH1cclxuXHJcbiAgLyoqIEZvY3VzZXMgdGhlIGlucHV0IHdoZW5ldmVyIHRoZSBjYWxlbmRhciBpcyBzaGlmdC10YWJiZWQgb3V0IG9mLiAqL1xyXG4gIHB1YmxpYyBvbkNhbGVuZGFyRm9jdXNPdXRTdGFydChldmVudDogS2V5Ym9hcmRFdmVudCkge1xyXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgIHRoaXMuZm9jdXNJbnB1dCgpO1xyXG4gIH1cclxuXHJcbiAgLyoqIENsb3NlcyB0aGUgY2FsZW5kYXIgYW5kIGZvY3VzZXMgdGhlIGlucHV0IHdoZW5ldmVyIHRoZSBjYWxlbmRhciBpcyB0YWJiZWQgb3V0IG9mLiAqL1xyXG4gIHB1YmxpYyBvbkNhbGVuZGFyRm9jdXNPdXRFbmQoZXZlbnQ6IEtleWJvYXJkRXZlbnQpIHtcclxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICB0aGlzLmlzQ2FsZW5kYXJPcGVuID0gZmFsc2U7XHJcbiAgICB0aGlzLmZvY3VzSW5wdXQoKTtcclxuICB9XHJcblxyXG4gIC8qKiBDbG9zZSB0aGUgY2FsZW5kYXIgaWYgdGhlIHVzZXIgY2xpY2tzIG91dHNpZGUgb2YgdGhlIGNhbGVuZGFyIGFuZCBkYXRlIGlucHV0LiAqL1xyXG4gIHB1YmxpYyBvbk92ZXJsYXlPdXRzaWRlQ2xpY2soZXZlbnQ6IE1vdXNlRXZlbnQpIHtcclxuICAgIC8vIERvIG5vdCBjbG9zZSB0aGUgY2FsZW5kYXIgaWYgdGhlIGNsaWNrIHdhcyB3aXRoaW4gdGhlIGRhdGUgaW5wdXQgb3IgYWN0aW9uIGJ1dHRvblxyXG4gICAgY29uc3QgcmVjdCA9IHRoaXMuZWwubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcclxuICAgIGNvbnN0IGNsaWNrZWRPdXRzaWRlQ29udHJvbCA9IGV2ZW50LmNsaWVudFkgPCByZWN0LnRvcCB8fFxyXG4gICAgICBldmVudC5jbGllbnRZID4gcmVjdC5ib3R0b20gfHxcclxuICAgICAgZXZlbnQuY2xpZW50WCA8IHJlY3QubGVmdCB8fFxyXG4gICAgICBldmVudC5jbGllbnRYID4gcmVjdC5yaWdodDtcclxuICAgIC8vIEl0J3MgcG9zc2libGUgdGhhdCB0aGUgdXNlciBoaXQgZW50ZXIgb24gdGhlIGFjdGlvbiBidXR0b24gaW5zdGVhZCBvZiBjbGlja2luZyB3aXRoIHRoZSBtb3VzZS5cclxuICAgIC8vIEluIHRoaXMgY2FzZSB0aGUgXCJjbGlja1wiIGV2ZW50IHdpbGwgYmUgb3V0c2lkZSBvZiB0aGUgY29tcG9uZW50IGJlY2F1c2UgdGhlIGNsaWVudHggYW5kIHkgYXJlIDAsXHJcbiAgICAvLyBidXQgd2UgZG9uJ3Qgd2FudCB0byBjbG9zZSBpbiB0aGlzIGNhc2UgYmVjYXVzZSBidXR0b24gY2xpY2tzIHRyaWdnZXIgY2FsZW5kYXIgb3Blbi9jbG9zZSBzZXBhcmF0ZWx5LlxyXG4gICAgY29uc3QgaXNBY3Rpb25DbGljayA9ICg8SFRNTEVsZW1lbnQ+ZXZlbnQudGFyZ2V0KS5pZCA9PT0gYCR7dGhpcy5pZH1fYWN0aW9uYDtcclxuXHJcbiAgICBpZiAoIWlzQWN0aW9uQ2xpY2sgJiYgY2xpY2tlZE91dHNpZGVDb250cm9sKSB7XHJcbiAgICAgIHRoaXMuaXNDYWxlbmRhck9wZW4gPSBmYWxzZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIC8qKiBJZiB0aGUgdXNlciB0YWJzIG91dCBvZiB0aGUgZm9ybSBjb250cm9sJ3MgYWN0aW9uIGJ1dHRvbiBhbmQgdGhlIGNhbGVuZGFyIGlzIG9wZW4sIGZvY3VzIHRoZSBmaXJzdCBpdGVtIGluIHRoZSBjYWxlbmRhciBvdmVybGF5ICovXHJcbiAgcHVibGljIG9uQWN0aW9uS2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCkge1xyXG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ1RhYicgJiYgIWV2ZW50LnNoaWZ0S2V5ICYmIHRoaXMuaXNDYWxlbmRhck9wZW4pIHtcclxuICAgICAgLy8gUHJldmVudCB0aGUgZGVmYXVsdCB0YWIgYWN0aW9uIHNvIHRoZSBmb2N1cyBkb2Vzbid0IG1vdmUgdG8gdGhlIG5leHQgZWxlbWVudCBpbiB0aGUgdGFiIG9yZGVyIGFmdGVyIHdlIG1hbnVhbGx5IGZvY3VzIHRoZSBjYWxlbmRhciBidXR0b24uXHJcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgIC8vIEZvY3VzIHRoZSBmaXJzdCBidXR0b24gaW4gdGhlIGNhbGVuZGFyIG92ZXJsYXlcclxuICAgICAgY29uc3QgZmlyc3RCdXR0b246IEhUTUxCdXR0b25FbGVtZW50IHwgbnVsbCB8IHVuZGVmaW5lZCA9IHRoaXMub3ZlcmxheT8ub3ZlcmxheVJlZi5ob3N0RWxlbWVudC5xdWVyeVNlbGVjdG9yKCdidXR0b246bm90KDpkaXNhYmxlZCknKTtcclxuICAgICAgZmlyc3RCdXR0b24/LmZvY3VzKCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25UZXh0Ym94S2V5ZG93bihldmVudDogS2V5Ym9hcmRFdmVudCkge1xyXG4gICAgaWYgKGV2ZW50LmtleSA9PT0gJ1RhYicgJiYgZXZlbnQuc2hpZnRLZXkpIHtcclxuICAgICAgLy8gSWYgdGhlIHVzZXIgaXMgdGFiYmluZyBiYWNrd2FyZHMgZnJvbSB0aGUgdGV4dGJveCwgY2xvc2UgdGhlIGNhbGVuZGFyLlxyXG4gICAgICB0aGlzLmlzQ2FsZW5kYXJPcGVuID0gZmFsc2U7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKiogV2hlbmV2ZXIgdGhlIHVzZXIgc2VsZWN0cyBhIGRhdGUgZnJvbSB0aGUgY2FsZW5kYXIsIHVwZGF0ZSB0aGUgZm9ybU1vZGVsIHdpdGggdGhlIHNlbGVjdGlvbiAqL1xyXG4gIHB1YmxpYyBvblNlbGVjdGlvbkNoYW5nZShzZWxlY3Rpb246IENhbGVuZGFyU2VsZWN0aW9uIHwgbnVsbCkge1xyXG4gICAgdGhpcy5jYWxlbmRhclNlbGVjdGlvbiA9IHNlbGVjdGlvbjtcclxuICAgIGlmIChpc0NhbGVuZGFyU2VsZWN0aW9uU2luZ2xlRGF0ZShzZWxlY3Rpb24pKSB7XHJcbiAgICAgIHRoaXMuZm9ybU1vZGVsLnNldFZhbHVlKHNlbGVjdGlvbik7XHJcbiAgICAgIHRoaXMuaXNDYWxlbmRhck9wZW4gPSBmYWxzZTtcclxuICAgICAgdGhpcy5mb2N1c0lucHV0KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBwdWJsaWMgb25UZXh0Ym94Qmx1cigpIHtcclxuICAgIC8vIFBhcnNlIHRoZSB0ZXh0Ym94IHZhbHVlIGludG8gYSBkYXRlIGFuZCB1cGRhdGUgdGhlIGZvcm0gbW9kZWxcclxuICAgIGNvbnN0IHZhbHVlID0gdGhpcy50ZXh0Ym94Q29udHJvbC52YWx1ZTtcclxuICAgIGlmICh2YWx1ZSkge1xyXG4gICAgICBjb25zdCBwYXJzZWREYXRlID0gbW9tZW50KHZhbHVlLCB0aGlzLnBhcnNlRm9ybWF0cyk7XHJcbiAgICAgIGlmIChwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xyXG4gICAgICAgIHRoaXMuZm9ybU1vZGVsLnNldFZhbHVlKHBhcnNlZERhdGUudG9EYXRlKCkpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuZm9ybU1vZGVsLnNldFZhbHVlKG51bGwpO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICB0aGlzLmZvcm1Nb2RlbC5zZXRWYWx1ZShudWxsKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBVcGRhdGUgdGhlIGZvcm0gbW9kZWwncyB0b3VjaGVkIGFuZCBkaXJ0eSBzdGF0dXMgYmFzZWQgb24gdGhlIHRleHRib3gncyBzdGF0dXMuXHJcbiAgICAvLyBTaW5jZSB0aGUgdXNlciBpbnRlcmFjdHMgd2l0aCBhIGNvbnRyb2wgdGhhdCBpcyBpbnRlcm5hbCB0byB0aGlzIGNvbXBvbmVudCwgdGhlXHJcbiAgICAvLyBmb3JtIG1vZGVsJ3Mgc3RhdHVzIHdvbid0IGJlIHVwZGF0ZWQgYXV0b21hdGljYWxseS5cclxuICAgIGlmICh0aGlzLnRleHRib3hDb250cm9sLnRvdWNoZWQgJiYgIXRoaXMuZm9ybU1vZGVsLnRvdWNoZWQpIHtcclxuICAgICAgdGhpcy5mb3JtTW9kZWwubWFya0FzVG91Y2hlZCgpO1xyXG4gICAgfVxyXG4gICAgaWYgKHRoaXMudGV4dGJveENvbnRyb2wuZGlydHkgJiYgIXRoaXMuZm9ybU1vZGVsLmRpcnR5KSB7XHJcbiAgICAgIHRoaXMuZm9ybU1vZGVsLm1hcmtBc0RpcnR5KCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIC8vIFNldHVwXHJcbiAgICBzdXBlci5uZ09uSW5pdCgpO1xyXG4gICAgdGhpcy5zZXREYXRlRm9ybWF0cygpO1xyXG5cclxuICAgIHRoaXMuZm9ybU1vZGVsLmFkZFZhbGlkYXRvcnModGhpcy5kYXRlVmFsaWRhdG9yKTtcclxuXHJcbiAgICAvLyBTdWJzY3JpcHRpb25zXHJcbiAgICB0aGlzLm9uRm9ybU1vZGVsU3RhdHVzQ2hhbmdlcygpO1xyXG4gICAgdGhpcy5vbkZvcm1Nb2RlbFZhbHVlQ2hhbmdlcygpO1xyXG4gICAgdGhpcy5vblRleHRib3hWYWx1ZUNoYW5nZXMoKTtcclxuXHJcbiAgICAvLyBTeW5jIHRoZSBpbml0aWFsIGRpc2FibGVkIHN0YXR1cyBhbmQgdmFsdWUgb2YgdGhlIHRleHRib3hcclxuICAgIHRoaXMuc3luY1RleHRib3hDb250cm9sRGlzYWJsZWRTdGF0dXModGhpcy5mb3JtTW9kZWwuc3RhdHVzKTtcclxuICAgIHRoaXMudGV4dGJveENvbnRyb2wuc2V0VmFsdWUodGhpcy5kYXRlRGlzcGxheVBpcGUudHJhbnNmb3JtKHRoaXMuZm9ybU1vZGVsLnZhbHVlLCB0cnVlKSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xyXG4gICAgdGhpcy5jYWxlbmRhclNlbGVjdGlvbiA9IHRoaXMuZm9ybU1vZGVsLnZhbHVlO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBvbkZvcm1Nb2RlbFN0YXR1c0NoYW5nZXMoKSB7XHJcbiAgICAvLyBLZWVwIHRoZSB0ZXh0Ym94Q29udHJvbCBkaXNhYmxlZCBzdGF0dXMgaW4gc3luYyB3aXRoIHRoZSBmb3JtTW9kZWxcclxuICAgIHRoaXMuZm9ybU1vZGVsLnN0YXR1c0NoYW5nZXMucGlwZShcclxuICAgICAgZGlzdGluY3RVbnRpbENoYW5nZWQoKSxcclxuICAgICAgdGFrZVVudGlsKHRoaXMuY29tcG9uZW50RGVzdHJveWVkKVxyXG4gICAgKS5zdWJzY3JpYmUoc3RhdHVzID0+IHtcclxuICAgICAgdGhpcy5zeW5jVGV4dGJveENvbnRyb2xEaXNhYmxlZFN0YXR1cyhzdGF0dXMpO1xyXG5cclxuICAgICAgaWYgKHRoaXMuaXNDYWxlbmRhck9wZW4pIHtcclxuICAgICAgICAvLyBBcyB2YWxpZGF0aW9uIG1lc3NhZ2VzIGFwcGVhci9kaXNhcHBlYXIsIHRoZSBkYXRlIGlucHV0IG1heSBoYXZlIHNoaWZ0ZWQgdXAgb3IgZG93biBvbiB0aGUgcGFnZS5cclxuICAgICAgICAvLyBVcGRhdGUgdGhlIG92ZXJsYXkgcG9zaXRpb24gdG8gZW5zdXJlIGl0J3Mgc3RpbGwgYWxpZ25lZCB3aXRoIHRoZSB0ZXh0Ym94IGFuZCBub3QgYmxvY2tpbmcgaXQuXHJcbiAgICAgICAgLy8gU2V0dGltZW91dCBpcyBuZWVkZWQgdG8gZW5zdXJlIHRoZSBvdmVybGF5IGlzIGJlaW5nIHVwZGF0ZWQgYWZ0ZXIgdGhlIG1lc3NhZ2UgaXMgcmVuZGVyZWQuXHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLm92ZXJsYXk/Lm92ZXJsYXlSZWY/LnVwZGF0ZVBvc2l0aW9uKCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBvbkZvcm1Nb2RlbFZhbHVlQ2hhbmdlcygpIHtcclxuICAgIC8vIFVwZGF0ZSB0aGUgY2FsZW5kYXIgc2VsZWN0aW9uIHRleHRib3ggdmFsdWUgd2l0aCBhIGZvcm1hdHRlZCBkYXRlIHdoZW4gdGhlIGZvcm0gbW9kZWwgY2hhbmdlcy5cclxuICAgIC8vIFRoaXMgaXMgdXN1YWxseSB0cmlnZ2VyZWQgYnkgcHJvZ3JhbW1hdGljIGNoYW5nZXMgdG8gdGhlIGZvcm0gbW9kZWwgYnkgYSBwYXJlbnQgY29tcG9uZW50LlxyXG4gICAgdGhpcy5mb3JtTW9kZWwudmFsdWVDaGFuZ2VzLnBpcGUoXHJcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKChhLCBiKSA9PiBtb21lbnQoYSkuaXNTYW1lKGIsICdkYXknKSksXHJcbiAgICAgIHRha2VVbnRpbCh0aGlzLmNvbXBvbmVudERlc3Ryb3llZClcclxuICAgICkuc3Vic2NyaWJlKHZhbHVlID0+IHtcclxuICAgICAgY29uc3QgZGlzcGxheVZhbHVlID0gdGhpcy5kYXRlRGlzcGxheVBpcGUudHJhbnNmb3JtKHZhbHVlLCB0cnVlKTtcclxuICAgICAgLy8gRG9uJ3QgZW1pdCBhbiBldmVudCB3aGVuIHNldHRpbmcgdGhlIHRleHRib3ggdmFsdWUgdG8gYXZvaWQgY2lyY3VsYXIgdXBkYXRlcyBiZXR3ZWVuIHRoZSB0ZXh0Ym94IGFuZCBmb3JtIG1vZGVsLlxyXG4gICAgICB0aGlzLnRleHRib3hDb250cm9sLnNldFZhbHVlKGRpc3BsYXlWYWx1ZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xyXG4gICAgICB0aGlzLmNhbGVuZGFyU2VsZWN0aW9uID0gdmFsdWU7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgb25UZXh0Ym94VmFsdWVDaGFuZ2VzKCkge1xyXG4gICAgLy8gVXBkYXRlIHRoZSBjYWxlbmRhciBzZWxlY3Rpb24gd2hlbiB0aGUgdGV4dGJveCB2YWx1ZSBjaGFuZ2VzIHRvIHVwZGF0ZSB0aGUgY2FsZW5kYXIuXHJcbiAgICAvLyBXZSBkb24ndCBwYXRjaCB0aGUgZm9ybU1vZGVsIGhlcmUgYmVjYXVzZSB3ZSBkb24ndCB3YW50IHRvIHRyaWdnZXIgdGhlXHJcbiAgICAvLyBkYXRlIGZvcm1hdHRpbmcgbG9naWMgYW5kIG92ZXJ3cml0ZSB0aGUgdXNlcidzIGlucHV0LlxyXG4gICAgLy8gV2UnbGwgZG8gdGhhdCB3aGVuIHRoZSB1c2VyIGJsdXJzIG91dCBvZiB0aGUgdGV4dGJveC4gU2VlIG9uVGV4dGJveEJsdXIoKVxyXG4gICAgdGhpcy50ZXh0Ym94Q29udHJvbC52YWx1ZUNoYW5nZXMucGlwZShcclxuICAgICAgZGVib3VuY2VUaW1lKDMwMCksXHJcbiAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXHJcbiAgICAgIHRha2VVbnRpbCh0aGlzLmNvbXBvbmVudERlc3Ryb3llZClcclxuICAgICkuc3Vic2NyaWJlKHZhbHVlID0+IHtcclxuICAgICAgaWYgKHZhbHVlKSB7XHJcbiAgICAgICAgY29uc3QgcGFyc2VkRGF0ZSA9IG1vbWVudCh2YWx1ZSwgdGhpcy5wYXJzZUZvcm1hdHMpO1xyXG4gICAgICAgIGlmIChwYXJzZWREYXRlLmlzVmFsaWQoKSkge1xyXG4gICAgICAgICAgLy8gSWYgdGhlIHBhcnNlZCBkYXRlIGlzIGJlZm9yZSB0aGUgbWluRGF0ZSwgc2V0IHRoZSB5ZWFyIHRvIHRoZSBjdXJyZW50IHllYXIuXHJcbiAgICAgICAgICAvLyBUaGlzIHByZXZlbnRzIHRoZSBjYWxlbmRhciBmcm9tIHNob3dpbmcgdW5oZWxwZnVsIGRhdGVzIGluIHRoZSBkaXN0YW50IHBhc3QgYXMgdGhlIHVzZXIgdHlwZXNcclxuICAgICAgICAgIGlmIChwYXJzZWREYXRlLnllYXIoKSA8IHRoaXMubWluRGF0ZS5nZXRGdWxsWWVhcigpKSB7XHJcbiAgICAgICAgICAgIHBhcnNlZERhdGUuc2V0KCd5ZWFyJywgbW9tZW50KCkueWVhcigpKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIHRoaXMuY2FsZW5kYXJTZWxlY3Rpb24gPSBwYXJzZWREYXRlLnRvRGF0ZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLmNhbGVuZGFyU2VsZWN0aW9uID0gbnVsbDtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHN5bmNUZXh0Ym94Q29udHJvbERpc2FibGVkU3RhdHVzKHN0YXR1czogRm9ybUNvbnRyb2xTdGF0dXMpIHtcclxuICAgIC8vIFRoZSB0ZXh0Ym94IHNob3VsZCBvbmx5IGJlIGRpc2FibGVkIGlmIHRoZSBmb3JtIG1vZGVsIGlzIGRpc2FibGVkLlxyXG4gICAgLy8gQWxsIG90aGVyIHN0YXR1c2VzIGFyZSBjb25zaWRlcmVkIGVuYWJsZWQuXHJcbiAgICBpZiAoc3RhdHVzID09PSAnRElTQUJMRUQnICYmIHRoaXMudGV4dGJveENvbnRyb2wuZW5hYmxlZCkge1xyXG4gICAgICB0aGlzLnRleHRib3hDb250cm9sLmRpc2FibGUoKTtcclxuICAgIH0gZWxzZSBpZiAoc3RhdHVzICE9PSAnRElTQUJMRUQnICYmIHRoaXMudGV4dGJveENvbnRyb2wuZGlzYWJsZWQpIHtcclxuICAgICAgdGhpcy50ZXh0Ym94Q29udHJvbC5lbmFibGUoKTtcclxuICAgIH1cclxuICB9O1xyXG5cclxuICAvKiogXHJcbiAgICogVXBkYXRlcyB0aGUgZGF0ZSBwYXJzaW5nIGZvcm1hdHMgYW5kIHBsYWNlaG9sZGVyIGJhc2VkIG9uIHRoZSB1c2VyJ3MgZGlzcGxheSBwcmVmZXJlbmNlLlxyXG4gICAqIE5PVEU6IFRoaXMgaXMgYXN5bmMgYmVjYXVzZSB3ZSdyZSByZXRyaWV2aW5nIHRoZSB1c2VyJ3MgcHJlZmVyZW5jZXMuIFdlJ3JlIG5vdCBhd2FpdGluZyB0aGUgcmVzdWx0XHJcbiAgICogYmVjYXVzZSB0aGUgb25seSBsb2dpYyB0aGF0IGRlcGVuZHMgb24gdGhpcyBpcyB0aGUgdGV4dCBib3ggZGF0ZSBwYXJzaW5nIGxvZ2ljIGFuZCBwbGFjZWhvbGRlci5cclxuICAgKiBPdXIgZm9ybXMgc2hvdWxkIGFsd2F5cyBiZSBiZWhpbmQgYSBwZW5kaW5nIG92ZXJsYXksIHNvIHRoZSB1c2VyIHdvbid0IGJlIGFibGUgdG8gaW50ZXJhY3Qgd2l0aCB0aGVcclxuICAgKiBmb3JtIHVudGlsIHRoZSB1c2VyIGlzIGxvYWRlZCBhbnl3YXkuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBhc3luYyBzZXREYXRlRm9ybWF0cygpIHtcclxuICAgIGNvbnN0IHsgcHJlZmVyZW5jZSB9ID0gYXdhaXQgbGFzdFZhbHVlRnJvbSh0aGlzLnVzZXJQcmVmZXJlbmNlU2VydmljZS5nZXRQcmVmZXJlbmNlcygpKTtcclxuICAgIGNvbnN0IGRhdGVGb3JtYXQgPSBwcmVmZXJlbmNlPy5kYXRlRm9ybWF0O1xyXG4gICAgdGhpcy5wbGFjZWhvbGRlciA9IGRhdGVGb3JtYXQgPz8gdGhpcy5wbGFjZWhvbGRlcjtcclxuICAgIHRoaXMucGFyc2VGb3JtYXRzID0gRGF0ZVRpbWVIZWxwZXIuZ2V0TW9tZW50UGFyc2VGb3JtYXRzKGRhdGVGb3JtYXQpO1xyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogVmFsaWRhdG9yIHRoYXQgY2hlY2tzIGlmIHRoZSBkYXRlIGlzIHdpdGhpbiB0aGUgbWluIGFuZCBtYXggZGF0ZSByYW5nZS5cclxuICAgKiBJZiB0aGUgZGF0ZSBpcyBvdXRzaWRlIG9mIHRoZSByYW5nZSwgdGhlIHZhbGlkYXRvciByZXR1cm5zIGFuIGVycm9yIHRoYXRcclxuICAgKiB0cmlnZ2VycyB0aGUgdmFsaWRhdGlvbiBtZXNzYWdlIHNlcnZpY2UgdG8gc2hvdyB0aGUgZXJyb3IgaW4gdGhlIGxhYmVsLlxyXG4gICAqL1xyXG4gIHByaXZhdGUgZGF0ZVZhbGlkYXRvcjogVmFsaWRhdG9yRm4gPSAoY29udHJvbDogQWJzdHJhY3RDb250cm9sKSA9PiB7XHJcbiAgICBpZiAoY29udHJvbC52YWx1ZSkge1xyXG4gICAgICBpZiAoY29udHJvbC52YWx1ZSA8IHRoaXMubWluRGF0ZSkge1xyXG4gICAgICAgIHJldHVybiB7IG1pbkRhdGU6IHsgbWluVmFsdWU6IHRoaXMubWluRGF0ZSB9IH07XHJcbiAgICAgIH0gZWxzZSBpZiAoY29udHJvbC52YWx1ZSA+IHRoaXMubWF4RGF0ZSkge1xyXG4gICAgICAgIHJldHVybiB7IG1heERhdGU6IHsgbWF4VmFsdWU6IHRoaXMubWF4RGF0ZSB9IH07XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbnVsbDtcclxuICB9O1xyXG5cclxuICAvKiogRm9jdXNlcyB0aGUgZGF0ZSBpbnB1dC4gKi9cclxuICBwcml2YXRlIGZvY3VzSW5wdXQoKSB7XHJcbiAgICB0aGlzLmVsLm5hdGl2ZUVsZW1lbnQucXVlcnlTZWxlY3RvcignaW5wdXQnKT8uZm9jdXMoKTtcclxuICB9XHJcbn1cclxuIiwiPGxhYmVsICpuZ0lmPVwibGFiZWxcIj5cclxuICA8c3Bhbj57e2xhYmVsIHwgdHJhbnNsYXRlfX08L3NwYW4+XHJcbiAgPHNwYW4gKm5nSWY9XCJ2YWxpZGF0aW9uRXJyb3JzLmxlbmd0aCA+IDAgJiYgZm9ybU1vZGVsLnRvdWNoZWQgJiYgZm9ybU1vZGVsLmludmFsaWRcIj4mbmJzcDt7e3ZhbGlkYXRpb25FcnJvcnN9fTwvc3Bhbj5cclxuICA8ZWMtaGVscC1wb3BvdmVyIGlkPVwie3tpZH19X2hlbHBQb3BvdmVyXCJcclxuICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiaGVscFBvcG92ZXJcIlxyXG4gICAgICAgICAgICAgICAgICAgY2xhc3M9XCJkLWlubGluZS1ibG9jayBteS1uMyBteC1uMVwiXHJcbiAgICAgICAgICAgICAgICAgICB0ZXh0PVwie3toZWxwUG9wb3ZlciB8IHRyYW5zbGF0ZX19XCJcclxuICAgICAgICAgICAgICAgICAgIGNvbnRlbnRQb3NpdGlvbj1cInt7aGVscFBvcG92ZXJQb3NpdGlvbn19XCI+XHJcbiAgPC9lYy1oZWxwLXBvcG92ZXI+XHJcbjwvbGFiZWw+XHJcblxyXG48ZWMtZm9ybS1jb250cm9sIGlkPVwie3tpZH19XCJcclxuICAgICAgICAgICAgICAgICBbcmVxdWlyZWRdPVwicmVxdWlyZWRcIlxyXG4gICAgICAgICAgICAgICAgIFthdXRvZm9jdXNdPVwiYXV0b2ZvY3VzXCJcclxuICAgICAgICAgICAgICAgICBbcGVuZGluZ109XCJwZW5kaW5nXCJcclxuICAgICAgICAgICAgICAgICBbcmVhZG9ubHldPVwicmVhZG9ubHlcIlxyXG4gICAgICAgICAgICAgICAgIFtmb3JtTW9kZWxdPVwiZm9ybU1vZGVsXCJcclxuICAgICAgICAgICAgICAgICAoYWN0aW9uQ2xpY2tlZCk9XCJpc0NhbGVuZGFyT3BlbiA9ICFpc0NhbGVuZGFyT3BlblwiXHJcbiAgICAgICAgICAgICAgICAgKGFjdGlvbktleWRvd24pPVwib25BY3Rpb25LZXlkb3duKCRldmVudClcIlxyXG4gICAgICAgICAgICAgICAgIFtzaG93Q2xlYXJdPVwiZmFsc2VcIlxyXG4gICAgICAgICAgICAgICAgIGFjdGlvbkljb249XCJpY29uLWRhdGVcIlxyXG4gICAgICAgICAgICAgICAgIGNka092ZXJsYXlPcmlnaW5cclxuICAgICAgICAgICAgICAgICAjb3ZlcmxheU9yaWdpbj1cImNka092ZXJsYXlPcmlnaW5cIj5cclxuICA8aW5wdXQgaWQ9XCJ7e2lkfX1faW5wdXRcIlxyXG4gICAgICAgICB0eXBlPVwidGV4dFwiXHJcbiAgICAgICAgIHBsYWNlaG9sZGVyPVwie3twbGFjZWhvbGRlcn19XCJcclxuICAgICAgICAgW2Zvcm1Db250cm9sXT1cInRleHRib3hDb250cm9sXCJcclxuICAgICAgICAgKGJsdXIpPVwib25UZXh0Ym94Qmx1cigpXCJcclxuICAgICAgICAgKGtleWRvd24pPVwib25UZXh0Ym94S2V5ZG93bigkZXZlbnQpXCI+XHJcbjwvZWMtZm9ybS1jb250cm9sPlxyXG5cclxuPG5nLXRlbXBsYXRlIGNka0Nvbm5lY3RlZE92ZXJsYXlcclxuICAgICAgICAgICAgICNvdmVybGF5PVwiY2RrQ29ubmVjdGVkT3ZlcmxheVwiXHJcbiAgICAgICAgICAgICBbY2RrQ29ubmVjdGVkT3ZlcmxheU9yaWdpbl09XCJvdmVybGF5T3JpZ2luXCJcclxuICAgICAgICAgICAgIFtjZGtDb25uZWN0ZWRPdmVybGF5T3Blbl09XCJpc0NhbGVuZGFyT3BlblwiXHJcbiAgICAgICAgICAgICBbY2RrQ29ubmVjdGVkT3ZlcmxheVNjcm9sbFN0cmF0ZWd5XT1cIm92ZXJsYXlTY3JvbGxTdHJhdGVneVwiXHJcbiAgICAgICAgICAgICBjZGtDb25uZWN0ZWRPdmVybGF5UGFuZWxDbGFzcz1cIm15LTFcIlxyXG4gICAgICAgICAgICAgKG92ZXJsYXlPdXRzaWRlQ2xpY2spPVwib25PdmVybGF5T3V0c2lkZUNsaWNrKCRldmVudClcIlxyXG4gICAgICAgICAgICAgKGRldGFjaCk9XCJpc0NhbGVuZGFyT3BlbiA9IGZhbHNlXCI+XHJcbiAgPGVjLWNhbGVuZGFyIFtpZF09XCJpZCArICdfY2FsZW5kYXInXCJcclxuICAgICAgICAgICAgICAgW21pbkRhdGVdPVwibWluRGF0ZVwiXHJcbiAgICAgICAgICAgICAgIFttYXhEYXRlXT1cIm1heERhdGVcIlxyXG4gICAgICAgICAgICAgICBbc2VsZWN0aW9uXT1cImNhbGVuZGFyU2VsZWN0aW9uXCJcclxuICAgICAgICAgICAgICAgKHNlbGVjdGlvbkNoYW5nZSk9XCJvblNlbGVjdGlvbkNoYW5nZSgkZXZlbnQpXCJcclxuICAgICAgICAgICAgICAgY2xhc3M9XCJjYXJkIHB4LTEgcHQtMSBwYi0yXCJcclxuICAgICAgICAgICAgICAgKGZvY3VzT3V0U3RhcnQpPVwib25DYWxlbmRhckZvY3VzT3V0U3RhcnQoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgICAgIChmb2N1c091dEVuZCk9XCJvbkNhbGVuZGFyRm9jdXNPdXRFbmQoJGV2ZW50KVwiPlxyXG4gIDwvZWMtY2FsZW5kYXI+XHJcbjwvbmctdGVtcGxhdGU+XHJcbiJdfQ==
|