Merge branch 'master' into VM/RED-3370
This commit is contained in:
commit
04edeb0da4
@ -13,6 +13,7 @@
|
||||
[routerLink]="breadcrumb.routerLink"
|
||||
class="breadcrumb"
|
||||
routerLinkActive="active"
|
||||
[id]="first ? 'navigateToActiveDossiers' : ''"
|
||||
>
|
||||
{{ breadcrumb.name$ | async }}
|
||||
</a>
|
||||
|
||||
@ -21,6 +21,7 @@ import { DossierTemplatesGuard } from '../../guards/dossier-templates.guard';
|
||||
import { DICTIONARY_TYPE, DOSSIER_TEMPLATE_ID } from '@utils/constants';
|
||||
import { DossierTemplateExistsGuard } from '../../guards/dossier-template-exists.guard';
|
||||
import { DictionaryExistsGuard } from '../../guards/dictionary-exists.guard';
|
||||
import { DossierStatesListingScreenComponent } from './screens/dossier-states-listing/dossier-states-listing-screen.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: 'dossier-templates', pathMatch: 'full' },
|
||||
@ -114,6 +115,14 @@ const routes: Routes = [
|
||||
routeGuards: [AuthGuard, RedRoleGuard],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'dossier-states',
|
||||
component: DossierStatesListingScreenComponent,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'default-colors',
|
||||
component: DefaultColorsScreenComponent,
|
||||
|
||||
@ -62,6 +62,7 @@ export class AdminSideNavComponent implements OnInit {
|
||||
{ screen: 'watermark', label: _('watermark') },
|
||||
{ screen: 'file-attributes', label: _('file-attributes') },
|
||||
{ screen: 'dossier-attributes', label: _('dossier-attributes') },
|
||||
{ screen: 'dossier-states', label: _('dossier-states') },
|
||||
{ screen: 'reports', label: _('reports') },
|
||||
{ screen: 'justifications', label: _('justifications') },
|
||||
],
|
||||
|
||||
@ -46,6 +46,10 @@ import { SmtpFormComponent } from './screens/general-config/smtp-form/smtp-form.
|
||||
import { FileAttributesConfigurationsDialogComponent } from './dialogs/file-attributes-configurations-dialog/file-attributes-configurations-dialog.component';
|
||||
import { SharedAdminModule } from './shared/shared-admin.module';
|
||||
import { BaseDossierTemplateScreenComponent } from './base-dossier-templates-screen/base-dossier-template-screen.component';
|
||||
import { DossierStatesListingScreenComponent } from './screens/dossier-states-listing/dossier-states-listing-screen.component';
|
||||
import { AddEditDossierStateDialogComponent } from './dialogs/add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component';
|
||||
import { A11yModule } from '@angular/cdk/a11y';
|
||||
import { ConfirmDeleteDossierStateDialogComponent } from './dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component';
|
||||
|
||||
const dialogs = [
|
||||
AddEditDossierTemplateDialogComponent,
|
||||
@ -95,8 +99,22 @@ const components = [
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
declarations: [...components],
|
||||
declarations: [
|
||||
...components,
|
||||
DossierStatesListingScreenComponent,
|
||||
AddEditDossierStateDialogComponent,
|
||||
ConfirmDeleteDossierStateDialogComponent,
|
||||
],
|
||||
providers: [AdminDialogService, AuditService, DigitalSignatureService, LicenseReportService, RulesService, SmtpConfigService],
|
||||
imports: [CommonModule, SharedModule, AdminRoutingModule, SharedAdminModule, NgxChartsModule, ColorPickerModule, MonacoEditorModule],
|
||||
imports: [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
AdminRoutingModule,
|
||||
SharedAdminModule,
|
||||
NgxChartsModule,
|
||||
ColorPickerModule,
|
||||
MonacoEditorModule,
|
||||
A11yModule,
|
||||
],
|
||||
})
|
||||
export class AdminModule {}
|
||||
|
||||
@ -0,0 +1,55 @@
|
||||
<section class="dialog">
|
||||
<div
|
||||
[translateParams]="{
|
||||
type: data.dossierState ? 'edit' : 'create',
|
||||
name: data.dossierState?.name
|
||||
}"
|
||||
[translate]="'add-edit-dossier-state.title'"
|
||||
class="dialog-header heading-l"
|
||||
></div>
|
||||
|
||||
<form [formGroup]="form">
|
||||
<div class="dialog-content flex">
|
||||
<div class="iqser-input-group required w-300">
|
||||
<label translate="add-edit-dossier-state.form.name"></label>
|
||||
<input
|
||||
[placeholder]="'add-edit-dossier-state.form.name-placeholder' | translate"
|
||||
formControlName="name"
|
||||
name="name"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="iqser-input-group required">
|
||||
<label translate="add-edit-dossier-state.form.color"></label>
|
||||
<input
|
||||
[placeholder]="'add-edit-dossier-state.form.color-placeholder' | translate"
|
||||
class="hex-color-input"
|
||||
formControlName="color"
|
||||
name="color"
|
||||
type="text"
|
||||
/>
|
||||
<div
|
||||
(colorPickerChange)="form.get('color').setValue($event)"
|
||||
[colorPicker]="form.get('color').value"
|
||||
[cpOutputFormat]="'hex'"
|
||||
[style.background]="form.get('color').value"
|
||||
class="input-icon"
|
||||
>
|
||||
<mat-icon
|
||||
*ngIf="!form.get('color').value || form.get('color').value?.length === 0"
|
||||
svgIcon="red:color-picker"
|
||||
></mat-icon>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button (click)="save()" [disabled]="disabled" color="primary" mat-flat-button type="button">
|
||||
{{ 'add-edit-dossier-state.save' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<iqser-circle-button (action)="close()" class="dialog-close" icon="iqser:close"></iqser-circle-button>
|
||||
</section>
|
||||
@ -0,0 +1,5 @@
|
||||
.iqser-input-group:nth-child(2) {
|
||||
width: fit-content;
|
||||
margin-top: 0;
|
||||
margin-left: 16px;
|
||||
}
|
||||
@ -0,0 +1,45 @@
|
||||
import { ChangeDetectionStrategy, Component, Inject, Injector } from '@angular/core';
|
||||
import { BaseDialogComponent } from '../../../../../../../../libs/common-ui/src';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { IDossierState } from '@red/domain';
|
||||
|
||||
interface DialogData {
|
||||
readonly dossierState: IDossierState;
|
||||
readonly dossierTemplateId: string;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-add-edit-dossier-state-dialog',
|
||||
templateUrl: './add-edit-dossier-state-dialog.component.html',
|
||||
styleUrls: ['./add-edit-dossier-state-dialog.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class AddEditDossierStateDialogComponent extends BaseDialogComponent {
|
||||
constructor(
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
protected readonly _injector: Injector,
|
||||
protected readonly _dialogRef: MatDialogRef<AddEditDossierStateDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: DialogData,
|
||||
) {
|
||||
super(_injector, _dialogRef);
|
||||
this.form = this.#getForm();
|
||||
this.initialFormValue = this.form.getRawValue();
|
||||
}
|
||||
|
||||
save(): void {
|
||||
const dossierState: IDossierState = {
|
||||
dossierStatusId: this.data.dossierState?.dossierStatusId,
|
||||
dossierTemplateId: this.data.dossierTemplateId,
|
||||
...this.form.getRawValue(),
|
||||
};
|
||||
this._dialogRef.close(dossierState);
|
||||
}
|
||||
|
||||
#getForm(): FormGroup {
|
||||
return this._formBuilder.group({
|
||||
name: [this.data.dossierState?.name, Validators.required],
|
||||
color: [this.data.dossierState?.color, Validators.required],
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,39 @@
|
||||
<section class="dialog">
|
||||
<div class="dialog-header heading-l">
|
||||
{{ 'confirm-delete-dossier-state.title' | translate }}
|
||||
</div>
|
||||
|
||||
<div class="dialog-content">
|
||||
<div class="heading">{{ 'confirm-delete-dossier-state.warning' | translate: translateArgs }}</div>
|
||||
|
||||
<ng-container *ngIf="data.dossierCount !== 0">
|
||||
<div class="replacement-suggestion">{{ 'confirm-delete-dossier-state.suggestion' | translate }}</div>
|
||||
|
||||
<form [formGroup]="form">
|
||||
<div class="flex">
|
||||
<div class="iqser-input-group w-300">
|
||||
<label translate="confirm-delete-dossier-state.form.status"></label>
|
||||
<mat-select
|
||||
[placeholder]="'confirm-delete-dossier-state.form.status-placeholder' | translate"
|
||||
formControlName="replaceDossierStatusId"
|
||||
>
|
||||
<mat-option>{{ 'confirm-delete-dossier-state.form.status-placeholder' | translate }}</mat-option>
|
||||
<mat-option *ngFor="let state of data.otherStates" [value]="state.dossierStatusId">
|
||||
{{ state.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button (click)="dialogRef.close(afterCloseValue)" color="primary" mat-flat-button>
|
||||
{{ label | translate }}
|
||||
</button>
|
||||
<div (click)="dialogRef.close()" [translate]="'confirm-delete-dossier-state.cancel'" class="all-caps-label cancel"></div>
|
||||
</div>
|
||||
|
||||
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
|
||||
</section>
|
||||
@ -0,0 +1,16 @@
|
||||
@use 'variables';
|
||||
|
||||
.replacement-suggestion {
|
||||
font-size: 13px;
|
||||
line-height: 18px;
|
||||
color: variables.$grey-1;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.dialog-header {
|
||||
color: variables.$primary;
|
||||
}
|
||||
|
||||
.heading {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
@ -0,0 +1,53 @@
|
||||
import { ChangeDetectionStrategy, Component, Inject } from '@angular/core';
|
||||
import { IDossierState } from '@red/domain';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
|
||||
interface DialogData {
|
||||
readonly toBeDeletedState: IDossierState;
|
||||
readonly otherStates: IDossierState[];
|
||||
readonly dossierCount: number;
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-confirm-delete-dossier-state-dialog',
|
||||
templateUrl: './confirm-delete-dossier-state-dialog.component.html',
|
||||
styleUrls: ['./confirm-delete-dossier-state-dialog.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ConfirmDeleteDossierStateDialogComponent {
|
||||
readonly form: FormGroup;
|
||||
|
||||
constructor(
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
readonly dialogRef: MatDialogRef<ConfirmDeleteDossierStateDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: DialogData,
|
||||
) {
|
||||
this.form = this.#getForm();
|
||||
}
|
||||
|
||||
get translateArgs() {
|
||||
return {
|
||||
name: this.data.toBeDeletedState.name,
|
||||
count: this.data.dossierCount,
|
||||
};
|
||||
}
|
||||
|
||||
get replaceDossierStatusId(): string {
|
||||
return this.form.get('replaceDossierStatusId').value;
|
||||
}
|
||||
|
||||
get label(): string {
|
||||
return this.replaceDossierStatusId ? 'confirm-delete-dossier-state.delete-replace' : 'confirm-delete-dossier-state.delete';
|
||||
}
|
||||
|
||||
get afterCloseValue(): string | true {
|
||||
return this.replaceDossierStatusId ?? true;
|
||||
}
|
||||
|
||||
#getForm(): FormGroup {
|
||||
return this._formBuilder.group({
|
||||
replaceDossierStatusId: [null],
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,97 @@
|
||||
<ng-container *ngIf="dossierStateService.all">
|
||||
<section>
|
||||
<div class="page-header">
|
||||
<redaction-dossier-template-breadcrumbs class="flex-1"></redaction-dossier-template-breadcrumbs>
|
||||
|
||||
<div class="actions flex-1">
|
||||
<redaction-dossier-template-actions></redaction-dossier-template-actions>
|
||||
|
||||
<iqser-circle-button
|
||||
[routerLink]="['../..']"
|
||||
[tooltip]="'common.close' | translate"
|
||||
icon="iqser:close"
|
||||
tooltipPosition="below"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="content-inner">
|
||||
<div class="overlay-shadow"></div>
|
||||
|
||||
<redaction-admin-side-nav type="dossierTemplates"></redaction-admin-side-nav>
|
||||
|
||||
<div class="content-container">
|
||||
<iqser-table
|
||||
[headerTemplate]="headerTemplate"
|
||||
[itemSize]="80"
|
||||
[noDataText]="'dossier-states-listing.no-data.title' | translate"
|
||||
[noMatchText]="'dossier-states-listing.no-match.title' | translate"
|
||||
[selectionEnabled]="true"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
emptyColumnWidth="1fr"
|
||||
noDataIcon="red:attribute"
|
||||
></iqser-table>
|
||||
</div>
|
||||
|
||||
<div class="right-container">
|
||||
<redaction-simple-doughnut-chart
|
||||
*ngIf="chartData"
|
||||
[config]="chartData"
|
||||
[radius]="80"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-states-listing.chart.dossier-states' | translate: { count: chartData.length }"
|
||||
[totalType]="'simpleLabel'"
|
||||
></redaction-simple-doughnut-chart>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ng-template #headerTemplate>
|
||||
<div class="table-header-actions">
|
||||
<iqser-input-with-action
|
||||
[(value)]="searchService.searchValue"
|
||||
[placeholder]="'dossier-states-listing.search' | translate"
|
||||
></iqser-input-with-action>
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="openAddEditStateDialog($event)"
|
||||
*ngIf="currentUser.isAdmin"
|
||||
[label]="'dossier-states-listing.add-new' | translate"
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:plus"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #tableItemTemplate let-entity="entity">
|
||||
<div *ngIf="cast(entity) as state">
|
||||
<div class="cell">
|
||||
<div class="flex-align-items-center">
|
||||
<div [style.background-color]="state.color" class="dossier-state-square"></div>
|
||||
<div class="state-name">{{ state.name }}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cell small-label">
|
||||
<span>{{ state.dossierCount }}</span>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<div *ngIf="currentUser.isAdmin" class="action-buttons">
|
||||
<iqser-circle-button
|
||||
(action)="openAddEditStateDialog($event, state)"
|
||||
[tooltip]="'dossier-states-listing.action.edit' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
<iqser-circle-button
|
||||
(action)="openConfirmDeleteStateDialog($event, state)"
|
||||
[tooltip]="'dossier-states-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
></iqser-circle-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</ng-template>
|
||||
</ng-container>
|
||||
@ -0,0 +1,18 @@
|
||||
@use 'variables';
|
||||
|
||||
.dossier-state-square {
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.state-name {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
color: variables.$grey-1;
|
||||
}
|
||||
|
||||
.right-container {
|
||||
padding: 50px 26px 0;
|
||||
}
|
||||
@ -0,0 +1,126 @@
|
||||
import { ChangeDetectionStrategy, Component, forwardRef, Injector, OnDestroy, OnInit } from '@angular/core';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
DefaultListingServices,
|
||||
IconButtonTypes,
|
||||
ListingComponent,
|
||||
LoadingService,
|
||||
TableColumnConfig,
|
||||
Toaster,
|
||||
} from '../../../../../../../../libs/common-ui/src';
|
||||
import { DossierState, IDossierState } from '@red/domain';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossiersService } from '../../../../services/entity-services/dossiers.service';
|
||||
import { DossierStateService } from '../../../../services/entity-services/dossier-state.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { HttpStatusCode } from '@angular/common/http';
|
||||
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { DossierTemplatesService } from '../../../../services/entity-services/dossier-templates.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-states-listing-screen.component.html',
|
||||
styleUrls: ['./dossier-states-listing-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [
|
||||
...DefaultListingServices,
|
||||
{ provide: ListingComponent, useExisting: forwardRef(() => DossierStatesListingScreenComponent) },
|
||||
],
|
||||
})
|
||||
export class DossierStatesListingScreenComponent extends ListingComponent<DossierState> implements OnInit, OnDestroy {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly #dossierTemplateId: string;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly tableHeaderLabel = _('dossier-states-listing.table-header.title');
|
||||
readonly tableColumnConfigs: TableColumnConfig<DossierState>[] = [
|
||||
{ label: _('dossier-states-listing.table-col-names.name'), sortByKey: 'searchKey' },
|
||||
{ label: _('dossier-states-listing.table-col-names.dossiers-count'), sortByKey: 'dossierCount' },
|
||||
];
|
||||
chartData: DoughnutChartConfig[];
|
||||
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
readonly dossierStateService: DossierStateService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _route: ActivatedRoute,
|
||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||
) {
|
||||
super(_injector);
|
||||
this.#dossierTemplateId = _route.snapshot.paramMap.get('dossierTemplateId');
|
||||
}
|
||||
|
||||
ngOnInit(): Promise<void> {
|
||||
return this.#loadData();
|
||||
}
|
||||
|
||||
openAddEditStateDialog($event: MouseEvent, dossierState?: IDossierState) {
|
||||
const data = {
|
||||
dossierState,
|
||||
dossierTemplateId: this.#dossierTemplateId,
|
||||
};
|
||||
this._dialogService.openDialog('addEditDossierState', $event, data, async (newValue: IDossierState) => {
|
||||
await this.#createNewDossierStateAndRefreshView(newValue);
|
||||
});
|
||||
}
|
||||
|
||||
openConfirmDeleteStateDialog($event: MouseEvent, dossierState: IDossierState) {
|
||||
const templateId = this.#dossierTemplateId;
|
||||
const data = {
|
||||
toBeDeletedState: dossierState,
|
||||
otherStates: this.entitiesService.all.filter(state => state.dossierStatusId !== dossierState.dossierStatusId),
|
||||
dossierCount: dossierState.dossierCount,
|
||||
};
|
||||
this._dialogService.openDialog('deleteDossierState', $event, data, async (value: string | true) => {
|
||||
if (value) {
|
||||
if (typeof value === 'string') {
|
||||
await firstValueFrom(this.dossierStateService.deleteAndReplace(dossierState.dossierStatusId, value));
|
||||
} else {
|
||||
await firstValueFrom(this.dossierStateService.delete(dossierState.dossierStatusId));
|
||||
}
|
||||
}
|
||||
|
||||
await this._dossierTemplatesService.refreshDossierTemplate(templateId);
|
||||
await this.#loadData();
|
||||
});
|
||||
}
|
||||
|
||||
async #createNewDossierStateAndRefreshView(newValue: IDossierState): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this.dossierStateService.setDossierState(newValue)).catch(error => {
|
||||
if (error.status === HttpStatusCode.Conflict) {
|
||||
this._toaster.error(_('dossier-states-listing.error.conflict'));
|
||||
} else {
|
||||
this._toaster.error(_('dossier-states-listing.error.generic'));
|
||||
}
|
||||
});
|
||||
await this._dossierTemplatesService.refreshDossierTemplate(this.#dossierTemplateId);
|
||||
await this.#loadData();
|
||||
}
|
||||
|
||||
async #loadData(): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._dossiersService.loadAll());
|
||||
|
||||
try {
|
||||
const dossierStates = this.dossierStateService.all.filter(d => d.dossierTemplateId === this.#dossierTemplateId);
|
||||
this.#setStatesCount(dossierStates);
|
||||
this.chartData = this.dossierStateService.all.map(state => {
|
||||
return { value: state.dossierCount, label: state.name, key: state.name, color: state.color };
|
||||
});
|
||||
|
||||
this.entitiesService.setEntities(dossierStates || []);
|
||||
} catch (e) {}
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
#setStatesCount(dossierStates: DossierState[]): void {
|
||||
dossierStates.forEach(state => (state.dossierCount = this._dossiersService.getCountWithState(state.dossierStatusId)));
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,8 @@ import { AddEditDossierAttributeDialogComponent } from '../dialogs/add-edit-doss
|
||||
import { ConfirmationDialogComponent, DialogConfig, DialogService, largeDialogConfig } from '@iqser/common-ui';
|
||||
import { UploadDictionaryDialogComponent } from '../dialogs/upload-dictionary-dialog/upload-dictionary-dialog.component';
|
||||
import { FileAttributesConfigurationsDialogComponent } from '../dialogs/file-attributes-configurations-dialog/file-attributes-configurations-dialog.component';
|
||||
import { AddEditDossierStateDialogComponent } from '../dialogs/add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component';
|
||||
import { ConfirmDeleteDossierStateDialogComponent } from '../dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component';
|
||||
|
||||
type DialogType =
|
||||
| 'confirm'
|
||||
@ -27,7 +29,9 @@ type DialogType =
|
||||
| 'smtpAuthConfig'
|
||||
| 'addEditDossierTemplate'
|
||||
| 'addEditDossierAttribute'
|
||||
| 'uploadDictionary';
|
||||
| 'uploadDictionary'
|
||||
| 'addEditDossierState'
|
||||
| 'deleteDossierState';
|
||||
|
||||
@Injectable()
|
||||
export class AdminDialogService extends DialogService<DialogType> {
|
||||
@ -82,6 +86,12 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
uploadDictionary: {
|
||||
component: UploadDictionaryDialogComponent,
|
||||
},
|
||||
addEditDossierState: {
|
||||
component: AddEditDossierStateDialogComponent,
|
||||
},
|
||||
deleteDossierState: {
|
||||
component: ConfirmDeleteDossierStateDialogComponent,
|
||||
},
|
||||
};
|
||||
|
||||
constructor(protected readonly _dialog: MatDialog) {
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
<input
|
||||
[placeholder]="'add-dossier-dialog.form.name.placeholder' | translate"
|
||||
formControlName="dossierName"
|
||||
id="dossierNameInput"
|
||||
name="dossierName"
|
||||
type="text"
|
||||
/>
|
||||
@ -16,7 +17,12 @@
|
||||
<div class="iqser-input-group required w-400">
|
||||
<mat-form-field floatLabel="always">
|
||||
<mat-label>{{ 'add-dossier-dialog.form.template' | translate }}</mat-label>
|
||||
<mat-select (valueChange)="dossierTemplateChanged($event)" formControlName="dossierTemplateId" style="width: 100%">
|
||||
<mat-select
|
||||
(valueChange)="dossierTemplateChanged($event)"
|
||||
formControlName="dossierTemplateId"
|
||||
id="dossierTemplateSelect"
|
||||
style="width: 100%"
|
||||
>
|
||||
<mat-option
|
||||
*ngFor="let dossierTemplate of dossierTemplates"
|
||||
[matTooltip]="dossierTemplate.description ? dossierTemplate.description : dossierTemplate.name"
|
||||
@ -88,7 +94,7 @@
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button [disabled]="disabled" color="primary" mat-flat-button type="submit">
|
||||
<button [disabled]="disabled" color="primary" id="createDossierSaveButton" mat-flat-button type="submit">
|
||||
{{ 'add-dossier-dialog.actions.save' | translate }}
|
||||
</button>
|
||||
|
||||
@ -98,11 +104,12 @@
|
||||
[label]="'add-dossier-dialog.actions.save-and-add-members' | translate"
|
||||
[type]="iconButtonTypes.dark"
|
||||
icon="red:assign"
|
||||
id="createDossierEditTeamButton"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
|
||||
<iqser-circle-button (action)="close()" class="dialog-close" icon="iqser:close"></iqser-circle-button>
|
||||
</section>
|
||||
|
||||
<ng-template #reportTemplateOptionTemplate let-option="option">
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form [formGroup]="form" *ngIf="form">
|
||||
<form *ngIf="form" [formGroup]="form">
|
||||
<div class="iqser-input-group">
|
||||
<mat-checkbox color="primary" formControlName="addToDictionaryAction" name="addToDictionaryAction">
|
||||
{{ 'add-edit-dictionary.form.add-to-dictionary-action' | translate }}
|
||||
@ -19,7 +19,7 @@
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div *ngIf="canEdit" class="display-name">
|
||||
<div *ngIf="canEditDisplayName" class="display-name">
|
||||
<div translate="edit-dossier-dialog.dictionary.display-name.edit"></div>
|
||||
<iqser-editable-input
|
||||
(save)="updateDisplayName($event)"
|
||||
|
||||
@ -20,10 +20,10 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
|
||||
|
||||
form: FormGroup;
|
||||
canEdit = false;
|
||||
canEditDisplayName = false;
|
||||
dossierDictionary: IDictionary;
|
||||
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
|
||||
@ViewChild(DictionaryManagerComponent, { static: false }) private readonly _dictionaryManager: DictionaryManagerComponent;
|
||||
|
||||
constructor(
|
||||
@ -58,6 +58,7 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
|
||||
async ngOnInit() {
|
||||
this._loadingService.start();
|
||||
this.canEdit = this._permissionsService.canEditDossier(this.dossier);
|
||||
this.canEditDisplayName = this._permissionsService.isOwner(this.dossier);
|
||||
await this._updateDossierDictionary();
|
||||
this.form = this._getForm();
|
||||
this._loadingService.stop();
|
||||
|
||||
@ -49,7 +49,14 @@
|
||||
</div>
|
||||
|
||||
<div *ngIf="showActionButtons" class="dialog-actions">
|
||||
<button (click)="save()" [disabled]="disabled || !valid || !changed" color="primary" mat-flat-button type="button">
|
||||
<button
|
||||
(click)="save()"
|
||||
[disabled]="disabled || !valid || !changed"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
type="button"
|
||||
id="editDossierSaveButton"
|
||||
>
|
||||
{{ 'edit-dossier-dialog.actions.save' | translate }}
|
||||
</button>
|
||||
<iqser-icon-button
|
||||
@ -65,5 +72,5 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()"></iqser-circle-button>
|
||||
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()" id="editDossierCloseButton"></iqser-circle-button>
|
||||
</section>
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<div class="iqser-input-group w-300 required">
|
||||
<mat-form-field floatLabel="always">
|
||||
<mat-label>{{ 'assign-dossier-owner.dialog.single-user' | translate }}</mat-label>
|
||||
<mat-select formControlName="owner">
|
||||
<mat-select formControlName="owner" id="editDossierOwnerSelect">
|
||||
<mat-option *ngFor="let userId of ownersSelectOptions" [value]="userId">
|
||||
{{ userId | name }}
|
||||
</mat-option>
|
||||
|
||||
@ -1,71 +1,89 @@
|
||||
<form [formGroup]="form">
|
||||
<div class="iqser-input-group required w-300">
|
||||
<label translate="edit-dossier-dialog.general-info.form.name.label"></label>
|
||||
<input
|
||||
[placeholder]="'edit-dossier-dialog.general-info.form.name.placeholder' | translate"
|
||||
formControlName="dossierName"
|
||||
name="dossierName"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="flex fields-container">
|
||||
<div class="iqser-input-group required w-300">
|
||||
<label translate="edit-dossier-dialog.general-info.form.name.label"></label>
|
||||
<input
|
||||
[placeholder]="'edit-dossier-dialog.general-info.form.name.placeholder' | translate"
|
||||
formControlName="dossierName"
|
||||
name="dossierName"
|
||||
type="text"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="iqser-input-group required w-400">
|
||||
<mat-form-field floatLabel="always">
|
||||
<mat-label>{{ 'edit-dossier-dialog.general-info.form.template' | translate }}</mat-label>
|
||||
<mat-select formControlName="dossierTemplateId" style="width: 100%">
|
||||
<mat-option
|
||||
*ngFor="let dossierTemplate of dossierTemplates"
|
||||
[matTooltip]="dossierTemplate.description ? dossierTemplate.description : dossierTemplate.name"
|
||||
[value]="dossierTemplate.dossierTemplateId"
|
||||
matTooltipPosition="after"
|
||||
<div class="iqser-input-group required w-400">
|
||||
<mat-form-field floatLabel="always">
|
||||
<mat-label>{{ 'edit-dossier-dialog.general-info.form.template' | translate }}</mat-label>
|
||||
<mat-select formControlName="dossierTemplateId" style="width: 100%">
|
||||
<mat-option
|
||||
*ngFor="let dossierTemplate of dossierTemplates"
|
||||
[matTooltip]="dossierTemplate.description ? dossierTemplate.description : dossierTemplate.name"
|
||||
[value]="dossierTemplate.dossierTemplateId"
|
||||
matTooltipPosition="after"
|
||||
>
|
||||
{{ dossierTemplate.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
|
||||
<div class="iqser-input-group w-400">
|
||||
<label translate="edit-dossier-dialog.general-info.form.description.label"></label>
|
||||
<textarea
|
||||
[placeholder]="'edit-dossier-dialog.general-info.form.description.placeholder' | translate"
|
||||
formControlName="description"
|
||||
iqserHasScrollbar
|
||||
name="description"
|
||||
rows="5"
|
||||
type="text"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<mat-checkbox class="watermark" color="primary" formControlName="watermarkEnabled">
|
||||
{{ 'edit-dossier-dialog.general-info.form.watermark' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<mat-checkbox class="watermark-preview" color="primary" formControlName="watermarkPreviewEnabled">
|
||||
{{ 'edit-dossier-dialog.general-info.form.watermark-preview' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex fields-container">
|
||||
<div class="iqser-input-group w-300">
|
||||
<label translate="edit-dossier-dialog.general-info.form.dossier-status.label"></label>
|
||||
<mat-select [placeholder]="statusPlaceholder" [disabled]="states.length === 0" formControlName="dossierStatusId">
|
||||
<mat-option *ngFor="let state of states" [value]="state.dossierStatusId">
|
||||
<div class="flex-align-items-center">
|
||||
<redaction-small-chip [color]="state.color"></redaction-small-chip>
|
||||
<div>{{ state.name }}</div>
|
||||
</div>
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</div>
|
||||
|
||||
<div class="due-date">
|
||||
<mat-checkbox
|
||||
(change)="hasDueDate = !hasDueDate"
|
||||
[checked]="hasDueDate"
|
||||
[disabled]="!permissionsService.canEditDossier(dossier)"
|
||||
class="filter-menu-checkbox"
|
||||
color="primary"
|
||||
>
|
||||
{{ dossierTemplate.name }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
</mat-form-field>
|
||||
</div>
|
||||
{{ 'edit-dossier-dialog.general-info.form.due-date' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
<div class="iqser-input-group w-400">
|
||||
<label translate="edit-dossier-dialog.general-info.form.description.label"></label>
|
||||
<textarea
|
||||
[placeholder]="'edit-dossier-dialog.general-info.form.description.placeholder' | translate"
|
||||
formControlName="description"
|
||||
iqserHasScrollbar
|
||||
name="description"
|
||||
rows="5"
|
||||
type="text"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<mat-checkbox class="watermark" color="primary" formControlName="watermarkEnabled">
|
||||
{{ 'edit-dossier-dialog.general-info.form.watermark' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<mat-checkbox class="watermark-preview" color="primary" formControlName="watermarkPreviewEnabled">
|
||||
{{ 'edit-dossier-dialog.general-info.form.watermark-preview' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="due-date">
|
||||
<mat-checkbox
|
||||
(change)="hasDueDate = !hasDueDate"
|
||||
[checked]="hasDueDate"
|
||||
[disabled]="!permissionsService.canEditDossier(dossier)"
|
||||
class="filter-menu-checkbox"
|
||||
color="primary"
|
||||
>
|
||||
{{ 'edit-dossier-dialog.general-info.form.due-date' | translate }}
|
||||
</mat-checkbox>
|
||||
|
||||
<div *ngIf="hasDueDate" class="iqser-input-group datepicker-wrapper">
|
||||
<input [matDatepicker]="picker" formControlName="dueDate" placeholder="dd/mm/yy" />
|
||||
<mat-datepicker-toggle [for]="picker" matSuffix>
|
||||
<mat-icon matDatepickerToggleIcon svgIcon="red:calendar"></mat-icon>
|
||||
</mat-datepicker-toggle>
|
||||
<mat-datepicker #picker></mat-datepicker>
|
||||
<div *ngIf="hasDueDate" class="iqser-input-group datepicker-wrapper">
|
||||
<input [matDatepicker]="picker" formControlName="dueDate" placeholder="dd/mm/yy" />
|
||||
<mat-datepicker-toggle [for]="picker" matSuffix>
|
||||
<mat-icon matDatepickerToggleIcon svgIcon="red:calendar"></mat-icon>
|
||||
</mat-datepicker-toggle>
|
||||
<mat-datepicker #picker></mat-datepicker>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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<EditDossierDialogComponent>,
|
||||
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;
|
||||
|
||||
@ -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<ForceAnnotationDialogComponent>,
|
||||
@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() {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
</div>
|
||||
|
||||
<div class="header-wrapper mt-8">
|
||||
<div class="heading-xl flex-1">{{ dossier.dossierName }}</div>
|
||||
<div class="heading-xl flex-1" id="dossierDetailsDossierName">{{ dossier.dossierName }}</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="collapsible; context: { action: 'collapse', tooltip: (collapseTooltip | translate) }"
|
||||
></ng-container>
|
||||
|
||||
@ -91,6 +91,18 @@ export class BulkActionsService {
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
async toggleAnalysis(files: File[], excluded: boolean) {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(
|
||||
this._reanalysisService.toggleAnalysis(
|
||||
files[0].dossierId,
|
||||
files.map(f => f.id),
|
||||
excluded,
|
||||
),
|
||||
);
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
async backToUnderReview(files: File[]): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(
|
||||
|
||||
@ -0,0 +1 @@
|
||||
<iqser-status-bar *ngIf="stats" [configs]="statusBarConfig"></iqser-status-bar>
|
||||
@ -0,0 +1,24 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
|
||||
import { DossierStats, StatusSorter } from '../../../../../../../../../../libs/red-domain/src';
|
||||
import { List, StatusBarConfig } from '../../../../../../../../../../libs/common-ui/src';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-documents-status',
|
||||
templateUrl: './dossier-documents-status.component.html',
|
||||
styleUrls: ['./dossier-documents-status.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossierDocumentsStatusComponent implements OnChanges {
|
||||
@Input() stats: DossierStats;
|
||||
statusBarConfig: List<StatusBarConfig<string>>;
|
||||
|
||||
private get _statusConfig(): List<StatusBarConfig<string>> {
|
||||
const { fileCountPerWorkflowStatus } = this.stats;
|
||||
const statuses = Object.keys(fileCountPerWorkflowStatus).sort(StatusSorter.byStatus);
|
||||
return statuses.map(status => ({ length: fileCountPerWorkflowStatus[status], color: status }));
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.statusBarConfig = this._statusConfig;
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,3 @@
|
||||
<iqser-status-bar *ngIf="stats" [configs]="statusBarConfig"></iqser-status-bar>
|
||||
|
||||
<div (longPress)="forceReanalysisAction($event)" class="action-buttons" redactionLongPress>
|
||||
<iqser-circle-button
|
||||
(action)="openEditDossierDialog($event, dossier.dossierId)"
|
||||
|
||||
@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/c
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { CircleButtonTypes, List, StatusBarConfig } from '@iqser/common-ui';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { Dossier, DossierStats, File, StatusSorter } from '@red/domain';
|
||||
import { Dossier, DossierStats, File } from '@red/domain';
|
||||
import { DossiersDialogService } from '../../../../services/dossiers-dialog.service';
|
||||
import { LongPressEvent } from '@shared/directives/long-press.directive';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
@ -39,14 +39,7 @@ export class DossiersListingActionsComponent implements OnChanges {
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
) {}
|
||||
|
||||
private get _statusConfig(): List<StatusBarConfig<string>> {
|
||||
const { fileCountPerWorkflowStatus } = this.stats;
|
||||
const statuses = Object.keys(fileCountPerWorkflowStatus).sort(StatusSorter.byStatus);
|
||||
return statuses.map(status => ({ length: fileCountPerWorkflowStatus[status], color: status }));
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.statusBarConfig = this._statusConfig;
|
||||
this.files = this.filesMapService.get(this.dossier.dossierId);
|
||||
this.displayReanalyseBtn = this.permissionsService.displayReanalyseBtn(this.dossier) && this.analysisForced;
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="right-chart">
|
||||
<redaction-simple-doughnut-chart
|
||||
*ngIf="documentsChartData$ | async as config"
|
||||
[config]="config"
|
||||
|
||||
@ -29,3 +29,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right-chart {
|
||||
border-left: 1px solid rgba(226, 228, 233, 0.9);
|
||||
}
|
||||
|
||||
@ -7,8 +7,9 @@ import { Dossier, DossierStats, FileCountPerWorkflowStatus, StatusSorter } from
|
||||
import { workflowFileStatusTranslations } from '../../../../translations/file-status-translations';
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
import { filter, map, switchMap } from 'rxjs/operators';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
|
||||
import { DossierStateService } from '../../../../../../services/entity-services/dossier-state.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossiers-listing-details',
|
||||
@ -25,6 +26,8 @@ export class DossiersListingDetailsComponent {
|
||||
readonly dossiersService: DossiersService,
|
||||
private readonly _dossierStatsMap: DossierStatsService,
|
||||
private readonly _translateChartService: TranslateChartService,
|
||||
private readonly _dossierStateService: DossierStateService,
|
||||
private readonly _translateService: TranslateService,
|
||||
) {
|
||||
this.documentsChartData$ = this.dossiersService.all$.pipe(
|
||||
mapEach(dossier => _dossierStatsMap.watch$(dossier.dossierId)),
|
||||
@ -37,12 +40,19 @@ export class DossiersListingDetailsComponent {
|
||||
}
|
||||
|
||||
private async _toDossierChartData(dossiers: Dossier[]): Promise<DoughnutChartConfig[]> {
|
||||
const config: DoughnutChartConfig[] = [];
|
||||
this._dossierStateService.all.forEach(state => {
|
||||
state.dossierCount = this.dossiersService.getCountWithState(state.dossierStatusId);
|
||||
config.push({ value: state.dossierCount, label: state.name, color: state.color });
|
||||
});
|
||||
const notAssignedLength = this.dossiersService.all.length - config.map(v => v.value).reduce((acc, val) => acc + val, 0);
|
||||
config.push({
|
||||
value: notAssignedLength,
|
||||
label: this._translateService.instant('edit-dossier-dialog.general-info.form.dossier-status.placeholder'),
|
||||
color: '#E2E4E9',
|
||||
});
|
||||
// TODO: deleted dossiers count should come with stats
|
||||
// const deletedDossiers = await this.dossiersService.getDeleted();
|
||||
return [
|
||||
{ value: dossiers.length, color: 'ACTIVE', label: _('active') },
|
||||
// { value: deletedDossiers.length, color: 'DELETED', label: _('archived') },
|
||||
];
|
||||
return config;
|
||||
}
|
||||
|
||||
private _toChartData(stats: DossierStats[]) {
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
<ng-container *ngIf="dossier.dossierStatusId">
|
||||
<div class="flex-align-items-center dossier-status-container">
|
||||
<div class="dossier-status-text">{{ currentState.name }}</div>
|
||||
<redaction-small-chip [color]="currentState.color"></redaction-small-chip>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="!dossier.dossierStatusId">
|
||||
<div class="flex-align-items-center dossier-status-container">
|
||||
<div class="dossier-status-text">{{ 'edit-dossier-dialog.general-info.form.dossier-status.placeholder' | translate }}</div>
|
||||
<redaction-small-chip [color]="'#E2E4E9'"></redaction-small-chip>
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -0,0 +1,16 @@
|
||||
@use 'variables';
|
||||
|
||||
.dossier-status-container {
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
redaction-small-chip {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.dossier-status-text {
|
||||
font-size: 13px;
|
||||
line-height: 16px;
|
||||
color: variables.$grey-1;
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnChanges, OnInit } from '@angular/core';
|
||||
import { Dossier } from '../../../../../../../../../../libs/red-domain/src';
|
||||
import { DossierStateService } from '../../../../../../services/entity-services/dossier-state.service';
|
||||
import { DossierState } from '@red/domain';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossiers-listing-status',
|
||||
templateUrl: './dossiers-listing-status.component.html',
|
||||
styleUrls: ['./dossiers-listing-status.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossiersListingStatusComponent implements OnInit, OnChanges {
|
||||
@Input() dossier: Dossier;
|
||||
currentState: DossierState;
|
||||
|
||||
constructor(private readonly _dossierStateService: DossierStateService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.#setState();
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
this.#setState();
|
||||
}
|
||||
|
||||
#setState(): void {
|
||||
if (this.dossier.dossierStatusId) {
|
||||
this.currentState = this._dossierStateService.all.find(s => s.dossierStatusId === this.dossier.dossierStatusId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,12 @@
|
||||
</div>
|
||||
|
||||
<div class="cell status-container">
|
||||
<redaction-dossier-documents-status [stats]="stats"></redaction-dossier-documents-status>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<redaction-dossiers-listing-status [dossier]="dossier"></redaction-dossiers-listing-status>
|
||||
|
||||
<redaction-dossiers-listing-actions [dossier]="dossier" [stats]="stats"></redaction-dossiers-listing-actions>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
@ -14,15 +14,15 @@ export class TableItemComponent implements OnChanges {
|
||||
@Input() dossier!: Dossier;
|
||||
|
||||
readonly stats$: Observable<DossierStats>;
|
||||
private readonly _ngOnChanges$ = new BehaviorSubject<string>(undefined);
|
||||
readonly #ngOnChanges$ = new BehaviorSubject<string>(undefined);
|
||||
|
||||
constructor(readonly dossierStatsService: DossierStatsService) {
|
||||
this.stats$ = this._ngOnChanges$.pipe(switchMap(dossierId => this.dossierStatsService.watch$(dossierId)));
|
||||
this.stats$ = this.#ngOnChanges$.pipe(switchMap(dossierId => this.dossierStatsService.watch$(dossierId)));
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
if (this.dossier) {
|
||||
this._ngOnChanges$.next(this.dossier.dossierId);
|
||||
this.#ngOnChanges$.next(this.dossier.dossierId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -26,7 +26,8 @@ export class ConfigService {
|
||||
{ label: _('dossier-listing.table-col-names.name'), sortByKey: 'searchKey', width: '2fr' },
|
||||
{ label: _('dossier-listing.table-col-names.needs-work') },
|
||||
{ label: _('dossier-listing.table-col-names.owner'), class: 'user-column' },
|
||||
{ label: _('dossier-listing.table-col-names.status'), class: 'flex-end', width: 'auto' },
|
||||
{ label: _('dossier-listing.table-col-names.documents-status'), class: 'flex-end', width: 'auto' },
|
||||
{ label: _('dossier-listing.table-col-names.dossier-status'), class: 'flex-end' },
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,8 @@ import { ConfigService } from './config.service';
|
||||
import { TableItemComponent } from './components/table-item/table-item.component';
|
||||
import { SharedDossiersModule } from '../../shared/shared-dossiers.module';
|
||||
import { DossierWorkloadColumnComponent } from './components/dossier-workload-column/dossier-workload-column.component';
|
||||
import { DossiersListingStatusComponent } from './components/dossiers-listing-status/dossiers-listing-status.component';
|
||||
import { DossierDocumentsStatusComponent } from './components/dossier-documents-status/dossier-documents-status.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@ -30,6 +32,8 @@ const routes: Routes = [
|
||||
DossiersListingDossierNameComponent,
|
||||
DossierWorkloadColumnComponent,
|
||||
TableItemComponent,
|
||||
DossiersListingStatusComponent,
|
||||
DossierDocumentsStatusComponent,
|
||||
],
|
||||
providers: [ConfigService],
|
||||
imports: [RouterModule.forChild(routes), CommonModule, SharedModule, SharedDossiersModule, IqserIconsModule, TranslateModule],
|
||||
|
||||
@ -92,7 +92,7 @@
|
||||
<mat-icon svgIcon="red:nav-first"></mat-icon>
|
||||
</div>
|
||||
|
||||
<div class="pages" id="pages">
|
||||
<div *ngIf="state.fileData$ | async as fileData" class="pages" id="pages">
|
||||
<redaction-page-indicator
|
||||
(pageSelected)="pageSelectedByClick($event)"
|
||||
*ngFor="let pageNumber of displayedPages"
|
||||
@ -100,6 +100,7 @@
|
||||
[active]="pageNumber === activeViewerPage"
|
||||
[number]="pageNumber"
|
||||
[showDottedIcon]="hasOnlyManualRedactionsAndIsExcluded(pageNumber)"
|
||||
[viewedPages]="fileData.viewedPages"
|
||||
></redaction-page-indicator>
|
||||
</div>
|
||||
|
||||
|
||||
@ -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<number>();
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<DossierState, IDossierState> {
|
||||
constructor(protected readonly _injector: Injector, private readonly _dossierTemplatesService: DossierTemplatesService) {
|
||||
super(_injector, DossierState, 'dossier-status');
|
||||
}
|
||||
|
||||
@Validate()
|
||||
setDossierState(@RequiredParam() body: IDossierState) {
|
||||
return this._post<unknown>(body, this._defaultModelPath);
|
||||
}
|
||||
|
||||
@Validate()
|
||||
loadAllForTemplate(@RequiredParam() templateId: string) {
|
||||
return this.loadAll(`${this._defaultModelPath}/dossier-template/${templateId}`);
|
||||
}
|
||||
|
||||
loadAllForAllTemplates(): Observable<DossierState[]> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -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<Dossier, IDossier> {
|
||||
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<Dossier, IDossier> {
|
||||
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<Dossier, IDossier> {
|
||||
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));
|
||||
}
|
||||
|
||||
@ -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 (
|
||||
|
||||
@ -49,13 +49,13 @@ export class ReanalysisService extends GenericService<unknown> {
|
||||
}
|
||||
|
||||
@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)),
|
||||
);
|
||||
}
|
||||
|
||||
@ -605,6 +605,7 @@
|
||||
"title": "Datei-Attribute anlegen"
|
||||
},
|
||||
"dossier": "Dossier",
|
||||
"dossier-states": "",
|
||||
"dossier-attribute-types": {
|
||||
"date": "Datum",
|
||||
"image": "Bild",
|
||||
|
||||
@ -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": {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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';
|
||||
|
||||
28
libs/red-domain/src/lib/dossier-state/dossier-state.model.ts
Normal file
28
libs/red-domain/src/lib/dossier-state/dossier-state.model.ts
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
8
libs/red-domain/src/lib/dossier-state/dossier-state.ts
Normal file
8
libs/red-domain/src/lib/dossier-state/dossier-state.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export interface IDossierState {
|
||||
description: string;
|
||||
dossierStatusId: string;
|
||||
dossierTemplateId: string;
|
||||
name: string;
|
||||
color: string;
|
||||
dossierCount?: number;
|
||||
}
|
||||
2
libs/red-domain/src/lib/dossier-state/index.ts
Normal file
2
libs/red-domain/src/lib/dossier-state/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './dossier-state';
|
||||
export * from './dossier-state.model';
|
||||
@ -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;
|
||||
|
||||
@ -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<DownloadFileType>;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "redaction",
|
||||
"version": "3.229.0",
|
||||
"version": "3.236.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user