Skip to content

Commit 33497a4

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 8162dd7 commit 33497a4

17 files changed

Lines changed: 376 additions & 75 deletions

package-lock.json

Lines changed: 0 additions & 72 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/app/devices/devices.component.html

Lines changed: 13 additions & 1 deletion
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]="allTabLabel"></mat-tab>
51+
<mat-tab [label]="activatedTabLabel"></mat-tab>
52+
<mat-tab [label]="discoveredTabLabel"></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%">
@@ -120,6 +125,13 @@ <h3 class="flex justify-center">
120125
}
121126
</mat-cell>
122127
</ng-container>
128+
<!-- productType Column -->
129+
<ng-container matColumnDef="productType">
130+
<mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'devices.table.productType.value' | translate }}</mat-header-cell>
131+
<mat-cell *matCellDef="let element" (click)="navigateTo(element.guid)">
132+
{{ getProductType(element) }}
133+
</mat-cell>
134+
</ng-container>
123135
<!-- tags Column -->
124136
<ng-container matColumnDef="tags">
125137
<mat-header-cell *matHeaderCellDef mat-sort-header>
@@ -198,7 +210,7 @@ <h3 class="flex justify-center">
198210
</mat-table>
199211
}
200212

201-
@if (totalCount() !== 0) {
213+
@if (activeTab() === 0 && totalCount() !== 0) {
202214
<div>
203215
<mat-paginator
204216
[pageSizeOptions]="[25, 50, 100]"

src/app/devices/devices.component.spec.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,4 +250,99 @@ describe('DevicesComponent', () => {
250250
component.tagFilterChange(matSelectChange)
251251
expect(component.filteredTags()).toBe(mockValue)
252252
})
253+
254+
describe('getProductType', () => {
255+
it('should return ISM when bit 4 (0x10) is set', () => {
256+
const device = { ...device01, deviceInfo: { fwSku: '16' } } as Device // 0x10 = 16
257+
expect(component.getProductType(device)).toBe('ISM')
258+
})
259+
260+
it('should return vPro when bit 3 (0x08) is set and bit 4 is not', () => {
261+
const device = { ...device01, deviceInfo: { fwSku: '8' } } as Device // 0x08 = 8
262+
expect(component.getProductType(device)).toBe('vPro')
263+
})
264+
265+
it('should return ISM when both bit 4 and bit 3 are set (ISM takes priority)', () => {
266+
const device = { ...device01, deviceInfo: { fwSku: '24' } } as Device // 0x18 = 24
267+
expect(component.getProductType(device)).toBe('ISM')
268+
})
269+
270+
it('should return empty string when neither bit is set', () => {
271+
const device = { ...device01, deviceInfo: { fwSku: '4' } } as Device // 0x04 = 4
272+
expect(component.getProductType(device)).toBe('')
273+
})
274+
275+
it('should return empty string when fwSku is undefined', () => {
276+
const device = { ...device01, deviceInfo: undefined } as Device
277+
expect(component.getProductType(device)).toBe('')
278+
})
279+
280+
it('should return empty string when fwSku is not a number', () => {
281+
const device = { ...device01, deviceInfo: { fwSku: 'notanumber' } } as Device
282+
expect(component.getProductType(device)).toBe('')
283+
})
284+
})
285+
286+
describe('onTabChange / applyTabFilter', () => {
287+
beforeEach(() => {
288+
component.allDevicesData = [
289+
{ ...device01, deviceInfo: { currentMode: 'acm', discovered: false } },
290+
{ ...device02, deviceInfo: { currentMode: 'not activated', discovered: true } }
291+
]
292+
})
293+
294+
it('should show all devices on tab 0', () => {
295+
component.onTabChange(0)
296+
expect(component.devices.data.length).toBe(2)
297+
})
298+
299+
it('should filter to activated devices on tab 1', () => {
300+
component.onTabChange(1)
301+
expect(component.devices.data.length).toBe(1)
302+
expect(component.devices.data[0].guid).toBe(device01.guid)
303+
})
304+
305+
it('should filter to discovered devices on tab 2', () => {
306+
component.onTabChange(2)
307+
expect(component.devices.data.length).toBe(1)
308+
expect(component.devices.data[0].guid).toBe(device02.guid)
309+
})
310+
311+
it('should set totalCount to serverTotalCount on tab 0', () => {
312+
;(component as any).serverTotalCount = 42
313+
component.onTabChange(0)
314+
expect(component.totalCount()).toBe(42)
315+
})
316+
317+
it('should set totalCount to filtered length on tab 1', () => {
318+
component.onTabChange(1)
319+
expect(component.totalCount()).toBe(1)
320+
})
321+
322+
it('should set totalCount to filtered length on tab 2', () => {
323+
component.onTabChange(2)
324+
expect(component.totalCount()).toBe(1)
325+
})
326+
})
327+
328+
describe('isNoData', () => {
329+
it('should return false when allDevicesData has entries regardless of totalCount', () => {
330+
component.allDevicesData = [device01]
331+
component.isLoading.set(false)
332+
component.totalCount.set(0) // filtered tab has 0 — should not trigger no-data
333+
expect(component.isNoData()).toBeFalse()
334+
})
335+
336+
it('should return true only when allDevicesData is empty and not loading', () => {
337+
component.allDevicesData = []
338+
component.isLoading.set(false)
339+
expect(component.isNoData()).toBeTrue()
340+
})
341+
342+
it('should return false when loading even if allDevicesData is empty', () => {
343+
component.allDevicesData = []
344+
component.isLoading.set(true)
345+
expect(component.isNoData()).toBeFalse()
346+
})
347+
})
253348
})

0 commit comments

Comments
 (0)