Initial boards component work.

This commit is contained in:
kiswa 2017-02-03 23:23:45 +00:00
parent 4d255af99e
commit 5c019bcaf1
9 changed files with 191 additions and 34 deletions

View File

@ -20,6 +20,7 @@ import {
InlineEdit, InlineEdit,
TopNav TopNav
} from './shared/index'; } from './shared/index';
import { BoardService } from './board/board.service';
@NgModule({ @NgModule({
imports: [ imports: [
@ -36,7 +37,8 @@ import {
AuthService, AuthService,
NotificationsService, NotificationsService,
ModalService, ModalService,
Constants Constants,
BoardService
], ],
declarations: [ declarations: [
AppComponent, AppComponent,

View File

@ -2,7 +2,7 @@ import { Routes, RouterModule } from '@angular/router';
import { AuthGuard } from './shared/index'; import { AuthGuard } from './shared/index';
import { Login } from './login/login.component'; import { Login } from './login/login.component';
import { Board } from './board/board.component'; import { BoardDisplay } from './board/board.component';
import { import {
Settings, Settings,
UserAdmin, UserAdmin,
@ -19,7 +19,12 @@ const ROUTES: Routes = [
}, },
{ {
path: 'boards', path: 'boards',
component: Board, component: BoardDisplay,
canActivate: [ AuthGuard ]
},
{
path: 'boards/:id',
component: BoardDisplay,
canActivate: [ AuthGuard ] canActivate: [ AuthGuard ]
}, },
{ {
@ -36,7 +41,7 @@ const ROUTES: Routes = [
export const ROUTE_COMPONENTS = [ export const ROUTE_COMPONENTS = [
Login, Login,
Board, BoardDisplay,
Settings, Settings,
UserAdmin, UserAdmin,
BoardAdmin, BoardAdmin,

View File

@ -3,11 +3,16 @@
<div class="board-nav"> <div class="board-nav">
<label> <label>
Select Board: Select Board:
<select> <select [(ngModel)]="boardNavId"
<option>Board Name Here</option> (change)="goToBoard()">
<option [ngValue]="null">Select Board...</option>
<option *ngFor="let board of boards"
[ngValue]="board.id">
{{ board.name }}
</option>
</select> </select>
</label> </label>
<div class="right"> <div class="right" *ngIf="activeBoard">
<label> <label>
Hide Filtered Items: Hide Filtered Items:
<input type="checkbox"> <input type="checkbox">
@ -27,7 +32,24 @@
</div> </div>
</div> </div>
<div class="board"> <div class="no-boards center" *ngIf="!boards || boards.length === 0">
<h1>No Boards</h1>
<p>{{ noBoardsMessage }}</p>
</div>
<div class="no-boards center"
*ngIf="!activeBoard && !activeUser.default_board_id">
<h1>No Default Board</h1>
<p>
You have not selected a default board. You may select a
default board in your Settings.
</p>
<p>Until then, select a board from the list above.</p>
</div>
<div class="board" *ngIf="activeBoard">
<div class="column"> <div class="column">
<h3> <h3>
<span class="icon icon-minus-squared-alt" title="Collapse All Tasks"></span> <span class="icon icon-minus-squared-alt" title="Collapse All Tasks"></span>
@ -173,5 +195,7 @@
<button class="flat"><i class="icon icon-plus"></i></button> <button class="flat"><i class="icon icon-plus"></i></button>
</div> </div>
</div> </div>
<pre><code>{{ activeUser | json }}</code></pre>
<pre><code>{{ activeBoard | json }}</code></pre>
</div> </div>

View File

@ -1,15 +1,123 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';
import { Title } from '@angular/platform-browser'; import { Title } from '@angular/platform-browser';
import { TopNav } from '../shared/index'; import { DragulaService } from 'ng2-dragula/ng2-dragula';
import {
TopNav,
ApiResponse,
Board,
Column,
User,
InlineEdit,
Modal,
Notification,
AuthService,
ModalService,
NotificationsService
} from '../shared/index';
import { BoardService } from './board.service';
@Component({ @Component({
selector: 'tb-board', selector: 'tb-board',
templateUrl: 'app/board/board.component.html' templateUrl: 'app/board/board.component.html'
}) })
export class Board { export class BoardDisplay {
constructor(private title: Title) { private activeUser: User;
private activeBoard: Board;
private boards: Array<Board>;
private boardNavId: number;
private noBoardsMessage: string;
constructor(private title: Title,
private router: Router,
private active: ActivatedRoute,
private auth: AuthService,
private modal: ModalService,
private boardService: BoardService,
private notes: NotificationsService,
private dragula: DragulaService) {
title.setTitle('TaskBoard - Kanban App'); title.setTitle('TaskBoard - Kanban App');
this.boardNavId = null;
active.params.subscribe(params => {
let id = +params['id']; // tslint:disable-line
this.boardNavId = id ? id : null;
this.updateActiveBoard();
});
boardService.getBoards().subscribe((response: ApiResponse) => {
this.updateBoardsList(response.data[1]);
});
auth.userChanged.subscribe((user: User) => {
this.updateActiveUser(user);
});
}
goToBoard(): void {
if (this.boardNavId === null) {
return;
}
this.router.navigate(['/boards/' + this.boardNavId]);
}
private updateBoardsList(boards: Array<any>): void {
let activeBoards: Array<Board> = [];
boards.forEach((board: any) => {
let currentBoard = new Board(+board.id, board.name,
board.is_active === '1', board.ownColumn,
board.ownCategory, board.ownAutoAction,
board.ownIssuetracker, board.sharedUser);
if (currentBoard.is_active) {
activeBoards.push(currentBoard);
}
});
this.boards = activeBoards;
this.boards.forEach(board => {
board.columns.sort((a: Column, b: Column) => {
return +a.position - +b.position;
});
});
this.updateActiveBoard();
}
private updateActiveBoard(): void {
if (!this.boardNavId || !this.boards) {
return;
}
this.boards.forEach(board => {
if (board.id === this.boardNavId) {
this.activeBoard = board;
}
});
}
private updateActiveUser(activeUser: User) {
this.activeUser = new User(+activeUser.default_board_id,
activeUser.email,
+activeUser.id,
activeUser.last_login,
+activeUser.security_level,
+activeUser.user_option_id,
activeUser.username,
activeUser.board_access);
this.noBoardsMessage = 'You are not assigned to any boards. ' +
'Contact an admin user to be added to a board.';
if (+activeUser.security_level === 1) {
this.noBoardsMessage = 'Go to Settings to create a board.';
}
} }
} }

View File

@ -1,4 +1,5 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { import {
ApiResponse, ApiResponse,
@ -48,7 +49,8 @@ export class AutoActions {
private modal: ModalService, private modal: ModalService,
private settings: SettingsService, private settings: SettingsService,
private actions: AutoActionsService, private actions: AutoActionsService,
private notes: NotificationsService) { private notes: NotificationsService,
private sanitizer: DomSanitizer) {
this.newAction = new AutoAction(); this.newAction = new AutoAction();
this.boards = []; this.boards = [];
this.autoActions = []; this.autoActions = [];
@ -230,7 +232,7 @@ export class AutoActions {
return desc; return desc;
} }
getTypeDescription(action: AutoAction): string { getTypeDescription(action: AutoAction): SafeHtml {
let desc = '', let desc = '',
board = this.getBoard(action.board_id); board = this.getBoard(action.board_id);
@ -267,7 +269,7 @@ export class AutoActions {
break; break;
} }
return desc; return this.sanitizer.bypassSecurityTrustHtml(desc);
} }
removeAutoAction(): void { removeAutoAction(): void {

View File

@ -169,9 +169,10 @@
<form> <form>
<input type="text" name="new-column" <input type="text" name="new-column"
placeholder="Column Name" placeholder="Column Name"
(keyup.enter)="cancelEnterKey($event)"
[(ngModel)]="modalProps.newColumnName"> [(ngModel)]="modalProps.newColumnName">
<button type="submit" class="flat" title="Add Column" <button type="submit" class="flat" title="Add Column"
(click)="modalProps.addColumn()"> (click)="modalProps.addColumn($event)">
<i class="icon icon-plus"></i> <i class="icon icon-plus"></i>
</button> </button>
</form> </form>
@ -198,12 +199,13 @@
<form> <form>
<input type="text" name="new-category" <input type="text" name="new-category"
placeholder="Category Name" placeholder="Category Name"
(keyup.enter)="cancelEnterKey($event)"
[(ngModel)]="modalProps.newCategoryName"> [(ngModel)]="modalProps.newCategoryName">
<input type="color" name="category-default-color" <input type="color" name="category-default-color"
title="Default Task Color" title="Default Task Color"
[(ngModel)]="modalProps.categoryDefaultColor"> [(ngModel)]="modalProps.categoryDefaultColor">
<button type="submit" class="flat" title="Add Category" <button type="submit" class="flat" title="Add Category"
(click)="modalProps.addCategory()"> (click)="modalProps.addCategory($event)">
<i class="icon icon-plus"></i> <i class="icon icon-plus"></i>
</button> </button>
</form> </form>
@ -242,12 +244,14 @@
<form> <form>
<input type="text" name="issue-tracker" <input type="text" name="issue-tracker"
placeholder="Issue Tracker URL - use %BUGID% as placeholder" placeholder="Issue Tracker URL - use %BUGID% as placeholder"
(keyup.enter)="cancelEnterKey($event)"
[(ngModel)]="modalProps.issueTrackerUrl"> [(ngModel)]="modalProps.issueTrackerUrl">
<input type="text" name="issue-tracker-bug-id" <input type="text" name="issue-tracker-bug-id"
placeholder="BUGID RegExp" placeholder="BUGID RegExp"
(keyup.enter)="cancelEnterKey($event)"
[(ngModel)]="modalProps.issueTrackerBugId"> [(ngModel)]="modalProps.issueTrackerBugId">
<button type="submit" class="flat" title="Add Issue Tracker" <button type="submit" class="flat" title="Add Issue Tracker"
(click)="modalProps.addIssueTracker()"> (click)="modalProps.addIssueTracker($event)">
<i class="icon icon-plus"></i> <i class="icon icon-plus"></i>
</button> </button>
</form> </form>

View File

@ -130,6 +130,11 @@ export class BoardAdmin {
this.boardService.removeBoard(this.boardToRemove.id) this.boardService.removeBoard(this.boardToRemove.id)
.subscribe((response: ApiResponse) => { .subscribe((response: ApiResponse) => {
this.handleResponse(response); this.handleResponse(response);
this.settings.getActions()
.subscribe((res: ApiResponse) => {
this.settings.updateActions(res.data[1]);
});
}); });
} }
@ -176,30 +181,24 @@ export class BoardAdmin {
this.sortBoards(); this.sortBoards();
} }
private cancelEnterKey(event: any): void {
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
}
private sortBoards(): void { private sortBoards(): void {
switch (this.sortFilter) { switch (this.sortFilter) {
case 'name-asc': case 'name-asc':
this.displayBoards.sort((a: Board, b: Board) => { this.displayBoards.sort((a: Board, b: Board) => {
let nameA = a.name.toUpperCase(), return a.name.localeCompare(b.name);
nameB = b.name.toUpperCase();
return nameA < nameB
? -1
: nameA > nameB
? 1
: 0;
}); });
break; break;
case 'name-desc': case 'name-desc':
this.displayBoards.sort((a: Board, b: Board) => { this.displayBoards.sort((a: Board, b: Board) => {
let nameA = a.name.toUpperCase(), return b.name.localeCompare(a.name);
nameB = b.name.toUpperCase();
return nameB < nameA
? -1
: nameB > nameA
? 1
: 0;
}); });
break; break;
case 'id-desc': case 'id-desc':

View File

@ -44,7 +44,10 @@ export class SettingsService {
} }
updateBoards(boards: Array<Board>): void { updateBoards(boards: Array<Board>): void {
this.boards.next(boards); this.getActions().subscribe((response: ApiResponse) => {
this.actions.next(response.data[1]);
this.boards.next(boards);
});
} }
getBoards(): Observable<ApiResponse> { getBoards(): Observable<ApiResponse> {

View File

@ -11,6 +11,16 @@
} }
} }
.no-boards {
@include shadow-low;
background-color: $white;
margin: 1em auto;
padding: 1em;
padding-bottom: .1em;
width: 45%;
}
.board { .board {
display: flex; display: flex;
height: calc(100% - 96px); height: calc(100% - 96px);