Merge branch 'master' into BASEPATH
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
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,36 @@
|
||||
</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]="classDeviceLastUpdatedOn(summary.value)" 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 +89,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>
|
||||
@@ -126,21 +125,20 @@
|
||||
<button class="h-8 min-h-8 px-2"
|
||||
matTooltip="not yet implemented"
|
||||
mat-button
|
||||
[matMenuTriggerFor]="accountBalanceMenu">
|
||||
<span class="font-medium text-sm text-hint">12 months</span>
|
||||
[matMenuTriggerFor]="tempRangeMenu">
|
||||
<span class="font-medium text-sm text-hint">1 week</span>
|
||||
</button>
|
||||
<mat-menu #accountBalanceMenu="matMenu">
|
||||
<button mat-menu-item>3 months</button>
|
||||
<button mat-menu-item>6 months</button>
|
||||
<button mat-menu-item>9 months</button>
|
||||
<mat-menu #tempRangeMenu="matMenu">
|
||||
<button mat-menu-item>1 month</button>
|
||||
<button mat-menu-item>12 months</button>
|
||||
<button mat-menu-item>all time</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</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,34 @@ export class DashboardComponent implements OnInit, AfterViewInit, OnDestroy
|
||||
return title.join(' - ')
|
||||
}
|
||||
|
||||
deviceStatusString(deviceStatus){
|
||||
if(deviceStatus == 0){
|
||||
return "passed"
|
||||
} else {
|
||||
return "failed"
|
||||
}
|
||||
}
|
||||
|
||||
classDeviceLastUpdatedOn(deviceSummary){
|
||||
if (deviceSummary.device.device_status !== 0) {
|
||||
return 'text-red' // if the device has failed, always highlight in red
|
||||
} else if(deviceSummary.device.device_status === 0 && deviceSummary.smart){
|
||||
if(moment().subtract(14, 'd').isBefore(deviceSummary.smart.collector_date)){
|
||||
// this device was updated in the last 2 weeks.
|
||||
return 'text-green'
|
||||
} else if(moment().subtract(1, 'm').isBefore(deviceSummary.smart.collector_date)){
|
||||
// this device was updated in the last month
|
||||
return 'text-yellow'
|
||||
} else{
|
||||
// last updated more than a month ago.
|
||||
return 'text-red'
|
||||
}
|
||||
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Track by function for ngFor loops
|
||||
*
|
||||
|
||||
@@ -53,59 +53,73 @@
|
||||
<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" class="my-2 col-span-2 lt-md:col-span-1">
|
||||
<div>
|
||||
<span class="inline-flex items-center font-bold text-xs px-2 py-2px rounded-full tracking-wide uppercase"
|
||||
[ngClass]="{'red-200': device?.device_status != 0,
|
||||
'green-200': device?.device_status == 0}">
|
||||
<span class="w-2 h-2 rounded-full mr-2"
|
||||
[ngClass]="{'bg-red': device?.device_status != 0,
|
||||
'bg-green': device?.device_status == 0}"></span>
|
||||
<span class="pr-2px leading-relaxed whitespace-no-wrap">{{device?.device_status == 0 ? 'passed' : 'failed'}}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-secondary text-md">Status</div>
|
||||
</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 +129,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">
|
||||
@@ -139,15 +153,15 @@
|
||||
<td mat-cell
|
||||
*matCellDef="let attribute">
|
||||
<span class="inline-flex items-center font-bold text-xs px-2 py-2px rounded-full tracking-wide uppercase"
|
||||
[ngClass]="{'red-200': attribute.status === 'failed',
|
||||
'green-200': attribute.status === 'passed',
|
||||
'yellow-200': attribute.status === 'warn'
|
||||
[ngClass]="{'red-200': getAttributeStatusName(attribute.status) === 'failed',
|
||||
'green-200': getAttributeStatusName(attribute.status) === 'passed',
|
||||
'yellow-200': getAttributeStatusName(attribute.status) === 'warn'
|
||||
}">
|
||||
<span class="w-2 h-2 rounded-full mr-2"
|
||||
[ngClass]="{'bg-red': attribute.status === 'failed',
|
||||
'bg-green': attribute.status === 'passed',
|
||||
'bg-yellow': attribute.status === 'warn'}"></span>
|
||||
<span class="pr-2px leading-relaxed whitespace-no-wrap" matTooltip="{{attribute.status_reason}}">{{attribute.status}}</span>
|
||||
[ngClass]="{'bg-red': getAttributeStatusName(attribute.status) === 'failed',
|
||||
'bg-green': getAttributeStatusName(attribute.status) === 'passed',
|
||||
'bg-yellow': getAttributeStatusName(attribute.status) === 'warn'}"></span>
|
||||
<span class="pr-2px leading-relaxed whitespace-no-wrap" matTooltip="{{attribute.status_reason}}">{{getAttributeStatusName(attribute.status)}}</span>
|
||||
</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
@@ -183,7 +197,7 @@
|
||||
<td mat-cell
|
||||
*matCellDef="let attribute">
|
||||
<span class="pr-6 whitespace-no-wrap" matTooltip="{{getAttributeDescription(attribute)}}">
|
||||
{{attribute.name}} <mat-icon *ngIf="getAttributeDescription(attribute)" class="icon-size-10" [svgIcon]="'info'"></mat-icon>
|
||||
{{getAttributeName(attribute)}} <mat-icon *ngIf="getAttributeDescription(attribute)" class="icon-size-10" [svgIcon]="'info'"></mat-icon>
|
||||
</span>
|
||||
</td>
|
||||
</ng-container>
|
||||
|
||||
@@ -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();
|
||||
@@ -98,8 +107,28 @@ export class DetailComponent implements OnInit, AfterViewInit, OnDestroy {
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
// @ Private methods
|
||||
// -----------------------------------------------------------------------------------------------------
|
||||
getAttributeStatusName(attribute_status){
|
||||
if(attribute_status == 0){
|
||||
return "passed"
|
||||
} else if (attribute_status == 1){
|
||||
return "warn"
|
||||
} else if (attribute_status == 2){
|
||||
return "failed"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
getAttributeName(attribute_data){
|
||||
let attribute_metadata = this.metadata[attribute_data.attribute_id]
|
||||
if(!attribute_metadata){
|
||||
return 'Unknown Attribute Name'
|
||||
} else {
|
||||
return attribute_metadata.display_name
|
||||
}
|
||||
return
|
||||
}
|
||||
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 +139,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 +157,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 +170,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 +187,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 +204,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,35 +237,44 @@ 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()
|
||||
rawHistory.push(this.getAttributeValue(attr))
|
||||
attr.chartData = [
|
||||
|
||||
|
||||
var attrHistory = []
|
||||
for (let smart_result of smart_results){
|
||||
attrHistory.push(this.getAttributeValue(smart_result.attrs[attrId]))
|
||||
}
|
||||
|
||||
// var rawHistory = (attr.history || []).map(hist_attr => this.getAttributeValue(hist_attr)).reverse()
|
||||
// rawHistory.push(this.getAttributeValue(attr))
|
||||
|
||||
attributes[attrId].chartData = [
|
||||
{
|
||||
name: "chart-line-sparkline",
|
||||
data: rawHistory
|
||||
data: attrHistory
|
||||
}
|
||||
]
|
||||
}
|
||||
//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 +336,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