Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

link firmware statistics to device lookup #35

Merged
merged 1 commit into from
Dec 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 47 additions & 7 deletions src/modules/lookup/device-lookup/device-lookup.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
import { Component } from '@angular/core';
import { Component, OnDestroy, ViewChild } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { IManagedObject } from '@c8y/client';
import { AlertService, BulkActionControl, Column, ColumnDataType, ModalService } from '@c8y/ngx-components';
import {
AlertService,
BulkActionControl,
Column,
ColumnDataType,
DataGridComponent,
ModalService
} from '@c8y/ngx-components';
import { DeviceAction } from '@models/extensions';
import { TenantSpecificDetails } from '@models/tenant-specific-details';
import { FakeMicroserviceService } from '@services/fake-microservice.service';
import { BsModalService } from 'ngx-bootstrap/modal';
import { Subject } from 'rxjs';
import { Subject, Subscription } from 'rxjs';
import { filter, take } from 'rxjs/operators';
import { ConfigurationUpdateModalComponent } from '../modals/configuration-update-modal/configuration-update-modal.component';
import { CustomFirmwareUpdateModalComponent } from '../modals/custom-firmware-update-modal/custom-firmware-update-modal.component';
Expand All @@ -17,7 +25,8 @@ import { DeviceTableDatasourceService } from './device-table-datasource.service'
selector: 'ps-device-lookup',
templateUrl: './device-lookup.component.html'
})
export class DeviceLookupComponent {
export class DeviceLookupComponent implements OnDestroy {
@ViewChild(DataGridComponent, { static: true }) dataGrid: DataGridComponent;
columns: Column[];
bulkActionControls: BulkActionControl[] = [
{
Expand All @@ -35,15 +44,46 @@ export class DeviceLookupComponent {
this.updateFirmware(selectedItemIds as any as { tenant: string; id: string }[])
}
];
private queryParamSub: Subscription;

constructor(
private credService: FakeMicroserviceService,
private c8yModalService: ModalService,
private modalService: BsModalService,
private alertService: AlertService,
public datasource: DeviceTableDatasourceService
public datasource: DeviceTableDatasourceService,
private route: ActivatedRoute
) {
this.columns = this.getDefaultColumns();
this.queryParamSub = this.route.queryParams.subscribe((params) => {
const columns = this.dataGrid ? this.dataGrid.columns : this.columns;
if (params && this.columns && this.columns.length) {
const paramKeys = Object.keys(params);
let paramChanged = false;
columns.forEach((col) => {
if (paramKeys.includes(col.name)) {
if (col.filterPredicate !== params[col.name]) {
paramChanged = true;
col.filterPredicate = params[col.name];
}
} else {
if (col.filterPredicate) {
paramChanged = true;
col.filterPredicate = undefined;
}
}
});
if (paramChanged && this.dataGrid) {
this.dataGrid.reload();
}
}
});
}

ngOnDestroy(): void {
if (this.queryParamSub) {
this.queryParamSub.unsubscribe();
}
}

getDefaultColumns(): Column[] {
Expand Down Expand Up @@ -92,7 +132,7 @@ export class DeviceLookupComponent {
visible: false
},
{
name: 'firmware_name',
name: 'firmwareName',
header: 'Firmware Name',
path: 'data.c8y_Firmware.name',
dataType: ColumnDataType.TextShort,
Expand All @@ -101,7 +141,7 @@ export class DeviceLookupComponent {
visible: false
},
{
name: 'firmware_version',
name: 'firmwareVersion',
header: 'Firmware Version',
path: 'data.c8y_Firmware.version',
dataType: ColumnDataType.TextShort,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Inject, Injectable, Optional } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { QueriesUtil, IResultList, IManagedObject, Client } from '@c8y/client';
import { ServerSideDataResult, Column, Pagination, DataSourceModifier } from '@c8y/ngx-components';
import { DeviceActionsFactory, HOOK_DEVICE_ACTION_FACTORY } from '@models/extensions';
Expand Down Expand Up @@ -34,24 +35,37 @@ export class DeviceTableDatasourceService {
constructor(
private credService: FakeMicroserviceService,
private deviceDetailsService: DeviceDetailsService,
private extensionService: ExtensionsService
private extensionService: ExtensionsService,
private router: Router,
private activatedRoute: ActivatedRoute
) {
this.deviceActionFactories = this.extensionService.getDeviceActionFactories();
this.serverSideDataCallback = this.onDataSourceModifier.bind(this);
}

async onDataSourceModifier(dataSourceModifier: DataSourceModifier): Promise<ServerSideDataResult> {
this.columns = [...(dataSourceModifier.columns || [])];
const queryParams = {};
this.columns.forEach((col) => {
if (col.filterPredicate) {
queryParams[col.name] = col.filterPredicate;
}
});

this.router.navigate([], {
relativeTo: this.activatedRoute,
queryParams
});
const credentials = await this.credService.prepareCachedDummyMicroserviceForAllSubtenants();
let clients = this.credService.createClients(credentials);
const columnsCopy = dataSourceModifier.columns.map((tmp) => Object.assign({}, tmp));
let tenantFilter = '';
const tenantIdCol = dataSourceModifier.columns.find((tmp) => tmp.path === 'tenantId');
const tenantIdCol = columnsCopy.find((tmp) => tmp.path === 'tenantId');
if (tenantIdCol && tenantIdCol.filterPredicate) {
clients = clients.filter((tmp) => tmp.core.tenant.includes(tenantIdCol.filterPredicate as string));
tenantFilter = tenantIdCol.filterPredicate as string;
tenantIdCol.filterPredicate = undefined;
}
const columnsCopy = dataSourceModifier.columns.map((tmp) => Object.assign({}, tmp));

columnsCopy.forEach((entry) => {
if (entry && entry.path) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ <h3>{{ "No device/firmware combination selected." | translate }}</h3>
<h4 class="card-title">{{ currentChart.label }}</h4>
</div>
<div class="card-block flex-grow">
<ps-pie-chart [pieChartLabels]="currentChart.labels" [pieChartData]="currentChart.values"></ps-pie-chart>
<ps-pie-chart [pieChartLabels]="currentChart.labels" [pieChartData]="currentChart.values" (indexClicked)="pieChartClicked($event)"></ps-pie-chart>

</div>
<!-- <div class="card-footer separator text-center">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { DeviceDetailsService } from '@services/device-details.service';
import { FakeMicroserviceService } from '@services/fake-microservice.service';
import { flatten } from 'lodash-es';

@Component({
selector: 'ps-firmware-statistics',
Expand All @@ -10,16 +12,24 @@ export class FirmwareStatisticsComponent {
isLoading = true;
charts: {
label: string;
type: string;
firmwareName: string;
labels: string[];
values: number[];
}[] = [];
currentChart: {
label: string;
type: string;
firmwareName: string;
labels: string[];
values: number[];
};

constructor(private credService: FakeMicroserviceService, private deviceDetailsService: DeviceDetailsService) {
constructor(
private credService: FakeMicroserviceService,
private deviceDetailsService: DeviceDetailsService,
private router: Router
) {
this.loadData();
}

Expand All @@ -30,6 +40,8 @@ export class FirmwareStatisticsComponent {
this.charts = result.map((tmp) => {
return {
label: tmp.label,
type: tmp.type,
firmwareName: tmp.firmwareName,
labels: tmp.entries.map((entry) => entry.version),
values: tmp.entries.map((entry) => entry.count)
};
Expand All @@ -47,13 +59,21 @@ export class FirmwareStatisticsComponent {
);
}

public selectChart(chart: { label: string; labels: string[]; values: number[] }): void {
public selectChart(chart: {
label: string;
type: string;
firmwareName: string;
labels: string[];
values: number[];
}): void {
this.currentChart = chart;
}

private async fetchForPage(): Promise<
{
label: string;
type: string;
firmwareName: string;
entries: {
version: string;
count: number;
Expand All @@ -63,20 +83,44 @@ export class FirmwareStatisticsComponent {
const credentials = await this.credService.prepareCachedDummyMicroserviceForAllSubtenants();
const clients = this.credService.createClients(credentials);
const result = await this.deviceDetailsService.getFirmwareStatisticsOfTenants(clients);
const mappedResult = Array.from(result.entries()).map(([key, value]) => {
const childEntries = Array.from(value.entries())
.map(([key2, value2]) => {
return {
version: key2,
count: value2
};
})
.sort((a, b) => b.count - a.count);
return {
label: key,
entries: childEntries
};
const mappedResult = Array.from(result.entries()).map(([type, value]) => {
return Array.from(value.entries()).map(([firmwareName, value2]) => {
const childEntries = Array.from(value2.entries())
.map(([key2, value3]) => {
return {
version: key2,
count: value3
};
})
.sort((a, b) => b.count - a.count);
return {
label: `${type} - ${firmwareName}`,
type,
firmwareName,
entries: childEntries
};
});
});
return mappedResult;
return flatten(mappedResult);
}

pieChartClicked(index: number): void {
const lookupPath = 'lookup';
const devicePath = 'device';
const config = this.router.config;
const lookupConfig = config.find((tmp) => tmp.path === lookupPath);
if (lookupConfig && lookupConfig.children && lookupConfig.children.find((tmp) => tmp.path === devicePath)) {
const firmwareVersion = this.currentChart.labels[index];
const type = this.currentChart.type;
const firmwareName = this.currentChart.firmwareName;

this.router.navigate([lookupPath, devicePath], {
queryParams: {
firmwareVersion,
type,
firmwareName
}
});
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@
[colors]="pieChartColors"
[legend]="pieChartLegend"
[plugins]="pieChartPlugins"
(chartClick)="onChartClick($event)"
>
</canvas>
9 changes: 8 additions & 1 deletion src/modules/statistics/pie-chart/pie-chart.component.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Component, Input } from '@angular/core';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { ChartOptions, ChartType } from 'chart.js';
import { Color, Label } from 'ng2-charts';
import * as pluginDataLabels from 'chartjs-plugin-datalabels';
Expand All @@ -10,6 +10,7 @@ import * as pluginDataLabels from 'chartjs-plugin-datalabels';
})
export class PieChartComponent {
@Input() pieChartData: number[];
@Output() indexClicked = new EventEmitter<number>();
public pieChartOptions: ChartOptions = {
responsive: true,
// legend: {
Expand Down Expand Up @@ -95,4 +96,10 @@ export class PieChartComponent {
constructor() {
this.pieChartColors = [];
}

onChartClick(event: any): void {
if (event && event.active && event.active.length) {
this.indexClicked.emit(event.active[0]._index);
}
}
}
Loading