Skip to content

Commit

Permalink
Added basic chapter 6 code
Browse files Browse the repository at this point in the history
  • Loading branch information
deanhume committed Dec 31, 2016
1 parent 99a3df3 commit 7fa21cc
Show file tree
Hide file tree
Showing 17 changed files with 637 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -0,0 +1 @@
node_modules
29 changes: 29 additions & 0 deletions chapter-6/push-notifications/article.html
@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<title>Progressive Times - Article</title>
<link href="https://fonts.googleapis.com/css?family=Raleway|Merriweather" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="./css/site.css">
</head>
<body>
<!-- header -->
<div id="article-header">
<div id="article-title"></div>
</div>
<!-- article -->
<p id="article"></p>
<hr>
<!-- scripts -->
<script async src="./js/article.js"></script>
<script>
// Register the service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.js').then(function(registration) {
// Registration was successful
});
}
</script>
</body>
</html>
18 changes: 18 additions & 0 deletions chapter-6/push-notifications/css/site.css
@@ -0,0 +1,18 @@
body{ font-family: 'Raleway', sans-serif; }
h1 { text-align: center;font-size: 60px;font-family: 'Merriweather', cursive; margin-top: 0px;}
h6 {text-align: center; font-size: 20px; margin-top: -32px;}
hr { border-top: 1px dashed #8c8b8b; width: 300px; }
a { text-decoration: none; color: black; }
a:hover { text-decoration: underline; }
p { width: 70%; margin: auto; text-align: center;padding-bottom: 20px; font-size: 18px; }
#header { background-color: gold; width: 100%; position: absolute; top: 0; left: 0; height: 200px;}
#latest { text-align: center; margin-top: 220px; }
#article-header { background-color: #03A9F4; width: 100%; position: absolute; top: 0; left: 0; height: 200px; }
#article-title { text-align: center; font-size: 54px; font-family: 'Merriweather', cursive; color: white;padding-top: 50px; }
#article { margin-top: 220px;}
#logo { margin-left: auto; margin-right: auto; width: 50px; display: block; padding-top: 25px; }

@media screen and (max-width: 550px) {
h1 { text-align: center;font-size: 40px;font-family: 'Merriweather', cursive; margin-top: 0px;}
#article-title { text-align: center; font-size: 40px; font-family: 'Merriweather', cursive; color: white;padding-top: 50px; }
}
5 changes: 5 additions & 0 deletions chapter-6/push-notifications/data/data-1.json
@@ -0,0 +1,5 @@
{
"id": 1,
"title": "Nose picking ban for Manila police",
"description": "Police in the Philippines have been warned not to take selfies or pick their noses while on duty, it's reported. <br><br> A memorandum issued by the National Capital Region Police Office (NCRPO) reminds officers not to do anything that might create a negative impression among members of the public, the Philippine Star reports. As well as leaving their noses alone, officers in the capital, Manila, have been told not to play online games, smoke or chew gum during their shifts. <br><br> The list also specifies that any bodily itches must remain unscratched, and officers should avoid unseemly posture such as standing on one leg, the paper says. The instructions are a response to police officers posting photos of themselves on social media while on duty in the city, GMA News Online reports. <br><br> Police leaders have repeatedly issued no-selfie orders, including after Typhoon Haiyan in 2013, when some officers reportedly posted pictures from the disaster zone. <br><br> Manila's residents will have seen an increase in police activity of late - the NCRPO says 85% of its force is now on patrol. President Rodrigo Duterte recently announced a major increase in government funding for the national police, as part of his controversial war on drugs. He's committed to boosting its budget by 24.6% next year, in order to hire more officers and buy more vehicles and guns.<br><br>source: BBC News"
}
5 changes: 5 additions & 0 deletions chapter-6/push-notifications/data/data-2.json
@@ -0,0 +1,5 @@
{
"id": 2,
"title": "Australian police find gun in biker's bottom",
"description": "The loaded pistol was uncovered on Monday after officers in Brisbane, Queensland, discovered a second handgun in his car.<br><br>A body search revealed the biker had the handgun 'secreted between his buttocks', Queensland Police said.<br><br>He was charged with weapons and drug offences.<br><br>Police also searched his inner-city apartment where they discovered a Taser, explosives and drugs.<br><br>source: BBC News"
}
5 changes: 5 additions & 0 deletions chapter-6/push-notifications/data/data-3.json
@@ -0,0 +1,5 @@
{
"id": 3,
"title": "Town's giant dog dropping goes missing",
"description": "A town in Spain is facing an unexpected bill after thieves apparently made off with a giant dog dropping being used as part of a local campaign.<br><br>Torrelodones, a municipality just outside the capital Madrid, is 2,400 euros ($2,726; £1,885) out of pocket after the three-metre high inflatable bought as part of a campaign to encourage pet-lovers to pick up after their dogs went missing, El Pais newspaper reports. The bizarre inflatable disappeared after it had been packed away in its carry-case and the police are now on the trail of the 30 kilogramme dog poop, town officials say.<br><br>Speaking to the ABC newspaper, town councillor Angel Guirao said staff were shocked and perplexed by the theft, and a replacement excrement was already on order because 'we know that the campaign has been a great success'.<br><br>source: BBC News"
}
5 changes: 5 additions & 0 deletions chapter-6/push-notifications/data/data-4.json
@@ -0,0 +1,5 @@
{
"id": 4,
"title": "Austrian man wins right to be called Zebra",
"description": "The man appealed to the Austrian Constitutional Court when a lower court rejected his proposed name change.<br><br>The man's grandfather changed his name from Zebra in the 1950s. Zebra had been the family name for centuries, so reverting to it was quite legal, the Constitutional Court ruled.<br><br>The lower court had argued that Zebra was a non-Austrian invented name.<br><br>In that earlier ruling, a judge said Zebra could only refer to a type of horse living in the African savannah.<br><br>Some other animal names would have been acceptable, as they already existed in Austrian official records, he argued. He gave as examples the family names 'Fuchs' (meaning fox), 'Biber' (beaver) and 'Strauss' (ostrich).<br><br>The last family member with the name Zebra died in 1991 - a great-uncle of the plaintiff. The plaintiff's current name was not disclosed.<br><br>source: BBC News"
}
24 changes: 24 additions & 0 deletions chapter-6/push-notifications/data/latest.json
@@ -0,0 +1,24 @@
{
"latestNews": [
{
"id": 1,
"title": "Nose picking ban for Manila police",
"description": "A new directive tells police in Manila not to pick their noses whilst on duty"
},
{
"id": 2,
"title": "Australian police find gun in biker's bottom",
"description": "Police in Australia find a loaded hangun wedged in the behind of a gang linked motorcyclist"
},
{
"id": 3,
"title": "Town's giant dog dropping goes missing",
"description": "Local police on the trail of a missing inflatable dog mess"
},
{
"id": 4,
"title": "Austrian man wins right to be called Zebra",
"description": "An Austrian man has won a court case enabling him to change his family name back to 'Zebra'"
}
]
}
1 change: 1 addition & 0 deletions chapter-6/push-notifications/images/newspaper.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 36 additions & 0 deletions chapter-6/push-notifications/index.html
@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<title>Progressive Times - Online News</title>
<link href="https://fonts.googleapis.com/css?family=Raleway|Merriweather" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="./css/site.css">
<!-- Adress bar styling -->
<meta name="theme-color" content="#FFD700">
<meta name="msapplication-navbutton-color" content="#FFD700">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
</head>
<body>
<!-- header -->
<div id="header">
<img id="logo" src="./images/newspaper.svg" />
<h1>Progressive Times</h1>
<h6>Latest News</h6>
</div>
<!-- latest news -->
<div id="latest"></div>
<hr>
<!-- javaScript -->
<script async src="./js/main.js"></script>
<script>
// Register the service worker
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./sw.js').then(function(registration) {
// Registration was successful
});
}
</script>
</body>
</html>
39 changes: 39 additions & 0 deletions chapter-6/push-notifications/js/article.js
@@ -0,0 +1,39 @@
function retrieveData(url) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var result = JSON.parse(this.responseText);
buildWebPage(result);
}
};
xhttp.open('GET', url, true);
xhttp.send();
}

// Get a value from the querystring
function findGetParameter(parameterName) {
var result = null,
tmp = [];
var items = location.search.substr(1).split("&");
for (var index = 0; index < items.length; index++) {
tmp = items[index].split("=");
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
}
return result;
}

// Load the article contents into the page
function loadArticle(){
// Get the details for the article
var articleId = findGetParameter('id');
var articleUrl = './data/data-' + articleId + '.json';
retrieveData(articleUrl);
}

// Build the web page with the resulting data
function buildWebPage(result){
document.getElementById('article').innerHTML = result.description;
document.getElementById('article-title').innerHTML = result.title;
}

loadArticle();
48 changes: 48 additions & 0 deletions chapter-6/push-notifications/js/main.js
@@ -0,0 +1,48 @@
function retrieveData(url) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var result = JSON.parse(this.responseText);
buildWebPage(result);
}
};
xhttp.open('GET', url, true);
xhttp.send();
}

// Get a value from the querystring
function findGetParameter(parameterName) {
var result = null,
tmp = [];
var items = location.search.substr(1).split("&");
for (var index = 0; index < items.length; index++) {
tmp = items[index].split("=");
if (tmp[0] === parameterName) result = decodeURIComponent(tmp[1]);
}
return result;
}

// Load the latest news data and populate content
function loadLatestNews(){
var dataUrl = './data/latest.json';
var result = retrieveData(dataUrl);
}

function buildWebPage(result) {
// Build up our HTML
var latestNews = '';

// Loop through the results
for (var i = 0; i < result.latestNews.length; i++) {

var title = '<h2><a href="./article.html?id=' + result.latestNews[i].id + '">' + result.latestNews[i].title + '</a></h2>';
var description = '<p>' + result.latestNews[i].description + '</p>'

latestNews += title + description;
}

// Update the DOM with the data
document.getElementById('latest').innerHTML = latestNews;
}

loadLatestNews();
16 changes: 16 additions & 0 deletions chapter-6/push-notifications/package.json
@@ -0,0 +1,16 @@
{
"name": "push-notifications",
"version": "1.0.0",
"description": "Simple example using push notifications",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"author": "Dean Hume",
"license": "ISC",
"dependencies": {
"express": "^4.14.0",
"web-push": "^3.2.1"
}
}
1 change: 1 addition & 0 deletions chapter-6/push-notifications/readme.md
@@ -0,0 +1 @@
steps to install the server.
40 changes: 40 additions & 0 deletions chapter-6/push-notifications/server.js
@@ -0,0 +1,40 @@
const webpush = require('web-push');
const express = require('express')
const app = express();

// VAPID keys should only be generated only once.
const vapidKeys = webpush.generateVAPIDKeys();

webpush.setVapidDetails(
'mailto:contact@deanhume.com',
vapidKeys.publicKey,
vapidKeys.privateKey
);

// Send a message
app.get('/sendMessage', function (req, res) {
// This is the same output of calling JSON.stringify on a PushSubscription
// This information comes from the server
const pushSubscription = {
endpoint: '.....',
keys: {
auth: '.....',
p256dh: '.....'
}
};

webpush.sendNotification(pushSubscription, 'Your Push Payload Text');
});

// Register the user
app.get('/register', function (req, res) {

});

// The server
app.listen(3000, function () {
console.log('Example app listening on port 3000!')
});



47 changes: 47 additions & 0 deletions chapter-6/push-notifications/sw.js
@@ -0,0 +1,47 @@
var cacheName = 'latestNews-v1';

// Cache our known resources during install
self.addEventListener('install', event => {
event.waitUntil(
caches.open(cacheName)
.then(cache => cache.addAll([
'./js/main.js',
'./js/article.js',
'./images/newspaper.svg',
'./css/site.css',
'./data/latest.json',
'./data/data-1.json',
'./article.html',
'./index.html'
]))
);
});

// Cache any new resources as they are fetched
self.addEventListener('fetch', function(event) {
event.respondWith(
caches.match(event.request, { ignoreSearch: true })
.then(function(response) {
if (response) {
return response;
}
var fetchRequest = event.request.clone();

return fetch(fetchRequest).then(
function(response) {
if(!response || response.status !== 200) {
return response;
}

var responseToCache = response.clone();
caches.open(cacheName)
.then(function(cache) {
cache.put(event.request, responseToCache);
});

return response;
}
);
})
);
});

0 comments on commit 7fa21cc

Please sign in to comment.