wip migrations

This commit is contained in:
Dan Percic 2024-12-16 11:15:45 +02:00
parent d3be2411ff
commit 84fcdde3ce
13 changed files with 235 additions and 260 deletions

View File

@ -82,12 +82,6 @@
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "apps/red-ui/src/environments/environment.ts",
"with": "apps/red-ui/src/environments/environment.prod.ts"
}
],
"optimization": {
"scripts": true,
"styles": {

View File

@ -1,14 +1,12 @@
import { Component, Renderer2, ViewContainerRef } from '@angular/core';
import { RouterHistoryService } from '@services/router-history.service';
import { UserPreferenceService } from '@users/user-preference.service';
import { getConfig } from '@iqser/common-ui';
import { AppConfig } from '@red/domain';
import { NavigationEnd, Router } from '@angular/router';
import { filter, map, switchMap, take, tap } from 'rxjs/operators';
import { APP_TYPE_PATHS } from '@common-ui/utils/constants';
import { MatIconRegistry } from '@angular/material/icon';
import { DomSanitizer } from '@angular/platform-browser';
import { NavigationEnd, Router } from '@angular/router';
import { TenantsService } from '@common-ui/tenants';
import { APP_TYPE_PATHS } from '@common-ui/utils/constants';
import { RouterHistoryService } from '@services/router-history.service';
import { UserPreferenceService } from '@users/user-preference.service';
import { filter, map, switchMap, take, tap } from 'rxjs/operators';
export function loadCustomTheme(cssFileName: string) {
const head = document.getElementsByTagName('head')[0];
@ -29,17 +27,16 @@ export function loadCustomTheme(cssFileName: string) {
export class AppComponent {
constructor(
/** ViewContainerRef needs to be injected for the color picker to work */
readonly viewContainerRef: ViewContainerRef,
viewContainerRef: ViewContainerRef,
/** RouterHistoryService needs to be injected for last dossiers screen to be updated on first app load */
private readonly _routerHistoryService: RouterHistoryService,
routerHistoryService: RouterHistoryService,
userPreferenceService: UserPreferenceService,
renderer: Renderer2,
private readonly _router: Router,
private readonly _iconRegistry: MatIconRegistry,
private readonly _sanitizer: DomSanitizer,
iconRegistry: MatIconRegistry,
sanitizer: DomSanitizer,
private readonly _tenantsService: TenantsService,
) {
const config = getConfig<AppConfig>();
renderer.addClass(document.body, userPreferenceService.getTheme());
const removeQueryParams = _router.events.pipe(
@ -57,10 +54,10 @@ export class AppComponent {
tap(() => {
const isDocumine = this._tenantsService.activeTenant.documine;
const logo = isDocumine ? 'documine' : 'redaction';
_iconRegistry.addSvgIconInNamespace(
iconRegistry.addSvgIconInNamespace(
'iqser',
'logo',
_sanitizer.bypassSecurityTrustResourceUrl(`/assets/icons/general/${logo}-logo.svg`),
sanitizer.bypassSecurityTrustResourceUrl(`/assets/icons/general/${logo}-logo.svg`),
);
if (isDocumine) {
document.getElementById('favicon').setAttribute('href', 'assets/icons/documine-logo.ico');

View File

@ -1,6 +1,6 @@
import { APP_BASE_HREF, DatePipe as BaseDatePipe } from '@angular/common';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { ErrorHandler, inject, NgModule, provideEnvironmentInitializer } from '@angular/core';
import { ErrorHandler, inject, isDevMode, NgModule, provideEnvironmentInitializer } from '@angular/core';
import { MatDividerModule } from '@angular/material/divider';
import { MatIcon } from '@angular/material/icon';
import { MatMenu, MatMenuContent, MatMenuItem, MatMenuTrigger } from '@angular/material/menu';
@ -14,6 +14,7 @@ import { EmptyStateComponent } from '@common-ui/empty-state';
import { HelpModeKey } from '@common-ui/help-mode/types';
import { InputWithActionComponent } from '@common-ui/inputs/input-with-action/input-with-action.component';
import { RoundCheckboxComponent } from '@common-ui/inputs/round-checkbox/round-checkbox.component';
import { provideCommonUi } from '@common-ui/provide-common-ui';
import { GET_TENANT_FROM_PATH_FN, UI_ROOT } from '@common-ui/utils';
import { AuthErrorComponent } from '@components/auth-error/auth-error.component';
import { BaseScreenComponent } from '@components/base-screen/base-screen.component';
@ -27,10 +28,12 @@ import { SkeletonTopBarComponent } from '@components/skeleton/skeleton-top-bar/s
import { SpotlightSearchComponent } from '@components/spotlight-search/spotlight-search.component';
import { TenantsMenuComponent } from '@components/tenants-menu/tenants-menu.component';
import { UserMenuComponent } from '@components/user-menu/user-menu.component';
import { environment } from '@environments/environment';
import {
CachingModule,
CircleButtonComponent,
ConnectionStatusComponent,
FullPageErrorComponent,
getConfig,
HelpButtonComponent,
HelpModeComponent,
HiddenActionDirective,
@ -41,12 +44,10 @@ import {
IqserLoadingModule,
IqserTranslateModule,
LanguageService,
MAX_RETRIES_ON_SERVER_ERROR,
SERVER_ERROR_SKIP_PATHS,
ServerErrorInterceptor,
StopPropagationDirective,
} from '@iqser/common-ui';
import { CommonUiModule } from '@iqser/common-ui/lib/common-ui.module';
import { provideHelpMode } from '@iqser/common-ui/lib/help-mode/utils/help-mode.provider';
import { LogoComponent, SkeletonComponent, ToastComponent } from '@iqser/common-ui/lib/shared';
import { TenantsModule } from '@iqser/common-ui/lib/tenants';
@ -76,199 +77,192 @@ import { IconsModule } from './modules/icons/icons.module';
import { PdfViewerModule } from './modules/pdf-viewer/pdf-viewer.module';
import { ACTIVE_DOSSIERS_SERVICE, ARCHIVED_DOSSIERS_SERVICE } from './tokens';
export const appModuleFactory = (config: AppConfig) => {
@NgModule({
declarations: [
AppComponent,
AuthErrorComponent,
NotificationsComponent,
SpotlightSearchComponent,
BreadcrumbsComponent,
DashboardSkeletonComponent,
DossierSkeletonComponent,
SkeletonTopBarComponent,
SkeletonStatsComponent,
BaseScreenComponent,
UserMenuComponent,
TenantsMenuComponent,
DownloadsListScreenComponent,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
MonacoEditorModule,
CommonUiModule.forRoot({
existingUserPreferenceService: UserPreferenceService,
configService: ConfigService,
configServiceFactory: () => new ConfigService(config),
}),
IqserUsersModule.forRoot({
existingUserService: UserService,
existingRoleGuard: RedRoleGuard,
}),
CachingModule.forRoot(UI_CACHES),
PdfViewerModule,
ToastrModule.forRoot({
closeButton: true,
enableHtml: true,
toastComponent: ToastComponent,
preventDuplicates: true,
resetTimeoutOnDuplicate: true,
}),
TenantsModule.forRoot(),
IqserTranslateModule.forRoot({ pathPrefix: config.BASE_TRANSLATIONS_DIRECTORY }),
IqserLoadingModule.forRoot(),
ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
LoggerModule.forRoot(undefined, {
ruleProvider: {
provide: TOKEN_LOGGER_RULES_SERVICE,
useClass: LoggerRulesService,
},
configProvider: {
provide: TOKEN_LOGGER_CONFIG,
useValue: {
level: environment.production ? NgxLoggerLevel.ERROR : NgxLoggerLevel.DEBUG,
enableSourceMaps: false,
timestampFormat: 'mm:ss:SSS',
disableFileDetails: true,
features: {
ANNOTATIONS: {
color: 'aqua',
enabled: false,
level: NgxLoggerLevel.DEBUG,
},
FILTERS: {
enabled: false,
},
TENANTS: {
enabled: false,
},
ROUTES: {
enabled: false,
},
PDF: {
enabled: false,
},
FILE: {
enabled: false,
},
CHANGES: {
enabled: false,
},
STATS: {
enabled: false,
},
REDACTION_LOG: {
enabled: true,
},
VIEWED_PAGES: {
enabled: false,
},
PAGES: {
enabled: false,
},
DOSSIERS_CHANGES: {
enabled: false,
},
GUARDS: {
enabled: false,
},
},
} as ILoggerConfig,
},
}),
CircleButtonComponent,
EmptyStateComponent,
SkeletonComponent,
LogoComponent,
HiddenActionDirective,
StopPropagationDirective,
InputWithActionComponent,
RoundCheckboxComponent,
IqserAllowDirective,
IqserDenyDirective,
IqserListingModule,
IconButtonComponent,
MatDividerModule,
ChevronButtonComponent,
InitialsAvatarComponent,
HelpModeComponent,
HelpButtonComponent,
MatMenuTrigger,
MatMenuItem,
MatIcon,
MatMenu,
MatMenuContent,
MatTooltip,
MatProgressSpinner,
IconsModule,
NavigateLastDossiersScreenDirective,
DatePipe,
TranslateModule,
],
providers: [
{
provide: UI_ROOT,
useValue: '/ui',
@NgModule({
declarations: [
AppComponent,
AuthErrorComponent,
NotificationsComponent,
SpotlightSearchComponent,
BreadcrumbsComponent,
DashboardSkeletonComponent,
DossierSkeletonComponent,
SkeletonTopBarComponent,
SkeletonStatsComponent,
BaseScreenComponent,
UserMenuComponent,
TenantsMenuComponent,
DownloadsListScreenComponent,
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
MonacoEditorModule,
IqserUsersModule.forRoot({
existingUserService: UserService,
existingRoleGuard: RedRoleGuard,
}),
CachingModule.forRoot(UI_CACHES),
PdfViewerModule,
ToastrModule.forRoot({
closeButton: true,
enableHtml: true,
toastComponent: ToastComponent,
preventDuplicates: true,
resetTimeoutOnDuplicate: true,
}),
TenantsModule.forRoot(),
IqserTranslateModule.forRoot({ pathPrefixFactory: () => getConfig<AppConfig>().BASE_TRANSLATIONS_DIRECTORY }),
IqserLoadingModule.forRoot(),
ServiceWorkerModule.register('ngsw-worker.js', { enabled: !isDevMode() }),
LoggerModule.forRoot(undefined, {
ruleProvider: {
provide: TOKEN_LOGGER_RULES_SERVICE,
useClass: LoggerRulesService,
},
{
provide: APP_BASE_HREF,
useFactory: () => {
const uiRoot = inject(UI_ROOT);
const tenant = inject(GET_TENANT_FROM_PATH_FN)();
console.log(tenant);
const appBaseHref = uiRoot + '/' + tenant;
inject(NGXLogger).info('Provide APP_BASE_HREF:', appBaseHref);
return appBaseHref;
},
},
{
provide: HTTP_INTERCEPTORS,
multi: true,
useClass: ServerErrorInterceptor,
},
{
provide: ErrorHandler,
useClass: GlobalErrorHandler,
},
provideEnvironmentInitializer(async () => {
const languageService = inject(LanguageService);
return languageService.setInitialLanguage();
}),
{
provide: MAX_RETRIES_ON_SERVER_ERROR,
useFactory: () => config.MAX_RETRIES_ON_SERVER_ERROR,
},
{
provide: SERVER_ERROR_SKIP_PATHS,
useValue: ['redaction-gateway-v1/license'],
},
{
provide: ACTIVE_DOSSIERS_SERVICE,
useExisting: ActiveDossiersService,
},
{
provide: ARCHIVED_DOSSIERS_SERVICE,
useExisting: ArchivedDossiersService,
},
{
provide: MAT_TOOLTIP_DEFAULT_OPTIONS,
configProvider: {
provide: TOKEN_LOGGER_CONFIG,
useValue: {
disableTooltipInteractivity: true,
showDelay: 1,
},
level: !isDevMode() ? NgxLoggerLevel.ERROR : NgxLoggerLevel.DEBUG,
enableSourceMaps: false,
timestampFormat: 'mm:ss:SSS',
disableFileDetails: true,
features: {
ANNOTATIONS: {
color: 'aqua',
enabled: false,
level: NgxLoggerLevel.DEBUG,
},
FILTERS: {
enabled: false,
},
TENANTS: {
enabled: false,
},
ROUTES: {
enabled: false,
},
PDF: {
enabled: false,
},
FILE: {
enabled: false,
},
CHANGES: {
enabled: false,
},
STATS: {
enabled: false,
},
REDACTION_LOG: {
enabled: true,
},
VIEWED_PAGES: {
enabled: false,
},
PAGES: {
enabled: false,
},
DOSSIERS_CHANGES: {
enabled: false,
},
GUARDS: {
enabled: false,
},
},
} as ILoggerConfig,
},
BaseDatePipe,
DatePipe,
...provideCustomDateFormatter(),
...provideHelpMode(helpModeKeys as HelpModeKey[]),
ColorPickerService,
],
bootstrap: [AppComponent],
})
class AppModule {}
}),
CircleButtonComponent,
EmptyStateComponent,
SkeletonComponent,
LogoComponent,
HiddenActionDirective,
StopPropagationDirective,
InputWithActionComponent,
RoundCheckboxComponent,
IqserAllowDirective,
IqserDenyDirective,
IqserListingModule,
IconButtonComponent,
MatDividerModule,
ChevronButtonComponent,
InitialsAvatarComponent,
HelpModeComponent,
HelpButtonComponent,
MatMenuTrigger,
MatMenuItem,
MatIcon,
MatMenu,
MatMenuContent,
MatTooltip,
MatProgressSpinner,
IconsModule,
NavigateLastDossiersScreenDirective,
DatePipe,
TranslateModule,
ConnectionStatusComponent,
FullPageErrorComponent,
],
providers: [
{
provide: UI_ROOT,
useValue: '/ui',
},
{
provide: APP_BASE_HREF,
useFactory: () => {
const uiRoot = inject(UI_ROOT);
const tenant = inject(GET_TENANT_FROM_PATH_FN)();
console.log(tenant);
const appBaseHref = uiRoot + '/' + tenant;
return AppModule;
};
inject(NGXLogger).info('Provide APP_BASE_HREF:', appBaseHref);
return appBaseHref;
},
},
{
provide: HTTP_INTERCEPTORS,
multi: true,
useClass: ServerErrorInterceptor,
},
{
provide: ErrorHandler,
useClass: GlobalErrorHandler,
},
provideEnvironmentInitializer(async () => {
const languageService = inject(LanguageService);
await languageService.setInitialLanguage();
}),
{
provide: SERVER_ERROR_SKIP_PATHS,
useValue: ['redaction-gateway-v1/license'],
},
{
provide: ACTIVE_DOSSIERS_SERVICE,
useExisting: ActiveDossiersService,
},
{
provide: ARCHIVED_DOSSIERS_SERVICE,
useExisting: ArchivedDossiersService,
},
{
provide: MAT_TOOLTIP_DEFAULT_OPTIONS,
useValue: {
disableTooltipInteractivity: true,
showDelay: 1,
},
},
BaseDatePipe,
DatePipe,
provideCustomDateFormatter(),
provideHelpMode(helpModeKeys as HelpModeKey[]),
ColorPickerService,
provideCommonUi({
existingUserPreferenceService: UserPreferenceService,
configService: ConfigService,
}),
],
bootstrap: [AppComponent],
})
export class AppModule {}

View File

@ -1,13 +1,12 @@
import { AsyncPipe, NgClass, NgForOf, NgIf } from '@angular/common';
import { HttpClient } from '@angular/common/http';
import { ChangeDetectorRef, Component, ElementRef, inject, OnInit, ViewChild } from '@angular/core';
import { ChangeDetectorRef, Component, ElementRef, inject, isDevMode, OnInit, ViewChild } from '@angular/core';
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatIcon } from '@angular/material/icon';
import { MatSlider, MatSliderThumb } from '@angular/material/slider';
import { MatTooltip } from '@angular/material/tooltip';
import { Router } from '@angular/router';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { environment } from '@environments/environment';
import {
getConfig,
HasScrollbarDirective,
@ -262,7 +261,7 @@ export class WatermarkScreenComponent implements OnInit {
this._loadingService.stop();
});
if (environment.production) {
if (!isDevMode()) {
this.instance.Core.setCustomFontURL(window.location.origin + this.#convertPath('/assets/pdftron/fonts'));
}

View File

@ -1,8 +1,7 @@
import { DestroyRef, inject, Injectable, signal, Signal } from '@angular/core';
import { DestroyRef, inject, Injectable, isDevMode, signal, Signal } from '@angular/core';
import { takeUntilDestroyed, toObservable, toSignal } from '@angular/core/rxjs-interop';
import { ActivatedRoute } from '@angular/router';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { environment } from '@environments/environment';
import { ErrorService, getConfig, LanguageService } from '@iqser/common-ui';
import { shareDistinctLast, UI_ROOT_PATH_FN } from '@iqser/common-ui/lib/utils';
import { TranslateService } from '@ngx-translate/core';
@ -171,7 +170,7 @@ export class PdfViewer {
// https://docs.apryse.com/web/get-started/migrating-to-v11/
this.#instance = await WebViewer.Iframe(this.#webViewerConfig, htmlElement);
if (environment.production) {
if (!isDevMode()) {
this.#instance.Core.setCustomFontURL(window.location.origin + this.#convertPath('/assets/pdftron/fonts'));
}

View File

@ -1,8 +1,9 @@
import { makeEnvironmentProviders } from '@angular/core';
import { DateAdapter, MAT_DATE_FORMATS } from '@angular/material/core';
import { CustomDateAdapter } from '@shared/CustomDateAdapter';
export function provideCustomDateFormatter() {
return [
return makeEnvironmentProviders([
{
provide: DateAdapter,
useClass: CustomDateAdapter,
@ -21,5 +22,5 @@ export function provideCustomDateFormatter() {
},
},
},
];
]);
}

View File

@ -1,6 +1,17 @@
import { Injectable } from '@angular/core';
import { inject, Injectable } from '@angular/core';
import { IqserConfigService } from '@iqser/common-ui';
import { AppConfig } from '@red/domain';
import { NGXLogger } from 'ngx-logger';
import { INITIAL_CONFIG } from '../tokens';
@Injectable()
export class ConfigService extends IqserConfigService<AppConfig> {}
@Injectable({ providedIn: 'root' })
export class ConfigService extends IqserConfigService<AppConfig> {
readonly #logger = inject(NGXLogger);
constructor() {
const initialConfig = inject(INITIAL_CONFIG);
super(initialConfig);
this.#logger.info('App started with initial config: ', initialConfig);
this.#logger.info('Updated config: ', this._values);
}
}

View File

@ -1,6 +1,9 @@
import { InjectionToken } from '@angular/core';
import { AppConfig } from '@red/domain';
export const DOSSIER_ID = new InjectionToken<string>('DOSSIER_ID');
export const ACTIVE_DOSSIERS_SERVICE = new InjectionToken<string>('Active dossiers service');
export const ARCHIVED_DOSSIERS_SERVICE = new InjectionToken<string>('Archived dossiers service');
export const INITIAL_CONFIG = new InjectionToken<AppConfig>('Initial App config to init config service');

View File

@ -1,6 +0,0 @@
export const environment = {
production: true,
licenseKey:
'S25lY29uIEFHKGVuLmtuZWNvbi5zd2lzcyk6T0VNOkREQS1SOjpCKzpBTVMoMj' +
'AyMjEwMjkpOkZGQ0M0RDMzMDdEQUI0RjM4QjMxM0JDOUIyNDMzODJDNEU2RjZGQ0I4M0NEOEFDNTc0MzU4QTk1OTczMEI2MjJGQUJFRjVDNw==',
};

View File

@ -1,6 +0,0 @@
export const environment = {
production: false,
licenseKey:
'S25lY29uIEFHKGVuLmtuZWNvbi5zd2lzcyk6T0VNOkREQS1SOjpCKzpBTVMoMj' +
'AyMjEwMjkpOkZGQ0M0RDMzMDdEQUI0RjM4QjMxM0JDOUIyNDMzODJDNEU2RjZGQ0I4M0NEOEFDNTc0MzU4QTk1OTczMEI2MjJGQUJFRjVDNw==',
};

View File

@ -1,15 +1,9 @@
import { ApplicationRef, enableProdMode } from '@angular/core';
import { enableDebugTools } from '@angular/platform-browser';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { bool } from '@common-ui/utils';
import { environment } from '@environments/environment';
import { AppConfig } from '@red/domain';
import { appModuleFactory } from './app/app.module';
import { LANDING_PAGE_THEMES, THEME_DIRECTORIES } from '@common-ui/utils/constants';
if (environment.production) {
enableProdMode();
}
import { AppConfig } from '@red/domain';
import { AppModule } from './app/app.module';
import { INITIAL_CONFIG } from './app/tokens';
// https://github.com/angular/angular/issues/11195#issuecomment-248020928
async function bootstrap(appConfig: AppConfig, version: { FRONTEND_APP_VERSION: string }) {
@ -24,17 +18,13 @@ async function bootstrap(appConfig: AppConfig, version: { FRONTEND_APP_VERSION:
FRONTEND_APP_VERSION: version.FRONTEND_APP_VERSION,
APP_NAME: appConfig.LANDING_PAGE_THEME === LANDING_PAGE_THEMES.MIXED ? 'Knecon Cloud' : isDocumine ? 'DocuMine' : 'RedactManager',
} as AppConfig;
console.log('Started with local config: ', config);
const appModule = appModuleFactory(config);
const ngModuleRef = await platformBrowserDynamic().bootstrapModule(appModule, { ngZoneEventCoalescing: true });
if (!environment.production) {
const applicationRef = ngModuleRef.injector.get(ApplicationRef);
const componentRef = applicationRef.components[0];
// allows to run `ng.profiler.timeChangeDetection();`
enableDebugTools(componentRef);
}
await platformBrowserDynamic([
{
provide: INITIAL_CONFIG,
useValue: config,
},
]).bootstrapModule(AppModule, { ngZoneEventCoalescing: true });
}
const randomNr = Math.random().toFixed(2);

@ -1 +1 @@
Subproject commit 58382ddfeed1d6d4d61f03abd1bbb0dd840afa94
Subproject commit 3bd45d958d7f9c7d504f907c2c4067244565c6f1

View File

@ -8,7 +8,6 @@ export interface AppConfig extends IqserAppConfig {
readonly BACKEND_APP_VERSION: string;
readonly EULA_URL: string;
readonly MAX_FILE_SIZE_MB: number;
readonly MAX_RETRIES_ON_SERVER_ERROR: number;
readonly RECENT_PERIOD_IN_HOURS: number;
readonly SELECTION_MODE: string;
readonly ANNOTATIONS_THRESHOLD: number;