More for attachments, and cleanup
This commit is contained in:
parent
fbddac7302
commit
babbf81610
@ -8,18 +8,21 @@
|
||||
<option [ngValue]="null">
|
||||
{{ strings['boards_selectBoard'] }}...
|
||||
</option>
|
||||
|
||||
<option *ngFor="let board of boards"
|
||||
[ngValue]="board.id">
|
||||
{{ board.name }}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<div class="right" *ngIf="activeBoard">
|
||||
<label>
|
||||
{{ strings['boards_hideFiltered'] }}:
|
||||
<input type="checkbox" [(ngModel)]="hideFiltered"
|
||||
(change)="toggleFiltered()">
|
||||
</label>
|
||||
|
||||
<label>
|
||||
{{ strings['boards_userFilter'] }}:
|
||||
<select [(ngModel)]="userFilter"
|
||||
@ -27,15 +30,18 @@
|
||||
<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 }}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
<label>
|
||||
{{ strings['boards_categoryFilter'] }}:
|
||||
<select [(ngModel)]="categoryFilter"
|
||||
@ -43,15 +49,18 @@
|
||||
<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 }}
|
||||
</option>
|
||||
</select>
|
||||
</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -62,7 +71,8 @@
|
||||
</div>
|
||||
|
||||
<div class="no-boards center"
|
||||
*ngIf="!loading && !activeBoard && this.boards.length > 0 && !activeUser.default_board_id">
|
||||
*ngIf="!loading && !activeBoard && this.boards.length > 0 &&
|
||||
!activeUser.default_board_id">
|
||||
<h1>{{ strings['boards_noDefault'] }}</h1>
|
||||
|
||||
<p>{{ strings['boards_noDefaultMessage'] }}
|
||||
@ -70,6 +80,7 @@
|
||||
{{ strings['settings'] }}
|
||||
</a>.
|
||||
</p>
|
||||
|
||||
<p></p>
|
||||
</div>
|
||||
|
||||
|
@ -25,7 +25,7 @@ export class BoardDisplayComponent implements OnInit, OnDestroy {
|
||||
|
||||
public categoryFilter: number;
|
||||
public userFilter: number;
|
||||
public boardNavId: number;
|
||||
public boardNavId: number | null;
|
||||
|
||||
public activeUser: User;
|
||||
public activeBoard: Board;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
|
||||
import * as marked from 'marked';
|
||||
import * as hljs from 'highlight.js';
|
||||
@ -59,7 +59,7 @@ export class BoardService {
|
||||
return this.http.get('api/boards')
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
);
|
||||
}
|
||||
|
||||
@ -67,7 +67,7 @@ export class BoardService {
|
||||
return this.http.post('api/users/' + userId + '/cols', { id: columnId })
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
);
|
||||
}
|
||||
|
||||
@ -75,7 +75,7 @@ export class BoardService {
|
||||
return this.http.post('api/boards/' + board.id, board)
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
);
|
||||
}
|
||||
|
||||
@ -83,7 +83,7 @@ export class BoardService {
|
||||
return this.http.post('api/columns/' + column.id, column)
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
);
|
||||
}
|
||||
|
||||
@ -91,7 +91,7 @@ export class BoardService {
|
||||
return this.http.post('api/tasks', task)
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
);
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ export class BoardService {
|
||||
return this.http.post('api/tasks/' + task.id, task)
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
);
|
||||
}
|
||||
|
||||
@ -107,7 +107,7 @@ export class BoardService {
|
||||
return this.http.delete('api/tasks/' + taskId)
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
);
|
||||
}
|
||||
|
||||
@ -115,7 +115,7 @@ export class BoardService {
|
||||
return this.http.get('api/activity/task/' + taskId)
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
);
|
||||
}
|
||||
|
||||
@ -123,7 +123,7 @@ export class BoardService {
|
||||
return this.http.post('api/comments/' + comment.id, comment)
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
);
|
||||
}
|
||||
|
||||
@ -131,35 +131,31 @@ export class BoardService {
|
||||
return this.http.delete('api/comments/' + commentId)
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
);
|
||||
}
|
||||
|
||||
/* istanbul ignore next */
|
||||
uploadAttachment(attachment: Attachment, data: FormData): Observable<ApiResponse> {
|
||||
const headers = new HttpHeaders();
|
||||
const options = { headers, params: new HttpParams() };
|
||||
options.params.set('attachment', JSON.stringify(attachment));
|
||||
|
||||
return this.http.post('api/attachments', data, options)
|
||||
uploadAttachment(attachment: Attachment): Observable<ApiResponse> {
|
||||
return this.http.post('api/attachments', attachment)
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
);
|
||||
}
|
||||
|
||||
removeAttachment(id: number): Observable<ApiResponse> {
|
||||
return this.http.delete('api/attachments/' + id)
|
||||
.pipe(
|
||||
map((response: ApiResponse) => response),
|
||||
catchError((err) => of(err.error as ApiResponse))
|
||||
)
|
||||
}
|
||||
|
||||
refreshToken(): void {
|
||||
this.http.post('api/refresh', {}).subscribe();
|
||||
}
|
||||
|
||||
private defaultCallback = (err: any, text: string) => {
|
||||
if (err) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private convertBoardData(boardData: any): Board {
|
||||
if (boardData instanceof Board) {
|
||||
return boardData;
|
||||
@ -174,6 +170,14 @@ export class BoardService {
|
||||
boardData.sharedUser);
|
||||
}
|
||||
|
||||
private defaultCallback = (err: any, text: string) => {
|
||||
if (err) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
private initMarked(): void {
|
||||
const renderer = new marked.Renderer();
|
||||
|
||||
|
@ -155,6 +155,31 @@
|
||||
|
||||
<div *ngIf="viewModalProps.attachments.length">
|
||||
<h3>{{ strings['boards_taskAttachments'] }}</h3>
|
||||
<div class="list-group">
|
||||
<div class="list-group-item" *ngFor="let item of viewModalProps.attachments">
|
||||
{{ item.filename }}
|
||||
<div class="detail small">
|
||||
{{ strings['boards_taskUploadedBy'] }}: {{ userName(item.user_id) }}
|
||||
{{ strings['boards_taskUploadedOn'] }} {{ item.timestamp * 1000 | date:'full' }}
|
||||
</div>
|
||||
|
||||
<div class="pull-right">
|
||||
<i class="icon icon-eye"
|
||||
[title]="strings['boards_taskView'] + ' ' + item.filename"
|
||||
(click)="viewFile(item.diskfilename)"></i>
|
||||
|
||||
<i class="icon icon-download"
|
||||
[title]="strings['boards_taskDownload'] + ' ' + item.filename"
|
||||
></i>
|
||||
|
||||
<i class="icon icon-trash-empty"
|
||||
[title]="strings['settings_remove'] + ' ' + item.filename"
|
||||
(click)="attachmentToRemove = item;
|
||||
modal.open(MODAL_CONFIRM_ATTACHMENT_ID +
|
||||
(columnData ? columnData.id : ''))"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@ -344,6 +369,25 @@
|
||||
</div>
|
||||
</tb-modal>
|
||||
|
||||
<tb-modal modal-title="{{ strings['boards_confirmRemoveAttachment'] }}" blocking="true"
|
||||
modal-id="{{ MODAL_CONFIRM_ATTACHMENT_ID + (columnData ? columnData.id : '') }}">
|
||||
<div class="center">
|
||||
{{ strings['boards_confirmWarningAttachment'] }}<br>
|
||||
{{ strings['boards_confirmContinue'] }}
|
||||
</div>
|
||||
<div class="buttons">
|
||||
<button class="flat"
|
||||
(click)="modal.close(MODAL_CONFIRM_ATTACHMENT_ID
|
||||
+ (columnData ? columnData.id : '')); removeAttachment()">
|
||||
{{ strings['yes'] }}
|
||||
</button>
|
||||
<button #defaultAction #focusMe
|
||||
(click)="modal.close(MODAL_CONFIRM_ATTACHMENT_ID + (columnData ? columnData.id : ''))">
|
||||
{{ strings['no'] }}
|
||||
</button>
|
||||
</div>
|
||||
</tb-modal>
|
||||
|
||||
<tb-modal modal-title="{{ strings['boards_confirmRemoveComment'] }}" blocking="true"
|
||||
modal-id="{{ MODAL_CONFIRM_COMMENT_ID + (columnData ? columnData.id : '') }}">
|
||||
<div class="center">
|
||||
|
@ -65,6 +65,7 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
||||
|
||||
public commentEdit: Comment;
|
||||
public commentToRemove: Comment;
|
||||
public attachmentToRemove: Attachment;
|
||||
public viewModalProps: Task;
|
||||
public modalProps: Task;
|
||||
public userOptions: UserOptions;
|
||||
@ -75,6 +76,7 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
||||
public MODAL_ID: string;
|
||||
public MODAL_VIEW_ID: string;
|
||||
public MODAL_CONFIRM_ID: string;
|
||||
public MODAL_CONFIRM_ATTACHMENT_ID: string;
|
||||
public MODAL_CONFIRM_COMMENT_ID: string;
|
||||
|
||||
// tslint:disable-next-line
|
||||
@ -100,6 +102,7 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
||||
this.MODAL_ID = 'add-task-form-';
|
||||
this.MODAL_VIEW_ID = 'view-task-form-';
|
||||
this.MODAL_CONFIRM_ID = 'task-remove-confirm';
|
||||
this.MODAL_CONFIRM_ATTACHMENT_ID = 'attachment-remove-confirm';
|
||||
this.MODAL_CONFIRM_COMMENT_ID = 'comment-remove-confirm';
|
||||
|
||||
this.quickAdd = new Task();
|
||||
@ -167,6 +170,10 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
||||
this.subs.forEach(sub => (sub.unsubscribe()));
|
||||
}
|
||||
|
||||
userName(id: number) {
|
||||
return this.activeBoard.users.find(u => u.id === id).username;
|
||||
}
|
||||
|
||||
sortTasks() {
|
||||
switch (this.sortOption) {
|
||||
case 'pos':
|
||||
@ -204,7 +211,7 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
||||
this.collapseTasks = !this.collapseTasks;
|
||||
}
|
||||
|
||||
updateTaskColorByCategory(event: Array<Category>) {
|
||||
updateTaskColorByCategory(event: Category[]) {
|
||||
this.modalProps.categories = event;
|
||||
this.modalProps.color = event[event.length - 1].default_task_color;
|
||||
}
|
||||
@ -314,22 +321,45 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', this.fileUpload);
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = () => {
|
||||
const attachment = new Attachment();
|
||||
|
||||
const attachment = new Attachment();
|
||||
attachment.filename = this.fileUpload.name;
|
||||
attachment.name = attachment.filename.split('.')[0];
|
||||
attachment.type = this.fileUpload.type;
|
||||
attachment.user_id = this.activeUser.id;
|
||||
attachment.task_id = this.viewModalProps.id;
|
||||
attachment.filename = this.fileUpload.name;
|
||||
attachment.name = attachment.filename.split('.').slice(0, -1).join('.');
|
||||
attachment.type = this.fileUpload.type;
|
||||
attachment.user_id = this.activeUser.id;
|
||||
attachment.task_id = this.viewModalProps.id;
|
||||
attachment.data = fileReader.result;
|
||||
|
||||
this.boardService.uploadAttachment(attachment, formData)
|
||||
.subscribe(response => {
|
||||
response.alerts.forEach(note => this.notes.add(note));
|
||||
this.boardService.uploadAttachment(attachment)
|
||||
.subscribe(response => {
|
||||
response.alerts.forEach(note => this.notes.add(note));
|
||||
|
||||
console.log(response);
|
||||
});
|
||||
if (response.status === 'success') {
|
||||
this.viewModalProps.attachments.push(attachment);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fileReader.readAsBinaryString(this.fileUpload);
|
||||
}
|
||||
|
||||
viewFile(hash: string) {
|
||||
window.open(`./files/${hash}`, 'tb-file-view');
|
||||
}
|
||||
|
||||
removeAttachment() {
|
||||
this.boardService.removeAttachment(this.attachmentToRemove.id).subscribe(res => {
|
||||
res.alerts.forEach(note => this.notes.add(note));
|
||||
|
||||
if (res.status === 'success') {
|
||||
const index = this.viewModalProps.attachments
|
||||
.findIndex(x => x.id === this.attachmentToRemove.id);
|
||||
|
||||
this.viewModalProps.attachments.splice(index, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
addComment() {
|
||||
@ -630,7 +660,7 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
||||
});
|
||||
}
|
||||
|
||||
private updateTaskComments(task: Task, newComments: Array<any>) {
|
||||
private updateTaskComments(task: Task, newComments: any[]) {
|
||||
task.comments = [];
|
||||
|
||||
if (!newComments) {
|
||||
|
@ -6,7 +6,6 @@ import {
|
||||
Output
|
||||
} from '@angular/core';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { CdkDragDrop, moveItemInArray, transferArrayItem } from '@angular/cdk/drag-drop';
|
||||
|
||||
import {
|
||||
ApiResponse,
|
||||
@ -143,14 +142,9 @@ export class TaskDisplayComponent implements OnInit {
|
||||
|
||||
const newBoardId = +(select[select.selectedIndex] as HTMLOptionElement).value;
|
||||
const taskData = { ...this.taskData };
|
||||
let boardData: Board;
|
||||
const boardData = this.boardsList.find(board => board.id === newBoardId);
|
||||
|
||||
this.boardsList.forEach(board => {
|
||||
if (board.id === newBoardId) {
|
||||
taskData.column_id = board.columns[0].id;
|
||||
boardData = board;
|
||||
}
|
||||
});
|
||||
taskData.column_id = boardData.columns[0].id;
|
||||
|
||||
this.boardService.addTask(taskData)
|
||||
.subscribe((response: ApiResponse) => {
|
||||
|
Reference in New Issue
Block a user