@firestitch/report 18.0.17 → 18.0.18

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.
@@ -8,6 +8,7 @@ import { FsPrompt } from '@firestitch/prompt';
8
8
  import { map, switchMap } from 'rxjs/operators';
9
9
  import { ReportData } from '../../data/report.data';
10
10
  import { GlobalSettingsComponent } from '../../dialogs/global-settings/global-settings.component';
11
+ import { ReportState } from '../../interfaces/report.interface';
11
12
  import * as i0 from "@angular/core";
12
13
  import * as i1 from "@firestitch/date";
13
14
  import * as i2 from "@firestitch/list";
@@ -17,6 +18,11 @@ import * as i2 from "@firestitch/list";
17
18
  // title, creates the report, then routes to it. The header gear opens the
18
19
  // global Report Settings dialog (AI knowledge document + semantic-database
19
20
  // build), which lives in this package. No routing is hard-coded here.
21
+ //
22
+ // Reports are soft-deletable: the row kebab deletes, "Show Deleted" flips the
23
+ // list into deleted mode (the backend hides deleted reports otherwise), and in
24
+ // that mode fs-list swaps Delete for Restore, which calls the undelete action
25
+ // endpoint.
20
26
  export class FsAiReportsComponent {
21
27
  // API base for the reports endpoints; override to mount elsewhere.
22
28
  basePath = input('reports');
@@ -27,6 +33,9 @@ export class FsAiReportsComponent {
27
33
  createPattern = input(':id');
28
34
  list = null;
29
35
  listConfig;
36
+ // Template-side handle on the enum, so the name cell can tell a deleted row
37
+ // (shown in Show Deleted mode) from a live one.
38
+ deletedState = ReportState.Deleted;
30
39
  _reportData = inject(ReportData);
31
40
  _router = inject(Router);
32
41
  _route = inject(ActivatedRoute);
@@ -101,6 +110,28 @@ export class FsAiReportsComponent {
101
110
  click: () => this.createReport(),
102
111
  },
103
112
  ],
113
+ rowActions: [
114
+ {
115
+ click: (report) => this._reportData.delete(report.id),
116
+ remove: {
117
+ title: 'Confirm',
118
+ template: 'Are you sure you would like to delete this report?',
119
+ },
120
+ menu: true,
121
+ label: 'Delete',
122
+ },
123
+ ],
124
+ // `filter: true` makes fs-list render the Show Deleted toggle and send
125
+ // `query` with the fetch; in that mode it also swaps the row's Delete
126
+ // action for Restore.
127
+ restore: {
128
+ query: { state: ReportState.Deleted },
129
+ filter: true,
130
+ filterLabel: 'Show Deleted',
131
+ menuLabel: 'Restore',
132
+ reload: true,
133
+ click: (report) => this._reportData.undelete(report.id),
134
+ },
104
135
  fetch: (query) => {
105
136
  return this._reportData.reports(query)
106
137
  .pipe(map((reports) => ({ data: reports ?? [] })));
@@ -108,7 +139,7 @@ export class FsAiReportsComponent {
108
139
  };
109
140
  }
110
141
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FsAiReportsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
111
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.14", type: FsAiReportsComponent, isStandalone: true, selector: "fs-ai-reports", inputs: { basePath: { classPropertyName: "basePath", publicName: "basePath", isSignal: true, isRequired: false, transformFunction: null }, openPattern: { classPropertyName: "openPattern", publicName: "openPattern", isSignal: true, isRequired: false, transformFunction: null }, createPattern: { classPropertyName: "createPattern", publicName: "createPattern", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list\n [config]=\"listConfig\"\n #list>\n\n <fs-list-column title=\"Name\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <a [routerLink]=\"openLink(row)\">{{ row.name }}</a>\n </ng-template>\n </fs-list-column>\n\n <fs-list-column title=\"Modified\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date [date]=\"row.modifyDate\"></fs-date>\n </ng-template>\n </fs-list-column>\n\n</fs-list>\n", styles: ["a{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: FsDateModule }, { kind: "component", type: i1.FsDateComponent, selector: "fs-date", inputs: ["date", "format", "timezone"] }, { kind: "ngmodule", type: FsListModule }, { kind: "component", type: i2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines", "cellRowType"], outputs: ["filtersReady"] }, { kind: "directive", type: i2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customizable", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i2.FsListCellDirective, selector: "[fs-list-cell],[fsListCell]", inputs: ["colspan", "align", "class", "fsListCell", "configTyping"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
142
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: FsAiReportsComponent, isStandalone: true, selector: "fs-ai-reports", inputs: { basePath: { classPropertyName: "basePath", publicName: "basePath", isSignal: true, isRequired: false, transformFunction: null }, openPattern: { classPropertyName: "openPattern", publicName: "openPattern", isSignal: true, isRequired: false, transformFunction: null }, createPattern: { classPropertyName: "createPattern", publicName: "createPattern", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list\n [config]=\"listConfig\"\n #list>\n\n <fs-list-column title=\"Name\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <!-- A deleted report can't be opened (the backend only assembles active\n ones), so in Show Deleted mode the name is plain text \u2014 restore it\n from the row menu first. -->\n @if (row.state === deletedState) {\n {{ row.name }}\n } @else {\n <a [routerLink]=\"openLink(row)\">{{ row.name }}</a>\n }\n </ng-template>\n </fs-list-column>\n\n <fs-list-column title=\"Modified\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date [date]=\"row.modifyDate\"></fs-date>\n </ng-template>\n </fs-list-column>\n\n</fs-list>\n", styles: ["a{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: FsDateModule }, { kind: "component", type: i1.FsDateComponent, selector: "fs-date", inputs: ["date", "format", "timezone"] }, { kind: "ngmodule", type: FsListModule }, { kind: "component", type: i2.FsListComponent, selector: "fs-list", inputs: ["config", "loaderLines", "cellRowType"], outputs: ["filtersReady"] }, { kind: "directive", type: i2.FsListColumnDirective, selector: "fs-list-column", inputs: ["show", "title", "name", "customizable", "sortable", "sortableDefault", "sortableDirection", "direction", "align", "width", "class"] }, { kind: "directive", type: i2.FsListCellDirective, selector: "[fs-list-cell],[fsListCell]", inputs: ["colspan", "align", "class", "fsListCell", "configTyping"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
112
143
  }
113
144
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FsAiReportsComponent, decorators: [{
114
145
  type: Component,
@@ -116,9 +147,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
116
147
  FsDateModule,
117
148
  FsListModule,
118
149
  RouterLink,
119
- ], template: "<fs-list\n [config]=\"listConfig\"\n #list>\n\n <fs-list-column title=\"Name\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <a [routerLink]=\"openLink(row)\">{{ row.name }}</a>\n </ng-template>\n </fs-list-column>\n\n <fs-list-column title=\"Modified\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date [date]=\"row.modifyDate\"></fs-date>\n </ng-template>\n </fs-list-column>\n\n</fs-list>\n", styles: ["a{cursor:pointer}\n"] }]
150
+ ], template: "<fs-list\n [config]=\"listConfig\"\n #list>\n\n <fs-list-column title=\"Name\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <!-- A deleted report can't be opened (the backend only assembles active\n ones), so in Show Deleted mode the name is plain text \u2014 restore it\n from the row menu first. -->\n @if (row.state === deletedState) {\n {{ row.name }}\n } @else {\n <a [routerLink]=\"openLink(row)\">{{ row.name }}</a>\n }\n </ng-template>\n </fs-list-column>\n\n <fs-list-column title=\"Modified\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date [date]=\"row.modifyDate\"></fs-date>\n </ng-template>\n </fs-list-column>\n\n</fs-list>\n", styles: ["a{cursor:pointer}\n"] }]
120
151
  }], ctorParameters: () => [], propDecorators: { list: [{
121
152
  type: ViewChild,
122
153
  args: [FsListComponent]
123
154
  }] } });
124
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnMtYWktcmVwb3J0cy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL3JlcG9ydHMvdmlld3MvcmVwb3J0cy9mcy1haS1yZXBvcnRzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy92aWV3cy9yZXBvcnRzL2ZzLWFpLXJlcG9ydHMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pILE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXJFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUVyRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLGVBQWUsRUFBZ0IsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDL0UsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRTlDLE9BQU8sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFaEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3BELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHlEQUF5RCxDQUFDOzs7O0FBSWxHLCtFQUErRTtBQUMvRSwyRUFBMkU7QUFDM0UsMkVBQTJFO0FBQzNFLDBFQUEwRTtBQUMxRSwyRUFBMkU7QUFDM0Usc0VBQXNFO0FBYXRFLE1BQU0sT0FBTyxvQkFBb0I7SUFFL0Is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QkFBb0I7NEZBQXBCLG9CQUFvQixzaEJBWXBCLGVBQWUsZ0RDL0M1Qix3ZEFxQkEsNEVEU0ksWUFBWSw0SUFDWixZQUFZLHVqQkFDWixVQUFVOzs0RkFHRCxvQkFBb0I7a0JBWmhDLFNBQVM7K0JBQ0UsZUFBZSxtQkFHUix1QkFBdUIsQ0FBQyxNQUFNLGNBQ25DLElBQUksV0FDUDt3QkFDUCxZQUFZO3dCQUNaLFlBQVk7d0JBQ1osVUFBVTtxQkFDWDt3REFlTSxJQUFJO3NCQURWLFNBQVM7dUJBQUMsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIERlc3Ryb3lSZWYsIFZpZXdDaGlsZCwgZWZmZWN0LCBpbmplY3QsIGlucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyLCBSb3V0ZXJMaW5rIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcblxuaW1wb3J0IHsgTWF0RGlhbG9nIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcblxuaW1wb3J0IHsgRnNEYXRlTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZGF0ZSc7XG5pbXBvcnQgeyBGc0xpc3RDb21wb25lbnQsIEZzTGlzdENvbmZpZywgRnNMaXN0TW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbGlzdCc7XG5pbXBvcnQgeyBGc1Byb21wdCB9IGZyb20gJ0BmaXJlc3RpdGNoL3Byb21wdCc7XG5cbmltcG9ydCB7IG1hcCwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBSZXBvcnREYXRhIH0gZnJvbSAnLi4vLi4vZGF0YS9yZXBvcnQuZGF0YSc7XG5pbXBvcnQgeyBHbG9iYWxTZXR0aW5nc0NvbXBvbmVudCB9IGZyb20gJy4uLy4uL2RpYWxvZ3MvZ2xvYmFsLXNldHRpbmdzL2dsb2JhbC1zZXR0aW5ncy5jb21wb25lbnQnO1xuaW1wb3J0IHsgUmVwb3J0TGlzdEl0ZW0gfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL3JlcG9ydC5pbnRlcmZhY2UnO1xuXG5cbi8vIFRoZSByZXBvcnRzIGxpc3Rpbmcg4oCUIGFuIGZzLWxpc3Qgb2YgcmVwb3J0cy4gUm93cyBhcmUgbGlua3MgYnVpbHQgZnJvbSBhIFVSTFxuLy8gcGF0dGVybiAoYSAnOmlkJyB0b2tlbiDihpIgdGhlIHJlcG9ydCBpZDsgYSBsZWFkaW5nICcvJyBtYWtlcyBpdCBhYnNvbHV0ZSxcbi8vIG90aGVyd2lzZSBpdCdzIHJlbGF0aXZlIHRvIHRoaXMgY29tcG9uZW50J3Mgcm91dGUpLiBDcmVhdGUgcHJvbXB0cyBmb3IgYVxuLy8gdGl0bGUsIGNyZWF0ZXMgdGhlIHJlcG9ydCwgdGhlbiByb3V0ZXMgdG8gaXQuIFRoZSBoZWFkZXIgZ2VhciBvcGVucyB0aGVcbi8vIGdsb2JhbCBSZXBvcnQgU2V0dGluZ3MgZGlhbG9nIChBSSBrbm93bGVkZ2UgZG9jdW1lbnQgKyBzZW1hbnRpYy1kYXRhYmFzZVxuLy8gYnVpbGQpLCB3aGljaCBsaXZlcyBpbiB0aGlzIHBhY2thZ2UuIE5vIHJvdXRpbmcgaXMgaGFyZC1jb2RlZCBoZXJlLlxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZnMtYWktcmVwb3J0cycsXG4gIHRlbXBsYXRlVXJsOiAnLi9mcy1haS1yZXBvcnRzLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vZnMtYWktcmVwb3J0cy5jb21wb25lbnQuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIEZzRGF0ZU1vZHVsZSxcbiAgICBGc0xpc3RNb2R1bGUsXG4gICAgUm91dGVyTGluayxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgRnNBaVJlcG9ydHNDb21wb25lbnQge1xuXG4gIC8vIEFQSSBiYXNlIGZvciB0aGUgcmVwb3J0cyBlbmRwb2ludHM7IG92ZXJyaWRlIHRvIG1vdW50IGVsc2V3aGVyZS5cbiAgcHVibGljIHJlYWRvbmx5IGJhc2VQYXRoID0gaW5wdXQ8c3RyaW5nPigncmVwb3J0cycpO1xuXG4gIC8vIFdoZXJlIGEgcm93IGxpbmtzIHRvOyAnOmlkJyBpcyByZXBsYWNlZCB3aXRoIHRoZSByZXBvcnQgaWQuIERlZmF1bHQgdGFrZXNcbiAgLy8geW91IHRvIDxjdXJyZW50IHJvdXRlPi86aWQuIEFic29sdXRlIHdoZW4gaXQgc3RhcnRzIHdpdGggJy8nLlxuICBwdWJsaWMgcmVhZG9ubHkgb3BlblBhdHRlcm4gPSBpbnB1dDxzdHJpbmc+KCc6aWQnKTtcblxuICAvLyBXaGVyZSBhIGZyZXNobHktY3JlYXRlZCByZXBvcnQgcm91dGVzIHRvOyBzYW1lICc6aWQnIHBhdHRlcm4gcnVsZXMuXG4gIHB1YmxpYyByZWFkb25seSBjcmVhdGVQYXR0ZXJuID0gaW5wdXQ8c3RyaW5nPignOmlkJyk7XG5cbiAgQFZpZXdDaGlsZChGc0xpc3RDb21wb25lbnQpXG4gIHB1YmxpYyBsaXN0OiBGc0xpc3RDb21wb25lbnQgPSBudWxsO1xuXG4gIHB1YmxpYyBsaXN0Q29uZmlnOiBGc0xpc3RDb25maWc8UmVwb3J0TGlzdEl0ZW0+O1xuXG4gIHByaXZhdGUgX3JlcG9ydERhdGEgPSBpbmplY3QoUmVwb3J0RGF0YSk7XG4gIHByaXZhdGUgX3JvdXRlciA9IGluamVjdChSb3V0ZXIpO1xuICBwcml2YXRlIF9yb3V0ZSA9IGluamVjdChBY3RpdmF0ZWRSb3V0ZSk7XG4gIHByaXZhdGUgX3Byb21wdCA9IGluamVjdChGc1Byb21wdCk7XG4gIHByaXZhdGUgX2RpYWxvZyA9IGluamVjdChNYXREaWFsb2cpO1xuICBwcml2YXRlIF9kZXN0cm95UmVmID0gaW5qZWN0KERlc3Ryb3lSZWYpO1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICB0aGlzLl9yZXBvcnREYXRhLmJhc2VQYXRoID0gdGhpcy5iYXNlUGF0aCgpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5faW5pdExpc3RDb25maWcoKTtcbiAgfVxuXG4gIC8vIHJvdXRlckxpbmsgY29tbWFuZHMgZm9yIGEgcmVwb3J0IHJvdyAoYnVpbHQgZnJvbSBvcGVuUGF0dGVybikuXG4gIHB1YmxpYyBvcGVuTGluayhyZXBvcnQ6IFJlcG9ydExpc3RJdGVtKTogdW5rbm93bltdIHtcbiAgICByZXR1cm4gdGhpcy5fcGF0dGVybkNvbW1hbmRzKHRoaXMub3BlblBhdHRlcm4oKSwgcmVwb3J0LmlkKTtcbiAgfVxuXG4gIC8vIFByb21wdCBmb3IgYSB0aXRsZSwgY3JlYXRlIHRoZSByZXBvcnQsIHRoZW4gcm91dGUgdG8gaXQgKGNyZWF0ZVBhdHRlcm4pLlxuICBwdWJsaWMgY3JlYXRlUmVwb3J0KCk6IHZvaWQge1xuICAgIHRoaXMuX3Byb21wdC5pbnB1dCh7XG4gICAgICB0aXRsZTogJ0NyZWF0ZSBSZXBvcnQnLFxuICAgICAgbGFiZWw6ICdUaXRsZScsXG4gICAgICBjb21taXRMYWJlbDogJ0NyZWF0ZScsXG4gICAgICByZXF1aXJlZDogdHJ1ZSxcbiAgICB9KVxuICAgICAgLnBpcGUoXG4gICAgICAgIHN3aXRjaE1hcCgobmFtZTogc3RyaW5nKSA9PiB0aGlzLl9yZXBvcnREYXRhLmNyZWF0ZShuYW1lKSksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKHJlcG9ydDogUmVwb3J0TGlzdEl0ZW0pID0+IHtcbiAgICAgICAgY29uc3QgcGF0dGVybiA9IHRoaXMuY3JlYXRlUGF0dGVybigpO1xuICAgICAgICB0aGlzLl9yb3V0ZXIubmF2aWdhdGUoXG4gICAgICAgICAgdGhpcy5fcGF0dGVybkNvbW1hbmRzKHBhdHRlcm4sIHJlcG9ydC5pZCksXG4gICAgICAgICAgcGF0dGVybi5zdGFydHNXaXRoKCcvJykgPyB7fSA6IHsgcmVsYXRpdmVUbzogdGhpcy5fcm91dGUgfSxcbiAgICAgICAgKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLy8gVHVybiBhICc6aWQnIHBhdHRlcm4gaW50byByb3V0ZXIgY29tbWFuZHMuIFJlbGF0aXZlIHVubGVzcyBpdCBzdGFydHNcbiAgLy8gd2l0aCAnLycsIGluIHdoaWNoIGNhc2UgdGhlIGZpcnN0IHNlZ21lbnQgY2FycmllcyB0aGUgbGVhZGluZyBzbGFzaC5cbiAgcHJpdmF0ZSBfcGF0dGVybkNvbW1hbmRzKHBhdHRlcm46IHN0cmluZywgaWQ6IG51bWJlcik6IHVua25vd25bXSB7XG4gICAgY29uc3QgYWJzb2x1dGUgPSBwYXR0ZXJuLnN0YXJ0c1dpdGgoJy8nKTtcbiAgICBjb25zdCBzZWdtZW50czogdW5rbm93bltdID0gcGF0dGVybi5zcGxpdCgnLycpXG4gICAgICAuZmlsdGVyKChzZWdtZW50KSA9PiBzZWdtZW50Lmxlbmd0aCA+IDApXG4gICAgICAubWFwKChzZWdtZW50KSA9PiAoc2VnbWVudCA9PT0gJzppZCcgPyBpZCA6IHNlZ21lbnQpKTtcblxuICAgIGlmICghc2VnbWVudHMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gW2lkXTtcbiAgICB9XG5cbiAgICBpZiAoYWJzb2x1dGUpIHtcbiAgICAgIHNlZ21lbnRzWzBdID0gYC8ke3NlZ21lbnRzWzBdfWA7XG4gICAgfVxuXG4gICAgcmV0dXJuIHNlZ21lbnRzO1xuICB9XG5cbiAgLy8gVGhlIGdsb2JhbCBSZXBvcnQgU2V0dGluZ3MgZGlhbG9nOiB0aGUgQUkga25vd2xlZGdlIGRvY3VtZW50IGFuZCB0aGVcbiAgLy8gc2VtYW50aWMtZGF0YWJhc2UgYnVpbGQuIEEgcnVubmluZyBidWlsZCBzdHJlYW1zIGludG8gdGhlIEZzUHJvY2VzcyBkb2NrLFxuICAvLyB3aGljaCBzdXJ2aXZlcyB0aGUgZGlhbG9nIGNsb3NpbmcuXG4gIHB1YmxpYyBvcGVuU2V0dGluZ3MoKTogdm9pZCB7XG4gICAgdGhpcy5fZGlhbG9nLm9wZW4oR2xvYmFsU2V0dGluZ3NDb21wb25lbnQsIHtcbiAgICAgIHdpZHRoOiAnOTAwcHgnLFxuICAgICAgbWF4V2lkdGg6ICc5NXZ3JyxcbiAgICAgIG1heEhlaWdodDogJzkwdmgnLFxuICAgICAgYXV0b0ZvY3VzOiBmYWxzZSxcbiAgICB9KTtcbiAgfVxuXG4gIHByaXZhdGUgX2luaXRMaXN0Q29uZmlnKCk6IHZvaWQge1xuICAgIHRoaXMubGlzdENvbmZpZyA9IHtcbiAgICAgIC8vIFRoZSBiYWNrZW5kIGxpc3QgaXMgbm90IHBhZ2VkIHlldDsgc2hvdyB0aGUgZnVsbCBzZXQgdW50aWwgaXQgaXMuXG4gICAgICBwYWdpbmc6IGZhbHNlLFxuICAgICAgYWN0aW9uczogW1xuICAgICAgICB7XG4gICAgICAgICAgLy8gSWNvbi1vbmx5OiB0aGUgZ2xvYmFsIFJlcG9ydCBTZXR0aW5ncyBkaWFsb2cuXG4gICAgICAgICAgaWNvbjogJ3NldHRpbmdzJyxcbiAgICAgICAgICB0b29sdGlwOiAnUmVwb3J0IHNldHRpbmdzJyxcbiAgICAgICAgICBwcmltYXJ5OiBmYWxzZSxcbiAgICAgICAgICBjbGljazogKCkgPT4gdGhpcy5vcGVuU2V0dGluZ3MoKSxcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIGxhYmVsOiAnQ3JlYXRlJyxcbiAgICAgICAgICBwcmltYXJ5OiB0cnVlLFxuICAgICAgICAgIGNsaWNrOiAoKSA9PiB0aGlzLmNyZWF0ZVJlcG9ydCgpLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIGZldGNoOiAocXVlcnkpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlcG9ydERhdGEucmVwb3J0cyhxdWVyeSlcbiAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgIG1hcCgocmVwb3J0czogUmVwb3J0TGlzdEl0ZW1bXSkgPT4gKHsgZGF0YTogcmVwb3J0cyA/PyBbXSB9KSksXG4gICAgICAgICAgKTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxufVxuIiwiPGZzLWxpc3RcbiAgICBbY29uZmlnXT1cImxpc3RDb25maWdcIlxuICAgICNsaXN0PlxuXG4gIDxmcy1saXN0LWNvbHVtbiB0aXRsZT1cIk5hbWVcIj5cbiAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgZnMtbGlzdC1jZWxsXG4gICAgICAgIGxldC1yb3c9XCJyb3dcIj5cbiAgICAgIDxhIFtyb3V0ZXJMaW5rXT1cIm9wZW5MaW5rKHJvdylcIj57eyByb3cubmFtZSB9fTwvYT5cbiAgICA8L25nLXRlbXBsYXRlPlxuICA8L2ZzLWxpc3QtY29sdW1uPlxuXG4gIDxmcy1saXN0LWNvbHVtbiB0aXRsZT1cIk1vZGlmaWVkXCI+XG4gICAgPG5nLXRlbXBsYXRlXG4gICAgICAgIGZzLWxpc3QtY2VsbFxuICAgICAgICBsZXQtcm93PVwicm93XCI+XG4gICAgICA8ZnMtZGF0ZSBbZGF0ZV09XCJyb3cubW9kaWZ5RGF0ZVwiPjwvZnMtZGF0ZT5cbiAgICA8L25nLXRlbXBsYXRlPlxuICA8L2ZzLWxpc3QtY29sdW1uPlxuXG48L2ZzLWxpc3Q+XG4iXX0=
155
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZnMtYWktcmVwb3J0cy5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL3JlcG9ydHMvdmlld3MvcmVwb3J0cy9mcy1haS1yZXBvcnRzLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy92aWV3cy9yZXBvcnRzL2ZzLWFpLXJlcG9ydHMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFFLFNBQVMsRUFBRSxVQUFVLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ2pILE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBQ2hFLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRXJFLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUVyRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLGVBQWUsRUFBZ0IsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDL0UsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRTlDLE9BQU8sRUFBRSxHQUFHLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFaEQsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLHdCQUF3QixDQUFDO0FBQ3BELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLHlEQUF5RCxDQUFDO0FBQ2xHLE9BQU8sRUFBa0IsV0FBVyxFQUFFLE1BQU0sbUNBQW1DLENBQUM7Ozs7QUFHaEYsK0VBQStFO0FBQy9FLDJFQUEyRTtBQUMzRSwyRUFBMkU7QUFDM0UsMEVBQTBFO0FBQzFFLDJFQUEy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QURWLFNBQVM7dUJBQUMsZUFBZSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIERlc3Ryb3lSZWYsIFZpZXdDaGlsZCwgZWZmZWN0LCBpbmplY3QsIGlucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyB0YWtlVW50aWxEZXN0cm95ZWQgfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQgeyBBY3RpdmF0ZWRSb3V0ZSwgUm91dGVyLCBSb3V0ZXJMaW5rIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcblxuaW1wb3J0IHsgTWF0RGlhbG9nIH0gZnJvbSAnQGFuZ3VsYXIvbWF0ZXJpYWwvZGlhbG9nJztcblxuaW1wb3J0IHsgRnNEYXRlTW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvZGF0ZSc7XG5pbXBvcnQgeyBGc0xpc3RDb21wb25lbnQsIEZzTGlzdENvbmZpZywgRnNMaXN0TW9kdWxlIH0gZnJvbSAnQGZpcmVzdGl0Y2gvbGlzdCc7XG5pbXBvcnQgeyBGc1Byb21wdCB9IGZyb20gJ0BmaXJlc3RpdGNoL3Byb21wdCc7XG5cbmltcG9ydCB7IG1hcCwgc3dpdGNoTWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuXG5pbXBvcnQgeyBSZXBvcnREYXRhIH0gZnJvbSAnLi4vLi4vZGF0YS9yZXBvcnQuZGF0YSc7XG5pbXBvcnQgeyBHbG9iYWxTZXR0aW5nc0NvbXBvbmVudCB9IGZyb20gJy4uLy4uL2RpYWxvZ3MvZ2xvYmFsLXNldHRpbmdzL2dsb2JhbC1zZXR0aW5ncy5jb21wb25lbnQnO1xuaW1wb3J0IHsgUmVwb3J0TGlzdEl0ZW0sIFJlcG9ydFN0YXRlIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcblxuXG4vLyBUaGUgcmVwb3J0cyBsaXN0aW5nIOKAlCBhbiBmcy1saXN0IG9mIHJlcG9ydHMuIFJvd3MgYXJlIGxpbmtzIGJ1aWx0IGZyb20gYSBVUkxcbi8vIHBhdHRlcm4gKGEgJzppZCcgdG9rZW4g4oaSIHRoZSByZXBvcnQgaWQ7IGEgbGVhZGluZyAnLycgbWFrZXMgaXQgYWJzb2x1dGUsXG4vLyBvdGhlcndpc2UgaXQncyByZWxhdGl2ZSB0byB0aGlzIGNvbXBvbmVudCdzIHJvdXRlKS4gQ3JlYXRlIHByb21wdHMgZm9yIGFcbi8vIHRpdGxlLCBjcmVhdGVzIHRoZSByZXBvcnQsIHRoZW4gcm91dGVzIHRvIGl0LiBUaGUgaGVhZGVyIGdlYXIgb3BlbnMgdGhlXG4vLyBnbG9iYWwgUmVwb3J0IFNldHRpbmdzIGRpYWxvZyAoQUkga25vd2xlZGdlIGRvY3VtZW50ICsgc2VtYW50aWMtZGF0YWJhc2Vcbi8vIGJ1aWxkKSwgd2hpY2ggbGl2ZXMgaW4gdGhpcyBwYWNrYWdlLiBObyByb3V0aW5nIGlzIGhhcmQtY29kZWQgaGVyZS5cbi8vXG4vLyBSZXBvcnRzIGFyZSBzb2Z0LWRlbGV0YWJsZTogdGhlIHJvdyBrZWJhYiBkZWxldGVzLCBcIlNob3cgRGVsZXRlZFwiIGZsaXBzIHRoZVxuLy8gbGlzdCBpbnRvIGRlbGV0ZWQgbW9kZSAodGhlIGJhY2tlbmQgaGlkZXMgZGVsZXRlZCByZXBvcnRzIG90aGVyd2lzZSksIGFuZCBpblxuLy8gdGhhdCBtb2RlIGZzLWxpc3Qgc3dhcHMgRGVsZXRlIGZvciBSZXN0b3JlLCB3aGljaCBjYWxscyB0aGUgdW5kZWxldGUgYWN0aW9uXG4vLyBlbmRwb2ludC5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2ZzLWFpLXJlcG9ydHMnLFxuICB0ZW1wbGF0ZVVybDogJy4vZnMtYWktcmVwb3J0cy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2ZzLWFpLXJlcG9ydHMuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBGc0RhdGVNb2R1bGUsXG4gICAgRnNMaXN0TW9kdWxlLFxuICAgIFJvdXRlckxpbmssXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIEZzQWlSZXBvcnRzQ29tcG9uZW50IHtcblxuICAvLyBBUEkgYmFzZSBmb3IgdGhlIHJlcG9ydHMgZW5kcG9pbnRzOyBvdmVycmlkZSB0byBtb3VudCBlbHNld2hlcmUuXG4gIHB1YmxpYyByZWFkb25seSBiYXNlUGF0aCA9IGlucHV0PHN0cmluZz4oJ3JlcG9ydHMnKTtcblxuICAvLyBXaGVyZSBhIHJvdyBsaW5rcyB0bzsgJzppZCcgaXMgcmVwbGFjZWQgd2l0aCB0aGUgcmVwb3J0IGlkLiBEZWZhdWx0IHRha2VzXG4gIC8vIHlvdSB0byA8Y3VycmVudCByb3V0ZT4vOmlkLiBBYnNvbHV0ZSB3aGVuIGl0IHN0YXJ0cyB3aXRoICcvJy5cbiAgcHVibGljIHJlYWRvbmx5IG9wZW5QYXR0ZXJuID0gaW5wdXQ8c3RyaW5nPignOmlkJyk7XG5cbiAgLy8gV2hlcmUgYSBmcmVzaGx5LWNyZWF0ZWQgcmVwb3J0IHJvdXRlcyB0bzsgc2FtZSAnOmlkJyBwYXR0ZXJuIHJ1bGVzLlxuICBwdWJsaWMgcmVhZG9ubHkgY3JlYXRlUGF0dGVybiA9IGlucHV0PHN0cmluZz4oJzppZCcpO1xuXG4gIEBWaWV3Q2hpbGQoRnNMaXN0Q29tcG9uZW50KVxuICBwdWJsaWMgbGlzdDogRnNMaXN0Q29tcG9uZW50ID0gbnVsbDtcblxuICBwdWJsaWMgbGlzdENvbmZpZzogRnNMaXN0Q29uZmlnPFJlcG9ydExpc3RJdGVtPjtcblxuICAvLyBUZW1wbGF0ZS1zaWRlIGhhbmRsZSBvbiB0aGUgZW51bSwgc28gdGhlIG5hbWUgY2VsbCBjYW4gdGVsbCBhIGRlbGV0ZWQgcm93XG4gIC8vIChzaG93biBpbiBTaG93IERlbGV0ZWQgbW9kZSkgZnJvbSBhIGxpdmUgb25lLlxuICBwdWJsaWMgcmVhZG9ubHkgZGVsZXRlZFN0YXRlID0gUmVwb3J0U3RhdGUuRGVsZXRlZDtcblxuICBwcml2YXRlIF9yZXBvcnREYXRhID0gaW5qZWN0KFJlcG9ydERhdGEpO1xuICBwcml2YXRlIF9yb3V0ZXIgPSBpbmplY3QoUm91dGVyKTtcbiAgcHJpdmF0ZSBfcm91dGUgPSBpbmplY3QoQWN0aXZhdGVkUm91dGUpO1xuICBwcml2YXRlIF9wcm9tcHQgPSBpbmplY3QoRnNQcm9tcHQpO1xuICBwcml2YXRlIF9kaWFsb2cgPSBpbmplY3QoTWF0RGlhbG9nKTtcbiAgcHJpdmF0ZSBfZGVzdHJveVJlZiA9IGluamVjdChEZXN0cm95UmVmKTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBlZmZlY3QoKCkgPT4ge1xuICAgICAgdGhpcy5fcmVwb3J0RGF0YS5iYXNlUGF0aCA9IHRoaXMuYmFzZVBhdGgoKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX2luaXRMaXN0Q29uZmlnKCk7XG4gIH1cblxuICAvLyByb3V0ZXJMaW5rIGNvbW1hbmRzIGZvciBhIHJlcG9ydCByb3cgKGJ1aWx0IGZyb20gb3BlblBhdHRlcm4pLlxuICBwdWJsaWMgb3BlbkxpbmsocmVwb3J0OiBSZXBvcnRMaXN0SXRlbSk6IHVua25vd25bXSB7XG4gICAgcmV0dXJuIHRoaXMuX3BhdHRlcm5Db21tYW5kcyh0aGlzLm9wZW5QYXR0ZXJuKCksIHJlcG9ydC5pZCk7XG4gIH1cblxuICAvLyBQcm9tcHQgZm9yIGEgdGl0bGUsIGNyZWF0ZSB0aGUgcmVwb3J0LCB0aGVuIHJvdXRlIHRvIGl0IChjcmVhdGVQYXR0ZXJuKS5cbiAgcHVibGljIGNyZWF0ZVJlcG9ydCgpOiB2b2lkIHtcbiAgICB0aGlzLl9wcm9tcHQuaW5wdXQoe1xuICAgICAgdGl0bGU6ICdDcmVhdGUgUmVwb3J0JyxcbiAgICAgIGxhYmVsOiAnVGl0bGUnLFxuICAgICAgY29tbWl0TGFiZWw6ICdDcmVhdGUnLFxuICAgICAgcmVxdWlyZWQ6IHRydWUsXG4gICAgfSlcbiAgICAgIC5waXBlKFxuICAgICAgICBzd2l0Y2hNYXAoKG5hbWU6IHN0cmluZykgPT4gdGhpcy5fcmVwb3J0RGF0YS5jcmVhdGUobmFtZSkpLFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZiksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKChyZXBvcnQ6IFJlcG9ydExpc3RJdGVtKSA9PiB7XG4gICAgICAgIGNvbnN0IHBhdHRlcm4gPSB0aGlzLmNyZWF0ZVBhdHRlcm4oKTtcbiAgICAgICAgdGhpcy5fcm91dGVyLm5hdmlnYXRlKFxuICAgICAgICAgIHRoaXMuX3BhdHRlcm5Db21tYW5kcyhwYXR0ZXJuLCByZXBvcnQuaWQpLFxuICAgICAgICAgIHBhdHRlcm4uc3RhcnRzV2l0aCgnLycpID8ge30gOiB7IHJlbGF0aXZlVG86IHRoaXMuX3JvdXRlIH0sXG4gICAgICAgICk7XG4gICAgICB9KTtcbiAgfVxuXG4gIC8vIFR1cm4gYSAnOmlkJyBwYXR0ZXJuIGludG8gcm91dGVyIGNvbW1hbmRzLiBSZWxhdGl2ZSB1bmxlc3MgaXQgc3RhcnRzXG4gIC8vIHdpdGggJy8nLCBpbiB3aGljaCBjYXNlIHRoZSBmaXJzdCBzZWdtZW50IGNhcnJpZXMgdGhlIGxlYWRpbmcgc2xhc2guXG4gIHByaXZhdGUgX3BhdHRlcm5Db21tYW5kcyhwYXR0ZXJuOiBzdHJpbmcsIGlkOiBudW1iZXIpOiB1bmtub3duW10ge1xuICAgIGNvbnN0IGFic29sdXRlID0gcGF0dGVybi5zdGFydHNXaXRoKCcvJyk7XG4gICAgY29uc3Qgc2VnbWVudHM6IHVua25vd25bXSA9IHBhdHRlcm4uc3BsaXQoJy8nKVxuICAgICAgLmZpbHRlcigoc2VnbWVudCkgPT4gc2VnbWVudC5sZW5ndGggPiAwKVxuICAgICAgLm1hcCgoc2VnbWVudCkgPT4gKHNlZ21lbnQgPT09ICc6aWQnID8gaWQgOiBzZWdtZW50KSk7XG5cbiAgICBpZiAoIXNlZ21lbnRzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIFtpZF07XG4gICAgfVxuXG4gICAgaWYgKGFic29sdXRlKSB7XG4gICAgICBzZWdtZW50c1swXSA9IGAvJHtzZWdtZW50c1swXX1gO1xuICAgIH1cblxuICAgIHJldHVybiBzZWdtZW50cztcbiAgfVxuXG4gIC8vIFRoZSBnbG9iYWwgUmVwb3J0IFNldHRpbmdzIGRpYWxvZzogdGhlIEFJIGtub3dsZWRnZSBkb2N1bWVudCBhbmQgdGhlXG4gIC8vIHNlbWFudGljLWRhdGFiYXNlIGJ1aWxkLiBBIHJ1bm5pbmcgYnVpbGQgc3RyZWFtcyBpbnRvIHRoZSBGc1Byb2Nlc3MgZG9jayxcbiAgLy8gd2hpY2ggc3Vydml2ZXMgdGhlIGRpYWxvZyBjbG9zaW5nLlxuICBwdWJsaWMgb3BlblNldHRpbmdzKCk6IHZvaWQge1xuICAgIHRoaXMuX2RpYWxvZy5vcGVuKEdsb2JhbFNldHRpbmdzQ29tcG9uZW50LCB7XG4gICAgICB3aWR0aDogJzkwMHB4JyxcbiAgICAgIG1heFdpZHRoOiAnOTV2dycsXG4gICAgICBtYXhIZWlnaHQ6ICc5MHZoJyxcbiAgICAgIGF1dG9Gb2N1czogZmFsc2UsXG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9pbml0TGlzdENvbmZpZygpOiB2b2lkIHtcbiAgICB0aGlzLmxpc3RDb25maWcgPSB7XG4gICAgICAvLyBUaGUgYmFja2VuZCBsaXN0IGlzIG5vdCBwYWdlZCB5ZXQ7IHNob3cgdGhlIGZ1bGwgc2V0IHVudGlsIGl0IGlzLlxuICAgICAgcGFnaW5nOiBmYWxzZSxcbiAgICAgIGFjdGlvbnM6IFtcbiAgICAgICAge1xuICAgICAgICAgIC8vIEljb24tb25seTogdGhlIGdsb2JhbCBSZXBvcnQgU2V0dGluZ3MgZGlhbG9nLlxuICAgICAgICAgIGljb246ICdzZXR0aW5ncycsXG4gICAgICAgICAgdG9vbHRpcDogJ1JlcG9ydCBzZXR0aW5ncycsXG4gICAgICAgICAgcHJpbWFyeTogZmFsc2UsXG4gICAgICAgICAgY2xpY2s6ICgpID0+IHRoaXMub3BlblNldHRpbmdzKCksXG4gICAgICAgIH0sXG4gICAgICAgIHtcbiAgICAgICAgICBsYWJlbDogJ0NyZWF0ZScsXG4gICAgICAgICAgcHJpbWFyeTogdHJ1ZSxcbiAgICAgICAgICBjbGljazogKCkgPT4gdGhpcy5jcmVhdGVSZXBvcnQoKSxcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICByb3dBY3Rpb25zOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBjbGljazogKHJlcG9ydCkgPT4gdGhpcy5fcmVwb3J0RGF0YS5kZWxldGUocmVwb3J0LmlkKSxcbiAgICAgICAgICByZW1vdmU6IHtcbiAgICAgICAgICAgIHRpdGxlOiAnQ29uZmlybScsXG4gICAgICAgICAgICB0ZW1wbGF0ZTogJ0FyZSB5b3Ugc3VyZSB5b3Ugd291bGQgbGlrZSB0byBkZWxldGUgdGhpcyByZXBvcnQ/JyxcbiAgICAgICAgICB9LFxuICAgICAgICAgIG1lbnU6IHRydWUsXG4gICAgICAgICAgbGFiZWw6ICdEZWxldGUnLFxuICAgICAgICB9LFxuICAgICAgXSxcbiAgICAgIC8vIGBmaWx0ZXI6IHRydWVgIG1ha2VzIGZzLWxpc3QgcmVuZGVyIHRoZSBTaG93IERlbGV0ZWQgdG9nZ2xlIGFuZCBzZW5kXG4gICAgICAvLyBgcXVlcnlgIHdpdGggdGhlIGZldGNoOyBpbiB0aGF0IG1vZGUgaXQgYWxzbyBzd2FwcyB0aGUgcm93J3MgRGVsZXRlXG4gICAgICAvLyBhY3Rpb24gZm9yIFJlc3RvcmUuXG4gICAgICByZXN0b3JlOiB7XG4gICAgICAgIHF1ZXJ5OiB7IHN0YXRlOiBSZXBvcnRTdGF0ZS5EZWxldGVkIH0sXG4gICAgICAgIGZpbHRlcjogdHJ1ZSxcbiAgICAgICAgZmlsdGVyTGFiZWw6ICdTaG93IERlbGV0ZWQnLFxuICAgICAgICBtZW51TGFiZWw6ICdSZXN0b3JlJyxcbiAgICAgICAgcmVsb2FkOiB0cnVlLFxuICAgICAgICBjbGljazogKHJlcG9ydCkgPT4gdGhpcy5fcmVwb3J0RGF0YS51bmRlbGV0ZShyZXBvcnQuaWQpLFxuICAgICAgfSxcbiAgICAgIGZldGNoOiAocXVlcnkpID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JlcG9ydERhdGEucmVwb3J0cyhxdWVyeSlcbiAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgIG1hcCgocmVwb3J0czogUmVwb3J0TGlzdEl0ZW1bXSkgPT4gKHsgZGF0YTogcmVwb3J0cyA/PyBbXSB9KSksXG4gICAgICAgICAgKTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxufVxuIiwiPGZzLWxpc3RcbiAgICBbY29uZmlnXT1cImxpc3RDb25maWdcIlxuICAgICNsaXN0PlxuXG4gIDxmcy1saXN0LWNvbHVtbiB0aXRsZT1cIk5hbWVcIj5cbiAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgZnMtbGlzdC1jZWxsXG4gICAgICAgIGxldC1yb3c9XCJyb3dcIj5cbiAgICAgIDwhLS0gQSBkZWxldGVkIHJlcG9ydCBjYW4ndCBiZSBvcGVuZWQgKHRoZSBiYWNrZW5kIG9ubHkgYXNzZW1ibGVzIGFjdGl2ZVxuICAgICAgICAgICBvbmVzKSwgc28gaW4gU2hvdyBEZWxldGVkIG1vZGUgdGhlIG5hbWUgaXMgcGxhaW4gdGV4dCDigJQgcmVzdG9yZSBpdFxuICAgICAgICAgICBmcm9tIHRoZSByb3cgbWVudSBmaXJzdC4gLS0+XG4gICAgICBAaWYgKHJvdy5zdGF0ZSA9PT0gZGVsZXRlZFN0YXRlKSB7XG4gICAgICAgIHt7IHJvdy5uYW1lIH19XG4gICAgICB9IEBlbHNlIHtcbiAgICAgICAgPGEgW3JvdXRlckxpbmtdPVwib3Blbkxpbmsocm93KVwiPnt7IHJvdy5uYW1lIH19PC9hPlxuICAgICAgfVxuICAgIDwvbmctdGVtcGxhdGU+XG4gIDwvZnMtbGlzdC1jb2x1bW4+XG5cbiAgPGZzLWxpc3QtY29sdW1uIHRpdGxlPVwiTW9kaWZpZWRcIj5cbiAgICA8bmctdGVtcGxhdGVcbiAgICAgICAgZnMtbGlzdC1jZWxsXG4gICAgICAgIGxldC1yb3c9XCJyb3dcIj5cbiAgICAgIDxmcy1kYXRlIFtkYXRlXT1cInJvdy5tb2RpZnlEYXRlXCI+PC9mcy1kYXRlPlxuICAgIDwvbmctdGVtcGxhdGU+XG4gIDwvZnMtbGlzdC1jb2x1bW4+XG5cbjwvZnMtbGlzdD5cbiJdfQ==
@@ -3,7 +3,7 @@ import { GridComponent, TooltipComponent, LegendComponent, DatasetComponent } fr
3
3
  import * as echarts from 'echarts/core';
4
4
  export { echarts as default };
5
5
  import { CanvasRenderer } from 'echarts/renderers';
6
- import { R as REPORT_CHART_COLORS_CSS } from './firestitch-report-firestitch-report-Dh8kteJk.mjs';
6
+ import { R as REPORT_CHART_COLORS_CSS } from './firestitch-report-firestitch-report-DwgbMhwr.mjs';
7
7
 
8
8
  // Tree-shaken ECharts build for the reports renderer: only the chart types and
9
9
  // components the option-builder emits are registered, keeping the lazy chunk
@@ -57,4 +57,4 @@ echarts.registerTheme('report', {
57
57
  axisLabel: { color: '#52606d', fontSize: 11 },
58
58
  },
59
59
  });
60
- //# sourceMappingURL=firestitch-report-echarts-F254vpF1.mjs.map
60
+ //# sourceMappingURL=firestitch-report-echarts-CMOBB-Er.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"firestitch-report-echarts-F254vpF1.mjs","sources":["../../src/app/reports/theme/echarts.ts"],"sourcesContent":["// Tree-shaken ECharts build for the reports renderer: only the chart types and\n// components the option-builder emits are registered, keeping the lazy chunk\n// lean. Loaded on demand by ngx-echarts via provideEchartsCore — see\n// REPORT_ECHARTS_PROVIDERS in reports-echarts.provider.ts.\n//\n// The canvas renderer (not SVG) is deliberate: chart.getDataURL() needs it for\n// the high-res images the PPT/PDF exports will use.\n\nimport { BarChart, LineChart, PieChart } from 'echarts/charts';\nimport {\n DatasetComponent,\n GridComponent,\n LegendComponent,\n TooltipComponent,\n} from 'echarts/components';\nimport * as echarts from 'echarts/core';\nimport { CanvasRenderer } from 'echarts/renderers';\n\nimport { REPORT_CHART_COLORS_CSS } from './palette';\n\necharts.use([\n BarChart,\n LineChart,\n PieChart,\n GridComponent,\n TooltipComponent,\n LegendComponent,\n DatasetComponent,\n CanvasRenderer,\n]);\n\n// The house theme — the single place report chart \"standards\" live (palette,\n// typography, tooltip styling). Polished defaults now; refined in the polish\n// phase.\necharts.registerTheme('report', {\n color: REPORT_CHART_COLORS_CSS,\n textStyle: {\n fontFamily: 'Roboto, \"Helvetica Neue\", sans-serif',\n },\n title: {\n textStyle: { color: '#1f2933', fontSize: 14, fontWeight: 600 },\n },\n legend: {\n textStyle: { color: '#52606d', fontSize: 11 },\n },\n tooltip: {\n backgroundColor: 'rgba(31, 41, 51, 0.92)',\n borderWidth: 0,\n textStyle: { color: '#fff', fontSize: 12 },\n },\n categoryAxis: {\n axisLine: { lineStyle: { color: '#cbd2d9' } },\n axisTick: { show: false },\n axisLabel: { color: '#52606d', fontSize: 11 },\n splitLine: { show: false },\n },\n valueAxis: {\n axisLine: { show: false },\n axisLabel: { color: '#52606d', fontSize: 11 },\n splitLine: { lineStyle: { color: '#e4e7eb' } },\n },\n timeAxis: {\n axisLine: { lineStyle: { color: '#cbd2d9' } },\n axisLabel: { color: '#52606d', fontSize: 11 },\n },\n});\n\nexport default echarts;\n"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAcA,OAAO,CAAC,GAAG,CAAC;IACV,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,aAAa;IACb,gBAAgB;IAChB,eAAe;IACf,gBAAgB;IAChB,cAAc;AACf,CAAA,CAAC,CAAC;AAEH;AACA;AACA;AACA,OAAO,CAAC,aAAa,CAAC,QAAQ,EAAE;AAC9B,IAAA,KAAK,EAAE,uBAAuB;AAC9B,IAAA,SAAS,EAAE;AACT,QAAA,UAAU,EAAE,sCAAsC;AACnD,KAAA;AACD,IAAA,KAAK,EAAE;AACL,QAAA,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE;AAC/D,KAAA;AACD,IAAA,MAAM,EAAE;QACN,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC9C,KAAA;AACD,IAAA,OAAO,EAAE;AACP,QAAA,eAAe,EAAE,wBAAwB;AACzC,QAAA,WAAW,EAAE,CAAC;QACd,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC3C,KAAA;AACD,IAAA,YAAY,EAAE;QACZ,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;AAC7C,QAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QACzB,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC7C,QAAA,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;AAC3B,KAAA;AACD,IAAA,SAAS,EAAE;AACT,QAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QACzB,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC7C,SAAS,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;AAC/C,KAAA;AACD,IAAA,QAAQ,EAAE;QACR,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;QAC7C,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC9C,KAAA;AACF,CAAA,CAAC"}
1
+ {"version":3,"file":"firestitch-report-echarts-CMOBB-Er.mjs","sources":["../../src/app/reports/theme/echarts.ts"],"sourcesContent":["// Tree-shaken ECharts build for the reports renderer: only the chart types and\n// components the option-builder emits are registered, keeping the lazy chunk\n// lean. Loaded on demand by ngx-echarts via provideEchartsCore — see\n// REPORT_ECHARTS_PROVIDERS in reports-echarts.provider.ts.\n//\n// The canvas renderer (not SVG) is deliberate: chart.getDataURL() needs it for\n// the high-res images the PPT/PDF exports will use.\n\nimport { BarChart, LineChart, PieChart } from 'echarts/charts';\nimport {\n DatasetComponent,\n GridComponent,\n LegendComponent,\n TooltipComponent,\n} from 'echarts/components';\nimport * as echarts from 'echarts/core';\nimport { CanvasRenderer } from 'echarts/renderers';\n\nimport { REPORT_CHART_COLORS_CSS } from './palette';\n\necharts.use([\n BarChart,\n LineChart,\n PieChart,\n GridComponent,\n TooltipComponent,\n LegendComponent,\n DatasetComponent,\n CanvasRenderer,\n]);\n\n// The house theme — the single place report chart \"standards\" live (palette,\n// typography, tooltip styling). Polished defaults now; refined in the polish\n// phase.\necharts.registerTheme('report', {\n color: REPORT_CHART_COLORS_CSS,\n textStyle: {\n fontFamily: 'Roboto, \"Helvetica Neue\", sans-serif',\n },\n title: {\n textStyle: { color: '#1f2933', fontSize: 14, fontWeight: 600 },\n },\n legend: {\n textStyle: { color: '#52606d', fontSize: 11 },\n },\n tooltip: {\n backgroundColor: 'rgba(31, 41, 51, 0.92)',\n borderWidth: 0,\n textStyle: { color: '#fff', fontSize: 12 },\n },\n categoryAxis: {\n axisLine: { lineStyle: { color: '#cbd2d9' } },\n axisTick: { show: false },\n axisLabel: { color: '#52606d', fontSize: 11 },\n splitLine: { show: false },\n },\n valueAxis: {\n axisLine: { show: false },\n axisLabel: { color: '#52606d', fontSize: 11 },\n splitLine: { lineStyle: { color: '#e4e7eb' } },\n },\n timeAxis: {\n axisLine: { lineStyle: { color: '#cbd2d9' } },\n axisLabel: { color: '#52606d', fontSize: 11 },\n },\n});\n\nexport default echarts;\n"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AAcA,OAAO,CAAC,GAAG,CAAC;IACV,QAAQ;IACR,SAAS;IACT,QAAQ;IACR,aAAa;IACb,gBAAgB;IAChB,eAAe;IACf,gBAAgB;IAChB,cAAc;AACf,CAAA,CAAC,CAAC;AAEH;AACA;AACA;AACA,OAAO,CAAC,aAAa,CAAC,QAAQ,EAAE;AAC9B,IAAA,KAAK,EAAE,uBAAuB;AAC9B,IAAA,SAAS,EAAE;AACT,QAAA,UAAU,EAAE,sCAAsC;AACnD,KAAA;AACD,IAAA,KAAK,EAAE;AACL,QAAA,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE,UAAU,EAAE,GAAG,EAAE;AAC/D,KAAA;AACD,IAAA,MAAM,EAAE;QACN,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC9C,KAAA;AACD,IAAA,OAAO,EAAE;AACP,QAAA,eAAe,EAAE,wBAAwB;AACzC,QAAA,WAAW,EAAE,CAAC;QACd,SAAS,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC3C,KAAA;AACD,IAAA,YAAY,EAAE;QACZ,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;AAC7C,QAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QACzB,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC7C,QAAA,SAAS,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;AAC3B,KAAA;AACD,IAAA,SAAS,EAAE;AACT,QAAA,QAAQ,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE;QACzB,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;QAC7C,SAAS,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;AAC/C,KAAA;AACD,IAAA,QAAQ,EAAE;QACR,QAAQ,EAAE,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE;QAC7C,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,EAAE;AAC9C,KAAA;AACF,CAAA,CAAC"}
@@ -116,12 +116,22 @@ class ReportData {
116
116
  ...config,
117
117
  });
118
118
  }
119
+ // Soft-delete: the report leaves the listing but keeps its pages and
120
+ // components, so undelete() brings back the same document.
119
121
  delete(reportId, config = {}) {
120
122
  return this._api.delete(this._path(`${reportId}`), {}, {
121
123
  key: 'report',
122
124
  ...config,
123
125
  });
124
126
  }
127
+ // Restore a soft-deleted report through its own action endpoint — the report
128
+ // PUT does not accept `state`.
129
+ undelete(reportId, config = {}) {
130
+ return this._api.post(this._path(`${reportId}/undelete`), {}, {
131
+ key: 'report',
132
+ ...config,
133
+ });
134
+ }
125
135
  // The assembled structure: pages → components (+ their filters) and the
126
136
  // report's filter groups.
127
137
  get(reportId, config = {}) {
@@ -2488,6 +2498,13 @@ const FREQUENCY_OPTIONS = [
2488
2498
  { value: 'quarter', name: 'Quarter' },
2489
2499
  { value: 'year', name: 'Annually' },
2490
2500
  ];
2501
+ // Reports are soft-deletable: a deleted report leaves the listing but keeps its
2502
+ // pages and components, and the listing's "Show Deleted" mode restores it.
2503
+ var ReportState;
2504
+ (function (ReportState) {
2505
+ ReportState["Active"] = "active";
2506
+ ReportState["Deleted"] = "deleted";
2507
+ })(ReportState || (ReportState = {}));
2491
2508
 
2492
2509
  // Rows fetched for a list component's export table — enough to fill a
2493
2510
  // slide/page table; the cap note covers the rest.
@@ -2582,7 +2599,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
2582
2599
  // complete synchronously after setOption.
2583
2600
  async function renderChartImage(component, data, width, height, pixelRatio = 3) {
2584
2601
  // The same tree-shaken echarts build + 'report' theme the live canvas uses.
2585
- const echarts = (await import('./firestitch-report-echarts-F254vpF1.mjs')).default;
2602
+ const echarts = (await import('./firestitch-report-echarts-CMOBB-Er.mjs')).default;
2586
2603
  const host = document.createElement('div');
2587
2604
  host.style.width = `${width}px`;
2588
2605
  host.style.height = `${height}px`;
@@ -2733,6 +2750,10 @@ class ReportPdfService {
2733
2750
  doc.text(config.measure.label, x + w / 2, y + h / 2 + 16, { align: 'center' });
2734
2751
  }
2735
2752
  }
2753
+ // The exported cell must read like the on-screen cell: the SQL already
2754
+ // carries the formatting, so the value goes out verbatim. A raw date is the
2755
+ // one value the client renders (the column stays a RAW timestamp for the
2756
+ // report timezone), and it is rendered here too.
2736
2757
  _cell(value, columnFormat) {
2737
2758
  if (value === null || value === undefined) {
2738
2759
  return '';
@@ -2741,9 +2762,6 @@ class ReportPdfService {
2741
2762
  const date = new Date(String(value));
2742
2763
  return Number.isNaN(date.getTime()) ? String(value) : format(date, 'MMM d, yyyy');
2743
2764
  }
2744
- if (columnFormat === 'number') {
2745
- return formatMeasureValue(value, 'number');
2746
- }
2747
2765
  return String(value);
2748
2766
  }
2749
2767
  _slug(name) {
@@ -2960,6 +2978,10 @@ class ReportPptxService {
2960
2978
  valign: 'middle',
2961
2979
  });
2962
2980
  }
2981
+ // The exported cell must read like the on-screen cell: the SQL already
2982
+ // carries the formatting, so the value goes out verbatim. A raw date is the
2983
+ // one value the client renders (the column stays a RAW timestamp for the
2984
+ // report timezone), and it is rendered here too.
2963
2985
  _cell(value, columnFormat) {
2964
2986
  if (value === null || value === undefined) {
2965
2987
  return '';
@@ -2968,9 +2990,6 @@ class ReportPptxService {
2968
2990
  const date = new Date(String(value));
2969
2991
  return Number.isNaN(date.getTime()) ? String(value) : format(date, 'MMM d, yyyy');
2970
2992
  }
2971
- if (columnFormat === 'number') {
2972
- return formatMeasureValue(value, 'number');
2973
- }
2974
2993
  return String(value);
2975
2994
  }
2976
2995
  _slug(name) {
@@ -3326,7 +3345,7 @@ class ReportComponent {
3326
3345
  ReportPdfService,
3327
3346
  // Tree-shaken ECharts core + the 'report' house theme, loaded lazily with
3328
3347
  // this route's chunk.
3329
- provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-F254vpF1.mjs').then((module) => module.default) }),
3348
+ provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-CMOBB-Er.mjs').then((module) => module.default) }),
3330
3349
  ], viewQueries: [{ propertyName: "_split", first: true, predicate: ["split"], descendants: true, static: true }, { propertyName: "_chatPanel", first: true, predicate: ["chatPanel"], descendants: true, read: ElementRef, static: true }], ngImport: i0, template: "<div\n #split\n class=\"report fs-row.align-start\">\n <fs-ai-chat\n #chatPanel\n class=\"chat\"\n style=\"min-height: 500px;\"\n basePath=\"reports\"\n [requestData]=\"{ reportId: selected?.id ?? null }\"\n [introMessage]=\"introMessage\"\n (response)=\"onChatResponse($event)\">\n </fs-ai-chat>\n <div\n class=\"resizer\"\n (pointerdown)=\"onResizeStart($event)\">\n </div>\n <div class=\"viewer fs-flex fs-column\">\n <div class=\"fs-row.align-center.gap-sm\">\n <fs-autocomplete-chips\n class=\"fs-flex\"\n [fetch]=\"fetchReports\"\n [(ngModel)]=\"selected\"\n [disabled]=\"loadingReports\"\n [padless]=\"true\"\n [multiple]=\"false\"\n [fetchOnFocus]=\"true\"\n (ngModelChange)=\"reportChange($event)\"\n placeholder=\"Report\"\n name=\"report\">\n <ng-template\n fsAutocompleteChipsTemplate\n let-object=\"object\">\n {{ object.name }}\n </ng-template>\n <ng-template\n fsAutocompleteChipsStatic\n (click)=\"createReport()\">\n Create Report\n </ng-template>\n </fs-autocomplete-chips>\n @if (report) {\n <fs-menu>\n <ng-template\n fs-menu-item\n (click)=\"reportSettings()\">\n <mat-icon>\n tune\n </mat-icon>\n Report settings\n </ng-template>\n <ng-template\n fs-menu-item\n (click)=\"toggleEditMode()\"\n [disabled]=\"editMode\">\n <mat-icon>\n dashboard_2_edit\n </mat-icon>\n {{ editMode ? 'Done editing layout' : 'Edit layout' }}\n </ng-template>\n <ng-template\n fs-menu-item\n (click)=\"exportPowerpoint()\">\n <mat-icon>\n slideshow\n </mat-icon>\n Export PowerPoint\n </ng-template>\n <ng-template\n fs-menu-item\n (click)=\"exportPdf()\">\n <mat-icon>\n picture_as_pdf\n </mat-icon>\n Export PDF\n </ng-template>\n </fs-menu>\n }\n </div>\n @if (report) {\n <!-- Report-level filters only (the report's actions live in the menu\n above). fs-filter reads its config once at init, so it's keyed on the\n filter signature: when the report-level filter set changes the block\n is recreated and re-reads the rebuilt config. -->\n @if (reportHasFilters) {\n @for (key of [reportFilterKey]; track key) {\n <fs-filter [config]=\"reportFilterConfig\"></fs-filter>\n }\n }\n <app-report-canvas\n [report]=\"report\"\n [editMode]=\"editMode\"\n (componentSettings)=\"componentSettings($event)\"\n (reportChanged)=\"onCanvasReportChanged()\"\n (editDone)=\"toggleEditMode()\">\n </app-report-canvas>\n }\n </div>\n</div>", styles: [".report{height:100%;min-height:500px}.report .chat{display:block;flex:0 0 25%;width:100%;height:100%;min-height:500px;min-width:0;border:none}.report .viewer{display:flex;flex-direction:column;min-width:0;height:100%;overflow:hidden}.report .viewer fs-filter{flex:0 0 auto;margin-top:10px;margin-bottom:0}.report .viewer ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.report .resizer{flex:0 0 11px;align-self:stretch;display:flex;justify-content:center;cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none}.report .resizer:before{content:\"\";width:0px;background:#0000001f;transition:width .12s ease,background-color .12s ease}.report .resizer:hover:before{width:3px;background:var(--brand-primary-color)}.report.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.report.resizing .resizer:before{width:3px;background:var(--brand-primary-color)}.report.resizing .chat,.report.resizing .viewer{pointer-events:none}::ng-deep body.body-report-reports .mat-mdc-card-content{display:flex;flex-direction:column;box-sizing:border-box}::ng-deep body.body-report-reports .mat-mdc-card-content mat-tab-nav-panel{flex:1;min-height:0}::ng-deep body.body-report-reports .mat-mdc-card-content mat-tab-nav-panel router-outlet+ng-component{height:100%}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$3.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$3.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: FsAutocompleteChipsModule }, { kind: "component", type: i2$2.FsAutocompleteChipsComponent, selector: "fs-autocomplete-chips", inputs: ["fetch", "appearance", "floatLabel", "readonly", "size", "label", "placeholder", "chipImage", "chipBackground", "chipColor", "chipIcon", "chipIconColor", "chipClass", "chipPadding", "shape", "hint", "allowText", "allowObject", "delay", "minPanelWidth", "maxPanelHeight", "validateText", "removable", "allowClear", "color", "background", "orderable", "padless", "initOnClick", "fetchOnFocus", "multiple", "multipleAdd", "confirm", "disabled", "groupBy", "panelWidth", "panelClass", "compareWith"], outputs: ["selected", "removed", "reordered", "clear", "panelOpened", "panelClosed"] }, { kind: "directive", type: i2$2.FsAutocompleteObjectDirective, selector: "[fsAutocompleteObject],[fsAutocompleteChipsTemplate]" }, { kind: "directive", type: i2$2.FsAutocompleteChipsStaticDirective, selector: "[fsAutocompleteChipsStatic]", inputs: ["show", "disable"], outputs: ["click", "selected"] }, { kind: "ngmodule", type: FsFilterModule }, { kind: "component", type: i2.FilterComponent, selector: "fs-filter", inputs: ["config"], outputs: ["closed", "opened", "ready"] }, { kind: "ngmodule", type: FsMenuModule }, { kind: "component", type: i2$3.FsMenuComponent, selector: "fs-menu", inputs: ["class", "buttonClass", "buttonType", "buttonColor"], outputs: ["opened", "closed"] }, { kind: "directive", type: i2$3.FsMenuItemDirective, selector: "fs-menu-group,[fs-menu-item]" }, { kind: "component", type: FsAiChatComponent, selector: "fs-ai-chat", inputs: ["basePath", "requestData", "introMessage"], outputs: ["response"] }, { kind: "component", type: MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: ReportCanvasComponent, selector: "app-report-canvas", inputs: ["report", "editMode"], outputs: ["componentSettings", "reportChanged", "editDone"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3331
3350
  }
3332
3351
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportComponent, decorators: [{
@@ -3340,7 +3359,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
3340
3359
  ReportPdfService,
3341
3360
  // Tree-shaken ECharts core + the 'report' house theme, loaded lazily with
3342
3361
  // this route's chunk.
3343
- provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-F254vpF1.mjs').then((module) => module.default) }),
3362
+ provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-CMOBB-Er.mjs').then((module) => module.default) }),
3344
3363
  ], imports: [
3345
3364
  FormsModule,
3346
3365
  FsAutocompleteChipsModule,
@@ -3983,6 +4002,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
3983
4002
  // title, creates the report, then routes to it. The header gear opens the
3984
4003
  // global Report Settings dialog (AI knowledge document + semantic-database
3985
4004
  // build), which lives in this package. No routing is hard-coded here.
4005
+ //
4006
+ // Reports are soft-deletable: the row kebab deletes, "Show Deleted" flips the
4007
+ // list into deleted mode (the backend hides deleted reports otherwise), and in
4008
+ // that mode fs-list swaps Delete for Restore, which calls the undelete action
4009
+ // endpoint.
3986
4010
  class FsAiReportsComponent {
3987
4011
  // API base for the reports endpoints; override to mount elsewhere.
3988
4012
  basePath = input('reports');
@@ -3993,6 +4017,9 @@ class FsAiReportsComponent {
3993
4017
  createPattern = input(':id');
3994
4018
  list = null;
3995
4019
  listConfig;
4020
+ // Template-side handle on the enum, so the name cell can tell a deleted row
4021
+ // (shown in Show Deleted mode) from a live one.
4022
+ deletedState = ReportState.Deleted;
3996
4023
  _reportData = inject(ReportData);
3997
4024
  _router = inject(Router);
3998
4025
  _route = inject(ActivatedRoute);
@@ -4067,6 +4094,28 @@ class FsAiReportsComponent {
4067
4094
  click: () => this.createReport(),
4068
4095
  },
4069
4096
  ],
4097
+ rowActions: [
4098
+ {
4099
+ click: (report) => this._reportData.delete(report.id),
4100
+ remove: {
4101
+ title: 'Confirm',
4102
+ template: 'Are you sure you would like to delete this report?',
4103
+ },
4104
+ menu: true,
4105
+ label: 'Delete',
4106
+ },
4107
+ ],
4108
+ // `filter: true` makes fs-list render the Show Deleted toggle and send
4109
+ // `query` with the fetch; in that mode it also swaps the row's Delete
4110
+ // action for Restore.
4111
+ restore: {
4112
+ query: { state: ReportState.Deleted },
4113
+ filter: true,
4114
+ filterLabel: 'Show Deleted',
4115
+ menuLabel: 'Restore',
4116
+ reload: true,
4117
+ click: (report) => this._reportData.undelete(report.id),
4118
+ },
4070
4119
  fetch: (query) => {
4071
4120
  return this._reportData.reports(query)
4072
4121
  .pipe(map((reports) => ({ data: reports ?? [] })));
@@ -4074,7 +4123,7 @@ class FsAiReportsComponent {
4074
4123
  };
4075
4124
  }
4076
4125
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FsAiReportsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4077
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.14", type: FsAiReportsComponent, isStandalone: true, selector: "fs-ai-reports", inputs: { basePath: { classPropertyName: "basePath", publicName: "basePath", isSignal: true, isRequired: false, transformFunction: null }, openPattern: { classPropertyName: "openPattern", publicName: "openPattern", isSignal: true, isRequired: false, transformFunction: null }, createPattern: { classPropertyName: "createPattern", publicName: "createPattern", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list\n [config]=\"listConfig\"\n #list>\n\n <fs-list-column title=\"Name\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <a [routerLink]=\"openLink(row)\">{{ row.name }}</a>\n </ng-template>\n </fs-list-column>\n\n <fs-list-column title=\"Modified\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date [date]=\"row.modifyDate\"></fs-date>\n </ng-template>\n </fs-list-column>\n\n</fs-list>\n", styles: ["a{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: FsDateModule }, { kind: "component", type: i2$4.FsDateComponent, selector: "fs-date", inputs: ["date", "format", "timezone"] }, { 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: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4126
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: FsAiReportsComponent, isStandalone: true, selector: "fs-ai-reports", inputs: { basePath: { classPropertyName: "basePath", publicName: "basePath", isSignal: true, isRequired: false, transformFunction: null }, openPattern: { classPropertyName: "openPattern", publicName: "openPattern", isSignal: true, isRequired: false, transformFunction: null }, createPattern: { classPropertyName: "createPattern", publicName: "createPattern", isSignal: true, isRequired: false, transformFunction: null } }, viewQueries: [{ propertyName: "list", first: true, predicate: FsListComponent, descendants: true }], ngImport: i0, template: "<fs-list\n [config]=\"listConfig\"\n #list>\n\n <fs-list-column title=\"Name\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <!-- A deleted report can't be opened (the backend only assembles active\n ones), so in Show Deleted mode the name is plain text \u2014 restore it\n from the row menu first. -->\n @if (row.state === deletedState) {\n {{ row.name }}\n } @else {\n <a [routerLink]=\"openLink(row)\">{{ row.name }}</a>\n }\n </ng-template>\n </fs-list-column>\n\n <fs-list-column title=\"Modified\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date [date]=\"row.modifyDate\"></fs-date>\n </ng-template>\n </fs-list-column>\n\n</fs-list>\n", styles: ["a{cursor:pointer}\n"], dependencies: [{ kind: "ngmodule", type: FsDateModule }, { kind: "component", type: i2$4.FsDateComponent, selector: "fs-date", inputs: ["date", "format", "timezone"] }, { 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: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4078
4127
  }
4079
4128
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FsAiReportsComponent, decorators: [{
4080
4129
  type: Component,
@@ -4082,7 +4131,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
4082
4131
  FsDateModule,
4083
4132
  FsListModule,
4084
4133
  RouterLink,
4085
- ], template: "<fs-list\n [config]=\"listConfig\"\n #list>\n\n <fs-list-column title=\"Name\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <a [routerLink]=\"openLink(row)\">{{ row.name }}</a>\n </ng-template>\n </fs-list-column>\n\n <fs-list-column title=\"Modified\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date [date]=\"row.modifyDate\"></fs-date>\n </ng-template>\n </fs-list-column>\n\n</fs-list>\n", styles: ["a{cursor:pointer}\n"] }]
4134
+ ], template: "<fs-list\n [config]=\"listConfig\"\n #list>\n\n <fs-list-column title=\"Name\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <!-- A deleted report can't be opened (the backend only assembles active\n ones), so in Show Deleted mode the name is plain text \u2014 restore it\n from the row menu first. -->\n @if (row.state === deletedState) {\n {{ row.name }}\n } @else {\n <a [routerLink]=\"openLink(row)\">{{ row.name }}</a>\n }\n </ng-template>\n </fs-list-column>\n\n <fs-list-column title=\"Modified\">\n <ng-template\n fs-list-cell\n let-row=\"row\">\n <fs-date [date]=\"row.modifyDate\"></fs-date>\n </ng-template>\n </fs-list-column>\n\n</fs-list>\n", styles: ["a{cursor:pointer}\n"] }]
4086
4135
  }], ctorParameters: () => [], propDecorators: { list: [{
4087
4136
  type: ViewChild,
4088
4137
  args: [FsListComponent]
@@ -4340,7 +4389,7 @@ class FsAiReportComponent {
4340
4389
  ReportPptxService,
4341
4390
  ReportPdfService,
4342
4391
  // Tree-shaken ECharts core + the 'report' house theme, loaded lazily.
4343
- provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-F254vpF1.mjs').then((module) => module.default) }),
4392
+ provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-CMOBB-Er.mjs').then((module) => module.default) }),
4344
4393
  ], viewQueries: [{ propertyName: "_split", first: true, predicate: ["split"], descendants: true, static: true }, { propertyName: "_chatPanel", first: true, predicate: ["chatPanel"], descendants: true, read: ElementRef, static: true }], ngImport: i0, template: "<div class=\"fs-ai-report fs-column\">\n\n <div class=\"fs-ai-report__header fs-row.align-center\">\n <h2 class=\"fs-ai-report__title fs-flex\">{{ report?.name }}</h2>\n\n @if (report) {\n <!-- Report-level filters, inline with the toolbar actions. fs-filter\n reads its config once at init, so it's keyed on the filter\n signature: when the report-level filter set changes the block is\n recreated and re-reads the rebuilt config. -->\n @if (reportHasFilters) {\n @for (key of [reportFilterKey]; track key) {\n <fs-filter\n class=\"fs-ai-report__filters\"\n [config]=\"reportFilterConfig\">\n </fs-filter>\n }\n }\n\n <button\n mat-icon-button\n type=\"button\"\n [matTooltip]=\"editMode ? 'Done' : 'Edit layout'\"\n (click)=\"toggleEditMode()\">\n <mat-icon>{{ editMode ? 'lock' : 'open_with' }}</mat-icon>\n </button>\n\n <button\n mat-icon-button\n type=\"button\"\n matTooltip=\"Export\"\n [fsMenuTriggerFor]=\"exportMenu\">\n <mat-icon>download</mat-icon>\n </button>\n <fs-menu #exportMenu>\n <ng-template\n fs-menu-item\n (click)=\"exportPowerpoint()\">\n Export PowerPoint\n </ng-template>\n <ng-template\n fs-menu-item\n (click)=\"exportPdf()\">\n Export PDF\n </ng-template>\n </fs-menu>\n\n <button\n mat-icon-button\n type=\"button\"\n matTooltip=\"Report settings\"\n (click)=\"reportSettings()\">\n <mat-icon>settings</mat-icon>\n </button>\n }\n </div>\n\n <div\n #split\n class=\"fs-ai-report__split fs-row.align-start\">\n <fs-ai-chat\n #chatPanel\n class=\"chat\"\n [basePath]=\"basePath()\"\n [requestData]=\"{ reportId: reportId() }\"\n (response)=\"onChatResponse($event)\">\n </fs-ai-chat>\n\n <div\n class=\"resizer\"\n (pointerdown)=\"onResizeStart($event)\">\n </div>\n\n <div class=\"viewer fs-flex fs-column\">\n @if (report) {\n <app-report-canvas\n [report]=\"report\"\n [editMode]=\"editMode\"\n (componentSettings)=\"componentSettings($event)\"\n (reportChanged)=\"onCanvasReportChanged()\"\n (editDone)=\"toggleEditMode()\">\n </app-report-canvas>\n }\n </div>\n </div>\n</div>\n", styles: [".fs-ai-report{height:100%;min-height:500px;display:flex;flex-direction:column}.fs-ai-report__header{flex:0 0 auto;margin-bottom:10px}.fs-ai-report__title{margin:0;min-width:120px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.fs-ai-report__filters{flex:0 1 auto;min-width:0;display:block;margin:0 5px 0 0}.fs-ai-report__filters ::ng-deep .filter-bar-container{align-items:center!important}.fs-ai-report__filters ::ng-deep .mat-mdc-form-field-subscript-wrapper{display:none}.fs-ai-report__split{flex:1 1 auto;min-height:0}.fs-ai-report .chat{display:block;flex:0 0 25%;width:100%;height:100%;min-height:400px;min-width:0;border:none}.fs-ai-report .viewer{display:flex;flex-direction:column;min-width:0;height:100%;overflow:hidden}.fs-ai-report .resizer{flex:0 0 11px;align-self:stretch;display:flex;justify-content:center;cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none}.fs-ai-report .resizer:before{content:\"\";width:3px;border-radius:3px;background:transparent;transition:background-color .12s ease}.fs-ai-report .resizer:hover:before{background:var(--brand-primary-color)}.fs-ai-report__split.resizing{cursor:col-resize;-webkit-user-select:none;user-select:none}.fs-ai-report__split.resizing .resizer:before{background:var(--brand-primary-color)}.fs-ai-report__split.resizing .chat,.fs-ai-report__split.resizing .viewer{pointer-events:none}\n"], dependencies: [{ kind: "ngmodule", type: FsFilterModule }, { kind: "component", type: i2.FilterComponent, selector: "fs-filter", inputs: ["config"], outputs: ["closed", "opened", "ready"] }, { kind: "ngmodule", type: FsMenuModule }, { kind: "component", type: i2$3.FsMenuComponent, selector: "fs-menu", inputs: ["class", "buttonClass", "buttonType", "buttonColor"], outputs: ["opened", "closed"] }, { kind: "directive", type: i2$3.FsMenuItemDirective, selector: "fs-menu-group,[fs-menu-item]" }, { kind: "directive", type: i2$3.FsMenuTriggerDirective, selector: "[fsMenuTriggerFor]", inputs: ["fsMenuTriggerFor"] }, { kind: "component", type: FsAiChatComponent, selector: "fs-ai-chat", inputs: ["basePath", "requestData", "introMessage"], outputs: ["response"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "component", type: i3$1.MatIconButton, selector: "button[mat-icon-button]", exportAs: ["matButton"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i4$2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i2$5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "component", type: ReportCanvasComponent, selector: "app-report-canvas", inputs: ["report", "editMode"], outputs: ["componentSettings", "reportChanged", "editDone"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4345
4394
  }
4346
4395
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FsAiReportComponent, decorators: [{
@@ -4353,7 +4402,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
4353
4402
  ReportPptxService,
4354
4403
  ReportPdfService,
4355
4404
  // Tree-shaken ECharts core + the 'report' house theme, loaded lazily.
4356
- provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-F254vpF1.mjs').then((module) => module.default) }),
4405
+ provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-CMOBB-Er.mjs').then((module) => module.default) }),
4357
4406
  ], imports: [
4358
4407
  FsFilterModule,
4359
4408
  FsMenuModule,
@@ -4383,5 +4432,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
4383
4432
  * Generated bundle index. Do not edit.
4384
4433
  */
4385
4434
 
4386
- export { FsAiReportsComponent as F, REPORT_CHART_COLORS_CSS as R, ReportComponent as a, FsAiReportComponent as b, ReportData as c, ReportService as d, ReportFilterStateService as e, FREQUENCY_OPTIONS as f };
4387
- //# sourceMappingURL=firestitch-report-firestitch-report-Dh8kteJk.mjs.map
4435
+ export { FsAiReportsComponent as F, REPORT_CHART_COLORS_CSS as R, ReportComponent as a, FsAiReportComponent as b, ReportData as c, ReportService as d, ReportFilterStateService as e, FREQUENCY_OPTIONS as f, ReportState as g };
4436
+ //# sourceMappingURL=firestitch-report-firestitch-report-DwgbMhwr.mjs.map