Boards use language settings, columns have task limit
This commit is contained in:
parent
d133903a37
commit
29edbaaed6
@ -6,7 +6,7 @@ linters:
|
||||
width: 4
|
||||
|
||||
NestingDepth:
|
||||
max_depth: 4
|
||||
max_depth: 5
|
||||
|
||||
SelectorDepth:
|
||||
max_depth: 4
|
||||
|
10
README.md
10
README.md
@ -151,11 +151,11 @@ Because I like seeing the numbers.
|
||||
|
||||
Language | Files | Blank | Comment | Code
|
||||
-------------|--------:|---------:|--------:|---------:
|
||||
TypeScript | 60 | 711 | 30 | 3294
|
||||
PHP | 18 | 562 | 19 | 1755
|
||||
HTML | 19 | 137 | 0 | 1193
|
||||
SASS | 14 | 225 | 12 | 1029
|
||||
__SUM:__ | __111__ | __1635__ | __61__ | __7271__
|
||||
TypeScript | 60 | 728 | 30 | 3352
|
||||
PHP | 18 | 562 | 19 | 1756
|
||||
HTML | 19 | 138 | 0 | 1223
|
||||
SASS | 14 | 231 | 12 | 1057
|
||||
__SUM:__ | __111__ | __1659__ | __61__ | __7388__
|
||||
|
||||
Command: `cloc --exclude-dir=vendor --exclude-ext=json src/`
|
||||
|
||||
|
@ -26,7 +26,7 @@ class Columns extends BaseController {
|
||||
}
|
||||
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addData($column);
|
||||
$this->apiJson->addData(R::exportAll($column));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
@ -108,6 +108,7 @@ class Columns extends BaseController {
|
||||
$this->apiJson->setSuccess();
|
||||
$this->apiJson->addAlert('success', 'Column ' .
|
||||
$update->name . ' updated.');
|
||||
$this->apiJson->addData(R::exportAll($update));
|
||||
|
||||
return $this->jsonResponse($response);
|
||||
}
|
||||
|
@ -2,10 +2,12 @@
|
||||
|
||||
<div class="board-nav">
|
||||
<label *ngIf="boards && boards.length">
|
||||
Select Board:
|
||||
{{ strings['boards_selectBoard'] }}:
|
||||
<select [(ngModel)]="boardNavId"
|
||||
(change)="goToBoard()">
|
||||
<option [ngValue]="null">Select Board...</option>
|
||||
<option [ngValue]="null">
|
||||
{{ strings['boards_selectBoard'] }}...
|
||||
</option>
|
||||
<option *ngFor="let board of boards"
|
||||
[ngValue]="board.id">
|
||||
{{ board.name }}
|
||||
@ -14,11 +16,11 @@
|
||||
</label>
|
||||
<div class="right" *ngIf="activeBoard">
|
||||
<label>
|
||||
Hide Filtered Items:
|
||||
{{ strings['boards_hideFiltered'] }}:
|
||||
<input type="checkbox">
|
||||
</label>
|
||||
<label>
|
||||
User Filter:
|
||||
{{ strings['boards_userFilter'] }}:
|
||||
<select [(ngModel)]="userFilter">
|
||||
<option [ngValue]="null">Any</option>
|
||||
<option *ngFor="let user of activeBoard.users"
|
||||
@ -28,7 +30,7 @@
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
Category Filter:
|
||||
{{ strings['boards_categoryFilter'] }}:
|
||||
<select [(ngModel)]="categoryFilter">
|
||||
<option [ngValue]="null">Any</option>
|
||||
<option *ngFor="let category of activeBoard.categories"
|
||||
@ -41,20 +43,21 @@
|
||||
</div>
|
||||
|
||||
<div class="no-boards center" *ngIf="noBoards()">
|
||||
<h1>No Boards</h1>
|
||||
<h1>{{ strings['boards_noBoards'] }}</h1>
|
||||
|
||||
<p>{{ noBoardsMessage }}</p>
|
||||
</div>
|
||||
|
||||
<div class="no-boards center"
|
||||
*ngIf="!loading && !activeBoard && !noBoards() && !activeUser.default_board_id">
|
||||
<h1>No Default Board</h1>
|
||||
<h1>{{ strings['boards_noDefault'] }}</h1>
|
||||
|
||||
<p>
|
||||
You have not selected a default board. You may select a
|
||||
default board in your <a href="javascript:" [routerLink]="['/settings']">Settings</a>.
|
||||
<p>{{ strings['boards_noDefaultMessage'] }}
|
||||
<a href="javascript:" [routerLink]="['/settings']">
|
||||
{{ strings['settings'] }}
|
||||
</a>.
|
||||
</p>
|
||||
<p>Until then, select a board from the list above.</p>
|
||||
<p></p>
|
||||
</div>
|
||||
|
||||
<div class="board" *ngIf="activeBoard">
|
||||
|
@ -27,6 +27,7 @@ export class BoardDisplay implements OnInit {
|
||||
private activeBoard: Board;
|
||||
private boards: Array<Board>;
|
||||
|
||||
private strings: any;
|
||||
private boardNavId: number;
|
||||
private userFilter: number;
|
||||
private categoryFilter: number;
|
||||
@ -52,6 +53,15 @@ export class BoardDisplay implements OnInit {
|
||||
this.pageName = 'Boards';
|
||||
this.loading = true;
|
||||
|
||||
stringsService.stringsChanged.subscribe(newStrings => {
|
||||
this.strings = newStrings;
|
||||
|
||||
// Updating the active user updates some display strings.
|
||||
if (this.activeUser) {
|
||||
this.updateActiveUser(this.activeUser);
|
||||
}
|
||||
});
|
||||
|
||||
boardService.getBoards().subscribe((response: ApiResponse) => {
|
||||
this.updateBoardsList(response.data[1]);
|
||||
this.loading = false;
|
||||
@ -151,11 +161,10 @@ export class BoardDisplay implements OnInit {
|
||||
activeUser.username,
|
||||
activeUser.board_access);
|
||||
|
||||
this.noBoardsMessage = 'You are not assigned to any boards. ' +
|
||||
'Contact an admin user to be added to a board.';
|
||||
this.noBoardsMessage = this.strings.boards_noBoardsMessageUser;
|
||||
|
||||
if (+activeUser.security_level === 1) {
|
||||
this.noBoardsMessage = 'Go to Settings to create a board.';
|
||||
this.noBoardsMessage = this.strings.boards_noBoardsMessageAdmin;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,7 @@ import 'rxjs/add/operator/catch';
|
||||
|
||||
import {
|
||||
ApiResponse,
|
||||
Column,
|
||||
Board,
|
||||
Task,
|
||||
User
|
||||
@ -41,6 +42,12 @@ export class BoardService {
|
||||
.catch(this.errorHandler);
|
||||
}
|
||||
|
||||
updateColumn(column: Column): Observable<ApiResponse> {
|
||||
return this.http.post('api/columns/' + column.id, column)
|
||||
.map(this.toApiResponse)
|
||||
.catch(this.errorHandler);
|
||||
}
|
||||
|
||||
addTask(task: Task): Observable<ApiResponse> {
|
||||
return this.http.post('api/tasks', task)
|
||||
.map(this.toApiResponse)
|
||||
@ -59,7 +66,6 @@ export class BoardService {
|
||||
.catch(this.errorHandler);
|
||||
}
|
||||
|
||||
// TODO: Determine when to use this
|
||||
refreshToken(): void {
|
||||
this.http.post('api/refresh', {}).subscribe();
|
||||
}
|
||||
|
@ -1,42 +1,57 @@
|
||||
<h3>
|
||||
<h3 [class.near-limit]="columnData.hasTaskLimit() &&
|
||||
columnData.task_limit - columnData.tasks.length === 1"
|
||||
[class.limit-reached]="columnData.hasTaskLimit() &&
|
||||
columnData.task_limit - columnData.tasks.length < 1">
|
||||
<span class="icon icon-minus-squared-alt"
|
||||
title="Collapse All Tasks"
|
||||
[title]="strings['boards_collapseAllTasks']"
|
||||
*ngIf="!collapseTasks"
|
||||
(click)="toggleTaskCollapse()"></span>
|
||||
<span class="icon icon-plus-squared-alt"
|
||||
title="Expand All Tasks"
|
||||
[title]="strings['boards_expandAllTasks']"
|
||||
*ngIf="collapseTasks"
|
||||
(click)="toggleTaskCollapse()"></span>
|
||||
|
||||
{{ columnData.name }}
|
||||
|
||||
<span class="badge" title="Tasks in Column">
|
||||
{{ columnData.tasks && columnData.tasks.length || 0 }}
|
||||
</span>
|
||||
|
||||
<span class="icon icon-angle-double-up"
|
||||
title="Expand Column" (click)="toggleCollapsed()"></span>
|
||||
<span class="right icon icon-angle-double-down"
|
||||
title="Collapse Column" (click)="toggleCollapsed()"></span>
|
||||
|
||||
<span class="count" *ngIf="columnData.hasTaskLimit()">
|
||||
{{ columnData.tasks.length + ' / ' + columnData.task_limit }}
|
||||
</span>
|
||||
|
||||
<span class="count-editor" title="Edit Task Limit"
|
||||
<span class="badge" [title]="strings['boards_tasksInColumn']">
|
||||
{{ columnData.tasks && columnData.tasks.length || 0 }}
|
||||
</span>
|
||||
|
||||
<span class="icon icon-angle-double-up"
|
||||
[title]="strings['boards_expandColumn']" (click)="toggleCollapsed()"></span>
|
||||
<span class="right icon icon-angle-double-down"
|
||||
[title]="strings['boards_collapseColumn']" (click)="toggleCollapsed()"></span>
|
||||
|
||||
<span class="count-editor"
|
||||
*ngIf="activeUser.isAdmin() || activeUser.isBoardAdmin()">
|
||||
<i class="icon icon-hashtag"
|
||||
(click)="showLimitEditor = !showLimitEditor"></i>
|
||||
[title]="strings['boards_editTaskLimit']"
|
||||
(click)="beginLimitEdit()"></i>
|
||||
|
||||
<div class="limit-editor" *ngIf="showLimitEditor">
|
||||
<input type="number" min="0" [(ngModel)]="columnData.task_limit">
|
||||
<input type="number" min="0"
|
||||
[title]="'0 = ' + strings['boards_noLimit']"
|
||||
[(ngModel)]="taskLimit">
|
||||
<i class="icon icon-cancel right"
|
||||
[title]="strings['boards_limitCancel']"
|
||||
(click)="cancelLimitChanges()"></i>
|
||||
<i class="icon icon-floppy primary right"
|
||||
[title]="strings['boards_limitSave']"
|
||||
(click)="saveLimitChanges()"></i>
|
||||
</div>
|
||||
</span>
|
||||
</h3>
|
||||
|
||||
<div class="quick-add">
|
||||
<input type="text" placeholder="Quick Add Task - Title Only"
|
||||
[(ngModel)]="quickAdd.title">
|
||||
<button class="flat" (click)="quickAddClicked()">
|
||||
<input type="text" [placeholder]="strings['boards_quickAdd']"
|
||||
[(ngModel)]="quickAdd.title" (keyup.enter)="quickAddClicked($event)">
|
||||
<button class="flat"
|
||||
[title] = "strings['boards_addTask']"
|
||||
(click)="quickAddClicked($event)">
|
||||
<i class="icon icon-plus"></i>
|
||||
</button>
|
||||
</div>
|
||||
@ -52,36 +67,44 @@
|
||||
|
||||
<tb-context-menu [menu-items]="contextMenuItems"></tb-context-menu>
|
||||
|
||||
<tb-modal modal-title="Confirm Task Removal" blocking="true"
|
||||
<tb-modal modal-title="{{ strings['boards_confirmRemoveTask'] }}" blocking="true"
|
||||
modal-id="{{ MODAL_CONFIRM_ID + columnData.id }}">
|
||||
<div class="center">Removing a task cannot be undone.<br>Continue?</div>
|
||||
<div class="center">
|
||||
{{ strings['boards_confirmWarning'] }}<br>
|
||||
{{ strings['boards_confirmContinue'] }}
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="flat"
|
||||
(click)="removeTask()">Yes</button>
|
||||
(click)="removeTask()">{{ strings['yes'] }}</button>
|
||||
<button #defaultAction #focusMe
|
||||
(click)="modal.close(MODAL_CONFIRM_ID + columnData.id)">No</button>
|
||||
(click)="modal.close(MODAL_CONFIRM_ID + columnData.id)">
|
||||
{{ strings['no'] }}
|
||||
</button>
|
||||
</div>
|
||||
</tb-modal>
|
||||
|
||||
<tb-modal *ngIf="activeBoard"
|
||||
modal-title="{{ modalProps.id === 0 ? 'Add' : 'Edit' }} Task"
|
||||
modal-title="{{ modalProps.id === 0
|
||||
? strings['boards_addTask']
|
||||
: strings['boards_editTask'] }}"
|
||||
modal-id="{{ MODAL_ID + columnData.id }}">
|
||||
<label>
|
||||
Title
|
||||
<input #focusMe type="text" name="title" placeholder="Task Title"
|
||||
[(ngModel)]="modalProps.title">
|
||||
{{ strings['boards_taskTitle'] }}
|
||||
<input #focusMe type="text" name="title"
|
||||
[placeholder]="strings['boards_taskTitlePlaceholder']"
|
||||
[(ngModel)]="modalProps.title">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Description
|
||||
{{ strings['boards_taskDescription'] }}
|
||||
<textarea name="description" rows="5"
|
||||
placeholder="What needs to get done?"
|
||||
[placeholder]="strings['boards_taskDescriptionPlaceholder']"
|
||||
(keyup.enter)="preventEnter($event)"
|
||||
[(ngModel)]="modalProps.description"></textarea>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Assignees
|
||||
{{ strings['boards_taskAssignees'] }}
|
||||
<select name="assignees" multiple [(ngModel)]="modalProps.assignees">
|
||||
<option *ngFor="let user of activeBoard.users"
|
||||
[ngValue]="user">{{ user.username }}</option>
|
||||
@ -89,7 +112,7 @@
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Categories
|
||||
{{ strings['boards_taskCategories'] }}
|
||||
<select name="categories" multiple [ngModel]="modalProps.categories"
|
||||
(ngModelChange)="updateTaskColorByCategory($event)">
|
||||
<option *ngFor="let category of activeBoard.categories"
|
||||
@ -99,7 +122,7 @@
|
||||
|
||||
<div class="half">
|
||||
<label>
|
||||
Column
|
||||
{{ strings['boards_taskColumn'] }}
|
||||
<select name="column" [(ngModel)]="modalProps.column_id">
|
||||
<option *ngFor="let column of activeBoard.columns"
|
||||
[ngValue]="column.id">{{ column.name }}</option>
|
||||
@ -107,19 +130,19 @@
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Color
|
||||
{{ strings['boards_taskColor'] }}
|
||||
<input type="color" [(ngModel)]="modalProps.color">
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="half">
|
||||
<label>
|
||||
Date Due
|
||||
{{ strings['boards_taskDateDue'] }}
|
||||
<input type="date" [(ngModel)]="modalProps.due_date">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
Points
|
||||
{{ strings['boards_taskPoints'] }}
|
||||
<input type="number" [(ngModel)]="modalProps.points">
|
||||
</label>
|
||||
</div>
|
||||
@ -128,15 +151,15 @@
|
||||
<button #defaultAction *ngIf="modalProps.id === 0"
|
||||
(click)="addTask()" [disabled]="saving">
|
||||
<i class="icon icon-plus"></i>
|
||||
Add Task
|
||||
{{ strings['boards_addTask'] }}
|
||||
</button>
|
||||
<button #defaultAction *ngIf="modalProps.id !== 0"
|
||||
(click)="updateTask()" [disabled]="saving">
|
||||
<i class="icon icon-floppy"></i>
|
||||
Save Task
|
||||
{{ strings['boards_saveTask'] }}
|
||||
</button>
|
||||
<button class="flat" (click)="modal.close(MODAL_ID + columnData.id)">
|
||||
Cancel
|
||||
{{ strings['cancel'] }}
|
||||
</button>
|
||||
</div>
|
||||
</tb-modal>
|
||||
|
@ -29,10 +29,11 @@ import { BoardService } from '../board.service';
|
||||
templateUrl: 'app/board/column/column.component.html'
|
||||
})
|
||||
export class ColumnDisplay implements OnInit {
|
||||
private strings: any;
|
||||
private templateElement: any;
|
||||
private collapseTasks: boolean;
|
||||
private saving: boolean;
|
||||
private hasTaskLimit: boolean;
|
||||
private showLimitEditor: boolean;
|
||||
|
||||
private activeUser: User;
|
||||
private activeBoard: Board;
|
||||
@ -47,6 +48,7 @@ export class ColumnDisplay implements OnInit {
|
||||
private quickAdd: Task;
|
||||
private modalProps: Task;
|
||||
private taskToRemove: number;
|
||||
private taskLimit: number;
|
||||
|
||||
@Input('column') columnData: Column;
|
||||
@Input('boards') boards: Array<Board>;
|
||||
@ -61,17 +63,21 @@ export class ColumnDisplay implements OnInit {
|
||||
this.tasks = [];
|
||||
this.collapseTasks = false;
|
||||
|
||||
this.contextMenuItems = [
|
||||
new ContextMenuItem('Add Task',
|
||||
this.getShowModalFunction())
|
||||
];
|
||||
|
||||
this.MODAL_ID = 'add-task-form-';
|
||||
this.MODAL_CONFIRM_ID = 'task-remove-confirm';
|
||||
|
||||
this.quickAdd = new Task();
|
||||
this.modalProps = new Task();
|
||||
|
||||
stringsService.stringsChanged.subscribe(newStrings => {
|
||||
this.strings = newStrings;
|
||||
|
||||
this.contextMenuItems = [
|
||||
new ContextMenuItem(this.strings.boards_addTask,
|
||||
this.getShowModalFunction())
|
||||
];
|
||||
});
|
||||
|
||||
boardService.activeBoardChanged.subscribe((board: Board) => {
|
||||
this.activeBoard = board;
|
||||
});
|
||||
@ -108,6 +114,8 @@ export class ColumnDisplay implements OnInit {
|
||||
if (isCollapsed) {
|
||||
this.templateElement.classList.add('collapsed');
|
||||
}
|
||||
|
||||
this.taskLimit = this.columnData.task_limit;
|
||||
}
|
||||
|
||||
toggleCollapsed() {
|
||||
@ -169,6 +177,8 @@ export class ColumnDisplay implements OnInit {
|
||||
|
||||
this.boardService.updateActiveBoard(response.data[2][0]);
|
||||
this.modal.close(this.MODAL_ID + this.columnData.id);
|
||||
|
||||
this.boardService.refreshToken();
|
||||
});
|
||||
}
|
||||
|
||||
@ -185,6 +195,41 @@ export class ColumnDisplay implements OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
beginLimitEdit() {
|
||||
this.taskLimit = this.columnData.task_limit;
|
||||
this.showLimitEditor = true;
|
||||
}
|
||||
|
||||
cancelLimitChanges() {
|
||||
this.showLimitEditor = false;
|
||||
}
|
||||
|
||||
saveLimitChanges() {
|
||||
let originalLimit = this.columnData.task_limit;
|
||||
|
||||
this.columnData.task_limit = this.taskLimit;
|
||||
|
||||
this.boardService.updateColumn(this.columnData)
|
||||
.subscribe((response: ApiResponse) => {
|
||||
response.alerts.forEach(note => this.notes.add(note));
|
||||
|
||||
if (response.status !== 'success') {
|
||||
this.columnData.task_limit = originalLimit;
|
||||
return;
|
||||
}
|
||||
|
||||
let colData = response.data[1][0];
|
||||
this.columnData = new Column(colData.id,
|
||||
colData.name,
|
||||
colData.position,
|
||||
colData.board_id,
|
||||
colData.task_limit,
|
||||
colData.ownTask);
|
||||
});
|
||||
|
||||
this.showLimitEditor = false;
|
||||
}
|
||||
|
||||
private validateTask(task: Task) {
|
||||
if (task.title === '') {
|
||||
this.notes.add(
|
||||
@ -206,7 +251,9 @@ export class ColumnDisplay implements OnInit {
|
||||
return () => { this.showModal(taskId); };
|
||||
}
|
||||
|
||||
private quickAddClicked() {
|
||||
private quickAddClicked(event: any) {
|
||||
this.preventEnter(event);
|
||||
|
||||
if (this.quickAdd.title === '') {
|
||||
this.showModal();
|
||||
return;
|
||||
|
@ -6,10 +6,13 @@
|
||||
[style.color]="getTextColor(taskData.color)"
|
||||
[ngClass]="{ 'icon-minus-squared-alt': !isCollapsed,
|
||||
'icon-plus-squared-alt': isCollapsed }"
|
||||
title="{{ isCollapsed ? 'Expand' : 'Collapse' }} Task"
|
||||
[title]="isCollapsed
|
||||
? strings['boards_expandTask']
|
||||
: strings['boards_collapseTask']"
|
||||
(click)="isCollapsed = !isCollapsed"></span>
|
||||
{{ taskData.title }}
|
||||
<span *ngIf="taskData.points > 0" class="badge right" title="Points">
|
||||
<span *ngIf="taskData.points > 0" class="badge right"
|
||||
[title]="strings['boards_taskPoints'] ">
|
||||
{{ taskData.points }}</span>
|
||||
</h4>
|
||||
|
||||
@ -18,25 +21,27 @@
|
||||
|
||||
<div class="stats">
|
||||
<span *ngIf="userOptions.show_assignee">
|
||||
Assigned To:
|
||||
{{ strings['boards_taskAssignedTo'] }}:
|
||||
<span *ngFor="let assignee of taskData.assignees">
|
||||
{{ assignee.username }}
|
||||
</span>
|
||||
<span *ngIf="!taskData.assignees || !taskData.assignees.length">
|
||||
Unassigned
|
||||
{{ strings['boards_taskUnassigned'] }}
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<span class="right">
|
||||
<span *ngIf="taskData.due_date">
|
||||
Due: {{ taskData.due_date }}
|
||||
{{ strings['boards_taskDue'] }}: {{ taskData.due_date }}
|
||||
</span>
|
||||
<span *ngIf="taskData.comments.length" class="icon icon-chat-empty"
|
||||
title="{{ taskData.comments.length }} Comments"></span>
|
||||
[title]="taskData.comments.length +
|
||||
strings['boards_taskComments']"></span>
|
||||
<span *ngIf="taskData.attachments.length" class="icon icon-attach"
|
||||
title="{{ taskData.attachments.length }} Attachments"></span>
|
||||
<span *ngFor="let category of taskData.categories"
|
||||
class="category" title="Category">
|
||||
[title]="taskData.attachments.length +
|
||||
strings['boards_taskAttachments']"></span>
|
||||
<span *ngFor="let category of taskData.categories" class="category"
|
||||
[title]="strings['boards_taskCategory']">
|
||||
{{ category.name }}
|
||||
</span>
|
||||
</span>
|
||||
|
@ -19,7 +19,8 @@ import {
|
||||
UserOptions,
|
||||
AuthService,
|
||||
ModalService,
|
||||
NotificationsService
|
||||
NotificationsService,
|
||||
StringsService
|
||||
} from '../../shared/index';
|
||||
import { BoardService } from '../board.service';
|
||||
|
||||
@ -28,6 +29,7 @@ import { BoardService } from '../board.service';
|
||||
templateUrl: 'app/board/task/task.component.html'
|
||||
})
|
||||
export class TaskDisplay implements OnInit {
|
||||
private strings: any;
|
||||
private userOptions: UserOptions;
|
||||
private contextMenuItems: Array<ContextMenuItem>;
|
||||
private selectMenuItem: ContextMenuItem;
|
||||
@ -55,12 +57,21 @@ export class TaskDisplay implements OnInit {
|
||||
private sanitizer: DomSanitizer,
|
||||
private boardService: BoardService,
|
||||
private modal: ModalService,
|
||||
private notes: NotificationsService) {
|
||||
private notes: NotificationsService,
|
||||
private stringsService: StringsService) {
|
||||
this.totalTasks = 0;
|
||||
this.completeTasks = 0;
|
||||
this.percentComplete = 0;
|
||||
this.contextMenuItems = [];
|
||||
|
||||
stringsService.stringsChanged.subscribe(newStrings => {
|
||||
this.strings = newStrings;
|
||||
|
||||
if (this.taskData) {
|
||||
this.generateContextMenuItems();
|
||||
}
|
||||
});
|
||||
|
||||
auth.userChanged.subscribe(() => {
|
||||
this.userOptions = auth.userOptions;
|
||||
});
|
||||
@ -98,7 +109,9 @@ export class TaskDisplay implements OnInit {
|
||||
}
|
||||
|
||||
getPercentTitle() {
|
||||
return 'Task ' + (this.percentComplete * 100) + '% Complete';
|
||||
return this.strings.boards_task + ' ' +
|
||||
(this.percentComplete * 100).toFixed(0) + '% ' +
|
||||
this.strings.boards_taskComplete;
|
||||
}
|
||||
|
||||
// Expects a color in full HEX with leading #, e.g. #ffffe0
|
||||
@ -112,7 +125,8 @@ export class TaskDisplay implements OnInit {
|
||||
}
|
||||
|
||||
private getMoveMenuItem() {
|
||||
let menuText = 'Move to Column: <select id="columnsList' + this.taskData.id + '">';
|
||||
let menuText = this.strings.boards_moveTask +
|
||||
': <select id="columnsList' + this.taskData.id + '">';
|
||||
|
||||
this.activeBoard.columns.forEach((column: Column) => {
|
||||
menuText += '<option value="' + column.id + '">' + column.name + '</option>';
|
||||
@ -161,29 +175,28 @@ export class TaskDisplay implements OnInit {
|
||||
|
||||
private generateContextMenuItems() {
|
||||
this.contextMenuItems = [
|
||||
new ContextMenuItem('View Task'),
|
||||
new ContextMenuItem('Edit Task', this.editTask),
|
||||
new ContextMenuItem('Remove Task', this.removeTask),
|
||||
new ContextMenuItem(this.strings.boards_viewTask),
|
||||
new ContextMenuItem(this.strings.boards_editTask, this.editTask),
|
||||
new ContextMenuItem(this.strings.boards_removeTask, this.removeTask),
|
||||
new ContextMenuItem('', null, true),
|
||||
this.getMoveMenuItem(),
|
||||
new ContextMenuItem('', null, true),
|
||||
new ContextMenuItem('Add Task', this.addTask)
|
||||
new ContextMenuItem(this.strings.boards_addTask, this.addTask)
|
||||
];
|
||||
|
||||
if (this.boardsList.length > 1) {
|
||||
this.contextMenuItems
|
||||
.splice(3, 0,
|
||||
new ContextMenuItem('', null, true),
|
||||
this.getMenuItem('Copy'),
|
||||
this.getMenuItem('Move'));
|
||||
this.getMenuItem(this.strings.boards_copyTaskTo),
|
||||
this.getMenuItem(this.strings.boards_moveTaskTo));
|
||||
}
|
||||
}
|
||||
|
||||
private getMenuItem(text: string): ContextMenuItem {
|
||||
let menuText = text + ' to Board: ' +
|
||||
let menuText = text + ': ' +
|
||||
'<i class="icon icon-help-circled" ' +
|
||||
'data-help="The task will be placed in the first ' +
|
||||
'column of the selected board."></i> ' +
|
||||
'data-help="' + this.strings.boards_copyMoveHelp + '"></i> ' +
|
||||
'<select id="boardsList' + text + '">';
|
||||
|
||||
this.boardsList.forEach((board: Board) => {
|
||||
|
@ -128,6 +128,64 @@
|
||||
"settings_selectAssignee": "Select Assignee",
|
||||
"settings_alterByPoints": "Alter color by points",
|
||||
"settings_noActions": "There are no automatic actions. Contact an admin user to create one.",
|
||||
"settings_noActionsAdmin": "There are no automatic actions. Use the <strong>Add Action</strong> form below to add one."
|
||||
"settings_noActionsAdmin": "There are no automatic actions. Use the <strong>Add Action</strong> form below to add one.",
|
||||
|
||||
"boards_selectBoard": "Select Board",
|
||||
"boards_hideFiltered": "Hide filtered items",
|
||||
"boards_userFilter": "User Filter",
|
||||
"boards_categoryFilter": "Category Filter",
|
||||
"boards_noBoards": "No Boards",
|
||||
"boards_noBoardsMessageUser": "You are not assigned to any boards. Contact an admin user to be added to a board.",
|
||||
"boards_noBoardsMessageAdmin": "Go to Settings to create a board.",
|
||||
"boards_noDefault": "No Default Board",
|
||||
"boards_noDefaultMessage": "You have not selected a default board. You may select a default board in your",
|
||||
"boards_noDefaultMessage2": "Until then, select a board from the list above.",
|
||||
|
||||
"boards_collapseAllTasks": "Collapse All Tasks",
|
||||
"boards_expandAllTasks": "Expand All Tasks",
|
||||
"boards_tasksInColumn": "Tasks in Column",
|
||||
"boards_expandColumn": "Expand Column",
|
||||
"boards_collapseColumn": "Collapse Column",
|
||||
"boards_editTaskLimit": "Edit Task Limit",
|
||||
"boards_noLimit": "no limit",
|
||||
"boards_limitCancel": "Cancel Changes",
|
||||
"boards_limitSave": "Save Changes",
|
||||
"boards_quickAdd": "Quick Add Task - Title Only",
|
||||
"boards_confirmRemoveTask": "Confirm Task Removal",
|
||||
"boards_confirmWarning": "Removing a task cannot be undone.",
|
||||
"boards_confirmContinue": "Continue?",
|
||||
|
||||
"boards_addTask": "Add Task",
|
||||
"boards_editTask": "Edit Task",
|
||||
"boards_viewTask": "View Task",
|
||||
"boards_removeTask": "Remove Task",
|
||||
"boards_moveTask": "Move to Column",
|
||||
|
||||
"boards_taskTitle": "Title",
|
||||
"boards_taskTitlePlaceholder": "Task Title",
|
||||
"boards_taskDescription": "Description",
|
||||
"boards_taskDescriptionPlaceholder": "What needs to get done?",
|
||||
"boards_taskAssignees": "Assignees",
|
||||
"boards_taskCategories": "Categories",
|
||||
"boards_taskColumn": "Column",
|
||||
"boards_taskColor": "Color",
|
||||
"boards_taskDateDue": "Date Due",
|
||||
"boards_taskPoints": "Points",
|
||||
"boards_saveTask": "Save Task",
|
||||
|
||||
"boards_copyTaskTo": "Copy to Board",
|
||||
"boards_moveTaskTo": "Move to Board",
|
||||
"boards_copyMoveHelp": "The task will be placed in the first column of the selected board.",
|
||||
"boards_expandTask": "Expand Task",
|
||||
"boards_collapseTask": "Collapse Task",
|
||||
"boards_taskAssignedTo": "Assigned To",
|
||||
"boards_taskUnassigned": "Unassigned",
|
||||
"boards_taskDue": "Due",
|
||||
"boards_taskComments": "Comments",
|
||||
"boards_taskAttachments": "Attachments",
|
||||
"boards_taskCategory": "Category",
|
||||
|
||||
"boards_task": "Task",
|
||||
"boards_taskComplete": "Complete"
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
"dashboard": "Salpicadero",
|
||||
"boards": "Tableros",
|
||||
"settings": "Ajustes",
|
||||
"settings": "Configuración",
|
||||
"logout": "Cerrar Sesión",
|
||||
|
||||
"settings_userSettings": "Mi Configuración",
|
||||
@ -128,6 +128,64 @@
|
||||
"settings_selectAssignee": "Seleccionar Cesionario",
|
||||
"settings_alterByPoints": "Alterar color por puntos",
|
||||
"settings_noActions": "No hay acciones automáticas. Póngase en contacto con un usuario administrador para crear uno.",
|
||||
"settings_noActionsAdmin": "No hay acciones automáticas. Utilice el botón <strong>Agregar Acción</strong> de abajo para agregar uno."
|
||||
"settings_noActionsAdmin": "No hay acciones automáticas. Utilice el botón <strong>Agregar Acción</strong> de abajo para agregar uno.",
|
||||
|
||||
"boards_selectBoard": "Seleccionar el Tablero",
|
||||
"boards_hideFiltered": "Ocultar los elementos filtrados",
|
||||
"boards_userFilter": "Filtro de usuario",
|
||||
"boards_categoryFilter": "Filtro de categoría",
|
||||
"boards_noBoards": "No Hay Tableros",
|
||||
"boards_noBoardsMessageUser": "Usted no está asignado a ninguno tablero. Póngase en contacto con un usuario administrador que se añade a un tablero.",
|
||||
"boards_noBoardsMessageAdmin": "Vaya a Configuración para crear un tablero.",
|
||||
"boards_noDefault": "Ningún Tablero Predeterminado",
|
||||
"boards_noDefaultMessage": "No ha seleccionado una tarjeta predeterminada. Puede seleccionar una tarjeta predeterminada en su",
|
||||
"boards_noDefaultMessage2": "Hasta entonces, seleccione un tablero de la lista anterior.",
|
||||
|
||||
"boards_collapseAllTasks": "Contraer Todas las Tareas",
|
||||
"boards_expandAllTasks": "Expandir Todas las Tareas",
|
||||
"boards_tasksInColumn": "Tareas en la Columna",
|
||||
"boards_expandColumn": "Expandir Columna",
|
||||
"boards_collapseColumn": "Contraer Columna",
|
||||
"boards_editTaskLimit": "Editar Límite de Tareas",
|
||||
"boards_noLimit": "sin límite",
|
||||
"boards_limitCancel": "Cancelar Cambios",
|
||||
"boards_limitSave": "Guardar Cambios",
|
||||
"boards_quickAdd": "Tarea de Añadir Rápido - Sólo Título",
|
||||
"boards_confirmRemoveTask": "Confirmar la Eliminación de Tarea",
|
||||
"boards_confirmWarning": "No se puede deshacer la eliminación de una tarea.",
|
||||
"boards_confirmContinue": "¿Continuar?",
|
||||
|
||||
"boards_addTask": "Agregar Tarea",
|
||||
"boards_editTask": "Editar Tarea",
|
||||
"boards_viewTask": "Ver Tarea",
|
||||
"boards_removeTask": "Eliminar tarea",
|
||||
"boards_moveTask": "Mover a la Columna",
|
||||
|
||||
"boards_taskTitle": "Título",
|
||||
"boards_taskTitlePlaceholder": "Tarea Título",
|
||||
"boards_taskDescription": "Descripción",
|
||||
"boards_taskDescriptionPlaceholder": "¿Qué se necesita hacer?",
|
||||
"boards_taskAssignees": "Cesionarios",
|
||||
"boards_taskCategories": "Categorías",
|
||||
"boards_taskColumn": "Columna",
|
||||
"boards_taskColor": "Color",
|
||||
"boards_taskDateDue": "Fecha de Vencimiento",
|
||||
"boards_taskPoints": "Puntos",
|
||||
"boards_saveTask": "Guardar Tarea",
|
||||
|
||||
"boards_copyTaskTo": "Copiar a el Tablero",
|
||||
"boards_moveTaskTo": "Mover a el Tablero",
|
||||
"boards_copyMoveHelp": "La tarea se colocará en la primera columna de la tabla seleccionada.",
|
||||
"boards_expandTask": "Expandir Tarea",
|
||||
"boards_collapseTask": "Contraer Tarea",
|
||||
"boards_taskAssignedTo": "Asignado a",
|
||||
"boards_taskUnassigned": "Sin asignar",
|
||||
"boards_taskDue": "Debido",
|
||||
"boards_taskComments": "Comentarios",
|
||||
"boards_taskAttachments": "Archivos Adjuntos",
|
||||
"boards_taskCategory": "Categoría",
|
||||
|
||||
"boards_task": "Tarea",
|
||||
"boards_taskComplete": "Completar"
|
||||
}
|
||||
|
||||
|
@ -52,6 +52,26 @@
|
||||
font-size: 24px;
|
||||
padding: 5px;
|
||||
|
||||
&.near-limit {
|
||||
box-shadow: 0 2px 2px 0 rgba(255, 150, 0, .4),
|
||||
0 1px 5px 0 rgba(255, 150, 0, .2),
|
||||
0 3px 1px -2px rgba(255, 150, 0, .2);
|
||||
|
||||
.count {
|
||||
color: rgb(255, 150, 0);
|
||||
}
|
||||
}
|
||||
|
||||
&.limit-reached {
|
||||
box-shadow: 0 2px 2px 0 rgba(255, 20, 0, .4),
|
||||
0 1px 5px 0 rgba(255, 20, 0, .2),
|
||||
0 3px 1px -2px rgba(255, 20, 0, .2);
|
||||
|
||||
.count {
|
||||
color: rgb(255, 20, 0);
|
||||
}
|
||||
}
|
||||
|
||||
span {
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -66,6 +86,28 @@
|
||||
margin-top: -4px;
|
||||
}
|
||||
|
||||
.limit-editor {
|
||||
@include shadow-float;
|
||||
|
||||
background-color: $white;
|
||||
border-radius: 3px;
|
||||
padding: 1em;
|
||||
position: absolute;
|
||||
right: 1.5em;
|
||||
width: 70px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.icon-cancel,
|
||||
.icon-floppy {
|
||||
margin: 5px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.icon-cancel {
|
||||
color: $color-text;
|
||||
}
|
||||
|
||||
.icon-angle-double-up,
|
||||
.badge {
|
||||
display: none;
|
||||
@ -121,7 +163,6 @@
|
||||
.icon-minus-squared-alt,
|
||||
.icon-plus-squared-alt,
|
||||
.tasks,
|
||||
.count,
|
||||
.quick-add {
|
||||
display: none;
|
||||
}
|
||||
|
Reference in New Issue
Block a user