!!!!WIP!!!!
adding InfluxDB - influxdb added to dockerfile - influxdb s6 service - influxdb config - adding defaults to config - creating a DeviceRepo interface (multiple db backends) - implemented DeviceRepo interface as ScruitnyRepository
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
<div *ngIf="data && data.data && data.data.length > 0; else emptyDashboard">
|
||||
|
||||
<div *ngIf="data && data.data && data.data.summary; else emptyDashboard">
|
||||
<div class="flex flex-col flex-auto w-full p-8 xs:p-2">
|
||||
|
||||
<div class="flex flex-wrap w-full">
|
||||
@@ -47,38 +48,37 @@
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap w-full">
|
||||
|
||||
<div *ngFor="let disk of data.data | deviceSort" class="flex gt-sm:w-1/2 min-w-80 p-4">
|
||||
<div [ngClass]="{'border-green': disk.smart_results[0]?.smart_status == 'passed',
|
||||
'border-red': disk.smart_results[0]?.smart_status == 'failed' }"
|
||||
<div *ngFor="let summary of data.data.summary | keyvalue" class="flex gt-sm:w-1/2 min-w-80 p-4">
|
||||
<div [ngClass]="{ 'border-green': summary.value.device.device_status == 0 && summary.value.smart,
|
||||
'border-red': summary.value.device.device_status != 0 }"
|
||||
class="relative flex flex-col flex-auto p-6 pr-3 pb-3 bg-card rounded border-l-4 shadow-md overflow-hidden">
|
||||
<div class="absolute bottom-0 right-0 w-24 h-24 -m-6">
|
||||
<mat-icon class="icon-size-96 opacity-12 text-green"
|
||||
*ngIf="disk.smart_results[0]?.smart_status == 'passed'"
|
||||
*ngIf="summary.value.device.device_status == 0 && summary.value.smart"
|
||||
[svgIcon]="'heroicons_outline:check-circle'"></mat-icon>
|
||||
<mat-icon class="icon-size-96 opacity-12 text-red"
|
||||
*ngIf="disk.smart_results[0]?.smart_status == 'failed'"
|
||||
*ngIf="summary.value.device.device_status != 0"
|
||||
[svgIcon]="'heroicons_outline:exclamation-circle'"></mat-icon>
|
||||
<mat-icon class="icon-size-96 opacity-12 text-yellow"
|
||||
*ngIf="!disk.smart_results[0]"
|
||||
*ngIf="!summary.value.smart"
|
||||
[svgIcon]="'heroicons_outline:question-mark-circle'"></mat-icon>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="flex flex-col">
|
||||
<a [routerLink]="'/device/'+ disk.wwn"
|
||||
class="font-bold text-md text-secondary uppercase tracking-wider">{{deviceTitle(disk)}}</a>
|
||||
<div [ngClass]="{'text-green': disk.smart_results[0]?.smart_status == 'passed',
|
||||
'text-red': disk.smart_results[0]?.smart_status == 'failed' }" class="font-medium text-sm" *ngIf="disk.smart_results[0]">
|
||||
Last Updated on {{disk.smart_results[0]?.date | date:'MMMM dd, yyyy - HH:mm' }}
|
||||
<a [routerLink]="'/device/'+ summary.value.device.wwn"
|
||||
class="font-bold text-md text-secondary uppercase tracking-wider">{{deviceTitle(summary.value.device)}}</a>
|
||||
<div [ngClass]="{'text-green': summary.value.device.device_status == 0 && summary.value.smart,
|
||||
'text-red': summary.value.device.device_status != 0 }" class="font-medium text-sm" *ngIf="summary.value.smart">
|
||||
Last Updated on {{summary.value.smart.collector_date | date:'MMMM dd, yyyy - HH:mm' }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-auto" *ngIf="disk.smart_results">
|
||||
<div class="ml-auto" *ngIf="summary.value.device">
|
||||
<button mat-icon-button
|
||||
[matMenuTriggerFor]="previousStatementMenu">
|
||||
<mat-icon [svgIcon]="'more_vert'"></mat-icon>
|
||||
</button>
|
||||
<mat-menu #previousStatementMenu="matMenu">
|
||||
<a mat-menu-item [routerLink]="'/device/'+ disk.wwn">
|
||||
<a mat-menu-item [routerLink]="'/device/'+ summary.value.device.wwn">
|
||||
<span class="flex items-center">
|
||||
<mat-icon class="icon-size-20 mr-3"
|
||||
[svgIcon]="'payment'"></mat-icon>
|
||||
@@ -90,22 +90,22 @@
|
||||
</div>
|
||||
<div class="flex flex-row flex-wrap mt-4 -mx-6">
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">S.M.A.R.T</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="disk.smart_results[0]; else unknownStatus">{{ disk.smart_results[0]?.smart_status | titlecase}}</div>
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Status</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="summary.value.smart?.collector_date; else unknownStatus">{{ deviceStatusString(summary.value.device.device_status) | titlecase}}</div>
|
||||
<ng-template #unknownStatus><div class="mt-2 font-medium text-3xl leading-none">No Data</div></ng-template>
|
||||
</div>
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Temperature</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="disk.smart_results[0]; else unknownTemp">{{ disk.smart_results[0]?.temp }}°C</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="summary.value.smart?.collector_date; else unknownTemp">{{ summary.value.smart?.temp }}°C</div>
|
||||
<ng-template #unknownTemp><div class="mt-2 font-medium text-3xl leading-none">--</div></ng-template>
|
||||
</div>
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Capacity</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none">{{ disk.capacity | fileSize}}</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none">{{ summary.value.device.capacity | fileSize}}</div>
|
||||
</div>
|
||||
<div class="flex flex-col mx-6 my-3 xs:w-full">
|
||||
<div class="font-semibold text-xs text-hint uppercase tracking-wider leading-none">Powered On</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="disk.smart_results[0]?.power_on_hours; else unknownPoweredOn">{{ humanizeDuration(disk.smart_results[0]?.power_on_hours * 60 * 60 * 1000, { round: true, largest: 1, units: ['y', 'd', 'h'] }) }}</div>
|
||||
<div class="mt-2 font-medium text-3xl leading-none" *ngIf="summary.value.smart?.power_on_hours; else unknownPoweredOn">{{ humanizeDuration(summary.value.smart?.power_on_hours * 60 * 60 * 1000, { round: true, largest: 1, units: ['y', 'd', 'h'] }) }}</div>
|
||||
<ng-template #unknownPoweredOn><div class="mt-2 font-medium text-3xl leading-none">--</div></ng-template>
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,7 +140,7 @@
|
||||
|
||||
</div>
|
||||
<div class="flex flex-col flex-auto">
|
||||
<apx-chart class="flex-auto w-full h-full"
|
||||
<apx-chart *ngIf="temperatureOptions" class="flex-auto w-full h-full"
|
||||
[chart]="temperatureOptions.chart"
|
||||
[colors]="temperatureOptions.colors"
|
||||
[fill]="temperatureOptions.fill"
|
||||
|
||||
@@ -84,16 +84,23 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
private _deviceDataTemperatureSeries() {
|
||||
var deviceTemperatureSeries = []
|
||||
|
||||
for(let device of this.data.data){
|
||||
console.log("DEVICE DATA SUMMARY", this.data)
|
||||
|
||||
for(const wwn in this.data.data.summary){
|
||||
var deviceSummary = this.data.data.summary[wwn]
|
||||
if (!deviceSummary.temp_history){
|
||||
continue
|
||||
}
|
||||
var deviceSeriesMetadata = {
|
||||
name: `/dev/${device.device_name}`,
|
||||
name: `/dev/${deviceSummary.device.device_name}`,
|
||||
data: []
|
||||
}
|
||||
for(let smartResults of device.smart_results){
|
||||
let newDate = new Date(smartResults.CreatedAt);
|
||||
|
||||
for(let tempHistory of deviceSummary.temp_history){
|
||||
let newDate = new Date(tempHistory.date);
|
||||
deviceSeriesMetadata.data.push({
|
||||
x: newDate,
|
||||
y: smartResults.temp
|
||||
y: tempHistory.temp
|
||||
})
|
||||
}
|
||||
deviceTemperatureSeries.push(deviceSeriesMetadata)
|
||||
@@ -181,6 +188,14 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
return title.join(' - ')
|
||||
}
|
||||
|
||||
deviceStatusString(deviceStatus){
|
||||
if(deviceStatus == 0){
|
||||
return "passed"
|
||||
} else {
|
||||
return "failed"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Track by function for ngFor loops
|
||||
*
|
||||
|
||||
@@ -53,59 +53,59 @@
|
||||
<div class="flex flex-auto w-1/4 p-4 lt-md:w-full">
|
||||
<treo-card class="flex flex-auto p-4 pt-6 flex-col flex-auto filter-list">
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="text-2xl font-semibold leading-tight">/dev/{{data.data.device_name}}</div>
|
||||
<div class="text-2xl font-semibold leading-tight">/dev/{{device?.device_name}}</div>
|
||||
</div>
|
||||
<div class="flex flex-col my-2 grid grid-cols-2">
|
||||
<div *ngIf="data.data.host_id" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.host_id}}</div>
|
||||
<div *ngIf="device?.host_id" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{device?.host_id}}</div>
|
||||
<div class="text-secondary text-md">Host ID</div>
|
||||
</div>
|
||||
<div *ngIf="data.data.device_type && data.data.device_type != 'ata' && data.data.device_type != 'scsi'" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.device_type | uppercase}}</div>
|
||||
<div *ngIf="device?.device_type && device?.device_type != 'ata' && device?.device_type != 'scsi'" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{device?.device_type | uppercase}}</div>
|
||||
<div class="text-secondary text-md">Device Type</div>
|
||||
</div>
|
||||
<div *ngIf="data.data.manufacturer" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.manufacturer}}</div>
|
||||
<div *ngIf="device?.manufacturer" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{device?.manufacturer}}</div>
|
||||
<div class="text-secondary text-md">Model Family</div>
|
||||
</div>
|
||||
<div class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.model_name}}</div>
|
||||
<div>{{device?.model_name}}</div>
|
||||
<div class="text-secondary text-md">Device Model</div>
|
||||
</div>
|
||||
<div class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.serial_number}}</div>
|
||||
<div>{{device?.serial_number}}</div>
|
||||
<div class="text-secondary text-md">Serial Number</div>
|
||||
</div>
|
||||
<div class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.wwn}}</div>
|
||||
<div>{{device?.wwn}}</div>
|
||||
<div class="text-secondary text-md">LU WWN Device Id</div>
|
||||
</div>
|
||||
<div class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.firmware}}</div>
|
||||
<div>{{device?.firmware}}</div>
|
||||
<div class="text-secondary text-md">Firmware Version</div>
|
||||
</div>
|
||||
<div class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.capacity | fileSize}}</div>
|
||||
<div>{{device?.capacity | fileSize}}</div>
|
||||
<div class="text-secondary text-md">Capacity</div>
|
||||
</div>
|
||||
<div *ngIf="data.data.rotational_speed" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.rotational_speed}} RPM</div>
|
||||
<div *ngIf="device?.rotational_speed" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{device?.rotational_speed}} RPM</div>
|
||||
<div class="text-secondary text-md">Rotation Rate</div>
|
||||
</div>
|
||||
<div *ngIf="data.data.device_protocol" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.device_protocol}}</div>
|
||||
<div *ngIf="device?.device_protocol" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{device?.device_protocol}}</div>
|
||||
<div class="text-secondary text-md">Protocol</div>
|
||||
</div>
|
||||
<div class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.smart_results[0]?.power_cycle_count}}</div>
|
||||
<div>{{smart_results[0]?.power_cycle_count}}</div>
|
||||
<div class="text-secondary text-md">Power Cycle Count</div>
|
||||
</div>
|
||||
<div *ngIf="data.data.smart_results[0]?.power_on_hours" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div matTooltip="{{humanizeDuration(data.data.smart_results[0]?.power_on_hours * 60 * 60 * 1000, { conjunction: ' and ', serialComma: false })}}">{{humanizeDuration(data.data.smart_results[0]?.power_on_hours *60 * 60 * 1000, { round: true, largest: 1, units: ['y', 'd', 'h'] })}}</div>
|
||||
<div *ngIf="smart_results[0]?.power_on_hours" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div matTooltip="{{humanizeDuration(smart_results[0]?.power_on_hours * 60 * 60 * 1000, { conjunction: ' and ', serialComma: false })}}">{{humanizeDuration(smart_results[0]?.power_on_hours *60 * 60 * 1000, { round: true, largest: 1, units: ['y', 'd', 'h'] })}}</div>
|
||||
<div class="text-secondary text-md">Powered On</div>
|
||||
</div>
|
||||
<div class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>{{data.data.smart_results[0]?.temp}}°C</div>
|
||||
<div>{{smart_results[0]?.temp}}°C</div>
|
||||
<div class="text-secondary text-md">Temperature</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -115,7 +115,7 @@
|
||||
<div class="flex flex-auto w-3/4 p-4 lt-md:w-full">
|
||||
<div class="flex flex-col flex-auto w-full bg-card shadow-md rounded ">
|
||||
<div class="p-6">
|
||||
<div class="font-bold text-md text-secondary uppercase tracking-wider">S.M.A.R.T {{data.data.device_protocol}} Attributes</div>
|
||||
<div class="font-bold text-md text-secondary uppercase tracking-wider">S.M.A.R.T {{device?.device_protocol}} Attributes</div>
|
||||
<div class="text-sm text-hint font-medium">{{this.smartAttributeDataSource.data.length}} visible, {{getHiddenAttributes()}} hidden</div>
|
||||
</div>
|
||||
<div class="overflow-auto">
|
||||
|
||||
@@ -19,7 +19,12 @@ import humanizeDuration from 'humanize-duration';
|
||||
export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
onlyCritical: boolean = true;
|
||||
data: any;
|
||||
// data: any;
|
||||
|
||||
metadata: any;
|
||||
device: any;
|
||||
smart_results: any[];
|
||||
|
||||
commonSparklineOptions: Partial<ApexOptions>;
|
||||
smartAttributeDataSource: MatTableDataSource<any>;
|
||||
smartAttributeTableColumns: string[];
|
||||
@@ -66,10 +71,14 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
.subscribe((data) => {
|
||||
|
||||
// Store the data
|
||||
this.data = data;
|
||||
// this.data = data;
|
||||
this.device = data.data.device;
|
||||
this.smart_results = data.data.smart_results
|
||||
this.metadata = data.metadata;
|
||||
|
||||
|
||||
// Store the table data
|
||||
this.smartAttributeDataSource.data = this._generateSmartAttributeTableDataSource(data.data.smart_results);
|
||||
this.smartAttributeDataSource.data = this._generateSmartAttributeTableDataSource(this.smart_results);
|
||||
|
||||
// Prepare the chart data
|
||||
this._prepareChartData();
|
||||
@@ -99,7 +108,7 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
// @ Private methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
getAttributeDescription(attribute_data){
|
||||
let attribute_metadata = this.data.metadata[attribute_data.attribute_id]
|
||||
let attribute_metadata = this.metadata[attribute_data.attribute_id]
|
||||
if(!attribute_metadata){
|
||||
return 'Unknown'
|
||||
} else {
|
||||
@@ -110,7 +119,7 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
getAttributeValue(attribute_data){
|
||||
if(this.isAta()) {
|
||||
let attribute_metadata = this.data.metadata[attribute_data.attribute_id]
|
||||
let attribute_metadata = this.metadata[attribute_data.attribute_id]
|
||||
if(!attribute_metadata){
|
||||
return attribute_data.value
|
||||
} else if (attribute_metadata.display_type == "raw") {
|
||||
@@ -128,7 +137,7 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
getAttributeValueType(attribute_data){
|
||||
if(this.isAta()) {
|
||||
let attribute_metadata = this.data.metadata[attribute_data.attribute_id]
|
||||
let attribute_metadata = this.metadata[attribute_data.attribute_id]
|
||||
if(!attribute_metadata){
|
||||
return ''
|
||||
} else {
|
||||
@@ -141,14 +150,14 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
getAttributeIdeal(attribute_data){
|
||||
if(this.isAta()){
|
||||
return this.data.metadata[attribute_data.attribute_id]?.display_type == "raw" ? this.data.metadata[attribute_data.attribute_id]?.ideal : ''
|
||||
return this.metadata[attribute_data.attribute_id]?.display_type == "raw" ? this.metadata[attribute_data.attribute_id]?.ideal : ''
|
||||
} else {
|
||||
return this.data.metadata[attribute_data.attribute_id]?.ideal
|
||||
return this.metadata[attribute_data.attribute_id]?.ideal
|
||||
}
|
||||
}
|
||||
|
||||
getAttributeWorst(attribute_data){
|
||||
let attribute_metadata = this.data.metadata[attribute_data.attribute_id]
|
||||
let attribute_metadata = this.metadata[attribute_data.attribute_id]
|
||||
if(!attribute_metadata){
|
||||
return attribute_data.worst
|
||||
} else {
|
||||
@@ -158,7 +167,7 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
|
||||
getAttributeThreshold(attribute_data){
|
||||
if(this.isAta()){
|
||||
let attribute_metadata = this.data.metadata[attribute_data.attribute_id]
|
||||
let attribute_metadata = this.metadata[attribute_data.attribute_id]
|
||||
if(!attribute_metadata || attribute_metadata.display_type == "normalized"){
|
||||
return attribute_data.thresh
|
||||
} else {
|
||||
@@ -175,29 +184,30 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
}
|
||||
|
||||
getAttributeCritical(attribute_data){
|
||||
return this.data.metadata[attribute_data.attribute_id]?.critical
|
||||
return this.metadata[attribute_data.attribute_id]?.critical
|
||||
}
|
||||
getHiddenAttributes(){
|
||||
let attributes_list
|
||||
if(this.isAta()){
|
||||
attributes_list = this.data.data.smart_results[0]?.ata_attributes
|
||||
} else if(this.isNvme()){
|
||||
attributes_list = this.data.data.smart_results[0]?.nvme_attributes
|
||||
} else {
|
||||
attributes_list = this.data.data.smart_results[0]?.scsi_attributes
|
||||
if (!this.smart_results || this.smart_results.length == 0) {
|
||||
return 0
|
||||
}
|
||||
|
||||
return attributes_list.length - this.smartAttributeDataSource.data.length
|
||||
let attributes_length = 0
|
||||
let attributes = this.smart_results[0]?.attrs
|
||||
if (attributes) {
|
||||
attributes_length = Object.keys(attributes).length
|
||||
}
|
||||
|
||||
return attributes_length - this.smartAttributeDataSource.data.length
|
||||
}
|
||||
|
||||
isAta(): boolean {
|
||||
return this.data.data.device_protocol == 'ATA'
|
||||
return this.device.device_protocol == 'ATA'
|
||||
}
|
||||
isScsi(): boolean {
|
||||
return this.data.data.device_protocol == 'SCSI'
|
||||
return this.device.device_protocol == 'SCSI'
|
||||
}
|
||||
isNvme(): boolean {
|
||||
return this.data.data.device_protocol == 'NVMe'
|
||||
return this.device.device_protocol == 'NVMe'
|
||||
}
|
||||
|
||||
private _generateSmartAttributeTableDataSource(smart_results){
|
||||
@@ -207,21 +217,22 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
return smartAttributeDataSource
|
||||
}
|
||||
var latest_smart_result = smart_results[0];
|
||||
let attributes_list = []
|
||||
let attributes = {}
|
||||
if(this.isScsi()) {
|
||||
this.smartAttributeTableColumns = ['status', 'name', 'value', 'thresh', 'history'];
|
||||
attributes_list = latest_smart_result.scsi_attributes
|
||||
attributes = latest_smart_result.attrs
|
||||
} else if(this.isNvme()){
|
||||
this.smartAttributeTableColumns = ['status', 'name', 'value', 'thresh', 'ideal', 'history'];
|
||||
attributes_list = latest_smart_result.nvme_attributes
|
||||
attributes = latest_smart_result.attrs
|
||||
} else {
|
||||
//ATA
|
||||
attributes_list = latest_smart_result.ata_attributes
|
||||
attributes = latest_smart_result.attrs
|
||||
this.smartAttributeTableColumns = ['status', 'id', 'name', 'value', 'worst', 'thresh','ideal', 'failure', 'history'];
|
||||
}
|
||||
|
||||
for(const attrId in attributes){
|
||||
var attr = attributes[attrId]
|
||||
|
||||
for(let attr of attributes_list){
|
||||
//chart history data
|
||||
if (!attr.chartData) {
|
||||
var rawHistory = (attr.history || []).map(hist_attr => this.getAttributeValue(hist_attr)).reverse()
|
||||
@@ -235,7 +246,7 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
}
|
||||
//determine when to include the attributes in table.
|
||||
|
||||
if(!this.onlyCritical || this.onlyCritical && this.data.metadata[attr.attribute_id]?.critical || attr.value < attr.thresh){
|
||||
if(!this.onlyCritical || this.onlyCritical && this.metadata[attr.attribute_id]?.critical || attr.value < attr.thresh){
|
||||
smartAttributeDataSource.push(attr)
|
||||
}
|
||||
}
|
||||
@@ -297,7 +308,7 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
}
|
||||
toggleOnlyCritical(){
|
||||
this.onlyCritical = !this.onlyCritical
|
||||
this.smartAttributeDataSource.data = this._generateSmartAttributeTableDataSource(this.data.data.smart_results);
|
||||
this.smartAttributeDataSource.data = this._generateSmartAttributeTableDataSource(this.smart_results);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user