From dbb53ca9da6121ebf3251532005688398f2a16c4 Mon Sep 17 00:00:00 2001 From: Max Date: Thu, 30 May 2024 20:40:58 +0200 Subject: [PATCH] Added live refresh to admin UI - Added lastLogin UI - Added operational time --- .../src/app/adminui/adminui.component.html | 4 +- frontend/src/app/adminui/adminui.component.ts | 33 ++++++++++++-- frontend/src/app/duration.pipe.spec.ts | 8 ++++ frontend/src/app/duration.pipe.ts | 29 ++++++++++++ frontend/src/app/relative-time.pipe.spec.ts | 8 ++++ frontend/src/app/relative-time.pipe.ts | 45 +++++++++++++++++++ 6 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 frontend/src/app/duration.pipe.spec.ts create mode 100644 frontend/src/app/duration.pipe.ts create mode 100644 frontend/src/app/relative-time.pipe.spec.ts create mode 100644 frontend/src/app/relative-time.pipe.ts diff --git a/frontend/src/app/adminui/adminui.component.html b/frontend/src/app/adminui/adminui.component.html index 3429e3a..261f5ad 100644 --- a/frontend/src/app/adminui/adminui.component.html +++ b/frontend/src/app/adminui/adminui.component.html @@ -22,7 +22,7 @@
Operational For
-
2 Years
+
{{ statistics.applicationOnlineTime | duration }}
Since launch
@@ -38,7 +38,7 @@
Last Admin Login
-
2 days ago
+
{{ statistics.lastUserLogin | relativeTime }}
Most recent login
diff --git a/frontend/src/app/adminui/adminui.component.ts b/frontend/src/app/adminui/adminui.component.ts index fd2b4b4..ad8e12c 100644 --- a/frontend/src/app/adminui/adminui.component.ts +++ b/frontend/src/app/adminui/adminui.component.ts @@ -6,6 +6,8 @@ import {DevelopmentStore} from "../../store/DevelopmentStore"; import {AuthStore} from "../../store/authStore"; import {Router} from "@angular/router"; import {FormatFileSizePipePipe} from "../format-file-size-pipe.pipe"; +import {DurationPipe} from "../duration.pipe"; +import {RelativeTimePipe} from "../relative-time.pipe"; @Component({ selector: 'app-adminui', @@ -14,7 +16,9 @@ import {FormatFileSizePipePipe} from "../format-file-size-pipe.pipe"; DatePipe, DecimalPipe, NgForOf, - FormatFileSizePipePipe + FormatFileSizePipePipe, + DurationPipe, + RelativeTimePipe ], templateUrl: './adminui.component.html', styleUrl: './adminui.component.scss' @@ -25,9 +29,12 @@ export class AdminuiComponent { expiredFileUploads: any[] = []; totalFileSizeOnDisk: number = 0; totalFileDownloads = 0; + statistics: any = {}; constructor(private developmentStore: DevelopmentStore, private authStore: AuthStore, private router: Router) { - this.verifyToken(); + setInterval(() => { + this.verifyToken(); + }, 1000); } async verifyToken() { @@ -38,12 +45,14 @@ export class AdminuiComponent { } await this.fetchFileUploads(); await this.fetchExpiredFileUploads(); + await this.fetchStatistics(); await this.calculateStatistics(); } async calculateStatistics() { - console.log("Calculating statistics..."); - console.log(this.fileUploads) + this.totalFileSizeOnDisk = 0; + this.totalFileDownloads = 0; + for(let fileUpload of this.fileUploads) { this.totalFileSizeOnDisk += fileUpload.fileSize; } @@ -86,4 +95,20 @@ export class AdminuiComponent { console.error(error); } } + async fetchStatistics() { + try { + const response = await axios({ + method: 'get', + url: this.developmentStore.getBaseUrl() + 'api/v1/secure/statistics', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer ' + await firstValueFrom(this.authStore.token$) + } + }); + this.statistics = response.data; + console.log(this.statistics) + } catch (error) { + console.error(error); + } + } } diff --git a/frontend/src/app/duration.pipe.spec.ts b/frontend/src/app/duration.pipe.spec.ts new file mode 100644 index 0000000..e38345d --- /dev/null +++ b/frontend/src/app/duration.pipe.spec.ts @@ -0,0 +1,8 @@ +import { DurationPipe } from './duration.pipe'; + +describe('DurationPipe', () => { + it('create an instance', () => { + const pipe = new DurationPipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/duration.pipe.ts b/frontend/src/app/duration.pipe.ts new file mode 100644 index 0000000..f94ee9a --- /dev/null +++ b/frontend/src/app/duration.pipe.ts @@ -0,0 +1,29 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'duration', + standalone: true +}) +export class DurationPipe implements PipeTransform { + + transform(value: number): string { + if (!value) { + return '0m'; + } + + let milliseconds = value; + const days = Math.floor(milliseconds / (24 * 60 * 60 * 1000)); + milliseconds %= 24 * 60 * 60 * 1000; + const hours = Math.floor(milliseconds / (60 * 60 * 1000)); + milliseconds %= 60 * 60 * 1000; + const minutes = Math.floor(milliseconds / (60 * 1000)); + + if (days > 0) { + return `${days}d ${hours}h ${minutes}m`; + } else if (hours > 0) { + return `${hours}h ${minutes}m`; + } else { + return `${minutes}m`; + } + } +} diff --git a/frontend/src/app/relative-time.pipe.spec.ts b/frontend/src/app/relative-time.pipe.spec.ts new file mode 100644 index 0000000..ba62c09 --- /dev/null +++ b/frontend/src/app/relative-time.pipe.spec.ts @@ -0,0 +1,8 @@ +import { RelativeTimePipe } from './relative-time.pipe'; + +describe('RelativeTimePipe', () => { + it('create an instance', () => { + const pipe = new RelativeTimePipe(); + expect(pipe).toBeTruthy(); + }); +}); diff --git a/frontend/src/app/relative-time.pipe.ts b/frontend/src/app/relative-time.pipe.ts new file mode 100644 index 0000000..9016478 --- /dev/null +++ b/frontend/src/app/relative-time.pipe.ts @@ -0,0 +1,45 @@ +import { Pipe, PipeTransform } from '@angular/core'; + +@Pipe({ + name: 'relativeTime', + standalone: true, + pure: false +}) +export class RelativeTimePipe implements PipeTransform { + + transform(value: string): string { + if (!value) { + return ''; + } + + const now = new Date(); + const past = new Date(value); + const elapsed = now.getTime() - past.getTime(); + + const msPerSecond = 1000; + const msPerMinute = msPerSecond * 60; + const msPerHour = msPerMinute * 60; + const msPerDay = msPerHour * 24; + const msPerWeek = msPerDay * 7; + const msPerMonth = msPerDay * 30; + const msPerYear = msPerDay * 365; + + if (elapsed < msPerSecond) { + return 'just now'; + } else if (elapsed < msPerMinute) { + return `${Math.round(elapsed / msPerSecond)} seconds ago`; + } else if (elapsed < msPerHour) { + return `${Math.round(elapsed / msPerMinute)} minutes ago`; + } else if (elapsed < msPerDay) { + return `${Math.round(elapsed / msPerHour)} hours ago`; + } else if (elapsed < msPerWeek) { + return `${Math.round(elapsed / msPerDay)} days ago`; + } else if (elapsed < msPerMonth) { + return `${Math.round(elapsed / msPerWeek)} weeks ago`; + } else if (elapsed < msPerYear) { + return `${Math.round(elapsed / msPerMonth)} months ago`; + } else { + return `${Math.round(elapsed / msPerYear)} years ago`; + } + } +}