RED-10363: backport for all the locked rules changes.

This commit is contained in:
Nicoleta Panaghiu 2024-11-21 11:34:00 +02:00
parent 301616fb06
commit bceea2568b
13 changed files with 322 additions and 309 deletions

View File

@ -258,6 +258,7 @@ export const appModuleFactory = (config: AppConfig) => {
provide: MAT_TOOLTIP_DEFAULT_OPTIONS,
useValue: {
disableTooltipInteractivity: true,
showDelay: 1,
},
},
BaseDatePipe,

View File

@ -11,8 +11,9 @@ import { DictionaryService } from '@services/entity-services/dictionary.service'
import { DefaultColorsService } from '@services/entity-services/default-colors.service';
import { WatermarkService } from '@services/entity-services/watermark.service';
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
import { getConfig } from '@iqser/common-ui';
import { getConfig, Toaster } from '@iqser/common-ui';
import { RulesService } from '../modules/admin/services/rules.service';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
export function templateExistsWhenEnteringAdmin(): CanActivateFn {
return async function (route: ActivatedRouteSnapshot): Promise<boolean> {
@ -53,6 +54,8 @@ export function templateExistsWhenEnteringDossierList(): CanActivateFn {
const dictionaryService = inject(DictionaryService);
const defaultColorsService = inject(DefaultColorsService);
const watermarksService = inject(WatermarkService);
const rulesService = inject(RulesService);
const toaster = inject(Toaster);
const isDocumine = getConfig().IS_DOCUMINE;
await firstValueFrom(dashboardStatsService.loadForTemplate(dossierTemplateId));
@ -67,6 +70,10 @@ export function templateExistsWhenEnteringDossierList(): CanActivateFn {
await firstValueFrom(fileAttributesService.loadFileAttributesConfig(dossierTemplateId));
await firstValueFrom(dictionaryService.loadDictionaryDataForDossierTemplate(dossierTemplateId));
await firstValueFrom(defaultColorsService.loadForDossierTemplate(dossierTemplateId));
const rules = await firstValueFrom(rulesService.getFor(dossierTemplateId));
if (rules.timeoutDetected) {
toaster.error(_('dossier-listing.rules.timeoutError'));
}
if (!isDocumine) {
await firstValueFrom(watermarksService.loadForDossierTemplate(dossierTemplateId));
}

View File

@ -1,8 +1,8 @@
<ng-container (longPress)="forceReanalysisAction($event)" *ngIf="selectedFiles.length" redactionLongPress>
<ng-container (longPress)="forceReanalysisAction($event)" *ngIf="selectedFiles().length" redactionLongPress>
<redaction-expandable-file-actions
[actions]="buttons"
[buttonType]="buttonType"
[maxWidth]="maxWidth"
[actions]="buttons()"
[buttonType]="buttonType()"
[maxWidth]="maxWidth()"
[tooltipPosition]="IqserTooltipPositions.above"
>
</redaction-expandable-file-actions>

View File

@ -1,6 +1,6 @@
import { Component, Input, OnChanges } from '@angular/core';
import { Component, computed, input, signal } from '@angular/core';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { CircleButtonType, CircleButtonTypes } from '@iqser/common-ui';
import { CircleButtonType, CircleButtonTypes, Toaster } from '@iqser/common-ui';
import { Action, ActionTypes, Dossier, File, ProcessingFileStatuses } from '@red/domain';
import { PermissionsService } from '@services/permissions.service';
import { LongPressDirective, LongPressEvent } from '@shared/directives/long-press.directive';
@ -9,6 +9,8 @@ import { BulkActionsService } from '../../services/bulk-actions.service';
import { ExpandableFileActionsComponent } from '@shared/components/expandable-file-actions/expandable-file-actions.component';
import { IqserTooltipPositions } from '@common-ui/utils';
import { NgIf } from '@angular/common';
import { RulesService } from '../../../admin/services/rules.service';
import { firstValueFrom } from 'rxjs';
@Component({
selector: 'redaction-dossier-overview-bulk-actions [dossier] [selectedFiles]',
@ -17,218 +19,194 @@ import { NgIf } from '@angular/common';
standalone: true,
imports: [LongPressDirective, ExpandableFileActionsComponent, NgIf],
})
export class DossierOverviewBulkActionsComponent implements OnChanges {
#analysisForced: boolean;
#canAssignToSelf: boolean;
#canAssign: boolean;
#canDelete: boolean;
#canReanalyse: boolean;
#canDisableAutoAnalysis: boolean;
#canEnableAutoAnalysis: boolean;
#canOcr: boolean;
#canSetToNew: boolean;
#canSetToUnderReview: boolean;
#canSetToUnderApproval: boolean;
#isReadyForApproval: boolean;
#canApprove: boolean;
#canUndoApproval: boolean;
#canToggleAnalysis: boolean;
#assignTooltip: string;
#toggleAnalysisTooltip: string;
#allFilesAreExcluded: boolean;
#canMoveToSameState: boolean;
@Input() dossier: Dossier;
@Input() selectedFiles: File[];
@Input() buttonType: CircleButtonType = CircleButtonTypes.default;
@Input() maxWidth: number;
buttons: Action[];
export class DossierOverviewBulkActionsComponent {
readonly dossier = input<Dossier>();
readonly selectedFiles = input<File[]>();
readonly buttonType = input<CircleButtonType>(CircleButtonTypes.default);
readonly maxWidth = input<number>();
readonly buttons = computed(() => this.#buttons);
readonly IqserTooltipPositions = IqserTooltipPositions;
readonly #areRulesLocked = computed(() => this._rulesService.currentTemplateRules().timeoutDetected);
readonly #allFilesAreUnderReviewOrUnassigned = computed(() =>
this.selectedFiles().reduce((acc, file) => acc && (file.isUnderReview || file.isNew), true),
);
readonly #allFilesAreUnderApproval = computed(() => this.selectedFiles().reduce((acc, file) => acc && file.isUnderApproval, true));
readonly #allFilesAreExcluded = computed(() => this.selectedFiles().reduce((acc, file) => acc && file.excluded, true));
readonly #allFilesAreApproved = computed(() => this.selectedFiles().reduce((acc, file) => acc && file.isApproved, true));
readonly #canMoveToSameState = computed(
() => this.#allFilesAreUnderReviewOrUnassigned() || this.#allFilesAreUnderApproval() || this.#allFilesAreApproved(),
);
readonly #canAssign = computed(
() =>
this.#canMoveToSameState() &&
(this._permissionsService.canAssignUser(this.selectedFiles(), this.dossier()) ||
this._permissionsService.canUnassignUser(this.selectedFiles(), this.dossier())),
);
readonly #canAssignToSelf = computed(
() => this.#canMoveToSameState() && this._permissionsService.canAssignToSelf(this.selectedFiles(), this.dossier()),
);
readonly #canDelete = computed(() => this._permissionsService.canSoftDeleteFile(this.selectedFiles(), this.dossier()));
readonly #canReanalyse = computed(() => this._permissionsService.canReanalyseFile(this.selectedFiles(), this.dossier()));
readonly #canDisableAutoAnalysis = computed(() =>
this._permissionsService.canDisableAutoAnalysis(this.selectedFiles(), this.dossier()),
);
readonly #canEnableAutoAnalysis = computed(() => this._permissionsService.canEnableAutoAnalysis(this.selectedFiles(), this.dossier()));
readonly #canToggleAnalysis = computed(() => this._permissionsService.canToggleAnalysis(this.selectedFiles(), this.dossier()));
readonly #canOcr = computed(() => this._permissionsService.canOcrFile(this.selectedFiles(), this.dossier()));
readonly #canSetToNew = computed(() => this._permissionsService.canSetToNew(this.selectedFiles(), this.dossier()));
readonly #canSetToUnderReview = computed(() => this._permissionsService.canSetUnderReview(this.selectedFiles(), this.dossier()));
readonly #canSetToUnderApproval = computed(() => this._permissionsService.canSetUnderApproval(this.selectedFiles(), this.dossier()));
readonly #isReadyForApproval = computed(() => this._permissionsService.isReadyForApproval(this.selectedFiles(), this.dossier()));
readonly #canApprove = computed(() => this._permissionsService.canBeApproved(this.selectedFiles(), this.dossier()));
readonly #canUndoApproval = computed(() => this._permissionsService.canUndoApproval(this.selectedFiles(), this.dossier()));
readonly #assignTooltip = computed(() =>
this.#allFilesAreUnderApproval() ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer'),
);
readonly #toggleAnalysisTooltip = computed(() =>
this.#allFilesAreExcluded() ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable'),
);
readonly #analysisForced = signal(false);
constructor(
private readonly _permissionsService: PermissionsService,
private readonly _userPreferenceService: UserPreferenceService,
private readonly _bulkActionsService: BulkActionsService,
private readonly _rulesService: RulesService,
private readonly _toaster: Toaster,
) {}
private get _buttons(): Action[] {
get #buttons(): Action[] {
const actions: Action[] = [
{
id: 'delete-files-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.delete(this.selectedFiles),
action: () => this._bulkActionsService.delete(this.selectedFiles()),
tooltip: _('dossier-overview.bulk.delete'),
icon: 'iqser:trash',
show: this.#canDelete,
show: this.#canDelete(),
},
{
id: 'assign-files-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.assign(this.selectedFiles),
tooltip: this.#assignTooltip,
action: () => this._bulkActionsService.assign(this.selectedFiles()),
tooltip: this.#assignTooltip(),
icon: 'red:assign',
show: this.#canAssign,
show: this.#canAssign(),
},
{
id: 'assign-files-to-me-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.assignToMe(this.selectedFiles),
action: () => this._bulkActionsService.assignToMe(this.selectedFiles()),
tooltip: _('dossier-overview.assign-me'),
icon: 'red:assign-me',
show: this.#canAssignToSelf,
show: this.#canAssignToSelf(),
},
{
id: 'to-new-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.setToNew(this.selectedFiles),
action: () => this._bulkActionsService.setToNew(this.selectedFiles()),
tooltip: _('dossier-overview.back-to-new'),
icon: 'red:undo',
show: this.#canSetToNew,
show: this.#canSetToNew(),
},
{
id: 'to-under-approval-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.setToUnderApproval(this.selectedFiles),
action: () => this._bulkActionsService.setToUnderApproval(this.selectedFiles()),
tooltip: _('dossier-overview.under-approval'),
icon: 'red:ready-for-approval',
show: this.#canSetToUnderApproval,
show: this.#canSetToUnderApproval(),
},
{
id: 'to-under-review-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.backToUnderReview(this.selectedFiles),
action: () => this._bulkActionsService.backToUnderReview(this.selectedFiles()),
tooltip: _('dossier-overview.under-review'),
icon: 'red:undo',
show: this.#canSetToUnderReview,
show: this.#canSetToUnderReview(),
},
{
id: 'download-files-btn',
type: ActionTypes.downloadBtn,
show: !this.selectedFiles.some(file => file.processingStatus === ProcessingFileStatuses.ERROR || !file.lastProcessed),
files: this.selectedFiles,
dossier: this.dossier,
show: !this.selectedFiles().some(file => file.processingStatus === ProcessingFileStatuses.ERROR || !file.lastProcessed),
files: this.selectedFiles(),
dossier: this.dossier(),
},
{
id: 'approve-files-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.approve(this.selectedFiles),
action: () => this._bulkActionsService.approve(this.selectedFiles()),
disabled: !this.#canApprove,
tooltip: this.#canApprove ? _('dossier-overview.approve') : _('dossier-overview.approve-disabled'),
icon: 'red:approved',
show: this.#isReadyForApproval,
show: this.#isReadyForApproval(),
},
{
id: 'set-under-approval-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.setToUnderApproval(this.selectedFiles),
action: () => this._bulkActionsService.setToUnderApproval(this.selectedFiles()),
tooltip: _('dossier-overview.under-approval'),
icon: 'red:undo',
show: this.#canUndoApproval,
show: this.#canUndoApproval(),
},
{
id: 'ocr-files-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.ocr(this.selectedFiles),
action: () => this._bulkActionsService.ocr(this.selectedFiles()),
tooltip: _('dossier-overview.ocr-file'),
icon: 'iqser:ocr',
show: this.#canOcr,
show: this.#canOcr(),
},
{
id: 'reanalyse-files-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.reanalyse(this.selectedFiles),
tooltip: _('dossier-overview.bulk.reanalyse'),
action: () => this.#reanalyseBulk(this.selectedFiles()),
tooltip: this.#areRulesLocked() ? _('dossier-listing.rules.timeoutError') : _('dossier-overview.bulk.reanalyse'),
icon: 'iqser:refresh',
disabled: this.#areRulesLocked(),
show:
this.#canReanalyse &&
(this.#analysisForced || this.#canEnableAutoAnalysis || this.selectedFiles.every(file => file.isError)),
this.#canReanalyse() &&
(this.#analysisForced() || this.#canEnableAutoAnalysis() || this.selectedFiles().every(file => file.isError)),
},
{
id: 'stop-automatic-analysis-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles),
action: () => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles()),
tooltip: _('dossier-overview.stop-auto-analysis'),
icon: 'red:disable-analysis',
show: this.#canDisableAutoAnalysis,
show: this.#canDisableAutoAnalysis(),
},
{
id: 'start-automatic-analysis-btn',
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles),
action: () => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles()),
tooltip: _('dossier-overview.start-auto-analysis'),
icon: 'red:enable-analysis',
show: this.#canEnableAutoAnalysis,
show: this.#canEnableAutoAnalysis(),
},
{
id: 'toggle-analysis-btn',
type: ActionTypes.toggle,
action: () => this._bulkActionsService.toggleAnalysis(this.selectedFiles, !this.#allFilesAreExcluded),
tooltip: this.#toggleAnalysisTooltip,
checked: !this.#allFilesAreExcluded,
show: this.#canToggleAnalysis,
action: () => this._bulkActionsService.toggleAnalysis(this.selectedFiles(), !this.#allFilesAreExcluded()),
tooltip: this.#toggleAnalysisTooltip(),
checked: !this.#allFilesAreExcluded(),
show: this.#canToggleAnalysis(),
},
];
return actions.filter(btn => btn.show);
}
ngOnChanges() {
this._setup();
}
forceReanalysisAction($event: LongPressEvent) {
this.#analysisForced = !$event.touchEnd && this._userPreferenceService.isIqserDevMode;
this._setup();
this.#analysisForced.set(!$event.touchEnd && this._userPreferenceService.isIqserDevMode);
}
private _setup() {
if (!this.selectedFiles.length) {
async #reanalyseBulk(selectedFiles: File[]) {
const rules = await firstValueFrom(this._rulesService.getFor(this.dossier().dossierTemplateId));
if (rules.timeoutDetected) {
this._toaster.error(_('dossier-listing.rules.timeoutError'));
return;
}
const allFilesAreUnderReviewOrUnassigned = this.selectedFiles.reduce(
(acc, file) => acc && (file.isUnderReview || file.isNew),
true,
);
const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true);
const allFilesAreApproved = this.selectedFiles.reduce((acc, file) => acc && file.isApproved, true);
this.#allFilesAreExcluded = this.selectedFiles.reduce((acc, file) => acc && file.excluded, true);
this.#canMoveToSameState = allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval || allFilesAreApproved;
this.#canAssign =
this.#canMoveToSameState &&
(this._permissionsService.canAssignUser(this.selectedFiles, this.dossier) ||
this._permissionsService.canUnassignUser(this.selectedFiles, this.dossier));
this.#canAssignToSelf = this.#canMoveToSameState && this._permissionsService.canAssignToSelf(this.selectedFiles, this.dossier);
this.#canDelete = this._permissionsService.canSoftDeleteFile(this.selectedFiles, this.dossier);
this.#canReanalyse = this._permissionsService.canReanalyseFile(this.selectedFiles, this.dossier);
this.#canDisableAutoAnalysis = this._permissionsService.canDisableAutoAnalysis(this.selectedFiles, this.dossier);
this.#canEnableAutoAnalysis = this._permissionsService.canEnableAutoAnalysis(this.selectedFiles, this.dossier);
this.#canToggleAnalysis = this._permissionsService.canToggleAnalysis(this.selectedFiles, this.dossier);
this.#canOcr = this._permissionsService.canOcrFile(this.selectedFiles, this.dossier);
this.#canSetToNew = this._permissionsService.canSetToNew(this.selectedFiles, this.dossier);
this.#canSetToUnderReview = this._permissionsService.canSetUnderReview(this.selectedFiles, this.dossier);
this.#canSetToUnderApproval = this._permissionsService.canSetUnderApproval(this.selectedFiles, this.dossier);
this.#isReadyForApproval = this._permissionsService.isReadyForApproval(this.selectedFiles, this.dossier);
this.#canApprove = this._permissionsService.canBeApproved(this.selectedFiles, this.dossier);
this.#canUndoApproval = this._permissionsService.canUndoApproval(this.selectedFiles, this.dossier);
this.#assignTooltip = allFilesAreUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer');
this.#toggleAnalysisTooltip = this.#allFilesAreExcluded
? _('file-preview.toggle-analysis.enable')
: _('file-preview.toggle-analysis.disable');
this.buttons = this._buttons;
await this._bulkActionsService.reanalyse(selectedFiles);
}
}

View File

@ -1,7 +1,15 @@
import { AsyncPipe, NgForOf, NgIf, NgTemplateOutlet } from '@angular/common';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { CircleButtonComponent, CircleButtonTypes, getConfig, IqserLoadingModule, ProgressBarConfigModel, Toaster } from '@iqser/common-ui';
import {
CircleButtonComponent,
CircleButtonTypes,
getConfig,
IqserAllowDirective,
IqserLoadingModule,
ProgressBarConfigModel,
Toaster,
} from '@iqser/common-ui';
import { FilterService, INestedFilter } from '@iqser/common-ui/lib/filtering';
import { getCurrentUser, InitialsAvatarComponent } from '@iqser/common-ui/lib/users';
import { ContextComponent, getParam, IqserTooltipPositions, shareLast } from '@iqser/common-ui/lib/utils';
@ -61,6 +69,7 @@ interface DossierDetailsContext {
AssignUserDropdownComponent,
InitialsAvatarComponent,
TeamMembersComponent,
IqserAllowDirective,
],
})
export class DossierDetailsComponent extends ContextComponent<DossierDetailsContext> {

View File

@ -1,5 +1,5 @@
<iqser-page-header
(closeAction)="router.navigate([dossier.dossiersListRouterLink])"
(closeAction)="router.navigate([dossier().dossiersListRouterLink])"
[actionConfigs]="actionConfigs"
[helpModeKey]="'document'"
[showCloseButton]="true"
@ -23,13 +23,13 @@
[attr.help-mode-key]="'download_dossier_in_dossier'"
[buttonId]="'download-files-btn'"
[disabled]="downloadFilesDisabled$ | async"
[dossier]="dossier"
[dossier]="dossier()"
[files]="entitiesService.all$ | async"
></redaction-file-download-btn>
<iqser-circle-button
(action)="downloadDossierAsCSV()"
*ngIf="permissionsService.canDownloadCsvReport(dossier)"
*ngIf="permissionsService.canDownloadCsvReport(dossier())"
[attr.help-mode-key]="'download_csv'"
[disabled]="listingService.areSomeSelected$ | async"
[icon]="'iqser:csv'"
@ -38,17 +38,20 @@
<iqser-circle-button
(action)="reanalyseDossier()"
*ngIf="permissionsService.displayReanalyseBtn(dossier)"
[disabled]="listingService.areSomeSelected$ | async"
*ngIf="permissionsService.displayReanalyseBtn(dossier())"
[disabled]="(listingService.areSomeSelected$ | async) || areRulesLocked()"
[icon]="'iqser:refresh'"
[tooltipClass]="'small warn'"
[tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all' | translate"
[tooltip]="
(areRulesLocked() ? 'dossier-listing.rules.timeoutError' : 'dossier-overview.new-rule.toast.actions.reanalyse-all')
| translate
"
[type]="circleButtonTypes.warn"
></iqser-circle-button>
<iqser-circle-button
(action)="upload.emit()"
*ngIf="permissionsService.canUploadFiles(dossier)"
*ngIf="permissionsService.canUploadFiles(dossier())"
[attr.help-mode-key]="'upload_document'"
[buttonId]="'upload-document-btn'"
[icon]="'iqser:upload'"

View File

@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ChangeDetectionStrategy, Component, computed, EventEmitter, input, OnInit, Output } from '@angular/core';
import {
ActionConfig,
CircleButtonComponent,
@ -25,12 +25,13 @@ import { Router } from '@angular/router';
import { Roles } from '@users/roles';
import { SortingService } from '@iqser/common-ui/lib/sorting';
import { List, some } from '@iqser/common-ui/lib/utils';
import { ComponentLogService } from '@services/files/component-log.service';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
import { AsyncPipe, NgIf } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { FileDownloadBtnComponent } from '@shared/components/buttons/file-download-btn/file-download-btn.component';
import { ViewModeSelectionComponent } from '../view-mode-selection/view-mode-selection.component';
import { RulesService } from '../../../admin/services/rules.service';
import { ComponentLogService } from '@services/files/component-log.service';
import { MatMenu, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@Component({
selector: 'redaction-dossier-overview-screen-header [dossier] [upload]',
@ -39,20 +40,21 @@ import { ViewModeSelectionComponent } from '../view-mode-selection/view-mode-sel
imports: [
IqserListingModule,
CircleButtonComponent,
MatMenuTrigger,
IqserAllowDirective,
AsyncPipe,
TranslateModule,
FileDownloadBtnComponent,
NgIf,
ViewModeSelectionComponent,
DisableStopPropagationDirective,
MatMenuTrigger,
IqserAllowDirective,
MatMenu,
MatMenuItem,
],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DossierOverviewScreenHeaderComponent implements OnInit {
@Input() dossier: Dossier;
readonly dossier = input<Dossier>();
@Output() readonly upload = new EventEmitter<void>();
readonly circleButtonTypes = CircleButtonTypes;
readonly roles = Roles;
@ -60,6 +62,9 @@ export class DossierOverviewScreenHeaderComponent implements OnInit {
readonly downloadFilesDisabled$: Observable<boolean>;
readonly downloadComponentLogsDisabled$: Observable<boolean>;
readonly isDocumine = getConfig().IS_DOCUMINE;
readonly areRulesLocked = computed(() => {
return this._rulesService.currentTemplateRules().timeoutDetected;
});
constructor(
private readonly _toaster: Toaster,
@ -74,6 +79,7 @@ export class DossierOverviewScreenHeaderComponent implements OnInit {
private readonly _loadingService: LoadingService,
private readonly _primaryFileAttributeService: PrimaryFileAttributeService,
private readonly _componentLogService: ComponentLogService,
private readonly _rulesService: RulesService,
) {
const someNotProcessed$ = this.entitiesService.all$.pipe(some(file => !file.lastProcessed));
this.downloadFilesDisabled$ = combineLatest([this.listingService.areSomeSelected$, someNotProcessed$]).pipe(
@ -85,13 +91,19 @@ export class DossierOverviewScreenHeaderComponent implements OnInit {
}
ngOnInit() {
this.actionConfigs = this.configService.actionConfig(this.dossier.id, this.listingService.areSomeSelected$);
this.actionConfigs = this.configService.actionConfig(this.dossier().id, this.listingService.areSomeSelected$);
}
async reanalyseDossier() {
this._loadingService.start();
const rules = await firstValueFrom(this._rulesService.getFor(this.dossier().dossierTemplateId));
if (rules.timeoutDetected) {
this._toaster.error(_('dossier-listing.rules.timeoutError'));
this._loadingService.stop();
return;
}
try {
await this._reanalysisService.reanalyzeDossier(this.dossier, true);
await this._reanalysisService.reanalyzeDossier(this.dossier(), true);
this._toaster.success(_('dossier-overview.reanalyse-dossier.success'));
} catch (e) {
this._toaster.error(_('dossier-overview.reanalyse-dossier.error'));
@ -102,12 +114,12 @@ export class DossierOverviewScreenHeaderComponent implements OnInit {
async downloadDossierAsCSV() {
const displayedEntities = await firstValueFrom(this.listingService.displayed$);
const entities = this.sortingService.defaultSort(displayedEntities);
const fileName = this.dossier.dossierName + '.export.csv';
const fileName = this.dossier().dossierName + '.export.csv';
const mapper = (file?: File) => ({
...file,
hasAnnotations: file.hasRedactions,
assignee: this._userService.getName(file.assignee) || '-',
primaryAttribute: this._primaryFileAttributeService.getPrimaryFileAttributeValue(file, this.dossier.dossierTemplateId),
primaryAttribute: this._primaryFileAttributeService.getPrimaryFileAttributeValue(file, this.dossier().dossierTemplateId),
});
const documineOnlyFields = ['hasAnnotations'];
const redactionOnlyFields = ['hasHints', 'hasImages', 'hasUpdates', 'hasRedactions'];
@ -130,10 +142,10 @@ export class DossierOverviewScreenHeaderComponent implements OnInit {
}
downloadComponentAsJSON() {
return firstValueFrom(this._componentLogService.exportJSON(this.dossier.dossierTemplateId, this.dossier.dossierId));
return firstValueFrom(this._componentLogService.exportJSON(this.dossier().dossierTemplateId, this.dossier().dossierId));
}
async downloadComponentAsXML() {
return firstValueFrom(this._componentLogService.exportXML(this.dossier.dossierTemplateId, this.dossier.dossierId));
return firstValueFrom(this._componentLogService.exportXML(this.dossier().dossierTemplateId, this.dossier().dossierId));
}
}

View File

@ -1,25 +1,25 @@
<div *ngIf="isDossierOverviewList && fileAttributesService.isEditingFileAttribute() === false" class="action-buttons">
<div *ngIf="isDossierOverviewList() && fileAttributesService.isEditingFileAttribute() === false" class="action-buttons">
<ng-container *ngTemplateOutlet="actions"></ng-container>
<redaction-processing-indicator *ngIf="showStatusBar" [file]="file"></redaction-processing-indicator>
<redaction-processing-indicator *ngIf="showStatusBar()" [file]="file()"></redaction-processing-indicator>
<iqser-status-bar *ngIf="showStatusBar" [configs]="[{ color: file.workflowStatus, length: 1 }]"></iqser-status-bar>
<iqser-status-bar *ngIf="showStatusBar()" [configs]="[{ color: file().workflowStatus, length: 1 }]"></iqser-status-bar>
</div>
<ng-container *ngIf="isFilePreview || isDossierOverviewWorkflow">
<ng-container *ngIf="isFilePreview() || isDossierOverviewWorkflow()">
<ng-container *ngTemplateOutlet="actions"></ng-container>
</ng-container>
<ng-template #actions (longPress)="forceReanalysisAction($event)" redactionLongPress>
<div class="file-actions">
<redaction-expandable-file-actions
[actions]="buttons"
[id]="'actions-for-' + file.fileId"
[maxWidth]="maxWidth"
[minWidth]="minWidth"
[actions]="buttons()"
[id]="'actions-for-' + file().fileId"
[maxWidth]="maxWidth()"
[minWidth]="minWidth()"
[tooltipPosition]="tooltipPosition"
[helpModeKeyPrefix]="helpModeKeyPrefix"
[isDossierOverviewWorkflow]="isDossierOverviewWorkflow"
[helpModeKeyPrefix]="helpModeKeyPrefix()"
[isDossierOverviewWorkflow]="isDossierOverviewWorkflow()"
></redaction-expandable-file-actions>
</div>
</ng-template>

View File

@ -1,4 +1,4 @@
import { ChangeDetectorRef, Component, HostBinding, Injector, Input, OnChanges, Optional, ViewChild } from '@angular/core';
import { Component, computed, HostBinding, Injector, input, Optional, signal, ViewChild } from '@angular/core';
import { toObservable } from '@angular/core/rxjs-interop';
import { Router } from '@angular/router';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
@ -36,6 +36,7 @@ import { FileAssignService } from '../../services/file-assign.service';
import { ProcessingIndicatorComponent } from '@shared/components/processing-indicator/processing-indicator.component';
import { StatusBarComponent } from '@common-ui/shared';
import { NgIf, NgTemplateOutlet } from '@angular/common';
import { RulesService } from '../../../admin/services/rules.service';
@Component({
selector: 'redaction-file-actions',
@ -44,51 +45,92 @@ import { NgIf, NgTemplateOutlet } from '@angular/common';
standalone: true,
imports: [ProcessingIndicatorComponent, StatusBarComponent, LongPressDirective, ExpandableFileActionsComponent, NgTemplateOutlet, NgIf],
})
export class FileActionsComponent implements OnChanges {
@Input({ required: true }) file: File;
@Input({ required: true }) dossier: Dossier;
@Input({ required: true }) type: 'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow';
@Input() maxWidth: number;
@Input() minWidth: number;
@Input() helpModeKeyPrefix: 'dossier' | 'editor' = 'dossier';
readonly currentUser = getCurrentUser<User>();
toggleTooltip?: string;
assignTooltip?: string;
showDownload = false;
showSetToNew = false;
showUndoApproval = false;
showAssignToSelf = false;
showImportRedactions = false;
showAssign = false;
showDelete = false;
showOCR = false;
canReanalyse = false;
canDisableAutoAnalysis = false;
canEnableAutoAnalysis = false;
showUnderReview = false;
showUnderApproval = false;
showApprove = false;
canToggleAnalysis = false;
showToggleAnalysis = false;
showStatusBar = false;
showReanalyseFilePreview = false;
showReanalyseDossierOverview = false;
analysisForced = false;
isDossierOverview = false;
isDossierOverviewList = false;
isDossierOverviewWorkflow = false;
isFilePreview = false;
isDossierMember = false;
tooltipPosition = IqserTooltipPositions.above;
buttons: Action[];
export class FileActionsComponent {
@ViewChild(ExpandableFileActionsComponent)
private readonly _expandableActionsComponent: ExpandableFileActionsComponent;
readonly file = input.required<File>();
readonly dossier = input.required<Dossier>();
readonly type = input.required<'file-preview' | 'dossier-overview-list' | 'dossier-overview-workflow'>();
readonly maxWidth = input<number>();
readonly minWidth = input<number>();
readonly helpModeKeyPrefix = input<'dossier' | 'editor'>('dossier');
readonly singleEntityAction = input(false);
readonly currentUser = getCurrentUser<User>();
readonly tooltipPosition = IqserTooltipPositions.above;
readonly isDossierOverview = computed(() => this.type().startsWith('dossier-overview'));
readonly isDossierOverviewList = computed(() => this.type() === 'dossier-overview-list');
readonly isDossierOverviewWorkflow = computed(() => this.type() === 'dossier-overview-workflow');
readonly isFilePreview = computed(() => this.type() === 'file-preview');
readonly buttons = computed(() => this.#buttons);
readonly showStatusBar = computed(() => !this.file().isError && !this.file().isUnprocessed && this.isDossierOverviewList());
readonly #assignTooltip? = computed(() =>
this.file().isUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer'),
);
readonly #showSetToNew = computed(
() => this._permissionsService.canSetToNew(this.file(), this.dossier()) && !this.isDossierOverviewWorkflow(),
);
readonly #showUndoApproval = computed(
() => this._permissionsService.canUndoApproval(this.file(), this.dossier()) && !this.isDossierOverviewWorkflow(),
);
readonly #showAssignToSelf = computed(
() => this._permissionsService.canAssignToSelf(this.file(), this.dossier()) && this.isDossierOverview(),
);
readonly #showImportRedactions = computed(() => this._permissionsService.canImportRedactions(this.file(), this.dossier()));
readonly #showAssign = computed(
() =>
(this._permissionsService.canAssignUser(this.file(), this.dossier()) ||
this._permissionsService.canUnassignUser(this.file(), this.dossier())) &&
this.isDossierOverview(),
);
readonly #showDelete = computed(() => this._permissionsService.canSoftDeleteFile(this.file(), this.dossier()));
readonly #showOCR = computed(() => this._permissionsService.canOcrFile(this.file(), this.dossier()));
readonly #canReanalyse = computed(() => this._permissionsService.canReanalyseFile(this.file(), this.dossier()));
readonly #canEnableAutoAnalysis = computed(() => this._permissionsService.canEnableAutoAnalysis([this.file()], this.dossier()));
readonly #showUnderReview = computed(
() => this._permissionsService.canSetUnderReview(this.file(), this.dossier()) && !this.isDossierOverviewWorkflow(),
);
readonly #showUnderApproval = computed(
() => this._permissionsService.canSetUnderApproval(this.file(), this.dossier()) && !this.isDossierOverviewWorkflow(),
);
readonly #showApprove = computed(
() => this._permissionsService.isReadyForApproval(this.file(), this.dossier()) && !this.isDossierOverviewWorkflow(),
);
readonly #canToggleAnalysis = computed(() => this._permissionsService.canToggleAnalysis(this.file(), this.dossier()));
readonly #toggleTooltip? = computed(() => {
if (!this.#canToggleAnalysis()) {
return _('file-preview.toggle-analysis.only-managers');
}
return this.file()?.excluded ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable');
});
readonly #showToggleAnalysis = computed(
() => !!this.file().lastProcessed && this._permissionsService.showToggleAnalysis(this.dossier()),
);
readonly #analysisForced = signal(false);
readonly #showReanalyse = computed(
() => (this.#canReanalyse() || this.file().excludedFromAutomaticAnalysis || this.#analysisForced()) && !this.file().dossierArchived,
);
readonly #isDossierMember = computed(() => this._permissionsService.isDossierMember(this.dossier()));
readonly #showDownload = computed(
() => this._permissionsService.canDownloadRedactedFile() && !!this.file().lastProcessed && this.#isDossierMember(),
);
readonly #showReanalyseFilePreview = computed(
() => this.#showReanalyse() && this.isFilePreview() && !this.file().isApproved && this.#isDossierMember(),
);
readonly #showReanalyseDossierOverview = computed(
() => this.#showReanalyse() && this.isDossierOverview() && !this.file().isApproved && this.#isDossierMember(),
);
readonly #ariaExpanded$ = toObservable(this._documentInfoService?.shown);
readonly #areRulesLocked = computed(() => this._rulesService.currentTemplateRules().timeoutDetected);
readonly #isDocumine = getConfig().IS_DOCUMINE;
readonly #canDisableAutoAnalysis = computed(
() => !this.#isDocumine && this._permissionsService.canDisableAutoAnalysis([this.file()], this.dossier()),
);
constructor(
private readonly _injector: Injector,
private readonly _filesService: FilesService,
private readonly _changeRef: ChangeDetectorRef,
private readonly _loadingService: LoadingService,
private readonly _dialogService: DossiersDialogService,
private readonly _iqserDialog: IqserDialog,
@ -99,6 +141,8 @@ export class FileActionsComponent implements OnChanges {
private readonly _activeDossiersService: ActiveDossiersService,
private readonly _fileManagementService: FileManagementService,
private readonly _userPreferenceService: UserPreferenceService,
private readonly _rulesService: RulesService,
private readonly _toasterService: Toaster,
readonly fileAttributesService: FileAttributesService,
@Optional() private readonly _documentInfoService: DocumentInfoService,
@Optional() private readonly _excludedPagesService: ExcludedPagesService,
@ -109,15 +153,7 @@ export class FileActionsComponent implements OnChanges {
return !!this._expandableActionsComponent?.expanded;
}
private get _toggleTooltip(): string {
if (!this.canToggleAnalysis) {
return _('file-preview.toggle-analysis.only-managers');
}
return this.file?.excluded ? _('file-preview.toggle-analysis.enable') : _('file-preview.toggle-analysis.disable');
}
private get _buttons(): Action[] {
get #buttons() {
const actions: Action[] = [
{
id: 'btn-delete_file',
@ -125,16 +161,16 @@ export class FileActionsComponent implements OnChanges {
action: () => this.#openDeleteFileDialog(),
tooltip: _('dossier-overview.delete.action'),
icon: 'iqser:trash',
show: this.showDelete,
show: this.#showDelete(),
helpModeKey: 'delete_file',
},
{
id: 'btn-assign',
type: ActionTypes.circleBtn,
action: () => this.#assign(),
tooltip: this.assignTooltip,
tooltip: this.#assignTooltip(),
icon: 'red:assign',
show: this.showAssign,
show: this.#showAssign(),
helpModeKey: 'assign_user',
},
{
@ -143,7 +179,7 @@ export class FileActionsComponent implements OnChanges {
action: () => this.#assignToMe(),
tooltip: _('dossier-overview.assign-me'),
icon: 'red:assign-me',
show: this.showAssignToSelf,
show: this.#showAssignToSelf(),
helpModeKey: 'assign_user',
},
{
@ -152,17 +188,17 @@ export class FileActionsComponent implements OnChanges {
action: () => this.#openImportRedactionsDialog(),
tooltip: _('dossier-overview.import-redactions'),
icon: 'red:import_redactions',
show: this.showImportRedactions && !this._iqserPermissionsService.has(Roles.getRss),
show: this.#showImportRedactions() && !this._iqserPermissionsService.has(Roles.getRss),
helpModeKey: 'import_redactions',
},
{
id: 'btn-download_file',
type: ActionTypes.downloadBtn,
files: [this.file],
dossier: this.dossier,
files: [this.file()],
dossier: this.dossier(),
tooltipClass: 'small',
show: this.showDownload,
disabled: this.file.processingStatus === ProcessingFileStatuses.ERROR,
show: this.#showDownload(),
disabled: this.file().processingStatus === ProcessingFileStatuses.ERROR,
helpModeKey: 'download',
},
{
@ -170,7 +206,7 @@ export class FileActionsComponent implements OnChanges {
type: ActionTypes.circleBtn,
action: () => this.#toggleDocumentInfo(),
tooltip: _('file-preview.document-info'),
ariaExpanded: toObservable(this._documentInfoService?.shown, { injector: this._injector }),
ariaExpanded: this.#ariaExpanded$,
icon: 'red:status-info',
show: !!this._documentInfoService,
helpModeKey: 'document_info',
@ -180,10 +216,10 @@ export class FileActionsComponent implements OnChanges {
type: ActionTypes.circleBtn,
action: () => this.#toggleExcludePages(),
tooltip: _('file-preview.exclude-pages'),
ariaExpanded: toObservable(this._excludedPagesService?.shown, { injector: this._injector }),
showDot: !!this.file.excludedPages?.length,
ariaExpanded: this.#ariaExpanded$,
showDot: !!this.file().excludedPages?.length,
icon: 'red:exclude-pages',
show: !!this._excludedPagesService && this._permissionsService.canExcludePages(this.file, this.dossier),
show: !!this._excludedPagesService && this._permissionsService.canExcludePages(this.file(), this.dossier()),
helpModeKey: 'exclude_pages',
},
{
@ -192,7 +228,7 @@ export class FileActionsComponent implements OnChanges {
action: () => this.#setToNew(),
tooltip: _('dossier-overview.back-to-new'),
icon: 'red:undo',
show: this.showSetToNew,
show: this.#showSetToNew(),
helpModeKey: 'change_status',
},
{
@ -201,7 +237,7 @@ export class FileActionsComponent implements OnChanges {
action: () => this.#setFileUnderApproval(),
tooltip: _('dossier-overview.under-approval'),
icon: 'red:ready-for-approval',
show: this.showUnderApproval,
show: this.#showUnderApproval(),
helpModeKey: 'change_status',
},
{
@ -210,17 +246,17 @@ export class FileActionsComponent implements OnChanges {
action: () => this.#setFileUnderReview(),
tooltip: _('dossier-overview.under-review'),
icon: 'red:undo',
show: this.showUnderReview,
show: this.#showUnderReview(),
helpModeKey: 'change_status',
},
{
id: 'btn-set_file_approved',
type: ActionTypes.circleBtn,
action: () => this.setFileApproved(),
tooltip: this.file.canBeApproved ? _('dossier-overview.approve') : _('dossier-overview.approve-disabled'),
tooltip: this.file().canBeApproved ? _('dossier-overview.approve') : _('dossier-overview.approve-disabled'),
icon: 'red:approved',
disabled: !this.file.canBeApproved,
show: this.showApprove,
disabled: !this.file().canBeApproved,
show: this.#showApprove(),
helpModeKey: 'change_status',
},
{
@ -229,18 +265,17 @@ export class FileActionsComponent implements OnChanges {
action: () => this.#toggleAutomaticAnalysis(),
tooltip: _('dossier-overview.stop-auto-analysis'),
icon: 'red:disable-analysis',
show: this.canDisableAutoAnalysis,
show: this.#canDisableAutoAnalysis(),
helpModeKey: 'stop_analysis',
},
{
id: 'btn-reanalyse_file_preview',
type: ActionTypes.circleBtn,
action: () => this.#reanalyseFile(),
tooltip: _('file-preview.reanalyse-notification'),
tooltipClass: 'small',
tooltip: this.#areRulesLocked() ? _('dossier-listing.rules.timeoutError') : _('file-preview.reanalyse-notification'),
icon: 'iqser:refresh',
show: this.showReanalyseFilePreview,
disabled: this.file.isProcessing,
show: this.#showReanalyseFilePreview(),
disabled: this.file().isProcessing || this.#areRulesLocked(),
helpModeKey: 'stop_analysis',
},
{
@ -248,9 +283,9 @@ export class FileActionsComponent implements OnChanges {
type: ActionTypes.circleBtn,
action: () => this.#toggleAutomaticAnalysis(),
tooltip: _('dossier-overview.start-auto-analysis'),
buttonType: this.isFilePreview ? CircleButtonTypes.warn : CircleButtonTypes.default,
buttonType: this.isFilePreview() ? CircleButtonTypes.warn : CircleButtonTypes.default,
icon: 'red:enable-analysis',
show: this.canEnableAutoAnalysis,
show: this.#canEnableAutoAnalysis(),
helpModeKey: 'stop_analysis',
},
{
@ -259,7 +294,7 @@ export class FileActionsComponent implements OnChanges {
action: () => this.#setFileUnderApproval(),
tooltip: _('dossier-overview.under-approval'),
icon: 'red:undo',
show: this.showUndoApproval,
show: this.#showUndoApproval(),
helpModeKey: 'change_status',
},
{
@ -268,27 +303,28 @@ export class FileActionsComponent implements OnChanges {
action: () => this.#ocrFile(),
tooltip: _('dossier-overview.ocr-file'),
icon: 'iqser:ocr',
show: this.showOCR,
show: this.#showOCR(),
helpModeKey: 'automatic_text_recognition',
},
{
id: 'btn-reanalyse_file',
type: ActionTypes.circleBtn,
action: () => this.#reanalyseFile(),
tooltip: _('dossier-overview.reanalyse.action'),
tooltip: this.#areRulesLocked() ? _('dossier-listing.rules.timeoutError') : _('dossier-overview.reanalyse.action'),
icon: 'iqser:refresh',
show: this.showReanalyseDossierOverview,
show: this.#showReanalyseDossierOverview(),
disabled: this.#areRulesLocked(),
helpModeKey: 'stop_analysis',
},
{
id: 'btn-toggle_analysis',
type: ActionTypes.toggle,
action: () => this.#toggleAnalysis(),
disabled: !this.canToggleAnalysis,
tooltip: this.toggleTooltip,
class: { 'mr-24': this.isDossierOverviewList },
checked: !this.file.excluded,
show: this.showToggleAnalysis && this.isDossierMember,
disabled: !this.#canToggleAnalysis,
tooltip: this.#toggleTooltip(),
class: { 'mr-24': this.isDossierOverviewList() },
checked: !this.file().excluded,
show: this.#showToggleAnalysis() && this.#isDossierMember(),
helpModeKey: 'disable_extraction',
},
];
@ -296,33 +332,28 @@ export class FileActionsComponent implements OnChanges {
return actions.filter(btn => btn.show);
}
ngOnChanges() {
this.#setup();
}
async setFileApproved() {
if (!this.file.analysisRequired && !this.file.hasUpdates) {
if (!this.file().analysisRequired && !this.file().hasUpdates) {
await this.#setFileApproved();
return;
}
const data: IConfirmationDialogData = {
title: this.file.analysisRequired
title: this.file().analysisRequired
? _('confirmation-dialog.approve-file-without-analysis.title')
: _('confirmation-dialog.approve-file.title'),
question: this.file.analysisRequired
question: this.file().analysisRequired
? _('confirmation-dialog.approve-file-without-analysis.question')
: _('confirmation-dialog.approve-file.question'),
confirmationText: this.file.analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.confirmationText') : null,
denyText: this.file.analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.denyText') : null,
confirmationText: this.file().analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.confirmationText') : null,
denyText: this.file().analysisRequired ? _('confirmation-dialog.approve-file-without-analysis.denyText') : null,
};
this._dialogService.openDialog('confirm', data, () => this.#setFileApproved());
}
forceReanalysisAction($event: LongPressEvent) {
this.analysisForced = !$event.touchEnd && this._userPreferenceService.isIqserDevMode;
this.#setup();
this.#analysisForced.set(!$event.touchEnd && this._userPreferenceService.isIqserDevMode);
}
#showOCRConfirmationDialog(): Observable<boolean> {
@ -337,7 +368,7 @@ export class FileActionsComponent implements OnChanges {
}
#openImportRedactionsDialog() {
this._dialogService.openDialog('importRedactions', { dossierId: this.file.dossierId, fileId: this.file.fileId });
this._dialogService.openDialog('importRedactions', { dossierId: this.file().dossierId, fileId: this.file().fileId });
}
#openDeleteFileDialog() {
@ -350,8 +381,8 @@ export class FileActionsComponent implements OnChanges {
async () => {
this._loadingService.start();
try {
const dossier = this._activeDossiersService.find(this.file.dossierId);
await firstValueFrom(this._fileManagementService.delete([this.file], this.file.dossierId));
const dossier = this._activeDossiersService.find(this.file().dossierId);
await firstValueFrom(this._fileManagementService.delete([this.file()], this.file().dossierId));
await this._injector.get(Router).navigate([dossier.routerLink]);
} catch (error) {
this._injector.get(Toaster).error(_('error.http.generic'), { params: error });
@ -362,8 +393,8 @@ export class FileActionsComponent implements OnChanges {
}
#assign() {
const files = [this.file];
const targetStatus = this.file.workflowStatus;
const files = [this.file()];
const targetStatus = this.file().workflowStatus;
const withCurrentUserAsDefault = true;
const withUnassignedOption = true;
this._iqserDialog.openDefault(AssignReviewerApproverDialogComponent, {
@ -377,29 +408,34 @@ export class FileActionsComponent implements OnChanges {
}
async #assignToMe() {
await this._fileAssignService.assignToMe([this.file]);
await this._fileAssignService.assignToMe([this.file()]);
}
async #reanalyseFile() {
const rules = await firstValueFrom(this._rulesService.getFor(this.dossier().dossierTemplateId));
if (rules.timeoutDetected) {
this._toasterService.error(_('dossier-listing.rules.timeoutError'));
return;
}
const params: ReanalyzeQueryParams = {
force: true,
triggeredByUser: true,
};
await this._reanalysisService.reanalyzeFilesForDossier([this.file], this.file.dossierId, params);
await this._reanalysisService.reanalyzeFilesForDossier([this.file()], this.file().dossierId, params);
}
async #toggleAutomaticAnalysis() {
this._loadingService.start();
await firstValueFrom(this._reanalysisService.toggleAutomaticAnalysis(this.file.dossierId, [this.file]));
await firstValueFrom(this._reanalysisService.toggleAutomaticAnalysis(this.file().dossierId, [this.file()]));
this._loadingService.stop();
}
async #setFileUnderApproval() {
await this._fileAssignService.assignApprover(this.file, true);
await this._fileAssignService.assignApprover(this.file(), true);
}
async #ocrFile() {
if (this.file.lastManualChangeDate) {
if (this.file().lastManualChangeDate) {
const confirm = await firstValueFrom(this.#showOCRConfirmationDialog());
if (!confirm) {
return;
@ -412,92 +448,47 @@ export class FileActionsComponent implements OnChanges {
viewerHeaderService.disableRotationButtons();
this._loadingService.start();
await this._reanalysisService.ocrFiles([this.file], this.file.dossierId);
await this._reanalysisService.ocrFiles([this.file()], this.file().dossierId);
this._loadingService.stop();
}
async #setFileUnderReview() {
await this._fileAssignService.assignReviewer(this.file, true);
await this._fileAssignService.assignReviewer(this.file(), true);
}
async #toggleAnalysis() {
this._loadingService.start();
await this._reanalysisService.toggleAnalysis(this.file.dossierId, [this.file], !this.file.excluded);
await this._reanalysisService.toggleAnalysis(this.file().dossierId, [this.file()], !this.file().excluded);
this._loadingService.stop();
}
#setup() {
this.isDossierOverviewList = this.type === 'dossier-overview-list';
this.isDossierOverviewWorkflow = this.type === 'dossier-overview-workflow';
this.isDossierOverview = this.type.startsWith('dossier-overview');
this.isFilePreview = this.type === 'file-preview';
this.assignTooltip = this.file.isUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer');
this.showAssign =
(this._permissionsService.canAssignUser(this.file, this.dossier) ||
this._permissionsService.canUnassignUser(this.file, this.dossier)) &&
this.isDossierOverview;
this.showAssignToSelf = this._permissionsService.canAssignToSelf(this.file, this.dossier) && this.isDossierOverview;
this.showImportRedactions = this._permissionsService.canImportRedactions(this.file, this.dossier);
this.showSetToNew = this._permissionsService.canSetToNew(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
this.showUndoApproval = this._permissionsService.canUndoApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
this.showUnderReview = this._permissionsService.canSetUnderReview(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
this.showUnderApproval = this._permissionsService.canSetUnderApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
this.showApprove = this._permissionsService.isReadyForApproval(this.file, this.dossier) && !this.isDossierOverviewWorkflow;
this.canToggleAnalysis = this._permissionsService.canToggleAnalysis(this.file, this.dossier);
this.showToggleAnalysis = !!this.file.lastProcessed && this._permissionsService.showToggleAnalysis(this.dossier);
this.toggleTooltip = this._toggleTooltip;
this.isDossierMember = this._permissionsService.isDossierMember(this.dossier);
this.showDelete = this._permissionsService.canSoftDeleteFile(this.file, this.dossier);
this.showOCR = this._permissionsService.canOcrFile(this.file, this.dossier);
this.canReanalyse = this._permissionsService.canReanalyseFile(this.file, this.dossier);
this.canDisableAutoAnalysis = !this.#isDocumine && this._permissionsService.canDisableAutoAnalysis([this.file], this.dossier);
this.canEnableAutoAnalysis = this._permissionsService.canEnableAutoAnalysis([this.file], this.dossier);
this.showStatusBar = !this.file.isError && !this.file.isUnprocessed && this.isDossierOverviewList;
const showReanalyse = this.canReanalyse || this.file.excludedFromAutomaticAnalysis || this.analysisForced;
this.showReanalyseFilePreview = showReanalyse && this.isFilePreview && !this.file.isApproved && this.isDossierMember;
this.showReanalyseDossierOverview = showReanalyse && this.isDossierOverview && !this.file.isApproved && this.isDossierMember;
this.showDownload = this._permissionsService.canDownloadRedactedFile() && !!this.file.lastProcessed && this.isDossierMember;
this.buttons = this._buttons;
this._changeRef.markForCheck();
}
async #setFileApproved() {
this._loadingService.start();
await this._filesService.setApproved(this.file);
await this._filesService.setApproved(this.file());
this._loadingService.stop();
}
async #setToNew() {
this._loadingService.start();
await this._filesService.setToNew(this.file);
await this._filesService.setToNew(this.file());
this._loadingService.stop();
}
#toggleExcludePages() {
this._excludedPagesService.toggle();
const shown = this._excludedPagesService.shown();
setLocalStorageDataByFileId(this.file.id, 'show-exclude-pages', shown);
setLocalStorageDataByFileId(this.file().id, 'show-exclude-pages', shown);
if (shown) {
setLocalStorageDataByFileId(this.file.id, 'show-document-info', false);
setLocalStorageDataByFileId(this.file().id, 'show-document-info', false);
}
}
#toggleDocumentInfo() {
this._documentInfoService.toggle();
const shown = this._documentInfoService.shown();
setLocalStorageDataByFileId(this.file.id, 'show-document-info', shown);
setLocalStorageDataByFileId(this.file().id, 'show-document-info', shown);
if (shown) {
setLocalStorageDataByFileId(this.file.id, 'show-exclude-pages', false);
setLocalStorageDataByFileId(this.file().id, 'show-exclude-pages', false);
}
}
}

View File

@ -913,6 +913,9 @@
"reanalyse": {
"action": "Ganzes Dossier analysieren"
},
"rules": {
"timeoutError": "Regeln für Dossier-Vorlagen gesperrt!"
},
"stats": {
"analyzed-pages": "{count, plural, one{Seite} other{Seiten}}",
"total-people": "Benutzer"

View File

@ -913,6 +913,9 @@
"reanalyse": {
"action": "Analyze entire dossier"
},
"rules": {
"timeoutError": "Dossier template rules locked!"
},
"stats": {
"analyzed-pages": "{count, plural, one{Page} other{Pages}}",
"total-people": "Total users"

View File

@ -913,6 +913,9 @@
"reanalyse": {
"action": "Gesamtes Dossier analysieren"
},
"rules": {
"timeoutError": "Regeln für Dossier-Vorlagen gesperrt!"
},
"stats": {
"analyzed-pages": "{count, plural, one{Page} other{Pages}}",
"total-people": "Anzahl der Benutzer"

View File

@ -913,6 +913,9 @@
"reanalyse": {
"action": "Analyze entire dossier"
},
"rules": {
"timeoutError": "Dossier template rules locked!"
},
"stats": {
"analyzed-pages": "{count, plural, one{Page} other{Pages}}",
"total-people": "Total users"