Skip to content

Commit 2daa143

Browse files
feat: add tabs, product type column, and discovered field
- Add three tabs to the devices page: All, Activated and Discovered with live counts in each tab label - Add 'Product Type' column (ISM / vPro) derived from fwSku bitmask Signed-off-by: ShradhaGupta31 <shradha.gupta@intel.com>
1 parent d9cea70 commit 2daa143

3 files changed

Lines changed: 71 additions & 1 deletion

File tree

src/app/devices/devices.component.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ <h3 class="flex justify-center">
4646
}
4747
</h3>
4848
} @else {
49+
<mat-tab-group (selectedTabChange)="onTabChange($event.index)">
50+
<mat-tab [label]="'All (' + allDevicesData.length + ')'"></mat-tab>
51+
<mat-tab [label]="'Activated (' + activatedCount + ')'"></mat-tab>
52+
<mat-tab [label]="'Discovered (' + discoveredCount + ')'"></mat-tab>
53+
</mat-tab-group>
4954
<div class="flex-row flex-wrap flex-1">
5055
<div class="flex flex-66" style="width: 66%">
5156
<mat-form-field data-cy="filterSearch" style="width: 100%">
@@ -121,6 +126,13 @@ <h3 class="flex justify-center">
121126
</mat-cell>
122127
</ng-container>
123128
<!-- tags Column -->
129+
<ng-container matColumnDef="productType">
130+
<mat-header-cell *matHeaderCellDef mat-sort-header>Product Type</mat-header-cell>
131+
<mat-cell *matCellDef="let element" (click)="navigateTo(element.guid)">
132+
{{ getProductType(element) }}
133+
</mat-cell>
134+
</ng-container>
135+
<!-- tags Column -->
124136
<ng-container matColumnDef="tags">
125137
<mat-header-cell *matHeaderCellDef mat-sort-header>
126138
<!-- include this always hidden icon to match spacing in the cell -->

src/app/devices/devices.component.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ import { MatButton, MatIconButton } from '@angular/material/button'
4747
import { MatToolbar } from '@angular/material/toolbar'
4848
import { MatSort } from '@angular/material/sort'
4949
import { MatInput } from '@angular/material/input'
50+
import { MatTabGroup, MatTab } from '@angular/material/tabs'
5051
import { TranslatePipe, TranslateService } from '@ngx-translate/core'
5152

5253
@Component({
@@ -86,6 +87,8 @@ import { TranslatePipe, TranslateService } from '@ngx-translate/core'
8687
MatPaginator,
8788
MatHint,
8889
RouterModule,
90+
MatTabGroup,
91+
MatTab,
8992
TranslatePipe
9093
]
9194
})
@@ -108,6 +111,46 @@ export class DevicesComponent implements OnInit, AfterViewInit {
108111
public powerStates: any
109112
public isCloudMode: boolean = environment.cloud
110113

114+
public activeTab = signal(0)
115+
public allDevicesData: Device[] = []
116+
private serverTotalCount = 0
117+
118+
get activatedCount(): number {
119+
return this.allDevicesData.filter(
120+
(d) => d.deviceInfo?.currentMode != null && d.deviceInfo.currentMode !== 'not activated'
121+
).length
122+
}
123+
124+
get discoveredCount(): number {
125+
return this.allDevicesData.filter((d) => d.deviceInfo?.discovered === true).length
126+
}
127+
128+
onTabChange(index: number): void {
129+
this.activeTab.set(index)
130+
this.applyTabFilter()
131+
}
132+
133+
private applyTabFilter(): void {
134+
let filtered: Device[]
135+
switch (this.activeTab()) {
136+
case 1:
137+
filtered = this.allDevicesData.filter(
138+
(d) => d.deviceInfo?.currentMode != null && d.deviceInfo.currentMode !== 'not activated'
139+
)
140+
this.totalCount.set(filtered.length)
141+
break
142+
case 2:
143+
filtered = this.allDevicesData.filter((d) => d.deviceInfo?.discovered === true)
144+
this.totalCount.set(filtered.length)
145+
break
146+
default:
147+
filtered = this.allDevicesData
148+
this.totalCount.set(this.serverTotalCount)
149+
break
150+
}
151+
this.devices.data = filtered
152+
}
153+
111154
get deleteDeviceLabel(): string {
112155
return this.isCloudMode
113156
? this.translate.instant('devices.actions.deactivateCloud.value')
@@ -119,6 +162,7 @@ export class DevicesComponent implements OnInit, AfterViewInit {
119162
'hostname',
120163
'guid',
121164
'status',
165+
'productType',
122166
'tags',
123167
'actions',
124168
'notification'
@@ -140,6 +184,7 @@ export class DevicesComponent implements OnInit, AfterViewInit {
140184
this.displayedColumns = [
141185
'select',
142186
'hostname',
187+
'productType',
143188
'tags',
144189
'actions',
145190
'notification'
@@ -211,6 +256,7 @@ export class DevicesComponent implements OnInit, AfterViewInit {
211256
.pipe(
212257
switchMap((res) => {
213258
this.totalCount.set(res.totalCount)
259+
this.serverTotalCount = res.totalCount
214260

215261
if (!environment.cloud) {
216262
return of(res.data) // Return as-is for non-cloud
@@ -251,7 +297,8 @@ export class DevicesComponent implements OnInit, AfterViewInit {
251297
})
252298
)
253299
.subscribe((devices) => {
254-
this.devices.data = devices
300+
this.allDevicesData = devices
301+
this.applyTabFilter()
255302

256303
// Restore selection state on data retrieval
257304
this.selectedDevices.clear()
@@ -342,6 +389,16 @@ export class DevicesComponent implements OnInit, AfterViewInit {
342389
await this.router.navigate([`/devices/${path}`])
343390
}
344391

392+
getProductType(device: Device): string {
393+
const skuNum = parseInt(device.deviceInfo?.fwSku ?? '', 10)
394+
if (isNaN(skuNum)) return ''
395+
const isISM = (skuNum & 0x10) > 0
396+
const isVPro = (skuNum & 0x08) > 0
397+
if (isISM) return 'ISM'
398+
if (isVPro) return 'vPro'
399+
return ''
400+
}
401+
345402
translateConnectionStatus(status?: boolean): string {
346403
switch (status) {
347404
case false:

src/models/models.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ export interface DeviceInfo {
3232
features: string
3333
ipAddress: string
3434
lastUpdated?: Date
35+
discovered?: boolean
3536
}
3637
export interface DeviceStats {
3738
totalCount: number

0 commit comments

Comments
 (0)