diff --git a/src/app/browse-by/browse-by-switcher/browse-by-decorator.ts b/src/app/browse-by/browse-by-switcher/browse-by-decorator.ts index 1ebaa7face..ceb4c6a6c6 100644 --- a/src/app/browse-by/browse-by-switcher/browse-by-decorator.ts +++ b/src/app/browse-by/browse-by-switcher/browse-by-decorator.ts @@ -1,6 +1,10 @@ import { hasNoValue } from '../../shared/empty.util'; import { InjectionToken } from '@angular/core'; import { GenericConstructor } from '../../core/shared/generic-constructor'; +import { + DEFAULT_THEME, + resolveTheme +} from '../../shared/object-collection/shared/listable-object/listable-object.decorator'; export enum BrowseByDataType { Title = 'title', @@ -10,7 +14,7 @@ export enum BrowseByDataType { export const DEFAULT_BROWSE_BY_TYPE = BrowseByDataType.Metadata; -export const BROWSE_BY_COMPONENT_FACTORY = new InjectionToken<(browseByType) => GenericConstructor>('getComponentByBrowseByType', { +export const BROWSE_BY_COMPONENT_FACTORY = new InjectionToken<(browseByType, theme) => GenericConstructor>('getComponentByBrowseByType', { providedIn: 'root', factory: () => getComponentByBrowseByType }); @@ -20,13 +24,17 @@ const map = new Map(); /** * Decorator used for rendering Browse-By pages by type * @param browseByType The type of page + * @param theme The optional theme for the component */ -export function rendersBrowseBy(browseByType: BrowseByDataType) { +export function rendersBrowseBy(browseByType: BrowseByDataType, theme = DEFAULT_THEME) { return function decorator(component: any) { if (hasNoValue(map.get(browseByType))) { - map.set(browseByType, component); + map.set(browseByType, new Map()); + } + if (hasNoValue(map.get(browseByType).get(theme))) { + map.get(browseByType).set(theme, component); } else { - throw new Error(`There can't be more than one component to render Browse-By of type "${browseByType}"`); + throw new Error(`There can't be more than one component to render Browse-By of type "${browseByType}" and theme "${theme}"`); } }; } @@ -34,11 +42,16 @@ export function rendersBrowseBy(browseByType: BrowseByDataType) { /** * Get the component used for rendering a Browse-By page by type * @param browseByType The type of page + * @param theme the theme to match */ -export function getComponentByBrowseByType(browseByType) { - const comp = map.get(browseByType); +export function getComponentByBrowseByType(browseByType, theme) { + let themeMap = map.get(browseByType); + if (hasNoValue(themeMap)) { + themeMap = map.get(DEFAULT_BROWSE_BY_TYPE); + } + const comp = resolveTheme(themeMap, theme); if (hasNoValue(comp)) { - map.get(DEFAULT_BROWSE_BY_TYPE); + return themeMap.get(DEFAULT_THEME); } return comp; } diff --git a/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.spec.ts b/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.spec.ts index cb82ddb7c4..c2e1c9cb68 100644 --- a/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.spec.ts +++ b/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.spec.ts @@ -4,7 +4,8 @@ import { NO_ERRORS_SCHEMA } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { BROWSE_BY_COMPONENT_FACTORY, BrowseByDataType } from './browse-by-decorator'; import { BrowseDefinition } from '../../core/shared/browse-definition.model'; -import { BehaviorSubject, of as observableOf } from 'rxjs'; +import { BehaviorSubject } from 'rxjs'; +import { ThemeService } from '../../shared/theme-support/theme.service'; describe('BrowseBySwitcherComponent', () => { let comp: BrowseBySwitcherComponent; @@ -44,11 +45,20 @@ describe('BrowseBySwitcherComponent', () => { data }; + let themeService: ThemeService; + let themeName: string; + beforeEach(waitForAsync(() => { + themeName = 'dspace'; + themeService = jasmine.createSpyObj('themeService', { + getThemeName: themeName, + }); + TestBed.configureTestingModule({ declarations: [BrowseBySwitcherComponent], providers: [ { provide: ActivatedRoute, useValue: activatedRouteStub }, + { provide: ThemeService, useValue: themeService }, { provide: BROWSE_BY_COMPONENT_FACTORY, useValue: jasmine.createSpy('getComponentByBrowseByType').and.returnValue(null) } ], schemas: [NO_ERRORS_SCHEMA] @@ -68,7 +78,7 @@ describe('BrowseBySwitcherComponent', () => { }); it(`should call getComponentByBrowseByType with type "${type.dataType}"`, () => { - expect((comp as any).getComponentByBrowseByType).toHaveBeenCalledWith(type.dataType); + expect((comp as any).getComponentByBrowseByType).toHaveBeenCalledWith(type.dataType, themeName); }); }); }); diff --git a/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.ts b/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.ts index cf4c1d9856..0d3a35bebf 100644 --- a/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.ts +++ b/src/app/browse-by/browse-by-switcher/browse-by-switcher.component.ts @@ -5,6 +5,7 @@ import { map } from 'rxjs/operators'; import { BROWSE_BY_COMPONENT_FACTORY } from './browse-by-decorator'; import { GenericConstructor } from '../../core/shared/generic-constructor'; import { BrowseDefinition } from '../../core/shared/browse-definition.model'; +import { ThemeService } from '../../shared/theme-support/theme.service'; @Component({ selector: 'ds-browse-by-switcher', @@ -21,7 +22,8 @@ export class BrowseBySwitcherComponent implements OnInit { browseByComponent: Observable; public constructor(protected route: ActivatedRoute, - @Inject(BROWSE_BY_COMPONENT_FACTORY) private getComponentByBrowseByType: (browseByType) => GenericConstructor) { + protected themeService: ThemeService, + @Inject(BROWSE_BY_COMPONENT_FACTORY) private getComponentByBrowseByType: (browseByType, theme) => GenericConstructor) { } /** @@ -29,7 +31,7 @@ export class BrowseBySwitcherComponent implements OnInit { */ ngOnInit(): void { this.browseByComponent = this.route.data.pipe( - map((data: { browseDefinition: BrowseDefinition }) => this.getComponentByBrowseByType(data.browseDefinition.dataType)) + map((data: { browseDefinition: BrowseDefinition }) => this.getComponentByBrowseByType(data.browseDefinition.dataType, this.themeService.getThemeName())) ); } diff --git a/src/app/shared/search/search-results/themed-search-results.component.ts b/src/app/shared/search/search-results/themed-search-results.component.ts new file mode 100644 index 0000000000..19a8fc55e8 --- /dev/null +++ b/src/app/shared/search/search-results/themed-search-results.component.ts @@ -0,0 +1,64 @@ +import { ThemedComponent } from '../../theme-support/themed.component'; +import { SearchResultsComponent, SelectionConfig } from './search-results.component'; +import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { CollectionElementLinkType } from '../../object-collection/collection-element-link.type'; +import { RemoteData } from '../../../core/data/remote-data'; +import { PaginatedList } from '../../../core/data/paginated-list.model'; +import { SearchResult } from '../models/search-result.model'; +import { DSpaceObject } from '../../../core/shared/dspace-object.model'; +import { PaginatedSearchOptions } from '../models/paginated-search-options.model'; +import { SortOptions } from '../../../core/cache/models/sort-options.model'; +import { ViewMode } from '../../../core/shared/view-mode.model'; +import { Context } from '../../../core/shared/context.model'; +import { ListableObject } from '../../object-collection/shared/listable-object.model'; + +/** + * Themed wrapper for SearchResultsComponent + */ +@Component({ + selector: 'ds-themed-search-results', + styleUrls: [], + templateUrl: '../../theme-support/themed.component.html', +}) +export class ThemedSearchResultsComponent extends ThemedComponent { + protected inAndOutputNames: (keyof SearchResultsComponent & keyof this)[] = ['linkType', 'searchResults', 'searchConfig', 'sortConfig', 'viewMode', 'configuration', 'disableHeader', 'selectable', 'context', 'hidePaginationDetail', 'selectionConfig', 'deselectObject', 'selectObject']; + + @Input() linkType: CollectionElementLinkType; + + @Input() searchResults: RemoteData>>; + + @Input() searchConfig: PaginatedSearchOptions; + + @Input() sortConfig: SortOptions; + + @Input() viewMode: ViewMode; + + @Input() configuration: string; + + @Input() disableHeader = false; + + @Input() selectable = false; + + @Input() context: Context; + + @Input() hidePaginationDetail = false; + + @Input() selectionConfig: SelectionConfig = null; + + @Output() deselectObject: EventEmitter = new EventEmitter(); + + @Output() selectObject: EventEmitter = new EventEmitter(); + + protected getComponentName(): string { + return 'SearchResultsComponent'; + } + + protected importThemedComponent(themeName: string): Promise { + return import(`../../../../themes/${themeName}/app/shared/search/search-results/search-results.component`); + } + + protected importUnthemedComponent(): Promise { + return import('./search-results.component'); + } + +} diff --git a/src/app/shared/search/search.component.html b/src/app/shared/search/search.component.html index c292c94c44..95f051778f 100644 --- a/src/app/shared/search/search.component.html +++ b/src/app/shared/search/search.component.html @@ -29,7 +29,7 @@ | translate}} - + (selectObject)="selectObject.emit($event)"> diff --git a/src/app/shared/search/search.module.ts b/src/app/shared/search/search.module.ts index 797d35d88f..cbc6d3e2f7 100644 --- a/src/app/shared/search/search.module.ts +++ b/src/app/shared/search/search.module.ts @@ -29,6 +29,7 @@ import { SharedModule } from '../shared.module'; import { SearchResultsComponent } from './search-results/search-results.component'; import { SearchComponent } from './search.component'; import { ThemedSearchComponent } from './themed-search.component'; +import { ThemedSearchResultsComponent } from './search-results/themed-search-results.component'; const COMPONENTS = [ SearchComponent, @@ -52,7 +53,8 @@ const COMPONENTS = [ SearchAuthorityFilterComponent, SearchSwitchConfigurationComponent, ConfigurationSearchPageComponent, - ThemedConfigurationSearchPageComponent + ThemedConfigurationSearchPageComponent, + ThemedSearchResultsComponent, ]; const ENTRY_COMPONENTS = [ diff --git a/src/themes/custom/app/shared/search/search-results/search-results.component.html b/src/themes/custom/app/shared/search/search-results/search-results.component.html new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/shared/search/search-results/search-results.component.scss b/src/themes/custom/app/shared/search/search-results/search-results.component.scss new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/themes/custom/app/shared/search/search-results/search-results.component.ts b/src/themes/custom/app/shared/search/search-results/search-results.component.ts new file mode 100644 index 0000000000..5084d4d405 --- /dev/null +++ b/src/themes/custom/app/shared/search/search-results/search-results.component.ts @@ -0,0 +1,17 @@ +import { SearchResultsComponent as BaseComponent } from '../../../../../../app/shared/search/search-results/search-results.component'; +import { Component } from '@angular/core'; +import { fadeIn, fadeInOut } from '../../../../../../app/shared/animations/fade'; + +@Component({ + selector: 'ds-search-results', + // templateUrl: './search-results.component.html', + templateUrl: '../../../../../../app/shared/search/search-results/search-results.component.html', + // styleUrls: ['./search-results.component.scss'], + animations: [ + fadeIn, + fadeInOut + ] +}) +export class SearchResultsComponent extends BaseComponent { + +} diff --git a/src/themes/custom/theme.module.ts b/src/themes/custom/theme.module.ts index 46607db98f..1c21f7f8af 100644 --- a/src/themes/custom/theme.module.ts +++ b/src/themes/custom/theme.module.ts @@ -94,6 +94,7 @@ import { EditItemTemplatePageComponent } from './app/collection-page/edit-item-template-page/edit-item-template-page.component'; import { LoadingComponent } from './app/shared/loading/loading.component'; +import { SearchResultsComponent } from './app/shared/search/search-results/search-results.component'; const DECLARATIONS = [ FileSectionComponent, @@ -143,6 +144,7 @@ const DECLARATIONS = [ ItemMetadataComponent, EditItemTemplatePageComponent, LoadingComponent, + SearchResultsComponent, ]; @NgModule({