Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/app/core/testing/pagination-service.stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ export class PaginationServiceStub {
updateRouteWithUrl = jasmine.createSpy('updateRouteWithUrl');
clearPagination = jasmine.createSpy('clearPagination');
getRouteParameterValue = jasmine.createSpy('getRouteParameterValue').and.returnValue(of(''));
getPageParam = jasmine.createSpy('getPageParam').and.returnValue(`${this.pagination.id}.page`);
getPageParam = jasmine.createSpy('getPageParam').and.callFake((paginationId: string) => `${paginationId}.page`);

}
14 changes: 13 additions & 1 deletion src/app/core/testing/search-configuration-service.stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
*/
export class SearchConfigurationServiceStub {

public paginationID = 'test-id';
public searchInstanceId = 'test-id';

public searchOptions: BehaviorSubject<SearchOptions> = new BehaviorSubject(new SearchOptions({}));
public paginatedSearchOptions: BehaviorSubject<PaginatedSearchOptions> = new BehaviorSubject(new PaginatedSearchOptions({}));
Expand All @@ -30,6 +30,18 @@ export class SearchConfigurationServiceStub {
return of([]);
}

getCurrentSearchInstanceParam(param: string) {
return `${this.searchInstanceId}.${param}`;
}

getCurrentSearchInstanceFilterParam(param: string) {
return `${this.searchInstanceId}.${param}`;
}

getCurrentPageParam() {
return `${this.searchInstanceId}.page`;
}

getCurrentScope(a) {
return of('test-id');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export class RecentItemListComponent implements OnInit, OnDestroy {
}

onLoadMore(): void {
this.paginationService.updateRouteWithUrl(this.searchConfigurationService.paginationID, ['search'], {
this.paginationService.updateRouteWithUrl(this.searchConfigurationService.searchInstanceId, ['search'], {
sortField: environment.homePage.recentSubmissions.sortField,
sortDirection: 'DESC' as SortDirection,
page: 1,
Expand Down
14 changes: 7 additions & 7 deletions src/app/my-dspace-page/my-dspace-configuration.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ describe('MyDSpaceConfigurationService', () => {

describe('when subscribeToSearchOptions is called', () => {
beforeEach(() => {
(service as any).subscribeToSearchOptions(defaults);
(service as any).subscribeToSearchOptions(defaults.pagination.id, defaults);
});
it('should call all getters it needs, but not call any others', () => {
expect(service.getCurrentPagination).not.toHaveBeenCalled();
Expand All @@ -168,14 +168,14 @@ describe('MyDSpaceConfigurationService', () => {
beforeEach(() => {
(service as any).subscribeToPaginatedSearchOptions('id', defaults);
});
it('should call all getters it needs', () => {
it('should call the pagination-specific getters it needs', () => {
expect(service.getCurrentPagination).toHaveBeenCalled();
expect(service.getCurrentSort).toHaveBeenCalled();
expect(service.getCurrentScope).toHaveBeenCalled();
expect(service.getCurrentConfiguration).toHaveBeenCalled();
expect(service.getCurrentQuery).toHaveBeenCalled();
expect(service.getCurrentDSOType).toHaveBeenCalled();
expect(service.getCurrentFilters).toHaveBeenCalled();
expect(service.getCurrentScope).not.toHaveBeenCalled();
expect(service.getCurrentConfiguration).not.toHaveBeenCalled();
expect(service.getCurrentQuery).not.toHaveBeenCalled();
expect(service.getCurrentDSOType).not.toHaveBeenCalled();
expect(service.getCurrentFilters).not.toHaveBeenCalled();
});
});
});
Expand Down
5 changes: 5 additions & 0 deletions src/app/my-dspace-page/my-dspace-configuration.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ export const SEARCH_CONFIG_SERVICE: InjectionToken<SearchConfigurationService> =
*/
@Injectable({ providedIn: 'root' })
export class MyDSpaceConfigurationService extends SearchConfigurationService {
/**
* Search instance id used for the MyDSpace search component.
*/
public searchInstanceId = 'mydspace-page';

/**
* Default pagination settings
*/
Expand Down
12 changes: 9 additions & 3 deletions src/app/my-dspace-page/my-dspace.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,28 +26,34 @@ export const myDSpaceGuard: CanActivateFn = (
configurationService: MyDSpaceConfigurationService = inject(MyDSpaceConfigurationService),
router: Router = inject(Router),
): Observable<boolean> => {
const configurationParam = configurationService.getCurrentSearchInstanceParam('configuration');
const configuration = route.queryParamMap.get(configurationParam) || route.queryParamMap.get('configuration');
return configurationService.getAvailableConfigurationTypes().pipe(
first(),
map((configurationList) => validateConfigurationParam(router, route.queryParamMap.get('configuration'), configurationList)));
map((configurationList) => validateConfigurationParam(router, configurationService, configuration, configurationList)));
};

/**
* Check if the given configuration is present in the list of those available
*
* @param router
* the service router
* @param configurationService
* the MyDSpace configuration service
* @param configuration
* the configuration to validate
* @param configurationList
* the list of available configuration
*
*/
function validateConfigurationParam(router: Router, configuration: string, configurationList: MyDSpaceConfigurationValueType[]): boolean {
function validateConfigurationParam(router: Router, configurationService: MyDSpaceConfigurationService, configuration: string, configurationList: MyDSpaceConfigurationValueType[]): boolean {
const configurationDefault: string = configurationList[0];
if (isEmpty(configuration) || !configurationList.includes(configuration as MyDSpaceConfigurationValueType)) {
// If configuration param is empty or is not included in available configurations redirect to a default configuration value
const navigationExtras: NavigationExtras = {
queryParams: { configuration: configurationDefault },
queryParams: {
[configurationService.getCurrentSearchInstanceParam('configuration')]: configurationDefault,
},
};

router.navigate([MYDSPACE_ROUTE], navigationExtras);
Expand Down
14 changes: 12 additions & 2 deletions src/app/search-navbar/search-navbar.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ import {
Router,
} from '@angular/router';
import { RouterTestingModule } from '@angular/router/testing';
import { PaginationService } from '@dspace/core/pagination/pagination.service';
import { TranslateLoaderMock } from '@dspace/core/testing/translate-loader.mock';
import {
TranslateLoader,
TranslateModule,
} from '@ngx-translate/core';

import { SearchService } from '../shared/search/search.service';
import { SearchConfigurationService } from '../shared/search/search-configuration.service';
import { SearchNavbarComponent } from './search-navbar.component';

describe('SearchNavbarComponent', () => {
Expand Down Expand Up @@ -54,6 +56,14 @@ describe('SearchNavbarComponent', () => {
],
providers: [
{ provide: SearchService, useValue: mockSearchService },
{ provide: PaginationService, useValue: { getPageParam: (id: string) => `${id}.page` } },
{
provide: SearchConfigurationService,
useValue: {
searchInstanceId: 'spc',
getCurrentSearchInstanceParam: (param: string) => `spc.${param}`,
},
},
],
})
.compileComponents();
Expand Down Expand Up @@ -100,7 +110,7 @@ describe('SearchNavbarComponent', () => {
fixture.detectChanges();
}));
it('to search page with empty query', () => {
const extras: NavigationExtras = { queryParams: { query: '' } };
const extras: NavigationExtras = { queryParams: { 'spc.query': '', 'spc.page': 1 } };
expect(component.onSubmit).toHaveBeenCalledWith({ query: '' });
expect(router.navigate).toHaveBeenCalledWith(['search'], extras);
});
Expand All @@ -125,7 +135,7 @@ describe('SearchNavbarComponent', () => {
fixture.detectChanges();
}));
it('to search page with query', async () => {
const extras: NavigationExtras = { queryParams: { query: 'test' } };
const extras: NavigationExtras = { queryParams: { 'spc.query': 'test', 'spc.page': 1 } };
expect(component.onSubmit).toHaveBeenCalledWith({ query: 'test' });

expect(router.navigate).toHaveBeenCalledWith(['search'], extras);
Expand Down
13 changes: 11 additions & 2 deletions src/app/search-navbar/search-navbar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import {
UntypedFormBuilder,
} from '@angular/forms';
import { Router } from '@angular/router';
import { PaginationService } from '@dspace/core/pagination/pagination.service';
import { TranslateModule } from '@ngx-translate/core';

import { expandSearchInput } from '../shared/animations/slide';
import { SearchService } from '../shared/search/search.service';
import { SearchConfigurationService } from '../shared/search/search-configuration.service';
import { BrowserOnlyPipe } from '../shared/utils/browser-only.pipe';
import { ClickOutsideDirective } from '../shared/utils/click-outside.directive';

Expand Down Expand Up @@ -43,7 +45,11 @@ export class SearchNavbarComponent {
// Search input field
@ViewChild('searchInput') searchField: ElementRef;

constructor(private formBuilder: UntypedFormBuilder, private router: Router, private searchService: SearchService) {
constructor(private formBuilder: UntypedFormBuilder,
private router: Router,
private searchService: SearchService,
private searchConfigurationService: SearchConfigurationService,
private paginationService: PaginationService) {
this.searchForm = this.formBuilder.group(({
query: '',
}));
Expand Down Expand Up @@ -80,7 +86,10 @@ export class SearchNavbarComponent {
*/
onSubmit(data: any) {
this.collapse();
const queryParams = Object.assign({}, data);
const queryParams = {
[this.searchConfigurationService.getCurrentSearchInstanceParam('query')]: data.query,
[this.paginationService.getPageParam(this.searchConfigurationService.searchInstanceId)]: 1,
};
const linkToNavigateTo = [this.searchService.getSearchLink().replace('/', '')];
this.searchForm.reset();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ describe('ConfigurationSearchPageComponent', () => {
expect(comp.configuration).toBe(CONFIGURATION);
expect(comp.fixedFilterQuery).toBe(QUERY);

expect(routeService.setParameter).toHaveBeenCalledWith('configuration', CONFIGURATION);
expect(routeService.setParameter).toHaveBeenCalledWith('fixedFilterQuery', QUERY);
expect(routeService.setParameter).toHaveBeenCalledWith('search-test-page-id.configuration', CONFIGURATION);
expect(routeService.setParameter).toHaveBeenCalledWith('search-test-page-id.fixedFilterQuery', QUERY);
});

});
5 changes: 5 additions & 0 deletions src/app/search-page/configuration-search-page.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ import { ViewModeSwitchComponent } from '../shared/view-mode-switch/view-mode-sw
provide: SEARCH_CONFIG_SERVICE,
useClass: SearchConfigurationService,
},
{
provide: SearchConfigurationService,
useExisting: SEARCH_CONFIG_SERVICE,
},
SearchService,
],
imports: [
AsyncPipe,
Expand Down
6 changes: 6 additions & 0 deletions src/app/search-page/search-page.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component } from '@angular/core';

import { SEARCH_CONFIG_SERVICE } from '../my-dspace-page/my-dspace-configuration.service';
import { SearchService } from '../shared/search/search.service';
import { SearchConfigurationService } from '../shared/search/search-configuration.service';
import { ThemedSearchComponent } from '../shared/search/themed-search.component';

Expand All @@ -12,6 +13,11 @@ import { ThemedSearchComponent } from '../shared/search/themed-search.component'
provide: SEARCH_CONFIG_SERVICE,
useClass: SearchConfigurationService,
},
{
provide: SearchConfigurationService,
useExisting: SEARCH_CONFIG_SERVICE,
},
SearchService,
],
imports: [
ThemedSearchComponent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,9 @@ export class ThemedConfigurationSearchPageComponent extends ThemedComponent<Conf
@Input() linkType: CollectionElementLinkType;

/**
* The pagination id used in the search
* The search instance id used in the search
*/
@Input() paginationId: string;
@Input() searchInstanceId: string;

/**
* Whether or not the search bar should be visible
Expand Down Expand Up @@ -151,7 +151,7 @@ export class ThemedConfigurationSearchPageComponent extends ThemedComponent<Conf
'useCachedVersionIfAvailable',
'inPlaceSearch',
'linkType',
'paginationId',
'searchInstanceId',
'searchEnabled',
'sideBarWidth',
'searchFormPlaceholder',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit
return this.externalSourceService.getExternalSourceEntries(this.externalSource.id, searchOptions).pipe(startWith(undefined));
}),
);
this.currentPagination$ = this.paginationService.getCurrentPagination(this.searchConfigService.paginationID, this.initialPagination);
this.currentPagination$ = this.paginationService.getCurrentPagination(this.searchConfigService.searchInstanceId, this.initialPagination);
this.importConfig = {
buttonLabel: 'submission.sections.describe.relationship-lookup.external-source.import-button-title.' + this.label,
};
Expand Down Expand Up @@ -256,7 +256,7 @@ export class DsDynamicLookupRelationExternalSourceTabComponent implements OnInit
* Method to reset the route when the tab is opened to make sure no strange pagination issues appears
*/
resetRoute() {
this.paginationService.updateRoute(this.searchConfigService.paginationID, {
this.paginationService.updateRoute(this.searchConfigService.searchInstanceId, {
page: 1,
pageSize: 5,
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ export class DsDynamicLookupRelationSearchTabComponent implements OnInit, OnDest
* Method to reset the route when the window is opened to make sure no strange pagination issues appears
*/
resetRoute() {
this.paginationService.updateRoute(this.searchConfigService.paginationID, this.initialPagination);
this.paginationService.updateRoute(this.searchConfigService.searchInstanceId, this.initialPagination);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -142,14 +142,14 @@ export class DsDynamicLookupRelationSelectionTabComponent implements OnInit {
);
}),
);
this.currentPagination$ = this.paginationService.getCurrentPagination(this.searchConfigService.paginationID, this.initialPagination);
this.currentPagination$ = this.paginationService.getCurrentPagination(this.searchConfigService.searchInstanceId, this.initialPagination);
}

/**
* Method to reset the route when the tab is opened to make sure no strange pagination issues appears
*/
resetRoute() {
this.paginationService.updateRoute(this.searchConfigService.paginationID, {
this.paginationService.updateRoute(this.searchConfigService.searchInstanceId, {
page: 1,
pageSize: 5,
});
Expand Down
20 changes: 16 additions & 4 deletions src/app/shared/object-collection/object-collection.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ import { PageInfo } from '@dspace/core/shared/page-info.model';
import { ViewMode } from '@dspace/core/shared/view-mode.model';
import { isEmpty } from '@dspace/shared/utils/empty.util';
import { setPlaceHolderAttributes } from '@dspace/shared/utils/object-list-utils';
import { Observable } from 'rxjs';
import {
BehaviorSubject,
combineLatest as observableCombineLatest,
Observable,
} from 'rxjs';
import {
distinctUntilChanged,
map,
Expand Down Expand Up @@ -146,6 +150,13 @@ export class ObjectCollectionComponent implements OnInit {
*/
@Input() showThumbnails;

/**
* The view mode to render. When not provided, this component falls back to the legacy `view` URL parameter.
*/
@Input() set viewMode(viewMode: ViewMode) {
this.viewMode$.next(viewMode);
}

/**
* the page info of the list
*/
Expand Down Expand Up @@ -195,6 +206,8 @@ export class ObjectCollectionComponent implements OnInit {
*/
currentMode$: Observable<ViewMode>;

private viewMode$: BehaviorSubject<ViewMode> = new BehaviorSubject<ViewMode>(undefined);

/**
* The available view modes
*/
Expand Down Expand Up @@ -227,10 +240,9 @@ export class ObjectCollectionComponent implements OnInit {
}

ngOnInit(): void {
this.currentMode$ = this.route
.queryParams
this.currentMode$ = observableCombineLatest([this.route.queryParams, this.viewMode$])
.pipe(
map((params) => isEmpty(params?.view) ? ViewMode.ListElement : params.view),
map(([params, viewMode]) => viewMode || (isEmpty(params?.view) ? ViewMode.ListElement : params.view)),
distinctUntilChanged(),
);
if (isPlatformBrowser(this.platformId)) {
Expand Down
Loading
Loading