From dfa1e5a84fddc8644f448525b70f89bcc96bd9e2 Mon Sep 17 00:00:00 2001 From: Matus Kasak Date: Wed, 26 Aug 2026 12:52:42 +0200 Subject: [PATCH] Clarin9/Restrict main search page to items only The main /search page previously returned all DSpace object types (items, collections and communities), matching the backend `default` discovery configuration. In v7 only items were shown there. Add a reusable `forcedDsoTypes` input to the (themed) SearchComponent that forces the given DSpaceObject types onto every search request the component makes, and set it to items only on the main search page. Community and collection results are therefore hidden from /search, while other search pages (MyDSpace, admin, browse, scoped configuration searches) are untouched. Clearing SearchPageComponent.forcedDsoTypes restores the previous behaviour, and the input can be reused to expose this as a facet/config later. Co-Authored-By: Claude Opus 4.8 --- src/app/search-page/search-page.component.html | 2 +- src/app/search-page/search-page.component.ts | 3 +++ src/app/shared/search/search.component.spec.ts | 11 +++++++++++ src/app/shared/search/search.component.ts | 8 ++++++++ src/app/shared/search/themed-search.component.ts | 4 ++++ 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/app/search-page/search-page.component.html b/src/app/search-page/search-page.component.html index 8d310607833..83ca9e536cc 100644 --- a/src/app/search-page/search-page.component.html +++ b/src/app/search-page/search-page.component.html @@ -1 +1 @@ - + diff --git a/src/app/search-page/search-page.component.ts b/src/app/search-page/search-page.component.ts index d5df0ec65c6..615c1d6f857 100644 --- a/src/app/search-page/search-page.component.ts +++ b/src/app/search-page/search-page.component.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; +import { DSpaceObjectType } from '../core/shared/dspace-object-type.model'; import { SearchConfigurationService } from '../core/shared/search/search-configuration.service'; import { SEARCH_CONFIG_SERVICE } from '../my-dspace-page/my-dspace-configuration.service'; import { ThemedSearchComponent } from '../shared/search/themed-search.component'; @@ -22,4 +23,6 @@ import { ThemedSearchComponent } from '../shared/search/themed-search.component' * It renders search results depending on the current search options */ export class SearchPageComponent { + /** Restrict the search page to items only (hides community/collection results); empty = all types. */ + forcedDsoTypes: DSpaceObjectType[] = [DSpaceObjectType.ITEM]; } diff --git a/src/app/shared/search/search.component.spec.ts b/src/app/shared/search/search.component.spec.ts index 0a8d63f1ab7..c60a0c95c7a 100644 --- a/src/app/shared/search/search.component.spec.ts +++ b/src/app/shared/search/search.component.spec.ts @@ -39,6 +39,7 @@ import { CommunityDataService } from '../../core/data/community-data.service'; import { RemoteData } from '../../core/data/remote-data'; import { RouteService } from '../../core/services/route.service'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model'; import { Item } from '../../core/shared/item.model'; import { SearchService } from '../../core/shared/search/search.service'; import { SearchConfigurationService } from '../../core/shared/search/search-configuration.service'; @@ -316,6 +317,16 @@ describe('SearchComponent', () => { expect((comp as any).retrieveSearchResults).toHaveBeenCalledWith(expectedSearchOptions); })); + it('should force the configured dsoTypes onto the search options when forcedDsoTypes is set', fakeAsync(() => { + const retrieveSpy = spyOn((comp as any), 'retrieveSearchResults').and.callThrough(); + comp.forcedDsoTypes = [DSpaceObjectType.ITEM]; + fixture.detectChanges(); + tick(100); + + const usedOptions = retrieveSpy.calls.mostRecent().args[0] as PaginatedSearchOptions; + expect(usedOptions.dsoTypes).toEqual([DSpaceObjectType.ITEM]); + })); + it('should retrieve SearchResults', fakeAsync(() => { fixture.detectChanges(); tick(100); diff --git a/src/app/shared/search/search.component.ts b/src/app/shared/search/search.component.ts index 701ce463769..8efeb1c3201 100644 --- a/src/app/shared/search/search.component.ts +++ b/src/app/shared/search/search.component.ts @@ -47,6 +47,7 @@ import { RemoteData } from '../../core/data/remote-data'; import { RouteService } from '../../core/services/route.service'; import { Context } from '../../core/shared/context.model'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model'; import { Item } from '../../core/shared/item.model'; import { getFirstCompletedRemoteData } from '../../core/shared/operators'; import { SearchService } from '../../core/shared/search/search.service'; @@ -242,6 +243,9 @@ export class SearchComponent implements OnDestroy, OnInit { */ @Input() renderOnServerSide: boolean; + /** Restrict results to these DSpaceObject types (e.g. items only); empty = all types. */ + @Input() forcedDsoTypes: DSpaceObjectType[] = []; + /** * The current configuration used during the search */ @@ -431,6 +435,10 @@ export class SearchComponent implements OnDestroy, OnInit { if (isEmpty(combinedOptions.scope)) { combinedOptions.scope = scope; } + // Force the configured result types (e.g. items only) when no explicit dsoTypes are set. + if (isNotEmpty(this.forcedDsoTypes) && isEmpty(combinedOptions.dsoTypes)) { + combinedOptions.dsoTypes = [...this.forcedDsoTypes]; + } const newSearchOptions = new PaginatedSearchOptions(combinedOptions); // check if search options are changed // if so retrieve new related results otherwise skip it diff --git a/src/app/shared/search/themed-search.component.ts b/src/app/shared/search/themed-search.component.ts index f60f8652f3c..f84f84c04f0 100644 --- a/src/app/shared/search/themed-search.component.ts +++ b/src/app/shared/search/themed-search.component.ts @@ -7,6 +7,7 @@ import { import { Context } from '../../core/shared/context.model'; import { DSpaceObject } from '../../core/shared/dspace-object.model'; +import { DSpaceObjectType } from '../../core/shared/dspace-object-type.model'; import { ViewMode } from '../../core/shared/view-mode.model'; import { CollectionElementLinkType } from '../object-collection/collection-element-link.type'; import { ListableObject } from '../object-collection/shared/listable-object.model'; @@ -51,6 +52,7 @@ export class ThemedSearchComponent extends ThemedComponent { 'query', 'scope', 'hideScopeInUrl', + 'forcedDsoTypes', 'resultFound', 'deselectObject', 'selectObject', @@ -106,6 +108,8 @@ export class ThemedSearchComponent extends ThemedComponent { @Input() hideScopeInUrl: boolean; + @Input() forcedDsoTypes: DSpaceObjectType[]; + @Output() resultFound: EventEmitter> = new EventEmitter(); @Output() deselectObject: EventEmitter = new EventEmitter();