dossier wrapper refactor

This commit is contained in:
Dan Percic 2021-08-10 23:01:17 +03:00
parent fbc32d7e23
commit 9e7edc6b69
24 changed files with 146 additions and 190 deletions

View File

@ -12,7 +12,7 @@
[routerLink]="'/main/dossiers/' + appStateService.activeDossierId"
mat-menu-item
>
{{ appStateService.activeDossier.dossier.dossierName }}
{{ appStateService.activeDossier.dossierName }}
</button>
<button
*ngIf="appStateService.activeFile"
@ -44,7 +44,7 @@
class="breadcrumb"
routerLinkActive="active"
>
{{ appStateService.activeDossier.dossier.dossierName }}
{{ appStateService.activeDossier.dossierName }}
</a>
<mat-icon *ngIf="appStateService.activeFile" svgIcon="red:arrow-right"></mat-icon>
<a

View File

@ -26,7 +26,7 @@
<div class="section small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:folder"></mat-icon>
<span>{{ 'file-preview.tabs.document-info.details.dossier' | translate: { dossierName: dossier.name } }}</span>
<span>{{ 'file-preview.tabs.document-info.details.dossier' | translate: { dossierName: dossier.dossierName } }}</span>
</div>
<div>
<mat-icon svgIcon="red:document"></mat-icon>
@ -36,11 +36,9 @@
<mat-icon svgIcon="red:calendar"></mat-icon>
<span>{{ 'file-preview.tabs.document-info.details.created-on' | translate: { date: file.added | date: 'mediumDate' } }}</span>
</div>
<div *ngIf="dossier.dossier.dueDate">
<div *ngIf="dossier.dueDate">
<mat-icon svgIcon="red:lightning"></mat-icon>
<span>{{
'file-preview.tabs.document-info.details.due' | translate: { date: dossier.dossier.dueDate | date: 'mediumDate' }
}}</span>
<span>{{ 'file-preview.tabs.document-info.details.due' | translate: { date: dossier.dueDate | date: 'mediumDate' } }}</span>
</div>
<div>
<mat-icon svgIcon="red:template"></mat-icon>

View File

@ -19,18 +19,18 @@
'dossier-overview.dossier-details.stats.created-on'
| translate
: {
date: activeDossier.dossier.date | date: 'd MMM. yyyy'
date: activeDossier.date | date: 'd MMM. yyyy'
}
}}
</span>
</div>
<div *ngIf="activeDossier.dossier.dueDate">
<div *ngIf="activeDossier.dueDate">
<mat-icon svgIcon="red:lightning"></mat-icon>
<span>{{
'dossier-overview.dossier-details.stats.due-date'
| translate
: {
date: activeDossier.dossier.dueDate | date: 'd MMM. yyyy'
date: activeDossier.dueDate | date: 'd MMM. yyyy'
}
}}</span>
</div>

View File

@ -5,7 +5,7 @@
</div>
<div class="header-wrapper mt-8">
<div class="heading-xl flex-1">{{ appStateService.activeDossier.dossier.dossierName }}</div>
<div class="heading-xl flex-1">{{ appStateService.activeDossier.dossierName }}</div>
<ng-container
*ngTemplateOutlet="collapsible; context: { action: 'collapse', tooltip: (collapseTooltip | translate) }"
></ng-container>
@ -65,7 +65,7 @@
></redaction-dossier-details-stats>
</div>
<div *ngIf="appStateService.activeDossier.dossier.description as description" class="pb-32">
<div *ngIf="appStateService.activeDossier.description as description" class="pb-32">
<div class="heading" translate="dossier-overview.dossier-details.description"></div>
<div class="mt-8">{{ description }}</div>
</div>

View File

@ -40,7 +40,7 @@ export class DossierDetailsComponent implements OnInit {
) {}
get memberIds(): string[] {
return this.appStateService.activeDossier.dossier.memberIds;
return this.appStateService.activeDossier.memberIds;
}
get hasFiles(): boolean {
@ -54,7 +54,7 @@ export class DossierDetailsComponent implements OnInit {
ngOnInit(): void {
this.owner = this._userService.getRedUserById(this.appStateService.activeDossier.ownerId);
this.calculateChartConfig();
this.appStateService.fileChanged.subscribe(() => {
this.appStateService.fileChanged$.subscribe(() => {
this.calculateChartConfig();
});
}
@ -81,12 +81,11 @@ export class DossierDetailsComponent implements OnInit {
async assignOwner(user: UserWrapper | string) {
this.owner = typeof user === 'string' ? this._userService.getRedUserById(user) : user;
const dw = Object.assign({}, this.appStateService.activeDossier);
dw.dossier.ownerId = this.owner.id;
await this.appStateService.createOrUpdateDossier(dw.dossier);
const dw = { ...this.appStateService.activeDossier, ownerId: this.owner.id };
await this.appStateService.createOrUpdateDossier(dw);
const ownerName = this._userService.getNameForId(this.owner.id);
const dossierName = this.appStateService.activeDossier.name;
const dossierName = this.appStateService.activeDossier.dossierName;
this._toaster.info(_('assignment.owner'), { params: { ownerName, dossierName } });
}
}

View File

@ -1,4 +1,4 @@
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { PermissionsService } from '@services/permissions.service';
import { DossierWrapper } from '@state/model/dossier.wrapper';
import { StatusSorter } from '@utils/sorters/status-sorter';
@ -11,7 +11,8 @@ import { FileStatusWrapper } from '@models/file/file-status.wrapper';
@Component({
selector: 'redaction-dossier-listing-actions',
templateUrl: './dossier-listing-actions.component.html',
styleUrls: ['./dossier-listing-actions.component.scss']
styleUrls: ['./dossier-listing-actions.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DossierListingActionsComponent implements OnInit {
readonly circleButtonTypes = CircleButtonTypes;

View File

@ -100,7 +100,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
this.screen = 'file-preview';
this._setup();
this.addSubscription = this.appStateService.fileChanged
this.addSubscription = this.appStateService.fileChanged$
.pipe(filter(file => file.fileId === this.fileStatus?.fileId))
.subscribe(fileStatus => {
this.fileStatus = fileStatus;

View File

@ -34,7 +34,7 @@ export class PageIndicatorComponent implements OnChanges, OnInit, OnDestroy {
}
ngOnInit(): void {
this._subscription = this._appStateService.fileChanged.subscribe(() => {
this._subscription = this._appStateService.fileChanged$.subscribe(() => {
this.canMarkPagesAsViewed = this._permissionService.canMarkPagesAsViewed();
});
}

View File

@ -82,11 +82,13 @@ export class TeamMembersManagerComponent implements OnInit {
const ownerId = this.selectedOwnerId;
const memberIds = this.selectedMembersList;
const approverIds = this.selectedApproversList;
const dw = Object.assign({}, this.dossierWrapper);
dw.dossier.memberIds = memberIds;
dw.dossier.approverIds = approverIds;
dw.dossier.ownerId = ownerId;
result = await this._appStateService.createOrUpdateDossier(dw.dossier);
const dw = {
...this.dossierWrapper,
memberIds,
approverIds,
ownerId
};
result = await this._appStateService.createOrUpdateDossier(dw);
this.save.emit(result);
} catch (error) {
this._toaster.error('Failed: ' + error.error ? error.error.message : error);

View File

@ -8,7 +8,6 @@ import { downloadTypesTranslations } from '../../../../translations/download-typ
import { IconButtonTypes } from '@iqser/common-ui';
@Component({
selector: 'redaction-add-dossier-dialog',
templateUrl: './add-dossier-dialog.component.html',
styleUrls: ['./add-dossier-dialog.component.scss']
})
@ -71,7 +70,7 @@ export class AddDossierDialogComponent {
async saveDossier() {
const dossier: Dossier = this._formToObject();
const foundDossier = this._appStateService.allDossiers.find(p => p.dossier.dossierId === dossier.dossierId);
const foundDossier = this._appStateService.allDossiers.find(p => p.dossierId === dossier.dossierId);
if (foundDossier) {
dossier.memberIds = foundDossier.memberIds;
}

View File

@ -6,7 +6,6 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DossierWrapper } from '@state/model/dossier.wrapper';
@Component({
selector: 'redaction-document-info-dialog',
templateUrl: './document-info-dialog.component.html',
styleUrls: ['./document-info-dialog.component.scss']
})

View File

@ -43,11 +43,11 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
get changed() {
if (this.dossierForm) {
for (const key of Object.keys(this.dossierForm.getRawValue())) {
if (this.dossierWrapper.dossier[key].length !== this.dossierForm.get(key).value.length) {
if (this.dossierWrapper[key].length !== this.dossierForm.get(key).value.length) {
return true;
}
const originalItems = [...this.dossierWrapper.dossier[key]].sort();
const originalItems = [...this.dossierWrapper[key]].sort();
const newItems = [...this.dossierForm.get(key).value].sort();
for (let idx = 0; idx < originalItems.length; ++idx) {
@ -71,8 +71,8 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
this.dossierForm = this._formBuilder.group(
{
reportTemplateIds: [this.dossierWrapper.dossier.reportTemplateIds],
downloadFileTypes: [this.dossierWrapper.dossier.downloadFileTypes]
reportTemplateIds: [this.dossierWrapper.reportTemplateIds],
downloadFileTypes: [this.dossierWrapper.downloadFileTypes]
},
{
validators: control =>
@ -85,7 +85,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
async save() {
const dossier = {
...this.dossierWrapper.dossier,
...this.dossierWrapper,
downloadFileTypes: this.dossierForm.get('downloadFileTypes').value,
reportTemplateIds: this.dossierForm.get('reportTemplateIds').value
};
@ -95,8 +95,8 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
revert() {
this.dossierForm.reset({
downloadFileTypes: this.dossierWrapper.dossier.downloadFileTypes,
reportTemplateIds: this.dossierWrapper.dossier.reportTemplateIds
downloadFileTypes: this.dossierWrapper.downloadFileTypes,
reportTemplateIds: this.dossierWrapper.reportTemplateIds
});
}
}

View File

@ -1,6 +1,6 @@
<section class="dialog">
<div class="dialog-header heading-l">
{{ 'edit-dossier-dialog.header' | translate: { dossierName: dossierWrapper.name } }}
{{ 'edit-dossier-dialog.header' | translate: { dossierName: dossierWrapper.dossierName } }}
</div>
<div class="dialog-content">

View File

@ -94,7 +94,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
async save() {
const dossier = {
...this.dossierWrapper.dossier,
...this.dossierWrapper,
dossierName: this.dossierForm.get('dossierName').value,
description: this.dossierForm.get('description').value,
watermarkEnabled: this.dossierForm.get('watermarkEnabled').value,

View File

@ -23,54 +23,54 @@
<cdk-virtual-scroll-viewport #scrollViewport [itemSize]="itemSize" redactionHasScrollbar>
<div
*cdkVirtualFor="let dw of sortedDisplayedEntities$ | async; trackBy: trackByPrimaryKey"
[class.pointer]="!!dw"
[routerLink]="[!!dw ? '/main/dossiers/' + dw.dossier.dossierId : []]"
*cdkVirtualFor="let item of sortedDisplayedEntities$ | async; trackBy: trackByPrimaryKey"
[class.pointer]="!!item"
[routerLink]="[item.routerLink]"
class="table-item"
>
<div class="filename">
<div [matTooltip]="dw.dossierName" class="table-item-title heading" matTooltipPosition="above">
{{ dw.dossierName }}
<div [matTooltip]="item.dossierName" class="table-item-title heading" matTooltipPosition="above">
{{ item.dossierName }}
</div>
<div class="small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:template"></mat-icon>
{{ getDossierTemplate(dw).name }}
{{ item.dossierTemplateName }}
</div>
</div>
<div class="small-label stats-subtitle">
<div>
<mat-icon svgIcon="red:document"></mat-icon>
{{ dw.files.length }}
{{ item.dossier.filesLength }}
</div>
<div>
<mat-icon svgIcon="red:pages"></mat-icon>
{{ dw.totalNumberOfPages }}
{{ item.dossier.totalNumberOfPages }}
</div>
<div>
<mat-icon svgIcon="red:user"></mat-icon>
{{ dw.numberOfMembers }}
{{ item.dossier.memberCount }}
</div>
<div>
<mat-icon svgIcon="red:calendar"></mat-icon>
{{ dw.dossier.date | date: 'mediumDate' }}
{{ item.dossier.date | date: 'mediumDate' }}
</div>
<div *ngIf="dw.dossier.dueDate">
<div *ngIf="item.dossier.dueDate">
<mat-icon svgIcon="red:lightning"></mat-icon>
{{ dw.dossier.dueDate | date: 'mediumDate' }}
{{ item.dossier.dueDate | date: 'mediumDate' }}
</div>
</div>
</div>
<div>
<redaction-needs-work-badge [needsWorkInput]="dw"></redaction-needs-work-badge>
<redaction-needs-work-badge [needsWorkInput]="item.dossier"></redaction-needs-work-badge>
</div>
<div class="user-column">
<redaction-initials-avatar [userId]="dw.dossier.ownerId" [withName]="true"></redaction-initials-avatar>
<redaction-initials-avatar [userId]="item.dossier.ownerId" [withName]="true"></redaction-initials-avatar>
</div>
<div class="status-container">
<redaction-dossier-listing-actions
(actionPerformed)="calculateData()"
[dossier]="dw"
[dossier]="item.dossier"
></redaction-dossier-listing-actions>
</div>
<div class="scrollbar-placeholder"></div>

View File

@ -1,4 +1,4 @@
import { AfterViewInit, ChangeDetectorRef, Component, Injector, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { Component, Injector, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { Dossier, DossierTemplateModel } from '@redaction/red-ui-http';
import { AppStateService } from '@state/app-state.service';
import { UserService } from '@services/user.service';
@ -31,19 +31,24 @@ import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';
const isLeavingScreen = event => event instanceof NavigationStart && event.url !== '/main/dossiers';
interface ListItem {
readonly dossierName: string;
readonly routerLink: string;
readonly dossierTemplateName: string;
readonly dossier: DossierWrapper;
}
@Component({
templateUrl: './dossier-listing-screen.component.html',
styleUrls: ['./dossier-listing-screen.component.scss'],
providers: [...DefaultListingServices]
})
export class DossierListingScreenComponent
extends ListingComponent<DossierWrapper>
implements OnInit, AfterViewInit, OnDestroy, OnAttach, OnDetach
{
export class DossierListingScreenComponent extends ListingComponent<ListItem> implements OnInit, OnDestroy, OnAttach, OnDetach {
readonly itemSize = 85;
protected readonly _primaryKey = 'dossierName';
readonly currentUser = this._userService.currentUser;
readonly tableHeaderLabel = _('dossier-listing.table-header.title');
readonly buttonConfigs: ButtonConfig[] = [
readonly buttonConfigs: readonly ButtonConfig[] = [
{
label: _('dossier-listing.add-new'),
action: () => this.openAddDossierDialog(),
@ -52,7 +57,7 @@ export class DossierListingScreenComponent
type: 'primary'
}
];
readonly tableColumnConfigs: TableColumnConfig<DossierWrapper>[] = [
readonly tableColumnConfigs: readonly TableColumnConfig<ListItem>[] = [
{
label: _('dossier-listing.table-col-names.name'),
sortByKey: 'dossierName'
@ -72,7 +77,6 @@ export class DossierListingScreenComponent
dossiersChartData: DoughnutChartConfig[] = [];
documentsChartData: DoughnutChartConfig[] = [];
protected readonly _primaryKey = 'dossierName';
private _lastScrollPosition: number;
@ViewChild('needsWorkTemplate', { read: TemplateRef, static: true })
@ -84,7 +88,6 @@ export class DossierListingScreenComponent
private readonly _router: Router,
protected readonly _injector: Injector,
private readonly _userService: UserService,
readonly changeDetectorRef: ChangeDetectorRef,
readonly permissionsService: PermissionsService,
private readonly _appStateService: AppStateService,
private readonly _translateService: TranslateService,
@ -97,10 +100,6 @@ export class DossierListingScreenComponent
this._loadEntitiesFromState();
}
private get _userId() {
return this._userService.currentUser.id;
}
private get _activeDossiersCount(): number {
return this.entitiesService.all.filter(p => p.dossier.status === Dossier.StatusEnum.ACTIVE).length;
}
@ -118,7 +117,7 @@ export class DossierListingScreenComponent
this.calculateData();
});
this.addSubscription = this._appStateService.fileChanged.subscribe(() => {
this.addSubscription = this._appStateService.fileChanged$.subscribe(() => {
this.calculateData();
});
@ -127,10 +126,6 @@ export class DossierListingScreenComponent
});
}
ngAfterViewInit() {
this.changeDetectorRef.detectChanges();
}
ngOnAttach() {
this._scrollViewport.scrollTo({ top: this._lastScrollPosition });
this._appStateService.reset();
@ -142,8 +137,8 @@ export class DossierListingScreenComponent
this.ngOnDestroy();
}
getDossierTemplate(dw: DossierWrapper): DossierTemplateModel {
return this._appStateService.getDossierTemplateById(dw.dossier.dossierTemplateId);
getDossierTemplate(dossierTemplateId: string): DossierTemplateModel {
return this._appStateService.getDossierTemplateById(dossierTemplateId);
}
openAddDossierDialog(): void {
@ -181,7 +176,17 @@ export class DossierListingScreenComponent
}
private _loadEntitiesFromState() {
this.entitiesService.setEntities(this._appStateService.allDossiers);
const entities = this._appStateService.allDossiers.map(dossier => this._toListItem(dossier));
this.entitiesService.setEntities(entities);
}
private _toListItem(dossier: DossierWrapper): ListItem {
return {
dossierName: dossier.dossierName,
routerLink: '/main/dossiers/' + dossier.dossierId.toString(),
dossierTemplateName: this.getDossierTemplate(dossier.dossierTemplateId).name,
dossier
};
}
private _computeAllFilters() {
@ -190,20 +195,20 @@ export class DossierListingScreenComponent
const allDistinctNeedsWork = new Set<string>();
const allDistinctDossierTemplates = new Set<string>();
this.entitiesService?.all?.forEach(entry => {
this.entitiesService.all?.forEach(entry => {
// all people
entry.dossier.memberIds.forEach(f => allDistinctPeople.add(f));
// Needs work
entry.files.forEach(file => {
entry.dossier.files.forEach(file => {
allDistinctFileStatus.add(file.status);
if (this.permissionsService.fileRequiresReanalysis(file)) allDistinctNeedsWork.add('analysis');
if (entry.hintsOnly) allDistinctNeedsWork.add('hint');
if (entry.hasRedactions) allDistinctNeedsWork.add('redaction');
if (entry.hasRequests) allDistinctNeedsWork.add('suggestion');
if (entry.hasNone) allDistinctNeedsWork.add('none');
if (file.analysisRequired) allDistinctNeedsWork.add('analysis');
if (entry.dossier.hintsOnly) allDistinctNeedsWork.add('hint');
if (entry.dossier.hasRedactions) allDistinctNeedsWork.add('redaction');
if (entry.dossier.hasRequests) allDistinctNeedsWork.add('suggestion');
if (entry.dossier.hasNone) allDistinctNeedsWork.add('none');
});
allDistinctDossierTemplates.add(entry.dossierTemplateId);
allDistinctDossierTemplates.add(entry.dossier.dossierTemplateId);
});
const statusFilters = [...allDistinctFileStatus].map<NestedFilter>(status => ({
@ -276,22 +281,22 @@ export class DossierListingScreenComponent
{
key: 'my-dossiers',
label: myDossiersLabel,
checker: (dw: DossierWrapper) => dw.ownerId === this._userId
checker: (dw: DossierWrapper) => dw.ownerId === this.currentUser.id
},
{
key: 'to-approve',
label: this._translateService.instant('dossier-listing.quick-filters.to-approve'),
checker: (dw: DossierWrapper) => dw.approverIds.includes(this._userId)
checker: (dw: DossierWrapper) => dw.approverIds.includes(this.currentUser.id)
},
{
key: 'to-review',
label: this._translateService.instant('dossier-listing.quick-filters.to-review'),
checker: (dw: DossierWrapper) => dw.memberIds.includes(this._userId)
checker: (dw: DossierWrapper) => dw.memberIds.includes(this.currentUser.id)
},
{
key: 'other',
label: this._translateService.instant('dossier-listing.quick-filters.other'),
checker: (dw: DossierWrapper) => !dw.memberIds.includes(this._userId)
checker: (dw: DossierWrapper) => !dw.memberIds.includes(this.currentUser.id)
}
];

View File

@ -141,7 +141,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<FileStatusW
this._loadEntitiesFromState();
});
this.addSubscription = this._appStateService.fileChanged.subscribe(() => {
this.addSubscription = this._appStateService.fileChanged$.subscribe(() => {
this.calculateData();
});

View File

@ -548,7 +548,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
private _subscribeToFileUpdates(): void {
this.addSubscription = timer(0, 5000).subscribe(async () => await this.appStateService.reloadActiveFile());
this.addSubscription = this.appStateService.fileReanalysed.subscribe(async (fileStatus: FileStatusWrapper) => {
this.addSubscription = this.appStateService.fileReanalysed$.subscribe(async (fileStatus: FileStatusWrapper) => {
if (fileStatus.fileId === this.fileId) {
await this._loadFileData(!this._reloadFileOnReanalysis);
this._reloadFileOnReanalysis = false;

View File

@ -25,7 +25,7 @@ export class FileActionService {
fileStatusWrapper = this._appStateService.activeFile;
}
return this._reanalysisControllerService.reanalyzeFile(
this._appStateService.activeDossier.dossier.dossierId,
this._appStateService.activeDossier.dossierId,
fileStatusWrapper.fileId,
true
);

View File

@ -31,9 +31,9 @@
</div>
<div class="red-input-group w-200 mr-8">
<mat-select [(ngModel)]="dossier" [disabled]="!compare">
<mat-option [value]="selectDossier">{{ selectDossier.name | translate }}</mat-option>
<mat-option [value]="selectDossier">{{ selectDossier.dossierName | translate }}</mat-option>
<mat-option *ngFor="let dossier of dossiers" [value]="dossier">
{{ dossier.name }}
{{ dossier.dossierName }}
</mat-option>
</mat-select>
</div>
@ -55,7 +55,7 @@
[original]="diffEditorText"
></ngx-monaco-diff-editor>
<div *ngIf="compare && dossier === selectDossier" class="no-dictionary-selected">
<div *ngIf="compare && dossier.dossierName === selectDossier.dossierName" class="no-dictionary-selected">
<mat-icon svgIcon="red:dictionary"></mat-icon>
<span class="heading-l" translate="dictionary-overview.select-dictionary"></span>
</div>

View File

@ -40,7 +40,7 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
showDiffEditor = false;
searchText = '';
selectDossier = { name: _('dictionary-overview.compare.select-dossier') };
selectDossier = { dossierName: _('dictionary-overview.compare.select-dossier') };
compare: false;
private _codeEditor: ICodeEditor;

View File

@ -16,11 +16,11 @@ export class PageHeaderComponent<T extends object> {
@Input() pageLabel: string;
@Input() showCloseButton: boolean;
@Input() actionConfigs: ActionConfig[];
@Input() buttonConfigs: ButtonConfig[];
@Input() actionConfigs: readonly ActionConfig[];
@Input() buttonConfigs: readonly ButtonConfig[];
@Input() searchPlaceholder: string;
@Input() searchWidth: number | 'full';
@Input() searchPosition: SearchPosition = this.searchPositions.afterFilters;
@Input() searchPosition: SearchPosition = SearchPositions.afterFilters;
readonly filters$ = this.filterService?.filterGroups$.pipe(map(all => all.filter(f => f.icon)));
readonly showResetFilters$ = this._showResetFilters$;

View File

@ -1,4 +1,4 @@
import { EventEmitter, Injectable } from '@angular/core';
import { Injectable } from '@angular/core';
import {
DictionaryControllerService,
Dossier,
@ -13,7 +13,7 @@ import { Toaster } from '@services/toaster.service';
import { TranslateService } from '@ngx-translate/core';
import { Event, NavigationEnd, ResolveStart, Router } from '@angular/router';
import { UserService } from '@services/user.service';
import { forkJoin, Observable, of } from 'rxjs';
import { forkJoin, Observable, of, Subject } from 'rxjs';
import { catchError, tap } from 'rxjs/operators';
import { FALLBACK_COLOR, hexToRgb } from '@utils/functions';
import { FileStatusWrapper } from '@models/file/file-status.wrapper';
@ -41,8 +41,8 @@ export interface AppState {
providedIn: 'root'
})
export class AppStateService {
fileChanged = new EventEmitter<FileStatusWrapper>();
fileReanalysed = new EventEmitter<FileStatusWrapper>();
fileChanged$ = new Subject<FileStatusWrapper>();
fileReanalysed$ = new Subject<FileStatusWrapper>();
private _appState: AppState;
constructor(
@ -208,7 +208,7 @@ export class AppStateService {
}
getDossierById(id: string) {
return this.allDossiers.find(dossier => dossier.dossier.dossierId === id);
return this.allDossiers.find(dossier => dossier.dossierId === id);
}
getFileById(dossierId: string, fileId: string) {
@ -252,9 +252,9 @@ export class AppStateService {
this._computeStats();
if (activeFileWrapper.lastProcessed !== oldProcessedDate) {
this.fileReanalysed.emit(activeFileWrapper);
this.fileReanalysed$.next(activeFileWrapper);
}
this.fileChanged.emit(activeFileWrapper);
this.fileChanged$.next(activeFileWrapper);
return activeFileWrapper;
}
@ -346,12 +346,13 @@ export class AppStateService {
const updatedDossier = await this._dossiersService.createOrUpdate(dossier);
let foundDossier = this.allDossiers.find(p => p.dossierId === updatedDossier.dossierId);
if (foundDossier) {
Object.assign((foundDossier.dossier = updatedDossier));
this._appState.dossiers.splice(this._appState.dossiers.indexOf(foundDossier), 1);
foundDossier = new DossierWrapper(updatedDossier, foundDossier.files);
} else {
foundDossier = new DossierWrapper(updatedDossier, []);
this._appState.dossiers.push(foundDossier);
}
this._appState.dossiers = [...this._appState.dossiers];
this._appState.dossiers.push(foundDossier);
return foundDossier;
} catch (error) {
this._toaster.error(
@ -705,8 +706,8 @@ export class AppStateService {
this._computeStats();
if (emitEvents) {
fileReanalysedEvent.forEach(file => this.fileReanalysed.emit(file));
fileStatusChangedEvent.forEach(file => this.fileChanged.emit(file));
fileReanalysedEvent.forEach(file => this.fileReanalysed$.next(file));
fileStatusChangedEvent.forEach(file => this.fileChanged$.next(file));
}
return files;
@ -716,12 +717,10 @@ export class AppStateService {
let totalAnalysedPages = 0;
let totalDocuments = 0;
const totalPeople = new Set<string>();
this.allDossiers.forEach(d => {
totalDocuments += d.files.length;
if (d.dossier.memberIds) {
d.dossier.memberIds.forEach(m => totalPeople.add(m));
}
d.memberIds?.forEach(m => totalPeople.add(m));
d.totalNumberOfPages = d.files.reduce((acc, file) => acc + file.numberOfPages, 0);
totalAnalysedPages += d.totalNumberOfPages;
});

View File

@ -2,9 +2,32 @@ import { FileStatusWrapper } from '@models/file/file-status.wrapper';
import * as moment from 'moment';
import { Dictionary, Dossier } from '@redaction/red-ui-http';
export class DossierWrapper {
totalNumberOfPages?: number;
export class DossierWrapper implements Dossier {
readonly approverIds = this._dossier.approverIds;
readonly date = this._dossier.date;
readonly description = this._dossier.description;
readonly dossierId = this._dossier.dossierId;
readonly dossierName = this._dossier.dossierName;
readonly dossierTemplateId = this._dossier.dossierTemplateId;
readonly downloadFileTypes = this._dossier.downloadFileTypes;
readonly dueDate = this._dossier.dueDate;
readonly hardDeletedTime = this._dossier.hardDeletedTime;
readonly memberIds = this._dossier.memberIds;
readonly ownerId = this._dossier.ownerId;
readonly reportTemplateIds = this._dossier.reportTemplateIds;
readonly reportTypes = this._dossier.reportTypes;
readonly softDeletedTime = this._dossier.softDeletedTime;
readonly status = this._dossier.status;
readonly watermarkEnabled = this._dossier.watermarkEnabled;
readonly hasMoreThanOneApprover = this.approverIds.length > 1;
readonly hasMoreThanOneReviewer = this.memberIds.length > 1;
readonly memberCount = this.memberIds.length;
hasFiles = this._files.length > 0;
filesLength = this._files.length;
totalNumberOfPages?: number;
hintsOnly?: boolean;
hasRedactions?: boolean;
hasRequests?: boolean;
@ -12,15 +35,12 @@ export class DossierWrapper {
hasPendingOrProcessing?: boolean;
allFilesApproved?: boolean;
type: Dictionary;
type?: Dictionary;
constructor(public dossier: Dossier, files: FileStatusWrapper[]) {
this._files = files ? files : [];
constructor(private readonly _dossier: Dossier, private _files: FileStatusWrapper[] = []) {
this._recomputeFileStatus();
}
private _files: FileStatusWrapper[];
get files() {
return this._files;
}
@ -30,84 +50,16 @@ export class DossierWrapper {
this._recomputeFileStatus();
}
get hasMoreThanOneApprover() {
return this.approverIds.length > 1;
}
get hasMoreThanOneReviewer() {
return this.memberIds.length > 1;
}
get dossierName() {
return this.dossier.dossierName;
}
get description() {
return this.dossier.description;
}
get dossierTemplateId() {
return this.dossier.dossierTemplateId;
}
get ownerId() {
return this.dossier.ownerId;
}
get dossierId() {
return this.dossier.dossierId;
}
get memberIds() {
return this.dossier.memberIds;
}
get approverIds() {
return this.dossier.approverIds;
}
get dossierDate() {
return this.dossier.date;
}
get numberOfMembers() {
return this.dossier.memberIds.length;
}
get dueDate() {
return this.dossier.dueDate;
}
get hasFiles() {
return this._files.length > 0;
}
get name() {
return this.dossier.dossierName;
}
get memberCount() {
return this.dossier.memberIds.length;
}
get watermarkEnabled(): boolean {
return this.dossier.watermarkEnabled;
}
hasStatus(status: string): boolean {
return !!this._files.find(f => f.status === status);
}
hasMember(key: string) {
return this.dossier.memberIds.indexOf(key) >= 0;
}
dueDateMatches(key: string) {
return moment(this.dueDate).format('DD/MM/YYYY') === key;
return this._dossier.memberIds.indexOf(key) >= 0;
}
addedDateMatches(key: string) {
return moment(this.dossierDate).format('DD/MM/YYYY') === key;
return moment(this.date).format('DD/MM/YYYY') === key;
}
private _recomputeFileStatus() {
@ -127,5 +79,7 @@ export class DossierWrapper {
this.hasPendingOrProcessing = this.hasPendingOrProcessing || f.isPending || f.isProcessing;
});
this.hasNone = !this.hasRequests && !this.hasRedactions && !this.hintsOnly;
this.hasFiles = this._files.length > 0;
this.filesLength = this._files.length;
}
}