diff --git a/src/app/shared/abstract-component-loader/dynamic-component-loader.utils.ts b/src/app/shared/abstract-component-loader/dynamic-component-loader.utils.ts new file mode 100644 index 00000000000..395da651836 --- /dev/null +++ b/src/app/shared/abstract-component-loader/dynamic-component-loader.utils.ts @@ -0,0 +1,123 @@ +import { hasNoValue, hasValue, isNotEmpty } from '../empty.util'; +import { DEFAULT_THEME } from '../object-collection/shared/listable-object/listable-object.decorator'; +import { ThemeConfig } from '../../../config/theme.model'; +import { environment } from '../../../environments/environment'; + +/** + * A class used to compare two matches and their relevancy to determine which of the two gains priority over the other + * + * "level" represents the index of the first default value that was used to find the match with: + * ViewMode being index 0, Context index 1 and theme index 2. Examples: + * - If a default value was used for context, but not view-mode and theme, the "level" will be 1 + * - If a default value was used for view-mode and context, but not for theme, the "level" will be 0 + * - If no default value was used for any of the fields, the "level" will be 3 + * + * "relevancy" represents the amount of values that didn't require a default value to fall back on. Examples: + * - If a default value was used for theme, but not view-mode and context, the "relevancy" will be 2 + * - If a default value was used for view-mode and context, but not for theme, the "relevancy" will be 1 + * - If a default value was used for all fields, the "relevancy" will be 0 + * - If no default value was used for any of the fields, the "relevancy" will be 3 + * + * To determine which of two MatchRelevancies is the most relevant, we compare "level" and "relevancy" in that order. + * If any of the two is higher than the other, that match is most relevant. Examples: + * - { level: 1, relevancy: 1 } is more relevant than { level: 0, relevancy: 2 } + * - { level: 1, relevancy: 1 } is less relevant than { level: 1, relevancy: 2 } + * - { level: 1, relevancy: 1 } is more relevant than { level: 1, relevancy: 0 } + * - { level: 1, relevancy: 1 } is less relevant than { level: 2, relevancy: 0 } + * - { level: 1, relevancy: 1 } is more relevant than null + */ +export class MatchRelevancy { + constructor(public match: any, + public level: number, + public relevancy: number) { + } + + isMoreRelevantThan(otherMatch: MatchRelevancy): boolean { + if (hasNoValue(otherMatch)) { + return true; + } + if (otherMatch.level > this.level) { + return false; + } + return !(otherMatch.level === this.level && otherMatch.relevancy > this.relevancy); + } + + isLessRelevantThan(otherMatch: MatchRelevancy): boolean { + return !this.isMoreRelevantThan(otherMatch); + } +} + +/** + * Find an object within a nested map, matching the provided keys as good as possible, falling back on defaults wherever + * needed. + * + * Starting off with a Map, it loops over the provided keys, going deeper into the map until it finds a value + * If at some point, no value is found, it'll attempt to use the default value for that index instead + * If the default value exists, the index is stored in the "level" + * If no default value exists, 1 is added to "relevancy" + * See {@link MatchRelevancy} what these represent + * + * @param typeMap a multidimensional map + * @param keys the keys of the multidimensional map to loop over. Each key represents a level within the map + * @param defaults the default values to use for each level, in case no value is found for the key at that index + * @returns matchAndLevel a {@link MatchRelevancy} object containing the match and its level of relevancy + */ +export function getMatch(typeMap: Map, keys: any[], defaults: any[]): MatchRelevancy { + let currentMap = typeMap; + let level = -1; + let relevancy = 0; + for (let i = 0; i < keys.length; i++) { + // If we're currently checking the theme, resolve it first to take extended themes into account + let currentMatch = defaults[i] === DEFAULT_THEME ? resolveTheme(currentMap, keys[i]) : currentMap.get(keys[i]); + if (hasNoValue(currentMatch)) { + currentMatch = currentMap.get(defaults[i]); + if (level === -1) { + level = i; + } + } else { + relevancy++; + } + if (hasValue(currentMatch)) { + if (currentMatch instanceof Map) { + currentMap = currentMatch as Map; + } else { + return new MatchRelevancy(currentMatch, level > -1 ? level : i + 1, relevancy); + } + } else { + return null; + } + } + return null; +} + +/** + * Searches for a ThemeConfig by its name; + */ +export const getThemeConfigFor = (themeName: string): ThemeConfig => { + return environment.themes.find((theme: ThemeConfig) => theme.name === themeName); +}; + +/** + * Find a match in the given map for the given theme name, taking theme extension into account + * + * @param contextMap A map of theme names to components + * @param themeName The name of the theme to check + * @param checkedThemeNames The list of theme names that are already checked + */ +export const resolveTheme = (contextMap: Map, themeName: string, checkedThemeNames: string[] = []): any => { + const match = contextMap.get(themeName); + if (hasValue(match)) { + return match; + } else { + const cfg: ThemeConfig = getThemeConfigFor(themeName); + if (hasValue(cfg) && isNotEmpty(cfg.extends)) { + const nextTheme: string = cfg.extends; + const nextCheckedThemeNames: string[] = [...checkedThemeNames, themeName]; + if (checkedThemeNames.includes(nextTheme)) { + throw new Error('Theme extension cycle detected: ' + [...nextCheckedThemeNames, nextTheme].join(' -> ')); + } else { + return resolveTheme(contextMap, nextTheme, nextCheckedThemeNames); + } + } + } +}; diff --git a/src/app/shared/log-in/container/log-in-container.component.spec.ts b/src/app/shared/log-in/container/log-in-container.component.spec.ts index 29598e422ec..c8c4a0eb96a 100644 --- a/src/app/shared/log-in/container/log-in-container.component.spec.ts +++ b/src/app/shared/log-in/container/log-in-container.component.spec.ts @@ -13,6 +13,8 @@ import { AuthMethod } from '../../../core/auth/models/auth.method'; import { AuthServiceStub } from '../../testing/auth-service.stub'; import { createTestComponent } from '../../testing/utils.test'; import { HardRedirectService } from '../../../core/services/hard-redirect.service'; +import { ThemeService } from '../../theme-support/theme.service'; +import { getMockThemeService } from '../../mocks/theme-service.mock'; describe('LogInContainerComponent', () => { @@ -43,6 +45,7 @@ describe('LogInContainerComponent', () => { providers: [ { provide: AuthService, useClass: AuthServiceStub }, { provide: HardRedirectService, useValue: hardRedirectService }, + { provide: ThemeService, useValue: getMockThemeService() }, LogInContainerComponent ], schemas: [ diff --git a/src/app/shared/log-in/container/log-in-container.component.ts b/src/app/shared/log-in/container/log-in-container.component.ts index f6a08a1e1ec..1bdde5c9f11 100644 --- a/src/app/shared/log-in/container/log-in-container.component.ts +++ b/src/app/shared/log-in/container/log-in-container.component.ts @@ -2,6 +2,7 @@ import { Component, Injector, Input, OnInit } from '@angular/core'; import { rendersAuthMethodType } from '../methods/log-in.methods-decorator'; import { AuthMethod } from '../../../core/auth/models/auth.method'; +import { ThemeService } from '../../theme-support/theme.service'; /** * This component represents a component container for log-in methods available. @@ -27,12 +28,10 @@ export class LogInContainerComponent implements OnInit { */ public objectInjector: Injector; - /** - * Initialize instance variables - * - * @param {Injector} injector - */ - constructor(private injector: Injector) { + constructor( + private injector: Injector, + private themeService: ThemeService, + ) { } /** @@ -52,7 +51,7 @@ export class LogInContainerComponent implements OnInit { * Find the correct component based on the AuthMethod's type */ getAuthMethodContent(): string { - return rendersAuthMethodType(this.authMethod.authMethodType); + return rendersAuthMethodType(this.authMethod.authMethodType, this.themeService.getThemeName()); } } diff --git a/src/app/shared/log-in/log-in.component.spec.ts b/src/app/shared/log-in/log-in.component.spec.ts index 0a13e8b701e..c518b23bacb 100644 --- a/src/app/shared/log-in/log-in.component.spec.ts +++ b/src/app/shared/log-in/log-in.component.spec.ts @@ -21,6 +21,8 @@ import { RouterTestingModule } from '@angular/router/testing'; import { HardRedirectService } from '../../core/services/hard-redirect.service'; import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service'; import { of } from 'rxjs'; +import { ThemeService } from '../theme-support/theme.service'; +import { getMockThemeService } from '../mocks/theme-service.mock'; describe('LogInComponent', () => { @@ -70,10 +72,10 @@ describe('LogInComponent', () => { providers: [ { provide: AuthService, useClass: AuthServiceStub }, { provide: NativeWindowService, useFactory: NativeWindowMockFactory }, - // { provide: Router, useValue: new RouterStub() }, { provide: ActivatedRoute, useValue: new ActivatedRouteStub() }, { provide: HardRedirectService, useValue: hardRedirectService }, { provide: AuthorizationDataService, useValue: authorizationService }, + { provide: ThemeService, useValue: getMockThemeService() }, provideMockStore({ initialState }), LogInComponent ], diff --git a/src/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.spec.ts b/src/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.spec.ts index de4f62eb9eb..7d4508b5901 100644 --- a/src/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.spec.ts +++ b/src/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.spec.ts @@ -1,5 +1,5 @@ import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; -import { ActivatedRoute, Router } from '@angular/router'; +import { Router } from '@angular/router'; import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'; import { provideMockStore } from '@ngrx/store/testing'; @@ -17,7 +17,6 @@ import { AuthMethodType } from '../../../../core/auth/models/auth.method-type'; import { LogInExternalProviderComponent } from './log-in-external-provider.component'; import { NativeWindowService } from '../../../../core/services/window.service'; import { RouterStub } from '../../../testing/router.stub'; -import { ActivatedRouteStub } from '../../../testing/active-router.stub'; import { NativeWindowMockFactory } from '../../../mocks/mock-native-window-ref'; import { HardRedirectService } from '../../../../core/services/hard-redirect.service'; @@ -73,7 +72,6 @@ describe('LogInExternalProviderComponent', () => { { provide: 'isStandalonePage', useValue: true }, { provide: NativeWindowService, useFactory: NativeWindowMockFactory }, { provide: Router, useValue: new RouterStub() }, - { provide: ActivatedRoute, useValue: new ActivatedRouteStub() }, { provide: HardRedirectService, useValue: hardRedirectService }, provideMockStore({ initialState }), ], diff --git a/src/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.ts b/src/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.ts index f1829684575..6ec2da18424 100644 --- a/src/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.ts +++ b/src/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.ts @@ -63,9 +63,9 @@ export class LogInExternalProviderComponent implements OnInit { @Inject('authMethodProvider') public injectedAuthMethodModel: AuthMethod, @Inject('isStandalonePage') public isStandalonePage: boolean, @Inject(NativeWindowService) protected _window: NativeWindowRef, - private authService: AuthService, - private hardRedirectService: HardRedirectService, - private store: Store + protected authService: AuthService, + protected hardRedirectService: HardRedirectService, + protected store: Store ) { this.authMethod = injectedAuthMethodModel; } diff --git a/src/app/shared/log-in/methods/log-in.methods-decorator.ts b/src/app/shared/log-in/methods/log-in.methods-decorator.ts index 0614bdeb511..84e1ea77b61 100644 --- a/src/app/shared/log-in/methods/log-in.methods-decorator.ts +++ b/src/app/shared/log-in/methods/log-in.methods-decorator.ts @@ -1,16 +1,21 @@ import { AuthMethodType } from '../../../core/auth/models/auth.method-type'; +import { DEFAULT_THEME } from '../../object-collection/shared/listable-object/listable-object.decorator'; +import { hasNoValue } from '../../empty.util'; +import { getMatch } from '../../abstract-component-loader/dynamic-component-loader.utils'; + +export const DEFAULT_AUTH_METHOD_TYPE = AuthMethodType.Password; const authMethodsMap = new Map(); -export function renderAuthMethodFor(authMethodType: AuthMethodType) { - return function decorator(objectElement: any) { - if (!objectElement) { - return; +export function renderAuthMethodFor(authMethodType: AuthMethodType, theme = DEFAULT_THEME) { + return function decorator(component: any) { + if (hasNoValue(authMethodsMap.get(authMethodType))) { + authMethodsMap.set(authMethodType, new Map()); } - authMethodsMap.set(authMethodType, objectElement); + authMethodsMap.get(authMethodType).set(theme, component); }; } -export function rendersAuthMethodType(authMethodType: AuthMethodType) { - return authMethodsMap.get(authMethodType); +export function rendersAuthMethodType(authMethodType: AuthMethodType, theme: string) { + return getMatch(authMethodsMap, [authMethodType, theme], [DEFAULT_AUTH_METHOD_TYPE, DEFAULT_THEME]).match; } diff --git a/src/app/shared/log-in/methods/password/log-in-password.component.ts b/src/app/shared/log-in/methods/password/log-in-password.component.ts index 22b3b131308..70ed4529464 100644 --- a/src/app/shared/log-in/methods/password/log-in-password.component.ts +++ b/src/app/shared/log-in/methods/password/log-in-password.component.ts @@ -77,10 +77,10 @@ export class LogInPasswordComponent implements OnInit { constructor( @Inject('authMethodProvider') public injectedAuthMethodModel: AuthMethod, @Inject('isStandalonePage') public isStandalonePage: boolean, - private authService: AuthService, - private hardRedirectService: HardRedirectService, - private formBuilder: UntypedFormBuilder, - private store: Store + protected authService: AuthService, + protected hardRedirectService: HardRedirectService, + protected formBuilder: UntypedFormBuilder, + protected store: Store ) { this.authMethod = injectedAuthMethodModel; } diff --git a/src/app/shared/metadata-representation/metadata-representation.decorator.ts b/src/app/shared/metadata-representation/metadata-representation.decorator.ts index ae601e480c4..599db7b4639 100644 --- a/src/app/shared/metadata-representation/metadata-representation.decorator.ts +++ b/src/app/shared/metadata-representation/metadata-representation.decorator.ts @@ -3,10 +3,8 @@ import { hasNoValue, hasValue } from '../empty.util'; import { Context } from '../../core/shared/context.model'; import { InjectionToken } from '@angular/core'; import { GenericConstructor } from '../../core/shared/generic-constructor'; -import { - resolveTheme, - DEFAULT_THEME, DEFAULT_CONTEXT -} from '../object-collection/shared/listable-object/listable-object.decorator'; +import { DEFAULT_THEME, DEFAULT_CONTEXT } from '../object-collection/shared/listable-object/listable-object.decorator'; +import { getMatch } from '../abstract-component-loader/dynamic-component-loader.utils'; export const METADATA_REPRESENTATION_COMPONENT_FACTORY = new InjectionToken<(entityType: string, mdRepresentationType: MetadataRepresentationType, context: Context, theme: string) => GenericConstructor>('getMetadataRepresentationComponent', { providedIn: 'root', @@ -53,30 +51,5 @@ export function metadataRepresentationComponent(entityType: string, mdRepresenta * @param theme the theme to match */ export function getMetadataRepresentationComponent(entityType: string, mdRepresentationType: MetadataRepresentationType, context: Context = DEFAULT_CONTEXT, theme = DEFAULT_THEME) { - const mapForEntity = map.get(entityType); - if (hasValue(mapForEntity)) { - const entityAndMDRepMap = mapForEntity.get(mdRepresentationType); - if (hasValue(entityAndMDRepMap)) { - const contextMap = entityAndMDRepMap.get(context); - if (hasValue(contextMap)) { - const match = resolveTheme(contextMap, theme); - if (hasValue(match)) { - return match; - } - if (hasValue(contextMap.get(DEFAULT_THEME))) { - return contextMap.get(DEFAULT_THEME); - } - } - if (hasValue(entityAndMDRepMap.get(DEFAULT_CONTEXT)) && - hasValue(entityAndMDRepMap.get(DEFAULT_CONTEXT).get(DEFAULT_THEME))) { - return entityAndMDRepMap.get(DEFAULT_CONTEXT).get(DEFAULT_THEME); - } - } - if (hasValue(mapForEntity.get(DEFAULT_REPRESENTATION_TYPE)) && - hasValue(mapForEntity.get(DEFAULT_REPRESENTATION_TYPE).get(DEFAULT_CONTEXT)) && - hasValue(mapForEntity.get(DEFAULT_REPRESENTATION_TYPE).get(DEFAULT_CONTEXT).get(DEFAULT_THEME))) { - return mapForEntity.get(DEFAULT_REPRESENTATION_TYPE).get(DEFAULT_CONTEXT).get(DEFAULT_THEME); - } - } - return map.get(DEFAULT_ENTITY_TYPE).get(DEFAULT_REPRESENTATION_TYPE).get(DEFAULT_CONTEXT).get(DEFAULT_THEME); + return getMatch(map, [entityType, mdRepresentationType, context, theme], [DEFAULT_ENTITY_TYPE, DEFAULT_REPRESENTATION_TYPE, DEFAULT_CONTEXT, DEFAULT_THEME]).match; } diff --git a/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.ts b/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.ts index e5654e63e00..872622577f9 100644 --- a/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.ts +++ b/src/app/shared/object-collection/shared/listable-object/listable-object.decorator.ts @@ -1,63 +1,20 @@ import { ViewMode } from '../../../../core/shared/view-mode.model'; import { Context } from '../../../../core/shared/context.model'; -import { hasNoValue, hasValue, isNotEmpty } from '../../../empty.util'; +import { hasNoValue, hasValue } from '../../../empty.util'; import { GenericConstructor } from '../../../../core/shared/generic-constructor'; import { ListableObject } from '../listable-object.model'; -import { environment } from '../../../../../environments/environment'; import { ThemeConfig } from '../../../../../config/theme.model'; import { InjectionToken } from '@angular/core'; +import { + getMatch, + getThemeConfigFor, + MatchRelevancy, +} from '../../../abstract-component-loader/dynamic-component-loader.utils'; export const DEFAULT_VIEW_MODE = ViewMode.ListElement; export const DEFAULT_CONTEXT = Context.Any; export const DEFAULT_THEME = '*'; -/** - * A class used to compare two matches and their relevancy to determine which of the two gains priority over the other - * - * "level" represents the index of the first default value that was used to find the match with: - * ViewMode being index 0, Context index 1 and theme index 2. Examples: - * - If a default value was used for context, but not view-mode and theme, the "level" will be 1 - * - If a default value was used for view-mode and context, but not for theme, the "level" will be 0 - * - If no default value was used for any of the fields, the "level" will be 3 - * - * "relevancy" represents the amount of values that didn't require a default value to fall back on. Examples: - * - If a default value was used for theme, but not view-mode and context, the "relevancy" will be 2 - * - If a default value was used for view-mode and context, but not for theme, the "relevancy" will be 1 - * - If a default value was used for all fields, the "relevancy" will be 0 - * - If no default value was used for any of the fields, the "relevancy" will be 3 - * - * To determine which of two MatchRelevancies is the most relevant, we compare "level" and "relevancy" in that order. - * If any of the two is higher than the other, that match is most relevant. Examples: - * - { level: 1, relevancy: 1 } is more relevant than { level: 0, relevancy: 2 } - * - { level: 1, relevancy: 1 } is less relevant than { level: 1, relevancy: 2 } - * - { level: 1, relevancy: 1 } is more relevant than { level: 1, relevancy: 0 } - * - { level: 1, relevancy: 1 } is less relevant than { level: 2, relevancy: 0 } - * - { level: 1, relevancy: 1 } is more relevant than null - */ -class MatchRelevancy { - constructor(public match: any, - public level: number, - public relevancy: number) { - } - - isMoreRelevantThan(otherMatch: MatchRelevancy): boolean { - if (hasNoValue(otherMatch)) { - return true; - } - if (otherMatch.level > this.level) { - return false; - } - if (otherMatch.level === this.level && otherMatch.relevancy > this.relevancy) { - return false; - } - return true; - } - - isLessRelevantThan(otherMatch: MatchRelevancy): boolean { - return !this.isMoreRelevantThan(otherMatch); - } -} - /** * Factory to allow us to inject getThemeConfigFor so we can mock it in tests */ @@ -118,77 +75,3 @@ export function getListableObjectComponent(types: (string | GenericConstructor, keys: any[], defaults: any[]): MatchRelevancy { - let currentMap = typeMap; - let level = -1; - let relevancy = 0; - for (let i = 0; i < keys.length; i++) { - // If we're currently checking the theme, resolve it first to take extended themes into account - let currentMatch = defaults[i] === DEFAULT_THEME ? resolveTheme(currentMap, keys[i]) : currentMap.get(keys[i]); - if (hasNoValue(currentMatch)) { - currentMatch = currentMap.get(defaults[i]); - if (level === -1) { - level = i; - } - } else { - relevancy++; - } - if (hasValue(currentMatch)) { - if (currentMatch instanceof Map) { - currentMap = currentMatch as Map; - } else { - return new MatchRelevancy(currentMatch, level > -1 ? level : i + 1, relevancy); - } - } else { - return null; - } - } - return null; -} - -/** - * Searches for a ThemeConfig by its name; - */ -export const getThemeConfigFor = (themeName: string): ThemeConfig => { - return environment.themes.find(theme => theme.name === themeName); -}; - -/** - * Find a match in the given map for the given theme name, taking theme extension into account - * - * @param contextMap A map of theme names to components - * @param themeName The name of the theme to check - * @param checkedThemeNames The list of theme names that are already checked - */ -export const resolveTheme = (contextMap: Map, themeName: string, checkedThemeNames: string[] = []): any => { - const match = contextMap.get(themeName); - if (hasValue(match)) { - return match; - } else { - const cfg = getThemeConfigFor(themeName); - if (hasValue(cfg) && isNotEmpty(cfg.extends)) { - const nextTheme = cfg.extends; - const nextCheckedThemeNames = [...checkedThemeNames, themeName]; - if (checkedThemeNames.includes(nextTheme)) { - throw new Error('Theme extension cycle detected: ' + [...nextCheckedThemeNames, nextTheme].join(' -> ')); - } else { - return resolveTheme(contextMap, nextTheme, nextCheckedThemeNames); - } - } - } -}; diff --git a/src/themes/custom/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.html b/src/themes/custom/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.html new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/themes/custom/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.scss b/src/themes/custom/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/themes/custom/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.ts b/src/themes/custom/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.ts new file mode 100644 index 00000000000..d1d840e14df --- /dev/null +++ b/src/themes/custom/app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.ts @@ -0,0 +1,18 @@ +import { Component, } from '@angular/core'; + +import { AuthMethodType } from '../../../../../../../app/core/auth/models/auth.method-type'; +import { renderAuthMethodFor } from '../../../../../../../app/shared/log-in/methods/log-in.methods-decorator'; +import { LogInExternalProviderComponent as BaseComponent } from '../../../../../../../app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component'; + +@Component({ + selector: 'ds-log-in-external-provider', + // templateUrl: './log-in-external-provider.component.html', + templateUrl: '../../../../../../../app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.html', + // styleUrls: ['./log-in-external-provider.component.scss'], + styleUrls: ['../../../../../../../app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component.scss'], +}) +@renderAuthMethodFor(AuthMethodType.Oidc, 'custom') +@renderAuthMethodFor(AuthMethodType.Shibboleth, 'custom') +@renderAuthMethodFor(AuthMethodType.Orcid, 'custom') +export class LogInExternalProviderComponent extends BaseComponent { +} diff --git a/src/themes/custom/app/shared/log-in/methods/password/log-in-password.component.html b/src/themes/custom/app/shared/log-in/methods/password/log-in-password.component.html new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/themes/custom/app/shared/log-in/methods/password/log-in-password.component.scss b/src/themes/custom/app/shared/log-in/methods/password/log-in-password.component.scss new file mode 100644 index 00000000000..e69de29bb2d diff --git a/src/themes/custom/app/shared/log-in/methods/password/log-in-password.component.ts b/src/themes/custom/app/shared/log-in/methods/password/log-in-password.component.ts new file mode 100644 index 00000000000..8425b8fd05e --- /dev/null +++ b/src/themes/custom/app/shared/log-in/methods/password/log-in-password.component.ts @@ -0,0 +1,18 @@ +import { Component } from '@angular/core'; + +import { AuthMethodType } from '../../../../../../../app/core/auth/models/auth.method-type'; +import { fadeOut } from '../../../../../../../app/shared/animations/fade'; +import { renderAuthMethodFor } from '../../../../../../../app/shared/log-in/methods/log-in.methods-decorator'; +import { LogInPasswordComponent as BaseComponent } from '../../../../../../../app/shared/log-in/methods/password/log-in-password.component'; + +@Component({ + selector: 'ds-log-in-password', + // templateUrl: './log-in-password.component.html', + templateUrl: '../../../../../../../app/shared/log-in/methods/password/log-in-password.component.html', + // styleUrls: ['./log-in-password.component.scss'], + styleUrls: ['../../../../../../../app/shared/log-in/methods/password/log-in-password.component.scss'], + animations: [fadeOut], +}) +@renderAuthMethodFor(AuthMethodType.Password, 'custom') +export class LogInPasswordComponent extends BaseComponent { +} diff --git a/src/themes/custom/eager-theme.module.ts b/src/themes/custom/eager-theme.module.ts index 7d7f5b3d8b4..a5759495a4b 100644 --- a/src/themes/custom/eager-theme.module.ts +++ b/src/themes/custom/eager-theme.module.ts @@ -54,6 +54,10 @@ import { ItemSearchResultListElementComponent } from './app/shared/object-list/search-result-list-element/item-search-result/item-types/item/item-search-result-list-element.component'; import { TopLevelCommunityListComponent } from './app/home-page/top-level-community-list/top-level-community-list.component'; +import { + LogInExternalProviderComponent +} from './app/shared/log-in/methods/log-in-external-provider/log-in-external-provider.component'; +import { LogInPasswordComponent } from './app/shared/log-in/methods/password/log-in-password.component'; /** @@ -75,6 +79,8 @@ const ENTRY_COMPONENTS = [ PublicationSidebarSearchListElementComponent, ItemSearchResultListElementComponent, TopLevelCommunityListComponent, + LogInExternalProviderComponent, + LogInPasswordComponent, ]; const DECLARATIONS = [