From 8edcf631973b6070a1e468cefd35495c52a048c9 Mon Sep 17 00:00:00 2001 From: AidenLYT Date: Fri, 27 Sep 2024 00:06:53 +0800 Subject: [PATCH 01/11] Add edit question page --- .../src/edit-page/edit-page.component.css | 214 ++++++++++++++++++ .../src/edit-page/edit-page.component.html | 49 ++++ .../src/edit-page/edit-page.component.spec.ts | 23 ++ .../src/edit-page/edit-page.component.ts | 85 +++++++ 4 files changed, 371 insertions(+) create mode 100644 peer-prep-fe/src/edit-page/edit-page.component.css create mode 100644 peer-prep-fe/src/edit-page/edit-page.component.html create mode 100644 peer-prep-fe/src/edit-page/edit-page.component.spec.ts create mode 100644 peer-prep-fe/src/edit-page/edit-page.component.ts diff --git a/peer-prep-fe/src/edit-page/edit-page.component.css b/peer-prep-fe/src/edit-page/edit-page.component.css new file mode 100644 index 0000000000..707d2b18ed --- /dev/null +++ b/peer-prep-fe/src/edit-page/edit-page.component.css @@ -0,0 +1,214 @@ +.edit-question-container { + background-color: darkgrey; + color: white; + width: 800px; + padding: 20px; + border-radius: 10px; + box-sizing: border-box; + margin-left: auto; + margin-right: auto; + font-family: "Signika", sans-serif; +} + +.question-title { + margin-top: -20px; +} + +.header { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 470px; +} + +.back-button { + background-color: transparent; + border: none; + color: #333; + font-size: 50px; + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 5px; + transition: transform 0.2s, color 0.2s; +} + +.back-button:hover { + color: mediumvioletred; + transform: scale(2.1); +} + +.description-box { + width: 100%; + max-width: 100%; + height: 80px; + margin-bottom: 10px; +} + +.editable-box { + width: 100%; + height: 100%; + padding: 10px; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 5px; + resize: none; + overflow-y: auto; + background-color: #333; + color: white; + font-size: 15px; + margin-top: -15px; +} + +.editable-box::-webkit-scrollbar { + width: 6px; +} + +.editable-box::-webkit-scrollbar-thumb { + background-color: #888; + border-radius: 10px; +} + +.question-category { + margin-top: -15px; +} + +.selection { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 4px; +} + +.dropdown { + position: relative; + display: inline-block; + width: 100%; +} + +.dropdown-toggle { + width: 80%; + padding: 10px; + background-color: #444; + color: white; + border: 1px solid #ccc; + border-radius: 5px; + cursor: pointer; + font-size: 15px; + margin-top: -15px; +} + +.dropdown-menu { + display: none; + position: absolute; + width: 80%; + border: 1px solid #ccc; + max-height: 200px; + overflow-y: auto; + box-shadow: 0px 8px 16px rgba(0,0,0,0.1); + z-index: 1; + border-radius: 3px; + background-color: #333333; + font-family: "Signika", sans-serif; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-item { + padding: 8px; + display: flex; + align-items: center; +} + +.dropdown-label { + display: flex; + align-items: center; + width: 100%; + cursor: pointer; +} + +.dropdown-label input[type="checkbox"] { + margin-left: auto; + cursor: pointer; +} + +.dropdown-item:hover { + background-color: grey; +} + +.dropdown-label input[type="checkbox"]:checked { + accent-color: #dddddd; +} + +input[type="checkbox"] { + margin-right: 10px; +} + +.difficulty-buttons { + display: flex; + justify-content: center; + margin-top: -10px; +} + +.diff-butt { + flex: 1; + padding: 10px 0; + background-color: #444; + border: 1px solid #ccc; + color: white; + cursor: pointer; + border-radius: 0; + font-size: 16px; + transition: background-color 0.3s; + width: 80px; +} + +.diff-butt:not(:last-child) { + border-right: none; +} + +.diff-butt:first-child { + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; +} + +.diff-butt:last-child { + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; +} + +.diff-butt.selected { + background-color: steelblue; +} + +.diff-butt:hover { + background-color: lightsteelblue; + color: black; + transform: scale(1.1); +} + +.save-button { + font-size: 16px; + position: relative; + left: 680px; + width: 80px; + height: 30px; + border-radius: 10px; + margin-top: 20px; + font-family: "Signika", sans-serif; + background-color: white; + color: black; +} + +.save-button:hover { + background-color: darkgreen; + color: white; + transform: scale(1.1); +} + + diff --git a/peer-prep-fe/src/edit-page/edit-page.component.html b/peer-prep-fe/src/edit-page/edit-page.component.html new file mode 100644 index 0000000000..fd49f20ccf --- /dev/null +++ b/peer-prep-fe/src/edit-page/edit-page.component.html @@ -0,0 +1,49 @@ +
+
+

EDIT QUESTION

+ +
+ +
+

QUESTION TITLE

+
+ +
+
+ +
+

QUESTION DESCRIPTION

+
+ +
+
+ +
+

CATEGORY

+
+ + +
+ + + +
+
+
+ +
+ +
+
diff --git a/peer-prep-fe/src/edit-page/edit-page.component.spec.ts b/peer-prep-fe/src/edit-page/edit-page.component.spec.ts new file mode 100644 index 0000000000..03644b64a4 --- /dev/null +++ b/peer-prep-fe/src/edit-page/edit-page.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EditPageComponent } from './edit-page.component'; + +describe('EditPageComponent', () => { + let component: EditPageComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [EditPageComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(EditPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/peer-prep-fe/src/edit-page/edit-page.component.ts b/peer-prep-fe/src/edit-page/edit-page.component.ts new file mode 100644 index 0000000000..c751906bb0 --- /dev/null +++ b/peer-prep-fe/src/edit-page/edit-page.component.ts @@ -0,0 +1,85 @@ +import { Component, OnInit } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {ActivatedRoute, Router} from "@angular/router"; +import {FormsModule} from "@angular/forms"; +import {NgClass, NgForOf} from "@angular/common"; + +@Component({ + selector: 'app-edit-page', + templateUrl: './edit-page.component.html', + standalone: true, + imports: [ + FormsModule, + NgClass, + NgForOf + ], + styleUrl: './edit-page.component.css' +}) +export class EditPageComponent implements OnInit { + questionTitle: string= ''; + questionId: string = ''; + questionDescription: string = ''; + categories = [ + {name: 'Algorithms', selected: false}, + {name: 'Database', selected: false}, + {name: 'Shell', selected: false}, + {name: 'Concurrency', selected: false}, + {name: 'JavaScript', selected: false}, + {name: 'pandas', selected: false}, + ]; + difficulty: string = ''; + dropdownOpen: boolean = false; + + constructor( + private http: HttpClient, + private router: Router, + private route: ActivatedRoute + ) {} + + ngOnInit() { + this.route.params.subscribe((params) => { + this.questionId = params['id']; + this.loadQuestionData(); + }); + } + + loadQuestionData() { + this.http.get(`/api/questions/$(this.questionId)`).subscribe((data: any) => { + this.questionTitle = data.title; + this.questionDescription = data.description; + this.categories.forEach(cat => { + cat.selected = data.categories.includes(cat.name); + }); + this.difficulty = data.difficulty; + }); + } + + setDifficulty(level: string) { + this.difficulty = level; + } + + saveQuestion() { + const updatedQuestion = { + title: this.questionTitle, + description: this.questionDescription, + categories: this.categories.filter(cat => cat.selected).map(cat => cat.name), + difficulty: this.difficulty + }; + this.http.put(`/api/questions/$(this.questionId)`, updatedQuestion).subscribe((response) => { + alert('Question updated successfully!'); + }, + (error) => { + alert('Error updating question'); + } + ); + } + + toggleDropdown() { + this.dropdownOpen = !this.dropdownOpen; + } + + navigateToList() { + this.router.navigate(['/list-of-questions']); + } +} + From 2d19f515f1bd90952574aca19616f3144e1d78ef Mon Sep 17 00:00:00 2001 From: AidenLYT Date: Fri, 27 Sep 2024 16:52:46 +0800 Subject: [PATCH 02/11] Add add question page --- .../src/add-page/add-page.component.css | 227 ++++++++++++++++++ .../src/add-page/add-page.component.html | 58 +++++ .../src/add-page/add-page.component.spec.ts | 23 ++ .../src/add-page/add-page.component.ts | 94 ++++++++ peer-prep-fe/src/app/app.routes.ts | 7 +- 5 files changed, 408 insertions(+), 1 deletion(-) create mode 100644 peer-prep-fe/src/add-page/add-page.component.css create mode 100644 peer-prep-fe/src/add-page/add-page.component.html create mode 100644 peer-prep-fe/src/add-page/add-page.component.spec.ts create mode 100644 peer-prep-fe/src/add-page/add-page.component.ts diff --git a/peer-prep-fe/src/add-page/add-page.component.css b/peer-prep-fe/src/add-page/add-page.component.css new file mode 100644 index 0000000000..98c7996ba6 --- /dev/null +++ b/peer-prep-fe/src/add-page/add-page.component.css @@ -0,0 +1,227 @@ +.add-question-container { + background-color: darkgrey; + color: white; + width: 800px; + padding: 20px; + border-radius: 10px; + box-sizing: border-box; + margin-left: auto; + margin-right: auto; + font-family: "Signika", sans-serif; +} + +.question-title { + margin-top: -20px; +} + +.header { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 470px; +} + +.back-button { + background-color: transparent; + border: none; + color: #333; + font-size: 50px; + cursor: pointer; + display: inline-flex; + align-items: center; + justify-content: center; + padding: 5px; + transition: transform 0.2s, color 0.2s; +} + +.back-button:hover { + color: mediumvioletred; + transform: scale(2.1); +} + +.description-box { + width: 100%; + max-width: 100%; + height: 80px; + margin-bottom: 10px; +} + +.editable-box { + width: 100%; + height: 100%; + padding: 10px; + box-sizing: border-box; + border: 1px solid #ccc; + border-radius: 5px; + resize: none; + overflow-y: auto; + background-color: #333; + color: white; + font-size: 15px; + margin-top: -15px; +} + +.editable-box::-webkit-scrollbar { + width: 6px; +} + +.editable-box::-webkit-scrollbar-thumb { + background-color: #888; + border-radius: 10px; +} + +.selection { + display: flex; + flex-direction: row; + justify-content: center; + align-items: center; + gap: 4px; +} + +.dropdown { + position: relative; + display: inline-block; + width: 100%; +} + +.dropdown-toggle { + width: 80%; + padding: 10px; + background-color: #444; + color: white; + border: 1px solid #ccc; + border-radius: 5px; + cursor: pointer; + font-size: 15px; + margin-top: -15px; +} + +.dropdown-menu { + display: none; + position: absolute; + width: 80%; + border: 1px solid #ccc; + max-height: 200px; + overflow-y: auto; + box-shadow: 0px 8px 16px rgba(0,0,0,0.1); + z-index: 1; + border-radius: 3px; + background-color: #333333; + font-family: "Signika", sans-serif; +} + +.dropdown-menu.show { + display: block; +} + +.dropdown-item { + padding: 8px; + display: flex; + align-items: center; +} + +.dropdown-label { + display: flex; + align-items: center; + width: 100%; + cursor: pointer; +} + +.dropdown-label input[type="checkbox"] { + margin-left: auto; + cursor: pointer; +} + +.dropdown-item:hover { + background-color: grey; +} + +.dropdown-label input[type="checkbox"]:checked { + accent-color: #dddddd; +} + +input[type="checkbox"] { + margin-right: 10px; +} + +.difficulty-buttons { + display: flex; + justify-content: center; + margin-top: -10px; +} + +.diff-butt { + flex: 1; + padding: 10px 0; + background-color: #444; + border: 1px solid #ccc; + color: white; + cursor: pointer; + border-radius: 0; + font-size: 16px; + transition: background-color 0.3s; + width: 80px; +} + +.diff-butt:not(:last-child) { + border-right: none; +} + +.diff-butt:first-child { + border-top-left-radius: 5px; + border-bottom-left-radius: 5px; +} + +.diff-butt:last-child { + border-top-right-radius: 5px; + border-bottom-right-radius: 5px; +} + +.diff-butt.selected { + background-color: steelblue; +} + +.diff-butt:hover { + background-color: lightsteelblue; + color: black; + transform: scale(1.1); +} + +.save-button { + font-size: 16px; + position: relative; + left: 680px; + width: 80px; + height: 30px; + border-radius: 10px; + margin-top: 20px; + font-family: "Signika", sans-serif; + background-color: white; + color: black; +} + +.save-button:hover { + background-color: darkgreen; + color: white; + transform: scale(1.1); +} + +.error-message-title { + color: red; + font-size: 15px; +} + +.error-message-description { + color: red; + font-size: 15px; + margin-top: -15px; +} + +.error-message-difficulty { + margin-top: 5px; + margin-left: 570px; + color: red; +} + + diff --git a/peer-prep-fe/src/add-page/add-page.component.html b/peer-prep-fe/src/add-page/add-page.component.html new file mode 100644 index 0000000000..2dcf34eb28 --- /dev/null +++ b/peer-prep-fe/src/add-page/add-page.component.html @@ -0,0 +1,58 @@ +
+
+

ADD QUESTION

+ +
+ +
+
+

QUESTION TITLE

+
+ +
+
+ Title is required. +
+
+ +
+

QUESTION DESCRIPTION

+
+ +
+
+ Description is required. +
+
+
+ +
+

CATEGORY

+
+ + +
+ + + +
+
+
+ +
+ +
+ +
diff --git a/peer-prep-fe/src/add-page/add-page.component.spec.ts b/peer-prep-fe/src/add-page/add-page.component.spec.ts new file mode 100644 index 0000000000..ed7cf9e30f --- /dev/null +++ b/peer-prep-fe/src/add-page/add-page.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AddPageComponent } from './add-page.component'; + +describe('AddPageComponent', () => { + let component: AddPageComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AddPageComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AddPageComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/peer-prep-fe/src/add-page/add-page.component.ts b/peer-prep-fe/src/add-page/add-page.component.ts new file mode 100644 index 0000000000..869af188cc --- /dev/null +++ b/peer-prep-fe/src/add-page/add-page.component.ts @@ -0,0 +1,94 @@ +import { Component } from '@angular/core'; +import {NgClass, NgForOf, NgIf} from "@angular/common"; +import {FormBuilder, FormsModule, Validators, FormGroup, ReactiveFormsModule, FormControl} from "@angular/forms"; +import {HttpClient} from "@angular/common/http"; +import {ActivatedRoute, Router, Routes} from "@angular/router"; + +@Component({ + selector: 'app-add-page', + standalone: true, + imports: [ + NgForOf, + FormsModule, + NgClass, + NgIf, + ReactiveFormsModule + ], + templateUrl: './add-page.component.html', + styleUrl: './add-page.component.css' +}) +export class AddPageComponent { + + questionTitle: string= ''; + questionDescription: string = ''; + categories = [ + {name: 'Algorithms', selected: false}, + {name: 'Database', selected: false}, + {name: 'Shell', selected: false}, + {name: 'Concurrency', selected: false}, + {name: 'JavaScript', selected: false}, + {name: 'pandas', selected: false}, + ]; + difficulty: string = 'easy'; + dropdownOpen: boolean = false; + + // constructor( + // private http: HttpClient, + // private router: Router, + // private route: ActivatedRoute + // ) {} + questionForm : FormGroup; + constructor(private fb: FormBuilder, private router : Router) { + this.questionForm = this.fb.group({ + title: ['', Validators.required], + description:['', Validators.required], + }); + } + + // questionForm: FormGroup; + // constructor(private router: Router, private fb: FormBuilder) { + // this.questionForm = this.fb.group({ + // title: ['', Validators.required], + // description:['', Validators.required], + // categories: this.fb.array([]), + // difficulty: ['', Validators.required] + // }) + // } + + + setDifficulty(level: string) { + this.difficulty = level; + } + + // saveQuestion() { + // const updatedQuestion = { + // title: this.questionTitle, + // description: this.questionDescription, + // categories: this.categories.filter(cat => cat.selected).map(cat => cat.name), + // difficulty: this.difficulty + // }; + // this.http.put(`/api/questions/$(this.questionId)`, updatedQuestion).subscribe((response) => { + // alert('Question updated successfully!'); + // }, + // (error) => { + // alert('Error updating question'); + // } + // ); + // } + + saveQuestion() { + if (this.questionForm.valid) { + alert("Success"); + } else { + this.questionForm.markAllAsTouched(); + } + } + + toggleDropdown() { + this.dropdownOpen = !this.dropdownOpen; + } + + navigateToList() { + this.router.navigate(['/list-of-questions']); + } +} diff --git a/peer-prep-fe/src/app/app.routes.ts b/peer-prep-fe/src/app/app.routes.ts index dc39edb5f2..5d03ec5fb9 100644 --- a/peer-prep-fe/src/app/app.routes.ts +++ b/peer-prep-fe/src/app/app.routes.ts @@ -1,3 +1,8 @@ import { Routes } from '@angular/router'; +import { AddPageComponent } from "../add-page/add-page.component"; +import {EditPageComponent} from "../edit-page/edit-page.component"; -export const routes: Routes = []; +export const routes: Routes = [ + {path: 'add-question', component: AddPageComponent}, + {path: 'edit-question', component: EditPageComponent} +]; From 4e50c6294f2b42ab644272477179476b7d05d5c5 Mon Sep 17 00:00:00 2001 From: AidenLYT Date: Fri, 27 Sep 2024 17:32:52 +0800 Subject: [PATCH 03/11] Change server.go connection to localhost:4200 Add service.ts Edit edit question page --- peer-prep-be/src/server.go | 4 ++-- .../src/edit-page/edit-page.component.ts | 10 +++++----- .../src/services/question.service.spec.ts | 16 ++++++++++++++++ peer-prep-fe/src/services/question.service.ts | 19 +++++++++++++++++++ 4 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 peer-prep-fe/src/services/question.service.spec.ts create mode 100644 peer-prep-fe/src/services/question.service.ts diff --git a/peer-prep-be/src/server.go b/peer-prep-be/src/server.go index fa63022cec..47c71caf49 100644 --- a/peer-prep-be/src/server.go +++ b/peer-prep-be/src/server.go @@ -19,7 +19,7 @@ func main() { e.Use(middleware.Recover()) // Recover // CORS e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ - AllowOrigins: []string{"*"}, + AllowOrigins: []string{"http://localhost:4200"}, AllowMethods: []string{echo.GET, echo.HEAD, echo.PUT, echo.PATCH, echo.POST, echo.DELETE}, })) @@ -28,5 +28,5 @@ func main() { e.GET("/", func(c echo.Context) error { return c.String(http.StatusOK, "Hello, World!") }) - e.Logger.Fatal(e.Start(":1323")) + e.Logger.Fatal(e.Start(":8080")) } diff --git a/peer-prep-fe/src/edit-page/edit-page.component.ts b/peer-prep-fe/src/edit-page/edit-page.component.ts index c751906bb0..bbdf3e6ee2 100644 --- a/peer-prep-fe/src/edit-page/edit-page.component.ts +++ b/peer-prep-fe/src/edit-page/edit-page.component.ts @@ -1,8 +1,8 @@ import { Component, OnInit } from '@angular/core'; -import {HttpClient} from "@angular/common/http"; import {ActivatedRoute, Router} from "@angular/router"; import {FormsModule} from "@angular/forms"; import {NgClass, NgForOf} from "@angular/common"; +import {QuestionService} from "../services/question.service"; @Component({ selector: 'app-edit-page', @@ -31,20 +31,20 @@ export class EditPageComponent implements OnInit { dropdownOpen: boolean = false; constructor( - private http: HttpClient, + private questionService: QuestionService, private router: Router, private route: ActivatedRoute ) {} ngOnInit() { this.route.params.subscribe((params) => { - this.questionId = params['id']; + this.questionId = '66f2a8a8aea02b6b4babc749'; this.loadQuestionData(); }); } loadQuestionData() { - this.http.get(`/api/questions/$(this.questionId)`).subscribe((data: any) => { + this.questionService.getQuestion(this.questionId).subscribe((data: any) => { this.questionTitle = data.title; this.questionDescription = data.description; this.categories.forEach(cat => { @@ -65,7 +65,7 @@ export class EditPageComponent implements OnInit { categories: this.categories.filter(cat => cat.selected).map(cat => cat.name), difficulty: this.difficulty }; - this.http.put(`/api/questions/$(this.questionId)`, updatedQuestion).subscribe((response) => { + this.questionService.updateQuestion(this.questionId, updatedQuestion).subscribe((response) => { alert('Question updated successfully!'); }, (error) => { diff --git a/peer-prep-fe/src/services/question.service.spec.ts b/peer-prep-fe/src/services/question.service.spec.ts new file mode 100644 index 0000000000..54f2238efc --- /dev/null +++ b/peer-prep-fe/src/services/question.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { QuestionService } from './question.service'; + +describe('QuestionService', () => { + let service: QuestionService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(QuestionService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/peer-prep-fe/src/services/question.service.ts b/peer-prep-fe/src/services/question.service.ts new file mode 100644 index 0000000000..8c2024ee11 --- /dev/null +++ b/peer-prep-fe/src/services/question.service.ts @@ -0,0 +1,19 @@ +import { Injectable } from '@angular/core'; +import {HttpClient} from "@angular/common/http"; +import {Observable} from "rxjs"; + +@Injectable({ + providedIn: 'root' +}) +export class QuestionService { + private baseUrl = 'http://localhost:8080/api/questions' + constructor(private http: HttpClient) { } + + getQuestion(id: string): Observable { + return this.http.get(`${this.baseUrl}/${id}`); + } + + updateQuestion(id: string, updatedQuestion: any): Observable { + return this.http.put(`${this.baseUrl}/${id}`, updatedQuestion); + } +} From f17f41a365ea8f1acb5d5925c0d0d84f4851e20a Mon Sep 17 00:00:00 2001 From: AidenLYT Date: Fri, 27 Sep 2024 19:42:25 +0800 Subject: [PATCH 04/11] Connect Edit Question page to BE --- .../src/edit-page/edit-page.component.css | 18 +++++ .../src/edit-page/edit-page.component.html | 70 +++++++++++-------- .../src/edit-page/edit-page.component.ts | 62 ++++++++++------ peer-prep-fe/src/services/question.service.ts | 3 +- 4 files changed, 100 insertions(+), 53 deletions(-) diff --git a/peer-prep-fe/src/edit-page/edit-page.component.css b/peer-prep-fe/src/edit-page/edit-page.component.css index 707d2b18ed..73020946e1 100644 --- a/peer-prep-fe/src/edit-page/edit-page.component.css +++ b/peer-prep-fe/src/edit-page/edit-page.component.css @@ -211,4 +211,22 @@ input[type="checkbox"] { transform: scale(1.1); } +.error-message-title { + color: red; + font-size: 15px; +} + +.error-message-description { + color: red; + font-size: 15px; + margin-top: -15px; +} + +.error-message-difficulty { + margin-top: 5px; + margin-left: 570px; + color: red; +} + + diff --git a/peer-prep-fe/src/edit-page/edit-page.component.html b/peer-prep-fe/src/edit-page/edit-page.component.html index fd49f20ccf..323ec76a37 100644 --- a/peer-prep-fe/src/edit-page/edit-page.component.html +++ b/peer-prep-fe/src/edit-page/edit-page.component.html @@ -4,46 +4,54 @@

EDIT QUESTION

-
-

QUESTION TITLE

-
- +
+
+

QUESTION TITLE

+
+ +
+
+ Title is required. +
-
-
-

QUESTION DESCRIPTION

-
- +
+

QUESTION DESCRIPTION

+
+ +
+
+ Description is required. +
-
+
-

CATEGORY

-
- diff --git a/peer-prep-fe/src/edit-page/edit-page.component.ts b/peer-prep-fe/src/edit-page/edit-page.component.ts index bbdf3e6ee2..e0298d5ba7 100644 --- a/peer-prep-fe/src/edit-page/edit-page.component.ts +++ b/peer-prep-fe/src/edit-page/edit-page.component.ts @@ -1,8 +1,9 @@ import { Component, OnInit } from '@angular/core'; import {ActivatedRoute, Router} from "@angular/router"; -import {FormsModule} from "@angular/forms"; -import {NgClass, NgForOf} from "@angular/common"; +import {FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators} from "@angular/forms"; +import {NgClass, NgForOf, NgIf} from "@angular/common"; import {QuestionService} from "../services/question.service"; +import {HttpClientModule} from "@angular/common/http"; @Component({ selector: 'app-edit-page', @@ -11,15 +12,19 @@ import {QuestionService} from "../services/question.service"; imports: [ FormsModule, NgClass, - NgForOf + NgForOf, + HttpClientModule, + ReactiveFormsModule, + NgIf ], - styleUrl: './edit-page.component.css' + styleUrls: ['./edit-page.component.css'] }) + export class EditPageComponent implements OnInit { - questionTitle: string= ''; + question_title: string= ''; questionId: string = ''; - questionDescription: string = ''; - categories = [ + question_description: string = ''; + question_categories = [ {name: 'Algorithms', selected: false}, {name: 'Database', selected: false}, {name: 'Shell', selected: false}, @@ -27,43 +32,58 @@ export class EditPageComponent implements OnInit { {name: 'JavaScript', selected: false}, {name: 'pandas', selected: false}, ]; - difficulty: string = ''; + question_complexity: string = ''; dropdownOpen: boolean = false; + questionForm : FormGroup; + constructor( private questionService: QuestionService, private router: Router, - private route: ActivatedRoute - ) {} + private route: ActivatedRoute, + private fb: FormBuilder + ) { + this.questionForm = this.fb.group({ + question_title: ['', Validators.required], + question_description: ['', Validators.required], + }); + } ngOnInit() { this.route.params.subscribe((params) => { - this.questionId = '66f2a8a8aea02b6b4babc749'; + this.questionId = params['id']; this.loadQuestionData(); }); } loadQuestionData() { + if (!this.questionForm.valid) { + this.questionForm.markAllAsTouched(); + } + this.questionService.getQuestion(this.questionId).subscribe((data: any) => { - this.questionTitle = data.title; - this.questionDescription = data.description; - this.categories.forEach(cat => { - cat.selected = data.categories.includes(cat.name); + const questionData = data.data.data; + this.question_title = questionData.question_title; + this.question_description = questionData.question_description; + const categoriesFromApi = questionData.question_categories || []; // Default to an empty array + this.question_categories.forEach(cat => { + cat.selected = categoriesFromApi.includes(cat.name); }); - this.difficulty = data.difficulty; + + this.question_complexity = questionData.question_complexity; }); } setDifficulty(level: string) { - this.difficulty = level; + this.question_complexity = level; } saveQuestion() { const updatedQuestion = { - title: this.questionTitle, - description: this.questionDescription, - categories: this.categories.filter(cat => cat.selected).map(cat => cat.name), - difficulty: this.difficulty + question_title: this.question_title, + question_description: this.question_description, + question_categories: this.question_categories.filter(cat => cat.selected).map(cat => cat.name), + question_complexity: this.question_complexity }; this.questionService.updateQuestion(this.questionId, updatedQuestion).subscribe((response) => { alert('Question updated successfully!'); diff --git a/peer-prep-fe/src/services/question.service.ts b/peer-prep-fe/src/services/question.service.ts index 8c2024ee11..81c17390e9 100644 --- a/peer-prep-fe/src/services/question.service.ts +++ b/peer-prep-fe/src/services/question.service.ts @@ -6,7 +6,7 @@ import {Observable} from "rxjs"; providedIn: 'root' }) export class QuestionService { - private baseUrl = 'http://localhost:8080/api/questions' + private baseUrl = 'http://localhost:8080/questions' constructor(private http: HttpClient) { } getQuestion(id: string): Observable { @@ -16,4 +16,5 @@ export class QuestionService { updateQuestion(id: string, updatedQuestion: any): Observable { return this.http.put(`${this.baseUrl}/${id}`, updatedQuestion); } + } From c2151b1a6107fc4f30113f87c1f4d75c1b8d906a Mon Sep 17 00:00:00 2001 From: AidenLYT Date: Fri, 27 Sep 2024 20:02:13 +0800 Subject: [PATCH 05/11] Connect add questions to BE --- .../src/add-page/add-page.component.html | 16 ++--- .../src/add-page/add-page.component.ts | 71 ++++++++----------- peer-prep-fe/src/app/app.config.ts | 7 +- peer-prep-fe/src/services/question.service.ts | 3 + 4 files changed, 46 insertions(+), 51 deletions(-) diff --git a/peer-prep-fe/src/add-page/add-page.component.html b/peer-prep-fe/src/add-page/add-page.component.html index 2dcf34eb28..942f05bbb1 100644 --- a/peer-prep-fe/src/add-page/add-page.component.html +++ b/peer-prep-fe/src/add-page/add-page.component.html @@ -8,9 +8,9 @@

ADD QUESTION

QUESTION TITLE

- +
-
+
Title is required.
@@ -18,9 +18,9 @@

QUESTION TITLE

QUESTION DESCRIPTION

- +
-
+
Description is required.
@@ -34,7 +34,7 @@

CATEGORY

Select all that applies diff --git a/peer-prep-fe/src/add-page/add-page.component.ts b/peer-prep-fe/src/add-page/add-page.component.ts index 869af188cc..9e0a3f3faf 100644 --- a/peer-prep-fe/src/add-page/add-page.component.ts +++ b/peer-prep-fe/src/add-page/add-page.component.ts @@ -3,6 +3,7 @@ import {NgClass, NgForOf, NgIf} from "@angular/common"; import {FormBuilder, FormsModule, Validators, FormGroup, ReactiveFormsModule, FormControl} from "@angular/forms"; import {HttpClient} from "@angular/common/http"; import {ActivatedRoute, Router, Routes} from "@angular/router"; +import {QuestionService} from "../services/question.service"; @Component({ selector: 'app-add-page', @@ -19,9 +20,9 @@ import {ActivatedRoute, Router, Routes} from "@angular/router"; }) export class AddPageComponent { - questionTitle: string= ''; - questionDescription: string = ''; - categories = [ + question_title: string= ''; + question_description: string = ''; + question_categories = [ {name: 'Algorithms', selected: false}, {name: 'Database', selected: false}, {name: 'Shell', selected: false}, @@ -29,59 +30,45 @@ export class AddPageComponent { {name: 'JavaScript', selected: false}, {name: 'pandas', selected: false}, ]; - difficulty: string = 'easy'; + question_complexity: string = 'Easy'; dropdownOpen: boolean = false; - // constructor( - // private http: HttpClient, - // private router: Router, - // private route: ActivatedRoute - // ) {} questionForm : FormGroup; - constructor(private fb: FormBuilder, private router : Router) { + + constructor( + private questionService: QuestionService, + private router: Router, + private route: ActivatedRoute, + private fb: FormBuilder + ) { this.questionForm = this.fb.group({ - title: ['', Validators.required], - description:['', Validators.required], + question_title: ['', Validators.required], + question_description: ['', Validators.required], }); } - // questionForm: FormGroup; - // constructor(private router: Router, private fb: FormBuilder) { - // this.questionForm = this.fb.group({ - // title: ['', Validators.required], - // description:['', Validators.required], - // categories: this.fb.array([]), - // difficulty: ['', Validators.required] - // }) - // } - - setDifficulty(level: string) { - this.difficulty = level; + this.question_complexity = level; } - // saveQuestion() { - // const updatedQuestion = { - // title: this.questionTitle, - // description: this.questionDescription, - // categories: this.categories.filter(cat => cat.selected).map(cat => cat.name), - // difficulty: this.difficulty - // }; - // this.http.put(`/api/questions/$(this.questionId)`, updatedQuestion).subscribe((response) => { - // alert('Question updated successfully!'); - // }, - // (error) => { - // alert('Error updating question'); - // } - // ); - // } saveQuestion() { - if (this.questionForm.valid) { - alert("Success"); - } else { + if (!this.questionForm.valid) { this.questionForm.markAllAsTouched(); } + const newQuestion = { + question_title: this.question_title, + question_description: this.question_description, + question_categories: this.question_categories.filter(cat => cat.selected).map(cat => cat.name), + question_complexity: this.question_complexity + }; + this.questionService.addQuestion(newQuestion).subscribe((response) => { + alert('Question updated successfully!'); + }, + (error) => { + alert('Error updating question'); + } + ); } toggleDropdown() { diff --git a/peer-prep-fe/src/app/app.config.ts b/peer-prep-fe/src/app/app.config.ts index a1e7d6f864..26aec981d2 100644 --- a/peer-prep-fe/src/app/app.config.ts +++ b/peer-prep-fe/src/app/app.config.ts @@ -2,7 +2,12 @@ import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core'; import { provideRouter } from '@angular/router'; import { routes } from './app.routes'; +import {provideHttpClient} from "@angular/common/http"; export const appConfig: ApplicationConfig = { - providers: [provideZoneChangeDetection({ eventCoalescing: true }), provideRouter(routes)] + providers: [ + provideZoneChangeDetection({ eventCoalescing: true }), + provideRouter(routes), + provideHttpClient() + ] }; diff --git a/peer-prep-fe/src/services/question.service.ts b/peer-prep-fe/src/services/question.service.ts index 81c17390e9..bc5edf14ee 100644 --- a/peer-prep-fe/src/services/question.service.ts +++ b/peer-prep-fe/src/services/question.service.ts @@ -17,4 +17,7 @@ export class QuestionService { return this.http.put(`${this.baseUrl}/${id}`, updatedQuestion); } + addQuestion(newQuestion: any): Observable { + return this.http.post(`${this.baseUrl}`, newQuestion); + } } From db07c94b5cbe8072e153da9f8b0c6471af35bc31 Mon Sep 17 00:00:00 2001 From: AidenLYT Date: Fri, 27 Sep 2024 20:38:36 +0800 Subject: [PATCH 06/11] Edit Add Question to connect to BE --- peer-prep-be/src/routes/question_route.go | 2 +- peer-prep-be/src/server.go | 2 +- .../src/add-page/add-page.component.html | 4 ++-- peer-prep-fe/src/add-page/add-page.component.ts | 16 ++++++++-------- .../src/edit-page/edit-page.component.ts | 2 +- peer-prep-fe/src/services/question.service.ts | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/peer-prep-be/src/routes/question_route.go b/peer-prep-be/src/routes/question_route.go index c091d96414..9b0052b584 100644 --- a/peer-prep-be/src/routes/question_route.go +++ b/peer-prep-be/src/routes/question_route.go @@ -9,7 +9,7 @@ func QuestionRoute(e *echo.Echo) { e.GET("/questions/:questionId", controllers.GetQuestion) e.GET("/questions", controllers.GetQuestions) e.GET("/questions/search", controllers.SearchQuestion) - e.POST("/question", controllers.CreateQuestion) + e.POST("/questions", controllers.CreateQuestion) e.PUT("/questions/:questionId", controllers.UpdateQuestion) e.DELETE("/questions/:questionId", controllers.DeleteQuestion) } \ No newline at end of file diff --git a/peer-prep-be/src/server.go b/peer-prep-be/src/server.go index 47c71caf49..bffe6754e0 100644 --- a/peer-prep-be/src/server.go +++ b/peer-prep-be/src/server.go @@ -19,7 +19,7 @@ func main() { e.Use(middleware.Recover()) // Recover // CORS e.Use(middleware.CORSWithConfig(middleware.CORSConfig{ - AllowOrigins: []string{"http://localhost:4200"}, + AllowOrigins: []string{"*"}, AllowMethods: []string{echo.GET, echo.HEAD, echo.PUT, echo.PATCH, echo.POST, echo.DELETE}, })) diff --git a/peer-prep-fe/src/add-page/add-page.component.html b/peer-prep-fe/src/add-page/add-page.component.html index 942f05bbb1..4b7e988288 100644 --- a/peer-prep-fe/src/add-page/add-page.component.html +++ b/peer-prep-fe/src/add-page/add-page.component.html @@ -8,7 +8,7 @@

ADD QUESTION

QUESTION TITLE

- +
Title is required. @@ -18,7 +18,7 @@

QUESTION TITLE

QUESTION DESCRIPTION

- +
Description is required. diff --git a/peer-prep-fe/src/add-page/add-page.component.ts b/peer-prep-fe/src/add-page/add-page.component.ts index 9e0a3f3faf..4b9967526a 100644 --- a/peer-prep-fe/src/add-page/add-page.component.ts +++ b/peer-prep-fe/src/add-page/add-page.component.ts @@ -7,6 +7,7 @@ import {QuestionService} from "../services/question.service"; @Component({ selector: 'app-add-page', + templateUrl: './add-page.component.html', standalone: true, imports: [ NgForOf, @@ -15,16 +16,14 @@ import {QuestionService} from "../services/question.service"; NgIf, ReactiveFormsModule ], - templateUrl: './add-page.component.html', styleUrl: './add-page.component.css' }) export class AddPageComponent { - question_title: string= ''; question_description: string = ''; question_categories = [ {name: 'Algorithms', selected: false}, - {name: 'Database', selected: false}, + {name: 'Databases', selected: false}, {name: 'Shell', selected: false}, {name: 'Concurrency', selected: false}, {name: 'JavaScript', selected: false}, @@ -51,17 +50,18 @@ export class AddPageComponent { this.question_complexity = level; } - saveQuestion() { if (!this.questionForm.valid) { this.questionForm.markAllAsTouched(); + return; } const newQuestion = { - question_title: this.question_title, - question_description: this.question_description, - question_categories: this.question_categories.filter(cat => cat.selected).map(cat => cat.name), - question_complexity: this.question_complexity + Question_title: this.questionForm.value.question_title, + Question_description: this.questionForm.value.question_description, + Question_categories: this.question_categories.filter(cat => cat.selected).map(cat => cat.name), + Question_complexity: this.question_complexity }; + console.log(newQuestion); this.questionService.addQuestion(newQuestion).subscribe((response) => { alert('Question updated successfully!'); }, diff --git a/peer-prep-fe/src/edit-page/edit-page.component.ts b/peer-prep-fe/src/edit-page/edit-page.component.ts index e0298d5ba7..a92b21225f 100644 --- a/peer-prep-fe/src/edit-page/edit-page.component.ts +++ b/peer-prep-fe/src/edit-page/edit-page.component.ts @@ -26,7 +26,7 @@ export class EditPageComponent implements OnInit { question_description: string = ''; question_categories = [ {name: 'Algorithms', selected: false}, - {name: 'Database', selected: false}, + {name: 'Databases', selected: false}, {name: 'Shell', selected: false}, {name: 'Concurrency', selected: false}, {name: 'JavaScript', selected: false}, diff --git a/peer-prep-fe/src/services/question.service.ts b/peer-prep-fe/src/services/question.service.ts index bc5edf14ee..d8e09c3151 100644 --- a/peer-prep-fe/src/services/question.service.ts +++ b/peer-prep-fe/src/services/question.service.ts @@ -18,6 +18,6 @@ export class QuestionService { } addQuestion(newQuestion: any): Observable { - return this.http.post(`${this.baseUrl}`, newQuestion); + return this.http.post(this.baseUrl, newQuestion); } } From 2c0f389ff310c7850d2e777844d1bd8fe1d5eb4f Mon Sep 17 00:00:00 2001 From: AidenLYT Date: Sat, 28 Sep 2024 18:47:00 +0800 Subject: [PATCH 07/11] Connect Edit-page with question-box --- .../question-box/question-box.component.css | 47 ++++++++++--------- .../question-box/question-box.component.html | 7 ++- .../question-box/question-box.component.ts | 22 +++++++-- .../src/edit-page/edit-page.component.css | 6 ++- .../src/edit-page/edit-page.component.html | 2 +- .../src/edit-page/edit-page.component.ts | 33 ++++++++----- 6 files changed, 78 insertions(+), 39 deletions(-) diff --git a/peer-prep-fe/src/components/question-box/question-box.component.css b/peer-prep-fe/src/components/question-box/question-box.component.css index 61218f0818..28aefc17c0 100644 --- a/peer-prep-fe/src/components/question-box/question-box.component.css +++ b/peer-prep-fe/src/components/question-box/question-box.component.css @@ -3,8 +3,8 @@ flex-direction: row; justify-content: space-between; align-items: center; - background-color: #2a2a2a; - padding: 10px 15px; + background-color: #2a2a2a; + padding: 10px 15px; border-radius: 10px; margin-bottom: 10px; width: 750px; @@ -22,29 +22,34 @@ background-color: transparent; cursor: pointer; border: none; - - } + max-width: 600px; +} + +.edit-icon { + background-color: transparent; + border: transparent; + color: white; + cursor: pointer; +} .difficulty { padding: 8px 12px; border-radius: 15px; font-size: 14px; font-family: Arial, Helvetica, sans-serif; - margin-left: 50px; - } - - .difficulty.Easy { - background-color: #159200; - color: white; - } - - .difficulty.Medium { - background-color: #CEC600; - color: white; - } - - .difficulty.Hard { - background-color: #A80000; - color: white; - } \ No newline at end of file + +.difficulty.Easy { + background-color: #159200; + color: white; +} + +.difficulty.Medium { + background-color: #CEC600; + color: white; +} + +.difficulty.Hard { + background-color: #A80000; + color: white; +} diff --git a/peer-prep-fe/src/components/question-box/question-box.component.html b/peer-prep-fe/src/components/question-box/question-box.component.html index 0c6befe96a..11f15fdc59 100644 --- a/peer-prep-fe/src/components/question-box/question-box.component.html +++ b/peer-prep-fe/src/components/question-box/question-box.component.html @@ -2,5 +2,10 @@ - {{ question.difficulty }} +
+ + {{ question.difficulty }} +
diff --git a/peer-prep-fe/src/components/question-box/question-box.component.ts b/peer-prep-fe/src/components/question-box/question-box.component.ts index d548d9b8ad..e289a8cd25 100644 --- a/peer-prep-fe/src/components/question-box/question-box.component.ts +++ b/peer-prep-fe/src/components/question-box/question-box.component.ts @@ -1,8 +1,9 @@ import { Component, Input } from '@angular/core'; -import { Question } from '../../app/models/question.model'; +import { Question } from '../../app/models/question.model'; import { CommonModule } from '@angular/common'; import { QuestionDescriptionComponent } from '../question-description/question-description.component'; import { MatDialog, MatDialogModule } from '@angular/material/dialog'; +import {EditPageComponent} from "../../edit-page/edit-page.component"; @Component({ selector: 'app-question-box', @@ -13,8 +14,8 @@ import { MatDialog, MatDialogModule } from '@angular/material/dialog'; }) export class QuestionBoxComponent { - @Input() question!: Question; - @Input() index!: number; + @Input() question!: Question; + @Input() index!: number; constructor(private dialog: MatDialog) {} @@ -29,5 +30,20 @@ export class QuestionBoxComponent { }); } + + openEditModal() { + this.dialog.open(EditPageComponent, { + data: { + questionId: '66f2a8a8aea02b6b4babc748', + }, + panelClass: 'custom-modalbox', + width: '800px', + height: '600px', + position: { + top: '200px', + }, + disableClose: true + }); + } } diff --git a/peer-prep-fe/src/edit-page/edit-page.component.css b/peer-prep-fe/src/edit-page/edit-page.component.css index 73020946e1..06c661ab02 100644 --- a/peer-prep-fe/src/edit-page/edit-page.component.css +++ b/peer-prep-fe/src/edit-page/edit-page.component.css @@ -8,6 +8,7 @@ margin-left: auto; margin-right: auto; font-family: "Signika", sans-serif; + height: 700px; } .question-title { @@ -26,7 +27,7 @@ background-color: transparent; border: none; color: #333; - font-size: 50px; + font-size: 40px; cursor: pointer; display: inline-flex; align-items: center; @@ -106,7 +107,7 @@ position: absolute; width: 80%; border: 1px solid #ccc; - max-height: 200px; + max-height: 100px; overflow-y: auto; box-shadow: 0px 8px 16px rgba(0,0,0,0.1); z-index: 1; @@ -203,6 +204,7 @@ input[type="checkbox"] { font-family: "Signika", sans-serif; background-color: white; color: black; + cursor: pointer; } .save-button:hover { diff --git a/peer-prep-fe/src/edit-page/edit-page.component.html b/peer-prep-fe/src/edit-page/edit-page.component.html index 323ec76a37..b4085e5c38 100644 --- a/peer-prep-fe/src/edit-page/edit-page.component.html +++ b/peer-prep-fe/src/edit-page/edit-page.component.html @@ -1,7 +1,7 @@

EDIT QUESTION

- +
diff --git a/peer-prep-fe/src/edit-page/edit-page.component.ts b/peer-prep-fe/src/edit-page/edit-page.component.ts index a92b21225f..2f6038cd00 100644 --- a/peer-prep-fe/src/edit-page/edit-page.component.ts +++ b/peer-prep-fe/src/edit-page/edit-page.component.ts @@ -1,9 +1,10 @@ -import { Component, OnInit } from '@angular/core'; +import {Component, Inject, OnInit} from '@angular/core'; import {ActivatedRoute, Router} from "@angular/router"; import {FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators} from "@angular/forms"; import {NgClass, NgForOf, NgIf} from "@angular/common"; import {QuestionService} from "../services/question.service"; import {HttpClientModule} from "@angular/common/http"; +import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; @Component({ selector: 'app-edit-page', @@ -26,11 +27,13 @@ export class EditPageComponent implements OnInit { question_description: string = ''; question_categories = [ {name: 'Algorithms', selected: false}, + {name: 'Arrays', selected: false}, + {name: 'Bit Manipulation', selected: false}, + {name: 'Brainteaser', selected: false}, {name: 'Databases', selected: false}, - {name: 'Shell', selected: false}, - {name: 'Concurrency', selected: false}, - {name: 'JavaScript', selected: false}, - {name: 'pandas', selected: false}, + {name: 'Data Structures', selected: false}, + {name: 'Recursion', selected: false}, + {name: 'Strings', selected: false}, ]; question_complexity: string = ''; dropdownOpen: boolean = false; @@ -41,7 +44,9 @@ export class EditPageComponent implements OnInit { private questionService: QuestionService, private router: Router, private route: ActivatedRoute, - private fb: FormBuilder + private fb: FormBuilder, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any ) { this.questionForm = this.fb.group({ question_title: ['', Validators.required], @@ -49,11 +54,17 @@ export class EditPageComponent implements OnInit { }); } + // ngOnInit() { + // this.route.params.subscribe((params) => { + // this.questionId = params['id']; + // this.loadQuestionData(); + // }); + // } ngOnInit() { - this.route.params.subscribe((params) => { - this.questionId = params['id']; + if(this.data?.questionId) { + this.questionId = this.data.questionId; this.loadQuestionData(); - }); + } } loadQuestionData() { @@ -98,8 +109,8 @@ export class EditPageComponent implements OnInit { this.dropdownOpen = !this.dropdownOpen; } - navigateToList() { - this.router.navigate(['/list-of-questions']); + navigateBack() { + this.dialogRef.close(); } } From 2f372949873cc4f5aec8c80b7a41ae904ab95aea Mon Sep 17 00:00:00 2001 From: AidenLYT Date: Sat, 28 Sep 2024 19:06:42 +0800 Subject: [PATCH 08/11] Connect list of questions with add question page --- .../src/add-page/add-page.component.css | 3 ++- .../src/add-page/add-page.component.html | 2 +- .../src/add-page/add-page.component.ts | 27 ++++++++++++------- .../question-box/question-box.component.ts | 2 +- .../search-and-filter.component.html | 5 ++-- .../search-and-filter.component.ts | 16 ++++++++++- .../src/edit-page/edit-page.component.ts | 1 + 7 files changed, 39 insertions(+), 17 deletions(-) diff --git a/peer-prep-fe/src/add-page/add-page.component.css b/peer-prep-fe/src/add-page/add-page.component.css index 98c7996ba6..e4874885d6 100644 --- a/peer-prep-fe/src/add-page/add-page.component.css +++ b/peer-prep-fe/src/add-page/add-page.component.css @@ -8,6 +8,7 @@ margin-left: auto; margin-right: auto; font-family: "Signika", sans-serif; + height: 700px; } .question-title { @@ -102,7 +103,7 @@ position: absolute; width: 80%; border: 1px solid #ccc; - max-height: 200px; + max-height: 100px; overflow-y: auto; box-shadow: 0px 8px 16px rgba(0,0,0,0.1); z-index: 1; diff --git a/peer-prep-fe/src/add-page/add-page.component.html b/peer-prep-fe/src/add-page/add-page.component.html index 4b7e988288..7d1f340450 100644 --- a/peer-prep-fe/src/add-page/add-page.component.html +++ b/peer-prep-fe/src/add-page/add-page.component.html @@ -1,7 +1,7 @@

ADD QUESTION

- +
diff --git a/peer-prep-fe/src/add-page/add-page.component.ts b/peer-prep-fe/src/add-page/add-page.component.ts index 4b9967526a..6f9b8512a8 100644 --- a/peer-prep-fe/src/add-page/add-page.component.ts +++ b/peer-prep-fe/src/add-page/add-page.component.ts @@ -1,9 +1,11 @@ -import { Component } from '@angular/core'; +import {Component, Inject} from '@angular/core'; import {NgClass, NgForOf, NgIf} from "@angular/common"; import {FormBuilder, FormsModule, Validators, FormGroup, ReactiveFormsModule, FormControl} from "@angular/forms"; import {HttpClient} from "@angular/common/http"; import {ActivatedRoute, Router, Routes} from "@angular/router"; import {QuestionService} from "../services/question.service"; +import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; +import {EditPageComponent} from "../edit-page/edit-page.component"; @Component({ selector: 'app-add-page', @@ -23,11 +25,13 @@ export class AddPageComponent { question_description: string = ''; question_categories = [ {name: 'Algorithms', selected: false}, + {name: 'Arrays', selected: false}, + {name: 'Bit Manipulation', selected: false}, + {name: 'Brainteaser', selected: false}, {name: 'Databases', selected: false}, - {name: 'Shell', selected: false}, - {name: 'Concurrency', selected: false}, - {name: 'JavaScript', selected: false}, - {name: 'pandas', selected: false}, + {name: 'Data Structures', selected: false}, + {name: 'Recursion', selected: false}, + {name: 'Strings', selected: false}, ]; question_complexity: string = 'Easy'; dropdownOpen: boolean = false; @@ -38,7 +42,9 @@ export class AddPageComponent { private questionService: QuestionService, private router: Router, private route: ActivatedRoute, - private fb: FormBuilder + private fb: FormBuilder, + private dialogRef: MatDialogRef, + @Inject(MAT_DIALOG_DATA) public data: any ) { this.questionForm = this.fb.group({ question_title: ['', Validators.required], @@ -63,10 +69,11 @@ export class AddPageComponent { }; console.log(newQuestion); this.questionService.addQuestion(newQuestion).subscribe((response) => { - alert('Question updated successfully!'); + alert('Question added successfully!'); + this.dialogRef.close(); }, (error) => { - alert('Error updating question'); + alert('Error adding question'); } ); } @@ -75,7 +82,7 @@ export class AddPageComponent { this.dropdownOpen = !this.dropdownOpen; } - navigateToList() { - this.router.navigate(['/list-of-questions']); + navigateBack() { + this.dialogRef.close(); } } diff --git a/peer-prep-fe/src/components/question-box/question-box.component.ts b/peer-prep-fe/src/components/question-box/question-box.component.ts index e289a8cd25..adffff2b81 100644 --- a/peer-prep-fe/src/components/question-box/question-box.component.ts +++ b/peer-prep-fe/src/components/question-box/question-box.component.ts @@ -34,7 +34,7 @@ export class QuestionBoxComponent { openEditModal() { this.dialog.open(EditPageComponent, { data: { - questionId: '66f2a8a8aea02b6b4babc748', + questionId: '66f7e238315ce6a3b381c481', }, panelClass: 'custom-modalbox', width: '800px', diff --git a/peer-prep-fe/src/components/search-and-filter/search-and-filter.component.html b/peer-prep-fe/src/components/search-and-filter/search-and-filter.component.html index 5192bd2c70..1814445d6f 100644 --- a/peer-prep-fe/src/components/search-and-filter/search-and-filter.component.html +++ b/peer-prep-fe/src/components/search-and-filter/search-and-filter.component.html @@ -5,10 +5,9 @@
- - + +
- \ No newline at end of file diff --git a/peer-prep-fe/src/components/search-and-filter/search-and-filter.component.ts b/peer-prep-fe/src/components/search-and-filter/search-and-filter.component.ts index e6c355b8ff..3071af9e2a 100644 --- a/peer-prep-fe/src/components/search-and-filter/search-and-filter.component.ts +++ b/peer-prep-fe/src/components/search-and-filter/search-and-filter.component.ts @@ -1,4 +1,7 @@ import { Component } from '@angular/core'; +import {EditPageComponent} from "../../edit-page/edit-page.component"; +import {MatDialog} from "@angular/material/dialog"; +import {AddPageComponent} from "../../add-page/add-page.component"; @Component({ selector: 'app-search-and-filter', @@ -8,5 +11,16 @@ import { Component } from '@angular/core'; styleUrl: './search-and-filter.component.css' }) export class SearchAndFilterComponent { - + constructor(private dialog: MatDialog) {} + openAddModal() { + this.dialog.open(AddPageComponent, { + panelClass: 'custom-modalbox', + width: '800px', + height: '600px', + position: { + top: '200px', + }, + disableClose: true + }); + } } diff --git a/peer-prep-fe/src/edit-page/edit-page.component.ts b/peer-prep-fe/src/edit-page/edit-page.component.ts index 2f6038cd00..28c09aeec0 100644 --- a/peer-prep-fe/src/edit-page/edit-page.component.ts +++ b/peer-prep-fe/src/edit-page/edit-page.component.ts @@ -98,6 +98,7 @@ export class EditPageComponent implements OnInit { }; this.questionService.updateQuestion(this.questionId, updatedQuestion).subscribe((response) => { alert('Question updated successfully!'); + this.dialogRef.close(); }, (error) => { alert('Error updating question'); From 20dfe41d33d2fefd40a862db96eefa7d19019375 Mon Sep 17 00:00:00 2001 From: AidenLYT Date: Sat, 28 Sep 2024 19:43:35 +0800 Subject: [PATCH 09/11] Edit testcase --- .../src/add-page/add-page.component.spec.ts | 18 +++++++++++++++--- .../src/add-page/add-page.component.ts | 15 ++++++++------- .../question-box/question-box.component.ts | 2 +- .../src/edit-page/edit-page.component.spec.ts | 15 ++++++++++++++- .../src/edit-page/edit-page.component.ts | 10 ++++------ .../src/services/question.service.spec.ts | 6 +++++- peer-prep-fe/src/services/question.service.ts | 1 + 7 files changed, 48 insertions(+), 19 deletions(-) diff --git a/peer-prep-fe/src/add-page/add-page.component.spec.ts b/peer-prep-fe/src/add-page/add-page.component.spec.ts index ed7cf9e30f..1cdc1a2643 100644 --- a/peer-prep-fe/src/add-page/add-page.component.spec.ts +++ b/peer-prep-fe/src/add-page/add-page.component.spec.ts @@ -1,6 +1,14 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; - import { AddPageComponent } from './add-page.component'; +import { MatDialogRef, MAT_DIALOG_DATA } from '@angular/material/dialog'; + +class MatDialogRefMock { + close() {} +} + +const mockDialogData = { + someProperty: 'someValue' +}; describe('AddPageComponent', () => { let component: AddPageComponent; @@ -8,9 +16,13 @@ describe('AddPageComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [AddPageComponent] + imports: [AddPageComponent], + providers: [ + { provide: MatDialogRef, useClass: MatDialogRefMock }, + { provide: MAT_DIALOG_DATA, useValue: mockDialogData } + ] }) - .compileComponents(); + .compileComponents(); fixture = TestBed.createComponent(AddPageComponent); component = fixture.componentInstance; diff --git a/peer-prep-fe/src/add-page/add-page.component.ts b/peer-prep-fe/src/add-page/add-page.component.ts index 6f9b8512a8..f6acfb4d98 100644 --- a/peer-prep-fe/src/add-page/add-page.component.ts +++ b/peer-prep-fe/src/add-page/add-page.component.ts @@ -1,12 +1,15 @@ -import {Component, Inject} from '@angular/core'; +import {Component, Inject, NgModule} from '@angular/core'; import {NgClass, NgForOf, NgIf} from "@angular/common"; import {FormBuilder, FormsModule, Validators, FormGroup, ReactiveFormsModule, FormControl} from "@angular/forms"; -import {HttpClient} from "@angular/common/http"; -import {ActivatedRoute, Router, Routes} from "@angular/router"; +import {HttpClient, HttpClientModule} from "@angular/common/http"; import {QuestionService} from "../services/question.service"; -import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; +import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from "@angular/material/dialog"; import {EditPageComponent} from "../edit-page/edit-page.component"; +@NgModule({ + imports: [HttpClientModule] +}) + @Component({ selector: 'app-add-page', templateUrl: './add-page.component.html', @@ -16,7 +19,7 @@ import {EditPageComponent} from "../edit-page/edit-page.component"; FormsModule, NgClass, NgIf, - ReactiveFormsModule + ReactiveFormsModule, ], styleUrl: './add-page.component.css' }) @@ -40,8 +43,6 @@ export class AddPageComponent { constructor( private questionService: QuestionService, - private router: Router, - private route: ActivatedRoute, private fb: FormBuilder, private dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any diff --git a/peer-prep-fe/src/components/question-box/question-box.component.ts b/peer-prep-fe/src/components/question-box/question-box.component.ts index adffff2b81..2834315eac 100644 --- a/peer-prep-fe/src/components/question-box/question-box.component.ts +++ b/peer-prep-fe/src/components/question-box/question-box.component.ts @@ -2,7 +2,7 @@ import { Component, Input } from '@angular/core'; import { Question } from '../../app/models/question.model'; import { CommonModule } from '@angular/common'; import { QuestionDescriptionComponent } from '../question-description/question-description.component'; -import { MatDialog, MatDialogModule } from '@angular/material/dialog'; +import {MatDialog, MatDialogModule, MatDialogRef} from '@angular/material/dialog'; import {EditPageComponent} from "../../edit-page/edit-page.component"; @Component({ diff --git a/peer-prep-fe/src/edit-page/edit-page.component.spec.ts b/peer-prep-fe/src/edit-page/edit-page.component.spec.ts index 03644b64a4..ca35b49a12 100644 --- a/peer-prep-fe/src/edit-page/edit-page.component.spec.ts +++ b/peer-prep-fe/src/edit-page/edit-page.component.spec.ts @@ -1,6 +1,15 @@ import { ComponentFixture, TestBed } from '@angular/core/testing'; import { EditPageComponent } from './edit-page.component'; +import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; + +class MatDialogRefMock { + close() {} +} + +const mockDialogData = { + someProperty: 'someValue' +}; describe('EditPageComponent', () => { let component: EditPageComponent; @@ -8,7 +17,11 @@ describe('EditPageComponent', () => { beforeEach(async () => { await TestBed.configureTestingModule({ - imports: [EditPageComponent] + imports: [EditPageComponent], + providers: [ + { provide: MatDialogRef, useClass: MatDialogRefMock }, + { provide: MAT_DIALOG_DATA, useValue: mockDialogData } + ] }) .compileComponents(); diff --git a/peer-prep-fe/src/edit-page/edit-page.component.ts b/peer-prep-fe/src/edit-page/edit-page.component.ts index 28c09aeec0..d530ab932f 100644 --- a/peer-prep-fe/src/edit-page/edit-page.component.ts +++ b/peer-prep-fe/src/edit-page/edit-page.component.ts @@ -1,10 +1,9 @@ import {Component, Inject, OnInit} from '@angular/core'; -import {ActivatedRoute, Router} from "@angular/router"; import {FormBuilder, FormGroup, FormsModule, ReactiveFormsModule, Validators} from "@angular/forms"; import {NgClass, NgForOf, NgIf} from "@angular/common"; import {QuestionService} from "../services/question.service"; -import {HttpClientModule} from "@angular/common/http"; -import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; +import {HttpClient, HttpClientModule} from "@angular/common/http"; +import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from "@angular/material/dialog"; @Component({ selector: 'app-edit-page', @@ -16,7 +15,8 @@ import {MAT_DIALOG_DATA, MatDialogRef} from "@angular/material/dialog"; NgForOf, HttpClientModule, ReactiveFormsModule, - NgIf + NgIf, + MatDialogModule ], styleUrls: ['./edit-page.component.css'] }) @@ -42,8 +42,6 @@ export class EditPageComponent implements OnInit { constructor( private questionService: QuestionService, - private router: Router, - private route: ActivatedRoute, private fb: FormBuilder, private dialogRef: MatDialogRef, @Inject(MAT_DIALOG_DATA) public data: any diff --git a/peer-prep-fe/src/services/question.service.spec.ts b/peer-prep-fe/src/services/question.service.spec.ts index 54f2238efc..86a8128b58 100644 --- a/peer-prep-fe/src/services/question.service.spec.ts +++ b/peer-prep-fe/src/services/question.service.spec.ts @@ -1,12 +1,16 @@ import { TestBed } from '@angular/core/testing'; import { QuestionService } from './question.service'; +import {HttpClientModule} from "@angular/common/http"; describe('QuestionService', () => { let service: QuestionService; beforeEach(() => { - TestBed.configureTestingModule({}); + TestBed.configureTestingModule({ + imports: [HttpClientModule], + providers: [QuestionService] + }); service = TestBed.inject(QuestionService); }); diff --git a/peer-prep-fe/src/services/question.service.ts b/peer-prep-fe/src/services/question.service.ts index d8e09c3151..d806ee142a 100644 --- a/peer-prep-fe/src/services/question.service.ts +++ b/peer-prep-fe/src/services/question.service.ts @@ -5,6 +5,7 @@ import {Observable} from "rxjs"; @Injectable({ providedIn: 'root' }) + export class QuestionService { private baseUrl = 'http://localhost:8080/questions' constructor(private http: HttpClient) { } From f36ddba04444b611b635daeea6b1c0fed604f3d4 Mon Sep 17 00:00:00 2001 From: AidenLYT Date: Sat, 28 Sep 2024 19:45:14 +0800 Subject: [PATCH 10/11] Remove ngModule for add-question --- peer-prep-fe/src/add-page/add-page.component.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/peer-prep-fe/src/add-page/add-page.component.ts b/peer-prep-fe/src/add-page/add-page.component.ts index f6acfb4d98..8e6a16fad1 100644 --- a/peer-prep-fe/src/add-page/add-page.component.ts +++ b/peer-prep-fe/src/add-page/add-page.component.ts @@ -6,10 +6,6 @@ import {QuestionService} from "../services/question.service"; import {MAT_DIALOG_DATA, MatDialogModule, MatDialogRef} from "@angular/material/dialog"; import {EditPageComponent} from "../edit-page/edit-page.component"; -@NgModule({ - imports: [HttpClientModule] -}) - @Component({ selector: 'app-add-page', templateUrl: './add-page.component.html', From 4c9739124855ea040ed248f85909548e83419444 Mon Sep 17 00:00:00 2001 From: AidenLYT Date: Sat, 28 Sep 2024 19:48:48 +0800 Subject: [PATCH 11/11] Remove ngModule --- peer-prep-fe/src/add-page/add-page.component.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/peer-prep-fe/src/add-page/add-page.component.ts b/peer-prep-fe/src/add-page/add-page.component.ts index 8e6a16fad1..4f1b4c4848 100644 --- a/peer-prep-fe/src/add-page/add-page.component.ts +++ b/peer-prep-fe/src/add-page/add-page.component.ts @@ -16,6 +16,7 @@ import {EditPageComponent} from "../edit-page/edit-page.component"; NgClass, NgIf, ReactiveFormsModule, + HttpClientModule ], styleUrl: './add-page.component.css' })