Merge pull request #2585 from tdonohue/port_2442_to_7x

[Port dspace-7_x] New themed components & minor CSS fixes
This commit is contained in:
Tim Donohue
2023-10-26 16:56:03 -05:00
committed by GitHub
37 changed files with 290 additions and 35 deletions

View File

@@ -89,11 +89,11 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
const lastItemRD = this.browseService.getFirstItemFor(definition, scope, SortDirection.DESC);
this.subs.push(
observableCombineLatest([firstItemRD, lastItemRD]).subscribe(([firstItem, lastItem]) => {
let lowerLimit = this.getLimit(firstItem, metadataKeys, this.appConfig.browseBy.defaultLowerLimit);
let upperLimit = this.getLimit(lastItem, metadataKeys, new Date().getUTCFullYear());
const options = [];
const oneYearBreak = Math.floor((upperLimit - this.appConfig.browseBy.oneYearLimit) / 5) * 5;
const fiveYearBreak = Math.floor((upperLimit - this.appConfig.browseBy.fiveYearLimit) / 10) * 10;
let lowerLimit: number = this.getLimit(firstItem, metadataKeys, this.appConfig.browseBy.defaultLowerLimit);
let upperLimit: number = this.getLimit(lastItem, metadataKeys, new Date().getUTCFullYear());
const options: number[] = [];
const oneYearBreak: number = Math.floor((upperLimit - this.appConfig.browseBy.oneYearLimit) / 5) * 5;
const fiveYearBreak: number = Math.floor((upperLimit - this.appConfig.browseBy.fiveYearLimit) / 10) * 10;
if (lowerLimit <= fiveYearBreak) {
lowerLimit -= 10;
} else if (lowerLimit <= oneYearBreak) {
@@ -101,7 +101,7 @@ export class BrowseByDatePageComponent extends BrowseByMetadataPageComponent {
} else {
lowerLimit -= 1;
}
let i = upperLimit;
let i: number = upperLimit;
while (i > lowerLimit) {
options.push(i);
if (i <= fiveYearBreak) {

View File

@@ -32,7 +32,7 @@
<section class="comcol-page-browse-section">
<div class="browse-by-metadata w-100">
<ds-browse-by *ngIf="startsWithOptions" class="col-xs-12 w-100"
<ds-themed-browse-by *ngIf="startsWithOptions" class="col-xs-12 w-100"
title="{{'browse.title' | translate:
{
collection: dsoNameService.getName((parent$ | async)?.payload),
@@ -48,7 +48,7 @@
[startsWithOptions]="startsWithOptions"
(prev)="goPrev()"
(next)="goNext()">
</ds-browse-by>
</ds-themed-browse-by>
<ds-themed-loading *ngIf="!startsWithOptions" message="{{'loading.browse-by-page' | translate}}"></ds-themed-loading>
</div>
</section>

View File

@@ -14,6 +14,7 @@ import { ThemedBrowseByTaxonomyPageComponent } from './browse-by-taxonomy-page/t
import { SharedBrowseByModule } from '../shared/browse-by/shared-browse-by.module';
import { DsoPageModule } from '../shared/dso-page/dso-page.module';
import { FormModule } from '../shared/form/form.module';
import { SharedModule } from '../shared/shared.module';
const ENTRY_COMPONENTS = [
// put only entry components that use custom decorator
@@ -35,6 +36,7 @@ const ENTRY_COMPONENTS = [
ComcolModule,
DsoPageModule,
FormModule,
SharedModule,
],
declarations: [
BrowseBySwitcherComponent,

View File

@@ -1,3 +1,3 @@
<ds-register-email-form
<ds-themed-register-email-form
[MESSAGE_PREFIX]="'forgot-email.form'" [typeRequest]="typeRequest">
</ds-register-email-form>
</ds-themed-register-email-form>

View File

@@ -1,12 +1,12 @@
<ng-container *ngVar="(itemRD$ | async) as itemRD">
<div class="mt-4" [ngClass]="placeholderFontClass" *ngIf="itemRD?.hasSucceeded && itemRD?.payload?.page.length > 0" @fadeIn>
<div class="d-flex flex-row border-bottom mb-4 pb-4 ng-tns-c416-2"></div>
<div class="d-flex flex-row border-bottom mb-4 pb-4"></div>
<h2> {{'home.recent-submissions.head' | translate}}</h2>
<div class="my-4" *ngFor="let item of itemRD?.payload?.page">
<ds-listable-object-component-loader [object]="item" [viewMode]="viewMode" class="pb-4">
</ds-listable-object-component-loader>
</div>
<button (click)="onLoadMore()" class="btn btn-primary search-button mt-4 float-left ng-tns-c290-40"> {{'vocabulary-treeview.load-more' | translate }} ...</button>
<button (click)="onLoadMore()" class="btn btn-primary search-button mt-4"> {{'vocabulary-treeview.load-more' | translate }} ...</button>
</div>
<ds-error *ngIf="itemRD?.hasFailed" message="{{'error.recent-submissions' | translate}}"></ds-error>
<ds-loading *ngIf="!itemRD || itemRD.isLoading" message="{{'loading.recent-submissions' | translate}}">

View File

@@ -3,8 +3,8 @@
<div>
<img class="mb-4 login-logo" src="assets/images/dspace-logo.png" alt="{{'repository.image.logo' | translate}}">
<h1 class="h3 mb-0 font-weight-normal">{{"login.form.header" | translate}}</h1>
<ds-log-in
[isStandalonePage]="true"></ds-log-in>
<ds-themed-log-in
[isStandalonePage]="true"></ds-themed-log-in>
</div>
</div>
</div>

View File

@@ -39,8 +39,9 @@ nav.navbar {
.navbar-nav {
::ng-deep a.nav-link {
color: var(--ds-navbar-link-color);
}
::ng-deep a.nav-link:hover {
&:hover, &:focus {
color: var(--ds-navbar-link-color-hover);
}
}
}

View File

@@ -2,6 +2,12 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { SharedModule } from '../shared/shared.module';
import { RegisterEmailFormComponent } from './register-email-form.component';
import { ThemedRegisterEmailFormComponent } from './themed-registry-email-form.component';
const DECLARATIONS = [
RegisterEmailFormComponent,
ThemedRegisterEmailFormComponent,
];
@NgModule({
imports: [
@@ -9,11 +15,11 @@ import { RegisterEmailFormComponent } from './register-email-form.component';
SharedModule
],
declarations: [
RegisterEmailFormComponent,
...DECLARATIONS,
],
providers: [],
exports: [
RegisterEmailFormComponent,
...DECLARATIONS,
]
})

View File

@@ -0,0 +1,36 @@
import { Component, Input } from '@angular/core';
import { ThemedComponent } from '../shared/theme-support/themed.component';
import { RegisterEmailFormComponent } from './register-email-form.component';
/**
* Themed wrapper for {@link RegisterEmailFormComponent}
*/
@Component({
selector: 'ds-themed-register-email-form',
styleUrls: [],
templateUrl: '../shared/theme-support/themed.component.html',
})
export class ThemedRegisterEmailFormComponent extends ThemedComponent<RegisterEmailFormComponent> {
@Input() MESSAGE_PREFIX: string;
@Input() typeRequest: string;
protected inAndOutputNames: (keyof RegisterEmailFormComponent & keyof this)[] = [
'MESSAGE_PREFIX',
'typeRequest',
];
protected getComponentName(): string {
return 'RegisterEmailFormComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../themes/${themeName}/app/register-email-form/register-email-form.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import('./register-email-form.component');
}
}

View File

@@ -1,3 +1,3 @@
<ds-register-email-form
<ds-themed-register-email-form
[MESSAGE_PREFIX]="'register-page.registration'" [typeRequest]="typeRequest">
</ds-register-email-form>
</ds-themed-register-email-form>

View File

@@ -7,8 +7,8 @@
ngbDropdownToggle>{{ 'nav.login' | translate }}</a>
<div class="loginDropdownMenu" [ngClass]="{'pl-3 pr-3': (loading | async)}" ngbDropdownMenu
[attr.aria-label]="'nav.login' | translate">
<ds-log-in
[isStandalonePage]="false"></ds-log-in>
<ds-themed-log-in
[isStandalonePage]="false"></ds-themed-log-in>
</div>
</div>
</li>

View File

@@ -1,14 +1,20 @@
import { NgModule } from '@angular/core';
import { BrowseByComponent } from './browse-by.component';
import { ThemedBrowseByComponent } from './themed-browse-by.component';
import { CommonModule } from '@angular/common';
import { SharedModule } from '../shared.module';
import { ResultsBackButtonModule } from '../results-back-button/results-back-button.module';
import { BrowseByRoutingModule } from '../../browse-by/browse-by-routing.module';
import { AccessControlRoutingModule } from '../../access-control/access-control-routing.module';
const DECLARATIONS = [
BrowseByComponent,
ThemedBrowseByComponent,
];
@NgModule({
declarations: [
BrowseByComponent,
...DECLARATIONS,
],
imports: [
ResultsBackButtonModule,
@@ -18,8 +24,7 @@ import { AccessControlRoutingModule } from '../../access-control/access-control-
SharedModule,
],
exports: [
BrowseByComponent,
SharedModule,
...DECLARATIONS,
]
})
export class SharedBrowseByModule { }

View File

@@ -0,0 +1,76 @@
import { Component, Input, Output, EventEmitter } from '@angular/core';
import { ThemedComponent } from '../theme-support/themed.component';
import { BrowseByComponent } from './browse-by.component';
import { Observable } from 'rxjs';
import { RemoteData } from '../../core/data/remote-data';
import { PaginatedList } from '../../core/data/paginated-list.model';
import { ListableObject } from '../object-collection/shared/listable-object.model';
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
import { SortOptions, SortDirection } from '../../core/cache/models/sort-options.model';
import { StartsWithType } from '../starts-with/starts-with-decorator';
/**
* Themed wrapper for {@link BrowseByComponent}
*/
@Component({
selector: 'ds-themed-browse-by',
styleUrls: [],
templateUrl: '../theme-support/themed.component.html',
})
export class ThemedBrowseByComponent extends ThemedComponent<BrowseByComponent> {
@Input() title: string;
@Input() parentname: string;
@Input() objects$: Observable<RemoteData<PaginatedList<ListableObject>>>;
@Input() paginationConfig: PaginationComponentOptions;
@Input() sortConfig: SortOptions;
@Input() type: StartsWithType;
@Input() startsWithOptions: number[];
@Input() showPaginator: boolean;
@Input() hideGear: boolean;
@Output() prev: EventEmitter<boolean> = new EventEmitter();
@Output() next: EventEmitter<boolean> = new EventEmitter();
@Output() pageSizeChange: EventEmitter<number> = new EventEmitter();
@Output() sortDirectionChange: EventEmitter<SortDirection> = new EventEmitter();
protected inAndOutputNames: (keyof BrowseByComponent & keyof this)[] = [
'title',
'parentname',
'objects$',
'paginationConfig',
'sortConfig',
'type',
'startsWithOptions',
'showPaginator',
'hideGear',
'prev',
'next',
'pageSizeChange',
'sortDirectionChange',
];
protected getComponentName(): string {
return 'BrowseByComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../themes/${themeName}/app/shared/browse-by/browse-by.component.ts`);
}
protected importUnthemedComponent(): Promise<any> {
return import('./browse-by.component');
}
}

View File

@@ -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', () => {
@@ -75,6 +77,7 @@ describe('LogInComponent', () => {
{ provide: HardRedirectService, useValue: hardRedirectService },
{ provide: AuthorizationDataService, useValue: authorizationService },
provideMockStore({ initialState }),
{ provide: ThemeService, useValue: getMockThemeService() },
LogInComponent
],
schemas: [
@@ -91,7 +94,7 @@ describe('LogInComponent', () => {
// synchronous beforeEach
beforeEach(() => {
const html = `<ds-log-in [isStandalonePage]="isStandalonePage"> </ds-log-in>`;
const html = `<ds-themed-log-in [isStandalonePage]="isStandalonePage"> </ds-themed-log-in>`;
testFixture = createTestComponent(html, TestComponent) as ComponentFixture<TestComponent>;
testComp = testFixture.componentInstance;

View File

@@ -0,0 +1,33 @@
import { Component, Input } from '@angular/core';
import { ThemedComponent } from '../theme-support/themed.component';
import { LogInComponent } from './log-in.component';
/**
* Themed wrapper for {@link LogInComponent}
*/
@Component({
selector: 'ds-themed-log-in',
styleUrls: [],
templateUrl: './../theme-support/themed.component.html'
})
export class ThemedLogInComponent extends ThemedComponent<LogInComponent> {
@Input() isStandalonePage: boolean;
protected inAndOutputNames: (keyof LogInComponent & keyof this)[] = [
'isStandalonePage',
];
protected getComponentName(): string {
return 'LogInComponent';
}
protected importThemedComponent(themeName: string): Promise<any> {
return import(`../../../themes/${themeName}/app/shared/log-in/log-in.component`);
}
protected importUnthemedComponent(): Promise<any> {
return import('./log-in.component');
}
}

View File

@@ -6,7 +6,7 @@
[attr.aria-label]="(((collapsed$ | async) ? 'search.filters.filter.expand' : 'search.filters.filter.collapse') | translate) + ' ' + (('search.filters.filter.' + filter.name + '.head') | translate | lowercase)"
[attr.data-test]="'filter-toggle' | dsBrowserOnly"
>
<h4 class="d-inline-block mb-0">
<h4 class="d-inline-block text-left mt-auto mb-auto">
{{'search.filters.filter.' + filter.name + '.head'| translate}}
</h4>
<span class="filter-toggle flex-grow-1 fas p-auto"

View File

@@ -17,7 +17,6 @@
line-height: var(--bs-line-height-base);
text-align: right;
position: relative;
top: -0.125rem; // Fix weird outline shape in Chrome
}
> button {

View File

@@ -192,6 +192,7 @@ import {
import { LogInContainerComponent } from './log-in/container/log-in-container.component';
import { LogInPasswordComponent } from './log-in/methods/password/log-in-password.component';
import { LogInComponent } from './log-in/log-in.component';
import { ThemedLogInComponent } from './log-in/themed-log-in.component';
import { MissingTranslationHelper } from './translate/missing-translation.helper';
import { FileValidator } from './utils/require-file.validator';
import { FileValueAccessorDirective } from './utils/file-value-accessor.directive';
@@ -339,6 +340,7 @@ const COMPONENTS = [
LoadingComponent,
ThemedLoadingComponent,
LogInComponent,
ThemedLogInComponent,
LogOutComponent,
ObjectListComponent,
ThemedObjectListComponent,

View File

@@ -134,6 +134,7 @@
<div class="m-2">
<div (click)="setAccepted(!accepted)">
<input type="checkbox"
class="mr-2"
title="accepted"
[checked]="accepted">
<span> {{ 'submission.sections.ccLicense.confirmation' | translate }}</span>

View File

@@ -0,0 +1,20 @@
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 {
PersonComponent as BaseComponent
} from '../../../../../../../app/entity-groups/research-entities/item-pages/person/person.component';
import { Context } from '../../../../../../../app/core/shared/context.model';
@listableObjectComponent('Person', ViewMode.StandalonePage, Context.Any, 'custom')
@Component({
selector: 'ds-person',
// styleUrls: ['./person.component.scss'],
styleUrls: ['../../../../../../../app/entity-groups/research-entities/item-pages/person/person.component.scss'],
// templateUrl: './person.component.html',
templateUrl: '../../../../../../../app/entity-groups/research-entities/item-pages/person/person.component.html',
})
export class PersonComponent extends BaseComponent {
}

View File

@@ -3,8 +3,8 @@
<div>
<img class="mb-4 login-logo" src="assets/images/dspace-logo.png">
<h1 class="h3 mb-0 font-weight-normal">{{"login.form.header" | translate}}</h1>
<ds-log-in
[isStandalonePage]="true"></ds-log-in>
<ds-themed-log-in
[isStandalonePage]="true"></ds-themed-log-in>
</div>
</div>
</div>

View File

@@ -0,0 +1,12 @@
import { Component } from '@angular/core';
import {
RegisterEmailFormComponent as BaseComponent
} from '../../../../app/register-email-form/register-email-form.component';
@Component({
selector: 'ds-register-email-form',
// templateUrl: './register-email-form.component.html',
templateUrl: '../../../../app/register-email-form/register-email-form.component.html',
})
export class RegisterEmailFormComponent extends BaseComponent {
}

View File

@@ -0,0 +1,17 @@
import { Component } from '@angular/core';
import { fadeIn, fadeInOut } from '../../../../../app/shared/animations/fade';
import { BrowseByComponent as BaseComponent } from '../../../../../app/shared/browse-by/browse-by.component';
@Component({
selector: 'ds-browse-by',
// styleUrls: ['./browse-by.component.scss'],
styleUrls: ['../../../../../app/shared/browse-by/browse-by.component.scss'],
// templateUrl: './browse-by.component.html',
templateUrl: '../../../../../app/shared/browse-by/browse-by.component.html',
animations: [
fadeIn,
fadeInOut,
],
})
export class BrowseByComponent extends BaseComponent {
}

View File

@@ -0,0 +1,12 @@
import { Component } from '@angular/core';
import { LogInComponent as BaseComponent } from '../../../../../app/shared/log-in/log-in.component';
@Component({
selector: 'ds-log-in',
// templateUrl: './log-in.component.html',
templateUrl: '../../../../../app/shared/log-in/log-in.component.html',
// styleUrls: ['./log-in.component.scss'],
styleUrls: ['../../../../../app/shared/log-in/log-in.component.scss'],
})
export class LogInComponent extends BaseComponent {
}

View File

@@ -0,0 +1,19 @@
import { Component } from '@angular/core';
import { BrowseEntry } from '../../../../../../app/core/shared/browse-entry.model';
import { ViewMode } from '../../../../../../app/core/shared/view-mode.model';
import { listableObjectComponent } from '../../../../../../app/shared/object-collection/shared/listable-object/listable-object.decorator';
import { Context } from '../../../../../../app/core/shared/context.model';
import {
BrowseEntryListElementComponent as BaseComponent
} from '../../../../../../app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component';
@Component({
selector: 'ds-browse-entry-list-element',
// styleUrls: ['./browse-entry-list-element.component.scss'],
styleUrls: ['../../../../../../app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.scss'],
// templateUrl: './browse-entry-list-element.component.html',
templateUrl: '../../../../../../app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component.html',
})
@listableObjectComponent(BrowseEntry, ViewMode.ListElement, Context.Any, 'custom')
export class BrowseEntryListElementComponent extends BaseComponent {
}

View File

@@ -54,6 +54,9 @@ 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 { LogInComponent } from './app/shared/log-in/log-in.component';
import { BrowseEntryListElementComponent } from './app/shared/object-list/browse-entry-list-element/browse-entry-list-element.component';
import { PersonComponent } from './app/entity-groups/research-entities/item-pages/person/person.component';
import { LangSwitchComponent } from './app/shared/lang-switch/lang-switch.component';
@@ -65,6 +68,7 @@ const ENTRY_COMPONENTS = [
JournalComponent,
JournalIssueComponent,
JournalVolumeComponent,
PersonComponent,
PublicationComponent,
UntypedItemComponent,
CommunityListElementComponent,
@@ -76,6 +80,7 @@ const ENTRY_COMPONENTS = [
PublicationSidebarSearchListElementComponent,
ItemSearchResultListElementComponent,
TopLevelCommunityListComponent,
BrowseEntryListElementComponent,
];
const DECLARATIONS = [
@@ -92,6 +97,7 @@ const DECLARATIONS = [
EditCollectionSelectorComponent,
EditCommunitySelectorComponent,
EditItemSelectorComponent,
LogInComponent,
LangSwitchComponent,
];

View File

@@ -157,6 +157,8 @@ import { EditBitstreamPageComponent } from './app/bitstream-page/edit-bitstream-
import { FormModule } from '../../app/shared/form/form.module';
import { RequestCopyModule } from 'src/app/request-copy/request-copy.module';
import {UserMenuComponent} from './app/shared/auth-nav-menu/user-menu/user-menu.component';
import { BrowseByComponent } from './app/shared/browse-by/browse-by.component';
import { RegisterEmailFormComponent } from './app/register-email-form/register-email-form.component';
const DECLARATIONS = [
FileSectionComponent,
@@ -241,6 +243,8 @@ const DECLARATIONS = [
ItemStatusComponent,
EditBitstreamPageComponent,
UserMenuComponent,
BrowseByComponent,
RegisterEmailFormComponent,
];
@NgModule({

View File

@@ -53,11 +53,12 @@ a.navbar-brand img {
.navbar-nav {
::ng-deep a.nav-link {
color: var(--ds-navbar-link-color);
}
::ng-deep a.nav-link:hover {
&:hover, &:focus {
color: var(--ds-navbar-link-color-hover);
}
}
}
.navbar-buttons {
display: flex;