Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1b1176b952 | ||
|
|
00c1c93b80 | ||
|
|
876776eb5b | ||
|
|
a92dc45bb7 |
@@ -1,4 +1,4 @@
|
|||||||
const DB_VERSION = 4;
|
const DB_VERSION = 6;
|
||||||
|
|
||||||
const USER_ID = localStorage.getItem('auth_user');
|
const USER_ID = localStorage.getItem('auth_user');
|
||||||
const USER_NAME = localStorage.getItem('auth_username');
|
const USER_NAME = localStorage.getItem('auth_username');
|
||||||
@@ -397,6 +397,26 @@ function dbGetRanking(minDate, maxDate, jugend, jugstrict) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function dbSettingsGet(key) {
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
if (canUseLocalDB) {
|
||||||
|
var request = db.transaction('settings').objectStore('settings').get(key);
|
||||||
|
request.onsuccess = function (event) {
|
||||||
|
resolve(typeof request.result != 'undefined' ? request.result.value : null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resolve(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function dbSettingsSet(key, value) {
|
||||||
|
if (canUseLocalDB) {
|
||||||
|
var os = db.transaction('settings', 'readwrite').objectStore('settings');
|
||||||
|
os.put({ key: key, value: value});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function updateSyncStatus() { // TODO
|
async function updateSyncStatus() { // TODO
|
||||||
// var syncStatus = document.getElementById('syncstatus');
|
// var syncStatus = document.getElementById('syncstatus');
|
||||||
// var lastSync = await dbGetData('update_times', 'last_sync');
|
// var lastSync = await dbGetData('update_times', 'last_sync');
|
||||||
@@ -433,6 +453,12 @@ async function runPageScript() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
updateSyncStatus();
|
updateSyncStatus();
|
||||||
|
|
||||||
|
if (isLoggedIn()) {
|
||||||
|
var plannings = await dbGetDataIndex('plannings', 'user', USER_ID);
|
||||||
|
plannings = plannings.map(function (e) { return e.regatta; });
|
||||||
|
dbSettingsSet('myregattas_' + BOATCLASS, plannings);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (typeof updateSyncStatusTimer == 'undefined') { // TODO
|
if (typeof updateSyncStatusTimer == 'undefined') { // TODO
|
||||||
// var syncStatus = document.getElementById('syncstatus');
|
// var syncStatus = document.getElementById('syncstatus');
|
||||||
@@ -465,7 +491,7 @@ function sync() {
|
|||||||
localTimes[entry['table']] = entry['time'];
|
localTimes[entry['table']] = entry['time'];
|
||||||
});
|
});
|
||||||
|
|
||||||
syncInProgress = 10;
|
syncInProgress = 11;
|
||||||
var syncOkay = true;
|
var syncOkay = true;
|
||||||
console.log("Sync Start");
|
console.log("Sync Start");
|
||||||
$('#i-sync').addClass('fa-spin');
|
$('#i-sync').addClass('fa-spin');
|
||||||
@@ -798,6 +824,38 @@ function sync() {
|
|||||||
syncInProgress -= 3;
|
syncInProgress -= 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NEWS
|
||||||
|
if (localTimes['news'] < serverTimes['news']) {
|
||||||
|
getJSON(QUERY_URL + 'get_news?changed-after=' + localTimes['news'], function (code, data) {
|
||||||
|
if (code == 200) {
|
||||||
|
var os = db.transaction('news', 'readwrite').objectStore('news');
|
||||||
|
console.log(data);
|
||||||
|
data.data.forEach(function (entry) {
|
||||||
|
os.put(entry);
|
||||||
|
});
|
||||||
|
os.openCursor().onsuccess = function (event) {
|
||||||
|
var cursor = event.target.result;
|
||||||
|
if (cursor) {
|
||||||
|
if (!data.keys.includes(parseInt(cursor.key))) {
|
||||||
|
os.delete(cursor.key);
|
||||||
|
}
|
||||||
|
cursor.continue();
|
||||||
|
} else {
|
||||||
|
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
|
||||||
|
osUpdateTimes.put({ table: 'news', time: serverTimes['news'] });
|
||||||
|
syncInProgress --;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
console.log("Something went wrong (HTTP " + code + ")");
|
||||||
|
syncOkay = false;
|
||||||
|
syncInProgress --;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
syncInProgress --;
|
||||||
|
}
|
||||||
|
|
||||||
// USERS
|
// USERS
|
||||||
if (localTimes['users'] < serverTimes['users']) {
|
if (localTimes['users'] < serverTimes['users']) {
|
||||||
getJSON(QUERY_URL + 'get_users?changed-after=' + localTimes['users'], function (code, data) {
|
getJSON(QUERY_URL + 'get_users?changed-after=' + localTimes['users'], function (code, data) {
|
||||||
@@ -878,6 +936,8 @@ function initDatabase() {
|
|||||||
|
|
||||||
canUseLocalDB = true;
|
canUseLocalDB = true;
|
||||||
|
|
||||||
|
if (typeof onDatabaseLoaded == 'function') onDatabaseLoaded();
|
||||||
|
|
||||||
db.transaction('update_times').objectStore('update_times').get('last_sync').onsuccess = function (event) {
|
db.transaction('update_times').objectStore('update_times').get('last_sync').onsuccess = function (event) {
|
||||||
var lastSync = event.target.result.time;
|
var lastSync = event.target.result.time;
|
||||||
if (lastSync > 0) {
|
if (lastSync > 0) {
|
||||||
@@ -953,6 +1013,18 @@ function initDatabase() {
|
|||||||
osUpdateTimes.add({ table: 'loggedin', status: isLoggedIn() });
|
osUpdateTimes.add({ table: 'loggedin', status: isLoggedIn() });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((oldVersion < 5) && (newVersion >= 5)) {
|
||||||
|
console.log('to version 5');
|
||||||
|
var osPushes = db.createObjectStore('settings', { keyPath: 'key' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((oldVersion < 6) && (newVersion >= 6)) {
|
||||||
|
console.log('to version 6');
|
||||||
|
var osNews = db.createObjectStore('news', { keyPath: 'id' });
|
||||||
|
var osUpdateTimes = upgradeTransaction.objectStore('update_times');
|
||||||
|
osUpdateTimes.add({ table: 'news', time: 0 });
|
||||||
|
}
|
||||||
|
|
||||||
var osUpdateTimes = upgradeTransaction.objectStore('update_times');
|
var osUpdateTimes = upgradeTransaction.objectStore('update_times');
|
||||||
osUpdateTimes.put({ table: 'last_sync', time: 0 });
|
osUpdateTimes.put({ table: 'last_sync', time: 0 });
|
||||||
}
|
}
|
||||||
@@ -976,6 +1048,7 @@ function resetDb(silent = true) {
|
|||||||
osUpdateTimes.put({ table: 'trim_boats', time: 0 });
|
osUpdateTimes.put({ table: 'trim_boats', time: 0 });
|
||||||
osUpdateTimes.put({ table: 'trim_users', time: 0 });
|
osUpdateTimes.put({ table: 'trim_users', time: 0 });
|
||||||
osUpdateTimes.put({ table: 'trim_trims', time: 0 });
|
osUpdateTimes.put({ table: 'trim_trims', time: 0 });
|
||||||
|
osUpdateTimes.put({ table: 'news', time: 0 });
|
||||||
osUpdateTimes.put({ table: 'users', time: 0 });
|
osUpdateTimes.put({ table: 'users', time: 0 });
|
||||||
console.log('DB update times reset');
|
console.log('DB update times reset');
|
||||||
if (!silent)
|
if (!silent)
|
||||||
|
|||||||
@@ -7,9 +7,11 @@
|
|||||||
|
|
||||||
?>
|
?>
|
||||||
//Loading the Service Worker
|
//Loading the Service Worker
|
||||||
|
var swRegistration = null;
|
||||||
if ('serviceWorker' in navigator) {
|
if ('serviceWorker' in navigator) {
|
||||||
window.addEventListener('load', function() {
|
window.addEventListener('load', async function() {
|
||||||
navigator.serviceWorker.register('<?php echo SERVER_ADDR; ?>/service-worker.js.php');
|
swRegistration = await navigator.serviceWorker.register('<?php echo SERVER_ADDR; ?>/service-worker.js.php');
|
||||||
|
if (typeof onServiceWorkerLoaded === 'function') onServiceWorkerLoaded();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const BOATCLASS = '<?php echo BOATCLASS; ?>';
|
|||||||
const LINK_PRE = '<?php echo SERVER_ADDR; ?>/';
|
const LINK_PRE = '<?php echo SERVER_ADDR; ?>/';
|
||||||
const YOUTH_AGE = '<?php echo $_CLASS['youth-age']; ?>';
|
const YOUTH_AGE = '<?php echo $_CLASS['youth-age']; ?>';
|
||||||
const YOUTH_GERMAN_NAME = '<?php echo $_CLASS['youth-german-name']; ?>';
|
const YOUTH_GERMAN_NAME = '<?php echo $_CLASS['youth-german-name']; ?>';
|
||||||
|
const PUSH_SERVER_KEY = '<?php echo PUSH_SERVER_KEY; ?>';
|
||||||
|
|
||||||
var randomId = function() { return '_' + Math.random().toString(36).substr(2, 9); }
|
var randomId = function() { return '_' + Math.random().toString(36).substr(2, 9); }
|
||||||
|
|
||||||
@@ -219,6 +220,166 @@ function resetCache() {
|
|||||||
toastInfo('The serviceWorker and the cache were deleted. A new serviceWorker will be generated on the next refresh.');
|
toastInfo('The serviceWorker and the cache were deleted. A new serviceWorker will be generated on the next refresh.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pushesPossible = false;
|
||||||
|
|
||||||
|
function urlB64ToUint8Array(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushesSubscribe() {
|
||||||
|
console.log('Subscribing');
|
||||||
|
const applicationServerKey = urlB64ToUint8Array(PUSH_SERVER_KEY);
|
||||||
|
swRegistration.pushManager.subscribe({
|
||||||
|
userVisibleOnly: true,
|
||||||
|
applicationServerKey: applicationServerKey
|
||||||
|
})
|
||||||
|
.then(function(subscription) {
|
||||||
|
pushesUpdateServerSubscription(subscription, true);
|
||||||
|
updatePushSwitches();
|
||||||
|
updatePushBadge();
|
||||||
|
})
|
||||||
|
.catch(function(err) {
|
||||||
|
console.log('Failed to subscribe the user: ', err);
|
||||||
|
toastError('Da ist leider etwas schief gelaufen. Bitte stelle sicher, dass Du mit dem Internet verbunden bist und versuche es erneut.', 5000);
|
||||||
|
pushesUnSubscribe(true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushesUnSubscribe(silent = false) {
|
||||||
|
console.log('Unsubscribing');
|
||||||
|
swRegistration.pushManager.getSubscription()
|
||||||
|
.then(function(subscription) {
|
||||||
|
if (subscription) {
|
||||||
|
pushesUpdateServerSubscription(subscription, false);
|
||||||
|
subscription.unsubscribe();
|
||||||
|
$('#menu-pushes').hideMenu();
|
||||||
|
updatePushBadge();
|
||||||
|
hideLoader();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function(error) {
|
||||||
|
console.log('Error unsubscribing', error);
|
||||||
|
$('#menu-pushes').hideMenu();
|
||||||
|
if (!silent) toastError('Da ist leider etwas schief gelaufen. Bitte versuche es erneut oder wende Dich an unseren Support.', 5000);
|
||||||
|
updatePushBadge();
|
||||||
|
hideLoader();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushesUpdateServerSubscription(subscription, enabled) {
|
||||||
|
console.log('updateServer', enabled, subscription);
|
||||||
|
$.ajax({
|
||||||
|
url: QUERY_URL + (enabled ? 'add' : 'remove') + '_subscription',
|
||||||
|
type: 'POST',
|
||||||
|
data: { subscription: JSON.stringify(subscription) },
|
||||||
|
success: function (data, textStatus, jqXHR) {
|
||||||
|
if (!enabled) {
|
||||||
|
toastOk('Du erhältst ab sofort keine Benachrichtigungen mehr von uns.');
|
||||||
|
}
|
||||||
|
hideLoader();
|
||||||
|
},
|
||||||
|
error: function (jqXHR, textStatus, errorThrown) {
|
||||||
|
throw 'Cannot update server subscription';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function initPushSettings() {
|
||||||
|
var items = [
|
||||||
|
['notify_channel_' + BOATCLASS + '_news', true],
|
||||||
|
['notify_channel_' + BOATCLASS + '_regatta_changed_my', true],
|
||||||
|
['notify_channel_' + BOATCLASS + '_regatta_changed_all', false],
|
||||||
|
['notify_channel_' + BOATCLASS + '_result_ready_my', true],
|
||||||
|
['notify_channel_' + BOATCLASS + '_result_ready_all', true],
|
||||||
|
['notify_channel_' + BOATCLASS + '_meldeschluss', true]
|
||||||
|
];
|
||||||
|
for (var i in items) {
|
||||||
|
var item = items[i];
|
||||||
|
if ((await dbSettingsGet(item[0])) == null) dbSettingsSet(item[0], item[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updatePushSwitches() {
|
||||||
|
$('#switch-pushes-news').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_news'));
|
||||||
|
$('#switch-pushes-regatta-changed-my').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_regatta_changed_my'));
|
||||||
|
$('#switch-pushes-regatta-changed-all').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_regatta_changed_all'));
|
||||||
|
$('#switch-pushes-result-ready-my').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_result_ready_my'));
|
||||||
|
$('#switch-pushes-result-ready-all').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_result_ready_all'));
|
||||||
|
$('#switch-pushes-meldeschluss').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_meldeschluss'));
|
||||||
|
|
||||||
|
if ($('#switch-pushes').prop('checked')) {
|
||||||
|
$('#p-pushes-info').show();
|
||||||
|
$('.a-switch-pushes-channel').show();
|
||||||
|
} else {
|
||||||
|
$('#p-pushes-info').hide();
|
||||||
|
$('.a-switch-pushes-channel').hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushesSubscribeClicked() {
|
||||||
|
showLoader();
|
||||||
|
if ($('#switch-pushes').prop('checked')) {
|
||||||
|
pushesSubscribe();
|
||||||
|
} else {
|
||||||
|
pushesUnSubscribe();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushesChannelClicked() {
|
||||||
|
dbSettingsSet('notify_channel_' + BOATCLASS + '_news', $('#switch-pushes-news').prop('checked'));
|
||||||
|
dbSettingsSet('notify_channel_' + BOATCLASS + '_regatta_changed_my', $('#switch-pushes-regatta-changed-my').prop('checked'));
|
||||||
|
dbSettingsSet('notify_channel_' + BOATCLASS + '_regatta_changed_all', $('#switch-pushes-regatta-changed-all').prop('checked'));
|
||||||
|
dbSettingsSet('notify_channel_' + BOATCLASS + '_result_ready_my', $('#switch-pushes-result-ready-my').prop('checked'));
|
||||||
|
dbSettingsSet('notify_channel_' + BOATCLASS + '_result_ready_all', $('#switch-pushes-result-ready-all').prop('checked'));
|
||||||
|
dbSettingsSet('notify_channel_' + BOATCLASS + '_meldeschluss', $('#switch-pushes-meldeschluss').prop('checked'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushesOpenMenu() {
|
||||||
|
$('#menu-settings').hideMenu();
|
||||||
|
if (!pushesPossible) {
|
||||||
|
toastWarn('Dein Browser unterstützt leider keine Benachrichtigungen.', 5000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Notification.permission == 'denied') {
|
||||||
|
toastWarn('Benachrichtigungen werden von Deinem Browser blockiert.', 5000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
swRegistration.pushManager.getSubscription().then(function(subscription) {
|
||||||
|
var isSub = (subscription !== null);
|
||||||
|
$('#switch-pushes').prop('checked', isSub);
|
||||||
|
updatePushSwitches();
|
||||||
|
$('#menu-pushes').showMenu();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updatePushBadge() {
|
||||||
|
if (!pushesPossible) return;
|
||||||
|
if (Notification.permission == 'denied') {
|
||||||
|
$('#badge-pushes').removeClass('bg-green2-dark').addClass('bg-red2-dark').text('BLOCKED');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
swRegistration.pushManager.getSubscription().then(function(subscription) {
|
||||||
|
var isSub = (subscription !== null);
|
||||||
|
if (isSub) {
|
||||||
|
$('#badge-pushes').removeClass('bg-red2-dark').addClass('bg-green2-dark').text('AN');
|
||||||
|
} else {
|
||||||
|
$('#badge-pushes').removeClass('bg-green2-dark').addClass('bg-red2-dark').text('AUS');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
var initRegatten = function() {
|
var initRegatten = function() {
|
||||||
showLoader();
|
showLoader();
|
||||||
|
|
||||||
@@ -235,4 +396,22 @@ var initRegatten = function() {
|
|||||||
$('.show-loggedin').hide();
|
$('.show-loggedin').hide();
|
||||||
$('.show-notloggedin').show();
|
$('.show-notloggedin').show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pushes
|
||||||
|
$('#a-switch-pushes').click(pushesSubscribeClicked);
|
||||||
|
$('.a-switch-pushes-channel').click(pushesChannelClicked);
|
||||||
|
}
|
||||||
|
|
||||||
|
var onServiceWorkerLoaded = function() {
|
||||||
|
if ((swRegistration !== null) && canUseLocalDB) {
|
||||||
|
pushesPossible = true;
|
||||||
|
updatePushBadge();
|
||||||
|
} else {
|
||||||
|
$('#badge-pushes').removeClass('bg-green2-dark').addClass('bg-red2-dark').text('NOT SUPPORTED');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var onDatabaseLoaded = function() {
|
||||||
|
onServiceWorkerLoaded();
|
||||||
|
initPushSettings();
|
||||||
}
|
}
|
||||||
@@ -173,6 +173,13 @@
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*** BLOCKQUOTE ***/
|
||||||
|
blockquote {
|
||||||
|
border-left: 0.5em solid rgba(0, 0, 0, 0.125);
|
||||||
|
font-style: italic;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
/*** BLINKING ICONS ***/
|
/*** BLINKING ICONS ***/
|
||||||
@keyframes fa-blink {
|
@keyframes fa-blink {
|
||||||
0% { opacity: 1; }
|
0% { opacity: 1; }
|
||||||
|
|||||||
@@ -12,6 +12,9 @@
|
|||||||
define('QUERY_URL', 'http://' . $_SERVER['SERVER_NAME'] . '/api/' . BOATCLASS . '/'); // url to api backend
|
define('QUERY_URL', 'http://' . $_SERVER['SERVER_NAME'] . '/api/' . BOATCLASS . '/'); // url to api backend
|
||||||
define('LOGGING_APIKEY', 'xxx'); // Apikey for Logging API -> get from ostertun.net/logging
|
define('LOGGING_APIKEY', 'xxx'); // Apikey for Logging API -> get from ostertun.net/logging
|
||||||
|
|
||||||
|
// PUSH
|
||||||
|
define('PUSH_SERVER_KEY', '');
|
||||||
|
|
||||||
// BOAT CLASS
|
// BOAT CLASS
|
||||||
$_CLASS = array(
|
$_CLASS = array(
|
||||||
'name' => 'Pirat',
|
'name' => 'Pirat',
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
// TODO: Create site
|
$sp['title'] = 'News - Regatten.net ' . $_CLASS['name'];
|
||||||
|
|
||||||
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
|
|
||||||
$sp['backbutton'] = true;
|
$sp['backbutton'] = true;
|
||||||
|
$sp['activenav'] = 5;
|
||||||
|
|
||||||
$content = $tpl->load('error', ['404', 'Seite existiert noch nicht']);
|
// Title
|
||||||
$content .= '<p>';
|
$content = "<h1>Neuigkeiten</h1>";
|
||||||
$content .= 'Die gesuchte Seite ist leider noch nicht verfügbar.<br>';
|
$content .= '<p>Aktuelles der letzten zwölf Monate</p>';
|
||||||
$content .= 'Wir arbeiten daran, sie schnellstmöglich zur Verfügung zu stellen.<br>';
|
|
||||||
$content .= 'Wie wäre es mit der Homepage?';
|
|
||||||
$content .= '</p>';
|
|
||||||
$content .= $tpl->load('button', ['Zur Startseite', LINK_PRE . 'index', 'css-class' => 'mb-3']);
|
|
||||||
$content .= $tpl->load('button', ['Kontakt', LINK_PRE . 'contact']);
|
|
||||||
|
|
||||||
$sp['output'] = $tpl->load('card', [$content, 'css-class' => 'text-center pt-3']);
|
$sp['output'] .= $tpl->load('card', [$content]);
|
||||||
|
|
||||||
|
// Menu
|
||||||
|
$sp['menus'] .= $tpl->load('menu/modal', ['html-id' => 'menu-news', 'title' => 'Details']);
|
||||||
|
|
||||||
|
$cardTemplate = $tpl->load('card', ['%CONTENT%', 'html-id' => '%ID%', 'css-class' => 'card-news']);
|
||||||
|
$cardTemplate = str_replace("\n", '', $cardTemplate);
|
||||||
|
$cardTemplate = str_replace("\r", '', $cardTemplate);
|
||||||
|
$sp['scripts'] .= "<script>const cardTemplate = '" . $cardTemplate . "';</script>";
|
||||||
|
$sp['scripts'] .= $scripts->load('news');
|
||||||
|
|
||||||
?>
|
?>
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="menu-settings" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="270">
|
<div id="menu-settings" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="310">
|
||||||
<div class="menu-title"><h1>Einstellungen</h1><p class="color-highlight"> </p><a href="#" class="close-menu"><i class="fa fa-times"></i></a></div>
|
<div class="menu-title"><h1>Einstellungen</h1><p class="color-highlight"> </p><a href="#" class="close-menu"><i class="fa fa-times"></i></a></div>
|
||||||
<div class="divider divider-margins mb-n2"></div>
|
<div class="divider divider-margins mb-n2"></div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
@@ -110,7 +110,7 @@
|
|||||||
<span>Login</span>
|
<span>Login</span>
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="#" data-menu="menu-signup" class="show-notloggedin border-0">
|
<a href="#" data-menu="menu-signup" class="show-notloggedin">
|
||||||
<i class="fa font-14 fa-user-plus rounded-s bg-highlight color-white"></i>
|
<i class="fa font-14 fa-user-plus rounded-s bg-highlight color-white"></i>
|
||||||
<span>Registrieren</span>
|
<span>Registrieren</span>
|
||||||
<span class="badge bg-red2-dark color-white">FREE</span>
|
<span class="badge bg-red2-dark color-white">FREE</span>
|
||||||
@@ -120,11 +120,88 @@
|
|||||||
<span>Account</span>
|
<span>Account</span>
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
<a href="#" onclick="logout();" class="show-loggedin border-0">
|
<a href="#" onclick="logout();" class="show-loggedin">
|
||||||
<i class="fa font-14 fa-sign-out-alt rounded-s bg-highlight color-white"></i>
|
<i class="fa font-14 fa-sign-out-alt rounded-s bg-highlight color-white"></i>
|
||||||
<span>Logout</span>
|
<span>Logout</span>
|
||||||
<i class="fa fa-angle-right"></i>
|
<i class="fa fa-angle-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
<a href="#" onclick="pushesOpenMenu()" class="border-0">
|
||||||
|
<i class="fa font-14 fa-bell rounded-s bg-highlight color-white"></i>
|
||||||
|
<span>Benachrichtigungen</span>
|
||||||
|
<span id="badge-pushes" class="badge color-white"></span>
|
||||||
|
<i class="fa fa-angle-right"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="menu-pushes" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="500">
|
||||||
|
<div class="menu-title"><h1>Benachrichtigungen</h1><p class="color-highlight">Bleibe immer auf dem aktuellen Stand</p><a href="#" class="close-menu"><i class="fa fa-times"></i></a></div>
|
||||||
|
<div class="divider divider-margins mb-n2"></div>
|
||||||
|
<div class="content">
|
||||||
|
<div class="list-group list-custom-small">
|
||||||
|
<a id="a-switch-pushes" href="#" data-trigger-switch="switch-pushes" class="pb-2">
|
||||||
|
<i class="fa font-14 fa-bell rounded-s bg-highlight color-white"></i>
|
||||||
|
<span>Benachrichtigungen aktivieren</span>
|
||||||
|
<div class="custom-control scale-switch ios-switch">
|
||||||
|
<input type="checkbox" class="ios-input" id="switch-pushes">
|
||||||
|
<label class="custom-control-label" for="switch-pushes"></label>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<div class="divider"></div>
|
||||||
|
<p style="line-height: 1.5em;" id="p-pushes-info">
|
||||||
|
Wähle hier, über was Du informiert werden möchtest.<br>
|
||||||
|
(meine) bezieht sich auf die Regatten, die in Deiner Saison-Planung sind,<br>
|
||||||
|
(alle) informiert Dich über alle Regatten
|
||||||
|
</p>
|
||||||
|
<a href="#" data-trigger-switch="switch-pushes-news" class="pb-2 a-switch-pushes-channel">
|
||||||
|
<i class="fa font-14 fa-newspaper rounded-s bg-highlight color-white"></i>
|
||||||
|
<span>Neuigkeiten</span>
|
||||||
|
<div class="custom-control scale-switch ios-switch">
|
||||||
|
<input type="checkbox" class="ios-input" id="switch-pushes-news">
|
||||||
|
<label class="custom-control-label" for="switch-pushes-news"></label>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a href="#" data-trigger-switch="switch-pushes-regatta-changed-my" class="pb-2 a-switch-pushes-channel">
|
||||||
|
<i class="fa font-14 fa-calendar-check rounded-s bg-highlight color-white"></i>
|
||||||
|
<span>Regatta verschoben (meine)</span>
|
||||||
|
<div class="custom-control scale-switch ios-switch">
|
||||||
|
<input type="checkbox" class="ios-input" id="switch-pushes-regatta-changed-my">
|
||||||
|
<label class="custom-control-label" for="switch-pushes-regatta-changed-my"></label>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a href="#" data-trigger-switch="switch-pushes-regatta-changed-all" class="pb-2 a-switch-pushes-channel">
|
||||||
|
<i class="fa font-14 fa-calendar-check rounded-s bg-highlight color-white"></i>
|
||||||
|
<span>Regatta verschoben (alle)</span>
|
||||||
|
<div class="custom-control scale-switch ios-switch">
|
||||||
|
<input type="checkbox" class="ios-input" id="switch-pushes-regatta-changed-all">
|
||||||
|
<label class="custom-control-label" for="switch-pushes-regatta-changed-all"></label>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a href="#" data-trigger-switch="switch-pushes-result-ready-my" class="pb-2 a-switch-pushes-channel">
|
||||||
|
<i class="fa font-14 fa-poll rounded-s bg-highlight color-white"></i>
|
||||||
|
<span>Ergebnisse verfügbar (meine)</span>
|
||||||
|
<div class="custom-control scale-switch ios-switch">
|
||||||
|
<input type="checkbox" class="ios-input" id="switch-pushes-result-ready-my">
|
||||||
|
<label class="custom-control-label" for="switch-pushes-result-ready-my"></label>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a href="#" data-trigger-switch="switch-pushes-result-ready-all" class="pb-2 a-switch-pushes-channel">
|
||||||
|
<i class="fa font-14 fa-poll rounded-s bg-highlight color-white"></i>
|
||||||
|
<span>Ergebnisse verfügbar (alle)</span>
|
||||||
|
<div class="custom-control scale-switch ios-switch">
|
||||||
|
<input type="checkbox" class="ios-input" id="switch-pushes-result-ready-all">
|
||||||
|
<label class="custom-control-label" for="switch-pushes-result-ready-all"></label>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a href="#" data-trigger-switch="switch-pushes-meldeschluss" class="pb-2 a-switch-pushes-channel">
|
||||||
|
<i class="fa font-14 fa-file-signature rounded-s bg-highlight color-white"></i>
|
||||||
|
<span>Melde-Erinnerungen</span>
|
||||||
|
<div class="custom-control scale-switch ios-switch">
|
||||||
|
<input type="checkbox" class="ios-input" id="switch-pushes-meldeschluss">
|
||||||
|
<label class="custom-control-label" for="switch-pushes-meldeschluss"></label>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
44
server/scripts/news.js
Normal file
44
server/scripts/news.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
async function onNewsClicked(id) {
|
||||||
|
var newsEntry = await dbGetData('news', id);
|
||||||
|
if (newsEntry == null) return;
|
||||||
|
|
||||||
|
$('#menu-news').css('height', '80%');
|
||||||
|
$('#menu-news').css('width', '90%');
|
||||||
|
$('#menu-news').find('.menu-title').find('p').text(newsEntry.title);
|
||||||
|
$('#menu-news').find('.content').addClass('pb-3');
|
||||||
|
$('#menu-news').find('.content').html(newsEntry.html);
|
||||||
|
|
||||||
|
$('#menu-news').showMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
function addCard(newsEntry) {
|
||||||
|
console.log(newsEntry);
|
||||||
|
var content = '<h2>' + newsEntry.title + '</h2>';
|
||||||
|
content += '<p class="mb-2"><i>' + formatDate('d.m.Y', newsEntry.date) + '</i></p>';
|
||||||
|
content += '<p class="mb-0">' + newsEntry.description.replace('\n', '<br>') + '</p>';
|
||||||
|
if (newsEntry.html != '') {
|
||||||
|
content += '<a class="btn btn-full rounded-s text-uppercase font-900 shadow-m bg-highlight mt-3" href="#" onclick="onNewsClicked(' + newsEntry.id + '); return false;">Mehr lesen</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$('.page-content').append(cardTemplate.replace('%ID%', 'card-news-' + newsEntry.id).replace('%CONTENT%', content));
|
||||||
|
}
|
||||||
|
|
||||||
|
var siteScript = async function() {
|
||||||
|
$('.card-news').remove();
|
||||||
|
var news = await dbGetData('news');
|
||||||
|
news.sort(function (a,b) {
|
||||||
|
return b.date.localeCompare(a.date);
|
||||||
|
});
|
||||||
|
var today = getToday();
|
||||||
|
var lastYear = new Date(today);
|
||||||
|
lastYear.setFullYear(lastYear.getFullYear() - 1);
|
||||||
|
console.log(today, lastYear);
|
||||||
|
for (var n in news) {
|
||||||
|
var newsEntry = news[n];
|
||||||
|
newsEntry.date = parseDate(newsEntry.date.substring(0, 10));
|
||||||
|
if (newsEntry.date > today) continue;
|
||||||
|
if (newsEntry.date < lastYear) break;
|
||||||
|
addCard(newsEntry);
|
||||||
|
}
|
||||||
|
hideLoader();
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
define('PWA_VERSION', '1.5');
|
define('PWA_VERSION', '1.6');
|
||||||
|
|
||||||
?>
|
?>
|
||||||
@@ -105,3 +105,146 @@ workbox.routing.registerRoute(
|
|||||||
|
|
||||||
//Learn more about Service Workers and Configurations
|
//Learn more about Service Workers and Configurations
|
||||||
//https://developers.google.com/web/tools/workbox/
|
//https://developers.google.com/web/tools/workbox/
|
||||||
|
|
||||||
|
|
||||||
|
// DB
|
||||||
|
|
||||||
|
var db = null;
|
||||||
|
if (indexedDB) {
|
||||||
|
var request = indexedDB.open('regatten_app_db_<?php echo BOATCLASS; ?>');
|
||||||
|
request.onerror = function (e) {
|
||||||
|
console.log('[sW] Cannot open DB:', e.target.errorCode);
|
||||||
|
};
|
||||||
|
request.onupgradeneeded = function (e) {
|
||||||
|
console.log('[sW] DB does not exist');
|
||||||
|
e.target.transaction.abort();
|
||||||
|
};
|
||||||
|
request.onsuccess = function (e) {
|
||||||
|
console.log('[sW] DB loaded');
|
||||||
|
db = e.target.result;
|
||||||
|
db.onerror = function (e) {
|
||||||
|
console.log('[sW] DB Error:', e)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function dbSettingsGet(key) {
|
||||||
|
return new Promise(function(resolve) {
|
||||||
|
if (db != null) {
|
||||||
|
var request = db.transaction('settings').objectStore('settings').get(key);
|
||||||
|
request.onsuccess = function (event) {
|
||||||
|
resolve(typeof request.result != 'undefined' ? request.result.value : null);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resolve(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function dbSettingsSet(key, value) {
|
||||||
|
if (db != null) {
|
||||||
|
var os = db.transaction('settings', 'readwrite').objectStore('settings');
|
||||||
|
os.put({ key: key, value: value});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// PUSHES
|
||||||
|
|
||||||
|
function getEntry(data, index, defaultValue) {
|
||||||
|
return ((typeof data[index] !== "undefined") ? data[index] : defaultValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isMyRegatta(id) {
|
||||||
|
return new Promise(async function (resolve) {
|
||||||
|
var regattas = await dbSettingsGet('myregattas_<?php echo BOATCLASS; ?>');
|
||||||
|
if (regattas == null) resolve(false);
|
||||||
|
else resolve(regattas.includes(id.toString()));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
self.addEventListener('push', async function(event) {
|
||||||
|
console.log('[sW] Push received:', event.data.text());
|
||||||
|
|
||||||
|
var data;
|
||||||
|
try {
|
||||||
|
data = JSON.parse(event.data.text());
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e);
|
||||||
|
data = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof data.type !== "undefined") {
|
||||||
|
switch (data.type) {
|
||||||
|
case 'notification':
|
||||||
|
if (typeof data.title === "undefined") break;
|
||||||
|
if (typeof data.body === "undefined") break;
|
||||||
|
if (typeof data.channel === "undefined") break;
|
||||||
|
|
||||||
|
// check channel
|
||||||
|
var okay = false;
|
||||||
|
switch (data.channel) {
|
||||||
|
case 'news':
|
||||||
|
if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_news')) okay = true;
|
||||||
|
break;
|
||||||
|
case 'regatta_changed':
|
||||||
|
if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_regatta_changed_all')) okay = true;
|
||||||
|
else if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_regatta_changed_my')) {
|
||||||
|
if (await isMyRegatta(getEntry(data, 'id', ''))) okay = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'result_ready':
|
||||||
|
if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_result_ready_all')) okay = true;
|
||||||
|
else if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_result_ready_my')) {
|
||||||
|
if (await isMyRegatta(getEntry(data, 'id', ''))) okay = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'meldeschluss':
|
||||||
|
if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_meldeschluss')) {
|
||||||
|
if (await isMyRegatta(getEntry(data, 'id', ''))) okay = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log('Unknown channel:', data.channel);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!okay) {
|
||||||
|
console.log('Notification channel not subscribed');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
data: data,
|
||||||
|
body: data.body,
|
||||||
|
icon: getEntry(data, 'icon', '<?php echo SERVER_ADDR; ?>/client/app/icons/icon-512x512.png'),
|
||||||
|
badge: '<?php echo SERVER_ADDR; ?>/client/app/icons/icon-96x96.png',
|
||||||
|
vibrate: [500,100,500]
|
||||||
|
};
|
||||||
|
if ((image = getEntry(data, 'image', null)) !== null) {
|
||||||
|
options.image = image;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force refresh on next app open
|
||||||
|
var os = db.transaction('update_times', 'readwrite').objectStore('update_times');
|
||||||
|
os.put({ table: 'last_sync', time: 0 });
|
||||||
|
|
||||||
|
console.log('Showing notification');
|
||||||
|
self.registration.showNotification(data.title, options);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('notificationclick', function(event) {
|
||||||
|
var data = event.notification.data;
|
||||||
|
|
||||||
|
event.notification.close();
|
||||||
|
|
||||||
|
var url = '<?php echo SERVER_ADDR; ?>' + getEntry(data, 'url', '');
|
||||||
|
|
||||||
|
event.waitUntil(
|
||||||
|
clients.openWindow(url)
|
||||||
|
);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user