annotation icon rework

This commit is contained in:
Timo Bejan 2020-11-11 12:05:18 +02:00
parent b962f08301
commit 0303b9e2c9
23 changed files with 178 additions and 70 deletions

View File

@ -74,6 +74,9 @@ import { ProjectListingEmptyComponent } from './screens/empty-states/project-lis
import { AnnotationActionsComponent } from './screens/file/annotation-actions/annotation-actions.component';
import { ProjectListingDetailsComponent } from './screens/project-listing-screen/project-listing-details/project-listing-details.component';
import { FileActionsComponent } from './common/file-actions/file-actions.component';
import { TypeAnnotationIconComponent } from './components/type-annotation-icon/type-annotation-icon.component';
import { TypeFilterComponent } from './components/type-filter/type-filter.component';
import { DictionaryAnnotationIconComponent } from './components/dictionary-annotation-icon/dictionary-annotation-icon.component';
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
@ -115,7 +118,10 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
AnnotationActionsComponent,
ProjectListingEmptyComponent,
ProjectListingDetailsComponent,
FileActionsComponent
FileActionsComponent,
TypeAnnotationIconComponent,
TypeFilterComponent,
DictionaryAnnotationIconComponent
],
imports: [
BrowserModule,

View File

@ -1,8 +1,3 @@
<div
[class.hint]="typeValue?.hint"
[class.request]="isSuggestionRequest"
[style.background-color]="color ? color : typeValue?.hexColor"
class="icon"
>
<span>{{ (typeValue?.type)[0] }}</span>
<div [class.hint]="type === 'circle'" [class.request]="type === 'rhombus'" [style.background-color]="color" class="icon">
<span>{{ label }}</span>
</div>

View File

@ -1,5 +1,4 @@
import { Component, Input, OnInit } from '@angular/core';
import { TypeValue } from '@redaction/red-ui-http';
import { Component, Input } from '@angular/core';
@Component({
selector: 'redaction-annotation-icon',
@ -7,14 +6,9 @@ import { TypeValue } from '@redaction/red-ui-http';
styleUrls: ['./annotation-icon.component.scss']
})
export class AnnotationIconComponent {
@Input() typeValue: TypeValue;
@Input() color: string;
@Input() type: 'square' | 'rhombus' | 'circle';
@Input() label: string;
constructor() {}
get isSuggestionRequest() {
return (
this.typeValue?.type === 'suggestion' || this.typeValue?.type === 'suggestion-remove'
);
}
}

View File

@ -0,0 +1 @@
<redaction-annotation-icon [color]="color" [type]="type" [label]="label"> </redaction-annotation-icon>

View File

@ -0,0 +1,27 @@
import { Component, Input, OnChanges } from '@angular/core';
import { AppStateService } from '../../state/app-state.service';
import { TypeValue } from '@redaction/red-ui-http';
@Component({
selector: 'redaction-dictionary-annotation-icon',
templateUrl: './dictionary-annotation-icon.component.html',
styleUrls: ['./dictionary-annotation-icon.component.scss']
})
export class DictionaryAnnotationIconComponent implements OnChanges {
@Input() dictionaryKey: string;
color: string;
label: string;
type: 'square' | 'circle';
constructor(private readonly _appStateService: AppStateService) {}
ngOnChanges(): void {
if (this.dictionaryKey) {
const typeValue: TypeValue = this._appStateService.getDictionaryTypeValue(this.dictionaryKey);
this.color = this._appStateService.getDictionaryColor(this.dictionaryKey);
this.type = typeValue.hint ? 'circle' : 'square';
this.label = this.dictionaryKey[0].toUpperCase();
}
}
}

View File

@ -0,0 +1 @@
<redaction-annotation-icon [color]="color" [type]="type" [label]="label"> </redaction-annotation-icon>

View File

@ -0,0 +1,32 @@
import { Component, Input, OnChanges } from '@angular/core';
import { AnnotationWrapper } from '../../screens/file/model/annotation.wrapper';
import { AppStateService } from '../../state/app-state.service';
@Component({
selector: 'redaction-type-annotation-icon',
templateUrl: './type-annotation-icon.component.html',
styleUrls: ['./type-annotation-icon.component.scss']
})
export class TypeAnnotationIconComponent implements OnChanges {
@Input() annotation: AnnotationWrapper;
label: string;
color: string;
type: 'square' | 'rhombus' | 'circle';
constructor(private _appStateService: AppStateService) {}
ngOnChanges(): void {
if (this.annotation) {
if (this.annotation.isSuggestion) {
this.color = this.annotation.modifyDictionary
? this._appStateService.getDictionaryColor('suggestion-dictionary')
: this._appStateService.getDictionaryColor('suggestion');
} else {
this.color = this._appStateService.getDictionaryColor(this.annotation.dictionary);
}
this.type = this.annotation.isSuggestion ? 'rhombus' : this.annotation.isRedactedOrIgnored ? 'square' : 'circle';
this.label = this.annotation.isSuggestion ? 'S' : this.annotation.isIgnored ? 'I' : this.annotation.dictionary[0].toUpperCase();
}
}
}

View File

@ -0,0 +1,6 @@
<redaction-annotation-icon *ngIf="filter.key === 'analysis'" type="square" label="A" color="#dd4d50"></redaction-annotation-icon>
<redaction-annotation-icon *ngIf="filter.key === 'redaction'" type="square" label="R" color="#283241"></redaction-annotation-icon>
<redaction-annotation-icon *ngIf="filter.key === 'hint'" type="round" label="H" color="#283241"></redaction-annotation-icon>
<redaction-annotation-icon *ngIf="filter.key === 'suggestion'" type="rhombus" label="S" [color]="suggestionColor"></redaction-annotation-icon>
<redaction-annotation-icon *ngIf="filter.key === 'suggestion-remove'" type="rhombus" label="S" [color]="suggestionColor"></redaction-annotation-icon>
{{ filter.label | translate }}

View File

@ -0,0 +1,6 @@
:host {
display: flex;
justify-content: center;
align-items: center;
gap: 4px;
}

View File

@ -0,0 +1,18 @@
import { Component, Input } from '@angular/core';
import { FilterModel } from '../../common/filter/model/filter.model';
import { AppStateService } from '../../state/app-state.service';
@Component({
selector: 'redaction-type-filter',
templateUrl: './type-filter.component.html',
styleUrls: ['./type-filter.component.scss']
})
export class TypeFilterComponent {
@Input() filter: FilterModel;
constructor(public appStateService: AppStateService) {}
get suggestionColor() {
return this.appStateService.getDictionaryColor('suggestion');
}
}

View File

@ -1,12 +1,6 @@
<div class="needs-work">
<redaction-annotation-icon *ngIf="reanalysisRequired()" [typeValue]="appStateService.getDictionaryTypeValue('analysis')"></redaction-annotation-icon>
<redaction-annotation-icon
*ngIf="needsWorkInput.hasRedactions"
[typeValue]="appStateService.getDictionaryTypeValue('redaction')"
></redaction-annotation-icon>
<redaction-annotation-icon *ngIf="needsWorkInput.hintsOnly" [typeValue]="appStateService.getDictionaryTypeValue('hint')"></redaction-annotation-icon>
<redaction-annotation-icon
*ngIf="needsWorkInput.hasRequests"
[typeValue]="appStateService.getDictionaryTypeValue('suggestion')"
></redaction-annotation-icon>
<redaction-annotation-icon *ngIf="reanalysisRequired()" type="square" label="A" color="#dd4d50"></redaction-annotation-icon>
<redaction-annotation-icon *ngIf="needsWorkInput.hasRedactions" type="square" label="R" color="#283241"></redaction-annotation-icon>
<redaction-annotation-icon *ngIf="needsWorkInput.hintsOnly" type="round" label="H" color="#283241"></redaction-annotation-icon>
<redaction-annotation-icon *ngIf="needsWorkInput.hasRequests" type="rhombus" label="S" [color]="suggestionColor"></redaction-annotation-icon>
</div>

View File

@ -23,4 +23,8 @@ export class NeedsWorkBadgeComponent implements OnInit {
return this.permissionsService.fileRequiresReanalysis(this.needsWorkInput);
}
}
get suggestionColor() {
return this.appStateService.getDictionaryColor('suggestion');
}
}

View File

@ -1,38 +1,47 @@
<div [class.visible]="menuType" *ngIf="canPerformAnnotationActions" class="annotation-actions">
<!-- <button-->
<!-- (click)="openMenu($event, 'APPROVE')"-->
<!-- *ngIf="canAcceptSuggestion"-->
<!-- [class.active]="menuType"-->
<!-- [matMenuTriggerFor]="menu"-->
<!-- class="confirm"-->
<!-- mat-icon-button-->
<!-- >-->
<!-- <mat-icon svgIcon="red:check-alt"></mat-icon>-->
<!-- </button>-->
<button
(click)="openMenu($event, 'APPROVE')"
*ngIf="canAcceptSuggestion"
[class.active]="menuType"
[matMenuTriggerFor]="menu"
class="confirm"
(click)="acceptSuggestion($event, annotation, annotation.modifyDictionary)"
*ngIf="!annotation.canUndo && (annotation.superType === 'suggestion' || annotation.superType === 'suggestion-remove')"
mat-icon-button
>
<mat-icon svgIcon="red:check-alt"></mat-icon>
</button>
<mat-menu #menu="matMenu" (closed)="onMenuClosed()" xPosition="before">
<ng-container *ngIf="menuType === 'APPROVE'">
<div (click)="acceptSuggestion($event, annotation, true)" mat-menu-item>
<redaction-annotation-icon [typeValue]="suggestionType" [color]="'#5B97DB'"></redaction-annotation-icon>
<div
[translate]="
annotation.superType === 'suggestion'
? 'file-preview.tabs.annotations.accept-suggestion.add-to-dict'
: 'file-preview.tabs.annotations.accept-suggestion.remove-from-dict'
"
></div>
</div>
<div (click)="acceptSuggestion($event, annotation, false)" mat-menu-item>
<redaction-annotation-icon [typeValue]="suggestionType"></redaction-annotation-icon>
<div translate="file-preview.tabs.annotations.accept-suggestion.only-here"></div>
</div>
</ng-container>
<!-- <ng-container *ngIf="menuType === 'APPROVE'">-->
<!-- <div (click)="acceptSuggestion($event, annotation, true)" mat-menu-item>-->
<!-- <redaction-annotation-icon [typeValue]="suggestionType" [color]="'#5B97DB'"></redaction-annotation-icon>-->
<!-- <div-->
<!-- [translate]="-->
<!-- annotation.superType === 'suggestion'-->
<!-- ? 'file-preview.tabs.annotations.accept-suggestion.add-to-dict'-->
<!-- : 'file-preview.tabs.annotations.accept-suggestion.remove-from-dict'-->
<!-- "-->
<!-- ></div>-->
<!-- </div>-->
<!-- <div (click)="acceptSuggestion($event, annotation, false)" mat-menu-item>-->
<!-- <redaction-annotation-icon [typeValue]="suggestionType"></redaction-annotation-icon>-->
<!-- <div translate="file-preview.tabs.annotations.accept-suggestion.only-here"></div>-->
<!-- </div>-->
<!-- </ng-container>-->
<ng-container *ngIf="menuType === 'SUGGEST-REMOVE'">
<div (click)="suggestRemoveAnnotation($event, annotation, true)" mat-menu-item>
<redaction-annotation-icon [typeValue]="suggestionType" [color]="'#5B97DB'"></redaction-annotation-icon>
<redaction-type-annotation-icon [annotation]="annotation"></redaction-type-annotation-icon>
<div [translate]="'file-preview.tabs.annotations.remove-annotation.remove-from-dict'"></div>
</div>
<div (click)="suggestRemoveAnnotation($event, annotation, false)" mat-menu-item>
<redaction-annotation-icon [typeValue]="suggestionType"></redaction-annotation-icon>
<redaction-type-annotation-icon [annotation]="annotation"></redaction-type-annotation-icon>
<div translate="file-preview.tabs.annotations.remove-annotation.only-here"></div>
</div>
</ng-container>

View File

@ -87,10 +87,7 @@
class="annotation"
>
<div class="details">
<redaction-annotation-icon
[color]="annotation.modifyDictionary ? '#5B97DB' : null"
[typeValue]="appStateService.getDictionaryTypeValueForAnnotation(annotation)"
></redaction-annotation-icon>
<redaction-type-annotation-icon [annotation]="annotation"></redaction-type-annotation-icon>
<div class="flex-1">
<div>
<strong>{{ annotation.typeLabel | translate }}</strong>
@ -120,8 +117,9 @@
<redaction-full-page-loading-indicator [message]="loadingMessage" [displayed]="!viewReady"></redaction-full-page-loading-indicator>
<ng-template #annotationFilterTemplate let-filter="filter">
<ng-container>
<redaction-annotation-icon [typeValue]="appStateService.getDictionaryTypeValue(filter.key)"></redaction-annotation-icon>
{{ filter.label ? (filter.label | translate) : (filter.key | humanize) }}
<redaction-type-filter *ngIf="isCategoryFilter(filter)" [filter]="filter"></redaction-type-filter>
<ng-container *ngIf="!isCategoryFilter(filter)">
<redaction-dictionary-annotation-icon [dictionaryKey]="filter.key"></redaction-dictionary-annotation-icon>
{{ filter.key | humanize }}
</ng-container>
</ng-template>

View File

@ -400,4 +400,8 @@ export class FilePreviewScreenComponent implements OnInit {
this.canPerformAnnotationActions = this.permissionsService.canPerformAnnotationActions();
await this.appStateService.reloadActiveProjectFiles();
}
isCategoryFilter(filter: FilterModel) {
return filter.filters && filter.filters.length > 0;
}
}

View File

@ -29,6 +29,18 @@ export class AnnotationWrapper {
redaction: boolean;
positions: Rectangle[];
get isIgnored() {
return this.superType === 'ignore';
}
get isRedactedOrIgnored() {
return this.superType === 'ignore' || this.superType === 'redaction';
}
get isSuggestion() {
return this.superType === 'suggestion' || this.superType === 'suggestion-remove';
}
static fromData(
user: UserWrapper,
dictionaryData: { [p: string]: TypeValue },

View File

@ -36,7 +36,9 @@ export class AnnotationDrawService {
switch (annotationWrapper.superType) {
case 'suggestion':
case 'suggestion-remove':
color = annotationWrapper.modifyDictionary ? '#5B97DB' : this._appStateService.getDictionaryColor(annotationWrapper.superType);
color = annotationWrapper.modifyDictionary
? this._appStateService.getDictionaryColor('suggestion-dictionary')
: this._appStateService.getDictionaryColor(annotationWrapper.superType);
break;
case 'hint':
case 'redaction':

View File

@ -192,8 +192,5 @@
<redaction-project-listing-empty *ngIf="!appStateService.hasProjects" (addProjectRequest)="openAddProjectDialog()"></redaction-project-listing-empty>
<ng-template #needsWorkTemplate let-filter="filter">
<ng-container>
<redaction-annotation-icon *ngIf="filter.key !== 'none'" [typeValue]="appStateService.getDictionaryTypeValue(filter.key)"></redaction-annotation-icon>
{{ filter.label | translate }}
</ng-container>
<redaction-type-filter [filter]="filter"></redaction-type-filter>
</ng-template>

View File

@ -52,8 +52,7 @@
<div class="mt-24 legend" *ngIf="hasFiles">
<div *ngFor="let filter of filters.needsWorkFilters" [class.active]="filter.checked" (click)="toggleFilter('needsWorkFilters', filter.key)">
<redaction-annotation-icon *ngIf="filter.key !== 'none'" [typeValue]="appStateService.getDictionaryTypeValue(filter.key)"></redaction-annotation-icon>
{{ 'filter.' + filter.key | translate }}
<redaction-type-filter [filter]="filter"></redaction-type-filter>
</div>
</div>

View File

@ -192,8 +192,5 @@
</section>
<ng-template #needsWorkTemplate let-filter="filter">
<ng-container>
<redaction-annotation-icon *ngIf="filter.key !== 'none'" [typeValue]="appStateService.getDictionaryTypeValue(filter.key)"></redaction-annotation-icon>
{{ filter.label | translate }}
</ng-container>
<redaction-type-filter [filter]="filter"></redaction-type-filter>
</ng-template>

View File

@ -104,8 +104,8 @@ export class AppStateService {
return this._reanalysisControllerService.reanalyzeProject(project.projectId);
}
getDictionaryColor(type: string) {
const color = this._dictionaryData[type].hexColor;
getDictionaryColor(type?: string) {
const color = this._dictionaryData[type]?.hexColor;
return color ? color : this._dictionaryData['default'].hexColor;
}
@ -370,6 +370,12 @@ export class AppStateService {
type: 'suggestion',
virtual: true
};
this._dictionaryData['suggestion-dictionary'] = {
hexColor: '#5B97DB',
type: 'suggestion-dictionary',
virtual: true
};
this._dictionaryData['suggestion-remove'] = {
hexColor: colors.requestRemove,
type: 'suggestion-remove',