Skip to content

Commit 61889ff

Browse files
feat: make notification sending configurable (#8)
* feat: make notification sending configurable * fix(service-worker): parse title and body from event data
1 parent df28b80 commit 61889ff

File tree

4 files changed

+120
-17
lines changed

4 files changed

+120
-17
lines changed

changelog.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
### 22nd Aug, 2022
2+
3+
* The dropdown can be refreshed to fetch the latest list of notifications available.
4+
* Integrated API (`POST /api/notifications/:id/send`) to trigger a specific push notification to all subscribers.
5+
* Show available notifications from backend on a dropdown to allow user to select which notification to send.
6+
17
### 19th Aug, 2022
28

39
* Display notification on device using service-worker

index.html

Lines changed: 33 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,56 @@
11
<!doctype html>
22
<html lang="en">
3+
34
<head>
45
<meta charset="utf-8">
56
<meta name="viewport" content="width=device-width, initial-scale=1">
67
<title>Dashboard</title>
78
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-gH2yIJqKdNHPEq0n4Mqa/HGKIhSkIHeL5AyhkYV8i59U5AR6csBvApHHNl/vI1Bx" crossorigin="anonymous">
89
</head>
10+
911
<body>
10-
<br>
12+
13+
<div class="text-center">
14+
<br>
15+
<h1>Simple Web Push Notifications Dashboard</h1>
16+
<div class="container">
17+
<button type="submit" class="btn btn-basic" id="subscribeButton">Click here to Subscribe!</button>
18+
</div>
19+
</div>
20+
21+
<br><hr>
22+
1123
<form id="notificationForm" class="container">
12-
<h2 class="h3 col-sm-6 fw-normal">Create Notification</h2>
24+
<h3 class="h3 col-sm-6 fw-normal">Create Notification Form</h3>
1325
<br>
14-
<div class="form-row col-sm-6 form-group">
26+
<div class="form-row col-sm-5 form-group">
1527
<label for="title">Title</label>
1628
<input type="text" class="form-control" id="title" name="title">
1729
</div>
1830
<br>
19-
<div class="form-row col-sm-6 form-group">
31+
<div class="form-row form-group">
2032
<label for="description">Description</label>
2133
<input type="text" class="form-control" id="description" name="description">
2234
</div>
2335
<br>
24-
<button type="submit" class="btn btn-primary">Submit</button>
36+
<button type="submit" class="btn btn-primary">Create</button>
2537
</form>
26-
<br>
27-
<div class="container">
28-
<button type="submit" class="btn btn-info" id="subscribeButton">Subscribe</button>
29-
</div>
38+
39+
<br><hr>
40+
41+
<form id="sendNotificationForm" class="container">
42+
<br>
43+
<h3 class="h3 col-sm-6 fw-normal">Select Notification to Send</h3>
44+
<br>
45+
<select class="form-select" id="notifications-list">
46+
</select>
47+
<br>
48+
<button type="submit" class="btn btn-primary" id="refresh-notifications-button">Refresh List</button>
49+
<button type="submit" class="btn btn-primary" id="send-notification-button">Send Selected</button>
50+
</form>
51+
3052
</body>
53+
3154
<script type="text/javascript" src="static/js/main.js"></script>
55+
3256
</html>

static/js/main.js

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
1-
const notificationForm = document.getElementById('notificationForm')
1+
const createNotificationForm = document.getElementById('notificationForm')
22
const subscribeButton = document.getElementById('subscribeButton')
3+
const sendNotificationButton = document.getElementById('send-notification-button')
4+
const refreshNotificationsButton = document.getElementById('refresh-notifications-button')
5+
const notificationsList = document.getElementById('notifications-list')
6+
7+
// Functions to call on window load
8+
updateNotificationsList()
39

410
// Common Functions
511
function getBaseUrl() {
@@ -10,7 +16,7 @@ function logError(error) {
1016
console.error('Error: ', error)
1117
}
1218

13-
function makeHttpRequest(method, url, body, headers) {
19+
function makeHttpRequest(method, url, headers, body) {
1420
return fetch(url, {
1521
method: method,
1622
body: body,
@@ -40,18 +46,30 @@ function urlBase64ToUint8Array(base64String) {
4046
}
4147

4248
// Event Listeners
43-
subscribeButton.addEventListener('click', function(event){
49+
subscribeButton.addEventListener('click', function(event) {
4450
event.preventDefault()
4551
let result = requestNotificationPermission()
4652
console.log(result)
4753
});
4854

49-
notificationForm.addEventListener('submit', function(event){
55+
createNotificationForm.addEventListener('submit', function(event) {
56+
event.preventDefault()
57+
let result = saveNotification(createNotificationForm)
58+
console.log(result)
59+
});
60+
61+
sendNotificationButton.addEventListener('click', function(event) {
5062
event.preventDefault()
51-
let result = saveNotification(notificationForm)
63+
let selected_notification_id = notificationsList.options[notificationsList.selectedIndex].id;
64+
let result = triggerSendingPushNotification(selected_notification_id)
5265
console.log(result)
5366
});
5467

68+
refreshNotificationsButton.addEventListener('click', function(event) {
69+
event.preventDefault()
70+
updateNotificationsList()
71+
})
72+
5573

5674
// Core Functions
5775
function saveNotification(notificationForm){
@@ -64,7 +82,7 @@ function saveNotification(notificationForm){
6482
let headers = {
6583
'Content-type': 'application/json; charset=UTF-8',
6684
}
67-
return makeHttpRequest('POST', url, body, headers)
85+
return makeHttpRequest('POST', url, headers, body)
6886
.then((responseJson) => {
6987
notificationForm.reset()
7088
return responseJson
@@ -96,6 +114,7 @@ function registerServiceWorker() {
96114

97115
function requestNotificationPermission() {
98116
if (Notification.permission === 'granted') {
117+
alert("You are already subscribed!")
99118
return Notification.permission
100119
}
101120
Notification.requestPermission()
@@ -138,7 +157,47 @@ function savePushSubscription(pushSubscription) {
138157
let headers = {
139158
'Content-type': 'application/json; charset=UTF-8',
140159
}
141-
return makeHttpRequest('POST', url, body, headers)
160+
return makeHttpRequest('POST', url, headers, body)
161+
.then((responseJson) => {
162+
return responseJson
163+
}).catch(error => console.error('Error: ', error))
164+
}
165+
166+
function triggerSendingPushNotification(notification_id) {
167+
let url = getBaseUrl() + '/api/notifications/' + notification_id + "/send"
168+
let headers = {
169+
'Content-type': 'application/json; charset=UTF-8',
170+
}
171+
return makeHttpRequest('POST', url, headers)
172+
.then((responseJson) => {
173+
return responseJson
174+
}).catch(error => console.error('Error: ', error))
175+
}
176+
177+
178+
function updateNotificationsList() {
179+
notificationsList.innerHTML = ''
180+
fetchAllNotifications()
181+
.then(data => {
182+
data.forEach(notification => render(notification))
183+
});
184+
}
185+
186+
function render(notification) {
187+
const option = document.createElement('option')
188+
let option_text = notification.title + " | " + notification.description
189+
option.id = notification.id
190+
const content = document.createTextNode(`${option_text}`)
191+
option.appendChild(content)
192+
notificationsList.appendChild(option)
193+
}
194+
195+
function fetchAllNotifications() {
196+
let url = getBaseUrl() + '/api/notifications'
197+
let headers = {
198+
'Content-type': 'application/json; charset=UTF-8',
199+
}
200+
return makeHttpRequest('GET', url, headers)
142201
.then((responseJson) => {
143202
return responseJson
144203
}).catch(error => console.error('Error: ', error))

static/js/service-worker.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,18 @@
1+
2+
// Event Listeners
13
self.addEventListener('push', function(event) {
2-
const promiseChain = self.registration.showNotification(event.data.text());
4+
const notification_data = event.data.json()
5+
const options = parseOptionsFromNotificationData(notification_data)
6+
const promiseChain = self.registration.showNotification(
7+
notification_data["title"],
8+
options,
9+
);
310
event.waitUntil(promiseChain);
411
});
12+
13+
// Utilities
14+
function parseOptionsFromNotificationData(notificationData) {
15+
return {
16+
"body": notificationData["description"]
17+
};
18+
}

0 commit comments

Comments
 (0)