Merge pull request #845 from atmire/w2p-72444_Support-multiple-dsoType-values-in-discovery

Support multiple dso type values in discovery
This commit is contained in:
Tim Donohue
2020-08-28 09:05:20 -05:00
committed by GitHub
26 changed files with 42 additions and 40 deletions

View File

@@ -133,7 +133,7 @@ export class CollectionItemMapperComponent implements OnInit {
return this.searchService.search(Object.assign(new PaginatedSearchOptions(options), { return this.searchService.search(Object.assign(new PaginatedSearchOptions(options), {
query: this.buildQuery(collectionRD.payload.id, options.query), query: this.buildQuery(collectionRD.payload.id, options.query),
scope: undefined, scope: undefined,
dsoType: DSpaceObjectType.ITEM, dsoTypes: [DSpaceObjectType.ITEM],
sort: this.defaultSortOptions sort: this.defaultSortOptions
}), 10000).pipe( }), 10000).pipe(
toDSpaceObjectListRD(), toDSpaceObjectListRD(),

View File

@@ -87,7 +87,7 @@ export class CollectionPageComponent implements OnInit {
scope: id, scope: id,
pagination: dto.paginationConfig, pagination: dto.paginationConfig,
sort: dto.sortConfig, sort: dto.sortConfig,
dsoType: DSpaceObjectType.ITEM dsoTypes: [DSpaceObjectType.ITEM]
})).pipe(toDSpaceObjectListRD()) as Observable<RemoteData<PaginatedList<Item>>> })).pipe(toDSpaceObjectListRD()) as Observable<RemoteData<PaginatedList<Item>>>
}), }),
startWith(undefined) // Make sure switching pages shows loading component startWith(undefined) // Make sure switching pages shows loading component

View File

@@ -125,7 +125,7 @@ export class ItemCollectionMapperComponent implements OnInit {
switchMap(([itemCollectionsRD, owningCollectionRD, searchOptions]) => { switchMap(([itemCollectionsRD, owningCollectionRD, searchOptions]) => {
return this.searchService.search(Object.assign(new PaginatedSearchOptions(searchOptions), { return this.searchService.search(Object.assign(new PaginatedSearchOptions(searchOptions), {
query: this.buildQuery([...itemCollectionsRD.payload.page, owningCollectionRD.payload], searchOptions.query), query: this.buildQuery([...itemCollectionsRD.payload.page, owningCollectionRD.payload], searchOptions.query),
dsoType: DSpaceObjectType.COLLECTION dsoTypes: [DSpaceObjectType.COLLECTION]
}), 10000).pipe( }), 10000).pipe(
toDSpaceObjectListRD(), toDSpaceObjectListRD(),
startWith(undefined) startWith(undefined)

View File

@@ -79,7 +79,7 @@ export class ItemMoveComponent implements OnInit {
loadSuggestions(query): void { loadSuggestions(query): void {
this.collectionSearchResults = this.searchService.search(new PaginatedSearchOptions({ this.collectionSearchResults = this.searchService.search(new PaginatedSearchOptions({
pagination: this.pagination, pagination: this.pagination,
dsoType: DSpaceObjectType.COLLECTION, dsoTypes: [DSpaceObjectType.COLLECTION],
query: query query: query
})).pipe( })).pipe(
first(), first(),

View File

@@ -2,14 +2,14 @@
<input type="search" <input type="search"
class="form-control" class="form-control"
(click)="$event.stopPropagation();" (click)="$event.stopPropagation();"
placeholder="{{'dso-selector.placeholder' | translate: { type: type.toString().toLowerCase() } }}" placeholder="{{'dso-selector.placeholder' | translate: { type: typesString } }}"
[formControl]="input" dsAutoFocus (keyup.enter)="selectSingleResult()"> [formControl]="input" dsAutoFocus (keyup.enter)="selectSingleResult()">
</div> </div>
<div class="dropdown-divider"></div> <div class="dropdown-divider"></div>
<div class="scrollable-menu list-group"> <div class="scrollable-menu list-group">
<button class="list-group-item list-group-item-action border-0 disabled" <button class="list-group-item list-group-item-action border-0 disabled"
*ngIf="(listEntries$ | async)?.payload.page.length == 0"> *ngIf="(listEntries$ | async)?.payload.page.length == 0">
{{'dso-selector.no-results' | translate: { type: type.toString().toLowerCase() } }} {{'dso-selector.no-results' | translate: { type: typesString } }}
</button> </button>
<button *ngFor="let listEntry of (listEntries$ | async)?.payload.page" <button *ngFor="let listEntry of (listEntries$ | async)?.payload.page"
class="list-group-item list-group-item-action border-0 list-entry" class="list-group-item list-group-item-action border-0 list-entry"

View File

@@ -49,7 +49,7 @@ describe('DSOSelectorComponent', () => {
component = fixture.componentInstance; component = fixture.componentInstance;
debugElement = fixture.debugElement; debugElement = fixture.debugElement;
component.currentDSOId = currentDSOId; component.currentDSOId = currentDSOId;
component.type = type; component.types = [type];
fixture.detectChanges(); fixture.detectChanges();
}); });
@@ -61,7 +61,7 @@ describe('DSOSelectorComponent', () => {
it('should initially call the search method on the SearchService with the given DSO uuid', () => { it('should initially call the search method on the SearchService with the given DSO uuid', () => {
const searchOptions = new PaginatedSearchOptions({ const searchOptions = new PaginatedSearchOptions({
query: currentDSOId, query: currentDSOId,
dsoType: type, dsoTypes: [type],
pagination: (component as any).defaultPagination pagination: (component as any).defaultPagination
}); });

View File

@@ -43,9 +43,12 @@ export class DSOSelectorComponent implements OnInit {
@Input() currentDSOId: string; @Input() currentDSOId: string;
/** /**
* The type of DSpace objects this components shows a list of * The types of DSpace objects this components shows a list of
*/ */
@Input() type: DSpaceObjectType; @Input() types: DSpaceObjectType[];
// list of allowed selectable dsoTypes
typesString: string;
/** /**
* Emits the selected Object when a user selects it in the list * Emits the selected Object when a user selects it in the list
@@ -91,6 +94,7 @@ export class DSOSelectorComponent implements OnInit {
*/ */
ngOnInit(): void { ngOnInit(): void {
this.input.setValue(this.currentDSOId); this.input.setValue(this.currentDSOId);
this.typesString = this.types.map((type: string) => type.toString().toLowerCase()).join(', ');
this.listEntries$ = this.input.valueChanges this.listEntries$ = this.input.valueChanges
.pipe( .pipe(
debounceTime(this.debounceTime), debounceTime(this.debounceTime),
@@ -99,7 +103,7 @@ export class DSOSelectorComponent implements OnInit {
return this.searchService.search( return this.searchService.search(
new PaginatedSearchOptions({ new PaginatedSearchOptions({
query: query, query: query,
dsoType: this.type !== DSpaceObjectType.DSPACEOBJECT ? this.type : null, dsoTypes: this.types,
pagination: this.defaultPagination pagination: this.defaultPagination
}) })
) )

View File

@@ -20,7 +20,7 @@ import { DSOSelectorModalWrapperComponent, SelectorActionType } from '../dso-sel
}) })
export class CreateCollectionParentSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { export class CreateCollectionParentSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit {
objectType = DSpaceObjectType.COLLECTION; objectType = DSpaceObjectType.COLLECTION;
selectorType = DSpaceObjectType.COMMUNITY; selectorTypes = [DSpaceObjectType.COMMUNITY];
action = SelectorActionType.CREATE; action = SelectorActionType.CREATE;
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {

View File

@@ -14,6 +14,6 @@
</h3> </h3>
<h5 class="px-2">{{'dso-selector.create.community.sub-level' | translate}}</h5> <h5 class="px-2">{{'dso-selector.create.community.sub-level' | translate}}</h5>
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [type]="selectorType" (onSelect)="selectObject($event)"></ds-dso-selector> <ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
</div> </div>
</div> </div>

View File

@@ -27,7 +27,7 @@ import {
}) })
export class CreateCommunityParentSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { export class CreateCommunityParentSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit {
objectType = DSpaceObjectType.COMMUNITY; objectType = DSpaceObjectType.COMMUNITY;
selectorType = DSpaceObjectType.COMMUNITY; selectorTypes = [DSpaceObjectType.COMMUNITY];
action = SelectorActionType.CREATE; action = SelectorActionType.CREATE;
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {

View File

@@ -18,7 +18,7 @@ import { DSOSelectorModalWrapperComponent, SelectorActionType } from '../dso-sel
}) })
export class CreateItemParentSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { export class CreateItemParentSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit {
objectType = DSpaceObjectType.ITEM; objectType = DSpaceObjectType.ITEM;
selectorType = DSpaceObjectType.COLLECTION; selectorTypes = [DSpaceObjectType.COLLECTION];
action = SelectorActionType.CREATE; action = SelectorActionType.CREATE;
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {

View File

@@ -5,6 +5,6 @@
</button> </button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid ? 'search.resourceid:' + dsoRD?.payload.uuid : null" [type]="selectorType" (onSelect)="selectObject($event)"></ds-dso-selector> <ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid ? 'search.resourceid:' + dsoRD?.payload.uuid : null" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
</div> </div>
</div> </div>

View File

@@ -124,7 +124,7 @@ describe('DSOSelectorModalWrapperComponent', () => {
}) })
class TestComponent extends DSOSelectorModalWrapperComponent implements OnInit { class TestComponent extends DSOSelectorModalWrapperComponent implements OnInit {
objectType = DSpaceObjectType.ITEM; objectType = DSpaceObjectType.ITEM;
selectorType = DSpaceObjectType.ITEM; selectorTypes = [DSpaceObjectType.ITEM];
action = SelectorActionType.EDIT; action = SelectorActionType.EDIT;
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute) { constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute) {

View File

@@ -29,9 +29,9 @@ export abstract class DSOSelectorModalWrapperComponent implements OnInit {
objectType: DSpaceObjectType; objectType: DSpaceObjectType;
/** /**
* The type of DSO that can be selected from this list * The types of DSO that can be selected from this list
*/ */
selectorType: DSpaceObjectType; selectorTypes: DSpaceObjectType[];
/** /**
* The type of action to perform * The type of action to perform

View File

@@ -20,7 +20,7 @@ import {
}) })
export class EditCollectionSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { export class EditCollectionSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit {
objectType = DSpaceObjectType.COLLECTION; objectType = DSpaceObjectType.COLLECTION;
selectorType = DSpaceObjectType.COLLECTION; selectorTypes = [DSpaceObjectType.COLLECTION];
action = SelectorActionType.EDIT; action = SelectorActionType.EDIT;
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {

View File

@@ -21,7 +21,7 @@ import {
export class EditCommunitySelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { export class EditCommunitySelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit {
objectType = DSpaceObjectType.COMMUNITY; objectType = DSpaceObjectType.COMMUNITY;
selectorType = DSpaceObjectType.COMMUNITY; selectorTypes = [DSpaceObjectType.COMMUNITY];
action = SelectorActionType.EDIT; action = SelectorActionType.EDIT;
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {

View File

@@ -17,7 +17,7 @@ import { DSOSelectorModalWrapperComponent, SelectorActionType } from '../dso-sel
}) })
export class EditItemSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { export class EditItemSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit {
objectType = DSpaceObjectType.ITEM; objectType = DSpaceObjectType.ITEM;
selectorType = DSpaceObjectType.ITEM; selectorTypes = [DSpaceObjectType.ITEM];
action = SelectorActionType.EDIT; action = SelectorActionType.EDIT;
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) { constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router) {

View File

@@ -130,9 +130,8 @@ describe('ExportMetadataSelectorComponent', () => {
done() done()
}); });
}); });
it('should show error notification', () => { it('should not invoke metadata-export script', () => {
expect(notificationService.error).toHaveBeenCalled(); expect(scriptService.invoke).not.toHaveBeenCalled();
expect(scriptRequestSucceeded).toBeFalse();
}); });
}); });

View File

@@ -28,7 +28,7 @@ import { DSOSelectorModalWrapperComponent, SelectorActionType } from '../dso-sel
}) })
export class ExportMetadataSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit { export class ExportMetadataSelectorComponent extends DSOSelectorModalWrapperComponent implements OnInit {
objectType = DSpaceObjectType.DSPACEOBJECT; objectType = DSpaceObjectType.DSPACEOBJECT;
selectorType = DSpaceObjectType.DSPACEOBJECT; selectorTypes = [DSpaceObjectType.COLLECTION, DSpaceObjectType.COMMUNITY];
action = SelectorActionType.EXPORT_METADATA; action = SelectorActionType.EXPORT_METADATA;
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router, constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute, private router: Router,
@@ -66,7 +66,6 @@ export class ExportMetadataSelectorComponent extends DSOSelectorModalWrapperComp
resp$.subscribe(); resp$.subscribe();
return resp$; return resp$;
} else { } else {
this.notificationsService.error(this.translationService.get('dso-selector.export-metadata.notValidDSO'));
return observableOf(false); return observableOf(false);
} }
} }

View File

@@ -13,7 +13,7 @@ describe('PaginatedSearchOptions', () => {
const scope = '0fde1ecb-82cc-425a-b600-ac3576d76b47'; const scope = '0fde1ecb-82cc-425a-b600-ac3576d76b47';
const baseUrl = 'www.rest.com'; const baseUrl = 'www.rest.com';
beforeEach(() => { beforeEach(() => {
options = new PaginatedSearchOptions({sort: sortOptions, pagination: pageOptions, filters: filters, query: query, scope: scope, dsoType: DSpaceObjectType.ITEM}); options = new PaginatedSearchOptions({sort: sortOptions, pagination: pageOptions, filters: filters, query: query, scope: scope, dsoTypes: [DSpaceObjectType.ITEM]});
}); });
describe('when toRestUrl is called', () => { describe('when toRestUrl is called', () => {

View File

@@ -12,7 +12,7 @@ export class PaginatedSearchOptions extends SearchOptions {
pagination?: PaginationComponentOptions; pagination?: PaginationComponentOptions;
sort?: SortOptions; sort?: SortOptions;
constructor(options: {configuration?: string, scope?: string, query?: string, dsoType?: DSpaceObjectType, filters?: SearchFilter[], fixedFilter?: any, pagination?: PaginationComponentOptions, sort?: SortOptions}) { constructor(options: {configuration?: string, scope?: string, query?: string, dsoTypes?: DSpaceObjectType[], filters?: SearchFilter[], fixedFilter?: any, pagination?: PaginationComponentOptions, sort?: SortOptions}) {
super(options); super(options);
this.pagination = options.pagination; this.pagination = options.pagination;
this.sort = options.sort; this.sort = options.sort;

View File

@@ -10,7 +10,7 @@ describe('SearchOptions', () => {
const scope = '0fde1ecb-82cc-425a-b600-ac3576d76b47'; const scope = '0fde1ecb-82cc-425a-b600-ac3576d76b47';
const baseUrl = 'www.rest.com'; const baseUrl = 'www.rest.com';
beforeEach(() => { beforeEach(() => {
options = new SearchOptions({ filters: filters, query: query, scope: scope , dsoType: DSpaceObjectType.ITEM}); options = new SearchOptions({ filters: filters, query: query, scope: scope , dsoTypes: [DSpaceObjectType.ITEM]});
}); });
describe('when toRestUrl is called', () => { describe('when toRestUrl is called', () => {

View File

@@ -12,15 +12,15 @@ export class SearchOptions {
view?: ViewMode = ViewMode.ListElement; view?: ViewMode = ViewMode.ListElement;
scope?: string; scope?: string;
query?: string; query?: string;
dsoType?: DSpaceObjectType; dsoTypes?: DSpaceObjectType[];
filters?: any; filters?: any;
fixedFilter?: any; fixedFilter?: any;
constructor(options: {configuration?: string, scope?: string, query?: string, dsoType?: DSpaceObjectType, filters?: SearchFilter[], fixedFilter?: any}) { constructor(options: {configuration?: string, scope?: string, query?: string, dsoTypes?: DSpaceObjectType[], filters?: SearchFilter[], fixedFilter?: any}) {
this.configuration = options.configuration; this.configuration = options.configuration;
this.scope = options.scope; this.scope = options.scope;
this.query = options.query; this.query = options.query;
this.dsoType = options.dsoType; this.dsoTypes = options.dsoTypes;
this.filters = options.filters; this.filters = options.filters;
this.fixedFilter = options.fixedFilter; this.fixedFilter = options.fixedFilter;
} }
@@ -44,8 +44,10 @@ export class SearchOptions {
if (isNotEmpty(this.scope)) { if (isNotEmpty(this.scope)) {
args.push(`scope=${this.scope}`); args.push(`scope=${this.scope}`);
} }
if (isNotEmpty(this.dsoType)) { if (isNotEmpty(this.dsoTypes)) {
args.push(`dsoType=${this.dsoType}`); this.dsoTypes.forEach((dsoType: string) => {
args.push(`dsoType=${dsoType}`);
})
} }
if (isNotEmpty(this.filters)) { if (isNotEmpty(this.filters)) {
this.filters.forEach((filter: SearchFilter) => { this.filters.forEach((filter: SearchFilter) => {

View File

@@ -82,7 +82,7 @@ describe('StatisticsService', () => {
const mockSearch: any = new SearchOptions({ const mockSearch: any = new SearchOptions({
query: 'mock-query', query: 'mock-query',
configuration: 'mock-configuration', configuration: 'mock-configuration',
dsoType: DSpaceObjectType.ITEM, dsoTypes: [DSpaceObjectType.ITEM],
scope: 'mock-scope' scope: 'mock-scope'
}); });

View File

@@ -68,8 +68,8 @@ export class StatisticsService {
if (hasValue(searchOptions.configuration)) { if (hasValue(searchOptions.configuration)) {
Object.assign(body, { configuration: searchOptions.configuration }) Object.assign(body, { configuration: searchOptions.configuration })
} }
if (hasValue(searchOptions.dsoType)) { if (isNotEmpty(searchOptions.dsoTypes)) {
Object.assign(body, { dsoType: searchOptions.dsoType.toLowerCase() }) Object.assign(body, { dsoType: searchOptions.dsoTypes[0].toLowerCase() })
} }
if (hasValue(searchOptions.scope)) { if (hasValue(searchOptions.scope)) {
Object.assign(body, { scope: searchOptions.scope }) Object.assign(body, { scope: searchOptions.scope })

View File

@@ -989,8 +989,6 @@
"dso-selector.export-metadata.dspaceobject.head": "Export metadata from", "dso-selector.export-metadata.dspaceobject.head": "Export metadata from",
"dso-selector.export-metadata.notValidDSO": "You can only export metadata for collections and communities",
"dso-selector.no-results": "No {{ type }} found", "dso-selector.no-results": "No {{ type }} found",
"dso-selector.placeholder": "Search for a {{ type }}", "dso-selector.placeholder": "Search for a {{ type }}",