diff --git a/frontend/src/app/adminui/adminui.component.html b/frontend/src/app/adminui/adminui.component.html
new file mode 100644
index 0000000..ac3e976
--- /dev/null
+++ b/frontend/src/app/adminui/adminui.component.html
@@ -0,0 +1 @@
+
adminui works!
diff --git a/frontend/src/app/adminui/adminui.component.scss b/frontend/src/app/adminui/adminui.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/src/app/adminui/adminui.component.spec.ts b/frontend/src/app/adminui/adminui.component.spec.ts
new file mode 100644
index 0000000..68793fb
--- /dev/null
+++ b/frontend/src/app/adminui/adminui.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { AdminuiComponent } from './adminui.component';
+
+describe('AdminuiComponent', () => {
+ let component: AdminuiComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [AdminuiComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(AdminuiComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/adminui/adminui.component.ts b/frontend/src/app/adminui/adminui.component.ts
new file mode 100644
index 0000000..948bec9
--- /dev/null
+++ b/frontend/src/app/adminui/adminui.component.ts
@@ -0,0 +1,12 @@
+import { Component } from '@angular/core';
+
+@Component({
+ selector: 'app-adminui',
+ standalone: true,
+ imports: [],
+ templateUrl: './adminui.component.html',
+ styleUrl: './adminui.component.scss'
+})
+export class AdminuiComponent {
+
+}
diff --git a/frontend/src/app/app.routes.ts b/frontend/src/app/app.routes.ts
index 4de0e46..51d840a 100644
--- a/frontend/src/app/app.routes.ts
+++ b/frontend/src/app/app.routes.ts
@@ -4,6 +4,7 @@ import {UploadComponent} from "./upload/upload.component";
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";
export const routes: Routes = [
{ path: '', redirectTo: 'home', pathMatch: 'full' },
@@ -12,6 +13,7 @@ export const routes: Routes = [
{ path: 'download', component: DownloadComponent },
{ path: 'credits', component: CreditsComponent },
{ path: 'licenses', component: LicensesComponent },
+ { path: 'login', component: LoginComponent },
// { path: 'download/:id', component: DownloadComponent }
{ path: '**', redirectTo: 'home' }
];
diff --git a/frontend/src/app/download/download.component.html b/frontend/src/app/download/download.component.html
index 0965040..91ea066 100644
--- a/frontend/src/app/download/download.component.html
+++ b/frontend/src/app/download/download.component.html
@@ -8,7 +8,7 @@
+ (keydown.enter)="requestDownload()"/>
+
+
Login to SharePulse
+
+
+ Login to SharePulse to access the administrative dashboard and manage uploaded files. Please note that registration is disabled.
+
+
+
+
diff --git a/frontend/src/app/login/login.component.scss b/frontend/src/app/login/login.component.scss
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/src/app/login/login.component.spec.ts b/frontend/src/app/login/login.component.spec.ts
new file mode 100644
index 0000000..1e19e5d
--- /dev/null
+++ b/frontend/src/app/login/login.component.spec.ts
@@ -0,0 +1,23 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { LoginComponent } from './login.component';
+
+describe('LoginComponent', () => {
+ let component: LoginComponent;
+ let fixture: ComponentFixture;
+
+ beforeEach(async () => {
+ await TestBed.configureTestingModule({
+ imports: [LoginComponent]
+ })
+ .compileComponents();
+
+ fixture = TestBed.createComponent(LoginComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+});
diff --git a/frontend/src/app/login/login.component.ts b/frontend/src/app/login/login.component.ts
new file mode 100644
index 0000000..a40d2e0
--- /dev/null
+++ b/frontend/src/app/login/login.component.ts
@@ -0,0 +1,60 @@
+import { Component } from '@angular/core';
+import {DevelopmentStore} from "../../store/DevelopmentStore";
+import {FormsModule} from "@angular/forms";
+import axios from "axios";
+import {NgClass, NgIf} from "@angular/common";
+import {AuthStore} from "../../store/authStore";
+import {firstValueFrom} from "rxjs";
+
+@Component({
+ selector: 'app-login',
+ standalone: true,
+ imports: [
+ FormsModule,
+ NgClass,
+ NgIf
+ ],
+ templateUrl: './login.component.html',
+ styleUrl: './login.component.scss'
+})
+export class LoginComponent {
+ inputUsername: string = "";
+ inputPassword: string = "";
+ loginFailed: boolean = false;
+ loginSuccessful: boolean = false;
+
+ constructor(private developmentStore: DevelopmentStore, private authStore: AuthStore) {
+ }
+
+ tryToLogin() {
+ console.log("Trying to login with username: " + this.inputUsername + " and password: " + this.inputPassword);
+
+ axios({
+ method: 'post',
+ url: this.developmentStore.getBaseUrl() + 'api/v1/auth/login',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ data: {
+ username: this.inputUsername,
+ password: this.inputPassword
+ }
+ })
+ .then(async response => {
+ console.log(response);
+ console.log(response.data);
+ if(response.data.token) {
+ this.loginSuccessful = true;
+ this.authStore.setToken(response.data.token);
+ this.authStore.setUsername(this.inputUsername);
+
+ console.log("Login successful");
+ console.log("Token: " + await firstValueFrom(this.authStore.token$));
+ console.log("Username: " + await firstValueFrom(this.authStore.username$));
+ }
+ })
+ .catch(error => {
+ this.loginFailed = true;
+ });
+ }
+}
diff --git a/frontend/src/store/authStore.ts b/frontend/src/store/authStore.ts
new file mode 100644
index 0000000..577ad1a
--- /dev/null
+++ b/frontend/src/store/authStore.ts
@@ -0,0 +1,40 @@
+import { Injectable } from '@angular/core';
+import { BehaviorSubject } from 'rxjs';
+import { map } from 'rxjs/operators';
+
+interface AuthStoreState {
+ username: string;
+ token: string;
+}
+
+@Injectable({
+ providedIn: 'root'
+})
+export class AuthStore {
+ private state: BehaviorSubject = new BehaviorSubject({
+ username: "",
+ token: "",
+ });
+
+ // Getter for username
+ get username$() {
+ return this.state.asObservable().pipe(map(state => state.username));
+ }
+
+ // Getter for token
+ get token$() {
+ return this.state.asObservable().pipe(map(state => state.token));
+ }
+
+ // Mutation for username
+ setUsername(username: string) {
+ const currentState = this.state.getValue();
+ this.state.next({ ...currentState, username });
+ }
+
+ // Mutation for token
+ setToken(token: string) {
+ const currentState = this.state.getValue();
+ this.state.next({ ...currentState, token });
+ }
+}