Skip to content

Commit

Permalink
IOT-1331: Moved column selector to own component + implemented column…
Browse files Browse the repository at this point in the history
… selection… (#150)

* Fixed routing of gateway list + fixed memory leak by unsubscribing properly from gateway fetches

* Fixed routing errors in gateway list

* Changed mqtt datatarget topic placeholder + added tooltip

* Added additional text changes from Product Owner

* Removed maxLenght from device AND gateway EUI, now removes non-hex digits on submit

* Added sticky to name column on gateway status table

* Implemented application table column selection

* Removed unused controller name from select

* Moved column selector to own component + implemented column selection on iot-device table
  • Loading branch information
fcv-iteratorIt committed Dec 5, 2023
1 parent ae520ae commit a9603f3
Show file tree
Hide file tree
Showing 12 changed files with 307 additions and 157 deletions.
Original file line number Diff line number Diff line change
@@ -1,30 +1,8 @@
<div class="select-container">
<mat-select
class="form-control table-select"
multiple="true"
[(value)]="optionalColumnsSelected"
(selectionChange)="handleColumnSelection($event)"
panelClass="tall"
>
<mat-option disabled>
<button
mat-raised-button
class="mat-primary fill text-sm"
(click)="selectAll()">
{{'QUESTION.DATATARGET.SELECTALLDEVICES' | translate}}
</button>
<button
mat-raised-button
class="mat-primary fill text-sm"
(click)="deSelectAll()">
{{'QUESTION.DATATARGET.DESELECTALLDEVICES' | translate}}
</button>
</mat-option>
<mat-option *ngFor="let option of optionalColumnOptions" [value]="option.id">
{{option.display | translate}}
</mat-option>
</mat-select>
</div>
<app-column-selector
[(displayedColumns)]="displayedColumns"
[columnDefinitions]="columnDefinitions"
[localStorageKey]="applicationSavedColumns"
></app-column-selector>

<div class="mat-elevation-z8">
<div class="loading-shade" *ngIf="isLoadingResults">
Expand Down Expand Up @@ -69,15 +47,15 @@

<!-- Devices Column -->
<ng-container matColumnDef="devices">
<th mat-header-cell *matHeaderCellDef class="col-2">
<th mat-header-cell *matHeaderCellDef mat-sort-header class="col-2">
{{ 'APPLICATION-TABLE.IOT-DEVICES' | translate }}</th>
<td mat-cell *matCellDef="let element">
{{element?.iotDevices?.length ?? 0}}
</td>
</ng-container>

<ng-container matColumnDef="dataTargets">
<th mat-header-cell *matHeaderCellDef class="col-1">
<th mat-header-cell *matHeaderCellDef mat-sort-header class="col-1">
{{ 'APPLICATION-TABLE.DATA-TARGETS' | translate}}
</th>
<td mat-cell *matCellDef="let application">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
.table-select {
width: 180px;
margin: 5px;

}

.select-container {
display: flex;
flex-direction: row;
justify-content: flex-end;
}

.flag-icon {
color: red;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
AfterViewInit,
ChangeDetectorRef,
Component,
Input,
OnInit,
Expand All @@ -16,13 +17,12 @@ import { DeleteDialogService } from '@shared/components/delete-dialog/delete-dia
import { merge, Observable, of as observableOf } from 'rxjs';
import { catchError, map, startWith, switchMap } from 'rxjs/operators';
import { DefaultPageSizeOptions } from '@shared/constants/page.constants';
import { MatSelectChange } from '@angular/material/select';
import { ControlledProperty } from '@shared/models/controlled-property.model';
import { ApplicationDeviceTypeEntries } from '@shared/enums/device-type';
import { ApplicationDeviceType } from '@applications/models/application-device-type.model';
import { Datatarget } from '@applications/datatarget/datatarget.model';
import { faFlag } from '@fortawesome/free-solid-svg-icons';
import { FormControl, FormGroup } from '@angular/forms';
import { TableColumn } from '@shared/types/table.type';

const columnDefinitions: TableColumn[] = [
{
Expand Down Expand Up @@ -123,9 +123,6 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit {
faFlagIcon = faFlag;

displayedColumns: string[] = [];
optionalColumnsSelected: string[] = [];
optionalColumnOptions: TableColumn[] = [];
d;

data: Application[] = [];

Expand All @@ -144,27 +141,13 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit {
public translate: TranslateService,
private applicationService: ApplicationService,
private router: Router,
private deleteDialogService: DeleteDialogService
private deleteDialogService: DeleteDialogService,
private cdRef: ChangeDetectorRef
) {}

ngOnInit() {
this.optionalColumnOptions = columnDefinitions.filter((o) => o.toggleable);

const userDisplayedColumns = localStorage.getItem(
this.applicationSavedColumns
);
if (userDisplayedColumns) {
const chosenColumns = userDisplayedColumns.split(',');
this.displayedColumns = chosenColumns;
this.optionalColumnsSelected = chosenColumns;
} else {
this.optionalColumnsSelected = columnDefinitions
.filter((o) => o.toggleable && o.default)
.map((o) => o.id);
this.displayedColumns = columnDefinitions
.filter((o) => o.default)
.map((o) => o.id);
}
// Detect changes done by child column selector
this.cdRef.detectChanges();
}

ngAfterViewInit() {
Expand Down Expand Up @@ -235,20 +218,6 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit {
this.router.navigate(['applications', 'edit-application', applicationId]);
}

handleColumnSelection({
source: { value: selectedColumns },
}: MatSelectChange) {
const displayedColumns = columnDefinitions
.filter((o) => !o.toggleable || selectedColumns.includes(o.id))
.map((o) => o.id);

localStorage.setItem(
this.applicationSavedColumns,
displayedColumns.join(',')
);
this.displayedColumns = displayedColumns;
}

mapControlledProperties(value: ControlledProperty[]) {
if (!value.length) return '-';

Expand Down Expand Up @@ -282,23 +251,5 @@ export class ApplicationsTableComponent implements AfterViewInit, OnInit {
return !!result;
}

selectAll() {
const allOptional = this.optionalColumnOptions.map((o) => o.id);
this.handleColumnSelection({
source: { value: allOptional },
} as MatSelectChange);
this.optionalColumnsSelected = allOptional;
}

deSelectAll() {
this.handleColumnSelection({ source: { value: [] } } as MatSelectChange);
this.optionalColumnsSelected = [];
}
}

interface TableColumn {
id: string;
display: string;
default: boolean;
toggleable: boolean;
protected readonly columnDefinitions = columnDefinitions;
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
<app-column-selector
[(displayedColumns)]="displayedColumns"
[columnDefinitions]="columnDefinitions"
[localStorageKey]="iotDeviceSavedColumns"
[placeholder]=""
></app-column-selector>

<div class="mat-elevation-z8">
<div class="loading-shade" *ngIf="isLoadingResults">
<mat-spinner *ngIf="isLoadingResults"></mat-spinner>
Expand All @@ -15,60 +22,47 @@
<th mat-sort-header="name" *matHeaderCellDef mat-header-cell>
{{ 'APPLICATION-TABLE.NAME' | translate }}
</th>
<td mat-cell *matCellDef="let element">
<a [routerLink]="['../iot-device', element.id]" routerLinkActive="active" class="device-link">{{element.name}}</a>
<td mat-cell *matCellDef="let iotDevice">
<a [routerLink]="['../iot-device', iotDevice.id]" routerLinkActive="active" class="device-link">{{iotDevice.name}}</a>
</td>
</ng-container>

<!-- Technology Column -->
<ng-container matColumnDef="technology">
<th mat-header-cell *matHeaderCellDef>{{ 'IOT-TABLE.NETWORK-TECHNOLOGY' | translate }}</th>
<td mat-cell *matCellDef="let element">{{"IOT-DEVICE-TYPES." + element.type | translate}}</td>
<ng-container matColumnDef="type">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'IOT-TABLE.NETWORK-TECHNOLOGY' | translate }}</th>
<td mat-cell *matCellDef="let iotDevice">{{"IOT-DEVICE-TYPES." + iotDevice.type | translate }}</td>
</ng-container>

<!-- Alarm Column -->
<ng-container matColumnDef="alarm">
<th mat-header-cell *matHeaderCellDef>{{ 'IOT-TABLE.ALARM' | translate }}</th>
<td mat-cell *matCellDef="let element">
N/A
</td>
<ng-container matColumnDef="deviceModel">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'IOTDEVICE.DEVICEMODEL' | translate }}</th>
<td mat-cell *matCellDef="let iotDevice">{{ iotDevice.deviceModel?.body?.name ?? '-' }}</td>
</ng-container>

<!-- Battery Column -->
<ng-container matColumnDef="battery">
<th *matHeaderCellDef mat-header-cell>
{{ 'IOT-TABLE.BATTERY' | translate }}
</th>
<td mat-cell *matCellDef="let element">
<div *ngIf="element.type === 'LORAWAN'; else noBatteryStatus">
<app-batteri-status [color]="batteryStatusColor" [percentage]="getBatteryProcentage(element)">
</app-batteri-status>
</div>
<ng-template #noBatteryStatus>
<div>
{{ 'IOTDEVICE-TABLE-ROW.NOT-SUPPORTED-SHORT' | translate }}
</div>
</ng-template>
</td>
<ng-container matColumnDef="deviceProfileName">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'IOTDEVICE.LORA.DEVICEPROFILE' | translate }}</th>
<td mat-cell *matCellDef="let iotDevice">{{ iotDevice.deviceProfileName ?? '-'}}</td>
</ng-container>

<!-- Active Column -->
<ng-container matColumnDef="active">
<th mat-header-cell *matHeaderCellDef mat-sort-header="active">
{{ 'IOT-TABLE.ACTIVE' | translate }}
</th>
<td mat-cell *matCellDef="let element">{{lastActive(element)}}</td>
<ng-container matColumnDef="deviceEUI">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'IOT-TABLE.DEV-EUI' | translate }}</th>
<td mat-cell *matCellDef="let iotDevice">{{iotDevice.deviceEUI ?? '-'}}</td>
</ng-container>

<ng-container matColumnDef="OTAAapplicationKey">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'IOT-TABLE.APP-KEY' | translate }}</th>
<td mat-cell *matCellDef="let iotDevice">{{iotDevice.OTAAapplicationKey ?? '-'}}</td>
</ng-container>


<!-- RSSI column -->
<ng-container matColumnDef="rssi">
<th *matHeaderCellDef mat-header-cell mat-sort-header="rssi">
{{ 'IOT-TABLE.RSSI' | translate }}
</th>
<td mat-cell *matCellDef="let element">
<ng-container *ngIf="element.type === 'LORAWAN' || element.type === 'SIGFOX'; else notSupported">
<div *ngIf="element.latestReceivedMessage?.rssi; else notAvailable">
{{element.latestReceivedMessage.rssi}}
<td mat-cell *matCellDef="let iotDevice">
<ng-container *ngIf="iotDevice.type === 'LORAWAN' || iotDevice.type === 'SIGFOX'; else notSupported">
<div *ngIf="iotDevice.latestReceivedMessage?.rssi; else notAvailable">
{{iotDevice.latestReceivedMessage.rssi}}
</div>
</ng-container>
</td>
Expand All @@ -79,30 +73,61 @@
<th *matHeaderCellDef mat-header-cell mat-sort-header="snr">
{{ 'IOT-TABLE.SNR' | translate }}
</th>
<td mat-cell *matCellDef="let element">
<ng-container *ngIf="element.type === 'LORAWAN' || element.type === 'SIGFOX'; else notSupported">
<div *ngIf="element.latestReceivedMessage?.snr; else notAvailable">
{{element.latestReceivedMessage?.snr}}
<td mat-cell *matCellDef="let iotDevice">
<ng-container *ngIf="iotDevice.type === 'LORAWAN' || iotDevice.type === 'SIGFOX'; else notSupported">
<div *ngIf="iotDevice.latestReceivedMessage?.snr; else notAvailable">
{{iotDevice.latestReceivedMessage?.snr}}
</div>
</ng-container>
</td>
</ng-container>

<ng-container matColumnDef="dataTargets">
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ 'APPLICATION-TABLE.DATA-TARGETS' | translate }}</th>
<td mat-cell *matCellDef="let iotDevice">{{iotDevice.connections?.length ?? 0}}</td>
</ng-container>

<!-- Battery Column -->
<ng-container matColumnDef="battery">
<th *matHeaderCellDef mat-header-cell>
{{ 'IOT-TABLE.BATTERY' | translate }}
</th>
<td mat-cell *matCellDef="let iotDevice">
<div *ngIf="iotDevice.type === 'LORAWAN'; else noBatteryStatus">
<app-batteri-status [color]="batteryStatusColor" [percentage]="getBatteryProcentage(iotDevice)">
</app-batteri-status>
</div>
<ng-template #noBatteryStatus>
<div>
{{ 'IOTDEVICE-TABLE-ROW.NOT-SUPPORTED-SHORT' | translate }}
</div>
</ng-template>
</td>
</ng-container>

<!-- Active Column -->
<ng-container matColumnDef="active">
<th mat-header-cell *matHeaderCellDef mat-sort-header="active">
{{ 'IOT-TABLE.ACTIVE' | translate }}
</th>
<td mat-cell *matCellDef="let iotDevice">{{lastActive(iotDevice)}}</td>
</ng-container>

<ng-container matColumnDef="menu">
<th mat-header-cell *matHeaderCellDef></th>
<td mat-cell *matCellDef="let element">
<td mat-cell *matCellDef="let iotDevice">
<div class="dropdown" *ngIf="canEdit">
<a href="#" role="button" id="tableRowDropdown-{{element.id}}" class="applicationRow__edit dropdown-toggle"
<a href="#" role="button" id="tableRowDropdown-{{iotDevice.id}}" class="applicationRow__edit dropdown-toggle"
data-toggle="dropdown" aria-expanded="false"
[attr.aria-label]="'APPLICATION-TABLE-ROW.SHOW-OPTIONS' | translate"></a>
<ul class="dropdown-menu dropdown-menu--table" attr.aria-labelledby="tableRowDropdown-{{element.id}}">
<ul class="dropdown-menu dropdown-menu--table" attr.aria-labelledby="tableRowDropdown-{{iotDevice.id}}">
<li class="dropdown-item">
<a [routerLink]="['../iot-device-edit', element.id]" routerLinkActive="active">{{ 'IOTDEVICE-TABLE-ROW.EDIT'
<a [routerLink]="['../iot-device-edit', iotDevice.id]" routerLinkActive="active">{{ 'IOTDEVICE-TABLE-ROW.EDIT'
| translate }}
</a>
</li>
<li class="dropdown-item">
<a (click)="clickDelete(element)" [routerLink]="[]">{{ 'IOTDEVICE-TABLE-ROW.DELETE' | translate }}</a>
<a (click)="clickDelete(iotDevice)" [routerLink]="[]">{{ 'IOTDEVICE-TABLE-ROW.DELETE' | translate }}</a>
</li>
</ul>
</div>
Expand Down

0 comments on commit a9603f3

Please sign in to comment.