@firestitch/report 18.9.0 → 18.10.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 (190) hide show
  1. package/app/reports/anchor-at-point.d.ts +14 -0
  2. package/app/reports/canvas-landing-page.d.ts +2 -0
  3. package/app/reports/components/component-chart/component-chart.component.d.ts +18 -2
  4. package/app/reports/components/component-kpi/component-kpi.component.d.ts +4 -1
  5. package/app/reports/components/report-canvas/report-canvas.component.d.ts +3 -0
  6. package/app/reports/components/report-component/report-component.component.d.ts +35 -1
  7. package/app/reports/components/report-view-picker/report-view-picker.component.d.ts +21 -0
  8. package/app/reports/data/report.data.d.ts +17 -2
  9. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +18 -3
  10. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +15 -6
  11. package/app/reports/dialogs/report-view/report-view-dialog.component.d.ts +13 -0
  12. package/app/reports/drill-crumbs.d.ts +12 -0
  13. package/app/reports/export/report-export-collector.service.d.ts +13 -4
  14. package/app/reports/export/report-filter-lines.d.ts +18 -0
  15. package/app/reports/filter-settings-rules.d.ts +33 -0
  16. package/app/reports/format.d.ts +0 -1
  17. package/app/reports/interfaces/canvas-landing-input.interface.d.ts +8 -0
  18. package/app/reports/interfaces/component-data-applied.interface.d.ts +13 -0
  19. package/app/reports/interfaces/component-data-drill.interface.d.ts +22 -0
  20. package/app/reports/interfaces/filter-bar-placement.type.d.ts +1 -0
  21. package/app/reports/interfaces/filter-component-toggle-state.interface.d.ts +4 -0
  22. package/app/reports/interfaces/filter-settings-option.interface.d.ts +4 -0
  23. package/app/reports/interfaces/filter-type-select-state.interface.d.ts +5 -0
  24. package/app/reports/interfaces/report-chart-hit.interface.d.ts +5 -0
  25. package/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.d.ts +4 -0
  26. package/app/reports/interfaces/report-chat-viewer-cross-filter.interface.d.ts +7 -0
  27. package/app/reports/interfaces/report-chat-viewer-detail.interface.d.ts +4 -0
  28. package/app/reports/interfaces/report-chat-viewer-drill-step.interface.d.ts +5 -0
  29. package/app/reports/interfaces/report-chat-viewer-drill.interface.d.ts +5 -0
  30. package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +3 -0
  31. package/app/reports/interfaces/report-chat-viewer-selection.interface.d.ts +5 -0
  32. package/app/reports/interfaces/report-chat-viewer-state.interface.d.ts +12 -0
  33. package/app/reports/interfaces/report-drill-crumb.interface.d.ts +6 -0
  34. package/app/reports/interfaces/report-drill-refusal.type.d.ts +1 -0
  35. package/app/reports/interfaces/report-drill-step.interface.d.ts +5 -0
  36. package/app/reports/interfaces/report-export-line-kind.type.d.ts +1 -0
  37. package/app/reports/interfaces/report-export-line.interface.d.ts +8 -0
  38. package/app/reports/interfaces/report-export-lines-input.interface.d.ts +9 -0
  39. package/app/reports/interfaces/report-export-snapshot.interface.d.ts +15 -0
  40. package/app/reports/interfaces/report-filter-line-context.interface.d.ts +8 -0
  41. package/app/reports/interfaces/report-filter-line-form.type.d.ts +1 -0
  42. package/app/reports/interfaces/report-filter-match.type.d.ts +1 -0
  43. package/app/reports/interfaces/report-filter-option-pair.interface.d.ts +4 -0
  44. package/app/reports/interfaces/report-filter-options-ask.interface.d.ts +6 -0
  45. package/app/reports/interfaces/report-filter-options-list.interface.d.ts +7 -0
  46. package/app/reports/interfaces/report-filter-options-request.interface.d.ts +6 -0
  47. package/app/reports/interfaces/report-filter-options-stream.interface.d.ts +11 -0
  48. package/app/reports/interfaces/report-filter-options.interface.d.ts +7 -0
  49. package/app/reports/interfaces/report-filter-skip.type.d.ts +1 -0
  50. package/app/reports/interfaces/report-mark-action.type.d.ts +1 -0
  51. package/app/reports/interfaces/report-mark-click.interface.d.ts +13 -0
  52. package/app/reports/interfaces/report-mark-context.interface.d.ts +6 -0
  53. package/app/reports/interfaces/report-mark-decision.interface.d.ts +6 -0
  54. package/app/reports/interfaces/report-mark-event.interface.d.ts +11 -0
  55. package/app/reports/interfaces/report-mark-point.interface.d.ts +8 -0
  56. package/app/reports/interfaces/report-temporary-state.interface.d.ts +4 -0
  57. package/app/reports/interfaces/report-tile-state.interface.d.ts +8 -0
  58. package/app/reports/interfaces/report-url-link.interface.d.ts +4 -0
  59. package/app/reports/interfaces/report-url-value-name.type.d.ts +1 -0
  60. package/app/reports/interfaces/report-url-write.interface.d.ts +4 -0
  61. package/app/reports/interfaces/report-view-config.interface.d.ts +11 -0
  62. package/app/reports/interfaces/report-view-create.interface.d.ts +7 -0
  63. package/app/reports/interfaces/report-view-deleted.interface.d.ts +4 -0
  64. package/app/reports/interfaces/report-view-dialog-data.interface.d.ts +7 -0
  65. package/app/reports/interfaces/report-view-dropped.interface.d.ts +5 -0
  66. package/app/reports/interfaces/report-view-menu-item.interface.d.ts +10 -0
  67. package/app/reports/interfaces/report-view-summary.interface.d.ts +11 -0
  68. package/app/reports/interfaces/report-view.interface.d.ts +7 -0
  69. package/app/reports/interfaces/report-viewer-feature.type.d.ts +1 -0
  70. package/app/reports/interfaces/report-views.interface.d.ts +7 -0
  71. package/app/reports/interfaces/report.interface.d.ts +27 -3
  72. package/app/reports/interfaces/tile-load-result.interface.d.ts +4 -0
  73. package/app/reports/mark-click.d.ts +20 -0
  74. package/app/reports/option-builder.d.ts +12 -1
  75. package/app/reports/report-chat-viewer-state.d.ts +8 -0
  76. package/app/reports/report-date-presets.d.ts +2 -0
  77. package/app/reports/report-filter-items.d.ts +27 -22
  78. package/app/reports/report-tile.d.ts +2 -0
  79. package/app/reports/report-url-state.d.ts +27 -10
  80. package/app/reports/report-view-config.d.ts +36 -0
  81. package/app/reports/report-view-menu.d.ts +15 -0
  82. package/app/reports/report-viewer-features.d.ts +5 -0
  83. package/app/reports/services/report-filter-options.service.d.ts +26 -0
  84. package/app/reports/services/report-filter-state.service.d.ts +64 -1
  85. package/app/reports/services/report-view.service.d.ts +51 -0
  86. package/app/reports/tile-data-state.d.ts +7 -0
  87. package/app/reports/tile-loads.d.ts +4 -0
  88. package/app/reports/views/report/fs-ai-report.component.d.ts +9 -1
  89. package/app/reports/views/report/report.component.d.ts +6 -0
  90. package/esm2022/app/reports/anchor-at-point.mjs +49 -0
  91. package/esm2022/app/reports/canvas-landing-page.mjs +25 -0
  92. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +97 -5
  93. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +11 -4
  94. package/esm2022/app/reports/components/component-list/component-list.component.mjs +7 -1
  95. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +47 -32
  96. package/esm2022/app/reports/components/report-component/report-component.component.mjs +257 -61
  97. package/esm2022/app/reports/components/report-view-picker/report-view-picker.component.mjs +115 -0
  98. package/esm2022/app/reports/data/report.data.mjs +87 -10
  99. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +106 -51
  100. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +86 -90
  101. package/esm2022/app/reports/dialogs/report-view/report-view-dialog.component.mjs +52 -0
  102. package/esm2022/app/reports/drill-crumbs.mjs +73 -0
  103. package/esm2022/app/reports/export/report-export-collector.service.mjs +187 -117
  104. package/esm2022/app/reports/export/report-filter-lines.mjs +235 -0
  105. package/esm2022/app/reports/export/report-pdf.service.mjs +12 -7
  106. package/esm2022/app/reports/export/report-pptx.service.mjs +18 -14
  107. package/esm2022/app/reports/filter-settings-rules.mjs +283 -0
  108. package/esm2022/app/reports/format.mjs +2 -22
  109. package/esm2022/app/reports/interfaces/canvas-landing-input.interface.mjs +2 -0
  110. package/esm2022/app/reports/interfaces/component-data-applied.interface.mjs +2 -0
  111. package/esm2022/app/reports/interfaces/component-data-drill.interface.mjs +2 -0
  112. package/esm2022/app/reports/interfaces/filter-bar-placement.type.mjs +2 -0
  113. package/esm2022/app/reports/interfaces/filter-component-toggle-state.interface.mjs +2 -0
  114. package/esm2022/app/reports/interfaces/filter-settings-option.interface.mjs +2 -0
  115. package/esm2022/app/reports/interfaces/filter-type-select-state.interface.mjs +2 -0
  116. package/esm2022/app/reports/interfaces/report-chart-hit.interface.mjs +2 -0
  117. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter-field.interface.mjs +2 -0
  118. package/esm2022/app/reports/interfaces/report-chat-viewer-cross-filter.interface.mjs +2 -0
  119. package/esm2022/app/reports/interfaces/report-chat-viewer-detail.interface.mjs +2 -0
  120. package/esm2022/app/reports/interfaces/report-chat-viewer-drill-step.interface.mjs +2 -0
  121. package/esm2022/app/reports/interfaces/report-chat-viewer-drill.interface.mjs +2 -0
  122. package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
  123. package/esm2022/app/reports/interfaces/report-chat-viewer-selection.interface.mjs +2 -0
  124. package/esm2022/app/reports/interfaces/report-chat-viewer-state.interface.mjs +1 -1
  125. package/esm2022/app/reports/interfaces/report-drill-crumb.interface.mjs +2 -0
  126. package/esm2022/app/reports/interfaces/report-drill-refusal.type.mjs +2 -0
  127. package/esm2022/app/reports/interfaces/report-drill-step.interface.mjs +2 -0
  128. package/esm2022/app/reports/interfaces/report-export-line-kind.type.mjs +2 -0
  129. package/esm2022/app/reports/interfaces/report-export-line.interface.mjs +2 -0
  130. package/esm2022/app/reports/interfaces/report-export-lines-input.interface.mjs +2 -0
  131. package/esm2022/app/reports/interfaces/report-export-snapshot.interface.mjs +2 -0
  132. package/esm2022/app/reports/interfaces/report-filter-line-context.interface.mjs +2 -0
  133. package/esm2022/app/reports/interfaces/report-filter-line-form.type.mjs +2 -0
  134. package/esm2022/app/reports/interfaces/report-filter-match.type.mjs +2 -0
  135. package/esm2022/app/reports/interfaces/report-filter-option-pair.interface.mjs +2 -0
  136. package/esm2022/app/reports/interfaces/report-filter-options-ask.interface.mjs +2 -0
  137. package/esm2022/app/reports/interfaces/report-filter-options-list.interface.mjs +2 -0
  138. package/esm2022/app/reports/interfaces/report-filter-options-request.interface.mjs +2 -0
  139. package/esm2022/app/reports/interfaces/report-filter-options-stream.interface.mjs +2 -0
  140. package/esm2022/app/reports/interfaces/report-filter-options.interface.mjs +2 -0
  141. package/esm2022/app/reports/interfaces/report-filter-skip.type.mjs +2 -0
  142. package/esm2022/app/reports/interfaces/report-mark-action.type.mjs +2 -0
  143. package/esm2022/app/reports/interfaces/report-mark-click.interface.mjs +2 -0
  144. package/esm2022/app/reports/interfaces/report-mark-context.interface.mjs +2 -0
  145. package/esm2022/app/reports/interfaces/report-mark-decision.interface.mjs +2 -0
  146. package/esm2022/app/reports/interfaces/report-mark-event.interface.mjs +2 -0
  147. package/esm2022/app/reports/interfaces/report-mark-point.interface.mjs +2 -0
  148. package/esm2022/app/reports/interfaces/report-temporary-state.interface.mjs +2 -0
  149. package/esm2022/app/reports/interfaces/report-tile-state.interface.mjs +2 -0
  150. package/esm2022/app/reports/interfaces/report-url-link.interface.mjs +2 -0
  151. package/esm2022/app/reports/interfaces/report-url-value-name.type.mjs +2 -0
  152. package/esm2022/app/reports/interfaces/report-url-write.interface.mjs +2 -0
  153. package/esm2022/app/reports/interfaces/report-view-config.interface.mjs +2 -0
  154. package/esm2022/app/reports/interfaces/report-view-create.interface.mjs +2 -0
  155. package/esm2022/app/reports/interfaces/report-view-deleted.interface.mjs +2 -0
  156. package/esm2022/app/reports/interfaces/report-view-dialog-data.interface.mjs +2 -0
  157. package/esm2022/app/reports/interfaces/report-view-dropped.interface.mjs +2 -0
  158. package/esm2022/app/reports/interfaces/report-view-menu-item.interface.mjs +2 -0
  159. package/esm2022/app/reports/interfaces/report-view-summary.interface.mjs +2 -0
  160. package/esm2022/app/reports/interfaces/report-view.interface.mjs +2 -0
  161. package/esm2022/app/reports/interfaces/report-viewer-feature.type.mjs +2 -0
  162. package/esm2022/app/reports/interfaces/report-views.interface.mjs +2 -0
  163. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  164. package/esm2022/app/reports/interfaces/tile-load-result.interface.mjs +2 -0
  165. package/esm2022/app/reports/mark-click.mjs +193 -0
  166. package/esm2022/app/reports/option-builder.mjs +159 -15
  167. package/esm2022/app/reports/report-chat-viewer-state.mjs +34 -0
  168. package/esm2022/app/reports/report-date-presets.mjs +18 -0
  169. package/esm2022/app/reports/report-filter-items.mjs +343 -72
  170. package/esm2022/app/reports/report-tile.mjs +12 -0
  171. package/esm2022/app/reports/report-url-state.mjs +596 -108
  172. package/esm2022/app/reports/report-view-config.mjs +697 -0
  173. package/esm2022/app/reports/report-view-menu.mjs +119 -0
  174. package/esm2022/app/reports/report-viewer-features.mjs +42 -0
  175. package/esm2022/app/reports/services/report-filter-options.service.mjs +238 -0
  176. package/esm2022/app/reports/services/report-filter-state.service.mjs +697 -62
  177. package/esm2022/app/reports/services/report-view.service.mjs +358 -0
  178. package/esm2022/app/reports/tile-data-state.mjs +127 -0
  179. package/esm2022/app/reports/tile-loads.mjs +38 -0
  180. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +177 -46
  181. package/esm2022/app/reports/views/report/report.component.mjs +103 -23
  182. package/esm2022/public_api.mjs +23 -1
  183. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs → firestitch-report-echarts-UBg8Wlhd.mjs} +2 -2
  184. package/fesm2022/{firestitch-report-echarts-DBMOHmBF.mjs.map → firestitch-report-echarts-UBg8Wlhd.mjs.map} +1 -1
  185. package/fesm2022/{firestitch-report-firestitch-report-CqbXT1gh.mjs → firestitch-report-firestitch-report-B1keNrcK.mjs} +9063 -4272
  186. package/fesm2022/firestitch-report-firestitch-report-B1keNrcK.mjs.map +1 -0
  187. package/fesm2022/firestitch-report.mjs +1 -1
  188. package/package.json +1 -1
  189. package/public_api.d.ts +22 -0
  190. package/fesm2022/firestitch-report-firestitch-report-CqbXT1gh.mjs.map +0 -1
@@ -0,0 +1,119 @@
1
+ export const VIEWS_LABEL = 'Views';
2
+ export const EDITED_TOOLTIP = 'The screen differs from this view';
3
+ export const SAVE_AS_TITLE = 'Save as new view';
4
+ export const RENAME_TITLE = 'Rename view';
5
+ export const CROSS_FILTER_NOTE = 'Cross-filters are temporary and are not saved.';
6
+ export const VIEW_NAME_BLANK = 'Enter a name';
7
+ // The server's limit on a view's name.
8
+ export const VIEW_NAME_MAX_LENGTH = 100;
9
+ // The menu for the open view (null when none is open), the views the viewer
10
+ // may see, whether the screen differs from the open view, and whether the
11
+ // viewer may share its views.
12
+ export function viewMenuItems(open, views, edited, canShare) {
13
+ const rows = [
14
+ ...views.filter((view) => view.mine),
15
+ ...views.filter((view) => !view.mine),
16
+ ].map((view) => viewRow(view, open, edited));
17
+ const actions = openViewActions(open, edited, canShare);
18
+ const resets = [
19
+ ...(open && edited ? [action('resetToView', `Reset to "${open.name}"`)] : []),
20
+ action('resetToDefaults', 'Reset to report defaults'),
21
+ ];
22
+ return [
23
+ ...rows,
24
+ ...withDivider(actions, rows.length > 0),
25
+ ...withDivider(resets, true),
26
+ ];
27
+ }
28
+ // The picker's label: 'Views', or the open view's name, marked while the
29
+ // screen differs from it.
30
+ export function pickerLabel(open, edited) {
31
+ if (!open) {
32
+ return VIEWS_LABEL;
33
+ }
34
+ return edited ? `${open.name} (edited)` : open.name;
35
+ }
36
+ // The picker's tooltip: only while the screen differs from the open view.
37
+ export function pickerTooltip(open, edited) {
38
+ return open && edited ? EDITED_TOOLTIP : null;
39
+ }
40
+ // The question before a view is deleted. A shared view says that everyone
41
+ // loses it.
42
+ export function deletePromptText(view) {
43
+ const question = `Delete the view "${view.name}"?`;
44
+ return view.shared ? `${question} Everyone it is shared with loses it.` : question;
45
+ }
46
+ // The line the save dialog shows under the name, or null: a cross-filter is
47
+ // on, and it does not go into the view.
48
+ export function saveDialogNote(hasCrossFilter) {
49
+ return hasCrossFilter ? CROSS_FILTER_NOTE : null;
50
+ }
51
+ // A name made of spaces only is no name; the server trims it.
52
+ export function viewNameError(name) {
53
+ return (name ?? '').trim() ? null : VIEW_NAME_BLANK;
54
+ }
55
+ function viewRow(view, open, edited) {
56
+ const isOpen = view.id === open?.id;
57
+ return {
58
+ kind: 'view',
59
+ label: view.name,
60
+ disabled: isOpen && !edited,
61
+ tooltip: viewTooltip(view),
62
+ divider: false,
63
+ viewId: view.id,
64
+ open: isOpen,
65
+ icon: viewIcon(view),
66
+ };
67
+ }
68
+ // Who shared a view of someone else's; whether one of the viewer's own opens
69
+ // by default or is shared.
70
+ function viewTooltip(view) {
71
+ if (!view.mine) {
72
+ return view.ownerName ? `Shared by ${view.ownerName}` : 'Shared with everyone';
73
+ }
74
+ if (view.personalDefault && view.shared) {
75
+ return 'Opens by default, shared with everyone';
76
+ }
77
+ if (view.personalDefault) {
78
+ return 'Opens by default';
79
+ }
80
+ return view.shared ? 'Shared with everyone' : null;
81
+ }
82
+ // The open row keeps this icon too; its check is drawn beside it.
83
+ function viewIcon(view) {
84
+ if (!view.mine) {
85
+ return 'people';
86
+ }
87
+ return view.personalDefault ? 'star' : null;
88
+ }
89
+ // The rows that act on the open view; with none open, only Save as new view.
90
+ function openViewActions(open, edited, canShare) {
91
+ const items = [];
92
+ if (open?.canChange && edited) {
93
+ items.push(action('saveChanges', 'Save changes'));
94
+ }
95
+ items.push(action('saveAsNew', 'Save as new view...'));
96
+ if (open?.canChange) {
97
+ items.push(action('rename', 'Rename...'));
98
+ }
99
+ if (open?.mine) {
100
+ items.push(open.personalDefault
101
+ ? action('clearDefault', 'Stop opening it by default')
102
+ : action('setDefault', 'Make it my default'));
103
+ }
104
+ if (open?.mine && canShare) {
105
+ items.push(open.shared ? action('unshare', 'Stop sharing') : action('share', 'Share with everyone'));
106
+ }
107
+ if (open?.canDelete) {
108
+ items.push(action('delete', 'Delete...'));
109
+ }
110
+ return items;
111
+ }
112
+ function action(kind, label) {
113
+ return { kind, label, disabled: false, tooltip: null, divider: false, viewId: null, open: false, icon: null };
114
+ }
115
+ // The same rows, the first with a line above it when `divider` is set.
116
+ function withDivider(items, divider) {
117
+ return items.map((item, index) => (index === 0 && divider ? { ...item, divider: true } : item));
118
+ }
119
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXZpZXctbWVudS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9yZXBvcnQtdmlldy1tZW51LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQW9CQSxNQUFNLENBQUMsTUFBTSxXQUFXLEdBQUcsT0FBTyxDQUFDO0FBQ25DLE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxtQ0FBbUMsQ0FBQztBQUNsRSxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQUcsa0JBQWtCLENBQUM7QUFDaEQsTUFBTSxDQUFDLE1BQU0sWUFBWSxHQUFHLGFBQWEsQ0FBQztBQUMxQyxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxnREFBZ0QsQ0FBQztBQUNsRixNQUFNLENBQUMsTUFBTSxlQUFlLEdBQUcsY0FBYyxDQUFDO0FBRTlDLHVDQUF1QztBQUN2QyxNQUFNLENBQUMsTUFBTSxvQkFBb0IsR0FBRyxHQUFHLENBQUM7QUFHeEMsNEVBQTRFO0FBQzVFLDBFQUEwRTtBQUMxRSw4QkFBOEI7QUFDOUIsTUFBTSxVQUFVLGFBQWEsQ0FDM0IsSUFBOEIsRUFDOUIsS0FBbUMsRUFDbkMsTUFBZSxFQUNmLFFBQWlCO0lBRWpCLE1BQU0sSUFBSSxHQUFHO1FBQ1gsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO1FBQ3BDLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDO0tBQ3RDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQzdDLE1BQU0sT0FBTyxHQUFHLGVBQWUsQ0FBQyxJQUFJLEVBQUUsTUFBTSxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lB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Ly8gV2hhdCB0aGUgVmlld3MgcGlja2VyIHNob3dzOiBpdHMgbGFiZWwsIGl0cyBtZW51IGFuZCB0aGUgd29yZHMgb2YgaXRzXG4vLyBwcm9tcHRzLiBQdXJlLCBzbyB0aGUgbm9kZSBoYXJuZXNzIHJ1bnMgZXZlcnkgY2FzZTsgdGhlIHBpY2tlclxuLy8gKFJlcG9ydFZpZXdQaWNrZXJDb21wb25lbnQpIG9ubHkgZHJhd3MgdGhlIHJvd3MgYW5kIHJ1bnMgdGhlIG9uZSBjbGlja2VkLlxuLy9cbi8vIFRoZSBtZW51LCB0b3AgdG8gYm90dG9tOlxuLy8gLSBUaGUgdmlld2VyJ3Mgb3duIHZpZXdzLCB0aGVuIHRoZSB2aWV3cyBvdGhlcnMgc2hhcmUgKGEgcGVvcGxlIGljb24gYW5kXG4vLyAgICdTaGFyZWQgYnkgPG5hbWU+JykuIFRoZSBvcGVuIHZpZXcgaGFzIGEgY2hlY2sgYmVzaWRlIGl0cyBvd24gaWNvbiBhbmRcbi8vICAgY2Fubm90IGJlIHBpY2tlZCBhZ2FpbiB3aGlsZSB0aGUgc2NyZWVuIHN0aWxsIHNob3dzIGl0OyB0aGUgdmlld2VyJ3Ncbi8vICAgZGVmYXVsdCBoYXMgYSBzdGFyLlxuLy8gLSBUaGUgYWN0aW9ucyBvbiB0aGUgb3BlbiB2aWV3LiBTYXZlIGNoYW5nZXMgb25seSB3aGlsZSB0aGUgc2NyZWVuXG4vLyAgIGRpZmZlcnMgZnJvbSBhIHZpZXcgdGhlIHZpZXdlciBtYXkgY2hhbmdlOyBSZW5hbWUgb25seSBvbiBhIHZpZXcgdGhlXG4vLyAgIHZpZXdlciBtYXkgY2hhbmdlOyB0aGUgZGVmYXVsdCBhbmQgc2hhcmluZyByb3dzIG9ubHkgb24gdGhlIHZpZXdlcidzXG4vLyAgIG93biB2aWV3LCBhbmQgc2hhcmluZyBvbmx5IHdoZW4gdGhlIHZpZXdlciBtYXkgc2hhcmU7IERlbGV0ZSBvbmx5IG9uIGFcbi8vICAgdmlldyB0aGUgdmlld2VyIG1heSBkZWxldGUuIFNhdmUgYXMgbmV3IHZpZXcgaXMgYWx3YXlzIHRoZXJlLlxuLy8gLSBSZXNldCB0byB0aGUgb3BlbiB2aWV3IHdoaWxlIHRoZSBzY3JlZW4gZGlmZmVycyBmcm9tIGl0LCBhbmQgUmVzZXQgdG9cbi8vICAgcmVwb3J0IGRlZmF1bHRzLlxuaW1wb3J0IHsgUmVwb3J0Vmlld01lbnVJdGVtIH0gZnJvbSAnLi9pbnRlcmZhY2VzL3JlcG9ydC12aWV3LW1lbnUtaXRlbS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0Vmlld1N1bW1hcnkgfSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LXZpZXctc3VtbWFyeS5pbnRlcmZhY2UnO1xuXG5cbmV4cG9ydCBjb25zdCBWSUVXU19MQUJFTCA9ICdWaWV3cyc7XG5leHBvcnQgY29uc3QgRURJVEVEX1RPT0xUSVAgPSAnVGhlIHNjcmVlbiBkaWZmZXJzIGZyb20gdGhpcyB2aWV3JztcbmV4cG9ydCBjb25zdCBTQVZFX0FTX1RJVExFID0gJ1NhdmUgYXMgbmV3IHZpZXcnO1xuZXhwb3J0IGNvbnN0IFJFTkFNRV9USVRMRSA9ICdSZW5hbWUgdmlldyc7XG5leHBvcnQgY29uc3QgQ1JPU1NfRklMVEVSX05PVEUgPSAnQ3Jvc3MtZmlsdGVycyBhcmUgdGVtcG9yYXJ5IGFuZCBhcmUgbm90IHNhdmVkLic7XG5leHBvcnQgY29uc3QgVklFV19OQU1FX0JMQU5LID0gJ0VudGVyIGEgbmFtZSc7XG5cbi8vIFRoZSBzZXJ2ZXIncyBsaW1pdCBvbiBhIHZpZXcncyBuYW1lLlxuZXhwb3J0IGNvbnN0IFZJRVdfTkFNRV9NQVhfTEVOR1RIID0gMTAwO1xuXG5cbi8vIFRoZSBtZW51IGZvciB0aGUgb3BlbiB2aWV3IChudWxsIHdoZW4gbm9uZSBpcyBvcGVuKSwgdGhlIHZpZXdzIHRoZSB2aWV3ZXJcbi8vIG1heSBzZWUsIHdoZXRoZXIgdGhlIHNjcmVlbiBkaWZmZXJzIGZyb20gdGhlIG9wZW4gdmlldywgYW5kIHdoZXRoZXIgdGhlXG4vLyB2aWV3ZXIgbWF5IHNoYXJlIGl0cyB2aWV3cy5cbmV4cG9ydCBmdW5jdGlvbiB2aWV3TWVudUl0ZW1zKFxuICBvcGVuOiBSZXBvcnRWaWV3U3VtbWFyeSB8IG51bGwsXG4gIHZpZXdzOiByZWFkb25seSBSZXBvcnRWaWV3U3VtbWFyeVtdLFxuICBlZGl0ZWQ6IGJvb2xlYW4sXG4gIGNhblNoYXJlOiBib29sZWFuLFxuKTogUmVwb3J0Vmlld01lbnVJdGVtW10ge1xuICBjb25zdCByb3dzID0gW1xuICAgIC4uLnZpZXdzLmZpbHRlcigodmlldykgPT4gdmlldy5taW5lKSxcbiAgICAuLi52aWV3cy5maWx0ZXIoKHZpZXcpID0+ICF2aWV3Lm1pbmUpLFxuICBdLm1hcCgodmlldykgPT4gdmlld1Jvdyh2aWV3LCBvcGVuLCBlZGl0ZWQpKTtcbiAgY29uc3QgYWN0aW9ucyA9IG9wZW5WaWV3QWN0aW9ucyhvcGVuLCBlZGl0ZWQsIGNhblNoYXJlKTtcbiAgY29uc3QgcmVzZXRzOiBSZXBvcnRWaWV3TWVudUl0ZW1bXSA9IFtcbiAgICAuLi4ob3BlbiAmJiBlZGl0ZWQgPyBbYWN0aW9uKCdyZXNldFRvVmlldycsIGBSZXNldCB0byBcIiR7b3Blbi5uYW1lfVwiYCldIDogW10pLFxuICAgIGFjdGlvbigncmVzZXRUb0RlZmF1bHRzJywgJ1Jlc2V0IHRvIHJlcG9ydCBkZWZhdWx0cycpLFxuICBdO1xuXG4gIHJldHVybiBbXG4gICAgLi4ucm93cyxcbiAgICAuLi53aXRoRGl2aWRlcihhY3Rpb25zLCByb3dzLmxlbmd0aCA+IDApLFxuICAgIC4uLndpdGhEaXZpZGVyKHJlc2V0cywgdHJ1ZSksXG4gIF07XG59XG5cbi8vIFRoZSBwaWNrZXIncyBsYWJlbDogJ1ZpZXdzJywgb3IgdGhlIG9wZW4gdmlldydzIG5hbWUsIG1hcmtlZCB3aGlsZSB0aGVcbi8vIHNjcmVlbiBkaWZmZXJzIGZyb20gaXQuXG5leHBvcnQgZnVuY3Rpb24gcGlja2VyTGFiZWwob3BlbjogUGljazxSZXBvcnRWaWV3U3VtbWFyeSwgJ25hbWUnPiB8IG51bGwsIGVkaXRlZDogYm9vbGVhbik6IHN0cmluZyB7XG4gIGlmICghb3Blbikge1xuICAgIHJldHVybiBWSUVXU19MQUJFTDtcbiAgfVxuXG4gIHJldHVybiBlZGl0ZWQgPyBgJHtvcGVuLm5hbWV9IChlZGl0ZWQpYCA6IG9wZW4ubmFtZTtcbn1cblxuLy8gVGhlIHBpY2tlcidzIHRvb2x0aXA6IG9ubHkgd2hpbGUgdGhlIHNjcmVlbiBkaWZmZXJzIGZyb20gdGhlIG9wZW4gdmlldy5cbmV4cG9ydCBmdW5jdGlvbiBwaWNrZXJUb29sdGlwKG9wZW46IFBpY2s8UmVwb3J0Vmlld1N1bW1hcnksICduYW1lJz4gfCBudWxsLCBlZGl0ZWQ6IGJvb2xlYW4pOiBzdHJpbmcgfCBudWxsIHtcbiAgcmV0dXJuIG9wZW4gJiYgZWRpdGVkID8gRURJVEVEX1RPT0xUSVAgOiBudWxsO1xufVxuXG4vLyBUaGUgcXVlc3Rpb24gYmVmb3JlIGEgdmlldyBpcyBkZWxldGVkLiBBIHNoYXJlZCB2aWV3IHNheXMgdGhhdCBldmVyeW9uZVxuLy8gbG9zZXMgaXQuXG5leHBvcnQgZnVuY3Rpb24gZGVsZXRlUHJvbXB0VGV4dCh2aWV3OiBQaWNrPFJlcG9ydFZpZXdTdW1tYXJ5LCAnbmFtZScgfCAnc2hhcmVkJz4pOiBzdHJpbmcge1xuICBjb25zdCBxdWVzdGlvbiA9IGBEZWxldGUgdGhlIHZpZXcgXCIke3ZpZXcubmFtZX1cIj9gO1xuXG4gIHJldHVybiB2aWV3LnNoYXJlZCA/IGAke3F1ZXN0aW9ufSBFdmVyeW9uZSBpdCBpcyBzaGFyZWQgd2l0aCBsb3NlcyBpdC5gIDogcXVlc3Rpb247XG59XG5cbi8vIFRoZSBsaW5lIHRoZSBzYXZlIGRpYWxvZyBzaG93cyB1bmRlciB0aGUgbmFtZSwgb3IgbnVsbDogYSBjcm9zcy1maWx0ZXIgaXNcbi8vIG9uLCBhbmQgaXQgZG9lcyBub3QgZ28gaW50byB0aGUgdmlldy5cbmV4cG9ydCBmdW5jdGlvbiBzYXZlRGlhbG9nTm90ZShoYXNDcm9zc0ZpbHRlcjogYm9vbGVhbik6IHN0cmluZyB8IG51bGwge1xuICByZXR1cm4gaGFzQ3Jvc3NGaWx0ZXIgPyBDUk9TU19GSUxURVJfTk9URSA6IG51bGw7XG59XG5cbi8vIEEgbmFtZSBtYWRlIG9mIHNwYWNlcyBvbmx5IGlzIG5vIG5hbWU7IHRoZSBzZXJ2ZXIgdHJpbXMgaXQuXG5leHBvcnQgZnVuY3Rpb24gdmlld05hbWVFcnJvcihuYW1lOiBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKTogc3RyaW5nIHwgbnVsbCB7XG4gIHJldHVybiAobmFtZSA/PyAnJykudHJpbSgpID8gbnVsbCA6IFZJRVdfTkFNRV9CTEFOSztcbn1cblxuXG5mdW5jdGlvbiB2aWV3Um93KHZpZXc6IFJlcG9ydFZpZXdTdW1tYXJ5LCBvcGVuOiBSZXBvcnRWaWV3U3VtbWFyeSB8IG51bGwsIGVkaXRlZDogYm9vbGVhbik6IFJlcG9ydFZpZXdNZW51SXRlbSB7XG4gIGNvbnN0IGlzT3BlbiA9IHZpZXcuaWQgPT09IG9wZW4/LmlkO1xuXG4gIHJldHVybiB7XG4gICAga2luZDogJ3ZpZXcnLFxuICAgIGxhYmVsOiB2aWV3Lm5hbWUsXG4gICAgZGlzYWJsZWQ6IGlzT3BlbiAmJiAhZWRpdGVkLFxuICAgIHRvb2x0aXA6IHZpZXdUb29sdGlwKHZpZXcpLFxuICAgIGRpdmlkZXI6IGZhbHNlLFxuICAgIHZpZXdJZDogdmlldy5pZCxcbiAgICBvcGVuOiBpc09wZW4sXG4gICAgaWNvbjogdmlld0ljb24odmlldyksXG4gIH07XG59XG5cbi8vIFdobyBzaGFyZWQgYSB2aWV3IG9mIHNvbWVvbmUgZWxzZSdzOyB3aGV0aGVyIG9uZSBvZiB0aGUgdmlld2VyJ3Mgb3duIG9wZW5zXG4vLyBieSBkZWZhdWx0IG9yIGlzIHNoYXJlZC5cbmZ1bmN0aW9uIHZpZXdUb29sdGlwKHZpZXc6IFJlcG9ydFZpZXdTdW1tYXJ5KTogc3RyaW5nIHwgbnVsbCB7XG4gIGlmICghdmlldy5taW5lKSB7XG4gICAgcmV0dXJuIHZpZXcub3duZXJOYW1lID8gYFNoYXJlZCBieSAke3ZpZXcub3duZXJOYW1lfWAgOiAnU2hhcmVkIHdpdGggZXZlcnlvbmUnO1xuICB9XG5cbiAgaWYgKHZpZXcucGVyc29uYWxEZWZhdWx0ICYmIHZpZXcuc2hhcmVkKSB7XG4gICAgcmV0dXJuICdPcGVucyBieSBkZWZhdWx0LCBzaGFyZWQgd2l0aCBldmVyeW9uZSc7XG4gIH1cblxuICBpZiAodmlldy5wZXJzb25hbERlZmF1bHQpIHtcbiAgICByZXR1cm4gJ09wZW5zIGJ5IGRlZmF1bHQnO1xuICB9XG5cbiAgcmV0dXJuIHZpZXcuc2hhcmVkID8gJ1NoYXJlZCB3aXRoIGV2ZXJ5b25lJyA6IG51bGw7XG59XG5cbi8vIFRoZSBvcGVuIHJvdyBrZWVwcyB0aGlzIGljb24gdG9vOyBpdHMgY2hlY2sgaXMgZHJhd24gYmVzaWRlIGl0LlxuZnVuY3Rpb24gdmlld0ljb24odmlldzogUmVwb3J0Vmlld1N1bW1hcnkpOiBSZXBvcnRWaWV3TWVudUl0ZW1bJ2ljb24nXSB7XG4gIGlmICghdmlldy5taW5lKSB7XG4gICAgcmV0dXJuICdwZW9wbGUnO1xuICB9XG5cbiAgcmV0dXJuIHZpZXcucGVyc29uYWxEZWZhdWx0ID8gJ3N0YXInIDogbnVsbDtcbn1cblxuLy8gVGhlIHJvd3MgdGhhdCBhY3Qgb24gdGhlIG9wZW4gdmlldzsgd2l0aCBub25lIG9wZW4sIG9ubHkgU2F2ZSBhcyBuZXcgdmlldy5cbmZ1bmN0aW9uIG9wZW5WaWV3QWN0aW9ucyhvcGVuOiBSZXBvcnRWaWV3U3VtbWFyeSB8IG51bGwsIGVkaXRlZDogYm9vbGVhbiwgY2FuU2hhcmU6IGJvb2xlYW4pOiBSZXBvcnRWaWV3TWVudUl0ZW1bXSB7XG4gIGNvbnN0IGl0ZW1zOiBSZXBvcnRWaWV3TWVudUl0ZW1bXSA9IFtdO1xuXG4gIGlmIChvcGVuPy5jYW5DaGFuZ2UgJiYgZWRpdGVkKSB7XG4gICAgaXRlbXMucHVzaChhY3Rpb24oJ3NhdmVDaGFuZ2VzJywgJ1NhdmUgY2hhbmdlcycpKTtcbiAgfVxuXG4gIGl0ZW1zLnB1c2goYWN0aW9uKCdzYXZlQXNOZXcnLCAnU2F2ZSBhcyBuZXcgdmlldy4uLicpKTtcblxuICBpZiAob3Blbj8uY2FuQ2hhbmdlKSB7XG4gICAgaXRlbXMucHVzaChhY3Rpb24oJ3JlbmFtZScsICdSZW5hbWUuLi4nKSk7XG4gIH1cblxuICBpZiAob3Blbj8ubWluZSkge1xuICAgIGl0ZW1zLnB1c2gob3Blbi5wZXJzb25hbERlZmF1bHRcbiAgICAgID8gYWN0aW9uKCdjbGVhckRlZmF1bHQnLCAnU3RvcCBvcGVuaW5nIGl0IGJ5IGRlZmF1bHQnKVxuICAgICAgOiBhY3Rpb24oJ3NldERlZmF1bHQnLCAnTWFrZSBpdCBteSBkZWZhdWx0JykpO1xuICB9XG5cbiAgaWYgKG9wZW4/Lm1pbmUgJiYgY2FuU2hhcmUpIHtcbiAgICBpdGVtcy5wdXNoKG9wZW4uc2hhcmVkID8gYWN0aW9uKCd1bnNoYXJlJywgJ1N0b3Agc2hhcmluZycpIDogYWN0aW9uKCdzaGFyZScsICdTaGFyZSB3aXRoIGV2ZXJ5b25lJykpO1xuICB9XG5cbiAgaWYgKG9wZW4/LmNhbkRlbGV0ZSkge1xuICAgIGl0ZW1zLnB1c2goYWN0aW9uKCdkZWxldGUnLCAnRGVsZXRlLi4uJykpO1xuICB9XG5cbiAgcmV0dXJuIGl0ZW1zO1xufVxuXG5mdW5jdGlvbiBhY3Rpb24oa2luZDogUmVwb3J0Vmlld01lbnVJdGVtWydraW5kJ10sIGxhYmVsOiBzdHJpbmcpOiBSZXBvcnRWaWV3TWVudUl0ZW0ge1xuICByZXR1cm4geyBraW5kLCBsYWJlbCwgZGlzYWJsZWQ6IGZhbHNlLCB0b29sdGlwOiBudWxsLCBkaXZpZGVyOiBmYWxzZSwgdmlld0lkOiBudWxsLCBvcGVuOiBmYWxzZSwgaWNvbjogbnVsbCB9O1xufVxuXG4vLyBUaGUgc2FtZSByb3dzLCB0aGUgZmlyc3Qgd2l0aCBhIGxpbmUgYWJvdmUgaXQgd2hlbiBgZGl2aWRlcmAgaXMgc2V0LlxuZnVuY3Rpb24gd2l0aERpdmlkZXIoaXRlbXM6IFJlcG9ydFZpZXdNZW51SXRlbVtdLCBkaXZpZGVyOiBib29sZWFuKTogUmVwb3J0Vmlld01lbnVJdGVtW10ge1xuICByZXR1cm4gaXRlbXMubWFwKChpdGVtLCBpbmRleCkgPT4gKGluZGV4ID09PSAwICYmIGRpdmlkZXIgPyB7IC4uLml0ZW0sIGRpdmlkZXI6IHRydWUgfSA6IGl0ZW0pKTtcbn1cbiJdfQ==
@@ -0,0 +1,42 @@
1
+ // The viewer features this viewer implements: the report GET names them
2
+ // (features=<comma list>), and the server assembles the report for exactly
3
+ // these. A feature joins the list in the change that builds its control, never
4
+ // before: the server sends a group only in a shape the viewer says it can show
5
+ // and clear, and a listed feature without its control would get a filter the
6
+ // viewer can neither show nor clear.
7
+ //
8
+ // scopeFilters needs no control of its own: a scope member is an ordinary
9
+ // filter row on its tile. excludeValues is a select's 'Exclude these' row,
10
+ // numberRange its min/max control, matchAny the report bar's Match select,
11
+ // and pageScope shows a page's groups in the report bar of that page.
12
+ // cascadingOptions narrows a select's list by the other filters of its tile
13
+ // (ReportFilterOptionsService). views is the Views picker in the report's
14
+ // header (ReportViewPickerComponent). drill is a time chart's click down, with
15
+ // the tile header's breadcrumb and its menu's Drill up and Back to top as the
16
+ // way back.
17
+ export const VIEWER_FEATURES = [
18
+ 'scopeFilters',
19
+ 'excludeValues',
20
+ 'numberRange',
21
+ 'matchAny',
22
+ 'pageScope',
23
+ 'cascadingOptions',
24
+ 'views',
25
+ 'drill',
26
+ ];
27
+ // The features a report offers on this screen: the ones its server serves
28
+ // (Report.viewerFeatures) that this viewer also implements.
29
+ export function offeredViewerFeatures(served) {
30
+ return (served ?? []).filter((feature) => VIEWER_FEATURES.includes(feature));
31
+ }
32
+ // Whether a select group offers 'Exclude these': the one rule the report bar,
33
+ // the tile headers and the report settings' default row share. The server
34
+ // must serve excludeValues, and no enabled member may bind several columns
35
+ // (multiColumn), since the server cannot leave values out there (an older
36
+ // server sends no multiColumn, and the toggle shows as before).
37
+ export function offersExclude(group, features) {
38
+ return group.type === 'select'
39
+ && !group.multiColumn
40
+ && (features ?? []).includes('excludeValues');
41
+ }
42
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXZpZXdlci1mZWF0dXJlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9yZXBvcnQtdmlld2VyLWZlYXR1cmVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUlBLHdFQUF3RTtBQUN4RSwyRUFBMkU7QUFDM0UsK0VBQStFO0FBQy9FLCtFQUErRTtBQUMvRSw2RUFBNkU7QUFDN0UscUNBQXFDO0FBQ3JDLEVBQUU7QUFDRiwwRUFBMEU7QUFDMUUsMkVBQTJFO0FBQzNFLDJFQUEyRTtBQUMzRSxzRUFBc0U7QUFDdEUsNEVBQTRFO0FBQzVFLDBFQUEwRTtBQUMxRSwrRUFBK0U7QUFDL0UsOEVBQThFO0FBQzlFLFlBQVk7QUFDWixNQUFNLENBQUMsTUFBTSxlQUFlLEdBQW1DO0lBQzdELGNBQWM7SUFDZCxlQUFlO0lBQ2YsYUFBYTtJQUNiLFVBQVU7SUFDVixXQUFXO0lBQ1gsa0JBQWtCO0lBQ2xCLE9BQU87SUFDUCxPQUFPO0NBQ1IsQ0FBQztBQUVGLDBFQUEwRTtBQUMxRSw0REFBNEQ7QUFDNUQsTUFBTSxVQUFVLHFCQUFxQixDQUFDLE1BQXlEO0lBQzdGLE9BQU8sQ0FBQyxNQUFNLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7QUFDL0UsQ0FBQztBQUVELDhFQUE4RTtBQUM5RSwwRUFBMEU7QUFDMUUsMkVBQTJFO0FBQzNFLDBFQUEwRTtBQUMxRSxnRUFBZ0U7QUFDaEUsTUFBTSxVQUFVLGFBQWEsQ0FDM0IsS0FBc0QsRUFDdEQsUUFBMkQ7SUFFM0QsT0FBTyxLQUFLLENBQUMsSUFBSSxLQUFLLFFBQVE7V0FDekIsQ0FBQyxLQUFLLENBQUMsV0FBVztXQUNsQixDQUFDLFFBQVEsSUFBSSxFQUFFLENBQUMsQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLENBQUM7QUFDbEQsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFJlcG9ydFZpZXdlckZlYXR1cmUgfSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LXZpZXdlci1mZWF0dXJlLnR5cGUnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyR3JvdXAgfSBmcm9tICcuL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5cblxuLy8gVGhlIHZpZXdlciBmZWF0dXJlcyB0aGlzIHZpZXdlciBpbXBsZW1lbnRzOiB0aGUgcmVwb3J0IEdFVCBuYW1lcyB0aGVtXG4vLyAoZmVhdHVyZXM9PGNvbW1hIGxpc3Q+KSwgYW5kIHRoZSBzZXJ2ZXIgYXNzZW1ibGVzIHRoZSByZXBvcnQgZm9yIGV4YWN0bHlcbi8vIHRoZXNlLiBBIGZlYXR1cmUgam9pbnMgdGhlIGxpc3QgaW4gdGhlIGNoYW5nZSB0aGF0IGJ1aWxkcyBpdHMgY29udHJvbCwgbmV2ZXJcbi8vIGJlZm9yZTogdGhlIHNlcnZlciBzZW5kcyBhIGdyb3VwIG9ubHkgaW4gYSBzaGFwZSB0aGUgdmlld2VyIHNheXMgaXQgY2FuIHNob3dcbi8vIGFuZCBjbGVhciwgYW5kIGEgbGlzdGVkIGZlYXR1cmUgd2l0aG91dCBpdHMgY29udHJvbCB3b3VsZCBnZXQgYSBmaWx0ZXIgdGhlXG4vLyB2aWV3ZXIgY2FuIG5laXRoZXIgc2hvdyBub3IgY2xlYXIuXG4vL1xuLy8gc2NvcGVGaWx0ZXJzIG5lZWRzIG5vIGNvbnRyb2wgb2YgaXRzIG93bjogYSBzY29wZSBtZW1iZXIgaXMgYW4gb3JkaW5hcnlcbi8vIGZpbHRlciByb3cgb24gaXRzIHRpbGUuIGV4Y2x1ZGVWYWx1ZXMgaXMgYSBzZWxlY3QncyAnRXhjbHVkZSB0aGVzZScgcm93LFxuLy8gbnVtYmVyUmFuZ2UgaXRzIG1pbi9tYXggY29udHJvbCwgbWF0Y2hBbnkgdGhlIHJlcG9ydCBiYXIncyBNYXRjaCBzZWxlY3QsXG4vLyBhbmQgcGFnZVNjb3BlIHNob3dzIGEgcGFnZSdzIGdyb3VwcyBpbiB0aGUgcmVwb3J0IGJhciBvZiB0aGF0IHBhZ2UuXG4vLyBjYXNjYWRpbmdPcHRpb25zIG5hcnJvd3MgYSBzZWxlY3QncyBsaXN0IGJ5IHRoZSBvdGhlciBmaWx0ZXJzIG9mIGl0cyB0aWxlXG4vLyAoUmVwb3J0RmlsdGVyT3B0aW9uc1NlcnZpY2UpLiB2aWV3cyBpcyB0aGUgVmlld3MgcGlja2VyIGluIHRoZSByZXBvcnQnc1xuLy8gaGVhZGVyIChSZXBvcnRWaWV3UGlja2VyQ29tcG9uZW50KS4gZHJpbGwgaXMgYSB0aW1lIGNoYXJ0J3MgY2xpY2sgZG93biwgd2l0aFxuLy8gdGhlIHRpbGUgaGVhZGVyJ3MgYnJlYWRjcnVtYiBhbmQgaXRzIG1lbnUncyBEcmlsbCB1cCBhbmQgQmFjayB0byB0b3AgYXMgdGhlXG4vLyB3YXkgYmFjay5cbmV4cG9ydCBjb25zdCBWSUVXRVJfRkVBVFVSRVM6IHJlYWRvbmx5IFJlcG9ydFZpZXdlckZlYXR1cmVbXSA9IFtcbiAgJ3Njb3BlRmlsdGVycycsXG4gICdleGNsdWRlVmFsdWVzJyxcbiAgJ251bWJlclJhbmdlJyxcbiAgJ21hdGNoQW55JyxcbiAgJ3BhZ2VTY29wZScsXG4gICdjYXNjYWRpbmdPcHRpb25zJyxcbiAgJ3ZpZXdzJyxcbiAgJ2RyaWxsJyxcbl07XG5cbi8vIFRoZSBmZWF0dXJlcyBhIHJlcG9ydCBvZmZlcnMgb24gdGhpcyBzY3JlZW46IHRoZSBvbmVzIGl0cyBzZXJ2ZXIgc2VydmVzXG4vLyAoUmVwb3J0LnZpZXdlckZlYXR1cmVzKSB0aGF0IHRoaXMgdmlld2VyIGFsc28gaW1wbGVtZW50cy5cbmV4cG9ydCBmdW5jdGlvbiBvZmZlcmVkVmlld2VyRmVhdHVyZXMoc2VydmVkOiByZWFkb25seSBSZXBvcnRWaWV3ZXJGZWF0dXJlW10gfCBudWxsIHwgdW5kZWZpbmVkKTogUmVwb3J0Vmlld2VyRmVhdHVyZVtdIHtcbiAgcmV0dXJuIChzZXJ2ZWQgPz8gW10pLmZpbHRlcigoZmVhdHVyZSkgPT4gVklFV0VSX0ZFQVRVUkVTLmluY2x1ZGVzKGZlYXR1cmUpKTtcbn1cblxuLy8gV2hldGhlciBhIHNlbGVjdCBncm91cCBvZmZlcnMgJ0V4Y2x1ZGUgdGhlc2UnOiB0aGUgb25lIHJ1bGUgdGhlIHJlcG9ydCBiYXIsXG4vLyB0aGUgdGlsZSBoZWFkZXJzIGFuZCB0aGUgcmVwb3J0IHNldHRpbmdzJyBkZWZhdWx0IHJvdyBzaGFyZS4gVGhlIHNlcnZlclxuLy8gbXVzdCBzZXJ2ZSBleGNsdWRlVmFsdWVzLCBhbmQgbm8gZW5hYmxlZCBtZW1iZXIgbWF5IGJpbmQgc2V2ZXJhbCBjb2x1bW5zXG4vLyAobXVsdGlDb2x1bW4pLCBzaW5jZSB0aGUgc2VydmVyIGNhbm5vdCBsZWF2ZSB2YWx1ZXMgb3V0IHRoZXJlIChhbiBvbGRlclxuLy8gc2VydmVyIHNlbmRzIG5vIG11bHRpQ29sdW1uLCBhbmQgdGhlIHRvZ2dsZSBzaG93cyBhcyBiZWZvcmUpLlxuZXhwb3J0IGZ1bmN0aW9uIG9mZmVyc0V4Y2x1ZGUoXG4gIGdyb3VwOiBQaWNrPFJlcG9ydEZpbHRlckdyb3VwLCAndHlwZScgfCAnbXVsdGlDb2x1bW4nPixcbiAgZmVhdHVyZXM6IHJlYWRvbmx5IFJlcG9ydFZpZXdlckZlYXR1cmVbXSB8IG51bGwgfCB1bmRlZmluZWQsXG4pOiBib29sZWFuIHtcbiAgcmV0dXJuIGdyb3VwLnR5cGUgPT09ICdzZWxlY3QnXG4gICAgJiYgIWdyb3VwLm11bHRpQ29sdW1uXG4gICAgJiYgKGZlYXR1cmVzID8/IFtdKS5pbmNsdWRlcygnZXhjbHVkZVZhbHVlcycpO1xufVxuIl19
@@ -0,0 +1,238 @@
1
+ import { DestroyRef, Injectable, inject } from '@angular/core';
2
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
+ import { Subject, defer, of } from 'rxjs';
4
+ import { catchError, filter, map, shareReplay, switchMap, take, tap } from 'rxjs/operators';
5
+ import { ReportData } from '../data/report.data';
6
+ import { isMatchAnyGroup } from '../report-filter-items';
7
+ import { tileDataState, tilePageId, valuesMatchAnyGroupIds } from '../tile-data-state';
8
+ import { reportComponents } from '../values';
9
+ import { ReportFilterStateService } from './report-filter-state.service';
10
+ import * as i0 from "@angular/core";
11
+ // The most picks one request asks names for: the server's option cap.
12
+ const SELECTED_CAP = 500;
13
+ // The options a select group's control offers. When the server serves
14
+ // cascadingOptions, a group's list is narrowed by the other entries of its
15
+ // host tile (the narrowed options POST); otherwise it is the full list (the
16
+ // options GET), fetched once per group while its host stays the same. The
17
+ // host is the member whose list the group shows (optionsHost).
18
+ //
19
+ // A list is replayed while its request's signature holds: the host's entries
20
+ // without the group's own, without a cross-filter entry and, while the
21
+ // groups match 'any', without the other groups this one combines with. A new
22
+ // signature fetches again, and a request still in flight for an older one is
23
+ // dropped (switchMap). fs-filter asks on focus and on each keystroke, so a
24
+ // list is fetched on the first of them after a change and replayed for the
25
+ // rest; typing filters the replayed list in the viewer (matchOptions).
26
+ //
27
+ // Every list and every 'selected' answer teaches label() the names of the
28
+ // values it holds, so a pick the narrowed list leaves out keeps its name.
29
+ //
30
+ // Each load of the report (the first, and every reload after a chat or
31
+ // dialog edit) starts again: no list is replayed and no name is kept from an
32
+ // earlier load, so an edit to a tile's source or to an option's name shows on
33
+ // the next ask, as when every bar build fetched its list.
34
+ export class ReportFilterOptionsService {
35
+ _reportData = inject(ReportData);
36
+ _filterState = inject(ReportFilterStateService);
37
+ _destroyRef = inject(DestroyRef);
38
+ _streams = new Map();
39
+ _labels = new Map();
40
+ // The picks each group has asked names for, so a value the server cannot
41
+ // name (its entity was deleted) is asked for once, not on every keystroke.
42
+ _asked = new Map();
43
+ // The report load the lists and names above belong to (the object init()
44
+ // last read).
45
+ _loaded = null;
46
+ // The options the group's control offers now. Nothing is read or sent
47
+ // until the list is subscribed to, so the signature is the one of the
48
+ // moment the control asks.
49
+ options(group, report) {
50
+ return defer(() => {
51
+ const narrowed = !!report?.viewerFeatures?.includes('cascadingOptions');
52
+ const host = optionsHost(group, narrowed);
53
+ if (!host || !report) {
54
+ return of([]);
55
+ }
56
+ this._syncLoad();
57
+ const stream = this._stream(group.id);
58
+ const seq = this._ask(stream, group, report, host, narrowed);
59
+ return stream.lists$
60
+ .pipe(filter((list) => list.seq >= seq), take(1), map((list) => list.options));
61
+ });
62
+ }
63
+ // The name a value of the group was last listed or labeled with in this
64
+ // load of the report, or null when no list or answer has named it yet.
65
+ label(groupId, value) {
66
+ this._syncLoad();
67
+ return this._labels.get(groupId)?.get(String(value)) ?? null;
68
+ }
69
+ // Whether the group's latest list was cut at 500.
70
+ truncated(groupId) {
71
+ this._syncLoad();
72
+ return this._streams.get(groupId)?.truncated ?? false;
73
+ }
74
+ // Whether the group's latest request failed. Its list is then empty, and
75
+ // the next ask fetches again.
76
+ failed(groupId) {
77
+ this._syncLoad();
78
+ return this._streams.get(groupId)?.failed ?? false;
79
+ }
80
+ // Sends a request when the signature moved, or when a pick has no name
81
+ // yet and was never asked for. Returns the number of the request whose
82
+ // answer the caller takes: the one sent, else the latest.
83
+ _ask(stream, group, report, host, narrowed) {
84
+ const body = narrowed ? this._request(group, report, host) : null;
85
+ // The host member is part of it: a report edit that moves the group's
86
+ // list to another member or column lists again.
87
+ const signature = JSON.stringify([host.id, host.filterColumn, body?.filters ?? null, body?.matchAnyGroupIds ?? []]);
88
+ const unnamed = (body?.selected ?? [])
89
+ .filter((value) => this.label(group.id, value) === null && !this._askedFor(group.id).has(String(value)));
90
+ if (signature === stream.signature && !unnamed.length) {
91
+ return stream.seq;
92
+ }
93
+ unnamed.forEach((value) => this._askedFor(group.id).add(String(value)));
94
+ stream.signature = signature;
95
+ stream.seq += 1;
96
+ stream.requests$.next({ seq: stream.seq, fetch: this._fetch(stream, group.id, report.id, host.id, body) });
97
+ return stream.seq;
98
+ }
99
+ // The narrowed request for the group: what its host tile's data request
100
+ // carries now, minus the entries that must not narrow the group's list.
101
+ _request(group, report, host) {
102
+ const tile = reportComponents(report).find((component) => component.id === host.componentId) ?? null;
103
+ const selected = groupPicks(this._filterState.value(group.id));
104
+ if (!tile) {
105
+ return { filters: [], ...(selected.length ? { selected } : {}) };
106
+ }
107
+ const snapshot = this._filterState.snapshot();
108
+ // A group whose only members are inline values lists through a value,
109
+ // which combines its groups by the tile rule over its own page.
110
+ const matchAnyGroupIds = tile.type === 'value'
111
+ ? valuesMatchAnyGroupIds(report, tilePageId(report, tile, snapshot), snapshot)
112
+ : tileDataState(report, tile, snapshot).matchAnyGroupIds ?? [];
113
+ // Under 'any' another group this one combines with does not limit which
114
+ // of its values can show rows, so the list leaves it out.
115
+ const combined = matchAnyGroupIds.length && isMatchAnyGroup(group, tilePageId(report, tile, snapshot))
116
+ ? matchAnyGroupIds
117
+ : [];
118
+ const groupOf = new Map((tile.filters ?? []).map((member) => [member.id, member.filterGroupId]));
119
+ const filters = this._filterState.resolveForComponent(tile)
120
+ .filter((entry) => {
121
+ const groupId = groupOf.get(entry.filterId) ?? null;
122
+ return !isCrossEntry(entry) && groupId !== group.id && !combined.includes(groupId);
123
+ });
124
+ return {
125
+ filters,
126
+ ...(matchAnyGroupIds.length ? { matchAnyGroupIds } : {}),
127
+ ...(selected.length ? { selected } : {}),
128
+ };
129
+ }
130
+ // One request's answer as a list. A failed request answers an empty list
131
+ // marked failed, and clears the signature, so the next ask fetches again.
132
+ _fetch(stream, groupId, reportId, filterId, body) {
133
+ const seq = stream.seq;
134
+ // An answer that lands after the report loaded again teaches no name.
135
+ const loaded = this._filterState.report();
136
+ const answer$ = body
137
+ ? this._reportData.filterOptionsNarrowed(reportId, filterId, body)
138
+ : this._reportData.filterOptions(reportId, filterId)
139
+ .pipe(map((options) => ({ options, truncated: false, narrowedBy: [], selected: [] })));
140
+ return answer$
141
+ .pipe(tap((answer) => {
142
+ if (this._filterState.report() === loaded) {
143
+ this._remember(groupId, [...(answer?.options ?? []), ...(answer?.selected ?? [])]);
144
+ }
145
+ }), map((answer) => ({
146
+ seq,
147
+ truncated: !!answer?.truncated,
148
+ failed: false,
149
+ options: (answer?.options ?? []).map((option) => ({ name: option.label, value: option.value })),
150
+ })), catchError(() => {
151
+ stream.signature = null;
152
+ return of({ seq, truncated: false, failed: true, options: [] });
153
+ }));
154
+ }
155
+ // The group's stream, opened on its first ask. It is subscribed to here,
156
+ // for the life of the report view, so an answer is kept for the next ask
157
+ // even when the control that asked has moved on. When the view goes, the
158
+ // stream ends: a request still in flight is dropped, whoever still listens.
159
+ _stream(groupId) {
160
+ const existing = this._streams.get(groupId);
161
+ if (existing) {
162
+ return existing;
163
+ }
164
+ const requests$ = new Subject();
165
+ const stream = {
166
+ signature: null,
167
+ seq: 0,
168
+ truncated: false,
169
+ failed: false,
170
+ requests$,
171
+ lists$: requests$
172
+ .pipe(switchMap((request) => request.fetch), tap((list) => {
173
+ stream.truncated = list.truncated;
174
+ stream.failed = list.failed;
175
+ }), takeUntilDestroyed(this._destroyRef), shareReplay({ bufferSize: 1, refCount: false })),
176
+ };
177
+ // Ends with the stream, when the view goes.
178
+ stream.lists$.subscribe();
179
+ this._streams.set(groupId, stream);
180
+ return stream;
181
+ }
182
+ // A new load of the report (init() read another report object) drops what
183
+ // the last load learned: every signature, so each list is fetched again on
184
+ // its next ask, and every name and asked pick.
185
+ _syncLoad() {
186
+ const loaded = this._filterState.report();
187
+ if (loaded === this._loaded) {
188
+ return;
189
+ }
190
+ this._loaded = loaded;
191
+ this._streams.forEach((stream) => {
192
+ stream.signature = null;
193
+ });
194
+ this._labels.clear();
195
+ this._asked.clear();
196
+ }
197
+ _remember(groupId, options) {
198
+ const labels = this._labels.get(groupId) ?? new Map();
199
+ for (const option of options) {
200
+ if (option && typeof option.label === 'string') {
201
+ labels.set(String(option.value), option.label);
202
+ }
203
+ }
204
+ this._labels.set(groupId, labels);
205
+ }
206
+ _askedFor(groupId) {
207
+ const asked = this._asked.get(groupId) ?? new Set();
208
+ this._asked.set(groupId, asked);
209
+ return asked;
210
+ }
211
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportFilterOptionsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
212
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportFilterOptionsService });
213
+ }
214
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportFilterOptionsService, decorators: [{
215
+ type: Injectable
216
+ }] });
217
+ // The member whose list a group shows. The narrowed POST names the server's
218
+ // host: the first enabled member with options, else the first with options.
219
+ // The options GET keeps its older rule, the first member with options, as
220
+ // loadGroupOptions does, so an older server is asked what it always was.
221
+ function optionsHost(group, narrowed) {
222
+ const members = (group.filters ?? []).filter((member) => member.hasOptions);
223
+ return (narrowed ? members.find((member) => member.enabled) : null) ?? members[0] ?? null;
224
+ }
225
+ // A cross-filter entry rides in the same filters array as the group entries
226
+ // and carries its crossFilterId. It never narrows a list: a click is a
227
+ // temporary look, and the chip of the cross-filter already shows it.
228
+ function isCrossEntry(entry) {
229
+ return 'crossFilterId' in entry;
230
+ }
231
+ // A select group's picks, kept or left out, that a request can name: text
232
+ // and numbers, at most SELECTED_CAP.
233
+ function groupPicks(value) {
234
+ return [...(value?.values ?? []), ...(value?.excludeValues ?? [])]
235
+ .filter((pick) => typeof pick === 'string' || typeof pick === 'number')
236
+ .slice(0, SELECTED_CAP);
237
+ }
238
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LWZpbHRlci1vcHRpb25zLnNlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvYXBwL3JlcG9ydHMvc2VydmljZXMvcmVwb3J0LWZpbHRlci1vcHRpb25zLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQy9ELE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRWhFLE9BQU8sRUFBYyxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUN0RCxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsV0FBVyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFNUYsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBVWpELE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUN6RCxPQUFPLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBQ3ZGLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUU3QyxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQzs7QUFHekUsc0VBQXNFO0FBQ3RFLE1BQU0sWUFBWSxHQUFHLEdBQUcsQ0FBQztBQUV6QixzRUFBc0U7QUFDdEUsMkVBQTJFO0FBQzNFLDRFQUE0RTtBQUM1RSwwRUFBMEU7QUFDMUUsK0RBQStEO0FBQy9ELEVBQUU7QUFDRiw2RUFBNkU7QUFDN0UsdUVBQXVFO0FBQ3ZFLDZFQUE2RTtBQUM3RSw2RUFBNkU7QUFDN0UsMkVBQTJFO0FBQzNFLDJFQUEyRTtBQUMzRSx1RUFBdUU7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QUUsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUM7QUFDNUYsQ0FBQztBQUVELDRFQUE0RTtBQUM1RSx1RUFBdUU7QUFDdkUscUVBQXFFO0FBQ3JFLFNBQVMsWUFBWSxDQUFDLEtBQTBCO0lBQzlDLE9BQU8sZUFBZSxJQUFJLEtBQUssQ0FBQztBQUNsQyxDQUFDO0FBRUQsMEVBQTBFO0FBQzFFLHFDQUFxQztBQUNyQyxTQUFTLFVBQVUsQ0FBQyxLQUFtQztJQUNyRCxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxNQUFNLElBQUksRUFBRSxDQUFDLEVBQUUsR0FBRyxDQUFDLEtBQUssRUFBRSxhQUFhLElBQUksRUFBRSxDQUFDLENBQUM7U0FDL0QsTUFBTSxDQUFDLENBQUMsSUFBSSxFQUEyQixFQUFFLENBQUMsT0FBTyxJQUFJLEtBQUssUUFBUSxJQUFJLE9BQU8sSUFBSSxLQUFLLFFBQVEsQ0FBQztTQUMvRixLQUFLLENBQUMsQ0FBQyxFQUFFLFlBQVksQ0FBQyxDQUFDO0FBQzVCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBEZXN0cm95UmVmLCBJbmplY3RhYmxlLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgU3ViamVjdCwgZGVmZXIsIG9mIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBjYXRjaEVycm9yLCBmaWx0ZXIsIG1hcCwgc2hhcmVSZXBsYXksIHN3aXRjaE1hcCwgdGFrZSwgdGFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBSZXBvcnREYXRhIH0gZnJvbSAnLi4vZGF0YS9yZXBvcnQuZGF0YSc7XG5pbXBvcnQgeyBSZXBvcnRGaWx0ZXJPcHRpb25QYWlyIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQtZmlsdGVyLW9wdGlvbi1wYWlyLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZXBvcnRGaWx0ZXJPcHRpb25zQXNrIH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQtZmlsdGVyLW9wdGlvbnMtYXNrLmludGVyZmFjZSc7XG5pbXBvcnQgeyBSZXBvcnRGaWx0ZXJPcHRpb25zTGlzdCB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1vcHRpb25zLWxpc3QuaW50ZXJmYWNlJztcbmltcG9ydCB7IFJlcG9ydEZpbHRlck9wdGlvbnNSZXF1ZXN0IH0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQtZmlsdGVyLW9wdGlvbnMtcmVxdWVzdC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyT3B0aW9uc1N0cmVhbSB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1vcHRpb25zLXN0cmVhbS5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyT3B0aW9ucyB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LWZpbHRlci1vcHRpb25zLmludGVyZmFjZSc7XG5pbXBvcnQge1xuICBGaWx0ZXJHcm91cFZhbHVlLCBSZXBvcnQsIFJlcG9ydEZpbHRlciwgUmVwb3J0RmlsdGVyR3JvdXAsIFJlcG9ydEZpbHRlck9wdGlvbiwgUmVzb2x2ZWRGaWx0ZXJWYWx1ZSxcbn0gZnJvbSAnLi4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IGlzTWF0Y2hBbnlHcm91cCB9IGZyb20gJy4uL3JlcG9ydC1maWx0ZXItaXRlbXMnO1xuaW1wb3J0IHsgdGlsZURhdGFTdGF0ZSwgdGlsZVBhZ2VJZCwgdmFsdWVzTWF0Y2hBbnlHcm91cElkcyB9IGZyb20gJy4uL3RpbGUtZGF0YS1zdGF0ZSc7XG5pbXBvcnQgeyByZXBvcnRDb21wb25lbnRzIH0gZnJvbSAnLi4vdmFsdWVzJztcblxuaW1wb3J0IHsgUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIH0gZnJvbSAnLi9yZXBvcnQtZmlsdGVyLXN0YXRlLnNlcnZpY2UnO1xuXG5cbi8vIFRoZSBtb3N0IHBpY2tzIG9uZSByZXF1ZXN0IGFza3MgbmFtZXMgZm9yOiB0aGUgc2VydmVyJ3Mgb3B0aW9uIGNhcC5cbmNvbnN0IFNFTEVDVEVEX0NBUCA9IDUwMDtcblxuLy8gVGhlIG9wdGlvbnMgYSBzZWxlY3QgZ3JvdXAncyBjb250cm9sIG9mZmVycy4gV2hlbiB0aGUgc2VydmVyIHNlcnZlc1xuLy8gY2FzY2FkaW5nT3B0aW9ucywgYSBncm91cCdzIGxpc3QgaXMgbmFycm93ZWQgYnkgdGhlIG90aGVyIGVudHJpZXMgb2YgaXRzXG4vLyBob3N0IHRpbGUgKHRoZSBuYXJyb3dlZCBvcHRpb25zIFBPU1QpOyBvdGhlcndpc2UgaXQgaXMgdGhlIGZ1bGwgbGlzdCAodGhlXG4vLyBvcHRpb25zIEdFVCksIGZldGNoZWQgb25jZSBwZXIgZ3JvdXAgd2hpbGUgaXRzIGhvc3Qgc3RheXMgdGhlIHNhbWUuIFRoZVxuLy8gaG9zdCBpcyB0aGUgbWVtYmVyIHdob3NlIGxpc3QgdGhlIGdyb3VwIHNob3dzIChvcHRpb25zSG9zdCkuXG4vL1xuLy8gQSBsaXN0IGlzIHJlcGxheWVkIHdoaWxlIGl0cyByZXF1ZXN0J3Mgc2lnbmF0dXJlIGhvbGRzOiB0aGUgaG9zdCdzIGVudHJpZXNcbi8vIHdpdGhvdXQgdGhlIGdyb3VwJ3Mgb3duLCB3aXRob3V0IGEgY3Jvc3MtZmlsdGVyIGVudHJ5IGFuZCwgd2hpbGUgdGhlXG4vLyBncm91cHMgbWF0Y2ggJ2FueScsIHdpdGhvdXQgdGhlIG90aGVyIGdyb3VwcyB0aGlzIG9uZSBjb21iaW5lcyB3aXRoLiBBIG5ld1xuLy8gc2lnbmF0dXJlIGZldGNoZXMgYWdhaW4sIGFuZCBhIHJlcXVlc3Qgc3RpbGwgaW4gZmxpZ2h0IGZvciBhbiBvbGRlciBvbmUgaXNcbi8vIGRyb3BwZWQgKHN3aXRjaE1hcCkuIGZzLWZpbHRlciBhc2tzIG9uIGZvY3VzIGFuZCBvbiBlYWNoIGtleXN0cm9rZSwgc28gYVxuLy8gbGlzdCBpcyBmZXRjaGVkIG9uIHRoZSBmaXJzdCBvZiB0aGVtIGFmdGVyIGEgY2hhbmdlIGFuZCByZXBsYXllZCBmb3IgdGhlXG4vLyByZXN0OyB0eXBpbmcgZmlsdGVycyB0aGUgcmVwbGF5ZWQgbGlzdCBpbiB0aGUgdmlld2VyIChtYXRjaE9wdGlvbnMpLlxuLy9cbi8vIEV2ZXJ5IGxpc3QgYW5kIGV2ZXJ5ICdzZWxlY3RlZCcgYW5zd2VyIHRlYWNoZXMgbGFiZWwoKSB0aGUgbmFtZXMgb2YgdGhlXG4vLyB2YWx1ZXMgaXQgaG9sZHMsIHNvIGEgcGljayB0aGUgbmFycm93ZWQgbGlzdCBsZWF2ZXMgb3V0IGtlZXBzIGl0cyBuYW1lLlxuLy9cbi8vIEVhY2ggbG9hZCBvZiB0aGUgcmVwb3J0ICh0aGUgZmlyc3QsIGFuZCBldmVyeSByZWxvYWQgYWZ0ZXIgYSBjaGF0IG9yXG4vLyBkaWFsb2cgZWRpdCkgc3RhcnRzIGFnYWluOiBubyBsaXN0IGlzIHJlcGxheWVkIGFuZCBubyBuYW1lIGlzIGtlcHQgZnJvbSBhblxuLy8gZWFybGllciBsb2FkLCBzbyBhbiBlZGl0IHRvIGEgdGlsZSdzIHNvdXJjZSBvciB0byBhbiBvcHRpb24ncyBuYW1lIHNob3dzIG9uXG4vLyB0aGUgbmV4dCBhc2ssIGFzIHdoZW4gZXZlcnkgYmFyIGJ1aWxkIGZldGNoZWQgaXRzIGxpc3QuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgUmVwb3J0RmlsdGVyT3B0aW9uc1NlcnZpY2Uge1xuXG4gIHByaXZhdGUgX3JlcG9ydERhdGEgPSBpbmplY3QoUmVwb3J0RGF0YSk7XG4gIHByaXZhdGUgX2ZpbHRlclN0YXRlID0gaW5qZWN0KFJlcG9ydEZpbHRlclN0YXRlU2VydmljZSk7XG4gIHByaXZhdGUgX2Rlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG4gIHByaXZhdGUgX3N0cmVhbXMgPSBuZXcgTWFwPG51bWJlciwgUmVwb3J0RmlsdGVyT3B0aW9uc1N0cmVhbT4oKTtcbiAgcHJpdmF0ZSBfbGFiZWxzID0gbmV3IE1hcDxudW1iZXIsIE1hcDxzdHJpbmcsIHN0cmluZz4+KCk7XG4gIC8vIFRoZSBwaWNrcyBlYWNoIGdyb3VwIGhhcyBhc2tlZCBuYW1lcyBmb3IsIHNvIGEgdmFsdWUgdGhlIHNlcnZlciBjYW5ub3RcbiAgLy8gbmFtZSAoaXRzIGVudGl0eSB3YXMgZGVsZXRlZCkgaXMgYXNrZWQgZm9yIG9uY2UsIG5vdCBvbiBldmVyeSBrZXlzdHJva2UuXG4gIHByaXZhdGUgX2Fza2VkID0gbmV3IE1hcDxudW1iZXIsIFNldDxzdHJpbmc+PigpO1xuICAvLyBUaGUgcmVwb3J0IGxvYWQgdGhlIGxpc3RzIGFuZCBuYW1lcyBhYm92ZSBiZWxvbmcgdG8gKHRoZSBvYmplY3QgaW5pdCgpXG4gIC8vIGxhc3QgcmVhZCkuXG4gIHByaXZhdGUgX2xvYWRlZDogUmVwb3J0IHwgbnVsbCA9IG51bGw7XG5cbiAgLy8gVGhlIG9wdGlvbnMgdGhlIGdyb3VwJ3MgY29udHJvbCBvZmZlcnMgbm93LiBOb3RoaW5nIGlzIHJlYWQgb3Igc2VudFxuICAvLyB1bnRpbCB0aGUgbGlzdCBpcyBzdWJzY3JpYmVkIHRvLCBzbyB0aGUgc2lnbmF0dXJlIGlzIHRoZSBvbmUgb2YgdGhlXG4gIC8vIG1vbWVudCB0aGUgY29udHJvbCBhc2tzLlxuICBwdWJsaWMgb3B0aW9ucyhncm91cDogUmVwb3J0RmlsdGVyR3JvdXAsIHJlcG9ydDogUmVwb3J0IHwgbnVsbCk6IE9ic2VydmFibGU8UmVwb3J0RmlsdGVyT3B0aW9uUGFpcltdPiB7XG4gICAgcmV0dXJuIGRlZmVyKCgpID0+IHtcbiAgICAgIGNvbnN0IG5hcnJvd2VkID0gISFyZXBvcnQ/LnZpZXdlckZlYXR1cmVzPy5pbmNsdWRlcygnY2FzY2FkaW5nT3B0aW9ucycpO1xuICAgICAgY29uc3QgaG9zdCA9IG9wdGlvbnNIb3N0KGdyb3VwLCBuYXJyb3dlZCk7XG5cbiAgICAgIGlmICghaG9zdCB8fCAhcmVwb3J0KSB7XG4gICAgICAgIHJldHVybiBvZihbXSk7XG4gICAgICB9XG5cbiAgICAgIHRoaXMuX3N5bmNMb2FkKCk7XG4gICAgICBjb25zdCBzdHJlYW0gPSB0aGlzLl9zdHJlYW0oZ3JvdXAuaWQpO1xuICAgICAgY29uc3Qgc2VxID0gdGhpcy5fYXNrKHN0cmVhbSwgZ3JvdXAsIHJlcG9ydCwgaG9zdCwgbmFycm93ZWQpO1xuXG4gICAgICByZXR1cm4gc3RyZWFtLmxpc3RzJFxuICAgICAgICAucGlwZShcbiAgICAgICAgICBmaWx0ZXIoKGxpc3QpID0+IGxpc3Quc2VxID49IHNlcSksXG4gICAgICAgICAgdGFrZSgxKSxcbiAgICAgICAgICBtYXAoKGxpc3QpID0+IGxpc3Qub3B0aW9ucyksXG4gICAgICAgICk7XG4gICAgfSk7XG4gIH1cblxuICAvLyBUaGUgbmFtZSBhIHZhbHVlIG9mIHRoZSBncm91cCB3YXMgbGFzdCBsaXN0ZWQgb3IgbGFiZWxlZCB3aXRoIGluIHRoaXNcbiAgLy8gbG9hZCBvZiB0aGUgcmVwb3J0LCBvciBudWxsIHdoZW4gbm8gbGlzdCBvciBhbnN3ZXIgaGFzIG5hbWVkIGl0IHlldC5cbiAgcHVibGljIGxhYmVsKGdyb3VwSWQ6IG51bWJlciwgdmFsdWU6IHVua25vd24pOiBzdHJpbmcgfCBudWxsIHtcbiAgICB0aGlzLl9zeW5jTG9hZCgpO1xuXG4gICAgcmV0dXJuIHRoaXMuX2xhYmVscy5nZXQoZ3JvdXBJZCk/LmdldChTdHJpbmcodmFsdWUpKSA/PyBudWxsO1xuICB9XG5cbiAgLy8gV2hldGhlciB0aGUgZ3JvdXAncyBsYXRlc3QgbGlzdCB3YXMgY3V0IGF0IDUwMC5cbiAgcHVibGljIHRydW5jYXRlZChncm91cElkOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICB0aGlzLl9zeW5jTG9hZCgpO1xuXG4gICAgcmV0dXJuIHRoaXMuX3N0cmVhbXMuZ2V0KGdyb3VwSWQpPy50cnVuY2F0ZWQgPz8gZmFsc2U7XG4gIH1cblxuICAvLyBXaGV0aGVyIHRoZSBncm91cCdzIGxhdGVzdCByZXF1ZXN0IGZhaWxlZC4gSXRzIGxpc3QgaXMgdGhlbiBlbXB0eSwgYW5kXG4gIC8vIHRoZSBuZXh0IGFzayBmZXRjaGVzIGFnYWluLlxuICBwdWJsaWMgZmFpbGVkKGdyb3VwSWQ6IG51bWJlcik6IGJvb2xlYW4ge1xuICAgIHRoaXMuX3N5bmNMb2FkKCk7XG5cbiAgICByZXR1cm4gdGhpcy5fc3RyZWFtcy5nZXQoZ3JvdXBJZCk/LmZhaWxlZCA/PyBmYWxzZTtcbiAgfVxuXG4gIC8vIFNlbmRzIGEgcmVxdWVzdCB3aGVuIHRoZSBzaWduYXR1cmUgbW92ZWQsIG9yIHdoZW4gYSBwaWNrIGhhcyBubyBuYW1lXG4gIC8vIHlldCBhbmQgd2FzIG5ldmVyIGFza2VkIGZvci4gUmV0dXJucyB0aGUgbnVtYmVyIG9mIHRoZSByZXF1ZXN0IHdob3NlXG4gIC8vIGFuc3dlciB0aGUgY2FsbGVyIHRha2VzOiB0aGUgb25lIHNlbnQsIGVsc2UgdGhlIGxhdGVzdC5cbiAgcHJpdmF0ZSBfYXNrKFxuICAgIHN0cmVhbTogUmVwb3J0RmlsdGVyT3B0aW9uc1N0cmVhbSxcbiAgICBncm91cDogUmVwb3J0RmlsdGVyR3JvdXAsXG4gICAgcmVwb3J0OiBSZXBvcnQsXG4gICAgaG9zdDogUmVwb3J0RmlsdGVyLFxuICAgIG5hcnJvd2VkOiBib29sZWFuLFxuICApOiBudW1iZXIge1xuICAgIGNvbnN0IGJvZHkgPSBuYXJyb3dlZCA/IHRoaXMuX3JlcXVlc3QoZ3JvdXAsIHJlcG9ydCwgaG9zdCkgOiBudWxsO1xuICAgIC8vIFRoZSBob3N0IG1lbWJlciBpcyBwYXJ0IG9mIGl0OiBhIHJlcG9ydCBlZGl0IHRoYXQgbW92ZXMgdGhlIGdyb3VwJ3NcbiAgICAvLyBsaXN0IHRvIGFub3RoZXIgbWVtYmVyIG9yIGNvbHVtbiBsaXN0cyBhZ2Fpbi5cbiAgICBjb25zdCBzaWduYXR1cmUgPSBKU09OLnN0cmluZ2lmeShbaG9zdC5pZCwgaG9zdC5maWx0ZXJDb2x1bW4sIGJvZHk/LmZpbHRlcnMgPz8gbnVsbCwgYm9keT8ubWF0Y2hBbnlHcm91cElkcyA/PyBbXV0pO1xuICAgIGNvbnN0IHVubmFtZWQgPSAoYm9keT8uc2VsZWN0ZWQgPz8gW10pXG4gICAgICAuZmlsdGVyKCh2YWx1ZSkgPT4gdGhpcy5sYWJlbChncm91cC5pZCwgdmFsdWUpID09PSBudWxsICYmICF0aGlzLl9hc2tlZEZvcihncm91cC5pZCkuaGFzKFN0cmluZyh2YWx1ZSkpKTtcblxuICAgIGlmIChzaWduYXR1cmUgPT09IHN0cmVhbS5zaWduYXR1cmUgJiYgIXVubmFtZWQubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gc3RyZWFtLnNlcTtcbiAgICB9XG5cbiAgICB1bm5hbWVkLmZvckVhY2goKHZhbHVlKSA9PiB0aGlzLl9hc2tlZEZvcihncm91cC5pZCkuYWRkKFN0cmluZyh2YWx1ZSkpKTtcbiAgICBzdHJlYW0uc2lnbmF0dXJlID0gc2lnbmF0dXJlO1xuICAgIHN0cmVhbS5zZXEgKz0gMTtcbiAgICBzdHJlYW0ucmVxdWVzdHMkLm5leHQoeyBzZXE6IHN0cmVhbS5zZXEsIGZldGNoOiB0aGlzLl9mZXRjaChzdHJlYW0sIGdyb3VwLmlkLCByZXBvcnQuaWQsIGhvc3QuaWQsIGJvZHkpIH0pO1xuXG4gICAgcmV0dXJuIHN0cmVhbS5zZXE7XG4gIH1cblxuICAvLyBUaGUgbmFycm93ZWQgcmVxdWVzdCBmb3IgdGhlIGdyb3VwOiB3aGF0IGl0cyBob3N0IHRpbGUncyBkYXRhIHJlcXVlc3RcbiAgLy8gY2FycmllcyBub3csIG1pbnVzIHRoZSBlbnRyaWVzIHRoYXQgbXVzdCBub3QgbmFycm93IHRoZSBncm91cCdzIGxpc3QuXG4gIHByaXZhdGUgX3JlcXVlc3QoZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLCByZXBvcnQ6IFJlcG9ydCwgaG9zdDogUmVwb3J0RmlsdGVyKTogUmVwb3J0RmlsdGVyT3B0aW9uc1JlcXVlc3Qge1xuICAgIGNvbnN0IHRpbGUgPSByZXBvcnRDb21wb25lbnRzKHJlcG9ydCkuZmluZCgoY29tcG9uZW50KSA9PiBjb21wb25lbnQuaWQgPT09IGhvc3QuY29tcG9uZW50SWQpID8/IG51bGw7XG4gICAgY29uc3Qgc2VsZWN0ZWQgPSBncm91cFBpY2tzKHRoaXMuX2ZpbHRlclN0YXRlLnZhbHVlKGdyb3VwLmlkKSk7XG5cbiAgICBpZiAoIXRpbGUpIHtcbiAgICAgIHJldHVybiB7IGZpbHRlcnM6IFtdLCAuLi4oc2VsZWN0ZWQubGVuZ3RoID8geyBzZWxlY3RlZCB9IDoge30pIH07XG4gICAgfVxuXG4gICAgY29uc3Qgc25hcHNob3QgPSB0aGlzLl9maWx0ZXJTdGF0ZS5zbmFwc2hvdCgpO1xuICAgIC8vIEEgZ3JvdXAgd2hvc2Ugb25seSBtZW1iZXJzIGFyZSBpbmxpbmUgdmFsdWVzIGxpc3RzIHRocm91Z2ggYSB2YWx1ZSxcbiAgICAvLyB3aGljaCBjb21iaW5lcyBpdHMgZ3JvdXBzIGJ5IHRoZSB0aWxlIHJ1bGUgb3ZlciBpdHMgb3duIHBhZ2UuXG4gICAgY29uc3QgbWF0Y2hBbnlHcm91cElkcyA9IHRpbGUudHlwZSA9PT0gJ3ZhbHVlJ1xuICAgICAgPyB2YWx1ZXNNYXRjaEFueUdyb3VwSWRzKHJlcG9ydCwgdGlsZVBhZ2VJZChyZXBvcnQsIHRpbGUsIHNuYXBzaG90KSwgc25hcHNob3QpXG4gICAgICA6IHRpbGVEYXRhU3RhdGUocmVwb3J0LCB0aWxlLCBzbmFwc2hvdCkubWF0Y2hBbnlHcm91cElkcyA/PyBbXTtcbiAgICAvLyBVbmRlciAnYW55JyBhbm90aGVyIGdyb3VwIHRoaXMgb25lIGNvbWJpbmVzIHdpdGggZG9lcyBub3QgbGltaXQgd2hpY2hcbiAgICAvLyBvZiBpdHMgdmFsdWVzIGNhbiBzaG93IHJvd3MsIHNvIHRoZSBsaXN0IGxlYXZlcyBpdCBvdXQuXG4gICAgY29uc3QgY29tYmluZWQgPSBtYXRjaEFueUdyb3VwSWRzLmxlbmd0aCAmJiBpc01hdGNoQW55R3JvdXAoZ3JvdXAsIHRpbGVQYWdlSWQocmVwb3J0LCB0aWxlLCBzbmFwc2hvdCkpXG4gICAgICA/IG1hdGNoQW55R3JvdXBJZHNcbiAgICAgIDogW107XG4gICAgY29uc3QgZ3JvdXBPZiA9IG5ldyBNYXAoKHRpbGUuZmlsdGVycyA/PyBbXSkubWFwKChtZW1iZXIpID0+IFttZW1iZXIuaWQsIG1lbWJlci5maWx0ZXJHcm91cElkXSkpO1xuICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLl9maWx0ZXJTdGF0ZS5yZXNvbHZlRm9yQ29tcG9uZW50KHRpbGUpXG4gICAgICAuZmlsdGVyKChlbnRyeSkgPT4ge1xuICAgICAgICBjb25zdCBncm91cElkID0gZ3JvdXBPZi5nZXQoZW50cnkuZmlsdGVySWQpID8/IG51bGw7XG5cbiAgICAgICAgcmV0dXJuICFpc0Nyb3NzRW50cnkoZW50cnkpICYmIGdyb3VwSWQgIT09IGdyb3VwLmlkICYmICFjb21iaW5lZC5pbmNsdWRlcyhncm91cElkKTtcbiAgICAgIH0pO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGZpbHRlcnMsXG4gICAgICAuLi4obWF0Y2hBbnlHcm91cElkcy5sZW5ndGggPyB7IG1hdGNoQW55R3JvdXBJZHMgfSA6IHt9KSxcbiAgICAgIC4uLihzZWxlY3RlZC5sZW5ndGggPyB7IHNlbGVjdGVkIH0gOiB7fSksXG4gICAgfTtcbiAgfVxuXG4gIC8vIE9uZSByZXF1ZXN0J3MgYW5zd2VyIGFzIGEgbGlzdC4gQSBmYWlsZWQgcmVxdWVzdCBhbnN3ZXJzIGFuIGVtcHR5IGxpc3RcbiAgLy8gbWFya2VkIGZhaWxlZCwgYW5kIGNsZWFycyB0aGUgc2lnbmF0dXJlLCBzbyB0aGUgbmV4dCBhc2sgZmV0Y2hlcyBhZ2Fpbi5cbiAgcHJpdmF0ZSBfZmV0Y2goXG4gICAgc3RyZWFtOiBSZXBvcnRGaWx0ZXJPcHRpb25zU3RyZWFtLFxuICAgIGdyb3VwSWQ6IG51bWJlcixcbiAgICByZXBvcnRJZDogbnVtYmVyLFxuICAgIGZpbHRlcklkOiBudW1iZXIsXG4gICAgYm9keTogUmVwb3J0RmlsdGVyT3B0aW9uc1JlcXVlc3QgfCBudWxsLFxuICApOiBPYnNlcnZhYmxlPFJlcG9ydEZpbHRlck9wdGlvbnNMaXN0PiB7XG4gICAgY29uc3Qgc2VxID0gc3RyZWFtLnNlcTtcbiAgICAvLyBBbiBhbnN3ZXIgdGhhdCBsYW5kcyBhZnRlciB0aGUgcmVwb3J0IGxvYWRlZCBhZ2FpbiB0ZWFjaGVzIG5vIG5hbWUuXG4gICAgY29uc3QgbG9hZGVkID0gdGhpcy5fZmlsdGVyU3RhdGUucmVwb3J0KCk7XG4gICAgY29uc3QgYW5zd2VyJDogT2JzZXJ2YWJsZTxSZXBvcnRGaWx0ZXJPcHRpb25zPiA9IGJvZHlcbiAgICAgID8gdGhpcy5fcmVwb3J0RGF0YS5maWx0ZXJPcHRpb25zTmFycm93ZWQocmVwb3J0SWQsIGZpbHRlcklkLCBib2R5KVxuICAgICAgOiB0aGlzLl9yZXBvcnREYXRhLmZpbHRlck9wdGlvbnMocmVwb3J0SWQsIGZpbHRlcklkKVxuICAgICAgICAucGlwZShtYXAoKG9wdGlvbnM6IFJlcG9ydEZpbHRlck9wdGlvbltdKSA9PiAoeyBvcHRpb25zLCB0cnVuY2F0ZWQ6IGZhbHNlLCBuYXJyb3dlZEJ5OiBbXSwgc2VsZWN0ZWQ6IFtdIH0pKSk7XG5cbiAgICByZXR1cm4gYW5zd2VyJFxuICAgICAgLnBpcGUoXG4gICAgICAgIHRhcCgoYW5zd2VyKSA9PiB7XG4gICAgICAgICAgaWYgKHRoaXMuX2ZpbHRlclN0YXRlLnJlcG9ydCgpID09PSBsb2FkZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX3JlbWVtYmVyKGdyb3VwSWQsIFsuLi4oYW5zd2VyPy5vcHRpb25zID8/IFtdKSwgLi4uKGFuc3dlcj8uc2VsZWN0ZWQgPz8gW10pXSk7XG4gICAgICAgICAgfVxuICAgICAgICB9KSxcbiAgICAgICAgbWFwKChhbnN3ZXIpID0+ICh7XG4gICAgICAgICAgc2VxLFxuICAgICAgICAgIHRydW5jYXRlZDogISFhbnN3ZXI/LnRydW5jYXRlZCxcbiAgICAgICAgICBmYWlsZWQ6IGZhbHNlLFxuICAgICAgICAgIG9wdGlvbnM6IChhbnN3ZXI/Lm9wdGlvbnMgPz8gW10pLm1hcCgob3B0aW9uKSA9PiAoeyBuYW1lOiBvcHRpb24ubGFiZWwsIHZhbHVlOiBvcHRpb24udmFsdWUgfSkpLFxuICAgICAgICB9KSksXG4gICAgICAgIGNhdGNoRXJyb3IoKCkgPT4ge1xuICAgICAgICAgIHN0cmVhbS5zaWduYXR1cmUgPSBudWxsO1xuXG4gICAgICAgICAgcmV0dXJuIG9mKHsgc2VxLCB0cnVuY2F0ZWQ6IGZhbHNlLCBmYWlsZWQ6IHRydWUsIG9wdGlvbnM6IFtdIH0pO1xuICAgICAgICB9KSxcbiAgICAgICk7XG4gIH1cblxuICAvLyBUaGUgZ3JvdXAncyBzdHJlYW0sIG9wZW5lZCBvbiBpdHMgZmlyc3QgYXNrLiBJdCBpcyBzdWJzY3JpYmVkIHRvIGhlcmUsXG4gIC8vIGZvciB0aGUgbGlmZSBvZiB0aGUgcmVwb3J0IHZpZXcsIHNvIGFuIGFuc3dlciBpcyBrZXB0IGZvciB0aGUgbmV4dCBhc2tcbiAgLy8gZXZlbiB3aGVuIHRoZSBjb250cm9sIHRoYXQgYXNrZWQgaGFzIG1vdmVkIG9uLiBXaGVuIHRoZSB2aWV3IGdvZXMsIHRoZVxuICAvLyBzdHJlYW0gZW5kczogYSByZXF1ZXN0IHN0aWxsIGluIGZsaWdodCBpcyBkcm9wcGVkLCB3aG9ldmVyIHN0aWxsIGxpc3RlbnMuXG4gIHByaXZhdGUgX3N0cmVhbShncm91cElkOiBudW1iZXIpOiBSZXBvcnRGaWx0ZXJPcHRpb25zU3RyZWFtIHtcbiAgICBjb25zdCBleGlzdGluZyA9IHRoaXMuX3N0cmVhbXMuZ2V0KGdyb3VwSWQpO1xuICAgIGlmIChleGlzdGluZykge1xuICAgICAgcmV0dXJuIGV4aXN0aW5nO1xuICAgIH1cblxuICAgIGNvbnN0IHJlcXVlc3RzJCA9IG5ldyBTdWJqZWN0PFJlcG9ydEZpbHRlck9wdGlvbnNBc2s+KCk7XG4gICAgY29uc3Qgc3RyZWFtOiBSZXBvcnRGaWx0ZXJPcHRpb25zU3RyZWFtID0ge1xuICAgICAgc2lnbmF0dXJlOiBudWxsLFxuICAgICAgc2VxOiAwLFxuICAgICAgdHJ1bmNhdGVkOiBmYWxzZSxcbiAgICAgIGZhaWxlZDogZmFsc2UsXG4gICAgICByZXF1ZXN0cyQsXG4gICAgICBsaXN0cyQ6IHJlcXVlc3RzJFxuICAgICAgICAucGlwZShcbiAgICAgICAgICBzd2l0Y2hNYXAoKHJlcXVlc3QpID0+IHJlcXVlc3QuZmV0Y2gpLFxuICAgICAgICAgIHRhcCgobGlzdCkgPT4ge1xuICAgICAgICAgICAgc3RyZWFtLnRydW5jYXRlZCA9IGxpc3QudHJ1bmNhdGVkO1xuICAgICAgICAgICAgc3RyZWFtLmZhaWxlZCA9IGxpc3QuZmFpbGVkO1xuICAgICAgICAgIH0pLFxuICAgICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgICAgICBzaGFyZVJlcGxheSh7IGJ1ZmZlclNpemU6IDEsIHJlZkNvdW50OiBmYWxzZSB9KSxcbiAgICAgICAgKSxcbiAgICB9O1xuXG4gICAgLy8gRW5kcyB3aXRoIHRoZSBzdHJlYW0sIHdoZW4gdGhlIHZpZXcgZ29lcy5cbiAgICBzdHJlYW0ubGlzdHMkLnN1YnNjcmliZSgpO1xuICAgIHRoaXMuX3N0cmVhbXMuc2V0KGdyb3VwSWQsIHN0cmVhbSk7XG5cbiAgICByZXR1cm4gc3RyZWFtO1xuICB9XG5cbiAgLy8gQSBuZXcgbG9hZCBvZiB0aGUgcmVwb3J0IChpbml0KCkgcmVhZCBhbm90aGVyIHJlcG9ydCBvYmplY3QpIGRyb3BzIHdoYXRcbiAgLy8gdGhlIGxhc3QgbG9hZCBsZWFybmVkOiBldmVyeSBzaWduYXR1cmUsIHNvIGVhY2ggbGlzdCBpcyBmZXRjaGVkIGFnYWluIG9uXG4gIC8vIGl0cyBuZXh0IGFzaywgYW5kIGV2ZXJ5IG5hbWUgYW5kIGFza2VkIHBpY2suXG4gIHByaXZhdGUgX3N5bmNMb2FkKCk6IHZvaWQge1xuICAgIGNvbnN0IGxvYWRlZCA9IHRoaXMuX2ZpbHRlclN0YXRlLnJlcG9ydCgpO1xuICAgIGlmIChsb2FkZWQgPT09IHRoaXMuX2xvYWRlZCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRoaXMuX2xvYWRlZCA9IGxvYWRlZDtcbiAgICB0aGlzLl9zdHJlYW1zLmZvckVhY2goKHN0cmVhbSkgPT4ge1xuICAgICAgc3RyZWFtLnNpZ25hdHVyZSA9IG51bGw7XG4gICAgfSk7XG4gICAgdGhpcy5fbGFiZWxzLmNsZWFyKCk7XG4gICAgdGhpcy5fYXNrZWQuY2xlYXIoKTtcbiAgfVxuXG4gIHByaXZhdGUgX3JlbWVtYmVyKGdyb3VwSWQ6IG51bWJlciwgb3B0aW9uczogUmVwb3J0RmlsdGVyT3B0aW9uW10pOiB2b2lkIHtcbiAgICBjb25zdCBsYWJlbHMgPSB0aGlzLl9sYWJlbHMuZ2V0KGdyb3VwSWQpID8/IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmc+KCk7XG5cbiAgICBmb3IgKGNvbnN0IG9wdGlvbiBvZiBvcHRpb25zKSB7XG4gICAgICBpZiAob3B0aW9uICYmIHR5cGVvZiBvcHRpb24ubGFiZWwgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGxhYmVscy5zZXQoU3RyaW5nKG9wdGlvbi52YWx1ZSksIG9wdGlvbi5sYWJlbCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5fbGFiZWxzLnNldChncm91cElkLCBsYWJlbHMpO1xuICB9XG5cbiAgcHJpdmF0ZSBfYXNrZWRGb3IoZ3JvdXBJZDogbnVtYmVyKTogU2V0PHN0cmluZz4ge1xuICAgIGNvbnN0IGFza2VkID0gdGhpcy5fYXNrZWQuZ2V0KGdyb3VwSWQpID8/IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgIHRoaXMuX2Fza2VkLnNldChncm91cElkLCBhc2tlZCk7XG5cbiAgICByZXR1cm4gYXNrZWQ7XG4gIH1cbn1cblxuXG4vLyBUaGUgbWVtYmVyIHdob3NlIGxpc3QgYSBncm91cCBzaG93cy4gVGhlIG5hcnJvd2VkIFBPU1QgbmFtZXMgdGhlIHNlcnZlcidzXG4vLyBob3N0OiB0aGUgZmlyc3QgZW5hYmxlZCBtZW1iZXIgd2l0aCBvcHRpb25zLCBlbHNlIHRoZSBmaXJzdCB3aXRoIG9wdGlvbnMuXG4vLyBUaGUgb3B0aW9ucyBHRVQga2VlcHMgaXRzIG9sZGVyIHJ1bGUsIHRoZSBmaXJzdCBtZW1iZXIgd2l0aCBvcHRpb25zLCBhc1xuLy8gbG9hZEdyb3VwT3B0aW9ucyBkb2VzLCBzbyBhbiBvbGRlciBzZXJ2ZXIgaXMgYXNrZWQgd2hhdCBpdCBhbHdheXMgd2FzLlxuZnVuY3Rpb24gb3B0aW9uc0hvc3QoZ3JvdXA6IFJlcG9ydEZpbHRlckdyb3VwLCBuYXJyb3dlZDogYm9vbGVhbik6IFJlcG9ydEZpbHRlciB8IG51bGwge1xuICBjb25zdCBtZW1iZXJzID0gKGdyb3VwLmZpbHRlcnMgPz8gW10pLmZpbHRlcigobWVtYmVyKSA9PiBtZW1iZXIuaGFzT3B0aW9ucyk7XG5cbiAgcmV0dXJuIChuYXJyb3dlZCA/IG1lbWJlcnMuZmluZCgobWVtYmVyKSA9PiBtZW1iZXIuZW5hYmxlZCkgOiBudWxsKSA/PyBtZW1iZXJzWzBdID8/IG51bGw7XG59XG5cbi8vIEEgY3Jvc3MtZmlsdGVyIGVudHJ5IHJpZGVzIGluIHRoZSBzYW1lIGZpbHRlcnMgYXJyYXkgYXMgdGhlIGdyb3VwIGVudHJpZXNcbi8vIGFuZCBjYXJyaWVzIGl0cyBjcm9zc0ZpbHRlcklkLiBJdCBuZXZlciBuYXJyb3dzIGEgbGlzdDogYSBjbGljayBpcyBhXG4vLyB0ZW1wb3JhcnkgbG9vaywgYW5kIHRoZSBjaGlwIG9mIHRoZSBjcm9zcy1maWx0ZXIgYWxyZWFkeSBzaG93cyBpdC5cbmZ1bmN0aW9uIGlzQ3Jvc3NFbnRyeShlbnRyeTogUmVzb2x2ZWRGaWx0ZXJWYWx1ZSk6IGJvb2xlYW4ge1xuICByZXR1cm4gJ2Nyb3NzRmlsdGVySWQnIGluIGVudHJ5O1xufVxuXG4vLyBBIHNlbGVjdCBncm91cCdzIHBpY2tzLCBrZXB0IG9yIGxlZnQgb3V0LCB0aGF0IGEgcmVxdWVzdCBjYW4gbmFtZTogdGV4dFxuLy8gYW5kIG51bWJlcnMsIGF0IG1vc3QgU0VMRUNURURfQ0FQLlxuZnVuY3Rpb24gZ3JvdXBQaWNrcyh2YWx1ZTogRmlsdGVyR3JvdXBWYWx1ZSB8IHVuZGVmaW5lZCk6IChzdHJpbmcgfCBudW1iZXIpW10ge1xuICByZXR1cm4gWy4uLih2YWx1ZT8udmFsdWVzID8/IFtdKSwgLi4uKHZhbHVlPy5leGNsdWRlVmFsdWVzID8/IFtdKV1cbiAgICAuZmlsdGVyKChwaWNrKTogcGljayBpcyBzdHJpbmcgfCBudW1iZXIgPT4gdHlwZW9mIHBpY2sgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiBwaWNrID09PSAnbnVtYmVyJylcbiAgICAuc2xpY2UoMCwgU0VMRUNURURfQ0FQKTtcbn1cbiJdfQ==