toggle visibility of ignored /skipped annotations, add undo

This commit is contained in:
Timo 2021-02-11 21:57:41 +02:00
parent 8f50fb0620
commit a46925a4cc
19 changed files with 194 additions and 140 deletions

View File

@ -31,6 +31,7 @@
>
<ng-template *ngTemplateOutlet="filterTemplate ? filterTemplate : defaultFilterTemplate; context: { filter: filter }"> </ng-template>
</mat-checkbox>
<ng-template *ngTemplateOutlet="actionsTemplate ? actionsTemplate : null; context: { filter: filter }"> </ng-template>
</div>
<div *ngIf="filter.filters && filter.expanded">
<div *ngFor="let subFilter of filter.filters" class="padding-left mat-menu-item" (click)="$event.stopPropagation()">
@ -42,6 +43,7 @@
<ng-template *ngTemplateOutlet="filterTemplate ? filterTemplate : defaultFilterTemplate; context: { filter: subFilter }">
</ng-template>
</mat-checkbox>
<ng-template *ngTemplateOutlet="actionsTemplate ? actionsTemplate : null; context: { filter: subFilter }"> </ng-template>
</div>
</div>
</div>

View File

@ -22,6 +22,7 @@ import { MAT_CHECKBOX_DEFAULT_OPTIONS } from '@angular/material/checkbox';
export class FilterComponent {
@Output() filtersChanged = new EventEmitter<FilterModel[]>();
@Input() filterTemplate: TemplateRef<any>;
@Input() actionsTemplate: TemplateRef<any>;
@Input() filters: FilterModel[] = [];
@Input() filterLabel = 'filter-menu.label';
@Input() icon: string;
@ -95,7 +96,7 @@ export class FilterComponent {
filterMouseLeave() {
this.mouseOver = false;
this.mouseOverTimeout = setTimeout(() => {
this.trigger.closeMenu();
// this.trigger.closeMenu();
}, 1000);
}
}

View File

@ -5,7 +5,7 @@ export const SuperTypeSorter = {
'suggestion-remove-dictionary': 8,
'suggestion-add': 5,
'suggestion-remove': 6,
ignore: 50,
skipped: 50,
redaction: 1,
manual: 2,
hint: 10,

View File

@ -25,11 +25,11 @@
}
.hint,
.ignore {
.skipped {
border-radius: 50%;
}
.ignore {
.skipped {
background-color: $grey-5;
}

View File

@ -18,6 +18,7 @@ button {
mat-icon {
width: 14px;
margin: 0;
}
&.primary {

View File

@ -27,8 +27,8 @@ export class TypeAnnotationIconComponent implements OnChanges {
this.label =
this.annotation.isSuggestion || this.annotation.isDeclinedSuggestion
? 'S'
: this.annotation.isIgnored
? 'I'
: this.annotation.isSkipped
? 'S'
: this.annotation.isReadyForAnalysis
? 'A'
: this.annotation.dictionary[0].toUpperCase();

View File

@ -5,7 +5,7 @@
<redaction-annotation-icon *ngIf="filter.key === 'manual-redaction'" type="square" label="M" [color]="dictionaryColor"></redaction-annotation-icon>
<redaction-annotation-icon *ngIf="filter.key === 'ignore'" type="square" label="I" [color]="dictionaryColor"></redaction-annotation-icon>
<redaction-annotation-icon *ngIf="filter.key === 'skipped'" type="square" label="S" [color]="dictionaryColor"></redaction-annotation-icon>
<redaction-annotation-icon
*ngIf="
filter.key === 'suggestion-remove' ||

View File

@ -1,111 +1,113 @@
<div [class.visible]="menuOpen" *ngIf="canPerformAnnotationActions" class="annotation-actions">
<redaction-circle-button
(action)="annotationActionsService.convertRecommendationToAnnotation($event, annotation, annotationsChanged)"
type="dark-bg"
*ngIf="annotationPermissions.canAcceptRecommendation"
tooltipPosition="before"
tooltip="annotation-actions.accept-recommendation.label"
icon="red:check-alt"
>
</redaction-circle-button>
<redaction-circle-button
(action)="annotationActionsService.acceptSuggestion($event, annotation, annotationsChanged)"
type="dark-bg"
*ngIf="annotationPermissions.canAcceptSuggestion"
tooltipPosition="before"
tooltip="annotation-actions.accept-suggestion.label"
icon="red:check-alt"
>
</redaction-circle-button>
<redaction-circle-button
(action)="annotationActionsService.undoDirectAction($event, annotation, annotationsChanged)"
*ngIf="annotationPermissions.canUndo"
type="dark-bg"
icon="red:undo"
tooltipPosition="before"
tooltip="annotation-actions.undo"
>
</redaction-circle-button>
<redaction-circle-button
(action)="hideAnnotation($event)"
*ngIf="annotation.isImage && viewerAnnotation?.isVisible()"
type="dark-bg"
icon="red:visibility-off"
tooltipPosition="before"
tooltip="annotation-actions.hide"
>
</redaction-circle-button>
<redaction-circle-button
(action)="showAnnotation($event)"
*ngIf="annotation.isImage && !viewerAnnotation?.isVisible()"
type="dark-bg"
icon="red:visibility"
tooltipPosition="before"
tooltip="annotation-actions.show"
>
</redaction-circle-button>
<redaction-circle-button
(action)="annotationActionsService.rejectSuggestion($event, annotation, annotationsChanged)"
type="dark-bg"
icon="red:close"
*ngIf="annotationPermissions.canRejectSuggestion"
tooltipPosition="before"
tooltip="annotation-actions.reject-suggestion"
>
</redaction-circle-button>
<redaction-circle-button
(action)="annotationActionsService.suggestRemoveAnnotation($event, annotation, false, annotationsChanged)"
type="dark-bg"
icon="red:trash"
*ngIf="annotationPermissions.canRemoveOrSuggestToRemoveOnlyHere && !annotationPermissions.canPerformMultipleRemoveActions"
tooltipPosition="before"
tooltip="annotation-actions.suggest-remove-annotation"
>
</redaction-circle-button>
<redaction-circle-button
*ngIf="annotationPermissions.canPerformMultipleRemoveActions"
(action)="openMenu($event)"
[class.active]="menuOpen"
[matMenuTriggerFor]="menu"
tooltipPosition="before"
tooltip="annotation-actions.suggest-remove-annotation"
type="dark-bg"
icon="red:trash"
>
</redaction-circle-button>
<mat-menu #menu="matMenu" (closed)="onMenuClosed()" xPosition="before">
<div
(click)="annotationActionsService.suggestRemoveAnnotation($event, annotation, true, annotationsChanged)"
mat-menu-item
*ngIf="annotationPermissions.canRemoveOrSuggestToRemoveFromDictionary"
<redaction-hidden-action (action)="logAnnotation(annotation)">
<div [class.visible]="menuOpen" *ngIf="canPerformAnnotationActions" class="annotation-actions">
<redaction-circle-button
(action)="annotationActionsService.convertRecommendationToAnnotation($event, annotation, annotationsChanged)"
type="dark-bg"
*ngIf="annotationPermissions.canAcceptRecommendation"
tooltipPosition="before"
tooltip="annotation-actions.accept-recommendation.label"
icon="red:check-alt"
>
<redaction-annotation-icon [type]="'rhombus'" [label]="'S'" [color]="dictionaryColor"></redaction-annotation-icon>
<div [translate]="'annotation-actions.remove-annotation.remove-from-dict'"></div>
</div>
<div
(click)="annotationActionsService.suggestRemoveAnnotation($event, annotation, false, annotationsChanged)"
mat-menu-item
*ngIf="annotationPermissions.canRemoveOrSuggestToRemoveOnlyHere"
>
<redaction-annotation-icon [type]="'rhombus'" [label]="'S'" [color]="suggestionColor"></redaction-annotation-icon>
<div translate="annotation-actions.remove-annotation.only-here"></div>
</div>
</redaction-circle-button>
<div
(click)="annotationActionsService.markAsFalsePositive($event, annotation, annotationsChanged)"
mat-menu-item
*ngIf="annotationPermissions.canMarkAsFalsePositive"
<redaction-circle-button
(action)="annotationActionsService.acceptSuggestion($event, annotation, annotationsChanged)"
type="dark-bg"
*ngIf="annotationPermissions.canAcceptSuggestion"
tooltipPosition="before"
tooltip="annotation-actions.accept-suggestion.label"
icon="red:check-alt"
>
<mat-icon svgIcon="red:thumb-down" class="false-positive-icon"></mat-icon>
<div translate="annotation-actions.remove-annotation.false-positive"></div>
</div>
</mat-menu>
</div>
</redaction-circle-button>
<redaction-circle-button
(action)="annotationActionsService.undoDirectAction($event, annotation, annotationsChanged)"
*ngIf="annotationPermissions.canUndo"
type="dark-bg"
icon="red:undo"
tooltipPosition="before"
tooltip="annotation-actions.undo"
>
</redaction-circle-button>
<redaction-circle-button
(action)="hideAnnotation($event)"
*ngIf="annotation.isImage && viewerAnnotation?.isVisible()"
type="dark-bg"
icon="red:visibility-off"
tooltipPosition="before"
tooltip="annotation-actions.hide"
>
</redaction-circle-button>
<redaction-circle-button
(action)="showAnnotation($event)"
*ngIf="annotation.isImage && !viewerAnnotation?.isVisible()"
type="dark-bg"
icon="red:visibility"
tooltipPosition="before"
tooltip="annotation-actions.show"
>
</redaction-circle-button>
<redaction-circle-button
(action)="annotationActionsService.rejectSuggestion($event, annotation, annotationsChanged)"
type="dark-bg"
icon="red:close"
*ngIf="annotationPermissions.canRejectSuggestion"
tooltipPosition="before"
tooltip="annotation-actions.reject-suggestion"
>
</redaction-circle-button>
<redaction-circle-button
(action)="annotationActionsService.suggestRemoveAnnotation($event, annotation, false, annotationsChanged)"
type="dark-bg"
icon="red:trash"
*ngIf="annotationPermissions.canRemoveOrSuggestToRemoveOnlyHere && !annotationPermissions.canPerformMultipleRemoveActions"
tooltipPosition="before"
tooltip="annotation-actions.suggest-remove-annotation"
>
</redaction-circle-button>
<redaction-circle-button
*ngIf="annotationPermissions.canPerformMultipleRemoveActions"
(action)="openMenu($event)"
[class.active]="menuOpen"
[matMenuTriggerFor]="menu"
tooltipPosition="before"
tooltip="annotation-actions.suggest-remove-annotation"
type="dark-bg"
icon="red:trash"
>
</redaction-circle-button>
<mat-menu #menu="matMenu" (closed)="onMenuClosed()" xPosition="before">
<div
(click)="annotationActionsService.suggestRemoveAnnotation($event, annotation, true, annotationsChanged)"
mat-menu-item
*ngIf="annotationPermissions.canRemoveOrSuggestToRemoveFromDictionary"
>
<redaction-annotation-icon [type]="'rhombus'" [label]="'S'" [color]="dictionaryColor"></redaction-annotation-icon>
<div [translate]="'annotation-actions.remove-annotation.remove-from-dict'"></div>
</div>
<div
(click)="annotationActionsService.suggestRemoveAnnotation($event, annotation, false, annotationsChanged)"
mat-menu-item
*ngIf="annotationPermissions.canRemoveOrSuggestToRemoveOnlyHere"
>
<redaction-annotation-icon [type]="'rhombus'" [label]="'S'" [color]="suggestionColor"></redaction-annotation-icon>
<div translate="annotation-actions.remove-annotation.only-here"></div>
</div>
<div
(click)="annotationActionsService.markAsFalsePositive($event, annotation, annotationsChanged)"
mat-menu-item
*ngIf="annotationPermissions.canMarkAsFalsePositive"
>
<mat-icon svgIcon="red:thumb-down" class="false-positive-icon"></mat-icon>
<div translate="annotation-actions.remove-annotation.false-positive"></div>
</div>
</mat-menu>
</div>
</redaction-hidden-action>

View File

@ -61,4 +61,8 @@ export class AnnotationActionsComponent implements OnInit {
get dictionaryColor() {
return this.appStateService.getDictionaryColor('suggestion-add-dictionary');
}
logAnnotation(annotation: AnnotationWrapper) {
console.log(annotation);
}
}

View File

@ -192,6 +192,7 @@
(filtersChanged)="filtersChanged($event)"
[chevron]="true"
[filterTemplate]="annotationFilterTemplate"
[actionsTemplate]="annotationFilterActionTemplate"
[filters]="annotationFilters"
></redaction-filter>
</div>
@ -286,3 +287,14 @@
{{ filter.key | humanize: false }}
</ng-container>
</ng-template>
<ng-template #annotationFilterActionTemplate let-filter="filter">
<ng-container *ngIf="filter.key === 'skipped'">
<redaction-circle-button
[icon]="areIgnoresVisible ? 'red:visibility' : 'red:visibility-off'"
(action)="toggleIgnoresVisible($event)"
class="skipped-toggle-button"
>
</redaction-circle-button>
</ng-container>
</ng-template>

View File

@ -166,3 +166,10 @@ redaction-dictionary-annotation-icon {
.ml-8 {
margin-left: 8px;
}
.skipped-toggle-button {
position: absolute;
right: 0;
justify-content: center;
align-items: center;
}

View File

@ -170,6 +170,10 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
return this.fileData?.redactionChangeLog?.redactionLogEntry?.length > 0;
}
get ignoreColor() {
return this.appStateService.getDictionaryColor('skipped');
}
ngOnInit(): void {
document.documentElement.addEventListener('fullscreenchange', (event) => {
if (!document.fullscreenElement) {
@ -548,6 +552,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
this.fileData.manualRedactions = manualRedactions;
this._rebuildFilters();
this._annotationDrawService.drawAnnotations(this._instance, this.annotationData.allAnnotations);
this._handleIgnoreAnnotationsDrawing();
});
}
@ -660,6 +665,11 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
}
}
switchView($event: MatButtonToggleChange) {
this.viewMode = $event.value;
this.updateViewMode();
}
// <!-- Dev Mode Features-->
async openSSRFilePreview() {
window.open(`/pdf-preview/${this.projectId}/${this.fileId}`, '_blank');
@ -678,8 +688,25 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
}
// <!-- End Dev Mode Features-->
switchView($event: MatButtonToggleChange) {
this.viewMode = $event.value;
this.updateViewMode();
areIgnoresVisible: boolean = false;
toggleIgnoresVisible($event) {
$event.stopPropagation();
$event.preventDefault();
this.areIgnoresVisible = !this.areIgnoresVisible;
this._handleIgnoreAnnotationsDrawing();
return false;
}
private _handleIgnoreAnnotationsDrawing() {
const allAnnotations = this._instance.annotManager.getAnnotationsList();
const ignoreAnnotations = allAnnotations.filter((a) => a.getCustomData('skipped'));
if (this.areIgnoresVisible) {
this._instance.annotManager.hideAnnotations(ignoreAnnotations);
} else {
this._instance.annotManager.showAnnotations(ignoreAnnotations);
}
}
}

View File

@ -10,7 +10,7 @@ export class AnnotationWrapper {
| 'suggestion-remove-dictionary'
| 'suggestion-add'
| 'suggestion-remove'
| 'ignore'
| 'skipped'
| 'redaction'
| 'manual-redaction'
| 'recommendation'
@ -49,7 +49,8 @@ export class AnnotationWrapper {
this.superType === 'suggestion-add-dictionary' ||
this.superType === 'suggestion-remove-dictionary' ||
this.superType === 'suggestion-add' ||
this.superType === 'suggestion-remove'
this.superType === 'suggestion-remove' ||
this.superType === 'skipped'
);
}
@ -74,11 +75,11 @@ export class AnnotationWrapper {
}
get isSuperTypeBasedColor() {
return this.isIgnored || this.isSuggestion || this.isReadyForAnalysis || this.isDeclinedSuggestion;
return this.isSkipped || this.isSuggestion || this.isReadyForAnalysis || this.isDeclinedSuggestion;
}
get isIgnored() {
return this.superType === 'ignore';
get isSkipped() {
return this.superType === 'skipped';
}
get isImage() {
@ -86,17 +87,13 @@ export class AnnotationWrapper {
}
get isFalsePositive() {
return this.dictionary === 'false_positive' && (this.superType === 'ignore' || this.superType === 'hint' || this.superType === 'redaction');
return this.dictionary === 'false_positive' && (this.superType === 'skipped' || this.superType === 'hint' || this.superType === 'redaction');
}
get isManualRedaction() {
return this.superType === 'manual-redaction';
}
get isRedactedOrIgnored() {
return this.superType === 'ignore' || this.superType === 'redaction';
}
get isDeclinedSuggestion() {
return this.superType === 'declined-suggestion';
}
@ -192,7 +189,7 @@ export class AnnotationWrapper {
annotationWrapper.superType = 'recommendation';
return;
} else {
annotationWrapper.superType = 'ignore';
annotationWrapper.superType = 'skipped';
return;
}
}
@ -234,7 +231,7 @@ export class AnnotationWrapper {
}
if (!annotationWrapper.superType) {
annotationWrapper.superType = annotationWrapper.redaction ? 'redaction' : annotationWrapper.hint ? 'hint' : 'ignore';
annotationWrapper.superType = annotationWrapper.redaction ? 'redaction' : annotationWrapper.hint ? 'hint' : 'skipped';
}
}

View File

@ -39,7 +39,7 @@ export class FileDataModel {
if (!areDevFeaturesEnabled) {
allAnnotations = allAnnotations.filter((annotation) => {
return !annotation.isIgnored && !annotation.isFalsePositive;
return !annotation.isFalsePositive;
});
}

View File

@ -86,9 +86,10 @@ export class AnnotationDrawService {
highlight.Hidden = annotationWrapper.isChangeLogRemoved;
highlight.setCustomData('redaction', annotationWrapper.isRedacted);
highlight.setCustomData('skipped', annotationWrapper.isSkipped);
highlight.setCustomData('changeLog', annotationWrapper.isChangeLogEntry);
highlight.setCustomData('changeLogRemoved', annotationWrapper.isChangeLogRemoved);
highlight.setCustomData('redactionColor', this.getColor(activeViewer, 'ignore', 'ignore'));
highlight.setCustomData('redactionColor', this.getColor(activeViewer, 'skipped', 'skipped'));
highlight.setCustomData('annotationColor', this.getColor(activeViewer, annotationWrapper.superType, annotationWrapper.dictionary));
return highlight;
@ -102,7 +103,7 @@ export class AnnotationDrawService {
case 'recommendation':
color = this._appStateService.getDictionaryColor(dictionary);
break;
case 'ignore':
case 'skipped':
color = this._appStateService.getDictionaryColor(superType);
break;
default:

View File

@ -103,7 +103,7 @@ export class AnnotationProcessingService {
hint: 0,
redaction: 0,
request: 0,
ignore: 0
skipped: 0
};
}
obj[pageNumber].annotations.push(annotation);

View File

@ -522,9 +522,9 @@ export class AppStateService {
virtual: true
};
dictionaryData['ignore'] = {
dictionaryData['skipped'] = {
hexColor: colors.notRedacted,
type: 'ignore',
type: 'skipped',
virtual: true
};
dictionaryData['default'] = {

View File

@ -433,7 +433,7 @@
"active": "Aktiv",
"archived": "Archiviert",
"hint": "Hinweis",
"ignore": "Ignorieren",
"skipped": "Ignorieren",
"redaction": "Redaktion",
"comment": "Kommentar",
"suggestion": "Redaktionsvorschlag",
@ -478,7 +478,7 @@
"suggestion-remove-dictionary": "Vorgeschlagene Wörterbuchentfernung",
"suggestion-add": "Vorgeschlagene Redaktion",
"suggestion-remove": "Vorgeschlagene Redaktionsentfernung",
"ignore": "Ignorieren",
"skipped": "Ignorieren",
"hint": "Hinweis",
"redaction": "Redaktion",
"manual-redaction": "Manuelle Redaktion",

View File

@ -443,7 +443,7 @@
"active": "Active",
"archived": "Archived",
"hint": "Hint",
"ignore": "Ignore",
"skipped": "Skipped",
"redaction": "Redaction",
"comment": "Comment",
"suggestion": "Suggestion for redaction",
@ -490,7 +490,7 @@
"suggestion-remove-dictionary": "Suggested dictionary removal",
"suggestion-add": "Suggested redaction",
"suggestion-remove": "Suggested redaction removal",
"ignore": "Ignore",
"skipped": "Skipped",
"hint": "Hint",
"redaction": "Redaction",
"manual-redaction": "Manual Redaction",