Initial boards component work.
This commit is contained in:
parent
4d255af99e
commit
5c019bcaf1
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
@ -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.';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
@ -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>
|
||||||
|
@ -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':
|
||||||
|
@ -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> {
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user