Task drag-and-drop.
This commit is contained in:
parent
ad051c1220
commit
92132b3f59
@ -17,12 +17,19 @@
|
||||
<div class="right" *ngIf="activeBoard">
|
||||
<label>
|
||||
{{ strings['boards_hideFiltered'] }}:
|
||||
<input type="checkbox">
|
||||
<input type="checkbox" [(ngModel)]="hideFiltered"
|
||||
(change)="toggleFiltered()">
|
||||
</label>
|
||||
<label>
|
||||
{{ strings['boards_userFilter'] }}:
|
||||
<select [(ngModel)]="userFilter">
|
||||
<option [ngValue]="null">Any</option>
|
||||
<select [(ngModel)]="userFilter"
|
||||
(change)="filterTasks('user')">
|
||||
<option [ngValue]="null">
|
||||
{{ strings['boards_filterByAny'] }}
|
||||
</option>
|
||||
<option [ngValue]="-1">
|
||||
{{ strings['boards_filterByUnassigned'] }}
|
||||
</option>
|
||||
<option *ngFor="let user of activeBoard.users"
|
||||
[ngValue]="user.id">
|
||||
{{ user.username }}
|
||||
@ -31,8 +38,14 @@
|
||||
</label>
|
||||
<label>
|
||||
{{ strings['boards_categoryFilter'] }}:
|
||||
<select [(ngModel)]="categoryFilter">
|
||||
<option [ngValue]="null">Any</option>
|
||||
<select [(ngModel)]="categoryFilter"
|
||||
(change)="filterTasks('cat')">
|
||||
<option [ngValue]="null">
|
||||
{{ strings['boards_filterByAny'] }}
|
||||
</option>
|
||||
<option [ngValue]="-1">
|
||||
{{ strings['boards_filterByUncategorized'] }}
|
||||
</option>
|
||||
<option *ngFor="let category of activeBoard.categories"
|
||||
[ngValue]="category.id">
|
||||
{{ category.name }}
|
||||
@ -61,7 +74,7 @@
|
||||
</div>
|
||||
|
||||
<div class="board" *ngIf="activeBoard">
|
||||
<tb-column class="column"
|
||||
<tb-column class="column" [id]="column.id"
|
||||
*ngFor="let column of activeBoard.columns"
|
||||
[column]="column"
|
||||
[boards]="boards"
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
ApiResponse,
|
||||
Board,
|
||||
Column,
|
||||
Task,
|
||||
User,
|
||||
Notification,
|
||||
AuthService,
|
||||
@ -31,9 +32,12 @@ export class BoardDisplay implements OnInit {
|
||||
private boardNavId: number;
|
||||
private userFilter: number;
|
||||
private categoryFilter: number;
|
||||
|
||||
private noBoardsMessage: string;
|
||||
private pageName: string;
|
||||
|
||||
private loading: boolean;
|
||||
private hideFiltered: boolean;
|
||||
|
||||
constructor(private title: Title,
|
||||
private router: Router,
|
||||
@ -71,6 +75,8 @@ export class BoardDisplay implements OnInit {
|
||||
|
||||
this.activeBoard = board;
|
||||
title.setTitle('TaskBoard - ' + board.name);
|
||||
this.userFilter = null;
|
||||
this.categoryFilter = null;
|
||||
});
|
||||
|
||||
auth.userChanged.subscribe((user: User) => {
|
||||
@ -96,6 +102,34 @@ export class BoardDisplay implements OnInit {
|
||||
}
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
let bag = this.dragula.find('tasks-bag');
|
||||
|
||||
if (bag) {
|
||||
this.dragula.destroy('tasks-bag');
|
||||
}
|
||||
|
||||
this.dragula.setOptions('tasks-bag', {
|
||||
moves: (el: any, container: any, handle: any) => {
|
||||
return handle.classList.contains('drag-handle');
|
||||
}
|
||||
});
|
||||
|
||||
this.dragula.dropModel.subscribe((value: any) => {
|
||||
this.activeBoard.columns.forEach(column => {
|
||||
let position = 0;
|
||||
column.tasks.forEach(task => {
|
||||
task.column_id = column.id;
|
||||
task.position = position;
|
||||
|
||||
position++;
|
||||
});
|
||||
});
|
||||
|
||||
this.boardService.updateBoard(this.activeBoard).subscribe();
|
||||
});
|
||||
}
|
||||
|
||||
goToBoard(): void {
|
||||
if (this.boardNavId === null) {
|
||||
return;
|
||||
@ -112,6 +146,70 @@ export class BoardDisplay implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
toggleFiltered() {
|
||||
this.activeBoard.columns.forEach(column => {
|
||||
column.tasks.forEach(task => {
|
||||
task.hideFiltered = this.hideFiltered;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
filterTasks(type: string) {
|
||||
this.activeBoard.columns.forEach(column => {
|
||||
column.tasks.forEach(task => {
|
||||
task.filtered = false;
|
||||
|
||||
if (this.userFilter) {
|
||||
let found = false;
|
||||
|
||||
if (this.userFilter === -1 &&
|
||||
task.assignees.length === 0) {
|
||||
found = true;
|
||||
}
|
||||
|
||||
task.assignees.forEach(user => {
|
||||
if (user.id === this.userFilter) {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!found) {
|
||||
task.filtered = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.categoryFilter) {
|
||||
let found = false;
|
||||
|
||||
if (this.categoryFilter === -1 &&
|
||||
task.categories.length === 0) {
|
||||
found = true;
|
||||
}
|
||||
|
||||
task.categories.forEach(cat => {
|
||||
if (cat.id === this.categoryFilter) {
|
||||
found = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (!found) {
|
||||
task.filtered = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private runFilter(testFunc: Function) {
|
||||
this.activeBoard.columns.forEach(column => {
|
||||
column.tasks.forEach(task => {
|
||||
let found = testFunc(task);
|
||||
|
||||
task.filtered = !found;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
private updateBoardsList(boards: Array<any>): void {
|
||||
let activeBoards: Array<Board> = [];
|
||||
|
||||
|
@ -42,6 +42,12 @@ export class BoardService {
|
||||
.catch(this.errorHandler);
|
||||
}
|
||||
|
||||
updateBoard(board: Board): Observable<ApiResponse> {
|
||||
return this.http.post('api/boards/' + board.id, board)
|
||||
.map(this.toApiResponse)
|
||||
.catch(this.errorHandler);
|
||||
}
|
||||
|
||||
updateColumn(column: Column): Observable<ApiResponse> {
|
||||
return this.http.post('api/columns/' + column.id, column)
|
||||
.map(this.toApiResponse)
|
||||
|
@ -71,8 +71,10 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="tasks">
|
||||
<tb-task class="task-container" *ngFor="let task of columnData.tasks"
|
||||
<div class="tasks"
|
||||
[dragula]="'tasks-bag'" [dragulaModel]="columnData.tasks">
|
||||
<tb-task class="task-container" [id]="task.id"
|
||||
*ngFor="let task of columnData.tasks"
|
||||
[task]="task" [boards]="boards"
|
||||
[add-task]="getShowModalFunction()"
|
||||
[edit-task]="getShowModalFunction(task.id)"
|
||||
|
@ -1,7 +1,9 @@
|
||||
<div class="task"
|
||||
[ngClass]="{ 'filtered': taskData.filtered,
|
||||
'hide': taskData.hideFiltered }"
|
||||
[style.backgroundColor]="taskData.color"
|
||||
[style.color]="getTextColor(taskData.color)">
|
||||
<h4>
|
||||
<h4 class="drag-handle">
|
||||
<span class="icon"
|
||||
[style.color]="getTextColor(taskData.color)"
|
||||
[ngClass]="{ 'icon-minus-squared-alt': !isCollapsed,
|
||||
|
@ -169,8 +169,16 @@ export class TaskDisplay implements OnInit {
|
||||
|
||||
menuText += '</select>';
|
||||
|
||||
let action = (event: any) => {
|
||||
if (event.target.tagName !== 'SELECT') {
|
||||
return;
|
||||
}
|
||||
|
||||
this.changeTaskColumn();
|
||||
};
|
||||
|
||||
return new ContextMenuItem(menuText,
|
||||
() => { this.changeTaskColumn(); },
|
||||
action,
|
||||
false, false);
|
||||
}
|
||||
|
||||
@ -240,7 +248,11 @@ export class TaskDisplay implements OnInit {
|
||||
|
||||
menuText += '</select>';
|
||||
|
||||
let action = () => {
|
||||
let action = (event: any) => {
|
||||
if (event.target.tagName !== 'SELECT') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (text === this.strings.boards_copyTaskTo) {
|
||||
this.copyTaskToBoard();
|
||||
return;
|
||||
|
@ -190,6 +190,10 @@
|
||||
"boards_taskCopied": "copied to board",
|
||||
"boards_taskMoved": "moved to board",
|
||||
|
||||
"boards_filterByAny": "Any",
|
||||
"boards_filterByUnassigned": "Unassigned",
|
||||
"boards_filterByUncategorized": "Uncategorized",
|
||||
|
||||
"boards_sortByPosition": "Position",
|
||||
"boards_sortByDueDate": "Due Date",
|
||||
"boards_sortByLastModified": "Last Modifed",
|
||||
|
@ -190,6 +190,10 @@
|
||||
"boards_taskCopied": "copiado a tablero",
|
||||
"boards_taskMoved": "movido a tablero",
|
||||
|
||||
"boards_filterByAny": "Alguna",
|
||||
"boards_filterByUnassigned": "Sin Asignar",
|
||||
"boards_filterByUncategorized": "Sin Categoría",
|
||||
|
||||
"boards_sortByPosition": "Posición",
|
||||
"boards_sortByDueDate": "Fecha de Vencimiento",
|
||||
"boards_sortByLastModified": "Última Modificación",
|
||||
|
@ -190,6 +190,8 @@
|
||||
}
|
||||
|
||||
.tasks {
|
||||
flex: 1 0;
|
||||
flex-direction: column;
|
||||
overflow-y: auto;
|
||||
padding: 7px;
|
||||
padding-top: 0;
|
||||
@ -283,6 +285,14 @@
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.filtered {
|
||||
opacity: .4;
|
||||
|
||||
&.hide {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user