mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-18 23:43:01 +00:00
[CST-4591] Add dropdown for selecting entity type when creating a new submission or importing from external source
This commit is contained in:
@@ -0,0 +1,24 @@
|
|||||||
|
<div class="add" *ngIf="!(moreThanOne$ | async)">
|
||||||
|
<button class="btn btn-lg btn-outline-primary mt-1 ml-2" [disabled]="!(initialized$|async)"
|
||||||
|
(click)="openPage(singleEntity)" role="button"
|
||||||
|
title="{{'mydspace.new-submission-external' | translate}}">
|
||||||
|
<i class="fa fa-file-import" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="add w-100" display="dynamic" placement="bottom-right"
|
||||||
|
ngbDropdown
|
||||||
|
*ngIf="(moreThanOne$ | async)">
|
||||||
|
<button class="btn btn-lg btn-outline-primary mt-1 ml-2" id="dropdownSubmission" ngbDropdownToggle
|
||||||
|
type="button" [disabled]="!(initialized$|async)"
|
||||||
|
attr.aria-label="{{'mydspace.new-submission-external' | translate}}"
|
||||||
|
title="{{'mydspace.new-submission-external' | translate}}">
|
||||||
|
<i class="fa fa-file-import" aria-hidden="true"></i>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<div ngbDropdownMenu
|
||||||
|
class="dropdown-menu"
|
||||||
|
id="entityControlsDropdownMenu"
|
||||||
|
aria-labelledby="dropdownSubmission">
|
||||||
|
<ds-entity-dropdown [isSubmission]="false" (selectionChange)="openPage($event)"></ds-entity-dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -0,0 +1,16 @@
|
|||||||
|
.parent {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload {
|
||||||
|
flex: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add {
|
||||||
|
flex: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
#entityControlsDropdownMenu {
|
||||||
|
min-width: 18rem;
|
||||||
|
box-shadow: $btn-focus-box-shadow;
|
||||||
|
}
|
@@ -0,0 +1,189 @@
|
|||||||
|
import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { createPaginatedList, createTestComponent } from '../../../shared/testing/utils.test';
|
||||||
|
import { MyDSpaceNewExternalDropdownComponent } from './my-dspace-new-external-dropdown.component';
|
||||||
|
import { EntityTypeService } from '../../../core/data/entity-type.service';
|
||||||
|
import { ItemType } from '../../../core/shared/item-relationships/item-type.model';
|
||||||
|
import { ResourceType } from '../../../core/shared/resource-type';
|
||||||
|
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||||
|
import { PageInfo } from '../../../core/shared/page-info.model';
|
||||||
|
import { RouterStub } from '../../../shared/testing/router.stub';
|
||||||
|
|
||||||
|
export function getMockEntityTypeService(): EntityTypeService {
|
||||||
|
const pageInfo = { elementsPerPage: 20, totalElements: 4, totalPages: 1, currentPage: 0 } as PageInfo;
|
||||||
|
const type1: ItemType = {
|
||||||
|
id: '1',
|
||||||
|
label: 'Publication',
|
||||||
|
uuid: '1',
|
||||||
|
type: new ResourceType('entitytype'),
|
||||||
|
_links: undefined
|
||||||
|
};
|
||||||
|
const type2: ItemType = {
|
||||||
|
id: '2',
|
||||||
|
label: 'Journal',
|
||||||
|
uuid: '2',
|
||||||
|
type: new ResourceType('entitytype'),
|
||||||
|
_links: undefined
|
||||||
|
};
|
||||||
|
const type3: ItemType = {
|
||||||
|
id: '2',
|
||||||
|
label: 'DataPackage',
|
||||||
|
uuid: '2',
|
||||||
|
type: new ResourceType('entitytype'),
|
||||||
|
_links: undefined
|
||||||
|
};
|
||||||
|
const rd$ = createSuccessfulRemoteDataObject$(createPaginatedList([type1, type2, type3]));
|
||||||
|
return jasmine.createSpyObj('entityTypeService', {
|
||||||
|
getAllAuthorizedRelationshipTypeImport: rd$,
|
||||||
|
hasMoreThanOneAuthorizedImport: observableOf(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMockEmptyEntityTypeService(): EntityTypeService {
|
||||||
|
const pageInfo = { elementsPerPage: 20, totalElements: 1, totalPages: 1, currentPage: 0 } as PageInfo;
|
||||||
|
const type1: ItemType = {
|
||||||
|
id: '1',
|
||||||
|
label: 'Publication',
|
||||||
|
uuid: '1',
|
||||||
|
type: new ResourceType('entitytype'),
|
||||||
|
_links: undefined
|
||||||
|
};
|
||||||
|
const rd$ = createSuccessfulRemoteDataObject$(createPaginatedList([type1]));
|
||||||
|
return jasmine.createSpyObj('entityTypeService', {
|
||||||
|
getAllAuthorizedRelationshipTypeImport: rd$,
|
||||||
|
hasMoreThanOneAuthorizedImport: observableOf(false)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('MyDSpaceNewExternalDropdownComponent test', () => {
|
||||||
|
let testComp: TestComponent;
|
||||||
|
let testFixture: ComponentFixture<TestComponent>;
|
||||||
|
let submissionComponent: MyDSpaceNewExternalDropdownComponent;
|
||||||
|
let submissionComponentFixture: ComponentFixture<MyDSpaceNewExternalDropdownComponent>;
|
||||||
|
|
||||||
|
const entityType1: ItemType = {
|
||||||
|
id: '1',
|
||||||
|
label: 'Publication',
|
||||||
|
uuid: '1',
|
||||||
|
type: new ResourceType('entitytype'),
|
||||||
|
_links: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('With only one Entity', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
MyDSpaceNewExternalDropdownComponent,
|
||||||
|
TestComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{ provide: EntityTypeService, useValue: getMockEmptyEntityTypeService() },
|
||||||
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
|
MyDSpaceNewExternalDropdownComponent
|
||||||
|
],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
const html = `<ds-my-dspace-new-submission (uploadEnd)="reload($event)"></ds-my-dspace-new-submission>`;
|
||||||
|
|
||||||
|
testFixture = createTestComponent(html, TestComponent) as ComponentFixture<TestComponent>;
|
||||||
|
testComp = testFixture.componentInstance;
|
||||||
|
|
||||||
|
submissionComponentFixture = TestBed.createComponent(MyDSpaceNewExternalDropdownComponent);
|
||||||
|
submissionComponent = submissionComponentFixture.componentInstance;
|
||||||
|
submissionComponentFixture.detectChanges();
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
testFixture.destroy();
|
||||||
|
submissionComponentFixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create MyDSpaceNewExternalDropdownComponent', inject([MyDSpaceNewExternalDropdownComponent], (app: MyDSpaceNewExternalDropdownComponent) => {
|
||||||
|
expect(app).toBeDefined();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should be a single button', inject([MyDSpaceNewExternalDropdownComponent], (app: MyDSpaceNewExternalDropdownComponent) => {
|
||||||
|
submissionComponentFixture.detectChanges();
|
||||||
|
const addDivElement: DebugElement = submissionComponentFixture.debugElement.query(By.css('.add'));
|
||||||
|
const addDiv = addDivElement.nativeElement;
|
||||||
|
expect(addDiv.innerHTML).toBeDefined();
|
||||||
|
const buttonElement: DebugElement = addDivElement.query(By.css('.btn'));
|
||||||
|
const button = buttonElement.nativeElement;
|
||||||
|
expect(button.innerHTML).toBeDefined();
|
||||||
|
const dropdownElement: DebugElement = submissionComponentFixture.debugElement.query(By.css('.dropdown-menu'));
|
||||||
|
expect(dropdownElement).toBeNull();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('With more than one Entity', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
MyDSpaceNewExternalDropdownComponent,
|
||||||
|
TestComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{ provide: EntityTypeService, useValue: getMockEntityTypeService() },
|
||||||
|
{ provide: Router, useValue: new RouterStub() },
|
||||||
|
MyDSpaceNewExternalDropdownComponent
|
||||||
|
],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
const html = `<ds-my-dspace-new-submission (uploadEnd)="reload($event)"></ds-my-dspace-new-submission>`;
|
||||||
|
|
||||||
|
testFixture = createTestComponent(html, TestComponent) as ComponentFixture<TestComponent>;
|
||||||
|
testComp = testFixture.componentInstance;
|
||||||
|
|
||||||
|
submissionComponentFixture = TestBed.createComponent(MyDSpaceNewExternalDropdownComponent);
|
||||||
|
submissionComponent = submissionComponentFixture.componentInstance;
|
||||||
|
submissionComponentFixture.detectChanges();
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
testFixture.destroy();
|
||||||
|
submissionComponentFixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create MyDSpaceNewExternalDropdownComponent', inject([MyDSpaceNewExternalDropdownComponent], (app: MyDSpaceNewExternalDropdownComponent) => {
|
||||||
|
expect(app).toBeDefined();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should be a dropdown button', inject([MyDSpaceNewExternalDropdownComponent], (app: MyDSpaceNewExternalDropdownComponent) => {
|
||||||
|
const dropdownElement: DebugElement = submissionComponentFixture.debugElement.query(By.css('.dropdown-menu'));
|
||||||
|
const dropdown = dropdownElement.nativeElement;
|
||||||
|
expect(dropdown.innerHTML).toBeDefined();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should invoke modalService.open', () => {
|
||||||
|
submissionComponent.openPage(entityType1);
|
||||||
|
|
||||||
|
expect((submissionComponent as any).router.navigate).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// declare a test component
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-test-cmp',
|
||||||
|
template: ``
|
||||||
|
})
|
||||||
|
class TestComponent {
|
||||||
|
reload = (event) => {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,106 @@
|
|||||||
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
import { Observable, of as observableOf, Subscription } from 'rxjs';
|
||||||
|
import { map, mergeMap, take } from 'rxjs/operators';
|
||||||
|
|
||||||
|
import { EntityTypeService } from '../../../core/data/entity-type.service';
|
||||||
|
import { ItemType } from '../../../core/shared/item-relationships/item-type.model';
|
||||||
|
import { FindListOptions } from '../../../core/data/request.models';
|
||||||
|
import { hasValue } from '../../../shared/empty.util';
|
||||||
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
|
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component represents the 'Import metadata from external source' dropdown menu
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-my-dspace-new-external-dropdown',
|
||||||
|
styleUrls: ['./my-dspace-new-external-dropdown.component.scss'],
|
||||||
|
templateUrl: './my-dspace-new-external-dropdown.component.html'
|
||||||
|
})
|
||||||
|
export class MyDSpaceNewExternalDropdownComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to verify if there are one or more entities available
|
||||||
|
*/
|
||||||
|
public moreThanOne$: Observable<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entity observble (only if there is only one entity available)
|
||||||
|
*/
|
||||||
|
public singleEntity$: Observable<ItemType>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entity object (only if there is only one entity available)
|
||||||
|
*/
|
||||||
|
public singleEntity: ItemType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TRUE if the page is initialized
|
||||||
|
*/
|
||||||
|
public initialized$: Observable<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array to track all subscriptions and unsubscribe them onDestroy
|
||||||
|
* @type {Array}
|
||||||
|
*/
|
||||||
|
public subs: Subscription[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize instance variables
|
||||||
|
*
|
||||||
|
* @param {EntityTypeService} entityTypeService
|
||||||
|
* @param {Router} router
|
||||||
|
*/
|
||||||
|
constructor(private entityTypeService: EntityTypeService,
|
||||||
|
private router: Router) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize entity type list
|
||||||
|
*/
|
||||||
|
ngOnInit() {
|
||||||
|
this.initialized$ = observableOf(false);
|
||||||
|
this.moreThanOne$ = this.entityTypeService.hasMoreThanOneAuthorizedImport();
|
||||||
|
this.singleEntity$ = this.moreThanOne$.pipe(
|
||||||
|
mergeMap((response: boolean) => {
|
||||||
|
if (!response) {
|
||||||
|
const findListOptions: FindListOptions = {
|
||||||
|
elementsPerPage: 1,
|
||||||
|
currentPage: 1
|
||||||
|
};
|
||||||
|
return this.entityTypeService.getAllAuthorizedRelationshipTypeImport(findListOptions).pipe(
|
||||||
|
map((entities: RemoteData<PaginatedList<ItemType>>) => {
|
||||||
|
this.initialized$ = observableOf(true);
|
||||||
|
return entities.payload.page[0];
|
||||||
|
}),
|
||||||
|
take(1)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.initialized$ = observableOf(true);
|
||||||
|
return observableOf(null);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
take(1)
|
||||||
|
);
|
||||||
|
this.subs.push(
|
||||||
|
this.singleEntity$.subscribe((result) => this.singleEntity = result )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called on clicking the button 'Import metadata from external source'. It opens the page of the external import.
|
||||||
|
*/
|
||||||
|
openPage(entity: ItemType) {
|
||||||
|
this.router.navigate(['/import-external'], { queryParams: { entity: entity.label } });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsubscribe from the subscription
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.subs
|
||||||
|
.filter((subscription) => hasValue(subscription))
|
||||||
|
.forEach((subscription) => subscription.unsubscribe());
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,20 @@
|
|||||||
|
<div class="add" *ngIf="!(moreThanOne$ | async)">
|
||||||
|
<button class="btn btn-lg btn-primary mt-1 ml-2" [disabled]="!(initialized$|async)" (click)="openDialog(singleEntity)" role="button">
|
||||||
|
<i class="fa fa-plus-circle" aria-hidden="true"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="add w-100" display="dynamic" placement="bottom-right"
|
||||||
|
ngbDropdown
|
||||||
|
*ngIf="(moreThanOne$ | async)">
|
||||||
|
<button class="btn btn-lg btn-primary mt-1 ml-2" id="dropdownSubmission" ngbDropdownToggle
|
||||||
|
type="button" [disabled]="!(initialized$|async)">
|
||||||
|
<i class="fa fa-plus-circle" aria-hidden="true"></i>
|
||||||
|
<span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<div ngbDropdownMenu
|
||||||
|
class="dropdown-menu"
|
||||||
|
id="entityControlsDropdownMenu"
|
||||||
|
aria-labelledby="dropdownSubmission">
|
||||||
|
<ds-entity-dropdown [isSubmission]="true" (selectionChange)="openDialog($event)"></ds-entity-dropdown>
|
||||||
|
</div>
|
||||||
|
</div>
|
@@ -0,0 +1,16 @@
|
|||||||
|
.parent {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.upload {
|
||||||
|
flex: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add {
|
||||||
|
flex: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
#entityControlsDropdownMenu {
|
||||||
|
min-width: 18rem;
|
||||||
|
box-shadow: $btn-focus-box-shadow;
|
||||||
|
}
|
@@ -0,0 +1,194 @@
|
|||||||
|
import { Component, DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { async, ComponentFixture, inject, TestBed } from '@angular/core/testing';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
|
import { of as observableOf } from 'rxjs';
|
||||||
|
import { createPaginatedList, createTestComponent } from '../../../shared/testing/utils.test';
|
||||||
|
import { MyDSpaceNewSubmissionDropdownComponent } from './my-dspace-new-submission-dropdown.component';
|
||||||
|
import { EntityTypeService } from '../../../core/data/entity-type.service';
|
||||||
|
import { ItemType } from '../../../core/shared/item-relationships/item-type.model';
|
||||||
|
import { ResourceType } from '../../../core/shared/resource-type';
|
||||||
|
import { createSuccessfulRemoteDataObject$ } from '../../../shared/remote-data.utils';
|
||||||
|
import { PageInfo } from '../../../core/shared/page-info.model';
|
||||||
|
|
||||||
|
export function getMockEntityTypeService(): EntityTypeService {
|
||||||
|
const type1: ItemType = {
|
||||||
|
id: '1',
|
||||||
|
label: 'Publication',
|
||||||
|
uuid: '1',
|
||||||
|
type: new ResourceType('entitytype'),
|
||||||
|
_links: undefined
|
||||||
|
};
|
||||||
|
const type2: ItemType = {
|
||||||
|
id: '2',
|
||||||
|
label: 'Journal',
|
||||||
|
uuid: '2',
|
||||||
|
type: new ResourceType('entitytype'),
|
||||||
|
_links: undefined
|
||||||
|
};
|
||||||
|
const type3: ItemType = {
|
||||||
|
id: '2',
|
||||||
|
label: 'DataPackage',
|
||||||
|
uuid: '2',
|
||||||
|
type: new ResourceType('entitytype'),
|
||||||
|
_links: undefined
|
||||||
|
};
|
||||||
|
const rd$ = createSuccessfulRemoteDataObject$(createPaginatedList([type1, type2, type3]));
|
||||||
|
return jasmine.createSpyObj('entityTypeService', {
|
||||||
|
getAllAuthorizedRelationshipType: rd$,
|
||||||
|
hasMoreThanOneAuthorized: observableOf(true)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getMockEmptyEntityTypeService(): EntityTypeService {
|
||||||
|
const pageInfo = { elementsPerPage: 20, totalElements: 1, totalPages: 1, currentPage: 0 } as PageInfo;
|
||||||
|
const type1: ItemType = {
|
||||||
|
id: '1',
|
||||||
|
label: 'Publication',
|
||||||
|
uuid: '1',
|
||||||
|
type: new ResourceType('entitytype'),
|
||||||
|
_links: undefined
|
||||||
|
};
|
||||||
|
const rd$ = createSuccessfulRemoteDataObject$(createPaginatedList([type1]));
|
||||||
|
return jasmine.createSpyObj('entityTypeService', {
|
||||||
|
getAllAuthorizedRelationshipType: rd$,
|
||||||
|
hasMoreThanOneAuthorized: observableOf(false)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('MyDSpaceNewSubmissionDropdownComponent test', () => {
|
||||||
|
let testComp: TestComponent;
|
||||||
|
let testFixture: ComponentFixture<TestComponent>;
|
||||||
|
let submissionComponent: MyDSpaceNewSubmissionDropdownComponent;
|
||||||
|
let submissionComponentFixture: ComponentFixture<MyDSpaceNewSubmissionDropdownComponent>;
|
||||||
|
|
||||||
|
const entityType1: ItemType = {
|
||||||
|
id: '1',
|
||||||
|
label: 'Publication',
|
||||||
|
uuid: '1',
|
||||||
|
type: new ResourceType('entitytype'),
|
||||||
|
_links: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
const modalStub = {
|
||||||
|
open: () => null,
|
||||||
|
close: () => null,
|
||||||
|
dismiss: () => null
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('With only one Entity', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
MyDSpaceNewSubmissionDropdownComponent,
|
||||||
|
TestComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{ provide: EntityTypeService, useValue: getMockEmptyEntityTypeService() },
|
||||||
|
{ provide: NgbModal, useValue: modalStub },
|
||||||
|
MyDSpaceNewSubmissionDropdownComponent
|
||||||
|
],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
const html = `<ds-my-dspace-new-submission (uploadEnd)="reload($event)"></ds-my-dspace-new-submission>`;
|
||||||
|
|
||||||
|
testFixture = createTestComponent(html, TestComponent) as ComponentFixture<TestComponent>;
|
||||||
|
testComp = testFixture.componentInstance;
|
||||||
|
|
||||||
|
submissionComponentFixture = TestBed.createComponent(MyDSpaceNewSubmissionDropdownComponent);
|
||||||
|
submissionComponent = submissionComponentFixture.componentInstance;
|
||||||
|
submissionComponentFixture.detectChanges();
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
testFixture.destroy();
|
||||||
|
submissionComponentFixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create MyDSpaceNewSubmissionDropdownComponent', inject([MyDSpaceNewSubmissionDropdownComponent], (app: MyDSpaceNewSubmissionDropdownComponent) => {
|
||||||
|
expect(app).toBeDefined();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should be a single button', inject([MyDSpaceNewSubmissionDropdownComponent], (app: MyDSpaceNewSubmissionDropdownComponent) => {
|
||||||
|
submissionComponentFixture.detectChanges();
|
||||||
|
const addDivElement: DebugElement = submissionComponentFixture.debugElement.query(By.css('.add'));
|
||||||
|
const addDiv = addDivElement.nativeElement;
|
||||||
|
expect(addDiv.innerHTML).toBeDefined();
|
||||||
|
const buttonElement: DebugElement = addDivElement.query(By.css('.btn'));
|
||||||
|
const button = buttonElement.nativeElement;
|
||||||
|
expect(button.innerHTML).toBeDefined();
|
||||||
|
const dropdownElement: DebugElement = submissionComponentFixture.debugElement.query(By.css('.dropdown-menu'));
|
||||||
|
expect(dropdownElement).toBeNull();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('With more than one Entity', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
TranslateModule.forRoot(),
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
MyDSpaceNewSubmissionDropdownComponent,
|
||||||
|
TestComponent
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
{ provide: EntityTypeService, useValue: getMockEntityTypeService() },
|
||||||
|
{ provide: NgbModal, useValue: modalStub },
|
||||||
|
MyDSpaceNewSubmissionDropdownComponent
|
||||||
|
],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
const html = `<ds-my-dspace-new-submission (uploadEnd)="reload($event)"></ds-my-dspace-new-submission>`;
|
||||||
|
|
||||||
|
testFixture = createTestComponent(html, TestComponent) as ComponentFixture<TestComponent>;
|
||||||
|
testComp = testFixture.componentInstance;
|
||||||
|
|
||||||
|
submissionComponentFixture = TestBed.createComponent(MyDSpaceNewSubmissionDropdownComponent);
|
||||||
|
submissionComponent = submissionComponentFixture.componentInstance;
|
||||||
|
submissionComponentFixture.detectChanges();
|
||||||
|
}));
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
testFixture.destroy();
|
||||||
|
submissionComponentFixture.destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create MyDSpaceNewSubmissionDropdownComponent', inject([MyDSpaceNewSubmissionDropdownComponent], (app: MyDSpaceNewSubmissionDropdownComponent) => {
|
||||||
|
expect(app).toBeDefined();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should be a dropdown button', inject([MyDSpaceNewSubmissionDropdownComponent], (app: MyDSpaceNewSubmissionDropdownComponent) => {
|
||||||
|
const dropdownElement: DebugElement = submissionComponentFixture.debugElement.query(By.css('.dropdown-menu'));
|
||||||
|
const dropdown = dropdownElement.nativeElement;
|
||||||
|
expect(dropdown.innerHTML).toBeDefined();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should invoke modalService.open', () => {
|
||||||
|
spyOn((submissionComponent as any).modalService, 'open').and.returnValue({ componentInstance: { } });
|
||||||
|
submissionComponent.openDialog(entityType1);
|
||||||
|
|
||||||
|
expect((submissionComponent as any).modalService.open).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// declare a test component
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-test-cmp',
|
||||||
|
template: ``
|
||||||
|
})
|
||||||
|
class TestComponent {
|
||||||
|
reload = (event) => {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,109 @@
|
|||||||
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
|
||||||
|
import { Observable, of as observableOf, Subscription } from 'rxjs';
|
||||||
|
import { map, mergeMap, take } from 'rxjs/operators';
|
||||||
|
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||||
|
|
||||||
|
import { EntityTypeService } from '../../../core/data/entity-type.service';
|
||||||
|
import { ItemType } from '../../../core/shared/item-relationships/item-type.model';
|
||||||
|
import { FindListOptions } from '../../../core/data/request.models';
|
||||||
|
import { hasValue } from '../../../shared/empty.util';
|
||||||
|
import { CreateItemParentSelectorComponent } from '../../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component';
|
||||||
|
import { RemoteData } from '../../../core/data/remote-data';
|
||||||
|
import { PaginatedList } from '../../../core/data/paginated-list.model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This component represents the new submission dropdown
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'ds-my-dspace-new-submission-dropdown',
|
||||||
|
styleUrls: ['./my-dspace-new-submission-dropdown.component.scss'],
|
||||||
|
templateUrl: './my-dspace-new-submission-dropdown.component.html'
|
||||||
|
})
|
||||||
|
export class MyDSpaceNewSubmissionDropdownComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to verify if there are one or more entities available
|
||||||
|
*/
|
||||||
|
public moreThanOne$: Observable<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entity observble (only if there is only one entity available)
|
||||||
|
*/
|
||||||
|
public singleEntity$: Observable<ItemType>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The entity object (only if there is only one entity available)
|
||||||
|
*/
|
||||||
|
public singleEntity: ItemType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TRUE if the page is initialized
|
||||||
|
*/
|
||||||
|
public initialized$: Observable<boolean>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array to track all subscriptions and unsubscribe them onDestroy
|
||||||
|
* @type {Array}
|
||||||
|
*/
|
||||||
|
public subs: Subscription[] = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize instance variables
|
||||||
|
*
|
||||||
|
* @param {EntityTypeService} entityTypeService
|
||||||
|
* @param {NgbModal} modalService
|
||||||
|
*/
|
||||||
|
constructor(private entityTypeService: EntityTypeService,
|
||||||
|
private modalService: NgbModal) { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize entity type list
|
||||||
|
*/
|
||||||
|
ngOnInit() {
|
||||||
|
this.initialized$ = observableOf(false);
|
||||||
|
this.moreThanOne$ = this.entityTypeService.hasMoreThanOneAuthorized();
|
||||||
|
this.singleEntity$ = this.moreThanOne$.pipe(
|
||||||
|
mergeMap((response: boolean) => {
|
||||||
|
if (!response) {
|
||||||
|
const findListOptions: FindListOptions = {
|
||||||
|
elementsPerPage: 1,
|
||||||
|
currentPage: 1
|
||||||
|
};
|
||||||
|
return this.entityTypeService.getAllAuthorizedRelationshipType(findListOptions).pipe(
|
||||||
|
map((entities: RemoteData<PaginatedList<ItemType>>) => {
|
||||||
|
this.initialized$ = observableOf(true);
|
||||||
|
return entities.payload.page[0];
|
||||||
|
}),
|
||||||
|
take(1)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.initialized$ = observableOf(true);
|
||||||
|
return observableOf(null);
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
take(1)
|
||||||
|
);
|
||||||
|
this.subs.push(
|
||||||
|
this.singleEntity$.subscribe((result) => this.singleEntity = result )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Method called on clicking the button "New Submition", It opens a dialog for
|
||||||
|
* select a collection.
|
||||||
|
*/
|
||||||
|
openDialog(entity: ItemType) {
|
||||||
|
const modalRef = this.modalService.open(CreateItemParentSelectorComponent);
|
||||||
|
modalRef.componentInstance.entityType = entity.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unsubscribe from the subscription
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.subs
|
||||||
|
.filter((subscription) => hasValue(subscription))
|
||||||
|
.forEach((subscription) => subscription.unsubscribe());
|
||||||
|
}
|
||||||
|
}
|
@@ -8,14 +8,10 @@
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="add">
|
<div class="add">
|
||||||
<button class="btn btn-lg btn-primary mt-1 ml-2" (click)="openDialog()" attr.aria-label="'mydspace.new-submission' | translate" title="{{'mydspace.new-submission' | translate}}">
|
<ds-my-dspace-new-submission-dropdown></ds-my-dspace-new-submission-dropdown>
|
||||||
<i class="fa fa-plus" aria-hidden="true"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="add">
|
<div class="add">
|
||||||
<a class="btn btn-lg btn-outline-primary mt-1 ml-2" [routerLink]="['/import-external']" role="button" attr.aria-label="{{'mydspace.new-submission-external' | translate}}" title="{{'mydspace.new-submission-external' | translate}}">
|
<ds-my-dspace-new-external-dropdown></ds-my-dspace-new-external-dropdown>
|
||||||
<i class="fa fa-file-import" aria-hidden="true"></i>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,7 +1,6 @@
|
|||||||
import { ChangeDetectorRef, Component, NO_ERRORS_SCHEMA } from '@angular/core';
|
import { ChangeDetectorRef, Component, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
|
import { ComponentFixture, inject, TestBed, waitForAsync } from '@angular/core/testing';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
import { RouterTestingModule } from '@angular/router/testing';
|
||||||
import { By } from '@angular/platform-browser';
|
|
||||||
|
|
||||||
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
|
||||||
import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
|
import { ScrollToService } from '@nicky-lenaers/ngx-scroll-to';
|
||||||
@@ -25,6 +24,8 @@ import { HttpXsrfTokenExtractor } from '@angular/common/http';
|
|||||||
import { CookieService } from '../../core/services/cookie.service';
|
import { CookieService } from '../../core/services/cookie.service';
|
||||||
import { CookieServiceMock } from '../../shared/mocks/cookie.service.mock';
|
import { CookieServiceMock } from '../../shared/mocks/cookie.service.mock';
|
||||||
import { HttpXsrfTokenExtractorMock } from '../../shared/mocks/http-xsrf-token-extractor.mock';
|
import { HttpXsrfTokenExtractorMock } from '../../shared/mocks/http-xsrf-token-extractor.mock';
|
||||||
|
import { getMockEntityTypeService } from './my-dspace-new-submission-dropdown/my-dspace-new-submission-dropdown.component.spec';
|
||||||
|
import { EntityTypeService } from '../../core/data/entity-type.service';
|
||||||
|
|
||||||
describe('MyDSpaceNewSubmissionComponent test', () => {
|
describe('MyDSpaceNewSubmissionComponent test', () => {
|
||||||
|
|
||||||
@@ -62,6 +63,7 @@ describe('MyDSpaceNewSubmissionComponent test', () => {
|
|||||||
{ provide: HttpXsrfTokenExtractor, useValue: new HttpXsrfTokenExtractorMock('mock-token') },
|
{ provide: HttpXsrfTokenExtractor, useValue: new HttpXsrfTokenExtractorMock('mock-token') },
|
||||||
{ provide: CookieService, useValue: new CookieServiceMock() },
|
{ provide: CookieService, useValue: new CookieServiceMock() },
|
||||||
{ provide: HostWindowService, useValue: new HostWindowServiceStub(800) },
|
{ provide: HostWindowService, useValue: new HostWindowServiceStub(800) },
|
||||||
|
{ provide: EntityTypeService, useValue: getMockEntityTypeService() },
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
}).compileComponents();
|
}).compileComponents();
|
||||||
@@ -104,20 +106,6 @@ describe('MyDSpaceNewSubmissionComponent test', () => {
|
|||||||
comp.uploaderComponent.uploader = uploader;
|
comp.uploaderComponent.uploader = uploader;
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call app.openDialog', (done) => {
|
|
||||||
spyOn(comp, 'openDialog');
|
|
||||||
const submissionButton = fixture.debugElement.query(By.css('button.btn-primary'));
|
|
||||||
submissionButton.triggerEventHandler('click', null);
|
|
||||||
|
|
||||||
fixture.detectChanges();
|
|
||||||
|
|
||||||
fixture.whenStable().then(() => {
|
|
||||||
expect(comp.openDialog).toHaveBeenCalled();
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show a collection selector if only one file are uploaded', (done) => {
|
it('should show a collection selector if only one file are uploaded', (done) => {
|
||||||
spyOn((comp as any).modalService, 'open').and.returnValue({ result: new Promise((res, rej) => {/****/}) });
|
spyOn((comp as any).modalService, 'open').and.returnValue({ result: new Promise((res, rej) => {/****/}) });
|
||||||
comp.afterFileLoaded(['']);
|
comp.afterFileLoaded(['']);
|
||||||
|
@@ -14,7 +14,6 @@ import { HALEndpointService } from '../../core/shared/hal-endpoint.service';
|
|||||||
import { NotificationType } from '../../shared/notifications/models/notification-type';
|
import { NotificationType } from '../../shared/notifications/models/notification-type';
|
||||||
import { hasValue } from '../../shared/empty.util';
|
import { hasValue } from '../../shared/empty.util';
|
||||||
import { SearchResult } from '../../shared/search/search-result.model';
|
import { SearchResult } from '../../shared/search/search-result.model';
|
||||||
import { CreateItemParentSelectorComponent } from '../../shared/dso-selector/modal-wrappers/create-item-parent-selector/create-item-parent-selector.component';
|
|
||||||
import { CollectionSelectorComponent } from '../collection-selector/collection-selector.component';
|
import { CollectionSelectorComponent } from '../collection-selector/collection-selector.component';
|
||||||
import { UploaderComponent } from '../../shared/uploader/uploader.component';
|
import { UploaderComponent } from '../../shared/uploader/uploader.component';
|
||||||
import { UploaderError } from '../../shared/uploader/uploader-error.model';
|
import { UploaderError } from '../../shared/uploader/uploader-error.model';
|
||||||
@@ -118,14 +117,6 @@ export class MyDSpaceNewSubmissionComponent implements OnDestroy, OnInit {
|
|||||||
this.notificationsService.error(null, this.translate.get(errorMessageKey));
|
this.notificationsService.error(null, this.translate.get(errorMessageKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Method called on clicking the button "New Submition", It opens a dialog for
|
|
||||||
* select a collection.
|
|
||||||
*/
|
|
||||||
openDialog() {
|
|
||||||
this.modalService.open(CreateItemParentSelectorComponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method invoked after all file are loaded from upload plugin
|
* Method invoked after all file are loaded from upload plugin
|
||||||
*/
|
*/
|
||||||
|
@@ -11,6 +11,8 @@ import { MyDSpaceGuard } from './my-dspace.guard';
|
|||||||
import { MyDSpaceConfigurationService } from './my-dspace-configuration.service';
|
import { MyDSpaceConfigurationService } from './my-dspace-configuration.service';
|
||||||
import { CollectionSelectorComponent } from './collection-selector/collection-selector.component';
|
import { CollectionSelectorComponent } from './collection-selector/collection-selector.component';
|
||||||
import { MyDspaceSearchModule } from './my-dspace-search.module';
|
import { MyDspaceSearchModule } from './my-dspace-search.module';
|
||||||
|
import { MyDSpaceNewSubmissionDropdownComponent } from './my-dspace-new-submission/my-dspace-new-submission-dropdown/my-dspace-new-submission-dropdown.component';
|
||||||
|
import { MyDSpaceNewExternalDropdownComponent } from './my-dspace-new-submission/my-dspace-new-external-dropdown/my-dspace-new-external-dropdown.component';
|
||||||
import { ThemedMyDSpacePageComponent } from './themed-my-dspace-page.component';
|
import { ThemedMyDSpacePageComponent } from './themed-my-dspace-page.component';
|
||||||
|
|
||||||
const DECLARATIONS = [
|
const DECLARATIONS = [
|
||||||
@@ -18,7 +20,9 @@ const DECLARATIONS = [
|
|||||||
ThemedMyDSpacePageComponent,
|
ThemedMyDSpacePageComponent,
|
||||||
MyDSpaceResultsComponent,
|
MyDSpaceResultsComponent,
|
||||||
MyDSpaceNewSubmissionComponent,
|
MyDSpaceNewSubmissionComponent,
|
||||||
CollectionSelectorComponent
|
CollectionSelectorComponent,
|
||||||
|
MyDSpaceNewSubmissionDropdownComponent,
|
||||||
|
MyDSpaceNewExternalDropdownComponent
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
Reference in New Issue
Block a user