remove some activeDossier calls

This commit is contained in:
Dan Percic 2021-11-12 01:35:59 +02:00
parent 0dd26a1eea
commit 41bc7a0055
16 changed files with 259 additions and 257 deletions

View File

@ -12,7 +12,7 @@ import { PermissionsService } from '@services/permissions.service';
class DialogData {
mode: 'approver' | 'reviewer';
dossier?: Dossier;
dossierId: string;
files?: File[];
ignoreChanged?: boolean;
}
@ -24,6 +24,7 @@ class DialogData {
export class AssignReviewerApproverDialogComponent {
usersForm: FormGroup;
searchForm: FormGroup;
readonly dossier: Dossier | undefined;
constructor(
readonly userService: UserService,
@ -36,6 +37,7 @@ export class AssignReviewerApproverDialogComponent {
private readonly _dialogRef: MatDialogRef<AssignReviewerApproverDialogComponent, boolean>,
@Inject(MAT_DIALOG_DATA) readonly data: DialogData,
) {
this.dossier = this._dossiersService.find(data.dossierId);
this._loadData();
}
@ -46,8 +48,8 @@ export class AssignReviewerApproverDialogComponent {
get singleUsersSelectOptions() {
const unassignUser = this._canUnassignFiles ? [undefined] : [];
return this.data.mode === 'approver'
? [...this._dossiersService.activeDossier.approverIds, ...unassignUser]
: [...this._dossiersService.activeDossier.memberIds, ...unassignUser];
? [...this.dossier.approverIds, ...unassignUser]
: [...this.dossier.memberIds, ...unassignUser];
}
get changed(): boolean {
@ -80,7 +82,7 @@ export class AssignReviewerApproverDialogComponent {
await this._filesService
.setReviewerFor(
this.data.files.map(f => f.fileId),
this._dossiersService.activeDossierId,
this.data.dossierId,
selectedUser,
)
.toPromise();
@ -88,7 +90,7 @@ export class AssignReviewerApproverDialogComponent {
await this._filesService
.setUnderApprovalFor(
this.data.files.map(f => f.fileId),
this._dossiersService.activeDossierId,
this.data.dossierId,
selectedUser,
)
.toPromise();

View File

@ -41,7 +41,7 @@ export class EditDossierDialogComponent {
private readonly _dialogRef: MatDialogRef<EditDossierDialogComponent>,
@Inject(MAT_DIALOG_DATA)
private readonly _data: {
dossier: Dossier;
dossierId: string;
afterSave: Function;
section?: Section;
},
@ -77,7 +77,7 @@ export class EditDossierDialogComponent {
},
];
this.dossier = _data.dossier;
this.dossier = this._dossiersService.find(_data.dossierId);
this.activeNav = _data.section || 'dossierInfo';
}
@ -111,7 +111,7 @@ export class EditDossierDialogComponent {
updatedDossier() {
this._toaster.success(_('edit-dossier-dialog.change-successful'), { params: { dossierName: this.dossier.dossierName } });
this.dossier = this._dossiersService.find(this.dossier.id);
this._changeRef.detectChanges();
this._changeRef.markForCheck();
this.afterSave();
}

View File

@ -1,76 +1,65 @@
<ng-container *ngIf="dossiersService.activeDossier$ | async as dossier">
<div>
<mat-icon svgIcon="iqser:document"></mat-icon>
<span>{{ 'dossier-overview.dossier-details.stats.documents' | translate: { count: dossier.files.length } }}</span>
</div>
<div>
<mat-icon svgIcon="red:user"></mat-icon>
<span>{{ 'dossier-overview.dossier-details.stats.people' | translate: { count: dossier.memberIds.length } }}</span>
</div>
<div>
<mat-icon svgIcon="iqser:pages"></mat-icon>
<span>{{
'dossier-overview.dossier-details.stats.analysed-pages' | translate: { count: dossier.totalNumberOfPages | number }
}}</span>
</div>
<div>
<mat-icon svgIcon="red:calendar"></mat-icon>
<span
>{{
'dossier-overview.dossier-details.stats.created-on'
| translate
: {
date: dossier.date | date: 'd MMM. yyyy'
}
}}
</span>
</div>
<div *ngIf="dossier.dueDate">
<mat-icon svgIcon="red:lightning"></mat-icon>
<span>{{
'dossier-overview.dossier-details.stats.due-date'
| translate
: {
date: dossier.dueDate | date: 'd MMM. yyyy'
}
}}</span>
</div>
<div>
<mat-icon svgIcon="red:template"></mat-icon>
<span>{{ dossierTemplate(dossier).name }} </span>
</div>
<div (click)="openDossierDictionaryDialog.emit()" *ngIf="dossier.type" class="link-property">
<mat-icon svgIcon="red:dictionary"></mat-icon>
<span>{{ 'dossier-overview.dossier-details.dictionary' | translate }} </span>
</div>
<div (click)="openEditDossierAttributesDialog(dossier, 'deletedDocuments')" class="link-property">
<mat-icon svgIcon="iqser:trash"></mat-icon>
<span>{{ 'dossier-overview.dossier-details.stats.deleted' | translate: { count: deletedFilesCount$ | async } }}</span>
<div>
<mat-icon svgIcon="iqser:document"></mat-icon>
<span>{{ 'dossier-overview.dossier-details.stats.documents' | translate: { count: dossier.files.length } }}</span>
</div>
<div>
<mat-icon svgIcon="red:user"></mat-icon>
<span>{{ 'dossier-overview.dossier-details.stats.people' | translate: { count: dossier.memberIds.length } }}</span>
</div>
<div>
<mat-icon svgIcon="iqser:pages"></mat-icon>
<span>{{ 'dossier-overview.dossier-details.stats.analysed-pages' | translate: { count: dossier.totalNumberOfPages | number } }}</span>
</div>
<div *ngIf="dossier.date | date: 'd MMM. yyyy' as date">
<mat-icon svgIcon="red:calendar"></mat-icon>
<span>{{ 'dossier-overview.dossier-details.stats.created-on' | translate: { date: date } }}</span>
</div>
<div *ngIf="dossier.dueDate | date: 'd MMM. yyyy' as dueDate">
<mat-icon svgIcon="red:lightning"></mat-icon>
<span>{{ 'dossier-overview.dossier-details.stats.due-date' | translate: { date: dueDate } }}</span>
</div>
<div>
<mat-icon svgIcon="red:template"></mat-icon>
<span>{{ dossierTemplate(dossier).name }} </span>
</div>
<div (click)="openDossierDictionaryDialog.emit()" *ngIf="dossier.type" class="link-property">
<mat-icon svgIcon="red:dictionary"></mat-icon>
<span>{{ 'dossier-overview.dossier-details.dictionary' | translate }} </span>
</div>
<div (click)="openEditDossierAttributesDialog(dossier.dossierId, 'deletedDocuments')" class="link-property">
<mat-icon svgIcon="iqser:trash"></mat-icon>
<span>{{ 'dossier-overview.dossier-details.stats.deleted' | translate: { count: deletedFilesCount$ | async } }}</span>
</div>
<ng-container *ngIf="dossierAttributes?.length">
<div (click)="attributesExpanded = true" *ngIf="!attributesExpanded" class="all-caps-label show-attributes">
{{ 'dossier-overview.dossier-details.attributes.expand' | translate: { count: dossierAttributes.length } }}
</div>
<ng-container *ngIf="dossierAttributes?.length">
<div (click)="attributesExpanded = true" *ngIf="!attributesExpanded" class="all-caps-label show-attributes">
{{ 'dossier-overview.dossier-details.attributes.expand' | translate: { count: dossierAttributes.length } }}
<ng-container *ngIf="attributesExpanded">
<div
(click)="openEditDossierAttributesDialog(dossier.dossierId, 'dossierAttributes')"
*ngFor="let attr of dossierAttributes"
class="link-property"
>
<mat-icon svgIcon="red:attribute"></mat-icon>
<span *ngIf="!attr.value"> {{ attr.label + ': -' }}</span>
<span *ngIf="attr.value && attr.type === 'DATE'"> {{ attr.label + ': ' + (attr.value | date: 'd MMM. yyyy') }}</span>
<span *ngIf="attr.value && attr.type === 'IMAGE'">
{{ attr.label + ': ' + ('dossier-overview.dossier-details.attributes.image-uploaded' | translate) }}</span
>
<span *ngIf="attr.value && (attr.type === 'TEXT' || attr.type === 'NUMBER')"> {{ attr.label + ': ' + attr.value }}</span>
</div>
<ng-container *ngIf="attributesExpanded">
<div
(click)="openEditDossierAttributesDialog(dossier, 'dossierAttributes')"
*ngFor="let attr of dossierAttributes"
class="link-property"
>
<mat-icon svgIcon="red:attribute"></mat-icon>
<span *ngIf="!attr.value"> {{ attr.label + ': -' }}</span>
<span *ngIf="attr.value && attr.type === 'DATE'"> {{ attr.label + ': ' + (attr.value | date: 'd MMM. yyyy') }}</span>
<span *ngIf="attr.value && attr.type === 'IMAGE'">
{{ attr.label + ': ' + ('dossier-overview.dossier-details.attributes.image-uploaded' | translate) }}</span
>
<span *ngIf="attr.value && (attr.type === 'TEXT' || attr.type === 'NUMBER')"> {{ attr.label + ': ' + attr.value }}</span>
</div>
<div (click)="attributesExpanded = false" class="all-caps-label hide-attributes">
{{ 'dossier-overview.dossier-details.attributes.show-less' | translate }}
</div>
</ng-container>
<div (click)="attributesExpanded = false" class="all-caps-label hide-attributes">
{{ 'dossier-overview.dossier-details.attributes.show-less' | translate }}
</div>
</ng-container>
</ng-container>

View File

@ -1,33 +1,36 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { AppStateService } from '@state/app-state.service';
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Dossier, DossierAttributeWithValue, DossierTemplate } from '@red/domain';
import { DossiersDialogService } from '../../../../services/dossiers-dialog.service';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
import { FilesService } from '@services/entity-services/files.service';
import { Observable } from 'rxjs';
import { distinctUntilChanged, map, switchMap } from 'rxjs/operators';
import { distinctUntilChanged, map } from 'rxjs/operators';
@Component({
selector: 'redaction-dossier-details-stats',
templateUrl: './dossier-details-stats.component.html',
styleUrls: ['./dossier-details-stats.component.scss'],
})
export class DossierDetailsStatsComponent {
export class DossierDetailsStatsComponent implements OnInit {
attributesExpanded = false;
deletedFilesCount$: Observable<number>;
@Input() dossierAttributes: DossierAttributeWithValue[];
@Output() readonly openDossierDictionaryDialog = new EventEmitter();
@Input()
dossierAttributes: DossierAttributeWithValue[];
@Input()
dossier: Dossier;
@Output()
readonly openDossierDictionaryDialog = new EventEmitter();
constructor(
private readonly _appStateService: AppStateService,
private readonly _dossierTemplatesService: DossierTemplatesService,
private readonly _dialogService: DossiersDialogService,
private readonly _filesService: FilesService,
readonly dossiersService: DossiersService,
) {
this.deletedFilesCount$ = dossiersService.activeDossier$.pipe(
switchMap(dossier => _filesService.getDeletedFilesFor(dossier.id)),
) {}
ngOnInit() {
this.deletedFilesCount$ = this._filesService.getDeletedFilesFor(this.dossier.id).pipe(
map(files => files.length),
distinctUntilChanged(),
);
@ -37,9 +40,9 @@ export class DossierDetailsStatsComponent {
return this._dossierTemplatesService.find(dossier.dossierTemplateId);
}
openEditDossierAttributesDialog(dossier: Dossier, section: string) {
openEditDossierAttributesDialog(dossierId: string, section: string) {
this._dialogService.openDialog('editDossier', null, {
dossier,
dossierId,
section: section,
});
}

View File

@ -1,4 +1,4 @@
<ng-container *ngIf="dossiersService.activeDossier$ | async as dossier">
<ng-container *ngIf="dossier$ | async as dossier">
<div class="collapsed-wrapper">
<ng-container *ngTemplateOutlet="collapsible; context: { action: 'expand', tooltip: (expandTooltip | translate) }"></ng-container>
<div class="all-caps-label" translate="dossier-details.title"></div>
@ -15,7 +15,7 @@
<div class="all-caps-label" translate="dossier-details.owner"></div>
<div class="mt-12 d-flex">
<ng-container *ngIf="!editingOwner; else editOwner">
<redaction-initials-avatar [user]="owner" [withName]="true" color="gray" size="large"></redaction-initials-avatar>
<redaction-initials-avatar [user]="dossier.ownerId" [withName]="true" color="gray" size="large"></redaction-initials-avatar>
<iqser-circle-button
(action)="editingOwner = true"
@ -40,7 +40,7 @@
<div *ngIf="dossier.hasFiles" class="mt-24">
<redaction-simple-doughnut-chart
[config]="documentsChartData"
[config]="calculateChartConfig(dossier)"
[radius]="63"
[strokeWidth]="15"
[subtitle]="'dossier-overview.dossier-details.charts.documents-in-dossier' | translate"
@ -62,6 +62,7 @@
<redaction-dossier-details-stats
(openDossierDictionaryDialog)="openDossierDictionaryDialog.emit()"
[dossierAttributes]="dossierAttributes"
[dossier]="dossier"
></redaction-dossier-details-stats>
</div>
@ -69,16 +70,16 @@
<div class="heading" translate="dossier-overview.dossier-details.description"></div>
<div class="mt-8">{{ description }}</div>
</div>
</ng-container>
<ng-template #editOwner>
<redaction-assign-user-dropdown
(cancel)="editingOwner = false"
(save)="editingOwner = false; assignOwner($event)"
[options]="managers"
[value]="owner"
></redaction-assign-user-dropdown>
</ng-template>
<ng-template #editOwner>
<redaction-assign-user-dropdown
(cancel)="editingOwner = false"
(save)="editingOwner = false; assignOwner($event, dossier)"
[options]="managers"
[value]="dossier.ownerId"
></redaction-assign-user-dropdown>
</ng-template>
</ng-container>
<ng-template #collapsible let-action="action" let-tooltip="tooltip">
<iqser-circle-button

View File

@ -1,4 +1,4 @@
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
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';
@ -7,8 +7,10 @@ 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 { DossierAttributeWithValue, IDossierRequest, StatusSorter, User } from '@red/domain';
import { Dossier, DossierAttributeWithValue, IDossierRequest, StatusSorter, User } from '@red/domain';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { ActivatedRoute } from '@angular/router';
import { Observable } from 'rxjs';
@Component({
selector: 'redaction-dossier-details',
@ -16,9 +18,7 @@ import { DossiersService } from '@services/entity-services/dossiers.service';
styleUrls: ['./dossier-details.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DossierDetailsComponent implements OnInit {
documentsChartData: DoughnutChartConfig[] = [];
owner: User;
export class DossierDetailsComponent {
editingOwner = false;
@Input() dossierAttributes: DossierAttributeWithValue[];
@Output() readonly openAssignDossierMembersDialog = new EventEmitter();
@ -29,6 +29,8 @@ export class DossierDetailsComponent implements OnInit {
readonly needsWorkFilters$ = this.filterService.getFilterModels$('needsWorkFilters');
readonly currentUser = this._userService.currentUser;
readonly dossierId: string;
readonly dossier$: Observable<Dossier>;
constructor(
readonly appStateService: AppStateService,
@ -38,43 +40,39 @@ export class DossierDetailsComponent implements OnInit {
private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _userService: UserService,
private readonly _toaster: Toaster,
) {}
activatedRoute: ActivatedRoute,
) {
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;
}
ngOnInit(): void {
this.owner = this._userService.find(this.dossiersService.activeDossier.ownerId);
}
calculateChartConfig(): void {
const activeDossier = this.dossiersService.activeDossier;
if (!activeDossier) {
return;
}
const groups = groupBy(activeDossier?.files, 'status');
let documentsChartData: DoughnutChartConfig[] = Object.keys(groups).map(status => ({
calculateChartConfig(dossier: Dossier): DoughnutChartConfig[] {
const groups = groupBy(dossier?.files, 'status');
const documentsChartData: DoughnutChartConfig[] = Object.keys(groups).map(status => ({
value: groups[status].length,
color: status,
label: fileStatusTranslations[status],
key: status,
}));
documentsChartData.sort((a, b) => StatusSorter.byStatus(a.key, b.key));
documentsChartData = this.translateChartService.translateStatus(documentsChartData);
this.documentsChartData = documentsChartData;
this._changeDetectorRef.detectChanges();
return this.translateChartService.translateStatus(documentsChartData);
}
async assignOwner(user: User | string) {
this.owner = typeof user === 'string' ? this._userService.find(user) : user;
const activeDossier = this.dossiersService.activeDossier;
const dossierRequest: IDossierRequest = { ...activeDossier, dossierId: activeDossier.dossierId, ownerId: this.owner.id };
async assignOwner(user: User | string, dossier: Dossier) {
const owner = typeof user === 'string' ? this._userService.find(user) : user;
const dossierRequest: IDossierRequest = { ...dossier, ownerId: owner.id };
await this.dossiersService.createOrUpdate(dossierRequest).toPromise();
const ownerName = this._userService.getNameForId(this.owner.id);
const dossierName = activeDossier.dossierName;
const ownerName = this._userService.getNameForId(owner.id);
const dossierName = dossier.dossierName;
this._toaster.info(_('assignment.owner'), { params: { ownerName, dossierName } });
}
}

View File

@ -1,8 +1,10 @@
import { Injectable, TemplateRef } from '@angular/core';
import {
ActionConfig,
IFilterGroup,
INestedFilter,
keyChecker,
List,
ListingMode,
ListingModes,
LoadingService,
@ -41,11 +43,11 @@ export class ConfigService {
private readonly _appConfigService: AppConfigService,
) {}
get actionConfig() {
actionConfig(dossierId: string): List<ActionConfig> {
return [
{
label: this._translateService.instant('dossier-overview.header-actions.edit'),
action: $event => this._openEditDossierDialog($event),
action: $event => this._openEditDossierDialog($event, dossierId),
icon: 'iqser:edit',
hide: !this._userService.currentUser.isManager,
},
@ -341,10 +343,8 @@ export class ConfigService {
].map(filter => new NestedFilter(filter));
}
private _openEditDossierDialog($event: MouseEvent) {
this._dialogService.openDialog('editDossier', $event, {
dossier: this._dossiersService.activeDossier,
});
private _openEditDossierDialog($event: MouseEvent, dossierId: string) {
this._dialogService.openDialog('editDossier', $event, { dossierId });
}
private _unassignFn = (reloadDossiers: () => Promise<void>) => async (file: File) => {

View File

@ -1,91 +1,100 @@
<section (longPress)="forceReanalysisAction($event)" *ngIf="!!currentDossier" redactionLongPress>
<iqser-page-header
(closeAction)="routerHistoryService.navigateToLastDossiersScreen()"
[actionConfigs]="actionConfigs"
[showCloseButton]="true"
[viewModeSelection]="viewModeSelection"
>
<redaction-file-download-btn
[dossier]="currentDossier"
[files]="entitiesService.all$ | async"
tooltipPosition="below"
></redaction-file-download-btn>
<ng-container *ngIf="dossier$ | async as dossier">
<section (longPress)="forceReanalysisAction($event)" redactionLongPress>
<iqser-page-header
(closeAction)="routerHistoryService.navigateToLastDossiersScreen()"
[actionConfigs]="actionConfigs"
[showCloseButton]="true"
[viewModeSelection]="viewModeSelection"
>
<redaction-file-download-btn
[dossier]="dossier"
[files]="entitiesService.all$ | async"
tooltipPosition="below"
></redaction-file-download-btn>
<iqser-circle-button
(action)="exportFilesAsCSV()"
[tooltip]="'dossier-overview.header-actions.download-csv' | translate"
icon="red:csv"
tooltipPosition="below"
></iqser-circle-button>
<iqser-circle-button
(action)="exportFilesAsCSV()"
[tooltip]="'dossier-overview.header-actions.download-csv' | translate"
icon="red:csv"
tooltipPosition="below"
></iqser-circle-button>
<iqser-circle-button
(action)="reanalyseDossier()"
*ngIf="permissionsService.displayReanalyseBtn(currentDossier) && analysisForced"
[tooltipClass]="'small ' + ((listingService.areSomeSelected$ | async) ? '' : 'warn')"
[tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all' | translate"
[type]="circleButtonTypes.warn"
icon="iqser:refresh"
tooltipPosition="below"
></iqser-circle-button>
<iqser-circle-button
(action)="reanalyseDossier()"
*ngIf="permissionsService.displayReanalyseBtn(dossier) && analysisForced"
[tooltipClass]="'small ' + ((listingService.areSomeSelected$ | async) ? '' : 'warn')"
[tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all' | translate"
[type]="circleButtonTypes.warn"
icon="iqser:refresh"
tooltipPosition="below"
></iqser-circle-button>
<iqser-circle-button
(action)="fileInput.click()"
[tooltip]="'dossier-overview.header-actions.upload-document' | translate"
[type]="circleButtonTypes.primary"
class="ml-14"
icon="iqser:upload"
tooltipPosition="below"
></iqser-circle-button>
</iqser-page-header>
<iqser-circle-button
(action)="fileInput.click()"
[tooltip]="'dossier-overview.header-actions.upload-document' | translate"
[type]="circleButtonTypes.primary"
class="ml-14"
icon="iqser:upload"
tooltipPosition="below"
></iqser-circle-button>
</iqser-page-header>
<div class="overlay-shadow"></div>
<div class="overlay-shadow"></div>
<div class="content-inner">
<div *ngIf="listingMode$ | async as mode" [class.extended]="collapsedDetails" class="content-container">
<iqser-table
(noDataAction)="fileInput.click()"
*ngIf="mode === listingModes.table"
[bulkActions]="bulkActions"
[hasScrollButton]="true"
[itemSize]="80"
[noDataButtonLabel]="'dossier-overview.no-data.action' | translate"
[noDataText]="'dossier-overview.no-data.title' | translate"
[noMatchText]="'dossier-overview.no-match.title' | translate"
[selectionEnabled]="true"
[showNoDataButton]="true"
[tableItemClasses]="{ disabled: disabledFn, 'last-opened': lastOpenedFn }"
noDataButtonIcon="iqser:upload"
noDataIcon="iqser:document"
></iqser-table>
<div class="content-inner">
<div *ngIf="listingMode$ | async as mode" [class.extended]="collapsedDetails" class="content-container">
<iqser-table
(noDataAction)="fileInput.click()"
*ngIf="mode === listingModes.table"
[bulkActions]="bulkActions"
[hasScrollButton]="true"
[itemSize]="80"
[noDataButtonLabel]="'dossier-overview.no-data.action' | translate"
[noDataText]="'dossier-overview.no-data.title' | translate"
[noMatchText]="'dossier-overview.no-match.title' | translate"
[selectionEnabled]="true"
[showNoDataButton]="true"
[tableItemClasses]="{ disabled: disabledFn, 'last-opened': lastOpenedFn }"
noDataButtonIcon="iqser:upload"
noDataIcon="iqser:document"
></iqser-table>
<iqser-workflow
(addElement)="fileInput.click()"
(noDataAction)="fileInput.click()"
*ngIf="mode === listingModes.workflow"
[config]="workflowConfig"
[itemClasses]="{ disabled: disabledFn }"
[itemTemplate]="workflowItemTemplate"
[noDataButtonLabel]="'dossier-overview.no-data.action' | translate"
[noDataText]="'dossier-overview.no-data.title' | translate"
[showNoDataButton]="true"
addElementColumn="UNASSIGNED"
addElementIcon="iqser:upload"
itemHeight="56px"
noDataButtonIcon="iqser:upload"
noDataIcon="iqser:document"
></iqser-workflow>
<iqser-workflow
(addElement)="fileInput.click()"
(noDataAction)="fileInput.click()"
*ngIf="mode === listingModes.workflow"
[config]="workflowConfig"
[itemClasses]="{ disabled: disabledFn }"
[itemTemplate]="workflowItemTemplate"
[noDataButtonLabel]="'dossier-overview.no-data.action' | translate"
[noDataText]="'dossier-overview.no-data.title' | translate"
[showNoDataButton]="true"
addElementColumn="UNASSIGNED"
addElementIcon="iqser:upload"
itemHeight="56px"
noDataButtonIcon="iqser:upload"
noDataIcon="iqser:document"
></iqser-workflow>
</div>
<div [class.collapsed]="collapsedDetails" class="right-container" iqserHasScrollbar>
<redaction-dossier-details
(openAssignDossierMembersDialog)="openAssignDossierMembersDialog()"
(openDossierDictionaryDialog)="openDossierDictionaryDialog()"
(toggleCollapse)="toggleCollapsedDetails()"
[dossierAttributes]="dossierAttributes"
></redaction-dossier-details>
</div>
</div>
</section>
<div [class.collapsed]="collapsedDetails" class="right-container" iqserHasScrollbar>
<redaction-dossier-details
(openAssignDossierMembersDialog)="openAssignDossierMembersDialog()"
(openDossierDictionaryDialog)="openDossierDictionaryDialog()"
(toggleCollapse)="toggleCollapsedDetails()"
[dossierAttributes]="dossierAttributes"
></redaction-dossier-details>
</div>
</div>
</section>
<ng-template #bulkActions>
<redaction-dossier-overview-bulk-actions
(reload)="bulkActionPerformed()"
[dossier]="dossier"
></redaction-dossier-overview-bulk-actions>
</ng-template>
</ng-container>
<ng-template #needsWorkFilterTemplate let-filter="filter">
<redaction-type-filter [filter]="filter"></redaction-type-filter>
@ -93,13 +102,6 @@
<input #fileInput (change)="uploadFiles($event.target['files'])" class="file-upload-input" multiple="true" type="file" />
<ng-template #bulkActions>
<redaction-dossier-overview-bulk-actions
(reload)="bulkActionPerformed()"
[dossier]="currentDossier"
></redaction-dossier-overview-bulk-actions>
</ng-template>
<ng-template #viewModeSelection>
<div *ngIf="listingMode$ | async as mode" class="view-mode-selection">
<div class="all-caps-label" translate="view-mode.view-as"></div>

View File

@ -17,12 +17,10 @@ import { FileDropOverlayService } from '@upload-download/services/file-drop-over
import { FileUploadModel } from '@upload-download/model/file-upload.model';
import { FileUploadService } from '@upload-download/services/file-upload.service';
import { StatusOverlayService } from '@upload-download/services/status-overlay.service';
import { TranslateService } from '@ngx-translate/core';
import * as moment from 'moment';
import { DossierDetailsComponent } from '../components/dossier-details/dossier-details.component';
import { UserService } from '@services/user.service';
import { timer } from 'rxjs';
import { take, tap } from 'rxjs/operators';
import { Observable, timer } from 'rxjs';
import { take, tap, withLatestFrom } from 'rxjs/operators';
import { convertFiles, Files, handleFileDrop } from '@utils/index';
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
import {
@ -44,7 +42,7 @@ import { DossierAttributesService } from '@shared/services/controller-wrappers/d
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { PermissionsService } from '@services/permissions.service';
import { RouterHistoryService } from '@services/router-history.service';
import { Router } from '@angular/router';
import { ActivatedRoute, Router } from '@angular/router';
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
import { ConfigService as AppConfigService } from '@services/config.service';
import { ConfigService } from '../config.service';
@ -66,7 +64,6 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
readonly currentUser = this._userService.currentUser;
readonly tableHeaderLabel = _('dossier-overview.table-header.title');
currentDossier = this._dossiersService.activeDossier;
collapsedDetails = false;
dossierAttributes: DossierAttributeWithValue[] = [];
tableColumnConfigs: readonly TableColumnConfig<File>[];
@ -74,8 +71,10 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
displayedInFileListAttributes: IFileAttributeConfig[] = [];
displayedAttributes: IFileAttributeConfig[] = [];
readonly workflowConfig: WorkflowConfig<File, FileStatus> = this._configService.workflowConfig(() => this.reloadDossiers());
readonly actionConfigs: readonly ActionConfig[] = this._configService.actionConfig;
@ViewChild(DossierDetailsComponent, { static: false }) private readonly _dossierDetailsComponent: DossierDetailsComponent;
readonly actionConfigs: readonly ActionConfig[];
readonly dossier$: Observable<Dossier>;
readonly dossierId: string;
currentDossier: Dossier;
private _lastScrolledIndex: number;
@ViewChild('needsWorkFilterTemplate', { read: TemplateRef, static: true })
private readonly _needsWorkFilterTemplate: TemplateRef<unknown>;
@ -94,7 +93,6 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
private readonly _dossierTemplatesService: DossierTemplatesService,
readonly routerHistoryService: RouterHistoryService,
private readonly _appConfigService: AppConfigService,
private readonly _translateService: TranslateService,
private readonly _dialogService: DossiersDialogService,
private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _fileUploadService: FileUploadService,
@ -104,8 +102,13 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
private readonly _fileAttributesService: FileAttributesService,
private readonly _configService: ConfigService,
private readonly _userPreferenceService: UserPreferenceService,
activatedRoute: ActivatedRoute,
) {
super(_injector);
this.dossierId = activatedRoute.snapshot.paramMap.get('dossierId');
this.actionConfigs = this._configService.actionConfig(this.dossierId);
this.dossier$ = this._dossiersService.getEntityChanged$(this.dossierId);
this.currentDossier = this._dossiersService.find(this.dossierId);
}
private _fileAttributeConfigs: IFileAttributeConfig[];
@ -219,20 +222,20 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
}
calculateData(): void {
if (!this._dossiersService.activeDossierId) {
if (!this.dossierId) {
return;
}
this._loadEntitiesFromState();
this._computeAllFilters();
this._dossierDetailsComponent?.calculateChartConfig();
this._changeDetectorRef.detectChanges();
this._changeDetectorRef.markForCheck();
}
@HostListener('drop', ['$event'])
onDrop(event: DragEvent): void {
handleFileDrop(event, this.currentDossier, this._uploadFiles.bind(this));
const currentDossier = this._dossiersService.find(this.dossierId);
handleFileDrop(event, currentDossier, this._uploadFiles.bind(this));
}
@HostListener('dragover', ['$event'])
@ -242,8 +245,8 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
}
exportFilesAsCSV() {
this.sortedDisplayedEntities$.pipe(take(1)).subscribe(entities => {
const fileName = this._dossiersService.activeDossier.dossierName + '.export.csv';
this.sortedDisplayedEntities$.pipe(take(1), withLatestFrom(this.dossier$)).subscribe(([entities, dossier]) => {
const fileName = dossier.dossierName + '.export.csv';
saveAsCSV(
fileName,
entities,
@ -279,12 +282,12 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
}
openAssignDossierMembersDialog(): void {
const data = { dossier: this.currentDossier, section: 'members' };
const data = { dossierId: this.dossierId, section: 'members' };
this._dialogService.openDialog('editDossier', null, data, async () => this.reloadDossiers());
}
openDossierDictionaryDialog() {
const data = { dossier: this.currentDossier, section: 'dossierDictionary' };
const data = { dossierId: this.dossierId, section: 'dossierDictionary' };
this._dialogService.openDialog('editDossier', null, data, async () => {
await this.reloadDossiers();
});
@ -298,7 +301,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
moment(file.lastUpdated).add(this._appConfigService.values.RECENT_PERIOD_IN_HOURS, 'hours').isAfter(moment());
private _loadEntitiesFromState() {
this.currentDossier = this._dossiersService.activeDossier;
this.currentDossier = this._dossiersService.find(this.dossierId);
if (this.currentDossier) {
this.entitiesService.setEntities([...this.currentDossier.files]);
}
@ -312,10 +315,6 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
}
private _computeAllFilters() {
if (!this.currentDossier) {
return;
}
const filterGroups = this._configService.filterGroups(
this.entitiesService.all,
this.listingMode,

View File

@ -1,7 +1,7 @@
<iqser-status-bar [configs]="statusConfig"></iqser-status-bar>
<div class="action-buttons" (longPress)="forceReanalysisAction($event)" redactionLongPress>
<div (longPress)="forceReanalysisAction($event)" class="action-buttons" redactionLongPress>
<iqser-circle-button
(action)="openEditDossierDialog($event, dossier)"
(action)="openEditDossierDialog($event, dossier.dossierId)"
*ngIf="currentUser.isManager"
[tooltip]="'dossier-listing.edit.action' | translate"
[type]="circleButtonTypes.dark"

View File

@ -55,9 +55,9 @@ export class DossiersListingActionsComponent {
this.analysisForced = !$event.touchEnd && this._userPreferenceService.areDevFeaturesEnabled;
}
openEditDossierDialog($event: MouseEvent, dossier: Dossier): void {
openEditDossierDialog($event: MouseEvent, dossierId: string): void {
this._dialogService.openDialog('editDossier', $event, {
dossier,
dossierId,
afterSave: () => this.actionPerformed.emit(),
});
}

View File

@ -38,7 +38,8 @@ import { DossiersService } from '@services/entity-services/dossiers.service';
})
export class DossiersListingScreenComponent
extends ListingComponent<Dossier>
implements OnInit, AfterViewInit, OnDestroy, OnAttach, OnDetach {
implements OnInit, AfterViewInit, OnDestroy, OnAttach, OnDetach
{
readonly currentUser = this._userService.currentUser;
readonly tableColumnConfigs = this._configService.tableConfig;
readonly tableHeaderLabel = _('dossier-listing.table-header.title');
@ -111,7 +112,7 @@ export class DossiersListingScreenComponent
await this._router.navigate([`/main/dossiers/${addResponse.dossier.id}`]);
if (addResponse.addMembers) {
this._dialogService.openDialog('editDossier', null, {
dossier: addResponse.dossier,
dossierId: addResponse.dossier.dossierId,
section: 'members',
});
}

View File

@ -70,6 +70,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
excludePages = false;
@ViewChild(PdfViewerComponent) readonly viewerComponent: PdfViewerComponent;
@ViewChild('fileActions') fileActions: FileActionsComponent;
readonly dossierId: string;
private _instance: WebViewerInstance;
private _lastPage: string;
private _reloadFileOnReanalysis = false;
@ -103,6 +104,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
private readonly _translateService: TranslateService,
) {
super();
this.dossierId = _activatedRoute.snapshot.paramMap.get('dossierId');
this._loadingService.start();
document.documentElement.addEventListener('fullscreenchange', () => {
if (!document.fullscreenElement) {
@ -243,9 +245,9 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
super.ngOnDestroy();
}
async ngOnAttach(previousRoute: ActivatedRouteSnapshot): Promise<void> {
async ngOnAttach(previousRoute: ActivatedRouteSnapshot): Promise<boolean> {
if (!this.appStateService.activeFile.canBeOpened) {
return this.dossiersService.goToActiveDossier();
return this._router.navigate([this.dossiersService.find(this.dossierId)?.routerLink]);
}
await this.ngOnInit();

View File

@ -5,6 +5,7 @@ import { OverlayRef } from '@angular/cdk/overlay';
import { StatusOverlayService } from '../services/status-overlay.service';
import { handleFileDrop } from '@utils/file-drop-utils';
import { DossiersService } from '@services/entity-services/dossiers.service';
import { ActivatedRoute } from '@angular/router';
@Component({
selector: 'redaction-file-drop',
@ -18,6 +19,7 @@ export class FileDropComponent {
private readonly _dossiersService: DossiersService,
private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _statusOverlayService: StatusOverlayService,
private readonly _activatedRoute: ActivatedRoute,
) {}
close() {
@ -33,7 +35,9 @@ export class FileDropComponent {
@HostListener('drop', ['$event'])
onDrop(event: DragEvent) {
handleFileDrop(event, this._dossiersService.activeDossier, this.uploadFiles.bind(this));
const dossierId = this._activatedRoute.snapshot.paramMap.get('dossierId');
console.log(dossierId);
handleFileDrop(event, this._dossiersService.find(dossierId), this.uploadFiles.bind(this));
}
@HostListener('dragover', ['$event'])
@ -48,6 +52,6 @@ export class FileDropComponent {
this._statusOverlayService.openUploadStatusOverlay();
}
this._dialogRef.detach();
this._changeDetectorRef.detectChanges();
this._changeDetectorRef.markForCheck();
}
}

View File

@ -29,7 +29,7 @@ export class AppStateGuard implements CanActivate {
}
if (this._userService.currentUser.isUser) {
await this._appStateService.loadAllDossiersIfNecessary();
await this._dossiersService.loadAllIfEmpty();
}
const { dossierId, fileId, dossierTemplateId, type } = route.params;

View File

@ -1,4 +1,4 @@
import { IListable, List } from '@iqser/common-ui';
import { Entity, List } from '@iqser/common-ui';
import { StatusSorter } from '../shared';
import { FileStatus, FileStatuses } from './types';
import { IFile } from './file';
@ -12,7 +12,7 @@ const processingStatuses: List<FileStatus> = [
FileStatuses.PROCESSING,
] as const;
export class File implements IFile, IListable {
export class File extends Entity<IFile> implements IFile {
readonly added?: string;
readonly allManualRedactionsApplied: boolean;
readonly analysisDuration?: number;
@ -64,6 +64,7 @@ export class File implements IFile, IListable {
readonly canBeOCRed: boolean;
constructor(file: IFile, readonly reviewerName: string, fileAttributesConfig?: IFileAttributesConfig) {
super(file);
this.added = file.added;
this.allManualRedactionsApplied = !!file.allManualRedactionsApplied;
this.analysisDuration = file.analysisDuration;