@smarterplan/ngx-smarterplan-admin 0.2.3 → 0.3.0

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 (64) hide show
  1. package/esm2022/lib/admin/admin.component.mjs +36 -0
  2. package/esm2022/lib/chevron/chevron.component.mjs +19 -0
  3. package/{esm2020 → esm2022}/lib/guest-link/guest-link.component.mjs +70 -62
  4. package/esm2022/lib/guide.guard.mjs +29 -0
  5. package/{esm2020 → esm2022}/lib/helpers.mjs +24 -24
  6. package/esm2022/lib/name-from-id.pipe.mjs +31 -0
  7. package/esm2022/lib/ngx-smarterplan-admin-routing.module.mjs +48 -0
  8. package/esm2022/lib/ngx-smarterplan-admin.module.mjs +89 -0
  9. package/esm2022/lib/ngx-smarterplan-admin.service.mjs +15 -0
  10. package/esm2022/lib/organisation/organisation.component.mjs +182 -0
  11. package/esm2022/lib/sp-admin.guard.mjs +29 -0
  12. package/esm2022/lib/user/detail-organisation/detail-organisation.component.mjs +207 -0
  13. package/esm2022/lib/user/form-mission/form-mission.component.mjs +290 -0
  14. package/esm2022/lib/user/form-organisation/form-organisation.component.mjs +139 -0
  15. package/esm2022/lib/user/user-mission-form/user-mission-form.component.mjs +132 -0
  16. package/esm2022/lib/user/user.component.mjs +353 -0
  17. package/esm2022/lib/visitor/create-batch/create-batch.component.mjs +112 -0
  18. package/esm2022/lib/visitor/template/template.component.mjs +295 -0
  19. package/esm2022/lib/visitor/visitor.component.mjs +318 -0
  20. package/{esm2020 → esm2022}/public-api.mjs +5 -5
  21. package/{esm2020 → esm2022}/smarterplan-ngx-smarterplan-admin.mjs +4 -4
  22. package/{fesm2020 → fesm2022}/smarterplan-ngx-smarterplan-admin.mjs +2205 -2065
  23. package/{fesm2020 → fesm2022}/smarterplan-ngx-smarterplan-admin.mjs.map +1 -1
  24. package/index.d.ts +5 -5
  25. package/lib/admin/admin.component.d.ts +13 -13
  26. package/lib/chevron/chevron.component.d.ts +9 -9
  27. package/lib/guest-link/guest-link.component.d.ts +20 -20
  28. package/lib/guide.guard.d.ts +11 -11
  29. package/lib/helpers.d.ts +2 -2
  30. package/lib/name-from-id.pipe.d.ts +11 -11
  31. package/lib/ngx-smarterplan-admin-routing.module.d.ts +7 -7
  32. package/lib/ngx-smarterplan-admin.module.d.ts +26 -26
  33. package/lib/ngx-smarterplan-admin.service.d.ts +6 -6
  34. package/lib/organisation/organisation.component.d.ts +54 -54
  35. package/lib/sp-admin.guard.d.ts +11 -11
  36. package/lib/user/detail-organisation/detail-organisation.component.d.ts +49 -49
  37. package/lib/user/form-mission/form-mission.component.d.ts +63 -63
  38. package/lib/user/form-organisation/form-organisation.component.d.ts +32 -32
  39. package/lib/user/user-mission-form/user-mission-form.component.d.ts +32 -32
  40. package/lib/user/user.component.d.ts +102 -102
  41. package/lib/visitor/create-batch/create-batch.component.d.ts +23 -23
  42. package/lib/visitor/template/template.component.d.ts +58 -58
  43. package/lib/visitor/visitor.component.d.ts +70 -70
  44. package/package.json +10 -16
  45. package/public-api.d.ts +2 -2
  46. package/esm2020/lib/admin/admin.component.mjs +0 -34
  47. package/esm2020/lib/chevron/chevron.component.mjs +0 -19
  48. package/esm2020/lib/guide.guard.mjs +0 -26
  49. package/esm2020/lib/name-from-id.pipe.mjs +0 -29
  50. package/esm2020/lib/ngx-smarterplan-admin-routing.module.mjs +0 -47
  51. package/esm2020/lib/ngx-smarterplan-admin.module.mjs +0 -88
  52. package/esm2020/lib/ngx-smarterplan-admin.service.mjs +0 -14
  53. package/esm2020/lib/organisation/organisation.component.mjs +0 -171
  54. package/esm2020/lib/sp-admin.guard.mjs +0 -26
  55. package/esm2020/lib/user/detail-organisation/detail-organisation.component.mjs +0 -191
  56. package/esm2020/lib/user/form-mission/form-mission.component.mjs +0 -265
  57. package/esm2020/lib/user/form-organisation/form-organisation.component.mjs +0 -125
  58. package/esm2020/lib/user/user-mission-form/user-mission-form.component.mjs +0 -121
  59. package/esm2020/lib/user/user.component.mjs +0 -336
  60. package/esm2020/lib/visitor/create-batch/create-batch.component.mjs +0 -106
  61. package/esm2020/lib/visitor/template/template.component.mjs +0 -277
  62. package/esm2020/lib/visitor/visitor.component.mjs +0 -299
  63. package/fesm2015/smarterplan-ngx-smarterplan-admin.mjs +0 -2245
  64. package/fesm2015/smarterplan-ngx-smarterplan-admin.mjs.map +0 -1
@@ -0,0 +1,353 @@
1
+ import { Component } from '@angular/core';
2
+ import { DomainType, filterUniqueArrayByID, ProfileEntity, waitUntil, } from '@smarterplan/ngx-smarterplan-core';
3
+ import { Subject } from 'rxjs';
4
+ import { GuestLinkComponent } from '../guest-link/guest-link.component';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@smarterplan/ngx-smarterplan-core";
7
+ import * as i2 from "@ng-bootstrap/ng-bootstrap";
8
+ import * as i3 from "@ngx-translate/core";
9
+ import * as i4 from "@angular/common";
10
+ import * as i5 from "../chevron/chevron.component";
11
+ import * as i6 from "./form-mission/form-mission.component";
12
+ import * as i7 from "./user-mission-form/user-mission-form.component";
13
+ import * as i8 from "./form-organisation/form-organisation.component";
14
+ import * as i9 from "./detail-organisation/detail-organisation.component";
15
+ class UserComponent {
16
+ userService;
17
+ missionService;
18
+ domainService;
19
+ organisationService;
20
+ modalService;
21
+ translate;
22
+ profileService;
23
+ users;
24
+ detailsUser = '-1';
25
+ detailsOrg = '-1';
26
+ query = '';
27
+ create = false;
28
+ edit = false;
29
+ working = false;
30
+ createForExistingUser = false;
31
+ isAddingOrg = false;
32
+ isAddingToExistingOrg = false;
33
+ userForAddingMission;
34
+ currentOrg;
35
+ me;
36
+ hideList = false;
37
+ orgsUsersMissions = [];
38
+ missionToEdit;
39
+ isSP = false;
40
+ isGuide = false;
41
+ clientsSP = [];
42
+ prestataireClients = [];
43
+ domains;
44
+ addToOrg;
45
+ orgSelectedDetails;
46
+ filteredOrgsUsersMissions;
47
+ loading = false;
48
+ destroy$ = new Subject();
49
+ profilesWithoutMission = [];
50
+ constructor(userService, missionService, domainService, organisationService, modalService, translate, profileService) {
51
+ this.userService = userService;
52
+ this.missionService = missionService;
53
+ this.domainService = domainService;
54
+ this.organisationService = organisationService;
55
+ this.modalService = modalService;
56
+ this.translate = translate;
57
+ this.profileService = profileService;
58
+ }
59
+ // @todo list my org and sub orgs
60
+ async ngOnInit() {
61
+ this.initInfo();
62
+ }
63
+ ngOnDestroy() {
64
+ this.destroy$.next(true);
65
+ this.destroy$.complete();
66
+ }
67
+ /**
68
+ * resetList fetches a fresh user list from server
69
+ */
70
+ async resetList() {
71
+ this.orgsUsersMissions = [];
72
+ let allMissions = [];
73
+ this.loading = true;
74
+ if (this.isSP) {
75
+ this.orgsUsersMissions = await this.initListForSP();
76
+ this.filteredOrgsUsersMissions = this.orgsUsersMissions;
77
+ this.loading = false;
78
+ return;
79
+ }
80
+ if (this.isGuide) {
81
+ // guide sees only its own organisation
82
+ allMissions =
83
+ await this.missionService.getMissionsByOrganisation(this.currentOrg.id);
84
+ }
85
+ else {
86
+ allMissions = await this.missionService.getMissionsByOrderedOrganisation(this.currentOrg.id);
87
+ const currentOrgMissions = await this.missionService.getMissionsByOrganisation(this.currentOrg.id);
88
+ allMissions = [...allMissions, ...currentOrgMissions];
89
+ }
90
+ allMissions = allMissions.filter((mission) => mission.user && !mission.user.deletedAt);
91
+ allMissions = filterUniqueArrayByID(allMissions);
92
+ if (allMissions) {
93
+ const orgs = allMissions.map((mis) => mis.organisation);
94
+ const profiles = allMissions.map((mis) => mis.user);
95
+ const uniqueOrg = filterUniqueArrayByID(orgs);
96
+ const uniqueUsers = filterUniqueArrayByID(profiles);
97
+ uniqueOrg.map((org) => {
98
+ const orgMissions = allMissions.filter((mis) => {
99
+ return mis.organisationID === org.id;
100
+ });
101
+ let users = this.getUsersForOrgMissions(uniqueUsers, orgMissions);
102
+ users = users.sort((user) => (user.user.email ? 0 : -1));
103
+ const object = {
104
+ org,
105
+ users,
106
+ };
107
+ this.orgsUsersMissions.push(object);
108
+ });
109
+ }
110
+ this.filteredOrgsUsersMissions = this.orgsUsersMissions;
111
+ this.loading = false;
112
+ }
113
+ async initInfo() {
114
+ await waitUntil(() => this.userService.cu !== undefined);
115
+ this.me = this.userService.cu;
116
+ this.currentOrg = this.userService.currentOrganisation();
117
+ this.isSP = this.userService.isSPAdmin();
118
+ this.isGuide = this.userService.isGuide();
119
+ this.resetList();
120
+ this.setDomains();
121
+ }
122
+ async initListForSP() {
123
+ const results = [];
124
+ let allMissions = [];
125
+ let allOrgs = [];
126
+ allOrgs = await this.organisationService.listOrganisations();
127
+ allOrgs = allOrgs.filter((o) => !o.deletedAt);
128
+ await Promise.all(allOrgs.map(async (org) => {
129
+ const missions = await this.missionService.getMissionsByOrganisation(org.id);
130
+ allMissions = [...allMissions, ...missions];
131
+ }));
132
+ const profiles = allMissions
133
+ .map((mis) => mis.user)
134
+ .filter((user) => !user.deletedAt);
135
+ const uniqueUsers = filterUniqueArrayByID(profiles.filter((profile) => profile !== null));
136
+ allOrgs.map((org) => {
137
+ const orgMissions = allMissions.filter((mis) => {
138
+ return mis.organisationID === org.id;
139
+ });
140
+ if (orgMissions.length > 0) {
141
+ if (orgMissions.filter((m) => m.orderedOrganisationID === '6e28201f-4679-4c29-9d2d-8a325f57cee9').length > 0) {
142
+ this.clientsSP.push(org.id);
143
+ }
144
+ else {
145
+ this.prestataireClients.push({
146
+ orgOwner: orgMissions[0].orderedOrganisationID,
147
+ prestataire: org.id,
148
+ });
149
+ }
150
+ }
151
+ const users = this.getUsersForOrgMissions(uniqueUsers, orgMissions);
152
+ const object = {
153
+ org,
154
+ users,
155
+ };
156
+ results.push(object);
157
+ });
158
+ // get profiles without Missions
159
+ let profilesWithoutMission = await this.profileService.listCurrentProfiles();
160
+ profilesWithoutMission = profilesWithoutMission.filter((profile) => !uniqueUsers.map((p) => p.id).includes(profile.id));
161
+ if (profilesWithoutMission.length > 0) {
162
+ this.profilesWithoutMission = [];
163
+ profilesWithoutMission.forEach((profile) => {
164
+ const user = new ProfileEntity(profile);
165
+ this.profilesWithoutMission.push(user);
166
+ });
167
+ }
168
+ return results;
169
+ }
170
+ // eslint-disable-next-line class-methods-use-this
171
+ getUsersForOrgMissions(uniqueUsers, orgMissions) {
172
+ const users = uniqueUsers.map((user) => {
173
+ const userMissions = orgMissions.filter((m) => m.userID === user.id);
174
+ if (userMissions.length > 0) {
175
+ const userProfile = new ProfileEntity(user);
176
+ // once we got the user we check filter only active missions (not deleted)
177
+ const activeMissions = userMissions.filter((mis) => !mis.deletedAt);
178
+ return {
179
+ missions: activeMissions,
180
+ user: userProfile,
181
+ };
182
+ }
183
+ return null;
184
+ });
185
+ return users.filter((us) => us !== null);
186
+ }
187
+ async setDomains() {
188
+ const domains = await this.domainService.getDomainsForOrgExcludingTypes([DomainType.FEATURE, DomainType.BOOKING], this.currentOrg.id);
189
+ this.domains = domains;
190
+ }
191
+ /**
192
+ * onToggleDetail folds/unfolds details for a given organisation
193
+ * @param i index of the organisation to be toggled
194
+ */
195
+ onToggleDetailOrg(index, org) {
196
+ this.detailsOrg = index === this.detailsOrg ? '-1' : index;
197
+ this.orgSelectedDetails = this.detailsOrg === '-1' ? null : org;
198
+ }
199
+ onToggleDetailUser(index) {
200
+ this.detailsUser = index === this.detailsUser ? '-1' : index;
201
+ }
202
+ async onAdd(org) {
203
+ this.create = true;
204
+ this.hideList = true;
205
+ this.addToOrg = org;
206
+ }
207
+ async onEdit(m) {
208
+ this.edit = true;
209
+ this.hideList = true;
210
+ this.missionToEdit = m;
211
+ }
212
+ onCancel() {
213
+ this.working = false;
214
+ this.create = false;
215
+ this.missionToEdit = null;
216
+ this.createForExistingUser = false;
217
+ }
218
+ onAddForUser(org, user) {
219
+ this.hideList = true;
220
+ this.createForExistingUser = true;
221
+ this.userForAddingMission = user;
222
+ this.addToOrg = org;
223
+ }
224
+ onAddOrg() {
225
+ this.hideList = true;
226
+ this.isAddingOrg = true;
227
+ }
228
+ orgAdded(isAdded) {
229
+ this.hideList = false;
230
+ this.isAddingOrg = false;
231
+ this.isAddingToExistingOrg = false;
232
+ if (isAdded) {
233
+ this.resetList();
234
+ }
235
+ }
236
+ userAdded(isAdded) {
237
+ this.hideList = false;
238
+ this.create = false;
239
+ this.addToOrg = null;
240
+ this.createForExistingUser = false;
241
+ this.userForAddingMission = null;
242
+ if (isAdded) {
243
+ this.resetList();
244
+ }
245
+ }
246
+ async onMissionEdited(mission) {
247
+ this.edit = false;
248
+ this.missionToEdit = null;
249
+ if (mission) {
250
+ await this.userService.createOrUpdateMissionForOrgWithProperty(mission, mission.organisationID, false);
251
+ this.resetList();
252
+ }
253
+ this.hideList = false;
254
+ }
255
+ async onMissionCreated(mission) {
256
+ this.createForExistingUser = false;
257
+ this.userForAddingMission = null;
258
+ if (mission) {
259
+ await this.userService.createOrUpdateMissionForOrgWithProperty(mission, mission.organisationID);
260
+ this.resetList();
261
+ }
262
+ this.hideList = false;
263
+ }
264
+ getOrderedOrg(orgID) {
265
+ let name;
266
+ this.prestataireClients.map(async (presta) => {
267
+ if (presta.prestataire === orgID) {
268
+ const org = this.orgsUsersMissions.filter((object) => object.org.id === presta.orgOwner);
269
+ if (org.length > 0) {
270
+ name = org[0].org.name;
271
+ }
272
+ }
273
+ });
274
+ return name;
275
+ }
276
+ domainIdsToStringForMission(mission) {
277
+ let names = '';
278
+ for (const domainID of mission.domains) {
279
+ const domain = this.domains.find((dom) => dom.id === domainID);
280
+ if (domain) {
281
+ names = `${names} ${domain.name},`;
282
+ }
283
+ }
284
+ return names.slice(0, -1); // to remove last comma
285
+ }
286
+ async onDeleteMission(mission) {
287
+ const message = this.translate.instant('confirm.deleteMission');
288
+ if (window.confirm(message)) {
289
+ await this.missionService.softDeleteMission(mission.id);
290
+ this.resetList();
291
+ }
292
+ }
293
+ async onDeleteUser(user) {
294
+ const message = this.translate.instant('confirm.deleteUser');
295
+ if (window.confirm(message)) {
296
+ const userMissions = await this.missionService.getMissionsFromUserID(user.id);
297
+ if (userMissions.length > 0) {
298
+ const resultDelete = [];
299
+ await Promise.all(userMissions.map(async (mission) => {
300
+ if (mission.orderedOrganisationID === this.currentOrg.id ||
301
+ this.isSP) {
302
+ const deletedMission = await this.missionService.softDeleteMission(mission.id);
303
+ if (deletedMission) {
304
+ resultDelete.push(deletedMission);
305
+ }
306
+ }
307
+ }));
308
+ if (resultDelete.length > 0) {
309
+ await this.userService.softDeleteUser(user.id);
310
+ await this.resetList();
311
+ }
312
+ }
313
+ else {
314
+ await this.userService.softDeleteUser(user.id);
315
+ await this.resetList();
316
+ }
317
+ }
318
+ }
319
+ applyResultsSearchBar(results) {
320
+ this.orgSelectedDetails = null;
321
+ this.filteredOrgsUsersMissions = results || this.orgsUsersMissions;
322
+ }
323
+ onAddInExistingOrg() {
324
+ this.hideList = true;
325
+ this.isAddingToExistingOrg = true;
326
+ }
327
+ /**
328
+ * Creates encypted link and sets it for guestLink for Space.
329
+ * @param mis
330
+ */
331
+ onSetForShareableLink(user, mission) {
332
+ const modalReference = this.modalService.open(GuestLinkComponent);
333
+ modalReference.componentInstance.username = user.email;
334
+ modalReference.componentInstance.spaceID = mission.spaceID;
335
+ }
336
+ async onClearToken(user) {
337
+ await this.userService.clearUserToken(user.user.id);
338
+ const firstMessage = this.translate.instant('firstTokenMessage');
339
+ const secondMessage = this.translate.instant('secondTokenMessage');
340
+ alert(firstMessage + user.user.displayName + secondMessage);
341
+ }
342
+ getStringNoSpace(data) {
343
+ return data.replace(/\s/g, '');
344
+ }
345
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UserComponent, deps: [{ token: i1.BaseUserService }, { token: i1.MissionService }, { token: i1.DomainService }, { token: i1.OrganisationService }, { token: i2.NgbModal }, { token: i3.TranslateService }, { token: i1.ProfileService }], target: i0.ɵɵFactoryTarget.Component });
346
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: UserComponent, selector: "lib-user", ngImport: i0, template: "<div class=\"dashboard-tab\">\r\n <div class=\"header-dashboard-tab\">\r\n <h3>{{'Users' | translate}}</h3>\r\n <!-- <app-search-bar *ngIf=\"!hideList\" [searchable]=\"orgsUsersMissions\" objectType=\"USER\"\r\n (searchEvent)=\"applyResultsSearchBar($event)\">\r\n </app-search-bar> -->\r\n <hr>\r\n </div>\r\n <div class=\"row\">\r\n <div class=\"col-md-8 col-lg-6\">\r\n <div class=\"row ml-0 mb-2\" *ngIf=\"!hideList\">\r\n <button class=\"btn btn-outline-primary rounded-pill add-button\" *ngIf=\"!isGuide\" (click)=\"onAddOrg()\">\r\n {{'Add user to new organisation' | translate}}</button>\r\n </div>\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"loading\">\r\n <lib-loader></lib-loader>\r\n </div>\r\n <div *ngIf=\"!hideList\">\r\n <ul class=\"list-group list-group-flush\" *ngIf=\"filteredOrgsUsersMissions\" data-testid=\"mission-organisation-list\">\r\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let o of filteredOrgsUsersMissions\">\r\n <div class=\"d-flex justify-content-between align-items-center font-weight-bold\"\r\n ngbTooltip=\"See details and users\" style=\"cursor: pointer;\" (click)=\"onToggleDetailOrg(o.org.id, o.org)\">\r\n {{o.org.name}} <small *ngIf=\"o.org.id == currentOrg.id\">({{'My organisation' | translate}})</small>\r\n <small *ngIf=\"isSP && clientsSP.includes(o.org.id)\">({{'Client of SmarterPlan' | translate}})</small>\r\n <small *ngIf=\"isSP && getOrderedOrg(o.org.id)\">({{'Client of ' | translate}}\r\n {{getOrderedOrg(o.org.id)}})</small>\r\n <lib-chevron [conditionShowing]=\"detailsOrg==o.org.id\" [ngClass]=\"[getStringNoSpace(o.org.name)]\"></lib-chevron>\r\n </div>\r\n <div class=\"missions\" *ngIf=\"detailsOrg==o.org.id\">\r\n <div class='d-flex'>\r\n <button data-testid=\"user-new-btn\" class=\"btn btn-outline-primary rounded-pill mt-3 mb-3\" (click)=\"onAdd(o.org)\">{{'Add user' |\r\n translate}}</button>\r\n </div>\r\n\r\n <ul class=\"list-group list-group-flush\" data-testid=\"mission-user-list\">\r\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let a of o.users\"\r\n (click)=\"onToggleDetailUser(a.user.id)\">\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n {{a.user.displayName}}\r\n <lib-chevron [conditionShowing]=\"detailsUser==a.user.id\" [ngClass]=\"[getStringNoSpace(a.user.displayName)]\"></lib-chevron>\r\n </div>\r\n\r\n <div *ngIf=\"detailsUser==a.user.id\">\r\n <div class=\"ml-3\">\r\n <div class=\"d-flex justify-content-between align-items-center mt-3\">\r\n {{'Email' | translate}}: {{a.user.email }}\r\n </div>\r\n <div class=\"d-flex justify-content-between align-items-center mt-3\">\r\n <button type=\"button\" class=\"btn btn-primary rounded-pill\" data-testid=\"mission-new-btn\"\r\n (click)=\"onAddForUser(o.org, a.user)\">{{'Add new mission' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-primary rounded-pill\" (click)=\"onClearToken(a)\">\r\n {{'Clear Token' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-primary rounded-pill\"\r\n (click)=\"onDeleteUser(a.user)\">{{'Delete user' | translate}}</button>\r\n </div>\r\n <div class=\"d-flex justify-content-between align-items-center mt-3\">\r\n {{ a.missions.length > 0 ? ('Current Missions' | translate) : ('No missions' | translate)}}\r\n </div>\r\n </div>\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item\" *ngFor=\"let mis of a.missions\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"mis.description\">\r\n {{'Description' | translate}}: {{mis.description}}</li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"mis.templateMissionID\">\r\n {{'Attendee of tour' | translate}}: {{mis.templateMission.title}}</li>\r\n\r\n <li class=\"list-group-item bg-transparent\">{{'Role' | translate}}: {{ mis.role }}</li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"mis.hashtags && mis.hashtags.length> 0\">\r\n {{'Hashtags' | translate}}: <ul class=\"keywordsDisplay no-border\">\r\n <div class=\"keywordsdisplayContainer\">\r\n <li class=\"keywordsItem\" *ngFor=\"let hashtag of mis.hashtags\">\r\n {{ hashtag | hashtagFromID | async }}</li>\r\n </div>\r\n </ul>\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Language' | translate }}: {{\r\n mis.locale ? mis.locale : ('Not applicable' | translate)}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Access level' | translate }}: {{\r\n mis.level}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Ordered by' | translate }}: {{\r\n mis.orderedOrganisation.name}}</li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"mis.domains\">{{'Domains' | translate }}:\r\n {{mis.domains ?\r\n domainIdsToStringForMission(mis) : (\"No data\" | translate) }}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Authorized location' | translate }}:\r\n {{ mis.space ? mis.space.name : \"No location\" | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Authorized zone' | translate }}:\r\n {{ mis.zone ? mis.zone.name : \"All zones allowed\" | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Starts' | translate }}:\r\n {{ mis.startDateTime ? (mis.startDateTime | timeDateString: \"day_time_zone\" | async) :\r\n \"No data\" | translate}}, {{'Ends' | translate}}: {{ mis.endDateTime\r\n ? (mis.endDateTime | timeDateString: \"day_time_zone\" | async)\r\n : \"No data\" | translate}}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Created' | translate }}:\r\n {{ mis.createdAt | timeDateString: \"day_time_zone\" | async }}\r\n </li>\r\n </ul>\r\n <div class=\"action-button-container\" >\r\n <button type=\"button\" data-testid=\"edit-mission-btn\" class=\"btn btn-outline-primary rounded-pill mr-2 action-button\"\r\n (click)=\"onEdit(mis)\">{{'Edit' |\r\n translate}}</button>\r\n <button type=\"button\" *ngIf=\"mis.role === 'VISITOR' || mis.role === 'VISITOR_MUSEUM'\"\r\n class=\"btn btn-outline-primary rounded-pill mr-2 action-button share-visitor-button\"\r\n (click)=\"onSetForShareableLink(a.user, mis)\">{{'Generate Shareable Link' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill action-button\"\r\n (click)=\"onDeleteMission(mis)\">{{'Delete' | translate}}</button>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n </li>\r\n <li class=\"list-group-item list-group-item-action\" *ngIf=\"profilesWithoutMission && profilesWithoutMission.length > 0\">\r\n <div class=\"d-flex justify-content-between align-items-center font-weight-bold\"\r\n ngbTooltip=\"See details\" style=\"cursor: pointer;\" (click)=\"onToggleDetailOrg('-2', null)\">\r\n {{\"Users without missions\" | translate}}\r\n <lib-chevron [conditionShowing]=\"detailsOrg=='-2'\"></lib-chevron>\r\n </div>\r\n <div class=\"missions\" *ngIf=\"detailsOrg=='-2'\">\r\n <ul class=\"list-group list-group-flush\" data-testid=\"mission-organisation-list\">\r\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let profile of profilesWithoutMission\" \r\n (click)=\"onToggleDetailUser(profile.id)\">\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n {{profile.displayName}}\r\n <lib-chevron [conditionShowing]=\"detailsUser==profile.id\" [ngClass]=\"[getStringNoSpace(profile.displayName)]\"></lib-chevron>\r\n </div>\r\n <div *ngIf=\"detailsUser==profile.id\">\r\n <div class=\"ml-3\">\r\n <div class=\"d-flex justify-content-between align-items-center mt-3\">\r\n {{'Email' | translate}}: {{profile.email }}\r\n </div>\r\n <div class=\"d-flex justify-content-between align-items-center mt-3\">\r\n <button type=\"button\" class=\"btn btn-primary rounded-pill\" data-testid=\"mission-new-btn\"\r\n (click)=\"onAddForUser(currentOrg, profile)\">{{'Add new mission' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-primary rounded-pill\"\r\n (click)=\"onDeleteUser(profile)\">{{'Delete user' | translate}}</button>\r\n </div>\r\n </div>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n\r\n <div *ngIf=\"create\">\r\n <lib-user-mission-form [addToOrganisation]=\"addToOrg\" [currentOrg]=\"currentOrg\" [isSP]=\"isSP\"\r\n (added)=\"userAdded($event)\">\r\n </lib-user-mission-form>\r\n </div>\r\n <div *ngIf=\"edit\">\r\n <lib-form-mission [missionToEdit]=\"missionToEdit\" [currentUserOrganisation]=\"currentOrg\" [isSP]=\"isSP\"\r\n (addedMissionInput)=\"onMissionEdited($event)\"></lib-form-mission>\r\n </div>\r\n <div *ngIf=\"createForExistingUser\">\r\n <lib-form-mission [organisationForMission]=\"addToOrg\" [currentUserOrganisation]=\"currentOrg\" [isSP]=\"isSP\"\r\n [userForMissionID]=\"userForAddingMission.id\" (addedMissionInput)=\"onMissionCreated($event)\">\r\n </lib-form-mission>\r\n </div>\r\n <div *ngIf=\"isAddingOrg || isAddingToExistingOrg\">\r\n <lib-form-organisation [currentOrg]=\"currentOrg\" [currentUser]=\"me\" [existing]=\"isAddingToExistingOrg\"\r\n (added)=\"orgAdded($event)\"></lib-form-organisation>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4 col-lg-6\" *ngIf=\"orgSelectedDetails && !isGuide\">\r\n <lib-detail-organisation [org]=\"orgSelectedDetails\" [currentOrg]=\"currentOrg\" [isSP]=\"isSP\"\r\n (orgChanged)='orgAdded($event)'></lib-detail-organisation>\r\n </div>\r\n </div>\r\n</div>", styles: [".add-button{width:-moz-fit-content;width:fit-content;margin-left:.5rem}li.ml-4{margin-left:3rem}.action-button-container{display:flex;justify-content:space-evenly}.action-button-container .action-button{width:145px}.action-button-container .share-visitor-button{width:-moz-fit-content;width:fit-content}\n"], dependencies: [{ kind: "directive", type: i2.NgbTooltip, selector: "[ngbTooltip]", inputs: ["animation", "autoClose", "placement", "popperOptions", "triggers", "positionTarget", "container", "disableTooltip", "tooltipClass", "openDelay", "closeDelay", "ngbTooltip"], outputs: ["shown", "hidden"], exportAs: ["ngbTooltip"] }, { kind: "directive", type: i4.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i1.LoaderComponent, selector: "lib-loader", inputs: ["useLogo", "color"] }, { kind: "component", type: i5.ChevronComponent, selector: "lib-chevron", inputs: ["conditionShowing"] }, { kind: "component", type: i6.FormMissionComponent, selector: "lib-form-mission", inputs: ["missionToEdit", "organisationForMission", "isSP", "userForMissionID", "currentUserOrganisation"], outputs: ["addedMissionInput"] }, { kind: "component", type: i7.UserMissionFormComponent, selector: "lib-user-mission-form", inputs: ["addToOrganisation", "isSP", "createForExistingUser", "currentOrg"], outputs: ["added"] }, { kind: "component", type: i8.FormOrganisationComponent, selector: "lib-form-organisation", inputs: ["currentOrg", "currentUser", "existing"], outputs: ["added"] }, { kind: "component", type: i9.DetailOrganisationComponent, selector: "lib-detail-organisation", inputs: ["org", "currentOrg", "isSP"], outputs: ["orgChanged"] }, { kind: "pipe", type: i4.AsyncPipe, name: "async" }, { kind: "pipe", type: i1.TimeDateToLocalStringPipe, name: "timeDateString" }, { kind: "pipe", type: i1.HashtagFromIdPipe, name: "hashtagFromID" }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }] });
347
+ }
348
+ export { UserComponent };
349
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: UserComponent, decorators: [{
350
+ type: Component,
351
+ args: [{ selector: 'lib-user', template: "<div class=\"dashboard-tab\">\r\n <div class=\"header-dashboard-tab\">\r\n <h3>{{'Users' | translate}}</h3>\r\n <!-- <app-search-bar *ngIf=\"!hideList\" [searchable]=\"orgsUsersMissions\" objectType=\"USER\"\r\n (searchEvent)=\"applyResultsSearchBar($event)\">\r\n </app-search-bar> -->\r\n <hr>\r\n </div>\r\n <div class=\"row\">\r\n <div class=\"col-md-8 col-lg-6\">\r\n <div class=\"row ml-0 mb-2\" *ngIf=\"!hideList\">\r\n <button class=\"btn btn-outline-primary rounded-pill add-button\" *ngIf=\"!isGuide\" (click)=\"onAddOrg()\">\r\n {{'Add user to new organisation' | translate}}</button>\r\n </div>\r\n <div class=\"d-flex justify-content-center\" *ngIf=\"loading\">\r\n <lib-loader></lib-loader>\r\n </div>\r\n <div *ngIf=\"!hideList\">\r\n <ul class=\"list-group list-group-flush\" *ngIf=\"filteredOrgsUsersMissions\" data-testid=\"mission-organisation-list\">\r\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let o of filteredOrgsUsersMissions\">\r\n <div class=\"d-flex justify-content-between align-items-center font-weight-bold\"\r\n ngbTooltip=\"See details and users\" style=\"cursor: pointer;\" (click)=\"onToggleDetailOrg(o.org.id, o.org)\">\r\n {{o.org.name}} <small *ngIf=\"o.org.id == currentOrg.id\">({{'My organisation' | translate}})</small>\r\n <small *ngIf=\"isSP && clientsSP.includes(o.org.id)\">({{'Client of SmarterPlan' | translate}})</small>\r\n <small *ngIf=\"isSP && getOrderedOrg(o.org.id)\">({{'Client of ' | translate}}\r\n {{getOrderedOrg(o.org.id)}})</small>\r\n <lib-chevron [conditionShowing]=\"detailsOrg==o.org.id\" [ngClass]=\"[getStringNoSpace(o.org.name)]\"></lib-chevron>\r\n </div>\r\n <div class=\"missions\" *ngIf=\"detailsOrg==o.org.id\">\r\n <div class='d-flex'>\r\n <button data-testid=\"user-new-btn\" class=\"btn btn-outline-primary rounded-pill mt-3 mb-3\" (click)=\"onAdd(o.org)\">{{'Add user' |\r\n translate}}</button>\r\n </div>\r\n\r\n <ul class=\"list-group list-group-flush\" data-testid=\"mission-user-list\">\r\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let a of o.users\"\r\n (click)=\"onToggleDetailUser(a.user.id)\">\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n {{a.user.displayName}}\r\n <lib-chevron [conditionShowing]=\"detailsUser==a.user.id\" [ngClass]=\"[getStringNoSpace(a.user.displayName)]\"></lib-chevron>\r\n </div>\r\n\r\n <div *ngIf=\"detailsUser==a.user.id\">\r\n <div class=\"ml-3\">\r\n <div class=\"d-flex justify-content-between align-items-center mt-3\">\r\n {{'Email' | translate}}: {{a.user.email }}\r\n </div>\r\n <div class=\"d-flex justify-content-between align-items-center mt-3\">\r\n <button type=\"button\" class=\"btn btn-primary rounded-pill\" data-testid=\"mission-new-btn\"\r\n (click)=\"onAddForUser(o.org, a.user)\">{{'Add new mission' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-primary rounded-pill\" (click)=\"onClearToken(a)\">\r\n {{'Clear Token' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-primary rounded-pill\"\r\n (click)=\"onDeleteUser(a.user)\">{{'Delete user' | translate}}</button>\r\n </div>\r\n <div class=\"d-flex justify-content-between align-items-center mt-3\">\r\n {{ a.missions.length > 0 ? ('Current Missions' | translate) : ('No missions' | translate)}}\r\n </div>\r\n </div>\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item\" *ngFor=\"let mis of a.missions\">\r\n <ul class=\"list-group list-group-flush\">\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"mis.description\">\r\n {{'Description' | translate}}: {{mis.description}}</li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"mis.templateMissionID\">\r\n {{'Attendee of tour' | translate}}: {{mis.templateMission.title}}</li>\r\n\r\n <li class=\"list-group-item bg-transparent\">{{'Role' | translate}}: {{ mis.role }}</li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"mis.hashtags && mis.hashtags.length> 0\">\r\n {{'Hashtags' | translate}}: <ul class=\"keywordsDisplay no-border\">\r\n <div class=\"keywordsdisplayContainer\">\r\n <li class=\"keywordsItem\" *ngFor=\"let hashtag of mis.hashtags\">\r\n {{ hashtag | hashtagFromID | async }}</li>\r\n </div>\r\n </ul>\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Language' | translate }}: {{\r\n mis.locale ? mis.locale : ('Not applicable' | translate)}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Access level' | translate }}: {{\r\n mis.level}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Ordered by' | translate }}: {{\r\n mis.orderedOrganisation.name}}</li>\r\n <li class=\"list-group-item bg-transparent\" *ngIf=\"mis.domains\">{{'Domains' | translate }}:\r\n {{mis.domains ?\r\n domainIdsToStringForMission(mis) : (\"No data\" | translate) }}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Authorized location' | translate }}:\r\n {{ mis.space ? mis.space.name : \"No location\" | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Authorized zone' | translate }}:\r\n {{ mis.zone ? mis.zone.name : \"All zones allowed\" | translate}}</li>\r\n <li class=\"list-group-item bg-transparent\">{{'Starts' | translate }}:\r\n {{ mis.startDateTime ? (mis.startDateTime | timeDateString: \"day_time_zone\" | async) :\r\n \"No data\" | translate}}, {{'Ends' | translate}}: {{ mis.endDateTime\r\n ? (mis.endDateTime | timeDateString: \"day_time_zone\" | async)\r\n : \"No data\" | translate}}\r\n </li>\r\n <li class=\"list-group-item bg-transparent\">{{'Created' | translate }}:\r\n {{ mis.createdAt | timeDateString: \"day_time_zone\" | async }}\r\n </li>\r\n </ul>\r\n <div class=\"action-button-container\" >\r\n <button type=\"button\" data-testid=\"edit-mission-btn\" class=\"btn btn-outline-primary rounded-pill mr-2 action-button\"\r\n (click)=\"onEdit(mis)\">{{'Edit' |\r\n translate}}</button>\r\n <button type=\"button\" *ngIf=\"mis.role === 'VISITOR' || mis.role === 'VISITOR_MUSEUM'\"\r\n class=\"btn btn-outline-primary rounded-pill mr-2 action-button share-visitor-button\"\r\n (click)=\"onSetForShareableLink(a.user, mis)\">{{'Generate Shareable Link' |\r\n translate}}</button>\r\n <button type=\"button\" class=\"btn btn-outline-primary rounded-pill action-button\"\r\n (click)=\"onDeleteMission(mis)\">{{'Delete' | translate}}</button>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n </li>\r\n <li class=\"list-group-item list-group-item-action\" *ngIf=\"profilesWithoutMission && profilesWithoutMission.length > 0\">\r\n <div class=\"d-flex justify-content-between align-items-center font-weight-bold\"\r\n ngbTooltip=\"See details\" style=\"cursor: pointer;\" (click)=\"onToggleDetailOrg('-2', null)\">\r\n {{\"Users without missions\" | translate}}\r\n <lib-chevron [conditionShowing]=\"detailsOrg=='-2'\"></lib-chevron>\r\n </div>\r\n <div class=\"missions\" *ngIf=\"detailsOrg=='-2'\">\r\n <ul class=\"list-group list-group-flush\" data-testid=\"mission-organisation-list\">\r\n <li class=\"list-group-item list-group-item-action\" *ngFor=\"let profile of profilesWithoutMission\" \r\n (click)=\"onToggleDetailUser(profile.id)\">\r\n <div class=\"d-flex justify-content-between align-items-center\">\r\n {{profile.displayName}}\r\n <lib-chevron [conditionShowing]=\"detailsUser==profile.id\" [ngClass]=\"[getStringNoSpace(profile.displayName)]\"></lib-chevron>\r\n </div>\r\n <div *ngIf=\"detailsUser==profile.id\">\r\n <div class=\"ml-3\">\r\n <div class=\"d-flex justify-content-between align-items-center mt-3\">\r\n {{'Email' | translate}}: {{profile.email }}\r\n </div>\r\n <div class=\"d-flex justify-content-between align-items-center mt-3\">\r\n <button type=\"button\" class=\"btn btn-primary rounded-pill\" data-testid=\"mission-new-btn\"\r\n (click)=\"onAddForUser(currentOrg, profile)\">{{'Add new mission' | translate}}</button>\r\n <button type=\"button\" class=\"btn btn-primary rounded-pill\"\r\n (click)=\"onDeleteUser(profile)\">{{'Delete user' | translate}}</button>\r\n </div>\r\n </div>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n </li>\r\n </ul>\r\n </div>\r\n\r\n <div *ngIf=\"create\">\r\n <lib-user-mission-form [addToOrganisation]=\"addToOrg\" [currentOrg]=\"currentOrg\" [isSP]=\"isSP\"\r\n (added)=\"userAdded($event)\">\r\n </lib-user-mission-form>\r\n </div>\r\n <div *ngIf=\"edit\">\r\n <lib-form-mission [missionToEdit]=\"missionToEdit\" [currentUserOrganisation]=\"currentOrg\" [isSP]=\"isSP\"\r\n (addedMissionInput)=\"onMissionEdited($event)\"></lib-form-mission>\r\n </div>\r\n <div *ngIf=\"createForExistingUser\">\r\n <lib-form-mission [organisationForMission]=\"addToOrg\" [currentUserOrganisation]=\"currentOrg\" [isSP]=\"isSP\"\r\n [userForMissionID]=\"userForAddingMission.id\" (addedMissionInput)=\"onMissionCreated($event)\">\r\n </lib-form-mission>\r\n </div>\r\n <div *ngIf=\"isAddingOrg || isAddingToExistingOrg\">\r\n <lib-form-organisation [currentOrg]=\"currentOrg\" [currentUser]=\"me\" [existing]=\"isAddingToExistingOrg\"\r\n (added)=\"orgAdded($event)\"></lib-form-organisation>\r\n </div>\r\n </div>\r\n\r\n <div class=\"col-md-4 col-lg-6\" *ngIf=\"orgSelectedDetails && !isGuide\">\r\n <lib-detail-organisation [org]=\"orgSelectedDetails\" [currentOrg]=\"currentOrg\" [isSP]=\"isSP\"\r\n (orgChanged)='orgAdded($event)'></lib-detail-organisation>\r\n </div>\r\n </div>\r\n</div>", styles: [".add-button{width:-moz-fit-content;width:fit-content;margin-left:.5rem}li.ml-4{margin-left:3rem}.action-button-container{display:flex;justify-content:space-evenly}.action-button-container .action-button{width:145px}.action-button-container .share-visitor-button{width:-moz-fit-content;width:fit-content}\n"] }]
352
+ }], ctorParameters: function () { return [{ type: i1.BaseUserService }, { type: i1.MissionService }, { type: i1.DomainService }, { type: i1.OrganisationService }, { type: i2.NgbModal }, { type: i3.TranslateService }, { type: i1.ProfileService }]; } });
353
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidXNlci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9uZ3gtc21hcnRlcnBsYW4tYWRtaW4vc3JjL2xpYi91c2VyL3VzZXIuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvbmd4LXNtYXJ0ZXJwbGFuLWFkbWluL3NyYy9saWIvdXNlci91c2VyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQVUsTUFBTSxlQUFlLENBQUM7QUFFbEQsT0FBTyxFQUlILFVBQVUsRUFDVixxQkFBcUIsRUFNckIsYUFBYSxFQUViLFNBQVMsR0FDWixNQUFNLG1DQUFtQyxDQUFDO0FBQzNDLE9BQU8sRUFBRSxPQUFPLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDL0IsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sb0NBQW9DLENBQUM7Ozs7Ozs7Ozs7O0FBR3hFLE1BS2EsYUFBYTtJQW9FVjtJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBQ0E7SUFDQTtJQXpFWixLQUFLLENBQXFDO0lBRTFDLFdBQVcsR0FBRyxJQUFJLENBQUM7SUFFbkIsVUFBVSxHQUFHLElBQUksQ0FBQztJQUVsQixLQUFLLEdBQUcsRUFBRSxDQUFDO0lBRVgsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUVmLElBQUksR0FBRyxLQUFLLENBQUM7SUFFYixPQUFPLEdBQUcsS0FBSyxDQUFDO0lBRWhCLHFCQUFxQixHQUFHLEtBQUssQ0FBQztJQUU5QixXQUFXLEdBQUcsS0FBSyxDQUFDO0lBRXBCLHFCQUFxQixHQUFHLEtBQUssQ0FBQztJQUU5QixvQkFBb0IsQ0FBZ0I7SUFFcEMsVUFBVSxDQUFlO0lBRXpCLEVBQUUsQ0FBZ0I7SUFFbEIsUUFBUSxHQUFHLEtBQUssQ0FBQztJQUVqQixpQkFBaUIsR0FNWixFQUFFLENBQUM7SUFFUixhQUFhLENBQVU7SUFFdkIsSUFBSSxH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QUksQ0FBQyxJQUFJLENBQUMsV0FBVyxHQUFHLGFBQWEsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFRCxnQkFBZ0IsQ0FBQyxJQUFJO1FBQ2pCLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbkMsQ0FBQzt3R0FsYlEsYUFBYTs0RkFBYixhQUFhLGdEQzFCMUIsaS9YQWdMTTs7U0R0Sk8sYUFBYTs0RkFBYixhQUFhO2tCQUx6QixTQUFTOytCQUNJLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBUcmFuc2xhdGVTZXJ2aWNlIH0gZnJvbSAnQG5neC10cmFuc2xhdGUvY29yZSc7XHJcbmltcG9ydCB7XHJcbiAgICBCYXNlVXNlclNlcnZpY2UsXHJcbiAgICBEb21haW4sXHJcbiAgICBEb21haW5TZXJ2aWNlLFxyXG4gICAgRG9tYWluVHlwZSxcclxuICAgIGZpbHRlclVuaXF1ZUFycmF5QnlJRCxcclxuICAgIE1pc3Npb24sXHJcbiAgICBNaXNzaW9uU2VydmljZSxcclxuICAgIE9yZ2FuaXNhdGlvbixcclxuICAgIE9yZ2FuaXNhdGlvblNlcnZpY2UsXHJcbiAgICBQcm9maWxlLFxyXG4gICAgUHJvZmlsZUVudGl0eSxcclxuICAgIFByb2ZpbGVTZXJ2aWNlLFxyXG4gICAgd2FpdFVudGlsLFxyXG59IGZyb20gJ0BzbWFydGVycGxhbi9uZ3gtc21hcnRlcnBsYW4tY29yZSc7XHJcbmltcG9ydCB7IFN1YmplY3QgfSBmcm9tICdyeGpzJztcclxuaW1wb3J0IHsgR3Vlc3RMaW5rQ29tcG9uZW50IH0gZnJvbSAnLi4vZ3Vlc3QtbGluay9ndWVzdC1saW5rLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IE5nYk1vZGFsIH0gZnJvbSAnQG5nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAnO1xyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ2xpYi11c2VyJyxcclxuICAgIHRlbXBsYXRlVXJsOiAnLi91c2VyLmNvbXBvbmVudC5odG1sJyxcclxuICAgIHN0eWxlVXJsczogWycuL3VzZXIuY29tcG9uZW50LnNjc3MnXSxcclxufSlcclxuZXhwb3J0IGNsYXNzIFVzZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xyXG4gICAgdXNlcnM6IEFycmF5PE1pc3Npb24gJiB7IG5hbWU6IHN0cmluZzsgfT47XHJcblxyXG4gICAgZGV0YWlsc1VzZXIgPSAnLTEnO1xyXG5cclxuICAgIGRldGFpbHNPcmcgPSAnLTEnO1xyXG5cclxuICAgIHF1ZXJ5ID0gJyc7XHJcblxyXG4gICAgY3JlYXRlID0gZmFsc2U7XHJcblxyXG4gICAgZWRpdCA9IGZhbHNlO1xyXG5cclxuICAgIHdvcmtpbmcgPSBmYWxzZTtcclxuXHJcbiAgICBjcmVhdGVGb3JFeGlzdGluZ1VzZXIgPSBmYWxzZTtcclxuXHJcbiAgICBpc0FkZGluZ09yZyA9IGZhbHNlO1xyXG5cclxuICAgIGlzQWRkaW5nVG9FeGlzdGluZ09yZyA9IGZhbHNlO1xyXG5cclxuICAgIHVzZXJGb3JBZGRpbmdNaXNzaW9uOiBQcm9maWxlRW50aXR5O1xyXG5cclxuICAgIGN1cnJlbnRPcmc6IE9yZ2FuaXNhdGlvbjtcclxuXHJcbiAgICBtZTogUHJvZmlsZUVudGl0eTtcclxuXHJcbiAgICBoaWRlTGlzdCA9IGZhbHNlO1xyXG5cclxuICAgIG9yZ3NVc2Vyc01pc3Npb25zOiBBcnJheTx7XHJcbiAgICAgICAgb3JnOiBPcmdhbmlzYXRpb247XHJcbiAgICAgICAgdXNlcnM6IEFycmF5PHtcclxuICAgICAgICAgICAgbWlzc2lvbnM6IE1pc3Npb25bXTtcclxuICAgICAgICAgICAgdXNlcjogUHJvZmlsZUVudGl0eTtcclxuICAgICAgICB9PjtcclxuICAgIH0+ID0gW107XHJcblxyXG4gICAgbWlzc2lvblRvRWRpdDogTWlzc2lvbjtcclxuXHJcbiAgICBpc1NQID0gZmFsc2U7XHJcblxyXG4gICAgaXNHdWlkZSA9IGZhbHNlO1xyXG5cclxuICAgIGNsaWVudHNTUDogc3RyaW5nW10gPSBbXTtcclxuXHJcbiAgICBwcmVzdGF0YWlyZUNsaWVudHM6IEFycmF5PHsgb3JnT3duZXI6IHN0cmluZzsgcHJlc3RhdGFpcmU6IHN0cmluZzsgfT4gPSBbXTtcclxuXHJcbiAgICBkb21haW5zOiBEb21haW5bXTtcclxuXHJcbiAgICBhZGRUb09yZzogT3JnYW5pc2F0aW9uO1xyXG5cclxuICAgIG9yZ1NlbGVjdGVkRGV0YWlsczogT3JnYW5pc2F0aW9uO1xyXG5cclxuICAgIGZpbHRlcmVkT3Jnc1VzZXJzTWlzc2lvbnM6IEFycmF5PHtcclxuICAgICAgICBvcmc6IE9yZ2FuaXNhdGlvbjtcclxuICAgICAgICB1c2VyczogQXJyYXk8e1xyXG4gICAgICAgICAgICBtaXNzaW9uczogTWlzc2lvbltdO1xyXG4gICAgICAgICAgICB1c2VyOiBQcm9maWxlRW50aXR5O1xyXG4gICAgICAgIH0+O1xyXG4gICAgfT47XHJcblxyXG4gICAgbG9hZGluZyA9IGZhbHNlO1xyXG5cclxuICAgIHByaXZhdGUgZGVzdHJveSQgPSBuZXcgU3ViamVjdCgpO1xyXG5cclxuICAgIHByb2ZpbGVzV2l0aG91dE1pc3Npb246IFByb2ZpbGVFbnRpdHlbXSA9IFtdO1xyXG5cclxuICAgIGNvbnN0cnVjdG9yKFxyXG4gICAgICAgIHByaXZhdGUgdXNlclNlcnZpY2U6IEJhc2VVc2VyU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIG1pc3Npb25TZXJ2aWNlOiBNaXNzaW9uU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIGRvbWFpblNlcnZpY2U6IERvbWFpblNlcnZpY2UsXHJcbiAgICAgICAgcHJpdmF0ZSBvcmdhbmlzYXRpb25TZXJ2aWNlOiBPcmdhbmlzYXRpb25TZXJ2aWNlLFxyXG4gICAgICAgIHByaXZhdGUgbW9kYWxTZXJ2aWNlOiBOZ2JNb2RhbCxcclxuICAgICAgICBwcml2YXRlIHRyYW5zbGF0ZTogVHJhbnNsYXRlU2VydmljZSxcclxuICAgICAgICBwcml2YXRlIHByb2ZpbGVTZXJ2aWNlOiBQcm9maWxlU2VydmljZSxcclxuICAgICkgeyB9XHJcblxyXG4gICAgLy8gQHRvZG8gbGlzdCBteSBvcmcgYW5kIHN1YiBvcmdzXHJcblxyXG5cclxuXHJcbiAgICBhc3luYyBuZ09uSW5pdCgpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICB0aGlzLmluaXRJbmZvKCk7XHJcbiAgICB9XHJcblxyXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5kZXN0cm95JC5uZXh0KHRydWUpO1xyXG4gICAgICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIHJlc2V0TGlzdCBmZXRjaGVzIGEgZnJlc2ggdXNlciBsaXN0IGZyb20gc2VydmVyXHJcbiAgICAgKi9cclxuICAgIGFzeW5jIHJlc2V0TGlzdCgpIHtcclxuICAgICAgICB0aGlzLm9yZ3NVc2Vyc01pc3Npb25zID0gW107XHJcbiAgICAgICAgbGV0IGFsbE1pc3Npb25zID0gW107XHJcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcclxuICAgICAgICBpZiAodGhpcy5pc1NQKSB7XHJcbiAgICAgICAgICAgIHRoaXMub3Jnc1VzZXJzTWlzc2lvbnMgPSBhd2FpdCB0aGlzLmluaXRMaXN0Rm9yU1AoKTtcclxuICAgICAgICAgICAgdGhpcy5maWx0ZXJlZE9yZ3NVc2Vyc01pc3Npb25zID0gdGhpcy5vcmdzVXNlcnNNaXNzaW9ucztcclxuICAgICAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmlzR3VpZGUpIHtcclxuICAgICAgICAgICAgLy8gZ3VpZGUgc2VlcyBvbmx5IGl0cyBvd24gb3JnYW5pc2F0aW9uXHJcbiAgICAgICAgICAgIGFsbE1pc3Npb25zID1cclxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMubWlzc2lvblNlcnZpY2UuZ2V0TWlzc2lvbnNCeU9yZ2FuaXNhdGlvbih0aGlzLmN1cnJlbnRPcmcuaWQpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGFsbE1pc3Npb25zID0gYXdhaXQgdGhpcy5taXNzaW9uU2VydmljZS5nZXRNaXNzaW9uc0J5T3JkZXJlZE9yZ2FuaXNhdGlvbihcclxuICAgICAgICAgICAgICAgIHRoaXMuY3VycmVudE9yZy5pZFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgICAgICBjb25zdCBjdXJyZW50T3JnTWlzc2lvbnMgPVxyXG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5taXNzaW9uU2VydmljZS5nZXRNaXNzaW9uc0J5T3JnYW5pc2F0aW9uKHRoaXMuY3VycmVudE9yZy5pZCk7XHJcbiAgICAgICAgICAgIGFsbE1pc3Npb25zID0gWy4uLmFsbE1pc3Npb25zLCAuLi5jdXJyZW50T3JnTWlzc2lvbnNdO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgYWxsTWlzc2lvbnMgPSBhbGxNaXNzaW9ucy5maWx0ZXIoKG1pc3Npb24pID0+IG1pc3Npb24udXNlciAmJiAhbWlzc2lvbi51c2VyLmRlbGV0ZWRBdCk7XHJcbiAgICAgICAgYWxsTWlzc2lvbnMgPSBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQoYWxsTWlzc2lvbnMpO1xyXG5cclxuICAgICAgICBpZiAoYWxsTWlzc2lvbnMpIHtcclxuICAgICAgICAgICAgY29uc3Qgb3JncyA9IGFsbE1pc3Npb25zLm1hcCgobWlzKSA9PiBtaXMub3JnYW5pc2F0aW9uKTtcclxuICAgICAgICAgICAgY29uc3QgcHJvZmlsZXMgPSBhbGxNaXNzaW9ucy5tYXAoKG1pcykgPT4gbWlzLnVzZXIpO1xyXG4gICAgICAgICAgICBjb25zdCB1bmlxdWVPcmcgPSBmaWx0ZXJVbmlxdWVBcnJheUJ5SUQob3Jncyk7XHJcbiAgICAgICAgICAgIGNvbnN0IHVuaXF1ZVVzZXJzID0gZmlsdGVyVW5pcXVlQXJyYXlCeUlEKHByb2ZpbGVzKTtcclxuICAgICAgICAgICAgdW5pcXVlT3JnLm1hcCgob3JnKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBvcmdNaXNzaW9ucyA9IGFsbE1pc3Npb25zLmZpbHRlcigobWlzKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG1pcy5vcmdhbmlzYXRpb25JRCA9PT0gb3JnLmlkO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICBsZXQgdXNlcnMgPSB0aGlzLmdldFVzZXJzRm9yT3JnTWlzc2lvbnModW5pcXVlVXNlcnMsIG9yZ01pc3Npb25zKTtcclxuICAgICAgICAgICAgICAgIHVzZXJzID0gdXNlcnMuc29ydCgodXNlcikgPT4gKHVzZXIudXNlci5lbWFpbCA/IDAgOiAtMSkpO1xyXG4gICAgICAgICAgICAgICAgY29uc3Qgb2JqZWN0ID0ge1xyXG4gICAgICAgICAgICAgICAgICAgIG9yZyxcclxuICAgICAgICAgICAgICAgICAgICB1c2VycyxcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9yZ3NVc2Vyc01pc3Npb25zLnB1c2gob2JqZWN0KTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuZmlsdGVyZWRPcmdzVXNlcnNNaXNzaW9ucyA9IHRoaXMub3Jnc1VzZXJzTWlzc2lvbnM7XHJcbiAgICAgICAgdGhpcy5sb2FkaW5nID0gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgaW5pdEluZm8oKSB7XHJcbiAgICAgICAgYXdhaXQgd2FpdFVudGlsKCgpID0+IHRoaXMudXNlclNlcnZpY2UuY3UgIT09IHVuZGVmaW5lZCk7XHJcbiAgICAgICAgdGhpcy5tZSA9IHRoaXMudXNlclNlcnZpY2UuY3U7XHJcbiAgICAgICAgdGhpcy5jdXJyZW50T3JnID0gdGhpcy51c2VyU2VydmljZS5jdXJyZW50T3JnYW5pc2F0aW9uKCk7XHJcbiAgICAgICAgdGhpcy5pc1NQID0gdGhpcy51c2VyU2VydmljZS5pc1NQQWRtaW4oKTtcclxuICAgICAgICB0aGlzLmlzR3VpZGUgPSB0aGlzLnVzZXJTZXJ2aWNlLmlzR3VpZGUoKTtcclxuICAgICAgICB0aGlzLnJlc2V0TGlzdCgpO1xyXG4gICAgICAgIHRoaXMuc2V0RG9tYWlucygpO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGluaXRMaXN0Rm9yU1AoKTogUHJvbWlzZTxhbnlbXT4ge1xyXG4gICAgICAgIGNvbnN0IHJlc3VsdHMgPSBbXTtcclxuICAgICAgICBsZXQgYWxsTWlzc2lvbnMgPSBbXTtcclxuICAgICAgICBsZXQgYWxsT3JncyA9IFtdO1xyXG4gICAgICAgIGFsbE9yZ3MgPSBhd2FpdCB0aGlzLm9yZ2FuaXNhdGlvblNlcnZpY2UubGlzdE9yZ2FuaXNhdGlvbnMoKTtcclxuICAgICAgICBhbGxPcmdzID0gYWxsT3Jncy5maWx0ZXIoKG8pID0+ICFvLmRlbGV0ZWRBdCk7XHJcbiAgICAgICAgYXdhaXQgUHJvbWlzZS5hbGwoXHJcbiAgICAgICAgICAgIGFsbE9yZ3MubWFwKGFzeW5jIChvcmcpID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG1pc3Npb25zID0gYXdhaXQgdGhpcy5taXNzaW9uU2VydmljZS5nZXRNaXNzaW9uc0J5T3JnYW5pc2F0aW9uKFxyXG4gICAgICAgICAgICAgICAgICAgIG9yZy5pZFxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIGFsbE1pc3Npb25zID0gWy4uLmFsbE1pc3Npb25zLCAuLi5taXNzaW9uc107XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgY29uc3QgcHJvZmlsZXMgPSBhbGxNaXNzaW9uc1xyXG4gICAgICAgICAgICAubWFwKChtaXMpID0+IG1pcy51c2VyKVxyXG4gICAgICAgICAgICAuZmlsdGVyKCh1c2VyKSA9PiAhdXNlci5kZWxldGVkQXQpO1xyXG4gICAgICAgIGNvbnN0IHVuaXF1ZVVzZXJzID0gZmlsdGVyVW5pcXVlQXJyYXlCeUlEKFxyXG4gICAgICAgICAgICBwcm9maWxlcy5maWx0ZXIoKHByb2ZpbGUpID0+IHByb2ZpbGUgIT09IG51bGwpXHJcbiAgICAgICAgKTtcclxuICAgICAgICBhbGxPcmdzLm1hcCgob3JnKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IG9yZ01pc3Npb25zID0gYWxsTWlzc2lvbnMuZmlsdGVyKChtaXMpID0+IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBtaXMub3JnYW5pc2F0aW9uSUQgPT09IG9yZy5pZDtcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICBpZiAob3JnTWlzc2lvbnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgIG9yZ01pc3Npb25zLmZpbHRlcihcclxuICAgICAgICAgICAgICAgICAgICAgICAgKG0pID0+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtLm9yZGVyZWRPcmdhbmlzYXRpb25JRCA9PT0gJzZlMjgyMDFmLTQ2NzktNGMyOS05ZDJkLThhMzI1ZjU3Y2VlOSdcclxuICAgICAgICAgICAgICAgICAgICApLmxlbmd0aCA+IDBcclxuICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2xpZW50c1NQLnB1c2gob3JnLmlkKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5wcmVzdGF0YWlyZUNsaWVudHMucHVzaCh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9yZ093bmVyOiBvcmdNaXNzaW9uc1swXS5vcmRlcmVkT3JnYW5pc2F0aW9uSUQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHByZXN0YXRhaXJlOiBvcmcuaWQsXHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY29uc3QgdXNlcnMgPSB0aGlzLmdldFVzZXJzRm9yT3JnTWlzc2lvbnModW5pcXVlVXNlcnMsIG9yZ01pc3Npb25zKTtcclxuICAgICAgICAgICAgY29uc3Qgb2JqZWN0ID0ge1xyXG4gICAgICAgICAgICAgICAgb3JnLFxyXG4gICAgICAgICAgICAgICAgdXNlcnMsXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIHJlc3VsdHMucHVzaChvYmplY3QpO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICAvLyBnZXQgcHJvZmlsZXMgd2l0aG91dCBNaXNzaW9uc1xyXG4gICAgICAgIGxldCBwcm9maWxlc1dpdGhvdXRNaXNzaW9uID0gYXdhaXQgdGhpcy5wcm9maWxlU2VydmljZS5saXN0Q3VycmVudFByb2ZpbGVzKCk7XHJcbiAgICAgICAgcHJvZmlsZXNXaXRob3V0TWlzc2lvbiA9IHByb2ZpbGVzV2l0aG91dE1pc3Npb24uZmlsdGVyKChwcm9maWxlKSA9PiAhdW5pcXVlVXNlcnMubWFwKChwKSA9PiBwLmlkKS5pbmNsdWRlcyhwcm9maWxlLmlkKSk7XHJcbiAgICAgICAgaWYgKHByb2ZpbGVzV2l0aG91dE1pc3Npb24ubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICB0aGlzLnByb2ZpbGVzV2l0aG91dE1pc3Npb24gPSBbXTtcclxuICAgICAgICAgICAgcHJvZmlsZXNXaXRob3V0TWlzc2lvbi5mb3JFYWNoKChwcm9maWxlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB1c2VyID0gbmV3IFByb2ZpbGVFbnRpdHkocHJvZmlsZSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnByb2ZpbGVzV2l0aG91dE1pc3Npb24ucHVzaCh1c2VyKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gcmVzdWx0cztcclxuICAgIH1cclxuXHJcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgY2xhc3MtbWV0aG9kcy11c2UtdGhpc1xyXG4gICAgZ2V0VXNlcnNGb3JPcmdNaXNzaW9ucyhcclxuICAgICAgICB1bmlxdWVVc2VyczogUHJvZmlsZVtdLFxyXG4gICAgICAgIG9yZ01pc3Npb25zOiBNaXNzaW9uW11cclxuICAgICk6IEFycmF5PHtcclxuICAgICAgICBtaXNzaW9uczogTWlzc2lvbltdO1xyXG4gICAgICAgIHVzZXI6IFByb2ZpbGVFbnRpdHk7XHJcbiAgICB9PiB7XHJcbiAgICAgICAgY29uc3QgdXNlcnMgPSB1bmlxdWVVc2Vycy5tYXAoKHVzZXIpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgdXNlck1pc3Npb25zID0gb3JnTWlzc2lvbnMuZmlsdGVyKChtKSA9PiBtLnVzZXJJRCA9PT0gdXNlci5pZCk7XHJcbiAgICAgICAgICAgIGlmICh1c2VyTWlzc2lvbnMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdXNlclByb2ZpbGUgPSBuZXcgUHJvZmlsZUVudGl0eSh1c2VyKTtcclxuICAgICAgICAgICAgICAgIC8vIG9uY2Ugd2UgZ290IHRoZSB1c2VyIHdlIGNoZWNrIGZpbHRlciBvbmx5IGFjdGl2ZSBtaXNzaW9ucyAobm90IGRlbGV0ZWQpXHJcbiAgICAgICAgICAgICAgICBjb25zdCBhY3RpdmVNaXNzaW9ucyA9IHVzZXJNaXNzaW9ucy5maWx0ZXIoKG1pcykgPT4gIW1pcy5kZWxldGVkQXQpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgICAgICBtaXNzaW9uczogYWN0aXZlTWlzc2lvbnMsXHJcbiAgICAgICAgICAgICAgICAgICAgdXNlcjogdXNlclByb2ZpbGUsXHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH0pO1xyXG4gICAgICAgIHJldHVybiB1c2Vycy5maWx0ZXIoKHVzKSA9PiB1cyAhPT0gbnVsbCk7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgc2V0RG9tYWlucygpIHtcclxuICAgICAgICBjb25zdCBkb21haW5zID0gYXdhaXQgdGhpcy5kb21haW5TZXJ2aWNlLmdldERvbWFpbnNGb3JPcmdFeGNsdWRpbmdUeXBlcyhcclxuICAgICAgICAgICAgW0RvbWFpblR5cGUuRkVBVFVSRSwgRG9tYWluVHlwZS5CT09LSU5HXSxcclxuICAgICAgICAgICAgdGhpcy5jdXJyZW50T3JnLmlkXHJcbiAgICAgICAgKTtcclxuICAgICAgICB0aGlzLmRvbWFpbnMgPSBkb21haW5zO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogb25Ub2dnbGVEZXRhaWwgZm9sZHMvdW5mb2xkcyBkZXRhaWxzIGZvciBhIGdpdmVuIG9yZ2FuaXNhdGlvblxyXG4gICAgICogQHBhcmFtIGkgaW5kZXggb2YgdGhlIG9yZ2FuaXNhdGlvbiB0byBiZSB0b2dnbGVkXHJcbiAgICAgKi9cclxuICAgIG9uVG9nZ2xlRGV0YWlsT3JnKGluZGV4LCBvcmcpIHtcclxuICAgICAgICB0aGlzLmRldGFpbHNPcmcgPSBpbmRleCA9PT0gdGhpcy5kZXRhaWxzT3JnID8gJy0xJyA6IGluZGV4O1xyXG4gICAgICAgIHRoaXMub3JnU2VsZWN0ZWREZXRhaWxzID0gdGhpcy5kZXRhaWxzT3JnID09PSAnLTEnID8gbnVsbCA6IG9yZztcclxuICAgIH1cclxuXHJcbiAgICBvblRvZ2dsZURldGFpbFVzZXIoaW5kZXgpIHtcclxuICAgICAgICB0aGlzLmRldGFpbHNVc2VyID0gaW5kZXggPT09IHRoaXMuZGV0YWlsc1VzZXIgPyAnLTEnIDogaW5kZXg7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgb25BZGQob3JnOiBPcmdhbmlzYXRpb24pIHtcclxuICAgICAgICB0aGlzLmNyZWF0ZSA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5oaWRlTGlzdCA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5hZGRUb09yZyA9IG9yZztcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBvbkVkaXQobTogTWlzc2lvbikge1xyXG4gICAgICAgIHRoaXMuZWRpdCA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5oaWRlTGlzdCA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5taXNzaW9uVG9FZGl0ID0gbTtcclxuICAgIH1cclxuXHJcbiAgICBvbkNhbmNlbCgpIHtcclxuICAgICAgICB0aGlzLndvcmtpbmcgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLmNyZWF0ZSA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMubWlzc2lvblRvRWRpdCA9IG51bGw7XHJcbiAgICAgICAgdGhpcy5jcmVhdGVGb3JFeGlzdGluZ1VzZXIgPSBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBvbkFkZEZvclVzZXIob3JnOiBPcmdhbmlzYXRpb24sIHVzZXI6IFByb2ZpbGVFbnRpdHkpIHtcclxuICAgICAgICB0aGlzLmhpZGVMaXN0ID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLmNyZWF0ZUZvckV4aXN0aW5nVXNlciA9IHRydWU7XHJcbiAgICAgICAgdGhpcy51c2VyRm9yQWRkaW5nTWlzc2lvbiA9IHVzZXI7XHJcbiAgICAgICAgdGhpcy5hZGRUb09yZyA9IG9yZztcclxuICAgIH1cclxuXHJcbiAgICBvbkFkZE9yZygpIHtcclxuICAgICAgICB0aGlzLmhpZGVMaXN0ID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLmlzQWRkaW5nT3JnID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICBvcmdBZGRlZChpc0FkZGVkOiBib29sZWFuKSB7XHJcbiAgICAgICAgdGhpcy5oaWRlTGlzdCA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuaXNBZGRpbmdPcmcgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLmlzQWRkaW5nVG9FeGlzdGluZ09yZyA9IGZhbHNlO1xyXG4gICAgICAgIGlmIChpc0FkZGVkKSB7XHJcbiAgICAgICAgICAgIHRoaXMucmVzZXRMaXN0KCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHVzZXJBZGRlZChpc0FkZGVkOiBib29sZWFuKSB7XHJcbiAgICAgICAgdGhpcy5oaWRlTGlzdCA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuY3JlYXRlID0gZmFsc2U7XHJcbiAgICAgICAgdGhpcy5hZGRUb09yZyA9IG51bGw7XHJcbiAgICAgICAgdGhpcy5jcmVhdGVGb3JFeGlzdGluZ1VzZXIgPSBmYWxzZTtcclxuICAgICAgICB0aGlzLnVzZXJGb3JBZGRpbmdNaXNzaW9uID0gbnVsbDtcclxuICAgICAgICBpZiAoaXNBZGRlZCkge1xyXG4gICAgICAgICAgICB0aGlzLnJlc2V0TGlzdCgpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBvbk1pc3Npb25FZGl0ZWQobWlzc2lvbjogTWlzc2lvbikge1xyXG4gICAgICAgIHRoaXMuZWRpdCA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMubWlzc2lvblRvRWRpdCA9IG51bGw7XHJcbiAgICAgICAgaWYgKG1pc3Npb24pIHtcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy51c2VyU2VydmljZS5jcmVhdGVPclVwZGF0ZU1pc3Npb25Gb3JPcmdXaXRoUHJvcGVydHkoXHJcbiAgICAgICAgICAgICAgICBtaXNzaW9uLFxyXG4gICAgICAgICAgICAgICAgbWlzc2lvbi5vcmdhbmlzYXRpb25JRCxcclxuICAgICAgICAgICAgICAgIGZhbHNlXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIHRoaXMucmVzZXRMaXN0KCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuaGlkZUxpc3QgPSBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBvbk1pc3Npb25DcmVhdGVkKG1pc3Npb246IE1pc3Npb24pIHtcclxuICAgICAgICB0aGlzLmNyZWF0ZUZvckV4aXN0aW5nVXNlciA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMudXNlckZvckFkZGluZ01pc3Npb24gPSBudWxsO1xyXG4gICAgICAgIGlmIChtaXNzaW9uKSB7XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMudXNlclNlcnZpY2UuY3JlYXRlT3JVcGRhdGVNaXNzaW9uRm9yT3JnV2l0aFByb3BlcnR5KFxyXG4gICAgICAgICAgICAgICAgbWlzc2lvbixcclxuICAgICAgICAgICAgICAgIG1pc3Npb24ub3JnYW5pc2F0aW9uSURcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgdGhpcy5yZXNldExpc3QoKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5oaWRlTGlzdCA9IGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIGdldE9yZGVyZWRPcmcob3JnSUQ6IHN0cmluZyk6IHN0cmluZyB8IG51bGwge1xyXG4gICAgICAgIGxldCBuYW1lO1xyXG4gICAgICAgIHRoaXMucHJlc3RhdGFpcmVDbGllbnRzLm1hcChhc3luYyAocHJlc3RhKSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChwcmVzdGEucHJlc3RhdGFpcmUgPT09IG9yZ0lEKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBvcmcgPSB0aGlzLm9yZ3NVc2Vyc01pc3Npb25zLmZpbHRlcihcclxuICAgICAgICAgICAgICAgICAgICAob2JqZWN0KSA9PiBvYmplY3Qub3JnLmlkID09PSBwcmVzdGEub3JnT3duZXJcclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICBpZiAob3JnLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgICAgICAgICBuYW1lID0gb3JnWzBdLm9yZy5uYW1lO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgcmV0dXJuIG5hbWU7XHJcbiAgICB9XHJcblxyXG4gICAgZG9tYWluSWRzVG9TdHJpbmdGb3JNaXNzaW9uKG1pc3Npb246IE1pc3Npb24pOiBzdHJpbmcge1xyXG4gICAgICAgIGxldCBuYW1lcyA9ICcnO1xyXG4gICAgICAgIGZvciAoY29uc3QgZG9tYWluSUQgb2YgbWlzc2lvbi5kb21haW5zKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGRvbWFpbiA9IHRoaXMuZG9tYWlucy5maW5kKChkb20pID0+IGRvbS5pZCA9PT0gZG9tYWluSUQpO1xyXG4gICAgICAgICAgICBpZiAoZG9tYWluKSB7XHJcbiAgICAgICAgICAgICAgICBuYW1lcyA9IGAke25hbWVzfSAke2RvbWFpbi5uYW1lfSxgO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBuYW1lcy5zbGljZSgwLCAtMSk7IC8vIHRvIHJlbW92ZSBsYXN0IGNvbW1hXHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgb25EZWxldGVNaXNzaW9uKG1pc3Npb246IE1pc3Npb24pIHtcclxuICAgICAgICBjb25zdCBtZXNzYWdlID0gdGhpcy50cmFuc2xhdGUuaW5zdGFudCgnY29uZmlybS5kZWxldGVNaXNzaW9uJyk7XHJcbiAgICAgICAgaWYgKHdpbmRvdy5jb25maXJtKG1lc3NhZ2UpKSB7XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMubWlzc2lvblNlcnZpY2Uuc29mdERlbGV0ZU1pc3Npb24obWlzc2lvbi5pZCk7XHJcbiAgICAgICAgICAgIHRoaXMucmVzZXRMaXN0KCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIG9uRGVsZXRlVXNlcih1c2VyKSB7XHJcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ2NvbmZpcm0uZGVsZXRlVXNlcicpO1xyXG4gICAgICAgIGlmICh3aW5kb3cuY29uZmlybShtZXNzYWdlKSkge1xyXG4gICAgICAgICAgICBjb25zdCB1c2VyTWlzc2lvbnMgPSBhd2FpdCB0aGlzLm1pc3Npb25TZXJ2aWNlLmdldE1pc3Npb25zRnJvbVVzZXJJRChcclxuICAgICAgICAgICAgICAgIHVzZXIuaWRcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgaWYgKHVzZXJNaXNzaW9ucy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHREZWxldGUgPSBbXTtcclxuICAgICAgICAgICAgICAgIGF3YWl0IFByb21pc2UuYWxsKFxyXG4gICAgICAgICAgICAgICAgICAgIHVzZXJNaXNzaW9ucy5tYXAoYXN5bmMgKG1pc3Npb24pID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWlzc2lvbi5vcmRlcmVkT3JnYW5pc2F0aW9uSUQgPT09IHRoaXMuY3VycmVudE9yZy5pZCB8fFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5pc1NQXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZGVsZXRlZE1pc3Npb24gPVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMubWlzc2lvblNlcnZpY2Uuc29mdERlbGV0ZU1pc3Npb24obWlzc2lvbi5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGVsZXRlZE1pc3Npb24pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHREZWxldGUucHVzaChkZWxldGVkTWlzc2lvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIGlmIChyZXN1bHREZWxldGUubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMudXNlclNlcnZpY2Uuc29mdERlbGV0ZVVzZXIodXNlci5pZCk7XHJcbiAgICAgICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5yZXNldExpc3QoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGF3YWl0IHRoaXMudXNlclNlcnZpY2Uuc29mdERlbGV0ZVVzZXIodXNlci5pZCk7XHJcbiAgICAgICAgICAgICAgICBhd2FpdCB0aGlzLnJlc2V0TGlzdCgpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGFwcGx5UmVzdWx0c1NlYXJjaEJhcihyZXN1bHRzKSB7XHJcbiAgICAgICAgdGhpcy5vcmdTZWxlY3RlZERldGFpbHMgPSBudWxsO1xyXG4gICAgICAgIHRoaXMuZmlsdGVyZWRPcmdzVXNlcnNNaXNzaW9ucyA9IHJlc3VsdHMgfHwgdGhpcy5vcmdzVXNlcnNNaXNzaW9ucztcclxuICAgIH1cclxuXHJcbiAgICBvbkFkZEluRXhpc3RpbmdPcmcoKSB7XHJcbiAgICAgICAgdGhpcy5oaWRlTGlzdCA9IHRydWU7XHJcbiAgICAgICAgdGhpcy5pc0FkZGluZ1RvRXhpc3RpbmdPcmcgPSB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBlbmN5cHRlZCBsaW5rIGFuZCBzZXRzIGl0IGZvciBndWVzdExpbmsgZm9yIFNwYWNlLlxyXG4gICAgICogQHBhcmFtIG1pc1xyXG4gICAgICovXHJcbiAgICBvblNldEZvclNoYXJlYWJsZUxpbmsodXNlcjogUHJvZmlsZUVudGl0eSwgbWlzc2lvbjogTWlzc2lvbikge1xyXG4gICAgICAgIGNvbnN0IG1vZGFsUmVmZXJlbmNlID0gdGhpcy5tb2RhbFNlcnZpY2Uub3BlbihHdWVzdExpbmtDb21wb25lbnQpO1xyXG4gICAgICAgIG1vZGFsUmVmZXJlbmNlLmNvbXBvbmVudEluc3RhbmNlLnVzZXJuYW1lID0gdXNlci5lbWFpbDtcclxuICAgICAgICBtb2RhbFJlZmVyZW5jZS5jb21wb25lbnRJbnN0YW5jZS5zcGFjZUlEID0gbWlzc2lvbi5zcGFjZUlEO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIG9uQ2xlYXJUb2tlbih1c2VyKSB7XHJcbiAgICAgICAgYXdhaXQgdGhpcy51c2VyU2VydmljZS5jbGVhclVzZXJUb2tlbih1c2VyLnVzZXIuaWQpO1xyXG4gICAgICAgIGNvbnN0IGZpcnN0TWVzc2FnZSA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ2ZpcnN0VG9rZW5NZXNzYWdlJyk7XHJcbiAgICAgICAgY29uc3Qgc2Vjb25kTWVzc2FnZSA9IHRoaXMudHJhbnNsYXRlLmluc3RhbnQoJ3NlY29uZFRva2VuTWVzc2FnZScpO1xyXG4gICAgICAgIGFsZXJ0KGZpcnN0TWVzc2FnZSArIHVzZXIudXNlci5kaXNwbGF5TmFtZSArIHNlY29uZE1lc3NhZ2UpO1xyXG4gICAgfVxyXG5cclxuICAgIGdldFN0cmluZ05vU3BhY2UoZGF0YSk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIGRhdGEucmVwbGFjZSgvXFxzL2csICcnKTtcclxuICAgIH1cclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwiZGFzaGJvYXJkLXRhYlwiPlxyXG4gIDxkaXYgY2xhc3M9XCJoZWFkZXItZGFzaGJvYXJkLXRhYlwiPlxyXG4gICAgPGgzPnt7J1VzZXJzJyB8IHRyYW5zbGF0ZX19PC9oMz5cclxuICAgIDwhLS0gPGFwcC1zZWFyY2gtYmFyICpuZ0lmPVwiIWhpZGVMaXN0XCIgW3NlYXJjaGFibGVdPVwib3Jnc1VzZXJzTWlzc2lvbnNcIiBvYmplY3RUeXBlPVwiVVNFUlwiXHJcbiAgICAgICAgKHNlYXJjaEV2ZW50KT1cImFwcGx5UmVzdWx0c1NlYXJjaEJhcigkZXZlbnQpXCI+XHJcbiAgICAgIDwvYXBwLXNlYXJjaC1iYXI+IC0tPlxyXG4gICAgPGhyPlxyXG4gIDwvZGl2PlxyXG4gIDxkaXYgY2xhc3M9XCJyb3dcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtOCBjb2wtbGctNlwiPlxyXG4gICAgICA8ZGl2IGNsYXNzPVwicm93IG1sLTAgbWItMlwiICpuZ0lmPVwiIWhpZGVMaXN0XCI+XHJcbiAgICAgICAgPGJ1dHRvbiBjbGFzcz1cImJ0biBidG4tb3V0bGluZS1wcmltYXJ5IHJvdW5kZWQtcGlsbCBhZGQtYnV0dG9uXCIgKm5nSWY9XCIhaXNHdWlkZVwiIChjbGljayk9XCJvbkFkZE9yZygpXCI+XHJcbiAgICAgICAgICB7eydBZGQgdXNlciB0byBuZXcgb3JnYW5pc2F0aW9uJyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1jZW50ZXJcIiAqbmdJZj1cImxvYWRpbmdcIj5cclxuICAgICAgICA8bGliLWxvYWRlcj48L2xpYi1sb2FkZXI+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8ZGl2ICpuZ0lmPVwiIWhpZGVMaXN0XCI+XHJcbiAgICAgICAgPHVsIGNsYXNzPVwibGlzdC1ncm91cCBsaXN0LWdyb3VwLWZsdXNoXCIgKm5nSWY9XCJmaWx0ZXJlZE9yZ3NVc2Vyc01pc3Npb25zXCIgZGF0YS10ZXN0aWQ9XCJtaXNzaW9uLW9yZ2FuaXNhdGlvbi1saXN0XCI+XHJcbiAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gbGlzdC1ncm91cC1pdGVtLWFjdGlvblwiICpuZ0Zvcj1cImxldCBvIG9mIGZpbHRlcmVkT3Jnc1VzZXJzTWlzc2lvbnNcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1jZW50ZXIgZm9udC13ZWlnaHQtYm9sZFwiXHJcbiAgICAgICAgICAgICAgbmdiVG9vbHRpcD1cIlNlZSBkZXRhaWxzIGFuZCB1c2Vyc1wiIHN0eWxlPVwiY3Vyc29yOiBwb2ludGVyO1wiIChjbGljayk9XCJvblRvZ2dsZURldGFpbE9yZyhvLm9yZy5pZCwgby5vcmcpXCI+XHJcbiAgICAgICAgICAgICAge3tvLm9yZy5uYW1lfX0gPHNtYWxsICpuZ0lmPVwiby5vcmcuaWQgPT0gY3VycmVudE9yZy5pZFwiPih7eydNeSBvcmdhbmlzYXRpb24nIHwgdHJhbnNsYXRlfX0pPC9zbWFsbD5cclxuICAgICAgICAgICAgICA8c21hbGwgKm5nSWY9XCJpc1NQICYmIGNsaWVudHNTUC5pbmNsdWRlcyhvLm9yZy5pZClcIj4oe3snQ2xpZW50IG9mIFNtYXJ0ZXJQbGFuJyB8IHRyYW5zbGF0ZX19KTwvc21hbGw+XHJcbiAgICAgICAgICAgICAgPHNtYWxsICpuZ0lmPVwiaXNTUCAmJiBnZXRPcmRlcmVkT3JnKG8ub3JnLmlkKVwiPih7eydDbGllbnQgb2YgJyB8IHRyYW5zbGF0ZX19XHJcbiAgICAgICAgICAgICAgICB7e2dldE9yZGVyZWRPcmcoby5vcmcuaWQpfX0pPC9zbWFsbD5cclxuICAgICAgICAgICAgICA8bGliLWNoZXZyb24gW2NvbmRpdGlvblNob3dpbmddPVwiZGV0YWlsc09yZz09by5vcmcuaWRcIiAgW25nQ2xhc3NdPVwiW2dldFN0cmluZ05vU3BhY2Uoby5vcmcubmFtZSldXCI+PC9saWItY2hldnJvbj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaXNzaW9uc1wiICpuZ0lmPVwiZGV0YWlsc09yZz09by5vcmcuaWRcIj5cclxuICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSdkLWZsZXgnPlxyXG4gICAgICAgICAgICAgICAgPGJ1dHRvbiBkYXRhLXRlc3RpZD1cInVzZXItbmV3LWJ0blwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsIG10LTMgbWItM1wiIChjbGljayk9XCJvbkFkZChvLm9yZylcIj57eydBZGQgdXNlcicgfFxyXG4gICAgICAgICAgICAgICAgICB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgICA8dWwgY2xhc3M9XCJsaXN0LWdyb3VwIGxpc3QtZ3JvdXAtZmx1c2hcIiBkYXRhLXRlc3RpZD1cIm1pc3Npb24tdXNlci1saXN0XCI+XHJcbiAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gbGlzdC1ncm91cC1pdGVtLWFjdGlvblwiICpuZ0Zvcj1cImxldCBhIG9mIG8udXNlcnNcIlxyXG4gICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25Ub2dnbGVEZXRhaWxVc2VyKGEudXNlci5pZClcIj5cclxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICB7e2EudXNlci5kaXNwbGF5TmFtZX19XHJcbiAgICAgICAgICAgICAgICAgICAgPGxpYi1jaGV2cm9uIFtjb25kaXRpb25TaG93aW5nXT1cImRldGFpbHNVc2VyPT1hLnVzZXIuaWRcIiBbbmdDbGFzc109XCJbZ2V0U3RyaW5nTm9TcGFjZShhLnVzZXIuZGlzcGxheU5hbWUpXVwiPjwvbGliLWNoZXZyb24+XHJcbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cImRldGFpbHNVc2VyPT1hLnVzZXIuaWRcIj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibWwtM1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1jZW50ZXIgbXQtM1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB7eydFbWFpbCcgfCB0cmFuc2xhdGV9fToge3thLnVzZXIuZW1haWwgfX1cclxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1jZW50ZXIgbXQtM1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSByb3VuZGVkLXBpbGxcIiBkYXRhLXRlc3RpZD1cIm1pc3Npb24tbmV3LWJ0blwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uQWRkRm9yVXNlcihvLm9yZywgYS51c2VyKVwiPnt7J0FkZCBuZXcgbWlzc2lvbicgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSByb3VuZGVkLXBpbGxcIiAoY2xpY2spPVwib25DbGVhclRva2VuKGEpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAge3snQ2xlYXIgVG9rZW4nIHwgdHJhbnNsYXRlfX08L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJidG4gYnRuLXByaW1hcnkgcm91bmRlZC1waWxsXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25EZWxldGVVc2VyKGEudXNlcilcIj57eydEZWxldGUgdXNlcicgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIGFsaWduLWl0ZW1zLWNlbnRlciBtdC0zXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHt7IGEubWlzc2lvbnMubGVuZ3RoID4gMCA/ICgnQ3VycmVudCBNaXNzaW9ucycgfCB0cmFuc2xhdGUpIDogKCdObyBtaXNzaW9ucycgfCB0cmFuc2xhdGUpfX1cclxuICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDx1bCBjbGFzcz1cImxpc3QtZ3JvdXAgbGlzdC1ncm91cC1mbHVzaFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtXCIgKm5nRm9yPVwibGV0IG1pcyBvZiBhLm1pc3Npb25zXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDx1bCBjbGFzcz1cImxpc3QtZ3JvdXAgbGlzdC1ncm91cC1mbHVzaFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxsaSBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBiZy10cmFuc3BhcmVudFwiICpuZ0lmPVwibWlzLmRlc2NyaXB0aW9uXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eydEZXNjcmlwdGlvbicgfCB0cmFuc2xhdGV9fToge3ttaXMuZGVzY3JpcHRpb259fTwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGJnLXRyYW5zcGFyZW50XCIgKm5nSWY9XCJtaXMudGVtcGxhdGVNaXNzaW9uSURcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7J0F0dGVuZGVlIG9mIHRvdXInIHwgdHJhbnNsYXRlfX06IHt7bWlzLnRlbXBsYXRlTWlzc2lvbi50aXRsZX19PC9saT5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGJnLXRyYW5zcGFyZW50XCI+e3snUm9sZScgfCB0cmFuc2xhdGV9fToge3sgbWlzLnJvbGUgfX08L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxsaSBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBiZy10cmFuc3BhcmVudFwiICpuZ0lmPVwibWlzLmhhc2h0YWdzICYmIG1pcy5oYXNodGFncy5sZW5ndGg+IDBcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7J0hhc2h0YWdzJyB8IHRyYW5zbGF0ZX19OiA8dWwgY2xhc3M9XCJrZXl3b3Jkc0Rpc3BsYXkgbm8tYm9yZGVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJrZXl3b3Jkc2Rpc3BsYXlDb250YWluZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJrZXl3b3Jkc0l0ZW1cIiAqbmdGb3I9XCJsZXQgaGFzaHRhZyBvZiBtaXMuaGFzaHRhZ3NcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGhhc2h0YWcgfCBoYXNodGFnRnJvbUlEIHwgYXN5bmMgfX08L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvdWw+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gYmctdHJhbnNwYXJlbnRcIj57eydMYW5ndWFnZScgfCB0cmFuc2xhdGUgfX06IHt7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaXMubG9jYWxlID8gbWlzLmxvY2FsZSA6ICgnTm90IGFwcGxpY2FibGUnIHwgdHJhbnNsYXRlKX19PC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gYmctdHJhbnNwYXJlbnRcIj57eydBY2Nlc3MgbGV2ZWwnIHwgdHJhbnNsYXRlIH19OiB7e1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWlzLmxldmVsfX08L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxsaSBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBiZy10cmFuc3BhcmVudFwiPnt7J09yZGVyZWQgYnknIHwgdHJhbnNsYXRlIH19OiB7e1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWlzLm9yZGVyZWRPcmdhbmlzYXRpb24ubmFtZX19PC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gYmctdHJhbnNwYXJlbnRcIiAqbmdJZj1cIm1pcy5kb21haW5zXCI+e3snRG9tYWlucycgfCB0cmFuc2xhdGUgfX06XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7e21pcy5kb21haW5zID9cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvbWFpbklkc1RvU3RyaW5nRm9yTWlzc2lvbihtaXMpIDogKFwiTm8gZGF0YVwiIHwgdHJhbnNsYXRlKSB9fTwvbGk+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGJnLXRyYW5zcGFyZW50XCI+e3snQXV0aG9yaXplZCBsb2NhdGlvbicgfCB0cmFuc2xhdGUgfX06XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBtaXMuc3BhY2UgPyBtaXMuc3BhY2UubmFtZSA6IFwiTm8gbG9jYXRpb25cIiB8IHRyYW5zbGF0ZX19PC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gYmctdHJhbnNwYXJlbnRcIj57eydBdXRob3JpemVkIHpvbmUnIHwgdHJhbnNsYXRlIH19OlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgbWlzLnpvbmUgPyBtaXMuem9uZS5uYW1lIDogXCJBbGwgem9uZXMgYWxsb3dlZFwiIHwgdHJhbnNsYXRlfX08L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxsaSBjbGFzcz1cImxpc3QtZ3JvdXAtaXRlbSBiZy10cmFuc3BhcmVudFwiPnt7J1N0YXJ0cycgfCB0cmFuc2xhdGUgfX06XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBtaXMuc3RhcnREYXRlVGltZSA/IChtaXMuc3RhcnREYXRlVGltZSB8IHRpbWVEYXRlU3RyaW5nOiBcImRheV90aW1lX3pvbmVcIiB8IGFzeW5jKSA6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIk5vIGRhdGFcIiB8IHRyYW5zbGF0ZX19LCB7eydFbmRzJyB8IHRyYW5zbGF0ZX19OiB7eyBtaXMuZW5kRGF0ZVRpbWVcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gKG1pcy5lbmREYXRlVGltZSB8IHRpbWVEYXRlU3RyaW5nOiBcImRheV90aW1lX3pvbmVcIiB8IGFzeW5jKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgOiBcIk5vIGRhdGFcIiB8IHRyYW5zbGF0ZX19XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICA8bGkgY2xhc3M9XCJsaXN0LWdyb3VwLWl0ZW0gYmctdHJhbnNwYXJlbnRcIj57eydDcmVhdGVkJyB8IHRyYW5zbGF0ZSB9fTpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IG1pcy5jcmVhdGVkQXQgIHwgdGltZURhdGVTdHJpbmc6IFwiZGF5X3RpbWVfem9uZVwiIHwgYXN5bmMgfX1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L3VsPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWN0aW9uLWJ1dHRvbi1jb250YWluZXJcIiA+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgZGF0YS10ZXN0aWQ9XCJlZGl0LW1pc3Npb24tYnRuXCIgY2xhc3M9XCJidG4gYnRuLW91dGxpbmUtcHJpbWFyeSByb3VuZGVkLXBpbGwgbXItMiBhY3Rpb24tYnV0dG9uXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkVkaXQobWlzKVwiPnt7J0VkaXQnIHxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zbGF0ZX19PC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgKm5nSWY9XCJtaXMucm9sZSA9PT0gJ1ZJU0lUT1InIHx8IG1pcy5yb2xlID09PSAnVklTSVRPUl9NVVNFVU0nXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsIG1yLTIgYWN0aW9uLWJ1dHRvbiBzaGFyZS12aXNpdG9yLWJ1dHRvblwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25TZXRGb3JTaGFyZWFibGVMaW5rKGEudXNlciwgbWlzKVwiPnt7J0dlbmVyYXRlIFNoYXJlYWJsZSBMaW5rJyB8XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1vdXRsaW5lLXByaW1hcnkgcm91bmRlZC1waWxsIGFjdGlvbi1idXR0b25cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uRGVsZXRlTWlzc2lvbihtaXMpXCI+e3snRGVsZXRlJyB8IHRyYW5zbGF0ZX19PC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgPC9saT5cclxuICAgICAgICAgICAgICAgICAgICA8L3VsPlxyXG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvbGk+XHJcbiAgICAgICAgICAgICAgPC91bD5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGxpc3QtZ3JvdXAtaXRlbS1hY3Rpb25cIiAqbmdJZj1cInByb2ZpbGVzV2l0aG91dE1pc3Npb24gJiYgcHJvZmlsZXNXaXRob3V0TWlzc2lvbi5sZW5ndGggPiAwXCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtY2VudGVyIGZvbnQtd2VpZ2h0LWJvbGRcIlxyXG4gICAgICAgICAgICAgIG5nYlRvb2x0aXA9XCJTZWUgZGV0YWlsc1wiIHN0eWxlPVwiY3Vyc29yOiBwb2ludGVyO1wiIChjbGljayk9XCJvblRvZ2dsZURldGFpbE9yZygnLTInLCBudWxsKVwiPlxyXG4gICAgICAgICAgICAgIHt7XCJVc2VycyB3aXRob3V0IG1pc3Npb25zXCIgfCB0cmFuc2xhdGV9fVxyXG4gICAgICAgICAgICAgIDxsaWItY2hldnJvbiBbY29uZGl0aW9uU2hvd2luZ109XCJkZXRhaWxzT3JnPT0nLTInXCI+PC9saWItY2hldnJvbj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJtaXNzaW9uc1wiICpuZ0lmPVwiZGV0YWlsc09yZz09Jy0yJ1wiPlxyXG4gICAgICAgICAgICAgIDx1bCBjbGFzcz1cImxpc3QtZ3JvdXAgbGlzdC1ncm91cC1mbHVzaFwiIGRhdGEtdGVzdGlkPVwibWlzc2lvbi1vcmdhbmlzYXRpb24tbGlzdFwiPlxyXG4gICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibGlzdC1ncm91cC1pdGVtIGxpc3QtZ3JvdXAtaXRlbS1hY3Rpb25cIiAqbmdGb3I9XCJsZXQgcHJvZmlsZSBvZiBwcm9maWxlc1dpdGhvdXRNaXNzaW9uXCIgXHJcbiAgICAgICAgICAgICAgICAoY2xpY2spPVwib25Ub2dnbGVEZXRhaWxVc2VyKHByb2ZpbGUuaWQpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBqdXN0aWZ5LWNvbnRlbnQtYmV0d2VlbiBhbGlnbi1pdGVtcy1jZW50ZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICB7e3Byb2ZpbGUuZGlzcGxheU5hbWV9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxsaWItY2hldnJvbiBbY29uZGl0aW9uU2hvd2luZ109XCJkZXRhaWxzVXNlcj09cHJvZmlsZS5pZFwiIFtuZ0NsYXNzXT1cIltnZXRTdHJpbmdOb1NwYWNlKHByb2ZpbGUuZGlzcGxheU5hbWUpXVwiPjwvbGliLWNoZXZyb24+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiAqbmdJZj1cImRldGFpbHNVc2VyPT1wcm9maWxlLmlkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm1sLTNcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWJldHdlZW4gYWxpZ24taXRlbXMtY2VudGVyIG10LTNcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3snRW1haWwnIHwgdHJhbnNsYXRlfX06IHt7cHJvZmlsZS5lbWFpbCB9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZC1mbGV4IGp1c3RpZnktY29udGVudC1iZXR3ZWVuIGFsaWduLWl0ZW1zLWNlbnRlciBtdC0zXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gdHlwZT1cImJ1dHRvblwiIGNsYXNzPVwiYnRuIGJ0bi1wcmltYXJ5IHJvdW5kZWQtcGlsbFwiIGRhdGEtdGVzdGlkPVwibWlzc2lvbi1uZXctYnRuXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uQWRkRm9yVXNlcihjdXJyZW50T3JnLCBwcm9maWxlKVwiPnt7J0FkZCBuZXcgbWlzc2lvbicgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBjbGFzcz1cImJ0biBidG4tcHJpbWFyeSByb3VuZGVkLXBpbGxcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkRlbGV0ZVVzZXIocHJvZmlsZSlcIj57eydEZWxldGUgdXNlcicgfCB0cmFuc2xhdGV9fTwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8L2xpPlxyXG4gICAgICAgICAgICAgIDwvdWw+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgPC9saT5cclxuICAgICAgICA8L3VsPlxyXG4gICAgICA8L2Rpdj5cclxuXHJcbiAgICAgIDxkaXYgKm5nSWY9XCJjcmVhdGVcIj5cclxuICAgICAgICA8bGliLXVzZXItbWlzc2lvbi1mb3JtIFthZGRUb09yZ2FuaXNhdGlvbl09XCJhZGRUb09yZ1wiIFtjdXJyZW50T3JnXT1cImN1cnJlbnRPcmdcIiBbaXNTUF09XCJpc1NQXCJcclxuICAgICAgICAgIChhZGRlZCk9XCJ1c2VyQWRkZWQoJGV2ZW50KVwiPlxyXG4gICAgICAgIDwvbGliLXVzZXItbWlzc2lvbi1mb3JtPlxyXG4gICAgICA8L2Rpdj5cclxuICAgICAgPGRpdiAqbmdJZj1cImVkaXRcIj5cclxuICAgICAgICA8bGliLWZvcm0tbWlzc2lvbiBbbWlzc2lvblRvRWRpdF09XCJtaXNzaW9uVG9FZGl0XCIgW2N1cnJlbnRVc2VyT3JnYW5pc2F0aW9uXT1cImN1cnJlbnRPcmdcIiBbaXNTUF09XCJpc1NQXCJcclxuICAgICAgICAgIChhZGRlZE1pc3Npb25JbnB1dCk9XCJvbk1pc3Npb25FZGl0ZWQoJGV2ZW50KVwiPjwvbGliLWZvcm0tbWlzc2lvbj5cclxuICAgICAgPC9kaXY+XHJcbiAgICAgIDxkaXYgKm5nSWY9XCJjcmVhdGVGb3JFeGlzdGluZ1VzZXJcIj5cclxuICAgICAgICA8bGliLWZvcm0tbWlzc2lvbiBbb3JnYW5pc2F0aW9uRm9yTWlzc2lvbl09XCJhZGRUb09yZ1wiIFtjdXJyZW50VXNlck9yZ2FuaXNhdGlvbl09XCJjdXJyZW50T3JnXCIgW2lzU1BdPVwiaXNTUFwiXHJcbiAgICAgICAgICBbdXNlckZvck1pc3Npb25JRF09XCJ1c2VyRm9yQWRkaW5nTWlzc2lvbi5pZFwiIChhZGRlZE1pc3Npb25JbnB1dCk9XCJvbk1pc3Npb25DcmVhdGVkKCRldmVudClcIj5cclxuICAgICAgICA8L2xpYi1mb3JtLW1pc3Npb24+XHJcbiAgICAgIDwvZGl2PlxyXG4gICAgICA8ZGl2ICpuZ0lmPVwiaXNBZGRpbmdPcmcgfHwgaXNBZGRpbmdUb0V4aXN0aW5nT3JnXCI+XHJcbiAgICAgICAgPGxpYi1mb3JtLW9yZ2FuaXNhdGlvbiBbY3VycmVudE9yZ109XCJjdXJyZW50T3JnXCIgW2N1cnJlbnRVc2VyXT1cIm1lXCIgW2V4aXN0aW5nXT1cImlzQWRkaW5nVG9FeGlzdGluZ09yZ1wiXHJcbiAgICAgICAgICAoYWRkZWQpPVwib3JnQWRkZWQoJGV2ZW50KVwiPjwvbGliLWZvcm0tb3JnYW5pc2F0aW9uPlxyXG4gICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG5cclxuICAgIDxkaXYgY2xhc3M9XCJjb2wtbWQtNCBjb2wtbGctNlwiICpuZ0lmPVwib3JnU2VsZWN0ZWREZXRhaWxzICYmICFpc0d1aWRlXCI+XHJcbiAgICAgIDxsaWItZGV0YWlsLW9yZ2FuaXNhdGlvbiBbb3JnXT1cIm9yZ1NlbGVjdGVkRGV0YWlsc1wiIFtjdXJyZW50T3JnXT1cImN1cnJlbnRPcmdcIiBbaXNTUF09XCJpc1NQXCJcclxuICAgICAgICAob3JnQ2hhbmdlZCk9J29yZ0FkZGVkKCRldmVudCknPjwvbGliLWRldGFpbC1vcmdhbmlzYXRpb24+XHJcbiAgICA8L2Rpdj5cclxuICA8L2Rpdj5cclxuPC9kaXY+Il19