Merge branch 'VM/RED-7549' into 'master'

RED-7549 - Bulk delete action dialog

Closes RED-7549

See merge request redactmanager/red-ui!75
This commit is contained in:
Dan Percic 2023-09-14 09:51:20 +02:00
commit b32f62021a
8 changed files with 118 additions and 18 deletions

View File

@ -60,7 +60,14 @@ export class AnnotationActionsComponent implements OnChanges {
}
get canRemoveRedaction(): boolean {
return (this.#isDocumine || this.annotations.length === 1) && this.annotationPermissions.canRemoveRedaction;
if (this.annotationPermissions.canRemoveRedaction) {
if (this.annotations.length > 1) {
const foundIgnoredHint = this.annotations.find(a => a.isIgnoredHint);
return !foundIgnoredHint && this.#sameType;
}
return true;
}
return false;
}
get viewerAnnotations() {
@ -131,4 +138,9 @@ export class AnnotationActionsComponent implements OnChanges {
helpModeKey(action: string) {
return this.#isDocumine ? `${action}_annotation` : '';
}
get #sameType() {
const type = this.annotations[0].superType;
return this.annotations.every(a => a.superType === type);
}
}

View File

@ -1,13 +1,51 @@
<section class="dialog">
<form (submit)="save()" [formGroup]="form">
<div
*ngIf="data.redactions.length === 1"
[innerHTML]="
'remove-redaction.dialog.title' | translate : { type: hint ? 'hint' : recommendation ? 'recommendation' : 'redaction' }
'remove-redaction.dialog.title' | translate: { type: hint ? 'hint' : recommendation ? 'recommendation' : 'redaction' }
"
class="dialog-header heading-l"
></div>
<div
*ngIf="data.redactions.length > 1"
[innerHTML]="
'remove-redaction.dialog.title-bulk' | translate: { type: hint ? 'hint' : recommendation ? 'recommendation' : 'redaction' }
"
class="dialog-header heading-l"
></div>
<div class="dialog-content">
<div class="dialog-content redaction">
<div *ngIf="data.redactions.length > 1">
<label
[translateParams]="{ type: hint ? 'hints' : recommendation ? 'recommendations' : 'redactions' }"
[translate]="'remove-redaction.dialog.content.redacted-text'"
class="selected-text"
></label>
<cdk-virtual-scroll-viewport
[itemSize]="16"
[ngStyle]="{ height: redactedTexts.length <= 5 ? 16 * redactedTexts.length + 'px' : 80 + 'px' }"
>
<ul *cdkVirtualFor="let text of redactedTexts; let idx = index">
<li>
{{
(isFalsePositive
? 'remove-redaction.dialog.content.list-item-false-positive'
: 'remove-redaction.dialog.content.list-item'
)
| translate
: {
text: text,
context: data.falsePositiveContext[idx]
}
| replaceNbsp
}}
</li>
</ul>
</cdk-virtual-scroll-viewport>
</div>
<iqser-details-radio [options]="options" formControlName="option"></iqser-details-radio>
<div class="iqser-input-group w-450">

View File

@ -1,3 +1,18 @@
.dialog-content {
height: 408px;
}
cdk-virtual-scroll-viewport {
margin-top: 8px;
}
:host ::ng-deep .cdk-virtual-scroll-orientation-vertical .cdk-virtual-scroll-content-wrapper {
max-width: 100% !important;
}
li {
white-space: nowrap;
text-overflow: ellipsis;
list-style-position: inside;
overflow: hidden;
}

View File

@ -3,7 +3,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormBuilder, UntypedFormGroup } from '@angular/forms';
import { DetailsRadioOption, IconButtonTypes, IqserDialogComponent } from '@iqser/common-ui';
import { tap } from 'rxjs/operators';
import { getRemoveRedactionOptions, RemoveRedactionOption } from '../../utils/dialog-options';
import { getRemoveRedactionOptions, RemoveAnnotationOptions, RemoveRedactionOption } from '../../utils/dialog-options';
import { RemoveRedactionData, RemoveRedactionResult } from '../../utils/dialog-types';
@Component({
@ -19,14 +19,16 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent<
readonly options: DetailsRadioOption<RemoveRedactionOption>[];
readonly recommendation;
readonly hint: boolean;
readonly redactedTexts: string[];
form!: UntypedFormGroup;
#applyToAllDossiers: boolean;
constructor(private readonly _formBuilder: FormBuilder) {
super();
this.recommendation = this.data.redactions.every(r => r.isRecommendation);
this.hint = this.data.redactions.every(r => r.hint);
this.recommendation = this.data.redactions[0].isRecommendation;
this.hint = this.data.redactions[0].hint;
this.options = getRemoveRedactionOptions(this.data);
this.redactedTexts = this.data.redactions.map(annotation => annotation.value);
this.form = this.#getForm();
this.#applyToAllDossiers = this.data.applyToAllDossiers ?? true;
@ -45,6 +47,10 @@ export class RemoveRedactionDialogComponent extends IqserDialogComponent<
.subscribe();
}
get isFalsePositive(): boolean {
return this.form.get('option').value.value === RemoveAnnotationOptions.FALSE_POSITIVE;
}
save(): void {
this.close(this.form.getRawValue());
}

View File

@ -6,20 +6,25 @@ export const removeRedactionTranslations: { [key in RemoveRedactionOption]: Dial
ONLY_HERE: {
label: _('remove-redaction.dialog.content.options.only-here.label'),
description: _('remove-redaction.dialog.content.options.only-here.description'),
descriptionBulk: _('remove-redaction.dialog.content.options.only-here.description-bulk'),
},
IN_DOSSIER: {
label: _('remove-redaction.dialog.content.options.in-dossier.label'),
labelBulk: _('remove-redaction.dialog.content.options.in-dossier.label-bulk'),
description: _('remove-redaction.dialog.content.options.in-dossier.description'),
descriptionBulk: _('remove-redaction.dialog.content.options.in-dossier.description-bulk'),
extraOptionLabel: _('remove-redaction.dialog.content.options.in-dossier.extraOptionLabel'),
},
FALSE_POSITIVE: {
label: _('remove-redaction.dialog.content.options.false-positive.label'),
description: _('remove-redaction.dialog.content.options.false-positive.description'),
descriptionBulk: _('remove-redaction.dialog.content.options.false-positive.description-bulk'),
extraOptionLabel: _('remove-redaction.dialog.content.options.false-positive.extraOptionLabel'),
},
DO_NOT_RECOMMEND: {
label: _('remove-redaction.dialog.content.options.do-not-recommend.label'),
description: _('remove-redaction.dialog.content.options.do-not-recommend.description'),
descriptionBulk: _('remove-redaction.dialog.content.options.do-not-recommend.description-bulk'),
extraOptionLabel: _('remove-redaction.dialog.content.options.do-not-recommend.extraOptionLabel'),
},
};

View File

@ -2052,11 +2052,11 @@
},
"only-here": {
"description": "Do not annotate \"{value}\" at this position in the current document.",
"description-bulk": "",
"description-bulk": "Do not annotate the selected terms at this position in the current document.",
"label": "Remove here"
}
},
"redacted-text": ""
"redacted-text": "Selected redactions"
},
"title": "Remove {count, plural, one{annotation} other {annotations}}"
}
@ -2070,30 +2070,38 @@
"content": {
"comment": "Comment",
"comment-placeholder": "Add remarks or mentions ...",
"list-item": "{text}",
"list-item-false-positive": "\"{text}\" in the context: \"{context}\"",
"options": {
"do-not-recommend": {
"description": "Do not recommend \"{value}\" as {type} in any document of the current dossier.",
"description-bulk": "",
"description-bulk": "Do not recommend the selected terms in any document of the current dossier.",
"extraOptionLabel": "Apply to all dossiers",
"label": "Remove from dossier"
},
"false-positive": {
"description": "\"{value}\" is not a {type} in this context: \"{context}\".",
"description-bulk": "Do not redact the selected terms in their respective context.",
"extraOptionLabel": "Apply to all dossiers",
"label": "False positive"
},
"in-dossier": {
"description": "Do not {type} \"{value}\" in any document of the current dossier.",
"description-bulk": "Do not redact the selected terms as their respective types in any dossier.",
"extraOptionLabel": "Apply to all dossiers",
"label": "Remove from dossier"
"label": "Remove from dossier",
"label-bulk": "No longer redact in any dossier"
},
"only-here": {
"description": "Do not {type, select, undefined{redact} other{type}} \"{value}\" at this position in the current document.",
"description-bulk": "Do not redact the selected terms at this position in the current document.",
"label": "Remove here"
}
}
},
"redacted-text": "Selected {type}"
},
"title": "Remove {type}"
"title": "Remove {type, select, redaction{redaction} recommendation{recommendation} other{hint}}",
"title-bulk": "Remove {type, select, redaction{redactions} recommendation{recommendations} other{hints}}"
}
},
"report-type": {

View File

@ -2070,6 +2070,8 @@
"content": {
"comment": "",
"comment-placeholder": "",
"list-item": "",
"list-item-false-positive": "",
"options": {
"do-not-recommend": {
"description": "",
@ -2079,21 +2081,27 @@
},
"false-positive": {
"description": "",
"description-bulk": "",
"extraOptionLabel": "",
"label": ""
},
"in-dossier": {
"description": "",
"description-bulk": "",
"extraOptionLabel": "",
"label": ""
"label": "",
"label-bulk": ""
},
"only-here": {
"description": "",
"description-bulk": "",
"label": ""
}
}
},
"redacted-text": ""
},
"title": ""
"title": "",
"title-bulk": ""
}
},
"report-type": {

View File

@ -2070,6 +2070,8 @@
"content": {
"comment": "Comment",
"comment-placeholder": "Add remarks or mentions ...",
"list-item": "",
"list-item-false-positive": "",
"options": {
"do-not-recommend": {
"description": "Do not recommend \"{value}\" as {type} in any document of the current dossier.",
@ -2079,21 +2081,27 @@
},
"false-positive": {
"description": "\"{value}\" is not a {type} in this context: \"{context}\".",
"description-bulk": "",
"extraOptionLabel": "Apply to all dossiers",
"label": "False positive"
},
"in-dossier": {
"description": "Do not {type} \"{value}\" in any document of the current dossier.",
"description-bulk": "",
"extraOptionLabel": "Apply to all dossiers",
"label": "Remove from dossier"
"label": "Remove from dossier",
"label-bulk": ""
},
"only-here": {
"description": "Do not {type} \"{value}\" at this position in the current document.",
"description-bulk": "",
"label": "Remove here"
}
}
},
"redacted-text": ""
},
"title": "Remove {type}"
"title": "Remove {type}",
"title-bulk": ""
}
},
"report-type": {