WIP
This commit is contained in:
parent
5fb33cffbf
commit
f96dd0bfe2
18 changed files with 2407 additions and 2298 deletions
4366
package-lock.json
generated
4366
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -54,6 +54,7 @@
|
|||
"devDependencies": {
|
||||
"@angular/cli": "1.7.3",
|
||||
"@angular/compiler-cli": "5.2.0",
|
||||
"@types/google.analytics": "0.0.39",
|
||||
"@types/jasmine": "2.8.2",
|
||||
"@types/jasminewd2": "2.0.3",
|
||||
"@types/node": "8.0.52",
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
|
||||
import { ConfigService } from './config.service';
|
||||
import { PushService } from './push.service';
|
||||
import { PushComponent } from './push/push.component';
|
||||
import { HttpModule } from '@angular/http';
|
||||
|
||||
|
||||
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
import { environment } from '../environments/environment';
|
||||
|
||||
|
@ -68,7 +62,6 @@ import { DashboardModule } from './dashboard/dashboard.module';
|
|||
],
|
||||
declarations: [
|
||||
AppComponent,
|
||||
PushComponent,
|
||||
FullLayoutComponent,
|
||||
SimpleLayoutComponent,
|
||||
NAV_DROPDOWN_DIRECTIVES,
|
||||
|
@ -79,8 +72,6 @@ import { DashboardModule } from './dashboard/dashboard.module';
|
|||
P500Component,
|
||||
],
|
||||
providers: [
|
||||
ConfigService,
|
||||
PushService,
|
||||
AuthGuard,
|
||||
OrgGuard,
|
||||
CustomerGuard,
|
||||
|
@ -100,4 +91,10 @@ import { DashboardModule } from './dashboard/dashboard.module';
|
|||
],
|
||||
bootstrap: [ AppComponent ]
|
||||
})
|
||||
export class AppModule { }
|
||||
export class AppModule {
|
||||
constructor () {
|
||||
if (environment.enableAnalytics) {
|
||||
(<any>window).ga('create', environment.analyticsKey, 'auto');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,3 +175,16 @@
|
|||
</div>
|
||||
</div><!--/.row-->
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<strong>Push Notification Settings</strong>
|
||||
<small>Would you like to recieve notfications from companys about their latests offers?</small>
|
||||
<div class="card-body">
|
||||
<app-push></app-push>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import { Component } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import {Router, NavigationEnd} from "@angular/router";
|
||||
import { GraphWidget } from '../widgets/graph-widget.component';
|
||||
import { OrgBarSnippetComponent } from '../snippets/org-snippet-bar.component';
|
||||
import { GraphPanel } from '../panels/graph-panel.component';
|
||||
import { DataType } from '../shared/data-types.enum';
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
@Component({
|
||||
templateUrl: 'dashboard.component.html'
|
||||
|
@ -50,6 +51,14 @@ export class DashboardComponent {
|
|||
dataType: DataType.currency,
|
||||
},
|
||||
];
|
||||
|
||||
constructor() { }
|
||||
constructor(private router: Router) {
|
||||
if (environment.enableAnalytics) {
|
||||
this.router.events.subscribe(event => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
(<any>window).ga('set', 'page', event.urlAfterRedirects);
|
||||
(<any>window).ga('send', 'pageview');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ import { FeedbackComponent } from './feedback.component';
|
|||
import { TransactionLogComponent } from './transaction-log.component';
|
||||
import { CategoryMonthComponent } from './category-month.component';
|
||||
import { PayrollLogComponent } from './payroll-log.component';
|
||||
import { OrgPushComponent } from './org-push.component';
|
||||
|
||||
import { LeaderboardComponent } from './leaderboard.component';
|
||||
import { MapComponent } from './map.component';
|
||||
import { TrailMapComponent } from './trail-map.component';
|
||||
|
@ -35,6 +37,10 @@ import { TransactionResultComponent } from '../shared/transaction-result.compone
|
|||
import { PayrollResultComponent } from '../shared/payroll-result.component';
|
||||
import { LeaderboardResultComponent } from '../shared/leaderboard-result.component';
|
||||
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { ConfigService } from '../config.service';
|
||||
import { PushComponent } from '../push/push.component';
|
||||
|
||||
// API key env variable import
|
||||
import { environment } from '../../environments/environment';
|
||||
|
||||
|
@ -42,6 +48,7 @@ import { environment } from '../../environments/environment';
|
|||
imports: [
|
||||
// Angular imports
|
||||
CommonModule,
|
||||
MatButtonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
ChartsModule,
|
||||
|
@ -56,6 +63,7 @@ import { environment } from '../../environments/environment';
|
|||
],
|
||||
declarations: [
|
||||
DashboardComponent,
|
||||
PushComponent,
|
||||
DashboardCustomerComponent,
|
||||
AccountEditComponent,
|
||||
AddDataComponent,
|
||||
|
@ -66,6 +74,7 @@ import { environment } from '../../environments/environment';
|
|||
TransactionResultComponent,
|
||||
PayrollLogComponent,
|
||||
PayrollResultComponent,
|
||||
OrgPushComponent,
|
||||
LeaderboardComponent,
|
||||
LeaderboardResultComponent,
|
||||
MapComponent,
|
||||
|
@ -80,6 +89,7 @@ import { environment } from '../../environments/environment';
|
|||
providers: [
|
||||
CurrencyPipe,
|
||||
GoogleMapsAPIWrapper,
|
||||
ConfigService
|
||||
],
|
||||
})
|
||||
export class DashboardModule { }
|
||||
|
|
|
@ -14,6 +14,7 @@ import { FeedbackComponent } from './feedback.component';
|
|||
import { TransactionLogComponent } from './transaction-log.component';
|
||||
import { CategoryMonthComponent } from './category-month.component';
|
||||
import { PayrollLogComponent } from './payroll-log.component';
|
||||
import { OrgPushComponent } from './org-push.component';
|
||||
import { LeaderboardComponent } from './leaderboard.component';
|
||||
import { MapComponent } from './map.component';
|
||||
import { TrailMapComponent } from './trail-map.component';
|
||||
|
@ -80,6 +81,12 @@ const routes: Routes = [
|
|||
data: { title: 'Payroll Log' },
|
||||
canActivate: [OrgGuard],
|
||||
},
|
||||
{
|
||||
path: 'org-push',
|
||||
component: OrgPushComponent,
|
||||
data: { title: 'Push Notifications' },
|
||||
canActivate: [OrgGuard],
|
||||
},
|
||||
{
|
||||
path: 'feedback',
|
||||
component: FeedbackComponent,
|
||||
|
|
47
src/app/dashboard/org-push.component.html
Normal file
47
src/app/dashboard/org-push.component.html
Normal file
|
@ -0,0 +1,47 @@
|
|||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<strong>Push Notifcations</strong>
|
||||
<small>Here you can send push notifications about sales to users</small>
|
||||
</div>
|
||||
<form class="form-horizontal" [formGroup]="pushForm" (ngSubmit)="onSubmit()">
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Title</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" formControlName="title">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Body</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" formControlName="body">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-block">
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Icon</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="text" class="form-control" formControlName="icon">
|
||||
<span class="help-block">Enter URL to Icon you would like to use.</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-md-3 form-control-label" for="text-input"><strong>Personalise Notifcations</strong></label>
|
||||
<div class="col-md-9">
|
||||
<input type="checkbox" class="form-control" formControlName="personalised" (change)="toggleEditable($event)" >
|
||||
<span class="help-block">Tick if you want to personalise notifications adding the users name.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<button type="submit" class="btn btn-sm btn-primary"><i class="fa fa-dot-circle-o"></i> Submit</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
47
src/app/dashboard/org-push.component.ts
Normal file
47
src/app/dashboard/org-push.component.ts
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { Component} from '@angular/core';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import { Validators, FormBuilder, FormGroup } from '@angular/forms';
|
||||
|
||||
|
||||
|
||||
@Component({
|
||||
templateUrl: './org-push.component.html'
|
||||
})
|
||||
|
||||
export class OrgPushComponent{
|
||||
pushForm: FormGroup;
|
||||
personalised = false;
|
||||
|
||||
constructor(
|
||||
private formBuilder: FormBuilder,
|
||||
private api: ApiService,
|
||||
) {
|
||||
this.pushForm = this.formBuilder.group({
|
||||
title: ['', [Validators.required]],
|
||||
body: ['', [Validators.required]],
|
||||
icon: ['', [Validators.required]],
|
||||
personalised: [true, [Validators.required]],
|
||||
});
|
||||
}
|
||||
|
||||
onSubmit(){
|
||||
console.log(this.pushForm.value)
|
||||
console.log(this.personalised)
|
||||
this.api.sendNotification(this.pushForm.value)
|
||||
.subscribe(
|
||||
res => {
|
||||
console.log('Message Sent', res)
|
||||
},
|
||||
err => {
|
||||
console.log('Message Failed to send', err)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
toggleEditable(event) {
|
||||
if ( event.target.checked ) {
|
||||
this.personalised = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -19,7 +19,6 @@
|
|||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<app-push>HELLO</app-push>
|
||||
</header>
|
||||
<div class="app-body">
|
||||
<div class="sidebar">
|
||||
|
@ -97,6 +96,14 @@
|
|||
</div>
|
||||
</a>
|
||||
</li>
|
||||
<li *ngIf="accountType == 'organisation'" class="nav-item">
|
||||
<a class="nav-link" routerLinkActive="active" [routerLink]="['/org-push']">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col-2"><i class="icon-envelope-letter"></i></div>
|
||||
<div class="col-10">Push Notifications</div>
|
||||
</div>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
|
|
@ -240,6 +240,14 @@ export class ApiService {
|
|||
);
|
||||
}
|
||||
|
||||
public sendNotification(data) {
|
||||
data.session_key = this.sessionKey;
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/push/org_send_notification',
|
||||
data
|
||||
);
|
||||
}
|
||||
|
||||
// Deletes account details on logout
|
||||
|
||||
public removeUserInfo() {
|
||||
|
@ -273,6 +281,32 @@ export class ApiService {
|
|||
localStorage.getItem('email');
|
||||
}
|
||||
|
||||
//Push Api
|
||||
|
||||
public addSubscriber(data) {
|
||||
const key = this.sessionKey;
|
||||
console.log(data)
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/subscription/add',
|
||||
{
|
||||
session_key : key,
|
||||
data : data
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public deleteSubscriber(data) {
|
||||
const key = this.sessionKey;
|
||||
console.log(data)
|
||||
return this.http.post<any>(
|
||||
this.apiUrl + '/subscription/delete',
|
||||
{
|
||||
session_key : key,
|
||||
data : data
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Leaderboard Api
|
||||
|
||||
public leaderboard_fetch(
|
||||
|
|
|
@ -1,73 +0,0 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/operator/catch';
|
||||
import 'rxjs/add/operator/map';
|
||||
import 'rxjs/add/observable/throw';
|
||||
|
||||
import { ConfigService } from './config.service';
|
||||
|
||||
@Injectable()
|
||||
export class PushService {
|
||||
|
||||
private API_URL: string
|
||||
|
||||
constructor(private http: HttpClient, private configService: ConfigService) {
|
||||
this.API_URL = this.configService.get('API_URL')
|
||||
}
|
||||
|
||||
// urlBase64ToUint8Array(base64String) {
|
||||
// const padding = '='.repeat((4 - base64String.length % 4) % 4);
|
||||
// const base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/');
|
||||
// const rawData = window.atob(base64);
|
||||
// const outputArray = new Uint8Array(rawData.length);
|
||||
// for (let i = 0; i < rawData.length; ++i) {
|
||||
// outputArray[i] = rawData.charCodeAt(i);
|
||||
// }
|
||||
// return outputArray;
|
||||
// }
|
||||
|
||||
addSubscriber(subscription) {
|
||||
|
||||
const url = `${this.API_URL}/webpush`;
|
||||
console.log('[Push Service] Adding subscriber')
|
||||
|
||||
let body = {
|
||||
action: 'subscribe',
|
||||
subscription: subscription
|
||||
}
|
||||
|
||||
return this.http
|
||||
.post(url, body)
|
||||
.catch(this.handleError);
|
||||
|
||||
}
|
||||
|
||||
deleteSubscriber(subscription) {
|
||||
|
||||
const url = `${this.API_URL}/webpush`;
|
||||
console.log('[Push Service] Deleting subscriber')
|
||||
|
||||
let body = {
|
||||
action: 'unsubscribe',
|
||||
subscription: subscription
|
||||
}
|
||||
|
||||
return this.http
|
||||
.post(url, body)
|
||||
.catch(this.handleError);
|
||||
|
||||
}
|
||||
|
||||
private handleError(error: Response | any) {
|
||||
let errMsg: string;
|
||||
if (error instanceof Response) {
|
||||
errMsg = `${error.statusText || 'Network error'}`;
|
||||
} else {
|
||||
errMsg = error.message ? error.message : error.toString();
|
||||
}
|
||||
return Observable.throw(errMsg);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
.button{
|
||||
padding: 15px 32px;
|
||||
}
|
|
@ -1,3 +1,2 @@
|
|||
<button (click)="subscribeToPush()">Subscribe To Push</button>
|
||||
<button (click)="unsubscribeFromPush()">Unsubscribe From Push</button>
|
||||
{{target}}
|
||||
<button mat-raised-button (click)="subscribeToPush()" [disabled]=subscribeButton>Subscribe To Pushs</button>
|
||||
<button mat-raised-button (click)="unsubscribeFromPush()" [disabled]=unsubscribeButton>Unsubscribe From Push</button>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { Component, OnInit } from '@angular/core';
|
||||
import { ConfigService } from './../config.service';
|
||||
import { PushService } from './../push.service';
|
||||
import { SwPush } from '@angular/service-worker';
|
||||
import { ApiService } from '../providers/api-service';
|
||||
import "rxjs/Rx";
|
||||
|
||||
|
||||
|
@ -12,13 +12,15 @@ import "rxjs/Rx";
|
|||
})
|
||||
export class PushComponent implements OnInit {
|
||||
|
||||
subscribeButton = false;
|
||||
unsubscribeButton = true;
|
||||
|
||||
private VAPID_PUBLIC_KEY: string;
|
||||
|
||||
tweets = []
|
||||
target = ''
|
||||
|
||||
|
||||
constructor(private pushService: PushService, private configService: ConfigService, private swPush: SwPush) {
|
||||
constructor(private api: ApiService, private configService: ConfigService, private swPush: SwPush) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
|
@ -36,51 +38,39 @@ export class PushComponent implements OnInit {
|
|||
|
||||
// Passing subscription object to our backend
|
||||
console.log(pushSubscription.endpoint)
|
||||
this.target = JSON.stringify(pushSubscription);
|
||||
console.log(pushSubscription.getKey)
|
||||
this.pushService.addSubscriber(pushSubscription)
|
||||
this.api.addSubscriber(pushSubscription)
|
||||
.subscribe(
|
||||
|
||||
res => {
|
||||
console.log('[App] Add subscriber request answer', res)
|
||||
this.subscribeButton = true;
|
||||
this.unsubscribeButton = false;
|
||||
},
|
||||
err => {
|
||||
console.log('[App] Add subscriber request failed', err)
|
||||
}
|
||||
|
||||
)
|
||||
})
|
||||
.catch(err => {
|
||||
console.error(err);
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
showNotification(){
|
||||
this.swPush.messages.subscribe(message => {
|
||||
console.log('[App] Push message received', message)
|
||||
})
|
||||
}
|
||||
|
||||
unsubscribeFromPush(){
|
||||
|
||||
this.subscribeButton = false;
|
||||
this.unsubscribeButton = true;
|
||||
// Get active subscription
|
||||
|
||||
this.swPush.subscription
|
||||
.take(1)
|
||||
.subscribe(pushSubscription => {
|
||||
|
||||
console.log('[App] pushSubscription', pushSubscription)
|
||||
|
||||
// Delete the subscription from the backend
|
||||
|
||||
this.pushService.deleteSubscriber(pushSubscription)
|
||||
this.api.deleteSubscriber(pushSubscription)
|
||||
.subscribe(
|
||||
|
||||
res => {
|
||||
console.log('[App] Delete subscriber request answer', res)
|
||||
// Unsubscribe current client (browser)
|
||||
|
||||
pushSubscription.unsubscribe()
|
||||
.then(success => {
|
||||
console.log('[App] Unsubscription successful', success)
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
|
||||
export const environment = {
|
||||
production: false,
|
||||
apiUrl: 'https://dev.peartrade.org/api',
|
||||
mapApiKey: 'CHANGEME',
|
||||
apiUrl: 'http://localhost:3000/api',
|
||||
mapApiKey: 'AIzaSyBhm0iaIGG0Ko5IsfZx-CpLt01YHkp4Y1w',
|
||||
config: {
|
||||
"VAPID_PUBLIC_KEY": "BMDZ6FANqsYRF9iGo3Ki0LdltGZZksgIFbgxBr_otO0H7jTFgcm3v2bGSgnVGJ5bidvLvuKStirfDNl4khVBiok"
|
||||
},
|
||||
enableAnalytics: false,
|
||||
analyticsKey: ''
|
||||
};
|
||||
|
|
|
@ -122,6 +122,15 @@
|
|||
<div class="sk-cube3 sk-cube"></div>
|
||||
</div>
|
||||
</app-root>
|
||||
<app-root></app-root>
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-119198369-1', 'auto');
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
|
@ -10,14 +10,12 @@ const options = {
|
|||
}
|
||||
|
||||
// NgPushRegistration-Object from the browser
|
||||
const pushSubscription = {"endpoint":"https://fcm.googleapis.com/fcm/send/dQn-7TOL3dM:APA91bHLuAR3G-XLxsSsjvo_P5UIEwrPS85Ho-fUZOFMpuuubEFgU6_dfgMZJvgvIOLCpSbRjPc_iWCdjgFz9snS3Rtg5H3H14RDeKt051CQp441PqqXrKHwR5ICpEyLV3x3jcEmGF8Q","expirationTime":null,"keys":{"p256dh":"BBq-RpOiUXSucWCUj8RrFy5jwKRZ6Rv9y7AHYqbE-0vIestbyRt8oxAC2yrbkwuKgPRYAElC32Sbs_Wo2mXNpJU=","auth":"sbIdhYisA6_Kc3_hDYJdog=="}};
|
||||
const pushSubscription = {"endpoint":"https://updates.push.services.mozilla.com/wpush/v2/gAAAAABanrgBKoC1etG5UeixhypVGQhGJoV5VtY72jIxx7rp0Bh3O4LZ4OmeYvGQgl0RxYD0ENNIzzMYTe0pgaynEOysvkyo4ybM6mHu_xFYrc9imf2F7lIuBCILCEjANG1gDoAWVRmBEMk0ZlYE4mq0KcoBjxwQDKTZsM4gITPmJdFxaCWRSls","keys":{"auth":"0uFlXtWtJH4arEGej3L_dQ","p256dh":"BMi13v5aFEgFgTwlSVDBv4uaxLOAdZ50U_-ITaP_-Brt6X3WN9gsl4G4oxhxTIj25zECdLARItXTJZ-Sof-O5bU"}};
|
||||
|
||||
const payload = JSON.stringify({
|
||||
notification: {
|
||||
title: 'Info',
|
||||
body: 'Hallo Welt!',
|
||||
icon: './assets/angular.png',
|
||||
data: 'additional data'
|
||||
title: '*TITLE*',
|
||||
body: '*BODY*',
|
||||
}
|
||||
});
|
||||
|
||||
|
|
Reference in a new issue