RED-3800 rss editing
This commit is contained in:
commit
4555f596bb
@ -149,9 +149,8 @@ export class ReportsScreenComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async _loadReportTemplates() {
|
private async _loadReportTemplates() {
|
||||||
this.availableTemplates$.next(
|
const reportTemplates = await this._reportTemplateService.getAvailableReportTemplates(this.#dossierTemplateId);
|
||||||
await firstValueFrom(this._reportTemplateService.getAvailableReportTemplates(this.#dossierTemplateId)),
|
this.availableTemplates$.next(reportTemplates);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _loadPlaceholders() {
|
private async _loadPlaceholders() {
|
||||||
|
|||||||
@ -214,18 +214,19 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($event.key === 'ArrowLeft') {
|
if (!$event.metaKey && !$event.ctrlKey && $event.key === 'ArrowLeft') {
|
||||||
this.pagesPanelActive = true;
|
this.pagesPanelActive = true;
|
||||||
this._changeDetectorRef.markForCheck();
|
this._changeDetectorRef.markForCheck();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($event.key === 'ArrowRight') {
|
if (!$event.metaKey && !$event.ctrlKey && $event.key === 'ArrowRight') {
|
||||||
this.pagesPanelActive = false;
|
this.pagesPanelActive = false;
|
||||||
// if we activated annotationsPanel -
|
// if we activated annotationsPanel -
|
||||||
// select first annotation from this page in case there is no
|
// select first annotation from this page in case there is no
|
||||||
// selected annotation on this page and not in multi select mode
|
// selected annotation on this page and not in multi select mode
|
||||||
if (!this.pagesPanelActive && !this.multiSelectService.isActive) {
|
if (!this.pagesPanelActive && !this.multiSelectService.isActive) {
|
||||||
|
this._documentViewer.clearSelection();
|
||||||
this._selectFirstAnnotationOnCurrentPageIfNecessary();
|
this._selectFirstAnnotationOnCurrentPageIfNecessary();
|
||||||
}
|
}
|
||||||
this._changeDetectorRef.markForCheck();
|
this._changeDetectorRef.markForCheck();
|
||||||
|
|||||||
@ -1,57 +1,72 @@
|
|||||||
<section class="dialog">
|
<section class="dialog">
|
||||||
<div translate="rss-dialog.title" class="dialog-header heading-l"></div>
|
<div class="dialog-header heading-l" translate="rss-dialog.title"></div>
|
||||||
|
|
||||||
<hr />
|
<hr />
|
||||||
<div class="dialog-content">
|
<div class="dialog-content">
|
||||||
<div class="table output-data" *ngIf="rssData$ | async as rssEntry">
|
<div *ngIf="rssData$ | async as rssEntry" class="table output-data">
|
||||||
<div class="table-header">Component</div>
|
<div class="table-header">Component</div>
|
||||||
<div class="table-header">Value</div>
|
<div class="table-header">Value</div>
|
||||||
<div class="table-header">Transformation</div>
|
<div class="table-header">Transformation</div>
|
||||||
<div class="table-header">Annotations</div>
|
<div class="table-header">
|
||||||
|
Annotations
|
||||||
|
<hr />
|
||||||
|
<div class="annotation-grid">
|
||||||
|
<div>Type</div>
|
||||||
|
<div>Rule</div>
|
||||||
|
<div>Pages</div>
|
||||||
|
<div>Reason</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<ng-container *ngFor="let entry of rssEntry.result | keyvalue: originalOrder">
|
<ng-container *ngFor="let entry of rssEntry.result | keyvalue: originalOrder">
|
||||||
<div class="bold">{{ entry.key }}</div>
|
<div class="bold">{{ entry.key }}</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="value-content">
|
<iqser-editable-input
|
||||||
<iqser-editable-input
|
(save)="saveEdit($event, entry)"
|
||||||
(save)="saveEdit($event, entry.value.originalKey)"
|
[buttonsType]="iconButtonTypes.dark"
|
||||||
[buttonsType]="iconButtonTypes.dark"
|
[cancelTooltip]="'rss-dialog.actions.cancel-edit' | translate"
|
||||||
[cancelTooltip]="'rss-dialog.actions.cancel-edit-name' | translate"
|
[editTooltip]="'rss-dialog.actions.edit' | translate"
|
||||||
[class]="'w-200'"
|
[saveTooltip]="'rss-dialog.actions.save' | translate"
|
||||||
[editTooltip]="'rss-dialog.actions.edit-name' | translate"
|
[value]="entry.value.value ?? entry.value.originalValue"
|
||||||
[saveTooltip]="'rss-dialog.actions.save-name' | translate"
|
>
|
||||||
[value]="entry.value.value ?? entry.value.originalValue"
|
<ng-container slot="editing">
|
||||||
></iqser-editable-input>
|
|
||||||
|
|
||||||
<div class="actions">
|
|
||||||
<iqser-circle-button
|
<iqser-circle-button
|
||||||
(action)="undo()"
|
(action)="undo(entry)"
|
||||||
icon="red:undo"
|
*ngIf="entry.value.value"
|
||||||
[showDot]="false"
|
[showDot]="true"
|
||||||
[tooltip]="'rss-dialog.actions.undo' | translate"
|
[tooltip]="'rss-dialog.actions.undo' | translate"
|
||||||
[type]="iconButtonTypes.dark"
|
[type]="iconButtonTypes.dark"
|
||||||
|
class="ml-2"
|
||||||
|
icon="red:undo"
|
||||||
></iqser-circle-button>
|
></iqser-circle-button>
|
||||||
</div>
|
</ng-container>
|
||||||
</div>
|
</iqser-editable-input>
|
||||||
</div>
|
</div>
|
||||||
<div>{{ entry.value.transformation }}</div>
|
<div>{{ entry.value.transformation }}</div>
|
||||||
<div>{{ entry.value.scmAnnotations | json }}</div>
|
<div class="annotation-grid">
|
||||||
|
<ng-container *ngFor="let annotation of entry.value.scmAnnotations">
|
||||||
|
<div>{{ annotation.type }}</div>
|
||||||
|
<div>{{ annotation.ruleNumber }}</div>
|
||||||
|
<div>{{ annotation.pages.join(',') }}</div>
|
||||||
|
<div>{{ annotation.reason }}</div>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="dialog-actions">
|
<div class="dialog-actions">
|
||||||
<button color="primary" mat-flat-button type="submit" (click)="exportJSON()">
|
<button (click)="exportJSON()" color="primary" mat-flat-button type="submit">
|
||||||
{{ 'rss-dialog.actions.export-json' | translate }}
|
{{ 'rss-dialog.actions.export-json' | translate }}
|
||||||
</button>
|
</button>
|
||||||
<button color="primary" mat-flat-button type="button" (click)="exportXML()">
|
<button (click)="exportXML()" color="primary" mat-flat-button type="button">
|
||||||
{{ 'rss-dialog.actions.export-xml' | translate }}
|
{{ 'rss-dialog.actions.export-xml' | translate }}
|
||||||
</button>
|
</button>
|
||||||
<button color="primary" mat-flat-button type="button" (click)="exportAllInDossier()" *ngIf="userPreferences.areDevFeaturesEnabled">
|
<button (click)="exportAllInDossier()" *ngIf="userPreferences.areDevFeaturesEnabled" color="primary" mat-flat-button type="button">
|
||||||
{{ 'Export All' }}
|
{{ 'Export All' }}
|
||||||
</button>
|
</button>
|
||||||
<div class="all-caps-label cancel" mat-dialog-close translate="rss-dialog.actions.close"></div>
|
<div class="all-caps-label cancel" mat-dialog-close translate="rss-dialog.actions.close"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
|
<iqser-circle-button (action)="close()" class="dialog-close" icon="iqser:close"></iqser-circle-button>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@ -47,3 +47,8 @@
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.annotation-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 3fr 1fr 1fr 5fr;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { Component, Inject } from '@angular/core';
|
import { Component, Inject, OnInit } from '@angular/core';
|
||||||
import { BaseDialogComponent, IconButtonTypes } from '@iqser/common-ui';
|
import { BaseDialogComponent, IconButtonTypes } from '@iqser/common-ui';
|
||||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
import { RssService } from '@services/files/rss.service';
|
import { RssService } from '@services/files/rss.service';
|
||||||
import { IFile, IRssEntry } from '@red/domain';
|
import { IFile, IRssEntry } from '@red/domain';
|
||||||
import { firstValueFrom, Observable } from 'rxjs';
|
import { BehaviorSubject, firstValueFrom } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { FilesMapService } from '@services/files/files-map.service';
|
import { FilesMapService } from '@services/files/files-map.service';
|
||||||
import { UserPreferenceService } from '@users/user-preference.service';
|
import { UserPreferenceService } from '@users/user-preference.service';
|
||||||
@ -17,12 +17,10 @@ interface RssData {
|
|||||||
templateUrl: './rss-dialog.component.html',
|
templateUrl: './rss-dialog.component.html',
|
||||||
styleUrls: ['./rss-dialog.component.scss'],
|
styleUrls: ['./rss-dialog.component.scss'],
|
||||||
})
|
})
|
||||||
export class RssDialogComponent extends BaseDialogComponent {
|
export class RssDialogComponent extends BaseDialogComponent implements OnInit {
|
||||||
readonly iconButtonTypes = IconButtonTypes;
|
readonly iconButtonTypes = IconButtonTypes;
|
||||||
|
|
||||||
rssData$: Observable<IRssEntry>;
|
rssData$ = new BehaviorSubject<IRssEntry>(null);
|
||||||
|
|
||||||
originalOrder = (a: KeyValue<string, any>, b: KeyValue<string, any>): number => 0;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
protected readonly _dialogRef: MatDialogRef<RssDialogComponent>,
|
protected readonly _dialogRef: MatDialogRef<RssDialogComponent>,
|
||||||
@ -32,22 +30,14 @@ export class RssDialogComponent extends BaseDialogComponent {
|
|||||||
@Inject(MAT_DIALOG_DATA) readonly data: RssData,
|
@Inject(MAT_DIALOG_DATA) readonly data: RssData,
|
||||||
) {
|
) {
|
||||||
super(_dialogRef);
|
super(_dialogRef);
|
||||||
this.rssData$ = this._rssService.getRSSData(this.data.file.dossierId, this.data.file.fileId).pipe(
|
|
||||||
map(entry => {
|
|
||||||
const mapped = {};
|
|
||||||
for (const key of Object.keys(entry.result)) {
|
|
||||||
const newKey = key.replace(new RegExp('_', 'g'), ' ');
|
|
||||||
(<any>entry.result[key]).originalKey = key;
|
|
||||||
mapped[newKey] = entry.result[key];
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
filaName: entry.filaName,
|
|
||||||
result: mapped,
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async ngOnInit(): Promise<void> {
|
||||||
|
await this.#loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
originalOrder = (a: KeyValue<string, any>, b: KeyValue<string, any>): number => 0;
|
||||||
|
|
||||||
exportJSON() {
|
exportJSON() {
|
||||||
this._rssService.exportJSON(this.data.file.dossierId, this.data.file.fileId, this.data.file.filename).subscribe();
|
this._rssService.exportJSON(this.data.file.dossierId, this.data.file.fileId, this.data.file.filename).subscribe();
|
||||||
}
|
}
|
||||||
@ -68,14 +58,39 @@ export class RssDialogComponent extends BaseDialogComponent {
|
|||||||
this.exportJSON();
|
this.exportJSON();
|
||||||
}
|
}
|
||||||
|
|
||||||
undo() {
|
async undo(entry: KeyValue<string, any>) {
|
||||||
console.log('Undo');
|
this._loadingService.start();
|
||||||
|
await firstValueFrom(this._rssService.revertOverride(this.data.file.dossierId, this.data.file.fileId, [entry.value.originalKey]));
|
||||||
|
await this.#loadData();
|
||||||
}
|
}
|
||||||
|
|
||||||
saveEdit(event: string, originalKey: string) {
|
async saveEdit(event: string, entry: KeyValue<string, any>) {
|
||||||
console.log(event, originalKey);
|
this._loadingService.start();
|
||||||
/**
|
await firstValueFrom(
|
||||||
* https://qa2.iqser.cloud/redaction-gateway-v1/swagger-ui/index.html#/rss-controller/revertOverrides
|
this._rssService.override(this.data.file.dossierId, this.data.file.fileId, { [entry.value.originalKey]: event }),
|
||||||
*/
|
);
|
||||||
|
await this.#loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
async #loadData(): Promise<void> {
|
||||||
|
this._loadingService.start();
|
||||||
|
const rssData = await firstValueFrom(
|
||||||
|
this._rssService.getRSSData(this.data.file.dossierId, this.data.file.fileId).pipe(
|
||||||
|
map(entry => {
|
||||||
|
const mapped = {};
|
||||||
|
for (const key of Object.keys(entry.result)) {
|
||||||
|
const newKey = key.replace(new RegExp('_', 'g'), ' ');
|
||||||
|
(<any>entry.result[key]).originalKey = key;
|
||||||
|
mapped[newKey] = entry.result[key];
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
filaName: entry.filaName,
|
||||||
|
result: mapped,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
this.rssData$.next(rssData);
|
||||||
|
this._loadingService.stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,7 +12,6 @@ import {
|
|||||||
ViewChild,
|
ViewChild,
|
||||||
} from '@angular/core';
|
} from '@angular/core';
|
||||||
import { ActivatedRoute, ActivatedRouteSnapshot, NavigationExtras, Router } from '@angular/router';
|
import { ActivatedRoute, ActivatedRouteSnapshot, NavigationExtras, Router } from '@angular/router';
|
||||||
import { Core } from '@pdftron/webviewer';
|
|
||||||
import {
|
import {
|
||||||
AutoUnsubscribe,
|
AutoUnsubscribe,
|
||||||
bool,
|
bool,
|
||||||
@ -26,7 +25,6 @@ import {
|
|||||||
HelpModeService,
|
HelpModeService,
|
||||||
List,
|
List,
|
||||||
LoadingService,
|
LoadingService,
|
||||||
log,
|
|
||||||
NestedFilter,
|
NestedFilter,
|
||||||
OnAttach,
|
OnAttach,
|
||||||
OnDetach,
|
OnDetach,
|
||||||
@ -73,7 +71,6 @@ import { ConfigService } from '@services/config.service';
|
|||||||
import { ReadableRedactionsService } from '../pdf-viewer/services/readable-redactions.service';
|
import { ReadableRedactionsService } from '../pdf-viewer/services/readable-redactions.service';
|
||||||
import { ROLES } from '@users/roles';
|
import { ROLES } from '@users/roles';
|
||||||
import { SuggestionsService } from './services/suggestions.service';
|
import { SuggestionsService } from './services/suggestions.service';
|
||||||
import Annotation = Core.Annotations.Annotation;
|
|
||||||
|
|
||||||
const textActions = [TextPopups.ADD_DICTIONARY, TextPopups.ADD_FALSE_POSITIVE];
|
const textActions = [TextPopups.ADD_DICTIONARY, TextPopups.ADD_FALSE_POSITIVE];
|
||||||
|
|
||||||
@ -92,10 +89,7 @@ export class FilePreviewScreenComponent
|
|||||||
fullScreen = false;
|
fullScreen = false;
|
||||||
readonly fileId = this.state.fileId;
|
readonly fileId = this.state.fileId;
|
||||||
readonly dossierId = this.state.dossierId;
|
readonly dossierId = this.state.dossierId;
|
||||||
readonly file$ = this.state.file$.pipe(
|
readonly file$ = this.state.file$.pipe(tap(file => this._fileDataService.loadAnnotations(file)));
|
||||||
tap(file => this._fileDataService.loadAnnotations(file)),
|
|
||||||
log('file'),
|
|
||||||
);
|
|
||||||
width: number;
|
width: number;
|
||||||
@ViewChild('annotationFilterTemplate', {
|
@ViewChild('annotationFilterTemplate', {
|
||||||
read: TemplateRef,
|
read: TemplateRef,
|
||||||
@ -180,6 +174,7 @@ export class FilePreviewScreenComponent
|
|||||||
const earmarks$ = isEarmarksViewMode$.pipe(
|
const earmarks$ = isEarmarksViewMode$.pipe(
|
||||||
tap(() => this._loadingService.start()),
|
tap(() => this._loadingService.start()),
|
||||||
switchMap(() => this._fileDataService.loadEarmarks()),
|
switchMap(() => this._fileDataService.loadEarmarks()),
|
||||||
|
switchMap(() => this._fileDataService.earmarks$),
|
||||||
tap(() => this.updateViewMode().then(() => this._loadingService.stop())),
|
tap(() => this.updateViewMode().then(() => this._loadingService.stop())),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -223,7 +218,7 @@ export class FilePreviewScreenComponent
|
|||||||
|
|
||||||
switch (this._viewModeService.viewMode) {
|
switch (this._viewModeService.viewMode) {
|
||||||
case ViewModes.STANDARD: {
|
case ViewModes.STANDARD: {
|
||||||
this._setAnnotationsColor(redactions, 'annotationColor');
|
this._readableRedactionsService.setAnnotationsColor(redactions, 'annotationColor');
|
||||||
const wrappers = await this._fileDataService.annotations;
|
const wrappers = await this._fileDataService.annotations;
|
||||||
const ocrAnnotationIds = wrappers.filter(a => a.isOCR).map(a => a.id);
|
const ocrAnnotationIds = wrappers.filter(a => a.isOCR).map(a => a.id);
|
||||||
const standardEntries = annotations
|
const standardEntries = annotations
|
||||||
@ -232,7 +227,7 @@ export class FilePreviewScreenComponent
|
|||||||
const nonStandardEntries = annotations.filter(
|
const nonStandardEntries = annotations.filter(
|
||||||
a => bool(a.getCustomData('changeLogRemoved')) || this._annotationManager.isHidden(a.Id),
|
a => bool(a.getCustomData('changeLogRemoved')) || this._annotationManager.isHidden(a.Id),
|
||||||
);
|
);
|
||||||
this._setAnnotationsOpacity(standardEntries, true);
|
this._readableRedactionsService.setAnnotationsOpacity(standardEntries, true);
|
||||||
this._annotationManager.show(standardEntries);
|
this._annotationManager.show(standardEntries);
|
||||||
this._annotationManager.hide(nonStandardEntries);
|
this._annotationManager.hide(nonStandardEntries);
|
||||||
break;
|
break;
|
||||||
@ -240,8 +235,8 @@ export class FilePreviewScreenComponent
|
|||||||
case ViewModes.DELTA: {
|
case ViewModes.DELTA: {
|
||||||
const changeLogEntries = annotations.filter(a => bool(a.getCustomData('changeLog')));
|
const changeLogEntries = annotations.filter(a => bool(a.getCustomData('changeLog')));
|
||||||
const nonChangeLogEntries = annotations.filter(a => !bool(a.getCustomData('changeLog')));
|
const nonChangeLogEntries = annotations.filter(a => !bool(a.getCustomData('changeLog')));
|
||||||
this._setAnnotationsColor(redactions, 'annotationColor');
|
this._readableRedactionsService.setAnnotationsColor(redactions, 'annotationColor');
|
||||||
this._setAnnotationsOpacity(changeLogEntries, true);
|
this._readableRedactionsService.setAnnotationsOpacity(changeLogEntries, true);
|
||||||
this._annotationManager.show(changeLogEntries);
|
this._annotationManager.show(changeLogEntries);
|
||||||
this._annotationManager.hide(nonChangeLogEntries);
|
this._annotationManager.hide(nonChangeLogEntries);
|
||||||
break;
|
break;
|
||||||
@ -250,14 +245,8 @@ export class FilePreviewScreenComponent
|
|||||||
const nonRedactionEntries = annotations.filter(
|
const nonRedactionEntries = annotations.filter(
|
||||||
a => !bool(a.getCustomData('redaction')) || bool(a.getCustomData('changeLogRemoved')),
|
a => !bool(a.getCustomData('redaction')) || bool(a.getCustomData('changeLogRemoved')),
|
||||||
);
|
);
|
||||||
if (this._readableRedactionsService.active) {
|
this._readableRedactionsService.setPreviewAnnotationsOpacity(redactions);
|
||||||
this._setAnnotationsOpacity(redactions, true);
|
this._readableRedactionsService.setPreviewAnnotationsColor(redactions);
|
||||||
this._setAnnotationsColor(redactions, 'annotationColor');
|
|
||||||
} else {
|
|
||||||
this._setAnnotationsOpacity(redactions);
|
|
||||||
this._setAnnotationsColor(redactions, 'redactionColor');
|
|
||||||
}
|
|
||||||
|
|
||||||
this._annotationManager.show(redactions);
|
this._annotationManager.show(redactions);
|
||||||
this._annotationManager.hide(nonRedactionEntries);
|
this._annotationManager.hide(nonRedactionEntries);
|
||||||
this._suggestionsService.hideSuggestionsInPreview(redactions);
|
this._suggestionsService.hideSuggestionsInPreview(redactions);
|
||||||
@ -762,20 +751,6 @@ export class FilePreviewScreenComponent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private _setAnnotationsOpacity(annotations: Annotation[], restoreToOriginal = false) {
|
|
||||||
annotations.forEach(annotation => {
|
|
||||||
annotation['Opacity'] = restoreToOriginal ? parseFloat(annotation.getCustomData('opacity')) : 1;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private _setAnnotationsColor(annotations: Annotation[], customData: string) {
|
|
||||||
annotations.forEach(annotation => {
|
|
||||||
const color = this._annotationDrawService.convertColor(annotation.getCustomData(customData));
|
|
||||||
annotation['StrokeColor'] = color;
|
|
||||||
annotation['FillColor'] = color;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private _navigateToDossier() {
|
private _navigateToDossier() {
|
||||||
this._logger.info('Navigating to ', this.state.dossier.dossierName);
|
this._logger.info('Navigating to ', this.state.dossier.dossierName);
|
||||||
return this._router.navigate([this.state.dossier.routerLink]);
|
return this._router.navigate([this.state.dossier.routerLink]);
|
||||||
|
|||||||
@ -181,9 +181,10 @@ export class FileDataService extends EntitiesService<AnnotationWrapper, Annotati
|
|||||||
async #buildRemovedRedactions(redactionLog: IRedactionLog, file: File): Promise<void> {
|
async #buildRemovedRedactions(redactionLog: IRedactionLog, file: File): Promise<void> {
|
||||||
const redactionLogCopy = JSON.parse(JSON.stringify(redactionLog));
|
const redactionLogCopy = JSON.parse(JSON.stringify(redactionLog));
|
||||||
redactionLogCopy.redactionLogEntry = redactionLogCopy.redactionLogEntry.reduce((filtered, entry) => {
|
redactionLogCopy.redactionLogEntry = redactionLogCopy.redactionLogEntry.reduce((filtered, entry) => {
|
||||||
const isRemoveChange = entry.manualChanges.find(c => this.#isRemoveChange(c.manualRedactionType));
|
const lastChange = entry.manualChanges.at(-1);
|
||||||
|
const isRemoveChange = this.#isRemoveChange(lastChange?.manualRedactionType);
|
||||||
if (isRemoveChange) {
|
if (isRemoveChange) {
|
||||||
entry.manualChanges = entry.manualChanges.filter(c => !this.#isRemoveChange(c.manualRedactionType));
|
entry.manualChanges.pop();
|
||||||
filtered.push(entry);
|
filtered.push(entry);
|
||||||
}
|
}
|
||||||
return filtered;
|
return filtered;
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import Annotation = Core.Annotations.Annotation;
|
|||||||
import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service';
|
import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service';
|
||||||
import { UserPreferenceService } from '@users/user-preference.service';
|
import { UserPreferenceService } from '@users/user-preference.service';
|
||||||
import { AnnotationDrawService } from '../../pdf-viewer/services/annotation-draw.service';
|
import { AnnotationDrawService } from '../../pdf-viewer/services/annotation-draw.service';
|
||||||
|
import { ReadableRedactionsService } from '../../pdf-viewer/services/readable-redactions.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class SuggestionsService {
|
export class SuggestionsService {
|
||||||
@ -15,6 +16,7 @@ export class SuggestionsService {
|
|||||||
private readonly _annotationManager: REDAnnotationManager,
|
private readonly _annotationManager: REDAnnotationManager,
|
||||||
private readonly _userPreferenceService: UserPreferenceService,
|
private readonly _userPreferenceService: UserPreferenceService,
|
||||||
private readonly _annotationDrawService: AnnotationDrawService,
|
private readonly _annotationDrawService: AnnotationDrawService,
|
||||||
|
private readonly _readableRedactionsService: ReadableRedactionsService,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
set removedRedactions(removedRedactions: AnnotationWrapper[]) {
|
set removedRedactions(removedRedactions: AnnotationWrapper[]) {
|
||||||
@ -39,14 +41,8 @@ export class SuggestionsService {
|
|||||||
|
|
||||||
#convertRemoveSuggestionsToRedactions(suggestions: Annotation[]): void {
|
#convertRemoveSuggestionsToRedactions(suggestions: Annotation[]): void {
|
||||||
const removeSuggestions = suggestions.filter(a => bool(a.getCustomData('suggestionRemove')));
|
const removeSuggestions = suggestions.filter(a => bool(a.getCustomData('suggestionRemove')));
|
||||||
|
this._readableRedactionsService.setPreviewAnnotationsOpacity(removeSuggestions);
|
||||||
removeSuggestions.forEach(suggestion => {
|
this._readableRedactionsService.setPreviewAnnotationsColor(removeSuggestions);
|
||||||
const color = this._annotationDrawService.convertColor(suggestion.getCustomData('redactionColor'));
|
|
||||||
suggestion['Opacity'] = 1;
|
|
||||||
suggestion['StrokeColor'] = color;
|
|
||||||
suggestion['FillColor'] = color;
|
|
||||||
});
|
|
||||||
|
|
||||||
this._annotationManager.show(removeSuggestions);
|
this._annotationManager.show(removeSuggestions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -19,6 +19,7 @@ import Quad = Core.Math.Quad;
|
|||||||
|
|
||||||
const DEFAULT_TEXT_ANNOTATION_OPACITY = 1;
|
const DEFAULT_TEXT_ANNOTATION_OPACITY = 1;
|
||||||
const DEFAULT_REMOVED_ANNOTATION_OPACITY = 0.2;
|
const DEFAULT_REMOVED_ANNOTATION_OPACITY = 0.2;
|
||||||
|
const FINAL_REDACTION_COLOR = '#000000';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AnnotationDrawService {
|
export class AnnotationDrawService {
|
||||||
@ -164,6 +165,7 @@ export class AnnotationDrawService {
|
|||||||
? this._defaultColorsService.getColor(dossierTemplateId, 'requestAddColor')
|
? this._defaultColorsService.getColor(dossierTemplateId, 'requestAddColor')
|
||||||
: this._defaultColorsService.getColor(dossierTemplateId, 'previewColor');
|
: this._defaultColorsService.getColor(dossierTemplateId, 'previewColor');
|
||||||
annotation.setCustomData('redactionColor', String(redactionColor));
|
annotation.setCustomData('redactionColor', String(redactionColor));
|
||||||
|
annotation.setCustomData('finalRedactionColor', FINAL_REDACTION_COLOR);
|
||||||
annotation.setCustomData('annotationColor', String(annotationWrapper.color));
|
annotation.setCustomData('annotationColor', String(annotationWrapper.color));
|
||||||
|
|
||||||
return annotation;
|
return annotation;
|
||||||
|
|||||||
@ -80,6 +80,11 @@ export class REDDocumentViewer {
|
|||||||
return merge(this.#documentUnloaded$, this.#documentLoaded$).pipe(shareLast());
|
return merge(this.#documentUnloaded$, this.#documentLoaded$).pipe(shareLast());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearSelection() {
|
||||||
|
this.#document.clearSelection();
|
||||||
|
this.#pdf.disable('textPopup');
|
||||||
|
}
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this.#logger.info('[PDF] Closing document');
|
this.#logger.info('[PDF] Closing document');
|
||||||
this.#document.closeDocument();
|
this.#document.closeDocument();
|
||||||
|
|||||||
@ -7,13 +7,15 @@ import { PdfViewer } from './pdf-viewer.service';
|
|||||||
import { REDAnnotationManager } from './annotation-manager.service';
|
import { REDAnnotationManager } from './annotation-manager.service';
|
||||||
import { AnnotationDrawService } from './annotation-draw.service';
|
import { AnnotationDrawService } from './annotation-draw.service';
|
||||||
import { BehaviorSubject, Observable } from 'rxjs';
|
import { BehaviorSubject, Observable } from 'rxjs';
|
||||||
|
import { Core } from '@pdftron/webviewer';
|
||||||
|
import Annotation = Core.Annotations.Annotation;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ReadableRedactionsService {
|
export class ReadableRedactionsService {
|
||||||
|
readonly active$: Observable<boolean>;
|
||||||
readonly #enableIcon = this._convertPath('/assets/icons/general/pdftron-action-enable-tooltips.svg');
|
readonly #enableIcon = this._convertPath('/assets/icons/general/pdftron-action-enable-tooltips.svg');
|
||||||
readonly #disableIcon = this._convertPath('/assets/icons/general/pdftron-action-disable-tooltips.svg');
|
readonly #disableIcon = this._convertPath('/assets/icons/general/pdftron-action-disable-tooltips.svg');
|
||||||
readonly #active$ = new BehaviorSubject<boolean>(false);
|
readonly #active$ = new BehaviorSubject<boolean>(true);
|
||||||
readonly active$: Observable<boolean>;
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(BASE_HREF_FN) private readonly _convertPath: BaseHrefFn,
|
@Inject(BASE_HREF_FN) private readonly _convertPath: BaseHrefFn,
|
||||||
@ -47,4 +49,27 @@ export class ReadableRedactionsService {
|
|||||||
img: this.toggleReadableRedactionsBtnIcon,
|
img: this.toggleReadableRedactionsBtnIcon,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setAnnotationsOpacity(annotations: Annotation[], restoreToOriginal = false) {
|
||||||
|
annotations.forEach(annotation => {
|
||||||
|
annotation['Opacity'] = restoreToOriginal ? parseFloat(annotation.getCustomData('opacity')) : 0.5;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setAnnotationsColor(annotations: Annotation[], customData: string) {
|
||||||
|
annotations.forEach(annotation => {
|
||||||
|
const color = this._annotationDrawService.convertColor(annotation.getCustomData(customData));
|
||||||
|
annotation['StrokeColor'] = color;
|
||||||
|
annotation['FillColor'] = color;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setPreviewAnnotationsOpacity(annotations: Annotation[]) {
|
||||||
|
this.setAnnotationsOpacity(annotations, !this.active);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPreviewAnnotationsColor(annotations: Annotation[]) {
|
||||||
|
const color = this.active ? 'redactionColor' : 'finalRedactionColor';
|
||||||
|
this.setAnnotationsColor(annotations, color);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -249,7 +249,7 @@ export class ViewerHeaderService {
|
|||||||
header.getItems().splice(10, header.getItems().length - 14, ...enabledItems);
|
header.getItems().splice(10, header.getItems().length - 14, ...enabledItems);
|
||||||
});
|
});
|
||||||
|
|
||||||
this._pdf.instance.UI.updateElement('selectToolButton', {
|
this._pdf.instance?.UI.updateElement('selectToolButton', {
|
||||||
img: this._convertPath('/assets/icons/general/pdftron-cursor.svg'),
|
img: this._convertPath('/assets/icons/general/pdftron-cursor.svg'),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,8 +106,7 @@ export class EditDossierDownloadPackageComponent
|
|||||||
existsWatermarks: this.#existsWatermarks$,
|
existsWatermarks: this.#existsWatermarks$,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.availableReportTypes =
|
this.availableReportTypes = (await this._reportTemplateController.getAvailableReportTemplates(dossierTemplateId)) || [];
|
||||||
(await firstValueFrom(this._reportTemplateController.getAvailableReportTemplates(dossierTemplateId))) || [];
|
|
||||||
|
|
||||||
this.form = this._getForm();
|
this.form = this._getForm();
|
||||||
if (!this.canEditDossier) {
|
if (!this.canEditDossier) {
|
||||||
|
|||||||
@ -200,7 +200,7 @@ export class AddEditEntityComponent extends BaseFormComponent implements OnInit
|
|||||||
private _toTechnicalName(value: string) {
|
private _toTechnicalName(value: string) {
|
||||||
const existingTechnicalNames = this._dictionariesMapService.get(this.dossierTemplateId).map(dict => dict.type);
|
const existingTechnicalNames = this._dictionariesMapService.get(this.dossierTemplateId).map(dict => dict.type);
|
||||||
const baseTechnicalName = toSnakeCase(value.trim());
|
const baseTechnicalName = toSnakeCase(value.trim());
|
||||||
let technicalName = baseTechnicalName;
|
let technicalName = baseTechnicalName.replaceAll(/[^A-Za-z0-9_-]/g, '');
|
||||||
let suffix = 1;
|
let suffix = 1;
|
||||||
while (existingTechnicalNames.includes(technicalName)) {
|
while (existingTechnicalNames.includes(technicalName)) {
|
||||||
technicalName = [baseTechnicalName, suffix++].join('_');
|
technicalName = [baseTechnicalName, suffix++].join('_');
|
||||||
|
|||||||
@ -2,8 +2,14 @@ import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/c
|
|||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
import { Dossier, File } from '@red/domain';
|
import { Dossier, File } from '@red/domain';
|
||||||
import { FileDownloadService } from '@upload-download/services/file-download.service';
|
import { FileDownloadService } from '@upload-download/services/file-download.service';
|
||||||
import { CircleButtonType, CircleButtonTypes, Toaster } from '@iqser/common-ui';
|
import { CircleButtonType, CircleButtonTypes, defaultDialogConfig, Toaster } from '@iqser/common-ui';
|
||||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
import {
|
||||||
|
DownloadDialogComponent,
|
||||||
|
DownloadDialogData,
|
||||||
|
DownloadDialogResult,
|
||||||
|
} from '@shared/dialogs/download-dialog/download-dialog.component';
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@ -25,6 +31,7 @@ export class FileDownloadBtnComponent implements OnChanges {
|
|||||||
constructor(
|
constructor(
|
||||||
private readonly _permissionsService: PermissionsService,
|
private readonly _permissionsService: PermissionsService,
|
||||||
private readonly _fileDownloadService: FileDownloadService,
|
private readonly _fileDownloadService: FileDownloadService,
|
||||||
|
private readonly _dialog: MatDialog,
|
||||||
private readonly _toaster: Toaster,
|
private readonly _toaster: Toaster,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
@ -35,9 +42,20 @@ export class FileDownloadBtnComponent implements OnChanges {
|
|||||||
|
|
||||||
async downloadFiles($event: MouseEvent) {
|
async downloadFiles($event: MouseEvent) {
|
||||||
$event.stopPropagation();
|
$event.stopPropagation();
|
||||||
const dossierId = this.files[0].dossierId;
|
const ref = this._dialog.open<DownloadDialogComponent, DownloadDialogData, DownloadDialogResult>(DownloadDialogComponent, {
|
||||||
const filesIds = this.files.map(f => f.id);
|
...defaultDialogConfig,
|
||||||
await firstValueFrom(this._fileDownloadService.downloadFiles(filesIds, dossierId));
|
data: { dossier: this.dossier, hasUnapprovedDocuments: this.files.some(file => !file.isApproved) },
|
||||||
|
});
|
||||||
|
const result = await firstValueFrom(ref.afterClosed());
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this._fileDownloadService.downloadFiles({
|
||||||
|
dossierId: this.dossier.id,
|
||||||
|
fileIds: this.files.map(f => f.id),
|
||||||
|
...result,
|
||||||
|
});
|
||||||
this._toaster.info(_('download-status.queued'));
|
this._toaster.info(_('download-status.queued'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core';
|
import { ChangeDetectionStrategy, Component, Input, OnChanges, SimpleChanges, ViewChild } from '@angular/core';
|
||||||
import { Action, ActionTypes, File } from '@red/domain';
|
import { Action, ActionTypes, Dossier, File } from '@red/domain';
|
||||||
import {
|
import {
|
||||||
CircleButtonType,
|
CircleButtonType,
|
||||||
|
defaultDialogConfig,
|
||||||
IqserTooltipPosition,
|
IqserTooltipPosition,
|
||||||
OverlappingElements,
|
OverlappingElements,
|
||||||
ScrollableParentView,
|
ScrollableParentView,
|
||||||
@ -13,6 +14,12 @@ import { FileDownloadService } from '@upload-download/services/file-download.ser
|
|||||||
import { PermissionsService } from '@services/permissions.service';
|
import { PermissionsService } from '@services/permissions.service';
|
||||||
import { firstValueFrom } from 'rxjs';
|
import { firstValueFrom } from 'rxjs';
|
||||||
import { MatMenuTrigger } from '@angular/material/menu';
|
import { MatMenuTrigger } from '@angular/material/menu';
|
||||||
|
import {
|
||||||
|
DownloadDialogComponent,
|
||||||
|
DownloadDialogData,
|
||||||
|
DownloadDialogResult,
|
||||||
|
} from '@shared/dialogs/download-dialog/download-dialog.component';
|
||||||
|
import { MatDialog } from '@angular/material/dialog';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'redaction-expandable-file-actions',
|
selector: 'redaction-expandable-file-actions',
|
||||||
@ -39,8 +46,13 @@ export class ExpandableFileActionsComponent implements OnChanges {
|
|||||||
private readonly _fileDownloadService: FileDownloadService,
|
private readonly _fileDownloadService: FileDownloadService,
|
||||||
private readonly _toaster: Toaster,
|
private readonly _toaster: Toaster,
|
||||||
private readonly _permissionsService: PermissionsService,
|
private readonly _permissionsService: PermissionsService,
|
||||||
|
private readonly _dialog: MatDialog,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
get overlappingElement() {
|
||||||
|
return this.helpModeKey === 'document_features_in_editor' ? OverlappingElements.USER_MENU : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges) {
|
ngOnChanges(changes: SimpleChanges) {
|
||||||
if (changes.actions || changes.maxWidth || changes.minWidth) {
|
if (changes.actions || changes.maxWidth || changes.minWidth) {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
@ -72,7 +84,7 @@ export class ExpandableFileActionsComponent implements OnChanges {
|
|||||||
// Patch download button
|
// Patch download button
|
||||||
const downloadBtn = this.actions.find(btn => btn.type === ActionTypes.downloadBtn);
|
const downloadBtn = this.actions.find(btn => btn.type === ActionTypes.downloadBtn);
|
||||||
if (downloadBtn) {
|
if (downloadBtn) {
|
||||||
downloadBtn.action = ($event: MouseEvent) => this._downloadFiles($event, downloadBtn.files);
|
downloadBtn.action = ($event: MouseEvent) => this._downloadFiles($event, downloadBtn.files, downloadBtn.dossier);
|
||||||
downloadBtn.disabled = !this._permissionsService.canDownloadFiles(downloadBtn.files, downloadBtn.dossier);
|
downloadBtn.disabled = !this._permissionsService.canDownloadFiles(downloadBtn.files, downloadBtn.dossier);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,20 +95,27 @@ export class ExpandableFileActionsComponent implements OnChanges {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async _downloadFiles($event: MouseEvent, files: File[]) {
|
|
||||||
$event.stopPropagation();
|
|
||||||
const dossierId = files[0].dossierId;
|
|
||||||
const filesIds = files.map(f => f.id);
|
|
||||||
await firstValueFrom(this._fileDownloadService.downloadFiles(filesIds, dossierId));
|
|
||||||
this._toaster.info(_('download-status.queued'));
|
|
||||||
}
|
|
||||||
|
|
||||||
onButtonClick(button: Action, $event: MouseEvent) {
|
onButtonClick(button: Action, $event: MouseEvent) {
|
||||||
button.action($event);
|
button.action($event);
|
||||||
this.matMenu.closeMenu();
|
this.matMenu.closeMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
get overlappingElement() {
|
private async _downloadFiles($event: MouseEvent, files: File[], dossier: Dossier) {
|
||||||
return this.helpModeKey === 'document_features_in_editor' ? OverlappingElements.USER_MENU : undefined;
|
$event.stopPropagation();
|
||||||
|
const ref = this._dialog.open<DownloadDialogComponent, DownloadDialogData, DownloadDialogResult>(DownloadDialogComponent, {
|
||||||
|
...defaultDialogConfig,
|
||||||
|
data: { dossier, hasUnapprovedDocuments: files.some(file => !file.isApproved) },
|
||||||
|
});
|
||||||
|
const result = await firstValueFrom(ref.afterClosed());
|
||||||
|
if (!result) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this._fileDownloadService.downloadFiles({
|
||||||
|
dossierId: dossier.id,
|
||||||
|
fileIds: files.map(f => f.id),
|
||||||
|
...result,
|
||||||
|
});
|
||||||
|
this._toaster.info(_('download-status.queued'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
flex-wrap: nowrap;
|
||||||
@include common-mixins.scroll-bar();
|
@include common-mixins.scroll-bar();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,7 +102,7 @@ export class AddDossierDialogComponent extends BaseDialogComponent implements On
|
|||||||
|
|
||||||
if (dossierTemplate) {
|
if (dossierTemplate) {
|
||||||
this.availableReportTypes =
|
this.availableReportTypes =
|
||||||
(await firstValueFrom(this._reportTemplateController.getAvailableReportTemplates(dossierTemplate.dossierTemplateId))) || [];
|
(await this._reportTemplateController.getAvailableReportTemplates(dossierTemplate.dossierTemplateId)) || [];
|
||||||
// update dropdown values
|
// update dropdown values
|
||||||
this.form.patchValue(
|
this.form.patchValue(
|
||||||
{
|
{
|
||||||
|
|||||||
@ -0,0 +1,61 @@
|
|||||||
|
<section class="dialog">
|
||||||
|
<form *ngIf="form" [formGroup]="form">
|
||||||
|
<div [translate]="'download-dialog.header'" class="dialog-header heading-l"></div>
|
||||||
|
|
||||||
|
<div *ngIf="data.hasUnapprovedDocuments" class="inline-dialog-toast toast-warning">
|
||||||
|
<div [translate]="'download-dialog.unapproved-files-warning'"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="dialog-content">
|
||||||
|
<redaction-select
|
||||||
|
*ngIf="availableReportTypes | async as reportTypes"
|
||||||
|
[label]="'report-type.label' | translate: { length: reportTypesLength }"
|
||||||
|
[optionTemplate]="reportTemplateOptionTemplate"
|
||||||
|
[options]="reportTypes"
|
||||||
|
[valueMapper]="reportTemplateValueMapper"
|
||||||
|
class="mb-16"
|
||||||
|
formControlName="reportTemplateIds"
|
||||||
|
></redaction-select>
|
||||||
|
|
||||||
|
<redaction-select
|
||||||
|
[label]="'download-type.label' | translate: { length: downloadFileTypesLength }"
|
||||||
|
[options]="downloadTypes"
|
||||||
|
formControlName="downloadFileTypes"
|
||||||
|
></redaction-select>
|
||||||
|
|
||||||
|
<div class="iqser-input-group required">
|
||||||
|
<label translate="download-dialog.form.redaction-preview-color"></label>
|
||||||
|
<input
|
||||||
|
[placeholder]="'download-dialog.form.redaction-preview-color-placeholder' | translate"
|
||||||
|
class="hex-color-input"
|
||||||
|
formControlName="redactionPreviewColor"
|
||||||
|
name="color"
|
||||||
|
type="text"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
(colorPickerChange)="form.controls.redactionPreviewColor.setValue($event)"
|
||||||
|
[colorPicker]="form.controls.redactionPreviewColor.value"
|
||||||
|
[cpOutputFormat]="'hex'"
|
||||||
|
[style.background]="form.controls.redactionPreviewColor.value"
|
||||||
|
class="input-icon"
|
||||||
|
>
|
||||||
|
<mat-icon
|
||||||
|
*ngIf="!form.controls.redactionPreviewColor.value || form.controls.redactionPreviewColor.value?.length === 0"
|
||||||
|
svgIcon="red:color-picker"
|
||||||
|
></mat-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="dialog-actions">
|
||||||
|
<button (click)="save()" [disabled]="form.invalid" color="primary" mat-flat-button type="submit">
|
||||||
|
{{ 'download-dialog.actions.save' | translate }}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<iqser-circle-button (action)="close()" class="dialog-close" icon="iqser:close"></iqser-circle-button>
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<ng-template #reportTemplateOptionTemplate let-option="option">
|
||||||
|
{{ option.fileName }} {{ option.multiFileReport ? ('reports-screen.multi-file-report' | translate) : '' }}
|
||||||
|
</ng-template>
|
||||||
@ -0,0 +1,100 @@
|
|||||||
|
import { Component, Inject } from '@angular/core';
|
||||||
|
import { Dossier, DownloadFileType, IReportTemplate } from '@red/domain';
|
||||||
|
import { downloadTypesForDownloadTranslations } from '@translations/download-types-translations';
|
||||||
|
import { ReportTemplateService } from '@services/report-template.service';
|
||||||
|
import { AbstractControl, FormBuilder } from '@angular/forms';
|
||||||
|
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||||
|
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
|
||||||
|
import { List } from '@iqser/common-ui';
|
||||||
|
|
||||||
|
export interface DownloadDialogData {
|
||||||
|
readonly dossier: Dossier;
|
||||||
|
readonly hasUnapprovedDocuments: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DownloadDialogResult {
|
||||||
|
downloadFileTypes: List<DownloadFileType>;
|
||||||
|
reportTemplateIds: List;
|
||||||
|
redactionPreviewColor: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'redaction-download-dialog',
|
||||||
|
templateUrl: './download-dialog.component.html',
|
||||||
|
styleUrls: ['./download-dialog.component.scss'],
|
||||||
|
})
|
||||||
|
export class DownloadDialogComponent {
|
||||||
|
readonly downloadTypes: { key: DownloadFileType; label: string }[] = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map(
|
||||||
|
(type: DownloadFileType) => ({
|
||||||
|
key: type,
|
||||||
|
label: downloadTypesForDownloadTranslations[type],
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
readonly availableReportTypes = this._availableReportTypes;
|
||||||
|
readonly form = this._getForm();
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private readonly _defaultColorsService: DefaultColorsService,
|
||||||
|
private readonly _reportTemplateController: ReportTemplateService,
|
||||||
|
private readonly _formBuilder: FormBuilder,
|
||||||
|
private readonly _dialogRef: MatDialogRef<DownloadDialogComponent, DownloadDialogResult>,
|
||||||
|
@Inject(MAT_DIALOG_DATA) readonly data: DownloadDialogData,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
get reportTypesLength() {
|
||||||
|
return this.form.controls.reportTemplateIds?.value?.length || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
get downloadFileTypesLength() {
|
||||||
|
return this.form.controls.downloadFileTypes?.value?.length || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private get _availableReportTypes() {
|
||||||
|
const dossierTemplateId = this.data.dossier.dossierTemplateId;
|
||||||
|
const result = this._reportTemplateController.getAvailableReportTemplates(dossierTemplateId);
|
||||||
|
return result.then(values => values ?? []);
|
||||||
|
}
|
||||||
|
|
||||||
|
reportTemplateValueMapper = (reportTemplate: IReportTemplate) => reportTemplate.templateId;
|
||||||
|
|
||||||
|
async save() {
|
||||||
|
const result: DownloadDialogResult = {
|
||||||
|
reportTemplateIds: this.form.controls.reportTemplateIds.value,
|
||||||
|
downloadFileTypes: this.form.controls.downloadFileTypes.value,
|
||||||
|
redactionPreviewColor: this.form.controls.redactionPreviewColor.value,
|
||||||
|
};
|
||||||
|
|
||||||
|
this._dialogRef.close(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
close() {
|
||||||
|
this._dialogRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private _hasReportTemplateOrDownloadType(control: AbstractControl) {
|
||||||
|
const atLeastAReportSelected = control.get('reportTemplateIds')?.value.length > 0;
|
||||||
|
const atLeastATypeSelected = control.get('downloadFileTypes')?.value.length > 0;
|
||||||
|
|
||||||
|
return atLeastATypeSelected || atLeastAReportSelected ? null : { reportTemplateIds: true, downloadFileTypes: true };
|
||||||
|
}
|
||||||
|
|
||||||
|
private _getForm() {
|
||||||
|
const previewColor = this._defaultColorsService.getColor(this.data.dossier.dossierTemplateId, 'previewColor');
|
||||||
|
return this._formBuilder.group(
|
||||||
|
{
|
||||||
|
reportTemplateIds: [this.data.dossier.reportTemplateIds],
|
||||||
|
downloadFileTypes: [this.data.dossier.downloadFileTypes],
|
||||||
|
redactionPreviewColor: [previewColor],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
validators: [control => this._hasReportTemplateOrDownloadType(control), control => this._isHexColor(control)],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private _isHexColor(control: AbstractControl) {
|
||||||
|
const color = control.get('redactionPreviewColor')?.value;
|
||||||
|
const isHexColor = /^#[0-9A-F]{6}$/i.test(color);
|
||||||
|
return isHexColor ? null : { redactionPreviewColor: true };
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -42,6 +42,7 @@ import { AddEditEntityComponent } from './components/add-edit-entity/add-edit-en
|
|||||||
import { ColorPickerModule } from 'ngx-color-picker';
|
import { ColorPickerModule } from 'ngx-color-picker';
|
||||||
import { WatermarkSelectorComponent } from './components/dossier-watermark-selector/watermark-selector.component';
|
import { WatermarkSelectorComponent } from './components/dossier-watermark-selector/watermark-selector.component';
|
||||||
import { OcrProgressBarComponent } from './components/ocr-progress-bar/ocr-progress-bar.component';
|
import { OcrProgressBarComponent } from './components/ocr-progress-bar/ocr-progress-bar.component';
|
||||||
|
import { DownloadDialogComponent } from './dialogs/download-dialog/download-dialog.component';
|
||||||
|
|
||||||
const buttons = [FileDownloadBtnComponent];
|
const buttons = [FileDownloadBtnComponent];
|
||||||
|
|
||||||
@ -76,7 +77,7 @@ const services = [SharedDialogService];
|
|||||||
const modules = [MatConfigModule, ScrollingModule, IconsModule, FormsModule, ReactiveFormsModule, ColorPickerModule];
|
const modules = [MatConfigModule, ScrollingModule, IconsModule, FormsModule, ReactiveFormsModule, ColorPickerModule];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [...components, ...utils, EditorComponent],
|
declarations: [...components, ...utils, EditorComponent, DownloadDialogComponent],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
...modules,
|
...modules,
|
||||||
|
|||||||
@ -29,11 +29,9 @@ export class FileDownloadService extends EntitiesService<IDownloadStatus, Downlo
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadFiles(fileIds: List, dossierId: string): Observable<DownloadStatus[]> {
|
downloadFiles(request: IPrepareDownloadRequest): Promise<DownloadStatus[]> {
|
||||||
return this.prepareDownload({
|
const prepare = this.prepareDownload(request).pipe(switchMap(() => this.loadAll()));
|
||||||
fileIds,
|
return firstValueFrom(prepare);
|
||||||
dossierId,
|
|
||||||
}).pipe(switchMap(() => this.loadAll()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadAll(): Observable<DownloadStatus[]> {
|
loadAll(): Observable<DownloadStatus[]> {
|
||||||
@ -61,7 +59,7 @@ export class FileDownloadService extends EntitiesService<IDownloadStatus, Downlo
|
|||||||
|
|
||||||
@Validate()
|
@Validate()
|
||||||
prepareDownload(@RequiredParam() body: IPrepareDownloadRequest): Observable<IDownloadResponse> {
|
prepareDownload(@RequiredParam() body: IPrepareDownloadRequest): Observable<IDownloadResponse> {
|
||||||
return this._post(body, `${this._defaultModelPath}/prepare`);
|
return this._post(body, `${this._defaultModelPath}/prepare-option`);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Validate()
|
@Validate()
|
||||||
|
|||||||
@ -40,6 +40,20 @@ export class RssService extends GenericService<void> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Validate()
|
||||||
|
override(
|
||||||
|
@RequiredParam() dossierId: string,
|
||||||
|
@RequiredParam() fileId: string,
|
||||||
|
@RequiredParam() componentOverrides: Record<string, string>,
|
||||||
|
) {
|
||||||
|
return this._post({ componentOverrides }, `rss/override/${dossierId}/${fileId}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Validate()
|
||||||
|
revertOverride(@RequiredParam() dossierId: string, @RequiredParam() fileId: string, @RequiredParam() components: string[]) {
|
||||||
|
return this._post({ components }, `rss/override/revert/${dossierId}/${fileId}`);
|
||||||
|
}
|
||||||
|
|
||||||
exportJSON(dossierId: string, fileId: string, name: string) {
|
exportJSON(dossierId: string, fileId: string, name: string) {
|
||||||
return this.getRSSData(dossierId, fileId).pipe(
|
return this.getRSSData(dossierId, fileId).pipe(
|
||||||
tap(data => {
|
tap(data => {
|
||||||
|
|||||||
@ -261,7 +261,7 @@ export class PermissionsService {
|
|||||||
if (files.length === 0) {
|
if (files.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return this.isApprover(dossier) && files.reduce((prev, file) => prev && file.isApproved, true);
|
return this.isApprover(dossier) && files.reduce((prev, file) => prev && !file.isInitialProcessing, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
canSoftDeleteDossier(dossier: IDossier): boolean {
|
canSoftDeleteDossier(dossier: IDossier): boolean {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { GenericService, HeadersConfiguration, RequiredParam, Validate } from '@iqser/common-ui';
|
import { GenericService, HeadersConfiguration, RequiredParam, Validate } from '@iqser/common-ui';
|
||||||
import { IPlaceholdersResponse, IReportTemplate } from '@red/domain';
|
import { IPlaceholdersResponse, IReportTemplate } from '@red/domain';
|
||||||
import { Observable, of } from 'rxjs';
|
import { firstValueFrom, Observable, of } from 'rxjs';
|
||||||
import { HttpResponse } from '@angular/common/http';
|
import { HttpResponse } from '@angular/common/http';
|
||||||
import { catchError } from 'rxjs/operators';
|
import { catchError } from 'rxjs/operators';
|
||||||
|
|
||||||
@ -34,7 +34,8 @@ export class ReportTemplateService extends GenericService<unknown> {
|
|||||||
|
|
||||||
@Validate()
|
@Validate()
|
||||||
getAvailableReportTemplates(@RequiredParam() dossierTemplateId: string) {
|
getAvailableReportTemplates(@RequiredParam() dossierTemplateId: string) {
|
||||||
return this.getAll<IReportTemplate[]>(`${this._defaultModelPath}/${dossierTemplateId}`);
|
const request = this.getAll<IReportTemplate[]>(`${this._defaultModelPath}/${dossierTemplateId}`);
|
||||||
|
return firstValueFrom(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Validate()
|
@Validate()
|
||||||
|
|||||||
@ -9,3 +9,12 @@ export const downloadTypesTranslations: { [key in DownloadFileType]: string } =
|
|||||||
FLATTEN: _('download-type.flatten'),
|
FLATTEN: _('download-type.flatten'),
|
||||||
DELTA_PREVIEW: _('download-type.delta-preview'),
|
DELTA_PREVIEW: _('download-type.delta-preview'),
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
export const downloadTypesForDownloadTranslations: { [key in DownloadFileType]: string } = {
|
||||||
|
ORIGINAL: _('download-type.original'),
|
||||||
|
PREVIEW: _('download-type.preview'),
|
||||||
|
REDACTED: _('download-type.redacted-only'),
|
||||||
|
ANNOTATED: _('download-type.annotated'),
|
||||||
|
FLATTEN: _('download-type.flatten'),
|
||||||
|
DELTA_PREVIEW: _('download-type.delta-preview'),
|
||||||
|
} as const;
|
||||||
|
|||||||
@ -13,7 +13,7 @@ export class RedRoleGuard extends IqserRoleGuard {
|
|||||||
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
|
async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
|
||||||
const currentUser = this._userService.currentUser;
|
const currentUser = this._userService.currentUser;
|
||||||
|
|
||||||
if (!currentUser.hasAnyRole) {
|
if (!currentUser?.hasAnyRole) {
|
||||||
await this._router.navigate(['/auth-error']);
|
await this._router.navigate(['/auth-error']);
|
||||||
this._loadingService.stop();
|
this._loadingService.stop();
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@ -1017,6 +1017,17 @@
|
|||||||
"active": "",
|
"active": "",
|
||||||
"archive": ""
|
"archive": ""
|
||||||
},
|
},
|
||||||
|
"download-dialog": {
|
||||||
|
"actions": {
|
||||||
|
"save": ""
|
||||||
|
},
|
||||||
|
"form": {
|
||||||
|
"redaction-preview-color": "",
|
||||||
|
"redaction-preview-color-placeholder": ""
|
||||||
|
},
|
||||||
|
"header": "",
|
||||||
|
"unapproved-files-warning": ""
|
||||||
|
},
|
||||||
"download-includes": "Wählen Sie die Dokumente für Ihr Download-Paket aus",
|
"download-includes": "Wählen Sie die Dokumente für Ihr Download-Paket aus",
|
||||||
"download-status": {
|
"download-status": {
|
||||||
"queued": "Ihr Download wurde zur Warteschlange hinzugefügt. Hier finden Sie alle angeforderten Downloads: <a href='/main/downloads'>My Downloads<a/>."
|
"queued": "Ihr Download wurde zur Warteschlange hinzugefügt. Hier finden Sie alle angeforderten Downloads: <a href='/main/downloads'>My Downloads<a/>."
|
||||||
@ -1028,7 +1039,8 @@
|
|||||||
"label": "{length} Dokumenten{length, plural, one{version} other{versionen}}",
|
"label": "{length} Dokumenten{length, plural, one{version} other{versionen}}",
|
||||||
"original": "Optimiertes PDF",
|
"original": "Optimiertes PDF",
|
||||||
"preview": "PDF-Vorschau",
|
"preview": "PDF-Vorschau",
|
||||||
"redacted": "geschwärztes PDF"
|
"redacted": "geschwärztes PDF",
|
||||||
|
"redacted-only": ""
|
||||||
},
|
},
|
||||||
"downloads-list": {
|
"downloads-list": {
|
||||||
"actions": {
|
"actions": {
|
||||||
@ -1941,9 +1953,13 @@
|
|||||||
},
|
},
|
||||||
"rss-dialog": {
|
"rss-dialog": {
|
||||||
"actions": {
|
"actions": {
|
||||||
|
"cancel-edit": "",
|
||||||
"close": "",
|
"close": "",
|
||||||
|
"edit": "",
|
||||||
"export-json": "",
|
"export-json": "",
|
||||||
"export-xml": ""
|
"export-xml": "",
|
||||||
|
"save": "",
|
||||||
|
"undo": ""
|
||||||
},
|
},
|
||||||
"title": ""
|
"title": ""
|
||||||
},
|
},
|
||||||
|
|||||||
@ -849,7 +849,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"download-file": "Download",
|
"download-file": "Download",
|
||||||
"download-file-disabled": "You need to be approver in the dossier and the {count, plural, one{file needs} other{files need}} to be approved in order to download.",
|
"download-file-disabled": "You need to be approver in the dossier and the {count, plural, one{file needs} other{files need}} to be initially processed in order to download.",
|
||||||
"file-listing": {
|
"file-listing": {
|
||||||
"file-entry": {
|
"file-entry": {
|
||||||
"file-error": "Re-processing required",
|
"file-error": "Re-processing required",
|
||||||
@ -1017,6 +1017,17 @@
|
|||||||
"active": "Active",
|
"active": "Active",
|
||||||
"archive": "Archived"
|
"archive": "Archived"
|
||||||
},
|
},
|
||||||
|
"download-dialog": {
|
||||||
|
"actions": {
|
||||||
|
"save": "Download"
|
||||||
|
},
|
||||||
|
"form": {
|
||||||
|
"redaction-preview-color": "Redaction preview color",
|
||||||
|
"redaction-preview-color-placeholder": "#000000"
|
||||||
|
},
|
||||||
|
"header": "Download options",
|
||||||
|
"unapproved-files-warning": "This download contains unapproved file(s)"
|
||||||
|
},
|
||||||
"download-includes": "Choose what is included at download:",
|
"download-includes": "Choose what is included at download:",
|
||||||
"download-status": {
|
"download-status": {
|
||||||
"queued": "Your download has been queued, you can see all your requested downloads here: <a href='/ui/main/downloads'>My Downloads<a/>."
|
"queued": "Your download has been queued, you can see all your requested downloads here: <a href='/ui/main/downloads'>My Downloads<a/>."
|
||||||
@ -1028,7 +1039,8 @@
|
|||||||
"label": "{length} document {length, plural, one{version} other{versions}}",
|
"label": "{length} document {length, plural, one{version} other{versions}}",
|
||||||
"original": "Optimized PDF",
|
"original": "Optimized PDF",
|
||||||
"preview": "Preview PDF",
|
"preview": "Preview PDF",
|
||||||
"redacted": "Redacted PDF"
|
"redacted": "Redacted PDF",
|
||||||
|
"redacted-only": "Redacted PDF (approved documents only)"
|
||||||
},
|
},
|
||||||
"downloads-list": {
|
"downloads-list": {
|
||||||
"actions": {
|
"actions": {
|
||||||
@ -1941,9 +1953,13 @@
|
|||||||
},
|
},
|
||||||
"rss-dialog": {
|
"rss-dialog": {
|
||||||
"actions": {
|
"actions": {
|
||||||
|
"cancel-edit": "Cancel",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
|
"edit": "Edit",
|
||||||
"export-json": "Export JSON",
|
"export-json": "Export JSON",
|
||||||
"export-xml": "Export XML"
|
"export-xml": "Export XML",
|
||||||
|
"save": "Save",
|
||||||
|
"undo": "Undo"
|
||||||
},
|
},
|
||||||
"title": "Structured Component Management"
|
"title": "Structured Component Management"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1017,6 +1017,17 @@
|
|||||||
"active": "",
|
"active": "",
|
||||||
"archive": ""
|
"archive": ""
|
||||||
},
|
},
|
||||||
|
"download-dialog": {
|
||||||
|
"actions": {
|
||||||
|
"save": ""
|
||||||
|
},
|
||||||
|
"form": {
|
||||||
|
"redaction-preview-color": "",
|
||||||
|
"redaction-preview-color-placeholder": ""
|
||||||
|
},
|
||||||
|
"header": "",
|
||||||
|
"unapproved-files-warning": ""
|
||||||
|
},
|
||||||
"download-includes": "Wählen Sie die Dokumente für Ihr Download-Paket aus",
|
"download-includes": "Wählen Sie die Dokumente für Ihr Download-Paket aus",
|
||||||
"download-status": {
|
"download-status": {
|
||||||
"queued": "Ihr Download wurde zur Warteschlange hinzugefügt. Hier finden Sie alle angeforderten Downloads: <a href='/main/downloads'>My Downloads<a/>."
|
"queued": "Ihr Download wurde zur Warteschlange hinzugefügt. Hier finden Sie alle angeforderten Downloads: <a href='/main/downloads'>My Downloads<a/>."
|
||||||
@ -1028,7 +1039,8 @@
|
|||||||
"label": "{length} Dokumenten{length, plural, one{version} other{versionen}}",
|
"label": "{length} Dokumenten{length, plural, one{version} other{versionen}}",
|
||||||
"original": "Optimiertes PDF",
|
"original": "Optimiertes PDF",
|
||||||
"preview": "PDF-Vorschau",
|
"preview": "PDF-Vorschau",
|
||||||
"redacted": "geschwärztes PDF"
|
"redacted": "geschwärztes PDF",
|
||||||
|
"redacted-only": ""
|
||||||
},
|
},
|
||||||
"downloads-list": {
|
"downloads-list": {
|
||||||
"actions": {
|
"actions": {
|
||||||
@ -1941,9 +1953,13 @@
|
|||||||
},
|
},
|
||||||
"rss-dialog": {
|
"rss-dialog": {
|
||||||
"actions": {
|
"actions": {
|
||||||
|
"cancel-edit": "",
|
||||||
"close": "",
|
"close": "",
|
||||||
|
"edit": "",
|
||||||
"export-json": "",
|
"export-json": "",
|
||||||
"export-xml": ""
|
"export-xml": "",
|
||||||
|
"save": "",
|
||||||
|
"undo": ""
|
||||||
},
|
},
|
||||||
"title": ""
|
"title": ""
|
||||||
},
|
},
|
||||||
|
|||||||
@ -849,7 +849,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"download-file": "Download",
|
"download-file": "Download",
|
||||||
"download-file-disabled": "You need to be approver in the dossier and the {count, plural, one{file needs} other{files need}} to be approved in order to download.",
|
"download-file-disabled": "You need to be approver in the dossier and the {count, plural, one{file needs} other{files need}} to be initially processed in order to download.",
|
||||||
"file-listing": {
|
"file-listing": {
|
||||||
"file-entry": {
|
"file-entry": {
|
||||||
"file-error": "Re-processing required",
|
"file-error": "Re-processing required",
|
||||||
@ -1017,6 +1017,17 @@
|
|||||||
"active": "Active",
|
"active": "Active",
|
||||||
"archive": "Archived"
|
"archive": "Archived"
|
||||||
},
|
},
|
||||||
|
"download-dialog": {
|
||||||
|
"actions": {
|
||||||
|
"save": "Download"
|
||||||
|
},
|
||||||
|
"form": {
|
||||||
|
"redaction-preview-color": "Redaction preview color",
|
||||||
|
"redaction-preview-color-placeholder": "#000000"
|
||||||
|
},
|
||||||
|
"header": "Download options",
|
||||||
|
"unapproved-files-warning": "This download contains unapproved file(s)"
|
||||||
|
},
|
||||||
"download-includes": "Choose what is included at download:",
|
"download-includes": "Choose what is included at download:",
|
||||||
"download-status": {
|
"download-status": {
|
||||||
"queued": "Your download has been queued, you can see all your requested downloads here: <a href='/ui/main/downloads'>My Downloads<a/>."
|
"queued": "Your download has been queued, you can see all your requested downloads here: <a href='/ui/main/downloads'>My Downloads<a/>."
|
||||||
@ -1028,7 +1039,8 @@
|
|||||||
"label": "{length} document {length, plural, one{version} other{versions}}",
|
"label": "{length} document {length, plural, one{version} other{versions}}",
|
||||||
"original": "Optimized PDF",
|
"original": "Optimized PDF",
|
||||||
"preview": "Preview PDF",
|
"preview": "Preview PDF",
|
||||||
"redacted": "Redacted PDF"
|
"redacted": "Redacted PDF",
|
||||||
|
"redacted-only": "Redacted PDF (redacted documents only)"
|
||||||
},
|
},
|
||||||
"downloads-list": {
|
"downloads-list": {
|
||||||
"actions": {
|
"actions": {
|
||||||
@ -1941,9 +1953,13 @@
|
|||||||
},
|
},
|
||||||
"rss-dialog": {
|
"rss-dialog": {
|
||||||
"actions": {
|
"actions": {
|
||||||
|
"cancel-edit": "Cancel",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
|
"edit": "Edit",
|
||||||
"export-json": "Export JSON",
|
"export-json": "Export JSON",
|
||||||
"export-xml": "Export XML"
|
"export-xml": "Export XML",
|
||||||
|
"save": "Save",
|
||||||
|
"undo": "Undo"
|
||||||
},
|
},
|
||||||
"title": "Structured Component Management"
|
"title": "Structured Component Management"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
Subproject commit 5f9c754abf0fb4fcc0606d811a66c5bbb88d164a
|
Subproject commit b58f1ca2fed8e8ddf2834c0fd15e48d00b6a1329
|
||||||
@ -2,8 +2,12 @@
|
|||||||
* Object containing information on which file and report types should be included in the download.
|
* Object containing information on which file and report types should be included in the download.
|
||||||
*/
|
*/
|
||||||
import { List } from '@iqser/common-ui';
|
import { List } from '@iqser/common-ui';
|
||||||
|
import { DownloadFileType } from '../shared';
|
||||||
|
|
||||||
export interface IPrepareDownloadRequest {
|
export interface IPrepareDownloadRequest {
|
||||||
readonly dossierId?: string;
|
readonly dossierId: string;
|
||||||
readonly fileIds?: List;
|
readonly fileIds: List;
|
||||||
|
readonly reportTemplateIds: List;
|
||||||
|
readonly downloadFileTypes: List<DownloadFileType>;
|
||||||
|
readonly redactionPreviewColor: string;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -146,7 +146,11 @@ export class File extends Entity<IFile> implements IFile {
|
|||||||
this.isUnderApproval = this.workflowStatus === WorkflowFileStatuses.UNDER_APPROVAL;
|
this.isUnderApproval = this.workflowStatus === WorkflowFileStatuses.UNDER_APPROVAL;
|
||||||
this.canBeApproved = !this.hasSuggestions && !this.isProcessing && !this.isError;
|
this.canBeApproved = !this.hasSuggestions && !this.isProcessing && !this.isError;
|
||||||
this.canBeOpened = !this.isError && !this.isUnprocessed && this.numberOfAnalyses > 0;
|
this.canBeOpened = !this.isError && !this.isUnprocessed && this.numberOfAnalyses > 0;
|
||||||
this.canBeOCRed = !this.excluded && !this.lastOCRTime && (this.isNew || this.isUnderReview || this.isUnderApproval);
|
this.canBeOCRed =
|
||||||
|
!this.excluded &&
|
||||||
|
!this.lastOCRTime &&
|
||||||
|
this.numberOfAnalyses !== 0 &&
|
||||||
|
(this.isNew || this.isUnderReview || this.isUnderApproval);
|
||||||
|
|
||||||
this.fileAttributes =
|
this.fileAttributes =
|
||||||
file.fileAttributes && file.fileAttributes.attributeIdToValue ? file.fileAttributes : { attributeIdToValue: {} };
|
file.fileAttributes && file.fileAttributes.attributeIdToValue ? file.fileAttributes : { attributeIdToValue: {} };
|
||||||
|
|||||||
2
package-lock.json
generated
2
package-lock.json
generated
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "redaction",
|
"name": "redaction",
|
||||||
"version": "3.813.0",
|
"version": "3.828.0",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "redaction",
|
"name": "redaction",
|
||||||
"version": "3.813.0",
|
"version": "3.828.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user