From f2f0f052cf133bd417f6ea36addd2cf2567f5519 Mon Sep 17 00:00:00 2001 From: Matthew Ross Date: Tue, 16 Jun 2020 11:00:01 -0400 Subject: [PATCH] Add direct linking to a task. Fixes #81 --- src/app/app.routes.ts | 5 +++++ src/app/board/board.component.ts | 7 +++++++ src/app/board/board.service.ts | 6 ++++++ src/app/board/column/column.component.html | 2 +- src/app/board/column/column.component.ts | 21 +++++++++++++++++-- src/app/shared/modal/modal.component.ts | 16 ++++++++------ .../app/board/column/column.component.spec.ts | 2 +- test/app/mocks.ts | 6 ++++++ test/app/shared/modal/modal.component.spec.ts | 4 ++-- 9 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 2571004..df84cc7 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -22,6 +22,11 @@ export const ROUTES: Routes = [ component: BoardDisplayComponent, canActivate: [ AuthGuard ] }, + { + path: 'boards/:id/:taskId', + component: BoardDisplayComponent, + canActivate: [ AuthGuard ] + }, { path: 'settings', component: SettingsComponent, diff --git a/src/app/board/board.component.ts b/src/app/board/board.component.ts index d4c5ebe..a81a377 100644 --- a/src/app/board/board.component.ts +++ b/src/app/board/board.component.ts @@ -80,6 +80,13 @@ export class BoardDisplayComponent implements OnInit, OnDestroy { this.loading = true; this.boardNavId = id ? id : null; this.updateActiveBoard(); + + if (!params.taskId) { + boardService.showTask(null); + return; + } + + boardService.showTask(params.taskId); }); this.subs.push(sub); } diff --git a/src/app/board/board.service.ts b/src/app/board/board.service.ts index 8df0e33..87408ec 100644 --- a/src/app/board/board.service.ts +++ b/src/app/board/board.service.ts @@ -28,8 +28,10 @@ export class BoardService extends ApiService { complete: 0 }; private activeBoard = new BehaviorSubject(null); + private showTaskId = new BehaviorSubject(null); public activeBoardChanged = this.activeBoard.asObservable(); + public showTaskIdChanged = this.showTaskId.asObservable(); constructor(private http: HttpClient, strat: LocationStrategy) { super(strat); @@ -42,6 +44,10 @@ export class BoardService extends ApiService { hljs.registerLanguage('php', php); } + showTask(id: number) { + this.showTaskId.next(id); + } + async convertMarkdown(markdown: string, callback = this.defaultCallback, doCount = false): Promise { this.checkCounts.total = 0; diff --git a/src/app/board/column/column.component.html b/src/app/board/column/column.component.html index 28bf8ff..9816fe4 100644 --- a/src/app/board/column/column.component.html +++ b/src/app/board/column/column.component.html @@ -89,7 +89,7 @@ [remove-task]="getRemoveTaskFunction(task.id)" [collapse]="collapseTasks" (on-update-boards)="callBoardUpdate();" - (dblclick)="$event.preventDefault();showViewModal(task.id)"> + (dblclick)="$event.preventDefault();getShowViewModalFunction(task.id)()"> diff --git a/src/app/board/column/column.component.ts b/src/app/board/column/column.component.ts index ec27862..273b9c0 100644 --- a/src/app/board/column/column.component.ts +++ b/src/app/board/column/column.component.ts @@ -8,6 +8,7 @@ import { Output, } from '@angular/core'; import { DomSanitizer } from '@angular/platform-browser'; +import { Location } from '@angular/common'; import { CdkDragDrop, moveItemInArray, @@ -92,6 +93,7 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy { constructor(public elRef: ElementRef, private auth: AuthService, + private location: Location, public notes: NotificationsService, public modal: ModalService, public stringsService: StringsService, @@ -99,7 +101,7 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy { private sanitizer: DomSanitizer) { this.templateElement = elRef.nativeElement; this.collapseTasks = false; - this.commentOrder = "oldest"; + this.commentOrder = 'oldest'; this.sortOption = 'pos'; this.MODAL_ID = 'add-task-form-'; @@ -126,6 +128,17 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy { }); this.subs.push(sub); + sub = boardService.showTaskIdChanged.subscribe(taskId => { + setTimeout(() => { + this.columnData?.tasks?.forEach(task => { + if (+task.id === +taskId) { + this.showViewModal(+taskId); + } + }); + }, 0); + }); + this.subs.push(sub); + sub = auth.userChanged.subscribe((user: User) => { if (user === null) { return; @@ -559,7 +572,11 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy { } getShowViewModalFunction(taskId: number): () => void { - return () => { this.showViewModal(taskId); }; + return () => { + const url = 'boards/' + this.activeBoard.id + '/' + taskId; + this.location.go(url); + this.showViewModal(taskId); + }; } showModal(taskId: number = 0) { diff --git a/src/app/shared/modal/modal.component.ts b/src/app/shared/modal/modal.component.ts index e0c39c7..929266d 100644 --- a/src/app/shared/modal/modal.component.ts +++ b/src/app/shared/modal/modal.component.ts @@ -4,6 +4,7 @@ import { OnInit, ContentChild } from '@angular/core'; +import { Location } from '@angular/common'; import { ModalService } from './modal.service'; @@ -30,7 +31,7 @@ export class ModalComponent implements OnInit { isOpen = false; animate = true; - constructor(public modalService: ModalService) { + constructor(public modalService: ModalService, private location: Location) { } ngOnInit() { @@ -39,6 +40,11 @@ export class ModalComponent implements OnInit { close(checkBlocking = false): void { this.modalService.close(this.modalId, checkBlocking); + + const path = this.location.path().split('/'); + path.length -= 1; + + this.location.go(path.join('/')) } filterClick(event: Event): void { @@ -52,13 +58,11 @@ export class ModalComponent implements OnInit { } keyup(event: KeyboardEvent): void { - // tslint:disable-next-line - if (event.keyCode === 27) { - this.modalService.close(this.modalId, true); + if (event.key === 'Escape' && this.isOpen) { + this.close(true); } - // tslint:disable-next-line - if (event.keyCode === 13) { + if (event.key === 'Enter') { this.clickDefaultAction(); } } diff --git a/test/app/board/column/column.component.spec.ts b/test/app/board/column/column.component.spec.ts index 14dcbd0..0137c39 100644 --- a/test/app/board/column/column.component.spec.ts +++ b/test/app/board/column/column.component.spec.ts @@ -513,7 +513,7 @@ describe('ColumnDisplay', () => { expect(called).toEqual(true); }); - it('opens a model to add a task', () => { + it('opens a modal to add a task', () => { component.quickAdd = { title: '' } as any; component.columnData = { id: 1 } as any; diff --git a/test/app/mocks.ts b/test/app/mocks.ts index 4b451e6..8dbd21b 100644 --- a/test/app/mocks.ts +++ b/test/app/mocks.ts @@ -19,6 +19,12 @@ export class BoardServiceMock { public activeBoardChanged = new BehaviorSubject({ id: 0, name: 'Test', columns: [] }); + public showTaskIdChanged = new BehaviorSubject(null); + + showTask(id: number) { + this.showTaskIdChanged.next(id); + } + getBoards() { return new BehaviorSubject({ data: [{}, [{ id: 1, name: 'Test', is_active: '1' }]] diff --git a/test/app/shared/modal/modal.component.spec.ts b/test/app/shared/modal/modal.component.spec.ts index 011afa1..7ced730 100644 --- a/test/app/shared/modal/modal.component.spec.ts +++ b/test/app/shared/modal/modal.component.spec.ts @@ -73,7 +73,7 @@ describe('Modal', () => { expect(checkBlocking).toEqual(true); }; - keyUp({ keyCode: 27 } as any); + keyUp({ key: 'Escape' } as any); }); it('handles the Enter key', () => { @@ -85,7 +85,7 @@ describe('Modal', () => { click: () => called = true } }; - keyUp({ keyCode: 13 } as any); + keyUp({ key: 'Enter' } as any); expect(called).toEqual(true); });