mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Merge branch 'main' of https://github.com/amanbudgujar/dspace-angular
This commit is contained in:
@@ -369,3 +369,8 @@ vocabularies:
|
||||
- filter: 'subject'
|
||||
vocabulary: 'srsc'
|
||||
enabled: true
|
||||
|
||||
# Default collection/community sorting order at Advanced search, Create/update community and collection when there are not a query.
|
||||
comcolSelectionSort:
|
||||
sortField: 'dc.title'
|
||||
sortDirection: 'ASC'
|
@@ -8,7 +8,7 @@
|
||||
<button class="mr-auto btn btn-success addEPerson-button"
|
||||
(click)="isEPersonFormShown = true">
|
||||
<i class="fas fa-plus"></i>
|
||||
<span class="d-none d-sm-inline">{{labelPrefix + 'button.add' | translate}}</span>
|
||||
<span class="d-none d-sm-inline ml-1">{{labelPrefix + 'button.add' | translate}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -30,7 +30,7 @@
|
||||
<div class="flex-grow-1 mr-3 ml-3">
|
||||
<div class="form-group input-group">
|
||||
<input type="text" name="query" id="query" formControlName="query"
|
||||
class="form-control" attr.aria-label="{{labelPrefix + 'search.placeholder' | translate}}"
|
||||
class="form-control" [attr.aria-label]="labelPrefix + 'search.placeholder' | translate"
|
||||
[placeholder]="(labelPrefix + 'search.placeholder' | translate)">
|
||||
<span class="input-group-append">
|
||||
<button type="submit" class="search-button btn btn-primary">
|
||||
@@ -72,13 +72,13 @@
|
||||
<td>{{epersonDto.eperson.email}}</td>
|
||||
<td>
|
||||
<div class="btn-group edit-field">
|
||||
<button class="delete-button" (click)="toggleEditEPerson(epersonDto.eperson)"
|
||||
<button (click)="toggleEditEPerson(epersonDto.eperson)"
|
||||
class="btn btn-outline-primary btn-sm access-control-editEPersonButton"
|
||||
title="{{labelPrefix + 'table.edit.buttons.edit' | translate: {name: epersonDto.eperson.name} }}">
|
||||
<i class="fas fa-edit fa-fw"></i>
|
||||
</button>
|
||||
<button [disabled]="!epersonDto.ableToDelete" (click)="deleteEPerson(epersonDto.eperson)"
|
||||
class="btn btn-outline-danger btn-sm access-control-deleteEPersonButton"
|
||||
class="delete-button btn btn-outline-danger btn-sm access-control-deleteEPersonButton"
|
||||
title="{{labelPrefix + 'table.edit.buttons.remove' | translate: {name: epersonDto.eperson.name} }}">
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
</button>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { Router } from '@angular/router';
|
||||
import { Observable, of as observableOf } from 'rxjs';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { BrowserModule, By } from '@angular/platform-browser';
|
||||
@@ -42,6 +42,7 @@ describe('EPeopleRegistryComponent', () => {
|
||||
let paginationService;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
jasmine.getEnv().allowRespy(true);
|
||||
mockEPeople = [EPersonMock, EPersonMock2];
|
||||
ePersonDataServiceStub = {
|
||||
activeEPerson: null,
|
||||
@@ -260,17 +261,16 @@ describe('EPeopleRegistryComponent', () => {
|
||||
describe('delete EPerson button when the isAuthorized returns false', () => {
|
||||
let ePeopleDeleteButton;
|
||||
beforeEach(() => {
|
||||
authorizationService = jasmine.createSpyObj('authorizationService', {
|
||||
isAuthorized: observableOf(false)
|
||||
});
|
||||
spyOn(authorizationService, 'isAuthorized').and.returnValue(observableOf(false));
|
||||
component.initialisePage();
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should be disabled', () => {
|
||||
ePeopleDeleteButton = fixture.debugElement.queryAll(By.css('#epeople tr td div button.delete-button'));
|
||||
ePeopleDeleteButton.forEach((deleteButton) => {
|
||||
ePeopleDeleteButton.forEach((deleteButton: DebugElement) => {
|
||||
expect(deleteButton.nativeElement.disabled).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { ComponentFixture, fakeAsync, flush, inject, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { BrowserModule, By } from '@angular/platform-browser';
|
||||
@@ -37,10 +37,10 @@ describe('MembersListComponent', () => {
|
||||
let ePersonDataServiceStub: any;
|
||||
let groupsDataServiceStub: any;
|
||||
let activeGroup;
|
||||
let allEPersons;
|
||||
let allGroups;
|
||||
let epersonMembers;
|
||||
let subgroupMembers;
|
||||
let allEPersons: EPerson[];
|
||||
let allGroups: Group[];
|
||||
let epersonMembers: EPerson[];
|
||||
let subgroupMembers: Group[];
|
||||
let paginationService;
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
@@ -53,7 +53,7 @@ describe('MembersListComponent', () => {
|
||||
activeGroup: activeGroup,
|
||||
epersonMembers: epersonMembers,
|
||||
subgroupMembers: subgroupMembers,
|
||||
findListByHref(href: string): Observable<RemoteData<PaginatedList<EPerson>>> {
|
||||
findListByHref(_href: string): Observable<RemoteData<PaginatedList<EPerson>>> {
|
||||
return createSuccessfulRemoteDataObject$(buildPaginatedList<EPerson>(new PageInfo(), groupsDataServiceStub.getEPersonMembers()));
|
||||
},
|
||||
searchByScope(scope: string, query: string): Observable<RemoteData<PaginatedList<EPerson>>> {
|
||||
@@ -147,6 +147,7 @@ describe('MembersListComponent', () => {
|
||||
});
|
||||
afterEach(fakeAsync(() => {
|
||||
fixture.destroy();
|
||||
fixture.debugElement.nativeElement.remove();
|
||||
flush();
|
||||
component = null;
|
||||
fixture.debugElement.nativeElement.remove();
|
||||
@@ -168,12 +169,19 @@ describe('MembersListComponent', () => {
|
||||
|
||||
describe('search', () => {
|
||||
describe('when searching without query', () => {
|
||||
let epersonsFound;
|
||||
let epersonsFound: DebugElement[];
|
||||
beforeEach(fakeAsync(() => {
|
||||
spyOn(component, 'isMemberOfGroup').and.callFake((ePerson: EPerson) => {
|
||||
return observableOf(activeGroup.epersons.includes(ePerson));
|
||||
});
|
||||
component.search({ scope: 'metadata', query: '' });
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
epersonsFound = fixture.debugElement.queryAll(By.css('#epersonsSearch tbody tr'));
|
||||
// Stop using the fake spy function (because otherwise the clicking on the buttons will not change anything
|
||||
// because they don't change the value of activeGroup.epersons)
|
||||
jasmine.getEnv().allowRespy(true);
|
||||
spyOn(component, 'isMemberOfGroup').and.callThrough();
|
||||
}));
|
||||
|
||||
it('should display all epersons', () => {
|
||||
@@ -182,62 +190,56 @@ describe('MembersListComponent', () => {
|
||||
|
||||
describe('if eperson is already a eperson', () => {
|
||||
it('should have delete button, else it should have add button', () => {
|
||||
activeGroup.epersons.map((eperson: EPerson) => {
|
||||
epersonsFound.map((foundEPersonRowElement) => {
|
||||
if (foundEPersonRowElement.debugElement !== undefined) {
|
||||
const epersonId = foundEPersonRowElement.debugElement.query(By.css('td:first-child'));
|
||||
const addButton = foundEPersonRowElement.debugElement.query(By.css('td:last-child .fa-plus'));
|
||||
const deleteButton = foundEPersonRowElement.debugElement.query(By.css('td:last-child .fa-trash-alt'));
|
||||
if (epersonId.nativeElement.textContent === eperson.id) {
|
||||
expect(addButton).toBeUndefined();
|
||||
expect(deleteButton).toBeDefined();
|
||||
const memberIds: string[] = activeGroup.epersons.map((ePerson: EPerson) => ePerson.id);
|
||||
epersonsFound.map((foundEPersonRowElement: DebugElement) => {
|
||||
const epersonId: DebugElement = foundEPersonRowElement.query(By.css('td:first-child'));
|
||||
const addButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-plus'));
|
||||
const deleteButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-trash-alt'));
|
||||
if (memberIds.includes(epersonId.nativeElement.textContent)) {
|
||||
expect(addButton).toBeNull();
|
||||
expect(deleteButton).not.toBeNull();
|
||||
} else {
|
||||
expect(deleteButton).toBeUndefined();
|
||||
expect(addButton).toBeDefined();
|
||||
expect(deleteButton).toBeNull();
|
||||
expect(addButton).not.toBeNull();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('if first add button is pressed', () => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
const addButton = fixture.debugElement.query(By.css('#epersonsSearch tbody .fa-plus'));
|
||||
const addButton: DebugElement = fixture.debugElement.query(By.css('#epersonsSearch tbody .fa-plus'));
|
||||
addButton.nativeElement.click();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
it('all groups in search member of selected group', () => {
|
||||
it('then all the ePersons are member of the active group', () => {
|
||||
epersonsFound = fixture.debugElement.queryAll(By.css('#epersonsSearch tbody tr'));
|
||||
expect(epersonsFound.length).toEqual(2);
|
||||
epersonsFound.map((foundEPersonRowElement) => {
|
||||
if (foundEPersonRowElement.debugElement !== undefined) {
|
||||
const addButton = foundEPersonRowElement.debugElement.query(By.css('td:last-child .fa-plus'));
|
||||
const deleteButton = foundEPersonRowElement.debugElement.query(By.css('td:last-child .fa-trash-alt'));
|
||||
expect(addButton).toBeUndefined();
|
||||
expect(deleteButton).toBeDefined();
|
||||
}
|
||||
epersonsFound.map((foundEPersonRowElement: DebugElement) => {
|
||||
const addButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-plus'));
|
||||
const deleteButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-trash-alt'));
|
||||
expect(addButton).toBeNull();
|
||||
expect(deleteButton).not.toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('if first delete button is pressed', () => {
|
||||
beforeEach(fakeAsync(() => {
|
||||
const addButton = fixture.debugElement.query(By.css('#epersonsSearch tbody .fa-trash-alt'));
|
||||
addButton.nativeElement.click();
|
||||
const deleteButton: DebugElement = fixture.debugElement.query(By.css('#epersonsSearch tbody .fa-trash-alt'));
|
||||
deleteButton.nativeElement.click();
|
||||
tick();
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
it('first eperson in search delete button, because now member', () => {
|
||||
it('then no ePerson is member of the active group', () => {
|
||||
epersonsFound = fixture.debugElement.queryAll(By.css('#epersonsSearch tbody tr'));
|
||||
epersonsFound.map((foundEPersonRowElement) => {
|
||||
if (foundEPersonRowElement.debugElement !== undefined) {
|
||||
const addButton = foundEPersonRowElement.debugElement.query(By.css('td:last-child .fa-plus'));
|
||||
const deleteButton = foundEPersonRowElement.debugElement.query(By.css('td:last-child .fa-trash-alt'));
|
||||
expect(deleteButton).toBeUndefined();
|
||||
expect(addButton).toBeDefined();
|
||||
}
|
||||
expect(epersonsFound.length).toEqual(2);
|
||||
epersonsFound.map((foundEPersonRowElement: DebugElement) => {
|
||||
const addButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-plus'));
|
||||
const deleteButton: DebugElement = foundEPersonRowElement.query(By.css('td:last-child .fa-trash-alt'));
|
||||
expect(deleteButton).toBeNull();
|
||||
expect(addButton).not.toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -249,6 +249,7 @@ export class MembersListComponent implements OnInit, OnDestroy {
|
||||
* @param ePerson EPerson we want to delete as member from group that is currently being edited
|
||||
*/
|
||||
deleteMemberFromGroup(ePerson: EpersonDtoModel) {
|
||||
ePerson.memberOfGroup = false;
|
||||
this.groupDataService.getActiveGroup().pipe(take(1)).subscribe((activeGroup: Group) => {
|
||||
if (activeGroup != null) {
|
||||
const response = this.groupDataService.deleteMemberFromGroup(activeGroup, ePerson.eperson);
|
||||
|
@@ -65,7 +65,7 @@
|
||||
<i class="fas fa-trash-alt fa-fw"></i>
|
||||
</button>
|
||||
|
||||
<p *ngIf="(isActiveGroup(group) | async)">{{ messagePrefix + '.table.edit.currentGroup' | translate }}</p>
|
||||
<span *ngIf="(isActiveGroup(group) | async)">{{ messagePrefix + '.table.edit.currentGroup' | translate }}</span>
|
||||
|
||||
<button *ngIf="!(isSubgroupOfGroup(group) | async) && !(isActiveGroup(group) | async)"
|
||||
(click)="addSubgroupToGroup(group)"
|
||||
|
@@ -1,14 +1,6 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import {
|
||||
ComponentFixture,
|
||||
fakeAsync,
|
||||
flush,
|
||||
inject,
|
||||
TestBed,
|
||||
tick,
|
||||
waitForAsync
|
||||
} from '@angular/core/testing';
|
||||
import { NO_ERRORS_SCHEMA, DebugElement } from '@angular/core';
|
||||
import { ComponentFixture, fakeAsync, flush, inject, TestBed, tick, waitForAsync } from '@angular/core/testing';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { BrowserModule, By } from '@angular/platform-browser';
|
||||
import { Router } from '@angular/router';
|
||||
@@ -46,8 +38,8 @@ describe('SubgroupsListComponent', () => {
|
||||
let ePersonDataServiceStub: any;
|
||||
let groupsDataServiceStub: any;
|
||||
let activeGroup;
|
||||
let subgroups;
|
||||
let allGroups;
|
||||
let subgroups: Group[];
|
||||
let allGroups: Group[];
|
||||
let routerStub;
|
||||
let paginationService;
|
||||
|
||||
@@ -65,7 +57,7 @@ describe('SubgroupsListComponent', () => {
|
||||
getSubgroups(): Group {
|
||||
return this.activeGroup;
|
||||
},
|
||||
findListByHref(href: string): Observable<RemoteData<PaginatedList<Group>>> {
|
||||
findListByHref(_href: string): Observable<RemoteData<PaginatedList<Group>>> {
|
||||
return this.subgroups$.pipe(
|
||||
map((currentGroups: Group[]) => {
|
||||
return createSuccessfulRemoteDataObject(buildPaginatedList<Group>(new PageInfo(), currentGroups));
|
||||
@@ -133,6 +125,7 @@ describe('SubgroupsListComponent', () => {
|
||||
});
|
||||
afterEach(fakeAsync(() => {
|
||||
fixture.destroy();
|
||||
fixture.debugElement.nativeElement.remove();
|
||||
flush();
|
||||
component = null;
|
||||
}));
|
||||
@@ -152,7 +145,7 @@ describe('SubgroupsListComponent', () => {
|
||||
});
|
||||
|
||||
describe('if first group delete button is pressed', () => {
|
||||
let groupsFound;
|
||||
let groupsFound: DebugElement[];
|
||||
beforeEach(fakeAsync(() => {
|
||||
const addButton = fixture.debugElement.query(By.css('#subgroupsOfGroup tbody .deleteButton'));
|
||||
addButton.triggerEventHandler('click', {
|
||||
@@ -170,7 +163,7 @@ describe('SubgroupsListComponent', () => {
|
||||
|
||||
describe('search', () => {
|
||||
describe('when searching with empty query', () => {
|
||||
let groupsFound;
|
||||
let groupsFound: DebugElement[];
|
||||
beforeEach(fakeAsync(() => {
|
||||
component.search({ query: '' });
|
||||
groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr'));
|
||||
@@ -181,9 +174,9 @@ describe('SubgroupsListComponent', () => {
|
||||
groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr'));
|
||||
expect(groupsFound.length).toEqual(2);
|
||||
groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr'));
|
||||
const groupIdsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr td:first-child'));
|
||||
const groupIdsFound: DebugElement[] = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr td:first-child'));
|
||||
allGroups.map((group: Group) => {
|
||||
expect(groupIdsFound.find((foundEl) => {
|
||||
expect(groupIdsFound.find((foundEl: DebugElement) => {
|
||||
return (foundEl.nativeElement.textContent.trim() === group.uuid);
|
||||
})).toBeTruthy();
|
||||
});
|
||||
@@ -195,30 +188,30 @@ describe('SubgroupsListComponent', () => {
|
||||
groupsFound = fixture.debugElement.queryAll(By.css('#groupsSearch tbody tr'));
|
||||
const getSubgroups = groupsDataServiceStub.getSubgroups().subgroups;
|
||||
if (getSubgroups !== undefined && getSubgroups.length > 0) {
|
||||
groupsFound.map((foundGroupRowElement) => {
|
||||
if (foundGroupRowElement.debugElement !== undefined) {
|
||||
const addButton = foundGroupRowElement.debugElement.query(By.css('td:last-child .fa-plus'));
|
||||
const deleteButton = foundGroupRowElement.debugElement.query(By.css('td:last-child .fa-trash-alt'));
|
||||
expect(addButton).toBeUndefined();
|
||||
expect(deleteButton).toBeDefined();
|
||||
groupsFound.map((foundGroupRowElement: DebugElement) => {
|
||||
const groupId: DebugElement = foundGroupRowElement.query(By.css('td:first-child'));
|
||||
const addButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-plus'));
|
||||
const deleteButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-trash-alt'));
|
||||
expect(addButton).toBeNull();
|
||||
if (activeGroup.id === groupId.nativeElement.textContent) {
|
||||
expect(deleteButton).toBeNull();
|
||||
} else {
|
||||
expect(deleteButton).not.toBeNull();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
getSubgroups.map((group: Group) => {
|
||||
groupsFound.map((foundGroupRowElement) => {
|
||||
if (foundGroupRowElement.debugElement !== undefined) {
|
||||
const groupId = foundGroupRowElement.debugElement.query(By.css('td:first-child'));
|
||||
const addButton = foundGroupRowElement.debugElement.query(By.css('td:last-child .fa-plus'));
|
||||
const deleteButton = foundGroupRowElement.debugElement.query(By.css('td:last-child .fa-trash-alt'));
|
||||
if (groupId.nativeElement.textContent === group.id) {
|
||||
expect(addButton).toBeUndefined();
|
||||
expect(deleteButton).toBeDefined();
|
||||
const subgroupIds: string[] = activeGroup.subgroups.map((group: Group) => group.id);
|
||||
groupsFound.map((foundGroupRowElement: DebugElement) => {
|
||||
const groupId: DebugElement = foundGroupRowElement.query(By.css('td:first-child'));
|
||||
const addButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-plus'));
|
||||
const deleteButton: DebugElement = foundGroupRowElement.query(By.css('td:last-child .fa-trash-alt'));
|
||||
if (subgroupIds.includes(groupId.nativeElement.textContent)) {
|
||||
expect(addButton).toBeNull();
|
||||
expect(deleteButton).not.toBeNull();
|
||||
} else {
|
||||
expect(deleteButton).toBeUndefined();
|
||||
expect(addButton).toBeDefined();
|
||||
expect(deleteButton).toBeNull();
|
||||
expect(addButton).not.toBeNull();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@@ -7,7 +7,7 @@
|
||||
<button class="mr-auto btn btn-success"
|
||||
[routerLink]="['newGroup']">
|
||||
<i class="fas fa-plus"></i>
|
||||
<span class="d-none d-sm-inline">{{messagePrefix + 'button.add' | translate}}</span>
|
||||
<span class="d-none d-sm-inline ml-1">{{messagePrefix + 'button.add' | translate}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -17,7 +17,7 @@
|
||||
<div class="flex-grow-1 mr-3">
|
||||
<div class="form-group input-group">
|
||||
<input type="text" name="query" id="query" formControlName="query"
|
||||
class="form-control" attr.aria-label="{{messagePrefix + 'search.placeholder' | translate}}"
|
||||
class="form-control" [attr.aria-label]="messagePrefix + 'search.placeholder' | translate"
|
||||
[placeholder]="(messagePrefix + 'search.placeholder' | translate)" >
|
||||
<span class="input-group-append">
|
||||
<button type="submit" class="search-button btn btn-primary">
|
||||
|
@@ -29,7 +29,7 @@
|
||||
<tbody>
|
||||
<tr *ngFor="let bitstreamFormat of (bitstreamFormats | async)?.payload?.page">
|
||||
<td>
|
||||
<label>
|
||||
<label class="mb-0">
|
||||
<input type="checkbox"
|
||||
[checked]="isSelected(bitstreamFormat) | async"
|
||||
(change)="selectBitStreamFormat(bitstreamFormat, $event)"
|
||||
|
@@ -29,7 +29,7 @@
|
||||
<tr *ngFor="let schema of (metadataSchemas | async)?.payload?.page"
|
||||
[ngClass]="{'table-primary' : isActive(schema) | async}">
|
||||
<td>
|
||||
<label>
|
||||
<label class="mb-0">
|
||||
<input type="checkbox"
|
||||
[checked]="isSelected(schema) | async"
|
||||
(change)="selectMetadataSchema(schema, $event)"
|
||||
|
@@ -1,3 +1,7 @@
|
||||
.selectable-row:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:host ::ng-deep #metadatadataschemagroup {
|
||||
display: flex;
|
||||
}
|
||||
|
@@ -34,14 +34,14 @@
|
||||
<tr *ngFor="let field of fields?.page"
|
||||
[ngClass]="{'table-primary' : isActive(field) | async}">
|
||||
<td>
|
||||
<label>
|
||||
<label class="mb-0">
|
||||
<input type="checkbox"
|
||||
[checked]="isSelected(field) | async"
|
||||
(change)="selectMetadataField(field, $event)">
|
||||
</label>
|
||||
</td>
|
||||
<td class="selectable-row" (click)="editField(field)">{{field.id}}</td>
|
||||
<td class="selectable-row" (click)="editField(field)">{{schema?.prefix}}.{{field.element}}<label *ngIf="field.qualifier">.</label>{{field.qualifier}}</td>
|
||||
<td class="selectable-row" (click)="editField(field)">{{schema?.prefix}}.{{field.element}}<label *ngIf="field.qualifier" class="mb-0">.</label>{{field.qualifier}}</td>
|
||||
<td class="selectable-row" (click)="editField(field)">{{field.scopeNote}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
@@ -1,3 +1,8 @@
|
||||
.selectable-row:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
:host ::ng-deep #metadatadatafieldgroup {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
@@ -52,7 +52,7 @@ describe(`LocaleInterceptor`, () => {
|
||||
|
||||
expect(httpRequest.request.headers.has('Accept-Language'));
|
||||
const lang = httpRequest.request.headers.get('Accept-Language');
|
||||
expect(lang).toBeDefined();
|
||||
expect(lang).not.toBeNull();
|
||||
expect(lang).toBe(languageList.toString());
|
||||
});
|
||||
|
||||
|
@@ -67,7 +67,7 @@ describe(`XsrfInterceptor`, () => {
|
||||
expect(httpRequest.request.headers.has('X-XSRF-TOKEN')).toBeTrue();
|
||||
expect(httpRequest.request.withCredentials).toBeTrue();
|
||||
const token = httpRequest.request.headers.get('X-XSRF-TOKEN');
|
||||
expect(token).toBeDefined();
|
||||
expect(token).not.toBeNull();
|
||||
expect(token).toBe(testToken.toString());
|
||||
|
||||
httpRequest.flush(mockPayload, { status: mockStatusCode, statusText: mockStatusText });
|
||||
@@ -116,11 +116,11 @@ describe(`XsrfInterceptor`, () => {
|
||||
// ensure mock XSRF token is in response
|
||||
expect(response.headers.has('DSPACE-XSRF-TOKEN')).toBeTrue();
|
||||
const token = response.headers.get('DSPACE-XSRF-TOKEN');
|
||||
expect(token).toBeDefined();
|
||||
expect(token).not.toBeNull();
|
||||
expect(token).toBe(mockNewXSRFToken.toString());
|
||||
|
||||
// ensure our XSRF-TOKEN cookie exists & has the same value as the new DSPACE-XSRF-TOKEN header
|
||||
expect(cookieService.get('XSRF-TOKEN')).toBeDefined();
|
||||
expect(cookieService.get('XSRF-TOKEN')).not.toBeNull();
|
||||
expect(cookieService.get('XSRF-TOKEN')).toBe(mockNewXSRFToken.toString());
|
||||
|
||||
done();
|
||||
@@ -153,7 +153,7 @@ describe(`XsrfInterceptor`, () => {
|
||||
expect(error.statusText).toBe(mockErrorText);
|
||||
|
||||
// ensure our XSRF-TOKEN cookie exists & has the same value as the new DSPACE-XSRF-TOKEN header
|
||||
expect(cookieService.get('XSRF-TOKEN')).toBeDefined();
|
||||
expect(cookieService.get('XSRF-TOKEN')).not.toBeNull();
|
||||
expect(cookieService.get('XSRF-TOKEN')).toBe(mockNewXSRFToken.toString());
|
||||
|
||||
done();
|
||||
|
@@ -104,9 +104,13 @@ describe('FullItemPageComponent', () => {
|
||||
fixture.detectChanges();
|
||||
}));
|
||||
|
||||
afterEach(() => {
|
||||
fixture.debugElement.nativeElement.remove();
|
||||
});
|
||||
|
||||
it('should display the item\'s metadata', () => {
|
||||
const table = fixture.debugElement.query(By.css('table'));
|
||||
for (const metadatum of mockItem.allMetadata([])) {
|
||||
for (const metadatum of mockItem.allMetadata(Object.keys(mockItem.metadata))) {
|
||||
expect(table.nativeElement.innerHTML).toContain(metadatum.value);
|
||||
}
|
||||
});
|
||||
@@ -137,7 +141,7 @@ describe('FullItemPageComponent', () => {
|
||||
|
||||
it('should display the item', () => {
|
||||
const objectLoader = fixture.debugElement.query(By.css('.full-item-info'));
|
||||
expect(objectLoader.nativeElement).toBeDefined();
|
||||
expect(objectLoader.nativeElement).not.toBeNull();
|
||||
});
|
||||
});
|
||||
describe('when the item is withdrawn and the user is not an admin', () => {
|
||||
@@ -161,7 +165,7 @@ describe('FullItemPageComponent', () => {
|
||||
|
||||
it('should display the item', () => {
|
||||
const objectLoader = fixture.debugElement.query(By.css('.full-item-info'));
|
||||
expect(objectLoader.nativeElement).toBeDefined();
|
||||
expect(objectLoader).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -173,7 +177,7 @@ describe('FullItemPageComponent', () => {
|
||||
|
||||
it('should display the item', () => {
|
||||
const objectLoader = fixture.debugElement.query(By.css('.full-item-info'));
|
||||
expect(objectLoader.nativeElement).toBeDefined();
|
||||
expect(objectLoader).not.toBeNull();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -253,7 +253,7 @@ describe('MiradorViewerComponent in development mode', () => {
|
||||
it('should show message', (() => {
|
||||
const value = fixture.debugElement
|
||||
.nativeElement.querySelector('#viewer-message');
|
||||
expect(value).toBeDefined();
|
||||
expect(value).not.toBeNull();
|
||||
}));
|
||||
|
||||
});
|
||||
|
@@ -3,7 +3,7 @@
|
||||
<div class="file-section">
|
||||
<ds-themed-file-download-link *ngFor="let file of bitstreams; let last=last;" [bitstream]="file" [item]="item">
|
||||
<span>{{file?.name}}</span>
|
||||
<span>({{(file?.sizeBytes) | dsFileSize }})</span>
|
||||
<span> ({{(file?.sizeBytes) | dsFileSize }})</span>
|
||||
<span *ngIf="!last" innerHTML="{{separator}}"></span>
|
||||
</ds-themed-file-download-link>
|
||||
<ds-themed-loading *ngIf="isLoading" message="{{'loading.default' | translate}}" [showMessage]="false"></ds-themed-loading>
|
||||
|
@@ -146,7 +146,7 @@ describe('FileSectionComponent', () => {
|
||||
|
||||
it('should contain a view less link', () => {
|
||||
const viewLess = fixture.debugElement.query(By.css('.bitstream-collapse'));
|
||||
expect(viewLess).toBeDefined();
|
||||
expect(viewLess).not.toBeNull();
|
||||
});
|
||||
|
||||
it('clicking on the view less link should reset the pages and call getNextPage()', () => {
|
||||
|
@@ -44,6 +44,6 @@ describe('ItemPageAbstractFieldComponent', () => {
|
||||
}));
|
||||
|
||||
it('should render a ds-metadata-values', () => {
|
||||
expect(fixture.debugElement.query(By.css('ds-metadata-values'))).toBeDefined();
|
||||
expect(fixture.debugElement.query(By.css('ds-metadata-values'))).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
@@ -41,6 +41,7 @@ describe('MenuResolver', () => {
|
||||
beforeEach(waitForAsync(() => {
|
||||
menuService = new MenuServiceStub();
|
||||
spyOn(menuService, 'getMenu').and.returnValue(observableOf(MENU_STATE));
|
||||
spyOn(menuService, 'addSection');
|
||||
|
||||
browseService = jasmine.createSpyObj('browseService', {
|
||||
getBrowseDefinitions: createSuccessfulRemoteDataObject$(createPaginatedList(BROWSE_DEFINITIONS))
|
||||
@@ -70,8 +71,6 @@ describe('MenuResolver', () => {
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
});
|
||||
resolver = TestBed.inject(MenuResolver);
|
||||
|
||||
spyOn(menuService, 'addSection');
|
||||
}));
|
||||
|
||||
it('should be created', () => {
|
||||
|
@@ -50,7 +50,8 @@ import { AccessControlRoutingModule } from '../../access-control/access-control-
|
||||
|
||||
@listableObjectComponent(BrowseEntry, ViewMode.ListElement, DEFAULT_CONTEXT, 'custom')
|
||||
@Component({
|
||||
selector: 'ds-browse-entry-list-element',
|
||||
// eslint-disable-next-line @angular-eslint/component-selector
|
||||
selector: '',
|
||||
template: ''
|
||||
})
|
||||
class MockThemedBrowseEntryListElementComponent {
|
||||
@@ -153,19 +154,21 @@ describe('BrowseByComponent', () => {
|
||||
it('should display a loading message when objects is empty', () => {
|
||||
(comp as any).objects = undefined;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.query(By.css('ds-themed-loading'))).toBeDefined();
|
||||
expect(fixture.debugElement.query(By.css('ds-themed-loading'))).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should display results when objects is not empty', () => {
|
||||
(comp as any).objects = observableOf({
|
||||
payload: {
|
||||
page: {
|
||||
length: 1
|
||||
}
|
||||
}
|
||||
});
|
||||
comp.objects$ = createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [
|
||||
Object.assign(new BrowseEntry(), {
|
||||
type: ITEM,
|
||||
authority: 'authority key 1',
|
||||
value: 'browse entry 1',
|
||||
language: null,
|
||||
count: 1,
|
||||
}),
|
||||
]));
|
||||
fixture.detectChanges();
|
||||
expect(fixture.debugElement.query(By.css('ds-viewable-collection'))).toBeDefined();
|
||||
expect(fixture.debugElement.query(By.css('ds-viewable-collection'))).not.toBeNull();
|
||||
});
|
||||
|
||||
describe('when showPaginator is true and browseEntries are provided', () => {
|
||||
@@ -237,15 +240,24 @@ describe('BrowseByComponent', () => {
|
||||
|
||||
describe('reset filters button', () => {
|
||||
it('should not be present when no startsWith or value is present ', () => {
|
||||
const button = fixture.debugElement.query(By.css('reset'));
|
||||
const button = fixture.debugElement.query(By.css('.reset'));
|
||||
expect(button).toBeNull();
|
||||
});
|
||||
it('should be present when a startsWith or value is present ', () => {
|
||||
comp.objects$ = createSuccessfulRemoteDataObject$(buildPaginatedList(new PageInfo(), [
|
||||
Object.assign(new BrowseEntry(), {
|
||||
type: ITEM,
|
||||
authority: 'authority key 1',
|
||||
value: 'browse entry 1',
|
||||
language: null,
|
||||
count: 1,
|
||||
}),
|
||||
]));
|
||||
comp.shouldDisplayResetButton$ = observableOf(true);
|
||||
fixture.detectChanges();
|
||||
|
||||
const button = fixture.debugElement.query(By.css('reset'));
|
||||
expect(button).toBeDefined();
|
||||
const button = fixture.debugElement.query(By.css('.reset'));
|
||||
expect(button).not.toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
|
@@ -7,7 +7,7 @@
|
||||
#searchFieldEl>
|
||||
</div>
|
||||
<div class="dropdown-divider"></div>
|
||||
<div class="scrollable-menu"
|
||||
<ul class="scrollable-menu p-0"
|
||||
aria-labelledby="dropdownMenuButton"
|
||||
(scroll)="onScroll($event)"
|
||||
infiniteScroll
|
||||
@@ -18,25 +18,25 @@
|
||||
[scrollWindow]="false"
|
||||
(scrolled)="onScrollDown()">
|
||||
|
||||
<button class="dropdown-item disabled" *ngIf="searchListCollection?.length == 0 && !(isLoading | async)">
|
||||
<li class="dropdown-item disabled" *ngIf="searchListCollection?.length == 0 && !(isLoading | async)">
|
||||
{{'submission.sections.general.no-collection' | translate}}
|
||||
</button>
|
||||
</li>
|
||||
<ng-container *ngIf="searchListCollection?.length > 0">
|
||||
<button *ngFor="let listItem of searchListCollection"
|
||||
<li *ngFor="let listItem of searchListCollection"
|
||||
class="dropdown-item collection-item"
|
||||
title="{{ listItem.collection.name }}"
|
||||
(click)="onSelect(listItem)">
|
||||
<ul class="list-unstyled mb-0">
|
||||
<li class="list-item text-truncate text-secondary" *ngFor="let item of listItem.communities">
|
||||
<div class="list-unstyled mb-0">
|
||||
<div class="list-item text-truncate text-secondary" *ngFor="let item of listItem.communities">
|
||||
{{ item.name}} <i class="fa fa-level-down" aria-hidden="true"></i>
|
||||
</div>
|
||||
<div class="list-item text-truncate text-primary font-weight-bold">{{ listItem.collection.name}}</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-item text-truncate text-primary font-weight-bold">{{ listItem.collection.name}}</li>
|
||||
</ul>
|
||||
</button>
|
||||
</ng-container>
|
||||
<button class="dropdown-item disabled" *ngIf="(isLoading | async)">
|
||||
<ds-themed-loading message="{{'loading.default' | translate}}">
|
||||
</ds-themed-loading>
|
||||
</button>
|
||||
|
||||
</div>
|
||||
</ul>
|
||||
|
@@ -11,6 +11,7 @@ import { PaginatedSearchOptions } from '../../search/models/paginated-search-opt
|
||||
import { hasValue } from '../../empty.util';
|
||||
import { createPaginatedList } from '../../testing/utils.test';
|
||||
import { NotificationsService } from '../../notifications/notifications.service';
|
||||
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||
|
||||
describe('DSOSelectorComponent', () => {
|
||||
let component: DSOSelectorComponent;
|
||||
@@ -34,7 +35,7 @@ describe('DSOSelectorComponent', () => {
|
||||
];
|
||||
|
||||
const searchService = {
|
||||
search: (options: PaginatedSearchOptions) => {
|
||||
search: (options: PaginatedSearchOptions, responseMsToLive?: number, useCachedVersionIfAvailable = true) => {
|
||||
if (hasValue(options.query) && options.query.startsWith('search.resourceid')) {
|
||||
return createSuccessfulRemoteDataObject$(createPaginatedList([searchResult]));
|
||||
} else if (options.pagination.currentPage === 1) {
|
||||
@@ -120,6 +121,43 @@ describe('DSOSelectorComponent', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('search', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(searchService, 'search').and.callThrough();
|
||||
});
|
||||
|
||||
it('should specify how to sort if no query is given', () => {
|
||||
component.sort = new SortOptions('dc.title', SortDirection.ASC);
|
||||
component.search(undefined, 0);
|
||||
|
||||
expect(searchService.search).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
query: undefined,
|
||||
sort: jasmine.objectContaining({
|
||||
field: 'dc.title',
|
||||
direction: SortDirection.ASC,
|
||||
}),
|
||||
}),
|
||||
null,
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it('should not specify how to sort if a query is given', () => {
|
||||
component.sort = new SortOptions('dc.title', SortDirection.ASC);
|
||||
component.search('testQuery', 0);
|
||||
|
||||
expect(searchService.search).toHaveBeenCalledWith(
|
||||
jasmine.objectContaining({
|
||||
query: 'testQuery',
|
||||
sort: null,
|
||||
}),
|
||||
null,
|
||||
true
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when search returns an error', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(searchService, 'search').and.returnValue(createFailedRemoteDataObject$());
|
||||
|
@@ -31,6 +31,7 @@ import { getFirstCompletedRemoteData, getFirstSucceededRemoteDataPayload } from
|
||||
import { hasNoValue, hasValue, isEmpty, isNotEmpty } from '../../empty.util';
|
||||
import { buildPaginatedList, PaginatedList } from '../../../core/data/paginated-list.model';
|
||||
import { SearchResult } from '../../search/models/search-result.model';
|
||||
import { SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||
import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { NotificationsService } from '../../notifications/notifications.service';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
@@ -69,6 +70,11 @@ export class DSOSelectorComponent implements OnInit, OnDestroy {
|
||||
*/
|
||||
@Input() types: DSpaceObjectType[];
|
||||
|
||||
/**
|
||||
* The sorting options
|
||||
*/
|
||||
@Input() sort: SortOptions;
|
||||
|
||||
// list of allowed selectable dsoTypes
|
||||
typesString: string;
|
||||
|
||||
@@ -221,13 +227,16 @@ export class DSOSelectorComponent implements OnInit, OnDestroy {
|
||||
* @param useCache Whether or not to use the cache
|
||||
*/
|
||||
search(query: string, page: number, useCache: boolean = true): Observable<RemoteData<PaginatedList<SearchResult<DSpaceObject>>>> {
|
||||
// default sort is only used when there is not query
|
||||
let efectiveSort = query ? null : this.sort;
|
||||
return this.searchService.search(
|
||||
new PaginatedSearchOptions({
|
||||
query: query,
|
||||
dsoTypes: this.types,
|
||||
pagination: Object.assign({}, this.defaultPagination, {
|
||||
currentPage: page
|
||||
})
|
||||
}),
|
||||
sort: efectiveSort
|
||||
}),
|
||||
null,
|
||||
useCache,
|
||||
|
@@ -8,7 +8,8 @@ import {
|
||||
getCollectionCreateRoute,
|
||||
COLLECTION_PARENT_PARAMETER
|
||||
} from '../../../../collection-page/collection-page-routing-paths';
|
||||
|
||||
import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model';
|
||||
import { environment } from '../../../../../environments/environment';
|
||||
/**
|
||||
* Component to wrap a list of existing communities inside a modal
|
||||
* Used to choose a community from to create a new collection in
|
||||
@@ -23,6 +24,7 @@ export class CreateCollectionParentSelectorComponent extends DSOSelectorModalWra
|
||||
selectorTypes = [DSpaceObjectType.COMMUNITY];
|
||||
action = SelectorActionType.CREATE;
|
||||
header = 'dso-selector.create.collection.sub-level';
|
||||
defaultSort = new SortOptions(environment.comcolSelectionSort.sortField, environment.comcolSelectionSort.sortDirection as SortDirection);
|
||||
|
||||
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {
|
||||
super(activeModal, route);
|
||||
|
@@ -14,6 +14,6 @@
|
||||
</h3>
|
||||
|
||||
<h5 class="px-2">{{'dso-selector.create.community.sub-level' | translate}}</h5>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" [sort]="defaultSort" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -12,6 +12,8 @@ import {
|
||||
getCommunityCreateRoute,
|
||||
COMMUNITY_PARENT_PARAMETER
|
||||
} from '../../../../community-page/community-page-routing-paths';
|
||||
import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model';
|
||||
import { environment } from '../../../../../environments/environment';
|
||||
|
||||
/**
|
||||
* Component to wrap a button - for top communities -
|
||||
@@ -29,6 +31,7 @@ export class CreateCommunityParentSelectorComponent extends DSOSelectorModalWrap
|
||||
objectType = DSpaceObjectType.COMMUNITY;
|
||||
selectorTypes = [DSpaceObjectType.COMMUNITY];
|
||||
action = SelectorActionType.CREATE;
|
||||
defaultSort = new SortOptions(environment.comcolSelectionSort.sortField, environment.comcolSelectionSort.sortDirection as SortDirection);
|
||||
|
||||
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {
|
||||
super(activeModal, route);
|
||||
|
@@ -4,6 +4,8 @@ import { DSpaceObjectType } from '../../../../core/shared/dspace-object-type.mod
|
||||
import { DSpaceObject } from '../../../../core/shared/dspace-object.model';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { DSOSelectorModalWrapperComponent, SelectorActionType } from '../dso-selector-modal-wrapper.component';
|
||||
import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model';
|
||||
import { environment } from '../../../../../environments/environment';
|
||||
|
||||
/**
|
||||
* Component to wrap a list of existing collections inside a modal
|
||||
@@ -21,6 +23,7 @@ export class CreateItemParentSelectorComponent extends DSOSelectorModalWrapperCo
|
||||
selectorTypes = [DSpaceObjectType.COLLECTION];
|
||||
action = SelectorActionType.CREATE;
|
||||
header = 'dso-selector.create.item.sub-level';
|
||||
defaultSort = new SortOptions(environment.comcolSelectionSort.sortField, environment.comcolSelectionSort.sortDirection as SortDirection);
|
||||
|
||||
/**
|
||||
* If present this value is used to filter collection list by entity type
|
||||
|
@@ -6,6 +6,6 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h5 *ngIf="header" class="px-2">{{header | translate}}</h5>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" [sort]="defaultSort" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -5,6 +5,7 @@ import { RemoteData } from '../../../core/data/remote-data';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model';
|
||||
import { hasValue, isNotEmpty } from '../../empty.util';
|
||||
import { SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||
|
||||
export enum SelectorActionType {
|
||||
CREATE = 'create',
|
||||
@@ -49,6 +50,11 @@ export abstract class DSOSelectorModalWrapperComponent implements OnInit {
|
||||
*/
|
||||
action: SelectorActionType;
|
||||
|
||||
/**
|
||||
* Default DSO ordering
|
||||
*/
|
||||
defaultSort: SortOptions;
|
||||
|
||||
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute) {
|
||||
}
|
||||
|
||||
|
@@ -8,6 +8,8 @@ import {
|
||||
SelectorActionType
|
||||
} from '../dso-selector-modal-wrapper.component';
|
||||
import { getCollectionEditRoute } from '../../../../collection-page/collection-page-routing-paths';
|
||||
import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model';
|
||||
import { environment } from '../../../../../environments/environment';
|
||||
|
||||
/**
|
||||
* Component to wrap a list of existing collections inside a modal
|
||||
@@ -22,6 +24,7 @@ export class EditCollectionSelectorComponent extends DSOSelectorModalWrapperComp
|
||||
objectType = DSpaceObjectType.COLLECTION;
|
||||
selectorTypes = [DSpaceObjectType.COLLECTION];
|
||||
action = SelectorActionType.EDIT;
|
||||
defaultSort = new SortOptions(environment.comcolSelectionSort.sortField, environment.comcolSelectionSort.sortDirection as SortDirection);
|
||||
|
||||
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {
|
||||
super(activeModal, route);
|
||||
|
@@ -8,6 +8,8 @@ import {
|
||||
SelectorActionType
|
||||
} from '../dso-selector-modal-wrapper.component';
|
||||
import { getCommunityEditRoute } from '../../../../community-page/community-page-routing-paths';
|
||||
import { SortDirection, SortOptions } from '../../../../core/cache/models/sort-options.model';
|
||||
import { environment } from '../../../../../environments/environment';
|
||||
|
||||
/**
|
||||
* Component to wrap a list of existing communities inside a modal
|
||||
@@ -23,6 +25,7 @@ export class EditCommunitySelectorComponent extends DSOSelectorModalWrapperCompo
|
||||
objectType = DSpaceObjectType.COMMUNITY;
|
||||
selectorTypes = [DSpaceObjectType.COMMUNITY];
|
||||
action = SelectorActionType.EDIT;
|
||||
defaultSort = new SortOptions(environment.comcolSelectionSort.sortField, environment.comcolSelectionSort.sortDirection as SortDirection);
|
||||
|
||||
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {
|
||||
super(activeModal, route);
|
||||
|
@@ -0,0 +1,11 @@
|
||||
<div>
|
||||
<div class="modal-header">{{'dso-selector.'+ action + '.' + objectType.toString().toLowerCase() + '.head' | translate}}
|
||||
<button type="button" class="close" (click)="close()" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h5 *ngIf="header" class="px-2">{{header | translate}}</h5>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
</div>
|
||||
</div>
|
@@ -14,7 +14,7 @@ import { Item } from '../../../../core/shared/item.model';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-edit-item-selector',
|
||||
templateUrl: '../dso-selector-modal-wrapper.component.html',
|
||||
templateUrl: 'edit-item-selector.component.html',
|
||||
})
|
||||
export class EditItemSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit {
|
||||
objectType = DSpaceObjectType.ITEM;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<a [routerLink]="(bitstreamPath$| async)?.routerLink" class="dont-break-out" [queryParams]="(bitstreamPath$| async)?.queryParams" [target]="isBlank ? '_blank': '_self'" [ngClass]="cssClasses">
|
||||
<span *ngIf="!(canDownload$ |async)"><i class="fas fa-lock"></i></span>
|
||||
<span *ngIf="!(canDownload$ |async)" class="pr-1"><i class="fas fa-lock"></i></span>
|
||||
<ng-container *ngTemplateOutlet="content"></ng-container>
|
||||
</a>
|
||||
|
||||
|
@@ -12,12 +12,11 @@
|
||||
[formGroupName]="idx"
|
||||
[ngClass]="[getClass('element', 'group'), getClass('grid', 'group')]"
|
||||
cdkDrag
|
||||
cdkDragHandle
|
||||
[cdkDragDisabled]="dragDisabled"
|
||||
[cdkDragPreviewClass]="'ds-submission-reorder-dragging'"
|
||||
[class.grey-background]="model.isInlineGroupArray">
|
||||
<!-- Item content -->
|
||||
<div class="drag-handle" [class.drag-disable]="dragDisabled" tabindex="0">
|
||||
<div class="drag-handle" [class.drag-disable]="dragDisabled" tabindex="0" cdkDragHandle>
|
||||
<i class="drag-icon fas fa-grip-vertical fa-fw" [class.drag-disable]="dragDisabled" ></i>
|
||||
</div>
|
||||
<ng-container *ngTemplateOutlet="startTemplate?.templateRef; context: groupModel"></ng-container>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<div [className]="'float-left w-100 ' + wrapperClass">
|
||||
<ul class="nav nav-pills d-flex flex-column flex-sm-row" [sortablejs]="chips.getChips()" [sortablejsOptions]="options">
|
||||
<div role="list" class="nav nav-pills d-flex flex-column flex-sm-row" [sortablejs]="chips.getChips()" [sortablejsOptions]="options">
|
||||
<ng-container *ngFor="let c of chips.getChips(); let i = index">
|
||||
<ng-template #tipContent>
|
||||
<p class="text-left p-0 m-0" *ngFor="let tip of tipText">
|
||||
@@ -7,7 +7,7 @@
|
||||
</p>
|
||||
</ng-template>
|
||||
|
||||
<li class="nav-item mr-2 mb-1"
|
||||
<div role="listitem" class="nav-item mr-2 mb-1"
|
||||
#t="ngbTooltip"
|
||||
triggers="manual"
|
||||
[ngbTooltip]="tipContent"
|
||||
@@ -40,10 +40,10 @@
|
||||
<p class="chip-label text-truncate d-table-cell">{{c.display}}</p><i class="fas fa-times ml-2" (click)="removeChips($event, i)" [title]="'chips.remove' | translate"></i>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</div>
|
||||
</ng-container>
|
||||
<div [class.chips-sort-ignore]="(isDragging | async)" class="flex-grow-1">
|
||||
<ng-content ></ng-content>
|
||||
</div>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -122,7 +122,7 @@ describe('ChipsComponent test suite', () => {
|
||||
}));
|
||||
|
||||
it('should save chips item index when drag and drop start', fakeAsync(() => {
|
||||
const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
|
||||
const de = chipsFixture.debugElement.query(By.css('div.nav-item'));
|
||||
|
||||
de.triggerEventHandler('dragstart', null);
|
||||
|
||||
@@ -131,7 +131,7 @@ describe('ChipsComponent test suite', () => {
|
||||
|
||||
it('should update chips item order when drag and drop end', fakeAsync(() => {
|
||||
spyOn(chipsComp.chips, 'updateOrder');
|
||||
const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
|
||||
const de = chipsFixture.debugElement.query(By.css('div.nav-item'));
|
||||
|
||||
de.triggerEventHandler('dragend', null);
|
||||
|
||||
@@ -158,7 +158,7 @@ describe('ChipsComponent test suite', () => {
|
||||
});
|
||||
|
||||
it('should show icon for every field that has a configured icon', () => {
|
||||
const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
|
||||
const de = chipsFixture.debugElement.query(By.css('div.nav-item'));
|
||||
const icons = de.queryAll(By.css('i.fas'));
|
||||
|
||||
expect(icons.length).toBe(4);
|
||||
@@ -166,7 +166,7 @@ describe('ChipsComponent test suite', () => {
|
||||
});
|
||||
|
||||
it('should show tooltip on mouse over an icon', () => {
|
||||
const de = chipsFixture.debugElement.query(By.css('li.nav-item'));
|
||||
const de = chipsFixture.debugElement.query(By.css('div.nav-item'));
|
||||
const icons = de.queryAll(By.css('i.fas'));
|
||||
|
||||
icons[0].triggerEventHandler('mouseover', null);
|
||||
|
@@ -109,7 +109,7 @@ describe('LangSwitchComponent', () => {
|
||||
}));
|
||||
|
||||
it('should define the main A HREF in the UI', (() => {
|
||||
expect(langSwitchElement.querySelector('a')).toBeDefined();
|
||||
expect(langSwitchElement.querySelector('a')).not.toBeNull();
|
||||
}));
|
||||
|
||||
describe('when selecting a language', () => {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<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">
|
||||
<div *ngIf="!(loading | async) && !(isAuthenticated | async)" class="px-4 py-3 mx-auto login-container">
|
||||
<ng-container *ngFor="let authMethod of (authMethods); let i = index">
|
||||
<div *ngIf="i === 1" class="text-center mt-2">
|
||||
<span class="align-middle">{{"login.form.or-divider" | translate}}</span>
|
||||
|
@@ -1,3 +1,8 @@
|
||||
.login-container {
|
||||
max-width: 450px;
|
||||
}
|
||||
|
||||
a {
|
||||
white-space: normal;
|
||||
padding: .25rem .75rem;
|
||||
}
|
||||
|
@@ -72,7 +72,7 @@ describe('ClaimedTaskActionsApproveComponent', () => {
|
||||
it('should display approve button', () => {
|
||||
const btn = fixture.debugElement.query(By.css('.btn-success'));
|
||||
|
||||
expect(btn).toBeDefined();
|
||||
expect(btn).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should display spin icon when approve is pending', () => {
|
||||
@@ -81,7 +81,7 @@ describe('ClaimedTaskActionsApproveComponent', () => {
|
||||
|
||||
const span = fixture.debugElement.query(By.css('.btn-success .fa-spin'));
|
||||
|
||||
expect(span).toBeDefined();
|
||||
expect(span).not.toBeNull();
|
||||
});
|
||||
|
||||
describe('submitTask', () => {
|
||||
|
@@ -66,7 +66,7 @@ describe('ClaimedTaskActionsEditMetadataComponent', () => {
|
||||
it('should display edit button', () => {
|
||||
const btn = fixture.debugElement.query(By.css('.btn-primary'));
|
||||
|
||||
expect(btn).toBeDefined();
|
||||
expect(btn).not.toBeNull();
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -89,7 +89,7 @@ describe('ClaimedTaskActionsRejectComponent', () => {
|
||||
it('should display reject button', () => {
|
||||
const btn = fixture.debugElement.query(By.css('.btn-danger'));
|
||||
|
||||
expect(btn).toBeDefined();
|
||||
expect(btn).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should display spin icon when reject is pending', () => {
|
||||
@@ -98,7 +98,7 @@ describe('ClaimedTaskActionsRejectComponent', () => {
|
||||
|
||||
const span = fixture.debugElement.query(By.css('.btn-danger .fa-spin'));
|
||||
|
||||
expect(span).toBeDefined();
|
||||
expect(span).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should call openRejectModal on reject button click', () => {
|
||||
|
@@ -72,7 +72,7 @@ describe('ClaimedTaskActionsReturnToPoolComponent', () => {
|
||||
it('should display return to pool button', () => {
|
||||
const btn = fixture.debugElement.query(By.css('.btn-secondary'));
|
||||
|
||||
expect(btn).toBeDefined();
|
||||
expect(btn).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should display spin icon when return to pool action is pending', () => {
|
||||
@@ -81,7 +81,7 @@ describe('ClaimedTaskActionsReturnToPoolComponent', () => {
|
||||
|
||||
const span = fixture.debugElement.query(By.css('.btn-secondary .fa-spin'));
|
||||
|
||||
expect(span).toBeDefined();
|
||||
expect(span).not.toBeNull();
|
||||
});
|
||||
|
||||
describe('actionExecution', () => {
|
||||
|
@@ -131,13 +131,13 @@ describe('PoolTaskActionsComponent', () => {
|
||||
it('should display claim task button', () => {
|
||||
const btn = fixture.debugElement.query(By.css('.btn-info'));
|
||||
|
||||
expect(btn).toBeDefined();
|
||||
expect(btn).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should display view button', () => {
|
||||
const btn = fixture.debugElement.query(By.css('button [data-test="view-btn"]'));
|
||||
const btn = fixture.debugElement.query(By.css('button[data-test="view-btn"]'));
|
||||
|
||||
expect(btn).toBeDefined();
|
||||
expect(btn).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should call claim task with href of getPoolTaskEndpointById', ((done) => {
|
||||
|
@@ -107,9 +107,9 @@ describe('WorkflowitemActionsComponent', () => {
|
||||
});
|
||||
|
||||
it('should display view button', () => {
|
||||
const btn = fixture.debugElement.query(By.css('button [data-test="view-btn"]'));
|
||||
const btn = fixture.debugElement.query(By.css('button[data-test="view-btn"]'));
|
||||
|
||||
expect(btn).toBeDefined();
|
||||
expect(btn).not.toBeNull();
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -2,18 +2,21 @@
|
||||
|
||||
<button class="btn btn-primary workflow-view mt-1 mb-3" data-test="view-btn"
|
||||
ngbTooltip="{{'submission.workspace.generic.view-help' | translate}}"
|
||||
[attr.aria-label]="'submission.workspace.generic.view-help' | translate"
|
||||
[routerLink]="[getWorkspaceItemViewRoute(object)]">
|
||||
<i class="fa fa-info-circle"></i> {{"submission.workspace.generic.view" | translate}}
|
||||
</button>
|
||||
|
||||
<a class="btn btn-primary mt-1 mb-3" id="{{'edit_' + object.id}}"
|
||||
ngbTooltip="{{'submission.workflow.generic.edit-help' | translate}}"
|
||||
[attr.aria-label]="'submission.workflow.generic.edit-help' | translate"
|
||||
[routerLink]="['/workspaceitems/' + object.id + '/edit']" role="button">
|
||||
<i class="fa fa-edit"></i> {{'submission.workflow.generic.edit' | translate}}
|
||||
</a>
|
||||
|
||||
<button type="button" id="{{'delete_' + object.id}}" class="btn btn-danger mt-1 mb-3"
|
||||
ngbTooltip="{{'submission.workflow.generic.delete-help' | translate}}"
|
||||
[attr.aria-label]="'submission.workflow.generic.delete-help' | translate"
|
||||
(click)="$event.preventDefault();confirmDiscard(content)">
|
||||
<span *ngIf="(processingDelete$ | async)"><i class='fas fa-circle-notch fa-spin'></i>
|
||||
{{'submission.workflow.tasks.generic.processing' | translate}}</span>
|
||||
|
@@ -123,19 +123,19 @@ describe('WorkspaceitemActionsComponent', () => {
|
||||
it('should display edit button', () => {
|
||||
const btn = fixture.debugElement.query(By.css('.btn-primary'));
|
||||
|
||||
expect(btn).toBeDefined();
|
||||
expect(btn).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should display delete button', () => {
|
||||
const btn = fixture.debugElement.query(By.css('.btn-danger'));
|
||||
|
||||
expect(btn).toBeDefined();
|
||||
expect(btn).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should display view button', () => {
|
||||
const btn = fixture.debugElement.query(By.css('button [data-test="view-btn"]'));
|
||||
const btn = fixture.debugElement.query(By.css('button[data-test="view-btn"]'));
|
||||
|
||||
expect(btn).toBeDefined();
|
||||
expect(btn).not.toBeNull();
|
||||
});
|
||||
|
||||
describe('on discard confirmation', () => {
|
||||
|
@@ -30,27 +30,34 @@ describe('ObjectCollectionComponent', () => {
|
||||
}).compileComponents(); // compile template and css
|
||||
}));
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ObjectCollectionComponent);
|
||||
objectCollectionComponent = fixture.componentInstance;
|
||||
}));
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should only show the grid component when the viewmode is set to grid', () => {
|
||||
objectCollectionComponent.currentMode$ = observableOf(ViewMode.GridElement);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.debugElement.query(By.css('ds-object-grid'))).toBeDefined();
|
||||
expect(fixture.debugElement.query(By.css('ds-object-list'))).toBeNull();
|
||||
expect(fixture.debugElement.query(By.css('ds-object-grid'))).not.toBeNull();
|
||||
expect(fixture.debugElement.query(By.css('ds-themed-object-list'))).toBeNull();
|
||||
});
|
||||
|
||||
it('should only show the list component when the viewmode is set to list', () => {
|
||||
objectCollectionComponent.currentMode$ = observableOf(ViewMode.ListElement);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.debugElement.query(By.css('ds-object-list'))).toBeDefined();
|
||||
expect(fixture.debugElement.query(By.css('ds-themed-object-list'))).not.toBeNull();
|
||||
expect(fixture.debugElement.query(By.css('ds-object-grid'))).toBeNull();
|
||||
});
|
||||
it('should set fallback placeholder font size during test', () => {
|
||||
objectCollectionComponent.currentMode$ = observableOf(ViewMode.ListElement);
|
||||
expect(fixture.debugElement.query(By.css('thumb-font-3'))).toBeDefined();
|
||||
|
||||
it('should set fallback placeholder font size during test', async () => {
|
||||
objectCollectionComponent.currentMode$ = observableOf(ViewMode.ListElement);
|
||||
fixture.detectChanges();
|
||||
|
||||
const comp = fixture.debugElement.query(By.css('ds-themed-object-list'));
|
||||
expect(comp).not.toBeNull();
|
||||
expect(comp.nativeElement.classList).not.toContain('hide-placeholder-text');
|
||||
});
|
||||
});
|
||||
|
@@ -48,7 +48,7 @@ describe('MyDSpaceItemStatusComponent', () => {
|
||||
|
||||
it('should display badge', () => {
|
||||
const badge = fixture.debugElement.query(By.css('span'));
|
||||
expect(badge).toBeDefined();
|
||||
expect(badge).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should init badge content and class', () => {
|
||||
|
@@ -63,7 +63,7 @@ describe('ItemSubmitterComponent', () => {
|
||||
it('should show a badge with submitter name', () => {
|
||||
const badge = fixture.debugElement.query(By.css('.badge'));
|
||||
|
||||
expect(badge).toBeDefined();
|
||||
expect(badge).not.toBeNull();
|
||||
expect(badge.nativeElement.innerHTML).toBe(EPersonMock.name);
|
||||
});
|
||||
});
|
||||
|
@@ -25,7 +25,8 @@
|
||||
<span class="text-muted">
|
||||
<ds-truncatable-part [id]="dso.id" [minLines]="1">
|
||||
<ng-container *ngIf="dso.firstMetadataValue('dc.publisher') || dso.firstMetadataValue('dc.date.issued')">
|
||||
(<span *ngIf="dso.firstMetadataValue('dc.publisher')" class="item-list-publisher" [innerHTML]="firstMetadataValue('dc.publisher') + ', '"></span>
|
||||
(<span *ngIf="dso.firstMetadataValue('dc.publisher')" class="item-list-publisher" [innerHTML]="firstMetadataValue('dc.publisher')"></span>
|
||||
<span *ngIf="dso.firstMetadataValue('dc.publisher') && dso.firstMetadataValue('dc.date.issued')">, </span>
|
||||
<span *ngIf="dso.firstMetadataValue('dc.date.issued')" class="item-list-date" [innerHTML]="firstMetadataValue('dc.date.issued')"></span>)
|
||||
</ng-container>
|
||||
<span *ngIf="dso.allMetadata(['dc.contributor.author', 'dc.creator', 'dc.contributor.*']).length > 0" class="item-list-authors">
|
||||
|
@@ -72,9 +72,9 @@ describe('PageSizeSelectorComponent', () => {
|
||||
});
|
||||
|
||||
it('it should show the size settings with the respective selectable options', (done) => {
|
||||
(comp as any).paginationOptions$.pipe(first()).subscribe((options) => {
|
||||
comp.paginationOptions$.pipe(first()).subscribe((options: PaginationComponentOptions) => {
|
||||
const pageSizeSetting = fixture.debugElement.query(By.css('div.page-size-settings'));
|
||||
expect(pageSizeSetting).toBeDefined();
|
||||
expect(pageSizeSetting).not.toBeNull();
|
||||
const childElements = pageSizeSetting.queryAll(By.css('option'));
|
||||
expect(childElements.length).toEqual(options.pageSizeOptions.length);
|
||||
done();
|
||||
@@ -83,10 +83,11 @@ describe('PageSizeSelectorComponent', () => {
|
||||
});
|
||||
|
||||
it('should have the proper rpp value selected by default', (done) => {
|
||||
(comp as any).paginationOptions$.pipe(take(1)).subscribe((options) => {
|
||||
comp.paginationOptions$.pipe(take(1)).subscribe(() => {
|
||||
const pageSizeSetting = fixture.debugElement.query(By.css('div.page-size-settings'));
|
||||
const childElementToBeSelected = pageSizeSetting.query(By.css('option[value="10"][selected="selected"]'));
|
||||
expect(childElementToBeSelected).toBeDefined();
|
||||
const childElementToBeSelected = pageSizeSetting.query(By.css('option[value="10"]'));
|
||||
expect(childElementToBeSelected).not.toBeNull();
|
||||
expect(childElementToBeSelected.nativeElement.selected).toBeTrue();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
@@ -14,6 +14,6 @@
|
||||
</h3>
|
||||
|
||||
<h5 class="px-2">{{'dso-selector.' + action + '.' + objectType.toString().toLowerCase() + '.input-header' | translate}}</h5>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" [sort]="defaultSort" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -4,6 +4,8 @@ import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model';
|
||||
import { DSOSelectorModalWrapperComponent, SelectorActionType } from '../../dso-selector/modal-wrappers/dso-selector-modal-wrapper.component';
|
||||
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
||||
import { SortDirection, SortOptions } from '../../../core/cache/models/sort-options.model';
|
||||
import { environment } from '../../../../environments/environment';
|
||||
|
||||
/**
|
||||
* Component to wrap a button - to select the entire repository -
|
||||
@@ -33,6 +35,11 @@ export class ScopeSelectorModalComponent extends DSOSelectorModalWrapperComponen
|
||||
*/
|
||||
scopeChange = new EventEmitter<DSpaceObject>();
|
||||
|
||||
/**
|
||||
* Default DSO ordering
|
||||
*/
|
||||
defaultSort = new SortOptions(environment.comcolSelectionSort.sortField, environment.comcolSelectionSort.sortDirection as SortDirection);
|
||||
|
||||
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute) {
|
||||
super(activeModal, route);
|
||||
}
|
||||
|
@@ -7,6 +7,7 @@ import { SearchService } from '../../../../core/shared/search/search.service';
|
||||
import { currentPath } from '../../../utils/route.utils';
|
||||
import { PaginationService } from '../../../../core/pagination/pagination.service';
|
||||
import { SearchConfigurationService } from '../../../../core/shared/search/search-configuration.service';
|
||||
import { stripOperatorFromFilterValue } from '../../search.utils';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-label',
|
||||
@@ -83,7 +84,8 @@ export class SearchLabelComponent implements OnInit {
|
||||
normalizeFilterValue(value: string) {
|
||||
// const pattern = /,[^,]*$/g;
|
||||
const pattern = /,authority*$/g;
|
||||
return value.replace(pattern, '');
|
||||
value = value.replace(pattern, '');
|
||||
return stripOperatorFromFilterValue(value);
|
||||
}
|
||||
|
||||
private getFilterName(): string {
|
||||
|
@@ -4,7 +4,6 @@ import { Observable } from 'rxjs';
|
||||
import { Params, Router } from '@angular/router';
|
||||
import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { stripOperatorFromFilterValue } from '../search.utils';
|
||||
|
||||
@Component({
|
||||
selector: 'ds-search-labels',
|
||||
@@ -37,7 +36,7 @@ export class SearchLabelsComponent {
|
||||
const labels = {};
|
||||
Object.keys(params)
|
||||
.forEach((key) => {
|
||||
labels[key] = [...params[key].map((value) => stripOperatorFromFilterValue(value))];
|
||||
labels[key] = [...params[key].map((value) => value)];
|
||||
});
|
||||
return labels;
|
||||
})
|
||||
|
@@ -107,6 +107,7 @@ describe('SearchSettingsComponent', () => {
|
||||
new SortOptions('dc.title', SortDirection.ASC),
|
||||
new SortOptions('dc.title', SortDirection.DESC)
|
||||
];
|
||||
comp.currentSortOption = new SortOptions('score', SortDirection.DESC);
|
||||
|
||||
// SearchPageComponent test instance
|
||||
fixture.detectChanges();
|
||||
@@ -133,7 +134,8 @@ describe('SearchSettingsComponent', () => {
|
||||
it('should have the proper order value selected by default', () => {
|
||||
fixture.detectChanges();
|
||||
const orderSetting = fixture.debugElement.query(By.css('div.result-order-settings'));
|
||||
const childElementToBeSelected = orderSetting.query(By.css('option[value="score,DESC"][selected="selected"]'));
|
||||
expect(childElementToBeSelected).toBeDefined();
|
||||
const childElementToBeSelected = orderSetting.query(By.css('option[value="score,DESC"]'));
|
||||
expect(childElementToBeSelected).not.toBeNull();
|
||||
expect(childElementToBeSelected.nativeElement.selected).toBeTrue();
|
||||
});
|
||||
});
|
||||
|
@@ -78,7 +78,7 @@ describe('SearchSwitchConfigurationComponent', () => {
|
||||
|
||||
it('should display select field properly', () => {
|
||||
const selectField = fixture.debugElement.query(By.css('.form-control'));
|
||||
expect(selectField).toBeDefined();
|
||||
expect(selectField).not.toBeNull();
|
||||
|
||||
const childElements = selectField.children;
|
||||
expect(childElements.length).toEqual(comp.configurationList.length);
|
||||
|
@@ -188,7 +188,7 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
|
||||
* Reset search form control on dropdown menu close
|
||||
*/
|
||||
onClose() {
|
||||
this.collectionDropdown.reset();
|
||||
this.collectionDropdown?.reset();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -199,7 +199,7 @@ export class SubmissionFormCollectionComponent implements OnChanges, OnInit {
|
||||
*/
|
||||
toggled(isOpen: boolean) {
|
||||
if (!isOpen) {
|
||||
this.collectionDropdown.reset();
|
||||
this.collectionDropdown?.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -96,6 +96,7 @@ describe('SubmissionFormSectionAddComponent Component', () => {
|
||||
|
||||
afterEach(() => {
|
||||
testFixture.destroy();
|
||||
testFixture.debugElement.nativeElement.remove();
|
||||
});
|
||||
|
||||
it('should create SubmissionFormSectionAddComponent', inject([SubmissionFormSectionAddComponent], (app: SubmissionFormSectionAddComponent) => {
|
||||
@@ -163,7 +164,7 @@ describe('SubmissionFormSectionAddComponent Component', () => {
|
||||
|
||||
it('should have dropdown menu closed', () => {
|
||||
|
||||
expect(dropdowBtn).not.toBeUndefined();
|
||||
expect(dropdowBtn).not.toBeNull();
|
||||
expect(dropdownMenu.nativeElement.classList).not.toContain('show');
|
||||
|
||||
});
|
||||
|
@@ -137,7 +137,7 @@ describe('SubmissionSectionContainerComponent test suite', () => {
|
||||
|
||||
const section = fixture.debugElement.query(By.css('[id^=\'sectionContent_\']'));
|
||||
expect(comp.getSectionContent).toHaveBeenCalled();
|
||||
expect(section).toBeDefined();
|
||||
expect(section).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should call removeSection properly', () => {
|
||||
@@ -165,7 +165,7 @@ describe('SubmissionSectionContainerComponent test suite', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
sectionErrorsDiv = fixture.debugElement.query(By.css('[id^=\'sectionGenericError_\']'));
|
||||
expect(sectionErrorsDiv).toBeDefined();
|
||||
expect(sectionErrorsDiv).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should display warning icon', () => {
|
||||
@@ -180,7 +180,7 @@ describe('SubmissionSectionContainerComponent test suite', () => {
|
||||
const iconWarn = fixture.debugElement.query(By.css('i.text-warning'));
|
||||
const iconErr = fixture.debugElement.query(By.css('i.text-danger'));
|
||||
const iconSuccess = fixture.debugElement.query(By.css('i.text-success'));
|
||||
expect(iconWarn).toBeDefined();
|
||||
expect(iconWarn).not.toBeNull();
|
||||
expect(iconErr).toBeNull();
|
||||
expect(iconSuccess).toBeNull();
|
||||
});
|
||||
@@ -198,7 +198,7 @@ describe('SubmissionSectionContainerComponent test suite', () => {
|
||||
const iconErr = fixture.debugElement.query(By.css('i.text-danger'));
|
||||
const iconSuccess = fixture.debugElement.query(By.css('i.text-success'));
|
||||
expect(iconWarn).toBeNull();
|
||||
expect(iconErr).toBeDefined();
|
||||
expect(iconErr).not.toBeNull();
|
||||
expect(iconSuccess).toBeNull();
|
||||
});
|
||||
|
||||
@@ -216,7 +216,7 @@ describe('SubmissionSectionContainerComponent test suite', () => {
|
||||
const iconSuccess = fixture.debugElement.query(By.css('i.text-success'));
|
||||
expect(iconWarn).toBeNull();
|
||||
expect(iconErr).toBeNull();
|
||||
expect(iconSuccess).toBeDefined();
|
||||
expect(iconSuccess).not.toBeNull();
|
||||
});
|
||||
|
||||
});
|
||||
@@ -224,7 +224,8 @@ describe('SubmissionSectionContainerComponent test suite', () => {
|
||||
|
||||
// declare a test component
|
||||
@Component({
|
||||
selector: 'ds-test-cmp',
|
||||
// eslint-disable-next-line @angular-eslint/component-selector
|
||||
selector: '',
|
||||
template: ``
|
||||
})
|
||||
class TestComponent {
|
||||
|
@@ -4694,7 +4694,7 @@
|
||||
|
||||
"submission.workflow.generic.delete": "Delete",
|
||||
|
||||
"submission.workflow.generic.delete-help": "If you would to discard this item, select \"Delete\". You will then be asked to confirm it.",
|
||||
"submission.workflow.generic.delete-help": "Select this option to discard this item. You will then be asked to confirm it.",
|
||||
|
||||
"submission.workflow.generic.edit": "Edit",
|
||||
|
||||
|
@@ -21,6 +21,7 @@ import { CommunityListConfig } from './community-list-config.interface';
|
||||
import { HomeConfig } from './homepage-config.interface';
|
||||
import { MarkdownConfig } from './markdown-config.interface';
|
||||
import { FilterVocabularyConfig } from './filter-vocabulary-config';
|
||||
import { DiscoverySortConfig } from './discovery-sort.config';
|
||||
|
||||
interface AppConfig extends Config {
|
||||
ui: UIServerConfig;
|
||||
@@ -46,6 +47,7 @@ interface AppConfig extends Config {
|
||||
info: InfoConfig;
|
||||
markdown: MarkdownConfig;
|
||||
vocabularies: FilterVocabularyConfig[];
|
||||
comcolSelectionSort: DiscoverySortConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -21,6 +21,7 @@ import { CommunityListConfig } from './community-list-config.interface';
|
||||
import { HomeConfig } from './homepage-config.interface';
|
||||
import { MarkdownConfig } from './markdown-config.interface';
|
||||
import { FilterVocabularyConfig } from './filter-vocabulary-config';
|
||||
import { DiscoverySortConfig } from './discovery-sort.config';
|
||||
|
||||
export class DefaultAppConfig implements AppConfig {
|
||||
production = false;
|
||||
@@ -421,4 +422,10 @@ export class DefaultAppConfig implements AppConfig {
|
||||
enabled: false
|
||||
}
|
||||
];
|
||||
|
||||
// Configuration that determines the metadata sorting of community and collection edition and creation when there are not a search query.
|
||||
comcolSelectionSort: DiscoverySortConfig = {
|
||||
sortField:'dc.title',
|
||||
sortDirection:'ASC',
|
||||
};
|
||||
}
|
||||
|
14
src/config/discovery-sort.config.ts
Normal file
14
src/config/discovery-sort.config.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { Config } from './config.interface';
|
||||
|
||||
/**
|
||||
* Config that determines a metadata sorting config.
|
||||
* It's created mainly to sort by metadata community and collection edition and creation
|
||||
*/
|
||||
export class DiscoverySortConfig implements Config {
|
||||
|
||||
public sortField: string;
|
||||
/**
|
||||
* ASC / DESC values expected
|
||||
*/
|
||||
public sortDirection: string;
|
||||
}
|
@@ -297,6 +297,10 @@ export const environment: BuildConfig = {
|
||||
enabled: false,
|
||||
mathjax: false,
|
||||
},
|
||||
comcolSelectionSort: {
|
||||
sortField:'dc.title',
|
||||
sortDirection:'ASC',
|
||||
},
|
||||
|
||||
vocabularies: [
|
||||
{
|
||||
|
@@ -246,3 +246,8 @@ ul.dso-edit-menu-dropdown > li .nav-item.nav-link {
|
||||
padding: 0;
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.table th,
|
||||
.table td {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
@@ -6,6 +6,6 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h5 *ngIf="header" class="px-2">{{header | translate}}</h5>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" [sort]="defaultSort" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -14,6 +14,6 @@
|
||||
</h3>
|
||||
|
||||
<h5 class="px-2">{{'dso-selector.create.community.sub-level' | translate}}</h5>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" [sort]="defaultSort" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -6,6 +6,6 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h5 *ngIf="header" class="px-2">{{header | translate}}</h5>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" [sort]="defaultSort" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -6,6 +6,6 @@
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<h5 *ngIf="header" class="px-2">{{header | translate}}</h5>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" [sort]="defaultSort" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
</div>
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user