@@ -96,13 +96,25 @@ const SearchPageLight = ({ darkMode = true }) => {
9696 const searchParam = urlParams . get ( 'search' ) ;
9797 const yearParam = urlParams . get ( 'publication_year' ) ;
9898 const institutionIdParam = urlParams . get ( 'institution_id' ) ;
99+ const authorIdParams = urlParams . getAll ( 'author_id' ) ;
100+ const institutionIdParams = urlParams . getAll ( 'institution_id' ) ;
101+ const publicationTypeParams = urlParams . getAll ( 'publication_type' ) ;
102+ const journalIdParams = urlParams . getAll ( 'journal_id' ) ;
103+ const startYearParam = urlParams . get ( 'start_year' ) ;
104+ const endYearParam = urlParams . get ( 'end_year' ) ;
99105
100106 // Check if we have any chart-related parameters (coming from graph click)
101- const hasChartParams = searchParam || yearParam || institutionIdParam ;
107+ const hasChartParams = searchParam || yearParam || institutionIdParam || authorIdParams . length > 0 ||
108+ institutionIdParams . length > 0 || publicationTypeParams . length > 0 ||
109+ journalIdParams . length > 0 || startYearParam || endYearParam ;
102110
103111 if ( hasChartParams ) {
104112 // Has URL parameters - came from graph click, auto-search
105- console . log ( 'Graph navigation detected - auto-searching with params:' , { searchParam, yearParam, institutionIdParam } ) ;
113+ console . log ( 'Graph navigation detected - auto-searching with params:' , {
114+ searchParam, yearParam, institutionIdParam, authorIdParams,
115+ institutionIdParams, publicationTypeParams, journalIdParams,
116+ startYearParam, endYearParam
117+ } ) ;
106118
107119 // Set search keyword if provided
108120 if ( searchParam ) {
@@ -114,15 +126,91 @@ const SearchPageLight = ({ darkMode = true }) => {
114126 setPublicationYear ( yearParam ) ;
115127 }
116128
117- // Handle institution if provided
118- if ( institutionIdParam ) {
119- fetchInstitutionById ( institutionIdParam ) ;
129+ // Set year range if provided
130+ if ( startYearParam ) {
131+ setStartYear ( startYearParam ) ;
132+ }
133+ if ( endYearParam ) {
134+ setEndYear ( endYearParam ) ;
135+ }
136+
137+ // Handle authors if provided
138+ if ( authorIdParams . length > 0 ) {
139+ console . log ( 'Setting author details for:' , authorIdParams ) ;
140+
141+ // Get author names from URL parameters if available
142+ const authorNameParams = urlParams . getAll ( 'author_name' ) ;
143+ console . log ( 'Author name params received:' , authorNameParams ) ;
144+
145+ // Create author objects with real names if available, otherwise use IDs
146+ const authors = authorIdParams . map ( ( id , index ) => {
147+ const displayName = authorNameParams [ index ] || `Author ${ id } ` ;
148+ console . log ( `Author ${ id } : using display name "${ displayName } "` ) ;
149+ return {
150+ id : `A${ id } ` ,
151+ display_name : displayName
152+ } ;
153+ } ) ;
154+
155+ console . log ( 'Setting selected authors:' , authors ) ;
156+ setSelectedAuthors ( authors ) ;
157+ }
158+
159+ // Handle institutions if provided
160+ if ( institutionIdParams . length > 0 ) {
161+ console . log ( 'Setting institution details for:' , institutionIdParams ) ;
162+
163+ // Get institution names from URL parameters if available
164+ const institutionNameParams = urlParams . getAll ( 'institution_name' ) ;
165+ console . log ( 'Institution name params received:' , institutionNameParams ) ;
166+
167+ // Create institution objects with real names if available, otherwise use IDs
168+ const institutions = institutionIdParams . map ( ( id , index ) => {
169+ const displayName = institutionNameParams [ index ] || `Institution ${ id } ` ;
170+ console . log ( `Institution ${ id } : using display name "${ displayName } "` ) ;
171+ return {
172+ id : `I${ id } ` ,
173+ display_name : displayName
174+ } ;
175+ } ) ;
176+
177+ console . log ( 'Setting selected institutions:' , institutions ) ;
178+ setSelectedInstitutions ( institutions ) ;
179+ }
180+
181+ // Handle publication types if provided
182+ if ( publicationTypeParams . length > 0 ) {
183+ const selectedTypes = publicationTypes . filter ( pt =>
184+ publicationTypeParams . includes ( pt . id )
185+ ) ;
186+ setSelectedPublicationTypes ( selectedTypes ) ;
187+ }
188+
189+ // Handle journals if provided
190+ if ( journalIdParams . length > 0 ) {
191+ // Fetch journal details for each journal ID
192+ Promise . all ( journalIdParams . map ( async ( journalId ) => {
193+ try {
194+ const response = await fetch ( `${ OPENALEX_API_BASE } /sources/S${ journalId } ` ) ;
195+ if ( response . ok ) {
196+ const journalData = await response . json ( ) ;
197+ return { id : journalData . id , display_name : journalData . display_name } ;
198+ }
199+ } catch ( error ) {
200+ console . error ( 'Failed to fetch journal details:' , error ) ;
201+ }
202+ } ) ) . then ( journals => {
203+ const validJournals = journals . filter ( journal => journal ) ;
204+ setSelectedJournals ( validJournals ) ;
205+ } ) ;
120206 }
121207
122208 // Auto-search with URL parameters
123209 setTimeout ( ( ) => {
124- performAutoSearchWithParams ( searchParam , yearParam , institutionIdParam ) ;
125- } , 200 ) ;
210+ performAutoSearchWithParams ( searchParam , yearParam , institutionIdParam , authorIdParams ,
211+ institutionIdParams , publicationTypeParams , journalIdParams ,
212+ startYearParam , endYearParam ) ;
213+ } , 1000 ) ; // Increased timeout to allow for author/institution fetching
126214 } else {
127215 // No URL parameters - any other navigation, just clear fields
128216 console . log ( 'Direct navigation - clearing fields, no auto-search' ) ;
@@ -145,8 +233,14 @@ const SearchPageLight = ({ darkMode = true }) => {
145233 } ;
146234
147235 // Separate function for auto-search with URL parameters
148- const performAutoSearchWithParams = async ( searchParam , yearParam , institutionIdParam , page = 1 ) => {
149- console . log ( 'performAutoSearchWithParams called with:' , { searchParam, yearParam, institutionIdParam, page } ) ;
236+ const performAutoSearchWithParams = async ( searchParam , yearParam , institutionIdParam , authorIdParams ,
237+ institutionIdParams , publicationTypeParams , journalIdParams ,
238+ startYearParam , endYearParam , page = 1 ) => {
239+ console . log ( 'performAutoSearchWithParams called with:' , {
240+ searchParam, yearParam, institutionIdParam, authorIdParams,
241+ institutionIdParams, publicationTypeParams, journalIdParams,
242+ startYearParam, endYearParam, page
243+ } ) ;
150244
151245 setLoading ( true ) ;
152246 setError ( null ) ;
@@ -161,7 +255,6 @@ const SearchPageLight = ({ darkMode = true }) => {
161255 // Use search parameter directly from URL
162256 if ( searchParam && searchParam . trim ( ) ) {
163257 const keyword = searchParam . trim ( ) ;
164- // Format: title_and_abstract.search:keyword (spaces become + in URL)
165258 filters . push ( `title_and_abstract.search:${ keyword } ` ) ;
166259 }
167260
@@ -170,9 +263,33 @@ const SearchPageLight = ({ darkMode = true }) => {
170263 filters . push ( `publication_year:${ yearParam . trim ( ) } ` ) ;
171264 }
172265
173- // Use institution parameter directly from URL
174- if ( institutionIdParam && institutionIdParam . trim ( ) ) {
175- filters . push ( `authorships.institutions.id:I${ institutionIdParam . trim ( ) } ` ) ;
266+ // Use year range parameters directly from URL
267+ if ( startYearParam && endYearParam && startYearParam . trim ( ) && endYearParam . trim ( ) ) {
268+ filters . push ( `publication_year:${ startYearParam . trim ( ) } -${ endYearParam . trim ( ) } ` ) ;
269+ }
270+
271+ // Use institution parameters directly from URL
272+ if ( institutionIdParams && institutionIdParams . length > 0 ) {
273+ const institutionFilters = institutionIdParams . map ( id => `authorships.institutions.id:I${ id . trim ( ) } ` ) ;
274+ filters . push ( institutionFilters . join ( '|' ) ) ;
275+ }
276+
277+ // Use author parameters directly from URL
278+ if ( authorIdParams && authorIdParams . length > 0 ) {
279+ const authorFilters = authorIdParams . map ( id => `authorships.author.id:A${ id . trim ( ) } ` ) ;
280+ filters . push ( authorFilters . join ( '|' ) ) ;
281+ }
282+
283+ // Use publication type parameters directly from URL
284+ if ( publicationTypeParams && publicationTypeParams . length > 0 ) {
285+ const typeFilters = publicationTypeParams . map ( type => `type:${ type } ` ) ;
286+ filters . push ( typeFilters . join ( '|' ) ) ;
287+ }
288+
289+ // Use journal parameters directly from URL
290+ if ( journalIdParams && journalIdParams . length > 0 ) {
291+ const journalFilters = journalIdParams . map ( id => `primary_location.source.id:S${ id . trim ( ) } ` ) ;
292+ filters . push ( journalFilters . join ( '|' ) ) ;
176293 }
177294
178295 const filterString = filters . join ( ',' ) ;
@@ -182,20 +299,35 @@ const SearchPageLight = ({ darkMode = true }) => {
182299 params . append ( 'page' , page . toString ( ) ) ;
183300 params . append ( 'sort' , 'cited_by_count:desc' ) ;
184301
185- const finalUrl = `${ OPENALEX_API_BASE } /works?${ params . toString ( ) } ` ;
186- console . log ( 'Auto-search URL:' , finalUrl ) ;
187- console . log ( 'Search filters:' , filters ) ;
188- console . log ( 'URL matches format: https://openalex.org/works?page=X&filter=...&sort=cited_by_count:desc' ) ;
302+ const url = `${ OPENALEX_API_BASE } /works?${ params . toString ( ) } ` ;
189303
190304 // Track API call for disclaimer
191- setApiCalls ( [ finalUrl ] ) ;
305+ setApiCalls ( [ url ] ) ;
192306
193- const url = `${ OPENALEX_API_BASE } /works?${ params . toString ( ) } ` ;
194307 const response = await fetch ( url ) ;
195308 if ( ! response . ok ) throw new Error ( 'Failed to fetch search results' ) ;
196309 const data = await response . json ( ) ;
197310
198- setResults ( data . results || [ ] ) ;
311+ // Deduplicate results based on work ID and title to prevent duplicates
312+ const uniqueResults = [ ] ;
313+ const seenIds = new Set ( ) ;
314+ const seenTitles = new Set ( ) ;
315+
316+ if ( data . results && Array . isArray ( data . results ) ) {
317+ data . results . forEach ( result => {
318+ const title = result . title || result . display_name || '' ;
319+ const normalizedTitle = title . toLowerCase ( ) . trim ( ) ;
320+
321+ // Check both ID and title for duplicates
322+ if ( result . id && ! seenIds . has ( result . id ) && ! seenTitles . has ( normalizedTitle ) ) {
323+ seenIds . add ( result . id ) ;
324+ seenTitles . add ( normalizedTitle ) ;
325+ uniqueResults . push ( result ) ;
326+ }
327+ } ) ;
328+ }
329+
330+ setResults ( uniqueResults ) ;
199331 setTotalResults ( data . meta ?. count || 0 ) ;
200332 setTotalPages ( Math . ceil ( ( data . meta ?. count || 0 ) / resultsPerPage ) ) ;
201333 setCurrentPage ( page ) ;
@@ -293,7 +425,26 @@ const SearchPageLight = ({ darkMode = true }) => {
293425 if ( ! response . ok ) throw new Error ( 'Failed to fetch search results' ) ;
294426 const data = await response . json ( ) ;
295427
296- setResults ( data . results || [ ] ) ;
428+ // Deduplicate results based on work ID and title to prevent duplicates
429+ const uniqueResults = [ ] ;
430+ const seenIds = new Set ( ) ;
431+ const seenTitles = new Set ( ) ;
432+
433+ if ( data . results && Array . isArray ( data . results ) ) {
434+ data . results . forEach ( result => {
435+ const title = result . title || result . display_name || '' ;
436+ const normalizedTitle = title . toLowerCase ( ) . trim ( ) ;
437+
438+ // Check both ID and title for duplicates
439+ if ( result . id && ! seenIds . has ( result . id ) && ! seenTitles . has ( normalizedTitle ) ) {
440+ seenIds . add ( result . id ) ;
441+ seenTitles . add ( normalizedTitle ) ;
442+ uniqueResults . push ( result ) ;
443+ }
444+ } ) ;
445+ }
446+
447+ setResults ( uniqueResults ) ;
297448 setTotalResults ( data . meta ?. count || 0 ) ;
298449 setTotalPages ( Math . ceil ( ( data . meta ?. count || 0 ) / resultsPerPage ) ) ;
299450 setCurrentPage ( page ) ;
@@ -318,10 +469,20 @@ const SearchPageLight = ({ darkMode = true }) => {
318469 const searchParam = urlParams . get ( 'search' ) ;
319470 const yearParam = urlParams . get ( 'publication_year' ) ;
320471 const institutionIdParam = urlParams . get ( 'institution_id' ) ;
321-
322- if ( searchParam || yearParam || institutionIdParam ) {
472+ const authorIdParams = urlParams . getAll ( 'author_id' ) ;
473+ const institutionIdParams = urlParams . getAll ( 'institution_id' ) ;
474+ const publicationTypeParams = urlParams . getAll ( 'publication_type' ) ;
475+ const journalIdParams = urlParams . getAll ( 'journal_id' ) ;
476+ const startYearParam = urlParams . get ( 'start_year' ) ;
477+ const endYearParam = urlParams . get ( 'end_year' ) ;
478+
479+ if ( searchParam || yearParam || institutionIdParam || authorIdParams . length > 0 ||
480+ institutionIdParams . length > 0 || publicationTypeParams . length > 0 ||
481+ journalIdParams . length > 0 || startYearParam || endYearParam ) {
323482 // Use auto-search with parameters
324- performAutoSearchWithParams ( searchParam , yearParam , institutionIdParam , newPage ) ;
483+ performAutoSearchWithParams ( searchParam , yearParam , institutionIdParam , authorIdParams ,
484+ institutionIdParams , publicationTypeParams , journalIdParams ,
485+ startYearParam , endYearParam , newPage ) ;
325486 } else {
326487 // Use regular search
327488 handleSearch ( newPage ) ;
0 commit comments