From 1ec81020339e29fcef6cd71ed877f82eddb7ad43 Mon Sep 17 00:00:00 2001
From: "alec.schmidt" <alec.schmidt@etu.hesge.ch>
Date: Wed, 7 Jun 2023 17:59:17 +0200
Subject: [PATCH] admin users dashboard fully functional

---
 API/db/app.db                                 | Bin 36864 -> 36864 bytes
 API/src/database/Database.ts                  |   3 +-
 frontend/src/app/admin/admin.component.html   |  16 ++++++-
 frontend/src/app/admin/admin.component.ts     |  35 +++++++++++----
 frontend/src/app/app.module.ts                |   6 ++-
 .../app/create-user/create-user.component.css |   0
 .../create-user/create-user.component.html    |  10 +++++
 .../create-user/create-user.component.spec.ts |  21 +++++++++
 .../app/create-user/create-user.component.ts  |  41 ++++++++++++++++++
 frontend/src/app/services/users.service.ts    |  26 ++++++++++-
 .../app/update-user/update-user.component.css |   0
 .../update-user/update-user.component.html    |   8 ++++
 .../update-user/update-user.component.spec.ts |  21 +++++++++
 .../app/update-user/update-user.component.ts  |  41 ++++++++++++++++++
 14 files changed, 214 insertions(+), 14 deletions(-)
 create mode 100644 frontend/src/app/create-user/create-user.component.css
 create mode 100644 frontend/src/app/create-user/create-user.component.html
 create mode 100644 frontend/src/app/create-user/create-user.component.spec.ts
 create mode 100644 frontend/src/app/create-user/create-user.component.ts
 create mode 100644 frontend/src/app/update-user/update-user.component.css
 create mode 100644 frontend/src/app/update-user/update-user.component.html
 create mode 100644 frontend/src/app/update-user/update-user.component.spec.ts
 create mode 100644 frontend/src/app/update-user/update-user.component.ts

diff --git a/API/db/app.db b/API/db/app.db
index b9f76f706498f88f8a0278596752a3792021fdff..56182c95bd846eb45693d59fe952a2c56c3ec843 100644
GIT binary patch
delta 155
zcmZozz|^pSX@WE(&qNt#MxKoc3;B5&7#NuNuQ2ex;lIMaZ?mAnW`18WaZ$;V)Z!9j
z5K)kmSeaTR#>&bdEh<@-nU|cJSAq~1Vq|3y6%|j+Nlgahl-$fbF0her82Eqizu|wg
lS<v7*zc?32i!mEFvos^r3|4k#QO?bO^qB=1*%mnj000DnEsp>I

delta 193
zcmZozz|^pSX@WGP$V3@uMv;vP3;Fr^-!L%oZ)4!!#(#x>KmYR0f&#Pn(<G!tC6n^=
zvhqudN@N&W8RX@~OY>4v(=zi?Q{arml-$fbF=kc<X;I0t%)I2(ypqJE<dlM(#LCnn
z1_lNZQBm>4oYZ762C3!Z|G~h-f1iQ>KK~mK+$^YYieHHbWDyUuJSW^>Zf0plsDaE3
S3=ABb|L8LdFmf$&2mk<&ygL^F

diff --git a/API/src/database/Database.ts b/API/src/database/Database.ts
index 1740240..5a94f6f 100644
--- a/API/src/database/Database.ts
+++ b/API/src/database/Database.ts
@@ -93,8 +93,7 @@ class DBHandler {
         const a = req.body as User_t;
 
         const request = "UPDATE users \
-                        SET username = '"+ a.username +"', password = '"+ a.password +"' \
-                        WHERE id = " + req.params.id;
+                        SET username = '"+ a.username + "', type = '" + a.type + "' WHERE id = " + req.params.id;
 
         asyncdb.all(request)
         .then(() => res.status(StatusCodes.OK).end())
diff --git a/frontend/src/app/admin/admin.component.html b/frontend/src/app/admin/admin.component.html
index e1119cd..10f9538 100644
--- a/frontend/src/app/admin/admin.component.html
+++ b/frontend/src/app/admin/admin.component.html
@@ -1,3 +1,5 @@
+<button (click)="modalCreate=true;">Create User</button>
+
 <table>
     <thead>
         <th>Username</th>
@@ -7,7 +9,7 @@
         <tr *ngFor="let user of users">
             <td>{{user.username}}</td>
             <td>{{user.type}}</td>
-            <td><button>UPDATE</button></td>
+            <td><button (click)="showUpdateModal(user)">UPDATE</button></td>
             <td><button (click)="deleteUser(user)">DELETE</button></td>
         </tr>
     </tbody>
@@ -26,4 +28,14 @@
             <td><button (click)="deleteQuestion(question)">DELETE</button></td>
         </tr>
     </tbody>
-</table>
\ No newline at end of file
+</table>
+
+
+
+<div *ngIf="modalUpdate">
+    <app-update-user [user]="userToEdit" (closeModal)="modalUpdate=false;"></app-update-user>
+</div>
+
+<div *ngIf="modalCreate">
+    <app-create-user (closeModal)="modalCreate=false;"></app-create-user>
+</div>
\ No newline at end of file
diff --git a/frontend/src/app/admin/admin.component.ts b/frontend/src/app/admin/admin.component.ts
index d1c2fc1..a46e7de 100644
--- a/frontend/src/app/admin/admin.component.ts
+++ b/frontend/src/app/admin/admin.component.ts
@@ -3,6 +3,7 @@ import { HttpClient } from '@angular/common/http';
 import { Answer, QandA, Question, User } from '../Types/types';
 import { UsersService } from '../services/users.service';
 import { QuestionsService } from '../services/questions.service';
+import { Subscription } from 'rxjs';
 
 @Component({
   selector: 'app-admin',
@@ -11,9 +12,14 @@ import { QuestionsService } from '../services/questions.service';
 })
 export class AdminComponent implements OnInit {
     public data;
-    public users: User[] = [];
-    public questions: Question[] = [];
-    public answers: Answer[] = [];
+    public users!: User[];
+    public questions!: Question[];
+    public answers!: Answer[];
+    private usersSub!: Subscription;
+    userToEdit!: User;
+
+    modalUpdate: boolean = false;
+    modalCreate: boolean = false;
 
     constructor(
       private http: HttpClient,
@@ -21,12 +27,15 @@ export class AdminComponent implements OnInit {
       private questionController: QuestionsService) { }
 
     ngOnInit(): void {
-      
-      this.http.get("http://0.0.0.0:30992/API/v1/user")
-      .subscribe(users => {
-        this.users = users as User[];
+
+      this.usersSub = this.userController.users.subscribe(userList => {
+        this.users = userList;
       });
 
+      this.userController.fetchUsers();
+
+      
+
       this.http.get("http://0.0.0.0:30992/API/v1/question")
       .subscribe(res => {
         let questions = res as QandA;
@@ -42,4 +51,14 @@ export class AdminComponent implements OnInit {
     deleteQuestion(question: Question) {
       this.questionController.deleteQuestion(question);
     }
-}
+
+    showUpdateModal(user: User){
+      this.userToEdit = user;
+      this.modalUpdate = true;
+    }
+
+    showCreateModal(){
+      this.modalCreate = true;
+    }
+
+  }
diff --git a/frontend/src/app/app.module.ts b/frontend/src/app/app.module.ts
index 0e5776e..e32444d 100644
--- a/frontend/src/app/app.module.ts
+++ b/frontend/src/app/app.module.ts
@@ -9,13 +9,17 @@ import { LoginComponent } from './login/login.component';
 import { ReactiveFormsModule } from '@angular/forms';
 import { TokenInterceptor } from './interceptors/token-interceptor';
 import { SignupComponent } from './signup/signup.component';
+import { CreateUserComponent } from './create-user/create-user.component';
+import { UpdateUserComponent } from './update-user/update-user.component';
 
 @NgModule({
   declarations: [
     AppComponent,
     AdminComponent,
     LoginComponent,
-    SignupComponent
+    SignupComponent,
+    CreateUserComponent,
+    UpdateUserComponent
   ],
   imports: [
     BrowserModule,
diff --git a/frontend/src/app/create-user/create-user.component.css b/frontend/src/app/create-user/create-user.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/src/app/create-user/create-user.component.html b/frontend/src/app/create-user/create-user.component.html
new file mode 100644
index 0000000..04fbabb
--- /dev/null
+++ b/frontend/src/app/create-user/create-user.component.html
@@ -0,0 +1,10 @@
+<h1>Create User</h1>
+<form [formGroup]="createUser" (ngSubmit)="onSubmit()">
+    <input type="text" placeholder="Username" formControlName="username">
+    <br>
+    <input type="password" placeholder="Password" formControlName="password">
+    <br>
+    <input type="type" placeholder="player" formControlName="type">
+    <br>
+    <button type="submit">Create</button>
+</form>
\ No newline at end of file
diff --git a/frontend/src/app/create-user/create-user.component.spec.ts b/frontend/src/app/create-user/create-user.component.spec.ts
new file mode 100644
index 0000000..0078050
--- /dev/null
+++ b/frontend/src/app/create-user/create-user.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { CreateUserComponent } from './create-user.component';
+
+describe('CreateUserComponent', () => {
+  let component: CreateUserComponent;
+  let fixture: ComponentFixture<CreateUserComponent>;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      declarations: [CreateUserComponent]
+    });
+    fixture = TestBed.createComponent(CreateUserComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/frontend/src/app/create-user/create-user.component.ts b/frontend/src/app/create-user/create-user.component.ts
new file mode 100644
index 0000000..2c197a5
--- /dev/null
+++ b/frontend/src/app/create-user/create-user.component.ts
@@ -0,0 +1,41 @@
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+import { FormControl, FormGroup, Validators } from '@angular/forms';
+import { User } from '../Types/types';
+import { UsersService } from '../services/users.service';
+
+@Component({
+  selector: 'app-create-user',
+  templateUrl: './create-user.component.html',
+  styleUrls: ['./create-user.component.css']
+})
+export class CreateUserComponent {
+  createUser: FormGroup
+
+  @Output() closeModal: EventEmitter<string> = new EventEmitter<string>();
+
+  constructor(private userController: UsersService) { }
+
+  ngOnInit(): void {
+    this.createUser = new FormGroup({
+      username: new FormControl('', Validators.required),
+      password: new FormControl('', Validators.required),
+      type: new FormControl('player', Validators.required)
+    });
+  }
+
+  onSubmit() {
+    const username = this.createUser.get("username")!.value;
+    const password = this.createUser.get("password")!.value;
+    const type = this.createUser.get("type")!.value;
+
+    const user: User = {
+      id: undefined,
+      username : username,
+      password: password,
+      type: type
+    }
+
+    this.userController.addUserAdmin(user);
+    this.closeModal.emit();
+  }
+}
diff --git a/frontend/src/app/services/users.service.ts b/frontend/src/app/services/users.service.ts
index ec04eb7..16331c6 100644
--- a/frontend/src/app/services/users.service.ts
+++ b/frontend/src/app/services/users.service.ts
@@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
 import { User } from '../Types/types';
 import { HttpClient } from '@angular/common/http';
 import { AuthenticationService } from './authentication.service';
+import { BehaviorSubject } from 'rxjs';
 
 const ROUTE = "http://0.0.0.0:30992/API/v1/user"
 
@@ -10,13 +11,15 @@ const ROUTE = "http://0.0.0.0:30992/API/v1/user"
 })
 export class UsersService {
 
+  private _users = new BehaviorSubject<User[]>([])
+
   constructor(
     private http: HttpClient,
     private auth: AuthenticationService) { }
 
   deleteUser(user: User) {
     this.http.delete(ROUTE + "/" + user.id.toString()).subscribe(res => {
-      console.log("PLZ REFRESH")
+      this.fetchUsers();
     });
   }
 
@@ -26,4 +29,25 @@ export class UsersService {
     });
   }
 
+  get users() {
+    return this._users.asObservable();
+  }
+
+  fetchUsers() {
+    this.http.get("http://0.0.0.0:30992/API/v1/user")
+      .subscribe(users => {
+        this._users.next(users as User[]);
+      });
+  }
+
+  addUserAdmin(user: User) {
+    this.http.post<User>(ROUTE, user).subscribe(res => {
+      this.fetchUsers();
+    });
+  }
+
+  updateUser(user:User) {
+    this.http.patch<User>(ROUTE + "/" + user.id.toString(), user).subscribe(res => this.fetchUsers())
+  }
+
 }
diff --git a/frontend/src/app/update-user/update-user.component.css b/frontend/src/app/update-user/update-user.component.css
new file mode 100644
index 0000000..e69de29
diff --git a/frontend/src/app/update-user/update-user.component.html b/frontend/src/app/update-user/update-user.component.html
new file mode 100644
index 0000000..a30c17a
--- /dev/null
+++ b/frontend/src/app/update-user/update-user.component.html
@@ -0,0 +1,8 @@
+<h1>Update User</h1>
+<form [formGroup]="updateUser" (ngSubmit)="onSubmit()">
+    <input type="text" formControlName="username">
+    <br>
+    <input type="text" formControlName="type">
+    <br>
+    <button type="submit">Update</button>
+</form>
\ No newline at end of file
diff --git a/frontend/src/app/update-user/update-user.component.spec.ts b/frontend/src/app/update-user/update-user.component.spec.ts
new file mode 100644
index 0000000..70d9289
--- /dev/null
+++ b/frontend/src/app/update-user/update-user.component.spec.ts
@@ -0,0 +1,21 @@
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { UpdateUserComponent } from './update-user.component';
+
+describe('UpdateUserComponent', () => {
+  let component: UpdateUserComponent;
+  let fixture: ComponentFixture<UpdateUserComponent>;
+
+  beforeEach(() => {
+    TestBed.configureTestingModule({
+      declarations: [UpdateUserComponent]
+    });
+    fixture = TestBed.createComponent(UpdateUserComponent);
+    component = fixture.componentInstance;
+    fixture.detectChanges();
+  });
+
+  it('should create', () => {
+    expect(component).toBeTruthy();
+  });
+});
diff --git a/frontend/src/app/update-user/update-user.component.ts b/frontend/src/app/update-user/update-user.component.ts
new file mode 100644
index 0000000..f1fa46d
--- /dev/null
+++ b/frontend/src/app/update-user/update-user.component.ts
@@ -0,0 +1,41 @@
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { FormControl, FormGroup, Validators } from '@angular/forms';
+import { User } from '../Types/types';
+import { UsersService } from '../services/users.service';
+
+@Component({
+  selector: 'app-update-user',
+  templateUrl: './update-user.component.html',
+  styleUrls: ['./update-user.component.css']
+})
+export class UpdateUserComponent implements OnInit {
+
+  updateUser: FormGroup
+
+  @Input() user!: User;
+  @Output() closeModal: EventEmitter<void> = new EventEmitter<void>();
+
+  constructor(private userController: UsersService) { }
+
+  ngOnInit(): void {
+    this.updateUser = new FormGroup({
+      username: new FormControl(this.user.username, Validators.required),
+      type: new FormControl(this.user.type, Validators.required)
+    });
+  }
+
+  onSubmit() {
+    const username = this.updateUser.get("username")!.value;
+    const type = this.updateUser.get("type")!.value;
+
+    const userToEdit: User = {
+      id: this.user.id,
+      username : username,
+      password: undefined,
+      type: type
+    }
+
+    this.userController.updateUser(userToEdit);
+    this.closeModal.emit();
+  }
+}
-- 
GitLab