move chart computations to dossier listing details component
This commit is contained in:
parent
9bd98a0c46
commit
9ba4120aa0
@ -41,7 +41,7 @@
|
||||
<ng-container *ngIf="dossier.stats$ | async as stats">
|
||||
<div *ngIf="stats.hasFiles" class="mt-24">
|
||||
<redaction-simple-doughnut-chart
|
||||
[config]="calculateChartConfig(dossier)"
|
||||
[config]="calculateChartConfig(stats.fileCountPerWorkflowStatus)"
|
||||
[radius]="63"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-overview.dossier-details.charts.documents-in-dossier' | translate"
|
||||
|
||||
@ -1,13 +1,12 @@
|
||||
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { groupBy } from '@utils/index';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { FilterService, Toaster } from '@iqser/common-ui';
|
||||
import { fileStatusTranslations } from '../../../../translations/file-status-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { Dossier, DossierAttributeWithValue, IDossierRequest, StatusSorter, User } from '@red/domain';
|
||||
import { Dossier, DossierAttributeWithValue, FileCountPerWorkflowStatus, IDossierRequest, StatusSorter, User } from '@red/domain';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
@ -44,20 +43,15 @@ export class DossierDetailsComponent {
|
||||
) {
|
||||
this.dossierId = activatedRoute.snapshot.paramMap.get('dossierId');
|
||||
this.dossier$ = this.dossiersService.getEntityChanged$(this.dossierId);
|
||||
// this.documentsChartData$ = this.dossier$.pipe(
|
||||
// switchMap(dossier => dossier.stats$),
|
||||
// map(stats => this._calculateChartConfig(stats.fileCountPerWorkflowStatus)),
|
||||
// );
|
||||
}
|
||||
|
||||
get managers() {
|
||||
return this._userService.managerUsers;
|
||||
return this._userService.managerUsers.map(manager => manager.id);
|
||||
}
|
||||
|
||||
calculateChartConfig(dossier: Dossier): DoughnutChartConfig[] {
|
||||
const groups = groupBy(dossier?.files, 'status');
|
||||
const documentsChartData: DoughnutChartConfig[] = Object.keys(groups).map(status => ({
|
||||
value: groups[status].length,
|
||||
calculateChartConfig(filesCount: FileCountPerWorkflowStatus): DoughnutChartConfig[] {
|
||||
const documentsChartData: DoughnutChartConfig[] = Object.keys(filesCount).map(status => ({
|
||||
value: filesCount[status],
|
||||
color: status,
|
||||
label: fileStatusTranslations[status],
|
||||
key: status,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
<div>
|
||||
<redaction-simple-doughnut-chart
|
||||
[config]="dossiersChartData"
|
||||
*ngIf="dossiersChartData$ | async as config"
|
||||
[config]="config"
|
||||
[radius]="80"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-listing.stats.charts.dossiers' | translate"
|
||||
@ -24,9 +25,11 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<redaction-simple-doughnut-chart
|
||||
[config]="documentsChartData"
|
||||
*ngIf="documentsChartData$ | async as config"
|
||||
[config]="config"
|
||||
[radius]="80"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-listing.stats.charts.total-documents' | translate"
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { FilterService, mapEach } from '@iqser/common-ui';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { Dossier, DossierStats, DossierStatuses, FileCountPerWorkflowStatus, StatusSorter } from '@red/domain';
|
||||
import { fileStatusTranslations } 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';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossiers-listing-details',
|
||||
@ -10,8 +16,53 @@ import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossiersListingDetailsComponent {
|
||||
@Input() dossiersChartData: DoughnutChartConfig[];
|
||||
@Input() documentsChartData: DoughnutChartConfig[];
|
||||
readonly documentsChartData$: Observable<DoughnutChartConfig[]>;
|
||||
readonly dossiersChartData$: Observable<DoughnutChartConfig[]>;
|
||||
|
||||
constructor(readonly filterService: FilterService, readonly dossiersService: DossiersService) {}
|
||||
constructor(
|
||||
readonly filterService: FilterService,
|
||||
readonly dossiersService: DossiersService,
|
||||
private readonly _translateChartService: TranslateChartService,
|
||||
) {
|
||||
this.documentsChartData$ = this.dossiersService.all$.pipe(
|
||||
mapEach(dossier => dossier.stats$),
|
||||
switchMap(stats$ => combineLatest(stats$)),
|
||||
filter(stats => !stats.some(s => s === undefined)),
|
||||
map(stats => this._toChartData(stats)),
|
||||
);
|
||||
|
||||
this.dossiersChartData$ = this.dossiersService.all$.pipe(map(dossiers => this._toDossierChartData(dossiers)));
|
||||
}
|
||||
|
||||
private _toDossierChartData(dossiers: Dossier[]): DoughnutChartConfig[] {
|
||||
const activeDossiersCount = dossiers.filter(p => p.status === DossierStatuses.ACTIVE).length;
|
||||
const inactiveDossiersCount = (dossiers.length = activeDossiersCount);
|
||||
|
||||
return [
|
||||
{ value: activeDossiersCount, color: 'ACTIVE', label: _('active') },
|
||||
{ value: inactiveDossiersCount, color: 'DELETED', label: _('archived') },
|
||||
];
|
||||
}
|
||||
|
||||
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: fileStatusTranslations[status],
|
||||
key: status,
|
||||
} as DoughnutChartConfig),
|
||||
);
|
||||
documentsChartData.sort((a, b) => StatusSorter.byStatus(a.key, b.key));
|
||||
return this._translateChartService.translateStatus(documentsChartData);
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,11 +18,7 @@
|
||||
</div>
|
||||
|
||||
<div class="right-container" iqserHasScrollbar>
|
||||
<redaction-dossiers-listing-details
|
||||
*ngIf="(entitiesService.noData$ | async) === false"
|
||||
[documentsChartData]="documentsChartData"
|
||||
[dossiersChartData]="dossiersChartData"
|
||||
></redaction-dossiers-listing-details>
|
||||
<redaction-dossiers-listing-details *ngIf="(entitiesService.noData$ | async) === false"></redaction-dossiers-listing-details>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@ -32,5 +28,5 @@
|
||||
</ng-template>
|
||||
|
||||
<ng-template #tableItemTemplate let-dossier="entity">
|
||||
<redaction-table-item (calculateData)="calculateData()" [dossier]="dossier"></redaction-table-item>
|
||||
<redaction-table-item (calculateData)="computeAllFilters()" [dossier]="dossier"></redaction-table-item>
|
||||
</ng-template>
|
||||
|
||||
@ -10,18 +10,15 @@ import {
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { Dossier, DossierStatuses, StatusSorter } from '@red/domain';
|
||||
import { Dossier } from '@red/domain';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { timer } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { Router } from '@angular/router';
|
||||
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
|
||||
import { groupBy } from '@utils/index';
|
||||
import { DefaultListingServicesTmp, EntitiesService, ListingComponent, OnAttach, OnDetach, TableComponent } from '@iqser/common-ui';
|
||||
import { fileStatusTranslations } from '../../../translations/file-status-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { ConfigService } from '../config.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
@ -44,8 +41,6 @@ export class DossiersListingScreenComponent
|
||||
readonly tableColumnConfigs = this._configService.tableConfig;
|
||||
readonly tableHeaderLabel = _('dossier-listing.table-header.title');
|
||||
readonly buttonConfigs = this._configService.buttonsConfig(() => this.openAddDossierDialog());
|
||||
dossiersChartData: DoughnutChartConfig[] = [];
|
||||
documentsChartData: DoughnutChartConfig[] = [];
|
||||
private _lastScrolledIndex: number;
|
||||
@ViewChild('needsWorkFilterTemplate', {
|
||||
read: TemplateRef,
|
||||
@ -66,23 +61,14 @@ export class DossiersListingScreenComponent
|
||||
private readonly _configService: ConfigService,
|
||||
) {
|
||||
super(_injector);
|
||||
this._appStateService.reset();
|
||||
}
|
||||
|
||||
private get _activeDossiersCount(): number {
|
||||
return this.entitiesService.all.filter(p => p.status === DossierStatuses.ACTIVE).length;
|
||||
}
|
||||
|
||||
private get _inactiveDossiersCount(): number {
|
||||
return this.entitiesService.all.length - this._activeDossiersCount;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.calculateData();
|
||||
this.computeAllFilters();
|
||||
|
||||
this.addSubscription = timer(0, 20000).subscribe(async () => {
|
||||
await this._appStateService.loadAllDossiers();
|
||||
this.calculateData();
|
||||
this.computeAllFilters();
|
||||
});
|
||||
}
|
||||
|
||||
@ -115,29 +101,7 @@ export class DossiersListingScreenComponent
|
||||
});
|
||||
}
|
||||
|
||||
calculateData(): void {
|
||||
this._computeAllFilters();
|
||||
|
||||
this.dossiersChartData = [
|
||||
{ value: this._activeDossiersCount, color: 'ACTIVE', label: _('active') },
|
||||
{ value: this._inactiveDossiersCount, color: 'DELETED', label: _('archived') },
|
||||
];
|
||||
const groups = groupBy(this._dossiersService.allFiles, 'status');
|
||||
this.documentsChartData = [];
|
||||
|
||||
for (const status of Object.keys(groups)) {
|
||||
this.documentsChartData.push({
|
||||
value: groups[status].length,
|
||||
color: status,
|
||||
label: fileStatusTranslations[status],
|
||||
key: status,
|
||||
});
|
||||
}
|
||||
this.documentsChartData.sort((a, b) => StatusSorter.byStatus(a.key, b.key));
|
||||
this.documentsChartData = this._translateChartService.translateStatus(this.documentsChartData);
|
||||
}
|
||||
|
||||
private _computeAllFilters() {
|
||||
computeAllFilters() {
|
||||
const filterGroups = this._configService.filterGroups(this.entitiesService.all, this._needsWorkFilterTemplate);
|
||||
this.filterService.addFilterGroups(filterGroups);
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ export class DossiersService extends EntitiesService<Dossier, IDossier> {
|
||||
const stats$ = dossier$.pipe(switchMap(updatedDossier => this._dossierStatsService.getFor([updatedDossier.dossierId])));
|
||||
|
||||
return combineLatest([dossier$, stats$]).pipe(
|
||||
map(([updatedDossier, stats]) => new Dossier(updatedDossier, stats[0], this.find(updatedDossier.dossierId)?.files ?? [])),
|
||||
map(([updatedDossier, stats]) => new Dossier(updatedDossier, stats[0], [])),
|
||||
tap(newDossier => this.replace(newDossier)),
|
||||
catchError(showToast),
|
||||
);
|
||||
|
||||
@ -120,7 +120,7 @@ export class AppStateService {
|
||||
return data ? data : this._dictionaryData[dossierTemplateId]['default'];
|
||||
}
|
||||
|
||||
async loadAllDossiers(emitEvents = true) {
|
||||
async loadAllDossiers() {
|
||||
const dossiers = await this._dossiersService.get().toPromise();
|
||||
if (!dossiers) {
|
||||
return;
|
||||
@ -133,17 +133,9 @@ export class AppStateService {
|
||||
const oldDossier = this._dossiersService.find(p.dossierId);
|
||||
const type = oldDossier?.type ?? (await this._getDictionaryFor(p));
|
||||
const stats = dossierStats.find(s => s.dossierId === p.dossierId);
|
||||
return new Dossier(p, stats, oldDossier?.files ?? [], type);
|
||||
this._dossiersService.replace(new Dossier(p, stats, [], type));
|
||||
});
|
||||
const mappedDossiers = await Promise.all(mappedDossiers$);
|
||||
const fileData = await this._filesService.getFor(mappedDossiers.map(p => p.id)).toPromise();
|
||||
|
||||
for (const dossierId of Object.keys(fileData)) {
|
||||
const dossier = mappedDossiers.find(p => p.id === dossierId);
|
||||
if (dossier) {
|
||||
this._processFiles(dossier, fileData[dossierId], emitEvents);
|
||||
}
|
||||
}
|
||||
return Promise.all(mappedDossiers$);
|
||||
}
|
||||
|
||||
async reloadActiveFile() {
|
||||
@ -160,10 +152,6 @@ export class AppStateService {
|
||||
this._userService.getNameForId(iFile.currentReviewer),
|
||||
this._fileAttributesService.getFileAttributeConfig(activeDossier.dossierTemplateId),
|
||||
);
|
||||
const files = activeDossier.files.filter(file => file.fileId !== activeFile.fileId);
|
||||
files.push(activeFile);
|
||||
const newDossier = new Dossier(activeDossier, activeDossier.stats, files, activeDossier.type);
|
||||
this._dossiersService.replace(newDossier);
|
||||
|
||||
if (activeFile.lastProcessed !== oldProcessedDate) {
|
||||
this.fileReanalysed$.next(activeFile);
|
||||
@ -514,9 +502,6 @@ export class AppStateService {
|
||||
}
|
||||
}
|
||||
|
||||
const newDossier = new Dossier(dossier, dossier.stats, newFiles, dossier.type);
|
||||
this._dossiersService.replace(newDossier);
|
||||
|
||||
return newFiles;
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,10 +68,6 @@ export class Dossier implements IDossier, IListable {
|
||||
return this._stats$.getValue();
|
||||
}
|
||||
|
||||
hasStatus(status: string): boolean {
|
||||
return !!this.files.find(f => f.status === status);
|
||||
}
|
||||
|
||||
hasMember(memberId: string): boolean {
|
||||
return !!this.memberIds && this.memberIds.indexOf(memberId) >= 0;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user