Skip to content

Commit

Permalink
Merge pull request #354 from Sunbird-cQube/dev
Browse files Browse the repository at this point in the history
merge dev to staging
  • Loading branch information
htvenkatesh authored Sep 13, 2023
2 parents d44b14d + 644a4e0 commit f1b6c74
Show file tree
Hide file tree
Showing 21 changed files with 320 additions and 21 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
"ng-circle-progress": "^1.6.0",
"ngx-bootstrap": "^9.0.0",
"ngx-daterangepicker-material": "^6.0.4",
"ngx-device-detector": "^4.0.1",
"ngx-spinner": "^14.0.0",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
Expand Down
33 changes: 20 additions & 13 deletions src/app/app.component.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Component } from '@angular/core';
import { Component, HostListener } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { environment } from 'src/environments/environment';
import { Router, NavigationStart, NavigationEnd, NavigationCancel, NavigationError, Event, ActivatedRoute } from '@angular/router';
import { filter, map } from 'rxjs/operators';
import { Title } from '@angular/platform-browser';
import { AppConfig } from './app.config';
import { HttpClient } from '@angular/common/http';
import { PageTrackerService } from './core/services/page-tracker.service';
declare const gtag: Function; // <------------Important: the declartion for gtag is required!
declare var dataLayer: Array<any>;

Expand All @@ -19,7 +19,7 @@ export class AppComponent {
title = 'cQube National';
loadingDataImg: boolean = false;
constructor(private translate: TranslateService, private titleService: Title,
private router: Router, private activatedRoute: ActivatedRoute, public config: AppConfig, private http: HttpClient) {
private router: Router, private activatedRoute: ActivatedRoute, public config: AppConfig, private http: HttpClient, private pageTrackerService: PageTrackerService) {
translate.setDefaultLang('en');
translate.use('en');
/** START : Code to Track Page View using gtag.js */
Expand All @@ -41,18 +41,20 @@ export class AppComponent {
// })
// })

// //Add dynamic title for selected pages - Start
// router.events.subscribe(event => {
// if (event instanceof NavigationEnd) {
// var title = this.getTitle(router.routerState, router.routerState.root).join(' > ');
// titleService.setTitle(title);
// }
// });

//Add dynamic title for selected pages - Start
router.events.subscribe(event => {
if (event instanceof NavigationEnd) {
if (event.url !== '/login') {
this.pageTrackerService.onPageChange(event);
}
}
});
}

ngOnInit() {
window.scrollTo(0, 0);
}

// collect that title data properties from all child routes
getTitle(state, parent) {
var data = [];
Expand Down Expand Up @@ -88,7 +90,7 @@ export class AppComponent {
}
}

async grabTheTrackIds(trackIds) {
async grabTheTrackIds(trackIds) {
for (const [key, value] of Object.entries(trackIds)) {
const gaTrackId = value;
let customGtagScriptEle = document.createElement('script');
Expand All @@ -107,5 +109,10 @@ export class AppComponent {
}
}


@HostListener('window:beforeunload', ['$event'])
handleUnload(event: Event): void {
if (this.router.url !== '/login') {
this.pageTrackerService.onPageChange(event);
}
}
}
16 changes: 16 additions & 0 deletions src/app/core/services/browser-detection.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { BrowserDetectionService } from './browser-detection.service';

describe('BrowserDetectionService', () => {
let service: BrowserDetectionService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(BrowserDetectionService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
27 changes: 27 additions & 0 deletions src/app/core/services/browser-detection.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Injectable } from '@angular/core';

@Injectable({
providedIn: 'root'
})
export class BrowserDetectionService {

constructor() { }

getBrowserType(): string {
const userAgent = window.navigator.userAgent;

if (userAgent.indexOf('Chrome') !== -1) {
return 'Chrome';
} else if (userAgent.indexOf('Firefox') !== -1) {
return 'Firefox';
} else if (userAgent.indexOf('Safari') !== -1) {
return 'Safari';
} else if (userAgent.indexOf('Edge') !== -1) {
return 'Edge';
} else if (userAgent.indexOf('IE') !== -1 || userAgent.indexOf('Trident/') !== -1) {
return 'Internet Explorer';
} else {
return 'Unknown';
}
}
}
16 changes: 16 additions & 0 deletions src/app/core/services/device-detection.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { DeviceDetectionService } from './device-detection.service';

describe('DeviceDetectionService', () => {
let service: DeviceDetectionService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(DeviceDetectionService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
21 changes: 21 additions & 0 deletions src/app/core/services/device-detection.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Injectable } from '@angular/core';
import { DeviceDetectorService } from 'ngx-device-detector';

@Injectable({
providedIn: 'root'
})
export class DeviceDetectionService {
constructor(private deviceService: DeviceDetectorService) {}

getDeviceType(): string {
if (this.deviceService.isDesktop()) {
return 'Desktop';
} else if (this.deviceService.isTablet()) {
return 'Tablet';
} else if (this.deviceService.isMobile()) {
return 'Mobile';
} else {
return 'Unknown';
}
}
}
16 changes: 16 additions & 0 deletions src/app/core/services/dom-event-tracker.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { DomEventTrackerService } from './dom-event-tracker.service';

describe('DomEventTrackerService', () => {
let service: DomEventTrackerService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(DomEventTrackerService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
29 changes: 29 additions & 0 deletions src/app/core/services/dom-event-tracker.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { Injectable } from '@angular/core';
import { TelemetryService } from './telemetry.service';
import { Router } from '@angular/router';

@Injectable({
providedIn: 'root'
})
export class DomEventTrackerService {

constructor(private readonly _router: Router, private readonly _telemetryService: TelemetryService) { }

onClick(event): void {
const { pageName, eventName } = event;
this._telemetryService.saveTelemetry({
pageName: pageName ? pageName : this._router.url?.slice(1),
pageEvent: "click",
pageEventName: eventName ? eventName : "filter"
}).subscribe(res => console.log('telemetry saved!!!'));;
}

onChange(event): void {
const { pageName, eventName } = event;
this._telemetryService.saveTelemetry({
pageName: pageName ? pageName : this._router.url?.slice(1),
pageEvent: "change",
pageEventName: eventName ? eventName : "filter"
}).subscribe(res => console.log('telemetry saved!!!'));;
}
}
16 changes: 16 additions & 0 deletions src/app/core/services/page-tracker.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { PageTrackerService } from './page-tracker.service';

describe('PageTrackerService', () => {
let service: PageTrackerService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(PageTrackerService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
30 changes: 30 additions & 0 deletions src/app/core/services/page-tracker.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Injectable } from '@angular/core';
import { TelemetryService } from './telemetry.service';

@Injectable({
providedIn: 'root'
})
export class PageTrackerService {

previousRoute: string;
startTime: Date;

constructor(private readonly _telemetryService: TelemetryService) { }

onPageChange(event): void {
if (this.previousRoute && event.url !== this.previousRoute) {
const now = new Date();
this._telemetryService.saveTelemetry({
pageName: this.previousRoute.slice(1),
pageEvent: "onLoad",
pageEventName: "onLoad",
timeSpent: (now.getTime() - this.startTime.getTime()),
timeIn: this.startTime.getTime(),
timeOut: now.getTime()
}).subscribe(res => console.log('telemetry saved!!!'));
}

this.startTime = new Date();
this.previousRoute = event.url;
}
}
16 changes: 16 additions & 0 deletions src/app/core/services/telemetry.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';

import { TelemetryService } from './telemetry.service';

describe('TelemetryService', () => {
let service: TelemetryService;

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(TelemetryService);
});

it('should be created', () => {
expect(service).toBeTruthy();
});
});
29 changes: 29 additions & 0 deletions src/app/core/services/telemetry.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { BrowserDetectionService } from './browser-detection.service';
import { DeviceDetectionService } from './device-detection.service';
import { formatDateToDDMMYY } from 'src/app/utilities/DateFormatter';

@Injectable({
providedIn: 'root'
})
export class TelemetryService {

constructor(private _http: HttpClient, private _browserDetectionService: BrowserDetectionService, private _deviceDetectionService: DeviceDetectionService) { }

saveTelemetry(eventData: any): Observable<any> {
let data = {
date: formatDateToDDMMYY(new Date()),
timestamp: new Date().getTime(),
userId: localStorage.getItem('user_id'),
deviceType: this._deviceDetectionService.getDeviceType(),
userLocation: "",
browserType: this._browserDetectionService.getBrowserType(),
...eventData
};

return this._http.post<any>(`${environment.apiURL}/captureTelemetry`, data);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
<i class="download-icon fa fa-download"></i>
</div> -->
<div *ngIf='(pagereportName == "student_assessment") || (pagereportName == "teachers_present") ||( pagereportName == "school_infra") ||( pagereportName == "school_progression") || (pagereportName == "school"); else templateName'>
<button class="btn" (click)="onDownload()" id="downloadButton">
<button class="btn" (click)="onDownload()" id="downloadButton" [attr.data-page-name]="pagereportName" [attr.data-event-name]="'download'" appClick>
<span class="button-text">School Report</span>
</button>
<!-- <i class="download-icon fa fa-2x fa-download"></i> -->
</div>

<ng-template #templateName>
<button class="btn" (click)="onDownload()" id="downloadButton">
<button class="btn" (click)="onDownload()" id="downloadButton" [attr.data-page-name]="pagereportName" [attr.data-event-name]="'download'" appClick>
<span class="button-text">Unit level report</span>
</button>
</ng-template>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<ng-select #selectRef class="mx-2 custom-dropdown" dropdownPosition="bottom" [id]="'filter-'+filter.name"
[name]="'filter-'+filter.name" [multiple]="isFilterMulti()" [closeOnSelect]="false"
placeholder="Select {{filter.name}}" [clearable]="resetOthers" [(ngModel)]="filter.value"
(ngModelChange)="onSelectOption($event, i, selectRef)">
(ngModelChange)="onSelectOption($event, i, selectRef)" appChange>
<ng-option *ngFor="let option of filter.options" [value]="option.value">{{ option.label }}</ng-option>
</ng-select>
</div>
Expand Down
8 changes: 8 additions & 0 deletions src/app/shared/directives/change.directive.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ChangeDirective } from './change.directive';

describe('ChangeDirective', () => {
it('should create an instance', () => {
const directive = new ChangeDirective();
expect(directive).toBeTruthy();
});
});
20 changes: 20 additions & 0 deletions src/app/shared/directives/change.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Directive, ElementRef, HostListener } from '@angular/core';
import { DomEventTrackerService } from 'src/app/core/services/dom-event-tracker.service';

@Directive({
selector: '[appChange]'
})
export class ChangeDirective {

constructor(private el: ElementRef, private readonly _domEventTrackerService: DomEventTrackerService) { }

@HostListener('change') onChange() {
const eventName = this.el.nativeElement.getAttribute("data-event-name");
const pageName = this.el.nativeElement.getAttribute("data-page-name");
this._domEventTrackerService.onChange({
eventName,
pageName
});
}

}
8 changes: 8 additions & 0 deletions src/app/shared/directives/click.directive.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { ClickDirective } from './click.directive';

describe('ClickDirective', () => {
it('should create an instance', () => {
const directive = new ClickDirective();
expect(directive).toBeTruthy();
});
});
20 changes: 20 additions & 0 deletions src/app/shared/directives/click.directive.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { Directive, ElementRef, HostListener } from '@angular/core';
import { DomEventTrackerService } from 'src/app/core/services/dom-event-tracker.service';

@Directive({
selector: '[appClick]'
})
export class ClickDirective {

constructor(private el: ElementRef, private readonly _domEventTrackerService: DomEventTrackerService) { }

@HostListener('click') onClick() {
const eventName = this.el.nativeElement.getAttribute("data-event-name");
const pageName = this.el.nativeElement.getAttribute("data-page-name");
this._domEventTrackerService.onClick({
eventName,
pageName
});
}

}
Loading

0 comments on commit f1b6c74

Please sign in to comment.