@nova-ui/dashboards
Version:
Nova Dashboards is a framework designed to provide feature developers with a common solution for presenting data coming from various sources within a single view, as well as a set of predefined widget visualizations that are 100% configuration-driven and
344 lines • 14.7 kB
JavaScript
"use strict";
// © 2022 SolarWinds Worldwide, LLC. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
Object.defineProperty(exports, "__esModule", { value: true });
exports.XYChartComponent = void 0;
const tslib_1 = require("tslib");
const core_1 = require("@angular/core");
// eslint-disable-next-line import/no-deprecated
const rxjs_1 = require("rxjs");
const operators_1 = require("rxjs/operators");
const bits_1 = require("@nova-ui/bits");
const charts_1 = require("@nova-ui/charts");
const types_1 = require("../../../../services/types");
const types_2 = require("../../../../types");
const legend_1 = require("../../../../widget-types/common/widget/legend");
const timeseries_helpers_1 = require("../../timeseries-helpers");
const timeseries_scales_service_1 = require("../../timeseries-scales.service");
const public_api_1 = require("../../transformer/public-api");
const types_3 = require("../../types");
const timeseries_chart_component_1 = require("../timeseries-chart.component");
let XYChartComponent = class XYChartComponent extends timeseries_chart_component_1.TimeseriesChartComponent {
constructor(eventBus, dataSource, timeseriesScalesService, changeDetector) {
super(eventBus, timeseriesScalesService, dataSource);
this.eventBus = eventBus;
this.timeseriesScalesService = timeseriesScalesService;
this.changeDetector = changeDetector;
this.valueAccessorKey = "y";
this.collectionId = "";
this.timeseriesChartTypes = types_3.TimeseriesChartTypes;
this.summaryLegendBcgColor = timeseries_helpers_1.SUMMARY_LEGEND_BCG_COLOR;
this.summaryLegendColor = timeseries_helpers_1.SUMMARY_LEGEND_COLOR;
this.transformers = new Map([
[
types_3.TimeseriesTransformer.None,
{ displayName: $localize `None`, transformer: undefined },
],
[
types_3.TimeseriesTransformer.ChangePoint,
{
displayName: $localize `Change Point`,
transformer: public_api_1.transformChangePoint,
},
],
[
types_3.TimeseriesTransformer.Difference,
{
displayName: $localize `Difference`,
transformer: public_api_1.transformDifference,
},
],
[
types_3.TimeseriesTransformer.FloatingAverage,
{
displayName: $localize `Floating Average`,
transformer: public_api_1.transformFloatingAverage,
},
],
[
types_3.TimeseriesTransformer.Linear,
{ displayName: $localize `Linear`, transformer: public_api_1.transformLinReg },
],
[
types_3.TimeseriesTransformer.Normalize,
{
displayName: $localize `Normalize`,
transformer: public_api_1.transformNormalize,
},
],
[
types_3.TimeseriesTransformer.PercentileStd,
{
displayName: $localize `Percentile Standardized`,
transformer: public_api_1.transformPercentileStd,
},
],
[
types_3.TimeseriesTransformer.Smoothing,
{
displayName: $localize `Smoothing`,
transformer: public_api_1.transformLoessSmoothing,
},
],
[
types_3.TimeseriesTransformer.LoessStandardize,
{
displayName: $localize `Smoothing Standardized`,
transformer: public_api_1.transformLoessStandardize,
},
],
[
types_3.TimeseriesTransformer.Standardize,
{
displayName: $localize `Standardize`,
transformer: public_api_1.transformStandardize,
},
],
]);
}
mapSeriesSet(data, scales) {
const yScales = [scales.y];
if (scales.yRight) {
yScales.push(scales.yRight);
}
const dataMapped = data.map((series) => {
// matches scale units to the metric unit for either left y-axis scale or right y-axis scale
let yScale = yScales.find((yScale) => yScale.scaleUnits === series.metricUnits);
if (!yScale) {
yScale =
yScales.find((yScale) => yScale.scaleUnits === "generic") ?? scales.y;
}
return {
...series,
scales: {
x: scales.x,
y: yScale,
},
renderer: this.renderer,
accessors: this.accessors,
};
});
if (this.widgetData.summarySerie) {
this.summarySerie = {
...this.widgetData.summarySerie,
accessors: new charts_1.XYAccessors(),
renderer: new charts_1.XYRenderer({
ignoreForDomainCalculation: true,
}),
scales: {
x: scales.x,
y: scales.y,
},
showInLegend: false,
preprocess: false,
};
dataMapped.push(this.summarySerie);
}
return dataMapped;
}
/** Checks if legend should be shown. */
hasLegend() {
return (this.configuration.legendPlacement &&
this.configuration.legendPlacement !== legend_1.LegendPlacement.None);
}
/** Checks if legend should be aligned to right. */
legendShouldBeAlignedRight() {
return this.configuration.legendPlacement === legend_1.LegendPlacement.Right;
}
onPrimaryDescClick(event, legendSeries) {
if (!this.seriesInteractive) {
return;
}
event.stopPropagation();
this.eventBus.getStream(types_1.INTERACTION).next({
payload: {
data: legendSeries,
interactionType: types_3.TimeseriesInteractionType.Series,
},
});
}
/** Updates chart data. */
updateChartData() {
const grid = this.chartAssist.chart.getGrid();
if (this.scales.y?.id) {
grid.leftScaleId = this.scales.y.id;
}
if ((this.scales.yRight && this.widgetData.series.length === 1) ||
(this.scales.y &&
this.scales.yRight &&
this.scales.y.scaleUnits === this.scales.yRight.scaleUnits)) {
// if there is only one series to display, or if the left y-axis and right y-axis have the same units, both y-axises are same
this.scales.yRight = this.scales.y;
grid.rightScaleId = this.scales.y.id;
}
else {
if (this.scales.yRight?.id) {
grid.rightScaleId = this.scales.yRight.id;
}
}
const gridConfig = grid.config();
// hides botom axis if it's not last chart in the group
gridConfig.axis.bottom.visible = !this.configuration?.hasAdjacentChart;
gridConfig.borders.bottom.visible =
!this.configuration?.hasAdjacentChart;
this.chartAssist.update(this.mapSeriesSet(this.widgetData.series, this.scales));
}
/**
* Initialize chart
*/
buildChart() {
this.buildChart$.next();
const colorProvider = this.configuration.chartColors &&
this.configuration.chartColors?.length > 0
? new charts_1.SequentialColorProvider(this.configuration.chartColors)
: (0, charts_1.defaultColorProvider)();
const palette = new charts_1.ChartPalette(colorProvider);
this.accessors = this.createAccessors(palette.standardColors);
this.chartAssist = this.createChartAssist(palette);
const chart = this.chartAssist.chart;
const gridConfig = chart.getGrid().config();
if (this.configuration.gridConfig?.xAxisTicksCount) {
gridConfig.axis.bottom.approximateTicks =
this.configuration.gridConfig.xAxisTicksCount;
}
if (gridConfig.dimension.marginLocked &&
this.configuration.gridConfig?.sideMarginLocked) {
gridConfig.dimension.marginLocked.left = true;
gridConfig.dimension.marginLocked.right = true;
}
if (this.configuration.gridConfig?.sideMargin) {
gridConfig.dimension.margin.left =
this.configuration.gridConfig.sideMargin;
gridConfig.dimension.margin.right =
this.configuration.gridConfig.sideMargin;
}
if (this.configuration.enableZoom && this.zoomPlugins.length) {
chart.addPlugin(this.zoomPlugins[0]);
}
chart
.getEventBus()
.getStream(charts_1.SET_DOMAIN_EVENT)
// eslint-disable-next-line import/no-deprecated
.pipe((0, operators_1.takeUntil)((0, rxjs_1.merge)(this.destroy$, this.buildChart$)))
.subscribe((event) => {
const payload = event.data;
const newDomain = payload[Object.keys(payload)[0]];
this.eventBus.getStream(types_1.SET_TIMEFRAME).next({
payload: {
startDatetime: newDomain[0],
endDatetime: newDomain[1],
selectedPresetId: undefined,
},
});
});
this.setupInteraction();
}
/**
* Subscribe to chart events and emit
*/
setupInteraction() {
// interaction with chart data points
this.chartAssist.chart
.getEventBus()
.getStream(charts_1.INTERACTION_DATA_POINTS_EVENT)
// eslint-disable-next-line import/no-deprecated
.pipe((0, operators_1.takeUntil)((0, rxjs_1.merge)(this.destroy$, this.buildChart$)))
.subscribe((values) => {
const payload = values.data;
if (payload.interactionType === charts_1.InteractionType.Click) {
this.eventBus.getStream(types_1.INTERACTION).next({
payload: {
data: payload.dataPoints,
interactionType: types_3.TimeseriesInteractionType.DataPoints,
},
});
}
});
// interaction with values
this.chartAssist.chart
.getEventBus()
.getStream(charts_1.INTERACTION_VALUES_EVENT)
// eslint-disable-next-line import/no-deprecated
.pipe((0, operators_1.takeUntil)((0, rxjs_1.merge)(this.destroy$, this.buildChart$)))
.subscribe((values) => {
const payload = values.data;
if (payload.interactionType === charts_1.InteractionType.Click) {
this.eventBus.getStream(types_1.INTERACTION).next({
payload: {
data: payload.values,
interactionType: types_3.TimeseriesInteractionType.Values,
},
});
}
});
}
displayLegendMenu() {
return (this.configuration.preset === types_3.TimeseriesChartPreset.Line &&
!!this.configuration.allowLegendMenu &&
this.configuration.projectType ===
types_3.TimeseriesWidgetProjectType.PerfstackApp);
}
displayDeleteButton() {
return (this.configuration.preset !== types_3.TimeseriesChartPreset.Line &&
!!this.configuration.allowLegendMenu &&
this.configuration.projectType ===
types_3.TimeseriesWidgetProjectType.PerfstackApp);
}
transformData(metricId, trId) {
const serie = this.widgetData.series.find((s) => s.id === metricId);
if (!serie) {
return;
}
serie.transformer = this.transformers.get(trId)?.transformer;
if (serie.rawData) {
if (serie.transformer === undefined) {
// revert transformed data
serie.data = serie.rawData;
this.updateYAxisDomain();
}
else {
this.transformSeriesData(serie);
}
}
this.updateChartData();
}
getLegendValue(legendSeries, valueAccessorKey) {
const val = this.chartAssist.getHighlightedValue(legendSeries, "y", "tick", valueAccessorKey);
if (this.configuration.projectType ===
types_3.TimeseriesWidgetProjectType.PerfstackApp &&
this.configuration.preset === types_3.TimeseriesChartPreset.StackedArea &&
this.configuration.units === "percent") {
const submetricsCount = this.chartAssist.legendSeriesSet.length;
const strVal = `${val ?? 0}`;
return `${parseFloat(strVal ?? "0") * submetricsCount} %`;
}
return val;
}
};
exports.XYChartComponent = XYChartComponent;
exports.XYChartComponent = XYChartComponent = tslib_1.__decorate([
(0, core_1.Injectable)(),
tslib_1.__param(0, (0, core_1.Inject)(types_2.PIZZAGNA_EVENT_BUS)),
tslib_1.__param(1, (0, core_1.Optional)()),
tslib_1.__param(1, (0, core_1.Inject)(types_2.DATA_SOURCE)),
tslib_1.__metadata("design:paramtypes", [bits_1.EventBus, Object, timeseries_scales_service_1.TimeseriesScalesService,
core_1.ChangeDetectorRef])
], XYChartComponent);
//# sourceMappingURL=xy-chart.component.js.map