@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
308 lines • 13.8 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.DrilldownWidgetTestComponent = exports.DrilldownDataSource = void 0;
const tslib_1 = require("tslib");
const http_1 = require("@angular/common/http");
const core_1 = require("@angular/core");
const cloneDeep_1 = tslib_1.__importDefault(require("lodash/cloneDeep"));
const groupBy_1 = tslib_1.__importDefault(require("lodash/groupBy"));
const rxjs_1 = require("rxjs");
// eslint-disable-next-line import/no-deprecated
const operators_1 = require("rxjs/operators");
const bits_1 = require("@nova-ui/bits");
const dashboards_1 = require("@nova-ui/dashboards");
const data_mock_1 = require("./data-mock");
const unit_test_registry_service_1 = require("../../../src/lib/services/unit-test-registry.service");
/**
* A simple KPI data source to retrieve the average rating of Harry Potter and the Sorcerer's Stone (book) via googleapis
*/
let DrilldownDataSource = class DrilldownDataSource extends bits_1.DataSourceService {
// This is the ID we'll use to identify the provider
static { this.providerId = "DrilldownDataSource"; }
constructor() {
super();
this.random = Math.random();
// Use this subject to communicate the data source's busy state
this.busy = new rxjs_1.BehaviorSubject(false);
this.applyFilters$ = new rxjs_1.Subject();
this.groupedDataHistory = [];
this.applyFilters$
// eslint-disable-next-line import/no-deprecated
.pipe((0, operators_1.switchMap)((filters) => this.getData(filters)))
.subscribe(async (res) => {
this.outputsSubject.next(await this.getFilteredData(res));
});
}
// In this example, getFilteredData is invoked every 10 minutes (Take a look at the refresher
// provider definition in the widget configuration below to see how the interval is set)
async getFilteredData(data) {
return (0, rxjs_1.of)(data)
.pipe(
// eslint-disable-next-line import/no-deprecated
(0, operators_1.map)((countries) => {
const widgetInput = this.getOutput(countries);
if (this.isDrillDown()) {
const activeDrillLvl = this.drillState.length;
const group = this.groupBy[activeDrillLvl];
const [lastGroupedValue, groupedData] = this.getTransformedDataForGroup(widgetInput, group);
this.groupedDataHistory.push(lastGroupedValue);
return groupedData;
}
return widgetInput;
}))
.toPromise();
}
ngOnDestroy() {
this.outputsSubject.complete();
}
// redefine parent method
async applyFilters() {
this.applyFilters$.next(this.getFilters());
}
getData(filters) {
this.drillState = filters.drillstate?.value;
this.groupBy = filters.group?.value;
this.busy.next(true);
return (0, rxjs_1.of)(this.cache || data_mock_1.GRAPH_DATA_MOCK).pipe(
// delay(1000),
// eslint-disable-next-line import/no-deprecated
(0, operators_1.tap)((data) => (this.cache = data)),
// eslint-disable-next-line import/no-deprecated
(0, operators_1.map)((data) => data.data.countries), (0, operators_1.catchError)((e) => (0, rxjs_1.of)([])), (0, operators_1.finalize)(() => this.busy.next(false)));
}
getTransformedDataForGroup(data, groupName) {
const groupedDict = (0, groupBy_1.default)(data, groupName);
const dataArr = Object.keys(groupedDict).map((property) => ({
id: property,
label: property,
// TODO: apply groups mapping here
statuses: [
{ key: "state_ok", value: groupedDict[property].length },
{
key: "status_unreachable",
value: generateNumberUpTo(100000),
},
{ key: "status_warning", value: generateNumberUpTo(10000) },
{ key: "status_unknown", value: generateNumberUpTo(1000) },
],
}));
return [groupedDict, dataArr];
}
isHome() {
return this.drillState.length === 0;
}
isBack() {
return (this.groupedDataHistory.length > this.drillState.length &&
!this.isHome());
}
isDrillDown() {
return this.drillState.length !== this.groupBy.length;
}
getOutput(data) {
if (this.isHome()) {
this.groupedDataHistory.length = 0;
}
if (this.isBack()) {
this.groupedDataHistory.length = this.groupedDataHistory.length - 1;
}
const lastHistoryValue = getLast(this.groupedDataHistory);
if (!lastHistoryValue) {
return data;
}
return lastHistoryValue[getLast(this.drillState)] || lastHistoryValue;
}
};
exports.DrilldownDataSource = DrilldownDataSource;
exports.DrilldownDataSource = DrilldownDataSource = tslib_1.__decorate([
(0, core_1.Injectable)(),
tslib_1.__metadata("design:paramtypes", [])
], DrilldownDataSource);
let DrilldownWidgetTestComponent = class DrilldownWidgetTestComponent {
constructor(drilldownRegistry, widgetTypesService, providerRegistry, changeDetectorRef) {
this.drilldownRegistry = drilldownRegistry;
this.widgetTypesService = widgetTypesService;
this.providerRegistry = providerRegistry;
this.changeDetectorRef = changeDetectorRef;
this.gridsterConfig = {};
this.editMode = false;
const drilldownWidget = (0, cloneDeep_1.default)(this.widgetTypesService.getWidgetType("drilldown"));
drilldownWidget.widget[dashboards_1.PizzagnaLayer.Structure].navigationBar.providers = {
DrilldownRegistry: {
providerId: dashboards_1.NOVA_TEST_REGISTRY,
properties: {},
},
};
this.widgetTypesService.registerWidgetType("drilldown", 2, drilldownWidget);
}
/** Used for restoring widgets state */
reInitializeDashboard() {
// destroys the components and their providers so the dashboard can re init data
this.dashboard = undefined;
this.changeDetectorRef.detectChanges();
this.initializeDashboard();
}
ngOnInit() {
this.initializeDashboard();
}
initializeDashboard() {
this.providerRegistry.setProviders({
[DrilldownDataSource.providerId]: {
provide: dashboards_1.DATA_SOURCE,
useClass: DrilldownDataSource,
// Any dependencies that need to be injected into the provider must be listed here
deps: [http_1.HttpClient],
},
[dashboards_1.NOVA_TEST_REGISTRY]: {
provide: dashboards_1.TEST_REGISTRY,
useExisting: unit_test_registry_service_1.UnitTestRegistryService,
deps: [],
},
});
// We're using a static configuration object for this example, but this is where
// the widget's configuration could potentially be populated from a database
const drilldownWidget = widgetConfig;
const widgets = {
// Complete the widget with information coming from its type definition
[drilldownWidget.id]: this.widgetTypesService.mergeWithWidgetType(drilldownWidget),
};
// Setting the widget dimensions and position (this is for gridster)
const positions = {
[drilldownWidget.id]: {
cols: 10,
rows: 10,
y: 0,
x: 0,
},
};
// Finally, assigning the variables we created above to the dashboard
this.dashboard = { positions, widgets };
}
};
exports.DrilldownWidgetTestComponent = DrilldownWidgetTestComponent;
tslib_1.__decorate([
(0, core_1.ViewChild)(dashboards_1.DashboardComponent),
tslib_1.__metadata("design:type", dashboards_1.DashboardComponent)
], DrilldownWidgetTestComponent.prototype, "dashboardComponent", void 0);
exports.DrilldownWidgetTestComponent = DrilldownWidgetTestComponent = tslib_1.__decorate([
(0, core_1.Component)({
selector: "drilldown-widget-test",
templateUrl: "./drilldown-widget-test.component.html",
styleUrls: ["./drilldown-widget-test.component.less"],
standalone: false,
}),
tslib_1.__metadata("design:paramtypes", [unit_test_registry_service_1.UnitTestRegistryService,
dashboards_1.WidgetTypesService,
dashboards_1.ProviderRegistryService,
core_1.ChangeDetectorRef])
], DrilldownWidgetTestComponent);
const widgetConfig = {
id: "drilldown",
type: "drilldown",
version: 2,
pizzagna: {
[dashboards_1.PizzagnaLayer.Configuration]: {
[dashboards_1.DEFAULT_PIZZAGNA_ROOT]: {
providers: {
[dashboards_1.WellKnownProviders.DataSource]: {
// Setting the data source providerId for the tile with id "kpi1"
providerId: DrilldownDataSource.providerId,
properties: {},
},
},
},
header: {
properties: {
title: "Drilldown Widget",
subtitle: "Countries BY continent THEN currency",
},
},
listWidget: {
providers: {
[dashboards_1.WellKnownProviders.Adapter]: {
providerId: dashboards_1.NOVA_DRILLDOWN_DATASOURCE_ADAPTER,
properties: {
// widget
navigationBarId: "navigationBar",
componentId: "listWidget",
dataPath: "data",
// adapter props
// drillstate: [""],
groupBy: ["continent.name", "currency"],
// components
componentsConfig: {
group: {
componentType: dashboards_1.ListGroupItemComponent.lateLoadKey,
properties: {
dataFieldIds: {
id: "id",
label: "label",
statuses: "statuses",
},
},
itemProperties: {
canNavigate: true,
},
},
leaf: {
componentType: dashboards_1.ListLeafItemComponent.lateLoadKey,
properties: {
dataFieldIds: {
icon: "icon",
status: "icon_status",
detailedUrl: "capital",
label: "name",
},
},
itemProperties: {
canNavigate: false,
},
},
},
},
},
DrilldownRegistry: {
providerId: dashboards_1.NOVA_TEST_REGISTRY,
properties: {},
},
},
properties: {
configuration: {
// FORMAT:
// componentType: ListLeafItemComponent.lateLoadKey,
// properties: {
// dataFieldIds: {
// icon: "",
// status: "code",
// detailedUrl: "capital",
// label: "name",
// },
// },
//
},
},
},
},
},
};
const getLast = (arr) => arr[arr.length - 1];
const generateNumberUpTo = (upperLimit) => Math.floor(Math.random() * upperLimit + 1);
//# sourceMappingURL=drilldown-widget-test.component.js.map