forked from jsnbuchanan/crowd-funder-for-time-pwa
add logic to send a time for notifications
This commit is contained in:
106
src/App.vue
106
src/App.vue
@@ -191,7 +191,7 @@
|
|||||||
>
|
>
|
||||||
<div class="w-full px-6 py-6 text-slate-900 text-center">
|
<div class="w-full px-6 py-6 text-slate-900 text-center">
|
||||||
<p v-if="serviceWorkerReady" class="text-lg mb-4">
|
<p v-if="serviceWorkerReady" class="text-lg mb-4">
|
||||||
Would you like to <b>turn on</b> notifications for this app?
|
Would you like to be notified of new activity once a day?
|
||||||
</p>
|
</p>
|
||||||
<p v-else class="text-lg mb-4">
|
<p v-else class="text-lg mb-4">
|
||||||
Waiting for system initialization, which may take up to 10
|
Waiting for system initialization, which may take up to 10
|
||||||
@@ -199,22 +199,42 @@
|
|||||||
<fa icon="spinner" spin />
|
<fa icon="spinner" spin />
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<button
|
<div v-if="serviceWorkerReady">
|
||||||
v-if="serviceWorkerReady"
|
<span class="flex flex-row justify-center">
|
||||||
class="block w-full text-center text-md font-bold uppercase bg-blue-600 text-white px-2 py-2 rounded-md mb-2"
|
<span class="mt-2">Yes, tell me at: </span>
|
||||||
@click="
|
<input
|
||||||
close(notification.id);
|
type="number"
|
||||||
turnOnNotifications();
|
class="rounded-l border border-r-0 border-slate-400 ml-2 mt-2 px-2 py-2 text-center w-20"
|
||||||
"
|
v-model="hourInput"
|
||||||
>
|
/>
|
||||||
Turn on Notifications
|
<span
|
||||||
</button>
|
class="rounded-r border border-slate-400 bg-slate-200 text-center text-blue-500 mt-2 px-2 py-2 w-20"
|
||||||
|
@click="hourAm = !hourAm"
|
||||||
|
>
|
||||||
|
<span v-if="hourAm"> AM <fa icon="chevron-down" /> </span>
|
||||||
|
<span v-else> PM <fa icon="chevron-up" /> </span>
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
class="block w-full text-center text-md font-bold uppercase bg-blue-600 text-white mt-2 px-2 py-2 rounded-md"
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
if (checkHour()) {
|
||||||
|
close(notification.id);
|
||||||
|
turnOnNotifications();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
Turn on Daily Message
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
@click="close(notification.id)"
|
@click="close(notification.id)"
|
||||||
class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white px-2 py-2 rounded-md"
|
class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white mt-4 px-2 py-2 rounded-md"
|
||||||
>
|
>
|
||||||
Maybe Later
|
No, Not Now
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -297,8 +317,11 @@
|
|||||||
<style></style>
|
<style></style>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Vue, Component } from "vue-facing-decorator";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
import { Vue, Component } from "vue-facing-decorator";
|
||||||
|
|
||||||
|
import * as libsUtil from "@/libs/util";
|
||||||
|
|
||||||
interface ServiceWorkerMessage {
|
interface ServiceWorkerMessage {
|
||||||
type: string;
|
type: string;
|
||||||
data: string;
|
data: string;
|
||||||
@@ -332,7 +355,9 @@ export default class App extends Vue {
|
|||||||
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
||||||
|
|
||||||
b64 = "";
|
b64 = "";
|
||||||
serviceWorkerReady = false;
|
hourAm = true;
|
||||||
|
hourInput = "8";
|
||||||
|
serviceWorkerReady = true;
|
||||||
|
|
||||||
async mounted() {
|
async mounted() {
|
||||||
try {
|
try {
|
||||||
@@ -461,6 +486,48 @@ export default class App extends Vue {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this allows us to show an error without closing the dialog
|
||||||
|
checkHour() {
|
||||||
|
if (!libsUtil.isNumeric(this.hourInput)) {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Not a Number",
|
||||||
|
text: "The time must be an hour number.",
|
||||||
|
},
|
||||||
|
5000,
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const hourNum = libsUtil.numberOrZero(this.hourInput);
|
||||||
|
if (!Number.isInteger(hourNum)) {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Not a Whole Number",
|
||||||
|
text: "The time must be a whole hour number.",
|
||||||
|
},
|
||||||
|
5000,
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (hourNum < 1 || hourNum > 12) {
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Not a Whole Number",
|
||||||
|
text: "The time must be an hour between 1 and 12.",
|
||||||
|
},
|
||||||
|
5000,
|
||||||
|
);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public async turnOnNotifications() {
|
public async turnOnNotifications() {
|
||||||
return this.askPermission()
|
return this.askPermission()
|
||||||
.then((permission) => {
|
.then((permission) => {
|
||||||
@@ -486,6 +553,15 @@ export default class App extends Vue {
|
|||||||
},
|
},
|
||||||
-1,
|
-1,
|
||||||
);
|
);
|
||||||
|
// we already checked that this is a valid hour number
|
||||||
|
const hourNum = libsUtil.numberOrZero(this.hourInput);
|
||||||
|
const utcHour =
|
||||||
|
hourNum + Math.round(new Date().getTimezoneOffset() / 60);
|
||||||
|
|
||||||
|
// This ignore commentary is because I'm adding non-standard stuff to the subscription object.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
subscription.notifyTime = { utcHour: utcHour };
|
||||||
this.sendSubscriptionToServer(subscription);
|
this.sendSubscriptionToServer(subscription);
|
||||||
return subscription;
|
return subscription;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -56,9 +56,13 @@ export function iconForUnitCode(unitCode: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// from https://stackoverflow.com/a/175787/845494
|
// from https://stackoverflow.com/a/175787/845494
|
||||||
|
// ... though it appears even this isn't precisely right so keep doing "|| 0" or something in sensitive places
|
||||||
//
|
//
|
||||||
export function isNumeric(str: string): boolean {
|
export function isNumeric(str: string): boolean {
|
||||||
return !isNaN(+str);
|
// This ignore commentary is because typescript complains when you pass a string to isNaN.
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
return !isNaN(str) && !isNaN(parseFloat(str));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function numberOrZero(str: string): number {
|
export function numberOrZero(str: string): number {
|
||||||
|
|||||||
@@ -20,8 +20,10 @@ import {
|
|||||||
faCalendar,
|
faCalendar,
|
||||||
faCamera,
|
faCamera,
|
||||||
faCheck,
|
faCheck,
|
||||||
|
faChevronDown,
|
||||||
faChevronLeft,
|
faChevronLeft,
|
||||||
faChevronRight,
|
faChevronRight,
|
||||||
|
faChevronUp,
|
||||||
faCircle,
|
faCircle,
|
||||||
faCircleCheck,
|
faCircleCheck,
|
||||||
faCircleInfo,
|
faCircleInfo,
|
||||||
@@ -81,8 +83,10 @@ library.add(
|
|||||||
faCalendar,
|
faCalendar,
|
||||||
faCamera,
|
faCamera,
|
||||||
faCheck,
|
faCheck,
|
||||||
|
faChevronDown,
|
||||||
faChevronLeft,
|
faChevronLeft,
|
||||||
faChevronRight,
|
faChevronRight,
|
||||||
|
faChevronUp,
|
||||||
faCircle,
|
faCircle,
|
||||||
faCircleCheck,
|
faCircleCheck,
|
||||||
faCircleInfo,
|
faCircleInfo,
|
||||||
|
|||||||
Reference in New Issue
Block a user