@solidev/data 0.0.9 → 0.1.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 (158) hide show
  1. package/esm2022/lib/auth/auth-interceptor.service.mjs +92 -0
  2. package/{esm2020 → esm2022}/lib/auth/auth.service.mjs +1 -1
  3. package/esm2022/lib/data/data-backend.mjs +135 -0
  4. package/esm2022/lib/data/data-model.mjs +292 -0
  5. package/esm2022/lib/dispedit/choice.pipe.mjs +81 -0
  6. package/esm2022/lib/dispedit/dispedit/dispedit.component.mjs +481 -0
  7. package/esm2022/lib/dispedit/factor.pipe.mjs +83 -0
  8. package/esm2022/lib/dispedit/factorc.pipe.mjs +101 -0
  9. package/esm2022/lib/dispedit/fkselect/fkselect.component.mjs +143 -0
  10. package/esm2022/lib/dispedit/flags/flags.component.mjs +141 -0
  11. package/esm2022/lib/dispedit/m2mselect/m2mselect.component.mjs +319 -0
  12. package/esm2022/lib/dispedit/richedit/richedit.component.mjs +127 -0
  13. package/esm2022/lib/dispedit/sdelete/sdelete.component.mjs +94 -0
  14. package/esm2022/lib/messages/message-zone/message-zone.component.mjs +58 -0
  15. package/esm2022/lib/messages/message.service.mjs +152 -0
  16. package/esm2022/lib/modellist/model-list-fields/model-list-field-header/model-list-field-header.component.mjs +66 -0
  17. package/esm2022/lib/modellist/model-list-fields/model-list-fields-selector/model-list-fields-selector.component.mjs +65 -0
  18. package/esm2022/lib/modellist/model-list-filters/filters/model-list-autocomplete-filter/model-list-autocomplete-filter.component.mjs +113 -0
  19. package/esm2022/lib/modellist/model-list-filters/filters/model-list-autocomplete-multi-filter/model-list-autocomplete-multi-filter.component.mjs +30 -0
  20. package/esm2022/lib/modellist/model-list-filters/filters/model-list-date-filter/model-list-date-filter.component.mjs +41 -0
  21. package/esm2022/lib/modellist/model-list-filters/filters/model-list-datetime-filter/model-list-datetime-filter.component.mjs +41 -0
  22. package/esm2022/lib/modellist/model-list-filters/filters/model-list-datetimerange-filter/model-list-datetime-range-filter.component.mjs +22 -0
  23. package/esm2022/lib/modellist/model-list-filters/filters/model-list-flags-filter/model-list-flags-filter.component.mjs +50 -0
  24. package/esm2022/lib/modellist/model-list-filters/filters/model-list-geodistance-filter/model-list-geodistance-filter.component.mjs +64 -0
  25. package/esm2022/lib/modellist/model-list-filters/filters/model-list-number-filter/model-list-number-filter.component.mjs +47 -0
  26. package/esm2022/lib/modellist/model-list-filters/filters/model-list-select-filter/model-list-select-filter.component.mjs +57 -0
  27. package/esm2022/lib/modellist/model-list-filters/filters/model-list-select-multi-filter/model-list-select-multi-filter.component.mjs +52 -0
  28. package/esm2022/lib/modellist/model-list-filters/filters/model-list-text-filter/model-list-text-filter.component.mjs +41 -0
  29. package/esm2022/lib/modellist/model-list-filters/filters/model-list-tree-filter/model-list-tree-filter.component.mjs +175 -0
  30. package/esm2022/lib/modellist/model-list-filters/model-list-filters/model-list-filters.component.mjs +51 -0
  31. package/esm2022/lib/modellist/model-list-filters/model-list-filters-select/model-list-filters-select.component.mjs +31 -0
  32. package/esm2022/lib/modellist/model-list-paginator/model-list-paginator/model-list-paginator.component.mjs +71 -0
  33. package/esm2022/lib/modellist/model-list-sorter/model-list-sorter/model-list-sorter.component.mjs +50 -0
  34. package/esm2022/lib/modellist/model-list.service.mjs +158 -0
  35. package/esm2022/lib/routing/breadcrumb/breadcrumb.component.mjs +143 -0
  36. package/esm2022/lib/updates/update/update.component.mjs +18 -0
  37. package/esm2022/lib/updates/update.service.mjs +59 -0
  38. package/esm2022/lib/uploader/ng-file-drop.directive.mjs +82 -0
  39. package/esm2022/lib/uploader/ng-file-select.directive.mjs +52 -0
  40. package/esm2022/lib/uploader/ngx-uploader.module.mjs +18 -0
  41. package/esm2022/lib/utils/tab-memory.service.mjs +81 -0
  42. package/{fesm2020 → fesm2022}/solidev-data.mjs +149 -149
  43. package/{fesm2020 → fesm2022}/solidev-data.mjs.map +1 -1
  44. package/lib/dispedit/dispedit/dispedit.component.d.ts +1 -1
  45. package/lib/dispedit/fkselect/fkselect.component.d.ts +1 -1
  46. package/lib/dispedit/flags/flags.component.d.ts +1 -1
  47. package/lib/dispedit/m2mselect/m2mselect.component.d.ts +1 -1
  48. package/lib/dispedit/richedit/richedit.component.d.ts +1 -1
  49. package/lib/dispedit/sdelete/sdelete.component.d.ts +1 -1
  50. package/lib/messages/message-zone/message-zone.component.d.ts +1 -1
  51. package/lib/modellist/model-list-fields/model-list-field-header/model-list-field-header.component.d.ts +1 -1
  52. package/lib/modellist/model-list-fields/model-list-fields-selector/model-list-fields-selector.component.d.ts +1 -1
  53. package/lib/modellist/model-list-filters/filters/model-list-autocomplete-filter/model-list-autocomplete-filter.component.d.ts +1 -1
  54. package/lib/modellist/model-list-filters/filters/model-list-autocomplete-multi-filter/model-list-autocomplete-multi-filter.component.d.ts +1 -1
  55. package/lib/modellist/model-list-filters/filters/model-list-date-filter/model-list-date-filter.component.d.ts +1 -1
  56. package/lib/modellist/model-list-filters/filters/model-list-datetime-filter/model-list-datetime-filter.component.d.ts +1 -1
  57. package/lib/modellist/model-list-filters/filters/model-list-datetimerange-filter/model-list-datetime-range-filter.component.d.ts +1 -1
  58. package/lib/modellist/model-list-filters/filters/model-list-flags-filter/model-list-flags-filter.component.d.ts +1 -1
  59. package/lib/modellist/model-list-filters/filters/model-list-geodistance-filter/model-list-geodistance-filter.component.d.ts +1 -1
  60. package/lib/modellist/model-list-filters/filters/model-list-number-filter/model-list-number-filter.component.d.ts +1 -1
  61. package/lib/modellist/model-list-filters/filters/model-list-select-filter/model-list-select-filter.component.d.ts +1 -1
  62. package/lib/modellist/model-list-filters/filters/model-list-select-multi-filter/model-list-select-multi-filter.component.d.ts +1 -1
  63. package/lib/modellist/model-list-filters/filters/model-list-text-filter/model-list-text-filter.component.d.ts +1 -1
  64. package/lib/modellist/model-list-filters/filters/model-list-tree-filter/model-list-tree-filter.component.d.ts +1 -1
  65. package/lib/modellist/model-list-filters/model-list-filters/model-list-filters.component.d.ts +1 -1
  66. package/lib/modellist/model-list-filters/model-list-filters-select/model-list-filters-select.component.d.ts +1 -1
  67. package/lib/modellist/model-list-paginator/model-list-paginator/model-list-paginator.component.d.ts +1 -1
  68. package/lib/modellist/model-list-sorter/model-list-sorter/model-list-sorter.component.d.ts +1 -1
  69. package/lib/routing/breadcrumb/breadcrumb.component.d.ts +1 -1
  70. package/lib/uploader/ng-file-drop.directive.d.ts +1 -1
  71. package/lib/uploader/ng-file-select.directive.d.ts +1 -1
  72. package/package.json +7 -13
  73. package/esm2020/lib/auth/auth-interceptor.service.mjs +0 -91
  74. package/esm2020/lib/data/data-backend.mjs +0 -134
  75. package/esm2020/lib/data/data-model.mjs +0 -291
  76. package/esm2020/lib/dispedit/choice.pipe.mjs +0 -79
  77. package/esm2020/lib/dispedit/dispedit/dispedit.component.mjs +0 -480
  78. package/esm2020/lib/dispedit/factor.pipe.mjs +0 -81
  79. package/esm2020/lib/dispedit/factorc.pipe.mjs +0 -99
  80. package/esm2020/lib/dispedit/fkselect/fkselect.component.mjs +0 -142
  81. package/esm2020/lib/dispedit/flags/flags.component.mjs +0 -140
  82. package/esm2020/lib/dispedit/m2mselect/m2mselect.component.mjs +0 -318
  83. package/esm2020/lib/dispedit/richedit/richedit.component.mjs +0 -126
  84. package/esm2020/lib/dispedit/sdelete/sdelete.component.mjs +0 -93
  85. package/esm2020/lib/messages/message-zone/message-zone.component.mjs +0 -57
  86. package/esm2020/lib/messages/message.service.mjs +0 -151
  87. package/esm2020/lib/modellist/model-list-fields/model-list-field-header/model-list-field-header.component.mjs +0 -65
  88. package/esm2020/lib/modellist/model-list-fields/model-list-fields-selector/model-list-fields-selector.component.mjs +0 -64
  89. package/esm2020/lib/modellist/model-list-filters/filters/model-list-autocomplete-filter/model-list-autocomplete-filter.component.mjs +0 -112
  90. package/esm2020/lib/modellist/model-list-filters/filters/model-list-autocomplete-multi-filter/model-list-autocomplete-multi-filter.component.mjs +0 -29
  91. package/esm2020/lib/modellist/model-list-filters/filters/model-list-date-filter/model-list-date-filter.component.mjs +0 -40
  92. package/esm2020/lib/modellist/model-list-filters/filters/model-list-datetime-filter/model-list-datetime-filter.component.mjs +0 -40
  93. package/esm2020/lib/modellist/model-list-filters/filters/model-list-datetimerange-filter/model-list-datetime-range-filter.component.mjs +0 -21
  94. package/esm2020/lib/modellist/model-list-filters/filters/model-list-flags-filter/model-list-flags-filter.component.mjs +0 -49
  95. package/esm2020/lib/modellist/model-list-filters/filters/model-list-geodistance-filter/model-list-geodistance-filter.component.mjs +0 -63
  96. package/esm2020/lib/modellist/model-list-filters/filters/model-list-number-filter/model-list-number-filter.component.mjs +0 -46
  97. package/esm2020/lib/modellist/model-list-filters/filters/model-list-select-filter/model-list-select-filter.component.mjs +0 -56
  98. package/esm2020/lib/modellist/model-list-filters/filters/model-list-select-multi-filter/model-list-select-multi-filter.component.mjs +0 -51
  99. package/esm2020/lib/modellist/model-list-filters/filters/model-list-text-filter/model-list-text-filter.component.mjs +0 -40
  100. package/esm2020/lib/modellist/model-list-filters/filters/model-list-tree-filter/model-list-tree-filter.component.mjs +0 -174
  101. package/esm2020/lib/modellist/model-list-filters/model-list-filters/model-list-filters.component.mjs +0 -50
  102. package/esm2020/lib/modellist/model-list-filters/model-list-filters-select/model-list-filters-select.component.mjs +0 -30
  103. package/esm2020/lib/modellist/model-list-paginator/model-list-paginator/model-list-paginator.component.mjs +0 -70
  104. package/esm2020/lib/modellist/model-list-sorter/model-list-sorter/model-list-sorter.component.mjs +0 -49
  105. package/esm2020/lib/modellist/model-list.service.mjs +0 -157
  106. package/esm2020/lib/routing/breadcrumb/breadcrumb.component.mjs +0 -142
  107. package/esm2020/lib/updates/update/update.component.mjs +0 -17
  108. package/esm2020/lib/updates/update.service.mjs +0 -58
  109. package/esm2020/lib/uploader/ng-file-drop.directive.mjs +0 -81
  110. package/esm2020/lib/uploader/ng-file-select.directive.mjs +0 -51
  111. package/esm2020/lib/uploader/ngx-uploader.module.mjs +0 -17
  112. package/esm2020/lib/utils/tab-memory.service.mjs +0 -80
  113. package/fesm2015/solidev-data.mjs +0 -6228
  114. package/fesm2015/solidev-data.mjs.map +0 -1
  115. /package/{esm2020 → esm2022}/lib/auth/jwt.mjs +0 -0
  116. /package/{esm2020 → esm2022}/lib/data/data-collection.mjs +0 -0
  117. /package/{esm2020 → esm2022}/lib/data/data-collection.mock.mjs +0 -0
  118. /package/{esm2020 → esm2022}/lib/data/data-parameters.mjs +0 -0
  119. /package/{esm2020 → esm2022}/lib/data/data-query.mjs +0 -0
  120. /package/{esm2020 → esm2022}/lib/data/data-query.mock.mjs +0 -0
  121. /package/{esm2020 → esm2022}/lib/data/fields/base.mjs +0 -0
  122. /package/{esm2020 → esm2022}/lib/data/fields/boolean.mjs +0 -0
  123. /package/{esm2020 → esm2022}/lib/data/fields/computed.mjs +0 -0
  124. /package/{esm2020 → esm2022}/lib/data/fields/datetime.mjs +0 -0
  125. /package/{esm2020 → esm2022}/lib/data/fields/index.mjs +0 -0
  126. /package/{esm2020 → esm2022}/lib/data/fields/numbers.mjs +0 -0
  127. /package/{esm2020 → esm2022}/lib/data/fields/primaryfield.mjs +0 -0
  128. /package/{esm2020 → esm2022}/lib/data/fields/relations.mjs +0 -0
  129. /package/{esm2020 → esm2022}/lib/data/fields/stringfields.mjs +0 -0
  130. /package/{esm2020 → esm2022}/lib/dispedit/dispedit/dispedit.constants.mjs +0 -0
  131. /package/{esm2020 → esm2022}/lib/modellist/model-list-fields/model-list-field-header/messages.mjs +0 -0
  132. /package/{esm2020 → esm2022}/lib/modellist/model-list-fields/model-list-fields.mjs +0 -0
  133. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/filtertypes.mjs +0 -0
  134. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-autocomplete-filter/model-list-autocomplete-filter.mjs +0 -0
  135. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-autocomplete-multi-filter/model-list-autocomplete-multi-filter.mjs +0 -0
  136. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-date-filter/model-list-date-filter.mjs +0 -0
  137. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-datetime-filter/model-list-datetime-filter.mjs +0 -0
  138. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-datetimerange-filter/model-list-datetimerange-filter.mjs +0 -0
  139. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-flags-filter/model-list-flags-filter.mjs +0 -0
  140. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-geodistance-filter/adapters/ban.mjs +0 -0
  141. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-geodistance-filter/model-list-geodistance-filter.mjs +0 -0
  142. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-number-filter/model-list-number-filter.mjs +0 -0
  143. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-select-filter/model-list-select-filter.mjs +0 -0
  144. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-select-multi-filter/model-list-select-multi-filter.mjs +0 -0
  145. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-text-filter/model-list-text-filter.mjs +0 -0
  146. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/filters/model-list-tree-filter/model-list-tree-filter.mjs +0 -0
  147. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/model-list-filter.mjs +0 -0
  148. /package/{esm2020 → esm2022}/lib/modellist/model-list-filters/model-list-filters.mjs +0 -0
  149. /package/{esm2020 → esm2022}/lib/modellist/model-list-paginator/model-list-paginator.mjs +0 -0
  150. /package/{esm2020 → esm2022}/lib/modellist/model-list-sorter/model-list-sorter.mjs +0 -0
  151. /package/{esm2020 → esm2022}/lib/routing/routing.mjs +0 -0
  152. /package/{esm2020 → esm2022}/lib/uploader/index.mjs +0 -0
  153. /package/{esm2020 → esm2022}/lib/uploader/interfaces.mjs +0 -0
  154. /package/{esm2020 → esm2022}/lib/uploader/ngx-uploader.class.mjs +0 -0
  155. /package/{esm2020 → esm2022}/lib/utils/slugify.mjs +0 -0
  156. /package/{esm2020 → esm2022}/lib/utils/template.mjs +0 -0
  157. /package/{esm2020 → esm2022}/public-api.mjs +0 -0
  158. /package/{esm2020 → esm2022}/solidev-data.mjs +0 -0
@@ -0,0 +1,481 @@
1
+ import { Component, EventEmitter, Inject, Input, Optional, Output, } from '@angular/core';
2
+ import { ReactiveFormsModule, UntypedFormGroup, } from '@angular/forms';
3
+ import { firstValueFrom } from 'rxjs';
4
+ import { FkselectComponent } from '../fkselect/fkselect.component';
5
+ import { BootstrapDataDisplayConfig, DATA_DISPLAY_CONFIG, } from '../../data/data-parameters';
6
+ import { CommonModule } from '@angular/common';
7
+ import { M2mselectComponent } from '../m2mselect/m2mselect.component';
8
+ import { ChoicePipe } from '../choice.pipe';
9
+ import * as i0 from "@angular/core";
10
+ import * as i1 from "../../messages/message.service";
11
+ import * as i2 from "@angular/common";
12
+ import * as i3 from "@angular/forms";
13
+ class DispeditComponent {
14
+ /**
15
+ * Constructor, can be given DATA_DISPLAY_CONFIG injection token to override display classes.
16
+ * By default, bs5 config is used
17
+ * @param dconf DataDisplayConfig item
18
+ * @param _msgs messages service
19
+ */
20
+ constructor(dconf, _msgs) {
21
+ this.dconf = dconf;
22
+ this._msgs = _msgs;
23
+ /**
24
+ * Starting edit mode
25
+ * If mode is inline, edit is always true.
26
+ */
27
+ this.edit = false;
28
+ /**
29
+ * Can be switched to edit mode?
30
+ * default : true
31
+ */
32
+ this.editable = true;
33
+ /**
34
+ * Display mode
35
+ * - dd provides display / edit within a dt/dd block
36
+ * - inline (to be renamed to form) provides a (label? and) form control
37
+ * */
38
+ this.mode = 'inline';
39
+ /**
40
+ * Custom choices
41
+ * If provided, a select form control will be used instead of base editor
42
+ */
43
+ this.choices = [];
44
+ /**
45
+ * Override placeholder, if provided.
46
+ * By default, manager.description is used
47
+ */
48
+ this.placeholder = '';
49
+ /**
50
+ * Override help, if provided.
51
+ * By default, manager.help is used.
52
+ */
53
+ this.help = '';
54
+ /**
55
+ * Hide label (for inline forms)
56
+ */
57
+ this.hideLabel = false;
58
+ /** Fk filter */
59
+ this.filter = {};
60
+ /** Output emitter, output model on every change */
61
+ this.changed = new EventEmitter();
62
+ /** Computed editor type */
63
+ this.realEditor = 'input.text';
64
+ /** Computed display type */
65
+ this.realDisplay = 'text';
66
+ /** Computed chocies type */
67
+ this.realChoices = [];
68
+ if (this.dconf === null) {
69
+ this.dconf = BootstrapDataDisplayConfig;
70
+ }
71
+ }
72
+ /**
73
+ * Init sequence.
74
+ * - Sets mode
75
+ * - Sets display function
76
+ * - Loads manager
77
+ * - Run misc checks on special values
78
+ * - Get help, placeholder strings
79
+ */
80
+ ngOnInit() {
81
+ this._setMode();
82
+ }
83
+ /**
84
+ * Upgrade all values on any change.
85
+ * @param changes
86
+ */
87
+ ngOnChanges(changes) {
88
+ this._setDisplayFn();
89
+ this.manager = this.model?.FM(this.field);
90
+ this.required = this.manager?.required || false;
91
+ this._checks();
92
+ this.realHelp = this.help || this.manager?.help || '';
93
+ this.realPlaceholder = this.placeholder || this.manager?.description || '';
94
+ this.realDefault = this.default;
95
+ this.save = this.save === undefined ? this.mode === 'dd' : this.save;
96
+ if ((!this.edit && this.mode === 'dd') ||
97
+ (!this.editable && this.mode === 'inline')) {
98
+ this.enableDisplayMode();
99
+ }
100
+ else {
101
+ this.enableEditMode();
102
+ }
103
+ }
104
+ /**
105
+ * Set up display mode.
106
+ * - get choices if available
107
+ * - get display type
108
+ * - process current value for display
109
+ * - set display classes
110
+ */
111
+ enableDisplayMode() {
112
+ this._getChoices();
113
+ this._getRealDisplay();
114
+ this._getDisplayValue();
115
+ this._setDisplayClasses();
116
+ this.edit = false;
117
+ }
118
+ /**
119
+ * Set up edit mode :
120
+ * - get choices if available
121
+ * - get editor type
122
+ * - prepare form controle
123
+ * - set form control value
124
+ * - update form control classes
125
+ */
126
+ enableEditMode() {
127
+ if (!this.editable) {
128
+ return;
129
+ }
130
+ this._getChoices();
131
+ this._getRealEditor();
132
+ this._setFormControl();
133
+ this._setFormControlValue();
134
+ this._setEditorClasses();
135
+ this.edit = true;
136
+ }
137
+ /**
138
+ * Update model field from form control value (if value is valid).
139
+ * If save boolean is true, save values to API.
140
+ */
141
+ async update() {
142
+ if (this.fg && this.model && this.fg.valid) {
143
+ switch (this.realEditor) {
144
+ case 'input.decimal':
145
+ this.model[this.field] = Math.round(this.fg.value[this.field] * this.manager.factor);
146
+ break;
147
+ default:
148
+ this.model[this.field] = this.fg.value[this.field];
149
+ }
150
+ if (this.save === true) {
151
+ return this._save();
152
+ }
153
+ }
154
+ }
155
+ unsetEdit() {
156
+ if (this.mode == 'dd' && this.edit) {
157
+ this.edit = false;
158
+ delete this.fg;
159
+ }
160
+ }
161
+ toggleEdit() {
162
+ if (!this.edit) {
163
+ this.enableEditMode();
164
+ }
165
+ else {
166
+ this.unsetEdit();
167
+ this.enableDisplayMode();
168
+ }
169
+ }
170
+ /**
171
+ * Reset field to default value
172
+ * TODO: check if edit mode needs to be changed / saved
173
+ */
174
+ async setDefault() {
175
+ if (this.model) {
176
+ this.model[this.field] = this.realDefault;
177
+ this.fg.controls[this.field].setValue(this.realDefault, {
178
+ emitEvent: false,
179
+ });
180
+ }
181
+ await this.update();
182
+ }
183
+ async selectedRefItem($event) {
184
+ if (this.model) {
185
+ if ($event !== null) {
186
+ this.model[this.field] = $event.id;
187
+ this.model[`${this.field}_details`] = $event;
188
+ if (this.form) {
189
+ const fv = {};
190
+ fv[this.field] = $event.id;
191
+ this.form.patchValue(fv, { emitEvent: true });
192
+ this.form.markAsTouched();
193
+ this.form.markAsDirty();
194
+ }
195
+ }
196
+ else {
197
+ this.model[this.field] = null;
198
+ delete this.model[`${this.field}_details`];
199
+ if (this.form) {
200
+ const fv = {};
201
+ fv[this.field] = null;
202
+ this.form.patchValue(fv, { emitEvent: true });
203
+ this.form.markAsTouched();
204
+ this.form.markAsDirty();
205
+ }
206
+ }
207
+ return this._save();
208
+ }
209
+ }
210
+ onM2MValuesChanges(v) {
211
+ this.m2mValues = v;
212
+ }
213
+ _checks() {
214
+ if (this.editor === 'quill' && !this.viewer) {
215
+ this.viewer = 'quill';
216
+ }
217
+ }
218
+ /**
219
+ * Save value to database, only if model have an id.
220
+ * If mode is dd, toggle edit / display mode.
221
+ * @private
222
+ */
223
+ async _save() {
224
+ if (this.model) {
225
+ if (this.model.id) {
226
+ try {
227
+ await firstValueFrom(this.model.update([this.field], { updateModel: true }));
228
+ }
229
+ catch (e) {
230
+ console.error(e);
231
+ let msg = '';
232
+ if (e && e.error && e.error[this.field]) {
233
+ msg = `${e.error[this.field]}`;
234
+ }
235
+ this._msgs.error("Erreur lors de l'enregistrement", msg, JSON.stringify(e));
236
+ return;
237
+ }
238
+ }
239
+ if (this.mode === 'dd') {
240
+ this.unsetEdit();
241
+ this.enableDisplayMode();
242
+ }
243
+ this.changed.next(this.model);
244
+ }
245
+ }
246
+ _display(x) {
247
+ if (x) {
248
+ if (x._display) {
249
+ if (x._display instanceof Function) {
250
+ return x._display();
251
+ }
252
+ else {
253
+ return x._display;
254
+ }
255
+ }
256
+ if (this._tpl) {
257
+ return this._tpl(x);
258
+ }
259
+ }
260
+ return '';
261
+ }
262
+ /**
263
+ * Set display mode based on current display config
264
+ * @private
265
+ */
266
+ _setMode() {
267
+ if (!this.mode) {
268
+ this.mode = this.dconf.dispEdit.defaultMode;
269
+ }
270
+ }
271
+ _setDisplayFn() {
272
+ if (this.display) {
273
+ if (this.display && typeof this.display === 'string') {
274
+ this._tpl = (model) => `${model[this.display]}`;
275
+ }
276
+ else if (this.display && typeof this.display === 'function') {
277
+ this._tpl = this.display.bind(this);
278
+ }
279
+ }
280
+ else {
281
+ this._tpl = (model) => `${model['name'] ||
282
+ model['title'] ||
283
+ model['id']}`;
284
+ }
285
+ }
286
+ _getChoices() {
287
+ // Set display choices
288
+ let choices;
289
+ if (this.choices && this.choices.length) {
290
+ choices = this.choices;
291
+ }
292
+ else if (this.manager?.choices) {
293
+ choices = this.manager?.choices;
294
+ }
295
+ // Set display value
296
+ if (choices && choices.length > 0) {
297
+ this.realChoices = choices;
298
+ }
299
+ else {
300
+ delete this.realChoices;
301
+ }
302
+ }
303
+ _getRealDisplay() {
304
+ this.realDisplay = this.viewer
305
+ ? this.viewer
306
+ : this.manager?.displayType
307
+ ? this.manager.displayType
308
+ : 'text';
309
+ if (this.realChoices && this.realChoices.length) {
310
+ this.realDisplay = 'choice';
311
+ }
312
+ }
313
+ _getRealEditor() {
314
+ this.realEditor = this.editor
315
+ ? this.editor
316
+ : this.manager?.editorType || 'input.text';
317
+ if (this.realChoices && this.realChoices.length) {
318
+ this.realEditor = 'select';
319
+ }
320
+ }
321
+ _setFormControl() {
322
+ if (!this.form) {
323
+ const fgc = {};
324
+ fgc[this.field] = this.model.FC(this.field);
325
+ this.fg = new UntypedFormGroup(fgc);
326
+ }
327
+ else {
328
+ this.fg = this.form;
329
+ this.fg.setControl(this.field, this.model.FC(this.field), {
330
+ emitEvent: false,
331
+ });
332
+ }
333
+ if (this.mode === 'inline') {
334
+ this.fg.valueChanges.subscribe(() => {
335
+ this.update();
336
+ });
337
+ }
338
+ }
339
+ _setFormControlValue() {
340
+ switch (this.realEditor) {
341
+ case 'input.datetime':
342
+ const value = this.model[this.field];
343
+ const now = new Date();
344
+ const localnow = new Date(now.getTime() - now.getTimezoneOffset() * 60000);
345
+ if (value === null) {
346
+ this.fg.controls[this.field].setValue(null, { emitEvent: true });
347
+ }
348
+ else {
349
+ const time = value ? new Date(value) : new Date();
350
+ const offset = time.getTimezoneOffset();
351
+ const localtime = new Date(time.getTime() - offset * 60000);
352
+ this.fg.controls[this.field].setValue(localtime.toISOString().substring(0, 16), { emitEvent: true });
353
+ }
354
+ this.realDefault =
355
+ this.default || this.manager?.required
356
+ ? localnow.toISOString().substring(0, 16)
357
+ : null;
358
+ break;
359
+ case 'input.date':
360
+ const dt = this.model.toJson([this.field])[this.field];
361
+ this.fg.controls[this.field].setValue(dt);
362
+ break;
363
+ case 'input.decimal':
364
+ this.fg.controls[this.field].setValue(this.model[this.field] /
365
+ (this.manager.factor || 1));
366
+ }
367
+ }
368
+ _setEditorClasses() {
369
+ // FIXME: use realEditorClasses
370
+ if (!this.inputClasses) {
371
+ this.inputClasses =
372
+ this.dconf.dispEdit.inputClasses[this.realEditor] || '';
373
+ }
374
+ }
375
+ _getDisplayValue() {
376
+ const value = this.model[this.field];
377
+ this.dispValue = value;
378
+ if (this.realChoices) {
379
+ for (const c of this.realChoices) {
380
+ if (c === value) {
381
+ this.txtValue = c;
382
+ return;
383
+ }
384
+ else if (c.value !== undefined && c.value === value) {
385
+ this.txtValue = c.desc;
386
+ return;
387
+ }
388
+ }
389
+ }
390
+ // Set display text depending on value and realDisplay value
391
+ if (value === true) {
392
+ this.txtValue = 'OUI';
393
+ }
394
+ else if (value === false) {
395
+ this.txtValue = 'NON';
396
+ }
397
+ else if (value === undefined || value === null) {
398
+ this.txtValue = 'non défini';
399
+ }
400
+ else {
401
+ switch (this.realDisplay) {
402
+ case 'fkdetails':
403
+ const details = this.model[`${this.field}_details`];
404
+ this.txtValue = this._display(details);
405
+ break;
406
+ case 'm2mdetails':
407
+ const m2mDetails = this.m2mValues ||
408
+ this.model[`${this.field}_details`];
409
+ this.txtValues = [];
410
+ for (const v of m2mDetails) {
411
+ this.txtValues.push(this._display(v));
412
+ }
413
+ break;
414
+ case 'decimal':
415
+ this.txtValue = `${value /
416
+ (this.manager.factor || 1)}`;
417
+ break;
418
+ default:
419
+ this.txtValue = `${value}`;
420
+ }
421
+ }
422
+ }
423
+ _setDisplayClasses() { }
424
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: DispeditComponent, deps: [{ token: DATA_DISPLAY_CONFIG, optional: true }, { token: i1.DataMessageService }], target: i0.ɵɵFactoryTarget.Component }); }
425
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: DispeditComponent, isStandalone: true, selector: "data-dispedit", inputs: { model: "model", field: "field", form: "form", edit: "edit", editable: "editable", mode: "mode", choices: "choices", inputClasses: "inputClasses", editor: "editor", viewer: "viewer", default: "default", placeholder: "placeholder", help: "help", hideLabel: "hideLabel", queryset: "queryset", collection: "collection", display: "display", filter: "filter" }, outputs: { changed: "changed" }, usesOnChanges: true, ngImport: i0, template: "\n<ng-template #titleTpl>\n <ng-content></ng-content>\n</ng-template>\n<ng-template #dispTpl>\n <ng-container [ngSwitch]=\"realDisplay\"><span class=\"editable disp-text\" *ngSwitchCase=\"'text'\" (click)=\"enableEditMode()\">{{txtValue}}</span><span class=\"editable disp-choice\" *ngSwitchCase=\"'choice'\" (click)=\"enableEditMode()\">{{txtValue}}</span><span class=\"editable disp-decimal\" *ngSwitchCase=\"'decimal'\" (click)=\"enableEditMode()\">{{txtValue}}</span><span class=\"editable disp-boolean\" *ngSwitchCase=\"'boolean'\" (click)=\"enableEditMode()\">{{txtValue}}</span><span class=\"editable disp-fkdetails\" *ngSwitchCase=\"'fkdetails'\" (click)=\"enableEditMode()\">\n <div class=\"fkitem\">{{txtValue}}</div></span><span class=\"editable disp-m2mdetails\" *ngSwitchCase=\"'m2mdetails'\" (click)=\"enableEditMode()\">\n <div class=\"m2mitem\" *ngFor=\"let v of txtValues\">{{v}}</div></span><span class=\"editable disp-datetime\" *ngSwitchCase=\"'datetime'\" (click)=\"enableEditMode()\">\n <ng-container *ngIf=\"dispValue\">{{txtValue|date:'short'}}</ng-container>\n <ng-container *ngIf=\"!dispValue\">{{txtValue}}</ng-container></span><span class=\"editable disp-datetime\" *ngSwitchCase=\"'date'\" (click)=\"enableEditMode()\">\n <ng-container *ngIf=\"dispValue\">{{txtValue|date:'shortDate'}}</ng-container>\n <ng-container *ngIf=\"!dispValue\">{{txtValue}}</ng-container></span></ng-container>\n</ng-template>\n<ng-template #editTpl let-form=\"form\">\n <ng-container [ngSwitch]=\"realEditor\">\n <ng-container *ngSwitchCase=\"'input.text'\">\n <input type=\"text\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" [placeholder]=\"realPlaceholder\">\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minlength']\">Trop court : {{$any(manager).minLength}} caract\u00E8res minimum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxlength']\">Trop long : {{$any(manager).maxLength}} caract\u00E8res maximum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['pattern']\">Format invalide...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.email'\">\n <input type=\"email\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" [placeholder]=\"realPlaceholder\">\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minlength']\">Trop court : {{$any(manager).minLength}} caract\u00E8res minimum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxlength']\">Trop long : {{$any(manager).maxLength}} caract\u00E8res maximum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['pattern']\">Format invalide...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['email']\">Format d'email invalide...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.password'\">\n <input type=\"password\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" [placeholder]=\"realPlaceholder\">\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minlength']\">Trop court : {{$any(manager).minLength}} caract\u00E8res minimum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxlength']\">Trop long : {{$any(manager).maxLength}} caract\u00E8res maximum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['pattern']\">Format invalide...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.datetime'\">\n <input type=\"datetime-local\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" (keyup.enter)=\"update()\">\n <div class=\"form-text\">{{realHelp}}</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minDate']\">Doit \u00EAtre post\u00E9rieur \u00E0 {{$any(manager).min|date:'short'}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxDate']\">Doit \u00EAtre ant\u00E9rieur \u00E0 {{$any(manager).max|date:'short'}}...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.date'\">\n <input type=\"date\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" (keyup.enter)=\"update()\">\n <div class=\"form-text\">{{realHelp}}</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minDate']\">Doit \u00EAtre post\u00E9rieur \u00E0 {{$any(manager).min|date:'short'}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxDate']\">Doit \u00EAtre ant\u00E9rieur \u00E0 {{$any(manager).max|date:'short'}}...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.number'\">\n <input type=\"number\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" [placeholder]=\"realPlaceholder\">\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['min']\">Trop petit : minimum {{$any(manager).min}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['max']\">Trop grand : maximum {{$any(manager).max}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.decimal'\">\n <input type=\"number\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" [placeholder]=\"realPlaceholder\">\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['min']\">Trop petit : minimum {{$any(manager).min}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['max']\">Trop grand : maximum {{$any(manager).max}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.checkbox'\">\n <input class=\"form-check-input\" type=\"checkbox\" [formControl]=\"form.get(field)\" (keyup.escape)=\"unsetEdit()\" (change)=\"update()\">\n <div class=\"form-text\">{{realHelp}}</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'textarea'\">\n <textarea [formControl]=\"form.get(field)\" (keyup.escape)=\"unsetEdit()\" [ngClass]=\"inputClasses\" (keyup.control.enter)=\"update()\" [placeholder]=\"realPlaceholder\"></textarea>\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minlength']\">Trop court : {{$any(manager).minLength}} caract\u00E8res minimum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxlength']\">Trop long : {{$any(manager).maxLength}} caract\u00E8res maximum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['pattern']\">Format invalide...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'fkselect'\">\n <data-fkselect [collection]=\"collection\" [filter]=\"filter\" (selected)=\"selectedRefItem($event)\" [placeholder]=\"placeholder\" (cancelled)=\"unsetEdit()\" (cleared)=\"selectedRefItem(null)\"></data-fkselect>\n </ng-container>\n <ng-container *ngSwitchCase=\"'m2mselect'\">\n <data-m2mselect [collection]=\"collection\" [filter]=\"filter\" (changed)=\"update()\" [formControl]=\"form.get(field)\" (detailsChanged)=\"onM2MValuesChanges($event)\" [model]=\"model\" [field]=\"field\" [placeholder]=\"placeholder\"></data-m2mselect>\n </ng-container>\n <ng-container *ngSwitchCase=\"'select'\">\n <select [formControl]=\"form.get(field)\" (keyup.escape)=\"unsetEdit()\" (change)=\"update()\" [ngClass]=\"inputClasses\">\n <option *ngFor=\"let c of realChoices\" [ngValue]=\"c.value!==undefined ? c.value : c\">{{c.desc ? c.desc : c}}</option>\n </select>\n <div class=\"form-text\">{{realHelp}}</div>\n </ng-container>\n </ng-container>\n</ng-template>\n<!-- Disp/edit toggler-->\n<ng-template #dispeditTpl>\n <ng-container *ngIf=\"!edit\">\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"edit\">\n <ng-container *ngIf=\"fg\">\n <form [formGroup]=\"fg\" (submit)=\"update()\">\n <ng-container *ngTemplateOutlet=\"editTpl; context: {form: fg}\"></ng-container>\n </form>\n </ng-container>\n </ng-container>\n</ng-template>\n<!-- DispEdit noform-->\n<ng-template #dispeditFormTpl>\n <ng-container *ngIf=\"!edit\">\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"edit\">\n <ng-container *ngIf=\"form\">\n <ng-container *ngTemplateOutlet=\"editTpl; context: {form: form}\"></ng-container>\n </ng-container>\n </ng-container>\n</ng-template>\n<!-- Dd display-->\n<ng-container *ngIf=\"mode==='dd'\">\n <dt [class.required]=\"required\" *ngIf=\"!hideLabel\"><span class=\"editable\" (click)=\"toggleEdit()\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container></span><span class=\"pointer float-end\" (click)=\"setDefault()\" *ngIf=\"realDefault!== undefined &amp;&amp; edit\"><i class=\"bi bi-trash ms-2\"></i></span></dt>\n <dd [class.mb-0]=\"hideLabel\">\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n </dd>\n</ng-container>\n<!-- Inline display-->\n<ng-container *ngIf=\"mode==='inline'\">\n <ng-container *ngIf=\"!hideLabel\"><span class=\"pointer float-end\" (click)=\"setDefault()\" *ngIf=\"realDefault!== undefined &amp;&amp; edit\"><i class=\"bi bi-trash ms-2\"></i></span>\n <label [class.required]=\"required\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n </ng-container>\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n</ng-container>\n<!-- Form display-->\n<ng-container *ngIf=\"mode==='form'\">\n <ng-container *ngIf=\"!hideLabel\"><span class=\"pointer float-end\" (click)=\"setDefault()\" *ngIf=\"realDefault!== undefined &amp;&amp; edit\"><i class=\"bi bi-trash ms-2\"></i></span>\n <label [class.required]=\"required\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n </ng-container>\n <ng-container *ngTemplateOutlet=\"dispeditFormTpl\"></ng-container>\n</ng-container>", styles: [".editable{cursor:pointer}form.inline{display:inline-block}.required{font-weight:700}.required:after{content:\" (*)\"}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i2.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i3.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i3.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i3.CheckboxControlValueAccessor, selector: "input[type=checkbox][formControlName],input[type=checkbox][formControl],input[type=checkbox][ngModel]" }, { kind: "directive", type: i3.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i3.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i3.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: FkselectComponent, selector: "data-fkselect", inputs: ["model", "field", "edit", "value", "queryset", "collection", "update", "filter", "mode", "display", "search", "label", "placeholder", "inputClasses"], outputs: ["selected", "cancelled", "cleared"] }, { kind: "component", type: M2mselectComponent, selector: "data-m2mselect", inputs: ["model", "field", "edit", "values", "queryset", "collection", "filter", "mode", "display", "search", "label", "placeholder", "emptyLabel", "inputClasses"], outputs: ["added", "removed", "cancelled", "cleared", "detailsChanged", "changed"] }] }); }
426
+ }
427
+ export { DispeditComponent };
428
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: DispeditComponent, decorators: [{
429
+ type: Component,
430
+ args: [{ selector: 'data-dispedit', standalone: true, imports: [
431
+ CommonModule,
432
+ ReactiveFormsModule,
433
+ FkselectComponent,
434
+ M2mselectComponent,
435
+ ChoicePipe,
436
+ ], template: "\n<ng-template #titleTpl>\n <ng-content></ng-content>\n</ng-template>\n<ng-template #dispTpl>\n <ng-container [ngSwitch]=\"realDisplay\"><span class=\"editable disp-text\" *ngSwitchCase=\"'text'\" (click)=\"enableEditMode()\">{{txtValue}}</span><span class=\"editable disp-choice\" *ngSwitchCase=\"'choice'\" (click)=\"enableEditMode()\">{{txtValue}}</span><span class=\"editable disp-decimal\" *ngSwitchCase=\"'decimal'\" (click)=\"enableEditMode()\">{{txtValue}}</span><span class=\"editable disp-boolean\" *ngSwitchCase=\"'boolean'\" (click)=\"enableEditMode()\">{{txtValue}}</span><span class=\"editable disp-fkdetails\" *ngSwitchCase=\"'fkdetails'\" (click)=\"enableEditMode()\">\n <div class=\"fkitem\">{{txtValue}}</div></span><span class=\"editable disp-m2mdetails\" *ngSwitchCase=\"'m2mdetails'\" (click)=\"enableEditMode()\">\n <div class=\"m2mitem\" *ngFor=\"let v of txtValues\">{{v}}</div></span><span class=\"editable disp-datetime\" *ngSwitchCase=\"'datetime'\" (click)=\"enableEditMode()\">\n <ng-container *ngIf=\"dispValue\">{{txtValue|date:'short'}}</ng-container>\n <ng-container *ngIf=\"!dispValue\">{{txtValue}}</ng-container></span><span class=\"editable disp-datetime\" *ngSwitchCase=\"'date'\" (click)=\"enableEditMode()\">\n <ng-container *ngIf=\"dispValue\">{{txtValue|date:'shortDate'}}</ng-container>\n <ng-container *ngIf=\"!dispValue\">{{txtValue}}</ng-container></span></ng-container>\n</ng-template>\n<ng-template #editTpl let-form=\"form\">\n <ng-container [ngSwitch]=\"realEditor\">\n <ng-container *ngSwitchCase=\"'input.text'\">\n <input type=\"text\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" [placeholder]=\"realPlaceholder\">\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minlength']\">Trop court : {{$any(manager).minLength}} caract\u00E8res minimum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxlength']\">Trop long : {{$any(manager).maxLength}} caract\u00E8res maximum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['pattern']\">Format invalide...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.email'\">\n <input type=\"email\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" [placeholder]=\"realPlaceholder\">\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minlength']\">Trop court : {{$any(manager).minLength}} caract\u00E8res minimum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxlength']\">Trop long : {{$any(manager).maxLength}} caract\u00E8res maximum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['pattern']\">Format invalide...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['email']\">Format d'email invalide...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.password'\">\n <input type=\"password\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" [placeholder]=\"realPlaceholder\">\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minlength']\">Trop court : {{$any(manager).minLength}} caract\u00E8res minimum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxlength']\">Trop long : {{$any(manager).maxLength}} caract\u00E8res maximum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['pattern']\">Format invalide...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.datetime'\">\n <input type=\"datetime-local\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" (keyup.enter)=\"update()\">\n <div class=\"form-text\">{{realHelp}}</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minDate']\">Doit \u00EAtre post\u00E9rieur \u00E0 {{$any(manager).min|date:'short'}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxDate']\">Doit \u00EAtre ant\u00E9rieur \u00E0 {{$any(manager).max|date:'short'}}...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.date'\">\n <input type=\"date\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" (keyup.enter)=\"update()\">\n <div class=\"form-text\">{{realHelp}}</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minDate']\">Doit \u00EAtre post\u00E9rieur \u00E0 {{$any(manager).min|date:'short'}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxDate']\">Doit \u00EAtre ant\u00E9rieur \u00E0 {{$any(manager).max|date:'short'}}...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.number'\">\n <input type=\"number\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" [placeholder]=\"realPlaceholder\">\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['min']\">Trop petit : minimum {{$any(manager).min}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['max']\">Trop grand : maximum {{$any(manager).max}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.decimal'\">\n <input type=\"number\" [formControl]=\"form.get(field)\" [ngClass]=\"inputClasses\" (keyup.escape)=\"unsetEdit()\" [placeholder]=\"realPlaceholder\">\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['min']\">Trop petit : minimum {{$any(manager).min}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['max']\">Trop grand : maximum {{$any(manager).max}}...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'input.checkbox'\">\n <input class=\"form-check-input\" type=\"checkbox\" [formControl]=\"form.get(field)\" (keyup.escape)=\"unsetEdit()\" (change)=\"update()\">\n <div class=\"form-text\">{{realHelp}}</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'textarea'\">\n <textarea [formControl]=\"form.get(field)\" (keyup.escape)=\"unsetEdit()\" [ngClass]=\"inputClasses\" (keyup.control.enter)=\"update()\" [placeholder]=\"realPlaceholder\"></textarea>\n <div class=\"form-text\" *ngIf=\"realHelp\">{{realHelp}}<span class=\"ms-1\" *ngIf=\"required\">(requis)</span></div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['minlength']\">Trop court : {{$any(manager).minLength}} caract\u00E8res minimum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['maxlength']\">Trop long : {{$any(manager).maxLength}} caract\u00E8res maximum...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['pattern']\">Format invalide...</div>\n <div class=\"invalid-feedback mt-0\" [class.d-block]=\"form &amp;&amp; !form.controls[field].pristine &amp;&amp; form.controls[field].errors?.['required']\">Ce champ est requis...</div>\n </ng-container>\n <ng-container *ngSwitchCase=\"'fkselect'\">\n <data-fkselect [collection]=\"collection\" [filter]=\"filter\" (selected)=\"selectedRefItem($event)\" [placeholder]=\"placeholder\" (cancelled)=\"unsetEdit()\" (cleared)=\"selectedRefItem(null)\"></data-fkselect>\n </ng-container>\n <ng-container *ngSwitchCase=\"'m2mselect'\">\n <data-m2mselect [collection]=\"collection\" [filter]=\"filter\" (changed)=\"update()\" [formControl]=\"form.get(field)\" (detailsChanged)=\"onM2MValuesChanges($event)\" [model]=\"model\" [field]=\"field\" [placeholder]=\"placeholder\"></data-m2mselect>\n </ng-container>\n <ng-container *ngSwitchCase=\"'select'\">\n <select [formControl]=\"form.get(field)\" (keyup.escape)=\"unsetEdit()\" (change)=\"update()\" [ngClass]=\"inputClasses\">\n <option *ngFor=\"let c of realChoices\" [ngValue]=\"c.value!==undefined ? c.value : c\">{{c.desc ? c.desc : c}}</option>\n </select>\n <div class=\"form-text\">{{realHelp}}</div>\n </ng-container>\n </ng-container>\n</ng-template>\n<!-- Disp/edit toggler-->\n<ng-template #dispeditTpl>\n <ng-container *ngIf=\"!edit\">\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"edit\">\n <ng-container *ngIf=\"fg\">\n <form [formGroup]=\"fg\" (submit)=\"update()\">\n <ng-container *ngTemplateOutlet=\"editTpl; context: {form: fg}\"></ng-container>\n </form>\n </ng-container>\n </ng-container>\n</ng-template>\n<!-- DispEdit noform-->\n<ng-template #dispeditFormTpl>\n <ng-container *ngIf=\"!edit\">\n <ng-container *ngTemplateOutlet=\"dispTpl\"></ng-container>\n </ng-container>\n <ng-container *ngIf=\"edit\">\n <ng-container *ngIf=\"form\">\n <ng-container *ngTemplateOutlet=\"editTpl; context: {form: form}\"></ng-container>\n </ng-container>\n </ng-container>\n</ng-template>\n<!-- Dd display-->\n<ng-container *ngIf=\"mode==='dd'\">\n <dt [class.required]=\"required\" *ngIf=\"!hideLabel\"><span class=\"editable\" (click)=\"toggleEdit()\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container></span><span class=\"pointer float-end\" (click)=\"setDefault()\" *ngIf=\"realDefault!== undefined &amp;&amp; edit\"><i class=\"bi bi-trash ms-2\"></i></span></dt>\n <dd [class.mb-0]=\"hideLabel\">\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n </dd>\n</ng-container>\n<!-- Inline display-->\n<ng-container *ngIf=\"mode==='inline'\">\n <ng-container *ngIf=\"!hideLabel\"><span class=\"pointer float-end\" (click)=\"setDefault()\" *ngIf=\"realDefault!== undefined &amp;&amp; edit\"><i class=\"bi bi-trash ms-2\"></i></span>\n <label [class.required]=\"required\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n </ng-container>\n <ng-container *ngTemplateOutlet=\"dispeditTpl\"></ng-container>\n</ng-container>\n<!-- Form display-->\n<ng-container *ngIf=\"mode==='form'\">\n <ng-container *ngIf=\"!hideLabel\"><span class=\"pointer float-end\" (click)=\"setDefault()\" *ngIf=\"realDefault!== undefined &amp;&amp; edit\"><i class=\"bi bi-trash ms-2\"></i></span>\n <label [class.required]=\"required\">\n <ng-container *ngTemplateOutlet=\"titleTpl\"></ng-container>\n </label>\n </ng-container>\n <ng-container *ngTemplateOutlet=\"dispeditFormTpl\"></ng-container>\n</ng-container>", styles: [".editable{cursor:pointer}form.inline{display:inline-block}.required{font-weight:700}.required:after{content:\" (*)\"}\n"] }]
437
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
438
+ type: Optional
439
+ }, {
440
+ type: Inject,
441
+ args: [DATA_DISPLAY_CONFIG]
442
+ }] }, { type: i1.DataMessageService }]; }, propDecorators: { model: [{
443
+ type: Input
444
+ }], field: [{
445
+ type: Input
446
+ }], form: [{
447
+ type: Input
448
+ }], edit: [{
449
+ type: Input
450
+ }], editable: [{
451
+ type: Input
452
+ }], mode: [{
453
+ type: Input
454
+ }], choices: [{
455
+ type: Input
456
+ }], inputClasses: [{
457
+ type: Input
458
+ }], editor: [{
459
+ type: Input
460
+ }], viewer: [{
461
+ type: Input
462
+ }], default: [{
463
+ type: Input
464
+ }], placeholder: [{
465
+ type: Input
466
+ }], help: [{
467
+ type: Input
468
+ }], hideLabel: [{
469
+ type: Input
470
+ }], queryset: [{
471
+ type: Input
472
+ }], collection: [{
473
+ type: Input
474
+ }], display: [{
475
+ type: Input
476
+ }], filter: [{
477
+ type: Input
478
+ }], changed: [{
479
+ type: Output
480
+ }] } });
481
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzcGVkaXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZGF0YS9zcmMvbGliL2Rpc3BlZGl0L2Rpc3BlZGl0L2Rpc3BlZGl0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2RhdGEvc3JjL2xpYi9kaXNwZWRpdC9kaXNwZWRpdC9kaXNwZWRpdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFlBQVksRUFDWixNQUFNLEVBQ04sS0FBSyxFQUdMLFFBQVEsRUFDUixNQUFNLEdBRVAsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxFQUNMLG1CQUFtQixFQUVuQixnQkFBZ0IsR0FDakIsTUFBTSxnQkFBZ0IsQ0FBQztBQUN4QixPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBUXRDLE9BQU8sRUFBRSxpQkFBaUIsRUFBVSxNQUFNLGdDQUFnQyxDQUFDO0FBRTNFLE9BQU8sRUFDTCwwQkFBMEIsRUFDMUIsbUJBQW1CLEdBRXBCLE1BQU0sNEJBQTRCLENBQUM7QUFFcEMsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQzs7Ozs7QUFFNUMsTUFhYSxpQkFBaUI7SUEyRzVCOzs7OztPQUtHO0lBQ0gsWUFDa0QsS0FBd0IsRUFDaEUsS0FBeUI7UUFEZSxVQUFLLEdBQUwsS0FBSyxDQUFtQjtRQUNoRSxVQUFLLEdBQUwsS0FBSyxDQUFvQjtRQTFHbkM7OztXQUdHO1FBQ2EsU0FBSSxHQUFHLEtBQUssQ0FBQztRQUM3Qjs7O1dBR0c7UUFDYSxhQUFRLEdBQUcsSUFBSSxDQUFDO1FBUWhDOzs7O2FBSUs7UUFD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QUNQLFlBQVk7d0JBQ1osbUJBQW1CO3dCQUNuQixpQkFBaUI7d0JBQ2pCLGtCQUFrQjt3QkFDbEIsVUFBVTtxQkFDWDs7MEJBb0hFLFFBQVE7OzBCQUFJLE1BQU07MkJBQUMsbUJBQW1COzZFQTlHekIsS0FBSztzQkFBcEIsS0FBSztnQkFFVSxLQUFLO3NCQUFwQixLQUFLO2dCQUVVLElBQUk7c0JBQW5CLEtBQUs7Z0JBS1UsSUFBSTtzQkFBbkIsS0FBSztnQkFLVSxRQUFRO3NCQUF2QixLQUFLO2dCQWFVLElBQUk7c0JBQW5CLEtBQUs7Z0JBS1UsT0FBTztzQkFBdEIsS0FBSztnQkFFVSxZQUFZO3NCQUEzQixLQUFLO2dCQUVVLE1BQU07c0JBQXJCLEtBQUs7Z0JBRVUsTUFBTTtzQkFBckIsS0FBSztnQkFFVSxPQUFPO3NCQUF0QixLQUFLO2dCQUtVLFdBQVc7c0JBQTFCLEtBQUs7Z0JBS1UsSUFBSTtzQkFBbkIsS0FBSztnQkFJVSxTQUFTO3NCQUF4QixLQUFLO2dCQUtVLFFBQVE7c0JBQXZCLEtBQUs7Z0JBRVUsVUFBVTtzQkFBekIsS0FBSztnQkFFVSxPQUFPO3NCQUF0QixLQUFLO2dCQUVVLE1BQU07c0JBQXJCLEtBQUs7Z0JBR1csT0FBTztzQkFBdkIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbmplY3QsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uSW5pdCxcbiAgT3B0aW9uYWwsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBEYXRhTW9kZWwgfSBmcm9tICcuLi8uLi9kYXRhL2RhdGEtbW9kZWwnO1xuaW1wb3J0IHsgQmFzZUZpZWxkTWFuYWdlciB9IGZyb20gJy4uLy4uL2RhdGEvZmllbGRzL2Jhc2UnO1xuaW1wb3J0IHtcbiAgUmVhY3RpdmVGb3Jtc01vZHVsZSxcbiAgVW50eXBlZEZvcm1Db250cm9sLFxuICBVbnR5cGVkRm9ybUdyb3VwLFxufSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBmaXJzdFZhbHVlRnJvbSB9IGZyb20gJ3J4anMnO1xuaW1wb3J0IHtcbiAgRElTUEVESVRfRElTUExBWV9UWVBFUyxcbiAgRElTUEVESVRfRURJVE9SX1RZUEVTLFxuICBJRGlzcEVkaXRDaG9pY2UsXG59IGZyb20gJy4vZGlzcGVkaXQuY29uc3RhbnRzJztcbmltcG9ydCB7IEZpbHRlckRhdGEsIFF1ZXJ5c2V0IH0gZnJvbSAnLi4vLi4vZGF0YS9kYXRhLXF1ZXJ5JztcbmltcG9ydCB7IENvbGxlY3Rpb24gfSBmcm9tICcuLi8uLi9kYXRhL2RhdGEtY29sbGVjdGlvbic7XG5pbXBvcnQgeyBGa3NlbGVjdENvbXBvbmVudCwgVHBsRnVuIH0gZnJvbSAnLi4vZmtzZWxlY3QvZmtzZWxlY3QuY29tcG9uZW50JztcbmltcG9ydCB7IERlY2ltYWxGaWVsZE1hbmFnZXIgfSBmcm9tICcuLi8uLi9kYXRhL2ZpZWxkcy9udW1iZXJzJztcbmltcG9ydCB7XG4gIEJvb3RzdHJhcERhdGFEaXNwbGF5Q29uZmlnLFxuICBEQVRBX0RJU1BMQVlfQ09ORklHLFxuICBEYXRhRGlzcGxheUNvbmZpZyxcbn0gZnJvbSAnLi4vLi4vZGF0YS9kYXRhLXBhcmFtZXRlcnMnO1xuaW1wb3J0IHsgRGF0YU1lc3NhZ2VTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vbWVzc2FnZXMvbWVzc2FnZS5zZXJ2aWNlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBNMm1zZWxlY3RDb21wb25lbnQgfSBmcm9tICcuLi9tMm1zZWxlY3QvbTJtc2VsZWN0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBDaG9pY2VQaXBlIH0gZnJvbSAnLi4vY2hvaWNlLnBpcGUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdkYXRhLWRpc3BlZGl0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2Rpc3BlZGl0LmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vZGlzcGVkaXQuY29tcG9uZW50LnNhc3MnXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIENvbW1vbk1vZHVsZSxcbiAgICBSZWFjdGl2ZUZvcm1zTW9kdWxlLFxuICAgIEZrc2VsZWN0Q29tcG9uZW50LFxuICAgIE0ybXNlbGVjdENvbXBvbmVudCxcbiAgICBDaG9pY2VQaXBlLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBEaXNwZWRpdENvbXBvbmVudDxGVCwgVCBleHRlbmRzIERhdGFNb2RlbCwgUiBleHRlbmRzIERhdGFNb2RlbD5cbiAgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlc1xue1xuICAvKiogTW9kZWwgKG1hbmRhdG9yeSkgKi9cbiAgQElucHV0KCkgcHVibGljIG1vZGVsITogVDtcbiAgLyoqIEZpZWxkIChtYW5kYXRvcnkpICovXG4gIEBJbnB1dCgpIHB1YmxpYyBmaWVsZCE6IHN0cmluZztcbiAgLyoqIEV4dGVybmFsIGZvcm0gKi9cbiAgQElucHV0KCkgcHVibGljIGZvcm0/OiBVbnR5cGVkRm9ybUdyb3VwO1xuICAvKipcbiAgICogU3RhcnRpbmcgZWRpdCBtb2RlXG4gICAqIElmIG1vZGUgaXMgaW5saW5lLCBlZGl0IGlzIGFsd2F5cyB0cnVlLlxuICAgKi9cbiAgQElucHV0KCkgcHVibGljIGVkaXQgPSBmYWxzZTtcbiAgLyoqXG4gICAqIENhbiBiZSBzd2l0Y2hlZCB0byBlZGl0IG1vZGU/XG4gICAqIGRlZmF1bHQgOiB0cnVlXG4gICAqL1xuICBASW5wdXQoKSBwdWJsaWMgZWRpdGFibGUgPSB0cnVlO1xuICAvKipcbiAgICogU2F2ZSB1cGRhdGVkIHZhbHVlcyA/XG4gICAqIElmIG5vdCBnaXZlbiwgZGVmYXVsdCB2YWx1ZSBkZXBlbmRzIG9uIG1vZGUgOlxuICAgKiAtIHNhdmUgaWYgbW9kZSBpcyBkZFxuICAgKiAtIGRvbid0IHNhdmUgaWYgbW9kZSBpcyBpbmxpbmVcbiAgICovXG4gIHB1YmxpYyBzYXZlPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIERpc3BsYXkgbW9kZVxuICAgKiAtIGRkIHByb3ZpZGVzIGRpc3BsYXkgLyBlZGl0IHdpdGhpbiBhIGR0L2RkIGJsb2NrXG4gICAqIC0gaW5saW5lICh0byBiZSByZW5hbWVkIHRvIGZvcm0pIHByb3ZpZGVzIGEgKGxhYmVsPyBhbmQpIGZvcm0gY29udHJvbFxuICAgKiAqL1xuICBASW5wdXQoKSBwdWJsaWMgbW9kZTogJ2RkJyB8ICdpbmxpbmUnIHwgJ2Zvcm0nID0gJ2lubGluZSc7XG4gIC8qKlxuICAgKiBDdXN0b20gY2hvaWNlc1xuICAgKiBJZiBwcm92aWRlZCwgYSBzZWxlY3QgZm9ybSBjb250cm9sIHdpbGwgYmUgdXNlZCBpbnN0ZWFkIG9mIGJhc2UgZWRpdG9yXG4gICAqL1xuICBASW5wdXQoKSBwdWJsaWMgY2hvaWNlczogSURpc3BFZGl0Q2hvaWNlW10gPSBbXTtcbiAgLyoqIEN1c3RvbSBpbnB1dCBjbGFzc2VzICovXG4gIEBJbnB1dCgpIHB1YmxpYyBpbnB1dENsYXNzZXMhOiBzdHJpbmdbXSB8IHN0cmluZztcbiAgLyoqIE92ZXJyaWRlIGVkaXRvciwgaWYgcHJvdmlkZWQgKi9cbiAgQElucHV0KCkgcHVibGljIGVkaXRvcj86IERJU1BFRElUX0VESVRPUl9UWVBFUztcbiAgLyoqIE92ZXJyaWRlIHZpZXdlciwgaWYgcHJvdmlkZWQgKi9cbiAgQElucHV0KCkgcHVibGljIHZpZXdlcj86IERJU1BFRElUX0RJU1BMQVlfVFlQRVM7XG4gIC8qKiBPdmVycmlkZSBkZWZhdWx0IHZhbHVlICovXG4gIEBJbnB1dCgpIHB1YmxpYyBkZWZhdWx0PzogYW55O1xuICAvKipcbiAgICogT3ZlcnJpZGUgcGxhY2Vob2xkZXIsIGlmIHByb3ZpZGVkLlxuICAgKiBCeSBkZWZhdWx0LCBtYW5hZ2VyLmRlc2NyaXB0aW9uIGlzIHVzZWRcbiAgICovXG4gIEBJbnB1dCgpIHB1YmxpYyBwbGFjZWhvbGRlcjogc3RyaW5nID0gJyc7XG4gIC8qKlxuICAgKiBPdmVycmlkZSBoZWxwLCBpZiBwcm92aWRlZC5cbiAgICogQnkgZGVmYXVsdCwgbWFuYWdlci5oZWxwIGlzIHVzZWQuXG4gICAqL1xuICBASW5wdXQoKSBwdWJsaWMgaGVscDogc3RyaW5nID0gJyc7XG4gIC8qKlxuICAgKiAgSGlkZSBsYWJlbCAoZm9yIGlubGluZSBmb3JtcylcbiAgICovXG4gIEBJbnB1dCgpIHB1YmxpYyBoaWRlTGFiZWw6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvLyBGSyBmaWVsZHNcbiAgLy8gVE9ETzogcmVuYW1lIGFzIGZrXyBvciByZWxhdGVkX1xuICAvKiogRmsgcXVlcnlzZXQgKi9cbiAgQElucHV0KCkgcHVibGljIHF1ZXJ5c2V0PzogUXVlcnlzZXQ8Uj47XG4gIC8qKiBGayBjb2xsZWN0aW9uICovXG4gIEBJbnB1dCgpIHB1YmxpYyBjb2xsZWN0aW9uPzogQ29sbGVjdGlvbjxSPjtcbiAgLyoqIEZrIGRpc3BsYXkgKi9cbiAgQElucHV0KCkgcHVibGljIGRpc3BsYXk/OiBzdHJpbmcgfCBUcGxGdW48Uj47XG4gIC8qKiBGayBmaWx0ZXIgKi9cbiAgQElucHV0KCkgcHVibGljIGZpbHRlcjogRmlsdGVyRGF0YSA9IHt9O1xuXG4gIC8qKiBPdXRwdXQgZW1pdHRlciwgb3V0cHV0IG1vZGVsIG9uIGV2ZXJ5IGNoYW5nZSAqL1xuICBAT3V0cHV0KCkgcHVibGljIGNoYW5nZWQgPSBuZXcgRXZlbnRFbWl0dGVyPFQ+KCk7XG5cbiAgLyoqIEZpZWxkIG1hbmFnZXIgKi9cbiAgcHVibGljIG1hbmFnZXI/OiBCYXNlRmllbGRNYW5hZ2VyPEZUPjtcblxuICAvKiogVGV4dCB2YWx1ZSB1c2VkIGZvciBkaXNwbGF5ICovXG4gIHB1YmxpYyB0eHRWYWx1ZT86IHN0cmluZztcbiAgLyoqIFRleHQgdmFsdWVzIHVzZWQgZm9yIG1hbnkgZGlzcGxheXMgKi9cbiAgcHVibGljIHR4dFZhbHVlcz86IHN0cmluZ1tdO1xuXG4gIC8qKiBDb21wdXRlZCBlZGl0b3IgdHlwZSAqL1xuICBwdWJsaWMgcmVhbEVkaXRvcjogRElTUEVESVRfRURJVE9SX1RZUEVTID0gJ2lucHV0LnRleHQnO1xuICAvKiogQ29tcHV0ZWQgZGlzcGxheSB0eXBlICovXG4gIHB1YmxpYyByZWFsRGlzcGxheTogRElTUEVESVRfRElTUExBWV9UWVBFUyA9ICd0ZXh0JztcbiAgLyoqIEN1cnJlbnQgZGlzcCByYXcgdmFsdWUgKi9cbiAgcHVibGljIGRpc3BWYWx1ZT86IGFueTtcbiAgLyoqIENvbXB1dGVkIGNob2NpZXMgdHlwZSAqL1xuICBwdWJsaWMgcmVhbENob2ljZXM/OiBJRGlzcEVkaXRDaG9pY2VbXSA9IFtdO1xuICAvKiogQ29tcHV0ZWQgaGVscCAqL1xuICBwdWJsaWMgcmVhbEhlbHAhOiBzdHJpbmc7XG4gIC8qKiBDb21wdXRlZCBwbGFjZWhvbGRlciAqL1xuICBwdWJsaWMgcmVhbFBsYWNlaG9sZGVyITogc3RyaW5nO1xuICAvKiogQ29tcHV0ZWQgcmVxdWlyZWQgKi9cbiAgcHVibGljIHJlcXVpcmVkITogYm9vbGVhbjtcbiAgLyoqIENvbXB1dGVkIGRlZmF1bHQgdmFsdWUgKi9cbiAgcHVibGljIHJlYWxEZWZhdWx0ITogYW55O1xuXG4gIHB1YmxpYyBtMm1WYWx1ZXM/OiBhbnlbXTtcblxuICAvLyBMb2NhbCBmb3JtIGdyb3VwXG4gIHB1YmxpYyBmZz86IFVudHlwZWRGb3JtR3JvdXA7XG5cbiAgLy8gRGlzcGxheSB0ZW1wbGF0ZSBmdW5jdGlvblxuICBwcml2YXRlIF90cGwhOiBUcGxGdW48Uj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdG9yLCBjYW4gYmUgZ2l2ZW4gREFUQV9ESVNQTEFZX0NPTkZJRyBpbmplY3Rpb24gdG9rZW4gdG8gb3ZlcnJpZGUgZGlzcGxheSBjbGFzc2VzLlxuICAgKiBCeSBkZWZhdWx0LCBiczUgY29uZmlnIGlzIHVzZWRcbiAgICogQHBhcmFtIGRjb25mIERhdGFEaXNwbGF5Q29uZmlnIGl0ZW1cbiAgICogQHBhcmFtIF9tc2dzIG1lc3NhZ2VzIHNlcnZpY2VcbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBPcHRpb25hbCgpIEBJbmplY3QoREFUQV9ESVNQTEFZX0NPTkZJRykgcHVibGljIGRjb25mOiBEYXRhRGlzcGxheUNvbmZpZyxcbiAgICBwcml2YXRlIF9tc2dzOiBEYXRhTWVzc2FnZVNlcnZpY2VcbiAgKSB7XG4gICAgaWYgKHRoaXMuZGNvbmYgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZGNvbmYgPSBCb290c3RyYXBEYXRhRGlzcGxheUNvbmZpZztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5pdCBzZXF1ZW5jZS5cbiAgICogLSBTZXRzIG1vZGVcbiAgICogLSBTZXRzIGRpc3BsYXkgZnVuY3Rpb25cbiAgICogLSBMb2FkcyBtYW5hZ2VyXG4gICAqIC0gUnVuIG1pc2MgY2hlY2tzIG9uIHNwZWNpYWwgdmFsdWVzXG4gICAqIC0gR2V0IGhlbHAsIHBsYWNlaG9sZGVyIHN0cmluZ3NcbiAgICovXG4gIHB1YmxpYyBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLl9zZXRNb2RlKCk7XG4gIH1cblxuICAvKipcbiAgICogVXBncmFkZSBhbGwgdmFsdWVzIG9uIGFueSBjaGFuZ2UuXG4gICAqIEBwYXJhbSBjaGFuZ2VzXG4gICAqL1xuICBwdWJsaWMgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIHRoaXMuX3NldERpc3BsYXlGbigpO1xuICAgIHRoaXMubWFuYWdlciA9IHRoaXMubW9kZWw/LkZNKHRoaXMuZmllbGQpO1xuICAgIHRoaXMucmVxdWlyZWQgPSB0aGlzLm1hbmFnZXI/LnJlcXVpcmVkIHx8IGZhbHNlO1xuICAgIHRoaXMuX2NoZWNrcygpO1xuICAgIHRoaXMucmVhbEhlbHAgPSB0aGlzLmhlbHAgfHwgdGhpcy5tYW5hZ2VyPy5oZWxwIHx8ICcnO1xuICAgIHRoaXMucmVhbFBsYWNlaG9sZGVyID0gdGhpcy5wbGFjZWhvbGRlciB8fCB0aGlzLm1hbmFnZXI/LmRlc2NyaXB0aW9uIHx8ICcnO1xuICAgIHRoaXMucmVhbERlZmF1bHQgPSB0aGlzLmRlZmF1bHQ7XG4gICAgdGhpcy5zYXZlID0gdGhpcy5zYXZlID09PSB1bmRlZmluZWQgPyB0aGlzLm1vZGUgPT09ICdkZCcgOiB0aGlzLnNhdmU7XG4gICAgaWYgKFxuICAgICAgKCF0aGlzLmVkaXQgJiYgdGhpcy5tb2RlID09PSAnZGQnKSB8fFxuICAgICAgKCF0aGlzLmVkaXRhYmxlICYmIHRoaXMubW9kZSA9PT0gJ2lubGluZScpXG4gICAgKSB7XG4gICAgICB0aGlzLmVuYWJsZURpc3BsYXlNb2RlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZW5hYmxlRWRpdE1vZGUoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0IHVwIGRpc3BsYXkgbW9kZS5cbiAgICogLSBnZXQgY2hvaWNlcyBpZiBhdmFpbGFibGVcbiAgICogLSBnZXQgZGlzcGxheSB0eXBlXG4gICAqIC0gcHJvY2VzcyBjdXJyZW50IHZhbHVlIGZvciBkaXNwbGF5XG4gICAqIC0gc2V0IGRpc3BsYXkgY2xhc3Nlc1xuICAgKi9cbiAgcHVibGljIGVuYWJsZURpc3BsYXlNb2RlKCkge1xuICAgIHRoaXMuX2dldENob2ljZXMoKTtcbiAgICB0aGlzLl9nZXRSZWFsRGlzcGxheSgpO1xuICAgIHRoaXMuX2dldERpc3BsYXlWYWx1ZSgpO1xuICAgIHRoaXMuX3NldERpc3BsYXlDbGFzc2VzKCk7XG4gICAgdGhpcy5lZGl0ID0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHVwIGVkaXQgbW9kZSA6XG4gICAqIC0gZ2V0IGNob2ljZXMgaWYgYXZhaWxhYmxlXG4gICAqIC0gZ2V0IGVkaXRvciB0eXBlXG4gICAqIC0gcHJlcGFyZSBmb3JtIGNvbnRyb2xlXG4gICAqIC0gc2V0IGZvcm0gY29udHJvbCB2YWx1ZVxuICAgKiAtIHVwZGF0ZSBmb3JtIGNvbnRyb2wgY2xhc3Nlc1xuICAgKi9cbiAgcHVibGljIGVuYWJsZUVkaXRNb2RlKCkge1xuICAgIGlmICghdGhpcy5lZGl0YWJsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLl9nZXRDaG9pY2VzKCk7XG4gICAgdGhpcy5fZ2V0UmVhbEVkaXRvcigpO1xuICAgIHRoaXMuX3NldEZvcm1Db250cm9sKCk7XG4gICAgdGhpcy5fc2V0Rm9ybUNvbnRyb2xWYWx1ZSgpO1xuICAgIHRoaXMuX3NldEVkaXRvckNsYXNzZXMoKTtcbiAgICB0aGlzLmVkaXQgPSB0cnVlO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSBtb2RlbCBmaWVsZCBmcm9tIGZvcm0gY29udHJvbCB2YWx1ZSAoaWYgdmFsdWUgaXMgdmFsaWQpLlxuICAgKiBJZiBzYXZlIGJvb2xlYW4gaXMgdHJ1ZSwgc2F2ZSB2YWx1ZXMgdG8gQVBJLlxuICAgKi9cbiAgcHVibGljIGFzeW5jIHVwZGF0ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5mZyAmJiB0aGlzLm1vZGVsICYmIHRoaXMuZmcudmFsaWQpIHtcbiAgICAgIHN3aXRjaCAodGhpcy5yZWFsRWRpdG9yKSB7XG4gICAgICAgIGNhc2UgJ2lucHV0LmRlY2ltYWwnOlxuICAgICAgICAgICh0aGlzLm1vZGVsIGFzIGFueSlbdGhpcy5maWVsZF0gPSBNYXRoLnJvdW5kKFxuICAgICAgICAgICAgdGhpcy5mZy52YWx1ZVt0aGlzLmZpZWxkXSAqICh0aGlzLm1hbmFnZXIgYXMgYW55KS5mYWN0b3JcbiAgICAgICAgICApO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICh0aGlzLm1vZGVsIGFzIGFueSlbdGhpcy5maWVsZF0gPSB0aGlzLmZnLnZhbHVlW3RoaXMuZmllbGRdO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuc2F2ZSA9PT0gdHJ1ZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc2F2ZSgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHVuc2V0RWRpdCgpIHtcbiAgICBpZiAodGhpcy5tb2RlID09ICdkZCcgJiYgdGhpcy5lZGl0KSB7XG4gICAgICB0aGlzLmVkaXQgPSBmYWxzZTtcbiAgICAgIGRlbGV0ZSB0aGlzLmZnO1xuICAgIH1cbiAgfVxuXG4gIHRvZ2dsZUVkaXQoKSB7XG4gICAgaWYgKCF0aGlzLmVkaXQpIHtcbiAgICAgIHRoaXMuZW5hYmxlRWRpdE1vZGUoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy51bnNldEVkaXQoKTtcbiAgICAgIHRoaXMuZW5hYmxlRGlzcGxheU1vZGUoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUmVzZXQgZmllbGQgdG8gZGVmYXVsdCB2YWx1ZVxuICAgKiBUT0RPOiBjaGVjayBpZiBlZGl0IG1vZGUgbmVlZHMgdG8gYmUgY2hhbmdlZCAvIHNhdmVkXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgc2V0RGVmYXVsdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5tb2RlbCkge1xuICAgICAgKHRoaXMubW9kZWwgYXMgYW55KVt0aGlzLmZpZWxkXSA9IHRoaXMucmVhbERlZmF1bHQ7XG4gICAgICB0aGlzLmZnIS5jb250cm9sc1t0aGlzLmZpZWxkXS5zZXRWYWx1ZSh0aGlzLnJlYWxEZWZhdWx0LCB7XG4gICAgICAgIGVtaXRFdmVudDogZmFsc2UsXG4gICAgICB9KTtcbiAgICB9XG4gICAgYXdhaXQgdGhpcy51cGRhdGUoKTtcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBzZWxlY3RlZFJlZkl0ZW0oJGV2ZW50OiBUIHwgbnVsbCkge1xuICAgIGlmICh0aGlzLm1vZGVsKSB7XG4gICAgICBpZiAoJGV2ZW50ICE9PSBudWxsKSB7XG4gICAgICAgICh0aGlzLm1vZGVsIGFzIGFueSlbdGhpcy5maWVsZF0gPSAkZXZlbnQuaWQ7XG4gICAgICAgICh0aGlzLm1vZGVsIGFzIGFueSlbYCR7dGhpcy5maWVsZH1fZGV0YWlsc2BdID0gJGV2ZW50O1xuICAgICAgICBpZiAodGhpcy5mb3JtKSB7XG4gICAgICAgICAgY29uc3QgZnY6IHsgW2luZGV4OiBzdHJpbmddOiBudW1iZXIgfCBudWxsIH0gPSB7fTtcbiAgICAgICAgICBmdlt0aGlzLmZpZWxkXSA9ICRldmVudC5pZDtcbiAgICAgICAgICB0aGlzLmZvcm0ucGF0Y2hWYWx1ZShmdiwgeyBlbWl0RXZlbnQ6IHRydWUgfSk7XG4gICAgICAgICAgdGhpcy5mb3JtLm1hcmtBc1RvdWNoZWQoKTtcbiAgICAgICAgICB0aGlzLmZvcm0ubWFya0FzRGlydHkoKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgKHRoaXMubW9kZWwgYXMgYW55KVt0aGlzLmZpZWxkXSA9IG51bGw7XG4gICAgICAgIGRlbGV0ZSAodGhpcy5tb2RlbCBhcyBhbnkpW2Ake3RoaXMuZmllbGR9X2RldGFpbHNgXTtcbiAgICAgICAgaWYgKHRoaXMuZm9ybSkge1xuICAgICAgICAgIGNvbnN0IGZ2OiB7IFtpbmRleDogc3RyaW5nXTogbnVtYmVyIHwgbnVsbCB9ID0ge307XG4gICAgICAgICAgZnZbdGhpcy5maWVsZF0gPSBudWxsO1xuICAgICAgICAgIHRoaXMuZm9ybS5wYXRjaFZhbHVlKGZ2LCB7IGVtaXRFdmVudDogdHJ1ZSB9KTtcbiAgICAgICAgICB0aGlzLmZvcm0ubWFya0FzVG91Y2hlZCgpO1xuICAgICAgICAgIHRoaXMuZm9ybS5tYXJrQXNEaXJ0eSgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gdGhpcy5fc2F2ZSgpO1xuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyBvbk0yTVZhbHVlc0NoYW5nZXModjogYW55W10pIHtcbiAgICB0aGlzLm0ybVZhbHVlcyA9IHY7XG4gIH1cblxuICBwcml2YXRlIF9jaGVja3MoKSB7XG4gICAgaWYgKHRoaXMuZWRpdG9yID09PSAncXVpbGwnICYmICF0aGlzLnZpZXdlcikge1xuICAgICAgdGhpcy52aWV3ZXIgPSAncXVpbGwnO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBTYXZlIHZhbHVlIHRvIGRhdGFiYXNlLCBvbmx5IGlmIG1vZGVsIGhhdmUgYW4gaWQuXG4gICAqIElmIG1vZGUgaXMgZGQsIHRvZ2dsZSBlZGl0IC8gZGlzcGxheSBtb2RlLlxuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBfc2F2ZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5tb2RlbCkge1xuICAgICAgaWYgKHRoaXMubW9kZWwuaWQpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBhd2FpdCBmaXJzdFZhbHVlRnJvbShcbiAgICAgICAgICAgIHRoaXMubW9kZWwudXBkYXRlKFt0aGlzLmZpZWxkXSwgeyB1cGRhdGVNb2RlbDogdHJ1ZSB9KVxuICAgICAgICAgICk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICAgIGxldCBtc2c6IHN0cmluZyA9ICcnO1xuICAgICAgICAgIGlmIChlICYmIChlIGFzIGFueSkuZXJyb3IgJiYgKGUgYXMgYW55KS5lcnJvclt0aGlzLmZpZWxkXSkge1xuICAgICAgICAgICAgbXNnID0gYCR7KGUgYXMgYW55KS5lcnJvclt0aGlzLmZpZWxkXX1gO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aGlzLl9tc2dzLmVycm9yKFxuICAgICAgICAgICAgXCJFcnJldXIgbG9ycyBkZSBsJ2VucmVnaXN0cmVtZW50XCIsXG4gICAgICAgICAgICBtc2csXG4gICAgICAgICAgICBKU09OLnN0cmluZ2lmeShlKVxuICAgICAgICAgICk7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5tb2RlID09PSAnZGQnKSB7XG4gICAgICAgIHRoaXMudW5zZXRFZGl0KCk7XG4gICAgICAgIHRoaXMuZW5hYmxlRGlzcGxheU1vZGUoKTtcbiAgICAgIH1cbiAgICAgIHRoaXMuY2hhbmdlZC5uZXh0KHRoaXMubW9kZWwpO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2Rpc3BsYXkoeDogYW55KTogYW55IHtcbiAgICBpZiAoeCkge1xuICAgICAgaWYgKHguX2Rpc3BsYXkpIHtcbiAgICAgICAgaWYgKHguX2Rpc3BsYXkgaW5zdGFuY2VvZiBGdW5jdGlvbikge1xuICAgICAgICAgIHJldHVybiB4Ll9kaXNwbGF5KCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgcmV0dXJuIHguX2Rpc3BsYXk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh0aGlzLl90cGwpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3RwbCh4KTtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICcnO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCBkaXNwbGF5IG1vZGUgYmFzZWQgb24gY3VycmVudCBkaXNwbGF5IGNvbmZpZ1xuICAgKiBAcHJpdmF0ZVxuICAgKi9cbiAgcHJpdmF0ZSBfc2V0TW9kZSgpIHtcbiAgICBpZiAoIXRoaXMubW9kZSkge1xuICAgICAgdGhpcy5tb2RlID0gdGhpcy5kY29uZi5kaXNwRWRpdC5kZWZhdWx0TW9kZTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9zZXREaXNwbGF5Rm4oKSB7XG4gICAgaWYgKHRoaXMuZGlzcGxheSkge1xuICAgICAgaWYgKHRoaXMuZGlzcGxheSAmJiB0eXBlb2YgdGhpcy5kaXNwbGF5ID09PSAnc3RyaW5nJykge1xuICAgICAgICB0aGlzLl90cGwgPSAobW9kZWw6IFIpID0+IGAkeyhtb2RlbCBhcyBhbnkpW3RoaXMuZGlzcGxheSBhcyBzdHJpbmddfWA7XG4gICAgICB9IGVsc2UgaWYgKHRoaXMuZGlzcGxheSAmJiB0eXBlb2YgdGhpcy5kaXNwbGF5ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHRoaXMuX3RwbCA9IHRoaXMuZGlzcGxheS5iaW5kKHRoaXMpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLl90cGwgPSAobW9kZWw6IFIpID0+XG4gICAgICAgIGAke1xuICAgICAgICAgIChtb2RlbCBhcyBhbnkpWyduYW1lJ10gfHxcbiAgICAgICAgICAobW9kZWwgYXMgYW55KVsndGl0bGUnXSB8fFxuICAgICAgICAgIChtb2RlbCBhcyBhbnkpWydpZCddXG4gICAgICAgIH1gO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2dldENob2ljZXMoKSB7XG4gICAgLy8gU2V0IGRpc3BsYXkgY2hvaWNlc1xuICAgIGxldCBjaG9pY2VzOiBJRGlzcEVkaXRDaG9pY2VbXSB8IHVuZGVmaW5lZDtcbiAgICBpZiAodGhpcy5jaG9pY2VzICYmIHRoaXMuY2hvaWNlcy5sZW5ndGgpIHtcbiAgICAgIGNob2ljZXMgPSB0aGlzLmNob2ljZXM7XG4gICAgfSBlbHNlIGlmICgodGhpcy5tYW5hZ2VyIGFzIGFueSk/LmNob2ljZXMpIHtcbiAgICAgIGNob2ljZXMgPSAodGhpcy5tYW5hZ2VyIGFzIGFueSk/LmNob2ljZXM7XG4gICAgfVxuICAgIC8vIFNldCBkaXNwbGF5IHZhbHVlXG4gICAgaWYgKGNob2ljZXMgJiYgY2hvaWNlcy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnJlYWxDaG9pY2VzID0gY2hvaWNlcztcbiAgICB9IGVsc2Uge1xuICAgICAgZGVsZXRlIHRoaXMucmVhbENob2ljZXM7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfZ2V0UmVhbERpc3BsYXkoKSB7XG4gICAgdGhpcy5yZWFsRGlzcGxheSA9IHRoaXMudmlld2VyXG4gICAgICA/IHRoaXMudmlld2VyXG4gICAgICA6IHRoaXMubWFuYWdlcj8uZGlzcGxheVR5cGVcbiAgICAgID8gdGhpcy5tYW5hZ2VyLmRpc3BsYXlUeXBlXG4gICAgICA6ICd0ZXh0JztcbiAgICBpZiAodGhpcy5yZWFsQ2hvaWNlcyAmJiB0aGlzLnJlYWxDaG9pY2VzLmxlbmd0aCkge1xuICAgICAgdGhpcy5yZWFsRGlzcGxheSA9ICdjaG9pY2UnO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2dldFJlYWxFZGl0b3IoKSB7XG4gICAgdGhpcy5yZWFsRWRpdG9yID0gdGhpcy5lZGl0b3JcbiAgICAgID8gdGhpcy5lZGl0b3JcbiAgICAgIDogdGhpcy5tYW5hZ2VyPy5lZGl0b3JUeXBlIHx8ICdpbnB1dC50ZXh0JztcbiAgICBpZiAodGhpcy5yZWFsQ2hvaWNlcyAmJiB0aGlzLnJlYWxDaG9pY2VzLmxlbmd0aCkge1xuICAgICAgdGhpcy5yZWFsRWRpdG9yID0gJ3NlbGVjdCc7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfc2V0Rm9ybUNvbnRyb2woKSB7XG4gICAgaWYgKCF0aGlzLmZvcm0pIHtcbiAgICAgIGNvbnN0IGZnYzogeyBbaW5kZXg6IHN0cmluZ106IFVudHlwZWRGb3JtQ29udHJvbCB9ID0ge307XG4gICAgICBmZ2NbdGhpcy5maWVsZF0gPSB0aGlzLm1vZGVsLkZDKHRoaXMuZmllbGQpO1xuICAgICAgdGhpcy5mZyA9IG5ldyBVbnR5cGVkRm9ybUdyb3VwKGZnYyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZmcgPSB0aGlzLmZvcm07XG4gICAgICB0aGlzLmZnLnNldENvbnRyb2wodGhpcy5maWVsZCwgdGhpcy5tb2RlbC5GQyh0aGlzLmZpZWxkKSwge1xuICAgICAgICBlbWl0RXZlbnQ6IGZhbHNlLFxuICAgICAgfSk7XG4gICAgfVxuICAgIGlmICh0aGlzLm1vZGUgPT09ICdpbmxpbmUnKSB7XG4gICAgICB0aGlzLmZnLnZhbHVlQ2hhbmdlcy5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLnVwZGF0ZSgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfc2V0Rm9ybUNvbnRyb2xWYWx1ZSgpIHtcbiAgICBzd2l0Y2ggKHRoaXMucmVhbEVkaXRvcikge1xuICAgICAgY2FzZSAnaW5wdXQuZGF0ZXRpbWUnOlxuICAgICAgICBjb25zdCB2YWx1ZSA9ICh0aGlzLm1vZGVsIGFzIGFueSlbdGhpcy5maWVsZF07XG4gICAgICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG4gICAgICAgIGNvbnN0IGxvY2Fsbm93ID0gbmV3IERhdGUoXG4gICAgICAgICAgbm93LmdldFRpbWUoKSAtIG5vdy5nZXRUaW1lem9uZU9mZnNldCgpICogNjAwMDBcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgdGhpcy5mZyEuY29udHJvbHNbdGhpcy5maWVsZF0uc2V0VmFsdWUobnVsbCwgeyBlbWl0RXZlbnQ6IHRydWUgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uc3QgdGltZSA9IHZhbHVlID8gbmV3IERhdGUodmFsdWUpIDogbmV3IERhdGUoKTtcbiAgICAgICAgICBjb25zdCBvZmZzZXQgPSB0aW1lLmdldFRpbWV6b25lT2Zmc2V0KCk7XG4gICAgICAgICAgY29uc3QgbG9jYWx0aW1lID0gbmV3IERhdGUodGltZS5nZXRUaW1lKCkgLSBvZmZzZXQgKiA2MDAwMCk7XG4gICAgICAgICAgdGhpcy5mZyEuY29udHJvbHNbdGhpcy5maWVsZF0uc2V0VmFsdWUoXG4gICAgICAgICAgICBsb2NhbHRpbWUudG9JU09TdHJpbmcoKS5zdWJzdHJpbmcoMCwgMTYpLFxuICAgICAgICAgICAgeyBlbWl0RXZlbnQ6IHRydWUgfVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZWFsRGVmYXVsdCA9XG4gICAgICAgICAgdGhpcy5kZWZhdWx0IHx8IHRoaXMubWFuYWdlcj8ucmVxdWlyZWRcbiAgICAgICAgICAgID8gbG9jYWxub3cudG9JU09TdHJpbmcoKS5zdWJzdHJpbmcoMCwgMTYpXG4gICAgICAgICAgICA6IG51bGw7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnaW5wdXQuZGF0ZSc6XG4gICAgICAgIGNvbnN0IGR0ID0gdGhpcy5tb2RlbC50b0pzb24oW3RoaXMuZmllbGRdKVt0aGlzLmZpZWxkXTtcbiAgICAgICAgdGhpcy5mZyEuY29udHJvbHNbdGhpcy5maWVsZF0uc2V0VmFsdWUoZHQpO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2lucHV0LmRlY2ltYWwnOlxuICAgICAgICB0aGlzLmZnIS5jb250cm9sc1t0aGlzLmZpZWxkXS5zZXRWYWx1ZShcbiAgICAgICAgICAodGhpcy5tb2RlbCBhcyBhbnkpW3RoaXMuZmllbGRdIC9cbiAgICAgICAgICAgICgodGhpcy5tYW5hZ2VyIGFzIHVua25vd24gYXMgRGVjaW1hbEZpZWxkTWFuYWdlcikuZmFjdG9yIHx8IDEpXG4gICAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfc2V0RWRpdG9yQ2xhc3NlcygpIHtcbiAgICAvLyBGSVhNRTogdXNlIHJlYWxFZGl0b3JDbGFzc2VzXG4gICAgaWYgKCF0aGlzLmlucHV0Q2xhc3Nlcykge1xuICAgICAgdGhpcy5pbnB1dENsYXNzZXMgPVxuICAgICAgICB0aGlzLmRjb25mLmRpc3BFZGl0LmlucHV0Q2xhc3Nlc1t0aGlzLnJlYWxFZGl0b3JdIHx8ICcnO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2dldERpc3BsYXlWYWx1ZSgpIHtcbiAgICBjb25zdCB2YWx1ZSA9ICh0aGlzLm1vZGVsIGFzIGFueSlbdGhpcy5maWVsZF07XG4gICAgdGhpcy5kaXNwVmFsdWUgPSB2YWx1ZTtcbiAgICBpZiAodGhpcy5yZWFsQ2hvaWNlcykge1xuICAgICAgZm9yIChjb25zdCBjIG9mIHRoaXMucmVhbENob2ljZXMpIHtcbiAgICAgICAgaWYgKGMgPT09IHZhbHVlKSB7XG4gICAgICAgICAgdGhpcy50eHRWYWx1ZSA9IGMgYXMgYW55O1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfSBlbHNlIGlmIChjLnZhbHVlICE9PSB1bmRlZmluZWQgJiYgYy52YWx1ZSA9PT0gdmFsdWUpIHtcbiAgICAgICAgICB0aGlzLnR4dFZhbHVlID0gYy5kZXNjO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICAvLyBTZXQgZGlzcGxheSB0ZXh0IGRlcGVuZGluZyBvbiB2YWx1ZSBhbmQgcmVhbERpc3BsYXkgdmFsdWVcbiAgICBpZiAodmFsdWUgPT09IHRydWUpIHtcbiAgICAgIHRoaXMudHh0VmFsdWUgPSAnT1VJJztcbiAgICB9IGVsc2UgaWYgKHZhbHVlID09PSBmYWxzZSkge1xuICAgICAgdGhpcy50eHRWYWx1ZSA9ICdOT04nO1xuICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCB8fCB2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgdGhpcy50eHRWYWx1ZSA9ICdub24gZMOpZmluaSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHN3aXRjaCAodGhpcy5yZWFsRGlzcGxheSkge1xuICAgICAgICBjYXNlICdma2RldGFpbHMnOlxuICAgICAgICAgIGNvbnN0IGRldGFpbHMgPSAodGhpcy5tb2RlbCBhcyBhbnkpW2Ake3RoaXMuZmllbGR9X2RldGFpbHNgXSBhcyBhbnk7XG4gICAgICAgICAgdGhpcy50eHRWYWx1ZSA9IHRoaXMuX2Rpc3BsYXkoZGV0YWlscyk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ20ybWRldGFpbHMnOlxuICAgICAgICAgIGNvbnN0IG0ybURldGFpbHMgPVxuICAgICAgICAgICAgdGhpcy5tMm1WYWx1ZXMgfHxcbiAgICAgICAgICAgICgodGhpcy5tb2RlbCBhcyBhbnkpW2Ake3RoaXMuZmllbGR9X2RldGFpbHNgXSBhcyBhbnlbXSk7XG4gICAgICAgICAgdGhpcy50eHRWYWx1ZXMgPSBbXTtcbiAgICAgICAgICBmb3IgKGNvbnN0IHYgb2YgbTJtRGV0YWlscykge1xuICAgICAgICAgICAgdGhpcy50eHRWYWx1ZXMucHVzaCh0aGlzLl9kaXNwbGF5KHYpKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ2RlY2ltYWwnOlxuICAgICAgICAgIHRoaXMudHh0VmFsdWUgPSBgJHtcbiAgICAgICAgICAgIHZhbHVlIC9cbiAgICAgICAgICAgICgodGhpcy5tYW5hZ2VyIGFzIHVua25vd24gYXMgRGVjaW1hbEZpZWxkTWFuYWdlcikuZmFjdG9yIHx8IDEpXG4gICAgICAgICAgfWA7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhpcy50eHRWYWx1ZSA9IGAke3ZhbHVlfWA7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfc2V0RGlzcGxheUNsYXNzZXMoKSB7fVxufVxuIiwiXG48bmctdGVtcGxhdGUgI3RpdGxlVHBsPlxuICA8bmctY29udGVudD48L25nLWNvbnRlbnQ+XG48L25nLXRlbXBsYXRlPlxuPG5nLXRlbXBsYXRlICNkaXNwVHBsPlxuICA8bmctY29udGFpbmVyIFtuZ1N3aXRjaF09XCJyZWFsRGlzcGxheVwiPjxzcGFuIGNsYXNzPVwiZWRpdGFibGUgZGlzcC10ZXh0XCIgKm5nU3dpdGNoQ2FzZT1cIid0ZXh0J1wiIChjbGljayk9XCJlbmFibGVFZGl0TW9kZSgpXCI+e3t0eHRWYWx1ZX19PC9zcGFuPjxzcGFuIGNsYXNzPVwiZWRpdGFibGUgZGlzcC1jaG9pY2VcIiAqbmdTd2l0Y2hDYXNlPVwiJ2Nob2ljZSdcIiAoY2xpY2spPVwiZW5hYmxlRWRpdE1vZGUoKVwiPnt7dHh0VmFsdWV9fTwvc3Bhbj48c3BhbiBjbGFzcz1cImVkaXRhYmxlIGRpc3AtZGVjaW1hbFwiICpuZ1N3aXRjaENhc2U9XCInZGVjaW1hbCdcIiAoY2xpY2spPVwiZW5hYmxlRWRpdE1vZGUoKVwiPnt7dHh0VmFsdWV9fTwvc3Bhbj48c3BhbiBjbGFzcz1cImVkaXRhYmxlIGRpc3AtYm9vbGVhblwiICpuZ1N3aXRjaENhc2U9XCInYm9vbGVhbidcIiAoY2xpY2spPVwiZW5hYmxlRWRpdE1vZGUoKVwiPnt7dHh0VmFsdWV9fTwvc3Bhbj48c3BhbiBjbGFzcz1cImVkaXRhYmxlIGRpc3AtZmtkZXRhaWxzXCIgKm5nU3dpdGNoQ2FzZT1cIidma2RldGFpbHMnXCIgKGNsaWNrKT1cImVuYWJsZUVkaXRNb2RlKClcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJma2l0ZW1cIj57e3R4dFZhbHVlfX08L2Rpdj48L3NwYW4+PHNwYW4gY2xhc3M9XCJlZGl0YWJsZSBkaXNwLW0ybWRldGFpbHNcIiAqbmdTd2l0Y2hDYXNlPVwiJ20ybWRldGFpbHMnXCIgKGNsaWNrKT1cImVuYWJsZUVkaXRNb2RlKClcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJtMm1pdGVtXCIgKm5nRm9yPVwibGV0IHYgb2YgdHh0VmFsdWVzXCI+e3t2fX08L2Rpdj48L3NwYW4+PHNwYW4gY2xhc3M9XCJlZGl0YWJsZSBkaXNwLWRhdGV0aW1lXCIgKm5nU3dpdGNoQ2FzZT1cIidkYXRldGltZSdcIiAoY2xpY2spPVwiZW5hYmxlRWRpdE1vZGUoKVwiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImRpc3BWYWx1ZVwiPnt7dHh0VmFsdWV8ZGF0ZTonc2hvcnQnfX08L25nLWNvbnRhaW5lcj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhZGlzcFZhbHVlXCI+e3t0eHRWYWx1ZX19PC9uZy1jb250YWluZXI+PC9zcGFuPjxzcGFuIGNsYXNzPVwiZWRpdGFibGUgZGlzcC1kYXRldGltZVwiICpuZ1N3aXRjaENhc2U9XCInZGF0ZSdcIiAoY2xpY2spPVwiZW5hYmxlRWRpdE1vZGUoKVwiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImRpc3BWYWx1ZVwiPnt7dHh0VmFsdWV8ZGF0ZTonc2hvcnREYXRlJ319PC9uZy1jb250YWluZXI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWRpc3BWYWx1ZVwiPnt7dHh0VmFsdWV9fTwvbmctY29udGFpbmVyPjwvc3Bhbj48L25nLWNvbnRhaW5lcj5cbjwvbmctdGVtcGxhdGU+XG48bmctdGVtcGxhdGUgI2VkaXRUcGwgbGV0LWZvcm09XCJmb3JtXCI+XG4gIDxuZy1jb250YWluZXIgW25nU3dpdGNoXT1cInJlYWxFZGl0b3JcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCInaW5wdXQudGV4dCdcIj5cbiAgICAgIDxpbnB1dCB0eXBlPVwidGV4dFwiIFtmb3JtQ29udHJvbF09XCJmb3JtLmdldChmaWVsZClcIiBbbmdDbGFzc109XCJpbnB1dENsYXNzZXNcIiAoa2V5dXAuZXNjYXBlKT1cInVuc2V0RWRpdCgpXCIgW3BsYWNlaG9sZGVyXT1cInJlYWxQbGFjZWhvbGRlclwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tdGV4dFwiICpuZ0lmPVwicmVhbEhlbHBcIj57e3JlYWxIZWxwfX08c3BhbiBjbGFzcz1cIm1zLTFcIiAqbmdJZj1cInJlcXVpcmVkXCI+KHJlcXVpcyk8L3NwYW4+PC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydtaW5sZW5ndGgnXVwiPlRyb3AgY291cnQgOiB7eyRhbnkobWFuYWdlcikubWluTGVuZ3RofX0gY2FyYWN0w6hyZXMgbWluaW11bS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWF4bGVuZ3RoJ11cIj5Ucm9wIGxvbmcgOiB7eyRhbnkobWFuYWdlcikubWF4TGVuZ3RofX0gY2FyYWN0w6hyZXMgbWF4aW11bS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsncGF0dGVybiddXCI+Rm9ybWF0IGludmFsaWRlLi4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydyZXF1aXJlZCddXCI+Q2UgY2hhbXAgZXN0IHJlcXVpcy4uLjwvZGl2PlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidpbnB1dC5lbWFpbCdcIj5cbiAgICAgIDxpbnB1dCB0eXBlPVwiZW1haWxcIiBbZm9ybUNvbnRyb2xdPVwiZm9ybS5nZXQoZmllbGQpXCIgW25nQ2xhc3NdPVwiaW5wdXRDbGFzc2VzXCIgKGtleXVwLmVzY2FwZSk9XCJ1bnNldEVkaXQoKVwiIFtwbGFjZWhvbGRlcl09XCJyZWFsUGxhY2Vob2xkZXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXRleHRcIiAqbmdJZj1cInJlYWxIZWxwXCI+e3tyZWFsSGVscH19PHNwYW4gY2xhc3M9XCJtcy0xXCIgKm5nSWY9XCJyZXF1aXJlZFwiPihyZXF1aXMpPC9zcGFuPjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWlubGVuZ3RoJ11cIj5Ucm9wIGNvdXJ0IDoge3skYW55KG1hbmFnZXIpLm1pbkxlbmd0aH19IGNhcmFjdMOocmVzIG1pbmltdW0uLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ21heGxlbmd0aCddXCI+VHJvcCBsb25nIDoge3skYW55KG1hbmFnZXIpLm1heExlbmd0aH19IGNhcmFjdMOocmVzIG1heGltdW0uLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ3BhdHRlcm4nXVwiPkZvcm1hdCBpbnZhbGlkZS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnZW1haWwnXVwiPkZvcm1hdCBkJ2VtYWlsIGludmFsaWRlLi4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydyZXF1aXJlZCddXCI+Q2UgY2hhbXAgZXN0IHJlcXVpcy4uLjwvZGl2PlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidpbnB1dC5wYXNzd29yZCdcIj5cbiAgICAgIDxpbnB1dCB0eXBlPVwicGFzc3dvcmRcIiBbZm9ybUNvbnRyb2xdPVwiZm9ybS5nZXQoZmllbGQpXCIgW25nQ2xhc3NdPVwiaW5wdXRDbGFzc2VzXCIgKGtleXVwLmVzY2FwZSk9XCJ1bnNldEVkaXQoKVwiIFtwbGFjZWhvbGRlcl09XCJyZWFsUGxhY2Vob2xkZXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXRleHRcIiAqbmdJZj1cInJlYWxIZWxwXCI+e3tyZWFsSGVscH19PHNwYW4gY2xhc3M9XCJtcy0xXCIgKm5nSWY9XCJyZXF1aXJlZFwiPihyZXF1aXMpPC9zcGFuPjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWlubGVuZ3RoJ11cIj5Ucm9wIGNvdXJ0IDoge3skYW55KG1hbmFnZXIpLm1pbkxlbmd0aH19IGNhcmFjdMOocmVzIG1pbmltdW0uLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ21heGxlbmd0aCddXCI+VHJvcCBsb25nIDoge3skYW55KG1hbmFnZXIpLm1heExlbmd0aH19IGNhcmFjdMOocmVzIG1heGltdW0uLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ3BhdHRlcm4nXVwiPkZvcm1hdCBpbnZhbGlkZS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsncmVxdWlyZWQnXVwiPkNlIGNoYW1wIGVzdCByZXF1aXMuLi48L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCInaW5wdXQuZGF0ZXRpbWUnXCI+XG4gICAgICA8aW5wdXQgdHlwZT1cImRhdGV0aW1lLWxvY2FsXCIgW2Zvcm1Db250cm9sXT1cImZvcm0uZ2V0KGZpZWxkKVwiIFtuZ0NsYXNzXT1cImlucHV0Q2xhc3Nlc1wiIChrZXl1cC5lc2NhcGUpPVwidW5zZXRFZGl0KClcIiAoa2V5dXAuZW50ZXIpPVwidXBkYXRlKClcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXRleHRcIj57e3JlYWxIZWxwfX08L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ3JlcXVpcmVkJ11cIj5DZSBjaGFtcCBlc3QgcmVxdWlzLi4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydtaW5EYXRlJ11cIj5Eb2l0IMOqdHJlIHBvc3TDqXJpZXVyIMOgICB7eyRhbnkobWFuYWdlcikubWlufGRhdGU6J3Nob3J0J319Li4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydtYXhEYXRlJ11cIj5Eb2l0IMOqdHJlIGFudMOpcmlldXIgw6AgIHt7JGFueShtYW5hZ2VyKS5tYXh8ZGF0ZTonc2hvcnQnfX0uLi48L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCInaW5wdXQuZGF0ZSdcIj5cbiAgICAgIDxpbnB1dCB0eXBlPVwiZGF0ZVwiIFtmb3JtQ29udHJvbF09XCJmb3JtLmdldChmaWVsZClcIiBbbmdDbGFzc109XCJpbnB1dENsYXNzZXNcIiAoa2V5dXAuZXNjYXBlKT1cInVuc2V0RWRpdCgpXCIgKGtleXVwLmVudGVyKT1cInVwZGF0ZSgpXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS10ZXh0XCI+e3tyZWFsSGVscH19PC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydyZXF1aXJlZCddXCI+Q2UgY2hhbXAgZXN0IHJlcXVpcy4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWluRGF0ZSddXCI+RG9pdCDDqnRyZSBwb3N0w6lyaWV1ciDDoCAge3skYW55KG1hbmFnZXIpLm1pbnxkYXRlOidzaG9ydCd9fS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWF4RGF0ZSddXCI+RG9pdCDDqnRyZSBhbnTDqXJpZXVyIMOgICB7eyRhbnkobWFuYWdlcikubWF4fGRhdGU6J3Nob3J0J319Li4uPC9kaXY+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiJ2lucHV0Lm51bWJlcidcIj5cbiAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCIgW2Zvcm1Db250cm9sXT1cImZvcm0uZ2V0KGZpZWxkKVwiIFtuZ0NsYXNzXT1cImlucHV0Q2xhc3Nlc1wiIChrZXl1cC5lc2NhcGUpPVwidW5zZXRFZGl0KClcIiBbcGxhY2Vob2xkZXJdPVwicmVhbFBsYWNlaG9sZGVyXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS10ZXh0XCIgKm5nSWY9XCJyZWFsSGVscFwiPnt7cmVhbEhlbHB9fTxzcGFuIGNsYXNzPVwibXMtMVwiICpuZ0lmPVwicmVxdWlyZWRcIj4ocmVxdWlzKTwvc3Bhbj48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ21pbiddXCI+VHJvcCBwZXRpdCA6IG1pbmltdW0ge3skYW55KG1hbmFnZXIpLm1pbn19Li4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydtYXgnXVwiPlRyb3AgZ3JhbmQgOiBtYXhpbXVtIHt7JGFueShtYW5hZ2VyKS5tYXh9fS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsncmVxdWlyZWQnXVwiPkNlIGNoYW1wIGVzdCByZXF1aXMuLi48L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCInaW5wdXQuZGVjaW1hbCdcIj5cbiAgICAgIDxpbnB1dCB0eXBlPVwibnVtYmVyXCIgW2Zvcm1Db250cm9sXT1cImZvcm0uZ2V0KGZpZWxkKVwiIFtuZ0NsYXNzXT1cImlucHV0Q2xhc3Nlc1wiIChrZXl1cC5lc2NhcGUpPVwidW5zZXRFZGl0KClcIiBbcGxhY2Vob2xkZXJdPVwicmVhbFBsYWNlaG9sZGVyXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS10ZXh0XCIgKm5nSWY9XCJyZWFsSGVscFwiPnt7cmVhbEhlbHB9fTxzcGFuIGNsYXNzPVwibXMtMVwiICpuZ0lmPVwicmVxdWlyZWRcIj4ocmVxdWlzKTwvc3Bhbj48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ21pbiddXCI+VHJvcCBwZXRpdCA6IG1pbmltdW0ge3skYW55KG1hbmFnZXIpLm1pbn19Li4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydtYXgnXVwiPlRyb3AgZ3JhbmQgOiBtYXhpbXVtIHt7JGFueShtYW5hZ2VyKS5tYXh9fS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsncmVxdWlyZWQnXVwiPkNlIGNoYW1wIGVzdCByZXF1aXMuLi48L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCInaW5wdXQuY2hlY2tib3gnXCI+XG4gICAgICA8aW5wdXQgY2xhc3M9XCJmb3JtLWNoZWNrLWlucHV0XCIgdHlwZT1cImNoZWNrYm94XCIgW2Zvcm1Db250cm9sXT1cImZvcm0uZ2V0KGZpZWxkKVwiIChrZXl1cC5lc2NhcGUpPVwidW5zZXRFZGl0KClcIiAoY2hhbmdlKT1cInVwZGF0ZSgpXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS10ZXh0XCI+e3tyZWFsSGVscH19PC9kaXY+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiJ3RleHRhcmVhJ1wiPlxuICAgICAgPHRleHRhcmVhIFtmb3JtQ29udHJvbF09XCJmb3JtLmdldChmaWVsZClcIiAoa2V5dXAuZXNjYXBlKT1cInVuc2V0RWRpdCgpXCIgW25nQ2xhc3NdPVwiaW5wdXRDbGFzc2VzXCIgKGtleXVwLmNvbnRyb2wuZW50ZXIpPVwidXBkYXRlKClcIiBbcGxhY2Vob2xkZXJdPVwicmVhbFBsYWNlaG9sZGVyXCI+PC90ZXh0YXJlYT5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXRleHRcIiAqbmdJZj1cInJlYWxIZWxwXCI+e3tyZWFsSGVscH19PHNwYW4gY2xhc3M9XCJtcy0xXCIgKm5nSWY9XCJyZXF1aXJlZFwiPihyZXF1aXMpPC9zcGFuPjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWlubGVuZ3RoJ11cIj5Ucm9wIGNvdXJ0IDoge3skYW55KG1hbmFnZXIpLm1pbkxlbmd0aH19IGNhcmFjdMOocmVzIG1pbmltdW0uLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ21heGxlbmd0aCddXCI+VHJvcCBsb25nIDoge3skYW55KG1hbmFnZXIpLm1heExlbmd0aH19IGNhcmFjdMOocmVzIG1heGltdW0uLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ3BhdHRlcm4nXVwiPkZvcm1hdCBpbnZhbGlkZS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsncmVxdWlyZWQnXVwiPkNlIGNoYW1wIGVzdCByZXF1aXMuLi48L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCInZmtzZWxlY3QnXCI+XG4gICAgICA8ZGF0YS1ma3NlbGVjdCBbY29sbGVjdGlvbl09XCJjb2xsZWN0aW9uXCIgW2ZpbHRlcl09XCJmaWx0ZXJcIiAoc2VsZWN0ZWQpPVwic2VsZWN0ZWRSZWZJdGVtKCRldmVudClcIiBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIiAoY2FuY2VsbGVkKT1cInVuc2V0RWRpdCgpXCIgKGNsZWFyZWQpPVwic2VsZWN0ZWRSZWZJdGVtKG51bGwpXCI+PC9kYXRhLWZrc2VsZWN0PlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidtMm1zZWxlY3QnXCI+XG4gICAgICA8ZGF0YS1tMm1zZWxlY3QgW2NvbGxlY3Rpb25dPVwiY29sbGVjdGlvblwiIFtmaWx0ZXJdPVwiZmlsdGVyXCIgKGNoYW5nZWQpPVwidXBkYXRlKClcIiBbZm9ybUNvbnRyb2xdPVwiZm9ybS5nZXQoZmllbGQpXCIgKGRldGFpbHNDaGFuZ2VkKT1cIm9uTTJNVmFsdWVzQ2hhbmdlcygkZXZlbnQpXCIgW21vZGVsXT1cIm1vZGVsXCIgW2ZpZWxkXT1cImZpZWxkXCIgW3BsYWNlaG9sZGVyXT1cInBsYWNlaG9sZGVyXCI+PC9kYXRhLW0ybXNlbGVjdD5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCInc2VsZWN0J1wiPlxuICAgICAgPHNlbGVjdCBbZm9ybUNvbnRyb2xdPVwiZm9ybS5nZXQoZmllbGQpXCIgKGtleXVwLmVzY2FwZSk9XCJ1bnNldEVkaXQoKVwiIChjaGFuZ2UpPVwidXBkYXRlKClcIiBbbmdDbGFzc109XCJpbnB1dENsYXNzZXNcIj5cbiAgICAgICAgPG9wdGlvbiAqbmdGb3I9XCJsZXQgYyBvZiByZWFsQ2hvaWNlc1wiIFtuZ1ZhbHVlXT1cImMudmFsdWUhPT11bmRlZmluZWQgPyBjLnZhbHVlIDogY1wiPnt7Yy5kZXNjID8gYy5kZXNjIDogY319PC9vcHRpb24+XG4gICAgICA8L3NlbGVjdD5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXRleHRcIj57e3JlYWxIZWxwfX08L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgPC9uZy1jb250YWluZXI+XG48L25nLXRlbXBsYXRlPlxuPCEtLSBEaXNwL2VkaXQgdG9nZ2xlci0tPlxuPG5nLXRlbXBsYXRlICNkaXNwZWRpdFRwbD5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFlZGl0XCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImRpc3BUcGxcIj48L25nLWNvbnRhaW5lcj5cbiAgPC9uZy1jb250YWluZXI+XG4gIDxuZy1jb250YWluZXIgKm5nSWY9XCJlZGl0XCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImZnXCI+XG4gICAgICA8Zm9ybSBbZm9ybUdyb3VwXT1cImZnXCIgKHN1Ym1pdCk9XCJ1cGRhdGUoKVwiPlxuICAgICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiZWRpdFRwbDsgY29udGV4dDoge2Zvcm06IGZnfVwiPjwvbmctY29udGFpbmVyPlxuICAgICAgPC9mb3JtPlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L25nLWNvbnRhaW5lcj5cbjwvbmctdGVtcGxhdGU+XG48IS0tIERpc3BFZGl0IG5vZm9ybS0tPlxuPG5nLXRlbXBsYXRlICNkaXNwZWRpdEZvcm1UcGw+XG4gIDxuZy1jb250YWluZXIgKm5nSWY9XCIhZWRpdFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJkaXNwVHBsXCI+PC9uZy1jb250YWluZXI+XG4gIDwvbmctY29udGFpbmVyPlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiZWRpdFwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJmb3JtXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiZWRpdFRwbDsgY29udGV4dDoge2Zvcm06IGZvcm19XCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIDwvbmctY29udGFpbmVyPlxuPC9uZy10ZW1wbGF0ZT5cbjwhLS0gRGQgZGlzcGxheS0tPlxuPG5nLWNvbnRhaW5lciAqbmdJZj1cIm1vZGU9PT0nZGQnXCI+XG4gIDxkdCBbY2xhc3MucmVxdWlyZWRdPVwicmVxdWlyZWRcIiAqbmdJZj1cIiFoaWRlTGFiZWxcIj48c3BhbiBjbGFzcz1cImVkaXRhYmxlXCIgKGNsaWNrKT1cInRvZ2dsZUVkaXQoKVwiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRpdGxlVHBsXCI+PC9uZy1jb250YWluZXI+PC9zcGFuPjxzcGFuIGNsYXNzPVwicG9pbnRlciBmbG9hdC1lbmRcIiAoY2xpY2spPVwic2V0RGVmYXVsdCgpXCIgKm5nSWY9XCJyZWFsRGVmYXVsdCE9PSB1bmRlZmluZWQgJmFtcDsmYW1wOyBlZGl0XCI+PGkgY2xhc3M9XCJiaSBiaS10cmFzaCBtcy0yXCI+PC9pPjwvc3Bhbj48L2R0PlxuICA8ZGQgW2NsYXNzLm1iLTBdPVwiaGlkZUxhYmVsXCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImRpc3BlZGl0VHBsXCI+PC9uZy1jb250YWluZXI+XG4gIDwvZGQ+XG48L25nLWNvbnRhaW5lcj5cbjwhLS0gSW5saW5lIGRpc3BsYXktLT5cbjxuZy1jb250YWluZXIgKm5nSWY9XCJtb2RlPT09J2lubGluZSdcIj5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFoaWRlTGFiZWxcIj48c3BhbiBjbGFzcz1cInBvaW50ZXIgZmxvYXQtZW5kXCIgKGNsaWNrKT1cInNldERlZmF1bHQoKVwiICpuZ0lmPVwicmVhbERlZmF1bHQhPT0gdW5kZWZpbmVkICZhbXA7JmFtcDsgZWRpdFwiPjxpIGNsYXNzPVwiYmkgYmktdHJhc2ggbXMtMlwiPjwvaT48L3NwYW4+XG4gICAgPGxhYmVsIFtjbGFzcy5yZXF1aXJlZF09XCJyZXF1aXJlZFwiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRpdGxlVHBsXCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9sYWJlbD5cbiAgPC9uZy1jb250YWluZXI+XG4gIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJkaXNwZWRpdFRwbFwiPjwvbmctY29udGFpbmVyPlxuPC9uZy1jb250YWluZXI+XG48IS0tIEZvcm0gZGlzcGxheS0tPlxuPG5nLWNvbnRhaW5lciAqbmdJZj1cIm1vZGU9PT0nZm9ybSdcIj5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFoaWRlTGFiZWxcIj48c3BhbiBjbGFzcz1cInBvaW50ZXIgZmxvYXQtZW5kXCIgKGNsaWNrKT1cInNldERlZmF1bHQoKVwiICpuZ0lmPVwicmVhbERlZmF1bHQhPT0gdW5kZWZpbmVkICZhbXA7JmFtcDsgZWRpdFwiPjxpIGNsYXNzPVwiYmkgYmktdHJhc2ggbXMtMlwiPjwvaT48L3NwYW4+XG4gICAgPGxhYmVsIFtjbGFzcy5yZXF1aXJlZF09XCJyZXF1aXJlZFwiPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cInRpdGxlVHBsXCI+PC9uZy1jb250YWluZXI+XG4gICAgPC9sYWJlbD5cbiAgPC9uZy1jb250YWluZXI+XG4gIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJkaXNwZWRpdEZvcm1UcGxcIj48L25nLWNvbnRhaW5lcj5cbjwvbmctY29udGFpbmVyPiJdfQ==