Compare commits

...

97 Commits

Author SHA1 Message Date
ostertun
5c22604896 Merge branch 'release/v_1.11.2' 2020-10-22 11:38:44 +02:00
ostertun
4a65b48520 Release v_1.11.2 2020-10-22 11:38:28 +02:00
ostertun
4eb2970671 Special fields 2020-10-22 11:37:19 +02:00
ostertun
0298cefc8b Merge branch 'hotfix/error_reporting' 2020-10-22 01:17:11 +02:00
ostertun
e17f99d005 Merge branch 'hotfix/error_reporting' into develop 2020-10-22 01:17:11 +02:00
ostertun
15d7060354 gitflow-hotfix-stash: error_reporting 2020-10-22 01:10:37 +02:00
ostertun
d38de287dd Merge branch 'hotfix/ios_problems' 2020-10-21 16:27:02 +02:00
ostertun
1cb6de2402 Merge branch 'hotfix/ios_problems' into develop 2020-10-21 16:27:01 +02:00
ostertun
da2beac8d3 hotfix 2020-10-21 16:26:40 +02:00
ostertun
92a11bcfa5 gitflow-hotfix-stash: ios_problems 2020-10-21 16:26:02 +02:00
ostertun
2ddeac4ba4 sW: melde-erinnerungen only for regattas not registered 2020-10-16 13:45:02 +02:00
ostertun
fa4770e12a Merge branch 'hotfix/remote_logout' 2020-10-16 13:01:24 +02:00
ostertun
a845137873 Merge branch 'hotfix/remote_logout' into develop 2020-10-16 13:01:24 +02:00
ostertun
a6f2568753 gitflow-hotfix-stash: remote_logout 2020-10-16 13:01:06 +02:00
ostertun
6d0fdea0e8 Merge branch 'hotfix/add_planning_list_button' 2020-10-16 10:19:20 +02:00
ostertun
8bc0d9b15e Merge branch 'hotfix/add_planning_list_button' into develop 2020-10-16 10:19:20 +02:00
ostertun
1252c02d7c gitflow-hotfix-stash: add_planning_list_button 2020-10-16 10:19:05 +02:00
ostertun
f617fa7923 Merge branch 'release/v_1.11' 2020-10-15 19:41:34 +02:00
ostertun
3ff17a63e0 Merge branch 'release/v_1.11' into develop 2020-10-15 19:41:33 +02:00
ostertun
c66dc96598 Release v_1.11 2020-10-15 19:40:57 +02:00
ostertun
f5d059202e RA-#9 Signup 2020-10-15 19:39:47 +02:00
ostertun
5962e1cc90 RA-#29 Follow Sailors 2020-10-15 19:02:25 +02:00
ostertun
9f3019b4c5 Notification info banner 2020-10-15 15:19:04 +02:00
ostertun
326ba4a6bd Merge branch 'hotfix/fix_inputs_forcesync' 2020-10-15 14:04:06 +02:00
ostertun
4228ec739d Merge branch 'hotfix/fix_inputs_forcesync' into develop 2020-10-15 14:04:06 +02:00
ostertun
a38c48dab4 hotfix v_1.10.5h1 2020-10-15 14:03:55 +02:00
ostertun
da48e79a36 gitflow-hotfix-stash: fix_inputs_forcesync 2020-10-15 14:03:17 +02:00
ostertun
de5abcdfaf Merge branch 'release/v_1.10.5' 2020-10-14 14:18:03 +02:00
ostertun
6b1e35cc14 Merge branch 'release/v_1.10.5' into develop 2020-10-14 14:18:03 +02:00
ostertun
89e24f69b7 Release v_1.10.5 2020-10-14 14:17:40 +02:00
ostertun
554b810e85 Merge branch 'feature/RA-29-runtime-analysis' into develop 2020-10-14 14:16:39 +02:00
ostertun
fbd1eaaae8 Fix: hide loader on first visit 2020-10-14 13:44:34 +02:00
ostertun
ce42f87227 Cache if regatta has results 2020-10-14 13:37:47 +02:00
ostertun
e66f95ff50 Merge branch 'release/v_1.10.4' 2020-10-14 12:59:58 +02:00
ostertun
fcd791ed65 Merge branch 'release/v_1.10.4' into develop 2020-10-14 12:59:57 +02:00
ostertun
439679bbbe Release v_1.10.4 2020-10-14 12:59:35 +02:00
ostertun
9a8d6892f2 Merge branch 'feature/RA-29-runtime-analysis' into develop 2020-10-14 12:57:35 +02:00
ostertun
3b71f3d707 Better logging 2020-10-14 12:35:15 +02:00
ostertun
94c6a42106 RA-#29 remove unused code from scripts 2020-10-14 12:07:40 +02:00
ostertun
0c9eb9c013 RA-#27 back button on menu opened 2020-10-14 11:52:22 +02:00
ostertun
2034e8b659 RA-#24: dont show info after force resync 2020-10-14 11:24:36 +02:00
ostertun
e57bf4a426 RA-#25 Show loader after sync 2020-10-14 11:19:32 +02:00
ostertun
3c8289d11c index: Sort last regattas desc. 2020-10-14 11:08:27 +02:00
ostertun
63de725ebd Disable dark mode 2020-10-14 11:05:39 +02:00
ostertun
69efb93646 Merge branch 'hotfix/site_build_logging' 2020-10-11 17:01:23 +02:00
ostertun
6f302d6527 Merge branch 'hotfix/site_build_logging' into develop 2020-10-11 17:01:23 +02:00
ostertun
bfc2f84f0f Fix 2020-10-11 17:01:19 +02:00
ostertun
0660b2b6b3 Merge branch 'hotfix/site_build_logging' into develop 2020-10-11 16:57:55 +02:00
ostertun
3ee722f6c2 Merge branch 'hotfix/site_build_logging' 2020-10-11 16:57:17 +02:00
ostertun
0ce58aeacc Merge branch 'hotfix/site_build_logging' into develop 2020-10-11 16:57:17 +02:00
ostertun
28ba380cca gitflow-hotfix-stash: site_build_logging 2020-10-11 16:57:09 +02:00
ostertun
357449c1c6 Merge branch 'hotfix/update_subscription' 2020-10-09 12:59:35 +02:00
ostertun
e84eaa2562 Merge branch 'hotfix/update_subscription' into develop 2020-10-09 12:59:35 +02:00
ostertun
de70522850 gitflow-hotfix-stash: update_subscription 2020-10-09 12:59:20 +02:00
ostertun
cf5f71d14e Merge branch 'hotfix/hide_preloader_console_button' 2020-10-08 12:56:42 +02:00
ostertun
775a7bd27a Merge branch 'hotfix/hide_preloader_console_button' into develop 2020-10-08 12:56:41 +02:00
ostertun
34b47e40ab gitflow-hotfix-stash: hide_preloader_console_button 2020-10-08 12:56:19 +02:00
ostertun
32ea581437 Merge branch 'release/v_1.10.3' 2020-10-08 12:48:12 +02:00
ostertun
4106a177f8 Merge branch 'release/v_1.10.3' into develop 2020-10-08 12:48:11 +02:00
ostertun
16ccbca2af Release v_1.10.3 2020-10-08 12:47:53 +02:00
ostertun
3fd9beae1e Add last sync info 2020-10-06 00:21:23 +02:00
ostertun
01d0ae96f9 Fix no-db warning 2020-10-05 23:55:20 +02:00
ostertun
c211817f78 Added no-db warning 2020-10-05 23:52:09 +02:00
ostertun
9ff0b96837 Merge branch 'release/v_1.10.2' 2020-10-05 20:32:21 +02:00
ostertun
7a3413b339 Merge branch 'release/v_1.10.2' into develop 2020-10-05 20:32:21 +02:00
ostertun
72ff731694 Release v_1.10.2 2020-10-05 20:32:10 +02:00
ostertun
3959b208b5 Added go2url site 2020-10-05 20:19:57 +02:00
ostertun
7b500bf67d Merge branch 'release/v_1.10' 2020-10-05 17:45:03 +02:00
ostertun
5c8c9db1de Merge branch 'release/v_1.10' into develop 2020-10-05 17:45:02 +02:00
ostertun
fa526b11a8 Release v_1.10 2020-10-05 17:44:43 +02:00
ostertun
2dc2225263 Focus search input on show sailor selector 2020-10-05 17:38:00 +02:00
ostertun
fcf9dc9a20 Fixes 2020-10-05 17:35:10 +02:00
ostertun
203c2534eb Merge branch 'develop' into feature/RA-22-add-sites 2020-10-05 17:31:12 +02:00
ostertun
730dd9112f Add planning_edit 2020-10-05 17:19:24 +02:00
ostertun
13ceef37d9 Merge branch 'hotfix/regattas_range' 2020-10-05 14:49:24 +02:00
ostertun
54852f4383 Merge branch 'hotfix/regattas_range' into develop 2020-10-05 14:49:23 +02:00
ostertun
8808d12bf1 gitflow-hotfix-stash: regattas_range 2020-10-05 14:49:00 +02:00
ostertun
c6d5450b0e Merge branch 'hotfix/fix_db_sync_log' 2020-10-05 14:35:22 +02:00
ostertun
15cbe15651 Merge branch 'hotfix/fix_db_sync_log' into develop 2020-10-05 14:35:21 +02:00
ostertun
cb8a1817ae gitflow-hotfix-stash: fix_db_sync_log 2020-10-05 14:34:56 +02:00
ostertun
acf51ea71c Merge branch 'release/v_1.9' 2020-10-05 13:59:22 +02:00
ostertun
be98511957 Merge branch 'release/v_1.9' into develop 2020-10-05 13:59:22 +02:00
ostertun
65608cdd5a Release v_1.9 2020-10-05 13:58:26 +02:00
ostertun
d0996fa0c3 Merge branch 'feature/RA-22-add-sites' into develop 2020-10-05 13:57:09 +02:00
ostertun
c9a90eb77c RA-#22 Show info on preloader while first sync 2020-10-05 13:56:47 +02:00
ostertun
754cb6f77d Added edit button to planning 2020-10-05 13:37:31 +02:00
ostertun
5e926f3e75 Add share button on own planning 2020-10-05 13:09:24 +02:00
ostertun
138071769c Added planning_list 2020-10-05 12:57:17 +02:00
ostertun
26d9d83ba2 Added planning_view 2020-10-05 12:26:33 +02:00
ostertun
eaa08ba301 Custom log function => log current time 2020-10-05 11:53:54 +02:00
ostertun
760c05286e RA-#22 Added planning incl setState 2020-10-02 19:26:03 +02:00
ostertun
3f676141d7 Merge branch 'feature/RA-13-dont-show-install-request-window-w' into develop 2020-10-02 17:42:39 +02:00
ostertun
ae9bf02c49 RA-#13 Dont show install promt when welcome banner active 2020-10-02 17:42:33 +02:00
ostertun
c2a482bba1 Fix RA-#10 background color of mobileConsole 2020-10-02 17:19:59 +02:00
ostertun
06266b788d Merge branch 'feature/RA-21-news-mark-unread-news-and-add-pagi' into develop 2020-10-02 14:24:11 +02:00
ostertun
3db5ae1723 RA-#21 News: mark unread and add pagination 2020-10-02 14:24:00 +02:00
ostertun
b784733b69 Merge branch 'release/v_1.8' into develop 2020-10-02 01:29:43 +02:00
37 changed files with 2751 additions and 1884 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
const DB_VERSION = 6;
const DB_VERSION = 7;
const USER_ID = localStorage.getItem('auth_user');
const USER_NAME = localStorage.getItem('auth_username');
@@ -20,11 +20,11 @@ var getJSON = function(url, callback) {
callback(xhr.status, xhr.response);
};
xhr.ontimeout = function () {
console.log("getJSON: timeout");
log("[db] getJSON: timeout");
callback(0, null);
}
xhr.onerror = function () {
console.log("getJSON: error");
log("[db] getJSON: error");
callback(0, null);
}
if (USER_ID != null) {
@@ -76,7 +76,7 @@ function dbGetData(table, id = null) {
if (code == 200) {
resolve(data.data);
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] Something went wrong (HTTP " + code + ")");
fail(strings.error_network, 5000);
resolve([]);
}
@@ -86,7 +86,7 @@ function dbGetData(table, id = null) {
if (code == 200) {
resolve(data.data);
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] Something went wrong (HTTP " + code + ")");
fail(strings.error_network, 5000);
resolve(null);
}
@@ -108,7 +108,7 @@ function dbGetDataIndex(table, indexName, value) {
if (code == 200) {
resolve(data.data);
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] Something went wrong (HTTP " + code + ")");
fail(strings.error_network, 5000);
resolve([]);
}
@@ -351,7 +351,7 @@ function dbGetRanking(minDate, maxDate, jugend, jugstrict) {
if (sailors[i].german == '0') {
sailors.splice(i, 1);
} else if (jugend) {
if (((sailors[i].year != null) && (sailors[i].year < (formatDate('Y', maxDate) - YOUTH_AGE))) ||
if (((sailors[i].year != null) && (sailors[i].year < (formatDate('Y', maxDate) - (await dbGetClassProp('youth-age'))))) ||
((sailors[i].year == null) && (jugstrict))) {
sailors.splice(i, 1);
}
@@ -417,32 +417,56 @@ function dbSettingsSet(key, value) {
}
}
async function updateSyncStatus() { // TODO
// var syncStatus = document.getElementById('syncstatus');
// var lastSync = await dbGetData('update_times', 'last_sync');
// lastSync = new Date(lastSync.time * 1000);
// var now = new Date();
// var diff = Math.round((now - lastSync) / 1000);
// var txt = '';
//
// if (diff < 30) { // 30 sec
// txt = 'jetzt';
// } else if (diff < 3600) { // 60 min
// diff = Math.round(diff / 60);
// txt = 'vor ' + diff + ' ' + (diff == 1 ? 'Minute' : 'Minuten');
// } else if (diff < 86400) { // 24 std
// diff = Math.round(diff / 3600);
// txt = 'vor ' + diff + ' ' + (diff == 1 ? 'Stunde' : 'Stunden');
// } else {
// diff = Math.round(diff / 86400);
// 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>';
// syncStatus.innerHTML = 'Zuletzt aktualisiert: ' + txt + btn;
function dbGetClassProp(key) {
return new Promise(function(resolve) {
if (canUseLocalDB) {
var request = db.transaction('class').objectStore('class').get(key);
request.onsuccess = function (event) {
resolve(typeof request.result != 'undefined' ? request.result.value : null);
}
} else {
getJSON(QUERY_URL + 'get_class_prop?key=' + key, function (code, data) {
if (code == 200) {
resolve(data.value);
} else {
log("[db] Something went wrong (HTTP " + code + ")");
fail(strings.error_network, 5000);
resolve(null);
}
});
}
});
}
async function updateSyncStatus() {
var lastSync = await dbGetData('update_times', 'last_sync');
lastSync = new Date(lastSync.time * 1000);
if (lastSync > 0) {
var now = new Date();
var diff = Math.round((now - lastSync) / 1000);
var txt = '';
if (diff < 30) { // 30 sec
txt = 'jetzt';
} else if (diff < 3600) { // 60 min
diff = Math.round(diff / 60);
txt = 'vor ' + diff + ' ' + (diff == 1 ? 'Minute' : 'Minuten');
} else if (diff < 86400) { // 24 std
diff = Math.round(diff / 3600);
txt = 'vor ' + diff + ' ' + (diff == 1 ? 'Stunde' : 'Stunden');
} else {
diff = Math.round(diff / 86400);
txt = 'vor ' + diff + ' ' + (diff == 1 ? 'Tag' : 'Tagen');
}
} else {
var txt = 'nie';
}
$('#syncstatus').html('Zuletzt aktualisiert: ' + txt);
}
async function runPageScript() {
log('[db] running page script...')
if (canUseLocalDB) {
var osUpdateTimes = db.transaction('update_times').objectStore('update_times');
osUpdateTimes.get('loggedin').onsuccess = function (event) {
@@ -456,25 +480,33 @@ async function runPageScript() {
if (isLoggedIn()) {
var plannings = await dbGetDataIndex('plannings', 'user', USER_ID);
plannings = plannings.map(function (e) { return e.regatta; });
dbSettingsSet('myregattas_' + BOATCLASS, plannings);
plannings_all = plannings.map(function (e) { return e.regatta; });
dbSettingsSet('myregattas_' + BOATCLASS, plannings_all);
for (var i = plannings.length - 1; i >= 0; i --) {
if (plannings[i].gemeldet == '1') plannings.splice(i, 1);
}
plannings_meldung_off = plannings.map(function (e) { return e.regatta; });
dbSettingsSet('myregattas_' + BOATCLASS + '_meldung_off', plannings_meldung_off);
} else {
dbSettingsSet('myregattas_' + BOATCLASS, null);
dbSettingsSet('myregattas_' + BOATCLASS + '_meldung_off', null);
}
}
if (typeof updateSyncStatusTimer == 'undefined') { // TODO
// var syncStatus = document.getElementById('syncstatus');
if (typeof updateSyncStatusTimer == 'undefined') {
if (canUseLocalDB) {
updateSyncStatusTimer = window.setInterval(updateSyncStatus, 10000);
} else {
// syncStatus.innerHTML = 'Keine Offline-Nutzung möglich.';
$('#syncstatus').html('Keine Offline-Nutzung möglich.');
$('#i-sync').parent().hide();
updateSyncStatusTimer = null;
}
// syncStatus.style.display = 'block';
}
if (typeof siteScript === 'function') {
log('[db] loading site script');
siteScript();
} else {
log('[db] no site script');
hideLoader();
}
}
@@ -483,6 +515,7 @@ function sync() {
if (!canUseLocalDB) return false;
if (syncInProgress > 0) return false;
return new Promise(function(resolve) {
var now = Math.floor(Date.now() / 1000);
db.transaction('update_times').objectStore('update_times').getAll().onsuccess = function (event) {
@@ -491,9 +524,9 @@ function sync() {
localTimes[entry['table']] = entry['time'];
});
syncInProgress = 11;
syncInProgress = 12;
var syncOkay = true;
console.log("Sync Start");
log("[db] Sync Start");
$('#i-sync').addClass('fa-spin');
var interval = window.setInterval(function () {
@@ -503,7 +536,7 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'last_sync', time: now });
}
console.log("Sync Stop");
log("[db] Sync Stop");
setTimeout(function(){
$('#i-sync').removeClass('fa-spin');
}, 500);
@@ -511,19 +544,39 @@ function sync() {
if (typeof onAfterSync === 'function') {
onAfterSync();
}
removeSyncInfoToPreloader();
showLoader();
runPageScript();
resolve();
}
}, 100);
getJSON(QUERY_URL + 'get_update_time', function (code, serverTimes) {
if (code == 200) {
// CLASS
getJSON(QUERY_URL + 'get_class', function (code, data) {
if (code == 200) {
var os = db.transaction('class', 'readwrite').objectStore('class');
log(data);
for (key in data) {
os.put({ key: key, value: data[key] });
}
syncInProgress --;
log('[db] class synced, remaining:', syncInProgress);
} else {
log("[db] class: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] class failed, remaining:', syncInProgress);
}
});
// CLUBS
if (localTimes['clubs'] < serverTimes['clubs']) {
getJSON(QUERY_URL + 'get_clubs?changed-after=' + localTimes['clubs'], function (code, data) {
if (code == 200) {
var os = db.transaction('clubs', 'readwrite').objectStore('clubs');
console.log(data);
data.data.forEach(function (entry) {
os.put(entry);
});
@@ -538,12 +591,14 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'clubs', time: serverTimes['clubs'] });
syncInProgress --;
log('[db] clubs synced, remaining:', syncInProgress);
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] clubs: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] clubs failed, remaining:', syncInProgress);
}
});
} else {
@@ -555,7 +610,6 @@ function sync() {
getJSON(QUERY_URL + 'get_boats?changed-after=' + localTimes['boats'], function (code, data) {
if (code == 200) {
var os = db.transaction('boats', 'readwrite').objectStore('boats');
console.log(data);
data.data.forEach(function (entry) {
os.put(entry);
});
@@ -570,12 +624,14 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'boats', time: serverTimes['boats'] });
syncInProgress --;
log('[db] boats synced, remaining:', syncInProgress);
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] boats: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] boats failed, remaining:', syncInProgress);
}
});
} else {
@@ -587,7 +643,6 @@ function sync() {
getJSON(QUERY_URL + 'get_sailors?changed-after=' + localTimes['sailors'], function (code, data) {
if (code == 200) {
var os = db.transaction('sailors', 'readwrite').objectStore('sailors');
console.log(data);
data.data.forEach(function (entry) {
os.put(entry);
});
@@ -602,12 +657,14 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'sailors', time: serverTimes['sailors'] });
syncInProgress --;
log('[db] sailors synced, remaining:', syncInProgress);
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] sailors: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] sailors failed, remaining:', syncInProgress);
}
});
} else {
@@ -619,7 +676,6 @@ function sync() {
getJSON(QUERY_URL + 'get_regattas?changed-after=' + localTimes['regattas'], function (code, data) {
if (code == 200) {
var os = db.transaction('regattas', 'readwrite').objectStore('regattas');
console.log(data);
data.data.forEach(function (entry) {
os.put(entry);
});
@@ -650,12 +706,14 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'regattas', time: serverTimes['regattas'] });
syncInProgress --;
log('[db] regattas synced, remaining:', syncInProgress);
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] regattas: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] regattas failed, remaining:', syncInProgress);
}
});
} else {
@@ -667,7 +725,6 @@ function sync() {
getJSON(QUERY_URL + 'get_results?changed-after=' + localTimes['results'], function (code, data) {
if (code == 200) {
var os = db.transaction('results', 'readwrite').objectStore('results');
console.log(data);
data.data.forEach(function (entry) {
os.put(entry);
});
@@ -682,12 +739,14 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'results', time: serverTimes['results'] });
syncInProgress --;
log('[db] results synced, remaining:', syncInProgress);
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] results: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] results failed, remaining:', syncInProgress);
}
});
} else {
@@ -699,7 +758,6 @@ function sync() {
getJSON(QUERY_URL + 'get_plannings?changed-after=' + localTimes['plannings'], function (code, data) {
if (code == 200) {
var os = db.transaction('plannings', 'readwrite').objectStore('plannings');
console.log(data);
data.data.forEach(function (entry) {
os.put(entry);
});
@@ -714,12 +772,14 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'plannings', time: serverTimes['plannings'] });
syncInProgress --;
log('[db] plannings synced, remaining:', syncInProgress);
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] plannings: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] plannings failed, remaining:', syncInProgress);
}
});
} else {
@@ -732,7 +792,6 @@ function sync() {
getJSON(QUERY_URL + 'get_trim_boats?changed-after=' + localTimes['trim_boats'], function (code, data) {
if (code == 200) {
var os = db.transaction('trim_boats', 'readwrite').objectStore('trim_boats');
console.log(data);
data.data.forEach(function (entry) {
os.put(entry);
});
@@ -747,12 +806,14 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'trim_boats', time: serverTimes['trim_boats'] });
syncInProgress --;
log('[db] trim_boats synced, remaining:', syncInProgress);
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] trim_boats: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] trim_boats failed, remaining:', syncInProgress);
}
});
} else {
@@ -764,7 +825,6 @@ function sync() {
getJSON(QUERY_URL + 'get_trim_users?changed-after=' + localTimes['trim_users'], function (code, data) {
if (code == 200) {
var os = db.transaction('trim_users', 'readwrite').objectStore('trim_users');
console.log(data);
data.data.forEach(function (entry) {
os.put(entry);
});
@@ -779,12 +839,14 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'trim_users', time: serverTimes['trim_users'] });
syncInProgress --;
log('[db] trim_users synced, remaining:', syncInProgress);
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] trim_users: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] trim_users failed, remaining:', syncInProgress);
}
});
} else {
@@ -796,7 +858,6 @@ function sync() {
getJSON(QUERY_URL + 'get_trim_trims?changed-after=' + localTimes['trim_trims'], function (code, data) {
if (code == 200) {
var os = db.transaction('trim_trims', 'readwrite').objectStore('trim_trims');
console.log(data);
data.data.forEach(function (entry) {
os.put(entry);
});
@@ -811,12 +872,14 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'trim_trims', time: serverTimes['trim_trims'] });
syncInProgress --;
log('[db] trim_trims synced, remaining:', syncInProgress);
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] trim_trims: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] trim_trims failed, remaining:', syncInProgress);
}
});
} else {
@@ -832,7 +895,6 @@ function sync() {
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);
});
@@ -847,12 +909,14 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'news', time: serverTimes['news'] });
syncInProgress --;
log('[db] news synced, remaining:', syncInProgress);
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] news: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] news failed, remaining:', syncInProgress);
}
});
} else {
@@ -864,7 +928,6 @@ function sync() {
getJSON(QUERY_URL + 'get_users?changed-after=' + localTimes['users'], function (code, data) {
if (code == 200) {
var os = db.transaction('users', 'readwrite').objectStore('users');
console.log(data);
data.data.forEach(function (entry) {
os.put(entry);
});
@@ -879,12 +942,14 @@ function sync() {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'users', time: serverTimes['users'] });
syncInProgress --;
log('[db] users synced, remaining:', syncInProgress);
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
log("[db] users: Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
log('[db] users failed, remaining:', syncInProgress);
}
});
} else {
@@ -892,12 +957,18 @@ function sync() {
}
} else {
console.log("Something went wrong (HTTP " + code + ")");
if (code == 401) {
log("[db] Auth invalid. Logout initiated");
logoutClearStorage();
} else {
log("[db] Something went wrong (HTTP " + code + ")");
}
syncOkay = false;
syncInProgress = 0;
}
});
};
});
}
function checkSync() {
@@ -913,28 +984,31 @@ function checkSync() {
}
function initDatabase() {
log('[db] Initializing DB...');
if (window.indexedDB) {
var request = window.indexedDB.open('regatten_app_db_' + BOATCLASS, DB_VERSION);
request.onerror = function (event) {
console.log("Cannot open DB: " + event.target.errorCode);
log("[db] Cannot open DB: " + event.target);
if (typeof onDatabaseLoaded == 'function') onDatabaseLoaded();
runPageScript();
};
request.onsuccess = function (event) {
console.log("Database loaded");
log("[db] Database loaded");
db = event.target.result;
db.onversionchange = function (event) {
if (syncTimer != null) window.clearInterval(syncTimer);
if (updateSyncStatusTimer != null) window.clearInterval(updateSyncStatusTimer);
// TODO document.getElementById('syncstatus').innerHTML = '';
$('#syncstatus').html('');
canUseLocalDB = false;
db.close();
location.reload;
}
db.onerror = function (event) {
console.log("DB Error: " + event.target.errorCode);
log("[db] DB Error: " + event.target);
};
canUseLocalDB = true;
@@ -943,10 +1017,12 @@ function initDatabase() {
db.transaction('update_times').objectStore('update_times').get('last_sync').onsuccess = function (event) {
var lastSync = event.target.result.time;
if (lastSync > 0) {
if (lastSync > 1) {
runPageScript();
} else {
if (lastSync < 1) addSyncInfoToPreloader();
db.transaction('update_times', 'readwrite').objectStore('update_times').put({ table: 'loggedin', status: isLoggedIn() });
loaderCount --;
}
};
@@ -964,10 +1040,10 @@ function initDatabase() {
var oldVersion = event.oldVersion;
var newVersion = event.newVersion;
console.log("Datenbank Version Upgrade von " + oldVersion + " auf " + newVersion);
log("[db] DB Version Upgrade from " + oldVersion + " to " + newVersion);
if ((oldVersion < 1) && (newVersion >= 1)) {
console.log('to version 1');
log('[db] to version 1');
var osClubs = db.createObjectStore('clubs', { keyPath: 'id' });
var osBoats = db.createObjectStore('boats', { keyPath: 'id' });
var osSailors = db.createObjectStore('sailors', { keyPath: 'id' });
@@ -996,7 +1072,7 @@ function initDatabase() {
}
if ((oldVersion < 2) && (newVersion >= 2)) {
console.log('to version 2');
log('[db] to version 2');
var osUsers = db.createObjectStore('users', { keyPath: 'id' });
osUsers.createIndex('username', 'username', { unique: true });
var osUpdateTimes = upgradeTransaction.objectStore('update_times');
@@ -1004,34 +1080,44 @@ function initDatabase() {
}
if ((oldVersion < 3) && (newVersion >= 3)) {
console.log('to version 3');
log('[db] to version 3');
var osYears = db.createObjectStore('years', { keyPath: 'year' });
var osUpdateTimes = upgradeTransaction.objectStore('update_times');
osUpdateTimes.put({ table: 'regattas', time: 0 });
}
if ((oldVersion < 4) && (newVersion >= 4)) {
console.log('to version 4');
log('[db] to version 4');
var osUpdateTimes = upgradeTransaction.objectStore('update_times');
osUpdateTimes.add({ table: 'loggedin', status: isLoggedIn() });
}
if ((oldVersion < 5) && (newVersion >= 5)) {
console.log('to version 5');
log('[db] to version 5');
var osPushes = db.createObjectStore('settings', { keyPath: 'key' });
}
if ((oldVersion < 6) && (newVersion >= 6)) {
console.log('to version 6');
log('[db] to version 6');
var osNews = db.createObjectStore('news', { keyPath: 'id' });
var osUpdateTimes = upgradeTransaction.objectStore('update_times');
osUpdateTimes.add({ table: 'news', time: 0 });
}
if ((oldVersion < 7) && (newVersion >= 7)) {
log('[db] to version 7');
var osClass = db.createObjectStore('class', { keyPath: 'key' });
}
// Force resync after db update
if (oldVersion >= 1) {
var osUpdateTimes = upgradeTransaction.objectStore('update_times');
osUpdateTimes.put({ table: 'last_sync', time: 0 });
osUpdateTimes.put({ table: 'last_sync', time: 1 });
}
}
} else {
if (typeof onDatabaseLoaded == 'function') onDatabaseLoaded();
runPageScript();
}
}
@@ -1040,7 +1126,7 @@ function resetDb() {
if (canUseLocalDB) {
showLoader();
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'last_sync', time: 0 });
osUpdateTimes.put({ table: 'last_sync', time: 1 });
osUpdateTimes.put({ table: 'clubs', time: 0 });
osUpdateTimes.put({ table: 'boats', time: 0 });
osUpdateTimes.put({ table: 'sailors', time: 0 });
@@ -1052,7 +1138,24 @@ function resetDb() {
osUpdateTimes.put({ table: 'trim_trims', time: 0 });
osUpdateTimes.put({ table: 'news', time: 0 });
osUpdateTimes.put({ table: 'users', time: 0 });
console.log('DB update times reset');
log('[db] DB update times reset');
hideLoader();
}
}
function addSyncInfoToPreloader() {
var preloader = document.getElementById('preloader');
var div = document.createElement('div');
div.id = 'preloader-sync-info';
div.classList = 'rounded-s shadow-m bg-highlight m-3 p-3';
div.style.position = 'fixed';
div.style.top = 0;
div.style.left = 0;
div.style.right = 0;
div.innerHTML = '<h2 class="color-white">Datenbank SYNC</h2><p class="mb-0 color-white">Um Dir alle n&ouml;tigen Informationen anzeigen zu k&ouml;nnen, m&uuml;ssen wir die Datenbank synchronisieren.<br>Dies kann einen Moment dauern. Bitte habe etwas Geduld. Beim n&auml;chsten &Ouml;ffnen geht es schneller.</p>';
preloader.appendChild(div);
}
function removeSyncInfoToPreloader() {
$('#preloader-sync-info').remove();
}

View File

@@ -38,6 +38,16 @@ function parseDate(string) {
return date;
}
function parseDbTimestamp(string) {
var year = string.substr(0, 4);
var month = string.substr(5, 2);
var day = string.substr(8, 2);
var hour = string.substr(11, 2);
var minute = string.substr(14, 2);
var second = string.substr(17, 2);
return new Date(year, month - 1, day, hour, minute, second);
}
function getToday() {
var date = new Date();
date = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));

View File

@@ -335,7 +335,7 @@ var mobileConsole = (function () {
var elements = {
lines: [],
acItems: [],
base: createElem('div', 'base', {
base: createElem('div', 'base page-bg', {
boxSizing: 'border-box',
position: 'fixed',
resize: 'none',
@@ -1038,7 +1038,7 @@ var mobileConsole = (function () {
function isRepeat(message, method) {
return (history.output.prevMsg === message && history.output.prevMethod === method) && (typeof message !== 'object') && (method !== 'trace') && (method !== 'group') && (method !== 'groupCollapsed') && (method !== 'groupEnd');
}
function newConsole() {
function newConsole2() {
try {
//get arguments, set vars
var method = arguments[0], className, isHTMLElement,
@@ -1155,6 +1155,8 @@ var mobileConsole = (function () {
if (!msgContainer.innerHTML) { return; }
leftContainer.appendChild(msgContainer);
var errorReportEntry = { message: arguments[1].newMessage };
if (detailTable || stackTable) {
setCSS(msgContainer, {cursor : 'pointer'});
leftContainer.appendChild(detailTable || stackTable);
@@ -1164,7 +1166,17 @@ var mobileConsole = (function () {
//populate right side
if (stackTrace && typeof stackTrace[stackTrace.length - 1] !== 'undefined') {
rightContainer.appendChild(setCSS(getLink(stackTrace[0].url, stackTrace[0].linkText), {color: '#808080'}));
errorReportEntry.stack = { caller: stackTrace[0].caller, file: stackTrace[0].url, line: stackTrace[0].line, col: stackTrace[0].col };
if ((typeof LINK_PRE !== 'undefined') && (errorReportEntry.stack.file.startsWith(LINK_PRE))) {
errorReportEntry.stack.file = errorReportEntry.stack.file.substr(LINK_PRE.length);
}
var pos = errorReportEntry.stack.file.indexOf('?');
if (pos >= 0) {
errorReportEntry.stack.file = errorReportEntry.stack.file.substr(0, pos);
}
}
if (typeof onConsoleOutput === 'function') onConsoleOutput(errorReportEntry);
//add to line
lineContainer.appendChild(leftContainer);
@@ -1195,11 +1207,7 @@ var mobileConsole = (function () {
}
//scroll
consoleElement.toggleScroll();
//==========================================================
//make sure we still call the original method, if applicable (not window.onerror)
if (typeof arguments[1].original === 'function') {
arguments[1].original.apply(console, arguments[1].originalArguments);
}
} catch (e) {
//not logging. why? throw error
if (options.browserinfo.isMobile) { alert(e); }
@@ -1211,6 +1219,37 @@ var mobileConsole = (function () {
}
}
function newConsole() {
if (typeof arguments[1].newMessage === 'object') {
var args = arguments[1].newMessage.slice();
var argString = [];
for (var i in args) {
if (typeof args[i] === 'object') {
if (argString.length > 0) {
arguments[1].newMessage = argString.join(' ');
newConsole2(...arguments);
argString = [];
}
arguments[1].newMessage = args[i];
newConsole2(...arguments);
} else {
argString.push(args[i]);
}
}
if (argString.length > 0) {
arguments[1].newMessage = argString.join(' ');
newConsole2(...arguments);
argString = [];
}
} else {
newConsole2(...arguments);
}
//==========================================================
//make sure we still call the original method, if applicable (not window.onerror)
if (typeof arguments[1].original === 'function') {
arguments[1].original.apply(console, arguments[1].originalArguments);
}
}
function interceptConsole(method) {
var original = console ? console[method] : missingMethod(), i, stackTraceOrig;
if (!console) { console = {}; } //create empty console if we have no console (IE?)
@@ -1218,7 +1257,7 @@ var mobileConsole = (function () {
var args = Array.prototype.slice.call(arguments);
args.original = original;
args.originalArguments = arguments;
args.newMessage = (method === 'assert') ? [args[0], args[1]] : args[0];
//args.newMessage = (method === 'assert') ? [args[0], args[1]] : args[0];
//create an Error and get its stack trace and format it
try { throw new Error(); } catch (e) { stackTraceOrig = e.stack; }
args.newStackTrace = formatStackTrace(args.newStackTrace, stackTraceOrig);
@@ -1241,6 +1280,12 @@ var mobileConsole = (function () {
return;
}
//Handle the new console logging
args.newMessage = [];
var i = 0;
while (typeof args[i] !== 'undefined') {
args.newMessage.push(args[i]);
i ++;
}
newConsole(method, args);
};
}

View File

@@ -20,8 +20,6 @@ $(document).ready(function(){
'use strict'
var pwaVersion = '<?php echo PWA_VERSION; ?>'; //must be identical to _manifest.json version. If not it will create update window loop
var pwaCookie = true; // if set to false, the PWA prompt will appear even if the user selects "maybe later"
var pwaNoCache = false; // always keep the cache clear to serve the freshest possible content
$('[data-pwa-version]').data('pwa-version', pwaVersion);
@@ -35,7 +33,7 @@ $(document).ready(function(){
//Enabling dismiss button
setTimeout(function(){
$('.pwa-dismiss').on('click',function(){
console.log('User Closed Add to Home / PWA Prompt')
log('[pwa] User Closed Add to Home / PWA Prompt')
createCookie('Sticky_pwa_rejected_install', true, 1);
$('body').find('#menu-install-pwa-android, #menu-install-pwa-ios, .menu-hider').removeClass('menu-active');
});
@@ -52,34 +50,37 @@ $(document).ready(function(){
//Firing PWA prompts for specific versions and when not on home screen.
if (isMobile.Android()) {
console.log('Android Detected');
log('[pwa] Android Detected');
function showInstallPromotion(){
if($('#menu-install-pwa-android, .add-to-home').length){
console.log('Triggering PWA Menu for Android');
log('[pwa] Triggering PWA Menu for Android');
if (!readCookie('Sticky_pwa_rejected_install')) {
setTimeout(function(){
$('.add-to-home').addClass('add-to-home-visible add-to-home-android');
$('#menu-install-pwa-android, .menu-hider').addClass('menu-active')
},4500);
},3000);
}
} else {
console.log('The div #menu-install-pwa-android was not found. Please add this div to show the install window')
}
}
let deferredPrompt;
window.addEventListener('beforeinstallprompt', (e) => {
e.preventDefault();
deferredPrompt = e;
var welcomActive = $('#menu-welcome').hasClass('menu-active');
if (welcomActive) {
$('#menu-welcome-a-okay').click(showInstallPromotion);
} else {
showInstallPromotion();
}
});
$('.pwa-install').on('click',function(e){
deferredPrompt.prompt();
deferredPrompt.userChoice
.then((choiceResult) => {
if (choiceResult.outcome === 'accepted') {
console.log('User accepted the A2HS prompt');
log('[pwa] User accepted the A2HS prompt');
} else {
console.log('User dismissed the A2HS prompt');
log('[pwa] User dismissed the A2HS prompt');
}
deferredPrompt = null;
});
@@ -91,98 +92,25 @@ $(document).ready(function(){
if (isMobile.iOS()) {
if(!isInWebAppiOS){
console.log('iOS Detected');
log('[pwa] iOS Detected');
if($('#menu-install-pwa-ios, .add-to-home').length){
if (!readCookie('Sticky_pwa_rejected_install')) {
console.log('Triggering PWA / Add to Home Screen Menu for iOS');
setTimeout(function(){
function triggerPwaInstallIos() {
log('[pwa] Triggering PWA / Add to Home Screen Menu for iOS');
$('.add-to-home').addClass('add-to-home-visible add-to-home-ios');
$('#menu-install-pwa-ios, .menu-hider').addClass('menu-active');
},4500);
};
}
var welcomActive = $('#menu-welcome').hasClass('menu-active');
if (welcomActive) {
$('#menu-welcome-a-okay').click(triggerPwaInstallIos);
} else {
console.log('The div #menu-install-pwa-ios was not found. Please add this div to show the install window')
}
}
}
//Creating Update Modal
function updateModal(){
var body = $('body');
var updateModal = $('#menu-update');
var mt = new Date();
var menuUpdate = mt.getHours() + ":" + mt.getMinutes() + ":" + mt.getSeconds();
if(!updateModal.length){
body.append('<div id="menu-update"></div>');
setTimeout(function(){
body.find('#menu-update').load('menu-update.html?ver='+menuUpdate);
},250);
}
};
//Update Version in 5 Seconds After New Version Detected
function updateButton(){
var counter = 3;
var interval = setInterval(function() {
counter--;
console.log(counter);
$('.page-update').html('Aktuallisierung in ... '+ counter + ' Sekunden');
if (counter == 0) {
clearInterval(interval);
window.location.reload(true)
}
}, 1000);
caches.delete('workbox-runtime').then(function() {
console.log('Content Updated - Cache Removed!');
});
//localStorage.clear();
sessionStorage.clear()
caches.keys().then(cacheNames => {
cacheNames.forEach(cacheName => {
caches.delete(cacheName);
});
});
};
//Check Version
function check_version(){
if($('link[data-pwa-version]').length){
function versionCheck(){
var dt = new Date();
var maniTimeVersion = dt.getHours() + ":" + dt.getMinutes() + ":" + dt.getSeconds();
var localVersionNumber = $('link[rel="manifest"]').data('pwa-version');
var onlineVersionJSON = "<?php echo SERVER_ADDR; ?>/manifest.json.php?ver=" + maniTimeVersion;
var onlineVersionNumber = "Connection Offline. Waiting to Reconect";
$.getJSON(onlineVersionJSON, function(onlineData) {onlineVersionNumber = onlineData.version;});
setTimeout(function(){
//console.log(' Checking PWA Content for updates...\n PWA Server Version: ' + onlineVersionNumber + '\n' + ' PWA Cached Version: ' + localVersionNumber);
if(onlineVersionNumber != localVersionNumber && onlineVersionNumber != "Connection Offline. Waiting to Reconect"){
updateModal();
console.log('New Version of Content Available. Refreshing. On Desktop Browsers a manual refresh maybe required.')
setTimeout(function(){
$('body').find('#menu-update').addClass('menu-active');
$('.menu-hider').addClass('menu-active-no-click');
updateButton();
},500);
}
if(onlineVersionNumber == localVersionNumber){/*No update required. Versions Identical*/}
if(onlineVersionNumber === "undefined"){/*Error Checking for Updates*/}
if(onlineVersionNumber === "Finding Online Version..."){
$('.reloadme').addClass('disabled');
$('body').find('#menu-update').removeClass('menu-active');
$('.menu-hider').removeClass('menu-active-no-click');
triggerPwaInstallIos();
}
},3000);
}
//Checking for new version every 60 seconds
setInterval(function(){versionCheck()}, 50000);
//Initial Load Version Check in 10 Second After Load
setTimeout(function(){versionCheck();}, 10000);
};
}
}
if(pwaCookie == false){
eraseCookie('Sticky_pwa_rejected_install');
}
//Reload To Clear Button
@@ -190,9 +118,6 @@ $(document).ready(function(){
location.reload();
});
//Check for Version Change if Online If not Kill the Function
if (navigator.onLine) {check_version();} else {function check_version(){}}
//Adding Offline Alerts
var offlineAlerts = $('.offline-message');
@@ -215,47 +140,19 @@ $(document).ready(function(){
setTimeout(function(){$('.online-message').removeClass('online-message-active');},2000);
}
$('.simulate-offline').on('click',function(){isOffline();})
$('.simulate-online').on('click',function(){isOnline();})
//Disable links to other pages if offline.
//Warning! Enabling offline for iOS can cause issues
//To allow offline functionality delete the next 7 lines
function returnFalse(){
var detectHREF = $(this).attr('href');
if(detectHREF.match(/.html/)){
isOffline();
return false;
}
}
//Check if Online / Offline
function updateOnlineStatus(event) {
var condition = navigator.onLine ? "online" : "offline";
isOnline();
console.log( 'Connection: Online');
$("a").off( "click", returnFalse );
log('[pwa] Connection: Online');
}
function updateOfflineStatus(event) {
isOffline();
$("a").on( "click", returnFalse );
console.log( 'Connection: Offline');
log('[pwa] Connection: Offline');
}
window.addEventListener('online', updateOnlineStatus);
window.addEventListener('offline', updateOfflineStatus);
if(pwaNoCache == true){
caches.delete('workbox-runtime').then(function() {
});
localStorage.clear();
sessionStorage.clear()
caches.keys().then(cacheNames => {
cacheNames.forEach(cacheName => {
caches.delete(cacheName);
});
});
}
});

View File

@@ -3,16 +3,53 @@
header('Content-Type: text/javascript');
require_once(__DIR__ . '/../../server/config.php');
require_once(__DIR__ . '/../../server/version.php');
?>
const QUERY_URL = '<?php echo QUERY_URL; ?>';
const BOATCLASS = '<?php echo BOATCLASS; ?>';
const LINK_PRE = '<?php echo SERVER_ADDR; ?>/';
const YOUTH_AGE = '<?php echo $_CLASS['youth-age']; ?>';
const YOUTH_GERMAN_NAME = '<?php echo $_CLASS['youth-german-name']; ?>';
const PUSH_SERVER_KEY = '<?php echo PUSH_SERVER_KEY; ?>';
var consoleOutput = [];
function onConsoleOutput(entry) {
consoleOutput.push(entry);
}
window.onerror = function(message, source, lineno, colno, errorError) {
if (source.startsWith(LINK_PRE)) {
source = source.substr(LINK_PRE.length);
}
var pos = source.indexOf('?');
if (pos >= 0) {
source = source.substr(0, pos);
}
consoleOutput.push({
message: message,
stack: {
caller: '',
file: source,
line: lineno,
col: colno
}
});
}
function log() {
var now = new Date();
var hour = now.getHours().toString();
var min = now.getMinutes().toString();
var sec = now.getSeconds().toString();
var millis = now.getMilliseconds().toString();
hour = (hour.length < 2 ? '0' + hour : hour);
min = (min.length < 2 ? '0' + min : min);
sec = (sec.length < 2 ? '0' + sec : sec);
while (millis.length < 3) millis = '0' + millis;
console.log('[' + hour + ':' + min + ':' + sec + '.' + millis + ']', ...arguments);
}
var randomId = function() { return '_' + Math.random().toString(36).substr(2, 9); }
var badges = {
@@ -118,6 +155,47 @@ function findGetParameter(parameterName) {
return result;
}
var signup = function() {
var username = $('#input-signup-username').val();
var email = $('#input-signup-email').val();
var password = $('#input-signup-password').val();
if (username == '') { $('#input-signup-username').focus(); return; }
if (email == '') { $('#input-signup-email').focus(); return; }
if (password == '') { $('#input-signup-password').focus(); return; }
showLoader();
$('#input-signup-username').val('').trigger('focusin').trigger('focusout');
$('#input-signup-email').val('').trigger('focusin').trigger('focusout');
$('#input-signup-password').val('').trigger('focusin').trigger('focusout');
$.ajax({
url: QUERY_URL + 'signup',
method: 'POST',
data: {
username: username,
email: email,
password: password
},
error: function (xhr, status, error) {
if (xhr.status == 409) {
toastError('Benutzername bereits vergeben');
$('#input-signup-email').val(email).trigger('focusin').trigger('focusout');
} else if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um Dich anzumelden');
$('#menu-signup').hideMenu();
} else {
log('[app] Signup: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
hideLoader();
},
success: function (data, status, xhr) {
$('#input-login-username').val(username);
$('#input-login-password').val(password);
login();
}
});
}
var login = function() {
showLoader();
var username = $('#input-login-username').val();
@@ -140,8 +218,8 @@ var login = function() {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um Dich anzumelden');
$('#menu-login').hideMenu();
} else {
console.log('Login: unbekannter Fehler', status, error);
console.log(xhr);
log('[app] Login: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
hideLoader();
@@ -173,7 +251,7 @@ var logout = function() {
hash: localStorage.getItem('auth_hash')
}
if ((auth.id === null) || (auth.hash === null)) {
console.log('Not logged in');
log('[app] Not logged in');
logoutClearStorage();
return;
}
@@ -185,14 +263,14 @@ var logout = function() {
},
error: function (xhr, status, error) {
if (xhr.status == 401) {
console.log('Not logged in');
log('[app] Not logged in');
logoutClearStorage();
} else if (xhr.status == 0) {
console.log('Could not delete auth from server');
log('[app] Could not delete auth from server');
logoutClearStorage();
} else {
console.log('Logout: unbekannter Fehler', status, error);
console.log(xhr);
log('[app] Logout: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
hideLoader();
}
@@ -209,12 +287,12 @@ function deleteDb() {
showLoader();
var request = window.indexedDB.deleteDatabase('regatten_app_db_' + BOATCLASS);
request.onerror = function (event) {
console.log('Cannot delete DB: ', event.target.errorCode);
log('[app] 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');
log('[app] 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);
@@ -228,13 +306,13 @@ function deleteCache() {
$('#menu-developer').hideMenu();
navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (let registration of registrations) {
console.log('Unregister sW:', registration);
log('[app] Unregister sW:', registration);
registration.unregister();
}
});
caches.keys().then((keyList) => {
return Promise.all(keyList.map((key) => {
console.log('Cache deleted:', key);
log('[app] Cache deleted:', key);
return caches.delete(key);
}));
});
@@ -260,7 +338,7 @@ function urlB64ToUint8Array(base64String) {
}
function pushesSubscribe() {
console.log('Subscribing');
log('[app] Subscribing');
const applicationServerKey = urlB64ToUint8Array(PUSH_SERVER_KEY);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
@@ -272,14 +350,14 @@ function pushesSubscribe() {
updatePushBadge();
})
.catch(function(err) {
console.log('Failed to subscribe the user: ', err);
log('[app] 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');
log('[app] Unsubscribing');
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
@@ -291,7 +369,7 @@ function pushesUnSubscribe(silent = false) {
}
})
.catch(function(error) {
console.log('Error unsubscribing', error);
log('[app] 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();
@@ -300,7 +378,7 @@ function pushesUnSubscribe(silent = false) {
}
function pushesUpdateServerSubscription(subscription, enabled) {
console.log('updateServer', enabled, subscription);
log('[app] updateServer', enabled, subscription);
$.ajax({
url: QUERY_URL + (enabled ? 'add' : 'remove') + '_subscription',
type: 'POST',
@@ -393,6 +471,7 @@ function pushesOpenMenu() {
}
function updatePushBadge() {
if (typeof onUpdatePushBadge === 'function') onUpdatePushBadge();
if (!pushesPossible) return;
if (Notification.permission == 'denied') {
$('#badge-pushes').removeClass('bg-green2-dark').addClass('bg-red2-dark').text('BLOCKED');
@@ -416,7 +495,7 @@ async function updateNewsBadge() {
var sum = 0;
for (var n in news) {
var newsEntry = news[n];
newsEntry.date = new Date(Date.parse(newsEntry.date));
newsEntry.date = parseDbTimestamp(newsEntry.date);
if (newsEntry.date > now) continue;
if (newsEntry.date < newsRead) continue;
sum ++;
@@ -427,8 +506,12 @@ async function updateNewsBadge() {
var initRegatten = function() {
showLoader();
log('[app] Initializing DB...');
initDatabase();
log('[app] Loading app specific code...');
if (isLoggedIn()) {
$('.show-loggedin').show();
$('.show-notloggedin').hide();
@@ -448,7 +531,8 @@ var initRegatten = function() {
}
var onServiceWorkerLoaded = function() {
if ((swRegistration !== null) && canUseLocalDB) {
log('[app] sW loaded');
if ((swRegistration !== null) && (swRegistration.pushManager) && canUseLocalDB) {
pushesPossible = true;
updatePushBadge();
} else {
@@ -457,6 +541,21 @@ var onServiceWorkerLoaded = function() {
}
var onDatabaseLoaded = function() {
log('[app] DB loaded');
if (!canUseLocalDB && !$('#menu-welcome').hasClass('menu-active')) {
function NoDbWarningOk() {
createCookie('regatten_nodb_banner', true, 1);
$('#menu-nodb-warning').hideMenu();
}
function showNoDbWarning() {
if (!readCookie('regatten_nodb_banner')) {
$('#menu-nodb-warning').showMenu();
}
}
$('#menu-nodb-warning-okay').click(NoDbWarningOk);
showNoDbWarning();
}
onServiceWorkerLoaded();
initPushSettings();
@@ -472,19 +571,39 @@ var addConsoleOpenerToPreloader = function() {
addConsoleOpenerToPreloader = function(){};
var preloader = document.getElementById('preloader');
var button = document.createElement('a');
button.id = 'button-show-console';
button.href = '#';
button.classList = 'btn btn-full rounded-s text-uppercase font-900 shadow-m bg-highlight m-3';
button.classList = 'btn rounded-s text-uppercase font-900 shadow-m m-3 bg-red2-dark bg-white';
button.style.position = 'fixed';
button.style.bottom = 0;
button.style.left = 0;
button.style.right = 0;
button.innerHTML = 'Show Console';
button.innerHTML = 'Fehlerbericht senden';
button.onclick = function(){
mobileConsole.displayConsole();
alert('FEHLERBERICHT\nEs wird jetzt ein Fehlerbericht an die Entwickler geschickt.\nBitte stelle sicher, dass Du mit dem Internet verbunden bist und drücke dann auf OK.');
$.ajax({
url: QUERY_URL + 'error_report',
method: 'POST',
data: {
errors: consoleOutput,
device: navigator.userAgent,
version: '<?php echo PWA_VERSION; ?>'
},
error: function (xhr, status, error) {
if (xhr.status == 0) {
alert('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um den Fehlerbericht zu senden');
} else {
alert('Beim Senden ist ein unbekannter Fehler aufgetreten. Bitte versuche es noch einmal');
}
},
success: function (data, status, xhr) {
alert('Wir leiten Dich jetzt zum erstellten Fehlerbericht um, sodass Du ggf. weitere Informationen ergänzen kannst.');
location.href = 'https://github.com/ostertun/RegattenApp/issues/' + data.issueNumber;
}
});
return false;
}
setTimeout(function(){
preloader.appendChild(button);
}, 5000);
$(button).hide();
}
addConsoleOpenerToPreloader();

13
server/content/go2url.php Normal file
View File

@@ -0,0 +1,13 @@
<?php
$sp['title'] = 'Umleitung - Regatten.net ' . $_CLASS['name'];
// Title
$content = '<h1>Umleitung</h1>';
$content .= '<p>Wir leiten Dich in K&uuml;rze zur gew&uuml;nschten Website weiter</p>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-title']);
$sp['scripts'] .= $scripts->load('go2url');
?>

View File

@@ -11,8 +11,7 @@
// Favorites
$content = '<h2>Deine Favoriten</h2>';
$thead = '<tr><th>Segler</th><th id="th-ranking">Rangliste</th></tr>';
$content .= $tpl->load('table', [$thead, 'html-id' => 'table-favorites', 'css-class' => 'mb-0 mt-3']);
$content .= '<div id="div-favorites" class="normal-list mb-0"></div>';
$content .= '<p id="p-favorites" class="mt-3">';
$content .= 'Du folgst <b>keinen</b> Seglern.<br>';
$content .= 'Um jemandem zu folgen, gehe zur <a href="' . LINK_PRE . 'sailors">Segler-Liste</a> und w&auml;hle bis zu f&uuml;nf Segler aus.';
@@ -38,6 +37,18 @@
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-notloggedin']);
// Notification Info
$content = '<h2 class="color-white">Push-Benachrichtigungen</h2>';
$content .= '<p class="mt-3 mb-3 color-white">';
$content .= '<b>Bleibe immer auf dem Laufendem!</b><br>';
$content .= 'Aktiviere einfach unsere Push-Benachrichtigungen und wir informieren Dich &uuml;ber alle &Auml;nderungen.<br>';
$content .= 'Du bestimmst nat&uuml;rlich, welche Benachrichtigungen Du bekommen m&ouml;chtest.';
$content .= '</p>';
$content .= $tpl->load('button', ['Jetzt aktivieren', '#', 'html-id' => 'button-notifications-activate', 'css-class' => 'bg-green2-dark']);
$content .= '<p class="text-center mt-3"><a id="a-notifications-later" class="color-grey2-light text-uppercase font-900">Vielleicht sp&auml;ter</a></p>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-notifications', 'css-class' => 'bg-blue2-dark']);
// Next
$content = '<h2>N&auml;chste Regatten</h2>';
$content .= '<div id="div-next" class="regattas-list mb-0"></div>';
@@ -69,7 +80,8 @@
$sp['output'] .= $tpl->load('card', [$content]);
// Regattas Menu
$items = '<p id="menu-item-yourplanning" class="mb-2 mt-1" style="line-height: 1.5em;"></p>';
$items = '<p id="menu-item-special" class="mb-2 mt-1" style="line-height: 1.5em;"></p>';
$items .= '<p id="menu-item-yourplanning" class="mb-2 mt-1" style="line-height: 1.5em;"></p>';
$items .= $tpl->load('menu/item-icon', ['Saison-Planungen', '', 'html-id' => 'menu-item-plannings', 'icon' => 'fa-calendar-alt']);
$items .= $tpl->load('menu/item-icon', ['Ergebnisse', '', 'html-id' => 'menu-item-results', 'icon' => 'fa-poll']);
$items .= $tpl->load('menu/item-icon', ['Bericht', '', 'html-id' => 'menu-item-bericht', 'icon' => 'fa-book']);
@@ -79,6 +91,10 @@
$items .= $tpl->load('menu/item-icon', ['Vereins-Website', '', 'html-id' => 'menu-item-clubwebsite', 'icon' => 'fa-globe']);
$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-regatta', 'title' => 'Regatta-Details', 'height' => 320]);
// Favorites Menu
$items = $tpl->load('menu/item-icon', ['Nicht mehr folgen', '#', 'html-id' => 'menu-item-unfollow', 'icon' => 'fa-heart', 'css-class' => ' border-0']);
$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-favorite', 'title' => 'Favorit', 'height' => 200]);
$sp['scripts'] .= $scripts->load('onRegattaClicked');
$sp['scripts'] .= $scripts->load('index');

View File

@@ -10,9 +10,15 @@
$sp['output'] .= $tpl->load('card', [$content]);
$sp['output'] .= '<div id="news-entries"></div>';
// Pagination
$sp['output'] .= $tpl->load('pagination', ['html-id' => 'pagination']);
// Menu
$sp['menus'] .= $tpl->load('menu/modal', ['html-id' => 'menu-news', 'title' => 'Details']);
$sp['scripts'] .= $scripts->load('pagination', ['pageChange', 'page', 'pageCount', 'pagination']);
$cardTemplate = $tpl->load('card', ['%CONTENT%', 'html-id' => '%ID%', 'css-class' => 'card-news']);
$cardTemplate = str_replace("\n", '', $cardTemplate);
$cardTemplate = str_replace("\r", '', $cardTemplate);

View File

@@ -1,19 +1,50 @@
<?php
// TODO: Create site
$sp['title'] = 'Saison-Planung - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = 'index';
$sp['activenav'] = 5;
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
// Title
$content = '<h1>Saison-Planung</h1>';
$content .= $tpl->load('button', ['<i class="fas fa-list"></i>&ensp;Saison-Planungen anderer', LINK_PRE . 'planning_list', 'css-class' => 'mt-2 mb-2']);
$content .= '<p class="mb-1"><b>Hinweis:</b> Diese Seite kannst nur Du sehen.<br>Wenn Du Deine Saison-Planung teilen möchtest, <a id="a-share-planning">klicke hier</a></p>';
$content .= $tpl->load('button', ['<i class="fas fa-edit"></i>&ensp;bearbeiten', LINK_PRE . 'planning_edit']);
$content .= $tpl->load('select', ['html-id' => 'select-year', 'placeholder' => 'Jahr', 'css-class' => 'mt-3 mb-0']);
$content = $tpl->load('error', ['404', 'Seite existiert noch nicht']);
$content .= '<p>';
$content .= 'Die gesuchte Seite ist leider noch nicht verf&uuml;gbar.<br>';
$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' => 'show-loggedin']);
$sp['output'] = $tpl->load('card', [$content, 'css-class' => 'text-center pt-3']);
// Not loggedin
$content = '<h1>Saison-Planung</h1>';
$content .= '<p>Um Deine Saison-Planung zu sehen, musst Du angemeldet sein.<br><a href="#" data-menu="menu-login">Melde Dich hier an</a> oder <a href="#" data-menu="menu-signup">registriere Dich jetzt kostenlos</a>.</p>';
$sp['output'] .= $tpl->load('card', [$content, 'css-class' => 'show-notloggedin']);
// Regattas
$content = '<p id="p-count" class="mb-0"></p>';
$content .= $tpl->load('input', ['html-id' => 'input-search', 'placeholder' => 'Suche', 'type' => 'text', 'css-class' => 'mt-2']);
$content .= '<div id="div-regattas" class="regattas-list mb-0"></div>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-regattas', 'css-class' => 'show-loggedin']);
// Menu
$items = '<p id="menu-item-special" class="mb-2 mt-1" style="line-height: 1.5em;"></p>';
$items .= '<p id="menu-item-yourplanning" class="mb-2 mt-1" style="line-height: 1.5em;"></p>';
$items .= $tpl->load('menu/item-icon', ['Status bearbeiten', '#', 'html-id' => 'menu-item-status', 'icon' => 'fa-edit']);
$items .= $tpl->load('menu/item-icon', ['Saison-Planungen', '', 'html-id' => 'menu-item-plannings', 'icon' => 'fa-calendar-alt']);
$items .= $tpl->load('menu/item-icon', ['Ergebnisse', '', 'html-id' => 'menu-item-results', 'icon' => 'fa-poll']);
$items .= $tpl->load('menu/item-icon', ['Bericht', '', 'html-id' => 'menu-item-bericht', 'icon' => 'fa-book']);
$items .= $tpl->load('menu/item-icon', ['Informationen', '', 'html-id' => 'menu-item-info', 'icon' => 'fa-info']);
$items .= $tpl->load('menu/item-icon-badge', ['Meldung', '', 'html-id' => 'menu-item-meldung', 'icon' => 'fa-file-signature', 'badge-id' => 'badge-regatta-meldung']);
$items .= $tpl->load('menu/item-icon', ['offizielle Ergebnisse', '', 'html-id' => 'menu-item-oresults', 'icon' => 'fa-poll']);
$items .= $tpl->load('menu/item-icon', ['Vereins-Website', '', 'html-id' => 'menu-item-clubwebsite', 'icon' => 'fa-globe']);
$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-regatta', 'title' => 'Regatta-Details', 'height' => 320]);
// Menu Edit status
$items = $tpl->load('menu/item-switch', ['Gemeldet', 'html-id' => 'switch-status-gemeldet', 'icon' => 'fa-file-signature']);
$items .= $tpl->load('menu/item-switch', ['Bezahlt', 'html-id' => 'switch-status-bezahlt', 'icon' => 'fa-euro-sign', 'css-class' => 'border-0']);
$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-status', 'title' => 'Status bearbeiten', 'height' => 220]);
$sp['scripts'] .= $scripts->load('onRegattaClicked');
$sp['scripts'] .= $scripts->load('planning');
?>

View File

@@ -1,19 +1,31 @@
<?php
// TODO: Create site
$sp['title'] = 'Saison-Planung bearbeiten - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = 'planning';
$sp['activenav'] = 5;
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
// Title, Inputs
$content = "<h1>Saison-Planung bearbeiten</h1>";
$content .= $tpl->load('select', ['html-id' => 'select-year', 'placeholder' => 'Jahr', 'css-class' => 'mt-3 mb-0']);
$content = $tpl->load('error', ['404', 'Seite existiert noch nicht']);
$content .= '<p>';
$content .= 'Die gesuchte Seite ist leider noch nicht verf&uuml;gbar.<br>';
$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]);
$sp['output'] = $tpl->load('card', [$content, 'css-class' => 'text-center pt-3']);
// Regattas
$content = '<p id="p-count" class="mb-0"></p>';
$content .= $tpl->load('input', ['html-id' => 'input-search', 'placeholder' => 'Suche', 'type' => 'text', 'css-class' => 'mt-2']);
$content .= '<div id="div-regattas" class="ranking-detail-list mb-0"></div>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-regattas']);
// Menu
$items = $tpl->load('menu/item-switch', ['In die Saison-Planung aufnehmen', 'html-id' => 'switch-planning-include', 'icon' => 'fa-check']);
$items .= $tpl->load('menu/item-simple', ['', '#', 'html-id' => 'item-steuermann']);
$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-edit', 'title' => 'Regatta bearbeiten', 'height' => 320]);
// Select sailor
$items = $tpl->load('input', ['html-id' => 'input-edit-search', 'placeholder' => 'Suche', 'type' => 'text']);
$sp['menus'] .= $tpl->load('menu/modal', [$items, 'html-id' => 'menu-sailor', 'height' => 500, 'width' => 350]);
$sp['scripts'] .= $scripts->load('planning_edit');
?>

View File

@@ -1,19 +1,27 @@
<?php
// TODO: Create site
$sp['title'] = 'Saison-Planungen - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = 'planning';
$sp['activenav'] = 5;
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
// Title
$content = '<h1>Saison-Planungen</h1>';
$content .= $tpl->load('select', ['html-id' => 'select-year', 'placeholder' => 'Jahr', 'css-class' => 'mt-3 mb-0']);
$content = $tpl->load('error', ['404', 'Seite existiert noch nicht']);
$content .= '<p>';
$content .= 'Die gesuchte Seite ist leider noch nicht verf&uuml;gbar.<br>';
$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' => 'show-loggedin']);
$sp['output'] = $tpl->load('card', [$content, 'css-class' => 'text-center pt-3']);
// Not loggedin
$content = '<h1>Saison-Planungen</h1>';
$content .= '<p>Um die Saison-Planungen anderer zu sehen, musst Du angemeldet sein.<br><a href="#" data-menu="menu-login">Melde Dich hier an</a> oder <a href="#" data-menu="menu-signup">registriere Dich jetzt kostenlos</a>.</p>';
$sp['output'] .= $tpl->load('card', [$content, 'css-class' => 'show-notloggedin']);
// Regattas
$content = $tpl->load('input', ['html-id' => 'input-search', 'placeholder' => 'Suche', 'type' => 'text']);
$content .= '<div id="div-users" class="normal-list mb-0"></div>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-regattas', 'css-class' => 'show-loggedin']);
$sp['scripts'] .= $scripts->load('planning_list');
?>

View File

@@ -1,19 +1,37 @@
<?php
// TODO: Create site
$sp['title'] = 'Saison-Planung - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = 'planning_list';
$sp['activenav'] = 5;
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
// Title
$content = '<h1>Saison-Planung</h1>';
$content .= '<p id="p-username" class="mb-1"></p>';
$content .= $tpl->load('button', ['<i class="fas fa-share-alt"></i>&ensp;Teilen', '#', 'html-id' => 'button-share']);
$content .= $tpl->load('select', ['html-id' => 'select-year', 'placeholder' => 'Jahr', 'css-class' => 'mt-3 mb-0']);
$content = $tpl->load('error', ['404', 'Seite existiert noch nicht']);
$content .= '<p>';
$content .= 'Die gesuchte Seite ist leider noch nicht verf&uuml;gbar.<br>';
$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]);
$sp['output'] = $tpl->load('card', [$content, 'css-class' => 'text-center pt-3']);
// Regattas
$content = '<p id="p-count" class="mb-0"></p>';
$content .= $tpl->load('input', ['html-id' => 'input-search', 'placeholder' => 'Suche', 'type' => 'text', 'css-class' => 'mt-2']);
$content .= '<div id="div-regattas" class="ranking-detail-list mb-0"></div>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-regattas']);
// Menu
$items = '<p id="menu-item-special" class="mb-2 mt-1" style="line-height: 1.5em;"></p>';
$items .= '<p id="menu-item-yourplanning" class="mb-2 mt-1" style="line-height: 1.5em;"></p>';
$items .= $tpl->load('menu/item-icon', ['Saison-Planungen', '', 'html-id' => 'menu-item-plannings', 'icon' => 'fa-calendar-alt']);
$items .= $tpl->load('menu/item-icon', ['Ergebnisse', '', 'html-id' => 'menu-item-results', 'icon' => 'fa-poll']);
$items .= $tpl->load('menu/item-icon', ['Bericht', '', 'html-id' => 'menu-item-bericht', 'icon' => 'fa-book']);
$items .= $tpl->load('menu/item-icon', ['Informationen', '', 'html-id' => 'menu-item-info', 'icon' => 'fa-info']);
$items .= $tpl->load('menu/item-icon-badge', ['Meldung', '', 'html-id' => 'menu-item-meldung', 'icon' => 'fa-file-signature', 'badge-id' => 'badge-regatta-meldung']);
$items .= $tpl->load('menu/item-icon', ['offizielle Ergebnisse', '', 'html-id' => 'menu-item-oresults', 'icon' => 'fa-poll']);
$items .= $tpl->load('menu/item-icon', ['Vereins-Website', '', 'html-id' => 'menu-item-clubwebsite', 'icon' => 'fa-globe']);
$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-regatta', 'title' => 'Regatta-Details', 'height' => 320]);
$sp['scripts'] .= $scripts->load('onRegattaClicked');
$sp['scripts'] .= $scripts->load('planning_view');
?>

View File

@@ -21,8 +21,11 @@
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-regattas']);
$sp['output'] .= $tpl->load('card', ['<p></p>', 'html-id' => 'card-special']);
// Menu
$items = '<p id="menu-item-yourplanning" class="mb-2 mt-1" style="line-height: 1.5em;"></p>';
$items = '<p id="menu-item-special" class="mb-2 mt-1" style="line-height: 1.5em;"></p>';
$items .= '<p id="menu-item-yourplanning" class="mb-2 mt-1" style="line-height: 1.5em;"></p>';
$items .= $tpl->load('menu/item-icon', ['Saison-Planungen', '', 'html-id' => 'menu-item-plannings', 'icon' => 'fa-calendar-alt']);
$items .= $tpl->load('menu/item-icon', ['Ergebnisse', '', 'html-id' => 'menu-item-results', 'icon' => 'fa-poll']);
$items .= $tpl->load('menu/item-icon', ['Bericht', '', 'html-id' => 'menu-item-bericht', 'icon' => 'fa-book']);

View File

@@ -31,9 +31,11 @@
$sp['output'] .= $tpl->load('pagination', ['html-id' => 'pagination']);
// Menu
$items = $tpl->load('menu/item-icon', ['', '#', 'html-id' => 'menu-item-year', 'icon' => 'fa-edit']);
$items = $tpl->load('menu/item-switch', ['Favorit', 'html-id' => 'menu-item-follow', 'icon' => 'fa-heart']);
$items .= $tpl->load('menu/item-icon-badge', ['Favorit', '#', 'html-id' => 'menu-item-follow-disabled', 'icon' => 'fa-heart', 'badge-value' => 'MAX REACHED']);
$items .= $tpl->load('menu/item-icon', ['', '#', 'html-id' => 'menu-item-year', 'icon' => 'fa-edit']);
$items .= $tpl->load('menu/item-icon', ['Vereins-Website', '', 'html-id' => 'menu-item-clubwebsite', 'icon' => 'fa-globe', 'css-class' => 'border-0']);
$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-sailor', 'title' => 'Segler-Details', 'height' => 200]);
$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-sailor', 'title' => 'Segler-Details', 'height' => 260]);
$items = '<p class="mb-2 mt-1" style="line-height: 1.5em;">Bitte trage hier den Jahrgang ein:</p>';
$items .= $tpl->load('input', ['html-id' => 'input-edityear', 'placeholder' => 'Jahrgang', 'type' => 'number']);

View File

@@ -1,29 +1,29 @@
<div id="menu-share" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="345" data-menu-effect="menu-over">
<div class="menu-title mt-n1"><h1>Share the Love</h1><p class="color-highlight">Just Tap the Social Icon. We'll add the Link</p><a href="#" class="close-menu"><i class="fa fa-times"></i></a></div>
<div class="menu-title mt-n1"><h1>Seite Teilen</h1><p class="color-highlight">Teile diese Seite mit Deinen Freunden!</p><a href="#" class="close-menu"><i class="fa fa-times"></i></a></div>
<div class="content mb-0">
<div class="divider mb-0"></div>
<div class="list-group list-custom-small list-icon-0">
<a href="#" class="shareToFacebook">
<a href="#" class="shareToFacebook" target="_blank">
<i class="font-18 fab fa-facebook color-facebook"></i>
<span class="font-13">Facebook</span>
<i class="fa fa-angle-right"></i>
</a>
<a href="#" class="shareToTwitter">
<a href="#" class="shareToTwitter" target="_blank">
<i class="font-18 fab fa-twitter-square color-twitter"></i>
<span class="font-13">Twitter</span>
<i class="fa fa-angle-right"></i>
</a>
<a href="#" class="shareToLinkedIn">
<a href="#" class="shareToLinkedIn" target="_blank">
<i class="font-18 fab fa-linkedin color-linkedin"></i>
<span class="font-13">LinkedIn</span>
<i class="fa fa-angle-right"></i>
</a>
<a href="#" class="shareToWhatsApp">
<a href="#" class="shareToWhatsApp" target="_blank">
<i class="font-18 fab fa-whatsapp-square color-whatsapp"></i>
<span class="font-13">WhatsApp</span>
<i class="fa fa-angle-right"></i>
</a>
<a href="#" class="shareToMail border-0">
<a href="#" class="shareToMail border-0" target="_blank">
<i class="font-18 fa fa-envelope-square color-mail"></i>
<span class="font-13">Email</span>
<i class="fa fa-angle-right"></i>
@@ -92,11 +92,12 @@
</div>
</div>
<div id="menu-settings" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="310">
<div id="menu-settings" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="260">
<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="content">
<div class="list-group list-custom-small">
<?php if (false) { /* DARK MODE DISABLED (set menu height to 310) */ ?>
<a href="#" data-toggle-theme data-trigger-switch="switch-dark" class="pb-2">
<i class="fa font-14 fa-moon rounded-s bg-dark1-dark color-white"></i>
<span>Dark Mode</span>
@@ -105,6 +106,7 @@
<label class="custom-control-label" for="switch-dark"></label>
</div>
</a>
<?php } ?>
<a href="#" data-menu="menu-login" class="show-notloggedin">
<i class="fa font-14 fa-sign-in-alt rounded-s bg-highlight color-white"></i>
<span>Login</span>
@@ -243,7 +245,7 @@
</div>
</div>
<div id="menu-login" class="menu menu-box-top menu-box-detached rounded-m" data-menu-height="270">
<div id="menu-login" class="menu menu-box-top menu-box-detached rounded-m" data-menu-height="320">
<div class="content bottom-0">
<h1 class="text-center mt-5 font-900">Login</h1>
<div class="input-style input-style-2 has-icon input-required">
@@ -257,18 +259,29 @@
<input id="input-login-password" class="form-control" type="password" placeholder="Passwort" />
</div>
<a class="btn btn-m mt-2 mb-2 btn-full bg-green2-dark text-uppercase font-900" href="#" onclick="login();">Login</a>
<p class="text-center mt-3"><a class="text-uppercase font-900" href="https://regatten.net/reset">Benutzername oder Passwort vergessen</a></p>
</div>
</div>
<div id="menu-signup" class="menu menu-box-modal menu-box-detached rounded-m" data-menu-height="300">
<div id="menu-signup" class="menu menu-box-top menu-box-detached rounded-m" data-menu-height="340">
<div class="content bottom-0">
<h1 class="text-center mt-5 font-900">Registrieren</h1>
<p class="text-center">
Momentan kannst Du Dich leider nicht in der App registrieren.<br>
Das ist aber kein Problem, registriere Dich einfach kostenlos auf unserer Website!
</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>
<p class="text-center font-10 bottom-0">Du kannst Dich danach in dieser App anmelden.</p>
<div class="input-style input-style-2 has-icon input-required">
<i class="input-icon fa fa-user color-theme"></i>
<span class="color-highlight">Benutzername</span>
<input id="input-signup-username" class="form-control" type="name" placeholder="Benutzername" />
</div>
<div class="input-style input-style-2 has-icon input-required">
<i class="input-icon fa fa-envelope color-theme"></i>
<span class="color-highlight">Email</span>
<input id="input-signup-email" class="form-control" type="email" placeholder="Email" />
</div>
<div class="input-style input-style-2 has-icon input-required">
<i class="input-icon fa fa-lock color-theme"></i>
<span class="color-highlight">Passwort</span>
<input id="input-signup-password" class="form-control" type="password" placeholder="Passwort" />
</div>
<a class="btn btn-m mt-2 mb-2 btn-full bg-green2-dark text-uppercase font-900" href="#" onclick="signup();">Registrieren</a>
</div>
</div>
@@ -291,14 +304,17 @@
</div>
</div>
<div id="menu-update">
<div id="menu-nodb-warning" class="menu menu-box-bottom menu-box-detached rounded-m" data-height="500">
<div class="menu-title"><h1>Warnung</h1><p class="color-highlight">Datenbank nicht unterst&uuml;tzt</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 bottom-0">
<p class="text-center mt-5"><i class="fa fa-sync-alt fa-7x color-highlight fa-spin"></i></p>
<h1 class="text-center mt-5 font-900">Update Verfügbar</h1>
<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.
<p>
Das Speichern der ben&ouml;tigten Daten wird von Deinem Ger&auml;t nicht unterst&uuml;tzt.<br>
Da deshalb die Daten jedesmal direkt vom Server geladen werden m&uuml;ssen, kannst Du die App nicht offline nutzen.<br>
Das Nachladen kann au&szlig;erdem gerade bei gro&szlig;en Datenmengen (wie Ranglisten) sehr lange dauern.
Wir empfehlen Dir daher, auf diesem Ger&auml;t unsere normale Website zu benutzen. Diese ist auch f&uuml;r Mobil-Ger&auml;te optimiert.
</p>
<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>
<a class="btn btn-m mt-2 btn-full bg-highlight text-uppercase font-900" href="https://regatten.net/">Zur Website</a>
<a id="menu-nodb-warning-okay" class="btn btn-m mt-2 mb-3 btn-full bg-highlight text-uppercase font-900" href="#">Nicht erneut anzeigen</a>
</div>
</div>

View File

@@ -18,7 +18,7 @@
<link rel="apple-touch-icon" sizes="180x180" href="<?php echo SERVER_ADDR; ?>/client/app/icons/icon-192x192.png">
</head>
<body class="detect-theme" data-background="none" data-highlight="blue2">
<body class="theme-light" data-background="none" data-highlight="blue2"><?php /* DARK MODE DISABLED: set class to "detect-theme" */ ?>
<div id="preloader"><div class="spinner-border color-highlight" role="status"></div></div>
@@ -27,7 +27,8 @@
<?php include(__DIR__ . '/headerfooter.php'); ?>
<!--start of page content, add your stuff here-->
<div class="page-content header-clear-medium">
<div class="page-content header-clear">
<div id="syncstatus" class="text-right mr-2 mb-1">Zuletzt aktualisiert: nie</div>
<?php echo $sp['output']; ?>
</div>
<!--end of page content, off canvas elements here-->

View File

@@ -21,8 +21,8 @@ async function onEditBoatnameClick() {
if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um den Bootsnamen zu bearbeiten');
} else {
console.log('EditBoatname: unbekannter Fehler', status, error);
console.log(xhr);
log('EditBoatname: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
hideLoader();

View File

@@ -23,8 +23,8 @@ function sendMessage() {
if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um eine Nachricht zu versenden');
} else {
console.log('Contact: unbekannter Fehler', status, error);
console.log(xhr);
log('Contact: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
hideLoader();

12
server/scripts/go2url.js Normal file
View File

@@ -0,0 +1,12 @@
var siteScript = function() {
hideLoader();
setTimeout(function() {
var url = findGetParameter('url');
if (url === null) {
$('#card-title').find('p').html('Wir konnten Dich leider nicht umleiten.<br><a href="' + LINK_PRE + 'index">Hier kommst Du zur&uuml;ck zur Startseite</a>');
} else {
showLoader();
location.href = url;
}
}, 2000);
}

View File

@@ -1,8 +1,84 @@
var firstCall = true;
var today;
var onUpdatePushBadge;
var onUnfollowClicked = async function() {
var id = $('#menu-item-unfollow').attr('data-sailor-id');
showLoader();
$('#menu-favorite').hideMenu();
var auth = {
id: localStorage.getItem('auth_id'),
hash: localStorage.getItem('auth_hash')
}
$.ajax({
url: QUERY_URL + 'sailor_unfollow',
method: 'POST',
data: {
auth: auth,
sailor: id
},
error: function (xhr, status, error) {
if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um Deine Favoriten zu bearbeiten.');
} else {
log('Unfollow: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
hideLoader();
},
success: async function (data, status, xhr) {
await sync();
toastOk('Erfolgreich');
hideLoader();
}
});
}
var onFavoriteClicked = async function(id) {
var sailor = await dbGetData('sailors', id);
$('#menu-favorite').find('.menu-title').find('p').text(sailor.name);
$('#menu-item-unfollow').attr('data-sailor-id', sailor.id);
$('#menu-favorite').showMenu();
}
var siteScript = async function() {
today = getToday();
if (firstCall) {
firstCall = false;
$('#button-notifications-activate').click(function(){
$('#menu-pushes').showMenu();
});
$('#a-notifications-later').click(function(){
createCookie('regatten_app_' + BOATCLASS + '_rejected_push', true, 1);
$('#card-notifications').hide();
});
if (readCookie('regatten_app_' + BOATCLASS + '_rejected_push')) {
$('#card-notifications').hide();
} else {
onUpdatePushBadge = function () {
if (!pushesPossible || (Notification.permission == 'denied')) {
$('#card-notifications').hide();
} else {
swRegistration.pushManager.getSubscription().then(function(subscription) {
var isSub = (subscription !== null);
if (isSub) {
$('#card-notifications').hide();
} else {
$('#card-notifications').show();
}
});
}
}
onUpdatePushBadge();
}
$('#menu-item-unfollow').click(onUnfollowClicked);
}
if (isLoggedIn()) {
$('#card-notloggedin').hide();
@@ -18,31 +94,41 @@ var siteScript = async function() {
}
if (watched.length > 0) {
var year = (new Date()).getFullYear();
$('#th-ranking').html('Rangliste ' + year);
var ranking = (await dbGetRanking(parseDate('01.12.' + (year - 1)), parseDate('30.11.' + year), false, false))[0];
tbody = '';
var list = '';
for (i in watched) {
sailor = watched[i];
tbody += '<tr><td>' + sailor.name + '</td><td>';
var club = null;
if (sailor.club != null)
club = await dbGetData('clubs', sailor.club);
var rank = null;
for (r in ranking) {
if (ranking[r].id == sailor.id) {
rank = ranking[r].rank;
rank = ranking[r];
break;
}
}
list += '<div onclick="onFavoriteClicked(' + sailor.id + ');">';
list += '<div>';
// Name
list += '<div><b>' + sailor.name + '</b></div>';
list += '</div><div>';
if (rank == null) {
tbody += '<i>nicht in der Rangliste</i>';
list += '<div>Nicht in der Rangliste</div>';
} else {
tbody += '<b>' + rank + '.</b> Platz';
// Rank
list += '<div>Platz <b>' + rank.rank + '</b></div>';
// rlp
list += '<div>' + rank.rlp.toFixed(3) + ' Punkte</div>';
}
tbody += '</td></tr>';
list += '</div></div>';
}
$('#table-favorites').find('tbody').html(tbody);
$('#div-favorites').html(list);
$('#p-favorites').hide();
$('#table-favorites').show();
$('#div-favorites').show();
} else {
$('#table-favorites').hide();
$('#div-favorites').hide();
$('#p-favorites').show();
}
$('#card-favorites').show();
@@ -50,7 +136,7 @@ var siteScript = async function() {
// Your next
var planningsDB = await dbGetDataIndex('plannings', 'user', user.id);
var minDate = getToday();
minDate.setDate(minDate.getDate() - 1);
minDate.setDate(minDate.getDate());
var maxDate = getToday();
maxDate.setDate(maxDate.getDate() + 28);
var regattas = await dbGetRegattasRange(minDate, maxDate);
@@ -102,6 +188,9 @@ var siteScript = async function() {
list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special
if (regatta.special.substr(0, 1) == '#') {
regatta.special = '* ' + regatta.special.substr(1);
}
list += '<div>' + regatta['special'] + '</div>';
// Icons
@@ -166,7 +255,7 @@ var siteScript = async function() {
// Next
var minDate = getToday();
minDate.setDate(minDate.getDate() - 1);
minDate.setDate(minDate.getDate());
var maxDate = getToday();
maxDate.setDate(maxDate.getDate() + 14);
var regattas = await dbGetRegattasRange(minDate, maxDate);
@@ -201,6 +290,9 @@ var siteScript = async function() {
list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special
if (regatta.special.substr(0, 1) == '#') {
regatta.special = '* ' + regatta.special.substr(1);
}
list += '<div>' + regatta['special'] + '</div>';
// Icons
@@ -273,12 +365,9 @@ var siteScript = async function() {
var maxDate = getToday();
maxDate.setDate(maxDate.getDate() - 1);
var regattas = await dbGetRegattasRange(minDate, maxDate);
var regattaResults = [];
for (id in regattas) {
var entry = regattas[id];
var results = await dbGetDataIndex('results', 'regatta', entry['id']);
regattaResults[entry['id']] = (results.length > 0);
}
regattas.sort(function(a,b){
return b.date.localeCompare(a.date);
});
if (regattas.length > 0) {
list = '';
for (i in regattas) {
@@ -310,6 +399,9 @@ var siteScript = async function() {
list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special
if (regatta.special.substr(0, 1) == '#') {
regatta.special = '* ' + regatta.special.substr(1);
}
list += '<div>' + regatta['special'] + '</div>';
// Icons
@@ -320,7 +412,7 @@ var siteScript = async function() {
icons.push('<i class="fas fa-book"></i>');
if (regatta['canceled'] == '1') {
icons.push('<i class="fas fa-times color-red2-dark"></i>');
} else if (regattaResults[regatta['id']]) {
} else if (regatta['results'] == '1') {
icons.push('<i class="fas fa-poll"></i>');
}
list += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>';

View File

@@ -1,3 +1,9 @@
var firstCall = true;
var rows = [];
var page = 1;
var pageCount = 0;
const showCount = 10;
async function onNewsClicked(id) {
var newsEntry = await dbGetData('news', id);
if (newsEntry == null) return;
@@ -11,33 +17,71 @@ async function onNewsClicked(id) {
$('#menu-news').showMenu();
}
function pageChange() {
$('h1')[0].scrollIntoView({ behavior: "smooth" });
drawList();
}
function addCard(newsEntry) {
var content = '<h2>' + newsEntry.title + '</h2>';
var badge = '';
if (newsEntry.unread) {
badge += '<span class="badge bg-highlight color-white p-1">NEW</span>&ensp;';
}
var content = '<h2>' + badge + 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));
$('#news-entries').append(cardTemplate.replace('%ID%', 'card-news-' + newsEntry.id).replace('%CONTENT%', content));
}
async function drawList() {
$('.card-news').remove();
if (rows.length > 0) {
var offset = (page - 1) * showCount;
var count = (page == pageCount ? (rows.length % showCount) : showCount);
if (count == 0) count = showCount;
for (i = 0; i < count; i ++) {
addCard(rows[i + offset]);
}
}
}
var siteScript = async function() {
$('.card-news').remove();
if (firstCall) {
firstCall = false;
initPagination();
}
rows = [];
var news = await dbGetData('news');
news.sort(function (a,b) {
return b.date.localeCompare(a.date);
});
var newsRead = await dbSettingsGet('news_read_' + BOATCLASS);
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));
newsEntry.date = parseDbTimestamp(newsEntry.date);
if (newsEntry.date > now) continue;
if (newsEntry.date < lastYear) break;
addCard(newsEntry);
newsEntry.unread = (newsEntry.date > newsRead);
rows.push(newsEntry);
}
pageCount = Math.ceil(rows.length / showCount);
if ((page < 1) || (page > pageCount)) {
if (page < 1) {
page = 1;
} else {
page = pageCount;
}
}
drawPagination();
drawList();
dbSettingsSet('news_read_' + BOATCLASS, now);
updateNewsBadge();
hideLoader();

View File

@@ -6,6 +6,20 @@ async function onRegattaClicked(id) {
var dateTo = parseDate(regatta['date']);
dateTo.setDate(dateTo.getDate() + Math.max(parseInt(regatta['length']) - 1, 0));
var specialFields = await dbGetClassProp('special-fields');
if (specialFields === null) specialFields = {};
if (regatta.special.substr(0, 1) == '#') {
regatta.special = regatta.special.substr(1);
if (typeof specialFields[regatta.special] !== 'undefined') {
$('#menu-item-special').text(specialFields[regatta.special]);
} else {
$('#menu-item-special').text('ERROR');
}
$('#menu-item-special').show();
} else {
$('#menu-item-special').hide();
}
var plannings = await dbGetDataIndex('plannings', 'regatta', regatta['id']);
var planning = null;
if (isLoggedIn()) {
@@ -32,11 +46,26 @@ async function onRegattaClicked(id) {
crew.push(sailor.name);
}
}
var status = '';
if (planning.gemeldet == '1') status = 'gemeldet';
if (planning.bezahlt == '1') {
if (status != '') status += ' und ';
status += 'bezahlt';
}
if (status != '') crew.push('<font style="font-style:italic;">' + status + '</font>');
$('#menu-item-yourplanning').html(crew.join('<br>'));
} else {
$('#menu-item-yourplanning').hide();
}
// Planning: Edit Status
if ((planning != null) && (typeof planningEditStatus === 'function')) {
$('#menu-item-status').show();
$('#menu-item-status').attr('onclick', 'planningEditStatus(' + regatta['id'] + ')');
} else {
$('#menu-item-status').hide();
}
// Planning
if ((plannings.length > 0) && (dateTo >= today)) {
$('#menu-item-plannings').show();
@@ -46,8 +75,7 @@ async function onRegattaClicked(id) {
}
// Results
var results = await dbGetDataIndex('results', 'regatta', regatta['id']);
if (results.length > 0) {
if (regatta['results'] == '1') {
$('#menu-item-results').show();
$('#menu-item-results').attr('href', LINK_PRE + 'result?regatta=' + regatta['id']);
} else {

310
server/scripts/planning.js Normal file
View File

@@ -0,0 +1,310 @@
async function planningSwitchChanged() {
showLoader();
var id = $('#switch-status-gemeldet').data('regatta');
var gemeldet = $('#switch-status-gemeldet').prop('checked');
var bezahlt = $('#switch-status-bezahlt').prop('checked');
var auth = {
id: localStorage.getItem('auth_id'),
hash: localStorage.getItem('auth_hash')
}
$.ajax({
url: QUERY_URL + 'planning_set_state',
method: 'POST',
data: {
auth: auth,
regatta: id,
gemeldet: gemeldet,
bezahlt: bezahlt
},
error: function (xhr, status, error) {
if (xhr.status == 401) {
log('authentification failed');
toastError('Authentifizierung fehlgeschlagen. Versuche es erneut.');
} else if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um den Status zu &auml;ndern');
} else {
log('Login: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
$('#menu-status').hideMenu();
hideLoader();
},
success: function (data, status, xhr) {
sync();
hideLoader();
}
});
}
async function planningEditStatus(id) {
$('#menu-regatta').hideMenu();
var regatta = await dbGetData('regattas', id);
$('#menu-status').find('.menu-title').find('p').text(regatta.name);
var plannings = await dbGetDataIndex('plannings', 'regatta', regatta['id']);
var planning = null;
if (isLoggedIn()) {
for (i in plannings) {
if (plannings[i]['user'] == USER_ID) {
planning = plannings[i];
break;
}
}
}
if (planning !== null) {
$('#switch-status-gemeldet').data('regatta', id);
$('#switch-status-gemeldet').prop('checked', planning.gemeldet == '1');
$('#switch-status-bezahlt').prop('checked', planning.bezahlt == '1');
$('#menu-status').showMenu();
}
}
function selectChange() {
var val = $('#select-year').val();
if (typeof siteScript === 'function') {
history.replaceState(null, '', '?year=' + val);
showLoader();
siteScript();
}
}
function initYear() {
var year = findGetParameter('year');
if (year === null) year = new Date().getFullYear();
$('#select-year').html('<option value="' + year + '">' + year + '</option>');
$('#select-year').val(year);
}
var firstCall = true;
var rows = [];
var today;
async function drawList () {
window.setTimeout(function () {
var list = '';
rows.forEach(function (entry) {
if (entry == null) {
list += '<div><div align="center" class="color-highlight"><b>Heute ist der ' + formatDate('d.m.Y', today) + '</b></div></div>';
} else if (search($('#input-search').val(), entry.keywords)) {
list += entry.content;
}
});
$('#div-regattas').html(list);
}, 0);
}
var siteScript = async function() {
if (!isLoggedIn()) {
hideLoader();
return;
}
if (firstCall) {
firstCall = false;
initYear();
$('#select-year').change(selectChange);
$('#input-search').on('input', drawList);
$('#switch-status-gemeldet').parent().parent().click(planningSwitchChanged);
$('#switch-status-bezahlt').parent().parent().click(planningSwitchChanged);
}
$('#a-share-planning').attr('href', LINK_PRE + 'planning_view?user=' + USER_ID);
today = getToday();
var selectedYear = $('#select-year').val();
var minDate = parseDate(selectedYear + '-01-01');
var maxDate = parseDate(selectedYear + '-12-31');
var regattas = await dbGetRegattasRange(minDate, maxDate);
var plannings = await dbGetDataIndex('plannings', 'user', USER_ID);
for (var i = regattas.length - 1; i >= 0; i --) {
var entry = regattas[i];
var okay = false;
for (p in plannings) {
if (plannings[p].regatta == entry.id) {
regattas[i].planning = plannings[p];
okay = true;
break;
}
}
if (!okay) {
regattas.splice(i, 1);
}
}
var years = await dbGetData('years');
years.sort(function (a, b) {
if (a['year'] > b['year']) return -1;
if (a['year'] < b['year']) return 1;
return 0;
});
var options = '';
for (id in years) {
var year = years[id]['year'];
options += '<option value="' + year + '">' + year + '</option>';
}
$('#select-year').html(options);
$('#select-year').val(selectedYear);
var count = regattas.length;
if (count > 0) {
if (count == 1) {
$('#p-count').html('Es wurde 1 Regatta gefunden!');
} else {
$('#p-count').html('Es wurden ' + count + ' Regatten gefunden!');
}
$('#div-regattas').show();
$('#input-search').parent().show();
var heute = false;
rows = [];
for (id in regattas) {
var entry = regattas[id];
var club = null;
if (entry['club'] != null)
club = await dbGetData('clubs', entry['club']);
if (entry.planning.steuermann !== null) {
entry.planning.steuermann = (await dbGetData('sailors', entry.planning.steuermann)).name;
}
var crewString = entry.planning.crew.split(',');
entry.planning.crew = [];
for (c in crewString) {
var sailor = await dbGetData('sailors', crewString[c]);
if (sailor !== null) {
entry.planning.crew.push(sailor.name);
}
}
var dateFrom = entry['dateFrom'];
var dateTo = entry['dateTo'];
var row = { keywords: [], content: '' };
row.keywords.push(entry['name']);
if (entry['number'] != null) row.keywords.push(entry['number']);
if (club != null) row.keywords.push(club['kurz'], club['name']);
if (entry.planning.steuermann != null) row.keywords.push(entry.planning.steuermann);
for (c in entry.planning.crew) row.keywords.push(entry.planning.crew[c]);
if (!heute && (today <= dateFrom)) {
rows.push(null);
heute = true;
}
row.content += '<div onclick="onRegattaClicked(' + entry['id'] + ');">';
// ZEILE 1
// Name
row.content += '<div><b>' + (entry['canceled'] == 1 ? '<s>' : '') + entry['name'] + (entry['canceled'] == 1 ? '</s>' : '') + '</b></div>';
// ZEILE 2
row.content += '<div>';
// Number
row.content += '<div>' + ((entry['number'] != null) ? ('# ' + entry['number']) : '') + '</div>';
// Club
row.content += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special
if (entry.special.substr(0, 1) == '#') {
entry.special = '* ' + entry.special.substr(1);
}
row.content += '<div>' + entry['special'] + '</div>';
// Icons
var icons = [];
if ((entry['meldung'] != '') && (dateTo >= today) && (entry['meldungOffen'] == '1') && (entry.planning.gemeldet != '1')) {
var color = '';
var planning = null;
if (isLoggedIn()) {
var plannings = await dbGetDataIndex('plannings', 'regatta', entry['id']);
for (id in plannings) {
if (plannings[id]['user'] == USER_ID) {
planning = plannings[id];
break;
}
}
}
if (entry['meldungSchluss'] != null) {
if ((planning == null) || (planning['gemeldet'] == '0')) {
var ms = 0;
if (entry['meldungEarly'] != null) {
ms = parseDate(entry['meldungEarly']);
}
if (ms < today) {
ms = parseDate(entry['meldungSchluss']);
}
var diff = Math.round((ms - today) / 86400000);
if (ms < today) {
color = ' color-red2-dark';
} else if (diff < 7) {
color = ' color-yellow2-dark';
}
}
}
if ((planning != null) && (planning['gemeldet'] == '0')) {
color += ' fa-blink';
}
icons.push('<i class="fas fa-file-signature' + color + '"></i>');
}
if (entry['bericht'] != '')
icons.push('<i class="fas fa-book"></i>');
if (entry['canceled'] == '1') {
icons.push('<i class="fas fa-times color-red2-dark"></i>');
} else if (entry['results'] == '1') {
icons.push('<i class="fas fa-poll"></i>');
}
if (entry.planning.gemeldet == '1') {
icons.push('<i class="fas fa-file-signature color-highlight"></i>');
}
if (entry.planning.bezahlt == '1') {
icons.push('<i class="fas fa-euro-sign color-highlight"></i>');
}
row.content += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>';
row.content += '</div>';
// ZEILE 3
row.content += '<div>';
// Date
if (entry['length'] < 1) {
if (formatDate('d.m', dateFrom) == '01.01') {
row.content += '<div><font class="color-red2-dark">Datum noch unklar</font></div>';
} else {
row.content += '<div>' + formatDate("d.m.Y", dateFrom) + ' - <font class="color-red2-dark">Datum nicht final</font></div>';
}
} else {
row.content += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>';
}
// RLF
row.content += '<div>' + parseFloat(entry['rlf']).toFixed(2) + '</div>';
row.content += '</div></div>';
rows.push(row);
}
if (!heute) {
rows.push(null);
}
drawList();
} else {
$('#p-count').html('Du hast noch keine Regatten in Deiner Saison-Planung!');
$('#div-regattas').hide();
$('#input-search').parent().hide();
}
hideLoader();
}

View File

@@ -0,0 +1,477 @@
async function planningSwitchChanged() {
showLoader();
var id = $('#switch-planning-include').data('regatta');
var include = $('#switch-planning-include').prop('checked');
var auth = {
id: localStorage.getItem('auth_id'),
hash: localStorage.getItem('auth_hash')
}
if (include) {
// add to planning
$.ajax({
url: QUERY_URL + 'planning_add',
method: 'POST',
data: {
auth: auth,
regatta: id
},
error: function (xhr, status, error) {
if (xhr.status == 401) {
log('authentification failed');
toastError('Authentifizierung fehlgeschlagen. Versuche es erneut.');
} else if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um die &Auml;nderungen zu speichern');
} else {
log('planning_add: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
$('#menu-edit').hideMenu();
hideLoader();
},
success: async function (data, status, xhr) {
await sync();
planningEdit(id);
hideLoader();
}
});
} else {
// remove from planning
$.ajax({
url: QUERY_URL + 'planning_remove',
method: 'POST',
data: {
auth: auth,
regatta: id
},
error: function (xhr, status, error) {
if (xhr.status == 401) {
log('authentification failed');
toastError('Authentifizierung fehlgeschlagen. Versuche es erneut.');
} else if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um die &Auml;nderungen zu speichern');
} else {
log('planning_remove: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
$('#menu-edit').hideMenu();
hideLoader();
},
success: async function (data, status, xhr) {
await sync();
planningEdit(id);
hideLoader();
}
});
}
}
var sailorIsSteuermann;
var sailors = [];
async function sailorSelected(sid) {
$('#menu-sailor').hideMenu();
showLoader();
var rid = $('#switch-planning-include').data('regatta');
var action = (sailorIsSteuermann ? 'planning_set_steuermann' : 'planning_add_crew');
// add sailor
var auth = {
id: localStorage.getItem('auth_id'),
hash: localStorage.getItem('auth_hash')
}
$.ajax({
url: QUERY_URL + action,
method: 'POST',
data: {
auth: auth,
regatta: rid,
sailor: sid
},
error: function (xhr, status, error) {
if (xhr.status == 401) {
log('authentification failed');
toastError('Authentifizierung fehlgeschlagen. Versuche es erneut.');
} else if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um die &Auml;nderungen zu speichern');
} else {
log(action + ': unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
hideLoader();
},
success: async function (data, status, xhr) {
await sync();
planningEdit(rid);
hideLoader();
}
});
}
async function sailorsSearch() {
$('.item-sailor-search').remove();
if (sailorIsSteuermann) {
var item = '<a class="item-sailor-search" onclick="sailorSelected(null)">';
item += '<span style="font-style:italic;">noch unklar</span>';
item += '<i class="fa fa-angle-right"></i>';
item += '</a>';
$('#menu-sailor').find('.content').find('.list-group').append(item);
}
if ($('#input-edit-search').val().length >= 3) {
sailors.forEach(function (entry) {
if (search($('#input-edit-search').val(), entry.keywords)) {
$('#menu-sailor').find('.content').find('.list-group').append(entry.content);
}
});
} else {
var item = '<p class="item-sailor-search">Gib mindestens 3 Zeichen ein</p>';
$('#menu-sailor').find('.content').find('.list-group').append(item);
}
}
async function initSailors() {
sailors = [];
var dbSailors = await dbGetData('sailors');
dbSailors.sort(function(a,b){
return a.name.localeCompare(b.name);
});
for (s in dbSailors) {
var item = '<a class="item-sailor-search" onclick="sailorSelected(' + dbSailors[s].id + ')">';
item += '<span>' + dbSailors[s].name + '</span>';
item += '<i class="fa fa-angle-right"></i>';
item += '</a>';
sailors.push({
keywords: [dbSailors[s].name],
content: item
});
}
}
async function planningChangeCrew(sid = null) {
if (sid !== null) {
showLoader();
var rid = $('#switch-planning-include').data('regatta');
// remove sailor
var auth = {
id: localStorage.getItem('auth_id'),
hash: localStorage.getItem('auth_hash')
}
$.ajax({
url: QUERY_URL + 'planning_remove_crew',
method: 'POST',
data: {
auth: auth,
regatta: rid,
sailor: sid
},
error: function (xhr, status, error) {
if (xhr.status == 401) {
log('authentification failed');
toastError('Authentifizierung fehlgeschlagen. Versuche es erneut.');
} else if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um die &Auml;nderungen zu speichern');
} else {
log('planning_remove_crew: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
$('#menu-edit').hideMenu();
hideLoader();
},
success: async function (data, status, xhr) {
await sync();
planningEdit(rid);
hideLoader();
}
});
} else {
sailorIsSteuermann = false;
$('#input-edit-search').val('').trigger('focusin').trigger('focusout');
sailorsSearch();
$('#menu-edit').hideMenu();
$('#menu-sailor').find('.menu-title').find('h1').text('Crew hinzufügen');
$('#menu-sailor').showMenu();
$('#input-edit-search').focus();
}
}
async function planningChangeSteuermann() {
sailorIsSteuermann = true;
$('#input-edit-search').val('').trigger('focusin').trigger('focusout');
sailorsSearch();
$('#menu-edit').hideMenu();
$('#menu-sailor').find('.menu-title').find('h1').text('Steuermann/-frau bearbeiten');
$('#menu-sailor').showMenu();
$('#input-edit-search').focus();
}
async function planningEdit(id) {
var regatta = await dbGetData('regattas', id);
$('#menu-edit').find('.menu-title').find('p').text(regatta.name);
var plannings = await dbGetDataIndex('plannings', 'regatta', regatta['id']);
var planning = null;
if (isLoggedIn()) {
for (i in plannings) {
if (plannings[i]['user'] == USER_ID) {
planning = plannings[i];
break;
}
}
}
$('#switch-planning-include').data('regatta', id);
if (planning !== null) {
$('#switch-planning-include').prop('checked', true);
$('#item-steuermann').show();
if (planning.steuermann !== null) {
$('#item-steuermann').find('span').text('Am Steuer: ' + (await dbGetData('sailors', planning.steuermann)).name);
} else {
$('#item-steuermann').find('span').html('Am Steuer: <font style="font-style:italic;">noch unklar</font>');
}
$('.item-crew').remove();
var crew = planning.crew.split(',');
for (c in crew) {
var sailor = await dbGetData('sailors', crew[c]);
if (sailor !== null) {
var item = '<a class="item-crew" onclick="planningChangeCrew(' + sailor.id + ')">';
item += '<span>' + sailor.name + '</span>';
item += '<i class="fa fa-angle-right"></i>';
item += '</a>';
$('#menu-edit').find('.content').find('.list-group').append(item);
}
}
var item = '<a class="item-crew" onclick="planningChangeCrew()">';
item += '<span style="font-style:italic;">Weiteren Segler hinzuf&uuml;gen</span>';
item += '<i class="fa fa-angle-right"></i>';
item += '</a>';
$('#menu-edit').find('.content').find('.list-group').append(item);
} else {
$('#switch-planning-include').prop('checked', false);
$('#item-steuermann').hide();
$('.item-crew').remove();
}
$('#menu-edit').showMenu();
}
function selectChange() {
var val = $('#select-year').val();
if (typeof siteScript === 'function') {
history.replaceState(null, '', '?year=' + val);
showLoader();
siteScript();
}
}
function initYear() {
var year = findGetParameter('year');
if (year === null) year = new Date().getFullYear();
$('#select-year').html('<option value="' + year + '">' + year + '</option>');
$('#select-year').val(year);
}
var firstCall = true;
var rows = [];
var today;
async function drawList () {
window.setTimeout(function () {
var list = '';
rows.forEach(function (entry) {
if (entry == null) {
list += '<div><div align="center" class="color-highlight"><b>Heute ist der ' + formatDate('d.m.Y', today) + '</b></div></div>';
} else if (search($('#input-search').val(), entry.keywords)) {
list += entry.content;
}
});
$('#div-regattas').html(list);
}, 0);
}
var siteScript = async function() {
if (!isLoggedIn()) {
location.href = LINK_PRE + 'planning';
return;
}
if (firstCall) {
firstCall = false;
initYear();
$('#select-year').change(selectChange);
$('#input-search').on('input', drawList);
$('#switch-planning-include').parent().parent().click(planningSwitchChanged);
$('#item-steuermann').click(planningChangeSteuermann);
$('#input-edit-search').on('input', sailorsSearch);
initSailors();
}
today = getToday();
var selectedYear = $('#select-year').val();
var minDate = parseDate(selectedYear + '-01-01');
var maxDate = parseDate(selectedYear + '-12-31');
var regattas = await dbGetRegattasRange(minDate, maxDate);
var plannings = await dbGetDataIndex('plannings', 'user', USER_ID);
for (var i = regattas.length - 1; i >= 0; i --) {
var entry = regattas[i];
var okay = false;
for (p in plannings) {
if (plannings[p].regatta == entry.id) {
regattas[i].planning = plannings[p];
okay = true;
break;
}
}
if (!okay) {
regattas[i].planning = null;
}
}
var years = await dbGetData('years');
years.sort(function (a, b) {
if (a['year'] > b['year']) return -1;
if (a['year'] < b['year']) return 1;
return 0;
});
var options = '';
for (id in years) {
var year = years[id]['year'];
options += '<option value="' + year + '">' + year + '</option>';
}
$('#select-year').html(options);
$('#select-year').val(selectedYear);
var count = regattas.length;
if (count > 0) {
if (count == 1) {
$('#p-count').html('Es wurde 1 Regatta gefunden!');
} else {
$('#p-count').html('Es wurden ' + count + ' Regatten gefunden!');
}
$('#div-regattas').show();
$('#input-search').parent().show();
var heute = false;
rows = [];
for (id in regattas) {
var entry = regattas[id];
var club = null;
if (entry['club'] != null)
club = await dbGetData('clubs', entry['club']);
if (entry.planning !== null) {
if (entry.planning.steuermann !== null) {
entry.planning.steuermann = (await dbGetData('sailors', entry.planning.steuermann)).name;
}
var crewString = entry.planning.crew.split(',');
entry.planning.crew = [];
for (c in crewString) {
var sailor = await dbGetData('sailors', crewString[c]);
if (sailor !== null) {
entry.planning.crew.push(sailor.name);
}
}
}
var dateFrom = entry['dateFrom'];
var dateTo = entry['dateTo'];
var row = { keywords: [], content: '' };
row.keywords.push(entry['name']);
if (entry['number'] != null) row.keywords.push(entry['number']);
if (club != null) row.keywords.push(club['kurz'], club['name']);
if (!heute && (today <= dateFrom)) {
rows.push(null);
heute = true;
}
if (entry.planning !== null) {
row.content += '<div onclick="planningEdit(' + entry['id'] + ');">';
} else {
row.content += '<div onclick="planningEdit(' + entry['id'] + ');" style="opacity:0.5;">';
}
// ZEILE 1
// Name
row.content += '<div><b>' + (entry['canceled'] == 1 ? '<s>' : '') + entry['name'] + (entry['canceled'] == 1 ? '</s>' : '') + '</b></div>';
// ZEILE 2
row.content += '<div>';
// Number
row.content += '<div>' + ((entry['number'] != null) ? ('# ' + entry['number']) : '') + '</div>';
// Special
if (entry.special.substr(0, 1) == '#') {
entry.special = '* ' + entry.special.substr(1);
}
row.content += '<div>' + entry['special'] + '</div>';
// Club
row.content += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
row.content += '</div>';
// ZEILE 3
row.content += '<div>';
// Date
if (entry['length'] < 1) {
if (formatDate('d.m', dateFrom) == '01.01') {
row.content += '<div><font class="color-red2-dark">Datum noch unklar</font></div>';
} else {
row.content += '<div>' + formatDate("d.m.Y", dateFrom) + ' - <font class="color-red2-dark">Datum nicht final</font></div>';
}
} else {
row.content += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>';
}
// RLF
row.content += '<div>' + parseFloat(entry['rlf']).toFixed(2) + '</div>';
row.content += '</div>';
if (entry.planning !== null) {
// ZEILE 4
row.content += '<div></div>';
// ZEILE 5
row.content += '<div>';
row.content += '<div>' + (entry.planning.steuermann !== null ? entry.planning.steuermann : 'noch unklar') + '</div>';
row.content += '</div>';
// ZEILE 6...
for (var i in entry.planning.crew) {
row.content += '<div>';
row.content += '<div>' + entry.planning.crew[i] + '</div>';
row.content += '</div>';
}
} else {
row.content += '<div>Du planst nicht, hierhin zu fahren</div>';
}
row.content += '</div>';
rows.push(row);
}
if (!heute) {
rows.push(null);
}
drawList();
} else {
$('#p-count').html('Keine Regatten gefunden!');
$('#div-regattas').hide();
$('#input-search').parent().hide();
}
hideLoader();
}

View File

@@ -0,0 +1,147 @@
async function onUserClicked(id) {
var user = await dbGetData('users', id);
if (user !== null) {
location.href = LINK_PRE + 'planning_view?user=' + user.id;
}
}
function selectChange() {
var val = $('#select-year').val();
if (typeof siteScript === 'function') {
history.replaceState(null, '', '?year=' + val);
showLoader();
siteScript();
}
}
function initYear() {
var year = findGetParameter('year');
if (year === null) year = new Date().getFullYear();
$('#select-year').html('<option value="' + year + '">' + year + '</option>');
$('#select-year').val(year);
}
var firstCall = true;
var rows = [];
var today;
async function drawList () {
window.setTimeout(function () {
var list = '';
rows.forEach(function (entry) {
if (search($('#input-search').val(), entry.keywords)) {
list += entry.content;
}
});
$('#div-users').html(list);
}, 0);
}
var siteScript = async function() {
if (!isLoggedIn()) {
hideLoader();
return;
}
if (firstCall) {
firstCall = false;
initYear();
$('#select-year').change(selectChange);
$('#input-search').on('input', drawList);
}
var selectedYear = $('#select-year').val();
var minDate = parseDate(selectedYear + '-01-01');
var maxDate = parseDate(selectedYear + '-12-31');
var regattas = await dbGetRegattasRange(minDate, maxDate);
var plannings = {};
for (var i in regattas) {
var entry = regattas[i];
var planning = await dbGetDataIndex('plannings', 'regatta', entry.id);
for (p in planning) {
if (!(planning[p].user in plannings)) {
plannings[planning[p].user] = {
user: await dbGetData('users', planning[p].user),
regattas: [],
sailors: {}
};
}
plannings[planning[p].user].regattas.push(entry);
var sailor = null;
if (planning[p].steuermann !== null) sailor = await dbGetData('sailors', planning[p].steuermann);
if (sailor !== null) {
if (!(sailor.id in plannings[planning[p].user].sailors)) plannings[planning[p].user].sailors[sailor.id] = sailor.name;
}
var crew = planning[p].crew.split(',');
for (i in crew) {
sailor = await dbGetData('sailors', crew[i]);
if (sailor !== null) {
if (!(sailor.id in plannings[planning[p].user].sailors)) plannings[planning[p].user].sailors[sailor.id] = sailor.name;
}
}
}
}
plannings = Object.values(plannings);
plannings.sort(function(a,b){
return a.user.username.localeCompare(b.user.username);
});
var years = await dbGetData('years');
years.sort(function (a, b) {
if (a['year'] > b['year']) return -1;
if (a['year'] < b['year']) return 1;
return 0;
});
var options = '';
for (id in years) {
var year = years[id]['year'];
options += '<option value="' + year + '">' + year + '</option>';
}
$('#select-year').html(options);
$('#select-year').val(selectedYear);
var count = plannings.length;
if (count > 0) {
$('#input-search').parent().show();
rows = [];
for (id in plannings) {
var entry = plannings[id];
var row = { keywords: [], content: '' };
row.keywords.push(entry.user.username);
for (i in entry.sailors) {
row.keywords.push(entry.sailors[i]);
}
row.content += '<div onclick="onUserClicked(' + entry.user.id + ');">';
// ZEILE 1
row.content += '<div></div>';
// ZEILE 2
row.content += '<div>';
// Name
row.content += '<div>' + entry.user.username + '</div>';
// Count of regattas
row.content += '<div>' + entry.regattas.length + ' Regatten</div>';
row.content += '</div></div>';
rows.push(row);
}
drawList();
} else {
$('#div-users').html('Es hat noch niemand eine Saison-Planung erstellt');
$('#input-search').parent().hide();
}
hideLoader();
}

View File

@@ -0,0 +1,223 @@
function selectChange() {
var val = $('#select-year').val();
if (typeof siteScript === 'function') {
history.replaceState(null, '', '?year=' + val);
showLoader();
siteScript();
}
}
function initYear() {
var year = findGetParameter('year');
if (year === null) year = new Date().getFullYear();
$('#select-year').html('<option value="' + year + '">' + year + '</option>');
$('#select-year').val(year);
}
var firstCall = true;
var rows = [];
var today;
async function drawList () {
window.setTimeout(function () {
var list = '';
rows.forEach(function (entry) {
if (entry == null) {
list += '<div><div align="center" class="color-highlight"><b>Heute ist der ' + formatDate('d.m.Y', today) + '</b></div></div>';
} else if (search($('#input-search').val(), entry.keywords)) {
list += entry.content;
}
});
$('#div-regattas').html(list);
}, 0);
}
var siteScript = async function() {
var userid = findGetParameter('user');
var user = null;
if (userid !== null) {
user = await dbGetData('users', userid);
}
if (user === null) {
location.href = LINK_PRE + 'planning_list';
return;
}
$('#p-username').text(user.username);
if (isLoggedIn() && (userid == USER_ID)) {
$('#button-share').show();
$('#button-share').click(function(){
$('#menu-share').showMenu();
});
} else {
$('#button-share').hide();
}
if (firstCall) {
firstCall = false;
initYear();
$('#select-year').change(selectChange);
$('#input-search').on('input', drawList);
}
today = getToday();
var selectedYear = $('#select-year').val();
var minDate = parseDate(selectedYear + '-01-01');
var maxDate = parseDate(selectedYear + '-12-31');
var regattas = await dbGetRegattasRange(minDate, maxDate);
var plannings = await dbGetDataIndex('plannings', 'user', user.id);
for (var i = regattas.length - 1; i >= 0; i --) {
var entry = regattas[i];
var okay = false;
for (p in plannings) {
if (plannings[p].regatta == entry.id) {
regattas[i].planning = plannings[p];
okay = true;
break;
}
}
if (!okay) {
regattas.splice(i, 1);
}
}
var years = await dbGetData('years');
years.sort(function (a, b) {
if (a['year'] > b['year']) return -1;
if (a['year'] < b['year']) return 1;
return 0;
});
var options = '';
for (id in years) {
var year = years[id]['year'];
options += '<option value="' + year + '">' + year + '</option>';
}
$('#select-year').html(options);
$('#select-year').val(selectedYear);
var count = regattas.length;
if (count > 0) {
if (count == 1) {
$('#p-count').html('Es wurde 1 Regatta gefunden!');
} else {
$('#p-count').html('Es wurden ' + count + ' Regatten gefunden!');
}
$('#div-regattas').show();
$('#input-search').parent().show();
var heute = false;
rows = [];
for (id in regattas) {
var entry = regattas[id];
var club = null;
if (entry['club'] != null)
club = await dbGetData('clubs', entry['club']);
if (entry.planning.steuermann !== null) {
entry.planning.steuermann = (await dbGetData('sailors', entry.planning.steuermann)).name;
}
var crewString = entry.planning.crew.split(',');
entry.planning.crew = [];
for (c in crewString) {
var sailor = await dbGetData('sailors', crewString[c]);
if (sailor !== null) {
entry.planning.crew.push(sailor.name);
}
}
var dateFrom = entry['dateFrom'];
var dateTo = entry['dateTo'];
var row = { keywords: [], content: '' };
row.keywords.push(entry['name']);
if (entry['number'] != null) row.keywords.push(entry['number']);
if (club != null) row.keywords.push(club['kurz'], club['name']);
if (entry.planning.steuermann != null) row.keywords.push(entry.planning.steuermann);
for (c in entry.planning.crew) row.keywords.push(entry.planning.crew[c]);
if (!heute && (today <= dateFrom)) {
rows.push(null);
heute = true;
}
row.content += '<div onclick="onRegattaClicked(' + entry['id'] + ');">';
// ZEILE 1
// Name
row.content += '<div><b>' + (entry['canceled'] == 1 ? '<s>' : '') + entry['name'] + (entry['canceled'] == 1 ? '</s>' : '') + '</b></div>';
// ZEILE 2
row.content += '<div>';
// Number
row.content += '<div>' + ((entry['number'] != null) ? ('# ' + entry['number']) : '') + '</div>';
// Special
if (entry.special.substr(0, 1) == '#') {
entry.special = '* ' + entry.special.substr(1);
}
row.content += '<div>' + entry['special'] + '</div>';
// Club
row.content += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
row.content += '</div>';
// ZEILE 3
row.content += '<div>';
// Date
if (entry['length'] < 1) {
if (formatDate('d.m', dateFrom) == '01.01') {
row.content += '<div><font class="color-red2-dark">Datum noch unklar</font></div>';
} else {
row.content += '<div>' + formatDate("d.m.Y", dateFrom) + ' - <font class="color-red2-dark">Datum nicht final</font></div>';
}
} else {
row.content += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>';
}
// RLF
row.content += '<div>' + parseFloat(entry['rlf']).toFixed(2) + '</div>';
row.content += '</div>';
// ZEILE 4
row.content += '<div></div>';
// ZEILE 5
row.content += '<div>';
row.content += '<div>' + (entry.planning.steuermann !== null ? entry.planning.steuermann : 'noch unklar') + '</div>';
row.content += '</div>';
// ZEILE 6...
for (var i in entry.planning.crew) {
row.content += '<div>';
row.content += '<div>' + entry.planning.crew[i] + '</div>';
row.content += '</div>';
}
row.content += '</div>';
rows.push(row);
}
if (!heute) {
rows.push(null);
}
drawList();
} else {
$('#p-count').html(user.username + ' hat noch keine Regatten in seiner/ihrer Saison-Planung!');
$('#div-regattas').hide();
$('#input-search').parent().hide();
}
hideLoader();
}

View File

@@ -137,6 +137,7 @@ async function selectChange(callSiteScript = true) {
jugend = jugstrict = true;
break;
case 'idjm':
var youthGermanName = await dbGetClassProp('youth-german-name');
var beginn = null;
var regattas = await dbGetData('regattas');
regattas.sort(function(a,b){ return b.date.localeCompare(a.date); });
@@ -146,7 +147,7 @@ async function selectChange(callSiteScript = true) {
if ((date < parseDate('01.01.' + year)) || (date > parseDate('31.12.' + year))) {
continue;
}
if (regatta.name.indexOf(YOUTH_GERMAN_NAME) >= 0) {
if (regatta.name.indexOf(youthGermanName) >= 0) {
beginn = ((regatta.meldungSchluss != null) ? parseDate(regatta.meldungSchluss) : date);
break;
}
@@ -162,7 +163,7 @@ async function selectChange(callSiteScript = true) {
jugend = true;
jugstrict = false;
} else {
$('#div-rank').html('Keine ' + YOUTH_GERMAN_NAME + ' gefunden!');
$('#div-rank').html('Keine ' + youthGermanName + ' gefunden!');
$('#input-search').parent().hide();
return;
}
@@ -175,7 +176,8 @@ async function selectChange(callSiteScript = true) {
$('#input-jugstrict').prop('checked', jugstrict);
if (callSiteScript && (typeof siteScript === 'function')) {
history.replaceState(null, '', '?type=' + type + '&year=' + year)
history.replaceState(null, '', '?type=' + type + '&year=' + year);
showLoader();
siteScript();
}
}
@@ -187,6 +189,7 @@ function buttonShowPressed() {
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)
showLoader();
siteScript();
}
}

View File

@@ -14,6 +14,7 @@ function selectChange(callSiteScript = true) {
if (callSiteScript && (typeof siteScript === 'function')) {
history.replaceState(null, '', '?year=' + val);
showLoader();
siteScript();
}
}
@@ -21,7 +22,8 @@ function selectChange(callSiteScript = true) {
function buttonShowPressed() {
if (typeof siteScript === 'function') {
history.replaceState(null, '', '?year=user&from=' + $('#input-from').val() + "&to=" + $('#input-to').val())
history.replaceState(null, '', '?year=user&from=' + $('#input-from').val() + "&to=" + $('#input-to').val());
showLoader();
siteScript();
}
}
@@ -77,12 +79,6 @@ var siteScript = async function() {
var minDate = parseDate($('#input-from').val());
var maxDate = parseDate($('#input-to').val());
var regattas = await dbGetRegattasRange(minDate, maxDate);
var regattaResults = [];
for (id in regattas) {
var entry = regattas[id];
var results = await dbGetDataIndex('results', 'regatta', entry['id']);
regattaResults[entry['id']] = (results.length > 0);
}
var selectedYear = $('#select-year').val();
@@ -113,6 +109,9 @@ var siteScript = async function() {
var heute = false;
rows = [];
var specialFields = await dbGetClassProp('special-fields');
if (specialFields === null) specialFields = {};
var specialShown = {};
for (id in regattas) {
var entry = regattas[id];
@@ -150,7 +149,16 @@ var siteScript = async function() {
row.content += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special
row.content += '<div>' + entry['special'] + '</div>';
if (entry.special.substr(0, 1) == '#') {
entry.special = entry.special.substr(1);
if (typeof specialFields[entry.special] !== 'undefined') {
specialShown[entry.special] = specialFields[entry.special];
entry.special = '* ' + entry.special;
} else {
entry.special = 'ERROR';
}
}
row.content += '<div>' + entry.special + '</div>';
// Icons
var icons = [];
@@ -194,7 +202,7 @@ var siteScript = async function() {
icons.push('<i class="fas fa-book"></i>');
if (entry['canceled'] == '1') {
icons.push('<i class="fas fa-times color-red2-dark"></i>');
} else if (regattaResults[entry['id']]) {
} else if (entry['results'] == '1') {
icons.push('<i class="fas fa-poll"></i>');
}
row.content += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>';
@@ -227,12 +235,24 @@ var siteScript = async function() {
rows.push(null);
}
if (Object.keys(specialShown).length > 0) {
var specialText = '';
for (key in specialShown) {
specialText += '* ' + key + ': ' + specialShown[key] + '<br>';
}
$('#card-special').find('p').html(specialText);
$('#card-special').show();
} else {
$('#card-special').hide();
}
drawList();
} else {
$('#p-count').html('Keine Regatten gefunden!');
$('#div-regattas').hide();
$('#input-search').parent().hide();
$('#card-special').hide();
}
hideLoader();

View File

@@ -4,6 +4,40 @@ var displayed = [];
var page = 1;
var pageCount = 0;
const showCount = 25;
var followedSailors = [];
async function onFollowChange() {
var id = $('#menu-item-follow').attr('data-sailor-id');
showLoader();
$('#menu-sailor').hideMenu();
var auth = {
id: localStorage.getItem('auth_id'),
hash: localStorage.getItem('auth_hash')
}
$.ajax({
url: QUERY_URL + ($('#menu-item-follow').prop('checked') ? 'sailor_follow' : 'sailor_unfollow'),
method: 'POST',
data: {
auth: auth,
sailor: id
},
error: function (xhr, status, error) {
if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um Deine Favoriten zu bearbeiten.');
} else {
log('Un/Follow: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
hideLoader();
},
success: async function (data, status, xhr) {
await sync();
toastOk('Erfolgreich');
hideLoader();
}
});
}
async function onEditYearClick() {
var id = $('#button-edityear').attr('data-sailor-id');
@@ -21,8 +55,8 @@ async function onEditYearClick() {
if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um den Jahrgang zu bearbeiten');
} else {
console.log('EditYear: unbekannter Fehler', status, error);
console.log(xhr);
log('EditYear: unbekannter Fehler', status, error);
log(xhr);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
hideLoader();
@@ -50,6 +84,26 @@ async function onListClicked(id) {
$('#menu-sailor').find('.menu-title').find('p').text(sailor.name);
// Follow
if (isLoggedIn()) {
var found = false;
for (var i in followedSailors) {
if (followedSailors[i].id == sailor.id) found = true;
}
if (found || (followedSailors.length < 5)) {
$('#menu-item-follow').attr('data-sailor-id', sailor.id);
$('#menu-item-follow').prop('checked', found);
$('#menu-item-follow').parent().parent().show();
$('#menu-item-follow-disabled').hide();
} else {
$('#menu-item-follow').parent().parent().hide();
$('#menu-item-follow-disabled').show();
}
} else {
$('#menu-item-follow').parent().parent().hide();
$('#menu-item-follow-disabled').hide();
}
// Edit Year
$('#button-edityear').attr('data-sailor-id', sailor.id);
$('#menu-edityear').find('.menu-title').find('p').text(sailor.name);
@@ -134,6 +188,19 @@ var siteScript = async function() {
$('#input-search').on('input', reSearch);
$('#menu-item-year').click(function(){ $('#menu-sailor').hideMenu(); $('#menu-edityear').showMenu(); });
$('#button-edityear').click(onEditYearClick);
$('#menu-item-follow').parent().parent().click(onFollowChange);
$('#menu-item-follow-disabled').click(function(){ $('#menu-sailor').hideMenu(); toastInfo('Du kannst maximal 5 Seglern folgen. Entferne erst einen Segler aus Deinen Favoriten, bevor Du andere aufnimmst.', 5000); });
}
if (isLoggedIn()) {
var user = await dbGetData('users', USER_ID);
followedSailors = [];
for (var i = 1; i <= 5; i ++) {
sailor_id = user['sailor' + i];
if (sailor_id != null) {
followedSailors.push(await dbGetData('sailors', sailor_id));
}
}
}
var results = await dbGetData('sailors');

View File

@@ -0,0 +1,8 @@
<a href="#" data-trigger-switch="$$html-id;" class="pb-2 $$css-class;">
<i class="fa font-14 $$icon; rounded-s bg-highlight color-white"></i>
<span>$$0;</span>
<div class="custom-control scale-switch ios-switch">
<input type="checkbox" class="ios-input" id="$$html-id;">
<label class="custom-control-label" for="$$html-id;"></label>
</div>
</a>

View File

@@ -1,4 +1,4 @@
<nav id="$$html-id;">
<nav id="$$html-id;" class="$$css-class;">
<ul class="pagination justify-content-center">
<li id="$$html-id;-1" class="page-item"><a onclick="onPaginationClick(this)" class="page-link color-black bg-theme rounded-xs shadow-x1 border-0" style="cursor: pointer;">1</a></li>
<li id="$$html-id;-2" class="page-item"><a onclick="onPaginationClick(this)" class="page-link color-black bg-theme rounded-xs shadow-x1 border-0" style="cursor: pointer;">2</a></li>

View File

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

View File

@@ -182,9 +182,9 @@ function getEntry(data, index, defaultValue) {
return ((typeof data[index] !== "undefined") ? data[index] : defaultValue);
}
function isMyRegatta(id) {
function isMyRegatta(id, suffix = '') {
return new Promise(async function (resolve) {
var regattas = await dbSettingsGet('myregattas_<?php echo BOATCLASS; ?>');
var regattas = await dbSettingsGet('myregattas_<?php echo BOATCLASS; ?>' + suffix);
if (regattas == null) resolve(false);
else resolve(regattas.includes(id.toString()));
});
@@ -228,15 +228,15 @@ self.addEventListener('push', async function(event) {
break;
case 'meldeschluss':
if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_meldeschluss')) {
if (await isMyRegatta(getEntry(data, 'id', ''))) okay = true;
if (await isMyRegatta(getEntry(data, 'id', ''), '_meldung_off')) okay = true;
}
break;
default:
console.log('Unknown channel:', data.channel);
console.log('[sW] Unknown channel:', data.channel);
break;
}
if (!okay) {
console.log('Notification channel not subscribed');
console.log('[sW] Notification channel not subscribed');
return;
}
@@ -255,7 +255,7 @@ self.addEventListener('push', async function(event) {
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 });
var request = os.put({ table: 'last_sync', time: 1 });
request.onerror = function (event) {
console.log('[sW] Error while saving data to DB:', e);
db.close();
@@ -267,7 +267,7 @@ self.addEventListener('push', async function(event) {
}
}
console.log('Showing notification');
console.log('[sW] Showing notification');
self.registration.showNotification(data.title, options);
break;
@@ -276,7 +276,7 @@ self.addEventListener('push', async function(event) {
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 });
var request = os.put({ table: 'last_sync', time: 1 });
request.onerror = function (event) {
console.log('[sW] Error while saving data to DB:', e);
db.close();
@@ -310,3 +310,16 @@ self.addEventListener('notificationclick', function(event) {
clients.openWindow(url)
);
});
self.addEventListener('pushsubscriptionchange', function(event) {
var formData = new URLSearchParams();
formData.append('old', JSON.stringify(event.oldSubscription));
formData.append('new', JSON.stringify(event.newSubscription));
event.waitUntil(
fetch('<?php echo QUERY_URL; ?>update_subscription', {
method: 'POST',
cache: 'no-cache',
body: formData
})
);
});