@solidev/data 0.0.1-dev.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 (155) hide show
  1. package/README.md +7 -0
  2. package/esm2020/lib/auth/auth-interceptor.service.mjs +73 -0
  3. package/esm2020/lib/auth/auth.service.mjs +114 -0
  4. package/esm2020/lib/auth/jwt.mjs +21 -0
  5. package/esm2020/lib/data/data-backend.mjs +106 -0
  6. package/esm2020/lib/data/data-collection.mjs +109 -0
  7. package/esm2020/lib/data/data-collection.mock.mjs +39 -0
  8. package/esm2020/lib/data/data-model.mjs +287 -0
  9. package/esm2020/lib/data/data-parameters.mjs +34 -0
  10. package/esm2020/lib/data/data-query.mjs +143 -0
  11. package/esm2020/lib/data/data-query.mock.mjs +46 -0
  12. package/esm2020/lib/data/fields/base.mjs +142 -0
  13. package/esm2020/lib/data/fields/boolean.mjs +38 -0
  14. package/esm2020/lib/data/fields/datetime.mjs +109 -0
  15. package/esm2020/lib/data/fields/index.mjs +7 -0
  16. package/esm2020/lib/data/fields/numbers.mjs +28 -0
  17. package/esm2020/lib/data/fields/primaryfield.mjs +9 -0
  18. package/esm2020/lib/data/fields/relations.mjs +53 -0
  19. package/esm2020/lib/data/fields/stringfields.mjs +71 -0
  20. package/esm2020/lib/dispedit/choice.pipe.mjs +38 -0
  21. package/esm2020/lib/dispedit/dispedit/dispedit.component.mjs +457 -0
  22. package/esm2020/lib/dispedit/dispedit/dispedit.constants.mjs +2 -0
  23. package/esm2020/lib/dispedit/dispedit.module.mjs +60 -0
  24. package/esm2020/lib/dispedit/fkselect/fkselect.component.mjs +140 -0
  25. package/esm2020/lib/dispedit/m2mselect/m2mselect.component.mjs +316 -0
  26. package/esm2020/lib/dispedit/sdelete/sdelete.component.mjs +43 -0
  27. package/esm2020/lib/messages/message-zone/message-zone.component.mjs +57 -0
  28. package/esm2020/lib/messages/message.service.mjs +151 -0
  29. package/esm2020/lib/modellist/model-list-fields/model-list-field-header/model-list-field-header.component.mjs +34 -0
  30. package/esm2020/lib/modellist/model-list-fields/model-list-fields-selector/model-list-fields-selector.component.mjs +63 -0
  31. package/esm2020/lib/modellist/model-list-fields/model-list-fields.mjs +225 -0
  32. package/esm2020/lib/modellist/model-list-filters/filters/filtertypes.mjs +3 -0
  33. package/esm2020/lib/modellist/model-list-filters/filters/model-list-autocomplete-filter/model-list-autocomplete-filter.component.mjs +104 -0
  34. package/esm2020/lib/modellist/model-list-filters/filters/model-list-autocomplete-filter/model-list-autocomplete-filter.mjs +31 -0
  35. package/esm2020/lib/modellist/model-list-filters/filters/model-list-autocomplete-multi-filter/model-list-autocomplete-multi-filter.component.mjs +25 -0
  36. package/esm2020/lib/modellist/model-list-filters/filters/model-list-autocomplete-multi-filter/model-list-autocomplete-multi-filter.mjs +40 -0
  37. package/esm2020/lib/modellist/model-list-filters/filters/model-list-datetime-filter/model-list-datetime-filter.component.mjs +21 -0
  38. package/esm2020/lib/modellist/model-list-filters/filters/model-list-datetime-filter/model-list-datetime-filter.mjs +14 -0
  39. package/esm2020/lib/modellist/model-list-filters/filters/model-list-datetimerange-filter/model-list-datetime-range-filter.component.mjs +21 -0
  40. package/esm2020/lib/modellist/model-list-filters/filters/model-list-datetimerange-filter/model-list-datetimerange-filter.mjs +14 -0
  41. package/esm2020/lib/modellist/model-list-filters/filters/model-list-flags-filter/model-list-flags-filter.component.mjs +21 -0
  42. package/esm2020/lib/modellist/model-list-filters/filters/model-list-flags-filter/model-list-flags-filter.mjs +14 -0
  43. package/esm2020/lib/modellist/model-list-filters/filters/model-list-geodistance-filter/model-list-geodistance-filter.component.mjs +21 -0
  44. package/esm2020/lib/modellist/model-list-filters/filters/model-list-geodistance-filter/model-list-geodistance-filter.mjs +14 -0
  45. package/esm2020/lib/modellist/model-list-filters/filters/model-list-number-filter/model-list-number-filter.component.mjs +44 -0
  46. package/esm2020/lib/modellist/model-list-filters/filters/model-list-number-filter/model-list-number-filter.mjs +49 -0
  47. package/esm2020/lib/modellist/model-list-filters/filters/model-list-select-filter/model-list-select-filter.component.mjs +45 -0
  48. package/esm2020/lib/modellist/model-list-filters/filters/model-list-select-filter/model-list-select-filter.mjs +26 -0
  49. package/esm2020/lib/modellist/model-list-filters/filters/model-list-select-multi-filter/model-list-select-multi-filter.component.mjs +21 -0
  50. package/esm2020/lib/modellist/model-list-filters/filters/model-list-select-multi-filter/model-list-select-multi-filter.mjs +14 -0
  51. package/esm2020/lib/modellist/model-list-filters/filters/model-list-text-filter/model-list-text-filter.component.mjs +40 -0
  52. package/esm2020/lib/modellist/model-list-filters/filters/model-list-text-filter/model-list-text-filter.mjs +14 -0
  53. package/esm2020/lib/modellist/model-list-filters/filters/model-list-tree-filter/model-list-tree-filter.component.mjs +21 -0
  54. package/esm2020/lib/modellist/model-list-filters/filters/model-list-tree-filter/model-list-tree-filter.mjs +14 -0
  55. package/esm2020/lib/modellist/model-list-filters/model-list-filter.mjs +41 -0
  56. package/esm2020/lib/modellist/model-list-filters/model-list-filters/model-list-filters.component.mjs +48 -0
  57. package/esm2020/lib/modellist/model-list-filters/model-list-filters-select/model-list-filters-select.component.mjs +30 -0
  58. package/esm2020/lib/modellist/model-list-filters/model-list-filters.mjs +80 -0
  59. package/esm2020/lib/modellist/model-list-paginator/model-list-paginator/model-list-paginator.component.mjs +70 -0
  60. package/esm2020/lib/modellist/model-list-paginator/model-list-paginator.mjs +47 -0
  61. package/esm2020/lib/modellist/model-list-sorter/model-list-sorter/model-list-sorter.component.mjs +49 -0
  62. package/esm2020/lib/modellist/model-list-sorter/model-list-sorter.mjs +116 -0
  63. package/esm2020/lib/modellist/model-list.service.mjs +115 -0
  64. package/esm2020/lib/routing/breadcrumb/breadcrumb.component.mjs +142 -0
  65. package/esm2020/lib/routing/routing.mjs +57 -0
  66. package/esm2020/lib/uploader/index.mjs +6 -0
  67. package/esm2020/lib/uploader/interfaces.mjs +8 -0
  68. package/esm2020/lib/uploader/ng-file-drop.directive.mjs +81 -0
  69. package/esm2020/lib/uploader/ng-file-select.directive.mjs +51 -0
  70. package/esm2020/lib/uploader/ngx-uploader.class.mjs +308 -0
  71. package/esm2020/lib/uploader/ngx-uploader.module.mjs +17 -0
  72. package/esm2020/lib/utils/slugify.mjs +16 -0
  73. package/esm2020/lib/utils/tab-memory.service.mjs +71 -0
  74. package/esm2020/public-api.mjs +41 -0
  75. package/esm2020/solidev-data.mjs +5 -0
  76. package/fesm2015/solidev-data.mjs +4791 -0
  77. package/fesm2015/solidev-data.mjs.map +1 -0
  78. package/fesm2020/solidev-data.mjs +4757 -0
  79. package/fesm2020/solidev-data.mjs.map +1 -0
  80. package/index.d.ts +5 -0
  81. package/lib/auth/auth-interceptor.service.d.ts +16 -0
  82. package/lib/auth/auth.service.d.ts +38 -0
  83. package/lib/auth/jwt.d.ts +22 -0
  84. package/lib/data/data-backend.d.ts +47 -0
  85. package/lib/data/data-collection.d.ts +87 -0
  86. package/lib/data/data-collection.mock.d.ts +19 -0
  87. package/lib/data/data-model.d.ts +91 -0
  88. package/lib/data/data-parameters.d.ts +26 -0
  89. package/lib/data/data-query.d.ts +100 -0
  90. package/lib/data/data-query.mock.d.ts +25 -0
  91. package/lib/data/fields/base.d.ts +116 -0
  92. package/lib/data/fields/boolean.d.ts +9 -0
  93. package/lib/data/fields/datetime.d.ts +39 -0
  94. package/lib/data/fields/index.d.ts +6 -0
  95. package/lib/data/fields/numbers.d.ts +31 -0
  96. package/lib/data/fields/primaryfield.d.ts +8 -0
  97. package/lib/data/fields/relations.d.ts +45 -0
  98. package/lib/data/fields/stringfields.d.ts +50 -0
  99. package/lib/dispedit/choice.pipe.d.ts +8 -0
  100. package/lib/dispedit/dispedit/dispedit.component.d.ts +177 -0
  101. package/lib/dispedit/dispedit/dispedit.constants.d.ts +6 -0
  102. package/lib/dispedit/dispedit.module.d.ts +20 -0
  103. package/lib/dispedit/fkselect/fkselect.component.d.ts +43 -0
  104. package/lib/dispedit/m2mselect/m2mselect.component.d.ts +120 -0
  105. package/lib/dispedit/sdelete/sdelete.component.d.ts +26 -0
  106. package/lib/messages/message-zone/message-zone.component.d.ts +14 -0
  107. package/lib/messages/message.service.d.ts +59 -0
  108. package/lib/modellist/model-list-fields/model-list-field-header/model-list-field-header.component.d.ts +15 -0
  109. package/lib/modellist/model-list-fields/model-list-fields-selector/model-list-fields-selector.component.d.ts +19 -0
  110. package/lib/modellist/model-list-fields/model-list-fields.d.ts +67 -0
  111. package/lib/modellist/model-list-filters/filters/filtertypes.d.ts +1 -0
  112. package/lib/modellist/model-list-filters/filters/model-list-autocomplete-filter/model-list-autocomplete-filter.component.d.ts +30 -0
  113. package/lib/modellist/model-list-filters/filters/model-list-autocomplete-filter/model-list-autocomplete-filter.d.ts +24 -0
  114. package/lib/modellist/model-list-filters/filters/model-list-autocomplete-multi-filter/model-list-autocomplete-multi-filter.component.d.ts +10 -0
  115. package/lib/modellist/model-list-filters/filters/model-list-autocomplete-multi-filter/model-list-autocomplete-multi-filter.d.ts +15 -0
  116. package/lib/modellist/model-list-filters/filters/model-list-datetime-filter/model-list-datetime-filter.component.d.ts +11 -0
  117. package/lib/modellist/model-list-filters/filters/model-list-datetime-filter/model-list-datetime-filter.d.ts +4 -0
  118. package/lib/modellist/model-list-filters/filters/model-list-datetimerange-filter/model-list-datetime-range-filter.component.d.ts +11 -0
  119. package/lib/modellist/model-list-filters/filters/model-list-datetimerange-filter/model-list-datetimerange-filter.d.ts +4 -0
  120. package/lib/modellist/model-list-filters/filters/model-list-flags-filter/model-list-flags-filter.component.d.ts +11 -0
  121. package/lib/modellist/model-list-filters/filters/model-list-flags-filter/model-list-flags-filter.d.ts +4 -0
  122. package/lib/modellist/model-list-filters/filters/model-list-geodistance-filter/model-list-geodistance-filter.component.d.ts +11 -0
  123. package/lib/modellist/model-list-filters/filters/model-list-geodistance-filter/model-list-geodistance-filter.d.ts +4 -0
  124. package/lib/modellist/model-list-filters/filters/model-list-number-filter/model-list-number-filter.component.d.ts +17 -0
  125. package/lib/modellist/model-list-filters/filters/model-list-number-filter/model-list-number-filter.d.ts +19 -0
  126. package/lib/modellist/model-list-filters/filters/model-list-select-filter/model-list-select-filter.component.d.ts +17 -0
  127. package/lib/modellist/model-list-filters/filters/model-list-select-filter/model-list-select-filter.d.ts +16 -0
  128. package/lib/modellist/model-list-filters/filters/model-list-select-multi-filter/model-list-select-multi-filter.component.d.ts +11 -0
  129. package/lib/modellist/model-list-filters/filters/model-list-select-multi-filter/model-list-select-multi-filter.d.ts +4 -0
  130. package/lib/modellist/model-list-filters/filters/model-list-text-filter/model-list-text-filter.component.d.ts +16 -0
  131. package/lib/modellist/model-list-filters/filters/model-list-text-filter/model-list-text-filter.d.ts +4 -0
  132. package/lib/modellist/model-list-filters/filters/model-list-tree-filter/model-list-tree-filter.component.d.ts +11 -0
  133. package/lib/modellist/model-list-filters/filters/model-list-tree-filter/model-list-tree-filter.d.ts +4 -0
  134. package/lib/modellist/model-list-filters/model-list-filter.d.ts +31 -0
  135. package/lib/modellist/model-list-filters/model-list-filters/model-list-filters.component.d.ts +9 -0
  136. package/lib/modellist/model-list-filters/model-list-filters-select/model-list-filters-select.component.d.ts +13 -0
  137. package/lib/modellist/model-list-filters/model-list-filters.d.ts +15 -0
  138. package/lib/modellist/model-list-paginator/model-list-paginator/model-list-paginator.component.d.ts +23 -0
  139. package/lib/modellist/model-list-paginator/model-list-paginator.d.ts +16 -0
  140. package/lib/modellist/model-list-sorter/model-list-sorter/model-list-sorter.component.d.ts +22 -0
  141. package/lib/modellist/model-list-sorter/model-list-sorter.d.ts +61 -0
  142. package/lib/modellist/model-list.service.d.ts +79 -0
  143. package/lib/routing/breadcrumb/breadcrumb.component.d.ts +42 -0
  144. package/lib/routing/routing.d.ts +64 -0
  145. package/lib/uploader/index.d.ts +5 -0
  146. package/lib/uploader/interfaces.d.ts +67 -0
  147. package/lib/uploader/ng-file-drop.directive.d.ts +22 -0
  148. package/lib/uploader/ng-file-select.directive.d.ts +19 -0
  149. package/lib/uploader/ngx-uploader.class.d.ts +35 -0
  150. package/lib/uploader/ngx-uploader.module.d.ts +8 -0
  151. package/lib/utils/slugify.d.ts +1 -0
  152. package/lib/utils/tab-memory.service.d.ts +29 -0
  153. package/package.json +32 -0
  154. package/public-api.d.ts +37 -0
  155. package/src/lib/data/README.md +35 -0
@@ -0,0 +1,457 @@
1
+ import { Component, EventEmitter, Inject, Input, Optional, Output, } from '@angular/core';
2
+ import { UntypedFormGroup } from '@angular/forms';
3
+ import { firstValueFrom } from 'rxjs';
4
+ import { BootstrapDataDisplayConfig, DATA_DISPLAY_CONFIG, } from '../../data/data-parameters';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "../../messages/message.service";
7
+ import * as i2 from "@angular/common";
8
+ import * as i3 from "@angular/forms";
9
+ import * as i4 from "../fkselect/fkselect.component";
10
+ import * as i5 from "../m2mselect/m2mselect.component";
11
+ export class DispeditComponent {
12
+ /**
13
+ * Constructor, can be given DATA_DISPLAY_CONFIG injection token to override display classes.
14
+ * By default, bs5 config is used
15
+ * @param dconf DataDisplayConfig item
16
+ * @param _msgs messages service
17
+ */
18
+ constructor(dconf, _msgs) {
19
+ this.dconf = dconf;
20
+ this._msgs = _msgs;
21
+ /**
22
+ * Starting edit mode
23
+ * If mode is inline, edit is always true.
24
+ */
25
+ this.edit = false;
26
+ /**
27
+ * Display mode
28
+ * - dd provides display / edit within a dt/dd block
29
+ * - inline (to be renamed to form) provides a (label? and) form control
30
+ * */
31
+ this.mode = 'inline';
32
+ /**
33
+ * Custom choices
34
+ * If provided, a select form control will be used instead of base editor
35
+ */
36
+ this.choices = [];
37
+ /**
38
+ * Override placeholder, if provided.
39
+ * By default, manager.description is used
40
+ */
41
+ this.placeholder = '';
42
+ /**
43
+ * Override help, if provided.
44
+ * By default, manager.help is used.
45
+ */
46
+ this.help = '';
47
+ /**
48
+ * Hide label (for inline forms)
49
+ */
50
+ this.hideLabel = false;
51
+ /** Fk filter */
52
+ this.filter = {};
53
+ /** Output emitter, output model on every change */
54
+ this.changed = new EventEmitter();
55
+ /** Computed editor type */
56
+ this.realEditor = 'input.text';
57
+ /** Computed display type */
58
+ this.realDisplay = 'text';
59
+ /** Computed chocies type */
60
+ this.realChoices = [];
61
+ if (this.dconf === null) {
62
+ this.dconf = BootstrapDataDisplayConfig;
63
+ }
64
+ }
65
+ /**
66
+ * Init sequence.
67
+ * - Sets mode
68
+ * - Sets display function
69
+ * - Loads manager
70
+ * - Run misc checks on special values
71
+ * - Get help, placeholder strings
72
+ */
73
+ ngOnInit() {
74
+ this._setMode();
75
+ }
76
+ /**
77
+ * Upgrade all values on any change.
78
+ * @param changes
79
+ */
80
+ ngOnChanges(changes) {
81
+ this._setDisplayFn();
82
+ this.manager = this.model?.FM(this.field);
83
+ this.required = this.manager?.required || false;
84
+ this._checks();
85
+ this.realHelp = this.help || this.manager?.help || '';
86
+ this.realPlaceholder = this.placeholder || this.manager?.description || '';
87
+ this.realDefault = this.default;
88
+ this.save = this.save === undefined ? this.mode === 'dd' : this.save;
89
+ if (!this.edit && this.mode === 'dd') {
90
+ this.enableDisplayMode();
91
+ }
92
+ else {
93
+ this.enableEditMode();
94
+ }
95
+ }
96
+ /**
97
+ * Set up display mode.
98
+ * - get choices if available
99
+ * - get display type
100
+ * - process current value for display
101
+ * - set display classes
102
+ */
103
+ enableDisplayMode() {
104
+ this._getChoices();
105
+ this._getRealDisplay();
106
+ this._getDisplayValue();
107
+ this._setDisplayClasses();
108
+ this.edit = false;
109
+ }
110
+ /**
111
+ * Set up edit mode :
112
+ * - get choices if available
113
+ * - get editor type
114
+ * - prepare form controle
115
+ * - set form control value
116
+ * - update form control classes
117
+ */
118
+ enableEditMode() {
119
+ this._getChoices();
120
+ this._getRealEditor();
121
+ this._setFormControl();
122
+ this._setFormControlValue();
123
+ this._setEditorClasses();
124
+ this.edit = true;
125
+ }
126
+ /**
127
+ * Update model field from form control value (if value is valid).
128
+ * If save boolean is true, save values to API.
129
+ */
130
+ async update() {
131
+ if (this.fg && this.model && this.fg.valid) {
132
+ switch (this.realEditor) {
133
+ case 'input.decimal':
134
+ this.model[this.field] = Math.round(this.fg.value[this.field] * this.manager.factor);
135
+ break;
136
+ default:
137
+ this.model[this.field] = this.fg.value[this.field];
138
+ }
139
+ if (this.save === true) {
140
+ return this._save();
141
+ }
142
+ }
143
+ }
144
+ unsetEdit() {
145
+ if (this.mode == 'dd' && this.edit) {
146
+ this.edit = false;
147
+ delete this.fg;
148
+ }
149
+ }
150
+ toggleEdit() {
151
+ if (!this.edit) {
152
+ this.enableEditMode();
153
+ }
154
+ else {
155
+ this.unsetEdit();
156
+ this.enableDisplayMode();
157
+ }
158
+ }
159
+ /**
160
+ * Reset field to default value
161
+ * TODO: check if edit mode needs to be changed / saved
162
+ */
163
+ async setDefault() {
164
+ if (this.model) {
165
+ this.model[this.field] = this.realDefault;
166
+ this.fg.controls[this.field].setValue(this.realDefault, {
167
+ emitEvent: false,
168
+ });
169
+ }
170
+ await this.update();
171
+ }
172
+ async selectedRefItem($event) {
173
+ if (this.model) {
174
+ if ($event !== null) {
175
+ this.model[this.field] = $event.id;
176
+ this.model[`${this.field}_details`] = $event;
177
+ if (this.form) {
178
+ const fv = {};
179
+ fv[this.field] = $event.id;
180
+ this.form.patchValue(fv, { emitEvent: true });
181
+ }
182
+ }
183
+ else {
184
+ this.model[this.field] = null;
185
+ delete this.model[`${this.field}_details`];
186
+ if (this.form) {
187
+ const fv = {};
188
+ fv[this.field] = null;
189
+ this.form.patchValue(fv, { emitEvent: true });
190
+ }
191
+ }
192
+ return this._save();
193
+ }
194
+ }
195
+ onM2MValuesChanges(v) {
196
+ this.m2mValues = v;
197
+ }
198
+ _checks() {
199
+ if (this.editor === 'quill' && !this.viewer) {
200
+ this.viewer = 'quill';
201
+ }
202
+ }
203
+ /**
204
+ * Save value to database, only if model have an id.
205
+ * If mode is dd, toggle edit / display mode.
206
+ * @private
207
+ */
208
+ async _save() {
209
+ if (this.model) {
210
+ if (this.model.id) {
211
+ try {
212
+ await firstValueFrom(this.model.update([this.field], { updateModel: true }));
213
+ }
214
+ catch (e) {
215
+ console.error(e);
216
+ let msg = '';
217
+ if (e && e.error && e.error[this.field]) {
218
+ msg = `${e.error[this.field]}`;
219
+ }
220
+ this._msgs.error("Erreur lors de l'enregistrement", msg, JSON.stringify(e));
221
+ return;
222
+ }
223
+ }
224
+ if (this.mode === 'dd') {
225
+ this.unsetEdit();
226
+ this.enableDisplayMode();
227
+ }
228
+ this.changed.next(this.model);
229
+ }
230
+ }
231
+ _display(x) {
232
+ if (x) {
233
+ if (x._display) {
234
+ if (x._display instanceof Function) {
235
+ return x._display();
236
+ }
237
+ else {
238
+ return x._display;
239
+ }
240
+ }
241
+ if (this._tpl) {
242
+ return this._tpl(x);
243
+ }
244
+ }
245
+ return '';
246
+ }
247
+ /**
248
+ * Set display mode based on current display config
249
+ * @private
250
+ */
251
+ _setMode() {
252
+ if (!this.mode) {
253
+ this.mode = this.dconf.dispEdit.defaultMode;
254
+ }
255
+ }
256
+ _setDisplayFn() {
257
+ if (this.display) {
258
+ if (this.display && typeof this.display === 'string') {
259
+ this._tpl = (model) => `${model[this.display]}`;
260
+ }
261
+ else if (this.display && typeof this.display === 'function') {
262
+ this._tpl = this.display.bind(this);
263
+ }
264
+ }
265
+ else {
266
+ this._tpl = (model) => `${model['name'] ||
267
+ model['title'] ||
268
+ model['id']}`;
269
+ }
270
+ }
271
+ _getChoices() {
272
+ // Set display choices
273
+ let choices;
274
+ if (this.choices && this.choices.length) {
275
+ choices = this.choices;
276
+ }
277
+ else if (this.manager?.choices) {
278
+ choices = this.manager?.choices;
279
+ }
280
+ // Set display value
281
+ if (choices && choices.length > 0) {
282
+ this.realChoices = choices;
283
+ }
284
+ else {
285
+ delete this.realChoices;
286
+ }
287
+ }
288
+ _getRealDisplay() {
289
+ this.realDisplay = this.viewer
290
+ ? this.viewer
291
+ : this.manager?.displayType
292
+ ? this.manager.displayType
293
+ : 'text';
294
+ if (this.realChoices && this.realChoices.length) {
295
+ this.realDisplay = 'choice';
296
+ }
297
+ }
298
+ _getRealEditor() {
299
+ this.realEditor = this.editor
300
+ ? this.editor
301
+ : this.manager?.editorType || 'input.text';
302
+ if (this.realChoices && this.realChoices.length) {
303
+ this.realEditor = 'select';
304
+ }
305
+ }
306
+ _setFormControl() {
307
+ if (!this.form) {
308
+ const fgc = {};
309
+ fgc[this.field] = this.model.FC(this.field);
310
+ this.fg = new UntypedFormGroup(fgc);
311
+ }
312
+ else {
313
+ this.fg = this.form;
314
+ this.fg.setControl(this.field, this.model.FC(this.field), {
315
+ emitEvent: false,
316
+ });
317
+ }
318
+ if (this.mode === 'inline') {
319
+ this.fg.valueChanges.subscribe(() => {
320
+ this.update();
321
+ });
322
+ }
323
+ }
324
+ _setFormControlValue() {
325
+ switch (this.realEditor) {
326
+ case 'input.datetime':
327
+ const value = this.model[this.field];
328
+ const now = new Date();
329
+ const localnow = new Date(now.getTime() - now.getTimezoneOffset() * 60000);
330
+ if (value === null) {
331
+ this.fg.controls[this.field].setValue(null, { emitEvent: true });
332
+ }
333
+ else {
334
+ const time = value ? new Date(value) : new Date();
335
+ const offset = time.getTimezoneOffset();
336
+ const localtime = new Date(time.getTime() - offset * 60000);
337
+ this.fg.controls[this.field].setValue(localtime.toISOString().substring(0, 16), { emitEvent: true });
338
+ }
339
+ this.realDefault =
340
+ this.default || this.manager?.required
341
+ ? localnow.toISOString().substring(0, 16)
342
+ : null;
343
+ break;
344
+ case 'input.date':
345
+ const dt = this.model.toJson([this.field])[this.field];
346
+ this.fg.controls[this.field].setValue(dt);
347
+ break;
348
+ case 'input.decimal':
349
+ this.fg.controls[this.field].setValue(this.model[this.field] /
350
+ (this.manager.factor || 1));
351
+ }
352
+ }
353
+ _setEditorClasses() {
354
+ // FIXME: use realEditorClasses
355
+ if (!this.inputClasses) {
356
+ this.inputClasses =
357
+ this.dconf.dispEdit.inputClasses[this.realEditor] || '';
358
+ }
359
+ }
360
+ _getDisplayValue() {
361
+ const value = this.model[this.field];
362
+ this.dispValue = value;
363
+ if (this.realChoices) {
364
+ for (const c of this.realChoices) {
365
+ if (c === value) {
366
+ this.txtValue = c;
367
+ return;
368
+ }
369
+ else if (c.value && c.value === value) {
370
+ this.txtValue = c.desc;
371
+ return;
372
+ }
373
+ }
374
+ }
375
+ // Set display text depending on value and realDisplay value
376
+ if (value === true) {
377
+ this.txtValue = 'OUI';
378
+ }
379
+ else if (value === false) {
380
+ this.txtValue = 'NON';
381
+ }
382
+ else if (value === undefined || value === null) {
383
+ this.txtValue = 'non défini';
384
+ }
385
+ else {
386
+ switch (this.realDisplay) {
387
+ case 'fkdetails':
388
+ const details = this.model[`${this.field}_details`];
389
+ this.txtValue = this._display(details);
390
+ break;
391
+ case 'm2mdetails':
392
+ const m2mDetails = this.m2mValues ||
393
+ this.model[`${this.field}_details`];
394
+ this.txtValues = [];
395
+ for (const v of m2mDetails) {
396
+ this.txtValues.push(this._display(v));
397
+ }
398
+ break;
399
+ case 'decimal':
400
+ this.txtValue = `${value /
401
+ (this.manager.factor || 1)}`;
402
+ break;
403
+ default:
404
+ this.txtValue = `${value}`;
405
+ }
406
+ }
407
+ }
408
+ _setDisplayClasses() { }
409
+ }
410
+ DispeditComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: DispeditComponent, deps: [{ token: DATA_DISPLAY_CONFIG, optional: true }, { token: i1.DataMessageService }], target: i0.ɵɵFactoryTarget.Component });
411
+ DispeditComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.1.0", type: DispeditComponent, selector: "data-dispedit", inputs: { model: "model", field: "field", form: "form", edit: "edit", 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>\n <!--span.editable.disp-quill(*ngSwitchCase=\"'quill'\", (click)=\"enableEditMode()\")-->\n <!-- quill-view-html([content]=\"txtValue||''\")-->\n </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=\"'quill'\")-->\n <!-- quill-editor([formControl]=\"form.get(field)\")-->\n <!-- .form-text(*ngIf=\"realHelp\") {{realHelp}}-->\n <!-- span.ms-1(*ngIf=\"required\") (requis)-->\n <!-- .invalid-feedback.mt-0([class.d-block]=\"form && !form.controls[field].pristine && form.controls[field].errors?.['minlength']\") Trop court : {{$any(manager).minLength}} caract\u00E8res minimum...-->\n <!-- .invalid-feedback.mt-0([class.d-block]=\"form && !form.controls[field].pristine && form.controls[field].errors?.['maxlength']\") Trop long : {{$any(manager).maxLength}} caract\u00E8res maximum...-->\n <!-- .invalid-feedback.mt-0([class.d-block]=\"form && !form.controls[field].pristine && form.controls[field].errors?.['pattern']\") Format invalide...-->\n <!-- .invalid-feedback.mt-0([class.d-block]=\"form && !form.controls[field].pristine && form.controls[field].errors?.['required']\") Ce champ est requis...-->\n <!-- button([ngClass]=\"inputClasses\") Enregistrer-->\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 ? 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: "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: "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: i4.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: i5.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"] }, { kind: "pipe", type: i2.DatePipe, name: "date" }] });
412
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.1.0", ngImport: i0, type: DispeditComponent, decorators: [{
413
+ type: Component,
414
+ args: [{ selector: 'data-dispedit', 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>\n <!--span.editable.disp-quill(*ngSwitchCase=\"'quill'\", (click)=\"enableEditMode()\")-->\n <!-- quill-view-html([content]=\"txtValue||''\")-->\n </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=\"'quill'\")-->\n <!-- quill-editor([formControl]=\"form.get(field)\")-->\n <!-- .form-text(*ngIf=\"realHelp\") {{realHelp}}-->\n <!-- span.ms-1(*ngIf=\"required\") (requis)-->\n <!-- .invalid-feedback.mt-0([class.d-block]=\"form && !form.controls[field].pristine && form.controls[field].errors?.['minlength']\") Trop court : {{$any(manager).minLength}} caract\u00E8res minimum...-->\n <!-- .invalid-feedback.mt-0([class.d-block]=\"form && !form.controls[field].pristine && form.controls[field].errors?.['maxlength']\") Trop long : {{$any(manager).maxLength}} caract\u00E8res maximum...-->\n <!-- .invalid-feedback.mt-0([class.d-block]=\"form && !form.controls[field].pristine && form.controls[field].errors?.['pattern']\") Format invalide...-->\n <!-- .invalid-feedback.mt-0([class.d-block]=\"form && !form.controls[field].pristine && form.controls[field].errors?.['required']\") Ce champ est requis...-->\n <!-- button([ngClass]=\"inputClasses\") Enregistrer-->\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 ? 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"] }]
415
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
416
+ type: Optional
417
+ }, {
418
+ type: Inject,
419
+ args: [DATA_DISPLAY_CONFIG]
420
+ }] }, { type: i1.DataMessageService }]; }, propDecorators: { model: [{
421
+ type: Input
422
+ }], field: [{
423
+ type: Input
424
+ }], form: [{
425
+ type: Input
426
+ }], edit: [{
427
+ type: Input
428
+ }], mode: [{
429
+ type: Input
430
+ }], choices: [{
431
+ type: Input
432
+ }], inputClasses: [{
433
+ type: Input
434
+ }], editor: [{
435
+ type: Input
436
+ }], viewer: [{
437
+ type: Input
438
+ }], default: [{
439
+ type: Input
440
+ }], placeholder: [{
441
+ type: Input
442
+ }], help: [{
443
+ type: Input
444
+ }], hideLabel: [{
445
+ type: Input
446
+ }], queryset: [{
447
+ type: Input
448
+ }], collection: [{
449
+ type: Input
450
+ }], display: [{
451
+ type: Input
452
+ }], filter: [{
453
+ type: Input
454
+ }], changed: [{
455
+ type: Output
456
+ }] } });
457
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGlzcGVkaXQuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvZGF0YS9zcmMvbGliL2Rpc3BlZGl0L2Rpc3BlZGl0L2Rpc3BlZGl0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2RhdGEvc3JjL2xpYi9kaXNwZWRpdC9kaXNwZWRpdC9kaXNwZWRpdC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFlBQVksRUFDWixNQUFNLEVBQ04sS0FBSyxFQUdMLFFBQVEsRUFDUixNQUFNLEdBRVAsTUFBTSxlQUFlLENBQUM7QUFHdkIsT0FBTyxFQUFzQixnQkFBZ0IsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ3RFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFVdEMsT0FBTyxFQUNMLDBCQUEwQixFQUMxQixtQkFBbUIsR0FFcEIsTUFBTSw0QkFBNEIsQ0FBQzs7Ozs7OztBQVFwQyxNQUFNLE9BQU8saUJBQWlCO0lBc0c1Qjs7Ozs7T0FLRztJQUNILFlBQ2tELEtBQXdCLEVBQ2hFLEtBQXlCO1FBRGUsVUFBSyxHQUFMLEtBQUssQ0FBbUI7UUFDaEUsVUFBSyxHQUFMLEtBQUssQ0FBb0I7UUFyR25DOzs7V0FHRztRQUNhLFNBQUksR0FBRyxLQUFLLENBQUM7UUFRN0I7Ozs7YUFJSztRQUNXLFNBQUksR0FBNkIsUUFBUSxDQUFDO1FBQzFEOzs7V0FHRztRQUNhLFlBQU8sR0FBc0IsRUFBRSxDQUFDO1FBU2hEOzs7V0FHRztRQUNhLGdCQUFXLEdBQVcsRUFBRSxDQUFDO1FBQ3pDOzs7V0FHRztRQUNhLFNBQUksR0FBVyxFQUFFLENBQUM7UUFDbEM7O1dBRUc7UUFDYSxjQUFTLEdBQVksS0FBSyxDQUFDO1FBVTNDLGdCQUFnQjtRQUNBLFdBQU0sR0FBZSxFQUFFLENBQUM7UUFFeEMs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QUFDLFFBQVEsR0FBRyxHQUNkLEtBQUs7d0JBQ0wsQ0FBRSxJQUFJLENBQUMsT0FBMEMsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUMvRCxFQUFFLENBQUM7b0JBQ0gsTUFBTTtnQkFDUjtvQkFDRSxJQUFJLENBQUMsUUFBUSxHQUFHLEdBQUcsS0FBSyxFQUFFLENBQUM7YUFDOUI7U0FDRjtJQUNILENBQUM7SUFFTyxrQkFBa0IsS0FBSSxDQUFDOzs4R0F4ZXBCLGlCQUFpQixrQkE2R04sbUJBQW1CO2tHQTdHOUIsaUJBQWlCLG1jQ3BDOUIsNCtkQTJKZTsyRkR2SEYsaUJBQWlCO2tCQUw3QixTQUFTOytCQUNFLGVBQWU7OzBCQWlIdEIsUUFBUTs7MEJBQUksTUFBTTsyQkFBQyxtQkFBbUI7NkVBekd6QixLQUFLO3NCQUFwQixLQUFLO2dCQUVVLEtBQUs7c0JBQXBCLEtBQUs7Z0JBRVUsSUFBSTtzQkFBbkIsS0FBSztnQkFLVSxJQUFJO3NCQUFuQixLQUFLO2dCQWFVLElBQUk7c0JBQW5CLEtBQUs7Z0JBS1UsT0FBTztzQkFBdEIsS0FBSztnQkFFVSxZQUFZO3NCQUEzQixLQUFLO2dCQUVVLE1BQU07c0JBQXJCLEtBQUs7Z0JBRVUsTUFBTTtzQkFBckIsS0FBSztnQkFFVSxPQUFPO3NCQUF0QixLQUFLO2dCQUtVLFdBQVc7c0JBQTFCLEtBQUs7Z0JBS1UsSUFBSTtzQkFBbkIsS0FBSztnQkFJVSxTQUFTO3NCQUF4QixLQUFLO2dCQUtVLFFBQVE7c0JBQXZCLEtBQUs7Z0JBRVUsVUFBVTtzQkFBekIsS0FBSztnQkFFVSxPQUFPO3NCQUF0QixLQUFLO2dCQUVVLE1BQU07c0JBQXJCLEtBQUs7Z0JBR1csT0FBTztzQkFBdkIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbmplY3QsXG4gIElucHV0LFxuICBPbkNoYW5nZXMsXG4gIE9uSW5pdCxcbiAgT3B0aW9uYWwsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBEYXRhTW9kZWwgfSBmcm9tICcuLi8uLi9kYXRhL2RhdGEtbW9kZWwnO1xuaW1wb3J0IHsgQmFzZUZpZWxkTWFuYWdlciB9IGZyb20gJy4uLy4uL2RhdGEvZmllbGRzL2Jhc2UnO1xuaW1wb3J0IHsgVW50eXBlZEZvcm1Db250cm9sLCBVbnR5cGVkRm9ybUdyb3VwIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xuaW1wb3J0IHsgZmlyc3RWYWx1ZUZyb20gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7XG4gIERJU1BFRElUX0RJU1BMQVlfVFlQRVMsXG4gIERJU1BFRElUX0VESVRPUl9UWVBFUyxcbiAgSURpc3BFZGl0Q2hvaWNlLFxufSBmcm9tICcuL2Rpc3BlZGl0LmNvbnN0YW50cyc7XG5pbXBvcnQgeyBGaWx0ZXJEYXRhLCBRdWVyeXNldCB9IGZyb20gJy4uLy4uL2RhdGEvZGF0YS1xdWVyeSc7XG5pbXBvcnQgeyBDb2xsZWN0aW9uIH0gZnJvbSAnLi4vLi4vZGF0YS9kYXRhLWNvbGxlY3Rpb24nO1xuaW1wb3J0IHsgVHBsRnVuIH0gZnJvbSAnLi4vZmtzZWxlY3QvZmtzZWxlY3QuY29tcG9uZW50JztcbmltcG9ydCB7IERlY2ltYWxGaWVsZE1hbmFnZXIgfSBmcm9tICcuLi8uLi9kYXRhL2ZpZWxkcy9udW1iZXJzJztcbmltcG9ydCB7XG4gIEJvb3RzdHJhcERhdGFEaXNwbGF5Q29uZmlnLFxuICBEQVRBX0RJU1BMQVlfQ09ORklHLFxuICBEYXRhRGlzcGxheUNvbmZpZyxcbn0gZnJvbSAnLi4vLi4vZGF0YS9kYXRhLXBhcmFtZXRlcnMnO1xuaW1wb3J0IHsgRGF0YU1lc3NhZ2VTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vbWVzc2FnZXMvbWVzc2FnZS5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZGF0YS1kaXNwZWRpdCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9kaXNwZWRpdC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2Rpc3BlZGl0LmNvbXBvbmVudC5zYXNzJ10sXG59KVxuZXhwb3J0IGNsYXNzIERpc3BlZGl0Q29tcG9uZW50PEZULCBUIGV4dGVuZHMgRGF0YU1vZGVsLCBSIGV4dGVuZHMgRGF0YU1vZGVsPlxuICBpbXBsZW1lbnRzIE9uSW5pdCwgT25DaGFuZ2VzXG57XG4gIC8qKiBNb2RlbCAobWFuZGF0b3J5KSAqL1xuICBASW5wdXQoKSBwdWJsaWMgbW9kZWwhOiBUO1xuICAvKiogRmllbGQgKG1hbmRhdG9yeSkgKi9cbiAgQElucHV0KCkgcHVibGljIGZpZWxkITogc3RyaW5nO1xuICAvKiogRXh0ZXJuYWwgZm9ybSAqL1xuICBASW5wdXQoKSBwdWJsaWMgZm9ybT86IFVudHlwZWRGb3JtR3JvdXA7XG4gIC8qKlxuICAgKiBTdGFydGluZyBlZGl0IG1vZGVcbiAgICogSWYgbW9kZSBpcyBpbmxpbmUsIGVkaXQgaXMgYWx3YXlzIHRydWUuXG4gICAqL1xuICBASW5wdXQoKSBwdWJsaWMgZWRpdCA9IGZhbHNlO1xuICAvKipcbiAgICogU2F2ZSB1cGRhdGVkIHZhbHVlcyA/XG4gICAqIElmIG5vdCBnaXZlbiwgZGVmYXVsdCB2YWx1ZSBkZXBlbmRzIG9uIG1vZGUgOlxuICAgKiAtIHNhdmUgaWYgbW9kZSBpcyBkZFxuICAgKiAtIGRvbid0IHNhdmUgaWYgbW9kZSBpcyBpbmxpbmVcbiAgICovXG4gIHB1YmxpYyBzYXZlPzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIERpc3BsYXkgbW9kZVxuICAgKiAtIGRkIHByb3ZpZGVzIGRpc3BsYXkgLyBlZGl0IHdpdGhpbiBhIGR0L2RkIGJsb2NrXG4gICAqIC0gaW5saW5lICh0byBiZSByZW5hbWVkIHRvIGZvcm0pIHByb3ZpZGVzIGEgKGxhYmVsPyBhbmQpIGZvcm0gY29udHJvbFxuICAgKiAqL1xuICBASW5wdXQoKSBwdWJsaWMgbW9kZTogJ2RkJyB8ICdpbmxpbmUnIHwgJ2Zvcm0nID0gJ2lubGluZSc7XG4gIC8qKlxuICAgKiBDdXN0b20gY2hvaWNlc1xuICAgKiBJZiBwcm92aWRlZCwgYSBzZWxlY3QgZm9ybSBjb250cm9sIHdpbGwgYmUgdXNlZCBpbnN0ZWFkIG9mIGJhc2UgZWRpdG9yXG4gICAqL1xuICBASW5wdXQoKSBwdWJsaWMgY2hvaWNlczogSURpc3BFZGl0Q2hvaWNlW10gPSBbXTtcbiAgLyoqIEN1c3RvbSBpbnB1dCBjbGFzc2VzICovXG4gIEBJbnB1dCgpIHB1YmxpYyBpbnB1dENsYXNzZXMhOiBzdHJpbmdbXSB8IHN0cmluZztcbiAgLyoqIE92ZXJyaWRlIGVkaXRvciwgaWYgcHJvdmlkZWQgKi9cbiAgQElucHV0KCkgcHVibGljIGVkaXRvcj86IERJU1BFRElUX0VESVRPUl9UWVBFUztcbiAgLyoqIE92ZXJyaWRlIHZpZXdlciwgaWYgcHJvdmlkZWQgKi9cbiAgQElucHV0KCkgcHVibGljIHZpZXdlcj86IERJU1BFRElUX0RJU1BMQVlfVFlQRVM7XG4gIC8qKiBPdmVycmlkZSBkZWZhdWx0IHZhbHVlICovXG4gIEBJbnB1dCgpIHB1YmxpYyBkZWZhdWx0PzogYW55O1xuICAvKipcbiAgICogT3ZlcnJpZGUgcGxhY2Vob2xkZXIsIGlmIHByb3ZpZGVkLlxuICAgKiBCeSBkZWZhdWx0LCBtYW5hZ2VyLmRlc2NyaXB0aW9uIGlzIHVzZWRcbiAgICovXG4gIEBJbnB1dCgpIHB1YmxpYyBwbGFjZWhvbGRlcjogc3RyaW5nID0gJyc7XG4gIC8qKlxuICAgKiBPdmVycmlkZSBoZWxwLCBpZiBwcm92aWRlZC5cbiAgICogQnkgZGVmYXVsdCwgbWFuYWdlci5oZWxwIGlzIHVzZWQuXG4gICAqL1xuICBASW5wdXQoKSBwdWJsaWMgaGVscDogc3RyaW5nID0gJyc7XG4gIC8qKlxuICAgKiAgSGlkZSBsYWJlbCAoZm9yIGlubGluZSBmb3JtcylcbiAgICovXG4gIEBJbnB1dCgpIHB1YmxpYyBoaWRlTGFiZWw6IGJvb2xlYW4gPSBmYWxzZTtcblxuICAvLyBGSyBmaWVsZHNcbiAgLy8gVE9ETzogcmVuYW1lIGFzIGZrXyBvciByZWxhdGVkX1xuICAvKiogRmsgcXVlcnlzZXQgKi9cbiAgQElucHV0KCkgcHVibGljIHF1ZXJ5c2V0PzogUXVlcnlzZXQ8Uj47XG4gIC8qKiBGayBjb2xsZWN0aW9uICovXG4gIEBJbnB1dCgpIHB1YmxpYyBjb2xsZWN0aW9uPzogQ29sbGVjdGlvbjxSPjtcbiAgLyoqIEZrIGRpc3BsYXkgKi9cbiAgQElucHV0KCkgcHVibGljIGRpc3BsYXk/OiBzdHJpbmcgfCBUcGxGdW48Uj47XG4gIC8qKiBGayBmaWx0ZXIgKi9cbiAgQElucHV0KCkgcHVibGljIGZpbHRlcjogRmlsdGVyRGF0YSA9IHt9O1xuXG4gIC8qKiBPdXRwdXQgZW1pdHRlciwgb3V0cHV0IG1vZGVsIG9uIGV2ZXJ5IGNoYW5nZSAqL1xuICBAT3V0cHV0KCkgcHVibGljIGNoYW5nZWQgPSBuZXcgRXZlbnRFbWl0dGVyPFQ+KCk7XG5cbiAgLyoqIEZpZWxkIG1hbmFnZXIgKi9cbiAgcHVibGljIG1hbmFnZXI/OiBCYXNlRmllbGRNYW5hZ2VyPEZUPjtcblxuICAvKiogVGV4dCB2YWx1ZSB1c2VkIGZvciBkaXNwbGF5ICovXG4gIHB1YmxpYyB0eHRWYWx1ZT86IHN0cmluZztcbiAgLyoqIFRleHQgdmFsdWVzIHVzZWQgZm9yIG1hbnkgZGlzcGxheXMgKi9cbiAgcHVibGljIHR4dFZhbHVlcz86IHN0cmluZ1tdO1xuXG4gIC8qKiBDb21wdXRlZCBlZGl0b3IgdHlwZSAqL1xuICBwdWJsaWMgcmVhbEVkaXRvcjogRElTUEVESVRfRURJVE9SX1RZUEVTID0gJ2lucHV0LnRleHQnO1xuICAvKiogQ29tcHV0ZWQgZGlzcGxheSB0eXBlICovXG4gIHB1YmxpYyByZWFsRGlzcGxheTogRElTUEVESVRfRElTUExBWV9UWVBFUyA9ICd0ZXh0JztcbiAgLyoqIEN1cnJlbnQgZGlzcCByYXcgdmFsdWUgKi9cbiAgcHVibGljIGRpc3BWYWx1ZT86IGFueTtcbiAgLyoqIENvbXB1dGVkIGNob2NpZXMgdHlwZSAqL1xuICBwdWJsaWMgcmVhbENob2ljZXM/OiBJRGlzcEVkaXRDaG9pY2VbXSA9IFtdO1xuICAvKiogQ29tcHV0ZWQgaGVscCAqL1xuICBwdWJsaWMgcmVhbEhlbHAhOiBzdHJpbmc7XG4gIC8qKiBDb21wdXRlZCBwbGFjZWhvbGRlciAqL1xuICBwdWJsaWMgcmVhbFBsYWNlaG9sZGVyITogc3RyaW5nO1xuICAvKiogQ29tcHV0ZWQgcmVxdWlyZWQgKi9cbiAgcHVibGljIHJlcXVpcmVkITogYm9vbGVhbjtcbiAgLyoqIENvbXB1dGVkIGRlZmF1bHQgdmFsdWUgKi9cbiAgcHVibGljIHJlYWxEZWZhdWx0ITogYW55O1xuXG4gIHB1YmxpYyBtMm1WYWx1ZXM/OiBhbnlbXTtcblxuICAvLyBMb2NhbCBmb3JtIGdyb3VwXG4gIHB1YmxpYyBmZz86IFVudHlwZWRGb3JtR3JvdXA7XG5cbiAgLy8gRGlzcGxheSB0ZW1wbGF0ZSBmdW5jdGlvblxuICBwcml2YXRlIF90cGwhOiBUcGxGdW48Uj47XG5cbiAgLyoqXG4gICAqIENvbnN0cnVjdG9yLCBjYW4gYmUgZ2l2ZW4gREFUQV9ESVNQTEFZX0NPTkZJRyBpbmplY3Rpb24gdG9rZW4gdG8gb3ZlcnJpZGUgZGlzcGxheSBjbGFzc2VzLlxuICAgKiBCeSBkZWZhdWx0LCBiczUgY29uZmlnIGlzIHVzZWRcbiAgICogQHBhcmFtIGRjb25mIERhdGFEaXNwbGF5Q29uZmlnIGl0ZW1cbiAgICogQHBhcmFtIF9tc2dzIG1lc3NhZ2VzIHNlcnZpY2VcbiAgICovXG4gIGNvbnN0cnVjdG9yKFxuICAgIEBPcHRpb25hbCgpIEBJbmplY3QoREFUQV9ESVNQTEFZX0NPTkZJRykgcHVibGljIGRjb25mOiBEYXRhRGlzcGxheUNvbmZpZyxcbiAgICBwcml2YXRlIF9tc2dzOiBEYXRhTWVzc2FnZVNlcnZpY2VcbiAgKSB7XG4gICAgaWYgKHRoaXMuZGNvbmYgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZGNvbmYgPSBCb290c3RyYXBEYXRhRGlzcGxheUNvbmZpZztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogSW5pdCBzZXF1ZW5jZS5cbiAgICogLSBTZXRzIG1vZGVcbiAgICogLSBTZXRzIGRpc3BsYXkgZnVuY3Rpb25cbiAgICogLSBMb2FkcyBtYW5hZ2VyXG4gICAqIC0gUnVuIG1pc2MgY2hlY2tzIG9uIHNwZWNpYWwgdmFsdWVzXG4gICAqIC0gR2V0IGhlbHAsIHBsYWNlaG9sZGVyIHN0cmluZ3NcbiAgICovXG4gIHB1YmxpYyBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLl9zZXRNb2RlKCk7XG4gIH1cblxuICAvKipcbiAgICogVXBncmFkZSBhbGwgdmFsdWVzIG9uIGFueSBjaGFuZ2UuXG4gICAqIEBwYXJhbSBjaGFuZ2VzXG4gICAqL1xuICBwdWJsaWMgbmdPbkNoYW5nZXMoY2hhbmdlczogU2ltcGxlQ2hhbmdlcyk6IHZvaWQge1xuICAgIHRoaXMuX3NldERpc3BsYXlGbigpO1xuICAgIHRoaXMubWFuYWdlciA9IHRoaXMubW9kZWw/LkZNKHRoaXMuZmllbGQpO1xuICAgIHRoaXMucmVxdWlyZWQgPSB0aGlzLm1hbmFnZXI/LnJlcXVpcmVkIHx8IGZhbHNlO1xuICAgIHRoaXMuX2NoZWNrcygpO1xuICAgIHRoaXMucmVhbEhlbHAgPSB0aGlzLmhlbHAgfHwgdGhpcy5tYW5hZ2VyPy5oZWxwIHx8ICcnO1xuICAgIHRoaXMucmVhbFBsYWNlaG9sZGVyID0gdGhpcy5wbGFjZWhvbGRlciB8fCB0aGlzLm1hbmFnZXI/LmRlc2NyaXB0aW9uIHx8ICcnO1xuICAgIHRoaXMucmVhbERlZmF1bHQgPSB0aGlzLmRlZmF1bHQ7XG4gICAgdGhpcy5zYXZlID0gdGhpcy5zYXZlID09PSB1bmRlZmluZWQgPyB0aGlzLm1vZGUgPT09ICdkZCcgOiB0aGlzLnNhdmU7XG4gICAgaWYgKCF0aGlzLmVkaXQgJiYgdGhpcy5tb2RlID09PSAnZGQnKSB7XG4gICAgICB0aGlzLmVuYWJsZURpc3BsYXlNb2RlKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZW5hYmxlRWRpdE1vZGUoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2V0IHVwIGRpc3BsYXkgbW9kZS5cbiAgICogLSBnZXQgY2hvaWNlcyBpZiBhdmFpbGFibGVcbiAgICogLSBnZXQgZGlzcGxheSB0eXBlXG4gICAqIC0gcHJvY2VzcyBjdXJyZW50IHZhbHVlIGZvciBkaXNwbGF5XG4gICAqIC0gc2V0IGRpc3BsYXkgY2xhc3Nlc1xuICAgKi9cbiAgcHVibGljIGVuYWJsZURpc3BsYXlNb2RlKCkge1xuICAgIHRoaXMuX2dldENob2ljZXMoKTtcbiAgICB0aGlzLl9nZXRSZWFsRGlzcGxheSgpO1xuICAgIHRoaXMuX2dldERpc3BsYXlWYWx1ZSgpO1xuICAgIHRoaXMuX3NldERpc3BsYXlDbGFzc2VzKCk7XG4gICAgdGhpcy5lZGl0ID0gZmFsc2U7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHVwIGVkaXQgbW9kZSA6XG4gICAqIC0gZ2V0IGNob2ljZXMgaWYgYXZhaWxhYmxlXG4gICAqIC0gZ2V0IGVkaXRvciB0eXBlXG4gICAqIC0gcHJlcGFyZSBmb3JtIGNvbnRyb2xlXG4gICAqIC0gc2V0IGZvcm0gY29udHJvbCB2YWx1ZVxuICAgKiAtIHVwZGF0ZSBmb3JtIGNvbnRyb2wgY2xhc3Nlc1xuICAgKi9cbiAgcHVibGljIGVuYWJsZUVkaXRNb2RlKCkge1xuICAgIHRoaXMuX2dldENob2ljZXMoKTtcbiAgICB0aGlzLl9nZXRSZWFsRWRpdG9yKCk7XG4gICAgdGhpcy5fc2V0Rm9ybUNvbnRyb2woKTtcbiAgICB0aGlzLl9zZXRGb3JtQ29udHJvbFZhbHVlKCk7XG4gICAgdGhpcy5fc2V0RWRpdG9yQ2xhc3NlcygpO1xuICAgIHRoaXMuZWRpdCA9IHRydWU7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlIG1vZGVsIGZpZWxkIGZyb20gZm9ybSBjb250cm9sIHZhbHVlIChpZiB2YWx1ZSBpcyB2YWxpZCkuXG4gICAqIElmIHNhdmUgYm9vbGVhbiBpcyB0cnVlLCBzYXZlIHZhbHVlcyB0byBBUEkuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgdXBkYXRlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLmZnICYmIHRoaXMubW9kZWwgJiYgdGhpcy5mZy52YWxpZCkge1xuICAgICAgc3dpdGNoICh0aGlzLnJlYWxFZGl0b3IpIHtcbiAgICAgICAgY2FzZSAnaW5wdXQuZGVjaW1hbCc6XG4gICAgICAgICAgKHRoaXMubW9kZWwgYXMgYW55KVt0aGlzLmZpZWxkXSA9IE1hdGgucm91bmQoXG4gICAgICAgICAgICB0aGlzLmZnLnZhbHVlW3RoaXMuZmllbGRdICogKHRoaXMubWFuYWdlciBhcyBhbnkpLmZhY3RvclxuICAgICAgICAgICk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgKHRoaXMubW9kZWwgYXMgYW55KVt0aGlzLmZpZWxkXSA9IHRoaXMuZmcudmFsdWVbdGhpcy5maWVsZF07XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5zYXZlID09PSB0cnVlKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zYXZlKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgdW5zZXRFZGl0KCkge1xuICAgIGlmICh0aGlzLm1vZGUgPT0gJ2RkJyAmJiB0aGlzLmVkaXQpIHtcbiAgICAgIHRoaXMuZWRpdCA9IGZhbHNlO1xuICAgICAgZGVsZXRlIHRoaXMuZmc7XG4gICAgfVxuICB9XG5cbiAgdG9nZ2xlRWRpdCgpIHtcbiAgICBpZiAoIXRoaXMuZWRpdCkge1xuICAgICAgdGhpcy5lbmFibGVFZGl0TW9kZSgpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnVuc2V0RWRpdCgpO1xuICAgICAgdGhpcy5lbmFibGVEaXNwbGF5TW9kZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBSZXNldCBmaWVsZCB0byBkZWZhdWx0IHZhbHVlXG4gICAqIFRPRE86IGNoZWNrIGlmIGVkaXQgbW9kZSBuZWVkcyB0byBiZSBjaGFuZ2VkIC8gc2F2ZWRcbiAgICovXG4gIHB1YmxpYyBhc3luYyBzZXREZWZhdWx0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLm1vZGVsKSB7XG4gICAgICAodGhpcy5tb2RlbCBhcyBhbnkpW3RoaXMuZmllbGRdID0gdGhpcy5yZWFsRGVmYXVsdDtcbiAgICAgIHRoaXMuZmchLmNvbnRyb2xzW3RoaXMuZmllbGRdLnNldFZhbHVlKHRoaXMucmVhbERlZmF1bHQsIHtcbiAgICAgICAgZW1pdEV2ZW50OiBmYWxzZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBhd2FpdCB0aGlzLnVwZGF0ZSgpO1xuICB9XG5cbiAgcHVibGljIGFzeW5jIHNlbGVjdGVkUmVmSXRlbSgkZXZlbnQ6IFQgfCBudWxsKSB7XG4gICAgaWYgKHRoaXMubW9kZWwpIHtcbiAgICAgIGlmICgkZXZlbnQgIT09IG51bGwpIHtcbiAgICAgICAgKHRoaXMubW9kZWwgYXMgYW55KVt0aGlzLmZpZWxkXSA9ICRldmVudC5pZDtcbiAgICAgICAgKHRoaXMubW9kZWwgYXMgYW55KVtgJHt0aGlzLmZpZWxkfV9kZXRhaWxzYF0gPSAkZXZlbnQ7XG4gICAgICAgIGlmICh0aGlzLmZvcm0pIHtcbiAgICAgICAgICBjb25zdCBmdjogeyBbaW5kZXg6IHN0cmluZ106IG51bWJlciB8IG51bGwgfSA9IHt9O1xuICAgICAgICAgIGZ2W3RoaXMuZmllbGRdID0gJGV2ZW50LmlkO1xuICAgICAgICAgIHRoaXMuZm9ybS5wYXRjaFZhbHVlKGZ2LCB7IGVtaXRFdmVudDogdHJ1ZSB9KTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgKHRoaXMubW9kZWwgYXMgYW55KVt0aGlzLmZpZWxkXSA9IG51bGw7XG4gICAgICAgIGRlbGV0ZSAodGhpcy5tb2RlbCBhcyBhbnkpW2Ake3RoaXMuZmllbGR9X2RldGFpbHNgXTtcbiAgICAgICAgaWYgKHRoaXMuZm9ybSkge1xuICAgICAgICAgIGNvbnN0IGZ2OiB7IFtpbmRleDogc3RyaW5nXTogbnVtYmVyIHwgbnVsbCB9ID0ge307XG4gICAgICAgICAgZnZbdGhpcy5maWVsZF0gPSBudWxsO1xuICAgICAgICAgIHRoaXMuZm9ybS5wYXRjaFZhbHVlKGZ2LCB7IGVtaXRFdmVudDogdHJ1ZSB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHRoaXMuX3NhdmUoKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgb25NMk1WYWx1ZXNDaGFuZ2VzKHY6IGFueVtdKSB7XG4gICAgdGhpcy5tMm1WYWx1ZXMgPSB2O1xuICB9XG5cbiAgcHJpdmF0ZSBfY2hlY2tzKCkge1xuICAgIGlmICh0aGlzLmVkaXRvciA9PT0gJ3F1aWxsJyAmJiAhdGhpcy52aWV3ZXIpIHtcbiAgICAgIHRoaXMudmlld2VyID0gJ3F1aWxsJztcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogU2F2ZSB2YWx1ZSB0byBkYXRhYmFzZSwgb25seSBpZiBtb2RlbCBoYXZlIGFuIGlkLlxuICAgKiBJZiBtb2RlIGlzIGRkLCB0b2dnbGUgZWRpdCAvIGRpc3BsYXkgbW9kZS5cbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgYXN5bmMgX3NhdmUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgaWYgKHRoaXMubW9kZWwpIHtcbiAgICAgIGlmICh0aGlzLm1vZGVsLmlkKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgZmlyc3RWYWx1ZUZyb20oXG4gICAgICAgICAgICB0aGlzLm1vZGVsLnVwZGF0ZShbdGhpcy5maWVsZF0sIHsgdXBkYXRlTW9kZWw6IHRydWUgfSlcbiAgICAgICAgICApO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcbiAgICAgICAgICBsZXQgbXNnOiBzdHJpbmcgPSAnJztcbiAgICAgICAgICBpZiAoZSAmJiAoZSBhcyBhbnkpLmVycm9yICYmIChlIGFzIGFueSkuZXJyb3JbdGhpcy5maWVsZF0pIHtcbiAgICAgICAgICAgIG1zZyA9IGAkeyhlIGFzIGFueSkuZXJyb3JbdGhpcy5maWVsZF19YDtcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhpcy5fbXNncy5lcnJvcihcbiAgICAgICAgICAgIFwiRXJyZXVyIGxvcnMgZGUgbCdlbnJlZ2lzdHJlbWVudFwiLFxuICAgICAgICAgICAgbXNnLFxuICAgICAgICAgICAgSlNPTi5zdHJpbmdpZnkoZSlcbiAgICAgICAgICApO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgaWYgKHRoaXMubW9kZSA9PT0gJ2RkJykge1xuICAgICAgICB0aGlzLnVuc2V0RWRpdCgpO1xuICAgICAgICB0aGlzLmVuYWJsZURpc3BsYXlNb2RlKCk7XG4gICAgICB9XG4gICAgICB0aGlzLmNoYW5nZWQubmV4dCh0aGlzLm1vZGVsKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9kaXNwbGF5KHg6IGFueSk6IGFueSB7XG4gICAgaWYgKHgpIHtcbiAgICAgIGlmICh4Ll9kaXNwbGF5KSB7XG4gICAgICAgIGlmICh4Ll9kaXNwbGF5IGluc3RhbmNlb2YgRnVuY3Rpb24pIHtcbiAgICAgICAgICByZXR1cm4geC5fZGlzcGxheSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJldHVybiB4Ll9kaXNwbGF5O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAodGhpcy5fdHBsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl90cGwoeCk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiAnJztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgZGlzcGxheSBtb2RlIGJhc2VkIG9uIGN1cnJlbnQgZGlzcGxheSBjb25maWdcbiAgICogQHByaXZhdGVcbiAgICovXG4gIHByaXZhdGUgX3NldE1vZGUoKSB7XG4gICAgaWYgKCF0aGlzLm1vZGUpIHtcbiAgICAgIHRoaXMubW9kZSA9IHRoaXMuZGNvbmYuZGlzcEVkaXQuZGVmYXVsdE1vZGU7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfc2V0RGlzcGxheUZuKCkge1xuICAgIGlmICh0aGlzLmRpc3BsYXkpIHtcbiAgICAgIGlmICh0aGlzLmRpc3BsYXkgJiYgdHlwZW9mIHRoaXMuZGlzcGxheSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhpcy5fdHBsID0gKG1vZGVsOiBSKSA9PiBgJHsobW9kZWwgYXMgYW55KVt0aGlzLmRpc3BsYXkgYXMgc3RyaW5nXX1gO1xuICAgICAgfSBlbHNlIGlmICh0aGlzLmRpc3BsYXkgJiYgdHlwZW9mIHRoaXMuZGlzcGxheSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aGlzLl90cGwgPSB0aGlzLmRpc3BsYXkuYmluZCh0aGlzKTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fdHBsID0gKG1vZGVsOiBSKSA9PlxuICAgICAgICBgJHtcbiAgICAgICAgICAobW9kZWwgYXMgYW55KVsnbmFtZSddIHx8XG4gICAgICAgICAgKG1vZGVsIGFzIGFueSlbJ3RpdGxlJ10gfHxcbiAgICAgICAgICAobW9kZWwgYXMgYW55KVsnaWQnXVxuICAgICAgICB9YDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9nZXRDaG9pY2VzKCkge1xuICAgIC8vIFNldCBkaXNwbGF5IGNob2ljZXNcbiAgICBsZXQgY2hvaWNlczogSURpc3BFZGl0Q2hvaWNlW10gfCB1bmRlZmluZWQ7XG4gICAgaWYgKHRoaXMuY2hvaWNlcyAmJiB0aGlzLmNob2ljZXMubGVuZ3RoKSB7XG4gICAgICBjaG9pY2VzID0gdGhpcy5jaG9pY2VzO1xuICAgIH0gZWxzZSBpZiAoKHRoaXMubWFuYWdlciBhcyBhbnkpPy5jaG9pY2VzKSB7XG4gICAgICBjaG9pY2VzID0gKHRoaXMubWFuYWdlciBhcyBhbnkpPy5jaG9pY2VzO1xuICAgIH1cbiAgICAvLyBTZXQgZGlzcGxheSB2YWx1ZVxuICAgIGlmIChjaG9pY2VzICYmIGNob2ljZXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5yZWFsQ2hvaWNlcyA9IGNob2ljZXM7XG4gICAgfSBlbHNlIHtcbiAgICAgIGRlbGV0ZSB0aGlzLnJlYWxDaG9pY2VzO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX2dldFJlYWxEaXNwbGF5KCkge1xuICAgIHRoaXMucmVhbERpc3BsYXkgPSB0aGlzLnZpZXdlclxuICAgICAgPyB0aGlzLnZpZXdlclxuICAgICAgOiB0aGlzLm1hbmFnZXI/LmRpc3BsYXlUeXBlXG4gICAgICA/IHRoaXMubWFuYWdlci5kaXNwbGF5VHlwZVxuICAgICAgOiAndGV4dCc7XG4gICAgaWYgKHRoaXMucmVhbENob2ljZXMgJiYgdGhpcy5yZWFsQ2hvaWNlcy5sZW5ndGgpIHtcbiAgICAgIHRoaXMucmVhbERpc3BsYXkgPSAnY2hvaWNlJztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9nZXRSZWFsRWRpdG9yKCkge1xuICAgIHRoaXMucmVhbEVkaXRvciA9IHRoaXMuZWRpdG9yXG4gICAgICA/IHRoaXMuZWRpdG9yXG4gICAgICA6IHRoaXMubWFuYWdlcj8uZWRpdG9yVHlwZSB8fCAnaW5wdXQudGV4dCc7XG4gICAgaWYgKHRoaXMucmVhbENob2ljZXMgJiYgdGhpcy5yZWFsQ2hvaWNlcy5sZW5ndGgpIHtcbiAgICAgIHRoaXMucmVhbEVkaXRvciA9ICdzZWxlY3QnO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3NldEZvcm1Db250cm9sKCkge1xuICAgIGlmICghdGhpcy5mb3JtKSB7XG4gICAgICBjb25zdCBmZ2M6IHsgW2luZGV4OiBzdHJpbmddOiBVbnR5cGVkRm9ybUNvbnRyb2wgfSA9IHt9O1xuICAgICAgZmdjW3RoaXMuZmllbGRdID0gdGhpcy5tb2RlbC5GQyh0aGlzLmZpZWxkKTtcbiAgICAgIHRoaXMuZmcgPSBuZXcgVW50eXBlZEZvcm1Hcm91cChmZ2MpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmZnID0gdGhpcy5mb3JtO1xuICAgICAgdGhpcy5mZy5zZXRDb250cm9sKHRoaXMuZmllbGQsIHRoaXMubW9kZWwuRkModGhpcy5maWVsZCksIHtcbiAgICAgICAgZW1pdEV2ZW50OiBmYWxzZSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICBpZiAodGhpcy5tb2RlID09PSAnaW5saW5lJykge1xuICAgICAgdGhpcy5mZy52YWx1ZUNoYW5nZXMuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy51cGRhdGUoKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3NldEZvcm1Db250cm9sVmFsdWUoKSB7XG4gICAgc3dpdGNoICh0aGlzLnJlYWxFZGl0b3IpIHtcbiAgICAgIGNhc2UgJ2lucHV0LmRhdGV0aW1lJzpcbiAgICAgICAgY29uc3QgdmFsdWUgPSAodGhpcy5tb2RlbCBhcyBhbnkpW3RoaXMuZmllbGRdO1xuICAgICAgICBjb25zdCBub3cgPSBuZXcgRGF0ZSgpO1xuICAgICAgICBjb25zdCBsb2NhbG5vdyA9IG5ldyBEYXRlKFxuICAgICAgICAgIG5vdy5nZXRUaW1lKCkgLSBub3cuZ2V0VGltZXpvbmVPZmZzZXQoKSAqIDYwMDAwXG4gICAgICAgICk7XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgIHRoaXMuZmchLmNvbnRyb2xzW3RoaXMuZmllbGRdLnNldFZhbHVlKG51bGwsIHsgZW1pdEV2ZW50OiB0cnVlIH0pO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNvbnN0IHRpbWUgPSB2YWx1ZSA/IG5ldyBEYXRlKHZhbHVlKSA6IG5ldyBEYXRlKCk7XG4gICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gdGltZS5nZXRUaW1lem9uZU9mZnNldCgpO1xuICAgICAgICAgIGNvbnN0IGxvY2FsdGltZSA9IG5ldyBEYXRlKHRpbWUuZ2V0VGltZSgpIC0gb2Zmc2V0ICogNjAwMDApO1xuICAgICAgICAgIHRoaXMuZmchLmNvbnRyb2xzW3RoaXMuZmllbGRdLnNldFZhbHVlKFxuICAgICAgICAgICAgbG9jYWx0aW1lLnRvSVNPU3RyaW5nKCkuc3Vic3RyaW5nKDAsIDE2KSxcbiAgICAgICAgICAgIHsgZW1pdEV2ZW50OiB0cnVlIH1cbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucmVhbERlZmF1bHQgPVxuICAgICAgICAgIHRoaXMuZGVmYXVsdCB8fCB0aGlzLm1hbmFnZXI/LnJlcXVpcmVkXG4gICAgICAgICAgICA/IGxvY2Fsbm93LnRvSVNPU3RyaW5nKCkuc3Vic3RyaW5nKDAsIDE2KVxuICAgICAgICAgICAgOiBudWxsO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2lucHV0LmRhdGUnOlxuICAgICAgICBjb25zdCBkdCA9IHRoaXMubW9kZWwudG9Kc29uKFt0aGlzLmZpZWxkXSlbdGhpcy5maWVsZF07XG4gICAgICAgIHRoaXMuZmchLmNvbnRyb2xzW3RoaXMuZmllbGRdLnNldFZhbHVlKGR0KTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdpbnB1dC5kZWNpbWFsJzpcbiAgICAgICAgdGhpcy5mZyEuY29udHJvbHNbdGhpcy5maWVsZF0uc2V0VmFsdWUoXG4gICAgICAgICAgKHRoaXMubW9kZWwgYXMgYW55KVt0aGlzLmZpZWxkXSAvXG4gICAgICAgICAgICAoKHRoaXMubWFuYWdlciBhcyB1bmtub3duIGFzIERlY2ltYWxGaWVsZE1hbmFnZXIpLmZhY3RvciB8fCAxKVxuICAgICAgICApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3NldEVkaXRvckNsYXNzZXMoKSB7XG4gICAgLy8gRklYTUU6IHVzZSByZWFsRWRpdG9yQ2xhc3Nlc1xuICAgIGlmICghdGhpcy5pbnB1dENsYXNzZXMpIHtcbiAgICAgIHRoaXMuaW5wdXRDbGFzc2VzID1cbiAgICAgICAgdGhpcy5kY29uZi5kaXNwRWRpdC5pbnB1dENsYXNzZXNbdGhpcy5yZWFsRWRpdG9yXSB8fCAnJztcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9nZXREaXNwbGF5VmFsdWUoKSB7XG4gICAgY29uc3QgdmFsdWUgPSAodGhpcy5tb2RlbCBhcyBhbnkpW3RoaXMuZmllbGRdO1xuICAgIHRoaXMuZGlzcFZhbHVlID0gdmFsdWU7XG4gICAgaWYgKHRoaXMucmVhbENob2ljZXMpIHtcbiAgICAgIGZvciAoY29uc3QgYyBvZiB0aGlzLnJlYWxDaG9pY2VzKSB7XG4gICAgICAgIGlmIChjID09PSB2YWx1ZSkge1xuICAgICAgICAgIHRoaXMudHh0VmFsdWUgPSBjIGFzIGFueTtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gZWxzZSBpZiAoYy52YWx1ZSAmJiBjLnZhbHVlID09PSB2YWx1ZSkge1xuICAgICAgICAgIHRoaXMudHh0VmFsdWUgPSBjLmRlc2M7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIC8vIFNldCBkaXNwbGF5IHRleHQgZGVwZW5kaW5nIG9uIHZhbHVlIGFuZCByZWFsRGlzcGxheSB2YWx1ZVxuICAgIGlmICh2YWx1ZSA9PT0gdHJ1ZSkge1xuICAgICAgdGhpcy50eHRWYWx1ZSA9ICdPVUknO1xuICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IGZhbHNlKSB7XG4gICAgICB0aGlzLnR4dFZhbHVlID0gJ05PTic7XG4gICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkIHx8IHZhbHVlID09PSBudWxsKSB7XG4gICAgICB0aGlzLnR4dFZhbHVlID0gJ25vbiBkw6lmaW5pJztcbiAgICB9IGVsc2Uge1xuICAgICAgc3dpdGNoICh0aGlzLnJlYWxEaXNwbGF5KSB7XG4gICAgICAgIGNhc2UgJ2ZrZGV0YWlscyc6XG4gICAgICAgICAgY29uc3QgZGV0YWlscyA9ICh0aGlzLm1vZGVsIGFzIGFueSlbYCR7dGhpcy5maWVsZH1fZGV0YWlsc2BdIGFzIGFueTtcbiAgICAgICAgICB0aGlzLnR4dFZhbHVlID0gdGhpcy5fZGlzcGxheShkZXRhaWxzKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnbTJtZGV0YWlscyc6XG4gICAgICAgICAgY29uc3QgbTJtRGV0YWlscyA9XG4gICAgICAgICAgICB0aGlzLm0ybVZhbHVlcyB8fFxuICAgICAgICAgICAgKCh0aGlzLm1vZGVsIGFzIGFueSlbYCR7dGhpcy5maWVsZH1fZGV0YWlsc2BdIGFzIGFueVtdKTtcbiAgICAgICAgICB0aGlzLnR4dFZhbHVlcyA9IFtdO1xuICAgICAgICAgIGZvciAoY29uc3QgdiBvZiBtMm1EZXRhaWxzKSB7XG4gICAgICAgICAgICB0aGlzLnR4dFZhbHVlcy5wdXNoKHRoaXMuX2Rpc3BsYXkodikpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnZGVjaW1hbCc6XG4gICAgICAgICAgdGhpcy50eHRWYWx1ZSA9IGAke1xuICAgICAgICAgICAgdmFsdWUgL1xuICAgICAgICAgICAgKCh0aGlzLm1hbmFnZXIgYXMgdW5rbm93biBhcyBEZWNpbWFsRmllbGRNYW5hZ2VyKS5mYWN0b3IgfHwgMSlcbiAgICAgICAgICB9YDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICB0aGlzLnR4dFZhbHVlID0gYCR7dmFsdWV9YDtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9zZXREaXNwbGF5Q2xhc3NlcygpIHt9XG59XG4iLCJcbjxuZy10ZW1wbGF0ZSAjdGl0bGVUcGw+XG4gIDxuZy1jb250ZW50PjwvbmctY29udGVudD5cbjwvbmctdGVtcGxhdGU+XG48bmctdGVtcGxhdGUgI2Rpc3BUcGw+XG4gIDxuZy1jb250YWluZXIgW25nU3dpdGNoXT1cInJlYWxEaXNwbGF5XCI+PHNwYW4gY2xhc3M9XCJlZGl0YWJsZSBkaXNwLXRleHRcIiAqbmdTd2l0Y2hDYXNlPVwiJ3RleHQnXCIgKGNsaWNrKT1cImVuYWJsZUVkaXRNb2RlKClcIj57e3R4dFZhbHVlfX08L3NwYW4+PHNwYW4gY2xhc3M9XCJlZGl0YWJsZSBkaXNwLWNob2ljZVwiICpuZ1N3aXRjaENhc2U9XCInY2hvaWNlJ1wiIChjbGljayk9XCJlbmFibGVFZGl0TW9kZSgpXCI+e3t0eHRWYWx1ZX19PC9zcGFuPjxzcGFuIGNsYXNzPVwiZWRpdGFibGUgZGlzcC1kZWNpbWFsXCIgKm5nU3dpdGNoQ2FzZT1cIidkZWNpbWFsJ1wiIChjbGljayk9XCJlbmFibGVFZGl0TW9kZSgpXCI+e3t0eHRWYWx1ZX19PC9zcGFuPjxzcGFuIGNsYXNzPVwiZWRpdGFibGUgZGlzcC1ib29sZWFuXCIgKm5nU3dpdGNoQ2FzZT1cIidib29sZWFuJ1wiIChjbGljayk9XCJlbmFibGVFZGl0TW9kZSgpXCI+e3t0eHRWYWx1ZX19PC9zcGFuPjxzcGFuIGNsYXNzPVwiZWRpdGFibGUgZGlzcC1ma2RldGFpbHNcIiAqbmdTd2l0Y2hDYXNlPVwiJ2ZrZGV0YWlscydcIiAoY2xpY2spPVwiZW5hYmxlRWRpdE1vZGUoKVwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZraXRlbVwiPnt7dHh0VmFsdWV9fTwvZGl2Pjwvc3Bhbj48c3BhbiBjbGFzcz1cImVkaXRhYmxlIGRpc3AtbTJtZGV0YWlsc1wiICpuZ1N3aXRjaENhc2U9XCInbTJtZGV0YWlscydcIiAoY2xpY2spPVwiZW5hYmxlRWRpdE1vZGUoKVwiPlxuICAgICAgPGRpdiBjbGFzcz1cIm0ybWl0ZW1cIiAqbmdGb3I9XCJsZXQgdiBvZiB0eHRWYWx1ZXNcIj57e3Z9fTwvZGl2Pjwvc3Bhbj48c3BhbiBjbGFzcz1cImVkaXRhYmxlIGRpc3AtZGF0ZXRpbWVcIiAqbmdTd2l0Y2hDYXNlPVwiJ2RhdGV0aW1lJ1wiIChjbGljayk9XCJlbmFibGVFZGl0TW9kZSgpXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZGlzcFZhbHVlXCI+e3t0eHRWYWx1ZXxkYXRlOidzaG9ydCd9fTwvbmctY29udGFpbmVyPlxuICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFkaXNwVmFsdWVcIj57e3R4dFZhbHVlfX08L25nLWNvbnRhaW5lcj48L3NwYW4+PHNwYW4gY2xhc3M9XCJlZGl0YWJsZSBkaXNwLWRhdGV0aW1lXCIgKm5nU3dpdGNoQ2FzZT1cIidkYXRlJ1wiIChjbGljayk9XCJlbmFibGVFZGl0TW9kZSgpXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZGlzcFZhbHVlXCI+e3t0eHRWYWx1ZXxkYXRlOidzaG9ydERhdGUnfX08L25nLWNvbnRhaW5lcj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCIhZGlzcFZhbHVlXCI+e3t0eHRWYWx1ZX19PC9uZy1jb250YWluZXI+PC9zcGFuPlxuICAgIDwhLS1zcGFuLmVkaXRhYmxlLmRpc3AtcXVpbGwoKm5nU3dpdGNoQ2FzZT1cIidxdWlsbCdcIiwgKGNsaWNrKT1cImVuYWJsZUVkaXRNb2RlKClcIiktLT5cbiAgICA8IS0tICBxdWlsbC12aWV3LWh0bWwoW2NvbnRlbnRdPVwidHh0VmFsdWV8fCcnXCIpLS0+XG4gIDwvbmctY29udGFpbmVyPlxuPC9uZy10ZW1wbGF0ZT5cbjxuZy10ZW1wbGF0ZSAjZWRpdFRwbCBsZXQtZm9ybT1cImZvcm1cIj5cbiAgPG5nLWNvbnRhaW5lciBbbmdTd2l0Y2hdPVwicmVhbEVkaXRvclwiPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidpbnB1dC50ZXh0J1wiPlxuICAgICAgPGlucHV0IHR5cGU9XCJ0ZXh0XCIgW2Zvcm1Db250cm9sXT1cImZvcm0uZ2V0KGZpZWxkKVwiIFtuZ0NsYXNzXT1cImlucHV0Q2xhc3Nlc1wiIChrZXl1cC5lc2NhcGUpPVwidW5zZXRFZGl0KClcIiBbcGxhY2Vob2xkZXJdPVwicmVhbFBsYWNlaG9sZGVyXCI+XG4gICAgICA8ZGl2IGNsYXNzPVwiZm9ybS10ZXh0XCIgKm5nSWY9XCJyZWFsSGVscFwiPnt7cmVhbEhlbHB9fTxzcGFuIGNsYXNzPVwibXMtMVwiICpuZ0lmPVwicmVxdWlyZWRcIj4ocmVxdWlzKTwvc3Bhbj48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ21pbmxlbmd0aCddXCI+VHJvcCBjb3VydCA6IHt7JGFueShtYW5hZ2VyKS5taW5MZW5ndGh9fSBjYXJhY3TDqHJlcyBtaW5pbXVtLi4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydtYXhsZW5ndGgnXVwiPlRyb3AgbG9uZyA6IHt7JGFueShtYW5hZ2VyKS5tYXhMZW5ndGh9fSBjYXJhY3TDqHJlcyBtYXhpbXVtLi4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydwYXR0ZXJuJ11cIj5Gb3JtYXQgaW52YWxpZGUuLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ3JlcXVpcmVkJ11cIj5DZSBjaGFtcCBlc3QgcmVxdWlzLi4uPC9kaXY+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiJ2lucHV0LmVtYWlsJ1wiPlxuICAgICAgPGlucHV0IHR5cGU9XCJlbWFpbFwiIFtmb3JtQ29udHJvbF09XCJmb3JtLmdldChmaWVsZClcIiBbbmdDbGFzc109XCJpbnB1dENsYXNzZXNcIiAoa2V5dXAuZXNjYXBlKT1cInVuc2V0RWRpdCgpXCIgW3BsYWNlaG9sZGVyXT1cInJlYWxQbGFjZWhvbGRlclwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tdGV4dFwiICpuZ0lmPVwicmVhbEhlbHBcIj57e3JlYWxIZWxwfX08c3BhbiBjbGFzcz1cIm1zLTFcIiAqbmdJZj1cInJlcXVpcmVkXCI+KHJlcXVpcyk8L3NwYW4+PC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydtaW5sZW5ndGgnXVwiPlRyb3AgY291cnQgOiB7eyRhbnkobWFuYWdlcikubWluTGVuZ3RofX0gY2FyYWN0w6hyZXMgbWluaW11bS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWF4bGVuZ3RoJ11cIj5Ucm9wIGxvbmcgOiB7eyRhbnkobWFuYWdlcikubWF4TGVuZ3RofX0gY2FyYWN0w6hyZXMgbWF4aW11bS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsncGF0dGVybiddXCI+Rm9ybWF0IGludmFsaWRlLi4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydlbWFpbCddXCI+Rm9ybWF0IGQnZW1haWwgaW52YWxpZGUuLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ3JlcXVpcmVkJ11cIj5DZSBjaGFtcCBlc3QgcmVxdWlzLi4uPC9kaXY+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiJ2lucHV0LnBhc3N3b3JkJ1wiPlxuICAgICAgPGlucHV0IHR5cGU9XCJwYXNzd29yZFwiIFtmb3JtQ29udHJvbF09XCJmb3JtLmdldChmaWVsZClcIiBbbmdDbGFzc109XCJpbnB1dENsYXNzZXNcIiAoa2V5dXAuZXNjYXBlKT1cInVuc2V0RWRpdCgpXCIgW3BsYWNlaG9sZGVyXT1cInJlYWxQbGFjZWhvbGRlclwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tdGV4dFwiICpuZ0lmPVwicmVhbEhlbHBcIj57e3JlYWxIZWxwfX08c3BhbiBjbGFzcz1cIm1zLTFcIiAqbmdJZj1cInJlcXVpcmVkXCI+KHJlcXVpcyk8L3NwYW4+PC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydtaW5sZW5ndGgnXVwiPlRyb3AgY291cnQgOiB7eyRhbnkobWFuYWdlcikubWluTGVuZ3RofX0gY2FyYWN0w6hyZXMgbWluaW11bS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWF4bGVuZ3RoJ11cIj5Ucm9wIGxvbmcgOiB7eyRhbnkobWFuYWdlcikubWF4TGVuZ3RofX0gY2FyYWN0w6hyZXMgbWF4aW11bS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsncGF0dGVybiddXCI+Rm9ybWF0IGludmFsaWRlLi4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydyZXF1aXJlZCddXCI+Q2UgY2hhbXAgZXN0IHJlcXVpcy4uLjwvZGl2PlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidpbnB1dC5kYXRldGltZSdcIj5cbiAgICAgIDxpbnB1dCB0eXBlPVwiZGF0ZXRpbWUtbG9jYWxcIiBbZm9ybUNvbnRyb2xdPVwiZm9ybS5nZXQoZmllbGQpXCIgW25nQ2xhc3NdPVwiaW5wdXRDbGFzc2VzXCIgKGtleXVwLmVzY2FwZSk9XCJ1bnNldEVkaXQoKVwiIChrZXl1cC5lbnRlcik9XCJ1cGRhdGUoKVwiPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tdGV4dFwiPnt7cmVhbEhlbHB9fTwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsncmVxdWlyZWQnXVwiPkNlIGNoYW1wIGVzdCByZXF1aXMuLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ21pbkRhdGUnXVwiPkRvaXQgw6p0cmUgcG9zdMOpcmlldXIgw6AgIHt7JGFueShtYW5hZ2VyKS5taW58ZGF0ZTonc2hvcnQnfX0uLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ21heERhdGUnXVwiPkRvaXQgw6p0cmUgYW50w6lyaWV1ciDDoCAge3skYW55KG1hbmFnZXIpLm1heHxkYXRlOidzaG9ydCd9fS4uLjwvZGl2PlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidpbnB1dC5kYXRlJ1wiPlxuICAgICAgPGlucHV0IHR5cGU9XCJkYXRlXCIgW2Zvcm1Db250cm9sXT1cImZvcm0uZ2V0KGZpZWxkKVwiIFtuZ0NsYXNzXT1cImlucHV0Q2xhc3Nlc1wiIChrZXl1cC5lc2NhcGUpPVwidW5zZXRFZGl0KClcIiAoa2V5dXAuZW50ZXIpPVwidXBkYXRlKClcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXRleHRcIj57e3JlYWxIZWxwfX08L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ3JlcXVpcmVkJ11cIj5DZSBjaGFtcCBlc3QgcmVxdWlzLi4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydtaW5EYXRlJ11cIj5Eb2l0IMOqdHJlIHBvc3TDqXJpZXVyIMOgICB7eyRhbnkobWFuYWdlcikubWlufGRhdGU6J3Nob3J0J319Li4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydtYXhEYXRlJ11cIj5Eb2l0IMOqdHJlIGFudMOpcmlldXIgw6AgIHt7JGFueShtYW5hZ2VyKS5tYXh8ZGF0ZTonc2hvcnQnfX0uLi48L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCInaW5wdXQubnVtYmVyJ1wiPlxuICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIiBbZm9ybUNvbnRyb2xdPVwiZm9ybS5nZXQoZmllbGQpXCIgW25nQ2xhc3NdPVwiaW5wdXRDbGFzc2VzXCIgKGtleXVwLmVzY2FwZSk9XCJ1bnNldEVkaXQoKVwiIFtwbGFjZWhvbGRlcl09XCJyZWFsUGxhY2Vob2xkZXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXRleHRcIiAqbmdJZj1cInJlYWxIZWxwXCI+e3tyZWFsSGVscH19PHNwYW4gY2xhc3M9XCJtcy0xXCIgKm5nSWY9XCJyZXF1aXJlZFwiPihyZXF1aXMpPC9zcGFuPjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWluJ11cIj5Ucm9wIHBldGl0IDogbWluaW11bSB7eyRhbnkobWFuYWdlcikubWlufX0uLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ21heCddXCI+VHJvcCBncmFuZCA6IG1heGltdW0ge3skYW55KG1hbmFnZXIpLm1heH19Li4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydyZXF1aXJlZCddXCI+Q2UgY2hhbXAgZXN0IHJlcXVpcy4uLjwvZGl2PlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidpbnB1dC5kZWNpbWFsJ1wiPlxuICAgICAgPGlucHV0IHR5cGU9XCJudW1iZXJcIiBbZm9ybUNvbnRyb2xdPVwiZm9ybS5nZXQoZmllbGQpXCIgW25nQ2xhc3NdPVwiaW5wdXRDbGFzc2VzXCIgKGtleXVwLmVzY2FwZSk9XCJ1bnNldEVkaXQoKVwiIFtwbGFjZWhvbGRlcl09XCJyZWFsUGxhY2Vob2xkZXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXRleHRcIiAqbmdJZj1cInJlYWxIZWxwXCI+e3tyZWFsSGVscH19PHNwYW4gY2xhc3M9XCJtcy0xXCIgKm5nSWY9XCJyZXF1aXJlZFwiPihyZXF1aXMpPC9zcGFuPjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWluJ11cIj5Ucm9wIHBldGl0IDogbWluaW11bSB7eyRhbnkobWFuYWdlcikubWlufX0uLi48L2Rpdj5cbiAgICAgIDxkaXYgY2xhc3M9XCJpbnZhbGlkLWZlZWRiYWNrIG10LTBcIiBbY2xhc3MuZC1ibG9ja109XCJmb3JtICZhbXA7JmFtcDsgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICZhbXA7JmFtcDsgZm9ybS5jb250cm9sc1tmaWVsZF0uZXJyb3JzPy5bJ21heCddXCI+VHJvcCBncmFuZCA6IG1heGltdW0ge3skYW55KG1hbmFnZXIpLm1heH19Li4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydyZXF1aXJlZCddXCI+Q2UgY2hhbXAgZXN0IHJlcXVpcy4uLjwvZGl2PlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidpbnB1dC5jaGVja2JveCdcIj5cbiAgICAgIDxpbnB1dCBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIiB0eXBlPVwiY2hlY2tib3hcIiBbZm9ybUNvbnRyb2xdPVwiZm9ybS5nZXQoZmllbGQpXCIgKGtleXVwLmVzY2FwZSk9XCJ1bnNldEVkaXQoKVwiIChjaGFuZ2UpPVwidXBkYXRlKClcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJmb3JtLXRleHRcIj57e3JlYWxIZWxwfX08L2Rpdj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgICA8bmctY29udGFpbmVyICpuZ1N3aXRjaENhc2U9XCIndGV4dGFyZWEnXCI+XG4gICAgICA8dGV4dGFyZWEgW2Zvcm1Db250cm9sXT1cImZvcm0uZ2V0KGZpZWxkKVwiIChrZXl1cC5lc2NhcGUpPVwidW5zZXRFZGl0KClcIiBbbmdDbGFzc109XCJpbnB1dENsYXNzZXNcIiAoa2V5dXAuY29udHJvbC5lbnRlcik9XCJ1cGRhdGUoKVwiIFtwbGFjZWhvbGRlcl09XCJyZWFsUGxhY2Vob2xkZXJcIj48L3RleHRhcmVhPlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tdGV4dFwiICpuZ0lmPVwicmVhbEhlbHBcIj57e3JlYWxIZWxwfX08c3BhbiBjbGFzcz1cIm1zLTFcIiAqbmdJZj1cInJlcXVpcmVkXCI+KHJlcXVpcyk8L3NwYW4+PC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydtaW5sZW5ndGgnXVwiPlRyb3AgY291cnQgOiB7eyRhbnkobWFuYWdlcikubWluTGVuZ3RofX0gY2FyYWN0w6hyZXMgbWluaW11bS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWF4bGVuZ3RoJ11cIj5Ucm9wIGxvbmcgOiB7eyRhbnkobWFuYWdlcikubWF4TGVuZ3RofX0gY2FyYWN0w6hyZXMgbWF4aW11bS4uLjwvZGl2PlxuICAgICAgPGRpdiBjbGFzcz1cImludmFsaWQtZmVlZGJhY2sgbXQtMFwiIFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJmFtcDsmYW1wOyAhZm9ybS5jb250cm9sc1tmaWVsZF0ucHJpc3RpbmUgJmFtcDsmYW1wOyBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsncGF0dGVybiddXCI+Rm9ybWF0IGludmFsaWRlLi4uPC9kaXY+XG4gICAgICA8ZGl2IGNsYXNzPVwiaW52YWxpZC1mZWVkYmFjayBtdC0wXCIgW2NsYXNzLmQtYmxvY2tdPVwiZm9ybSAmYW1wOyZhbXA7ICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmYW1wOyZhbXA7IGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydyZXF1aXJlZCddXCI+Q2UgY2hhbXAgZXN0IHJlcXVpcy4uLjwvZGl2PlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDwhLS1uZy1jb250YWluZXIoKm5nU3dpdGNoQ2FzZT1cIidxdWlsbCdcIiktLT5cbiAgICA8IS0tICBxdWlsbC1lZGl0b3IoW2Zvcm1Db250cm9sXT1cImZvcm0uZ2V0KGZpZWxkKVwiKS0tPlxuICAgIDwhLS0gIC5mb3JtLXRleHQoKm5nSWY9XCJyZWFsSGVscFwiKSB7e3JlYWxIZWxwfX0tLT5cbiAgICA8IS0tICAgIHNwYW4ubXMtMSgqbmdJZj1cInJlcXVpcmVkXCIpIChyZXF1aXMpLS0+XG4gICAgPCEtLSAgLmludmFsaWQtZmVlZGJhY2subXQtMChbY2xhc3MuZC1ibG9ja109XCJmb3JtICYmICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmJiBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWlubGVuZ3RoJ11cIikgVHJvcCBjb3VydCA6IHt7JGFueShtYW5hZ2VyKS5taW5MZW5ndGh9fSBjYXJhY3TDqHJlcyBtaW5pbXVtLi4uLS0+XG4gICAgPCEtLSAgLmludmFsaWQtZmVlZGJhY2subXQtMChbY2xhc3MuZC1ibG9ja109XCJmb3JtICYmICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmJiBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsnbWF4bGVuZ3RoJ11cIikgVHJvcCBsb25nIDoge3skYW55KG1hbmFnZXIpLm1heExlbmd0aH19IGNhcmFjdMOocmVzIG1heGltdW0uLi4tLT5cbiAgICA8IS0tICAuaW52YWxpZC1mZWVkYmFjay5tdC0wKFtjbGFzcy5kLWJsb2NrXT1cImZvcm0gJiYgIWZvcm0uY29udHJvbHNbZmllbGRdLnByaXN0aW5lICYmIGZvcm0uY29udHJvbHNbZmllbGRdLmVycm9ycz8uWydwYXR0ZXJuJ11cIikgRm9ybWF0IGludmFsaWRlLi4uLS0+XG4gICAgPCEtLSAgLmludmFsaWQtZmVlZGJhY2subXQtMChbY2xhc3MuZC1ibG9ja109XCJmb3JtICYmICFmb3JtLmNvbnRyb2xzW2ZpZWxkXS5wcmlzdGluZSAmJiBmb3JtLmNvbnRyb2xzW2ZpZWxkXS5lcnJvcnM/LlsncmVxdWlyZWQnXVwiKSBDZSBjaGFtcCBlc3QgcmVxdWlzLi4uLS0+XG4gICAgPCEtLSAgYnV0dG9uKFtuZ0NsYXNzXT1cImlucHV0Q2xhc3Nlc1wiKSBFbnJlZ2lzdHJlci0tPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidma3NlbGVjdCdcIj5cbiAgICAgIDxkYXRhLWZrc2VsZWN0IFtjb2xsZWN0aW9uXT1cImNvbGxlY3Rpb25cIiBbZmlsdGVyXT1cImZpbHRlclwiIChzZWxlY3RlZCk9XCJzZWxlY3RlZFJlZkl0ZW0oJGV2ZW50KVwiIFtwbGFjZWhvbGRlcl09XCJwbGFjZWhvbGRlclwiIChjYW5jZWxsZWQpPVwidW5zZXRFZGl0KClcIiAoY2xlYXJlZCk9XCJzZWxlY3RlZFJlZkl0ZW0obnVsbClcIj48L2RhdGEtZmtzZWxlY3Q+XG4gICAgPC9uZy1jb250YWluZXI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiJ20ybXNlbGVjdCdcIj5cbiAgICAgIDxkYXRhLW0ybXNlbGVjdCBbY29sbGVjdGlvbl09XCJjb2xsZWN0aW9uXCIgW2ZpbHRlcl09XCJmaWx0ZXJcIiAoY2hhbmdlZCk9XCJ1cGRhdGUoKVwiIFtmb3JtQ29udHJvbF09XCJmb3JtLmdldChmaWVsZClcIiAoZGV0YWlsc0NoYW5nZWQpPVwib25NMk1WYWx1ZXNDaGFuZ2VzKCRldmVudClcIiBbbW9kZWxdPVwibW9kZWxcIiBbZmllbGRdPVwiZmllbGRcIiBbcGxhY2Vob2xkZXJdPVwicGxhY2Vob2xkZXJcIj48L2RhdGEtbTJtc2VsZWN0PlxuICAgIDwvbmctY29udGFpbmVyPlxuICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidzZWxlY3QnXCI+XG4gICAgICA8c2VsZWN0IFtmb3JtQ29udHJvbF09XCJmb3JtLmdldChmaWVsZClcIiAoa2V5dXAuZXNjYXBlKT1cInVuc2V0RWRpdCgpXCIgKGNoYW5nZSk9XCJ1cGRhdGUoKVwiIFtuZ0NsYXNzXT1cImlucHV0Q2xhc3Nlc1wiPlxuICAgICAgICA8b3B0aW9uICpuZ0Zvcj1cImxldCBjIG9mIHJlYWxDaG9pY2VzXCIgW25nVmFsdWVdPVwiYy52YWx1ZSA/IGMudmFsdWUgOiBjXCI+e3tjLmRlc2MgPyBjLmRlc2MgOiBjfX08L29wdGlvbj5cbiAgICAgIDwvc2VsZWN0PlxuICAgICAgPGRpdiBjbGFzcz1cImZvcm0tdGV4dFwiPnt7cmVhbEhlbHB9fTwvZGl2PlxuICAgIDwvbmctY29udGFpbmVyPlxuICA8L25nLWNvbnRhaW5lcj5cbjwvbmctdGVtcGxhdGU+XG48IS0tIERpc3AvZWRpdCB0b2dnbGVyLS0+XG48bmctdGVtcGxhdGUgI2Rpc3BlZGl0VHBsPlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWVkaXRcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiZGlzcFRwbFwiPjwvbmctY29udGFpbmVyPlxuICA8L25nLWNvbnRhaW5lcj5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImVkaXRcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwiZmdcIj5cbiAgICAgIDxmb3JtIFtmb3JtR3JvdXBdPVwiZmdcIiAoc3VibWl0KT1cInVwZGF0ZSgpXCI+XG4gICAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJlZGl0VHBsOyBjb250ZXh0OiB7Zm9ybTogZmd9XCI+PC9uZy1jb250YWluZXI+XG4gICAgICA8L2Zvcm0+XG4gICAgPC9uZy1jb250YWluZXI+XG4gIDwvbmctY29udGFpbmVyPlxuPC9uZy10ZW1wbGF0ZT5cbjwhLS0gRGlzcEVkaXQgbm9mb3JtLS0+XG48bmctdGVtcGxhdGUgI2Rpc3BlZGl0Rm9ybVRwbD5cbiAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIiFlZGl0XCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImRpc3BUcGxcIj48L25nLWNvbnRhaW5lcj5cbiAgPC9uZy1jb250YWluZXI+XG4gIDxuZy1jb250YWluZXIgKm5nSWY9XCJlZGl0XCI+XG4gICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cImZvcm1cIj5cbiAgICAgIDxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJlZGl0VHBsOyBjb250ZXh0OiB7Zm9ybTogZm9ybX1cIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L25nLWNvbnRhaW5lcj5cbiAgPC9uZy1jb250YWluZXI+XG48L25nLXRlbXBsYXRlPlxuPCEtLSBEZCBkaXNwbGF5LS0+XG48bmctY29udGFpbmVyICpuZ0lmPVwibW9kZT09PSdkZCdcIj5cbiAgPGR0IFtjbGFzcy5yZXF1aXJlZF09XCJyZXF1aXJlZFwiICpuZ0lmPVwiIWhpZGVMYWJlbFwiPjxzcGFuIGNsYXNzPVwiZWRpdGFibGVcIiAoY2xpY2spPVwidG9nZ2xlRWRpdCgpXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGl0bGVUcGxcIj48L25nLWNvbnRhaW5lcj48L3NwYW4+PHNwYW4gY2xhc3M9XCJwb2ludGVyIGZsb2F0LWVuZFwiIChjbGljayk9XCJzZXREZWZhdWx0KClcIiAqbmdJZj1cInJlYWxEZWZhdWx0IT09IHVuZGVmaW5lZCAmYW1wOyZhbXA7IGVkaXRcIj48aSBjbGFzcz1cImJpIGJpLXRyYXNoIG1zLTJcIj48L2k+PC9zcGFuPjwvZHQ+XG4gIDxkZCBbY2xhc3MubWItMF09XCJoaWRlTGFiZWxcIj5cbiAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiZGlzcGVkaXRUcGxcIj48L25nLWNvbnRhaW5lcj5cbiAgPC9kZD5cbjwvbmctY29udGFpbmVyPlxuPCEtLSBJbmxpbmUgZGlzcGxheS0tPlxuPG5nLWNvbnRhaW5lciAqbmdJZj1cIm1vZGU9PT0naW5saW5lJ1wiPlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWhpZGVMYWJlbFwiPjxzcGFuIGNsYXNzPVwicG9pbnRlciBmbG9hdC1lbmRcIiAoY2xpY2spPVwic2V0RGVmYXVsdCgpXCIgKm5nSWY9XCJyZWFsRGVmYXVsdCE9PSB1bmRlZmluZWQgJmFtcDsmYW1wOyBlZGl0XCI+PGkgY2xhc3M9XCJiaSBiaS10cmFzaCBtcy0yXCI+PC9pPjwvc3Bhbj5cbiAgICA8bGFiZWwgW2NsYXNzLnJlcXVpcmVkXT1cInJlcXVpcmVkXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGl0bGVUcGxcIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L2xhYmVsPlxuICA8L25nLWNvbnRhaW5lcj5cbiAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImRpc3BlZGl0VHBsXCI+PC9uZy1jb250YWluZXI+XG48L25nLWNvbnRhaW5lcj5cbjwhLS0gRm9ybSBkaXNwbGF5LS0+XG48bmctY29udGFpbmVyICpuZ0lmPVwibW9kZT09PSdmb3JtJ1wiPlxuICA8bmctY29udGFpbmVyICpuZ0lmPVwiIWhpZGVMYWJlbFwiPjxzcGFuIGNsYXNzPVwicG9pbnRlciBmbG9hdC1lbmRcIiAoY2xpY2spPVwic2V0RGVmYXVsdCgpXCIgKm5nSWY9XCJyZWFsRGVmYXVsdCE9PSB1bmRlZmluZWQgJmFtcDsmYW1wOyBlZGl0XCI+PGkgY2xhc3M9XCJiaSBiaS10cmFzaCBtcy0yXCI+PC9pPjwvc3Bhbj5cbiAgICA8bGFiZWwgW2NsYXNzLnJlcXVpcmVkXT1cInJlcXVpcmVkXCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwidGl0bGVUcGxcIj48L25nLWNvbnRhaW5lcj5cbiAgICA8L2xhYmVsPlxuICA8L25nLWNvbnRhaW5lcj5cbiAgPG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImRpc3BlZGl0Rm9ybVRwbFwiPjwvbmctY29udGFpbmVyPlxuPC9uZy1jb250YWluZXI+Il19