mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 18:14:17 +00:00
Merge branch 'main' into w2p-97184_theme-feedback_contribute-main
This commit is contained in:
@@ -214,6 +214,9 @@ languages:
|
|||||||
- code: tr
|
- code: tr
|
||||||
label: Türkçe
|
label: Türkçe
|
||||||
active: true
|
active: true
|
||||||
|
- code: vi
|
||||||
|
label: Tiếng Việt
|
||||||
|
active: true
|
||||||
- code: kk
|
- code: kk
|
||||||
label: Қазақ
|
label: Қазақ
|
||||||
active: true
|
active: true
|
||||||
|
@@ -8,10 +8,10 @@
|
|||||||
<span class="fa fa-chevron-right invisible" aria-hidden="true"></span>
|
<span class="fa fa-chevron-right invisible" aria-hidden="true"></span>
|
||||||
</button>
|
</button>
|
||||||
<div class="align-middle pt-2">
|
<div class="align-middle pt-2">
|
||||||
<a *ngIf="node!==loadingNode" [routerLink]="[]" (click)="getNextPage(node)"
|
<button *ngIf="node!==loadingNode" (click)="getNextPage(node)"
|
||||||
class="btn btn-outline-primary btn-sm" role="button">
|
class="btn btn-outline-primary btn-sm" role="button">
|
||||||
<i class="fas fa-angle-down"></i> {{ 'communityList.showMore' | translate }}
|
<i class="fas fa-angle-down"></i> {{ 'communityList.showMore' | translate }}
|
||||||
</a>
|
</button>
|
||||||
<ds-themed-loading *ngIf="node===loadingNode && dataSource.loading$ | async" class="ds-themed-loading"></ds-themed-loading>
|
<ds-themed-loading *ngIf="node===loadingNode && dataSource.loading$ | async" class="ds-themed-loading"></ds-themed-loading>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -16,6 +16,7 @@ import { of as observableOf } from 'rxjs';
|
|||||||
import { By } from '@angular/platform-browser';
|
import { By } from '@angular/platform-browser';
|
||||||
import { isEmpty, isNotEmpty } from '../../shared/empty.util';
|
import { isEmpty, isNotEmpty } from '../../shared/empty.util';
|
||||||
import { FlatNode } from '../flat-node.model';
|
import { FlatNode } from '../flat-node.model';
|
||||||
|
import { RouterLinkWithHref } from '@angular/router';
|
||||||
|
|
||||||
describe('CommunityListComponent', () => {
|
describe('CommunityListComponent', () => {
|
||||||
let component: CommunityListComponent;
|
let component: CommunityListComponent;
|
||||||
@@ -194,7 +195,7 @@ describe('CommunityListComponent', () => {
|
|||||||
}),
|
}),
|
||||||
CdkTreeModule,
|
CdkTreeModule,
|
||||||
RouterTestingModule],
|
RouterTestingModule],
|
||||||
declarations: [CommunityListComponent],
|
declarations: [CommunityListComponent, RouterLinkWithHref],
|
||||||
providers: [CommunityListComponent,
|
providers: [CommunityListComponent,
|
||||||
{ provide: CommunityListService, useValue: communityListServiceStub },],
|
{ provide: CommunityListService, useValue: communityListServiceStub },],
|
||||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||||
@@ -230,9 +231,14 @@ describe('CommunityListComponent', () => {
|
|||||||
expect(showMoreEl).toBeTruthy();
|
expect(showMoreEl).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not render the show more button as an empty link', () => {
|
||||||
|
const debugElements = fixture.debugElement.queryAll(By.directive(RouterLinkWithHref));
|
||||||
|
expect(debugElements).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
describe('when show more of top communities is clicked', () => {
|
describe('when show more of top communities is clicked', () => {
|
||||||
beforeEach(fakeAsync(() => {
|
beforeEach(fakeAsync(() => {
|
||||||
const showMoreLink = fixture.debugElement.query(By.css('.show-more-node a'));
|
const showMoreLink = fixture.debugElement.query(By.css('.show-more-node .btn-outline-primary'));
|
||||||
showMoreLink.triggerEventHandler('click', {
|
showMoreLink.triggerEventHandler('click', {
|
||||||
preventDefault: () => {/**/
|
preventDefault: () => {/**/
|
||||||
}
|
}
|
||||||
@@ -240,6 +246,7 @@ describe('CommunityListComponent', () => {
|
|||||||
tick();
|
tick();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('tree contains maximum of currentPage (2) * (2) elementsPerPage of first top communities, or less if there are less communities (3)', () => {
|
it('tree contains maximum of currentPage (2) * (2) elementsPerPage of first top communities, or less if there are less communities (3)', () => {
|
||||||
const expandableNodesFound = fixture.debugElement.queryAll(By.css('.expandable-node a'));
|
const expandableNodesFound = fixture.debugElement.queryAll(By.css('.expandable-node a'));
|
||||||
const childlessNodesFound = fixture.debugElement.queryAll(By.css('.childless-node a'));
|
const childlessNodesFound = fixture.debugElement.queryAll(By.css('.childless-node a'));
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { ChangeDetectorRef, Component, Input, OnInit } from '@angular/core';
|
||||||
import { ScriptDataService } from '../core/data/processes/script-data.service';
|
import { ScriptDataService } from '../core/data/processes/script-data.service';
|
||||||
import { FormControl, FormGroup } from '@angular/forms';
|
import { FormControl, FormGroup } from '@angular/forms';
|
||||||
import { getFirstCompletedRemoteData } from '../core/shared/operators';
|
import { getFirstCompletedRemoteData } from '../core/shared/operators';
|
||||||
@@ -40,7 +40,8 @@ export class CurationFormComponent implements OnInit {
|
|||||||
private notificationsService: NotificationsService,
|
private notificationsService: NotificationsService,
|
||||||
private translateService: TranslateService,
|
private translateService: TranslateService,
|
||||||
private handleService: HandleService,
|
private handleService: HandleService,
|
||||||
private router: Router
|
private router: Router,
|
||||||
|
private cdr: ChangeDetectorRef
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +60,7 @@ export class CurationFormComponent implements OnInit {
|
|||||||
.filter((value) => isNotEmpty(value) && value.includes('='))
|
.filter((value) => isNotEmpty(value) && value.includes('='))
|
||||||
.map((value) => value.split('=')[1].trim());
|
.map((value) => value.split('=')[1].trim());
|
||||||
this.form.get('task').patchValue(this.tasks[0]);
|
this.form.get('task').patchValue(this.tasks[0]);
|
||||||
|
this.cdr.detectChanges();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,7 +1,4 @@
|
|||||||
@media screen and (max-width: map-get($grid-breakpoints, md)) {
|
:host {
|
||||||
:host.open {
|
position: relative;
|
||||||
background-color: var(--bs-white);
|
z-index: var(--ds-nav-z-index);
|
||||||
top: 0;
|
|
||||||
position: sticky;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -1,3 +0,0 @@
|
|||||||
:host {
|
|
||||||
z-index: var(--ds-nav-z-index);
|
|
||||||
}
|
|
@@ -11,13 +11,12 @@
|
|||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.navbar ::ng-deep {
|
.navbar-toggler {
|
||||||
a {
|
border: none;
|
||||||
color: var(--ds-header-icon-color);
|
color: var(--ds-header-icon-color);
|
||||||
|
|
||||||
&:hover, &:focus {
|
&:hover, &:focus {
|
||||||
color: var(--ds-header-icon-color-hover);
|
color: var(--ds-header-icon-color-hover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
@@ -38,7 +38,7 @@ import { IdentifierDataService } from '../../core/data/identifier-data.service';
|
|||||||
import { IdentifierDataComponent } from '../../shared/object-list/identifier-data/identifier-data.component';
|
import { IdentifierDataComponent } from '../../shared/object-list/identifier-data/identifier-data.component';
|
||||||
import { ItemRegisterDoiComponent } from './item-register-doi/item-register-doi.component';
|
import { ItemRegisterDoiComponent } from './item-register-doi/item-register-doi.component';
|
||||||
import { DsoSharedModule } from '../../dso-shared/dso-shared.module';
|
import { DsoSharedModule } from '../../dso-shared/dso-shared.module';
|
||||||
|
import { ItemCurateComponent } from './item-curate/item-curate.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module that contains all components related to the Edit Item page administrator functionality
|
* Module that contains all components related to the Edit Item page administrator functionality
|
||||||
@@ -81,7 +81,8 @@ import { DsoSharedModule } from '../../dso-shared/dso-shared.module';
|
|||||||
VirtualMetadataComponent,
|
VirtualMetadataComponent,
|
||||||
ItemAuthorizationsComponent,
|
ItemAuthorizationsComponent,
|
||||||
IdentifierDataComponent,
|
IdentifierDataComponent,
|
||||||
ItemRegisterDoiComponent
|
ItemRegisterDoiComponent,
|
||||||
|
ItemCurateComponent
|
||||||
],
|
],
|
||||||
providers: [
|
providers: [
|
||||||
BundleDataService,
|
BundleDataService,
|
||||||
|
@@ -41,6 +41,7 @@ import { ItemPageVersionHistoryGuard } from './item-page-version-history.guard';
|
|||||||
import { ItemPageCollectionMapperGuard } from './item-page-collection-mapper.guard';
|
import { ItemPageCollectionMapperGuard } from './item-page-collection-mapper.guard';
|
||||||
import { ThemedDsoEditMetadataComponent } from '../../dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component';
|
import { ThemedDsoEditMetadataComponent } from '../../dso-shared/dso-edit-metadata/themed-dso-edit-metadata.component';
|
||||||
import { ItemPageRegisterDoiGuard } from './item-page-register-doi.guard';
|
import { ItemPageRegisterDoiGuard } from './item-page-register-doi.guard';
|
||||||
|
import { ItemCurateComponent } from './item-curate/item-curate.component';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Routing module that handles the routing for the Edit Item page administrator functionality
|
* Routing module that handles the routing for the Edit Item page administrator functionality
|
||||||
@@ -82,6 +83,11 @@ import { ItemPageRegisterDoiGuard } from './item-page-register-doi.guard';
|
|||||||
data: { title: 'item.edit.tabs.metadata.title', showBreadcrumbs: true },
|
data: { title: 'item.edit.tabs.metadata.title', showBreadcrumbs: true },
|
||||||
canActivate: [ItemPageMetadataGuard]
|
canActivate: [ItemPageMetadataGuard]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'curate',
|
||||||
|
component: ItemCurateComponent,
|
||||||
|
data: { title: 'item.edit.tabs.curate.title', showBreadcrumbs: true }
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'relationships',
|
path: 'relationships',
|
||||||
component: ItemRelationshipsComponent,
|
component: ItemRelationshipsComponent,
|
||||||
|
@@ -0,0 +1,7 @@
|
|||||||
|
<div class="container mt-3">
|
||||||
|
<h3>{{'item.edit.curate.title' |translate:{item: (itemName$ |async)} }}</h3>
|
||||||
|
<ds-curation-form
|
||||||
|
*ngIf="dsoRD$ | async as dsoRD"
|
||||||
|
[dsoHandle]="dsoRD?.payload.handle"
|
||||||
|
></ds-curation-form>
|
||||||
|
</div>
|
@@ -0,0 +1,75 @@
|
|||||||
|
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { CUSTOM_ELEMENTS_SCHEMA, DebugElement } from '@angular/core';
|
||||||
|
import { ItemCurateComponent } from './item-curate.component';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { createSuccessfulRemoteDataObject } from '../../../shared/remote-data.utils';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
|
||||||
|
import { Item } from '../../../core/shared/item.model';
|
||||||
|
|
||||||
|
describe('ItemCurateComponent', () => {
|
||||||
|
let comp: ItemCurateComponent;
|
||||||
|
let fixture: ComponentFixture<ItemCurateComponent>;
|
||||||
|
let debugEl: DebugElement;
|
||||||
|
|
||||||
|
let routeStub;
|
||||||
|
let dsoNameService;
|
||||||
|
|
||||||
|
const item = Object.assign(new Item(), {
|
||||||
|
handle: '123456789/1',
|
||||||
|
metadata: {'dc.title': ['Item Name']}
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(waitForAsync(() => {
|
||||||
|
routeStub = {
|
||||||
|
parent: {
|
||||||
|
data: observableOf({
|
||||||
|
dso: createSuccessfulRemoteDataObject(item)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dsoNameService = jasmine.createSpyObj('dsoNameService', {
|
||||||
|
getName: 'Item Name'
|
||||||
|
});
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [TranslateModule.forRoot()],
|
||||||
|
declarations: [ItemCurateComponent],
|
||||||
|
providers: [
|
||||||
|
{provide: ActivatedRoute, useValue: routeStub},
|
||||||
|
{provide: DSONameService, useValue: dsoNameService}
|
||||||
|
],
|
||||||
|
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
fixture = TestBed.createComponent(ItemCurateComponent);
|
||||||
|
comp = fixture.componentInstance;
|
||||||
|
debugEl = fixture.debugElement;
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
describe('init', () => {
|
||||||
|
it('should initialise the comp', () => {
|
||||||
|
expect(comp).toBeDefined();
|
||||||
|
expect(debugEl.nativeElement.innerHTML).toContain('ds-curation-form');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should contain the item information provided in the route', (done) => {
|
||||||
|
comp.dsoRD$.subscribe((value) => {
|
||||||
|
expect(value.payload.handle).toEqual('123456789/1');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should contain the item name', (done) => {
|
||||||
|
comp.itemName$.subscribe((value) => {
|
||||||
|
expect(value).toEqual('Item Name');
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,39 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { filter, map, take } from 'rxjs/operators';
|
||||||
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { DSONameService } from '../../../core/breadcrumbs/dso-name.service';
|
||||||
|
import { hasValue } from '../../../shared/empty.util';
|
||||||
|
import { Item } from '../../../core/shared/item.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component for managing a collection's curation tasks
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-item-curate',
|
||||||
|
templateUrl: './item-curate.component.html',
|
||||||
|
})
|
||||||
|
export class ItemCurateComponent implements OnInit {
|
||||||
|
dsoRD$: Observable<RemoteData<Item>>;
|
||||||
|
itemName$: Observable<string>;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
private route: ActivatedRoute,
|
||||||
|
private dsoNameService: DSONameService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.dsoRD$ = this.route.parent.data.pipe(
|
||||||
|
take(1),
|
||||||
|
map((data) => data.dso),
|
||||||
|
);
|
||||||
|
|
||||||
|
this.itemName$ = this.dsoRD$.pipe(
|
||||||
|
filter((rd: RemoteData<Item>) => hasValue(rd)),
|
||||||
|
map((rd: RemoteData<Item>) => {
|
||||||
|
return this.dsoNameService.getName(rd.payload);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -8,10 +8,10 @@
|
|||||||
</ds-themed-file-download-link>
|
</ds-themed-file-download-link>
|
||||||
<ds-themed-loading *ngIf="isLoading" message="{{'loading.default' | translate}}" [showMessage]="false"></ds-themed-loading>
|
<ds-themed-loading *ngIf="isLoading" message="{{'loading.default' | translate}}" [showMessage]="false"></ds-themed-loading>
|
||||||
<div *ngIf="!isLastPage" class="mt-1" id="view-more">
|
<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>
|
<button class="bitstream-view-more btn btn-outline-secondary btn-sm" (click)="getNextPage()">{{'item.page.bitstreams.view-more' | translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="isLastPage && currentPage != 1" class="mt-1" id="collapse">
|
<div *ngIf="isLastPage && currentPage != 1" class="mt-1" id="collapse">
|
||||||
<a class="bitstream-collapse btn btn-outline-secondary btn-sm" [routerLink]="[]" (click)="currentPage = undefined; getNextPage();">{{'item.page.bitstreams.collapse' | translate}}</a>
|
<button class="bitstream-collapse btn btn-outline-secondary btn-sm" (click)="currentPage = undefined; getNextPage();">{{'item.page.bitstreams.collapse' | translate}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ds-metadata-field-wrapper>
|
</ds-metadata-field-wrapper>
|
||||||
|
@@ -7,12 +7,12 @@
|
|||||||
<ds-themed-loading *ngIf="(i + 1) === objects.length && (i > 0) && (!representations || representations?.length === 0)" message="{{'loading.default' | translate}}"></ds-themed-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 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">
|
<div *ngIf="(objects.length * incrementBy) < total" class="float-left">
|
||||||
<a [routerLink]="[]" (click)="increase()">{{'item.page.related-items.view-more' |
|
<button class="btn btn-link btn-link-inline" (click)="increase()">{{'item.page.related-items.view-more' |
|
||||||
translate:{ amount: (total - (objects.length * incrementBy) < incrementBy) ? total - (objects.length * incrementBy) : incrementBy } }}</a>
|
translate:{ amount: (total - (objects.length * incrementBy) < incrementBy) ? total - (objects.length * incrementBy) : incrementBy } }}</button>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="objects.length > 1" class="float-right">
|
<div *ngIf="objects.length > 1" class="float-right">
|
||||||
<a [routerLink]="[]" (click)="decrease()">{{'item.page.related-items.view-less' |
|
<button class="btn btn-link btn-link-inline" (click)="decrease()">{{'item.page.related-items.view-less' |
|
||||||
translate:{ amount: representations?.length } }}</a>
|
translate:{ amount: representations?.length } }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@@ -7,12 +7,12 @@
|
|||||||
<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>
|
<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 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">
|
<div *ngIf="itemsRD?.payload?.totalPages > objects.length" class="float-left" id="view-more">
|
||||||
<a [routerLink]="[]" (click)="increase()">{{'item.page.related-items.view-more' |
|
<button class="btn btn-link btn-link-inline" (click)="increase()">{{'item.page.related-items.view-more' |
|
||||||
translate:{ amount: (itemsRD?.payload?.totalElements - (incrementBy * objects.length) < incrementBy) ? itemsRD?.payload?.totalElements - (incrementBy * objects.length) : incrementBy } }}</a>
|
translate:{ amount: (itemsRD?.payload?.totalElements - (incrementBy * objects.length) < incrementBy) ? itemsRD?.payload?.totalElements - (incrementBy * objects.length) : incrementBy } }}</button>
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="objects.length > 1" class="float-right" id="view-less">
|
<div *ngIf="objects.length > 1" class="float-right" id="view-less">
|
||||||
<a [routerLink]="[]" (click)="decrease()">{{'item.page.related-items.view-less' |
|
<button class="btn btn-link btn-link-inline" (click)="decrease()">{{'item.page.related-items.view-less' |
|
||||||
translate:{ amount: itemsRD?.payload?.page?.length } }}</a>
|
translate:{ amount: itemsRD?.payload?.page?.length } }}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@@ -4,9 +4,9 @@
|
|||||||
<input #searchInput [@toggleAnimation]="isExpanded" [attr.aria-label]="('nav.search' | translate)" name="query"
|
<input #searchInput [@toggleAnimation]="isExpanded" [attr.aria-label]="('nav.search' | translate)" name="query"
|
||||||
formControlName="query" type="text" placeholder="{{searchExpanded ? ('nav.search' | translate) : ''}}"
|
formControlName="query" type="text" placeholder="{{searchExpanded ? ('nav.search' | translate) : ''}}"
|
||||||
class="d-inline-block bg-transparent position-absolute form-control dropdown-menu-right p-1" [attr.data-test]="'header-search-box' | dsBrowserOnly">
|
class="d-inline-block bg-transparent position-absolute form-control dropdown-menu-right p-1" [attr.data-test]="'header-search-box' | dsBrowserOnly">
|
||||||
<a class="submit-icon" [routerLink]="" (click)="searchExpanded ? onSubmit(searchForm.value) : expand()" [attr.data-test]="'header-search-icon' | dsBrowserOnly">
|
<button class="submit-icon btn btn-link btn-link-inline" [attr.aria-label]="'nav.search.button' | translate" type="button" (click)="searchExpanded ? onSubmit(searchForm.value) : expand()" [attr.data-test]="'header-search-icon' | dsBrowserOnly">
|
||||||
<em class="fas fa-search fa-lg fa-fw"></em>
|
<em class="fas fa-search fa-lg fa-fw"></em>
|
||||||
</a>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,13 +1,14 @@
|
|||||||
input[type="text"] {
|
input[type="text"] {
|
||||||
margin-top: calc(-0.5 * var(--bs-font-size-base));
|
margin-top: calc(-0.5 * var(--bs-font-size-base));
|
||||||
background-color: #fff !important;
|
background-color: #fff !important;
|
||||||
|
border-color: var(--ds-header-icon-color);
|
||||||
|
|
||||||
&.collapsed {
|
&.collapsed {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
a.submit-icon {
|
.submit-icon {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
|
@@ -19,7 +19,7 @@
|
|||||||
</li>
|
</li>
|
||||||
<li *ngIf="(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item">
|
<li *ngIf="(isAuthenticated | async) && !(isXsOrSm$ | async) && (showAuth | async)" class="nav-item">
|
||||||
<div ngbDropdown display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
|
<div ngbDropdown display="dynamic" placement="bottom-right" class="d-inline-block" @fadeInOut>
|
||||||
<a href="javascript:void(0);" role="button" [attr.aria-label]="'nav.user-profile-menu-and-logout' |translate" (click)="$event.preventDefault()" [title]="'nav.user-profile-menu-and-logout' | translate" class="px-1" [attr.data-test]="'user-menu' | dsBrowserOnly" ngbDropdownToggle>
|
<a href="javascript:void(0);" role="button" [attr.aria-label]="'nav.user-profile-menu-and-logout' |translate" (click)="$event.preventDefault()" [title]="'nav.user-profile-menu-and-logout' | translate" class="dropdownLogout px-1" [attr.data-test]="'user-menu' | dsBrowserOnly" ngbDropdownToggle>
|
||||||
<i class="fas fa-user-circle fa-lg fa-fw"></i></a>
|
<i class="fas fa-user-circle fa-lg fa-fw"></i></a>
|
||||||
<div class="logoutDropdownMenu" ngbDropdownMenu [attr.aria-label]="'nav.user-profile-menu-and-logout' |translate">
|
<div class="logoutDropdownMenu" ngbDropdownMenu [attr.aria-label]="'nav.user-profile-menu-and-logout' |translate">
|
||||||
<ds-user-menu></ds-user-menu>
|
<ds-user-menu></ds-user-menu>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li *ngIf="(isAuthenticated | async) && (isXsOrSm$ | async)" class="nav-item">
|
<li *ngIf="(isAuthenticated | async) && (isXsOrSm$ | async)" class="nav-item">
|
||||||
<a id="logoutLink" role="button" [attr.aria-label]="'nav.logout' |translate" [title]="'nav.logout' | translate" routerLink="/logout" routerLinkActive="active" class="px-1">
|
<a role="button" [attr.aria-label]="'nav.logout' |translate" [title]="'nav.logout' | translate" routerLink="/logout" routerLinkActive="active" class="logoutLink px-1">
|
||||||
<i class="fas fa-sign-out-alt fa-lg fa-fw"></i>
|
<i class="fas fa-sign-out-alt fa-lg fa-fw"></i>
|
||||||
<span class="sr-only">(current)</span>
|
<span class="sr-only">(current)</span>
|
||||||
</a>
|
</a>
|
||||||
|
@@ -12,7 +12,7 @@
|
|||||||
background-color: transparent !important;
|
background-color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-toggle {
|
.loginLink, .dropdownLogin, .logoutLink, .dropdownLogout {
|
||||||
color: var(--ds-header-icon-color);
|
color: var(--ds-header-icon-color);
|
||||||
|
|
||||||
&:hover, &:focus {
|
&:hover, &:focus {
|
||||||
|
@@ -358,7 +358,7 @@ describe('AuthNavMenuComponent', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should render logout link', inject([Store], (store: Store<AppState>) => {
|
it('should render logout link', inject([Store], (store: Store<AppState>) => {
|
||||||
const logoutDropdownMenu = deNavMenuItem.query(By.css('a[id=logoutLink]'));
|
const logoutDropdownMenu = deNavMenuItem.query(By.css('a.logoutLink'));
|
||||||
expect(logoutDropdownMenu.nativeElement).toBeDefined();
|
expect(logoutDropdownMenu.nativeElement).toBeDefined();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<div class="btn-group" data-toggle="buttons">
|
<div class="btn-group" data-toggle="buttons">
|
||||||
<a *ngIf="isToShow(viewModeEnum.ListElement)"
|
<button *ngIf="isToShow(viewModeEnum.ListElement)"
|
||||||
routerLink="."
|
routerLink="."
|
||||||
[queryParams]="{view: 'list'}"
|
[queryParams]="{view: 'list'}"
|
||||||
queryParamsHandling="merge"
|
queryParamsHandling="merge"
|
||||||
@@ -8,9 +8,9 @@
|
|||||||
[class.active]="currentMode === viewModeEnum.ListElement"
|
[class.active]="currentMode === viewModeEnum.ListElement"
|
||||||
class="btn btn-secondary"
|
class="btn btn-secondary"
|
||||||
[attr.data-test]="'list-view' | dsBrowserOnly">
|
[attr.data-test]="'list-view' | dsBrowserOnly">
|
||||||
<i class="fas fa-list" title="{{'search.view-switch.show-list' | translate}}"></i>
|
<span class="fas fa-list"></span><span class="sr-only">{{'search.view-switch.show-list' | translate}}</span>
|
||||||
</a>
|
</button>
|
||||||
<a *ngIf="isToShow(viewModeEnum.GridElement)"
|
<button *ngIf="isToShow(viewModeEnum.GridElement)"
|
||||||
routerLink="."
|
routerLink="."
|
||||||
[queryParams]="{view: 'grid'}"
|
[queryParams]="{view: 'grid'}"
|
||||||
queryParamsHandling="merge"
|
queryParamsHandling="merge"
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
[class.active]="currentMode === viewModeEnum.GridElement"
|
[class.active]="currentMode === viewModeEnum.GridElement"
|
||||||
class="btn btn-secondary"
|
class="btn btn-secondary"
|
||||||
[attr.data-test]="'grid-view' | dsBrowserOnly">
|
[attr.data-test]="'grid-view' | dsBrowserOnly">
|
||||||
<i class="fas fa-th-large" title="{{'search.view-switch.show-grid' | translate}}"></i>
|
<span class="fas fa-th-large"></span><span class="sr-only">{{'search.view-switch.show-grid' | translate}}</span>
|
||||||
</a>
|
</button>
|
||||||
<a *ngIf="isToShow(viewModeEnum.DetailedListElement)"
|
<button *ngIf="isToShow(viewModeEnum.DetailedListElement)"
|
||||||
routerLink="."
|
routerLink="."
|
||||||
[queryParams]="{view: 'detailed'}"
|
[queryParams]="{view: 'detailed'}"
|
||||||
queryParamsHandling="merge"
|
queryParamsHandling="merge"
|
||||||
@@ -30,6 +30,6 @@
|
|||||||
[class.active]="currentMode === viewModeEnum.DetailedListElement"
|
[class.active]="currentMode === viewModeEnum.DetailedListElement"
|
||||||
class="btn btn-secondary"
|
class="btn btn-secondary"
|
||||||
[attr.data-test]="'detail-view' | dsBrowserOnly">
|
[attr.data-test]="'detail-view' | dsBrowserOnly">
|
||||||
<i class="far fa-square" title="{{'search.view-switch.show-detail' | translate}}"></i>
|
<span class="far fa-square"></span><span class="sr-only">{{'search.view-switch.show-detail' | translate}}</span>
|
||||||
</a>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -61,7 +61,7 @@ describe('ViewModeSwitchComponent', () => {
|
|||||||
searchService.setViewMode(ViewMode.ListElement);
|
searchService.setViewMode(ViewMode.ListElement);
|
||||||
tick();
|
tick();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const debugElements = fixture.debugElement.queryAll(By.css('a'));
|
const debugElements = fixture.debugElement.queryAll(By.css('button'));
|
||||||
listButton = debugElements[0].nativeElement;
|
listButton = debugElements[0].nativeElement;
|
||||||
gridButton = debugElements[1].nativeElement;
|
gridButton = debugElements[1].nativeElement;
|
||||||
}));
|
}));
|
||||||
@@ -96,7 +96,7 @@ describe('ViewModeSwitchComponent', () => {
|
|||||||
searchService.setViewMode(ViewMode.ListElement);
|
searchService.setViewMode(ViewMode.ListElement);
|
||||||
tick();
|
tick();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
const debugElements = fixture.debugElement.queryAll(By.css('a'));
|
const debugElements = fixture.debugElement.queryAll(By.css('button'));
|
||||||
listButton = debugElements[0].nativeElement;
|
listButton = debugElements[0].nativeElement;
|
||||||
detailButton = debugElements[1].nativeElement;
|
detailButton = debugElements[1].nativeElement;
|
||||||
}));
|
}));
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<span class="mb-5" [innerHTML]="licenseText$ | async"></span>
|
<span class="mb-5 preserve-line-breaks" [innerHTML]="licenseText$ | async"></span>
|
||||||
<br> <br>
|
<br> <br>
|
||||||
<ds-form *ngIf="formModel" #formRef="formComponent"
|
<ds-form *ngIf="formModel" #formRef="formComponent"
|
||||||
[formId]="formId"
|
[formId]="formId"
|
||||||
|
@@ -2291,6 +2291,7 @@
|
|||||||
"item.edit.tabs.curate.head": "Curate",
|
"item.edit.tabs.curate.head": "Curate",
|
||||||
|
|
||||||
"item.edit.tabs.curate.title": "Item Edit - Curate",
|
"item.edit.tabs.curate.title": "Item Edit - Curate",
|
||||||
|
"item.edit.curate.title": "Curate Item: {{item}}",
|
||||||
|
|
||||||
"item.edit.tabs.metadata.head": "Metadata",
|
"item.edit.tabs.metadata.head": "Metadata",
|
||||||
|
|
||||||
@@ -3146,6 +3147,9 @@
|
|||||||
|
|
||||||
"nav.search": "Search",
|
"nav.search": "Search",
|
||||||
|
|
||||||
|
"nav.search.button": "Submit search",
|
||||||
|
|
||||||
|
|
||||||
"nav.statistics.header": "Statistics",
|
"nav.statistics.header": "Statistics",
|
||||||
|
|
||||||
"nav.stop-impersonating": "Stop impersonating EPerson",
|
"nav.stop-impersonating": "Stop impersonating EPerson",
|
||||||
|
2541
src/assets/i18n/vi.json5
Normal file
2541
src/assets/i18n/vi.json5
Normal file
File diff suppressed because it is too large
Load Diff
@@ -229,6 +229,7 @@ export class DefaultAppConfig implements AppConfig {
|
|||||||
{ code: 'fi', label: 'Suomi', active: true },
|
{ code: 'fi', label: 'Suomi', active: true },
|
||||||
{ code: 'sv', label: 'Svenska', active: true },
|
{ code: 'sv', label: 'Svenska', active: true },
|
||||||
{ code: 'tr', label: 'Türkçe', active: true },
|
{ code: 'tr', label: 'Türkçe', active: true },
|
||||||
|
{ code: 'vi', label: 'Tiếng Việt', active: true },
|
||||||
{ code: 'kk', label: 'Қазақ', active: true },
|
{ code: 'kk', label: 'Қазақ', active: true },
|
||||||
{ code: 'bn', label: 'বাংলা', active: true },
|
{ code: 'bn', label: 'বাংলা', active: true },
|
||||||
{ code: 'hi', label: 'हिंदी', active: true},
|
{ code: 'hi', label: 'हिंदी', active: true},
|
||||||
|
@@ -96,6 +96,7 @@ ngb-modal-backdrop {
|
|||||||
.researcher-profile-switch button:focus {
|
.researcher-profile-switch button:focus {
|
||||||
outline: none !important;
|
outline: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.researcher-profile-switch .switch.checked {
|
.researcher-profile-switch .switch.checked {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
@@ -121,6 +122,7 @@ ngb-modal-backdrop {
|
|||||||
box-shadow: none !important;
|
box-shadow: none !important;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.custom-accordion .card:first-of-type {
|
.custom-accordion .card:first-of-type {
|
||||||
border-bottom: var(--bs-card-border-width) solid var(--bs-card-border-color) !important;
|
border-bottom: var(--bs-card-border-width) solid var(--bs-card-border-color) !important;
|
||||||
border-bottom-left-radius: var(--bs-card-border-radius) !important;
|
border-bottom-left-radius: var(--bs-card-border-radius) !important;
|
||||||
@@ -155,6 +157,7 @@ ds-dynamic-form-control-container.d-none {
|
|||||||
.modal-body ds-listable-object-component-loader div.row > div:first-child {
|
.modal-body ds-listable-object-component-loader div.row > div:first-child {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-body ds-listable-object-component-loader div.row > div:nth-child(2) {
|
.modal-body ds-listable-object-component-loader div.row > div:nth-child(2) {
|
||||||
flex: 0 0 100%;
|
flex: 0 0 100%;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
@@ -176,6 +179,7 @@ ds-dynamic-form-control-container.d-none {
|
|||||||
padding: 0.1rem;
|
padding: 0.1rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumb-font-1 {
|
.thumb-font-1 {
|
||||||
.thumbnail-placeholder {
|
.thumbnail-placeholder {
|
||||||
@media screen and (max-width: map-get($grid-breakpoints, sm)) {
|
@media screen and (max-width: map-get($grid-breakpoints, sm)) {
|
||||||
@@ -190,12 +194,14 @@ ds-dynamic-form-control-container.d-none {
|
|||||||
padding: 0.125rem;
|
padding: 0.125rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumb-font-2 {
|
.thumb-font-2 {
|
||||||
.thumbnail-placeholder {
|
.thumbnail-placeholder {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
padding: 0.125rem;
|
padding: 0.125rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.thumb-font-3 {
|
.thumb-font-3 {
|
||||||
.thumbnail-placeholder {
|
.thumbnail-placeholder {
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
@@ -203,7 +209,17 @@ ds-dynamic-form-control-container.d-none {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn.btn-link.btn-link-inline {
|
||||||
|
display: inline;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
&:not(:disabled){
|
||||||
|
&:hover, &:focus {
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
.badge-validation {
|
.badge-validation {
|
||||||
background-color: #{map-get($theme-colors, warning)};
|
background-color: #{map-get($theme-colors, warning)};
|
||||||
|
@@ -6,7 +6,7 @@ import { HeaderNavbarWrapperComponent as BaseComponent } from '../../../../app/h
|
|||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-header-navbar-wrapper',
|
selector: 'ds-header-navbar-wrapper',
|
||||||
styleUrls: ['header-navbar-wrapper.component.scss'],
|
styleUrls: ['../../../../app/header-nav-wrapper/header-navbar-wrapper.component.scss'],
|
||||||
templateUrl: 'header-navbar-wrapper.component.html',
|
templateUrl: 'header-navbar-wrapper.component.html',
|
||||||
})
|
})
|
||||||
export class HeaderNavbarWrapperComponent extends BaseComponent {
|
export class HeaderNavbarWrapperComponent extends BaseComponent {
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-grow-1 ml-auto justify-content-end align-items-center">
|
<div class="d-flex flex-grow-1 ml-auto justify-content-end align-items-center">
|
||||||
<ds-search-navbar class="navbar-search"></ds-search-navbar>
|
<ds-themed-search-navbar></ds-themed-search-navbar>
|
||||||
<ds-lang-switch></ds-lang-switch>
|
<ds-lang-switch></ds-lang-switch>
|
||||||
<ds-context-help-toggle></ds-context-help-toggle>
|
<ds-context-help-toggle></ds-context-help-toggle>
|
||||||
<ds-themed-auth-nav-menu></ds-themed-auth-nav-menu>
|
<ds-themed-auth-nav-menu></ds-themed-auth-nav-menu>
|
||||||
|
@@ -15,5 +15,12 @@
|
|||||||
.navbar-toggler .navbar-toggler-icon {
|
.navbar-toggler .navbar-toggler-icon {
|
||||||
background-image: none !important;
|
background-image: none !important;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
color: var(--bs-link-color);
|
}
|
||||||
|
|
||||||
|
.navbar-toggler {
|
||||||
|
color: var(--ds-header-icon-color);
|
||||||
|
|
||||||
|
&:hover, &:focus {
|
||||||
|
color: var(--ds-header-icon-color-hover);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ nav.navbar {
|
|||||||
border-top: 1px var(--ds-header-navbar-border-top-color) solid;
|
border-top: 1px var(--ds-header-navbar-border-top-color) solid;
|
||||||
border-bottom: 5px var(--ds-header-navbar-border-bottom-color) solid;
|
border-bottom: 5px var(--ds-header-navbar-border-bottom-color) solid;
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
color: var(--ds-header-icon-color);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Mobile menu styling **/
|
/** Mobile menu styling **/
|
||||||
|
Reference in New Issue
Block a user