@firestitch/report 18.0.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 (58) hide show
  1. package/app/reports/components/component-chart/component-chart.component.d.ts +16 -0
  2. package/app/reports/components/component-kpi/component-kpi.component.d.ts +12 -0
  3. package/app/reports/components/component-list/component-list.component.d.ts +27 -0
  4. package/app/reports/components/report-canvas/report-canvas.component.d.ts +84 -0
  5. package/app/reports/components/report-component/report-component.component.d.ts +71 -0
  6. package/app/reports/components/timezone-select/timezone-select.component.d.ts +18 -0
  7. package/app/reports/data/report.data.d.ts +48 -0
  8. package/app/reports/dialogs/component-settings/component-settings.component.d.ts +49 -0
  9. package/app/reports/dialogs/report-settings/report-settings.component.d.ts +25 -0
  10. package/app/reports/export/offscreen-chart.d.ts +2 -0
  11. package/app/reports/export/report-export-collector.service.d.ts +26 -0
  12. package/app/reports/export/report-pdf.service.d.ts +13 -0
  13. package/app/reports/export/report-pptx.service.d.ts +14 -0
  14. package/app/reports/format.d.ts +1 -0
  15. package/app/reports/interfaces/report.interface.d.ts +174 -0
  16. package/app/reports/layout.d.ts +11 -0
  17. package/app/reports/option-builder.d.ts +15 -0
  18. package/app/reports/report-filter-items.d.ts +9 -0
  19. package/app/reports/services/report-filter-state.service.d.ts +25 -0
  20. package/app/reports/services/report.service.d.ts +15 -0
  21. package/app/reports/theme/echarts.d.ts +2 -0
  22. package/app/reports/theme/palette.d.ts +2 -0
  23. package/app/reports/views/report/report.component.d.ts +50 -0
  24. package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +47 -0
  25. package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +33 -0
  26. package/esm2022/app/reports/components/component-list/component-list.component.mjs +178 -0
  27. package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +347 -0
  28. package/esm2022/app/reports/components/report-component/report-component.component.mjs +453 -0
  29. package/esm2022/app/reports/components/timezone-select/timezone-select.component.mjs +70 -0
  30. package/esm2022/app/reports/data/report.data.mjs +152 -0
  31. package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +221 -0
  32. package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +109 -0
  33. package/esm2022/app/reports/export/offscreen-chart.mjs +33 -0
  34. package/esm2022/app/reports/export/report-export-collector.service.mjs +94 -0
  35. package/esm2022/app/reports/export/report-pdf.service.mjs +155 -0
  36. package/esm2022/app/reports/export/report-pptx.service.mjs +224 -0
  37. package/esm2022/app/reports/format.mjs +25 -0
  38. package/esm2022/app/reports/interfaces/report.interface.mjs +16 -0
  39. package/esm2022/app/reports/layout.mjs +50 -0
  40. package/esm2022/app/reports/option-builder.mjs +293 -0
  41. package/esm2022/app/reports/report-filter-items.mjs +125 -0
  42. package/esm2022/app/reports/services/report-filter-state.service.mjs +177 -0
  43. package/esm2022/app/reports/services/report.service.mjs +56 -0
  44. package/esm2022/app/reports/theme/echarts.mjs +59 -0
  45. package/esm2022/app/reports/theme/palette.mjs +10 -0
  46. package/esm2022/app/reports/views/report/report.component.mjs +354 -0
  47. package/esm2022/firestitch-report.mjs +5 -0
  48. package/esm2022/public_api.mjs +13 -0
  49. package/fesm2022/firestitch-report-echarts-BxYnpz7n.mjs +60 -0
  50. package/fesm2022/firestitch-report-echarts-BxYnpz7n.mjs.map +1 -0
  51. package/fesm2022/firestitch-report-firestitch-report-Cnotycly.mjs +3107 -0
  52. package/fesm2022/firestitch-report-firestitch-report-Cnotycly.mjs.map +1 -0
  53. package/fesm2022/firestitch-report.mjs +2 -0
  54. package/fesm2022/firestitch-report.mjs.map +1 -0
  55. package/index.d.ts +5 -0
  56. package/package.json +39 -0
  57. package/public_api.d.ts +5 -0
  58. package/styles.scss +1 -0
@@ -0,0 +1,109 @@
1
+ import { ChangeDetectionStrategy, Component, DestroyRef, inject } from '@angular/core';
2
+ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { MatButton } from '@angular/material/button';
5
+ import { MAT_DIALOG_DATA, MatDialogActions, MatDialogContent, MatDialogRef, MatDialogTitle } from '@angular/material/dialog';
6
+ import { MatFormField, MatLabel, MatHint, MatSuffix } from '@angular/material/form-field';
7
+ import { MatInput } from '@angular/material/input';
8
+ import { MatOption, MatSelect } from '@angular/material/select';
9
+ import { MatTabsModule } from '@angular/material/tabs';
10
+ import { FsDialogModule } from '@firestitch/dialog';
11
+ import { FsFormModule } from '@firestitch/form';
12
+ import { FsMessage } from '@firestitch/message';
13
+ import { FsPrompt } from '@firestitch/prompt';
14
+ import { FsTabsModule } from '@firestitch/tabs';
15
+ import { TimezoneSelectComponent } from '../../components/timezone-select/timezone-select.component';
16
+ import { switchMap, tap } from 'rxjs/operators';
17
+ import { ReportData } from '../../data/report.data';
18
+ import { DEFAULT_HEADING_SIZE } from '../../layout';
19
+ import * as i0 from "@angular/core";
20
+ import * as i1 from "@angular/forms";
21
+ import * as i2 from "@firestitch/form";
22
+ import * as i3 from "@firestitch/dialog";
23
+ import * as i4 from "@firestitch/tabs";
24
+ import * as i5 from "@angular/material/tabs";
25
+ // Report settings, in two tabs:
26
+ // Settings — name + page setup (size, orientation, layout mode). The layout
27
+ // mode is the big one: Freeform (position anything anywhere) vs Flow
28
+ // (components flow into rows by width %).
29
+ // Styles — the report's typographic styles. Sizes are in POINTS so they
30
+ // map 1:1 to PDF/PowerPoint; we start with the Heading size.
31
+ export class ReportSettingsComponent {
32
+ selectedTab = 'settings';
33
+ name = '';
34
+ pageSize = 'widescreen';
35
+ pageOrientation = 'landscape';
36
+ layout = 'freeform';
37
+ // Empty until the report has one; app-timezone-select then defaults it to the
38
+ // viewer's browser zone (which Save persists, making the report's zone explicit).
39
+ timezone = '';
40
+ headingSize = DEFAULT_HEADING_SIZE;
41
+ _data = inject(MAT_DIALOG_DATA);
42
+ _dialogRef = inject(MatDialogRef);
43
+ _reportData = inject(ReportData);
44
+ _message = inject(FsMessage);
45
+ _prompt = inject(FsPrompt);
46
+ _destroyRef = inject(DestroyRef);
47
+ ngOnInit() {
48
+ const report = this._data.report;
49
+ this.name = report.name;
50
+ this.pageSize = report.pageSize;
51
+ this.pageOrientation = report.pageOrientation;
52
+ this.layout = report.layout ?? 'freeform';
53
+ this.timezone = report.timezone ?? '';
54
+ this.headingSize = report.config?.styles?.heading?.size ?? DEFAULT_HEADING_SIZE;
55
+ }
56
+ // Confirm and delete here, while the dialog is still open, then close with
57
+ // a `deleted` result. The page reacts to the result; it no longer owns the
58
+ // prompt or the API call.
59
+ delete() {
60
+ this._prompt.confirm({
61
+ title: 'Delete Report',
62
+ template: `Delete "${this._data.report.name}"? This cannot be undone.`,
63
+ })
64
+ .pipe(switchMap(() => this._reportData.delete(this._data.report.id)), takeUntilDestroyed(this._destroyRef))
65
+ .subscribe(() => {
66
+ this._message.success('Report deleted');
67
+ this._dialogRef.close({ action: 'deleted' });
68
+ });
69
+ }
70
+ save = () => {
71
+ return this._reportData.update(this._data.report.id, {
72
+ name: this.name,
73
+ pageSize: this.pageSize,
74
+ pageOrientation: this.pageOrientation,
75
+ layout: this.layout,
76
+ timezone: this.timezone,
77
+ styles: { heading: { size: this.headingSize } },
78
+ })
79
+ .pipe(tap(() => {
80
+ this._message.success('Report settings saved');
81
+ this._dialogRef.close({ action: 'saved' });
82
+ }));
83
+ };
84
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportSettingsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
85
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: ReportSettingsComponent, isStandalone: true, selector: "ng-component", ngImport: i0, template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n Report Settings\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Name\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"name\"\n name=\"name\"\n [fsFormRequired]=\"true\">\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Page Size\n </mat-label>\n <mat-select\n [(ngModel)]=\"pageSize\"\n name=\"pageSize\">\n <mat-option value=\"widescreen\">\n Widescreen (13.33\" \u00D7 7.5\")\n </mat-option>\n <mat-option value=\"letter\">\n Letter (11\" \u00D7 8.5\")\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Orientation\n </mat-label>\n <mat-select\n [(ngModel)]=\"pageOrientation\"\n name=\"pageOrientation\">\n <mat-option value=\"landscape\">\n Landscape\n </mat-option>\n <mat-option value=\"portrait\">\n Portrait\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Layout\n </mat-label>\n <mat-select\n [(ngModel)]=\"layout\"\n name=\"layout\">\n <mat-option value=\"freeform\">\n Freeform \u2014 position components anywhere on the page\n </mat-option>\n <mat-option value=\"flow\">\n Flow \u2014 components flow into rows by width %\n </mat-option>\n </mat-select>\n <mat-hint>\n Freeform is like PowerPoint; Flow is like a responsive dashboard.\n </mat-hint>\n </mat-form-field>\n <fs-ai-report-timezone-select [(timezone)]=\"timezone\"></fs-ai-report-timezone-select>\n </div>\n </mat-tab>\n <mat-tab\n label=\"Styles\"\n name=\"styles\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Heading Size\n </mat-label>\n <input\n matInput\n type=\"number\"\n step=\"1\"\n min=\"6\"\n max=\"96\"\n [(ngModel)]=\"headingSize\"\n name=\"headingSize\"\n [fsFormMin]=\"6\"\n [fsFormMax]=\"96\">\n <span matTextSuffix>\n pt\n </span>\n <mat-hint>\n Applies to component titles. Points map 1:1 to PDF and PowerPoint.\n </mat-hint>\n </mat-form-field>\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <fs-form-dialog-actions>\n <button\n type=\"button\"\n mat-button\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n </fs-form-dialog-actions>\n </mat-dialog-actions>\n </fs-dialog>\n</form>", styles: ["mat-form-field{width:100%}.tab-body{padding-top:16px}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NumberValueAccessor, selector: "input[type=number][formControlName],input[type=number][formControl],input[type=number][ngModel]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.MinValidator, selector: "input[type=number][min][formControlName],input[type=number][min][formControl],input[type=number][min][ngModel]", inputs: ["min"] }, { kind: "directive", type: i1.MaxValidator, selector: "input[type=number][max][formControlName],input[type=number][max][formControl],input[type=number][max][ngModel]", inputs: ["max"] }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i1.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FsFormModule }, { kind: "directive", type: i2.FsFormDirective, selector: "[fsForm]", inputs: ["wrapperSelector", "messageSelector", "hintSelector", "labelSelector", "autocomplete", "shortcuts", "confirm", "confirmDialog", "confirmDrawer", "confirmBrowser", "dirtySubmitButton", "submit", "successDelay", "errorDelay", "deactivationGuard"], outputs: ["fsForm", "invalid", "valid", "submitted", "reseted", "cleared"], exportAs: ["fsForm"] }, { kind: "directive", type: i2.FsFormRequiredDirective, selector: "[fsFormRequired],[ngModel][required]", inputs: ["fsFormRequired", "required", "fsFormRequiredMessage"] }, { kind: "directive", type: i2.FsFormMinDirective, selector: "[fsFormMin]", inputs: ["fsFormMin", "fsFormMinMessage"] }, { kind: "directive", type: i2.FsFormMaxDirective, selector: "[fsFormMax]", inputs: ["fsFormMax", "fsFormMaxMessage"] }, { kind: "component", type: i2.FsFormDialogActionsComponent, selector: "fs-form-dialog-actions", inputs: ["save", "create", "close", "done", "closeData", "name"] }, { kind: "directive", type: i2.FsFormNoFsValidatorsDirective, selector: "[ngModel]:not([required]):not([fsFormRequired]):not([fsFormCompare]):not([fsFormDateRange]):not([fsFormEmail]):not([fsFormEmails]):not([fsFormFunction]):not([fsFormGreater]):not([fsFormGreaterEqual]):not([fsFormInteger]):not([fsFormLesser]):not([fsFormMax]):not([fsFormMaxLength]):not([fsFormMin]):not([fsFormMinLength]):not([fsFormNumeric]):not([fsFormPattern]):not([fsFormPhone]):not([fsFormUrl]):not([validate])" }, { kind: "directive", type: i2.FsButtonDirective, selector: "[mat-raised-button],[mat-button],[mat-flat-button],[mat-stroked-button]", inputs: ["name", "dirtySubmit"] }, { kind: "ngmodule", type: FsDialogModule }, { kind: "component", type: i3.FsDialogComponent, selector: "fs-dialog", inputs: ["mobileMode", "mobileButtonPlacement", "mobileWidth", "mode", "buttonLayout"] }, { kind: "ngmodule", type: FsTabsModule }, { kind: "directive", type: i4.FsTabsHeaderTabGroupDirective, selector: "mat-tab-group, matTabGroup, [matTabGroup]", inputs: ["orientation", "selected", "selectedData"], outputs: ["selectedChange", "selectedDataChange"], exportAs: ["fsTabsHeaderTabGroup"] }, { kind: "directive", type: i4.FsTabsTabDirective, selector: "mat-tab,matTab", inputs: ["name", "data"], exportAs: ["fsTabsTab"] }, { kind: "ngmodule", type: MatTabsModule }, { kind: "component", type: i5.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i5.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "component", type: MatButton, selector: " button[mat-button], button[mat-raised-button], button[mat-flat-button], button[mat-stroked-button] ", exportAs: ["matButton"] }, { kind: "directive", type: MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }, { kind: "component", type: MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: MatLabel, selector: "mat-label" }, { kind: "directive", type: MatHint, selector: "mat-hint", inputs: ["align", "id"] }, { kind: "directive", type: MatSuffix, selector: "[matSuffix], [matIconSuffix], [matTextSuffix]", inputs: ["matTextSuffix"] }, { kind: "directive", type: MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "component", type: TimezoneSelectComponent, selector: "fs-ai-report-timezone-select", inputs: ["placeholder", "required", "disabled", "timezone"], outputs: ["timezoneChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
86
+ }
87
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportSettingsComponent, decorators: [{
88
+ type: Component,
89
+ args: [{ changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
90
+ FormsModule,
91
+ FsFormModule,
92
+ FsDialogModule,
93
+ FsTabsModule,
94
+ MatTabsModule,
95
+ MatButton,
96
+ MatDialogTitle,
97
+ MatDialogContent,
98
+ MatDialogActions,
99
+ MatFormField,
100
+ MatLabel,
101
+ MatHint,
102
+ MatSuffix,
103
+ MatInput,
104
+ MatSelect,
105
+ MatOption,
106
+ TimezoneSelectComponent,
107
+ ], template: "<form\n fsForm\n [submit]=\"save\">\n <fs-dialog>\n <h1 mat-dialog-title>\n Report Settings\n </h1>\n <mat-dialog-content>\n <mat-tab-group [(selected)]=\"selectedTab\">\n <mat-tab\n label=\"Settings\"\n name=\"settings\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Name\n </mat-label>\n <input\n matInput\n [(ngModel)]=\"name\"\n name=\"name\"\n [fsFormRequired]=\"true\">\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Page Size\n </mat-label>\n <mat-select\n [(ngModel)]=\"pageSize\"\n name=\"pageSize\">\n <mat-option value=\"widescreen\">\n Widescreen (13.33\" \u00D7 7.5\")\n </mat-option>\n <mat-option value=\"letter\">\n Letter (11\" \u00D7 8.5\")\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Orientation\n </mat-label>\n <mat-select\n [(ngModel)]=\"pageOrientation\"\n name=\"pageOrientation\">\n <mat-option value=\"landscape\">\n Landscape\n </mat-option>\n <mat-option value=\"portrait\">\n Portrait\n </mat-option>\n </mat-select>\n </mat-form-field>\n <mat-form-field>\n <mat-label>\n Layout\n </mat-label>\n <mat-select\n [(ngModel)]=\"layout\"\n name=\"layout\">\n <mat-option value=\"freeform\">\n Freeform \u2014 position components anywhere on the page\n </mat-option>\n <mat-option value=\"flow\">\n Flow \u2014 components flow into rows by width %\n </mat-option>\n </mat-select>\n <mat-hint>\n Freeform is like PowerPoint; Flow is like a responsive dashboard.\n </mat-hint>\n </mat-form-field>\n <fs-ai-report-timezone-select [(timezone)]=\"timezone\"></fs-ai-report-timezone-select>\n </div>\n </mat-tab>\n <mat-tab\n label=\"Styles\"\n name=\"styles\">\n <div class=\"fs-column tab-body\">\n <mat-form-field>\n <mat-label>\n Heading Size\n </mat-label>\n <input\n matInput\n type=\"number\"\n step=\"1\"\n min=\"6\"\n max=\"96\"\n [(ngModel)]=\"headingSize\"\n name=\"headingSize\"\n [fsFormMin]=\"6\"\n [fsFormMax]=\"96\">\n <span matTextSuffix>\n pt\n </span>\n <mat-hint>\n Applies to component titles. Points map 1:1 to PDF and PowerPoint.\n </mat-hint>\n </mat-form-field>\n </div>\n </mat-tab>\n </mat-tab-group>\n </mat-dialog-content>\n <mat-dialog-actions>\n <fs-form-dialog-actions>\n <button\n type=\"button\"\n mat-button\n color=\"warn\"\n (click)=\"delete()\">\n Delete\n </button>\n </fs-form-dialog-actions>\n </mat-dialog-actions>\n </fs-dialog>\n</form>", styles: ["mat-form-field{width:100%}.tab-body{padding-top:16px}\n"] }]
108
+ }] });
109
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXNldHRpbmdzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9kaWFsb2dzL3JlcG9ydC1zZXR0aW5ncy9yZXBvcnQtc2V0dGluZ3MuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2RpYWxvZ3MvcmVwb3J0LXNldHRpbmdzL3JlcG9ydC1zZXR0aW5ncy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBVSxNQUFNLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDL0YsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNEJBQTRCLENBQUM7QUFDaEUsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTdDLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUNyRCxPQUFPLEVBQUUsZUFBZSxFQUFFLGdCQUFnQixFQUFFLGdCQUFnQixFQUFFLFlBQVksRUFBRSxjQUFjLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUM3SCxPQUFPLEVBQUUsWUFBWSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDMUYsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQ25ELE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sMEJBQTBCLENBQUM7QUFDaEUsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBRXZELE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNwRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFN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QUFjO3dCQUNkLGdCQUFnQjt3QkFDaEIsZ0JBQWdCO3dCQUNoQixZQUFZO3dCQUNaLFFBQVE7d0JBQ1IsT0FBTzt3QkFDUCxTQUFTO3dCQUNULFFBQVE7d0JBQ1IsU0FBUzt3QkFDVCxTQUFTO3dCQUNULHVCQUF1QjtxQkFDeEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBEZXN0cm95UmVmLCBPbkluaXQsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgdGFrZVVudGlsRGVzdHJveWVkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5cbmltcG9ydCB7IE1hdEJ1dHRvbiB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2J1dHRvbic7XG5pbXBvcnQgeyBNQVRfRElBTE9HX0RBVEEsIE1hdERpYWxvZ0FjdGlvbnMsIE1hdERpYWxvZ0NvbnRlbnQsIE1hdERpYWxvZ1JlZiwgTWF0RGlhbG9nVGl0bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC9kaWFsb2cnO1xuaW1wb3J0IHsgTWF0Rm9ybUZpZWxkLCBNYXRMYWJlbCwgTWF0SGludCwgTWF0U3VmZml4IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZm9ybS1maWVsZCc7XG5pbXBvcnQgeyBNYXRJbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2lucHV0JztcbmltcG9ydCB7IE1hdE9wdGlvbiwgTWF0U2VsZWN0IH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvc2VsZWN0JztcbmltcG9ydCB7IE1hdFRhYnNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90YWJzJztcblxuaW1wb3J0IHsgRnNEaWFsb2dNb2R1bGUgfSBmcm9tICdAZmlyZXN0aXRjaC9kaWFsb2cnO1xuaW1wb3J0IHsgRnNGb3JtTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZm9ybSc7XG5pbXBvcnQgeyBGc01lc3NhZ2UgfSBmcm9tICdAZmlyZXN0aXRjaC9tZXNzYWdlJztcbmltcG9ydCB7IEZzUHJvbXB0IH0gZnJvbSAnQGZpcmVzdGl0Y2gvcHJvbXB0JztcbmltcG9ydCB7IEZzVGFic01vZHVsZSB9IGZyb20gJ0BmaXJlc3RpdGNoL3RhYnMnO1xuXG5pbXBvcnQgeyBUaW1lem9uZVNlbGVjdENvbXBvbmVudCB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvdGltZXpvbmUtc2VsZWN0L3RpbWV6b25lLXNlbGVjdC5jb21wb25lbnQnO1xuXG5pbXBvcnQgeyBzd2l0Y2hNYXAsIHRhcCB9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcblxuaW1wb3J0IHsgUmVwb3J0RGF0YSB9IGZyb20gJy4uLy4uL2RhdGEvcmVwb3J0LmRhdGEnO1xuaW1wb3J0IHsgUmVwb3J0IH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IERFRkFVTFRfSEVBRElOR19TSVpFIH0gZnJvbSAnLi4vLi4vbGF5b3V0JztcblxuXG4vLyBXaGF0IHRoZSBkaWFsb2cgaGFuZHMgYmFjayB3aGVuIGl0IGNsb3Nlcywgc28gdGhlIHBhZ2Uga25vd3Mgd2hhdCBoYXBwZW5lZFxuLy8gd2l0aG91dCBzbmlmZmluZyBtYWdpYyBzdHJpbmdzLiBBIGRpc21pc3NlZCBkaWFsb2cgY2xvc2VzIHdpdGggYHVuZGVmaW5lZGAuXG5leHBvcnQgaW50ZXJmYWNlIFJlcG9ydFNldHRpbmdzUmVzdWx0IHtcbiAgYWN0aW9uOiAnc2F2ZWQnIHwgJ2RlbGV0ZWQnO1xufVxuXG5cbi8vIFJlcG9ydCBzZXR0aW5ncywgaW4gdHdvIHRhYnM6XG4vLyAgIFNldHRpbmdzIOKAlCBuYW1lICsgcGFnZSBzZXR1cCAoc2l6ZSwgb3JpZW50YXRpb24sIGxheW91dCBtb2RlKS4gVGhlIGxheW91dFxuLy8gICBtb2RlIGlzIHRoZSBiaWcgb25lOiBGcmVlZm9ybSAocG9zaXRpb24gYW55dGhpbmcgYW55d2hlcmUpIHZzIEZsb3dcbi8vICAgKGNvbXBvbmVudHMgZmxvdyBpbnRvIHJvd3MgYnkgd2lkdGggJSkuXG4vLyAgIFN0eWxlcyAgIOKAlCB0aGUgcmVwb3J0J3MgdHlwb2dyYXBoaWMgc3R5bGVzLiBTaXplcyBhcmUgaW4gUE9JTlRTIHNvIHRoZXlcbi8vICAgbWFwIDE6MSB0byBQREYvUG93ZXJQb2ludDsgd2Ugc3RhcnQgd2l0aCB0aGUgSGVhZGluZyBzaXplLlxuQENvbXBvbmVudCh7XG4gIHRlbXBsYXRlVXJsOiAnLi9yZXBvcnQtc2V0dGluZ3MuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9yZXBvcnQtc2V0dGluZ3MuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBGb3Jtc01vZHVsZSxcbiAgICBGc0Zvcm1Nb2R1bGUsXG4gICAgRnNEaWFsb2dNb2R1bGUsXG4gICAgRnNUYWJzTW9kdWxlLFxuICAgIE1hdFRhYnNNb2R1bGUsXG4gICAgTWF0QnV0dG9uLFxuICAgIE1hdERpYWxvZ1RpdGxlLFxuICAgIE1hdERpYWxvZ0NvbnRlbnQsXG4gICAgTWF0RGlhbG9nQWN0aW9ucyxcbiAgICBNYXRGb3JtRmllbGQsXG4gICAgTWF0TGFiZWwsXG4gICAgTWF0SGludCxcbiAgICBNYXRTdWZmaXgsXG4gICAgTWF0SW5wdXQsXG4gICAgTWF0U2VsZWN0LFxuICAgIE1hdE9wdGlvbixcbiAgICBUaW1lem9uZVNlbGVjdENvbXBvbmVudCxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgUmVwb3J0U2V0dGluZ3NDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuXG4gIHB1YmxpYyBzZWxlY3RlZFRhYiA9ICdzZXR0aW5ncyc7XG5cbiAgcHVibGljIG5hbWUgPSAnJztcbiAgcHVibGljIHBhZ2VTaXplOiAnd2lkZXNjcmVlbicgfCAnbGV0dGVyJyA9ICd3aWRlc2NyZWVuJztcbiAgcHVibGljIHBhZ2VPcmllbnRhdGlvbjogJ2xhbmRzY2FwZScgfCAncG9ydHJhaXQnID0gJ2xhbmRzY2FwZSc7XG4gIHB1YmxpYyBsYXlvdXQ6ICdmcmVlZm9ybScgfCAnZmxvdycgPSAnZnJlZWZvcm0nO1xuICAvLyBFbXB0eSB1bnRpbCB0aGUgcmVwb3J0IGhhcyBvbmU7IGFwcC10aW1lem9uZS1zZWxlY3QgdGhlbiBkZWZhdWx0cyBpdCB0byB0aGVcbiAgLy8gdmlld2VyJ3MgYnJvd3NlciB6b25lICh3aGljaCBTYXZlIHBlcnNpc3RzLCBtYWtpbmcgdGhlIHJlcG9ydCdzIHpvbmUgZXhwbGljaXQpLlxuICBwdWJsaWMgdGltZXpvbmUgPSAnJztcbiAgcHVibGljIGhlYWRpbmdTaXplID0gREVGQVVMVF9IRUFESU5HX1NJWkU7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfZGF0YTogeyByZXBvcnQ6IFJlcG9ydCB9ID0gaW5qZWN0KE1BVF9ESUFMT0dfREFUQSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2RpYWxvZ1JlZiA9IGluamVjdDxNYXREaWFsb2dSZWY8UmVwb3J0U2V0dGluZ3NDb21wb25lbnQsIFJlcG9ydFNldHRpbmdzUmVzdWx0Pj4oTWF0RGlhbG9nUmVmKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfcmVwb3J0RGF0YSA9IGluamVjdChSZXBvcnREYXRhKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfbWVzc2FnZSA9IGluamVjdChGc01lc3NhZ2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9wcm9tcHQgPSBpbmplY3QoRnNQcm9tcHQpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9kZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuXG4gIHB1YmxpYyBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICBjb25zdCByZXBvcnQgPSB0aGlzLl9kYXRhLnJlcG9ydDtcbiAgICB0aGlzLm5hbWUgPSByZXBvcnQubmFtZTtcbiAgICB0aGlzLnBhZ2VTaXplID0gcmVwb3J0LnBhZ2VTaXplO1xuICAgIHRoaXMucGFnZU9yaWVudGF0aW9uID0gcmVwb3J0LnBhZ2VPcmllbnRhdGlvbjtcbiAgICB0aGlzLmxheW91dCA9IHJlcG9ydC5sYXlvdXQgPz8gJ2ZyZWVmb3JtJztcbiAgICB0aGlzLnRpbWV6b25lID0gcmVwb3J0LnRpbWV6b25lID8/ICcnO1xuICAgIHRoaXMuaGVhZGluZ1NpemUgPSByZXBvcnQuY29uZmlnPy5zdHlsZXM/LmhlYWRpbmc/LnNpemUgPz8gREVGQVVMVF9IRUFESU5HX1NJWkU7XG4gIH1cblxuICAvLyBDb25maXJtIGFuZCBkZWxldGUgaGVyZSwgd2hpbGUgdGhlIGRpYWxvZyBpcyBzdGlsbCBvcGVuLCB0aGVuIGNsb3NlIHdpdGhcbiAgLy8gYSBgZGVsZXRlZGAgcmVzdWx0LiBUaGUgcGFnZSByZWFjdHMgdG8gdGhlIHJlc3VsdDsgaXQgbm8gbG9uZ2VyIG93bnMgdGhlXG4gIC8vIHByb21wdCBvciB0aGUgQVBJIGNhbGwuXG4gIHB1YmxpYyBkZWxldGUoKTogdm9pZCB7XG4gICAgdGhpcy5fcHJvbXB0LmNvbmZpcm0oe1xuICAgICAgdGl0bGU6ICdEZWxldGUgUmVwb3J0JyxcbiAgICAgIHRlbXBsYXRlOiBgRGVsZXRlIFwiJHt0aGlzLl9kYXRhLnJlcG9ydC5uYW1lfVwiPyBUaGlzIGNhbm5vdCBiZSB1bmRvbmUuYCxcbiAgICB9KVxuICAgICAgLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcCgoKSA9PiB0aGlzLl9yZXBvcnREYXRhLmRlbGV0ZSh0aGlzLl9kYXRhLnJlcG9ydC5pZCkpLFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZiksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHtcbiAgICAgICAgdGhpcy5fbWVzc2FnZS5zdWNjZXNzKCdSZXBvcnQgZGVsZXRlZCcpO1xuICAgICAgICB0aGlzLl9kaWFsb2dSZWYuY2xvc2UoeyBhY3Rpb246ICdkZWxldGVkJyB9KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHVibGljIHNhdmUgPSAoKSA9PiB7XG4gICAgcmV0dXJuIHRoaXMuX3JlcG9ydERhdGEudXBkYXRlKHRoaXMuX2RhdGEucmVwb3J0LmlkLCB7XG4gICAgICBuYW1lOiB0aGlzLm5hbWUsXG4gICAgICBwYWdlU2l6ZTogdGhpcy5wYWdlU2l6ZSxcbiAgICAgIHBhZ2VPcmllbnRhdGlvbjogdGhpcy5wYWdlT3JpZW50YXRpb24sXG4gICAgICBsYXlvdXQ6IHRoaXMubGF5b3V0LFxuICAgICAgdGltZXpvbmU6IHRoaXMudGltZXpvbmUsXG4gICAgICBzdHlsZXM6IHsgaGVhZGluZzogeyBzaXplOiB0aGlzLmhlYWRpbmdTaXplIH0gfSxcbiAgICB9KVxuICAgICAgLnBpcGUoXG4gICAgICAgIHRhcCgoKSA9PiB7XG4gICAgICAgICAgdGhpcy5fbWVzc2FnZS5zdWNjZXNzKCdSZXBvcnQgc2V0dGluZ3Mgc2F2ZWQnKTtcbiAgICAgICAgICB0aGlzLl9kaWFsb2dSZWYuY2xvc2UoeyBhY3Rpb246ICdzYXZlZCcgfSk7XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfTtcbn1cbiIsIjxmb3JtXG4gICAgZnNGb3JtXG4gICAgW3N1Ym1pdF09XCJzYXZlXCI+XG4gIDxmcy1kaWFsb2c+XG4gICAgPGgxIG1hdC1kaWFsb2ctdGl0bGU+XG4gICAgICBSZXBvcnQgU2V0dGluZ3NcbiAgICA8L2gxPlxuICAgIDxtYXQtZGlhbG9nLWNvbnRlbnQ+XG4gICAgICA8bWF0LXRhYi1ncm91cCBbKHNlbGVjdGVkKV09XCJzZWxlY3RlZFRhYlwiPlxuICAgICAgICA8bWF0LXRhYlxuICAgICAgICAgICAgbGFiZWw9XCJTZXR0aW5nc1wiXG4gICAgICAgICAgICBuYW1lPVwic2V0dGluZ3NcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZnMtY29sdW1uIHRhYi1ib2R5XCI+XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgTmFtZVxuICAgICAgICAgICAgICA8L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cIm5hbWVcIlxuICAgICAgICAgICAgICAgIG5hbWU9XCJuYW1lXCJcbiAgICAgICAgICAgICAgICBbZnNGb3JtUmVxdWlyZWRdPVwidHJ1ZVwiPlxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICBQYWdlIFNpemVcbiAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInBhZ2VTaXplXCJcbiAgICAgICAgICAgICAgICAgIG5hbWU9XCJwYWdlU2l6ZVwiPlxuICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIHZhbHVlPVwid2lkZXNjcmVlblwiPlxuICAgICAgICAgICAgICAgICAgV2lkZXNjcmVlbiAoMTMuMzNcIiDDlyA3LjVcIilcbiAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gdmFsdWU9XCJsZXR0ZXJcIj5cbiAgICAgICAgICAgICAgICAgIExldHRlciAoMTFcIiDDlyA4LjVcIilcbiAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgT3JpZW50YXRpb25cbiAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cInBhZ2VPcmllbnRhdGlvblwiXG4gICAgICAgICAgICAgICAgICBuYW1lPVwicGFnZU9yaWVudGF0aW9uXCI+XG4gICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gdmFsdWU9XCJsYW5kc2NhcGVcIj5cbiAgICAgICAgICAgICAgICAgIExhbmRzY2FwZVxuICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgICA8bWF0LW9wdGlvbiB2YWx1ZT1cInBvcnRyYWl0XCI+XG4gICAgICAgICAgICAgICAgICBQb3J0cmFpdFxuICAgICAgICAgICAgICAgIDwvbWF0LW9wdGlvbj5cbiAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgPG1hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICBMYXlvdXRcbiAgICAgICAgICAgICAgPC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgIDxtYXQtc2VsZWN0XG4gICAgICAgICAgICAgICAgICBbKG5nTW9kZWwpXT1cImxheW91dFwiXG4gICAgICAgICAgICAgICAgICBuYW1lPVwibGF5b3V0XCI+XG4gICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gdmFsdWU9XCJmcmVlZm9ybVwiPlxuICAgICAgICAgICAgICAgICAgRnJlZWZvcm0g4oCUIHBvc2l0aW9uIGNvbXBvbmVudHMgYW55d2hlcmUgb24gdGhlIHBhZ2VcbiAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgICAgPG1hdC1vcHRpb24gdmFsdWU9XCJmbG93XCI+XG4gICAgICAgICAgICAgICAgICBGbG93IOKAlCBjb21wb25lbnRzIGZsb3cgaW50byByb3dzIGJ5IHdpZHRoICVcbiAgICAgICAgICAgICAgICA8L21hdC1vcHRpb24+XG4gICAgICAgICAgICAgIDwvbWF0LXNlbGVjdD5cbiAgICAgICAgICAgICAgPG1hdC1oaW50PlxuICAgICAgICAgICAgICAgIEZyZWVmb3JtIGlzIGxpa2UgUG93ZXJQb2ludDsgRmxvdyBpcyBsaWtlIGEgcmVzcG9uc2l2ZSBkYXNoYm9hcmQuXG4gICAgICAgICAgICAgIDwvbWF0LWhpbnQ+XG4gICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPGZzLWFpLXJlcG9ydC10aW1lem9uZS1zZWxlY3QgWyh0aW1lem9uZSldPVwidGltZXpvbmVcIj48L2ZzLWFpLXJlcG9ydC10aW1lem9uZS1zZWxlY3Q+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvbWF0LXRhYj5cbiAgICAgICAgPG1hdC10YWJcbiAgICAgICAgICAgIGxhYmVsPVwiU3R5bGVzXCJcbiAgICAgICAgICAgIG5hbWU9XCJzdHlsZXNcIj5cbiAgICAgICAgICA8ZGl2IGNsYXNzPVwiZnMtY29sdW1uIHRhYi1ib2R5XCI+XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgSGVhZGluZyBTaXplXG4gICAgICAgICAgICAgIDwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8aW5wdXRcbiAgICAgICAgICAgICAgICBtYXRJbnB1dFxuICAgICAgICAgICAgICAgIHR5cGU9XCJudW1iZXJcIlxuICAgICAgICAgICAgICAgIHN0ZXA9XCIxXCJcbiAgICAgICAgICAgICAgICBtaW49XCI2XCJcbiAgICAgICAgICAgICAgICBtYXg9XCI5NlwiXG4gICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJoZWFkaW5nU2l6ZVwiXG4gICAgICAgICAgICAgICAgbmFtZT1cImhlYWRpbmdTaXplXCJcbiAgICAgICAgICAgICAgICBbZnNGb3JtTWluXT1cIjZcIlxuICAgICAgICAgICAgICAgIFtmc0Zvcm1NYXhdPVwiOTZcIj5cbiAgICAgICAgICAgICAgPHNwYW4gbWF0VGV4dFN1ZmZpeD5cbiAgICAgICAgICAgICAgICBwdFxuICAgICAgICAgICAgICA8L3NwYW4+XG4gICAgICAgICAgICAgIDxtYXQtaGludD5cbiAgICAgICAgICAgICAgICBBcHBsaWVzIHRvIGNvbXBvbmVudCB0aXRsZXMuIFBvaW50cyBtYXAgMToxIHRvIFBERiBhbmQgUG93ZXJQb2ludC5cbiAgICAgICAgICAgICAgPC9tYXQtaGludD5cbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvbWF0LXRhYj5cbiAgICAgIDwvbWF0LXRhYi1ncm91cD5cbiAgICA8L21hdC1kaWFsb2ctY29udGVudD5cbiAgICA8bWF0LWRpYWxvZy1hY3Rpb25zPlxuICAgICAgPGZzLWZvcm0tZGlhbG9nLWFjdGlvbnM+XG4gICAgICAgIDxidXR0b25cbiAgICAgICAgICAgIHR5cGU9XCJidXR0b25cIlxuICAgICAgICAgICAgbWF0LWJ1dHRvblxuICAgICAgICAgICAgY29sb3I9XCJ3YXJuXCJcbiAgICAgICAgICAgIChjbGljayk9XCJkZWxldGUoKVwiPlxuICAgICAgICAgIERlbGV0ZVxuICAgICAgICA8L2J1dHRvbj5cbiAgICAgIDwvZnMtZm9ybS1kaWFsb2ctYWN0aW9ucz5cbiAgICA8L21hdC1kaWFsb2ctYWN0aW9ucz5cbiAgPC9mcy1kaWFsb2c+XG48L2Zvcm0+Il19
@@ -0,0 +1,33 @@
1
+ import { buildChartOption } from '../option-builder';
2
+ // Renders a chart to a PNG data URL WITHOUT it being on screen — the PDF
3
+ // export needs every page's charts, but the canvas only renders the active
4
+ // page. ECharts happily initializes against a detached element when given
5
+ // explicit pixel dimensions; animations are disabled so getDataURL is
6
+ // complete synchronously after setOption.
7
+ export async function renderChartImage(component, data, width, height, pixelRatio = 3) {
8
+ // The same tree-shaken echarts build + 'report' theme the live canvas uses.
9
+ const echarts = (await import('../theme/echarts')).default;
10
+ const host = document.createElement('div');
11
+ host.style.width = `${width}px`;
12
+ host.style.height = `${height}px`;
13
+ const chart = echarts.init(host, 'report', {
14
+ renderer: 'canvas',
15
+ width,
16
+ height,
17
+ });
18
+ try {
19
+ chart.setOption({
20
+ ...buildChartOption(component, data),
21
+ animation: false,
22
+ });
23
+ return chart.getDataURL({
24
+ type: 'png',
25
+ pixelRatio,
26
+ backgroundColor: '#ffffff',
27
+ });
28
+ }
29
+ finally {
30
+ chart.dispose();
31
+ }
32
+ }
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2Zmc2NyZWVuLWNoYXJ0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2V4cG9ydC9vZmZzY3JlZW4tY2hhcnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFHckQseUVBQXlFO0FBQ3pFLDJFQUEyRTtBQUMzRSwwRUFBMEU7QUFDMUUsc0VBQXNFO0FBQ3RFLDBDQUEwQztBQUMxQyxNQUFNLENBQUMsS0FBSyxVQUFVLGdCQUFnQixDQUNwQyxTQUEwQixFQUMxQixJQUFtQixFQUNuQixLQUFhLEVBQ2IsTUFBYyxFQUNkLFVBQVUsR0FBRyxDQUFDO0lBRWQsNEVBQTRFO0lBQzVFLE1BQU0sT0FBTyxHQUFHLENBQUMsTUFBTSxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztJQUUzRCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzNDLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLEdBQUcsS0FBSyxJQUFJLENBQUM7SUFDaEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsR0FBRyxNQUFNLElBQUksQ0FBQztJQUVsQyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksRUFBRSxRQUFRLEVBQUU7UUFDekMsUUFBUSxFQUFFLFFBQVE7UUFDbEIsS0FBSztRQUNMLE1BQU07S0FDUCxDQUFDLENBQUM7SUFFSCxJQUFJLENBQUM7UUFDSCxLQUFLLENBQUMsU0FBUyxDQUFDO1lBQ2QsR0FBRyxnQkFBZ0IsQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDO1lBQ3BDLFNBQVMsRUFBRSxLQUFLO1NBQ2pCLENBQUMsQ0FBQztRQUVILE9BQU8sS0FBSyxDQUFDLFVBQVUsQ0FBQztZQUN0QixJQUFJLEVBQUUsS0FBSztZQUNYLFVBQVU7WUFDVixlQUFlLEVBQUUsU0FBUztTQUMzQixDQUFDLENBQUM7SUFDTCxDQUFDO1lBQVMsQ0FBQztRQUNULEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUNsQixDQUFDO0FBQ0gsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudERhdGEsIFJlcG9ydENvbXBvbmVudCB9IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5pbXBvcnQgeyBidWlsZENoYXJ0T3B0aW9uIH0gZnJvbSAnLi4vb3B0aW9uLWJ1aWxkZXInO1xuXG5cbi8vIFJlbmRlcnMgYSBjaGFydCB0byBhIFBORyBkYXRhIFVSTCBXSVRIT1VUIGl0IGJlaW5nIG9uIHNjcmVlbiDigJQgdGhlIFBERlxuLy8gZXhwb3J0IG5lZWRzIGV2ZXJ5IHBhZ2UncyBjaGFydHMsIGJ1dCB0aGUgY2FudmFzIG9ubHkgcmVuZGVycyB0aGUgYWN0aXZlXG4vLyBwYWdlLiBFQ2hhcnRzIGhhcHBpbHkgaW5pdGlhbGl6ZXMgYWdhaW5zdCBhIGRldGFjaGVkIGVsZW1lbnQgd2hlbiBnaXZlblxuLy8gZXhwbGljaXQgcGl4ZWwgZGltZW5zaW9uczsgYW5pbWF0aW9ucyBhcmUgZGlzYWJsZWQgc28gZ2V0RGF0YVVSTCBpc1xuLy8gY29tcGxldGUgc3luY2hyb25vdXNseSBhZnRlciBzZXRPcHRpb24uXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVuZGVyQ2hhcnRJbWFnZShcbiAgY29tcG9uZW50OiBSZXBvcnRDb21wb25lbnQsXG4gIGRhdGE6IENvbXBvbmVudERhdGEsXG4gIHdpZHRoOiBudW1iZXIsXG4gIGhlaWdodDogbnVtYmVyLFxuICBwaXhlbFJhdGlvID0gMyxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIC8vIFRoZSBzYW1lIHRyZWUtc2hha2VuIGVjaGFydHMgYnVpbGQgKyAncmVwb3J0JyB0aGVtZSB0aGUgbGl2ZSBjYW52YXMgdXNlcy5cbiAgY29uc3QgZWNoYXJ0cyA9IChhd2FpdCBpbXBvcnQoJy4uL3RoZW1lL2VjaGFydHMnKSkuZGVmYXVsdDtcblxuICBjb25zdCBob3N0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gIGhvc3Quc3R5bGUud2lkdGggPSBgJHt3aWR0aH1weGA7XG4gIGhvc3Quc3R5bGUuaGVpZ2h0ID0gYCR7aGVpZ2h0fXB4YDtcblxuICBjb25zdCBjaGFydCA9IGVjaGFydHMuaW5pdChob3N0LCAncmVwb3J0Jywge1xuICAgIHJlbmRlcmVyOiAnY2FudmFzJyxcbiAgICB3aWR0aCxcbiAgICBoZWlnaHQsXG4gIH0pO1xuXG4gIHRyeSB7XG4gICAgY2hhcnQuc2V0T3B0aW9uKHtcbiAgICAgIC4uLmJ1aWxkQ2hhcnRPcHRpb24oY29tcG9uZW50LCBkYXRhKSxcbiAgICAgIGFuaW1hdGlvbjogZmFsc2UsXG4gICAgfSk7XG5cbiAgICByZXR1cm4gY2hhcnQuZ2V0RGF0YVVSTCh7XG4gICAgICB0eXBlOiAncG5nJyxcbiAgICAgIHBpeGVsUmF0aW8sXG4gICAgICBiYWNrZ3JvdW5kQ29sb3I6ICcjZmZmZmZmJyxcbiAgICB9KTtcbiAgfSBmaW5hbGx5IHtcbiAgICBjaGFydC5kaXNwb3NlKCk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,94 @@
1
+ import { Injectable, inject } from '@angular/core';
2
+ import { forkJoin, map, of } from 'rxjs';
3
+ import { catchError } from 'rxjs/operators';
4
+ import { format } from 'date-fns';
5
+ import { ReportData } from '../data/report.data';
6
+ import { FREQUENCY_OPTIONS, } from '../interfaces/report.interface';
7
+ import { ReportFilterStateService } from '../services/report-filter-state.service';
8
+ import * as i0 from "@angular/core";
9
+ // Rows fetched for a list component's export table — enough to fill a
10
+ // slide/page table; the cap note covers the rest.
11
+ const LIST_EXPORT_ROWS = 100;
12
+ // Gathers everything an export needs: every component's data across ALL pages
13
+ // (the canvas only renders the active page, so exports can't scrape the
14
+ // screen), fetched fresh with the viewer's current filter state. One failed
15
+ // component degrades to a note in the deck, never a failed export.
16
+ export class ReportExportCollectorService {
17
+ _reportData = inject(ReportData);
18
+ _filterState = inject(ReportFilterStateService);
19
+ collect(report) {
20
+ const requests = [];
21
+ const slots = [];
22
+ report.pages.forEach((page, pageIndex) => {
23
+ for (const component of page.components) {
24
+ slots.push({ pageIndex });
25
+ requests.push(this._componentData(report, component));
26
+ }
27
+ });
28
+ const all$ = requests.length ? forkJoin(requests) : of([]);
29
+ return all$
30
+ .pipe(map((collected) => {
31
+ const pages = report.pages.map((page) => ({ page, components: [] }));
32
+ collected.forEach((item, index) => {
33
+ pages[slots[index].pageIndex].components.push(item);
34
+ });
35
+ return {
36
+ report,
37
+ pages,
38
+ filterSummary: this._filterSummary(report),
39
+ };
40
+ }));
41
+ }
42
+ _componentData(report, component) {
43
+ const filters = this._filterState.resolveForComponent(component);
44
+ // A time-series chart carries the viewer's Frequency override so the export
45
+ // re-buckets exactly as the screen does; lists carry their export paging.
46
+ const frequency = this._filterState.frequency();
47
+ const isTimeSeries = component.type === 'chart' && component.config?.xAxis?.kind === 'time';
48
+ const state = component.type === 'list'
49
+ ? { page: 1, pageSize: LIST_EXPORT_ROWS }
50
+ : (isTimeSeries && frequency ? { frequency } : {});
51
+ return this._reportData.componentData(report.id, component.id, filters, state)
52
+ .pipe(map((data) => ({ component, data })), catchError(() => of({ component, data: null })));
53
+ }
54
+ // "Report Period: Jun 12, 2025 – Jun 12, 2026", "Organization: A, B" — one
55
+ // line per filter group that has an active session value.
56
+ _filterSummary(report) {
57
+ const lines = [];
58
+ for (const group of report.filterGroups ?? []) {
59
+ const value = this._filterState.value(group.id);
60
+ if (!value) {
61
+ continue;
62
+ }
63
+ const label = group.label || 'Filter';
64
+ if (value.start || value.end) {
65
+ lines.push(`${label}: ${this._date(value.start)} – ${this._date(value.end)}`);
66
+ }
67
+ else if (value.values?.length) {
68
+ lines.push(`${label}: ${value.values.map((item) => String(item)).join(', ')}`);
69
+ }
70
+ else if (value.value?.trim()) {
71
+ lines.push(`${label}: "${value.value.trim()}"`);
72
+ }
73
+ }
74
+ const frequency = this._filterState.frequency();
75
+ if (frequency) {
76
+ const option = FREQUENCY_OPTIONS.find((item) => item.value === frequency);
77
+ lines.push(`Frequency: ${option?.name ?? frequency}`);
78
+ }
79
+ return lines;
80
+ }
81
+ _date(value) {
82
+ if (!value) {
83
+ return '…';
84
+ }
85
+ const date = value instanceof Date ? value : new Date(value);
86
+ return Number.isNaN(date.getTime()) ? String(value) : format(date, 'MMM d, yyyy');
87
+ }
88
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportExportCollectorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
89
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportExportCollectorService });
90
+ }
91
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportExportCollectorService, decorators: [{
92
+ type: Injectable
93
+ }] });
94
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LWV4cG9ydC1jb2xsZWN0b3Iuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9leHBvcnQvcmVwb3J0LWV4cG9ydC1jb2xsZWN0b3Iuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVuRCxPQUFPLEVBQWMsUUFBUSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFDckQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBRTVDLE9BQU8sRUFBRSxNQUFNLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFFbEMsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ2pELE9BQU8sRUFFTCxpQkFBaUIsR0FJbEIsTUFBTSxnQ0FBZ0MsQ0FBQztBQUN4QyxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSx5Q0FBeUMsQ0FBQzs7QUFvQm5GLHNFQUFzRTtBQUN0RSxrREFBa0Q7QUFDbEQsTUFBTSxnQkFBZ0IsR0FBRyxHQUFHLENBQUM7QUFFN0IsOEVBQThFO0FBQzlFLHdFQUF3RTtBQUN4RSw0RUFBNEU7QUFDNUUsbUVBQW1FO0FBRW5FLE1BQU0sT0FBTyw0QkFBNEI7SUFFL0IsV0FBVyxHQUFHLE1BQU0sQ0FBQyxVQUFVLENBQUMsQ0FBQztJQUNqQyxZQUFZLEdBQUcsTUFBTSxDQUFDLHdCQUF3QixDQUFDLENBQUM7SUFFakQsT0FBTyxDQUFDLE1BQWM7UUFDM0IsTUFBTSxRQUFRLEdBQXFDLEVBQUUsQ0FBQztRQUN0RCxNQUFNLEtBQUssR0FBNEIsRUFBRSxDQUFDO1FBRTFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxFQUFFLFNBQVMsRUFBRSxFQUFFO1lBQ3ZDLEtBQUssTUFBTSxT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RUFBRSxJQUFJLElBQUksU0FBUyxFQUFFLENBQUMsQ0FBQztRQUN4RCxDQUFDO1FBRUQsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0lBRU8sS0FBSyxDQUFDLEtBQXVDO1FBQ25ELElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNYLE9BQU8sR0FBRyxDQUFDO1FBQ2IsQ0FBQztRQUVELE1BQU0sSUFBSSxHQUFHLEtBQUssWUFBWSxJQUFJLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUM7UUFFN0QsT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsYUFBYSxDQUFDLENBQUM7SUFDcEYsQ0FBQzt3R0EzRlUsNEJBQTRCOzRHQUE1Qiw0QkFBNEI7OzRGQUE1Qiw0QkFBNEI7a0JBRHhDLFVBQVUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBJbmplY3RhYmxlLCBpbmplY3QgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgZm9ya0pvaW4sIG1hcCwgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IGNhdGNoRXJyb3IgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5cbmltcG9ydCB7IGZvcm1hdCB9IGZyb20gJ2RhdGUtZm5zJztcblxuaW1wb3J0IHsgUmVwb3J0RGF0YSB9IGZyb20gJy4uL2RhdGEvcmVwb3J0LmRhdGEnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50RGF0YSxcbiAgRlJFUVVFTkNZX09QVElPTlMsXG4gIFJlcG9ydCxcbiAgUmVwb3J0Q29tcG9uZW50LFxuICBSZXBvcnRQYWdlLFxufSBmcm9tICcuLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvcmVwb3J0LWZpbHRlci1zdGF0ZS5zZXJ2aWNlJztcblxuXG5leHBvcnQgaW50ZXJmYWNlIENvbGxlY3RlZENvbXBvbmVudCB7XG4gIGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50O1xuICBkYXRhOiBDb21wb25lbnREYXRhIHwgbnVsbDsgLy8gbnVsbCA9IGl0cyBxdWVyeSBmYWlsZWQ7IGV4cG9ydHMgc2hvdyBhIG5vdGVcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb2xsZWN0ZWRQYWdlIHtcbiAgcGFnZTogUmVwb3J0UGFnZTtcbiAgY29tcG9uZW50czogQ29sbGVjdGVkQ29tcG9uZW50W107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29sbGVjdGVkUmVwb3J0IHtcbiAgcmVwb3J0OiBSZXBvcnQ7XG4gIHBhZ2VzOiBDb2xsZWN0ZWRQYWdlW107XG4gIC8vIEh1bWFuLXJlYWRhYmxlIGxpbmVzIGRlc2NyaWJpbmcgdGhlIGFjdGl2ZSBmaWx0ZXJzLCBmb3IgdGhlIHRpdGxlIHNsaWRlL3BhZ2UuXG4gIGZpbHRlclN1bW1hcnk6IHN0cmluZ1tdO1xufVxuXG4vLyBSb3dzIGZldGNoZWQgZm9yIGEgbGlzdCBjb21wb25lbnQncyBleHBvcnQgdGFibGUg4oCUIGVub3VnaCB0byBmaWxsIGFcbi8vIHNsaWRlL3BhZ2UgdGFibGU7IHRoZSBjYXAgbm90ZSBjb3ZlcnMgdGhlIHJlc3QuXG5jb25zdCBMSVNUX0VYUE9SVF9ST1dTID0gMTAwO1xuXG4vLyBHYXRoZXJzIGV2ZXJ5dGhpbmcgYW4gZXhwb3J0IG5lZWRzOiBldmVyeSBjb21wb25lbnQncyBkYXRhIGFjcm9zcyBBTEwgcGFnZXNcbi8vICh0aGUgY2FudmFzIG9ubHkgcmVuZGVycyB0aGUgYWN0aXZlIHBhZ2UsIHNvIGV4cG9ydHMgY2FuJ3Qgc2NyYXBlIHRoZVxuLy8gc2NyZWVuKSwgZmV0Y2hlZCBmcmVzaCB3aXRoIHRoZSB2aWV3ZXIncyBjdXJyZW50IGZpbHRlciBzdGF0ZS4gT25lIGZhaWxlZFxuLy8gY29tcG9uZW50IGRlZ3JhZGVzIHRvIGEgbm90ZSBpbiB0aGUgZGVjaywgbmV2ZXIgYSBmYWlsZWQgZXhwb3J0LlxuQEluamVjdGFibGUoKVxuZXhwb3J0IGNsYXNzIFJlcG9ydEV4cG9ydENvbGxlY3RvclNlcnZpY2Uge1xuXG4gIHByaXZhdGUgX3JlcG9ydERhdGEgPSBpbmplY3QoUmVwb3J0RGF0YSk7XG4gIHByaXZhdGUgX2ZpbHRlclN0YXRlID0gaW5qZWN0KFJlcG9ydEZpbHRlclN0YXRlU2VydmljZSk7XG5cbiAgcHVibGljIGNvbGxlY3QocmVwb3J0OiBSZXBvcnQpOiBPYnNlcnZhYmxlPENvbGxlY3RlZFJlcG9ydD4ge1xuICAgIGNvbnN0IHJlcXVlc3RzOiBPYnNlcnZhYmxlPENvbGxlY3RlZENvbXBvbmVudD5bXSA9IFtdO1xuICAgIGNvbnN0IHNsb3RzOiB7IHBhZ2VJbmRleDogbnVtYmVyIH1bXSA9IFtdO1xuXG4gICAgcmVwb3J0LnBhZ2VzLmZvckVhY2goKHBhZ2UsIHBhZ2VJbmRleCkgPT4ge1xuICAgICAgZm9yIChjb25zdCBjb21wb25lbnQgb2YgcGFnZS5jb21wb25lbnRzKSB7XG4gICAgICAgIHNsb3RzLnB1c2goeyBwYWdlSW5kZXggfSk7XG4gICAgICAgIHJlcXVlc3RzLnB1c2godGhpcy5fY29tcG9uZW50RGF0YShyZXBvcnQsIGNvbXBvbmVudCkpO1xuICAgICAgfVxuICAgIH0pO1xuXG4gICAgY29uc3QgYWxsJCA9IHJlcXVlc3RzLmxlbmd0aCA/IGZvcmtKb2luKHJlcXVlc3RzKSA6IG9mKFtdIGFzIENvbGxlY3RlZENvbXBvbmVudFtdKTtcblxuICAgIHJldHVybiBhbGwkXG4gICAgICAucGlwZShcbiAgICAgICAgbWFwKChjb2xsZWN0ZWQpID0+IHtcbiAgICAgICAgICBjb25zdCBwYWdlczogQ29sbGVjdGVkUGFnZVtdID0gcmVwb3J0LnBhZ2VzLm1hcCgocGFnZSkgPT4gKHsgcGFnZSwgY29tcG9uZW50czogW10gfSkpO1xuICAgICAgICAgIGNvbGxlY3RlZC5mb3JFYWNoKChpdGVtLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgcGFnZXNbc2xvdHNbaW5kZXhdLnBhZ2VJbmRleF0uY29tcG9uZW50cy5wdXNoKGl0ZW0pO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHJlcG9ydCxcbiAgICAgICAgICAgIHBhZ2VzLFxuICAgICAgICAgICAgZmlsdGVyU3VtbWFyeTogdGhpcy5fZmlsdGVyU3VtbWFyeShyZXBvcnQpLFxuICAgICAgICAgIH07XG4gICAgICAgIH0pLFxuICAgICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgX2NvbXBvbmVudERhdGEocmVwb3J0OiBSZXBvcnQsIGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50KTogT2JzZXJ2YWJsZTxDb2xsZWN0ZWRDb21wb25lbnQ+IHtcbiAgICBjb25zdCBmaWx0ZXJzID0gdGhpcy5fZmlsdGVyU3RhdGUucmVzb2x2ZUZvckNvbXBvbmVudChjb21wb25lbnQpO1xuICAgIC8vIEEgdGltZS1zZXJpZXMgY2hhcnQgY2FycmllcyB0aGUgdmlld2VyJ3MgRnJlcXVlbmN5IG92ZXJyaWRlIHNvIHRoZSBleHBvcnRcbiAgICAvLyByZS1idWNrZXRzIGV4YWN0bHkgYXMgdGhlIHNjcmVlbiBkb2VzOyBsaXN0cyBjYXJyeSB0aGVpciBleHBvcnQgcGFnaW5nLlxuICAgIGNvbnN0IGZyZXF1ZW5jeSA9IHRoaXMuX2ZpbHRlclN0YXRlLmZyZXF1ZW5jeSgpO1xuICAgIGNvbnN0IGlzVGltZVNlcmllcyA9IGNvbXBvbmVudC50eXBlID09PSAnY2hhcnQnICYmIGNvbXBvbmVudC5jb25maWc/LnhBeGlzPy5raW5kID09PSAndGltZSc7XG4gICAgY29uc3Qgc3RhdGUgPSBjb21wb25lbnQudHlwZSA9PT0gJ2xpc3QnXG4gICAgICA/IHsgcGFnZTogMSwgcGFnZVNpemU6IExJU1RfRVhQT1JUX1JPV1MgfVxuICAgICAgOiAoaXNUaW1lU2VyaWVzICYmIGZyZXF1ZW5jeSA/IHsgZnJlcXVlbmN5IH0gOiB7fSk7XG5cbiAgICByZXR1cm4gdGhpcy5fcmVwb3J0RGF0YS5jb21wb25lbnREYXRhKHJlcG9ydC5pZCwgY29tcG9uZW50LmlkLCBmaWx0ZXJzLCBzdGF0ZSlcbiAgICAgIC5waXBlKFxuICAgICAgICBtYXAoKGRhdGE6IENvbXBvbmVudERhdGEpID0+ICh7IGNvbXBvbmVudCwgZGF0YSB9KSksXG4gICAgICAgIGNhdGNoRXJyb3IoKCkgPT4gb2YoeyBjb21wb25lbnQsIGRhdGE6IG51bGwgfSkpLFxuICAgICAgKTtcbiAgfVxuXG4gIC8vIFwiUmVwb3J0IFBlcmlvZDogSnVuIDEyLCAyMDI1IOKAkyBKdW4gMTIsIDIwMjZcIiwgXCJPcmdhbml6YXRpb246IEEsIEJcIiDigJQgb25lXG4gIC8vIGxpbmUgcGVyIGZpbHRlciBncm91cCB0aGF0IGhhcyBhbiBhY3RpdmUgc2Vzc2lvbiB2YWx1ZS5cbiAgcHJpdmF0ZSBfZmlsdGVyU3VtbWFyeShyZXBvcnQ6IFJlcG9ydCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXTtcblxuICAgIGZvciAoY29uc3QgZ3JvdXAgb2YgcmVwb3J0LmZpbHRlckdyb3VwcyA/PyBbXSkge1xuICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLl9maWx0ZXJTdGF0ZS52YWx1ZShncm91cC5pZCk7XG4gICAgICBpZiAoIXZhbHVlKSB7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBsYWJlbCA9IGdyb3VwLmxhYmVsIHx8ICdGaWx0ZXInO1xuXG4gICAgICBpZiAodmFsdWUuc3RhcnQgfHwgdmFsdWUuZW5kKSB7XG4gICAgICAgIGxpbmVzLnB1c2goYCR7bGFiZWx9OiAke3RoaXMuX2RhdGUodmFsdWUuc3RhcnQpfSDigJMgJHt0aGlzLl9kYXRlKHZhbHVlLmVuZCl9YCk7XG4gICAgICB9IGVsc2UgaWYgKHZhbHVlLnZhbHVlcz8ubGVuZ3RoKSB7XG4gICAgICAgIGxpbmVzLnB1c2goYCR7bGFiZWx9OiAke3ZhbHVlLnZhbHVlcy5tYXAoKGl0ZW0pID0+IFN0cmluZyhpdGVtKSkuam9pbignLCAnKX1gKTtcbiAgICAgIH0gZWxzZSBpZiAodmFsdWUudmFsdWU/LnRyaW0oKSkge1xuICAgICAgICBsaW5lcy5wdXNoKGAke2xhYmVsfTogXCIke3ZhbHVlLnZhbHVlLnRyaW0oKX1cImApO1xuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGZyZXF1ZW5jeSA9IHRoaXMuX2ZpbHRlclN0YXRlLmZyZXF1ZW5jeSgpO1xuICAgIGlmIChmcmVxdWVuY3kpIHtcbiAgICAgIGNvbnN0IG9wdGlvbiA9IEZSRVFVRU5DWV9PUFRJT05TLmZpbmQoKGl0ZW0pID0+IGl0ZW0udmFsdWUgPT09IGZyZXF1ZW5jeSk7XG4gICAgICBsaW5lcy5wdXNoKGBGcmVxdWVuY3k6ICR7b3B0aW9uPy5uYW1lID8/IGZyZXF1ZW5jeX1gKTtcbiAgICB9XG5cbiAgICByZXR1cm4gbGluZXM7XG4gIH1cblxuICBwcml2YXRlIF9kYXRlKHZhbHVlOiBEYXRlIHwgc3RyaW5nIHwgbnVsbCB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gICAgaWYgKCF2YWx1ZSkge1xuICAgICAgcmV0dXJuICfigKYnO1xuICAgIH1cblxuICAgIGNvbnN0IGRhdGUgPSB2YWx1ZSBpbnN0YW5jZW9mIERhdGUgPyB2YWx1ZSA6IG5ldyBEYXRlKHZhbHVlKTtcblxuICAgIHJldHVybiBOdW1iZXIuaXNOYU4oZGF0ZS5nZXRUaW1lKCkpID8gU3RyaW5nKHZhbHVlKSA6IGZvcm1hdChkYXRlLCAnTU1NIGQsIHl5eXknKTtcbiAgfVxufVxuIl19
@@ -0,0 +1,155 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { format } from 'date-fns';
3
+ import { formatMeasureValue } from '../format';
4
+ import { pageGeometry } from '../layout';
5
+ import { renderChartImage } from './offscreen-chart';
6
+ import * as i0 from "@angular/core";
7
+ // Inches → points (the PDF unit).
8
+ const PT = 72;
9
+ // Component title strip height, points.
10
+ const TITLE_H = 18;
11
+ // Approximate table row height, points — drives the rows-that-fit cap.
12
+ const TABLE_ROW_H = 16;
13
+ // Builds the PDF client-side with jspdf. The report's unit is inches and PDFs
14
+ // are points at exactly 72/inch, so each report page becomes one PDF page of
15
+ // the exact physical size and components land at their precise positions.
16
+ // Charts are rendered through an offscreen ECharts instance at 3× pixel
17
+ // ratio — pixel-identical to the screen, crisp at print size — and tables are
18
+ // drawn with jspdf-autotable. Both libraries load lazily into their own chunks.
19
+ export class ReportPdfService {
20
+ async export(collected) {
21
+ const { jsPDF } = await import('jspdf');
22
+ const autoTable = (await import('jspdf-autotable')).default;
23
+ const report = collected.report;
24
+ const pageW = report.pageWidth * PT;
25
+ const pageH = report.pageHeight * PT;
26
+ const doc = new jsPDF({
27
+ orientation: pageW >= pageH ? 'landscape' : 'portrait',
28
+ unit: 'pt',
29
+ format: [pageW, pageH],
30
+ });
31
+ this._titlePage(doc, collected, pageW, pageH);
32
+ for (const collectedPage of collected.pages) {
33
+ doc.addPage([pageW, pageH], pageW >= pageH ? 'landscape' : 'portrait');
34
+ const geometry = pageGeometry(report, collectedPage.page);
35
+ for (const item of collectedPage.components) {
36
+ await this._renderComponent(doc, autoTable, item, geometry.get(item.component.id));
37
+ }
38
+ }
39
+ doc.save(`${this._slug(report.name)}.pdf`);
40
+ }
41
+ _titlePage(doc, collected, pageW, pageH) {
42
+ doc.setFont('helvetica', 'bold');
43
+ doc.setFontSize(28);
44
+ doc.setTextColor('#1f2933');
45
+ doc.text(collected.report.name, 40, pageH * 0.35);
46
+ doc.setFont('helvetica', 'normal');
47
+ doc.setFontSize(11);
48
+ doc.setTextColor('#52606d');
49
+ const lines = [
50
+ format(new Date(), 'MMMM d, yyyy'),
51
+ ...collected.filterSummary,
52
+ ];
53
+ doc.text(lines, 40, pageH * 0.35 + 26);
54
+ }
55
+ async _renderComponent(doc, autoTable, item, geometry) {
56
+ const component = item.component;
57
+ // Geometry arrives in inches (flow layout pre-resolved); the PDF draws in
58
+ // points.
59
+ const inches = geometry ?? component;
60
+ const x = inches.x * PT;
61
+ const y = inches.y * PT;
62
+ const w = inches.w * PT;
63
+ const h = inches.h * PT;
64
+ if (component.title) {
65
+ doc.setFont('helvetica', 'bold');
66
+ doc.setFontSize(9);
67
+ doc.setTextColor('#1f2933');
68
+ doc.text(component.title, x, y + 10, { maxWidth: w });
69
+ }
70
+ const bodyY = y + TITLE_H;
71
+ const bodyH = Math.max(20, h - TITLE_H);
72
+ if (!item.data || !item.data.rows?.length) {
73
+ doc.setFont('helvetica', 'italic');
74
+ doc.setFontSize(9);
75
+ doc.setTextColor('#7b8794');
76
+ doc.text(item.data ? 'No data' : 'Data unavailable', x + w / 2, bodyY + bodyH / 2, { align: 'center' });
77
+ return;
78
+ }
79
+ switch (component.type) {
80
+ case 'chart': {
81
+ const image = await renderChartImage(component, item.data, w, bodyH);
82
+ doc.addImage(image, 'PNG', x, bodyY, w, bodyH);
83
+ break;
84
+ }
85
+ case 'list':
86
+ this._renderTable(doc, autoTable, component, item.data, x, bodyY, w, bodyH);
87
+ break;
88
+ case 'kpi':
89
+ this._renderKpi(doc, component, item.data, x, bodyY, w, bodyH);
90
+ break;
91
+ }
92
+ }
93
+ _renderTable(doc, autoTable, component, data, x, y, w, h) {
94
+ const config = component.config;
95
+ const columns = config.columns?.length
96
+ ? config.columns
97
+ : data.columns.map((column) => ({ column, label: column }));
98
+ const cap = Math.max(2, Math.floor(h / TABLE_ROW_H) - 1);
99
+ const rows = data.rows.slice(0, cap);
100
+ const remaining = (data.paging?.total ?? data.rows.length) - rows.length;
101
+ const body = rows.map((row) => columns.map((column) => this._cell(row[column.column], column.format)));
102
+ if (remaining > 0) {
103
+ body.push([`… ${remaining} more row(s) — use the component's CSV export for the full dataset`]);
104
+ }
105
+ autoTable(doc, {
106
+ head: [columns.map((column) => column.label || column.column)],
107
+ body,
108
+ startY: y,
109
+ margin: { left: x },
110
+ tableWidth: w,
111
+ styles: { fontSize: 8, cellPadding: 3, textColor: '#1f2933' },
112
+ headStyles: { fillColor: '#4e79a7', textColor: '#ffffff', fontStyle: 'bold' },
113
+ alternateRowStyles: { fillColor: '#f5f7fa' },
114
+ theme: 'grid',
115
+ });
116
+ }
117
+ _renderKpi(doc, component, data, x, y, w, h) {
118
+ const config = component.config;
119
+ const row = data.rows[0] ?? {};
120
+ const column = config.measure?.column ?? Object.keys(row)[0];
121
+ const value = formatMeasureValue(row[column], config.measure?.format);
122
+ doc.setFont('helvetica', 'bold');
123
+ doc.setFontSize(26);
124
+ doc.setTextColor('#1f2933');
125
+ doc.text(value, x + w / 2, y + h / 2, { align: 'center' });
126
+ if (config.measure?.label) {
127
+ doc.setFont('helvetica', 'normal');
128
+ doc.setFontSize(9);
129
+ doc.setTextColor('#7b8794');
130
+ doc.text(config.measure.label, x + w / 2, y + h / 2 + 16, { align: 'center' });
131
+ }
132
+ }
133
+ _cell(value, columnFormat) {
134
+ if (value === null || value === undefined) {
135
+ return '';
136
+ }
137
+ if (columnFormat === 'date') {
138
+ const date = new Date(String(value));
139
+ return Number.isNaN(date.getTime()) ? String(value) : format(date, 'MMM d, yyyy');
140
+ }
141
+ if (columnFormat === 'number') {
142
+ return formatMeasureValue(value, 'number');
143
+ }
144
+ return String(value);
145
+ }
146
+ _slug(name) {
147
+ return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '') || 'report';
148
+ }
149
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportPdfService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
150
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportPdfService });
151
+ }
152
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportPdfService, decorators: [{
153
+ type: Injectable
154
+ }] });
155
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0LXBkZi5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2V4cG9ydC9yZXBvcnQtcGRmLnNlcnZpY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUUzQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sVUFBVSxDQUFDO0FBRWxDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLFdBQVcsQ0FBQztBQU8vQyxPQUFPLEVBQXFCLFlBQVksRUFBRSxNQUFNLFdBQVcsQ0FBQztBQUM1RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQzs7QUFJckQsa0NBQWtDO0FBQ2xDLE1BQU0sRUFBRSxHQUFHLEVBQUUsQ0FBQztBQUVkLHdDQUF3QztBQUN4QyxNQUFNLE9BQU8sR0FBRyxFQUFFLENBQUM7QUFDbkIsdUVBQXVFO0FBQ3ZFLE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQztBQUV2Qiw4RUFBOEU7QUFDOUUsNkVBQTZFO0FBQzdFLDBFQUEwRTtBQUMxRSx3RUFBd0U7QUFDeEUsOEVBQThFO0FBQzlFLGdGQUFnRjtBQUVoRixNQUFNLE9BQU8sZ0JBQWdCO0lBRXBCLEtBQUssQ0FBQyxNQUFNLENBQUMsU0FBMEI7UUFDNUMsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3hDLE1BQU0sU0FBUyxHQUFHLENBQUMsTUFBTSxNQUFNLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQztRQUU1RCxNQUFNLE1BQU0sR0FBRyxTQUFTLENBQUMsTUFBTSxDQUFDO1FBQ2hDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDO1FBQ3BDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxVQUFVLEdBQUcs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Qjs7NEZBQWhCLGdCQUFnQjtrQkFENUIsVUFBVSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IEluamVjdGFibGUgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgZm9ybWF0IH0gZnJvbSAnZGF0ZS1mbnMnO1xuXG5pbXBvcnQgeyBmb3JtYXRNZWFzdXJlVmFsdWUgfSBmcm9tICcuLi9mb3JtYXQnO1xuaW1wb3J0IHtcbiAgQ29tcG9uZW50RGF0YSxcbiAgS3BpQ29uZmlnLFxuICBMaXN0Q29uZmlnLFxuICBSZXBvcnRDb21wb25lbnQsXG59IGZyb20gJy4uL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7IC8vIENvbXBvbmVudERhdGEgdXNlZCBpbiBtZXRob2Qgc2lnbmF0dXJlcyBiZWxvd1xuaW1wb3J0IHsgQ29tcG9uZW50R2VvbWV0cnksIHBhZ2VHZW9tZXRyeSB9IGZyb20gJy4uL2xheW91dCc7XG5pbXBvcnQgeyByZW5kZXJDaGFydEltYWdlIH0gZnJvbSAnLi9vZmZzY3JlZW4tY2hhcnQnO1xuaW1wb3J0IHsgQ29sbGVjdGVkQ29tcG9uZW50LCBDb2xsZWN0ZWRSZXBvcnQgfSBmcm9tICcuL3JlcG9ydC1leHBvcnQtY29sbGVjdG9yLnNlcnZpY2UnO1xuXG5cbi8vIEluY2hlcyDihpIgcG9pbnRzICh0aGUgUERGIHVuaXQpLlxuY29uc3QgUFQgPSA3MjtcblxuLy8gQ29tcG9uZW50IHRpdGxlIHN0cmlwIGhlaWdodCwgcG9pbnRzLlxuY29uc3QgVElUTEVfSCA9IDE4O1xuLy8gQXBwcm94aW1hdGUgdGFibGUgcm93IGhlaWdodCwgcG9pbnRzIOKAlCBkcml2ZXMgdGhlIHJvd3MtdGhhdC1maXQgY2FwLlxuY29uc3QgVEFCTEVfUk9XX0ggPSAxNjtcblxuLy8gQnVpbGRzIHRoZSBQREYgY2xpZW50LXNpZGUgd2l0aCBqc3BkZi4gVGhlIHJlcG9ydCdzIHVuaXQgaXMgaW5jaGVzIGFuZCBQREZzXG4vLyBhcmUgcG9pbnRzIGF0IGV4YWN0bHkgNzIvaW5jaCwgc28gZWFjaCByZXBvcnQgcGFnZSBiZWNvbWVzIG9uZSBQREYgcGFnZSBvZlxuLy8gdGhlIGV4YWN0IHBoeXNpY2FsIHNpemUgYW5kIGNvbXBvbmVudHMgbGFuZCBhdCB0aGVpciBwcmVjaXNlIHBvc2l0aW9ucy5cbi8vIENoYXJ0cyBhcmUgcmVuZGVyZWQgdGhyb3VnaCBhbiBvZmZzY3JlZW4gRUNoYXJ0cyBpbnN0YW5jZSBhdCAzw5cgcGl4ZWxcbi8vIHJhdGlvIOKAlCBwaXhlbC1pZGVudGljYWwgdG8gdGhlIHNjcmVlbiwgY3Jpc3AgYXQgcHJpbnQgc2l6ZSDigJQgYW5kIHRhYmxlcyBhcmVcbi8vIGRyYXduIHdpdGgganNwZGYtYXV0b3RhYmxlLiBCb3RoIGxpYnJhcmllcyBsb2FkIGxhemlseSBpbnRvIHRoZWlyIG93biBjaHVua3MuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgUmVwb3J0UGRmU2VydmljZSB7XG5cbiAgcHVibGljIGFzeW5jIGV4cG9ydChjb2xsZWN0ZWQ6IENvbGxlY3RlZFJlcG9ydCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IHsganNQREYgfSA9IGF3YWl0IGltcG9ydCgnanNwZGYnKTtcbiAgICBjb25zdCBhdXRvVGFibGUgPSAoYXdhaXQgaW1wb3J0KCdqc3BkZi1hdXRvdGFibGUnKSkuZGVmYXVsdDtcblxuICAgIGNvbnN0IHJlcG9ydCA9IGNvbGxlY3RlZC5yZXBvcnQ7XG4gICAgY29uc3QgcGFnZVcgPSByZXBvcnQucGFnZVdpZHRoICogUFQ7XG4gICAgY29uc3QgcGFnZUggPSByZXBvcnQucGFnZUhlaWdodCAqIFBUO1xuXG4gICAgY29uc3QgZG9jID0gbmV3IGpzUERGKHtcbiAgICAgIG9yaWVudGF0aW9uOiBwYWdlVyA+PSBwYWdlSCA/ICdsYW5kc2NhcGUnIDogJ3BvcnRyYWl0JyxcbiAgICAgIHVuaXQ6ICdwdCcsXG4gICAgICBmb3JtYXQ6IFtwYWdlVywgcGFnZUhdLFxuICAgIH0pO1xuXG4gICAgdGhpcy5fdGl0bGVQYWdlKGRvYywgY29sbGVjdGVkLCBwYWdlVywgcGFnZUgpO1xuXG4gICAgZm9yIChjb25zdCBjb2xsZWN0ZWRQYWdlIG9mIGNvbGxlY3RlZC5wYWdlcykge1xuICAgICAgZG9jLmFkZFBhZ2UoW3BhZ2VXLCBwYWdlSF0sIHBhZ2VXID49IHBhZ2VIID8gJ2xhbmRzY2FwZScgOiAncG9ydHJhaXQnKTtcbiAgICAgIGNvbnN0IGdlb21ldHJ5ID0gcGFnZUdlb21ldHJ5KHJlcG9ydCwgY29sbGVjdGVkUGFnZS5wYWdlKTtcblxuICAgICAgZm9yIChjb25zdCBpdGVtIG9mIGNvbGxlY3RlZFBhZ2UuY29tcG9uZW50cykge1xuICAgICAgICBhd2FpdCB0aGlzLl9yZW5kZXJDb21wb25lbnQoZG9jLCBhdXRvVGFibGUsIGl0ZW0sIGdlb21ldHJ5LmdldChpdGVtLmNvbXBvbmVudC5pZCkpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGRvYy5zYXZlKGAke3RoaXMuX3NsdWcocmVwb3J0Lm5hbWUpfS5wZGZgKTtcbiAgfVxuXG4gIHByaXZhdGUgX3RpdGxlUGFnZShkb2M6IGFueSwgY29sbGVjdGVkOiBDb2xsZWN0ZWRSZXBvcnQsIHBhZ2VXOiBudW1iZXIsIHBhZ2VIOiBudW1iZXIpOiB2b2lkIHtcbiAgICBkb2Muc2V0Rm9udCgnaGVsdmV0aWNhJywgJ2JvbGQnKTtcbiAgICBkb2Muc2V0Rm9udFNpemUoMjgpO1xuICAgIGRvYy5zZXRUZXh0Q29sb3IoJyMxZjI5MzMnKTtcbiAgICBkb2MudGV4dChjb2xsZWN0ZWQucmVwb3J0Lm5hbWUsIDQwLCBwYWdlSCAqIDAuMzUpO1xuXG4gICAgZG9jLnNldEZvbnQoJ2hlbHZldGljYScsICdub3JtYWwnKTtcbiAgICBkb2Muc2V0Rm9udFNpemUoMTEpO1xuICAgIGRvYy5zZXRUZXh0Q29sb3IoJyM1MjYwNmQnKTtcblxuICAgIGNvbnN0IGxpbmVzID0gW1xuICAgICAgZm9ybWF0KG5ldyBEYXRlKCksICdNTU1NIGQsIHl5eXknKSxcbiAgICAgIC4uLmNvbGxlY3RlZC5maWx0ZXJTdW1tYXJ5LFxuICAgIF07XG4gICAgZG9jLnRleHQobGluZXMsIDQwLCBwYWdlSCAqIDAuMzUgKyAyNik7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIF9yZW5kZXJDb21wb25lbnQoZG9jOiBhbnksIGF1dG9UYWJsZTogYW55LCBpdGVtOiBDb2xsZWN0ZWRDb21wb25lbnQsIGdlb21ldHJ5PzogQ29tcG9uZW50R2VvbWV0cnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBjb21wb25lbnQgPSBpdGVtLmNvbXBvbmVudDtcbiAgICAvLyBHZW9tZXRyeSBhcnJpdmVzIGluIGluY2hlcyAoZmxvdyBsYXlvdXQgcHJlLXJlc29sdmVkKTsgdGhlIFBERiBkcmF3cyBpblxuICAgIC8vIHBvaW50cy5cbiAgICBjb25zdCBpbmNoZXMgPSBnZW9tZXRyeSA/PyBjb21wb25lbnQ7XG4gICAgY29uc3QgeCA9IGluY2hlcy54ICogUFQ7XG4gICAgY29uc3QgeSA9IGluY2hlcy55ICogUFQ7XG4gICAgY29uc3QgdyA9IGluY2hlcy53ICogUFQ7XG4gICAgY29uc3QgaCA9IGluY2hlcy5oICogUFQ7XG5cbiAgICBpZiAoY29tcG9uZW50LnRpdGxlKSB7XG4gICAgICBkb2Muc2V0Rm9udCgnaGVsdmV0aWNhJywgJ2JvbGQnKTtcbiAgICAgIGRvYy5zZXRGb250U2l6ZSg5KTtcbiAgICAgIGRvYy5zZXRUZXh0Q29sb3IoJyMxZjI5MzMnKTtcbiAgICAgIGRvYy50ZXh0KGNvbXBvbmVudC50aXRsZSwgeCwgeSArIDEwLCB7IG1heFdpZHRoOiB3IH0pO1xuICAgIH1cblxuICAgIGNvbnN0IGJvZHlZID0geSArIFRJVExFX0g7XG4gICAgY29uc3QgYm9keUggPSBNYXRoLm1heCgyMCwgaCAtIFRJVExFX0gpO1xuXG4gICAgaWYgKCFpdGVtLmRhdGEgfHwgIWl0ZW0uZGF0YS5yb3dzPy5sZW5ndGgpIHtcbiAgICAgIGRvYy5zZXRGb250KCdoZWx2ZXRpY2EnLCAnaXRhbGljJyk7XG4gICAgICBkb2Muc2V0Rm9udFNpemUoOSk7XG4gICAgICBkb2Muc2V0VGV4dENvbG9yKCcjN2I4Nzk0Jyk7XG4gICAgICBkb2MudGV4dChpdGVtLmRhdGEgPyAnTm8gZGF0YScgOiAnRGF0YSB1bmF2YWlsYWJsZScsIHggKyB3IC8gMiwgYm9keVkgKyBib2R5SCAvIDIsIHsgYWxpZ246ICdjZW50ZXInIH0pO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgc3dpdGNoIChjb21wb25lbnQudHlwZSkge1xuICAgICAgY2FzZSAnY2hhcnQnOiB7XG4gICAgICAgIGNvbnN0IGltYWdlID0gYXdhaXQgcmVuZGVyQ2hhcnRJbWFnZShjb21wb25lbnQsIGl0ZW0uZGF0YSwgdywgYm9keUgpO1xuICAgICAgICBkb2MuYWRkSW1hZ2UoaW1hZ2UsICdQTkcnLCB4LCBib2R5WSwgdywgYm9keUgpO1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ2xpc3QnOlxuICAgICAgICB0aGlzLl9yZW5kZXJUYWJsZShkb2MsIGF1dG9UYWJsZSwgY29tcG9uZW50LCBpdGVtLmRhdGEsIHgsIGJvZHlZLCB3LCBib2R5SCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAna3BpJzpcbiAgICAgICAgdGhpcy5fcmVuZGVyS3BpKGRvYywgY29tcG9uZW50LCBpdGVtLmRhdGEsIHgsIGJvZHlZLCB3LCBib2R5SCk7XG4gICAgICAgIGJyZWFrO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgX3JlbmRlclRhYmxlKFxuICAgIGRvYzogYW55LFxuICAgIGF1dG9UYWJsZTogYW55LFxuICAgIGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50LFxuICAgIGRhdGE6IENvbXBvbmVudERhdGEsXG4gICAgeDogbnVtYmVyLCB5OiBudW1iZXIsIHc6IG51bWJlciwgaDogbnVtYmVyLFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBjb25maWcgPSBjb21wb25lbnQuY29uZmlnIGFzIExpc3RDb25maWc7XG4gICAgY29uc3QgY29sdW1ucyA9IGNvbmZpZy5jb2x1bW5zPy5sZW5ndGhcbiAgICAgID8gY29uZmlnLmNvbHVtbnNcbiAgICAgIDogZGF0YS5jb2x1bW5zLm1hcCgoY29sdW1uKSA9PiAoeyBjb2x1bW4sIGxhYmVsOiBjb2x1bW4gfSkpO1xuXG4gICAgY29uc3QgY2FwID0gTWF0aC5tYXgoMiwgTWF0aC5mbG9vcihoIC8gVEFCTEVfUk9XX0gpIC0gMSk7XG4gICAgY29uc3Qgcm93cyA9IGRhdGEucm93cy5zbGljZSgwLCBjYXApO1xuICAgIGNvbnN0IHJlbWFpbmluZyA9IChkYXRhLnBhZ2luZz8udG90YWwgPz8gZGF0YS5yb3dzLmxlbmd0aCkgLSByb3dzLmxlbmd0aDtcblxuICAgIGNvbnN0IGJvZHkgPSByb3dzLm1hcCgocm93KSA9PiBjb2x1bW5zLm1hcCgoY29sdW1uKSA9PiB0aGlzLl9jZWxsKHJvd1tjb2x1bW4uY29sdW1uXSwgY29sdW1uLmZvcm1hdCkpKTtcblxuICAgIGlmIChyZW1haW5pbmcgPiAwKSB7XG4gICAgICBib2R5LnB1c2goW2DigKYgJHtyZW1haW5pbmd9IG1vcmUgcm93KHMpIOKAlCB1c2UgdGhlIGNvbXBvbmVudCdzIENTViBleHBvcnQgZm9yIHRoZSBmdWxsIGRhdGFzZXRgXSk7XG4gICAgfVxuXG4gICAgYXV0b1RhYmxlKGRvYywge1xuICAgICAgaGVhZDogW2NvbHVtbnMubWFwKChjb2x1bW4pID0+IGNvbHVtbi5sYWJlbCB8fCBjb2x1bW4uY29sdW1uKV0sXG4gICAgICBib2R5LFxuICAgICAgc3RhcnRZOiB5LFxuICAgICAgbWFyZ2luOiB7IGxlZnQ6IHggfSxcbiAgICAgIHRhYmxlV2lkdGg6IHcsXG4gICAgICBzdHlsZXM6IHsgZm9udFNpemU6IDgsIGNlbGxQYWRkaW5nOiAzLCB0ZXh0Q29sb3I6ICcjMWYyOTMzJyB9LFxuICAgICAgaGVhZFN0eWxlczogeyBmaWxsQ29sb3I6ICcjNGU3OWE3JywgdGV4dENvbG9yOiAnI2ZmZmZmZicsIGZvbnRTdHlsZTogJ2JvbGQnIH0sXG4gICAgICBhbHRlcm5hdGVSb3dTdHlsZXM6IHsgZmlsbENvbG9yOiAnI2Y1ZjdmYScgfSxcbiAgICAgIHRoZW1lOiAnZ3JpZCcsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9yZW5kZXJLcGkoXG4gICAgZG9jOiBhbnksXG4gICAgY29tcG9uZW50OiBSZXBvcnRDb21wb25lbnQsXG4gICAgZGF0YTogQ29tcG9uZW50RGF0YSxcbiAgICB4OiBudW1iZXIsIHk6IG51bWJlciwgdzogbnVtYmVyLCBoOiBudW1iZXIsXG4gICk6IHZvaWQge1xuICAgIGNvbnN0IGNvbmZpZyA9IGNvbXBvbmVudC5jb25maWcgYXMgS3BpQ29uZmlnO1xuICAgIGNvbnN0IHJvdyA9IGRhdGEucm93c1swXSA/PyB7fTtcbiAgICBjb25zdCBjb2x1bW4gPSBjb25maWcubWVhc3VyZT8uY29sdW1uID8/IE9iamVjdC5rZXlzKHJvdylbMF07XG4gICAgY29uc3QgdmFsdWUgPSBmb3JtYXRNZWFzdXJlVmFsdWUocm93W2NvbHVtbl0sIGNvbmZpZy5tZWFzdXJlPy5mb3JtYXQpO1xuXG4gICAgZG9jLnNldEZvbnQoJ2hlbHZldGljYScsICdib2xkJyk7XG4gICAgZG9jLnNldEZvbnRTaXplKDI2KTtcbiAgICBkb2Muc2V0VGV4dENvbG9yKCcjMWYyOTMzJyk7XG4gICAgZG9jLnRleHQodmFsdWUsIHggKyB3IC8gMiwgeSArIGggLyAyLCB7IGFsaWduOiAnY2VudGVyJyB9KTtcblxuICAgIGlmIChjb25maWcubWVhc3VyZT8ubGFiZWwpIHtcbiAgICAgIGRvYy5zZXRGb250KCdoZWx2ZXRpY2EnLCAnbm9ybWFsJyk7XG4gICAgICBkb2Muc2V0Rm9udFNpemUoOSk7XG4gICAgICBkb2Muc2V0VGV4dENvbG9yKCcjN2I4Nzk0Jyk7XG4gICAgICBkb2MudGV4dChjb25maWcubWVhc3VyZS5sYWJlbCwgeCArIHcgLyAyLCB5ICsgaCAvIDIgKyAxNiwgeyBhbGlnbjogJ2NlbnRlcicgfSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfY2VsbCh2YWx1ZTogdW5rbm93biwgY29sdW1uRm9ybWF0Pzogc3RyaW5nKTogc3RyaW5nIHtcbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cblxuICAgIGlmIChjb2x1bW5Gb3JtYXQgPT09ICdkYXRlJykge1xuICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKFN0cmluZyh2YWx1ZSkpO1xuXG4gICAgICByZXR1cm4gTnVtYmVyLmlzTmFOKGRhdGUuZ2V0VGltZSgpKSA/IFN0cmluZyh2YWx1ZSkgOiBmb3JtYXQoZGF0ZSwgJ01NTSBkLCB5eXl5Jyk7XG4gICAgfVxuXG4gICAgaWYgKGNvbHVtbkZvcm1hdCA9PT0gJ251bWJlcicpIHtcbiAgICAgIHJldHVybiBmb3JtYXRNZWFzdXJlVmFsdWUodmFsdWUsICdudW1iZXInKTtcbiAgICB9XG5cbiAgICByZXR1cm4gU3RyaW5nKHZhbHVlKTtcbiAgfVxuXG4gIHByaXZhdGUgX3NsdWcobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgICByZXR1cm4gbmFtZS50b0xvd2VyQ2FzZSgpLnJlcGxhY2UoL1teYS16MC05XSsvZywgJy0nKS5yZXBsYWNlKC9eLSt8LSskL2csICcnKSB8fCAncmVwb3J0JztcbiAgfVxufVxuIl19