RED-4416: Annotation colors
This commit is contained in:
parent
80cef8bad6
commit
d9435b8b4d
@ -1,6 +1,16 @@
|
||||
import { annotationTypesTranslations, SuggestionAddFalsePositive } from '@translations/annotation-types-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { Highlight, IComment, IManualChange, IPoint, IRectangle, LogEntryStatus, ManualRedactionType } from '@red/domain';
|
||||
import {
|
||||
AnnotationIconType,
|
||||
Dictionary,
|
||||
Highlight,
|
||||
IComment,
|
||||
IManualChange,
|
||||
IPoint,
|
||||
IRectangle,
|
||||
LogEntryStatus,
|
||||
ManualRedactionType,
|
||||
} from '@red/domain';
|
||||
import { RedactionLogEntry } from '@models/file/redaction-log.entry';
|
||||
import {
|
||||
FalsePositiveSuperTypes,
|
||||
@ -10,7 +20,7 @@ import {
|
||||
SuperType,
|
||||
SuperTypes,
|
||||
} from '@models/file/super-types';
|
||||
import { IListable, List } from '@iqser/common-ui';
|
||||
import { IListable, KeysOf, List } from '@iqser/common-ui';
|
||||
|
||||
export class AnnotationWrapper implements IListable, Record<string, unknown> {
|
||||
[x: string]: unknown;
|
||||
@ -91,6 +101,10 @@ export class AnnotationWrapper implements IListable, Record<string, unknown> {
|
||||
return this.isSuggestion || this.isDeclinedSuggestion;
|
||||
}
|
||||
|
||||
get colorKey(): KeysOf<Dictionary> {
|
||||
return this.isSkipped ? 'skippedHexColor' : this.isRecommendation ? 'recommendationHexColor' : 'hexColor';
|
||||
}
|
||||
|
||||
get isSkipped() {
|
||||
return this.superType === SuperTypes.Skipped;
|
||||
}
|
||||
@ -139,6 +153,10 @@ export class AnnotationWrapper implements IListable, Record<string, unknown> {
|
||||
return this.superType === SuperTypes.TextHighlight;
|
||||
}
|
||||
|
||||
get iconShape(): AnnotationIconType {
|
||||
return this.isRecommendation ? 'hexagon' : this.isHint ? 'circle' : this.isSuggestion ? 'rhombus' : 'square';
|
||||
}
|
||||
|
||||
get isIgnoredHint() {
|
||||
return this.superType === SuperTypes.IgnoredHint;
|
||||
}
|
||||
|
||||
@ -83,7 +83,11 @@
|
||||
</div>
|
||||
|
||||
<div class="cell center">
|
||||
<redaction-annotation-icon [dictionary]="dict" [type]="dict.hint ? 'circle' : 'square'"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
[color]="dict.hexColor"
|
||||
[label]="dict.label.charAt(0)"
|
||||
[type]="dict.hint ? 'circle' : 'square'"
|
||||
></redaction-annotation-icon>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
|
||||
@ -19,10 +19,6 @@
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
redaction-dictionary-annotation-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
redaction-dictionary-manager {
|
||||
|
||||
@ -11,7 +11,16 @@ import {
|
||||
TableColumnConfig,
|
||||
WorkflowConfig,
|
||||
} from '@iqser/common-ui';
|
||||
import { Dossier, File, IFileAttributeConfig, ProcessingType, StatusSorter, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
|
||||
import {
|
||||
AnnotationShapeMap,
|
||||
Dossier,
|
||||
File,
|
||||
IFileAttributeConfig,
|
||||
ProcessingType,
|
||||
StatusSorter,
|
||||
WorkflowFileStatus,
|
||||
WorkflowFileStatuses,
|
||||
} from '@red/domain';
|
||||
import { workflowFileStatusTranslations } from '@translations/file-status-translations';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
@ -277,6 +286,7 @@ export class ConfigService {
|
||||
new NestedFilter({
|
||||
id: item,
|
||||
label: workloadTranslations[item],
|
||||
metadata: { shape: AnnotationShapeMap[item] },
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Injectable, TemplateRef } from '@angular/core';
|
||||
import { ButtonConfig, IFilterGroup, INestedFilter, keyChecker, NestedFilter, TableColumnConfig } from '@iqser/common-ui';
|
||||
import { Dossier, DossierTemplate, StatusSorter, User, WorkflowFileStatus } from '@red/domain';
|
||||
import { AnnotationShapeMap, Dossier, DossierTemplate, StatusSorter, User, WorkflowFileStatus } from '@red/domain';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
@ -145,6 +145,7 @@ export class ConfigService {
|
||||
new NestedFilter({
|
||||
id: type,
|
||||
label: workloadTranslations[type],
|
||||
metadata: { shape: AnnotationShapeMap[type] },
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@ -32,12 +32,17 @@ export class TypeAnnotationIconComponent implements OnChanges {
|
||||
this.color = this.annotation.color;
|
||||
} else {
|
||||
const type = this.annotation.isSuperTypeBasedColor ? this.annotation.superType : this.annotation.type;
|
||||
this.color = this._dictionariesMapService.getDictionaryColor(
|
||||
type,
|
||||
this._dossierTemplateId,
|
||||
isRecommendation,
|
||||
isSkipped || isIgnoredHint,
|
||||
);
|
||||
if (type === 'dossier_redaction') {
|
||||
this.color = this.screenStateService.dossierDictionary[this.annotation.colorKey] as string;
|
||||
} else {
|
||||
// todo: use annotation.colorKey
|
||||
this.color = this._dictionariesMapService.getDictionaryColor(
|
||||
type,
|
||||
this._dossierTemplateId,
|
||||
isRecommendation,
|
||||
isSkipped || isIgnoredHint,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
this.type =
|
||||
|
||||
@ -101,18 +101,5 @@
|
||||
</ng-template>
|
||||
|
||||
<ng-template #annotationFilterTemplate let-filter="filter">
|
||||
<redaction-type-filter
|
||||
*ngIf="filter.topLevelFilter"
|
||||
[dossierTemplateId]="state.dossierTemplateId"
|
||||
[filter]="filter"
|
||||
></redaction-type-filter>
|
||||
|
||||
<ng-container *ngIf="!filter.topLevelFilter">
|
||||
<redaction-dictionary-annotation-icon
|
||||
[dictionaryKey]="filter.id"
|
||||
[dossierTemplateId]="state.dossierTemplateId"
|
||||
></redaction-dictionary-annotation-icon>
|
||||
|
||||
{{ filter.label }}
|
||||
</ng-container>
|
||||
<redaction-type-filter [dossierTemplateId]="state.dossierTemplateId" [filter]="filter"></redaction-type-filter>
|
||||
</ng-template>
|
||||
|
||||
@ -53,10 +53,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
::ng-deep redaction-dictionary-annotation-icon {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.analysis-progress {
|
||||
padding: 12px 20px;
|
||||
max-width: 400px;
|
||||
|
||||
@ -194,7 +194,12 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._loadingService.start();
|
||||
this._annotationManager.hide(annotations);
|
||||
const highlights = await this._fileDataService.loadTextHighlights();
|
||||
await this._annotationDrawService.draw(highlights, this.state.dossierTemplateId, this._skippedService.hideSkipped);
|
||||
await this._annotationDrawService.draw(
|
||||
highlights,
|
||||
this.state.dossierTemplateId,
|
||||
this._skippedService.hideSkipped,
|
||||
this.state.dossierDictionary,
|
||||
);
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
@ -595,7 +600,12 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this._handleDeltaAnnotationFilters(currentFilters);
|
||||
}
|
||||
|
||||
await this._annotationDrawService.draw(newAnnotations, this.state.dossierTemplateId, this._skippedService.hideSkipped);
|
||||
await this._annotationDrawService.draw(
|
||||
newAnnotations,
|
||||
this.state.dossierTemplateId,
|
||||
this._skippedService.hideSkipped,
|
||||
this.state.dossierDictionary,
|
||||
);
|
||||
}
|
||||
|
||||
private _handleDeltaAnnotationFilters(currentFilters: NestedFilter[]) {
|
||||
|
||||
@ -235,7 +235,12 @@ export class AnnotationActionsService {
|
||||
annotationWrapper.resizing = false;
|
||||
|
||||
this._annotationManager.delete(annotationWrapper);
|
||||
await this._annotationDrawService.draw([annotationWrapper], this._state.dossierTemplateId, this._skippedService.hideSkipped);
|
||||
await this._annotationDrawService.draw(
|
||||
[annotationWrapper],
|
||||
this._state.dossierTemplateId,
|
||||
this._skippedService.hideSkipped,
|
||||
this._state.dossierDictionary,
|
||||
);
|
||||
this._annotationManager.deselect();
|
||||
await this._fileDataService.annotationsChanged();
|
||||
}
|
||||
@ -275,6 +280,7 @@ export class AnnotationActionsService {
|
||||
annotation.FillColor = this._annotationDrawService.getAndConvertColor(
|
||||
annotationWrapper.superType,
|
||||
dossierTemplateId,
|
||||
this._state.dossierDictionary,
|
||||
annotationWrapper.type,
|
||||
);
|
||||
annotation.StrokeColor = annotation.FillColor;
|
||||
|
||||
@ -65,27 +65,34 @@ export class AnnotationProcessingService {
|
||||
} else {
|
||||
// top level filter
|
||||
if (topLevelFilter) {
|
||||
this._createParentFilter(
|
||||
a.isHighlight ? a.filterKey : a.superType,
|
||||
filterMap,
|
||||
filters,
|
||||
a.isHighlight,
|
||||
a.isHighlight ? a.color : null,
|
||||
);
|
||||
this._createParentFilter(a.isHighlight ? a.filterKey : a.superType, filterMap, filters, a.isHighlight, {
|
||||
color: a.isHighlight ? a.color : null,
|
||||
shortLabel: a.isHighlight ? '' : null,
|
||||
shape: a.iconShape,
|
||||
});
|
||||
} else {
|
||||
let parentFilter = filterMap.get(a.superType);
|
||||
if (!parentFilter) {
|
||||
parentFilter = this._createParentFilter(a.superType, filterMap, filters);
|
||||
}
|
||||
|
||||
const dictionary =
|
||||
a.type === 'dossier_redaction'
|
||||
? this.#state.dossierDictionary
|
||||
: this.#dictionariesMapService.getDictionary(a.type, this.#state.dossierTemplateId);
|
||||
|
||||
if (!parentFilter) {
|
||||
parentFilter = this._createParentFilter(a.superType, filterMap, filters, false, {
|
||||
shape: a.iconShape,
|
||||
});
|
||||
}
|
||||
const childFilter: IFilter = {
|
||||
id: a.filterKey,
|
||||
label: dictionary.label,
|
||||
checked: false,
|
||||
matches: 1,
|
||||
metadata: {
|
||||
color: dictionary[a.colorKey],
|
||||
shape: a.iconShape,
|
||||
},
|
||||
skipTranslation: true,
|
||||
};
|
||||
filterMap.set(a.filterKey, childFilter);
|
||||
parentFilter.children.push(new Filter(childFilter));
|
||||
@ -154,7 +161,7 @@ export class AnnotationProcessingService {
|
||||
filterMap: Map<string, INestedFilter>,
|
||||
filters: INestedFilter[],
|
||||
skipTranslation = false,
|
||||
color?: string,
|
||||
metadata?: Record<string, any>,
|
||||
) {
|
||||
const filter: INestedFilter = new NestedFilter({
|
||||
id: key,
|
||||
@ -162,7 +169,7 @@ export class AnnotationProcessingService {
|
||||
matches: 1,
|
||||
label: skipTranslation ? key : annotationTypesTranslations[key],
|
||||
skipTranslation,
|
||||
color,
|
||||
metadata,
|
||||
});
|
||||
filterMap.set(key, filter);
|
||||
filters.push(filter);
|
||||
|
||||
@ -149,7 +149,12 @@ export class PdfProxyService {
|
||||
|
||||
private _configureElements() {
|
||||
const dossierTemplateId = this._state.dossierTemplateId;
|
||||
const color = this._annotationDrawService.getAndConvertColor(dossierTemplateId, dossierTemplateId, 'manual');
|
||||
const color = this._annotationDrawService.getAndConvertColor(
|
||||
dossierTemplateId,
|
||||
dossierTemplateId,
|
||||
this._state.dossierDictionary,
|
||||
'manual',
|
||||
);
|
||||
this._documentViewer.setRectangleToolStyles(color);
|
||||
}
|
||||
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Core } from '@pdftron/webviewer';
|
||||
import { hexToRgb } from '../../../utils';
|
||||
import { hexToRgb } from '@utils/functions';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { RedactionLogService } from '@services/files/redaction-log.service';
|
||||
|
||||
import { IRectangle, ISectionGrid, ISectionRectangle } from '@red/domain';
|
||||
import { Dictionary, IRectangle, ISectionGrid, ISectionRectangle } from '@red/domain';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
import { SuperTypes } from '@models/file/super-types';
|
||||
@ -32,16 +32,16 @@ export class AnnotationDrawService {
|
||||
private readonly _documentViewer: REDDocumentViewer,
|
||||
) {}
|
||||
|
||||
async draw(annotations: List<AnnotationWrapper>, dossierTemplateId: string, hideSkipped: boolean) {
|
||||
async draw(annotations: List<AnnotationWrapper>, dossierTemplateId: string, hideSkipped: boolean, dossierDictionary: Dictionary) {
|
||||
try {
|
||||
await this._draw(annotations, dossierTemplateId, hideSkipped);
|
||||
await this._draw(annotations, dossierTemplateId, hideSkipped, dossierDictionary);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
|
||||
getAndConvertColor(superType: string, dossierTemplateId: string, dictionary?: string) {
|
||||
return this.convertColor(this.#getColor(superType, dossierTemplateId, dictionary));
|
||||
getAndConvertColor(superType: string, dossierTemplateId: string, dossierDictionary: Dictionary, type?: string) {
|
||||
return this.convertColor(this.#getColor(superType, dossierTemplateId, type, dossierDictionary));
|
||||
}
|
||||
|
||||
convertColor(hexColor: string) {
|
||||
@ -64,31 +64,45 @@ export class AnnotationDrawService {
|
||||
return this._pdf.quad(x1, y1, x2, y2, x3, y3, x4, y4);
|
||||
}
|
||||
|
||||
#getColor(superType: string, dossierTemplateId: string, dictionary?: string) {
|
||||
#getColor(superType: string, dossierTemplateId: string, type: string, dossierDictionary: Dictionary) {
|
||||
let color: string;
|
||||
let dictionary: Dictionary;
|
||||
|
||||
if (type === 'dossier_redaction') {
|
||||
dictionary = dossierDictionary;
|
||||
} else {
|
||||
dictionary = this._dictionariesMapService.getDictionary(type, dossierTemplateId);
|
||||
}
|
||||
|
||||
switch (superType) {
|
||||
case SuperTypes.Hint:
|
||||
case SuperTypes.Redaction:
|
||||
color = this._dictionariesMapService.getDictionaryColor(dictionary, dossierTemplateId);
|
||||
color = dictionary.hexColor;
|
||||
break;
|
||||
case SuperTypes.Recommendation:
|
||||
color = this._dictionariesMapService.getDictionaryColor(dictionary, dossierTemplateId, true);
|
||||
color = dictionary.recommendationHexColor;
|
||||
break;
|
||||
case SuperTypes.Skipped:
|
||||
case SuperTypes.IgnoredHint:
|
||||
color = this._dictionariesMapService.getDictionaryColor(dictionary, dossierTemplateId, false, true);
|
||||
color = dictionary.skippedHexColor;
|
||||
break;
|
||||
default:
|
||||
color = this._dictionariesMapService.getDictionaryColor(superType, dossierTemplateId);
|
||||
color = dictionary.hexColor;
|
||||
break;
|
||||
}
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
private async _draw(annotationWrappers: List<AnnotationWrapper>, dossierTemplateId: string, hideSkipped: boolean) {
|
||||
private async _draw(
|
||||
annotationWrappers: List<AnnotationWrapper>,
|
||||
dossierTemplateId: string,
|
||||
hideSkipped: boolean,
|
||||
dossierDictionary: Dictionary,
|
||||
) {
|
||||
const totalPages = await firstValueFrom(this._pdf.totalPages$);
|
||||
const annotations = annotationWrappers
|
||||
.map(annotation => this._computeAnnotation(annotation, dossierTemplateId, hideSkipped, totalPages))
|
||||
.map(annotation => this._computeAnnotation(annotation, dossierTemplateId, hideSkipped, totalPages, dossierDictionary))
|
||||
.filterTruthy();
|
||||
const documentLoaded = await firstValueFrom(this._documentViewer.loaded$);
|
||||
if (!documentLoaded) {
|
||||
@ -100,22 +114,27 @@ export class AnnotationDrawService {
|
||||
const { dossierId, fileId } = this._pdf;
|
||||
const sectionsGrid$ = this._redactionLogService.getSectionGrid(dossierId, fileId);
|
||||
const sectionsGrid = await firstValueFrom(sectionsGrid$).catch(() => ({ rectanglesPerPage: {} }));
|
||||
await this._drawSections(sectionsGrid, dossierTemplateId);
|
||||
await this._drawSections(sectionsGrid, dossierTemplateId, dossierDictionary);
|
||||
}
|
||||
}
|
||||
|
||||
private async _drawSections(sectionGrid: ISectionGrid, dossierTemplateId: string) {
|
||||
private async _drawSections(sectionGrid: ISectionGrid, dossierTemplateId: string, dossierDictionary: Dictionary) {
|
||||
const sections: Core.Annotations.RectangleAnnotation[] = [];
|
||||
for (const page of Object.keys(sectionGrid.rectanglesPerPage)) {
|
||||
const sectionRectangles = sectionGrid.rectanglesPerPage[page];
|
||||
sectionRectangles.forEach(sectionRectangle => {
|
||||
sections.push(this._computeSection(dossierTemplateId, parseInt(page, 10), sectionRectangle));
|
||||
sections.push(this._computeSection(dossierTemplateId, parseInt(page, 10), sectionRectangle, dossierDictionary));
|
||||
});
|
||||
}
|
||||
await this._annotationManager.add(sections);
|
||||
}
|
||||
|
||||
private _computeSection(dossierTemplateId: string, pageNumber: number, sectionRectangle: ISectionRectangle) {
|
||||
private _computeSection(
|
||||
dossierTemplateId: string,
|
||||
pageNumber: number,
|
||||
sectionRectangle: ISectionRectangle,
|
||||
dossierDictionary: Dictionary,
|
||||
) {
|
||||
const rectangleAnnot = this._pdf.rectangle();
|
||||
const pageHeight = this._documentViewer.getHeight(pageNumber);
|
||||
const rectangle: IRectangle = {
|
||||
@ -130,13 +149,19 @@ export class AnnotationDrawService {
|
||||
rectangleAnnot.Width = rectangle.width + 2;
|
||||
rectangleAnnot.Height = rectangle.height + 2;
|
||||
rectangleAnnot.ReadOnly = true;
|
||||
rectangleAnnot.StrokeColor = this.getAndConvertColor('analysis', dossierTemplateId, 'analysis');
|
||||
rectangleAnnot.StrokeColor = this.getAndConvertColor('analysis', dossierTemplateId, dossierDictionary, 'analysis');
|
||||
rectangleAnnot.StrokeThickness = 1;
|
||||
|
||||
return rectangleAnnot;
|
||||
}
|
||||
|
||||
private _computeAnnotation(annotationWrapper: AnnotationWrapper, dossierTemplateId: string, hideSkipped: boolean, totalPages: number) {
|
||||
private _computeAnnotation(
|
||||
annotationWrapper: AnnotationWrapper,
|
||||
dossierTemplateId: string,
|
||||
hideSkipped: boolean,
|
||||
totalPages: number,
|
||||
dossierDictionary: Dictionary,
|
||||
) {
|
||||
const pageNumber = this._pdf.isCompare ? annotationWrapper.pageNumber * 2 - 1 : annotationWrapper.pageNumber;
|
||||
if (pageNumber > totalPages) {
|
||||
// skip imported annotations from files that have more pages than the current one
|
||||
@ -165,7 +190,12 @@ export class AnnotationDrawService {
|
||||
annotation.Opacity = annotationWrapper.isChangeLogRemoved ? DEFAULT_REMOVED_ANNOTATION_OPACITY : DEFAULT_TEXT_ANNOTATION_OPACITY;
|
||||
annotation.setContents(annotationWrapper.content);
|
||||
annotation.PageNumber = pageNumber;
|
||||
annotation.StrokeColor = this.getAndConvertColor(annotationWrapper.superType, dossierTemplateId, annotationWrapper.type);
|
||||
annotation.StrokeColor = this.getAndConvertColor(
|
||||
annotationWrapper.superType,
|
||||
dossierTemplateId,
|
||||
dossierDictionary,
|
||||
annotationWrapper.type,
|
||||
);
|
||||
annotation.Id = annotationWrapper.id;
|
||||
annotation.ReadOnly = true;
|
||||
|
||||
@ -180,10 +210,10 @@ export class AnnotationDrawService {
|
||||
annotation.setCustomData('changeLog', String(annotationWrapper.isChangeLogEntry));
|
||||
annotation.setCustomData('changeLogRemoved', String(annotationWrapper.isChangeLogRemoved));
|
||||
annotation.setCustomData('opacity', String(annotation.Opacity));
|
||||
annotation.setCustomData('redactionColor', String(this.#getColor('redaction', dossierTemplateId, 'preview')));
|
||||
annotation.setCustomData('redactionColor', String(this.#getColor('redaction', dossierTemplateId, 'preview', dossierDictionary)));
|
||||
annotation.setCustomData(
|
||||
'annotationColor',
|
||||
String(this.#getColor(annotationWrapper.superType, dossierTemplateId, annotationWrapper.type)),
|
||||
String(this.#getColor(annotationWrapper.superType, dossierTemplateId, annotationWrapper.type, dossierDictionary)),
|
||||
);
|
||||
|
||||
return annotation;
|
||||
|
||||
@ -1,10 +1,3 @@
|
||||
<div
|
||||
#icon
|
||||
[class.hint]="isHint"
|
||||
[class.none]="type === 'none'"
|
||||
[class.recommendation]="isRecommendation"
|
||||
[class.request]="isRequest"
|
||||
class="icon"
|
||||
>
|
||||
<span>{{ label || dictionary?.label?.charAt(0) }}</span>
|
||||
<div #icon [class]="'icon ' + type">
|
||||
<span>{{ label }}</span>
|
||||
</div>
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
background-color: var(--color);
|
||||
}
|
||||
|
||||
.request {
|
||||
.rhombus {
|
||||
transform: scale(0.8) rotate(45deg);
|
||||
|
||||
span {
|
||||
@ -23,7 +23,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
.recommendation {
|
||||
.hexagon {
|
||||
position: relative;
|
||||
width: 16px;
|
||||
height: 10px;
|
||||
@ -52,15 +52,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.hint,
|
||||
.skipped {
|
||||
.circle {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.skipped {
|
||||
background-color: var(--iqser-grey-5);
|
||||
}
|
||||
|
||||
.none {
|
||||
color: var(--iqser-accent);
|
||||
}
|
||||
|
||||
@ -1,36 +1,19 @@
|
||||
import { Component, ElementRef, Input, OnChanges, ViewChild } from '@angular/core';
|
||||
import { Dictionary } from '@red/domain';
|
||||
import { AnnotationIconType } from '@red/domain';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-annotation-icon',
|
||||
selector: 'redaction-annotation-icon [color] [type] [label]',
|
||||
templateUrl: './annotation-icon.component.html',
|
||||
styleUrls: ['./annotation-icon.component.scss'],
|
||||
})
|
||||
export class AnnotationIconComponent implements OnChanges {
|
||||
@Input() color: string;
|
||||
@Input() type: 'square' | 'rhombus' | 'circle' | 'hexagon' | 'none';
|
||||
@Input() type: AnnotationIconType;
|
||||
@Input() label: string;
|
||||
@Input() dictionary: Dictionary;
|
||||
|
||||
@ViewChild('icon', { static: true }) icon: ElementRef;
|
||||
|
||||
get isHint() {
|
||||
return this.type === 'circle' || this.dictionary?.type === 'hint';
|
||||
}
|
||||
|
||||
get isRequest() {
|
||||
return this.type === 'rhombus' || this.dictionary?.type === 'redaction';
|
||||
}
|
||||
|
||||
get isRecommendation() {
|
||||
return this.type === 'hexagon' || this.dictionary?.type === 'recommendation';
|
||||
}
|
||||
|
||||
get backgroundColor() {
|
||||
return this.color || this.dictionary?.hexColor;
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.icon.nativeElement.style.setProperty('--color', this.backgroundColor);
|
||||
this.icon.nativeElement.style.setProperty('--color', this.color);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1 +0,0 @@
|
||||
<redaction-annotation-icon [color]="color" [label]="label" [type]="type"></redaction-annotation-icon>
|
||||
@ -1,27 +0,0 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
|
||||
@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;
|
||||
@Input() dossierTemplateId: string;
|
||||
|
||||
color: string;
|
||||
label: string;
|
||||
type: 'square' | 'circle';
|
||||
|
||||
constructor(private readonly _dictionariesMapService: DictionariesMapService) {}
|
||||
|
||||
ngOnChanges(): void {
|
||||
if (this.dictionaryKey) {
|
||||
const dictionary = this._dictionariesMapService.getDictionary(this.dictionaryKey, this.dossierTemplateId);
|
||||
this.color = this._dictionariesMapService.getDictionaryColor(this.dictionaryKey, this.dossierTemplateId);
|
||||
this.type = dictionary.hint ? 'circle' : 'square';
|
||||
this.label = this.dictionaryKey[0].toUpperCase();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,67 +1,14 @@
|
||||
<ng-container *ngIf="!filter.icon">
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.id === 'redaction'"
|
||||
[color]="dictionaryColor"
|
||||
label="R"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.id === 'recommendation'"
|
||||
[color]="dictionaryColor"
|
||||
label="R"
|
||||
type="hexagon"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="filter.id === 'hint'" [color]="dictionaryColor" label="H" type="circle"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.id === 'manual-redaction'"
|
||||
[color]="dictionaryColor"
|
||||
label="M"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.id === 'skipped'"
|
||||
[color]="dictionaryColor"
|
||||
label="S"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.id === 'ignored-hint'"
|
||||
[color]="dictionaryColor"
|
||||
label="I"
|
||||
type="circle"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="isSuggestion(filter.id)"
|
||||
[color]="dictionaryColor"
|
||||
label="S"
|
||||
type="rhombus"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="needsAnalysis(filter.id)"
|
||||
[color]="dictionaryColor"
|
||||
label="A"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.id === 'declined-suggestion'"
|
||||
[color]="dictionaryColor"
|
||||
label="S"
|
||||
type="rhombus"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="filter.id === 'none'" color="transparent" label="-" type="none"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.id === 'updated'"
|
||||
[color]="dictionaryColor"
|
||||
label="U"
|
||||
type="square"
|
||||
></redaction-annotation-icon>
|
||||
<redaction-annotation-icon *ngIf="filter.id === 'image'" [color]="dictionaryColor" label="I" type="square"></redaction-annotation-icon>
|
||||
|
||||
<div *ngIf="filter.id === 'comment'">
|
||||
<mat-icon svgIcon="red:comment"></mat-icon>
|
||||
</div>
|
||||
|
||||
<redaction-annotation-icon *ngIf="filter.color" [color]="filter.color" [label]="''" type="square"></redaction-annotation-icon>
|
||||
<redaction-annotation-icon
|
||||
*ngIf="filter.id !== 'comment'"
|
||||
[color]="color"
|
||||
[label]="label"
|
||||
[type]="filter.metadata?.shape"
|
||||
></redaction-annotation-icon>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="filter.icon">
|
||||
|
||||
@ -1,35 +1,47 @@
|
||||
import { Component, Input, OnChanges } from '@angular/core';
|
||||
import { INestedFilter, Required } from '@iqser/common-ui';
|
||||
import { INestedFilter } from '@iqser/common-ui';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
import { SuperTypes } from '@models/file/super-types';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-type-filter',
|
||||
selector: 'redaction-type-filter [dossierTemplateId]',
|
||||
templateUrl: './type-filter.component.html',
|
||||
styleUrls: ['./type-filter.component.scss'],
|
||||
})
|
||||
export class TypeFilterComponent implements OnChanges {
|
||||
@Input() filter: INestedFilter;
|
||||
@Input() @Required() dossierTemplateId!: string;
|
||||
@Input() dossierTemplateId: string;
|
||||
@Input() dossierId: string;
|
||||
|
||||
dictionaryColor: string;
|
||||
label: string;
|
||||
color: string;
|
||||
|
||||
private _suggestionsKeys = [
|
||||
'suggestion-remove',
|
||||
private _suggestionsKeys: string[] = [
|
||||
SuperTypes.SuggestionRemove,
|
||||
SuperTypes.SuggestionForceRedaction,
|
||||
SuperTypes.SuggestionAdd,
|
||||
SuperTypes.SuggestionRemoveDictionary,
|
||||
SuperTypes.SuggestionAddDictionary,
|
||||
SuperTypes.DeclinedSuggestion,
|
||||
'suggestion',
|
||||
'suggestion-force-redaction',
|
||||
'suggestion-add',
|
||||
'suggestion-remove-dictionary',
|
||||
'suggestion-add-dictionary',
|
||||
];
|
||||
private _needsAnalysisKeys = ['add-dictionary', 'remove-only-here', 'change-legal-basis', 'analysis'];
|
||||
private _needsAnalysisKeys: string[] = ['remove-only-here', 'analysis'];
|
||||
|
||||
constructor(private readonly _dictionariesMapService: DictionariesMapService) {}
|
||||
|
||||
isSuggestion = (key: string) => this._suggestionsKeys.includes(key);
|
||||
|
||||
needsAnalysis = (key: string) => this._needsAnalysisKeys.includes(key);
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.dictionaryColor = this._dictionariesMapService.getDictionaryColor(this.filter.id, this.dossierTemplateId);
|
||||
this.label =
|
||||
this.filter.metadata?.shortLabel === ''
|
||||
? ''
|
||||
: this.filter.id === 'none'
|
||||
? '-'
|
||||
: this._needsAnalysisKeys.includes(this.filter.id)
|
||||
? 'A'
|
||||
: this._suggestionsKeys.includes(this.filter.id)
|
||||
? 'S'
|
||||
: this.filter.id.charAt(0);
|
||||
this.color = this.filter.metadata?.color || (this.filter.id === 'none' ? 'transparent' : this.dictionaryColor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,6 @@ import { IconsModule } from '../icons/icons.module';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { AnnotationIconComponent } from './components/annotation-icon/annotation-icon.component';
|
||||
import { DonutChartComponent } from './components/donut-chart/donut-chart.component';
|
||||
import { DictionaryAnnotationIconComponent } from './components/dictionary-annotation-icon/dictionary-annotation-icon.component';
|
||||
import { CommonUiModule } from '@iqser/common-ui';
|
||||
import { SelectComponent } from './components/select/select.component';
|
||||
import { NavigateLastDossiersScreenDirective } from './directives/navigate-last-dossiers-screen.directive';
|
||||
@ -46,7 +45,6 @@ const components = [
|
||||
PaginationComponent,
|
||||
AnnotationIconComponent,
|
||||
DonutChartComponent,
|
||||
DictionaryAnnotationIconComponent,
|
||||
SelectComponent,
|
||||
DictionaryManagerComponent,
|
||||
AssignUserDropdownComponent,
|
||||
|
||||
@ -13,6 +13,7 @@ export class DictionariesMapService extends EntitiesMapService<Dictionary, IDict
|
||||
return this.get(dossierTemplateId, type) || this.get(dossierTemplateId, 'default');
|
||||
}
|
||||
|
||||
// todo is this necessary?
|
||||
getDictionaryColor(type: string, dossierTemplateId: string, isRecommendation = false, isSkipped = false) {
|
||||
const defaultColor = '#CCCCCC';
|
||||
if (!this.get(dossierTemplateId)) {
|
||||
|
||||
@ -5,7 +5,7 @@ export class GlobalErrorHandler extends ErrorHandler {
|
||||
handleError(error: Error): void {
|
||||
const chunkFailedMessage = /Loading chunk [\d]+ failed/;
|
||||
console.write(error);
|
||||
if (error.message.includes('An error happened during access validation')) {
|
||||
if (error.message?.includes('An error happened during access validation')) {
|
||||
console.log('User is not authorized to access this page');
|
||||
}
|
||||
|
||||
|
||||
@ -16,3 +16,23 @@ export type ManualRedactionActions =
|
||||
| 'undo'
|
||||
| 'force-redaction'
|
||||
| 'request-force-redaction';
|
||||
|
||||
export const AnnotationIconTypes = {
|
||||
square: 'square',
|
||||
rhombus: 'rhombus',
|
||||
circle: 'circle',
|
||||
hexagon: 'hexagon',
|
||||
none: 'none',
|
||||
} as const;
|
||||
|
||||
export type AnnotationIconType = keyof typeof AnnotationIconTypes;
|
||||
|
||||
export const AnnotationShapeMap: Record<string, AnnotationIconType> = {
|
||||
analysis: AnnotationIconTypes.square,
|
||||
hint: AnnotationIconTypes.circle,
|
||||
redaction: AnnotationIconTypes.square,
|
||||
suggestion: AnnotationIconTypes.rhombus,
|
||||
updated: AnnotationIconTypes.square,
|
||||
image: AnnotationIconTypes.square,
|
||||
none: AnnotationIconTypes.none,
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user