From bf0685339ae0a372c6159cb6dc06e4b2d997a087 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Fri, 9 Jun 2023 23:37:01 +0300 Subject: [PATCH] RED-6829: update file data service --- apps/red-ui/src/app/app-routing.module.ts | 52 +++++------ .../base-screen/base-screen.component.ts | 4 +- .../user-menu/user-menu.component.ts | 9 +- .../app/models/file/annotation.permissions.ts | 8 +- .../modules/account/account-routing.module.ts | 4 +- .../account-side-nav.component.ts | 4 +- .../preferences/preferences.component.ts | 4 +- .../user-profile-screen.component.ts | 4 +- .../app/modules/admin/admin-routing.module.ts | 22 ++--- ...clone-dossier-template-dialog.component.ts | 4 +- .../add-entity-dialog.component.ts | 4 +- .../screens/audit/audit-screen.component.ts | 4 +- .../default-colors-screen.component.ts | 4 +- .../digital-signature-screen.component.ts | 4 +- ...sier-templates-listing-screen.component.ts | 4 +- .../dictionary/dictionary-screen.component.ts | 4 +- .../entity-info/entity-info.component.ts | 4 +- ...dd-edit-file-attribute-dialog.component.ts | 4 +- ...ile-attributes-listing-screen.component.ts | 4 +- .../general-config-form.component.ts | 4 +- .../smtp-form/smtp-form.component.ts | 4 +- .../system-preferences-form.component.ts | 4 +- .../license-screen.component.ts | 6 +- .../permissions-screen.component.ts | 4 +- .../reports-screen.component.ts | 4 +- .../user-listing-screen.component.ts | 5 +- .../watermark-screen.component.ts | 4 +- .../watermarks-listing-screen.component.ts | 4 +- .../admin-side-nav.component.ts | 24 +++--- .../template-stats.component.ts | 4 +- .../dossier-details.component.ts | 4 +- ...ossier-overview-screen-header.component.ts | 4 +- .../file-attribute.component.ts | 4 +- .../dossier-overview/config.service.ts | 5 +- .../annotation-actions.component.ts | 4 +- .../annotation-card.component.ts | 4 +- .../annotation-references-list.component.html | 4 +- .../annotation-references-list.component.ts | 4 +- .../annotations-list.component.html | 2 +- .../comments/comments.component.html | 4 +- .../components/comments/comments.component.ts | 12 ++- .../document-info.component.html | 12 +-- .../document-info/document-info.component.ts | 19 ++-- .../file-workload/file-workload.component.ts | 2 +- .../highlights-separator.component.ts | 4 +- .../page-exclusion.component.ts | 17 +--- .../page-indicator.component.ts | 4 +- .../components/pages/pages.component.ts | 2 +- .../view-switch/view-switch.component.html | 86 +++++++++---------- .../view-switch/view-switch.component.ts | 42 +++++---- .../document-info-dialog.component.ts | 2 +- .../highlight-action-dialog.component.ts | 4 +- .../manual-annotation-dialog.component.ts | 6 +- .../file-preview-screen.component.ts | 35 ++++---- .../services/annotation-references.service.ts | 30 +++---- .../services/file-data.service.ts | 84 +++++++----------- .../services/file-preview-state.service.ts | 10 ++- .../services/manual-redaction.service.ts | 6 +- .../pdf-annotation-actions.service.ts | 4 +- .../services/pdf-proxy.service.ts | 12 +-- .../file-preview/services/stamp.service.ts | 2 +- .../services/page-rotation.service.ts | 19 ++-- .../dossiers-listing-actions.component.ts | 4 +- .../file-actions/file-actions.component.ts | 6 +- .../edit-dossier-dialog.component.ts | 6 +- .../team-members/team-members.component.ts | 14 +-- .../add-dossier-dialog.component.ts | 8 +- .../app/services/files/earmarks.service.ts | 2 +- .../src/app/services/files/files.service.ts | 15 ++-- .../services/files/redaction-log.service.ts | 13 ++- .../src/app/services/permissions.service.ts | 82 +++++++++--------- .../src/app/services/reanalysis.service.ts | 14 +-- apps/red-ui/src/app/users/roles.ts | 2 +- apps/red-ui/src/app/users/user.service.ts | 8 +- apps/red-ui/src/app/utils/main.resolver.ts | 4 +- 75 files changed, 407 insertions(+), 442 deletions(-) diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts index d856101fd..5eb70338e 100644 --- a/apps/red-ui/src/app/app-routing.module.ts +++ b/apps/red-ui/src/app/app-routing.module.ts @@ -25,7 +25,7 @@ import { TrashGuard } from '@guards/trash.guard'; import { ARCHIVE_ROUTE, BreadcrumbTypes, DOSSIER_ID, DOSSIER_TEMPLATE_ID, DOSSIERS_ARCHIVE, DOSSIERS_ROUTE, FILE_ID } from '@red/domain'; import { DossierFilesGuard } from '@guards/dossier-files-guard'; import { WebViewerLoadedGuard } from './modules/pdf-viewer/services/webviewer-loaded.guard'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { mainResolver } from '@utils/main.resolver'; const dossierTemplateIdRoutes: IqserRoutes = [ @@ -36,7 +36,7 @@ const dossierTemplateIdRoutes: IqserRoutes = [ routeGuards: [DossiersGuard], dossiersService: ACTIVE_DOSSIERS_SERVICE, permissions: { - allow: [ROLES.files.readStatus], + allow: [Roles.files.readStatus], redirectTo: '/auth-error', }, }, @@ -49,7 +49,7 @@ const dossierTemplateIdRoutes: IqserRoutes = [ breadcrumbs: [BreadcrumbTypes.dossierTemplate, BreadcrumbTypes.dossier], dossiersService: ACTIVE_DOSSIERS_SERVICE, permissions: { - allow: [ROLES.dossierAttributes.read, ROLES.dossierAttributes.readConfig], + allow: [Roles.dossierAttributes.read, Roles.dossierAttributes.readConfig], redirectTo: '/auth-error', }, skeleton: 'dossier', @@ -64,7 +64,7 @@ const dossierTemplateIdRoutes: IqserRoutes = [ breadcrumbs: [BreadcrumbTypes.dossierTemplate, BreadcrumbTypes.dossier, BreadcrumbTypes.file], dossiersService: ACTIVE_DOSSIERS_SERVICE, permissions: { - allow: [ROLES.readRedactionLog, ROLES.files.downloadOriginal, ROLES.highlights.read], + allow: [Roles.readRedactionLog, Roles.files.downloadOriginal, Roles.highlights.read], redirectTo: '/auth-error', }, }, @@ -120,19 +120,19 @@ const mainRoutes: IqserRoutes = [ routeGuards: [IqserAuthGuard, RedRoleGuard, IqserPermissionsGuard, DossierTemplatesGuard, DashboardGuard], permissions: { allow: [ - ROLES.any, - ROLES.templates.read, - ROLES.fileAttributes.readConfig, - ROLES.watermarks.read, - ROLES.dictionaryTypes.read, - ROLES.colors.read, - ROLES.states.read, - ROLES.notifications.read, + Roles.any, + Roles.templates.read, + Roles.fileAttributes.readConfig, + Roles.watermarks.read, + Roles.dictionaryTypes.read, + Roles.colors.read, + Roles.states.read, + Roles.notifications.read, 'RED_USER', ], redirectTo: { RED_USER: '/main/admin', - [ROLES.templates.read]: '/main/admin', + [Roles.templates.read]: '/main/admin', [DEFAULT_REDIRECT_KEY]: '/auth-error', }, }, @@ -147,7 +147,7 @@ const mainRoutes: IqserRoutes = [ data: { routeGuards: [IqserAuthGuard, RedRoleGuard], permissions: { - allow: ROLES.readDownloadStatus, + allow: Roles.readDownloadStatus, redirectTo: '/auth-error', }, }, @@ -159,7 +159,7 @@ const mainRoutes: IqserRoutes = [ data: { routeGuards: [IqserAuthGuard, RedRoleGuard, DossiersGuard], permissions: { - allow: [ROLES.search], + allow: [Roles.search], redirectTo: '/auth-error', }, }, @@ -172,7 +172,7 @@ const mainRoutes: IqserRoutes = [ routeGuards: [IqserAuthGuard, RedRoleGuard, DossiersGuard, TrashGuard], dossiersService: ACTIVE_DOSSIERS_SERVICE, permissions: { - allow: [ROLES.dossiers.read, ROLES.files.readStatus], + allow: [Roles.dossiers.read, Roles.files.readStatus], redirectTo: '/auth-error', }, }, @@ -185,19 +185,19 @@ const mainRoutes: IqserRoutes = [ routeGuards: [IqserAuthGuard, RedRoleGuard, DossierTemplatesGuard, DashboardGuard], permissions: { allow: [ - ROLES.any, - ROLES.templates.read, - ROLES.fileAttributes.readConfig, - ROLES.watermarks.read, - ROLES.dictionaryTypes.read, - ROLES.colors.read, - ROLES.states.read, - ROLES.notifications.read, - ROLES.dossiers.read, + Roles.any, + Roles.templates.read, + Roles.fileAttributes.readConfig, + Roles.watermarks.read, + Roles.dictionaryTypes.read, + Roles.colors.read, + Roles.states.read, + Roles.notifications.read, + Roles.dossiers.read, 'RED_USER', ], redirectTo: { - [ROLES.any]: '/auth-error', + [Roles.any]: '/auth-error', RED_USER: '/main/admin', [DEFAULT_REDIRECT_KEY]: '/', }, diff --git a/apps/red-ui/src/app/components/base-screen/base-screen.component.ts b/apps/red-ui/src/app/components/base-screen/base-screen.component.ts index a77022c21..3961f1bb6 100644 --- a/apps/red-ui/src/app/components/base-screen/base-screen.component.ts +++ b/apps/red-ui/src/app/components/base-screen/base-screen.component.ts @@ -10,7 +10,7 @@ import { IqserPermissionsService, List, shareDistinctLast, TenantsService } from import { BreadcrumbsService } from '@services/breadcrumbs.service'; import { FeaturesService } from '@services/features.service'; import { ARCHIVE_ROUTE, DOSSIERS_ARCHIVE, DOSSIERS_ROUTE } from '@red/domain'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { REDDocumentViewer } from '../../modules/pdf-viewer/services/document-viewer.service'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; @@ -22,7 +22,7 @@ const isSearchScreen: (url: string) => boolean = url => url.includes('/search'); styleUrls: ['./base-screen.component.scss'], }) export class BaseScreenComponent { - readonly roles = ROLES; + readonly roles = Roles; readonly documentViewer = inject(REDDocumentViewer); readonly currentUser = this.userService.currentUser; readonly searchActions: List = [ diff --git a/apps/red-ui/src/app/components/user-menu/user-menu.component.ts b/apps/red-ui/src/app/components/user-menu/user-menu.component.ts index f0012aa5d..49690a0ce 100644 --- a/apps/red-ui/src/app/components/user-menu/user-menu.component.ts +++ b/apps/red-ui/src/app/components/user-menu/user-menu.component.ts @@ -1,9 +1,10 @@ import { Component, inject } from '@angular/core'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { getCurrentUser, IqserPermissionsService, List, TenantsService } from '@iqser/common-ui'; import { User } from '@red/domain'; import { UserService } from '@users/user.service'; + interface MenuItem { readonly id: string; readonly name: string; @@ -34,19 +35,19 @@ export class UserMenuComponent { id: 'admin', name: _('top-bar.navigation-items.my-account.children.admin'), routerLink: '/main/admin', - show: (this.currentUser.isManager || this.currentUser.isUserAdmin) && this.#permissionsService.has([ROLES.templates.read]), + show: (this.currentUser.isManager || this.currentUser.isUserAdmin) && this.#permissionsService.has([Roles.templates.read]), }, { id: 'downloads', name: _('top-bar.navigation-items.my-account.children.downloads'), routerLink: '/main/downloads', - show: this.currentUser.isUser && this.#permissionsService.has(ROLES.readDownloadStatus), + show: this.currentUser.isUser && this.#permissionsService.has(Roles.readDownloadStatus), }, { id: 'trash', name: _('top-bar.navigation-items.my-account.children.trash'), routerLink: '/main/trash', - show: this.currentUser.isUser && this.#permissionsService.has([ROLES.dossiers.read, ROLES.files.readStatus]), + show: this.currentUser.isUser && this.#permissionsService.has([Roles.dossiers.read, Roles.files.readStatus]), }, ]; diff --git a/apps/red-ui/src/app/models/file/annotation.permissions.ts b/apps/red-ui/src/app/models/file/annotation.permissions.ts index 1d4b9cda5..3932f2142 100644 --- a/apps/red-ui/src/app/models/file/annotation.permissions.ts +++ b/apps/red-ui/src/app/models/file/annotation.permissions.ts @@ -2,7 +2,7 @@ import { AnnotationWrapper } from './annotation.wrapper'; import { Dictionary } from '@red/domain'; import { isArray } from 'lodash-es'; import { IqserPermissionsService } from '@iqser/common-ui'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; export class AnnotationPermissions { canUndo = true; @@ -29,9 +29,9 @@ export class AnnotationPermissions { } const summedPermissions: AnnotationPermissions = new AnnotationPermissions(); - const canAddRedaction = permissionsService.has(ROLES.redactions.write); - const canRequestRedaction = permissionsService.has(ROLES.redactions.request); - const canProcessManualRedaction = permissionsService.has(ROLES.redactions.processManualRequest); + const canAddRedaction = permissionsService.has(Roles.redactions.write); + const canRequestRedaction = permissionsService.has(Roles.redactions.request); + const canProcessManualRedaction = permissionsService.has(Roles.redactions.processManualRequest); const canAddOrRequestRedaction = canAddRedaction || canRequestRedaction; for (const annotation of annotations) { diff --git a/apps/red-ui/src/app/modules/account/account-routing.module.ts b/apps/red-ui/src/app/modules/account/account-routing.module.ts index a3cfdffae..75e216243 100644 --- a/apps/red-ui/src/app/modules/account/account-routing.module.ts +++ b/apps/red-ui/src/app/modules/account/account-routing.module.ts @@ -4,7 +4,7 @@ import { CompositeRouteGuard, IqserAuthGuard, IqserPermissionsGuard, IqserRoutes import { RedRoleGuard } from '@users/red-role.guard'; import { BaseAccountScreenComponent } from './base-account-screen/base-account-screen-component'; import { PreferencesComponent } from './screens/preferences/preferences.component'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; const routes: IqserRoutes = [ { path: '', redirectTo: 'user-profile', pathMatch: 'full' }, @@ -24,7 +24,7 @@ const routes: IqserRoutes = [ data: { routeGuards: [IqserAuthGuard, RedRoleGuard], permissions: { - allow: [ROLES.notifications.write, 'RED_USER'], + allow: [Roles.notifications.write, 'RED_USER'], redirectTo: '/', }, }, diff --git a/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.ts b/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.ts index 0a5d7b80e..d337c138c 100644 --- a/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.ts +++ b/apps/red-ui/src/app/modules/account/account-side-nav/account-side-nav.component.ts @@ -1,7 +1,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { ChangeDetectionStrategy, Component } from '@angular/core'; import { getCurrentUser, IqserPermissionsService } from '@iqser/common-ui'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { User } from '@red/domain'; interface NavItem { @@ -26,7 +26,7 @@ export class AccountSideNavComponent { }, { screen: 'notifications', - show: this.currentUser.isUser && this._permissionsService.has(ROLES.notifications.write), + show: this.currentUser.isUser && this._permissionsService.has(Roles.notifications.write), label: _('notifications.label'), }, { diff --git a/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.ts b/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.ts index 7f374b298..3ecb9c9cf 100644 --- a/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.ts +++ b/apps/red-ui/src/app/modules/account/screens/preferences/preferences.component.ts @@ -3,7 +3,7 @@ import { PreferencesKeys, UserPreferenceService } from '@users/user-preference.s import { FormBuilder, FormGroup } from '@angular/forms'; import { ActivatedRoute } from '@angular/router'; import { AsControl, BaseFormComponent, IqserPermissionsService } from '@iqser/common-ui'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; interface PreferencesForm { // preferences @@ -52,7 +52,7 @@ export class PreferencesComponent extends BaseFormComponent { loadAllAnnotationsWarning: [this.userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning)], }); - if (!this._permissionsService.has(ROLES.managePreferences)) { + if (!this._permissionsService.has(Roles.managePreferences)) { this.form.disable(); } diff --git a/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.ts b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.ts index 5e7e951de..442b268ce 100644 --- a/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.ts +++ b/apps/red-ui/src/app/modules/account/screens/user-profile/user-profile-screen/user-profile-screen.component.ts @@ -16,7 +16,7 @@ import { languagesTranslations } from '@translations/languages-translations'; import { UserService } from '@users/user.service'; import { firstValueFrom } from 'rxjs'; import { UserPreferenceService } from '@users/user-preference.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { UserProfileDialogService } from '../services/user-profile-dialog.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -136,7 +136,7 @@ export class UserProfileScreenComponent extends BaseFormComponent implements OnI private _initializeForm(): void { try { this.form = this._getForm(); - if (!this._permissionsService.has(ROLES.updateMyProfile)) { + if (!this._permissionsService.has(Roles.updateMyProfile)) { this.form.disable(); } this.#profileModel = { diff --git a/apps/red-ui/src/app/modules/admin/admin-routing.module.ts b/apps/red-ui/src/app/modules/admin/admin-routing.module.ts index 17b960c77..4abb5739d 100644 --- a/apps/red-ui/src/app/modules/admin/admin-routing.module.ts +++ b/apps/red-ui/src/app/modules/admin/admin-routing.module.ts @@ -17,7 +17,7 @@ import { templateExistsWhenEnteringAdmin } from '@guards/dossier-template-exists import { entityExistsGuard } from '@guards/entity-exists-guard.service'; import { BaseEntityScreenComponent } from './base-entity-screen/base-entity-screen.component'; import { PermissionsGuard } from '@guards/permissions-guard'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; const dossierTemplateIdRoutes: IqserRoutes = [ { @@ -54,7 +54,7 @@ const dossierTemplateIdRoutes: IqserRoutes = [ data: { routeGuards: [IqserAuthGuard, RedRoleGuard], permissions: { - allow: [ROLES.rules.read], + allow: [Roles.rules.read], redirectTo: 'info', }, }, @@ -82,7 +82,7 @@ const dossierTemplateIdRoutes: IqserRoutes = [ canActivate: [IqserAuthGuard, IqserPermissionsGuard], data: { permissions: { - allow: [ROLES.reportTemplates.read], + allow: [Roles.reportTemplates.read], redirectTo: '/auth-error', }, }, @@ -122,7 +122,7 @@ const dossierTemplateIdRoutes: IqserRoutes = [ canActivate: [IqserPermissionsGuard], data: { permissions: { - allow: [ROLES.legalBasis.read], + allow: [Roles.legalBasis.read], redirectTo: '/auth-error', }, }, @@ -155,7 +155,7 @@ const routes: IqserRoutes = [ routeGuards: [IqserAuthGuard, RedRoleGuard, DossierTemplatesGuard], requiredRoles: ['RED_MANAGER', 'RED_ADMIN'], permissions: { - allow: [ROLES.templates.read], + allow: [Roles.templates.read], redirectTo: '/', }, }, @@ -173,7 +173,7 @@ const routes: IqserRoutes = [ data: { routeGuards: [IqserAuthGuard, RedRoleGuard], permissions: { - allow: [ROLES.users.read, 'RED_USER_ADMIN'], + allow: [Roles.users.read, 'RED_USER_ADMIN'], redirectTo: '/', }, }, @@ -186,7 +186,7 @@ const routes: IqserRoutes = [ routeGuards: [IqserAuthGuard, RedRoleGuard, PermissionsGuard], permissionsObject: 'Dossier', permissions: { - allow: [ROLES.manageAclPermissions, 'RED_ADMIN'], + allow: [Roles.manageAclPermissions, 'RED_ADMIN'], redirectTo: '/', }, }, @@ -198,7 +198,7 @@ const routes: IqserRoutes = [ canActivate: [IqserAuthGuard, IqserPermissionsGuard, RedRoleGuard], data: { permissions: { - allow: [ROLES.license.readReport, 'RED_ADMIN'], + allow: [Roles.license.readReport, 'RED_ADMIN'], redirectTo: '/', }, }, @@ -216,7 +216,7 @@ const routes: IqserRoutes = [ canActivate: [IqserAuthGuard, IqserPermissionsGuard, RedRoleGuard], data: { permissions: { - allow: [ROLES.digitalSignature.read, 'RED_ADMIN'], + allow: [Roles.digitalSignature.read, 'RED_ADMIN'], redirectTo: '/', }, }, @@ -233,7 +233,7 @@ const routes: IqserRoutes = [ canActivate: [IqserAuthGuard, IqserPermissionsGuard, RedRoleGuard], data: { permissions: { - allow: [ROLES.searchAudit, 'RED_ADMIN'], + allow: [Roles.searchAudit, 'RED_ADMIN'], redirectTo: '/', }, }, @@ -252,7 +252,7 @@ const routes: IqserRoutes = [ data: { routeGuards: [IqserAuthGuard, RedRoleGuard], permissions: { - allow: [ROLES.generalConfiguration.read, ROLES.smtp.read, 'RED_ADMIN'], + allow: [Roles.generalConfiguration.read, Roles.smtp.read, 'RED_ADMIN'], redirectTo: '/', }, }, diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-clone-dossier-template-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-clone-dossier-template-dialog.component.ts index 32f7d650c..24a4cb89f 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-clone-dossier-template-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-edit-dossier-template-dialog/add-edit-clone-dossier-template-dialog.component.ts @@ -9,7 +9,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { DossierTemplate, IDossierTemplate } from '@red/domain'; import { HttpStatusCode } from '@angular/common/http'; import dayjs, { Dayjs } from 'dayjs'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; interface EditCloneTemplateData { dossierTemplateId: string; @@ -26,7 +26,7 @@ const downloadTypes = ['ORIGINAL', 'PREVIEW', 'DELTA_PREVIEW', 'REDACTED'].map(t styleUrls: ['./add-edit-clone-dossier-template-dialog.component.scss'], }) export class AddEditCloneDossierTemplateDialogComponent extends BaseDialogComponent { - readonly roles = ROLES; + readonly roles = Roles; hasValidFrom: boolean; hasValidTo: boolean; readonly downloadTypes = downloadTypes; diff --git a/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.ts b/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.ts index a4877078d..b5974388a 100644 --- a/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/dialogs/add-entity-dialog/add-entity-dialog.component.ts @@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, inject, ViewChild } from '@angular/ import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog'; import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-edit-entity.component'; import { BaseDialogComponent, IconButtonTypes } from '@iqser/common-ui'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; interface DialogData { readonly dossierTemplateId: string; @@ -15,7 +15,7 @@ interface DialogData { }) export class AddEntityDialogComponent extends BaseDialogComponent { readonly iconButtonTypes = IconButtonTypes; - readonly roles = ROLES; + readonly roles = Roles; readonly data = inject(MAT_DIALOG_DATA); @ViewChild(AddEditEntityComponent, { static: true }) private readonly _addEditEntityComponent: AddEditEntityComponent; diff --git a/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts index 6197d48b0..37973b4da 100644 --- a/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/audit/audit-screen.component.ts @@ -17,7 +17,7 @@ import { AuditService } from '../../services/audit.service'; import { firstValueFrom } from 'rxjs'; import { Dayjs } from 'dayjs'; import { RouterHistoryService } from '@services/router-history.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { AdminDialogService } from '../../services/admin-dialog.service'; const PAGE_SIZE = 50; @@ -35,7 +35,7 @@ export class AuditScreenComponent extends ListingComponent implements OnI readonly form: UntypedFormGroup = this._getForm(); readonly routerHistoryService = inject(RouterHistoryService); readonly permissionsService = inject(IqserPermissionsService); - readonly roles = ROLES; + readonly roles = Roles; readonly currentUser = getCurrentUser(); categories: string[] = []; diff --git a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts index 841a828a3..f111beede 100644 --- a/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/default-colors/default-colors-screen.component.ts @@ -15,7 +15,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { combineLatest } from 'rxjs'; import { map, tap } from 'rxjs/operators'; import { DefaultColorsService } from '@services/entity-services/default-colors.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; interface ListItem extends IListable { readonly key: string; @@ -31,7 +31,7 @@ interface ListItem extends IListable { export class DefaultColorsScreenComponent extends ListingComponent { readonly circleButtonTypes = CircleButtonTypes; readonly currentUser = getCurrentUser(); - readonly roles = ROLES; + readonly roles = Roles; readonly translations = defaultColorsTranslations; readonly tableHeaderLabel = _('default-colors-screen.table-header.title'); readonly tableColumnConfigs: TableColumnConfig[] = [ diff --git a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts index f53c497d4..9034f49ee 100644 --- a/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/digital-signature/digital-signature-screen.component.ts @@ -8,7 +8,7 @@ import { AdminDialogService } from '../../services/admin-dialog.service'; import { PkcsSignatureConfigurationComponent } from '../../dialogs/configure-digital-signature-dialog/form/pkcs-signature-configuration/pkcs-signature-configuration.component'; import { KmsSignatureConfigurationComponent } from '../../dialogs/configure-digital-signature-dialog/form/kms-signature-configuration/kms-signature-configuration.component'; import { DigitalSignatureOptions, IKmsDigitalSignatureRequest, IPkcsDigitalSignatureRequest, User } from '@red/domain'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ selector: 'redaction-digital-signature-screen', @@ -21,7 +21,7 @@ export class DigitalSignatureScreenComponent implements OnInit { readonly certificateType = DigitalSignatureOptions; readonly iconButtonTypes = IconButtonTypes; - readonly roles = ROLES; + readonly roles = Roles; readonly currentUser = getCurrentUser(); digitalSignature: IPkcsDigitalSignatureRequest | IKmsDigitalSignatureRequest; diff --git a/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing-screen/dossier-templates-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing-screen/dossier-templates-listing-screen.component.ts index 0e9f8d21e..9ac11e170 100644 --- a/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing-screen/dossier-templates-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/dossier-templates-listing/dossier-templates-listing-screen/dossier-templates-listing-screen.component.ts @@ -16,7 +16,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { RouterHistoryService } from '@services/router-history.service'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { firstValueFrom } from 'rxjs'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ templateUrl: './dossier-templates-listing-screen.component.html', @@ -30,7 +30,7 @@ import { ROLES } from '@users/roles'; export class DossierTemplatesListingScreenComponent extends ListingComponent { readonly iconButtonTypes = IconButtonTypes; readonly circleButtonTypes = CircleButtonTypes; - readonly roles = ROLES; + readonly roles = Roles; readonly currentUser = getCurrentUser(); readonly tableHeaderLabel = _('dossier-templates-listing.table-header.title'); readonly tableColumnConfigs: TableColumnConfig[] = [ diff --git a/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts index 4b4441d82..ef7f9e7ba 100644 --- a/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/entities/screens/dictionary/dictionary-screen.component.ts @@ -6,7 +6,7 @@ import { getCurrentUser, getParam, IqserPermissionsService, List, LoadingService import { BehaviorSubject } from 'rxjs'; import { DICTIONARY_TO_ENTRY_TYPE_MAP, DICTIONARY_TYPE_KEY_MAP, DictionaryType, DOSSIER_TEMPLATE_ID, ENTITY_TYPE, User } from '@red/domain'; import { PermissionsService } from '@services/permissions.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { NGXLogger } from 'ngx-logger'; @Component({ @@ -16,7 +16,7 @@ import { NGXLogger } from 'ngx-logger'; }) export class DictionaryScreenComponent implements OnInit { readonly currentUser = getCurrentUser(); - readonly roles = ROLES; + readonly roles = Roles; readonly initialEntries$ = new BehaviorSubject([]); isLeavingPage = false; readonly type: DictionaryType; diff --git a/apps/red-ui/src/app/modules/admin/screens/entities/screens/entity-info/entity-info.component.ts b/apps/red-ui/src/app/modules/admin/screens/entities/screens/entity-info/entity-info.component.ts index 69d38b00c..8c123a20d 100644 --- a/apps/red-ui/src/app/modules/admin/screens/entities/screens/entity-info/entity-info.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/entities/screens/entity-info/entity-info.component.ts @@ -7,7 +7,7 @@ import { PermissionsService } from '@services/permissions.service'; import { AddEditEntityComponent } from '@shared/components/add-edit-entity/add-edit-entity.component'; import { IconButtonTypes, IqserEventTarget } from '@iqser/common-ui'; import { Observable } from 'rxjs'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ selector: 'redaction-entity-info', @@ -19,7 +19,7 @@ export class EntityInfoComponent { readonly currentUser = getCurrentUser(); readonly entity$: Observable; readonly dossierTemplateId: string; - readonly roles = ROLES; + readonly roles = Roles; readonly iconButtonTypes = IconButtonTypes; @ViewChild(AddEditEntityComponent) private readonly _addEditEntityComponent: AddEditEntityComponent; diff --git a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts index b6f5b6363..feed67329 100644 --- a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/add-edit-file-attribute-dialog/add-edit-file-attribute-dialog.component.ts @@ -10,7 +10,7 @@ import { MatSelectModule } from '@angular/material/select'; import { NgForOf } from '@angular/common'; import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatTooltipModule } from '@angular/material/tooltip'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { MatSlideToggleModule } from '@angular/material/slide-toggle'; export interface AddEditFileAttributeDialogData { @@ -40,7 +40,7 @@ export interface AddEditFileAttributeDialogData { ], }) export class AddEditFileAttributeDialogComponent extends BaseDialogComponent { - readonly roles = ROLES; + readonly roles = Roles; readonly DISPLAYED_FILTERABLE_LIMIT = 3; readonly translations = fileAttributeTypesTranslations; readonly fileAttribute = this.data.fileAttribute; diff --git a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts index 6ff7e657b..32b44d964 100644 --- a/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/file-attributes-listing/file-attributes-listing-screen.component.ts @@ -21,7 +21,7 @@ import { HttpStatusCode } from '@angular/common/http'; import { firstValueFrom } from 'rxjs'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { PermissionsService } from '@services/permissions.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { MatDialog } from '@angular/material/dialog'; import { AddEditFileAttributeDialogComponent, @@ -58,7 +58,7 @@ export class FileAttributesListingScreenComponent extends ListingComponent; #existingConfiguration: IFileAttributesConfig; @ViewChild('fileInput') private _fileInput: ElementRef; diff --git a/apps/red-ui/src/app/modules/admin/screens/general-config/general-config-form/general-config-form.component.ts b/apps/red-ui/src/app/modules/admin/screens/general-config/general-config-form/general-config-form.component.ts index 216cebe57..f235e191a 100644 --- a/apps/red-ui/src/app/modules/admin/screens/general-config/general-config-form/general-config-form.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/general-config/general-config-form/general-config-form.component.ts @@ -5,7 +5,7 @@ import { IGeneralConfiguration } from '@red/domain'; import { ConfigService } from '@services/config.service'; import { UntypedFormBuilder, UntypedFormGroup } from '@angular/forms'; import { firstValueFrom } from 'rxjs'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ selector: 'redaction-general-config-form', @@ -23,7 +23,7 @@ export class GeneralConfigFormComponent extends BaseFormComponent implements OnI ) { super(); this.form = this._getForm(); - if (!_permissionsService.has(ROLES.generalConfiguration.write)) { + if (!_permissionsService.has(Roles.generalConfiguration.write)) { this.form.disable(); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/general-config/smtp-form/smtp-form.component.ts b/apps/red-ui/src/app/modules/admin/screens/general-config/smtp-form/smtp-form.component.ts index e1830a2bf..7be3cd13e 100644 --- a/apps/red-ui/src/app/modules/admin/screens/general-config/smtp-form/smtp-form.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/general-config/smtp-form/smtp-form.component.ts @@ -6,7 +6,7 @@ import { AdminDialogService } from '../../../services/admin-dialog.service'; import { SmtpConfigService } from '../../../services/smtp-config.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { firstValueFrom } from 'rxjs'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ selector: 'redaction-smtp-form', @@ -26,7 +26,7 @@ export class SmtpFormComponent extends BaseFormComponent implements OnInit { ) { super(); this.form = this._getForm(); - if (!_permissionsService.has(ROLES.smtp.write)) { + if (!_permissionsService.has(Roles.smtp.write)) { this.form.disable(); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/general-config/system-preferences-form/system-preferences-form.component.ts b/apps/red-ui/src/app/modules/admin/screens/general-config/system-preferences-form/system-preferences-form.component.ts index b7cd5a4b4..000ac9054 100644 --- a/apps/red-ui/src/app/modules/admin/screens/general-config/system-preferences-form/system-preferences-form.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/general-config/system-preferences-form/system-preferences-form.component.ts @@ -4,7 +4,7 @@ import { SystemPreferences } from '@red/domain'; import { BaseFormComponent, IqserPermissionsService, KeysOf, LoadingService } from '@iqser/common-ui'; import { SystemPreferencesService } from '@services/system-preferences.service'; import { systemPreferencesTranslations } from '@translations/system-preferences-translations'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; export type ValueType = 'number' | 'string' | 'boolean'; @@ -30,7 +30,7 @@ export class SystemPreferencesFormComponent extends BaseFormComponent { super(); this.form = this._getForm(); this._loadData(); - if (!_permissionsService.has(ROLES.appConfiguration.write)) { + if (!_permissionsService.has(Roles.appConfiguration.write)) { this.form.disable(); } } diff --git a/apps/red-ui/src/app/modules/admin/screens/license/license-screen/license-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/license/license-screen/license-screen.component.ts index e704a511f..c4609aac6 100644 --- a/apps/red-ui/src/app/modules/admin/screens/license/license-screen/license-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/license/license-screen/license-screen.component.ts @@ -6,7 +6,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { RouterHistoryService } from '@services/router-history.service'; import { LicenseService } from '@services/license.service'; import { map } from 'rxjs/operators'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import type { User } from '@red/domain'; @Component({ @@ -14,7 +14,7 @@ import type { User } from '@red/domain'; styleUrls: ['./license-screen.component.scss'], }) export class LicenseScreenComponent { - readonly roles = ROLES; + readonly roles = Roles; readonly currentUser = getCurrentUser(); readonly currentYear = new Date().getFullYear(); readonly buttonConfigs: readonly ButtonConfig[] = [ @@ -23,7 +23,7 @@ export class LicenseScreenComponent { action: (): void => this.sendMail(), type: IconButtonTypes.primary, helpModeKey: 'license_information', - hide: !this.permissionsService.has(ROLES.license.readReport), + hide: !this.permissionsService.has(Roles.license.readReport), }, ]; diff --git a/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.ts index 5ffd9f7de..c4cc7cb84 100644 --- a/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/permissions/permissions-screen/permissions-screen.component.ts @@ -19,7 +19,7 @@ import { interval, map, Subscription } from 'rxjs'; import { switchMap, tap } from 'rxjs/operators'; import { permissionsTranslations } from '@translations/permissions-translations'; import { RouterHistoryService } from '@services/router-history.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ templateUrl: './permissions-screen.component.html', @@ -27,7 +27,7 @@ import { ROLES } from '@users/roles'; providers: listingProvidersFactory(PermissionsScreenComponent), }) export class PermissionsScreenComponent extends ListingComponent implements OnDestroy { - readonly roles = ROLES; + readonly roles = Roles; readonly currentUser = getCurrentUser(); readonly translations = permissionsTranslations; readonly tableColumnConfigs: TableColumnConfig[]; diff --git a/apps/red-ui/src/app/modules/admin/screens/reports/reports-screen/reports-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/reports/reports-screen/reports-screen.component.ts index 5c59fa254..39646ad6e 100644 --- a/apps/red-ui/src/app/modules/admin/screens/reports/reports-screen/reports-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/reports/reports-screen/reports-screen.component.ts @@ -12,7 +12,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { AdminDialogService } from '../../../services/admin-dialog.service'; import { ReportTemplateService } from '@services/report-template.service'; import { BehaviorSubject, firstValueFrom } from 'rxjs'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; interface Placeholder { placeholder: string; @@ -33,7 +33,7 @@ export class ReportsScreenComponent implements OnInit { readonly placeholders$ = new BehaviorSubject([]); readonly availableTemplates$ = new BehaviorSubject([]); readonly currentUser = getCurrentUser(); - readonly roles = ROLES; + readonly roles = Roles; @ViewChild('fileInput') private readonly _fileInput: ElementRef; readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); diff --git a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts index f44870d34..7ab70f3bf 100644 --- a/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/user-listing/user-listing-screen.component.ts @@ -12,7 +12,6 @@ import { listingProvidersFactory, LoadingService, NestedFilter, - OverlappingElements, SearchPositions, TableColumnConfig, } from '@iqser/common-ui'; @@ -22,7 +21,7 @@ import { rolesTranslations } from '@translations/roles-translations'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { userTypeChecker, userTypeFilters } from '../../../../utils'; import { RouterHistoryService } from '@services/router-history.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; function configToFilter({ key, label }: DonutChartConfig) { return new NestedFilter({ @@ -45,7 +44,7 @@ export class UserListingScreenComponent extends ListingComponent implement readonly translations = rolesTranslations; readonly iconButtonTypes = IconButtonTypes; readonly circleButtonTypes = CircleButtonTypes; - readonly roles = ROLES; + readonly roles = Roles; readonly currentUser = this._userService.currentUser; readonly canDeleteSelected$ = this.#canDeleteSelected$; readonly tableHeaderLabel = _('user-listing.table-header.title'); diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts index cbf1c03af..f3c297204 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermark-screen/watermark-screen.component.ts @@ -36,7 +36,7 @@ import { LicenseService } from '@services/license.service'; import { UserPreferenceService } from '@users/user-preference.service'; import { Router } from '@angular/router'; import { WatermarksMapService } from '@services/entity-services/watermarks-map.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { environment } from '@environments/environment'; import { tap } from 'rxjs/operators'; import { watermarkTranslations } from '@translations/watermark-translations'; @@ -143,7 +143,7 @@ export class WatermarkScreenComponent implements OnInit { verticalTextAlignment: [null], }); - if (!this.currentUser.isAdmin || !this.permissionsService.has(ROLES.watermarks.write)) { + if (!this.currentUser.isAdmin || !this.permissionsService.has(Roles.watermarks.write)) { form.disable(); } diff --git a/apps/red-ui/src/app/modules/admin/screens/watermark/watermarks-listing/watermarks-listing-screen.component.ts b/apps/red-ui/src/app/modules/admin/screens/watermark/watermarks-listing/watermarks-listing-screen.component.ts index 86c073f31..b4590f6ea 100644 --- a/apps/red-ui/src/app/modules/admin/screens/watermark/watermarks-listing/watermarks-listing-screen.component.ts +++ b/apps/red-ui/src/app/modules/admin/screens/watermark/watermarks-listing/watermarks-listing-screen.component.ts @@ -17,7 +17,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { WatermarkService } from '@services/entity-services/watermark.service'; import { AdminDialogService } from '../../../services/admin-dialog.service'; import { WatermarksMapService } from '@services/entity-services/watermarks-map.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ templateUrl: './watermarks-listing-screen.component.html', @@ -28,7 +28,7 @@ export class WatermarksListingScreenComponent extends ListingComponent(); - readonly roles = ROLES; + readonly roles = Roles; readonly tableColumnConfigs: TableColumnConfig[] = [ { label: _('watermarks-listing.table-col-names.name'), sortByKey: 'searchKey', width: '2fr' }, { label: _('watermarks-listing.table-col-names.status'), sortByKey: 'enabled', class: 'flex-center' }, diff --git a/apps/red-ui/src/app/modules/admin/shared/components/admin-side-nav/admin-side-nav.component.ts b/apps/red-ui/src/app/modules/admin/shared/components/admin-side-nav/admin-side-nav.component.ts index 6a4fc5df1..8a2fcccea 100644 --- a/apps/red-ui/src/app/modules/admin/shared/components/admin-side-nav/admin-side-nav.component.ts +++ b/apps/red-ui/src/app/modules/admin/shared/components/admin-side-nav/admin-side-nav.component.ts @@ -4,7 +4,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { adminSideNavTranslations } from '@translations/admin-side-nav-translations'; import { ActivatedRoute, RouterLink, RouterLinkActive } from '@angular/router'; import { AdminSideNavType, AdminSideNavTypes, DOSSIER_TEMPLATE_ID, ENTITY_TYPE, User, WATERMARK_ID } from '@red/domain'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { getCurrentUser, IqserHelpModeModule, IqserPermissionsService, SideNavComponent, TenantPipe } from '@iqser/common-ui'; import { TranslateModule } from '@ngx-translate/core'; import { NgForOf, NgIf } from '@angular/common'; @@ -28,7 +28,7 @@ export class AdminSideNavComponent implements OnInit { @Input() disabledItems: string[] = []; readonly translations = adminSideNavTranslations; readonly currentUser = getCurrentUser(); - readonly roles = ROLES; + readonly roles = Roles; prefix: string; readonly items: { readonly [key in AdminSideNavType]: NavItem[] } = { @@ -36,43 +36,43 @@ export class AdminSideNavComponent implements OnInit { { screen: 'dossier-templates', label: _('admin-side-nav.dossier-templates'), - show: (this.currentUser.isManager || this.currentUser.isAdmin) && this._permissionsService.has(ROLES.templates.read), + show: (this.currentUser.isManager || this.currentUser.isAdmin) && this._permissionsService.has(Roles.templates.read), helpModeKey: 'dossier_templates', }, { screen: 'digital-signature', label: _('admin-side-nav.digital-signature'), - show: this.currentUser.isAdmin && this._permissionsService.has(ROLES.digitalSignature.read), + show: this.currentUser.isAdmin && this._permissionsService.has(Roles.digitalSignature.read), helpModeKey: 'digital_signature', }, { screen: 'license-info', label: _('admin-side-nav.license-information'), - show: this.currentUser.isAdmin && this._permissionsService.has(ROLES.license.readReport), + show: this.currentUser.isAdmin && this._permissionsService.has(Roles.license.readReport), helpModeKey: 'license_information', }, { screen: 'audit', label: _('admin-side-nav.audit'), - show: this.currentUser.isAdmin && this._permissionsService.has(ROLES.searchAudit), + show: this.currentUser.isAdmin && this._permissionsService.has(Roles.searchAudit), helpModeKey: 'audit', }, { screen: 'users', label: _('admin-side-nav.user-management'), - show: this.currentUser.isUserAdmin && this._permissionsService.has(ROLES.users.read), + show: this.currentUser.isUserAdmin && this._permissionsService.has(Roles.users.read), helpModeKey: 'user_management', }, { screen: 'dossier-permissions', label: _('dossier-permissions'), - show: this.currentUser.isAdmin && this._permissionsService.has(ROLES.manageAclPermissions), + show: this.currentUser.isAdmin && this._permissionsService.has(Roles.manageAclPermissions), helpModeKey: 'dossier_permissions', }, { screen: 'general-config', label: _('admin-side-nav.configurations'), - show: this.currentUser.isAdmin && this._permissionsService.has([ROLES.generalConfiguration.read, ROLES.smtp.read]), + show: this.currentUser.isAdmin && this._permissionsService.has([Roles.generalConfiguration.read, Roles.smtp.read]), helpModeKey: 'configurations', }, ], @@ -92,7 +92,7 @@ export class AdminSideNavComponent implements OnInit { { screen: 'rules', label: _('admin-side-nav.rule-editor'), - show: this.userPreferenceService.areDevFeaturesEnabled && this._permissionsService.has(ROLES.rules.read), + show: this.userPreferenceService.areDevFeaturesEnabled && this._permissionsService.has(Roles.rules.read), }, { screen: 'default-colors', @@ -127,13 +127,13 @@ export class AdminSideNavComponent implements OnInit { { screen: 'reports', label: _('admin-side-nav.reports'), - show: this._permissionsService.has([ROLES.reportTemplates.read]), + show: this._permissionsService.has([Roles.reportTemplates.read]), helpModeKey: 'reports', }, { screen: 'justifications', label: _('admin-side-nav.justifications'), - show: this._permissionsService.has([ROLES.legalBasis.read]), + show: this._permissionsService.has([Roles.legalBasis.read]), helpModeKey: 'justifications', }, ], diff --git a/apps/red-ui/src/app/modules/dashboard/components/template-stats/template-stats.component.ts b/apps/red-ui/src/app/modules/dashboard/components/template-stats/template-stats.component.ts index bb83e1846..ab68ec944 100644 --- a/apps/red-ui/src/app/modules/dashboard/components/template-stats/template-stats.component.ts +++ b/apps/red-ui/src/app/modules/dashboard/components/template-stats/template-stats.component.ts @@ -3,7 +3,7 @@ import { DashboardStats } from '@red/domain'; import { IconButtonTypes } from '@iqser/common-ui'; import { TranslateChartService } from '@services/translate-chart.service'; import { SharedDialogService } from '@shared/services/dialog.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { PermissionsService } from '@services/permissions.service'; @Component({ @@ -13,7 +13,7 @@ import { PermissionsService } from '@services/permissions.service'; }) export class TemplateStatsComponent { readonly iconButtonTypes = IconButtonTypes; - readonly roles = ROLES; + readonly roles = Roles; @Input() stats: DashboardStats; diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts index 422309a48..4b04618b6 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/components/dossier-details/dossier-details.component.ts @@ -30,7 +30,7 @@ import { DossierStatsService } from '@services/dossiers/dossier-stats.service'; import { map, tap } from 'rxjs/operators'; import { DossiersService } from '@services/dossiers/dossiers.service'; import { FilesMapService } from '@services/files/files-map.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; interface DossierDetailsContext { needsWorkFilters: INestedFilter[] | undefined; @@ -49,7 +49,7 @@ export class DossierDetailsComponent extends ContextComponent(); readonly collapseTooltip = _('dossier-details.collapse'); readonly expandTooltip = _('dossier-details.expand'); diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts index 53935da38..138bf667c 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/components/screen-header/dossier-overview-screen-header.component.ts @@ -21,7 +21,7 @@ import { UserService } from '@users/user.service'; import { ConfigService } from '../../config.service'; import { PrimaryFileAttributeService } from '@services/primary-file-attribute.service'; import { Router } from '@angular/router'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ selector: 'redaction-dossier-overview-screen-header [dossier] [upload]', @@ -31,7 +31,7 @@ export class DossierOverviewScreenHeaderComponent implements OnInit { @Input() dossier: Dossier; @Output() readonly upload = new EventEmitter(); readonly circleButtonTypes = CircleButtonTypes; - readonly roles = ROLES; + readonly roles = Roles; actionConfigs: List; readonly downloadBtnDisabled$: Observable; diff --git a/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-attribute/file-attribute.component.ts b/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-attribute/file-attribute.component.ts index b4e1b40b4..3d297ac4c 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-attribute/file-attribute.component.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/components/table-item/file-attribute/file-attribute.component.ts @@ -1,4 +1,4 @@ -import { Component, HostListener, Input, OnDestroy, OnInit } from '@angular/core'; +import { Component, HostListener, Input, OnDestroy } from '@angular/core'; import { Dossier, File, FileAttributeConfigTypes, IFileAttributeConfig } from '@red/domain'; import { BaseFormComponent, HelpModeService, ListingService, Toaster } from '@iqser/common-ui'; import { PermissionsService } from '@services/permissions.service'; @@ -76,7 +76,7 @@ export class FileAttributeComponent extends BaseFormComponent implements OnDestr await firstValueFrom( this.fileAttributesService.setFileAttributes({ attributeIdToValue }, this.file.dossierId, this.file.fileId), ); - await firstValueFrom(this._filesService.reload(this.file.dossierId, this.file)); + await this._filesService.reload(this.file.dossierId, this.file); this.initialFormValue = rawFormValue; this._toaster.success(_('file-attribute.update.success')); } catch (e) { diff --git a/apps/red-ui/src/app/modules/dossier-overview/config.service.ts b/apps/red-ui/src/app/modules/dossier-overview/config.service.ts index 8e086002d..73f3dc512 100644 --- a/apps/red-ui/src/app/modules/dossier-overview/config.service.ts +++ b/apps/red-ui/src/app/modules/dossier-overview/config.service.ts @@ -12,7 +12,6 @@ import { ListingMode, ListingModes, NestedFilter, - OverlappingElements, TableColumnConfig, WorkflowColumn, WorkflowConfig, @@ -46,7 +45,7 @@ import { map } from 'rxjs/operators'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { UserPreferenceService } from '@users/user-preference.service'; import { DossiersService } from '@services/dossiers/dossiers.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Injectable() export class ConfigService { @@ -160,7 +159,7 @@ export class ConfigService { label: this._translateService.instant('dossier-overview.header-actions.edit'), action: () => this._openEditDossierDialog(dossierId), icon: 'iqser:edit', - hide: !this.#currentUser.isManager && !this._iqserPermissionsService.has(ROLES.dossiers.edit), + hide: !this.#currentUser.isManager && !this._iqserPermissionsService.has(Roles.dossiers.edit), helpModeKey: 'edit_dossier_in_dossier', disabled$, }, diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts index 29d7c3a92..14931ac74 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-actions/annotation-actions.component.ts @@ -9,7 +9,7 @@ import { FilePreviewStateService } from '../../services/file-preview-state.servi import { HelpModeService, IqserPermissionsService, shareLast } from '@iqser/common-ui'; import { ViewModeService } from '../../services/view-mode.service'; import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { map } from 'rxjs'; export const AnnotationButtonTypes = { @@ -30,7 +30,7 @@ export class AnnotationActionsComponent implements OnChanges { @Input() canPerformAnnotationActions: boolean; @Input() alwaysVisible: boolean; annotationPermissions: AnnotationPermissions; - readonly roles = ROLES; + readonly roles = Roles; isImage = true; diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts index d32a7c768..8fb71348f 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-card/annotation-card.component.ts @@ -2,7 +2,7 @@ import { Component, Input } from '@angular/core'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { MultiSelectService } from '../../services/multi-select.service'; import { annotationTypesTranslations } from '@translations/annotation-types-translations'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ selector: 'redaction-annotation-card', @@ -10,7 +10,7 @@ import { ROLES } from '@users/roles'; styleUrls: ['./annotation-card.component.scss'], }) export class AnnotationCardComponent { - readonly roles = ROLES; + readonly roles = Roles; readonly annotationTypesTranslations = annotationTypesTranslations; @Input() annotation: AnnotationWrapper; @Input() isSelected = false; diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-references-list/annotation-references-list.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotation-references-list/annotation-references-list.component.html index ad8059702..35788aec1 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-references-list/annotation-references-list.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-references-list/annotation-references-list.component.html @@ -1,4 +1,4 @@ -
+
@@ -7,7 +7,7 @@
-
+
diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotation-references-list/annotation-references-list.component.ts b/apps/red-ui/src/app/modules/file-preview/components/annotation-references-list/annotation-references-list.component.ts index 08dfaaf16..85abfc36b 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotation-references-list/annotation-references-list.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/annotation-references-list/annotation-references-list.component.ts @@ -4,6 +4,7 @@ import { AnnotationReferencesService } from '../../services/annotation-reference import { Observable, switchMap } from 'rxjs'; import { AnnotationsListingService } from '../../services/annotations-listing.service'; import { filter } from 'rxjs/operators'; +import { toObservable } from '@angular/core/rxjs-interop'; @Component({ selector: 'redaction-annotation-references-list', @@ -13,12 +14,13 @@ import { filter } from 'rxjs/operators'; export class AnnotationReferencesListComponent { @Output() readonly referenceClicked = new EventEmitter(); readonly isSelected$: Observable; + readonly annotation$ = toObservable(this.annotationReferencesService.annotation); constructor( private readonly _listingService: AnnotationsListingService, readonly annotationReferencesService: AnnotationReferencesService, ) { - this.isSelected$ = this.annotationReferencesService.annotation$.pipe( + this.isSelected$ = this.annotation$.pipe( filter(annotation => !!annotation), switchMap(annotation => this._listingService.isSelected$(annotation)), ); diff --git a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.html b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.html index ac61e425b..c853de2dc 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/annotations-list/annotations-list.component.html @@ -11,5 +11,5 @@ diff --git a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html index 2bec686eb..c9e06db24 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/comments/comments.component.html @@ -9,7 +9,7 @@
impleme private readonly _commentingService: CommentingService, private readonly _loadingService: LoadingService, private readonly _changeRef: ChangeDetectorRef, - private readonly _stateService: FilePreviewStateService, + protected readonly _state: FilePreviewStateService, ) { super(); } @@ -47,8 +46,7 @@ export class CommentsComponent extends ContextComponent impleme ); super._initContext({ - file: this._stateService.file$, - dossier: this._stateService.dossier$, + dossier: this._state.dossier$, hiddenComments: this.hiddenComments$, }); } @@ -58,7 +56,7 @@ export class CommentsComponent extends ContextComponent impleme return; } this._loadingService.start(); - const { dossierId, fileId } = this._stateService; + const { dossierId, fileId } = this._state; const commentId = await this._manualRedactionService.addComment(value, this.annotation.id, dossierId, fileId); this.annotation.comments.push({ text: value, @@ -77,7 +75,7 @@ export class CommentsComponent extends ContextComponent impleme async deleteComment(comment: IComment): Promise { this._loadingService.start(); - const { dossierId, fileId } = this._stateService; + const { dossierId, fileId } = this._state; await this._manualRedactionService.deleteComment(comment.id, this.annotation.id, dossierId, fileId); this.annotation.comments.splice(this.annotation.comments.indexOf(comment), 1); this._changeRef.markForCheck(); diff --git a/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.html b/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.html index 7ae8d0496..a937e9d58 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.html @@ -2,18 +2,18 @@
@@ -38,10 +38,10 @@
- {{ 'file-preview.tabs.document-info.details.pages' | translate : { pages: ctx.file.numberOfPages } }} + {{ 'file-preview.tabs.document-info.details.pages' | translate : { pages: _state.file().numberOfPages } }}
-
+
diff --git a/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.ts b/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.ts index 9328d3a55..34fe6a665 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/document-info/document-info.component.ts @@ -1,11 +1,11 @@ -import { Component } from '@angular/core'; +import { Component, inject } from '@angular/core'; import { DossierTemplatesService } from '@services/dossier-templates/dossier-templates.service'; import { DocumentInfoService } from '../../services/document-info.service'; import { combineLatest, switchMap } from 'rxjs'; import { PermissionsService } from '@services/permissions.service'; import { FilePreviewStateService } from '../../services/file-preview-state.service'; import { map } from 'rxjs/operators'; -import { type Dossier, type File, type FileAttributeConfigType, FileAttributeConfigTypes } from '@red/domain'; +import { type Dossier, type FileAttributeConfigType, FileAttributeConfigTypes } from '@red/domain'; import { FilePreviewDialogService } from '../../services/file-preview-dialog.service'; import { FileAttributesService } from '@services/entity-services/file-attributes.service'; import { ContextComponent } from '@iqser/common-ui'; @@ -17,7 +17,6 @@ interface FileAttribute { } interface Context { - readonly file: File; readonly dossier: Dossier; readonly dossierTemplateName: string; readonly fileAttributes: FileAttribute[]; @@ -29,8 +28,9 @@ interface Context { styleUrls: ['./document-info.component.scss'], }) export class DocumentInfoComponent extends ContextComponent { + protected readonly _state = inject(FilePreviewStateService); + constructor( - state: FilePreviewStateService, fileAttributesService: FileAttributesService, readonly permissionsService: PermissionsService, readonly documentInfoService: DocumentInfoService, @@ -38,25 +38,24 @@ export class DocumentInfoComponent extends ContextComponent { private readonly _dossierTemplatesService: DossierTemplatesService, ) { super(); - const fileAttributes$ = combineLatest([state.file$, state.dossier$, fileAttributesService.fileAttributesConfig$]).pipe( + const fileAttributes$ = combineLatest([this._state.file$, this._state.dossier$, fileAttributesService.fileAttributesConfig$]).pipe( switchMap(([file, dossier]) => this.documentInfoService.fileAttributes$(file.id, dossier.id, dossier.dossierTemplateId)), ); - const dossierTemplateName$ = state.dossier$.pipe( + const dossierTemplateName$ = this._state.dossier$.pipe( switchMap(dossier => this._dossierTemplatesService.getEntityChanged$(dossier.dossierTemplateId)), map(dossierTemplate => dossierTemplate.name), ); super._initContext({ - file: state.file$, - dossier: state.dossier$, + dossier: this._state.dossier$, dossierTemplateName: dossierTemplateName$, fileAttributes: fileAttributes$, }); } - edit(file: File) { - this._dialogService.openDialog('documentInfo', file); + edit() { + this._dialogService.openDialog('documentInfo', this._state.file()); } isDate(attribute: FileAttribute) { diff --git a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts index 9a5847844..35155252d 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/file-workload/file-workload.component.ts @@ -275,7 +275,7 @@ export class FileWorkloadComponent extends AutoUnsubscribe implements OnDestroy } scrollQuickNavLast() { - this.pdf.navigateTo(this.state.file.numberOfPages); + this.pdf.navigateTo(this.state.file().numberOfPages); } preventKeyDefault($event: KeyboardEvent): void { diff --git a/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.ts b/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.ts index 531e7ec32..3b4fd1418 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/highlights-separator/highlights-separator.component.ts @@ -6,7 +6,7 @@ import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { FilePreviewDialogService } from '../../services/file-preview-dialog.service'; import { FileDataService } from '../../services/file-data.service'; import { MultiSelectService } from '../../services/multi-select.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ selector: 'redaction-highlights-separator [highlightGroup] [annotation]', @@ -20,7 +20,7 @@ export class HighlightsSeparatorComponent { readonly circleButtonTypes = CircleButtonTypes; readonly isWritable$ = this._state.isWritable$; readonly multiSelectInactive$ = this._multiSelectService.inactive$; - readonly roles = ROLES; + readonly roles = Roles; constructor( private readonly _dialogService: FilePreviewDialogService, diff --git a/apps/red-ui/src/app/modules/file-preview/components/page-exclusion/page-exclusion.component.ts b/apps/red-ui/src/app/modules/file-preview/components/page-exclusion/page-exclusion.component.ts index 1bccd02a6..cf6ae6609 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/page-exclusion/page-exclusion.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/page-exclusion/page-exclusion.component.ts @@ -5,7 +5,7 @@ import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { IPageRange } from '@red/domain'; import { ReanalysisService } from '@services/reanalysis.service'; import { ExcludedPagesService } from '../../services/excluded-pages.service'; -import { combineLatest, firstValueFrom, Observable } from 'rxjs'; +import { combineLatest, Observable } from 'rxjs'; import { FilePreviewStateService } from '../../services/file-preview-state.service'; import { map } from 'rxjs/operators'; import { extractPageRanges } from '@utils/page-ranges-mapper'; @@ -53,11 +53,10 @@ export class PageExclusionComponent { async excludePagesRange(inputValue: string): Promise { this._loadingService.start(); - const file = this._state.file; + const file = this._state.file(); try { const pageRanges = extractPageRanges(inputValue, file); - const excludePages$ = this._reanalysisService.excludePages({ pageRanges }, file.dossierId, file); - await firstValueFrom(excludePages$); + await this._reanalysisService.excludePages({ pageRanges }, file); this._inputComponent.reset(); } catch (e) { this._toaster.error(_('file-preview.tabs.exclude-pages.error')); @@ -67,15 +66,7 @@ export class PageExclusionComponent { async includePagesRange(range: IPageRange): Promise { this._loadingService.start(); - const file = this._state.file; - const includePages$ = this._reanalysisService.includePages( - { - pageRanges: [range], - }, - file.dossierId, - file, - ); - await firstValueFrom(includePages$); + await this._reanalysisService.includePages({ pageRanges: [range] }, this._state.file()); this._inputComponent.reset(); this._loadingService.stop(); } diff --git a/apps/red-ui/src/app/modules/file-preview/components/page-indicator/page-indicator.component.ts b/apps/red-ui/src/app/modules/file-preview/components/page-indicator/page-indicator.component.ts index 505ccaaa9..41d14a15b 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/page-indicator/page-indicator.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/page-indicator/page-indicator.component.ts @@ -62,7 +62,7 @@ export class PageIndicatorComponent extends ContextComponent annotation.manual); - return hasOnlyManualRedactions && this.#state.file.excludedPages.includes(pageNumber); + return hasOnlyManualRedactions && this.#state.file().excludedPages.includes(pageNumber); } getViewedPage(viewedPages: ViewedPage[], pageNumber: number) { diff --git a/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.html b/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.html index 0236cd2fb..f07a84b74 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.html +++ b/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.html @@ -1,51 +1,49 @@ - + + +
+
-
- -
+
+ +
-
- -
- -
- -
-
+
+ +
diff --git a/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts b/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts index d17fbd564..a79ec3af4 100644 --- a/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/components/view-switch/view-switch.component.ts @@ -1,15 +1,13 @@ -import { Component, Inject } from '@angular/core'; +import { Component, computed, Inject } from '@angular/core'; import { ViewMode, ViewModes } from '@red/domain'; import { ViewModeService } from '../../services/view-mode.service'; import { FilePreviewStateService } from '../../services/file-preview-state.service'; -import { combineLatest, Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; import { FileDataService } from '../../services/file-data.service'; import { BASE_HREF, ConfirmOptions, IConfirmationDialogData, Toaster } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { UserPreferenceService } from '@users/user-preference.service'; import { FilePreviewDialogService } from '../../services/file-preview-dialog.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ selector: 'redaction-view-switch', @@ -17,32 +15,32 @@ import { ROLES } from '@users/roles'; styleUrls: ['./view-switch.component.scss'], }) export class ViewSwitchComponent { + readonly roles = Roles; readonly viewModes = ViewModes; - readonly canSwitchToDeltaView$: Observable; - readonly canSwitchToRedactedView$: Observable; - readonly canSwitchToEarmarksView$: Observable; - readonly roles = ROLES; + readonly canSwitchToDeltaView = computed(() => { + const annotations = this._fileDataService.annotations(); + const file = this._state.file(); + const hasChangeLog = annotations.some(a => a.isChangeLogEntry); + return hasChangeLog && !file.isApproved; + }); + readonly canSwitchToRedactedView = computed(() => { + const file = this._state.file(); + return !file.analysisRequired && !file.excluded; + }); + readonly canSwitchToEarmarksView = computed(() => { + const file = this._state.file(); + return file.hasHighlights && !file.analysisRequired && !file.excluded; + }); constructor( @Inject(BASE_HREF) private readonly _baseHref: string, readonly viewModeService: ViewModeService, - private readonly _stateService: FilePreviewStateService, + private readonly _state: FilePreviewStateService, private readonly _fileDataService: FileDataService, private readonly _userPreferenceService: UserPreferenceService, private readonly _dialogService: FilePreviewDialogService, private readonly _toaster: Toaster, - ) { - const hasChangeLog$ = this._fileDataService.annotations$.pipe(map(annotations => annotations.some(a => a.isChangeLogEntry))); - this.canSwitchToDeltaView$ = combineLatest([hasChangeLog$, _stateService.file$]).pipe( - map(([hasChangeLog, file]) => hasChangeLog && !file.isApproved), - ); - - this.canSwitchToRedactedView$ = _stateService.file$.pipe(map(file => !file.analysisRequired && !file.excluded)); - - this.canSwitchToEarmarksView$ = _stateService.file$.pipe( - map(file => file.hasHighlights && !file.analysisRequired && !file.excluded), - ); - } + ) {} switchView(viewMode: ViewMode) { if (viewMode === ViewModes.REDACTED) { @@ -57,7 +55,7 @@ export class ViewSwitchComponent { return this.viewModeService.switchToRedacted(); } - const suggestions = (await this._fileDataService.annotations).filter(a => a.isSuggestion); + const suggestions = this._fileDataService.annotations().filter(a => a.isSuggestion); if (!suggestions.length) { return this.viewModeService.switchToRedacted(); } diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/document-info-dialog/document-info-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/document-info-dialog/document-info-dialog.component.ts index 642ca91e3..a2c6e5484 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/document-info-dialog/document-info-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/document-info-dialog/document-info-dialog.component.ts @@ -43,7 +43,7 @@ export class DocumentInfoDialogComponent extends BaseDialogComponent implements ...this._mapFormValues(this.form.getRawValue()), }; await firstValueFrom(this._fileAttributesService.setFileAttributes({ attributeIdToValue }, this.file.dossierId, this.file.fileId)); - await firstValueFrom(this._filesService.reload(this.file.dossierId, this.file)); + await this._filesService.reload(this.file.dossierId, this.file); this._dialogRef.close(true); } diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/highlight-action-dialog/highlight-action-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/highlight-action-dialog/highlight-action-dialog.component.ts index 85c2297be..ba03c74e4 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/highlight-action-dialog/highlight-action-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/highlight-action-dialog/highlight-action-dialog.component.ts @@ -7,7 +7,7 @@ import { EarmarksService } from '@services/files/earmarks.service'; import { firstValueFrom } from 'rxjs'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; import { highlightsTranslations } from '@translations/highlights-translations'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; export interface HighlightActionData { readonly operation: EarmarkOperation; @@ -24,7 +24,7 @@ export interface HighlightActionData { }) export class HighlightActionDialogComponent extends BaseDialogComponent { readonly translations = highlightsTranslations; - readonly roles = ROLES; + readonly roles = Roles; readonly #operation = this.data.operation; readonly options: DetailsRadioOption[] = [ { diff --git a/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts b/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts index 69fd16aa3..783741417 100644 --- a/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/dialogs/manual-redaction-dialog/manual-annotation-dialog.component.ts @@ -10,7 +10,7 @@ import { BaseDialogComponent, CircleButtonTypes, IqserPermissionsService } from import { firstValueFrom } from 'rxjs'; import { ManualRedactionService } from '../../services/manual-redaction.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; export interface LegalBasisOption { label?: string; @@ -23,7 +23,7 @@ export interface LegalBasisOption { styleUrls: ['./manual-annotation-dialog.component.scss'], }) export class ManualAnnotationDialogComponent extends BaseDialogComponent implements OnInit { - readonly roles = ROLES; + readonly roles = Roles; readonly circleButtonTypes = CircleButtonTypes; isDictionaryRequest: boolean; isFalsePositiveRequest: boolean; @@ -172,7 +172,7 @@ export class ManualAnnotationDialogComponent extends BaseDialogComponent impleme addRedactionRequest.legalBasis = legalOption.legalBasis; } - if (this.iqserPermissionsService.has(ROLES.getRss)) { + if (this.iqserPermissionsService.has(Roles.getRss)) { const selectedType = this.possibleDictionaries.find(d => d.type === addRedactionRequest.type); addRedactionRequest.addToDictionary = selectedType.hasDictionary; } else { diff --git a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts index 8c826f479..bb70a9991 100644 --- a/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts +++ b/apps/red-ui/src/app/modules/file-preview/file-preview-screen.component.ts @@ -41,12 +41,12 @@ import { AnnotationDrawService } from '../pdf-viewer/services/annotation-draw.se import { AnnotationProcessingService } from './services/annotation-processing.service'; import { Dictionary, File, ViewModes } from '@red/domain'; import { PermissionsService } from '@services/permissions.service'; -import { combineLatest, firstValueFrom, Observable, of, pairwise } from 'rxjs'; +import { combineLatest, firstValueFrom, of, pairwise } from 'rxjs'; import { PreferencesKeys, UserPreferenceService } from '@users/user-preference.service'; import { byId, byPage, download, handleFilterDelta, hasChanges } from '../../utils'; import { FilesService } from '@services/files/files.service'; import { FileManagementService } from '@services/files/file-management.service'; -import { catchError, filter, map, startWith, switchMap, tap, withLatestFrom } from 'rxjs/operators'; +import { catchError, filter, map, startWith, switchMap, tap } from 'rxjs/operators'; import { FilesMapService } from '@services/files/files-map.service'; import { ViewModeService } from './services/view-mode.service'; import { ReanalysisService } from '@services/reanalysis.service'; @@ -72,7 +72,7 @@ import { AnnotationsListingService } from './services/annotations-listing.servic import { PdfProxyService } from './services/pdf-proxy.service'; import { ConfigService } from '@services/config.service'; import { ReadableRedactionsService } from '../pdf-viewer/services/readable-redactions.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { SuggestionsService } from './services/suggestions.service'; const textActions = [TextPopups.ADD_DICTIONARY, TextPopups.ADD_FALSE_POSITIVE]; @@ -87,7 +87,7 @@ export class FilePreviewScreenComponent implements AfterViewInit, OnInit, OnDestroy, OnAttach, OnDetach, ComponentCanDeactivate { readonly circleButtonTypes = CircleButtonTypes; - readonly roles = ROLES; + readonly roles = Roles; fullScreen = false; readonly fileId = this.state.fileId; readonly dossierId = this.state.dossierId; @@ -176,7 +176,6 @@ export class FilePreviewScreenComponent const earmarks$ = isEarmarksViewMode$.pipe( tap(() => this._loadingService.start()), switchMap(() => this._fileDataService.loadEarmarks()), - switchMap(() => this._fileDataService.earmarks$), tap(() => this.updateViewMode().then(() => this._loadingService.stop())), ); @@ -202,8 +201,8 @@ export class FilePreviewScreenComponent ); return isChangingFromEarmarksViewMode$.pipe( - withLatestFrom(this._fileDataService.earmarks$), - map(([, earmarks]) => this.deleteAnnotations(earmarks.get(this.pdf.currentPage) ?? [], [])), + map(() => this._fileDataService.earmarks().get(this.pdf.currentPage) ?? []), + map(earmarks => this.deleteAnnotations(earmarks, [])), ); } @@ -220,7 +219,7 @@ export class FilePreviewScreenComponent switch (this._viewModeService.viewMode()) { case ViewModes.STANDARD: { - const wrappers = await this._fileDataService.annotations; + const wrappers = this._fileDataService.annotations(); const ocrAnnotationIds = wrappers.filter(a => a.isOCR).map(a => a.id); const standardEntries = annotations .filter(a => !bool(a.getCustomData('changeLogRemoved')) && !this._annotationManager.isHidden(a.Id)) @@ -288,7 +287,7 @@ export class FilePreviewScreenComponent } async ngOnAttach(previousRoute: ActivatedRouteSnapshot) { - if (!this.state.file.canBeOpened) { + if (!this.state.file().canBeOpened) { return this._navigateToDossier(); } @@ -302,7 +301,7 @@ export class FilePreviewScreenComponent } async ngOnInit(): Promise { - const file = this.state.file; + const file = this.state.file(); if (!file) { return this._handleDeletedFile(); @@ -329,7 +328,7 @@ export class FilePreviewScreenComponent openManualAnnotationDialog(manualRedactionEntryWrapper: ManualRedactionEntryWrapper) { return this._ngZone.run(() => { - const file = this.state.file; + const file = this.state.file(); this._dialogService.openDialog( 'manualAnnotation', @@ -403,7 +402,7 @@ export class FilePreviewScreenComponent async viewerReady(pageNumber: string = this._activatedRoute.snapshot.queryParams.page) { if (pageNumber) { - const file = this.state.file; + const file = this.state.file(); let page = parseInt(pageNumber, 10); if (page < 1 || Number.isNaN(page)) { @@ -463,18 +462,22 @@ export class FilePreviewScreenComponent ); const currentPageAnnotations$ = combineLatest([currentPageIfNotHighlightsView$, annotations$]).pipe( + tap(() => console.time('annotation-filter')), map( ([page, [oldAnnotations, newAnnotations]]) => [oldAnnotations.filter(byPage(page)), newAnnotations.filter(byPage(page))] as const, ), + tap(() => console.timeEnd('annotation-filter')), ); return combineLatest([currentPageAnnotations$, documentLoaded$]).pipe( filter(([, loaded]) => loaded), + tap(() => console.time('loadAnnotations')), map(([annotations]) => annotations), switchMap(annotations => this.drawChangedAnnotations(...annotations)), tap(([, newAnnotations]) => this.#highlightSelectedAnnotations(newAnnotations)), tap(() => this.updateViewMode()), + tap(() => console.timeEnd('loadAnnotations')), ); } @@ -622,7 +625,7 @@ export class FilePreviewScreenComponent this.addActiveScreenSubscription = this.state.blob$ .pipe( tap(() => this._errorService.clear()), - switchMap(blob => this.pdf.loadDocument(blob, this.state.file, () => this.state.reloadBlob())), + switchMap(blob => this.pdf.loadDocument(blob, this.state.file(), () => this.state.reloadBlob())), ) .subscribe(); @@ -641,9 +644,9 @@ export class FilePreviewScreenComponent this.addActiveScreenSubscription = this._viewerHeaderService.events$ .pipe( filter(event => event.type === ViewerEvents.LOAD_ALL_ANNOTATIONS), - switchMap(() => this._fileDataService.annotations), - switchMap>(annotations => { + switchMap(() => { // TODO: this switchMap is ugly, to be refactored + const annotations = this._fileDataService.annotations(); const showWarning = !this.userPreferenceService.getBool(PreferencesKeys.loadAllAnnotationsWarning); const annotationsExceedThreshold = annotations.length >= this.configService.values.ANNOTATIONS_THRESHOLD; @@ -749,7 +752,7 @@ export class FilePreviewScreenComponent const secondaryFilters = this._filterService.getGroup('secondaryFilters').filters; const hasAnyFilterSet = [...primaryFilters, ...secondaryFilters].some(f => f.checked || f.indeterminate); const autoExpandFilters = this.userPreferenceService.getAutoExpandFiltersOnActions(); - const isReviewer = this.permissionsService.isFileAssignee(this.state.file); + const isReviewer = this.permissionsService.isFileAssignee(this.state.file()); const shouldExpandFilters = hasAnyFilterSet && autoExpandFilters && isReviewer; if (!shouldExpandFilters) { diff --git a/apps/red-ui/src/app/modules/file-preview/services/annotation-references.service.ts b/apps/red-ui/src/app/modules/file-preview/services/annotation-references.service.ts index b51a47c16..914376c97 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/annotation-references.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/annotation-references.service.ts @@ -1,34 +1,28 @@ -import { Injectable } from '@angular/core'; -import { BehaviorSubject, Observable, switchMap } from 'rxjs'; -import { filterEach, shareDistinctLast } from '@iqser/common-ui'; +import { computed, Injectable, Signal, signal } from '@angular/core'; +import { BehaviorSubject } from 'rxjs'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { filter, map } from 'rxjs/operators'; import { FileDataService } from './file-data.service'; @Injectable() export class AnnotationReferencesService { - readonly annotation$: Observable; - readonly references$: Observable; + readonly references: Signal; + readonly annotation: Signal; private readonly _annotation$ = new BehaviorSubject(undefined); + readonly #annotation = signal(undefined); constructor(private readonly _fileDataService: FileDataService) { - this.annotation$ = this._annotation$.asObservable().pipe(shareDistinctLast()); - this.references$ = this.#references$; - } - - get #references$(): Observable { - const annotations$ = this._fileDataService.annotations$.pipe(map(dict => Object.values(dict))); - return this.annotation$.pipe( - filter(annotation => !!annotation), - switchMap(({ reference }) => annotations$.pipe(filterEach(a => reference.includes(a.id)))), - ); + this.annotation = this.#annotation.asReadonly(); + this.references = computed(() => { + const annotation = this.annotation(); + return annotation ? this._fileDataService.annotations().filter(a => annotation.reference.includes(a.id)) : []; + }); } show(annotation: AnnotationWrapper) { - this._annotation$.next(annotation); + this.#annotation.set(annotation); } hide() { - this._annotation$.next(undefined); + this.#annotation.set(undefined); } } diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts index 38bbc5896..94c9302e6 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-data.service.ts @@ -10,15 +10,14 @@ import { ViewModes, } from '@red/domain'; import { AnnotationWrapper } from '@models/file/annotation.wrapper'; -import { firstValueFrom, Observable, Subject } from 'rxjs'; -import { Injectable, signal } from '@angular/core'; +import { firstValueFrom, Observable } from 'rxjs'; +import { effect, Injectable, Signal, signal } from '@angular/core'; import { FilePreviewStateService } from './file-preview-state.service'; import { ViewedPagesService } from '@services/files/viewed-pages.service'; import { UserPreferenceService } from '@users/user-preference.service'; -import { map, switchMap, tap, withLatestFrom } from 'rxjs/operators'; import { PermissionsService } from '@services/permissions.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; -import { EntitiesService, shareLast, Toaster } from '@iqser/common-ui'; +import { EntitiesService, Toaster } from '@iqser/common-ui'; import { RedactionLogService } from '@services/files/redaction-log.service'; import { EarmarksService } from '@services/files/earmarks.service'; import { ViewModeService } from './view-mode.service'; @@ -30,7 +29,7 @@ import { DefaultColorsService } from '@services/entity-services/default-colors.s import { DictionaryService } from '@services/entity-services/dictionary.service'; import { SuggestionsService } from './suggestions.service'; import { ViewedPagesMapService } from '@services/files/viewed-pages-map.service'; -import { takeUntilDestroyed, toObservable } from '@angular/core/rxjs-interop'; +import { toObservable } from '@angular/core/rxjs-interop'; const DELTA_VIEW_TIME = 10 * 60 * 1000; // 10 minutes; @@ -45,10 +44,11 @@ export function chronologicallyBy(property: (x: T) => string) { @Injectable() export class FileDataService extends EntitiesService { missingTypes = new Set(); + readonly earmarks: Signal>; + readonly annotations: Signal; readonly annotations$: Observable; - readonly earmarks$: Observable>; protected readonly _entityClass = AnnotationWrapper; - readonly #redactionLog$ = new Subject(); + readonly #annotations = signal([]); readonly #earmarks = signal>(new Map()); #originalViewedPages: ViewedPage[] = []; @@ -70,38 +70,15 @@ export class FileDataService extends EntitiesService - viewMode === ViewModes.TEXT_HIGHLIGHTS - ? this.earmarks$.pipe(map(textHighlights => ([] as AnnotationWrapper[]).concat(...textHighlights.values()))) - : this.annotations$.pipe(map(annotations => this.#getVisibleAnnotations(annotations, viewMode))), - ), - tap(annotations => this.setEntities(annotations)), - takeUntilDestroyed(), - ) - .subscribe(); - } - - get annotations() { - return firstValueFrom(this.annotations$); - } - - get #annotations$() { - return this.#redactionLog$.pipe( - tap(() => console.time('buildAnnotations')), - withLatestFrom(this._state.file$), - tap(([redactionLog, file]) => this.#buildRemovedRedactions(redactionLog, file)), - switchMap(([redactionLog, file]) => this.#convertData(redactionLog, file)), - tap(() => this.#checkMissingTypes()), - map(annotations => - this._userPreferenceService.areDevFeaturesEnabled ? annotations : annotations.filter(a => !a.isFalsePositive), - ), - tap(() => console.timeEnd('buildAnnotations')), - shareLast(), - ); + this.annotations$ = toObservable(this.#annotations); + this.annotations = this.#annotations.asReadonly(); + this.earmarks = this.#earmarks.asReadonly(); + effect(() => { + const viewMode = this._viewModeService.viewMode(); + const earmarks = ([] as AnnotationWrapper[]).concat(...this.#earmarks().values()); + const annotations = this.#getVisibleAnnotations(this.#annotations(), viewMode); + this.setEntities(viewMode === ViewModes.TEXT_HIGHLIGHTS ? earmarks : annotations); + }); } setEntities(entities: AnnotationWrapper[]): void { @@ -137,14 +114,14 @@ export class FileDataService extends EntitiesService> { const rawHighlights = await this._earmarksService.getEarmarks(this._state.dossierId, this._state.fileId); const earmarks = rawHighlights.groupBy(h => h.pageNumber); this.#earmarks.set(earmarks); @@ -153,14 +130,14 @@ export class FileDataService extends EntitiesService !a.isFalsePositive); + this.#annotations.set(annotations); } #checkMissingTypes() { @@ -199,7 +176,7 @@ export class FileDataService extends EntitiesService { + async #buildRemovedRedactions(redactionLog: IRedactionLog): Promise { const redactionLogCopy: IRedactionLog = JSON.parse(JSON.stringify(redactionLog)); const redactionLogEntries: IRedactionLogEntry[] = []; @@ -217,15 +194,16 @@ export class FileDataService extends EntitiesService !a.isSkipped); } - async #convertData(redactionLog: IRedactionLog, file: File) { + async #convertData(redactionLog: IRedactionLog) { if (!redactionLog.redactionLogEntry) { return []; } + const file = this._state.file(); const annotations: AnnotationWrapper[] = []; const sourceIds: { [key: string]: AnnotationWrapper[] } = {}; const dictionaries = this._state.dictionaries; diff --git a/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts b/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts index 57c6d331b..e5d46ae68 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/file-preview-state.service.ts @@ -1,4 +1,4 @@ -import { Injectable, Injector } from '@angular/core'; +import { Injectable, Injector, Signal } from '@angular/core'; import { combineLatest, firstValueFrom, from, merge, Observable, of, pairwise, Subject, switchMap } from 'rxjs'; import { Dictionary, Dossier, DOSSIER_ID, DOSSIER_TEMPLATE_ID, File, FILE_ID } from '@red/domain'; import { Router } from '@angular/router'; @@ -14,6 +14,7 @@ import { HttpEvent, HttpEventType, HttpProgressEvent, HttpResponse } from '@angu import { TranslateService } from '@ngx-translate/core'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service'; +import { toSignal } from '@angular/core/rxjs-interop'; const ONE_MEGABYTE = 1024 * 1024; @@ -41,7 +42,7 @@ export class FilePreviewStateService { readonly dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID); readonly fileId = getParam(FILE_ID); dossier: Dossier; - file: File; + readonly file: Signal; readonly dossierDictionary$: Observable; #dossierDictionary: Dictionary; readonly #reloadBlob$ = new Subject(); @@ -66,7 +67,8 @@ export class FilePreviewStateService { ) { const dossiersService = dossiersServiceResolver(_injector, router); this.dossier$ = dossiersService.getEntityChanged$(this.dossierId).pipe(tap(dossier => (this.dossier = dossier))); - this.file$ = _filesMapService.watch$(this.dossierId, this.fileId).pipe(tap(file => (this.file = file))); + this.file$ = _filesMapService.watch$(this.dossierId, this.fileId); + this.file = toSignal(this.file$); // this.file$ = combineLatest([this.isAttached, file$]).pipe( // filter(([isAttached]) => isAttached), // map(([, file]) => file), @@ -157,7 +159,7 @@ export class FilePreviewStateService { const progress = Math.round((event.loaded / event.total) * 100); const loading: string = this._translateService.instant('loading'); this._loadingService.update({ - title: loading + ' ' + this.file.filename, + title: loading + ' ' + this.file().filename, type: 'progress-bar', value: progress, remainingTime: this.#getRemainingTimeVerbose(event, startTime), diff --git a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts index 39ad69d26..0ef6fc812 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/manual-redaction.service.ts @@ -20,7 +20,7 @@ import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { type ManualRedactionEntryType } from '@models/file/manual-redaction-entry.wrapper'; import { NGXLogger } from 'ngx-logger'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { firstValueFrom, of } from 'rxjs'; function getResponseType(error: boolean, isConflict: boolean) { @@ -95,12 +95,12 @@ export class ManualRedactionService extends GenericService { addAnnotation(requests: List, dossierId: string, fileId: string, dictionaryLabel?: string) { const toast = requests[0].addToDictionary ? this.#showAddToDictionaryToast(requests, dictionaryLabel) : this.#showToast('add'); - const canAddRedaction = this._iqaerPermissionsService.has(ROLES.redactions.write); + const canAddRedaction = this._iqaerPermissionsService.has(Roles.redactions.write); if (canAddRedaction && this._permissionsService.isApprover(this.#dossier(dossierId))) { return this.add(requests, dossierId, fileId).pipe(toast); } - const canRequestRedaction = this._iqaerPermissionsService.has(ROLES.redactions.request); + const canRequestRedaction = this._iqaerPermissionsService.has(Roles.redactions.request); if (canRequestRedaction) { return this.requestAdd(requests, dossierId, fileId).pipe(toast); } diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts index 9feac270f..d8cab65ea 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-annotation-actions.service.ts @@ -8,7 +8,7 @@ import { AnnotationActionsService } from './annotation-actions.service'; import { BASE_HREF_FN, IqserPermissionsService } from '@iqser/common-ui'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; import { IHeaderElement } from '@red/domain'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { REDAnnotationManager } from '../../pdf-viewer/services/annotation-manager.service'; @Injectable() @@ -159,7 +159,7 @@ export class PdfAnnotationActionsService { canAcceptRecommendation: permissions.reduce((acc, next) => acc && next.canAcceptRecommendation, true), canAcceptSuggestion: permissions.reduce((acc, next) => acc && next.canAcceptSuggestion, true), canUndo: - this.#iqserPermissionsService.has(ROLES.redactions.deleteManual) && + this.#iqserPermissionsService.has(Roles.redactions.deleteManual) && permissions.reduce((acc, next) => acc && next.canUndo, true), canMarkAsFalsePositive: permissions.reduce((acc, next) => acc && next.canMarkAsFalsePositive, true), canForceRedaction: permissions.reduce((acc, next) => acc && next.canForceRedaction, true), diff --git a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts index d7181a405..11ad5e0dc 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/pdf-proxy.service.ts @@ -33,7 +33,7 @@ import { PermissionsService } from '@services/permissions.service'; import { AnnotationsListingService } from './annotations-listing.service'; import { PdfAnnotationActionsService } from './pdf-annotation-actions.service'; import { DictionariesMapService } from '@services/entity-services/dictionaries-map.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { AnnotationActionsService } from './annotation-actions.service'; import Annotation = Core.Annotations.Annotation; import Quad = Core.Math.Quad; @@ -53,7 +53,7 @@ export class PdfProxyService { readonly #visibilityOffIcon = this._convertPath('/assets/icons/general/visibility-off.svg'); readonly #visibilityIcon = this._convertPath('/assets/icons/general/visibility.svg'); readonly #falsePositiveIcon = this._convertPath('/assets/icons/general/pdftron-action-false-positive.svg'); - readonly #addRedactionIcon = this._iqserPermissionsService.has(ROLES.getRss) + readonly #addRedactionIcon = this._iqserPermissionsService.has(Roles.getRss) ? this._convertPath('/assets/icons/general/pdftron-action-add-component.svg') : this._convertPath('/assets/icons/general/pdftron-action-add-redaction.svg'); readonly #addDictIcon = this._convertPath('/assets/icons/general/pdftron-action-add-dict.svg'); @@ -148,7 +148,7 @@ export class PdfProxyService { private _configureTextPopup() { const popups: IHeaderElement[] = []; - if (!this._state.file.isApproved) { + if (!this._state.file().isApproved) { // Adding directly to the false-positive dict is only available in dev-mode if (this._userPreferenceService.areDevFeaturesEnabled) { popups.push({ @@ -160,7 +160,7 @@ export class PdfProxyService { }); } - if (this._iqserPermissionsService.has(ROLES.redactions.write) || this._iqserPermissionsService.has(ROLES.redactions.request)) { + if (this._iqserPermissionsService.has(Roles.redactions.write) || this._iqserPermissionsService.has(Roles.redactions.request)) { popups.push({ type: 'actionButton', dataElement: TextPopups.ADD_REDACTION, @@ -169,7 +169,7 @@ export class PdfProxyService { onClick: () => this._addManualRedactionOfType(ManualRedactionEntryTypes.REDACTION), }); - if (!this._iqserPermissionsService.has(ROLES.getRss)) { + if (!this._iqserPermissionsService.has(Roles.getRss)) { popups.push({ type: 'actionButton', dataElement: TextPopups.ADD_DICTIONARY, @@ -194,7 +194,7 @@ export class PdfProxyService { } private _handleCustomActions() { - const isCurrentPageExcluded = this._state.file.isPageExcluded(this._pdf.currentPage); + const isCurrentPageExcluded = this._state.file().isPageExcluded(this._pdf.currentPage); if (this._viewModeService.isRedacted()) { this._viewerHeaderService.enable([HeaderElements.TOGGLE_READABLE_REDACTIONS]); diff --git a/apps/red-ui/src/app/modules/file-preview/services/stamp.service.ts b/apps/red-ui/src/app/modules/file-preview/services/stamp.service.ts index deab39e4c..92d6daf91 100644 --- a/apps/red-ui/src/app/modules/file-preview/services/stamp.service.ts +++ b/apps/red-ui/src/app/modules/file-preview/services/stamp.service.ts @@ -29,7 +29,7 @@ export class StampService { return; } - const file = this._state.file; + const file = this._state.file(); const allPages = [...Array(file.numberOfPages).keys()].map(page => page + 1); try { diff --git a/apps/red-ui/src/app/modules/pdf-viewer/services/page-rotation.service.ts b/apps/red-ui/src/app/modules/pdf-viewer/services/page-rotation.service.ts index bd3e17b5d..473072de5 100644 --- a/apps/red-ui/src/app/modules/pdf-viewer/services/page-rotation.service.ts +++ b/apps/red-ui/src/app/modules/pdf-viewer/services/page-rotation.service.ts @@ -2,7 +2,7 @@ import { Injectable, Injector } from '@angular/core'; import { BehaviorSubject, firstValueFrom, Observable, of } from 'rxjs'; import { RotationType } from '@red/domain'; import { FileManagementService } from '@services/files/file-management.service'; -import { distinctUntilChanged, map, switchMap, tap } from 'rxjs/operators'; +import { distinctUntilChanged, map, tap } from 'rxjs/operators'; import { ConfirmationDialogComponent, ConfirmOption, @@ -21,8 +21,8 @@ import { REDDocumentViewer } from './document-viewer.service'; @Injectable() export class PageRotationService { - readonly #rotations$ = new BehaviorSubject>({}); readonly rotations$: Observable>; + readonly #rotations$ = new BehaviorSubject>({}); constructor( private readonly _pdf: PdfViewer, @@ -48,6 +48,10 @@ export class PageRotationService { return Math.abs(rotationsSum < 360 ? rotationsSum : 360 - rotationsSum); } + get #rotations() { + return this.#rotations$.value; + } + isRotated$(page: number) { return this.#rotations$.pipe( map(rotations => !!rotations[page]), @@ -55,7 +59,7 @@ export class PageRotationService { ); } - applyRotation() { + async applyRotation() { this._loadingService.start(); const pages = this.#rotations$.value; const { dossierId, fileId } = this._pdf; @@ -73,9 +77,10 @@ export class PageRotationService { const request$ = this._fileManagementService.rotatePage({ pages }, dossierId, fileId); this.clearRotations(); - const reloaded$ = request$.pipe(switchMap(() => this._filesService.reload(dossierId, file))); + await firstValueFrom(request$); + await this._filesService.reload(dossierId, file); - return firstValueFrom(reloaded$.pipe(tap(() => this._loadingService.stop()))); + this._loadingService.stop(); } discardRotation() { @@ -101,10 +106,6 @@ export class PageRotationService { return this.hasRotations ? this.#showConfirmationDialog() : of(false); } - get #rotations() { - return this.#rotations$.value; - } - #showConfirmationDialog() { const ref = this._injector.get(MatDialog).open(ConfirmationDialogComponent, { ...defaultDialogConfig, diff --git a/apps/red-ui/src/app/modules/shared-dossiers/components/dossiers-listing-actions/dossiers-listing-actions.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/components/dossiers-listing-actions/dossiers-listing-actions.component.ts index 70696ade6..ca07bbd07 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/components/dossiers-listing-actions/dossiers-listing-actions.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/components/dossiers-listing-actions/dossiers-listing-actions.component.ts @@ -7,7 +7,7 @@ import { LongPressEvent } from '@shared/directives/long-press.directive'; import { UserPreferenceService } from '@users/user-preference.service'; import { FilesMapService } from '@services/files/files-map.service'; import { ReanalysisService } from '@services/reanalysis.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; @Component({ selector: 'redaction-dossiers-listing-actions [dossier]', @@ -15,7 +15,7 @@ import { ROLES } from '@users/roles'; }) export class DossiersListingActionsComponent implements OnChanges { readonly circleButtonTypes = CircleButtonTypes; - readonly roles = ROLES; + readonly roles = Roles; readonly scrollableParentViews = ScrollableParentViews; readonly currentUser = getCurrentUser(); diff --git a/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts index b7813e91f..2d81f3fec 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/components/file-actions/file-actions.component.ts @@ -29,7 +29,7 @@ import { PageRotationService } from '../../../pdf-viewer/services/page-rotation. import { FileAssignService } from '../../services/file-assign.service'; import { ViewerHeaderService } from '../../../pdf-viewer/services/viewer-header.service'; import { ROTATION_ACTION_BUTTONS } from '../../../pdf-viewer/utils/constants'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { FileAttributesService } from '@services/entity-services/file-attributes.service'; @Component({ @@ -145,7 +145,7 @@ export class FileActionsComponent implements OnChanges { action: () => this.#openImportRedactionsDialog(), tooltip: _('dossier-overview.import-redactions'), icon: 'red:import_redactions', - show: this.showImportRedactions && !this._iqserPermissionsService.has(ROLES.getRss), + show: this.showImportRedactions && !this._iqserPermissionsService.has(Roles.getRss), }, { id: 'download-file-btn', @@ -176,7 +176,7 @@ export class FileActionsComponent implements OnChanges { show: !!this._excludedPagesService && this._permissionsService.canExcludePages(this.file, this.dossier) && - !this._iqserPermissionsService.has(ROLES.getRss), + !this._iqserPermissionsService.has(Roles.getRss), }, { id: 'set-file-to-new-btn', diff --git a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts index b68092279..ece30b9ba 100644 --- a/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts +++ b/apps/red-ui/src/app/modules/shared-dossiers/dialogs/edit-dossier-dialog/edit-dossier-dialog.component.ts @@ -22,7 +22,7 @@ import { EditDossierTeamComponent } from './edit-dossier-team/edit-dossier-team. import { PermissionsService } from '@services/permissions.service'; import { DossiersService } from '@services/dossiers/dossiers.service'; import { dossiersServiceProvider } from '@services/entity-services/dossiers.service.provider'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; type Section = 'dossierInfo' | 'downloadPackage' | 'dossierDictionary' | 'members' | 'dossierAttributes'; @@ -40,7 +40,7 @@ interface NavItem { providers: [dossiersServiceProvider], }) export class EditDossierDialogComponent extends BaseDialogComponent implements AfterViewInit { - readonly roles = ROLES; + readonly roles = Roles; navItems: NavItem[] = []; readonly iconButtonTypes = IconButtonTypes; activeNav: Section; @@ -100,7 +100,7 @@ export class EditDossierDialogComponent extends BaseDialogComponent implements A return ( (['members'].includes(this.activeNav) && this.#currentUser.isManager && - this.iqserPermissionsService.has(ROLES.dossiers.edit)) || + this.iqserPermissionsService.has(Roles.dossiers.edit)) || this._permissionsService.canEditDossier(this._dossier) ); } diff --git a/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.ts b/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.ts index 660581475..b2fdc9a8b 100644 --- a/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.ts +++ b/apps/red-ui/src/app/modules/shared/components/team-members/team-members.component.ts @@ -1,7 +1,7 @@ import { Component, ElementRef, EventEmitter, inject, Input, OnChanges, Output, ViewChild } from '@angular/core'; import { CircleButtonTypes, getCurrentUser, List } from '@iqser/common-ui'; import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { User } from '@red/domain'; import { UserService } from '@users/user.service'; @@ -12,7 +12,7 @@ import { UserService } from '@users/user.service'; }) export class TeamMembersComponent implements OnChanges { readonly circleButtonTypes = CircleButtonTypes; - readonly roles = ROLES; + readonly roles = Roles; readonly currentUser = getCurrentUser(); readonly userService = inject(UserService); @@ -31,11 +31,6 @@ export class TeamMembersComponent implements OnChanges { constructor(private readonly _dialogService: DossiersDialogService) {} - ngOnChanges() { - this.memberIds ??= []; - this.memberIds = [...this.memberIds].sort((a, b) => this.userService.getName(a).localeCompare(this.userService.getName(b))); - } - get maxTeamMembersBeforeExpand(): number { return this.perLine - (this.canAdd ? 1 : 0); } @@ -48,6 +43,11 @@ export class TeamMembersComponent implements OnChanges { return this.memberIds.length > this.maxTeamMembersBeforeExpand ? this.memberIds.length - (this.maxTeamMembersBeforeExpand - 1) : 0; } + ngOnChanges() { + this.memberIds ??= []; + this.memberIds = [...this.memberIds].sort((a, b) => this.userService.getName(a).localeCompare(this.userService.getName(b))); + } + toggleExpandedTeam() { this.expandedTeam = !this.expandedTeam; } diff --git a/apps/red-ui/src/app/modules/shared/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts b/apps/red-ui/src/app/modules/shared/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts index ca5ae6e26..cda06c8b2 100644 --- a/apps/red-ui/src/app/modules/shared/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts +++ b/apps/red-ui/src/app/modules/shared/dialogs/add-dossier-dialog/add-dossier-dialog.component.ts @@ -11,7 +11,7 @@ import { firstValueFrom } from 'rxjs'; import dayjs from 'dayjs'; import { Router } from '@angular/router'; import { DossiersDialogService } from '../../../shared-dossiers/services/dossiers-dialog.service'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; interface DialogData { readonly dossierTemplateId?: string; @@ -22,7 +22,7 @@ interface DialogData { styleUrls: ['./add-dossier-dialog.component.scss'], }) export class AddDossierDialogComponent extends BaseDialogComponent implements OnInit { - readonly roles = ROLES; + readonly roles = Roles; readonly iconButtonTypes = IconButtonTypes; hasDueDate = false; @@ -33,8 +33,8 @@ export class AddDossierDialogComponent extends BaseDialogComponent implements On })) .filter( element => - !this.permissionsService.has(ROLES.getRss) || - (this.permissionsService.has(ROLES.getRss) && !['DELTA_PREVIEW', 'REDACTED'].includes(element.key)), + !this.permissionsService.has(Roles.getRss) || + (this.permissionsService.has(Roles.getRss) && !['DELTA_PREVIEW', 'REDACTED'].includes(element.key)), ); dossierTemplates: IDossierTemplate[]; availableReportTypes: IReportTemplate[] = []; diff --git a/apps/red-ui/src/app/services/files/earmarks.service.ts b/apps/red-ui/src/app/services/files/earmarks.service.ts index 6e27ee7d2..b1e0d561f 100644 --- a/apps/red-ui/src/app/services/files/earmarks.service.ts +++ b/apps/red-ui/src/app/services/files/earmarks.service.ts @@ -18,7 +18,7 @@ export class EarmarksService extends GenericService { map(response => response.highlights), map(highlights => highlights.map(highlight => AnnotationWrapper.fromEarmark(highlight))), map(highlights => highlights.sort((h1, h2) => h1.color.localeCompare(h2.color))), - catchError(() => of([])), + catchError(() => of([] as AnnotationWrapper[])), ); return firstValueFrom(request); diff --git a/apps/red-ui/src/app/services/files/files.service.ts b/apps/red-ui/src/app/services/files/files.service.ts index 326847766..b177c6c6c 100644 --- a/apps/red-ui/src/app/services/files/files.service.ts +++ b/apps/red-ui/src/app/services/files/files.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { EntitiesService, isArray, List, mapEach, QueryParam } from '@iqser/common-ui'; import { File, IFile } from '@red/domain'; -import { firstValueFrom, Observable } from 'rxjs'; +import { firstValueFrom } from 'rxjs'; import { UserService } from '@users/user.service'; import { FilesMapService } from './files-map.service'; import { map, switchMap, tap } from 'rxjs/operators'; @@ -36,13 +36,12 @@ export class FilesService extends EntitiesService { return loadStats$.pipe(tap(files => this._filesMapService.set(dossierId, files))); } - reload(dossierId: string, file: File): Observable { - return super._getOne([dossierId, file.id]).pipe( - map(_file => new File(_file, this._userService.getName(_file.assignee))), - switchMap(_file => this._dossierStatsService.getFor([dossierId]).pipe(map(() => _file))), - map(_file => this._filesMapService.replace(dossierId, [_file])), - tap(() => this._logger.info('[FILE] Reloaded')), - ); + async reload(dossierId: string, file: File) { + const _file = await firstValueFrom(super._getOne([dossierId, file.id])); + const reloadedFile = new File(_file, this._userService.getName(_file.assignee)); + await firstValueFrom(this._dossierStatsService.getFor([dossierId])); + this._logger.info('[FILE] Reloaded'); + return this._filesMapService.replace(dossierId, [reloadedFile]); } async setAssignee(files: File | List, assigneeId: string) { diff --git a/apps/red-ui/src/app/services/files/redaction-log.service.ts b/apps/red-ui/src/app/services/files/redaction-log.service.ts index de795404e..8e9133564 100644 --- a/apps/red-ui/src/app/services/files/redaction-log.service.ts +++ b/apps/red-ui/src/app/services/files/redaction-log.service.ts @@ -1,8 +1,8 @@ import { Injectable } from '@angular/core'; import { GenericService, QueryParam } from '@iqser/common-ui'; import { IRedactionLog, ISectionGrid } from '@red/domain'; -import { catchError, tap } from 'rxjs/operators'; -import { of } from 'rxjs'; +import { catchError } from 'rxjs/operators'; +import { firstValueFrom, of } from 'rxjs'; @Injectable({ providedIn: 'root', @@ -10,17 +10,16 @@ import { of } from 'rxjs'; export class RedactionLogService extends GenericService { protected readonly _defaultModelPath = ''; - getRedactionLog(dossierId: string, fileId: string, withManualRedactions?: boolean) { + async getRedactionLog(dossierId: string, fileId: string, withManualRedactions?: boolean) { const queryParams: QueryParam[] = []; if (withManualRedactions) { queryParams.push({ key: 'withManualRedactions', value: withManualRedactions }); } const redactionLog$ = this._getOne([dossierId, fileId], 'redactionLog', queryParams); - return redactionLog$.pipe( - tap(redactionLog => redactionLog.redactionLogEntry.sort((a, b) => a.positions[0].page - b.positions[0].page)), - catchError(() => of({} as IRedactionLog)), - ); + const redactionLog = await firstValueFrom(redactionLog$.pipe(catchError(() => of({} as IRedactionLog)))); + redactionLog.redactionLogEntry.sort((a, b) => a.positions[0].page - b.positions[0].page); + return redactionLog; } getSectionGrid(dossierId: string, fileId: string) { diff --git a/apps/red-ui/src/app/services/permissions.service.ts b/apps/red-ui/src/app/services/permissions.service.ts index 79a6708d8..99c53ebe4 100644 --- a/apps/red-ui/src/app/services/permissions.service.ts +++ b/apps/red-ui/src/app/services/permissions.service.ts @@ -4,7 +4,7 @@ import { DashboardStats, Dictionary, Dossier, DOSSIERS_ARCHIVE, DossierTemplate, import { FilesMapService } from '@services/files/files-map.service'; import { FeaturesService } from '@services/features.service'; import { IqserPermissionsService } from '@iqser/common-ui'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { UserPreferenceService } from '@users/user-preference.service'; import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service'; @@ -25,16 +25,16 @@ export class PermissionsService { canAddEditJustifications() { return ( - this._userPreferenceService.areDevFeaturesEnabled && this.isAdmin() && this._iqserPermissionsService.has(ROLES.legalBasis.write) + this._userPreferenceService.areDevFeaturesEnabled && this.isAdmin() && this._iqserPermissionsService.has(Roles.legalBasis.write) ); } canEditGlobalFileAttributes() { - return this._iqserPermissionsService.has(ROLES.fileAttributes.write) && this.isAdmin(); + return this._iqserPermissionsService.has(Roles.fileAttributes.write) && this.isAdmin(); } canEditGlobalDossierAttributes() { - return this._iqserPermissionsService.has(ROLES.dossierAttributes.writeConfig) && this.isAdmin(); + return this._iqserPermissionsService.has(Roles.dossierAttributes.writeConfig) && this.isAdmin(); } canDownloadEntityDictionary(): boolean { @@ -42,11 +42,11 @@ export class PermissionsService { } canPerformDossierStatesActions() { - return this.isAdmin() && this._iqserPermissionsService.has(ROLES.states.write); + return this.isAdmin() && this._iqserPermissionsService.has(Roles.states.write); } canEditEntities(): boolean { - return this._iqserPermissionsService.has(ROLES.dictionaryTypes.write) && this.isAdmin(); + return this._iqserPermissionsService.has(Roles.dictionaryTypes.write) && this.isAdmin(); } canDeleteEntities(entity: Dictionary | Dictionary[]): boolean { @@ -54,7 +54,7 @@ export class PermissionsService { return ( entities.length && this.isAdmin() && - this._iqserPermissionsService.has(ROLES.dictionaryTypes.delete) && + this._iqserPermissionsService.has(Roles.dictionaryTypes.delete) && entities.reduce((acc, _entity) => this._canDeleteEntity(_entity) && acc, true) ); } @@ -66,14 +66,14 @@ export class PermissionsService { displayReanalyseBtn(dossier: Dossier): boolean { return ( dossier.isActive && - this._iqserPermissionsService.has(ROLES.dossiers.reanalyze) && + this._iqserPermissionsService.has(Roles.dossiers.reanalyze) && this.isApprover(dossier) && !!this._filesMapService.get(dossier.id).find(f => f.analysisRequired) ); } canUploadFiles(dossier: Dossier): boolean { - return this._iqserPermissionsService.has(ROLES.files.upload) && dossier.isActive; + return this._iqserPermissionsService.has(Roles.files.upload) && dossier.isActive; } canDownloadCsvReport(dossier: Dossier): boolean { @@ -88,7 +88,7 @@ export class PermissionsService { } canToggleAnalysis(file: File | File[], dossier: Dossier): boolean { - if (!this._iqserPermissionsService.has(ROLES.files.reanalyze)) { + if (!this._iqserPermissionsService.has(Roles.files.reanalyze)) { return false; } @@ -98,27 +98,27 @@ export class PermissionsService { } showToggleAnalysis(dossier: Dossier): boolean { - return this._iqserPermissionsService.has(ROLES.excludeIncludeFile) && dossier.isActive; + return this._iqserPermissionsService.has(Roles.excludeIncludeFile) && dossier.isActive; } canReanalyseFile(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.files.reanalyze) && + this._iqserPermissionsService.has(Roles.files.reanalyze) && files.reduce((acc, _file) => this._canReanalyseFile(_file, dossier) && acc, true) ); } canEnableAutoAnalysis(files: File[], dossier: Dossier): boolean { return ( - this._iqserPermissionsService.has(ROLES.files.reanalyze) && + this._iqserPermissionsService.has(Roles.files.reanalyze) && files.reduce((acc, _file) => this._canEnableAutoAnalysis(_file, dossier) && acc, true) ); } canDisableAutoAnalysis(files: File[], dossier: Dossier): boolean { return ( - this._iqserPermissionsService.has(ROLES.files.reanalyze) && + this._iqserPermissionsService.has(Roles.files.reanalyze) && files.reduce((acc, _file) => this._canDisableAutoAnalysis(_file, dossier) && acc, true) ); } @@ -130,7 +130,7 @@ export class PermissionsService { canSoftDeleteFile(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.files.delete) && + this._iqserPermissionsService.has(Roles.files.delete) && files.reduce((acc, _file) => this._canSoftDeleteFile(_file, dossier) && acc, true) ); } @@ -138,7 +138,7 @@ export class PermissionsService { canRestoreFile(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.files.delete) && + this._iqserPermissionsService.has(Roles.files.delete) && files.reduce((acc, _file) => this._canRestoreFile(_file, dossier) && acc, true) ); } @@ -146,7 +146,7 @@ export class PermissionsService { canHardDeleteFile(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.files.delete) && + this._iqserPermissionsService.has(Roles.files.delete) && files.reduce((acc, _file) => this._canHardDeleteFile(_file, dossier) && acc, true) ); } @@ -154,7 +154,7 @@ export class PermissionsService { canOcrFile(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.files.reanalyze) && + this._iqserPermissionsService.has(Roles.files.reanalyze) && files.reduce((acc, _file) => this._canOcrFile(_file, dossier) && acc, true) ); } @@ -162,7 +162,7 @@ export class PermissionsService { canAssignToSelf(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.setReviewer) && + this._iqserPermissionsService.has(Roles.setReviewer) && files.reduce((acc, _file) => this._canAssignToSelf(_file, dossier) && acc, true) ); } @@ -170,7 +170,7 @@ export class PermissionsService { canAssignUser(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.setReviewer) && + this._iqserPermissionsService.has(Roles.setReviewer) && files.reduce((acc, _file) => this._canAssignUser(_file, dossier) && acc, true) ); } @@ -178,7 +178,7 @@ export class PermissionsService { canUnassignUser(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.setReviewer) && + this._iqserPermissionsService.has(Roles.setReviewer) && files.reduce((acc, _file) => this._canUnassignUser(_file, dossier) && acc, true) ); } @@ -196,7 +196,7 @@ export class PermissionsService { canBeApproved(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.files.setApproved) && + this._iqserPermissionsService.has(Roles.files.setApproved) && files.reduce((acc, _file) => this._canBeApproved(_file, dossier) && acc, true) ); } @@ -204,7 +204,7 @@ export class PermissionsService { isReadyForApproval(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.files.setApproved) && + this._iqserPermissionsService.has(Roles.files.setApproved) && files.reduce((acc, _file) => this._isReadyForApproval(_file, dossier) && acc, true) ); } @@ -212,7 +212,7 @@ export class PermissionsService { canSetUnderApproval(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.files.setUnderApproval) && + this._iqserPermissionsService.has(Roles.files.setUnderApproval) && files.reduce((acc, _file) => this._canSetUnderApproval(_file, dossier) && acc, true) ); } @@ -246,14 +246,14 @@ export class PermissionsService { canUndoApproval(file: File | File[], dossier: Dossier): boolean { const files = file instanceof File ? [file] : file; return ( - this._iqserPermissionsService.has(ROLES.files.setApproved) && + this._iqserPermissionsService.has(Roles.files.setApproved) && files.reduce((acc, _file) => this._canUndoApproval(_file, dossier) && acc, true) ); } canMarkPagesAsViewed(file: File): boolean { return ( - this._iqserPermissionsService.has(ROLES.manageViewedPages) && + this._iqserPermissionsService.has(Roles.manageViewedPages) && (file.isUnderReview || file.isUnderApproval) && this.isFileAssignee(file) ); @@ -267,20 +267,20 @@ export class PermissionsService { } canDeleteDossier(dossier: IDossier): boolean { - return this._iqserPermissionsService.has(ROLES.dossiers.delete) && this.isOwner(dossier); + return this._iqserPermissionsService.has(Roles.dossiers.delete) && this.isOwner(dossier); } canRestoreDossier(dossier: IDossier): boolean { - return this._iqserPermissionsService.has(ROLES.dossiers.delete) && this.isOwner(dossier); + return this._iqserPermissionsService.has(Roles.dossiers.delete) && this.isOwner(dossier); } canCreateDossier(dossierTemplate: DossierTemplate | DashboardStats): boolean { - return this._iqserPermissionsService.has(ROLES.dossiers.write) && this.isManager() && dossierTemplate.isActive; + return this._iqserPermissionsService.has(Roles.dossiers.write) && this.isManager() && dossierTemplate.isActive; } canArchiveDossier(dossier: Dossier): boolean { return ( - this._iqserPermissionsService.has(ROLES.dossiers.archived) && + this._iqserPermissionsService.has(Roles.dossiers.archived) && this._featuresService.isEnabled(DOSSIERS_ARCHIVE) && dossier.isActive && this.isOwner(dossier) @@ -288,7 +288,7 @@ export class PermissionsService { } canEditDossier(dossier: Dossier): boolean { - return this._iqserPermissionsService.has(ROLES.dossiers.edit) && this.isManager() && !!dossier?.ownerId; + return this._iqserPermissionsService.has(Roles.dossiers.edit) && this.isManager() && !!dossier?.ownerId; } canEditDossierDictionary(dossier: Dossier): boolean { @@ -296,16 +296,16 @@ export class PermissionsService { dossier.isActive && this._dossierDictionariesMapService.get(dossier.id).length > 0 && this.isOwner(dossier) && - this._iqserPermissionsService.has(ROLES.dossiers.dictionaryEntries.write) + this._iqserPermissionsService.has(Roles.dossiers.dictionaryEntries.write) ); } canEditDossierAttributes(dossier: Dossier): boolean { - return dossier.isActive && this.isOwner(dossier) && this._iqserPermissionsService.has(ROLES.dossierAttributes.write); + return dossier.isActive && this.isOwner(dossier) && this._iqserPermissionsService.has(Roles.dossierAttributes.write); } canEditTeamMembers(): boolean { - return this._iqserPermissionsService.has(ROLES.dossiers.edit) && this.isManager(); + return this._iqserPermissionsService.has(Roles.dossiers.edit) && this.isManager(); } isAdmin(): boolean { @@ -317,16 +317,16 @@ export class PermissionsService { } canAddComment(file: File, dossier: Dossier): boolean { - return this._iqserPermissionsService.has(ROLES.comments.write) && this.isAssigneeOrApprover(file, dossier) && !file.isApproved; + return this._iqserPermissionsService.has(Roles.comments.write) && this.isAssigneeOrApprover(file, dossier) && !file.isApproved; } canExcludePages(file: File, dossier: Dossier): boolean { - return this._iqserPermissionsService.has(ROLES.excludeIncludePages) && this.canPerformAnnotationActions(file, dossier); + return this._iqserPermissionsService.has(Roles.excludeIncludePages) && this.canPerformAnnotationActions(file, dossier); } canDeleteComment(comment: IComment, file: File, dossier: Dossier) { return ( - this._iqserPermissionsService.has(ROLES.comments.delete) && + this._iqserPermissionsService.has(Roles.comments.delete) && (comment.user === this.#userId || this.isApprover(dossier)) && !file.isApproved ); @@ -334,7 +334,7 @@ export class PermissionsService { canImportRedactions(file: File, dossier: Dossier) { return ( - this._iqserPermissionsService.has(ROLES.redactions.write) && + this._iqserPermissionsService.has(Roles.redactions.write) && dossier.isActive && this.isFileAssignee(file) && !file.isApproved && @@ -343,15 +343,15 @@ export class PermissionsService { } canRotatePage(file: File) { - return this.isFileAssignee(file) && this._iqserPermissionsService.has(ROLES.files.rotatePage); + return this.isFileAssignee(file) && this._iqserPermissionsService.has(Roles.files.rotatePage); } canDownloadRedactedFile() { - return this._iqserPermissionsService.has(ROLES.files.processDownload); + return this._iqserPermissionsService.has(Roles.files.processDownload); } canEditRules() { - return this._iqserPermissionsService.has(ROLES.rules.write) && this.isAdmin(); + return this._iqserPermissionsService.has(Roles.rules.write) && this.isAdmin(); } private _canDeleteEntity(entity: Dictionary): boolean { diff --git a/apps/red-ui/src/app/services/reanalysis.service.ts b/apps/red-ui/src/app/services/reanalysis.service.ts index b9b9ca856..74977606e 100644 --- a/apps/red-ui/src/app/services/reanalysis.service.ts +++ b/apps/red-ui/src/app/services/reanalysis.service.ts @@ -1,7 +1,7 @@ import { Injectable } from '@angular/core'; import { GenericService, List, QueryParam, Toaster } from '@iqser/common-ui'; import { Dossier, File, IPageExclusionRequest } from '@red/domain'; -import { catchError, switchMap, tap } from 'rxjs/operators'; +import { catchError, tap } from 'rxjs/operators'; import { FilesService } from './files/files.service'; import { FilesMapService } from './files/files-map.service'; import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker'; @@ -26,12 +26,16 @@ export class ReanalysisService extends GenericService { super(); } - excludePages(body: IPageExclusionRequest, dossierId: string, file: File) { - return this._post(body, `exclude-pages/${dossierId}/${file.id}`).pipe(switchMap(() => this._filesService.reload(dossierId, file))); + async excludePages(body: IPageExclusionRequest, file: File) { + const dossierId = file.dossierId; + await firstValueFrom(this._post(body, `exclude-pages/${dossierId}/${file.id}`)); + return await this._filesService.reload(dossierId, file); } - includePages(body: IPageExclusionRequest, dossierId: string, file: File) { - return this._post(body, `include-pages/${dossierId}/${file.id}`).pipe(switchMap(() => this._filesService.reload(dossierId, file))); + async includePages(body: IPageExclusionRequest, file: File) { + const dossierId = file.dossierId; + await firstValueFrom(this._post(body, `include-pages/${dossierId}/${file.id}`)); + return await this._filesService.reload(dossierId, file); } async reanalyzeFilesForDossier(files: List, dossierId: string, params?: ReanalyzeQueryParams) { diff --git a/apps/red-ui/src/app/users/roles.ts b/apps/red-ui/src/app/users/roles.ts index 97a0f7a24..68769ca03 100644 --- a/apps/red-ui/src/app/users/roles.ts +++ b/apps/red-ui/src/app/users/roles.ts @@ -1,4 +1,4 @@ -export const ROLES = { +export const Roles = { RED_CREATE_TENANT: 'red-create-tenant', RED_DEPLOYMENT_INFO: 'red-deployment-info', RED_GET_TENANTS: 'red-get-tenants', diff --git a/apps/red-ui/src/app/users/user.service.ts b/apps/red-ui/src/app/users/user.service.ts index 55bbec07e..2bdd7735d 100644 --- a/apps/red-ui/src/app/users/user.service.ts +++ b/apps/red-ui/src/app/users/user.service.ts @@ -1,7 +1,7 @@ import { inject, Injectable } from '@angular/core'; import { User } from '@red/domain'; import { IIqserUser, IqserUserService, List, QueryParam } from '@iqser/common-ui'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { of } from 'rxjs'; @Injectable({ @@ -15,19 +15,19 @@ export class UserService extends IqserUserService { const currentUser = await super.loadCurrentUser(); this._permissionsService.add({ - [ROLES.any]: (permission, all) => Object.keys(all).some(key => this._permissionsFilter(key)), + [Roles.any]: (permission, all) => Object.keys(all).some(key => this._permissionsFilter(key)), }); return currentUser; } loadAll() { - const canReadUsers = this._permissionsService.has(ROLES.users.read); + const canReadUsers = this._permissionsService.has(Roles.users.read); return canReadUsers ? super.loadAll() : of([]); } getAll() { - const canReadAllUsers = this._permissionsService.has(ROLES.users.readAll); + const canReadAllUsers = this._permissionsService.has(Roles.users.readAll); const url = canReadAllUsers ? this._defaultModelPath : `${this._defaultModelPath}/red`; return super.getAll(url); } diff --git a/apps/red-ui/src/app/utils/main.resolver.ts b/apps/red-ui/src/app/utils/main.resolver.ts index 90fe00c94..2ebc0f383 100644 --- a/apps/red-ui/src/app/utils/main.resolver.ts +++ b/apps/red-ui/src/app/utils/main.resolver.ts @@ -10,7 +10,7 @@ import { FeaturesService } from '@services/features.service'; import { GeneralSettingsService } from '@services/general-settings.service'; import { tap } from 'rxjs/operators'; import { firstValueFrom } from 'rxjs'; -import { ROLES } from '@users/roles'; +import { Roles } from '@users/roles'; import { DossiersChangesService } from '@services/dossiers/dossier-changes.service'; import { ResolveFn } from '@angular/router'; @@ -26,7 +26,7 @@ export const mainResolver: ResolveFn = async () => { logger.info('[ROUTES] Main resolver started...'); inject(FeaturesService).loadConfig(); - if (inject(IqserPermissionsService).has(ROLES.dossiers.read)) { + if (inject(IqserPermissionsService).has(Roles.dossiers.read)) { inject(DossiersChangesService).initialize(); }