From 3d9471ca2086f463efd4157ed94f4a8f6de3d1e7 Mon Sep 17 00:00:00 2001
From: Jonny Ngo Luong <jonnynl@stud.ntnu.no>
Date: Wed, 7 Apr 2021 19:57:24 +0200
Subject: [PATCH] feat: adding category implemented (#20)

co-author: @amalieur
---
 client/src/app/app-routing.module.ts          |  4 +-
 client/src/app/app.component.html             |  1 +
 client/src/app/app.module.ts                  |  6 +-
 .../admin-category.component.html             |  9 --
 .../admin-category.component.scss             |  0
 .../admin-category.component.ts               | 57 -------------
 .../app/categories/admin/admin.component.html | 16 ++++
 .../app/categories/admin/admin.component.scss | 50 +++++++++++
 .../admin.component.spec.ts}                  | 12 +--
 .../app/categories/admin/admin.component.ts   | 85 +++++++++++++++++++
 .../post-details/post-details.component.html  |  4 +-
 .../post-details/post-details.component.ts    |  2 +-
 .../controllers/categoryController/index.ts   | 10 +--
 .../src/controllers/postController/index.ts   |  5 +-
 server/src/models/post.ts                     |  2 +-
 15 files changed, 174 insertions(+), 89 deletions(-)
 delete mode 100644 client/src/app/categories/admin-category/admin-category.component.html
 delete mode 100644 client/src/app/categories/admin-category/admin-category.component.scss
 delete mode 100644 client/src/app/categories/admin-category/admin-category.component.ts
 create mode 100644 client/src/app/categories/admin/admin.component.html
 create mode 100644 client/src/app/categories/admin/admin.component.scss
 rename client/src/app/categories/{admin-category/admin-category.component.spec.ts => admin/admin.component.spec.ts} (52%)
 create mode 100644 client/src/app/categories/admin/admin.component.ts

diff --git a/client/src/app/app-routing.module.ts b/client/src/app/app-routing.module.ts
index 91980c6..5d71e76 100644
--- a/client/src/app/app-routing.module.ts
+++ b/client/src/app/app-routing.module.ts
@@ -7,7 +7,7 @@ import { UserRegistrationFormComponent } from './users/user-registration-form/us
 import { UserLoginFormComponent } from './users/user-login-form/user-login-form.component';
 import { UserProfileComponent } from './users/user-profile/user-profile.component';
 import { UserGuestProfileComponent } from './users/user-guest-profile/user-guest-profile.component';
-import { AdminCategoryComponent} from './categories/admin-category/admin-category.component';
+import { AdminComponent} from './categories/admin/admin.component';
 import { HomeComponent } from './home/home.component';
 import { UserProfileEditFormComponent } from './users/user-profile-edit-form/user-profile-edit-form.component';
 
@@ -26,7 +26,7 @@ const routes: Routes = [
   { path: 'register', component: UserRegistrationFormComponent },
   { path: 'login', component: UserLoginFormComponent },
   
-  { path: 'admin/category', component: AdminCategoryComponent }
+  { path: 'admin/category', component: AdminComponent }
 ];
 
 @NgModule({
diff --git a/client/src/app/app.component.html b/client/src/app/app.component.html
index 5178819..800e37e 100644
--- a/client/src/app/app.component.html
+++ b/client/src/app/app.component.html
@@ -2,6 +2,7 @@
 	<div class="navbar">
 		<span class="logo" (click)="navigate('/')">SellPoint</span>
 		<nav>
+			<span *ngIf="user.getIsAdmin" (click)="navigate('/admin/category')">Admin</span>
 			<span (click)="navigate('/annonse')">Annonser</span>
 			<span (click)="navigate('/annonse/ny')">Lag annonse</span>
 			<span *ngIf="!user.getUserId" (click)="navigate('/register')">Registrer</span>
diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts
index 5e1d0cf..6e36efd 100644
--- a/client/src/app/app.module.ts
+++ b/client/src/app/app.module.ts
@@ -9,8 +9,8 @@ import { PostModule } from './posts/post.module';
 import { UserModule } from './users/user.module';
 import { AuthModule } from './authentication/auth.module';
 import { SharedModule } from './shared/shared.module';
-import { AdminCategoryComponent } from './categories/admin-category/admin-category.component';
 import { HomeComponent } from './home/home.component';
+import { AdminComponent } from './categories/admin/admin.component';
 
 export function tokenGetter() {
   return localStorage.getItem("token");
@@ -19,8 +19,8 @@ export function tokenGetter() {
 @NgModule({
   declarations: [
     AppComponent,
-    AdminCategoryComponent,
-    HomeComponent
+    HomeComponent,
+    AdminComponent,
   ],
   imports: [
     BrowserModule,
diff --git a/client/src/app/categories/admin-category/admin-category.component.html b/client/src/app/categories/admin-category/admin-category.component.html
deleted file mode 100644
index c5106d5..0000000
--- a/client/src/app/categories/admin-category/admin-category.component.html
+++ /dev/null
@@ -1,9 +0,0 @@
-<div class="categoryForm">
-	<h3>Legg til kategori</h3>
-
-	<app-text-input [(inputModel)]="name" label="Kategorinavn" (blur)="checkForm()"></app-text-input>
-
-	<p>{{statusMessage}}</p>
-
-	<app-button (click)="addCategory" text="Legg til"></app-button>
-</div>
\ No newline at end of file
diff --git a/client/src/app/categories/admin-category/admin-category.component.scss b/client/src/app/categories/admin-category/admin-category.component.scss
deleted file mode 100644
index e69de29..0000000
diff --git a/client/src/app/categories/admin-category/admin-category.component.ts b/client/src/app/categories/admin-category/admin-category.component.ts
deleted file mode 100644
index 344b98e..0000000
--- a/client/src/app/categories/admin-category/admin-category.component.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import { Component, OnInit } from '@angular/core';
-import { Router } from '@angular/router';
-import { AuthService } from 'src/app/authentication/auth.service';
-import { PostService } from 'src/app/posts/post.service';
-
-@Component({
-  selector: 'app-admin-category',
-  templateUrl: './admin-category.component.html',
-  styleUrls: ['./admin-category.component.scss']
-})
-export class AdminCategoryComponent implements OnInit {
-  user: new User();
-  name: string = "";
-  statusMessage: string = "";
-
-  constructor(private postService: PostService, private authService: AuthService) { }
-
-  ngOnInit(): void {
-    this.user = this.authService.getCurrentUser();
-    if (this.user.get)
-  }
-
-  /**
-   * Validates the form
-   */
-  checkForm(): boolean {
-    if (this.name == "") {
-      this.setStatusMessage("Brukernavn kan ikke være tom");
-      return false;
-    }
-   
-    this.setStatusMessage("");
-    return true;
-  }
-
-  /**
-   * Publishes and registers the user if given arguments are valid
-   */
-  registerCategory() {
-    if (this.checkForm()) {
-      // Adds user to database and redirects to the homepage afterwards
-      this.postService.addCategory(name).then(status => {
-        console.log("Category was added: " + JSON.stringify(status));
-        loadCategories();
-      }).catch(error => {
-        console.log("Error adding category: " + error);
-      });
-    }
-  }
-
-  /**
-   * Sets the status message for user feedback on form submit
-   */
-  setStatusMessage(message: string) {
-    this.statusMessage = message;
-  }
-}
diff --git a/client/src/app/categories/admin/admin.component.html b/client/src/app/categories/admin/admin.component.html
new file mode 100644
index 0000000..5bd7ffe
--- /dev/null
+++ b/client/src/app/categories/admin/admin.component.html
@@ -0,0 +1,16 @@
+<div class="categoryForm">
+    <div class="cardWrapper">
+        <h3>Alle kategorier</h3>
+        <div>
+            <p *ngFor="let category of categories">{{category.getName}}</p>
+        </div>
+	</div>
+	<div class="cardWrapper">
+		<h3>Legg til kategori</h3>
+		<div>
+			<app-input [(inputModel)]="name" label="Kategorinavn" (blur)="checkForm()"></app-input>
+			<p class="status">{{statusMessage}}</p>
+			<app-button (click)="addCategory()" text="Legg til"></app-button>
+		</div>
+	</div>
+</div>
diff --git a/client/src/app/categories/admin/admin.component.scss b/client/src/app/categories/admin/admin.component.scss
new file mode 100644
index 0000000..5dc210b
--- /dev/null
+++ b/client/src/app/categories/admin/admin.component.scss
@@ -0,0 +1,50 @@
+:host > .categoryForm {
+    padding: 5%;
+    display:flex;
+    justify-content: center;
+    flex-direction: column;
+    align-items: center;
+    margin-bottom: 50px;
+    h3 {
+        font-family: 'Josefin Sans', sans-serif;
+        font-size: 1.5rem;
+        font-weight: 500;
+        padding: 10px;
+    }
+    & > div.cardWrapper {
+        color: #fff;
+        display: flex;
+        flex-direction: column;
+        background: linear-gradient(90deg, #14A35A 0%, #24e072 100%);
+        padding: 10px;
+        width: 40%;
+        min-width: 300px;
+        max-width: 400px;
+        margin: 10px;
+    }
+}
+div.cardWrapper > div {
+    color: #000;
+    display: flex;
+    flex-direction: column;
+    gap: 10px;
+    background-color: #fff;
+    box-shadow: inset 0px 4px 4px rgb(0 0 0 / 50%);
+    padding: 20px 10px;
+}
+p.status {
+    margin: 10px 0 5px 5px;
+    font-style: italic;
+}
+div.other {
+    font-family: 'Josefin Sans', sans-serif;
+    display: flex;
+    justify-content: space-between;
+    padding: 10px 0 5px 0;
+    & > a {
+        color: #000;
+        &:visited {
+            color: #000;
+        }
+    }
+}
\ No newline at end of file
diff --git a/client/src/app/categories/admin-category/admin-category.component.spec.ts b/client/src/app/categories/admin/admin.component.spec.ts
similarity index 52%
rename from client/src/app/categories/admin-category/admin-category.component.spec.ts
rename to client/src/app/categories/admin/admin.component.spec.ts
index 7797ede..eb28e42 100644
--- a/client/src/app/categories/admin-category/admin-category.component.spec.ts
+++ b/client/src/app/categories/admin/admin.component.spec.ts
@@ -1,20 +1,20 @@
 import { ComponentFixture, TestBed } from '@angular/core/testing';
 
-import { AdminCategoryComponent } from './admin-category.component';
+import { AdminComponent } from './admin.component';
 
-describe('AdminCategoryComponent', () => {
-  let component: AdminCategoryComponent;
-  let fixture: ComponentFixture<AdminCategoryComponent>;
+describe('AdminComponent', () => {
+  let component: AdminComponent;
+  let fixture: ComponentFixture<AdminComponent>;
 
   beforeEach(async () => {
     await TestBed.configureTestingModule({
-      declarations: [ AdminCategoryComponent ]
+      declarations: [ AdminComponent ]
     })
     .compileComponents();
   });
 
   beforeEach(() => {
-    fixture = TestBed.createComponent(AdminCategoryComponent);
+    fixture = TestBed.createComponent(AdminComponent);
     component = fixture.componentInstance;
     fixture.detectChanges();
   });
diff --git a/client/src/app/categories/admin/admin.component.ts b/client/src/app/categories/admin/admin.component.ts
new file mode 100644
index 0000000..dababdb
--- /dev/null
+++ b/client/src/app/categories/admin/admin.component.ts
@@ -0,0 +1,85 @@
+import { Component, OnInit } from '@angular/core';
+import { Router } from '@angular/router';
+import { AuthService } from 'src/app/authentication/auth.service';
+import { Category } from 'src/app/models/category.model';
+import { User } from 'src/app/models/user.model';
+import { PostService } from 'src/app/posts/post.service';
+
+@Component({
+  selector: 'app-admin',
+  templateUrl: './admin.component.html',
+  styleUrls: ['./admin.component.scss']
+})
+export class AdminComponent implements OnInit {
+  user: User = new User();
+  categories: Array<Category> = [];
+  name: string = "";
+  statusMessage: string = "";
+
+  constructor(private postService: PostService, private authService: AuthService, private router: Router) { }
+
+  ngOnInit(): void {
+    // Restrict page load to logged in admin users only
+    this.user = this.authService.getCurrentUser();
+    if (!this.user.getIsAdmin) {
+      this.router.navigateByUrl("/");
+    }
+    this.loadCategories();
+  }
+
+  /**
+   * Validates the form
+   */
+  checkForm(): boolean {
+    if (this.name == "") {
+      this.setStatusMessage("Kategorinavn kan ikke være tom");
+      return false;
+    }
+   
+    this.setStatusMessage("");
+    return true;
+  }
+
+  /**
+   * Publishes and add category if given arguments are valid
+   */
+  addCategory() {
+    if (this.checkForm()) {
+      const category: Category = new Category(
+        {
+          id: 0,
+          name: this.name,
+        }
+      );
+      // Adds user to database and redirects to the homepage afterwards
+      this.postService.addCategory(category).then(status => {
+        console.log("Category was with name: " + this.name+ " was added!");
+        this.loadCategories();
+        this.categories.push(category);
+        this.name = ""; // Reset input
+      }).catch(error => {
+        console.log("Error adding category: " + error);
+      });
+    }
+  }
+
+  /*
+   * Get the categories from database
+   */
+  loadCategories() {
+    // Gets all categories from database and displays them
+    this.postService.getAllCategories().then(categories => {
+      console.log(categories);
+      this.categories = categories;
+    }).catch(error => {
+      console.log(error);
+    });
+  }
+
+  /**
+   * Sets the status message for user feedback on form submit
+   */
+  setStatusMessage(message: string) {
+    this.statusMessage = message;
+  }
+}
diff --git a/client/src/app/posts/post-details/post-details.component.html b/client/src/app/posts/post-details/post-details.component.html
index 28d51fa..db8f81e 100644
--- a/client/src/app/posts/post-details/post-details.component.html
+++ b/client/src/app/posts/post-details/post-details.component.html
@@ -38,8 +38,8 @@
                 <a [href]="'mailto:'+owner.getEmail"><app-button class="ownerButton" text="Kontakt selger" (click)="contactPost()"></app-button></a>
             </div>
             <div *ngIf="userId == post.getOwner || user.getIsAdmin" class="buttonContainer">
-                <app-button class="ownerButton" text="Rediger annonse" (click)="editPost()"></app-button>
-                <app-button class="ownerButton" text="Slett annonse" (click)="deletePost()"></app-button>
+                <app-button *ngIf="userId == post.getOwner" class="ownerButton" text="Rediger annonse" (click)="editPost()"></app-button>
+                <app-button *ngIf="userId == post.getOwner || user.getIsAdmin" class="ownerButton" text="Slett annonse" (click)="deletePost()"></app-button>
                 <div *ngIf="post.getStatus != 1">
                     <app-button class="ownerButton" text="Marker solgt" (click)="markClosePost()"></app-button>
                 </div>
diff --git a/client/src/app/posts/post-details/post-details.component.ts b/client/src/app/posts/post-details/post-details.component.ts
index 337853e..3836004 100644
--- a/client/src/app/posts/post-details/post-details.component.ts
+++ b/client/src/app/posts/post-details/post-details.component.ts
@@ -70,7 +70,7 @@ export class PostDetailsComponent implements OnInit {
    */
   deletePost() {
     // Check if we are the owner of the post
-    if (this.userId == this.post.getOwner) {
+    if (this.userId == this.post.getOwner || this.user.getIsAdmin) {
       this.postService.deletePost(this.post.getId).then(data => {
         console.log("Successfully deleted post: " + this.post.getId);
         this.router.navigateByUrl("/annonse");
diff --git a/server/src/controllers/categoryController/index.ts b/server/src/controllers/categoryController/index.ts
index 909626d..c509ee1 100644
--- a/server/src/controllers/categoryController/index.ts
+++ b/server/src/controllers/categoryController/index.ts
@@ -19,12 +19,12 @@ const category = new Category();
 
 /* ============================= CREATE ============================= */
 // Create category `/api/category/`
-router.route('/').post(adminPermission, async (request: Request, response: Response) => {
-	const {categoryName} = request.body;
+router.route('/').post(authenticateToken, adminPermission, async (request: Request, response: Response) => {
+	const {name} = request.body;
 	try {
 		const input = (` INSERT INTO category(name) VALUES (?);`)
 		return response.status(200).json(
-            await query(input,[categoryName])
+            await query(input, [name])
         );
 	} catch (error) {
 		return response.status(400).send("Bad Request");
@@ -52,7 +52,7 @@ router.route('/:categoryid').get(async (request: Request, response: Response) =>
 });
 
 /* ============================= UPDATE ============================= */
-router.route('/').put(authenticateToken, async (request: Request, response: Response) => {
+router.route('/').put(authenticateToken, adminPermission, async (request: Request, response: Response) => {
     const categoryid = request.params.categoryid;
 	const {categoryName} = request.body;
 	try {
@@ -64,7 +64,7 @@ router.route('/').put(authenticateToken, async (request: Request, response: Resp
 
 /* ============================= DELETE ============================= */
 // remove category with id `/api/category/#categoryid`
-router.route('/').delete(authenticateToken, async (request: Request, response: Response) => {
+router.route('/').delete(authenticateToken, adminPermission, async (request: Request, response: Response) => {
     const categoryid = request.params.categoryid;
 	try {
 		response.status(200).json(await query("DELETE FROM category WHERE categoryid = ?",[categoryid]));
diff --git a/server/src/controllers/postController/index.ts b/server/src/controllers/postController/index.ts
index 72539a3..0e17147 100644
--- a/server/src/controllers/postController/index.ts
+++ b/server/src/controllers/postController/index.ts
@@ -31,13 +31,12 @@ router.route("/").post(async (request: Request, response: Response) => {
       timestamp: timestamp,
       owner: owner,
       categoryid: categoryid,
-      imageUrl: imageUrl,
-      status: status,
+      imageUrl: imageUrl
     };
 
     if (Object.values(post).filter((p) => p == undefined).length > 0)
       return response.status(500).send("Error");
-    const input = `INSERT INTO post(title, description, price, timestamp, owner, categoryid, imageUrl, status) VALUES (?,?,?,?,?,?,?,?)`;
+    const input = `INSERT INTO post(title, description, price, timestamp, owner, categoryid, imageUrl) VALUES (?,?,?,?,?,?,?)`;
     return response.status(200).json(await query(input, Object.values(post)));
   } catch (error) {
     return response.status(400).send("Bad Request");
diff --git a/server/src/models/post.ts b/server/src/models/post.ts
index 108cb3c..563fd39 100644
--- a/server/src/models/post.ts
+++ b/server/src/models/post.ts
@@ -7,7 +7,7 @@ interface IPost {
 	owner: number;
 	categoryid: number;
 	imageUrl: string;
-	status: number;
+	status?: number;
 }
 
 // Eksporterer IPost til bruk i andre filer.
-- 
GitLab