11import { ChangeDetectionStrategy , Component , EventEmitter , Inject , Input , OnInit , Output } from '@angular/core' ;
2- import { Router } from '@angular/router' ;
2+ import { NavigationStart , Router } from '@angular/router' ;
33
44import { BehaviorSubject , combineLatest , Observable , Subscription } from 'rxjs' ;
5- import { debounceTime , distinctUntilChanged , filter , map , switchMap } from 'rxjs/operators' ;
5+ import { debounceTime , distinctUntilChanged , filter , map , switchMap , take } from 'rxjs/operators' ;
66import { uniqueId } from 'lodash' ;
77
88import { PaginatedList } from '../../core/data/paginated-list.model' ;
@@ -11,7 +11,7 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model';
1111import { pushInOut } from '../animations/push' ;
1212import { HostWindowService } from '../host-window.service' ;
1313import { SidebarService } from '../sidebar/sidebar.service' ;
14- import { hasValue } from '../empty.util' ;
14+ import { hasValue , hasValueOperator , isNotEmpty } from '../empty.util' ;
1515import { RouteService } from '../../core/services/route.service' ;
1616import { SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component' ;
1717import { PaginatedSearchOptions } from './models/paginated-search-options.model' ;
@@ -34,6 +34,9 @@ import { CollectionElementLinkType } from '../object-collection/collection-eleme
3434import { environment } from 'src/environments/environment' ;
3535import { SubmissionObject } from '../../core/submission/models/submission-object.model' ;
3636import { SearchFilterConfig } from './models/search-filter-config.model' ;
37+ import { ITEM_MODULE_PATH } from '../../item-page/item-page-routing-paths' ;
38+ import { COLLECTION_MODULE_PATH } from '../../collection-page/collection-page-routing-paths' ;
39+ import { COMMUNITY_MODULE_PATH } from '../../community-page/community-page-routing-paths' ;
3740
3841@Component ( {
3942 selector : 'ds-search' ,
@@ -218,9 +221,21 @@ export class SearchComponent implements OnInit {
218221 searchLink : string ;
219222
220223 /**
221- * Subscription to unsubscribe from
224+ * Regex to match UUIDs
222225 */
223- sub : Subscription ;
226+ uuidRegex = / \b [ 0 - 9 a - f ] { 8 } \b - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 4 } - [ 0 - 9 a - f ] { 4 } - \b [ 0 - 9 a - f ] { 12 } \b / g;
227+
228+ /**
229+ * List of paths that are considered to be the start of a route to an object page (excluding "/", e.g. "items")
230+ * These are expected to end on an object UUID
231+ * If they match the route we're navigating to, an object property will be added to the search event sent
232+ */
233+ allowedObjectPaths : string [ ] = [ 'entities' , ITEM_MODULE_PATH , COLLECTION_MODULE_PATH , COMMUNITY_MODULE_PATH ] ;
234+
235+ /**
236+ * Subscriptions to unsubscribe from
237+ */
238+ subs : Subscription [ ] = [ ] ;
224239
225240 /**
226241 * Emits an event with the current search result entries
@@ -290,7 +305,7 @@ export class SearchComponent implements OnInit {
290305 ) ;
291306 const searchOptions$ : Observable < PaginatedSearchOptions > = this . getSearchOptions ( ) . pipe ( distinctUntilChanged ( ) ) ;
292307
293- this . sub = combineLatest ( [ configuration$ , searchSortOptions$ , searchOptions$ , sortOption$ ] ) . pipe (
308+ this . subs . push ( combineLatest ( [ configuration$ , searchSortOptions$ , searchOptions$ , sortOption$ ] ) . pipe (
294309 filter ( ( [ configuration , searchSortOptions , searchOptions , sortOption ] : [ string , SortOptions [ ] , PaginatedSearchOptions , SortOptions ] ) => {
295310 // filter for search options related to instanced paginated id
296311 return searchOptions . pagination . id === this . paginationId ;
@@ -318,7 +333,9 @@ export class SearchComponent implements OnInit {
318333 this . retrieveSearchResults ( newSearchOptions ) ;
319334 this . retrieveFilters ( searchOptions ) ;
320335 }
321- } ) ;
336+ } ) ) ;
337+
338+ this . subscribeToRoutingEvents ( ) ;
322339 }
323340
324341 /**
@@ -360,12 +377,10 @@ export class SearchComponent implements OnInit {
360377 }
361378
362379 /**
363- * Unsubscribe from the subscription
380+ * Unsubscribe from the subscriptions
364381 */
365382 ngOnDestroy ( ) : void {
366- if ( hasValue ( this . sub ) ) {
367- this . sub . unsubscribe ( ) ;
368- }
383+ this . subs . filter ( ( sub ) => hasValue ( sub ) ) . forEach ( ( sub ) => sub . unsubscribe ( ) ) ;
369384 }
370385
371386 /**
@@ -420,6 +435,43 @@ export class SearchComponent implements OnInit {
420435 } ) ;
421436 }
422437
438+ /**
439+ * Subscribe to routing events to detect when a user moves away from the search page
440+ * When the user is routing to an object page, it needs to send out a separate search event containing that object's UUID
441+ * This method should only be called once and is essentially what SearchTrackingComponent used to do (now removed)
442+ * @private
443+ */
444+ private subscribeToRoutingEvents ( ) {
445+ this . subs . push (
446+ this . router . events . pipe (
447+ filter ( ( event ) => event instanceof NavigationStart ) ,
448+ map ( ( event : NavigationStart ) => this . getDsoUUIDFromUrl ( event . url ) ) ,
449+ hasValueOperator ( ) ,
450+ ) . subscribe ( ( uuid ) => {
451+ if ( this . resultsRD$ . value . hasSucceeded ) {
452+ this . service . trackSearch ( this . searchOptions$ . value , this . resultsRD$ . value . payload as SearchObjects < DSpaceObject > , uuid ) ;
453+ }
454+ } ) ,
455+ ) ;
456+ }
457+
458+ /**
459+ * Get the UUID from a DSO url
460+ * Return null if the url isn't an object page (allowedObjectPaths) or the UUID couldn't be found
461+ * @param url
462+ */
463+ private getDsoUUIDFromUrl ( url : string ) : string {
464+ if ( isNotEmpty ( url ) ) {
465+ if ( this . allowedObjectPaths . some ( ( path ) => url . startsWith ( `/${ path } ` ) ) ) {
466+ const uuid = url . substring ( url . lastIndexOf ( '/' ) + 1 ) ;
467+ if ( uuid . match ( this . uuidRegex ) ) {
468+ return uuid ;
469+ }
470+ }
471+ }
472+ return null ;
473+ }
474+
423475 /**
424476 * Check if the sidebar is collapsed
425477 * @returns {Observable<boolean> } emits true if the sidebar is currently collapsed, false if it is expanded
0 commit comments