diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index cc1841907..3da673d13 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -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({ diff --git a/src/app/core/directives/internal-link-disable.directive.ts b/src/app/core/directives/internal-link-disable.directive.ts new file mode 100644 index 000000000..d15db8d47 --- /dev/null +++ b/src/app/core/directives/internal-link-disable.directive.ts @@ -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(); + } + } + } +} diff --git a/src/app/core/validators/noWhitespace.validator.ts b/src/app/core/validators/noWhitespace.validator.ts new file mode 100644 index 000000000..696232327 --- /dev/null +++ b/src/app/core/validators/noWhitespace.validator.ts @@ -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; + }; +} diff --git a/src/app/phase-bug-reporting/new-issue/new-issue.component.html b/src/app/phase-bug-reporting/new-issue/new-issue.component.html index 5af3d8332..dd98459dd 100644 --- a/src/app/phase-bug-reporting/new-issue/new-issue.component.html +++ b/src/app/phase-bug-reporting/new-issue/new-issue.component.html @@ -7,6 +7,7 @@

New Issue

Title required. + Title cannot contain only whitespaces. Title cannot exceed 256 characters. {{ 256 - title.value?.length }} characters remaining. diff --git a/src/app/phase-bug-reporting/new-issue/new-issue.component.ts b/src/app/phase-bug-reporting/new-issue/new-issue.component.ts index 58234c92c..cbd3e3c40 100644 --- a/src/app/phase-bug-reporting/new-issue/new-issue.component.ts +++ b/src/app/phase-bug-reporting/new-issue/new-issue.component.ts @@ -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({ @@ -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] @@ -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) diff --git a/src/app/shared/comment-editor/comment-editor.component.html b/src/app/shared/comment-editor/comment-editor.component.html index bac61dda7..67e729946 100644 --- a/src/app/shared/comment-editor/comment-editor.component.html +++ b/src/app/shared/comment-editor/comment-editor.component.html @@ -57,7 +57,7 @@
- +
Nothing to preview.
diff --git a/src/app/shared/issue/description/description.component.html b/src/app/shared/issue/description/description.component.html index 1d7c9bee8..08837c415 100644 --- a/src/app/shared/issue/description/description.component.html +++ b/src/app/shared/issue/description/description.component.html @@ -8,7 +8,7 @@

{{ descriptionTitle }}

- +
- #{{ duplicatedIssue.id }} + #{{ duplicatedIssue.id }} cancel diff --git a/src/app/shared/shared.module.ts b/src/app/shared/shared.module.ts index cfc65f82c..7fd9fe400 100644 --- a/src/app/shared/shared.module.ts +++ b/src/app/shared/shared.module.ts @@ -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, diff --git a/src/app/shared/view-issue/issue-dispute/issue-dispute.component.html b/src/app/shared/view-issue/issue-dispute/issue-dispute.component.html index 5350eb33d..4ab0cab8d 100644 --- a/src/app/shared/view-issue/issue-dispute/issue-dispute.component.html +++ b/src/app/shared/view-issue/issue-dispute/issue-dispute.component.html @@ -9,10 +9,10 @@

Disputes

?
- +

- +
Disputes
- +
Team's Response
- +
{{ 'The content you are editing has chang
?
- +
@@ -25,7 +25,7 @@

{{ 'The content you are editing has chang
- +
Tester's Response

?
- +

- +
Tester's Response

Reason for Disagreement:

- +