RED-3796: Use dossier template stats endpoint
This commit is contained in:
parent
06c9b2bbc7
commit
30dbee52d2
14
apps/red-ui/src/app/guards/dashboard-guard.service.ts
Normal file
14
apps/red-ui/src/app/guards/dashboard-guard.service.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate } from '@angular/router';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class DashboardGuard implements CanActivate {
|
||||
constructor(private readonly _dashboardStatsService: DashboardStatsService) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
|
||||
await firstValueFrom(this._dashboardStatsService.loadAll());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { DOSSIER_TEMPLATE_ID } from '@utils/constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
|
||||
@ -1,15 +1,11 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CanActivate } from '@angular/router';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class DossierTemplatesGuard implements CanActivate {
|
||||
constructor(
|
||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
) {}
|
||||
constructor(private readonly _dossierTemplatesService: DossierTemplatesService) {}
|
||||
|
||||
async canActivate(): Promise<boolean> {
|
||||
await firstValueFrom(this._dossierTemplatesService.loadAll());
|
||||
|
||||
@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
|
||||
import { DOSSIER_TEMPLATE_ID, ENTITY_TYPE } from '@utils/constants';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class EntityExistsGuard implements CanActivate {
|
||||
|
||||
@ -6,7 +6,7 @@ import { AdminDialogService } from '../services/admin-dialog.service';
|
||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { LoadingService } from '@iqser/common-ui';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, Input } from '@angular/core';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
@ -23,7 +23,7 @@ export class AddEditDossierStateDialogComponent extends BaseDialogComponent {
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _dossierStateService: DossierStatesService,
|
||||
private readonly _dossierStatesService: DossierStatesService,
|
||||
protected readonly _injector: Injector,
|
||||
protected readonly _dialogRef: MatDialogRef<AddEditDossierStateDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: DialogData,
|
||||
@ -45,7 +45,7 @@ export class AddEditDossierStateDialogComponent extends BaseDialogComponent {
|
||||
};
|
||||
this._loadingService.start();
|
||||
try {
|
||||
await firstValueFrom(this._dossierStateService.createOrUpdate(dossierState));
|
||||
await firstValueFrom(this._dossierStatesService.createOrUpdate(dossierState));
|
||||
this._toaster.success(_('add-edit-dossier-state.success'), { params: { type: this.type } });
|
||||
this._dialogRef.close();
|
||||
} catch (e) {}
|
||||
|
||||
@ -3,7 +3,7 @@ import { AbstractControl, FormBuilder, FormGroup, Validators } from '@angular/fo
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { applyIntervalConstraints } from '@utils/date-inputs-utils';
|
||||
import { downloadTypesTranslations } from '../../../../translations/download-types-translations';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { BaseDialogComponent, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossierTemplate, DownloadFileType, IDossierTemplate } from '@red/domain';
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { DossierTemplate } from '@red/domain';
|
||||
import { LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
@ -29,7 +29,7 @@ export class ConfirmDeleteDossierStateDialogComponent {
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _dossierStateService: DossierStatesService,
|
||||
private readonly _dossierStatesService: DossierStatesService,
|
||||
private readonly _dialogRef: MatDialogRef<ConfirmDeleteDossierStateDialogComponent>,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _archivedDossiersService: ArchivedDossiersService,
|
||||
@ -55,7 +55,7 @@ export class ConfirmDeleteDossierStateDialogComponent {
|
||||
|
||||
async save(): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._dossierStateService.deleteState(this.data.toBeDeletedState, this.replaceDossierStatusId));
|
||||
await firstValueFrom(this._dossierStatesService.deleteState(this.data.toBeDeletedState, this.replaceDossierStatusId));
|
||||
await firstValueFrom(
|
||||
forkJoin([this._activeDossiersService.loadAll().pipe(take(1)), this._archivedDossiersService.loadAll().pipe(take(1))]),
|
||||
);
|
||||
|
||||
@ -4,7 +4,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { FileAttributeEncodingTypes, IFileAttributesConfig } from '@red/domain';
|
||||
import { fileAttributeEncodingTypesTranslations } from '../../translations/file-attribute-encoding-types-translations';
|
||||
import { BaseDialogComponent, Toaster } from '@iqser/common-ui';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||
|
||||
@ -13,7 +13,7 @@ import { defaultColorsTranslations } from '../../translations/default-colors-tra
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { DOSSIER_TEMPLATE_ID } from '@utils/constants';
|
||||
|
||||
@ -15,7 +15,7 @@ import {
|
||||
import { UserService } from '@services/user.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { RouterHistoryService } from '@services/router-history.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -28,7 +28,7 @@ import { HttpStatusCode } from '@angular/common/http';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { ReportTemplateService } from '../../../../services/report-template.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { DOSSIER_TEMPLATE_ID } from '@utils/constants';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { DossierTemplate, DossierTemplateStats } from '@red/domain';
|
||||
|
||||
@ -3,7 +3,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { Justification } from '@red/domain';
|
||||
import { JustificationsService } from '@services/entity-services/justifications.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { BaseDialogComponent, LoadingService } from '@iqser/common-ui';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ import {
|
||||
} from '@iqser/common-ui';
|
||||
import { AddEditJustificationDialogComponent } from './add-edit-justification-dialog/add-edit-justification-dialog.component';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { JustificationsService } from '@services/entity-services/justifications.service';
|
||||
import { Justification } from '@red/domain';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
@ -10,7 +10,7 @@ import {
|
||||
import { removeBraces } from '@utils/functions';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { AdminDialogService } from '../../../services/admin-dialog.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { ReportTemplateService } from '@services/report-template.service';
|
||||
import { BehaviorSubject, firstValueFrom } from 'rxjs';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
@ -18,7 +18,7 @@ import { TrashItem } from '@red/domain';
|
||||
import { TrashService } from '@services/entity-services/trash.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './trash-screen.component.html',
|
||||
|
||||
@ -3,7 +3,7 @@ import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { AdminDialogService } from '../../../services/admin-dialog.service';
|
||||
import { CircleButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||
import { DOSSIER_TEMPLATE_ID } from '@utils/constants';
|
||||
@ -37,6 +37,7 @@ export class DossierTemplateActionsComponent implements OnInit {
|
||||
openEditDossierTemplateDialog($event: MouseEvent) {
|
||||
this._dialogService.openDialog('addEditDossierTemplate', $event, this.dossierTemplateId);
|
||||
}
|
||||
|
||||
openCloneDossierTemplateDialog($event: MouseEvent) {
|
||||
this._dialogService.openDialog('cloneDossierTemplate', $event, this.dossierTemplateId);
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { dossierMemberChecker, dossierTemplateChecker } from '@utils/index';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
|
||||
@Injectable()
|
||||
export class ConfigService {
|
||||
|
||||
@ -1,13 +1,32 @@
|
||||
<div *ngIf="dossierTemplate$ | async as dossierTemplate" [class.empty]="empty" class="dialog">
|
||||
<ng-container *ngIf="!empty">
|
||||
<a [routerLink]="dossierTemplate.dossiersRouterLink" class="heading">{{ dossierTemplate.name }}</a>
|
||||
<div>
|
||||
<!-- <pre>{{ stats$ | async | json }}</pre>-->
|
||||
<div *ngIf="stats as dossierTemplate" [class.empty]="dossierTemplate.isEmpty" class="dialog">
|
||||
<ng-container *ngIf="!dossierTemplate.isEmpty; else empty">
|
||||
<div class="flex-1">
|
||||
<a [routerLink]="['..', dossierTemplate.dossierTemplateId]" class="heading">{{ dossierTemplate.name }}</a>
|
||||
{{ dossierTemplate.id }}
|
||||
</div>
|
||||
<div class="flex-2">
|
||||
<redaction-simple-doughnut-chart
|
||||
[config]="translateChartService.translateDossierStates(dossierTemplate.dossiersChartData, dossierTemplate.id)"
|
||||
[radius]="70"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-template-charts.active-dossiers' | translate: { count: dossierTemplate.numberOfActiveDossiers }"
|
||||
direction="row"
|
||||
totalType="sum"
|
||||
></redaction-simple-doughnut-chart>
|
||||
</div>
|
||||
<div class="flex-2">
|
||||
<redaction-simple-doughnut-chart
|
||||
[config]="translateChartService.translateWorkflowStatus(dossierTemplate.documentsChartData)"
|
||||
[radius]="70"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-template-charts.total-documents' | translate"
|
||||
direction="row"
|
||||
totalType="sum"
|
||||
></redaction-simple-doughnut-chart>
|
||||
</div>
|
||||
<div>stats2</div>
|
||||
</ng-container>
|
||||
|
||||
<div *ngIf="empty" class="empty">
|
||||
<ng-template #empty>
|
||||
<div class="text-muted">
|
||||
<div class="heading mb-8">
|
||||
{{ dossierTemplate.name }}
|
||||
@ -22,5 +41,5 @@
|
||||
[type]="iconButtonTypes.primary"
|
||||
icon="iqser:plus"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
.dialog {
|
||||
flex-direction: row;
|
||||
max-width: unset;
|
||||
min-height: unset;
|
||||
margin: 0 0 16px 0;
|
||||
|
||||
.heading {
|
||||
@ -11,22 +12,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
> div {
|
||||
&.empty {
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24px;
|
||||
}
|
||||
|
||||
&:not(.empty) > div {
|
||||
padding: 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
|
||||
&:not(:first-child) {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-left: 1px solid var(--iqser-separator);
|
||||
}
|
||||
|
||||
&.empty {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,49 +1,28 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplate, DossierTemplateStats } from '@red/domain';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
import { DossierTemplateStatsService } from '@services/entity-services/dossier-template-stats.service';
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { DashboardStats } from '@red/domain';
|
||||
import { IconButtonTypes } from '@iqser/common-ui';
|
||||
import { DossiersDialogService } from '../../../dossier/services/dossiers-dialog.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { DossiersDialogService } from '../../../dossier/shared/services/dossiers-dialog.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-template-stats [dossierTemplateId]',
|
||||
selector: 'redaction-template-stats [stats]',
|
||||
templateUrl: './template-stats.component.html',
|
||||
styleUrls: ['./template-stats.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class TemplateStatsComponent implements OnChanges {
|
||||
export class TemplateStatsComponent {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
|
||||
@Input() dossierTemplateId: string;
|
||||
|
||||
readonly dossierTemplate$: Observable<DossierTemplate>;
|
||||
readonly stats$: Observable<DossierTemplateStats>;
|
||||
readonly #ngOnChanges$ = new BehaviorSubject<string>(undefined);
|
||||
@Input() stats: DashboardStats;
|
||||
|
||||
constructor(
|
||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||
private readonly _dossierTemplateStatsService: DossierTemplateStatsService,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _router: Router,
|
||||
) {
|
||||
this.dossierTemplate$ = this.#ngOnChanges$.pipe(switchMap(id => this._dossierTemplatesService.getEntityChanged$(id)));
|
||||
this.stats$ = this.#ngOnChanges$.pipe(switchMap(id => this._dossierTemplateStatsService.watch$(id)));
|
||||
}
|
||||
|
||||
get empty(): boolean {
|
||||
return false;
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
if (this.dossierTemplateId) {
|
||||
this.#ngOnChanges$.next(this.dossierTemplateId);
|
||||
}
|
||||
}
|
||||
private readonly _translateService: TranslateService,
|
||||
readonly translateChartService: TranslateChartService,
|
||||
) {}
|
||||
|
||||
newDossier(): void {
|
||||
this._dialogService.openDialog('addDossier', null, { dossierTemplateId: this.dossierTemplateId });
|
||||
this._dialogService.openDialog('addDossier', null, { dossierTemplateId: this.stats.dossierTemplateId });
|
||||
}
|
||||
}
|
||||
|
||||
@ -9,8 +9,5 @@
|
||||
|
||||
<div class="mb-32" translate="dashboard.greeting.subtitle"></div>
|
||||
|
||||
<redaction-template-stats
|
||||
*ngFor="let dossierTemplate of dossierTemplatesService.all$ | async"
|
||||
[dossierTemplateId]="dossierTemplate.id"
|
||||
></redaction-template-stats>
|
||||
<redaction-template-stats *ngFor="let dossierTemplate of stats$ | async" [stats]="dossierTemplate"></redaction-template-stats>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { UserService } from '../../../services/user.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dashboard-screen',
|
||||
@ -10,6 +10,7 @@ import { DossierTemplatesService } from '@services/entity-services/dossier-templ
|
||||
})
|
||||
export class DashboardScreenComponent {
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly stats$ = this._dashboardStatsService.all$;
|
||||
|
||||
constructor(private readonly _userService: UserService, readonly dossierTemplatesService: DossierTemplatesService) {}
|
||||
constructor(private readonly _userService: UserService, private readonly _dashboardStatsService: DashboardStatsService) {}
|
||||
}
|
||||
|
||||
@ -4,10 +4,11 @@ import { DashboardScreenComponent } from './dashboard-screen/dashboard-screen.co
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { TemplateStatsComponent } from './components/template-stats/template-stats.component';
|
||||
import { DossierTemplatesGuard } from '../../guards/dossier-templates.guard';
|
||||
import { CompositeRouteGuard } from '@iqser/common-ui';
|
||||
import { SharedDossiersModule } from '../dossier/shared/shared-dossiers.module';
|
||||
import { BreadcrumbTypes } from '@red/domain';
|
||||
import { DossierTemplatesGuard } from '../../guards/dossier-templates.guard';
|
||||
import { DashboardGuard } from '../../guards/dashboard-guard.service';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
@ -15,8 +16,8 @@ const routes = [
|
||||
component: DashboardScreenComponent,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [DossierTemplatesGuard],
|
||||
breadcrumbs: [BreadcrumbTypes.dashboard],
|
||||
routeGuards: [DossierTemplatesGuard, DashboardGuard],
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core';
|
||||
import { Dossier, DossierAttributeWithValue, DossierStats } from '@red/domain';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { firstValueFrom, Observable } from 'rxjs';
|
||||
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
|
||||
import { DossiersDialogService } from '../../../dossier/services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from '../../../dossier/shared/services/dossiers-dialog.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-details-stats',
|
||||
|
||||
@ -10,7 +10,7 @@ import { ActivatedRoute } from '@angular/router';
|
||||
import { firstValueFrom, Observable } from 'rxjs';
|
||||
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
|
||||
import { map, pluck, switchMap } from 'rxjs/operators';
|
||||
import { DossiersDialogService } from '../../../dossier/services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from '../../../dossier/shared/services/dossiers-dialog.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { DOSSIER_ID } from '@utils/constants';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
@ -80,7 +80,7 @@ export class DossierDetailsComponent {
|
||||
key: status,
|
||||
}));
|
||||
documentsChartData.sort((a, b) => StatusSorter.byStatus(a.key, b.key));
|
||||
return this.translateChartService.translateStatus(documentsChartData);
|
||||
return this.translateChartService.translateLabels(documentsChartData);
|
||||
}
|
||||
|
||||
#calculateStatusConfig(stats: DossierStats): ProgressBarConfigModel[] {
|
||||
|
||||
@ -17,7 +17,7 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { DossiersDialogService } from '../dossier/services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from '../dossier/shared/services/dossiers-dialog.service';
|
||||
import { annotationFilterChecker, RedactionFilterSorter } from '../../utils';
|
||||
import { workloadTranslations } from '../dossier/translations/workload-translations';
|
||||
import { ConfigService as AppConfigService } from '@services/config.service';
|
||||
|
||||
@ -28,7 +28,7 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
|
||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||
import { ConfigService } from '../config.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Dossier, File } from '@red/domain';
|
||||
import { DossiersDialogService } from '../../dossier/services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from '../../dossier/shared/services/dossiers-dialog.service';
|
||||
import { ConfirmationDialogInput, LoadingService } from '@iqser/common-ui';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
|
||||
@ -5,13 +5,13 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { downloadTypesTranslations } from '../../../../translations/download-types-translations';
|
||||
import { BaseDialogComponent, IconButtonTypes, LoadingService, SaveOptions } from '@iqser/common-ui';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { ReportTemplateService } from '@services/report-template.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DOSSIER_TEMPLATE_ID } from '@utils/constants';
|
||||
import dayjs from 'dayjs';
|
||||
import { Router } from '@angular/router';
|
||||
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from '../../shared/services/dossiers-dialog.service';
|
||||
|
||||
interface DialogData {
|
||||
readonly dossierTemplateId?: string;
|
||||
|
||||
@ -2,14 +2,14 @@ import { ChangeDetectionStrategy, Component, Input, OnInit } from '@angular/core
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Dossier, IDossierRequest, IDossierTemplate } from '@red/domain';
|
||||
import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface';
|
||||
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from '../../../shared/services/dossiers-dialog.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { EditDossierDialogComponent } from '../edit-dossier-dialog.component';
|
||||
import { ConfirmationDialogInput, ConfirmOptions, IconButtonTypes, LoadingService, TitleColors, Toaster } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DOSSIER_TEMPLATE_ID } from '@utils/constants';
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, HostBinding, Input, OnChanges, Optional, ViewChild } from '@angular/core';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { Action, ActionTypes, Dossier, File } from '@red/domain';
|
||||
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
|
||||
import {
|
||||
CircleButtonType,
|
||||
CircleButtonTypes,
|
||||
@ -24,7 +24,6 @@ import { ExcludedPagesService } from '../../../../file-preview/services/excluded
|
||||
import { DocumentInfoService } from '../../../../file-preview/services/document-info.service';
|
||||
import { ExpandableFileActionsComponent } from '@shared/components/expandable-file-actions/expandable-file-actions.component';
|
||||
import { firstValueFrom, Observable } from 'rxjs';
|
||||
import { RedactionImportService } from '../../services/redaction-import.service';
|
||||
import { PageRotationService } from '../../../../file-preview/services/page-rotation.service';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { AddDossierDialogComponent } from '../dialogs/add-dossier-dialog/add-dossier-dialog.component';
|
||||
import { EditDossierDialogComponent } from '../dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
|
||||
import { AssignReviewerApproverDialogComponent } from '../dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
|
||||
import { AddDossierDialogComponent } from '../../dialogs/add-dossier-dialog/add-dossier-dialog.component';
|
||||
import { EditDossierDialogComponent } from '../../dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
|
||||
import { AssignReviewerApproverDialogComponent } from '../../dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
|
||||
import { ConfirmationDialogComponent, DialogConfig, DialogService, largeDialogConfig } from '@iqser/common-ui';
|
||||
import { ImportRedactionsDialogComponent } from '../../file-preview/dialogs/import-redactions-dialog/import-redactions-dialog';
|
||||
import { ImportRedactionsDialogComponent } from '../../../file-preview/dialogs/import-redactions-dialog/import-redactions-dialog';
|
||||
|
||||
type DialogType = 'confirm' | 'editDossier' | 'addDossier' | 'assignFile' | 'importRedactions';
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { Dossier, File } from '@red/domain';
|
||||
import { DossiersDialogService } from '../../services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from './dossiers-dialog.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { ConfirmationDialogInput, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
|
||||
@ -4,7 +4,7 @@ import { FileAssignService } from './services/file-assign.service';
|
||||
import { FileActionsComponent } from './components/file-actions/file-actions.component';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { RedactionImportService } from './services/redaction-import.service';
|
||||
import { DossiersDialogService } from '../services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from './services/dossiers-dialog.service';
|
||||
import { EditDossierDialogComponent } from '../dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
|
||||
import { AddDossierDialogComponent } from '../dialogs/add-dossier-dialog/add-dossier-dialog.component';
|
||||
import { AssignReviewerApproverDialogComponent } from '../dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
|
||||
|
||||
@ -3,7 +3,7 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { CircleButtonTypes, List, ScrollableParentView, ScrollableParentViews, StatusBarConfig } from '@iqser/common-ui';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { Dossier, DossierStats, File } from '@red/domain';
|
||||
import { DossiersDialogService } from '../../../dossier/services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from '../../../dossier/shared/services/dossiers-dialog.service';
|
||||
import { LongPressEvent } from '@shared/directives/long-press.directive';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
|
||||
@ -1,25 +1,24 @@
|
||||
<div>
|
||||
<div *ngIf="stats$ | async as stats">
|
||||
<redaction-simple-doughnut-chart
|
||||
*ngIf="dossiersChartData$ | async as config"
|
||||
[config]="config"
|
||||
[config]="dossiersChartData$ | async"
|
||||
[radius]="80"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-listing.stats.charts.dossiers' | translate: { count: activeDossiersService.all.length }"
|
||||
[subtitle]="'dossier-template-charts.active-dossiers' | translate: { count: stats.numberOfActiveDossiers }"
|
||||
></redaction-simple-doughnut-chart>
|
||||
|
||||
<div *ngIf="activeDossiersService.generalStats$ | async as stats" class="dossier-stats-container">
|
||||
<div class="dossier-stats-container">
|
||||
<div class="dossier-stats-item">
|
||||
<mat-icon svgIcon="red:needs-work"></mat-icon>
|
||||
<div>
|
||||
<div class="heading">{{ stats.totalAnalyzedPages | number }}</div>
|
||||
<div [translateParams]="{ count: stats.totalAnalyzedPages }" [translate]="'dossier-listing.stats.analyzed-pages'"></div>
|
||||
<div class="heading">{{ stats.numberOfPages | number }}</div>
|
||||
<div [translateParams]="{ count: stats.numberOfPages }" [translate]="'dossier-listing.stats.analyzed-pages'"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dossier-stats-item">
|
||||
<mat-icon svgIcon="red:user"></mat-icon>
|
||||
<div>
|
||||
<div class="heading">{{ stats.totalPeople }}</div>
|
||||
<div class="heading">{{ stats.numberOfPeople }}</div>
|
||||
<div translate="dossier-listing.stats.total-people"></div>
|
||||
</div>
|
||||
</div>
|
||||
@ -28,10 +27,9 @@
|
||||
|
||||
<div class="right-chart">
|
||||
<redaction-simple-doughnut-chart
|
||||
*ngIf="documentsChartData$ | async as config"
|
||||
[config]="config"
|
||||
[config]="documentsChartData$ | async"
|
||||
[radius]="80"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-listing.stats.charts.total-documents' | translate"
|
||||
[subtitle]="'dossier-template-charts.total-documents' | translate"
|
||||
></redaction-simple-doughnut-chart>
|
||||
</div>
|
||||
|
||||
@ -1,15 +1,12 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { FilterService, mapEach } from '@iqser/common-ui';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { DossierStats, FileCountPerWorkflowStatus, StatusSorter } from '@red/domain';
|
||||
import { workflowFileStatusTranslations } from '../../../../translations/file-status-translations';
|
||||
import { Observable } from 'rxjs';
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
import { filter, map, switchMap } from 'rxjs/operators';
|
||||
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { DOSSIER_TEMPLATE_ID } from '@utils/constants';
|
||||
import { DashboardStats } from '@red/domain';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossiers-listing-details',
|
||||
@ -18,59 +15,20 @@ import { DossierStatesMapService } from '@services/entity-services/dossier-state
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossiersListingDetailsComponent {
|
||||
readonly stats$: Observable<DashboardStats>;
|
||||
readonly documentsChartData$: Observable<DoughnutChartConfig[]>;
|
||||
readonly dossiersChartData$: Observable<DoughnutChartConfig[]>;
|
||||
|
||||
constructor(
|
||||
readonly filterService: FilterService,
|
||||
readonly activeDossiersService: ActiveDossiersService,
|
||||
private readonly _dossierStatsMap: DossierStatsService,
|
||||
private readonly _dashboardStatsService: DashboardStatsService,
|
||||
private readonly _translateChartService: TranslateChartService,
|
||||
private readonly _dossierStatesMapService: DossierStatesMapService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _route: ActivatedRoute,
|
||||
) {
|
||||
this.documentsChartData$ = this.activeDossiersService.all$.pipe(
|
||||
mapEach(dossier => _dossierStatsMap.watch$(dossier.dossierId)),
|
||||
switchMap(stats$ => combineLatest(stats$)),
|
||||
filter(stats => !stats.some(s => s === undefined)),
|
||||
map(stats => this._toChartData(stats)),
|
||||
const dossierTemplateId: string = this._route.snapshot.paramMap.get(DOSSIER_TEMPLATE_ID);
|
||||
this.stats$ = this._dashboardStatsService.getEntityChanged$(dossierTemplateId);
|
||||
this.dossiersChartData$ = this.stats$.pipe(
|
||||
map(s => this._translateChartService.translateDossierStates(s.dossiersChartData, dossierTemplateId)),
|
||||
);
|
||||
|
||||
this.dossiersChartData$ = this.activeDossiersService.all$.pipe(map(() => this._toDossierChartData()));
|
||||
}
|
||||
|
||||
private _toDossierChartData(): DoughnutChartConfig[] {
|
||||
const configArray: DoughnutChartConfig[] = this._dossierStatesMapService.stats;
|
||||
const undefinedStateLength =
|
||||
this.activeDossiersService.all.length - configArray.map(v => v.value).reduce((acc, val) => acc + val, 0);
|
||||
configArray.push({
|
||||
value: undefinedStateLength,
|
||||
label: this._translateService.instant('edit-dossier-dialog.general-info.form.dossier-state.placeholder'),
|
||||
color: '#E2E4E9',
|
||||
});
|
||||
|
||||
return configArray;
|
||||
}
|
||||
|
||||
private _toChartData(stats: DossierStats[]) {
|
||||
const chartData: FileCountPerWorkflowStatus = {};
|
||||
stats.forEach(stat => {
|
||||
const statuses: FileCountPerWorkflowStatus = stat.fileCountPerWorkflowStatus;
|
||||
Object.keys(statuses).forEach(status => {
|
||||
chartData[status] = chartData[status] ? (chartData[status] as number) + (statuses[status] as number) : statuses[status];
|
||||
});
|
||||
});
|
||||
|
||||
const documentsChartData = Object.keys(chartData).map(
|
||||
status =>
|
||||
({
|
||||
value: chartData[status],
|
||||
color: status,
|
||||
label: workflowFileStatusTranslations[status],
|
||||
key: status,
|
||||
} as DoughnutChartConfig),
|
||||
);
|
||||
documentsChartData.sort((a, b) => StatusSorter.byStatus(a.key, b.key));
|
||||
return this._translateChartService.translateStatus(documentsChartData);
|
||||
this.documentsChartData$ = this.stats$.pipe(map(s => this._translateChartService.translateWorkflowStatus(s.documentsChartData)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@ import { dossierMemberChecker, dossierStateChecker, RedactionFilterSorter } from
|
||||
import { workloadTranslations } from '../dossier/translations/workload-translations';
|
||||
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
|
||||
import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service';
|
||||
import { DossiersDialogService } from '../dossier/services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from '../dossier/shared/services/dossiers-dialog.service';
|
||||
|
||||
@Injectable()
|
||||
export class ConfigService {
|
||||
|
||||
@ -6,9 +6,10 @@ import { DefaultListingServicesTmp, EntitiesService, ListingComponent, OnAttach,
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { ConfigService } from '../config.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { DossiersDialogService } from '../../dossier/services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from '../../dossier/shared/services/dossiers-dialog.service';
|
||||
import { Router } from '@angular/router';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossiers-listing-screen.component.html',
|
||||
@ -40,8 +41,10 @@ export class DossiersListingScreenComponent extends ListingComponent<Dossier> im
|
||||
private readonly _configService: ConfigService,
|
||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _router: Router,
|
||||
) {
|
||||
super(_injector);
|
||||
this._router.routeReuseStrategy.shouldReuseRoute = () => false;
|
||||
}
|
||||
|
||||
get defaultDossierTemplateId(): string {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { DocumentInfoService } from '../../services/document-info.service';
|
||||
import { combineLatest, Observable, switchMap } from 'rxjs';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
|
||||
@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { BehaviorSubject, merge, Observable } from 'rxjs';
|
||||
import { shareLast } from '@iqser/common-ui';
|
||||
import { filter, map, startWith, tap, withLatestFrom } from 'rxjs/operators';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { File, IFileAttributeConfig } from '@red/domain';
|
||||
|
||||
@ -6,7 +6,7 @@ import { Dictionary, DICTIONARY_TYPE_KEY_MAP, DictionaryType, Dossier, DossierTe
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { EditorComponent } from '@shared/components/editor/editor.component';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration;
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { Dossier, DossierStats } from '@red/domain';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { List } from '@iqser/common-ui';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
|
||||
@ -47,6 +47,7 @@
|
||||
> div {
|
||||
border-radius: 4px;
|
||||
padding: 3px 8px;
|
||||
width: 100%;
|
||||
|
||||
&:not(:last-child) {
|
||||
margin-bottom: 8px;
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, Input, OnChanges, OnInit } from '@angular/core';
|
||||
import { Component, Input, OnChanges, OnInit, Optional } from '@angular/core';
|
||||
import { Color } from '@red/domain';
|
||||
import { FilterService, INestedFilter } from '@iqser/common-ui';
|
||||
import { Observable, of } from 'rxjs';
|
||||
@ -30,17 +30,20 @@ export class SimpleDoughnutChartComponent implements OnChanges, OnInit {
|
||||
filtersEnabled: boolean;
|
||||
|
||||
chartData: any[] = [];
|
||||
perimeter: number;
|
||||
cx = 0;
|
||||
cy = 0;
|
||||
size = 0;
|
||||
|
||||
filters$: Observable<INestedFilter[]>;
|
||||
|
||||
constructor(readonly filterService: FilterService) {
|
||||
this.filterService.filterGroups$.subscribe(() => {
|
||||
this.filtersEnabled = !!this.filterService.filterGroups.find(g => g.slug === this.filterKey);
|
||||
});
|
||||
constructor(@Optional() readonly filterService: FilterService) {
|
||||
if (filterService) {
|
||||
this.filterService.filterGroups$.subscribe(() => {
|
||||
this.filtersEnabled = !!this.filterService.filterGroups.find(g => g.slug === this.filterKey);
|
||||
});
|
||||
} else {
|
||||
this.filtersEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
get circumference(): number {
|
||||
@ -56,7 +59,7 @@ export class SimpleDoughnutChartComponent implements OnChanges, OnInit {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.filters$ = this.filterService.getFilterModels$(this.filterKey) ?? of([]);
|
||||
this.filters$ = (this.filtersEnabled && this.filterService.getFilterModels$(this.filterKey)) ?? of([]);
|
||||
}
|
||||
|
||||
ngOnChanges(): void {
|
||||
@ -67,7 +70,7 @@ export class SimpleDoughnutChartComponent implements OnChanges, OnInit {
|
||||
}
|
||||
|
||||
filterChecked$(key: string): Observable<boolean> {
|
||||
return this.filters$.pipe(map(all => all?.find(e => e.id === key)?.checked));
|
||||
return this.filtersEnabled ? this.filters$.pipe(map(all => all?.find(e => e.id === key)?.checked)) : of(false);
|
||||
}
|
||||
|
||||
calculateChartData() {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
|
||||
import { CircleButtonTypes, List } from '@iqser/common-ui';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { DossiersDialogService } from '../../../dossier/services/dossiers-dialog.service';
|
||||
import { DossiersDialogService } from '../../../dossier/shared/services/dossiers-dialog.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-team-members',
|
||||
|
||||
@ -10,7 +10,7 @@ import { DOSSIER_ID, DOSSIER_TEMPLATE_ID, DOSSIERS_ARCHIVE, FILE_ID } from '@uti
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
import { dossiersServiceResolver } from '@services/entity-services/dossiers.service.provider';
|
||||
import { FeaturesService } from '@services/features.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
|
||||
export type RouterLinkActiveOptions = { exact: boolean } | IsActiveMatchOptions;
|
||||
export type BreadcrumbDisplayType = 'text' | 'dropdown';
|
||||
|
||||
@ -0,0 +1,29 @@
|
||||
import { EntitiesService, mapEach } from '@iqser/common-ui';
|
||||
import { DashboardStats, IDashboardStats } from '@red/domain';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { NGXLogger } from 'ngx-logger';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map, switchMap, tap } from 'rxjs/operators';
|
||||
import { DossierStatesService } from '@services/entity-services/dossier-states.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class DashboardStatsService extends EntitiesService<DashboardStats, IDashboardStats> {
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _dossierStatesService: DossierStatesService,
|
||||
private readonly _logger: NGXLogger,
|
||||
) {
|
||||
super(_injector, DashboardStats, 'dossier-template/stats');
|
||||
}
|
||||
|
||||
loadAll(): Observable<DashboardStats[]> {
|
||||
return this.getAll(this._defaultModelPath).pipe(
|
||||
mapEach(entity => new DashboardStats(entity)),
|
||||
switchMap(entities => this._dossierStatesService.loadAllForAllTemplates().pipe(map(() => entities))),
|
||||
tap(entities => entities.sort((a, b) => (a.numberOfActiveDossiers > 0 && b.numberOfActiveDossiers === 0 ? -1 : 1))),
|
||||
tap(entities => this.setEntities(entities)),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -2,12 +2,12 @@ import { EntitiesService, List, mapEach, RequiredParam, Toaster, Validate } from
|
||||
import { DossierTemplate, IDossierTemplate } from '@red/domain';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { forkJoin, Observable, of } from 'rxjs';
|
||||
import { FileAttributesService } from './file-attributes.service';
|
||||
import { FileAttributesService } from '../entity-services/file-attributes.service';
|
||||
import { catchError, mapTo, switchMap, tap } from 'rxjs/operators';
|
||||
import { DossierTemplateStatsService } from '@services/entity-services/dossier-template-stats.service';
|
||||
import { DossierTemplateStatsService } from '../entity-services/dossier-template-stats.service';
|
||||
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DictionaryService } from '@services/entity-services/dictionary.service';
|
||||
import { DictionaryService } from '../entity-services/dictionary.service';
|
||||
|
||||
const DOSSIER_TEMPLATE_CONFLICT_MSG = _('dossier-templates-listing.error.conflict');
|
||||
const GENERIC_MSG = _('dossier-templates-listing.error.generic');
|
||||
@ -4,11 +4,6 @@ import { timer } from 'rxjs';
|
||||
import { CHANGED_CHECK_INTERVAL, DOSSIERS_ROUTE } from '@utils/constants';
|
||||
import { DossiersService } from './dossiers.service';
|
||||
|
||||
export interface IDossiersStats {
|
||||
totalPeople: number;
|
||||
totalAnalyzedPages: number;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
@ -23,8 +18,4 @@ export class ActiveDossiersService extends DossiersService {
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
getCountWithState(dossierStatusId: string): number {
|
||||
return this.all.filter(dossier => dossier.dossierStatusId === dossierStatusId).length;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,23 +1,21 @@
|
||||
import { EntitiesService, List, mapEach, QueryParam, RequiredParam, shareLast, Toaster, Validate } from '@iqser/common-ui';
|
||||
import { EntitiesService, List, mapEach, QueryParam, RequiredParam, Toaster, Validate } from '@iqser/common-ui';
|
||||
import { Dossier, DossierStats, IDossier, IDossierChanges, IDossierRequest } from '@red/domain';
|
||||
import { combineLatest, forkJoin, Observable, of, Subject, throwError } from 'rxjs';
|
||||
import { forkJoin, Observable, of, Subject, throwError } from 'rxjs';
|
||||
import { catchError, filter, map, switchMap, tap } from 'rxjs/operators';
|
||||
import { Injector } from '@angular/core';
|
||||
import { DossierStatesService } from '../entity-services/dossier-states.service';
|
||||
import { DossierStatsService } from './dossier-stats.service';
|
||||
import { IDossiersStats } from './active-dossiers.service';
|
||||
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { NGXLogger } from 'ngx-logger';
|
||||
import { DashboardStatsService } from '@services/dossier-templates/dashboard-stats.service';
|
||||
|
||||
const CONFLICT_MSG = _('add-dossier-dialog.errors.dossier-already-exists');
|
||||
const GENERIC_MSG = _('add-dossier-dialog.errors.generic');
|
||||
|
||||
export abstract class DossiersService extends EntitiesService<Dossier, IDossier> {
|
||||
readonly dossierFileChanges$ = new Subject<string>();
|
||||
readonly generalStats$ = this.all$.pipe(switchMap(entities => this.#generalStats$(entities)));
|
||||
protected readonly _dossierStatsService = this._injector.get(DossierStatsService);
|
||||
protected readonly _dossierStateService = this._injector.get(DossierStatesService);
|
||||
protected readonly _dashboardStatsService = this._injector.get(DashboardStatsService);
|
||||
protected readonly _toaster = this._injector.get(Toaster);
|
||||
protected readonly _logger = this._injector.get(NGXLogger);
|
||||
|
||||
@ -64,7 +62,7 @@ export abstract class DossiersService extends EntitiesService<Dossier, IDossier>
|
||||
mapEach(entity => new Dossier(entity)),
|
||||
/* Load stats before updating entities */
|
||||
switchMap(dossiers => this._dossierStatsService.getFor(dossierIds(dossiers)).pipe(map(() => dossiers))),
|
||||
switchMap(dossiers => this._dossierStateService.loadAllForAllTemplates().pipe(map(() => dossiers))),
|
||||
switchMap(dossiers => this._dashboardStatsService.loadAll().pipe(map(() => dossiers))),
|
||||
tap(dossiers => this.setEntities(dossiers)),
|
||||
);
|
||||
}
|
||||
@ -86,28 +84,4 @@ export abstract class DossiersService extends EntitiesService<Dossier, IDossier>
|
||||
switchMap(dossier => this._dossierStatsService.getFor([dossier.dossierId])),
|
||||
);
|
||||
}
|
||||
|
||||
#computeStats(entities: List<Dossier>): IDossiersStats {
|
||||
let totalAnalyzedPages = 0;
|
||||
const totalPeople = new Set<string>();
|
||||
|
||||
entities.forEach(dossier => {
|
||||
dossier.memberIds?.forEach(m => totalPeople.add(m));
|
||||
totalAnalyzedPages += this._dossierStatsService.get(dossier.dossierId).numberOfPages;
|
||||
});
|
||||
|
||||
return {
|
||||
totalPeople: totalPeople.size,
|
||||
totalAnalyzedPages,
|
||||
};
|
||||
}
|
||||
|
||||
#generalStats$(entities: List<Dossier>): Observable<IDossiersStats> {
|
||||
const stats$ = entities.map(entity => this._dossierStatsService.watch$(entity.dossierId));
|
||||
return combineLatest(stats$).pipe(
|
||||
filter(stats => stats.every(s => !!s)),
|
||||
map(() => this.#computeStats(entities)),
|
||||
shareLast(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { Injectable, Injector } from '@angular/core';
|
||||
import { EntitiesService, mapEach, RequiredParam, Toaster, Validate } from '@iqser/common-ui';
|
||||
import { DossierState, IDossierState } from '@red/domain';
|
||||
import { EMPTY, forkJoin, Observable, switchMap } from 'rxjs';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service';
|
||||
import { catchError, defaultIfEmpty, tap } from 'rxjs/operators';
|
||||
import { DossierStatesMapService } from '@services/entity-services/dossier-states-map.service';
|
||||
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
||||
|
||||
@ -12,11 +12,6 @@ import { flatMap } from 'lodash-es';
|
||||
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
|
||||
export interface IDossiersStats {
|
||||
totalPeople: number;
|
||||
totalAnalyzedPages: number;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
|
||||
@ -2,17 +2,34 @@ import { Injectable } from '@angular/core';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { rolesTranslations } from '../translations/roles-translations';
|
||||
import { workflowFileStatusTranslations } from '../translations/file-status-translations';
|
||||
import { DossierStatesMapService } from './entity-services/dossier-states-map.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class TranslateChartService {
|
||||
constructor(private readonly _translateService: TranslateService) {}
|
||||
constructor(private readonly _translateService: TranslateService, private readonly _dossierStatesMapService: DossierStatesMapService) {}
|
||||
|
||||
translateStatus(config: DoughnutChartConfig[]): DoughnutChartConfig[] {
|
||||
translateLabels(config: DoughnutChartConfig[]): DoughnutChartConfig[] {
|
||||
return config.map(val => ({ ...val, label: this._translateService.instant(val.label) }));
|
||||
}
|
||||
|
||||
translateDossierStates(config: DoughnutChartConfig[], dossierTemplateId: string): DoughnutChartConfig[] {
|
||||
return config.map(val => {
|
||||
if (!val.key) {
|
||||
return { ...val, label: this._translateService.instant(val.label) };
|
||||
} else {
|
||||
const dossierState = this._dossierStatesMapService.get(dossierTemplateId, val.key);
|
||||
return { ...val, key: null, label: dossierState.name, color: dossierState.color };
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
translateWorkflowStatus(config: DoughnutChartConfig[]): DoughnutChartConfig[] {
|
||||
return config.map(val => ({ ...val, label: this._translateService.instant(workflowFileStatusTranslations[val.label] as string) }));
|
||||
}
|
||||
|
||||
translateRoles(config: DoughnutChartConfig[]): DoughnutChartConfig[] {
|
||||
return config.map(val => ({
|
||||
...val,
|
||||
|
||||
@ -775,10 +775,6 @@
|
||||
},
|
||||
"stats": {
|
||||
"analyzed-pages": "Seiten",
|
||||
"charts": {
|
||||
"dossiers": "Dossiers",
|
||||
"total-documents": "Anzahl der Dokumente"
|
||||
},
|
||||
"total-people": "Anzahl der Benutzer"
|
||||
},
|
||||
"table-col-names": {
|
||||
@ -793,6 +789,10 @@
|
||||
"title": "{length} {length, plural, one{aktives Dossier} other{aktive Dossiers}}"
|
||||
}
|
||||
},
|
||||
"dossier-template-charts": {
|
||||
"active-dossiers": "Aktive Dossiers",
|
||||
"total-documents": "Anzahl der Dokumente"
|
||||
},
|
||||
"dossier-overview": {
|
||||
"approve": "Genehmigen",
|
||||
"approve-disabled": "Das Dokument kann erst genehmigt werden, wenn eine Analyse auf Basis der aktuellen Wörterbücher durchgeführt wurde und die Vorschläge bearbeitet wurden.",
|
||||
|
||||
@ -775,10 +775,6 @@
|
||||
},
|
||||
"stats": {
|
||||
"analyzed-pages": "{count, plural, one{Page} other{Pages}}",
|
||||
"charts": {
|
||||
"dossiers": "{count, plural, one{Dossier} other{Dossiers}}",
|
||||
"total-documents": "Total Documents"
|
||||
},
|
||||
"total-people": "Total users"
|
||||
},
|
||||
"table-col-names": {
|
||||
@ -793,6 +789,10 @@
|
||||
"title": "{length} active {length, plural, one{Dossier} other{Dossiers}}"
|
||||
}
|
||||
},
|
||||
"dossier-template-charts": {
|
||||
"active-dossiers": "Active {count, plural, one{Dossier} other{Dossiers}}",
|
||||
"total-documents": "Total Documents"
|
||||
},
|
||||
"dossier-overview": {
|
||||
"approve": "Approve",
|
||||
"approve-disabled": "File can only be approved once it has been analysed with the latest dictionaries and all suggestions have been processed.",
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit f06c007bec1a7da5c257e68d6df8c806419ceb2b
|
||||
Subproject commit 5444b09e647672383a0b39d23400a98d7efb6536
|
||||
@ -0,0 +1,89 @@
|
||||
import { IDashboardStats, ProcessingFileStatus, StatusSorter, WorkflowFileStatus } from '@red/domain';
|
||||
import { IListable } from '@iqser/common-ui';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
|
||||
export class DashboardStats implements IListable, IDashboardStats {
|
||||
readonly dossierCountByStatus: [
|
||||
{
|
||||
count: number;
|
||||
statusId: string;
|
||||
},
|
||||
];
|
||||
readonly dossierTemplateId: string;
|
||||
readonly dossiersInTemplate: [string];
|
||||
readonly fileCountPerProcessingStatus: [
|
||||
{
|
||||
readonly count: number;
|
||||
readonly processingStatus: ProcessingFileStatus;
|
||||
},
|
||||
];
|
||||
readonly fileCountPerWorkflowStatus: [
|
||||
{
|
||||
readonly count: number;
|
||||
readonly workflowStatus: WorkflowFileStatus;
|
||||
},
|
||||
];
|
||||
readonly name: string;
|
||||
readonly numberOfActiveDossiers: number;
|
||||
readonly numberOfActiveFiles: number;
|
||||
readonly numberOfArchivedDossiers: number;
|
||||
readonly numberOfDeletedDossiers: number;
|
||||
readonly numberOfExcludedPages: number;
|
||||
readonly numberOfPages: number;
|
||||
readonly numberOfPeople: number;
|
||||
readonly numberOfSoftDeletedFiles: number;
|
||||
readonly dossiersChartData: DoughnutChartConfig[];
|
||||
readonly documentsChartData: DoughnutChartConfig[];
|
||||
|
||||
constructor(stats: IDashboardStats) {
|
||||
this.dossierCountByStatus = stats.dossierCountByStatus;
|
||||
this.dossierTemplateId = stats.dossierTemplateId;
|
||||
this.dossiersInTemplate = stats.dossiersInTemplate;
|
||||
this.fileCountPerProcessingStatus = stats.fileCountPerProcessingStatus;
|
||||
this.fileCountPerWorkflowStatus = stats.fileCountPerWorkflowStatus;
|
||||
this.name = stats.name;
|
||||
this.numberOfActiveDossiers = stats.numberOfActiveDossiers;
|
||||
this.numberOfActiveFiles = stats.numberOfActiveFiles;
|
||||
this.numberOfArchivedDossiers = stats.numberOfArchivedDossiers;
|
||||
this.numberOfDeletedDossiers = stats.numberOfDeletedDossiers;
|
||||
this.numberOfExcludedPages = stats.numberOfExcludedPages;
|
||||
this.numberOfPages = stats.numberOfPages;
|
||||
this.numberOfPeople = stats.numberOfPeople;
|
||||
this.numberOfSoftDeletedFiles = stats.numberOfSoftDeletedFiles;
|
||||
|
||||
this.dossiersChartData = this._dossiersChartData;
|
||||
this.documentsChartData = this._documentsChartData;
|
||||
}
|
||||
|
||||
get isEmpty(): boolean {
|
||||
return this.numberOfActiveDossiers === 0;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
return this.dossierTemplateId;
|
||||
}
|
||||
|
||||
get searchKey(): string {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
private get _dossiersChartData(): DoughnutChartConfig[] {
|
||||
return this.dossierCountByStatus.map(d => ({
|
||||
value: d.count,
|
||||
color: '#e2e4e9',
|
||||
label: 'edit-dossier-dialog.general-info.form.dossier-state.placeholder',
|
||||
key: d.statusId,
|
||||
}));
|
||||
}
|
||||
|
||||
private get _documentsChartData(): DoughnutChartConfig[] {
|
||||
const configArray: DoughnutChartConfig[] = this.fileCountPerWorkflowStatus.map(d => ({
|
||||
value: d.count,
|
||||
color: d.workflowStatus,
|
||||
label: d.workflowStatus,
|
||||
key: d.workflowStatus,
|
||||
}));
|
||||
configArray.sort((a: DoughnutChartConfig, b) => StatusSorter.byStatus(a.label, b.label));
|
||||
return configArray;
|
||||
}
|
||||
}
|
||||
33
libs/red-domain/src/lib/dossier-templates/dashboard-stats.ts
Normal file
33
libs/red-domain/src/lib/dossier-templates/dashboard-stats.ts
Normal file
@ -0,0 +1,33 @@
|
||||
import { ProcessingFileStatus, WorkflowFileStatus } from '@red/domain';
|
||||
|
||||
export interface IDashboardStats {
|
||||
readonly dossierCountByStatus: [
|
||||
{
|
||||
count: number;
|
||||
statusId: string;
|
||||
},
|
||||
];
|
||||
readonly dossierTemplateId: string;
|
||||
readonly dossiersInTemplate: [string];
|
||||
readonly fileCountPerProcessingStatus: [
|
||||
{
|
||||
readonly count: number;
|
||||
readonly processingStatus: ProcessingFileStatus;
|
||||
},
|
||||
];
|
||||
readonly fileCountPerWorkflowStatus: [
|
||||
{
|
||||
readonly count: number;
|
||||
readonly workflowStatus: WorkflowFileStatus;
|
||||
},
|
||||
];
|
||||
readonly name: string;
|
||||
readonly numberOfActiveDossiers: number;
|
||||
readonly numberOfActiveFiles: number;
|
||||
readonly numberOfArchivedDossiers: number;
|
||||
readonly numberOfDeletedDossiers: number;
|
||||
readonly numberOfExcludedPages: number;
|
||||
readonly numberOfPages: number;
|
||||
readonly numberOfPeople: number;
|
||||
readonly numberOfSoftDeletedFiles: number;
|
||||
}
|
||||
@ -2,4 +2,6 @@ export * from './dossier-template';
|
||||
export * from './dossier-template.model';
|
||||
export * from './dossier-template-stats';
|
||||
export * from './dossier-template-stats.model';
|
||||
export * from './dashboard-stats';
|
||||
export * from './dashboard-stats.model';
|
||||
export * from './types';
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user