Skip to content

Commit 0f0847c

Browse files
100414: Refactor SearchTrackerComponent to SearchComponent
1 parent fbacebb commit 0f0847c

6 files changed

Lines changed: 66 additions & 189 deletions

File tree

src/app/core/shared/search/search.service.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,8 +334,9 @@ export class SearchService implements OnDestroy {
334334
* Send search event to rest api using angularitics
335335
* @param config Paginated search options used
336336
* @param searchQueryResponse The response objects of the performed search
337+
* @param object Optional UUID of an object a search was performed and clicked for
337338
*/
338-
trackSearch(config: PaginatedSearchOptions, searchQueryResponse: SearchObjects<DSpaceObject>) {
339+
trackSearch(config: PaginatedSearchOptions, searchQueryResponse: SearchObjects<DSpaceObject>, object?: string) {
339340
const filters: { filter: string, operator: string, value: string, label: string; }[] = [];
340341
const appliedFilters = searchQueryResponse.appliedFilters || [];
341342
for (let i = 0, filtersLength = appliedFilters.length; i < filtersLength; i++) {
@@ -357,6 +358,7 @@ export class SearchService implements OnDestroy {
357358
order: config.sort.direction
358359
},
359360
filters: filters,
361+
object,
360362
},
361363
});
362364
}

src/app/search-page/search-page.module.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { CoreModule } from '../core/core.module';
44
import { SharedModule } from '../shared/shared.module';
55
import { SidebarService } from '../shared/sidebar/sidebar.service';
66
import { ConfigurationSearchPageGuard } from './configuration-search-page.guard';
7-
import { SearchTrackerComponent } from './search-tracker.component';
87
import { StatisticsModule } from '../statistics/statistics.module';
98
import { SearchPageComponent } from './search-page.component';
109
import { SidebarFilterService } from '../shared/sidebar/filter/sidebar-filter.service';
@@ -17,7 +16,6 @@ import { SearchModule } from '../shared/search/search.module';
1716

1817
const components = [
1918
SearchPageComponent,
20-
SearchTrackerComponent,
2119
ThemedSearchPageComponent
2220
];
2321

src/app/search-page/search-tracker.component.html

Lines changed: 0 additions & 1 deletion
This file was deleted.

src/app/search-page/search-tracker.component.scss

Lines changed: 0 additions & 3 deletions
This file was deleted.

src/app/search-page/search-tracker.component.ts

Lines changed: 0 additions & 171 deletions
This file was deleted.

src/app/shared/search/search.component.ts

Lines changed: 63 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { ChangeDetectionStrategy, Component, EventEmitter, Inject, Input, OnInit, Output } from '@angular/core';
2-
import { Router } from '@angular/router';
2+
import { NavigationStart, Router } from '@angular/router';
33

44
import { 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';
66
import { uniqueId } from 'lodash';
77

88
import { PaginatedList } from '../../core/data/paginated-list.model';
@@ -11,7 +11,7 @@ import { DSpaceObject } from '../../core/shared/dspace-object.model';
1111
import { pushInOut } from '../animations/push';
1212
import { HostWindowService } from '../host-window.service';
1313
import { SidebarService } from '../sidebar/sidebar.service';
14-
import { hasValue } from '../empty.util';
14+
import { hasValue, hasValueOperator, isNotEmpty } from '../empty.util';
1515
import { RouteService } from '../../core/services/route.service';
1616
import { SEARCH_CONFIG_SERVICE } from '../../my-dspace-page/my-dspace-page.component';
1717
import { PaginatedSearchOptions } from './models/paginated-search-options.model';
@@ -34,6 +34,9 @@ import { CollectionElementLinkType } from '../object-collection/collection-eleme
3434
import { environment } from 'src/environments/environment';
3535
import { SubmissionObject } from '../../core/submission/models/submission-object.model';
3636
import { 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-9a-f]{8}\b-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-\b[0-9a-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

Comments
 (0)