+
+
+
+
+
-
-
- {{ 'edit-dossier-dialog.general-info.form.template' | translate }}
-
-
+
+ {{ 'edit-dossier-dialog.general-info.form.template' | translate }}
+
+
+ {{ dossierTemplate.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ 'edit-dossier-dialog.general-info.form.watermark' | translate }}
+
+
+
+
+
+ {{ 'edit-dossier-dialog.general-info.form.watermark-preview' | translate }}
+
+
+
+
+
+
+
+
+
+ {{ 'edit-dossier-dialog.general-info.form.due-date' | translate }}
+
-
-
-
-
-
-
-
- {{ 'edit-dossier-dialog.general-info.form.watermark' | translate }}
-
-
-
-
-
- {{ 'edit-dossier-dialog.general-info.form.watermark-preview' | translate }}
-
-
-
-
diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.scss b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.scss
index 695782375..cadbd6f7a 100644
--- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.scss
+++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.scss
@@ -23,3 +23,15 @@
border-top: none;
padding: 0;
}
+
+.fields-container {
+ flex-direction: column;
+
+ &:first-child {
+ margin-right: 40px;
+ }
+}
+
+redaction-small-chip {
+ margin-right: 8px;
+}
diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts
index 8b9d48bf1..622aca251 100644
--- a/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component.ts
@@ -1,7 +1,7 @@
import { Component, Input, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import * as moment from 'moment';
-import { Dossier, IDossierRequest, IDossierTemplate } from '@red/domain';
+import { Dossier, DossierState, IDossierRequest, IDossierTemplate } from '@red/domain';
import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface';
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
import { PermissionsService } from '@services/permissions.service';
@@ -14,7 +14,9 @@ import { DossiersService } from '@services/entity-services/dossiers.service';
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
import { firstValueFrom } from 'rxjs';
+import { DossierStateService } from '@services/entity-services/dossier-state.service';
import { DOSSIER_TEMPLATE_ID } from '@utils/constants';
+import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'redaction-edit-dossier-general-info',
@@ -29,9 +31,12 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
form: FormGroup;
hasDueDate: boolean;
dossierTemplates: IDossierTemplate[];
+ states: DossierState[];
+ currentStatus: DossierState;
constructor(
readonly permissionsService: PermissionsService,
+ private readonly _dossierStateService: DossierStateService,
private readonly _dossierTemplatesService: DossierTemplatesService,
private readonly _dossiersService: DossiersService,
private readonly _dossierStatsService: DossierStatsService,
@@ -40,6 +45,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
private readonly _router: Router,
private readonly _editDossierDialogRef: MatDialogRef
,
private readonly _toaster: Toaster,
+ private readonly _translateService: TranslateService,
) {}
get changed(): boolean {
@@ -67,12 +73,26 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
return this.hasDueDate && this.form.get('dueDate').value === null;
}
+ get statusPlaceholder(): string {
+ if (this.states.length === 0) {
+ return this._translateService.instant('edit-dossier-dialog.general-info.form.dossier-status.no-status-placeholder');
+ }
+
+ return (
+ this.currentStatus?.name ?? this._translateService.instant('edit-dossier-dialog.general-info.form.dossier-status.placeholder')
+ );
+ }
+
ngOnInit() {
- this._filterInvalidDossierTemplates();
- this.form = this._getForm();
+ this.#filterInvalidDossierTemplates();
+ this.form = this.#getForm();
if (!this.permissionsService.canEditDossier(this.dossier)) {
this.form.disable();
}
+ this.states = this._dossierStateService.all.filter(s => s.dossierTemplateId === this.dossier.dossierTemplateId);
+ if (this.dossier.dossierStatusId) {
+ this.currentStatus = this._dossierStateService.all.find(s => s.dossierStatusId === this.dossier.dossierStatusId);
+ }
this.hasDueDate = !!this.dossier.dueDate;
}
@@ -80,6 +100,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
this.form.reset({
dossierName: this.dossier.dossierName,
dossierTemplateId: this.dossier.dossierTemplateId,
+ dossierStatusId: this.dossier.dossierStatusId,
description: this.dossier.description,
watermarkEnabled: this.dossier.watermarkEnabled,
watermarkPreviewEnabled: this.dossier.watermarkPreviewEnabled,
@@ -96,6 +117,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
watermarkPreviewEnabled: this.form.get('watermarkPreviewEnabled').value,
dueDate: this.hasDueDate ? this.form.get('dueDate').value : undefined,
dossierTemplateId: this.form.get(DOSSIER_TEMPLATE_ID).value,
+ dossierStatusId: this.form.get('dossierStatusId').value,
} as IDossierRequest;
try {
await firstValueFrom(this._dossiersService.createOrUpdate(dossier));
@@ -122,11 +144,11 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
this._dialogService.openDialog('confirm', null, data, async () => {
await firstValueFrom(this._dossiersService.delete(this.dossier));
this._editDossierDialogRef.close();
- this._router.navigate(['main', 'dossiers']).then(() => this._notifyDossierDeleted());
+ this._router.navigate(['main', 'dossiers']).then(() => this.#notifyDossierDeleted());
});
}
- private _getForm(): FormGroup {
+ #getForm(): FormGroup {
return this._formBuilder.group({
dossierName: [this.dossier.dossierName, Validators.required],
dossierTemplateId: [
@@ -136,6 +158,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
},
Validators.required,
],
+ dossierStatusId: [this.dossier.dossierStatusId],
description: [this.dossier.description],
dueDate: [this.dossier.dueDate],
watermarkEnabled: [this.dossier.watermarkEnabled],
@@ -143,11 +166,11 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
});
}
- private _notifyDossierDeleted() {
+ #notifyDossierDeleted() {
this._toaster.success(_('edit-dossier-dialog.delete-successful'), { params: { dossierName: this.dossier.dossierName } });
}
- private _filterInvalidDossierTemplates() {
+ #filterInvalidDossierTemplates() {
this.dossierTemplates = this._dossierTemplatesService.all.filter(r => {
if (this.dossier?.dossierTemplateId === r.dossierTemplateId) {
return true;
diff --git a/apps/red-ui/src/app/modules/dossier/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/dossier/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts
index 9dbbe5eb8..5fc82072b 100644
--- a/apps/red-ui/src/app/modules/dossier/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/dialogs/force-redaction-dialog/force-annotation-dialog.component.ts
@@ -10,6 +10,7 @@ import { DossiersService } from '@services/entity-services/dossiers.service';
import { JustificationsService } from '@services/entity-services/justifications.service';
import { Dossier, ILegalBasisChangeRequest } from '@red/domain';
import { firstValueFrom } from 'rxjs';
+import { AnnotationWrapper } from '@models/file/annotation.wrapper';
export interface LegalBasisOption {
label?: string;
@@ -37,11 +38,11 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen
private readonly _permissionsService: PermissionsService,
protected readonly _injector: Injector,
protected readonly _dialogRef: MatDialogRef,
- @Inject(MAT_DIALOG_DATA) private readonly _data: { readonly dossier: Dossier; readonly hint: boolean },
+ @Inject(MAT_DIALOG_DATA)
+ private readonly _data: { readonly dossier: Dossier; readonly hint: boolean; annotations: AnnotationWrapper[] },
) {
super(_injector, _dialogRef);
this.form = this._getForm();
- this.initialFormValue = this.form.getRawValue();
}
get isHintDialog() {
@@ -59,6 +60,14 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen
}));
this.legalOptions.sort((a, b) => a.label.localeCompare(b.label));
+
+ // Set pre-existing reason if it exists
+ const existingReason = this.legalOptions.find(option => option.legalBasis === this._data.annotations[0].legalBasis);
+ if (!this._data.hint && existingReason) {
+ this.form.patchValue({ reason: existingReason }, { emitEvent: false });
+ }
+
+ this.initialFormValue = this.form.getRawValue();
}
save() {
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.ts
index 90d3354dd..72d1e1ae3 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/bulk-actions/dossier-overview-bulk-actions.component.ts
@@ -19,24 +19,26 @@ export class DossierOverviewBulkActionsComponent implements OnChanges {
@Input() @Required() selectedFiles: File[];
@Input() buttonType: CircleButtonType = CircleButtonTypes.dark;
@Input() maxWidth: number;
-
- analysisForced: boolean;
- canAssignToSelf: boolean;
- canAssign: boolean;
- canDelete: boolean;
- canReanalyse: boolean;
- canDisableAutoAnalysis: boolean;
- canEnableAutoAnalysis: boolean;
- canOcr: boolean;
- canSetToUnderReview: boolean;
- canSetToUnderApproval: boolean;
- isReadyForApproval: boolean;
- canApprove: boolean;
- canUndoApproval: boolean;
- assignTooltip: string;
buttons: Action[];
- private _canMoveToSameState: boolean;
+ #analysisForced: boolean;
+ #canAssignToSelf: boolean;
+ #canAssign: boolean;
+ #canDelete: boolean;
+ #canReanalyse: boolean;
+ #canDisableAutoAnalysis: boolean;
+ #canEnableAutoAnalysis: boolean;
+ #canOcr: boolean;
+ #canSetToUnderReview: boolean;
+ #canSetToUnderApproval: boolean;
+ #isReadyForApproval: boolean;
+ #canApprove: boolean;
+ #canUndoApproval: boolean;
+ #canToggleAnalysis: boolean;
+ #assignTooltip: string;
+ #toggleAnalysisTooltip: string;
+ #allFilesAreExcluded: boolean;
+ #canMoveToSameState: boolean;
constructor(
private readonly _permissionsService: PermissionsService,
@@ -52,35 +54,35 @@ export class DossierOverviewBulkActionsComponent implements OnChanges {
action: () => this._bulkActionsService.delete(this.selectedFiles),
tooltip: _('dossier-overview.bulk.delete'),
icon: 'iqser:trash',
- show: this.canDelete,
+ show: this.#canDelete,
},
{
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.assign(this.selectedFiles),
- tooltip: this.assignTooltip,
+ tooltip: this.#assignTooltip,
icon: 'red:assign',
- show: this.canAssign,
+ show: this.#canAssign,
},
{
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.assignToMe(this.selectedFiles),
tooltip: _('dossier-overview.assign-me'),
icon: 'red:assign-me',
- show: this.canAssignToSelf,
+ show: this.#canAssignToSelf,
},
{
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.setToUnderApproval(this.selectedFiles),
tooltip: _('dossier-overview.under-approval'),
icon: 'red:ready-for-approval',
- show: this.canSetToUnderApproval,
+ show: this.#canSetToUnderApproval,
},
{
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.backToUnderReview(this.selectedFiles),
tooltip: _('dossier-overview.under-review'),
icon: 'red:undo',
- show: this.canSetToUnderReview,
+ show: this.#canSetToUnderReview,
},
{
type: ActionTypes.downloadBtn,
@@ -90,45 +92,53 @@ export class DossierOverviewBulkActionsComponent implements OnChanges {
{
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.approve(this.selectedFiles),
- disabled: !this.canApprove,
- tooltip: this.canApprove ? _('dossier-overview.approve') : _('dossier-overview.approve-disabled'),
+ disabled: !this.#canApprove,
+ tooltip: this.#canApprove ? _('dossier-overview.approve') : _('dossier-overview.approve-disabled'),
icon: 'red:approved',
- show: this.isReadyForApproval,
+ show: this.#isReadyForApproval,
},
{
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.setToUnderApproval(this.selectedFiles),
tooltip: _('dossier-overview.under-approval'),
icon: 'red:undo',
- show: this.canUndoApproval,
+ show: this.#canUndoApproval,
},
{
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.ocr(this.selectedFiles),
tooltip: _('dossier-overview.ocr-file'),
icon: 'iqser:ocr',
- show: this.canOcr,
+ show: this.#canOcr,
},
{
type: ActionTypes.circleBtn,
action: () => this._bulkActionsService.reanalyse(this.selectedFiles),
tooltip: _('dossier-overview.bulk.reanalyse'),
icon: 'iqser:refresh',
- show: this.canReanalyse && (this.analysisForced || this.canEnableAutoAnalysis),
+ show: this.#canReanalyse && (this.#analysisForced || this.#canEnableAutoAnalysis),
},
{
type: ActionTypes.circleBtn,
- action: $event => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles),
+ action: () => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles),
tooltip: _('dossier-overview.disable-auto-analysis'),
icon: 'red:stop',
- show: this.canDisableAutoAnalysis,
+ show: this.#canDisableAutoAnalysis,
},
{
type: ActionTypes.circleBtn,
- action: $event => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles),
+ action: () => this._bulkActionsService.toggleAutomaticAnalysis(this.selectedFiles),
tooltip: _('dossier-overview.enable-auto-analysis'),
icon: 'red:play',
- show: this.canEnableAutoAnalysis,
+ show: this.#canEnableAutoAnalysis,
+ },
+
+ {
+ type: ActionTypes.toggle,
+ action: () => this._bulkActionsService.toggleAnalysis(this.selectedFiles, !this.#allFilesAreExcluded),
+ tooltip: this.#toggleAnalysisTooltip,
+ checked: !this.#allFilesAreExcluded,
+ show: this.#canToggleAnalysis,
},
].filter(btn => btn.show);
}
@@ -138,7 +148,7 @@ export class DossierOverviewBulkActionsComponent implements OnChanges {
}
forceReanalysisAction($event: LongPressEvent) {
- this.analysisForced = !$event.touchEnd && this._userPreferenceService.areDevFeaturesEnabled;
+ this.#analysisForced = !$event.touchEnd && this._userPreferenceService.areDevFeaturesEnabled;
this._setup();
}
@@ -151,37 +161,44 @@ export class DossierOverviewBulkActionsComponent implements OnChanges {
true,
);
const allFilesAreUnderApproval = this.selectedFiles.reduce((acc, file) => acc && file.isUnderApproval, true);
- this._canMoveToSameState = allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval;
+ this.#allFilesAreExcluded = this.selectedFiles.reduce((acc, file) => acc && file.excluded, true);
+ this.#canMoveToSameState = allFilesAreUnderReviewOrUnassigned || allFilesAreUnderApproval;
- this.canAssign =
- this._canMoveToSameState &&
+ this.#canAssign =
+ this.#canMoveToSameState &&
this.selectedFiles.reduce(
(acc, file) => (acc && this._permissionsService.canAssignUser(file)) || this._permissionsService.canUnassignUser(file),
true,
);
- this.canAssignToSelf = this._canMoveToSameState && this._permissionsService.canAssignToSelf(this.selectedFiles);
+ this.#canAssignToSelf = this.#canMoveToSameState && this._permissionsService.canAssignToSelf(this.selectedFiles);
- this.canDelete = this._permissionsService.canDeleteFile(this.selectedFiles);
+ this.#canDelete = this._permissionsService.canDeleteFile(this.selectedFiles);
- this.canReanalyse = this._permissionsService.canReanalyseFile(this.selectedFiles);
+ this.#canReanalyse = this._permissionsService.canReanalyseFile(this.selectedFiles);
- this.canDisableAutoAnalysis = this._permissionsService.canDisableAutoAnalysis(this.selectedFiles);
+ this.#canDisableAutoAnalysis = this._permissionsService.canDisableAutoAnalysis(this.selectedFiles);
- this.canEnableAutoAnalysis = this._permissionsService.canEnableAutoAnalysis(this.selectedFiles);
+ this.#canEnableAutoAnalysis = this._permissionsService.canEnableAutoAnalysis(this.selectedFiles);
- this.canOcr = this.selectedFiles.reduce((acc, file) => acc && file.canBeOCRed, true);
+ this.#canToggleAnalysis = this._permissionsService.canToggleAnalysis(this.selectedFiles);
- this.canSetToUnderReview = this._permissionsService.canSetUnderReview(this.selectedFiles) && !isWorkflow;
+ this.#canOcr = this.selectedFiles.reduce((acc, file) => acc && file.canBeOCRed, true);
- this.canSetToUnderApproval = this._permissionsService.canSetUnderApproval(this.selectedFiles) && !isWorkflow;
+ this.#canSetToUnderReview = this._permissionsService.canSetUnderReview(this.selectedFiles) && !isWorkflow;
- this.isReadyForApproval = this._permissionsService.isReadyForApproval(this.selectedFiles) && !isWorkflow;
+ this.#canSetToUnderApproval = this._permissionsService.canSetUnderApproval(this.selectedFiles) && !isWorkflow;
- this.canApprove = this._permissionsService.canBeApproved(this.selectedFiles) && !isWorkflow;
+ this.#isReadyForApproval = this._permissionsService.isReadyForApproval(this.selectedFiles) && !isWorkflow;
- this.canUndoApproval = this._permissionsService.canUndoApproval(this.selectedFiles) && !isWorkflow;
+ this.#canApprove = this._permissionsService.canBeApproved(this.selectedFiles) && !isWorkflow;
- this.assignTooltip = allFilesAreUnderApproval ? _('dossier-overview.assign-approver') : _('dossier-overview.assign-reviewer');
+ this.#canUndoApproval = this._permissionsService.canUndoApproval(this.selectedFiles) && !isWorkflow;
+
+ 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;
}
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html
index 62fdd4772..183ebc0d0 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html
+++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html
@@ -5,7 +5,7 @@
-
+
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-indicator/page-indicator.component.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-indicator/page-indicator.component.ts
index dc226a6cc..2e06a8c49 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-indicator/page-indicator.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/components/page-indicator/page-indicator.component.ts
@@ -1,11 +1,9 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnChanges, OnDestroy, Output } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { ConfigService } from '@services/config.service';
-import { DossiersService } from '@services/entity-services/dossiers.service';
import { ViewedPagesService } from '@services/entity-services/viewed-pages.service';
import { IViewedPage } from '@red/domain';
import { AutoUnsubscribe } from '@iqser/common-ui';
-import { FilesMapService } from '@services/entity-services/files-map.service';
import { FilePreviewStateService } from '../../services/file-preview-state.service';
import { firstValueFrom } from 'rxjs';
@@ -20,6 +18,7 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
@Input() showDottedIcon = false;
@Input() number: number;
@Input() activeSelection = false;
+ @Input() viewedPages: IViewedPage[] = [];
@Output() readonly pageSelected = new EventEmitter
();
@@ -28,8 +27,6 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
constructor(
private readonly _viewedPagesService: ViewedPagesService,
- private readonly _filesMapService: FilesMapService,
- private readonly _dossiersService: DossiersService,
private readonly _configService: ConfigService,
private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _permissionService: PermissionsService,
@@ -39,7 +36,7 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
}
get activePage() {
- return this._viewedPages.find(p => p.page === this.number);
+ return this.viewedPages.find(p => p.page === this.number);
}
get dossierId() {
@@ -50,10 +47,6 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
return this._stateService.fileId;
}
- private get _viewedPages(): IViewedPage[] {
- return this._stateService.fileData?.viewedPages || [];
- }
-
ngOnChanges() {
this._setReadState();
return this.handlePageRead();
@@ -104,7 +97,7 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
if (this.activePage) {
this.activePage.showAsUnseen = false;
} else {
- this._viewedPages.push({ page: this.number, fileId: this.fileId });
+ this.viewedPages.push({ page: this.number, fileId: this.fileId });
}
this._setReadState();
}
@@ -113,8 +106,8 @@ export class PageIndicatorComponent extends AutoUnsubscribe implements OnDestroy
const removePage$ = this._viewedPagesService.removePage(this.dossierId, this.fileId, this.number);
await firstValueFrom(removePage$);
- this._viewedPages.splice(
- this._viewedPages.findIndex(p => p.page === this.number),
+ this.viewedPages.splice(
+ this.viewedPages.findIndex(p => p.page === this.number),
1,
);
this._setReadState();
diff --git a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/annotation-actions.service.ts b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/annotation-actions.service.ts
index 05e5a6e32..9f0682b63 100644
--- a/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/annotation-actions.service.ts
+++ b/apps/red-ui/src/app/modules/dossier/screens/file-preview-screen/services/annotation-actions.service.ts
@@ -77,7 +77,7 @@ export class AnnotationActionsService {
hint: boolean = false,
) {
const { dossierId, fileId } = this._screenStateService;
- const data = { dossier: this._dossier, hint };
+ const data = { dossier: this._dossier, annotations, hint };
this._dialogService.openDialog('forceAnnotation', $event, data, (request: ILegalBasisChangeRequest) => {
annotations.forEach(annotation => {
this._processObsAndEmit(
diff --git a/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts b/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts
index e084f178c..8b4d73884 100644
--- a/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts
+++ b/apps/red-ui/src/app/modules/dossier/shared/components/file-actions/file-actions.component.ts
@@ -345,7 +345,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnDestroy,
private async _toggleAnalysis() {
this._loadingService.start();
- await firstValueFrom(this._reanalysisService.toggleAnalysis(this.file.dossierId, this.file.fileId, !this.file.excluded));
+ await firstValueFrom(this._reanalysisService.toggleAnalysis(this.file.dossierId, [this.file.fileId], !this.file.excluded));
this._loadingService.stop();
}
diff --git a/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.ts b/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.ts
index bd5230711..d91417945 100644
--- a/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.ts
+++ b/apps/red-ui/src/app/modules/shared/components/simple-doughnut-chart/simple-doughnut-chart.component.ts
@@ -23,7 +23,7 @@ export class SimpleDoughnutChartComponent implements OnChanges, OnInit {
@Input() radius = 85;
@Input() strokeWidth = 20;
@Input() direction: 'row' | 'column' = 'column';
- @Input() totalType: 'sum' | 'count' = 'sum';
+ @Input() totalType: 'sum' | 'count' | 'simpleLabel' = 'sum';
@Input() counterText: string;
@Input() filterKey = 'statusFilters';
@Input() helpModeKey: 'filter_for_status';
@@ -97,7 +97,11 @@ export class SimpleDoughnutChartComponent implements OnChanges, OnInit {
}
getLabel({ label, value }: DoughnutChartConfig): string {
- return this.totalType === 'sum' ? `${value} ${label}` : `${label} (${value} ${this.counterText})`;
+ return this.totalType === 'simpleLabel'
+ ? `${label}`
+ : this.totalType === 'sum'
+ ? `${value} ${label}`
+ : `${label} (${value} ${this.counterText})`;
}
selectValue(key: string): void {
diff --git a/apps/red-ui/src/app/services/entity-services/dossier-state.service.ts b/apps/red-ui/src/app/services/entity-services/dossier-state.service.ts
new file mode 100644
index 000000000..a3c2edc54
--- /dev/null
+++ b/apps/red-ui/src/app/services/entity-services/dossier-state.service.ts
@@ -0,0 +1,41 @@
+import { Injectable, Injector } from '@angular/core';
+import { EntitiesService, mapEach, RequiredParam, Validate } from '@iqser/common-ui';
+import { DossierState, IDossierState } from '@red/domain';
+import { forkJoin, Observable, switchMap } from 'rxjs';
+import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
+import { map, tap } from 'rxjs/operators';
+
+@Injectable({
+ providedIn: 'root',
+})
+export class DossierStateService extends EntitiesService {
+ constructor(protected readonly _injector: Injector, private readonly _dossierTemplatesService: DossierTemplatesService) {
+ super(_injector, DossierState, 'dossier-status');
+ }
+
+ @Validate()
+ setDossierState(@RequiredParam() body: IDossierState) {
+ return this._post(body, this._defaultModelPath);
+ }
+
+ @Validate()
+ loadAllForTemplate(@RequiredParam() templateId: string) {
+ return this.loadAll(`${this._defaultModelPath}/dossier-template/${templateId}`);
+ }
+
+ loadAllForAllTemplates(): Observable {
+ return this._dossierTemplatesService.all$.pipe(
+ mapEach(template => template.dossierTemplateId),
+ mapEach(id => this.loadAllForTemplate(id)),
+ switchMap(all => forkJoin(all)),
+ map(value => value.flatMap(item => item)),
+ tap(value => this.setEntities(value)),
+ );
+ }
+
+ @Validate()
+ deleteAndReplace(@RequiredParam() dossierStatusId: string, @RequiredParam() replaceDossierStatusId: string) {
+ const url = `${this._defaultModelPath}/${dossierStatusId}?replaceDossierStatusId=${replaceDossierStatusId}`;
+ return this.delete({}, url);
+ }
+}
diff --git a/apps/red-ui/src/app/services/entity-services/dossiers.service.ts b/apps/red-ui/src/app/services/entity-services/dossiers.service.ts
index 0babadb88..4787fdb30 100644
--- a/apps/red-ui/src/app/services/entity-services/dossiers.service.ts
+++ b/apps/red-ui/src/app/services/entity-services/dossiers.service.ts
@@ -7,6 +7,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
+import { DossierStateService } from '@services/entity-services/dossier-state.service';
export interface IDossiersStats {
totalPeople: number;
@@ -37,6 +38,7 @@ export class DossiersService extends EntitiesService {
private readonly _toaster: Toaster,
protected readonly _injector: Injector,
private readonly _dossierStatsService: DossierStatsService,
+ private readonly _dossierStateService: DossierStateService,
) {
super(_injector, Dossier, 'dossier');
@@ -54,6 +56,7 @@ export class DossiersService extends EntitiesService {
mapEach(entity => new Dossier(entity)),
/* Load stats before updating entities */
switchMap(dossiers => this._dossierStatsService.getFor(dossierIds(dossiers)).pipe(mapTo(dossiers))),
+ switchMap(dossiers => this._dossierStateService.loadAllForAllTemplates().pipe(mapTo(dossiers))),
tap(dossiers => this.setEntities(dossiers)),
);
}
@@ -108,6 +111,10 @@ export class DossiersService extends EntitiesService {
return firstValueFrom(super.delete(body, 'deleted-dossiers/hard-delete', body));
}
+ getCountWithState(dossierStatusId: string): number {
+ return this.all.filter(dossier => dossier.dossierStatusId === dossierStatusId).length;
+ }
+
private _emitFileChanges(changes: ChangesDetails): void {
changes.dossierChanges.filter(change => change.fileChanges).forEach(change => this.dossierFileChanges$.next(change.dossierId));
}
diff --git a/apps/red-ui/src/app/services/permissions.service.ts b/apps/red-ui/src/app/services/permissions.service.ts
index c1242d5c4..21404c135 100644
--- a/apps/red-ui/src/app/services/permissions.service.ts
+++ b/apps/red-ui/src/app/services/permissions.service.ts
@@ -23,8 +23,10 @@ export class PermissionsService {
return ((file.isUnderReview || file.isNew) && this.isDossierMember(dossier)) || (file.isUnderApproval && this.isApprover(dossier));
}
- canToggleAnalysis(file: File): boolean {
- return this.isFileAssignee(file) && (file.isNew || file.isUnderReview || file.isUnderApproval);
+ canToggleAnalysis(file: File | File[]): boolean {
+ const files = file instanceof File ? [file] : file;
+ const sameState = new Set(files.map(f => f.excluded)).size === 1;
+ return sameState && files.reduce((acc, _file) => this._canToggleAnalysis(_file) && acc, true);
}
canReanalyseFile(file: File | File[]): boolean {
@@ -152,6 +154,10 @@ export class PermissionsService {
return (comment.user === this._userService.currentUser.id || this.isApprover(dossier)) && !file.isApproved;
}
+ private _canToggleAnalysis(file: File): boolean {
+ return this.isFileAssignee(file) && (file.isNew || file.isUnderReview || file.isUnderApproval);
+ }
+
// https://jira.iqser.com/browse/RED-2787
private _canDeleteFile(file: File, dossier: Dossier): boolean {
return (
diff --git a/apps/red-ui/src/app/services/reanalysis.service.ts b/apps/red-ui/src/app/services/reanalysis.service.ts
index a636a7b60..03d002626 100644
--- a/apps/red-ui/src/app/services/reanalysis.service.ts
+++ b/apps/red-ui/src/app/services/reanalysis.service.ts
@@ -49,13 +49,13 @@ export class ReanalysisService extends GenericService {
}
@Validate()
- toggleAnalysis(@RequiredParam() dossierId: string, @RequiredParam() fileId: string, excluded?: boolean) {
+ toggleAnalysis(@RequiredParam() dossierId: string, @RequiredParam() fileIds: string[], excluded?: boolean) {
const queryParams: QueryParam[] = [];
if (excluded) {
queryParams.push({ key: 'excluded', value: excluded });
}
- return this._post({}, `toggle-analysis/${dossierId}/${fileId}`, queryParams).pipe(
+ return this._post(fileIds, `toggle-analysis/${dossierId}/bulk`, queryParams).pipe(
switchMap(() => this._filesService.loadAll(dossierId)),
);
}
diff --git a/apps/red-ui/src/assets/i18n/de.json b/apps/red-ui/src/assets/i18n/de.json
index 21819e941..b228549e1 100644
--- a/apps/red-ui/src/assets/i18n/de.json
+++ b/apps/red-ui/src/assets/i18n/de.json
@@ -605,6 +605,7 @@
"title": "Datei-Attribute anlegen"
},
"dossier": "Dossier",
+ "dossier-states": "",
"dossier-attribute-types": {
"date": "Datum",
"image": "Bild",
diff --git a/apps/red-ui/src/assets/i18n/en.json b/apps/red-ui/src/assets/i18n/en.json
index 9a64201c7..df128effe 100644
--- a/apps/red-ui/src/assets/i18n/en.json
+++ b/apps/red-ui/src/assets/i18n/en.json
@@ -8,7 +8,6 @@
"all": "All",
"none": "None"
},
- "active": "Active",
"add-dossier-dialog": {
"actions": {
"save": "Save",
@@ -72,6 +71,16 @@
"save": "Save Attribute",
"title": "{type, select, edit{Edit {name}} create{Add New} other{}} Dossier Attribute"
},
+ "add-edit-dossier-state": {
+ "form": {
+ "color": "Hex Color",
+ "color-placeholder": "#",
+ "name": "Status Name",
+ "name-placeholder": "Enter Name"
+ },
+ "save": "Save Status",
+ "title": "{type, select, edit{Edit {name}} create{Create} other{}} Dossier Status"
+ },
"add-edit-dossier-template": {
"error": {
"conflict": "Failed to create dossier template: a dossier template with the same name already exists.",
@@ -296,8 +305,8 @@
"suggestion-add": "Suggested redaction",
"suggestion-add-dictionary": "Suggested dictionary add",
"suggestion-change-legal-basis": "Suggested change legal basis",
- "suggestion-force-hint": "",
- "suggestion-force-redaction": "Suggestion force hint",
+ "suggestion-force-hint": "Suggestion force hint",
+ "suggestion-force-redaction": "Suggestion force redaction",
"suggestion-recategorize-image": "Suggested recategorize image",
"suggestion-remove": "Suggested local removal",
"suggestion-remove-dictionary": "Suggested dictionary removal",
@@ -399,6 +408,18 @@
}
},
"configurations": "Configurations",
+ "confirm-delete-dossier-state": {
+ "cancel": "Cancel",
+ "delete-replace": "Delete and Replace",
+ "delete": "Delete only",
+ "form": {
+ "status": "Replace Status",
+ "status-placeholder": "Choose another status"
+ },
+ "suggestion": "Would you like to replace the states of the Dossiers with another status?",
+ "title": "Delete Dossier Status",
+ "warning": "The {name} status is assigned to {count} {count, plural, one{Dossier} other{Dossiers}}."
+ },
"confirm-delete-file-attribute": {
"cancel": "Keep {type, select, single{Attribute} bulk{Attributes} other{}}",
"delete": "Delete {type, select, single{Attribute} bulk{Attributes} other{}}",
@@ -696,10 +717,11 @@
"total-people": "Total users"
},
"table-col-names": {
+ "documents-status": "Documents Status",
+ "dossier-status": "Dossier Status",
"name": "Name",
"needs-work": "Workload",
- "owner": "Owner",
- "status": "Status"
+ "owner": "Owner"
},
"table-header": {
"title": "{length} active {length, plural, one{Dossier} other{Dossiers}}"
@@ -803,6 +825,35 @@
"under-review": "Under Review",
"upload-files": "Drag & drop files anywhere..."
},
+ "dossier-states": "Dossier States",
+ "dossier-states-listing": {
+ "action": {
+ "delete": "Delete Status",
+ "edit": "Edit Status"
+ },
+ "add-new": "New Status",
+ "chart": {
+ "dossier-states": "{count, plural, one{Dossier State} other{Dossier States}}"
+ },
+ "error": {
+ "conflict": "Dossier State with this name already exists!",
+ "generic": "Failed to add Dossier State"
+ },
+ "no-data": {
+ "title": "There are no dossier states."
+ },
+ "no-match": {
+ "title": "No dossier states match your current filters."
+ },
+ "search": "Search...",
+ "table-col-names": {
+ "dossiers-count": "Dossiers Count",
+ "name": "Name"
+ },
+ "table-header": {
+ "title": "{length} dossier {length, plural, one{state} other{states}}"
+ }
+ },
"dossier-template-info": "Info",
"dossier-template-info-screen": {
"created-by": "Created by",
@@ -957,6 +1008,11 @@
"label": "Description",
"placeholder": "Enter Description"
},
+ "dossier-status": {
+ "label": "Dossier Status",
+ "no-status-placeholder": "This dossier template has no states",
+ "placeholder": "Undefined"
+ },
"due-date": "Due Date",
"name": {
"label": "Dossier Name",
@@ -1633,8 +1689,8 @@
"no-time-left": "Time to restore already passed"
},
"toggle-auto-analysis-message": {
- "success": "{toggleOperation} automatic processing.",
- "error": "Something went wrong."
+ "error": "Something went wrong.",
+ "success": "{toggleOperation} automatic processing."
},
"top-bar": {
"navigation-items": {
diff --git a/bamboo-specs/src/main/java/buildjob/PlanSpec.java b/bamboo-specs/src/main/java/buildjob/PlanSpec.java
index 2ca8f1b37..f9fdee0a0 100644
--- a/bamboo-specs/src/main/java/buildjob/PlanSpec.java
+++ b/bamboo-specs/src/main/java/buildjob/PlanSpec.java
@@ -48,6 +48,7 @@ public class PlanSpec {
.userPermissions("atlbamboo", PermissionType.EDIT, PermissionType.VIEW, PermissionType.ADMIN, PermissionType.CLONE, PermissionType.BUILD)
.userPermissions("tbejan", PermissionType.ADMIN, PermissionType.EDIT, PermissionType.VIEW, PermissionType.CLONE, PermissionType.BUILD)
.groupPermissions("devplant", PermissionType.EDIT, PermissionType.VIEW, PermissionType.BUILD)
+ .groupPermissions("Documentation", PermissionType.VIEW)
.loggedInUserPermissions(PermissionType.VIEW).anonymousUserPermissionView();
return new PlanPermissions(planIdentifier.getProjectKey(), planIdentifier.getPlanKey()).permissions(permission);
}
diff --git a/libs/red-domain/src/index.ts b/libs/red-domain/src/index.ts
index aee8ff159..e2d4bf0e4 100644
--- a/libs/red-domain/src/index.ts
+++ b/libs/red-domain/src/index.ts
@@ -19,3 +19,4 @@ export * from './lib/configuration';
export * from './lib/signature';
export * from './lib/legal-basis';
export * from './lib/dossier-stats';
+export * from './lib/dossier-state';
diff --git a/libs/red-domain/src/lib/dossier-state/dossier-state.model.ts b/libs/red-domain/src/lib/dossier-state/dossier-state.model.ts
new file mode 100644
index 000000000..242a34ace
--- /dev/null
+++ b/libs/red-domain/src/lib/dossier-state/dossier-state.model.ts
@@ -0,0 +1,28 @@
+import { IListable } from '@iqser/common-ui';
+import { IDossierState } from './dossier-state';
+
+export class DossierState implements IDossierState, IListable {
+ readonly description: string;
+ readonly dossierStatusId: string;
+ readonly dossierTemplateId: string;
+ readonly name: string;
+ readonly color: string;
+ dossierCount?: number;
+
+ constructor(dossierState: IDossierState) {
+ this.description = dossierState.description;
+ this.dossierStatusId = dossierState.dossierStatusId;
+ this.dossierTemplateId = dossierState.dossierTemplateId;
+ this.name = dossierState.name;
+ this.color = dossierState.color;
+ this.dossierCount = dossierState.dossierCount;
+ }
+
+ get id(): string {
+ return this.dossierStatusId;
+ }
+
+ get searchKey(): string {
+ return this.name;
+ }
+}
diff --git a/libs/red-domain/src/lib/dossier-state/dossier-state.ts b/libs/red-domain/src/lib/dossier-state/dossier-state.ts
new file mode 100644
index 000000000..f7491e23b
--- /dev/null
+++ b/libs/red-domain/src/lib/dossier-state/dossier-state.ts
@@ -0,0 +1,8 @@
+export interface IDossierState {
+ description: string;
+ dossierStatusId: string;
+ dossierTemplateId: string;
+ name: string;
+ color: string;
+ dossierCount?: number;
+}
diff --git a/libs/red-domain/src/lib/dossier-state/index.ts b/libs/red-domain/src/lib/dossier-state/index.ts
new file mode 100644
index 000000000..166b90570
--- /dev/null
+++ b/libs/red-domain/src/lib/dossier-state/index.ts
@@ -0,0 +1,2 @@
+export * from './dossier-state';
+export * from './dossier-state.model';
diff --git a/libs/red-domain/src/lib/dossiers/dossier.model.ts b/libs/red-domain/src/lib/dossiers/dossier.model.ts
index 8c8ab6e5b..e2a79d550 100644
--- a/libs/red-domain/src/lib/dossiers/dossier.model.ts
+++ b/libs/red-domain/src/lib/dossiers/dossier.model.ts
@@ -11,6 +11,7 @@ export class Dossier implements IDossier, IListable {
readonly approverIds: List;
readonly reportTemplateIds: List;
readonly dossierName: string;
+ readonly dossierStatusId: string;
readonly date: string;
readonly dueDate?: string;
readonly description?: string;
@@ -29,6 +30,7 @@ export class Dossier implements IDossier, IListable {
this.date = dossier.date;
this.description = dossier.description;
this.dossierName = dossier.dossierName;
+ this.dossierStatusId = dossier.dossierStatusId;
this.dossierTemplateId = dossier.dossierTemplateId;
this.downloadFileTypes = dossier.downloadFileTypes;
this.dueDate = dossier.dueDate;
diff --git a/libs/red-domain/src/lib/dossiers/dossier.ts b/libs/red-domain/src/lib/dossiers/dossier.ts
index 9b4883801..1ff219033 100644
--- a/libs/red-domain/src/lib/dossiers/dossier.ts
+++ b/libs/red-domain/src/lib/dossiers/dossier.ts
@@ -7,6 +7,7 @@ export interface IDossier {
readonly date: string;
readonly description?: string;
readonly dossierId: string;
+ readonly dossierStatusId: string;
readonly dossierName: string;
readonly dossierTemplateId: string;
readonly downloadFileTypes?: List;
diff --git a/package.json b/package.json
index 7ecfcc778..c2f6e6561 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "redaction",
- "version": "3.229.0",
+ "version": "3.236.0",
"private": true,
"license": "MIT",
"scripts": {
diff --git a/paligo-theme.tar.gz b/paligo-theme.tar.gz
index bce044f60..8b823f63c 100644
Binary files a/paligo-theme.tar.gz and b/paligo-theme.tar.gz differ