@valtimo/task 11.3.1 → 12.0.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 (55) hide show
  1. package/esm2022/lib/components/assign-user-to-task/assign-user-to-task.component.mjs +122 -0
  2. package/esm2022/lib/components/task-detail-modal/task-detail-modal.component.mjs +202 -0
  3. package/esm2022/lib/components/task-list/task-list.component.mjs +287 -0
  4. package/esm2022/lib/models/index.mjs +2 -2
  5. package/esm2022/lib/models/task-definition.model.mjs +2 -2
  6. package/esm2022/lib/models/task-list.model.mjs +8 -14
  7. package/esm2022/lib/models/task.model.mjs +2 -2
  8. package/esm2022/lib/services/index.mjs +20 -0
  9. package/esm2022/lib/services/task-list-column.service.mjs +192 -0
  10. package/esm2022/lib/services/task-list-pagination.service.mjs +74 -0
  11. package/esm2022/lib/services/task-list-sort.service.mjs +90 -0
  12. package/esm2022/lib/services/task-list.service.mjs +60 -0
  13. package/esm2022/lib/services/task.service.mjs +94 -0
  14. package/esm2022/lib/task-permissions.mjs +2 -2
  15. package/esm2022/lib/task-routing.module.mjs +7 -7
  16. package/esm2022/lib/task.module.mjs +23 -17
  17. package/esm2022/public_api.mjs +6 -6
  18. package/fesm2022/valtimo-task.mjs +749 -316
  19. package/fesm2022/valtimo-task.mjs.map +1 -1
  20. package/lib/{assign-user-to-task → components/assign-user-to-task}/assign-user-to-task.component.d.ts +7 -7
  21. package/lib/components/assign-user-to-task/assign-user-to-task.component.d.ts.map +1 -0
  22. package/lib/{task-detail-modal → components/task-detail-modal}/task-detail-modal.component.d.ts +3 -4
  23. package/lib/components/task-detail-modal/task-detail-modal.component.d.ts.map +1 -0
  24. package/lib/components/task-list/task-list.component.d.ts +65 -0
  25. package/lib/components/task-list/task-list.component.d.ts.map +1 -0
  26. package/lib/models/task-list.model.d.ts +45 -8
  27. package/lib/models/task-list.model.d.ts.map +1 -1
  28. package/lib/models/task.model.d.ts +22 -1
  29. package/lib/models/task.model.d.ts.map +1 -1
  30. package/lib/services/index.d.ts +5 -0
  31. package/lib/services/index.d.ts.map +1 -0
  32. package/lib/services/task-list-column.service.d.ts +27 -0
  33. package/lib/services/task-list-column.service.d.ts.map +1 -0
  34. package/lib/services/task-list-pagination.service.d.ts +20 -0
  35. package/lib/services/task-list-pagination.service.d.ts.map +1 -0
  36. package/lib/services/task-list-sort.service.d.ts +23 -0
  37. package/lib/services/task-list-sort.service.d.ts.map +1 -0
  38. package/lib/services/task-list.service.d.ts +23 -0
  39. package/lib/services/task-list.service.d.ts.map +1 -0
  40. package/lib/{task.service.d.ts → services/task.service.d.ts} +9 -8
  41. package/lib/services/task.service.d.ts.map +1 -0
  42. package/lib/task.module.d.ts +5 -5
  43. package/lib/task.module.d.ts.map +1 -1
  44. package/package.json +7 -6
  45. package/public_api.d.ts +4 -4
  46. package/public_api.d.ts.map +1 -1
  47. package/esm2022/lib/assign-user-to-task/assign-user-to-task.component.mjs +0 -122
  48. package/esm2022/lib/task-detail-modal/task-detail-modal.component.mjs +0 -219
  49. package/esm2022/lib/task-list/task-list.component.mjs +0 -259
  50. package/esm2022/lib/task.service.mjs +0 -72
  51. package/lib/assign-user-to-task/assign-user-to-task.component.d.ts.map +0 -1
  52. package/lib/task-detail-modal/task-detail-modal.component.d.ts.map +0 -1
  53. package/lib/task-list/task-list.component.d.ts +0 -54
  54. package/lib/task-list/task-list.component.d.ts.map +0 -1
  55. package/lib/task.service.d.ts.map +0 -1
@@ -0,0 +1,122 @@
1
+ /*
2
+ * Copyright 2015-2024 Ritense BV, the Netherlands.
3
+ *
4
+ * Licensed under EUPL, Version 1.2 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" basis,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { Component, EventEmitter, Input, Output, } from '@angular/core';
17
+ import { BehaviorSubject, combineLatest, Subscription, take, tap } from 'rxjs';
18
+ import * as i0 from "@angular/core";
19
+ import * as i1 from "../../services";
20
+ import * as i2 from "@angular/common";
21
+ import * as i3 from "@valtimo/components";
22
+ import * as i4 from "@ngx-translate/core";
23
+ export class AssignUserToTaskComponent {
24
+ constructor(taskService) {
25
+ this.taskService = taskService;
26
+ this.assignmentOfTaskChanged = new EventEmitter();
27
+ this.assignedIdOnServer$ = new BehaviorSubject(null);
28
+ this.assignedUserFullName$ = new BehaviorSubject(null);
29
+ this.candidateUsersForTask$ = new BehaviorSubject(undefined);
30
+ this.disabled$ = new BehaviorSubject(true);
31
+ this.userIdToAssign = null;
32
+ this._subscriptions = new Subscription();
33
+ }
34
+ ngOnInit() {
35
+ this._subscriptions.add(this.taskService.getCandidateUsers(this.taskId).subscribe(candidateUsers => {
36
+ this.candidateUsersForTask$.next(candidateUsers);
37
+ if (this.assigneeId) {
38
+ this.assignedIdOnServer$.next(this.assigneeId);
39
+ this.userIdToAssign = this.assigneeId;
40
+ this.assignedUserFullName$.next(this.getAssignedUserName(candidateUsers, this.assigneeId));
41
+ }
42
+ this.enable();
43
+ }));
44
+ }
45
+ ngOnChanges(changes) {
46
+ this.candidateUsersForTask$.pipe(take(1)).subscribe(candidateUsers => {
47
+ const currentUserId = changes.assigneeId?.currentValue || this.assigneeId;
48
+ this.assignedIdOnServer$.next(currentUserId || null);
49
+ this.userIdToAssign = currentUserId || null;
50
+ this.assignedUserFullName$.next(this.getAssignedUserName(candidateUsers ?? [], currentUserId));
51
+ });
52
+ }
53
+ ngOnDestroy() {
54
+ this._subscriptions.unsubscribe();
55
+ }
56
+ assignTask(userId) {
57
+ this.disable();
58
+ combineLatest([
59
+ this.candidateUsersForTask$,
60
+ this.taskService.assignTask(this.taskId, { assignee: userId }),
61
+ ])
62
+ .pipe(take(1), tap(([candidateUsers]) => {
63
+ this.userIdToAssign = userId;
64
+ this.assignedIdOnServer$.next(userId);
65
+ this.assignedUserFullName$.next(this.getAssignedUserName(candidateUsers ?? [], userId));
66
+ this.emitChange();
67
+ this.enable();
68
+ }))
69
+ .subscribe();
70
+ }
71
+ unassignTask() {
72
+ this.disable();
73
+ this.taskService
74
+ .unassignTask(this.taskId)
75
+ .pipe(tap(() => {
76
+ this.clear();
77
+ this.emitChange();
78
+ this.enable();
79
+ }))
80
+ .subscribe();
81
+ }
82
+ getAssignedUserName(users, userId) {
83
+ if (users && userId) {
84
+ const findUser = users.find(user => user.id === userId);
85
+ return findUser ? findUser.label : userId;
86
+ }
87
+ return userId || '-';
88
+ }
89
+ mapUsersForDropdown(users) {
90
+ return (users &&
91
+ users
92
+ .map(user => ({ ...user, lastName: user.lastName?.split(' ').splice(-1)[0] || '' }))
93
+ .sort((a, b) => a.lastName.localeCompare(b.lastName))
94
+ .map(user => ({ text: user.label, id: user.id })));
95
+ }
96
+ clear() {
97
+ this.assignedIdOnServer$.next(null);
98
+ this.userIdToAssign = null;
99
+ }
100
+ emitChange() {
101
+ this.assignmentOfTaskChanged.emit();
102
+ }
103
+ enable() {
104
+ this.disabled$.next(false);
105
+ }
106
+ disable() {
107
+ this.disabled$.next(true);
108
+ }
109
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: AssignUserToTaskComponent, deps: [{ token: i1.TaskService }], target: i0.ɵɵFactoryTarget.Component }); }
110
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.3", type: AssignUserToTaskComponent, selector: "valtimo-assign-user-to-task", inputs: { taskId: "taskId", assigneeId: "assigneeId" }, outputs: { assignmentOfTaskChanged: "assignmentOfTaskChanged" }, usesOnChanges: true, ngImport: i0, template: "<!--\n ~ Copyright 2015-2024 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<ng-container\n *ngIf=\"{\n candidateUsers: candidateUsersForTask$ | async,\n disabled: disabled$ | async,\n idOnServer: assignedIdOnServer$ | async\n } as obs\"\n>\n <div class=\"container-fluid\">\n <div class=\"row mt-2 mb-2\">\n <div class=\"col-12 pl-0 d-flex flex-row align-items-center\">\n <valtimo-searchable-dropdown-select\n *ngIf=\"obs.candidateUsers; else loading\"\n [style]=\"'underlinedText'\"\n [items]=\"mapUsersForDropdown(obs.candidateUsers)\"\n [buttonText]=\"'assignTask.header' | translate\"\n [searchText]=\"'interface.typeToSearch' | translate\"\n [noResultsText]=\"'interface.noSearchResults' | translate\"\n [disabled]=\"obs.disabled\"\n [selectedText]=\"'assignTask.assignedTo' | translate\"\n [selectedTextValue]=\"assignedUserFullName$ | async\"\n [clearSelectionButtonTitle]=\"'assignTask.remove' | translate\"\n [hasSelection]=\"userIdToAssign === obs.idOnServer && obs.idOnServer !== null\"\n [width]=\"250\"\n (itemSelected)=\"assignTask($event)\"\n (clearSelection)=\"unassignTask()\"\n >\n </valtimo-searchable-dropdown-select>\n </div>\n </div>\n </div>\n</ng-container>\n\n<ng-template #loading>\n <h5>\n <b>{{ 'assignTask.fetchingUsers' | translate }}</b>\n </h5>\n</ng-template>\n", styles: [".container-fluid{color:#959595}i{font-size:13px}\n/*!\n * Copyright 2015-2024 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.SearchableDropdownSelectComponent, selector: "valtimo-searchable-dropdown-select", inputs: ["style", "items", "buttonText", "searchText", "noResultsText", "disabled", "selectedText", "selectedTextValue", "clearSelectionButtonTitle", "hasSelection", "width", "hasPermission", "showClearSelection"], outputs: ["itemSelected", "clearSelection"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }, { kind: "pipe", type: i4.TranslatePipe, name: "translate" }] }); }
111
+ }
112
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: AssignUserToTaskComponent, decorators: [{
113
+ type: Component,
114
+ args: [{ selector: 'valtimo-assign-user-to-task', template: "<!--\n ~ Copyright 2015-2024 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<ng-container\n *ngIf=\"{\n candidateUsers: candidateUsersForTask$ | async,\n disabled: disabled$ | async,\n idOnServer: assignedIdOnServer$ | async\n } as obs\"\n>\n <div class=\"container-fluid\">\n <div class=\"row mt-2 mb-2\">\n <div class=\"col-12 pl-0 d-flex flex-row align-items-center\">\n <valtimo-searchable-dropdown-select\n *ngIf=\"obs.candidateUsers; else loading\"\n [style]=\"'underlinedText'\"\n [items]=\"mapUsersForDropdown(obs.candidateUsers)\"\n [buttonText]=\"'assignTask.header' | translate\"\n [searchText]=\"'interface.typeToSearch' | translate\"\n [noResultsText]=\"'interface.noSearchResults' | translate\"\n [disabled]=\"obs.disabled\"\n [selectedText]=\"'assignTask.assignedTo' | translate\"\n [selectedTextValue]=\"assignedUserFullName$ | async\"\n [clearSelectionButtonTitle]=\"'assignTask.remove' | translate\"\n [hasSelection]=\"userIdToAssign === obs.idOnServer && obs.idOnServer !== null\"\n [width]=\"250\"\n (itemSelected)=\"assignTask($event)\"\n (clearSelection)=\"unassignTask()\"\n >\n </valtimo-searchable-dropdown-select>\n </div>\n </div>\n </div>\n</ng-container>\n\n<ng-template #loading>\n <h5>\n <b>{{ 'assignTask.fetchingUsers' | translate }}</b>\n </h5>\n</ng-template>\n", styles: [".container-fluid{color:#959595}i{font-size:13px}\n/*!\n * Copyright 2015-2024 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
115
+ }], ctorParameters: () => [{ type: i1.TaskService }], propDecorators: { taskId: [{
116
+ type: Input
117
+ }], assigneeId: [{
118
+ type: Input
119
+ }], assignmentOfTaskChanged: [{
120
+ type: Output
121
+ }] } });
122
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXNzaWduLXVzZXItdG8tdGFzay5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy92YWx0aW1vL3Rhc2svc3JjL2xpYi9jb21wb25lbnRzL2Fzc2lnbi11c2VyLXRvLXRhc2svYXNzaWduLXVzZXItdG8tdGFzay5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy92YWx0aW1vL3Rhc2svc3JjL2xpYi9jb21wb25lbnRzL2Fzc2lnbi11c2VyLXRvLXRhc2svYXNzaWduLXVzZXItdG8tdGFzay5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE9BQU8sRUFDTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLEtBQUssRUFJTCxNQUFNLEdBRVAsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUFDLGVBQWUsRUFBRSxhQUFhLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUMsTUFBTSxNQUFNLENBQUM7Ozs7OztBQVM3RSxNQUFNLE9BQU8seUJBQXlCO0lBWXBDLFlBQW9CLFdBQXdCO1FBQXhCLGdCQUFXLEdBQVgsV0FBVyxDQUFhO1FBVGxDLDRCQUF1QixHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFFaEQsd0JBQW1CLEdBQUcsSUFBSSxlQUFlLENBQWdCLElBQUksQ0FBQyxDQUFDO1FBQy9ELDBCQUFxQixHQUFHLElBQUksZUFBZSxDQUFnQixJQUFJLENBQUMsQ0FBQztRQUNqRSwyQkFBc0IsR0FBRyxJQUFJLGVBQWUsQ0FBMEIsU0FBUyxDQUFDLENBQUM7UUFDakYsY0FBUyxHQUFHLElBQUksZUFBZSxDQUFVLElBQUksQ0FBQyxDQUFDO1FBQy9DLG1CQUFjLEdBQWtCLElBQUksQ0FBQztRQUNwQyxtQkFBYyxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7SUFFRyxDQUFDO0lBRXpD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SUFDN0IsQ0FBQztJQUVPLFVBQVU7UUFDaEIsSUFBSSxDQUFDLHVCQUF1QixDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3RDLENBQUM7SUFFTyxNQUFNO1FBQ1osSUFBSSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDN0IsQ0FBQztJQUVPLE9BQU87UUFDYixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUM1QixDQUFDOzhHQS9HVSx5QkFBeUI7a0dBQXpCLHlCQUF5QixpTkNuQ3RDLDJnRUFxREE7OzJGRGxCYSx5QkFBeUI7a0JBTHJDLFNBQVM7K0JBQ0UsNkJBQTZCO2dGQUs5QixNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csVUFBVTtzQkFBbEIsS0FBSztnQkFDSSx1QkFBdUI7c0JBQWhDLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IDIwMTUtMjAyNCBSaXRlbnNlIEJWLCB0aGUgTmV0aGVybGFuZHMuXG4gKlxuICogTGljZW5zZWQgdW5kZXIgRVVQTCwgVmVyc2lvbiAxLjIgKHRoZSBcIkxpY2Vuc2VcIik7XG4gKiB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuXG4gKiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAqXG4gKiBodHRwczovL2pvaW51cC5lYy5ldXJvcGEuZXUvY29sbGVjdGlvbi9ldXBsL2V1cGwtdGV4dC1ldXBsLTEyXG4gKlxuICogVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICogZGlzdHJpYnV0ZWQgdW5kZXIgdGhlIExpY2Vuc2UgaXMgZGlzdHJpYnV0ZWQgb24gYW4gXCJBUyBJU1wiIGJhc2lzLFxuICogV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gKiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gKiBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS5cbiAqL1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFNpbXBsZUNoYW5nZXMsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtEcm9wZG93bkl0ZW19IGZyb20gJ0B2YWx0aW1vL2NvbXBvbmVudHMnO1xuaW1wb3J0IHtCZWhhdmlvclN1YmplY3QsIGNvbWJpbmVMYXRlc3QsIFN1YnNjcmlwdGlvbiwgdGFrZSwgdGFwfSBmcm9tICdyeGpzJztcbmltcG9ydCB7VGFza1NlcnZpY2V9IGZyb20gJy4uLy4uL3NlcnZpY2VzJztcbmltcG9ydCB7TmFtZWRVc2VyfSBmcm9tICdAdmFsdGltby9jb25maWcnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWx0aW1vLWFzc2lnbi11c2VyLXRvLXRhc2snLFxuICB0ZW1wbGF0ZVVybDogJy4vYXNzaWduLXVzZXItdG8tdGFzay5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2Fzc2lnbi11c2VyLXRvLXRhc2suY29tcG9uZW50LnNjc3MnXSxcbn0pXG5leHBvcnQgY2xhc3MgQXNzaWduVXNlclRvVGFza0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzLCBPbkRlc3Ryb3kge1xuICBASW5wdXQoKSB0YXNrSWQ6IHN0cmluZztcbiAgQElucHV0KCkgYXNzaWduZWVJZDogc3RyaW5nO1xuICBAT3V0cHV0KCkgYXNzaWdubWVudE9mVGFza0NoYW5nZWQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgcHVibGljIGFzc2lnbmVkSWRPblNlcnZlciQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZyB8IG51bGw+KG51bGwpO1xuICBwdWJsaWMgYXNzaWduZWRVc2VyRnVsbE5hbWUkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxzdHJpbmcgfCBudWxsPihudWxsKTtcbiAgcHVibGljIGNhbmRpZGF0ZVVzZXJzRm9yVGFzayQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PE5hbWVkVXNlcltdIHwgdW5kZWZpbmVkPih1bmRlZmluZWQpO1xuICBwdWJsaWMgZGlzYWJsZWQkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPih0cnVlKTtcbiAgcHVibGljIHVzZXJJZFRvQXNzaWduOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBfc3Vic2NyaXB0aW9ucyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHRhc2tTZXJ2aWNlOiBUYXNrU2VydmljZSkge31cblxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5fc3Vic2NyaXB0aW9ucy5hZGQoXG4gICAgICB0aGlzLnRhc2tTZXJ2aWNlLmdldENhbmRpZGF0ZVVzZXJzKHRoaXMudGFza0lkKS5zdWJzY3JpYmUoY2FuZGlkYXRlVXNlcnMgPT4ge1xuICAgICAgICB0aGlzLmNhbmRpZGF0ZVVzZXJzRm9yVGFzayQubmV4dChjYW5kaWRhdGVVc2Vycyk7XG4gICAgICAgIGlmICh0aGlzLmFzc2lnbmVlSWQpIHtcbiAgICAgICAgICB0aGlzLmFzc2lnbmVkSWRPblNlcnZlciQubmV4dCh0aGlzLmFzc2lnbmVlSWQpO1xuICAgICAgICAgIHRoaXMudXNlcklkVG9Bc3NpZ24gPSB0aGlzLmFzc2lnbmVlSWQ7XG4gICAgICAgICAgdGhpcy5hc3NpZ25lZFVzZXJGdWxsTmFtZSQubmV4dChcbiAgICAgICAgICAgIHRoaXMuZ2V0QXNzaWduZWRVc2VyTmFtZShjYW5kaWRhdGVVc2VycywgdGhpcy5hc3NpZ25lZUlkKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5lbmFibGUoKTtcbiAgICAgIH0pXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgdGhpcy5jYW5kaWRhdGVVc2Vyc0ZvclRhc2skLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKGNhbmRpZGF0ZVVzZXJzID0+IHtcbiAgICAgIGNvbnN0IGN1cnJlbnRVc2VySWQgPSBjaGFuZ2VzLmFzc2lnbmVlSWQ/LmN1cnJlbnRWYWx1ZSB8fCB0aGlzLmFzc2lnbmVlSWQ7XG4gICAgICB0aGlzLmFzc2lnbmVkSWRPblNlcnZlciQubmV4dChjdXJyZW50VXNlcklkIHx8IG51bGwpO1xuICAgICAgdGhpcy51c2VySWRUb0Fzc2lnbiA9IGN1cnJlbnRVc2VySWQgfHwgbnVsbDtcbiAgICAgIHRoaXMuYXNzaWduZWRVc2VyRnVsbE5hbWUkLm5leHQoXG4gICAgICAgIHRoaXMuZ2V0QXNzaWduZWRVc2VyTmFtZShjYW5kaWRhdGVVc2VycyA/PyBbXSwgY3VycmVudFVzZXJJZClcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5fc3Vic2NyaXB0aW9ucy51bnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcHVibGljIGFzc2lnblRhc2sodXNlcklkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmRpc2FibGUoKTtcbiAgICBjb21iaW5lTGF0ZXN0KFtcbiAgICAgIHRoaXMuY2FuZGlkYXRlVXNlcnNGb3JUYXNrJCxcbiAgICAgIHRoaXMudGFza1NlcnZpY2UuYXNzaWduVGFzayh0aGlzLnRhc2tJZCwge2Fzc2lnbmVlOiB1c2VySWR9KSxcbiAgICBdKVxuICAgICAgLnBpcGUoXG4gICAgICAgIHRha2UoMSksXG4gICAgICAgIHRhcCgoW2NhbmRpZGF0ZVVzZXJzXSkgPT4ge1xuICAgICAgICAgIHRoaXMudXNlcklkVG9Bc3NpZ24gPSB1c2VySWQ7XG4gICAgICAgICAgdGhpcy5hc3NpZ25lZElkT25TZXJ2ZXIkLm5leHQodXNlcklkKTtcbiAgICAgICAgICB0aGlzLmFzc2lnbmVkVXNlckZ1bGxOYW1lJC5uZXh0KHRoaXMuZ2V0QXNzaWduZWRVc2VyTmFtZShjYW5kaWRhdGVVc2VycyA/PyBbXSwgdXNlcklkKSk7XG4gICAgICAgICAgdGhpcy5lbWl0Q2hhbmdlKCk7XG4gICAgICAgICAgdGhpcy5lbmFibGUoKTtcbiAgICAgICAgfSlcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHB1YmxpYyB1bmFzc2lnblRhc2soKTogdm9pZCB7XG4gICAgdGhpcy5kaXNhYmxlKCk7XG4gICAgdGhpcy50YXNrU2VydmljZVxuICAgICAgLnVuYXNzaWduVGFzayh0aGlzLnRhc2tJZClcbiAgICAgIC5waXBlKFxuICAgICAgICB0YXAoKCkgPT4ge1xuICAgICAgICAgIHRoaXMuY2xlYXIoKTtcbiAgICAgICAgICB0aGlzLmVtaXRDaGFuZ2UoKTtcbiAgICAgICAgICB0aGlzLmVuYWJsZSgpO1xuICAgICAgICB9KVxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgpO1xuICB9XG5cbiAgcHVibGljIGdldEFzc2lnbmVkVXNlck5hbWUodXNlcnM6IE5hbWVkVXNlcltdLCB1c2VySWQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKHVzZXJzICYmIHVzZXJJZCkge1xuICAgICAgY29uc3QgZmluZFVzZXIgPSB1c2Vycy5maW5kKHVzZXIgPT4gdXNlci5pZCA9PT0gdXNlcklkKTtcbiAgICAgIHJldHVybiBmaW5kVXNlciA/IGZpbmRVc2VyLmxhYmVsIDogdXNlcklkO1xuICAgIH1cbiAgICByZXR1cm4gdXNlcklkIHx8ICctJztcbiAgfVxuXG4gIHB1YmxpYyBtYXBVc2Vyc0ZvckRyb3Bkb3duKHVzZXJzOiBOYW1lZFVzZXJbXSk6IERyb3Bkb3duSXRlbVtdIHtcbiAgICByZXR1cm4gKFxuICAgICAgdXNlcnMgJiZcbiAgICAgIHVzZXJzXG4gICAgICAgIC5tYXAodXNlciA9PiAoey4uLnVzZXIsIGxhc3ROYW1lOiB1c2VyLmxhc3ROYW1lPy5zcGxpdCgnICcpLnNwbGljZSgtMSlbMF0gfHwgJyd9KSlcbiAgICAgICAgLnNvcnQoKGEsIGIpID0+IGEubGFzdE5hbWUubG9jYWxlQ29tcGFyZShiLmxhc3ROYW1lKSlcbiAgICAgICAgLm1hcCh1c2VyID0+ICh7dGV4dDogdXNlci5sYWJlbCwgaWQ6IHVzZXIuaWR9KSlcbiAgICApO1xuICB9XG5cbiAgcHJpdmF0ZSBjbGVhcigpOiB2b2lkIHtcbiAgICB0aGlzLmFzc2lnbmVkSWRPblNlcnZlciQubmV4dChudWxsKTtcbiAgICB0aGlzLnVzZXJJZFRvQXNzaWduID0gbnVsbDtcbiAgfVxuXG4gIHByaXZhdGUgZW1pdENoYW5nZSgpOiB2b2lkIHtcbiAgICB0aGlzLmFzc2lnbm1lbnRPZlRhc2tDaGFuZ2VkLmVtaXQoKTtcbiAgfVxuXG4gIHByaXZhdGUgZW5hYmxlKCk6IHZvaWQge1xuICAgIHRoaXMuZGlzYWJsZWQkLm5leHQoZmFsc2UpO1xuICB9XG5cbiAgcHJpdmF0ZSBkaXNhYmxlKCk6IHZvaWQge1xuICAgIHRoaXMuZGlzYWJsZWQkLm5leHQodHJ1ZSk7XG4gIH1cbn1cbiIsIjwhLS1cbiAgfiBDb3B5cmlnaHQgMjAxNS0yMDI0IFJpdGVuc2UgQlYsIHRoZSBOZXRoZXJsYW5kcy5cbiAgflxuICB+IExpY2Vuc2VkIHVuZGVyIEVVUEwsIFZlcnNpb24gMS4yICh0aGUgXCJMaWNlbnNlXCIpO1xuICB+IHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAgfiBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXRcbiAgflxuICB+IGh0dHBzOi8vam9pbnVwLmVjLmV1cm9wYS5ldS9jb2xsZWN0aW9uL2V1cGwvZXVwbC10ZXh0LWV1cGwtMTJcbiAgflxuICB+IFVubGVzcyByZXF1aXJlZCBieSBhcHBsaWNhYmxlIGxhdyBvciBhZ3JlZWQgdG8gaW4gd3JpdGluZywgc29mdHdhcmVcbiAgfiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgYmFzaXMsXG4gIH4gV0lUSE9VVCBXQVJSQU5USUVTIE9SIENPTkRJVElPTlMgT0YgQU5ZIEtJTkQsIGVpdGhlciBleHByZXNzIG9yIGltcGxpZWQuXG4gIH4gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZFxuICB+IGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICAtLT5cblxuPG5nLWNvbnRhaW5lclxuICAqbmdJZj1cIntcbiAgICBjYW5kaWRhdGVVc2VyczogY2FuZGlkYXRlVXNlcnNGb3JUYXNrJCB8IGFzeW5jLFxuICAgIGRpc2FibGVkOiBkaXNhYmxlZCQgfCBhc3luYyxcbiAgICBpZE9uU2VydmVyOiBhc3NpZ25lZElkT25TZXJ2ZXIkIHwgYXN5bmNcbiAgfSBhcyBvYnNcIlxuPlxuICA8ZGl2IGNsYXNzPVwiY29udGFpbmVyLWZsdWlkXCI+XG4gICAgPGRpdiBjbGFzcz1cInJvdyBtdC0yIG1iLTJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMTIgcGwtMCBkLWZsZXggZmxleC1yb3cgYWxpZ24taXRlbXMtY2VudGVyXCI+XG4gICAgICAgIDx2YWx0aW1vLXNlYXJjaGFibGUtZHJvcGRvd24tc2VsZWN0XG4gICAgICAgICAgKm5nSWY9XCJvYnMuY2FuZGlkYXRlVXNlcnM7IGVsc2UgbG9hZGluZ1wiXG4gICAgICAgICAgW3N0eWxlXT1cIid1bmRlcmxpbmVkVGV4dCdcIlxuICAgICAgICAgIFtpdGVtc109XCJtYXBVc2Vyc0ZvckRyb3Bkb3duKG9icy5jYW5kaWRhdGVVc2VycylcIlxuICAgICAgICAgIFtidXR0b25UZXh0XT1cIidhc3NpZ25UYXNrLmhlYWRlcicgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgIFtzZWFyY2hUZXh0XT1cIidpbnRlcmZhY2UudHlwZVRvU2VhcmNoJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgW25vUmVzdWx0c1RleHRdPVwiJ2ludGVyZmFjZS5ub1NlYXJjaFJlc3VsdHMnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICBbZGlzYWJsZWRdPVwib2JzLmRpc2FibGVkXCJcbiAgICAgICAgICBbc2VsZWN0ZWRUZXh0XT1cIidhc3NpZ25UYXNrLmFzc2lnbmVkVG8nIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICBbc2VsZWN0ZWRUZXh0VmFsdWVdPVwiYXNzaWduZWRVc2VyRnVsbE5hbWUkIHwgYXN5bmNcIlxuICAgICAgICAgIFtjbGVhclNlbGVjdGlvbkJ1dHRvblRpdGxlXT1cIidhc3NpZ25UYXNrLnJlbW92ZScgfCB0cmFuc2xhdGVcIlxuICAgICAgICAgIFtoYXNTZWxlY3Rpb25dPVwidXNlcklkVG9Bc3NpZ24gPT09IG9icy5pZE9uU2VydmVyICYmIG9icy5pZE9uU2VydmVyICE9PSBudWxsXCJcbiAgICAgICAgICBbd2lkdGhdPVwiMjUwXCJcbiAgICAgICAgICAoaXRlbVNlbGVjdGVkKT1cImFzc2lnblRhc2soJGV2ZW50KVwiXG4gICAgICAgICAgKGNsZWFyU2VsZWN0aW9uKT1cInVuYXNzaWduVGFzaygpXCJcbiAgICAgICAgPlxuICAgICAgICA8L3ZhbHRpbW8tc2VhcmNoYWJsZS1kcm9wZG93bi1zZWxlY3Q+XG4gICAgICA8L2Rpdj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L25nLWNvbnRhaW5lcj5cblxuPG5nLXRlbXBsYXRlICNsb2FkaW5nPlxuICA8aDU+XG4gICAgPGI+e3sgJ2Fzc2lnblRhc2suZmV0Y2hpbmdVc2VycycgfCB0cmFuc2xhdGUgfX08L2I+XG4gIDwvaDU+XG48L25nLXRlbXBsYXRlPlxuIl19
@@ -0,0 +1,202 @@
1
+ /*
2
+ * Copyright 2015-2024 Ritense BV, the Netherlands.
3
+ *
4
+ * Licensed under EUPL, Version 1.2 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" basis,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ import { Component, EventEmitter, Output, ViewChild, ViewEncapsulation, } from '@angular/core';
17
+ import { FormioOptionsImpl, } from '@valtimo/components';
18
+ import moment from 'moment';
19
+ import { map, take } from 'rxjs/operators';
20
+ import { BehaviorSubject, combineLatest, distinctUntilChanged, Subscription, tap, } from 'rxjs';
21
+ import * as i0 from "@angular/core";
22
+ import * as i1 from "ngx-toastr";
23
+ import * as i2 from "@valtimo/process-link";
24
+ import * as i3 from "@angular/router";
25
+ import * as i4 from "../../services/task.service";
26
+ import * as i5 from "@valtimo/security";
27
+ import * as i6 from "@valtimo/components";
28
+ import * as i7 from "@valtimo/document";
29
+ import * as i8 from "@ngx-translate/core";
30
+ import * as i9 from "@angular/common";
31
+ import * as i10 from "../assign-user-to-task/assign-user-to-task.component";
32
+ moment.locale(localStorage.getItem('langKey') || '');
33
+ export class TaskDetailModalComponent {
34
+ constructor(toastr, processLinkService, router, taskService, userProviderService, modalService, stateService, documentService, translateService) {
35
+ this.toastr = toastr;
36
+ this.processLinkService = processLinkService;
37
+ this.router = router;
38
+ this.taskService = taskService;
39
+ this.userProviderService = userProviderService;
40
+ this.modalService = modalService;
41
+ this.stateService = stateService;
42
+ this.documentService = documentService;
43
+ this.translateService = translateService;
44
+ this.formSubmit = new EventEmitter();
45
+ this.assignmentOfTaskChanged = new EventEmitter();
46
+ this.task$ = new BehaviorSubject(null);
47
+ this.formDefinition$ = new BehaviorSubject(undefined);
48
+ this.formFlowInstanceId$ = new BehaviorSubject(undefined);
49
+ this.page$ = new BehaviorSubject(null);
50
+ this.formioOptions$ = new BehaviorSubject(null);
51
+ this.errorMessage$ = new BehaviorSubject(undefined);
52
+ this.isAdmin$ = this.userProviderService
53
+ .getUserSubject()
54
+ .pipe(map(userIdentity => userIdentity?.roles?.includes('ROLE_ADMIN')));
55
+ this.formIoFormData$ = new BehaviorSubject(null);
56
+ this.loading$ = new BehaviorSubject(true);
57
+ this.taskProcessLinkType$ = new BehaviorSubject(null);
58
+ this.processLinkIsForm$ = this.taskProcessLinkType$.pipe(map(type => type === 'form'));
59
+ this.processLinkIsFormFlow$ = this.taskProcessLinkType$.pipe(map(type => type === 'form-flow'));
60
+ this.processLinkId$ = new BehaviorSubject(undefined);
61
+ this._subscriptions = new Subscription();
62
+ const options = new FormioOptionsImpl();
63
+ options.disableAlerts = true;
64
+ this.formioOptions$.next(options);
65
+ }
66
+ ngAfterViewInit() {
67
+ this._subscriptions.add(this.modal.modalShowing$
68
+ .pipe(distinctUntilChanged(), tap(modalShowing => {
69
+ if (!modalShowing) {
70
+ if (this.formFlow) {
71
+ this.formFlow.saveData();
72
+ }
73
+ }
74
+ }))
75
+ .subscribe());
76
+ }
77
+ ngOnDestroy() {
78
+ this._subscriptions.unsubscribe();
79
+ }
80
+ openTaskDetails(task) {
81
+ this.resetTaskProcessLinkType();
82
+ this.resetFormDefinition();
83
+ this.getTaskProcessLink(task.id);
84
+ this.setDocumentDefinitionNameInService(task);
85
+ const documentId = task.businessKey;
86
+ this.stateService.setDocumentId(documentId);
87
+ this.task$.next(task);
88
+ this.page$.next({
89
+ title: task.name,
90
+ subtitle: `${this.translateService.instant('taskDetail.taskCreated')} ${task.created}`,
91
+ });
92
+ //only load from formlink when process link failed for backwards compatibility
93
+ if (!this.taskProcessLinkType$.getValue()) {
94
+ this.modal.show();
95
+ }
96
+ }
97
+ gotoProcessLinkScreen() {
98
+ this.modal.hide();
99
+ this.router.navigate(['process-links']);
100
+ }
101
+ onChange(event) {
102
+ if (event.data) {
103
+ this.formIoFormData$.next(event.data);
104
+ }
105
+ }
106
+ onSubmit(submission) {
107
+ if (submission.data) {
108
+ this.formIoFormData$.next(submission.data);
109
+ }
110
+ combineLatest([this.processLinkId$, this.taskProcessLinkType$, this.task$])
111
+ .pipe(take(1))
112
+ .subscribe(([processLinkId, taskProcessLinkType, task]) => {
113
+ if (taskProcessLinkType === 'form') {
114
+ if (processLinkId) {
115
+ this.processLinkService
116
+ .submitForm(processLinkId, submission.data, task.businessKey, task.id)
117
+ .subscribe({
118
+ next: (_) => {
119
+ this.completeTask();
120
+ },
121
+ error: errors => {
122
+ this.form.showErrors(errors);
123
+ },
124
+ });
125
+ }
126
+ }
127
+ });
128
+ }
129
+ completeTask() {
130
+ this.task$.pipe(take(1)).subscribe(task => {
131
+ this.toastr.success(`${task.name} ${this.translateService.instant('taskDetail.taskCompleted')}`);
132
+ this.modal.hide();
133
+ this.task$.next(null);
134
+ this.formSubmit.emit();
135
+ });
136
+ }
137
+ resetFormDefinition() {
138
+ this.formDefinition$.next(null);
139
+ this.loading$.next(true);
140
+ }
141
+ getTaskProcessLink(taskId) {
142
+ this.taskService.getTaskProcessLink(taskId).subscribe({
143
+ next: res => {
144
+ if (res != null) {
145
+ switch (res?.type) {
146
+ case 'form':
147
+ this.taskProcessLinkType$.next('form');
148
+ this.processLinkId$.next(res.processLinkId);
149
+ this.setFormDefinitionAndOpenModal(res.properties.prefilledForm);
150
+ break;
151
+ case 'form-flow':
152
+ this.taskProcessLinkType$.next('form-flow');
153
+ this.formFlowInstanceId$.next(res.properties.formFlowInstanceId);
154
+ break;
155
+ }
156
+ this.loading$.next(false);
157
+ }
158
+ },
159
+ error: _ => {
160
+ this.loading$.next(false);
161
+ },
162
+ });
163
+ }
164
+ resetTaskProcessLinkType() {
165
+ this.taskProcessLinkType$.next(null);
166
+ this.processLinkId$.next(null);
167
+ }
168
+ setFormDefinitionAndOpenModal(formDefinition) {
169
+ this.taskProcessLinkType$.next('form');
170
+ this.formDefinition$.next(formDefinition);
171
+ this.modal.show();
172
+ }
173
+ setDocumentDefinitionNameInService(task) {
174
+ this.documentService
175
+ .getProcessDocumentDefinitionFromProcessInstanceId(task.processInstanceId)
176
+ .subscribe(processDocumentDefinition => {
177
+ const documentDefinitionName = processDocumentDefinition.id.documentDefinitionId.name;
178
+ this.modalService.setDocumentDefinitionName(documentDefinitionName);
179
+ this.stateService.setDocumentDefinitionName(documentDefinitionName);
180
+ });
181
+ }
182
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: TaskDetailModalComponent, deps: [{ token: i1.ToastrService }, { token: i2.ProcessLinkService }, { token: i3.Router }, { token: i4.TaskService }, { token: i5.UserProviderService }, { token: i6.ValtimoModalService }, { token: i6.FormIoStateService }, { token: i7.DocumentService }, { token: i8.TranslateService }], target: i0.ɵɵFactoryTarget.Component }); }
183
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.3", type: TaskDetailModalComponent, selector: "valtimo-task-detail-modal", outputs: { formSubmit: "formSubmit", assignmentOfTaskChanged: "assignmentOfTaskChanged" }, viewQueries: [{ propertyName: "form", first: true, predicate: ["form"], descendants: true }, { propertyName: "formFlow", first: true, predicate: ["formFlow"], descendants: true }, { propertyName: "modal", first: true, predicate: ["taskDetailModal"], descendants: true }], ngImport: i0, template: "<!--\n ~ Copyright 2015-2024 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<valtimo-modal\n #taskDetailModal\n *ngIf=\"{\n loading: loading$ | async,\n page: page$ | async,\n task: task$ | async,\n formDefinition: formDefinition$ | async,\n processLinkIsForm: processLinkIsForm$ | async,\n formioOptions: formioOptions$ | async,\n processLinkIsFormFlow: processLinkIsFormFlow$ | async,\n formFlowInstanceId: formFlowInstanceId$ | async,\n errorMessage: errorMessage$ | async\n } as obs\"\n elementId=\"taskDetailModal\"\n [title]=\"obs.page?.title\"\n [subtitle]=\"obs.page?.subtitle\"\n [templateBelowSubtitle]=\"assignUserToTask\"\n>\n <div body *ngIf=\"obs.formDefinition && obs.processLinkIsForm\">\n <valtimo-form-io\n #form\n [form]=\"obs.formDefinition\"\n (submit)=\"onSubmit($event)\"\n (change)=\"onChange($event)\"\n [options]=\"obs.formioOptions\"\n ></valtimo-form-io>\n </div>\n <div body *ngIf=\"obs.processLinkIsFormFlow\">\n <valtimo-form-flow\n #formFlow\n [formIoFormData]=\"formIoFormData$\"\n [formFlowInstanceId]=\"obs.formFlowInstanceId\"\n (formFlowComplete)=\"completeTask()\"\n ></valtimo-form-flow>\n </div>\n <div body *ngIf=\"obs.loading\">\n <div class=\"text-black mb-0 p-3 text-center\">\n {{ 'formManagement.loading' | translate }}\n </div>\n </div>\n <div\n body\n *ngIf=\"\n obs.loading === false && !obs.formDefinition && !obs.formFlowInstanceId && !obs.errorMessage\n \"\n >\n <div class=\"bg-warning text-black mb-0 p-3 text-center\">\n {{\n (isAdmin$ | async)\n ? ('formManagement.noFormDefinitionFoundAdmin' | translate)\n : ('formManagement.noFormDefinitionFoundUser' | translate)\n }}\n </div>\n </div>\n <div body *ngIf=\"obs.errorMessage\">\n <div class=\"bg-danger text-black mb-0 p-3 text-center\">\n {{ obs.errorMessage }}\n </div>\n </div>\n <div footer>\n <div class=\"mb-0 p-3 text-center\" *ngIf=\"!!obs.formDefinition\">\n <button\n class=\"btn btn-secondary btn-space\"\n type=\"button\"\n (click)=\"gotoProcessLinkScreen()\"\n id=\"process-link-button\"\n >\n {{ 'formManagement.gotoProcessLinksButton' | translate }}\n </button>\n </div>\n </div>\n</valtimo-modal>\n\n<ng-template #assignUserToTask>\n <ng-container *ngIf=\"task$ | async as task\">\n <valtimo-assign-user-to-task\n *ngIf=\"task && assignmentOfTaskChanged\"\n [taskId]=\"task.id\"\n [assigneeId]=\"task.assignee\"\n (assignmentOfTaskChanged)=\"assignmentOfTaskChanged.emit()\"\n ></valtimo-assign-user-to-task>\n </ng-container>\n</ng-template>\n", styles: ["#taskDetailModal .formio-component-submit{text-align:right}\n/*!\n * Copyright 2015-2024 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"], dependencies: [{ kind: "directive", type: i9.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i6.FormioComponent, selector: "valtimo-form-io", inputs: ["options", "submission", "form", "readOnly", "formRefresh$"], outputs: ["submit", "change"] }, { kind: "component", type: i6.ModalComponent, selector: "valtimo-modal", inputs: ["elementId", "title", "subtitle", "templateBelowSubtitle", "showFooter"] }, { kind: "component", type: i2.FormFlowComponent, selector: "valtimo-form-flow", inputs: ["formIoFormData", "formFlowInstanceId"], outputs: ["formFlowComplete"] }, { kind: "component", type: i10.AssignUserToTaskComponent, selector: "valtimo-assign-user-to-task", inputs: ["taskId", "assigneeId"], outputs: ["assignmentOfTaskChanged"] }, { kind: "pipe", type: i9.AsyncPipe, name: "async" }, { kind: "pipe", type: i8.TranslatePipe, name: "translate" }], encapsulation: i0.ViewEncapsulation.None }); }
184
+ }
185
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.3", ngImport: i0, type: TaskDetailModalComponent, decorators: [{
186
+ type: Component,
187
+ args: [{ selector: 'valtimo-task-detail-modal', encapsulation: ViewEncapsulation.None, template: "<!--\n ~ Copyright 2015-2024 Ritense BV, the Netherlands.\n ~\n ~ Licensed under EUPL, Version 1.2 (the \"License\");\n ~ you may not use this file except in compliance with the License.\n ~ You may obtain a copy of the License at\n ~\n ~ https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n ~\n ~ Unless required by applicable law or agreed to in writing, software\n ~ distributed under the License is distributed on an \"AS IS\" basis,\n ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n ~ See the License for the specific language governing permissions and\n ~ limitations under the License.\n -->\n\n<valtimo-modal\n #taskDetailModal\n *ngIf=\"{\n loading: loading$ | async,\n page: page$ | async,\n task: task$ | async,\n formDefinition: formDefinition$ | async,\n processLinkIsForm: processLinkIsForm$ | async,\n formioOptions: formioOptions$ | async,\n processLinkIsFormFlow: processLinkIsFormFlow$ | async,\n formFlowInstanceId: formFlowInstanceId$ | async,\n errorMessage: errorMessage$ | async\n } as obs\"\n elementId=\"taskDetailModal\"\n [title]=\"obs.page?.title\"\n [subtitle]=\"obs.page?.subtitle\"\n [templateBelowSubtitle]=\"assignUserToTask\"\n>\n <div body *ngIf=\"obs.formDefinition && obs.processLinkIsForm\">\n <valtimo-form-io\n #form\n [form]=\"obs.formDefinition\"\n (submit)=\"onSubmit($event)\"\n (change)=\"onChange($event)\"\n [options]=\"obs.formioOptions\"\n ></valtimo-form-io>\n </div>\n <div body *ngIf=\"obs.processLinkIsFormFlow\">\n <valtimo-form-flow\n #formFlow\n [formIoFormData]=\"formIoFormData$\"\n [formFlowInstanceId]=\"obs.formFlowInstanceId\"\n (formFlowComplete)=\"completeTask()\"\n ></valtimo-form-flow>\n </div>\n <div body *ngIf=\"obs.loading\">\n <div class=\"text-black mb-0 p-3 text-center\">\n {{ 'formManagement.loading' | translate }}\n </div>\n </div>\n <div\n body\n *ngIf=\"\n obs.loading === false && !obs.formDefinition && !obs.formFlowInstanceId && !obs.errorMessage\n \"\n >\n <div class=\"bg-warning text-black mb-0 p-3 text-center\">\n {{\n (isAdmin$ | async)\n ? ('formManagement.noFormDefinitionFoundAdmin' | translate)\n : ('formManagement.noFormDefinitionFoundUser' | translate)\n }}\n </div>\n </div>\n <div body *ngIf=\"obs.errorMessage\">\n <div class=\"bg-danger text-black mb-0 p-3 text-center\">\n {{ obs.errorMessage }}\n </div>\n </div>\n <div footer>\n <div class=\"mb-0 p-3 text-center\" *ngIf=\"!!obs.formDefinition\">\n <button\n class=\"btn btn-secondary btn-space\"\n type=\"button\"\n (click)=\"gotoProcessLinkScreen()\"\n id=\"process-link-button\"\n >\n {{ 'formManagement.gotoProcessLinksButton' | translate }}\n </button>\n </div>\n </div>\n</valtimo-modal>\n\n<ng-template #assignUserToTask>\n <ng-container *ngIf=\"task$ | async as task\">\n <valtimo-assign-user-to-task\n *ngIf=\"task && assignmentOfTaskChanged\"\n [taskId]=\"task.id\"\n [assigneeId]=\"task.assignee\"\n (assignmentOfTaskChanged)=\"assignmentOfTaskChanged.emit()\"\n ></valtimo-assign-user-to-task>\n </ng-container>\n</ng-template>\n", styles: ["#taskDetailModal .formio-component-submit{text-align:right}\n/*!\n * Copyright 2015-2024 Ritense BV, the Netherlands.\n *\n * Licensed under EUPL, Version 1.2 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * https://joinup.ec.europa.eu/collection/eupl/eupl-text-eupl-12\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" basis,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n"] }]
188
+ }], ctorParameters: () => [{ type: i1.ToastrService }, { type: i2.ProcessLinkService }, { type: i3.Router }, { type: i4.TaskService }, { type: i5.UserProviderService }, { type: i6.ValtimoModalService }, { type: i6.FormIoStateService }, { type: i7.DocumentService }, { type: i8.TranslateService }], propDecorators: { form: [{
189
+ type: ViewChild,
190
+ args: ['form']
191
+ }], formFlow: [{
192
+ type: ViewChild,
193
+ args: ['formFlow']
194
+ }], modal: [{
195
+ type: ViewChild,
196
+ args: ['taskDetailModal']
197
+ }], formSubmit: [{
198
+ type: Output
199
+ }], assignmentOfTaskChanged: [{
200
+ type: Output
201
+ }] } });
202
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFzay1kZXRhaWwtbW9kYWwuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdmFsdGltby90YXNrL3NyYy9saWIvY29tcG9uZW50cy90YXNrLWRldGFpbC1tb2RhbC90YXNrLWRldGFpbC1tb2RhbC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy92YWx0aW1vL3Rhc2svc3JjL2xpYi9jb21wb25lbnRzL3Rhc2stZGV0YWlsLW1vZGFsL3Rhc2stZGV0YWlsLW1vZGFsLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBRUgsT0FBTyxFQUVMLFNBQVMsRUFDVCxZQUFZLEVBRVosTUFBTSxFQUNOLFNBQVMsRUFDVCxpQkFBaUIsR0FDbEIsTUFBTSxlQUFlLENBQUM7QUFFdkIsT0FBTyxFQUVMLGlCQUFpQixHQU1sQixNQUFNLHFCQUFxQixDQUFDO0FBSTdCLE9BQU8sTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUU1QixPQUFPLEVBQUMsR0FBRyxFQUFFLElBQUksRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBRXpDLE9BQU8sRUFDTCxlQUFlLEVBQ2YsYUFBYSxFQUNiLG9CQUFvQixFQUVwQixZQUFZLEVBQ1osR0FBRyxHQUNKLE1BQU0sTUFBTSxDQUFDOzs7Ozs7Ozs7Ozs7QUFLZCxNQUFNLENBQUMsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7QUFRckQsTUFBTSxPQUFPLHdCQUF3QjtJQTZCbkMsWUFDbUIsTUFBcUIsRUFDckIsa0JBQXNDLEVBQ3RDLE1BQWMsRUFDZCxXQUF3QixFQUN4QixtQkFBd0MsRUFDeEMsWUFBaUMsRUFDakMsWUFBZ0MsRUFDaEMsZUFBZ0MsRUFDaEMsZ0JBQWtDO1FBUmxDLFdBQU0sR0FBTixNQUFNLENB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Z0JBQ00sUUFBUTtzQkFBOUIsU0FBUzt1QkFBQyxVQUFVO2dCQUNTLEtBQUs7c0JBQWxDLFNBQVM7dUJBQUMsaUJBQWlCO2dCQUNsQixVQUFVO3NCQUFuQixNQUFNO2dCQUNHLHVCQUF1QjtzQkFBaEMsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgMjAxNS0yMDI0IFJpdGVuc2UgQlYsIHRoZSBOZXRoZXJsYW5kcy5cbiAqXG4gKiBMaWNlbnNlZCB1bmRlciBFVVBMLCBWZXJzaW9uIDEuMiAodGhlIFwiTGljZW5zZVwiKTtcbiAqIHlvdSBtYXkgbm90IHVzZSB0aGlzIGZpbGUgZXhjZXB0IGluIGNvbXBsaWFuY2Ugd2l0aCB0aGUgTGljZW5zZS5cbiAqIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICpcbiAqIGh0dHBzOi8vam9pbnVwLmVjLmV1cm9wYS5ldS9jb2xsZWN0aW9uL2V1cGwvZXVwbC10ZXh0LWV1cGwtMTJcbiAqXG4gKiBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlXG4gKiBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiBcIkFTIElTXCIgYmFzaXMsXG4gKiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAqIFNlZSB0aGUgTGljZW5zZSBmb3IgdGhlIHNwZWNpZmljIGxhbmd1YWdlIGdvdmVybmluZyBwZXJtaXNzaW9ucyBhbmRcbiAqIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLlxuICovXG5cbmltcG9ydCB7XG4gIEFmdGVyVmlld0luaXQsXG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgVmlld0NoaWxkLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1JvdXRlcn0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcbmltcG9ydCB7XG4gIEZvcm1pb0NvbXBvbmVudCxcbiAgRm9ybWlvT3B0aW9uc0ltcGwsXG4gIEZvcm1Jb1N0YXRlU2VydmljZSxcbiAgRm9ybWlvU3VibWlzc2lvbixcbiAgTW9kYWxDb21wb25lbnQsXG4gIFZhbHRpbW9Gb3JtaW9PcHRpb25zLFxuICBWYWx0aW1vTW9kYWxTZXJ2aWNlLFxufSBmcm9tICdAdmFsdGltby9jb21wb25lbnRzJztcbmltcG9ydCB7VGFzaywgVGFza1Byb2Nlc3NMaW5rVHlwZX0gZnJvbSAnLi4vLi4vbW9kZWxzJztcbmltcG9ydCB7Rm9ybUZsb3dDb21wb25lbnQsIEZvcm1TdWJtaXNzaW9uUmVzdWx0LCBQcm9jZXNzTGlua1NlcnZpY2V9IGZyb20gJ0B2YWx0aW1vL3Byb2Nlc3MtbGluayc7XG5pbXBvcnQge0Zvcm1pb0Zvcm19IGZyb20gJ0Bmb3JtaW8vYW5ndWxhcic7XG5pbXBvcnQgbW9tZW50IGZyb20gJ21vbWVudCc7XG5pbXBvcnQge1RvYXN0clNlcnZpY2V9IGZyb20gJ25neC10b2FzdHInO1xuaW1wb3J0IHttYXAsIHRha2V9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7VGFza1NlcnZpY2V9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3Rhc2suc2VydmljZSc7XG5pbXBvcnQge1xuICBCZWhhdmlvclN1YmplY3QsXG4gIGNvbWJpbmVMYXRlc3QsXG4gIGRpc3RpbmN0VW50aWxDaGFuZ2VkLFxuICBPYnNlcnZhYmxlLFxuICBTdWJzY3JpcHRpb24sXG4gIHRhcCxcbn0gZnJvbSAncnhqcyc7XG5pbXBvcnQge1VzZXJQcm92aWRlclNlcnZpY2V9IGZyb20gJ0B2YWx0aW1vL3NlY3VyaXR5JztcbmltcG9ydCB7RG9jdW1lbnRTZXJ2aWNlfSBmcm9tICdAdmFsdGltby9kb2N1bWVudCc7XG5pbXBvcnQge1RyYW5zbGF0ZVNlcnZpY2V9IGZyb20gJ0BuZ3gtdHJhbnNsYXRlL2NvcmUnO1xuXG5tb21lbnQubG9jYWxlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdsYW5nS2V5JykgfHwgJycpO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWx0aW1vLXRhc2stZGV0YWlsLW1vZGFsJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3Rhc2stZGV0YWlsLW1vZGFsLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vdGFzay1kZXRhaWwtbW9kYWwuY29tcG9uZW50LnNjc3MnXSxcbiAgZW5jYXBzdWxhdGlvbjogVmlld0VuY2Fwc3VsYXRpb24uTm9uZSxcbn0pXG5leHBvcnQgY2xhc3MgVGFza0RldGFpbE1vZGFsQ29tcG9uZW50IGltcGxlbWVudHMgQWZ0ZXJWaWV3SW5pdCwgT25EZXN0cm95IHtcbiAgQFZpZXdDaGlsZCgnZm9ybScpIGZvcm06IEZvcm1pb0NvbXBvbmVudDtcbiAgQFZpZXdDaGlsZCgnZm9ybUZsb3cnKSBmb3JtRmxvdzogRm9ybUZsb3dDb21wb25lbnQ7XG4gIEBWaWV3Q2hpbGQoJ3Rhc2tEZXRhaWxNb2RhbCcpIG1vZGFsOiBNb2RhbENvbXBvbmVudDtcbiAgQE91dHB1dCgpIGZvcm1TdWJtaXQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBhc3NpZ25tZW50T2ZUYXNrQ2hhbmdlZCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcblxuICBwdWJsaWMgcmVhZG9ubHkgdGFzayQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFRhc2sgfCBudWxsPihudWxsKTtcbiAgcHVibGljIHJlYWRvbmx5IGZvcm1EZWZpbml0aW9uJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8Rm9ybWlvRm9ybT4odW5kZWZpbmVkKTtcbiAgcHVibGljIHJlYWRvbmx5IGZvcm1GbG93SW5zdGFuY2VJZCQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZz4odW5kZWZpbmVkKTtcbiAgcHVibGljIHJlYWRvbmx5IHBhZ2UkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxhbnk+KG51bGwpO1xuICBwdWJsaWMgcmVhZG9ubHkgZm9ybWlvT3B0aW9ucyQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PFZhbHRpbW9Gb3JtaW9PcHRpb25zPihudWxsKTtcbiAgcHVibGljIHJlYWRvbmx5IGVycm9yTWVzc2FnZSQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZz4odW5kZWZpbmVkKTtcbiAgcHVibGljIHJlYWRvbmx5IGlzQWRtaW4kOiBPYnNlcnZhYmxlPGJvb2xlYW4+ID0gdGhpcy51c2VyUHJvdmlkZXJTZXJ2aWNlXG4gICAgLmdldFVzZXJTdWJqZWN0KClcbiAgICAucGlwZShtYXAodXNlcklkZW50aXR5ID0+IHVzZXJJZGVudGl0eT8ucm9sZXM/LmluY2x1ZGVzKCdST0xFX0FETUlOJykpKTtcbiAgcHVibGljIHJlYWRvbmx5IGZvcm1Jb0Zvcm1EYXRhJCA9IG5ldyBCZWhhdmlvclN1YmplY3Q8YW55PihudWxsKTtcbiAgcHVibGljIHJlYWRvbmx5IGxvYWRpbmckID0gbmV3IEJlaGF2aW9yU3ViamVjdDxib29sZWFuPih0cnVlKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IHRhc2tQcm9jZXNzTGlua1R5cGUkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxUYXNrUHJvY2Vzc0xpbmtUeXBlIHwgbnVsbD4obnVsbCk7XG4gIHB1YmxpYyByZWFkb25seSBwcm9jZXNzTGlua0lzRm9ybSQgPSB0aGlzLnRhc2tQcm9jZXNzTGlua1R5cGUkLnBpcGUobWFwKHR5cGUgPT4gdHlwZSA9PT0gJ2Zvcm0nKSk7XG4gIHB1YmxpYyByZWFkb25seSBwcm9jZXNzTGlua0lzRm9ybUZsb3ckID0gdGhpcy50YXNrUHJvY2Vzc0xpbmtUeXBlJC5waXBlKFxuICAgIG1hcCh0eXBlID0+IHR5cGUgPT09ICdmb3JtLWZsb3cnKVxuICApO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgcHJvY2Vzc0xpbmtJZCQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZz4odW5kZWZpbmVkKTtcblxuICBwcml2YXRlIF9zdWJzY3JpcHRpb25zID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHByaXZhdGUgcmVhZG9ubHkgdG9hc3RyOiBUb2FzdHJTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgcHJvY2Vzc0xpbmtTZXJ2aWNlOiBQcm9jZXNzTGlua1NlcnZpY2UsXG4gICAgcHJpdmF0ZSByZWFkb25seSByb3V0ZXI6IFJvdXRlcixcbiAgICBwcml2YXRlIHJlYWRvbmx5IHRhc2tTZXJ2aWNlOiBUYXNrU2VydmljZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IHVzZXJQcm92aWRlclNlcnZpY2U6IFVzZXJQcm92aWRlclNlcnZpY2UsXG4gICAgcHJpdmF0ZSByZWFkb25seSBtb2RhbFNlcnZpY2U6IFZhbHRpbW9Nb2RhbFNlcnZpY2UsXG4gICAgcHJpdmF0ZSByZWFkb25seSBzdGF0ZVNlcnZpY2U6IEZvcm1Jb1N0YXRlU2VydmljZSxcbiAgICBwcml2YXRlIHJlYWRvbmx5IGRvY3VtZW50U2VydmljZTogRG9jdW1lbnRTZXJ2aWNlLFxuICAgIHByaXZhdGUgcmVhZG9ubHkgdHJhbnNsYXRlU2VydmljZTogVHJhbnNsYXRlU2VydmljZVxuICApIHtcbiAgICBjb25zdCBvcHRpb25zID0gbmV3IEZvcm1pb09wdGlvbnNJbXBsKCk7XG4gICAgb3B0aW9ucy5kaXNhYmxlQWxlcnRzID0gdHJ1ZTtcbiAgICB0aGlzLmZvcm1pb09wdGlvbnMkLm5leHQob3B0aW9ucyk7XG4gIH1cblxuICBwdWJsaWMgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIHRoaXMuX3N1YnNjcmlwdGlvbnMuYWRkKFxuICAgICAgdGhpcy5tb2RhbC5tb2RhbFNob3dpbmckXG4gICAgICAgIC5waXBlKFxuICAgICAgICAgIGRpc3RpbmN0VW50aWxDaGFuZ2VkKCksXG4gICAgICAgICAgdGFwKG1vZGFsU2hvd2luZyA9PiB7XG4gICAgICAgICAgICBpZiAoIW1vZGFsU2hvd2luZykge1xuICAgICAgICAgICAgICBpZiAodGhpcy5mb3JtRmxvdykge1xuICAgICAgICAgICAgICAgIHRoaXMuZm9ybUZsb3cuc2F2ZURhdGEoKTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0pXG4gICAgICAgIClcbiAgICAgICAgLnN1YnNjcmliZSgpXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBuZ09uRGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLl9zdWJzY3JpcHRpb25zLnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBwdWJsaWMgb3BlblRhc2tEZXRhaWxzKHRhc2s6IFRhc2spOiB2b2lkIHtcbiAgICB0aGlzLnJlc2V0VGFza1Byb2Nlc3NMaW5rVHlwZSgpO1xuICAgIHRoaXMucmVzZXRGb3JtRGVmaW5pdGlvbigpO1xuICAgIHRoaXMuZ2V0VGFza1Byb2Nlc3NMaW5rKHRhc2suaWQpO1xuICAgIHRoaXMuc2V0RG9jdW1lbnREZWZpbml0aW9uTmFtZUluU2VydmljZSh0YXNrKTtcbiAgICBjb25zdCBkb2N1bWVudElkID0gdGFzay5idXNpbmVzc0tleTtcbiAgICB0aGlzLnN0YXRlU2VydmljZS5zZXREb2N1bWVudElkKGRvY3VtZW50SWQpO1xuXG4gICAgdGhpcy50YXNrJC5uZXh0KHRhc2spO1xuICAgIHRoaXMucGFnZSQubmV4dCh7XG4gICAgICB0aXRsZTogdGFzay5uYW1lLFxuICAgICAgc3VidGl0bGU6IGAke3RoaXMudHJhbnNsYXRlU2VydmljZS5pbnN0YW50KCd0YXNrRGV0YWlsLnRhc2tDcmVhdGVkJyl9ICR7dGFzay5jcmVhdGVkfWAsXG4gICAgfSk7XG5cbiAgICAvL29ubHkgbG9hZCBmcm9tIGZvcm1saW5rIHdoZW4gcHJvY2VzcyBsaW5rIGZhaWxlZCBmb3IgYmFja3dhcmRzIGNvbXBhdGliaWxpdHlcbiAgICBpZiAoIXRoaXMudGFza1Byb2Nlc3NMaW5rVHlwZSQuZ2V0VmFsdWUoKSkge1xuICAgICAgdGhpcy5tb2RhbC5zaG93KCk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIGdvdG9Qcm9jZXNzTGlua1NjcmVlbigpOiB2b2lkIHtcbiAgICB0aGlzLm1vZGFsLmhpZGUoKTtcbiAgICB0aGlzLnJvdXRlci5uYXZpZ2F0ZShbJ3Byb2Nlc3MtbGlua3MnXSk7XG4gIH1cblxuICBwdWJsaWMgb25DaGFuZ2UoZXZlbnQ6IGFueSk6IHZvaWQge1xuICAgIGlmIChldmVudC5kYXRhKSB7XG4gICAgICB0aGlzLmZvcm1Jb0Zvcm1EYXRhJC5uZXh0KGV2ZW50LmRhdGEpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBvblN1Ym1pdChzdWJtaXNzaW9uOiBGb3JtaW9TdWJtaXNzaW9uKTogdm9pZCB7XG4gICAgaWYgKHN1Ym1pc3Npb24uZGF0YSkge1xuICAgICAgdGhpcy5mb3JtSW9Gb3JtRGF0YSQubmV4dChzdWJtaXNzaW9uLmRhdGEpO1xuICAgIH1cblxuICAgIGNvbWJpbmVMYXRlc3QoW3RoaXMucHJvY2Vzc0xpbmtJZCQsIHRoaXMudGFza1Byb2Nlc3NMaW5rVHlwZSQsIHRoaXMudGFzayRdKVxuICAgICAgLnBpcGUodGFrZSgxKSlcbiAgICAgIC5zdWJzY3JpYmUoKFtwcm9jZXNzTGlua0lkLCB0YXNrUHJvY2Vzc0xpbmtUeXBlLCB0YXNrXSkgPT4ge1xuICAgICAgICBpZiAodGFza1Byb2Nlc3NMaW5rVHlwZSA9PT0gJ2Zvcm0nKSB7XG4gICAgICAgICAgaWYgKHByb2Nlc3NMaW5rSWQpIHtcbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc0xpbmtTZXJ2aWNlXG4gICAgICAgICAgICAgIC5zdWJtaXRGb3JtKHByb2Nlc3NMaW5rSWQsIHN1Ym1pc3Npb24uZGF0YSwgdGFzay5idXNpbmVzc0tleSwgdGFzay5pZClcbiAgICAgICAgICAgICAgLnN1YnNjcmliZSh7XG4gICAgICAgICAgICAgICAgbmV4dDogKF86IEZvcm1TdWJtaXNzaW9uUmVzdWx0KSA9PiB7XG4gICAgICAgICAgICAgICAgICB0aGlzLmNvbXBsZXRlVGFzaygpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgZXJyb3I6IGVycm9ycyA9PiB7XG4gICAgICAgICAgICAgICAgICB0aGlzLmZvcm0uc2hvd0Vycm9ycyhlcnJvcnMpO1xuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICBwdWJsaWMgY29tcGxldGVUYXNrKCk6IHZvaWQge1xuICAgIHRoaXMudGFzayQucGlwZSh0YWtlKDEpKS5zdWJzY3JpYmUodGFzayA9PiB7XG4gICAgICB0aGlzLnRvYXN0ci5zdWNjZXNzKFxuICAgICAgICBgJHt0YXNrLm5hbWV9ICR7dGhpcy50cmFuc2xhdGVTZXJ2aWNlLmluc3RhbnQoJ3Rhc2tEZXRhaWwudGFza0NvbXBsZXRlZCcpfWBcbiAgICAgICk7XG4gICAgICB0aGlzLm1vZGFsLmhpZGUoKTtcbiAgICAgIHRoaXMudGFzayQubmV4dChudWxsKTtcbiAgICAgIHRoaXMuZm9ybVN1Ym1pdC5lbWl0KCk7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHJlc2V0Rm9ybURlZmluaXRpb24oKTogdm9pZCB7XG4gICAgdGhpcy5mb3JtRGVmaW5pdGlvbiQubmV4dChudWxsKTtcbiAgICB0aGlzLmxvYWRpbmckLm5leHQodHJ1ZSk7XG4gIH1cblxuICBwcml2YXRlIGdldFRhc2tQcm9jZXNzTGluayh0YXNrSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMudGFza1NlcnZpY2UuZ2V0VGFza1Byb2Nlc3NMaW5rKHRhc2tJZCkuc3Vic2NyaWJlKHtcbiAgICAgIG5leHQ6IHJlcyA9PiB7XG4gICAgICAgIGlmIChyZXMgIT0gbnVsbCkge1xuICAgICAgICAgIHN3aXRjaCAocmVzPy50eXBlKSB7XG4gICAgICAgICAgICBjYXNlICdmb3JtJzpcbiAgICAgICAgICAgICAgdGhpcy50YXNrUHJvY2Vzc0xpbmtUeXBlJC5uZXh0KCdmb3JtJyk7XG4gICAgICAgICAgICAgIHRoaXMucHJvY2Vzc0xpbmtJZCQubmV4dChyZXMucHJvY2Vzc0xpbmtJZCk7XG4gICAgICAgICAgICAgIHRoaXMuc2V0Rm9ybURlZmluaXRpb25BbmRPcGVuTW9kYWwocmVzLnByb3BlcnRpZXMucHJlZmlsbGVkRm9ybSk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnZm9ybS1mbG93JzpcbiAgICAgICAgICAgICAgdGhpcy50YXNrUHJvY2Vzc0xpbmtUeXBlJC5uZXh0KCdmb3JtLWZsb3cnKTtcbiAgICAgICAgICAgICAgdGhpcy5mb3JtRmxvd0luc3RhbmNlSWQkLm5leHQocmVzLnByb3BlcnRpZXMuZm9ybUZsb3dJbnN0YW5jZUlkKTtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIHRoaXMubG9hZGluZyQubmV4dChmYWxzZSk7XG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgICBlcnJvcjogXyA9PiB7XG4gICAgICAgIHRoaXMubG9hZGluZyQubmV4dChmYWxzZSk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSByZXNldFRhc2tQcm9jZXNzTGlua1R5cGUoKTogdm9pZCB7XG4gICAgdGhpcy50YXNrUHJvY2Vzc0xpbmtUeXBlJC5uZXh0KG51bGwpO1xuICAgIHRoaXMucHJvY2Vzc0xpbmtJZCQubmV4dChudWxsKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0Rm9ybURlZmluaXRpb25BbmRPcGVuTW9kYWwoZm9ybURlZmluaXRpb246IGFueSk6IHZvaWQge1xuICAgIHRoaXMudGFza1Byb2Nlc3NMaW5rVHlwZSQubmV4dCgnZm9ybScpO1xuICAgIHRoaXMuZm9ybURlZmluaXRpb24kLm5leHQoZm9ybURlZmluaXRpb24pO1xuICAgIHRoaXMubW9kYWwuc2hvdygpO1xuICB9XG5cbiAgcHJpdmF0ZSBzZXREb2N1bWVudERlZmluaXRpb25OYW1lSW5TZXJ2aWNlKHRhc2s6IFRhc2spOiB2b2lkIHtcbiAgICB0aGlzLmRvY3VtZW50U2VydmljZVxuICAgICAgLmdldFByb2Nlc3NEb2N1bWVudERlZmluaXRpb25Gcm9tUHJvY2Vzc0luc3RhbmNlSWQodGFzay5wcm9jZXNzSW5zdGFuY2VJZClcbiAgICAgIC5zdWJzY3JpYmUocHJvY2Vzc0RvY3VtZW50RGVmaW5pdGlvbiA9PiB7XG4gICAgICAgIGNvbnN0IGRvY3VtZW50RGVmaW5pdGlvbk5hbWUgPSBwcm9jZXNzRG9jdW1lbnREZWZpbml0aW9uLmlkLmRvY3VtZW50RGVmaW5pdGlvbklkLm5hbWU7XG4gICAgICAgIHRoaXMubW9kYWxTZXJ2aWNlLnNldERvY3VtZW50RGVmaW5pdGlvbk5hbWUoZG9jdW1lbnREZWZpbml0aW9uTmFtZSk7XG4gICAgICAgIHRoaXMuc3RhdGVTZXJ2aWNlLnNldERvY3VtZW50RGVmaW5pdGlvbk5hbWUoZG9jdW1lbnREZWZpbml0aW9uTmFtZSk7XG4gICAgICB9KTtcbiAgfVxufVxuIiwiPCEtLVxuICB+IENvcHlyaWdodCAyMDE1LTIwMjQgUml0ZW5zZSBCViwgdGhlIE5ldGhlcmxhbmRzLlxuICB+XG4gIH4gTGljZW5zZWQgdW5kZXIgRVVQTCwgVmVyc2lvbiAxLjIgKHRoZSBcIkxpY2Vuc2VcIik7XG4gIH4geW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLlxuICB+IFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdFxuICB+XG4gIH4gaHR0cHM6Ly9qb2ludXAuZWMuZXVyb3BhLmV1L2NvbGxlY3Rpb24vZXVwbC9ldXBsLXRleHQtZXVwbC0xMlxuICB+XG4gIH4gVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZVxuICB+IGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuIFwiQVMgSVNcIiBiYXNpcyxcbiAgfiBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC5cbiAgfiBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kXG4gIH4gbGltaXRhdGlvbnMgdW5kZXIgdGhlIExpY2Vuc2UuXG4gIC0tPlxuXG48dmFsdGltby1tb2RhbFxuICAjdGFza0RldGFpbE1vZGFsXG4gICpuZ0lmPVwie1xuICAgIGxvYWRpbmc6IGxvYWRpbmckIHwgYXN5bmMsXG4gICAgcGFnZTogcGFnZSQgfCBhc3luYyxcbiAgICB0YXNrOiB0YXNrJCB8IGFzeW5jLFxuICAgIGZvcm1EZWZpbml0aW9uOiBmb3JtRGVmaW5pdGlvbiQgfCBhc3luYyxcbiAgICBwcm9jZXNzTGlua0lzRm9ybTogcHJvY2Vzc0xpbmtJc0Zvcm0kIHwgYXN5bmMsXG4gICAgZm9ybWlvT3B0aW9uczogZm9ybWlvT3B0aW9ucyQgfCBhc3luYyxcbiAgICBwcm9jZXNzTGlua0lzRm9ybUZsb3c6IHByb2Nlc3NMaW5rSXNGb3JtRmxvdyQgfCBhc3luYyxcbiAgICBmb3JtRmxvd0luc3RhbmNlSWQ6IGZvcm1GbG93SW5zdGFuY2VJZCQgfCBhc3luYyxcbiAgICBlcnJvck1lc3NhZ2U6IGVycm9yTWVzc2FnZSQgfCBhc3luY1xuICB9IGFzIG9ic1wiXG4gIGVsZW1lbnRJZD1cInRhc2tEZXRhaWxNb2RhbFwiXG4gIFt0aXRsZV09XCJvYnMucGFnZT8udGl0bGVcIlxuICBbc3VidGl0bGVdPVwib2JzLnBhZ2U/LnN1YnRpdGxlXCJcbiAgW3RlbXBsYXRlQmVsb3dTdWJ0aXRsZV09XCJhc3NpZ25Vc2VyVG9UYXNrXCJcbj5cbiAgPGRpdiBib2R5ICpuZ0lmPVwib2JzLmZvcm1EZWZpbml0aW9uICYmIG9icy5wcm9jZXNzTGlua0lzRm9ybVwiPlxuICAgIDx2YWx0aW1vLWZvcm0taW9cbiAgICAgICNmb3JtXG4gICAgICBbZm9ybV09XCJvYnMuZm9ybURlZmluaXRpb25cIlxuICAgICAgKHN1Ym1pdCk9XCJvblN1Ym1pdCgkZXZlbnQpXCJcbiAgICAgIChjaGFuZ2UpPVwib25DaGFuZ2UoJGV2ZW50KVwiXG4gICAgICBbb3B0aW9uc109XCJvYnMuZm9ybWlvT3B0aW9uc1wiXG4gICAgPjwvdmFsdGltby1mb3JtLWlvPlxuICA8L2Rpdj5cbiAgPGRpdiBib2R5ICpuZ0lmPVwib2JzLnByb2Nlc3NMaW5rSXNGb3JtRmxvd1wiPlxuICAgIDx2YWx0aW1vLWZvcm0tZmxvd1xuICAgICAgI2Zvcm1GbG93XG4gICAgICBbZm9ybUlvRm9ybURhdGFdPVwiZm9ybUlvRm9ybURhdGEkXCJcbiAgICAgIFtmb3JtRmxvd0luc3RhbmNlSWRdPVwib2JzLmZvcm1GbG93SW5zdGFuY2VJZFwiXG4gICAgICAoZm9ybUZsb3dDb21wbGV0ZSk9XCJjb21wbGV0ZVRhc2soKVwiXG4gICAgPjwvdmFsdGltby1mb3JtLWZsb3c+XG4gIDwvZGl2PlxuICA8ZGl2IGJvZHkgKm5nSWY9XCJvYnMubG9hZGluZ1wiPlxuICAgIDxkaXYgY2xhc3M9XCJ0ZXh0LWJsYWNrIG1iLTAgcC0zIHRleHQtY2VudGVyXCI+XG4gICAgICB7eyAnZm9ybU1hbmFnZW1lbnQubG9hZGluZycgfCB0cmFuc2xhdGUgfX1cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXZcbiAgICBib2R5XG4gICAgKm5nSWY9XCJcbiAgICAgIG9icy5sb2FkaW5nID09PSBmYWxzZSAmJiAhb2JzLmZvcm1EZWZpbml0aW9uICYmICFvYnMuZm9ybUZsb3dJbnN0YW5jZUlkICYmICFvYnMuZXJyb3JNZXNzYWdlXG4gICAgXCJcbiAgPlxuICAgIDxkaXYgY2xhc3M9XCJiZy13YXJuaW5nIHRleHQtYmxhY2sgbWItMCBwLTMgdGV4dC1jZW50ZXJcIj5cbiAgICAgIHt7XG4gICAgICAgIChpc0FkbWluJCB8IGFzeW5jKVxuICAgICAgICAgID8gKCdmb3JtTWFuYWdlbWVudC5ub0Zvcm1EZWZpbml0aW9uRm91bmRBZG1pbicgfCB0cmFuc2xhdGUpXG4gICAgICAgICAgOiAoJ2Zvcm1NYW5hZ2VtZW50Lm5vRm9ybURlZmluaXRpb25Gb3VuZFVzZXInIHwgdHJhbnNsYXRlKVxuICAgICAgfX1cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgYm9keSAqbmdJZj1cIm9icy5lcnJvck1lc3NhZ2VcIj5cbiAgICA8ZGl2IGNsYXNzPVwiYmctZGFuZ2VyIHRleHQtYmxhY2sgbWItMCBwLTMgdGV4dC1jZW50ZXJcIj5cbiAgICAgIHt7IG9icy5lcnJvck1lc3NhZ2UgfX1cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG4gIDxkaXYgZm9vdGVyPlxuICAgIDxkaXYgY2xhc3M9XCJtYi0wIHAtMyB0ZXh0LWNlbnRlclwiICpuZ0lmPVwiISFvYnMuZm9ybURlZmluaXRpb25cIj5cbiAgICAgIDxidXR0b25cbiAgICAgICAgY2xhc3M9XCJidG4gYnRuLXNlY29uZGFyeSBidG4tc3BhY2VcIlxuICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgKGNsaWNrKT1cImdvdG9Qcm9jZXNzTGlua1NjcmVlbigpXCJcbiAgICAgICAgaWQ9XCJwcm9jZXNzLWxpbmstYnV0dG9uXCJcbiAgICAgID5cbiAgICAgICAge3sgJ2Zvcm1NYW5hZ2VtZW50LmdvdG9Qcm9jZXNzTGlua3NCdXR0b24nIHwgdHJhbnNsYXRlIH19XG4gICAgICA8L2J1dHRvbj5cbiAgICA8L2Rpdj5cbiAgPC9kaXY+XG48L3ZhbHRpbW8tbW9kYWw+XG5cbjxuZy10ZW1wbGF0ZSAjYXNzaWduVXNlclRvVGFzaz5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cInRhc2skIHwgYXN5bmMgYXMgdGFza1wiPlxuICAgIDx2YWx0aW1vLWFzc2lnbi11c2VyLXRvLXRhc2tcbiAgICAgICpuZ0lmPVwidGFzayAmJiBhc3NpZ25tZW50T2ZUYXNrQ2hhbmdlZFwiXG4gICAgICBbdGFza0lkXT1cInRhc2suaWRcIlxuICAgICAgW2Fzc2lnbmVlSWRdPVwidGFzay5hc3NpZ25lZVwiXG4gICAgICAoYXNzaWdubWVudE9mVGFza0NoYW5nZWQpPVwiYXNzaWdubWVudE9mVGFza0NoYW5nZWQuZW1pdCgpXCJcbiAgICA+PC92YWx0aW1vLWFzc2lnbi11c2VyLXRvLXRhc2s+XG4gIDwvbmctY29udGFpbmVyPlxuPC9uZy10ZW1wbGF0ZT5cbiJdfQ==