RED-3796: Removed routerPath

This commit is contained in:
Adina Țeudan 2022-05-03 23:02:13 +03:00
parent fadbf34894
commit 06c9b2bbc7
30 changed files with 144 additions and 142 deletions

View File

@ -9,7 +9,7 @@ import { DownloadsListScreenComponent } from '@components/downloads-list-screen/
import { DossiersGuard } from '@guards/dossiers.guard';
import { ACTIVE_DOSSIERS_SERVICE, ARCHIVED_DOSSIERS_SERVICE } from './tokens';
import { FeaturesGuard } from '@guards/features-guard.service';
import { DOSSIER_TEMPLATE_ID, DOSSIERS_ARCHIVE } from '@utils/constants';
import { ARCHIVE_ROUTE, DOSSIER_TEMPLATE_ID, DOSSIERS_ARCHIVE, DOSSIERS_ROUTE } from '@utils/constants';
import { DossierTemplatesGuard } from '@guards/dossier-templates.guard';
import { DossierTemplateExistsGuard } from '@guards/dossier-template-exists.guard';
@ -46,24 +46,37 @@ const routes: Routes = [
},
},
{
path: `:${DOSSIER_TEMPLATE_ID}/dossiers`,
loadChildren: () => import('./modules/dossier/dossiers.module').then(m => m.DossiersModule),
path: `:${DOSSIER_TEMPLATE_ID}`,
children: [
{
path: `${DOSSIERS_ROUTE}`,
loadChildren: () => import('./modules/dossier/dossiers.module').then(m => m.DossiersModule),
canActivate: [CompositeRouteGuard],
data: {
routeGuards: [DossiersGuard],
dossiersService: ACTIVE_DOSSIERS_SERVICE,
},
},
{
path: `${ARCHIVE_ROUTE}`,
loadChildren: () => import('./modules/archive/archive.module').then(m => m.ArchiveModule),
canActivate: [CompositeRouteGuard],
data: {
routeGuards: [FeaturesGuard, DossiersGuard],
dossiersService: ARCHIVED_DOSSIERS_SERVICE,
features: [DOSSIERS_ARCHIVE],
},
},
{
path: '**',
redirectTo: `${DOSSIERS_ROUTE}`,
pathMatch: 'full',
},
],
canActivate: [CompositeRouteGuard],
data: {
routeGuards: [AuthGuard, RedRoleGuard, DossierTemplatesGuard, DossierTemplateExistsGuard, DossiersGuard],
routeGuards: [AuthGuard, RedRoleGuard, DossierTemplatesGuard, DossierTemplateExistsGuard],
requiredRoles: ['RED_USER', 'RED_MANAGER'],
dossiersService: ACTIVE_DOSSIERS_SERVICE,
},
},
{
path: `:${DOSSIER_TEMPLATE_ID}/archive`,
loadChildren: () => import('./modules/archive/archive.module').then(m => m.ArchiveModule),
canActivate: [CompositeRouteGuard],
data: {
routeGuards: [FeaturesGuard, AuthGuard, RedRoleGuard, DossierTemplatesGuard, DossierTemplateExistsGuard, DossiersGuard],
requiredRoles: ['RED_USER', 'RED_MANAGER'],
dossiersService: ARCHIVED_DOSSIERS_SERVICE,
features: [DOSSIERS_ARCHIVE],
},
},
{
@ -83,11 +96,6 @@ const routes: Routes = [
requiredRoles: ['RED_USER', 'RED_MANAGER'],
},
},
{
path: `:${DOSSIER_TEMPLATE_ID}`,
redirectTo: `:${DOSSIER_TEMPLATE_ID}/dossiers`,
pathMatch: 'full',
},
],
},
{

View File

@ -7,10 +7,10 @@ import { TranslateService } from '@ngx-translate/core';
import { SpotlightSearchAction } from '@components/spotlight-search/spotlight-search-action';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { filter, map, startWith } from 'rxjs/operators';
import { HelpModeService, shareDistinctLast } from '@iqser/common-ui';
import { shareDistinctLast } from '@iqser/common-ui';
import { BreadcrumbsService } from '@services/breadcrumbs.service';
import { FeaturesService } from '@services/features.service';
import { DOSSIERS_ARCHIVE } from '@utils/constants';
import { ARCHIVE_ROUTE, DOSSIERS_ARCHIVE, DOSSIERS_ROUTE } from '@utils/constants';
interface MenuItem {
readonly id: string;
@ -91,7 +91,6 @@ export class BaseScreenComponent {
readonly userPreferenceService: UserPreferenceService,
readonly titleService: Title,
readonly breadcrumbsService: BreadcrumbsService,
readonly helpModeService: HelpModeService,
) {}
private get _hideSearchThisDossier() {
@ -100,7 +99,7 @@ export class BaseScreenComponent {
return true;
}
const isDossierOverview = (routerLink.includes('dossiers') || routerLink.includes('archive')) && routerLink.length === 3;
const isDossierOverview = (routerLink.includes(DOSSIERS_ROUTE) || routerLink.includes(ARCHIVE_ROUTE)) && routerLink.length === 3;
return !isDossierOverview;
}

View File

@ -3,7 +3,7 @@ import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
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 { DOSSIER_ID, DOSSIER_TEMPLATE_ID } from '@utils/constants';
import { DossiersService } from '@services/dossiers/dossiers.service';
@Injectable({ providedIn: 'root' })
@ -17,16 +17,17 @@ export class DossierFilesGuard implements CanActivate {
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
const dossierId = route.paramMap.get(DOSSIER_ID);
const dossierTemplateId = route.paramMap.get(DOSSIER_TEMPLATE_ID);
const token: ProviderToken<DossiersService> = route.data.dossiersService;
const dossiersService: DossiersService = this._injector.get<DossiersService>(token);
if (!dossiersService.has(dossierId)) {
await this._router.navigate(['/main', dossiersService.routerPath]);
await this._router.navigate(['/main', dossierTemplateId]);
return false;
}
if (!this._filesMapService.has(dossierId)) {
await firstValueFrom(this._filesService.loadAll(dossierId, dossiersService.routerPath));
await firstValueFrom(this._filesService.loadAll(dossierId));
}
return true;
}

View File

@ -10,7 +10,7 @@ export class DossierTemplateExistsGuard implements CanActivate {
async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
const dossierTemplateId: string = route.paramMap.get(DOSSIER_TEMPLATE_ID);
if (!this._dossierTemplatesService.find(dossierTemplateId)) {
const adminView = !(route.routeConfig.path.includes('dossiers') || route.routeConfig.path.includes('archive'));
const adminView = !!route.pathFromRoot.find(r => r.routeConfig?.path === 'admin');
const routerPath = adminView ? ['main', 'admin', 'dossier-templates'] : [''];
await this._router.navigate(routerPath);
return false;

View File

@ -1,8 +1,8 @@
import { Component, Inject } from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DossierTemplatesService } from '../../../../services/entity-services/dossier-templates.service';
import { DossierTemplate, IDossierTemplate } from '../../../../../../../../libs/red-domain/src';
import { LoadingService, Toaster } from '../../../../../../../../libs/common-ui/src';
import { DossierTemplatesService } from '@services/entity-services/dossier-templates.service';
import { DossierTemplate } from '@red/domain';
import { LoadingService, Toaster } from '@iqser/common-ui';
import { firstValueFrom } from 'rxjs';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
@ -11,8 +11,8 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
styleUrls: ['./clone-dossier-template-dialog.component.scss'],
})
export class CloneDossierTemplateDialogComponent {
private readonly _dossierTemplate: DossierTemplate;
nameOfClonedDossierTemplate: string;
private readonly _dossierTemplate: DossierTemplate;
constructor(
private readonly _toaster: Toaster,
@ -25,6 +25,17 @@ export class CloneDossierTemplateDialogComponent {
this.nameOfClonedDossierTemplate = this._getCloneName();
}
async save() {
this._loadingService.start();
try {
await firstValueFrom(this._dossierTemplatesService.clone(this.dossierTemplateId, this.nameOfClonedDossierTemplate));
this._dialogRef.close(true);
} catch (error: any) {
this._toaster.error(_('clone-dossier-template.error.generic'), { error });
}
this._loadingService.stop();
}
private _getCloneName(): string | null {
const templateName = this._dossierTemplate.name.trim();
@ -47,15 +58,4 @@ export class CloneDossierTemplateDialogComponent {
}
return `Clone of ${nameOfClonedTemplate}`;
}
async save() {
this._loadingService.start();
try {
await firstValueFrom(this._dossierTemplatesService.clone(this.dossierTemplateId, this.nameOfClonedDossierTemplate));
this._dialogRef.close(true);
} catch (error: any) {
this._toaster.error(_('clone-dossier-template.error.generic'), { error });
}
this._loadingService.stop();
}
}

View File

@ -49,18 +49,16 @@ export class RedRoleGuard implements CanActivate {
return;
}
if (!this._userService.currentUser.isUser && state.url.startsWith('/main/dossiers')) {
this._router.navigate(['/main/admin']);
obs.next(false);
obs.complete();
return;
}
if (route.data.requiredRoles) {
if (this._userService.hasAnyRole(route.data.requiredRoles)) {
obs.next(true);
obs.complete();
} else {
this._router.navigate(['/main/dossiers']);
if (!this._userService.currentUser.isUser) {
this._router.navigate(['/main/admin']);
} else {
this._router.navigate(['/']);
}
obs.next(false);
obs.complete();
}

View File

@ -35,7 +35,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, this.dossier.routerPath));
await firstValueFrom(this._filesService.loadAll(this.dossier.dossierId));
});
}
}

View File

@ -1,5 +1,5 @@
<iqser-page-header
(closeAction)="router.navigate(['/main', dossiersService.routerPath])"
(closeAction)="router.navigate([dossier.dossiersListRouterLink])"
[actionConfigs]="actionConfigs"
[helpModeKey]="'document'"
[showCloseButton]="true"

View File

@ -1,4 +1,4 @@
import { Component, ElementRef, forwardRef, HostListener, Injector, OnDestroy, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { Component, ElementRef, forwardRef, HostListener, Injector, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { Dossier, DossierAttributeWithValue, File, IFileAttributeConfig, WorkflowFileStatus } from '@red/domain';
import { FileDropOverlayService } from '@upload-download/services/file-drop-overlay.service';
import { FileUploadModel } from '@upload-download/model/file-upload.model';
@ -126,7 +126,7 @@ export class DossierOverviewScreenComponent extends ListingComponent<File> imple
get #dossierFilesChange$() {
return this._dossiersService.dossierFileChanges$.pipe(
filter(dossierId => dossierId === this.dossierId),
switchMap(dossierId => this._filesService.loadAll(dossierId, this._dossiersService.routerPath)),
switchMap(dossierId => this._filesService.loadAll(dossierId)),
);
}

View File

@ -139,7 +139,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
this._loadingService.start();
await firstValueFrom(this._trashService.deleteDossier(this.dossier));
this._editDossierDialogRef.close();
await this._router.navigate(['main', 'dossiers']);
await this._router.navigate([this.dossier.dossiersListRouterLink]);
this._loadingService.stop();
this._toaster.success(_('edit-dossier-dialog.delete-successful'), { params: this.dossier });
});
@ -161,7 +161,7 @@ export class EditDossierGeneralInfoComponent implements OnInit, EditDossierSecti
if (result === ConfirmOptions.CONFIRM) {
this._loadingService.start();
await firstValueFrom(this._archivedDossiersService.archive([this.dossier]));
await this._router.navigate(['main', 'dossiers']);
await this._router.navigate([this.dossier.dossiersListRouterLink]);
this._toaster.success(_('dossier-listing.archive.archive-succeeded'), { params: this.dossier });
this._editDossierDialogRef.close();
this._loadingService.stop();

View File

@ -81,7 +81,7 @@ export class FilePreviewStateService {
#dossierFilesChange$() {
return this._dossiersService.dossierFileChanges$.pipe(
filter(dossierId => dossierId === this.dossierId),
switchMap(dossierId => this._filesService.loadAll(dossierId, this._dossiersService.routerPath)),
switchMap(dossierId => this._filesService.loadAll(dossierId)),
);
}

View File

@ -1,8 +1,8 @@
<a [routerLinkActive]="'active'" [routerLink]="['..', 'dossiers']" class="red-tab">
<a [routerLinkActive]="'active'" [routerLink]="['..', DOSSIERS_ROUTE]" class="red-tab">
{{ 'dossiers-type-switch.active' | translate }}
</a>
<a [routerLinkActive]="'active'" [routerLink]="['..', 'archive']" class="red-tab">
<a [routerLinkActive]="'active'" [routerLink]="['..', ARCHIVE_ROUTE]" class="red-tab">
{{ 'dossiers-type-switch.archive' | translate }}
</a>

View File

@ -1,4 +1,5 @@
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { ARCHIVE_ROUTE, DOSSIERS_ROUTE } from '@utils/constants';
@Component({
selector: 'redaction-dossiers-type-switch',
@ -6,4 +7,7 @@ import { ChangeDetectionStrategy, Component } from '@angular/core';
styleUrls: ['./dossiers-type-switch.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class DossiersTypeSwitchComponent {}
export class DossiersTypeSwitchComponent {
readonly DOSSIERS_ROUTE = DOSSIERS_ROUTE;
readonly ARCHIVE_ROUTE = ARCHIVE_ROUTE;
}

View File

@ -42,7 +42,7 @@ export class FileUploadService extends GenericService<IFileUploadResult> impleme
super(_injector, 'upload');
const fileFetch$ = this._fetchFiles$.pipe(
throttleTime(250),
switchMap(dossierId => this._filesService.loadAll(dossierId, 'dossiers')),
switchMap(dossierId => this._filesService.loadAll(dossierId)),
);
this._subscriptions.add(fileFetch$.subscribe());
const interval$ = interval(2500).pipe(tap(() => this._handleUploads()));

View File

@ -136,7 +136,7 @@ export class BreadcrumbsService {
name$: this._dossierTemplatesService.getEntityChanged$(dossierTemplateId).pipe(pluck('name')),
type: 'text' as BreadcrumbDisplayType,
options: {
routerLink: ['/main', dossierTemplateId],
routerLink: ['/main', dossierTemplateId, this._dossiersService.routerPath],
routerLinkActiveOptions: { exact: true },
clamp: true,
},
@ -146,12 +146,11 @@ export class BreadcrumbsService {
private _addDossierBreadcrumb(params: Record<string, string>): void {
const dossiersService = this._dossiersService;
const dossierId: string = params[DOSSIER_ID];
const dossierTemplateId: string = params[DOSSIER_TEMPLATE_ID];
this._append({
name$: dossiersService.getEntityChanged$(dossierId).pipe(pluck('dossierName')),
type: 'text' as BreadcrumbDisplayType,
options: {
routerLink: ['/main', dossierTemplateId, dossiersService.routerPath, dossierId],
routerLink: [dossiersService.find(dossierId).routerLink],
routerLinkActiveOptions: { exact: true },
clamp: true,
},
@ -159,15 +158,13 @@ export class BreadcrumbsService {
}
private _addFileBreadcrumb(params: Record<string, string>): void {
const dossierTemplateId: string = params[DOSSIER_TEMPLATE_ID];
const dossierId: string = params[DOSSIER_ID];
const fileId: string = params[FILE_ID];
const dossiersService = this._dossiersService;
this._append({
name$: this._filesMapService.watch$(dossierId, fileId).pipe(pluck('filename')),
type: 'text' as BreadcrumbDisplayType,
options: {
routerLink: ['/main', dossierTemplateId, dossiersService.routerPath, dossierId, 'file', fileId],
routerLink: [this._filesMapService.get(dossierId, fileId).routerLink],
clamp: true,
},
});

View File

@ -1,7 +1,7 @@
import { Injectable, Injector } from '@angular/core';
import { switchMap, tap } from 'rxjs/operators';
import { timer } from 'rxjs';
import { CHANGED_CHECK_INTERVAL } from '@utils/constants';
import { CHANGED_CHECK_INTERVAL, DOSSIERS_ROUTE } from '@utils/constants';
import { DossiersService } from './dossiers.service';
export interface IDossiersStats {
@ -14,7 +14,7 @@ export interface IDossiersStats {
})
export class ActiveDossiersService extends DossiersService {
constructor(protected readonly _injector: Injector) {
super(_injector, 'dossier', 'dossiers');
super(_injector, 'dossier', DOSSIERS_ROUTE);
timer(CHANGED_CHECK_INTERVAL, CHANGED_CHECK_INTERVAL)
.pipe(

View File

@ -7,7 +7,7 @@ import { ActiveDossiersService } from './active-dossiers.service';
import { DossiersService } from './dossiers.service';
import { FilesMapService } from '../entity-services/files-map.service';
import { FeaturesService } from '@services/features.service';
import { DOSSIERS_ARCHIVE } from '@utils/constants';
import { ARCHIVE_ROUTE, DOSSIERS_ARCHIVE } from '@utils/constants';
@Injectable({ providedIn: 'root' })
export class ArchivedDossiersService extends DossiersService {
@ -17,7 +17,7 @@ export class ArchivedDossiersService extends DossiersService {
private readonly _filesMapService: FilesMapService,
private readonly _featuresService: FeaturesService,
) {
super(_injector, 'archived-dossiers', 'archive');
super(_injector, 'archived-dossiers', ARCHIVE_ROUTE);
}
archive(dossiers: Dossier[]): Observable<unknown> {

View File

@ -61,7 +61,7 @@ export abstract class DossiersService extends EntitiesService<Dossier, IDossier>
loadAll(): Observable<Dossier[]> {
const dossierIds = (dossiers: Dossier[]) => dossiers.map(d => d.id);
return this.getAll().pipe(
mapEach(entity => new Dossier(entity, this.routerPath)),
mapEach(entity => new Dossier(entity)),
/* Load stats before updating entities */
switchMap(dossiers => this._dossierStatsService.getFor(dossierIds(dossiers)).pipe(map(() => dossiers))),
switchMap(dossiers => this._dossierStateService.loadAllForAllTemplates().pipe(map(() => dossiers))),
@ -81,7 +81,7 @@ export abstract class DossiersService extends EntitiesService<Dossier, IDossier>
private _load(id: string): Observable<DossierStats[]> {
const queryParams: List<QueryParam> = [{ key: 'includeArchived', value: this._path === 'archived-dossiers' }];
return super._getOne([id], this._defaultModelPath, queryParams).pipe(
map(entity => new Dossier(entity, 'dossiers')),
map(entity => new Dossier(entity)),
tap(dossier => this.replace(dossier)),
switchMap(dossier => this._dossierStatsService.getFor([dossier.dossierId])),
);

View File

@ -1,11 +1,11 @@
import { GenericService, HeadersConfiguration, IRouterPath, List, QueryParam, RequiredParam, Validate } from '@iqser/common-ui';
import { GenericService, HeadersConfiguration, List, QueryParam, RequiredParam, Validate } from '@iqser/common-ui';
import { Injectable, Injector } from '@angular/core';
import { HttpHeaders, HttpResponse } from '@angular/common/http';
import { Observable } from 'rxjs';
import { switchMap } from 'rxjs/operators';
import { FilesService } from '@services/entity-services/files.service';
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
import { IPageRotationRequest } from '@red/domain';
import { File, IPageRotationRequest } from '@red/domain';
@Injectable({
providedIn: 'root',
@ -20,10 +20,9 @@ export class FileManagementService extends GenericService<unknown> {
}
@Validate()
delete(@RequiredParam() files: List<IRouterPath>, @RequiredParam() dossierId: string) {
delete(@RequiredParam() files: List<File>, @RequiredParam() dossierId: string) {
const fileIds = files.map(f => f.id);
const routerPath: string = files[0].routerPath;
return super._post(fileIds, `delete/${dossierId}`).pipe(switchMap(() => this._filesService.loadAll(dossierId, routerPath)));
return super._post(fileIds, `delete/${dossierId}`).pipe(switchMap(() => this._filesService.loadAll(dossierId)));
}
@Validate()

View File

@ -12,11 +12,7 @@ export class FilesMapService extends EntitiesMapService<File, IFile> {
replaceFiles(files: File[], property: keyof IFile, generateValue: Function) {
const newFiles = files.map(
file =>
new File(
{ ...file, [property]: generateValue(file[property]), lastUpdated: new Date().toISOString() },
file.reviewerName,
file.routerPath,
),
new File({ ...file, [property]: generateValue(file[property]), lastUpdated: new Date().toISOString() }, file.reviewerName),
);
this.replace(newFiles);
}

View File

@ -1,5 +1,5 @@
import { Injectable, Injector } from '@angular/core';
import { EntitiesService, IRouterPath, List, mapEach, RequiredParam, Validate } from '@iqser/common-ui';
import { EntitiesService, List, mapEach, RequiredParam, Validate } from '@iqser/common-ui';
import { File, IFile } from '@red/domain';
import { Observable } from 'rxjs';
import { UserService } from '../user.service';
@ -23,9 +23,9 @@ export class FilesService extends EntitiesService<File, IFile> {
}
/** Reload dossier files + stats. */
loadAll(dossierId: string, routerPath: string) {
loadAll(dossierId: string) {
const files$ = this.getFor(dossierId).pipe(
mapEach(file => new File(file, this._userService.getNameForId(file.assignee), routerPath)),
mapEach(file => new File(file, this._userService.getNameForId(file.assignee))),
tap(() => this._logger.info('[FILE] Loaded')),
);
const loadStats$ = files$.pipe(switchMap(files => this._dossierStatsService.getFor([dossierId]).pipe(map(() => files))));
@ -34,7 +34,7 @@ export class FilesService extends EntitiesService<File, IFile> {
reload(dossierId: string, file: File): Observable<boolean> {
return super._getOne([dossierId, file.id]).pipe(
map(_file => new File(_file, this._userService.getNameForId(_file.assignee), file.routerPath)),
map(_file => new File(_file, this._userService.getNameForId(_file.assignee))),
switchMap(_file => this._dossierStatsService.getFor([dossierId]).pipe(map(() => _file))),
map(_file => this._filesMapService.replace([_file])),
tap(() => this._logger.info('[FILE] Reloaded')),
@ -42,56 +42,46 @@ export class FilesService extends EntitiesService<File, IFile> {
}
@Validate()
setUnassigned(@RequiredParam() files: List<IRouterPath>, @RequiredParam() dossierId: string) {
setUnassigned(@RequiredParam() files: List<File>, @RequiredParam() dossierId: string) {
const url = `${this._defaultModelPath}/set-assignee/${dossierId}/bulk`;
const fileIds = files.map(f => f.id);
const routerPath: string = files[0].routerPath;
return this._post<unknown>(fileIds, url).pipe(switchMap(() => this.loadAll(dossierId, routerPath)));
return this._post<unknown>(fileIds, url).pipe(switchMap(() => this.loadAll(dossierId)));
}
@Validate()
setToNewFor(@RequiredParam() files: List<IRouterPath>, @RequiredParam() dossierId: string) {
setToNewFor(@RequiredParam() files: List<File>, @RequiredParam() dossierId: string) {
const url = `${this._defaultModelPath}/new/${dossierId}/bulk`;
const fileIds = files.map(f => f.id);
const routerPath: string = files[0].routerPath;
return this._post<unknown>(fileIds, url).pipe(switchMap(() => this.loadAll(dossierId, routerPath)));
return this._post<unknown>(fileIds, url).pipe(switchMap(() => this.loadAll(dossierId)));
}
@Validate()
setUnderApprovalFor(@RequiredParam() files: List<IRouterPath>, @RequiredParam() dossierId: string, assigneeId: string) {
setUnderApprovalFor(@RequiredParam() files: List<File>, @RequiredParam() dossierId: string, assigneeId: string) {
const url = `${this._defaultModelPath}/under-approval/${dossierId}/bulk`;
const fileIds = files.map(f => f.id);
const routerPath: string = files[0].routerPath;
return this._post<unknown>(fileIds, url, [{ key: 'assigneeId', value: assigneeId }]).pipe(
switchMap(() => this.loadAll(dossierId, routerPath)),
);
return this._post<unknown>(fileIds, url, [{ key: 'assigneeId', value: assigneeId }]).pipe(switchMap(() => this.loadAll(dossierId)));
}
@Validate()
setReviewerFor(@RequiredParam() files: List<IRouterPath>, @RequiredParam() dossierId: string, assigneeId: string) {
setReviewerFor(@RequiredParam() files: List<File>, @RequiredParam() dossierId: string, assigneeId: string) {
const url = `${this._defaultModelPath}/under-review/${dossierId}/bulk`;
const fileIds = files.map(f => f.id);
const routerPath: string = files[0].routerPath;
return this._post<unknown>(fileIds, url, [{ key: 'assigneeId', value: assigneeId }]).pipe(
switchMap(() => this.loadAll(dossierId, routerPath)),
);
return this._post<unknown>(fileIds, url, [{ key: 'assigneeId', value: assigneeId }]).pipe(switchMap(() => this.loadAll(dossierId)));
}
@Validate()
setApprovedFor(@RequiredParam() files: List<IRouterPath>, @RequiredParam() dossierId: string) {
setApprovedFor(@RequiredParam() files: List<File>, @RequiredParam() dossierId: string) {
const fileIds = files.map(f => f.id);
const routerPath: string = files[0].routerPath;
return this._post<unknown>(fileIds, `${this._defaultModelPath}/approved/${dossierId}/bulk`).pipe(
switchMap(() => this.loadAll(dossierId, routerPath)),
switchMap(() => this.loadAll(dossierId)),
);
}
@Validate()
setUnderReviewFor(@RequiredParam() files: List<IRouterPath>, @RequiredParam() dossierId: string) {
setUnderReviewFor(@RequiredParam() files: List<File>, @RequiredParam() dossierId: string) {
const fileIds = files.map(f => f.id);
const routerPath: string = files[0].routerPath;
return this._post<unknown>(fileIds, `${this._defaultModelPath}/under-review/${dossierId}/bulk`).pipe(
switchMap(() => this.loadAll(dossierId, routerPath)),
switchMap(() => this.loadAll(dossierId)),
);
}
}

View File

@ -56,6 +56,6 @@ export class PlatformSearchService extends GenericService<ISearchResponse> {
}
private _loadFilesFor$(dossiers: Dossier[]) {
return zip(...dossiers.map(dossier => this._filesService.loadAll(dossier.id, dossier.routerPath)));
return zip(...dossiers.map(dossier => this._filesService.loadAll(dossier.id)));
}
}

View File

@ -81,7 +81,7 @@ export class TrashService extends GenericService<TrashItem> {
getFiles(dossierIds = this._activeDossiersService.all.map(d => d.id)): Observable<TrashFile[]> {
return this._post<Record<string, IFile[]>>(dossierIds, 'status/softdeleted').pipe(
map(res => flatMap(Object.values(res))),
mapEach(file => new File(file, this._userService.getNameForId(file.assignee), this._activeDossiersService.routerPath)),
mapEach(file => new File(file, this._userService.getNameForId(file.assignee))),
mapEach(file => {
const dossier = this._activeDossiersService.find(file.dossierId);
return new TrashFile(
@ -133,6 +133,6 @@ export class TrashService extends GenericService<TrashItem> {
}
private _restoreFiles(@RequiredParam() dossierId: string, @RequiredParam() fileIds: List) {
return this._post(fileIds, `delete/restore/${dossierId}`).pipe(switchMap(() => this._filesService.loadAll(dossierId, 'dossiers')));
return this._post(fileIds, `delete/restore/${dossierId}`).pipe(switchMap(() => this._filesService.loadAll(dossierId)));
}
}

View File

@ -1,5 +1,5 @@
import { Injectable, Injector } from '@angular/core';
import { GenericService, IRouterPath, List, QueryParam, RequiredParam, Toaster, Validate } from '@iqser/common-ui';
import { GenericService, List, QueryParam, RequiredParam, Toaster, Validate } from '@iqser/common-ui';
import { Dossier, File, IPageExclusionRequest } from '@red/domain';
import { catchError, switchMap, tap } from 'rxjs/operators';
import { FilesService } from './entity-services/files.service';
@ -36,9 +36,8 @@ export class ReanalysisService extends GenericService<unknown> {
}
@Validate()
reanalyzeFilesForDossier(@RequiredParam() files: List<IRouterPath>, @RequiredParam() dossierId: string, params?: ReanalyzeQueryParams) {
reanalyzeFilesForDossier(@RequiredParam() files: List<File>, @RequiredParam() dossierId: string, params?: ReanalyzeQueryParams) {
const fileIds = files.map(f => f.id);
const routerPath: string = files[0].routerPath;
const queryParams: QueryParam[] = [];
if (params?.force) {
queryParams.push({ key: 'force', value: true });
@ -47,22 +46,19 @@ export class ReanalysisService extends GenericService<unknown> {
queryParams.push({ key: 'triggeredByUser', value: true });
}
return this._post(fileIds, `reanalyze/${dossierId}/bulk`, queryParams).pipe(
switchMap(() => this._filesService.loadAll(dossierId, routerPath)),
);
return this._post(fileIds, `reanalyze/${dossierId}/bulk`, queryParams).pipe(switchMap(() => this._filesService.loadAll(dossierId)));
}
@Validate()
toggleAnalysis(@RequiredParam() dossierId: string, @RequiredParam() files: List<IRouterPath>, excluded?: boolean) {
toggleAnalysis(@RequiredParam() dossierId: string, @RequiredParam() files: List<File>, excluded?: boolean) {
const fileIds = files.map(f => f.id);
const routerPath: string = files[0].routerPath;
const queryParams: QueryParam[] = [];
if (excluded) {
queryParams.push({ key: 'excluded', value: excluded });
}
return this._post(fileIds, `toggle-analysis/${dossierId}/bulk`, queryParams).pipe(
switchMap(() => this._filesService.loadAll(dossierId, routerPath)),
switchMap(() => this._filesService.loadAll(dossierId)),
);
}
@ -86,24 +82,19 @@ export class ReanalysisService extends GenericService<unknown> {
}
@Validate()
ocrFiles(@RequiredParam() files: List<IRouterPath>, @RequiredParam() dossierId: string) {
ocrFiles(@RequiredParam() files: List<File>, @RequiredParam() dossierId: string) {
const fileIds = files.map(f => f.id);
const routerPath: string = files[0].routerPath;
return this._post(fileIds, `ocr/reanalyze/${dossierId}/bulk`).pipe(
switchMap(() => this._filesService.loadAll(dossierId, routerPath)),
);
return this._post(fileIds, `ocr/reanalyze/${dossierId}/bulk`).pipe(switchMap(() => this._filesService.loadAll(dossierId)));
}
@Validate()
reanalyzeDossier(@RequiredParam() dossier: Dossier, force?: boolean) {
const { dossierId, routerPath } = dossier;
const { dossierId } = dossier;
const queryParams: QueryParam[] = [];
if (force) {
queryParams.push({ key: 'force', value: force });
}
return this._post({}, `reanalyze/${dossierId}`, queryParams).pipe(
switchMap(() => this._filesService.loadAll(dossierId, routerPath)),
);
return this._post({}, `reanalyze/${dossierId}`, queryParams).pipe(switchMap(() => this._filesService.loadAll(dossierId)));
}
}

View File

@ -5,3 +5,6 @@ export const FILE_ID = 'fileId';
export const DOSSIER_TEMPLATE_ID = 'dossierTemplateId';
export const ENTITY_TYPE = 'entity';
export const DOSSIERS_ARCHIVE = 'DOSSIERS_ARCHIVE';
export const ARCHIVE_ROUTE = 'archive';
export const DOSSIERS_ROUTE = 'dossiers';

View File

@ -1,7 +1,7 @@
{
"ADMIN_CONTACT_NAME": null,
"ADMIN_CONTACT_URL": null,
"API_URL": "https://dev-08.iqser.cloud/redaction-gateway-v1",
"API_URL": "https://dev-04.iqser.cloud/redaction-gateway-v1",
"APP_NAME": "RedactManager",
"AUTO_READ_TIME": 3,
"BACKEND_APP_VERSION": "4.4.40",
@ -17,7 +17,7 @@
"MAX_RETRIES_ON_SERVER_ERROR": 3,
"OAUTH_CLIENT_ID": "redaction",
"OAUTH_IDP_HINT": null,
"OAUTH_URL": "https://dev-08.iqser.cloud/auth/realms/redaction",
"OAUTH_URL": "https://dev-04.iqser.cloud/auth/realms/redaction",
"RECENT_PERIOD_IN_HOURS": 24,
"SELECTION_MODE": "structural",
"MANUAL_BASE_URL": "https://docs.redactmanager.com/preview"

@ -1 +1 @@
Subproject commit 7bc942ae164164dadba94045f1f249a6cbb17284
Subproject commit f06c007bec1a7da5c257e68d6df8c806419ceb2b

View File

@ -1,8 +1,9 @@
import { IListable, IRouterPath, List } from '@iqser/common-ui';
import { IListable, List } from '@iqser/common-ui';
import { IDossier } from './dossier';
import { DownloadFileType } from '../shared';
import { ARCHIVE_ROUTE, DOSSIERS_ROUTE } from '@utils/constants';
export class Dossier implements IDossier, IListable, IRouterPath {
export class Dossier implements IDossier, IListable {
readonly dossierId: string;
readonly dossierTemplateId: string;
readonly ownerId: string;
@ -23,7 +24,7 @@ export class Dossier implements IDossier, IListable, IRouterPath {
readonly archivedTime: string;
readonly hasReviewers: boolean;
constructor(dossier: IDossier, readonly routerPath: string) {
constructor(dossier: IDossier) {
this.dossierId = dossier.dossierId;
this.approverIds = dossier.approverIds;
this.date = dossier.date;
@ -50,7 +51,12 @@ export class Dossier implements IDossier, IListable, IRouterPath {
}
get routerLink(): string {
return `/main/${this.dossierTemplateId}/${this.routerPath}/${this.dossierId}`;
return `${this.dossiersListRouterLink}/${this.dossierId}`;
}
get dossiersListRouterLink(): string {
const routerPath = this.isArchived ? ARCHIVE_ROUTE : DOSSIERS_ROUTE;
return `/main/${this.dossierTemplateId}/${routerPath}`;
}
get searchKey(): string {

View File

@ -1,4 +1,4 @@
import { Entity, IRouterPath } from '@iqser/common-ui';
import { Entity } from '@iqser/common-ui';
import { StatusSorter } from '../shared';
import {
isFullProcessingStatuses,
@ -10,8 +10,9 @@ import {
} from './types';
import { IFile } from './file';
import { FileAttributes } from '../file-attributes';
import { ARCHIVE_ROUTE, DOSSIERS_ROUTE } from '@utils/constants';
export class File extends Entity<IFile> implements IFile, IRouterPath {
export class File extends Entity<IFile> implements IFile {
readonly added?: string;
readonly allManualRedactionsApplied: boolean;
readonly analysisDuration?: number;
@ -51,6 +52,8 @@ export class File extends Entity<IFile> implements IFile, IRouterPath {
readonly redactionModificationDate: string;
readonly lastManualChangeDate?: string;
readonly hasHighlights: boolean;
readonly dossierArchived: boolean;
readonly dossierTemplateId: string;
readonly statusSort: number;
readonly cacheIdentifier?: string;
@ -70,7 +73,7 @@ export class File extends Entity<IFile> implements IFile, IRouterPath {
readonly canBeOpened: boolean;
readonly canBeOCRed: boolean;
constructor(file: IFile, readonly reviewerName: string, readonly routerPath: string, readonly dossierTemplateId?: string) {
constructor(file: IFile, readonly reviewerName: string) {
super(file);
this.added = file.added;
this.allManualRedactionsApplied = !!file.allManualRedactionsApplied;
@ -112,6 +115,8 @@ export class File extends Entity<IFile> implements IFile, IRouterPath {
this.redactionModificationDate = file.redactionModificationDate ?? '';
this.lastManualChangeDate = file.lastManualChangeDate;
this.hasHighlights = file.hasHighlights;
this.dossierArchived = file.dossierArchived;
this.dossierTemplateId = file.dossierTemplateId;
this.statusSort = StatusSorter[this.workflowStatus];
this.cacheIdentifier = btoa(this.fileManipulationDate ?? '');
@ -146,6 +151,7 @@ export class File extends Entity<IFile> implements IFile, IRouterPath {
}
get routerLink(): string | undefined {
return this.canBeOpened ? `/main/${this.dossierTemplateId}/${this.routerPath}/${this.dossierId}/file/${this.fileId}` : undefined;
const routerPath = this.dossierArchived ? ARCHIVE_ROUTE : DOSSIERS_ROUTE;
return this.canBeOpened ? `/main/${this.dossierTemplateId}/${routerPath}/${this.dossierId}/file/${this.fileId}` : undefined;
}
}

View File

@ -149,6 +149,10 @@ export interface IFile {
readonly hasHighlights: boolean;
readonly dossierArchived: boolean;
readonly dossierTemplateId: string;
/**
* Last time the actual file was touched
*/