@firestitch/report 18.6.1 → 18.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/reports/components/component-chart/component-chart.component.d.ts +6 -7
- package/app/reports/components/component-kpi/component-kpi.component.d.ts +17 -9
- package/app/reports/components/component-kpi/components/sparkline/sparkline.component.d.ts +8 -0
- package/app/reports/components/component-list/component-list.component.d.ts +39 -10
- package/app/reports/components/component-note/component-note.component.d.ts +12 -0
- package/app/reports/components/report-canvas/report-canvas.component.d.ts +0 -10
- package/app/reports/components/report-component/report-component.component.d.ts +5 -12
- package/app/reports/data/report.data.d.ts +2 -3
- package/app/reports/dialogs/component-settings/component-settings.component.d.ts +34 -2
- package/app/reports/dialogs/list-columns/list-columns.component.d.ts +23 -0
- package/app/reports/dialogs/report-settings/report-locale-patch.d.ts +5 -0
- package/app/reports/dialogs/report-settings/report-settings.component.d.ts +20 -2
- package/app/reports/enums/report-change-polarity.enum.d.ts +5 -0
- package/app/reports/enums/report-chart-color.enum.d.ts +12 -0
- package/app/reports/enums/report-chart-data-labels.enum.d.ts +6 -0
- package/app/reports/enums/report-chart-date-label.enum.d.ts +5 -0
- package/app/reports/enums/report-chart-line-style.enum.d.ts +5 -0
- package/app/reports/enums/report-chart-mark-stat.enum.d.ts +6 -0
- package/app/reports/enums/report-kpi-trend.enum.d.ts +5 -0
- package/app/reports/enums/report-list-column-format.enum.d.ts +6 -0
- package/app/reports/enums/report-number-units.enum.d.ts +6 -0
- package/app/reports/enums/report-value-format.enum.d.ts +5 -0
- package/app/reports/export/offscreen-chart.d.ts +2 -2
- package/app/reports/export/report-export-collector.service.d.ts +37 -8
- package/app/reports/export/report-pdf.service.d.ts +6 -0
- package/app/reports/export/report-pptx.service.d.ts +24 -0
- package/app/reports/format.d.ts +64 -3
- package/app/reports/interfaces/report-chat-viewer-filter.interface.d.ts +2 -0
- package/app/reports/interfaces/report.interface.d.ts +205 -14
- package/app/reports/kpi-card.d.ts +48 -0
- package/app/reports/layout.d.ts +0 -9
- package/app/reports/list-config.d.ts +16 -0
- package/app/reports/option-builder.d.ts +76 -9
- package/app/reports/output-notes.d.ts +14 -0
- package/app/reports/pipes/report-date.pipe.d.ts +2 -1
- package/app/reports/pipes/report-number.pipe.d.ts +8 -0
- package/app/reports/pipes/report-output.pipe.d.ts +10 -0
- package/app/reports/report-filter-items.d.ts +5 -2
- package/app/reports/report-url-state.d.ts +4 -0
- package/app/reports/services/report-filter-state.service.d.ts +27 -2
- package/app/reports/theme/palette.d.ts +6 -0
- package/app/reports/theme/typography.d.ts +2 -0
- package/esm2022/app/reports/components/component-chart/component-chart.component.mjs +23 -20
- package/esm2022/app/reports/components/component-kpi/component-kpi.component.mjs +56 -29
- package/esm2022/app/reports/components/component-kpi/components/sparkline/sparkline.component.mjs +19 -0
- package/esm2022/app/reports/components/component-list/component-list.component.mjs +218 -32
- package/esm2022/app/reports/components/component-note/component-note.component.mjs +30 -0
- package/esm2022/app/reports/components/report-canvas/report-canvas.component.mjs +7 -61
- package/esm2022/app/reports/components/report-component/report-component.component.mjs +99 -100
- package/esm2022/app/reports/data/report.data.mjs +20 -7
- package/esm2022/app/reports/dialogs/component-settings/component-settings.component.mjs +133 -13
- package/esm2022/app/reports/dialogs/list-columns/list-columns.component.mjs +56 -0
- package/esm2022/app/reports/dialogs/report-settings/report-locale-patch.mjs +13 -0
- package/esm2022/app/reports/dialogs/report-settings/report-settings.component.mjs +138 -20
- package/esm2022/app/reports/enums/report-change-polarity.enum.mjs +11 -0
- package/esm2022/app/reports/enums/report-chart-color.enum.mjs +19 -0
- package/esm2022/app/reports/enums/report-chart-data-labels.enum.mjs +13 -0
- package/esm2022/app/reports/enums/report-chart-date-label.enum.mjs +13 -0
- package/esm2022/app/reports/enums/report-chart-line-style.enum.mjs +12 -0
- package/esm2022/app/reports/enums/report-chart-mark-stat.enum.mjs +12 -0
- package/esm2022/app/reports/enums/report-kpi-trend.enum.mjs +10 -0
- package/esm2022/app/reports/enums/report-list-column-format.enum.mjs +14 -0
- package/esm2022/app/reports/enums/report-number-units.enum.mjs +14 -0
- package/esm2022/app/reports/enums/report-value-format.enum.mjs +13 -0
- package/esm2022/app/reports/export/offscreen-chart.mjs +5 -4
- package/esm2022/app/reports/export/report-export-collector.service.mjs +186 -40
- package/esm2022/app/reports/export/report-pdf.service.mjs +332 -67
- package/esm2022/app/reports/export/report-pptx.service.mjs +765 -106
- package/esm2022/app/reports/format.mjs +917 -57
- package/esm2022/app/reports/interfaces/report-chat-viewer-filter.interface.mjs +1 -1
- package/esm2022/app/reports/interfaces/report.interface.mjs +1 -1
- package/esm2022/app/reports/kpi-card.mjs +174 -0
- package/esm2022/app/reports/layout.mjs +1 -46
- package/esm2022/app/reports/list-config.mjs +106 -0
- package/esm2022/app/reports/option-builder.mjs +1457 -117
- package/esm2022/app/reports/output-notes.mjs +158 -0
- package/esm2022/app/reports/pipes/report-date.pipe.mjs +7 -6
- package/esm2022/app/reports/pipes/report-number.pipe.mjs +25 -0
- package/esm2022/app/reports/pipes/report-output.pipe.mjs +28 -0
- package/esm2022/app/reports/report-filter-items.mjs +28 -3
- package/esm2022/app/reports/report-url-state.mjs +56 -15
- package/esm2022/app/reports/services/report-filter-state.service.mjs +274 -22
- package/esm2022/app/reports/theme/echarts.mjs +8 -2
- package/esm2022/app/reports/theme/palette.mjs +35 -1
- package/esm2022/app/reports/theme/typography.mjs +8 -1
- package/esm2022/app/reports/views/report/fs-ai-report.component.mjs +2 -2
- package/esm2022/app/reports/views/report/report.component.mjs +3 -4
- package/esm2022/public_api.mjs +10 -1
- package/fesm2022/{firestitch-report-echarts-Djtmaxj1.mjs → firestitch-report-echarts-qCBE3LqM.mjs} +9 -3
- package/fesm2022/firestitch-report-echarts-qCBE3LqM.mjs.map +1 -0
- package/fesm2022/{firestitch-report-firestitch-report-D3zseBZc.mjs → firestitch-report-firestitch-report-DbsWbE-j.mjs} +5523 -875
- package/fesm2022/firestitch-report-firestitch-report-DbsWbE-j.mjs.map +1 -0
- package/fesm2022/firestitch-report.mjs +1 -1
- package/package.json +1 -1
- package/public_api.d.ts +9 -0
- package/fesm2022/firestitch-report-echarts-Djtmaxj1.mjs.map +0 -1
- package/fesm2022/firestitch-report-firestitch-report-D3zseBZc.mjs.map +0 -1
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PipeTransform } from '@angular/core';
|
|
2
|
+
import { FormattedOutputValue } from '../format';
|
|
3
|
+
import { ListColumn, ReportFormatContext } from '../interfaces/report.interface';
|
|
4
|
+
import { ListOutputColumn } from '../list-config';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
export declare class ReportOutputPipe implements PipeTransform {
|
|
7
|
+
transform(row: Record<string, unknown> | null | undefined, column: ListColumn, output: ListOutputColumn, context: ReportFormatContext): FormattedOutputValue;
|
|
8
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ReportOutputPipe, never>;
|
|
9
|
+
static ɵpipe: i0.ɵɵPipeDeclaration<ReportOutputPipe, "fsReportOutput", true>;
|
|
10
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { IFilterConfigItem } from '@firestitch/filter';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
import { ReportData } from './data/report.data';
|
|
4
|
-
import { ChartGranularity, FilterGroupValue, Report, ReportFilterGroup } from './interfaces/report.interface';
|
|
4
|
+
import { ChartGranularity, FilterGroupValue, Report, ReportFilterGroup, ReportLocaleTag } from './interfaces/report.interface';
|
|
5
5
|
export declare function dateBoundString(value: Date | string | null | undefined): string | undefined;
|
|
6
|
-
export declare function dateBoundLabel(value: Date | string | null | undefined): string | null;
|
|
6
|
+
export declare function dateBoundLabel(value: Date | string | null | undefined, locale: ReportLocaleTag): string | null;
|
|
7
7
|
export declare function dateFromBound(value: string | null | undefined): Date | null;
|
|
8
8
|
export declare function dateToBound(value: Date | null | undefined): string | null;
|
|
9
9
|
export declare function relativeLabel(relative: string): string;
|
|
@@ -29,6 +29,9 @@ export declare function matchOptions(options$: Observable<{
|
|
|
29
29
|
value: unknown;
|
|
30
30
|
}[]>;
|
|
31
31
|
export declare function filterItemForGroup(group: ReportFilterGroup, reportData: ReportData, reportId: number, initial?: FilterGroupValue): IFilterConfigItem;
|
|
32
|
+
export declare const LIST_SEARCH_ITEM = "listSearch";
|
|
33
|
+
export declare const LIST_SEARCH_MAX_LENGTH = 100;
|
|
34
|
+
export declare function listSearchItem(value: string | null): IFilterConfigItem;
|
|
32
35
|
export declare function hasTimeSeriesChart(report: Report | null): boolean;
|
|
33
36
|
export declare function isGranularityOffered(report: Report, granularity: ChartGranularity | null): boolean;
|
|
34
37
|
export declare function groupByFilterItem(report: Report, initial?: ChartGranularity | null): IFilterConfigItem | null;
|
|
@@ -3,8 +3,12 @@ import { FilterGroupValue, ReportFilterType, ReportSort, ReportUrlParams, Report
|
|
|
3
3
|
export { GROUP_PARAM_PREFIX } from './report-filter-items';
|
|
4
4
|
export declare const LIST_SORT_PARAM_PREFIX = "s";
|
|
5
5
|
export declare const DATE_RANGE_SEPARATOR = "..";
|
|
6
|
+
export declare const LIST_SEARCH_PARAM_PREFIX = "q";
|
|
7
|
+
export declare const LIST_HIDDEN_PARAM_PREFIX = "h";
|
|
6
8
|
export declare const OWNED_PARAM: RegExp;
|
|
7
9
|
export declare function readReportUrlParams(params: ParamMap): ReportUrlParams;
|
|
10
|
+
export declare function encodeColumnList(names: readonly string[]): string;
|
|
11
|
+
export declare function decodeColumnList(raw: string): string[];
|
|
8
12
|
export declare function decodeFilterValue(type: ReportFilterType, raw: string, resolveRelative: (name: string) => {
|
|
9
13
|
start: Date;
|
|
10
14
|
end: Date;
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import { Observable } from 'rxjs';
|
|
2
2
|
import { ReportChatViewerFilter } from '../interfaces/report-chat-viewer-filter.interface';
|
|
3
|
-
import { ChartGranularity, FilterGroupDefault, FilterGroupValue, Report, ReportComponent, ReportFilterGroup, ReportSort, ReportUrlParams, ReportUrlSnapshot, ResolvedFilterValue } from '../interfaces/report.interface';
|
|
3
|
+
import { ChartGranularity, FilterGroupDefault, FilterGroupValue, Report, ReportComponent, ReportFilterGroup, ReportFormatContext, ReportSort, ReportUrlParams, ReportUrlSnapshot, ResolvedFilterValue } from '../interfaces/report.interface';
|
|
4
4
|
import * as i0 from "@angular/core";
|
|
5
5
|
export declare function sameDefault(a: FilterGroupDefault | null, b: FilterGroupDefault | null): boolean;
|
|
6
|
+
export declare function sameFilterValue(a: FilterGroupValue | null | undefined, b: FilterGroupValue | null | undefined): boolean;
|
|
7
|
+
export declare function movedGroupValues(lastReported: Map<number, FilterGroupValue | null>, reported: {
|
|
8
|
+
groupId: number;
|
|
9
|
+
value: FilterGroupValue | null;
|
|
10
|
+
}[]): {
|
|
11
|
+
groupId: number;
|
|
12
|
+
value: FilterGroupValue | null;
|
|
13
|
+
}[];
|
|
14
|
+
export declare function listSearchText(text: string): string;
|
|
6
15
|
export declare function defaultSignature(group: ReportFilterGroup): string;
|
|
7
16
|
export declare class ReportFilterStateService {
|
|
8
17
|
readonly timezone: import("@angular/core").WritableSignal<string>;
|
|
18
|
+
readonly formatContext: import("@angular/core").WritableSignal<ReportFormatContext>;
|
|
19
|
+
readonly listHidden: import("@angular/core").WritableSignal<ReadonlyMap<number, readonly string[]>>;
|
|
9
20
|
private _values;
|
|
10
21
|
private _groups;
|
|
11
22
|
private _sessionDisabled;
|
|
@@ -13,6 +24,10 @@ export declare class ReportFilterStateService {
|
|
|
13
24
|
private _frequency;
|
|
14
25
|
private _frequencyChanged$;
|
|
15
26
|
private _listSorts;
|
|
27
|
+
private _listSearches;
|
|
28
|
+
private _lists;
|
|
29
|
+
private _serverSearches;
|
|
30
|
+
private _listSearchChanged$;
|
|
16
31
|
private _changed$;
|
|
17
32
|
private _urlChanged$;
|
|
18
33
|
init(report: Report, restore?: ReportUrlParams | null): void;
|
|
@@ -26,7 +41,13 @@ export declare class ReportFilterStateService {
|
|
|
26
41
|
setFrequency(frequency: ChartGranularity | null): void;
|
|
27
42
|
frequencyChanges(): Observable<void>;
|
|
28
43
|
listSort(componentId: number): ReportSort | null;
|
|
29
|
-
setListSort(
|
|
44
|
+
setListSort(component: ReportComponent, sort: ReportSort | null): void;
|
|
45
|
+
listSearch(componentId: number): string | null;
|
|
46
|
+
listSearchable(component: ReportComponent): boolean;
|
|
47
|
+
setListSearch(componentId: number, text: string): void;
|
|
48
|
+
hiddenColumns(componentId: number): readonly string[];
|
|
49
|
+
setHiddenColumns(componentId: number, names: readonly string[]): void;
|
|
50
|
+
listSearchChanges(componentId: number): Observable<void>;
|
|
30
51
|
urlChanges(): Observable<void>;
|
|
31
52
|
urlSnapshot(report: Report): ReportUrlSnapshot;
|
|
32
53
|
isFilterDisabled(filterId: number): boolean;
|
|
@@ -36,10 +57,14 @@ export declare class ReportFilterStateService {
|
|
|
36
57
|
viewerFilters(): ReportChatViewerFilter[];
|
|
37
58
|
resolveForReport(report: Report, pageId?: number | null): ResolvedFilterValue[];
|
|
38
59
|
private _resolvedFields;
|
|
60
|
+
private _livePreset;
|
|
39
61
|
private _seed;
|
|
40
62
|
private _restore;
|
|
41
63
|
private _restoreGroups;
|
|
42
64
|
private _restoreListSorts;
|
|
65
|
+
private _restoreListSearches;
|
|
66
|
+
private _restoreListHidden;
|
|
67
|
+
private _dropUnsearchable;
|
|
43
68
|
private _prune;
|
|
44
69
|
private _withPreset;
|
|
45
70
|
private _isDefault;
|
|
@@ -1,4 +1,10 @@
|
|
|
1
|
+
import { ReportChangePolarity } from '../enums/report-change-polarity.enum';
|
|
2
|
+
import { ReportChartColor } from '../enums/report-chart-color.enum';
|
|
1
3
|
import { WaterfallStepKind } from '../interfaces/report.interface';
|
|
2
4
|
export declare const REPORT_CHART_COLORS: string[];
|
|
3
5
|
export declare const REPORT_CHART_COLORS_CSS: string[];
|
|
6
|
+
export declare const REPORT_CHART_COLOR_BY_NAME: Record<ReportChartColor, string>;
|
|
7
|
+
export declare const REPORT_REFERENCE_COLOR = "52606d";
|
|
4
8
|
export declare const REPORT_WATERFALL_COLORS: Record<WaterfallStepKind, string>;
|
|
9
|
+
export declare const REPORT_KPI_CHANGE_COLORS: Record<ReportChangePolarity, string>;
|
|
10
|
+
export declare const REPORT_KPI_SPARKLINE_COLOR: string;
|
|
@@ -1,21 +1,27 @@
|
|
|
1
|
-
import { ChangeDetectionStrategy, Component,
|
|
1
|
+
import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';
|
|
2
2
|
import { NgxEchartsDirective } from 'ngx-echarts';
|
|
3
3
|
import { buildChartOption } from '../../option-builder';
|
|
4
|
+
import { ReportFilterStateService } from '../../services/report-filter-state.service';
|
|
5
|
+
import { ComponentNoteComponent } from '../component-note/component-note.component';
|
|
4
6
|
import * as i0 from "@angular/core";
|
|
5
7
|
// ECharts host for a chart component. Pure rendering: the parent owns the
|
|
6
|
-
// data fetch; this maps (component config, rows
|
|
7
|
-
// chart instance for resize + the future
|
|
8
|
-
// canvas renderer registered in
|
|
8
|
+
// data fetch; this maps (component config, rows, the open report's format
|
|
9
|
+
// context) → option and exposes the chart instance for resize + the future
|
|
10
|
+
// image exports (getDataURL needs the canvas renderer registered in
|
|
11
|
+
// theme/echarts.ts). The shared note under the plot names the days a
|
|
12
|
+
// comparison compares and why windowed series read as they do; the series'
|
|
13
|
+
// tooltips describe the windows themselves.
|
|
9
14
|
export class ComponentChartComponent {
|
|
10
|
-
component;
|
|
11
|
-
data = null;
|
|
12
|
-
options =
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
? buildChartOption(this.component, this.data)
|
|
15
|
+
component = input.required();
|
|
16
|
+
data = input(null);
|
|
17
|
+
options = computed(() => {
|
|
18
|
+
const data = this.data();
|
|
19
|
+
return data
|
|
20
|
+
? buildChartOption(this.component(), data, this._filterState.formatContext())
|
|
17
21
|
: null;
|
|
18
|
-
}
|
|
22
|
+
});
|
|
23
|
+
_chart = null;
|
|
24
|
+
_filterState = inject(ReportFilterStateService);
|
|
19
25
|
onChartInit(chart) {
|
|
20
26
|
this._chart = chart;
|
|
21
27
|
}
|
|
@@ -32,16 +38,13 @@ export class ComponentChartComponent {
|
|
|
32
38
|
}) ?? null;
|
|
33
39
|
}
|
|
34
40
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
35
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "
|
|
41
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.1.0", version: "18.2.14", type: ComponentChartComponent, isStandalone: true, selector: "app-report-component-chart", inputs: { component: { classPropertyName: "component", publicName: "component", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<div\n class=\"chart-host\"\n echarts\n [options]=\"options() ?? {}\"\n [theme]=\"'report'\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\">\n</div>\n<app-report-component-note [data]=\"data()\"></app-report-component-note>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:100%}.chart-host{flex:1 1 0;width:100%;min-height:0}\n"], dependencies: [{ kind: "component", type: ComponentNoteComponent, selector: "app-report-component-note", inputs: ["data", "windows", "windowDescriptions", "windowNotes"] }, { kind: "directive", type: NgxEchartsDirective, selector: "echarts, [echarts]", inputs: ["options", "theme", "initOpts", "merge", "autoResize", "loading", "loadingType", "loadingOpts"], outputs: ["chartInit", "optionsError", "chartClick", "chartDblClick", "chartMouseDown", "chartMouseMove", "chartMouseUp", "chartMouseOver", "chartMouseOut", "chartGlobalOut", "chartContextMenu", "chartHighlight", "chartDownplay", "chartSelectChanged", "chartLegendSelectChanged", "chartLegendSelected", "chartLegendUnselected", "chartLegendLegendSelectAll", "chartLegendLegendInverseSelect", "chartLegendScroll", "chartDataZoom", "chartDataRangeSelected", "chartGraphRoam", "chartGeoRoam", "chartTreeRoam", "chartTimelineChanged", "chartTimelinePlayChanged", "chartRestore", "chartDataViewChanged", "chartMagicTypeChanged", "chartGeoSelectChanged", "chartGeoSelected", "chartGeoUnselected", "chartAxisAreaSelected", "chartBrush", "chartBrushEnd", "chartBrushSelected", "chartGlobalCursorTaken", "chartRendered", "chartFinished"], exportAs: ["echarts"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
36
42
|
}
|
|
37
43
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentChartComponent, decorators: [{
|
|
38
44
|
type: Component,
|
|
39
45
|
args: [{ selector: 'app-report-component-chart', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
46
|
+
ComponentNoteComponent,
|
|
40
47
|
NgxEchartsDirective,
|
|
41
|
-
], template: "<div\n class=\"chart-host\"\n echarts\n [options]=\"options ?? {}\"\n [theme]=\"'report'\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\">\n</div>\n", styles: [":host{display:
|
|
42
|
-
}]
|
|
43
|
-
|
|
44
|
-
}], data: [{
|
|
45
|
-
type: Input
|
|
46
|
-
}] } });
|
|
47
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LWNoYXJ0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9jb21wb25lbnRzL2NvbXBvbmVudC1jaGFydC9jb21wb25lbnQtY2hhcnQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LWNoYXJ0L2NvbXBvbmVudC1jaGFydC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBYSxNQUFNLGVBQWUsQ0FBQztBQUdyRixPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxhQUFhLENBQUM7QUFHbEQsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7O0FBR3hELDBFQUEwRTtBQUMxRSwwRUFBMEU7QUFDMUUsNkVBQTZFO0FBQzdFLG1EQUFtRDtBQVduRCxNQUFNLE9BQU8sdUJBQXVCO0lBRWxCLFNBQVMsQ0FBa0I7SUFDM0IsSUFBSSxHQUF5QixJQUFJLENBQUM7SUFFM0MsT0FBTyxHQUF5QixJQUFJLENBQUM7SUFFcEMsTUFBTSxHQUFtQixJQUFJLENBQUM7SUFFL0IsV0FBVztRQUNoQixJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLElBQUk7WUFDeEMsQ0FBQyxDQUFDLGdCQUFnQixDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUUsSUFBSSxDQUFDLElBQUksQ0FBQztZQUM3QyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ1gsQ0FBQztJQUVNLFdBQVcsQ0FBQyxLQUFjO1FBQy9CLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDO0lBQ3RCLENBQUM7SUFFRCw2REFBNkQ7SUFDdEQsTUFBTTtRQUNYLElBQUksQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUM7SUFDeEIsQ0FBQztJQUVELHdEQUF3RDtJQUNqRCxVQUFVLENBQUMsVUFBVSxHQUFHLENBQUM7UUFDOUIsT0FBTyxJQUFJLENBQUMsTUFBTSxFQUFFLFVBQVUsQ0FBQztZQUM3QixJQUFJLEVBQUUsS0FBSztZQUNYLFVBQVU7WUFDVixlQUFlLEVBQUUsU0FBUztTQUMzQixDQUFDLElBQUksSUFBSSxDQUFDO0lBQ2IsQ0FBQzt3R0EvQlUsdUJBQXVCOzRGQUF2Qix1QkFBdUIsNkpDdkJwQywyS0FRQSwwSURZSSxtQkFBbUI7OzRGQUdWLHVCQUF1QjtrQkFWbkMsU0FBUzsrQkFDRSw0QkFBNEIsbUJBR3JCLHVCQUF1QixDQUFDLE1BQU0sY0FDbkMsSUFBSSxXQUNQO3dCQUNQLG1CQUFtQjtxQkFDcEI7OEJBSWUsU0FBUztzQkFBeEIsS0FBSztnQkFDVSxJQUFJO3NCQUFuQixLQUFLIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgSW5wdXQsIE9uQ2hhbmdlcyB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgdHlwZSB7IEVDaGFydHNPcHRpb24sIEVDaGFydHMgfSBmcm9tICdlY2hhcnRzJztcbmltcG9ydCB7IE5neEVjaGFydHNEaXJlY3RpdmUgfSBmcm9tICduZ3gtZWNoYXJ0cyc7XG5cbmltcG9ydCB7IENvbXBvbmVudERhdGEsIFJlcG9ydENvbXBvbmVudCB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5pbXBvcnQgeyBidWlsZENoYXJ0T3B0aW9uIH0gZnJvbSAnLi4vLi4vb3B0aW9uLWJ1aWxkZXInO1xuXG5cbi8vIEVDaGFydHMgaG9zdCBmb3IgYSBjaGFydCBjb21wb25lbnQuIFB1cmUgcmVuZGVyaW5nOiB0aGUgcGFyZW50IG93bnMgdGhlXG4vLyBkYXRhIGZldGNoOyB0aGlzIG1hcHMgKGNvbXBvbmVudCBjb25maWcsIHJvd3MpIOKGkiBvcHRpb24gYW5kIGV4cG9zZXMgdGhlXG4vLyBjaGFydCBpbnN0YW5jZSBmb3IgcmVzaXplICsgdGhlIGZ1dHVyZSBpbWFnZSBleHBvcnRzIChnZXREYXRhVVJMIG5lZWRzIHRoZVxuLy8gY2FudmFzIHJlbmRlcmVyIHJlZ2lzdGVyZWQgaW4gdGhlbWUvZWNoYXJ0cy50cykuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdhcHAtcmVwb3J0LWNvbXBvbmVudC1jaGFydCcsXG4gIHRlbXBsYXRlVXJsOiAnLi9jb21wb25lbnQtY2hhcnQuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9jb21wb25lbnQtY2hhcnQuY29tcG9uZW50LnNjc3MnXSxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBOZ3hFY2hhcnRzRGlyZWN0aXZlLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBDb21wb25lbnRDaGFydENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcyB7XG5cbiAgQElucHV0KCkgcHVibGljIGNvbXBvbmVudDogUmVwb3J0Q29tcG9uZW50O1xuICBASW5wdXQoKSBwdWJsaWMgZGF0YTogQ29tcG9uZW50RGF0YSB8IG51bGwgPSBudWxsO1xuXG4gIHB1YmxpYyBvcHRpb25zOiBFQ2hhcnRzT3B0aW9uIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSBfY2hhcnQ6IEVDaGFydHMgfCBudWxsID0gbnVsbDtcblxuICBwdWJsaWMgbmdPbkNoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy5vcHRpb25zID0gdGhpcy5jb21wb25lbnQgJiYgdGhpcy5kYXRhXG4gICAgICA/IGJ1aWxkQ2hhcnRPcHRpb24odGhpcy5jb21wb25lbnQsIHRoaXMuZGF0YSlcbiAgICAgIDogbnVsbDtcbiAgfVxuXG4gIHB1YmxpYyBvbkNoYXJ0SW5pdChjaGFydDogRUNoYXJ0cyk6IHZvaWQge1xuICAgIHRoaXMuX2NoYXJ0ID0gY2hhcnQ7XG4gIH1cblxuICAvLyBDYWxsZWQgYnkgdGhlIGNhbnZhcyB3aGVuIHRoZSBib3ggaXMgcmVzaXplZCBpbiBlZGl0IG1vZGUuXG4gIHB1YmxpYyByZXNpemUoKTogdm9pZCB7XG4gICAgdGhpcy5fY2hhcnQ/LnJlc2l6ZSgpO1xuICB9XG5cbiAgLy8gSGlnaC1yZXMgaW1hZ2UgZm9yIHRoZSAobGF0ZXItcGhhc2UpIFBQVC9QREYgZXhwb3J0cy5cbiAgcHVibGljIGdldERhdGFVUkwocGl4ZWxSYXRpbyA9IDMpOiBzdHJpbmcgfCBudWxsIHtcbiAgICByZXR1cm4gdGhpcy5fY2hhcnQ/LmdldERhdGFVUkwoe1xuICAgICAgdHlwZTogJ3BuZycsXG4gICAgICBwaXhlbFJhdGlvLFxuICAgICAgYmFja2dyb3VuZENvbG9yOiAnI2ZmZmZmZicsXG4gICAgfSkgPz8gbnVsbDtcbiAgfVxufVxuIiwiPGRpdlxuICBjbGFzcz1cImNoYXJ0LWhvc3RcIlxuICBlY2hhcnRzXG4gIFtvcHRpb25zXT1cIm9wdGlvbnMgPz8ge31cIlxuICBbdGhlbWVdPVwiJ3JlcG9ydCdcIlxuICBbYXV0b1Jlc2l6ZV09XCJ0cnVlXCJcbiAgKGNoYXJ0SW5pdCk9XCJvbkNoYXJ0SW5pdCgkZXZlbnQpXCI+XG48L2Rpdj5cbiJdfQ==
|
|
48
|
+
], template: "<div\n class=\"chart-host\"\n echarts\n [options]=\"options() ?? {}\"\n [theme]=\"'report'\"\n [autoResize]=\"true\"\n (chartInit)=\"onChartInit($event)\">\n</div>\n<app-report-component-note [data]=\"data()\"></app-report-component-note>\n", styles: [":host{display:flex;flex-direction:column;width:100%;height:100%}.chart-host{flex:1 1 0;width:100%;min-height:0}\n"] }]
|
|
49
|
+
}] });
|
|
50
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LWNoYXJ0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9jb21wb25lbnRzL2NvbXBvbmVudC1jaGFydC9jb21wb25lbnQtY2hhcnQuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LWNoYXJ0L2NvbXBvbmVudC1jaGFydC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFFBQVEsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRzVGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLGFBQWEsQ0FBQztBQUdsRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQztBQUN0RixPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQzs7QUFHcEYsMEVBQTBFO0FBQzFFLDBFQUEwRTtBQUMxRSwyRUFBMkU7QUFDM0Usb0VBQW9FO0FBQ3BFLHFFQUFxRTtBQUNyRSwyRUFBMkU7QUFDM0UsNENBQTRDO0FBWTVDLE1BQU0sT0FBTyx1QkFBdUI7SUFFbEIsU0FBUyxHQUFHLEtBQUssQ0FBQyxRQUFRLEVBQW1CLENBQUM7SUFDOUMsSUFBSSxHQUFHLEtBQUssQ0FBdUIsSUFBSSxDQUFDLENBQUM7SUFFekMsT0FBTyxHQUFHLFFBQVEsQ0FBdUIsR0FBRyxFQUFFO1FBQzVELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUV6QixPQUFPLElBQUk7WUFDVCxDQUFDLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLFNBQVMsRUFBRSxFQUFFLElBQUksRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLGFBQWEsRUFBRSxDQUFDO1lBQzdFLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDWCxDQUFDLENBQUMsQ0FBQztJQUVLLE1BQU0sR0FBbUIsSUFBSSxDQUFDO0lBQ3JCLFlBQVksR0FBRyxNQUFNLENBQUMsd0JBQXdCLENBQUMsQ0FBQztJQUUxRCxXQUFXLENBQUMsS0FBYztRQUMvQixJQUFJLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUN0QixDQUFDO0lBRUQsNkRBQTZEO0lBQ3RELE1BQU07UUFDWCxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sRUFBRSxDQUFDO0lBQ3hCLENBQUM7SUFFRCx3REFBd0Q7SUFDakQsVUFBVSxDQUFDLFVBQVUsR0FBRyxDQUFDO1FBQzlCLE9BQU8sSUFBSSxDQUFDLE1BQU0sRUFBRSxVQUFVLENBQUM7WUFDN0IsSUFBSSxFQUFFLEtBQUs7WUFDWCxVQUFVO1lBQ1YsZUFBZSxFQUFFLFNBQVM7U0FDM0IsQ0FBQyxJQUFJLElBQUksQ0FBQztJQUNiLENBQUM7d0dBaENVLHVCQUF1Qjs0RkFBdkIsdUJBQXVCLDBWQzdCcEMsd1BBU0EsMktEZ0JJLHNCQUFzQix3SUFDdEIsbUJBQW1COzs0RkFHVix1QkFBdUI7a0JBWG5DLFNBQVM7K0JBQ0UsNEJBQTRCLG1CQUdyQix1QkFBdUIsQ0FBQyxNQUFNLGNBQ25DLElBQUksV0FDUDt3QkFDUCxzQkFBc0I7d0JBQ3RCLG1CQUFtQjtxQkFDcEIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSwgQ29tcG9uZW50LCBjb21wdXRlZCwgaW5qZWN0LCBpbnB1dCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgdHlwZSB7IEVDaGFydHNPcHRpb24sIEVDaGFydHMgfSBmcm9tICdlY2hhcnRzJztcbmltcG9ydCB7IE5neEVjaGFydHNEaXJlY3RpdmUgfSBmcm9tICduZ3gtZWNoYXJ0cyc7XG5cbmltcG9ydCB7IENvbXBvbmVudERhdGEsIFJlcG9ydENvbXBvbmVudCB9IGZyb20gJy4uLy4uL2ludGVyZmFjZXMvcmVwb3J0LmludGVyZmFjZSc7XG5pbXBvcnQgeyBidWlsZENoYXJ0T3B0aW9uIH0gZnJvbSAnLi4vLi4vb3B0aW9uLWJ1aWxkZXInO1xuaW1wb3J0IHsgUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvcmVwb3J0LWZpbHRlci1zdGF0ZS5zZXJ2aWNlJztcbmltcG9ydCB7IENvbXBvbmVudE5vdGVDb21wb25lbnQgfSBmcm9tICcuLi9jb21wb25lbnQtbm90ZS9jb21wb25lbnQtbm90ZS5jb21wb25lbnQnO1xuXG5cbi8vIEVDaGFydHMgaG9zdCBmb3IgYSBjaGFydCBjb21wb25lbnQuIFB1cmUgcmVuZGVyaW5nOiB0aGUgcGFyZW50IG93bnMgdGhlXG4vLyBkYXRhIGZldGNoOyB0aGlzIG1hcHMgKGNvbXBvbmVudCBjb25maWcsIHJvd3MsIHRoZSBvcGVuIHJlcG9ydCdzIGZvcm1hdFxuLy8gY29udGV4dCkg4oaSIG9wdGlvbiBhbmQgZXhwb3NlcyB0aGUgY2hhcnQgaW5zdGFuY2UgZm9yIHJlc2l6ZSArIHRoZSBmdXR1cmVcbi8vIGltYWdlIGV4cG9ydHMgKGdldERhdGFVUkwgbmVlZHMgdGhlIGNhbnZhcyByZW5kZXJlciByZWdpc3RlcmVkIGluXG4vLyB0aGVtZS9lY2hhcnRzLnRzKS4gVGhlIHNoYXJlZCBub3RlIHVuZGVyIHRoZSBwbG90IG5hbWVzIHRoZSBkYXlzIGFcbi8vIGNvbXBhcmlzb24gY29tcGFyZXMgYW5kIHdoeSB3aW5kb3dlZCBzZXJpZXMgcmVhZCBhcyB0aGV5IGRvOyB0aGUgc2VyaWVzJ1xuLy8gdG9vbHRpcHMgZGVzY3JpYmUgdGhlIHdpbmRvd3MgdGhlbXNlbHZlcy5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1yZXBvcnQtY29tcG9uZW50LWNoYXJ0JyxcbiAgdGVtcGxhdGVVcmw6ICcuL2NvbXBvbmVudC1jaGFydC5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL2NvbXBvbmVudC1jaGFydC5jb21wb25lbnQuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIENvbXBvbmVudE5vdGVDb21wb25lbnQsXG4gICAgTmd4RWNoYXJ0c0RpcmVjdGl2ZSxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgQ29tcG9uZW50Q2hhcnRDb21wb25lbnQge1xuXG4gIHB1YmxpYyByZWFkb25seSBjb21wb25lbnQgPSBpbnB1dC5yZXF1aXJlZDxSZXBvcnRDb21wb25lbnQ+KCk7XG4gIHB1YmxpYyByZWFkb25seSBkYXRhID0gaW5wdXQ8Q29tcG9uZW50RGF0YSB8IG51bGw+KG51bGwpO1xuXG4gIHB1YmxpYyByZWFkb25seSBvcHRpb25zID0gY29tcHV0ZWQ8RUNoYXJ0c09wdGlvbiB8IG51bGw+KCgpID0+IHtcbiAgICBjb25zdCBkYXRhID0gdGhpcy5kYXRhKCk7XG5cbiAgICByZXR1cm4gZGF0YVxuICAgICAgPyBidWlsZENoYXJ0T3B0aW9uKHRoaXMuY29tcG9uZW50KCksIGRhdGEsIHRoaXMuX2ZpbHRlclN0YXRlLmZvcm1hdENvbnRleHQoKSlcbiAgICAgIDogbnVsbDtcbiAgfSk7XG5cbiAgcHJpdmF0ZSBfY2hhcnQ6IEVDaGFydHMgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSByZWFkb25seSBfZmlsdGVyU3RhdGUgPSBpbmplY3QoUmVwb3J0RmlsdGVyU3RhdGVTZXJ2aWNlKTtcblxuICBwdWJsaWMgb25DaGFydEluaXQoY2hhcnQ6IEVDaGFydHMpOiB2b2lkIHtcbiAgICB0aGlzLl9jaGFydCA9IGNoYXJ0O1xuICB9XG5cbiAgLy8gQ2FsbGVkIGJ5IHRoZSBjYW52YXMgd2hlbiB0aGUgYm94IGlzIHJlc2l6ZWQgaW4gZWRpdCBtb2RlLlxuICBwdWJsaWMgcmVzaXplKCk6IHZvaWQge1xuICAgIHRoaXMuX2NoYXJ0Py5yZXNpemUoKTtcbiAgfVxuXG4gIC8vIEhpZ2gtcmVzIGltYWdlIGZvciB0aGUgKGxhdGVyLXBoYXNlKSBQUFQvUERGIGV4cG9ydHMuXG4gIHB1YmxpYyBnZXREYXRhVVJMKHBpeGVsUmF0aW8gPSAzKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgcmV0dXJuIHRoaXMuX2NoYXJ0Py5nZXREYXRhVVJMKHtcbiAgICAgIHR5cGU6ICdwbmcnLFxuICAgICAgcGl4ZWxSYXRpbyxcbiAgICAgIGJhY2tncm91bmRDb2xvcjogJyNmZmZmZmYnLFxuICAgIH0pID8/IG51bGw7XG4gIH1cbn1cbiIsIjxkaXZcbiAgY2xhc3M9XCJjaGFydC1ob3N0XCJcbiAgZWNoYXJ0c1xuICBbb3B0aW9uc109XCJvcHRpb25zKCkgPz8ge31cIlxuICBbdGhlbWVdPVwiJ3JlcG9ydCdcIlxuICBbYXV0b1Jlc2l6ZV09XCJ0cnVlXCJcbiAgKGNoYXJ0SW5pdCk9XCJvbkNoYXJ0SW5pdCgkZXZlbnQpXCI+XG48L2Rpdj5cbjxhcHAtcmVwb3J0LWNvbXBvbmVudC1ub3RlIFtkYXRhXT1cImRhdGEoKVwiPjwvYXBwLXJlcG9ydC1jb21wb25lbnQtbm90ZT5cbiJdfQ==
|
|
@@ -1,36 +1,63 @@
|
|
|
1
|
-
import { ChangeDetectionStrategy, Component,
|
|
2
|
-
import {
|
|
1
|
+
import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';
|
|
2
|
+
import { ReportChangePolarity } from '../../enums/report-change-polarity.enum';
|
|
3
|
+
import { ReportKpiTrend } from '../../enums/report-kpi-trend.enum';
|
|
4
|
+
import { kpiCardView } from '../../kpi-card';
|
|
5
|
+
import { componentNoteLines } from '../../output-notes';
|
|
6
|
+
import { ReportFilterStateService } from '../../services/report-filter-state.service';
|
|
7
|
+
import { REPORT_KPI_CHANGE_COLORS, REPORT_KPI_SPARKLINE_COLOR } from '../../theme/palette';
|
|
8
|
+
import { REPORT_KPI_VALUE_FONT_SIZE } from '../../theme/typography';
|
|
9
|
+
import { DEFAULT_TEXT_COLOR } from '../../text';
|
|
10
|
+
import { ComponentNoteComponent } from '../component-note/component-note.component';
|
|
11
|
+
import { SparklineComponent } from './components/sparkline/sparkline.component';
|
|
3
12
|
import * as i0 from "@angular/core";
|
|
4
13
|
// A single big number: the component's measure aggregated over all (filtered)
|
|
5
|
-
// rows server-side
|
|
14
|
+
// rows server-side, in the open report's format context (its locale, its
|
|
15
|
+
// currency, and whether a percent arrives as a 0-1 ratio or, from an older
|
|
16
|
+
// server, already x100). With a comparison, a target or a sparkline the server
|
|
17
|
+
// sends every other number the card shows too (ComponentData.kpi); kpi-card.ts
|
|
18
|
+
// decides what each line says, and this only lays them out, in order: the
|
|
19
|
+
// value and its label, the delta, the days, the target and the trend, then the
|
|
20
|
+
// note.
|
|
21
|
+
//
|
|
22
|
+
// The palette's colors and the value's size arrive as custom properties from
|
|
23
|
+
// the same constants the exports draw with. A host page overrides a color by
|
|
24
|
+
// setting --report-kpi-good-color, --report-kpi-bad-color,
|
|
25
|
+
// --report-kpi-neutral-color or --report-kpi-sparkline-color around the report.
|
|
6
26
|
export class ComponentKpiComponent {
|
|
7
|
-
component;
|
|
8
|
-
data = null;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
27
|
+
component = input.required();
|
|
28
|
+
data = input(null);
|
|
29
|
+
ReportKpiTrend = ReportKpiTrend;
|
|
30
|
+
tokens = {
|
|
31
|
+
valueSize: `${REPORT_KPI_VALUE_FONT_SIZE}px`,
|
|
32
|
+
text: DEFAULT_TEXT_COLOR,
|
|
33
|
+
good: `#${REPORT_KPI_CHANGE_COLORS[ReportChangePolarity.Good]}`,
|
|
34
|
+
bad: `#${REPORT_KPI_CHANGE_COLORS[ReportChangePolarity.Bad]}`,
|
|
35
|
+
neutral: `#${REPORT_KPI_CHANGE_COLORS[ReportChangePolarity.Neutral]}`,
|
|
36
|
+
sparkline: `#${REPORT_KPI_SPARKLINE_COLOR}`,
|
|
37
|
+
};
|
|
38
|
+
// Read off the component on every data change rather than through a memo of
|
|
39
|
+
// the config: a settings save repaints the same component object with new
|
|
40
|
+
// KPI keys, then reloads its data.
|
|
41
|
+
view = computed(() => kpiCardView((this.component().config ?? {}), this.data(), { format: this._filterState.formatContext(), timezone: this._filterState.timezone() }));
|
|
42
|
+
// The note sits under the card only when it has something to say, so an
|
|
43
|
+
// empty one takes no room.
|
|
44
|
+
hasNote = computed(() => componentNoteLines(this.data(), { locale: this._filterState.formatContext().locale, timezone: this._filterState.timezone() }, { windows: false, windowDescriptions: true }).length > 0);
|
|
45
|
+
_filterState = inject(ReportFilterStateService);
|
|
25
46
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentKpiComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
26
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentKpiComponent, isStandalone: true, selector: "app-report-component-kpi", inputs: { component: { classPropertyName: "component", publicName: "component", isSignal:
|
|
47
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ComponentKpiComponent, isStandalone: true, selector: "app-report-component-kpi", inputs: { component: { classPropertyName: "component", publicName: "component", isSignal: true, isRequired: true, transformFunction: null }, data: { classPropertyName: "data", publicName: "data", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "style.--report-kpi-value-size": "tokens.valueSize", "style.--report-kpi-text-default": "tokens.text", "style.--report-kpi-good-default": "tokens.good", "style.--report-kpi-bad-default": "tokens.bad", "style.--report-kpi-neutral-default": "tokens.neutral", "style.--report-kpi-sparkline-default": "tokens.sparkline" } }, ngImport: i0, template: "@let card = view();\n<div class=\"kpi fs-column.gap-xs.align-center.justify-center\">\n <div class=\"kpi-value\">{{ card.value }}</div>\n @if (card.label) {\n <div class=\"kpi-label small\">{{ card.label }}</div>\n }\n @if (card.delta; as delta) {\n <div class=\"kpi-delta fs-row.gap-xs.align-baseline.justify-center.wrap\">\n <span\n class=\"kpi-change\"\n [attr.data-tone]=\"delta.tone\">\n @if (delta.trend !== ReportKpiTrend.Flat) {\n <svg\n class=\"kpi-arrow\"\n [class.down]=\"delta.trend === ReportKpiTrend.Down\"\n viewBox=\"0 0 10 10\">\n <polygon points=\"5,1 9.5,9 0.5,9\"></polygon>\n </svg>\n }\n {{ delta.text }}\n </span>\n @if (delta.compared) {\n <span class=\"small\">{{ delta.compared }}</span>\n }\n </div>\n }\n @if (card.window) {\n <div class=\"kpi-line small\">{{ card.window }}</div>\n }\n @if (card.target; as target) {\n <div class=\"kpi-target fs-column.gap-xs.align-center\">\n <div class=\"kpi-line small\">\n {{ target.text }}\n @if (target.progress) {\n \u00B7 {{ target.progress }}\n }\n </div>\n @if (target.fill !== null) {\n <div\n class=\"kpi-progress\"\n [attr.data-tone]=\"target.tone\">\n <div\n class=\"kpi-progress-fill\"\n [style.width.%]=\"target.fill * 100\">\n </div>\n </div>\n }\n </div>\n }\n @if (card.sparkline; as sparkline) {\n <app-component-kpi-sparkline\n class=\"kpi-sparkline\"\n [values]=\"sparkline.values\"\n [partial]=\"sparkline.partial\">\n </app-component-kpi-sparkline>\n }\n <!-- The card prints its own days, so the note leaves them out. A KPI has no\n tooltip, so its note also says what a windowed value is. -->\n @if (hasNote()) {\n <app-report-component-note\n [data]=\"data()\"\n [windows]=\"false\"\n [windowDescriptions]=\"true\">\n </app-report-component-note>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%;--report-kpi-good: var(--report-kpi-good-color, var(--report-kpi-good-default));--report-kpi-bad: var(--report-kpi-bad-color, var(--report-kpi-bad-default));--report-kpi-neutral: var(--report-kpi-neutral-color, var(--report-kpi-neutral-default));--report-kpi-sparkline: var(--report-kpi-sparkline-color, var(--report-kpi-sparkline-default))}.kpi{width:100%;height:100%;overflow:hidden;text-align:center}.kpi .kpi-value{font-size:var(--report-kpi-value-size);font-weight:600;color:var(--report-kpi-text-default);line-height:1}.kpi .kpi-line{max-width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.kpi-change{font-weight:600;white-space:nowrap}.kpi-change[data-tone=good]{color:var(--report-kpi-good)}.kpi-change[data-tone=bad]{color:var(--report-kpi-bad)}.kpi-change[data-tone=neutral]{color:var(--report-kpi-neutral)}.kpi-arrow{width:.7em;height:.7em;fill:currentColor}.kpi-arrow.down{transform:rotate(180deg)}.kpi-delta,.kpi-target{max-width:100%}.kpi-progress{position:relative;width:120px;max-width:100%;height:4px;border-radius:2px;overflow:hidden;color:var(--report-kpi-neutral)}.kpi-progress[data-tone=good]{color:var(--report-kpi-good)}.kpi-progress:before{content:\"\";position:absolute;inset:0;background:currentColor;opacity:.2}.kpi-progress .kpi-progress-fill{position:relative;height:100%;background:currentColor}.kpi-sparkline{max-width:240px;flex:0 0 auto}\n"], dependencies: [{ kind: "component", type: ComponentNoteComponent, selector: "app-report-component-note", inputs: ["data", "windows", "windowDescriptions", "windowNotes"] }, { kind: "component", type: SparklineComponent, selector: "app-component-kpi-sparkline", inputs: ["values", "partial"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
27
48
|
}
|
|
28
49
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ComponentKpiComponent, decorators: [{
|
|
29
50
|
type: Component,
|
|
30
|
-
args: [{ selector: 'app-report-component-kpi', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
51
|
+
args: [{ selector: 'app-report-component-kpi', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, imports: [
|
|
52
|
+
ComponentNoteComponent,
|
|
53
|
+
SparklineComponent,
|
|
54
|
+
], host: {
|
|
55
|
+
'[style.--report-kpi-value-size]': 'tokens.valueSize',
|
|
56
|
+
'[style.--report-kpi-text-default]': 'tokens.text',
|
|
57
|
+
'[style.--report-kpi-good-default]': 'tokens.good',
|
|
58
|
+
'[style.--report-kpi-bad-default]': 'tokens.bad',
|
|
59
|
+
'[style.--report-kpi-neutral-default]': 'tokens.neutral',
|
|
60
|
+
'[style.--report-kpi-sparkline-default]': 'tokens.sparkline',
|
|
61
|
+
}, template: "@let card = view();\n<div class=\"kpi fs-column.gap-xs.align-center.justify-center\">\n <div class=\"kpi-value\">{{ card.value }}</div>\n @if (card.label) {\n <div class=\"kpi-label small\">{{ card.label }}</div>\n }\n @if (card.delta; as delta) {\n <div class=\"kpi-delta fs-row.gap-xs.align-baseline.justify-center.wrap\">\n <span\n class=\"kpi-change\"\n [attr.data-tone]=\"delta.tone\">\n @if (delta.trend !== ReportKpiTrend.Flat) {\n <svg\n class=\"kpi-arrow\"\n [class.down]=\"delta.trend === ReportKpiTrend.Down\"\n viewBox=\"0 0 10 10\">\n <polygon points=\"5,1 9.5,9 0.5,9\"></polygon>\n </svg>\n }\n {{ delta.text }}\n </span>\n @if (delta.compared) {\n <span class=\"small\">{{ delta.compared }}</span>\n }\n </div>\n }\n @if (card.window) {\n <div class=\"kpi-line small\">{{ card.window }}</div>\n }\n @if (card.target; as target) {\n <div class=\"kpi-target fs-column.gap-xs.align-center\">\n <div class=\"kpi-line small\">\n {{ target.text }}\n @if (target.progress) {\n \u00B7 {{ target.progress }}\n }\n </div>\n @if (target.fill !== null) {\n <div\n class=\"kpi-progress\"\n [attr.data-tone]=\"target.tone\">\n <div\n class=\"kpi-progress-fill\"\n [style.width.%]=\"target.fill * 100\">\n </div>\n </div>\n }\n </div>\n }\n @if (card.sparkline; as sparkline) {\n <app-component-kpi-sparkline\n class=\"kpi-sparkline\"\n [values]=\"sparkline.values\"\n [partial]=\"sparkline.partial\">\n </app-component-kpi-sparkline>\n }\n <!-- The card prints its own days, so the note leaves them out. A KPI has no\n tooltip, so its note also says what a windowed value is. -->\n @if (hasNote()) {\n <app-report-component-note\n [data]=\"data()\"\n [windows]=\"false\"\n [windowDescriptions]=\"true\">\n </app-report-component-note>\n }\n</div>\n", styles: [":host{display:block;width:100%;height:100%;--report-kpi-good: var(--report-kpi-good-color, var(--report-kpi-good-default));--report-kpi-bad: var(--report-kpi-bad-color, var(--report-kpi-bad-default));--report-kpi-neutral: var(--report-kpi-neutral-color, var(--report-kpi-neutral-default));--report-kpi-sparkline: var(--report-kpi-sparkline-color, var(--report-kpi-sparkline-default))}.kpi{width:100%;height:100%;overflow:hidden;text-align:center}.kpi .kpi-value{font-size:var(--report-kpi-value-size);font-weight:600;color:var(--report-kpi-text-default);line-height:1}.kpi .kpi-line{max-width:100%;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.kpi-change{font-weight:600;white-space:nowrap}.kpi-change[data-tone=good]{color:var(--report-kpi-good)}.kpi-change[data-tone=bad]{color:var(--report-kpi-bad)}.kpi-change[data-tone=neutral]{color:var(--report-kpi-neutral)}.kpi-arrow{width:.7em;height:.7em;fill:currentColor}.kpi-arrow.down{transform:rotate(180deg)}.kpi-delta,.kpi-target{max-width:100%}.kpi-progress{position:relative;width:120px;max-width:100%;height:4px;border-radius:2px;overflow:hidden;color:var(--report-kpi-neutral)}.kpi-progress[data-tone=good]{color:var(--report-kpi-good)}.kpi-progress:before{content:\"\";position:absolute;inset:0;background:currentColor;opacity:.2}.kpi-progress .kpi-progress-fill{position:relative;height:100%;background:currentColor}.kpi-sparkline{max-width:240px;flex:0 0 auto}\n"] }]
|
|
62
|
+
}] });
|
|
63
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tcG9uZW50LWtwaS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBwL3JlcG9ydHMvY29tcG9uZW50cy9jb21wb25lbnQta3BpL2NvbXBvbmVudC1rcGkuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9yZXBvcnRzL2NvbXBvbmVudHMvY29tcG9uZW50LWtwaS9jb21wb25lbnQta3BpLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFFNUYsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0seUNBQXlDLENBQUM7QUFDL0UsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1DQUFtQyxDQUFDO0FBRW5FLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM3QyxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUN4RCxPQUFPLEVBQUUsd0JBQXdCLEVBQUUsTUFBTSw0Q0FBNEMsQ0FBQztBQUN0RixPQUFPLEVBQUUsd0JBQXdCLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMzRixPQUFPLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNwRSxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFDaEQsT0FBTyxFQUFFLHNCQUFzQixFQUFFLE1BQU0sNENBQTRDLENBQUM7QUFFcEYsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sNENBQTRDLENBQUM7O0FBR2hGLDhFQUE4RTtBQUM5RSx5RUFBeUU7QUFDekUsMkVBQTJFO0FBQzNFLCtFQUErRTtBQUMvRSwrRUFBK0U7QUFDL0UsMEVBQTBFO0FBQzFFLCtFQUErRTtBQUMvRSxRQUFRO0FBQ1IsRUFBRTtBQUNGLDZFQUE2RTtBQUM3RSw2RUFBNkU7QUFDN0UsMkRBQTJEO0FBQzNELGdGQUFnRjtBQW9CaEYsTUFBTSxPQUFPLHFCQUFxQjtJQUVoQixTQUFTLEdBQUcsS0FBSyxDQUFDLFFBQVEsRUFBbUIsQ0FBQztJQUM5QyxJQUFJLEdBQUcsS0FBSyxDQUF1QixJQUFJLENBQUMsQ0FBQztJQUV6QyxjQUFjLEdBQUcsY0FBYyxDQUFDO0lBRWhDLE1BQU0sR0FBRztRQUN2QixTQUFTLEVBQUUsR0FBRywwQkFBMEIsSUFBSTtRQUM1QyxJQUFJLEVBQUUsa0JBQWtCO1FBQ3hCLElBQUksRUFBRSxJQUFJLHdCQUF3QixDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxFQUFFO1FBQy9ELEdBQUcsRUFBRSxJQUFJLHdCQUF3QixDQUFDLG9CQUFvQixDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQzdELE9BQU8sRUFBRSxJQUFJLHdCQUF3QixDQUFDLG9CQUFvQixDQUFDLE9BQU8sQ0FBQyxFQUFFO1FBQ3JFLFNBQVMsRUFBRSxJQUFJLDBCQUEwQixFQUFFO0tBQzVDLENBQUM7SUFFRiw0RUFBNEU7SUFDNUUsMEVBQTBFO0lBQzFFLG1DQUFtQztJQUNuQixJQUFJLEdBQUcsUUFBUSxDQUFDLEdBQUcsRUFBRSxDQUFDLFdBQVcsQ0FDL0MsQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBYyxFQUM1QyxJQUFJLENBQUMsSUFBSSxFQUFFLEVBQ1gsRUFBRSxNQUFNLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUN0RixDQUFDLENBQUM7SUFFSCx3RUFBd0U7SUFDeEUsMkJBQTJCO0lBQ1gsT0FBTyxHQUFHLFFBQVEsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxrQkFBa0IsQ0FDekQsSUFBSSxDQUFDLElBQUksRUFBRSxFQUNYLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxZQUFZLENBQUMsYUFBYSxFQUFFLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxJQUFJLENBQUMsWUFBWSxDQUFDLFFBQVEsRUFBRSxFQUFFLEVBQzVGLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxJQUFJLEVBQUUsQ0FDN0MsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFFRyxZQUFZLEdBQUcsTUFBTSxDQUFDLHdCQUF3QixDQUFDLENBQUM7d0dBakN0RCxxQkFBcUI7NEZBQXJCLHFCQUFxQiwrcUJDaERsQyw0aUVBa0VBLG05Q0Q5Qkksc0JBQXNCLHdJQUN0QixrQkFBa0I7OzRGQVdULHFCQUFxQjtrQkFuQmpDLFNBQVM7K0JBQ0UsMEJBQTBCLG1CQUduQix1QkFBdUIsQ0FBQyxNQUFNLGNBQ25DLElBQUksV0FDUDt3QkFDUCxzQkFBc0I7d0JBQ3RCLGtCQUFrQjtxQkFDbkIsUUFDSzt3QkFDSixpQ0FBaUMsRUFBRSxrQkFBa0I7d0JBQ3JELG1DQUFtQyxFQUFFLGFBQWE7d0JBQ2xELG1DQUFtQyxFQUFFLGFBQWE7d0JBQ2xELGtDQUFrQyxFQUFFLFlBQVk7d0JBQ2hELHNDQUFzQyxFQUFFLGdCQUFnQjt3QkFDeEQsd0NBQXdDLEVBQUUsa0JBQWtCO3FCQUM3RCIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQsIGNvbXB1dGVkLCBpbmplY3QsIGlucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IFJlcG9ydENoYW5nZVBvbGFyaXR5IH0gZnJvbSAnLi4vLi4vZW51bXMvcmVwb3J0LWNoYW5nZS1wb2xhcml0eS5lbnVtJztcbmltcG9ydCB7IFJlcG9ydEtwaVRyZW5kIH0gZnJvbSAnLi4vLi4vZW51bXMvcmVwb3J0LWtwaS10cmVuZC5lbnVtJztcbmltcG9ydCB7IENvbXBvbmVudERhdGEsIEtwaUNvbmZpZywgUmVwb3J0Q29tcG9uZW50IH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9yZXBvcnQuaW50ZXJmYWNlJztcbmltcG9ydCB7IGtwaUNhcmRWaWV3IH0gZnJvbSAnLi4vLi4va3BpLWNhcmQnO1xuaW1wb3J0IHsgY29tcG9uZW50Tm90ZUxpbmVzIH0gZnJvbSAnLi4vLi4vb3V0cHV0LW5vdGVzJztcbmltcG9ydCB7IFJlcG9ydEZpbHRlclN0YXRlU2VydmljZSB9IGZyb20gJy4uLy4uL3NlcnZpY2VzL3JlcG9ydC1maWx0ZXItc3RhdGUuc2VydmljZSc7XG5pbXBvcnQgeyBSRVBPUlRfS1BJX0NIQU5HRV9DT0xPUlMsIFJFUE9SVF9LUElfU1BBUktMSU5FX0NPTE9SIH0gZnJvbSAnLi4vLi4vdGhlbWUvcGFsZXR0ZSc7XG5pbXBvcnQgeyBSRVBPUlRfS1BJX1ZBTFVFX0ZPTlRfU0laRSB9IGZyb20gJy4uLy4uL3RoZW1lL3R5cG9ncmFwaHknO1xuaW1wb3J0IHsgREVGQVVMVF9URVhUX0NPTE9SIH0gZnJvbSAnLi4vLi4vdGV4dCc7XG5pbXBvcnQgeyBDb21wb25lbnROb3RlQ29tcG9uZW50IH0gZnJvbSAnLi4vY29tcG9uZW50LW5vdGUvY29tcG9uZW50LW5vdGUuY29tcG9uZW50JztcblxuaW1wb3J0IHsgU3BhcmtsaW5lQ29tcG9uZW50IH0gZnJvbSAnLi9jb21wb25lbnRzL3NwYXJrbGluZS9zcGFya2xpbmUuY29tcG9uZW50JztcblxuXG4vLyBBIHNpbmdsZSBiaWcgbnVtYmVyOiB0aGUgY29tcG9uZW50J3MgbWVhc3VyZSBhZ2dyZWdhdGVkIG92ZXIgYWxsIChmaWx0ZXJlZClcbi8vIHJvd3Mgc2VydmVyLXNpZGUsIGluIHRoZSBvcGVuIHJlcG9ydCdzIGZvcm1hdCBjb250ZXh0IChpdHMgbG9jYWxlLCBpdHNcbi8vIGN1cnJlbmN5LCBhbmQgd2hldGhlciBhIHBlcmNlbnQgYXJyaXZlcyBhcyBhIDAtMSByYXRpbyBvciwgZnJvbSBhbiBvbGRlclxuLy8gc2VydmVyLCBhbHJlYWR5IHgxMDApLiBXaXRoIGEgY29tcGFyaXNvbiwgYSB0YXJnZXQgb3IgYSBzcGFya2xpbmUgdGhlIHNlcnZlclxuLy8gc2VuZHMgZXZlcnkgb3RoZXIgbnVtYmVyIHRoZSBjYXJkIHNob3dzIHRvbyAoQ29tcG9uZW50RGF0YS5rcGkpOyBrcGktY2FyZC50c1xuLy8gZGVjaWRlcyB3aGF0IGVhY2ggbGluZSBzYXlzLCBhbmQgdGhpcyBvbmx5IGxheXMgdGhlbSBvdXQsIGluIG9yZGVyOiB0aGVcbi8vIHZhbHVlIGFuZCBpdHMgbGFiZWwsIHRoZSBkZWx0YSwgdGhlIGRheXMsIHRoZSB0YXJnZXQgYW5kIHRoZSB0cmVuZCwgdGhlbiB0aGVcbi8vIG5vdGUuXG4vL1xuLy8gVGhlIHBhbGV0dGUncyBjb2xvcnMgYW5kIHRoZSB2YWx1ZSdzIHNpemUgYXJyaXZlIGFzIGN1c3RvbSBwcm9wZXJ0aWVzIGZyb21cbi8vIHRoZSBzYW1lIGNvbnN0YW50cyB0aGUgZXhwb3J0cyBkcmF3IHdpdGguIEEgaG9zdCBwYWdlIG92ZXJyaWRlcyBhIGNvbG9yIGJ5XG4vLyBzZXR0aW5nIC0tcmVwb3J0LWtwaS1nb29kLWNvbG9yLCAtLXJlcG9ydC1rcGktYmFkLWNvbG9yLFxuLy8gLS1yZXBvcnQta3BpLW5ldXRyYWwtY29sb3Igb3IgLS1yZXBvcnQta3BpLXNwYXJrbGluZS1jb2xvciBhcm91bmQgdGhlIHJlcG9ydC5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FwcC1yZXBvcnQtY29tcG9uZW50LWtwaScsXG4gIHRlbXBsYXRlVXJsOiAnLi9jb21wb25lbnQta3BpLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vY29tcG9uZW50LWtwaS5jb21wb25lbnQuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIENvbXBvbmVudE5vdGVDb21wb25lbnQsXG4gICAgU3BhcmtsaW5lQ29tcG9uZW50LFxuICBdLFxuICBob3N0OiB7XG4gICAgJ1tzdHlsZS4tLXJlcG9ydC1rcGktdmFsdWUtc2l6ZV0nOiAndG9rZW5zLnZhbHVlU2l6ZScsXG4gICAgJ1tzdHlsZS4tLXJlcG9ydC1rcGktdGV4dC1kZWZhdWx0XSc6ICd0b2tlbnMudGV4dCcsXG4gICAgJ1tzdHlsZS4tLXJlcG9ydC1rcGktZ29vZC1kZWZhdWx0XSc6ICd0b2tlbnMuZ29vZCcsXG4gICAgJ1tzdHlsZS4tLXJlcG9ydC1rcGktYmFkLWRlZmF1bHRdJzogJ3Rva2Vucy5iYWQnLFxuICAgICdbc3R5bGUuLS1yZXBvcnQta3BpLW5ldXRyYWwtZGVmYXVsdF0nOiAndG9rZW5zLm5ldXRyYWwnLFxuICAgICdbc3R5bGUuLS1yZXBvcnQta3BpLXNwYXJrbGluZS1kZWZhdWx0XSc6ICd0b2tlbnMuc3BhcmtsaW5lJyxcbiAgfSxcbn0pXG5leHBvcnQgY2xhc3MgQ29tcG9uZW50S3BpQ29tcG9uZW50IHtcblxuICBwdWJsaWMgcmVhZG9ubHkgY29tcG9uZW50ID0gaW5wdXQucmVxdWlyZWQ8UmVwb3J0Q29tcG9uZW50PigpO1xuICBwdWJsaWMgcmVhZG9ubHkgZGF0YSA9IGlucHV0PENvbXBvbmVudERhdGEgfCBudWxsPihudWxsKTtcblxuICBwdWJsaWMgcmVhZG9ubHkgUmVwb3J0S3BpVHJlbmQgPSBSZXBvcnRLcGlUcmVuZDtcblxuICBwdWJsaWMgcmVhZG9ubHkgdG9rZW5zID0ge1xuICAgIHZhbHVlU2l6ZTogYCR7UkVQT1JUX0tQSV9WQUxVRV9GT05UX1NJWkV9cHhgLFxuICAgIHRleHQ6IERFRkFVTFRfVEVYVF9DT0xPUixcbiAgICBnb29kOiBgIyR7UkVQT1JUX0tQSV9DSEFOR0VfQ09MT1JTW1JlcG9ydENoYW5nZVBvbGFyaXR5Lkdvb2RdfWAsXG4gICAgYmFkOiBgIyR7UkVQT1JUX0tQSV9DSEFOR0VfQ09MT1JTW1JlcG9ydENoYW5nZVBvbGFyaXR5LkJhZF19YCxcbiAgICBuZXV0cmFsOiBgIyR7UkVQT1JUX0tQSV9DSEFOR0VfQ09MT1JTW1JlcG9ydENoYW5nZVBvbGFyaXR5Lk5ldXRyYWxdfWAsXG4gICAgc3BhcmtsaW5lOiBgIyR7UkVQT1JUX0tQSV9TUEFSS0xJTkVfQ09MT1J9YCxcbiAgfTtcblxuICAvLyBSZWFkIG9mZiB0aGUgY29tcG9uZW50IG9uIGV2ZXJ5IGRhdGEgY2hhbmdlIHJhdGhlciB0aGFuIHRocm91Z2ggYSBtZW1vIG9mXG4gIC8vIHRoZSBjb25maWc6IGEgc2V0dGluZ3Mgc2F2ZSByZXBhaW50cyB0aGUgc2FtZSBjb21wb25lbnQgb2JqZWN0IHdpdGggbmV3XG4gIC8vIEtQSSBrZXlzLCB0aGVuIHJlbG9hZHMgaXRzIGRhdGEuXG4gIHB1YmxpYyByZWFkb25seSB2aWV3ID0gY29tcHV0ZWQoKCkgPT4ga3BpQ2FyZFZpZXcoXG4gICAgKHRoaXMuY29tcG9uZW50KCkuY29uZmlnID8/IHt9KSBhcyBLcGlDb25maWcsXG4gICAgdGhpcy5kYXRhKCksXG4gICAgeyBmb3JtYXQ6IHRoaXMuX2ZpbHRlclN0YXRlLmZvcm1hdENvbnRleHQoKSwgdGltZXpvbmU6IHRoaXMuX2ZpbHRlclN0YXRlLnRpbWV6b25lKCkgfSxcbiAgKSk7XG5cbiAgLy8gVGhlIG5vdGUgc2l0cyB1bmRlciB0aGUgY2FyZCBvbmx5IHdoZW4gaXQgaGFzIHNvbWV0aGluZyB0byBzYXksIHNvIGFuXG4gIC8vIGVtcHR5IG9uZSB0YWtlcyBubyByb29tLlxuICBwdWJsaWMgcmVhZG9ubHkgaGFzTm90ZSA9IGNvbXB1dGVkKCgpID0+IGNvbXBvbmVudE5vdGVMaW5lcyhcbiAgICB0aGlzLmRhdGEoKSxcbiAgICB7IGxvY2FsZTogdGhpcy5fZmlsdGVyU3RhdGUuZm9ybWF0Q29udGV4dCgpLmxvY2FsZSwgdGltZXpvbmU6IHRoaXMuX2ZpbHRlclN0YXRlLnRpbWV6b25lKCkgfSxcbiAgICB7IHdpbmRvd3M6IGZhbHNlLCB3aW5kb3dEZXNjcmlwdGlvbnM6IHRydWUgfSxcbiAgKS5sZW5ndGggPiAwKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9maWx0ZXJTdGF0ZSA9IGluamVjdChSZXBvcnRGaWx0ZXJTdGF0ZVNlcnZpY2UpO1xufVxuIiwiQGxldCBjYXJkID0gdmlldygpO1xuPGRpdiBjbGFzcz1cImtwaSBmcy1jb2x1bW4uZ2FwLXhzLmFsaWduLWNlbnRlci5qdXN0aWZ5LWNlbnRlclwiPlxuICA8ZGl2IGNsYXNzPVwia3BpLXZhbHVlXCI+e3sgY2FyZC52YWx1ZSB9fTwvZGl2PlxuICBAaWYgKGNhcmQubGFiZWwpIHtcbiAgICA8ZGl2IGNsYXNzPVwia3BpLWxhYmVsIHNtYWxsXCI+e3sgY2FyZC5sYWJlbCB9fTwvZGl2PlxuICB9XG4gIEBpZiAoY2FyZC5kZWx0YTsgYXMgZGVsdGEpIHtcbiAgICA8ZGl2IGNsYXNzPVwia3BpLWRlbHRhIGZzLXJvdy5nYXAteHMuYWxpZ24tYmFzZWxpbmUuanVzdGlmeS1jZW50ZXIud3JhcFwiPlxuICAgICAgPHNwYW5cbiAgICAgICAgICBjbGFzcz1cImtwaS1jaGFuZ2VcIlxuICAgICAgICAgIFthdHRyLmRhdGEtdG9uZV09XCJkZWx0YS50b25lXCI+XG4gICAgICAgIEBpZiAoZGVsdGEudHJlbmQgIT09IFJlcG9ydEtwaVRyZW5kLkZsYXQpIHtcbiAgICAgICAgICA8c3ZnXG4gICAgICAgICAgICAgIGNsYXNzPVwia3BpLWFycm93XCJcbiAgICAgICAgICAgICAgW2NsYXNzLmRvd25dPVwiZGVsdGEudHJlbmQgPT09IFJlcG9ydEtwaVRyZW5kLkRvd25cIlxuICAgICAgICAgICAgICB2aWV3Qm94PVwiMCAwIDEwIDEwXCI+XG4gICAgICAgICAgICA8cG9seWdvbiBwb2ludHM9XCI1LDEgOS41LDkgMC41LDlcIj48L3BvbHlnb24+XG4gICAgICAgICAgPC9zdmc+XG4gICAgICAgIH1cbiAgICAgICAge3sgZGVsdGEudGV4dCB9fVxuICAgICAgPC9zcGFuPlxuICAgICAgQGlmIChkZWx0YS5jb21wYXJlZCkge1xuICAgICAgICA8c3BhbiBjbGFzcz1cInNtYWxsXCI+e3sgZGVsdGEuY29tcGFyZWQgfX08L3NwYW4+XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIH1cbiAgQGlmIChjYXJkLndpbmRvdykge1xuICAgIDxkaXYgY2xhc3M9XCJrcGktbGluZSBzbWFsbFwiPnt7IGNhcmQud2luZG93IH19PC9kaXY+XG4gIH1cbiAgQGlmIChjYXJkLnRhcmdldDsgYXMgdGFyZ2V0KSB7XG4gICAgPGRpdiBjbGFzcz1cImtwaS10YXJnZXQgZnMtY29sdW1uLmdhcC14cy5hbGlnbi1jZW50ZXJcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJrcGktbGluZSBzbWFsbFwiPlxuICAgICAgICB7eyB0YXJnZXQudGV4dCB9fVxuICAgICAgICBAaWYgKHRhcmdldC5wcm9ncmVzcykge1xuICAgICAgICAgIMK3IHt7IHRhcmdldC5wcm9ncmVzcyB9fVxuICAgICAgICB9XG4gICAgICA8L2Rpdj5cbiAgICAgIEBpZiAodGFyZ2V0LmZpbGwgIT09IG51bGwpIHtcbiAgICAgICAgPGRpdlxuICAgICAgICAgICAgY2xhc3M9XCJrcGktcHJvZ3Jlc3NcIlxuICAgICAgICAgICAgW2F0dHIuZGF0YS10b25lXT1cInRhcmdldC50b25lXCI+XG4gICAgICAgICAgPGRpdlxuICAgICAgICAgICAgY2xhc3M9XCJrcGktcHJvZ3Jlc3MtZmlsbFwiXG4gICAgICAgICAgICBbc3R5bGUud2lkdGguJV09XCJ0YXJnZXQuZmlsbCAqIDEwMFwiPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIH1cbiAgICA8L2Rpdj5cbiAgfVxuICBAaWYgKGNhcmQuc3BhcmtsaW5lOyBhcyBzcGFya2xpbmUpIHtcbiAgICA8YXBwLWNvbXBvbmVudC1rcGktc3BhcmtsaW5lXG4gICAgICBjbGFzcz1cImtwaS1zcGFya2xpbmVcIlxuICAgICAgW3ZhbHVlc109XCJzcGFya2xpbmUudmFsdWVzXCJcbiAgICAgIFtwYXJ0aWFsXT1cInNwYXJrbGluZS5wYXJ0aWFsXCI+XG4gICAgPC9hcHAtY29tcG9uZW50LWtwaS1zcGFya2xpbmU+XG4gIH1cbiAgPCEtLSBUaGUgY2FyZCBwcmludHMgaXRzIG93biBkYXlzLCBzbyB0aGUgbm90ZSBsZWF2ZXMgdGhlbSBvdXQuIEEgS1BJIGhhcyBub1xuICAgICAgIHRvb2x0aXAsIHNvIGl0cyBub3RlIGFsc28gc2F5cyB3aGF0IGEgd2luZG93ZWQgdmFsdWUgaXMuIC0tPlxuICBAaWYgKGhhc05vdGUoKSkge1xuICAgIDxhcHAtcmVwb3J0LWNvbXBvbmVudC1ub3RlXG4gICAgICBbZGF0YV09XCJkYXRhKClcIlxuICAgICAgW3dpbmRvd3NdPVwiZmFsc2VcIlxuICAgICAgW3dpbmRvd0Rlc2NyaXB0aW9uc109XCJ0cnVlXCI+XG4gICAgPC9hcHAtcmVwb3J0LWNvbXBvbmVudC1ub3RlPlxuICB9XG48L2Rpdj5cbiJdfQ==
|
package/esm2022/app/reports/components/component-kpi/components/sparkline/sparkline.component.mjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ChangeDetectionStrategy, Component, computed, input } from '@angular/core';
|
|
2
|
+
import { kpiSparklineGeometry } from '../../../../kpi-card';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
// A KPI's trend over its last periods: a line that stretches to the card's
|
|
5
|
+
// width, broken where a period has no value, with the last point marked
|
|
6
|
+
// (hollow while its period is still running). The markers are drawn over the
|
|
7
|
+
// line rather than in it, so they stay round however the line is stretched.
|
|
8
|
+
export class SparklineComponent {
|
|
9
|
+
values = input([]);
|
|
10
|
+
partial = input(false);
|
|
11
|
+
geometry = computed(() => kpiSparklineGeometry(this.values(), this.partial()));
|
|
12
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SparklineComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: SparklineComponent, isStandalone: true, selector: "app-component-kpi-sparkline", inputs: { values: { classPropertyName: "values", publicName: "values", isSignal: true, isRequired: false, transformFunction: null }, partial: { classPropertyName: "partial", publicName: "partial", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<svg\n class=\"sparkline-lines\"\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"none\">\n @for (line of geometry().lines; track $index) {\n <polyline [attr.points]=\"line\"></polyline>\n }\n</svg>\n@for (dot of geometry().dots; track $index) {\n <span\n class=\"sparkline-marker\"\n [style.left.%]=\"dot.x\"\n [style.top.%]=\"dot.y\">\n </span>\n}\n@if (geometry().last; as last) {\n <span\n class=\"sparkline-marker\"\n [class.hollow]=\"last.hollow\"\n [style.left.%]=\"last.x\"\n [style.top.%]=\"last.y\">\n </span>\n}\n", styles: [":host{display:block;position:relative;width:calc(100% - 6px);height:28px;margin:3px;color:var(--report-kpi-sparkline)}.sparkline-lines{display:block;width:100%;height:100%;overflow:visible}.sparkline-lines polyline{fill:none;stroke:currentColor;stroke-width:1.5;stroke-linejoin:round;stroke-linecap:round;vector-effect:non-scaling-stroke}.sparkline-marker{position:absolute;box-sizing:border-box;width:6px;height:6px;margin:-3px 0 0 -3px;border:1.5px solid currentColor;border-radius:50%;background:currentColor}.sparkline-marker.hollow{background:Canvas}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
14
|
+
}
|
|
15
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: SparklineComponent, decorators: [{
|
|
16
|
+
type: Component,
|
|
17
|
+
args: [{ selector: 'app-component-kpi-sparkline', changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, template: "<svg\n class=\"sparkline-lines\"\n viewBox=\"0 0 100 100\"\n preserveAspectRatio=\"none\">\n @for (line of geometry().lines; track $index) {\n <polyline [attr.points]=\"line\"></polyline>\n }\n</svg>\n@for (dot of geometry().dots; track $index) {\n <span\n class=\"sparkline-marker\"\n [style.left.%]=\"dot.x\"\n [style.top.%]=\"dot.y\">\n </span>\n}\n@if (geometry().last; as last) {\n <span\n class=\"sparkline-marker\"\n [class.hollow]=\"last.hollow\"\n [style.left.%]=\"last.x\"\n [style.top.%]=\"last.y\">\n </span>\n}\n", styles: [":host{display:block;position:relative;width:calc(100% - 6px);height:28px;margin:3px;color:var(--report-kpi-sparkline)}.sparkline-lines{display:block;width:100%;height:100%;overflow:visible}.sparkline-lines polyline{fill:none;stroke:currentColor;stroke-width:1.5;stroke-linejoin:round;stroke-linecap:round;vector-effect:non-scaling-stroke}.sparkline-marker{position:absolute;box-sizing:border-box;width:6px;height:6px;margin:-3px 0 0 -3px;border:1.5px solid currentColor;border-radius:50%;background:currentColor}.sparkline-marker.hollow{background:Canvas}\n"] }]
|
|
18
|
+
}] });
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhcmtsaW5lLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9jb21wb25lbnRzL2NvbXBvbmVudC1rcGkvY29tcG9uZW50cy9zcGFya2xpbmUvc3BhcmtsaW5lLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9hcHAvcmVwb3J0cy9jb21wb25lbnRzL2NvbXBvbmVudC1rcGkvY29tcG9uZW50cy9zcGFya2xpbmUvc3BhcmtsaW5lLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUVwRixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQzs7QUFHNUQsMkVBQTJFO0FBQzNFLHdFQUF3RTtBQUN4RSw2RUFBNkU7QUFDN0UsNEVBQTRFO0FBUTVFLE1BQU0sT0FBTyxrQkFBa0I7SUFFYixNQUFNLEdBQUcsS0FBSyxDQUFvQixFQUFFLENBQUMsQ0FBQztJQUN0QyxPQUFPLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRXZCLFFBQVEsR0FBRyxRQUFRLENBQUMsR0FBRyxFQUFFLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLE1BQU0sRUFBRSxFQUFFLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLENBQUM7d0dBTHBGLGtCQUFrQjs0RkFBbEIsa0JBQWtCLDRWQ2hCL0Isc2pCQXVCQTs7NEZEUGEsa0JBQWtCO2tCQVA5QixTQUFTOytCQUNFLDZCQUE2QixtQkFHdEIsdUJBQXVCLENBQUMsTUFBTSxjQUNuQyxJQUFJIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgY29tcHV0ZWQsIGlucHV0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IGtwaVNwYXJrbGluZUdlb21ldHJ5IH0gZnJvbSAnLi4vLi4vLi4vLi4va3BpLWNhcmQnO1xuXG5cbi8vIEEgS1BJJ3MgdHJlbmQgb3ZlciBpdHMgbGFzdCBwZXJpb2RzOiBhIGxpbmUgdGhhdCBzdHJldGNoZXMgdG8gdGhlIGNhcmQnc1xuLy8gd2lkdGgsIGJyb2tlbiB3aGVyZSBhIHBlcmlvZCBoYXMgbm8gdmFsdWUsIHdpdGggdGhlIGxhc3QgcG9pbnQgbWFya2VkXG4vLyAoaG9sbG93IHdoaWxlIGl0cyBwZXJpb2QgaXMgc3RpbGwgcnVubmluZykuIFRoZSBtYXJrZXJzIGFyZSBkcmF3biBvdmVyIHRoZVxuLy8gbGluZSByYXRoZXIgdGhhbiBpbiBpdCwgc28gdGhleSBzdGF5IHJvdW5kIGhvd2V2ZXIgdGhlIGxpbmUgaXMgc3RyZXRjaGVkLlxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLWNvbXBvbmVudC1rcGktc3BhcmtsaW5lJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3NwYXJrbGluZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3NwYXJrbGluZS5jb21wb25lbnQuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbn0pXG5leHBvcnQgY2xhc3MgU3BhcmtsaW5lQ29tcG9uZW50IHtcblxuICBwdWJsaWMgcmVhZG9ubHkgdmFsdWVzID0gaW5wdXQ8KG51bWJlciB8IG51bGwpW10+KFtdKTtcbiAgcHVibGljIHJlYWRvbmx5IHBhcnRpYWwgPSBpbnB1dChmYWxzZSk7XG5cbiAgcHVibGljIHJlYWRvbmx5IGdlb21ldHJ5ID0gY29tcHV0ZWQoKCkgPT4ga3BpU3BhcmtsaW5lR2VvbWV0cnkodGhpcy52YWx1ZXMoKSwgdGhpcy5wYXJ0aWFsKCkpKTtcbn1cbiIsIjxzdmdcbiAgICBjbGFzcz1cInNwYXJrbGluZS1saW5lc1wiXG4gICAgdmlld0JveD1cIjAgMCAxMDAgMTAwXCJcbiAgICBwcmVzZXJ2ZUFzcGVjdFJhdGlvPVwibm9uZVwiPlxuICBAZm9yIChsaW5lIG9mIGdlb21ldHJ5KCkubGluZXM7IHRyYWNrICRpbmRleCkge1xuICAgIDxwb2x5bGluZSBbYXR0ci5wb2ludHNdPVwibGluZVwiPjwvcG9seWxpbmU+XG4gIH1cbjwvc3ZnPlxuQGZvciAoZG90IG9mIGdlb21ldHJ5KCkuZG90czsgdHJhY2sgJGluZGV4KSB7XG4gIDxzcGFuXG4gICAgY2xhc3M9XCJzcGFya2xpbmUtbWFya2VyXCJcbiAgICBbc3R5bGUubGVmdC4lXT1cImRvdC54XCJcbiAgICBbc3R5bGUudG9wLiVdPVwiZG90LnlcIj5cbiAgPC9zcGFuPlxufVxuQGlmIChnZW9tZXRyeSgpLmxhc3Q7IGFzIGxhc3QpIHtcbiAgPHNwYW5cbiAgICBjbGFzcz1cInNwYXJrbGluZS1tYXJrZXJcIlxuICAgIFtjbGFzcy5ob2xsb3ddPVwibGFzdC5ob2xsb3dcIlxuICAgIFtzdHlsZS5sZWZ0LiVdPVwibGFzdC54XCJcbiAgICBbc3R5bGUudG9wLiVdPVwibGFzdC55XCI+XG4gIDwvc3Bhbj5cbn1cbiJdfQ==
|