mirror of
https://github.com/DSpace/dspace-angular.git
synced 2025-10-07 01:54:15 +00:00
Added search scope lookup to replace dropdown
This commit is contained in:
@@ -8,52 +8,6 @@ describe('Search Page', () => {
|
||||
cy.get(SEARCHFORM_ID + ' input[name="query"]').should('have.value', queryString);
|
||||
});
|
||||
|
||||
|
||||
it('should have right scope selected when navigating to page with scope parameter', () => {
|
||||
// First, visit search with no params just to get the set of the scope options
|
||||
cy.visit('/search');
|
||||
cy.get(SEARCHFORM_ID + ' select[name="scope"] > option').as('options');
|
||||
|
||||
// Find length of scope options, select a random index
|
||||
cy.get('@options').its('length')
|
||||
.then(len => Math.floor(Math.random() * Math.floor(len)))
|
||||
.then((index) => {
|
||||
// return the option at that (randomly selected) index
|
||||
return cy.get('@options').eq(index);
|
||||
})
|
||||
.then((option) => {
|
||||
const randomScope: any = option.val();
|
||||
// Visit the search page with the randomly selected option as a pararmeter
|
||||
cy.visit('/search?scope=' + randomScope);
|
||||
// Verify that scope is selected when the page reloads
|
||||
cy.get(SEARCHFORM_ID + ' select[name="scope"]').find('option:selected').should('have.value', randomScope);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
it('should redirect to the correct url when scope was set and submit button was triggered', () => {
|
||||
// First, visit search with no params just to get the set of scope options
|
||||
cy.visit('/search');
|
||||
cy.get(SEARCHFORM_ID + ' select[name="scope"] > option').as('options');
|
||||
|
||||
// Find length of scope options, select a random index (i.e. a random option in selectbox)
|
||||
cy.get('@options').its('length')
|
||||
.then(len => Math.floor(Math.random() * Math.floor(len)))
|
||||
.then((index) => {
|
||||
// return the option at that (randomly selected) index
|
||||
return cy.get('@options').eq(index);
|
||||
})
|
||||
.then((option) => {
|
||||
const randomScope: any = option.val();
|
||||
// Select the option at our random index & click the search button
|
||||
cy.get(SEARCHFORM_ID + ' select[name="scope"]').select(randomScope);
|
||||
cy.get(SEARCHFORM_ID + ' button.search-button').click();
|
||||
// Result should be the page URL should include that scope & page will reload with scope selected
|
||||
cy.url().should('include', 'scope=' + randomScope);
|
||||
cy.get(SEARCHFORM_ID + ' select[name="scope"]').find('option:selected').should('have.value', randomScope);
|
||||
});
|
||||
});
|
||||
|
||||
it('should redirect to the correct url when query was set and submit button was triggered', () => {
|
||||
const queryString = 'Another interesting query string';
|
||||
cy.visit('/search');
|
||||
@@ -62,5 +16,4 @@ describe('Search Page', () => {
|
||||
cy.get(SEARCHFORM_ID + ' button.search-button').click();
|
||||
cy.url().should('include', 'query=' + encodeURI(queryString));
|
||||
});
|
||||
|
||||
});
|
||||
|
@@ -395,48 +395,6 @@ export class SearchService implements OnDestroy {
|
||||
return this.rdb.buildFromHref(href);
|
||||
}
|
||||
|
||||
/**
|
||||
* Request a list of DSpaceObjects that can be used as a scope, based on the current scope
|
||||
* @param {string} scopeId UUID of the current scope, if the scope is empty, the repository wide scopes will be returned
|
||||
* @returns {Observable<DSpaceObject[]>} Emits a list of DSpaceObjects which represent possible scopes
|
||||
*/
|
||||
getScopes(scopeId?: string): Observable<DSpaceObject[]> {
|
||||
|
||||
if (isEmpty(scopeId)) {
|
||||
const top: Observable<Community[]> = this.communityService.findTop({ elementsPerPage: 9999 }).pipe(
|
||||
getFirstSucceededRemoteData(),
|
||||
map(
|
||||
(communities: RemoteData<PaginatedList<Community>>) => communities.payload.page
|
||||
)
|
||||
);
|
||||
return top;
|
||||
}
|
||||
|
||||
const scopeObject: Observable<RemoteData<DSpaceObject>> = this.dspaceObjectService.findById(scopeId).pipe(getFirstSucceededRemoteData());
|
||||
const scopeList: Observable<DSpaceObject[]> = scopeObject.pipe(
|
||||
switchMap((dsoRD: RemoteData<DSpaceObject>) => {
|
||||
if ((dsoRD.payload as any).type === Community.type.value) {
|
||||
const community: Community = dsoRD.payload as Community;
|
||||
this.linkService.resolveLinks(community, followLink('subcommunities'), followLink('collections'));
|
||||
return observableCombineLatest([
|
||||
community.subcommunities.pipe(getFirstCompletedRemoteData()),
|
||||
community.collections.pipe(getFirstCompletedRemoteData())
|
||||
]).pipe(
|
||||
map(([subCommunities, collections]) => {
|
||||
/*if this is a community, we also need to show the direct children*/
|
||||
return [community, ...subCommunities.payload.page, ...collections.payload.page];
|
||||
})
|
||||
);
|
||||
} else {
|
||||
return observableOf([dsoRD.payload]);
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
return scopeList;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the current view mode based on the current URL
|
||||
* @returns {Observable<ViewMode>} The current view mode
|
||||
|
@@ -15,7 +15,7 @@
|
||||
[query]="(searchOptions$ | async)?.query"
|
||||
[scope]="(searchOptions$ | async)?.scope"
|
||||
[currentUrl]="getSearchLink()"
|
||||
[scopes]="(scopeListRD$ | async)"
|
||||
[showScopeSelector]="true"
|
||||
[inPlaceSearch]="inPlaceSearch"
|
||||
[searchPlaceholder]="'mydspace.search-form.placeholder' | translate">
|
||||
</ds-search-form>
|
||||
|
@@ -78,11 +78,6 @@ export class MyDSpacePageComponent implements OnInit {
|
||||
*/
|
||||
sortOptions$: Observable<SortOptions[]>;
|
||||
|
||||
/**
|
||||
* The current relevant scopes
|
||||
*/
|
||||
scopeListRD$: Observable<DSpaceObject[]>;
|
||||
|
||||
/**
|
||||
* Emits true if were on a small screen
|
||||
*/
|
||||
@@ -144,10 +139,6 @@ export class MyDSpacePageComponent implements OnInit {
|
||||
this.resultsRD$.next(results);
|
||||
});
|
||||
|
||||
this.scopeListRD$ = this.searchConfigService.getCurrentScope('').pipe(
|
||||
switchMap((scopeId) => this.service.getScopes(scopeId))
|
||||
);
|
||||
|
||||
this.context$ = this.searchConfigService.getCurrentConfiguration('workspace')
|
||||
.pipe(
|
||||
map((configuration: string) => {
|
||||
|
@@ -47,7 +47,7 @@
|
||||
[query]="(searchOptions$ | async)?.query"
|
||||
[scope]="(searchOptions$ | async)?.scope"
|
||||
[currentUrl]="searchLink"
|
||||
[scopes]="(scopeListRD$ | async)"
|
||||
[showScopeSelector]="true"
|
||||
[inPlaceSearch]="inPlaceSearch"
|
||||
[searchPlaceholder]="'search.search-form.placeholder' | translate">
|
||||
</ds-search-form>
|
||||
|
@@ -55,11 +55,6 @@ export class SearchComponent implements OnInit {
|
||||
*/
|
||||
sortOptions$: Observable<SortOptions[]>;
|
||||
|
||||
/**
|
||||
* The current relevant scopes
|
||||
*/
|
||||
scopeListRD$: Observable<DSpaceObject[]>;
|
||||
|
||||
/**
|
||||
* Emits true if were on a small screen
|
||||
*/
|
||||
@@ -137,9 +132,7 @@ export class SearchComponent implements OnInit {
|
||||
).subscribe((results) => {
|
||||
this.resultsRD$.next(results);
|
||||
});
|
||||
this.scopeListRD$ = this.searchConfigService.getCurrentScope('').pipe(
|
||||
switchMap((scopeId) => this.service.getScopes(scopeId))
|
||||
);
|
||||
|
||||
if (isEmpty(this.configuration$)) {
|
||||
this.configuration$ = this.searchConfigService.getCurrentConfiguration('default');
|
||||
}
|
||||
|
@@ -9,7 +9,8 @@ import { hasValue, isNotEmpty } from '../../empty.util';
|
||||
export enum SelectorActionType {
|
||||
CREATE = 'create',
|
||||
EDIT = 'edit',
|
||||
EXPORT_METADATA = 'export-metadata'
|
||||
EXPORT_METADATA = 'export-metadata',
|
||||
SET_SCOPE = 'set-scope'
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,6 +78,7 @@ export abstract class DSOSelectorModalWrapperComponent implements OnInit {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called when an object has been selected
|
||||
* @param dso The selected DSpaceObject
|
||||
|
@@ -0,0 +1,19 @@
|
||||
<div>
|
||||
<div class="modal-header">{{'dso-selector.'+ action + '.' + objectType.toString().toLowerCase() + '.head' | translate}}
|
||||
<button type="button" class="close" (click)="selectObject(undefined)" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<button class="btn btn-outline-primary btn-lg btn-block" (click)="selectObject(undefined)">{{'dso-selector.' + action + '.' + objectType.toString().toLowerCase() + '.button'| translate }}</button>
|
||||
<h3 class="position-relative py-1 my-3 font-weight-normal">
|
||||
<hr>
|
||||
<div id="create-community-or-separator" class="text-center position-absolute w-100">
|
||||
<span class="px-4 bg-white">or</span>
|
||||
</div>
|
||||
</h3>
|
||||
|
||||
<h5 class="px-2">{{'dso-selector.' + action + '.' + objectType.toString().toLowerCase() + '.input-header' | translate}}</h5>
|
||||
<ds-dso-selector [currentDSOId]="dsoRD?.payload.uuid" [types]="selectorTypes" (onSelect)="selectObject($event)"></ds-dso-selector>
|
||||
</div>
|
||||
</div>
|
@@ -0,0 +1,3 @@
|
||||
#create-community-or-separator {
|
||||
top: 0;
|
||||
}
|
@@ -0,0 +1,73 @@
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { DebugElement, NO_ERRORS_SCHEMA } from '@angular/core';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { ScopeSelectorModalComponent } from './scope-selector-modal.component';
|
||||
import { Community } from '../../../core/shared/community.model';
|
||||
import { MetadataValue } from '../../../core/shared/metadata.models';
|
||||
import { createSuccessfulRemoteDataObject } from '../../remote-data.utils';
|
||||
import { RouterStub } from '../../testing/router.stub';
|
||||
|
||||
describe('ScopeSelectorModalComponent', () => {
|
||||
let component: ScopeSelectorModalComponent;
|
||||
let fixture: ComponentFixture<ScopeSelectorModalComponent>;
|
||||
let debugElement: DebugElement;
|
||||
|
||||
const community = new Community();
|
||||
community.uuid = '1234-1234-1234-1234';
|
||||
community.metadata = {
|
||||
'dc.title': [Object.assign(new MetadataValue(), {
|
||||
value: 'Community title',
|
||||
language: undefined
|
||||
})]
|
||||
};
|
||||
const router = new RouterStub();
|
||||
const communityRD = createSuccessfulRemoteDataObject(community);
|
||||
const modalStub = jasmine.createSpyObj('modalStub', ['close']);
|
||||
|
||||
beforeEach(waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [TranslateModule.forRoot()],
|
||||
declarations: [ScopeSelectorModalComponent],
|
||||
providers: [
|
||||
{ provide: NgbActiveModal, useValue: modalStub },
|
||||
{
|
||||
provide: ActivatedRoute,
|
||||
useValue: {
|
||||
root: {
|
||||
snapshot: {
|
||||
data: {
|
||||
dso: communityRD,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
provide: Router, useValue: router
|
||||
}
|
||||
],
|
||||
schemas: [NO_ERRORS_SCHEMA]
|
||||
}).compileComponents();
|
||||
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ScopeSelectorModalComponent);
|
||||
component = fixture.componentInstance;
|
||||
debugElement = fixture.debugElement;
|
||||
fixture.detectChanges();
|
||||
spyOn(component.scopeChange, 'emit');
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should call navigate on the router with the correct edit path when navigate is called', () => {
|
||||
component.navigate(community);
|
||||
expect(component.scopeChange.emit).toHaveBeenCalledWith(community);
|
||||
});
|
||||
|
||||
});
|
@@ -0,0 +1,34 @@
|
||||
import { Component, EventEmitter, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { DSpaceObjectType } from '../../../core/shared/dspace-object-type.model';
|
||||
import { DSOSelectorModalWrapperComponent, SelectorActionType } from '../../dso-selector/modal-wrappers/dso-selector-modal-wrapper.component';
|
||||
import { DSpaceObject } from '../../../core/shared/dspace-object.model';
|
||||
|
||||
/**
|
||||
* Component to wrap a button - for top communities -
|
||||
* and a list of parent communities - for sub communities
|
||||
* inside a modal
|
||||
* Used to create a new community
|
||||
*/
|
||||
|
||||
@Component({
|
||||
selector: 'ds-scope-selector-modal',
|
||||
styleUrls: ['./scope-selector-modal.component.scss'],
|
||||
templateUrl: './scope-selector-modal.component.html',
|
||||
})
|
||||
export class ScopeSelectorModalComponent extends DSOSelectorModalWrapperComponent implements OnInit {
|
||||
objectType = DSpaceObjectType.COMMUNITY;
|
||||
selectorTypes = [DSpaceObjectType.COMMUNITY, DSpaceObjectType.COLLECTION];
|
||||
action = SelectorActionType.SET_SCOPE;
|
||||
scopeChange = new EventEmitter<DSpaceObject>();
|
||||
|
||||
constructor(protected activeModal: NgbActiveModal, protected route: ActivatedRoute) {
|
||||
super(activeModal, route);
|
||||
}
|
||||
|
||||
navigate(dso: DSpaceObject) {
|
||||
/* Handle search navigation in underlying component */
|
||||
this.scopeChange.emit(dso);
|
||||
}
|
||||
}
|
@@ -1,17 +1,14 @@
|
||||
<form #form="ngForm" (ngSubmit)="onSubmit(form.value)" class="row" action="/search">
|
||||
<div *ngIf="isNotEmpty(scopes)" class="col-12 col-sm-3">
|
||||
<select [(ngModel)]="scope" name="scope" class="form-control" aria-label="Search scope" (change)="onScopeChange($event.target.value)" tabindex="0">
|
||||
<option value>{{'search.form.search_dspace' | translate}}</option>
|
||||
<option *ngFor="let scopeOption of scopes" [value]="scopeOption.id">{{scopeOption?.name ? scopeOption.name : 'search.form.search_dspace' | translate}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div [ngClass]="{'col-sm-9': isNotEmpty(scopes)}" class="col-12">
|
||||
<div class="form-group input-group">
|
||||
<input type="text" [(ngModel)]="query" name="query" class="form-control" attr.aria-label="{{ searchPlaceholder }}"
|
||||
[placeholder]="searchPlaceholder">
|
||||
<span class="input-group-append">
|
||||
<form #form="ngForm" (ngSubmit)="onSubmit(form.value)" action="/search">
|
||||
<div>
|
||||
<div class="form-group input-group">
|
||||
<div *ngIf="showScopeSelector === true" class="input-group-prepend">
|
||||
<button class="scope-button btn btn-outline-secondary text-truncate" [ngbTooltip]="(selectedScope | async)?.name" type="button" (click)="openScopeModal()">{{(selectedScope | async)?.name || ('search.form.scope.all' | translate)}}</button>
|
||||
</div>
|
||||
<input type="text" [(ngModel)]="query" name="query" class="form-control" attr.aria-label="{{ searchPlaceholder }}"
|
||||
[placeholder]="searchPlaceholder">
|
||||
<span class="input-group-append">
|
||||
<button type="submit" class="search-button btn btn-{{brandColor}}"><i class="fas fa-search"></i> {{ ('search.form.search' | translate) }}</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@@ -3,3 +3,7 @@
|
||||
background-color: var(--bs-input-bg);
|
||||
color: var(--bs-input-color);
|
||||
}
|
||||
|
||||
.scope-button {
|
||||
max-width: $search-form-scope-max-width;
|
||||
}
|
||||
|
@@ -8,13 +8,11 @@ import { Community } from '../../core/shared/community.model';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||
import { SearchService } from '../../core/shared/search/search.service';
|
||||
import { PaginationComponentOptions } from '../pagination/pagination-component-options.model';
|
||||
import { SortDirection, SortOptions } from '../../core/cache/models/sort-options.model';
|
||||
import { FindListOptions } from '../../core/data/request.models';
|
||||
import { of as observableOf } from 'rxjs';
|
||||
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
|
||||
import { PaginationServiceStub } from '../testing/pagination-service.stub';
|
||||
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
||||
import { createSuccessfulRemoteDataObject$ } from '../remote-data.utils';
|
||||
|
||||
describe('SearchFormComponent', () => {
|
||||
let comp: SearchFormComponent;
|
||||
@@ -35,7 +33,8 @@ describe('SearchFormComponent', () => {
|
||||
useValue: {}
|
||||
},
|
||||
{ provide: PaginationService, useValue: paginationService },
|
||||
{ provide: SearchConfigurationService, useValue: searchConfigService }
|
||||
{ provide: SearchConfigurationService, useValue: searchConfigService },
|
||||
{ provide: DSpaceObjectDataService, useValue: { findById: () => createSuccessfulRemoteDataObject$(undefined)} }
|
||||
],
|
||||
declarations: [SearchFormComponent]
|
||||
}).compileComponents();
|
||||
@@ -48,24 +47,6 @@ describe('SearchFormComponent', () => {
|
||||
el = de.nativeElement;
|
||||
});
|
||||
|
||||
it('should display scopes when available with default and all scopes', () => {
|
||||
|
||||
comp.scopes = objects;
|
||||
fixture.detectChanges();
|
||||
const select: HTMLElement = de.query(By.css('select')).nativeElement;
|
||||
expect(select).toBeDefined();
|
||||
const options: HTMLCollection = select.children;
|
||||
const defOption: Element = options.item(0);
|
||||
expect(defOption.getAttribute('value')).toBe('');
|
||||
|
||||
let index = 1;
|
||||
objects.forEach((object) => {
|
||||
expect(options.item(index).textContent).toBe(object.name);
|
||||
expect(options.item(index).getAttribute('value')).toBe(object.uuid);
|
||||
index++;
|
||||
});
|
||||
});
|
||||
|
||||
it('should not display scopes when empty', () => {
|
||||
fixture.detectChanges();
|
||||
const select = de.query(By.css('select'));
|
||||
@@ -84,17 +65,17 @@ describe('SearchFormComponent', () => {
|
||||
}));
|
||||
|
||||
it('should select correct scope option in scope select', fakeAsync(() => {
|
||||
comp.scopes = objects;
|
||||
fixture.detectChanges();
|
||||
|
||||
fixture.detectChanges();
|
||||
comp.showScopeSelector = true;
|
||||
const testCommunity = objects[1];
|
||||
comp.scope = testCommunity.id;
|
||||
comp.selectedScope.next(testCommunity);
|
||||
|
||||
fixture.detectChanges();
|
||||
tick();
|
||||
const scopeSelect = de.query(By.css('select')).nativeElement;
|
||||
const scopeSelect = de.query(By.css('.scope-button')).nativeElement;
|
||||
|
||||
expect(scopeSelect.value).toBe(testCommunity.id);
|
||||
expect(scopeSelect.textContent).toBe(testCommunity.name);
|
||||
}));
|
||||
// it('should call updateSearch when clicking the submit button with correct parameters', fakeAsync(() => {
|
||||
// comp.query = 'Test String'
|
||||
@@ -118,7 +99,7 @@ describe('SearchFormComponent', () => {
|
||||
//
|
||||
// expect(comp.updateSearch).toHaveBeenCalledWith({ scope: scope, query: query });
|
||||
// }));
|
||||
});
|
||||
});
|
||||
|
||||
export const objects: DSpaceObject[] = [
|
||||
Object.assign(new Community(), {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||||
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
||||
import { DSpaceObject } from '../../core/shared/dspace-object.model';
|
||||
import { Router } from '@angular/router';
|
||||
import { isNotEmpty } from '../empty.util';
|
||||
@@ -6,6 +6,12 @@ import { SearchService } from '../../core/shared/search/search.service';
|
||||
import { currentPath } from '../utils/route.utils';
|
||||
import { PaginationService } from '../../core/pagination/pagination.service';
|
||||
import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ScopeSelectorModalComponent } from './scope-selector-modal/scope-selector-modal.component';
|
||||
import { take } from 'rxjs/operators';
|
||||
import { BehaviorSubject } from 'rxjs';
|
||||
import { DSpaceObjectDataService } from '../../core/data/dspace-object-data.service';
|
||||
import { getFirstSucceededRemoteDataPayload } from '../../core/shared/operators';
|
||||
|
||||
/**
|
||||
* This component renders a simple item page.
|
||||
@@ -22,7 +28,7 @@ import { SearchConfigurationService } from '../../core/shared/search/search-conf
|
||||
/**
|
||||
* Component that represents the search form
|
||||
*/
|
||||
export class SearchFormComponent {
|
||||
export class SearchFormComponent implements OnInit {
|
||||
/**
|
||||
* The search query
|
||||
*/
|
||||
@@ -39,12 +45,9 @@ export class SearchFormComponent {
|
||||
@Input()
|
||||
scope = '';
|
||||
|
||||
@Input() currentUrl: string;
|
||||
selectedScope: BehaviorSubject<DSpaceObject> = new BehaviorSubject<DSpaceObject>(undefined);
|
||||
|
||||
/**
|
||||
* The available scopes
|
||||
*/
|
||||
@Input() scopes: DSpaceObject[];
|
||||
@Input() currentUrl: string;
|
||||
|
||||
/**
|
||||
* Whether or not the search button should be displayed large
|
||||
@@ -61,6 +64,11 @@ export class SearchFormComponent {
|
||||
*/
|
||||
@Input() searchPlaceholder: string;
|
||||
|
||||
/**
|
||||
* Defines whether or not to show the scope selector
|
||||
*/
|
||||
@Input() showScopeSelector = false;
|
||||
|
||||
/**
|
||||
* Output the search data on submit
|
||||
*/
|
||||
@@ -68,8 +76,17 @@ export class SearchFormComponent {
|
||||
|
||||
constructor(private router: Router, private searchService: SearchService,
|
||||
private paginationService: PaginationService,
|
||||
private searchConfig: SearchConfigurationService
|
||||
) {
|
||||
private searchConfig: SearchConfigurationService,
|
||||
private modalService: NgbModal,
|
||||
private dsoService: DSpaceObjectDataService
|
||||
) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (isNotEmpty(this.scope)) {
|
||||
this.dsoService.findById(this.scope).pipe(getFirstSucceededRemoteDataPayload())
|
||||
.subscribe((scope: DSpaceObject) => this.selectedScope.next(scope));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,8 +102,8 @@ export class SearchFormComponent {
|
||||
* Updates the search when the current scope has been changed
|
||||
* @param {string} scope The new scope
|
||||
*/
|
||||
onScopeChange(scope: string) {
|
||||
this.updateSearch({ scope });
|
||||
onScopeChange(scope: DSpaceObject) {
|
||||
this.updateSearch({ scope: scope ? scope.uuid : undefined });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,11 +111,11 @@ export class SearchFormComponent {
|
||||
* @param data Updated parameters
|
||||
*/
|
||||
updateSearch(data: any) {
|
||||
const queryParams = Object.assign({}, data);
|
||||
const pageParam = this.paginationService.getPageParam(this.searchConfig.paginationID);
|
||||
queryParams[pageParam] = 1;
|
||||
const queryParams = Object.assign({}, data);
|
||||
const pageParam = this.paginationService.getPageParam(this.searchConfig.paginationID);
|
||||
queryParams[pageParam] = 1;
|
||||
|
||||
this.router.navigate(this.getSearchLinkParts(), {
|
||||
this.router.navigate(this.getSearchLinkParts(), {
|
||||
queryParams: queryParams,
|
||||
queryParamsHandling: 'merge'
|
||||
});
|
||||
@@ -131,4 +148,12 @@ export class SearchFormComponent {
|
||||
}
|
||||
return this.getSearchLink().split('/');
|
||||
}
|
||||
|
||||
openScopeModal() {
|
||||
const ref = this.modalService.open(ScopeSelectorModalComponent);
|
||||
ref.componentInstance.scopeChange.pipe(take(1)).subscribe((scope: DSpaceObject) => {
|
||||
this.selectedScope.next(scope);
|
||||
this.onScopeChange(scope);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -233,6 +233,7 @@ import { OnClickMenuItemComponent } from './menu/menu-item/onclick-menu-item.com
|
||||
import { TextMenuItemComponent } from './menu/menu-item/text-menu-item.component';
|
||||
import { ThemedConfigurationSearchPageComponent } from '../search-page/themed-configuration-search-page.component';
|
||||
import { SearchNavbarComponent } from '../search-navbar/search-navbar.component';
|
||||
import { ScopeSelectorModalComponent } from './search-form/scope-selector-modal/scope-selector-modal.component';
|
||||
|
||||
/**
|
||||
* Declaration needed to make sure all decorator functions are called in time
|
||||
@@ -458,7 +459,8 @@ const COMPONENTS = [
|
||||
PublicationSidebarSearchListElementComponent,
|
||||
CollectionSidebarSearchListElementComponent,
|
||||
CommunitySidebarSearchListElementComponent,
|
||||
SearchNavbarComponent
|
||||
SearchNavbarComponent,
|
||||
ScopeSelectorModalComponent
|
||||
];
|
||||
|
||||
const ENTRY_COMPONENTS = [
|
||||
@@ -522,7 +524,8 @@ const ENTRY_COMPONENTS = [
|
||||
CommunitySidebarSearchListElementComponent,
|
||||
LinkMenuItemComponent,
|
||||
OnClickMenuItemComponent,
|
||||
TextMenuItemComponent
|
||||
TextMenuItemComponent,
|
||||
ScopeSelectorModalComponent
|
||||
];
|
||||
|
||||
const SHARED_SEARCH_PAGE_COMPONENTS = [
|
||||
|
@@ -1203,6 +1203,12 @@
|
||||
|
||||
"dso-selector.placeholder": "Search for a {{ type }}",
|
||||
|
||||
"dso-selector.set-scope.community.head": "Select a search scope",
|
||||
|
||||
"dso-selector.set-scope.community.button": "Search all of DSpace",
|
||||
|
||||
"dso-selector.set-scope.community.input-header": "Search for a community or collection",
|
||||
|
||||
|
||||
|
||||
"confirmation-modal.export-metadata.header": "Export metadata for {{ dsoName }}",
|
||||
@@ -3101,6 +3107,8 @@
|
||||
|
||||
"search.form.search_dspace": "All repository",
|
||||
|
||||
"search.form.scope.all": "All of DSpace",
|
||||
|
||||
|
||||
|
||||
"search.results.head": "Search Results",
|
||||
|
@@ -3,3 +3,5 @@
|
||||
|
||||
@import '_bootstrap_variables.scss';
|
||||
@import '../../node_modules/bootstrap/scss/variables.scss';
|
||||
|
||||
$search-form-scope-max-width: 150px;
|
||||
|
Reference in New Issue
Block a user