diff --git a/app/app.ts b/app/app.ts index 0d276aa..ccc888a 100644 --- a/app/app.ts +++ b/app/app.ts @@ -1,6 +1,6 @@ import { Component, Type, ViewChild } from '@angular/core'; import { Nav, Platform, Loading } from 'ionic-angular'; -import { Keyboard, Splashscreen, StatusBar } from 'ionic-native'; +import { GoogleAnalytics, Keyboard, Splashscreen, StatusBar } from 'ionic-native'; import { Deploy } from '@ionic/cloud-angular'; import { AuthService } from './services/auth'; @@ -21,13 +21,17 @@ export class LustrumApp { private notifier: NotificationService, private deploy: Deploy ) { - this.initializeCordova(); this.initializeRootPage(); + if (this.platform.is('cordova')) { + this.initializeCordova(); + } } private initializeCordova() { this.platform.ready().then(() => { Keyboard.disableScroll(true); + GoogleAnalytics.startTrackerWithId('UA-79997582-1'); + GoogleAnalytics.enableUncaughtExceptionReporting(true); this.runDeploy(); }); } diff --git a/app/directives/maps-href.ts b/app/directives/maps-href.ts new file mode 100644 index 0000000..963e191 --- /dev/null +++ b/app/directives/maps-href.ts @@ -0,0 +1,37 @@ +import { Directive, ElementRef, Input, OnInit } from '@angular/core'; +import { Platform } from 'ionic-angular'; + + +@Directive({ + selector: '[csrMapsHref]' +}) +export class MapsHrefDirective implements OnInit { + @Input('csrMapsHref') mapsQuery: string; + + private el: HTMLElement; + + constructor( + el: ElementRef, + private platform: Platform + ) { + this.el = el.nativeElement; + } + + ngOnInit() { + let query = encodeURIComponent(this.mapsQuery); + let url = this.getPlatformMapsUrl(); + this.el.setAttribute('href', url + query); + } + + private getPlatformMapsUrl(): string { + if (this.platform.is('mobile')) { + if (this.platform.is('ios')) { + return 'maps://maps.apple.com/?q='; + } else { + return 'geo:0,0?q='; + } + } else { + return 'https://maps.google.com?q='; + } + } +} diff --git a/app/pages/about/about.ts b/app/pages/about/about.ts index 4b8d56f..21a93d7 100644 --- a/app/pages/about/about.ts +++ b/app/pages/about/about.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { Loading, NavController } from 'ionic-angular'; +import { GoogleAnalytics } from 'ionic-native'; import { SystemBrowserDirective } from '../../directives/system-browser'; import { AuthService } from '../../services/auth'; @@ -30,4 +31,8 @@ export class AboutPage { }, 1000); } + ionViewDidEnter() { + GoogleAnalytics.trackView('About'); + } + } diff --git a/app/pages/event-detail/event-detail.html b/app/pages/event-detail/event-detail.html index 4f0653a..0c65085 100644 --- a/app/pages/event-detail/event-detail.html +++ b/app/pages/event-detail/event-detail.html @@ -9,7 +9,7 @@

{{ event.naam || event.titel }}

-

+

{{ event.locatie }}

{{ getDateTimes(event._meta.start, event._meta.end) }}

diff --git a/app/pages/event-detail/event-detail.ts b/app/pages/event-detail/event-detail.ts index eacf8f9..f01b8dc 100644 --- a/app/pages/event-detail/event-detail.ts +++ b/app/pages/event-detail/event-detail.ts @@ -1,16 +1,19 @@ import { Component } from '@angular/core'; import { DomSanitizationService } from '@angular/platform-browser'; import { NavParams, Toast } from 'ionic-angular'; +import { GoogleAnalytics } from 'ionic-native'; import * as moment from 'moment'; import 'moment/locale/nl'; +import { MapsHrefDirective } from '../../directives/maps-href'; import { NotificationService } from '../../services/notification'; import { ApiData } from '../../services/api-data'; import { Event } from '../../models/event'; @Component({ - templateUrl: 'build/pages/event-detail/event-detail.html' + templateUrl: 'build/pages/event-detail/event-detail.html', + directives: [MapsHrefDirective] }) export class EventDetailPage { event: Event; @@ -25,11 +28,6 @@ export class EventDetailPage { this.event = navParams.data; } - getLocationUrl(location: string): any { - let url = 'geo:0,0?q=' + encodeURIComponent(location); - return this.sanitizer.bypassSecurityTrustUrl(url); - } - getDateTimes(start: any, end: any): string { let line1, line2: string; let multipleDays: boolean = !start.isSame(end, 'day'); @@ -77,6 +75,7 @@ export class EventDetailPage { this.apiData.postAction(cat, id, 'aanmelden').then((event: Event) => { this.apiData.addJoined(cat, Number(id)); this.event = this.apiData.addEventMeta(event); + GoogleAnalytics.trackEvent('Events', 'Join', event._meta.category, id); return 'Aanmelden gelukt!'; }, error => { console.log(error); @@ -96,6 +95,7 @@ export class EventDetailPage { this.apiData.postAction(cat, id, 'afmelden').then((event: Event) => { this.apiData.removeJoined(cat, Number(id)); this.event = this.apiData.addEventMeta(event); + GoogleAnalytics.trackEvent('Events', 'Leave', event._meta.category, id); return 'Afmelden gelukt!'; }, error => { console.log(error); @@ -105,4 +105,8 @@ export class EventDetailPage { this.processingAction = false; }); } + + ionViewDidEnter() { + GoogleAnalytics.trackView('Event Detail'); + } } diff --git a/app/pages/event-list/event-list.ts b/app/pages/event-list/event-list.ts index 721549a..6c0ef45 100644 --- a/app/pages/event-list/event-list.ts +++ b/app/pages/event-list/event-list.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { Alert, Modal, NavController } from 'ionic-angular'; +import { GoogleAnalytics } from 'ionic-native'; import * as _ from 'lodash'; import * as moment from 'moment'; import 'moment/locale/nl'; @@ -80,4 +81,8 @@ export class EventListPage { this.nav.push(EventDetailPage, event); } + ionViewDidEnter() { + GoogleAnalytics.trackView('Event List'); + } + } diff --git a/app/pages/map/map.ts b/app/pages/map/map.ts index b041752..fc003b4 100644 --- a/app/pages/map/map.ts +++ b/app/pages/map/map.ts @@ -1,5 +1,6 @@ import { Component } from '@angular/core'; import { NavController } from 'ionic-angular'; +import { GoogleAnalytics } from 'ionic-native'; import { TripDetailPage } from '../trip-detail/trip-detail'; import { TripDetailTwoPage } from '../trip-detail-two/trip-detail-two'; @@ -79,4 +80,8 @@ export class MapPage { mapEle.classList.add('show-map'); }); } + + ionViewDidEnter() { + GoogleAnalytics.trackView('Map'); + } } diff --git a/app/pages/member-detail/member-detail.html b/app/pages/member-detail/member-detail.html index 03b1334..c74005e 100644 --- a/app/pages/member-detail/member-detail.html +++ b/app/pages/member-detail/member-detail.html @@ -2,7 +2,7 @@ {{ member.naam.voornaam }} {{ member.naam.tussenvoegsel }} {{ member.naam.achternaam }} - + @@ -29,7 +29,7 @@

{{ member.email }}

- + @@ -39,7 +39,7 @@

{{ member.email }}

{{ member.mobiel }}

- +

{{ member.huis.naam || 'adres' }}

@@ -71,7 +71,7 @@

{{ member.studie.naam }} ({{ member.studie.sinds }})

- diff --git a/app/pages/member-detail/member-detail.ts b/app/pages/member-detail/member-detail.ts index 58399cb..b507e02 100644 --- a/app/pages/member-detail/member-detail.ts +++ b/app/pages/member-detail/member-detail.ts @@ -1,16 +1,18 @@ import { Component } from '@angular/core'; import { DomSanitizationService } from '@angular/platform-browser'; import { ActionSheet, NavController, NavParams, Platform } from 'ionic-angular'; -import { Contacts, Calendar } from 'ionic-native'; +import { Contacts, Calendar, GoogleAnalytics } from 'ionic-native'; import * as moment from 'moment'; import 'moment/locale/nl'; +import { MapsHrefDirective } from '../../directives/maps-href'; import { NotificationService } from '../../services/notification'; import { Member } from '../../models/member'; @Component({ - templateUrl: 'build/pages/member-detail/member-detail.html' + templateUrl: 'build/pages/member-detail/member-detail.html', + directives: [MapsHrefDirective] }) export class MemberDetailPage { member: Member; @@ -29,12 +31,6 @@ export class MemberDetailPage { this.member.geboortedatum = date; } - getLocationUrl(huis): any { - let q = encodeURIComponent(this.member.huis.adres + ', ' + this.member.huis.woonplaats); - let url = this.platform.is('ios') ? 'maps://maps.apple.com/?q=' : 'geo:0,0?q='; - return this.sanitizer.bypassSecurityTrustUrl(url + q); - } - getSafeUrl(scheme: string, target: string): any { let url = scheme + ':' + encodeURIComponent(target); return this.sanitizer.bypassSecurityTrustUrl(url); @@ -87,6 +83,7 @@ export class MemberDetailPage { let createdContact = Contacts.create(contact); createdContact.save( contact => { + GoogleAnalytics.trackEvent('Members', 'Save', 'New'); this.notifier.notify('Succesvol opgeslagen in contacten.'); }, err => { @@ -106,4 +103,8 @@ export class MemberDetailPage { Calendar.openCalendar(date.toDate()); } + + ionViewDidEnter() { + GoogleAnalytics.trackView('Member Detail'); + } } diff --git a/app/pages/member-list/member-list.html b/app/pages/member-list/member-list.html index ec0f865..2651d6c 100644 --- a/app/pages/member-list/member-list.html +++ b/app/pages/member-list/member-list.html @@ -3,18 +3,18 @@ Ledenlijst - - +
- +
diff --git a/app/pages/member-list/member-list.scss b/app/pages/member-list/member-list.scss index a81681f..2fa69cb 100644 --- a/app/pages/member-list/member-list.scss +++ b/app/pages/member-list/member-list.scss @@ -1,7 +1,8 @@ -.ios .member-list { - min-height: 100%; -} +// Disable as it seems buggy +// .ios .member-list { +// min-height: 100%; +// } .member-list { margin-bottom: 0; diff --git a/app/pages/member-list/member-list.ts b/app/pages/member-list/member-list.ts index 1f9fed7..74df9a8 100644 --- a/app/pages/member-list/member-list.ts +++ b/app/pages/member-list/member-list.ts @@ -1,5 +1,6 @@ -import { Component, ViewChild } from '@angular/core'; +import { Component, Renderer, ViewChild } from '@angular/core'; import { Content, NavController, Platform } from 'ionic-angular'; +import { GoogleAnalytics } from 'ionic-native'; import * as _ from 'lodash'; import { IMemberGroup, IMemberShort } from '../../models/member'; @@ -23,7 +24,8 @@ export class MemberListPage { constructor( private apiData: ApiData, private nav: NavController, - private platform: Platform + private platform: Platform, + private renderer: Renderer ) { apiData.getMemberList().then((members: IMemberShort[]) => { let grouped = _.groupBy(members, c => c.achternaam.replace(/[a-z ']/g, '')[0]); @@ -38,7 +40,8 @@ export class MemberListPage { // Hide searchbar by default on iOS if (this.platform.is('ios')) { - this.content.setScrollTop(44); + // Disable as it seems buggy + // this.content.setScrollTop(44); } }, () => { this.failedToLoad = true; @@ -78,9 +81,13 @@ export class MemberListPage { this.lastQueryText = queryText; } - startSearch() { + startSearch(searchBar) { setTimeout(() => { this.searching = true; + setTimeout(() => { + let el = searchBar._searchbarInput.nativeElement; + this.renderer.invokeElementMethod(el, 'focus', []); + }, 0); }, 200); } @@ -104,4 +111,8 @@ export class MemberListPage { }); } + ionViewDidEnter() { + GoogleAnalytics.trackView('Member List'); + } + } diff --git a/app/pages/tutorial/tutorial.ts b/app/pages/tutorial/tutorial.ts index 4961482..91268de 100644 --- a/app/pages/tutorial/tutorial.ts +++ b/app/pages/tutorial/tutorial.ts @@ -1,6 +1,6 @@ import { Component } from '@angular/core'; import { NavController, Platform } from 'ionic-angular'; -import { StatusBar } from 'ionic-native'; +import { GoogleAnalytics, StatusBar } from 'ionic-native'; import { LoginPage } from '../login/login'; @@ -44,6 +44,7 @@ export class TutorialPage { private ionViewDidEnter() { this.platform.ready().then(() => { StatusBar.styleDefault(); + GoogleAnalytics.trackView('Tutorial'); }); } diff --git a/app/services/auth.ts b/app/services/auth.ts index cbdcfbc..3e9a0a9 100644 --- a/app/services/auth.ts +++ b/app/services/auth.ts @@ -2,6 +2,7 @@ import { Injectable } from '@angular/core'; import { Headers, Http } from '@angular/http'; import { AuthHttp, JwtHelper, tokenNotExpired } from 'angular2-jwt'; import { LocalStorage, Platform, SqlStorage, Storage } from 'ionic-angular'; +import { GoogleAnalytics } from 'ionic-native'; import { Observable } from 'rxjs/Rx'; import { Push } from '@ionic/cloud-angular'; @@ -26,9 +27,7 @@ export class AuthService { this.storage.get('userId').then((userId: string) => { if (userId) { this.userId = userId; - this.push.register((token) => { - this.push.saveToken(token, {}); - }); + this.registerLogin('Automatic'); } }).catch(error => { console.log(error); @@ -80,9 +79,7 @@ export class AuthService { this.localStorage.set('id_token', data.token); this.storage.set('refresh_token', data.refreshToken); this.scheduleRefresh(); - this.push.register((token) => { - this.push.saveToken(token, {}); - }); + this.registerLogin('Manual'); resolve(); }, error => { reject(error); @@ -97,13 +94,33 @@ export class AuthService { this.localStorage.remove('id_token'); this.storage.remove('refresh_token'); this.unscheduleRefresh(); - this.push.unregister(); + this.registerLogout(reload ? 'Automatic' : 'Manual'); if (reload) { location.reload(); } } + private registerLogin(type: string) { + if (this.platform.is('cordova')) { + this.push.register((token) => { + this.push.saveToken(token, {}); + }); + this.platform.ready().then(() => { + GoogleAnalytics.trackEvent('Authorization', 'Login', type); + }); + } + } + + private registerLogout(type: string) { + if (this.platform.is('cordova')) { + this.push.unregister(); + this.platform.ready().then(() => { + GoogleAnalytics.trackEvent('Authorization', 'Logout', type); + }); + } + } + private authenticated(): boolean { return tokenNotExpired(); } diff --git a/package.json b/package.json index 276fd20..8c8c858 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "cordova-plugin-crosswalk-webview@1.7.2", "cordova-plugin-contacts@2.1.0", "cordova-plugin-device@1.1.2", + "cordova-plugin-google-analytics@0.8.1", "cordova-plugin-inappbrowser@1.4.0", "cordova-plugin-splashscreen@3.2.2", "cordova-plugin-statusbar@2.1.3", @@ -87,7 +88,7 @@ "variables": { "SENDER_ID": "335763697269" }, - "locator": "phonegap-plugin-push@1.7.1", + "locator": "phonegap-plugin-push@1.7.2", "id": "phonegap-plugin-push" } ],