Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bd45d958d | ||
|
|
36cc0cff3a |
@ -1,101 +0,0 @@
|
||||
import { inject, ModuleWithProviders, NgModule, Optional, Provider, SkipSelf } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { MatIconModule, MatIconRegistry } from '@angular/material/icon';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { CommonUiOptions, IqserAppConfig, ModuleOptions } from './utils';
|
||||
import { ConnectionStatusComponent, FullPageErrorComponent } from './error';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatCheckboxModule } from '@angular/material/checkbox';
|
||||
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
||||
import { MatTooltipModule } from '@angular/material/tooltip';
|
||||
import { ApiPathInterceptor, DefaultUserPreferenceService, IqserConfigService, IqserUserPreferenceService } from './services';
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { MatDialogModule } from '@angular/material/dialog';
|
||||
import { CircleButtonComponent, IconButtonComponent } from './buttons';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { ICONS } from './utils/constants';
|
||||
import { StopPropagationDirective } from './directives';
|
||||
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
|
||||
|
||||
const matModules = [MatIconModule, MatButtonModule, MatDialogModule, MatCheckboxModule, MatTooltipModule, MatProgressBarModule];
|
||||
const components = [ConnectionStatusComponent, FullPageErrorComponent];
|
||||
|
||||
@NgModule({
|
||||
declarations: [...components],
|
||||
imports: [
|
||||
CommonModule,
|
||||
...matModules,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
TranslateModule,
|
||||
IconButtonComponent,
|
||||
CircleButtonComponent,
|
||||
StopPropagationDirective,
|
||||
],
|
||||
exports: [...components],
|
||||
providers: [
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
multi: true,
|
||||
useClass: ApiPathInterceptor,
|
||||
},
|
||||
{ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { appearance: 'outline' } },
|
||||
],
|
||||
})
|
||||
export class CommonUiModule {
|
||||
constructor(@Optional() @SkipSelf() parentModule?: CommonUiModule) {
|
||||
if (parentModule) {
|
||||
throw new Error('CommonUiModule is already loaded. Import it in the AppModule only!');
|
||||
}
|
||||
|
||||
const iconRegistry = inject(MatIconRegistry);
|
||||
const sanitizer = inject(DomSanitizer);
|
||||
|
||||
ICONS.forEach(icon => {
|
||||
const url = sanitizer.bypassSecurityTrustResourceUrl(`/assets/icons/${icon}.svg`);
|
||||
iconRegistry.addSvgIconInNamespace('iqser', icon, url);
|
||||
});
|
||||
}
|
||||
|
||||
static forRoot<
|
||||
UserPreference extends IqserUserPreferenceService,
|
||||
Config extends IqserConfigService<AppConfig>,
|
||||
AppConfig extends IqserAppConfig = IqserAppConfig,
|
||||
>(options: CommonUiOptions<UserPreference, Config, AppConfig>): ModuleWithProviders<CommonUiModule> {
|
||||
const userPreferenceService = ModuleOptions.getService(
|
||||
IqserUserPreferenceService,
|
||||
DefaultUserPreferenceService,
|
||||
options.existingUserPreferenceService,
|
||||
);
|
||||
|
||||
const configServiceProviders = this._getConfigServiceProviders(options.configServiceFactory, options.configService);
|
||||
|
||||
return {
|
||||
ngModule: CommonUiModule,
|
||||
providers: [userPreferenceService, ...configServiceProviders],
|
||||
};
|
||||
}
|
||||
|
||||
private static _getConfigServiceProviders(configServiceFactory: () => unknown, configService?: unknown): Provider[] {
|
||||
if (configService) {
|
||||
return [
|
||||
{
|
||||
provide: configService,
|
||||
useFactory: configServiceFactory,
|
||||
},
|
||||
{
|
||||
provide: IqserConfigService,
|
||||
useExisting: configService,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
provide: IqserConfigService,
|
||||
useFactory: configServiceFactory,
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
import { animate, state, style, transition, trigger } from '@angular/animations';
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
||||
import { NgClass } from '@angular/common';
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { connectionStatusTranslations } from '../../translations';
|
||||
import { ErrorService } from '../error.service';
|
||||
@ -16,8 +17,7 @@ import { ErrorService } from '../error.service';
|
||||
transition('* => online', animate('3s ease-in')),
|
||||
]),
|
||||
],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: false,
|
||||
imports: [NgClass],
|
||||
})
|
||||
export class ConnectionStatusComponent {
|
||||
protected readonly connectionStatusTranslations = connectionStatusTranslations;
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { fromEvent, merge, Observable, Subject } from 'rxjs';
|
||||
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
|
||||
import { LoadingService } from '../loading';
|
||||
import { distinctUntilChanged, filter, map, tap } from 'rxjs/operators';
|
||||
import { NavigationStart, Router } from '@angular/router';
|
||||
import { shareLast } from '../utils';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
|
||||
import { NavigationStart, Router } from '@angular/router';
|
||||
import { fromEvent, merge, Observable, Subject } from 'rxjs';
|
||||
import { distinctUntilChanged, filter, map, tap } from 'rxjs/operators';
|
||||
import { LoadingService } from '../loading';
|
||||
import { shareLast } from '../utils';
|
||||
|
||||
export class CustomError {
|
||||
readonly label: string;
|
||||
@ -39,17 +39,17 @@ const isSameEventType = (previous: Event | string | undefined, current: Event |
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ErrorService {
|
||||
readonly offline$: Observable<Event>;
|
||||
readonly online$: Observable<Event>;
|
||||
readonly connectionStatus$: Observable<string | undefined>;
|
||||
readonly #error$ = new Subject<ErrorType>();
|
||||
readonly error$ = this.#error$.pipe(filter(error => !error || !isOffline(error)));
|
||||
readonly #error$ = new Subject<ErrorType | undefined>();
|
||||
readonly #online$ = new Subject();
|
||||
readonly #loadingService = inject(LoadingService);
|
||||
readonly #router = inject(Router);
|
||||
readonly #displayNotification$ = new Subject<string | undefined>();
|
||||
#notificationTimeout: Record<string, NodeJS.Timeout | undefined> = {};
|
||||
#displayedNotificationType: string | undefined;
|
||||
readonly offline$: Observable<Event>;
|
||||
readonly online$: Observable<Event>;
|
||||
readonly connectionStatus$: Observable<string | undefined>;
|
||||
readonly error$ = this.#error$.pipe(filter(error => !error || !isOffline(error)));
|
||||
|
||||
constructor() {
|
||||
this.#router.events
|
||||
|
||||
@ -1,15 +1,18 @@
|
||||
@if (errorService.error$ | async; as error) {
|
||||
@if (normalizedError(); as normalizedError) {
|
||||
<section class="full-page-section"></section>
|
||||
<section class="full-page-content flex-align-items-center">
|
||||
<mat-icon svgIcon="iqser:failure"></mat-icon>
|
||||
<div [translate]="errorTitle(error)" class="heading-l mt-24"></div>
|
||||
@if (error.message) {
|
||||
<div class="mt-16 error">{{ error.message }}</div>
|
||||
|
||||
<div [translate]="normalizedError.title" class="heading-l mt-24"></div>
|
||||
|
||||
@if (normalizedError.error.message) {
|
||||
<div class="mt-16 error">{{ normalizedError.error.message }}</div>
|
||||
}
|
||||
|
||||
<iqser-icon-button
|
||||
(action)="action(error)"
|
||||
[icon]="actionIcon(error)"
|
||||
[label]="actionLabel(error) | translate"
|
||||
(action)="action(normalizedError.error)"
|
||||
[icon]="normalizedError.actionIcon"
|
||||
[label]="normalizedError.actionLabel | translate"
|
||||
[type]="iconButtonTypes.primary"
|
||||
class="mt-20"
|
||||
></iqser-icon-button>
|
||||
|
||||
@ -1,30 +1,33 @@
|
||||
import { ChangeDetectionStrategy, Component, inject } from '@angular/core';
|
||||
import { Component, computed, inject } from '@angular/core';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { MatIcon } from '@angular/material/icon';
|
||||
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
|
||||
import { IconButtonTypes } from '../../buttons';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { IconButtonComponent, IconButtonTypes } from '../../buttons';
|
||||
import { CustomError, ErrorService, ErrorType } from '../error.service';
|
||||
|
||||
@Component({
|
||||
selector: 'iqser-full-page-error',
|
||||
templateUrl: './full-page-error.component.html',
|
||||
styleUrls: ['./full-page-error.component.scss'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
standalone: false,
|
||||
imports: [MatIcon, IconButtonComponent, TranslatePipe],
|
||||
})
|
||||
export class FullPageErrorComponent {
|
||||
readonly #error = toSignal(inject(ErrorService).error$);
|
||||
protected readonly normalizedError = computed(() => {
|
||||
const error = this.#error();
|
||||
if (!error) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
error: error,
|
||||
title: error instanceof CustomError ? error.label : _('error.title'),
|
||||
actionLabel: error instanceof CustomError ? error.actionLabel : _('error.reload'),
|
||||
actionIcon: error instanceof CustomError ? error.actionIcon : 'iqser:refresh',
|
||||
};
|
||||
});
|
||||
protected readonly iconButtonTypes = IconButtonTypes;
|
||||
protected readonly errorService = inject(ErrorService);
|
||||
|
||||
errorTitle(error: ErrorType): string {
|
||||
return error instanceof CustomError ? error.label : _('error.title');
|
||||
}
|
||||
|
||||
actionLabel(error: ErrorType): string {
|
||||
return error instanceof CustomError ? error.actionLabel : _('error.reload');
|
||||
}
|
||||
|
||||
actionIcon(error: ErrorType): string {
|
||||
return error instanceof CustomError ? error.actionIcon : 'iqser:refresh';
|
||||
}
|
||||
|
||||
action(error: ErrorType): void {
|
||||
if (error instanceof CustomError && error.action) {
|
||||
|
||||
@ -10,10 +10,11 @@ import {
|
||||
import { Inject, Injectable, Optional } from '@angular/core';
|
||||
import { finalize, MonoTypeOperatorFunction, Observable, retry, throwError, timer } from 'rxjs';
|
||||
import { catchError, tap } from 'rxjs/operators';
|
||||
import { MAX_RETRIES_ON_SERVER_ERROR, SERVER_ERROR_SKIP_PATHS } from './tokens';
|
||||
import { ErrorService } from './error.service';
|
||||
import { KeycloakStatusService } from '../tenants';
|
||||
import { LoadingService } from '../loading';
|
||||
import { getConfig } from '../services';
|
||||
import { KeycloakStatusService } from '../tenants';
|
||||
import { ErrorService } from './error.service';
|
||||
import { SERVER_ERROR_SKIP_PATHS } from './tokens';
|
||||
|
||||
function updateSeconds(seconds: number) {
|
||||
if (seconds === 0 || seconds === 1) {
|
||||
@ -52,12 +53,12 @@ function backoffOnServerError(maxRetries = 3, skippedPaths: string[] = []): Mono
|
||||
@Injectable()
|
||||
export class ServerErrorInterceptor implements HttpInterceptor {
|
||||
private readonly _urlsWithError = new Set();
|
||||
readonly #config = getConfig();
|
||||
|
||||
constructor(
|
||||
private readonly _errorService: ErrorService,
|
||||
private readonly _loadingService: LoadingService,
|
||||
private readonly _keycloakStatusService: KeycloakStatusService,
|
||||
@Optional() @Inject(MAX_RETRIES_ON_SERVER_ERROR) private readonly _maxRetries: number,
|
||||
@Optional() @Inject(SERVER_ERROR_SKIP_PATHS) private readonly _skippedPaths: string[],
|
||||
) {}
|
||||
|
||||
@ -88,7 +89,7 @@ export class ServerErrorInterceptor implements HttpInterceptor {
|
||||
}),
|
||||
);
|
||||
}),
|
||||
backoffOnServerError(this._maxRetries, this._skippedPaths),
|
||||
backoffOnServerError(this.#config.MAX_RETRIES_ON_SERVER_ERROR, this._skippedPaths),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { InjectionToken } from '@angular/core';
|
||||
|
||||
export const MAX_RETRIES_ON_SERVER_ERROR = new InjectionToken<number>('Number of retries before giving up');
|
||||
export const SERVER_ERROR_SKIP_PATHS = new InjectionToken<string[]>('A list of paths to skip when handling server errors');
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { Inject, Injectable, Renderer2, RendererFactory2 } from '@angular/core';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { BehaviorSubject, firstValueFrom } from 'rxjs';
|
||||
import { getConfig } from '../services';
|
||||
import { IqserUserPreferenceService } from '../services';
|
||||
import { getConfig, IqserUserPreferenceService } from '../services';
|
||||
import { HelpModeDialogComponent } from './help-mode-dialog/help-mode-dialog.component';
|
||||
import { HELP_MODE_KEYS, MANUAL_BASE_URL } from './tokens';
|
||||
import { HELP_MODE_KEYS } from './tokens';
|
||||
import { HelpModeKey } from './types';
|
||||
import {
|
||||
DOCUMINE_THEME_CLASS,
|
||||
@ -20,7 +20,6 @@ import {
|
||||
ScrollableParentViews,
|
||||
WEB_VIEWER_ELEMENTS,
|
||||
} from './utils/constants';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
|
||||
export interface Helper {
|
||||
readonly element: HTMLElement;
|
||||
@ -39,13 +38,13 @@ export class HelpModeService {
|
||||
readonly #isDocumine = getConfig().IS_DOCUMINE;
|
||||
#helpers: Record<string, Helper> = {};
|
||||
#dialogMode = false;
|
||||
readonly #config = getConfig();
|
||||
readonly isHelpModeActive$ = this.#isHelpModeActive$.asObservable();
|
||||
readonly isHelpModeActive = toSignal(this.isHelpModeActive$, { initialValue: false });
|
||||
readonly helpModeDialogIsOpened$ = this.#helpModeDialogIsOpened$.asObservable();
|
||||
|
||||
constructor(
|
||||
@Inject(HELP_MODE_KEYS) private readonly _keys: HelpModeKey[],
|
||||
@Inject(MANUAL_BASE_URL) private readonly _manualBaseURL: string,
|
||||
private readonly _dialog: MatDialog,
|
||||
private readonly _rendererFactory: RendererFactory2,
|
||||
private readonly _translateService: TranslateService,
|
||||
@ -161,7 +160,7 @@ export class HelpModeService {
|
||||
|
||||
#generateDocsLink(key: string) {
|
||||
const currentLang = this._translateService.currentLang;
|
||||
return `${this._manualBaseURL}/${currentLang}/index-${currentLang}.html?contextId=${key}`;
|
||||
return `${this.#config.MANUAL_BASE_URL}/${currentLang}/index-${currentLang}.html?contextId=${key}`;
|
||||
}
|
||||
|
||||
#isElementVisible(helper: Helper): boolean {
|
||||
|
||||
@ -1,8 +1,4 @@
|
||||
import { inject, InjectionToken } from '@angular/core';
|
||||
import { IqserConfigService } from '../services/iqser-config.service';
|
||||
import { InjectionToken } from '@angular/core';
|
||||
import { HelpModeKey } from './types';
|
||||
|
||||
export const HELP_MODE_KEYS = new InjectionToken<HelpModeKey>('Help mode keys');
|
||||
export const MANUAL_BASE_URL = new InjectionToken<string>('Base manual URL', {
|
||||
factory: () => inject(IqserConfigService).values.MANUAL_BASE_URL,
|
||||
});
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { makeEnvironmentProviders } from '@angular/core';
|
||||
import { HelpModeService } from '../help-mode.service';
|
||||
import { HELP_MODE_KEYS } from '../tokens';
|
||||
import { HelpModeKey } from '../types';
|
||||
|
||||
export function provideHelpMode(helpModeKeys: HelpModeKey[]) {
|
||||
return [{ provide: HELP_MODE_KEYS, useValue: helpModeKeys }, HelpModeService];
|
||||
return makeEnvironmentProviders([{ provide: HELP_MODE_KEYS, useValue: helpModeKeys }, HelpModeService]);
|
||||
}
|
||||
|
||||
17
src/lib/interceptors/api-path.interceptor.ts
Normal file
17
src/lib/interceptors/api-path.interceptor.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { HttpHandlerFn, HttpInterceptorFn, HttpRequest } from '@angular/common/http';
|
||||
import { inject } from '@angular/core';
|
||||
import { getConfig } from '../services/iqser-config.service';
|
||||
import { UI_ROOT_PATH_FN } from '../utils/tokens';
|
||||
|
||||
export const apiPathInterceptorFn: HttpInterceptorFn = (req: HttpRequest<unknown>, next: HttpHandlerFn) => {
|
||||
const config = getConfig();
|
||||
const convertPath = inject(UI_ROOT_PATH_FN);
|
||||
|
||||
if (!req.url.startsWith('/assets')) {
|
||||
const apiUrl = `${config.API_URL}${req.url}`;
|
||||
return next(req.clone({ url: apiUrl }));
|
||||
}
|
||||
|
||||
const url = convertPath(req.url);
|
||||
return next(req.clone({ url }));
|
||||
};
|
||||
49
src/lib/provide-common-ui.ts
Normal file
49
src/lib/provide-common-ui.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { provideHttpClient, withInterceptors } from '@angular/common/http';
|
||||
import { EnvironmentProviders, inject, makeEnvironmentProviders, provideAppInitializer, Provider, Type } from '@angular/core';
|
||||
import { MAT_FORM_FIELD_DEFAULT_OPTIONS } from '@angular/material/form-field';
|
||||
import { MatIconRegistry } from '@angular/material/icon';
|
||||
import { DomSanitizer } from '@angular/platform-browser';
|
||||
import { apiPathInterceptorFn } from './interceptors/api-path.interceptor';
|
||||
import { CONFIG_SERVICE, DefaultUserPreferenceService, IqserConfigService, IqserUserPreferenceService } from './services';
|
||||
import { ICONS } from './utils/constants';
|
||||
|
||||
type ProvideCommonUiOptions = {
|
||||
configService: Type<IqserConfigService>;
|
||||
existingUserPreferenceService: Type<IqserUserPreferenceService>;
|
||||
};
|
||||
|
||||
export function provideCommonUi(options: ProvideCommonUiOptions): EnvironmentProviders {
|
||||
return makeEnvironmentProviders([
|
||||
provideCommonIcons(),
|
||||
{
|
||||
provide: CONFIG_SERVICE,
|
||||
useExisting: options.configService,
|
||||
},
|
||||
provideHttpClient(withInterceptors([apiPathInterceptorFn])),
|
||||
{ provide: MAT_FORM_FIELD_DEFAULT_OPTIONS, useValue: { appearance: 'outline' } },
|
||||
getService(IqserUserPreferenceService, DefaultUserPreferenceService, options.existingUserPreferenceService),
|
||||
]);
|
||||
}
|
||||
|
||||
export function getService<B, D, E>(base: B, _default: Type<D>, existing?: E): Provider {
|
||||
if (existing) {
|
||||
return {
|
||||
provide: base,
|
||||
useExisting: existing,
|
||||
};
|
||||
}
|
||||
|
||||
return { provide: base, useClass: _default };
|
||||
}
|
||||
|
||||
function provideCommonIcons() {
|
||||
return provideAppInitializer(() => {
|
||||
const iconRegistry = inject(MatIconRegistry);
|
||||
const sanitizer = inject(DomSanitizer);
|
||||
|
||||
ICONS.forEach(icon => {
|
||||
const url = sanitizer.bypassSecurityTrustResourceUrl(`/assets/icons/${icon}.svg`);
|
||||
iconRegistry.addSvgIconInNamespace('iqser', icon, url);
|
||||
});
|
||||
});
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
|
||||
import { inject, Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { UI_ROOT_PATH_FN } from '../utils/tokens';
|
||||
import { getConfig } from './iqser-config.service';
|
||||
|
||||
@Injectable()
|
||||
export class ApiPathInterceptor implements HttpInterceptor {
|
||||
readonly #config = getConfig();
|
||||
readonly #convertPath = inject(UI_ROOT_PATH_FN);
|
||||
|
||||
intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
|
||||
if (!req.url.startsWith('/assets')) {
|
||||
const apiUrl = `${this.#config.API_URL}${req.url}`;
|
||||
return next.handle(req.clone({ url: apiUrl }));
|
||||
}
|
||||
|
||||
const url = this.#convertPath(req.url);
|
||||
return next.handle(req.clone({ url }));
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,3 @@
|
||||
import exp from 'constants';
|
||||
|
||||
export * from './toaster.service';
|
||||
export * from './error-message.service';
|
||||
export * from './generic.service';
|
||||
@ -9,5 +7,4 @@ export * from './entities-map.service';
|
||||
export * from './iqser-user-preference.service';
|
||||
export * from './language.service';
|
||||
export * from './iqser-config.service';
|
||||
export * from './api-path.interceptor';
|
||||
export * from './skeleton.service';
|
||||
|
||||
@ -1,18 +1,19 @@
|
||||
import { Inject, inject, Injectable } from '@angular/core';
|
||||
import { inject, InjectionToken } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { CacheApiService } from '../caching/cache-api.service';
|
||||
import { wipeAllCaches } from '../caching/cache-utils';
|
||||
import { IqserAppConfig } from '../utils/iqser-app-config';
|
||||
import { LANDING_PAGE_THEMES, MANUAL_BASE_URL, THEME_DIRECTORIES } from '../utils/constants';
|
||||
import { IStoredTenantId, TenantsService } from '../tenants';
|
||||
import { LANDING_PAGE_THEMES, MANUAL_BASE_URL, THEME_DIRECTORIES } from '../utils/constants';
|
||||
import { IqserAppConfig } from '../utils/iqser-app-config';
|
||||
|
||||
@Injectable()
|
||||
export class IqserConfigService<T extends IqserAppConfig = IqserAppConfig> {
|
||||
export const CONFIG_SERVICE = new InjectionToken<IqserConfigService>('IqserConfigService');
|
||||
|
||||
export abstract class IqserConfigService<T extends IqserAppConfig = IqserAppConfig> {
|
||||
protected readonly _cacheApiService = inject(CacheApiService);
|
||||
protected readonly _titleService = inject(Title);
|
||||
protected readonly _tenantsService = inject(TenantsService);
|
||||
|
||||
constructor(@Inject('Doesnt matter') protected _values: T) {
|
||||
protected constructor(protected _values: T) {
|
||||
this._checkFrontendVersion();
|
||||
this.#updateAppType();
|
||||
this._titleService.setTitle(this._values.APP_NAME);
|
||||
@ -73,5 +74,5 @@ export class IqserConfigService<T extends IqserAppConfig = IqserAppConfig> {
|
||||
}
|
||||
|
||||
export function getConfig<T extends IqserAppConfig = IqserAppConfig>() {
|
||||
return inject<IqserConfigService<T>>(IqserConfigService).values;
|
||||
return inject<IqserConfigService<T>>(CONFIG_SERVICE).values;
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
export interface IqserTranslateModuleOptions {
|
||||
readonly pathPrefix?: string;
|
||||
readonly pathPrefixFactory?: () => string;
|
||||
}
|
||||
|
||||
@ -45,7 +45,10 @@ export class IqserTranslateModule {
|
||||
providers: [
|
||||
{
|
||||
provide: translateLoaderToken,
|
||||
useFactory: () => pruningTranslationLoaderFactory(pathPrefix),
|
||||
useFactory: () => {
|
||||
const prefix = options?.pathPrefixFactory !== undefined ? options.pathPrefixFactory() : pathPrefix;
|
||||
return pruningTranslationLoaderFactory(prefix);
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: MissingTranslationHandler,
|
||||
|
||||
@ -17,4 +17,3 @@ export * from './context.component';
|
||||
export * from './tokens';
|
||||
export * from './module-options';
|
||||
export * from './iqser-app-config';
|
||||
export * from './types/common-ui-options';
|
||||
|
||||
@ -9,4 +9,5 @@ export interface IqserAppConfig {
|
||||
readonly MANUAL_BASE_URL: string;
|
||||
readonly BASE_TRANSLATIONS_DIRECTORY?: string;
|
||||
readonly LANDING_PAGE_THEME: 'redactmanager' | 'documine' | 'mixed';
|
||||
readonly MAX_RETRIES_ON_SERVER_ERROR?: number;
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ export const UI_ROOT_PATH_FN = new InjectionToken<(path: string) => string>('App
|
||||
const root = inject(UI_ROOT);
|
||||
|
||||
return (path: string) => {
|
||||
if (path[0] === '/') {
|
||||
if (path.startsWith('/')) {
|
||||
return root + path;
|
||||
}
|
||||
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
import { Type } from '@angular/core';
|
||||
import { IqserConfigService } from '../../services/iqser-config.service';
|
||||
import { IqserUserPreferenceService } from '../../services/iqser-user-preference.service';
|
||||
import { IqserAppConfig } from '../iqser-app-config';
|
||||
|
||||
export interface CommonUiOptions<
|
||||
UserPreference extends IqserUserPreferenceService,
|
||||
Config extends IqserConfigService<AppConfig>,
|
||||
AppConfig extends IqserAppConfig,
|
||||
> {
|
||||
existingUserPreferenceService?: Type<UserPreference>;
|
||||
configService?: Type<Config>;
|
||||
configServiceFactory: () => Config;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user