@firestitch/report 18.6.0 → 18.7.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 (76) hide show
  1. package/app/reports/components/component-chart/component-chart.component.d.ts +6 -7
  2. package/app/reports/components/component-kpi/component-kpi.component.d.ts +8 -8
  3. package/app/reports/components/component-list/component-list.component.d.ts +33 -11
  4. package/app/reports/components/report-component/report-component.component.d.ts +3 -0
  5. package/app/reports/data/report.data.d.ts +2 -1
  6. package/app/reports/dialogs/list-columns/list-columns.component.d.ts +23 -0
  7. package/app/reports/dialogs/report-settings/report-locale-patch.d.ts +5 -0
  8. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +20 -1
  9. package/app/reports/enums/report-chart-color.enum.d.ts +12 -0
  10. package/app/reports/enums/report-chart-data-labels.enum.d.ts +6 -0
  11. package/app/reports/enums/report-chart-date-label.enum.d.ts +5 -0
  12. package/app/reports/enums/report-chart-line-style.enum.d.ts +5 -0
  13. package/app/reports/enums/report-chart-mark-stat.enum.d.ts +6 -0
  14. package/app/reports/enums/report-list-column-format.enum.d.ts +6 -0
  15. package/app/reports/enums/report-number-units.enum.d.ts +6 -0
  16. package/app/reports/enums/report-value-format.enum.d.ts +5 -0
  17. package/app/reports/export/offscreen-chart.d.ts +2 -2
  18. package/app/reports/export/report-export-collector.service.d.ts +12 -9
  19. package/app/reports/export/report-pdf.service.d.ts +1 -0
  20. package/app/reports/export/report-pptx.service.d.ts +17 -0
  21. package/app/reports/format.d.ts +39 -4
  22. package/app/reports/interfaces/report.interface.d.ts +82 -10
  23. package/app/reports/list-config.d.ts +9 -0
  24. package/app/reports/option-builder.d.ts +69 -8
  25. package/app/reports/pipes/report-date.pipe.d.ts +2 -1
  26. package/app/reports/pipes/report-number.pipe.d.ts +8 -0
  27. package/app/reports/report-filter-items.d.ts +5 -2
  28. package/app/reports/report-url-state.d.ts +5 -0
  29. package/app/reports/services/report-filter-state.service.d.ts +29 -2
  30. package/app/reports/theme/palette.d.ts +3 -0
  31. package/app/reports/theme/typography.d.ts +1 -0
  32. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +19 -20
  33. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +23 -26
  34. package/esm2022/app/reports/components/component-list/component-list.component.mjs +157 -53
  35. package/esm2022/app/reports/components/report-component/report-component.component.mjs +81 -19
  36. package/esm2022/app/reports/data/report.data.mjs +17 -4
  37. package/esm2022/app/reports/dialogs/global-settings/global-settings.component.mjs +2 -2
  38. package/esm2022/app/reports/dialogs/list-columns/list-columns.component.mjs +56 -0
  39. package/esm2022/app/reports/dialogs/report-settings/report-locale-patch.mjs +13 -0
  40. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +137 -15
  41. package/esm2022/app/reports/enums/report-chart-color.enum.mjs +19 -0
  42. package/esm2022/app/reports/enums/report-chart-data-labels.enum.mjs +13 -0
  43. package/esm2022/app/reports/enums/report-chart-date-label.enum.mjs +13 -0
  44. package/esm2022/app/reports/enums/report-chart-line-style.enum.mjs +12 -0
  45. package/esm2022/app/reports/enums/report-chart-mark-stat.enum.mjs +12 -0
  46. package/esm2022/app/reports/enums/report-list-column-format.enum.mjs +14 -0
  47. package/esm2022/app/reports/enums/report-number-units.enum.mjs +14 -0
  48. package/esm2022/app/reports/enums/report-value-format.enum.mjs +13 -0
  49. package/esm2022/app/reports/export/offscreen-chart.mjs +5 -4
  50. package/esm2022/app/reports/export/report-export-collector.service.mjs +96 -39
  51. package/esm2022/app/reports/export/report-pdf.service.mjs +94 -37
  52. package/esm2022/app/reports/export/report-pptx.service.mjs +482 -85
  53. package/esm2022/app/reports/format.mjs +502 -57
  54. package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
  55. package/esm2022/app/reports/list-config.mjs +74 -0
  56. package/esm2022/app/reports/option-builder.mjs +880 -95
  57. package/esm2022/app/reports/pipes/report-date.pipe.mjs +7 -6
  58. package/esm2022/app/reports/pipes/report-number.pipe.mjs +25 -0
  59. package/esm2022/app/reports/report-filter-items.mjs +28 -3
  60. package/esm2022/app/reports/report-url-state.mjs +60 -15
  61. package/esm2022/app/reports/services/report-filter-state.service.mjs +275 -29
  62. package/esm2022/app/reports/theme/echarts.mjs +8 -2
  63. package/esm2022/app/reports/theme/palette.mjs +19 -1
  64. package/esm2022/app/reports/theme/typography.mjs +4 -1
  65. package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +11 -4
  66. package/esm2022/app/reports/views/report/report.component.mjs +6 -2
  67. package/esm2022/public_api.mjs +9 -1
  68. package/fesm2022/{firestitch-report-echarts-B9nl9XKM.mjs → firestitch-report-echarts-u5ImuZT5.mjs} +9 -3
  69. package/fesm2022/firestitch-report-echarts-u5ImuZT5.mjs.map +1 -0
  70. package/fesm2022/{firestitch-report-firestitch-report-Bb65HEYB.mjs → firestitch-report-firestitch-report-Cz-kA_id.mjs} +3213 -613
  71. package/fesm2022/firestitch-report-firestitch-report-Cz-kA_id.mjs.map +1 -0
  72. package/fesm2022/firestitch-report.mjs +1 -1
  73. package/package.json +1 -1
  74. package/public_api.d.ts +8 -0
  75. package/fesm2022/firestitch-report-echarts-B9nl9XKM.mjs.map +0 -1
  76. package/fesm2022/firestitch-report-firestitch-report-Bb65HEYB.mjs.map +0 -1
@@ -1,10 +1,15 @@
1
- import { ChangeDetectionStrategy, Component, DestroyRef, Input, ViewChild, inject, signal } from '@angular/core';
1
+ import { NgTemplateOutlet } from '@angular/common';
2
+ import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, Injector, afterNextRender, computed, effect, inject, input, signal, untracked, viewChild, } from '@angular/core';
2
3
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
4
  import { FsListComponent, FsListModule, PaginationStrategy } from '@firestitch/list';
4
- import { map } from 'rxjs';
5
+ import { map, merge, tap } from 'rxjs';
5
6
  import { ReportData } from '../../data/report.data';
6
- import { formatPeriodLabel } from '../../option-builder';
7
+ import { ReportListColumnFormat } from '../../enums/report-list-column-format.enum';
8
+ import { formatPlainNumber, hasNumberFormat } from '../../format';
9
+ import { LIST_TOTAL_LABEL, columnClasses, listPinnedColumns, listSortTerms, listTotalsLabelColumn, } from '../../list-config';
10
+ import { pivotColumnSpecs } from '../../option-builder';
7
11
  import { ReportDatePipe } from '../../pipes/report-date.pipe';
12
+ import { ReportNumberPipe } from '../../pipes/report-number.pipe';
8
13
  import { ReportFilterStateService } from '../../services/report-filter-state.service';
9
14
  import * as i0 from "@angular/core";
10
15
  import * as i1 from "@firestitch/list";
@@ -15,14 +20,16 @@ import * as i1 from "@firestitch/list";
15
20
  // every request takes its values from the shared filter-state service.
16
21
  // Paging and sorting are pushed into the SQL wrap server-side.
17
22
  export class ComponentListComponent {
18
- reportId;
19
- component;
20
- listComponent;
23
+ reportId = input.required();
24
+ component = input.required();
25
+ listComponent = viewChild(FsListComponent);
21
26
  listConfig;
22
27
  // A plain list's columns are authored and fixed at init. A cross-tab's are
23
28
  // the pivot dimension's VALUES, so they arrive with the rows and change
24
29
  // whenever the filters do — which is why this is a signal rather than the
25
- // one-shot read it used to be.
30
+ // one-shot read it used to be. `numeric` marks a column whose cells are
31
+ // formatted numbers, decided once here rather than per cell, so the column
32
+ // and its header are right-aligned.
26
33
  columns = signal([]);
27
34
  // A cross-tab sorts only by its row-key column: every other header is a
28
35
  // pivot value, and the server orders the long rows before pivoting, so a
@@ -35,28 +42,92 @@ export class ComponentListComponent {
35
42
  // (it only renders what _load() fetched, which lists skip), so the warning
36
43
  // belongs here.
37
44
  truncated = signal(false);
45
+ // Why the search box did not narrow the rows (the list has no text column to
46
+ // search), from the latest page 1; null when the search applied or none was
47
+ // made.
48
+ searchNote = signal(null);
49
+ // config.totals, read once at init: a list with totals renders its columns
50
+ // with a footer template, which fs-list reads only when it builds them.
51
+ showTotals = signal(false);
52
+ // The totals row from the latest page 1, raw values keyed like the columns;
53
+ // null when the list has none, or the server says why in totalsNote.
54
+ totals = signal(null);
55
+ totalsNote = signal(null);
56
+ // How many rows the list shows (load more appends) out of how many its
57
+ // filters keep. A cross-tab counts grid rows.
58
+ rowCount = signal(null);
38
59
  // The report's effective zone, which date cells render in. Injected right
39
60
  // here rather than read off _filterState, which is declared further down and
40
61
  // is still undefined while this initializer runs.
41
62
  timezone = inject(ReportFilterStateService).timezone;
63
+ // The open report's format context: date cells, number cells and a
64
+ // cross-tab's period headings are written in its locale (and money in its
65
+ // currency). Injected here for the same reason.
66
+ formatContext = inject(ReportFilterStateService).formatContext;
67
+ ReportListColumnFormat = ReportListColumnFormat;
68
+ // How many leading columns stay in view while the list scrolls sideways.
69
+ pinned = computed(() => listPinnedColumns(this.component().config));
70
+ columnClasses = columnClasses;
71
+ // The config columns the viewer hid on this list (the Columns dialog, or the
72
+ // URL). fs-list hides and shows them in place through [show], so the rows
73
+ // already fetched stand.
74
+ hidden = computed(() => new Set(this._filterState.hiddenColumns(this.component().id)));
75
+ totalLabel = LIST_TOTAL_LABEL;
76
+ // The column whose footer cell reads 'Total': the first one shown, unless
77
+ // it holds a total itself.
78
+ totalsLabelColumn = computed(() => listTotalsLabelColumn(this.columns().filter((column) => !this.hidden().has(column.column)), this.totals()));
79
+ // The line under the list: its row count, then why it has no totals and why
80
+ // its search narrowed nothing. The digits are written in the report's
81
+ // locale, never the app's.
82
+ caption = computed(() => {
83
+ const count = this.rowCount();
84
+ const locale = this.formatContext().locale;
85
+ const parts = [];
86
+ if (count) {
87
+ const total = formatPlainNumber(count.total, locale);
88
+ parts.push(count.shown < count.total
89
+ ? `Showing ${formatPlainNumber(count.shown, locale)} of ${total}`
90
+ : `${total} row(s)`);
91
+ }
92
+ return [...parts, this.totalsNote(), this.searchNote()]
93
+ .filter((part) => !!part)
94
+ .join(' · ');
95
+ });
42
96
  _reportData = inject(ReportData);
43
97
  _filterState = inject(ReportFilterStateService);
44
98
  _destroyRef = inject(DestroyRef);
99
+ _elementRef = inject(ElementRef);
100
+ _injector = inject(Injector);
101
+ _pinOffsetsRef = null;
102
+ constructor() {
103
+ // Hiding or showing a column moves the pinned columns after it.
104
+ effect(() => {
105
+ this.hidden();
106
+ untracked(() => this._schedulePinOffsets());
107
+ });
108
+ }
45
109
  ngOnInit() {
46
- const config = (this.component.config ?? {});
110
+ const component = this.component();
111
+ const config = (component.config ?? {});
47
112
  this.pivoted.set(!!config.pivotBy?.column);
48
- this.columns.set(config.columns ?? []);
113
+ this.showTotals.set(config.totals === true);
114
+ this.columns.set((config.columns ?? []).map((column) => ({ ...column, numeric: hasNumberFormat(column) })));
49
115
  this._initListConfig(config);
116
+ this._observePinOffsets();
50
117
  // A change to any group this list's filters belong to (from the report bar
51
118
  // or the component header strip) re-runs the list.
52
- this._filterState.changesFor(this.component)
53
- .pipe(takeUntilDestroyed(this._destroyRef))
54
- .subscribe(() => this.listComponent?.reload());
119
+ // So does a change of the text in its search box (in the component header).
120
+ merge(this._filterState.changesFor(component), this._filterState.listSearchChanges(component.id))
121
+ .pipe(tap(() => this.listComponent()?.reload()), takeUntilDestroyed(this._destroyRef))
122
+ .subscribe();
55
123
  }
56
124
  _initListConfig(config) {
57
125
  // The viewer's last sort wins over the authored one, so a list recreated
58
126
  // in the same session (page switch, reload after an edit) keeps it.
59
- const sort = this._filterState.listSort(this.component.id) ?? config.sort;
127
+ // fs-list holds one sorting column, so it shows the authored sort's first
128
+ // term; the request sends only that term and the server appends the rest.
129
+ const sort = this._filterState.listSort(this.component().id)
130
+ ?? listSortTerms(config)[0];
60
131
  this.listConfig = {
61
132
  // Inside a report component the list is a clean data pane — no status
62
133
  // bar, no reload button (filter changes already refetch).
@@ -108,12 +179,17 @@ export class ComponentListComponent {
108
179
  const [column, direction] = order.split(',');
109
180
  state.sort = { column, direction: direction === 'desc' ? 'desc' : 'asc' };
110
181
  }
111
- this._filterState.setListSort(this.component.id, state.sort ?? null);
182
+ const component = this.component();
183
+ this._filterState.setListSort(component, state.sort ?? null);
184
+ const search = this._filterState.listSearch(component.id);
185
+ if (search) {
186
+ state.search = search;
187
+ }
112
188
  // One source for filter values, the same one charts, KPIs and the exports
113
189
  // read, so the list is filtered exactly as its header strip shows.
114
- const filters = this._filterState.resolveForComponent(this.component);
190
+ const filters = this._filterState.resolveForComponent(component);
115
191
  return this._reportData
116
- .componentData(this.reportId, this.component.id, filters, state)
192
+ .componentData(this.reportId(), component.id, filters, state)
117
193
  .pipe(map((data) => {
118
194
  // A cross-tab's headers come back with the rows: the row-key column
119
195
  // first, then one per pivot value. Re-read them on every fetch, since
@@ -122,6 +198,20 @@ export class ComponentListComponent {
122
198
  this.columns.set(this._pivotColumns(data));
123
199
  this.truncated.set(!!data.truncated);
124
200
  }
201
+ // Only page 1 carries the notes and the totals; a load-more page
202
+ // leaves them as they are.
203
+ if (state.page === 1) {
204
+ this.searchNote.set(data.searchNote ?? null);
205
+ this.totals.set(data.totals ?? null);
206
+ this.totalsNote.set(data.totalsNote ?? null);
207
+ }
208
+ // The server's page size when it sends one (it clamps the request),
209
+ // the size the paging below hands fs-list too.
210
+ const size = data.paging?.pageSize ?? state.pageSize;
211
+ const shown = (state.page - 1) * size + (data.rows?.length ?? 0);
212
+ this.rowCount.set({ shown, total: data.paging?.total ?? shown });
213
+ // New rows can widen a pinned column, which moves the ones after it.
214
+ this._schedulePinOffsets();
125
215
  return {
126
216
  data: data.rows ?? [],
127
217
  paging: {
@@ -132,50 +222,64 @@ export class ComponentListComponent {
132
222
  };
133
223
  }));
134
224
  }
135
- // A cross-tab's columns, built from the wire. The first is the row key and
136
- // keeps its authored label; the rest are pivot VALUES used as headings. When
137
- // the pivot axis is a time dimension the server sends the grain it bucketed
138
- // at, so a period-start like "2026-01-01" is shown as "Jan 2026" — the same
139
- // formatter the chart's x-axis uses, so a grid and a chart of the same query
140
- // label their periods identically.
225
+ // A cross-tab's columns, built from the wire by pivotColumnSpecs(): the same
226
+ // headings and cell format the PDF and PowerPoint exports use.
141
227
  _pivotColumns(data) {
142
- const config = (this.component.config ?? {});
143
- const granularity = data.granularity;
144
- const multiYear = this._spansMultipleYears(data.columns ?? []);
145
- return (data.columns ?? []).map((column, index) => {
146
- if (index === 0) {
147
- return { column, label: config.rowBy?.label || column };
148
- }
149
- return {
150
- column,
151
- label: granularity ? formatPeriodLabel(column, granularity, multiYear) : column,
152
- };
153
- });
228
+ const config = (this.component().config ?? {});
229
+ return pivotColumnSpecs(config, data, this.formatContext().locale);
230
+ }
231
+ // A tile resize reflows the table's auto layout, so the pinned columns'
232
+ // widths, and with them their offsets, change.
233
+ _observePinOffsets() {
234
+ if (this.pinned() < 2 || typeof ResizeObserver === 'undefined') {
235
+ return;
236
+ }
237
+ const observer = new ResizeObserver(() => this._schedulePinOffsets());
238
+ observer.observe(this._elementRef.nativeElement);
239
+ this._destroyRef.onDestroy(() => observer.disconnect());
240
+ }
241
+ // Measures the pinned offsets once the next render has laid the table out.
242
+ // One pending measurement covers every request made before it runs. Only
243
+ // afterNextRender exists in every Angular version this library runs on.
244
+ _schedulePinOffsets() {
245
+ if (this.pinned() < 2 || this._pinOffsetsRef) {
246
+ return;
247
+ }
248
+ this._pinOffsetsRef = afterNextRender(() => {
249
+ this._pinOffsetsRef = null;
250
+ this._updatePinOffsets();
251
+ }, { injector: this._injector });
154
252
  }
155
- // Whether the period columns cross a year boundary, which decides if the
156
- // formatter appends the year to each heading.
157
- _spansMultipleYears(columns) {
158
- const years = new Set(columns
159
- .map((column) => /^(\d{4})-\d{2}-\d{2}/.exec(column))
160
- .filter(Boolean)
161
- .map((match) => match[1]));
162
- return years.size > 1;
253
+ // Each pinned column sticks at the summed width of the visible pinned
254
+ // columns before it. A hidden column renders no header, so the next pinned
255
+ // one takes its place. A variable is written only when its value changed,
256
+ // which keeps a resize from restyling the table for nothing.
257
+ _updatePinOffsets() {
258
+ const host = this._elementRef.nativeElement;
259
+ let left = 0;
260
+ for (let index = 0; index < this.pinned(); index++) {
261
+ const header = host.querySelector(`thead th.report-pin-${index}`);
262
+ if (!header) {
263
+ continue;
264
+ }
265
+ const name = `--report-pin-left-${index}`;
266
+ const value = `${Math.round(left * 100) / 100}px`;
267
+ if (host.style.getPropertyValue(name) !== value) {
268
+ host.style.setProperty(name, value);
269
+ }
270
+ left += header.getBoundingClientRect().width;
271
+ }
163
272
  }
164
273
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
165
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentListComponent, isStandalone: true, selector: "app-report-component-list", inputs: { reportId: "reportId", component: "component" }, viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<fs-list [config]=\"listConfig\">\n @for (column of columns(); track column.column) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [sortable]=\"!pivoted() || $first\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (column.format === 'date') {\n {{ row[column.column] | fsReportDate: timezone() }}\n } @else {\n {{ row[column.column] }}\n }\n </ng-template>\n </fs-list-column>\n }\n</fs-list>\n", styles: [":host{display:block;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;height:100%;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines", "cellRowType"], outputs: ["filtersReady"] }, { kind: "directive", type: i1.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customizable", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1.FsListCellDirective, selector: "[fs-list-cell],[fsListCell]", inputs: ["colspan", "align", "class", "fsListCell", "configTyping"] }, { kind: "pipe", type: ReportDatePipe, name: "fsReportDate" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
274
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentListComponent, isStandalone: true, selector: "app-report-component-list", inputs: { reportId: { classPropertyName: "reportId", publicName: "reportId", isSignal: true, isRequired: true, transformFunction: null }, component: { classPropertyName: "component", publicName: "component", isSignal: true, isRequired: true, transformFunction: null } }, viewQueries: [{ propertyName: "listComponent", first: true, predicate: FsListComponent, descendants: true, isSignal: true }], ngImport: i0, template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<!-- fs-list reads a column's footer template once, as a direct child of\n fs-list-column, so a list with totals renders its columns in a branch of\n their own rather than wrapping the footer in an @if. -->\n<fs-list\n [config]=\"listConfig\"\n [class.report-totals-empty]=\"!totals()\">\n @if (showTotals()) {\n @for (column of columns(); track column.column) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], column: column }\">\n </ng-container>\n </ng-template>\n <ng-template fs-list-footer>\n @if (totals()?.[column.column] !== undefined) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: totals()?.[column.column], column: column }\">\n </ng-container>\n } @else if (column.column === totalsLabelColumn()) {\n {{ totalLabel }}\n }\n </ng-template>\n </fs-list-column>\n }\n } @else {\n @for (column of columns(); track column.column) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], column: column }\">\n </ng-container>\n </ng-template>\n </fs-list-column>\n }\n }\n</fs-list>\n\n@if (caption()) {\n <div class=\"list-caption small\">\n {{ caption() }}\n </div>\n}\n\n<!-- One cell, in the body and the totals row alike: a date column as a day in\n the report's zone and locale, any other through its number format. -->\n<ng-template\n #cellTpl\n let-value\n let-column=\"column\">\n @if (column.format === ReportListColumnFormat.Date) {\n {{ value | fsReportDate: timezone() : formatContext().locale }}\n } @else {\n {{ value | fsReportNumber: column : formatContext() }}\n }\n</ng-template>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;flex:1 1 auto;height:auto;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list .fs-list-table tfoot td{position:sticky;bottom:0;z-index:1;background-color:#fff;font-weight:500;box-shadow:inset 0 1px #0000001f}:host ::ng-deep fs-list.report-totals-empty tfoot{display:none}:host ::ng-deep fs-list .report-pinned{position:sticky;left:var(--report-pin-left, 0px);z-index:1;background-color:#fff}:host ::ng-deep fs-list .report-pin-0{--report-pin-left: var(--report-pin-left-0, 0px)}:host ::ng-deep fs-list .report-pin-1{--report-pin-left: var(--report-pin-left-1, 0px)}:host ::ng-deep fs-list .report-pin-2{--report-pin-left: var(--report-pin-left-2, 0px)}:host ::ng-deep fs-list .report-pin-last{box-shadow:inset -1px 0 #0000001f}:host ::ng-deep fs-list .fs-list-table thead th.report-pinned{z-index:3}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pinned{z-index:2}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pin-last{box-shadow:inset -1px 0 #0000001f,inset 0 1px #0000001f}:host ::ng-deep fs-list th.report-nowrap,:host ::ng-deep fs-list td.report-nowrap{white-space:nowrap}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.list-caption{flex:0 0 auto;padding-top:4px}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"], dependencies: [{ kind: "ngmodule", type: FsListModule }, { kind: "component", type: i1.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines", "cellRowType"], outputs: ["filtersReady"] }, { kind: "directive", type: i1.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customizable", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i1.FsListCellDirective, selector: "[fs-list-cell],[fsListCell]", inputs: ["colspan", "align", "class", "fsListCell", "configTyping"] }, { kind: "directive", type: i1.FsListFooterDirective, selector: "[fs-list-footer]", inputs: ["colspan", "align", "class"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "pipe", type: ReportDatePipe, name: "fsReportDate" }, { kind: "pipe", type: ReportNumberPipe, name: "fsReportNumber" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
166
275
  }
167
276
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentListComponent, decorators: [{
168
277
  type: Component,
169
278
  args: [{ selector: 'app-report-component-list', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
170
279
  FsListModule,
280
+ NgTemplateOutlet,
171
281
  ReportDatePipe,
172
- ], template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<fs-list [config]=\"listConfig\">\n @for (column of columns(); track column.column) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [sortable]=\"!pivoted() || $first\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n @if (column.format === 'date') {\n {{ row[column.column] | fsReportDate: timezone() }}\n } @else {\n {{ row[column.column] }}\n }\n </ng-template>\n </fs-list-column>\n }\n</fs-list>\n", styles: [":host{display:block;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;height:100%;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"] }]
173
- }], propDecorators: { reportId: [{
174
- type: Input
175
- }], component: [{
176
- type: Input
177
- }], listComponent: [{
178
- type: ViewChild,
179
- args: [FsListComponent]
180
- }] } });
181
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LWxpc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LWxpc3QvY29tcG9uZW50LWxpc3QuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LWxpc3QvY29tcG9uZW50LWxpc3QuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFVLFNBQVMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ3pILE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRWhFLE9BQU8sRUFBRSxlQUFlLEVBQWdCLFlBQVksRUFBRSxrQkFBa0IsRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBRW5HLE9BQU8sRUFBYyxHQUFHLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFdkMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBUXBELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQ3pELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQzs7O0FBR3RGLDhFQUE4RTtBQUM5RSxzRUFBc0U7QUFDdEUsOEVBQThFO0FBQzlFLDRFQUE0RTtBQUM1RSx1RUFBdUU7QUFDdkUsK0RBQStEO0FBWS9ELE1BQU0sT0FBTyxzQkFBc0I7SUFFakIsUUFBUSxDQUFTO0lBQ2pCLFNBQVMsQ0FBa0I7SUFHcEMsYUFBYSxDQUFrQjtJQUUvQixVQUFVLENBQWU7SUFFaEMsMkVBQTJFO0lBQzNF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bEMsU0FBUzsrQkFDRSwyQkFBMkIsbUJBR3BCLHVCQUF1QixDQUFDLE1BQU0sY0FDbkMsSUFBSSxXQUNQO3dCQUNQLFlBQVk7d0JBQ1osY0FBYztxQkFDZjs4QkFJZSxRQUFRO3NCQUF2QixLQUFLO2dCQUNVLFNBQVM7c0JBQXhCLEtBQUs7Z0JBR0MsYUFBYTtzQkFEbkIsU0FBUzt1QkFBQyxlQUFlIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRGVzdHJveVJlZiwgSW5wdXQsIE9uSW5pdCwgVmlld0NoaWxkLCBpbmplY3QsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuXG5pbXBvcnQgeyBGc0xpc3RDb21wb25lbnQsIEZzTGlzdENvbmZpZywgRnNMaXN0TW9kdWxlLCBQYWdpbmF0aW9uU3RyYXRlZ3kgfSBmcm9tICdAZmlyZXN0aXRjaC9saXN0JztcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgbWFwIH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IFJlcG9ydERhdGEgfSBmcm9tICcuLi8uLi9kYXRhL3JlcG9ydC5kYXRhJztcbmltcG9ydCB7XG4gIENvbXBvbmVudERhdGEsXG4gIENvbXBvbmVudERhdGFTdGF0ZSxcbiAgTGlzdENvbmZpZyxcbiAgUmVwb3J0Q29tcG9uZW50LFxuICBSZXBvcnRTb3J0LFxufSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgZm9ybWF0UGVyaW9kTGFiZWwgfSBmcm9tICcuLi8uLi9vcHRpb24tYnVpbGRlcic7XG5pbXBvcnQgeyBSZXBvcnREYXRlUGlwZSB9IGZyb20gJy4uLy4uL3BpcGVzL3JlcG9ydC1kYXRlLnBpcGUnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVwb3J0LWZpbHRlci1zdGF0ZS5zZXJ2aWNlJztcblxuXG4vLyBBIGxpc3QgY29tcG9uZW50OiBhbiBGc0xpc3QgcmVuZGVyZWQgZnJvbSB0aGUgY29tcG9uZW50J3MgY29uZmlnLiBJdCBoYXMgbm9cbi8vIGZpbHRlciBiYXIgb2YgaXRzIG93bjogaXRzIGZpbHRlcnMgYXJlIGdyb3VwLWtleWVkIGxpa2UgZXZlcnkgb3RoZXJcbi8vIGNvbXBvbmVudCdzLCBzbyBjb21wb25lbnQtbGV2ZWwgZ3JvdXBzIHJlbmRlciBpbiB0aGUgY29tcG9uZW50IGhlYWRlciBzdHJpcFxuLy8gKFJlcG9ydENvbXBvbmVudENvbXBvbmVudCkgYW5kIHJlcG9ydC1sZXZlbCBncm91cHMgaW4gdGhlIHJlcG9ydCBiYXIsIGFuZFxuLy8gZXZlcnkgcmVxdWVzdCB0YWtlcyBpdHMgdmFsdWVzIGZyb20gdGhlIHNoYXJlZCBmaWx0ZXItc3RhdGUgc2VydmljZS5cbi8vIFBhZ2luZyBhbmQgc29ydGluZyBhcmUgcHVzaGVkIGludG8gdGhlIFNRTCB3cmFwIHNlcnZlci1zaWRlLlxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLXJlcG9ydC1jb21wb25lbnQtbGlzdCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9jb21wb25lbnQtbGlzdC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2NvbXBvbmVudC1saXN0LmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgRnNMaXN0TW9kdWxlLFxuICAgIFJlcG9ydERhdGVQaXBlLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBDb21wb25lbnRMaXN0Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBASW5wdXQoKSBwdWJsaWMgcmVwb3J0SWQ6IG51bWJlcjtcbiAgQElucHV0KCkgcHVibGljIGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50O1xuXG4gIEBWaWV3Q2hpbGQoRnNMaXN0Q29tcG9uZW50KVxuICBwdWJsaWMgbGlzdENvbXBvbmVudDogRnNMaXN0Q29tcG9uZW50O1xuXG4gIHB1YmxpYyBsaXN0Q29uZmlnOiBGc0xpc3RDb25maWc7XG5cbiAgLy8gQSBwbGFpbiBsaXN0J3MgY29sdW1ucyBhcmUgYXV0aG9yZWQgYW5kIGZpeGVkIGF0IGluaXQuIEEgY3Jvc3MtdGFiJ3MgYXJlXG4gIC8vIHRoZSBwaXZvdCBkaW1lbnNpb24ncyBWQUxVRVMsIHNvIHRoZXkgYXJyaXZlIHdpdGggdGhlIHJvd3MgYW5kIGNoYW5nZVxuICAvLyB3aGVuZXZlciB0aGUgZmlsdGVycyBkbyDigJQgd2hpY2ggaXMgd2h5IHRoaXMgaXMgYSBzaWduYWwgcmF0aGVyIHRoYW4gdGhlXG4gIC8vIG9uZS1zaG90IHJlYWQgaXQgdXNlZCB0byBiZS5cbiAgcHVibGljIGNvbHVtbnMgPSBzaWduYWw8eyBjb2x1bW46IHN0cmluZzsgbGFiZWw/OiBzdHJpbmc7IGZvcm1hdD86IHN0cmluZyB9W10+KFtdKTtcblxuICAvLyBBIGNyb3NzLXRhYiBzb3J0cyBvbmx5IGJ5IGl0cyByb3cta2V5IGNvbHVtbjogZXZlcnkgb3RoZXIgaGVhZGVyIGlzIGFcbiAgLy8gcGl2b3QgdmFsdWUsIGFuZCB0aGUgc2VydmVyIG9yZGVycyB0aGUgbG9uZyByb3dzIGJlZm9yZSBwaXZvdGluZywgc28gYVxuICAvLyBjbGljayBvbiBcIk1hciAyMDI2XCIgaGFzIG5vdGhpbmcgdG8gb3JkZXIgYnkuXG4gIHB1YmxpYyBwaXZvdGVkID0gc2lnbmFsKGZhbHNlKTtcblxuICAvLyBBIGN1dCByZXN1bHQgaXMgd29yc2UgZm9yIGEgZ3JpZCB0aGFuIGZvciBhIGxpc3Q6IHRoZSBjdXQgbGFuZHMgb24gdGhlIExPTkdcbiAgLy8gcm93cyBiZWZvcmUgdGhlIHJlc2hhcGUsIHNvIGEgcGl2b3QgdmFsdWUgbGl2aW5nIG9ubHkgaW4gdGhlIHRhaWwgdmFuaXNoZXNcbiAgLy8gYXMgYSB3aG9sZSBDT0xVTU4gYW5kIHN0cmFkZGxlZCBjZWxscyBjb21lIGJhY2sgYmxhbmssIGluZGlzdGluZ3Vpc2hhYmxlXG4gIC8vIGZyb20gYSByZWFsIHplcm8uIFRoZSBwYXJlbnQncyB0cnVuY2F0aW9uIGJhbm5lciBuZXZlciBmaXJlcyBmb3IgYSBsaXN0XG4gIC8vIChpdCBvbmx5IHJlbmRlcnMgd2hhdCBfbG9hZCgpIGZldGNoZWQsIHdoaWNoIGxpc3RzIHNraXApLCBzbyB0aGUgd2FybmluZ1xuICAvLyBiZWxvbmdzIGhlcmUuXG4gIHB1YmxpYyB0cnVuY2F0ZWQgPSBzaWduYWwoZmFsc2UpO1xuXG4gIC8vIFRoZSByZXBvcnQncyBlZmZlY3RpdmUgem9uZSwgd2hpY2ggZGF0ZSBjZWxscyByZW5kZXIgaW4uIEluamVjdGVkIHJpZ2h0XG4gIC8vIGhlcmUgcmF0aGVyIHRoYW4gcmVhZCBvZmYgX2ZpbHRlclN0YXRlLCB3aGljaCBpcyBkZWNsYXJlZCBmdXJ0aGVyIGRvd24gYW5kXG4gIC8vIGlzIHN0aWxsIHVuZGVmaW5lZCB3aGlsZSB0aGlzIGluaXRpYWxpemVyIHJ1bnMuXG4gIHB1YmxpYyByZWFkb25seSB0aW1lem9uZSA9IGluamVjdChSZXBvcnRGaWx0ZXJTdGF0ZVNlcnZpY2UpLnRpbWV6b25lO1xuXG4gIHByaXZhdGUgX3JlcG9ydERhdGEgPSBpbmplY3QoUmVwb3J0RGF0YSk7XG4gIHByaXZhdGUgX2ZpbHRlclN0YXRlID0gaW5qZWN0KFJlcG9ydEZpbHRlclN0YXRlU2VydmljZSk7XG4gIHByaXZhdGUgX2Rlc3Ryb3lSZWYgPSBpbmplY3QoRGVzdHJveVJlZik7XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9ICh0aGlzLmNvbXBvbmVudC5jb25maWcgPz8ge30pIGFzIExpc3RDb25maWc7XG4gICAgdGhpcy5waXZvdGVkLnNldCghIWNvbmZpZy5waXZvdEJ5Py5jb2x1bW4pO1xuICAgIHRoaXMuY29sdW1ucy5zZXQoY29uZmlnLmNvbHVtbnMgPz8gW10pO1xuXG4gICAgdGhpcy5faW5pdExpc3RDb25maWcoY29uZmlnKTtcblxuICAgIC8vIEEgY2hhbmdlIHRvIGFueSBncm91cCB0aGlzIGxpc3QncyBmaWx0ZXJzIGJlbG9uZyB0byAoZnJvbSB0aGUgcmVwb3J0IGJhclxuICAgIC8vIG9yIHRoZSBjb21wb25lbnQgaGVhZGVyIHN0cmlwKSByZS1ydW5zIHRoZSBsaXN0LlxuICAgIHRoaXMuX2ZpbHRlclN0YXRlLmNoYW5nZXNGb3IodGhpcy5jb21wb25lbnQpXG4gICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZikpXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMubGlzdENvbXBvbmVudD8ucmVsb2FkKCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW5pdExpc3RDb25maWcoY29uZmlnOiBMaXN0Q29uZmlnKTogdm9pZCB7XG4gICAgLy8gVGhlIHZpZXdlcidzIGxhc3Qgc29ydCB3aW5zIG92ZXIgdGhlIGF1dGhvcmVkIG9uZSwgc28gYSBsaXN0IHJlY3JlYXRlZFxuICAgIC8vIGluIHRoZSBzYW1lIHNlc3Npb24gKHBhZ2Ugc3dpdGNoLCByZWxvYWQgYWZ0ZXIgYW4gZWRpdCkga2VlcHMgaXQuXG4gICAgY29uc3Qgc29ydDogUmVwb3J0U29ydCB8IHVuZGVmaW5lZCA9IHRoaXMuX2ZpbHRlclN0YXRlLmxpc3RTb3J0KHRoaXMuY29tcG9uZW50LmlkKSA/PyBjb25maWcuc29ydDtcblxuICAgIHRoaXMubGlzdENvbmZpZyA9IHtcbiAgICAgIC8vIEluc2lkZSBhIHJlcG9ydCBjb21wb25lbnQgdGhlIGxpc3QgaXMgYSBjbGVhbiBkYXRhIHBhbmUg4oCUIG5vIHN0YXR1c1xuICAgICAgLy8gYmFyLCBubyByZWxvYWQgYnV0dG9uIChmaWx0ZXIgY2hhbmdlcyBhbHJlYWR5IHJlZmV0Y2gpLlxuICAgICAgc3RhdHVzOiBmYWxzZSxcbiAgICAgIHJlbG9hZDogZmFsc2UsXG4gICAgICAvLyBGc0xpc3QgbmV2ZXIgdG91Y2hlcyB0aGUgVVJMIG9yIHBlcnNpc3RzIHNvcnQvcGFnaW5nIHN0YXRlLiBUaGUgc29ydFxuICAgICAgLy8gcmVhY2hlcyB0aGUgVVJMIHRocm91Z2ggUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIChzZXRMaXN0U29ydCksIGFuZFxuICAgICAgLy8gcGFnaW5nIHN0YXlzIG91dCBvZiBpdC5cbiAgICAgIHF1ZXJ5UGFyYW06IGZhbHNlLFxuICAgICAgcGVyc2lzdDogZmFsc2UsXG4gICAgICBzb3J0OiBzb3J0XG4gICAgICAgID8geyB2YWx1ZTogc29ydC5jb2x1bW4sIGRpcmVjdGlvbjogc29ydC5kaXJlY3Rpb24gPz8gJ2FzYycgfVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIC8vIExvYWQtbW9yZTogdGhlIGxpc3Qga2VlcHMgYSBmaXhlZCwgc2Nyb2xsYWJsZSBoZWlnaHQgYW5kIGFwcGVuZHMgdGhlXG4gICAgICAvLyBuZXh0IHBhZ2UgaW4gcGxhY2UgaW5zdGVhZCBvZiBzd2FwcGluZyBwYWdlcy4gVGhlIGJ1dHRvbiBpcyBwaW5uZWQgdG9cbiAgICAgIC8vIHRoZSBib3R0b20gb2YgdGhlIHNjcm9sbCBwYW5lIChzZWUgY29tcG9uZW50IFNDU1MpLlxuICAgICAgLy9cbiAgICAgIC8vIFVzZXMgdGhlIE9mZnNldCBzdHJhdGVneSAob2Zmc2V0ICsgbGltaXQpIHJhdGhlciB0aGFuIE1hbnk6IGluXG4gICAgICAvLyBAZmlyZXN0aXRjaC9saXN0IHRoZSBwYWdpbmF0aW9uIHRlbXBsYXRlIHJlc29sdmVzIGBoYXNNYW55U3RyYXRlZ3lgXG4gICAgICAvLyBCRUZPUkUgYGxvYWRNb3JlRW5hYmxlZGAsIGFuZCBNYW55IHJlbmRlcnMgYSBmb3J3YXJkLW9ubHkgcGFnZSBwYWdlciDigJRcbiAgICAgIC8vIHNvIE1hbnkgd291bGQgc3VwcHJlc3MgdGhlIGxvYWQtbW9yZSBidXR0b24gZW50aXJlbHkuIE9mZnNldCArIGxvYWRNb3JlXG4gICAgICAvLyBpcyB0aGUgY29tYmluYXRpb24gdGhhdCBhY3R1YWxseSByZW5kZXJzIGFuZCBhcHBlbmRzLiBgX2ZldGNoYCBhbHJlYWR5XG4gICAgICAvLyBkZXJpdmVzIGBwYWdlYCBmcm9tIGBvZmZzZXRgLCBzbyB0aGUgc2VydmVyLXNpZGUgd3JhcCBpcyB1bmFmZmVjdGVkLlxuICAgICAgcGFnaW5nOiB7XG4gICAgICAgIGxpbWl0OiBjb25maWcucGFnZVNpemUgPz8gMjUsXG4gICAgICAgIHN0cmF0ZWd5OiBQYWdpbmF0aW9uU3RyYXRlZ3kuT2Zmc2V0LFxuICAgICAgfSxcbiAgICAgIGxvYWRNb3JlOiB7XG4gICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgIGxhYmVsOiAnTG9hZCBtb3JlJyxcbiAgICAgICAgYnV0dG9uVHlwZTogJ3N0cm9rZWQnLFxuICAgICAgfSxcbiAgICAgIGZldGNoOiAocXVlcnk6IGFueSkgPT4gdGhpcy5fZmV0Y2gocXVlcnkpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIF9mZXRjaChxdWVyeTogYW55KTogT2JzZXJ2YWJsZTx7IGRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W107IHBhZ2luZzogYW55IH0+IHtcbiAgICAvLyBNYW55L2xvYWQtbW9yZSBzZW5kcyBgb2Zmc2V0YCArIGBsaW1pdGAgKG5vdCBgcGFnZWApOyBkZXJpdmUgdGhlIHBhZ2Ugc29cbiAgICAvLyB0aGUgc2VydmVyLXNpZGUgd3JhcCBrZWVwcyB3b3JraW5nIHVuY2hhbmdlZC4gUGFnZSBzdHJhdGVneSBzdGlsbCBzZW5kc1xuICAgIC8vIGBwYWdlYCBkaXJlY3RseS5cbiAgICBjb25zdCBwYWdlU2l6ZSA9IHF1ZXJ5LmxpbWl0ID8/IDI1O1xuICAgIGNvbnN0IHBhZ2UgPSBxdWVyeS5wYWdlXG4gICAgICA/PyAocXVlcnkub2Zmc2V0ICE9IG51bGwgPyBNYXRoLmZsb29yKHF1ZXJ5Lm9mZnNldCAvIHBhZ2VTaXplKSArIDEgOiAxKTtcblxuICAgIGNvbnN0IHN0YXRlOiBDb21wb25lbnREYXRhU3RhdGUgPSB7XG4gICAgICBwYWdlLFxuICAgICAgcGFnZVNpemUsXG4gICAgfTtcblxuICAgIGNvbnN0IG9yZGVyID0gU3RyaW5nKHF1ZXJ5Lm9yZGVyID8/ICcnKTtcbiAgICBpZiAob3JkZXIpIHtcbiAgICAgIGNvbnN0IFtjb2x1bW4sIGRpcmVjdGlvbl0gPSBvcmRlci5zcGxpdCgnLCcpO1xuICAgICAgc3RhdGUuc29ydCA9IHsgY29sdW1uLCBkaXJlY3Rpb246IGRpcmVjdGlvbiA9PT0gJ2Rlc2MnID8gJ2Rlc2MnIDogJ2FzYycgfTtcbiAgICB9XG5cbiAgICB0aGlzLl9maWx0ZXJTdGF0ZS5zZXRMaXN0U29ydCh0aGlzLmNvbXBvbmVudC5pZCwgc3RhdGUuc29ydCA/PyBudWxsKTtcblxuICAgIC8vIE9uZSBzb3VyY2UgZm9yIGZpbHRlciB2YWx1ZXMsIHRoZSBzYW1lIG9uZSBjaGFydHMsIEtQSXMgYW5kIHRoZSBleHBvcnRzXG4gICAgLy8gcmVhZCwgc28gdGhlIGxpc3QgaXMgZmlsdGVyZWQgZXhhY3RseSBhcyBpdHMgaGVhZGVyIHN0cmlwIHNob3dzLlxuICAgIGNvbnN0IGZpbHRlcnMgPSB0aGlzLl9maWx0ZXJTdGF0ZS5yZXNvbHZlRm9yQ29tcG9uZW50KHRoaXMuY29tcG9uZW50KTtcblxuICAgIHJldHVybiB0aGlzLl9yZXBvcnREYXRhXG4gICAgICAuY29tcG9uZW50RGF0YSh0aGlzLnJlcG9ydElkLCB0aGlzLmNvbXBvbmVudC5pZCwgZmlsdGVycywgc3RhdGUpXG4gICAgICAucGlwZShcbiAgICAgICAgbWFwKChkYXRhOiBDb21wb25lbnREYXRhKSA9PiB7XG4gICAgICAgICAgLy8gQSBjcm9zcy10YWIncyBoZWFkZXJzIGNvbWUgYmFjayB3aXRoIHRoZSByb3dzOiB0aGUgcm93LWtleSBjb2x1bW5cbiAgICAgICAgICAvLyBmaXJzdCwgdGhlbiBvbmUgcGVyIHBpdm90IHZhbHVlLiBSZS1yZWFkIHRoZW0gb24gZXZlcnkgZmV0Y2gsIHNpbmNlXG4gICAgICAgICAgLy8gYSBmaWx0ZXIgY2hhbmdlIGNhbiBhZGQgb3IgcmVtb3ZlIGEgY29sdW1uLlxuICAgICAgICAgIGlmICh0aGlzLnBpdm90ZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5zLnNldCh0aGlzLl9waXZvdENvbHVtbnMoZGF0YSkpO1xuICAgICAgICAgICAgdGhpcy50cnVuY2F0ZWQuc2V0KCEhZGF0YS50cnVuY2F0ZWQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBkYXRhOiBkYXRhLnJvd3MgPz8gW10sXG4gICAgICAgICAgICBwYWdpbmc6IHtcbiAgICAgICAgICAgICAgbGltaXQ6IGRhdGEucGFnaW5nPy5wYWdlU2l6ZSA/PyBzdGF0ZS5wYWdlU2l6ZSxcbiAgICAgICAgICAgICAgcmVjb3JkczogZGF0YS5wYWdpbmc/LnRvdGFsID8/IChkYXRhLnJvd3M/Lmxlbmd0aCA/PyAwKSxcbiAgICAgICAgICAgICAgcGFnZTogZGF0YS5wYWdpbmc/LnBhZ2UgPz8gc3RhdGUucGFnZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfTtcbiAgICAgICAgfSksXG4gICAgICApO1xuICB9XG5cbiAgLy8gQSBjcm9zcy10YWIncyBjb2x1bW5zLCBidWlsdCBmcm9tIHRoZSB3aXJlLiBUaGUgZmlyc3QgaXMgdGhlIHJvdyBrZXkgYW5kXG4gIC8vIGtlZXBzIGl0cyBhdXRob3JlZCBsYWJlbDsgdGhlIHJlc3QgYXJlIHBpdm90IFZBTFVFUyB1c2VkIGFzIGhlYWRpbmdzLiBXaGVuXG4gIC8vIHRoZSBwaXZvdCBheGlzIGlzIGEgdGltZSBkaW1lbnNpb24gdGhlIHNlcnZlciBzZW5kcyB0aGUgZ3JhaW4gaXQgYnVja2V0ZWRcbiAgLy8gYXQsIHNvIGEgcGVyaW9kLXN0YXJ0IGxpa2UgXCIyMDI2LTAxLTAxXCIgaXMgc2hvd24gYXMgXCJKYW4gMjAyNlwiIOKAlCB0aGUgc2FtZVxuICAvLyBmb3JtYXR0ZXIgdGhlIGNoYXJ0J3MgeC1heGlzIHVzZXMsIHNvIGEgZ3JpZCBhbmQgYSBjaGFydCBvZiB0aGUgc2FtZSBxdWVyeVxuICAvLyBsYWJlbCB0aGVpciBwZXJpb2RzIGlkZW50aWNhbGx5LlxuICBwcml2YXRlIF9waXZvdENvbHVtbnMoZGF0YTogQ29tcG9uZW50RGF0YSk6IHsgY29sdW1uOiBzdHJpbmc7IGxhYmVsPzogc3RyaW5nOyBmb3JtYXQ/OiBzdHJpbmcgfVtdIHtcbiAgICBjb25zdCBjb25maWcgPSAodGhpcy5jb21wb25lbnQuY29uZmlnID8/IHt9KSBhcyBMaXN0Q29uZmlnO1xuICAgIGNvbnN0IGdyYW51bGFyaXR5ID0gZGF0YS5ncmFudWxhcml0eTtcbiAgICBjb25zdCBtdWx0aVllYXIgPSB0aGlzLl9zcGFuc011bHRpcGxlWWVhcnMoZGF0YS5jb2x1bW5zID8/IFtdKTtcblxuICAgIHJldHVybiAoZGF0YS5jb2x1bW5zID8/IFtdKS5tYXAoKGNvbHVtbiwgaW5kZXgpID0+IHtcbiAgICAgIGlmIChpbmRleCA9PT0gMCkge1xuICAgICAgICByZXR1cm4geyBjb2x1bW4sIGxhYmVsOiBjb25maWcucm93Qnk/LmxhYmVsIHx8IGNvbHVtbiB9O1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBjb2x1bW4sXG4gICAgICAgIGxhYmVsOiBncmFudWxhcml0eSA/IGZvcm1hdFBlcmlvZExhYmVsKGNvbHVtbiwgZ3JhbnVsYXJpdHksIG11bHRpWWVhcikgOiBjb2x1bW4sXG4gICAgICB9O1xuICAgIH0pO1xuICB9XG5cbiAgLy8gV2hldGhlciB0aGUgcGVyaW9kIGNvbHVtbnMgY3Jvc3MgYSB5ZWFyIGJvdW5kYXJ5LCB3aGljaCBkZWNpZGVzIGlmIHRoZVxuICAvLyBmb3JtYXR0ZXIgYXBwZW5kcyB0aGUgeWVhciB0byBlYWNoIGhlYWRpbmcuXG4gIHByaXZhdGUgX3NwYW5zTXVsdGlwbGVZZWFycyhjb2x1bW5zOiBzdHJpbmdbXSk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHllYXJzID0gbmV3IFNldChcbiAgICAgIGNvbHVtbnNcbiAgICAgICAgLm1hcCgoY29sdW1uKSA9PiAvXihcXGR7NH0pLVxcZHsyfS1cXGR7Mn0vLmV4ZWMoY29sdW1uKSlcbiAgICAgICAgLmZpbHRlcihCb29sZWFuKVxuICAgICAgICAubWFwKChtYXRjaCkgPT4gbWF0Y2hbMV0pLFxuICAgICk7XG5cbiAgICByZXR1cm4geWVhcnMuc2l6ZSA+IDE7XG4gIH1cbn1cbiIsIkBpZiAodHJ1bmNhdGVkKCkpIHtcbiAgPGRpdiBjbGFzcz1cInBpdm90LXRydW5jYXRlZFwiPlxuICAgIFRoaXMgZ3JpZCB3YXMgYnVpbHQgZnJvbSBhIHBhcnRpYWwgcmVzdWx0LCBzbyBzb21lIGNvbHVtbnMgb3IgdmFsdWVzIG1heSBiZSBtaXNzaW5nLiBOYXJyb3cgaXQgd2l0aCBhIGZpbHRlci5cbiAgPC9kaXY+XG59XG5cbjxmcy1saXN0IFtjb25maWddPVwibGlzdENvbmZpZ1wiPlxuICBAZm9yIChjb2x1bW4gb2YgY29sdW1ucygpOyB0cmFjayBjb2x1bW4uY29sdW1uKSB7XG4gICAgPGZzLWxpc3QtY29sdW1uXG4gICAgICBbbmFtZV09XCJjb2x1bW4uY29sdW1uXCJcbiAgICAgIFt0aXRsZV09XCJjb2x1bW4ubGFiZWwgfHwgY29sdW1uLmNvbHVtblwiXG4gICAgICBbc29ydGFibGVdPVwiIXBpdm90ZWQoKSB8fCAkZmlyc3RcIj5cbiAgICAgIDxuZy10ZW1wbGF0ZVxuICAgICAgICBmcy1saXN0LWNlbGxcbiAgICAgICAgbGV0LXJvdz1cInJvd1wiPlxuICAgICAgICBAaWYgKGNvbHVtbi5mb3JtYXQgPT09ICdkYXRlJykge1xuICAgICAgICAgIHt7IHJvd1tjb2x1bW4uY29sdW1uXSB8IGZzUmVwb3J0RGF0ZTogdGltZXpvbmUoKSB9fVxuICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICB7eyByb3dbY29sdW1uLmNvbHVtbl0gfX1cbiAgICAgICAgfVxuICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICA8L2ZzLWxpc3QtY29sdW1uPlxuICB9XG48L2ZzLWxpc3Q+XG4iXX0=
282
+ ReportNumberPipe,
283
+ ], template: "@if (truncated()) {\n <div class=\"pivot-truncated\">\n This grid was built from a partial result, so some columns or values may be missing. Narrow it with a filter.\n </div>\n}\n\n<!-- fs-list reads a column's footer template once, as a direct child of\n fs-list-column, so a list with totals renders its columns in a branch of\n their own rather than wrapping the footer in an @if. -->\n<fs-list\n [config]=\"listConfig\"\n [class.report-totals-empty]=\"!totals()\">\n @if (showTotals()) {\n @for (column of columns(); track column.column) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], column: column }\">\n </ng-container>\n </ng-template>\n <ng-template fs-list-footer>\n @if (totals()?.[column.column] !== undefined) {\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: totals()?.[column.column], column: column }\">\n </ng-container>\n } @else if (column.column === totalsLabelColumn()) {\n {{ totalLabel }}\n }\n </ng-template>\n </fs-list-column>\n }\n } @else {\n @for (column of columns(); track column.column) {\n <fs-list-column\n [name]=\"column.column\"\n [title]=\"column.label || column.column\"\n [show]=\"!hidden().has(column.column)\"\n [sortable]=\"!pivoted() || $first\"\n [align]=\"column.numeric ? 'right' : 'left'\"\n [class]=\"columnClasses(column, $index, pinned())\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <ng-container\n [ngTemplateOutlet]=\"cellTpl\"\n [ngTemplateOutletContext]=\"{ $implicit: row[column.column], column: column }\">\n </ng-container>\n </ng-template>\n </fs-list-column>\n }\n }\n</fs-list>\n\n@if (caption()) {\n <div class=\"list-caption small\">\n {{ caption() }}\n </div>\n}\n\n<!-- One cell, in the body and the totals row alike: a date column as a day in\n the report's zone and locale, any other through its number format. -->\n<ng-template\n #cellTpl\n let-value\n let-column=\"column\">\n @if (column.format === ReportListColumnFormat.Date) {\n {{ value | fsReportDate: timezone() : formatContext().locale }}\n } @else {\n {{ value | fsReportNumber: column : formatContext() }}\n }\n</ng-template>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:100%;min-height:0}:host ::ng-deep fs-list{display:flex;flex-direction:column;flex:1 1 auto;height:auto;min-height:0}:host ::ng-deep fs-list .fs-list-container{display:flex;flex-direction:column;flex:1 1 auto;min-height:0;height:100%}:host ::ng-deep fs-list .fs-list-header-container{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-container .fs-list-table-container{flex:1 1 auto;min-height:0;overflow-y:auto!important}:host ::ng-deep fs-list .fs-list-table thead th{position:sticky;top:0;z-index:1;background-color:#fff}:host ::ng-deep fs-list .fs-list-table tfoot td{position:sticky;bottom:0;z-index:1;background-color:#fff;font-weight:500;box-shadow:inset 0 1px #0000001f}:host ::ng-deep fs-list.report-totals-empty tfoot{display:none}:host ::ng-deep fs-list .report-pinned{position:sticky;left:var(--report-pin-left, 0px);z-index:1;background-color:#fff}:host ::ng-deep fs-list .report-pin-0{--report-pin-left: var(--report-pin-left-0, 0px)}:host ::ng-deep fs-list .report-pin-1{--report-pin-left: var(--report-pin-left-1, 0px)}:host ::ng-deep fs-list .report-pin-2{--report-pin-left: var(--report-pin-left-2, 0px)}:host ::ng-deep fs-list .report-pin-last{box-shadow:inset -1px 0 #0000001f}:host ::ng-deep fs-list .fs-list-table thead th.report-pinned{z-index:3}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pinned{z-index:2}:host ::ng-deep fs-list .fs-list-table tfoot td.report-pin-last{box-shadow:inset -1px 0 #0000001f,inset 0 1px #0000001f}:host ::ng-deep fs-list th.report-nowrap,:host ::ng-deep fs-list td.report-nowrap{white-space:nowrap}:host ::ng-deep fs-list fs-list-pagination{flex:0 0 auto}:host ::ng-deep fs-list .fs-list-load-more{position:sticky;bottom:0;background-color:#fff}:host ::ng-deep fs-list .fs-list-load-more button{margin-top:0}.list-caption{flex:0 0 auto;padding-top:4px}.pivot-truncated{flex:0 0 auto;padding:8px 12px;margin-bottom:8px;border-radius:4px;background-color:#fff4e5;color:#663c00}\n"] }]
284
+ }], ctorParameters: () => [] });
285
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LWxpc3QuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LWxpc3QvY29tcG9uZW50LWxpc3QuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LWxpc3QvY29tcG9uZW50LWxpc3QuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDbkQsT0FBTyxFQUVMLHVCQUF1QixFQUN2QixTQUFTLEVBQ1QsVUFBVSxFQUNWLFVBQVUsRUFDVixRQUFRLEVBRVIsZUFBZSxFQUNmLFFBQVEsRUFDUixNQUFNLEVBQ04sTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBQ04sU0FBUyxFQUNULFNBQVMsR0FDVixNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUVoRSxPQUFPLEVBQUUsZUFBZSxFQUFnQixZQUFZLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUVuRyxPQUFPLEVBQWMsR0FBRyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFbkQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3BELE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDRDQUE0QyxDQUFDO0FBQ3BGLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxlQUFlLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFTbEUsT0FBTyxFQUNMLGdCQUFnQixFQUNoQixhQUFhLEVBQ2IsaUJBQWlCLEVBQ2pCLGFBQWEsRUFDYixxQkFBcUIsR0FDdEIsTUFBTSxtQkFBbUIsQ0FBQztBQUMz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bGF0ZU91dGxldCB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQge1xuICBBZnRlclJlbmRlclJlZixcbiAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXG4gIENvbXBvbmVudCxcbiAgRGVzdHJveVJlZixcbiAgRWxlbWVudFJlZixcbiAgSW5qZWN0b3IsXG4gIE9uSW5pdCxcbiAgYWZ0ZXJOZXh0UmVuZGVyLFxuICBjb21wdXRlZCxcbiAgZWZmZWN0LFxuICBpbmplY3QsXG4gIGlucHV0LFxuICBzaWduYWwsXG4gIHVudHJhY2tlZCxcbiAgdmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IHRha2VVbnRpbERlc3Ryb3llZCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUvcnhqcy1pbnRlcm9wJztcblxuaW1wb3J0IHsgRnNMaXN0Q29tcG9uZW50LCBGc0xpc3RDb25maWcsIEZzTGlzdE1vZHVsZSwgUGFnaW5hdGlvblN0cmF0ZWd5IH0gZnJvbSAnQGZpcmVzdGl0Y2gvbGlzdCc7XG5cbmltcG9ydCB7IE9ic2VydmFibGUsIG1hcCwgbWVyZ2UsIHRhcCB9IGZyb20gJ3J4anMnO1xuXG5pbXBvcnQgeyBSZXBvcnREYXRhIH0gZnJvbSAnLi4vLi4vZGF0YS9yZXBvcnQuZGF0YSc7XG5pbXBvcnQgeyBSZXBvcnRMaXN0Q29sdW1uRm9ybWF0IH0gZnJvbSAnLi4vLi4vZW51bXMvcmVwb3J0LWxpc3QtY29sdW1uLWZvcm1hdC5lbnVtJztcbmltcG9ydCB7IGZvcm1hdFBsYWluTnVtYmVyLCBoYXNOdW1iZXJGb3JtYXQgfSBmcm9tICcuLi8uLi9mb3JtYXQnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50RGF0YSxcbiAgQ29tcG9uZW50RGF0YVN0YXRlLFxuICBMaXN0Q29sdW1uLFxuICBMaXN0Q29uZmlnLFxuICBSZXBvcnRDb21wb25lbnQsXG4gIFJlcG9ydFNvcnQsXG59IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5pbXBvcnQge1xuICBMSVNUX1RPVEFMX0xBQkVMLFxuICBjb2x1bW5DbGFzc2VzLFxuICBsaXN0UGlubmVkQ29sdW1ucyxcbiAgbGlzdFNvcnRUZXJtcyxcbiAgbGlzdFRvdGFsc0xhYmVsQ29sdW1uLFxufSBmcm9tICcuLi8uLi9saXN0LWNvbmZpZyc7XG5pbXBvcnQgeyBwaXZvdENvbHVtblNwZWNzIH0gZnJvbSAnLi4vLi4vb3B0aW9uLWJ1aWxkZXInO1xuaW1wb3J0IHsgUmVwb3J0RGF0ZVBpcGUgfSBmcm9tICcuLi8uLi9waXBlcy9yZXBvcnQtZGF0ZS5waXBlJztcbmltcG9ydCB7IFJlcG9ydE51bWJlclBpcGUgfSBmcm9tICcuLi8uLi9waXBlcy9yZXBvcnQtbnVtYmVyLnBpcGUnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVwb3J0LWZpbHRlci1zdGF0ZS5zZXJ2aWNlJztcblxuXG4vLyBBIGxpc3QgY29tcG9uZW50OiBhbiBGc0xpc3QgcmVuZGVyZWQgZnJvbSB0aGUgY29tcG9uZW50J3MgY29uZmlnLiBJdCBoYXMgbm9cbi8vIGZpbHRlciBiYXIgb2YgaXRzIG93bjogaXRzIGZpbHRlcnMgYXJlIGdyb3VwLWtleWVkIGxpa2UgZXZlcnkgb3RoZXJcbi8vIGNvbXBvbmVudCdzLCBzbyBjb21wb25lbnQtbGV2ZWwgZ3JvdXBzIHJlbmRlciBpbiB0aGUgY29tcG9uZW50IGhlYWRlciBzdHJpcFxuLy8gKFJlcG9ydENvbXBvbmVudENvbXBvbmVudCkgYW5kIHJlcG9ydC1sZXZlbCBncm91cHMgaW4gdGhlIHJlcG9ydCBiYXIsIGFuZFxuLy8gZXZlcnkgcmVxdWVzdCB0YWtlcyBpdHMgdmFsdWVzIGZyb20gdGhlIHNoYXJlZCBmaWx0ZXItc3RhdGUgc2VydmljZS5cbi8vIFBhZ2luZyBhbmQgc29ydGluZyBhcmUgcHVzaGVkIGludG8gdGhlIFNRTCB3cmFwIHNlcnZlci1zaWRlLlxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLXJlcG9ydC1jb21wb25lbnQtbGlzdCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9jb21wb25lbnQtbGlzdC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2NvbXBvbmVudC1saXN0LmNvbXBvbmVudC5zY3NzJ10sXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBpbXBvcnRzOiBbXG4gICAgRnNMaXN0TW9kdWxlLFxuICAgIE5nVGVtcGxhdGVPdXRsZXQsXG4gICAgUmVwb3J0RGF0ZVBpcGUsXG4gICAgUmVwb3J0TnVtYmVyUGlwZSxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgQ29tcG9uZW50TGlzdENvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG5cbiAgcHVibGljIHJlYWRvbmx5IHJlcG9ydElkID0gaW5wdXQucmVxdWlyZWQ8bnVtYmVyPigpO1xuICBwdWJsaWMgcmVhZG9ubHkgY29tcG9uZW50ID0gaW5wdXQucmVxdWlyZWQ8UmVwb3J0Q29tcG9uZW50PigpO1xuXG4gIHB1YmxpYyByZWFkb25seSBsaXN0Q29tcG9uZW50ID0gdmlld0NoaWxkKEZzTGlzdENvbXBvbmVudCk7XG5cbiAgcHVibGljIGxpc3RDb25maWc6IEZzTGlzdENvbmZpZztcblxuICAvLyBBIHBsYWluIGxpc3QncyBjb2x1bW5zIGFyZSBhdXRob3JlZCBhbmQgZml4ZWQgYXQgaW5pdC4gQSBjcm9zcy10YWIncyBhcmVcbiAgLy8gdGhlIHBpdm90IGRpbWVuc2lvbidzIFZBTFVFUywgc28gdGhleSBhcnJpdmUgd2l0aCB0aGUgcm93cyBhbmQgY2hhbmdlXG4gIC8vIHdoZW5ldmVyIHRoZSBmaWx0ZXJzIGRvIOKAlCB3aGljaCBpcyB3aHkgdGhpcyBpcyBhIHNpZ25hbCByYXRoZXIgdGhhbiB0aGVcbiAgLy8gb25lLXNob3QgcmVhZCBpdCB1c2VkIHRvIGJlLiBgbnVtZXJpY2AgbWFya3MgYSBjb2x1bW4gd2hvc2UgY2VsbHMgYXJlXG4gIC8vIGZvcm1hdHRlZCBudW1iZXJzLCBkZWNpZGVkIG9uY2UgaGVyZSByYXRoZXIgdGhhbiBwZXIgY2VsbCwgc28gdGhlIGNvbHVtblxuICAvLyBhbmQgaXRzIGhlYWRlciBhcmUgcmlnaHQtYWxpZ25lZC5cbiAgcHVibGljIGNvbHVtbnMgPSBzaWduYWw8KExpc3RDb2x1bW4gJiB7IG51bWVyaWM6IGJvb2xlYW4gfSlbXT4oW10pO1xuXG4gIC8vIEEgY3Jvc3MtdGFiIHNvcnRzIG9ubHkgYnkgaXRzIHJvdy1rZXkgY29sdW1uOiBldmVyeSBvdGhlciBoZWFkZXIgaXMgYVxuICAvLyBwaXZvdCB2YWx1ZSwgYW5kIHRoZSBzZXJ2ZXIgb3JkZXJzIHRoZSBsb25nIHJvd3MgYmVmb3JlIHBpdm90aW5nLCBzbyBhXG4gIC8vIGNsaWNrIG9uIFwiTWFyIDIwMjZcIiBoYXMgbm90aGluZyB0byBvcmRlciBieS5cbiAgcHVibGljIHBpdm90ZWQgPSBzaWduYWwoZmFsc2UpO1xuXG4gIC8vIEEgY3V0IHJlc3VsdCBpcyB3b3JzZSBmb3IgYSBncmlkIHRoYW4gZm9yIGEgbGlzdDogdGhlIGN1dCBsYW5kcyBvbiB0aGUgTE9OR1xuICAvLyByb3dzIGJlZm9yZSB0aGUgcmVzaGFwZSwgc28gYSBwaXZvdCB2YWx1ZSBsaXZpbmcgb25seSBpbiB0aGUgdGFpbCB2YW5pc2hlc1xuICAvLyBhcyBhIHdob2xlIENPTFVNTiBhbmQgc3RyYWRkbGVkIGNlbGxzIGNvbWUgYmFjayBibGFuaywgaW5kaXN0aW5ndWlzaGFibGVcbiAgLy8gZnJvbSBhIHJlYWwgemVyby4gVGhlIHBhcmVudCdzIHRydW5jYXRpb24gYmFubmVyIG5ldmVyIGZpcmVzIGZvciBhIGxpc3RcbiAgLy8gKGl0IG9ubHkgcmVuZGVycyB3aGF0IF9sb2FkKCkgZmV0Y2hlZCwgd2hpY2ggbGlzdHMgc2tpcCksIHNvIHRoZSB3YXJuaW5nXG4gIC8vIGJlbG9uZ3MgaGVyZS5cbiAgcHVibGljIHRydW5jYXRlZCA9IHNpZ25hbChmYWxzZSk7XG5cbiAgLy8gV2h5IHRoZSBzZWFyY2ggYm94IGRpZCBub3QgbmFycm93IHRoZSByb3dzICh0aGUgbGlzdCBoYXMgbm8gdGV4dCBjb2x1bW4gdG9cbiAgLy8gc2VhcmNoKSwgZnJvbSB0aGUgbGF0ZXN0IHBhZ2UgMTsgbnVsbCB3aGVuIHRoZSBzZWFyY2ggYXBwbGllZCBvciBub25lIHdhc1xuICAvLyBtYWRlLlxuICBwdWJsaWMgcmVhZG9ubHkgc2VhcmNoTm90ZSA9IHNpZ25hbDxzdHJpbmcgfCBudWxsPihudWxsKTtcblxuICAvLyBjb25maWcudG90YWxzLCByZWFkIG9uY2UgYXQgaW5pdDogYSBsaXN0IHdpdGggdG90YWxzIHJlbmRlcnMgaXRzIGNvbHVtbnNcbiAgLy8gd2l0aCBhIGZvb3RlciB0ZW1wbGF0ZSwgd2hpY2ggZnMtbGlzdCByZWFkcyBvbmx5IHdoZW4gaXQgYnVpbGRzIHRoZW0uXG4gIHB1YmxpYyByZWFkb25seSBzaG93VG90YWxzID0gc2lnbmFsKGZhbHNlKTtcblxuICAvLyBUaGUgdG90YWxzIHJvdyBmcm9tIHRoZSBsYXRlc3QgcGFnZSAxLCByYXcgdmFsdWVzIGtleWVkIGxpa2UgdGhlIGNvbHVtbnM7XG4gIC8vIG51bGwgd2hlbiB0aGUgbGlzdCBoYXMgbm9uZSwgb3IgdGhlIHNlcnZlciBzYXlzIHdoeSBpbiB0b3RhbHNOb3RlLlxuICBwdWJsaWMgcmVhZG9ubHkgdG90YWxzID0gc2lnbmFsPFJlY29yZDxzdHJpbmcsIHVua25vd24+IHwgbnVsbD4obnVsbCk7XG5cbiAgcHVibGljIHJlYWRvbmx5IHRvdGFsc05vdGUgPSBzaWduYWw8c3RyaW5nIHwgbnVsbD4obnVsbCk7XG5cbiAgLy8gSG93IG1hbnkgcm93cyB0aGUgbGlzdCBzaG93cyAobG9hZCBtb3JlIGFwcGVuZHMpIG91dCBvZiBob3cgbWFueSBpdHNcbiAgLy8gZmlsdGVycyBrZWVwLiBBIGNyb3NzLXRhYiBjb3VudHMgZ3JpZCByb3dzLlxuICBwdWJsaWMgcmVhZG9ubHkgcm93Q291bnQgPSBzaWduYWw8eyBzaG93bjogbnVtYmVyOyB0b3RhbDogbnVtYmVyIH0gfCBudWxsPihudWxsKTtcblxuICAvLyBUaGUgcmVwb3J0J3MgZWZmZWN0aXZlIHpvbmUsIHdoaWNoIGRhdGUgY2VsbHMgcmVuZGVyIGluLiBJbmplY3RlZCByaWdodFxuICAvLyBoZXJlIHJhdGhlciB0aGFuIHJlYWQgb2ZmIF9maWx0ZXJTdGF0ZSwgd2hpY2ggaXMgZGVjbGFyZWQgZnVydGhlciBkb3duIGFuZFxuICAvLyBpcyBzdGlsbCB1bmRlZmluZWQgd2hpbGUgdGhpcyBpbml0aWFsaXplciBydW5zLlxuICBwdWJsaWMgcmVhZG9ubHkgdGltZXpvbmUgPSBpbmplY3QoUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlKS50aW1lem9uZTtcblxuICAvLyBUaGUgb3BlbiByZXBvcnQncyBmb3JtYXQgY29udGV4dDogZGF0ZSBjZWxscywgbnVtYmVyIGNlbGxzIGFuZCBhXG4gIC8vIGNyb3NzLXRhYidzIHBlcmlvZCBoZWFkaW5ncyBhcmUgd3JpdHRlbiBpbiBpdHMgbG9jYWxlIChhbmQgbW9uZXkgaW4gaXRzXG4gIC8vIGN1cnJlbmN5KS4gSW5qZWN0ZWQgaGVyZSBmb3IgdGhlIHNhbWUgcmVhc29uLlxuICBwdWJsaWMgcmVhZG9ubHkgZm9ybWF0Q29udGV4dCA9IGluamVjdChSZXBvcnRGaWx0ZXJTdGF0ZVNlcnZpY2UpLmZvcm1hdENvbnRleHQ7XG5cbiAgcHVibGljIHJlYWRvbmx5IFJlcG9ydExpc3RDb2x1bW5Gb3JtYXQgPSBSZXBvcnRMaXN0Q29sdW1uRm9ybWF0O1xuXG4gIC8vIEhvdyBtYW55IGxlYWRpbmcgY29sdW1ucyBzdGF5IGluIHZpZXcgd2hpbGUgdGhlIGxpc3Qgc2Nyb2xscyBzaWRld2F5cy5cbiAgcHVibGljIHJlYWRvbmx5IHBpbm5lZCA9IGNvbXB1dGVkKCgpID0+IGxpc3RQaW5uZWRDb2x1bW5zKHRoaXMuY29tcG9uZW50KCkuY29uZmlnKSk7XG5cbiAgcHVibGljIHJlYWRvbmx5IGNvbHVtbkNsYXNzZXMgPSBjb2x1bW5DbGFzc2VzO1xuXG4gIC8vIFRoZSBjb25maWcgY29sdW1ucyB0aGUgdmlld2VyIGhpZCBvbiB0aGlzIGxpc3QgKHRoZSBDb2x1bW5zIGRpYWxvZywgb3IgdGhlXG4gIC8vIFVSTCkuIGZzLWxpc3QgaGlkZXMgYW5kIHNob3dzIHRoZW0gaW4gcGxhY2UgdGhyb3VnaCBbc2hvd10sIHNvIHRoZSByb3dzXG4gIC8vIGFscmVhZHkgZmV0Y2hlZCBzdGFuZC5cbiAgcHVibGljIHJlYWRvbmx5IGhpZGRlbiA9IGNvbXB1dGVkKCgpID0+IG5ldyBTZXQodGhpcy5fZmlsdGVyU3RhdGUuaGlkZGVuQ29sdW1ucyh0aGlzLmNvbXBvbmVudCgpLmlkKSkpO1xuXG4gIHB1YmxpYyByZWFkb25seSB0b3RhbExhYmVsID0gTElTVF9UT1RBTF9MQUJFTDtcblxuICAvLyBUaGUgY29sdW1uIHdob3NlIGZvb3RlciBjZWxsIHJlYWRzICdUb3RhbCc6IHRoZSBmaXJzdCBvbmUgc2hvd24sIHVubGVzc1xuICAvLyBpdCBob2xkcyBhIHRvdGFsIGl0c2VsZi5cbiAgcHVibGljIHJlYWRvbmx5IHRvdGFsc0xhYmVsQ29sdW1uID0gY29tcHV0ZWQoKCkgPT4gbGlzdFRvdGFsc0xhYmVsQ29sdW1uKFxuICAgIHRoaXMuY29sdW1ucygpLmZpbHRlcigoY29sdW1uKSA9PiAhdGhpcy5oaWRkZW4oKS5oYXMoY29sdW1uLmNvbHVtbikpLFxuICAgIHRoaXMudG90YWxzKCksXG4gICkpO1xuXG4gIC8vIFRoZSBsaW5lIHVuZGVyIHRoZSBsaXN0OiBpdHMgcm93IGNvdW50LCB0aGVuIHdoeSBpdCBoYXMgbm8gdG90YWxzIGFuZCB3aHlcbiAgLy8gaXRzIHNlYXJjaCBuYXJyb3dlZCBub3RoaW5nLiBUaGUgZGlnaXRzIGFyZSB3cml0dGVuIGluIHRoZSByZXBvcnQnc1xuICAvLyBsb2NhbGUsIG5ldmVyIHRoZSBhcHAncy5cbiAgcHVibGljIHJlYWRvbmx5IGNhcHRpb24gPSBjb21wdXRlZCgoKSA9PiB7XG4gICAgY29uc3QgY291bnQgPSB0aGlzLnJvd0NvdW50KCk7XG4gICAgY29uc3QgbG9jYWxlID0gdGhpcy5mb3JtYXRDb250ZXh0KCkubG9jYWxlO1xuICAgIGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgaWYgKGNvdW50KSB7XG4gICAgICBjb25zdCB0b3RhbCA9IGZvcm1hdFBsYWluTnVtYmVyKGNvdW50LnRvdGFsLCBsb2NhbGUpO1xuICAgICAgcGFydHMucHVzaChjb3VudC5zaG93biA8IGNvdW50LnRvdGFsXG4gICAgICAgID8gYFNob3dpbmcgJHtmb3JtYXRQbGFpbk51bWJlcihjb3VudC5zaG93biwgbG9jYWxlKX0gb2YgJHt0b3RhbH1gXG4gICAgICAgIDogYCR7dG90YWx9IHJvdyhzKWApO1xuICAgIH1cblxuICAgIHJldHVybiBbLi4ucGFydHMsIHRoaXMudG90YWxzTm90ZSgpLCB0aGlzLnNlYXJjaE5vdGUoKV1cbiAgICAgIC5maWx0ZXIoKHBhcnQpOiBwYXJ0IGlzIHN0cmluZyA9PiAhIXBhcnQpXG4gICAgICAuam9pbignIMK3ICcpO1xuICB9KTtcblxuICBwcml2YXRlIF9yZXBvcnREYXRhID0gaW5qZWN0KFJlcG9ydERhdGEpO1xuICBwcml2YXRlIF9maWx0ZXJTdGF0ZSA9IGluamVjdChSZXBvcnRGaWx0ZXJTdGF0ZVNlcnZpY2UpO1xuICBwcml2YXRlIF9kZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuICBwcml2YXRlIF9lbGVtZW50UmVmID0gaW5qZWN0PEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+PihFbGVtZW50UmVmKTtcbiAgcHJpdmF0ZSBfaW5qZWN0b3IgPSBpbmplY3QoSW5qZWN0b3IpO1xuICBwcml2YXRlIF9waW5PZmZzZXRzUmVmOiBBZnRlclJlbmRlclJlZiB8IG51bGwgPSBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIC8vIEhpZGluZyBvciBzaG93aW5nIGEgY29sdW1uIG1vdmVzIHRoZSBwaW5uZWQgY29sdW1ucyBhZnRlciBpdC5cbiAgICBlZmZlY3QoKCkgPT4ge1xuICAgICAgdGhpcy5oaWRkZW4oKTtcbiAgICAgIHVudHJhY2tlZCgoKSA9PiB0aGlzLl9zY2hlZHVsZVBpbk9mZnNldHMoKSk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgY29uc3QgY29tcG9uZW50ID0gdGhpcy5jb21wb25lbnQoKTtcbiAgICBjb25zdCBjb25maWcgPSAoY29tcG9uZW50LmNvbmZpZyA/PyB7fSkgYXMgTGlzdENvbmZpZztcbiAgICB0aGlzLnBpdm90ZWQuc2V0KCEhY29uZmlnLnBpdm90Qnk/LmNvbHVtbik7XG4gICAgdGhpcy5zaG93VG90YWxzLnNldChjb25maWcudG90YWxzID09PSB0cnVlKTtcbiAgICB0aGlzLmNvbHVtbnMuc2V0KChjb25maWcuY29sdW1ucyA/PyBbXSkubWFwKChjb2x1bW4pID0+ICh7IC4uLmNvbHVtbiwgbnVtZXJpYzogaGFzTnVtYmVyRm9ybWF0KGNvbHVtbikgfSkpKTtcblxuICAgIHRoaXMuX2luaXRMaXN0Q29uZmlnKGNvbmZpZyk7XG4gICAgdGhpcy5fb2JzZXJ2ZVBpbk9mZnNldHMoKTtcblxuICAgIC8vIEEgY2hhbmdlIHRvIGFueSBncm91cCB0aGlzIGxpc3QncyBmaWx0ZXJzIGJlbG9uZyB0byAoZnJvbSB0aGUgcmVwb3J0IGJhclxuICAgIC8vIG9yIHRoZSBjb21wb25lbnQgaGVhZGVyIHN0cmlwKSByZS1ydW5zIHRoZSBsaXN0LlxuICAgIC8vIFNvIGRvZXMgYSBjaGFuZ2Ugb2YgdGhlIHRleHQgaW4gaXRzIHNlYXJjaCBib3ggKGluIHRoZSBjb21wb25lbnQgaGVhZGVyKS5cbiAgICBtZXJnZSh0aGlzLl9maWx0ZXJTdGF0ZS5jaGFuZ2VzRm9yKGNvbXBvbmVudCksIHRoaXMuX2ZpbHRlclN0YXRlLmxpc3RTZWFyY2hDaGFuZ2VzKGNvbXBvbmVudC5pZCkpXG4gICAgICAucGlwZShcbiAgICAgICAgdGFwKCgpID0+IHRoaXMubGlzdENvbXBvbmVudCgpPy5yZWxvYWQoKSksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIHByaXZhdGUgX2luaXRMaXN0Q29uZmlnKGNvbmZpZzogTGlzdENvbmZpZyk6IHZvaWQge1xuICAgIC8vIFRoZSB2aWV3ZXIncyBsYXN0IHNvcnQgd2lucyBvdmVyIHRoZSBhdXRob3JlZCBvbmUsIHNvIGEgbGlzdCByZWNyZWF0ZWRcbiAgICAvLyBpbiB0aGUgc2FtZSBzZXNzaW9uIChwYWdlIHN3aXRjaCwgcmVsb2FkIGFmdGVyIGFuIGVkaXQpIGtlZXBzIGl0LlxuICAgIC8vIGZzLWxpc3QgaG9sZHMgb25lIHNvcnRpbmcgY29sdW1uLCBzbyBpdCBzaG93cyB0aGUgYXV0aG9yZWQgc29ydCdzIGZpcnN0XG4gICAgLy8gdGVybTsgdGhlIHJlcXVlc3Qgc2VuZHMgb25seSB0aGF0IHRlcm0gYW5kIHRoZSBzZXJ2ZXIgYXBwZW5kcyB0aGUgcmVzdC5cbiAgICBjb25zdCBzb3J0OiBSZXBvcnRTb3J0IHwgdW5kZWZpbmVkID0gdGhpcy5fZmlsdGVyU3RhdGUubGlzdFNvcnQodGhpcy5jb21wb25lbnQoKS5pZClcbiAgICAgID8/IGxpc3RTb3J0VGVybXMoY29uZmlnKVswXTtcblxuICAgIHRoaXMubGlzdENvbmZpZyA9IHtcbiAgICAgIC8vIEluc2lkZSBhIHJlcG9ydCBjb21wb25lbnQgdGhlIGxpc3QgaXMgYSBjbGVhbiBkYXRhIHBhbmUg4oCUIG5vIHN0YXR1c1xuICAgICAgLy8gYmFyLCBubyByZWxvYWQgYnV0dG9uIChmaWx0ZXIgY2hhbmdlcyBhbHJlYWR5IHJlZmV0Y2gpLlxuICAgICAgc3RhdHVzOiBmYWxzZSxcbiAgICAgIHJlbG9hZDogZmFsc2UsXG4gICAgICAvLyBGc0xpc3QgbmV2ZXIgdG91Y2hlcyB0aGUgVVJMIG9yIHBlcnNpc3RzIHNvcnQvcGFnaW5nIHN0YXRlLiBUaGUgc29ydFxuICAgICAgLy8gcmVhY2hlcyB0aGUgVVJMIHRocm91Z2ggUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIChzZXRMaXN0U29ydCksIGFuZFxuICAgICAgLy8gcGFnaW5nIHN0YXlzIG91dCBvZiBpdC5cbiAgICAgIHF1ZXJ5UGFyYW06IGZhbHNlLFxuICAgICAgcGVyc2lzdDogZmFsc2UsXG4gICAgICBzb3J0OiBzb3J0XG4gICAgICAgID8geyB2YWx1ZTogc29ydC5jb2x1bW4sIGRpcmVjdGlvbjogc29ydC5kaXJlY3Rpb24gPz8gJ2FzYycgfVxuICAgICAgICA6IHVuZGVmaW5lZCxcbiAgICAgIC8vIExvYWQtbW9yZTogdGhlIGxpc3Qga2VlcHMgYSBmaXhlZCwgc2Nyb2xsYWJsZSBoZWlnaHQgYW5kIGFwcGVuZHMgdGhlXG4gICAgICAvLyBuZXh0IHBhZ2UgaW4gcGxhY2UgaW5zdGVhZCBvZiBzd2FwcGluZyBwYWdlcy4gVGhlIGJ1dHRvbiBpcyBwaW5uZWQgdG9cbiAgICAgIC8vIHRoZSBib3R0b20gb2YgdGhlIHNjcm9sbCBwYW5lIChzZWUgY29tcG9uZW50IFNDU1MpLlxuICAgICAgLy9cbiAgICAgIC8vIFVzZXMgdGhlIE9mZnNldCBzdHJhdGVneSAob2Zmc2V0ICsgbGltaXQpIHJhdGhlciB0aGFuIE1hbnk6IGluXG4gICAgICAvLyBAZmlyZXN0aXRjaC9saXN0IHRoZSBwYWdpbmF0aW9uIHRlbXBsYXRlIHJlc29sdmVzIGBoYXNNYW55U3RyYXRlZ3lgXG4gICAgICAvLyBCRUZPUkUgYGxvYWRNb3JlRW5hYmxlZGAsIGFuZCBNYW55IHJlbmRlcnMgYSBmb3J3YXJkLW9ubHkgcGFnZSBwYWdlciDigJRcbiAgICAgIC8vIHNvIE1hbnkgd291bGQgc3VwcHJlc3MgdGhlIGxvYWQtbW9yZSBidXR0b24gZW50aXJlbHkuIE9mZnNldCArIGxvYWRNb3JlXG4gICAgICAvLyBpcyB0aGUgY29tYmluYXRpb24gdGhhdCBhY3R1YWxseSByZW5kZXJzIGFuZCBhcHBlbmRzLiBgX2ZldGNoYCBhbHJlYWR5XG4gICAgICAvLyBkZXJpdmVzIGBwYWdlYCBmcm9tIGBvZmZzZXRgLCBzbyB0aGUgc2VydmVyLXNpZGUgd3JhcCBpcyB1bmFmZmVjdGVkLlxuICAgICAgcGFnaW5nOiB7XG4gICAgICAgIGxpbWl0OiBjb25maWcucGFnZVNpemUgPz8gMjUsXG4gICAgICAgIHN0cmF0ZWd5OiBQYWdpbmF0aW9uU3RyYXRlZ3kuT2Zmc2V0LFxuICAgICAgfSxcbiAgICAgIGxvYWRNb3JlOiB7XG4gICAgICAgIGVuYWJsZWQ6IHRydWUsXG4gICAgICAgIGxhYmVsOiAnTG9hZCBtb3JlJyxcbiAgICAgICAgYnV0dG9uVHlwZTogJ3N0cm9rZWQnLFxuICAgICAgfSxcbiAgICAgIGZldGNoOiAocXVlcnk6IGFueSkgPT4gdGhpcy5fZmV0Y2gocXVlcnkpLFxuICAgIH07XG4gIH1cblxuICBwcml2YXRlIF9mZXRjaChxdWVyeTogYW55KTogT2JzZXJ2YWJsZTx7IGRhdGE6IFJlY29yZDxzdHJpbmcsIHVua25vd24+W107IHBhZ2luZzogYW55IH0+IHtcbiAgICAvLyBNYW55L2xvYWQtbW9yZSBzZW5kcyBgb2Zmc2V0YCArIGBsaW1pdGAgKG5vdCBgcGFnZWApOyBkZXJpdmUgdGhlIHBhZ2Ugc29cbiAgICAvLyB0aGUgc2VydmVyLXNpZGUgd3JhcCBrZWVwcyB3b3JraW5nIHVuY2hhbmdlZC4gUGFnZSBzdHJhdGVneSBzdGlsbCBzZW5kc1xuICAgIC8vIGBwYWdlYCBkaXJlY3RseS5cbiAgICBjb25zdCBwYWdlU2l6ZSA9IHF1ZXJ5LmxpbWl0ID8/IDI1O1xuICAgIGNvbnN0IHBhZ2UgPSBxdWVyeS5wYWdlXG4gICAgICA/PyAocXVlcnkub2Zmc2V0ICE9IG51bGwgPyBNYXRoLmZsb29yKHF1ZXJ5Lm9mZnNldCAvIHBhZ2VTaXplKSArIDEgOiAxKTtcblxuICAgIGNvbnN0IHN0YXRlOiBDb21wb25lbnREYXRhU3RhdGUgPSB7XG4gICAgICBwYWdlLFxuICAgICAgcGFnZVNpemUsXG4gICAgfTtcblxuICAgIGNvbnN0IG9yZGVyID0gU3RyaW5nKHF1ZXJ5Lm9yZGVyID8/ICcnKTtcbiAgICBpZiAob3JkZXIpIHtcbiAgICAgIGNvbnN0IFtjb2x1bW4sIGRpcmVjdGlvbl0gPSBvcmRlci5zcGxpdCgnLCcpO1xuICAgICAgc3RhdGUuc29ydCA9IHsgY29sdW1uLCBkaXJlY3Rpb246IGRpcmVjdGlvbiA9PT0gJ2Rlc2MnID8gJ2Rlc2MnIDogJ2FzYycgfTtcbiAgICB9XG5cbiAgICBjb25zdCBjb21wb25lbnQgPSB0aGlzLmNvbXBvbmVudCgpO1xuICAgIHRoaXMuX2ZpbHRlclN0YXRlLnNldExpc3RTb3J0KGNvbXBvbmVudCwgc3RhdGUuc29ydCA/PyBudWxsKTtcblxuICAgIGNvbnN0IHNlYXJjaCA9IHRoaXMuX2ZpbHRlclN0YXRlLmxpc3RTZWFyY2goY29tcG9uZW50LmlkKTtcbiAgICBpZiAoc2VhcmNoKSB7XG4gICAgICBzdGF0ZS5zZWFyY2ggPSBzZWFyY2g7XG4gICAgfVxuXG4gICAgLy8gT25lIHNvdXJjZSBmb3IgZmlsdGVyIHZhbHVlcywgdGhlIHNhbWUgb25lIGNoYXJ0cywgS1BJcyBhbmQgdGhlIGV4cG9ydHNcbiAgICAvLyByZWFkLCBzbyB0aGUgbGlzdCBpcyBmaWx0ZXJlZCBleGFjdGx5IGFzIGl0cyBoZWFkZXIgc3RyaXAgc2hvd3MuXG4gICAgY29uc3QgZmlsdGVycyA9IHRoaXMuX2ZpbHRlclN0YXRlLnJlc29sdmVGb3JDb21wb25lbnQoY29tcG9uZW50KTtcblxuICAgIHJldHVybiB0aGlzLl9yZXBvcnREYXRhXG4gICAgICAuY29tcG9uZW50RGF0YSh0aGlzLnJlcG9ydElkKCksIGNvbXBvbmVudC5pZCwgZmlsdGVycywgc3RhdGUpXG4gICAgICAucGlwZShcbiAgICAgICAgbWFwKChkYXRhOiBDb21wb25lbnREYXRhKSA9PiB7XG4gICAgICAgICAgLy8gQSBjcm9zcy10YWIncyBoZWFkZXJzIGNvbWUgYmFjayB3aXRoIHRoZSByb3dzOiB0aGUgcm93LWtleSBjb2x1bW5cbiAgICAgICAgICAvLyBmaXJzdCwgdGhlbiBvbmUgcGVyIHBpdm90IHZhbHVlLiBSZS1yZWFkIHRoZW0gb24gZXZlcnkgZmV0Y2gsIHNpbmNlXG4gICAgICAgICAgLy8gYSBmaWx0ZXIgY2hhbmdlIGNhbiBhZGQgb3IgcmVtb3ZlIGEgY29sdW1uLlxuICAgICAgICAgIGlmICh0aGlzLnBpdm90ZWQoKSkge1xuICAgICAgICAgICAgdGhpcy5jb2x1bW5zLnNldCh0aGlzLl9waXZvdENvbHVtbnMoZGF0YSkpO1xuICAgICAgICAgICAgdGhpcy50cnVuY2F0ZWQuc2V0KCEhZGF0YS50cnVuY2F0ZWQpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIC8vIE9ubHkgcGFnZSAxIGNhcnJpZXMgdGhlIG5vdGVzIGFuZCB0aGUgdG90YWxzOyBhIGxvYWQtbW9yZSBwYWdlXG4gICAgICAgICAgLy8gbGVhdmVzIHRoZW0gYXMgdGhleSBhcmUuXG4gICAgICAgICAgaWYgKHN0YXRlLnBhZ2UgPT09IDEpIHtcbiAgICAgICAgICAgIHRoaXMuc2VhcmNoTm90ZS5zZXQoZGF0YS5zZWFyY2hOb3RlID8/IG51bGwpO1xuICAgICAgICAgICAgdGhpcy50b3RhbHMuc2V0KGRhdGEudG90YWxzID8/IG51bGwpO1xuICAgICAgICAgICAgdGhpcy50b3RhbHNOb3RlLnNldChkYXRhLnRvdGFsc05vdGUgPz8gbnVsbCk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gVGhlIHNlcnZlcidzIHBhZ2Ugc2l6ZSB3aGVuIGl0IHNlbmRzIG9uZSAoaXQgY2xhbXBzIHRoZSByZXF1ZXN0KSxcbiAgICAgICAgICAvLyB0aGUgc2l6ZSB0aGUgcGFnaW5nIGJlbG93IGhhbmRzIGZzLWxpc3QgdG9vLlxuICAgICAgICAgIGNvbnN0IHNpemUgPSBkYXRhLnBhZ2luZz8ucGFnZVNpemUgPz8gc3RhdGUucGFnZVNpemU7XG4gICAgICAgICAgY29uc3Qgc2hvd24gPSAoc3RhdGUucGFnZSAtIDEpICogc2l6ZSArIChkYXRhLnJvd3M/Lmxlbmd0aCA/PyAwKTtcbiAgICAgICAgICB0aGlzLnJvd0NvdW50LnNldCh7IHNob3duLCB0b3RhbDogZGF0YS5wYWdpbmc/LnRvdGFsID8/IHNob3duIH0pO1xuXG4gICAgICAgICAgLy8gTmV3IHJvd3MgY2FuIHdpZGVuIGEgcGlubmVkIGNvbHVtbiwgd2hpY2ggbW92ZXMgdGhlIG9uZXMgYWZ0ZXIgaXQuXG4gICAgICAgICAgdGhpcy5fc2NoZWR1bGVQaW5PZmZzZXRzKCk7XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZGF0YTogZGF0YS5yb3dzID8/IFtdLFxuICAgICAgICAgICAgcGFnaW5nOiB7XG4gICAgICAgICAgICAgIGxpbWl0OiBkYXRhLnBhZ2luZz8ucGFnZVNpemUgPz8gc3RhdGUucGFnZVNpemUsXG4gICAgICAgICAgICAgIHJlY29yZHM6IGRhdGEucGFnaW5nPy50b3RhbCA/PyAoZGF0YS5yb3dzPy5sZW5ndGggPz8gMCksXG4gICAgICAgICAgICAgIHBhZ2U6IGRhdGEucGFnaW5nPy5wYWdlID8/IHN0YXRlLnBhZ2UsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH07XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfVxuXG4gIC8vIEEgY3Jvc3MtdGFiJ3MgY29sdW1ucywgYnVpbHQgZnJvbSB0aGUgd2lyZSBieSBwaXZvdENvbHVtblNwZWNzKCk6IHRoZSBzYW1lXG4gIC8vIGhlYWRpbmdzIGFuZCBjZWxsIGZvcm1hdCB0aGUgUERGIGFuZCBQb3dlclBvaW50IGV4cG9ydHMgdXNlLlxuICBwcml2YXRlIF9waXZvdENvbHVtbnMoZGF0YTogQ29tcG9uZW50RGF0YSk6IChMaXN0Q29sdW1uICYgeyBudW1lcmljOiBib29sZWFuIH0pW10ge1xuICAgIGNvbnN0IGNvbmZpZyA9ICh0aGlzLmNvbXBvbmVudCgpLmNvbmZpZyA/PyB7fSkgYXMgTGlzdENvbmZpZztcblxuICAgIHJldHVybiBwaXZvdENvbHVtblNwZWNzKGNvbmZpZywgZGF0YSwgdGhpcy5mb3JtYXRDb250ZXh0KCkubG9jYWxlKTtcbiAgfVxuXG4gIC8vIEEgdGlsZSByZXNpemUgcmVmbG93cyB0aGUgdGFibGUncyBhdXRvIGxheW91dCwgc28gdGhlIHBpbm5lZCBjb2x1bW5zJ1xuICAvLyB3aWR0aHMsIGFuZCB3aXRoIHRoZW0gdGhlaXIgb2Zmc2V0cywgY2hhbmdlLlxuICBwcml2YXRlIF9vYnNlcnZlUGluT2Zmc2V0cygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5waW5uZWQoKSA8IDIgfHwgdHlwZW9mIFJlc2l6ZU9ic2VydmVyID09PSAndW5kZWZpbmVkJykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IG9ic2VydmVyID0gbmV3IFJlc2l6ZU9ic2VydmVyKCgpID0+IHRoaXMuX3NjaGVkdWxlUGluT2Zmc2V0cygpKTtcbiAgICBvYnNlcnZlci5vYnNlcnZlKHRoaXMuX2VsZW1lbnRSZWYubmF0aXZlRWxlbWVudCk7XG4gICAgdGhpcy5fZGVzdHJveVJlZi5vbkRlc3Ryb3koKCkgPT4gb2JzZXJ2ZXIuZGlzY29ubmVjdCgpKTtcbiAgfVxuXG4gIC8vIE1lYXN1cmVzIHRoZSBwaW5uZWQgb2Zmc2V0cyBvbmNlIHRoZSBuZXh0IHJlbmRlciBoYXMgbGFpZCB0aGUgdGFibGUgb3V0LlxuICAvLyBPbmUgcGVuZGluZyBtZWFzdXJlbWVudCBjb3ZlcnMgZXZlcnkgcmVxdWVzdCBtYWRlIGJlZm9yZSBpdCBydW5zLiBPbmx5XG4gIC8vIGFmdGVyTmV4dFJlbmRlciBleGlzdHMgaW4gZXZlcnkgQW5ndWxhciB2ZXJzaW9uIHRoaXMgbGlicmFyeSBydW5zIG9uLlxuICBwcml2YXRlIF9zY2hlZHVsZVBpbk9mZnNldHMoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucGlubmVkKCkgPCAyIHx8IHRoaXMuX3Bpbk9mZnNldHNSZWYpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9waW5PZmZzZXRzUmVmID0gYWZ0ZXJOZXh0UmVuZGVyKCgpID0+IHtcbiAgICAgIHRoaXMuX3Bpbk9mZnNldHNSZWYgPSBudWxsO1xuICAgICAgdGhpcy5fdXBkYXRlUGluT2Zmc2V0cygpO1xuICAgIH0sIHsgaW5qZWN0b3I6IHRoaXMuX2luamVjdG9yIH0pO1xuICB9XG5cbiAgLy8gRWFjaCBwaW5uZWQgY29sdW1uIHN0aWNrcyBhdCB0aGUgc3VtbWVkIHdpZHRoIG9mIHRoZSB2aXNpYmxlIHBpbm5lZFxuICAvLyBjb2x1bW5zIGJlZm9yZSBpdC4gQSBoaWRkZW4gY29sdW1uIHJlbmRlcnMgbm8gaGVhZGVyLCBzbyB0aGUgbmV4dCBwaW5uZWRcbiAgLy8gb25lIHRha2VzIGl0cyBwbGFjZS4gQSB2YXJpYWJsZSBpcyB3cml0dGVuIG9ubHkgd2hlbiBpdHMgdmFsdWUgY2hhbmdlZCxcbiAgLy8gd2hpY2gga2VlcHMgYSByZXNpemUgZnJvbSByZXN0eWxpbmcgdGhlIHRhYmxlIGZvciBub3RoaW5nLlxuICBwcml2YXRlIF91cGRhdGVQaW5PZmZzZXRzKCk6IHZvaWQge1xuICAgIGNvbnN0IGhvc3QgPSB0aGlzLl9lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgbGV0IGxlZnQgPSAwO1xuXG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHRoaXMucGlubmVkKCk7IGluZGV4KyspIHtcbiAgICAgIGNvbnN0IGhlYWRlciA9IGhvc3QucXVlcnlTZWxlY3RvcjxIVE1MRWxlbWVudD4oYHRoZWFkIHRoLnJlcG9ydC1waW4tJHtpbmRleH1gKTtcblxuICAgICAgaWYgKCFoZWFkZXIpIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG5hbWUgPSBgLS1yZXBvcnQtcGluLWxlZnQtJHtpbmRleH1gO1xuICAgICAgY29uc3QgdmFsdWUgPSBgJHtNYXRoLnJvdW5kKGxlZnQgKiAxMDApIC8gMTAwfXB4YDtcblxuICAgICAgaWYgKGhvc3Quc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZShuYW1lKSAhPT0gdmFsdWUpIHtcbiAgICAgICAgaG9zdC5zdHlsZS5zZXRQcm9wZXJ0eShuYW1lLCB2YWx1ZSk7XG4gICAgICB9XG5cbiAgICAgIGxlZnQgKz0gaGVhZGVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoO1xuICAgIH1cbiAgfVxufVxuIiwiQGlmICh0cnVuY2F0ZWQoKSkge1xuICA8ZGl2IGNsYXNzPVwicGl2b3QtdHJ1bmNhdGVkXCI+XG4gICAgVGhpcyBncmlkIHdhcyBidWlsdCBmcm9tIGEgcGFydGlhbCByZXN1bHQsIHNvIHNvbWUgY29sdW1ucyBvciB2YWx1ZXMgbWF5IGJlIG1pc3NpbmcuIE5hcnJvdyBpdCB3aXRoIGEgZmlsdGVyLlxuICA8L2Rpdj5cbn1cblxuPCEtLSBmcy1saXN0IHJlYWRzIGEgY29sdW1uJ3MgZm9vdGVyIHRlbXBsYXRlIG9uY2UsIGFzIGEgZGlyZWN0IGNoaWxkIG9mXG4gICAgIGZzLWxpc3QtY29sdW1uLCBzbyBhIGxpc3Qgd2l0aCB0b3RhbHMgcmVuZGVycyBpdHMgY29sdW1ucyBpbiBhIGJyYW5jaCBvZlxuICAgICB0aGVpciBvd24gcmF0aGVyIHRoYW4gd3JhcHBpbmcgdGhlIGZvb3RlciBpbiBhbiBAaWYuIC0tPlxuPGZzLWxpc3RcbiAgW2NvbmZpZ109XCJsaXN0Q29uZmlnXCJcbiAgW2NsYXNzLnJlcG9ydC10b3RhbHMtZW1wdHldPVwiIXRvdGFscygpXCI+XG4gIEBpZiAoc2hvd1RvdGFscygpKSB7XG4gICAgQGZvciAoY29sdW1uIG9mIGNvbHVtbnMoKTsgdHJhY2sgY29sdW1uLmNvbHVtbikge1xuICAgICAgPGZzLWxpc3QtY29sdW1uXG4gICAgICAgIFtuYW1lXT1cImNvbHVtbi5jb2x1bW5cIlxuICAgICAgICBbdGl0bGVdPVwiY29sdW1uLmxhYmVsIHx8IGNvbHVtbi5jb2x1bW5cIlxuICAgICAgICBbc2hvd109XCIhaGlkZGVuKCkuaGFzKGNvbHVtbi5jb2x1bW4pXCJcbiAgICAgICAgW3NvcnRhYmxlXT1cIiFwaXZvdGVkKCkgfHwgJGZpcnN0XCJcbiAgICAgICAgW2FsaWduXT1cImNvbHVtbi5udW1lcmljID8gJ3JpZ2h0JyA6ICdsZWZ0J1wiXG4gICAgICAgIFtjbGFzc109XCJjb2x1bW5DbGFzc2VzKGNvbHVtbiwgJGluZGV4LCBwaW5uZWQoKSlcIj5cbiAgICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgZnMtbGlzdC1jZWxsXG4gICAgICAgICAgbGV0LXJvdz1cInJvd1wiPlxuICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImNlbGxUcGxcIlxuICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiByb3dbY29sdW1uLmNvbHVtbl0sIGNvbHVtbjogY29sdW1uIH1cIj5cbiAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPG5nLXRlbXBsYXRlIGZzLWxpc3QtZm9vdGVyPlxuICAgICAgICAgIEBpZiAodG90YWxzKCk/Lltjb2x1bW4uY29sdW1uXSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICA8bmctY29udGFpbmVyXG4gICAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImNlbGxUcGxcIlxuICAgICAgICAgICAgICBbbmdUZW1wbGF0ZU91dGxldENvbnRleHRdPVwieyAkaW1wbGljaXQ6IHRvdGFscygpPy5bY29sdW1uLmNvbHVtbl0sIGNvbHVtbjogY29sdW1uIH1cIj5cbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxuICAgICAgICAgIH0gQGVsc2UgaWYgKGNvbHVtbi5jb2x1bW4gPT09IHRvdGFsc0xhYmVsQ29sdW1uKCkpIHtcbiAgICAgICAgICAgIHt7IHRvdGFsTGFiZWwgfX1cbiAgICAgICAgICB9XG4gICAgICAgIDwvbmctdGVtcGxhdGU+XG4gICAgICA8L2ZzLWxpc3QtY29sdW1uPlxuICAgIH1cbiAgfSBAZWxzZSB7XG4gICAgQGZvciAoY29sdW1uIG9mIGNvbHVtbnMoKTsgdHJhY2sgY29sdW1uLmNvbHVtbikge1xuICAgICAgPGZzLWxpc3QtY29sdW1uXG4gICAgICAgIFtuYW1lXT1cImNvbHVtbi5jb2x1bW5cIlxuICAgICAgICBbdGl0bGVdPVwiY29sdW1uLmxhYmVsIHx8IGNvbHVtbi5jb2x1bW5cIlxuICAgICAgICBbc2hvd109XCIhaGlkZGVuKCkuaGFzKGNvbHVtbi5jb2x1bW4pXCJcbiAgICAgICAgW3NvcnRhYmxlXT1cIiFwaXZvdGVkKCkgfHwgJGZpcnN0XCJcbiAgICAgICAgW2FsaWduXT1cImNvbHVtbi5udW1lcmljID8gJ3JpZ2h0JyA6ICdsZWZ0J1wiXG4gICAgICAgIFtjbGFzc109XCJjb2x1bW5DbGFzc2VzKGNvbHVtbiwgJGluZGV4LCBwaW5uZWQoKSlcIj5cbiAgICAgICAgPG5nLXRlbXBsYXRlXG4gICAgICAgICAgZnMtbGlzdC1jZWxsXG4gICAgICAgICAgbGV0LXJvdz1cInJvd1wiPlxuICAgICAgICAgIDxuZy1jb250YWluZXJcbiAgICAgICAgICAgIFtuZ1RlbXBsYXRlT3V0bGV0XT1cImNlbGxUcGxcIlxuICAgICAgICAgICAgW25nVGVtcGxhdGVPdXRsZXRDb250ZXh0XT1cInsgJGltcGxpY2l0OiByb3dbY29sdW1uLmNvbHVtbl0sIGNvbHVtbjogY29sdW1uIH1cIj5cbiAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgIDwvZnMtbGlzdC1jb2x1bW4+XG4gICAgfVxuICB9XG48L2ZzLWxpc3Q+XG5cbkBpZiAoY2FwdGlvbigpKSB7XG4gIDxkaXYgY2xhc3M9XCJsaXN0LWNhcHRpb24gc21hbGxcIj5cbiAgICB7eyBjYXB0aW9uKCkgfX1cbiAgPC9kaXY+XG59XG5cbjwhLS0gT25lIGNlbGwsIGluIHRoZSBib2R5IGFuZCB0aGUgdG90YWxzIHJvdyBhbGlrZTogYSBkYXRlIGNvbHVtbiBhcyBhIGRheSBpblxuICAgICB0aGUgcmVwb3J0J3Mgem9uZSBhbmQgbG9jYWxlLCBhbnkgb3RoZXIgdGhyb3VnaCBpdHMgbnVtYmVyIGZvcm1hdC4gLS0+XG48bmctdGVtcGxhdGVcbiAgI2NlbGxUcGxcbiAgbGV0LXZhbHVlXG4gIGxldC1jb2x1bW49XCJjb2x1bW5cIj5cbiAgQGlmIChjb2x1bW4uZm9ybWF0ID09PSBSZXBvcnRMaXN0Q29sdW1uRm9ybWF0LkRhdGUpIHtcbiAgICB7eyB2YWx1ZSB8IGZzUmVwb3J0RGF0ZTogdGltZXpvbmUoKSA6IGZvcm1hdENvbnRleHQoKS5sb2NhbGUgfX1cbiAgfSBAZWxzZSB7XG4gICAge3sgdmFsdWUgfCBmc1JlcG9ydE51bWJlcjogY29sdW1uIDogZm9ybWF0Q29udGV4dCgpIH19XG4gIH1cbjwvbmctdGVtcGxhdGU+XG4iXX0=