mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 10:04:11 +00:00
89676: Themeable browse-by-page decorator & search-results component
This commit is contained in:
@@ -1,6 +1,10 @@
|
|||||||
import { hasNoValue } from '../../shared/empty.util';
|
import { hasNoValue } from '../../shared/empty.util';
|
||||||
import { InjectionToken } from '@angular/core';
|
import { InjectionToken } from '@angular/core';
|
||||||
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
||||||
|
import {
|
||||||
|
DEFAULT_THEME,
|
||||||
|
resolveTheme
|
||||||
|
} from '../../shared/object-collection/shared/listable-object/listable-object.decorator';
|
||||||
|
|
||||||
export enum BrowseByDataType {
|
export enum BrowseByDataType {
|
||||||
Title = 'title',
|
Title = 'title',
|
||||||
@@ -10,7 +14,7 @@ export enum BrowseByDataType {
|
|||||||
|
|
||||||
export const DEFAULT_BROWSE_BY_TYPE = BrowseByDataType.Metadata;
|
export const DEFAULT_BROWSE_BY_TYPE = BrowseByDataType.Metadata;
|
||||||
|
|
||||||
export const BROWSE_BY_COMPONENT_FACTORY = new InjectionToken<(browseByType) => GenericConstructor<any>>('getComponentByBrowseByType', {
|
export const BROWSE_BY_COMPONENT_FACTORY = new InjectionToken<(browseByType, theme) => GenericConstructor<any>>('getComponentByBrowseByType', {
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
factory: () => getComponentByBrowseByType
|
factory: () => getComponentByBrowseByType
|
||||||
});
|
});
|
||||||
@@ -20,13 +24,17 @@ const map = new Map();
|
|||||||
/**
|
/**
|
||||||
* Decorator used for rendering Browse-By pages by type
|
* Decorator used for rendering Browse-By pages by type
|
||||||
* @param browseByType The type of page
|
* @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) {
|
return function decorator(component: any) {
|
||||||
if (hasNoValue(map.get(browseByType))) {
|
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 {
|
} 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
|
* Get the component used for rendering a Browse-By page by type
|
||||||
* @param browseByType The type of page
|
* @param browseByType The type of page
|
||||||
|
* @param theme the theme to match
|
||||||
*/
|
*/
|
||||||
export function getComponentByBrowseByType(browseByType) {
|
export function getComponentByBrowseByType(browseByType, theme) {
|
||||||
const comp = map.get(browseByType);
|
let themeMap = map.get(browseByType);
|
||||||
|
if (hasNoValue(themeMap)) {
|
||||||
|
themeMap = map.get(DEFAULT_BROWSE_BY_TYPE);
|
||||||
|
}
|
||||||
|
const comp = resolveTheme(themeMap, theme);
|
||||||
if (hasNoValue(comp)) {
|
if (hasNoValue(comp)) {
|
||||||
map.get(DEFAULT_BROWSE_BY_TYPE);
|
return themeMap.get(DEFAULT_THEME);
|
||||||
}
|
}
|
||||||
return comp;
|
return comp;
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,7 @@ import { map } from 'rxjs/operators';
|
|||||||
import { BROWSE_BY_COMPONENT_FACTORY } from './browse-by-decorator';
|
import { BROWSE_BY_COMPONENT_FACTORY } from './browse-by-decorator';
|
||||||
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
import { GenericConstructor } from '../../core/shared/generic-constructor';
|
||||||
import { BrowseDefinition } from '../../core/shared/browse-definition.model';
|
import { BrowseDefinition } from '../../core/shared/browse-definition.model';
|
||||||
|
import { ThemeService } from '../../shared/theme-support/theme.service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-browse-by-switcher',
|
selector: 'ds-browse-by-switcher',
|
||||||
@@ -21,7 +22,8 @@ export class BrowseBySwitcherComponent implements OnInit {
|
|||||||
browseByComponent: Observable<any>;
|
browseByComponent: Observable<any>;
|
||||||
|
|
||||||
public constructor(protected route: ActivatedRoute,
|
public constructor(protected route: ActivatedRoute,
|
||||||
@Inject(BROWSE_BY_COMPONENT_FACTORY) private getComponentByBrowseByType: (browseByType) => GenericConstructor<any>) {
|
protected themeService: ThemeService,
|
||||||
|
@Inject(BROWSE_BY_COMPONENT_FACTORY) private getComponentByBrowseByType: (browseByType, theme) => GenericConstructor<any>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -29,7 +31,7 @@ export class BrowseBySwitcherComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.browseByComponent = this.route.data.pipe(
|
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()))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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<SearchResultsComponent> {
|
||||||
|
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<PaginatedList<SearchResult<DSpaceObject>>>;
|
||||||
|
|
||||||
|
@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<ListableObject> = new EventEmitter<ListableObject>();
|
||||||
|
|
||||||
|
@Output() selectObject: EventEmitter<ListableObject> = new EventEmitter<ListableObject>();
|
||||||
|
|
||||||
|
protected getComponentName(): string {
|
||||||
|
return 'SearchResultsComponent';
|
||||||
|
}
|
||||||
|
|
||||||
|
protected importThemedComponent(themeName: string): Promise<any> {
|
||||||
|
return import(`../../../../themes/${themeName}/app/shared/search/search-results/search-results.component`);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected importUnthemedComponent(): Promise<any> {
|
||||||
|
return import('./search-results.component');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -29,7 +29,7 @@
|
|||||||
| translate}}
|
| translate}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<ds-search-results [searchResults]="resultsRD$ | async"
|
<ds-themed-search-results [searchResults]="resultsRD$ | async"
|
||||||
[searchConfig]="searchOptions$ | async"
|
[searchConfig]="searchOptions$ | async"
|
||||||
[configuration]="(currentConfiguration$ | async)"
|
[configuration]="(currentConfiguration$ | async)"
|
||||||
[disableHeader]="!searchEnabled"
|
[disableHeader]="!searchEnabled"
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
[selectable]="selectable"
|
[selectable]="selectable"
|
||||||
[selectionConfig]="selectionConfig"
|
[selectionConfig]="selectionConfig"
|
||||||
(deselectObject)="deselectObject.emit($event)"
|
(deselectObject)="deselectObject.emit($event)"
|
||||||
(selectObject)="selectObject.emit($event)"></ds-search-results>
|
(selectObject)="selectObject.emit($event)"></ds-themed-search-results>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
@@ -28,6 +28,7 @@ import { MissingTranslationHelper } from '../translate/missing-translation.helpe
|
|||||||
import { SharedModule } from '../shared.module';
|
import { SharedModule } from '../shared.module';
|
||||||
import { SearchResultsComponent } from './search-results/search-results.component';
|
import { SearchResultsComponent } from './search-results/search-results.component';
|
||||||
import { SearchComponent } from './search.component';
|
import { SearchComponent } from './search.component';
|
||||||
|
import { ThemedSearchResultsComponent } from './search-results/themed-search-results.component';
|
||||||
|
|
||||||
const COMPONENTS = [
|
const COMPONENTS = [
|
||||||
SearchComponent,
|
SearchComponent,
|
||||||
@@ -50,7 +51,8 @@ const COMPONENTS = [
|
|||||||
SearchAuthorityFilterComponent,
|
SearchAuthorityFilterComponent,
|
||||||
SearchSwitchConfigurationComponent,
|
SearchSwitchConfigurationComponent,
|
||||||
ConfigurationSearchPageComponent,
|
ConfigurationSearchPageComponent,
|
||||||
ThemedConfigurationSearchPageComponent
|
ThemedConfigurationSearchPageComponent,
|
||||||
|
ThemedSearchResultsComponent,
|
||||||
];
|
];
|
||||||
|
|
||||||
const ENTRY_COMPONENTS = [
|
const ENTRY_COMPONENTS = [
|
||||||
|
Reference in New Issue
Block a user