Merge pull request #1674 from atmire/w2p-91272_Add-themed-components-to-upstream-branch

Add more themed components
This commit is contained in:
Tim Donohue
2022-07-27 13:53:29 -05:00
committed by GitHub
130 changed files with 693 additions and 158 deletions

View File

@@ -45,7 +45,7 @@
</div>
</form>
<ds-loading *ngIf="searching$ | async"></ds-loading>
<ds-themed-loading *ngIf="searching$ | async"></ds-themed-loading>
<ds-pagination
*ngIf="(pageInfoState$ | async)?.totalElements > 0 && !(searching$ | async)"
[paginationOptions]="config"

View File

@@ -36,12 +36,12 @@
</button>
</ds-form>
<ds-loading [showMessage]="false" *ngIf="!formGroup"></ds-loading>
<ds-themed-loading [showMessage]="false" *ngIf="!formGroup"></ds-themed-loading>
<div *ngIf="epersonService.getActiveEPerson() | async">
<h5>{{messagePrefix + '.groupsEPersonIsMemberOf' | translate}}</h5>
<ds-loading [showMessage]="false" *ngIf="!(groups | async)"></ds-loading>
<ds-themed-loading [showMessage]="false" *ngIf="!(groups | async)"></ds-themed-loading>
<ds-pagination
*ngIf="(groups | async)?.payload?.totalElements > 0"

View File

@@ -33,7 +33,7 @@
</div>
</form>
<ds-loading *ngIf="loading$ | async"></ds-loading>
<ds-themed-loading *ngIf="loading$ | async"></ds-themed-loading>
<ds-pagination
*ngIf="(pageInfoState$ | async)?.totalElements > 0 && !(loading$ | async)"
[paginationOptions]="config"

View File

@@ -20,6 +20,8 @@ import { FeatureID } from '../../core/data/feature-authorization/feature-id';
import createSpy = jasmine.createSpy;
import { createSuccessfulRemoteDataObject } from '../../shared/remote-data.utils';
import { Item } from '../../core/shared/item.model';
import { ThemeService } from '../../shared/theme-support/theme.service';
import { getMockThemeService } from '../../shared/mocks/theme-service.mock';
describe('AdminSidebarComponent', () => {
let comp: AdminSidebarComponent;
@@ -60,6 +62,7 @@ describe('AdminSidebarComponent', () => {
declarations: [AdminSidebarComponent],
providers: [
Injector,
{ provide: ThemeService, useValue: getMockThemeService() },
{ provide: MenuService, useValue: menuService },
{ provide: CSSVariableService, useClass: CSSVariableServiceStub },
{ provide: AuthService, useClass: AuthServiceStub },

View File

@@ -9,6 +9,7 @@ import { CSSVariableService } from '../../shared/sass-helper/sass-helper.service
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
import { MenuID } from '../../shared/menu/menu-id.model';
import { ActivatedRoute } from '@angular/router';
import { ThemeService } from '../../shared/theme-support/theme.service';
/**
* Component representing the admin sidebar
@@ -56,9 +57,10 @@ export class AdminSidebarComponent extends MenuComponent implements OnInit {
private variableService: CSSVariableService,
private authService: AuthService,
public authorizationService: AuthorizationDataService,
public route: ActivatedRoute
public route: ActivatedRoute,
protected themeService: ThemeService
) {
super(menuService, injector, authorizationService, route);
super(menuService, injector, authorizationService, route, themeService);
this.inFocus$ = new BehaviorSubject(false);
}

View File

@@ -27,7 +27,7 @@
</div>
</div>
<ds-error *ngIf="bitstreamRD?.hasFailed" message="{{'error.bitstream' | translate}}"></ds-error>
<ds-loading *ngIf="!bitstreamRD || !formatsRD || bitstreamRD?.isLoading || formatsRD?.isLoading"
message="{{'loading.bitstream' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="!bitstreamRD || !formatsRD || bitstreamRD?.isLoading || formatsRD?.isLoading"
message="{{'loading.bitstream' | translate}}"></ds-themed-loading>
</div>
</ng-container>

View File

@@ -40,7 +40,7 @@
(prev)="goPrev()"
(next)="goNext()">
</ds-browse-by>
<ds-loading *ngIf="!startsWithOptions" message="{{'loading.browse-by-page' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="!startsWithOptions" message="{{'loading.browse-by-page' | translate}}"></ds-themed-loading>
</div>
</section>
<ng-container *ngVar="(parent$ | async) as parent">

View File

@@ -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<any>>('getComponentByBrowseByType', {
export const BROWSE_BY_COMPONENT_FACTORY = new InjectionToken<(browseByType, theme) => GenericConstructor<any>>('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;
}

View File

@@ -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);
});
});
});

View File

@@ -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<any>;
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 {
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()))
);
}

View File

@@ -6,7 +6,7 @@ import { CreateCollectionPageComponent } from './create-collection-page/create-c
import { AuthenticatedGuard } from '../core/auth/authenticated.guard';
import { CreateCollectionPageGuard } from './create-collection-page/create-collection-page.guard';
import { DeleteCollectionPageComponent } from './delete-collection-page/delete-collection-page.component';
import { EditItemTemplatePageComponent } from './edit-item-template-page/edit-item-template-page.component';
import { ThemedEditItemTemplatePageComponent } from './edit-item-template-page/themed-edit-item-template-page.component';
import { ItemTemplatePageResolver } from './edit-item-template-page/item-template-page.resolver';
import { CollectionBreadcrumbResolver } from '../core/breadcrumbs/collection-breadcrumb.resolver';
import { DSOBreadcrumbsService } from '../core/breadcrumbs/dso-breadcrumbs.service';
@@ -52,7 +52,7 @@ import { MenuItemType } from '../shared/menu/menu-item-type.model';
},
{
path: ITEMTEMPLATE_PATH,
component: EditItemTemplatePageComponent,
component: ThemedEditItemTemplatePageComponent,
canActivate: [AuthenticatedGuard],
resolve: {
item: ItemTemplatePageResolver,

View File

@@ -56,8 +56,8 @@
</div>
<ds-error *ngIf="itemRD?.hasFailed"
message="{{'error.recent-submissions' | translate}}"></ds-error>
<ds-loading *ngIf="!itemRD || itemRD.isLoading"
message="{{'loading.recent-submissions' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="!itemRD || itemRD.isLoading"
message="{{'loading.recent-submissions' | translate}}"></ds-themed-loading>
<div *ngIf="!itemRD?.isLoading && itemRD?.payload?.page.length === 0" class="alert alert-info w-100" role="alert">
{{'collection.page.browse.recent.empty' | translate}}
</div>
@@ -74,7 +74,7 @@
</div>
<ds-error *ngIf="collectionRD?.hasFailed"
message="{{'error.collection' | translate}}"></ds-error>
<ds-loading *ngIf="collectionRD?.isLoading"
message="{{'loading.collection' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="collectionRD?.isLoading"
message="{{'loading.collection' | translate}}"></ds-themed-loading>
</div>
</div>

View File

@@ -8,6 +8,7 @@ import { CollectionPageRoutingModule } from './collection-page-routing.module';
import { CreateCollectionPageComponent } from './create-collection-page/create-collection-page.component';
import { DeleteCollectionPageComponent } from './delete-collection-page/delete-collection-page.component';
import { EditItemTemplatePageComponent } from './edit-item-template-page/edit-item-template-page.component';
import { ThemedEditItemTemplatePageComponent } from './edit-item-template-page/themed-edit-item-template-page.component';
import { EditItemPageModule } from '../item-page/edit-item-page/edit-item-page.module';
import { CollectionItemMapperComponent } from './collection-item-mapper/collection-item-mapper.component';
import { SearchService } from '../core/shared/search/search.service';
@@ -32,6 +33,7 @@ import { ComcolModule } from '../shared/comcol/comcol.module';
CreateCollectionPageComponent,
DeleteCollectionPageComponent,
EditItemTemplatePageComponent,
ThemedEditItemTemplatePageComponent,
CollectionItemMapperComponent
],
providers: [

View File

@@ -25,7 +25,7 @@
<label class="form-check-label"
for="externalSourceCheck">{{ 'collection.edit.tabs.source.external' | translate }}</label>
</div>
<ds-loading *ngIf="!contentSource" [message]="'loading.content-source' | translate"></ds-loading>
<ds-themed-loading *ngIf="!contentSource" [message]="'loading.content-source' | translate"></ds-themed-loading>
<h4 *ngIf="contentSource && (contentSource?.harvestType !== harvestTypeNone)">{{ 'collection.edit.tabs.source.form.head' | translate }}</h4>
</div>
<div class="row">

View File

@@ -3,10 +3,10 @@
<div class="col-12" *ngVar="(itemRD$ | async) as itemRD">
<ng-container *ngIf="itemRD?.hasSucceeded">
<h2 class="border-bottom">{{ 'collection.edit.template.head' | translate:{ collection: collection?.name } }}</h2>
<ds-item-metadata [updateService]="itemTemplateService" [item]="itemRD?.payload"></ds-item-metadata>
<ds-themed-item-metadata [updateService]="itemTemplateService" [item]="itemRD?.payload"></ds-themed-item-metadata>
<button [routerLink]="getCollectionEditUrl(collection)" class="btn btn-outline-secondary">{{ 'collection.edit.template.cancel' | translate }}</button>
</ng-container>
<ds-loading *ngIf="itemRD?.isLoading" [message]="'collection.edit.template.loading' | translate"></ds-loading>
<ds-themed-loading *ngIf="itemRD?.isLoading" [message]="'collection.edit.template.loading' | translate"></ds-themed-loading>
<ds-alert *ngIf="itemRD?.hasFailed" [type]="AlertTypeEnum.Error" [content]="'collection.edit.template.error' | translate"></ds-alert>
</div>
</div>

View File

@@ -0,0 +1,25 @@
import { Component } from '@angular/core';
import { ThemedComponent } from '../../shared/theme-support/themed.component';
import { EditItemTemplatePageComponent } from './edit-item-template-page.component';
@Component({
selector: 'ds-themed-edit-item-template-page',
styleUrls: [],
templateUrl: '../../shared/theme-support/themed.component.html',
})
/**
* Component for editing the item template of a collection
*/
export class ThemedEditItemTemplatePageComponent extends ThemedComponent<EditItemTemplatePageComponent> {
protected getComponentName(): string {
return 'EditItemTemplatePageComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../themes/${themeName}/app/collection-page/edit-item-template-page/edit-item-template-page.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import('./edit-item-template-page.component');
}
}

View File

@@ -1,4 +1,4 @@
<ds-loading *ngIf="(dataSource.loading$ | async) && !loadingNode" class="ds-loading"></ds-loading>
<ds-themed-loading *ngIf="(dataSource.loading$ | async) && !loadingNode" class="ds-themed-loading"></ds-themed-loading>
<cdk-tree [dataSource]="dataSource" [treeControl]="treeControl">
<!-- This is the tree node template for show more node -->
<cdk-tree-node *cdkTreeNodeDef="let node; when: isShowMore" cdkTreeNodePadding
@@ -12,7 +12,7 @@
class="btn btn-outline-primary btn-sm" role="button">
<i class="fas fa-angle-down"></i> {{ 'communityList.showMore' | translate }}
</a>
<ds-loading *ngIf="node===loadingNode && dataSource.loading$ | async" class="ds-loading"></ds-loading>
<ds-themed-loading *ngIf="node===loadingNode && dataSource.loading$ | async" class="ds-themed-loading"></ds-themed-loading>
</div>
</div>
<div class="text-muted" cdkTreeNodePadding>
@@ -57,7 +57,7 @@
<span class="{{node.isExpanded ? 'fa fa-chevron-down' : 'fa fa-chevron-right'}}"
aria-hidden="true"></span>
</button>
<ds-loading class="ds-loading"></ds-loading>
<ds-themed-loading class="ds-themed-loading"></ds-themed-loading>
</div>
</cdk-tree-node>
<!-- This is the tree node template for leaf nodes (collections and (sub)coms without children) -->

View File

@@ -41,5 +41,5 @@
</div>
<ds-error *ngIf="communityRD?.hasFailed" message="{{'error.community' | translate}}"></ds-error>
<ds-loading *ngIf="communityRD?.isLoading" message="{{'loading.community' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="communityRD?.isLoading" message="{{'loading.community' | translate}}"></ds-themed-loading>
</div>

View File

@@ -9,5 +9,5 @@
</ds-viewable-collection>
</div>
<ds-error *ngIf="subCollectionsRD?.hasFailed" message="{{'error.sub-collections' | translate}}"></ds-error>
<ds-loading *ngIf="subCollectionsRD?.isLoading" message="{{'loading.sub-collections' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="subCollectionsRD?.isLoading" message="{{'loading.sub-collections' | translate}}"></ds-themed-loading>
</ng-container>

View File

@@ -9,5 +9,5 @@
</ds-viewable-collection>
</div>
<ds-error *ngIf="subCommunitiesRD?.hasFailed" message="{{'error.sub-communities' | translate}}"></ds-error>
<ds-loading *ngIf="subCommunitiesRD?.isLoading" message="{{'loading.sub-communities' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="subCommunitiesRD?.isLoading" message="{{'loading.sub-communities' | translate}}"></ds-themed-loading>
</ng-container>

View File

@@ -8,7 +8,7 @@
<nav role="navigation" [attr.aria-label]="'nav.user.description' | translate" class="navbar navbar-light navbar-expand-md flex-shrink-0 px-0">
<ds-search-navbar></ds-search-navbar>
<ds-lang-switch></ds-lang-switch>
<ds-auth-nav-menu></ds-auth-nav-menu>
<ds-themed-auth-nav-menu></ds-themed-auth-nav-menu>
<ds-impersonate-navbar></ds-impersonate-navbar>
<div class="pl-2">
<button class="navbar-toggler" type="button" (click)="toggleNavbar()"

View File

@@ -10,4 +10,4 @@
</ds-viewable-collection>
</div>
<ds-error *ngIf="communitiesRD?.hasFailed " message="{{'error.top-level-communites' | translate}}"></ds-error>
<ds-loading *ngIf="communitiesRD?.isLoading " message="{{'loading.top-level-communities' | translate}}"></ds-loading></ng-container>
<ds-themed-loading *ngIf="communitiesRD?.isLoading " message="{{'loading.top-level-communities' | translate}}"></ds-themed-loading></ng-container>

View File

@@ -1,6 +1,8 @@
import { NO_ERRORS_SCHEMA } from '@angular/core';
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { ImportExternalPageComponent } from './import-external-page.component';
import { ThemeService } from '../shared/theme-support/theme.service';
import { getMockThemeService } from '../shared/mocks/theme-service.mock';
describe('ImportExternalPageComponent', () => {
let component: ImportExternalPageComponent;
@@ -9,6 +11,9 @@ describe('ImportExternalPageComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ ImportExternalPageComponent ],
providers:[
{ provide: ThemeService, useValue: getMockThemeService() },
],
schemas: [NO_ERRORS_SCHEMA]
})
.compileComponents();

View File

@@ -15,6 +15,7 @@ import { ItemPrivateComponent } from './item-private/item-private.component';
import { ItemPublicComponent } from './item-public/item-public.component';
import { ItemDeleteComponent } from './item-delete/item-delete.component';
import { ItemMetadataComponent } from './item-metadata/item-metadata.component';
import { ThemedItemMetadataComponent } from './item-metadata/themed-item-metadata.component';
import { EditInPlaceFieldComponent } from './item-metadata/edit-in-place-field/edit-in-place-field.component';
import { ItemBitstreamsComponent } from './item-bitstreams/item-bitstreams.component';
import { ItemEditBitstreamComponent } from './item-bitstreams/item-edit-bitstream/item-edit-bitstream.component';
@@ -63,6 +64,7 @@ import { ResourcePoliciesModule } from '../../shared/resource-policies/resource-
ItemDeleteComponent,
ItemStatusComponent,
ItemMetadataComponent,
ThemedItemMetadataComponent,
ItemRelationshipsComponent,
ItemBitstreamsComponent,
ItemVersionHistoryComponent,
@@ -84,7 +86,8 @@ import { ResourcePoliciesModule } from '../../shared/resource-policies/resource-
ObjectValuesPipe
],
exports: [
ItemMetadataComponent
EditInPlaceFieldComponent,
ThemedItemMetadataComponent,
]
})
export class EditItemPageModule {

View File

@@ -44,7 +44,7 @@
class="alert alert-info w-100 d-inline-block mt-4" role="alert">
{{'item.edit.bitstreams.empty' | translate}}
</div>
<ds-loading *ngIf="!bundles" message="{{'loading.bitstreams' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="!bundles" message="{{'loading.bitstreams' | translate}}"></ds-themed-loading>
<div class="button-row bottom">
<div class="mt-4 float-right space-children-mr ml-gap">

View File

@@ -29,5 +29,5 @@
</ng-container>
</div>
</ng-container>
<ds-loading *ngIf="(loading$ | async)" [message]="'loading.bitstreams' | translate"></ds-loading>
<ds-themed-loading *ngIf="(loading$ | async)" [message]="'loading.bitstreams' | translate"></ds-themed-loading>
</ds-pagination>

View File

@@ -0,0 +1,34 @@
import { Component, Input } from '@angular/core';
import { Item } from '../../../core/shared/item.model';
import { UpdateDataService } from '../../../core/data/update-data.service';
import { ItemMetadataComponent } from './item-metadata.component';
import { ThemedComponent } from '../../../shared/theme-support/themed.component';
@Component({
selector: 'ds-themed-item-metadata',
styleUrls: [],
templateUrl: './../../../shared/theme-support/themed.component.html',
})
/**
* Component for displaying an item's metadata edit page
*/
export class ThemedItemMetadataComponent extends ThemedComponent<ItemMetadataComponent> {
@Input() item: Item;
@Input() updateService: UpdateDataService<Item>;
protected inAndOutputNames: (keyof ItemMetadataComponent & keyof this)[] = ['item', 'updateService'];
protected getComponentName(): string {
return 'ItemMetadataComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../../themes/${themeName}/app/item-page/edit-item-page/item-metadata/item-metadata.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import(`./item-metadata.component`);
}
}

View File

@@ -31,5 +31,5 @@
<div *ngIf="updateValues.length === 0">{{"item.edit.relationships.no-relationships" | translate}}</div>
</ng-container>
</ng-container>
<ds-loading *ngIf="loading$ | async"></ds-loading>
<ds-themed-loading *ngIf="loading$ | async"></ds-themed-loading>
</ng-container>

View File

@@ -32,7 +32,7 @@
></ds-edit-relationship-list>
</div>
</ng-container>
<ds-loading *ngIf="!relationshipTypes"></ds-loading>
<ds-themed-loading *ngIf="!relationshipTypes"></ds-themed-loading>
</ng-container>
<div class="button-row bottom">
<div class="float-right space-children-mr ml-gap">

View File

@@ -27,6 +27,8 @@ import { createPaginatedList } from '../../../shared/testing/utils.test';
import { FieldChangeType } from '../../../core/data/object-updates/field-change-type.model';
import { RelationshipTypeService } from '../../../core/data/relationship-type.service';
import { relationshipTypes } from '../../../shared/testing/relationship-types.mock';
import { ThemeService } from '../../../shared/theme-support/theme.service';
import { getMockThemeService } from '../../../shared/mocks/theme-service.mock';
let comp: any;
let fixture: ComponentFixture<ItemRelationshipsComponent>;
@@ -211,6 +213,7 @@ describe('ItemRelationshipsComponent', () => {
imports: [SharedModule, TranslateModule.forRoot()],
declarations: [ItemRelationshipsComponent],
providers: [
{ provide: ThemeService, useValue: getMockThemeService() },
{ provide: ItemDataService, useValue: itemService },
{ provide: ObjectUpdatesService, useValue: objectUpdatesService },
{ provide: Router, useValue: router },

View File

@@ -30,7 +30,7 @@ export class CollectionsComponent implements OnInit {
label = 'item.page.collections';
separator = '<br/>';
@Input() separator = '<br/>';
/**
* Amount of mapped collections that should be fetched at once.

View File

@@ -43,5 +43,5 @@
</div>
</div>
<ds-error *ngIf="itemRD?.hasFailed" message="{{'error.item' | translate}}"></ds-error>
<ds-loading *ngIf="itemRD?.isLoading" message="{{'loading.item' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="itemRD?.isLoading" message="{{'loading.item' | translate}}"></ds-themed-loading>
</div>

View File

@@ -1,9 +1,9 @@
<ng-container *ngVar="mediaList$ | async as mediaList">
<ds-loading
<ds-themed-loading
*ngIf="isLoading"
message="{{ 'loading.default' | translate }}"
[showMessage]="false"
></ds-loading>
></ds-themed-loading>
<div class="media-viewer" *ngIf="!isLoading">
<ng-container *ngIf="mediaList.length > 0">
<ng-container *ngIf="videoOptions">

View File

@@ -110,7 +110,7 @@ describe('MediaViewerComponent', () => {
});
it('should display a loading component', () => {
const loading = fixture.debugElement.query(By.css('ds-loading'));
const loading = fixture.debugElement.query(By.css('ds-themed-loading'));
expect(loading.nativeElement).toBeDefined();
});
});

View File

@@ -6,7 +6,7 @@
<span>({{(file?.sizeBytes) | dsFileSize }})</span>
<span *ngIf="!last" innerHTML="{{separator}}"></span>
</ds-file-download-link>
<ds-loading *ngIf="isLoading" message="{{'loading.default' | translate}}" [showMessage]="false"></ds-loading>
<ds-themed-loading *ngIf="isLoading" message="{{'loading.default' | translate}}" [showMessage]="false"></ds-themed-loading>
<div *ngIf="!isLastPage" class="mt-1" id="view-more">
<a class="bitstream-view-more btn btn-outline-secondary btn-sm" [routerLink]="[]" (click)="getNextPage()">{{'item.page.bitstreams.view-more' | translate}}</a>
</div>

View File

@@ -86,7 +86,7 @@ describe('FileSectionComponent', () => {
});
it('should display a loading component', () => {
const loading = fixture.debugElement.query(By.css('ds-loading'));
const loading = fixture.debugElement.query(By.css('ds-themed-loading'));
expect(loading.nativeElement).toBeDefined();
});
});

View File

@@ -9,5 +9,5 @@
</div>
</div>
<ds-error *ngIf="itemRD?.hasFailed" message="{{'error.item' | translate}}"></ds-error>
<ds-loading *ngIf="itemRD?.isLoading" message="{{'loading.item' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="itemRD?.isLoading" message="{{'loading.item' | translate}}"></ds-themed-loading>
</div>

View File

@@ -98,7 +98,7 @@ describe('ItemPageComponent', () => {
});
it('should display a loading component', () => {
const loading = fixture.debugElement.query(By.css('ds-loading'));
const loading = fixture.debugElement.query(By.css('ds-themed-loading'));
expect(loading.nativeElement).toBeDefined();
});
});

View File

@@ -4,7 +4,7 @@
<ds-metadata-representation-loader *ngFor="let rep of representations"
[mdRepresentation]="rep">
</ds-metadata-representation-loader>
<ds-loading *ngIf="(i + 1) === objects.length && (i > 0) && (!representations || representations?.length === 0)" message="{{'loading.default' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="(i + 1) === objects.length && (i > 0) && (!representations || representations?.length === 0)" message="{{'loading.default' | translate}}"></ds-themed-loading>
<div class="d-inline-block w-100 mt-2" *ngIf="(i + 1) === objects.length && representations?.length > 0">
<div *ngIf="(objects.length * incrementBy) < total" class="float-left">
<a [routerLink]="[]" (click)="increase()">{{'item.page.related-items.view-more' |

View File

@@ -4,7 +4,7 @@
<ds-listable-object-component-loader *ngFor="let item of itemsRD?.payload?.page"
[object]="item" [viewMode]="viewMode">
</ds-listable-object-component-loader>
<ds-loading *ngIf="(i + 1) === objects.length && (itemsRD || i > 0) && !(itemsRD?.hasSucceeded && itemsRD?.payload && itemsRD?.payload?.page?.length > 0)" message="{{'loading.default' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="(i + 1) === objects.length && (itemsRD || i > 0) && !(itemsRD?.hasSucceeded && itemsRD?.payload && itemsRD?.payload?.page?.length > 0)" message="{{'loading.default' | translate}}"></ds-themed-loading>
<div class="d-inline-block w-100 mt-2" *ngIf="(i + 1) === objects.length && itemsRD?.payload?.page?.length > 0">
<div *ngIf="itemsRD?.payload?.totalPages > objects.length" class="float-left" id="view-more">
<a [routerLink]="[]" (click)="increase()">{{'item.page.related-items.view-more' |

View File

@@ -11,8 +11,7 @@ import { MenuID } from '../../shared/menu/menu-id.model';
* Represents an expandable section in the navbar
*/
@Component({
/* eslint-disable @angular-eslint/component-selector */
selector: 'li[ds-expandable-navbar-section]',
selector: 'ds-expandable-navbar-section',
templateUrl: './expandable-navbar-section.component.html',
styleUrls: ['./expandable-navbar-section.component.scss'],
animations: [slide]

View File

@@ -0,0 +1,29 @@
import { Component } from '@angular/core';
import { ThemedComponent } from '../../shared/theme-support/themed.component';
import { ExpandableNavbarSectionComponent } from './expandable-navbar-section.component';
import { rendersSectionForMenu } from '../../shared/menu/menu-section.decorator';
import { MenuID } from '../../shared/menu/menu-id.model';
/**
* Themed wrapper for ExpandableNavbarSectionComponent
*/
@Component({
/* eslint-disable @angular-eslint/component-selector */
selector: 'li[ds-themed-expandable-navbar-section]',
styleUrls: [],
templateUrl: '../../shared/theme-support/themed.component.html',
})
@rendersSectionForMenu(MenuID.PUBLIC, true)
export class ThemedExpandableNavbarSectionComponent extends ThemedComponent<ExpandableNavbarSectionComponent> {
protected getComponentName(): string {
return 'ExpandableNavbarSectionComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../themes/${themeName}/app/navbar/expandable-navbar-section/expandable-navbar-section.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import(`./expandable-navbar-section.component`);
}
}

View File

@@ -4,7 +4,7 @@
<div class="container">
<div class="reset-padding-md w-100">
<div id="collapsingNav">
<ul class="navbar-nav mr-auto shadow-none">
<ul class="navbar-nav navbar-navigation mr-auto shadow-none">
<ng-container *ngFor="let section of (sections | async)">
<ng-container *ngComponentOutlet="(sectionMap$ | async).get(section.id)?.component; injector: (sectionMap$ | async).get(section.id)?.injector;"></ng-container>
</ng-container>

View File

@@ -20,6 +20,8 @@ import { BrowseDefinition } from '../core/shared/browse-definition.model';
import { BrowseByDataType } from '../browse-by/browse-by-switcher/browse-by-decorator';
import { Item } from '../core/shared/item.model';
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
import { ThemeService } from '../shared/theme-support/theme.service';
import { getMockThemeService } from '../shared/mocks/theme-service.mock';
let comp: NavbarComponent;
let fixture: ComponentFixture<NavbarComponent>;
@@ -91,6 +93,7 @@ describe('NavbarComponent', () => {
declarations: [NavbarComponent],
providers: [
Injector,
{ provide: ThemeService, useValue: getMockThemeService() },
{ provide: MenuService, useValue: menuService },
{ provide: HostWindowService, useValue: new HostWindowServiceStub(800) },
{ provide: ActivatedRoute, useValue: routeStub },

View File

@@ -7,6 +7,7 @@ import { BrowseService } from '../core/browse/browse.service';
import { ActivatedRoute } from '@angular/router';
import { AuthorizationDataService } from '../core/data/feature-authorization/authorization-data.service';
import { MenuID } from '../shared/menu/menu-id.model';
import { ThemeService } from '../shared/theme-support/theme.service';
/**
* Component representing the public navbar
@@ -29,9 +30,10 @@ export class NavbarComponent extends MenuComponent {
public windowService: HostWindowService,
public browseService: BrowseService,
public authorizationService: AuthorizationDataService,
public route: ActivatedRoute
public route: ActivatedRoute,
protected themeService: ThemeService
) {
super(menuService, injector, authorizationService, route);
super(menuService, injector, authorizationService, route, themeService);
}
ngOnInit(): void {

View File

@@ -7,6 +7,7 @@ import { CoreModule } from '../core/core.module';
import { NavbarEffects } from './navbar.effects';
import { NavbarSectionComponent } from './navbar-section/navbar-section.component';
import { ExpandableNavbarSectionComponent } from './expandable-navbar-section/expandable-navbar-section.component';
import { ThemedExpandableNavbarSectionComponent } from './expandable-navbar-section/themed-expandable-navbar-section.component';
import { NavbarComponent } from './navbar.component';
import { MenuModule } from '../shared/menu/menu.module';
import { SharedModule } from '../shared/shared.module';
@@ -20,7 +21,7 @@ const effects = [
const ENTRY_COMPONENTS = [
// put only entry components that use custom decorator
NavbarSectionComponent,
ExpandableNavbarSectionComponent,
ThemedExpandableNavbarSectionComponent,
];
@NgModule({
@@ -36,13 +37,14 @@ const ENTRY_COMPONENTS = [
NavbarComponent,
ThemedNavbarComponent,
NavbarSectionComponent,
ExpandableNavbarSectionComponent
ExpandableNavbarSectionComponent,
ThemedExpandableNavbarSectionComponent,
],
providers: [],
exports: [
ThemedNavbarComponent,
NavbarSectionComponent,
ExpandableNavbarSectionComponent
ThemedExpandableNavbarSectionComponent
]
})

View File

@@ -38,7 +38,7 @@
<button *ngIf="!showOutputLogs && process?._links?.output?.href != undefined" id="showOutputButton" class="btn btn-primary" (click)="showProcessOutputLogs()">
{{ 'process.detail.logs.button' | translate }}
</button>
<ds-loading *ngIf="retrievingOutputLogs$ | async" class="ds-loading" message="{{ 'process.detail.logs.loading' | translate }}"></ds-loading>
<ds-themed-loading *ngIf="retrievingOutputLogs$ | async" class="ds-themed-loading" message="{{ 'process.detail.logs.loading' | translate }}"></ds-themed-loading>
<pre class="font-weight-bold text-secondary bg-light p-3"
*ngIf="showOutputLogs && (outputLogs$ | async)?.length > 0">{{ (outputLogs$ | async) }}</pre>
<p id="no-output-logs-message" *ngIf="(!(retrievingOutputLogs$ | async) && showOutputLogs)

View File

@@ -5,5 +5,5 @@
<ds-email-request-copy [subject]="subject$ | async" [message]="message$ | async" (send)="deny($event)"></ds-email-request-copy>
</div>
<ds-loading *ngIf="!itemRequestRD || itemRequestRD?.isLoading"></ds-loading>
<ds-themed-loading *ngIf="!itemRequestRD || itemRequestRD?.isLoading"></ds-themed-loading>
</div>

View File

@@ -26,5 +26,5 @@
</p>
</div>
</div>
<ds-loading *ngIf="!itemRequestRD || itemRequestRD?.isLoading"></ds-loading>
<ds-themed-loading *ngIf="!itemRequestRD || itemRequestRD?.isLoading"></ds-themed-loading>
</div>

View File

@@ -13,5 +13,5 @@
</form>
</ds-email-request-copy>
</div>
<ds-loading *ngIf="!itemRequestRD || itemRequestRD?.isLoading"></ds-loading>
<ds-themed-loading *ngIf="!itemRequestRD || itemRequestRD?.isLoading"></ds-themed-loading>
</div>

View File

@@ -9,7 +9,7 @@
<ds-themed-breadcrumbs></ds-themed-breadcrumbs>
<div class="container d-flex justify-content-center align-items-center h-100" *ngIf="shouldShowRouteLoader">
<ds-loading [showMessage]="false"></ds-loading>
<ds-themed-loading [showMessage]="false"></ds-themed-loading>
</div>
<div [class.d-none]="shouldShowRouteLoader">
<router-outlet></router-outlet>
@@ -24,5 +24,5 @@
</ds-notifications-board>
<div class="ds-full-screen-loader" *ngIf="shouldShowFullscreenLoader">
<ds-loading [showMessage]="false"></ds-loading>
<ds-themed-loading [showMessage]="false"></ds-themed-loading>
</div>

View File

@@ -0,0 +1,25 @@
import { Component } from '@angular/core';
import { ThemedComponent } from '../theme-support/themed.component';
import { AuthNavMenuComponent } from './auth-nav-menu.component';
/**
* Themed wrapper for {@link AuthNavMenuComponent}
*/
@Component({
selector: 'ds-themed-auth-nav-menu',
styleUrls: [],
templateUrl: '../theme-support/themed.component.html',
})
export class ThemedAuthNavMenuComponent extends ThemedComponent<AuthNavMenuComponent> {
protected getComponentName(): string {
return 'AuthNavMenuComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../themes/${themeName}/app/shared/auth-nav-menu/auth-nav-menu.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import(`./auth-nav-menu.component`);
}
}

View File

@@ -1,4 +1,4 @@
<ds-loading *ngIf="(loading$ | async)"></ds-loading>
<ds-themed-loading *ngIf="(loading$ | async)"></ds-themed-loading>
<div *ngIf="!(loading$ | async)">
<span class="dropdown-item-text">{{(user$ | async)?.name}} ({{(user$ | async)?.email}})</span>
<a class="dropdown-item" [routerLink]="[profileRoute]" routerLinkActive="active">{{'nav.profile' | translate}}</a>

View File

@@ -14,7 +14,7 @@
(next)="goNext()">
</ds-viewable-collection>
</div>
<ds-loading *ngIf="!objects || objects?.isLoading" message="{{'loading.browse-by' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="!objects || objects?.isLoading" message="{{'loading.browse-by' | translate}}"></ds-themed-loading>
<ds-error *ngIf="objects?.hasFailed" message="{{'error.browse-by' | translate}}"></ds-error>
<div *ngIf="!objects?.isLoading && objects?.payload?.page.length === 0">
<div *ngIf="shouldDisplayResetButton$ |async" class="d-inline-block mb-4 reset">

View File

@@ -17,7 +17,6 @@ import { SortDirection, SortOptions } from '../../core/cache/models/sort-options
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
import { PaginationService } from '../../core/pagination/pagination.service';
import { PaginationServiceStub } from '../testing/pagination-service.stub';
import { FindListOptions } from '../../core/data/find-list-options.model';
import {
ListableObjectComponentLoaderComponent
} from '../object-collection/shared/listable-object/listable-object-component-loader.component';
@@ -37,7 +36,6 @@ import { HostWindowServiceStub } from '../testing/host-window-service.stub';
import { HostWindowService } from '../host-window.service';
import { RouteService } from '../../core/services/route.service';
import { routeServiceStub } from '../testing/route-service.stub';
import SpyObj = jasmine.SpyObj;
import { GroupDataService } from '../../core/eperson/group-data.service';
import { createPaginatedList } from '../testing/utils.test';
import { LinkHeadService } from '../../core/services/link-head.service';
@@ -45,6 +43,7 @@ import { ConfigurationDataService } from '../../core/data/configuration-data.ser
import { ConfigurationProperty } from '../../core/shared/configuration-property.model';
import { SearchConfigurationServiceStub } from '../testing/search-configuration-service.stub';
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
import { getMockThemeService } from '../mocks/theme-service.mock';
@listableObjectComponent(BrowseEntry, ViewMode.ListElement, DEFAULT_CONTEXT, 'custom')
@Component({
@@ -107,13 +106,10 @@ describe('BrowseByComponent', () => {
});
const paginationService = new PaginationServiceStub(paginationConfig);
let themeService: SpyObj<ThemeService>;
let themeService;
beforeEach(waitForAsync(() => {
themeService = jasmine.createSpyObj('themeService', {
getThemeName: 'dspace',
getThemeName$: observableOf('dspace'),
});
themeService = getMockThemeService('dspace');
TestBed.configureTestingModule({
imports: [
CommonModule,
@@ -142,19 +138,16 @@ describe('BrowseByComponent', () => {
],
schemas: [NO_ERRORS_SCHEMA]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(BrowseByComponent);
comp = fixture.componentInstance;
comp.paginationConfig = paginationConfig;
fixture.detectChanges();
});
}));
it('should display a loading message when objects is empty', () => {
(comp as any).objects = undefined;
fixture.detectChanges();
expect(fixture.debugElement.query(By.css('ds-loading'))).toBeDefined();
expect(fixture.debugElement.query(By.css('ds-themed-loading'))).toBeDefined();
});
it('should display results when objects is not empty', () => {

View File

@@ -35,8 +35,8 @@
</button>
</ng-container>
<button class="dropdown-item disabled" *ngIf="(isLoading | async)">
<ds-loading message="{{'loading.default' | translate}}">
</ds-loading>
<ds-themed-loading message="{{'loading.default' | translate}}">
</ds-themed-loading>
</button>
</div>

View File

@@ -13,7 +13,7 @@
<div class="d-flex flex-md-row justify-content-between flex-column">
<div class="w-100 d-flex align-items-center">
<ds-loading *ngIf="!(groupRD$ | async)"></ds-loading>
<ds-themed-loading *ngIf="!(groupRD$ | async)"></ds-themed-loading>
<div *ngIf="hasNoGroup$ | async">
{{'comcol-role.edit.no-group' | translate}}
</div>

View File

@@ -31,7 +31,7 @@
</ng-container>
<button *ngIf="loading"
class="list-group-item list-group-item-action border-0 list-entry">
<ds-loading [showMessage]="false"></ds-loading>
<ds-themed-loading [showMessage]="false"></ds-themed-loading>
</button>
</div>
</div>

View File

@@ -21,8 +21,8 @@
</ul>
</button>
<button class="dropdown-item disabled" *ngIf="(isLoadingList | async)" >
<ds-loading message="{{'loading.default' | translate}}">
</ds-loading>
<ds-themed-loading message="{{'loading.default' | translate}}">
</ds-themed-loading>
</button>
</div>

View File

@@ -1,7 +1,7 @@
<div class="d-flex">
<span class="mr-auto text-contents">
<ng-container *ngIf="!(metadataRepresentation$ | async)">
<ds-loading [showMessage]="false"></ds-loading>
<ds-themed-loading [showMessage]="false"></ds-themed-loading>
</ng-container>
<ng-container *ngIf="(metadataRepresentation$ | async)">
<ds-metadata-representation-loader [mdRepresentation]="metadataRepresentation$ | async"></ds-metadata-representation-loader>

View File

@@ -1,7 +1,7 @@
<div class="d-flex">
<span class="mr-auto text-contents">
<ng-container *ngIf="!(relatedItem$ | async)">
<ds-loading [showMessage]="false"></ds-loading>
<ds-themed-loading [showMessage]="false"></ds-themed-loading>
</ng-container>
<ng-container *ngIf="(relatedItem$ | async)">
<ds-listable-object-component-loader [showLabel]="false" [viewMode]="viewType" [object]="(relatedItem$ | async)"></ds-listable-object-component-loader>

View File

@@ -57,7 +57,7 @@
</div>
<div class="d-flex">
<ds-loading *ngIf="!chips" [showMessage]="false"></ds-loading>
<ds-themed-loading *ngIf="!chips" [showMessage]="false"></ds-themed-loading>
<div *ngIf="chips && !chips.hasItems()">
<input type="text"
class="border-0 form-control-plaintext tag-input mt-1 mb-1 pl-2 text-muted"

View File

@@ -6,7 +6,7 @@
</button>
</div>
<div class="modal-body">
<ds-loading *ngIf="!item || !collection"></ds-loading>
<ds-themed-loading *ngIf="!item || !collection"></ds-themed-loading>
<ng-container *ngIf="item && collection">
<ul ngbNav #nav="ngbNav" class="nav-tabs">
<li ngbNavItem>

View File

@@ -21,8 +21,8 @@
[importConfig]="importConfig"
(importObject)="import($event)">
</ds-viewable-collection>
<ds-loading *ngIf="!entriesRD || entriesRD?.isLoading"
message="{{'loading.search-results' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="!entriesRD || entriesRD?.isLoading"
message="{{'loading.search-results' | translate}}"></ds-themed-loading>
<ds-error *ngIf="entriesRD?.hasFailed && (!entriesRD?.errorMessage || entriesRD?.statusCode != 400)"
message="{{'error.search-results' | translate}}"></ds-error>
<div *ngIf="entriesRD?.payload?.page?.length == 0 || entriesRD?.statusCode == 400" id="empty-external-entry-list">

View File

@@ -145,8 +145,8 @@ describe('DsDynamicLookupRelationExternalSourceTabComponent', () => {
expect(viewableCollection).toBeNull();
});
it('should display a ds-loading component', () => {
const loading = fixture.debugElement.query(By.css('ds-loading'));
it('should display a ds-themed-loading component', () => {
const loading = fixture.debugElement.query(By.css('ds-themed-loading'));
expect(loading).not.toBeNull();
});
});

View File

@@ -0,0 +1,40 @@
import { Component, Input, ComponentFactoryResolver, ChangeDetectorRef } from '@angular/core';
import { ThemedComponent } from '../theme-support/themed.component';
import { LoadingComponent } from './loading.component';
import { ThemeService } from '../theme-support/theme.service';
/**
* Themed wrapper for LoadingComponent
*/
@Component({
selector: 'ds-themed-loading',
styleUrls: [],
templateUrl: '../../shared/theme-support/themed.component.html',
})
export class ThemedLoadingComponent extends ThemedComponent<LoadingComponent> {
@Input() message: string;
@Input() showMessage = true;
protected inAndOutputNames: (keyof LoadingComponent & keyof this)[] = ['message', 'showMessage'];
constructor(
protected resolver: ComponentFactoryResolver,
protected cdr: ChangeDetectorRef,
protected themeService: ThemeService
) {
super(resolver, cdr, themeService);
}
protected getComponentName(): string {
return 'LoadingComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../themes/${themeName}/app/shared/loading/loading.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import('./loading.component');
}
}

View File

@@ -1,4 +1,4 @@
<ds-loading *ngIf="(loading | async) || (isAuthenticated | async)" class="m-5"></ds-loading>
<ds-themed-loading *ngIf="(loading | async) || (isAuthenticated | async)" class="m-5"></ds-themed-loading>
<div *ngIf="!(loading | async) && !(isAuthenticated | async)" class="px-4 py-3 login-container">
<ng-container *ngFor="let authMethod of (authMethods | async); let i = index">
<div *ngIf="i === 1" class="text-center mt-2">

View File

@@ -1,4 +1,6 @@
import { DEFAULT_THEME } from '../object-collection/shared/listable-object/listable-object.decorator';
import { MenuID } from './menu-id.model';
import { hasValue } from '../empty.util';
const menuComponentMap = new Map();
@@ -8,7 +10,7 @@ const menuComponentMap = new Map();
* @param {boolean} expandable True when the section should be expandable, false when if should not
* @returns {(menuSectionWrapperComponent: GenericConstructor) => void}
*/
export function rendersSectionForMenu(menuID: MenuID, expandable: boolean) {
export function rendersSectionForMenu(menuID: MenuID, expandable: boolean, theme = DEFAULT_THEME) {
return function decorator(menuSectionWrapperComponent: any) {
if (!menuSectionWrapperComponent) {
return;
@@ -16,7 +18,10 @@ export function rendersSectionForMenu(menuID: MenuID, expandable: boolean) {
if (!menuComponentMap.get(menuID)) {
menuComponentMap.set(menuID, new Map());
}
menuComponentMap.get(menuID).set(expandable, menuSectionWrapperComponent);
if (!menuComponentMap.get(menuID).get(expandable)) {
menuComponentMap.get(menuID).set(expandable, new Map());
}
menuComponentMap.get(menuID).get(expandable).set(theme, menuSectionWrapperComponent);
};
}
@@ -26,6 +31,11 @@ export function rendersSectionForMenu(menuID: MenuID, expandable: boolean) {
* @param {boolean} expandable True when the section should be expandable, false when if should not
* @returns {GenericConstructor} The constructor of the matching Component
*/
export function getComponentForMenu(menuID: MenuID, expandable: boolean) {
return menuComponentMap.get(menuID).get(expandable);
export function getComponentForMenu(menuID: MenuID, expandable: boolean, theme: string) {
const comp = menuComponentMap.get(menuID).get(expandable).get(theme);
if (hasValue(comp)) {
return comp;
} else {
return menuComponentMap.get(menuID).get(expandable).get(DEFAULT_THEME);
}
}

View File

@@ -13,6 +13,8 @@ import { MenuID } from './menu-id.model';
import { Item } from '../../core/shared/item.model';
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
import { createSuccessfulRemoteDataObject } from '../remote-data.utils';
import { ThemeService } from '../theme-support/theme.service';
import { getMockThemeService } from '../mocks/theme-service.mock';
describe('MenuComponent', () => {
let comp: MenuComponent;
@@ -57,6 +59,7 @@ describe('MenuComponent', () => {
declarations: [MenuComponent],
providers: [
Injector,
{ provide: ThemeService, useValue: getMockThemeService() },
{ provide: MenuService, useClass: MenuServiceStub },
{ provide: AuthorizationDataService, useValue: authorizationService },
{ provide: ActivatedRoute, useValue: routeStub },

View File

@@ -12,6 +12,7 @@ import { MenuID } from './menu-id.model';
import { ActivatedRoute } from '@angular/router';
import { AuthorizationDataService } from '../../core/data/feature-authorization/authorization-data.service';
import { FeatureID } from '../../core/data/feature-authorization/feature-id';
import { ThemeService } from '../theme-support/theme.service';
/**
* A basic implementation of a MenuComponent
@@ -72,7 +73,9 @@ export class MenuComponent implements OnInit, OnDestroy {
private activatedRouteLastChild: ActivatedRoute;
constructor(protected menuService: MenuService, protected injector: Injector, public authorizationService: AuthorizationDataService, public route: ActivatedRoute) {
constructor(protected menuService: MenuService, protected injector: Injector, public authorizationService: AuthorizationDataService,
public route: ActivatedRoute, protected themeService: ThemeService
) {
}
/**
@@ -215,7 +218,7 @@ export class MenuComponent implements OnInit, OnDestroy {
private getSectionComponent(section: MenuSection): Observable<GenericConstructor<MenuSectionComponent>> {
return this.menuService.hasSubSections(this.menuID, section.id).pipe(
map((expandable: boolean) => {
return getComponentForMenu(this.menuID, expandable);
return getComponentForMenu(this.menuID, expandable, this.themeService.getThemeName());
}
),
);

View File

@@ -128,6 +128,8 @@ export class ListableObjectComponentLoaderComponent implements OnInit, OnChanges
'context',
'viewMode',
'value',
'hideBadges',
'contentChange',
];
constructor(

View File

@@ -23,5 +23,5 @@
</div>
</div>
<ds-error *ngIf="objects.hasFailed" message="{{'error.objects' | translate}}"></ds-error>
<ds-loading *ngIf="objects.isLoading" message="{{'loading.objects' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="objects.isLoading" message="{{'loading.objects' | translate}}"></ds-themed-loading>
</ds-pagination>

View File

@@ -24,7 +24,7 @@
</div>
</div>
<ds-error *ngIf="objects.hasFailed" message="{{'error.objects' | translate}}"></ds-error>
<ds-loading *ngIf="objects.isLoading" message="{{'loading.objects' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="objects.isLoading" message="{{'loading.objects' | translate}}"></ds-themed-loading>
</ds-pagination>

View File

@@ -6,6 +6,6 @@
<ds-workflowitem-actions [object]="dso" (processCompleted)="reloadedObject.emit($event.reloadedObject)"></ds-workflowitem-actions>
</ng-container>
<ds-loading
<ds-themed-loading
*ngIf="!(item$ | async)"
[showMessage]="false"></ds-loading>
[showMessage]="false"></ds-themed-loading>

View File

@@ -6,6 +6,6 @@
<ds-workspaceitem-actions [object]="dso" (processCompleted)="reloadedObject.emit($event.reloadedObject)"></ds-workspaceitem-actions>
</ng-container>
<ds-loading
<ds-themed-loading
*ngIf="!(item$ | async)"
[showMessage]="false"></ds-loading>
[showMessage]="false"></ds-themed-loading>

View File

@@ -28,7 +28,7 @@
{{'collection.select.empty' | translate}}
</div>
<ds-error *ngIf="collectionsRD?.hasFailed" message="{{'error.collections' | translate}}"></ds-error>
<ds-loading *ngIf="!collectionsRD || collectionsRD?.isLoading" message="{{'loading.collections' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="!collectionsRD || collectionsRD?.isLoading" message="{{'loading.collections' | translate}}"></ds-themed-loading>
<div class="space-children-mr float-right" *ngVar="(selectedIds$ | async) as selectedIds">
<button class="btn btn-outline-secondary collection-cancel" (click)="onCancel()">
<i class="fas fa-times"></i> {{cancelButton | translate}}

View File

@@ -36,7 +36,7 @@
{{'item.select.empty' | translate}}
</div>
<ds-error *ngIf="itemsRD?.hasFailed" message="{{'error.items' | translate}}"></ds-error>
<ds-loading *ngIf="!itemsRD || itemsRD?.isLoading" message="{{'loading.items' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="!itemsRD || itemsRD?.isLoading" message="{{'loading.items' | translate}}"></ds-themed-loading>
<div *ngVar="(selectedIds$ | async) as selectedIds">
<button class="btn btn-outline-secondary item-cancel float-left" (click)="onCancel()">{{cancelButton | translate}}</button>
<button class="btn item-confirm float-right"

View File

@@ -18,7 +18,7 @@
>
</ds-viewable-collection>
</div>
<ds-loading *ngIf="isLoading()" message="{{'loading.search-results' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="isLoading()" message="{{'loading.search-results' | translate}}"></ds-themed-loading>
<ds-error
*ngIf="showError()"
message="{{errorMessageLabel() | translate}}"></ds-error>

View File

@@ -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');
}
}

View File

@@ -29,7 +29,7 @@
| translate}}
</button>
</div>
<ds-search-results [searchResults]="resultsRD$ | async"
<ds-themed-search-results [searchResults]="resultsRD$ | async"
[searchConfig]="searchOptions$ | async"
[configuration]="(currentConfiguration$ | async)"
[disableHeader]="!searchEnabled"
@@ -38,7 +38,7 @@
[selectable]="selectable"
[selectionConfig]="selectionConfig"
(deselectObject)="deselectObject.emit($event)"
(selectObject)="selectObject.emit($event)"></ds-search-results>
(selectObject)="selectObject.emit($event)"></ds-themed-search-results>
</div>
</div>
</ng-template>

View File

@@ -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 = [

View File

@@ -59,6 +59,7 @@ import {
import { ViewModeSwitchComponent } from './view-mode-switch/view-mode-switch.component';
import { VarDirective } from './utils/var.directive';
import { AuthNavMenuComponent } from './auth-nav-menu/auth-nav-menu.component';
import { ThemedAuthNavMenuComponent } from './auth-nav-menu/themed-auth-nav-menu.component';
import { LogOutComponent } from './log-out/log-out.component';
import { DragClickDirective } from './utils/drag-click.directive';
import { TruncatePipe } from './utils/truncate.pipe';
@@ -289,6 +290,7 @@ import { ExternalLinkMenuItemComponent } from './menu/menu-item/external-link-me
import { DsoPageOrcidButtonComponent } from './dso-page/dso-page-orcid-button/dso-page-orcid-button.component';
import { LogInOrcidComponent } from './log-in/methods/orcid/log-in-orcid.component';
import { BrowserOnlyPipe } from './utils/browser-only.pipe';
import { ThemedLoadingComponent } from './loading/themed-loading.component';
import { PersonPageClaimButtonComponent } from './dso-page/person-page-claim-button/person-page-claim-button.component';
import { SearchExportCsvComponent } from './search/search-export-csv/search-export-csv.component';
@@ -340,6 +342,7 @@ const COMPONENTS = [
// put shared components here
AlertComponent,
AuthNavMenuComponent,
ThemedAuthNavMenuComponent,
UserMenuComponent,
ChipsComponent,
DsSelectComponent,
@@ -347,6 +350,7 @@ const COMPONENTS = [
FileSectionComponent,
LangSwitchComponent,
LoadingComponent,
ThemedLoadingComponent,
LogInComponent,
LogOutComponent,
NumberPickerComponent,

View File

@@ -23,7 +23,7 @@
</div>
</div>
<div class="treeview-container">
<ds-loading *ngIf="loading | async" [showMessage]="false"></ds-loading>
<ds-themed-loading *ngIf="loading | async" [showMessage]="false"></ds-themed-loading>
<h4 *ngIf="!(loading | async) && dataSource.data.length === 0" class="text-center text-muted mt-4" >
<span>{{'vocabulary-treeview.search.no-result' | translate}}</span>
</h4>

View File

@@ -11,7 +11,7 @@
<ng-container *ngVar="reports$ | async as reports">
<ng-container *ngIf="!reports">
<ds-loading></ds-loading>
<ds-themed-loading></ds-themed-loading>
</ng-container>
<ng-container *ngIf="reports">

View File

@@ -22,7 +22,7 @@
</div>
<div class="submission-form-content">
<ds-loading *ngIf="(isLoading() | async)" message="Loading..."></ds-loading>
<ds-themed-loading *ngIf="(isLoading() | async)" message="Loading..."></ds-themed-loading>
<ng-container *ngFor="let object of (submissionSections | async)">
<ds-submission-section-container [collectionId]="collectionId"
[submissionId]="submissionId"

View File

@@ -5,7 +5,7 @@
</button>
</div>
<div class="modal-body">
<ds-loading *ngIf="isLoading()"></ds-loading>
<ds-themed-loading *ngIf="isLoading()"></ds-themed-loading>
<ds-collection-dropdown [ngClass]="{'d-none': isLoading()}"
(selectionChange)="selectObject($event)"
(searchComplete)="searchComplete()"

View File

@@ -22,8 +22,8 @@
[importConfig]="importConfig"
(importObject)="import($event)">
</ds-viewable-collection>
<ds-loading *ngIf="(isLoading$ | async)"
message="{{'loading.search-results' | translate}}"></ds-loading>
<ds-themed-loading *ngIf="(isLoading$ | async)"
message="{{'loading.search-results' | translate}}"></ds-themed-loading>
<div *ngIf="!(isLoading$ | async) && entriesRD?.payload?.page?.length === 0" id="empty-external-entry-list">
<ds-alert [type]="'alert-info'">{{ 'search.results.empty' | translate }}</ds-alert>
</div>

View File

@@ -4,7 +4,7 @@
<ng-container class="selection">
<span *ngIf="!submissionCcLicenses">
<ds-loading></ds-loading>
<ds-themed-loading></ds-themed-loading>
</span>
<span *ngIf="getSelectedCcLicense()">
{{ getSelectedCcLicense().name }}
@@ -121,7 +121,7 @@
<ng-container *ngIf="getCcLicenseLink$()">
<ng-container *ngVar="getCcLicenseLink$() | async as licenseLink">
<div *ngIf="!licenseLink">
<ds-loading></ds-loading>
<ds-themed-loading></ds-themed-loading>
</div>
<div *ngIf="licenseLink"
class="mt-2 p-4 bg-light text-dark">

View File

@@ -1,4 +1,4 @@
<ds-loading *ngIf="isLoading" message="Loading..."></ds-loading>
<ds-themed-loading *ngIf="isLoading" message="Loading..."></ds-themed-loading>
<ds-form *ngIf="!isLoading && formModel" #formRef="formComponent"
[formId]="formId"
[formModel]="formModel"

View File

@@ -1,7 +1,7 @@
<div class="thumbnail" [class.limit-width]="limitWidth">
<ds-loading *ngIf="isLoading; else showThumbnail" class="thumbnail-content" [showMessage]="false">
<ds-themed-loading *ngIf="isLoading; else showThumbnail" class="thumbnail-content" [showMessage]="false">
text-content
</ds-loading>
</ds-themed-loading>
<ng-template #showThumbnail>
<img *ngIf="src !== null" class="thumbnail-content img-fluid"
[src]="src | dsSafeUrl" [alt]="alt | translate" (error)="errorHandler()">

View File

@@ -115,7 +115,7 @@ describe('ThumbnailComponent', () => {
comp.thumbnail = thumbnail;
comp.ngOnChanges();
fixture.detectChanges();
expect(de.query(By.css('ds-loading'))).toBeTruthy();
expect(de.query(By.css('ds-themed-loading'))).toBeTruthy();
});
});

View File

@@ -0,0 +1,15 @@
import { Component } from '@angular/core';
import { AdminSidebarComponent as BaseComponent } from '../../../../../app/admin/admin-sidebar/admin-sidebar.component';
/**
* Component representing the admin sidebar
*/
@Component({
selector: 'ds-admin-sidebar',
// templateUrl: './admin-sidebar.component.html',
templateUrl: '../../../../../app/admin/admin-sidebar/admin-sidebar.component.html',
// styleUrls: ['./admin-sidebar.component.scss']
styleUrls: ['../../../../../app/admin/admin-sidebar/admin-sidebar.component.scss']
})
export class AdminSidebarComponent extends BaseComponent {
}

View File

@@ -0,0 +1,16 @@
import { Component } from '@angular/core';
import {
EditItemTemplatePageComponent as BaseComponent
} from '../../../../../app/collection-page/edit-item-template-page/edit-item-template-page.component';
@Component({
selector: 'ds-edit-item-template-page',
styleUrls: ['./edit-item-template-page.component.scss'],
// templateUrl: './edit-item-template-page.component.html',
templateUrl: '../../../../../app/collection-page/edit-item-template-page/edit-item-template-page.component.html',
})
/**
* Component for editing the item template of a collection
*/
export class EditItemTemplatePageComponent extends BaseComponent {
}

View File

@@ -0,0 +1,23 @@
import { Component } from '@angular/core';
import { ViewMode } from '../../../../../../../app/core/shared/view-mode.model';
import {
listableObjectComponent
} from '../../../../../../../app/shared/object-collection/shared/listable-object/listable-object.decorator';
import {
JournalIssueComponent as BaseComponent
} from '../../../../../../../app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component';
import { Context } from '../../../../../../../app/core/shared/context.model';
@listableObjectComponent('JournalIssue', ViewMode.StandalonePage, Context.Any, 'custom')
@Component({
selector: 'ds-journal-issue',
// styleUrls: ['./journal-issue.component.scss'],
styleUrls: ['../../../../../../../app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.scss'],
// templateUrl: './journal-issue.component.html',
templateUrl: '../../../../../../../app/entity-groups/journal-entities/item-pages/journal-issue/journal-issue.component.html',
})
/**
* The component for displaying metadata and relations of an item of the type Journal Issue
*/
export class JournalIssueComponent extends BaseComponent {
}

Some files were not shown because too many files have changed in this diff Show More