Attachments fully working
This commit is contained in:
parent
5748f762e9
commit
a109c9d0a5
@ -35,6 +35,7 @@ export const ROUTES: Routes = [
|
|||||||
{
|
{
|
||||||
path: 'files/:hash',
|
path: 'files/:hash',
|
||||||
component: FileViewerComponent,
|
component: FileViewerComponent,
|
||||||
|
canActivate: [ AuthGuard ]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -123,6 +123,14 @@ export class BoardService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addComment(comment: Comment): Observable<ApiResponse> {
|
||||||
|
return this.http.post('api/comments', comment)
|
||||||
|
.pipe(
|
||||||
|
map((response: ApiResponse) => response),
|
||||||
|
catchError((err) => of(err.error as ApiResponse))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
updateComment(comment: Comment): Observable<ApiResponse> {
|
updateComment(comment: Comment): Observable<ApiResponse> {
|
||||||
return this.http.post('api/comments/' + comment.id, comment)
|
return this.http.post('api/comments/' + comment.id, comment)
|
||||||
.pipe(
|
.pipe(
|
||||||
@ -139,8 +147,7 @@ export class BoardService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
addAttachment(attachment: Attachment): Observable<ApiResponse> {
|
||||||
uploadAttachment(attachment: Attachment): Observable<ApiResponse> {
|
|
||||||
return this.http.post('api/attachments', attachment)
|
return this.http.post('api/attachments', attachment)
|
||||||
.pipe(
|
.pipe(
|
||||||
map((response: ApiResponse) => response),
|
map((response: ApiResponse) => response),
|
||||||
@ -148,6 +155,14 @@ export class BoardService {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uploadAttachment(data: FormData, hash: string): Observable<ApiResponse> {
|
||||||
|
return this.http.post('api/upload/' + hash, data)
|
||||||
|
.pipe(
|
||||||
|
map((response: ApiResponse) => response),
|
||||||
|
catchError((err) => of(err.error as ApiResponse))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
removeAttachment(id: number): Observable<ApiResponse> {
|
removeAttachment(id: number): Observable<ApiResponse> {
|
||||||
return this.http.delete('api/attachments/' + id)
|
return this.http.delete('api/attachments/' + id)
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -178,8 +178,11 @@
|
|||||||
<i class="icon icon-eye" (click)="viewFile(item.diskfilename)"
|
<i class="icon icon-eye" (click)="viewFile(item.diskfilename)"
|
||||||
[title]="strings['boards_taskView'] + ' ' + item.filename"></i>
|
[title]="strings['boards_taskView'] + ' ' + item.filename"></i>
|
||||||
|
|
||||||
<i class="icon icon-download" [title]="strings['boards_taskDownload']
|
<a [href]="getUrl(item.diskfilename)" download="{{ item.filename }}">
|
||||||
+ ' ' + item.filename"></i>
|
<i class="icon icon-download"
|
||||||
|
[title]="strings['boards_taskDownload'] + ' ' +
|
||||||
|
item.filename"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
<i class="icon icon-trash-empty"
|
<i class="icon icon-trash-empty"
|
||||||
[title]="strings['settings_remove'] + ' ' + item.filename"
|
[title]="strings['settings_remove'] + ' ' + item.filename"
|
||||||
@ -191,12 +194,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div class="file-upload">
|
||||||
<h3>{{ strings['boards_taskAddAttachment'] }}</h3>
|
<h3>{{ strings['boards_taskAddAttachment'] }}</h3>
|
||||||
|
|
||||||
<input type="file" #fileupload (change)="fileChange(fileupload.files[0])">
|
<input type="file" class="fileuploadinput" #fileupload
|
||||||
|
(change)="fileChange(fileupload.files[0])">
|
||||||
|
|
||||||
<button (click)="uploadFile()" [disabled]="!fileupload.files[0]">
|
<button (click)="addFile()"
|
||||||
|
[disabled]="!fileupload.files[0] || fileUploading">
|
||||||
<i class="icon icon-upload"></i>
|
<i class="icon icon-upload"></i>
|
||||||
|
|
||||||
{{ strings['boards_taskUpload'] }}
|
{{ strings['boards_taskUpload'] }}
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
OnDestroy,
|
OnDestroy,
|
||||||
Output
|
Output
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { DomSanitizer, } from '@angular/platform-browser';
|
import { DomSanitizer } from '@angular/platform-browser';
|
||||||
import {
|
import {
|
||||||
CdkDragDrop,
|
CdkDragDrop,
|
||||||
moveItemInArray,
|
moveItemInArray,
|
||||||
@ -40,12 +40,15 @@ import { BoardService } from '../board.service';
|
|||||||
templateUrl: './column.component.html'
|
templateUrl: './column.component.html'
|
||||||
})
|
})
|
||||||
export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
||||||
|
public moveItemInArray: any;
|
||||||
|
public transferArrayItem: any;
|
||||||
|
public fileUpload: any;
|
||||||
|
|
||||||
private fileUpload: any;
|
|
||||||
private subs = [];
|
private subs = [];
|
||||||
|
|
||||||
public viewTaskActivities: ActivitySimple[];
|
public viewTaskActivities: ActivitySimple[];
|
||||||
|
|
||||||
|
public fileUploading: boolean;
|
||||||
public showActivity: boolean;
|
public showActivity: boolean;
|
||||||
public collapseActivity: boolean;
|
public collapseActivity: boolean;
|
||||||
public isOverdue: boolean;
|
public isOverdue: boolean;
|
||||||
@ -88,7 +91,7 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
constructor(public elRef: ElementRef,
|
constructor(public elRef: ElementRef,
|
||||||
private auth: AuthService,
|
private auth: AuthService,
|
||||||
private notes: NotificationsService,
|
public notes: NotificationsService,
|
||||||
public modal: ModalService,
|
public modal: ModalService,
|
||||||
public stringsService: StringsService,
|
public stringsService: StringsService,
|
||||||
public boardService: BoardService,
|
public boardService: BoardService,
|
||||||
@ -107,6 +110,9 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
|||||||
this.modalProps = new Task();
|
this.modalProps = new Task();
|
||||||
this.viewModalProps = new Task();
|
this.viewModalProps = new Task();
|
||||||
|
|
||||||
|
this.moveItemInArray = moveItemInArray;
|
||||||
|
this.transferArrayItem = transferArrayItem;
|
||||||
|
|
||||||
let sub = stringsService.stringsChanged.subscribe(newStrings => {
|
let sub = stringsService.stringsChanged.subscribe(newStrings => {
|
||||||
this.strings = newStrings;
|
this.strings = newStrings;
|
||||||
});
|
});
|
||||||
@ -231,9 +237,7 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.modal.close(this.MODAL_ID + (this.columnData
|
this.modal.close(this.MODAL_ID + this.columnData.id + '');
|
||||||
? this.columnData.id + ''
|
|
||||||
: ''));
|
|
||||||
|
|
||||||
const boardData = response.data[2][0];
|
const boardData = response.data[2][0];
|
||||||
boardData.ownColumn.forEach((column: any) => {
|
boardData.ownColumn.forEach((column: any) => {
|
||||||
@ -252,10 +256,10 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
|||||||
|
|
||||||
drop(event: CdkDragDrop<string[]>, colIndex: number) {
|
drop(event: CdkDragDrop<string[]>, colIndex: number) {
|
||||||
if (event.previousContainer === event.container) {
|
if (event.previousContainer === event.container) {
|
||||||
moveItemInArray(event.container.data,
|
this.moveItemInArray(event.container.data,
|
||||||
event.previousIndex, event.currentIndex);
|
event.previousIndex, event.currentIndex);
|
||||||
} else {
|
} else {
|
||||||
transferArrayItem(event.previousContainer.data,
|
this.transferArrayItem(event.previousContainer.data,
|
||||||
event.container.data, event.previousIndex, event.currentIndex);
|
event.container.data, event.previousIndex, event.currentIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,9 +290,7 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.boardService.updateActiveBoard(response.data[2][0]);
|
this.boardService.updateActiveBoard(response.data[2][0]);
|
||||||
this.modal.close(this.MODAL_ID + (this.columnData
|
this.modal.close(this.MODAL_ID + this.columnData?.id + '');
|
||||||
? this.columnData.id + ''
|
|
||||||
: ''));
|
|
||||||
|
|
||||||
this.boardService.refreshToken();
|
this.boardService.refreshToken();
|
||||||
this.saving = false;
|
this.saving = false;
|
||||||
@ -309,60 +311,63 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
|
||||||
fileChange(file: File) {
|
fileChange(file: File) {
|
||||||
this.fileUpload = file;
|
this.fileUpload = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
addFile() {
|
||||||
uploadFile() {
|
|
||||||
if (!this.fileUpload) {
|
if (!this.fileUpload) {
|
||||||
this.notes.add({ type: 'error', text: this.strings.boards_taskNoFileError });
|
this.notes
|
||||||
|
.add({ type: 'error', text: this.strings.boards_taskNoFileError });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileReader = new FileReader();
|
this.fileUploading = true;
|
||||||
fileReader.onload = () => {
|
const attachment = new Attachment();
|
||||||
const attachment = new Attachment();
|
|
||||||
|
|
||||||
attachment.filename = this.fileUpload.name;
|
attachment.filename = this.fileUpload.name;
|
||||||
attachment.name = attachment.filename.split('.').slice(0, -1).join('.');
|
attachment.name = attachment.filename.split('.').slice(0, -1).join('.');
|
||||||
attachment.type = this.fileUpload.type;
|
attachment.type = this.fileUpload.type;
|
||||||
attachment.user_id = this.activeUser.id;
|
attachment.user_id = this.activeUser.id;
|
||||||
attachment.task_id = this.viewModalProps.id;
|
attachment.task_id = this.viewModalProps.id;
|
||||||
attachment.data = fileReader.result;
|
|
||||||
|
|
||||||
this.boardService.uploadAttachment(attachment)
|
this.boardService.addAttachment(attachment).subscribe(response => {
|
||||||
.subscribe(response => {
|
if (response.status !== 'success') {
|
||||||
response.alerts.forEach(note => this.notes.add(note));
|
this.fileUploading = false;
|
||||||
|
this.resetFileInput();
|
||||||
|
|
||||||
if (response.status === 'success') {
|
return;
|
||||||
attachment.id = response.data[1].id;
|
}
|
||||||
attachment.diskfilename = response.data[1].diskfilename;
|
|
||||||
|
|
||||||
this.viewModalProps.attachments.push(attachment);
|
attachment.id = response.data[1].id;
|
||||||
}
|
attachment.diskfilename = response.data[1].diskfilename;
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
fileReader.readAsBinaryString(this.fileUpload);
|
this.uploadFile(attachment, response);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
viewFile(hash: string) {
|
viewFile(hash: string) {
|
||||||
window.open(`./files/${hash}`, 'tb-file-view');
|
window.open(`./files/${hash}`, 'tb-file-view');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getUrl(hash: string) {
|
||||||
|
const url = `./api/uploads/${hash}`;
|
||||||
|
return this.sanitizer.bypassSecurityTrustResourceUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
removeAttachment() {
|
removeAttachment() {
|
||||||
this.boardService.removeAttachment(this.attachmentToRemove.id).subscribe(res => {
|
this.boardService.removeAttachment(this.attachmentToRemove.id)
|
||||||
res.alerts.forEach(note => this.notes.add(note));
|
.subscribe(res => {
|
||||||
|
res.alerts.forEach(note => this.notes.add(note));
|
||||||
|
|
||||||
if (res.status === 'success') {
|
if (res.status === 'success') {
|
||||||
const index = this.viewModalProps.attachments
|
const index = this.viewModalProps.attachments
|
||||||
.findIndex(x => x.id === this.attachmentToRemove.id);
|
.findIndex(x => x.id === this.attachmentToRemove.id);
|
||||||
|
|
||||||
this.viewModalProps.attachments.splice(index, 1);
|
this.viewModalProps.attachments.splice(index, 1);
|
||||||
}
|
this.updateTaskActivity(this.viewModalProps.id);
|
||||||
});
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
addComment() {
|
addComment() {
|
||||||
@ -370,14 +375,15 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.viewModalProps.comments.push(
|
const comment = new Comment(0, this.newComment, this.activeUser.id,
|
||||||
new Comment(0, this.newComment, this.activeUser.id,
|
this.viewModalProps.id);
|
||||||
this.viewModalProps.id));
|
|
||||||
|
|
||||||
this.newComment = '';
|
this.newComment = '';
|
||||||
|
|
||||||
this.boardService.updateTask(this.viewModalProps)
|
this.boardService.addComment(comment)
|
||||||
.subscribe((response: ApiResponse) => {
|
.subscribe((response: ApiResponse) => {
|
||||||
|
response.alerts.forEach(note => this.notes.add(note));
|
||||||
|
|
||||||
if (response.status !== 'success') {
|
if (response.status !== 'success') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -582,7 +588,8 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getUserName(userId: number) {
|
getUserName(userId: number) {
|
||||||
const user = this.activeBoard.users.find((test: User) => test.id === +userId);
|
const user = this.activeBoard.users
|
||||||
|
.find((test: User) => test.id === +userId);
|
||||||
|
|
||||||
return user.username;
|
return user.username;
|
||||||
}
|
}
|
||||||
@ -614,6 +621,34 @@ export class ColumnDisplayComponent implements OnInit, OnDestroy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private uploadFile(attachment: Attachment, response: ApiResponse) {
|
||||||
|
const data = new FormData();
|
||||||
|
data.append('file', this.fileUpload);
|
||||||
|
|
||||||
|
this.boardService.uploadAttachment(data, attachment.diskfilename)
|
||||||
|
.subscribe(res => {
|
||||||
|
res.alerts.forEach(note => this.notes.add(note));
|
||||||
|
|
||||||
|
this.fileUploading = false;
|
||||||
|
this.resetFileInput();
|
||||||
|
|
||||||
|
if (res.status === 'success') {
|
||||||
|
response.alerts.forEach(note => this.notes.add(note));
|
||||||
|
|
||||||
|
this.viewModalProps.attachments.push(attachment);
|
||||||
|
this.updateTaskActivity(this.viewModalProps.id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private resetFileInput() {
|
||||||
|
const upload = document.getElementsByClassName('fileuploadinput');
|
||||||
|
|
||||||
|
Array.from(upload).forEach((input: any) => {
|
||||||
|
input.value = '';
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
private updateTaskActivity(id: number) {
|
private updateTaskActivity(id: number) {
|
||||||
this.viewTaskActivities = [];
|
this.viewTaskActivities = [];
|
||||||
|
|
||||||
|
@ -1 +1,17 @@
|
|||||||
<tb-top-nav page-name="{{ pageName }}"></tb-top-nav>
|
<tb-top-nav page-name="{{ pageName }}" [show-buttons]="false"></tb-top-nav>
|
||||||
|
|
||||||
|
<div class="file-viewer">
|
||||||
|
<div class="header">
|
||||||
|
{{ strings['attachment'] }}: {{ attachment?.filename }}
|
||||||
|
|
||||||
|
<span class="right">
|
||||||
|
<a [href]="fileUrl" download="{{ attachment?.filename }}">
|
||||||
|
{{strings['boards_taskDownload']}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content" *ngIf="isLoaded">
|
||||||
|
<iframe seamless [src]="fileUrl"></iframe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@ -1,42 +1,78 @@
|
|||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { Title } from '@angular/platform-browser';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import {
|
||||||
|
Title,
|
||||||
|
DomSanitizer,
|
||||||
|
SafeResourceUrl
|
||||||
|
} from '@angular/platform-browser';
|
||||||
|
|
||||||
import { StringsService, AuthService } from '../shared/services';
|
import { FileViewerService } from './file-viewer.service';
|
||||||
import { User } from '../shared/models';
|
import { User, Attachment } from '../shared/models';
|
||||||
|
import {
|
||||||
|
StringsService,
|
||||||
|
AuthService,
|
||||||
|
NotificationsService
|
||||||
|
} from '../shared/services';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-file-viewer',
|
selector: 'tb-file-viewer',
|
||||||
templateUrl: './file-viewer.component.html'
|
templateUrl: './file-viewer.component.html'
|
||||||
})
|
})
|
||||||
export class FileViewerComponent implements OnInit, OnDestroy {
|
export class FileViewerComponent implements OnInit, OnDestroy {
|
||||||
private subs: any[];
|
private subs: any[];
|
||||||
|
private fileHash: string;
|
||||||
|
|
||||||
public activeUser: User;
|
|
||||||
public pageName: string;
|
|
||||||
public strings: any;
|
public strings: any;
|
||||||
|
public pageName: string;
|
||||||
|
public isLoaded: boolean;
|
||||||
|
public fileUrl: SafeResourceUrl;
|
||||||
|
|
||||||
constructor(public title: Title,
|
public attachment: Attachment;
|
||||||
public auth: AuthService,
|
public activeUser: User;
|
||||||
public stringsService: StringsService) {
|
|
||||||
|
constructor(private title: Title,
|
||||||
|
private active: ActivatedRoute,
|
||||||
|
private sanitizer: DomSanitizer,
|
||||||
|
public service: FileViewerService,
|
||||||
|
private notes: NotificationsService,
|
||||||
|
private auth: AuthService,
|
||||||
|
private stringsService: StringsService) {
|
||||||
title.setTitle('TaskBoard - File Viewer');
|
title.setTitle('TaskBoard - File Viewer');
|
||||||
|
this.isLoaded = false;
|
||||||
this.subs = [];
|
this.subs = [];
|
||||||
|
|
||||||
let sub = stringsService.stringsChanged.subscribe(newStrings => {
|
let sub = this.stringsService.stringsChanged.subscribe(newStrings => {
|
||||||
this.strings = newStrings;
|
this.strings = newStrings;
|
||||||
|
|
||||||
|
this.pageName = this.strings.files;
|
||||||
|
this.title.setTitle(`TaskBoard - ${this.pageName}`);
|
||||||
});
|
});
|
||||||
this.subs.push(sub);
|
this.subs.push(sub);
|
||||||
|
|
||||||
sub = auth.userChanged.subscribe((user: User) => {
|
sub = this.auth.userChanged.subscribe((user: User) => {
|
||||||
this.activeUser = user;
|
this.activeUser = user;
|
||||||
});
|
});
|
||||||
this.subs.push(sub);
|
this.subs.push(sub);
|
||||||
|
|
||||||
|
sub = this.active.params.subscribe(params => {
|
||||||
|
this.fileHash = params.hash;
|
||||||
|
});
|
||||||
|
this.subs.push(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
this.pageName = this.strings.files;
|
this.service.getAttachmentInfo(this.fileHash).subscribe(res => {
|
||||||
|
res.alerts.forEach(note => this.notes.add(note));
|
||||||
|
|
||||||
console.log(this.stringsService, this.activeUser, this.pageName);
|
if (res.status === 'success') {
|
||||||
|
this.attachment = res.data[1];
|
||||||
|
|
||||||
|
const url = `./api/uploads/${this.attachment.diskfilename}`;
|
||||||
|
this.fileUrl = this.sanitizer.bypassSecurityTrustResourceUrl(url);
|
||||||
|
|
||||||
|
this.isLoaded = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnDestroy() {
|
ngOnDestroy() {
|
||||||
|
@ -5,6 +5,7 @@ import { RouterModule } from '@angular/router';
|
|||||||
import { SharedModule } from '../shared/shared.module';
|
import { SharedModule } from '../shared/shared.module';
|
||||||
|
|
||||||
import { FileViewerComponent } from './file-viewer.component';
|
import { FileViewerComponent } from './file-viewer.component';
|
||||||
|
import { FileViewerService } from './file-viewer.service';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
@ -15,6 +16,9 @@ import { FileViewerComponent } from './file-viewer.component';
|
|||||||
declarations: [
|
declarations: [
|
||||||
FileViewerComponent
|
FileViewerComponent
|
||||||
],
|
],
|
||||||
|
providers: [
|
||||||
|
FileViewerService
|
||||||
|
],
|
||||||
exports: [
|
exports: [
|
||||||
FileViewerComponent
|
FileViewerComponent
|
||||||
]
|
]
|
||||||
|
22
src/app/files/file-viewer.service.ts
Normal file
22
src/app/files/file-viewer.service.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { HttpClient } from '@angular/common/http';
|
||||||
|
|
||||||
|
import { Observable, of } from 'rxjs';
|
||||||
|
import { map, catchError } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { ApiResponse } from '../shared/models';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class FileViewerService {
|
||||||
|
|
||||||
|
constructor(private http: HttpClient) {}
|
||||||
|
|
||||||
|
getAttachmentInfo(hash: string): Observable<ApiResponse> {
|
||||||
|
return this.http.get('api/attachments/hash/' + hash)
|
||||||
|
.pipe(
|
||||||
|
map((response: ApiResponse) => response),
|
||||||
|
catchError((err) => of(err.error as ApiResponse))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Reference in New Issue
Block a user