Compare commits

...

30 Commits
v_1.5 ... v_1.8

Author SHA1 Message Date
ostertun
a45af73c25 Merge branch 'release/v_1.8' 2020-10-02 01:29:43 +02:00
ostertun
f30eac8aa5 Release v_1.8 2020-10-02 01:27:31 +02:00
ostertun
99b624ff92 Merge branch 'feature/RA-4-notifications-ignore-my-regattas' into develop 2020-10-02 01:24:16 +02:00
ostertun
e74ffa9a70 Merge branch 'feature/RA-19-update-url-on-year-change' into develop 2020-10-02 01:24:11 +02:00
ostertun
cbb398988d Merge branch 'feature/RA-20-update-news-badge' into develop 2020-10-02 01:24:00 +02:00
ostertun
856f6c1d66 RA-#20 Update news badge 2020-10-02 01:23:46 +02:00
ostertun
2ea26408be RA-#3 Trigger inputs after programmatically changed 2020-10-02 00:59:34 +02:00
ostertun
fb1ca6d28e RA-#19 Update URL on year change 2020-10-02 00:49:53 +02:00
ostertun
6a5d06325d RA-#4 Notifications: can select "my regattas" channels only when logged in 2020-10-02 00:13:58 +02:00
ostertun
72ac8df460 Merge branch 'feature/dev_buttons' into develop 2020-10-01 23:36:05 +02:00
ostertun
246231fd0e RA-#8 Fix deleteCache 2020-10-01 23:35:49 +02:00
ostertun
3e533f65fc Added show-console-button to preloader 2020-10-01 23:26:22 +02:00
ostertun
2533c3d66a RA-#16 Updated Dev Buttons 2020-10-01 23:25:48 +02:00
ostertun
cacee5a54a RA-#17 Fix padding of body 2020-10-01 22:46:53 +02:00
ostertun
274aa85cf7 Merge branch 'release/v_1.7' 2020-10-01 03:21:20 +02:00
ostertun
4317e4fe87 Release v_1.7
Prepare github repo
small fixes
2020-10-01 03:19:42 +02:00
Timon Ostertun
b7dec825ca Update issue templates 2020-10-01 03:00:38 +02:00
Timon Ostertun
6ca6a79dc3 Update issue templates 2020-10-01 02:59:12 +02:00
Timon Ostertun
d1e5d753b4 Create README.md 2020-10-01 01:03:41 +02:00
Timon Ostertun
7afacc3fff Update issue templates 2020-09-30 23:56:51 +02:00
Timon Ostertun
77ea57d643 RA-#1 Notifications: Badge Icon 2020-09-30 23:24:24 +02:00
Timon Ostertun
a72c462483 RA-#4 Registration open icon is red when deadline expired 2020-09-30 22:46:20 +02:00
Timon Ostertun
b739e6cc4e RA-#7 Fix serviceWorker 2020-09-30 22:45:43 +02:00
Timon Ostertun
eb47cdf016 RA-#7 Removed unnecessary files from cache 2020-09-30 22:25:59 +02:00
Timon Ostertun
12c1a614bb Fix #5 serviceWorker DB access
serviceWorker openes DB only when needed and closes it directly
2020-09-30 16:46:10 +02:00
Timon Ostertun
0fb1bb0462 Added mobile console 2020-09-30 14:36:07 +02:00
Timon Ostertun
1b1176b952 Release v_1.6 2020-09-27 23:18:37 +02:00
Timon Ostertun
00c1c93b80 Added news 2020-09-27 23:17:56 +02:00
Timon Ostertun
876776eb5b Added notifications 2020-09-27 21:54:43 +02:00
Timon Ostertun
a92dc45bb7 Can subscribe to pushes 2020-09-27 14:35:25 +02:00
23 changed files with 2654 additions and 321 deletions

View File

@@ -0,0 +1,20 @@
---
name: "[DE] Feature-Anfrage"
about: Schlage eine Idee für dieses Projekt vor
title: ''
labels: enhancement
assignees: ''
---
**Bezieht sich Deine Feature-Anfrage auf ein Problem? Bitte beschreiben.**
Eine klare und präzise Beschreibung des Problems. Z.B. Ich bin immer frustriert, wenn [...]
**Beschreibe die gewünschte Lösung**
Eine klare und präzise Beschreibung dessen, was passieren soll.
**Beschreibe Alternativen, die Du in Betracht gezogen hast**
Eine klare und präzise Beschreibung aller alternativen Lösungen oder Funktionen, die Du in Betracht gezogen hast.
**Zusätzlicher Kontext**
Füge hier weitere Kontexte oder Screenshots zur Feature-Anfrage hinzu.

View File

@@ -0,0 +1,38 @@
---
name: "[DE] Fehlerbericht"
about: Erstelle einen Bericht, um uns zu helfen, die App zu verbessern
title: ''
labels: bug
assignees: ''
---
**Beschreibe den Fehler**
Eine klare und präzise Beschreibung des Fehlers.
**Reproduzierung**
Schritte zum Reproduzieren des Fehlers:
1. Gehe zu '...'
2. Klicke auf '....'
3. Scrolle nach unten zu '....'
4. Sieh den Fehler
**Erwartetes Verhalten**
Eine klare und präzise Beschreibung dessen, was Du erwartet hattest.
**Screenshots**
Füge gegebenenfalls Screenshots hinzu, um Dein Problem zu erklären.
**Desktop (bitte verfolständige die folgenden Informationen):**
- Betriebssystem: [z.B. Windows 10]
- Browser [z.B. chrome, safari]
- Version [z.B. 2.14]
**Smartphone (bitte verfolständige die folgenden Informationen):**
- Gerät: [z.B. iPhone 6]
- Betriebssystem: [z.B. iOS 8.1]
- Browser [z.B. stock browser, safari]
- Version [z.B. 2.14]
**Zusätzlicher Kontext**
Füge hier einen anderen Kontext zum Problem hinzu.

View File

@@ -0,0 +1,38 @@
---
name: "[EN] Bug report"
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. Windows 10]
- Browser [e.g. chrome, safari]
- Version [e.g. 2.14]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone 6]
- OS: [e.g. iOS 8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 2.14]
**Additional context**
Add any other context about the problem here.

View File

@@ -0,0 +1,20 @@
---
name: "[EN] Feature request"
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

11
README.md Normal file
View File

@@ -0,0 +1,11 @@
# Regatten.net App
Willkommen im GitHub-Repository unserer neuen Regatten.net App.
Falls sich jemand dafür interessiert, ist hier der gesamte Quellcode unserer neuen App zu finden.
Bitte beachtet, dass diese App einschließlich dem gesamten Quellcode exklusivem Urheberrecht unterliegt. Sie darf also nicht kopiert, verteilt oder verändert werden.
Sollte Interesse an einer Anbindung an unser System bestehen, kontaktiere uns bitte einfach (https://regatten.net/contact)
Der Hauptzweck dieses Repository besteht jedoch darin, Feedback von Euch zu unserer neuen App zu bekommen.
Selbstverständlich könnt Ihr uns auch weiterhin auf anderen Kanälen erreichen, doch für Problem-Meldungen und Verbesserungsvorschläge ist GitHub am besten geeignet.
Wie Du Teil unseres BETA-Programmes wirst, die App installierst und Feedback gibst, erfährst Du in unserem [Wiki](https://github.com/ostertun/RegattenApp/wiki).

View File

@@ -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');
@@ -161,19 +161,19 @@ function dbGetResultCalculated(regatta) {
return new Promise(async function(resolve) { return new Promise(async function(resolve) {
var results = await dbGetDataIndex('results', 'regatta', regatta.id); var results = await dbGetDataIndex('results', 'regatta', regatta.id);
if (results.length > 0) { if (results.length > 0) {
var gemeldet = results.length; var gemeldet = results.length;
for (id in results) { for (id in results) {
results[id]['finished'] = false; results[id]['finished'] = false;
results[id]['values'] = []; results[id]['values'] = [];
results[id]['values_all'] = []; results[id]['values_all'] = [];
results[id]['texts'] = []; results[id]['texts'] = [];
var copy = []; var copy = [];
for (var i = 0; i < regatta['races']; i ++) { for (var i = 0; i < regatta['races']; i ++) {
var race = results[id]['race' + (i + 1)].replace(',', '.'); var race = results[id]['race' + (i + 1)].replace(',', '.');
if (!isNaN(race)) { if (!isNaN(race)) {
copy[i] = results[id]['values'][i] = parseFloat(race); copy[i] = results[id]['values'][i] = parseFloat(race);
results[id]['texts'][i] = race; results[id]['texts'][i] = race;
@@ -198,7 +198,7 @@ function dbGetResultCalculated(regatta) {
// Unbekannt // Unbekannt
default: results[id]['values'][i] = 0; copy[i] = 0; break; default: results[id]['values'][i] = 0; copy[i] = 0; break;
} }
if (results[id]['values'][i] != 0) { if (results[id]['values'][i] != 0) {
results[id]['texts'][i] = race + ' (' + results[id]['values'][i] + ')'; results[id]['texts'][i] = race + ' (' + results[id]['values'][i] + ')';
} else { } else {
@@ -206,7 +206,7 @@ function dbGetResultCalculated(regatta) {
} }
} }
} }
results[id]['values_all'] = [...results[id]['values']]; results[id]['values_all'] = [...results[id]['values']];
for (var s = 0; s < regatta['streicher']; s ++) { for (var s = 0; s < regatta['streicher']; s ++) {
var max = Math.max(...copy); var max = Math.max(...copy);
@@ -217,7 +217,7 @@ function dbGetResultCalculated(regatta) {
} }
} }
} }
var brutto = 0; var brutto = 0;
var netto = 0; var netto = 0;
for (var i = 0; i < regatta['races']; i ++) { for (var i = 0; i < regatta['races']; i ++) {
@@ -233,11 +233,11 @@ function dbGetResultCalculated(regatta) {
results[id]['brutto'] = brutto; results[id]['brutto'] = brutto;
results[id]['netto'] = netto; results[id]['netto'] = netto;
} }
compareResultsRaceCount = regatta['races']; compareResultsRaceCount = regatta['races'];
results.sort(compareResults); results.sort(compareResults);
var place = 1; var place = 1;
for (id in results) { for (id in results) {
if ((id > 0) && (compareResults(results[id], results[id - 1]) == 0)) { if ((id > 0) && (compareResults(results[id], results[id - 1]) == 0)) {
@@ -247,9 +247,9 @@ function dbGetResultCalculated(regatta) {
} }
place ++; place ++;
} }
resolve(results); resolve(results);
} else { } else {
resolve([]); resolve([]);
} }
@@ -259,26 +259,26 @@ function dbGetResultCalculated(regatta) {
function dbGetRanking(minDate, maxDate, jugend, jugstrict) { function dbGetRanking(minDate, maxDate, jugend, jugstrict) {
return new Promise(async function(resolve) { return new Promise(async function(resolve) {
var rankNoResults = []; var rankNoResults = [];
var sailors = await dbGetData('sailors'); var sailors = await dbGetData('sailors');
var regattas = await dbGetRegattasRange(minDate, maxDate); var regattas = await dbGetRegattasRange(minDate, maxDate);
var sailorIds = {}; var sailorIds = {};
for (s in sailors) { for (s in sailors) {
sailorIds[sailors[s].id] = s; sailorIds[sailors[s].id] = s;
} }
for (var i in sailors) { for (var i in sailors) {
sailors[i].regattas = {}; sailors[i].regattas = {};
sailors[i].tmp_rlp = []; sailors[i].tmp_rlp = [];
} }
for (var i in regattas) { for (var i in regattas) {
var regatta = regattas[i]; var regatta = regattas[i];
// regatta has to be min. 2 days to be ranking regatta // regatta has to be min. 2 days to be ranking regatta
if (regatta.length < 2) continue; if (regatta.length < 2) continue;
var results = await dbGetDataIndex('results', 'regatta', regatta.id); var results = await dbGetDataIndex('results', 'regatta', regatta.id);
if (results.length <= 0) { if (results.length <= 0) {
if (regatta.dateTo <= getToday()) { if (regatta.dateTo <= getToday()) {
@@ -288,7 +288,7 @@ function dbGetRanking(minDate, maxDate, jugend, jugstrict) {
} }
continue; continue;
} }
// in one race there must be at least 10 boats started // in one race there must be at least 10 boats started
var ok = false; var ok = false;
for (var j = 1; j <= regatta.races; j ++) { for (var j = 1; j <= regatta.races; j ++) {
@@ -304,9 +304,9 @@ function dbGetRanking(minDate, maxDate, jugend, jugstrict) {
} }
} }
if (!ok) continue; if (!ok) continue;
var fb = regatta.finishedBoats; var fb = regatta.finishedBoats;
// calc m // calc m
var m; var m;
if (regatta.m > 0) { if (regatta.m > 0) {
@@ -320,16 +320,16 @@ function dbGetRanking(minDate, maxDate, jugend, jugstrict) {
m = 4; m = 4;
} }
} }
// add regatta to each sailor // add regatta to each sailor
for (var r in results) { for (var r in results) {
var result = results[r]; var result = results[r];
if (result.rlp == 0) continue; if (result.rlp == 0) continue;
// check if crew is youth // check if crew is youth
// TODO: not used // TODO: not used
sailors[sailorIds[result.steuermann]].regattas[regatta.id] = { sailors[sailorIds[result.steuermann]].regattas[regatta.id] = {
regatta: regatta.id, regatta: regatta.id,
boat: result.boat, boat: result.boat,
@@ -345,7 +345,7 @@ function dbGetRanking(minDate, maxDate, jugend, jugstrict) {
} }
} }
} }
// remove not german or not youth sailors // remove not german or not youth sailors
for (var i = sailors.length - 1; i >= 0; i --) { for (var i = sailors.length - 1; i >= 0; i --) {
if (sailors[i].german == '0') { if (sailors[i].german == '0') {
@@ -357,13 +357,13 @@ function dbGetRanking(minDate, maxDate, jugend, jugstrict) {
} }
} }
} }
for (var i = sailors.length - 1; i >= 0; i --) { for (var i = sailors.length - 1; i >= 0; i --) {
// sort rlps desc // sort rlps desc
sailors[i].tmp_rlp.sort(function (a,b) { sailors[i].tmp_rlp.sort(function (a,b) {
return b[1] - a[1]; return b[1] - a[1];
}); });
// calc mean rlp // calc mean rlp
var sum = 0; var sum = 0;
var cnt = 0; var cnt = 0;
@@ -383,20 +383,40 @@ function dbGetRanking(minDate, maxDate, jugend, jugstrict) {
sailors.splice(i, 1); sailors.splice(i, 1);
} }
} }
sailors.sort(function (a,b) { sailors.sort(function (a,b) {
if (a.m != b.m) return b.m - a.m; if (a.m != b.m) return b.m - a.m;
return b.rlp - a.rlp; return b.rlp - a.rlp;
}); });
for (var i = 0; i < sailors.length; i ++) { for (var i = 0; i < sailors.length; i ++) {
sailors[i].rank = (i + 1); sailors[i].rank = (i + 1);
} }
resolve([sailors, rankNoResults]); resolve([sailors, rankNoResults]);
}); });
} }
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');
@@ -404,7 +424,7 @@ async function updateSyncStatus() { // TODO
// var now = new Date(); // var now = new Date();
// var diff = Math.round((now - lastSync) / 1000); // var diff = Math.round((now - lastSync) / 1000);
// var txt = ''; // var txt = '';
// //
// if (diff < 30) { // 30 sec // if (diff < 30) { // 30 sec
// txt = 'jetzt'; // txt = 'jetzt';
// } else if (diff < 3600) { // 60 min // } else if (diff < 3600) { // 60 min
@@ -417,7 +437,7 @@ async function updateSyncStatus() { // TODO
// diff = Math.round(diff / 86400); // diff = Math.round(diff / 86400);
// txt = 'vor ' + diff + ' ' + (diff == 1 ? 'Tag' : 'Tagen'); // txt = 'vor ' + diff + ' ' + (diff == 1 ? 'Tag' : 'Tagen');
// } // }
// //
// var btn = '<a href="#" onclick="setLoading(true); sync(); return false;"><i class="fas fa-sync"></i> Sync</a>'; // var btn = '<a href="#" onclick="setLoading(true); sync(); return false;"><i class="fas fa-sync"></i> Sync</a>';
// syncStatus.innerHTML = 'Zuletzt aktualisiert: ' + txt + btn; // syncStatus.innerHTML = 'Zuletzt aktualisiert: ' + txt + btn;
} }
@@ -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');
@@ -445,7 +471,7 @@ async function runPageScript() {
} }
// syncStatus.style.display = 'block'; // syncStatus.style.display = 'block';
} }
if (typeof siteScript === 'function') { if (typeof siteScript === 'function') {
siteScript(); siteScript();
} else { } else {
@@ -456,20 +482,20 @@ async function runPageScript() {
function sync() { function sync() {
if (!canUseLocalDB) return false; if (!canUseLocalDB) return false;
if (syncInProgress > 0) return false; if (syncInProgress > 0) return false;
var now = Math.floor(Date.now() / 1000); var now = Math.floor(Date.now() / 1000);
db.transaction('update_times').objectStore('update_times').getAll().onsuccess = function (event) { db.transaction('update_times').objectStore('update_times').getAll().onsuccess = function (event) {
var localTimes = {}; var localTimes = {};
event.target.result.forEach(function (entry) { event.target.result.forEach(function (entry) {
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');
var interval = window.setInterval(function () { var interval = window.setInterval(function () {
if (syncInProgress <= 0) { if (syncInProgress <= 0) {
window.clearInterval(interval); window.clearInterval(interval);
@@ -481,14 +507,17 @@ function sync() {
setTimeout(function(){ setTimeout(function(){
$('#i-sync').removeClass('fa-spin'); $('#i-sync').removeClass('fa-spin');
}, 500); }, 500);
if (typeof onAfterSync === 'function') {
onAfterSync();
}
runPageScript(); runPageScript();
} }
}, 100); }, 100);
getJSON(QUERY_URL + 'get_update_time', function (code, serverTimes) { getJSON(QUERY_URL + 'get_update_time', function (code, serverTimes) {
if (code == 200) { if (code == 200) {
// CLUBS // CLUBS
if (localTimes['clubs'] < serverTimes['clubs']) { if (localTimes['clubs'] < serverTimes['clubs']) {
getJSON(QUERY_URL + 'get_clubs?changed-after=' + localTimes['clubs'], function (code, data) { getJSON(QUERY_URL + 'get_clubs?changed-after=' + localTimes['clubs'], function (code, data) {
@@ -520,7 +549,7 @@ function sync() {
} else { } else {
syncInProgress --; syncInProgress --;
} }
// BOATS // BOATS
if (localTimes['boats'] < serverTimes['boats']) { if (localTimes['boats'] < serverTimes['boats']) {
getJSON(QUERY_URL + 'get_boats?changed-after=' + localTimes['boats'], function (code, data) { getJSON(QUERY_URL + 'get_boats?changed-after=' + localTimes['boats'], function (code, data) {
@@ -552,7 +581,7 @@ function sync() {
} else { } else {
syncInProgress --; syncInProgress --;
} }
// SAILORS // SAILORS
if (localTimes['sailors'] < serverTimes['sailors']) { if (localTimes['sailors'] < serverTimes['sailors']) {
getJSON(QUERY_URL + 'get_sailors?changed-after=' + localTimes['sailors'], function (code, data) { getJSON(QUERY_URL + 'get_sailors?changed-after=' + localTimes['sailors'], function (code, data) {
@@ -584,7 +613,7 @@ function sync() {
} else { } else {
syncInProgress --; syncInProgress --;
} }
// REGATTAS // REGATTAS
if (localTimes['regattas'] < serverTimes['regattas']) { if (localTimes['regattas'] < serverTimes['regattas']) {
getJSON(QUERY_URL + 'get_regattas?changed-after=' + localTimes['regattas'], function (code, data) { getJSON(QUERY_URL + 'get_regattas?changed-after=' + localTimes['regattas'], function (code, data) {
@@ -617,7 +646,7 @@ function sync() {
osYears.put({ year: y }); osYears.put({ year: y });
} }
} }
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times'); var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'regattas', time: serverTimes['regattas'] }); osUpdateTimes.put({ table: 'regattas', time: serverTimes['regattas'] });
syncInProgress --; syncInProgress --;
@@ -632,7 +661,7 @@ function sync() {
} else { } else {
syncInProgress --; syncInProgress --;
} }
// RESULTS // RESULTS
if (localTimes['results'] < serverTimes['results']) { if (localTimes['results'] < serverTimes['results']) {
getJSON(QUERY_URL + 'get_results?changed-after=' + localTimes['results'], function (code, data) { getJSON(QUERY_URL + 'get_results?changed-after=' + localTimes['results'], function (code, data) {
@@ -664,7 +693,7 @@ function sync() {
} else { } else {
syncInProgress --; syncInProgress --;
} }
// PLANNINGS // PLANNINGS
if (localTimes['plannings'] < serverTimes['plannings']) { if (localTimes['plannings'] < serverTimes['plannings']) {
getJSON(QUERY_URL + 'get_plannings?changed-after=' + localTimes['plannings'], function (code, data) { getJSON(QUERY_URL + 'get_plannings?changed-after=' + localTimes['plannings'], function (code, data) {
@@ -696,7 +725,7 @@ function sync() {
} else { } else {
syncInProgress --; syncInProgress --;
} }
if (isLoggedIn()) { if (isLoggedIn()) {
// TRIM_BOATS // TRIM_BOATS
if (localTimes['trim_boats'] < serverTimes['trim_boats']) { if (localTimes['trim_boats'] < serverTimes['trim_boats']) {
@@ -729,7 +758,7 @@ function sync() {
} else { } else {
syncInProgress --; syncInProgress --;
} }
// TRIM_USERS // TRIM_USERS
if (localTimes['trim_users'] < serverTimes['trim_users']) { if (localTimes['trim_users'] < serverTimes['trim_users']) {
getJSON(QUERY_URL + 'get_trim_users?changed-after=' + localTimes['trim_users'], function (code, data) { getJSON(QUERY_URL + 'get_trim_users?changed-after=' + localTimes['trim_users'], function (code, data) {
@@ -761,7 +790,7 @@ function sync() {
} else { } else {
syncInProgress --; syncInProgress --;
} }
// TRIM_TRIMS // TRIM_TRIMS
if (localTimes['trim_trims'] < serverTimes['trim_trims']) { if (localTimes['trim_trims'] < serverTimes['trim_trims']) {
getJSON(QUERY_URL + 'get_trim_trims?changed-after=' + localTimes['trim_trims'], function (code, data) { getJSON(QUERY_URL + 'get_trim_trims?changed-after=' + localTimes['trim_trims'], function (code, data) {
@@ -793,11 +822,43 @@ function sync() {
} else { } else {
syncInProgress --; syncInProgress --;
} }
} else { } else {
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) {
@@ -829,7 +890,7 @@ function sync() {
} else { } else {
syncInProgress --; syncInProgress --;
} }
} else { } else {
console.log("Something went wrong (HTTP " + code + ")"); console.log("Something went wrong (HTTP " + code + ")");
syncOkay = false; syncOkay = false;
@@ -856,13 +917,13 @@ function initDatabase() {
var request = window.indexedDB.open('regatten_app_db_' + BOATCLASS, DB_VERSION); var request = window.indexedDB.open('regatten_app_db_' + BOATCLASS, DB_VERSION);
request.onerror = function (event) { request.onerror = function (event) {
console.log("Cannot open DB: " + event.target.errorCode); console.log("Cannot open DB: " + event.target.errorCode);
runPageScript(); runPageScript();
}; };
request.onsuccess = function (event) { request.onsuccess = function (event) {
console.log("Database loaded"); console.log("Database loaded");
db = event.target.result; db = event.target.result;
db.onversionchange = function (event) { db.onversionchange = function (event) {
if (syncTimer != null) window.clearInterval(syncTimer); if (syncTimer != null) window.clearInterval(syncTimer);
if (updateSyncStatusTimer != null) window.clearInterval(updateSyncStatusTimer); if (updateSyncStatusTimer != null) window.clearInterval(updateSyncStatusTimer);
@@ -871,13 +932,15 @@ function initDatabase() {
db.close(); db.close();
location.reload; location.reload;
} }
db.onerror = function (event) { db.onerror = function (event) {
console.log("DB Error: " + event.target.errorCode); console.log("DB Error: " + event.target.errorCode);
}; };
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) {
@@ -886,11 +949,11 @@ function initDatabase() {
db.transaction('update_times', 'readwrite').objectStore('update_times').put({ table: 'loggedin', status: isLoggedIn() }); db.transaction('update_times', 'readwrite').objectStore('update_times').put({ table: 'loggedin', status: isLoggedIn() });
} }
}; };
checkSync(); checkSync();
syncTimer = window.setInterval(checkSync, 300000); // 5 min syncTimer = window.setInterval(checkSync, 300000); // 5 min
window.ononline = function () { window.ononline = function () {
checkSync(); checkSync();
} }
@@ -900,9 +963,9 @@ function initDatabase() {
var upgradeTransaction = event.target.transaction; var upgradeTransaction = event.target.transaction;
var oldVersion = event.oldVersion; var oldVersion = event.oldVersion;
var newVersion = event.newVersion; var newVersion = event.newVersion;
console.log("Datenbank Version Upgrade von " + oldVersion + " auf " + newVersion); console.log("Datenbank Version Upgrade von " + oldVersion + " auf " + newVersion);
if ((oldVersion < 1) && (newVersion >= 1)) { if ((oldVersion < 1) && (newVersion >= 1)) {
console.log('to version 1'); console.log('to version 1');
var osClubs = db.createObjectStore('clubs', { keyPath: 'id' }); var osClubs = db.createObjectStore('clubs', { keyPath: 'id' });
@@ -931,7 +994,7 @@ function initDatabase() {
osUpdateTimes.add({ table: 'trim_users', time: 0 }); osUpdateTimes.add({ table: 'trim_users', time: 0 });
osUpdateTimes.add({ table: 'trim_trims', time: 0 }); osUpdateTimes.add({ table: 'trim_trims', time: 0 });
} }
if ((oldVersion < 2) && (newVersion >= 2)) { if ((oldVersion < 2) && (newVersion >= 2)) {
console.log('to version 2'); console.log('to version 2');
var osUsers = db.createObjectStore('users', { keyPath: 'id' }); var osUsers = db.createObjectStore('users', { keyPath: 'id' });
@@ -939,20 +1002,32 @@ function initDatabase() {
var osUpdateTimes = upgradeTransaction.objectStore('update_times'); var osUpdateTimes = upgradeTransaction.objectStore('update_times');
osUpdateTimes.add({ table: 'users', time: 0 }); osUpdateTimes.add({ table: 'users', time: 0 });
} }
if ((oldVersion < 3) && (newVersion >= 3)) { if ((oldVersion < 3) && (newVersion >= 3)) {
console.log('to version 3'); console.log('to version 3');
var osYears = db.createObjectStore('years', { keyPath: 'year' }); var osYears = db.createObjectStore('years', { keyPath: 'year' });
var osUpdateTimes = upgradeTransaction.objectStore('update_times'); var osUpdateTimes = upgradeTransaction.objectStore('update_times');
osUpdateTimes.put({ table: 'regattas', time: 0 }); osUpdateTimes.put({ table: 'regattas', time: 0 });
} }
if ((oldVersion < 4) && (newVersion >= 4)) { if ((oldVersion < 4) && (newVersion >= 4)) {
console.log('to version 4'); console.log('to version 4');
var osUpdateTimes = upgradeTransaction.objectStore('update_times'); var osUpdateTimes = upgradeTransaction.objectStore('update_times');
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 });
} }
@@ -961,8 +1036,7 @@ function initDatabase() {
} }
} }
function resetDb(silent = true) { function resetDb() {
$('#menu-developer').hideMenu();
if (canUseLocalDB) { if (canUseLocalDB) {
showLoader(); showLoader();
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times'); var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
@@ -976,13 +1050,9 @@ 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)
toastInfo('The database was reset. Please reload or close this tab.<br>At the next visit, a full sync will be performed.');
hideLoader(); hideLoader();
} else {
if (!silent)
toastWarn('Your device does not support storing data locally. All data is fetched directly from our server.<br>As a result, you can not reset your database.');
} }
} }

View File

@@ -27,13 +27,13 @@ function parseDate(string) {
} else { } else {
return null; return null;
} }
if (isNaN(year) || isNaN(month) || isNaN(day)) return null; if (isNaN(year) || isNaN(month) || isNaN(day)) return null;
if (year.toString().length == 2) year = (year < 70 ? 2000 : 1900) + year; if (year.toString().length == 2) year = (year < 70 ? 2000 : 1900) + year;
if ((year < 1970) || (year > 3000)) return null; if ((year < 1970) || (year > 3000)) return null;
if ((month < 1) || (month > 12)) return null; if ((month < 1) || (month > 12)) return null;
if ((day < 1) || (day > 31)) return null; if ((day < 1) || (day > 31)) return null;
var date = new Date(Date.UTC(year, month - 1, day)); var date = new Date(Date.UTC(year, month - 1, day));
return date; return date;
} }
@@ -51,37 +51,37 @@ function formatDate(format, date = null) {
date = new Date(date.valueOf()); date = new Date(date.valueOf());
date.setMinutes(date.getMinutes() + date.getTimezoneOffset()); date.setMinutes(date.getMinutes() + date.getTimezoneOffset());
} }
format = format.replace("M", "%1%"); format = format.replace("M", "%1%");
format = format.replace("F", "%2%"); format = format.replace("F", "%2%");
format = format.replace("D", "%3%"); format = format.replace("D", "%3%");
format = format.replace("l", "%4%"); format = format.replace("l", "%4%");
var tmp = date.getFullYear().toString(); var tmp = date.getFullYear().toString();
var tmp2 = tmp.substr(2); var tmp2 = tmp.substr(2);
format = format.replace("Y", tmp); format = format.replace("Y", tmp);
format = format.replace('y', tmp2); format = format.replace('y', tmp2);
tmp = (date.getMonth() + 1).toString(); tmp = (date.getMonth() + 1).toString();
tmp2 = (tmp.length > 1 ? tmp : ('0' + tmp)); tmp2 = (tmp.length > 1 ? tmp : ('0' + tmp));
format = format.replace('n', tmp); format = format.replace('n', tmp);
format = format.replace('m', tmp2); format = format.replace('m', tmp2);
tmp = date.getDate().toString(); tmp = date.getDate().toString();
tmp2 = (tmp.length > 1 ? tmp : ('0' + tmp)); tmp2 = (tmp.length > 1 ? tmp : ('0' + tmp));
format = format.replace('j', tmp); format = format.replace('j', tmp);
format = format.replace('d', tmp2); format = format.replace('d', tmp2);
tmp = date.getDay(); tmp = date.getDay();
tmp2 = (tmp == 0 ? 7 : tmp); tmp2 = (tmp == 0 ? 7 : tmp);
format = format.replace('w', tmp); format = format.replace('w', tmp);
format = format.replace('N', tmp2); format = format.replace('N', tmp2);
format = format.replace('%1%', strings.months_short[date.getMonth()]); format = format.replace('%1%', strings.months_short[date.getMonth()]);
format = format.replace('%2%', strings.months_long[date.getMonth()]); format = format.replace('%2%', strings.months_long[date.getMonth()]);
format = format.replace('%3%', strings.weekdays_short[date.getDay()]); format = format.replace('%3%', strings.weekdays_short[date.getDay()]);
format = format.replace('%4%', strings.weekdays_long[date.getDay()]); format = format.replace('%4%', strings.weekdays_long[date.getDay()]);
return format; return format;
} }

File diff suppressed because it is too large Load Diff

View File

@@ -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();
}); });
} }

View File

@@ -1,9 +1,9 @@
<?php <?php
header('Content-Type: text/javascript'); header('Content-Type: text/javascript');
require_once(__DIR__ . '/../../server/config.php'); require_once(__DIR__ . '/../../server/config.php');
?> ?>
const QUERY_URL = '<?php echo QUERY_URL; ?>'; const QUERY_URL = '<?php echo QUERY_URL; ?>';
@@ -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); }
@@ -121,8 +122,8 @@ var login = function() {
showLoader(); showLoader();
var username = $('#input-login-username').val(); var username = $('#input-login-username').val();
var password = $('#input-login-password').val(); var password = $('#input-login-password').val();
$('#input-login-username').val(''); $('#input-login-username').val('').trigger('focusin').trigger('focusout');
$('#input-login-password').val(''); $('#input-login-password').val('').trigger('focusin').trigger('focusout');
$.ajax({ $.ajax({
url: QUERY_URL + 'login', url: QUERY_URL + 'login',
method: 'POST', method: 'POST',
@@ -134,7 +135,7 @@ var login = function() {
error: function (xhr, status, error) { error: function (xhr, status, error) {
if (xhr.status == 401) { if (xhr.status == 401) {
toastError('Benutzername oder Passwort falsch'); toastError('Benutzername oder Passwort falsch');
$('#input-login-username').val(username); $('#input-login-username').val(username).trigger('focusin').trigger('focusout');
} else if (xhr.status == 0) { } else if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um Dich anzumelden'); toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um Dich anzumelden');
$('#menu-login').hideMenu(); $('#menu-login').hideMenu();
@@ -202,7 +203,28 @@ var logout = function() {
}); });
} }
function resetCache() { function deleteDb() {
$('#menu-developer').hideMenu();
if (canUseLocalDB) {
showLoader();
var request = window.indexedDB.deleteDatabase('regatten_app_db_' + BOATCLASS);
request.onerror = function (event) {
console.log('Cannot delete DB: ', event.target.errorCode);
toastError('Beim Löschen der Datenbank ist ein Fehler aufgetreten.<br>Bitte melde diesen Fehler. (Dev-Menu => Problem melden)', 5000);
hideLoader();
}
request.onsuccess = function (event) {
console.log('DB deleted');
toastInfo('Die Datenbank wurde gelöscht. Die Seite lädt in wenigen Sekunden neu und erstellt damit eine neue Datenbank.', 10000);
hideLoader();
setTimeout(function(){ location.reload(); }, 3000);
}
} else {
toastWarn('Dein Gerät unterstützt kein lokales Speichern der Daten. Alle Daten werden direkt vom Server gezogen.<br>Entsprechend kannst Du die Datenbank auch nicht zurücksetzen.', 10000);
}
}
function deleteCache() {
$('#menu-developer').hideMenu(); $('#menu-developer').hideMenu();
navigator.serviceWorker.getRegistrations().then(function (registrations) { navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (let registration of registrations) { for (let registration of registrations) {
@@ -216,14 +238,197 @@ function resetCache() {
return caches.delete(key); return caches.delete(key);
})); }));
}); });
toastInfo('The serviceWorker and the cache were deleted. A new serviceWorker will be generated on the next refresh.'); toastInfo('Der serviceWorker und alle Caches wurden gelöscht. Die Seite lädt in wenigen Sekunden neu und erstellt damit neue Caches.', 10000);
setTimeout(function(){ location.reload(); }, 3000);
}
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-all').show();
$('.a-switch-pushes-channel-my').show();
if (!isLoggedIn()) {
$('.a-switch-pushes-channel-my').find('div').remove();
$('.a-switch-pushes-channel-my').find('.badge').text('nicht angemeldet');
}
} else {
$('#p-pushes-info').hide();
$('.a-switch-pushes-channel-all').hide();
$('.a-switch-pushes-channel-my').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&uuml;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');
}
});
}
async function updateNewsBadge() {
var newsRead = await dbSettingsGet('news_read_' + BOATCLASS);
if (newsRead === null) dbSettingsSet('news_read_' + BOATCLASS, newsRead = new Date());
var news = await dbGetData('news');
var now = new Date();
var sum = 0;
for (var n in news) {
var newsEntry = news[n];
newsEntry.date = new Date(Date.parse(newsEntry.date));
if (newsEntry.date > now) continue;
if (newsEntry.date < newsRead) continue;
sum ++;
}
updateBadge('more/news', sum);
} }
var initRegatten = function() { var initRegatten = function() {
showLoader(); showLoader();
initDatabase(); initDatabase();
if (isLoggedIn()) { if (isLoggedIn()) {
$('.show-loggedin').show(); $('.show-loggedin').show();
$('.show-notloggedin').hide(); $('.show-notloggedin').hide();
@@ -235,4 +440,51 @@ 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-all').click(pushesChannelClicked);
$('.a-switch-pushes-channel-my').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();
updateNewsBadge();
}
var onAfterSync = function() {
updateNewsBadge();
}
// Add console opener to preloader
var addConsoleOpenerToPreloader = function() {
addConsoleOpenerToPreloader = function(){};
var preloader = document.getElementById('preloader');
var button = document.createElement('a');
button.href = '#';
button.classList = 'btn btn-full rounded-s text-uppercase font-900 shadow-m bg-highlight m-3';
button.style.position = 'fixed';
button.style.bottom = 0;
button.style.left = 0;
button.style.right = 0;
button.innerHTML = 'Show Console';
button.onclick = function(){
mobileConsole.displayConsole();
return false;
}
setTimeout(function(){
preloader.appendChild(button);
}, 5000);
}
addConsoleOpenerToPreloader();

View File

@@ -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; }

View File

@@ -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',

View File

@@ -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&uuml;gbar.<br>'; $content .= '<p>Aktuelles der letzten zw&ouml;lf Monate</p>';
$content .= 'Wir arbeiten daran, sie schnellstm&ouml;glich zur Verf&uuml;gung zu stellen.<br>';
$content .= 'Wie w&auml;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');
?> ?>

View File

@@ -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">&nbsp;</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">&nbsp;</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,40 +120,125 @@
<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>
</div> </div>
<div id="menu-developer" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="310"> <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&auml;hle hier, &uuml;ber was Du informiert werden m&ouml;chtest.<br>
(meine) bezieht sich auf die Regatten, die in Deiner Saison-Planung sind,<br>
(alle) informiert Dich &uuml;ber alle Regatten
</p>
<a href="#" data-trigger-switch="switch-pushes-news" class="pb-2 a-switch-pushes-channel-all">
<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-my">
<i class="fa font-14 fa-calendar-check rounded-s bg-highlight color-white"></i>
<span>Regatta verschoben (meine)</span>
<span class="badge bg-red2-dark color-white"></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-all">
<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-my">
<i class="fa font-14 fa-poll rounded-s bg-highlight color-white"></i>
<span>Ergebnisse verf&uuml;gbar (meine)</span>
<span class="badge bg-red2-dark color-white"></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-all">
<i class="fa font-14 fa-poll rounded-s bg-highlight color-white"></i>
<span>Ergebnisse verf&uuml;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-my">
<i class="fa font-14 fa-file-signature rounded-s bg-highlight color-white"></i>
<span>Melde-Erinnerungen</span>
<span class="badge bg-red2-dark color-white"></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 id="menu-developer" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="360">
<div class="menu-title"><h1>Entwickler-Optionen</h1><p class="color-highlight">Version <?php echo PWA_VERSION; ?></p><a href="#" class="close-menu"><i class="fa fa-times"></i></a></div> <div class="menu-title"><h1>Entwickler-Optionen</h1><p class="color-highlight">Version <?php echo PWA_VERSION; ?></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">
<div class="list-group list-custom-small"> <div class="list-group list-custom-small">
<a href="https://info.ostertun.net/regatten/beta"> <a href="https://github.com/ostertun/RegattenApp/wiki">
<i class="fa font-14 fa-info rounded-s bg-highlight color-white"></i> <i class="fa font-14 fa-info rounded-s bg-highlight color-white"></i>
<span>Infos zur BETA</span> <span>App-Wiki</span>
<i class="fa fa-angle-right"></i> <i class="fa fa-angle-right"></i>
</a> </a>
<a href="javascript:resetDb(false);"> <a href="javascript:deleteDb();">
<i class="fa font-14 fa-database rounded-s bg-highlight color-white"></i> <i class="fa font-14 fa-database rounded-s bg-highlight color-white"></i>
<span>Reset Database</span> <span>Reset Database</span>
<i class="fa fa-angle-right"></i> <i class="fa fa-angle-right"></i>
</a> </a>
<a href="javascript:resetCache();"> <a href="javascript:deleteCache();">
<i class="fa font-14 fa-trash-alt rounded-s bg-highlight color-white"></i> <i class="fa font-14 fa-trash-alt rounded-s bg-highlight color-white"></i>
<span>Reset Cache</span> <span>Reset Cache</span>
<i class="fa fa-angle-right"></i> <i class="fa fa-angle-right"></i>
</a> </a>
<a href="https://report.regatten.net/" class="border-0"> <a href="https://github.com/ostertun/RegattenApp/issues">
<i class="fa font-14 fa-bug rounded-s bg-highlight color-white"></i> <i class="fa font-14 fa-bug rounded-s bg-highlight color-white"></i>
<span>Problem melden</span> <span>Problem melden</span>
<i class="fa fa-angle-right"></i> <i class="fa fa-angle-right"></i>
</a> </a>
<a href="#" onclick="mobileConsole.displayConsole(); return false;" class="border-0 menu-close">
<i class="fa font-14 fa-terminal rounded-s bg-highlight color-white"></i>
<span>Console anzeigen</span>
<i class="fa fa-angle-right"></i>
</a>
</div> </div>
</div> </div>
</div> </div>
@@ -181,7 +266,7 @@
<p class="text-center"> <p class="text-center">
Momentan kannst Du Dich leider nicht in der App registrieren.<br> Momentan kannst Du Dich leider nicht in der App registrieren.<br>
Das ist aber kein Problem, registriere Dich einfach kostenlos auf unserer Website! Das ist aber kein Problem, registriere Dich einfach kostenlos auf unserer Website!
</p> </p>
<a href="https://regatten.net/de/signup" class="btn btn-center-xl btn-m shadow-xl rounded-s bg-highlight font-900 text-center">Registrieren</a> <a href="https://regatten.net/de/signup" class="btn btn-center-xl btn-m shadow-xl rounded-s bg-highlight font-900 text-center">Registrieren</a>
<p class="text-center font-10 bottom-0">Du kannst Dich danach in dieser App anmelden.</p> <p class="text-center font-10 bottom-0">Du kannst Dich danach in dieser App anmelden.</p>
</div> </div>
@@ -212,8 +297,8 @@
<h1 class="text-center mt-5 font-900">Update Verfügbar</h1> <h1 class="text-center mt-5 font-900">Update Verfügbar</h1>
<p class="text-center"> <p class="text-center">
Eine neue Version unserer App ist verf&uuml;gbar. Keine Sorge, Du musst nichts machen. Wir aktuallisieren den Inhalt in wenigen Sekunden. Eine neue Version unserer App ist verf&uuml;gbar. Keine Sorge, Du musst nichts machen. Wir aktuallisieren den Inhalt in wenigen Sekunden.
</p> </p>
<a href="#" class="page-update btn btn-center-xl btn-m shadow-xl rounded-s bg-highlight font-900 text-center">Update</a> <a href="#" class="page-update btn btn-center-xl btn-m shadow-xl rounded-s bg-highlight font-900 text-center">Update</a>
<p class="text-center font-10 bottom-0">Die App wird neu laden und das Update ist abgeschlossen.</p> <p class="text-center font-10 bottom-0">Die App wird neu laden und das Update ist abgeschlossen.</p>
</div> </div>
</div> </div>

View File

@@ -1,7 +1,8 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html lang="de"> <html lang="de">
<head> <head>
<script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/mobileconsole.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"> <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
@@ -16,36 +17,36 @@
<link rel="icon" type="image/x-icon" href="<?php echo SERVER_ADDR; ?>/client/app/icons/favicon.ico"> <link rel="icon" type="image/x-icon" href="<?php echo SERVER_ADDR; ?>/client/app/icons/favicon.ico">
<link rel="apple-touch-icon" sizes="180x180" href="<?php echo SERVER_ADDR; ?>/client/app/icons/icon-192x192.png"> <link rel="apple-touch-icon" sizes="180x180" href="<?php echo SERVER_ADDR; ?>/client/app/icons/icon-192x192.png">
</head> </head>
<body class="detect-theme" data-background="none" data-highlight="blue2"> <body class="detect-theme" data-background="none" data-highlight="blue2">
<div id="preloader"><div class="spinner-border color-highlight" role="status"></div></div> <div id="preloader"><div class="spinner-border color-highlight" role="status"></div></div>
<div id="page"> <div id="page">
<?php include(__DIR__ . '/headerfooter.php'); ?> <?php include(__DIR__ . '/headerfooter.php'); ?>
<!--start of page content, add your stuff here--> <!--start of page content, add your stuff here-->
<div class="page-content header-clear-medium"> <div class="page-content header-clear-medium">
<?php echo $sp['output']; ?> <?php echo $sp['output']; ?>
</div> </div>
<!--end of page content, off canvas elements here--> <!--end of page content, off canvas elements here-->
<?php include(__DIR__ . '/menus.php'); ?> <?php include(__DIR__ . '/menus.php'); ?>
<?php echo $sp['menus']; ?> <?php echo $sp['menus']; ?>
<?php <?php
if ($site == 'index') { if ($site == 'index') {
include(__DIR__ . '/install.php'); include(__DIR__ . '/install.php');
} }
?> ?>
<!--end of div id page--> <!--end of div id page-->
</div> </div>
<?php echo $sp['scripts']; ?> <?php echo $sp['scripts']; ?>
<script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/jquery.js"></script> <script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/jquery.js"></script>
<script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/bootstrap.min.js"></script> <script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/bootstrap.min.js"></script>
<script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/strings.js.php"></script> <script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/strings.js.php"></script>
@@ -55,5 +56,5 @@
<script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/custom.js.php"></script> <script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/custom.js.php"></script>
<script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/pwa.js.php"></script> <script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/pwa.js.php"></script>
</body> </body>
</html> </html>

View File

@@ -42,7 +42,7 @@ function addRace() {
var m = parseFloat($('#input-m').val()); var m = parseFloat($('#input-m').val());
var fb = parseFloat($('#input-fb').val()); var fb = parseFloat($('#input-fb').val());
var pl = parseFloat($('#input-pl').val().replace(',', '.')); var pl = parseFloat($('#input-pl').val().replace(',', '.'));
if (isNaN(rlf) || (rlf < 1) || (rlf > 1.6)) { if (isNaN(rlf) || (rlf < 1) || (rlf > 1.6)) {
toastError('RLF ungültig'); toastError('RLF ungültig');
return; return;
@@ -59,7 +59,7 @@ function addRace() {
toastError('pl ungültig'); toastError('pl ungültig');
return; return;
} }
var race = { var race = {
rlf: rlf, rlf: rlf,
m: m, m: m,
@@ -67,12 +67,12 @@ function addRace() {
pl: pl, pl: pl,
rlp: (100 * rlf * ((fb + 1 - pl) / fb)) rlp: (100 * rlf * ((fb + 1 - pl) / fb))
}; };
$('#input-rlf').val(''); $('#input-rlf').val('').trigger('focusin').trigger('focusout');
$('#input-m').val(''); $('#input-m').val('').trigger('focusin').trigger('focusout');
$('#input-fb').val(''); $('#input-fb').val('').trigger('focusin').trigger('focusout');
$('#input-pl').val(''); $('#input-pl').val('').trigger('focusin').trigger('focusout');
races.push(race); races.push(race);
reCalc(); reCalc();
} }
@@ -89,4 +89,4 @@ var siteScript = async function () {
} }
reCalc(); reCalc();
hideLoader(); hideLoader();
} }

View File

@@ -3,12 +3,12 @@ function sendMessage() {
var email = $('#input-email').val(); var email = $('#input-email').val();
var subject = $('#input-subject').val(); var subject = $('#input-subject').val();
var message = $('#input-message').val(); var message = $('#input-message').val();
if ((name == '') || (email == '') || (subject == '') || (message == '')) { if ((name == '') || (email == '') || (subject == '') || (message == '')) {
toastError('Bitte f&uuml;lle alle Felder aus!'); toastError('Bitte f&uuml;lle alle Felder aus!');
return; return;
} }
showLoader(); showLoader();
$.ajax({ $.ajax({
url: QUERY_URL + 'contact', url: QUERY_URL + 'contact',
@@ -31,8 +31,8 @@ function sendMessage() {
}, },
success: function (data, status, xhr) { success: function (data, status, xhr) {
toastOk('Nachricht erfolgreich versandt!'); toastOk('Nachricht erfolgreich versandt!');
$('#input-subject').val(''); $('#input-subject').val('').trigger('focusin').trigger('focusout');
$('#input-message').val(''); $('#input-message').val('').trigger('focusin').trigger('focusout');
hideLoader(); hideLoader();
} }
}); });
@@ -46,4 +46,4 @@ var siteScript = async function () {
} }
$('#button-send').click(sendMessage); $('#button-send').click(sendMessage);
hideLoader(); hideLoader();
} }

View File

@@ -2,12 +2,12 @@ var today;
var siteScript = async function() { var siteScript = async function() {
today = getToday(); today = getToday();
if (isLoggedIn()) { if (isLoggedIn()) {
$('#card-notloggedin').hide(); $('#card-notloggedin').hide();
var user = await dbGetData('users', localStorage.getItem('auth_user')); var user = await dbGetData('users', localStorage.getItem('auth_user'));
// Favorites // Favorites
var watched = []; var watched = [];
for (var i = 1; i <= 5; i ++) { for (var i = 1; i <= 5; i ++) {
@@ -46,7 +46,7 @@ var siteScript = async function() {
$('#p-favorites').show(); $('#p-favorites').show();
} }
$('#card-favorites').show(); $('#card-favorites').show();
// Your next // Your next
var planningsDB = await dbGetDataIndex('plannings', 'user', user.id); var planningsDB = await dbGetDataIndex('plannings', 'user', user.id);
var minDate = getToday(); var minDate = getToday();
@@ -75,35 +75,35 @@ var siteScript = async function() {
for (i in plannings) { for (i in plannings) {
var planning = plannings[i]; var planning = plannings[i];
var regatta = planning.regatta; var regatta = planning.regatta;
if (regatta['length'] < 1) continue; if (regatta['length'] < 1) continue;
var club = null; var club = null;
if (regatta['club'] != null) if (regatta['club'] != null)
club = await dbGetData('clubs', regatta['club']); club = await dbGetData('clubs', regatta['club']);
var dateFrom = regatta['dateFrom']; var dateFrom = regatta['dateFrom'];
var dateTo = regatta['dateTo']; var dateTo = regatta['dateTo'];
// output // output
list += '<div onclick="onRegattaClicked(' + regatta['id'] + ');">'; list += '<div onclick="onRegattaClicked(' + regatta['id'] + ');">';
// ZEILE 1 // ZEILE 1
// Name // Name
list += '<div><b>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</b></div>'; list += '<div><b>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</b></div>';
// ZEILE 2 // ZEILE 2
list += '<div>'; list += '<div>';
// Number // Number
list += '<div>' + ((regatta['number'] != null) ? ('# ' + regatta['number']) : '') + '</div>'; list += '<div>' + ((regatta['number'] != null) ? ('# ' + regatta['number']) : '') + '</div>';
// Club // Club
list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>'; list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special // Special
list += '<div>' + regatta['special'] + '</div>'; list += '<div>' + regatta['special'] + '</div>';
// Icons // Icons
var icons = []; var icons = [];
if (regatta['info'] != '') if (regatta['info'] != '')
@@ -120,8 +120,10 @@ var siteScript = async function() {
ms = parseDate(regatta['meldungSchluss']); ms = parseDate(regatta['meldungSchluss']);
} }
var diff = Math.round((ms - today) / 86400000); var diff = Math.round((ms - today) / 86400000);
if ((ms >= today) && (diff < 7)) { if (ms < today) {
color = ' color-red2-dark'; color = ' color-red2-dark';
} else if (diff < 7) {
color = ' color-yellow2-dark';
} }
} }
} }
@@ -134,18 +136,18 @@ var siteScript = async function() {
icons.push('<i class="fas fa-times color-red2-dark"></i>'); icons.push('<i class="fas fa-times color-red2-dark"></i>');
} }
list += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>'; list += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>';
list += '</div>'; list += '</div>';
// ZEILE 3 // ZEILE 3
list += '<div>'; list += '<div>';
// Date // Date
list += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>'; list += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>';
// RLF // RLF
list += '<div>' + parseFloat(regatta['rlf']).toFixed(2) + '</div>'; list += '<div>' + parseFloat(regatta['rlf']).toFixed(2) + '</div>';
list += '</div></div>'; list += '</div></div>';
} }
$('#div-yournext').html(list); $('#div-yournext').html(list);
@@ -161,7 +163,7 @@ var siteScript = async function() {
$('#card-yournext').hide(); $('#card-yournext').hide();
$('#card-notloggedin').show(); $('#card-notloggedin').show();
} }
// Next // Next
var minDate = getToday(); var minDate = getToday();
minDate.setDate(minDate.getDate() - 1); minDate.setDate(minDate.getDate() - 1);
@@ -172,35 +174,35 @@ var siteScript = async function() {
list = ''; list = '';
for (i in regattas) { for (i in regattas) {
var regatta = regattas[i]; var regatta = regattas[i];
if (regatta['length'] < 1) continue; if (regatta['length'] < 1) continue;
var club = null; var club = null;
if (regatta['club'] != null) if (regatta['club'] != null)
club = await dbGetData('clubs', regatta['club']); club = await dbGetData('clubs', regatta['club']);
var plannings = await dbGetDataIndex('plannings', 'regatta', regatta['id']); var plannings = await dbGetDataIndex('plannings', 'regatta', regatta['id']);
var dateFrom = regatta['dateFrom']; var dateFrom = regatta['dateFrom'];
var dateTo = regatta['dateTo']; var dateTo = regatta['dateTo'];
// output // output
list += '<div onclick="onRegattaClicked(' + regatta['id'] + ');">'; list += '<div onclick="onRegattaClicked(' + regatta['id'] + ');">';
// ZEILE 1 // ZEILE 1
// Name // Name
list += '<div><b>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</b></div>'; list += '<div><b>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</b></div>';
// ZEILE 2 // ZEILE 2
list += '<div>'; list += '<div>';
// Number // Number
list += '<div>' + ((regatta['number'] != null) ? ('# ' + regatta['number']) : '') + '</div>'; list += '<div>' + ((regatta['number'] != null) ? ('# ' + regatta['number']) : '') + '</div>';
// Club // Club
list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>'; list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special // Special
list += '<div>' + regatta['special'] + '</div>'; list += '<div>' + regatta['special'] + '</div>';
// Icons // Icons
var icons = []; var icons = [];
if (regatta['info'] != '') if (regatta['info'] != '')
@@ -227,8 +229,10 @@ var siteScript = async function() {
ms = parseDate(regatta['meldungSchluss']); ms = parseDate(regatta['meldungSchluss']);
} }
var diff = Math.round((ms - today) / 86400000); var diff = Math.round((ms - today) / 86400000);
if ((ms >= today) && (diff < 7)) { if (ms < today) {
color = ' color-red2-dark'; color = ' color-red2-dark';
} else if (diff < 7) {
color = ' color-yellow2-dark';
} }
} }
} }
@@ -241,18 +245,18 @@ var siteScript = async function() {
icons.push('<i class="fas fa-times color-red2-dark"></i>'); icons.push('<i class="fas fa-times color-red2-dark"></i>');
} }
list += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>'; list += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>';
list += '</div>'; list += '</div>';
// ZEILE 3 // ZEILE 3
list += '<div>'; list += '<div>';
// Date // Date
list += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>'; list += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>';
// RLF // RLF
list += '<div>' + parseFloat(regatta['rlf']).toFixed(2) + '</div>'; list += '<div>' + parseFloat(regatta['rlf']).toFixed(2) + '</div>';
list += '</div></div>'; list += '</div></div>';
} }
$('#div-next').html(list); $('#div-next').html(list);
@@ -262,7 +266,7 @@ var siteScript = async function() {
$('#div-next').hide(); $('#div-next').hide();
$('#p-next').show(); $('#p-next').show();
} }
// Last // Last
var minDate = getToday(); var minDate = getToday();
minDate.setDate(minDate.getDate() - 14); minDate.setDate(minDate.getDate() - 14);
@@ -279,35 +283,35 @@ var siteScript = async function() {
list = ''; list = '';
for (i in regattas) { for (i in regattas) {
var regatta = regattas[i]; var regatta = regattas[i];
if (regatta['length'] < 1) continue; if (regatta['length'] < 1) continue;
var club = null; var club = null;
if (regatta['club'] != null) if (regatta['club'] != null)
club = await dbGetData('clubs', regatta['club']); club = await dbGetData('clubs', regatta['club']);
var dateFrom = regatta['dateFrom']; var dateFrom = regatta['dateFrom'];
var dateTo = regatta['dateTo']; var dateTo = regatta['dateTo'];
// output // output
list += '<div onclick="onRegattaClicked(' + regatta['id'] + ');">'; list += '<div onclick="onRegattaClicked(' + regatta['id'] + ');">';
// ZEILE 1 // ZEILE 1
// Name // Name
list += '<div><b>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</b></div>'; list += '<div><b>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</b></div>';
// ZEILE 2 // ZEILE 2
list += '<div>'; list += '<div>';
// Number // Number
list += '<div>' + ((regatta['number'] != null) ? ('# ' + regatta['number']) : '') + '</div>'; list += '<div>' + ((regatta['number'] != null) ? ('# ' + regatta['number']) : '') + '</div>';
// Club // Club
list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>'; list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special // Special
list += '<div>' + regatta['special'] + '</div>'; list += '<div>' + regatta['special'] + '</div>';
// Icons // Icons
var icons = []; var icons = [];
if (regatta['info'] != '') if (regatta['info'] != '')
@@ -320,18 +324,18 @@ var siteScript = async function() {
icons.push('<i class="fas fa-poll"></i>'); icons.push('<i class="fas fa-poll"></i>');
} }
list += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>'; list += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>';
list += '</div>'; list += '</div>';
// ZEILE 3 // ZEILE 3
list += '<div>'; list += '<div>';
// Date // Date
list += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>'; list += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>';
// RLF // RLF
list += '<div>' + parseFloat(regatta['rlf']).toFixed(2) + '</div>'; list += '<div>' + parseFloat(regatta['rlf']).toFixed(2) + '</div>';
list += '</div></div>'; list += '</div></div>';
} }
$('#div-last').html(list); $('#div-last').html(list);
@@ -341,6 +345,6 @@ var siteScript = async function() {
$('#div-last').hide(); $('#div-last').hide();
$('#p-last').show(); $('#p-last').show();
} }
hideLoader(); hideLoader();
} }

44
server/scripts/news.js Normal file
View 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) {
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 now = new Date();
var lastYear = new Date();
lastYear.setFullYear(lastYear.getFullYear() - 1);
for (var n in news) {
var newsEntry = news[n];
newsEntry.date = new Date(Date.parse(newsEntry.date));
if (newsEntry.date > now) continue;
if (newsEntry.date < lastYear) break;
addCard(newsEntry);
}
dbSettingsSet('news_read_' + BOATCLASS, now);
updateNewsBadge();
hideLoader();
}

View File

@@ -11,7 +11,7 @@ async function onRankingClicked(id) {
} }
} }
if (sailor == null) return; if (sailor == null) return;
$('#menu-rank').find('.menu-title').find('p').text(sailor.name); $('#menu-rank').find('.menu-title').find('p').text(sailor.name);
if (lastRanking != null) { if (lastRanking != null) {
var lastRank; var lastRank;
@@ -25,83 +25,83 @@ async function onRankingClicked(id) {
} else { } else {
$('#menu-item-text').hide(); $('#menu-item-text').hide();
} }
list = ''; list = '';
for (var i in sailor.regattas) { for (var i in sailor.regattas) {
var entry = sailor.regattas[i]; var entry = sailor.regattas[i];
var regatta = entry.regatta; var regatta = entry.regatta;
var boat = await dbGetData('boats', entry.boat); var boat = await dbGetData('boats', entry.boat);
var dateFrom = parseDate(regatta.date); var dateFrom = parseDate(regatta.date);
var dateTo = parseDate(regatta.date); var dateTo = parseDate(regatta.date);
dateTo.setDate(dateTo.getDate() + Math.max(parseInt(regatta.length) - 1, 0)); dateTo.setDate(dateTo.getDate() + Math.max(parseInt(regatta.length) - 1, 0));
list += '<div onclick="onDetailClicked(' + regatta.id + ')">'; list += '<div onclick="onDetailClicked(' + regatta.id + ')">';
// ZEILE 1 // ZEILE 1
list += '<div><b>' + regatta.name + '</b></div>'; list += '<div><b>' + regatta.name + '</b></div>';
// ZEILE 2 // ZEILE 2
list += '<div>'; list += '<div>';
// DATE // DATE
list += '<div>' + formatDate('d.m.Y', dateFrom) + ' - ' + formatDate('d.m.Y', dateTo) + '</div>'; list += '<div>' + formatDate('d.m.Y', dateFrom) + ' - ' + formatDate('d.m.Y', dateTo) + '</div>';
// m // m
list += '<div>m: ' + entry.m + '</div>'; list += '<div>m: ' + entry.m + '</div>';
// rlf // rlf
list += '<div>RLF: ' + parseFloat(regatta.rlf).toFixed(2) + '</div>'; list += '<div>RLF: ' + parseFloat(regatta.rlf).toFixed(2) + '</div>';
list += '</div>'; list += '</div>';
// ZEILE 3 // ZEILE 3
list += '<div>'; list += '<div>';
// Place // Place
list += '<div>Platz ' + entry.place + ' / ' + entry.fb + '</div>'; list += '<div>Platz ' + entry.place + ' / ' + entry.fb + '</div>';
// rlp // rlp
var color; var color;
if (entry.used == 0) { color = 'color-red2-dark'; } if (entry.used == 0) { color = 'color-red2-dark'; }
else if (entry.used == entry.m) { color = 'color-green2-dark'; } else if (entry.used == entry.m) { color = 'color-green2-dark'; }
else { color = 'color-yellow2-dark'; } else { color = 'color-yellow2-dark'; }
list += '<div>Punkte: ' + entry.used + ' x <b class="' + color + '">' + parseFloat(entry.rlp).toFixed(2) + '</b></div>'; list += '<div>Punkte: ' + entry.used + ' x <b class="' + color + '">' + parseFloat(entry.rlp).toFixed(2) + '</b></div>';
list += '</div>'; list += '</div>';
// ZEILE 4 // ZEILE 4
list += '<div>'; list += '<div>';
// Sailnumber // Sailnumber
list += '<div>' + boat.sailnumber + '</div>'; list += '<div>' + boat.sailnumber + '</div>';
// Boatname // Boatname
list += '<div>' + boat.name + '</div>'; list += '<div>' + boat.name + '</div>';
list += '</div>'; list += '</div>';
// ZEILE 5... // ZEILE 5...
var crew = entry.crew.split(','); var crew = entry.crew.split(',');
for (var c in crew) { for (var c in crew) {
var cr = await dbGetData('sailors', crew[c]); var cr = await dbGetData('sailors', crew[c]);
if (cr != null) { if (cr != null) {
list += '<div>'; list += '<div>';
// Name // Name
list += '<div>' + cr.name + '</div>'; list += '<div>' + cr.name + '</div>';
// Year // Year
list += '<div>' + ((cr.year != null) ? ('(' + cr.year + ')') : '') + '</div>'; list += '<div>' + ((cr.year != null) ? ('(' + cr.year + ')') : '') + '</div>';
list += '</div>'; list += '</div>';
} }
} }
list += '</div>'; list += '</div>';
} }
$('#div-details').html(list); $('#div-details').html(list);
$('#menu-rank').showMenu(); $('#menu-rank').showMenu();
$('#menu-rank').scrollTop(0); $('#menu-rank').scrollTop(0);
} }
@@ -111,8 +111,8 @@ async function selectChange(callSiteScript = true) {
var year = parseInt($('#select-year').val()); var year = parseInt($('#select-year').val());
if (type == "user") { if (type == "user") {
$('#select-year').parent().hide(); $('#select-year').parent().hide();
$('#input-from').parent().show(); $('#input-from').trigger('focusin').trigger('focusout').parent().show();
$('#input-to').parent().show(); $('#input-to').trigger('focusin').trigger('focusout').parent().show();
$('#input-jugend').parent().parent().show(); $('#input-jugend').parent().parent().show();
$('#input-jugstrict').parent().parent().show(); $('#input-jugstrict').parent().parent().show();
$('#button-show').show(); $('#button-show').show();
@@ -123,7 +123,7 @@ async function selectChange(callSiteScript = true) {
$('#input-jugend').parent().parent().hide(); $('#input-jugend').parent().parent().hide();
$('#input-jugstrict').parent().parent().hide(); $('#input-jugstrict').parent().parent().hide();
$('#button-show').hide(); $('#button-show').hide();
var from, to, jugend, jugstrict; var from, to, jugend, jugstrict;
switch (type) { switch (type) {
case 'year': case 'year':
@@ -168,14 +168,26 @@ async function selectChange(callSiteScript = true) {
} }
break; break;
} }
$('#input-from').val(from); $('#input-from').val(from);
$('#input-to').val(to); $('#input-to').val(to);
$('#input-jugend').prop('checked', jugend); $('#input-jugend').prop('checked', jugend);
$('#input-jugstrict').prop('checked', jugstrict); $('#input-jugstrict').prop('checked', jugstrict);
if (callSiteScript && (typeof siteScript === 'function')) if (callSiteScript && (typeof siteScript === 'function')) {
history.replaceState(null, '', '?type=' + type + '&year=' + year)
siteScript(); siteScript();
}
}
}
function buttonShowPressed() {
if (typeof siteScript === 'function') {
var chboxes = '';
if ($('#input-jugend').prop('checked')) chboxes += '&jugend=on'
if ($('#input-jugstrict').prop('checked')) chboxes += '&jugstrict=on'
history.replaceState(null, '', '?type=user&from=' + $('#input-from').val() + "&to=" + $('#input-to').val() + chboxes)
siteScript();
} }
} }
@@ -186,10 +198,23 @@ function initSelects() {
if (year === null) year = new Date().getFullYear(); if (year === null) year = new Date().getFullYear();
$('#select-type').val(type); $('#select-type').val(type);
$('#select-year').html('<option value="' + year + '">' + year + '</option>'); $('#select-year').html('<option value="' + year + '">' + year + '</option>');
$('#select-year').val(year); $('#select-year').val(year);
if (type == "user") {
var from = findGetParameter('from');
var to = findGetParameter('to');
if (from === null) from = formatDate('Y-m-d')
if (to === null) to = formatDate('Y-m-d')
$('#input-from').val(from).trigger('focusin').trigger('focusout');
$('#input-to').val(to).trigger('focusin').trigger('focusout');
var jugend = findGetParameter('jugend');
var jugstrict = findGetParameter('jugstrict');
$('#input-jugend').prop('checked', jugend !== null);
$('#input-jugstrict').prop('checked', jugstrict !== null);
}
selectChange(false); selectChange(false);
} }
@@ -218,17 +243,17 @@ var siteScript = async function() {
initSelects(); initSelects();
$('#select-type').change(selectChange); $('#select-type').change(selectChange);
$('#select-year').change(selectChange); $('#select-year').change(selectChange);
$('#button-show').click(siteScript); $('#button-show').click(buttonShowPressed);
$('#input-search').on('input', drawList); $('#input-search').on('input', drawList);
} }
var minDate = parseDate($('#input-from').val()); var minDate = parseDate($('#input-from').val());
var maxDate = parseDate($('#input-to').val()); var maxDate = parseDate($('#input-to').val());
var jugend = $('#input-jugend').prop('checked'); var jugend = $('#input-jugend').prop('checked');
var jugstrict = $('#input-jugstrict').prop('checked'); var jugstrict = $('#input-jugstrict').prop('checked');
var dbRanking = await dbGetRanking(minDate, maxDate, jugend, jugstrict); var dbRanking = await dbGetRanking(minDate, maxDate, jugend, jugstrict);
ranking = dbRanking[0]; ranking = dbRanking[0];
lastRanking = null; lastRanking = null;
if (($('#select-type').val() == 'year') || ($('#select-type').val() == 'youth')) { if (($('#select-type').val() == 'year') || ($('#select-type').val() == 'youth')) {
lastRanking = {}; lastRanking = {};
@@ -240,9 +265,9 @@ var siteScript = async function() {
lastRanking[lDbRanking[i].id] = lDbRanking[i].rank; lastRanking[lDbRanking[i].id] = lDbRanking[i].rank;
} }
} }
var selectedYear = $('#select-year').val(); var selectedYear = $('#select-year').val();
var years = await dbGetData('years'); var years = await dbGetData('years');
years.sort(function (a, b) { years.sort(function (a, b) {
if (a['year'] > b['year']) return -1; if (a['year'] > b['year']) return -1;
@@ -256,7 +281,7 @@ var siteScript = async function() {
} }
$('#select-year').html(options); $('#select-year').html(options);
$('#select-year').val(selectedYear); $('#select-year').val(selectedYear);
if (dbRanking[1].length > 0) { if (dbRanking[1].length > 0) {
$('#card-noresults').show(); $('#card-noresults').show();
list = ''; list = '';
@@ -269,18 +294,18 @@ var siteScript = async function() {
} else { } else {
$('#card-noresults').hide(); $('#card-noresults').hide();
} }
var count = ranking.length; var count = ranking.length;
if (count > 0) { if (count > 0) {
$('#input-search').parent().show(); $('#input-search').parent().show();
var dsvEnd = false; var dsvEnd = false;
rows = []; rows = [];
for (id in ranking) { for (id in ranking) {
var entry = ranking[id]; var entry = ranking[id];
for (var i in entry.regattas) { for (var i in entry.regattas) {
entry.regattas[i].regatta = await dbGetData('regattas', entry.regattas[i].regatta); entry.regattas[i].regatta = await dbGetData('regattas', entry.regattas[i].regatta);
} }
@@ -288,26 +313,26 @@ var siteScript = async function() {
entry.regattas.sort(function (a,b) { entry.regattas.sort(function (a,b) {
return a.regatta.date.localeCompare(b.regatta.date); return a.regatta.date.localeCompare(b.regatta.date);
}); });
var club = null; var club = null;
if (entry['club'] != null) if (entry['club'] != null)
club = await dbGetData('clubs', entry['club']); club = await dbGetData('clubs', entry['club']);
var row = { keywords: [], content: '' }; var row = { keywords: [], content: '' };
row.keywords.push(entry['name']); row.keywords.push(entry['name']);
if (entry['year'] != null) row.keywords.push(entry['year']); if (entry['year'] != null) row.keywords.push(entry['year']);
if (club != null) row.keywords.push(club['kurz'], club['name']); if (club != null) row.keywords.push(club['kurz'], club['name']);
if (!dsvEnd && (entry.m < 9)) { if (!dsvEnd && (entry.m < 9)) {
rows.push(null); rows.push(null);
dsvEnd = true; dsvEnd = true;
} }
row.content += '<div onclick="onRankingClicked(' + entry['id'] + ');">'; row.content += '<div onclick="onRankingClicked(' + entry['id'] + ');">';
// ZEILE 1 // ZEILE 1
row.content += '<div>'; row.content += '<div>';
// Rank // Rank
var icon = ''; var icon = '';
if (lastRanking != null) { if (lastRanking != null) {
@@ -321,39 +346,39 @@ var siteScript = async function() {
icon = '<i class="font-16 fas ' + icon + '" style="width: 1.1em; text-align: center;"></i> '; icon = '<i class="font-16 fas ' + icon + '" style="width: 1.1em; text-align: center;"></i> ';
} }
row.content += '<div>' + icon + '<b>' + entry.rank + '.</b></div>'; row.content += '<div>' + icon + '<b>' + entry.rank + '.</b></div>';
// m // m
row.content += '<div>m = ' + entry.m + '</div>'; row.content += '<div>m = ' + entry.m + '</div>';
// rlp // rlp
row.content += '<div>' + entry.rlp.toFixed(3) + '</div>'; row.content += '<div>' + entry.rlp.toFixed(3) + '</div>';
row.content += '</div>'; row.content += '</div>';
// ZEILE 2 // ZEILE 2
row.content += '<div>'; row.content += '<div>';
// Name // Name
row.content += '<div><b>' + entry.name + '</b></div>'; row.content += '<div><b>' + entry.name + '</b></div>';
// Year // Year
row.content += '<div>' + ((entry.year != null) ? ('(' + entry.year + ')') : '') + '</div>'; row.content += '<div>' + ((entry.year != null) ? ('(' + entry.year + ')') : '') + '</div>';
row.content += '</div></div>'; row.content += '</div></div>';
rows.push(row); rows.push(row);
} }
if (!dsvEnd) { if (!dsvEnd) {
rows.push(null); rows.push(null);
} }
drawList(); drawList();
} else { } else {
$('#div-rank').html('Keine Ergebnisse gefunden!'); $('#div-rank').html('Keine Ergebnisse gefunden!');
$('#input-search').parent().hide(); $('#input-search').parent().hide();
} }
hideLoader(); hideLoader();
} }

View File

@@ -1,29 +1,47 @@
function selectChange(callSiteScript = true) { function selectChange(callSiteScript = true) {
var val = $('#select-year').val(); var val = $('#select-year').val();
if (val == "user") { if (val == "user") {
$('#input-from').parent().show(); $('#input-from').trigger('focusin').trigger('focusout').parent().show();
$('#input-to').parent().show(); $('#input-to').trigger('focusin').trigger('focusout').parent().show();
$('#button-show').show(); $('#button-show').show();
} else { } else {
$('#input-from').parent().hide(); $('#input-from').parent().hide();
$('#input-to').parent().hide(); $('#input-to').parent().hide();
$('#button-show').hide(); $('#button-show').hide();
$('#input-from').val(val + '-01-01'); $('#input-from').val(val + '-01-01');
$('#input-to').val(val + '-12-31'); $('#input-to').val(val + '-12-31');
if (callSiteScript && (typeof siteScript === 'function')) if (callSiteScript && (typeof siteScript === 'function')) {
history.replaceState(null, '', '?year=' + val);
siteScript(); siteScript();
}
}
}
function buttonShowPressed() {
if (typeof siteScript === 'function') {
history.replaceState(null, '', '?year=user&from=' + $('#input-from').val() + "&to=" + $('#input-to').val())
siteScript();
} }
} }
function initYear() { function initYear() {
var year = findGetParameter('year'); var year = findGetParameter('year');
if (year === null) year = new Date().getFullYear(); if (year === null) year = new Date().getFullYear();
$('#select-year').html('<option value="' + year + '">' + year + '</option>'); $('#select-year').html('<option value="' + year + '">' + year + '</option>');
$('#select-year').val(year); $('#select-year').val(year);
if (year == "user") {
var from = findGetParameter('from');
var to = findGetParameter('to');
if (from === null) from = formatDate('Y-m-d')
if (to === null) to = formatDate('Y-m-d')
$('#input-from').val(from).trigger('focusin').trigger('focusout');
$('#input-to').val(to).trigger('focusin').trigger('focusout');
}
selectChange(false); selectChange(false);
} }
@@ -50,12 +68,12 @@ var siteScript = async function() {
firstCall = false; firstCall = false;
initYear(); initYear();
$('#select-year').change(selectChange); $('#select-year').change(selectChange);
$('#button-show').click(siteScript); $('#button-show').click(buttonShowPressed);
$('#input-search').on('input', drawList); $('#input-search').on('input', drawList);
} }
today = getToday(); today = getToday();
var minDate = parseDate($('#input-from').val()); var minDate = parseDate($('#input-from').val());
var maxDate = parseDate($('#input-to').val()); var maxDate = parseDate($('#input-to').val());
var regattas = await dbGetRegattasRange(minDate, maxDate); var regattas = await dbGetRegattasRange(minDate, maxDate);
@@ -65,9 +83,9 @@ var siteScript = async function() {
var results = await dbGetDataIndex('results', 'regatta', entry['id']); var results = await dbGetDataIndex('results', 'regatta', entry['id']);
regattaResults[entry['id']] = (results.length > 0); regattaResults[entry['id']] = (results.length > 0);
} }
var selectedYear = $('#select-year').val(); var selectedYear = $('#select-year').val();
var years = await dbGetData('years'); var years = await dbGetData('years');
years.sort(function (a, b) { years.sort(function (a, b) {
if (a['year'] > b['year']) return -1; if (a['year'] > b['year']) return -1;
@@ -81,7 +99,7 @@ var siteScript = async function() {
} }
$('#select-year').html(options); $('#select-year').html(options);
$('#select-year').val(selectedYear); $('#select-year').val(selectedYear);
var count = regattas.length; var count = regattas.length;
if (count > 0) { if (count > 0) {
if (count == 1) { if (count == 1) {
@@ -91,49 +109,49 @@ var siteScript = async function() {
} }
$('#div-regattas').show(); $('#div-regattas').show();
$('#input-search').parent().show(); $('#input-search').parent().show();
var heute = false; var heute = false;
rows = []; rows = [];
for (id in regattas) { for (id in regattas) {
var entry = regattas[id]; var entry = regattas[id];
var club = null; var club = null;
if (entry['club'] != null) if (entry['club'] != null)
club = await dbGetData('clubs', entry['club']); club = await dbGetData('clubs', entry['club']);
var plannings = await dbGetDataIndex('plannings', 'regatta', entry['id']); var plannings = await dbGetDataIndex('plannings', 'regatta', entry['id']);
var dateFrom = entry['dateFrom']; var dateFrom = entry['dateFrom'];
var dateTo = entry['dateTo']; var dateTo = entry['dateTo'];
var row = { keywords: [], content: '' }; var row = { keywords: [], content: '' };
row.keywords.push(entry['name']); row.keywords.push(entry['name']);
if (entry['number'] != null) row.keywords.push(entry['number']); if (entry['number'] != null) row.keywords.push(entry['number']);
if (club != null) row.keywords.push(club['kurz'], club['name']); if (club != null) row.keywords.push(club['kurz'], club['name']);
if (!heute && (today <= dateFrom)) { if (!heute && (today <= dateFrom)) {
rows.push(null); rows.push(null);
heute = true; heute = true;
} }
row.content += '<div onclick="onRegattaClicked(' + entry['id'] + ');">'; row.content += '<div onclick="onRegattaClicked(' + entry['id'] + ');">';
// ZEILE 1 // ZEILE 1
// Name // Name
row.content += '<div><b>' + (entry['canceled'] == 1 ? '<s>' : '') + entry['name'] + (entry['canceled'] == 1 ? '</s>' : '') + '</b></div>'; row.content += '<div><b>' + (entry['canceled'] == 1 ? '<s>' : '') + entry['name'] + (entry['canceled'] == 1 ? '</s>' : '') + '</b></div>';
// ZEILE 2 // ZEILE 2
row.content += '<div>'; row.content += '<div>';
// Number // Number
row.content += '<div>' + ((entry['number'] != null) ? ('# ' + entry['number']) : '') + '</div>'; row.content += '<div>' + ((entry['number'] != null) ? ('# ' + entry['number']) : '') + '</div>';
// Club // Club
row.content += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>'; row.content += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special // Special
row.content += '<div>' + entry['special'] + '</div>'; row.content += '<div>' + entry['special'] + '</div>';
// Icons // Icons
var icons = []; var icons = [];
if (entry['info'] != '') if (entry['info'] != '')
@@ -160,8 +178,10 @@ var siteScript = async function() {
ms = parseDate(entry['meldungSchluss']); ms = parseDate(entry['meldungSchluss']);
} }
var diff = Math.round((ms - today) / 86400000); var diff = Math.round((ms - today) / 86400000);
if ((ms >= today) && (diff < 7)) { if (ms < today) {
color = ' color-red2-dark'; color = ' color-red2-dark';
} else if (diff < 7) {
color = ' color-yellow2-dark';
} }
} }
} }
@@ -178,12 +198,12 @@ var siteScript = async function() {
icons.push('<i class="fas fa-poll"></i>'); icons.push('<i class="fas fa-poll"></i>');
} }
row.content += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>'; row.content += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>';
row.content += '</div>'; row.content += '</div>';
// ZEILE 3 // ZEILE 3
row.content += '<div>'; row.content += '<div>';
// Date // Date
if (entry['length'] < 1) { if (entry['length'] < 1) {
if (formatDate('d.m', dateFrom) == '01.01') { if (formatDate('d.m', dateFrom) == '01.01') {
@@ -194,26 +214,26 @@ var siteScript = async function() {
} else { } else {
row.content += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>'; row.content += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>';
} }
// RLF // RLF
row.content += '<div>' + parseFloat(entry['rlf']).toFixed(2) + '</div>'; row.content += '<div>' + parseFloat(entry['rlf']).toFixed(2) + '</div>';
row.content += '</div></div>'; row.content += '</div></div>';
rows.push(row); rows.push(row);
} }
if (!heute) { if (!heute) {
rows.push(null); rows.push(null);
} }
drawList(); drawList();
} else { } else {
$('#p-count').html('Keine Regatten gefunden!'); $('#p-count').html('Keine Regatten gefunden!');
$('#div-regattas').hide(); $('#div-regattas').hide();
$('#input-search').parent().hide(); $('#input-search').parent().hide();
} }
hideLoader(); hideLoader();
} }

View File

@@ -1,5 +1,5 @@
<?php <?php
define('PWA_VERSION', '1.5'); define('PWA_VERSION', '1.8');
?> ?>

View File

@@ -1,9 +1,9 @@
<?php <?php
header('Content-Type: text/javascript'); header('Content-Type: text/javascript');
require_once(__DIR__ . '/server/config.php'); require_once(__DIR__ . '/server/config.php');
?> ?>
importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js'); importScripts('https://storage.googleapis.com/workbox-cdn/releases/5.1.2/workbox-sw.js');
@@ -41,7 +41,7 @@ workbox.precaching.precacheAndRoute([
return $hash; return $hash;
} }
$hash = md5(getDirHash(__DIR__)); $hash = md5(getDirHash(__DIR__));
$path = __DIR__ . '/server/content/'; $path = __DIR__ . '/server/content/';
$dir = opendir($path); $dir = opendir($path);
while ($file = readdir($dir)) { while ($file = readdir($dir)) {
@@ -50,21 +50,25 @@ workbox.precaching.precacheAndRoute([
echo "\t{url: '$file', revision: '$hash'},\n"; echo "\t{url: '$file', revision: '$hash'},\n";
} }
closedir($dir); closedir($dir);
// ASSETS // ASSETS
$filesToCache = [ $filesToCache = [
'/manifest.json.php', '/manifest.json.php',
]; ];
$dirsToCache = [ $dirsToCache = [
'/client', '/client/app',
'/client/fonts/css',
'/client/fonts/webfonts',
'/client/images',
'/client/scripts',
'/client/styles',
]; ];
function addDir($path) { function addDir($path) {
global $filesToCache; global $filesToCache;
if ($dir = opendir(__DIR__ . $path)) { if ($dir = opendir(__DIR__ . $path)) {
while (($file = readdir($dir)) !== false) { while (($file = readdir($dir)) !== false) {
if ($file == '.') continue; if (substr($file, 0, 1) == '.') continue;
if ($file == '..') continue;
if (is_dir(__DIR__ . $path . '/' . $file)) { if (is_dir(__DIR__ . $path . '/' . $file)) {
addDir($path . '/' . $file); addDir($path . '/' . $file);
} else { } else {
@@ -74,11 +78,11 @@ workbox.precaching.precacheAndRoute([
closedir($dir); closedir($dir);
} }
} }
foreach ($dirsToCache as $path) { foreach ($dirsToCache as $path) {
addDir($path); addDir($path);
} }
foreach ($filesToCache as $file) { foreach ($filesToCache as $file) {
$revision = md5_file(__DIR__ . $file); $revision = md5_file(__DIR__ . $file);
$file = SERVER_ADDR . $file; $file = SERVER_ADDR . $file;
@@ -104,4 +108,205 @@ 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
function openDb() {
return new Promise(function(resolve) {
if (indexedDB) {
var request = indexedDB.open('regatten_app_db_<?php echo BOATCLASS; ?>');
request.onerror = function (e) {
console.log('[sW] Cannot open DB:', e.targer.errorCode);
resolve(null);
};
request.onupgradeneeded = function (e) {
console.log('[sW] DB does not exist');
e.target.transaction.abort();
resolve(null);
};
request.onsuccess = function (e) {
console.log('[sW] DB loaded');
var db = e.target.result;
db.onerror = function (e) {
console.log('[sW] DB Error:', e);
};
resolve(db);
}
} else {
resolve(null);
}
});
}
function dbSettingsGet(key) {
return new Promise(async function(resolve) {
var db = await openDb();
if (db !== null) {
var request = db.transaction('settings').objectStore('settings').get(key);
request.onsuccess = function (event) {
db.close();
console.log('[sW] DB closed');
resolve(typeof request.result != 'undefined' ? request.result.value : null);
}
} else {
resolve(null);
}
});
}
async function dbSettingsSet(key, value) {
var db = await openDb();
if (db != null) {
var os = db.transaction('settings', 'readwrite').objectStore('settings');
var request = os.put({ key: key, value: value});
request.onerror = function (event) {
console.log('[sW] Error while saving data to DB:', e);
db.close();
console.log('[sW] DB closed');
}
request.onsuccess = function (event) {
db.close();
console.log('[sW] DB closed');
}
}
}
// 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/badge-128x128.png',
vibrate: [500,100,500]
};
if ((image = getEntry(data, 'image', null)) !== null) {
options.image = image;
}
// Force refresh on next app open
var db = await openDb();
if (db != null) {
var os = db.transaction('update_times', 'readwrite').objectStore('update_times');
var request = os.put({ table: 'last_sync', time: 0 });
request.onerror = function (event) {
console.log('[sW] Error while saving data to DB:', e);
db.close();
console.log('[sW] DB closed');
}
request.onsuccess = function (event) {
db.close();
console.log('[sW] DB closed');
}
}
console.log('Showing notification');
self.registration.showNotification(data.title, options);
break;
case 'forcesync':
// Force refresh on next app open
var db = await openDb();
if (db != null) {
var os = db.transaction('update_times', 'readwrite').objectStore('update_times');
var request = os.put({ table: 'last_sync', time: 0 });
request.onerror = function (event) {
console.log('[sW] Error while saving data to DB:', e);
db.close();
console.log('[sW] DB closed');
}
request.onsuccess = function (event) {
console.log('[sW] Data successfully saved');
db.close();
console.log('[sW] DB closed');
}
}
break;
default:
console.log('[sW] Push type unknown:', data.type);
break;
}
} else {
console.log('[sW] No push type given!');
}
});
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)
);
});