tin-spa 2.0.0 → 2.1.1

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 (242) hide show
  1. package/README.md +2 -2
  2. package/esm2020/lib/classes/Classes.mjs +214 -0
  3. package/esm2020/lib/classes/TinCore.mjs +213 -0
  4. package/esm2020/lib/components/activity/activity.component.mjs +24 -0
  5. package/esm2020/lib/components/attach/attach.component.mjs +105 -0
  6. package/esm2020/lib/components/change-password/change-password.component.mjs +92 -0
  7. package/esm2020/lib/components/check/check.component.mjs +56 -0
  8. package/esm2020/lib/components/chips/chips.component.mjs +58 -0
  9. package/esm2020/lib/components/create-account/create-account.component.mjs +72 -0
  10. package/esm2020/lib/components/date/date.component.mjs +82 -0
  11. package/esm2020/lib/components/datetime/datetime.component.mjs +39 -0
  12. package/esm2020/lib/components/filter/filter.component.mjs +46 -0
  13. package/esm2020/lib/components/form/form.component.mjs +107 -0
  14. package/esm2020/lib/components/label/label.component.mjs +25 -0
  15. package/esm2020/lib/components/loader/loader.component.mjs +24 -0
  16. package/esm2020/lib/components/login/login.component.mjs +113 -0
  17. package/esm2020/lib/components/logs/logs.component.mjs +37 -0
  18. package/esm2020/lib/components/message/messageDialog.component.mjs +32 -0
  19. package/esm2020/lib/components/money/currency-input-mask.directive.mjs +185 -0
  20. package/esm2020/lib/components/money/currency-input-mask.module.mjs +28 -0
  21. package/esm2020/lib/components/money/money.component.mjs +108 -0
  22. package/esm2020/lib/components/nav-menu/nav-menu.component.mjs +49 -0
  23. package/esm2020/lib/components/number/number.component.mjs +102 -0
  24. package/esm2020/lib/components/option/option.component.mjs +59 -0
  25. package/esm2020/lib/components/profile/profile.component.mjs +93 -0
  26. package/esm2020/lib/components/recover-account/recover-account.component.mjs +46 -0
  27. package/esm2020/lib/components/roles/addRoleDialog.component.mjs +61 -0
  28. package/esm2020/lib/components/roles/roles.component.mjs +91 -0
  29. package/esm2020/lib/components/select/select.component.mjs +71 -0
  30. package/esm2020/lib/components/settings/settings.component.mjs +63 -0
  31. package/esm2020/lib/components/signup/signup.component.mjs +50 -0
  32. package/esm2020/lib/components/steps/steps.component.mjs +90 -0
  33. package/esm2020/lib/components/table/detailsDialog.component.mjs +137 -0
  34. package/esm2020/lib/components/table/table.component.mjs +350 -0
  35. package/esm2020/lib/components/text/text.component.mjs +166 -0
  36. package/esm2020/lib/components/tiles/tiles.component.mjs +41 -0
  37. package/esm2020/lib/components/tin-spa.component.mjs +19 -0
  38. package/esm2020/lib/components/users/users.component.mjs +119 -0
  39. package/esm2020/lib/modules/admin/admin-routing.module.mjs +29 -0
  40. package/esm2020/lib/modules/admin/admin.module.mjs +26 -0
  41. package/esm2020/lib/modules/index/index-routing.module.mjs +27 -0
  42. package/esm2020/lib/modules/index/index.module.mjs +26 -0
  43. package/esm2020/lib/modules/spa-admin.module.mjs +73 -0
  44. package/esm2020/lib/modules/spa-index.module.mjs +52 -0
  45. package/esm2020/lib/modules/spa-mat.module.mjs +67 -0
  46. package/esm2020/lib/modules/spa-user.module.mjs +49 -0
  47. package/esm2020/lib/modules/user/user-routing.module.mjs +23 -0
  48. package/esm2020/lib/modules/user/user.module.mjs +26 -0
  49. package/esm2020/lib/pipes/camelToWords.pipe.mjs +23 -0
  50. package/esm2020/lib/services/auth.service.mjs +142 -0
  51. package/esm2020/lib/services/data.service.mjs +125 -0
  52. package/esm2020/lib/services/export.service.mjs +16 -0
  53. package/esm2020/lib/services/http.service.mjs +79 -0
  54. package/esm2020/lib/services/loader-interceptor.service.mjs +77 -0
  55. package/esm2020/lib/services/loader.service.mjs +17 -0
  56. package/esm2020/lib/services/log.service.mjs +77 -0
  57. package/esm2020/lib/services/message.service.mjs +52 -0
  58. package/esm2020/lib/services/storage.service.mjs +34 -0
  59. package/esm2020/lib/services/tin-spa.service.mjs +14 -0
  60. package/esm2020/lib/tin-spa.module.mjs +114 -0
  61. package/esm2020/public-api.mjs +62 -0
  62. package/esm2020/tin-spa.mjs +5 -0
  63. package/fesm2015/tin-spa.mjs +4026 -0
  64. package/fesm2015/tin-spa.mjs.map +1 -0
  65. package/fesm2020/tin-spa.mjs +4008 -0
  66. package/fesm2020/tin-spa.mjs.map +1 -0
  67. package/index.d.ts +5 -0
  68. package/lib/classes/Classes.d.ts +69 -62
  69. package/lib/classes/TinCore.d.ts +6 -0
  70. package/lib/components/activity/activity.component.d.ts +3 -0
  71. package/lib/components/attach/attach.component.d.ts +4 -1
  72. package/lib/components/change-password/change-password.component.d.ts +3 -0
  73. package/lib/components/check/check.component.d.ts +3 -0
  74. package/lib/components/chips/chips.component.d.ts +3 -0
  75. package/lib/components/create-account/create-account.component.d.ts +3 -0
  76. package/lib/components/date/date.component.d.ts +19 -7
  77. package/lib/components/datetime/datetime.component.d.ts +3 -0
  78. package/lib/components/filter/filter.component.d.ts +4 -0
  79. package/lib/components/form/form.component.d.ts +23 -0
  80. package/lib/components/label/label.component.d.ts +3 -0
  81. package/lib/components/loader/loader.component.d.ts +3 -0
  82. package/lib/components/login/login.component.d.ts +6 -0
  83. package/lib/components/logs/logs.component.d.ts +3 -0
  84. package/lib/components/message/messageDialog.component.d.ts +3 -0
  85. package/lib/components/money/currency-input-mask.directive.d.ts +41 -0
  86. package/lib/components/money/currency-input-mask.module.d.ts +9 -0
  87. package/lib/components/money/money.component.d.ts +19 -3
  88. package/lib/components/nav-menu/nav-menu.component.d.ts +3 -0
  89. package/lib/components/number/number.component.d.ts +31 -0
  90. package/lib/components/option/option.component.d.ts +3 -0
  91. package/lib/components/profile/profile.component.d.ts +6 -2
  92. package/lib/components/recover-account/recover-account.component.d.ts +3 -0
  93. package/lib/components/roles/addRoleDialog.component.d.ts +3 -0
  94. package/lib/components/roles/roles.component.d.ts +3 -0
  95. package/lib/components/select/select.component.d.ts +5 -1
  96. package/lib/components/settings/settings.component.d.ts +3 -0
  97. package/lib/components/signup/signup.component.d.ts +3 -0
  98. package/lib/components/steps/steps.component.d.ts +3 -0
  99. package/lib/components/table/detailsDialog.component.d.ts +26 -0
  100. package/lib/components/table/table.component.d.ts +57 -17
  101. package/lib/components/text/text.component.d.ts +14 -10
  102. package/lib/components/tiles/tiles.component.d.ts +3 -0
  103. package/lib/components/tin-spa.component.d.ts +4 -4
  104. package/lib/components/users/users.component.d.ts +4 -0
  105. package/lib/modules/admin/admin-routing.module.d.ts +7 -0
  106. package/lib/modules/admin/admin.module.d.ts +9 -0
  107. package/lib/modules/index/index-routing.module.d.ts +7 -0
  108. package/lib/modules/index/index.module.d.ts +9 -0
  109. package/lib/modules/spa-admin.module.d.ts +13 -0
  110. package/lib/modules/spa-index.module.d.ts +10 -0
  111. package/lib/modules/spa-mat.module.d.ts +31 -0
  112. package/lib/modules/spa-user.module.d.ts +9 -0
  113. package/lib/modules/user/user-routing.module.d.ts +7 -0
  114. package/lib/modules/user/user.module.d.ts +9 -0
  115. package/lib/pipes/camelToWords.pipe.d.ts +7 -0
  116. package/lib/services/auth.service.d.ts +3 -0
  117. package/lib/services/data.service.d.ts +5 -1
  118. package/lib/services/export.service.d.ts +3 -4
  119. package/lib/services/http.service.d.ts +3 -0
  120. package/lib/services/loader-interceptor.service.d.ts +3 -0
  121. package/lib/services/loader.service.d.ts +3 -0
  122. package/lib/services/log.service.d.ts +3 -0
  123. package/lib/services/message.service.d.ts +3 -0
  124. package/lib/services/storage.service.d.ts +3 -0
  125. package/lib/services/tin-spa.service.d.ts +3 -0
  126. package/lib/tin-spa.module.d.ts +30 -0
  127. package/package.json +24 -23
  128. package/public-api.d.ts +7 -2
  129. package/bundles/tin-spa.umd.js +0 -3672
  130. package/bundles/tin-spa.umd.js.map +0 -1
  131. package/bundles/tin-spa.umd.min.js +0 -16
  132. package/bundles/tin-spa.umd.min.js.map +0 -1
  133. package/esm2015/lib/classes/Classes.js +0 -254
  134. package/esm2015/lib/classes/TinCore.js +0 -139
  135. package/esm2015/lib/components/activity/activity.component.js +0 -26
  136. package/esm2015/lib/components/attach/attach.component.js +0 -107
  137. package/esm2015/lib/components/change-password/change-password.component.js +0 -102
  138. package/esm2015/lib/components/check/check.component.js +0 -63
  139. package/esm2015/lib/components/chips/chips.component.js +0 -66
  140. package/esm2015/lib/components/create-account/create-account.component.js +0 -78
  141. package/esm2015/lib/components/date/date.component.js +0 -45
  142. package/esm2015/lib/components/datetime/datetime.component.js +0 -44
  143. package/esm2015/lib/components/filter/filter.component.js +0 -40
  144. package/esm2015/lib/components/label/label.component.js +0 -29
  145. package/esm2015/lib/components/loader/loader.component.js +0 -29
  146. package/esm2015/lib/components/login/login.component.js +0 -114
  147. package/esm2015/lib/components/logs/logs.component.js +0 -39
  148. package/esm2015/lib/components/message/messageDialog.component.js +0 -31
  149. package/esm2015/lib/components/money/money.component.js +0 -52
  150. package/esm2015/lib/components/nav-menu/nav-menu.component.js +0 -51
  151. package/esm2015/lib/components/option/option.component.js +0 -63
  152. package/esm2015/lib/components/profile/profile.component.js +0 -98
  153. package/esm2015/lib/components/recover-account/recover-account.component.js +0 -53
  154. package/esm2015/lib/components/roles/addRoleDialog.component.js +0 -61
  155. package/esm2015/lib/components/roles/roles.component.js +0 -94
  156. package/esm2015/lib/components/select/select.component.js +0 -77
  157. package/esm2015/lib/components/settings/settings.component.js +0 -63
  158. package/esm2015/lib/components/signup/signup.component.js +0 -57
  159. package/esm2015/lib/components/steps/steps.component.js +0 -93
  160. package/esm2015/lib/components/table/table.component.js +0 -107
  161. package/esm2015/lib/components/text/text.component.js +0 -165
  162. package/esm2015/lib/components/tiles/tiles.component.js +0 -41
  163. package/esm2015/lib/components/timeout/timeout.component.js +0 -90
  164. package/esm2015/lib/components/tin-spa.component.js +0 -19
  165. package/esm2015/lib/components/users/users.component.js +0 -120
  166. package/esm2015/lib/dnd.directive.js +0 -51
  167. package/esm2015/lib/modules/spa-admin.module.js +0 -50
  168. package/esm2015/lib/modules/spa-index.module.js +0 -35
  169. package/esm2015/lib/modules/spa-mat.module.js +0 -53
  170. package/esm2015/lib/modules/spa-user.module.js +0 -33
  171. package/esm2015/lib/services/auth.service.js +0 -155
  172. package/esm2015/lib/services/data.service.js +0 -115
  173. package/esm2015/lib/services/export.service.js +0 -29
  174. package/esm2015/lib/services/http.service.js +0 -84
  175. package/esm2015/lib/services/loader-interceptor.service.js +0 -83
  176. package/esm2015/lib/services/loader.service.js +0 -17
  177. package/esm2015/lib/services/log.service.js +0 -76
  178. package/esm2015/lib/services/message.service.js +0 -58
  179. package/esm2015/lib/services/storage.service.js +0 -42
  180. package/esm2015/lib/services/tin-spa.service.js +0 -14
  181. package/esm2015/lib/tin-spa.module.js +0 -91
  182. package/esm2015/public-api.js +0 -56
  183. package/esm2015/tin-spa.js +0 -8
  184. package/esm5/lib/classes/Classes.js +0 -313
  185. package/esm5/lib/classes/TinCore.js +0 -166
  186. package/esm5/lib/components/activity/activity.component.js +0 -27
  187. package/esm5/lib/components/attach/attach.component.js +0 -119
  188. package/esm5/lib/components/change-password/change-password.component.js +0 -104
  189. package/esm5/lib/components/check/check.component.js +0 -64
  190. package/esm5/lib/components/chips/chips.component.js +0 -68
  191. package/esm5/lib/components/create-account/create-account.component.js +0 -80
  192. package/esm5/lib/components/date/date.component.js +0 -46
  193. package/esm5/lib/components/datetime/datetime.component.js +0 -45
  194. package/esm5/lib/components/filter/filter.component.js +0 -41
  195. package/esm5/lib/components/label/label.component.js +0 -30
  196. package/esm5/lib/components/loader/loader.component.js +0 -31
  197. package/esm5/lib/components/login/login.component.js +0 -117
  198. package/esm5/lib/components/logs/logs.component.js +0 -41
  199. package/esm5/lib/components/message/messageDialog.component.js +0 -32
  200. package/esm5/lib/components/money/money.component.js +0 -53
  201. package/esm5/lib/components/nav-menu/nav-menu.component.js +0 -53
  202. package/esm5/lib/components/option/option.component.js +0 -64
  203. package/esm5/lib/components/profile/profile.component.js +0 -102
  204. package/esm5/lib/components/recover-account/recover-account.component.js +0 -55
  205. package/esm5/lib/components/roles/addRoleDialog.component.js +0 -63
  206. package/esm5/lib/components/roles/roles.component.js +0 -100
  207. package/esm5/lib/components/select/select.component.js +0 -79
  208. package/esm5/lib/components/settings/settings.component.js +0 -66
  209. package/esm5/lib/components/signup/signup.component.js +0 -59
  210. package/esm5/lib/components/steps/steps.component.js +0 -105
  211. package/esm5/lib/components/table/table.component.js +0 -109
  212. package/esm5/lib/components/text/text.component.js +0 -168
  213. package/esm5/lib/components/tiles/tiles.component.js +0 -42
  214. package/esm5/lib/components/timeout/timeout.component.js +0 -92
  215. package/esm5/lib/components/tin-spa.component.js +0 -17
  216. package/esm5/lib/components/users/users.component.js +0 -126
  217. package/esm5/lib/dnd.directive.js +0 -52
  218. package/esm5/lib/modules/spa-admin.module.js +0 -53
  219. package/esm5/lib/modules/spa-index.module.js +0 -38
  220. package/esm5/lib/modules/spa-mat.module.js +0 -56
  221. package/esm5/lib/modules/spa-user.module.js +0 -36
  222. package/esm5/lib/services/auth.service.js +0 -157
  223. package/esm5/lib/services/data.service.js +0 -116
  224. package/esm5/lib/services/export.service.js +0 -30
  225. package/esm5/lib/services/http.service.js +0 -85
  226. package/esm5/lib/services/loader-interceptor.service.js +0 -85
  227. package/esm5/lib/services/loader.service.js +0 -18
  228. package/esm5/lib/services/log.service.js +0 -112
  229. package/esm5/lib/services/message.service.js +0 -59
  230. package/esm5/lib/services/storage.service.js +0 -74
  231. package/esm5/lib/services/tin-spa.service.js +0 -16
  232. package/esm5/lib/tin-spa.module.js +0 -94
  233. package/esm5/public-api.js +0 -56
  234. package/esm5/tin-spa.js +0 -8
  235. package/fesm2015/tin-spa.js +0 -3184
  236. package/fesm2015/tin-spa.js.map +0 -1
  237. package/fesm5/tin-spa.js +0 -3422
  238. package/fesm5/tin-spa.js.map +0 -1
  239. package/lib/components/timeout/timeout.component.d.ts +0 -21
  240. package/lib/dnd.directive.d.ts +0 -8
  241. package/tin-spa.d.ts +0 -7
  242. package/tin-spa.metadata.json +0 -1
@@ -0,0 +1,350 @@
1
+ import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
2
+ import { MatTableDataSource } from '@angular/material/table';
3
+ import { FormConfig } from '../../classes/Classes';
4
+ import { detailsDialog } from './detailsDialog.component';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "../../services/data.service";
7
+ import * as i2 from "../../services/message.service";
8
+ import * as i3 from "@angular/cdk/layout";
9
+ import * as i4 from "@angular/material/dialog";
10
+ import * as i5 from "@angular/common";
11
+ import * as i6 from "@angular/material/table";
12
+ import * as i7 from "@angular/material/paginator";
13
+ import * as i8 from "@angular/material/button";
14
+ import * as i9 from "@angular/material/icon";
15
+ import * as i10 from "@angular/material/tooltip";
16
+ import * as i11 from "../check/check.component";
17
+ import * as i12 from "../filter/filter.component";
18
+ import * as i13 from "../../pipes/camelToWords.pipe";
19
+ export class TableComponent {
20
+ constructor(dataService, messageService, breakpointObserver, dialog) {
21
+ this.dataService = dataService;
22
+ this.messageService = messageService;
23
+ this.breakpointObserver = breakpointObserver;
24
+ this.dialog = dialog;
25
+ this.actionsWidth = "50px";
26
+ this.data = [];
27
+ this.refreshClick = new EventEmitter();
28
+ this.createClick = new EventEmitter();
29
+ this.viewClick = new EventEmitter();
30
+ this.editClick = new EventEmitter();
31
+ this.deleteClick = new EventEmitter();
32
+ this.custom1Click = new EventEmitter();
33
+ this.custom2Click = new EventEmitter();
34
+ this.custom3Click = new EventEmitter();
35
+ this.smallScreen = false;
36
+ this.options = [];
37
+ this.displayedColumns = [];
38
+ // detect screen size changes
39
+ this.breakpointObserver.observe(["(max-width: 600px)"]).subscribe((result) => {
40
+ if (result.matches) {
41
+ this.smallScreen = true;
42
+ this.setColumns();
43
+ }
44
+ else {
45
+ this.smallScreen = false;
46
+ this.setColumns();
47
+ }
48
+ });
49
+ }
50
+ ngOnInit() {
51
+ this.options = this.config.columns;
52
+ this.setColumns();
53
+ this.createButton = this.getButton('create');
54
+ this.viewButton = this.getButton('view');
55
+ this.editButton = this.getButton('edit');
56
+ this.deleteButton = this.getButton('delete');
57
+ this.custom1Button = this.getButton('custom1');
58
+ this.custom2Button = this.getButton('custom2');
59
+ this.custom3Button = this.getButton('custom3');
60
+ if (this.config.loadAction) {
61
+ this.loadData();
62
+ }
63
+ this.formDefaults();
64
+ }
65
+ ngOnChanges() {
66
+ if (!this.config.loadAction) {
67
+ console.log("Table data Changed");
68
+ this.dataSource = this.data;
69
+ this.tableDataSource = new MatTableDataSource(this.dataSource);
70
+ setTimeout(() => { this.tableDataSource.paginator = this.tablePaginator; }, 5);
71
+ }
72
+ }
73
+ getButton(name) {
74
+ if (!this.config.buttons)
75
+ return null;
76
+ return this.config.buttons.find(x => x.name == name);
77
+ }
78
+ getIcon(buttonName) {
79
+ let b = this.getButton(buttonName);
80
+ if (b.icon) {
81
+ return b.icon.name;
82
+ }
83
+ let i = 'pageview';
84
+ switch (buttonName) {
85
+ case 'view':
86
+ i = 'pageview';
87
+ break;
88
+ case 'edit':
89
+ i = 'edit';
90
+ break;
91
+ case 'delete':
92
+ i = 'delete';
93
+ break;
94
+ default:
95
+ break;
96
+ }
97
+ return i;
98
+ }
99
+ setColumns() {
100
+ if (!this.config?.columns) {
101
+ return;
102
+ }
103
+ if (this.smallScreen) {
104
+ this.displayedColumns = this.config.minColumns;
105
+ }
106
+ else {
107
+ this.displayedColumns = this.config.columns.map(({ name }) => name);
108
+ }
109
+ let buttonsCount = this.config.buttons.filter(x => x.name != 'create').length ?? 0;
110
+ if (buttonsCount > 0) {
111
+ if (!this.displayedColumns.find(x => x == 'action') && this.config.buttons) {
112
+ this.displayedColumns.push("action");
113
+ }
114
+ this.actionsWidth = `${buttonsCount * 40 + 20}px`;
115
+ }
116
+ }
117
+ getOptions(column) {
118
+ let x = this.options.find(opt => opt.name === column);
119
+ return x;
120
+ }
121
+ testIconCondition(column, row) {
122
+ const option = this.getOptions(column);
123
+ if (option && option.icon && !option.icon.condition) {
124
+ return true;
125
+ }
126
+ if (option && option.icon && option.icon.condition) {
127
+ return option.icon.condition(row[column]);
128
+ }
129
+ return false;
130
+ }
131
+ testDisabled(row, buttonName) {
132
+ let button = this.getButton(buttonName);
133
+ if (button.disabled) {
134
+ return button.disabled(row);
135
+ }
136
+ return false;
137
+ }
138
+ testVisible(row, buttonName) {
139
+ let button = this.getButton(buttonName);
140
+ if (button.visible) {
141
+ return button.visible(row);
142
+ }
143
+ return true;
144
+ }
145
+ //Actions
146
+ refreshClicked() {
147
+ console.log("Refresh");
148
+ this.refreshClick.emit();
149
+ if (this.config.loadAction) {
150
+ this.loadData();
151
+ }
152
+ }
153
+ view(x) {
154
+ console.log("View");
155
+ this.viewClick.emit(x);
156
+ // this.doAction('view', x);
157
+ }
158
+ create(x) {
159
+ console.log("Create " + x);
160
+ this.createClick.emit(x);
161
+ this.doAction('create', x);
162
+ }
163
+ edit(x) {
164
+ console.log("Edit " + x);
165
+ this.editClick.emit(x);
166
+ this.doAction('edit', x);
167
+ }
168
+ delete(x) {
169
+ console.log("Delete");
170
+ this.deleteClick.emit(x);
171
+ this.doAction('delete', x);
172
+ }
173
+ custom1(x) {
174
+ console.log("Custom 1");
175
+ this.custom1Click.emit(x);
176
+ this.doAction('custom1', x);
177
+ }
178
+ custom2(x) {
179
+ console.log("Custom 2");
180
+ this.custom2Click.emit(x);
181
+ this.doAction('custom2', x);
182
+ }
183
+ custom3(x) {
184
+ console.log("Custom 3");
185
+ this.custom3Click.emit(x);
186
+ this.doAction('custom3', x);
187
+ }
188
+ viewModel(row) {
189
+ let button = this.getButton('view');
190
+ if (button && !button.dialog) {
191
+ this.view(row);
192
+ return;
193
+ }
194
+ if (!this.config.formConfig) {
195
+ this.messageService.toast("Please configure form");
196
+ return;
197
+ }
198
+ const dialogRef = this.dialog.open(detailsDialog, {
199
+ width: "900px",
200
+ data: { mode: "view", config: this.config, details: row, smallScreen: this.smallScreen },
201
+ });
202
+ dialogRef.afterClosed().subscribe((result) => {
203
+ if (result.message) {
204
+ this.refreshClicked();
205
+ }
206
+ });
207
+ }
208
+ newModel() {
209
+ let button = this.getButton('create');
210
+ if (button && !button.dialog) {
211
+ this.create('');
212
+ return;
213
+ }
214
+ if (!this.config.formConfig) {
215
+ this.messageService.toast("Please configure form");
216
+ return;
217
+ }
218
+ const dialogRef = this.dialog.open(detailsDialog, {
219
+ width: "900px",
220
+ data: { mode: "create", config: this.config, smallScreen: this.smallScreen }
221
+ });
222
+ dialogRef.afterClosed().subscribe((result) => {
223
+ if (result.message == "success") {
224
+ this.create(result.data);
225
+ this.refreshClicked();
226
+ }
227
+ else if (result.message == "emit") {
228
+ this.create(result.data);
229
+ }
230
+ });
231
+ }
232
+ editModel(row) {
233
+ let button = this.getButton('edit');
234
+ if (button && !button.dialog) {
235
+ this.edit(row);
236
+ return;
237
+ }
238
+ if (!this.config.formConfig) {
239
+ this.messageService.toast("Please configure form");
240
+ return;
241
+ }
242
+ const dialogRef = this.dialog.open(detailsDialog, {
243
+ width: "900px",
244
+ data: { mode: "edit", config: this.config, details: row, smallScreen: this.smallScreen },
245
+ });
246
+ dialogRef.afterClosed().subscribe((result) => {
247
+ if (result.message == "success") {
248
+ this.edit(result.data);
249
+ this.refreshClicked();
250
+ }
251
+ else if (result.message == "emit") {
252
+ this.edit(result.data);
253
+ }
254
+ });
255
+ }
256
+ deleteModel(row) {
257
+ let button = this.getButton('delete');
258
+ if (button && !button.dialog) {
259
+ this.delete(row);
260
+ return;
261
+ }
262
+ this.messageService.confirm(`DELETE ?`).subscribe((result) => {
263
+ if (result == "yes") {
264
+ this.delete(row);
265
+ this.refreshClicked();
266
+ }
267
+ });
268
+ }
269
+ doAction(buttonName, row) {
270
+ let b = this.getButton(buttonName);
271
+ if (!b)
272
+ return;
273
+ if (b.action && buttonName != 'delete')
274
+ return;
275
+ if (!b.action)
276
+ return;
277
+ this.dataService.CallApi(b.action, row).subscribe((apiResponse) => {
278
+ if (apiResponse.success) {
279
+ if (b.action.successMessage) {
280
+ this.messageService.toast(b.action.successMessage);
281
+ }
282
+ else {
283
+ this.messageService.toast("Updated");
284
+ }
285
+ this.refreshClicked();
286
+ }
287
+ else {
288
+ this.messageService.toast("Error: " + apiResponse.message);
289
+ }
290
+ });
291
+ }
292
+ loadData() {
293
+ console.log("loading");
294
+ if (this.config.loadAction) {
295
+ this.dataService.CallApi(this.config.loadAction, "").subscribe((apiResponse) => {
296
+ this.dataSource = apiResponse.data;
297
+ this.tableDataSource = new MatTableDataSource(apiResponse.data);
298
+ this.tableDataSource.paginator = this.tablePaginator;
299
+ if (apiResponse.success) {
300
+ this.tableDataSource = new MatTableDataSource(apiResponse.data);
301
+ this.tableDataSource.paginator = this.tablePaginator;
302
+ }
303
+ else {
304
+ this.messageService.toast("Error: " + JSON.stringify(apiResponse));
305
+ }
306
+ });
307
+ }
308
+ }
309
+ formDefaults() {
310
+ if (!this.config.formConfig) {
311
+ let config = new FormConfig;
312
+ config.fields = [];
313
+ this.config.columns.forEach(column => {
314
+ let field = { name: column.name, type: column.type };
315
+ config.fields.push(field);
316
+ });
317
+ this.config.formConfig = config;
318
+ }
319
+ }
320
+ }
321
+ TableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TableComponent, deps: [{ token: i1.DataServiceLib }, { token: i2.MessageService }, { token: i3.BreakpointObserver }, { token: i4.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
322
+ TableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: TableComponent, selector: "spa-table", inputs: { data: "data", config: "config" }, outputs: { refreshClick: "refreshClick", createClick: "createClick", viewClick: "viewClick", editClick: "editClick", deleteClick: "deleteClick", custom1Click: "custom1Click", custom2Click: "custom2Click", custom3Click: "custom3Click" }, viewQueries: [{ propertyName: "tablePaginator", first: true, predicate: ["tablePaginator"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "\n<div class=\"top\">\n\n <div >\n <!-- <button *ngIf=\"config.newText\" id=\"btnNew\" mat-raised-button color=\"primary\" (click)=\"newModel()\">{{config.newText}}</button> -->\n <button *ngIf=\"createButton\" id=\"btnNew\" mat-raised-button color=\"primary\" (click)=\"newModel()\">{{createButton.display}}</button>\n </div>\n\n <div *ngIf=\"config.showFilter\" class=\"d-flex justify-content-end\">\n <spa-filter [data]=\"tableDataSource\" (refreshClick)=\"refreshClicked()\"></spa-filter>\n </div>\n\n</div>\n\n<div>\n\n <p *ngIf=\"!config\"><em>Configure Table</em></p>\n <p *ngIf=\"!dataSource\"><em>Loading...</em></p>\n\n\n\n <div *ngIf=\"dataSource\">\n\n\n <table mat-table [dataSource]=\"tableDataSource\" class=\"mat-elevation-z8\">\n <ng-container *ngFor=\"let column of config.columns\" [matColumnDef]=\"column.name\">\n <th mat-header-cell *matHeaderCellDef>{{ column.name | camelToWords }}</th>\n <td mat-cell *matCellDef=\"let row;\" >\n\n <ng-container [ngSwitch]=\"column.type\">\n\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <spa-check [value]=\"row[column.name]\" [readonly]=\"true\"></spa-check>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'date'\">\n {{row[column.name] | date : 'dd/MM/yyyy'}}\n <mat-icon *ngIf=\"column.icon && testIconCondition(column.name, row)\" [matTooltip]=\"column.icon?.tip\" matTooltipPosition=\"above\" [ngStyle]=\"{'color':column.icon?.color}\">{{column.icon.name }}</mat-icon>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'money'\">\n {{row[column.name] | currency:'':''}}\n <mat-icon *ngIf=\"column.icon && testIconCondition(column.name, row)\" [matTooltip]=\"column.icon?.tip\" matTooltipPosition=\"above\" [ngStyle]=\"{'color':column.icon?.color}\">{{column.icon.name }}</mat-icon>\n </ng-container>\n\n <ng-container *ngSwitchDefault>\n <label>{{row[column.name]}}</label>\n <mat-icon *ngIf=\"column.icon && testIconCondition(column.name, row)\" [matTooltip]=\"column.icon?.tip\" matTooltipPosition=\"above\" [ngStyle]=\"{'color':column.icon?.color}\">{{column.icon.name }}</mat-icon>\n </ng-container>\n\n </ng-container>\n\n\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"action\">\n <th mat-header-cell *matHeaderCellDef> Action </th>\n <td mat-cell *matCellDef=\"let row\" [ngStyle]=\"{width:smallScreen ? '50px' : actionsWidth}\">\n\n\n <button mat-mini-fab color=\"primary\" [matTooltip]=\"viewButton.tip ?? 'view' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':viewButton.color}\" [disabled]=\"testDisabled(row,'view')\" *ngIf=\"viewButton && testVisible(row,'view')\" (click)=\"viewModel(row)\">\n <mat-icon>{{getIcon('view')}}</mat-icon>\n </button>\n\n <button mat-mini-fab color=\"primary\" [matTooltip]=\"custom1Button.tip ?? 'custom1' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':custom1Button.color}\" [disabled]=\"testDisabled(row,'custom1')\" *ngIf=\"!smallScreen && custom1Button && testVisible(row,'custom1')\" (click)=\"custom1(row)\">\n <mat-icon>{{getIcon('custom1')}}</mat-icon>\n </button>\n\n <button mat-mini-fab color=\"primary\" [matTooltip]=\"custom2Button.tip ?? 'custom2' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':custom2Button.color}\" [disabled]=\"testDisabled(row,'custom2')\" *ngIf=\"!smallScreen && custom2Button && testVisible(row,'custom2')\" (click)=\"custom2(row)\">\n <mat-icon>{{getIcon('custom2')}}</mat-icon>\n </button>\n\n <button mat-mini-fab color=\"primary\" [matTooltip]=\"custom3Button.tip ?? 'custom3' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':custom3Button.color}\" [disabled]=\"testDisabled(row,'custom3')\" *ngIf=\"!smallScreen && custom3Button && testVisible(row,'custom3')\" (click)=\"custom3(row)\">\n <mat-icon>{{getIcon('custom3')}}</mat-icon>\n </button>\n\n\n <button mat-mini-fab color=\"primary\" [matTooltip]=\"editButton.tip ?? 'edit' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':editButton.color}\" [disabled]=\"testDisabled(row,'edit')\" *ngIf=\"!smallScreen && editButton && testVisible(row,'edit')\" (click)=\"editModel(row)\">\n <mat-icon>{{getIcon('edit')}}</mat-icon>\n </button>\n\n <button mat-mini-fab color=\"warn\" [matTooltip]=\"deleteButton.tip ?? 'delete' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':deleteButton.color}\" [disabled]=\"testDisabled(row,'delete')\" *ngIf=\"!smallScreen && deleteButton && testVisible(row,'delete')\" (click)=\"deleteModel(row)\">\n <mat-icon>{{getIcon('delete')}}</mat-icon>\n </button>\n\n </td>\n </ng-container>\n\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n\n </div>\n\n <mat-paginator #tablePaginator [pageSizeOptions]=\"[10, 20, 50]\" showFirstLastButtons></mat-paginator>\n\n</div>\n\n<p *ngIf=\"dataSource?.length == 0\"><em>No Data</em></p>\n\n\n", styles: [".top{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;align-items:center}.mat-mini-fab{width:32px;height:32px}.mat-mini-fab mat-icon{font-size:16px;margin-top:-3px}\n"], dependencies: [{ kind: "directive", type: i5.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i5.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i5.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i5.NgSwitch, selector: "[ngSwitch]", inputs: ["ngSwitch"] }, { kind: "directive", type: i5.NgSwitchCase, selector: "[ngSwitchCase]", inputs: ["ngSwitchCase"] }, { kind: "directive", type: i5.NgSwitchDefault, selector: "[ngSwitchDefault]" }, { kind: "component", type: i6.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i6.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i6.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i6.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i6.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i6.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i6.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i6.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i6.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i6.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "component", type: i7.MatPaginator, selector: "mat-paginator", inputs: ["disabled"], exportAs: ["matPaginator"] }, { kind: "component", type: i8.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { kind: "component", type: i9.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "directive", type: i10.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { kind: "component", type: i11.CheckComponent, selector: "spa-check", inputs: ["readonly", "display", "value"], outputs: ["valueChange", "click", "check", "uncheck"] }, { kind: "component", type: i12.FilterComponent, selector: "spa-filter", inputs: ["data"], outputs: ["refreshClick"] }, { kind: "pipe", type: i5.CurrencyPipe, name: "currency" }, { kind: "pipe", type: i5.DatePipe, name: "date" }, { kind: "pipe", type: i13.CamelToWordsPipe, name: "camelToWords" }] });
323
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: TableComponent, decorators: [{
324
+ type: Component,
325
+ args: [{ selector: 'spa-table', template: "\n<div class=\"top\">\n\n <div >\n <!-- <button *ngIf=\"config.newText\" id=\"btnNew\" mat-raised-button color=\"primary\" (click)=\"newModel()\">{{config.newText}}</button> -->\n <button *ngIf=\"createButton\" id=\"btnNew\" mat-raised-button color=\"primary\" (click)=\"newModel()\">{{createButton.display}}</button>\n </div>\n\n <div *ngIf=\"config.showFilter\" class=\"d-flex justify-content-end\">\n <spa-filter [data]=\"tableDataSource\" (refreshClick)=\"refreshClicked()\"></spa-filter>\n </div>\n\n</div>\n\n<div>\n\n <p *ngIf=\"!config\"><em>Configure Table</em></p>\n <p *ngIf=\"!dataSource\"><em>Loading...</em></p>\n\n\n\n <div *ngIf=\"dataSource\">\n\n\n <table mat-table [dataSource]=\"tableDataSource\" class=\"mat-elevation-z8\">\n <ng-container *ngFor=\"let column of config.columns\" [matColumnDef]=\"column.name\">\n <th mat-header-cell *matHeaderCellDef>{{ column.name | camelToWords }}</th>\n <td mat-cell *matCellDef=\"let row;\" >\n\n <ng-container [ngSwitch]=\"column.type\">\n\n <ng-container *ngSwitchCase=\"'checkbox'\">\n <spa-check [value]=\"row[column.name]\" [readonly]=\"true\"></spa-check>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'date'\">\n {{row[column.name] | date : 'dd/MM/yyyy'}}\n <mat-icon *ngIf=\"column.icon && testIconCondition(column.name, row)\" [matTooltip]=\"column.icon?.tip\" matTooltipPosition=\"above\" [ngStyle]=\"{'color':column.icon?.color}\">{{column.icon.name }}</mat-icon>\n </ng-container>\n\n <ng-container *ngSwitchCase=\"'money'\">\n {{row[column.name] | currency:'':''}}\n <mat-icon *ngIf=\"column.icon && testIconCondition(column.name, row)\" [matTooltip]=\"column.icon?.tip\" matTooltipPosition=\"above\" [ngStyle]=\"{'color':column.icon?.color}\">{{column.icon.name }}</mat-icon>\n </ng-container>\n\n <ng-container *ngSwitchDefault>\n <label>{{row[column.name]}}</label>\n <mat-icon *ngIf=\"column.icon && testIconCondition(column.name, row)\" [matTooltip]=\"column.icon?.tip\" matTooltipPosition=\"above\" [ngStyle]=\"{'color':column.icon?.color}\">{{column.icon.name }}</mat-icon>\n </ng-container>\n\n </ng-container>\n\n\n </td>\n </ng-container>\n\n <ng-container matColumnDef=\"action\">\n <th mat-header-cell *matHeaderCellDef> Action </th>\n <td mat-cell *matCellDef=\"let row\" [ngStyle]=\"{width:smallScreen ? '50px' : actionsWidth}\">\n\n\n <button mat-mini-fab color=\"primary\" [matTooltip]=\"viewButton.tip ?? 'view' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':viewButton.color}\" [disabled]=\"testDisabled(row,'view')\" *ngIf=\"viewButton && testVisible(row,'view')\" (click)=\"viewModel(row)\">\n <mat-icon>{{getIcon('view')}}</mat-icon>\n </button>\n\n <button mat-mini-fab color=\"primary\" [matTooltip]=\"custom1Button.tip ?? 'custom1' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':custom1Button.color}\" [disabled]=\"testDisabled(row,'custom1')\" *ngIf=\"!smallScreen && custom1Button && testVisible(row,'custom1')\" (click)=\"custom1(row)\">\n <mat-icon>{{getIcon('custom1')}}</mat-icon>\n </button>\n\n <button mat-mini-fab color=\"primary\" [matTooltip]=\"custom2Button.tip ?? 'custom2' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':custom2Button.color}\" [disabled]=\"testDisabled(row,'custom2')\" *ngIf=\"!smallScreen && custom2Button && testVisible(row,'custom2')\" (click)=\"custom2(row)\">\n <mat-icon>{{getIcon('custom2')}}</mat-icon>\n </button>\n\n <button mat-mini-fab color=\"primary\" [matTooltip]=\"custom3Button.tip ?? 'custom3' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':custom3Button.color}\" [disabled]=\"testDisabled(row,'custom3')\" *ngIf=\"!smallScreen && custom3Button && testVisible(row,'custom3')\" (click)=\"custom3(row)\">\n <mat-icon>{{getIcon('custom3')}}</mat-icon>\n </button>\n\n\n <button mat-mini-fab color=\"primary\" [matTooltip]=\"editButton.tip ?? 'edit' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':editButton.color}\" [disabled]=\"testDisabled(row,'edit')\" *ngIf=\"!smallScreen && editButton && testVisible(row,'edit')\" (click)=\"editModel(row)\">\n <mat-icon>{{getIcon('edit')}}</mat-icon>\n </button>\n\n <button mat-mini-fab color=\"warn\" [matTooltip]=\"deleteButton.tip ?? 'delete' \" matTooltipPosition=\"above\" style=\"margin-right:5px\" [ngStyle]=\"{'background-color':deleteButton.color}\" [disabled]=\"testDisabled(row,'delete')\" *ngIf=\"!smallScreen && deleteButton && testVisible(row,'delete')\" (click)=\"deleteModel(row)\">\n <mat-icon>{{getIcon('delete')}}</mat-icon>\n </button>\n\n </td>\n </ng-container>\n\n\n <tr mat-header-row *matHeaderRowDef=\"displayedColumns\"></tr>\n <tr mat-row *matRowDef=\"let row; columns: displayedColumns;\"></tr>\n </table>\n\n </div>\n\n <mat-paginator #tablePaginator [pageSizeOptions]=\"[10, 20, 50]\" showFirstLastButtons></mat-paginator>\n\n</div>\n\n<p *ngIf=\"dataSource?.length == 0\"><em>No Data</em></p>\n\n\n", styles: [".top{display:flex;flex-direction:row;flex-wrap:wrap;justify-content:space-between;align-items:center}.mat-mini-fab{width:32px;height:32px}.mat-mini-fab mat-icon{font-size:16px;margin-top:-3px}\n"] }]
326
+ }], ctorParameters: function () { return [{ type: i1.DataServiceLib }, { type: i2.MessageService }, { type: i3.BreakpointObserver }, { type: i4.MatDialog }]; }, propDecorators: { tablePaginator: [{
327
+ type: ViewChild,
328
+ args: ['tablePaginator']
329
+ }], data: [{
330
+ type: Input
331
+ }], config: [{
332
+ type: Input
333
+ }], refreshClick: [{
334
+ type: Output
335
+ }], createClick: [{
336
+ type: Output
337
+ }], viewClick: [{
338
+ type: Output
339
+ }], editClick: [{
340
+ type: Output
341
+ }], deleteClick: [{
342
+ type: Output
343
+ }], custom1Click: [{
344
+ type: Output
345
+ }], custom2Click: [{
346
+ type: Output
347
+ }], custom3Click: [{
348
+ type: Output
349
+ }] } });
350
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGluLXNwYS9zcmMvbGliL2NvbXBvbmVudHMvdGFibGUvdGFibGUuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGluLXNwYS9zcmMvbGliL2NvbXBvbmVudHMvdGFibGUvdGFibGUuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsS0FBSyxFQUFVLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDMUYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFN0QsT0FBTyxFQUFrQixVQUFVLEVBQWUsTUFBTSx1QkFBdUIsQ0FBQztBQUloRixPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7Ozs7Ozs7Ozs7Ozs7OztBQVUxRCxNQUFNLE9BQU8sY0FBYztJQUV6QixZQUFvQixXQUEyQixFQUFVLGNBQThCLEVBQVUsa0JBQXNDLEVBQVMsTUFBaUI7UUFBN0ksZ0JBQVcsR0FBWCxXQUFXLENBQWdCO1FBQVUsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQVUsdUJBQWtCLEdBQWxCLGtCQUFrQixDQUFvQjtRQUFTLFdBQU0sR0FBTixNQUFNLENBQVc7UUEyQ2pLLGlCQUFZLEdBQUcsTUFBTSxDQUFDO1FBb0JiLFNBQUksR0FBTyxFQUFFLENBQUM7UUFHYixpQkFBWSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7UUFDbEMsZ0JBQVcsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQ2pDLGNBQVMsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQy9CLGNBQVMsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO1FBQy9CLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FB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QUNHLFlBQVk7c0JBQXJCLE1BQU07Z0JBQ0csWUFBWTtzQkFBckIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25Jbml0LCBPdXRwdXQsIFZpZXdDaGlsZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTWF0VGFibGVEYXRhU291cmNlIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvdGFibGUnO1xuaW1wb3J0IHsgRGF0ZVBpcGUsIEN1cnJlbmN5UGlwZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBCdXR0b24sIENvbHVtbiwgRm9ybUNvbmZpZywgVGFibGVDb25maWcgfSBmcm9tICcuLi8uLi9jbGFzc2VzL0NsYXNzZXMnO1xuaW1wb3J0IHsgTWF0UGFnaW5hdG9yIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvcGFnaW5hdG9yJztcbmltcG9ydCB7IE1lc3NhZ2VTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvbWVzc2FnZS5zZXJ2aWNlJztcbmltcG9ydCB7IE1hdERpYWxvZyB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2RpYWxvZyc7XG5pbXBvcnQgeyBkZXRhaWxzRGlhbG9nIH0gZnJvbSAnLi9kZXRhaWxzRGlhbG9nLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBCcmVha3BvaW50T2JzZXJ2ZXIsIEJyZWFrcG9pbnRTdGF0ZSB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9sYXlvdXQnO1xuaW1wb3J0IHsgRGF0YVNlcnZpY2VMaWIgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9kYXRhLnNlcnZpY2UnO1xuaW1wb3J0IHsgQXBpUmVzcG9uc2UgfSBmcm9tICcuLi8uLi9jbGFzc2VzL1RpbkNvcmUnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdzcGEtdGFibGUnLFxuICB0ZW1wbGF0ZVVybDogJy4vdGFibGUuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi90YWJsZS5jb21wb25lbnQuY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgVGFibGVDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZGF0YVNlcnZpY2U6IERhdGFTZXJ2aWNlTGliLCBwcml2YXRlIG1lc3NhZ2VTZXJ2aWNlOiBNZXNzYWdlU2VydmljZSwgcHJpdmF0ZSBicmVha3BvaW50T2JzZXJ2ZXI6IEJyZWFrcG9pbnRPYnNlcnZlciwgcHVibGljIGRpYWxvZzogTWF0RGlhbG9nKVxuICB7XG4gICAgLy8gZGV0ZWN0IHNjcmVlbiBzaXplIGNoYW5nZXNcbiAgICB0aGlzLmJyZWFrcG9pbnRPYnNlcnZlci5vYnNlcnZlKFsgXCIobWF4LXdpZHRoOiA2MDBweClcIl0pLnN1YnNjcmliZSgocmVzdWx0OiBCcmVha3BvaW50U3RhdGUpID0+IHtcblxuICAgICAgaWYgKHJlc3VsdC5tYXRjaGVzKSB7XG4gICAgICAgIHRoaXMuc21hbGxTY3JlZW4gPSB0cnVlXG4gICAgICAgIHRoaXMuc2V0Q29sdW1ucygpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLnNtYWxsU2NyZWVuID0gZmFsc2VcbiAgICAgICAgdGhpcy5zZXRDb2x1bW5zKClcbiAgICAgIH1cblxuICAgIH0pO1xuICB9XG5cblxuICBuZ09uSW5pdCgpIHtcblxuICAgIHRoaXMub3B0aW9ucyA9IHRoaXMuY29uZmlnLmNvbHVtbnM7XG5cbiAgICB0aGlzLnNldENvbHVtbnMoKVxuXG4gICAgdGhpcy5jcmVhdGVCdXR0b24gPSB0aGlzLmdldEJ1dHRvbignY3JlYXRlJylcbiAgICB0aGlzLnZpZXdCdXR0b24gPSB0aGlzLmdldEJ1dHRvbigndmlldycpXG4gICAgdGhpcy5lZGl0QnV0dG9uID0gdGhpcy5nZXRCdXR0b24oJ2VkaXQnKVxuICAgIHRoaXMuZGVsZXRlQnV0dG9uID0gdGhpcy5nZXRCdXR0b24oJ2RlbGV0ZScpXG4gICAgdGhpcy5jdXN0b20xQnV0dG9uID0gdGhpcy5nZXRCdXR0b24oJ2N1c3RvbTEnKVxuICAgIHRoaXMuY3VzdG9tMkJ1dHRvbiA9IHRoaXMuZ2V0QnV0dG9uKCdjdXN0b20yJylcbiAgICB0aGlzLmN1c3RvbTNCdXR0b24gPSB0aGlzLmdldEJ1dHRvbignY3VzdG9tMycpXG5cblxuICAgIGlmICh0aGlzLmNvbmZpZy5sb2FkQWN0aW9uKXtcbiAgICAgIHRoaXMubG9hZERhdGEoKTtcbiAgICB9XG5cbiAgICB0aGlzLmZvcm1EZWZhdWx0cygpO1xuXG5cblxuICB9XG5cblxuICBhY3Rpb25zV2lkdGggPSBcIjUwcHhcIjtcblxuXG5cbiAgbmdPbkNoYW5nZXMoKSB7XG5cbiAgICBpZiAoIXRoaXMuY29uZmlnLmxvYWRBY3Rpb24pe1xuICAgICAgY29uc29sZS5sb2coXCJUYWJsZSBkYXRhIENoYW5nZWRcIilcbiAgICAgIHRoaXMuZGF0YVNvdXJjZSA9IHRoaXMuZGF0YTtcblxuICAgICAgdGhpcy50YWJsZURhdGFTb3VyY2UgPSBuZXcgTWF0VGFibGVEYXRhU291cmNlPGFueT4odGhpcy5kYXRhU291cmNlKTtcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4geyB0aGlzLnRhYmxlRGF0YVNvdXJjZS5wYWdpbmF0b3IgPSB0aGlzLnRhYmxlUGFnaW5hdG9yOyB9LCA1KVxuICAgIH1cblxuICB9XG5cblxuICBAVmlld0NoaWxkKCd0YWJsZVBhZ2luYXRvcicpIHRhYmxlUGFnaW5hdG9yOiBNYXRQYWdpbmF0b3I7XG5cblxuICBASW5wdXQoKSBkYXRhOiBhbnkgPVtdO1xuICBASW5wdXQoKSBjb25maWc6IFRhYmxlQ29uZmlnO1xuXG4gIEBPdXRwdXQoKSByZWZyZXNoQ2xpY2sgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBjcmVhdGVDbGljayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHZpZXdDbGljayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGVkaXRDbGljayA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGRlbGV0ZUNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgY3VzdG9tMUNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgY3VzdG9tMkNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgY3VzdG9tM0NsaWNrID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuXG4gIHNtYWxsU2NyZWVuID0gZmFsc2VcblxuICBjcmVhdGVCdXR0b246IEJ1dHRvbjtcbiAgdmlld0J1dHRvblxuICBlZGl0QnV0dG9uXG4gIGRlbGV0ZUJ1dHRvblxuICBjdXN0b20xQnV0dG9uXG4gIGN1c3RvbTJCdXR0b25cbiAgY3VzdG9tM0J1dHRvblxuXG4gIC8vVGFibGVcbiAgdGFibGVEYXRhU291cmNlO1xuICBkYXRhU291cmNlOiBhbnlbXTtcbiAgb3B0aW9uczogQ29sdW1uW10gPSBbXTtcbiAgZGlzcGxheWVkQ29sdW1ucyA9IFtdXG5cblxuICBnZXRCdXR0b24obmFtZTogc3RyaW5nKSB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZy5idXR0b25zKSByZXR1cm4gbnVsbFxuICAgIHJldHVybiB0aGlzLmNvbmZpZy5idXR0b25zLmZpbmQoeCA9PiB4Lm5hbWUgPT0gbmFtZSlcbiAgfVxuXG4gIGdldEljb24oYnV0dG9uTmFtZTogc3RyaW5nKXtcblxuICAgIGxldCBiID0gdGhpcy5nZXRCdXR0b24oYnV0dG9uTmFtZSk7XG4gICAgaWYgKGIuaWNvbil7XG4gICAgICByZXR1cm4gYi5pY29uLm5hbWVcbiAgICB9XG5cbiAgICBsZXQgaSA9ICdwYWdldmlldydcblxuICAgIHN3aXRjaCAoYnV0dG9uTmFtZSkge1xuXG4gICAgICBjYXNlICd2aWV3JzpcbiAgICAgICAgaSA9ICdwYWdldmlldydcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICdlZGl0JzpcbiAgICAgICAgaSA9ICdlZGl0J1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ2RlbGV0ZSc6XG4gICAgICAgIGkgPSAnZGVsZXRlJ1xuICAgICAgICBicmVhaztcblxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuXG4gICAgcmV0dXJuIGk7XG4gIH1cblxuICBzZXRDb2x1bW5zICgpe1xuXG4gICAgaWYgKCF0aGlzLmNvbmZpZz8uY29sdW1ucyl7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBpZiAodGhpcy5zbWFsbFNjcmVlbikge1xuICAgICAgdGhpcy5kaXNwbGF5ZWRDb2x1bW5zID0gdGhpcy5jb25maWcubWluQ29sdW1uc1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnMgPSB0aGlzLmNvbmZpZy5jb2x1bW5zLm1hcCgoeyBuYW1lIH0pID0+IG5hbWUpXG4gICAgfVxuXG5cbiAgICBsZXQgYnV0dG9uc0NvdW50ID0gdGhpcy5jb25maWcuYnV0dG9ucy5maWx0ZXIoeCA9PiB4Lm5hbWUgIT0gJ2NyZWF0ZScpLmxlbmd0aCA/PyAwXG4gICAgaWYgKGJ1dHRvbnNDb3VudCA+IDApe1xuXG4gICAgICBpZiAoIXRoaXMuZGlzcGxheWVkQ29sdW1ucy5maW5kKHggPT4geCA9PSAnYWN0aW9uJykgJiYgdGhpcy5jb25maWcuYnV0dG9ucykge1xuICAgICAgICB0aGlzLmRpc3BsYXllZENvbHVtbnMucHVzaChcImFjdGlvblwiKVxuICAgICAgfVxuXG4gICAgICB0aGlzLmFjdGlvbnNXaWR0aCA9IGAke2J1dHRvbnNDb3VudCAqIDQwICsgMjB9cHhgXG5cbiAgICB9XG5cbiAgfVxuXG4gIGdldE9wdGlvbnMoY29sdW1uKXtcbiAgICBsZXQgeCA9IHRoaXMub3B0aW9ucy5maW5kKG9wdCA9PiBvcHQubmFtZSA9PT0gY29sdW1uKTtcbiAgICByZXR1cm4gIHhcbiAgfVxuXG5cbiAgdGVzdEljb25Db25kaXRpb24oY29sdW1uOiBzdHJpbmcsIHJvdzogYW55KTogYm9vbGVhbiB7XG5cbiAgICBjb25zdCBvcHRpb24gPSB0aGlzLmdldE9wdGlvbnMoY29sdW1uKTtcblxuICAgIGlmIChvcHRpb24gJiYgb3B0aW9uLmljb24gJiYgIW9wdGlvbi5pY29uLmNvbmRpdGlvbil7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAob3B0aW9uICYmIG9wdGlvbi5pY29uICYmIG9wdGlvbi5pY29uLmNvbmRpdGlvbikge1xuICAgICAgcmV0dXJuIG9wdGlvbi5pY29uLmNvbmRpdGlvbihyb3dbY29sdW1uXSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdGVzdERpc2FibGVkKHJvdywgYnV0dG9uTmFtZTogc3RyaW5nKTogYm9vbGVhbntcblxuICAgIGxldCBidXR0b24gPSB0aGlzLmdldEJ1dHRvbihidXR0b25OYW1lKVxuXG4gICAgaWYgKGJ1dHRvbi5kaXNhYmxlZCl7XG5cbiAgICAgIHJldHVybiBidXR0b24uZGlzYWJsZWQocm93KTtcbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICB0ZXN0VmlzaWJsZShyb3csIGJ1dHRvbk5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuXG4gICAgbGV0IGJ1dHRvbiA9IHRoaXMuZ2V0QnV0dG9uKGJ1dHRvbk5hbWUpXG5cbiAgICBpZiAoYnV0dG9uLnZpc2libGUpIHtcblxuICAgICAgcmV0dXJuIGJ1dHRvbi52aXNpYmxlKHJvdyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuXG4gIC8vQWN0aW9uc1xuXG4gIHJlZnJlc2hDbGlja2VkKCkge1xuICAgIGNvbnNvbGUubG9nKFwiUmVmcmVzaFwiKVxuICAgIHRoaXMucmVmcmVzaENsaWNrLmVtaXQoKTtcblxuICAgIGlmICh0aGlzLmNvbmZpZy5sb2FkQWN0aW9uKSB7XG4gICAgICB0aGlzLmxvYWREYXRhKCk7XG4gICAgfVxuICB9XG5cbiAgdmlldyh4KSB7XG4gICAgY29uc29sZS5sb2coXCJWaWV3XCIpXG4gICAgdGhpcy52aWV3Q2xpY2suZW1pdCh4KTtcbiAgICAvLyB0aGlzLmRvQWN0aW9uKCd2aWV3JywgeCk7XG4gIH1cblxuICBjcmVhdGUoeCkge1xuICAgIGNvbnNvbGUubG9nKFwiQ3JlYXRlIFwiICsgeClcbiAgICB0aGlzLmNyZWF0ZUNsaWNrLmVtaXQoeCk7XG4gICAgdGhpcy5kb0FjdGlvbignY3JlYXRlJywgeCk7XG4gIH1cblxuICBlZGl0KHgpIHtcbiAgICBjb25zb2xlLmxvZyhcIkVkaXQgXCIgKyB4KVxuICAgIHRoaXMuZWRpdENsaWNrLmVtaXQoeCk7XG4gICAgdGhpcy5kb0FjdGlvbignZWRpdCcsIHgpO1xuICB9XG5cbiAgZGVsZXRlKHgpIHtcbiAgICBjb25zb2xlLmxvZyhcIkRlbGV0ZVwiKVxuICAgIHRoaXMuZGVsZXRlQ2xpY2suZW1pdCh4KTtcbiAgICB0aGlzLmRvQWN0aW9uKCdkZWxldGUnLCB4KTtcbiAgfVxuXG4gIGN1c3RvbTEoeCkge1xuICAgIGNvbnNvbGUubG9nKFwiQ3VzdG9tIDFcIilcbiAgICB0aGlzLmN1c3RvbTFDbGljay5lbWl0KHgpO1xuICAgIHRoaXMuZG9BY3Rpb24oJ2N1c3RvbTEnLCB4KTtcbiAgfVxuXG4gIGN1c3RvbTIoeCkge1xuICAgIGNvbnNvbGUubG9nKFwiQ3VzdG9tIDJcIilcbiAgICB0aGlzLmN1c3RvbTJDbGljay5lbWl0KHgpO1xuICAgIHRoaXMuZG9BY3Rpb24oJ2N1c3RvbTInLCB4KTtcbiAgfVxuXG4gIGN1c3RvbTMoeCkge1xuICAgIGNvbnNvbGUubG9nKFwiQ3VzdG9tIDNcIilcbiAgICB0aGlzLmN1c3RvbTNDbGljay5lbWl0KHgpO1xuICAgIHRoaXMuZG9BY3Rpb24oJ2N1c3RvbTMnLCB4KTtcbiAgfVxuXG5cbiAgdmlld01vZGVsKHJvdykge1xuXG4gICAgbGV0IGJ1dHRvbiA9IHRoaXMuZ2V0QnV0dG9uKCd2aWV3Jyk7XG4gICAgaWYgKGJ1dHRvbiAmJiAhYnV0dG9uLmRpYWxvZykge1xuICAgICAgdGhpcy52aWV3KHJvdyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmNvbmZpZy5mb3JtQ29uZmlnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2VTZXJ2aWNlLnRvYXN0KFwiUGxlYXNlIGNvbmZpZ3VyZSBmb3JtXCIpXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihkZXRhaWxzRGlhbG9nLCB7XG4gICAgICB3aWR0aDogXCI5MDBweFwiLFxuICAgICAgZGF0YTogeyBtb2RlOiBcInZpZXdcIiwgY29uZmlnOiB0aGlzLmNvbmZpZywgZGV0YWlsczogcm93LCBzbWFsbFNjcmVlbjogdGhpcy5zbWFsbFNjcmVlbiB9LFxuICAgIH0pO1xuXG4gICAgZGlhbG9nUmVmLmFmdGVyQ2xvc2VkKCkuc3Vic2NyaWJlKChyZXN1bHQpID0+IHtcbiAgICAgIGlmIChyZXN1bHQubWVzc2FnZSkge1xuICAgICAgICB0aGlzLnJlZnJlc2hDbGlja2VkKCk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgfVxuXG4gIG5ld01vZGVsKCkge1xuXG4gICAgbGV0IGJ1dHRvbiA9IHRoaXMuZ2V0QnV0dG9uKCdjcmVhdGUnKTtcbiAgICBpZiAoYnV0dG9uICYmICFidXR0b24uZGlhbG9nKXtcbiAgICAgIHRoaXMuY3JlYXRlKCcnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuY29uZmlnLmZvcm1Db25maWcpe1xuICAgICAgdGhpcy5tZXNzYWdlU2VydmljZS50b2FzdChcIlBsZWFzZSBjb25maWd1cmUgZm9ybVwiKVxuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGRpYWxvZ1JlZiA9IHRoaXMuZGlhbG9nLm9wZW4oZGV0YWlsc0RpYWxvZywge1xuICAgICAgd2lkdGg6IFwiOTAwcHhcIixcbiAgICAgIGRhdGE6IHsgbW9kZTogXCJjcmVhdGVcIiwgY29uZmlnOiB0aGlzLmNvbmZpZywgc21hbGxTY3JlZW46IHRoaXMuc21hbGxTY3JlZW4gfVxuICAgIH0pO1xuXG4gICAgZGlhbG9nUmVmLmFmdGVyQ2xvc2VkKCkuc3Vic2NyaWJlKChyZXN1bHQpID0+IHtcbiAgICAgIGlmIChyZXN1bHQubWVzc2FnZSA9PVwic3VjY2Vzc1wiKSB7XG4gICAgICAgIHRoaXMuY3JlYXRlKHJlc3VsdC5kYXRhKTtcbiAgICAgICAgdGhpcy5yZWZyZXNoQ2xpY2tlZCgpO1xuICAgICAgfWVsc2UgaWYgKHJlc3VsdC5tZXNzYWdlID09XCJlbWl0XCIpe1xuICAgICAgICB0aGlzLmNyZWF0ZShyZXN1bHQuZGF0YSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuXG5cbiAgZWRpdE1vZGVsKHJvdykge1xuXG4gICAgbGV0IGJ1dHRvbiA9IHRoaXMuZ2V0QnV0dG9uKCdlZGl0Jyk7XG4gICAgaWYgKGJ1dHRvbiAmJiAhYnV0dG9uLmRpYWxvZykge1xuICAgICAgdGhpcy5lZGl0KHJvdyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmNvbmZpZy5mb3JtQ29uZmlnKSB7XG4gICAgICB0aGlzLm1lc3NhZ2VTZXJ2aWNlLnRvYXN0KFwiUGxlYXNlIGNvbmZpZ3VyZSBmb3JtXCIpXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZGlhbG9nUmVmID0gdGhpcy5kaWFsb2cub3BlbihkZXRhaWxzRGlhbG9nLCB7XG4gICAgICB3aWR0aDogXCI5MDBweFwiLFxuICAgICAgZGF0YTogeyBtb2RlOiBcImVkaXRcIiwgY29uZmlnOiB0aGlzLmNvbmZpZywgZGV0YWlsczogcm93LCBzbWFsbFNjcmVlbjogdGhpcy5zbWFsbFNjcmVlbiB9LFxuICAgIH0pO1xuXG4gICAgZGlhbG9nUmVmLmFmdGVyQ2xvc2VkKCkuc3Vic2NyaWJlKChyZXN1bHQpID0+IHtcbiAgICAgIGlmIChyZXN1bHQubWVzc2FnZSA9PSBcInN1Y2Nlc3NcIikge1xuICAgICAgICB0aGlzLmVkaXQocmVzdWx0LmRhdGEpO1xuICAgICAgICB0aGlzLnJlZnJlc2hDbGlja2VkKCk7XG4gICAgICB9IGVsc2UgaWYgKHJlc3VsdC5tZXNzYWdlID09IFwiZW1pdFwiKSB7XG4gICAgICAgIHRoaXMuZWRpdChyZXN1bHQuZGF0YSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBkZWxldGVNb2RlbChyb3cpIHtcblxuICAgIGxldCBidXR0b24gPSB0aGlzLmdldEJ1dHRvbignZGVsZXRlJyk7XG4gICAgaWYgKGJ1dHRvbiAmJiAhYnV0dG9uLmRpYWxvZykge1xuICAgICAgdGhpcy5kZWxldGUocm93KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLm1lc3NhZ2VTZXJ2aWNlLmNvbmZpcm0oYERFTEVURSA/YCkuc3Vic2NyaWJlKChyZXN1bHQpID0+IHtcbiAgICAgICAgaWYgKHJlc3VsdCA9PSBcInllc1wiKSB7XG4gICAgICAgICAgdGhpcy5kZWxldGUocm93KVxuICAgICAgICAgIHRoaXMucmVmcmVzaENsaWNrZWQoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gIH1cblxuICBkb0FjdGlvbihidXR0b25OYW1lLHJvdyl7XG5cblxuICAgIGxldCBiID0gdGhpcy5nZXRCdXR0b24oYnV0dG9uTmFtZSlcblxuICAgIGlmICghYikgcmV0dXJuO1xuXG4gICAgaWYgKGIuYWN0aW9uICYmIGJ1dHRvbk5hbWUgIT0gJ2RlbGV0ZScpIHJldHVybjtcblxuICAgIGlmICghYi5hY3Rpb24pIHJldHVybjtcblxuXG4gICAgdGhpcy5kYXRhU2VydmljZS5DYWxsQXBpKGIuYWN0aW9uLCByb3cpLnN1YnNjcmliZSgoYXBpUmVzcG9uc2UpID0+IHtcblxuICAgICAgaWYgKGFwaVJlc3BvbnNlLnN1Y2Nlc3MpIHtcbiAgICAgICAgaWYgKGIuYWN0aW9uLnN1Y2Nlc3NNZXNzYWdlKXtcbiAgICAgICAgICB0aGlzLm1lc3NhZ2VTZXJ2aWNlLnRvYXN0KGIuYWN0aW9uLnN1Y2Nlc3NNZXNzYWdlKTtcbiAgICAgICAgfWVsc2V7XG4gICAgICAgICAgdGhpcy5tZXNzYWdlU2VydmljZS50b2FzdChcIlVwZGF0ZWRcIik7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJlZnJlc2hDbGlja2VkKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLm1lc3NhZ2VTZXJ2aWNlLnRvYXN0KFwiRXJyb3I6IFwiICsgYXBpUmVzcG9uc2UubWVzc2FnZSk7XG4gICAgICB9XG4gICAgfSk7XG5cbiAgfVxuXG4gIGxvYWREYXRhKCl7XG4gICAgY29uc29sZS5sb2coXCJsb2FkaW5nXCIpXG5cbiAgICBpZiAodGhpcy5jb25maWcubG9hZEFjdGlvbil7XG5cbiAgICAgIHRoaXMuZGF0YVNlcnZpY2UuQ2FsbEFwaSh0aGlzLmNvbmZpZy5sb2FkQWN0aW9uLCBcIlwiKS5zdWJzY3JpYmUoKGFwaVJlc3BvbnNlOiBBcGlSZXNwb25zZSkgPT4ge1xuXG4gICAgICAgIHRoaXMuZGF0YVNvdXJjZSA9IGFwaVJlc3BvbnNlLmRhdGFcblxuICAgICAgICB0aGlzLnRhYmxlRGF0YVNvdXJjZSA9IG5ldyBNYXRUYWJsZURhdGFTb3VyY2U8YW55PihhcGlSZXNwb25zZS5kYXRhKTtcbiAgICAgICAgdGhpcy50YWJsZURhdGFTb3VyY2UucGFnaW5hdG9yID0gdGhpcy50YWJsZVBhZ2luYXRvcjtcblxuICAgICAgICBpZiAoYXBpUmVzcG9uc2Uuc3VjY2Vzcyl7XG4gICAgICAgICAgdGhpcy50YWJsZURhdGFTb3VyY2UgPSBuZXcgTWF0VGFibGVEYXRhU291cmNlKGFwaVJlc3BvbnNlLmRhdGEpO1xuICAgICAgICAgIHRoaXMudGFibGVEYXRhU291cmNlLnBhZ2luYXRvciA9IHRoaXMudGFibGVQYWdpbmF0b3I7XG4gICAgICAgIH1lbHNle1xuICAgICAgICAgIHRoaXMubWVzc2FnZVNlcnZpY2UudG9hc3QoXCJFcnJvcjogXCIgKyBKU09OLnN0cmluZ2lmeShhcGlSZXNwb25zZSkpO1xuICAgICAgICB9XG5cbiAgICAgIH0pO1xuICAgIH1cblxuICB9XG5cbiAgZm9ybURlZmF1bHRzKCl7XG5cbiAgICBpZiAoIXRoaXMuY29uZmlnLmZvcm1Db25maWcpe1xuICAgICAgbGV0IGNvbmZpZyA9IG5ldyBGb3JtQ29uZmlnXG5cbiAgICAgIGNvbmZpZy5maWVsZHMgPSBbXVxuXG4gICAgICB0aGlzLmNvbmZpZy5jb2x1bW5zLmZvckVhY2goY29sdW1uID0+IHtcblxuICAgICAgICBsZXQgZmllbGQgPSB7bmFtZTogY29sdW1uLm5hbWUsIHR5cGU6IGNvbHVtbi50eXBlfVxuICAgICAgICBjb25maWcuZmllbGRzLnB1c2goZmllbGQpXG5cbiAgICAgIH0pO1xuXG4gICAgICB0aGlzLmNvbmZpZy5mb3JtQ29uZmlnID0gY29uZmlnO1xuICAgIH1cbiAgfVxuXG59XG4iLCJcbjxkaXYgY2xhc3M9XCJ0b3BcIj5cblxuICA8ZGl2ID5cbiAgICA8IS0tIDxidXR0b24gKm5nSWY9XCJjb25maWcubmV3VGV4dFwiIGlkPVwiYnRuTmV3XCIgbWF0LXJhaXNlZC1idXR0b24gY29sb3I9XCJwcmltYXJ5XCIgKGNsaWNrKT1cIm5ld01vZGVsKClcIj57e2NvbmZpZy5uZXdUZXh0fX08L2J1dHRvbj4gLS0+XG4gICAgPGJ1dHRvbiAqbmdJZj1cImNyZWF0ZUJ1dHRvblwiIGlkPVwiYnRuTmV3XCIgbWF0LXJhaXNlZC1idXR0b24gY29sb3I9XCJwcmltYXJ5XCIgKGNsaWNrKT1cIm5ld01vZGVsKClcIj57e2NyZWF0ZUJ1dHRvbi5kaXNwbGF5fX08L2J1dHRvbj5cbiAgPC9kaXY+XG5cbiAgPGRpdiAqbmdJZj1cImNvbmZpZy5zaG93RmlsdGVyXCIgY2xhc3M9XCJkLWZsZXgganVzdGlmeS1jb250ZW50LWVuZFwiPlxuICAgIDxzcGEtZmlsdGVyIFtkYXRhXT1cInRhYmxlRGF0YVNvdXJjZVwiIChyZWZyZXNoQ2xpY2spPVwicmVmcmVzaENsaWNrZWQoKVwiPjwvc3BhLWZpbHRlcj5cbiAgPC9kaXY+XG5cbjwvZGl2PlxuXG48ZGl2PlxuXG4gIDxwICpuZ0lmPVwiIWNvbmZpZ1wiPjxlbT5Db25maWd1cmUgVGFibGU8L2VtPjwvcD5cbiAgPHAgKm5nSWY9XCIhZGF0YVNvdXJjZVwiPjxlbT5Mb2FkaW5nLi4uPC9lbT48L3A+XG5cblxuXG4gIDxkaXYgKm5nSWY9XCJkYXRhU291cmNlXCI+XG5cblxuICAgIDx0YWJsZSBtYXQtdGFibGUgW2RhdGFTb3VyY2VdPVwidGFibGVEYXRhU291cmNlXCIgY2xhc3M9XCJtYXQtZWxldmF0aW9uLXo4XCI+XG4gICAgICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCBjb2x1bW4gb2YgY29uZmlnLmNvbHVtbnNcIiBbbWF0Q29sdW1uRGVmXT1cImNvbHVtbi5uYW1lXCI+XG4gICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+e3sgY29sdW1uLm5hbWUgfCBjYW1lbFRvV29yZHMgfX08L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93O1wiID5cblxuICAgICAgICAgIDxuZy1jb250YWluZXIgW25nU3dpdGNoXT1cImNvbHVtbi50eXBlXCI+XG5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidjaGVja2JveCdcIj5cbiAgICAgICAgICAgICAgPHNwYS1jaGVjayBbdmFsdWVdPVwicm93W2NvbHVtbi5uYW1lXVwiIFtyZWFkb25seV09XCJ0cnVlXCI+PC9zcGEtY2hlY2s+XG4gICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cblxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdTd2l0Y2hDYXNlPVwiJ2RhdGUnXCI+XG4gICAgICAgICAgICAgIHt7cm93W2NvbHVtbi5uYW1lXSB8IGRhdGUgOiAnZGQvTU0veXl5eSd9fVxuICAgICAgICAgICAgICA8bWF0LWljb24gKm5nSWY9XCJjb2x1bW4uaWNvbiAmJiB0ZXN0SWNvbkNvbmRpdGlvbihjb2x1bW4ubmFtZSwgcm93KVwiIFttYXRUb29sdGlwXT1cImNvbHVtbi5pY29uPy50aXBcIiBtYXRUb29sdGlwUG9zaXRpb249XCJhYm92ZVwiIFtuZ1N0eWxlXT1cInsnY29sb3InOmNvbHVtbi5pY29uPy5jb2xvcn1cIj57e2NvbHVtbi5pY29uLm5hbWUgfX08L21hdC1pY29uPlxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoQ2FzZT1cIidtb25leSdcIj5cbiAgICAgICAgICAgICAge3tyb3dbY29sdW1uLm5hbWVdIHwgY3VycmVuY3k6Jyc6Jyd9fVxuICAgICAgICAgICAgICA8bWF0LWljb24gKm5nSWY9XCJjb2x1bW4uaWNvbiAmJiB0ZXN0SWNvbkNvbmRpdGlvbihjb2x1bW4ubmFtZSwgcm93KVwiIFttYXRUb29sdGlwXT1cImNvbHVtbi5pY29uPy50aXBcIiBtYXRUb29sdGlwUG9zaXRpb249XCJhYm92ZVwiIFtuZ1N0eWxlXT1cInsnY29sb3InOmNvbHVtbi5pY29uPy5jb2xvcn1cIj57e2NvbHVtbi5pY29uLm5hbWUgfX08L21hdC1pY29uPlxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nU3dpdGNoRGVmYXVsdD5cbiAgICAgICAgICAgICAgPGxhYmVsPnt7cm93W2NvbHVtbi5uYW1lXX19PC9sYWJlbD5cbiAgICAgICAgICAgICAgPG1hdC1pY29uICpuZ0lmPVwiY29sdW1uLmljb24gJiYgdGVzdEljb25Db25kaXRpb24oY29sdW1uLm5hbWUsIHJvdylcIiBbbWF0VG9vbHRpcF09XCJjb2x1bW4uaWNvbj8udGlwXCIgbWF0VG9vbHRpcFBvc2l0aW9uPVwiYWJvdmVcIiBbbmdTdHlsZV09XCJ7J2NvbG9yJzpjb2x1bW4uaWNvbj8uY29sb3J9XCI+e3tjb2x1bW4uaWNvbi5uYW1lIH19PC9tYXQtaWNvbj5cbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuXG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XG5cblxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cbiAgICAgIDxuZy1jb250YWluZXIgbWF0Q29sdW1uRGVmPVwiYWN0aW9uXCI+XG4gICAgICAgIDx0aCBtYXQtaGVhZGVyLWNlbGwgKm1hdEhlYWRlckNlbGxEZWY+IEFjdGlvbiA8L3RoPlxuICAgICAgICA8dGQgbWF0LWNlbGwgKm1hdENlbGxEZWY9XCJsZXQgcm93XCIgW25nU3R5bGVdPVwie3dpZHRoOnNtYWxsU2NyZWVuID8gJzUwcHgnIDogYWN0aW9uc1dpZHRofVwiPlxuXG5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1taW5pLWZhYiBjb2xvcj1cInByaW1hcnlcIiBbbWF0VG9vbHRpcF09XCJ2aWV3QnV0dG9uLnRpcCA/PyAndmlldycgXCIgbWF0VG9vbHRpcFBvc2l0aW9uPVwiYWJvdmVcIiBzdHlsZT1cIm1hcmdpbi1yaWdodDo1cHhcIiBbbmdTdHlsZV09XCJ7J2JhY2tncm91bmQtY29sb3InOnZpZXdCdXR0b24uY29sb3J9XCIgW2Rpc2FibGVkXT1cInRlc3REaXNhYmxlZChyb3csJ3ZpZXcnKVwiICpuZ0lmPVwidmlld0J1dHRvbiAmJiB0ZXN0VmlzaWJsZShyb3csJ3ZpZXcnKVwiIChjbGljayk9XCJ2aWV3TW9kZWwocm93KVwiPlxuICAgICAgICAgICAgPG1hdC1pY29uPnt7Z2V0SWNvbigndmlldycpfX08L21hdC1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgPGJ1dHRvbiBtYXQtbWluaS1mYWIgY29sb3I9XCJwcmltYXJ5XCIgW21hdFRvb2x0aXBdPVwiY3VzdG9tMUJ1dHRvbi50aXAgPz8gJ2N1c3RvbTEnIFwiIG1hdFRvb2x0aXBQb3NpdGlvbj1cImFib3ZlXCIgc3R5bGU9XCJtYXJnaW4tcmlnaHQ6NXB4XCIgW25nU3R5bGVdPVwieydiYWNrZ3JvdW5kLWNvbG9yJzpjdXN0b20xQnV0dG9uLmNvbG9yfVwiIFtkaXNhYmxlZF09XCJ0ZXN0RGlzYWJsZWQocm93LCdjdXN0b20xJylcIiAqbmdJZj1cIiFzbWFsbFNjcmVlbiAmJiBjdXN0b20xQnV0dG9uICYmIHRlc3RWaXNpYmxlKHJvdywnY3VzdG9tMScpXCIgKGNsaWNrKT1cImN1c3RvbTEocm93KVwiPlxuICAgICAgICAgICAgPG1hdC1pY29uPnt7Z2V0SWNvbignY3VzdG9tMScpfX08L21hdC1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgPGJ1dHRvbiBtYXQtbWluaS1mYWIgY29sb3I9XCJwcmltYXJ5XCIgW21hdFRvb2x0aXBdPVwiY3VzdG9tMkJ1dHRvbi50aXAgPz8gJ2N1c3RvbTInIFwiIG1hdFRvb2x0aXBQb3NpdGlvbj1cImFib3ZlXCIgc3R5bGU9XCJtYXJnaW4tcmlnaHQ6NXB4XCIgW25nU3R5bGVdPVwieydiYWNrZ3JvdW5kLWNvbG9yJzpjdXN0b20yQnV0dG9uLmNvbG9yfVwiIFtkaXNhYmxlZF09XCJ0ZXN0RGlzYWJsZWQocm93LCdjdXN0b20yJylcIiAqbmdJZj1cIiFzbWFsbFNjcmVlbiAmJiBjdXN0b20yQnV0dG9uICYmIHRlc3RWaXNpYmxlKHJvdywnY3VzdG9tMicpXCIgKGNsaWNrKT1cImN1c3RvbTIocm93KVwiPlxuICAgICAgICAgICAgPG1hdC1pY29uPnt7Z2V0SWNvbignY3VzdG9tMicpfX08L21hdC1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPlxuXG4gICAgICAgICAgPGJ1dHRvbiBtYXQtbWluaS1mYWIgY29sb3I9XCJwcmltYXJ5XCIgW21hdFRvb2x0aXBdPVwiY3VzdG9tM0J1dHRvbi50aXAgPz8gJ2N1c3RvbTMnIFwiIG1hdFRvb2x0aXBQb3NpdGlvbj1cImFib3ZlXCIgc3R5bGU9XCJtYXJnaW4tcmlnaHQ6NXB4XCIgW25nU3R5bGVdPVwieydiYWNrZ3JvdW5kLWNvbG9yJzpjdXN0b20zQnV0dG9uLmNvbG9yfVwiIFtkaXNhYmxlZF09XCJ0ZXN0RGlzYWJsZWQocm93LCdjdXN0b20zJylcIiAqbmdJZj1cIiFzbWFsbFNjcmVlbiAmJiBjdXN0b20zQnV0dG9uICYmIHRlc3RWaXNpYmxlKHJvdywnY3VzdG9tMycpXCIgKGNsaWNrKT1cImN1c3RvbTMocm93KVwiPlxuICAgICAgICAgICAgPG1hdC1pY29uPnt7Z2V0SWNvbignY3VzdG9tMycpfX08L21hdC1pY29uPlxuICAgICAgICAgIDwvYnV0dG9uPlxuXG5cbiAgICAgICAgICA8YnV0dG9uIG1hdC1taW5pLWZhYiBjb2xvcj1cInByaW1hcnlcIiBbbWF0VG9vbHRpcF09XCJlZGl0QnV0dG9uLnRpcCA/PyAnZWRpdCcgXCIgbWF0VG9vbHRpcFBvc2l0aW9uPVwiYWJvdmVcIiBzdHlsZT1cIm1hcmdpbi1yaWdodDo1cHhcIiBbbmdTdHlsZV09XCJ7J2JhY2tncm91bmQtY29sb3InOmVkaXRCdXR0b24uY29sb3J9XCIgW2Rpc2FibGVkXT1cInRlc3REaXNhYmxlZChyb3csJ2VkaXQnKVwiICpuZ0lmPVwiIXNtYWxsU2NyZWVuICYmIGVkaXRCdXR0b24gJiYgdGVzdFZpc2libGUocm93LCdlZGl0JylcIiAoY2xpY2spPVwiZWRpdE1vZGVsKHJvdylcIj5cbiAgICAgICAgICAgIDxtYXQtaWNvbj57e2dldEljb24oJ2VkaXQnKX19PC9tYXQtaWNvbj5cbiAgICAgICAgICA8L2J1dHRvbj5cblxuICAgICAgICAgIDxidXR0b24gbWF0LW1pbmktZmFiIGNvbG9yPVwid2FyblwiIFttYXRUb29sdGlwXT1cImRlbGV0ZUJ1dHRvbi50aXAgPz8gJ2RlbGV0ZScgXCIgbWF0VG9vbHRpcFBvc2l0aW9uPVwiYWJvdmVcIiBzdHlsZT1cIm1hcmdpbi1yaWdodDo1cHhcIiBbbmdTdHlsZV09XCJ7J2JhY2tncm91bmQtY29sb3InOmRlbGV0ZUJ1dHRvbi5jb2xvcn1cIiBbZGlzYWJsZWRdPVwidGVzdERpc2FibGVkKHJvdywnZGVsZXRlJylcIiAqbmdJZj1cIiFzbWFsbFNjcmVlbiAmJiBkZWxldGVCdXR0b24gJiYgdGVzdFZpc2libGUocm93LCdkZWxldGUnKVwiIChjbGljayk9XCJkZWxldGVNb2RlbChyb3cpXCI+XG4gICAgICAgICAgICA8bWF0LWljb24+e3tnZXRJY29uKCdkZWxldGUnKX19PC9tYXQtaWNvbj5cbiAgICAgICAgICA8L2J1dHRvbj5cblxuICAgICAgICA8L3RkPlxuICAgICAgPC9uZy1jb250YWluZXI+XG5cblxuICAgICAgPHRyIG1hdC1oZWFkZXItcm93ICptYXRIZWFkZXJSb3dEZWY9XCJkaXNwbGF5ZWRDb2x1bW5zXCI+PC90cj5cbiAgICAgIDx0ciBtYXQtcm93ICptYXRSb3dEZWY9XCJsZXQgcm93OyBjb2x1bW5zOiBkaXNwbGF5ZWRDb2x1bW5zO1wiPjwvdHI+XG4gICAgPC90YWJsZT5cblxuICA8L2Rpdj5cblxuICA8bWF0LXBhZ2luYXRvciAjdGFibGVQYWdpbmF0b3IgW3BhZ2VTaXplT3B0aW9uc109XCJbMTAsIDIwLCA1MF1cIiBzaG93Rmlyc3RMYXN0QnV0dG9ucz48L21hdC1wYWdpbmF0b3I+XG5cbjwvZGl2PlxuXG48cCAqbmdJZj1cImRhdGFTb3VyY2U/Lmxlbmd0aCA9PSAwXCI+PGVtPk5vIERhdGE8L2VtPjwvcD5cblxuXG4iXX0=