-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #175 from OS2iot/feature/IOT-1530_datatarget_log
Feature/iot 1530 datatarget log
- Loading branch information
Showing
50 changed files
with
1,040 additions
and
665 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 109 additions & 0 deletions
109
src/app/applications/datatarget/datatarget-detail/datatarget-detail-tabs-common.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { Location } from "@angular/common"; | ||
import { HttpResponse } from "@angular/common/http"; | ||
import { ActivatedRoute, Router } from "@angular/router"; | ||
import { DatatargetDetail } from "@applications/datatarget/datatarget-detail/datatarget-detail"; | ||
import { Datatarget } from "@applications/datatarget/datatarget.model"; | ||
import { DatatargetService } from "@applications/datatarget/datatarget.service"; | ||
import { faExclamationTriangle } from "@fortawesome/free-solid-svg-icons"; | ||
import { TranslateService } from "@ngx-translate/core"; | ||
import { DeleteDialogService } from "@shared/components/delete-dialog/delete-dialog.service"; | ||
import { OrganizationAccessScope } from "@shared/enums/access-scopes"; | ||
import { BackButton } from "@shared/models/back-button.model"; | ||
import { DropdownButton } from "@shared/models/dropdown-button.model"; | ||
import { MeService } from "@shared/services/me.service"; | ||
import { NavTab } from "@shared/types/nav-tabs.type"; | ||
import { Subscription } from "rxjs"; | ||
|
||
export abstract class DatatargetDetailTabsCommon implements DatatargetDetail { | ||
protected abstract getDetailsLink(): string; | ||
|
||
faExclamationTriangle = faExclamationTriangle; | ||
|
||
logLink: "datatarget-log" = "datatarget-log"; | ||
navTabs: NavTab[] = [ | ||
{ | ||
label: "APPLICATION.DETAILS", | ||
link: this.getDetailsLink(), | ||
index: 0, | ||
}, | ||
{ | ||
label: "GEN.LOG", | ||
link: this.logLink, | ||
index: 1, | ||
}, | ||
]; | ||
|
||
datatarget: Datatarget; | ||
backButton: BackButton = { label: "", routerLink: undefined }; | ||
dropdownButton: DropdownButton; | ||
canEdit: boolean; | ||
|
||
private subscriptions: Subscription[] = []; | ||
private deleteDialogSubscription: Subscription; | ||
|
||
constructor( | ||
route: ActivatedRoute, | ||
router: Router, | ||
translate: TranslateService, | ||
meService: MeService, | ||
private location: Location, | ||
private datatargetService: DatatargetService, | ||
public deleteDialogService: DeleteDialogService | ||
) { | ||
// Load first tab if none was selected | ||
const path = this.location.path(); | ||
if (!this.navTabs.some(tab => path.includes(tab.link))) { | ||
router.navigate([path, this.navTabs[0].link], { replaceUrl: true }); | ||
} | ||
// URL params | ||
const paramMap = route.snapshot.paramMap; | ||
const id: number = +paramMap.get("datatargetId"); | ||
const appId: number = +paramMap.get("id"); | ||
if (id) { | ||
// Fetch datatarget info | ||
this.subscriptions.push(this.getDatatarget(id)); | ||
this.dropdownButton = { | ||
label: "", | ||
editRouterLink: "../../datatarget-edit/" + id, | ||
isErasable: true, | ||
}; | ||
} | ||
// Translate button labels | ||
this.subscriptions.push( | ||
translate.get(["NAV.MY-DATATARGET", "DATATARGET.SHOW-OPTIONS"]).subscribe(translations => { | ||
this.backButton.label = translations["NAV.MY-DATATARGET"]; | ||
this.dropdownButton.label = translations["DATATARGET.SHOW-OPTIONS"]; | ||
}) | ||
); | ||
// Check user permissions | ||
this.canEdit = meService.hasAccessToTargetOrganization(OrganizationAccessScope.ApplicationWrite, undefined, appId); | ||
} | ||
|
||
protected onDestroy(): void { | ||
this.subscriptions?.forEach(s => s?.unsubscribe()); | ||
this.deleteDialogSubscription?.unsubscribe(); | ||
} | ||
|
||
private getDatatarget = (id: number) => | ||
this.datatargetService.get(id).subscribe((dataTarget: Datatarget) => { | ||
this.datatarget = dataTarget; | ||
}); | ||
|
||
onDeleteDatatarget() { | ||
this.deleteDialogSubscription?.unsubscribe(); | ||
this.deleteDialogSubscription = this.deleteDialogService.showSimpleDialog().subscribe(response => { | ||
// Do nothing if user cancels | ||
if (!response) return; | ||
this.subscriptions.push( | ||
this.datatargetService.delete(this.datatarget.id).subscribe((deleteResponse: HttpResponse<any>) => { | ||
if (deleteResponse?.ok) { | ||
this.location.back(); | ||
} else { | ||
// TODO: Show error / snackbar?? | ||
console.log("Delete failed", deleteResponse); | ||
} | ||
}) | ||
); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
43 changes: 43 additions & 0 deletions
43
src/app/applications/datatarget/datatarget-log/datatarget-log.component.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
<div class="mat-elevation-z8 datatarget-log-container"> | ||
<div class="loading-shade" *ngIf="isLoadingResults"> | ||
<mat-spinner></mat-spinner> | ||
</div> | ||
|
||
<table mat-table [dataSource]="dataSource" matSort matSortActive="createdAt" matSortDirection="desc"> | ||
<!-- Timestamp column --> | ||
<ng-container matColumnDef="createdAt"> | ||
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ "GATEWAY.STATS-TIMESTAMP" | translate }}</th> | ||
<td mat-cell *matCellDef="let element">{{ element.createdAt | date:'dd-MM-yyyy - HH:mm:ss' }}</td> | ||
</ng-container> | ||
|
||
<!-- Type column --> | ||
<ng-container matColumnDef="type"> | ||
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ "DATATARGET-TABLE.TYPE" | translate }}</th> | ||
<td mat-cell *matCellDef="let element"> | ||
<fa-icon *ngIf="element.type === 'OK'" [icon]="faCheckCircle" class="fa-ok"></fa-icon> | ||
<fa-icon *ngIf="element.type === 'ERROR'" [icon]="faExclamationTriangle" class="fa-error"></fa-icon> | ||
{{ ('DATATARGET.RESPONSE_TYPE.' + element.type) | translate }} | ||
</td> | ||
</ng-container> | ||
|
||
<!-- Message column --> | ||
<ng-container matColumnDef="message"> | ||
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ "GEN.MESSAGE" | translate }}</th> | ||
<td mat-cell *matCellDef="let element">{{ element.statusCode }} {{ element.message }}</td> | ||
</ng-container> | ||
|
||
<!-- Device column --> | ||
<ng-container matColumnDef="device"> | ||
<th mat-header-cell *matHeaderCellDef mat-sort-header>{{ "GEN.DEVICE" | translate }}</th> | ||
<td mat-cell *matCellDef="let element">{{ element.iotDevice?.name }}</td> | ||
</ng-container> | ||
|
||
<!-- Actually showing the data --> | ||
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> | ||
<tr mat-row *matRowDef="let row; columns: displayedColumns"></tr> | ||
</table> | ||
|
||
<!-- Pagination --> | ||
<mat-paginator [pageSizeOptions]="pageSizeOptions" [pageSize]="pageSize" showFirstLastButtons> | ||
</mat-paginator> | ||
</div> |
11 changes: 11 additions & 0 deletions
11
src/app/applications/datatarget/datatarget-log/datatarget-log.component.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
:host { | ||
.datatarget-log-container { | ||
margin: 2em; | ||
} | ||
.fa-ok { | ||
color: green !important; | ||
} | ||
.fa-error { | ||
color: red !important; | ||
} | ||
} |
23 changes: 23 additions & 0 deletions
23
src/app/applications/datatarget/datatarget-log/datatarget-log.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
|
||
import { DatatargetLogComponent } from './datatarget-log.component'; | ||
|
||
describe('DatatargetLogComponent', () => { | ||
let component: DatatargetLogComponent; | ||
let fixture: ComponentFixture<DatatargetLogComponent>; | ||
|
||
beforeEach(async () => { | ||
await TestBed.configureTestingModule({ | ||
imports: [DatatargetLogComponent] | ||
}) | ||
.compileComponents(); | ||
|
||
fixture = TestBed.createComponent(DatatargetLogComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
57 changes: 57 additions & 0 deletions
57
src/app/applications/datatarget/datatarget-log/datatarget-log.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import { AfterViewInit, Component, OnDestroy, ViewChild } from "@angular/core"; | ||
import { MatPaginator } from "@angular/material/paginator"; | ||
import { MatSort } from "@angular/material/sort"; | ||
import { MatTableDataSource } from "@angular/material/table"; | ||
import { ActivatedRoute } from "@angular/router"; | ||
import { environment } from "@environments/environment"; | ||
import { faCheckCircle, faExclamationTriangle } from "@fortawesome/free-solid-svg-icons"; | ||
import { DefaultPageSizeOptions } from "@shared/constants/page.constants"; | ||
import { Subscription } from "rxjs"; | ||
import { DatatargetLog } from "./datatarget-log.model"; | ||
import { DatatargetLogService } from "./datatarget-log.service"; | ||
|
||
@Component({ | ||
selector: "app-datatarget-log", | ||
templateUrl: "./datatarget-log.component.html", | ||
styleUrl: "./datatarget-log.component.scss", | ||
}) | ||
export class DatatargetLogComponent implements OnDestroy, AfterViewInit { | ||
@ViewChild(MatPaginator) paginator: MatPaginator; | ||
@ViewChild(MatSort) sort: MatSort; | ||
|
||
displayedColumns: string[] = ["createdAt", "type", "message", "device"]; | ||
pageSizeOptions = DefaultPageSizeOptions; | ||
pageSize = environment.tablePageSize; | ||
faExclamationTriangle = faExclamationTriangle; | ||
faCheckCircle = faCheckCircle; | ||
|
||
dataSource = new MatTableDataSource<DatatargetLog>(); | ||
isLoadingResults = true; | ||
|
||
private datatargetLogSubscription: Subscription; | ||
|
||
constructor(datatargetLogService: DatatargetLogService, route: ActivatedRoute) { | ||
const id: number = +route.parent.snapshot.paramMap.get("datatargetId"); | ||
|
||
this.datatargetLogSubscription = datatargetLogService.get(id).subscribe(logs => { | ||
this.dataSource = new MatTableDataSource<DatatargetLog>(logs); | ||
this.setViewChildren(); | ||
this.isLoadingResults = false; | ||
}); | ||
} | ||
|
||
ngAfterViewInit(): void { | ||
this.setViewChildren(); | ||
} | ||
|
||
ngOnDestroy(): void { | ||
this.datatargetLogSubscription?.unsubscribe(); | ||
} | ||
|
||
private setViewChildren = () => { | ||
if (this.dataSource) { | ||
this.dataSource.paginator = this.paginator; | ||
this.dataSource.sort = this.sort; | ||
} | ||
}; | ||
} |
10 changes: 10 additions & 0 deletions
10
src/app/applications/datatarget/datatarget-log/datatarget-log.model.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { IotDevice } from "@applications/iot-devices/iot-device.model"; | ||
|
||
export class DatatargetLog { | ||
createdAt: Date; | ||
|
||
type: string; | ||
message: string; | ||
statusCode?: number; | ||
iotDevice?: IotDevice; | ||
} |
17 changes: 17 additions & 0 deletions
17
src/app/applications/datatarget/datatarget-log/datatarget-log.service.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { Injectable } from "@angular/core"; | ||
import { RestService } from "@shared/services/rest.service"; | ||
import { Observable } from "rxjs"; | ||
import { DatatargetLog } from "./datatarget-log.model"; | ||
|
||
const baseUrl = "datatarget-log"; | ||
|
||
@Injectable({ | ||
providedIn: "root", | ||
}) | ||
export class DatatargetLogService { | ||
constructor(private restService: RestService) {} | ||
|
||
get(id: number): Observable<DatatargetLog[]> { | ||
return this.restService.get(baseUrl, null, id); | ||
} | ||
} |
Oops, something went wrong.