Merge branch 'RED-3313'
This commit is contained in:
commit
953fcbb7ce
@ -6,8 +6,9 @@ import { BaseScreenComponent } from '@components/base-screen/base-screen.compone
|
||||
import { RouteReuseStrategy, RouterModule, Routes } from '@angular/router';
|
||||
import { NgModule } from '@angular/core';
|
||||
import { DownloadsListScreenComponent } from '@components/downloads-list-screen/downloads-list-screen.component';
|
||||
import { DossiersGuard } from '@guards/dossiers.guard';
|
||||
import { DossierTemplatesGuard } from '@guards/dossier-templates.guard';
|
||||
import { DossiersGuard } from '@guards/dossiers.guard';
|
||||
import { ACTIVE_DOSSIERS_SERVICE, ARCHIVED_DOSSIERS_SERVICE } from './tokens';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@ -38,6 +39,18 @@ const routes: Routes = [
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard, DossierTemplatesGuard, DossiersGuard],
|
||||
requiredRoles: ['RED_USER', 'RED_MANAGER'],
|
||||
dossiersService: ACTIVE_DOSSIERS_SERVICE,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'main/archive',
|
||||
component: BaseScreenComponent,
|
||||
loadChildren: () => import('./modules/archive/archive.module').then(m => m.ArchiveModule),
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard, DossierTemplatesGuard, DossiersGuard],
|
||||
requiredRoles: ['RED_USER', 'RED_MANAGER'],
|
||||
dossiersService: ARCHIVED_DOSSIERS_SERVICE,
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -54,6 +67,16 @@ const routes: Routes = [
|
||||
routeGuards: [AuthGuard, RedRoleGuard],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'main/search',
|
||||
component: BaseScreenComponent,
|
||||
loadChildren: () => import('./modules/search/search.module').then(m => m.SearchModule),
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard, DossiersGuard],
|
||||
requiredRoles: ['RED_USER', 'RED_MANAGER'],
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '**',
|
||||
redirectTo: 'main/dossiers',
|
||||
|
||||
@ -20,7 +20,7 @@ import { AppRoutingModule } from './app-routing.module';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { FileUploadDownloadModule } from '@upload-download/file-upload-download.module';
|
||||
import { PlatformLocation } from '@angular/common';
|
||||
import { BASE_HREF } from './tokens';
|
||||
import { ACTIVE_DOSSIERS_SERVICE, ARCHIVED_DOSSIERS_SERVICE, BASE_HREF } from './tokens';
|
||||
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
|
||||
import { GlobalErrorHandler } from '@utils/global-error-handler.service';
|
||||
import { REDMissingTranslationHandler } from '@utils/missing-translations-handler';
|
||||
@ -44,6 +44,8 @@ import { GeneralSettingsService } from '@services/general-settings.service';
|
||||
import { BreadcrumbsComponent } from '@components/breadcrumbs/breadcrumbs.component';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.service';
|
||||
|
||||
export function httpLoaderFactory(httpClient: HttpClient, configService: ConfigService): PruningTranslationLoader {
|
||||
return new PruningTranslationLoader(httpClient, '/assets/i18n/', `.json?version=${configService.values.FRONTEND_APP_VERSION}`);
|
||||
@ -144,6 +146,14 @@ const components = [AppComponent, AuthErrorComponent, NotificationsComponent, Sp
|
||||
useFactory: (configService: ConfigService) => configService.values.MAX_RETRIES_ON_SERVER_ERROR,
|
||||
deps: [ConfigService],
|
||||
},
|
||||
{
|
||||
provide: ACTIVE_DOSSIERS_SERVICE,
|
||||
useExisting: ActiveDossiersService,
|
||||
},
|
||||
{
|
||||
provide: ARCHIVED_DOSSIERS_SERVICE,
|
||||
useExisting: ArchivedDossiersService,
|
||||
},
|
||||
DatePipe,
|
||||
],
|
||||
bootstrap: [AppComponent],
|
||||
|
||||
@ -3,7 +3,7 @@
|
||||
<div class="top-bar">
|
||||
<div *ngIf="!currentUser.isUser" class="menu-placeholder"></div>
|
||||
|
||||
<div *ngIf="currentUser.isUser" class="menu flex-2 visible-lg breadcrumbs-container">
|
||||
<div *ngIf="currentUser.isUser" class="flex-2 visible-lg breadcrumbs-container">
|
||||
<redaction-breadcrumbs></redaction-breadcrumbs>
|
||||
</div>
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
<div class="app-name">{{ titleService.getTitle() }}</div>
|
||||
</div>
|
||||
|
||||
<div class="menu right flex-2">
|
||||
<div class="actions flex-2">
|
||||
<div class="buttons">
|
||||
<redaction-spotlight-search
|
||||
*ngIf="(isSearchScreen$ | async) === false && (currentUser.isUser || currentUser.isManager)"
|
||||
|
||||
@ -1,3 +1,9 @@
|
||||
redaction-spotlight-search {
|
||||
margin-right: 16px !important;
|
||||
}
|
||||
|
||||
.actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
@ -19,7 +19,7 @@ interface MenuItem {
|
||||
}
|
||||
|
||||
const isNavigationStart = event => event instanceof NavigationStart;
|
||||
const isSearchScreen = url => url.includes('/main/dossiers') && url.includes('/search');
|
||||
const isSearchScreen: (url: string) => boolean = url => url.includes('/search');
|
||||
|
||||
@Component({
|
||||
templateUrl: './base-screen.component.html',
|
||||
@ -57,7 +57,12 @@ export class BaseScreenComponent {
|
||||
action: (query): void => this._searchThisDossier(query),
|
||||
},
|
||||
{
|
||||
text: this._translateService.instant('search.entire-platform'),
|
||||
text: this._translateService.instant('search.active-dossiers'),
|
||||
icon: 'red:enter',
|
||||
action: (query): void => this._search(query, [], true),
|
||||
},
|
||||
{
|
||||
text: this._translateService.instant('search.all-dossiers'),
|
||||
icon: 'red:enter',
|
||||
action: (query): void => this._search(query, []),
|
||||
},
|
||||
@ -80,12 +85,12 @@ export class BaseScreenComponent {
|
||||
) {}
|
||||
|
||||
private get _hideSearchThisDossier() {
|
||||
const routerLink = this.breadcrumbsService.breadcrumbs[1]?.routerLink;
|
||||
const routerLink = this.breadcrumbsService.breadcrumbs[1]?.options?.routerLink;
|
||||
if (!routerLink) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const isDossierOverview = routerLink.includes('dossiers') && routerLink.length === 3;
|
||||
const isDossierOverview = (routerLink.includes('dossiers') || routerLink.includes('archive')) && routerLink.length === 3;
|
||||
return !isDossierOverview;
|
||||
}
|
||||
|
||||
@ -93,13 +98,13 @@ export class BaseScreenComponent {
|
||||
return item.name;
|
||||
}
|
||||
|
||||
private _search(query: string, dossierIds: string[]) {
|
||||
const queryParams = { query, dossierIds: dossierIds.join(',') };
|
||||
this._router.navigate(['main/dossiers/search'], { queryParams }).then();
|
||||
private _search(query: string, dossierIds: string[], onlyActive = false) {
|
||||
const queryParams = { query, dossierIds: dossierIds.join(','), onlyActive };
|
||||
this._router.navigate(['main/search'], { queryParams }).then();
|
||||
}
|
||||
|
||||
private _searchThisDossier(query: string) {
|
||||
const routerLink = this.breadcrumbsService.breadcrumbs[1]?.routerLink;
|
||||
const routerLink = this.breadcrumbsService.breadcrumbs[1]?.options?.routerLink;
|
||||
if (!routerLink) {
|
||||
return this._search(query, []);
|
||||
}
|
||||
|
||||
@ -9,16 +9,36 @@
|
||||
<mat-icon *ngIf="!first" svgIcon="iqser:arrow-right"></mat-icon>
|
||||
|
||||
<a
|
||||
[class.clamp]="breadcrumb.clamp"
|
||||
*ngIf="is(breadcrumb, 'text')"
|
||||
[class.clamp]="breadcrumb.options.clamp"
|
||||
[id]="first ? 'navigateToActiveDossiers' : ''"
|
||||
[matTooltip]="breadcrumb.clamp && (breadcrumb.name$ | async)"
|
||||
[routerLinkActiveOptions]="breadcrumb.routerLinkActiveOptions || { exact: false }"
|
||||
[routerLink]="breadcrumb.routerLink"
|
||||
[matTooltip]="breadcrumb.options.clamp && (breadcrumb.name$ | async)"
|
||||
[routerLinkActiveOptions]="breadcrumb.options.routerLinkActiveOptions || { exact: false }"
|
||||
[routerLink]="breadcrumb.options.routerLink"
|
||||
class="breadcrumb"
|
||||
routerLinkActive="active"
|
||||
>
|
||||
{{ breadcrumb.name$ | async }}
|
||||
</a>
|
||||
|
||||
<ng-container *ngIf="is(breadcrumb, 'dropdown')">
|
||||
<button [matMenuTriggerFor]="dropdownMenu" class="dropdown-breadcrumb" mat-button>
|
||||
<span>{{ breadcrumb.name$ | async }}</span>
|
||||
<mat-icon svgIcon="iqser:arrow-down"></mat-icon>
|
||||
</button>
|
||||
|
||||
<mat-menu #dropdownMenu="matMenu" class="padding-bottom-8">
|
||||
<a
|
||||
*ngFor="let option of breadcrumb.options.options"
|
||||
[routerLink]="option.options.routerLink"
|
||||
mat-menu-item
|
||||
routerLinkActive="active"
|
||||
>
|
||||
{{ option.name$ | async }}
|
||||
<mat-icon class="checkmark" svgIcon="iqser:check"></mat-icon>
|
||||
</a>
|
||||
</mat-menu>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</ng-template>
|
||||
</div>
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
:host {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
height: 100%;
|
||||
|
||||
> .breadcrumbs > *:not(:last-child) {
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.dropdown-breadcrumb {
|
||||
margin-left: -16px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { BreadcrumbsService } from '@services/breadcrumbs.service';
|
||||
import { Component } from '@angular/core';
|
||||
import { Breadcrumb, BreadcrumbDisplayType, BreadcrumbsService } from '@services/breadcrumbs.service';
|
||||
|
||||
/** Removed on push change detection because [aria-expanded] doesn't seem to work correctly on the dropdown button */
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-breadcrumbs',
|
||||
templateUrl: './breadcrumbs.component.html',
|
||||
styleUrls: ['./breadcrumbs.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class BreadcrumbsComponent {
|
||||
constructor(readonly breadcrumbsService: BreadcrumbsService) {}
|
||||
|
||||
is(breadcrumb: Breadcrumb, type: BreadcrumbDisplayType): boolean {
|
||||
return breadcrumb.type === type;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, OnInit } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DatePipe } from '@shared/pipes/date.pipe';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { NotificationsService } from '@services/notifications.service';
|
||||
import { Notification } from '@red/domain';
|
||||
import { distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators';
|
||||
@ -33,7 +33,7 @@ export class NotificationsComponent extends AutoUnsubscribe implements OnInit {
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _notificationsService: NotificationsService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _datePipe: DatePipe,
|
||||
) {
|
||||
super();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
|
||||
import { DICTIONARY_TYPE, DOSSIER_TEMPLATE_ID } from '@utils/constants';
|
||||
import { DictionariesMapService } from '../services/entity-services/dictionaries-map.service';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class DictionaryExistsGuard implements CanActivate {
|
||||
|
||||
@ -1,15 +1,15 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector, ProviderToken } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DOSSIER_ID } from '@utils/constants';
|
||||
import { DossiersService } from '../services/dossiers/dossiers.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class DossierFilesGuard implements CanActivate {
|
||||
constructor(
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _injector: Injector,
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _filesService: FilesService,
|
||||
private readonly _router: Router,
|
||||
@ -17,14 +17,16 @@ export class DossierFilesGuard implements CanActivate {
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
|
||||
const dossierId = route.paramMap.get(DOSSIER_ID);
|
||||
const token: ProviderToken<DossiersService> = route.data.dossiersService;
|
||||
const dossiersService: DossiersService = this._injector.get<DossiersService>(token);
|
||||
|
||||
if (!this._dossiersService.has(dossierId)) {
|
||||
await this._router.navigate(['/main', 'dossiers']);
|
||||
if (!dossiersService.has(dossierId)) {
|
||||
await this._router.navigate(['/main', dossiersService.routerPath]);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this._filesMapService.has(dossierId)) {
|
||||
await firstValueFrom(this._filesService.loadAll(dossierId));
|
||||
await firstValueFrom(this._filesService.loadAll(dossierId, dossiersService.routerPath));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1,14 +1,29 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CanActivate } from '@angular/router';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { Injectable, Injector, ProviderToken } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate } from '@angular/router';
|
||||
import { firstValueFrom, forkJoin } from 'rxjs';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.service';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class DossiersGuard implements CanActivate {
|
||||
constructor(private readonly _dossiersService: DossiersService) {}
|
||||
constructor(
|
||||
private readonly _injector: Injector,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _archivedDossiersService: ArchivedDossiersService,
|
||||
) {}
|
||||
|
||||
async canActivate(): Promise<boolean> {
|
||||
await firstValueFrom(this._dossiersService.loadAll());
|
||||
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
|
||||
const token: ProviderToken<DossiersService> = route.data.dossiersService;
|
||||
if (token) {
|
||||
const dossiersService: DossiersService = this._injector.get<DossiersService>(token);
|
||||
await firstValueFrom(dossiersService.loadAll());
|
||||
} else {
|
||||
const services = [this._archivedDossiersService, this._activeDossiersService];
|
||||
const loading$ = forkJoin(services.map(service => service.loadAll().pipe(take(1))));
|
||||
await firstValueFrom(loading$);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,22 +1,25 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector, ProviderToken } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { DOSSIER_ID, FILE_ID } from '@utils/constants';
|
||||
import { DossiersService } from '../services/dossiers/dossiers.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class FilePreviewGuard implements CanActivate {
|
||||
constructor(
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _router: Router,
|
||||
private readonly _injector: Injector,
|
||||
) {}
|
||||
|
||||
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
|
||||
const token: ProviderToken<DossiersService> = route.data.dossiersService;
|
||||
const dossiersService: DossiersService = this._injector.get<DossiersService>(token);
|
||||
|
||||
const dossierId = route.paramMap.get(DOSSIER_ID);
|
||||
const fileId = route.paramMap.get(FILE_ID);
|
||||
|
||||
const dossier = this._dossiersService.find(dossierId);
|
||||
const dossier = dossiersService.find(dossierId);
|
||||
|
||||
if (!this._filesMapService.get(dossierId, fileId)) {
|
||||
await this._router.navigate([dossier.routerLink]);
|
||||
|
||||
14
apps/red-ui/src/app/guards/trash-dossiers.guard.ts
Normal file
14
apps/red-ui/src/app/guards/trash-dossiers.guard.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CanActivate } from '@angular/router';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { TrashDossiersService } from '@services/entity-services/trash-dossiers.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class TrashDossiersGuard implements CanActivate {
|
||||
constructor(private readonly _trashDossiersService: TrashDossiersService) {}
|
||||
|
||||
async canActivate(): Promise<boolean> {
|
||||
await firstValueFrom(this._trashDossiersService.loadAll());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,7 @@ import { RouterModule } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { NotificationsScreenComponent } from './notifications-screen/notifications-screen.component';
|
||||
import { PendingChangesGuard } from '../../../../guards/can-deactivate.guard';
|
||||
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||
|
||||
const routes = [{ path: '', component: NotificationsScreenComponent, canDeactivate: [PendingChangesGuard] }];
|
||||
|
||||
|
||||
@ -3,7 +3,7 @@ import { RouterModule } from '@angular/router';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { UserProfileScreenComponent } from './user-profile-screen/user-profile-screen.component';
|
||||
import { PendingChangesGuard } from '../../../../guards/can-deactivate.guard';
|
||||
import { PendingChangesGuard } from '@guards/can-deactivate.guard';
|
||||
|
||||
const routes = [{ path: '', component: UserProfileScreenComponent, canDeactivate: [PendingChangesGuard] }];
|
||||
|
||||
|
||||
@ -17,11 +17,12 @@ import { TrashScreenComponent } from './screens/trash/trash-screen.component';
|
||||
import { GeneralConfigScreenComponent } from './screens/general-config/general-config-screen.component';
|
||||
import { BaseAdminScreenComponent } from './base-admin-screen/base-admin-screen.component';
|
||||
import { BaseDossierTemplateScreenComponent } from './base-dossier-templates-screen/base-dossier-template-screen.component';
|
||||
import { DossierTemplatesGuard } from '../../guards/dossier-templates.guard';
|
||||
import { DossierTemplatesGuard } from '@guards/dossier-templates.guard';
|
||||
import { DICTIONARY_TYPE, DOSSIER_TEMPLATE_ID } from '@utils/constants';
|
||||
import { DossierTemplateExistsGuard } from '../../guards/dossier-template-exists.guard';
|
||||
import { DictionaryExistsGuard } from '../../guards/dictionary-exists.guard';
|
||||
import { DossierTemplateExistsGuard } from '@guards/dossier-template-exists.guard';
|
||||
import { DictionaryExistsGuard } from '@guards/dictionary-exists.guard';
|
||||
import { DossierStatesListingScreenComponent } from './screens/dossier-states-listing/dossier-states-listing-screen.component';
|
||||
import { TrashDossiersGuard } from '@guards/trash-dossiers.guard';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: 'dossier-templates', pathMatch: 'full' },
|
||||
@ -199,7 +200,7 @@ const routes: Routes = [
|
||||
component: TrashScreenComponent,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [AuthGuard, RedRoleGuard],
|
||||
routeGuards: [AuthGuard, RedRoleGuard, TrashDossiersGuard],
|
||||
requiredRoles: ['RED_MANAGER'],
|
||||
},
|
||||
},
|
||||
|
||||
@ -15,7 +15,6 @@ import { ColorPickerModule } from 'ngx-color-picker';
|
||||
import { AddEditFileAttributeDialogComponent } from './dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component';
|
||||
import { AddEditDossierTemplateDialogComponent } from './dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component';
|
||||
import { AddEditDictionaryDialogComponent } from './dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component';
|
||||
import { ConfirmDeleteAttributeDialogComponent } from './dialogs/confirm-delete-attribute-dialog/confirm-delete-attribute-dialog.component';
|
||||
import { EditColorDialogComponent } from './dialogs/edit-color-dialog/edit-color-dialog.component';
|
||||
import { ComboChartComponent, ComboSeriesVerticalComponent } from './components/combo-chart';
|
||||
import { NgxChartsModule } from '@swimlane/ngx-charts';
|
||||
@ -24,7 +23,6 @@ import { GeneralConfigScreenComponent } from './screens/general-config/general-c
|
||||
import { SmtpAuthDialogComponent } from './dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
|
||||
import { AddEditUserDialogComponent } from './dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
|
||||
import { UsersStatsComponent } from './components/users-stats/users-stats.component';
|
||||
import { ConfirmDeleteUsersDialogComponent } from './dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component';
|
||||
import { FileAttributesCsvImportDialogComponent } from './dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
|
||||
import { ActiveFieldsListingComponent } from './dialogs/file-attributes-csv-import-dialog/active-fields-listing/active-fields-listing.component';
|
||||
import { AdminSideNavComponent } from './admin-side-nav/admin-side-nav.component';
|
||||
@ -55,11 +53,9 @@ const dialogs = [
|
||||
AddEditDossierTemplateDialogComponent,
|
||||
AddEditDictionaryDialogComponent,
|
||||
AddEditFileAttributeDialogComponent,
|
||||
ConfirmDeleteAttributeDialogComponent,
|
||||
EditColorDialogComponent,
|
||||
SmtpAuthDialogComponent,
|
||||
AddEditUserDialogComponent,
|
||||
ConfirmDeleteUsersDialogComponent,
|
||||
FileAttributesConfigurationsDialogComponent,
|
||||
FileAttributesCsvImportDialogComponent,
|
||||
AddEditDossierAttributeDialogComponent,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
<div class="menu flex-2 visible-lg breadcrumbs-container">
|
||||
<div class="flex-2 visible-lg breadcrumbs-container">
|
||||
<ng-container *ngIf="dossierTemplate$ | async as dossierTemplate">
|
||||
<a
|
||||
*ngIf="root || dossierTemplate"
|
||||
|
||||
@ -10,9 +10,8 @@ import { BaseDialogComponent } from '@iqser/common-ui';
|
||||
styleUrls: ['./add-edit-user-dialog.component.scss'],
|
||||
})
|
||||
export class AddEditUserDialogComponent extends BaseDialogComponent {
|
||||
@ViewChild(UserDetailsComponent) private readonly _userDetailsComponent: UserDetailsComponent;
|
||||
|
||||
resettingPassword = false;
|
||||
@ViewChild(UserDetailsComponent) private readonly _userDetailsComponent: UserDetailsComponent;
|
||||
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
@ -21,14 +20,6 @@ export class AddEditUserDialogComponent extends BaseDialogComponent {
|
||||
) {
|
||||
super(_injector, _dialogRef, !!user);
|
||||
}
|
||||
X;
|
||||
toggleResetPassword() {
|
||||
this.resettingPassword = !this.resettingPassword;
|
||||
}
|
||||
|
||||
async save(): Promise<void> {
|
||||
await this._userDetailsComponent.save();
|
||||
}
|
||||
|
||||
get changed(): boolean {
|
||||
return this._userDetailsComponent.changed;
|
||||
@ -38,6 +29,14 @@ export class AddEditUserDialogComponent extends BaseDialogComponent {
|
||||
return this._userDetailsComponent.valid;
|
||||
}
|
||||
|
||||
toggleResetPassword() {
|
||||
this.resettingPassword = !this.resettingPassword;
|
||||
}
|
||||
|
||||
async save(): Promise<void> {
|
||||
await this._userDetailsComponent.save();
|
||||
}
|
||||
|
||||
closeDialog(event) {
|
||||
this._dialogRef.close(event);
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@ import { AdminDialogService } from '../../../services/admin-dialog.service';
|
||||
import { BaseFormComponent, IconButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { rolesTranslations } from '../../../../../translations/roles-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { User } from '@red/domain';
|
||||
import { IProfileUpdateRequest, User } from '@red/domain';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { HttpStatusCode } from '@angular/common/http';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
@ -83,7 +83,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
||||
|
||||
async save() {
|
||||
this._loadingService.start();
|
||||
const userData = { ...this.form.getRawValue(), roles: this.activeRoles };
|
||||
const userData: IProfileUpdateRequest = { ...this.form.getRawValue(), roles: this.activeRoles };
|
||||
|
||||
if (!this.user) {
|
||||
await firstValueFrom(this.userService.create(userData))
|
||||
@ -105,9 +105,7 @@ export class UserDetailsComponent extends BaseFormComponent implements OnChanges
|
||||
}
|
||||
|
||||
delete() {
|
||||
this._dialogService.openDialog('deleteUsers', null, [this.user.id], () => {
|
||||
this.closeDialog.emit(true);
|
||||
});
|
||||
this._dialogService.deleteUsers([this.user.id], null, () => this.closeDialog.emit(true));
|
||||
}
|
||||
|
||||
private _getForm(): FormGroup {
|
||||
|
||||
@ -1,39 +0,0 @@
|
||||
<section class="dialog">
|
||||
<div class="dialog-header heading-l">
|
||||
{{ 'confirm-delete-file-attribute.title' | translate: translateArgs }}
|
||||
</div>
|
||||
|
||||
<div *ngIf="showToast" class="inline-dialog-toast toast-error">
|
||||
<div translate="confirm-delete-file-attribute.toast-error"></div>
|
||||
<a (click)="showToast = false" class="toast-close-button">
|
||||
<mat-icon svgIcon="iqser:close"></mat-icon>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="dialog-content">
|
||||
<div class="heading" translate="confirm-delete-file-attribute.warning"></div>
|
||||
|
||||
<ng-container *ngFor="let checkbox of checkboxes; let idx = index">
|
||||
<mat-checkbox [(ngModel)]="checkbox.value" [class.error]="!checkbox.value && showToast" color="primary">
|
||||
{{ checkbox.label }}
|
||||
</mat-checkbox>
|
||||
</ng-container>
|
||||
|
||||
<ul class="templates-container flex">
|
||||
<li *ngFor="let template of data.templates" class="small-label">{{ template.fileName }}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button (click)="deleteFileAttribute()" color="primary" mat-flat-button>
|
||||
{{ 'confirm-delete-file-attribute.delete' | translate: { type: type } }}
|
||||
</button>
|
||||
<div
|
||||
(click)="this.dialogRef.close()"
|
||||
[translateParams]="{ type: type }"
|
||||
[translate]="'confirm-delete-file-attribute.cancel'"
|
||||
class="all-caps-label cancel"
|
||||
></div>
|
||||
</div>
|
||||
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
|
||||
</section>
|
||||
@ -1,27 +0,0 @@
|
||||
@use 'variables';
|
||||
|
||||
.dialog-header {
|
||||
color: variables.$primary;
|
||||
}
|
||||
|
||||
.heading {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
mat-checkbox {
|
||||
width: 100%;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.templates-container {
|
||||
padding: 0 45px;
|
||||
margin-top: 0;
|
||||
flex-direction: column;
|
||||
|
||||
li {
|
||||
margin: 5px 0;
|
||||
}
|
||||
}
|
||||
@ -1,89 +0,0 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { DossierAttributeConfig, FileAttributeConfig, IReportTemplate } from '@red/domain';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
const isFileAttributeConfig = (value: DossierAttributeConfig | FileAttributeConfig): value is FileAttributeConfig =>
|
||||
value instanceof FileAttributeConfig;
|
||||
|
||||
interface CheckBox {
|
||||
value: boolean;
|
||||
label: string;
|
||||
}
|
||||
|
||||
interface DialogData {
|
||||
attribute: FileAttributeConfig | DossierAttributeConfig;
|
||||
templates: IReportTemplate[];
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-confirm-delete-attribute-dialog',
|
||||
templateUrl: './confirm-delete-attribute-dialog.component.html',
|
||||
styleUrls: ['./confirm-delete-attribute-dialog.component.scss'],
|
||||
})
|
||||
export class ConfirmDeleteAttributeDialogComponent {
|
||||
checkboxes: CheckBox[];
|
||||
showToast = false;
|
||||
|
||||
constructor(
|
||||
private readonly _translateService: TranslateService,
|
||||
readonly dialogRef: MatDialogRef<ConfirmDeleteAttributeDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: DialogData,
|
||||
) {
|
||||
this.checkboxes = this.checkBoxConfig;
|
||||
}
|
||||
|
||||
get checkBoxConfig(): CheckBox[] {
|
||||
const checkBoxes = isFileAttributeConfig(this.data.attribute) ? this._fileAttributeCheckboxes : this._dossierAttributeCheckboxes;
|
||||
if (this.data.templates.length !== 0) {
|
||||
checkBoxes.push({
|
||||
value: false,
|
||||
label: this._translateService.instant('confirm-delete-file-attribute.impacted-report', {
|
||||
count: this.data.templates.length,
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
return checkBoxes;
|
||||
}
|
||||
|
||||
get valid() {
|
||||
return this.checkboxes.reduce((acc, currentValue) => acc && currentValue.value, true);
|
||||
}
|
||||
|
||||
get type(): 'bulk' | 'single' {
|
||||
return this.data.attribute ? 'single' : 'bulk';
|
||||
}
|
||||
|
||||
get translateArgs() {
|
||||
return {
|
||||
type: this.type,
|
||||
name: this.data.attribute?.label,
|
||||
};
|
||||
}
|
||||
|
||||
private get _fileAttributeCheckboxes(): CheckBox[] {
|
||||
return [
|
||||
{
|
||||
value: false,
|
||||
label: this._translateService.instant('confirm-delete-file-attribute.file-impacted-documents', { type: this.type }),
|
||||
},
|
||||
{ value: false, label: this._translateService.instant('confirm-delete-file-attribute.file-lost-details') },
|
||||
];
|
||||
}
|
||||
|
||||
private get _dossierAttributeCheckboxes(): CheckBox[] {
|
||||
return [
|
||||
{ value: false, label: this._translateService.instant('confirm-delete-file-attribute.dossier-impacted-documents') },
|
||||
{ value: false, label: this._translateService.instant('confirm-delete-file-attribute.dossier-lost-details') },
|
||||
];
|
||||
}
|
||||
|
||||
deleteFileAttribute() {
|
||||
if (this.valid) {
|
||||
this.dialogRef.close(true);
|
||||
} else {
|
||||
this.showToast = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
<section class="dialog">
|
||||
<div
|
||||
[translateParams]="{ usersCount: userIds.length }"
|
||||
[translate]="'confirm-delete-users.title'"
|
||||
class="dialog-header heading-l"
|
||||
></div>
|
||||
|
||||
<div *ngIf="showToast" class="inline-dialog-toast toast-error">
|
||||
<div translate="confirm-delete-users.toast-error"></div>
|
||||
<a (click)="showToast = false" class="toast-close-button">
|
||||
<mat-icon svgIcon="iqser:close"></mat-icon>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="dialog-content">
|
||||
<div class="heading" translate="confirm-delete-users.warning"></div>
|
||||
|
||||
<mat-checkbox
|
||||
*ngFor="let checkbox of checkboxes; let idx = index"
|
||||
[(ngModel)]="checkbox.value"
|
||||
[class.error]="!checkbox.value && showToast"
|
||||
color="primary"
|
||||
>
|
||||
{{
|
||||
checkbox.label
|
||||
| translate
|
||||
: {
|
||||
dossiersCount: dossiersCount,
|
||||
usersCount: userIds.length
|
||||
}
|
||||
}}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button (click)="deleteUser()" color="primary" mat-flat-button>
|
||||
{{ 'confirm-delete-users.delete' | translate: { usersCount: userIds.length } }}
|
||||
</button>
|
||||
<div
|
||||
(click)="cancel()"
|
||||
[translateParams]="{ usersCount: userIds.length }"
|
||||
[translate]="'confirm-delete-users.cancel'"
|
||||
class="all-caps-label cancel"
|
||||
></div>
|
||||
</div>
|
||||
<iqser-circle-button class="dialog-close" icon="iqser:close" mat-dialog-close></iqser-circle-button>
|
||||
</section>
|
||||
@ -1,17 +0,0 @@
|
||||
@use 'variables';
|
||||
|
||||
.dialog-header {
|
||||
color: variables.$primary;
|
||||
}
|
||||
|
||||
.heading {
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
mat-checkbox {
|
||||
width: 100%;
|
||||
|
||||
&:not(:last-of-type) {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { List, LoadingService } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-confirm-delete-users-dialog',
|
||||
templateUrl: './confirm-delete-users-dialog.component.html',
|
||||
styleUrls: ['./confirm-delete-users-dialog.component.scss'],
|
||||
})
|
||||
export class ConfirmDeleteUsersDialogComponent {
|
||||
readonly checkboxes = [
|
||||
{ value: false, label: _('confirm-delete-users.impacted-dossiers') },
|
||||
{ value: false, label: _('confirm-delete-users.impacted-documents') },
|
||||
];
|
||||
showToast = false;
|
||||
dossiersCount: number;
|
||||
|
||||
constructor(
|
||||
private readonly _userService: UserService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
@Inject(MAT_DIALOG_DATA) readonly userIds: List<string>,
|
||||
readonly dialogRef: MatDialogRef<ConfirmDeleteUsersDialogComponent>,
|
||||
) {
|
||||
this.dossiersCount = this._dossierCount;
|
||||
}
|
||||
|
||||
get valid() {
|
||||
return this.checkboxes[0].value && this.checkboxes[1].value;
|
||||
}
|
||||
|
||||
private get _dossierCount(): number {
|
||||
return this._dossiersService.all.filter(dw => this.userIds.reduce((prev, userId) => prev || dw.memberIds.includes(userId), false))
|
||||
.length;
|
||||
}
|
||||
|
||||
async deleteUser() {
|
||||
if (this.valid) {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._userService.delete(this.userIds));
|
||||
this.dialogRef.close(true);
|
||||
} else {
|
||||
this.showToast = true;
|
||||
}
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.dialogRef.close();
|
||||
}
|
||||
}
|
||||
@ -65,6 +65,12 @@
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #impactedTemplates let-data="data">
|
||||
<ul class="templates-container flex">
|
||||
<li *ngFor="let template of data.templates" class="small-label">{{ template.fileName }}</li>
|
||||
</ul>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #tableItemTemplate let-entity="entity">
|
||||
<div *ngIf="cast(entity) as attribute">
|
||||
<div class="cell">
|
||||
@ -89,7 +95,7 @@
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="openConfirmDeleteAttributeDialog($event, attribute)"
|
||||
(action)="openConfirmDeleteAttributeDialog($event, [attribute])"
|
||||
[tooltip]="'dossier-attributes-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
|
||||
@ -0,0 +1,9 @@
|
||||
.templates-container {
|
||||
padding: 0 45px;
|
||||
margin-top: 0;
|
||||
flex-direction: column;
|
||||
|
||||
li {
|
||||
margin: 5px 0;
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, forwardRef, Injector, OnInit } from '@angular/core';
|
||||
import { Component, forwardRef, Injector, OnInit, TemplateRef, ViewChild } from '@angular/core';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
DefaultListingServicesTmp,
|
||||
@ -39,6 +39,7 @@ export class DossierAttributesListingScreenComponent extends ListingComponent<Do
|
||||
{ label: _('dossier-attributes-listing.table-col-names.placeholder'), width: '2fr' },
|
||||
{ label: _('dossier-attributes-listing.table-col-names.type'), sortByKey: 'type' },
|
||||
];
|
||||
@ViewChild('impactedTemplates') impactedTemplatesRef: TemplateRef<unknown>;
|
||||
readonly #dossierTemplateId: string;
|
||||
|
||||
constructor(
|
||||
@ -58,16 +59,11 @@ export class DossierAttributesListingScreenComponent extends ListingComponent<Do
|
||||
await this._loadData();
|
||||
}
|
||||
|
||||
async openConfirmDeleteAttributeDialog($event: MouseEvent, dossierAttribute?: DossierAttributeConfig) {
|
||||
const dossierTemplateId = this.#dossierTemplateId;
|
||||
const resp = await firstValueFrom(
|
||||
this._reportTemplateService.getTemplatesByPlaceholder(dossierTemplateId, dossierAttribute.placeholder),
|
||||
);
|
||||
|
||||
this._dialogService.openDialog('deleteAttribute', $event, { attribute: dossierAttribute, templates: resp }, async () => {
|
||||
async openConfirmDeleteAttributeDialog($event: MouseEvent, attributes: DossierAttributeConfig[] = this.listingService.selected) {
|
||||
await this._dialogService.deleteAttributes(attributes, this.#dossierTemplateId, this.impactedTemplatesRef, $event, async () => {
|
||||
this._loadingService.start();
|
||||
const ids = dossierAttribute ? [dossierAttribute.id] : this.listingService.selected.map(item => item.id);
|
||||
await firstValueFrom(this._dossierAttributesService.delete(ids, dossierTemplateId));
|
||||
const ids = attributes.map(a => a.id);
|
||||
await firstValueFrom(this._dossierAttributesService.delete(ids, this.#dossierTemplateId));
|
||||
await this._loadData();
|
||||
});
|
||||
}
|
||||
|
||||
@ -11,15 +11,15 @@ import {
|
||||
} from '@iqser/common-ui';
|
||||
import { DossierState, IDossierState } from '@red/domain';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossiersService } from '../../../../services/entity-services/dossiers.service';
|
||||
import { DossierStateService } from '../../../../services/entity-services/dossier-state.service';
|
||||
import { ActiveDossiersService } from '../../../../services/dossiers/active-dossiers.service';
|
||||
import { DossierStateService } from '@services/entity-services/dossier-state.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { UserService } from '../../../../services/user.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { HttpStatusCode } from '@angular/common/http';
|
||||
import { DoughnutChartConfig } from '../../../shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { DossierTemplatesService } from '../../../../services/entity-services/dossier-templates.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-states-listing-screen.component.html',
|
||||
@ -33,7 +33,6 @@ import { DossierTemplatesService } from '../../../../services/entity-services/do
|
||||
export class DossierStatesListingScreenComponent extends ListingComponent<DossierState> implements OnInit, OnDestroy {
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly #dossierTemplateId: string;
|
||||
readonly currentUser = this._userService.currentUser;
|
||||
readonly tableHeaderLabel = _('dossier-states-listing.table-header.title');
|
||||
readonly tableColumnConfigs: TableColumnConfig<DossierState>[] = [
|
||||
@ -42,11 +41,12 @@ export class DossierStatesListingScreenComponent extends ListingComponent<Dossie
|
||||
{ label: _('dossier-states-listing.table-col-names.dossiers-count') },
|
||||
];
|
||||
chartData: DoughnutChartConfig[];
|
||||
readonly #dossierTemplateId: string;
|
||||
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
readonly dossierStateService: DossierStateService,
|
||||
private readonly _dialogService: AdminDialogService,
|
||||
private readonly _userService: UserService,
|
||||
@ -99,7 +99,7 @@ export class DossierStatesListingScreenComponent extends ListingComponent<Dossie
|
||||
|
||||
async #createNewDossierStateAndRefreshView(newValue: IDossierState): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this.dossierStateService.setDossierState(newValue)).catch(error => {
|
||||
await firstValueFrom(this.dossierStateService.updateDossierState(newValue)).catch(error => {
|
||||
if (error.status === HttpStatusCode.Conflict) {
|
||||
this._toaster.error(_('dossier-states-listing.error.conflict'));
|
||||
} else {
|
||||
@ -112,7 +112,8 @@ export class DossierStatesListingScreenComponent extends ListingComponent<Dossie
|
||||
|
||||
async #loadData(): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._dossiersService.loadAll());
|
||||
// TODO: Move this in service; dossiers states service should be a mapping service
|
||||
await firstValueFrom(this._activeDossiersService.loadAll());
|
||||
|
||||
try {
|
||||
const dossierStates = this.dossierStateService.all.filter(d => d.dossierTemplateId === this.#dossierTemplateId);
|
||||
@ -130,6 +131,6 @@ export class DossierStatesListingScreenComponent extends ListingComponent<Dossie
|
||||
}
|
||||
|
||||
#setStatesCount(dossierStates: DossierState[]): void {
|
||||
dossierStates.forEach(state => (state.dossierCount = this._dossiersService.getCountWithState(state.dossierStatusId)));
|
||||
dossierStates.forEach(state => (state.dossierCount = this._activeDossiersService.getCountWithState(state.dossierStatusId)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,6 +37,12 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ng-template #impactedTemplates let-data="data">
|
||||
<ul class="templates-container flex">
|
||||
<li *ngFor="let template of data.templates" class="small-label">{{ template.fileName }}</li>
|
||||
</ul>
|
||||
</ng-template>
|
||||
|
||||
<ng-template #bulkActions>
|
||||
<iqser-circle-button
|
||||
(click)="openConfirmDeleteAttributeDialog($event)"
|
||||
@ -126,7 +132,7 @@
|
||||
icon="iqser:edit"
|
||||
></iqser-circle-button>
|
||||
<iqser-circle-button
|
||||
(action)="openConfirmDeleteAttributeDialog($event, attribute)"
|
||||
(action)="openConfirmDeleteAttributeDialog($event, [attribute])"
|
||||
[tooltip]="'file-attributes-listing.action.delete' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
|
||||
@ -1,4 +1,14 @@
|
||||
import { ChangeDetectionStrategy, Component, ElementRef, forwardRef, Injector, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import {
|
||||
ChangeDetectionStrategy,
|
||||
Component,
|
||||
ElementRef,
|
||||
forwardRef,
|
||||
Injector,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
TemplateRef,
|
||||
ViewChild,
|
||||
} from '@angular/core';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
@ -50,6 +60,7 @@ export class FileAttributesListingScreenComponent extends ListingComponent<FileA
|
||||
rightIconTooltip: _('file-attributes-listing.table-col-names.primary-info-tooltip'),
|
||||
},
|
||||
];
|
||||
@ViewChild('impactedTemplates') impactedTemplatesRef: TemplateRef<unknown>;
|
||||
private _existingConfiguration: IFileAttributesConfig;
|
||||
@ViewChild('fileInput') private _fileInput: ElementRef;
|
||||
readonly #dossierTemplateId: string;
|
||||
@ -93,25 +104,15 @@ export class FileAttributesListingScreenComponent extends ListingComponent<FileA
|
||||
});
|
||||
}
|
||||
|
||||
async openConfirmDeleteAttributeDialog($event: MouseEvent, fileAttribute?: FileAttributeConfig) {
|
||||
const dossierTemplateId = this.#dossierTemplateId;
|
||||
const resp = await firstValueFrom(
|
||||
this._reportTemplateService.getTemplatesByPlaceholder(dossierTemplateId, fileAttribute.placeholder),
|
||||
);
|
||||
|
||||
this._dialogService.openDialog('deleteAttribute', $event, { attribute: fileAttribute, templates: resp }, async () => {
|
||||
async openConfirmDeleteAttributeDialog(
|
||||
$event: MouseEvent,
|
||||
attributes: FileAttributeConfig[] = this.listingService.selected,
|
||||
): Promise<void> {
|
||||
await this._dialogService.deleteAttributes(attributes, this.#dossierTemplateId, this.impactedTemplatesRef, $event, async () => {
|
||||
this._loadingService.start();
|
||||
if (fileAttribute) {
|
||||
await firstValueFrom(this._fileAttributesService.deleteFileAttributes([fileAttribute.id], dossierTemplateId));
|
||||
} else {
|
||||
await firstValueFrom(
|
||||
this._fileAttributesService.deleteFileAttributes(
|
||||
this.listingService.selected.map(f => f.id),
|
||||
dossierTemplateId,
|
||||
),
|
||||
);
|
||||
}
|
||||
await this._dossierTemplatesService.refreshDossierTemplate(dossierTemplateId);
|
||||
const ids = attributes.map(a => a.id);
|
||||
await firstValueFrom(this._fileAttributesService.deleteFileAttributes(ids, this.#dossierTemplateId));
|
||||
await firstValueFrom(this._dossierTemplatesService.refreshDossierTemplate(this.#dossierTemplateId));
|
||||
await this._loadData();
|
||||
});
|
||||
}
|
||||
@ -148,7 +149,7 @@ export class FileAttributesListingScreenComponent extends ListingComponent<FileA
|
||||
}
|
||||
this._loadingService.stop();
|
||||
});
|
||||
await this._dossierTemplatesService.refreshDossierTemplate(this.#dossierTemplateId);
|
||||
await firstValueFrom(this._dossierTemplatesService.refreshDossierTemplate(this.#dossierTemplateId));
|
||||
await this._loadData();
|
||||
}
|
||||
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
import { ChangeDetectionStrategy, Component, forwardRef, Injector, OnInit } from '@angular/core';
|
||||
import { ChangeDetectionStrategy, Component, forwardRef, Injector } from '@angular/core';
|
||||
import {
|
||||
CircleButtonTypes,
|
||||
ConfirmationDialogInput,
|
||||
DefaultListingServices,
|
||||
DefaultListingServicesTmp,
|
||||
EntitiesService,
|
||||
getLeftDateTime,
|
||||
IListable,
|
||||
ListingComponent,
|
||||
@ -11,35 +12,33 @@ import {
|
||||
TableColumnConfig,
|
||||
TitleColors,
|
||||
} from '@iqser/common-ui';
|
||||
import { ConfigService } from '@services/config.service';
|
||||
import * as moment from 'moment';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { AdminDialogService } from '../../services/admin-dialog.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { Observable } from 'rxjs';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { RouterHistoryService } from '@services/router-history.service';
|
||||
import { IDossier } from '@red/domain';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
|
||||
interface DossierListItem extends IDossier, IListable {
|
||||
readonly canRestore: boolean;
|
||||
readonly canHardDelete: boolean;
|
||||
readonly restoreDate: string;
|
||||
}
|
||||
import { TrashDossier } from '@red/domain';
|
||||
import { TrashDossiersService } from '@services/entity-services/trash-dossiers.service';
|
||||
|
||||
@Component({
|
||||
templateUrl: './trash-screen.component.html',
|
||||
styleUrls: ['./trash-screen.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => TrashScreenComponent) }],
|
||||
providers: [
|
||||
...DefaultListingServicesTmp,
|
||||
{
|
||||
provide: EntitiesService,
|
||||
useExisting: TrashDossiersService,
|
||||
},
|
||||
{ provide: ListingComponent, useExisting: forwardRef(() => TrashScreenComponent) },
|
||||
],
|
||||
})
|
||||
export class TrashScreenComponent extends ListingComponent<DossierListItem> implements OnInit {
|
||||
export class TrashScreenComponent extends ListingComponent<TrashDossier> {
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
readonly tableHeaderLabel = _('trash.table-header.title');
|
||||
readonly canRestoreSelected$ = this._canRestoreSelected$;
|
||||
readonly canHardDeleteSelected$ = this._canHardDeleteSelected$;
|
||||
readonly tableColumnConfigs: TableColumnConfig<DossierListItem>[] = [
|
||||
readonly tableColumnConfigs: TableColumnConfig<TrashDossier>[] = [
|
||||
{ label: _('trash.table-col-names.name'), sortByKey: 'searchKey' },
|
||||
{ label: _('trash.table-col-names.owner'), class: 'user-column' },
|
||||
{ label: _('trash.table-col-names.deleted-on'), sortByKey: 'softDeletedTime' },
|
||||
@ -49,13 +48,16 @@ export class TrashScreenComponent extends ListingComponent<DossierListItem> impl
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _trashDossiersService: TrashDossiersService,
|
||||
readonly routerHistoryService: RouterHistoryService,
|
||||
private readonly _configService: ConfigService,
|
||||
private readonly _adminDialogService: AdminDialogService,
|
||||
) {
|
||||
super(_injector);
|
||||
|
||||
this.sortingService.setSortingOption({
|
||||
column: 'softDeletedTime',
|
||||
order: SortingOrders.desc,
|
||||
});
|
||||
}
|
||||
|
||||
private get _canRestoreSelected$(): Observable<boolean> {
|
||||
@ -72,17 +74,7 @@ export class TrashScreenComponent extends ListingComponent<DossierListItem> impl
|
||||
);
|
||||
}
|
||||
|
||||
disabledFn = (dossier: DossierListItem) => !dossier.canRestore;
|
||||
|
||||
async ngOnInit(): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await this._loadDossiersData();
|
||||
this.sortingService.setSortingOption({
|
||||
column: 'softDeletedTime',
|
||||
order: SortingOrders.desc,
|
||||
});
|
||||
this._loadingService.stop();
|
||||
}
|
||||
disabledFn = (dossier: TrashDossier) => !dossier.canRestore;
|
||||
|
||||
hardDelete(dossiers = this.listingService.selected): void {
|
||||
const data = new ConfirmationDialogInput({
|
||||
@ -95,60 +87,13 @@ export class TrashScreenComponent extends ListingComponent<DossierListItem> impl
|
||||
},
|
||||
});
|
||||
this._adminDialogService.openDialog('confirm', null, data, () => {
|
||||
this._loadingService.loadWhile(this._hardDelete(dossiers));
|
||||
const dossierIds: string[] = dossiers.map(d => d.id);
|
||||
this._loadingService.loadWhile(this._trashDossiersService.hardDelete(dossierIds));
|
||||
});
|
||||
}
|
||||
|
||||
restore(dossiers = this.listingService.selected): void {
|
||||
this._loadingService.loadWhile(this._restore(dossiers));
|
||||
}
|
||||
|
||||
private _getRestoreDate(softDeletedTime: string): string {
|
||||
return moment(softDeletedTime).add(this._configService.values.DELETE_RETENTION_HOURS, 'hours').toISOString();
|
||||
}
|
||||
|
||||
private async _loadDossiersData(): Promise<void> {
|
||||
this.entitiesService.setEntities(this._toListItems(await this._dossiersService.getDeleted()).filter(d => d.canRestore));
|
||||
}
|
||||
|
||||
private _canRestoreDossier(restoreDate: string): boolean {
|
||||
const { daysLeft, hoursLeft, minutesLeft } = getLeftDateTime(restoreDate);
|
||||
|
||||
return daysLeft >= 0 && hoursLeft >= 0 && minutesLeft > 0;
|
||||
}
|
||||
|
||||
private _toListItems(dossiers: IDossier[]): DossierListItem[] {
|
||||
return dossiers.map(dossier => this._toListItem(dossier));
|
||||
}
|
||||
|
||||
private _toListItem(dossier: IDossier): DossierListItem {
|
||||
const restoreDate = this._getRestoreDate(dossier.softDeletedTime);
|
||||
return {
|
||||
id: dossier.dossierId,
|
||||
...dossier,
|
||||
searchKey: dossier.dossierName,
|
||||
restoreDate,
|
||||
canRestore: this._canRestoreDossier(restoreDate),
|
||||
canHardDelete: this._permissionsService.canDeleteDossier(dossier),
|
||||
// Because of migrations, for some this is not set
|
||||
softDeletedTime: dossier.softDeletedTime || '-',
|
||||
};
|
||||
}
|
||||
|
||||
private async _restore(dossiers: DossierListItem[]): Promise<void> {
|
||||
const dossierIds = dossiers.map(d => d.id);
|
||||
await this._dossiersService.restore(dossierIds);
|
||||
this._removeFromList(dossierIds);
|
||||
}
|
||||
|
||||
private async _hardDelete(dossiers: DossierListItem[]) {
|
||||
const dossierIds = dossiers.map(d => d.id);
|
||||
await this._dossiersService.hardDelete(dossierIds);
|
||||
this._removeFromList(dossierIds);
|
||||
}
|
||||
|
||||
private _removeFromList(ids: string[]): void {
|
||||
const entities = this.entitiesService.all.filter(e => !ids.includes(e.id));
|
||||
this.entitiesService.setEntities(entities);
|
||||
const dossierIds: string[] = dossiers.map(d => d.id);
|
||||
this._loadingService.loadWhile(this._trashDossiersService.restore(dossierIds));
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,7 +80,7 @@ export class UserListingScreenComponent extends ListingComponent<User> implement
|
||||
}
|
||||
|
||||
openDeleteUsersDialog(userIds: string[], $event?: MouseEvent) {
|
||||
this._dialogService.openDialog('deleteUsers', $event, userIds, async () => {
|
||||
this._dialogService.deleteUsers(userIds, $event, async () => {
|
||||
await this._loadData();
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,31 +1,42 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, TemplateRef } from '@angular/core';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { AddEditFileAttributeDialogComponent } from '../dialogs/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component';
|
||||
import { AddEditDictionaryDialogComponent } from '../dialogs/add-edit-dictionary-dialog/add-edit-dictionary-dialog.component';
|
||||
import { AddEditDossierTemplateDialogComponent } from '../dialogs/add-edit-dossier-template-dialog/add-edit-dossier-template-dialog.component';
|
||||
import { ConfirmDeleteAttributeDialogComponent } from '../dialogs/confirm-delete-attribute-dialog/confirm-delete-attribute-dialog.component';
|
||||
import { EditColorDialogComponent } from '../dialogs/edit-color-dialog/edit-color-dialog.component';
|
||||
import { SmtpAuthDialogComponent } from '../dialogs/smtp-auth-dialog/smtp-auth-dialog.component';
|
||||
import { AddEditUserDialogComponent } from '../dialogs/add-edit-user-dialog/add-edit-user-dialog.component';
|
||||
import { ConfirmDeleteUsersDialogComponent } from '../dialogs/confirm-delete-users-dialog/confirm-delete-users-dialog.component';
|
||||
import { FileAttributesCsvImportDialogComponent } from '../dialogs/file-attributes-csv-import-dialog/file-attributes-csv-import-dialog.component';
|
||||
import { AddEditDossierAttributeDialogComponent } from '../dialogs/add-edit-dossier-attribute-dialog/add-edit-dossier-attribute-dialog.component';
|
||||
import { ConfirmationDialogComponent, DialogConfig, DialogService, largeDialogConfig } from '@iqser/common-ui';
|
||||
import {
|
||||
ConfirmationDialogComponent,
|
||||
ConfirmationDialogInput,
|
||||
ConfirmOptions,
|
||||
DialogConfig,
|
||||
DialogService,
|
||||
largeDialogConfig,
|
||||
LoadingService,
|
||||
TitleColors,
|
||||
} from '@iqser/common-ui';
|
||||
import { UploadDictionaryDialogComponent } from '../dialogs/upload-dictionary-dialog/upload-dictionary-dialog.component';
|
||||
import { FileAttributesConfigurationsDialogComponent } from '../dialogs/file-attributes-configurations-dialog/file-attributes-configurations-dialog.component';
|
||||
import { AddEditDossierStateDialogComponent } from '../dialogs/add-edit-dossier-state-dialog/add-edit-dossier-state-dialog.component';
|
||||
import { ConfirmDeleteDossierStateDialogComponent } from '../dialogs/confirm-delete-dossier-state-dialog/confirm-delete-dossier-state-dialog.component';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { firstValueFrom, forkJoin } from 'rxjs';
|
||||
import { ActiveDossiersService } from '../../../services/dossiers/active-dossiers.service';
|
||||
import { UserService } from '../../../services/user.service';
|
||||
import { IDossierAttributeConfig, IFileAttributeConfig, IReportTemplate } from '@red/domain';
|
||||
import { ReportTemplateService } from '../../../services/report-template.service';
|
||||
|
||||
type DialogType =
|
||||
| 'confirm'
|
||||
| 'addEditDictionary'
|
||||
| 'editColor'
|
||||
| 'addEditFileAttribute'
|
||||
| 'deleteAttribute'
|
||||
| 'importFileAttributes'
|
||||
| 'fileAttributesConfigurations'
|
||||
| 'addEditUser'
|
||||
| 'deleteUsers'
|
||||
| 'smtpAuthConfig'
|
||||
| 'addEditDossierTemplate'
|
||||
| 'addEditDossierAttribute'
|
||||
@ -52,10 +63,6 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
component: AddEditFileAttributeDialogComponent,
|
||||
dialogConfig: { autoFocus: true },
|
||||
},
|
||||
deleteAttribute: {
|
||||
component: ConfirmDeleteAttributeDialogComponent,
|
||||
dialogConfig: { disableClose: false },
|
||||
},
|
||||
fileAttributesConfigurations: {
|
||||
component: FileAttributesConfigurationsDialogComponent,
|
||||
},
|
||||
@ -63,10 +70,6 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
component: FileAttributesCsvImportDialogComponent,
|
||||
dialogConfig: { ...largeDialogConfig, ...{ disableClose: false } },
|
||||
},
|
||||
deleteUsers: {
|
||||
component: ConfirmDeleteUsersDialogComponent,
|
||||
dialogConfig: { autoFocus: true, disableClose: false },
|
||||
},
|
||||
addEditUser: {
|
||||
component: AddEditUserDialogComponent,
|
||||
dialogConfig: { autoFocus: true },
|
||||
@ -94,7 +97,88 @@ export class AdminDialogService extends DialogService<DialogType> {
|
||||
},
|
||||
};
|
||||
|
||||
constructor(protected readonly _dialog: MatDialog) {
|
||||
constructor(
|
||||
protected readonly _dialog: MatDialog,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _reportTemplateService: ReportTemplateService,
|
||||
) {
|
||||
super(_dialog);
|
||||
}
|
||||
|
||||
deleteUsers(userIds: string[], $event?: MouseEvent, cb?: () => Promise<void> | void): void {
|
||||
const data = new ConfirmationDialogInput({
|
||||
title: _('confirm-delete-users.title'),
|
||||
question: _('confirm-delete-users.warning'),
|
||||
confirmationText: _('confirm-delete-users.delete'),
|
||||
denyText: _('confirm-delete-users.cancel'),
|
||||
titleColor: TitleColors.WARN,
|
||||
translateParams: { usersCount: 1, dossiersCount: this._getUsersDossiersCount(userIds) },
|
||||
checkboxes: [
|
||||
{ value: false, label: _('confirm-delete-users.impacted-dossiers') },
|
||||
{ value: false, label: _('confirm-delete-users.impacted-documents') },
|
||||
],
|
||||
toastMessage: _('confirm-delete-users.toast-error'),
|
||||
});
|
||||
|
||||
this.openDialog('confirm', $event, data, async result => {
|
||||
if (result === ConfirmOptions.CONFIRM) {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._userService.delete(userIds));
|
||||
await cb();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async deleteAttributes(
|
||||
attributes: IFileAttributeConfig[] | IDossierAttributeConfig[],
|
||||
dossierTemplateId: string,
|
||||
impactedTemplatesRef: TemplateRef<unknown>,
|
||||
$event?: MouseEvent,
|
||||
cb?: () => Promise<void> | void,
|
||||
): Promise<void> {
|
||||
this._loadingService.start();
|
||||
const templates$ = attributes
|
||||
.map(a => a.placeholder)
|
||||
.map(placeholder => this._reportTemplateService.getTemplatesByPlaceholder(dossierTemplateId, placeholder as string));
|
||||
const templates: IReportTemplate[] = (await firstValueFrom(forkJoin(templates$))).flat();
|
||||
const templateIds = new Set<string>(templates.map(t => t.templateId));
|
||||
const uniqueTemplates = Array.from(templateIds).map(id => templates.find(t => t.templateId === id));
|
||||
this._loadingService.stop();
|
||||
|
||||
const data = new ConfirmationDialogInput({
|
||||
title: _('confirm-delete-file-attribute.title'),
|
||||
question: _('confirm-delete-file-attribute.warning'),
|
||||
confirmationText: _('confirm-delete-file-attribute.delete'),
|
||||
denyText: _('confirm-delete-file-attribute.cancel'),
|
||||
titleColor: TitleColors.WARN,
|
||||
checkboxes: [
|
||||
{
|
||||
value: false,
|
||||
label: 'confirm-delete-file-attribute.file-impacted-documents',
|
||||
},
|
||||
{ value: false, label: 'confirm-delete-file-attribute.file-lost-details' },
|
||||
],
|
||||
toastMessage: _('confirm-delete-file-attribute.toast-error'),
|
||||
translateParams: { reportsCount: uniqueTemplates.length, count: attributes.length, name: attributes[0].label },
|
||||
});
|
||||
if (templates.length) {
|
||||
data.checkboxes.push({
|
||||
value: false,
|
||||
label: _('confirm-delete-file-attribute.impacted-report'),
|
||||
extraContent: impactedTemplatesRef,
|
||||
extraContentData: { templates: uniqueTemplates },
|
||||
});
|
||||
}
|
||||
this.openDialog('confirm', $event, data, async () => {
|
||||
await cb();
|
||||
});
|
||||
}
|
||||
|
||||
private _getUsersDossiersCount(userIds: string[]): number {
|
||||
return this._activeDossiersService.all.filter(dw => userIds.reduce((prev, userId) => prev || dw.memberIds.includes(userId), false))
|
||||
.length;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,44 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { BreadcrumbTypes } from '@red/domain';
|
||||
import { ArchivedDossiersScreenComponent } from './screens/archived-dossiers-screen/archived-dossiers-screen.component';
|
||||
import { DOSSIER_ID, FILE_ID } from '@utils/constants';
|
||||
import { CompositeRouteGuard } from '@iqser/common-ui';
|
||||
import { ARCHIVED_DOSSIERS_SERVICE } from '../../tokens';
|
||||
import { DossierFilesGuard } from '@guards/dossier-files-guard';
|
||||
import { FilePreviewGuard } from '../../guards/file-preview.guard';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
pathMatch: 'full',
|
||||
component: ArchivedDossiersScreenComponent,
|
||||
data: { breadcrumbs: [BreadcrumbTypes.archive] },
|
||||
},
|
||||
{
|
||||
path: `:${DOSSIER_ID}`,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [DossierFilesGuard],
|
||||
breadcrumbs: [BreadcrumbTypes.archive, BreadcrumbTypes.dossier],
|
||||
dossiersService: ARCHIVED_DOSSIERS_SERVICE,
|
||||
},
|
||||
loadChildren: () => import('../dossier/screens/dossier-overview/dossier-overview.module').then(m => m.DossierOverviewModule),
|
||||
},
|
||||
{
|
||||
path: `:${DOSSIER_ID}/file/:${FILE_ID}`,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [DossierFilesGuard, FilePreviewGuard],
|
||||
breadcrumbs: [BreadcrumbTypes.archive, BreadcrumbTypes.dossier, BreadcrumbTypes.file],
|
||||
dossiersService: ARCHIVED_DOSSIERS_SERVICE,
|
||||
},
|
||||
loadChildren: () => import('../dossier/screens/file-preview-screen/file-preview.module').then(m => m.FilePreviewModule),
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class ArchiveRoutingModule {}
|
||||
17
apps/red-ui/src/app/modules/archive/archive.module.ts
Normal file
17
apps/red-ui/src/app/modules/archive/archive.module.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { ArchivedDossiersScreenComponent } from './screens/archived-dossiers-screen/archived-dossiers-screen.component';
|
||||
import { ArchiveRoutingModule } from './archive-routing.module';
|
||||
import { TableItemComponent } from './components/table-item/table-item.component';
|
||||
import { ConfigService } from './services/config.service';
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
|
||||
const components = [TableItemComponent];
|
||||
const screens = [ArchivedDossiersScreenComponent];
|
||||
|
||||
@NgModule({
|
||||
declarations: [...components, ...screens],
|
||||
imports: [CommonModule, ArchiveRoutingModule, SharedModule],
|
||||
providers: [ConfigService],
|
||||
})
|
||||
export class ArchiveModule {}
|
||||
@ -0,0 +1,13 @@
|
||||
<div class="cell">
|
||||
<redaction-dossiers-listing-dossier-name [dossierStats]="stats$ | async" [dossier]="dossier"></redaction-dossiers-listing-dossier-name>
|
||||
</div>
|
||||
|
||||
<div class="cell small-label">{{ dossier.archivedTime | date: 'd MMM. yyyy' }}</div>
|
||||
|
||||
<div class="cell user-column">
|
||||
<redaction-initials-avatar [user]="dossier.ownerId" [withName]="true"></redaction-initials-avatar>
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<redaction-dossier-status [dossier]="dossier"></redaction-dossier-status>
|
||||
</div>
|
||||
@ -0,0 +1,28 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
|
||||
import { Dossier, DossierStats } from '@red/domain';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { DossierStatsService } from '../../../../services/dossiers/dossier-stats.service';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-table-item [dossier]',
|
||||
templateUrl: './table-item.component.html',
|
||||
styleUrls: ['./table-item.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class TableItemComponent implements OnChanges {
|
||||
@Input() dossier!: Dossier;
|
||||
|
||||
readonly stats$: Observable<DossierStats>;
|
||||
readonly #ngOnChanges$ = new BehaviorSubject<string>(undefined);
|
||||
|
||||
constructor(readonly dossierStatsService: DossierStatsService) {
|
||||
this.stats$ = this.#ngOnChanges$.pipe(switchMap(dossierId => this.dossierStatsService.watch$(dossierId)));
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
if (this.dossier) {
|
||||
this.#ngOnChanges$.next(this.dossier.dossierId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
<section>
|
||||
<iqser-page-header></iqser-page-header>
|
||||
|
||||
<div class="overlay-shadow"></div>
|
||||
|
||||
<div class="content-inner">
|
||||
<div class="content-container">
|
||||
<iqser-table
|
||||
[itemSize]="80"
|
||||
[noDataText]="'archived-dossiers-listing.no-data.title' | translate"
|
||||
[noMatchText]="'archived-dossiers-listing.no-match.title' | translate"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
noDataIcon="red:folder"
|
||||
></iqser-table>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<ng-template #tableItemTemplate let-dossier="entity">
|
||||
<redaction-table-item [dossier]="dossier"></redaction-table-item>
|
||||
</ng-template>
|
||||
@ -0,0 +1,26 @@
|
||||
import { ChangeDetectionStrategy, Component, forwardRef, Injector } from '@angular/core';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { ConfigService } from '../../services/config.service';
|
||||
import { DefaultListingServicesTmp, EntitiesService, ListingComponent } from '@iqser/common-ui';
|
||||
import { ArchivedDossiersService } from '../../../../services/dossiers/archived-dossiers.service';
|
||||
import { Dossier } from '@red/domain';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-archived-dossiers-screen',
|
||||
templateUrl: './archived-dossiers-screen.component.html',
|
||||
styleUrls: ['./archived-dossiers-screen.component.scss'],
|
||||
providers: [
|
||||
...DefaultListingServicesTmp,
|
||||
{ provide: EntitiesService, useExisting: ArchivedDossiersService },
|
||||
{ provide: ListingComponent, useExisting: forwardRef(() => ArchivedDossiersScreenComponent) },
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ArchivedDossiersScreenComponent extends ListingComponent<Dossier> {
|
||||
readonly tableColumnConfigs = this._configService.tableConfig;
|
||||
readonly tableHeaderLabel = _('archived-dossiers-listing.table-header.title');
|
||||
|
||||
constructor(protected readonly _injector: Injector, private readonly _configService: ConfigService) {
|
||||
super(_injector);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { TableColumnConfig } from '@iqser/common-ui';
|
||||
import { Dossier } from '@red/domain';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
|
||||
@Injectable()
|
||||
export class ConfigService {
|
||||
get tableConfig(): TableColumnConfig<Dossier>[] {
|
||||
return [
|
||||
{ label: _('archived-dossiers-listing.table-col-names.name'), sortByKey: 'searchKey', width: '2fr' },
|
||||
{ label: _('archived-dossiers-listing.table-col-names.last-modified'), sortByKey: 'archivedTime' },
|
||||
{ label: _('archived-dossiers-listing.table-col-names.owner'), class: 'user-column' },
|
||||
{ label: _('archived-dossiers-listing.table-col-names.dossier-status'), class: 'flex-end', width: '2fr' },
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -5,7 +5,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import * as moment from 'moment';
|
||||
import { downloadTypesTranslations } from '../../../../translations/download-types-translations';
|
||||
import { BaseDialogComponent, IconButtonTypes, SaveOptions } from '@iqser/common-ui';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { ReportTemplateService } from '@services/report-template.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
@ -29,7 +29,7 @@ export class AddDossierDialogComponent extends BaseDialogComponent {
|
||||
availableReportTypes = [];
|
||||
|
||||
constructor(
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _reportTemplateController: ReportTemplateService,
|
||||
@ -61,7 +61,7 @@ export class AddDossierDialogComponent extends BaseDialogComponent {
|
||||
reportTemplateValueMapper = (reportTemplate: IReportTemplate) => reportTemplate.templateId;
|
||||
|
||||
async save(options?: SaveOptions) {
|
||||
const savedDossier = await firstValueFrom(this._dossiersService.createOrUpdate(this._formToObject()));
|
||||
const savedDossier = await firstValueFrom(this._activeDossiersService.createOrUpdate(this._formToObject()));
|
||||
if (savedDossier) {
|
||||
this._dialogRef.close({ dossier: savedDossier, addMembers: options?.addMembers });
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { Dossier, File } from '@red/domain';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
@ -30,14 +30,14 @@ export class AssignReviewerApproverDialogComponent {
|
||||
readonly userService: UserService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _filesService: FilesService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _dialogRef: MatDialogRef<AssignReviewerApproverDialogComponent, boolean>,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: DialogData,
|
||||
) {
|
||||
this.dossier = this._dossiersService.find(this.data.files[0].dossierId);
|
||||
this.dossier = this._activeDossiersService.find(this.data.files[0].dossierId);
|
||||
this.form = this._getForm();
|
||||
}
|
||||
|
||||
@ -102,28 +102,11 @@ export class AssignReviewerApproverDialogComponent {
|
||||
this._loadingService.start();
|
||||
try {
|
||||
if (!this.selectedUser) {
|
||||
await firstValueFrom(
|
||||
this._filesService.setUnassigned(
|
||||
this.data.files.map(f => f.fileId),
|
||||
this.dossier.id,
|
||||
),
|
||||
);
|
||||
await firstValueFrom(this._filesService.setUnassigned(this.data.files, this.dossier.id));
|
||||
} else if (this.data.mode === 'reviewer') {
|
||||
await firstValueFrom(
|
||||
this._filesService.setReviewerFor(
|
||||
this.data.files.map(f => f.fileId),
|
||||
this.dossier.id,
|
||||
this.selectedUser,
|
||||
),
|
||||
);
|
||||
await firstValueFrom(this._filesService.setReviewerFor(this.data.files, this.dossier.id, this.selectedUser));
|
||||
} else {
|
||||
await firstValueFrom(
|
||||
this._filesService.setUnderApprovalFor(
|
||||
this.data.files.map(f => f.fileId),
|
||||
this.dossier.id,
|
||||
this.selectedUser,
|
||||
),
|
||||
);
|
||||
await firstValueFrom(this._filesService.setUnderApprovalFor(this.data.files, this.dossier.id, this.selectedUser));
|
||||
}
|
||||
} catch (error) {
|
||||
this._toaster.error(_('error.http.generic'), { params: error });
|
||||
|
||||
@ -3,7 +3,7 @@ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { JustificationsService } from '@services/entity-services/justifications.service';
|
||||
import { Dossier } from '@red/domain';
|
||||
import { BaseDialogComponent } from '@iqser/common-ui';
|
||||
@ -23,7 +23,8 @@ export class ChangeLegalBasisDialogComponent extends BaseDialogComponent impleme
|
||||
|
||||
constructor(
|
||||
private readonly _justificationsService: JustificationsService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
protected readonly _injector: Injector,
|
||||
protected readonly _dialogRef: MatDialogRef<ChangeLegalBasisDialogComponent>,
|
||||
|
||||
@ -3,7 +3,7 @@ import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { Dossier, File, IFileAttributeConfig } from '@red/domain';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { BaseDialogComponent } from '@iqser/common-ui';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
@ -19,16 +19,16 @@ export class DocumentInfoDialogComponent extends BaseDialogComponent implements
|
||||
private readonly _dossier: Dossier;
|
||||
|
||||
constructor(
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _fileAttributesService: FileAttributesService,
|
||||
private readonly _filesService: FilesService,
|
||||
protected readonly _injector: Injector,
|
||||
protected readonly _dialogRef: MatDialogRef<DocumentInfoDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: File,
|
||||
@Inject(MAT_DIALOG_DATA) readonly file: File,
|
||||
) {
|
||||
super(_injector, _dialogRef);
|
||||
this._dossier = this._dossiersService.find(this.data.dossierId);
|
||||
this._dossier = this._activeDossiersService.find(this.file.dossierId);
|
||||
}
|
||||
|
||||
async ngOnInit() {
|
||||
@ -42,11 +42,11 @@ export class DocumentInfoDialogComponent extends BaseDialogComponent implements
|
||||
|
||||
async save() {
|
||||
const attributeIdToValue = {
|
||||
...this.data.fileAttributes?.attributeIdToValue,
|
||||
...this.file.fileAttributes?.attributeIdToValue,
|
||||
...this.form.getRawValue(),
|
||||
};
|
||||
await firstValueFrom(this._fileAttributesService.setFileAttributes({ attributeIdToValue }, this.data.dossierId, this.data.fileId));
|
||||
await firstValueFrom(this._filesService.reload(this.data.dossierId, this.data.fileId));
|
||||
await firstValueFrom(this._fileAttributesService.setFileAttributes({ attributeIdToValue }, this.file.dossierId, this.file.fileId));
|
||||
await firstValueFrom(this._filesService.reload(this.file.dossierId, this.file));
|
||||
this._dialogRef.close(true);
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ export class DocumentInfoDialogComponent extends BaseDialogComponent implements
|
||||
this.attributes.reduce(
|
||||
(acc, attr) => ({
|
||||
...acc,
|
||||
[attr.id]: [this.data.fileAttributes?.attributeIdToValue[attr.id]],
|
||||
[attr.id]: [this.file.fileAttributes?.attributeIdToValue[attr.id]],
|
||||
}),
|
||||
{},
|
||||
),
|
||||
|
||||
@ -50,7 +50,7 @@ export class EditDossierAttributesComponent implements EditDossierSectionInterfa
|
||||
}
|
||||
|
||||
get disabled(): boolean {
|
||||
return !this._permissionsService.isOwner(this.dossier);
|
||||
return !this._permissionsService.canHardDeleteOrRestore(this.dossier);
|
||||
}
|
||||
|
||||
get valid(): boolean {
|
||||
|
||||
@ -7,6 +7,7 @@ import {
|
||||
DefaultListingServices,
|
||||
getLeftDateTime,
|
||||
IListable,
|
||||
IRouterPath,
|
||||
ListingComponent,
|
||||
LoadingService,
|
||||
SortingOrders,
|
||||
@ -21,11 +22,11 @@ import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { FileManagementService } from '@services/entity-services/file-management.service';
|
||||
import { workflowFileStatusTranslations } from '../../../translations/file-status-translations';
|
||||
import { workflowFileStatusTranslations } from '../../../../../translations/file-status-translations';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
|
||||
interface FileListItem extends IFile, IListable {
|
||||
interface FileListItem extends IFile, IListable, IRouterPath {
|
||||
readonly canHardDelete: boolean;
|
||||
readonly canRestore: boolean;
|
||||
readonly restoreDate: string;
|
||||
@ -129,14 +130,13 @@ export class EditDossierDeletedDocumentsComponent extends ListingComponent<FileL
|
||||
disabledFn = (file: FileListItem) => !file.canRestore;
|
||||
|
||||
private async _restore(files: FileListItem[]): Promise<void> {
|
||||
const fileIds = files.map(f => f.fileId);
|
||||
await firstValueFrom(this._fileManagementService.restore(fileIds, this.dossier.id));
|
||||
const fileIds = files.map(f => f.id);
|
||||
await firstValueFrom(this._fileManagementService.restore(files, this.dossier.id));
|
||||
this._removeFromList(fileIds);
|
||||
await firstValueFrom(this._filesService.loadAll(files[0].dossierId));
|
||||
}
|
||||
|
||||
private async _hardDelete(files: FileListItem[]) {
|
||||
const fileIds = files.map(f => f.fileId);
|
||||
const fileIds = files.map(f => f.id);
|
||||
await firstValueFrom(this._fileManagementService.hardDelete(this.dossier.id, fileIds));
|
||||
this._removeFromList(fileIds);
|
||||
}
|
||||
@ -151,7 +151,7 @@ export class EditDossierDeletedDocumentsComponent extends ListingComponent<FileL
|
||||
}
|
||||
|
||||
private _toListItem(_file: IFile): FileListItem {
|
||||
const file = new File(_file, this._userService.getNameForId(_file.assignee));
|
||||
const file = new File(_file, this._userService.getNameForId(_file.assignee), this.dossier.routerPath);
|
||||
const restoreDate = this._getRestoreDate(_file.softDeleted);
|
||||
return {
|
||||
id: file.fileId,
|
||||
@ -164,7 +164,10 @@ export class EditDossierDeletedDocumentsComponent extends ListingComponent<FileL
|
||||
}
|
||||
|
||||
private _canPerformActions(file: File): boolean {
|
||||
return this._userService.currentUser.isManager || this._permissionsService.canDeleteFile(file);
|
||||
return (
|
||||
this._permissionsService.canHardDeleteOrRestore(this.dossier) &&
|
||||
(this._userService.currentUser.isManager || this._permissionsService.canDeleteFile(file))
|
||||
);
|
||||
}
|
||||
|
||||
private _canRestore(file: File, restoreDate: string): boolean {
|
||||
|
||||
@ -5,10 +5,10 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { DictionaryManagerComponent } from '@shared/components/dictionary-manager/dictionary-manager.component';
|
||||
import { DictionaryService } from '@shared/services/dictionary.service';
|
||||
import { CircleButtonTypes, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-dossier-dictionary',
|
||||
@ -57,8 +57,8 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
|
||||
|
||||
async ngOnInit() {
|
||||
this._loadingService.start();
|
||||
this.canEdit = this._permissionsService.canEditDossier(this.dossier);
|
||||
this.canEditDisplayName = this._permissionsService.isOwner(this.dossier);
|
||||
this.canEdit = this._permissionsService.canEditDossierDictionary(this.dossier);
|
||||
this.canEditDisplayName = this._permissionsService.canEditDossierDictionaryDisplayName(this.dossier);
|
||||
await this._updateDossierDictionary();
|
||||
this.form = this._getForm();
|
||||
this._loadingService.stop();
|
||||
@ -121,7 +121,7 @@ export class EditDossierDictionaryComponent implements EditDossierSectionInterfa
|
||||
addToDictionaryAction: [
|
||||
{
|
||||
value: this.dossierDictionary.addToDictionaryAction,
|
||||
disabled: !this._permissionsService.isOwner(this.dossier),
|
||||
disabled: !this._permissionsService.canEditDossierDictionaryAddAction(this.dossier),
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
@ -1,17 +1,31 @@
|
||||
<form *ngIf="form" [formGroup]="form">
|
||||
<redaction-select
|
||||
[label]="'report-type.label' | translate: { length: reportTypesLength }"
|
||||
[optionTemplate]="reportTemplateOptionTemplate"
|
||||
[options]="availableReportTypes"
|
||||
[valueMapper]="reportTemplateValueMapper"
|
||||
class="mr-16"
|
||||
formControlName="reportTemplateIds"
|
||||
></redaction-select>
|
||||
<redaction-select
|
||||
[label]="'download-type.label' | translate: { length: downloadFileTypesLength }"
|
||||
[options]="downloadTypes"
|
||||
formControlName="downloadFileTypes"
|
||||
></redaction-select>
|
||||
<div>
|
||||
<redaction-select
|
||||
[label]="'report-type.label' | translate: { length: reportTypesLength }"
|
||||
[optionTemplate]="reportTemplateOptionTemplate"
|
||||
[options]="availableReportTypes"
|
||||
[valueMapper]="reportTemplateValueMapper"
|
||||
class="mr-16"
|
||||
formControlName="reportTemplateIds"
|
||||
></redaction-select>
|
||||
<redaction-select
|
||||
[label]="'download-type.label' | translate: { length: downloadFileTypesLength }"
|
||||
[options]="downloadTypes"
|
||||
formControlName="downloadFileTypes"
|
||||
></redaction-select>
|
||||
</div>
|
||||
|
||||
<div class="mt-32 mb-14">
|
||||
<mat-checkbox class="watermark" color="primary" formControlName="watermarkEnabled">
|
||||
{{ 'edit-dossier-dialog.general-info.form.watermark' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<mat-checkbox class="watermark-preview" color="primary" formControlName="watermarkPreviewEnabled">
|
||||
{{ 'edit-dossier-dialog.general-info.form.watermark-preview' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<ng-template #reportTemplateOptionTemplate let-option="option">
|
||||
|
||||
@ -10,4 +10,9 @@ redaction-select {
|
||||
form {
|
||||
height: calc(100% - 44px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,10 +3,10 @@ import { Dossier, DownloadFileType, IReportTemplate } from '@red/domain';
|
||||
import { FormBuilder, FormGroup } from '@angular/forms';
|
||||
import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface';
|
||||
import { downloadTypesTranslations } from '../../../../../translations/download-types-translations';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ReportTemplateService } from '@services/report-template.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-dossier-download-package',
|
||||
@ -40,9 +40,17 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
|
||||
return this.form.controls['downloadFileTypes']?.value?.length || 0;
|
||||
}
|
||||
|
||||
get changed() {
|
||||
if (this.form) {
|
||||
for (const key of Object.keys(this.form.getRawValue())) {
|
||||
get changed(): boolean {
|
||||
if (!this.form) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const key of Object.keys(this.form.getRawValue())) {
|
||||
if (key.startsWith('watermark')) {
|
||||
if (this.dossier[key] !== this.form.get(key).value) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (this.dossier[key].length !== this.form.get(key).value.length) {
|
||||
return true;
|
||||
}
|
||||
@ -86,6 +94,8 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
|
||||
...this.dossier,
|
||||
downloadFileTypes: this.form.get('downloadFileTypes').value,
|
||||
reportTemplateIds: this.form.get('reportTemplateIds').value,
|
||||
watermarkEnabled: this.form.get('watermarkEnabled').value,
|
||||
watermarkPreviewEnabled: this.form.get('watermarkPreviewEnabled').value,
|
||||
};
|
||||
|
||||
const updatedDossier = await firstValueFrom(this._dossiersService.createOrUpdate(dossier));
|
||||
@ -96,6 +106,8 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
|
||||
this.form.reset({
|
||||
downloadFileTypes: this.dossier.downloadFileTypes,
|
||||
reportTemplateIds: this.dossier.reportTemplateIds,
|
||||
watermarkEnabled: this.dossier.watermarkEnabled,
|
||||
watermarkPreviewEnabled: this.dossier.watermarkPreviewEnabled,
|
||||
});
|
||||
}
|
||||
|
||||
@ -104,6 +116,8 @@ export class EditDossierDownloadPackageComponent implements OnInit, EditDossierS
|
||||
{
|
||||
reportTemplateIds: [this.dossier.reportTemplateIds],
|
||||
downloadFileTypes: [this.dossier.downloadFileTypes],
|
||||
watermarkEnabled: [this.dossier.watermarkEnabled],
|
||||
watermarkPreviewEnabled: [this.dossier.watermarkPreviewEnabled],
|
||||
},
|
||||
{
|
||||
validators: control =>
|
||||
|
||||
@ -5,13 +5,10 @@
|
||||
|
||||
<div class="dialog-content">
|
||||
<iqser-side-nav [title]="'edit-dossier-dialog.side-nav-title' | translate">
|
||||
<div
|
||||
(click)="changeTab(item.key)"
|
||||
*ngFor="let item of navItems"
|
||||
[class.active]="item.key === activeNav"
|
||||
[translate]="item.sideNavTitle || item.title"
|
||||
class="item"
|
||||
></div>
|
||||
<div (click)="changeTab(item.key)" *ngFor="let item of navItems" [class.active]="item.key === activeNav" class="item">
|
||||
{{ item.sideNavTitle || item.title | translate }}
|
||||
<mat-icon *ngIf="item.readonly" svgIcon="red:read-only"></mat-icon>
|
||||
</div>
|
||||
</iqser-side-nav>
|
||||
|
||||
<div>
|
||||
@ -20,6 +17,11 @@
|
||||
{{ activeNavItem.title | translate }}
|
||||
</div>
|
||||
|
||||
<div *ngIf="activeNavItem.readonly" class="read-only all-caps-label primary">
|
||||
<mat-icon class="mr-8" svgIcon="red:read-only"></mat-icon>
|
||||
{{ 'readonly' | translate }}
|
||||
</div>
|
||||
|
||||
<redaction-edit-dossier-general-info
|
||||
*ngIf="activeNav === 'dossierInfo'"
|
||||
[dossier]="dossier"
|
||||
@ -53,9 +55,9 @@
|
||||
(click)="save()"
|
||||
[disabled]="disabled || !valid || !changed"
|
||||
color="primary"
|
||||
id="editDossierSaveButton"
|
||||
mat-flat-button
|
||||
type="button"
|
||||
id="editDossierSaveButton"
|
||||
>
|
||||
{{ 'edit-dossier-dialog.actions.save' | translate }}
|
||||
</button>
|
||||
@ -72,5 +74,5 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<iqser-circle-button class="dialog-close" icon="iqser:close" (action)="close()" id="editDossierCloseButton"></iqser-circle-button>
|
||||
<iqser-circle-button (action)="close()" class="dialog-close" icon="iqser:close" id="editDossierCloseButton"></iqser-circle-button>
|
||||
</section>
|
||||
|
||||
@ -41,3 +41,15 @@ redaction-edit-dossier-dictionary {
|
||||
.stats-subtitle {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.read-only {
|
||||
display: flex;
|
||||
position: absolute;
|
||||
right: 32px;
|
||||
top: 108px;
|
||||
|
||||
mat-icon {
|
||||
height: 14px;
|
||||
width: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,21 +10,30 @@ 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 { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { EditDossierTeamComponent } from './edit-dossier-team/edit-dossier-team.component';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider';
|
||||
|
||||
type Section = 'dossierInfo' | 'downloadPackage' | 'dossierDictionary' | 'members' | 'dossierAttributes' | 'deletedDocuments';
|
||||
|
||||
interface NavItem {
|
||||
key: Section;
|
||||
title?: string;
|
||||
sideNavTitle?: string;
|
||||
readonly?: boolean;
|
||||
}
|
||||
|
||||
@Component({
|
||||
templateUrl: './edit-dossier-dialog.component.html',
|
||||
styleUrls: ['./edit-dossier-dialog.component.scss'],
|
||||
providers: [dossiersServiceProvider],
|
||||
})
|
||||
export class EditDossierDialogComponent extends BaseDialogComponent implements AfterViewInit {
|
||||
readonly navItems: { key: Section; title?: string; sideNavTitle?: string }[];
|
||||
navItems: NavItem[] = [];
|
||||
readonly iconButtonTypes = IconButtonTypes;
|
||||
activeNav: Section;
|
||||
readonly dossier$: Observable<Dossier>;
|
||||
@ -40,7 +49,7 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A
|
||||
|
||||
constructor(
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: DossiersService,
|
||||
private readonly _changeRef: ChangeDetectorRef,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
@ -54,48 +63,16 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A
|
||||
},
|
||||
) {
|
||||
super(_injector, _dialogRef, true);
|
||||
this.navItems = [
|
||||
{
|
||||
key: 'dossierInfo',
|
||||
title: _('edit-dossier-dialog.nav-items.general-info'),
|
||||
sideNavTitle: _('edit-dossier-dialog.nav-items.dossier-info'),
|
||||
},
|
||||
{
|
||||
key: 'downloadPackage',
|
||||
title: _('edit-dossier-dialog.nav-items.choose-download'),
|
||||
sideNavTitle: _('edit-dossier-dialog.nav-items.download-package'),
|
||||
},
|
||||
{
|
||||
key: 'dossierDictionary',
|
||||
sideNavTitle: _('edit-dossier-dialog.nav-items.dictionary'),
|
||||
title: _('edit-dossier-dialog.nav-items.dossier-dictionary'),
|
||||
},
|
||||
{
|
||||
key: 'members',
|
||||
title: _('edit-dossier-dialog.nav-items.team-members'),
|
||||
sideNavTitle: _('edit-dossier-dialog.nav-items.members'),
|
||||
},
|
||||
{
|
||||
key: 'dossierAttributes',
|
||||
title: _('edit-dossier-dialog.nav-items.dossier-attributes'),
|
||||
},
|
||||
{
|
||||
key: 'deletedDocuments',
|
||||
sideNavTitle: _('edit-dossier-dialog.nav-items.deleted-documents'),
|
||||
},
|
||||
];
|
||||
|
||||
this.dossier$ = this._dossiersService.getEntityChanged$(_data.dossierId).pipe(tap(dossier => (this._dossier = dossier)));
|
||||
this.dossier$ = this._activeDossiersService.getEntityChanged$(_data.dossierId).pipe(
|
||||
tap(dossier => {
|
||||
this._dossier = dossier;
|
||||
this._initializeNavItems();
|
||||
}),
|
||||
);
|
||||
this.activeNav = _data.section || 'dossierInfo';
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
if (!this._dossier.ownerId) {
|
||||
this._toaster.error(_('edit-dossier-dialog.missing-owner'));
|
||||
}
|
||||
}
|
||||
|
||||
get activeNavItem(): { key: string; title?: string } {
|
||||
get activeNavItem(): NavItem {
|
||||
return this.navItems.find(item => item.key === this.activeNav);
|
||||
}
|
||||
|
||||
@ -137,6 +114,12 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A
|
||||
return this.activeComponent?.disabled;
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
if (!this._dossier.ownerId) {
|
||||
this._toaster.error(_('edit-dossier-dialog.missing-owner'));
|
||||
}
|
||||
}
|
||||
|
||||
async save(options?: SaveOptions) {
|
||||
this._loadingService.start();
|
||||
const result = await this.activeComponent.save();
|
||||
@ -171,4 +154,40 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A
|
||||
this.activeNav = key;
|
||||
}
|
||||
}
|
||||
|
||||
private _initializeNavItems(): void {
|
||||
this.navItems = [
|
||||
{
|
||||
key: 'dossierInfo',
|
||||
title: _('edit-dossier-dialog.nav-items.general-info'),
|
||||
sideNavTitle: _('edit-dossier-dialog.nav-items.dossier-info'),
|
||||
readonly: !this._dossier.isActive,
|
||||
},
|
||||
{
|
||||
key: 'downloadPackage',
|
||||
title: _('edit-dossier-dialog.nav-items.choose-download'),
|
||||
sideNavTitle: _('edit-dossier-dialog.nav-items.download-package'),
|
||||
},
|
||||
{
|
||||
key: 'dossierDictionary',
|
||||
sideNavTitle: _('edit-dossier-dialog.nav-items.dictionary'),
|
||||
title: _('edit-dossier-dialog.nav-items.dossier-dictionary'),
|
||||
readonly: !this._permissionsService.canEditDossierDictionary(this._dossier),
|
||||
},
|
||||
{
|
||||
key: 'members',
|
||||
title: _('edit-dossier-dialog.nav-items.team-members'),
|
||||
sideNavTitle: _('edit-dossier-dialog.nav-items.members'),
|
||||
},
|
||||
{
|
||||
key: 'dossierAttributes',
|
||||
title: _('edit-dossier-dialog.nav-items.dossier-attributes'),
|
||||
readonly: !this._permissionsService.canEditDossierAttributes(this._dossier),
|
||||
},
|
||||
{
|
||||
key: 'deletedDocuments',
|
||||
sideNavTitle: _('edit-dossier-dialog.nav-items.deleted-documents'),
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { Dossier, IDossierRequest } from '@red/domain';
|
||||
import { AutoUnsubscribe } from '@iqser/common-ui';
|
||||
import { EditDossierSaveResult, EditDossierSectionInterface } from '../edit-dossier-section.interface';
|
||||
import { BehaviorSubject, firstValueFrom } from 'rxjs';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-dossier-team',
|
||||
|
||||
@ -38,18 +38,6 @@
|
||||
type="text"
|
||||
></textarea>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<mat-checkbox class="watermark" color="primary" formControlName="watermarkEnabled">
|
||||
{{ 'edit-dossier-dialog.general-info.form.watermark' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<mat-checkbox class="watermark-preview" color="primary" formControlName="watermarkPreviewEnabled">
|
||||
{{ 'edit-dossier-dialog.general-info.form.watermark-preview' | translate }}
|
||||
</mat-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex fields-container">
|
||||
@ -69,7 +57,7 @@
|
||||
<mat-checkbox
|
||||
(change)="hasDueDate = !hasDueDate"
|
||||
[checked]="hasDueDate"
|
||||
[disabled]="!permissionsService.canEditDossier(dossier)"
|
||||
[disabled]="form.get('dueDate').disabled"
|
||||
class="filter-menu-checkbox"
|
||||
color="primary"
|
||||
>
|
||||
@ -95,5 +83,13 @@
|
||||
[type]="iconButtonTypes.dark"
|
||||
icon="iqser:trash"
|
||||
></iqser-icon-button>
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="archiveDossier()"
|
||||
*ngIf="permissionsService.canArchiveDossier(dossier)"
|
||||
[label]="'dossier-listing.archive.action' | translate"
|
||||
[type]="iconButtonTypes.dark"
|
||||
icon="red:archive"
|
||||
></iqser-icon-button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@ -8,15 +8,17 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { MatDialogRef } from '@angular/material/dialog';
|
||||
import { EditDossierDialogComponent } from '../edit-dossier-dialog.component';
|
||||
import { ConfirmationDialogInput, IconButtonTypes, TitleColors, Toaster } from '@iqser/common-ui';
|
||||
import { ConfirmationDialogInput, ConfirmOptions, IconButtonTypes, LoadingService, TitleColors, Toaster } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
|
||||
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DossierStateService } from '@services/entity-services/dossier-state.service';
|
||||
import { DOSSIER_TEMPLATE_ID } from '@utils/constants';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DossiersService } from '@services/dossiers/dossiers.service';
|
||||
import { TrashDossiersService } from '@services/entity-services/trash-dossiers.service';
|
||||
import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-edit-dossier-general-info',
|
||||
@ -39,13 +41,16 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
private readonly _dossierStateService: DossierStateService,
|
||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _trashDossiersService: TrashDossiersService,
|
||||
private readonly _dossierStatsService: DossierStatsService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _router: Router,
|
||||
private readonly _editDossierDialogRef: MatDialogRef<EditDossierDialogComponent>,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _translateService: TranslateService,
|
||||
private readonly _archivedDossiersService: ArchivedDossiersService,
|
||||
) {}
|
||||
|
||||
get changed(): boolean {
|
||||
@ -102,8 +107,6 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
dossierTemplateId: this.dossier.dossierTemplateId,
|
||||
dossierStatusId: this.dossier.dossierStatusId,
|
||||
description: this.dossier.description,
|
||||
watermarkEnabled: this.dossier.watermarkEnabled,
|
||||
watermarkPreviewEnabled: this.dossier.watermarkPreviewEnabled,
|
||||
dueDate: this.dossier.dueDate,
|
||||
});
|
||||
}
|
||||
@ -113,8 +116,6 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
...this.dossier,
|
||||
dossierName: this.form.get('dossierName').value,
|
||||
description: this.form.get('description').value,
|
||||
watermarkEnabled: this.form.get('watermarkEnabled').value,
|
||||
watermarkPreviewEnabled: this.form.get('watermarkPreviewEnabled').value,
|
||||
dueDate: this.hasDueDate ? this.form.get('dueDate').value : undefined,
|
||||
dossierTemplateId: this.form.get(DOSSIER_TEMPLATE_ID).value,
|
||||
dossierStatusId: this.form.get('dossierStatusId').value,
|
||||
@ -129,7 +130,6 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
title: _('confirmation-dialog.delete-dossier.title'),
|
||||
titleColor: TitleColors.WARN,
|
||||
question: _('confirmation-dialog.delete-dossier.question'),
|
||||
// details: _('confirmation-dialog.delete-dossier.details'),
|
||||
confirmationText: _('confirmation-dialog.delete-dossier.confirmation-text'),
|
||||
requireInput: true,
|
||||
denyText: _('confirmation-dialog.delete-dossier.deny-text'),
|
||||
@ -139,34 +139,56 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
|
||||
},
|
||||
});
|
||||
this._dialogService.openDialog('confirm', null, data, async () => {
|
||||
await firstValueFrom(this._dossiersService.delete(this.dossier));
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._trashDossiersService.delete(this.dossier));
|
||||
this._editDossierDialogRef.close();
|
||||
this._router.navigate(['main', 'dossiers']).then(() => this.#notifyDossierDeleted());
|
||||
await this._router.navigate(['main', 'dossiers']);
|
||||
this._loadingService.stop();
|
||||
this._toaster.success(_('edit-dossier-dialog.delete-successful'), { params: this.dossier });
|
||||
});
|
||||
}
|
||||
|
||||
archiveDossier() {
|
||||
const data = new ConfirmationDialogInput({
|
||||
title: _('confirm-archive-dossier.title'),
|
||||
details: _('confirm-archive-dossier.details'),
|
||||
question: _('confirm-archive-dossier.warning'),
|
||||
confirmationText: _('confirm-archive-dossier.archive'),
|
||||
denyText: _('confirm-archive-dossier.cancel'),
|
||||
titleColor: TitleColors.WARN,
|
||||
translateParams: { ...this.dossier },
|
||||
checkboxes: [{ value: false, label: _('confirm-archive-dossier.checkbox.documents') }],
|
||||
toastMessage: _('confirm-archive-dossier.toast-error'),
|
||||
});
|
||||
this._dialogService.openDialog('confirm', null, data, async result => {
|
||||
if (result === ConfirmOptions.CONFIRM) {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(this._archivedDossiersService.archive([this.dossier]));
|
||||
await this._router.navigate(['main', 'dossiers']);
|
||||
this._toaster.success(_('dossier-listing.archive.archive-succeeded'), { params: this.dossier });
|
||||
this._editDossierDialogRef.close();
|
||||
this._loadingService.stop();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#getForm(): FormGroup {
|
||||
const formFieldWithArchivedCheck = value => ({ value, disabled: !this.dossier.isActive });
|
||||
return this._formBuilder.group({
|
||||
dossierName: [this.dossier.dossierName, Validators.required],
|
||||
dossierName: [formFieldWithArchivedCheck(this.dossier.dossierName), Validators.required],
|
||||
dossierTemplateId: [
|
||||
{
|
||||
value: this.dossier.dossierTemplateId,
|
||||
disabled: this._dossierStatsService.get(this.dossier.dossierId).hasFiles,
|
||||
disabled: this._dossierStatsService.get(this.dossier.dossierId).hasFiles || !this.dossier.isActive,
|
||||
},
|
||||
Validators.required,
|
||||
],
|
||||
dossierStatusId: [{ value: this.dossier.dossierStatusId, disabled: !this.states.length }],
|
||||
description: [this.dossier.description],
|
||||
dueDate: [this.dossier.dueDate],
|
||||
watermarkEnabled: [this.dossier.watermarkEnabled],
|
||||
watermarkPreviewEnabled: [this.dossier.watermarkPreviewEnabled],
|
||||
dossierStatusId: [{ value: this.dossier.dossierStatusId, disabled: !this.states.length || !this.dossier.isActive }],
|
||||
description: [formFieldWithArchivedCheck(this.dossier.description)],
|
||||
dueDate: [formFieldWithArchivedCheck(this.dossier.dueDate)],
|
||||
});
|
||||
}
|
||||
|
||||
#notifyDossierDeleted() {
|
||||
this._toaster.success(_('edit-dossier-dialog.delete-successful'), { params: { dossierName: this.dossier.dossierName } });
|
||||
}
|
||||
|
||||
#filterInvalidDossierTemplates() {
|
||||
this.dossierTemplates = this._dossierTemplatesService.all.filter(r => {
|
||||
if (this.dossier?.dossierTemplateId === r.dossierTemplateId) {
|
||||
|
||||
@ -6,7 +6,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/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { JustificationsService } from '@services/entity-services/justifications.service';
|
||||
import { Dossier, ILegalBasisChangeRequest } from '@red/domain';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
@ -27,7 +27,7 @@ export class ForceAnnotationDialogComponent extends BaseDialogComponent implemen
|
||||
legalOptions: LegalBasisOption[] = [];
|
||||
|
||||
constructor(
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _notificationService: Toaster,
|
||||
|
||||
@ -6,7 +6,7 @@ import { ManualAnnotationService } from '../../services/manual-annotation.servic
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { JustificationsService } from '@services/entity-services/justifications.service';
|
||||
import { Dictionary, Dossier, IAddRedactionRequest } from '@red/domain';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { DictionaryService } from '@shared/services/dictionary.service';
|
||||
import { BaseDialogComponent, CircleButtonTypes } from '@iqser/common-ui';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
@ -36,14 +36,15 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _justificationsService: JustificationsService,
|
||||
private readonly _manualAnnotationService: ManualAnnotationService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
protected readonly _injector: Injector,
|
||||
protected readonly _dialogRef: MatDialogRef<ManualAnnotationDialogComponent>,
|
||||
@Inject(MAT_DIALOG_DATA) public data: { manualRedactionEntryWrapper: ManualRedactionEntryWrapper; dossierId: string },
|
||||
) {
|
||||
super(_injector, _dialogRef);
|
||||
this._dossier = this._dossiersService.find(this.data.dossierId);
|
||||
this._dossier = this._activeDossiersService.find(this.data.dossierId);
|
||||
|
||||
this.isFalsePositiveRequest = this.data.manualRedactionEntryWrapper.type === 'FALSE_POSITIVE';
|
||||
this.isDictionaryRequest = this.data.manualRedactionEntryWrapper.type === 'DICTIONARY' || this.isFalsePositiveRequest;
|
||||
|
||||
@ -1,23 +1,20 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { SearchScreenComponent } from './screens/search-screen/search-screen.component';
|
||||
import { FilePreviewGuard } from '@guards/file-preview.guard';
|
||||
import { DossierFilesGuard } from '@guards/dossier-files-guard';
|
||||
import { CompositeRouteGuard } from '@iqser/common-ui';
|
||||
import { BreadcrumbTypes } from '@red/domain';
|
||||
import { DOSSIER_ID, FILE_ID } from '@utils/constants';
|
||||
import { ACTIVE_DOSSIERS_SERVICE } from '../../tokens';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'search',
|
||||
component: SearchScreenComponent,
|
||||
},
|
||||
{
|
||||
path: `:${DOSSIER_ID}`,
|
||||
canActivate: [CompositeRouteGuard],
|
||||
data: {
|
||||
routeGuards: [DossierFilesGuard],
|
||||
breadcrumbs: [BreadcrumbTypes.main, BreadcrumbTypes.dossier],
|
||||
dossiersService: ACTIVE_DOSSIERS_SERVICE,
|
||||
},
|
||||
loadChildren: () => import('./screens/dossier-overview/dossier-overview.module').then(m => m.DossierOverviewModule),
|
||||
},
|
||||
@ -27,6 +24,7 @@ const routes: Routes = [
|
||||
data: {
|
||||
routeGuards: [DossierFilesGuard, FilePreviewGuard],
|
||||
breadcrumbs: [BreadcrumbTypes.main, BreadcrumbTypes.dossier, BreadcrumbTypes.file],
|
||||
dossiersService: ACTIVE_DOSSIERS_SERVICE,
|
||||
},
|
||||
loadChildren: () => import('./screens/file-preview-screen/file-preview.module').then(m => m.FilePreviewModule),
|
||||
},
|
||||
|
||||
@ -1,66 +1,31 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { AddDossierDialogComponent } from './dialogs/add-dossier-dialog/add-dossier-dialog.component';
|
||||
import { AssignReviewerApproverDialogComponent } from './dialogs/assign-reviewer-approver-dialog/assign-reviewer-approver-dialog.component';
|
||||
import { ManualAnnotationDialogComponent } from './dialogs/manual-redaction-dialog/manual-annotation-dialog.component';
|
||||
import { ForceAnnotationDialogComponent } from './dialogs/force-redaction-dialog/force-annotation-dialog.component';
|
||||
import { RemoveAnnotationsDialogComponent } from './dialogs/remove-annotations-dialog/remove-annotations-dialog.component';
|
||||
import { DocumentInfoDialogComponent } from './dialogs/document-info-dialog/document-info-dialog.component';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { DossiersRoutingModule } from './dossiers-routing.module';
|
||||
import { FileUploadDownloadModule } from '@upload-download/file-upload-download.module';
|
||||
import { DossiersDialogService } from './services/dossiers-dialog.service';
|
||||
import { ManualAnnotationService } from './services/manual-annotation.service';
|
||||
import { AnnotationProcessingService } from './services/annotation-processing.service';
|
||||
import { EditDossierDialogComponent } from './dialogs/edit-dossier-dialog/edit-dossier-dialog.component';
|
||||
import { EditDossierGeneralInfoComponent } from './dialogs/edit-dossier-dialog/general-info/edit-dossier-general-info.component';
|
||||
import { EditDossierDownloadPackageComponent } from './dialogs/edit-dossier-dialog/download-package/edit-dossier-download-package.component';
|
||||
import { EditDossierDictionaryComponent } from './dialogs/edit-dossier-dialog/dictionary/edit-dossier-dictionary.component';
|
||||
import { ChangeLegalBasisDialogComponent } from './dialogs/change-legal-basis-dialog/change-legal-basis-dialog.component';
|
||||
import { RecategorizeImageDialogComponent } from './dialogs/recategorize-image-dialog/recategorize-image-dialog.component';
|
||||
import { EditDossierAttributesComponent } from './dialogs/edit-dossier-dialog/attributes/edit-dossier-attributes.component';
|
||||
import { SearchScreenComponent } from './screens/search-screen/search-screen.component';
|
||||
import { EditDossierDeletedDocumentsComponent } from './dialogs/edit-dossier-dialog/deleted-documents/edit-dossier-deleted-documents.component';
|
||||
import { OverlayModule } from '@angular/cdk/overlay';
|
||||
import { SharedDossiersModule } from './shared/shared-dossiers.module';
|
||||
import { ResizeAnnotationDialogComponent } from './dialogs/resize-annotation-dialog/resize-annotation-dialog.component';
|
||||
import { EditDossierTeamComponent } from './dialogs/edit-dossier-dialog/edit-dossier-team/edit-dossier-team.component';
|
||||
import { HighlightActionDialogComponent } from './screens/file-preview-screen/dialogs/highlight-action-dialog/highlight-action-dialog.component';
|
||||
import { ColorPickerModule } from 'ngx-color-picker';
|
||||
|
||||
const screens = [SearchScreenComponent];
|
||||
|
||||
const dialogs = [
|
||||
AddDossierDialogComponent,
|
||||
EditDossierDialogComponent,
|
||||
ManualAnnotationDialogComponent,
|
||||
ForceAnnotationDialogComponent,
|
||||
RemoveAnnotationsDialogComponent,
|
||||
ResizeAnnotationDialogComponent,
|
||||
DocumentInfoDialogComponent,
|
||||
AssignReviewerApproverDialogComponent,
|
||||
ChangeLegalBasisDialogComponent,
|
||||
RecategorizeImageDialogComponent,
|
||||
HighlightActionDialogComponent,
|
||||
];
|
||||
|
||||
const components = [
|
||||
EditDossierGeneralInfoComponent,
|
||||
EditDossierDownloadPackageComponent,
|
||||
EditDossierDictionaryComponent,
|
||||
EditDossierAttributesComponent,
|
||||
EditDossierTeamComponent,
|
||||
EditDossierDeletedDocumentsComponent,
|
||||
|
||||
...screens,
|
||||
...dialogs,
|
||||
];
|
||||
|
||||
const services = [DossiersDialogService, ManualAnnotationService, AnnotationProcessingService];
|
||||
|
||||
@NgModule({
|
||||
declarations: [...components],
|
||||
providers: [...services],
|
||||
declarations: [...dialogs],
|
||||
imports: [
|
||||
CommonModule,
|
||||
SharedModule,
|
||||
|
||||
@ -182,7 +182,7 @@ export class DossierOverviewBulkActionsComponent implements OnChanges {
|
||||
|
||||
this.#canToggleAnalysis = this._permissionsService.canToggleAnalysis(this.selectedFiles);
|
||||
|
||||
this.#canOcr = this.selectedFiles.reduce((acc, file) => acc && file.canBeOCRed, true);
|
||||
this.#canOcr = this._permissionsService.canOcrFile(this.selectedFiles);
|
||||
|
||||
this.#canSetToUnderReview = this._permissionsService.canSetUnderReview(this.selectedFiles) && !isWorkflow;
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ import { DossierTemplatesService } from '@services/entity-services/dossier-templ
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { firstValueFrom, Observable } from 'rxjs';
|
||||
import { map, switchMap } from 'rxjs/operators';
|
||||
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
|
||||
import { DossierStatsService } from '../../../../../../services/dossiers/dossier-stats.service';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
|
||||
@Component({
|
||||
@ -43,7 +43,7 @@ export class DossierDetailsStatsComponent implements OnInit {
|
||||
openEditDossierDialog(section: string): void {
|
||||
const data = { dossierId: this.dossier.dossierId, section };
|
||||
this._dialogService.openDialog('editDossier', null, data, async () => {
|
||||
await firstValueFrom(this._filesService.loadAll(this.dossier.dossierId));
|
||||
await firstValueFrom(this._filesService.loadAll(this.dossier.dossierId, this.dossier.routerPath));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -3,17 +3,17 @@ import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/si
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { FilterService, ProgressBarConfigModel, shareLast, Toaster } from '@iqser/common-ui';
|
||||
import { workflowFileStatusTranslations } from '../../../../translations/file-status-translations';
|
||||
import { workflowFileStatusTranslations } from '../../../../../../translations/file-status-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { Dossier, DossierAttributeWithValue, DossierStats, IDossierRequest, StatusSorter, User } from '@red/domain';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { firstValueFrom, Observable } from 'rxjs';
|
||||
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
|
||||
import { DossierStatsService } from '../../../../../../services/dossiers/dossier-stats.service';
|
||||
import { map, pluck, switchMap } from 'rxjs/operators';
|
||||
import { DossiersDialogService } from '../../../../services/dossiers-dialog.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { DOSSIER_ID } from '@utils/constants';
|
||||
import { DossiersService } from '../../../../../../services/dossiers/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-dossier-details',
|
||||
@ -37,19 +37,19 @@ export class DossierDetailsComponent {
|
||||
statusConfig$: Observable<ProgressBarConfigModel[]>;
|
||||
|
||||
constructor(
|
||||
readonly dossiersService: DossiersService,
|
||||
readonly translateChartService: TranslateChartService,
|
||||
readonly filterService: FilterService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _changeDetectorRef: ChangeDetectorRef,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _filesService: FilesService,
|
||||
private readonly _dossierStatsService: DossierStatsService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
activatedRoute: ActivatedRoute,
|
||||
private readonly _activatedRoute: ActivatedRoute,
|
||||
) {
|
||||
this.dossierId = activatedRoute.snapshot.paramMap.get(DOSSIER_ID);
|
||||
this.dossier$ = this.dossiersService.getEntityChanged$(this.dossierId).pipe(shareLast());
|
||||
this.dossierId = _activatedRoute.snapshot.paramMap.get(DOSSIER_ID);
|
||||
this.dossier$ = this._dossiersService.getEntityChanged$(this.dossierId).pipe(shareLast());
|
||||
this.dossierStats$ = this.dossier$.pipe(
|
||||
pluck('dossierId'),
|
||||
switchMap(dossierId => this._dossierStatsService.watch$(dossierId)),
|
||||
@ -65,7 +65,7 @@ export class DossierDetailsComponent {
|
||||
async assignOwner(user: User | string, dossier: Dossier) {
|
||||
const owner = typeof user === 'string' ? this._userService.find(user) : user;
|
||||
const dossierRequest: IDossierRequest = { ...dossier, ownerId: owner.id };
|
||||
await firstValueFrom(this.dossiersService.createOrUpdate(dossierRequest));
|
||||
await firstValueFrom(this._dossiersService.createOrUpdate(dossierRequest));
|
||||
|
||||
const ownerName = this._userService.getNameForId(owner.id);
|
||||
const dossierName = dossier.dossierName;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<iqser-page-header
|
||||
(closeAction)="routerHistoryService.navigateToLastDossiersScreen()"
|
||||
(closeAction)="router.navigate(['/main', dossiersService.routerPath])"
|
||||
[actionConfigs]="actionConfigs"
|
||||
[helpModeKey]="'document'"
|
||||
[showCloseButton]="true"
|
||||
@ -8,17 +8,18 @@
|
||||
<redaction-file-download-btn
|
||||
[disabled]="listingService.areSomeSelected$ | async"
|
||||
[files]="entitiesService.all$ | async"
|
||||
tooltipPosition="below"
|
||||
iqserHelpMode="edit_dossier_in_dossier"
|
||||
tooltipPosition="below"
|
||||
></redaction-file-download-btn>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="downloadDossierAsCSV()"
|
||||
*ngIf="permissionsService.canDownloadCsvReport(dossier)"
|
||||
[disabled]="listingService.areSomeSelected$ | async"
|
||||
[tooltip]="'dossier-overview.header-actions.download-csv' | translate"
|
||||
icon="iqser:csv"
|
||||
tooltipPosition="below"
|
||||
iqserHelpMode="edit_dossier_in_dossier"
|
||||
tooltipPosition="below"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
@ -34,12 +35,13 @@
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="upload.emit()"
|
||||
*ngIf="permissionsService.canUploadFiles(dossier)"
|
||||
[tooltip]="'dossier-overview.header-actions.upload-document' | translate"
|
||||
[type]="circleButtonTypes.primary"
|
||||
class="ml-14"
|
||||
icon="iqser:upload"
|
||||
tooltipPosition="below"
|
||||
iqserHelpMode="edit_dossier_in_dossier"
|
||||
tooltipPosition="below"
|
||||
></iqser-circle-button>
|
||||
</iqser-page-header>
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { RouterHistoryService } from '@services/router-history.service';
|
||||
import {
|
||||
ActionConfig,
|
||||
CircleButtonTypes,
|
||||
@ -21,14 +20,16 @@ import { UserService } from '@services/user.service';
|
||||
import { ConfigService } from '../../config.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { PrimaryFileAttributeService } from '../../../../../../services/primary-file-attribute.service';
|
||||
import { Router } from '@angular/router';
|
||||
import { DossiersService } from '../../../../../../services/dossiers/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-screen-header',
|
||||
templateUrl: './screen-header.component.html',
|
||||
styleUrls: ['./screen-header.component.scss'],
|
||||
selector: 'redaction-dossier-overview-screen-header',
|
||||
templateUrl: './dossier-overview-screen-header.component.html',
|
||||
styleUrls: ['./dossier-overview-screen-header.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class ScreenHeaderComponent implements OnInit {
|
||||
export class DossierOverviewScreenHeaderComponent implements OnInit {
|
||||
@Input() @Required() dossier: Dossier;
|
||||
@Output() @Required() readonly upload = new EventEmitter<void>();
|
||||
readonly circleButtonTypes = CircleButtonTypes;
|
||||
@ -37,12 +38,13 @@ export class ScreenHeaderComponent implements OnInit {
|
||||
constructor(
|
||||
private readonly _toaster: Toaster,
|
||||
readonly configService: ConfigService,
|
||||
readonly router: Router,
|
||||
readonly dossiersService: DossiersService,
|
||||
private readonly _userService: UserService,
|
||||
readonly listingService: ListingService<File>,
|
||||
readonly sortingService: SortingService<File>,
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly entitiesService: EntitiesService<File>,
|
||||
readonly routerHistoryService: RouterHistoryService,
|
||||
private readonly _reanalysisService: ReanalysisService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _primaryFileAttributeService: PrimaryFileAttributeService,
|
||||
@ -55,7 +57,7 @@ export class ScreenHeaderComponent implements OnInit {
|
||||
async reanalyseDossier() {
|
||||
this._loadingService.start();
|
||||
try {
|
||||
await firstValueFrom(this._reanalysisService.reanalyzeDossier(this.dossier.dossierId, true));
|
||||
await firstValueFrom(this._reanalysisService.reanalyzeDossier(this.dossier, true));
|
||||
this._toaster.success(_('dossier-overview.reanalyse-dossier.success'));
|
||||
} catch (e) {
|
||||
this._toaster.error(_('dossier-overview.reanalyse-dossier.error'));
|
||||
@ -1,8 +1,8 @@
|
||||
import { ChangeDetectionStrategy, Component, Input } from '@angular/core';
|
||||
import { File } from '@red/domain';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
import { DossiersService } from '../../../../../../../services/dossiers/dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-file-workload',
|
||||
@ -44,6 +44,7 @@ export class FileWorkloadComponent {
|
||||
}
|
||||
|
||||
private _getDictionaryColor(type: string) {
|
||||
return this._dictionariesMapService.getDictionaryColor(type, this._dossiersService.find(this.file.dossierId).dossierTemplateId);
|
||||
const dossierTemplateId = this._dossiersService.find(this.file.dossierId).dossierTemplateId;
|
||||
return this._dictionariesMapService.getDictionaryColor(type, dossierTemplateId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,7 +12,7 @@ import {
|
||||
WorkflowConfig,
|
||||
} from '@iqser/common-ui';
|
||||
import { File, IFileAttributeConfig, StatusSorter, WorkflowFileStatus, WorkflowFileStatuses } from '@red/domain';
|
||||
import { workflowFileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import { workflowFileStatusTranslations } from '../../../../translations/file-status-translations';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
@ -164,7 +164,7 @@ export class ConfigService {
|
||||
checkedRequiredFilters: () => NestedFilter[],
|
||||
checkedNotRequiredFilters: () => NestedFilter[],
|
||||
) {
|
||||
const allDistinctWorkflowFileStatuses = new Set<string>();
|
||||
const allDistinctWorkflowFileStatuses = new Set<WorkflowFileStatus>();
|
||||
const allDistinctPeople = new Set<string>();
|
||||
const allDistinctAddedDates = new Set<string>();
|
||||
const allDistinctNeedsWork = new Set<string>();
|
||||
@ -328,7 +328,9 @@ export class ConfigService {
|
||||
}
|
||||
|
||||
_recentlyModifiedChecker = (file: File) =>
|
||||
moment(file.lastUpdated).add(this._appConfigService.values.RECENT_PERIOD_IN_HOURS, 'hours').isAfter(moment());
|
||||
moment(file.lastUpdated)
|
||||
.add(this._appConfigService.values.RECENT_PERIOD_IN_HOURS as number, 'hours')
|
||||
.isAfter(moment());
|
||||
|
||||
_assignedToMeChecker = (file: File) => file.assignee === this._userService.currentUser.id;
|
||||
|
||||
|
||||
@ -9,15 +9,13 @@ import { DossierOverviewBulkActionsComponent } from './components/bulk-actions/d
|
||||
import { DossierDetailsComponent } from './components/dossier-details/dossier-details.component';
|
||||
import { DossierDetailsStatsComponent } from './components/dossier-details-stats/dossier-details-stats.component';
|
||||
import { TableItemComponent } from './components/table-item/table-item.component';
|
||||
import { ConfigService } from './config.service';
|
||||
import { SharedDossiersModule } from '../../shared/shared-dossiers.module';
|
||||
import { FileWorkloadComponent } from './components/table-item/file-workload/file-workload.component';
|
||||
import { FileStatsComponent } from './components/file-stats/file-stats.component';
|
||||
import { WorkflowItemComponent } from './components/workflow-item/workflow-item.component';
|
||||
import { ScreenHeaderComponent } from './components/screen-header/screen-header.component';
|
||||
import { DossierOverviewScreenHeaderComponent } from './components/screen-header/dossier-overview-screen-header.component';
|
||||
import { ViewModeSelectionComponent } from './components/view-mode-selection/view-mode-selection.component';
|
||||
import { FileNameColumnComponent } from './components/table-item/file-name-column/file-name-column.component';
|
||||
import { BulkActionsService } from './services/bulk-actions.service';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
@ -40,11 +38,10 @@ const routes: Routes = [
|
||||
TableItemComponent,
|
||||
FileStatsComponent,
|
||||
WorkflowItemComponent,
|
||||
ScreenHeaderComponent,
|
||||
DossierOverviewScreenHeaderComponent,
|
||||
ViewModeSelectionComponent,
|
||||
FileNameColumnComponent,
|
||||
],
|
||||
providers: [ConfigService, BulkActionsService],
|
||||
imports: [RouterModule.forChild(routes), CommonModule, SharedModule, SharedDossiersModule, IqserIconsModule, TranslateModule],
|
||||
})
|
||||
export class DossierOverviewModule {}
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
<ng-container *ngIf="dossier$ | async as dossier">
|
||||
<section>
|
||||
<redaction-screen-header (upload)="fileInput.click()" [dossier]="dossier"></redaction-screen-header>
|
||||
<redaction-dossier-overview-screen-header
|
||||
(upload)="fileInput.click()"
|
||||
[dossier]="dossier"
|
||||
></redaction-dossier-overview-screen-header>
|
||||
|
||||
<div class="overlay-shadow"></div>
|
||||
|
||||
@ -18,7 +21,7 @@
|
||||
[noDataText]="'dossier-overview.no-data.title' | translate"
|
||||
[noMatchText]="'dossier-overview.no-match.title' | translate"
|
||||
[selectionEnabled]="true"
|
||||
[showNoDataButton]="true"
|
||||
[showNoDataButton]="permissionsService.canUploadFiles(dossier)"
|
||||
[tableColumnConfigs]="tableColumnConfigs"
|
||||
[tableItemClasses]="{ disabled: disabledFn, 'last-opened': lastOpenedFn }"
|
||||
helpModeKey="document-list"
|
||||
|
||||
@ -38,17 +38,25 @@ import { PermissionsService } from '@services/permissions.service';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { FileAttributesService } from '@services/entity-services/file-attributes.service';
|
||||
import { ConfigService } from '../config.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { DOSSIER_ID } from '@utils/constants';
|
||||
import { BulkActionsService } from '../services/bulk-actions.service';
|
||||
import { DossiersService } from '../../../../../services/dossiers/dossiers.service';
|
||||
import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider';
|
||||
|
||||
@Component({
|
||||
templateUrl: './dossier-overview-screen.component.html',
|
||||
styleUrls: ['./dossier-overview-screen.component.scss'],
|
||||
providers: [...DefaultListingServices, { provide: ListingComponent, useExisting: forwardRef(() => DossierOverviewScreenComponent) }],
|
||||
providers: [
|
||||
...DefaultListingServices,
|
||||
ConfigService,
|
||||
BulkActionsService,
|
||||
{ provide: ListingComponent, useExisting: forwardRef(() => DossierOverviewScreenComponent) },
|
||||
dossiersServiceProvider,
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
})
|
||||
export class DossierOverviewScreenComponent extends ListingComponent<File> implements OnInit, OnDestroy, OnAttach {
|
||||
@ -75,8 +83,8 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
constructor(
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _router: Router,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dossierTemplatesService: DossierTemplatesService,
|
||||
private readonly _fileUploadService: FileUploadService,
|
||||
private readonly _filesService: FilesService,
|
||||
@ -87,12 +95,12 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
private readonly _fileMapService: FilesMapService,
|
||||
private readonly _errorService: ErrorService,
|
||||
private readonly _route: ActivatedRoute,
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly configService: ConfigService,
|
||||
readonly activatedRoute: ActivatedRoute,
|
||||
) {
|
||||
super(_injector);
|
||||
this.dossierId = activatedRoute.snapshot.paramMap.get(DOSSIER_ID);
|
||||
this.dossierId = _route.snapshot.paramMap.get(DOSSIER_ID);
|
||||
this.dossier$ = this._dossiersService
|
||||
.getEntityChanged$(this.dossierId)
|
||||
.pipe(tap(dossier => (this.dossierTemplateId = dossier.dossierTemplateId)));
|
||||
@ -125,7 +133,9 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
this._fileDropOverlayService.initFileDropHandling(this.dossierId);
|
||||
if (this.currentDossier.isActive) {
|
||||
this._fileDropOverlayService.initFileDropHandling(this.dossierId);
|
||||
}
|
||||
|
||||
this.addSubscription = this.configService.listingMode$.subscribe(() => {
|
||||
this._computeAllFilters();
|
||||
@ -134,7 +144,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
|
||||
this.addSubscription = this._dossiersService.dossierFileChanges$
|
||||
.pipe(
|
||||
filter(dossierId => dossierId === this.dossierId),
|
||||
switchMap(dossierId => this._filesService.loadAll(dossierId)),
|
||||
switchMap(dossierId => this._filesService.loadAll(dossierId, this._dossiersService.routerPath)),
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
import { Dossier, File } from '@red/domain';
|
||||
import { DossiersDialogService } from '../../../services/dossiers-dialog.service';
|
||||
import { ConfirmationDialogInput, LoadingService } from '@iqser/common-ui';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '../../../../../services/dossiers/active-dossiers.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { FileAssignService } from '../../../shared/services/file-assign.service';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
@ -15,7 +15,7 @@ export class BulkActionsService {
|
||||
constructor(
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _filesService: FilesService,
|
||||
private readonly _fileAssignService: FileAssignService,
|
||||
private readonly _reanalysisService: ReanalysisService,
|
||||
@ -29,13 +29,7 @@ export class BulkActionsService {
|
||||
this._assignFiles(files, 'approver', true);
|
||||
} else {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(
|
||||
this._filesService.setUnderApprovalFor(
|
||||
files.map(f => f.id),
|
||||
dossier.id,
|
||||
dossier.approverIds[0],
|
||||
),
|
||||
);
|
||||
await firstValueFrom(this._filesService.setUnderApprovalFor(files, dossier.id, dossier.approverIds[0]));
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
@ -46,12 +40,7 @@ export class BulkActionsService {
|
||||
|
||||
async ocr(files: File[]) {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(
|
||||
this._reanalysisService.ocrFiles(
|
||||
files.map(f => f.fileId),
|
||||
files[0].dossierId,
|
||||
),
|
||||
);
|
||||
await firstValueFrom(this._reanalysisService.ocrFiles(files, files[0].dossierId));
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
@ -65,12 +54,7 @@ export class BulkActionsService {
|
||||
}),
|
||||
async () => {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(
|
||||
this._fileManagementService.delete(
|
||||
files.map(item => item.fileId),
|
||||
files[0].dossierId,
|
||||
),
|
||||
);
|
||||
await firstValueFrom(this._fileManagementService.delete(files, files[0].dossierId));
|
||||
this._loadingService.stop();
|
||||
},
|
||||
);
|
||||
@ -78,9 +62,8 @@ export class BulkActionsService {
|
||||
|
||||
async reanalyse(files: File[]) {
|
||||
this._loadingService.start();
|
||||
const fileIds = files.map(file => file.fileId);
|
||||
await firstValueFrom(
|
||||
this._reanalysisService.reanalyzeFilesForDossier(fileIds, files[0].dossierId, { force: true, triggeredByUser: true }),
|
||||
this._reanalysisService.reanalyzeFilesForDossier(files, files[0].dossierId, { force: true, triggeredByUser: true }),
|
||||
);
|
||||
this._loadingService.stop();
|
||||
}
|
||||
@ -93,24 +76,13 @@ export class BulkActionsService {
|
||||
|
||||
async toggleAnalysis(files: File[], excluded: boolean) {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(
|
||||
this._reanalysisService.toggleAnalysis(
|
||||
files[0].dossierId,
|
||||
files.map(f => f.id),
|
||||
excluded,
|
||||
),
|
||||
);
|
||||
await firstValueFrom(this._reanalysisService.toggleAnalysis(files[0].dossierId, files, excluded));
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
async backToUnderReview(files: File[]): Promise<void> {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(
|
||||
this._filesService.setUnderReviewFor(
|
||||
files.map(f => f.id),
|
||||
files[0].dossierId,
|
||||
),
|
||||
);
|
||||
await firstValueFrom(this._filesService.setUnderReviewFor(files, files[0].dossierId));
|
||||
this._loadingService.stop();
|
||||
}
|
||||
|
||||
@ -135,23 +107,13 @@ export class BulkActionsService {
|
||||
}),
|
||||
async () => {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(
|
||||
this._filesService.setApprovedFor(
|
||||
files.map(f => f.id),
|
||||
files[0].dossierId,
|
||||
),
|
||||
);
|
||||
await firstValueFrom(this._filesService.setApprovedFor(files, files[0].dossierId));
|
||||
this._loadingService.stop();
|
||||
},
|
||||
);
|
||||
} else {
|
||||
this._loadingService.start();
|
||||
await firstValueFrom(
|
||||
this._filesService.setApprovedFor(
|
||||
files.map(f => f.id),
|
||||
files[0].dossierId,
|
||||
),
|
||||
);
|
||||
await firstValueFrom(this._filesService.setApprovedFor(files, files[0].dossierId));
|
||||
this._loadingService.stop();
|
||||
}
|
||||
}
|
||||
@ -161,7 +123,7 @@ export class BulkActionsService {
|
||||
}
|
||||
|
||||
private _getDossier(files: File[]): Dossier {
|
||||
return this._dossiersService.find(files[0].dossierId);
|
||||
return this._activeDossiersService.find(files[0].dossierId);
|
||||
}
|
||||
|
||||
private _assignFiles(files: File[], mode: 'reviewer' | 'approver', ignoreChanged = false, withUnassignedOption = false) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
|
||||
import { DossierStats, StatusSorter } from '../../../../../../../../../../libs/red-domain/src';
|
||||
import { DossierStats, StatusSorter } from '@red/domain';
|
||||
import { List, StatusBarConfig } from '@iqser/common-ui';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -2,15 +2,15 @@
|
||||
<iqser-circle-button
|
||||
(action)="openEditDossierDialog($event, dossier.dossierId)"
|
||||
*ngIf="currentUser.isUser"
|
||||
[icon]="currentUser.isManager ? 'iqser:edit' : 'red:info'"
|
||||
[scrollableParentView]="scrollableParentView"
|
||||
[tooltip]="(currentUser.isManager ? 'dossier-listing.edit.action' : 'dossier-listing.dossier-info.action') | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
[icon]="currentUser.isManager ? 'iqser:edit' : 'red:info'"
|
||||
iqserHelpMode="edit_dossier"
|
||||
[scrollableParentView]="scrollableParentView"
|
||||
></iqser-circle-button>
|
||||
|
||||
<iqser-circle-button
|
||||
(action)="reanalyseDossier($event, dossier.dossierId)"
|
||||
(action)="reanalyseDossier($event, dossier)"
|
||||
*ngIf="displayReanalyseBtn"
|
||||
[tooltip]="'dossier-listing.reanalyse.action' | translate"
|
||||
[type]="circleButtonTypes.dark"
|
||||
@ -19,8 +19,8 @@
|
||||
|
||||
<redaction-file-download-btn
|
||||
[files]="files"
|
||||
[scrollableParentView]="scrollableParentView"
|
||||
[type]="circleButtonTypes.dark"
|
||||
iqserHelpMode="download_dossier"
|
||||
[scrollableParentView]="scrollableParentView"
|
||||
></redaction-file-download-btn>
|
||||
</div>
|
||||
|
||||
@ -8,7 +8,7 @@ import { LongPressEvent } from '@shared/directives/long-press.directive';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { ReanalysisService } from '@services/reanalysis.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '../../../../../../services/dossiers/active-dossiers.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
@Component({
|
||||
@ -32,13 +32,17 @@ export class DossiersListingActionsComponent implements OnChanges {
|
||||
constructor(
|
||||
private readonly _reanalysisService: ReanalysisService,
|
||||
private readonly _userService: UserService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
readonly permissionsService: PermissionsService,
|
||||
readonly filesMapService: FilesMapService,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _userPreferenceService: UserPreferenceService,
|
||||
) {}
|
||||
|
||||
get scrollableParentView(): ScrollableParentView {
|
||||
return ScrollableParentViews.VIRTUAL_SCROLL;
|
||||
}
|
||||
|
||||
ngOnChanges() {
|
||||
this.files = this.filesMapService.get(this.dossier.dossierId);
|
||||
this.displayReanalyseBtn = this.permissionsService.displayReanalyseBtn(this.dossier) && this.analysisForced;
|
||||
@ -52,12 +56,8 @@ export class DossiersListingActionsComponent implements OnChanges {
|
||||
this._dialogService.openDialog('editDossier', $event, { dossierId });
|
||||
}
|
||||
|
||||
async reanalyseDossier($event: MouseEvent, id: string): Promise<void> {
|
||||
async reanalyseDossier($event: MouseEvent, dossier: Dossier): Promise<void> {
|
||||
$event.stopPropagation();
|
||||
await firstValueFrom(this._reanalysisService.reanalyzeDossier(id));
|
||||
}
|
||||
|
||||
get scrollableParentView(): ScrollableParentView {
|
||||
return ScrollableParentViews.VIRTUAL_SCROLL;
|
||||
await firstValueFrom(this._reanalysisService.reanalyzeDossier(dossier));
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,10 +4,10 @@
|
||||
[config]="config"
|
||||
[radius]="80"
|
||||
[strokeWidth]="15"
|
||||
[subtitle]="'dossier-listing.stats.charts.dossiers' | translate: { count: dossiersService.all.length }"
|
||||
[subtitle]="'dossier-listing.stats.charts.dossiers' | translate: { count: activeDossiersService.all.length }"
|
||||
></redaction-simple-doughnut-chart>
|
||||
|
||||
<div *ngIf="dossiersService.generalStats$ | async as stats" class="dossier-stats-container">
|
||||
<div *ngIf="activeDossiersService.generalStats$ | async as stats" class="dossier-stats-container">
|
||||
<div class="dossier-stats-item">
|
||||
<mat-icon svgIcon="red:needs-work"></mat-icon>
|
||||
<div>
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
import { ChangeDetectionStrategy, Component } from '@angular/core';
|
||||
import { DoughnutChartConfig } from '@shared/components/simple-doughnut-chart/simple-doughnut-chart.component';
|
||||
import { FilterService, mapEach } from '@iqser/common-ui';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '../../../../../../services/dossiers/active-dossiers.service';
|
||||
import { combineLatest, Observable } from 'rxjs';
|
||||
import { DossierStats, FileCountPerWorkflowStatus, StatusSorter } from '@red/domain';
|
||||
import { workflowFileStatusTranslations } from '../../../../translations/file-status-translations';
|
||||
import { workflowFileStatusTranslations } from '../../../../../../translations/file-status-translations';
|
||||
import { TranslateChartService } from '@services/translate-chart.service';
|
||||
import { filter, map, switchMap } from 'rxjs/operators';
|
||||
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
|
||||
import { DossierStateService } from '../../../../../../services/entity-services/dossier-state.service';
|
||||
import { DossierStatsService } from '../../../../../../services/dossiers/dossier-stats.service';
|
||||
import { DossierStateService } from '@services/entity-services/dossier-state.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
@Component({
|
||||
@ -23,25 +23,25 @@ export class DossiersListingDetailsComponent {
|
||||
|
||||
constructor(
|
||||
readonly filterService: FilterService,
|
||||
readonly dossiersService: DossiersService,
|
||||
readonly activeDossiersService: ActiveDossiersService,
|
||||
private readonly _dossierStatsMap: DossierStatsService,
|
||||
private readonly _translateChartService: TranslateChartService,
|
||||
private readonly _dossierStateService: DossierStateService,
|
||||
private readonly _translateService: TranslateService,
|
||||
) {
|
||||
this.documentsChartData$ = this.dossiersService.all$.pipe(
|
||||
this.documentsChartData$ = this.activeDossiersService.all$.pipe(
|
||||
mapEach(dossier => _dossierStatsMap.watch$(dossier.dossierId)),
|
||||
switchMap(stats$ => combineLatest(stats$)),
|
||||
filter(stats => !stats.some(s => s === undefined)),
|
||||
map(stats => this._toChartData(stats)),
|
||||
);
|
||||
|
||||
this.dossiersChartData$ = this.dossiersService.all$.pipe(map(() => this._toDossierChartData()));
|
||||
this.dossiersChartData$ = this.activeDossiersService.all$.pipe(map(() => this._toDossierChartData()));
|
||||
}
|
||||
|
||||
private _toDossierChartData(): DoughnutChartConfig[] {
|
||||
this._dossierStateService.all.forEach(
|
||||
state => (state.dossierCount = this.dossiersService.getCountWithState(state.dossierStatusId)),
|
||||
state => (state.dossierCount = this.activeDossiersService.getCountWithState(state.dossierStatusId)),
|
||||
);
|
||||
const configArray: DoughnutChartConfig[] = [
|
||||
...this._dossierStateService.all
|
||||
@ -54,7 +54,7 @@ export class DossiersListingDetailsComponent {
|
||||
.values(),
|
||||
];
|
||||
|
||||
const notAssignedLength = this.dossiersService.all.length - configArray.map(v => v.value).reduce((acc, val) => acc + val, 0);
|
||||
const notAssignedLength = this.activeDossiersService.all.length - configArray.map(v => v.value).reduce((acc, val) => acc + val, 0);
|
||||
configArray.push({
|
||||
value: notAssignedLength,
|
||||
label: this._translateService.instant('edit-dossier-dialog.general-info.form.dossier-status.placeholder'),
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
<ng-container *ngIf="dossier.dossierStatusId && currentState">
|
||||
<div class="flex-align-items-center dossier-status-container">
|
||||
<div class="dossier-status-text">{{ currentState.name }}</div>
|
||||
<redaction-small-chip [color]="currentState.color"></redaction-small-chip>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="!dossier.dossierStatusId || !currentState">
|
||||
<div class="flex-align-items-center dossier-status-container">
|
||||
<div class="dossier-status-text">{{ 'edit-dossier-dialog.general-info.form.dossier-status.placeholder' | translate }}</div>
|
||||
<redaction-small-chip [color]="'#E2E4E9'"></redaction-small-chip>
|
||||
</div>
|
||||
</ng-container>
|
||||
@ -21,7 +21,7 @@
|
||||
</div>
|
||||
|
||||
<div class="cell">
|
||||
<redaction-dossiers-listing-status [dossier]="dossier"></redaction-dossiers-listing-status>
|
||||
<redaction-dossier-status [dossier]="dossier"></redaction-dossier-status>
|
||||
|
||||
<redaction-dossiers-listing-actions [dossier]="dossier" [stats]="stats"></redaction-dossiers-listing-actions>
|
||||
</div>
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { ChangeDetectionStrategy, Component, Input, OnChanges } from '@angular/core';
|
||||
import { Dossier, DossierStats } from '@red/domain';
|
||||
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
|
||||
import { DossierStatsService } from '../../../../../../services/dossiers/dossier-stats.service';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
import { switchMap } from 'rxjs/operators';
|
||||
|
||||
|
||||
@ -5,12 +5,12 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { workflowFileStatusTranslations } from '../../translations/file-status-translations';
|
||||
import { workflowFileStatusTranslations } from '../../../../translations/file-status-translations';
|
||||
import { dossierMemberChecker, dossierStateChecker, dossierTemplateChecker, RedactionFilterSorter } from '@utils/index';
|
||||
import { workloadTranslations } from '../../translations/workload-translations';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DossierStatsService } from '@services/entity-services/dossier-stats.service';
|
||||
import { DossierStateService } from '../../../../services/entity-services/dossier-state.service';
|
||||
import { DossierStatsService } from '../../../../services/dossiers/dossier-stats.service';
|
||||
import { DossierStateService } from '@services/entity-services/dossier-state.service';
|
||||
|
||||
@Injectable()
|
||||
export class ConfigService {
|
||||
|
||||
@ -7,12 +7,10 @@ import { RouterModule, Routes } from '@angular/router';
|
||||
import { DossiersListingActionsComponent } from './components/dossiers-listing-actions/dossiers-listing-actions.component';
|
||||
import { SharedModule } from '@shared/shared.module';
|
||||
import { DossiersListingDetailsComponent } from './components/dossiers-listing-details/dossiers-listing-details.component';
|
||||
import { DossiersListingDossierNameComponent } from './components/dossiers-listing-dossier-name/dossiers-listing-dossier-name.component';
|
||||
import { ConfigService } from './config.service';
|
||||
import { TableItemComponent } from './components/table-item/table-item.component';
|
||||
import { SharedDossiersModule } from '../../shared/shared-dossiers.module';
|
||||
import { DossierWorkloadColumnComponent } from './components/dossier-workload-column/dossier-workload-column.component';
|
||||
import { DossiersListingStatusComponent } from './components/dossiers-listing-status/dossiers-listing-status.component';
|
||||
import { DossierDocumentsStatusComponent } from './components/dossier-documents-status/dossier-documents-status.component';
|
||||
|
||||
const routes: Routes = [
|
||||
@ -29,10 +27,8 @@ const routes: Routes = [
|
||||
DossiersListingScreenComponent,
|
||||
DossiersListingActionsComponent,
|
||||
DossiersListingDetailsComponent,
|
||||
DossiersListingDossierNameComponent,
|
||||
DossierWorkloadColumnComponent,
|
||||
TableItemComponent,
|
||||
DossiersListingStatusComponent,
|
||||
DossierDocumentsStatusComponent,
|
||||
],
|
||||
providers: [ConfigService],
|
||||
|
||||
@ -8,7 +8,7 @@ import { DossiersDialogService } from '../../../services/dossiers-dialog.service
|
||||
import { DefaultListingServicesTmp, EntitiesService, ListingComponent, OnAttach, TableComponent } from '@iqser/common-ui';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { ConfigService } from '../config.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '../../../../../services/dossiers/active-dossiers.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { tap } from 'rxjs/operators';
|
||||
@ -18,7 +18,7 @@ import { tap } from 'rxjs/operators';
|
||||
styleUrls: ['./dossiers-listing-screen.component.scss'],
|
||||
providers: [
|
||||
...DefaultListingServicesTmp,
|
||||
{ provide: EntitiesService, useExisting: DossiersService },
|
||||
{ provide: EntitiesService, useExisting: ActiveDossiersService },
|
||||
{ provide: ListingComponent, useExisting: forwardRef(() => DossiersListingScreenComponent) },
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
@ -40,7 +40,7 @@ export class DossiersListingScreenComponent extends ListingComponent<Dossier> im
|
||||
protected readonly _injector: Injector,
|
||||
private readonly _userService: UserService,
|
||||
readonly permissionsService: PermissionsService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _translateChartService: TranslateChartService,
|
||||
private readonly _configService: ConfigService,
|
||||
@ -55,7 +55,7 @@ export class DossiersListingScreenComponent extends ListingComponent<Dossier> im
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.addSubscription = this._dossiersService.all$.pipe(tap(() => this._computeAllFilters())).subscribe();
|
||||
this.addSubscription = this._activeDossiersService.all$.pipe(tap(() => this._computeAllFilters())).subscribe();
|
||||
}
|
||||
|
||||
ngOnAttach(): void {
|
||||
|
||||
@ -72,6 +72,10 @@ export class AnnotationActionsComponent implements OnChanges {
|
||||
return this.annotations?.length === 1 && this.annotations?.[0].resizing;
|
||||
}
|
||||
|
||||
get scrollableParentView(): ScrollableParentView {
|
||||
return ScrollableParentViews.ANNOTATIONS_LIST;
|
||||
}
|
||||
|
||||
async ngOnChanges(): Promise<void> {
|
||||
await this._setPermissions();
|
||||
}
|
||||
@ -115,10 +119,6 @@ export class AnnotationActionsComponent implements OnChanges {
|
||||
this.annotationActionsService.cancelResize($event, this.viewer, this.annotations[0], this.annotationsChanged);
|
||||
}
|
||||
|
||||
get scrollableParentView(): ScrollableParentView {
|
||||
return ScrollableParentViews.ANNOTATIONS_LIST;
|
||||
}
|
||||
|
||||
private async _setPermissions() {
|
||||
const dossier = await this._state.dossier;
|
||||
this.annotationPermissions = AnnotationPermissions.forUser(
|
||||
|
||||
@ -3,7 +3,7 @@ import { DossiersDialogService } from '../../../../services/dossiers-dialog.serv
|
||||
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
|
||||
import { DocumentInfoService } from '../../services/document-info.service';
|
||||
import { combineLatest, Observable, switchMap } from 'rxjs';
|
||||
import { PermissionsService } from '../../../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FilePreviewStateService } from '../../services/file-preview-state.service';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { File } from '@red/domain';
|
||||
|
||||
@ -40,7 +40,7 @@
|
||||
|
||||
<div class="flex-center">
|
||||
<mat-icon class="primary-white" svgIcon="red:read-only"></mat-icon>
|
||||
<span class="read-only-text" translate="readonly"></span>
|
||||
<span [translate]="(state.dossier$ | async).isActive ? 'readonly' : 'readonly-archived'" class="read-only-text"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@ -67,7 +67,7 @@ export class PageExclusionComponent {
|
||||
endPage,
|
||||
};
|
||||
});
|
||||
const excludePages$ = this._reanalysisService.excludePages({ pageRanges }, this._state.dossierId, this._state.fileId);
|
||||
const excludePages$ = this._reanalysisService.excludePages({ pageRanges }, file.dossierId, file);
|
||||
await firstValueFrom(excludePages$);
|
||||
this._inputComponent.reset();
|
||||
} catch (e) {
|
||||
@ -78,12 +78,13 @@ export class PageExclusionComponent {
|
||||
|
||||
async includePagesRange(range: IPageRange): Promise<void> {
|
||||
this._loadingService.start();
|
||||
const file = await this._state.file;
|
||||
const includePages$ = this._reanalysisService.includePages(
|
||||
{
|
||||
pageRanges: [range],
|
||||
},
|
||||
this._state.dossierId,
|
||||
this._state.fileId,
|
||||
file.dossierId,
|
||||
file,
|
||||
);
|
||||
await firstValueFrom(includePages$);
|
||||
this._inputComponent.reset();
|
||||
|
||||
@ -3,7 +3,7 @@ import { Dossier, File, StatusBarConfigs, User } from '@red/domain';
|
||||
import { List, LoadingService, Toaster } from '@iqser/common-ui';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { FileAssignService } from '../../../../shared/services/file-assign.service';
|
||||
import { workflowFileStatusTranslations } from '../../../../translations/file-status-translations';
|
||||
import { workflowFileStatusTranslations } from '../../../../../../translations/file-status-translations';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { UserService } from '@services/user.service';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
@ -11,7 +11,7 @@ import { TranslateService } from '@ngx-translate/core';
|
||||
import { BehaviorSubject, combineLatest, firstValueFrom, Observable, switchMap } from 'rxjs';
|
||||
import { FilePreviewStateService } from '../../services/file-preview-state.service';
|
||||
import { distinctUntilChanged, map } from 'rxjs/operators';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '../../../../../../services/dossiers/active-dossiers.service';
|
||||
|
||||
@Component({
|
||||
selector: 'redaction-user-management',
|
||||
@ -42,9 +42,9 @@ export class UserManagementComponent {
|
||||
readonly loadingService: LoadingService,
|
||||
readonly translateService: TranslateService,
|
||||
readonly stateService: FilePreviewStateService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
) {
|
||||
this._dossier$ = this.stateService.file$.pipe(switchMap(file => this._dossiersService.getEntityChanged$(file.dossierId)));
|
||||
this._dossier$ = this.stateService.file$.pipe(switchMap(file => this._activeDossiersService.getEntityChanged$(file.dossierId)));
|
||||
this.statusBarConfig$ = this.stateService.file$.pipe(map(file => [{ length: 1, color: file.workflowStatus }]));
|
||||
this.assignTooltip$ = this.stateService.file$.pipe(
|
||||
map(file =>
|
||||
@ -96,15 +96,15 @@ export class UserManagementComponent {
|
||||
const assigneeId = typeof user === 'string' ? user : user?.id;
|
||||
const reviewerName = this.userService.getNameForId(assigneeId);
|
||||
|
||||
const { dossierId, fileId, filename } = file;
|
||||
const { dossierId, filename } = file;
|
||||
this.loadingService.start();
|
||||
|
||||
if (!assigneeId) {
|
||||
await firstValueFrom(this.filesService.setUnassigned([fileId], dossierId));
|
||||
await firstValueFrom(this.filesService.setUnassigned([file], dossierId));
|
||||
} else if (file.isNew || file.isUnderReview) {
|
||||
await firstValueFrom(this.filesService.setReviewerFor([fileId], dossierId, assigneeId));
|
||||
await firstValueFrom(this.filesService.setReviewerFor([file], dossierId, assigneeId));
|
||||
} else if (file.isUnderApproval) {
|
||||
await firstValueFrom(this.filesService.setUnderApprovalFor([fileId], dossierId, assigneeId));
|
||||
await firstValueFrom(this.filesService.setUnderApprovalFor([file], dossierId, assigneeId));
|
||||
}
|
||||
|
||||
this.loadingService.stop();
|
||||
|
||||
@ -3,7 +3,7 @@ import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { Dictionary, Dossier } from '@red/domain';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '../../../../../../services/dossiers/active-dossiers.service';
|
||||
import { BaseDialogComponent } from '@iqser/common-ui';
|
||||
import { DictionaryService } from '@shared/services/dictionary.service';
|
||||
import { ManualAnnotationService } from '../../../../services/manual-annotation.service';
|
||||
@ -33,14 +33,14 @@ export class AcceptRecommendationDialogComponent extends BaseDialogComponent imp
|
||||
private readonly _formBuilder: FormBuilder,
|
||||
private readonly _manualAnnotationService: ManualAnnotationService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _dictionaryService: DictionaryService,
|
||||
protected readonly _injector: Injector,
|
||||
protected readonly _dialogRef: MatDialogRef<AcceptRecommendationDialogComponent, AcceptRecommendationReturnType>,
|
||||
@Inject(MAT_DIALOG_DATA) readonly data: AcceptRecommendationData,
|
||||
) {
|
||||
super(_injector, _dialogRef);
|
||||
this._dossier = this._dossiersService.find(this.data.dossierId);
|
||||
this._dossier = this._activeDossiersService.find(this.data.dossierId);
|
||||
this.isDocumentAdmin = this._permissionsService.isApprover(this._dossier);
|
||||
this.form = this._getForm();
|
||||
this.initialFormValue = this.form.getRawValue();
|
||||
|
||||
@ -10,6 +10,9 @@ import { FilePreviewStateService } from './services/file-preview-state.service';
|
||||
import { PdfViewerDataService } from '../../services/pdf-viewer-data.service';
|
||||
import { AnnotationReferencesService } from './services/annotation-references.service';
|
||||
import { FilterService } from '@iqser/common-ui';
|
||||
import { ManualAnnotationService } from '../../services/manual-annotation.service';
|
||||
import { AnnotationProcessingService } from '../../services/annotation-processing.service';
|
||||
import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider';
|
||||
import { PageRotationService } from './services/page-rotation.service';
|
||||
import { PdfViewer } from './services/pdf-viewer.service';
|
||||
|
||||
@ -28,4 +31,7 @@ export const filePreviewScreenProviders = [
|
||||
AnnotationReferencesService,
|
||||
PageRotationService,
|
||||
PdfViewer,
|
||||
ManualAnnotationService,
|
||||
AnnotationProcessingService,
|
||||
dossiersServiceProvider,
|
||||
];
|
||||
|
||||
@ -34,7 +34,6 @@ import { clearStamps, stampPDFPage } from '@utils/page-stamper';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { handleFilterDelta } from '@utils/filter-utils';
|
||||
import { FilesService } from '@services/entity-services/files.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { FileManagementService } from '@services/entity-services/file-management.service';
|
||||
import { catchError, map, switchMap, tap } from 'rxjs/operators';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
@ -50,6 +49,7 @@ import { FilePreviewStateService } from './services/file-preview-state.service';
|
||||
import { FileDataModel } from '../../../../models/file/file-data.model';
|
||||
import { filePreviewScreenProviders } from './file-preview-providers';
|
||||
import { ManualAnnotationService } from '../../services/manual-annotation.service';
|
||||
import { DossiersService } from '../../../../services/dossiers/dossiers.service';
|
||||
import { PageRotationService } from './services/page-rotation.service';
|
||||
import { ComponentCanDeactivate } from '../../../../guards/can-deactivate.guard';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
@ -254,7 +254,7 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
const file = await this.stateService.file;
|
||||
if (file?.analysisRequired && !file.excludedFromAutomaticAnalysis) {
|
||||
const reanalyzeFiles = this._reanalysisService.reanalyzeFilesForDossier([this.fileId], this.dossierId, { force: true });
|
||||
const reanalyzeFiles = this._reanalysisService.reanalyzeFilesForDossier([file], this.dossierId, { force: true });
|
||||
await firstValueFrom(reanalyzeFiles);
|
||||
}
|
||||
|
||||
@ -449,7 +449,8 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
async annotationsChangedByReviewAction(annotation?: AnnotationWrapper) {
|
||||
this.multiSelectService.deactivate();
|
||||
const fileReloaded = await firstValueFrom(this._filesService.reload(this.dossierId, this.fileId));
|
||||
const file = await this.stateService.file;
|
||||
const fileReloaded = await firstValueFrom(this._filesService.reload(this.dossierId, file));
|
||||
if (!fileReloaded) {
|
||||
await this._reloadAnnotationsForPage(annotation?.pageNumber ?? this.activeViewerPage);
|
||||
}
|
||||
@ -574,7 +575,10 @@ export class FilePreviewScreenComponent extends AutoUnsubscribe implements OnIni
|
||||
|
||||
private _subscribeToFileUpdates(): void {
|
||||
this.addActiveScreenSubscription = timer(0, 5000)
|
||||
.pipe(switchMap(() => this._filesService.reload(this.dossierId, this.fileId)))
|
||||
.pipe(
|
||||
switchMap(() => this.stateService.file$),
|
||||
switchMap(file => this._filesService.reload(this.dossierId, file)),
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
this.addActiveScreenSubscription = this._dossiersService
|
||||
|
||||
@ -14,7 +14,7 @@ import { Dossier, IAddRedactionRequest, ILegalBasisChangeRequest, IRectangle, IR
|
||||
import { toPosition } from '../../../utils/pdf-calculation.utils';
|
||||
import { AnnotationDrawService } from './annotation-draw.service';
|
||||
import { translateQuads } from '@utils/pdf-coordinates';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '../../../../../services/dossiers/active-dossiers.service';
|
||||
import {
|
||||
AcceptRecommendationData,
|
||||
AcceptRecommendationDialogComponent,
|
||||
@ -38,12 +38,12 @@ export class AnnotationActionsService {
|
||||
private readonly _dialogService: DossiersDialogService,
|
||||
private readonly _dialog: MatDialog,
|
||||
private readonly _annotationDrawService: AnnotationDrawService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
private readonly _screenStateService: FilePreviewStateService,
|
||||
) {}
|
||||
|
||||
private get _dossier(): Dossier {
|
||||
return this._dossiersService.find(this._screenStateService.dossierId);
|
||||
return this._activeDossiersService.find(this._screenStateService.dossierId);
|
||||
}
|
||||
|
||||
acceptSuggestion($event: MouseEvent, annotations: AnnotationWrapper[], annotationsChanged: EventEmitter<AnnotationWrapper>) {
|
||||
|
||||
@ -3,7 +3,6 @@ import { Core, WebViewerInstance } from '@pdftron/webviewer';
|
||||
import { hexToRgb } from '@utils/functions';
|
||||
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
|
||||
import { UserPreferenceService } from '@services/user-preference.service';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { RedactionLogService } from '../../../services/redaction-log.service';
|
||||
import { environment } from '@environments/environment';
|
||||
|
||||
@ -11,6 +10,7 @@ import { IRectangle, ISectionGrid, ISectionRectangle } from '@red/domain';
|
||||
import { SkippedService } from './skipped.service';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
import { DossiersService } from '../../../../../services/dossiers/dossiers.service';
|
||||
import Annotation = Core.Annotations.Annotation;
|
||||
|
||||
@Injectable()
|
||||
|
||||
@ -1,15 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, Injector } from '@angular/core';
|
||||
import { BehaviorSubject, firstValueFrom, from, Observable, pairwise, switchMap } from 'rxjs';
|
||||
import { FileDataModel } from '@models/file/file-data.model';
|
||||
import { Dossier, File } from '@red/domain';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { FilesMapService } from '@services/entity-services/files-map.service';
|
||||
import { PermissionsService } from '../../../../../services/permissions.service';
|
||||
import { PermissionsService } from '@services/permissions.service';
|
||||
import { boolFactory } from '@iqser/common-ui';
|
||||
import { filter, startWith } from 'rxjs/operators';
|
||||
import { FileManagementService } from '@services/entity-services/file-management.service';
|
||||
import { DOSSIER_ID, FILE_ID } from '@utils/constants';
|
||||
import { DossiersService } from '../../../../../services/dossiers/dossiers.service';
|
||||
import { dossiersServiceResolver } from '@services/entity-services/dossiers.service.provider';
|
||||
import { wipeFilesCache } from '../../../../../../../../../libs/red-cache/src';
|
||||
|
||||
@Injectable()
|
||||
@ -28,19 +29,19 @@ export class FilePreviewStateService {
|
||||
readonly #fileData$ = new BehaviorSubject<FileDataModel | undefined>(undefined);
|
||||
|
||||
constructor(
|
||||
dossiersService: DossiersService,
|
||||
filesMapService: FilesMapService,
|
||||
permissionsService: PermissionsService,
|
||||
activatedRoute: ActivatedRoute,
|
||||
private readonly _fileManagementService: FileManagementService,
|
||||
private readonly _injector: Injector,
|
||||
private readonly _route: ActivatedRoute,
|
||||
private readonly _filesMapService: FilesMapService,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
) {
|
||||
this.fileId = activatedRoute.snapshot.paramMap.get(FILE_ID);
|
||||
this.dossierId = activatedRoute.snapshot.paramMap.get(DOSSIER_ID);
|
||||
this.dossierTemplateId = dossiersService.find(this.dossierId).dossierTemplateId;
|
||||
this.fileId = _route.snapshot.paramMap.get(FILE_ID);
|
||||
this.dossierId = _route.snapshot.paramMap.get(DOSSIER_ID);
|
||||
this.dossierTemplateId = this._dossiersService.find(this.dossierId).dossierTemplateId;
|
||||
|
||||
this.dossier$ = dossiersService.getEntityChanged$(this.dossierId);
|
||||
this.file$ = filesMapService.watch$(this.dossierId, this.fileId);
|
||||
[this.isReadonly$, this.isWritable$] = boolFactory(this.file$, file => !permissionsService.canPerformAnnotationActions(file));
|
||||
this.dossier$ = this._dossiersService.getEntityChanged$(this.dossierId);
|
||||
this.file$ = _filesMapService.watch$(this.dossierId, this.fileId);
|
||||
[this.isReadonly$, this.isWritable$] = boolFactory(this.file$, file => !_permissionsService.canPerformAnnotationActions(file));
|
||||
|
||||
this.fileData$ = this.#fileData$.asObservable().pipe(filter(value => !!value));
|
||||
this.blob$ = this.#blob$;
|
||||
@ -66,6 +67,10 @@ export class FilePreviewStateService {
|
||||
return firstValueFrom(this.blob$);
|
||||
}
|
||||
|
||||
private get _dossiersService(): DossiersService {
|
||||
return dossiersServiceResolver(this._injector);
|
||||
}
|
||||
|
||||
get #blob$() {
|
||||
return this.file$.pipe(
|
||||
startWith(undefined),
|
||||
|
||||
@ -17,7 +17,7 @@ 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 { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
||||
import { DossiersService } from '@services/entity-services/dossiers.service';
|
||||
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
|
||||
import { Observable } from 'rxjs';
|
||||
import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service';
|
||||
import { ManualRedactionEntryType } from '@models/file/manual-redaction-entry.wrapper';
|
||||
@ -32,7 +32,7 @@ export class ManualAnnotationService extends GenericService<IManualAddResponse>
|
||||
private readonly _dictionariesMapService: DictionariesMapService,
|
||||
private readonly _toaster: Toaster,
|
||||
private readonly _permissionsService: PermissionsService,
|
||||
private readonly _dossiersService: DossiersService,
|
||||
private readonly _activeDossiersService: ActiveDossiersService,
|
||||
protected readonly _injector: Injector,
|
||||
) {
|
||||
super(_injector, 'manualRedaction');
|
||||
@ -372,7 +372,7 @@ export class ManualAnnotationService extends GenericService<IManualAddResponse>
|
||||
}
|
||||
|
||||
private _dossier(dossierId: string): Dossier {
|
||||
return this._dossiersService.find(dossierId);
|
||||
return this._activeDossiersService.find(dossierId);
|
||||
}
|
||||
|
||||
private _getMessage(mode: AnnotationActionMode, modifyDictionary?: boolean, error = false, isConflict = false) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user