import { Injectable } from '@angular/core'; import { map, take, } from 'rxjs/operators'; import { RequestService } from '../core/data/request.service'; import { RestRequest } from '../core/data/rest-request.model'; import { DSpaceObject } from '../core/shared/dspace-object.model'; import { HALEndpointService } from '../core/shared/hal-endpoint.service'; import { hasValue, isNotEmpty, } from '../shared/empty.util'; import { SearchOptions } from '../shared/search/models/search-options.model'; import { TrackRequest } from './track-request.model'; /** * The statistics service */ @Injectable({ providedIn: 'root' }) export class StatisticsService { constructor( protected requestService: RequestService, protected halService: HALEndpointService, ) { } private sendEvent(linkPath: string, body: any) { const requestId = this.requestService.generateRequestId(); this.halService.getEndpoint(linkPath).pipe( map((endpoint: string) => new TrackRequest(requestId, endpoint, JSON.stringify(body))), take(1), // otherwise the previous events will fire again ).subscribe((request: RestRequest) => this.requestService.send(request)); } /** * To track a page view * @param dso: The dso which was viewed * @param referrer: The referrer used by the client to reach the dso page */ trackViewEvent( dso: DSpaceObject, referrer: string, ) { this.sendEvent('/statistics/viewevents', { targetId: dso.uuid, targetType: (dso as any).type, referrer, }); } /** * To track a search * @param searchOptions: The query, scope, dsoType and configuration of the search. Filters from this object are ignored in favor of the filters parameter of this method. * @param page: An object that describes the pagination status * @param sort: An object that describes the sort status * @param filters: An array of search filters used to filter the result set * @param clickedObject: UUID of object clicked */ trackSearchEvent( searchOptions: SearchOptions, page: { size: number, totalElements: number, totalPages: number, number: number }, sort: { by: string, order: string }, filters?: { filter: string, operator: string, value: string, label: string }[], clickedObject?: string, ) { const body = { query: searchOptions.query, page: { size: page.size, totalElements: page.totalElements, totalPages: page.totalPages, number: page.number, }, sort: { by: sort.by, order: sort.order.toLowerCase(), }, }; if (hasValue(searchOptions.configuration)) { Object.assign(body, { configuration: searchOptions.configuration }); } if (isNotEmpty(searchOptions.dsoTypes)) { Object.assign(body, { dsoType: searchOptions.dsoTypes[0].toLowerCase() }); } if (hasValue(searchOptions.scope)) { Object.assign(body, { scope: searchOptions.scope }); } if (isNotEmpty(filters)) { const bodyFilters = []; for (let i = 0, arrayLength = filters.length; i < arrayLength; i++) { const filter = filters[i]; bodyFilters.push({ filter: filter.filter, operator: filter.operator, value: filter.value, label: filter.label, }); } Object.assign(body, { appliedFilters: bodyFilters }); } if (hasValue(clickedObject)) { Object.assign(body, { clickedObject }); } this.sendEvent('/statistics/searchevents', body); } }