From 069a345aa341f1c2d94f550199384e30409b5828 Mon Sep 17 00:00:00 2001 From: Dan Percic Date: Sat, 8 Apr 2023 20:44:00 +0300 Subject: [PATCH] RED-6523: simplify tenants handling --- apps/red-ui/src/app/app-routing.module.ts | 229 +++++++++--------- apps/red-ui/src/app/app.component.html | 12 - apps/red-ui/src/app/app.component.ts | 14 +- apps/red-ui/src/app/app.module.ts | 64 ++--- .../base-screen/base-screen.component.html | 16 +- .../base-screen/base-screen.component.ts | 22 +- .../system-preferences-form.component.ts | 3 +- .../dossiers/dossier-changes.service.ts | 21 +- .../src/app/services/features.service.ts | 19 +- .../global-error-handler.service.ts | 0 .../src/app/services/license.service.ts | 19 +- .../services/system-preferences.service.ts | 25 +- .../app/utils/configuration.initializer.ts | 63 ----- apps/red-ui/src/app/utils/index.ts | 2 - apps/red-ui/src/app/utils/main.resolver.ts | 57 +++++ apps/red-ui/src/assets/config/config.json | 4 +- apps/red-ui/src/main.ts | 17 +- libs/common-ui | 2 +- 18 files changed, 281 insertions(+), 308 deletions(-) rename apps/red-ui/src/app/{utils => services}/global-error-handler.service.ts (100%) delete mode 100644 apps/red-ui/src/app/utils/configuration.initializer.ts create mode 100644 apps/red-ui/src/app/utils/main.resolver.ts diff --git a/apps/red-ui/src/app/app-routing.module.ts b/apps/red-ui/src/app/app-routing.module.ts index 0d10b048e..f39e3d8b4 100644 --- a/apps/red-ui/src/app/app-routing.module.ts +++ b/apps/red-ui/src/app/app-routing.module.ts @@ -3,6 +3,8 @@ import { CompositeRouteGuard, CustomRouteReuseStrategy, DEFAULT_REDIRECT_KEY, + ifLoggedIn, + ifNotLoggedIn, IqserAuthGuard, IqserPermissionsGuard, IqserRoutes, @@ -24,6 +26,7 @@ import { ARCHIVE_ROUTE, BreadcrumbTypes, DOSSIER_ID, DOSSIER_TEMPLATE_ID, DOSSIE import { DossierFilesGuard } from '@guards/dossier-files-guard'; import { WebViewerLoadedGuard } from './modules/pdf-viewer/services/webviewer-loaded.guard'; import { ROLES } from '@users/roles'; +import { mainResolver } from '@utils/main.resolver'; const dossierTemplateIdRoutes: IqserRoutes = [ { @@ -94,127 +97,135 @@ const dossierTemplateIdRoutes: IqserRoutes = [ }, ]; +const mainRoutes: IqserRoutes = [ + { + path: '', + redirectTo: 'dashboard', + pathMatch: 'full', + }, + { + path: 'account', + loadChildren: () => import('./modules/account/account.module').then(m => m.AccountModule), + }, + { + path: 'admin', + loadChildren: () => import('./modules/admin/admin.module').then(m => m.AdminModule), + canActivate: [RedRoleGuard], + }, + { + path: 'dashboard', + loadChildren: () => import('./modules/dashboard/dashboard.module').then(m => m.DashboardModule), + canActivate: [CompositeRouteGuard], + data: { + 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, + 'RED_USER', + ], + redirectTo: { + RED_USER: '/main/admin', + [ROLES.templates.read]: '/main/admin', + [DEFAULT_REDIRECT_KEY]: '/auth-error', + }, + }, + skeleton: 'dashboard', + }, + }, + { + path: 'downloads', + // TODO: transform into a lazy loaded module + component: DownloadsListScreenComponent, + canActivate: [CompositeRouteGuard, IqserPermissionsGuard], + data: { + routeGuards: [IqserAuthGuard, RedRoleGuard], + permissions: { + allow: ROLES.readDownloadStatus, + redirectTo: '/auth-error', + }, + }, + }, + { + path: 'search', + loadChildren: () => import('./modules/search/search.module').then(m => m.SearchModule), + canActivate: [CompositeRouteGuard, IqserPermissionsGuard], + data: { + routeGuards: [IqserAuthGuard, RedRoleGuard, DossiersGuard], + permissions: { + allow: [ROLES.search], + redirectTo: '/auth-error', + }, + }, + }, + { + path: 'trash', + loadChildren: () => import('./modules/trash/trash.module').then(m => m.TrashModule), + canActivate: [CompositeRouteGuard, IqserPermissionsGuard], + data: { + routeGuards: [IqserAuthGuard, RedRoleGuard, DossiersGuard, TrashGuard], + dossiersService: ACTIVE_DOSSIERS_SERVICE, + permissions: { + allow: [ROLES.dossiers.read, ROLES.files.readStatus], + redirectTo: '/auth-error', + }, + }, + }, + { + path: `:${DOSSIER_TEMPLATE_ID}`, + children: dossierTemplateIdRoutes, + canActivate: [CompositeRouteGuard, IqserPermissionsGuard], + data: { + routeGuards: [IqserAuthGuard, RedRoleGuard, DossierTemplatesGuard, DashboardGuard, DossierTemplateExistsGuard], + 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, + 'RED_USER', + ], + redirectTo: { + [ROLES.any]: '/auth-error', + RED_USER: '/main/admin', + [DEFAULT_REDIRECT_KEY]: '/', + }, + }, + }, + }, +]; + const routes: IqserRoutes = [ { path: '', pathMatch: 'full', + canActivate: [ifNotLoggedIn], component: TenantResolveComponent, }, { path: ':tenant', - component: TenantResolveComponent, + redirectTo: ':tenant/main', + pathMatch: 'full', }, { path: ':tenant/main', + canActivate: [ifLoggedIn], component: BaseScreenComponent, - children: [ - { - path: '', - redirectTo: 'dashboard', - pathMatch: 'full', - }, - { - path: 'account', - loadChildren: () => import('./modules/account/account.module').then(m => m.AccountModule), - }, - { - path: 'admin', - loadChildren: () => import('./modules/admin/admin.module').then(m => m.AdminModule), - canActivate: [RedRoleGuard], - }, - { - path: 'dashboard', - loadChildren: () => import('./modules/dashboard/dashboard.module').then(m => m.DashboardModule), - canActivate: [CompositeRouteGuard], - data: { - 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, - 'RED_USER', - ], - redirectTo: { - RED_USER: '/main/admin', - [ROLES.templates.read]: '/main/admin', - [DEFAULT_REDIRECT_KEY]: '/auth-error', - }, - }, - skeleton: 'dashboard', - }, - }, - { - path: 'downloads', - // TODO: transform into a lazy loaded module - component: DownloadsListScreenComponent, - canActivate: [CompositeRouteGuard, IqserPermissionsGuard], - data: { - routeGuards: [IqserAuthGuard, RedRoleGuard], - permissions: { - allow: ROLES.readDownloadStatus, - redirectTo: '/auth-error', - }, - }, - }, - { - path: 'search', - loadChildren: () => import('./modules/search/search.module').then(m => m.SearchModule), - canActivate: [CompositeRouteGuard, IqserPermissionsGuard], - data: { - routeGuards: [IqserAuthGuard, RedRoleGuard, DossiersGuard], - permissions: { - allow: [ROLES.search], - redirectTo: '/auth-error', - }, - }, - }, - { - path: 'trash', - loadChildren: () => import('./modules/trash/trash.module').then(m => m.TrashModule), - canActivate: [CompositeRouteGuard, IqserPermissionsGuard], - data: { - routeGuards: [IqserAuthGuard, RedRoleGuard, DossiersGuard, TrashGuard], - dossiersService: ACTIVE_DOSSIERS_SERVICE, - permissions: { - allow: [ROLES.dossiers.read, ROLES.files.readStatus], - redirectTo: '/auth-error', - }, - }, - }, - { - path: `:${DOSSIER_TEMPLATE_ID}`, - children: dossierTemplateIdRoutes, - canActivate: [CompositeRouteGuard, IqserPermissionsGuard], - data: { - routeGuards: [IqserAuthGuard, RedRoleGuard, DossierTemplatesGuard, DashboardGuard, DossierTemplateExistsGuard], - 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, - 'RED_USER', - ], - redirectTo: { - [ROLES.any]: '/auth-error', - RED_USER: '/main/admin', - [DEFAULT_REDIRECT_KEY]: '/', - }, - }, - }, - }, - ], + resolve: { + whateverThisMainRouteNeeds: mainResolver, + }, + children: mainRoutes, }, { path: ':tenant/auth-error', diff --git a/apps/red-ui/src/app/app.component.html b/apps/red-ui/src/app/app.component.html index a5f32ccc0..05cc79134 100644 --- a/apps/red-ui/src/app/app.component.html +++ b/apps/red-ui/src/app/app.component.html @@ -1,17 +1,5 @@ - - - - - - - - - - - - diff --git a/apps/red-ui/src/app/app.component.ts b/apps/red-ui/src/app/app.component.ts index 9a11ac19b..35f63282f 100644 --- a/apps/red-ui/src/app/app.component.ts +++ b/apps/red-ui/src/app/app.component.ts @@ -1,11 +1,8 @@ import { Component, Inject, OnDestroy, Renderer2, ViewContainerRef } from '@angular/core'; import { RouterHistoryService } from '@services/router-history.service'; -import { REDDocumentViewer } from './modules/pdf-viewer/services/document-viewer.service'; -import { DossiersChangesService } from '@services/dossiers/dossier-changes.service'; import { DOCUMENT } from '@angular/common'; import { UserPreferenceService } from '@users/user-preference.service'; -import { getConfig, IqserPermissionsService } from '@iqser/common-ui'; -import { ROLES } from '@users/roles'; +import { getConfig } from '@iqser/common-ui'; import { AppConfig } from '@red/domain'; import { ActivatedRoute, ParamMap, Router } from '@angular/router'; import { Subscription } from 'rxjs'; @@ -38,22 +35,13 @@ export class AppComponent implements OnDestroy { /** RouterHistoryService needs to be injected for last dossiers screen to be updated on first app load */ private readonly _routerHistoryService: RouterHistoryService, userPreferenceService: UserPreferenceService, - readonly documentViewer: REDDocumentViewer, - dossierChangesService: DossiersChangesService, @Inject(DOCUMENT) document: Document, renderer: Renderer2, - permissionsService: IqserPermissionsService, private readonly _router: Router, route: ActivatedRoute, ) { renderer.addClass(document.body, userPreferenceService.getTheme()); loadCustomTheme(); - // TODO: Find a better place to initialize dossiers refresh - if (permissionsService.has(ROLES.dossiers.read)) { - const refreshSub = dossierChangesService.initializeRefresh().subscribe(); - this.#subscription.add(refreshSub); - } - const sub = route.queryParamMap.subscribe(queryParams => this.#navigate(queryParams)); this.#subscription.add(sub); } diff --git a/apps/red-ui/src/app/app.module.ts b/apps/red-ui/src/app/app.module.ts index d296b2e47..e1ed543b3 100644 --- a/apps/red-ui/src/app/app.module.ts +++ b/apps/red-ui/src/app/app.module.ts @@ -1,12 +1,11 @@ import { BrowserModule } from '@angular/platform-browser'; -import { APP_INITIALIZER, ErrorHandler, NgModule } from '@angular/core'; +import { ENVIRONMENT_INITIALIZER, ErrorHandler, inject, NgModule } from '@angular/core'; import { AppComponent } from './app.component'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { BaseScreenComponent } from '@components/base-screen/base-screen.component'; import { MissingTranslationHandler } from '@ngx-translate/core'; import { - BASE_HREF, CachingModule, CircleButtonComponent, CommonUiModule, @@ -19,10 +18,8 @@ import { IqserHelpModeModule, IqserListingModule, IqserLoadingModule, - IqserPermissionsService, IqserTranslateModule, IqserUsersModule, - KeycloakStatusService, LanguageService, LogoComponent, MAX_RETRIES_ON_SERVER_ERROR, @@ -48,53 +45,43 @@ import { FileUploadDownloadModule } from '@upload-download/file-upload-download. import { DatePipe as BaseDatePipe } from '@angular/common'; import { ACTIVE_DOSSIERS_SERVICE, ARCHIVED_DOSSIERS_SERVICE } from './tokens'; import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor'; -import { GlobalErrorHandler } from '@utils/global-error-handler.service'; +import { GlobalErrorHandler } from '@services/global-error-handler.service'; import { REDMissingTranslationHandler } from '@utils/missing-translations-handler'; -import { configurationInitializer } from '@utils/configuration.initializer'; import { ConfigService } from '@services/config.service'; import { SpotlightSearchComponent } from '@components/spotlight-search/spotlight-search.component'; import { DatePipe } from '@shared/pipes/date.pipe'; import * as links from '../assets/help-mode/links.json'; -import { KeycloakService } from 'keycloak-angular'; -import { GeneralSettingsService } from '@services/general-settings.service'; import { BreadcrumbsComponent } from '@components/breadcrumbs/breadcrumbs.component'; import { UserPreferenceService } from '@users/user-preference.service'; import { UserService } from '@users/user.service'; import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service'; import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.service'; -import { FeaturesService } from '@services/features.service'; import { MAT_TOOLTIP_DEFAULT_OPTIONS } from '@angular/material/tooltip'; import { LoggerModule, NgxLoggerLevel, TOKEN_LOGGER_CONFIG, TOKEN_LOGGER_RULES_SERVICE } from 'ngx-logger'; import { LoggerRulesService } from '@services/logger-rules.service'; import { AppConfig, ILoggerConfig } from '@red/domain'; -import { SystemPreferencesService } from '@services/system-preferences.service'; import { PdfViewerModule } from './modules/pdf-viewer/pdf-viewer.module'; -import { LicenseService } from '@services/license.service'; import { UI_CACHES } from '@utils/constants'; import { RedRoleGuard } from '@users/red-role.guard'; import { SkeletonTopBarComponent } from '@components/skeleton/skeleton-top-bar/skeleton-top-bar.component'; import { DossierSkeletonComponent } from '@components/skeleton/dossier-skeleton/dossier-skeleton.component'; import { SkeletonStatsComponent } from '@components/skeleton/skeleton-stats/skeleton-stats.component'; -const screens = [BaseScreenComponent, DownloadsListScreenComponent]; - -const components = [ - AppComponent, - AuthErrorComponent, - NotificationsComponent, - SpotlightSearchComponent, - BreadcrumbsComponent, - DashboardSkeletonComponent, - DossierSkeletonComponent, - SkeletonTopBarComponent, - SkeletonStatsComponent, - - ...screens, -]; - export const appModuleFactory = (config: AppConfig) => { @NgModule({ - declarations: [...components], + declarations: [ + AppComponent, + AuthErrorComponent, + NotificationsComponent, + SpotlightSearchComponent, + BreadcrumbsComponent, + DashboardSkeletonComponent, + DossierSkeletonComponent, + SkeletonTopBarComponent, + SkeletonStatsComponent, + BaseScreenComponent, + DownloadsListScreenComponent, + ], imports: [ BrowserModule, BrowserAnimationsModule, @@ -187,23 +174,12 @@ export const appModuleFactory = (config: AppConfig) => { useClass: GlobalErrorHandler, }, { - provide: APP_INITIALIZER, + provide: ENVIRONMENT_INITIALIZER, multi: true, - useFactory: configurationInitializer, - deps: [ - BASE_HREF, - KeycloakStatusService, - KeycloakService, - ConfigService, - SystemPreferencesService, - FeaturesService, - GeneralSettingsService, - LanguageService, - UserService, - UserPreferenceService, - LicenseService, - IqserPermissionsService, - ], + useValue: async () => { + const languageService = inject(LanguageService); + return languageService.setInitialLanguage(); + }, }, { provide: MissingTranslationHandler, diff --git a/apps/red-ui/src/app/components/base-screen/base-screen.component.html b/apps/red-ui/src/app/components/base-screen/base-screen.component.html index c88743c2d..18b3eb2be 100644 --- a/apps/red-ui/src/app/components/base-screen/base-screen.component.html +++ b/apps/red-ui/src/app/components/base-screen/base-screen.component.html @@ -43,10 +43,6 @@ - -