Merge branch 'master' into VM/RED-9260
This commit is contained in:
commit
f1b7effe3a
@ -16,10 +16,7 @@ export const canForceRedaction = (annotation: AnnotationWrapper, canAddRedaction
|
||||
export const canAcceptRecommendation = (annotation: AnnotationWrapper) => annotation.isRecommendation && !annotation.pending;
|
||||
|
||||
export const canMarkAsFalsePositive = (annotation: AnnotationWrapper, annotationEntity: Dictionary) =>
|
||||
annotation.canBeMarkedAsFalsePositive &&
|
||||
!annotation.hasBeenForcedRedaction &&
|
||||
!annotation.hasBeenResizedLocally &&
|
||||
annotationEntity?.hasDictionary;
|
||||
annotation.canBeMarkedAsFalsePositive && !annotation.hasBeenResizedLocally && annotationEntity?.hasDictionary;
|
||||
|
||||
export const canRemoveOnlyHere = (annotation: AnnotationWrapper, canAddRedaction: boolean, autoAnalysisDisabled: boolean) =>
|
||||
canAddRedaction &&
|
||||
@ -30,7 +27,7 @@ export const canRemoveFromDictionary = (annotation: AnnotationWrapper, autoAnaly
|
||||
annotation.isModifyDictionary &&
|
||||
(annotation.isRedacted || annotation.isSkipped || annotation.isHint || (annotation.isIgnoredHint && !annotation.isRuleBased)) &&
|
||||
(autoAnalysisDisabled || !annotation.pending) &&
|
||||
[LogEntryEngines.DICTIONARY, LogEntryEngines.DOSSIER_DICTIONARY].some(engine => annotation.engines.includes(engine));
|
||||
annotation.isDictBased;
|
||||
|
||||
export const canRemoveRedaction = (annotation: AnnotationWrapper, permissions: AnnotationPermissions) =>
|
||||
(!annotation.isIgnoredHint || !annotation.isRuleBased) &&
|
||||
|
||||
@ -74,13 +74,17 @@ export class AnnotationWrapper implements IListable {
|
||||
}
|
||||
|
||||
get isDictBased() {
|
||||
return this.engines.includes(LogEntryEngines.DICTIONARY);
|
||||
return [LogEntryEngines.DICTIONARY, LogEntryEngines.DOSSIER_DICTIONARY].some(engine => this.engines.includes(engine));
|
||||
}
|
||||
|
||||
get isRedactedImageHint() {
|
||||
return this.IMAGE_HINT && this.superType === SuperTypes.Redaction;
|
||||
}
|
||||
|
||||
get isSkippedImageHint() {
|
||||
return this.IMAGE_HINT && this.superType === SuperTypes.Hint;
|
||||
}
|
||||
|
||||
get searchKey(): string {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { CircleButtonComponent, IconButtonComponent, IconButtonTypes, IqserDialogComponent, UploadFileComponent } from '@iqser/common-ui';
|
||||
import { CircleButtonComponent, IconButtonComponent, IqserDialogComponent, UploadFileComponent } from '@iqser/common-ui';
|
||||
import { FileAttributeEncodingTypes, IComponentMapping } from '@red/domain';
|
||||
import { FormBuilder, ReactiveFormsModule, UntypedFormGroup, Validators } from '@angular/forms';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
@ -22,6 +22,7 @@ interface DialogResult {
|
||||
file: Blob;
|
||||
encoding: string;
|
||||
delimiter: string;
|
||||
fileName?: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
@ -63,16 +64,18 @@ export class AddEditComponentMappingDialogComponent
|
||||
async ngOnInit() {
|
||||
if (this.data.mapping?.fileName) {
|
||||
this.activeFile = { name: this.data.mapping.fileName } as File;
|
||||
const file = await firstValueFrom(
|
||||
const fileContent = await firstValueFrom(
|
||||
this._componentMappingService.getComponentMappingFile(this.data.dossierTemplateId, this.data.mapping.id),
|
||||
);
|
||||
const file = new Blob([fileContent.body as Blob], { type: 'text/csv' });
|
||||
this.form.get('file').setValue(file);
|
||||
this.initialFormValue = this.form.getRawValue();
|
||||
}
|
||||
}
|
||||
|
||||
fileChanged(file: Blob) {
|
||||
fileChanged(file: File) {
|
||||
this.form.get('file').setValue(file);
|
||||
this.form.get('fileName').setValue(file?.name);
|
||||
}
|
||||
|
||||
save() {
|
||||
@ -83,6 +86,7 @@ export class AddEditComponentMappingDialogComponent
|
||||
return this._formBuilder.group({
|
||||
name: [this.data?.mapping?.name, Validators.required],
|
||||
file: [null, Validators.required],
|
||||
fileName: [this.data?.mapping?.fileName, Validators.required],
|
||||
encoding: this.encodingTypeOptions.find(e => e === this.data?.mapping?.encoding) ?? this.encodingTypeOptions[0],
|
||||
delimiter: [this.data?.mapping?.delimiter ?? ',', Validators.required],
|
||||
});
|
||||
|
||||
@ -44,6 +44,10 @@
|
||||
<span>{{ entity.numberOfLines }}</span>
|
||||
</div>
|
||||
|
||||
<div class="cell" [matTooltip]="entity.columnLabelsString" [matTooltipPosition]="'above'" [matTooltipClass]="'custom-tooltip'">
|
||||
<span class="ellipsis">{{ entity.columnLabelsString }}</span>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div *allow="roles.componentMappings.write; if: currentUser.isAdmin" class="action-buttons">
|
||||
<iqser-circle-button
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
.ellipsis {
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
::ng-deep .custom-tooltip {
|
||||
max-width: 300px;
|
||||
white-space: normal;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
@ -30,9 +30,11 @@ import { DossierTemplateActionsComponent } from '../../shared/components/dossier
|
||||
import { DossierTemplateBreadcrumbsComponent } from '../../shared/components/dossier-template-breadcrumbs/dossier-template-breadcrumbs.component';
|
||||
import { AddEditComponentMappingDialogComponent } from './add-edit-component-mapping-dialog/add-edit-component-mapping-dialog.component';
|
||||
import { download } from '@utils/file-download-utils';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
|
||||
@Component({
|
||||
templateUrl: './component-mappings-screen.component.html',
|
||||
styleUrls: ['./component-mappings-screen.component.scss'],
|
||||
providers: listingProvidersFactory(ComponentMappingsScreenComponent),
|
||||
standalone: true,
|
||||
imports: [
|
||||
@ -48,6 +50,7 @@ import { download } from '@utils/file-download-utils';
|
||||
InputWithActionComponent,
|
||||
IconButtonComponent,
|
||||
IqserAllowDirective,
|
||||
MatTooltip,
|
||||
],
|
||||
})
|
||||
export default class ComponentMappingsScreenComponent extends ListingComponent<ComponentMapping> implements OnInit {
|
||||
@ -61,6 +64,7 @@ export default class ComponentMappingsScreenComponent extends ListingComponent<C
|
||||
{ label: _('component-mappings-screen.table-col-names.name'), sortByKey: 'searchKey' },
|
||||
{ label: _('component-mappings-screen.table-col-names.version') },
|
||||
{ label: _('component-mappings-screen.table-col-names.number-of-lines') },
|
||||
{ label: _('component-mappings-screen.table-col-names.column-labels') },
|
||||
];
|
||||
readonly tableHeaderLabel = _('component-mappings-screen.table-header.title');
|
||||
|
||||
@ -95,8 +99,8 @@ export default class ComponentMappingsScreenComponent extends ListingComponent<C
|
||||
const result = await dialog.result();
|
||||
if (result) {
|
||||
this._loadingService.start();
|
||||
const { id, name, encoding, delimiter } = result;
|
||||
const newMapping = { id, name, encoding, delimiter };
|
||||
const { id, name, encoding, delimiter, fileName } = result;
|
||||
const newMapping = { id, name, encoding, delimiter, fileName };
|
||||
await firstValueFrom(
|
||||
this._componentMappingService.createUpdateComponentMapping(this.#dossierTemplateId, newMapping, result.file),
|
||||
);
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
</mat-checkbox>
|
||||
|
||||
<div class="iqser-input-group datepicker-wrapper">
|
||||
<ng-container *ngIf="hasValidFrom()">
|
||||
@if (hasValidFrom()) {
|
||||
<input
|
||||
(dateChange)="applyValidityIntervalConstraints()"
|
||||
[matDatepicker]="fromPicker"
|
||||
@ -44,7 +44,7 @@
|
||||
<mat-icon matDatepickerToggleIcon svgIcon="iqser:calendar"></mat-icon>
|
||||
</mat-datepicker-toggle>
|
||||
<mat-datepicker #fromPicker></mat-datepicker>
|
||||
</ng-container>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -53,7 +53,7 @@
|
||||
{{ 'add-edit-clone-dossier-template.form.valid-to' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="iqser-input-group datepicker-wrapper">
|
||||
<ng-container *ngIf="hasValidTo()">
|
||||
@if (hasValidTo()) {
|
||||
<input
|
||||
(dateChange)="applyValidityIntervalConstraints()"
|
||||
[matDatepicker]="toPicker"
|
||||
@ -64,77 +64,79 @@
|
||||
<mat-icon matDatepickerToggleIcon svgIcon="iqser:calendar"></mat-icon>
|
||||
</mat-datepicker-toggle>
|
||||
<mat-datepicker #toPicker></mat-datepicker>
|
||||
</ng-container>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!isDocumine" class="mt-24">
|
||||
<div class="heading">
|
||||
{{ 'add-edit-clone-dossier-template.form.apply-updates-default.heading' | translate }}
|
||||
</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="applyDictionaryUpdatesToAllDossiersByDefault">
|
||||
{{ 'add-edit-clone-dossier-template.form.apply-updates-default.description' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-24">
|
||||
<div class="heading mb-14">{{ 'download-includes' | translate }}</div>
|
||||
|
||||
<redaction-select
|
||||
[label]="
|
||||
'download-type.label'
|
||||
| translate
|
||||
: {
|
||||
length: form.controls['downloadFileTypes'].value.length
|
||||
}
|
||||
"
|
||||
[options]="downloadTypes"
|
||||
formControlName="downloadFileTypes"
|
||||
></redaction-select>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!isDocumine" class="mt-24">
|
||||
<div class="heading">
|
||||
{{ 'add-edit-clone-dossier-template.form.upload-settings.heading' | translate }}
|
||||
</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="ocrByDefault">
|
||||
{{ 'add-edit-clone-dossier-template.form.upload-settings.ocr-by-default' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="removeWatermark">
|
||||
{{ 'add-edit-clone-dossier-template.form.upload-settings.remove-watermark' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!isDocumine" class="mt-24 hidden-elements">
|
||||
<div class="heading">{{ 'add-edit-clone-dossier-template.form.hidden-text.heading' | translate }}</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="keepHiddenText">
|
||||
{{ 'add-edit-clone-dossier-template.form.hidden-text.title' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="info">{{ 'add-edit-clone-dossier-template.form.hidden-text.description' | translate }}</div>
|
||||
</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="keepImageMetadata">
|
||||
{{ 'add-edit-clone-dossier-template.form.image-metadata.title' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="info">{{ 'add-edit-clone-dossier-template.form.image-metadata.description' | translate }}</div>
|
||||
</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="keepOverlappingObjects">
|
||||
{{ 'add-edit-clone-dossier-template.form.overlapping-elements.title' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="info">
|
||||
{{ 'add-edit-clone-dossier-template.form.overlapping-elements.description' | translate }}
|
||||
@if (!isDocumine) {
|
||||
<div class="mt-24">
|
||||
<div class="heading">
|
||||
{{ 'add-edit-clone-dossier-template.form.apply-updates-default.heading' | translate }}
|
||||
</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="applyDictionaryUpdatesToAllDossiersByDefault">
|
||||
{{ 'add-edit-clone-dossier-template.form.apply-updates-default.description' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-24">
|
||||
<div class="heading mb-14">{{ 'download-includes' | translate }}</div>
|
||||
|
||||
<redaction-select
|
||||
[label]="
|
||||
'download-type.label'
|
||||
| translate
|
||||
: {
|
||||
length: form.controls['downloadFileTypes'].value.length,
|
||||
}
|
||||
"
|
||||
[options]="downloadTypes"
|
||||
formControlName="downloadFileTypes"
|
||||
></redaction-select>
|
||||
</div>
|
||||
|
||||
<div class="mt-24">
|
||||
<div class="heading">
|
||||
{{ 'add-edit-clone-dossier-template.form.upload-settings.heading' | translate }}
|
||||
</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="ocrByDefault">
|
||||
{{ 'add-edit-clone-dossier-template.form.upload-settings.ocr-by-default' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="removeWatermark">
|
||||
{{ 'add-edit-clone-dossier-template.form.upload-settings.remove-watermark' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-24 hidden-elements">
|
||||
<div class="heading">{{ 'add-edit-clone-dossier-template.form.hidden-text.heading' | translate }}</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="keepHiddenText">
|
||||
{{ 'add-edit-clone-dossier-template.form.hidden-text.title' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="info">{{ 'add-edit-clone-dossier-template.form.hidden-text.description' | translate }}</div>
|
||||
</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="keepImageMetadata">
|
||||
{{ 'add-edit-clone-dossier-template.form.image-metadata.title' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="info">{{ 'add-edit-clone-dossier-template.form.image-metadata.description' | translate }}</div>
|
||||
</div>
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="keepOverlappingObjects">
|
||||
{{ 'add-edit-clone-dossier-template.form.overlapping-elements.title' | translate }}
|
||||
</mat-checkbox>
|
||||
<div class="info">
|
||||
{{ 'add-edit-clone-dossier-template.form.overlapping-elements.description' | translate }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
|
||||
@ -26,6 +26,7 @@ import { NgIf } from '@angular/common';
|
||||
import { MatDatepickerModule } from '@angular/material/datepicker';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { SelectComponent } from '@shared/components/select/select.component';
|
||||
import { MatSuffix } from '@angular/material/form-field';
|
||||
|
||||
const downloadTypes = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map(type => ({
|
||||
key: type,
|
||||
@ -47,6 +48,7 @@ const downloadTypes = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map(t
|
||||
SelectComponent,
|
||||
IconButtonComponent,
|
||||
MatIcon,
|
||||
MatSuffix,
|
||||
],
|
||||
})
|
||||
export default class DossierTemplateInfoScreenComponent extends BaseFormComponent implements OnInit {
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { Component, input, Input } from '@angular/core';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { Dossier } from '@red/domain';
|
||||
import { Dossier, File } from '@red/domain';
|
||||
import { ComponentLogService } from '@services/files/component-log.service';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
@ -13,15 +13,18 @@ import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
|
||||
imports: [MatTooltip, TranslateModule, MatMenuTrigger, MatMenu, MatMenuItem],
|
||||
})
|
||||
export class DocumineExportComponent {
|
||||
@Input() dossier: Dossier;
|
||||
readonly dossier = input<Dossier>();
|
||||
readonly file = input<File>();
|
||||
|
||||
constructor(private readonly _componentLogService: ComponentLogService) {}
|
||||
|
||||
downloadComponentAsJSON() {
|
||||
return firstValueFrom(this._componentLogService.exportJSON(this.dossier.dossierTemplateId, this.dossier.dossierId));
|
||||
return firstValueFrom(
|
||||
this._componentLogService.exportJSON(this.dossier().dossierTemplateId, this.dossier().dossierId, this.file()),
|
||||
);
|
||||
}
|
||||
|
||||
async downloadComponentAsXML() {
|
||||
return firstValueFrom(this._componentLogService.exportXML(this.dossier.dossierTemplateId, this.dossier.dossierId));
|
||||
return firstValueFrom(this._componentLogService.exportXML(this.dossier().dossierTemplateId, this.dossier().dossierId, this.file()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,64 +1,76 @@
|
||||
<div (click)="select()" [ngClass]="{ selected: selected, editing: editing }" class="component-value">
|
||||
<div class="component">{{ entryLabel }}</div>
|
||||
<div *ngIf="!editing; else editValue" class="value">
|
||||
<div class="text">
|
||||
<span
|
||||
*ngFor="let componentValue of entry.componentValues"
|
||||
[innerHTML]="transformNewLines(componentValue.value ?? componentValue.originalValue)"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<iqser-circle-button
|
||||
(action)="edit()"
|
||||
*ngIf="canEdit"
|
||||
[tooltip]="'component-management.actions.edit' | translate"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
<div *ngIf="hasUpdatedValues && canEdit" class="changes-dot"></div>
|
||||
</div>
|
||||
</div>
|
||||
<mat-icon *ngIf="!editing" class="arrow-right" svgIcon="red:arrow-right"></mat-icon>
|
||||
</div>
|
||||
|
||||
<ng-template #editValue>
|
||||
<div (cdkDropListDropped)="drop($event)" cdkDropList>
|
||||
<div *ngFor="let value of entry.componentValues; let index = index" cdkDrag class="editing-value">
|
||||
<mat-icon cdkDragHandle class="draggable" svgIcon="red:draggable-dots"></mat-icon>
|
||||
<div class="iqser-input-group w-full">
|
||||
<textarea [id]="'value-input-' + index" [(ngModel)]="value.value" rows="1" type="text"></textarea>
|
||||
@if (!editing) {
|
||||
<div class="value">
|
||||
<div class="text">
|
||||
@for (componentValue of entry.componentValues; track componentValue) {
|
||||
<span [innerHTML]="transformNewLines(componentValue.value ?? componentValue.originalValue)"></span>
|
||||
}
|
||||
</div>
|
||||
<div class="actions">
|
||||
@if (canEdit) {
|
||||
<iqser-circle-button
|
||||
(action)="edit()"
|
||||
[tooltip]="'component-management.actions.edit' | translate"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
@if (hasUpdatedValues) {
|
||||
<div class="changes-dot"></div>
|
||||
}
|
||||
}
|
||||
</div>
|
||||
<iqser-circle-button
|
||||
(action)="removeValue(index)"
|
||||
[tooltip]="'component-management.actions.delete' | translate"
|
||||
class="remove-value"
|
||||
icon="iqser:trash"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="editing-actions">
|
||||
<iqser-icon-button
|
||||
(action)="save()"
|
||||
[disabled]="disabled"
|
||||
[label]="'component-management.actions.save' | translate"
|
||||
[type]="iconButtonTypes.primary"
|
||||
></iqser-icon-button>
|
||||
<div (click)="deselect($event)" class="all-caps-label cancel" translate="component-management.actions.cancel"></div>
|
||||
<div class="flex right">
|
||||
<iqser-circle-button
|
||||
(action)="undo()"
|
||||
*ngIf="hasUpdatedValues && canEdit"
|
||||
[tooltip]="'component-management.actions.undo' | translate"
|
||||
class="undo-value"
|
||||
icon="red:undo"
|
||||
showDot
|
||||
></iqser-circle-button>
|
||||
<iqser-circle-button
|
||||
(action)="add()"
|
||||
[tooltip]="'component-management.actions.add' | translate"
|
||||
class="add-value"
|
||||
icon="iqser:plus"
|
||||
></iqser-circle-button>
|
||||
} @else {
|
||||
<div (cdkDropListDropped)="drop($event)" cdkDropList>
|
||||
@for (value of entry.componentValues; track value) {
|
||||
<div cdkDrag class="editing-value">
|
||||
<mat-icon
|
||||
[class.hidden-button]="entry.componentValues.length === 1"
|
||||
cdkDragHandle
|
||||
class="draggable"
|
||||
svgIcon="red:draggable-dots"
|
||||
></mat-icon>
|
||||
<div class="iqser-input-group w-full">
|
||||
<textarea [id]="'value-input-' + $index" [(ngModel)]="value.value" rows="1" type="text"></textarea>
|
||||
</div>
|
||||
<iqser-circle-button
|
||||
(action)="removeValue($index)"
|
||||
[tooltip]="'component-management.actions.delete' | translate"
|
||||
[class.hidden-button]="entry.componentValues.length === 1"
|
||||
class="remove-value"
|
||||
icon="iqser:trash"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
<div class="editing-actions">
|
||||
<iqser-icon-button
|
||||
(action)="save()"
|
||||
[disabled]="disabled"
|
||||
[label]="'component-management.actions.save' | translate"
|
||||
[type]="iconButtonTypes.primary"
|
||||
></iqser-icon-button>
|
||||
<div (click)="deselect($event)" class="all-caps-label cancel" translate="component-management.actions.cancel"></div>
|
||||
<div class="flex right">
|
||||
@if (hasUpdatedValues && canEdit) {
|
||||
<iqser-circle-button
|
||||
(action)="undo()"
|
||||
[tooltip]="'component-management.actions.undo' | translate"
|
||||
class="undo-value"
|
||||
icon="red:undo"
|
||||
showDot
|
||||
></iqser-circle-button>
|
||||
}
|
||||
<iqser-circle-button
|
||||
(action)="add()"
|
||||
[tooltip]="'component-management.actions.add' | translate"
|
||||
class="add-value"
|
||||
icon="iqser:plus"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (!editing) {
|
||||
<mat-icon class="arrow-right" svgIcon="red:arrow-right"></mat-icon>
|
||||
}
|
||||
</div>
|
||||
|
||||
@ -59,7 +59,6 @@
|
||||
&:not(.header):hover,
|
||||
&.selected {
|
||||
background-color: var(--iqser-grey-8);
|
||||
border-left: 4px solid var(--iqser-primary);
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
|
||||
@ -67,18 +66,31 @@
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.component {
|
||||
margin-left: 22px;
|
||||
}
|
||||
.value {
|
||||
margin-right: 26px;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
.component {
|
||||
margin-left: 26px;
|
||||
}
|
||||
|
||||
.value {
|
||||
.actions {
|
||||
iqser-circle-button {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
border-left: 4px solid var(--iqser-primary);
|
||||
|
||||
.component {
|
||||
margin-left: 22px;
|
||||
}
|
||||
|
||||
.arrow-right {
|
||||
visibility: visible;
|
||||
@ -129,6 +141,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.hidden-button {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
::ng-deep .add-value {
|
||||
mat-icon {
|
||||
transform: scale(2);
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<div class="page-header">
|
||||
<div class="flex">
|
||||
<redaction-view-switch *ngIf="!isDocumine"></redaction-view-switch>
|
||||
<redaction-documine-export *ngIf="isDocumine" [dossier]="state.dossier()"></redaction-documine-export>
|
||||
<redaction-documine-export *ngIf="isDocumine" [dossier]="state.dossier()" [file]="state.file()"></redaction-documine-export>
|
||||
</div>
|
||||
|
||||
<!-- TODO: mode this file preview header to a separate component-->
|
||||
|
||||
@ -32,197 +32,212 @@
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
||||
<div class="right-content">
|
||||
<ng-container *ngIf="!isDocumine">
|
||||
<redaction-readonly-banner
|
||||
*ngIf="showAnalysisDisabledBanner; else readOnlyBanner"
|
||||
[customTranslation]="translations.analysisDisabled"
|
||||
></redaction-readonly-banner>
|
||||
<ng-template #readOnlyBanner>
|
||||
<redaction-readonly-banner *ngIf="state.isReadonly()"></redaction-readonly-banner>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
@if (displayedAnnotations$ | async; as annotations) {
|
||||
<div class="right-content">
|
||||
<ng-container *ngIf="!isDocumine">
|
||||
<redaction-readonly-banner
|
||||
*ngIf="showAnalysisDisabledBanner; else readOnlyBanner"
|
||||
[customTranslation]="translations.analysisDisabled"
|
||||
></redaction-readonly-banner>
|
||||
<ng-template #readOnlyBanner>
|
||||
<redaction-readonly-banner *ngIf="state.isReadonly()"></redaction-readonly-banner>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
|
||||
<div *ngIf="multiSelectService.active()" class="multi-select">
|
||||
<div class="selected-wrapper">
|
||||
<iqser-round-checkbox
|
||||
(click)="annotationManager.deselect()"
|
||||
[indeterminate]="listingService.areSomeSelected$ | async"
|
||||
type="with-bg"
|
||||
></iqser-round-checkbox>
|
||||
<div *ngIf="multiSelectService.active()" class="multi-select">
|
||||
<div class="selected-wrapper">
|
||||
<iqser-round-checkbox
|
||||
(click)="annotationManager.deselect()"
|
||||
[indeterminate]="listingService.areSomeSelected$ | async"
|
||||
type="with-bg"
|
||||
></iqser-round-checkbox>
|
||||
|
||||
<span class="all-caps-label">{{ listingService.selectedLength$ | async }} selected </span>
|
||||
<span class="all-caps-label">{{ listingService.selectedLength$ | async }} selected </span>
|
||||
|
||||
<redaction-annotation-actions
|
||||
*ngIf="listingService.areSomeSelected$ | async"
|
||||
[alwaysVisible]="true"
|
||||
[annotations]="listingService.selectedEntities$ | async"
|
||||
[canPerformAnnotationActions]="state.isWritable()"
|
||||
buttonType="primary"
|
||||
tooltipPosition="above"
|
||||
></redaction-annotation-actions>
|
||||
</div>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="multiSelectService.deactivate()"
|
||||
[tooltip]="'file-preview.tabs.multi-select.close' | translate"
|
||||
[type]="circleButtonTypes.primary"
|
||||
icon="iqser:close"
|
||||
tooltipPosition="before"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
|
||||
<div class="annotations-wrapper" [class.documine-direction]="isDocumine">
|
||||
<div [class.border-left]="isDocumine">
|
||||
<div
|
||||
#quickNavigation
|
||||
*ngIf="!(documentInfoService.shown() && isDocumine); else documentInfo"
|
||||
(keydown)="preventKeyDefault($event)"
|
||||
(keyup)="preventKeyDefault($event)"
|
||||
[class.active-panel]="pagesPanelActive"
|
||||
class="quick-navigation"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
(click)="scrollQuickNavFirst()"
|
||||
[class.disabled]="pdf.currentPage() === 1"
|
||||
[matTooltip]="'file-preview.quick-nav.jump-first' | translate"
|
||||
[class.documine-height]="isDocumine"
|
||||
class="jump"
|
||||
matTooltipPosition="above"
|
||||
>
|
||||
<mat-icon svgIcon="iqser:nav-first"></mat-icon>
|
||||
</div>
|
||||
|
||||
<redaction-pages (click)="pagesPanelActive = true" [pages]="displayedPages"></redaction-pages>
|
||||
|
||||
<div
|
||||
(click)="scrollQuickNavLast()"
|
||||
[class.disabled]="pdf.currentPage() === state.file()?.numberOfPages"
|
||||
[matTooltip]="'file-preview.quick-nav.jump-last' | translate"
|
||||
[class.documine-height]="isDocumine"
|
||||
class="jump"
|
||||
matTooltipPosition="above"
|
||||
>
|
||||
<mat-icon svgIcon="iqser:nav-last"></mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content" [class.documine-width]="isDocumine">
|
||||
<div
|
||||
*ngIf="!viewModeService.isEarmarks()"
|
||||
[attr.anotation-page-header]="pdf.currentPage()"
|
||||
[hidden]="excludedPagesService.shown()"
|
||||
class="workload-separator"
|
||||
>
|
||||
<span *ngIf="!!pdf.currentPage()" class="flex-align-items-center">
|
||||
<ng-container *ngIf="!isDocumine; else documineHeader">
|
||||
<iqser-circle-button
|
||||
(action)="excludedPagesService.toggle()"
|
||||
*ngIf="currentPageIsExcluded()"
|
||||
[size]="14"
|
||||
[tooltip]="'file-preview.excluded-from-redaction' | translate | capitalize"
|
||||
class="mr-10 primary"
|
||||
icon="red:exclude-pages"
|
||||
tooltipPosition="above"
|
||||
></iqser-circle-button>
|
||||
|
||||
<span
|
||||
[translateParams]="{ page: pdf.currentPage(), count: activeAnnotations.length }"
|
||||
[translate]="'page'"
|
||||
class="all-caps-label"
|
||||
></span>
|
||||
</ng-container>
|
||||
</span>
|
||||
|
||||
<div *ngIf="multiSelectService.active()">
|
||||
<div
|
||||
(click)="selectAllOnActivePage()"
|
||||
class="all-caps-label primary pointer"
|
||||
translate="file-preview.tabs.annotations.select-all"
|
||||
></div>
|
||||
<div
|
||||
(click)="deselectAllOnActivePage()"
|
||||
class="all-caps-label primary pointer"
|
||||
translate="file-preview.tabs.annotations.select-none"
|
||||
></div>
|
||||
</div>
|
||||
<redaction-annotation-actions
|
||||
*ngIf="listingService.areSomeSelected$ | async"
|
||||
[alwaysVisible]="true"
|
||||
[annotations]="listingService.selectedEntities$ | async"
|
||||
[canPerformAnnotationActions]="state.isWritable()"
|
||||
buttonType="primary"
|
||||
tooltipPosition="above"
|
||||
></redaction-annotation-actions>
|
||||
</div>
|
||||
|
||||
<div
|
||||
#annotationsElement
|
||||
(keydown)="preventKeyDefault($event)"
|
||||
(keyup)="preventKeyDefault($event)"
|
||||
[class.active-panel]="!pagesPanelActive"
|
||||
[hidden]="excludedPagesService.shown()"
|
||||
class="annotations"
|
||||
id="annotations-list"
|
||||
tabindex="1"
|
||||
>
|
||||
<ng-container *ngIf="pdf.currentPage() && !displayedAnnotations.get(pdf.currentPage())?.length">
|
||||
<iqser-empty-state
|
||||
[horizontalPadding]="24"
|
||||
[text]="'file-preview.no-data.title' | translate"
|
||||
[verticalPadding]="40"
|
||||
icon="iqser:document"
|
||||
<iqser-circle-button
|
||||
(action)="multiSelectService.deactivate()"
|
||||
[tooltip]="'file-preview.tabs.multi-select.close' | translate"
|
||||
[type]="circleButtonTypes.primary"
|
||||
icon="iqser:close"
|
||||
tooltipPosition="before"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
|
||||
<div class="annotations-wrapper" [class.documine-direction]="isDocumine">
|
||||
<div [class.border-left]="isDocumine">
|
||||
<div
|
||||
#quickNavigation
|
||||
*ngIf="!(documentInfoService.shown() && isDocumine); else documentInfo"
|
||||
(keydown)="preventKeyDefault($event)"
|
||||
(keyup)="preventKeyDefault($event)"
|
||||
[class.active-panel]="pagesPanelActive"
|
||||
class="quick-navigation"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
(click)="scrollQuickNavFirst()"
|
||||
[class.disabled]="pdf.currentPage() === 1"
|
||||
[matTooltip]="'file-preview.quick-nav.jump-first' | translate"
|
||||
[class.documine-height]="isDocumine"
|
||||
class="jump"
|
||||
matTooltipPosition="above"
|
||||
>
|
||||
<ng-container *ngIf="currentPageIsExcluded() && displayedPages.length">
|
||||
{{ 'file-preview.tabs.annotations.page-is' | translate }}
|
||||
<a
|
||||
(click)="excludedPagesService.toggle()"
|
||||
class="with-underline"
|
||||
translate="file-preview.excluded-from-redaction"
|
||||
></a
|
||||
>.
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="(fileDataService.allLength$ | async) === 0 || filterService.noAnnotationsFilterChecked">
|
||||
{{ 'file-preview.tabs.annotations.no-annotations' | translate }}
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="
|
||||
(fileDataService.allLength$ | async) > 0 &&
|
||||
displayedPages.length === 0 &&
|
||||
!filterService.noAnnotationsFilterChecked
|
||||
"
|
||||
>{{ 'file-preview.tabs.annotations.wrong-filters' | translate }}
|
||||
<a (click)="filterService.reset()" class="with-underline" translate="file-preview.tabs.annotations.reset"></a>
|
||||
{{ 'file-preview.tabs.annotations.the-filters' | translate }}
|
||||
</ng-container>
|
||||
</iqser-empty-state>
|
||||
|
||||
<div *ngIf="displayedPages.length" class="no-annotations-buttons-container mt-32">
|
||||
<iqser-icon-button
|
||||
(action)="jumpToPreviousWithAnnotations()"
|
||||
[disabled]="pdf.currentPage() <= displayedPages[0]"
|
||||
[label]="'file-preview.tabs.annotations.jump-to-previous' | translate"
|
||||
[type]="iconButtonTypes.dark"
|
||||
icon="iqser:nav-prev"
|
||||
></iqser-icon-button>
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="jumpToNextWithAnnotations()"
|
||||
[disabled]="pdf.currentPage() >= displayedPages[displayedPages.length - 1]"
|
||||
[label]="'file-preview.tabs.annotations.jump-to-next' | translate"
|
||||
[type]="iconButtonTypes.dark"
|
||||
class="mt-8"
|
||||
icon="iqser:nav-next"
|
||||
></iqser-icon-button>
|
||||
<mat-icon svgIcon="iqser:nav-first"></mat-icon>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<redaction-annotations-list
|
||||
(pagesPanelActive)="pagesPanelActive = $event"
|
||||
[annotations]="(displayedAnnotations$ | async)?.get(pdf.currentPage())"
|
||||
></redaction-annotations-list>
|
||||
<redaction-pages (click)="pagesPanelActive = true" [pages]="displayedPages"></redaction-pages>
|
||||
|
||||
<div
|
||||
(click)="scrollQuickNavLast()"
|
||||
[class.disabled]="pdf.currentPage() === state.file()?.numberOfPages"
|
||||
[matTooltip]="'file-preview.quick-nav.jump-last' | translate"
|
||||
[class.documine-height]="isDocumine"
|
||||
class="jump"
|
||||
matTooltipPosition="above"
|
||||
>
|
||||
<mat-icon svgIcon="iqser:nav-last"></mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<redaction-page-exclusion *ngIf="excludedPagesService.shown()"></redaction-page-exclusion>
|
||||
<div class="content" [class.documine-width]="isDocumine">
|
||||
@if (state.file().excluded && documentInfoService.hidden()) {
|
||||
<iqser-empty-state
|
||||
[horizontalPadding]="40"
|
||||
[text]="'file-preview.tabs.is-excluded' | translate"
|
||||
icon="red:needs-work"
|
||||
></iqser-empty-state>
|
||||
} @else {
|
||||
<div
|
||||
*ngIf="!viewModeService.isEarmarks()"
|
||||
[attr.anotation-page-header]="pdf.currentPage()"
|
||||
[hidden]="excludedPagesService.shown()"
|
||||
class="workload-separator"
|
||||
>
|
||||
<span *ngIf="!!pdf.currentPage()" class="flex-align-items-center">
|
||||
<ng-container *ngIf="!isDocumine; else documineHeader">
|
||||
<iqser-circle-button
|
||||
(action)="excludedPagesService.toggle()"
|
||||
*ngIf="currentPageIsExcluded()"
|
||||
[size]="14"
|
||||
[tooltip]="'file-preview.excluded-from-redaction' | translate | capitalize"
|
||||
class="mr-10 primary"
|
||||
icon="red:exclude-pages"
|
||||
tooltipPosition="above"
|
||||
></iqser-circle-button>
|
||||
|
||||
<span
|
||||
[translateParams]="{ page: pdf.currentPage(), count: activeAnnotations.length }"
|
||||
[translate]="'page'"
|
||||
class="all-caps-label"
|
||||
></span>
|
||||
</ng-container>
|
||||
</span>
|
||||
|
||||
<div *ngIf="multiSelectService.active()">
|
||||
<div
|
||||
(click)="selectAllOnActivePage()"
|
||||
class="all-caps-label primary pointer"
|
||||
translate="file-preview.tabs.annotations.select-all"
|
||||
></div>
|
||||
<div
|
||||
(click)="deselectAllOnActivePage()"
|
||||
class="all-caps-label primary pointer"
|
||||
translate="file-preview.tabs.annotations.select-none"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
#annotationsElement
|
||||
(keydown)="preventKeyDefault($event)"
|
||||
(keyup)="preventKeyDefault($event)"
|
||||
[class.active-panel]="!pagesPanelActive"
|
||||
[hidden]="excludedPagesService.shown()"
|
||||
class="annotations"
|
||||
id="annotations-list"
|
||||
tabindex="1"
|
||||
>
|
||||
<ng-container *ngIf="pdf.currentPage() && !displayedAnnotations.get(pdf.currentPage())?.length">
|
||||
<iqser-empty-state
|
||||
[horizontalPadding]="24"
|
||||
[text]="'file-preview.no-data.title' | translate"
|
||||
[verticalPadding]="40"
|
||||
icon="iqser:document"
|
||||
>
|
||||
<ng-container *ngIf="currentPageIsExcluded() && displayedPages.length">
|
||||
{{ 'file-preview.tabs.annotations.page-is' | translate }}
|
||||
<a
|
||||
(click)="excludedPagesService.toggle()"
|
||||
class="with-underline"
|
||||
translate="file-preview.excluded-from-redaction"
|
||||
></a
|
||||
>.
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="(fileDataService.allLength$ | async) === 0 || filterService.noAnnotationsFilterChecked"
|
||||
>
|
||||
{{ 'file-preview.tabs.annotations.no-annotations' | translate }}
|
||||
</ng-container>
|
||||
|
||||
<ng-container
|
||||
*ngIf="
|
||||
(fileDataService.allLength$ | async) > 0 &&
|
||||
displayedPages.length === 0 &&
|
||||
!filterService.noAnnotationsFilterChecked
|
||||
"
|
||||
>{{ 'file-preview.tabs.annotations.wrong-filters' | translate }}
|
||||
<a
|
||||
(click)="filterService.reset()"
|
||||
class="with-underline"
|
||||
translate="file-preview.tabs.annotations.reset"
|
||||
></a>
|
||||
{{ 'file-preview.tabs.annotations.the-filters' | translate }}
|
||||
</ng-container>
|
||||
</iqser-empty-state>
|
||||
|
||||
<div *ngIf="displayedPages.length" class="no-annotations-buttons-container mt-32">
|
||||
<iqser-icon-button
|
||||
(action)="jumpToPreviousWithAnnotations()"
|
||||
[disabled]="pdf.currentPage() <= displayedPages[0]"
|
||||
[label]="'file-preview.tabs.annotations.jump-to-previous' | translate"
|
||||
[type]="iconButtonTypes.dark"
|
||||
icon="iqser:nav-prev"
|
||||
></iqser-icon-button>
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="jumpToNextWithAnnotations()"
|
||||
[disabled]="pdf.currentPage() >= displayedPages[displayedPages.length - 1]"
|
||||
[label]="'file-preview.tabs.annotations.jump-to-next' | translate"
|
||||
[type]="iconButtonTypes.dark"
|
||||
class="mt-8"
|
||||
icon="iqser:nav-next"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<redaction-annotations-list
|
||||
(pagesPanelActive)="pagesPanelActive = $event"
|
||||
[annotations]="annotations.get(pdf.currentPage())"
|
||||
></redaction-annotations-list>
|
||||
</div>
|
||||
}
|
||||
<redaction-page-exclusion *ngIf="excludedPagesService.shown()"></redaction-page-exclusion>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<ng-template #annotationFilterActionTemplate let-filter="filter">
|
||||
<iqser-circle-button
|
||||
|
||||
@ -25,7 +25,7 @@ import { workloadTranslations } from '@translations/workload-translations';
|
||||
import { UserPreferenceService } from '@users/user-preference.service';
|
||||
import { getLocalStorageDataByFileId } from '@utils/local-storage';
|
||||
import { combineLatest, delay, Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { map, tap } from 'rxjs/operators';
|
||||
import scrollIntoView from 'scroll-into-view-if-needed';
|
||||
import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service';
|
||||
import { REDDocumentViewer } from '../../../pdf-viewer/services/document-viewer.service';
|
||||
@ -182,6 +182,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
||||
delay(0),
|
||||
map(([annotations, primary, secondary]) => this.#filterAnnotations(annotations, primary, secondary)),
|
||||
map(annotations => this.#mapListItemsFromAnnotationWrapperArray(annotations)),
|
||||
tap(annotations => this.#scrollToFirstAnnotationPage(annotations)),
|
||||
);
|
||||
}
|
||||
|
||||
@ -520,4 +521,11 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnInit, On
|
||||
});
|
||||
return listItemsMap;
|
||||
}
|
||||
|
||||
#scrollToFirstAnnotationPage(annotations: Map<number, ListItem<AnnotationWrapper>[]>) {
|
||||
if (this.isDocumine && annotations.size && !this.displayedPages.includes(this.pdf.currentPage())) {
|
||||
const page = annotations.keys().next().value;
|
||||
this.pdf.navigateTo(page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<ng-container *ngIf="state.file() as file">
|
||||
<iqser-empty-state
|
||||
*ngIf="file.excluded && documentInfoService.hidden()"
|
||||
*ngIf="file.excluded && documentInfoService.hidden() && !this.isDocumine"
|
||||
[horizontalPadding]="40"
|
||||
[text]="'file-preview.tabs.is-excluded' | translate"
|
||||
icon="red:needs-work"
|
||||
@ -8,5 +8,5 @@
|
||||
|
||||
<redaction-document-info *ngIf="documentInfoService.shown() && !isDocumine" id="document-info"></redaction-document-info>
|
||||
|
||||
<redaction-file-workload *ngIf="!file.excluded"></redaction-file-workload>
|
||||
<redaction-file-workload *ngIf="!file.excluded || isDocumine"></redaction-file-workload>
|
||||
</ng-container>
|
||||
|
||||
@ -1,9 +1,6 @@
|
||||
<section class="dialog">
|
||||
<form (submit)="save()" [formGroup]="form">
|
||||
<div
|
||||
[innerHTML]="'resize-redaction.dialog.header' | translate: { type: redaction.HINT ? 'hint' : 'redaction' }"
|
||||
class="dialog-header heading-l"
|
||||
></div>
|
||||
<div [innerHTML]="'resize-redaction.dialog.header' | translate: { type: dialogHeaderType }" class="dialog-header heading-l"></div>
|
||||
|
||||
<div class="dialog-content redaction">
|
||||
<ng-container *ngIf="!redaction.isImage && !redaction.AREA">
|
||||
|
||||
@ -63,6 +63,10 @@ export class ResizeRedactionDialogComponent extends IqserDialogComponent<
|
||||
this.form = this.#getForm();
|
||||
}
|
||||
|
||||
get dialogHeaderType() {
|
||||
return this.data.redaction.HINT ? 'hint' : this.data.redaction.isSkippedImageHint ? 'image' : 'redaction';
|
||||
}
|
||||
|
||||
get displayedDictionaryLabel() {
|
||||
const dictType = this.form.get('dictionary').value;
|
||||
if (dictType) {
|
||||
|
||||
@ -39,7 +39,7 @@
|
||||
}
|
||||
|
||||
&.documine-container {
|
||||
width: 70%;
|
||||
width: 60%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -275,6 +275,7 @@ export class ViewerHeaderService {
|
||||
|
||||
updateElements(): void {
|
||||
this._pdf.instance?.UI.setHeaderItems(header => {
|
||||
const documineButtons = this.#isDocumine ? 1 : 0;
|
||||
const enabledItems: IHeaderElement[] = [];
|
||||
const groups: HeaderElementType[][] = [
|
||||
[HeaderElements.COMPARE_BUTTON, HeaderElements.CLOSE_COMPARE_BUTTON],
|
||||
@ -293,15 +294,15 @@ export class ViewerHeaderService {
|
||||
groups.forEach(group => this.#pushGroup(enabledItems, group));
|
||||
|
||||
const loadAllAnnotationsButton = this.#buttons.get(HeaderElements.LOAD_ALL_ANNOTATIONS);
|
||||
let startButtons = 11;
|
||||
let deleteCount = 15;
|
||||
let startButtons = 11 - documineButtons;
|
||||
let deleteCount = 15 - documineButtons;
|
||||
|
||||
if (this.#isEnabled(HeaderElements.LOAD_ALL_ANNOTATIONS)) {
|
||||
if (!header.getItems().includes(loadAllAnnotationsButton)) {
|
||||
header.get('leftPanelButton').insertAfter(loadAllAnnotationsButton);
|
||||
}
|
||||
startButtons = 12;
|
||||
deleteCount = 16;
|
||||
startButtons = 12 - documineButtons;
|
||||
deleteCount = 16 - documineButtons;
|
||||
} else {
|
||||
header.delete(HeaderElements.LOAD_ALL_ANNOTATIONS);
|
||||
}
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
[tooltipPosition]="tooltipPosition"
|
||||
[helpModeKeyPrefix]="helpModeKeyPrefix"
|
||||
[isDossierOverviewWorkflow]="isDossierOverviewWorkflow"
|
||||
[file]="file"
|
||||
></redaction-expandable-file-actions>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
@ -1,3 +1,14 @@
|
||||
@if (isDocumine) {
|
||||
<iqser-circle-button
|
||||
[attr.help-mode-key]="'component_download'"
|
||||
[icon]="'red:extract'"
|
||||
[matMenuTriggerFor]="bulkComponentDownloadMenu"
|
||||
[tooltip]="'documine-export.export-tooltip' | translate"
|
||||
[tooltipPosition]="tooltipPosition"
|
||||
dropdownButton
|
||||
></iqser-circle-button>
|
||||
}
|
||||
|
||||
<ng-container *ngFor="let btn of displayedButtons; trackBy: trackBy">
|
||||
<iqser-circle-button
|
||||
(action)="btn.action($event)"
|
||||
@ -73,3 +84,8 @@
|
||||
</ng-container>
|
||||
</button>
|
||||
</mat-menu>
|
||||
|
||||
<mat-menu #bulkComponentDownloadMenu="matMenu">
|
||||
<button (click)="downloadComponentAsJSON()" [innerHTML]="'component-download.json' | translate" mat-menu-item></button>
|
||||
<button (click)="downloadComponentAsXML()" [innerHTML]="'component-download.xml' | translate" mat-menu-item></button>
|
||||
</mat-menu>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, inject, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core';
|
||||
import { Action, ActionTypes, Dossier, File } from '@red/domain';
|
||||
import { CircleButtonComponent, CircleButtonType, IqserDialog, StopPropagationDirective, Toaster } from '@iqser/common-ui';
|
||||
import { CircleButtonComponent, CircleButtonType, getConfig, IqserDialog, StopPropagationDirective, Toaster } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { FileDownloadService } from '@upload-download/services/file-download.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
@ -13,6 +13,8 @@ import { FileDownloadBtnComponent } from '@shared/components/buttons/file-downlo
|
||||
import { MatSlideToggle } from '@angular/material/slide-toggle';
|
||||
import { MatTooltip } from '@angular/material/tooltip';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { ComponentLogService } from '@services/files/component-log.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-expandable-file-actions',
|
||||
@ -44,11 +46,13 @@ export class ExpandableFileActionsComponent implements OnChanges {
|
||||
@Input() tooltipPosition: IqserTooltipPosition;
|
||||
@Input() helpModeKeyPrefix: 'dossier' | 'editor';
|
||||
@Input() isDossierOverviewWorkflow = false;
|
||||
@Input() file: File;
|
||||
displayedButtons: Action[];
|
||||
hiddenButtons: Action[];
|
||||
expanded = false;
|
||||
@ViewChild(MatMenuTrigger) readonly matMenu: MatMenuTrigger;
|
||||
readonly trackBy = trackByFactory();
|
||||
readonly isDocumine = getConfig().IS_DOCUMINE;
|
||||
readonly #appBaseHref = inject(APP_BASE_HREF);
|
||||
|
||||
constructor(
|
||||
@ -56,6 +60,7 @@ export class ExpandableFileActionsComponent implements OnChanges {
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _dialog: IqserDialog,
|
||||
private readonly _componentLogService: ComponentLogService,
|
||||
) {}
|
||||
|
||||
ngOnChanges(changes: SimpleChanges) {
|
||||
@ -124,4 +129,12 @@ export class ExpandableFileActionsComponent implements OnChanges {
|
||||
params: { downloadHref: `${this.#appBaseHref}/main/downloads` },
|
||||
});
|
||||
}
|
||||
|
||||
downloadComponentAsJSON() {
|
||||
return firstValueFrom(this._componentLogService.exportJSON(this.file.dossierTemplateId, this.file.dossierId, this.file));
|
||||
}
|
||||
|
||||
async downloadComponentAsXML() {
|
||||
return firstValueFrom(this._componentLogService.exportXML(this.file.dossierTemplateId, this.file.dossierId, this.file));
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,7 @@ export class ComponentMappingsService extends EntitiesService<IComponentMapping,
|
||||
file: Blob,
|
||||
): Observable<IComponentMapping> {
|
||||
const formParams = new FormData();
|
||||
formParams.append('file', file);
|
||||
formParams.append('file', file, componentMapping.fileName);
|
||||
|
||||
const queryParams: List<QueryParam> = [
|
||||
{ key: 'name', value: componentMapping.name },
|
||||
|
||||
@ -568,6 +568,7 @@
|
||||
},
|
||||
"search": "Nach Name suchen...",
|
||||
"table-col-names": {
|
||||
"column-labels": "Column labels",
|
||||
"name": "Name",
|
||||
"number-of-lines": "Zeilenzahl",
|
||||
"version": "Version"
|
||||
|
||||
@ -568,6 +568,7 @@
|
||||
},
|
||||
"search": "Search by name...",
|
||||
"table-col-names": {
|
||||
"column-labels": "Column labels",
|
||||
"name": "name",
|
||||
"number-of-lines": "Number of lines",
|
||||
"version": "version"
|
||||
|
||||
@ -568,6 +568,7 @@
|
||||
},
|
||||
"search": "Search by name...",
|
||||
"table-col-names": {
|
||||
"column-labels": "Column labels",
|
||||
"name": "name",
|
||||
"number-of-lines": "Number of lines",
|
||||
"version": "version"
|
||||
|
||||
@ -568,6 +568,7 @@
|
||||
},
|
||||
"search": "Search by name...",
|
||||
"table-col-names": {
|
||||
"column-labels": "Column labels",
|
||||
"name": "name",
|
||||
"number-of-lines": "Number of lines",
|
||||
"version": "version"
|
||||
@ -1271,8 +1272,8 @@
|
||||
"dictionary": "Dictionary",
|
||||
"dossier-attributes": "Dossier attributes",
|
||||
"dossier-dictionary": "Dossier dictionary",
|
||||
"dossier-info": "Dossier Info",
|
||||
"download-package": "Download Package",
|
||||
"dossier-info": "Dossier info",
|
||||
"download-package": "Download package",
|
||||
"general-info": "General Information",
|
||||
"members": "Members",
|
||||
"team-members": "Team Members"
|
||||
|
||||
@ -164,7 +164,7 @@ $dark-accent-10: darken(vars.$accent, 10%);
|
||||
body {
|
||||
--workload-width: 350px;
|
||||
--documine-workload-content-width: 287px;
|
||||
--structured-component-management-width: 30%;
|
||||
--structured-component-management-width: 40%;
|
||||
--qiuck-navigation-width: 61px;
|
||||
--iqser-app-name-font-family: OpenSans Extrabold, sans-serif;
|
||||
--iqser-app-name-font-size: 13px;
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit 98ac49fbc81bb9989c14a8ca06c11d98ed042c86
|
||||
Subproject commit 9bbaecb7e566afe2efb8dbce73dce6eb5373801b
|
||||
@ -6,6 +6,7 @@ export interface IComponentMapping extends IListable {
|
||||
fileName: string;
|
||||
version: number;
|
||||
columnLabels: string[];
|
||||
columnLabelsString: string;
|
||||
numberOfLines: number;
|
||||
encoding: string;
|
||||
delimiter: string;
|
||||
@ -17,6 +18,7 @@ export class ComponentMapping implements IComponentMapping, IListable {
|
||||
readonly fileName: string;
|
||||
readonly version: number;
|
||||
readonly columnLabels: string[];
|
||||
readonly columnLabelsString: string;
|
||||
readonly numberOfLines: number;
|
||||
readonly encoding: string;
|
||||
readonly delimiter: string;
|
||||
@ -27,6 +29,7 @@ export class ComponentMapping implements IComponentMapping, IListable {
|
||||
this.fileName = componentMapping.fileName;
|
||||
this.version = componentMapping.version;
|
||||
this.columnLabels = componentMapping.columnLabels;
|
||||
this.columnLabelsString = componentMapping.columnLabels?.join(', ');
|
||||
this.numberOfLines = componentMapping.numberOfLines;
|
||||
this.encoding = componentMapping.encoding;
|
||||
this.delimiter = componentMapping.delimiter;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user