Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Question SPA #30

Merged
merged 56 commits into from
Sep 28, 2024
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
423a305
init question components
limcaaarl Sep 18, 2024
e15dd72
Add route for questions page
limcaaarl Sep 18, 2024
e35083b
Add table component
limcaaarl Sep 19, 2024
b335b67
Fix primeflex import
limcaaarl Sep 19, 2024
330999c
Add delete question event handling
limcaaarl Sep 19, 2024
2a21887
Merge branch 'init-primeflex' of https://github.com/limcaaarl/cs3219-…
limcaaarl Sep 20, 2024
7691aa8
Merge branch 'init-primeflex' into question-spa-frontend
limcaaarl Sep 20, 2024
6049982
Add dialog box for creating new question
limcaaarl Sep 20, 2024
8ee7707
Add edit button for each row
limcaaarl Sep 20, 2024
19dfe9d
Add Prime Icons
limcaaarl Sep 20, 2024
0a9794f
Fix edit bugs
limcaaarl Sep 21, 2024
a1eebb9
Fix spacing issues
limcaaarl Sep 21, 2024
398a915
Fix row duplicate bug
limcaaarl Sep 21, 2024
669c329
Update question data to read locally
limcaaarl Sep 21, 2024
6c3c4ea
Fix pagination bug
limcaaarl Sep 21, 2024
7a8e2f4
Reformat code for consistent indetation
limcaaarl Sep 22, 2024
807dc1b
Refactor classes and enums into separate files
limcaaarl Sep 22, 2024
599addf
Fix bug where selected row is not getting updated after edit
limcaaarl Sep 22, 2024
b0bae2a
Remove redundant component
limcaaarl Sep 22, 2024
56d7831
Merge pull request #29 from limcaaarl/question-spa-frontend
limcaaarl Sep 22, 2024
25ce3b8
Fix lint error
limcaaarl Sep 22, 2024
6aee0ac
Merge pull request #31 from limcaaarl/question-spa-frontend
limcaaarl Sep 22, 2024
68d682e
Merge branch 'main' into question-spa-frontend
limcaaarl Sep 24, 2024
6323496
Update minor changes
limcaaarl Sep 24, 2024
78872ba
Fix indentations inconsistencies for .html files
limcaaarl Sep 24, 2024
31dd2a8
Update budget limit
limcaaarl Sep 24, 2024
c91c83c
Merge branch 'main' into question-spa-frontend
limcaaarl Sep 25, 2024
90173d7
Generate template for service caller
limcaaarl Sep 25, 2024
f20f99c
Refactor models into separate files
limcaaarl Sep 25, 2024
20205c6
Add config file to store base url
limcaaarl Sep 25, 2024
f8b1544
Implement QuestionService with getQuestions method
limcaaarl Sep 25, 2024
ddb9c84
Fix linting
limcaaarl Sep 25, 2024
193e33f
Implement getTopics method
limcaaarl Sep 26, 2024
ca65293
Add forkJoin to combine question and topic API calls
limcaaarl Sep 26, 2024
bbbf308
Add API calls
limcaaarl Sep 26, 2024
abd4117
Integrate API calls with UI
limcaaarl Sep 26, 2024
ce558d0
Update error message handling
limcaaarl Sep 27, 2024
a354be1
Fix merge conflicts
limcaaarl Sep 27, 2024
7a3313c
Add loading spinner when fetching all data
limcaaarl Sep 27, 2024
dc4279b
Update loading spinner style
limcaaarl Sep 27, 2024
1ddb1f9
Remove locally stored questions
limcaaarl Sep 27, 2024
b84cb20
Update id column to be sortable
limcaaarl Sep 27, 2024
efc6e14
Fix topics field validation
limcaaarl Sep 27, 2024
9e8fc42
Update form errors to use the new Angular @if syntax
limcaaarl Sep 27, 2024
60464d3
Update to use formGroup.value instead of field listeners
limcaaarl Sep 27, 2024
129e4b0
Fix dialog header text
limcaaarl Sep 27, 2024
8ce20c2
Move question.service.ts to shared services folder
limcaaarl Sep 27, 2024
e63f15c
Extract dialog box into a new component
limcaaarl Sep 27, 2024
6fc2041
Update topics dropdown to allow addition of new topics
limcaaarl Sep 27, 2024
b5168bb
Fix margin issue with dialog box
limcaaarl Sep 27, 2024
4d03d12
Fix css issue with add new topic button
limcaaarl Sep 27, 2024
4d3cb1c
Improve add new topic behaviour
samuelim01 Sep 27, 2024
a4ea983
Fix minor issues
limcaaarl Sep 27, 2024
4d25437
Fix merge conflicts
limcaaarl Sep 27, 2024
ae4ba44
Fix bugs
limcaaarl Sep 28, 2024
28dbdd2
Merge branch 'main' into question-spa-frontend
limcaaarl Sep 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@angular/platform-browser-dynamic": "^18.2.0",
"@angular/router": "^18.2.0",
"primeflex": "^3.3.1",
"primeicons": "^7.0.0",
"primeng": "^17.18.10",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
Expand Down
9 changes: 0 additions & 9 deletions frontend/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,10 +1 @@
<main class="main">
<div class="content">
<p class="mt-0">Hello, this is a paragraph!</p>
<p-button label="Click me!"/>
<label class="mt-4" for="password">I am a label.</label>
<p-password class="mt-2" id="password"/>
</div>
</main>

<router-outlet />
1 change: 0 additions & 1 deletion frontend/src/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';

import { routes } from './app.routes';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';

Expand Down
8 changes: 7 additions & 1 deletion frontend/src/app/app.routes.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import { Routes } from '@angular/router';
import { QuestionsComponent } from './questions/questions.component';

export const routes: Routes = [];
export const routes: Routes = [
{
path: 'questions',
component: QuestionsComponent,
},
];
5 changes: 5 additions & 0 deletions frontend/src/app/questions/difficulty-levels.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum DifficultyLevels {
EASY = 'Easy',
MEDIUM = 'Medium',
HARD = 'Hard',
}
22 changes: 22 additions & 0 deletions frontend/src/app/questions/question.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
export interface Question {
id?: number;
title?: string;
description?: string;
topics?: string[];
difficulty?: string;
}

export interface Column {
field: string;
header: string;
}

export interface Topic {
label: string;
value: string;
}

export interface Difficulty {
label: string;
value: string;
}
Empty file.
158 changes: 158 additions & 0 deletions frontend/src/app/questions/questions.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
<div class="card mx-8">
<p-toast />
<p-toolbar styleClass="mb-2 gap-2">
<div class="p-justify-end">
<p-button
icon="pi pi-plus"
severity="primary"
[outlined]="true"
label="New"
class="mr-2"
(onClick)="openNewQuestion()" />
<p-button
icon="pi pi-trash"
severity="danger"
label="Delete"
(onClick)="deleteSelectedQuestions()"
[disabled]="!selectedQuestions || !selectedQuestions.length" />
</div>
</p-toolbar>
<p-table
[columns]="cols"
[value]="questions"
[(selection)]="selectedQuestions"
datakey="id"
[tableStyle]="{ 'min-width': '50rem' }"
[paginator]="true"
[rows]="5"
[rowsPerPageOptions]="[5, 10, 20]"
styleClass="p-datatable-gridlines-striped">
<ng-template pTemplate="caption">
<div class="flex">
<h3 class="m-0">Manage Questions</h3>
</div>
</ng-template>
<ng-template pTemplate="header" let-columns>
<tr>
<th style="width: 4rem"><p-tableHeaderCheckbox /></th>
<th>Id</th>
<th>Title</th>
<th>Description</th>
<th>Topics</th>
<th>Difficulty</th>
<th></th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-question>
<tr>
<td>
<p-tableCheckbox [value]="question" />
</td>
<td>{{question.id}}</td>
<td>{{question.title}}</td>
<td>{{question.description}}</td>
<td>{{question.topics}}</td>
limcaaarl marked this conversation as resolved.
Show resolved Hide resolved
<td>{{question.difficulty}}</td>
<td>
<p-button
label="Edit"
severity="primary"
icon="pi pi-file-edit"
class="mr-2"
[text]="true"
(onClick)="editQuestion(question)" />
</td>
</tr>
</ng-template>
</p-table>

<p-dialog
header="Header"
[(visible)]="isDialogVisible"
[modal]="true"
[style]="{ width: '25rem' }">
<ng-template pTemplate="header">
<div class="inline-flex align-items-center justify-content-center gap-2">
<span class="font-bold white-space-nowrap">
Create new question
</span>
</div>
</ng-template>

<form [formGroup]="questionFormGroup">
<div class="field grid col-12">
<label for="title">Title</label>
<input
formControlName="textTitle"
type="text"
pInputText
id="title"
required

class="text-base text-color surface-overlay p-2 border-1 border-solid surface-border border-round appearance-none outline-none focus:border-primary w-full">
<small class="p-error" *ngIf="submitted && (question.title === undefined || !question.title)">
samuelim01 marked this conversation as resolved.
Show resolved Hide resolved
Title is required.
</small>
</div>
<div class="formgrid grid field">
<div class="field col-12 md:col-6">
<label for="questionTopics">Topics</label>
<p-multiSelect
required="true"
[style]="{'width':'100%'}"
[options]="topics"
formControlName="selectedTopics"
optionLabel="label"
optionValue="value"
placeholder="Select Topics"/>
<small class="p-error" *ngIf="submitted && (question.topics === undefined || question.topics.length === 0)">
Topic is required.
</small>
</div>
<div class="field col-12 md:col-6">
<label for="questionTopics">Difficulty</label>
<p-dropdown
[required]="true"
[style]="{'width':'100%'}"
[options]="difficulties"
formControlName="selectedDifficulty"
optionLabel="label"
optionValue="value"
placeholder="Select Difficulty" />
<small class="p-error" *ngIf="submitted && (question.difficulty === undefined || !question.difficulty)">
Difficulty is required.
</small>
</div>
</div>
<div class="field grid col-12" field>
<label for="questionDescription">Description</label>
<textarea
formControlName="textDescription"
[required]="true"
id="questionDescription"
type="text"
rows="6"
class="text-base text-color surface-overlay p-2 border-1 border-solid surface-border border-round appearance-none outline-none focus:border-primary w-full">
</textarea>
<small class="p-error" *ngIf="submitted && (question.description === undefined || !question.description)">
Description is required.
</small>
</div>
</form>

<ng-template pTemplate="footer">
<p-button
label="Cancel"
[text]="true"
severity="secondary"
(onClick)="isDialogVisible = false" />
<p-button
label="Save"
class="p-button-success"
(onClick)="saveQuestion()"
/>
</ng-template>
</p-dialog>

<p-confirmDialog [style]="{ width: '450px' }" />
</div>
22 changes: 22 additions & 0 deletions frontend/src/app/questions/questions.component.spec.ts
samuelim01 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { QuestionsComponent } from './questions.component';

describe('QuestionsComponent', () => {
let component: QuestionsComponent;
let fixture: ComponentFixture<QuestionsComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [QuestionsComponent],
}).compileComponents();

fixture = TestBed.createComponent(QuestionsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Loading
Loading