@firestitch/report 18.0.18 → 18.0.19
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.
- package/app/reports/dialogs/global-settings/components/semantic-database/semantic-database.component.d.ts +5 -3
- package/app/reports/export/report-export-collector.service.d.ts +1 -0
- package/app/reports/format.d.ts +1 -1
- package/app/reports/interfaces/report.interface.d.ts +1 -0
- package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +2 -2
- package/esm2022/app/reports/dialogs/global-settings/components/semantic-database/semantic-database.component.mjs +11 -6
- package/esm2022/app/reports/export/report-export-collector.service.mjs +31 -11
- package/esm2022/app/reports/export/report-pdf.service.mjs +2 -2
- package/esm2022/app/reports/export/report-pptx.service.mjs +2 -2
- package/esm2022/app/reports/format.mjs +21 -6
- package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
- package/esm2022/app/reports/services/report-filter-state.service.mjs +17 -2
- package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +2 -2
- package/esm2022/app/reports/views/report/report.component.mjs +2 -2
- package/fesm2022/{firestitch-report-echarts-CMOBB-Er.mjs → firestitch-report-echarts-CfwgLaOA.mjs} +2 -2
- package/fesm2022/{firestitch-report-echarts-CMOBB-Er.mjs.map → firestitch-report-echarts-CfwgLaOA.mjs.map} +1 -1
- package/fesm2022/{firestitch-report-firestitch-report-DwgbMhwr.mjs → firestitch-report-firestitch-report-_MCMM4XH.mjs} +86 -32
- package/fesm2022/firestitch-report-firestitch-report-_MCMM4XH.mjs.map +1 -0
- package/fesm2022/firestitch-report.mjs +1 -1
- package/package.json +1 -1
- package/fesm2022/firestitch-report-firestitch-report-DwgbMhwr.mjs.map +0 -1
|
@@ -27,7 +27,7 @@ import { FsZoomPanComponent, FsZoomPanModule } from '@firestitch/zoom-pan';
|
|
|
27
27
|
import { FsApi, StreamEventType } from '@firestitch/api';
|
|
28
28
|
import * as i1$1 from '@angular/material/menu';
|
|
29
29
|
import { MatMenuModule } from '@angular/material/menu';
|
|
30
|
-
import { format, startOfYear, startOfQuarter, startOfMonth, subMonths, subDays, parseISO, isValid } from 'date-fns';
|
|
30
|
+
import { format, startOfYear, startOfQuarter, startOfMonth, subMonths, subDays, subWeeks, startOfWeek, endOfWeek, parseISO, isValid } from 'date-fns';
|
|
31
31
|
import { DatePipe } from '@angular/common';
|
|
32
32
|
import * as i1 from '@firestitch/list';
|
|
33
33
|
import { PaginationStrategy, FsListComponent, FsListModule } from '@firestitch/list';
|
|
@@ -629,6 +629,21 @@ class ReportFilterStateService {
|
|
|
629
629
|
_relativeRange(relative) {
|
|
630
630
|
const now = new Date();
|
|
631
631
|
switch (relative) {
|
|
632
|
+
// A calendar week, Sunday to Saturday, in whole days — not the rolling
|
|
633
|
+
// seven days `last7Days` gives, which never lines up with the week a
|
|
634
|
+
// partner has already been sent. `lastWeek` is the one a weekly report
|
|
635
|
+
// wants: it ends at endOfWeek rather than at `now`, because the week it
|
|
636
|
+
// names has closed. `thisWeek` follows every other preset here and runs
|
|
637
|
+
// up to now, so it is deliberately a part-finished week.
|
|
638
|
+
case 'thisWeek':
|
|
639
|
+
return { start: startOfWeek(now, { weekStartsOn: 0 }), end: now };
|
|
640
|
+
case 'lastWeek': {
|
|
641
|
+
const previous = subWeeks(now, 1);
|
|
642
|
+
return {
|
|
643
|
+
start: startOfWeek(previous, { weekStartsOn: 0 }),
|
|
644
|
+
end: endOfWeek(previous, { weekStartsOn: 0 }),
|
|
645
|
+
};
|
|
646
|
+
}
|
|
632
647
|
case 'last7Days':
|
|
633
648
|
return { start: subDays(now, 7), end: now };
|
|
634
649
|
case 'last30Days':
|
|
@@ -993,9 +1008,20 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
993
1008
|
}] } });
|
|
994
1009
|
|
|
995
1010
|
// Measure-value formatting shared by the KPI renderer and the exports — the
|
|
996
|
-
// config's `format` (number | percent | currency)
|
|
997
|
-
// screen, in PowerPoint and in PDF.
|
|
998
|
-
|
|
1011
|
+
// config's `format` (number | percent | currency) and `precision` mean the same
|
|
1012
|
+
// thing on screen, in PowerPoint and in PDF.
|
|
1013
|
+
// A bare `new Intl.NumberFormat()` defaults to maximumFractionDigits: 3, which
|
|
1014
|
+
// is why an unconfigured percentage reads 38.298%. When the measure names a
|
|
1015
|
+
// precision it is pinned as BOTH the minimum and the maximum, so a column of
|
|
1016
|
+
// rates lines up instead of each value showing however many decimals it happens
|
|
1017
|
+
// to need. Undefined leaves the locale default alone, so a report authored
|
|
1018
|
+
// before precision existed renders exactly as it did.
|
|
1019
|
+
function getFractionDigits(precision) {
|
|
1020
|
+
return Number.isFinite(precision)
|
|
1021
|
+
? { minimumFractionDigits: precision, maximumFractionDigits: precision }
|
|
1022
|
+
: {};
|
|
1023
|
+
}
|
|
1024
|
+
function formatMeasureValue(value, format, precision) {
|
|
999
1025
|
if (value === null || value === undefined || value === '') {
|
|
1000
1026
|
return '—';
|
|
1001
1027
|
}
|
|
@@ -1003,17 +1029,21 @@ function formatMeasureValue(value, format) {
|
|
|
1003
1029
|
if (!Number.isFinite(numeric)) {
|
|
1004
1030
|
return String(value);
|
|
1005
1031
|
}
|
|
1032
|
+
const fractionDigits = getFractionDigits(precision);
|
|
1006
1033
|
switch (format) {
|
|
1007
1034
|
case 'percent':
|
|
1008
|
-
return `${new Intl.NumberFormat().format(numeric)}%`;
|
|
1035
|
+
return `${new Intl.NumberFormat(undefined, fractionDigits).format(numeric)}%`;
|
|
1009
1036
|
case 'currency':
|
|
1010
1037
|
return new Intl.NumberFormat(undefined, {
|
|
1011
1038
|
style: 'currency',
|
|
1012
1039
|
currency: 'USD',
|
|
1040
|
+
// Whole dollars unless the measure asks for decimals — cents were
|
|
1041
|
+
// unrepresentable before, because this was hardcoded to 0.
|
|
1013
1042
|
maximumFractionDigits: 0,
|
|
1043
|
+
...fractionDigits,
|
|
1014
1044
|
}).format(numeric);
|
|
1015
1045
|
default:
|
|
1016
|
-
return new Intl.NumberFormat().format(numeric);
|
|
1046
|
+
return new Intl.NumberFormat(undefined, fractionDigits).format(numeric);
|
|
1017
1047
|
}
|
|
1018
1048
|
}
|
|
1019
1049
|
|
|
@@ -1033,7 +1063,7 @@ class ComponentKpiComponent {
|
|
|
1033
1063
|
return;
|
|
1034
1064
|
}
|
|
1035
1065
|
const column = config.measure?.column ?? Object.keys(row)[0];
|
|
1036
|
-
this.value = formatMeasureValue(row[column], config.measure?.format);
|
|
1066
|
+
this.value = formatMeasureValue(row[column], config.measure?.format, config.measure?.precision);
|
|
1037
1067
|
}
|
|
1038
1068
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentKpiComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1039
1069
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentKpiComponent, isStandalone: true, selector: "app-report-component-kpi", inputs: { component: "component", data: "data" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"kpi\">\n <div class=\"kpi-value\">{{ value }}</div>\n @if (label) {\n <div class=\"kpi-label\">{{ label }}</div>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%}.kpi{width:100%;height:100%;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px}.kpi .kpi-value{font-size:34px;font-weight:600;color:#1f2933;line-height:1}.kpi .kpi-label{font-size:12px;color:#7b8794}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
@@ -2526,8 +2556,10 @@ class ReportExportCollectorService {
|
|
|
2526
2556
|
}
|
|
2527
2557
|
});
|
|
2528
2558
|
const all$ = requests.length ? forkJoin(requests) : of([]);
|
|
2529
|
-
|
|
2530
|
-
|
|
2559
|
+
// The summary rides alongside the component data rather than being built at
|
|
2560
|
+
// the end, because naming a select filter's values is itself a request.
|
|
2561
|
+
return forkJoin({ collected: all$, filterSummary: this._filterSummary(report) })
|
|
2562
|
+
.pipe(map$1(({ collected, filterSummary }) => {
|
|
2531
2563
|
const pages = report.pages.map((page) => ({ page, components: [] }));
|
|
2532
2564
|
collected.forEach((item, index) => {
|
|
2533
2565
|
pages[slots[index].pageIndex].components.push(item);
|
|
@@ -2535,7 +2567,7 @@ class ReportExportCollectorService {
|
|
|
2535
2567
|
return {
|
|
2536
2568
|
report,
|
|
2537
2569
|
pages,
|
|
2538
|
-
filterSummary
|
|
2570
|
+
filterSummary,
|
|
2539
2571
|
};
|
|
2540
2572
|
}));
|
|
2541
2573
|
}
|
|
@@ -2551,8 +2583,12 @@ class ReportExportCollectorService {
|
|
|
2551
2583
|
return this._reportData.componentData(report.id, component.id, filters, state)
|
|
2552
2584
|
.pipe(map$1((data) => ({ component, data })), catchError(() => of({ component, data: null })));
|
|
2553
2585
|
}
|
|
2554
|
-
// "Report Period: Jun 12, 2025 – Jun 12, 2026", "Organization:
|
|
2555
|
-
// line per filter group that has an active session value.
|
|
2586
|
+
// "Report Period: Jun 12, 2025 – Jun 12, 2026", "Organization: Alnylam - AHP,
|
|
2587
|
+
// Alnylam - PH1" — one line per filter group that has an active session value.
|
|
2588
|
+
//
|
|
2589
|
+
// A select group stores ids, so its line has to be named off the option list
|
|
2590
|
+
// before it can be printed; a date or keyword group already holds its own
|
|
2591
|
+
// display value and resolves synchronously.
|
|
2556
2592
|
_filterSummary(report) {
|
|
2557
2593
|
const lines = [];
|
|
2558
2594
|
for (const group of report.filterGroups ?? []) {
|
|
@@ -2562,21 +2598,34 @@ class ReportExportCollectorService {
|
|
|
2562
2598
|
}
|
|
2563
2599
|
const label = group.label || 'Filter';
|
|
2564
2600
|
if (value.start || value.end) {
|
|
2565
|
-
lines.push(`${label}: ${this._date(value.start)} – ${this._date(value.end)}`);
|
|
2601
|
+
lines.push(of(`${label}: ${this._date(value.start)} – ${this._date(value.end)}`));
|
|
2566
2602
|
}
|
|
2567
2603
|
else if (value.values?.length) {
|
|
2568
|
-
lines.push(
|
|
2604
|
+
lines.push(this._selectLine(label, group, report.id, value.values));
|
|
2569
2605
|
}
|
|
2570
2606
|
else if (value.value?.trim()) {
|
|
2571
|
-
lines.push(`${label}: "${value.value.trim()}"`);
|
|
2607
|
+
lines.push(of(`${label}: "${value.value.trim()}"`));
|
|
2572
2608
|
}
|
|
2573
2609
|
}
|
|
2574
2610
|
const frequency = this._filterState.frequency();
|
|
2575
2611
|
if (frequency) {
|
|
2576
2612
|
const option = FREQUENCY_OPTIONS.find((item) => item.value === frequency);
|
|
2577
|
-
lines.push(`Frequency: ${option?.name ?? frequency}`);
|
|
2613
|
+
lines.push(of(`Frequency: ${option?.name ?? frequency}`));
|
|
2578
2614
|
}
|
|
2579
|
-
return lines;
|
|
2615
|
+
return lines.length ? forkJoin(lines) : of([]);
|
|
2616
|
+
}
|
|
2617
|
+
// One select group's line, with its stored ids resolved to the same names the
|
|
2618
|
+
// on-screen chips show — a cover reading "Organization: 8774, 8777" tells the
|
|
2619
|
+
// client nothing about what the report covers.
|
|
2620
|
+
//
|
|
2621
|
+
// Uses the report bar's own loader and resolver so the two can't drift, which
|
|
2622
|
+
// also means a value whose entity was deleted keeps showing its raw id rather
|
|
2623
|
+
// than dropping off the cover and silently understating the filter. A failed
|
|
2624
|
+
// option fetch degrades the whole line to ids for the same reason: an export
|
|
2625
|
+
// must never fail on a cosmetic lookup.
|
|
2626
|
+
_selectLine(label, group, reportId, values) {
|
|
2627
|
+
return resolveOptionValues(loadGroupOptions(group, this._reportData, reportId), values)
|
|
2628
|
+
.pipe(map$1((resolved) => `${label}: ${resolved.map((item) => item.name).join(', ')}`), catchError(() => of(`${label}: ${values.map((item) => String(item)).join(', ')}`)));
|
|
2580
2629
|
}
|
|
2581
2630
|
_date(value) {
|
|
2582
2631
|
if (!value) {
|
|
@@ -2599,7 +2648,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
2599
2648
|
// complete synchronously after setOption.
|
|
2600
2649
|
async function renderChartImage(component, data, width, height, pixelRatio = 3) {
|
|
2601
2650
|
// The same tree-shaken echarts build + 'report' theme the live canvas uses.
|
|
2602
|
-
const echarts = (await import('./firestitch-report-echarts-
|
|
2651
|
+
const echarts = (await import('./firestitch-report-echarts-CfwgLaOA.mjs')).default;
|
|
2603
2652
|
const host = document.createElement('div');
|
|
2604
2653
|
host.style.width = `${width}px`;
|
|
2605
2654
|
host.style.height = `${height}px`;
|
|
@@ -2738,7 +2787,7 @@ class ReportPdfService {
|
|
|
2738
2787
|
const config = component.config;
|
|
2739
2788
|
const row = data.rows[0] ?? {};
|
|
2740
2789
|
const column = config.measure?.column ?? Object.keys(row)[0];
|
|
2741
|
-
const value = formatMeasureValue(row[column], config.measure?.format);
|
|
2790
|
+
const value = formatMeasureValue(row[column], config.measure?.format, config.measure?.precision);
|
|
2742
2791
|
doc.setFont('helvetica', 'bold');
|
|
2743
2792
|
doc.setFontSize(26);
|
|
2744
2793
|
doc.setTextColor('#1f2933');
|
|
@@ -2968,7 +3017,7 @@ class ReportPptxService {
|
|
|
2968
3017
|
const config = component.config;
|
|
2969
3018
|
const row = data.rows[0] ?? {};
|
|
2970
3019
|
const column = config.measure?.column ?? Object.keys(row)[0];
|
|
2971
|
-
const value = formatMeasureValue(row[column], config.measure?.format);
|
|
3020
|
+
const value = formatMeasureValue(row[column], config.measure?.format, config.measure?.precision);
|
|
2972
3021
|
slide.addText([
|
|
2973
3022
|
{ text: value, options: { fontSize: 28, bold: true, color: '1F2933', breakLine: true } },
|
|
2974
3023
|
{ text: config.measure?.label ?? '', options: { fontSize: 10, color: '7B8794' } },
|
|
@@ -3345,8 +3394,8 @@ class ReportComponent {
|
|
|
3345
3394
|
ReportPdfService,
|
|
3346
3395
|
// Tree-shaken ECharts core + the 'report' house theme, loaded lazily with
|
|
3347
3396
|
// this route's chunk.
|
|
3348
|
-
provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-
|
|
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 });
|
|
3397
|
+
provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-CfwgLaOA.mjs').then((module) => module.default) }),
|
|
3398
|
+
], 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", "showThinking"], outputs: ["response", "showThinkingChange"] }, { 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 });
|
|
3350
3399
|
}
|
|
3351
3400
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ReportComponent, decorators: [{
|
|
3352
3401
|
type: Component,
|
|
@@ -3359,7 +3408,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
3359
3408
|
ReportPdfService,
|
|
3360
3409
|
// Tree-shaken ECharts core + the 'report' house theme, loaded lazily with
|
|
3361
3410
|
// this route's chunk.
|
|
3362
|
-
provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-
|
|
3411
|
+
provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-CfwgLaOA.mjs').then((module) => module.default) }),
|
|
3363
3412
|
], imports: [
|
|
3364
3413
|
FormsModule,
|
|
3365
3414
|
FsAutocompleteChipsModule,
|
|
@@ -3567,6 +3616,10 @@ class SemanticDatabaseComponent {
|
|
|
3567
3616
|
K: 'Stopped',
|
|
3568
3617
|
F: 'Failed',
|
|
3569
3618
|
};
|
|
3619
|
+
// The streamed frames that carry a line for the feed: progress, and the final
|
|
3620
|
+
// frame the backend sends when a run ends badly. Without the error kind the
|
|
3621
|
+
// feed stops on the last progress line and never says what went wrong.
|
|
3622
|
+
static LOG_KINDS = ['log', 'error'];
|
|
3570
3623
|
// A row that is still owed content says so; a built one says nothing. On a
|
|
3571
3624
|
// finished build every stage is done on every row, so chipping them all was
|
|
3572
3625
|
// noise that buried the one row that mattered.
|
|
@@ -3706,7 +3759,7 @@ class SemanticDatabaseComponent {
|
|
|
3706
3759
|
// A hard stream/transport failure (the build couldn't even start)
|
|
3707
3760
|
// finalizes here — completed$ won't fire in that case.
|
|
3708
3761
|
tap({ error: (error) => this._finalizeBuild(error) }), filter((event) => event?.type === StreamEventType.Data
|
|
3709
|
-
&& event.data?.kind
|
|
3762
|
+
&& SemanticDatabaseComponent.LOG_KINDS.includes(event.data?.kind)
|
|
3710
3763
|
&& typeof event.data.line === 'string'), map((event) => event.data.line));
|
|
3711
3764
|
this._process
|
|
3712
3765
|
.run('Semantic database build', target$)
|
|
@@ -3718,9 +3771,10 @@ class SemanticDatabaseComponent {
|
|
|
3718
3771
|
* Wrap up one build run exactly once. On a hard stream error, surface the
|
|
3719
3772
|
* actual server-side reason pulled off the broken stream — the generic
|
|
3720
3773
|
* "could not run" line only when the failure carried no server text at all;
|
|
3721
|
-
* otherwise refresh the status and announce how the build actually ended
|
|
3722
|
-
* build
|
|
3723
|
-
*
|
|
3774
|
+
* otherwise refresh the status and announce how the build actually ended. A
|
|
3775
|
+
* failed build always names its reason on the row (the backend records one for
|
|
3776
|
+
* every way a run can die, fatals included), and that reason must surface
|
|
3777
|
+
* instead of the run silently doing nothing.
|
|
3724
3778
|
*/
|
|
3725
3779
|
_finalizeBuild(streamError) {
|
|
3726
3780
|
if (this._buildFinalized) {
|
|
@@ -3732,7 +3786,7 @@ class SemanticDatabaseComponent {
|
|
|
3732
3786
|
const detail = this._streamErrorDetail(streamError);
|
|
3733
3787
|
this._message.error(detail
|
|
3734
3788
|
? `The semantic database build failed — ${detail}`
|
|
3735
|
-
: 'The semantic database build could not run —
|
|
3789
|
+
: 'The semantic database build could not run — the connection to the server was lost.');
|
|
3736
3790
|
this._refreshStatus();
|
|
3737
3791
|
return;
|
|
3738
3792
|
}
|
|
@@ -4389,8 +4443,8 @@ class FsAiReportComponent {
|
|
|
4389
4443
|
ReportPptxService,
|
|
4390
4444
|
ReportPdfService,
|
|
4391
4445
|
// Tree-shaken ECharts core + the 'report' house theme, loaded lazily.
|
|
4392
|
-
provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-
|
|
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 });
|
|
4446
|
+
provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-CfwgLaOA.mjs').then((module) => module.default) }),
|
|
4447
|
+
], 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", "showThinking"], outputs: ["response", "showThinkingChange"] }, { 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 });
|
|
4394
4448
|
}
|
|
4395
4449
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: FsAiReportComponent, decorators: [{
|
|
4396
4450
|
type: Component,
|
|
@@ -4402,7 +4456,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4402
4456
|
ReportPptxService,
|
|
4403
4457
|
ReportPdfService,
|
|
4404
4458
|
// Tree-shaken ECharts core + the 'report' house theme, loaded lazily.
|
|
4405
|
-
provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-
|
|
4459
|
+
provideEchartsCore({ echarts: () => import('./firestitch-report-echarts-CfwgLaOA.mjs').then((module) => module.default) }),
|
|
4406
4460
|
], imports: [
|
|
4407
4461
|
FsFilterModule,
|
|
4408
4462
|
FsMenuModule,
|
|
@@ -4433,4 +4487,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImpo
|
|
|
4433
4487
|
*/
|
|
4434
4488
|
|
|
4435
4489
|
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-
|
|
4490
|
+
//# sourceMappingURL=firestitch-report-firestitch-report-_MCMM4XH.mjs.map
|