mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-15 14:03:06 +00:00
Merge branch 'master' into w2p-67611_Convert-external-source-to-entity
Conflicts: src/app/shared/form/builder/ds-dynamic-form-ui/ds-dynamic-form-control-container.component.ts
This commit is contained in:
@@ -10,8 +10,9 @@ module.exports = {
|
|||||||
// The REST API server settings.
|
// The REST API server settings.
|
||||||
rest: {
|
rest: {
|
||||||
ssl: true,
|
ssl: true,
|
||||||
host: 'dspace7-entities.atmire.com',
|
host: 'dspace7.4science.cloud',
|
||||||
port: 443,
|
port: 443,
|
||||||
|
// NOTE: Space is capitalized because 'namespace' is a reserved string in TypeScript
|
||||||
nameSpace: '/server/api'
|
nameSpace: '/server/api'
|
||||||
},
|
},
|
||||||
// Caching settings
|
// Caching settings
|
||||||
|
@@ -0,0 +1,93 @@
|
|||||||
|
import { StatusCodeOnlyResponseParsingService } from './status-code-only-response-parsing.service';
|
||||||
|
|
||||||
|
describe('StatusCodeOnlyResponseParsingService', () => {
|
||||||
|
let service;
|
||||||
|
let statusCode;
|
||||||
|
let statusText;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
service = new StatusCodeOnlyResponseParsingService();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('parse', () => {
|
||||||
|
|
||||||
|
it('should return a RestResponse that doesn\'t contain the response body', () => {
|
||||||
|
const payload = 'd9128e44-183b-479d-aa2e-d39435838bf6';
|
||||||
|
const result = service.parse(undefined, {
|
||||||
|
payload,
|
||||||
|
statusCode: 201,
|
||||||
|
statusText: '201'
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(JSON.stringify(result).indexOf(payload)).toBe(-1);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the response is successful', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
statusCode = 201;
|
||||||
|
statusText = `${statusCode}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a success RestResponse', () => {
|
||||||
|
const result = service.parse(undefined, {
|
||||||
|
statusCode,
|
||||||
|
statusText
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.isSuccessful).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a RestResponse with the correct status code', () => {
|
||||||
|
const result = service.parse(undefined, {
|
||||||
|
statusCode,
|
||||||
|
statusText
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.statusCode).toBe(statusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a RestResponse with the correct status text', () => {
|
||||||
|
const result = service.parse(undefined, {
|
||||||
|
statusCode,
|
||||||
|
statusText
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.statusText).toBe(statusText);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the response is unsuccessful', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
statusCode = 400;
|
||||||
|
statusText = `${statusCode}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an error RestResponse', () => {
|
||||||
|
const result = service.parse(undefined, {
|
||||||
|
statusCode,
|
||||||
|
statusText
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.isSuccessful).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a RestResponse with the correct status code', () => {
|
||||||
|
const result = service.parse(undefined, {
|
||||||
|
statusCode,
|
||||||
|
statusText
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.statusCode).toBe(statusCode);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a RestResponse with the correct status text', () => {
|
||||||
|
const result = service.parse(undefined, {
|
||||||
|
statusCode,
|
||||||
|
statusText
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.statusText).toBe(statusText);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,26 @@
|
|||||||
|
import { Injectable } from '@angular/core';
|
||||||
|
import { RestResponse } from '../cache/response.models';
|
||||||
|
import { DSpaceRESTV2Response } from '../dspace-rest-v2/dspace-rest-v2-response.model';
|
||||||
|
import { ResponseParsingService } from './parsing.service';
|
||||||
|
import { RestRequest } from './request.models';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A responseparser that will only look at the status code and status
|
||||||
|
* text of the response, and ignore anything else that might be there
|
||||||
|
*/
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root'
|
||||||
|
})
|
||||||
|
export class StatusCodeOnlyResponseParsingService implements ResponseParsingService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse the response and only extract the status code and status text
|
||||||
|
*
|
||||||
|
* @param request The request that was sent to the server
|
||||||
|
* @param data The response to parse
|
||||||
|
*/
|
||||||
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
|
const isSuccessful = data.statusCode >= 200 && data.statusCode < 300;
|
||||||
|
return new RestResponse(isSuccessful, data.statusCode, data.statusText);
|
||||||
|
}
|
||||||
|
}
|
@@ -125,9 +125,3 @@ export const getFirstOccurrence = () =>
|
|||||||
source.pipe(
|
source.pipe(
|
||||||
map((rd) => Object.assign(rd, { payload: rd.payload.page.length > 0 ? rd.payload.page[0] : undefined }))
|
map((rd) => Object.assign(rd, { payload: rd.payload.page.length > 0 ? rd.payload.page[0] : undefined }))
|
||||||
);
|
);
|
||||||
|
|
||||||
export const obsLog = (logString?: string) =>
|
|
||||||
<T>(source: Observable<T>): Observable<T> =>
|
|
||||||
source.pipe(
|
|
||||||
tap((t) => console.log(logString || '', t))
|
|
||||||
);
|
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
import { Inject, Injectable } from '@angular/core';
|
import { Inject, Injectable } from '@angular/core';
|
||||||
|
import { deepClone } from 'fast-json-patch';
|
||||||
|
import { DSOResponseParsingService } from '../data/dso-response-parsing.service';
|
||||||
|
|
||||||
import { ResponseParsingService } from '../data/parsing.service';
|
import { ResponseParsingService } from '../data/parsing.service';
|
||||||
import { RestRequest } from '../data/request.models';
|
import { RestRequest } from '../data/request.models';
|
||||||
@@ -76,7 +78,9 @@ export class SubmissionResponseParsingService extends BaseResponseParsingService
|
|||||||
protected toCache = false;
|
protected toCache = false;
|
||||||
|
|
||||||
constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig,
|
constructor(@Inject(GLOBAL_CONFIG) protected EnvConfig: GlobalConfig,
|
||||||
protected objectCache: ObjectCacheService) {
|
protected objectCache: ObjectCacheService,
|
||||||
|
protected dsoParser: DSOResponseParsingService
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +92,7 @@ export class SubmissionResponseParsingService extends BaseResponseParsingService
|
|||||||
* @returns {RestResponse}
|
* @returns {RestResponse}
|
||||||
*/
|
*/
|
||||||
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
parse(request: RestRequest, data: DSpaceRESTV2Response): RestResponse {
|
||||||
|
this.dsoParser.parse(deepClone(request), deepClone(data));
|
||||||
if (isNotEmpty(data.payload)
|
if (isNotEmpty(data.payload)
|
||||||
&& isNotEmpty(data.payload._links)
|
&& isNotEmpty(data.payload._links)
|
||||||
&& this.isSuccessStatus(data.statusCode)) {
|
&& this.isSuccessStatus(data.statusCode)) {
|
||||||
|
@@ -0,0 +1,64 @@
|
|||||||
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
|
import { OrgUnitInputSuggestionsComponent } from './org-unit-input-suggestions.component';
|
||||||
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
|
let component: OrgUnitInputSuggestionsComponent;
|
||||||
|
let fixture: ComponentFixture<OrgUnitInputSuggestionsComponent>;
|
||||||
|
|
||||||
|
let suggestions: string[];
|
||||||
|
let testValue;
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
suggestions = ['test', 'suggestion', 'example']
|
||||||
|
testValue = 'bla';
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('OrgUnitInputSuggestionsComponent', () => {
|
||||||
|
beforeEach(async(() => {
|
||||||
|
init();
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
declarations: [OrgUnitInputSuggestionsComponent],
|
||||||
|
imports: [
|
||||||
|
FormsModule,
|
||||||
|
],
|
||||||
|
providers: [
|
||||||
|
],
|
||||||
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
}).overrideComponent(OrgUnitInputSuggestionsComponent, {
|
||||||
|
set: { changeDetection: ChangeDetectionStrategy.Default }
|
||||||
|
}).compileComponents();
|
||||||
|
}));
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
fixture = TestBed.createComponent(OrgUnitInputSuggestionsComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
component.suggestions = suggestions;
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When the component is initialized', () => {
|
||||||
|
it('should set the value to the first value of the suggestions', () => {
|
||||||
|
expect(component.value).toEqual('test');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When onSubmit is called', () => {
|
||||||
|
it('should set the value to parameter of the method', () => {
|
||||||
|
component.onSubmit(testValue);
|
||||||
|
expect(component.value).toEqual(testValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('When onClickSuggestion is called', () => {
|
||||||
|
it('should set the value to parameter of the method', () => {
|
||||||
|
component.onClickSuggestion(testValue);
|
||||||
|
expect(component.value).toEqual(testValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@@ -85,8 +85,7 @@ import { DsDynamicLookupRelationModalComponent } from './relation-lookup-modal/d
|
|||||||
import {
|
import {
|
||||||
getAllSucceededRemoteData,
|
getAllSucceededRemoteData,
|
||||||
getRemoteDataPayload,
|
getRemoteDataPayload,
|
||||||
getSucceededRemoteData,
|
getSucceededRemoteData
|
||||||
obsLog
|
|
||||||
} from '../../../../core/shared/operators';
|
} from '../../../../core/shared/operators';
|
||||||
import { RemoteData } from '../../../../core/data/remote-data';
|
import { RemoteData } from '../../../../core/data/remote-data';
|
||||||
import { Item } from '../../../../core/shared/item.model';
|
import { Item } from '../../../../core/shared/item.model';
|
||||||
@@ -100,7 +99,6 @@ import { PaginatedList } from '../../../../core/data/paginated-list';
|
|||||||
import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model';
|
import { ItemSearchResult } from '../../../object-collection/shared/item-search-result.model';
|
||||||
import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model';
|
import { ItemMetadataRepresentation } from '../../../../core/shared/metadata-representation/item/item-metadata-representation.model';
|
||||||
import { MetadataValue } from '../../../../core/shared/metadata.models';
|
import { MetadataValue } from '../../../../core/shared/metadata.models';
|
||||||
import * as uuidv4 from 'uuid/v4';
|
|
||||||
import { Collection } from '../../../../core/shared/collection.model';
|
import { Collection } from '../../../../core/shared/collection.model';
|
||||||
|
|
||||||
export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type<DynamicFormControl> | null {
|
export function dsDynamicFormControlMapFn(model: DynamicFormControlModel): Type<DynamicFormControl> | null {
|
||||||
|
@@ -26,9 +26,11 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => {
|
|||||||
let item1;
|
let item1;
|
||||||
let item2;
|
let item2;
|
||||||
let item3;
|
let item3;
|
||||||
|
let item4;
|
||||||
let searchResult1;
|
let searchResult1;
|
||||||
let searchResult2;
|
let searchResult2;
|
||||||
let searchResult3;
|
let searchResult3;
|
||||||
|
let searchResult4;
|
||||||
let listID;
|
let listID;
|
||||||
let selection$;
|
let selection$;
|
||||||
|
|
||||||
@@ -42,9 +44,11 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => {
|
|||||||
item1 = Object.assign(new Item(), { uuid: 'e1c51c69-896d-42dc-8221-1d5f2ad5516e' });
|
item1 = Object.assign(new Item(), { uuid: 'e1c51c69-896d-42dc-8221-1d5f2ad5516e' });
|
||||||
item2 = Object.assign(new Item(), { uuid: 'c8279647-1acc-41ae-b036-951d5f65649b' });
|
item2 = Object.assign(new Item(), { uuid: 'c8279647-1acc-41ae-b036-951d5f65649b' });
|
||||||
item3 = Object.assign(new Item(), { uuid: 'c3bcbff5-ec0c-4831-8e4c-94b9c933ccac' });
|
item3 = Object.assign(new Item(), { uuid: 'c3bcbff5-ec0c-4831-8e4c-94b9c933ccac' });
|
||||||
|
item4 = Object.assign(new Item(), { uuid: 'f96a385e-de10-45b2-be66-7f10bf52f765' });
|
||||||
searchResult1 = Object.assign(new ItemSearchResult(), { indexableObject: item1 });
|
searchResult1 = Object.assign(new ItemSearchResult(), { indexableObject: item1 });
|
||||||
searchResult2 = Object.assign(new ItemSearchResult(), { indexableObject: item2 });
|
searchResult2 = Object.assign(new ItemSearchResult(), { indexableObject: item2 });
|
||||||
searchResult3 = Object.assign(new ItemSearchResult(), { indexableObject: item3 });
|
searchResult3 = Object.assign(new ItemSearchResult(), { indexableObject: item3 });
|
||||||
|
searchResult4 = Object.assign(new ItemSearchResult(), { indexableObject: item4 });
|
||||||
listID = '6b0c8221-fcb4-47a8-b483-ca32363fffb3';
|
listID = '6b0c8221-fcb4-47a8-b483-ca32363fffb3';
|
||||||
selection$ = observableOf([searchResult1, searchResult2]);
|
selection$ = observableOf([searchResult1, searchResult2]);
|
||||||
|
|
||||||
@@ -102,12 +106,12 @@ describe('DsDynamicLookupRelationSearchTabComponent', () => {
|
|||||||
describe('selectPage', () => {
|
describe('selectPage', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
spyOn(component.selectObject, 'emit');
|
spyOn(component.selectObject, 'emit');
|
||||||
component.selectPage([searchResult1, searchResult2, searchResult3]);
|
component.selectPage([searchResult1, searchResult2, searchResult4]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit the page filtered from already selected objects and call select on the service for all objects', () => {
|
it('should emit the page filtered from already selected objects and call select on the service for all objects', () => {
|
||||||
expect(component.selectObject.emit).toHaveBeenCalledWith(searchResult3);
|
expect(component.selectObject.emit).toHaveBeenCalledWith(searchResult4);
|
||||||
expect(selectableListService.select).toHaveBeenCalledWith(listID, [searchResult1, searchResult2, searchResult3]);
|
expect(selectableListService.select).toHaveBeenCalledWith(listID, [searchResult1, searchResult2, searchResult4]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -1,15 +1,20 @@
|
|||||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { TranslateModule } from '@ngx-translate/core';
|
import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
|
import { SearchConfigurationService } from '../../../../../../core/shared/search/search-configuration.service';
|
||||||
import { RouterTestingModule } from '@angular/router/testing';
|
|
||||||
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
import { NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { VarDirective } from '../../../../../utils/var.directive';
|
import { VarDirective } from '../../../../../utils/var.directive';
|
||||||
import { of as observableOf } from 'rxjs';
|
import { Observable, of as observableOf } from 'rxjs';
|
||||||
import { PaginatedSearchOptions } from '../../../../../search/paginated-search-options.model';
|
import { PaginatedSearchOptions } from '../../../../../search/paginated-search-options.model';
|
||||||
import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model';
|
import { ItemSearchResult } from '../../../../../object-collection/shared/item-search-result.model';
|
||||||
import { Item } from '../../../../../../core/shared/item.model';
|
import { Item } from '../../../../../../core/shared/item.model';
|
||||||
import { DsDynamicLookupRelationSelectionTabComponent } from './dynamic-lookup-relation-selection-tab.component';
|
import { DsDynamicLookupRelationSelectionTabComponent } from './dynamic-lookup-relation-selection-tab.component';
|
||||||
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../../../../../pagination/pagination-component-options.model';
|
||||||
|
import { Router } from '@angular/router';
|
||||||
|
import { By } from '@angular/platform-browser';
|
||||||
|
import { RemoteData } from '../../../../../../core/data/remote-data';
|
||||||
|
import { PaginatedList } from '../../../../../../core/data/paginated-list';
|
||||||
|
import { ListableObject } from '../../../../../object-collection/shared/listable-object.model';
|
||||||
|
import { createSuccessfulRemoteDataObject$ } from '../../../../../testing/utils';
|
||||||
|
|
||||||
describe('DsDynamicLookupRelationSelectionTabComponent', () => {
|
describe('DsDynamicLookupRelationSelectionTabComponent', () => {
|
||||||
let component: DsDynamicLookupRelationSelectionTabComponent;
|
let component: DsDynamicLookupRelationSelectionTabComponent;
|
||||||
@@ -20,7 +25,9 @@ describe('DsDynamicLookupRelationSelectionTabComponent', () => {
|
|||||||
let searchResult1 = Object.assign(new ItemSearchResult(), { indexableObject: item1 });
|
let searchResult1 = Object.assign(new ItemSearchResult(), { indexableObject: item1 });
|
||||||
let searchResult2 = Object.assign(new ItemSearchResult(), { indexableObject: item2 });
|
let searchResult2 = Object.assign(new ItemSearchResult(), { indexableObject: item2 });
|
||||||
let listID = '6b0c8221-fcb4-47a8-b483-ca32363fffb3';
|
let listID = '6b0c8221-fcb4-47a8-b483-ca32363fffb3';
|
||||||
let selection$ = observableOf([searchResult1, searchResult2]);
|
let selection$;
|
||||||
|
let selectionRD$;
|
||||||
|
let router;
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
pSearchOptions = new PaginatedSearchOptions({ pagination: new PaginationComponentOptions() });
|
pSearchOptions = new PaginatedSearchOptions({ pagination: new PaginationComponentOptions() });
|
||||||
@@ -30,17 +37,23 @@ describe('DsDynamicLookupRelationSelectionTabComponent', () => {
|
|||||||
searchResult2 = Object.assign(new ItemSearchResult(), { indexableObject: item2 });
|
searchResult2 = Object.assign(new ItemSearchResult(), { indexableObject: item2 });
|
||||||
listID = '6b0c8221-fcb4-47a8-b483-ca32363fffb3';
|
listID = '6b0c8221-fcb4-47a8-b483-ca32363fffb3';
|
||||||
selection$ = observableOf([searchResult1, searchResult2]);
|
selection$ = observableOf([searchResult1, searchResult2]);
|
||||||
|
selectionRD$ = createSelection([searchResult1, searchResult2]);
|
||||||
|
router = jasmine.createSpyObj('router', ['navigate'])
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
init();
|
init();
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
declarations: [DsDynamicLookupRelationSelectionTabComponent, VarDirective],
|
declarations: [DsDynamicLookupRelationSelectionTabComponent, VarDirective],
|
||||||
imports: [TranslateModule.forRoot(), RouterTestingModule.withRoutes([])],
|
imports: [TranslateModule.forRoot()],
|
||||||
providers: [
|
providers: [
|
||||||
{
|
{
|
||||||
provide: SearchConfigurationService, useValue: {
|
provide: SearchConfigurationService, useValue: {
|
||||||
paginatedSearchOptions: observableOf(pSearchOptions)
|
paginatedSearchOptions: observableOf(pSearchOptions)
|
||||||
}
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: Router, useValue: router
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
@@ -59,4 +72,26 @@ describe('DsDynamicLookupRelationSelectionTabComponent', () => {
|
|||||||
it('should create', () => {
|
it('should create', () => {
|
||||||
expect(component).toBeTruthy();
|
expect(component).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should call navigate on the router when is called resetRoute', () => {
|
||||||
|
component.resetRoute();
|
||||||
|
expect(router.navigate).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should call navigate on the router when is called resetRoute', () => {
|
||||||
|
component.selectionRD$ = createSelection([]);
|
||||||
|
fixture.detectChanges();
|
||||||
|
const colComponent = fixture.debugElement.query(By.css('ds-viewable-collection'));
|
||||||
|
expect(colComponent).toBe(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call navigate on the router when is called resetRoute', () => {
|
||||||
|
component.selectionRD$ = selectionRD$;
|
||||||
|
const colComponent = fixture.debugElement.query(By.css('ds-viewable-collection'));
|
||||||
|
expect(colComponent).not.toBe(null);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function createSelection(content: ListableObject[]): Observable<RemoteData<PaginatedList<ListableObject>>> {
|
||||||
|
return createSuccessfulRemoteDataObject$(new PaginatedList(undefined, content));
|
||||||
|
}
|
||||||
|
@@ -5,6 +5,11 @@ export class MockResponseMap extends Map<string, any> {};
|
|||||||
|
|
||||||
export const MOCK_RESPONSE_MAP: InjectionToken<MockResponseMap> = new InjectionToken<MockResponseMap>('mockResponseMap');
|
export const MOCK_RESPONSE_MAP: InjectionToken<MockResponseMap> = new InjectionToken<MockResponseMap>('mockResponseMap');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List of endpoints with their matching mock response
|
||||||
|
* Note that this list is only used in development mode
|
||||||
|
* In production the actual endpoints on the REST server will be called
|
||||||
|
*/
|
||||||
export const mockResponseMap: MockResponseMap = new Map([
|
export const mockResponseMap: MockResponseMap = new Map([
|
||||||
// [ '/config/submissionforms/traditionalpageone', mockSubmissionResponse ]
|
// [ '/config/submissionforms/traditionalpageone', mockSubmissionResponse ]
|
||||||
]);
|
]);
|
||||||
|
@@ -10,7 +10,7 @@ import { Observable } from 'rxjs';
|
|||||||
templateUrl: './selectable-list-item-control.component.html'
|
templateUrl: './selectable-list-item-control.component.html'
|
||||||
})
|
})
|
||||||
/**
|
/**
|
||||||
* Component for determining what component to use depending on the item's relationship type (relationship.type)
|
* Component for rendering list item that has a control (checkbox or radio button) because it's selectable
|
||||||
*/
|
*/
|
||||||
export class SelectableListItemControlComponent implements OnInit {
|
export class SelectableListItemControlComponent implements OnInit {
|
||||||
/**
|
/**
|
||||||
|
@@ -1,21 +1,11 @@
|
|||||||
import {
|
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
|
||||||
ChangeDetectionStrategy,
|
|
||||||
Component,
|
|
||||||
EventEmitter,
|
|
||||||
Input,
|
|
||||||
Output,
|
|
||||||
ViewEncapsulation
|
|
||||||
} from '@angular/core';
|
|
||||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||||
import { PaginatedList } from '../../core/data/paginated-list';
|
import { PaginatedList } from '../../core/data/paginated-list';
|
||||||
import { RemoteData } from '../../core/data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
import { fadeIn } from '../animations/fade';
|
import { fadeIn } from '../animations/fade';
|
||||||
import { ListableObject } from '../object-collection/shared/listable-object.model';
|
import { ListableObject } from '../object-collection/shared/listable-object.model';
|
||||||
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
|
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
|
||||||
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
|
||||||
import { SearchResult } from '../search/search-result.model';
|
|
||||||
import { SelectableListService } from './selectable-list/selectable-list.service';
|
import { SelectableListService } from './selectable-list/selectable-list.service';
|
||||||
import { map, take, tap } from 'rxjs/operators';
|
|
||||||
import { ViewMode } from '../../core/shared/view-mode.model';
|
import { ViewMode } from '../../core/shared/view-mode.model';
|
||||||
import { Context } from '../../core/shared/context.model';
|
import { Context } from '../../core/shared/context.model';
|
||||||
import { CollectionElementLinkType } from '../object-collection/collection-element-link.type';
|
import { CollectionElementLinkType } from '../object-collection/collection-element-link.type';
|
||||||
@@ -60,9 +50,6 @@ export class ObjectListComponent {
|
|||||||
@Input() hidePagerWhenSinglePage = true;
|
@Input() hidePagerWhenSinglePage = true;
|
||||||
@Input() selectable = false;
|
@Input() selectable = false;
|
||||||
@Input() selectionConfig: { repeatable: boolean, listId: string };
|
@Input() selectionConfig: { repeatable: boolean, listId: string };
|
||||||
// @Input() previousSelection: ListableObject[] = [];
|
|
||||||
// allSelected = false;
|
|
||||||
// selectAllLoading = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The link type of the listable elements
|
* The link type of the listable elements
|
||||||
|
@@ -55,7 +55,7 @@ export class SelectableListSelectSingleAction extends SelectableListAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action to deselect objects in a the selectable list
|
* Action to deselect a single object in a the selectable list
|
||||||
*/
|
*/
|
||||||
export class SelectableListDeselectSingleAction extends SelectableListAction {
|
export class SelectableListDeselectSingleAction extends SelectableListAction {
|
||||||
payload: ListableObject;
|
payload: ListableObject;
|
||||||
@@ -67,7 +67,7 @@ export class SelectableListDeselectSingleAction extends SelectableListAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action to deselect a single object in a the selectable list
|
* Action to deselect objects in a the selectable list
|
||||||
*/
|
*/
|
||||||
export class SelectableListDeselectAction extends SelectableListAction {
|
export class SelectableListDeselectAction extends SelectableListAction {
|
||||||
payload: ListableObject[];
|
payload: ListableObject[];
|
||||||
|
@@ -14,7 +14,7 @@ import { map } from 'rxjs/operators';
|
|||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component represents the part of the search sidebar that contains the general search settings.
|
* This component represents the part of the search sidebar that contains the page size settings.
|
||||||
*/
|
*/
|
||||||
export class PageSizeSelectorComponent implements OnInit {
|
export class PageSizeSelectorComponent implements OnInit {
|
||||||
/**
|
/**
|
||||||
|
@@ -8,7 +8,7 @@ import { RemoteData } from '../../../core/data/remote-data';
|
|||||||
import { SearchFilterConfig } from '../search-filter-config.model';
|
import { SearchFilterConfig } from '../search-filter-config.model';
|
||||||
import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service';
|
import { SearchConfigurationService } from '../../../core/shared/search/search-configuration.service';
|
||||||
import { SearchFilterService } from '../../../core/shared/search/search-filter.service';
|
import { SearchFilterService } from '../../../core/shared/search/search-filter.service';
|
||||||
import { getSucceededRemoteData, obsLog } from '../../../core/shared/operators';
|
import { getSucceededRemoteData } from '../../../core/shared/operators';
|
||||||
import { SEARCH_CONFIG_SERVICE } from '../../../+my-dspace-page/my-dspace-page.component';
|
import { SEARCH_CONFIG_SERVICE } from '../../../+my-dspace-page/my-dspace-page.component';
|
||||||
import { currentPath } from '../../utils/route.utils';
|
import { currentPath } from '../../utils/route.utils';
|
||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
@@ -4,7 +4,7 @@ import { TranslateModule } from '@ngx-translate/core';
|
|||||||
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
|
import { ChangeDetectionStrategy, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { Observable, of as observableOf } from 'rxjs';
|
import { Observable, of as observableOf } from 'rxjs';
|
||||||
import { Params } from '@angular/router';
|
import { Params, Router } from '@angular/router';
|
||||||
import { SearchLabelComponent } from './search-label.component';
|
import { SearchLabelComponent } from './search-label.component';
|
||||||
import { ObjectKeysPipe } from '../../../utils/object-keys-pipe';
|
import { ObjectKeysPipe } from '../../../utils/object-keys-pipe';
|
||||||
import { SEARCH_CONFIG_SERVICE } from '../../../../+my-dspace-page/my-dspace-page.component';
|
import { SEARCH_CONFIG_SERVICE } from '../../../../+my-dspace-page/my-dspace-page.component';
|
||||||
@@ -39,7 +39,8 @@ describe('SearchLabelComponent', () => {
|
|||||||
declarations: [SearchLabelComponent, ObjectKeysPipe],
|
declarations: [SearchLabelComponent, ObjectKeysPipe],
|
||||||
providers: [
|
providers: [
|
||||||
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
{ provide: SearchService, useValue: new SearchServiceStub(searchLink) },
|
||||||
{ provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() }
|
{ provide: SEARCH_CONFIG_SERVICE, useValue: new SearchConfigurationServiceStub() },
|
||||||
|
{ provide: Router, useValue: {} }
|
||||||
// { provide: SearchConfigurationService, useValue: {getCurrentFrontendFilters : () => observableOf({})} }
|
// { provide: SearchConfigurationService, useValue: {getCurrentFrontendFilters : () => observableOf({})} }
|
||||||
],
|
],
|
||||||
schemas: [NO_ERRORS_SCHEMA]
|
schemas: [NO_ERRORS_SCHEMA]
|
||||||
|
@@ -1,9 +1,10 @@
|
|||||||
import { Component, Input, OnInit } from '@angular/core';
|
import { Component, Input, OnInit } from '@angular/core';
|
||||||
import { Observable } from 'rxjs';
|
import { Observable } from 'rxjs';
|
||||||
import { Params } from '@angular/router';
|
import { Params, Router } from '@angular/router';
|
||||||
import { map } from 'rxjs/operators';
|
import { map } from 'rxjs/operators';
|
||||||
import { hasValue, isNotEmpty } from '../../../empty.util';
|
import { hasValue, isNotEmpty } from '../../../empty.util';
|
||||||
import { SearchService } from '../../../../core/shared/search/search.service';
|
import { SearchService } from '../../../../core/shared/search/search.service';
|
||||||
|
import { currentPath } from '../../../utils/route.utils';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'ds-search-label',
|
selector: 'ds-search-label',
|
||||||
@@ -25,7 +26,8 @@ export class SearchLabelComponent implements OnInit {
|
|||||||
* Initialize the instance variable
|
* Initialize the instance variable
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
private searchService: SearchService) {
|
private searchService: SearchService,
|
||||||
|
private router: Router) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
@@ -55,7 +57,7 @@ export class SearchLabelComponent implements OnInit {
|
|||||||
*/
|
*/
|
||||||
private getSearchLink(): string {
|
private getSearchLink(): string {
|
||||||
if (this.inPlaceSearch) {
|
if (this.inPlaceSearch) {
|
||||||
return './';
|
return currentPath(this.router);
|
||||||
}
|
}
|
||||||
return this.searchService.getSearchLink();
|
return this.searchService.getSearchLink();
|
||||||
}
|
}
|
||||||
|
18
src/app/shared/utils/relation-query.utils.spec.ts
Normal file
18
src/app/shared/utils/relation-query.utils.spec.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import { getFilterByRelation, getQueryByRelations } from './relation-query.utils';
|
||||||
|
|
||||||
|
describe('Relation Query Utils', () => {
|
||||||
|
const relationtype = 'isAuthorOfPublication';
|
||||||
|
const itemUUID = 'a7939af0-36ad-430d-af09-7be8b0a4dadd';
|
||||||
|
describe('getQueryByRelations', () => {
|
||||||
|
it('Should return the correct query based on relationtype and uuid', () => {
|
||||||
|
const result = getQueryByRelations(relationtype, itemUUID);
|
||||||
|
expect(result).toEqual('query=relation.isAuthorOfPublication:a7939af0-36ad-430d-af09-7be8b0a4dadd');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('getFilterByRelation', () => {
|
||||||
|
it('Should return the correct query based on relationtype and uuid', () => {
|
||||||
|
const result = getFilterByRelation(relationtype, itemUUID);
|
||||||
|
expect(result).toEqual('f.isAuthorOfPublication=a7939af0-36ad-430d-af09-7be8b0a4dadd');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
22
src/app/shared/utils/route.utils.spec.ts
Normal file
22
src/app/shared/utils/route.utils.spec.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { currentPath } from './route.utils';
|
||||||
|
|
||||||
|
describe('Route Utils', () => {
|
||||||
|
const urlTree = {
|
||||||
|
root: {
|
||||||
|
children: {
|
||||||
|
primary: {
|
||||||
|
segments: [
|
||||||
|
{ path: 'test' },
|
||||||
|
{ path: 'path' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const router = { parseUrl: () => urlTree } as any;
|
||||||
|
it('Should return the correct current path based on the router', () => {
|
||||||
|
const result = currentPath(router);
|
||||||
|
expect(result).toEqual('/test/path');
|
||||||
|
});
|
||||||
|
});
|
@@ -1,5 +1,9 @@
|
|||||||
import { Router } from '@angular/router';
|
import { Router } from '@angular/router';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Util function to retrieve the current path (without query parameters) the user is on
|
||||||
|
* @param router The router service
|
||||||
|
*/
|
||||||
export function currentPath(router: Router) {
|
export function currentPath(router: Router) {
|
||||||
const urlTree = router.parseUrl(router.url);
|
const urlTree = router.parseUrl(router.url);
|
||||||
return '/' + urlTree.root.children.primary.segments.map((it) => it.path).join('/')
|
return '/' + urlTree.root.children.primary.segments.map((it) => it.path).join('/')
|
||||||
|
@@ -1,4 +1,11 @@
|
|||||||
|
import { ResponseParsingService } from '../core/data/parsing.service';
|
||||||
import { PostRequest } from '../core/data/request.models';
|
import { PostRequest } from '../core/data/request.models';
|
||||||
|
import { StatusCodeOnlyResponseParsingService } from '../core/data/status-code-only-response-parsing.service';
|
||||||
|
import { GenericConstructor } from '../core/shared/generic-constructor';
|
||||||
|
|
||||||
export class TrackRequest extends PostRequest {
|
export class TrackRequest extends PostRequest {
|
||||||
|
|
||||||
|
getResponseParser(): GenericConstructor<ResponseParsingService> {
|
||||||
|
return StatusCodeOnlyResponseParsingService;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -166,8 +166,8 @@ export class SubmissionSectionformComponent extends SectionModelComponent {
|
|||||||
.subscribe(([sectionData, workspaceItem]: [WorkspaceitemSectionFormObject, WorkspaceItem]) => {
|
.subscribe(([sectionData, workspaceItem]: [WorkspaceitemSectionFormObject, WorkspaceItem]) => {
|
||||||
if (isUndefined(this.formModel)) {
|
if (isUndefined(this.formModel)) {
|
||||||
this.sectionData.errors = [];
|
this.sectionData.errors = [];
|
||||||
// Is the first loading so init form
|
|
||||||
this.workspaceItem = workspaceItem;
|
this.workspaceItem = workspaceItem;
|
||||||
|
// Is the first loading so init form
|
||||||
this.initForm(sectionData);
|
this.initForm(sectionData);
|
||||||
this.sectionData.data = sectionData;
|
this.sectionData.data = sectionData;
|
||||||
this.subscriptions();
|
this.subscriptions();
|
||||||
|
Reference in New Issue
Block a user