Skip to content

Commit

Permalink
Merge branch 'master' into default-main
Browse files Browse the repository at this point in the history
  • Loading branch information
cheehongw authored Feb 3, 2024
2 parents b60a182 + d4b5422 commit 0cd1148
Show file tree
Hide file tree
Showing 13 changed files with 63 additions and 15 deletions.
3 changes: 2 additions & 1 deletion src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const routes: Routes = [
{ path: 'phaseBugReporting', loadChildren: () => PhaseBugReportingModule, canLoad: [AuthGuard] },
{ path: 'phaseTeamResponse', loadChildren: () => PhaseTeamResponseModule, canLoad: [AuthGuard] },
{ path: 'phaseTesterResponse', loadChildren: () => PhaseTesterResponseModule, canLoad: [AuthGuard] },
{ path: 'phaseModeration', loadChildren: () => PhaseModerationModule, canLoad: [AuthGuard] }
{ path: 'phaseModeration', loadChildren: () => PhaseModerationModule, canLoad: [AuthGuard] },
{ path: '**', redirectTo: '' }
];

@NgModule({
Expand Down
32 changes: 32 additions & 0 deletions src/app/core/directives/internal-link-disable.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Directive, HostListener } from '@angular/core';
import { ErrorHandlingService } from '../services/error-handling.service';

class InvalidLinkError extends Error {
constructor() {
super('Invalid link!');
Object.setPrototypeOf(this, InvalidLinkError.prototype);
}
}

@Directive({
selector: '[disableInternalLink]'
})
export class InternalLinkDisableDirective {
constructor(private errorHandlingService: ErrorHandlingService) {}

@HostListener('click', ['$event'])
public onClick(e: MouseEvent): void {
const srcElement = e.target;

if (srcElement instanceof HTMLAnchorElement) {
const baseURI = srcElement.baseURI;
const href = srcElement.href;

if (href.startsWith(baseURI)) {
this.errorHandlingService.handleError(new InvalidLinkError());
e.preventDefault();
e.stopPropagation();
}
}
}
}
10 changes: 10 additions & 0 deletions src/app/core/validators/noWhitespace.validator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { AbstractControl, ValidationErrors, ValidatorFn } from '@angular/forms';

export function noWhitespace(): ValidatorFn {
return (title: AbstractControl): ValidationErrors | null => {
if (title.value && title.value.trim() === '') {
return { whitespace: true };
}
return null;
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ <h1 class="mat-display-1 title">New Issue</h1>
<mat-form-field>
<input id="title" formControlName="title" matInput placeholder="Title" required maxlength="256" />
<mat-error *ngIf="title.errors && title.errors['required'] && (title.touched || title.dirty)"> Title required. </mat-error>
<mat-error *ngIf="title.errors && title.errors['whitespace']"> Title cannot contain only whitespaces. </mat-error>
<mat-error *ngIf="title.errors && title.errors['maxlength']"> Title cannot exceed 256 characters. </mat-error>
<mat-hint *ngIf="title.value?.length >= 206"> {{ 256 - title.value?.length }} characters remaining. </mat-hint>
</mat-form-field>
Expand Down
4 changes: 3 additions & 1 deletion src/app/phase-bug-reporting/new-issue/new-issue.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Issue } from '../../core/models/issue.model';
import { ErrorHandlingService } from '../../core/services/error-handling.service';
import { IssueService } from '../../core/services/issue.service';
import { LabelService } from '../../core/services/label.service';
import { noWhitespace } from '../../core/validators/noWhitespace.validator';
import { SUBMIT_BUTTON_TEXT } from '../../shared/view-issue/view-issue.component';

@Component({
Expand All @@ -28,7 +29,7 @@ export class NewIssueComponent implements OnInit {

ngOnInit() {
this.newIssueForm = this.formBuilder.group({
title: ['', [Validators.required, Validators.maxLength(256)]],
title: ['', [Validators.required, Validators.maxLength(256), noWhitespace()]],
description: [''],
severity: ['', Validators.required],
type: ['', Validators.required]
Expand All @@ -41,6 +42,7 @@ export class NewIssueComponent implements OnInit {
if (this.newIssueForm.invalid) {
return;
}

this.isFormPending = true;
this.issueService
.createIssue(this.title.value, Issue.updateDescription(this.description.value), this.severity.value, this.type.value)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
</mat-tab>
<mat-tab label="Preview">
<div class="tab-content" style="min-height: 228px">
<markdown #markdownArea *ngIf="commentField.value !== ''" [data]="sanitize(commentField.value)"></markdown>
<markdown #markdownArea *ngIf="commentField.value !== ''" [data]="sanitize(commentField.value)" disableInternalLink></markdown>
<div *ngIf="commentField.value === ''">Nothing to preview.</div>
</div>
</mat-tab>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ <h3 class="mat-title">{{ descriptionTitle }}</h3>
</button>
</div>
<div *ngIf="!isEditing" class="comment">
<markdown [data]="issue.description"></markdown>
<markdown [data]="issue.description" disableInternalLink></markdown>
</div>
<div *ngIf="isEditing">
<app-comment-editor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
matTooltipPosition="above"
(removed)="removeDuplicateStatus(duplicatedIssue)"
>
<a class="no-underline link-grey-dark" [routerLink]="['./' + duplicatedIssue.id]"> #{{ duplicatedIssue.id }} </a>
<a class="no-underline link-grey-dark" [routerLink]="['../' + duplicatedIssue.id]"> #{{ duplicatedIssue.id }} </a>
<mat-icon *ngIf="permissions.isTeamResponseEditable() || permissions.isTutorResponseEditable()" matChipRemove>cancel</mat-icon>
</mat-chip>
</mat-chip-list>
Expand Down
4 changes: 3 additions & 1 deletion src/app/shared/shared.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ import { NgModule } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { FormDisableControlDirective } from '../core/directives/form-disable-control.directive';
import { InternalLinkDisableDirective } from '../core/directives/internal-link-disable.directive';
import { ActionToasterModule } from './action-toasters/action-toasters.module';
import { ErrorToasterModule } from './error-toasters/error-toaster.module';
import { MaterialModule } from './material.module';

@NgModule({
imports: [CommonModule, FormsModule, ReactiveFormsModule, HttpClientModule, RouterModule, MaterialModule, ErrorToasterModule],
declarations: [FormDisableControlDirective],
declarations: [FormDisableControlDirective, InternalLinkDisableDirective],
exports: [
FormDisableControlDirective,
InternalLinkDisableDirective,
CommonModule,
FormsModule,
ReactiveFormsModule,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ <h3 class="mat-title">Disputes</h3>
<div class="container" *ngFor="let dispute of issue.issueDisputes; index as i; trackBy: trackDisputeList">
<div style="display: flex; align-items: center">
<div class="question-mark">?</div>
<markdown [data]="this.getItemTitleText(dispute.title)"></markdown>
<markdown [data]="this.getItemTitleText(dispute.title)" disableInternalLink></markdown>
</div>
<br />
<markdown [data]="dispute.description"></markdown>
<markdown [data]="dispute.description" disableInternalLink></markdown>
<br />
<div>
<mat-checkbox
Expand All @@ -27,7 +27,7 @@ <h3 class="mat-title">Disputes</h3>
<br />
<div>
<markdown data="### Tutor's Response: "></markdown>
<markdown [data]="dispute.tutorResponse" *ngIf="!isEditing"></markdown>
<markdown [data]="dispute.tutorResponse" *ngIf="!isEditing" disableInternalLink></markdown>
</div>
<div *ngIf="isEditing">
<app-comment-editor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ <h3 class="mat-title">Team's Response</h3>
<button style="float: right" mat-button *ngIf="canEditIssue() && !isEditing" (click)="changeToEditMode()">Edit</button>
</div>
<div *ngIf="!isEditing" class="comment">
<markdown [data]="issue.teamResponse"></markdown>
<markdown [data]="issue.teamResponse" disableInternalLink></markdown>
</div>
<div *ngIf="isEditing">
<app-comment-editor
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ <h1 mat-dialog-title style="margin: 0">{{ 'The content you are editing has chang
<mat-expansion-panel-header>
<mat-panel-title class="response-title">
<div class="question-mark">?</div>
<markdown [data]="data.updatedResponses[i].getTitleInMarkDown()"></markdown>
<markdown [data]="data.updatedResponses[i].getTitleInMarkDown()" disableInternalLink></markdown>
</mat-panel-title>
<mat-panel-description>
<mat-chip-list>
Expand All @@ -25,7 +25,7 @@ <h1 mat-dialog-title style="margin: 0">{{ 'The content you are editing has chang
</mat-panel-description>
</mat-expansion-panel-header>
<br />
<markdown [data]="data.updatedResponses[i].description"></markdown>
<markdown [data]="data.updatedResponses[i].description" disableInternalLink></markdown>
<br />
<div
*ngIf="data.updatedResponses[i].isDisagree() === data.outdatedResponses[i].isDisagree() || !showDiff"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ <h3 class="mat-title">Tester's Response</h3>
<div class="container" *ngFor="let response of issue.testerResponses; index as i; trackBy: trackDisagreeList">
<div style="display: flex; align-items: center">
<div class="question-mark">?</div>
<markdown [data]="response.getTitleInMarkDown()"></markdown>
<markdown [data]="response.getTitleInMarkDown()" disableInternalLink></markdown>
</div>
<br />
<markdown [data]="response.description"></markdown>
<markdown [data]="response.description" disableInternalLink></markdown>
<br />
<div>
<mat-radio-group
Expand All @@ -31,7 +31,7 @@ <h3 class="mat-title">Tester's Response</h3>
<div *ngIf="testerResponseForm.get(getDisagreeRadioFormId(i)).value">
<div>
<p style="font-weight: 500">Reason for Disagreement:</p>
<markdown [data]="response.reasonForDisagreement" *ngIf="!isEditing"></markdown>
<markdown [data]="response.reasonForDisagreement" *ngIf="!isEditing" disableInternalLink></markdown>
</div>
<div *ngIf="isEditing">
<app-comment-editor
Expand Down

0 comments on commit 0cd1148

Please sign in to comment.