tango-app-ui-manage-tickets 3.7.0-beta.61 → 3.7.0-beta.63

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.
Files changed (177) hide show
  1. package/esm2022/lib/components/add-csm-modal/add-csm-modal.component.mjs +98 -0
  2. package/esm2022/lib/components/audit-log/audit-log.component.mjs +11 -0
  3. package/esm2022/lib/components/audit-mapping-list/audit-mapping-list.component.mjs +496 -0
  4. package/esm2022/lib/components/audit-metrics/audit-metrics.component.mjs +298 -0
  5. package/esm2022/lib/components/audit-report-popup/audit-report-popup.component.mjs +389 -0
  6. package/esm2022/lib/components/audit-retag/audit-retag.component.mjs +480 -0
  7. package/esm2022/lib/components/comment-model/comment-model.component.mjs +58 -0
  8. package/esm2022/lib/components/count/count.component.mjs +89 -0
  9. package/esm2022/lib/components/custom-select/custom-select.component.mjs +187 -0
  10. package/esm2022/lib/components/filter-options/filter-options.component.mjs +41 -0
  11. package/esm2022/lib/components/footfall-dic/footfall-dic.component.mjs +1061 -0
  12. package/esm2022/lib/components/footfall-dicview/footfall-dicview.component.mjs +1014 -0
  13. package/esm2022/lib/components/footfall-popup/footfall-popup.component.mjs +15 -0
  14. package/esm2022/lib/components/group-select/group-select.component.mjs +155 -0
  15. package/esm2022/lib/components/re-trigger/re-trigger.component.mjs +96 -0
  16. package/esm2022/lib/components/reactive-select/reactive-select.component.mjs +108 -0
  17. package/esm2022/lib/components/remove-audit/remove-audit.component.mjs +81 -0
  18. package/esm2022/lib/components/start-audit/start-audit.component.mjs +769 -0
  19. package/esm2022/lib/components/tango-manage-tickets/tango-manage-tickets.component.mjs +131 -0
  20. package/esm2022/lib/components/ticket-filter-panel/ticket-filter-panel.component.mjs +435 -0
  21. package/esm2022/lib/components/ticket-footfall-new/ticket-footfall-new.component.mjs +2749 -0
  22. package/esm2022/lib/components/ticketclosepopup/ticketclosepopup.component.mjs +43 -0
  23. package/esm2022/lib/components/tickets/tickets.component.mjs +847 -0
  24. package/esm2022/lib/components/viewcategory/viewcategory.component.mjs +89 -0
  25. package/esm2022/lib/services/audit.service.mjs +88 -0
  26. package/esm2022/lib/services/excel.service.mjs +45 -0
  27. package/esm2022/lib/services/ticket.service.mjs +319 -0
  28. package/esm2022/lib/services/timer.service.mjs +84 -0
  29. package/esm2022/lib/tango-manage-tickets-routing.module.mjs +44 -0
  30. package/esm2022/lib/tango-manage-tickets.module.mjs +109 -0
  31. package/esm2022/public-api.mjs +6 -0
  32. package/esm2022/tango-app-ui-manage-tickets.mjs +5 -0
  33. package/fesm2022/tango-app-ui-manage-tickets.mjs +10192 -0
  34. package/fesm2022/tango-app-ui-manage-tickets.mjs.map +1 -0
  35. package/index.d.ts +5 -0
  36. package/lib/components/add-csm-modal/add-csm-modal.component.d.ts +30 -0
  37. package/lib/components/audit-log/audit-log.component.d.ts +5 -0
  38. package/lib/components/audit-mapping-list/audit-mapping-list.component.d.ts +73 -0
  39. package/lib/components/audit-metrics/audit-metrics.component.d.ts +59 -0
  40. package/lib/components/audit-report-popup/audit-report-popup.component.d.ts +52 -0
  41. package/lib/components/audit-retag/audit-retag.component.d.ts +59 -0
  42. package/lib/components/comment-model/comment-model.component.d.ts +17 -0
  43. package/lib/components/count/count.component.d.ts +23 -0
  44. package/lib/components/custom-select/custom-select.component.d.ts +35 -0
  45. package/lib/components/filter-options/filter-options.component.d.ts +15 -0
  46. package/lib/components/footfall-dic/footfall-dic.component.d.ts +143 -0
  47. package/lib/components/footfall-dicview/footfall-dicview.component.d.ts +132 -0
  48. package/lib/components/footfall-popup/footfall-popup.component.d.ts +8 -0
  49. package/lib/components/group-select/group-select.component.d.ts +33 -0
  50. package/lib/components/re-trigger/re-trigger.component.d.ts +32 -0
  51. package/lib/components/reactive-select/reactive-select.component.d.ts +32 -0
  52. package/lib/components/remove-audit/remove-audit.component.d.ts +16 -0
  53. package/lib/components/start-audit/start-audit.component.d.ts +86 -0
  54. package/lib/components/tango-manage-tickets/tango-manage-tickets.component.d.ts +28 -0
  55. package/lib/components/ticket-filter-panel/ticket-filter-panel.component.d.ts +79 -0
  56. package/lib/components/ticket-footfall-new/ticket-footfall-new.component.d.ts +287 -0
  57. package/lib/components/ticketclosepopup/ticketclosepopup.component.d.ts +15 -0
  58. package/lib/components/tickets/tickets.component.d.ts +88 -0
  59. package/lib/components/viewcategory/viewcategory.component.d.ts +16 -0
  60. package/lib/services/audit.service.d.ts +36 -0
  61. package/lib/services/excel.service.d.ts +10 -0
  62. package/lib/services/ticket.service.d.ts +87 -0
  63. package/lib/services/timer.service.d.ts +22 -0
  64. package/lib/tango-manage-tickets-routing.module.d.ts +7 -0
  65. package/lib/tango-manage-tickets.module.d.ts +38 -0
  66. package/package.json +25 -12
  67. package/{src/public-api.ts → public-api.d.ts} +2 -8
  68. package/.eslintrc.json +0 -37
  69. package/ng-package.json +0 -7
  70. package/src/lib/components/add-csm-modal/add-csm-modal.component.html +0 -32
  71. package/src/lib/components/add-csm-modal/add-csm-modal.component.scss +0 -14
  72. package/src/lib/components/add-csm-modal/add-csm-modal.component.spec.ts +0 -23
  73. package/src/lib/components/add-csm-modal/add-csm-modal.component.ts +0 -94
  74. package/src/lib/components/audit-log/audit-log.component.html +0 -1
  75. package/src/lib/components/audit-log/audit-log.component.scss +0 -0
  76. package/src/lib/components/audit-log/audit-log.component.spec.ts +0 -23
  77. package/src/lib/components/audit-log/audit-log.component.ts +0 -10
  78. package/src/lib/components/audit-mapping-list/audit-mapping-list.component.html +0 -234
  79. package/src/lib/components/audit-mapping-list/audit-mapping-list.component.scss +0 -186
  80. package/src/lib/components/audit-mapping-list/audit-mapping-list.component.spec.ts +0 -23
  81. package/src/lib/components/audit-mapping-list/audit-mapping-list.component.ts +0 -520
  82. package/src/lib/components/audit-metrics/audit-metrics.component.html +0 -345
  83. package/src/lib/components/audit-metrics/audit-metrics.component.scss +0 -34
  84. package/src/lib/components/audit-metrics/audit-metrics.component.spec.ts +0 -23
  85. package/src/lib/components/audit-metrics/audit-metrics.component.ts +0 -292
  86. package/src/lib/components/audit-report-popup/audit-report-popup.component.html +0 -111
  87. package/src/lib/components/audit-report-popup/audit-report-popup.component.scss +0 -101
  88. package/src/lib/components/audit-report-popup/audit-report-popup.component.spec.ts +0 -23
  89. package/src/lib/components/audit-report-popup/audit-report-popup.component.ts +0 -397
  90. package/src/lib/components/audit-retag/audit-retag.component.html +0 -129
  91. package/src/lib/components/audit-retag/audit-retag.component.scss +0 -146
  92. package/src/lib/components/audit-retag/audit-retag.component.spec.ts +0 -23
  93. package/src/lib/components/audit-retag/audit-retag.component.ts +0 -489
  94. package/src/lib/components/comment-model/comment-model.component.html +0 -24
  95. package/src/lib/components/comment-model/comment-model.component.scss +0 -20
  96. package/src/lib/components/comment-model/comment-model.component.spec.ts +0 -23
  97. package/src/lib/components/comment-model/comment-model.component.ts +0 -53
  98. package/src/lib/components/count/count.component.html +0 -54
  99. package/src/lib/components/count/count.component.scss +0 -14
  100. package/src/lib/components/count/count.component.spec.ts +0 -23
  101. package/src/lib/components/count/count.component.ts +0 -82
  102. package/src/lib/components/custom-select/custom-select.component.html +0 -134
  103. package/src/lib/components/custom-select/custom-select.component.scss +0 -204
  104. package/src/lib/components/custom-select/custom-select.component.spec.ts +0 -23
  105. package/src/lib/components/custom-select/custom-select.component.ts +0 -189
  106. package/src/lib/components/filter-options/filter-options.component.html +0 -51
  107. package/src/lib/components/filter-options/filter-options.component.scss +0 -102
  108. package/src/lib/components/filter-options/filter-options.component.spec.ts +0 -23
  109. package/src/lib/components/filter-options/filter-options.component.ts +0 -38
  110. package/src/lib/components/footfall-dic/footfall-dic.component.html +0 -1275
  111. package/src/lib/components/footfall-dic/footfall-dic.component.scss +0 -273
  112. package/src/lib/components/footfall-dic/footfall-dic.component.spec.ts +0 -23
  113. package/src/lib/components/footfall-dic/footfall-dic.component.ts +0 -1206
  114. package/src/lib/components/footfall-dicview/footfall-dicview.component.html +0 -1136
  115. package/src/lib/components/footfall-dicview/footfall-dicview.component.scss +0 -416
  116. package/src/lib/components/footfall-dicview/footfall-dicview.component.spec.ts +0 -23
  117. package/src/lib/components/footfall-dicview/footfall-dicview.component.ts +0 -1168
  118. package/src/lib/components/footfall-popup/footfall-popup.component.html +0 -61
  119. package/src/lib/components/footfall-popup/footfall-popup.component.scss +0 -20
  120. package/src/lib/components/footfall-popup/footfall-popup.component.spec.ts +0 -23
  121. package/src/lib/components/footfall-popup/footfall-popup.component.ts +0 -12
  122. package/src/lib/components/group-select/group-select.component.html +0 -44
  123. package/src/lib/components/group-select/group-select.component.scss +0 -144
  124. package/src/lib/components/group-select/group-select.component.spec.ts +0 -23
  125. package/src/lib/components/group-select/group-select.component.ts +0 -145
  126. package/src/lib/components/re-trigger/re-trigger.component.html +0 -53
  127. package/src/lib/components/re-trigger/re-trigger.component.scss +0 -16
  128. package/src/lib/components/re-trigger/re-trigger.component.spec.ts +0 -23
  129. package/src/lib/components/re-trigger/re-trigger.component.ts +0 -96
  130. package/src/lib/components/reactive-select/reactive-select.component.html +0 -18
  131. package/src/lib/components/reactive-select/reactive-select.component.scss +0 -52
  132. package/src/lib/components/reactive-select/reactive-select.component.spec.ts +0 -23
  133. package/src/lib/components/reactive-select/reactive-select.component.ts +0 -104
  134. package/src/lib/components/remove-audit/remove-audit.component.html +0 -38
  135. package/src/lib/components/remove-audit/remove-audit.component.scss +0 -27
  136. package/src/lib/components/remove-audit/remove-audit.component.spec.ts +0 -23
  137. package/src/lib/components/remove-audit/remove-audit.component.ts +0 -81
  138. package/src/lib/components/start-audit/start-audit.component.html +0 -174
  139. package/src/lib/components/start-audit/start-audit.component.scss +0 -185
  140. package/src/lib/components/start-audit/start-audit.component.spec.ts +0 -23
  141. package/src/lib/components/start-audit/start-audit.component.ts +0 -761
  142. package/src/lib/components/tango-manage-tickets/tango-manage-tickets.component.html +0 -43
  143. package/src/lib/components/tango-manage-tickets/tango-manage-tickets.component.scss +0 -35
  144. package/src/lib/components/tango-manage-tickets/tango-manage-tickets.component.spec.ts +0 -23
  145. package/src/lib/components/tango-manage-tickets/tango-manage-tickets.component.ts +0 -118
  146. package/src/lib/components/ticket-filter-panel/ticket-filter-panel.component.html +0 -386
  147. package/src/lib/components/ticket-filter-panel/ticket-filter-panel.component.scss +0 -87
  148. package/src/lib/components/ticket-filter-panel/ticket-filter-panel.component.spec.ts +0 -23
  149. package/src/lib/components/ticket-filter-panel/ticket-filter-panel.component.ts +0 -494
  150. package/src/lib/components/ticket-footfall-new/ticket-footfall-new.component.html +0 -4743
  151. package/src/lib/components/ticket-footfall-new/ticket-footfall-new.component.scss +0 -1208
  152. package/src/lib/components/ticket-footfall-new/ticket-footfall-new.component.spec.ts +0 -23
  153. package/src/lib/components/ticket-footfall-new/ticket-footfall-new.component.ts +0 -3344
  154. package/src/lib/components/ticketclosepopup/ticketclosepopup.component.html +0 -100
  155. package/src/lib/components/ticketclosepopup/ticketclosepopup.component.scss +0 -34
  156. package/src/lib/components/ticketclosepopup/ticketclosepopup.component.spec.ts +0 -23
  157. package/src/lib/components/ticketclosepopup/ticketclosepopup.component.ts +0 -48
  158. package/src/lib/components/tickets/tickets.component.html +0 -451
  159. package/src/lib/components/tickets/tickets.component.scss +0 -131
  160. package/src/lib/components/tickets/tickets.component.spec.ts +0 -23
  161. package/src/lib/components/tickets/tickets.component.ts +0 -809
  162. package/src/lib/components/viewcategory/viewcategory.component.html +0 -38
  163. package/src/lib/components/viewcategory/viewcategory.component.scss +0 -29
  164. package/src/lib/components/viewcategory/viewcategory.component.spec.ts +0 -23
  165. package/src/lib/components/viewcategory/viewcategory.component.ts +0 -79
  166. package/src/lib/services/audit.service.spec.ts +0 -16
  167. package/src/lib/services/audit.service.ts +0 -98
  168. package/src/lib/services/excel.service.ts +0 -48
  169. package/src/lib/services/ticket.service.spec.ts +0 -16
  170. package/src/lib/services/ticket.service.ts +0 -501
  171. package/src/lib/services/timer.service.spec.ts +0 -16
  172. package/src/lib/services/timer.service.ts +0 -92
  173. package/src/lib/tango-manage-tickets-routing.module.ts +0 -37
  174. package/src/lib/tango-manage-tickets.module.ts +0 -68
  175. package/tsconfig.lib.json +0 -14
  176. package/tsconfig.lib.prod.json +0 -10
  177. package/tsconfig.spec.json +0 -14
@@ -0,0 +1,435 @@
1
+ import { Component, EventEmitter, HostListener, Input, Output } from '@angular/core';
2
+ import { Validators } from '@angular/forms';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/forms";
5
+ import * as i2 from "../../services/ticket.service";
6
+ import * as i3 from "@angular/common";
7
+ export class TicketFilterPanelComponent {
8
+ fb;
9
+ eRef;
10
+ service;
11
+ apply = new EventEmitter();
12
+ panelClosed = new EventEmitter(); // ✅ not `close`
13
+ permissionType = null;
14
+ userType = null; // e.g. 'tango' or others
15
+ client;
16
+ onDocumentClick(event) {
17
+ // 1️⃣ Always close dropdowns first
18
+ this.dropdownState.status = false;
19
+ this.dropdownState.reviewer = false;
20
+ this.dropdownState.approver = false;
21
+ // 2️⃣ If filter is not open → nothing to close
22
+ if (!this.isOpen)
23
+ return;
24
+ // 3️⃣ Check if clicked inside filter card
25
+ const clickedInside = this.eRef.nativeElement.contains(event.target);
26
+ // 4️⃣ If clicked OUTSIDE → close entire filter panel
27
+ if (!clickedInside) {
28
+ this.isOpen = false;
29
+ this.panelClosed.emit();
30
+ this.filterForm.reset({
31
+ status: [],
32
+ reviewerCondition: null,
33
+ reviewerFrom: null,
34
+ reviewerTo: null,
35
+ approverCondition: null,
36
+ approverFrom: null,
37
+ approverTo: null,
38
+ tangoCondition: null,
39
+ tangoFrom: null,
40
+ tangoTo: null,
41
+ reviewedBy: [],
42
+ approvedBy: []
43
+ });
44
+ }
45
+ }
46
+ isOpen = false; // controls visibility
47
+ // called from parent via #filterPanel.open()
48
+ open() {
49
+ this.isOpen = true;
50
+ }
51
+ // called from close button inside the panel
52
+ close() {
53
+ this.isOpen = false;
54
+ this.panelClosed.emit();
55
+ }
56
+ showPanel = false; // you can also control this from parent
57
+ statusOptions = [
58
+ 'Open',
59
+ 'In-Progress',
60
+ 'Closed',
61
+ 'Under Tango Review',
62
+ 'Tango Review Done',
63
+ 'Expired',
64
+ 'Tango Expired',
65
+ ];
66
+ conditionOptions = [
67
+ { value: 'gt', label: '> Greater than' },
68
+ { value: 'lt', label: '< Lesser than' },
69
+ { value: 'gte', label: '>= Greater than or equal to' },
70
+ { value: 'lte', label: '<= Lesser than or equal to' },
71
+ { value: 'between', label: 'Between' },
72
+ ];
73
+ filterForm;
74
+ constructor(fb, eRef, service) {
75
+ this.fb = fb;
76
+ this.eRef = eRef;
77
+ this.service = service;
78
+ this.filterForm = this.fb.group({
79
+ status: [[]],
80
+ reviewerCondition: [null],
81
+ reviewerFrom: [null, [Validators.min(0), Validators.max(100)]],
82
+ reviewerTo: [null, [Validators.min(0), Validators.max(100)]],
83
+ approverCondition: [null],
84
+ approverFrom: [null, [Validators.min(0), Validators.max(100)]],
85
+ approverTo: [null, [Validators.min(0), Validators.max(100)]],
86
+ tangoCondition: [null],
87
+ tangoFrom: [null, [Validators.min(0), Validators.max(100)]],
88
+ tangoTo: [null, [Validators.min(0), Validators.max(100)]],
89
+ reviewedBy: [[]],
90
+ approvedBy: [[]],
91
+ });
92
+ this.onReset();
93
+ }
94
+ limitValue(event, controlName) {
95
+ let value = Number(event.target.value);
96
+ if (value < 0)
97
+ value = 0;
98
+ if (value > 100)
99
+ value = 100;
100
+ event.target.value = value;
101
+ this.filterForm.get(controlName)?.setValue(value, { emitEvent: false });
102
+ }
103
+ get isTango() {
104
+ return this.userType === 'tango';
105
+ }
106
+ // SHOW / HIDE RULES
107
+ // Reviewer accuracy and "Reviewed by" visible for tango + reviewer
108
+ get showReviewerAccuracy() {
109
+ return this.isTango || this.permissionType === 'review';
110
+ }
111
+ get showReviewedBy() {
112
+ return this.permissionType === 'review';
113
+ }
114
+ // Approver accuracy and "Approved by" visible for tango + approver
115
+ get showApproverAccuracy() {
116
+ return this.isTango || this.permissionType === 'approve';
117
+ }
118
+ get showApprovedBy() {
119
+ return this.permissionType === 'approve';
120
+ }
121
+ // Tango accuracy only for tango users
122
+ get showTangoAccuracy() {
123
+ return this.isTango;
124
+ }
125
+ statusDropdownOpen = false;
126
+ isStatusSelected(status) {
127
+ const selected = this.filterForm.value.status || [];
128
+ return selected.includes(status);
129
+ }
130
+ onStatusChange(event, status) {
131
+ const checkbox = event.target;
132
+ const selected = this.filterForm.value.status || [];
133
+ let next;
134
+ if (checkbox.checked) {
135
+ next = selected.includes(status) ? selected : [...selected, status];
136
+ }
137
+ else {
138
+ next = selected.filter(s => s !== status);
139
+ }
140
+ this.filterForm.patchValue({ status: next });
141
+ }
142
+ toggleStatusDropdown(event) {
143
+ if (event) {
144
+ event.stopPropagation(); // avoid document click closing it
145
+ }
146
+ this.statusDropdownOpen = !this.statusDropdownOpen;
147
+ }
148
+ // Are all statuses currently selected?
149
+ areAllStatusesSelected() {
150
+ const selected = this.filterForm.value.status || [];
151
+ return selected.length > 0 && selected.length === this.statusOptions.length;
152
+ }
153
+ // Handle "Select All" checkbox change
154
+ onStatusSelectAllChange(event) {
155
+ const checkbox = event.target;
156
+ if (checkbox.checked) {
157
+ // Select every status
158
+ this.filterForm.patchValue({ status: [...this.statusOptions] });
159
+ }
160
+ else {
161
+ // Clear all
162
+ this.filterForm.patchValue({ status: [] });
163
+ }
164
+ }
165
+ get selectedStatuses() {
166
+ return this.filterForm.value.status || [];
167
+ }
168
+ isBetween(controlName) {
169
+ return this.filterForm.get(controlName)?.value === 'between';
170
+ }
171
+ ngOnChanges(changes) {
172
+ if (changes['client'] || changes['permissionType'] || changes['userType']) {
173
+ this.loadReviewerList();
174
+ }
175
+ }
176
+ // full user list you already have
177
+ userList = [];
178
+ reviewerSearchTerm = '';
179
+ // ✅ simple computed list for *ngFor
180
+ get filteredReviewerList() {
181
+ const term = (this.reviewerSearchTerm || '').trim().toLowerCase();
182
+ if (!term) {
183
+ return this.userList;
184
+ }
185
+ return this.userList.filter(u => {
186
+ const email = (u.email || '').toLowerCase();
187
+ const name = (u.name || '').toLowerCase();
188
+ return email.includes(term) || name.includes(term);
189
+ });
190
+ }
191
+ approverSearchTerm;
192
+ get filteredApproverList() {
193
+ const term = (this.approverSearchTerm || '').trim().toLowerCase();
194
+ if (!term) {
195
+ return this.userList;
196
+ }
197
+ return this.userList.filter((u) => {
198
+ const email = (u.email || '').toLowerCase();
199
+ const name = (u.name || '').toLowerCase();
200
+ return email.includes(term) || name.includes(term);
201
+ });
202
+ }
203
+ onApproverSearch(value) {
204
+ this.approverSearchTerm = value;
205
+ }
206
+ loadReviewerList() {
207
+ if (!this.client) {
208
+ this.userList = [];
209
+ return;
210
+ }
211
+ let type;
212
+ if (this.userType === 'tango') {
213
+ type = 'tango'; // or 'all'
214
+ }
215
+ else if (this.permissionType === 'review') {
216
+ type = 'review';
217
+ }
218
+ else if (this.permissionType === 'approve') {
219
+ type = 'approve';
220
+ }
221
+ else {
222
+ this.userList = [];
223
+ return;
224
+ }
225
+ this.service.getReviewerApi(this.client, type, '').subscribe({
226
+ next: (res) => {
227
+ if (res && res.code === 200) {
228
+ this.userList = res.data;
229
+ }
230
+ else {
231
+ this.userList = [];
232
+ }
233
+ },
234
+ error: () => {
235
+ this.userList = [];
236
+ }
237
+ });
238
+ }
239
+ // open flags
240
+ reviewerDropdownOpen = false;
241
+ approverDropdownOpen = false;
242
+ // convenience getters
243
+ get selectedReviewedBy() {
244
+ return this.filterForm.value.reviewedBy || [];
245
+ }
246
+ get selectedApprovedBy() {
247
+ return this.filterForm.value.approvedBy || [];
248
+ }
249
+ // --- Reviewed By helpers ---
250
+ toggleReviewerDropdown(event) {
251
+ if (event)
252
+ event.stopPropagation();
253
+ this.reviewerDropdownOpen = !this.reviewerDropdownOpen;
254
+ }
255
+ isReviewerSelected(email) {
256
+ return this.selectedReviewedBy.includes(email);
257
+ }
258
+ onReviewerChange(event, email) {
259
+ const checkbox = event.target;
260
+ const selected = [...this.selectedReviewedBy];
261
+ if (checkbox.checked) {
262
+ if (!selected.includes(email))
263
+ selected.push(email);
264
+ }
265
+ else {
266
+ const i = selected.indexOf(email);
267
+ if (i >= 0)
268
+ selected.splice(i, 1);
269
+ }
270
+ this.filterForm.patchValue({ reviewedBy: selected });
271
+ }
272
+ areAllReviewersSelected() {
273
+ return (this.userList.length > 0 &&
274
+ this.selectedReviewedBy.length === this.userList.length);
275
+ }
276
+ onReviewerSelectAll(event) {
277
+ const checkbox = event.target;
278
+ if (checkbox.checked) {
279
+ this.filterForm.patchValue({
280
+ reviewedBy: this.userList.map((u) => u.email),
281
+ });
282
+ }
283
+ else {
284
+ this.filterForm.patchValue({ reviewedBy: [] });
285
+ }
286
+ }
287
+ // --- Approved By helpers ---
288
+ toggleApproverDropdown(event) {
289
+ if (event)
290
+ event.stopPropagation();
291
+ this.approverDropdownOpen = !this.approverDropdownOpen;
292
+ }
293
+ isApproverSelected(email) {
294
+ return this.selectedApprovedBy.includes(email);
295
+ }
296
+ onApproverChange(event, email) {
297
+ const checkbox = event.target;
298
+ const selected = [...this.selectedApprovedBy];
299
+ if (checkbox.checked) {
300
+ if (!selected.includes(email))
301
+ selected.push(email);
302
+ }
303
+ else {
304
+ const i = selected.indexOf(email);
305
+ if (i >= 0)
306
+ selected.splice(i, 1);
307
+ }
308
+ this.filterForm.patchValue({ approvedBy: selected });
309
+ }
310
+ areAllApproversSelected() {
311
+ return (this.userList.length > 0 &&
312
+ this.selectedApprovedBy.length === this.userList.length);
313
+ }
314
+ onApproverSelectAll(event) {
315
+ const checkbox = event.target;
316
+ if (checkbox.checked) {
317
+ this.filterForm.patchValue({
318
+ approvedBy: this.userList.map((u) => u.email),
319
+ });
320
+ }
321
+ else {
322
+ this.filterForm.patchValue({ approvedBy: [] });
323
+ }
324
+ }
325
+ onReset() {
326
+ this.filterForm.reset({
327
+ status: [],
328
+ reviewerCondition: null,
329
+ reviewerFrom: null,
330
+ reviewerTo: null,
331
+ approverCondition: null,
332
+ approverFrom: null,
333
+ approverTo: null,
334
+ tangoCondition: null,
335
+ tangoFrom: null,
336
+ tangoTo: null,
337
+ reviewedBy: [],
338
+ approvedBy: []
339
+ });
340
+ // 2️⃣ Reset search terms
341
+ this.reviewerSearchTerm = '';
342
+ this.approverSearchTerm = '';
343
+ // 3️⃣ Build empty payload to send back
344
+ const payload = {
345
+ filterByStatus: [],
346
+ filterByReviewer: null,
347
+ filterByApprover: null,
348
+ filterByTango: null,
349
+ filterByReviewedBy: [],
350
+ fileterByApprovedBy: []
351
+ };
352
+ // 4️⃣ Emit the now-empty filter result
353
+ this.apply.emit(payload);
354
+ // 5️⃣ Close the filter panel
355
+ this.close();
356
+ }
357
+ mapAccuracy(condition, from, to) {
358
+ // nothing selected
359
+ if (!condition || from == null)
360
+ return null;
361
+ // "between" → "90 to 100"
362
+ if (condition === 'between') {
363
+ if (to == null)
364
+ return null;
365
+ return `${from} to ${to}`;
366
+ }
367
+ // other conditions (gt, lt, gte, lte)
368
+ const opMap = {
369
+ gt: '>',
370
+ lt: '<',
371
+ gte: '>=',
372
+ lte: '<=',
373
+ between: '', // already handled above
374
+ };
375
+ return `${opMap[condition]} ${from}`; // e.g. ">= 90"
376
+ }
377
+ onApply() {
378
+ const raw = this.filterForm.value;
379
+ const reviewerStr = this.mapAccuracy(raw.reviewerCondition, raw.reviewerFrom, raw.reviewerTo);
380
+ const approverStr = this.mapAccuracy(raw.approverCondition, raw.approverFrom, raw.approverTo);
381
+ const tangoStr = this.mapAccuracy(raw.tangoCondition, raw.tangoFrom, raw.tangoTo);
382
+ const payload = {
383
+ filterByStatus: raw.status || [],
384
+ filterByReviewer: reviewerStr,
385
+ filterByApprover: approverStr,
386
+ filterByTango: tangoStr,
387
+ filterByReviewedBy: raw.reviewedBy || [],
388
+ fileterByApprovedBy: raw.approvedBy || [],
389
+ };
390
+ this.apply.emit(payload);
391
+ this.close();
392
+ this.showPanel = false;
393
+ }
394
+ dropdownState = {
395
+ status: false,
396
+ reviewer: false,
397
+ approver: false
398
+ };
399
+ // @HostListener('document:click')
400
+ closeAll() {
401
+ this.dropdownState.status = false;
402
+ this.dropdownState.reviewer = false;
403
+ this.dropdownState.approver = false;
404
+ }
405
+ toggleDropdown(type, event) {
406
+ event.stopPropagation();
407
+ // Close all before opening a new one
408
+ this.closeAll();
409
+ // Toggle only the selected one
410
+ this.dropdownState[type] = !this.dropdownState[type];
411
+ }
412
+ isDropdownOpen(type) {
413
+ return this.dropdownState[type];
414
+ }
415
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TicketFilterPanelComponent, deps: [{ token: i1.FormBuilder }, { token: i0.ElementRef }, { token: i2.TicketService }], target: i0.ɵɵFactoryTarget.Component });
416
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: TicketFilterPanelComponent, selector: "lib-ticket-filter-panel", inputs: { permissionType: "permissionType", userType: "userType", client: "client" }, outputs: { apply: "apply", panelClosed: "panelClosed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, usesOnChanges: true, ngImport: i0, template: "<!-- ticket-filter-panel.component.html -->\r\n<div class=\"filter-wrapper\" *ngIf=\"isOpen\">\r\n <div class=\"filter-card\">\r\n <div class=\"filter-header d-flex justify-content-between align-items-center mb-3\">\r\n <div class=\"title\">Filter Options</div>\r\n <!-- <button type=\"button\" class=\"btn-close\" (click)=\"close()\">\u2715</button> -->\r\n </div>\r\n\r\n <form [formGroup]=\"filterForm\">\r\n <!-- Status -->\r\n<div class=\"mb-3 position-relative\" (click)=\"$event.stopPropagation()\">\r\n <label class=\"form-label\">Status</label>\r\n\r\n <!-- Header / trigger -->\r\n <div\r\n class=\"status-select border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleDropdown('status', $event)\"\r\n >\r\n <span *ngIf=\"!selectedStatuses.length\">Select</span>\r\n\r\n <span *ngIf=\"selectedStatuses.length === 1\">\r\n {{ selectedStatuses[0] }}\r\n </span>\r\n\r\n <span *ngIf=\"selectedStatuses.length > 1\" class=\"d-flex align-items-center\">\r\n <span>{{ selectedStatuses[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedStatuses.length - 1 }}\r\n </span>\r\n </span>\r\n\r\n </div>\r\n\r\n <!-- DROPDOWN PANEL (OVERLAY) -->\r\n <div\r\n class=\"status-dropdown position-absolute w-100 mt-1 border rounded p-1 bg-white\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n *ngIf=\"isDropdownOpen('status')\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 d-flex align-items-center mb-2\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input \"\r\n id=\"status-select-all\"\r\n [checked]=\"areAllStatusesSelected()\"\r\n (change)=\"onStatusSelectAllChange($event)\"\r\n />\r\n <label class=\"form-check-label text-dark ms-2\" for=\"status-select-all\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n\r\n <!-- Options -->\r\n <div\r\n class=\"form-check px-0 d-flex align-items-center mb-1\"\r\n *ngFor=\"let s of statusOptions\"\r\n >\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input \"\r\n [id]=\"'status-' + s\"\r\n [checked]=\"isStatusSelected(s)\"\r\n (change)=\"onStatusChange($event, s)\"\r\n />\r\n <label class=\"form-check-label text-dark ms-2\" [for]=\"'status-' + s\">\r\n {{ s }}\r\n </label>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n\r\n <!-- Reviewer accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showReviewerAccuracy\" (click)=\"closeAll()\">\r\n <label class=\"form-label\">Reviewer accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-100\" formControlName=\"reviewerCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <!-- one or two inputs -->\r\n <ng-container *ngIf=\"isBetween('reviewerCondition'); else singleReviewer\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerFrom\"\r\n placeholder=\"From\" (input)=\"limitValue($event, 'reviewerFrom')\" />\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerTo\"\r\n placeholder=\"To\" (input)=\"limitValue($event, 'reviewerTo')\" />\r\n </ng-container>\r\n <ng-template #singleReviewer>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerFrom\"\r\n placeholder=\"1 to 100%\" (input)=\"limitValue($event, 'reviewerFrom')\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n\r\n <!-- Approver accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showApproverAccuracy\" (click)=\"closeAll()\">\r\n <label class=\"form-label\">Approver accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-100\" formControlName=\"approverCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <ng-container *ngIf=\"isBetween('approverCondition'); else singleApprover\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverFrom\"\r\n placeholder=\"From\" \r\n (input)=\"limitValue($event, 'approverFrom')\"/>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverTo\"\r\n placeholder=\"To\" (input)=\"limitValue($event, 'approverTo')\" />\r\n </ng-container>\r\n <ng-template #singleApprover>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverFrom\"\r\n placeholder=\"1 to 100%\" (input)=\"limitValue($event, 'approverFrom')\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n\r\n <!-- Tango accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showTangoAccuracy\" (click)=\"closeAll()\">\r\n <label class=\"form-label\">Tango accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-100\" formControlName=\"tangoCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <ng-container *ngIf=\"isBetween('tangoCondition'); else singleTango\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoFrom\"\r\n placeholder=\"From\" (input)=\"limitValue($event, 'tangoFrom')\" />\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoTo\"\r\n placeholder=\"To\" (input)=\"limitValue($event, 'tangoTo')\" />\r\n </ng-container>\r\n <ng-template #singleTango>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoFrom\"\r\n placeholder=\"1 to 100%\" (input)=\"limitValue($event, 'tangoFrom')\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n<div\r\n class=\"mb-3 position-relative\"\r\n *ngIf=\"showReviewedBy\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n <label class=\"form-label\">Reviewed by</label>\r\n\r\n <!-- Trigger / display -->\r\n <div\r\n class=\"border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleDropdown('reviewer', $event)\"\r\n >\r\n <!-- 0 selected -->\r\n <span *ngIf=\"!selectedReviewedBy.length\">\r\n Select\r\n </span>\r\n\r\n <!-- 1 selected -->\r\n <span *ngIf=\"selectedReviewedBy.length === 1\">\r\n {{ selectedReviewedBy[0] }}\r\n </span>\r\n\r\n <!-- >1 selected -->\r\n <span\r\n *ngIf=\"selectedReviewedBy.length > 1\"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <span>{{ selectedReviewedBy[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedReviewedBy.length - 1 }}\r\n </span>\r\n </span>\r\n </div>\r\n\r\n<div\r\n *ngIf=\"isDropdownOpen('reviewer')\"\r\n class=\"position-absolute w-100 border rounded bg-white p-1 mt-1\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n\r\n <!-- \uD83D\uDD0D Search box -->\r\n <!-- <div class=\"mb-2 px-0\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search by email\"\r\n [(ngModel)]=\"reviewerSearchTerm\"\r\n (click)=\"$event.stopPropagation()\"\r\n />\r\n </div> -->\r\n\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 mb-2 d-flex align-items-center\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"reviewer-all\"\r\n [checked]=\"areAllReviewersSelected()\"\r\n (change)=\"onReviewerSelectAll($event)\"\r\n />\r\n <label for=\"reviewer-all\" class=\"form-check-label text-dark ms-2\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- Options \u2013 now use getter filteredReviewerList -->\r\n <div\r\n class=\"form-check mb-1 px-0 d-flex align-items-center\"\r\n *ngFor=\"let u of filteredReviewerList\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"'rev-' + u.email\"\r\n [checked]=\"isReviewerSelected(u.email)\"\r\n (change)=\"onReviewerChange($event, u.email)\"\r\n />\r\n <label class=\"form-check-label text-dark ms-2\" [for]=\"'rev-' + u.email\">\r\n {{ u.email }}\r\n </label>\r\n </div>\r\n</div>\r\n\r\n\r\n</div>\r\n\r\n\r\n <!-- Approved By -->\r\n<div\r\n class=\"mb-3 position-relative\"\r\n *ngIf=\"showApprovedBy\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n <label class=\"form-label\">Approved by</label>\r\n\r\n <!-- Trigger / display -->\r\n <div\r\n class=\"border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleDropdown('approver', $event)\"\r\n >\r\n <!-- 0 selected -->\r\n <span *ngIf=\"!selectedApprovedBy.length\">\r\n Select\r\n </span>\r\n\r\n <!-- 1 selected -->\r\n <span *ngIf=\"selectedApprovedBy.length === 1\">\r\n {{ selectedApprovedBy[0] }}\r\n </span>\r\n\r\n <!-- >1 selected -->\r\n <span\r\n *ngIf=\"selectedApprovedBy.length > 1\"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <span>{{ selectedApprovedBy[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedApprovedBy.length - 1 }}\r\n </span>\r\n </span>\r\n\r\n </div>\r\n<!-- Dropdown panel -->\r\n<div\r\n *ngIf=\"isDropdownOpen('approver')\"\r\n class=\"position-absolute w-100 border rounded bg-white p-1 mt-1\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n\r\n <!-- \uD83D\uDD0D Search box -->\r\n <!-- <div class=\"mb-2 px-0\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search by email\"\r\n [ngModel]=\"approverSearchTerm\"\r\n (ngModelChange)=\"onReviewerSearch($event)\"\r\n (click)=\"$event.stopPropagation()\"\r\n />\r\n </div> -->\r\n\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 mb-2 d-flex align-items-center\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"reviewer-all\"\r\n [checked]=\"areAllReviewersSelected()\"\r\n (change)=\"onReviewerSelectAll($event)\"\r\n />\r\n <label for=\"reviewer-all\" class=\"form-check-label text-dark ms-2\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- Options (use filteredReviewerList instead of userList) -->\r\n <div\r\n class=\"form-check mb-1 px-0 d-flex align-items-center\"\r\n *ngFor=\"let u of filteredApproverList\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"'rev-' + u.email\"\r\n [checked]=\"isReviewerSelected(u.email)\"\r\n (change)=\"onReviewerChange($event, u.email)\"\r\n />\r\n <label class=\"form-check-label text-dark ms-2\" [for]=\"'rev-' + u.email\">\r\n {{ u.email }}\r\n </label>\r\n </div>\r\n</div>\r\n\r\n <!-- Dropdown panel -->\r\n\r\n</div>\r\n\r\n\r\n <!-- Footer buttons -->\r\n <div class=\"d-flex justify-content-between w-100 mt-4\">\r\n <button type=\"button\" class=\"btn btn-outline w-50 me-1\" (click)=\"onReset()\">\r\n Reset\r\n </button>\r\n <button type=\"button\" class=\"btn btn-primary w-50 ms-1\" (click)=\"onApply()\">\r\n Apply\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n</div>\r\n", styles: [".filter-wrapper{position:absolute;top:0;right:0;padding:16px;z-index:1050}.filter-card{width:350px;background:#fff;border-radius:12px;padding:16px 18px;box-shadow:0 8px 30px #00000014;font-size:13px}.filter-header .title{font-weight:600;font-size:14px}.btn-close{border:none;background:transparent;font-size:16px;cursor:pointer}.form-label{font-size:12px;margin-bottom:4px}.form-select,.form-control{font-size:13px}.gap-2{gap:4px}.badge{padding:0 6px;border-radius:999px;font-size:11px;background:#e5f3ff;color:#007bff}input[type=checkbox]{width:16px!important;height:16px!important;margin:-2px 5px;border-radius:4px!important;-webkit-appearance:none;-moz-appearance:none;-o-appearance:none;appearance:none;outline:1px solid var(--gray-600, #D0D5DD)!important;box-shadow:none;font-size:.5em;text-align:center;line-height:1em;background:#fff}input[type=checkbox]{outline:1px solid var(--primary-600, #00A3FF)!important;background-color:var(--primary-50, #EAF8FF)}input[type=checkbox]:checked:after{content:\"\";transform:rotate(45deg);border-bottom:2px solid #00A3FF;border-right:2px solid #00A3FF;display:inline-block;width:.5em;padding-left:3px;padding-top:10px;padding-right:0}.text-dark{color:#344054!important}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i1.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: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }] });
417
+ }
418
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: TicketFilterPanelComponent, decorators: [{
419
+ type: Component,
420
+ args: [{ selector: 'lib-ticket-filter-panel', template: "<!-- ticket-filter-panel.component.html -->\r\n<div class=\"filter-wrapper\" *ngIf=\"isOpen\">\r\n <div class=\"filter-card\">\r\n <div class=\"filter-header d-flex justify-content-between align-items-center mb-3\">\r\n <div class=\"title\">Filter Options</div>\r\n <!-- <button type=\"button\" class=\"btn-close\" (click)=\"close()\">\u2715</button> -->\r\n </div>\r\n\r\n <form [formGroup]=\"filterForm\">\r\n <!-- Status -->\r\n<div class=\"mb-3 position-relative\" (click)=\"$event.stopPropagation()\">\r\n <label class=\"form-label\">Status</label>\r\n\r\n <!-- Header / trigger -->\r\n <div\r\n class=\"status-select border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleDropdown('status', $event)\"\r\n >\r\n <span *ngIf=\"!selectedStatuses.length\">Select</span>\r\n\r\n <span *ngIf=\"selectedStatuses.length === 1\">\r\n {{ selectedStatuses[0] }}\r\n </span>\r\n\r\n <span *ngIf=\"selectedStatuses.length > 1\" class=\"d-flex align-items-center\">\r\n <span>{{ selectedStatuses[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedStatuses.length - 1 }}\r\n </span>\r\n </span>\r\n\r\n </div>\r\n\r\n <!-- DROPDOWN PANEL (OVERLAY) -->\r\n <div\r\n class=\"status-dropdown position-absolute w-100 mt-1 border rounded p-1 bg-white\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n *ngIf=\"isDropdownOpen('status')\"\r\n (click)=\"$event.stopPropagation()\"\r\n >\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 d-flex align-items-center mb-2\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input \"\r\n id=\"status-select-all\"\r\n [checked]=\"areAllStatusesSelected()\"\r\n (change)=\"onStatusSelectAllChange($event)\"\r\n />\r\n <label class=\"form-check-label text-dark ms-2\" for=\"status-select-all\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n\r\n <!-- Options -->\r\n <div\r\n class=\"form-check px-0 d-flex align-items-center mb-1\"\r\n *ngFor=\"let s of statusOptions\"\r\n >\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input \"\r\n [id]=\"'status-' + s\"\r\n [checked]=\"isStatusSelected(s)\"\r\n (change)=\"onStatusChange($event, s)\"\r\n />\r\n <label class=\"form-check-label text-dark ms-2\" [for]=\"'status-' + s\">\r\n {{ s }}\r\n </label>\r\n </div>\r\n </div>\r\n</div>\r\n\r\n\r\n\r\n <!-- Reviewer accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showReviewerAccuracy\" (click)=\"closeAll()\">\r\n <label class=\"form-label\">Reviewer accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-100\" formControlName=\"reviewerCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <!-- one or two inputs -->\r\n <ng-container *ngIf=\"isBetween('reviewerCondition'); else singleReviewer\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerFrom\"\r\n placeholder=\"From\" (input)=\"limitValue($event, 'reviewerFrom')\" />\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerTo\"\r\n placeholder=\"To\" (input)=\"limitValue($event, 'reviewerTo')\" />\r\n </ng-container>\r\n <ng-template #singleReviewer>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"reviewerFrom\"\r\n placeholder=\"1 to 100%\" (input)=\"limitValue($event, 'reviewerFrom')\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n\r\n <!-- Approver accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showApproverAccuracy\" (click)=\"closeAll()\">\r\n <label class=\"form-label\">Approver accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-100\" formControlName=\"approverCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <ng-container *ngIf=\"isBetween('approverCondition'); else singleApprover\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverFrom\"\r\n placeholder=\"From\" \r\n (input)=\"limitValue($event, 'approverFrom')\"/>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverTo\"\r\n placeholder=\"To\" (input)=\"limitValue($event, 'approverTo')\" />\r\n </ng-container>\r\n <ng-template #singleApprover>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"approverFrom\"\r\n placeholder=\"1 to 100%\" (input)=\"limitValue($event, 'approverFrom')\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n\r\n <!-- Tango accuracy -->\r\n <div class=\"mb-3\" *ngIf=\"showTangoAccuracy\" (click)=\"closeAll()\">\r\n <label class=\"form-label\">Tango accuracy (%) by condition</label>\r\n <div class=\"d-flex gap-2\">\r\n <select class=\"form-select w-100\" formControlName=\"tangoCondition\">\r\n <option [ngValue]=\"null\">Select</option>\r\n <option *ngFor=\"let c of conditionOptions\" [ngValue]=\"c.value\">\r\n {{ c.label }}\r\n </option>\r\n </select>\r\n\r\n <ng-container *ngIf=\"isBetween('tangoCondition'); else singleTango\">\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoFrom\"\r\n placeholder=\"From\" (input)=\"limitValue($event, 'tangoFrom')\" />\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoTo\"\r\n placeholder=\"To\" (input)=\"limitValue($event, 'tangoTo')\" />\r\n </ng-container>\r\n <ng-template #singleTango>\r\n <input\r\n type=\"number\"\r\n min=\"1\"\r\n max=\"100\"\r\n class=\"form-control\"\r\n formControlName=\"tangoFrom\"\r\n placeholder=\"1 to 100%\" (input)=\"limitValue($event, 'tangoFrom')\" />\r\n </ng-template>\r\n </div>\r\n </div>\r\n<div\r\n class=\"mb-3 position-relative\"\r\n *ngIf=\"showReviewedBy\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n <label class=\"form-label\">Reviewed by</label>\r\n\r\n <!-- Trigger / display -->\r\n <div\r\n class=\"border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleDropdown('reviewer', $event)\"\r\n >\r\n <!-- 0 selected -->\r\n <span *ngIf=\"!selectedReviewedBy.length\">\r\n Select\r\n </span>\r\n\r\n <!-- 1 selected -->\r\n <span *ngIf=\"selectedReviewedBy.length === 1\">\r\n {{ selectedReviewedBy[0] }}\r\n </span>\r\n\r\n <!-- >1 selected -->\r\n <span\r\n *ngIf=\"selectedReviewedBy.length > 1\"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <span>{{ selectedReviewedBy[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedReviewedBy.length - 1 }}\r\n </span>\r\n </span>\r\n </div>\r\n\r\n<div\r\n *ngIf=\"isDropdownOpen('reviewer')\"\r\n class=\"position-absolute w-100 border rounded bg-white p-1 mt-1\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n\r\n <!-- \uD83D\uDD0D Search box -->\r\n <!-- <div class=\"mb-2 px-0\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search by email\"\r\n [(ngModel)]=\"reviewerSearchTerm\"\r\n (click)=\"$event.stopPropagation()\"\r\n />\r\n </div> -->\r\n\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 mb-2 d-flex align-items-center\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"reviewer-all\"\r\n [checked]=\"areAllReviewersSelected()\"\r\n (change)=\"onReviewerSelectAll($event)\"\r\n />\r\n <label for=\"reviewer-all\" class=\"form-check-label text-dark ms-2\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- Options \u2013 now use getter filteredReviewerList -->\r\n <div\r\n class=\"form-check mb-1 px-0 d-flex align-items-center\"\r\n *ngFor=\"let u of filteredReviewerList\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"'rev-' + u.email\"\r\n [checked]=\"isReviewerSelected(u.email)\"\r\n (change)=\"onReviewerChange($event, u.email)\"\r\n />\r\n <label class=\"form-check-label text-dark ms-2\" [for]=\"'rev-' + u.email\">\r\n {{ u.email }}\r\n </label>\r\n </div>\r\n</div>\r\n\r\n\r\n</div>\r\n\r\n\r\n <!-- Approved By -->\r\n<div\r\n class=\"mb-3 position-relative\"\r\n *ngIf=\"showApprovedBy\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n <label class=\"form-label\">Approved by</label>\r\n\r\n <!-- Trigger / display -->\r\n <div\r\n class=\"border rounded px-3 py-2 d-flex justify-content-between align-items-center\"\r\n (click)=\"toggleDropdown('approver', $event)\"\r\n >\r\n <!-- 0 selected -->\r\n <span *ngIf=\"!selectedApprovedBy.length\">\r\n Select\r\n </span>\r\n\r\n <!-- 1 selected -->\r\n <span *ngIf=\"selectedApprovedBy.length === 1\">\r\n {{ selectedApprovedBy[0] }}\r\n </span>\r\n\r\n <!-- >1 selected -->\r\n <span\r\n *ngIf=\"selectedApprovedBy.length > 1\"\r\n class=\"d-flex align-items-center\"\r\n >\r\n <span>{{ selectedApprovedBy[0] }}</span>\r\n <span class=\"badge ms-2\">\r\n +{{ selectedApprovedBy.length - 1 }}\r\n </span>\r\n </span>\r\n\r\n </div>\r\n<!-- Dropdown panel -->\r\n<div\r\n *ngIf=\"isDropdownOpen('approver')\"\r\n class=\"position-absolute w-100 border rounded bg-white p-1 mt-1\"\r\n style=\"z-index: 1000; max-height: 220px; overflow-y: auto;\"\r\n (click)=\"$event.stopPropagation()\"\r\n>\r\n\r\n <!-- \uD83D\uDD0D Search box -->\r\n <!-- <div class=\"mb-2 px-0\">\r\n <input\r\n type=\"text\"\r\n class=\"form-control form-control-sm\"\r\n placeholder=\"Search by email\"\r\n [ngModel]=\"approverSearchTerm\"\r\n (ngModelChange)=\"onReviewerSearch($event)\"\r\n (click)=\"$event.stopPropagation()\"\r\n />\r\n </div> -->\r\n\r\n <!-- Select All -->\r\n <div class=\"form-check px-0 mb-2 d-flex align-items-center\">\r\n <input\r\n type=\"checkbox\"\r\n class=\"form-check-input\"\r\n id=\"reviewer-all\"\r\n [checked]=\"areAllReviewersSelected()\"\r\n (change)=\"onReviewerSelectAll($event)\"\r\n />\r\n <label for=\"reviewer-all\" class=\"form-check-label text-dark ms-2\">\r\n Select All\r\n </label>\r\n </div>\r\n\r\n <!-- Options (use filteredReviewerList instead of userList) -->\r\n <div\r\n class=\"form-check mb-1 px-0 d-flex align-items-center\"\r\n *ngFor=\"let u of filteredApproverList\"\r\n >\r\n <input\r\n class=\"form-check-input\"\r\n type=\"checkbox\"\r\n [id]=\"'rev-' + u.email\"\r\n [checked]=\"isReviewerSelected(u.email)\"\r\n (change)=\"onReviewerChange($event, u.email)\"\r\n />\r\n <label class=\"form-check-label text-dark ms-2\" [for]=\"'rev-' + u.email\">\r\n {{ u.email }}\r\n </label>\r\n </div>\r\n</div>\r\n\r\n <!-- Dropdown panel -->\r\n\r\n</div>\r\n\r\n\r\n <!-- Footer buttons -->\r\n <div class=\"d-flex justify-content-between w-100 mt-4\">\r\n <button type=\"button\" class=\"btn btn-outline w-50 me-1\" (click)=\"onReset()\">\r\n Reset\r\n </button>\r\n <button type=\"button\" class=\"btn btn-primary w-50 ms-1\" (click)=\"onApply()\">\r\n Apply\r\n </button>\r\n </div>\r\n </form>\r\n </div>\r\n</div>\r\n", styles: [".filter-wrapper{position:absolute;top:0;right:0;padding:16px;z-index:1050}.filter-card{width:350px;background:#fff;border-radius:12px;padding:16px 18px;box-shadow:0 8px 30px #00000014;font-size:13px}.filter-header .title{font-weight:600;font-size:14px}.btn-close{border:none;background:transparent;font-size:16px;cursor:pointer}.form-label{font-size:12px;margin-bottom:4px}.form-select,.form-control{font-size:13px}.gap-2{gap:4px}.badge{padding:0 6px;border-radius:999px;font-size:11px;background:#e5f3ff;color:#007bff}input[type=checkbox]{width:16px!important;height:16px!important;margin:-2px 5px;border-radius:4px!important;-webkit-appearance:none;-moz-appearance:none;-o-appearance:none;appearance:none;outline:1px solid var(--gray-600, #D0D5DD)!important;box-shadow:none;font-size:.5em;text-align:center;line-height:1em;background:#fff}input[type=checkbox]{outline:1px solid var(--primary-600, #00A3FF)!important;background-color:var(--primary-50, #EAF8FF)}input[type=checkbox]:checked:after{content:\"\";transform:rotate(45deg);border-bottom:2px solid #00A3FF;border-right:2px solid #00A3FF;display:inline-block;width:.5em;padding-left:3px;padding-top:10px;padding-right:0}.text-dark{color:#344054!important}\n"] }]
421
+ }], ctorParameters: () => [{ type: i1.FormBuilder }, { type: i0.ElementRef }, { type: i2.TicketService }], propDecorators: { apply: [{
422
+ type: Output
423
+ }], panelClosed: [{
424
+ type: Output
425
+ }], permissionType: [{
426
+ type: Input
427
+ }], userType: [{
428
+ type: Input
429
+ }], client: [{
430
+ type: Input
431
+ }], onDocumentClick: [{
432
+ type: HostListener,
433
+ args: ['document:click', ['$event']]
434
+ }] } });
435
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGlja2V0LWZpbHRlci1wYW5lbC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90YW5nby1tYW5hZ2UtdGlja2V0cy9zcmMvbGliL2NvbXBvbmVudHMvdGlja2V0LWZpbHRlci1wYW5lbC90aWNrZXQtZmlsdGVyLXBhbmVsLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLW1hbmFnZS10aWNrZXRzL3NyYy9saWIvY29tcG9uZW50cy90aWNrZXQtZmlsdGVyLXBhbmVsL3RpY2tldC1maWx0ZXItcGFuZWwuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBYyxZQUFZLEVBQUUsWUFBWSxFQUFFLEtBQUssRUFBYSxNQUFNLEVBQWlCLE1BQU0sZUFBZSxDQUFDO0FBQzNILE9BQU8sRUFBMEIsVUFBVSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7Ozs7O0FBVXBFLE1BQU0sT0FBTywwQkFBMEI7SUFnRmpCO0lBQXdCO0lBQXlCO0lBL0UxRCxLQUFLLEdBQUcsSUFBSSxZQUFZLEVBQU8sQ0FBQztJQUNqQyxXQUFXLEdBQUcsSUFBSSxZQUFZLEVBQVEsQ0FBQyxDQUFHLGdCQUFnQjtJQUMzRCxjQUFjLEdBQWtCLElBQUksQ0FBQztJQUN2QyxRQUFRLEdBQWtCLElBQUksQ0FBQyxDQUFDLHlCQUF5QjtJQUN6RCxNQUFNLENBQU07SUFFckIsZUFBZSxDQUFDLEtBQWlCO1FBRS9CLG1DQUFtQztRQUNuQyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7UUFDbEMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxRQUFRLEdBQUcsS0FBSyxDQUFDO1FBQ3BDLElBQUksQ0FBQyxhQUFhLENBQUMsUUFBUSxHQUFHLEtBQUssQ0FBQztRQUVwQywrQ0FBK0M7UUFDL0MsSUFBSSxDQUFDLElBQUksQ0FB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QUFFLENBQUM7UUFFeEIscUNBQXFDO1FBQ3JDLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztRQUVoQiwrQkFBK0I7UUFDL0IsSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDdkQsQ0FBQztJQUVELGNBQWMsQ0FBQyxJQUF3QztRQUNyRCxPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDbEMsQ0FBQzt3R0FqZVksMEJBQTBCOzRGQUExQiwwQkFBMEIseVNDWHZDLHkzWkFrWUE7OzRGRHZYYSwwQkFBMEI7a0JBTHRDLFNBQVM7K0JBQ0UseUJBQXlCO3FJQUt4QixLQUFLO3NCQUFkLE1BQU07Z0JBQ0UsV0FBVztzQkFBcEIsTUFBTTtnQkFDRSxjQUFjO3NCQUF0QixLQUFLO2dCQUNDLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csTUFBTTtzQkFBZCxLQUFLO2dCQUVOLGVBQWU7c0JBRGIsWUFBWTt1QkFBQyxnQkFBZ0IsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRWxlbWVudFJlZiwgRXZlbnRFbWl0dGVyLCBIb3N0TGlzdGVuZXIsIElucHV0LCBPbkNoYW5nZXMsIE91dHB1dCwgU2ltcGxlQ2hhbmdlcyB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBGb3JtQnVpbGRlciwgRm9ybUdyb3VwLCBWYWxpZGF0b3JzIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBUaWNrZXRTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvdGlja2V0LnNlcnZpY2UnO1xyXG5cclxudHlwZSBDb25kaXRpb24gPSAnZ3QnIHwgJ2x0JyB8ICdndGUnIHwgJ2x0ZScgfCAnYmV0d2Vlbic7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2xpYi10aWNrZXQtZmlsdGVyLXBhbmVsJyxcclxuICB0ZW1wbGF0ZVVybDogJy4vdGlja2V0LWZpbHRlci1wYW5lbC5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL3RpY2tldC1maWx0ZXItcGFuZWwuY29tcG9uZW50LnNjc3MnXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBUaWNrZXRGaWx0ZXJQYW5lbENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XHJcbiAgIEBPdXRwdXQoKSBhcHBseSA9IG5ldyBFdmVudEVtaXR0ZXI8YW55PigpO1xyXG4gIEBPdXRwdXQoKSBwYW5lbENsb3NlZCA9IG5ldyBFdmVudEVtaXR0ZXI8dm9pZD4oKTsgICAvLyDinIUgbm90IGBjbG9zZWBcclxuICBASW5wdXQoKSBwZXJtaXNzaW9uVHlwZTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XHJcbkBJbnB1dCgpIHVzZXJUeXBlOiBzdHJpbmcgfCBudWxsID0gbnVsbDsgLy8gZS5nLiAndGFuZ28nIG9yIG90aGVyc1xyXG5ASW5wdXQoKSBjbGllbnQgOmFueTtcclxuIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmNsaWNrJywgWyckZXZlbnQnXSlcclxub25Eb2N1bWVudENsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XHJcblxyXG4gIC8vIDHvuI/ig6MgQWx3YXlzIGNsb3NlIGRyb3Bkb3ducyBmaXJzdFxyXG4gIHRoaXMuZHJvcGRvd25TdGF0ZS5zdGF0dXMgPSBmYWxzZTtcclxuICB0aGlzLmRyb3Bkb3duU3RhdGUucmV2aWV3ZXIgPSBmYWxzZTtcclxuICB0aGlzLmRyb3Bkb3duU3RhdGUuYXBwcm92ZXIgPSBmYWxzZTtcclxuXHJcbiAgLy8gMu+4j+KDoyBJZiBmaWx0ZXIgaXMgbm90IG9wZW4g4oaSIG5vdGhpbmcgdG8gY2xvc2VcclxuICBpZiAoIXRoaXMuaXNPcGVuKSByZXR1cm47XHJcblxyXG4gIC8vIDPvuI/ig6MgQ2hlY2sgaWYgY2xpY2tlZCBpbnNpZGUgZmlsdGVyIGNhcmRcclxuICBjb25zdCBjbGlja2VkSW5zaWRlID0gdGhpcy5lUmVmLm5hdGl2ZUVsZW1lbnQuY29udGFpbnMoZXZlbnQudGFyZ2V0KTtcclxuXHJcbiAgLy8gNO+4j+KDoyBJZiBjbGlja2VkIE9VVFNJREUg4oaSIGNsb3NlIGVudGlyZSBmaWx0ZXIgcGFuZWxcclxuICBpZiAoIWNsaWNrZWRJbnNpZGUpIHtcclxuICAgIHRoaXMuaXNPcGVuID0gZmFsc2U7XHJcbiAgICB0aGlzLnBhbmVsQ2xvc2VkLmVtaXQoKTtcclxuICAgdGhpcy5maWx0ZXJGb3JtLnJlc2V0KHtcclxuICAgIHN0YXR1czogW10sXHJcbiAgICByZXZpZXdlckNvbmRpdGlvbjogbnVsbCxcclxuICAgIHJldmlld2VyRnJvbTogbnVsbCxcclxuICAgIHJldmlld2VyVG86IG51bGwsXHJcblxyXG4gICAgYXBwcm92ZXJDb25kaXRpb246IG51bGwsXHJcbiAgICBhcHByb3ZlckZyb206IG51bGwsXHJcbiAgICBhcHByb3ZlclRvOiBudWxsLFxyXG5cclxuICAgIHRhbmdvQ29uZGl0aW9uOiBudWxsLFxyXG4gICAgdGFuZ29Gcm9tOiBudWxsLFxyXG4gICAgdGFuZ29UbzogbnVsbCxcclxuXHJcbiAgICByZXZpZXdlZEJ5OiBbXSxcclxuICAgIGFwcHJvdmVkQnk6IFtdXHJcbiAgfSk7XHJcblxyXG4gIH1cclxufVxyXG4gIGlzT3BlbiA9IGZhbHNlOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBjb250cm9scyB2aXNpYmlsaXR5XHJcblxyXG4gIC8vIGNhbGxlZCBmcm9tIHBhcmVudCB2aWEgI2ZpbHRlclBhbmVsLm9wZW4oKVxyXG4gIG9wZW4oKSB7XHJcbiAgICB0aGlzLmlzT3BlbiA9IHRydWU7XHJcbiAgfVxyXG5cclxuICAvLyBjYWxsZWQgZnJvbSBjbG9zZSBidXR0b24gaW5zaWRlIHRoZSBwYW5lbFxyXG4gIGNsb3NlKCkge1xyXG4gICAgdGhpcy5pc09wZW4gPSBmYWxzZTtcclxuICAgIHRoaXMucGFuZWxDbG9zZWQuZW1pdCgpO1xyXG4gIH1cclxuXHJcbiAgc2hvd1BhbmVsID0gZmFsc2U7ICAgICAgICAgICAvLyB5b3UgY2FuIGFsc28gY29udHJvbCB0aGlzIGZyb20gcGFyZW50XHJcblxyXG5zdGF0dXNPcHRpb25zOiBhbnlbXSA9IFtcclxuICAnT3BlbicsXHJcbiAgJ0luLVByb2dyZXNzJyxcclxuICAnQ2xvc2VkJyxcclxuICAnVW5kZXIgVGFuZ28gUmV2aWV3JyxcclxuICAnVGFuZ28gUmV2aWV3IERvbmUnLFxyXG4gICdFeHBpcmVkJyxcclxuICAnVGFuZ28gRXhwaXJlZCcsXHJcbl07XHJcblxyXG5cclxuICBjb25kaXRpb25PcHRpb25zID0gW1xyXG4gICAgeyB2YWx1ZTogJ2d0JywgbGFiZWw6ICc+IEdyZWF0ZXIgdGhhbicgfSxcclxuICAgIHsgdmFsdWU6ICdsdCcsIGxhYmVsOiAnPCBMZXNzZXIgdGhhbicgfSxcclxuICAgIHsgdmFsdWU6ICdndGUnLCBsYWJlbDogJz49IEdyZWF0ZXIgdGhhbiBvciBlcXVhbCB0bycgfSxcclxuICAgIHsgdmFsdWU6ICdsdGUnLCBsYWJlbDogJzw9IExlc3NlciB0aGFuIG9yIGVxdWFsIHRvJyB9LFxyXG4gICAgeyB2YWx1ZTogJ2JldHdlZW4nLCBsYWJlbDogJ0JldHdlZW4nIH0sXHJcbiAgXTtcclxuXHJcbiAgZmlsdGVyRm9ybTogRm9ybUdyb3VwO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGZiOiBGb3JtQnVpbGRlcixwcml2YXRlIGVSZWY6IEVsZW1lbnRSZWYscHJpdmF0ZSBzZXJ2aWNlOlRpY2tldFNlcnZpY2UpIHtcclxuICAgIHRoaXMuZmlsdGVyRm9ybSA9IHRoaXMuZmIuZ3JvdXAoe1xyXG4gICAgICBzdGF0dXM6IFtbXV0sXHJcblxyXG4gICAgICByZXZpZXdlckNvbmRpdGlvbjogW251bGwgYXMgQ29uZGl0aW9uIHwgbnVsbF0sXHJcbiAgICAgIHJldmlld2VyRnJvbTogW251bGwsW1ZhbGlkYXRvcnMubWluKDApLCBWYWxpZGF0b3JzLm1heCgxMDApXV0sXHJcbiAgICAgIHJldmlld2VyVG86IFtudWxsLFtWYWxpZGF0b3JzLm1pbigwKSwgVmFsaWRhdG9ycy5tYXgoMTAwKV1dLFxyXG5cclxuICAgICAgYXBwcm92ZXJDb25kaXRpb246IFtudWxsIGFzIENvbmRpdGlvbiB8IG51bGxdLFxyXG4gICAgICBhcHByb3ZlckZyb206IFtudWxsLFtWYWxpZGF0b3JzLm1pbigwKSwgVmFsaWRhdG9ycy5tYXgoMTAwKV1dLFxyXG4gICAgICBhcHByb3ZlclRvOiBbbnVsbCxbVmFsaWRhdG9ycy5taW4oMCksIFZhbGlkYXRvcnMubWF4KDEwMCldXSxcclxuXHJcbiAgICAgIHRhbmdvQ29uZGl0aW9uOiBbbnVsbCBhcyBDb25kaXRpb24gfCBudWxsXSxcclxuICAgICAgdGFuZ29Gcm9tOiBbbnVsbCxbVmFsaWRhdG9ycy5taW4oMCksIFZhbGlkYXRvcnMubWF4KDEwMCldXSxcclxuICAgICAgdGFuZ29UbzogW251bGwsW1ZhbGlkYXRvcnMubWluKDApLCBWYWxpZGF0b3JzLm1heCgxMDApXV0sXHJcblxyXG4gICAgICByZXZpZXdlZEJ5OiBbW11dLFxyXG4gIGFwcHJvdmVkQnk6IFtbXV0sICBcclxuICAgIH0pO1xyXG4gICAgdGhpcy5vblJlc2V0KCk7XHJcbiAgfVxyXG5saW1pdFZhbHVlKGV2ZW50OiBhbnksIGNvbnRyb2xOYW1lOiBzdHJpbmcpIHtcclxuICBsZXQgdmFsdWUgPSBOdW1iZXIoZXZlbnQudGFyZ2V0LnZhbHVlKTtcclxuXHJcbiAgaWYgKHZhbHVlIDwgMCkgdmFsdWUgPSAwO1xyXG4gIGlmICh2YWx1ZSA+IDEwMCkgdmFsdWUgPSAxMDA7XHJcblxyXG4gIGV2ZW50LnRhcmdldC52YWx1ZSA9IHZhbHVlO1xyXG4gIHRoaXMuZmlsdGVyRm9ybS5nZXQoY29udHJvbE5hbWUpPy5zZXRWYWx1ZSh2YWx1ZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xyXG59XHJcblxyXG5nZXQgaXNUYW5nbygpOiBib29sZWFuIHtcclxuICByZXR1cm4gdGhpcy51c2VyVHlwZSA9PT0gJ3RhbmdvJztcclxufVxyXG5cclxuLy8gU0hPVyAvIEhJREUgUlVMRVNcclxuXHJcbi8vIFJldmlld2VyIGFjY3VyYWN5IGFuZCBcIlJldmlld2VkIGJ5XCIgdmlzaWJsZSBmb3IgdGFuZ28gKyByZXZpZXdlclxyXG5nZXQgc2hvd1Jldmlld2VyQWNjdXJhY3koKTogYm9vbGVhbiB7XHJcbiAgcmV0dXJuIHRoaXMuaXNUYW5nbyB8fCB0aGlzLnBlcm1pc3Npb25UeXBlID09PSAncmV2aWV3JztcclxufVxyXG5cclxuZ2V0IHNob3dSZXZpZXdlZEJ5KCk6IGJvb2xlYW4ge1xyXG4gIHJldHVybiAgdGhpcy5wZXJtaXNzaW9uVHlwZSA9PT0gJ3Jldmlldyc7XHJcbn1cclxuXHJcbi8vIEFwcHJvdmVyIGFjY3VyYWN5IGFuZCBcIkFwcHJvdmVkIGJ5XCIgdmlzaWJsZSBmb3IgdGFuZ28gKyBhcHByb3ZlclxyXG5nZXQgc2hvd0FwcHJvdmVyQWNjdXJhY3koKTogYm9vbGVhbiB7XHJcbiAgcmV0dXJuIHRoaXMuaXNUYW5nbyB8fCB0aGlzLnBlcm1pc3Npb25UeXBlID09PSAnYXBwcm92ZSc7XHJcbn1cclxuXHJcbmdldCBzaG93QXBwcm92ZWRCeSgpOiBib29sZWFuIHtcclxuICByZXR1cm4gIHRoaXMucGVybWlzc2lvblR5cGUgPT09ICdhcHByb3ZlJztcclxufVxyXG5cclxuLy8gVGFuZ28gYWNjdXJhY3kgb25seSBmb3IgdGFuZ28gdXNlcnNcclxuZ2V0IHNob3dUYW5nb0FjY3VyYWN5KCk6IGJvb2xlYW4ge1xyXG4gIHJldHVybiB0aGlzLmlzVGFuZ287XHJcbn1cclxuc3RhdHVzRHJvcGRvd25PcGVuID0gZmFsc2U7XHJcbmlzU3RhdHVzU2VsZWN0ZWQoc3RhdHVzOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICBjb25zdCBzZWxlY3RlZDogc3RyaW5nW10gPSB0aGlzLmZpbHRlckZvcm0udmFsdWUuc3RhdHVzIHx8IFtdO1xyXG4gIHJldHVybiBzZWxlY3RlZC5pbmNsdWRlcyhzdGF0dXMpO1xyXG59XHJcblxyXG5vblN0YXR1c0NoYW5nZShldmVudDogRXZlbnQsIHN0YXR1czogc3RyaW5nKSB7XHJcbiAgY29uc3QgY2hlY2tib3ggPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcclxuICBjb25zdCBzZWxlY3RlZDogc3RyaW5nW10gPSB0aGlzLmZpbHRlckZvcm0udmFsdWUuc3RhdHVzIHx8IFtdO1xyXG4gIGxldCBuZXh0OiBzdHJpbmdbXTtcclxuXHJcbiAgaWYgKGNoZWNrYm94LmNoZWNrZWQpIHtcclxuICAgIG5leHQgPSBzZWxlY3RlZC5pbmNsdWRlcyhzdGF0dXMpID8gc2VsZWN0ZWQgOiBbLi4uc2VsZWN0ZWQsIHN0YXR1c107XHJcbiAgfSBlbHNlIHtcclxuICAgIG5leHQgPSBzZWxlY3RlZC5maWx0ZXIocyA9PiBzICE9PSBzdGF0dXMpO1xyXG4gIH1cclxuXHJcbiAgdGhpcy5maWx0ZXJGb3JtLnBhdGNoVmFsdWUoeyBzdGF0dXM6IG5leHQgfSk7XHJcbn1cclxuXHJcbnRvZ2dsZVN0YXR1c0Ryb3Bkb3duKGV2ZW50PzogTW91c2VFdmVudCkge1xyXG4gIGlmIChldmVudCkge1xyXG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7IC8vIGF2b2lkIGRvY3VtZW50IGNsaWNrIGNsb3NpbmcgaXRcclxuICB9XHJcbiAgdGhpcy5zdGF0dXNEcm9wZG93bk9wZW4gPSAhdGhpcy5zdGF0dXNEcm9wZG93bk9wZW47XHJcbn1cclxuXHJcbi8vIEFyZSBhbGwgc3RhdHVzZXMgY3VycmVudGx5IHNlbGVjdGVkP1xyXG5hcmVBbGxTdGF0dXNlc1NlbGVjdGVkKCk6IGJvb2xlYW4ge1xyXG4gIGNvbnN0IHNlbGVjdGVkOiBzdHJpbmdbXSA9IHRoaXMuZmlsdGVyRm9ybS52YWx1ZS5zdGF0dXMgfHwgW107XHJcbiAgcmV0dXJuIHNlbGVjdGVkLmxlbmd0aCA+IDAgJiYgc2VsZWN0ZWQubGVuZ3RoID09PSB0aGlzLnN0YXR1c09wdGlvbnMubGVuZ3RoO1xyXG59XHJcblxyXG4vLyBIYW5kbGUgXCJTZWxlY3QgQWxsXCIgY2hlY2tib3ggY2hhbmdlXHJcbm9uU3RhdHVzU2VsZWN0QWxsQ2hhbmdlKGV2ZW50OiBFdmVudCkge1xyXG4gIGNvbnN0IGNoZWNrYm94ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XHJcblxyXG4gIGlmIChjaGVja2JveC5jaGVja2VkKSB7XHJcbiAgICAvLyBTZWxlY3QgZXZlcnkgc3RhdHVzXHJcbiAgICB0aGlzLmZpbHRlckZvcm0ucGF0Y2hWYWx1ZSh7IHN0YXR1czogWy4uLnRoaXMuc3RhdHVzT3B0aW9uc10gfSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIC8vIENsZWFyIGFsbFxyXG4gICAgdGhpcy5maWx0ZXJGb3JtLnBhdGNoVmFsdWUoeyBzdGF0dXM6IFtdIH0pO1xyXG4gIH1cclxufVxyXG5nZXQgc2VsZWN0ZWRTdGF0dXNlcygpOiBzdHJpbmdbXSB7XHJcbiAgcmV0dXJuIHRoaXMuZmlsdGVyRm9ybS52YWx1ZS5zdGF0dXMgfHwgW107XHJcbn1cclxuXHJcbiAgaXNCZXR3ZWVuKGNvbnRyb2xOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgIHJldHVybiB0aGlzLmZpbHRlckZvcm0uZ2V0KGNvbnRyb2xOYW1lKT8udmFsdWUgPT09ICdiZXR3ZWVuJztcclxuICB9XHJcbm5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcclxuICBpZiAoY2hhbmdlc1snY2xpZW50J10gfHwgY2hhbmdlc1sncGVybWlzc2lvblR5cGUnXSB8fCBjaGFuZ2VzWyd1c2VyVHlwZSddKSB7XHJcbiAgICB0aGlzLmxvYWRSZXZpZXdlckxpc3QoKTtcclxuICB9XHJcbn1cclxuLy8gZnVsbCB1c2VyIGxpc3QgeW91IGFscmVhZHkgaGF2ZVxyXG51c2VyTGlzdDogYW55W10gPSBbXTtcclxuXHJcblxyXG5yZXZpZXdlclNlYXJjaFRlcm06IHN0cmluZyA9ICcnO1xyXG5cclxuLy8g4pyFIHNpbXBsZSBjb21wdXRlZCBsaXN0IGZvciAqbmdGb3JcclxuZ2V0IGZpbHRlcmVkUmV2aWV3ZXJMaXN0KCk6IHsgZW1haWw6IHN0cmluZzsgbmFtZT86IHN0cmluZyB9W10ge1xyXG4gIGNvbnN0IHRlcm0gPSAodGhpcy5yZXZpZXdlclNlYXJjaFRlcm0gfHwgJycpLnRyaW0oKS50b0xvd2VyQ2FzZSgpO1xyXG5cclxuICBpZiAoIXRlcm0pIHtcclxuICAgIHJldHVybiB0aGlzLnVzZXJMaXN0O1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHRoaXMudXNlckxpc3QuZmlsdGVyKHUgPT4ge1xyXG4gICAgY29uc3QgZW1haWwgPSAodS5lbWFpbCB8fCAnJykudG9Mb3dlckNhc2UoKTtcclxuICAgIGNvbnN0IG5hbWUgPSAodS5uYW1lIHx8ICcnKS50b0xvd2VyQ2FzZSgpO1xyXG4gICAgcmV0dXJuIGVtYWlsLmluY2x1ZGVzKHRlcm0pIHx8IG5hbWUuaW5jbHVkZXModGVybSk7XHJcbiAgfSk7XHJcbn1cclxuYXBwcm92ZXJTZWFyY2hUZXJtOmFueTtcclxuZ2V0IGZpbHRlcmVkQXBwcm92ZXJMaXN0KCk6IGFueVtdIHtcclxuICBjb25zdCB0ZXJtID0gKHRoaXMuYXBwcm92ZXJTZWFyY2hUZXJtIHx8ICcnKS50cmltKCkudG9Mb3dlckNhc2UoKTtcclxuICBpZiAoIXRlcm0pIHtcclxuICAgIHJldHVybiB0aGlzLnVzZXJMaXN0O1xyXG4gIH1cclxuXHJcbiAgcmV0dXJuIHRoaXMudXNlckxpc3QuZmlsdGVyKCh1OiBhbnkpID0+IHtcclxuICAgIGNvbnN0IGVtYWlsID0gKHUuZW1haWwgfHwgJycpLnRvTG93ZXJDYXNlKCk7XHJcbiAgICBjb25zdCBuYW1lID0gKHUubmFtZSB8fCAnJykudG9Mb3dlckNhc2UoKTtcclxuICAgIHJldHVybiBlbWFpbC5pbmNsdWRlcyh0ZXJtKSB8fCBuYW1lLmluY2x1ZGVzKHRlcm0pO1xyXG4gIH0pO1xyXG59XHJcblxyXG5vbkFwcHJvdmVyU2VhcmNoKHZhbHVlOiBzdHJpbmcpIHtcclxuICB0aGlzLmFwcHJvdmVyU2VhcmNoVGVybSA9IHZhbHVlO1xyXG59XHJcbnByaXZhdGUgbG9hZFJldmlld2VyTGlzdCgpOiB2b2lkIHtcclxuICBpZiAoIXRoaXMuY2xpZW50KSB7XHJcbiAgICB0aGlzLnVzZXJMaXN0ID0gW107XHJcbiAgICByZXR1cm47XHJcbiAgfVxyXG5cclxuICBsZXQgdHlwZTogc3RyaW5nO1xyXG5cclxuICBpZiAodGhpcy51c2VyVHlwZSA9PT0gJ3RhbmdvJykge1xyXG4gICAgdHlwZSA9ICd0YW5nbyc7ICAgIC8vIG9yICdhbGwnXHJcbiAgfSBlbHNlIGlmICh0aGlzLnBlcm1pc3Npb25UeXBlID09PSAncmV2aWV3Jykge1xyXG4gICAgdHlwZSA9ICdyZXZpZXcnO1xyXG4gIH0gZWxzZSBpZiAodGhpcy5wZXJtaXNzaW9uVHlwZSA9PT0gJ2FwcHJvdmUnKSB7XHJcbiAgICB0eXBlID0gJ2FwcHJvdmUnO1xyXG4gIH0gZWxzZSB7XHJcbiAgICB0aGlzLnVzZXJMaXN0ID0gW107XHJcbiAgICByZXR1cm47XHJcbiAgfVxyXG5cclxuICB0aGlzLnNlcnZpY2UuZ2V0UmV2aWV3ZXJBcGkodGhpcy5jbGllbnQsIHR5cGUsJycpLnN1YnNjcmliZSh7XHJcbiAgICBuZXh0OiAocmVzOiBhbnkpID0+IHtcclxuICAgICAgaWYgKHJlcyAmJiByZXMuY29kZSA9PT0gMjAwKSB7XHJcbiAgICAgICAgdGhpcy51c2VyTGlzdCA9IHJlcy5kYXRhO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMudXNlckxpc3QgPSBbXTtcclxuICAgICAgfVxyXG4gICAgfSxcclxuICAgIGVycm9yOiAoKSA9PiB7XHJcbiAgICAgIHRoaXMudXNlckxpc3QgPSBbXTtcclxuICAgIH1cclxuICB9KTtcclxufVxyXG5cclxuLy8gb3BlbiBmbGFnc1xyXG5yZXZpZXdlckRyb3Bkb3duT3BlbiA9IGZhbHNlO1xyXG5hcHByb3ZlckRyb3Bkb3duT3BlbiA9IGZhbHNlO1xyXG5cclxuLy8gY29udmVuaWVuY2UgZ2V0dGVyc1xyXG5nZXQgc2VsZWN0ZWRSZXZpZXdlZEJ5KCk6IHN0cmluZ1tdIHtcclxuICByZXR1cm4gdGhpcy5maWx0ZXJGb3JtLnZhbHVlLnJldmlld2VkQnkgfHwgW107XHJcbn1cclxuXHJcbmdldCBzZWxlY3RlZEFwcHJvdmVkQnkoKTogc3RyaW5nW10ge1xyXG4gIHJldHVybiB0aGlzLmZpbHRlckZvcm0udmFsdWUuYXBwcm92ZWRCeSB8fCBbXTtcclxufVxyXG5cclxuLy8gLS0tIFJldmlld2VkIEJ5IGhlbHBlcnMgLS0tXHJcblxyXG50b2dnbGVSZXZpZXdlckRyb3Bkb3duKGV2ZW50PzogTW91c2VFdmVudCkge1xyXG4gIGlmIChldmVudCkgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgdGhpcy5yZXZpZXdlckRyb3Bkb3duT3BlbiA9ICF0aGlzLnJldmlld2VyRHJvcGRvd25PcGVuO1xyXG59XHJcblxyXG5pc1Jldmlld2VyU2VsZWN0ZWQoZW1haWw6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gIHJldHVybiB0aGlzLnNlbGVjdGVkUmV2aWV3ZWRCeS5pbmNsdWRlcyhlbWFpbCk7XHJcbn1cclxuXHJcbm9uUmV2aWV3ZXJDaGFuZ2UoZXZlbnQ6IEV2ZW50LCBlbWFpbDogc3RyaW5nKSB7XHJcbiAgY29uc3QgY2hlY2tib3ggPSBldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudDtcclxuICBjb25zdCBzZWxlY3RlZCA9IFsuLi50aGlzLnNlbGVjdGVkUmV2aWV3ZWRCeV07XHJcblxyXG4gIGlmIChjaGVja2JveC5jaGVja2VkKSB7XHJcbiAgICBpZiAoIXNlbGVjdGVkLmluY2x1ZGVzKGVtYWlsKSkgc2VsZWN0ZWQucHVzaChlbWFpbCk7XHJcbiAgfSBlbHNlIHtcclxuICAgIGNvbnN0IGkgPSBzZWxlY3RlZC5pbmRleE9mKGVtYWlsKTtcclxuICAgIGlmIChpID49IDApIHNlbGVjdGVkLnNwbGljZShpLCAxKTtcclxuICB9XHJcblxyXG4gIHRoaXMuZmlsdGVyRm9ybS5wYXRjaFZhbHVlKHsgcmV2aWV3ZWRCeTogc2VsZWN0ZWQgfSk7XHJcbn1cclxuXHJcbmFyZUFsbFJldmlld2Vyc1NlbGVjdGVkKCk6IGJvb2xlYW4ge1xyXG4gIHJldHVybiAoXHJcbiAgICB0aGlzLnVzZXJMaXN0Lmxlbmd0aCA+IDAgJiZcclxuICAgIHRoaXMuc2VsZWN0ZWRSZXZpZXdlZEJ5Lmxlbmd0aCA9PT0gdGhpcy51c2VyTGlzdC5sZW5ndGhcclxuICApO1xyXG59XHJcblxyXG5vblJldmlld2VyU2VsZWN0QWxsKGV2ZW50OiBFdmVudCkge1xyXG4gIGNvbnN0IGNoZWNrYm94ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XHJcblxyXG4gIGlmIChjaGVja2JveC5jaGVja2VkKSB7XHJcbiAgICB0aGlzLmZpbHRlckZvcm0ucGF0Y2hWYWx1ZSh7XHJcbiAgICAgIHJldmlld2VkQnk6IHRoaXMudXNlckxpc3QubWFwKCh1OmFueSkgPT4gdS5lbWFpbCksXHJcbiAgICB9KTtcclxuICB9IGVsc2Uge1xyXG4gICAgdGhpcy5maWx0ZXJGb3JtLnBhdGNoVmFsdWUoeyByZXZpZXdlZEJ5OiBbXSB9KTtcclxuICB9XHJcbn1cclxuXHJcbi8vIC0tLSBBcHByb3ZlZCBCeSBoZWxwZXJzIC0tLVxyXG5cclxudG9nZ2xlQXBwcm92ZXJEcm9wZG93bihldmVudD86IE1vdXNlRXZlbnQpIHtcclxuICBpZiAoZXZlbnQpIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gIHRoaXMuYXBwcm92ZXJEcm9wZG93bk9wZW4gPSAhdGhpcy5hcHByb3ZlckRyb3Bkb3duT3BlbjtcclxufVxyXG5cclxuaXNBcHByb3ZlclNlbGVjdGVkKGVtYWlsOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICByZXR1cm4gdGhpcy5zZWxlY3RlZEFwcHJvdmVkQnkuaW5jbHVkZXMoZW1haWwpO1xyXG59XHJcblxyXG5vbkFwcHJvdmVyQ2hhbmdlKGV2ZW50OiBFdmVudCwgZW1haWw6IHN0cmluZykge1xyXG4gIGNvbnN0IGNoZWNrYm94ID0gZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQ7XHJcbiAgY29uc3Qgc2VsZWN0ZWQgPSBbLi4udGhpcy5zZWxlY3RlZEFwcHJvdmVkQnldO1xyXG5cclxuICBpZiAoY2hlY2tib3guY2hlY2tlZCkge1xyXG4gICAgaWYgKCFzZWxlY3RlZC5pbmNsdWRlcyhlbWFpbCkpIHNlbGVjdGVkLnB1c2goZW1haWwpO1xyXG4gIH0gZWxzZSB7XHJcbiAgICBjb25zdCBpID0gc2VsZWN0ZWQuaW5kZXhPZihlbWFpbCk7XHJcbiAgICBpZiAoaSA+PSAwKSBzZWxlY3RlZC5zcGxpY2UoaSwgMSk7XHJcbiAgfVxyXG5cclxuICB0aGlzLmZpbHRlckZvcm0ucGF0Y2hWYWx1ZSh7IGFwcHJvdmVkQnk6IHNlbGVjdGVkIH0pO1xyXG59XHJcblxyXG5hcmVBbGxBcHByb3ZlcnNTZWxlY3RlZCgpOiBib29sZWFuIHtcclxuICByZXR1cm4gKFxyXG4gICAgdGhpcy51c2VyTGlzdC5sZW5ndGggPiAwICYmXHJcbiAgICB0aGlzLnNlbGVjdGVkQXBwcm92ZWRCeS5sZW5ndGggPT09IHRoaXMudXNlckxpc3QubGVuZ3RoXHJcbiAgKTtcclxufVxyXG5cclxub25BcHByb3ZlclNlbGVjdEFsbChldmVudDogRXZlbnQpIHtcclxuICBjb25zdCBjaGVja2JveCA9IGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50O1xyXG5cclxuICBpZiAoY2hlY2tib3guY2hlY2tlZCkge1xyXG4gICAgdGhpcy5maWx0ZXJGb3JtLnBhdGNoVmFsdWUoe1xyXG4gICAgICBhcHByb3ZlZEJ5OiB0aGlzLnVzZXJMaXN0Lm1hcCgodTphbnkpID0+IHUuZW1haWwpLFxyXG4gICAgfSk7XHJcbiAgfSBlbHNlIHtcclxuICAgIHRoaXMuZmlsdGVyRm9ybS5wYXRjaFZhbHVlKHsgYXBwcm92ZWRCeTogW10gfSk7XHJcbiAgfVxyXG59XHJcblxyXG5vblJlc2V0KCk6IHZvaWQge1xyXG4gIHRoaXMuZmlsdGVyRm9ybS5yZXNldCh7XHJcbiAgICBzdGF0dXM6IFtdLFxyXG4gICAgcmV2aWV3ZXJDb25kaXRpb246IG51bGwsXHJcbiAgICByZXZpZXdlckZyb206IG51bGwsXHJcbiAgICByZXZpZXdlclRvOiBudWxsLFxyXG5cclxuICAgIGFwcHJvdmVyQ29uZGl0aW9uOiBudWxsLFxyXG4gICAgYXBwcm92ZXJGcm9tOiBudWxsLFxyXG4gICAgYXBwcm92ZXJUbzogbnVsbCxcclxuXHJcbiAgICB0YW5nb0NvbmRpdGlvbjogbnVsbCxcclxuICAgIHRhbmdvRnJvbTogbnVsbCxcclxuICAgIHRhbmdvVG86IG51bGwsXHJcblxyXG4gICAgcmV2aWV3ZWRCeTogW10sXHJcbiAgICBhcHByb3ZlZEJ5OiBbXVxyXG4gIH0pO1xyXG5cclxuICAvLyAy77iP4oOjIFJlc2V0IHNlYXJjaCB0ZXJtc1xyXG4gIHRoaXMucmV2aWV3ZXJTZWFyY2hUZXJtID0gJyc7XHJcbiAgdGhpcy5hcHByb3ZlclNlYXJjaFRlcm0gPSAnJztcclxuXHJcbiAgLy8gM++4j+KDoyBCdWlsZCBlbXB0eSBwYXlsb2FkIHRvIHNlbmQgYmFja1xyXG4gIGNvbnN0IHBheWxvYWQgPSB7XHJcbiAgICBmaWx0ZXJCeVN0YXR1czogW10sXHJcbiAgICBmaWx0ZXJCeVJldmlld2VyOiBudWxsLFxyXG4gICAgZmlsdGVyQnlBcHByb3ZlcjogbnVsbCxcclxuICAgIGZpbHRlckJ5VGFuZ286IG51bGwsXHJcbiAgICBmaWx0ZXJCeVJldmlld2VkQnk6IFtdLFxyXG4gICAgZmlsZXRlckJ5QXBwcm92ZWRCeTogW11cclxuICB9O1xyXG5cclxuICAvLyA077iP4oOjIEVtaXQgdGhlIG5vdy1lbXB0eSBmaWx0ZXIgcmVzdWx0XHJcbiAgdGhpcy5hcHBseS5lbWl0KHBheWxvYWQpO1xyXG5cclxuICAvLyA177iP4oOjIENsb3NlIHRoZSBmaWx0ZXIgcGFuZWxcclxuICB0aGlzLmNsb3NlKCk7XHJcbn1cclxuXHJcbnByaXZhdGUgbWFwQWNjdXJhY3koXHJcbiAgY29uZGl0aW9uOiBDb25kaXRpb24gfCBudWxsLFxyXG4gIGZyb206IG51bWJlciB8IG51bGwsXHJcbiAgdG86IG51bWJlciB8IG51bGxcclxuKTogc3RyaW5nIHwgbnVsbCB7XHJcblxyXG4gIC8vIG5vdGhpbmcgc2VsZWN0ZWRcclxuICBpZiAoIWNvbmRpdGlvbiB8fCBmcm9tID09IG51bGwpIHJldHVybiBudWxsO1xyXG5cclxuICAvLyBcImJldHdlZW5cIiDihpIgXCI5MCB0byAxMDBcIlxyXG4gIGlmIChjb25kaXRpb24gPT09ICdiZXR3ZWVuJykge1xyXG4gICAgaWYgKHRvID09IG51bGwpIHJldHVybiBudWxsO1xyXG4gICAgcmV0dXJuIGAke2Zyb219IHRvICR7dG99YDtcclxuICB9XHJcblxyXG4gIC8vIG90aGVyIGNvbmRpdGlvbnMgKGd0LCBsdCwgZ3RlLCBsdGUpXHJcbiAgY29uc3Qgb3BNYXA6IFJlY29yZDxDb25kaXRpb24sIHN0cmluZz4gPSB7XHJcbiAgICBndDogJz4nLFxyXG4gICAgbHQ6ICc8JyxcclxuICAgIGd0ZTogJz49JyxcclxuICAgIGx0ZTogJzw9JyxcclxuICAgIGJldHdlZW46ICcnLCAvLyBhbHJlYWR5IGhhbmRsZWQgYWJvdmVcclxuICB9O1xyXG5cclxuICByZXR1cm4gYCR7b3BNYXBbY29uZGl0aW9uXX0gJHtmcm9tfWA7ICAvLyBlLmcuIFwiPj0gOTBcIlxyXG59XHJcblxyXG4gIG9uQXBwbHkoKTogdm9pZCB7XHJcblxyXG4gICBjb25zdCByYXcgPSB0aGlzLmZpbHRlckZvcm0udmFsdWU7XHJcblxyXG4gIGNvbnN0IHJldmlld2VyU3RyID0gdGhpcy5tYXBBY2N1cmFjeShyYXcucmV2aWV3ZXJDb25kaXRpb24sIHJhdy5yZXZpZXdlckZyb20sIHJhdy5yZXZpZXdlclRvKTtcclxuICBjb25zdCBhcHByb3ZlclN0ciA9IHRoaXMubWFwQWNjdXJhY3kocmF3LmFwcHJvdmVyQ29uZGl0aW9uLCByYXcuYXBwcm92ZXJGcm9tLCByYXcuYXBwcm92ZXJUbyk7XHJcbiAgY29uc3QgdGFuZ29TdHIgICAgPSB0aGlzLm1hcEFjY3VyYWN5KHJhdy50YW5nb0NvbmRpdGlvbiwgcmF3LnRhbmdvRnJvbSwgcmF3LnRhbmdvVG8pO1xyXG5cclxuICBjb25zdCBwYXlsb2FkID0ge1xyXG4gICAgZmlsdGVyQnlTdGF0dXM6IHJhdy5zdGF0dXMgfHwgW10sXHJcblxyXG4gICAgZmlsdGVyQnlSZXZpZXdlcjogcmV2aWV3ZXJTdHIsXHJcbiAgICBmaWx0ZXJCeUFwcHJvdmVyOiBhcHByb3ZlclN0cixcclxuICAgIGZpbHRlckJ5VGFuZ286IHRhbmdvU3RyLFxyXG5cclxuICAgIGZpbHRlckJ5UmV2aWV3ZWRCeTogcmF3LnJldmlld2VkQnkgfHwgW10sICAgICAgICBcclxuICAgIGZpbGV0ZXJCeUFwcHJvdmVkQnk6IHJhdy5hcHByb3ZlZEJ5IHx8IFtdLCAgICAgICAgXHJcbiAgfTtcclxuICB0aGlzLmFwcGx5LmVtaXQocGF5bG9hZCk7XHJcbiAgdGhpcy5jbG9zZSgpO1xyXG4gICAgdGhpcy5zaG93UGFuZWwgPSBmYWxzZTtcclxuICB9XHJcblxyXG5kcm9wZG93blN0YXRlID0ge1xyXG4gIHN0YXR1czogZmFsc2UsXHJcbiAgcmV2aWV3ZXI6IGZhbHNlLFxyXG4gIGFwcHJvdmVyOiBmYWxzZVxyXG59O1xyXG4vLyBASG9zdExpc3RlbmVyKCdkb2N1bWVudDpjbGljaycpXHJcbmNsb3NlQWxsKCkge1xyXG4gIHRoaXMuZHJvcGRvd25TdGF0ZS5zdGF0dXMgPSBmYWxzZTtcclxuICB0aGlzLmRyb3Bkb3duU3RhdGUucmV2aWV3ZXIgPSBmYWxzZTtcclxuICB0aGlzLmRyb3Bkb3duU3RhdGUuYXBwcm92ZXIgPSBmYWxzZTtcclxufVxyXG5cclxudG9nZ2xlRHJvcGRvd24odHlwZTogJ3N0YXR1cycgfCAncmV2aWV3ZXInIHwgJ2FwcHJvdmVyJywgZXZlbnQ6IE1vdXNlRXZlbnQpIHtcclxuICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcclxuXHJcbiAgLy8gQ2xvc2UgYWxsIGJlZm9yZSBvcGVuaW5nIGEgbmV3IG9uZVxyXG4gIHRoaXMuY2xvc2VBbGwoKTtcclxuXHJcbiAgLy8gVG9nZ2xlIG9ubHkgdGhlIHNlbGVjdGVkIG9uZVxyXG4gIHRoaXMuZHJvcGRvd25TdGF0ZVt0eXBlXSA9ICF0aGlzLmRyb3Bkb3duU3RhdGVbdHlwZV07XHJcbn1cclxuXHJcbmlzRHJvcGRvd25PcGVuKHR5cGU6ICdzdGF0dXMnIHwgJ3Jldmlld2VyJyB8ICdhcHByb3ZlcicpIHtcclxuICByZXR1cm4gdGhpcy5kcm9wZG93blN0YXRlW3R5cGVdO1xyXG59XHJcbn1cclxuIiwiPCEtLSB0aWNrZXQtZmlsdGVyLXBhbmVsLmNvbXBvbmVudC5odG1sIC0tPlxyXG48ZGl2IGNsYXNzPVwiZmlsdGVyLXdyYXBwZXJcIiAqbmdJZj1cImlzT3BlblwiPlxyXG4gIDxkaXYgY2xhc3M9XCJmaWx0ZXItY2FyZFwiPlxyXG4gICAgPGRpdiBjbGFzcz1cImZpbHRlci1oZWFkZXIgZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIGFsaWduLWl0ZW1zLWNlbnRlciBtYi0zXCI+XHJcbiAgPGRpdiBjbGFzcz1cInRpdGxlXCI+RmlsdGVyIE9wdGlvbnM8L2Rpdj5cclxuICAgICAgPCEtLSA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0bi1jbG9zZVwiIChjbGljayk9XCJjbG9zZSgpXCI+4pyVPC9idXR0b24+IC0tPlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPGZvcm0gW2Zvcm1Hcm91cF09XCJmaWx0ZXJGb3JtXCI+XHJcbiAgICAgIDwhLS0gU3RhdHVzIC0tPlxyXG48ZGl2IGNsYXNzPVwibWItMyBwb3NpdGlvbi1yZWxhdGl2ZVwiIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIj5cclxuICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsXCI+U3RhdHVzPC9sYWJlbD5cclxuXHJcbiAgPCEtLSBIZWFkZXIgLyB0cmlnZ2VyIC0tPlxyXG4gIDxkaXZcclxuICAgIGNsYXNzPVwic3RhdHVzLXNlbGVjdCBib3JkZXIgcm91bmRlZCBweC0zIHB5LTIgZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIGFsaWduLWl0ZW1zLWNlbnRlclwiXHJcbiAgICAoY2xpY2spPVwidG9nZ2xlRHJvcGRvd24oJ3N0YXR1cycsICRldmVudClcIlxyXG4gID5cclxuICAgIDxzcGFuICpuZ0lmPVwiIXNlbGVjdGVkU3RhdHVzZXMubGVuZ3RoXCI+U2VsZWN0PC9zcGFuPlxyXG5cclxuICAgIDxzcGFuICpuZ0lmPVwic2VsZWN0ZWRTdGF0dXNlcy5sZW5ndGggPT09IDFcIj5cclxuICAgICAge3sgc2VsZWN0ZWRTdGF0dXNlc1swXSB9fVxyXG4gICAgPC9zcGFuPlxyXG5cclxuICAgIDxzcGFuICpuZ0lmPVwic2VsZWN0ZWRTdGF0dXNlcy5sZW5ndGggPiAxXCIgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyXCI+XHJcbiAgICAgIDxzcGFuPnt7IHNlbGVjdGVkU3RhdHVzZXNbMF0gfX08L3NwYW4+XHJcbiAgICAgIDxzcGFuIGNsYXNzPVwiYmFkZ2UgbXMtMlwiPlxyXG4gICAgICAgICt7eyBzZWxlY3RlZFN0YXR1c2VzLmxlbmd0aCAtIDEgfX1cclxuICAgICAgPC9zcGFuPlxyXG4gICAgPC9zcGFuPlxyXG5cclxuICA8L2Rpdj5cclxuXHJcbiAgPCEtLSBEUk9QRE9XTiBQQU5FTCAoT1ZFUkxBWSkgLS0+XHJcbiAgPGRpdlxyXG4gICAgY2xhc3M9XCJzdGF0dXMtZHJvcGRvd24gcG9zaXRpb24tYWJzb2x1dGUgdy0xMDAgbXQtMSBib3JkZXIgcm91bmRlZCBwLTEgYmctd2hpdGVcIlxyXG4gICAgc3R5bGU9XCJ6LWluZGV4OiAxMDAwOyBtYXgtaGVpZ2h0OiAyMjBweDsgb3ZlcmZsb3cteTogYXV0bztcIlxyXG4gICAqbmdJZj1cImlzRHJvcGRvd25PcGVuKCdzdGF0dXMnKVwiXHJcbiAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcclxuICA+XHJcbiAgICA8IS0tIFNlbGVjdCBBbGwgLS0+XHJcbiAgICA8ZGl2IGNsYXNzPVwiZm9ybS1jaGVjayBweC0wIGQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXIgbWItMlwiPlxyXG4gICAgICA8aW5wdXRcclxuICAgICAgICB0eXBlPVwiY2hlY2tib3hcIlxyXG4gICAgICAgIGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dCBcIlxyXG4gICAgICAgIGlkPVwic3RhdHVzLXNlbGVjdC1hbGxcIlxyXG4gICAgICAgIFtjaGVja2VkXT1cImFyZUFsbFN0YXR1c2VzU2VsZWN0ZWQoKVwiXHJcbiAgICAgICAgKGNoYW5nZSk9XCJvblN0YXR1c1NlbGVjdEFsbENoYW5nZSgkZXZlbnQpXCJcclxuICAgICAgLz5cclxuICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbCB0ZXh0LWRhcmsgbXMtMlwiIGZvcj1cInN0YXR1cy1zZWxlY3QtYWxsXCI+XHJcbiAgICAgICAgU2VsZWN0IEFsbFxyXG4gICAgICA8L2xhYmVsPlxyXG4gICAgPC9kaXY+XHJcblxyXG5cclxuICAgIDwhLS0gT3B0aW9ucyAtLT5cclxuICAgIDxkaXZcclxuICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrIHB4LTAgZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlciBtYi0xXCJcclxuICAgICAgKm5nRm9yPVwibGV0IHMgb2Ygc3RhdHVzT3B0aW9uc1wiXHJcbiAgICA+XHJcbiAgICAgIDxpbnB1dFxyXG4gICAgICAgIHR5cGU9XCJjaGVja2JveFwiXHJcbiAgICAgICAgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0IFwiXHJcbiAgICAgICAgW2lkXT1cIidzdGF0dXMtJyArIHNcIlxyXG4gICAgICAgIFtjaGVja2VkXT1cImlzU3RhdHVzU2VsZWN0ZWQocylcIlxyXG4gICAgICAgIChjaGFuZ2UpPVwib25TdGF0dXNDaGFuZ2UoJGV2ZW50LCBzKVwiXHJcbiAgICAgIC8+XHJcbiAgICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWwgdGV4dC1kYXJrIG1zLTJcIiBbZm9yXT1cIidzdGF0dXMtJyArIHNcIj5cclxuICAgICAgICB7eyBzIH19XHJcbiAgICAgIDwvbGFiZWw+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcblxyXG5cclxuXHJcbiAgICAgIDwhLS0gUmV2aWV3ZXIgYWNjdXJhY3kgLS0+XHJcbiAgICAgIDxkaXYgY2xhc3M9XCJtYi0zXCIgKm5nSWY9XCJzaG93UmV2aWV3ZXJBY2N1cmFjeVwiIChjbGljayk9XCJjbG9zZUFsbCgpXCI+XHJcbiAgICAgICAgPGxhYmVsIGNsYXNzPVwiZm9ybS1sYWJlbFwiPlJldmlld2VyIGFjY3VyYWN5ICglKSBieSBjb25kaXRpb248L2xhYmVsPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXggZ2FwLTJcIj5cclxuICAgICAgICAgIDxzZWxlY3QgY2xhc3M9XCJmb3JtLXNlbGVjdCB3LTEwMFwiIGZvcm1Db250cm9sTmFtZT1cInJldmlld2VyQ29uZGl0aW9uXCI+XHJcbiAgICAgICAgICAgIDxvcHRpb24gW25nVmFsdWVdPVwibnVsbFwiPlNlbGVjdDwvb3B0aW9uPlxyXG4gICAgICAgICAgICA8b3B0aW9uICpuZ0Zvcj1cImxldCBjIG9mIGNvbmRpdGlvbk9wdGlvbnNcIiBbbmdWYWx1ZV09XCJjLnZhbHVlXCI+XHJcbiAgICAgICAgICAgICAge3sgYy5sYWJlbCB9fVxyXG4gICAgICAgICAgICA8L29wdGlvbj5cclxuICAgICAgICAgIDwvc2VsZWN0PlxyXG5cclxuICAgICAgICAgIDwhLS0gb25lIG9yIHR3byBpbnB1dHMgLS0+XHJcbiAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiaXNCZXR3ZWVuKCdyZXZpZXdlckNvbmRpdGlvbicpOyBlbHNlIHNpbmdsZVJldmlld2VyXCI+XHJcbiAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxyXG4gICAgICAgICAgICAgIG1pbj1cIjFcIlxyXG4gICAgICAgICAgICAgIG1heD1cIjEwMFwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxyXG4gICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInJldmlld2VyRnJvbVwiXHJcbiAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJGcm9tXCIgKGlucHV0KT1cImxpbWl0VmFsdWUoJGV2ZW50LCAncmV2aWV3ZXJGcm9tJylcIiAvPlxyXG4gICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICBtaW49XCIxXCJcclxuICAgICAgICAgICAgICBtYXg9XCIxMDBcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcclxuICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJyZXZpZXdlclRvXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlRvXCIgKGlucHV0KT1cImxpbWl0VmFsdWUoJGV2ZW50LCAncmV2aWV3ZXJUbycpXCIgLz5cclxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNzaW5nbGVSZXZpZXdlcj5cclxuICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgbWluPVwiMVwiXHJcbiAgICAgICAgICAgICAgbWF4PVwiMTAwXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXHJcbiAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwicmV2aWV3ZXJGcm9tXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIjEgdG8gMTAwJVwiIChpbnB1dCk9XCJsaW1pdFZhbHVlKCRldmVudCwgJ3Jldmlld2VyRnJvbScpXCIgLz5cclxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPCEtLSBBcHByb3ZlciBhY2N1cmFjeSAtLT5cclxuICAgICAgPGRpdiBjbGFzcz1cIm1iLTNcIiAqbmdJZj1cInNob3dBcHByb3ZlckFjY3VyYWN5XCIgKGNsaWNrKT1cImNsb3NlQWxsKClcIj5cclxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsXCI+QXBwcm92ZXIgYWNjdXJhY3kgKCUpIGJ5IGNvbmRpdGlvbjwvbGFiZWw+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBnYXAtMlwiPlxyXG4gICAgICAgICAgPHNlbGVjdCBjbGFzcz1cImZvcm0tc2VsZWN0IHctMTAwXCIgZm9ybUNvbnRyb2xOYW1lPVwiYXBwcm92ZXJDb25kaXRpb25cIj5cclxuICAgICAgICAgICAgPG9wdGlvbiBbbmdWYWx1ZV09XCJudWxsXCI+U2VsZWN0PC9vcHRpb24+XHJcbiAgICAgICAgICAgIDxvcHRpb24gKm5nRm9yPVwibGV0IGMgb2YgY29uZGl0aW9uT3B0aW9uc1wiIFtuZ1ZhbHVlXT1cImMudmFsdWVcIj5cclxuICAgICAgICAgICAgICB7eyBjLmxhYmVsIH19XHJcbiAgICAgICAgICAgIDwvb3B0aW9uPlxyXG4gICAgICAgICAgPC9zZWxlY3Q+XHJcblxyXG4gICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImlzQmV0d2VlbignYXBwcm92ZXJDb25kaXRpb24nKTsgZWxzZSBzaW5nbGVBcHByb3ZlclwiPlxyXG4gICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICBtaW49XCIxXCJcclxuICAgICAgICAgICAgICBtYXg9XCIxMDBcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcclxuICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJhcHByb3ZlckZyb21cIlxyXG4gICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiRnJvbVwiIFxyXG4gICAgICAgICAgICAgIChpbnB1dCk9XCJsaW1pdFZhbHVlKCRldmVudCwgJ2FwcHJvdmVyRnJvbScpXCIvPlxyXG4gICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICBtaW49XCIxXCJcclxuICAgICAgICAgICAgICBtYXg9XCIxMDBcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcclxuICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJhcHByb3ZlclRvXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlRvXCIgKGlucHV0KT1cImxpbWl0VmFsdWUoJGV2ZW50LCAnYXBwcm92ZXJUbycpXCIgLz5cclxuICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNzaW5nbGVBcHByb3Zlcj5cclxuICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgbWluPVwiMVwiXHJcbiAgICAgICAgICAgICAgbWF4PVwiMTAwXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXHJcbiAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwiYXBwcm92ZXJGcm9tXCJcclxuICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIjEgdG8gMTAwJVwiIChpbnB1dCk9XCJsaW1pdFZhbHVlKCRldmVudCwgJ2FwcHJvdmVyRnJvbScpXCIgLz5cclxuICAgICAgICAgIDwvbmctdGVtcGxhdGU+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgPCEtLSBUYW5nbyBhY2N1cmFjeSAtLT5cclxuICAgICAgPGRpdiBjbGFzcz1cIm1iLTNcIiAqbmdJZj1cInNob3dUYW5nb0FjY3VyYWN5XCIgKGNsaWNrKT1cImNsb3NlQWxsKClcIj5cclxuICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsXCI+VGFuZ28gYWNjdXJhY3kgKCUpIGJ5IGNvbmRpdGlvbjwvbGFiZWw+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBnYXAtMlwiPlxyXG4gICAgICAgICAgPHNlbGVjdCBjbGFzcz1cImZvcm0tc2VsZWN0IHctMTAwXCIgZm9ybUNvbnRyb2xOYW1lPVwidGFuZ29Db25kaXRpb25cIj5cclxuICAgICAgICAgICAgPG9wdGlvbiBbbmdWYWx1ZV09XCJudWxsXCI+U2VsZWN0PC9vcHRpb24+XHJcbiAgICAgICAgICAgIDxvcHRpb24gKm5nRm9yPVwibGV0IGMgb2YgY29uZGl0aW9uT3B0aW9uc1wiIFtuZ1ZhbHVlXT1cImMudmFsdWVcIj5cclxuICAgICAgICAgICAgICB7eyBjLmxhYmVsIH19XHJcbiAgICAgICAgICAgIDwvb3B0aW9uPlxyXG4gICAgICAgICAgPC9zZWxlY3Q+XHJcblxyXG4gICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImlzQmV0d2VlbigndGFuZ29Db25kaXRpb24nKTsgZWxzZSBzaW5nbGVUYW5nb1wiPlxyXG4gICAgICAgICAgICA8aW5wdXRcclxuICAgICAgICAgICAgICB0eXBlPVwibnVtYmVyXCJcclxuICAgICAgICAgICAgICBtaW49XCIxXCJcclxuICAgICAgICAgICAgICBtYXg9XCIxMDBcIlxyXG4gICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sXCJcclxuICAgICAgICAgICAgICBmb3JtQ29udHJvbE5hbWU9XCJ0YW5nb0Zyb21cIlxyXG4gICAgICAgICAgICAgIHBsYWNlaG9sZGVyPVwiRnJvbVwiIChpbnB1dCk9XCJsaW1pdFZhbHVlKCRldmVudCwgJ3RhbmdvRnJvbScpXCIgLz5cclxuICAgICAgICAgICAgPGlucHV0XHJcbiAgICAgICAgICAgICAgdHlwZT1cIm51bWJlclwiXHJcbiAgICAgICAgICAgICAgbWluPVwiMVwiXHJcbiAgICAgICAgICAgICAgbWF4PVwiMTAwXCJcclxuICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY29udHJvbFwiXHJcbiAgICAgICAgICAgICAgZm9ybUNvbnRyb2xOYW1lPVwidGFuZ29Ub1wiXHJcbiAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJUb1wiIChpbnB1dCk9XCJsaW1pdFZhbHVlKCRldmVudCwgJ3RhbmdvVG8nKVwiIC8+XHJcbiAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgIDxuZy10ZW1wbGF0ZSAjc2luZ2xlVGFuZ28+XHJcbiAgICAgICAgICAgIDxpbnB1dFxyXG4gICAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxyXG4gICAgICAgICAgICAgIG1pbj1cIjFcIlxyXG4gICAgICAgICAgICAgIG1heD1cIjEwMFwiXHJcbiAgICAgICAgICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2xcIlxyXG4gICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cInRhbmdvRnJvbVwiXHJcbiAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCIxIHRvIDEwMCVcIiAoaW5wdXQpPVwibGltaXRWYWx1ZSgkZXZlbnQsICd0YW5nb0Zyb20nKVwiIC8+XHJcbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICA8L2Rpdj5cclxuPGRpdlxyXG4gIGNsYXNzPVwibWItMyBwb3NpdGlvbi1yZWxhdGl2ZVwiXHJcbiAgKm5nSWY9XCJzaG93UmV2aWV3ZWRCeVwiXHJcbiAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXHJcbj5cclxuICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsXCI+UmV2aWV3ZWQgYnk8L2xhYmVsPlxyXG5cclxuICA8IS0tIFRyaWdnZXIgLyBkaXNwbGF5IC0tPlxyXG4gIDxkaXZcclxuICAgIGNsYXNzPVwiYm9yZGVyIHJvdW5kZWQgcHgtMyBweS0yIGQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1jZW50ZXJcIlxyXG4gICAgKGNsaWNrKT1cInRvZ2dsZURyb3Bkb3duKCdyZXZpZXdlcicsICRldmVudClcIlxyXG4gID5cclxuICAgIDwhLS0gMCBzZWxlY3RlZCAtLT5cclxuICAgIDxzcGFuICpuZ0lmPVwiIXNlbGVjdGVkUmV2aWV3ZWRCeS5sZW5ndGhcIj5cclxuICAgICAgU2VsZWN0XHJcbiAgICA8L3NwYW4+XHJcblxyXG4gICAgPCEtLSAxIHNlbGVjdGVkIC0tPlxyXG4gICAgPHNwYW4gKm5nSWY9XCJzZWxlY3RlZFJldmlld2VkQnkubGVuZ3RoID09PSAxXCI+XHJcbiAgICAgIHt7IHNlbGVjdGVkUmV2aWV3ZWRCeVswXSB9fVxyXG4gICAgPC9zcGFuPlxyXG5cclxuICAgIDwhLS0gPjEgc2VsZWN0ZWQgLS0+XHJcbiAgICA8c3BhblxyXG4gICAgICAqbmdJZj1cInNlbGVjdGVkUmV2aWV3ZWRCeS5sZW5ndGggPiAxXCJcclxuICAgICAgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyXCJcclxuICAgID5cclxuICAgICAgPHNwYW4+e3sgc2VsZWN0ZWRSZXZpZXdlZEJ5WzBdIH19PC9zcGFuPlxyXG4gICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIG1zLTJcIj5cclxuICAgICAgICAre3sgc2VsZWN0ZWRSZXZpZXdlZEJ5Lmxlbmd0aCAtIDEgfX1cclxuICAgICAgPC9zcGFuPlxyXG4gICAgPC9zcGFuPlxyXG4gIDwvZGl2PlxyXG5cclxuPGRpdlxyXG4gICpuZ0lmPVwiaXNEcm9wZG93bk9wZW4oJ3Jldmlld2VyJylcIlxyXG4gIGNsYXNzPVwicG9zaXRpb24tYWJzb2x1dGUgdy0xMDAgYm9yZGVyIHJvdW5kZWQgYmctd2hpdGUgcC0xIG10LTFcIlxyXG4gIHN0eWxlPVwiei1pbmRleDogMTAwMDsgbWF4LWhlaWdodDogMjIwcHg7IG92ZXJmbG93LXk6IGF1dG87XCJcclxuICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcclxuPlxyXG5cclxuICA8IS0tIPCflI0gU2VhcmNoIGJveCAtLT5cclxuICA8IS0tIDxkaXYgY2xhc3M9XCJtYi0yIHB4LTBcIj5cclxuICAgIDxpbnB1dFxyXG4gICAgICB0eXBlPVwidGV4dFwiXHJcbiAgICAgIGNsYXNzPVwiZm9ybS1jb250cm9sIGZvcm0tY29udHJvbC1zbVwiXHJcbiAgICAgIHBsYWNlaG9sZGVyPVwiU2VhcmNoIGJ5IGVtYWlsXCJcclxuICAgICAgWyhuZ01vZGVsKV09XCJyZXZpZXdlclNlYXJjaFRlcm1cIlxyXG4gICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcclxuICAgIC8+XHJcbiAgPC9kaXY+IC0tPlxyXG5cclxuICA8IS0tIFNlbGVjdCBBbGwgLS0+XHJcbiAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2sgcHgtMCBtYi0yIGQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cclxuICAgIDxpbnB1dFxyXG4gICAgICB0eXBlPVwiY2hlY2tib3hcIlxyXG4gICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxyXG4gICAgICBpZD1cInJldmlld2VyLWFsbFwiXHJcbiAgICAgIFtjaGVja2VkXT1cImFyZUFsbFJldmlld2Vyc1NlbGVjdGVkKClcIlxyXG4gICAgICAoY2hhbmdlKT1cIm9uUmV2aWV3ZXJTZWxlY3RBbGwoJGV2ZW50KVwiXHJcbiAgICAvPlxyXG4gICAgPGxhYmVsIGZvcj1cInJldmlld2VyLWFsbFwiIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbCB0ZXh0LWRhcmsgbXMtMlwiPlxyXG4gICAgICBTZWxlY3QgQWxsXHJcbiAgICA8L2xhYmVsPlxyXG4gIDwvZGl2PlxyXG5cclxuICA8IS0tIE9wdGlvbnMg4oCTIG5vdyB1c2UgZ2V0dGVyIGZpbHRlcmVkUmV2aWV3ZXJMaXN0IC0tPlxyXG4gIDxkaXZcclxuICAgIGNsYXNzPVwiZm9ybS1jaGVjayBtYi0xIHB4LTAgZC1mbGV4IGFsaWduLWl0ZW1zLWNlbnRlclwiXHJcbiAgICAqbmdGb3I9XCJsZXQgdSBvZiBmaWx0ZXJlZFJldmlld2VyTGlzdFwiXHJcbiAgPlxyXG4gICAgPGlucHV0XHJcbiAgICAgIGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiXHJcbiAgICAgIHR5cGU9XCJjaGVja2JveFwiXHJcbiAgICAgIFtpZF09XCIncmV2LScgKyB1LmVtYWlsXCJcclxuICAgICAgW2NoZWNrZWRdPVwiaXNSZXZpZXdlclNlbGVjdGVkKHUuZW1haWwpXCJcclxuICAgICAgKGNoYW5nZSk9XCJvblJldmlld2VyQ2hhbmdlKCRldmVudCwgdS5lbWFpbClcIlxyXG4gICAgLz5cclxuICAgIDxsYWJlbCBjbGFzcz1cImZvcm0tY2hlY2stbGFiZWwgdGV4dC1kYXJrIG1zLTJcIiBbZm9yXT1cIidyZXYtJyArIHUuZW1haWxcIj5cclxuICAgICAge3sgdS5lbWFpbCB9fVxyXG4gICAgPC9sYWJlbD5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcblxyXG5cclxuPC9kaXY+XHJcblxyXG5cclxuICAgICAgPCEtLSBBcHByb3ZlZCBCeSAtLT5cclxuPGRpdlxyXG4gIGNsYXNzPVwibWItMyBwb3NpdGlvbi1yZWxhdGl2ZVwiXHJcbiAgKm5nSWY9XCJzaG93QXBwcm92ZWRCeVwiXHJcbiAgKGNsaWNrKT1cIiRldmVudC5zdG9wUHJvcGFnYXRpb24oKVwiXHJcbj5cclxuICA8bGFiZWwgY2xhc3M9XCJmb3JtLWxhYmVsXCI+QXBwcm92ZWQgYnk8L2xhYmVsPlxyXG5cclxuICA8IS0tIFRyaWdnZXIgLyBkaXNwbGF5IC0tPlxyXG4gIDxkaXZcclxuICAgIGNsYXNzPVwiYm9yZGVyIHJvdW5kZWQgcHgtMyBweS0yIGQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1jZW50ZXJcIlxyXG4gICAgKGNsaWNrKT1cInRvZ2dsZURyb3Bkb3duKCdhcHByb3ZlcicsICRldmVudClcIlxyXG4gID5cclxuICAgIDwhLS0gMCBzZWxlY3RlZCAtLT5cclxuICAgIDxzcGFuICpuZ0lmPVwiIXNlbGVjdGVkQXBwcm92ZWRCeS5sZW5ndGhcIj5cclxuICAgICAgU2VsZWN0XHJcbiAgICA8L3NwYW4+XHJcblxyXG4gICAgPCEtLSAxIHNlbGVjdGVkIC0tPlxyXG4gICAgPHNwYW4gKm5nSWY9XCJzZWxlY3RlZEFwcHJvdmVkQnkubGVuZ3RoID09PSAxXCI+XHJcbiAgICAgIHt7IHNlbGVjdGVkQXBwcm92ZWRCeVswXSB9fVxyXG4gICAgPC9zcGFuPlxyXG5cclxuICAgIDwhLS0gPjEgc2VsZWN0ZWQgLS0+XHJcbiAgICA8c3BhblxyXG4gICAgICAqbmdJZj1cInNlbGVjdGVkQXBwcm92ZWRCeS5sZW5ndGggPiAxXCJcclxuICAgICAgY2xhc3M9XCJkLWZsZXggYWxpZ24taXRlbXMtY2VudGVyXCJcclxuICAgID5cclxuICAgICAgPHNwYW4+e3sgc2VsZWN0ZWRBcHByb3ZlZEJ5WzBdIH19PC9zcGFuPlxyXG4gICAgICA8c3BhbiBjbGFzcz1cImJhZGdlIG1zLTJcIj5cclxuICAgICAgICAre3sgc2VsZWN0ZWRBcHByb3ZlZEJ5Lmxlbmd0aCAtIDEgfX1cclxuICAgICAgPC9zcGFuPlxyXG4gICAgPC9zcGFuPlxyXG5cclxuICA8L2Rpdj5cclxuPCEtLSBEcm9wZG93biBwYW5lbCAtLT5cclxuPGRpdlxyXG4gKm5nSWY9XCJpc0Ryb3Bkb3duT3BlbignYXBwcm92ZXInKVwiXHJcbiAgY2xhc3M9XCJwb3NpdGlvbi1hYnNvbHV0ZSB3LTEwMCBib3JkZXIgcm91bmRlZCBiZy13aGl0ZSBwLTEgbXQtMVwiXHJcbiAgc3R5bGU9XCJ6LWluZGV4OiAxMDAwOyBtYXgtaGVpZ2h0OiAyMjBweDsgb3ZlcmZsb3cteTogYXV0bztcIlxyXG4gIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxyXG4+XHJcblxyXG4gIDwhLS0g8J+UjSBTZWFyY2ggYm94IC0tPlxyXG4gIDwhLS0gPGRpdiBjbGFzcz1cIm1iLTIgcHgtMFwiPlxyXG4gICAgPGlucHV0XHJcbiAgICAgIHR5cGU9XCJ0ZXh0XCJcclxuICAgICAgY2xhc3M9XCJmb3JtLWNvbnRyb2wgZm9ybS1jb250cm9sLXNtXCJcclxuICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2ggYnkgZW1haWxcIlxyXG4gICAgICBbbmdNb2RlbF09XCJhcHByb3ZlclNlYXJjaFRlcm1cIlxyXG4gICAgICAobmdNb2RlbENoYW5nZSk9XCJvblJldmlld2VyU2VhcmNoKCRldmVudClcIlxyXG4gICAgICAoY2xpY2spPVwiJGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpXCJcclxuICAgIC8+XHJcbiAgPC9kaXY+IC0tPlxyXG5cclxuICA8IS0tIFNlbGVjdCBBbGwgLS0+XHJcbiAgPGRpdiBjbGFzcz1cImZvcm0tY2hlY2sgcHgtMCBtYi0yIGQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cclxuICAgIDxpbnB1dFxyXG4gICAgICB0eXBlPVwiY2hlY2tib3hcIlxyXG4gICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxyXG4gICAgICBpZD1cInJldmlld2VyLWFsbFwiXHJcbiAgICAgIFtjaGVja2VkXT1cImFyZUFsbFJldmlld2Vyc1NlbGVjdGVkKClcIlxyXG4gICAgICAoY2hhbmdlKT1cIm9uUmV2aWV3ZXJTZWxlY3RBbGwoJGV2ZW50KVwiXHJcbiAgICAvPlxyXG4gICAgPGxhYmVsIGZvcj1cInJldmlld2VyLWFsbFwiIGNsYXNzPVwiZm9ybS1jaGVjay1sYWJlbCB0ZXh0LWRhcmsgbXMtMlwiPlxyXG4gICAgICBTZWxlY3QgQWxsXHJcbiAgICA8L2xhYmVsPlxyXG4gIDwvZGl2PlxyXG5cclxuICA8IS0tIE9wdGlvbnMgKHVzZSBmaWx0ZXJlZFJldmlld2VyTGlzdCBpbnN0ZWFkIG9mIHVzZXJMaXN0KSAtLT5cclxuICA8ZGl2XHJcbiAgICBjbGFzcz1cImZvcm0tY2hlY2sgbWItMSBweC0wIGQtZmxleCBhbGlnbi1pdGVtcy1jZW50ZXJcIlxyXG4gICAgKm5nRm9yPVwibGV0IHUgb2YgZmlsdGVyZWRBcHByb3Zlckxpc3RcIlxyXG4gID5cclxuICAgIDxpbnB1dFxyXG4gICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIlxyXG4gICAgICB0eXBlPVwiY2hlY2tib3hcIlxyXG4gICAgICBbaWRdPVwiJ3Jldi0nICsgdS5lbWFpbFwiXHJcbiAgICAgIFtjaGVja2VkXT1cImlzUmV2aWV3ZXJTZWxlY3RlZCh1LmVtYWlsKVwiXHJcbiAgICAgIChjaGFuZ2UpPVwib25SZXZpZXdlckNoYW5nZSgkZXZlbnQsIHUuZW1haWwpXCJcclxuICAgIC8+XHJcbiAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsIHRleHQtZGFyayBtcy0yXCIgW2Zvcl09XCIncmV2LScgKyB1LmVtYWlsXCI+XHJcbiAgICAgIHt7IHUuZW1haWwgfX1cclxuICAgIDwvbGFiZWw+XHJcbiAgPC9kaXY+XHJcbjwvZGl2PlxyXG5cclxuICA8IS0tIERyb3Bkb3duIHBhbmVsIC0tPlxyXG5cclxuPC9kaXY+XHJcblxyXG5cclxuICAgICAgPCEtLSBGb290ZXIgYnV0dG9ucyAtLT5cclxuICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiB3LTEwMCBtdC00XCI+XHJcbiAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUgdy01MCBtZS0xXCIgKGNsaWNrKT1cIm9uUmVzZXQoKVwiPlxyXG4gICAgICAgICAgUmVzZXRcclxuICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSB3LTUwIG1zLTFcIiAoY2xpY2spPVwib25BcHBseSgpXCI+XHJcbiAgICAgICAgICBBcHBseVxyXG4gICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZm9ybT5cclxuICA8L2Rpdj5cclxuPC9kaXY+XHJcbiJdfQ==