From 0f0a331c568f029579266fb113aa885b83f4e48a Mon Sep 17 00:00:00 2001 From: Timo Date: Tue, 23 Feb 2021 11:05:03 +0200 Subject: [PATCH] force redaction phase 1 --- .../service/annotation-actions.service.ts | 29 +++ apps/red-ui/src/app/icons/icons.module.ts | 1 + .../annotation-actions.component.html | 10 ++ .../file/model/annotation.permissions.ts | 3 + .../file/service/manual-annotation.service.ts | 41 ++++- apps/red-ui/src/assets/i18n/en.json | 3 + .../src/assets/icons/general/thumb-up.svg | 9 + .../api/manualRedactionController.service.ts | 169 ++++++++++++++++++ .../src/lib/model/forceRedactionRequest.ts | 17 ++ .../src/lib/model/manualForceRedaction.ts | 28 +++ .../src/lib/model/manualRedactions.ts | 2 + libs/red-ui-http/src/lib/model/models.ts | 2 + 12 files changed, 313 insertions(+), 1 deletion(-) create mode 100644 apps/red-ui/src/assets/icons/general/thumb-up.svg create mode 100644 libs/red-ui-http/src/lib/model/forceRedactionRequest.ts create mode 100644 libs/red-ui-http/src/lib/model/manualForceRedaction.ts diff --git a/apps/red-ui/src/app/common/service/annotation-actions.service.ts b/apps/red-ui/src/app/common/service/annotation-actions.service.ts index af30b2c58..65ae7b988 100644 --- a/apps/red-ui/src/app/common/service/annotation-actions.service.ts +++ b/apps/red-ui/src/app/common/service/annotation-actions.service.ts @@ -35,6 +35,21 @@ export class AnnotationActionsService { }); } + public forceRedaction($event: MouseEvent, annotations: AnnotationWrapper[], annotationsChanged: EventEmitter) { + $event?.stopPropagation(); + annotations.forEach((annotation) => { + this._processObsAndEmit( + this._manualAnnotationService.forceRedaction({ + annotationId: annotation.id, + comment: 'Test', + legalBasis: 'Test' + }), + annotation, + annotationsChanged + ); + }); + } + public suggestRemoveAnnotation( $event: MouseEvent, annotations: AnnotationWrapper[], @@ -98,6 +113,20 @@ export class AnnotationActionsService { return { annotation: a, permissions: AnnotationPermissions.forUser(this._permissionsService.currentUser, a) }; }); + const canForceRedaction = annotationPermissions.reduce((acc, next) => acc && next.permissions.canForceRedaction, true); + if (canForceRedaction) { + availableActions.push({ + type: 'actionButton', + img: '/assets/icons/general/thumb-up.svg', + title: this._translateService.instant('annotation-actions.force-redaction.label'), + onClick: () => { + this._ngZone.run(() => { + this.forceRedaction(null, annotations, annotationsChanged); + }); + } + }); + } + const canAcceptRecommendation = annotationPermissions.reduce((acc, next) => acc && next.permissions.canAcceptRecommendation, true); if (canAcceptRecommendation) { availableActions.push({ diff --git a/apps/red-ui/src/app/icons/icons.module.ts b/apps/red-ui/src/app/icons/icons.module.ts index 2da675192..0c8622230 100644 --- a/apps/red-ui/src/app/icons/icons.module.ts +++ b/apps/red-ui/src/app/icons/icons.module.ts @@ -65,6 +65,7 @@ export class IconsModule { 'status-collapse', 'template', 'thumb-down', + 'thumb-up', 'trash', 'under-construction', 'undo', diff --git a/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.html b/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.html index 3aec4a365..f1566968c 100644 --- a/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.html +++ b/apps/red-ui/src/app/screens/file/annotation-actions/annotation-actions.component.html @@ -1,5 +1,15 @@
+ + + this._notify(this._getMessage('suggest', false)), + (error) => this._notify(this._getMessage('suggest', false, true), NotificationType.ERROR, error) + ) + ); + } + + private _makeForceRedaction(forceRedactionRequest: ForceRedactionRequest) { + return this._manualRedactionControllerService + .forceRedaction(forceRedactionRequest, this._appStateService.activeProject.project.projectId, this._appStateService.activeFile.fileId) + .pipe( + tap( + () => this._notify(this._getMessage('add', false)), + (error) => this._notify(this._getMessage('add', false, true), NotificationType.ERROR, error) + ) + ); + } + private _makeRedactionRequest(manualRedactionEntry: AddRedactionRequest) { return this._manualRedactionControllerService .requestAddRedaction(manualRedactionEntry, this._appStateService.activeProject.project.projectId, this._appStateService.activeFile.fileId) diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json index e20c12086..0711b5924 100644 --- a/apps/red-ui/src/assets/i18n/en.json +++ b/apps/red-ui/src/assets/i18n/en.json @@ -371,6 +371,9 @@ } } }, + "force-redaction": { + "label": "Force Redaction" + }, "accept-suggestion": { "label": "Accept Suggestion", "add-to-dict": "Approve and add to dictionary", diff --git a/apps/red-ui/src/assets/icons/general/thumb-up.svg b/apps/red-ui/src/assets/icons/general/thumb-up.svg new file mode 100644 index 000000000..60f1effdb --- /dev/null +++ b/apps/red-ui/src/assets/icons/general/thumb-up.svg @@ -0,0 +1,9 @@ + + + + + + diff --git a/libs/red-ui-http/src/lib/api/manualRedactionController.service.ts b/libs/red-ui-http/src/lib/api/manualRedactionController.service.ts index 39ba46009..aa6c682cb 100644 --- a/libs/red-ui-http/src/lib/api/manualRedactionController.service.ts +++ b/libs/red-ui-http/src/lib/api/manualRedactionController.service.ts @@ -25,6 +25,7 @@ import { RemoveRedactionRequest } from '../model/removeRedactionRequest'; import { BASE_PATH } from '../variables'; import { Configuration } from '../configuration'; +import { ForceRedactionRequest } from '..'; @Injectable() export class ManualRedactionControllerService { @@ -140,6 +141,174 @@ export class ManualRedactionControllerService { ); } + /** + * Forces a redaction + * None + * @param body forceRedactionRequest + * @param projectId projectId + * @param fileId fileId + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public forceRedaction( + body: ForceRedactionRequest, + projectId: string, + fileId: string, + observe?: 'body', + reportProgress?: boolean + ): Observable; + public forceRedaction( + body: ForceRedactionRequest, + projectId: string, + fileId: string, + observe?: 'response', + reportProgress?: boolean + ): Observable>; + public forceRedaction( + body: ForceRedactionRequest, + projectId: string, + fileId: string, + observe?: 'events', + reportProgress?: boolean + ): Observable>; + public forceRedaction( + body: ForceRedactionRequest, + projectId: string, + fileId: string, + observe: any = 'body', + reportProgress: boolean = false + ): Observable { + if (body === null || body === undefined) { + throw new Error('Required parameter body was null or undefined when calling forceRedaction.'); + } + + if (projectId === null || projectId === undefined) { + throw new Error('Required parameter projectId was null or undefined when calling forceRedaction.'); + } + + if (fileId === null || fileId === undefined) { + throw new Error('Required parameter fileId was null or undefined when calling forceRedaction.'); + } + + let headers = this.defaultHeaders; + + // authentication (RED-OAUTH) required + if (this.configuration.accessToken) { + const accessToken = typeof this.configuration.accessToken === 'function' ? this.configuration.accessToken() : this.configuration.accessToken; + headers = headers.set('Authorization', 'Bearer ' + accessToken); + } + + // to determine the Accept header + const httpHeaderAccepts: string[] = ['application/json']; + const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts); + if (httpHeaderAcceptSelected !== undefined) { + headers = headers.set('Accept', httpHeaderAcceptSelected); + } + + // to determine the Content-Type header + const consumes: string[] = ['application/json']; + const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes); + if (httpContentTypeSelected !== undefined) { + headers = headers.set('Content-Type', httpContentTypeSelected); + } + + return this.httpClient.request( + 'post', + `${this.basePath}/manualRedaction/redaction/force/${encodeURIComponent(String(projectId))}/${encodeURIComponent(String(fileId))}`, + { + body: body, + withCredentials: this.configuration.withCredentials, + headers: headers, + observe: observe, + reportProgress: reportProgress + } + ); + } + + /** + * Adds a request to force a redaction. + * None + * @param body forceRedactionRequest + * @param projectId projectId + * @param fileId fileId + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public requestForceRedaction( + body: ForceRedactionRequest, + projectId: string, + fileId: string, + observe?: 'body', + reportProgress?: boolean + ): Observable; + public requestForceRedaction( + body: ForceRedactionRequest, + projectId: string, + fileId: string, + observe?: 'response', + reportProgress?: boolean + ): Observable>; + public requestForceRedaction( + body: ForceRedactionRequest, + projectId: string, + fileId: string, + observe?: 'events', + reportProgress?: boolean + ): Observable>; + public requestForceRedaction( + body: ForceRedactionRequest, + projectId: string, + fileId: string, + observe: any = 'body', + reportProgress: boolean = false + ): Observable { + if (body === null || body === undefined) { + throw new Error('Required parameter body was null or undefined when calling requestForceRedaction.'); + } + + if (projectId === null || projectId === undefined) { + throw new Error('Required parameter projectId was null or undefined when calling requestForceRedaction.'); + } + + if (fileId === null || fileId === undefined) { + throw new Error('Required parameter fileId was null or undefined when calling requestForceRedaction.'); + } + + let headers = this.defaultHeaders; + + // authentication (RED-OAUTH) required + if (this.configuration.accessToken) { + const accessToken = typeof this.configuration.accessToken === 'function' ? this.configuration.accessToken() : this.configuration.accessToken; + headers = headers.set('Authorization', 'Bearer ' + accessToken); + } + + // to determine the Accept header + let httpHeaderAccepts: string[] = ['application/json']; + const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts); + if (httpHeaderAcceptSelected !== undefined) { + headers = headers.set('Accept', httpHeaderAcceptSelected); + } + + // to determine the Content-Type header + const consumes: string[] = ['application/json']; + const httpContentTypeSelected: string | undefined = this.configuration.selectHeaderContentType(consumes); + if (httpContentTypeSelected !== undefined) { + headers = headers.set('Content-Type', httpContentTypeSelected); + } + + return this.httpClient.request( + 'post', + `${this.basePath}/manualRedaction/request/force/${encodeURIComponent(String(projectId))}/${encodeURIComponent(String(fileId))}`, + { + body: body, + withCredentials: this.configuration.withCredentials, + headers: headers, + observe: observe, + reportProgress: reportProgress + } + ); + } + /** * Adds a manual redaction * None diff --git a/libs/red-ui-http/src/lib/model/forceRedactionRequest.ts b/libs/red-ui-http/src/lib/model/forceRedactionRequest.ts new file mode 100644 index 000000000..76de68146 --- /dev/null +++ b/libs/red-ui-http/src/lib/model/forceRedactionRequest.ts @@ -0,0 +1,17 @@ +/** + * API Documentation for Redaction Gateway + * Description for redaction + * + * OpenAPI spec version: 1.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +export interface ForceRedactionRequest { + annotationId?: string; + comment?: string; + legalBasis?: string; +} diff --git a/libs/red-ui-http/src/lib/model/manualForceRedaction.ts b/libs/red-ui-http/src/lib/model/manualForceRedaction.ts new file mode 100644 index 000000000..3fc515724 --- /dev/null +++ b/libs/red-ui-http/src/lib/model/manualForceRedaction.ts @@ -0,0 +1,28 @@ +/** + * API Documentation for Redaction Gateway + * Description for redaction + * + * OpenAPI spec version: 1.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ + +export interface ManualForceRedaction { + id?: string; + legalBasis?: string; + processedDate?: string; + requestDate?: string; + status?: ManualForceRedaction.StatusEnum; + user?: string; +} +export namespace ManualForceRedaction { + export type StatusEnum = 'REQUESTED' | 'APPROVED' | 'DECLINED'; + export const StatusEnum = { + REQUESTED: 'REQUESTED' as StatusEnum, + APPROVED: 'APPROVED' as StatusEnum, + DECLINED: 'DECLINED' as StatusEnum + }; +} diff --git a/libs/red-ui-http/src/lib/model/manualRedactions.ts b/libs/red-ui-http/src/lib/model/manualRedactions.ts index c42f1e644..9756af330 100644 --- a/libs/red-ui-http/src/lib/model/manualRedactions.ts +++ b/libs/red-ui-http/src/lib/model/manualRedactions.ts @@ -12,9 +12,11 @@ import { Comment } from './comment'; import { IdRemoval } from './idRemoval'; import { ManualRedactionEntry } from './manualRedactionEntry'; +import { ManualForceRedaction } from './manualForceRedaction'; export interface ManualRedactions { comments?: { [key: string]: Array }; entriesToAdd?: Array; + forceRedactions?: Array; idsToRemove?: Array; } diff --git a/libs/red-ui-http/src/lib/model/models.ts b/libs/red-ui-http/src/lib/model/models.ts index e2d88a6ab..e1d6cb38c 100644 --- a/libs/red-ui-http/src/lib/model/models.ts +++ b/libs/red-ui-http/src/lib/model/models.ts @@ -52,3 +52,5 @@ export * from './digitalSignature'; export * from './digitalSignatureViewModel'; export * from './redactionChangeLog'; export * from './redactionChangeLogEntry'; +export * from './forceRedactionRequest'; +export * from './manualForceRedaction';