mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-08 18:44:14 +00:00
[CST-3088] fixed code
This commit is contained in:
@@ -251,7 +251,6 @@ export class AuthInterceptor implements HttpInterceptor {
|
|||||||
|
|
||||||
// Pass on the new request instead of the original request.
|
// Pass on the new request instead of the original request.
|
||||||
return next.handle(newReq).pipe(
|
return next.handle(newReq).pipe(
|
||||||
// tap((response) => console.log('next.handle: ', response)),
|
|
||||||
map((response) => {
|
map((response) => {
|
||||||
// Intercept a Login/Logout response
|
// Intercept a Login/Logout response
|
||||||
if (response instanceof HttpResponse && this.isSuccess(response) && this.isAuthRequest(response)) {
|
if (response instanceof HttpResponse && this.isSuccess(response) && this.isAuthRequest(response)) {
|
||||||
|
@@ -144,6 +144,7 @@ import { Vocabulary } from './submission/vocabularies/models/vocabulary.model';
|
|||||||
import { VocabularyEntriesResponseParsingService } from './submission/vocabularies/vocabulary-entries-response-parsing.service';
|
import { VocabularyEntriesResponseParsingService } from './submission/vocabularies/vocabulary-entries-response-parsing.service';
|
||||||
import { VocabularyEntryDetail } from './submission/vocabularies/models/vocabulary-entry-detail.model';
|
import { VocabularyEntryDetail } from './submission/vocabularies/models/vocabulary-entry-detail.model';
|
||||||
import { VocabularyService } from './submission/vocabularies/vocabulary.service';
|
import { VocabularyService } from './submission/vocabularies/vocabulary.service';
|
||||||
|
import { VocabularyTreeviewService } from '../shared/vocabulary-treeview/vocabulary-treeview.service';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When not in production, endpoint responses can be mocked for testing purposes
|
* When not in production, endpoint responses can be mocked for testing purposes
|
||||||
@@ -268,7 +269,8 @@ const PROVIDERS = [
|
|||||||
FilteredDiscoveryPageResponseParsingService,
|
FilteredDiscoveryPageResponseParsingService,
|
||||||
{ provide: NativeWindowService, useFactory: NativeWindowFactory },
|
{ provide: NativeWindowService, useFactory: NativeWindowFactory },
|
||||||
VocabularyService,
|
VocabularyService,
|
||||||
VocabularyEntriesResponseParsingService
|
VocabularyEntriesResponseParsingService,
|
||||||
|
VocabularyTreeviewService
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -115,12 +115,6 @@ export abstract class DataService<T extends CacheableObject> {
|
|||||||
|
|
||||||
result$ = this.getSearchEndpoint(searchMethod);
|
result$ = this.getSearchEndpoint(searchMethod);
|
||||||
|
|
||||||
if (hasValue(options.searchParams)) {
|
|
||||||
options.searchParams.forEach((param: RequestParam) => {
|
|
||||||
args.push(`${param.fieldName}=${param.fieldValue}`);
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return result$.pipe(map((result: string) => this.buildHrefFromFindOptions(result, options, args, ...linksToFollow)));
|
return result$.pipe(map((result: string) => this.buildHrefFromFindOptions(result, options, args, ...linksToFollow)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -351,7 +345,7 @@ export abstract class DataService<T extends CacheableObject> {
|
|||||||
return hrefObs.pipe(
|
return hrefObs.pipe(
|
||||||
find((href: string) => hasValue(href)),
|
find((href: string) => hasValue(href)),
|
||||||
tap((href: string) => {
|
tap((href: string) => {
|
||||||
this.requestService.removeByHrefSubstring(href);
|
this.requestService.removeByHrefSubstring(searchMethod);
|
||||||
const request = new FindListRequest(this.requestService.generateRequestId(), href, options);
|
const request = new FindListRequest(this.requestService.generateRequestId(), href, options);
|
||||||
if (hasValue(this.responseMsToLive)) {
|
if (hasValue(this.responseMsToLive)) {
|
||||||
request.responseMsToLive = this.responseMsToLive;
|
request.responseMsToLive = this.responseMsToLive;
|
||||||
|
@@ -20,6 +20,7 @@ import { VocabularyService } from './vocabulary.service';
|
|||||||
import { getMockRequestService } from '../../../shared/mocks/request.service.mock';
|
import { getMockRequestService } from '../../../shared/mocks/request.service.mock';
|
||||||
import { getMockRemoteDataBuildService } from '../../../shared/mocks/remote-data-build.service.mock';
|
import { getMockRemoteDataBuildService } from '../../../shared/mocks/remote-data-build.service.mock';
|
||||||
import { VocabularyOptions } from './models/vocabulary-options.model';
|
import { VocabularyOptions } from './models/vocabulary-options.model';
|
||||||
|
import { VocabularyFindOptions } from './models/vocabulary-find-options.model';
|
||||||
|
|
||||||
describe('VocabularyService', () => {
|
describe('VocabularyService', () => {
|
||||||
let scheduler: TestScheduler;
|
let scheduler: TestScheduler;
|
||||||
@@ -208,9 +209,9 @@ describe('VocabularyService', () => {
|
|||||||
const endpointURL = `https://rest.api/rest/api/submission/vocabularies`;
|
const endpointURL = `https://rest.api/rest/api/submission/vocabularies`;
|
||||||
const requestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}`;
|
const requestURL = `https://rest.api/rest/api/submission/vocabularies/${vocabulary.id}`;
|
||||||
const entryDetailEndpointURL = `https://rest.api/rest/api/submission/vocabularyEntryDetails`;
|
const entryDetailEndpointURL = `https://rest.api/rest/api/submission/vocabularyEntryDetails`;
|
||||||
const entryDetailRequestURL = `https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:SCB110/${hierarchicalVocabulary.id}:testValue`;
|
const entryDetailRequestURL = `https://rest.api/rest/api/submission/vocabularyEntryDetails/${hierarchicalVocabulary.id}:testValue`;
|
||||||
const entryDetailParentRequestURL = `https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:SCB110/${hierarchicalVocabulary.id}:testValue/parent`;
|
const entryDetailParentRequestURL = `https://rest.api/rest/api/submission/vocabularyEntryDetails/${hierarchicalVocabulary.id}:testValue/parent`;
|
||||||
const entryDetailChildrenRequestURL = `https://rest.api/rest/api/submission/vocabularyEntryDetails/srsc:SCB110/${hierarchicalVocabulary.id}:testValue/children`;
|
const entryDetailChildrenRequestURL = `https://rest.api/rest/api/submission/vocabularyEntryDetails/${hierarchicalVocabulary.id}:testValue/children`;
|
||||||
const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a';
|
const requestUUID = '8b3c613a-5a4b-438b-9686-be1d5b4a1c5a';
|
||||||
const vocabularyId = 'types';
|
const vocabularyId = 'types';
|
||||||
const metadata = 'dc.type';
|
const metadata = 'dc.type';
|
||||||
@@ -490,7 +491,7 @@ describe('VocabularyService', () => {
|
|||||||
scheduler = getTestScheduler();
|
scheduler = getTestScheduler();
|
||||||
|
|
||||||
halService = jasmine.createSpyObj('halService', {
|
halService = jasmine.createSpyObj('halService', {
|
||||||
getEndpoint: cold('a', { a: endpointURL })
|
getEndpoint: cold('a', { a: entryDetailEndpointURL })
|
||||||
});
|
});
|
||||||
|
|
||||||
responseCacheEntry = new RequestEntry();
|
responseCacheEntry = new RequestEntry();
|
||||||
@@ -517,9 +518,10 @@ describe('VocabularyService', () => {
|
|||||||
spyOn((service as any).vocabularyEntryDetailDataService, 'findById').and.callThrough();
|
spyOn((service as any).vocabularyEntryDetailDataService, 'findById').and.callThrough();
|
||||||
spyOn((service as any).vocabularyEntryDetailDataService, 'findAll').and.callThrough();
|
spyOn((service as any).vocabularyEntryDetailDataService, 'findAll').and.callThrough();
|
||||||
spyOn((service as any).vocabularyEntryDetailDataService, 'findByHref').and.callThrough();
|
spyOn((service as any).vocabularyEntryDetailDataService, 'findByHref').and.callThrough();
|
||||||
|
spyOn((service as any).vocabularyEntryDetailDataService, 'findAllByHref').and.callThrough();
|
||||||
spyOn((service as any).vocabularyEntryDetailDataService, 'searchBy').and.callThrough();
|
spyOn((service as any).vocabularyEntryDetailDataService, 'searchBy').and.callThrough();
|
||||||
spyOn((service as any).vocabularyEntryDetailDataService, 'getSearchByHref').and.returnValue(observableOf(searchRequestURL));
|
spyOn((service as any).vocabularyEntryDetailDataService, 'getSearchByHref').and.returnValue(observableOf(searchRequestURL));
|
||||||
spyOn((service as any).vocabularyEntryDetailDataService, 'getFindAllHref').and.returnValue(observableOf(entriesRequestURL));
|
spyOn((service as any).vocabularyEntryDetailDataService, 'getFindAllHref').and.returnValue(observableOf(entryDetailChildrenRequestURL));
|
||||||
spyOn((service as any).vocabularyEntryDetailDataService, 'getBrowseEndpoint').and.returnValue(observableOf(entryDetailEndpointURL));
|
spyOn((service as any).vocabularyEntryDetailDataService, 'getBrowseEndpoint').and.returnValue(observableOf(entryDetailEndpointURL));
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -528,7 +530,7 @@ describe('VocabularyService', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('findEntryDetailByHref', () => {
|
describe('findEntryDetailByHref', () => {
|
||||||
it('should proxy the call to vocabularyDataService.findVocabularyByHref', () => {
|
it('should proxy the call to vocabularyDataService.findEntryDetailByHref', () => {
|
||||||
scheduler.schedule(() => service.findEntryDetailByHref(entryDetailRequestURL));
|
scheduler.schedule(() => service.findEntryDetailByHref(entryDetailRequestURL));
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
@@ -563,7 +565,7 @@ describe('VocabularyService', () => {
|
|||||||
|
|
||||||
describe('getEntryDetailParent', () => {
|
describe('getEntryDetailParent', () => {
|
||||||
it('should proxy the call to vocabularyDataService.getEntryDetailParent', () => {
|
it('should proxy the call to vocabularyDataService.getEntryDetailParent', () => {
|
||||||
scheduler.schedule(() => service.getEntryDetailParent('testValue', hierarchicalVocabulary.id));
|
scheduler.schedule(() => service.getEntryDetailParent('testValue', hierarchicalVocabulary.id).subscribe());
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect((service as any).vocabularyEntryDetailDataService.findByHref).toHaveBeenCalledWith(entryDetailParentRequestURL);
|
expect((service as any).vocabularyEntryDetailDataService.findByHref).toHaveBeenCalledWith(entryDetailParentRequestURL);
|
||||||
@@ -580,10 +582,20 @@ describe('VocabularyService', () => {
|
|||||||
|
|
||||||
describe('getEntryDetailChildren', () => {
|
describe('getEntryDetailChildren', () => {
|
||||||
it('should proxy the call to vocabularyDataService.getEntryDetailChildren', () => {
|
it('should proxy the call to vocabularyDataService.getEntryDetailChildren', () => {
|
||||||
scheduler.schedule(() => service.getEntryDetailChildren('testValue', hierarchicalVocabulary.id, new PageInfo()));
|
const options: VocabularyFindOptions = new VocabularyFindOptions(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
pageInfo.elementsPerPage,
|
||||||
|
pageInfo.currentPage
|
||||||
|
);
|
||||||
|
scheduler.schedule(() => service.getEntryDetailChildren('testValue', hierarchicalVocabulary.id, pageInfo).subscribe());
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect((service as any).vocabularyEntryDetailDataService.findAllByHref).toHaveBeenCalledWith(entryDetailChildrenRequestURL);
|
expect((service as any).vocabularyEntryDetailDataService.findAllByHref).toHaveBeenCalledWith(entryDetailChildrenRequestURL, options);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return a RemoteData<PaginatedList<ResourcePolicy>> for the object with the given URL', () => {
|
it('should return a RemoteData<PaginatedList<ResourcePolicy>> for the object with the given URL', () => {
|
||||||
@@ -595,9 +607,19 @@ describe('VocabularyService', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('searchByTop', () => {
|
describe('searchByTop', () => {
|
||||||
it('should proxy the call to vocabularyEntryDetailDataService.searchBy', () => {
|
it('should proxy the call to vocabularyEntryDetailDataService.searchBy', () => {
|
||||||
const options = new FindListOptions();
|
const options: VocabularyFindOptions = new VocabularyFindOptions(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
pageInfo.elementsPerPage,
|
||||||
|
pageInfo.currentPage
|
||||||
|
);
|
||||||
options.searchParams = [new RequestParam('vocabulary', 'srsc')];
|
options.searchParams = [new RequestParam('vocabulary', 'srsc')];
|
||||||
scheduler.schedule(() => service.searchTopEntries('srsc', pageInfo));
|
scheduler.schedule(() => service.searchTopEntries('srsc', pageInfo));
|
||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
@@ -615,5 +637,14 @@ describe('VocabularyService', () => {
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('clearSearchTopRequests', () => {
|
||||||
|
it('should remove requests on the data service\'s endpoint', (done) => {
|
||||||
|
service.clearSearchTopRequests();
|
||||||
|
|
||||||
|
expect(requestService.removeByHrefSubstring).toHaveBeenCalledWith(`search/${(service as any).searchTopMethod}`);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -353,10 +353,26 @@ export class VocabularyService {
|
|||||||
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved
|
* @param linksToFollow List of {@link FollowLinkConfig} that indicate which {@link HALLink}s should be automatically resolved
|
||||||
*/
|
*/
|
||||||
searchTopEntries(name: string, pageInfo: PageInfo, ...linksToFollow: Array<FollowLinkConfig<VocabularyEntryDetail>>): Observable<RemoteData<PaginatedList<VocabularyEntryDetail>>> {
|
searchTopEntries(name: string, pageInfo: PageInfo, ...linksToFollow: Array<FollowLinkConfig<VocabularyEntryDetail>>): Observable<RemoteData<PaginatedList<VocabularyEntryDetail>>> {
|
||||||
const options = new FindListOptions();
|
const options: VocabularyFindOptions = new VocabularyFindOptions(
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
pageInfo.elementsPerPage,
|
||||||
|
pageInfo.currentPage
|
||||||
|
);
|
||||||
options.searchParams = [new RequestParam('vocabulary', name)];
|
options.searchParams = [new RequestParam('vocabulary', name)];
|
||||||
return this.vocabularyEntryDetailDataService.searchBy(this.searchTopMethod, options, ...linksToFollow)
|
return this.vocabularyEntryDetailDataService.searchBy(this.searchTopMethod, options, ...linksToFollow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all search Top Requests
|
||||||
|
*/
|
||||||
|
clearSearchTopRequests(): void {
|
||||||
|
this.requestService.removeByHrefSubstring(`search/${this.searchTopMethod}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -59,12 +59,13 @@ export abstract class DsDynamicVocabularyComponent extends DynamicFormControlCom
|
|||||||
}
|
}
|
||||||
initValue$ = initEntry$.pipe(map((initEntry: VocabularyEntry) => {
|
initValue$ = initEntry$.pipe(map((initEntry: VocabularyEntry) => {
|
||||||
if (isNotEmpty(initEntry)) {
|
if (isNotEmpty(initEntry)) {
|
||||||
return new FormFieldMetadataValueObject(
|
// Integrate FormFieldMetadataValueObject with retrieved information
|
||||||
initEntry.value,
|
return Object.assign(new FormFieldMetadataValueObject(), this.model.value, {
|
||||||
null,
|
value: initEntry.value,
|
||||||
initEntry.authority,
|
authority: initEntry.authority,
|
||||||
initEntry.display
|
display: initEntry.display,
|
||||||
);
|
otherInformation: initEntry.otherInformation
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
return this.model.value as any;
|
return this.model.value as any;
|
||||||
}
|
}
|
||||||
|
@@ -20,6 +20,7 @@ import { createTestComponent } from '../../../../../testing/utils.test';
|
|||||||
import { AuthorityConfidenceStateDirective } from '../../../../../authority-confidence/authority-confidence-state.directive';
|
import { AuthorityConfidenceStateDirective } from '../../../../../authority-confidence/authority-confidence-state.directive';
|
||||||
import { ObjNgFor } from '../../../../../utils/object-ngfor.pipe';
|
import { ObjNgFor } from '../../../../../utils/object-ngfor.pipe';
|
||||||
import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
import { VocabularyEntry } from '../../../../../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
|
import { createSuccessfulRemoteDataObject$ } from '../../../../../remote-data.utils';
|
||||||
|
|
||||||
export let TYPEAHEAD_TEST_GROUP;
|
export let TYPEAHEAD_TEST_GROUP;
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ function init() {
|
|||||||
vocabularyOptions: {
|
vocabularyOptions: {
|
||||||
closed: false,
|
closed: false,
|
||||||
metadata: 'typeahead',
|
metadata: 'typeahead',
|
||||||
name: 'EVENTAuthority',
|
name: 'vocabulary',
|
||||||
scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23'
|
scope: 'c1c16450-d56f-41bc-bb81-27f1d1eb5c23'
|
||||||
} as VocabularyOptions,
|
} as VocabularyOptions,
|
||||||
disabled: false,
|
disabled: false,
|
||||||
@@ -50,13 +51,47 @@ function init() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('DsDynamicTypeaheadComponent test suite', () => {
|
fdescribe('DsDynamicTypeaheadComponent test suite', () => {
|
||||||
|
|
||||||
let testComp: TestComponent;
|
let testComp: TestComponent;
|
||||||
let typeaheadComp: DsDynamicTypeaheadComponent;
|
let typeaheadComp: DsDynamicTypeaheadComponent;
|
||||||
let testFixture: ComponentFixture<TestComponent>;
|
let testFixture: ComponentFixture<TestComponent>;
|
||||||
let typeaheadFixture: ComponentFixture<DsDynamicTypeaheadComponent>;
|
let typeaheadFixture: ComponentFixture<DsDynamicTypeaheadComponent>;
|
||||||
|
let service: any;
|
||||||
let html;
|
let html;
|
||||||
|
let vocabulary = {
|
||||||
|
id: 'vocabulary',
|
||||||
|
name: 'vocabulary',
|
||||||
|
scrollable: true,
|
||||||
|
hierarchical: false,
|
||||||
|
preloadLevel: 0,
|
||||||
|
type: 'vocabulary',
|
||||||
|
_links: {
|
||||||
|
self: {
|
||||||
|
url: 'self'
|
||||||
|
},
|
||||||
|
entries: {
|
||||||
|
url: 'entries'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let hierarchicalVocabulary = {
|
||||||
|
id: 'hierarchicalVocabulary',
|
||||||
|
name: 'hierarchicalVocabulary',
|
||||||
|
scrollable: true,
|
||||||
|
hierarchical: true,
|
||||||
|
preloadLevel: 2,
|
||||||
|
type: 'vocabulary',
|
||||||
|
_links: {
|
||||||
|
self: {
|
||||||
|
url: 'self'
|
||||||
|
},
|
||||||
|
entries: {
|
||||||
|
url: 'entries'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// async beforeEach
|
// async beforeEach
|
||||||
beforeEach(async(() => {
|
beforeEach(async(() => {
|
||||||
@@ -113,7 +148,7 @@ describe('DsDynamicTypeaheadComponent test suite', () => {
|
|||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('', () => {
|
describe('not hiearchical', () => {
|
||||||
describe('when init model value is empty', () => {
|
describe('when init model value is empty', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
|
||||||
@@ -121,6 +156,8 @@ describe('DsDynamicTypeaheadComponent test suite', () => {
|
|||||||
typeaheadComp = typeaheadFixture.componentInstance; // FormComponent test instance
|
typeaheadComp = typeaheadFixture.componentInstance; // FormComponent test instance
|
||||||
typeaheadComp.group = TYPEAHEAD_TEST_GROUP;
|
typeaheadComp.group = TYPEAHEAD_TEST_GROUP;
|
||||||
typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG);
|
typeaheadComp.model = new DynamicTypeaheadModel(TYPEAHEAD_TEST_MODEL_CONFIG);
|
||||||
|
service = (typeaheadComp as any).vocabularyService;
|
||||||
|
spyOn(service, 'findVocabularyById').and.returnValue(createSuccessfulRemoteDataObject$(vocabulary));
|
||||||
typeaheadFixture.detectChanges();
|
typeaheadFixture.detectChanges();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -119,7 +119,8 @@ export class DsDynamicTypeaheadComponent extends DsDynamicVocabularyComponent im
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.vocabulary$ = this.vocabularyService.findVocabularyById(this.model.vocabularyOptions.name).pipe(
|
this.vocabulary$ = this.vocabularyService.findVocabularyById(this.model.vocabularyOptions.name).pipe(
|
||||||
getFirstSucceededRemoteDataPayload()
|
getFirstSucceededRemoteDataPayload(),
|
||||||
|
distinctUntilChanged()
|
||||||
);
|
);
|
||||||
|
|
||||||
this.group.get(this.model.id).valueChanges.pipe(
|
this.group.get(this.model.id).valueChanges.pipe(
|
||||||
|
@@ -11,6 +11,7 @@ export interface OtherInformation {
|
|||||||
* A class representing a specific input-form field's value
|
* A class representing a specific input-form field's value
|
||||||
*/
|
*/
|
||||||
export class FormFieldMetadataValueObject implements MetadataValueInterface {
|
export class FormFieldMetadataValueObject implements MetadataValueInterface {
|
||||||
|
metadata?: string;
|
||||||
value: any;
|
value: any;
|
||||||
display: string;
|
display: string;
|
||||||
language: any;
|
language: any;
|
||||||
@@ -43,6 +44,9 @@ export class FormFieldMetadataValueObject implements MetadataValueInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.place = place;
|
this.place = place;
|
||||||
|
if (isNotEmpty(metadata)) {
|
||||||
|
this.metadata = metadata;
|
||||||
|
}
|
||||||
|
|
||||||
this.otherInformation = otherInformation;
|
this.otherInformation = otherInformation;
|
||||||
}
|
}
|
||||||
|
@@ -182,8 +182,8 @@ export abstract class FieldParser {
|
|||||||
fieldIds.forEach((id) => {
|
fieldIds.forEach((id) => {
|
||||||
if (this.initFormValues.hasOwnProperty(id)) {
|
if (this.initFormValues.hasOwnProperty(id)) {
|
||||||
const valueObj: FormFieldMetadataValueObject = Object.assign(new FormFieldMetadataValueObject(), this.initFormValues[id][innerIndex]);
|
const valueObj: FormFieldMetadataValueObject = Object.assign(new FormFieldMetadataValueObject(), this.initFormValues[id][innerIndex]);
|
||||||
// valueObj.metadata = id;
|
// Set metadata name, used for Qualdrop fields
|
||||||
// valueObj.value = this.initFormValues[id][innerIndex];
|
valueObj.metadata = id;
|
||||||
values.push(valueObj);
|
values.push(valueObj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -6,6 +6,7 @@ import { PaginatedList } from '../../core/data/paginated-list';
|
|||||||
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
|
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
|
||||||
import { RemoteData } from '../../core/data/remote-data';
|
import { RemoteData } from '../../core/data/remote-data';
|
||||||
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
|
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
|
||||||
|
import { Vocabulary } from '../../core/submission/vocabularies/models/vocabulary.model';
|
||||||
|
|
||||||
export class VocabularyServiceStub {
|
export class VocabularyServiceStub {
|
||||||
|
|
||||||
@@ -37,4 +38,8 @@ export class VocabularyServiceStub {
|
|||||||
getVocabularyEntryByID(id: string, vocabularyOptions: VocabularyOptions): Observable<VocabularyEntry> {
|
getVocabularyEntryByID(id: string, vocabularyOptions: VocabularyOptions): Observable<VocabularyEntry> {
|
||||||
return observableOf(Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 }));
|
return observableOf(Object.assign(new VocabularyEntry(), { authority: 1, display: 'one', value: 1 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
findVocabularyById(id: string): Observable<RemoteData<Vocabulary>> {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h4 class="modal-title">{{'treeview.header' | translate}}</h4>
|
<h4 class="modal-title">{{'vocabulary-treeview.header' | translate}}</h4>
|
||||||
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
|
<button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('Cross click')">
|
||||||
<span aria-hidden="true">×</span>
|
<span aria-hidden="true">×</span>
|
||||||
</button>
|
</button>
|
||||||
@@ -13,19 +13,19 @@
|
|||||||
<input type="text" class="form-control" [(ngModel)]="searchText" (keyup.enter)="search()">
|
<input type="text" class="form-control" [(ngModel)]="searchText" (keyup.enter)="search()">
|
||||||
<div class="input-group-append" id="button-addon4">
|
<div class="input-group-append" id="button-addon4">
|
||||||
<button class="btn btn-outline-primary" type="button" (click)="search()" [disabled]="!isSearchEnabled()">
|
<button class="btn btn-outline-primary" type="button" (click)="search()" [disabled]="!isSearchEnabled()">
|
||||||
{{'treeview.search.form.search' | translate}}
|
{{'vocabulary-treeview.search.form.search' | translate}}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-outline-secondary" type="button" (click)="reset()">
|
<button class="btn btn-outline-secondary" type="button" (click)="reset()">
|
||||||
{{'treeview.search.form.reset' | translate}}
|
{{'vocabulary-treeview.search.form.reset' | translate}}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="treeview-container">
|
<div class="treeview-container">
|
||||||
<ds-loading *ngIf="searching | async" [showMessage]="false"></ds-loading>
|
<ds-loading *ngIf="loading | async" [showMessage]="false"></ds-loading>
|
||||||
<h4 *ngIf="!(searching | async) && dataSource.data.length === 0" class="text-center text-muted mt-4" >
|
<h4 *ngIf="!(loading | async) && dataSource.data.length === 0" class="text-center text-muted mt-4" >
|
||||||
<span>{{'treeview.search.no-result' | translate}}</span>
|
<span>{{'vocabulary-treeview.search.no-result' | translate}}</span>
|
||||||
</h4>
|
</h4>
|
||||||
<cdk-tree [dataSource]="dataSource" [treeControl]="treeControl">
|
<cdk-tree [dataSource]="dataSource" [treeControl]="treeControl">
|
||||||
<!-- Leaf node -->
|
<!-- Leaf node -->
|
||||||
@@ -62,13 +62,13 @@
|
|||||||
|
|
||||||
<cdk-tree-node *cdkTreeNodeDef="let node; when: isLoadMore" cdkTreeNodePadding>
|
<cdk-tree-node *cdkTreeNodeDef="let node; when: isLoadMore" cdkTreeNodePadding>
|
||||||
<button class="btn btn-outline-secondary btn-sm" (click)="loadMore(node.loadMoreParentItem)">
|
<button class="btn btn-outline-secondary btn-sm" (click)="loadMore(node.loadMoreParentItem)">
|
||||||
{{'treeview.load-more' | translate}}...
|
{{'vocabulary-treeview.load-more' | translate}}...
|
||||||
</button>
|
</button>
|
||||||
</cdk-tree-node>
|
</cdk-tree-node>
|
||||||
|
|
||||||
<cdk-tree-node *cdkTreeNodeDef="let node; when: isLoadMoreRoot">
|
<cdk-tree-node *cdkTreeNodeDef="let node; when: isLoadMoreRoot">
|
||||||
<button class="btn btn-outline-secondary btn-sm" (click)="loadMoreRoot(node)">
|
<button class="btn btn-outline-secondary btn-sm" (click)="loadMoreRoot(node)">
|
||||||
{{'treeview.load-more' | translate}}...
|
{{'vocabulary-treeview.load-more' | translate}}...
|
||||||
</button>
|
</button>
|
||||||
</cdk-tree-node>
|
</cdk-tree-node>
|
||||||
</cdk-tree>
|
</cdk-tree>
|
||||||
|
@@ -16,6 +16,7 @@ import { TreeviewFlatNode } from './vocabulary-treeview-node.model';
|
|||||||
import { FormFieldMetadataValueObject } from '../form/builder/models/form-field-metadata-value.model';
|
import { FormFieldMetadataValueObject } from '../form/builder/models/form-field-metadata-value.model';
|
||||||
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
|
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
|
||||||
import { PageInfo } from '../../core/shared/page-info.model';
|
import { PageInfo } from '../../core/shared/page-info.model';
|
||||||
|
import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
|
|
||||||
describe('VocabularyTreeviewComponent test suite', () => {
|
describe('VocabularyTreeviewComponent test suite', () => {
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ describe('VocabularyTreeviewComponent test suite', () => {
|
|||||||
getData: jasmine.createSpy('getData'),
|
getData: jasmine.createSpy('getData'),
|
||||||
loadMore: jasmine.createSpy('loadMore'),
|
loadMore: jasmine.createSpy('loadMore'),
|
||||||
loadMoreRoot: jasmine.createSpy('loadMoreRoot'),
|
loadMoreRoot: jasmine.createSpy('loadMoreRoot'),
|
||||||
isSearching: jasmine.createSpy('isSearching'),
|
isLoading: jasmine.createSpy('isLoading'),
|
||||||
searchByQuery: jasmine.createSpy('searchByQuery'),
|
searchByQuery: jasmine.createSpy('searchByQuery'),
|
||||||
restoreNodes: jasmine.createSpy('restoreNodes'),
|
restoreNodes: jasmine.createSpy('restoreNodes'),
|
||||||
cleanTree: jasmine.createSpy('cleanTree'),
|
cleanTree: jasmine.createSpy('cleanTree'),
|
||||||
@@ -100,7 +101,7 @@ describe('VocabularyTreeviewComponent test suite', () => {
|
|||||||
comp = fixture.componentInstance;
|
comp = fixture.componentInstance;
|
||||||
compAsAny = comp;
|
compAsAny = comp;
|
||||||
vocabularyTreeviewServiceStub.getData.and.returnValue(observableOf([]));
|
vocabularyTreeviewServiceStub.getData.and.returnValue(observableOf([]));
|
||||||
vocabularyTreeviewServiceStub.isSearching.and.returnValue(observableOf(false));
|
vocabularyTreeviewServiceStub.isLoading.and.returnValue(observableOf(false));
|
||||||
comp.vocabularyOptions = vocabularyOptions;
|
comp.vocabularyOptions = vocabularyOptions;
|
||||||
comp.selectedItem = null;
|
comp.selectedItem = null;
|
||||||
});
|
});
|
||||||
@@ -118,19 +119,27 @@ describe('VocabularyTreeviewComponent test suite', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should should init component properly with init value as FormFieldMetadataValueObject', () => {
|
it('should should init component properly with init value as FormFieldMetadataValueObject', () => {
|
||||||
comp.selectedItem = new FormFieldMetadataValueObject('test', null, 'auth001');
|
const currentValue = new FormFieldMetadataValueObject();
|
||||||
|
currentValue.value = 'testValue';
|
||||||
|
currentValue.otherInformation = {
|
||||||
|
id: 'entryID'
|
||||||
|
};
|
||||||
|
comp.selectedItem = currentValue;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(comp.dataSource.data).toEqual([]);
|
expect(comp.dataSource.data).toEqual([]);
|
||||||
expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), 'auth001');
|
expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), 'entryID');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should should init component properly with init value as AuthorityEntry', () => {
|
it('should should init component properly with init value as VocabularyEntry', () => {
|
||||||
const authority = new VocabularyEntryDetail();
|
const currentValue = new VocabularyEntry();
|
||||||
authority.id = 'auth001';
|
currentValue.value = 'testValue';
|
||||||
comp.selectedItem = authority;
|
currentValue.otherInformation = {
|
||||||
|
id: 'entryID'
|
||||||
|
};
|
||||||
|
comp.selectedItem = currentValue;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
expect(comp.dataSource.data).toEqual([]);
|
expect(comp.dataSource.data).toEqual([]);
|
||||||
expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), 'auth001');
|
expect(vocabularyTreeviewServiceStub.initialize).toHaveBeenCalledWith(comp.vocabularyOptions, new PageInfo(), 'entryID');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call loadMore function', () => {
|
it('should call loadMore function', () => {
|
||||||
|
@@ -16,6 +16,7 @@ import { VocabularyTreeviewService } from './vocabulary-treeview.service';
|
|||||||
import { LOAD_MORE, LOAD_MORE_ROOT, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model';
|
import { LOAD_MORE, LOAD_MORE_ROOT, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model';
|
||||||
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
|
import { VocabularyOptions } from '../../core/submission/vocabularies/models/vocabulary-options.model';
|
||||||
import { PageInfo } from '../../core/shared/page-info.model';
|
import { PageInfo } from '../../core/shared/page-info.model';
|
||||||
|
import { VocabularyEntry } from '../../core/submission/vocabularies/models/vocabulary-entry.model';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that show a hierarchical vocabulary in a tree view
|
* Component that show a hierarchical vocabulary in a tree view
|
||||||
@@ -78,9 +79,9 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit {
|
|||||||
searchText: string;
|
searchText: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A boolean representing if a search operation is pending
|
* A boolean representing if tree is loading
|
||||||
*/
|
*/
|
||||||
searching: Observable<boolean>;
|
loading: Observable<boolean>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An event fired when a vocabulary entry is selected.
|
* An event fired when a vocabulary entry is selected.
|
||||||
@@ -198,7 +199,7 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
const descriptionLabel = 'tree.description.' + this.vocabularyOptions.name;
|
const descriptionLabel = 'vocabulary-treeview.tree.description.' + this.vocabularyOptions.name;
|
||||||
this.description = this.translate.get(descriptionLabel).pipe(
|
this.description = this.translate.get(descriptionLabel).pipe(
|
||||||
filter((msg) => msg !== descriptionLabel),
|
filter((msg) => msg !== descriptionLabel),
|
||||||
startWith('')
|
startWith('')
|
||||||
@@ -207,13 +208,13 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit {
|
|||||||
// set isAuthenticated
|
// set isAuthenticated
|
||||||
this.isAuthenticated = this.store.pipe(select(isAuthenticated));
|
this.isAuthenticated = this.store.pipe(select(isAuthenticated));
|
||||||
|
|
||||||
this.searching = this.vocabularyTreeviewService.isSearching();
|
this.loading = this.vocabularyTreeviewService.isLoading();
|
||||||
|
|
||||||
this.isAuthenticated.pipe(
|
this.isAuthenticated.pipe(
|
||||||
find((isAuth) => isAuth)
|
find((isAuth) => isAuth)
|
||||||
).subscribe(() => {
|
).subscribe(() => {
|
||||||
const valueId: string = (this.selectedItem) ? (this.selectedItem.authority || this.selectedItem.id) : null;
|
const entryId: string = (this.selectedItem) ? this.getEntryId(this.selectedItem) : null;
|
||||||
this.vocabularyTreeviewService.initialize(this.vocabularyOptions, new PageInfo(), valueId);
|
this.vocabularyTreeviewService.initialize(this.vocabularyOptions, new PageInfo(), entryId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,4 +293,11 @@ export class VocabularyTreeviewComponent implements OnDestroy, OnInit {
|
|||||||
.filter((sub) => hasValue(sub))
|
.filter((sub) => hasValue(sub))
|
||||||
.forEach((sub) => sub.unsubscribe());
|
.forEach((sub) => sub.unsubscribe());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return an id for a given {@link VocabularyEntry}
|
||||||
|
*/
|
||||||
|
private getEntryId(entry: VocabularyEntry): string {
|
||||||
|
return entry.authority || entry.otherInformation.id || undefined;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -50,39 +50,47 @@ describe('VocabularyTreeviewService test suite', () => {
|
|||||||
let nodeMapWithChildren: Map<string, TreeviewNode>;
|
let nodeMapWithChildren: Map<string, TreeviewNode>;
|
||||||
let searchNodeMap: Map<string, TreeviewNode>;
|
let searchNodeMap: Map<string, TreeviewNode>;
|
||||||
let vocabularyOptions;
|
let vocabularyOptions;
|
||||||
|
let pageInfo: PageInfo;
|
||||||
|
|
||||||
const vocabularyServiceStub = jasmine.createSpyObj('VocabularyService', {
|
const vocabularyServiceStub = jasmine.createSpyObj('VocabularyService', {
|
||||||
getVocabularyEntriesByValue: jasmine.createSpy('getVocabularyEntriesByValue'),
|
getVocabularyEntriesByValue: jasmine.createSpy('getVocabularyEntriesByValue'),
|
||||||
getEntryDetailParent: jasmine.createSpy('getEntryDetailParent'),
|
getEntryDetailParent: jasmine.createSpy('getEntryDetailParent'),
|
||||||
findEntryDetailByValue: jasmine.createSpy('findEntryDetailByValue'),
|
findEntryDetailByValue: jasmine.createSpy('findEntryDetailByValue'),
|
||||||
searchTopEntries: jasmine.createSpy('searchTopEntries'),
|
searchTopEntries: jasmine.createSpy('searchTopEntries'),
|
||||||
getEntryDetailChildren: jasmine.createSpy('getEntryDetailChildren')
|
getEntryDetailChildren: jasmine.createSpy('getEntryDetailChildren'),
|
||||||
|
clearSearchTopRequests: jasmine.createSpy('clearSearchTopRequests')
|
||||||
});
|
});
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
|
|
||||||
|
pageInfo = Object.assign(new PageInfo(), {
|
||||||
|
elementsPerPage: 1,
|
||||||
|
totalElements: 3,
|
||||||
|
totalPages: 1,
|
||||||
|
currentPage: 1
|
||||||
|
});
|
||||||
loadMoreNode = new TreeviewNode(LOAD_MORE_NODE, false, new PageInfo(), item);
|
loadMoreNode = new TreeviewNode(LOAD_MORE_NODE, false, new PageInfo(), item);
|
||||||
loadMoreRootNode = new TreeviewNode(LOAD_MORE_ROOT_NODE, false, new PageInfo(), null);
|
loadMoreRootNode = new TreeviewNode(LOAD_MORE_ROOT_NODE, false, new PageInfo(), null);
|
||||||
loadMoreRootFlatNode = new TreeviewFlatNode(LOAD_MORE_ROOT_NODE, 1, false, new PageInfo(), null);
|
loadMoreRootFlatNode = new TreeviewFlatNode(LOAD_MORE_ROOT_NODE, 1, false, new PageInfo(), null);
|
||||||
item = new VocabularyEntryDetail();
|
item = new VocabularyEntryDetail();
|
||||||
item.id = item.value = item.display = 'root1';
|
item.id = item.value = item.display = 'root1';
|
||||||
item.otherInformation = { children: 'root1-child1::root1-child2', id: 'root1' };
|
item.otherInformation = { hasChildren: 'true', id: 'root1' };
|
||||||
itemNode = new TreeviewNode(item, true);
|
itemNode = new TreeviewNode(item, true, pageInfo);
|
||||||
searchItemNode = new TreeviewNode(item, true, new PageInfo(), null, true);
|
searchItemNode = new TreeviewNode(item, true, new PageInfo(), null, true);
|
||||||
|
|
||||||
item2 = new VocabularyEntryDetail();
|
item2 = new VocabularyEntryDetail();
|
||||||
item2.id = item2.value = item2.display = 'root2';
|
item2.id = item2.value = item2.display = 'root2';
|
||||||
item2.otherInformation = { id: 'root2' };
|
item2.otherInformation = { id: 'root2' };
|
||||||
itemNode2 = new TreeviewNode(item2);
|
itemNode2 = new TreeviewNode(item2, false, pageInfo);
|
||||||
|
|
||||||
item3 = new VocabularyEntryDetail();
|
item3 = new VocabularyEntryDetail();
|
||||||
item3.id = item3.value = item3.display = 'root3';
|
item3.id = item3.value = item3.display = 'root3';
|
||||||
item3.otherInformation = { id: 'root3' };
|
item3.otherInformation = { id: 'root3' };
|
||||||
itemNode3 = new TreeviewNode(item3);
|
itemNode3 = new TreeviewNode(item3, false, pageInfo);
|
||||||
|
|
||||||
child = new VocabularyEntryDetail();
|
child = new VocabularyEntryDetail();
|
||||||
child.id = child.value = child.display = 'root1-child1';
|
child.id = child.value = child.display = 'root1-child1';
|
||||||
child.otherInformation = { parent: 'root1', children: 'root1-child1-child1', id: 'root1-child1' };
|
child.otherInformation = { parent: 'root1', hasChildren: 'true', id: 'root1-child1' };
|
||||||
childNode = new TreeviewNode(child);
|
childNode = new TreeviewNode(child);
|
||||||
searchChildNode = new TreeviewNode(child, true, new PageInfo(), item, true);
|
searchChildNode = new TreeviewNode(child, true, new PageInfo(), item, true);
|
||||||
|
|
||||||
@@ -167,12 +175,6 @@ describe('VocabularyTreeviewService test suite', () => {
|
|||||||
|
|
||||||
describe('initialize', () => {
|
describe('initialize', () => {
|
||||||
it('should set vocabularyName and call retrieveTopNodes method', () => {
|
it('should set vocabularyName and call retrieveTopNodes method', () => {
|
||||||
const pageInfo = Object.assign(new PageInfo(), {
|
|
||||||
elementsPerPage: 1,
|
|
||||||
totalElements: 3,
|
|
||||||
totalPages: 1,
|
|
||||||
currentPage: 1
|
|
||||||
});
|
|
||||||
serviceAsAny.vocabularyService.searchTopEntries.and.returnValue(hot('-a', {
|
serviceAsAny.vocabularyService.searchTopEntries.and.returnValue(hot('-a', {
|
||||||
a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [item, item2, item3]))
|
a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [item, item2, item3]))
|
||||||
}));
|
}));
|
||||||
@@ -181,16 +183,12 @@ describe('VocabularyTreeviewService test suite', () => {
|
|||||||
scheduler.flush();
|
scheduler.flush();
|
||||||
|
|
||||||
expect(serviceAsAny.vocabularyName).toEqual(vocabularyOptions.name);
|
expect(serviceAsAny.vocabularyName).toEqual(vocabularyOptions.name);
|
||||||
|
expect(serviceAsAny.pageInfo).toEqual(pageInfo);
|
||||||
|
console.log(serviceAsAny.dataChange.value[0].pageInfo, itemNode.pageInfo);
|
||||||
expect(serviceAsAny.dataChange.value).toEqual([itemNode, itemNode2, itemNode3]);
|
expect(serviceAsAny.dataChange.value).toEqual([itemNode, itemNode2, itemNode3]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set initValueHierarchy', () => {
|
it('should set initValueHierarchy', () => {
|
||||||
const pageInfo = Object.assign(new PageInfo(), {
|
|
||||||
elementsPerPage: 1,
|
|
||||||
totalElements: 3,
|
|
||||||
totalPages: 1,
|
|
||||||
currentPage: 1
|
|
||||||
});
|
|
||||||
serviceAsAny.vocabularyService.searchTopEntries.and.returnValue(hot('-c', {
|
serviceAsAny.vocabularyService.searchTopEntries.and.returnValue(hot('-c', {
|
||||||
a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [item, item2, item3]))
|
a: createSuccessfulRemoteDataObject(new PaginatedList(pageInfo, [item, item2, item3]))
|
||||||
}));
|
}));
|
||||||
@@ -239,7 +237,7 @@ describe('VocabularyTreeviewService test suite', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should add children nodes properly', () => {
|
it('should add children nodes properly', () => {
|
||||||
const pageInfo = Object.assign(new PageInfo(), {
|
pageInfo = Object.assign(new PageInfo(), {
|
||||||
elementsPerPage: 1,
|
elementsPerPage: 1,
|
||||||
totalElements: 2,
|
totalElements: 2,
|
||||||
totalPages: 2,
|
totalPages: 2,
|
||||||
@@ -260,7 +258,7 @@ describe('VocabularyTreeviewService test suite', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should add loadMore node properly', () => {
|
it('should add loadMore node properly', () => {
|
||||||
const pageInfo = Object.assign(new PageInfo(), {
|
pageInfo = Object.assign(new PageInfo(), {
|
||||||
elementsPerPage: 1,
|
elementsPerPage: 1,
|
||||||
totalElements: 2,
|
totalElements: 2,
|
||||||
totalPages: 2,
|
totalPages: 2,
|
||||||
@@ -285,7 +283,7 @@ describe('VocabularyTreeviewService test suite', () => {
|
|||||||
|
|
||||||
describe('searchByQuery', () => {
|
describe('searchByQuery', () => {
|
||||||
it('should set tree data properly after a search', () => {
|
it('should set tree data properly after a search', () => {
|
||||||
const pageInfo = Object.assign(new PageInfo(), {
|
pageInfo = Object.assign(new PageInfo(), {
|
||||||
elementsPerPage: 1,
|
elementsPerPage: 1,
|
||||||
totalElements: 1,
|
totalElements: 1,
|
||||||
totalPages: 1,
|
totalPages: 1,
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
|
import { BehaviorSubject, Observable, of as observableOf } from 'rxjs';
|
||||||
import { flatMap, map, merge, scan, take, tap } from 'rxjs/operators';
|
import { flatMap, map, merge, scan } from 'rxjs/operators';
|
||||||
import { findIndex } from 'lodash';
|
import { findIndex } from 'lodash';
|
||||||
|
|
||||||
import { LOAD_MORE_NODE, LOAD_MORE_ROOT_NODE, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model';
|
import { LOAD_MORE_NODE, LOAD_MORE_ROOT_NODE, TreeviewFlatNode, TreeviewNode } from './vocabulary-treeview-node.model';
|
||||||
@@ -56,14 +56,18 @@ export class VocabularyTreeviewService {
|
|||||||
private initValueHierarchy: string[] = [];
|
private initValueHierarchy: string[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A boolean representing if a search operation is pending
|
* A boolean representing if any operation is pending
|
||||||
*/
|
*/
|
||||||
private searching = new BehaviorSubject<boolean>(false);
|
private loading = new BehaviorSubject<boolean>(false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An observable to change the searching status
|
* The {@link PageInfo} object
|
||||||
*/
|
*/
|
||||||
private hideSearchingWhenUnsubscribed$ = new Observable(() => () => this.searching.next(false));
|
private pageInfo: PageInfo;
|
||||||
|
/**
|
||||||
|
* An observable to change the loading status
|
||||||
|
*/
|
||||||
|
private hideSearchingWhenUnsubscribed$ = new Observable(() => () => this.loading.next(false));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize instance variables
|
* Initialize instance variables
|
||||||
@@ -92,8 +96,10 @@ export class VocabularyTreeviewService {
|
|||||||
* @param initValueId The entry id of the node to mark as selected, if any
|
* @param initValueId The entry id of the node to mark as selected, if any
|
||||||
*/
|
*/
|
||||||
initialize(options: VocabularyOptions, pageInfo: PageInfo, initValueId?: string): void {
|
initialize(options: VocabularyOptions, pageInfo: PageInfo, initValueId?: string): void {
|
||||||
|
this.loading.next(true);
|
||||||
this.vocabularyOptions = options;
|
this.vocabularyOptions = options;
|
||||||
this.vocabularyName = options.name;
|
this.vocabularyName = options.name;
|
||||||
|
this.pageInfo = pageInfo;
|
||||||
if (isNotEmpty(initValueId)) {
|
if (isNotEmpty(initValueId)) {
|
||||||
this.getNodeHierarchyById(initValueId)
|
this.getNodeHierarchyById(initValueId)
|
||||||
.subscribe((hierarchy: string[]) => {
|
.subscribe((hierarchy: string[]) => {
|
||||||
@@ -160,17 +166,17 @@ export class VocabularyTreeviewService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a search operation is pending
|
* Check if any operation is pending
|
||||||
*/
|
*/
|
||||||
isSearching(): Observable<boolean> {
|
isLoading(): Observable<boolean> {
|
||||||
return this.searching;
|
return this.loading;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Perform a search operation by query
|
* Perform a search operation by query
|
||||||
*/
|
*/
|
||||||
searchByQuery(query: string) {
|
searchByQuery(query: string) {
|
||||||
this.searching.next(true);
|
this.loading.next(true);
|
||||||
if (isEmpty(this.storedNodes)) {
|
if (isEmpty(this.storedNodes)) {
|
||||||
this.storedNodes = this.dataChange.value;
|
this.storedNodes = this.dataChange.value;
|
||||||
this.storedNodeMap = this.nodeMap;
|
this.storedNodeMap = this.nodeMap;
|
||||||
@@ -192,7 +198,7 @@ export class VocabularyTreeviewService {
|
|||||||
merge(this.hideSearchingWhenUnsubscribed$)
|
merge(this.hideSearchingWhenUnsubscribed$)
|
||||||
).subscribe((nodes: TreeviewNode[]) => {
|
).subscribe((nodes: TreeviewNode[]) => {
|
||||||
this.dataChange.next(nodes);
|
this.dataChange.next(nodes);
|
||||||
this.searching.next(false);
|
this.loading.next(false);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +206,7 @@ export class VocabularyTreeviewService {
|
|||||||
* Reset tree state with the one before the search
|
* Reset tree state with the one before the search
|
||||||
*/
|
*/
|
||||||
restoreNodes() {
|
restoreNodes() {
|
||||||
this.searching.next(false);
|
this.loading.next(false);
|
||||||
this.dataChange.next(this.storedNodes);
|
this.dataChange.next(this.storedNodes);
|
||||||
this.nodeMap = this.storedNodeMap;
|
this.nodeMap = this.storedNodeMap;
|
||||||
|
|
||||||
@@ -224,8 +230,8 @@ export class VocabularyTreeviewService {
|
|||||||
const entryDetail: VocabularyEntryDetail = Object.assign(new VocabularyEntryDetail(), entry, {
|
const entryDetail: VocabularyEntryDetail = Object.assign(new VocabularyEntryDetail(), entry, {
|
||||||
id: entryId
|
id: entryId
|
||||||
});
|
});
|
||||||
const hasChildren = entry.hasOtherInformation() && isNotEmpty((entry.otherInformation as any).children);
|
const hasChildren = entry.hasOtherInformation() && (entry.otherInformation as any)!.hasChildren == 'true';
|
||||||
const pageInfo: PageInfo = new PageInfo();
|
const pageInfo: PageInfo = this.pageInfo;
|
||||||
const isInInitValueHierarchy = this.initValueHierarchy.includes(entryId);
|
const isInInitValueHierarchy = this.initValueHierarchy.includes(entryId);
|
||||||
const result = new TreeviewNode(
|
const result = new TreeviewNode(
|
||||||
entryDetail,
|
entryDetail,
|
||||||
@@ -295,8 +301,10 @@ export class VocabularyTreeviewService {
|
|||||||
this.vocabularyService.searchTopEntries(this.vocabularyName, pageInfo).pipe(
|
this.vocabularyService.searchTopEntries(this.vocabularyName, pageInfo).pipe(
|
||||||
getFirstSucceededRemoteDataPayload()
|
getFirstSucceededRemoteDataPayload()
|
||||||
).subscribe((list: PaginatedList<VocabularyEntryDetail>) => {
|
).subscribe((list: PaginatedList<VocabularyEntryDetail>) => {
|
||||||
const newNodes: TreeviewNode[] = list.page.map((entry: VocabularyEntryDetail) => this._generateNode(entry))
|
this.vocabularyService.clearSearchTopRequests();
|
||||||
|
const newNodes: TreeviewNode[] = list.page.map((entry: VocabularyEntryDetail) => this._generateNode(entry));
|
||||||
nodes.push(...newNodes);
|
nodes.push(...newNodes);
|
||||||
|
|
||||||
if ((list.pageInfo.currentPage + 1) <= list.pageInfo.totalPages) {
|
if ((list.pageInfo.currentPage + 1) <= list.pageInfo.totalPages) {
|
||||||
// Need a new load more node
|
// Need a new load more node
|
||||||
const newPageInfo: PageInfo = Object.assign(new PageInfo(), list.pageInfo, {
|
const newPageInfo: PageInfo = Object.assign(new PageInfo(), list.pageInfo, {
|
||||||
@@ -306,6 +314,7 @@ export class VocabularyTreeviewService {
|
|||||||
loadMoreNode.updatePageInfo(newPageInfo);
|
loadMoreNode.updatePageInfo(newPageInfo);
|
||||||
nodes.push(loadMoreNode);
|
nodes.push(loadMoreNode);
|
||||||
}
|
}
|
||||||
|
this.loading.next(false);
|
||||||
// Notify the change.
|
// Notify the change.
|
||||||
this.dataChange.next(nodes);
|
this.dataChange.next(nodes);
|
||||||
});
|
});
|
||||||
@@ -328,8 +337,7 @@ export class VocabularyTreeviewService {
|
|||||||
if (isNotEmpty(children)) {
|
if (isNotEmpty(children)) {
|
||||||
const newChildren = children
|
const newChildren = children
|
||||||
.filter((entry: TreeviewNode) => {
|
.filter((entry: TreeviewNode) => {
|
||||||
const ii = findIndex(node.children, (nodeEntry) => nodeEntry.item.id === entry.item.id);
|
return findIndex(node.children, (nodeEntry) => nodeEntry.item.id === entry.item.id) === -1;
|
||||||
return ii === -1;
|
|
||||||
});
|
});
|
||||||
newChildren.forEach((entry: TreeviewNode) => {
|
newChildren.forEach((entry: TreeviewNode) => {
|
||||||
entry.loadMoreParentItem = node.item
|
entry.loadMoreParentItem = node.item
|
||||||
|
@@ -2712,6 +2712,24 @@
|
|||||||
"title": "DSpace",
|
"title": "DSpace",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
"vocabulary-treeview.header": "Hierarchical tree view",
|
||||||
|
|
||||||
|
"vocabulary-treeview.load-more": "Load more",
|
||||||
|
|
||||||
|
"vocabulary-treeview.search.form.reset": "Reset",
|
||||||
|
|
||||||
|
"vocabulary-treeview.search.form.search": "Search",
|
||||||
|
|
||||||
|
"vocabulary-treeview.search.no-result": "There were no items to show",
|
||||||
|
|
||||||
|
"vocabulary-treeview.tree.description.nsi": "The Norwegian Science Index",
|
||||||
|
|
||||||
|
"vocabulary-treeview.tree.description.srsc": "Research Subject Categories",
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
"administrativeView.search.results.head": "Administrative Search",
|
"administrativeView.search.results.head": "Administrative Search",
|
||||||
|
|
||||||
"menu.section.admin_search": "Admin Search",
|
"menu.section.admin_search": "Admin Search",
|
||||||
|
Reference in New Issue
Block a user