diff --git a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts index f47e7323e..63e81cb84 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component.ts @@ -157,12 +157,12 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent attr.primaryAttribute); - let fileAttributeConfigs = this.data.existingConfiguration.fileAttributeConfigs; + let fileAttributeConfigs = this.data.existingConfiguration.fileAttributeConfigs ?? []; if (newPrimary) { fileAttributeConfigs = fileAttributeConfigs.map(attr => new FileAttributeConfig({ ...attr, primaryAttribute: false })); } - const fileAttributes = { + const fileAttributes: IFileAttributesConfig = { ...this.baseConfigForm.getRawValue(), fileAttributeConfigs: [ ...fileAttributeConfigs.filter(a => !this.allEntities.find(entity => entity.csvColumn === a.csvColumnHeader)), @@ -173,12 +173,14 @@ export class FileAttributesCsvImportDialogComponent extends ListingComponent files.length), - distinctUntilChanged(), ); } diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html index c8e3d0b17..c56fb0f9c 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.html @@ -33,7 +33,7 @@
@@ -66,7 +66,7 @@
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.ts index 744641109..73f53d01c 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/components/dossier-details/dossier-details.component.ts @@ -12,6 +12,7 @@ import { ActivatedRoute } from '@angular/router'; import { Observable } from 'rxjs'; import { DossierStatsService } from '@services/entity-services/dossier-stats.service'; import { pluck, switchMap } from 'rxjs/operators'; +import { DossiersDialogService } from '../../../../services/dossiers-dialog.service'; @Component({ selector: 'redaction-dossier-details', @@ -22,8 +23,6 @@ import { pluck, switchMap } from 'rxjs/operators'; export class DossierDetailsComponent { editingOwner = false; @Input() dossierAttributes: DossierAttributeWithValue[]; - @Output() readonly openAssignDossierMembersDialog = new EventEmitter(); - @Output() readonly openDossierDictionaryDialog = new EventEmitter(); @Output() readonly toggleCollapse = new EventEmitter(); collapseTooltip = _('dossier-details.collapse'); expandTooltip = _('dossier-details.expand'); @@ -43,6 +42,7 @@ export class DossierDetailsComponent { private readonly _userService: UserService, private readonly _dossierStatsService: DossierStatsService, private readonly _toaster: Toaster, + private readonly _dialogService: DossiersDialogService, activatedRoute: ActivatedRoute, ) { this.dossierId = activatedRoute.snapshot.paramMap.get('dossierId'); @@ -77,4 +77,11 @@ export class DossierDetailsComponent { const dossierName = dossier.dossierName; this._toaster.info(_('assignment.owner'), { params: { ownerName, dossierName } }); } + + openEditDossierDialog(dossier: Dossier, section: string): void { + const data = { dossierId: this.dossierId, section }; + this._dialogService.openDialog('editDossier', null, data, async () => { + await this.appStateService.getFiles(dossier); + }); + } } diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html index ed6c8a24e..5a41d4587 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.html @@ -46,8 +46,6 @@
diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts index cd93a954d..d834b4d15 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts +++ b/apps/red-ui/src/app/modules/dossier/screens/dossier-overview/screen/dossier-overview-screen.component.ts @@ -20,7 +20,6 @@ import * as moment from 'moment'; import { Observable, timer } from 'rxjs'; import { switchMap, tap } from 'rxjs/operators'; import { convertFiles, Files, handleFileDrop } from '@utils/index'; -import { DossiersDialogService } from '../../../services/dossiers-dialog.service'; import { CircleButtonTypes, DefaultListingServices, @@ -84,7 +83,6 @@ export class DossierOverviewScreenComponent extends ListingComponent imple private readonly _dossiersService: DossiersService, private readonly _dossierTemplatesService: DossierTemplatesService, private readonly _appConfigService: AppConfigService, - private readonly _dialogService: DossiersDialogService, private readonly _fileUploadService: FileUploadService, private readonly _statusOverlayService: StatusOverlayService, private readonly _fileDropOverlayService: FileDropOverlayService, @@ -150,7 +148,10 @@ export class DossierOverviewScreenComponent extends ListingComponent imple this.addSubscription = this._fileMapService .get$(this.dossierId) - .pipe(tap(files => this.entitiesService.setEntities(files))) + .pipe( + tap(files => this.entitiesService.setEntities(files)), + tap(() => this._computeAllFilters()), + ) .subscribe(); this._fileDropOverlayService.initFileDropHandling(this.dossierId); @@ -226,20 +227,6 @@ export class DossierOverviewScreenComponent extends ListingComponent imple (this._fileInput as any).nativeElement.value = null; } - openAssignDossierMembersDialog(): void { - const data = { dossierId: this.dossierId, section: 'members' }; - this._dialogService.openDialog('editDossier', null, data, async () => { - await this.reloadFiles(); - }); - } - - openDossierDictionaryDialog() { - const data = { dossierId: this.dossierId, section: 'dossierDictionary' }; - this._dialogService.openDialog('editDossier', null, data, async () => { - await this.reloadFiles(); - }); - } - recentlyModifiedChecker = (file: File) => moment(file.lastUpdated).add(this._appConfigService.values.RECENT_PERIOD_IN_HOURS, 'hours').isAfter(moment()); diff --git a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.html b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.html index 00db21572..ffcf42195 100644 --- a/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.html +++ b/apps/red-ui/src/app/modules/dossier/screens/dossiers-listing/components/dossiers-listing-details/dossiers-listing-details.component.html @@ -1,6 +1,7 @@
this._toChartData(stats)), ); - this.dossiersChartData$ = this.dossiersService.all$.pipe(map(dossiers => this._toDossierChartData(dossiers))); + this.dossiersChartData$ = this.dossiersService.all$.pipe(switchMap(dossiers => this._toDossierChartData(dossiers))); } - private _toDossierChartData(dossiers: Dossier[]): DoughnutChartConfig[] { - const activeDossiersCount = dossiers.filter(p => p.status === DossierStatuses.ACTIVE).length; - const inactiveDossiersCount = dossiers.length - activeDossiersCount; - + private async _toDossierChartData(dossiers: Dossier[]): Promise { + // TODO: deleted dossiers count should come with stats + const deletedDossiers = await this.dossiersService.getDeleted(); return [ - { value: activeDossiersCount, color: 'ACTIVE', label: _('active') }, - { value: inactiveDossiersCount, color: 'DELETED', label: _('archived') }, + { value: dossiers.length, color: 'ACTIVE', label: _('active') }, + { value: deletedDossiers.length, color: 'DELETED', label: _('archived') }, ]; } diff --git a/apps/red-ui/src/app/modules/dossier/utils/file.guard.ts b/apps/red-ui/src/app/modules/dossier/utils/file.guard.ts new file mode 100644 index 000000000..566eddbfc --- /dev/null +++ b/apps/red-ui/src/app/modules/dossier/utils/file.guard.ts @@ -0,0 +1,32 @@ +import { Injectable } from '@angular/core'; +import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router'; +import { FilesMapService } from '@services/entity-services/files-map.service'; +import { AppStateService } from '@state/app-state.service'; +import { DossiersService } from '@services/entity-services/dossiers.service'; + +@Injectable() +export class FilesGuard implements CanActivate { + constructor( + private readonly _filesMapService: FilesMapService, + private readonly _dossiersService: DossiersService, + private readonly _appStateService: AppStateService, + private readonly _router: Router, + ) {} + + async canActivate(route: ActivatedRouteSnapshot): Promise { + const dossierId = route.paramMap.get('dossierId'); + const fileId = route.paramMap.get('fileId'); + + if (!this._filesMapService.get(dossierId, fileId)) { + const dossier = this._dossiersService.find(dossierId); + await this._appStateService.getFiles(dossier); + + if (!this._filesMapService.get(dossierId, fileId)) { + await this._router.navigate([dossier.routerLink]); + return false; + } + } + + return true; + } +} diff --git a/apps/red-ui/src/app/services/entity-services/dossiers.service.ts b/apps/red-ui/src/app/services/entity-services/dossiers.service.ts index 91cb93b2a..ebde93070 100644 --- a/apps/red-ui/src/app/services/entity-services/dossiers.service.ts +++ b/apps/red-ui/src/app/services/entity-services/dossiers.service.ts @@ -41,7 +41,7 @@ export class DossiersService extends EntitiesService { return combineLatest([dossier$, stats$]).pipe( map(([updatedDossier]) => new Dossier(updatedDossier)), - tap(newDossier => this.replace(newDossier)), + tap(newDossier => this.replace([newDossier])), catchError(showToast), ); } diff --git a/apps/red-ui/src/app/services/entity-services/files-map.service.ts b/apps/red-ui/src/app/services/entity-services/files-map.service.ts index 27c8bf090..d0758a22a 100644 --- a/apps/red-ui/src/app/services/entity-services/files-map.service.ts +++ b/apps/red-ui/src/app/services/entity-services/files-map.service.ts @@ -13,6 +13,10 @@ export class FilesMapService { constructor(private readonly _filesService: FilesService) {} get$(dossierId: string) { + if (!this._map.has(dossierId)) { + this._map.set(dossierId, new BehaviorSubject([])); + } + return this._map.get(dossierId).asObservable(); } diff --git a/apps/red-ui/src/app/services/user.service.ts b/apps/red-ui/src/app/services/user.service.ts index fe2626696..7ffdf7a9c 100644 --- a/apps/red-ui/src/app/services/user.service.ts +++ b/apps/red-ui/src/app/services/user.service.ts @@ -56,7 +56,7 @@ export class UserService extends EntitiesService { const userId = (<{ sub: string }>decoded).sub; const roles = this._keycloakService.getUserRoles(true).filter(role => role.startsWith('RED_')); - this.replace(new User(await this._keycloakService.loadUserProfile(true), roles, userId)); + this.replace([new User(await this._keycloakService.loadUserProfile(true), roles, userId)]); this._currentUser$.next(this.find(userId)); } diff --git a/apps/red-ui/src/app/state/app-state.service.ts b/apps/red-ui/src/app/state/app-state.service.ts index c3bd1dc02..75667f909 100644 --- a/apps/red-ui/src/app/state/app-state.service.ts +++ b/apps/red-ui/src/app/state/app-state.service.ts @@ -112,9 +112,7 @@ export class AppStateService { const dossierIds = dossiers.map(dossier => dossier.dossierId); await this._dossierStatsService.getFor(dossierIds).toPromise(); - dossiers.forEach(dossier => { - this._dossiersService.replace(new Dossier(dossier)); - }); + this._dossiersService.replace(dossiers.map(dossier => new Dossier(dossier))); } async reloadFile(dossierId: string, fileId: string) { @@ -175,7 +173,7 @@ export class AppStateService { await this._fileAttributesService.getFileAttributesConfig(dossierTemplateId).toPromise(); const newDossierTemplate = new DossierTemplate(dossierTemplate); - this._dossierTemplatesService.replace(newDossierTemplate); + this._dossierTemplatesService.replace([newDossierTemplate]); await this.refreshDossierTemplateDictionaryData(dossierTemplateId); } diff --git a/libs/common-ui b/libs/common-ui index 74fcbf080..17c65675b 160000 --- a/libs/common-ui +++ b/libs/common-ui @@ -1 +1 @@ -Subproject commit 74fcbf080b593622220bb2c7de08f69163acab04 +Subproject commit 17c65675b934698a61a2c80435f532e5a77f0c97 diff --git a/package.json b/package.json index ed3cbc059..e6f19fcf6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "redaction", - "version": "3.25.0", + "version": "3.30.0", "private": true, "license": "MIT", "scripts": { diff --git a/paligo-theme.tar.gz b/paligo-theme.tar.gz index 7df49637e..bc51f6cd9 100644 Binary files a/paligo-theme.tar.gz and b/paligo-theme.tar.gz differ