force redaction phase 1

This commit is contained in:
Timo 2021-02-23 11:05:03 +02:00
parent 992ac2b3ed
commit 0f0a331c56
12 changed files with 313 additions and 1 deletions

View File

@ -35,6 +35,21 @@ export class AnnotationActionsService {
});
}
public forceRedaction($event: MouseEvent, annotations: AnnotationWrapper[], annotationsChanged: EventEmitter<AnnotationWrapper>) {
$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({

View File

@ -65,6 +65,7 @@ export class IconsModule {
'status-collapse',
'template',
'thumb-down',
'thumb-up',
'trash',
'under-construction',
'undo',

View File

@ -1,5 +1,15 @@
<redaction-hidden-action (action)="logAnnotation(annotation)">
<div [class.visible]="menuOpen" *ngIf="canPerformAnnotationActions" class="annotation-actions">
<redaction-circle-button
(action)="annotationActionsService.forceRedaction($event, [annotation], annotationsChanged)"
type="dark-bg"
*ngIf="annotationPermissions.canForceRedaction"
tooltipPosition="before"
tooltip="annotation-actions.force-redaction.label"
icon="red:thumb-up"
>
</redaction-circle-button>
<redaction-circle-button
(action)="annotationActionsService.convertRecommendationToAnnotation($event, [annotation], annotationsChanged)"
type="dark-bg"

View File

@ -14,10 +14,13 @@ export class AnnotationPermissions {
canAcceptSuggestion: boolean;
canRejectSuggestion: boolean;
canForceRedaction: boolean;
public static forUser(user: UserWrapper, annotation: AnnotationWrapper) {
const permissions: AnnotationPermissions = new AnnotationPermissions();
permissions.canUndo = annotation.userId === user.id && annotation.isUndoableSuperType;
permissions.canForceRedaction = annotation.isSkipped && !permissions.canUndo;
permissions.canAcceptRecommendation = annotation.isRecommendation;

View File

@ -1,6 +1,12 @@
import { Injectable } from '@angular/core';
import { AppStateService } from '../../../state/app-state.service';
import { AddRedactionRequest, DictionaryControllerService, ManualRedactionControllerService, ManualRedactionEntry } from '@redaction/red-ui-http';
import {
AddRedactionRequest,
DictionaryControllerService,
ForceRedactionRequest,
ManualRedactionControllerService,
ManualRedactionEntry
} from '@redaction/red-ui-http';
import { AnnotationWrapper } from '../model/annotation.wrapper';
import { NotificationService, NotificationType } from '../../../notification/notification.service';
import { TranslateService } from '@ngx-translate/core';
@ -65,6 +71,17 @@ export class ManualAnnotationService {
}
}
// this wraps
// /manualRedaction/redaction/force
// /manualRedaction/request/force
public forceRedaction(request: ForceRedactionRequest) {
if (this._permissionsService.isManagerAndOwner()) {
return this._makeForceRedaction(request);
} else {
return this._makeForceRedactionRequest(request);
}
}
// this wraps
// /manualRedaction/approve
public approveRequest(annotationId: string, addToDictionary: boolean = false) {
@ -173,6 +190,28 @@ export class ManualAnnotationService {
}
}
private _makeForceRedactionRequest(forceRedactionRequest: ForceRedactionRequest) {
return this._manualRedactionControllerService
.requestForceRedaction(forceRedactionRequest, this._appStateService.activeProject.project.projectId, this._appStateService.activeFile.fileId)
.pipe(
tap(
() => 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)

View File

@ -371,6 +371,9 @@
}
}
},
"force-redaction": {
"label": "Force Redaction"
},
"accept-suggestion": {
"label": "Accept Suggestion",
"add-to-dict": "Approve and add to dictionary",

View File

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -256 1792 1792" id="svg3888" version="1.1"
width="100%" height="100%">
<defs id="defs3896"/>
<g transform="matrix(1,0,0,-1,129.08475,1346.1695)" id="g3890">
<path
d="m 256,192 q 0,26 -19,45 -19,19 -45,19 -26,0 -45,-19 -19,-19 -19,-45 0,-26 19,-45 19,-19 45,-19 26,0 45,19 19,19 19,45 z m 1152,576 q 0,51 -39,89.5 -39,38.5 -89,38.5 H 928 q 0,58 48,159.5 48,101.5 48,160.5 0,98 -32,145 -32,47 -128,47 -26,-26 -38,-85 -12,-59 -30.5,-125.5 Q 777,1131 736,1088 714,1065 659,997 655,992 636,967 617,942 604.5,926 592,910 570,883.5 548,857 530,839.5 512,822 491.5,804 471,786 451.5,777 432,768 416,768 H 384 V 128 h 32 q 13,0 31.5,-3 18.5,-3 33,-6.5 14.5,-3.5 38,-11 Q 542,100 553.5,96 565,92 589,83.5 613,75 618,73 829,0 960,0 h 121 q 192,0 192,167 0,26 -5,56 30,16 47.5,52.5 17.5,36.5 17.5,73.5 0,37 -18,69 53,50 53,119 0,25 -10,55.5 -10,30.5 -25,47.5 32,1 53.5,47 21.5,46 21.5,81 z m 128,1 q 0,-89 -49,-163 9,-33 9,-69 0,-77 -38,-144 3,-21 3,-43 0,-101 -60,-178 1,-139 -85,-219.5 -86,-80.5 -227,-80.5 h -36 -93 q -96,0 -189.5,22.5 Q 677,-83 554,-40 438,0 416,0 H 128 Q 75,0 37.5,37.5 0,75 0,128 V 768 Q 0,821 37.5,858.5 75,896 128,896 h 274 q 36,24 137,155 58,75 107,128 24,25 35.5,85.5 11.5,60.5 30.5,126.5 19,66 62,108 39,37 90,37 84,0 151,-32.5 67,-32.5 102,-101.5 35,-69 35,-186 0,-93 -48,-192 h 176 q 104,0 180,-76 76,-76 76,-179 z"
id="path3892" style="fill:currentColor"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -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<ManualAddResponse>;
public forceRedaction(
body: ForceRedactionRequest,
projectId: string,
fileId: string,
observe?: 'response',
reportProgress?: boolean
): Observable<HttpResponse<ManualAddResponse>>;
public forceRedaction(
body: ForceRedactionRequest,
projectId: string,
fileId: string,
observe?: 'events',
reportProgress?: boolean
): Observable<HttpEvent<ManualAddResponse>>;
public forceRedaction(
body: ForceRedactionRequest,
projectId: string,
fileId: string,
observe: any = 'body',
reportProgress: boolean = false
): Observable<any> {
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<ManualAddResponse>(
'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<ManualAddResponse>;
public requestForceRedaction(
body: ForceRedactionRequest,
projectId: string,
fileId: string,
observe?: 'response',
reportProgress?: boolean
): Observable<HttpResponse<ManualAddResponse>>;
public requestForceRedaction(
body: ForceRedactionRequest,
projectId: string,
fileId: string,
observe?: 'events',
reportProgress?: boolean
): Observable<HttpEvent<ManualAddResponse>>;
public requestForceRedaction(
body: ForceRedactionRequest,
projectId: string,
fileId: string,
observe: any = 'body',
reportProgress: boolean = false
): Observable<any> {
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<ManualAddResponse>(
'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

View File

@ -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;
}

View File

@ -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
};
}

View File

@ -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<Comment> };
entriesToAdd?: Array<ManualRedactionEntry>;
forceRedactions?: Array<ManualForceRedaction>;
idsToRemove?: Array<IdRemoval>;
}

View File

@ -52,3 +52,5 @@ export * from './digitalSignature';
export * from './digitalSignatureViewModel';
export * from './redactionChangeLog';
export * from './redactionChangeLogEntry';
export * from './forceRedactionRequest';
export * from './manualForceRedaction';