From 8925841f91aca1f6dc0e8821a64ea5c41dafe2f7 Mon Sep 17 00:00:00 2001 From: Timo Bejan Date: Sun, 1 Nov 2020 22:34:47 +0200 Subject: [PATCH] integrated comments and fixed some flows for manual redactions --- .../comments/comments.component.html | 24 ++++++----- .../comments/comments.component.scss | 5 ++- .../components/comments/comments.component.ts | 40 +++++++++++++++---- .../file-preview-screen.component.html | 10 ++--- .../file-preview-screen.component.scss | 2 +- .../file-preview-screen.component.ts | 20 ++++++---- .../screens/file/model/annotation.wrapper.ts | 27 ++++++++++--- .../app/screens/file/model/file-data.model.ts | 8 +++- .../file/service/manual-annotation.service.ts | 34 ++++++++++++---- 9 files changed, 123 insertions(+), 47 deletions(-) diff --git a/apps/red-ui/src/app/components/comments/comments.component.html b/apps/red-ui/src/app/components/comments/comments.component.html index 6ffdc1bdb..053d2f670 100644 --- a/apps/red-ui/src/app/components/comments/comments.component.html +++ b/apps/red-ui/src/app/components/comments/comments.component.html @@ -1,13 +1,17 @@ -
- +
+
-
+
-
{{ comment }}
+ + + + +
{{ comment.text }}
@@ -16,10 +20,10 @@
- - - - - - +
+
+ + +
+
diff --git a/apps/red-ui/src/app/components/comments/comments.component.scss b/apps/red-ui/src/app/components/comments/comments.component.scss index fe36f7832..ee4689c48 100644 --- a/apps/red-ui/src/app/components/comments/comments.component.scss +++ b/apps/red-ui/src/app/components/comments/comments.component.scss @@ -37,8 +37,11 @@ } .trash-icon { - color: $primary; display: none; + + &.red { + color: $primary; + } } &:hover { diff --git a/apps/red-ui/src/app/components/comments/comments.component.ts b/apps/red-ui/src/app/components/comments/comments.component.ts index d40c32d5d..ae89765a1 100644 --- a/apps/red-ui/src/app/components/comments/comments.component.ts +++ b/apps/red-ui/src/app/components/comments/comments.component.ts @@ -1,19 +1,26 @@ import { ChangeDetectorRef, Component, Input } from '@angular/core'; import { FormBuilder, FormGroup, Validators } from '@angular/forms'; - +import { Comment } from '@redaction/red-ui-http'; +import { ManualAnnotationService } from '../../screens/file/service/manual-annotation.service'; +import { AnnotationWrapper } from '../../screens/file/model/annotation.wrapper'; +import { UserService } from '../../user/user.service'; +import { AppStateService } from '../../state/app-state.service'; @Component({ selector: 'redaction-comments', templateUrl: './comments.component.html', styleUrls: ['./comments.component.scss'] }) export class CommentsComponent { - @Input() public comments: string[] = []; + @Input() public annotation: AnnotationWrapper; public expanded = false; public commentForm: FormGroup; constructor( private readonly _changeDetectorRef: ChangeDetectorRef, - private readonly _formBuilder: FormBuilder + private readonly _appStateService: AppStateService, + private readonly _formBuilder: FormBuilder, + private readonly _userService: UserService, + private readonly _manualAnnotationService: ManualAnnotationService ) { this.commentForm = this._formBuilder.group({ comment: ['', Validators.required] @@ -21,7 +28,7 @@ export class CommentsComponent { } public get more(): boolean { - return this.comments.length > 2; + return this.annotation?.comments?.length > 2; } public toggleSeeMore($event: MouseEvent): void { @@ -31,11 +38,30 @@ export class CommentsComponent { } public addComment(): void { - console.log(`Adding comment "${this.commentForm.value.comment}"...`); + const value = this.commentForm.value.comment; + if (value) { + this._manualAnnotationService + .addComment(value, this.annotation.id) + .subscribe((commentResponse) => { + this.annotation.comments.push({ + text: value, + id: commentResponse.commentId, + user: this._userService.userId + }); + }); + } this.commentForm.reset(); } - public deleteComment(comment: string): void { - console.log(`Deleting comment "${comment}"...`); + public deleteComment(comment: Comment): void { + this._manualAnnotationService + .deleteComment(comment.id, this.annotation.id) + .subscribe(() => { + this.annotation.comments.splice(this.annotation.comments.indexOf(comment), 1); + }); + } + + canDeleteComment(comment: Comment) { + return comment.user === this._userService.userId; } } diff --git a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html index 650ab0a9f..e784e9cfe 100644 --- a/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html +++ b/apps/red-ui/src/app/screens/file/file-preview-screen/file-preview-screen.component.html @@ -159,14 +159,12 @@
-
- {{ annotation.pageNumber }} -
+ + + - +
{ this.fileData = fileDataModel; - const manualRedactionAnnotations = fileDataModel.manualRedactions.entriesToAdd.map( - (mr) => AnnotationWrapper.fromManualRedaction(mr) + + const manualRedactionAnnotations = fileDataModel.entriesToAdd.map((mr) => + AnnotationWrapper.fromManualRedaction( + mr, + fileDataModel.manualRedactions.comments + ) ); const redactionLogAnnotations = fileDataModel.redactionLog.redactionLogEntry.map( - (rde) => AnnotationWrapper.fromRedactionLog(rde) + (rde) => + AnnotationWrapper.fromRedactionLog( + rde, + fileDataModel.manualRedactions.comments + ) ); this.annotations.push(...manualRedactionAnnotations); @@ -132,6 +140,7 @@ export class FilePreviewScreenComponent implements OnInit { this.filters = this._annotationProcessingService.getAnnotationFilter( this.annotations ); + this.filtersChanged(this.filters); this._changeDetectorRef.detectChanges(); }); } @@ -424,10 +433,7 @@ export class FilePreviewScreenComponent implements OnInit { viewerReady($event: WebViewerInstance) { this.instance = $event; this.viewReady = true; - this._annotationDrawService.drawAnnotations( - this.instance, - this.fileData.manualRedactions.entriesToAdd - ); + this._annotationDrawService.drawAnnotations(this.instance, this.fileData.entriesToAdd); } filtersChanged(filters: FilterModel[]) { diff --git a/apps/red-ui/src/app/screens/file/model/annotation.wrapper.ts b/apps/red-ui/src/app/screens/file/model/annotation.wrapper.ts index d696523b8..79998c81c 100644 --- a/apps/red-ui/src/app/screens/file/model/annotation.wrapper.ts +++ b/apps/red-ui/src/app/screens/file/model/annotation.wrapper.ts @@ -1,18 +1,21 @@ -import { ManualRedactionEntry, Point, RedactionLogEntry } from '@redaction/red-ui-http'; +import { Comment, ManualRedactionEntry, Point, RedactionLogEntry } from '@redaction/red-ui-http'; export class AnnotationWrapper { superType: 'request' | 'redaction' | 'hint' | 'ignore'; dictionary: string; color: string; - comments: string[] = []; - uuid: string; + comments: Comment[] = []; manualRedactionEntry: ManualRedactionEntry; firstTopLeftPoint: Point; id: string; content: string; + manual: boolean; pageNumber; - static fromRedactionLog(redactionLogEntry: RedactionLogEntry) { + static fromRedactionLog( + redactionLogEntry: RedactionLogEntry, + comments: { [key: string]: Array } + ) { const annotationWrapper = new AnnotationWrapper(); annotationWrapper.superType = redactionLogEntry.redacted ? 'redaction' @@ -23,16 +26,24 @@ export class AnnotationWrapper { annotationWrapper.firstTopLeftPoint = redactionLogEntry.positions[0]?.topLeft; annotationWrapper.pageNumber = redactionLogEntry.positions[0]?.page; annotationWrapper.id = redactionLogEntry.id; + annotationWrapper.manual = false; annotationWrapper.content = annotationWrapper.superType === 'redaction' || annotationWrapper.superType === 'ignore' ? AnnotationWrapper.createAnnotationContentForRedactionLogEntry(redactionLogEntry) : null; + annotationWrapper.comments = comments[redactionLogEntry.id] + ? comments[redactionLogEntry.id] + : []; return annotationWrapper; } - static fromManualRedaction(manualRedactionEntry: ManualRedactionEntry) { + static fromManualRedaction( + manualRedactionEntry: ManualRedactionEntry, + comments: { [key: string]: Array } + ) { + console.log(manualRedactionEntry); const annotationWrapper = new AnnotationWrapper(); - annotationWrapper.superType = 'request'; + annotationWrapper.superType = !manualRedactionEntry.addToDictionary ? 'request' : 'request'; annotationWrapper.dictionary = manualRedactionEntry.type; annotationWrapper.firstTopLeftPoint = manualRedactionEntry.positions[0]?.topLeft; annotationWrapper.pageNumber = manualRedactionEntry.positions[0]?.page; @@ -40,6 +51,10 @@ export class AnnotationWrapper { annotationWrapper.content = manualRedactionEntry.addToDictionary ? null : AnnotationWrapper.createAnnotationContentForManualRedaction(manualRedactionEntry); + annotationWrapper.manual = true; + annotationWrapper.comments = comments[manualRedactionEntry.id] + ? comments[manualRedactionEntry.id] + : []; return annotationWrapper; } diff --git a/apps/red-ui/src/app/screens/file/model/file-data.model.ts b/apps/red-ui/src/app/screens/file/model/file-data.model.ts index 902219f23..cc92e42cd 100644 --- a/apps/red-ui/src/app/screens/file/model/file-data.model.ts +++ b/apps/red-ui/src/app/screens/file/model/file-data.model.ts @@ -1,4 +1,4 @@ -import { ManualRedactions, RedactionLog } from '@redaction/red-ui-http'; +import { ManualRedactionEntry, ManualRedactions, RedactionLog } from '@redaction/red-ui-http'; export class FileDataModel { constructor( @@ -7,4 +7,10 @@ export class FileDataModel { public redactionLog: RedactionLog, public manualRedactions: ManualRedactions ) {} + + get entriesToAdd(): ManualRedactionEntry[] { + return this.manualRedactions.entriesToAdd.filter( + (e) => !this.redactionLog.redactionLogEntry.find((r) => r.id === e.id) + ); + } } diff --git a/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts b/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts index bbabd7500..b0d598246 100644 --- a/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts +++ b/apps/red-ui/src/app/screens/file/service/manual-annotation.service.ts @@ -25,12 +25,30 @@ export class ManualAnnotationService { private readonly _dictionaryControllerService: DictionaryControllerService ) {} + public addComment(comment: string, annotationId: string) { + return this._manualRedactionControllerService.addComment( + { text: comment }, + this._appStateService.activeProjectId, + this._appStateService.activeFileId, + annotationId + ); + } + + deleteComment(commentId: string, annotationId: string) { + return this._manualRedactionControllerService.undoComment( + this._appStateService.activeProjectId, + this._appStateService.activeFileId, + annotationId, + commentId + ); + } + public makeDictionaryEntry(manualRedactionEntry: ManualRedactionEntry) { - if (this._appStateService.isActiveProjectOwner) { - return this._makeDictionaryEntry(manualRedactionEntry); - } else { - return this._makeDictionaryRequest(manualRedactionEntry); - } + // if (this._appStateService.isActiveProjectOwner) { + // return this._makeDictionaryEntry(manualRedactionEntry); + // } else { + return this._makeDictionaryRequest(manualRedactionEntry); + // } } public makeRedaction(manualRedactionEntry: ManualRedactionEntry) { @@ -47,7 +65,7 @@ export class ManualAnnotationService { .approveRequest( this._appStateService.activeProjectId, this._appStateService.activeFile.fileId, - annotationWrapper.uuid + annotationWrapper.id ) .pipe( tap( @@ -68,12 +86,12 @@ export class ManualAnnotationService { ? this._manualRedactionControllerService.undo( this._appStateService.activeProjectId, this._appStateService.activeFile.fileId, - annotationWrapper.uuid + annotationWrapper.id ) : this._manualRedactionControllerService.declineRequest( this._appStateService.activeProjectId, this._appStateService.activeFile.fileId, - annotationWrapper.uuid + annotationWrapper.id ); return observable.pipe(