diff --git a/frontend/src/app/adminui/adminui.component.html b/frontend/src/app/adminui/adminui.component.html
index ac3e976..3429e3a 100644
--- a/frontend/src/app/adminui/adminui.component.html
+++ b/frontend/src/app/adminui/adminui.component.html
@@ -1 +1,146 @@
-
adminui works!
+
+
Admin Dashboard
+
+
+
+
+
+
Total Files Uploaded
+
{{ fileUploads.length + expiredFileUploads.length }}
+
Since launch
+
+
+
+
+
+
Total File Size on Disk
+
{{ totalFileSizeOnDisk | formatFileSizePipe }}
+
Across all files
+
+
+
+
+
+
Operational For
+
2 Years
+
Since launch
+
+
+
+
+
+
Total Downloads
+
{{ totalFileDownloads }}
+
All time
+
+
+
+
+
+
Last Admin Login
+
2 days ago
+
Most recent login
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Active file uploads
+
+
+
+
+ Entity ID |
+ File ID |
+ File Name |
+ File Size |
+ Single Download |
+ Disabled |
+ Upload Date |
+ Uploaded By IP |
+ Download Count |
+
+ Password Protected |
+
+
+
+
+ {{ file.id }} |
+ {{ file.fileId }} |
+ {{ file.fileName }} |
+ {{ file.fileSize | formatFileSizePipe }} |
+ {{ file.singleDownload ? 'true' : 'false' }} |
+ {{ file.disabled ? 'true' : 'false' }} |
+ {{ file.uploadDate | date: 'medium' }} |
+ {{ file.uploadedByIpAddress }} |
+ {{ file.downloadCount }} |
+
+ {{ file.passwordProtected ? 'true' : 'false' }} |
+
+
+
+
+
+
Expired file uploads
+
+
+
+
+ Entity ID |
+ File ID |
+ File Name |
+ File Size |
+ Single Download |
+ Disabled |
+ Upload Date |
+ Uploaded By IP |
+ Download Count |
+
+ Password Protected |
+
+
+
+
+ {{ file.id }} |
+ {{ file.fileId }} |
+ {{ file.fileName }} |
+ {{ file.fileSize | number }} |
+ {{ file.singleDownload ? 'true' : 'false' }} |
+ {{ file.disabled ? 'true' : 'false' }} |
+ {{ file.uploadDate | date: 'medium' }} |
+ {{ file.uploadedByIpAddress }} |
+ {{ file.downloadCount }} |
+
+ {{ file.passwordProtected ? 'true' : 'false' }} |
+
+
+
+
+
diff --git a/frontend/src/app/adminui/adminui.component.ts b/frontend/src/app/adminui/adminui.component.ts
index 948bec9..fd2b4b4 100644
--- a/frontend/src/app/adminui/adminui.component.ts
+++ b/frontend/src/app/adminui/adminui.component.ts
@@ -1,12 +1,89 @@
import { Component } from '@angular/core';
+import {DatePipe, DecimalPipe, NgForOf} from "@angular/common";
+import axios from "axios";
+import {firstValueFrom} from "rxjs";
+import {DevelopmentStore} from "../../store/DevelopmentStore";
+import {AuthStore} from "../../store/authStore";
+import {Router} from "@angular/router";
+import {FormatFileSizePipePipe} from "../format-file-size-pipe.pipe";
@Component({
selector: 'app-adminui',
standalone: true,
- imports: [],
+ imports: [
+ DatePipe,
+ DecimalPipe,
+ NgForOf,
+ FormatFileSizePipePipe
+ ],
templateUrl: './adminui.component.html',
styleUrl: './adminui.component.scss'
})
export class AdminuiComponent {
+ fileUploads: any[] = [];
+ expiredFileUploads: any[] = [];
+ totalFileSizeOnDisk: number = 0;
+ totalFileDownloads = 0;
+
+ constructor(private developmentStore: DevelopmentStore, private authStore: AuthStore, private router: Router) {
+ this.verifyToken();
+ }
+
+ async verifyToken() {
+ if(await firstValueFrom(this.authStore.token$) === "") {
+ console.log("No token present, redirecting to login...");
+ await this.router.navigate(['/login']);
+ return;
+ }
+ await this.fetchFileUploads();
+ await this.fetchExpiredFileUploads();
+ await this.calculateStatistics();
+ }
+
+ async calculateStatistics() {
+ console.log("Calculating statistics...");
+ console.log(this.fileUploads)
+ for(let fileUpload of this.fileUploads) {
+ this.totalFileSizeOnDisk += fileUpload.fileSize;
+ }
+
+ for(let fileUpload of this.expiredFileUploads) {
+ this.totalFileDownloads += fileUpload.downloadCount;
+ }
+ for(let fileUpload of this.fileUploads) {
+ this.totalFileDownloads += fileUpload.downloadCount;
+ }
+ }
+
+ async fetchFileUploads() {
+ try {
+ const response = await axios({
+ method: 'get',
+ url: this.developmentStore.getBaseUrl() + 'api/v1/secure/upload-history',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer ' + await firstValueFrom(this.authStore.token$)
+ }
+ });
+ this.fileUploads = response.data;
+ } catch (error) {
+ console.error(error);
+ }
+ }
+ async fetchExpiredFileUploads() {
+ try {
+ const response = await axios({
+ method: 'get',
+ url: this.developmentStore.getBaseUrl() + 'api/v1/secure/expired-upload-history',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer ' + await firstValueFrom(this.authStore.token$)
+ }
+ });
+ this.expiredFileUploads = response.data;
+ } catch (error) {
+ console.error(error);
+ }
+ }
}
diff --git a/frontend/src/app/app.routes.ts b/frontend/src/app/app.routes.ts
index 51d840a..4f6ea4f 100644
--- a/frontend/src/app/app.routes.ts
+++ b/frontend/src/app/app.routes.ts
@@ -5,6 +5,7 @@ import {DownloadComponent} from "./download/download.component";
import {CreditsComponent} from "./credits/credits.component";
import {LicensesComponent} from "./credits/licenses/licenses.component";
import {LoginComponent} from "./login/login.component";
+import {AdminuiComponent} from "./adminui/adminui.component";
export const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
@@ -14,6 +15,7 @@ export const routes: Routes = [
{ path: 'credits', component: CreditsComponent },
{ path: 'licenses', component: LicensesComponent },
{ path: 'login', component: LoginComponent },
+ { path: 'secure/administration', component: AdminuiComponent},
// { path: 'download/:id', component: DownloadComponent }
{ path: '**', redirectTo: 'home' }
];
diff --git a/frontend/src/app/login/login.component.html b/frontend/src/app/login/login.component.html
index 3c45505..2c2cb22 100644
--- a/frontend/src/app/login/login.component.html
+++ b/frontend/src/app/login/login.component.html
@@ -8,7 +8,7 @@
+ [ngClass]="{'input-error': loginFailed}" autofocus >