Pull request #296: New state concept
Merge in RED/ui from new-state-concept to master * commit 'fe9d3816f33c22cb5467ebe4a94eeeee863a5f0f': update common ui move delete dossier to dossiers service fix merge fix init order fix some rebase errors fix search screen not showing results move create or update dossier to dossiers service move active dossier to dossiers service move some methods to dossiers service move stats to dossiers service remove dossier template id from file make dossier files readonly fix some errors update types / undefineds
This commit is contained in:
commit
2118a59eb0
@ -3,25 +3,6 @@
|
||||
<div class="top-bar">
|
||||
<div *ngIf="!currentUser.isUser" class="menu-placeholder"></div>
|
||||
|
||||
<div *ngIf="currentUser.isUser" class="menu visible-lt-lg">
|
||||
<button [matMenuTriggerFor]="menuNav" mat-flat-button>
|
||||
<mat-icon svgIcon="red:menu"></mat-icon>
|
||||
</button>
|
||||
<mat-menu #menuNav="matMenu">
|
||||
<button mat-menu-item routerLink="/main/dossiers" translate="top-bar.navigation-items.dossiers"></button>
|
||||
<button *ngIf="appStateService.activeDossier" [routerLink]="'/main/dossiers/' + appStateService.activeDossierId" mat-menu-item>
|
||||
{{ appStateService.activeDossier.dossierName }}
|
||||
</button>
|
||||
<button
|
||||
*ngIf="appStateService.activeFile"
|
||||
[routerLink]="'/main/dossiers/' + appStateService.activeDossierId + '/file/' + appStateService.activeFile.fileId"
|
||||
mat-menu-item
|
||||
>
|
||||
{{ appStateService.activeFile.filename }}
|
||||
</button>
|
||||
</mat-menu>
|
||||
</div>
|
||||
|
||||
<div *ngIf="currentUser.isUser" class="menu flex-2 visible-lg breadcrumbs-container">
|
||||
<a *ngIf="(isDossiersView$ | async) === false" class="breadcrumb back" redactionNavigateLastDossiersScreen>
|
||||
<mat-icon svgIcon="iqser:expand"></mat-icon>
|
||||
@ -37,28 +18,26 @@
|
||||
translate="top-bar.navigation-items.dossiers"
|
||||
></a>
|
||||
|
||||
<mat-icon *ngIf="appStateService.activeDossier" svgIcon="iqser:arrow-right"></mat-icon>
|
||||
<ng-container *ngIf="dossiersService.activeDossier$ | async as dossier">
|
||||
<mat-icon svgIcon="iqser:arrow-right"></mat-icon>
|
||||
|
||||
<a
|
||||
*ngIf="appStateService.activeDossier"
|
||||
[routerLinkActiveOptions]="{ exact: true }"
|
||||
[routerLink]="'/main/dossiers/' + appStateService.activeDossierId"
|
||||
class="breadcrumb"
|
||||
routerLinkActive="active"
|
||||
>
|
||||
{{ appStateService.activeDossier.dossierName }}
|
||||
</a>
|
||||
<a
|
||||
[routerLinkActiveOptions]="{ exact: true }"
|
||||
[routerLink]="dossier.routerLink"
|
||||
class="breadcrumb"
|
||||
routerLinkActive="active"
|
||||
>
|
||||
{{ dossier.dossierName }}
|
||||
</a>
|
||||
</ng-container>
|
||||
|
||||
<mat-icon *ngIf="appStateService.activeFile" svgIcon="iqser:arrow-right"></mat-icon>
|
||||
<ng-container *ngIf="appStateService.activeFile as activeFile">
|
||||
<mat-icon svgIcon="iqser:arrow-right"></mat-icon>
|
||||
|
||||
<a
|
||||
*ngIf="appStateService.activeFile"
|
||||
[routerLink]="'/main/dossiers/' + appStateService.activeDossierId + '/file/' + appStateService.activeFile.fileId"
|
||||
class="breadcrumb"
|
||||
routerLinkActive="active"
|
||||
>
|
||||
{{ appStateService.activeFile.filename }}
|
||||
</a>
|
||||
<a [routerLink]="activeFile.routerLink" class="breadcrumb" routerLinkActive="active">
|
||||
{{ activeFile.filename }}
|
||||
</a>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { SpotlightSearchAction } from '@components/spotlight-search/spotlight-search-action';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { distinctUntilChanged, filter, map, startWith } from 'rxjs/operators';
|
||||
import { DossiersService } from '../../modules/dossier/services/dossiers.service';
|
||||
|
||||
interface MenuItem {
|
||||
readonly name: string;
|
||||
@ -54,8 +55,8 @@ export class BaseScreenComponent {
|
||||
{
|
||||
text: this._translateService.instant('search.this-dossier'),
|
||||
icon: 'red:enter',
|
||||
hide: (): boolean => !this.appStateService.activeDossier,
|
||||
action: (query): void => this._search(query, this.appStateService.activeDossier.id)
|
||||
hide: (): boolean => !this.dossiersService.activeDossier,
|
||||
action: (query): void => this._search(query, this.dossiersService.activeDossierId)
|
||||
},
|
||||
{
|
||||
text: this._translateService.instant('search.entire-platform'),
|
||||
@ -74,6 +75,7 @@ export class BaseScreenComponent {
|
||||
|
||||
constructor(
|
||||
readonly appStateService: AppStateService,
|
||||
readonly dossiersService: DossiersService,
|
||||
readonly userService: UserService,
|
||||
readonly userPreferenceService: UserPreferenceService,
|
||||
readonly titleService: Title,
|
||||
|
||||
@ -8,6 +8,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { NotificationType, NotificationTypeEnum } from '@models/notification-types';
|
||||
import { notificationsTranslations } from '../../translations/notifications-translations';
|
||||
import { DossiersService } from '../../modules/dossier/services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-notifications',
|
||||
@ -23,6 +24,7 @@ export class NotificationsComponent {
|
||||
private readonly _userService: UserService,
|
||||
private readonly _notificationControllerService: NotificationControllerService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _datePipe: DatePipe
|
||||
) {
|
||||
this._notificationControllerService.getNotifications(false).subscribe((response: NotificationResponse) => {
|
||||
@ -96,12 +98,12 @@ export class NotificationsComponent {
|
||||
}
|
||||
|
||||
private _getDossierName(dossierId: string | undefined) {
|
||||
const dossier = this._appStateService.getDossierById(dossierId);
|
||||
const dossier = this._dossiersService.find(dossierId);
|
||||
return dossier?.dossierName || this._translateService.instant(_('dossier'));
|
||||
}
|
||||
|
||||
private _getFileName(dossierId: string | undefined, fileId: string | undefined) {
|
||||
const file = this._appStateService.getFileById(dossierId, fileId);
|
||||
const file = this._dossiersService.find(dossierId, fileId);
|
||||
return file?.filename || this._translateService.instant(_('file'));
|
||||
}
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ export class Audit implements IAudit, IListable {
|
||||
readonly details?: unknown;
|
||||
readonly message?: string;
|
||||
readonly objectId?: string;
|
||||
readonly recordDate?: string;
|
||||
readonly recordDate: string;
|
||||
readonly userId?: string;
|
||||
|
||||
constructor(audit: IAudit) {
|
||||
@ -20,7 +20,7 @@ export class Audit implements IAudit, IListable {
|
||||
this.userId = audit.userId;
|
||||
}
|
||||
|
||||
get id() {
|
||||
get id(): string {
|
||||
return this.recordDate;
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@ export class Dictionary implements IDictionary, IListable {
|
||||
readonly entries?: List;
|
||||
readonly hexColor?: string;
|
||||
readonly hint: boolean;
|
||||
readonly label?: string;
|
||||
readonly label: string;
|
||||
readonly rank?: number;
|
||||
readonly recommendation: boolean;
|
||||
|
||||
|
||||
@ -11,17 +11,17 @@ const processingStatuses: List<FileStatus> = [
|
||||
] as const;
|
||||
|
||||
export class File implements IFile, IListable {
|
||||
readonly added: string;
|
||||
readonly added?: string;
|
||||
readonly allManualRedactionsApplied: boolean;
|
||||
readonly analysisDuration: number;
|
||||
readonly analysisDuration?: number;
|
||||
readonly analysisRequired: boolean;
|
||||
readonly approvalDate: string;
|
||||
readonly currentReviewer: string;
|
||||
readonly dictionaryVersion: number;
|
||||
readonly dossierDictionaryVersion: number;
|
||||
readonly approvalDate?: string;
|
||||
readonly currentReviewer?: string;
|
||||
readonly dictionaryVersion?: number;
|
||||
readonly dossierDictionaryVersion?: number;
|
||||
readonly dossierId: string;
|
||||
readonly excluded: boolean;
|
||||
readonly fileAttributes: FileAttributes;
|
||||
readonly fileAttributes?: FileAttributes;
|
||||
readonly fileId: string;
|
||||
readonly filename: string;
|
||||
readonly hasAnnotationComments: boolean;
|
||||
@ -29,22 +29,21 @@ export class File implements IFile, IListable {
|
||||
readonly hasImages: boolean;
|
||||
readonly hasRedactions: boolean;
|
||||
readonly hasUpdates: boolean;
|
||||
readonly lastOCRTime: string;
|
||||
readonly lastProcessed: string;
|
||||
readonly lastReviewer: string;
|
||||
readonly lastUpdated: string;
|
||||
readonly lastUploaded: string;
|
||||
readonly legalBasisVersion: number;
|
||||
readonly numberOfAnalyses: number;
|
||||
readonly numberOfPages: number;
|
||||
readonly rulesVersion: number;
|
||||
readonly lastOCRTime?: string;
|
||||
readonly lastProcessed?: string;
|
||||
readonly lastReviewer?: string;
|
||||
readonly lastUpdated?: string;
|
||||
readonly lastUploaded?: string;
|
||||
readonly legalBasisVersion?: number;
|
||||
readonly numberOfAnalyses?: number;
|
||||
readonly numberOfPages?: number;
|
||||
readonly rulesVersion?: number;
|
||||
readonly status: FileStatus;
|
||||
readonly uploader: string;
|
||||
readonly excludedPages: number[];
|
||||
readonly uploader?: string;
|
||||
readonly excludedPages?: number[];
|
||||
readonly hasSuggestions: boolean;
|
||||
readonly dossierTemplateId: string;
|
||||
|
||||
primaryAttribute: string;
|
||||
readonly primaryAttribute: string;
|
||||
lastOpened: boolean;
|
||||
readonly statusSort: number;
|
||||
readonly cacheIdentifier: string;
|
||||
@ -62,25 +61,25 @@ export class File implements IFile, IListable {
|
||||
readonly isWorkable: boolean;
|
||||
readonly canBeOCRed: boolean;
|
||||
|
||||
constructor(file: IFile, public reviewerName: string, fileAttributesConfig?: FileAttributesConfig) {
|
||||
constructor(file: IFile, readonly reviewerName: string, fileAttributesConfig?: FileAttributesConfig) {
|
||||
this.added = file.added;
|
||||
this.allManualRedactionsApplied = file.allManualRedactionsApplied;
|
||||
this.allManualRedactionsApplied = !!file.allManualRedactionsApplied;
|
||||
this.analysisDuration = file.analysisDuration;
|
||||
this.analysisRequired = file.analysisRequired && !file.excluded;
|
||||
this.analysisRequired = !!file.analysisRequired && !file.excluded;
|
||||
this.approvalDate = file.approvalDate;
|
||||
this.currentReviewer = file.currentReviewer;
|
||||
this.dictionaryVersion = file.dictionaryVersion;
|
||||
this.dossierDictionaryVersion = file.dossierDictionaryVersion;
|
||||
this.dossierId = file.dossierId;
|
||||
this.excluded = file.excluded;
|
||||
this.excluded = !!file.excluded;
|
||||
this.fileAttributes = file.fileAttributes;
|
||||
this.fileId = file.fileId;
|
||||
this.filename = file.filename;
|
||||
this.hasAnnotationComments = file.hasAnnotationComments;
|
||||
this.hasHints = file.hasHints;
|
||||
this.hasImages = file.hasImages;
|
||||
this.hasRedactions = file.hasRedactions;
|
||||
this.hasUpdates = file.hasUpdates;
|
||||
this.hasAnnotationComments = !!file.hasAnnotationComments;
|
||||
this.hasHints = !!file.hasHints;
|
||||
this.hasImages = !!file.hasImages;
|
||||
this.hasRedactions = !!file.hasRedactions;
|
||||
this.hasUpdates = !!file.hasUpdates;
|
||||
this.lastOCRTime = file.lastOCRTime;
|
||||
this.lastProcessed = file.lastProcessed;
|
||||
this.lastReviewer = file.lastReviewer;
|
||||
@ -94,11 +93,12 @@ export class File implements IFile, IListable {
|
||||
this.rulesVersion = file.rulesVersion;
|
||||
this.uploader = file.uploader;
|
||||
this.excludedPages = file.excludedPages;
|
||||
this.hasSuggestions = file.hasSuggestions;
|
||||
this.dossierTemplateId = file.dossierTemplateId;
|
||||
this.hasSuggestions = !!file.hasSuggestions;
|
||||
|
||||
this.statusSort = StatusSorter[this.status];
|
||||
this.cacheIdentifier = btoa(this.lastUploaded + this.lastOCRTime);
|
||||
if (this.lastUpdated && this.lastOCRTime) {
|
||||
this.cacheIdentifier = btoa(this.lastUploaded + this.lastOCRTime);
|
||||
}
|
||||
this.hintsOnly = this.hasHints && !this.hasRedactions;
|
||||
this.hasNone = !this.hasRedactions && !this.hasHints && !this.hasSuggestions;
|
||||
this.isUnassigned = !this.currentReviewer;
|
||||
|
||||
@ -5,8 +5,8 @@ import { KeycloakProfile } from 'keycloak-js';
|
||||
export class User implements IUser, IListable {
|
||||
readonly email: string;
|
||||
readonly username: string;
|
||||
readonly firstName: string;
|
||||
readonly lastName: string;
|
||||
readonly firstName?: string;
|
||||
readonly lastName?: string;
|
||||
readonly name: string;
|
||||
readonly searchKey: string;
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { UserControllerService } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { LoadingService } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { User } from '@models/user';
|
||||
import { DossiersService } from '../../../dossier/services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-confirm-delete-users-dialog',
|
||||
@ -20,13 +20,13 @@ export class ConfirmDeleteUsersDialogComponent {
|
||||
dossiersCount: number;
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _userControllerService: UserControllerService,
|
||||
readonly dialogRef: MatDialogRef<ConfirmDeleteUsersDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) readonly users: User[]
|
||||
) {
|
||||
this.dossiersCount = this._appStateService.allDossiers.filter(dw => {
|
||||
this.dossiersCount = this._dossiersService.all.filter(dw => {
|
||||
for (const user of this.users) {
|
||||
if (dw.memberIds.indexOf(user.id) !== -1) {
|
||||
return true;
|
||||
|
||||
@ -5,6 +5,7 @@ import { DossiersDialogService } from '../../services/dossiers-dialog.service';
|
||||
import { AutoUnsubscribe } from '@iqser/common-ui';
|
||||
import { File } from '@models/file/file';
|
||||
import { FileAttributesService } from '../../services/file-attributes.service';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-document-info',
|
||||
@ -13,12 +14,13 @@ import { FileAttributesService } from '../../services/file-attributes.service';
|
||||
})
|
||||
export class DocumentInfoComponent extends AutoUnsubscribe implements OnInit {
|
||||
@Input() file: File;
|
||||
@Output() closeDocumentInfoView = new EventEmitter();
|
||||
@Output() readonly closeDocumentInfoView = new EventEmitter();
|
||||
|
||||
fileAttributesConfig: FileAttributesConfig;
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _fileAttributesService: FileAttributesService,
|
||||
private readonly _dialogService: DossiersDialogService
|
||||
) {
|
||||
@ -26,7 +28,7 @@ export class DocumentInfoComponent extends AutoUnsubscribe implements OnInit {
|
||||
}
|
||||
|
||||
get dossier() {
|
||||
return this._appStateService.getDossierById(this.file.dossierId);
|
||||
return this._dossiersService.find(this.file.dossierId);
|
||||
}
|
||||
|
||||
get dossierTemplateName(): string {
|
||||
@ -34,10 +36,10 @@ export class DocumentInfoComponent extends AutoUnsubscribe implements OnInit {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.fileAttributesConfig = this._fileAttributesService.getFileAttributeConfig(this.file.dossierTemplateId);
|
||||
this.fileAttributesConfig = this._fileAttributesService.getFileAttributeConfig(this.dossier.dossierTemplateId);
|
||||
|
||||
this.addSubscription = this._appStateService.dossierTemplateChanged$.subscribe(() => {
|
||||
this.fileAttributesConfig = this._fileAttributesService.getFileAttributeConfig(this.file.dossierTemplateId);
|
||||
this.fileAttributesConfig = this._fileAttributesService.getFileAttributeConfig(this.dossier.dossierTemplateId);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -1,9 +1,10 @@
|
||||
import {Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges} from '@angular/core';
|
||||
import {ViewedPages, ViewedPagesControllerService} from '@redaction/red-ui-http';
|
||||
import {AppStateService} from '@state/app-state.service';
|
||||
import {PermissionsService} from '@services/permissions.service';
|
||||
import {ConfigService} from '@services/config.service';
|
||||
import {Subscription} from 'rxjs';
|
||||
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges } from '@angular/core';
|
||||
import { ViewedPages, ViewedPagesControllerService } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { ConfigService } from '@services/config.service';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-page-indicator',
|
||||
@ -16,7 +17,7 @@ export class PageIndicatorComponent implements OnChanges, OnInit, OnDestroy {
|
||||
@Input() viewedPages: ViewedPages;
|
||||
@Input() activeSelection = false;
|
||||
|
||||
@Output() pageSelected = new EventEmitter<number>();
|
||||
@Output() readonly pageSelected = new EventEmitter<number>();
|
||||
|
||||
pageReadTimeout: number = null;
|
||||
canMarkPagesAsViewed: boolean;
|
||||
@ -25,10 +26,10 @@ export class PageIndicatorComponent implements OnChanges, OnInit, OnDestroy {
|
||||
constructor(
|
||||
private readonly _viewedPagesControllerService: ViewedPagesControllerService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _configService: ConfigService,
|
||||
private readonly _permissionService: PermissionsService
|
||||
) {
|
||||
}
|
||||
) {}
|
||||
|
||||
get read() {
|
||||
return this.viewedPages?.pages?.findIndex(p => p.page === this.number) >= 0;
|
||||
@ -96,15 +97,15 @@ export class PageIndicatorComponent implements OnChanges, OnInit, OnDestroy {
|
||||
|
||||
private _markPageRead() {
|
||||
this._viewedPagesControllerService
|
||||
.addPage({page: this.number}, this._appStateService.activeDossierId, this._appStateService.activeFileId)
|
||||
.addPage({ page: this.number }, this._dossiersService.activeDossierId, this._appStateService.activeFileId)
|
||||
.subscribe(() => {
|
||||
this.viewedPages?.pages?.push({page: this.number, fileId: this._appStateService.activeFileId});
|
||||
this.viewedPages?.pages?.push({ page: this.number, fileId: this._appStateService.activeFileId });
|
||||
});
|
||||
}
|
||||
|
||||
private _markPageUnread() {
|
||||
this._viewedPagesControllerService
|
||||
.removePage(this._appStateService.activeDossierId, this._appStateService.activeFileId, this.number)
|
||||
.removePage(this._dossiersService.activeDossierId, this._appStateService.activeFileId, this.number)
|
||||
.subscribe(() => {
|
||||
this.viewedPages?.pages?.splice(
|
||||
this.viewedPages?.pages?.findIndex(p => p.page === this.number),
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { IDossier } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { DossierRequest, IDossier } from '@redaction/red-ui-http';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { Toaster } from '@iqser/common-ui';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-team-members-manager',
|
||||
@ -28,7 +28,7 @@ export class TeamMembersManagerComponent implements OnInit {
|
||||
readonly userService: UserService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _appStateService: AppStateService
|
||||
private readonly _dossiersService: DossiersService
|
||||
) {}
|
||||
|
||||
get selectedOwnerId(): string {
|
||||
@ -52,22 +52,17 @@ export class TeamMembersManagerComponent implements OnInit {
|
||||
}
|
||||
|
||||
async saveMembers() {
|
||||
let result;
|
||||
try {
|
||||
const ownerId = this.selectedOwnerId;
|
||||
const memberIds = this.selectedMembersList;
|
||||
const approverIds = this.selectedApproversList;
|
||||
const dw = {
|
||||
...this.dossier,
|
||||
memberIds,
|
||||
approverIds,
|
||||
ownerId
|
||||
};
|
||||
result = await this._appStateService.createOrUpdateDossier(dw);
|
||||
const dossier = {
|
||||
...this.dossier,
|
||||
memberIds: this.selectedMembersList,
|
||||
approverIds: this.selectedApproversList,
|
||||
ownerId: this.selectedOwnerId
|
||||
} as DossierRequest;
|
||||
|
||||
const result = await this._dossiersService.createOrUpdate(dossier).toPromise();
|
||||
if (result) {
|
||||
this.save.emit(result);
|
||||
this._updateChanged();
|
||||
} catch (error) {
|
||||
this._toaster.error(_('error.http.generic'), { params: error });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -83,7 +83,7 @@
|
||||
</button>
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="saveDossierAndAddMembers()"
|
||||
(action)="saveDossier(true)"
|
||||
[disabled]="disabled"
|
||||
[label]="'add-dossier-dialog.actions.save-and-add-members' | translate"
|
||||
[type]="iconButtonTypes.dark"
|
||||
|
||||
@ -1,11 +1,18 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {MatDialogRef} from '@angular/material/dialog';
|
||||
import {DossierRequest, DownloadFileType, IDossierTemplate, ReportTemplate, ReportTemplateControllerService} from '@redaction/red-ui-http';
|
||||
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
|
||||
import {AppStateService} from '@state/app-state.service';
|
||||
import { Component } from '@angular/core';
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import {
|
||||
DossierRequest,
|
||||
DownloadFileType,
|
||||
IDossierTemplate,
|
||||
ReportTemplate,
|
||||
ReportTemplateControllerService
|
||||
} from '@redaction/red-ui-http';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import * as moment from 'moment';
|
||||
import {downloadTypesTranslations} from '../../../../translations/download-types-translations';
|
||||
import {IconButtonTypes} from '@iqser/common-ui';
|
||||
import { downloadTypesTranslations } from '../../../../translations/download-types-translations';
|
||||
import { IconButtonTypes } from '@iqser/common-ui';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './add-dossier-dialog.component.html',
|
||||
@ -22,10 +29,10 @@ export class AddDossierDialogComponent {
|
||||
}));
|
||||
dossierTemplates: IDossierTemplate[];
|
||||
availableReportTypes = [];
|
||||
reportTemplateValueMapper = (reportTemplate: ReportTemplate) => reportTemplate.templateId;
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _reportTemplateController: ReportTemplateControllerService,
|
||||
readonly dialogRef: MatDialogRef<AddDossierDialogComponent>
|
||||
@ -45,7 +52,7 @@ export class AddDossierDialogComponent {
|
||||
validators: control =>
|
||||
control.value.reportTemplateIds?.length > 0 || control.value.downloadFileTypes?.length > 0
|
||||
? null
|
||||
: {downloadPackage: true}
|
||||
: { downloadPackage: true }
|
||||
}
|
||||
);
|
||||
}
|
||||
@ -66,18 +73,12 @@ export class AddDossierDialogComponent {
|
||||
return this.dossierForm.invalid;
|
||||
}
|
||||
|
||||
async saveDossier() {
|
||||
const savedDossier = await this._appStateService.createOrUpdateDossier(this._formToObject());
|
||||
if (savedDossier) {
|
||||
this.dialogRef.close({dossier: savedDossier});
|
||||
}
|
||||
}
|
||||
reportTemplateValueMapper = (reportTemplate: ReportTemplate) => reportTemplate.templateId;
|
||||
|
||||
async saveDossierAndAddMembers() {
|
||||
const dossier: DossierRequest = this._formToObject();
|
||||
const savedDossier = await this._appStateService.createOrUpdateDossier(dossier);
|
||||
async saveDossier(addMembers = false) {
|
||||
const savedDossier = await this._dossiersService.createOrUpdate(this._formToObject()).toPromise();
|
||||
if (savedDossier) {
|
||||
this.dialogRef.close({addMembers: true, dossier: savedDossier});
|
||||
this.dialogRef.close({ dossier: savedDossier, addMembers });
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,7 +95,7 @@ export class AddDossierDialogComponent {
|
||||
downloadFileTypes: dossierTemplate.downloadFileTypes,
|
||||
reportTemplateIds: [] // TODO DEFAULT
|
||||
},
|
||||
{emitEvent: false}
|
||||
{ emitEvent: false }
|
||||
);
|
||||
} else {
|
||||
this.availableReportTypes = [];
|
||||
@ -103,7 +104,7 @@ export class AddDossierDialogComponent {
|
||||
downloadFileTypes: [],
|
||||
reportTemplateIds: []
|
||||
},
|
||||
{emitEvent: false}
|
||||
{ emitEvent: false }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ import { File } from '@models/file/file';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { FilesService } from '../../services/files.service';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
class DialogData {
|
||||
mode: 'approver' | 'reviewer';
|
||||
@ -29,6 +30,7 @@ export class AssignReviewerApproverDialogComponent {
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _filesService: FilesService,
|
||||
private readonly _dialogRef: MatDialogRef<AssignReviewerApproverDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: DialogData
|
||||
@ -42,8 +44,8 @@ export class AssignReviewerApproverDialogComponent {
|
||||
|
||||
get singleUsersSelectOptions() {
|
||||
return this.data.mode === 'approver'
|
||||
? this._appStateService.activeDossier.approverIds
|
||||
: this._appStateService.activeDossier.memberIds;
|
||||
? this._dossiersService.activeDossier.approverIds
|
||||
: this._dossiersService.activeDossier.memberIds;
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
@ -72,7 +74,7 @@ export class AssignReviewerApproverDialogComponent {
|
||||
await this._filesService
|
||||
.setReviewerFor(
|
||||
this.data.files.map(f => f.fileId),
|
||||
this._appStateService.activeDossierId,
|
||||
this._dossiersService.activeDossierId,
|
||||
selectedUser
|
||||
)
|
||||
.toPromise();
|
||||
@ -81,7 +83,7 @@ export class AssignReviewerApproverDialogComponent {
|
||||
.setUnderApprovalFor(
|
||||
this.data.files.map(f => f.fileId),
|
||||
selectedUser,
|
||||
this._appStateService.activeDossierId
|
||||
this._dossiersService.activeDossierId
|
||||
)
|
||||
.toPromise();
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { LegalBasisMappingControllerService } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
export interface LegalBasisOption {
|
||||
label?: string;
|
||||
@ -27,6 +28,7 @@ export class ChangeLegalBasisDialogComponent implements OnInit {
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _legalBasisMappingControllerService: LegalBasisMappingControllerService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
public dialogRef: MatDialogRef<ChangeLegalBasisDialogComponent>,
|
||||
@ -45,7 +47,7 @@ export class ChangeLegalBasisDialogComponent implements OnInit {
|
||||
comment: this.isDocumentAdmin ? [null] : [null, Validators.required]
|
||||
});
|
||||
const data = await this._legalBasisMappingControllerService
|
||||
.getLegalBasisMapping(this._appStateService.activeDossier.dossierTemplateId)
|
||||
.getLegalBasisMapping(this._dossiersService.activeDossier.dossierTemplateId)
|
||||
.toPromise();
|
||||
|
||||
this.legalOptions = data
|
||||
|
||||
@ -5,6 +5,7 @@ import { AppStateService } from '@state/app-state.service';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
import { FileAttributesService } from '../../services/file-attributes.service';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './document-info-dialog.component.html',
|
||||
@ -15,17 +16,18 @@ export class DocumentInfoDialogComponent implements OnInit {
|
||||
file: IFile;
|
||||
attributes: IFileAttributeConfig[];
|
||||
|
||||
private _dossier: Dossier;
|
||||
private readonly _dossier: Dossier;
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _fileAttributesService: FileAttributesService,
|
||||
public dialogRef: MatDialogRef<DocumentInfoDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: IFile
|
||||
) {
|
||||
this.file = this.data;
|
||||
this._dossier = this._appStateService.getDossierById(this.file.dossierId);
|
||||
this._dossier = this._dossiersService.find(this.file.dossierId);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
@ -8,6 +7,7 @@ import { DictionaryService } from '@shared/services/dictionary.service';
|
||||
import { FormBuilder } from '@angular/forms';
|
||||
import { CircleButtonTypes, LoadingService } from '@iqser/common-ui';
|
||||
import { IDictionary } from '@redaction/red-ui-http';
|
||||
import { DossiersService } from '../../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-dossier-dictionary',
|
||||
@ -20,10 +20,10 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
|
||||
canEdit = false;
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
|
||||
@ViewChild(DictionaryManagerComponent, { static: false }) private _dictionaryManager: DictionaryManagerComponent;
|
||||
@ViewChild(DictionaryManagerComponent, { static: false }) private readonly _dictionaryManager: DictionaryManagerComponent;
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
@ -42,7 +42,7 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
|
||||
|
||||
async ngOnInit() {
|
||||
this._loadingService.start();
|
||||
await this._appStateService.updateDossierDictionary(this.dossier.dossierTemplateId, this.dossier.id);
|
||||
await this._dossiersService.updateDossierDictionary(this.dossier.dossierTemplateId, this.dossier.id);
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
@ -51,7 +51,7 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
|
||||
await this._dictionaryService
|
||||
.updateType(typeValue, this.dossier.dossierTemplateId, 'dossier_redaction', this.dossier.id)
|
||||
.toPromise();
|
||||
await this._appStateService.updateDossierDictionary(this.dossier.dossierTemplateId, this.dossier.id);
|
||||
await this._dossiersService.updateDossierDictionary(this.dossier.dossierTemplateId, this.dossier.id);
|
||||
this.updateDossier.emit();
|
||||
}
|
||||
|
||||
@ -66,7 +66,7 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
|
||||
false
|
||||
)
|
||||
.toPromise();
|
||||
await this._appStateService.updateDossierDictionary(this.dossier.dossierTemplateId, this.dossier.id);
|
||||
await this._dossiersService.updateDossierDictionary(this.dossier.dossierTemplateId, this.dossier.id);
|
||||
this.updateDossier.emit();
|
||||
}
|
||||
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { DownloadFileType, ReportTemplate, ReportTemplateControllerService } from '@redaction/red-ui-http';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
import { EditDossierSectionInterface } from '../edit-dossier-section.interface';
|
||||
import { downloadTypesTranslations } from '../../../../../translations/download-types-translations';
|
||||
import { DossiersService } from '../../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-dossier-download-package',
|
||||
@ -23,7 +23,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
|
||||
@Output() readonly updateDossier = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _reportTemplateController: ReportTemplateControllerService,
|
||||
private readonly _formBuilder: FormBuilder
|
||||
) {}
|
||||
@ -87,7 +87,7 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
|
||||
downloadFileTypes: this.dossierForm.get('downloadFileTypes').value,
|
||||
reportTemplateIds: this.dossierForm.get('reportTemplateIds').value
|
||||
};
|
||||
await this._appStateService.createOrUpdateDossier(dossier);
|
||||
await this._dossiersService.createOrUpdate(dossier).toPromise();
|
||||
this.updateDossier.emit();
|
||||
}
|
||||
|
||||
|
||||
@ -12,6 +12,7 @@ import { EditDossierAttributesComponent } from './attributes/edit-dossier-attrib
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { EditDossierDeletedDocumentsComponent } from './deleted-documents/edit-dossier-deleted-documents.component';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
type Section = 'dossierInfo' | 'downloadPackage' | 'dossierDictionary' | 'members' | 'dossierAttributes' | 'deletedDocuments';
|
||||
|
||||
@ -34,6 +35,7 @@ export class EditDossierDialogComponent {
|
||||
constructor(
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _changeRef: ChangeDetectorRef,
|
||||
@Inject(MAT_DIALOG_DATA)
|
||||
private readonly _data: {
|
||||
@ -106,7 +108,7 @@ export class EditDossierDialogComponent {
|
||||
|
||||
updatedDossier() {
|
||||
this._toaster.success(_('edit-dossier-dialog.change-successful'), { params: { dossierName: this.dossier.dossierName } });
|
||||
this.dossier = this._appStateService.getDossierById(this.dossier.id);
|
||||
this.dossier = this._dossiersService.find(this.dossier.id);
|
||||
this._changeRef.detectChanges();
|
||||
this.afterSave();
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { IDossierTemplate } from '@redaction/red-ui-http';
|
||||
import { DossierRequest, IDossierTemplate } from '@redaction/red-ui-http';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import * as moment from 'moment';
|
||||
@ -12,6 +12,7 @@ import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { EditDossierDialogComponent } from '../edit-dossier-dialog.component';
|
||||
import { ConfirmationDialogInput, IconButtonTypes, TitleColors, Toaster } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossiersService } from '../../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-dossier-general-info',
|
||||
@ -31,6 +32,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _router: Router,
|
||||
@ -99,8 +101,8 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
watermarkEnabled: this.dossierForm.get('watermarkEnabled').value,
|
||||
dueDate: this.hasDueDate ? this.dossierForm.get('dueDate').value : undefined,
|
||||
dossierTemplateId: this.dossierForm.get('dossierTemplateId').value
|
||||
};
|
||||
await this._appStateService.createOrUpdateDossier(dossier);
|
||||
} as DossierRequest;
|
||||
await this._dossiersService.createOrUpdate(dossier).toPromise();
|
||||
this.updateDossier.emit();
|
||||
}
|
||||
|
||||
@ -119,7 +121,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
}
|
||||
});
|
||||
this._dialogService.openDialog('confirm', null, data, async () => {
|
||||
await this._appStateService.deleteDossier(this.dossier);
|
||||
await this._dossiersService.delete(this.dossier).toPromise();
|
||||
this._editDossierDialogRef.componentInstance.afterSave();
|
||||
this._editDossierDialogRef.close();
|
||||
this._router.navigate(['main', 'dossiers']).then(() => this._notifyDossierDeleted());
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { ForceRedactionRequest, LegalBasisMappingControllerService } from '@redaction/red-ui-http';
|
||||
import { Toaster } from '@iqser/common-ui';
|
||||
@ -8,6 +7,7 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { ManualAnnotationService } from '../../services/manual-annotation.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
export interface LegalBasisOption {
|
||||
label?: string;
|
||||
@ -26,7 +26,7 @@ export class ForceRedactionDialogComponent implements OnInit {
|
||||
legalOptions: LegalBasisOption[] = [];
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _notificationService: Toaster,
|
||||
@ -39,7 +39,7 @@ export class ForceRedactionDialogComponent implements OnInit {
|
||||
|
||||
async ngOnInit() {
|
||||
this._legalBasisMappingControllerService
|
||||
.getLegalBasisMapping(this._appStateService.activeDossier.dossierTemplateId)
|
||||
.getLegalBasisMapping(this._dossiersService.activeDossier.dossierTemplateId)
|
||||
.subscribe(data => {
|
||||
data.map(lbm => {
|
||||
this.legalOptions.push({
|
||||
|
||||
@ -11,6 +11,7 @@ import { ManualAnnotationService } from '../../services/manual-annotation.servic
|
||||
import { ManualAnnotationResponse } from '@models/file/manual-annotation-response';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { TypeValue } from '@models/file/type-value';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
export interface LegalBasisOption {
|
||||
label?: string;
|
||||
@ -35,6 +36,7 @@ export class ManualAnnotationDialogComponent implements OnInit {
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _notificationService: Toaster,
|
||||
@ -60,7 +62,7 @@ export class ManualAnnotationDialogComponent implements OnInit {
|
||||
|
||||
async ngOnInit() {
|
||||
this._legalBasisMappingControllerService
|
||||
.getLegalBasisMapping(this._appStateService.activeDossier.dossierTemplateId)
|
||||
.getLegalBasisMapping(this._dossiersService.activeDossier.dossierTemplateId)
|
||||
.subscribe(data => {
|
||||
data.map(lbm => {
|
||||
this.legalOptions.push({
|
||||
@ -86,7 +88,7 @@ export class ManualAnnotationDialogComponent implements OnInit {
|
||||
comment: this.isDocumentAdmin ? [null] : [null, Validators.required]
|
||||
});
|
||||
|
||||
for (const key of Object.keys(this._appStateService.dictionaryData[this._appStateService.activeDossier.dossierTemplateId])) {
|
||||
for (const key of Object.keys(this._appStateService.dictionaryData[this._dossiersService.activeDossier.dossierTemplateId])) {
|
||||
const dictionaryData = this._appStateService.getDictionaryTypeValue(key);
|
||||
if (!dictionaryData.virtual && dictionaryData.addToDictionaryAction) {
|
||||
this.redactionDictionaries.push(dictionaryData);
|
||||
@ -103,6 +105,14 @@ export class ManualAnnotationDialogComponent implements OnInit {
|
||||
);
|
||||
}
|
||||
|
||||
format(value: string) {
|
||||
return value.replace(
|
||||
// eslint-disable-next-line no-control-regex,max-len
|
||||
/([^\s\d-]{2,})[-\u00AD]\u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]/gi,
|
||||
'$1'
|
||||
);
|
||||
}
|
||||
|
||||
private _enhanceManualRedaction(addRedactionRequest: AddRedactionRequest) {
|
||||
const legalOption: LegalBasisOption = this.redactionForm.get('reason').value;
|
||||
addRedactionRequest.type = this.redactionForm.get('dictionary').value;
|
||||
@ -118,12 +128,4 @@ export class ManualAnnotationDialogComponent implements OnInit {
|
||||
const commentValue = this.redactionForm.get('comment').value;
|
||||
addRedactionRequest.comment = commentValue ? { text: commentValue } : null;
|
||||
}
|
||||
|
||||
format(value: string) {
|
||||
return value.replace(
|
||||
// eslint-disable-next-line no-control-regex,max-len
|
||||
/([^\s\d-]{2,})[-\u00AD]\u000D\u000A|[\u000A\u000B\u000C\u000D\u0085\u2028\u2029]/gi,
|
||||
'$1'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +80,6 @@ const components = [
|
||||
];
|
||||
|
||||
const services = [
|
||||
DossiersService,
|
||||
DossiersDialogService,
|
||||
AnnotationActionsService,
|
||||
ManualAnnotationService,
|
||||
|
||||
@ -3,43 +3,43 @@
|
||||
(action)="delete()"
|
||||
*ngIf="canDelete"
|
||||
[tooltip]="'dossier-overview.bulk.delete' | translate"
|
||||
icon="red:trash"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:trash"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="assign()"
|
||||
*ngIf="canAssign"
|
||||
[tooltip]="assignTooltip"
|
||||
icon="red:assign"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:assign"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="assignToMe()"
|
||||
*ngIf="canAssignToSelf"
|
||||
[tooltip]="'dossier-overview.assign-me' | translate"
|
||||
icon="red:assign-me"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:assign-me"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="setToUnderApproval()"
|
||||
*ngIf="canSetToUnderApproval"
|
||||
[tooltip]="'dossier-overview.under-approval' | translate"
|
||||
icon="red:ready-for-approval"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:ready-for-approval"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="setToUnderReview()"
|
||||
*ngIf="canSetToUnderReview"
|
||||
[tooltip]="'dossier-overview.under-review' | translate"
|
||||
icon="red:undo"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:undo"
|
||||
></iqser-circle-button>
|
||||
|
||||
<redaction-file-download-btn [dossier]="dossier" [file]="selectedFiles"></redaction-file-download-btn>
|
||||
<redaction-file-download-btn [dossier]="dossier" [files]="selectedFiles"></redaction-file-download-btn>
|
||||
|
||||
<!-- Approved-->
|
||||
<iqser-circle-button
|
||||
@ -47,8 +47,8 @@
|
||||
*ngIf="isReadyForApproval"
|
||||
[disabled]="!canApprove"
|
||||
[tooltip]="canApprove ? ('dossier-overview.approve' | translate) : ('dossier-overview.approve-disabled' | translate)"
|
||||
icon="red:approved"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:approved"
|
||||
></iqser-circle-button>
|
||||
|
||||
<!-- Back to approval -->
|
||||
@ -56,23 +56,23 @@
|
||||
(action)="setToUnderApproval()"
|
||||
*ngIf="canUndoApproval"
|
||||
[tooltip]="'dossier-overview.under-approval' | translate"
|
||||
icon="red:undo"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:undo"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="ocr()"
|
||||
*ngIf="canOcr"
|
||||
[tooltip]="'dossier-overview.ocr-file' | translate"
|
||||
icon="red:ocr"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="red:ocr"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="reanalyse()"
|
||||
*ngIf="canReanalyse"
|
||||
[tooltip]="'dossier-overview.bulk.reanalyse' | translate"
|
||||
icon="iqser:refresh"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:refresh"
|
||||
></iqser-circle-button>
|
||||
</ng-container>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { AppStateService } from '../../../../../../state/app-state.service';
|
||||
import { FileManagementControllerService, ReanalysisControllerService } from '@redaction/red-ui-http';
|
||||
import { PermissionsService } from '../../../../../../services/permissions.service';
|
||||
@ -9,6 +9,7 @@ import { DossiersDialogService } from '../../../../services/dossiers-dialog.serv
|
||||
import { CircleButtonTypes, ConfirmationDialogInput, EntitiesService, LoadingService } from '@iqser/common-ui';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-overview-bulk-actions',
|
||||
@ -18,6 +19,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
export class DossierOverviewBulkActionsComponent {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
|
||||
@Input() dossier: Dossier;
|
||||
@Output() readonly reload = new EventEmitter();
|
||||
|
||||
constructor(
|
||||
@ -32,19 +34,12 @@ export class DossierOverviewBulkActionsComponent {
|
||||
private readonly _entitiesService: EntitiesService<File>
|
||||
) {}
|
||||
|
||||
get dossier() {
|
||||
return this._appStateService?.activeDossier;
|
||||
}
|
||||
|
||||
get selectedFiles(): File[] {
|
||||
return this._entitiesService.selected;
|
||||
}
|
||||
|
||||
get areAllFilesSelected() {
|
||||
return (
|
||||
this._appStateService.activeDossier.files.length !== 0 &&
|
||||
this.selectedFiles.length === this._appStateService.activeDossier.files.length
|
||||
);
|
||||
return this.dossier.files.length !== 0 && this.selectedFiles.length === this.dossier.files.length;
|
||||
}
|
||||
|
||||
get areSomeFilesSelected() {
|
||||
@ -133,7 +128,7 @@ export class DossierOverviewBulkActionsComponent {
|
||||
await this._fileManagementControllerService
|
||||
.deleteFiles(
|
||||
this.selectedFiles.map(item => item.fileId),
|
||||
this._appStateService.activeDossierId
|
||||
this.dossier.dossierId
|
||||
)
|
||||
.toPromise();
|
||||
await this._appStateService.reloadActiveDossierFiles();
|
||||
@ -146,20 +141,16 @@ export class DossierOverviewBulkActionsComponent {
|
||||
|
||||
setToUnderApproval() {
|
||||
// If more than 1 approver - show dialog and ask who to assign
|
||||
if (this._appStateService.activeDossier.approverIds.length > 1) {
|
||||
if (this.dossier.approverIds.length > 1) {
|
||||
this._assignFiles('approver', true);
|
||||
} else {
|
||||
this._performBulkAction(
|
||||
this._fileActionService.setFilesUnderApproval(this.selectedFiles, this._appStateService.activeDossier.approverIds[0])
|
||||
);
|
||||
this._performBulkAction(this._fileActionService.setFilesUnderApproval(this.selectedFiles, this.dossier.approverIds[0]));
|
||||
}
|
||||
}
|
||||
|
||||
async reanalyse() {
|
||||
const fileIds = this.selectedFiles.filter(file => file.analysisRequired).map(file => file.fileId);
|
||||
this._performBulkAction(
|
||||
this._reanalysisControllerService.reanalyzeFilesForDossier(fileIds, this._appStateService.activeDossier.id)
|
||||
);
|
||||
this._performBulkAction(this._reanalysisControllerService.reanalyzeFilesForDossier(fileIds, this.dossier.id));
|
||||
}
|
||||
|
||||
ocr() {
|
||||
|
||||
@ -1,66 +1,68 @@
|
||||
<div>
|
||||
<mat-icon svgIcon="red:document"></mat-icon>
|
||||
<span>{{ 'dossier-overview.dossier-details.stats.documents' | translate: { count: activeDossier.files.length } }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:user"></mat-icon>
|
||||
<span>{{ 'dossier-overview.dossier-details.stats.people' | translate: { count: activeDossier.memberIds.length } }}</span>
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:pages"></mat-icon>
|
||||
<span>{{
|
||||
'dossier-overview.dossier-details.stats.analysed-pages' | translate: { count: activeDossier.totalNumberOfPages | number }
|
||||
}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:calendar"></mat-icon>
|
||||
<span
|
||||
>{{
|
||||
'dossier-overview.dossier-details.stats.created-on'
|
||||
<ng-container *ngIf="dossiersService.activeDossier$ | async as dossier">
|
||||
<div>
|
||||
<mat-icon svgIcon="red: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="red: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: activeDossier.date | date: 'd MMM. yyyy'
|
||||
date: dossier.dueDate | date: 'd MMM. yyyy'
|
||||
}
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div *ngIf="activeDossier.dueDate">
|
||||
<mat-icon svgIcon="red:lightning"></mat-icon>
|
||||
<span>{{
|
||||
'dossier-overview.dossier-details.stats.due-date'
|
||||
| translate
|
||||
: {
|
||||
date: activeDossier.dueDate | date: 'd MMM. yyyy'
|
||||
}
|
||||
}}</span>
|
||||
</div>
|
||||
<div>
|
||||
<mat-icon svgIcon="red:template"></mat-icon>
|
||||
<span>{{ dossierTemplate?.name }} </span>
|
||||
</div>
|
||||
<div (click)="openDossierDictionaryDialog.emit()" *ngIf="activeDossier.type" class="link-property">
|
||||
<mat-icon svgIcon="red:dictionary"></mat-icon>
|
||||
<span>{{ 'dossier-overview.dossier-details.dictionary' | translate }} </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 } }}
|
||||
}}</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>
|
||||
|
||||
<ng-container *ngIf="attributesExpanded">
|
||||
<div (click)="openEditDossierAttributesDialog()" *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>
|
||||
<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>
|
||||
|
||||
<div (click)="attributesExpanded = false" class="all-caps-label hide-attributes">
|
||||
{{ 'dossier-overview.dossier-details.attributes.show-less' | translate }}
|
||||
</div>
|
||||
<ng-container *ngIf="attributesExpanded">
|
||||
<div (click)="openEditDossierAttributesDialog(dossier)" *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>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
|
||||
@ -4,6 +4,7 @@ import { AppStateService } from '@state/app-state.service';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
import { IDossierTemplate } from '@redaction/red-ui-http';
|
||||
import { DossiersDialogService } from '../../../../services/dossiers-dialog.service';
|
||||
import { DossiersService } from '../../../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-details-stats',
|
||||
@ -15,19 +16,19 @@ export class DossierDetailsStatsComponent {
|
||||
@Input() dossierAttributes: DossierAttributeWithValue[];
|
||||
@Output() readonly openDossierDictionaryDialog = new EventEmitter();
|
||||
|
||||
constructor(private readonly _appStateService: AppStateService, private readonly _dialogService: DossiersDialogService) {}
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
readonly dossiersService: DossiersService
|
||||
) {}
|
||||
|
||||
get activeDossier(): Dossier {
|
||||
return this._appStateService.activeDossier;
|
||||
dossierTemplate(dossier: Dossier): IDossierTemplate {
|
||||
return this._appStateService.getDossierTemplateById(dossier.dossierTemplateId);
|
||||
}
|
||||
|
||||
get dossierTemplate(): IDossierTemplate {
|
||||
return this._appStateService.getDossierTemplateById(this.activeDossier.dossierTemplateId);
|
||||
}
|
||||
|
||||
openEditDossierAttributesDialog() {
|
||||
openEditDossierAttributesDialog(dossier: Dossier) {
|
||||
this._dialogService.openDialog('editDossier', null, {
|
||||
dossier: this.activeDossier,
|
||||
dossier,
|
||||
section: 'dossierAttributes'
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
<ng-container *ngIf="appStateService.activeDossier">
|
||||
<ng-container *ngIf="dossiersService.activeDossier$ | 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>
|
||||
</div>
|
||||
|
||||
<div class="header-wrapper mt-8">
|
||||
<div class="heading-xl flex-1">{{ appStateService.activeDossier.dossierName }}</div>
|
||||
<div class="heading-xl flex-1">{{ dossier.dossierName }}</div>
|
||||
<ng-container
|
||||
*ngTemplateOutlet="collapsible; context: { action: 'collapse', tooltip: (collapseTooltip | translate) }"
|
||||
></ng-container>
|
||||
@ -33,12 +33,12 @@
|
||||
<div class="all-caps-label" translate="dossier-details.members"></div>
|
||||
<redaction-team-members
|
||||
(openAssignDossierMembersDialog)="openAssignDossierMembersDialog.emit()"
|
||||
[memberIds]="memberIds"
|
||||
[memberIds]="dossier.memberIds"
|
||||
[perLine]="9"
|
||||
></redaction-team-members>
|
||||
</div>
|
||||
|
||||
<div *ngIf="hasFiles" class="mt-24">
|
||||
<div *ngIf="dossier.hasFiles" class="mt-24">
|
||||
<redaction-simple-doughnut-chart
|
||||
[config]="documentsChartData"
|
||||
[radius]="63"
|
||||
@ -48,7 +48,7 @@
|
||||
></redaction-simple-doughnut-chart>
|
||||
</div>
|
||||
|
||||
<div *ngIf="hasFiles" class="mt-24 legend pb-32">
|
||||
<div *ngIf="dossier.hasFiles" class="mt-24 legend pb-32">
|
||||
<div
|
||||
(click)="filterService.toggleFilter('needsWorkFilters', filter.id)"
|
||||
*ngFor="let filter of needsWorkFilters$ | async"
|
||||
@ -58,14 +58,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div [class.mt-24]="!hasFiles" class="pb-32">
|
||||
<div [class.mt-24]="!dossier.hasFiles" class="pb-32">
|
||||
<redaction-dossier-details-stats
|
||||
(openDossierDictionaryDialog)="openDossierDictionaryDialog.emit()"
|
||||
[dossierAttributes]="dossierAttributes"
|
||||
></redaction-dossier-details-stats>
|
||||
</div>
|
||||
|
||||
<div *ngIf="appStateService.activeDossier.description as description" class="pb-32">
|
||||
<div *ngIf="dossier.description as description" class="pb-32">
|
||||
<div class="heading" translate="dossier-overview.dossier-details.description"></div>
|
||||
<div class="mt-8">{{ description }}</div>
|
||||
</div>
|
||||
|
||||
@ -8,8 +8,9 @@ import { FilterService, Toaster } from '@iqser/common-ui';
|
||||
import { DossierAttributeWithValue } from '@models/dossier-attributes.model';
|
||||
import { fileStatusTranslations } from '../../../../translations/file-status-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { List } from '@redaction/red-ui-http';
|
||||
import { DossierRequest } from '@redaction/red-ui-http';
|
||||
import { User } from '@models/user';
|
||||
import { DossiersService } from '../../../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-details',
|
||||
@ -32,6 +33,7 @@ export class DossierDetailsComponent implements OnInit {
|
||||
|
||||
constructor(
|
||||
readonly appStateService: AppStateService,
|
||||
readonly dossiersService: DossiersService,
|
||||
readonly translateChartService: TranslateChartService,
|
||||
readonly filterService: FilterService,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
@ -39,20 +41,12 @@ export class DossierDetailsComponent implements OnInit {
|
||||
private readonly _toaster: Toaster
|
||||
) {}
|
||||
|
||||
get memberIds(): List {
|
||||
return this.appStateService.activeDossier.memberIds;
|
||||
}
|
||||
|
||||
get hasFiles(): boolean {
|
||||
return this.appStateService.activeDossier.hasFiles;
|
||||
}
|
||||
|
||||
get managers() {
|
||||
return this._userService.managerUsers;
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.owner = this._userService.getRedUserById(this.appStateService.activeDossier.ownerId);
|
||||
this.owner = this._userService.getRedUserById(this.dossiersService.activeDossier.ownerId);
|
||||
this.calculateChartConfig();
|
||||
this.appStateService.fileChanged$.subscribe(() => {
|
||||
this.calculateChartConfig();
|
||||
@ -60,11 +54,12 @@ export class DossierDetailsComponent implements OnInit {
|
||||
}
|
||||
|
||||
calculateChartConfig(): void {
|
||||
if (!this.appStateService.activeDossier) {
|
||||
const activeDossier = this.dossiersService.activeDossier;
|
||||
if (!activeDossier) {
|
||||
return;
|
||||
}
|
||||
|
||||
const groups = groupBy(this.appStateService.activeDossier?.files, 'status');
|
||||
const groups = groupBy(activeDossier?.files, 'status');
|
||||
this.documentsChartData = [];
|
||||
for (const status of Object.keys(groups)) {
|
||||
this.documentsChartData.push({
|
||||
@ -81,11 +76,12 @@ export class DossierDetailsComponent implements OnInit {
|
||||
|
||||
async assignOwner(user: User | string) {
|
||||
this.owner = typeof user === 'string' ? this._userService.getRedUserById(user) : user;
|
||||
const dw = { ...this.appStateService.activeDossier, id: this.appStateService.activeDossierId, ownerId: this.owner.id };
|
||||
await this.appStateService.createOrUpdateDossier(dw);
|
||||
const activeDossier = this.dossiersService.activeDossier;
|
||||
const dossierRequest: DossierRequest = { ...activeDossier, dossierId: activeDossier.dossierId, ownerId: this.owner.id };
|
||||
await this.dossiersService.createOrUpdate(dossierRequest).toPromise();
|
||||
|
||||
const ownerName = this._userService.getNameForId(this.owner.id);
|
||||
const dossierName = this.appStateService.activeDossier.dossierName;
|
||||
const dossierName = activeDossier.dossierName;
|
||||
this._toaster.info(_('assignment.owner'), { params: { ownerName, dossierName } });
|
||||
}
|
||||
}
|
||||
|
||||
@ -14,6 +14,4 @@ export class TableItemComponent {
|
||||
@Input() @Required() statsTemplate!: TemplateRef<unknown>;
|
||||
@Input() @Required() displayedAttributes!: IFileAttributeConfig[];
|
||||
@Output() readonly calculateData = new EventEmitter<void>();
|
||||
|
||||
constructor() {}
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@ import { annotationFilterChecker, RedactionFilterSorter, StatusSorter } from '@u
|
||||
import { workloadTranslations } from '../../translations/workload-translations';
|
||||
import * as moment from 'moment';
|
||||
import { ConfigService as AppConfigService } from '@services/config.service';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
@Injectable()
|
||||
export class ConfigService {
|
||||
@ -21,6 +22,7 @@ export class ConfigService {
|
||||
private readonly _fileActionService: FileActionService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _userService: UserService,
|
||||
@ -331,7 +333,7 @@ export class ConfigService {
|
||||
|
||||
private _openEditDossierDialog($event: MouseEvent) {
|
||||
this._dialogService.openDialog('editDossier', $event, {
|
||||
dossier: this._appStateService.activeDossier
|
||||
dossier: this._dossiersService.activeDossier
|
||||
});
|
||||
}
|
||||
|
||||
@ -345,7 +347,7 @@ export class ConfigService {
|
||||
};
|
||||
|
||||
private _underApprovalFn = (reloadDossiers: () => Promise<void>) => async (file: File) => {
|
||||
if (this._appStateService.activeDossier.approverIds.length > 1) {
|
||||
if (this._dossiersService.activeDossier.approverIds.length > 1) {
|
||||
this._fileActionService.assignFile('approver', null, file, () => this._loadingService.loadWhile(reloadDossiers()), true);
|
||||
} else {
|
||||
this._loadingService.start();
|
||||
|
||||
@ -7,13 +7,13 @@
|
||||
>
|
||||
<redaction-file-download-btn
|
||||
[dossier]="currentDossier"
|
||||
[file]="entitiesService.all$ | async"
|
||||
[files]="entitiesService.all$ | async"
|
||||
tooltipPosition="below"
|
||||
></redaction-file-download-btn>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="reanalyseDossier()"
|
||||
*ngIf="permissionsService.displayReanalyseBtn()"
|
||||
*ngIf="permissionsService.displayReanalyseBtn(currentDossier)"
|
||||
[tooltipClass]="'small ' + ((entitiesService.areSomeSelected$ | async) ? '' : 'warn')"
|
||||
[tooltip]="'dossier-overview.new-rule.toast.actions.reanalyse-all' | translate"
|
||||
[type]="circleButtonTypes.warn"
|
||||
@ -87,7 +87,10 @@
|
||||
<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()"></redaction-dossier-overview-bulk-actions>
|
||||
<redaction-dossier-overview-bulk-actions
|
||||
(reload)="bulkActionPerformed()"
|
||||
[dossier]="currentDossier"
|
||||
></redaction-dossier-overview-bulk-actions>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #viewModeSelection>
|
||||
|
||||
@ -50,6 +50,7 @@ import { Router } from '@angular/router';
|
||||
import { FileAttributesService } from '../../../services/file-attributes.service';
|
||||
import { ConfigService as AppConfigService } from '@services/config.service';
|
||||
import { ConfigService } from '../config.service';
|
||||
import { DossiersService } from '../../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-overview-screen.component.html',
|
||||
@ -60,7 +61,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
readonly listingModes = ListingModes;
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
currentDossier = this._appStateService.activeDossier;
|
||||
currentDossier = this._dossiersService.activeDossier;
|
||||
readonly tableHeaderLabel = _('dossier-overview.table-header.title');
|
||||
collapsedDetails = false;
|
||||
dossierAttributes: DossierAttributeWithValue[] = [];
|
||||
@ -83,6 +84,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
readonly routerHistoryService: RouterHistoryService,
|
||||
private readonly _appConfigService: AppConfigService,
|
||||
private readonly _translateService: TranslateService,
|
||||
@ -96,11 +98,6 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
private readonly _configService: ConfigService
|
||||
) {
|
||||
super(_injector);
|
||||
this._loadEntitiesFromState();
|
||||
this.fileAttributeConfigs = this._fileAttributesService.getFileAttributeConfig(
|
||||
this.currentDossier.dossierTemplateId
|
||||
)?.fileAttributeConfigs;
|
||||
this.tableColumnConfigs = this._configService.tableConfig(this.displayedAttributes);
|
||||
}
|
||||
|
||||
get checkedRequiredFilters(): NestedFilter[] {
|
||||
@ -133,6 +130,11 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
this._loadingService.start();
|
||||
this._loadEntitiesFromState();
|
||||
this.fileAttributeConfigs = this._fileAttributesService.getFileAttributeConfig(
|
||||
this.currentDossier.dossierTemplateId
|
||||
)?.fileAttributeConfigs;
|
||||
this.tableColumnConfigs = this._configService.tableConfig(this.displayedAttributes);
|
||||
try {
|
||||
this._fileDropOverlayService.initFileDropHandling();
|
||||
|
||||
@ -197,7 +199,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
}
|
||||
|
||||
calculateData(): void {
|
||||
if (!this._appStateService.activeDossierId) {
|
||||
if (!this._dossiersService.activeDossierId) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -249,9 +251,9 @@ 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._appStateService.activeDossier;
|
||||
this.currentDossier = this._dossiersService.activeDossier;
|
||||
if (this.currentDossier) {
|
||||
this.entitiesService.setEntities(this.currentDossier.files);
|
||||
this.entitiesService.setEntities([...this.currentDossier.files]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -4,17 +4,17 @@
|
||||
(action)="openEditDossierDialog($event, dossier)"
|
||||
*ngIf="currentUser.isManager"
|
||||
[tooltip]="'dossier-listing.edit.action' | translate"
|
||||
icon="iqser:edit"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="reanalyseDossier($event, dossier)"
|
||||
*ngIf="permissionsService.displayReanalyseBtn(dossier)"
|
||||
[tooltip]="'dossier-listing.reanalyse.action' | translate"
|
||||
icon="iqser:refresh"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:refresh"
|
||||
></iqser-circle-button>
|
||||
|
||||
<redaction-file-download-btn [dossier]="dossier" [file]="dossier.files" [type]="circleButtonTypes.dark"></redaction-file-download-btn>
|
||||
<redaction-file-download-btn [dossier]="dossier" [files]="dossier.files" [type]="circleButtonTypes.dark"></redaction-file-download-btn>
|
||||
</div>
|
||||
|
||||
@ -6,11 +6,11 @@
|
||||
[subtitle]="'dossier-listing.stats.charts.dossiers' | translate"
|
||||
></redaction-simple-doughnut-chart>
|
||||
|
||||
<div class="dossier-stats-container">
|
||||
<div *ngIf="dossiersService.stats$ | async as stats" class="dossier-stats-container">
|
||||
<div class="dossier-stats-item">
|
||||
<mat-icon svgIcon="red:needs-work"></mat-icon>
|
||||
<div>
|
||||
<div class="heading">{{ appStateService.totalAnalysedPages | number }}</div>
|
||||
<div class="heading">{{ stats.totalAnalyzedPages | number }}</div>
|
||||
<div translate="dossier-listing.stats.analyzed-pages"></div>
|
||||
</div>
|
||||
</div>
|
||||
@ -18,7 +18,7 @@
|
||||
<div class="dossier-stats-item">
|
||||
<mat-icon svgIcon="red:user"></mat-icon>
|
||||
<div>
|
||||
<div class="heading">{{ appStateService.totalPeople }}</div>
|
||||
<div class="heading">{{ stats.totalPeople }}</div>
|
||||
<div translate="dossier-listing.stats.total-people"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { DossiersService } from '../../../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossiers-listing-details',
|
||||
@ -13,5 +13,5 @@ export class DossiersListingDetailsComponent {
|
||||
@Input() dossiersChartData: DoughnutChartConfig[];
|
||||
@Input() documentsChartData: DoughnutChartConfig[];
|
||||
|
||||
constructor(readonly appStateService: AppStateService, readonly filterService: FilterService) {}
|
||||
constructor(readonly filterService: FilterService, readonly dossiersService: DossiersService) {}
|
||||
}
|
||||
|
||||
@ -9,7 +9,5 @@ import { Required } from '@iqser/common-ui';
|
||||
})
|
||||
export class TableItemComponent {
|
||||
@Input() @Required() dossier!: Dossier;
|
||||
@Output() readonly calculateData = new EventEmitter<void>();
|
||||
|
||||
constructor() {}
|
||||
@Output() readonly calculateData = new EventEmitter();
|
||||
}
|
||||
|
||||
@ -11,15 +11,31 @@ import { tap } from 'rxjs/operators';
|
||||
import { Router } from '@angular/router';
|
||||
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
|
||||
import { groupBy, StatusSorter } from '@utils/index';
|
||||
import { DefaultListingServices, ListingComponent, OnAttach, OnDetach, TableComponent } from '@iqser/common-ui';
|
||||
import {
|
||||
EntitiesService,
|
||||
FilterService,
|
||||
ListingComponent,
|
||||
OnAttach,
|
||||
OnDetach,
|
||||
SearchService,
|
||||
SortingService,
|
||||
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/dossiers.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossiers-listing-screen.component.html',
|
||||
styleUrls: ['./dossiers-listing-screen.component.scss'],
|
||||
providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => DossiersListingScreenComponent) }]
|
||||
providers: [
|
||||
FilterService,
|
||||
SearchService,
|
||||
SortingService,
|
||||
{ provide: EntitiesService, useExisting: DossiersService },
|
||||
{ provide: ListingComponent, useExisting: forwardRef(() => DossiersListingScreenComponent) }
|
||||
]
|
||||
})
|
||||
export class DossiersListingScreenComponent
|
||||
extends ListingComponent<Dossier>
|
||||
@ -45,13 +61,13 @@ export class DossiersListingScreenComponent
|
||||
private readonly _userService: UserService,
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _translateChartService: TranslateChartService,
|
||||
private readonly _configService: ConfigService
|
||||
) {
|
||||
super(_injector);
|
||||
this._appStateService.reset();
|
||||
this._loadEntitiesFromState();
|
||||
}
|
||||
|
||||
private get _activeDossiersCount(): number {
|
||||
@ -67,7 +83,6 @@ export class DossiersListingScreenComponent
|
||||
|
||||
this.addSubscription = timer(0, 10000).subscribe(async () => {
|
||||
await this._appStateService.loadAllDossiers();
|
||||
this._loadEntitiesFromState();
|
||||
this.calculateData();
|
||||
});
|
||||
|
||||
@ -84,7 +99,6 @@ export class DossiersListingScreenComponent
|
||||
|
||||
ngOnAttach(): void {
|
||||
this._appStateService.reset();
|
||||
this._loadEntitiesFromState();
|
||||
this.ngOnInit();
|
||||
this.ngAfterViewInit();
|
||||
this._tableComponent.scrollViewport.scrollToIndex(this._lastScrolledIndex, 'smooth');
|
||||
@ -113,7 +127,7 @@ export class DossiersListingScreenComponent
|
||||
{ value: this._activeDossiersCount, color: 'ACTIVE', label: _('active') },
|
||||
{ value: this._inactiveDossiersCount, color: 'DELETED', label: _('archived') }
|
||||
];
|
||||
const groups = groupBy(this._appStateService.aggregatedFiles, 'status');
|
||||
const groups = groupBy(this._dossiersService.allFiles, 'status');
|
||||
this.documentsChartData = [];
|
||||
|
||||
for (const status of Object.keys(groups)) {
|
||||
@ -128,10 +142,6 @@ export class DossiersListingScreenComponent
|
||||
this.documentsChartData = this._translateChartService.translateStatus(this.documentsChartData);
|
||||
}
|
||||
|
||||
private _loadEntitiesFromState() {
|
||||
this.entitiesService.setEntities(this._appStateService.allDossiers);
|
||||
}
|
||||
|
||||
private _computeAllFilters() {
|
||||
const filterGroups = this._configService.filterGroups(this.entitiesService.all, this._needsWorkFilterTemplate);
|
||||
for (const filterGroup of filterGroups) {
|
||||
|
||||
@ -29,7 +29,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex-1 actions-container">
|
||||
<div *ngIf="dossiersService.activeDossier$ | async as dossier" class="flex-1 actions-container">
|
||||
<ng-container *ngIf="!appStateService.activeFile.excluded">
|
||||
<ng-container *ngIf="!appStateService.activeFile.isProcessing">
|
||||
<iqser-status-bar [configs]="statusBarConfig" [small]="true"></iqser-status-bar>
|
||||
@ -48,7 +48,7 @@
|
||||
></redaction-initials-avatar>
|
||||
<div
|
||||
(click)="editingReviewer = true"
|
||||
*ngIf="!editingReviewer && canAssignReviewer"
|
||||
*ngIf="!editingReviewer && canAssignReviewer(dossier)"
|
||||
class="assign-reviewer pointer"
|
||||
translate="file-preview.assign-reviewer"
|
||||
></div>
|
||||
@ -58,7 +58,7 @@
|
||||
(cancel)="editingReviewer = false"
|
||||
(save)="assignReviewer($event)"
|
||||
*ngIf="editingReviewer"
|
||||
[options]="singleUsersSelectOptions"
|
||||
[options]="singleUsersSelectOptions(dossier)"
|
||||
[value]="currentReviewer"
|
||||
></redaction-assign-user-dropdown>
|
||||
|
||||
@ -118,7 +118,7 @@
|
||||
<iqser-circle-button
|
||||
(action)="closeFullScreen()"
|
||||
*ngIf="!fullScreen"
|
||||
[routerLink]="['/main/dossiers/' + appStateService.activeDossierId]"
|
||||
[routerLink]="dossier.routerLink"
|
||||
[tooltip]="'common.close' | translate"
|
||||
class="ml-8"
|
||||
icon="iqser:close"
|
||||
|
||||
@ -42,6 +42,8 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { FileActionsComponent } from '../../shared/components/file-actions/file-actions.component';
|
||||
import { User } from '@models/user';
|
||||
import { FilesService } from '../../services/files.service';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
|
||||
const ALL_HOTKEY_ARRAY = ['Escape', 'F', 'f'];
|
||||
@ -82,6 +84,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
constructor(
|
||||
readonly appStateService: AppStateService,
|
||||
readonly dossiersService: DossiersService,
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly userPreferenceService: UserPreferenceService,
|
||||
readonly userService: UserService,
|
||||
@ -111,12 +114,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
});
|
||||
}
|
||||
|
||||
get singleUsersSelectOptions(): List {
|
||||
return this.appStateService.activeFile?.isUnderApproval
|
||||
? this.appStateService.activeDossier.approverIds
|
||||
: this.appStateService.activeDossier.memberIds;
|
||||
}
|
||||
|
||||
get assignTooltip(): string {
|
||||
return this.appStateService.activeFile.isUnderApproval
|
||||
? this._translateService.instant('dossier-overview.assign-approver')
|
||||
@ -159,10 +156,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
return this.fileData?.fileData;
|
||||
}
|
||||
|
||||
get dossierId(): string {
|
||||
return this.appStateService.activeDossierId;
|
||||
}
|
||||
|
||||
get fileId(): string {
|
||||
return this.appStateService.activeFileId;
|
||||
}
|
||||
@ -197,8 +190,12 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
return this.status === 'UNDER_REVIEW' || this.status === 'UNDER_APPROVAL';
|
||||
}
|
||||
|
||||
get canAssignReviewer(): boolean {
|
||||
return !this.currentReviewer && this.permissionsService.canAssignUser() && this.appStateService.activeDossier.hasReviewers;
|
||||
singleUsersSelectOptions(dossier: Dossier): List {
|
||||
return this.appStateService.activeFile?.isUnderApproval ? dossier.approverIds : dossier.memberIds;
|
||||
}
|
||||
|
||||
canAssignReviewer(dossier: Dossier): boolean {
|
||||
return !this.currentReviewer && this.permissionsService.canAssignUser() && dossier.hasReviewers;
|
||||
}
|
||||
|
||||
updateViewMode(): void {
|
||||
@ -243,8 +240,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
async ngOnAttach(previousRoute: ActivatedRouteSnapshot): Promise<void> {
|
||||
if (!this.appStateService.activeFile.canBeOpened) {
|
||||
await this._router.navigate(['/main/dossiers/' + this.dossierId]);
|
||||
return;
|
||||
return await this.dossiersService.goToActiveDossier();
|
||||
}
|
||||
|
||||
await this.ngOnInit();
|
||||
@ -278,7 +274,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
console.log('[REDACTION] Delete previous annotations time: ' + (new Date().getTime() - startTime) + 'ms');
|
||||
const processStartTime = new Date().getTime();
|
||||
const newAnnotationsData = this.fileData.getAnnotations(
|
||||
this.appStateService.dictionaryData[this.appStateService.activeDossier.dossierTemplateId],
|
||||
this.appStateService.dictionaryData[this.dossiersService.activeDossier.dossierTemplateId],
|
||||
this.userService.currentUser,
|
||||
this.viewMode,
|
||||
this.userPreferenceService.areDevFeaturesEnabled
|
||||
@ -290,7 +286,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
this.annotationData = newAnnotationsData;
|
||||
const annotationFilters = this._annotationProcessingService.getAnnotationFilter(this.annotations);
|
||||
const primaryFilters = this._filterService.getGroup('primaryFilters')?.filters;
|
||||
console.log(annotationFilters);
|
||||
this._filterService.addFilterGroup({
|
||||
slug: 'primaryFilters',
|
||||
filterTemplate: this._filterTemplate,
|
||||
@ -302,8 +297,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
filterTemplate: this._filterTemplate,
|
||||
filters: processFilters(secondaryFilters, AnnotationProcessingService.secondaryAnnotationFilters)
|
||||
});
|
||||
console.log(this.annotations);
|
||||
console.log(this.appStateService.activeFile);
|
||||
console.log('[REDACTION] Process time: ' + (new Date().getTime() - processStartTime) + 'ms');
|
||||
console.log(
|
||||
'[REDACTION] Annotation Redraw and filter rebuild time: ' +
|
||||
@ -451,8 +444,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
switch (action) {
|
||||
case 'delete':
|
||||
await this._router.navigate([`/main/dossiers/${this.dossierId}`]);
|
||||
return;
|
||||
return await this.dossiersService.goToActiveDossier();
|
||||
|
||||
case 'enable-analysis':
|
||||
case 'reanalyse':
|
||||
@ -522,7 +514,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
downloadOriginalFile() {
|
||||
this.addSubscription = this._fileManagementControllerService
|
||||
.downloadOriginalFile(this.dossierId, this.fileId, true, this.fileData.file.cacheIdentifier, 'response')
|
||||
.downloadOriginalFile(this.fileData.file.dossierId, this.fileId, true, this.fileData.file.cacheIdentifier, 'response')
|
||||
.subscribe(data => {
|
||||
download(data, this.fileData.file.filename);
|
||||
});
|
||||
@ -538,15 +530,6 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
return false;
|
||||
}
|
||||
|
||||
// <!-- Dev Mode Features-->
|
||||
async openSSRFilePreview() {
|
||||
window.open(`/pdf-preview/${this.dossierId}/${this.fileId}`, '_blank');
|
||||
}
|
||||
|
||||
async openHTMLDebug() {
|
||||
window.open(`/html-debug/${this.dossierId}/${this.fileId}`, '_blank');
|
||||
}
|
||||
|
||||
private _setHiddenPropertyToNewAnnotations(newAnnotations: AnnotationWrapper[], oldAnnotations: AnnotationWrapper[]) {
|
||||
newAnnotations.map((newAnnotation: AnnotationWrapper) => {
|
||||
const oldAnnotation = oldAnnotations.find((a: AnnotationWrapper) => a.annotationId === newAnnotation.annotationId);
|
||||
@ -619,7 +602,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
}
|
||||
|
||||
if (fileData.file.isError) {
|
||||
await this._router.navigate(['/main/dossiers/' + this.dossierId]);
|
||||
await this.dossiersService.goToActiveDossier();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -13,11 +13,11 @@ import { List, MatchedDocument, SearchControllerService, SearchResult } from '@r
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { debounceTime, map, skip, switchMap, tap } from 'rxjs/operators';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { fileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { RouterHistoryService } from '@services/router-history.service';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
interface ListItem extends IListable {
|
||||
readonly dossierId: string;
|
||||
@ -65,19 +65,20 @@ export class SearchScreenComponent extends ListingComponent<ListItem> implements
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _activatedRoute: ActivatedRoute,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
readonly routerHistoryService: RouterHistoryService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _searchControllerService: SearchControllerService
|
||||
) {
|
||||
super(_injector);
|
||||
this.searchService.skip = true;
|
||||
|
||||
this.filterService.addFilterGroup({
|
||||
slug: 'dossiers',
|
||||
label: this._translateService.instant('search-screen.filters.by-dossier'),
|
||||
filterceptionPlaceholder: this._translateService.instant('search-screen.filters.search-placeholder'),
|
||||
icon: 'red:folder',
|
||||
filters: this._appStateService.allDossiers.map(
|
||||
filters: this._dossiersService.all.map(
|
||||
dossier =>
|
||||
new NestedFilter({
|
||||
id: dossier.id,
|
||||
@ -135,7 +136,7 @@ export class SearchScreenComponent extends ListingComponent<ListItem> implements
|
||||
}
|
||||
|
||||
private _toListItem({ dossierId, fileId, unmatchedTerms, highlights }: MatchedDocument): ListItem {
|
||||
const file = this._appStateService.getFileById(dossierId, fileId);
|
||||
const file = this._dossiersService.find(dossierId, fileId);
|
||||
if (!file) {
|
||||
return undefined;
|
||||
}
|
||||
@ -147,7 +148,7 @@ export class SearchScreenComponent extends ListingComponent<ListItem> implements
|
||||
highlights,
|
||||
status: file.status,
|
||||
numberOfPages: file.numberOfPages,
|
||||
dossierName: this._appStateService.getDossierById(dossierId).dossierName,
|
||||
dossierName: this._dossiersService.find(dossierId).dossierName,
|
||||
filename: file.filename,
|
||||
searchKey: file.filename,
|
||||
routerLink: `/main/dossiers/${dossierId}/file/${fileId}`
|
||||
|
||||
@ -5,12 +5,14 @@ import { hexToRgb } from '@utils/functions';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { DossiersService } from './dossiers.service';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
|
||||
@Injectable()
|
||||
export class AnnotationDrawService {
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _redactionLogControllerService: RedactionLogControllerService,
|
||||
private readonly _userPreferenceService: UserPreferenceService
|
||||
) {}
|
||||
@ -28,7 +30,7 @@ export class AnnotationDrawService {
|
||||
|
||||
if (this._userPreferenceService.areDevFeaturesEnabled) {
|
||||
this._redactionLogControllerService
|
||||
.getSectionGrid(this._appStateService.activeDossierId, this._appStateService.activeFileId)
|
||||
.getSectionGrid(this._dossiersService.activeDossierId, this._appStateService.activeFileId)
|
||||
.subscribe(sectionGrid => {
|
||||
this.drawSections(activeViewer, sectionGrid);
|
||||
});
|
||||
|
||||
@ -1,12 +1,15 @@
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { IDossier } from '@redaction/red-ui-http';
|
||||
import { EntitiesService, List, QueryParam } from '@iqser/common-ui';
|
||||
import { DossierRequest, IDossier } from '@redaction/red-ui-http';
|
||||
import { EntitiesService, List, QueryParam, RequiredParam, Toaster, Validate } from '@iqser/common-ui';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
import { filter, map } from 'rxjs/operators';
|
||||
import { catchError, filter, map, tap } from 'rxjs/operators';
|
||||
import { TEMPORARY_INJECTOR } from './injector';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
|
||||
import { ActivationEnd, Router } from '@angular/router';
|
||||
import { BaseScreenComponent } from '@components/base-screen/base-screen.component';
|
||||
import { File } from '@models/file/file';
|
||||
import { DictionaryService } from '@shared/services/dictionary.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
|
||||
export interface IDossiersStats {
|
||||
totalPeople: number;
|
||||
@ -14,63 +17,139 @@ export interface IDossiersStats {
|
||||
}
|
||||
|
||||
const getRelatedEvents = filter(event => event instanceof ActivationEnd && event.snapshot.component !== BaseScreenComponent);
|
||||
const DOSSIER_EXISTS_MSG = _('add-dossier-dialog.errors.dossier-already-exists');
|
||||
const GENERIC_MGS = _('add-dossier-dialog.errors.generic');
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class DossiersService extends EntitiesService<Dossier, IDossier> {
|
||||
readonly stats$ = this.all$.pipe(map(entities => this._computeStats(entities)));
|
||||
readonly activeDossierId$: Observable<string | null>;
|
||||
readonly activeDossier$: Observable<Dossier | null>;
|
||||
private readonly _activeDossierId$ = new BehaviorSubject<string | null>(null);
|
||||
readonly activeDossier$: Observable<Dossier | undefined>;
|
||||
readonly dossierChanged$ = new Subject<Dossier>();
|
||||
private readonly _activeDossier$ = new BehaviorSubject<Dossier | undefined>(undefined);
|
||||
|
||||
constructor(protected readonly _injector: Injector, private readonly _router: Router) {
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _router: Router,
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
private readonly _toaster: Toaster
|
||||
) {
|
||||
super(TEMPORARY_INJECTOR(_injector), 'dossier');
|
||||
this.activeDossierId$ = this._activeDossierId$.asObservable();
|
||||
this.activeDossier$ = this.activeDossierId$.pipe(map(id => this.all.find(dossier => dossier.id === id)));
|
||||
this.activeDossier$ = this._activeDossier$.asObservable();
|
||||
|
||||
_router.events.pipe(getRelatedEvents).subscribe((event: ActivationEnd) => {
|
||||
const dossierId = event.snapshot.paramMap.get('dossierId');
|
||||
const sameIdAsCurrentActive = dossierId === this._activeDossierId$.getValue();
|
||||
const sameIdAsCurrentActive = dossierId === this._activeDossier$.getValue()?.dossierId;
|
||||
|
||||
if (sameIdAsCurrentActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dossierId === null || dossierId === undefined) {
|
||||
return this._activeDossierId$.next(null);
|
||||
return this._activeDossier$.next(undefined);
|
||||
}
|
||||
|
||||
// const notFound = !this.all.some(dossier => dossier.id === dossierId);
|
||||
// if (notFound) {
|
||||
// return this._router.navigate(['/main/dossiers']).then();
|
||||
// }
|
||||
if (!this.has(dossierId)) {
|
||||
this._activeDossier$.next(undefined);
|
||||
return this._router.navigate(['/main/dossiers']).then();
|
||||
}
|
||||
|
||||
this._activeDossierId$.next(dossierId);
|
||||
this._activeDossier$.next(this.find(dossierId));
|
||||
this.updateDossierDictionary(this.activeDossier.dossierTemplateId, dossierId).then();
|
||||
});
|
||||
}
|
||||
|
||||
get allFiles(): File[] {
|
||||
return this.all.reduce((acc: File[], { files }) => [...acc, ...files], []);
|
||||
}
|
||||
|
||||
get activeDossier(): Dossier | undefined {
|
||||
return this._activeDossier$.value;
|
||||
}
|
||||
|
||||
get activeDossierId(): string | undefined {
|
||||
return this._activeDossier$.value?.dossierId;
|
||||
}
|
||||
|
||||
goToActiveDossier(): Promise<void> {
|
||||
return this._router.navigate([this.activeDossier?.routerLink]).then();
|
||||
}
|
||||
|
||||
find(dossierId: string): Dossier | undefined;
|
||||
find(dossierId: string, fileId: string): File | undefined;
|
||||
find(dossierId: string, fileId?: string): Dossier | File | undefined {
|
||||
const dossier = this.all.find(item => item.dossierId === dossierId);
|
||||
return fileId ? dossier?.files.find(file => file.fileId === fileId) : dossier;
|
||||
}
|
||||
|
||||
replace(newDossier: Dossier) {
|
||||
const dossiers = this.all.filter(dossier => dossier.dossierId !== newDossier.dossierId);
|
||||
dossiers.push(newDossier);
|
||||
this.setEntities(dossiers);
|
||||
this.dossierChanged$.next(newDossier);
|
||||
if (newDossier.dossierId === this.activeDossierId) {
|
||||
this._activeDossier$.next(newDossier);
|
||||
}
|
||||
}
|
||||
|
||||
has(dossierId: string): boolean {
|
||||
return this.all.some(dossier => dossier.dossierId === dossierId);
|
||||
}
|
||||
|
||||
async updateDossierDictionary(dossierTemplateId: string, dossierId: string) {
|
||||
// dossier exists, load its dictionary
|
||||
const dossier = this.find(dossierId);
|
||||
try {
|
||||
dossier.type = await this._dictionaryService.getFor(dossierTemplateId, 'dossier_redaction', dossierId).toPromise();
|
||||
} catch (e) {
|
||||
dossier.type = null;
|
||||
}
|
||||
}
|
||||
|
||||
get(): Observable<IDossier[]>;
|
||||
get(dossierId: string): Observable<IDossier>;
|
||||
get(dossierId?: string): Observable<IDossier | IDossier[]> {
|
||||
return dossierId ? super._getOne([dossierId]) : super.getAll();
|
||||
}
|
||||
|
||||
createOrUpdate(dossier: IDossier): Promise<IDossier> {
|
||||
return this._post(dossier).toPromise();
|
||||
@Validate()
|
||||
createOrUpdate(@RequiredParam() dossier: DossierRequest): Observable<Dossier | undefined> {
|
||||
return this._post(dossier).pipe(
|
||||
map(updatedDossier => new Dossier(updatedDossier, this.find(updatedDossier.dossierId)?.files ?? [])),
|
||||
tap(newDossier => this.replace(newDossier)),
|
||||
catchError(error => {
|
||||
this._toaster.error(error.status === 409 ? DOSSIER_EXISTS_MSG : GENERIC_MGS);
|
||||
return of(undefined);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
getDeleted(): Promise<IDossier[]> {
|
||||
return this.getAll('deleted-dossiers').toPromise();
|
||||
}
|
||||
|
||||
restore(dossierIds: List): Promise<unknown> {
|
||||
delete(dossier: Dossier): Observable<unknown> {
|
||||
const updateDossiers = () => {
|
||||
console.log(this.all.filter(d => d.dossierId !== dossier.dossierId));
|
||||
this.setEntities(this.all.filter(d => d.dossierId !== dossier.dossierId));
|
||||
};
|
||||
const showToast = () => {
|
||||
this._toaster.error(_('dossier-listing.delete.delete-failed'), { params: dossier });
|
||||
return of({});
|
||||
};
|
||||
return super.delete(dossier.dossierId).pipe(tap(updateDossiers), catchError(showToast));
|
||||
}
|
||||
|
||||
@Validate()
|
||||
restore(@RequiredParam() dossierIds: List): Promise<unknown> {
|
||||
return this._post(dossierIds, 'deleted-dossiers/restore').toPromise();
|
||||
}
|
||||
|
||||
hardDelete(dossierIds: List): Promise<unknown> {
|
||||
@Validate()
|
||||
hardDelete(@RequiredParam() dossierIds: List): Promise<unknown> {
|
||||
const body = dossierIds.map<QueryParam>(id => ({ key: 'dossierId', value: id }));
|
||||
return this.delete(body, 'deleted-dossiers/hard-delete', body).toPromise();
|
||||
return super.delete(body, 'deleted-dossiers/hard-delete', body).toPromise();
|
||||
}
|
||||
|
||||
private _computeStats(entities: List<Dossier>): IDossiersStats {
|
||||
|
||||
@ -10,6 +10,7 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { AnnotationActionMode } from '../models/annotation-action-mode.model';
|
||||
import { annotationActionsTranslations } from '../translations/annotation-actions-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossiersService } from './dossiers.service';
|
||||
|
||||
@Injectable()
|
||||
export class ManualAnnotationService {
|
||||
@ -19,6 +20,7 @@ export class ManualAnnotationService {
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _toaster: Toaster,
|
||||
@ -46,13 +48,13 @@ export class ManualAnnotationService {
|
||||
const obs = !secondParam
|
||||
? this._manualRedactionControllerService[this.CONFIG[mode]](
|
||||
body,
|
||||
this._appStateService.activeDossierId,
|
||||
this._dossiersService.activeDossierId,
|
||||
this._appStateService.activeFileId
|
||||
)
|
||||
: this._manualRedactionControllerService[this.CONFIG[mode]](
|
||||
body,
|
||||
secondParam,
|
||||
this._appStateService.activeDossierId,
|
||||
this._dossiersService.activeDossierId,
|
||||
this._appStateService.activeFileId
|
||||
);
|
||||
|
||||
@ -74,7 +76,7 @@ export class ManualAnnotationService {
|
||||
return this._manualRedactionControllerService.addComment(
|
||||
{ text: comment },
|
||||
annotationId,
|
||||
this._appStateService.activeDossierId,
|
||||
this._dossiersService.activeDossierId,
|
||||
this._appStateService.activeFileId
|
||||
);
|
||||
}
|
||||
@ -84,7 +86,7 @@ export class ManualAnnotationService {
|
||||
return this._manualRedactionControllerService.undoComment(
|
||||
annotationId,
|
||||
commentId,
|
||||
this._appStateService.activeDossierId,
|
||||
this._dossiersService.activeDossierId,
|
||||
this._appStateService.activeFileId
|
||||
);
|
||||
}
|
||||
|
||||
@ -11,11 +11,13 @@ import { FileDataModel } from '@models/file/file-data.model';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { File } from '@models/file/file';
|
||||
import { DossiersService } from './dossiers.service';
|
||||
|
||||
@Injectable()
|
||||
export class PdfViewerDataService {
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _man: ManualRedactionControllerService,
|
||||
private readonly _fileManagementControllerService: FileManagementControllerService,
|
||||
@ -25,7 +27,7 @@ export class PdfViewerDataService {
|
||||
|
||||
loadActiveFileRedactionLog() {
|
||||
return this._redactionLogControllerService
|
||||
.getRedactionLog(this._appStateService.activeDossierId, this._appStateService.activeFileId)
|
||||
.getRedactionLog(this._dossiersService.activeDossierId, this._appStateService.activeFileId)
|
||||
.pipe(
|
||||
tap(
|
||||
redactionLog => redactionLog.redactionLogEntry.sort((a, b) => a.positions[0].page - b.positions[0].page),
|
||||
@ -47,7 +49,7 @@ export class PdfViewerDataService {
|
||||
getViewedPagesForActiveFile() {
|
||||
if (this._permissionsService.canMarkPagesAsViewed()) {
|
||||
return this._viewedPagesControllerService
|
||||
.getViewedPages(this._appStateService.activeDossierId, this._appStateService.activeFileId)
|
||||
.getViewedPages(this._dossiersService.activeDossierId, this._appStateService.activeFileId)
|
||||
.pipe(catchError(() => of({ pages: [] })));
|
||||
}
|
||||
return of({ pages: [] });
|
||||
|
||||
@ -47,8 +47,8 @@
|
||||
|
||||
<!-- download redacted file-->
|
||||
<redaction-file-download-btn
|
||||
[dossier]="appStateService.activeDossier"
|
||||
[file]="file"
|
||||
[dossier]="dossiersService.activeDossier$ | async"
|
||||
[files]="[file]"
|
||||
[tooltipClass]="'small'"
|
||||
[tooltipPosition]="tooltipPosition"
|
||||
[type]="buttonType"
|
||||
|
||||
@ -20,6 +20,7 @@ import { filter } from 'rxjs/operators';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { LongPressEvent } from '@shared/directives/long-press.directive';
|
||||
import { FileActionService } from '../../services/file-action.service';
|
||||
import { DossiersService } from '../../../services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-file-actions',
|
||||
@ -60,6 +61,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
|
||||
constructor(
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly appStateService: AppStateService,
|
||||
readonly dossiersService: DossiersService,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _fileActionService: FileActionService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
@ -105,7 +107,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
|
||||
this._setup();
|
||||
});
|
||||
|
||||
this.addSubscription = this.appStateService.dossierChanged$.subscribe(() => {
|
||||
this.addSubscription = this.dossiersService.dossierChanged$.subscribe(() => {
|
||||
this._setup();
|
||||
});
|
||||
}
|
||||
@ -172,7 +174,7 @@ export class FileActionsComponent extends AutoUnsubscribe implements OnInit, OnD
|
||||
|
||||
setFileUnderApproval($event: MouseEvent) {
|
||||
$event.stopPropagation();
|
||||
if (this.appStateService.activeDossier.approverIds.length > 1) {
|
||||
if (this.dossiersService.activeDossier.approverIds.length > 1) {
|
||||
this._fileActionService.assignFile('approver', $event, this.file, () => this.reloadDossiers('assign-reviewer'), true);
|
||||
} else {
|
||||
this.addSubscription = this._fileActionService.setFilesUnderApproval([this.file]).subscribe(() => {
|
||||
|
||||
@ -8,6 +8,7 @@ import { DossiersDialogService } from '../../services/dossiers-dialog.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { FilesService } from '../../services/files.service';
|
||||
import { ConfirmationDialogInput } from '@iqser/common-ui';
|
||||
import { DossiersService } from '../../services/dossiers.service';
|
||||
|
||||
@Injectable()
|
||||
export class FileActionService {
|
||||
@ -17,11 +18,12 @@ export class FileActionService {
|
||||
private readonly _userService: UserService,
|
||||
private readonly _fileService: FilesService,
|
||||
private readonly _reanalysisControllerService: ReanalysisControllerService,
|
||||
private readonly _appStateService: AppStateService
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService
|
||||
) {}
|
||||
|
||||
reanalyseFile(file = this._appStateService.activeFile) {
|
||||
return this._reanalysisControllerService.reanalyzeFile(this._appStateService.activeDossier.id, file.fileId, true);
|
||||
return this._reanalysisControllerService.reanalyzeFile(this._dossiersService.activeDossier.id, file.fileId, true);
|
||||
}
|
||||
|
||||
toggleAnalysis(file = this._appStateService.activeFile) {
|
||||
@ -51,34 +53,34 @@ export class FileActionService {
|
||||
|
||||
setFilesUnderApproval(files: File[], approverId?: string) {
|
||||
if (!approverId) {
|
||||
approverId = this._appStateService.activeDossier.approverIds[0];
|
||||
approverId = this._dossiersService.activeDossier.approverIds[0];
|
||||
}
|
||||
|
||||
return this._fileService.setUnderApprovalFor(
|
||||
files.map(f => f.fileId),
|
||||
approverId,
|
||||
this._appStateService.activeDossierId
|
||||
this._dossiersService.activeDossierId
|
||||
);
|
||||
}
|
||||
|
||||
setFilesApproved(files: File[]) {
|
||||
return this._fileService.setApprovedFor(
|
||||
files.map(f => f.fileId),
|
||||
this._appStateService.activeDossierId
|
||||
this._dossiersService.activeDossierId
|
||||
);
|
||||
}
|
||||
|
||||
setFilesUnderReview(files: File[]) {
|
||||
return this._fileService.setUnderReviewFor(
|
||||
files.map(f => f.fileId),
|
||||
this._appStateService.activeDossierId
|
||||
this._dossiersService.activeDossierId
|
||||
);
|
||||
}
|
||||
|
||||
ocrFiles(files: File[]) {
|
||||
return this._reanalysisControllerService.ocrFiles(
|
||||
files.map(f => f.fileId),
|
||||
this._appStateService.activeDossierId
|
||||
this._dossiersService.activeDossierId
|
||||
);
|
||||
}
|
||||
|
||||
@ -101,7 +103,7 @@ export class FileActionService {
|
||||
await this._fileService
|
||||
.setReviewerFor(
|
||||
files.map(f => f.fileId),
|
||||
this._appStateService.activeDossierId,
|
||||
this._dossiersService.activeDossierId,
|
||||
this._userService.currentUser.id
|
||||
)
|
||||
.toPromise();
|
||||
|
||||
@ -3,8 +3,7 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { Dossier } from '../../../../../state/model/dossier';
|
||||
import { File } from '@models/file/file';
|
||||
import { FileDownloadService } from '@upload-download/services/file-download.service';
|
||||
import { Toaster } from '@iqser/common-ui';
|
||||
import { AutoUnsubscribe, CircleButtonType, CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { AutoUnsubscribe, CircleButtonType, CircleButtonTypes, List, Toaster } from '@iqser/common-ui';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
|
||||
@ -18,7 +17,7 @@ export type MenuState = 'OPEN' | 'CLOSED';
|
||||
})
|
||||
export class FileDownloadBtnComponent extends AutoUnsubscribe implements OnDestroy {
|
||||
@Input() dossier: Dossier;
|
||||
@Input() file: File | File[];
|
||||
@Input() files: List<File>;
|
||||
@Input() tooltipPosition: 'above' | 'below' | 'before' | 'after' = 'above';
|
||||
@Input() type: CircleButtonType = CircleButtonTypes.default;
|
||||
@Input() tooltipClass: string;
|
||||
@ -34,11 +33,7 @@ export class FileDownloadBtnComponent extends AutoUnsubscribe implements OnDestr
|
||||
}
|
||||
|
||||
get canDownloadFiles() {
|
||||
if (!Array.isArray(this.file)) {
|
||||
return this._permissionsService.canDownloadFiles(this.file);
|
||||
}
|
||||
|
||||
return this.file.length > 0 && this.file.reduce((acc, file) => acc && this._permissionsService.canDownloadFiles(file), true);
|
||||
return this.files.length > 0 && this.files.reduce((acc, file) => acc && this._permissionsService.canDownloadFiles(file), true);
|
||||
}
|
||||
|
||||
get tooltip() {
|
||||
@ -50,7 +45,7 @@ export class FileDownloadBtnComponent extends AutoUnsubscribe implements OnDestr
|
||||
downloadFiles($event: MouseEvent) {
|
||||
$event.stopPropagation();
|
||||
this.addSubscription = this._fileDownloadService
|
||||
.downloadFiles(Array.isArray(this.file) ? this.file : [this.file], this.dossier)
|
||||
.downloadFiles(this.files, this.dossier)
|
||||
.subscribe(() => this._toaster.info(_('download-status.queued')));
|
||||
}
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@
|
||||
<div class="iqser-input-group w-200 mt-0">
|
||||
<mat-select [(ngModel)]="dossier" [disabled]="!compare">
|
||||
<mat-option [value]="selectDossier">{{ selectDossier.dossierName | translate }}</mat-option>
|
||||
<mat-option *ngFor="let dossier of dossiers" [value]="dossier">
|
||||
<mat-option *ngFor="let dossier of dossiersService.all$ | async" [value]="dossier">
|
||||
{{ dossier.dossierName }}
|
||||
</mat-option>
|
||||
</mat-select>
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Component, EventEmitter, Input, OnChanges, OnInit, Output } from '@angular/core';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { Debounce, IconButtonTypes, List } from '@iqser/common-ui';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map, take } from 'rxjs/operators';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DictionaryService } from '@shared/services/dictionary.service';
|
||||
import { DossiersService } from '../../../dossier/services/dossiers.service';
|
||||
import ICodeEditor = monaco.editor.ICodeEditor;
|
||||
import IDiffEditor = monaco.editor.IDiffEditor;
|
||||
import IModelDeltaDecoration = monaco.editor.IModelDeltaDecoration;
|
||||
@ -44,7 +44,7 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
|
||||
private _decorations: string[] = [];
|
||||
private _searchDecorations: string[] = [];
|
||||
|
||||
constructor(private readonly _dictionaryService: DictionaryService, private readonly _appStateService: AppStateService) {}
|
||||
constructor(private readonly _dictionaryService: DictionaryService, readonly dossiersService: DossiersService) {}
|
||||
|
||||
private _dossier: Dossier = this.selectDossier as Dossier;
|
||||
|
||||
@ -72,10 +72,6 @@ export class DictionaryManagerComponent implements OnChanges, OnInit {
|
||||
});
|
||||
}
|
||||
|
||||
get dossiers() {
|
||||
return this._appStateService.allDossiers;
|
||||
}
|
||||
|
||||
get editorValue(): string {
|
||||
return this.currentEntries.join('\n');
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { AppStateService } from '../../../../state/app-state.service';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { INestedFilter } from '@iqser/common-ui';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -4,7 +4,7 @@ import { FileUploadModel } from '../model/file-upload.model';
|
||||
import { OverlayRef } from '@angular/cdk/overlay';
|
||||
import { StatusOverlayService } from '../services/status-overlay.service';
|
||||
import { handleFileDrop } from '@utils/file-drop-utils';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { DossiersService } from '../../dossier/services/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-file-drop',
|
||||
@ -15,7 +15,7 @@ export class FileDropComponent {
|
||||
constructor(
|
||||
private readonly _dialogRef: OverlayRef,
|
||||
private readonly _fileUploadService: FileUploadService,
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _statusOverlayService: StatusOverlayService
|
||||
) {}
|
||||
@ -33,7 +33,7 @@ export class FileDropComponent {
|
||||
|
||||
@HostListener('drop', ['$event'])
|
||||
onDrop(event: DragEvent) {
|
||||
handleFileDrop(event, this._appStateService.activeDossier, this.uploadFiles.bind(this));
|
||||
handleFileDrop(event, this._dossiersService.activeDossier, this.uploadFiles.bind(this));
|
||||
}
|
||||
|
||||
@HostListener('dragover', ['$event'])
|
||||
|
||||
@ -10,6 +10,7 @@ import { DownloadStatusWrapper } from '../model/download-status.wrapper';
|
||||
import { AppStateService } from '@state/app-state.service';
|
||||
import { KeycloakService } from 'keycloak-angular';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { List } from '@iqser/common-ui';
|
||||
|
||||
@Injectable()
|
||||
export class FileDownloadService {
|
||||
@ -34,7 +35,7 @@ export class FileDownloadService {
|
||||
});
|
||||
}
|
||||
|
||||
downloadFiles(files: File[], dossier: Dossier): Observable<any> {
|
||||
downloadFiles(files: List<File>, dossier: Dossier): Observable<any> {
|
||||
return this._downloadControllerService
|
||||
.prepareDownload({
|
||||
fileIds: files.map(f => f.fileId),
|
||||
|
||||
@ -10,6 +10,7 @@ import { toNumber } from '@utils/functions';
|
||||
import { UploadControllerService } from '@redaction/red-ui-http';
|
||||
import { isCsv } from '@utils/file-drop-utils';
|
||||
import { ErrorMessageService } from '@iqser/common-ui';
|
||||
import { DossiersService } from '../../dossier/services/dossiers.service';
|
||||
|
||||
export interface ActiveUpload {
|
||||
subscription: Subscription;
|
||||
@ -28,6 +29,7 @@ export class FileUploadService {
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _applicationRef: ApplicationRef,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _configService: ConfigService,
|
||||
@ -57,7 +59,7 @@ export class FileUploadService {
|
||||
async uploadFiles(files: FileUploadModel[]): Promise<number> {
|
||||
const maxSizeMB = this._configService.values.MAX_FILE_SIZE_MB;
|
||||
const maxSizeBytes = toNumber(maxSizeMB) * 1024 * 1024;
|
||||
const dossierFiles = this._appStateService.activeDossier.files;
|
||||
const dossierFiles = this._dossiersService.activeDossier.files;
|
||||
let option: 'overwrite' | 'skip';
|
||||
for (let idx = 0; idx < files.length; ++idx) {
|
||||
const file = files[idx];
|
||||
|
||||
@ -4,26 +4,31 @@ import { UserService } from './user.service';
|
||||
import { File } from '@models/file/file';
|
||||
import { Comment } from '@redaction/red-ui-http';
|
||||
import { Dossier } from '@state/model/dossier';
|
||||
import { DossiersService } from '../modules/dossier/services/dossiers.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class PermissionsService {
|
||||
constructor(private readonly _appStateService: AppStateService, private readonly _userService: UserService) {}
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _dossiersService: DossiersService
|
||||
) {}
|
||||
|
||||
private get _activeFile(): File | undefined {
|
||||
return this._appStateService.activeFile;
|
||||
}
|
||||
|
||||
private get _activeDossier(): Dossier | undefined {
|
||||
return this._appStateService.activeDossier;
|
||||
return this._dossiersService.activeDossier;
|
||||
}
|
||||
|
||||
isReviewerOrApprover(file?: File): boolean {
|
||||
return this.isFileReviewer(file) || this.isApprover();
|
||||
}
|
||||
|
||||
displayReanalyseBtn(dossier = this._activeDossier): boolean {
|
||||
displayReanalyseBtn(dossier: Dossier): boolean {
|
||||
return this.isApprover(dossier) && dossier.files.filter(file => file.analysisRequired).length > 0;
|
||||
}
|
||||
|
||||
@ -46,7 +51,7 @@ export class PermissionsService {
|
||||
canAssignToSelf(file = this._activeFile): boolean {
|
||||
const precondition = this.isDossierMember() && !file.isProcessing && !file.isError && !file.isApproved;
|
||||
|
||||
const isTheOnlyReviewer = !this._appStateService.activeDossier?.hasReviewers;
|
||||
const isTheOnlyReviewer = !this._activeDossier?.hasReviewers;
|
||||
|
||||
if (precondition) {
|
||||
if (
|
||||
@ -85,7 +90,7 @@ export class PermissionsService {
|
||||
return file?.isUnderReview && this.isReviewerOrApprover(file);
|
||||
}
|
||||
|
||||
isOwner(dossier = this._activeDossier, user = this._userService.currentUser): boolean {
|
||||
isOwner(dossier: Dossier, user = this._userService.currentUser): boolean {
|
||||
return dossier?.ownerId === user.id;
|
||||
}
|
||||
|
||||
@ -113,8 +118,8 @@ export class PermissionsService {
|
||||
return ['UNDER_REVIEW', 'UNDER_APPROVAL'].includes(file?.status) && this.isFileReviewer(file);
|
||||
}
|
||||
|
||||
canDownloadFiles(file = this._activeFile): boolean {
|
||||
const dossier = this._appStateService.getDossierById(file?.dossierId);
|
||||
canDownloadFiles(file: File): boolean {
|
||||
const dossier = this._dossiersService.find(file?.dossierId);
|
||||
if (!dossier) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
|
||||
import { AppStateService } from './app-state.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { DossiersService } from '../modules/dossier/services/dossiers.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
@ -9,6 +10,7 @@ import { UserService } from '@services/user.service';
|
||||
export class AppStateGuard implements CanActivate {
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _router: Router
|
||||
) {}
|
||||
@ -30,12 +32,12 @@ export class AppStateGuard implements CanActivate {
|
||||
|
||||
const { dossierId, fileId, dossierTemplateId, type } = route.params;
|
||||
|
||||
if (dossierId && !this._appStateService.getDossierById(dossierId)) {
|
||||
if (dossierId && !this._dossiersService.find(dossierId)) {
|
||||
await this._router.navigate(['main', 'dossiers']);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fileId && !this._appStateService.getFileById(dossierId, fileId)) {
|
||||
if (fileId && !this._dossiersService.find(dossierId, fileId)) {
|
||||
await this._router.navigate(['main', 'dossiers', dossierId]);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Colors, IDossier, IFile, ReanalysisControllerService } from '@redaction/red-ui-http';
|
||||
import { Colors, IFile, ReanalysisControllerService } from '@redaction/red-ui-http';
|
||||
import { Toaster } from '@iqser/common-ui';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { Event, NavigationEnd, ResolveStart, Router } from '@angular/router';
|
||||
import { Event, ResolveStart, Router } from '@angular/router';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { forkJoin, Observable, of, Subject } from 'rxjs';
|
||||
import { catchError, map, tap } from 'rxjs/operators';
|
||||
import { catchError, filter, first, map, tap } from 'rxjs/operators';
|
||||
import { FALLBACK_COLOR, hexToRgb } from '@utils/functions';
|
||||
import { File } from '@models/file/file';
|
||||
import { Dossier } from './model/dossier';
|
||||
import { TypeValue } from '@models/file/type-value';
|
||||
import { DossierTemplate } from '@models/file/dossier-template';
|
||||
import { DossiersService } from '../modules/dossier/services/dossiers.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { FilesService } from '../modules/dossier/services/files.service';
|
||||
import { DictionaryService } from '@shared/services/dictionary.service';
|
||||
@ -20,14 +19,10 @@ import { DossierTemplatesService } from '../modules/dossier/services/dossier-tem
|
||||
import { FileAttributesService } from '../modules/dossier/services/file-attributes.service';
|
||||
|
||||
export interface AppState {
|
||||
dossiers: Dossier[];
|
||||
dossierTemplates: DossierTemplate[];
|
||||
activeDossierId: string;
|
||||
activeFileId: string;
|
||||
activeDossierTemplateId: string;
|
||||
activeDictionaryType: string;
|
||||
totalAnalysedPages?: number;
|
||||
totalPeople?: number;
|
||||
activeFileId?: string;
|
||||
activeDossierTemplateId?: string;
|
||||
activeDictionaryType?: string;
|
||||
}
|
||||
|
||||
@Injectable({
|
||||
@ -36,7 +31,6 @@ export interface AppState {
|
||||
export class AppStateService {
|
||||
readonly fileChanged$ = new Subject<File>();
|
||||
readonly fileReanalysed$ = new Subject<File>();
|
||||
readonly dossierChanged$ = new Subject<Dossier>();
|
||||
readonly dossierTemplateChanged$ = new Subject<DossierTemplate>();
|
||||
|
||||
private _appState: AppState;
|
||||
@ -55,45 +49,37 @@ export class AppStateService {
|
||||
private readonly _userPreferenceService: UserPreferenceService
|
||||
) {
|
||||
this._appState = {
|
||||
dossiers: [],
|
||||
dossierTemplates: [],
|
||||
activeDossierId: null,
|
||||
activeFileId: null,
|
||||
activeDossierTemplateId: null,
|
||||
activeDictionaryType: null
|
||||
dossierTemplates: []
|
||||
};
|
||||
|
||||
_router.events.subscribe((event: Event) => {
|
||||
_router.events.subscribe(async (event: Event) => {
|
||||
if (AppStateService._isFileOverviewRoute(event)) {
|
||||
const url = (event as ResolveStart).url.replace('/main/dossiers/', '');
|
||||
const [dossierId, , fileId] = url.split(/[/?]/);
|
||||
return this.activateFile(dossierId, fileId);
|
||||
}
|
||||
if (AppStateService._isDossierOverviewRoute(event)) {
|
||||
const dossierId = (event as ResolveStart).url.replace('/main/dossiers/', '');
|
||||
return this.activateDossier(dossierId);
|
||||
}
|
||||
if (AppStateService._isRandomRoute(event)) {
|
||||
this._appState.activeDossierId = null;
|
||||
await _dossiersService.activeDossier$
|
||||
.pipe(
|
||||
filter(dossier => !!dossier),
|
||||
first()
|
||||
)
|
||||
.toPromise();
|
||||
return await this.activateFile(dossierId, fileId);
|
||||
}
|
||||
|
||||
this._appState.activeFileId = undefined;
|
||||
});
|
||||
}
|
||||
|
||||
private _dictionaryData: { [key: string]: { [key: string]: TypeValue } } = null;
|
||||
private _dictionaryData?: { [key: string]: { [key: string]: TypeValue } };
|
||||
|
||||
get dictionaryData(): { [key: string]: { [key: string]: TypeValue } } {
|
||||
get dictionaryData(): { [key: string]: { [key: string]: TypeValue } } | undefined {
|
||||
return this._dictionaryData;
|
||||
}
|
||||
|
||||
get aggregatedFiles(): File[] {
|
||||
return this.allDossiers.reduce((acc, { files }) => [...acc, ...files], []);
|
||||
}
|
||||
|
||||
get activeDossierTemplateId(): string {
|
||||
get activeDossierTemplateId(): string | undefined {
|
||||
return this._appState.activeDossierTemplateId;
|
||||
}
|
||||
|
||||
get activeDossierTemplate(): DossierTemplate {
|
||||
get activeDossierTemplate(): DossierTemplate | undefined {
|
||||
return this.getDossierTemplateById(this.activeDossierTemplateId);
|
||||
}
|
||||
|
||||
@ -101,95 +87,65 @@ export class AppStateService {
|
||||
return this._appState.dossierTemplates;
|
||||
}
|
||||
|
||||
get activeDictionaryType(): string {
|
||||
get activeDictionaryType(): string | undefined {
|
||||
return this._appState.activeDictionaryType;
|
||||
}
|
||||
|
||||
get activeDictionary(): TypeValue {
|
||||
return this.activeDossierTemplateId && this.dictionaryData[this.activeDossierTemplateId]
|
||||
get activeDictionary(): TypeValue | undefined {
|
||||
return this.activeDossierTemplateId &&
|
||||
this.activeDictionaryType &&
|
||||
this.dictionaryData &&
|
||||
this.dictionaryData[this.activeDossierTemplateId]
|
||||
? this.dictionaryData[this.activeDossierTemplateId][this.activeDictionaryType]
|
||||
: null;
|
||||
}
|
||||
|
||||
get activeDossierId(): string {
|
||||
return this._appState.activeDossierId;
|
||||
}
|
||||
|
||||
get activeDossier(): Dossier | undefined {
|
||||
return this.allDossiers.find(p => p.id === this.activeDossierId);
|
||||
}
|
||||
|
||||
get allDossiers(): Dossier[] {
|
||||
return this._appState.dossiers;
|
||||
}
|
||||
|
||||
get hasDossiers() {
|
||||
return this.allDossiers?.length > 0;
|
||||
: undefined;
|
||||
}
|
||||
|
||||
get activeFile(): File | undefined {
|
||||
return this.activeDossier?.files.find(f => f.fileId === this.activeFileId);
|
||||
return this._dossiersService.activeDossier?.files.find(f => f.fileId === this.activeFileId);
|
||||
}
|
||||
|
||||
get activeFileId(): string {
|
||||
get activeFileId(): string | undefined {
|
||||
return this._appState.activeFileId;
|
||||
}
|
||||
|
||||
get totalAnalysedPages(): number {
|
||||
return this._appState.totalAnalysedPages;
|
||||
}
|
||||
|
||||
get totalPeople(): number {
|
||||
return this._appState.totalPeople;
|
||||
}
|
||||
|
||||
private static _isFileOverviewRoute(event: Event) {
|
||||
return event instanceof ResolveStart && event.url.includes('/main/dossiers/') && event.url.includes('/file/');
|
||||
}
|
||||
|
||||
private static _isDossierOverviewRoute(event: Event) {
|
||||
return (
|
||||
event instanceof ResolveStart &&
|
||||
event.url.includes('/main/dossiers/') &&
|
||||
!event.url.includes('/file/') &&
|
||||
!event.url.includes('/search')
|
||||
);
|
||||
}
|
||||
|
||||
private static _isRandomRoute(event: Event) {
|
||||
return event instanceof NavigationEnd && !event.url.includes('/main/dossiers/') && !event.url.includes('/file/');
|
||||
}
|
||||
|
||||
async reloadActiveDossierFilesIfNecessary() {
|
||||
if (this.activeDossier?.hasPendingOrProcessing) {
|
||||
if (this._dossiersService.activeDossier?.hasPendingOrProcessing) {
|
||||
await this.reloadActiveDossierFiles();
|
||||
}
|
||||
}
|
||||
|
||||
getDictionaryColor(type?: string, dossierTemplateId = this.activeDossier?.dossierTemplateId) {
|
||||
getDictionaryColor(type?: string, dossierTemplateId = this._dossiersService.activeDossier?.dossierTemplateId) {
|
||||
if (!dossierTemplateId) {
|
||||
dossierTemplateId = this.dossierTemplates[0]?.dossierTemplateId;
|
||||
}
|
||||
if (!dossierTemplateId) {
|
||||
|
||||
if (!dossierTemplateId || !this._dictionaryData) {
|
||||
return '#cccccc';
|
||||
}
|
||||
const color = this._dictionaryData[dossierTemplateId][type]?.hexColor;
|
||||
|
||||
let color;
|
||||
if (type) {
|
||||
color = this._dictionaryData[dossierTemplateId][type]?.hexColor;
|
||||
}
|
||||
return color ?? this._dictionaryData[dossierTemplateId]['default'].hexColor;
|
||||
}
|
||||
|
||||
getDossierTemplateById(id: string): DossierTemplate {
|
||||
getDossierTemplateById(id?: string): DossierTemplate | undefined {
|
||||
if (!id) {
|
||||
return undefined;
|
||||
}
|
||||
return this.dossierTemplates.find(rs => rs.dossierTemplateId === id);
|
||||
}
|
||||
|
||||
getDictionaryTypeValue(key: string, dossierTemplateId?: string): TypeValue {
|
||||
if (!dossierTemplateId && this.activeDossier) {
|
||||
dossierTemplateId = this.activeDossier.dossierTemplateId;
|
||||
}
|
||||
|
||||
getDictionaryTypeValue(key: string, dossierTemplateId = this._dossiersService.activeDossier.dossierTemplateId): TypeValue | undefined {
|
||||
if (!dossierTemplateId) {
|
||||
dossierTemplateId = this.dossierTemplates.length > 0 ? this.dossierTemplates[0].dossierTemplateId : undefined;
|
||||
}
|
||||
if (!dossierTemplateId) {
|
||||
if (!dossierTemplateId || !this._dictionaryData) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -197,49 +153,43 @@ export class AppStateService {
|
||||
return data ? data : this._dictionaryData[dossierTemplateId]['default'];
|
||||
}
|
||||
|
||||
getDossierById(id: string) {
|
||||
return this.allDossiers.find(dossier => dossier.id === id);
|
||||
}
|
||||
|
||||
getFileById(dossierId: string, fileId: string) {
|
||||
return this.getDossierById(dossierId)?.files.find(file => file.fileId === fileId);
|
||||
}
|
||||
|
||||
async loadAllDossiers(emitEvents: boolean = true) {
|
||||
async loadAllDossiers(emitEvents = true) {
|
||||
const dossiers = await this._dossiersService.get().toPromise();
|
||||
if (!dossiers) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mappedDossiers = dossiers.map(p => new Dossier(p, this._getExistingFiles(p.dossierId)));
|
||||
const getFiles = (dossierId: string) => this._dossiersService.find(dossierId)?.files ?? [];
|
||||
const mappedDossiers = dossiers.map(p => new Dossier(p, getFiles(p.dossierId)));
|
||||
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);
|
||||
this._processFiles(dossier, fileData[dossierId], emitEvents);
|
||||
if (dossier) {
|
||||
this._processFiles(dossier, fileData[dossierId], emitEvents);
|
||||
}
|
||||
}
|
||||
|
||||
this._appState.dossiers = mappedDossiers;
|
||||
this._computeStats();
|
||||
}
|
||||
|
||||
async reloadActiveFile() {
|
||||
if (!this.activeFile) {
|
||||
const activeDossier = this._dossiersService.activeDossier;
|
||||
|
||||
if (!this.activeFile || !activeDossier) {
|
||||
return null;
|
||||
}
|
||||
const oldProcessedDate = this.activeFile.lastProcessed;
|
||||
const dossierTemplateId = this.activeFile.dossierTemplateId;
|
||||
const iFile = await this._filesService.get(this.activeDossierId, this.activeFileId).toPromise();
|
||||
iFile.dossierTemplateId = dossierTemplateId;
|
||||
const iFile = await this._filesService.get(activeDossier.dossierId, this.activeFileId).toPromise();
|
||||
|
||||
const activeFile = new File(
|
||||
iFile,
|
||||
this._userService.getNameForId(iFile.currentReviewer),
|
||||
this._fileAttributesService.getFileAttributeConfig(iFile.dossierTemplateId)
|
||||
this._fileAttributesService.getFileAttributeConfig(activeDossier.dossierTemplateId)
|
||||
);
|
||||
this.activeDossier.files = this.activeDossier?.files.map(file => (file.fileId === activeFile.fileId ? activeFile : file));
|
||||
const files = activeDossier.files.filter(file => file.fileId !== activeFile.fileId);
|
||||
files.push(activeFile);
|
||||
const newDossier = new Dossier(activeDossier, files);
|
||||
this._dossiersService.replace(newDossier);
|
||||
|
||||
this._computeStats();
|
||||
if (activeFile.lastProcessed !== oldProcessedDate) {
|
||||
this.fileReanalysed$.next(activeFile);
|
||||
}
|
||||
@ -247,48 +197,25 @@ export class AppStateService {
|
||||
return activeFile;
|
||||
}
|
||||
|
||||
async getFiles(dossier: Dossier = this.activeDossier, emitEvents = true) {
|
||||
async getFiles(dossier = this._dossiersService.activeDossier, emitEvents = true) {
|
||||
const files = await this._filesService.getFor(dossier.id).toPromise();
|
||||
|
||||
return this._processFiles(dossier, files, emitEvents);
|
||||
}
|
||||
|
||||
async reanalyzeDossier({ id }: Dossier = this.activeDossier) {
|
||||
async reanalyzeDossier({ id } = this._dossiersService.activeDossier) {
|
||||
await this._reanalysisControllerService.reanalyzeDossier(id, true).toPromise();
|
||||
}
|
||||
|
||||
async activateDossier(dossierId: string) {
|
||||
this._appState.activeFileId = null;
|
||||
this._appState.activeDossierId = dossierId;
|
||||
if (!this.activeDossier) {
|
||||
this._appState.activeDossierId = null;
|
||||
await this._router.navigate(['/main/dossiers']);
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateDossierDictionary(this.activeDossier.dossierTemplateId, dossierId);
|
||||
}
|
||||
|
||||
async updateDossierDictionary(dossierTemplateId: string, dossierId: string) {
|
||||
// dossier exists, load its dictionary
|
||||
const dossier = this.getDossierById(dossierId);
|
||||
try {
|
||||
dossier.type = await this._dictionaryService.getFor(dossierTemplateId, 'dossier_redaction', dossierId).toPromise();
|
||||
} catch (e) {
|
||||
dossier.type = null;
|
||||
}
|
||||
}
|
||||
|
||||
async activateFile(dossierId: string, fileId: string) {
|
||||
if (this.activeDossierId === dossierId && this.activeFileId === fileId) {
|
||||
if (this._dossiersService.activeDossierId === dossierId && this.activeFileId === fileId) {
|
||||
return;
|
||||
}
|
||||
await this.activateDossier(dossierId);
|
||||
if (this.activeDossier) {
|
||||
if (this._dossiersService.activeDossier) {
|
||||
this._appState.activeFileId = fileId;
|
||||
if (!this.activeFile) {
|
||||
this._appState.activeFileId = null;
|
||||
await this._router.navigate(['/main/dossiers/' + dossierId]);
|
||||
await this._dossiersService.goToActiveDossier();
|
||||
}
|
||||
}
|
||||
await this._updateLastActiveFileForDossier(dossierId, fileId);
|
||||
@ -316,47 +243,12 @@ export class AppStateService {
|
||||
|
||||
reset() {
|
||||
this._appState.activeFileId = null;
|
||||
this._appState.activeDossierId = null;
|
||||
this._appState.activeDossierTemplateId = null;
|
||||
this._appState.activeDictionaryType = null;
|
||||
}
|
||||
|
||||
deleteDossier(dossier: Dossier) {
|
||||
return this._dossiersService
|
||||
.delete(dossier.id)
|
||||
.toPromise()
|
||||
.then(
|
||||
() => {
|
||||
const index = this.allDossiers.findIndex(p => p.id === dossier.id);
|
||||
this._appState.dossiers.splice(index, 1);
|
||||
},
|
||||
() => this._toaster.error(_('dossier-listing.delete.delete-failed'), { params: dossier })
|
||||
);
|
||||
}
|
||||
|
||||
async createOrUpdateDossier(dossier: IDossier) {
|
||||
try {
|
||||
const updatedDossier = await this._dossiersService.createOrUpdate(dossier);
|
||||
let foundDossier = this.allDossiers.find(p => p.id === updatedDossier.dossierId);
|
||||
if (foundDossier) {
|
||||
this._appState.dossiers.splice(this._appState.dossiers.indexOf(foundDossier), 1);
|
||||
foundDossier = new Dossier(updatedDossier, foundDossier.files);
|
||||
} else {
|
||||
foundDossier = new Dossier(updatedDossier, []);
|
||||
}
|
||||
|
||||
this._appState.dossiers.push(foundDossier);
|
||||
this.dossierChanged$.next(foundDossier);
|
||||
return foundDossier;
|
||||
} catch (error) {
|
||||
this._toaster.error(
|
||||
error.status === 409 ? _('add-dossier-dialog.errors.dossier-already-exists') : _('add-dossier-dialog.errors.generic')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async reloadActiveDossierFiles() {
|
||||
if (this.activeDossierId) {
|
||||
if (this._dossiersService.activeDossierId) {
|
||||
await this.getFiles();
|
||||
}
|
||||
}
|
||||
@ -391,7 +283,7 @@ export class AppStateService {
|
||||
}
|
||||
|
||||
async loadAllDossiersIfNecessary() {
|
||||
if (!this.allDossiers.length) {
|
||||
if (!this._dossiersService.all.length) {
|
||||
await this.loadAllDossiers();
|
||||
}
|
||||
}
|
||||
@ -407,7 +299,7 @@ export class AppStateService {
|
||||
async loadDictionaryData(): Promise<void> {
|
||||
const observables = [];
|
||||
for (const dossierTemplate of this.dossierTemplates) {
|
||||
observables.push(this._getDictionaryDataForDossierTemplateObservables(dossierTemplate.dossierTemplateId));
|
||||
observables.push(this._getDictionaryDataForDossierTemplate$(dossierTemplate.dossierTemplateId));
|
||||
}
|
||||
const result = await forkJoin(observables).toPromise();
|
||||
|
||||
@ -420,7 +312,7 @@ export class AppStateService {
|
||||
}
|
||||
|
||||
async refreshDossierTemplateDictionaryData(dossierTemplateId: string) {
|
||||
this._dictionaryData[dossierTemplateId] = await this._getDictionaryDataForDossierTemplateObservables(dossierTemplateId).toPromise();
|
||||
this._dictionaryData[dossierTemplateId] = await this._getDictionaryDataForDossierTemplate$(dossierTemplateId).toPromise();
|
||||
}
|
||||
|
||||
loadColors(dossierTemplateId: string) {
|
||||
@ -442,7 +334,7 @@ export class AppStateService {
|
||||
);
|
||||
}
|
||||
|
||||
private _getDictionaryDataForDossierTemplateObservables(dossierTemplateId: string): Observable<{ [key: string]: any }> {
|
||||
private _getDictionaryDataForDossierTemplate$(dossierTemplateId: string): Observable<{ [key: string]: any }> {
|
||||
const dictionaryData: { [key: string]: any } = {};
|
||||
|
||||
const typeObs = this._dictionaryService.getAllTypes(dossierTemplateId).pipe(
|
||||
@ -650,96 +542,50 @@ export class AppStateService {
|
||||
})
|
||||
);
|
||||
|
||||
console.log(dictionaryData);
|
||||
|
||||
return forkJoin([typeObs, colorsObs]).pipe(map(() => dictionaryData));
|
||||
}
|
||||
|
||||
private async _updateLastActiveFileForDossier(dossierId: string, fileId: string) {
|
||||
this.activeDossier.files.forEach(f => {
|
||||
this._dossiersService.activeDossier.files.forEach(f => {
|
||||
f.lastOpened = f.fileId === fileId;
|
||||
});
|
||||
|
||||
await this._userPreferenceService.saveLastOpenedFileForDossier(dossierId, fileId);
|
||||
}
|
||||
|
||||
private _getExistingFiles(dossierId: string): File[] {
|
||||
const dossier = this.allDossiers.find(p => p.id === dossierId);
|
||||
return dossier?.files ?? [];
|
||||
}
|
||||
|
||||
private _processFiles(dossier: Dossier, iFiles: IFile[], emitEvents = true) {
|
||||
const oldFiles = [...dossier.files];
|
||||
const fileAttributes = this._fileAttributesService.getFileAttributeConfig(dossier.dossierTemplateId);
|
||||
const newFiles = iFiles.map(iFile => new File(iFile, this._userService.getNameForId(iFile.currentReviewer), fileAttributes));
|
||||
|
||||
const fileChangedEvent: File[] = [];
|
||||
const fileReanalysedEvent: File[] = [];
|
||||
const lastOpenedFileId = this._userPreferenceService.getLastOpenedFileForDossier(dossier.id);
|
||||
newFiles.forEach(file => (file.lastOpened = file.fileId === lastOpenedFileId));
|
||||
|
||||
for (const iFile of iFiles) {
|
||||
for (const newFile of newFiles) {
|
||||
let found = false;
|
||||
iFile.dossierTemplateId = dossier.dossierTemplateId;
|
||||
|
||||
for (const oldFile of oldFiles) {
|
||||
if (oldFile.fileId === iFile.fileId) {
|
||||
if (oldFile.fileId === newFile.fileId) {
|
||||
// emit when analysis count changed
|
||||
const file = new File(
|
||||
iFile,
|
||||
this._userService.getNameForId(iFile.currentReviewer),
|
||||
this._fileAttributesService.getFileAttributeConfig(iFile.dossierTemplateId)
|
||||
);
|
||||
file.lastOpened = file.fileId === this._userPreferenceService.getLastOpenedFileForDossier(dossier.id);
|
||||
if (JSON.stringify(oldFile) !== JSON.stringify(file)) {
|
||||
fileChangedEvent.push(file);
|
||||
if (JSON.stringify(oldFile) !== JSON.stringify(newFile) && emitEvents) {
|
||||
this.fileChanged$.next(newFile);
|
||||
}
|
||||
if (oldFile.lastProcessed !== iFile.lastProcessed) {
|
||||
fileReanalysedEvent.push(file);
|
||||
if (oldFile.lastProcessed !== newFile.lastProcessed && emitEvents) {
|
||||
this.fileReanalysed$.next(newFile);
|
||||
}
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// emit for new file
|
||||
if (!found) {
|
||||
const file = new File(
|
||||
iFile,
|
||||
this._userService.getNameForId(iFile.currentReviewer),
|
||||
this._fileAttributesService.getFileAttributeConfig(iFile.dossierTemplateId)
|
||||
);
|
||||
fileChangedEvent.push(file);
|
||||
if (!found && emitEvents) {
|
||||
this.fileChanged$.next(newFile);
|
||||
}
|
||||
}
|
||||
|
||||
dossier.files = iFiles.map(
|
||||
iFile =>
|
||||
new File(
|
||||
iFile,
|
||||
this._userService.getNameForId(iFile.currentReviewer),
|
||||
this._fileAttributesService.getFileAttributeConfig(iFile.dossierTemplateId)
|
||||
)
|
||||
);
|
||||
this._computeStats();
|
||||
const newDossier = new Dossier(dossier, newFiles);
|
||||
this._dossiersService.replace(newDossier);
|
||||
|
||||
if (emitEvents) {
|
||||
fileReanalysedEvent.forEach(file => this.fileReanalysed$.next(file));
|
||||
fileChangedEvent.forEach(file => this.fileChanged$.next(file));
|
||||
}
|
||||
|
||||
const lastOpenedFileId = this._userPreferenceService.getLastOpenedFileForDossier(dossier.id);
|
||||
|
||||
dossier.files.forEach(file => (file.lastOpened = file.fileId === lastOpenedFileId));
|
||||
|
||||
return iFiles;
|
||||
}
|
||||
|
||||
private _computeStats() {
|
||||
let totalAnalysedPages = 0;
|
||||
const totalPeople = new Set<string>();
|
||||
|
||||
this.allDossiers.forEach(d => {
|
||||
d.memberIds?.forEach(m => totalPeople.add(m));
|
||||
totalAnalysedPages += d.totalNumberOfPages;
|
||||
});
|
||||
|
||||
this._appState.totalPeople = totalPeople.size;
|
||||
this._appState.totalAnalysedPages = totalAnalysedPages;
|
||||
return newFiles;
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,9 +4,10 @@ import { IListable } from '@iqser/common-ui';
|
||||
export class DossierAttributeConfig implements IDossierAttributeConfig, IListable {
|
||||
readonly id: string;
|
||||
readonly editable: boolean;
|
||||
readonly label?: string;
|
||||
readonly label: string;
|
||||
readonly placeholder?: string;
|
||||
readonly type?: DossierAttributeConfigType;
|
||||
readonly dossierTemplateId: string;
|
||||
|
||||
constructor(dossierAttributeConfig: IDossierAttributeConfig) {
|
||||
this.id = dossierAttributeConfig.id;
|
||||
@ -14,6 +15,7 @@ export class DossierAttributeConfig implements IDossierAttributeConfig, IListabl
|
||||
this.label = dossierAttributeConfig.label;
|
||||
this.placeholder = dossierAttributeConfig.placeholder;
|
||||
this.type = dossierAttributeConfig.type;
|
||||
this.dossierTemplateId = dossierAttributeConfig.dossierTemplateId;
|
||||
}
|
||||
|
||||
get searchKey(): string {
|
||||
|
||||
@ -4,38 +4,37 @@ import { IListable } from '@iqser/common-ui';
|
||||
|
||||
export class Dossier implements IDossier, IListable {
|
||||
readonly dossierId: string;
|
||||
readonly ownerId: string;
|
||||
readonly memberIds: List;
|
||||
readonly approverIds: List;
|
||||
readonly reportTemplateIds: List;
|
||||
readonly dossierTemplateId: string;
|
||||
readonly ownerId: string;
|
||||
readonly memberIds?: List;
|
||||
readonly approverIds?: List;
|
||||
readonly reportTemplateIds?: List;
|
||||
readonly dossierName: string;
|
||||
readonly date: string;
|
||||
readonly description: string;
|
||||
readonly downloadFileTypes: List<DownloadFileType>;
|
||||
readonly dueDate: string;
|
||||
readonly hardDeletedTime: string;
|
||||
readonly reportTypes: List;
|
||||
readonly softDeletedTime: string;
|
||||
readonly status: DossierStatus;
|
||||
readonly date?: string;
|
||||
readonly dueDate?: string;
|
||||
readonly description?: string;
|
||||
readonly downloadFileTypes?: List<DownloadFileType>;
|
||||
readonly hardDeletedTime?: string;
|
||||
readonly reportTypes?: List;
|
||||
readonly softDeletedTime?: string;
|
||||
readonly status?: DossierStatus;
|
||||
readonly watermarkEnabled: boolean;
|
||||
readonly hasReviewers: boolean;
|
||||
|
||||
reanalysisRequired = this._files.some(file => file.analysisRequired);
|
||||
hasFiles = this._files.length > 0;
|
||||
filesLength = this._files.length;
|
||||
readonly reanalysisRequired = this.files.some(file => file.analysisRequired);
|
||||
readonly hasFiles = this.files.length > 0;
|
||||
readonly filesLength = this.files.length;
|
||||
|
||||
totalNumberOfPages?: number;
|
||||
hintsOnly?: boolean;
|
||||
hasRedactions?: boolean;
|
||||
hasSuggestions?: boolean;
|
||||
hasNone?: boolean;
|
||||
hasPendingOrProcessing?: boolean;
|
||||
readonly totalNumberOfPages: number;
|
||||
readonly hintsOnly: boolean;
|
||||
readonly hasRedactions: boolean;
|
||||
readonly hasSuggestions: boolean;
|
||||
readonly hasNone: boolean;
|
||||
readonly hasPendingOrProcessing: boolean;
|
||||
|
||||
allFilesApproved?: boolean;
|
||||
type?: IDictionary;
|
||||
|
||||
constructor(dossier: IDossier, private _files: File[] = []) {
|
||||
constructor(dossier: IDossier, readonly files: List<File> = []) {
|
||||
this.dossierId = dossier.dossierId;
|
||||
this.approverIds = dossier.approverIds;
|
||||
this.date = dossier.date;
|
||||
@ -51,10 +50,29 @@ export class Dossier implements IDossier, IListable {
|
||||
this.reportTypes = dossier.reportTypes;
|
||||
this.softDeletedTime = dossier.softDeletedTime;
|
||||
this.status = dossier.status;
|
||||
this.watermarkEnabled = dossier.watermarkEnabled;
|
||||
this.hasReviewers = this.memberIds.length > 1;
|
||||
this.watermarkEnabled = !!dossier.watermarkEnabled;
|
||||
this.hasReviewers = !!this.memberIds && this.memberIds.length > 1;
|
||||
|
||||
this._recomputeFileStatus();
|
||||
let hintsOnly = false;
|
||||
let hasRedactions = false;
|
||||
let hasSuggestions = false;
|
||||
let totalNumberOfPages = 0;
|
||||
let hasPendingOrProcessing = false;
|
||||
|
||||
this.files.forEach(f => {
|
||||
hintsOnly = hintsOnly || f.hintsOnly;
|
||||
hasRedactions = hasRedactions || f.hasRedactions;
|
||||
hasSuggestions = hasSuggestions || f.hasSuggestions;
|
||||
totalNumberOfPages += f.numberOfPages ?? 0;
|
||||
hasPendingOrProcessing = hasPendingOrProcessing || f.isPending || f.isProcessing;
|
||||
});
|
||||
|
||||
this.hintsOnly = hintsOnly;
|
||||
this.hasRedactions = hasRedactions;
|
||||
this.hasSuggestions = hasSuggestions;
|
||||
this.totalNumberOfPages = totalNumberOfPages;
|
||||
this.hasPendingOrProcessing = hasPendingOrProcessing;
|
||||
this.hasNone = !this.hasSuggestions && !this.hasRedactions && !this.hintsOnly;
|
||||
}
|
||||
|
||||
get id(): string {
|
||||
@ -69,42 +87,11 @@ export class Dossier implements IDossier, IListable {
|
||||
return this.dossierName;
|
||||
}
|
||||
|
||||
get files(): File[] {
|
||||
return this._files;
|
||||
}
|
||||
|
||||
set files(files: File[]) {
|
||||
this._files = files ? files : [];
|
||||
this._recomputeFileStatus();
|
||||
}
|
||||
|
||||
hasStatus(status: string): boolean {
|
||||
return !!this._files.find(f => f.status === status);
|
||||
return !!this.files.find(f => f.status === status);
|
||||
}
|
||||
|
||||
hasMember(memberId: string): boolean {
|
||||
return this.memberIds.indexOf(memberId) >= 0;
|
||||
}
|
||||
|
||||
private _recomputeFileStatus() {
|
||||
this.hintsOnly = false;
|
||||
this.hasRedactions = false;
|
||||
this.hasSuggestions = false;
|
||||
this.hasNone = false;
|
||||
this.allFilesApproved = true;
|
||||
this.totalNumberOfPages = 0;
|
||||
this.hasPendingOrProcessing = false;
|
||||
this._files.forEach(f => {
|
||||
this.hintsOnly = this.hintsOnly || f.hintsOnly;
|
||||
this.hasRedactions = this.hasRedactions || f.hasRedactions;
|
||||
this.hasSuggestions = this.hasSuggestions || f.hasSuggestions;
|
||||
this.allFilesApproved = this.allFilesApproved && f.isApproved;
|
||||
this.totalNumberOfPages += f.numberOfPages;
|
||||
this.hasPendingOrProcessing = this.hasPendingOrProcessing || f.isPending || f.isProcessing;
|
||||
});
|
||||
this.hasNone = !this.hasSuggestions && !this.hasRedactions && !this.hintsOnly;
|
||||
this.hasFiles = this._files.length > 0;
|
||||
this.filesLength = this._files.length;
|
||||
this.reanalysisRequired = this._files.some(file => file.analysisRequired);
|
||||
return !!this.memberIds && this.memberIds.indexOf(memberId) >= 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import * as moment from 'moment';
|
||||
import { List } from '@iqser/common-ui';
|
||||
|
||||
export const FALLBACK_COLOR = '#CCCCCC';
|
||||
|
||||
export function groupBy(xs: any[], key: string) {
|
||||
export function groupBy(xs: List<unknown>, key: string) {
|
||||
return xs.reduce((rv, x) => {
|
||||
(rv[x[key]] = rv[x[key]] || []).push(x);
|
||||
return rv;
|
||||
|
||||
@ -15,7 +15,7 @@ export interface IAudit {
|
||||
readonly details?: unknown;
|
||||
readonly message?: string;
|
||||
readonly objectId?: string;
|
||||
readonly recordDate?: string;
|
||||
readonly recordDate: string;
|
||||
readonly recordId?: number;
|
||||
readonly userId?: string;
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ export interface IDictionary {
|
||||
/**
|
||||
* Label of the type
|
||||
*/
|
||||
readonly label?: string;
|
||||
readonly label: string;
|
||||
/**
|
||||
* The rank of this dictionary, higher rank means higher importance.
|
||||
*/
|
||||
|
||||
@ -12,17 +12,17 @@
|
||||
import { List } from '../red-types';
|
||||
|
||||
export interface IDossier {
|
||||
readonly dossierId: string;
|
||||
readonly dossierName: string;
|
||||
readonly dossierTemplateId: string;
|
||||
readonly approverIds?: List;
|
||||
readonly date?: string;
|
||||
readonly description?: string;
|
||||
readonly dossierId?: string;
|
||||
readonly dossierName?: string;
|
||||
readonly dossierTemplateId?: string;
|
||||
readonly downloadFileTypes?: List<DownloadFileType>;
|
||||
readonly dueDate?: string;
|
||||
readonly hardDeletedTime?: string;
|
||||
readonly memberIds?: List;
|
||||
readonly ownerId?: string;
|
||||
readonly ownerId: string;
|
||||
readonly reportTemplateIds?: List;
|
||||
readonly reportTypes?: List;
|
||||
readonly softDeletedTime?: string;
|
||||
|
||||
@ -13,9 +13,9 @@
|
||||
export interface IDossierAttributeConfig {
|
||||
readonly id: string;
|
||||
readonly editable?: boolean;
|
||||
readonly label?: string;
|
||||
readonly label: string;
|
||||
readonly placeholder?: string;
|
||||
readonly dossierTemplateId?: string;
|
||||
readonly dossierTemplateId: string;
|
||||
readonly type?: DossierAttributeConfigType;
|
||||
}
|
||||
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
* https://github.com/swagger-api/swagger-codegen.git
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
import { FileAttributes } from './fileAttributes';
|
||||
import { FileAttributes } from "./fileAttributes";
|
||||
|
||||
/**
|
||||
* Object containing information on a specific file.
|
||||
@ -50,11 +50,7 @@ export interface IFile {
|
||||
/**
|
||||
* The ID of the dossier the file belongs to.
|
||||
*/
|
||||
readonly dossierId?: string;
|
||||
/**
|
||||
* The dossierTemplateId for this file.
|
||||
*/
|
||||
dossierTemplateId?: string;
|
||||
readonly dossierId: string;
|
||||
/**
|
||||
* Shows if the file was excluded from analysis.
|
||||
*/
|
||||
@ -67,11 +63,11 @@ export interface IFile {
|
||||
/**
|
||||
* The ID of the file.
|
||||
*/
|
||||
readonly fileId?: string;
|
||||
readonly fileId: string;
|
||||
/**
|
||||
* The file's name.
|
||||
*/
|
||||
readonly filename?: string;
|
||||
readonly filename: string;
|
||||
/**
|
||||
* Shows if this file has comments on annotations.
|
||||
*/
|
||||
@ -147,7 +143,7 @@ export interface IFile {
|
||||
/**
|
||||
* The status of the file with regard to its analysis an review processes.
|
||||
*/
|
||||
readonly status?: FileStatus;
|
||||
readonly status: FileStatus;
|
||||
/**
|
||||
* The ID of the user who uploaded the file.
|
||||
*/
|
||||
|
||||
@ -17,7 +17,7 @@ export interface IUser {
|
||||
/**
|
||||
* Email of user.
|
||||
*/
|
||||
readonly email?: string;
|
||||
readonly email: string;
|
||||
/**
|
||||
* First name of user.
|
||||
*/
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user