Compare commits

...

49 Commits
v_1.1 ... v_1.8

Author SHA1 Message Date
ostertun
a45af73c25 Merge branch 'release/v_1.8' 2020-10-02 01:29:43 +02:00
ostertun
f30eac8aa5 Release v_1.8 2020-10-02 01:27:31 +02:00
ostertun
99b624ff92 Merge branch 'feature/RA-4-notifications-ignore-my-regattas' into develop 2020-10-02 01:24:16 +02:00
ostertun
e74ffa9a70 Merge branch 'feature/RA-19-update-url-on-year-change' into develop 2020-10-02 01:24:11 +02:00
ostertun
cbb398988d Merge branch 'feature/RA-20-update-news-badge' into develop 2020-10-02 01:24:00 +02:00
ostertun
856f6c1d66 RA-#20 Update news badge 2020-10-02 01:23:46 +02:00
ostertun
2ea26408be RA-#3 Trigger inputs after programmatically changed 2020-10-02 00:59:34 +02:00
ostertun
fb1ca6d28e RA-#19 Update URL on year change 2020-10-02 00:49:53 +02:00
ostertun
6a5d06325d RA-#4 Notifications: can select "my regattas" channels only when logged in 2020-10-02 00:13:58 +02:00
ostertun
72ac8df460 Merge branch 'feature/dev_buttons' into develop 2020-10-01 23:36:05 +02:00
ostertun
246231fd0e RA-#8 Fix deleteCache 2020-10-01 23:35:49 +02:00
ostertun
3e533f65fc Added show-console-button to preloader 2020-10-01 23:26:22 +02:00
ostertun
2533c3d66a RA-#16 Updated Dev Buttons 2020-10-01 23:25:48 +02:00
ostertun
cacee5a54a RA-#17 Fix padding of body 2020-10-01 22:46:53 +02:00
ostertun
274aa85cf7 Merge branch 'release/v_1.7' 2020-10-01 03:21:20 +02:00
ostertun
4317e4fe87 Release v_1.7
Prepare github repo
small fixes
2020-10-01 03:19:42 +02:00
Timon Ostertun
b7dec825ca Update issue templates 2020-10-01 03:00:38 +02:00
Timon Ostertun
6ca6a79dc3 Update issue templates 2020-10-01 02:59:12 +02:00
Timon Ostertun
d1e5d753b4 Create README.md 2020-10-01 01:03:41 +02:00
Timon Ostertun
7afacc3fff Update issue templates 2020-09-30 23:56:51 +02:00
Timon Ostertun
77ea57d643 RA-#1 Notifications: Badge Icon 2020-09-30 23:24:24 +02:00
Timon Ostertun
a72c462483 RA-#4 Registration open icon is red when deadline expired 2020-09-30 22:46:20 +02:00
Timon Ostertun
b739e6cc4e RA-#7 Fix serviceWorker 2020-09-30 22:45:43 +02:00
Timon Ostertun
eb47cdf016 RA-#7 Removed unnecessary files from cache 2020-09-30 22:25:59 +02:00
Timon Ostertun
12c1a614bb Fix #5 serviceWorker DB access
serviceWorker openes DB only when needed and closes it directly
2020-09-30 16:46:10 +02:00
Timon Ostertun
0fb1bb0462 Added mobile console 2020-09-30 14:36:07 +02:00
Timon Ostertun
1b1176b952 Release v_1.6 2020-09-27 23:18:37 +02:00
Timon Ostertun
00c1c93b80 Added news 2020-09-27 23:17:56 +02:00
Timon Ostertun
876776eb5b Added notifications 2020-09-27 21:54:43 +02:00
Timon Ostertun
a92dc45bb7 Can subscribe to pushes 2020-09-27 14:35:25 +02:00
Timon Ostertun
2bf623733d Release v_1.5 2020-09-27 01:35:43 +02:00
Timon Ostertun
60caf85daa Added add_year, add_boatname 2020-09-27 01:33:45 +02:00
Timon Ostertun
eddcff9e39 Added contact 2020-09-27 00:53:53 +02:00
Timon Ostertun
967ad50755 Moved api backend to main website 2020-09-27 00:05:57 +02:00
Timon Ostertun
a437d05647 Small fixes 2020-09-26 23:42:00 +02:00
Timon Ostertun
658bfcc4a8 Release v_1.4 2020-09-26 20:11:47 +02:00
Timon Ostertun
b5b1897dac Welcome banner 2020-09-26 20:10:36 +02:00
Timon Ostertun
b32b5e3c00 Fix toasts 2020-09-26 19:34:53 +02:00
Timon Ostertun
08e5afeb6e Added regatta_plan 2020-09-26 19:22:46 +02:00
Timon Ostertun
364fd6fea0 rank can idjm 2020-09-26 18:58:29 +02:00
Timon Ostertun
4143545117 Small fixes 2020-09-26 18:38:05 +02:00
Timon Ostertun
9e30ed5e9c Added ranking, calc 2020-09-26 18:08:34 +02:00
Timon Ostertun
9d1ba271f3 Added TODO sites 2020-09-26 18:08:14 +02:00
Timon Ostertun
8eff91f28b Fix login / logout 2020-09-26 18:06:44 +02:00
Timon Ostertun
641210e7f4 Release v_1.3 2020-09-25 23:42:31 +02:00
Timon Ostertun
c660fed9f0 Added lists (sailors, boats, clubs) 2020-09-25 23:39:49 +02:00
Timon Ostertun
5bc2d19800 Fix v_1.2 2020-09-25 19:02:52 +02:00
Timon Ostertun
89d53e0854 Release v_1.2 2020-09-25 18:51:10 +02:00
Timon Ostertun
9f16806179 New regattas list on index 2020-09-25 18:48:42 +02:00
69 changed files with 5062 additions and 1767 deletions

View File

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

View File

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

View File

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

View File

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

View File

@@ -6,14 +6,13 @@ RewriteBase /projects/RegattenApp/
### RESTRICTED FOLDER
RewriteRule ^(.*)server(.*)$ / [R=301,L,NC]
RewriteRule ^(.*)content(.*)$ / [R=301,L,NC]
### CONTENT LOADER
# Keep this subfolders untouched
RewriteRule ^(api)($|/) - [L]
#RewriteRule ^(api)($|/) - [L]
# Show site
RewriteRule ^([^\.]*)$ index.php?request=$1 [QSA]

11
README.md Normal file
View File

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

View File

@@ -1,8 +0,0 @@
RewriteEngine on
# root directory:
RewriteBase /projects/RegattenApp/api/
# Show site
RewriteRule ^(.*)$ index.php?request=$1 [QSA]

View File

@@ -1,37 +0,0 @@
<?php
// DATABASE Credentials
define('DB_USER', 'regattenwebsite');
define('DB_PASS', 'RBpOv4YYtZKWIGcN');
define('DB_HOST', 'localhost');
define('DB_DATABASE', 'regattenwebsite');
define('DB_CHANGE_TIME', true);
define('DB_USE_UTF8', true); // use utf-8 in DB requests
// DATABASE Table names
define('DB_TABLE_USERS', 'users');
define('DB_TABLE_LOGINS', 'logins');
define('DB_TABLE_KEEPLOGGEDIN', 'keeploggedin');
define('DB_TABLE_RESET', 'rstpw');
define('DB_TABLE_CLUBS', 'regatta_clubs');
define('DB_TABLE_SUFFIX_BOATS', '_boats');
define('DB_TABLE_SUFFIX_SAILORS', '_sailors');
define('DB_TABLE_SUFFIX_PLANNING', '_planning');
define('DB_TABLE_SUFFIX_REGATTAS', '_regattas');
define('DB_TABLE_SUFFIX_RESULTS', '_results');
define('DB_TABLE_TRIM_BOATS', 'trim_boats');
define('DB_TABLE_TRIM_USERS', 'trim_users');
define('DB_TABLE_TRIM_TRIMS', 'trim_trims');
define('DB_TABLE_NEWS', 'news');
define('DB_TABLE_UPDATETIMES', '_updatetimes');
// OUTGOING MAILS - Credentials for outgoing mails
define('MAIL_SMTP_HOST', 'ssl://ostertun.net'); // SMTP Server address
define('MAIL_SMTP_PORT', 465); // port to use
define('MAIL_FROM_ADDRESS', 'no-reply@regatten.net'); // address to send mails from
define('MAIL_USERNAME', MAIL_FROM_ADDRESS); // if true: username
define('MAIL_PASSWORD', 'pVc05j_3'); // & password
?>

View File

@@ -1,157 +0,0 @@
<?php
/*
Mysql Database Support
----------------------
Required defines:
- DB_HOST (STRING)
- DB_USER (STRING)
- DB_PASS (STRING)
- DB_DATABASE (STRING)
- DB_USE_UTF8 (BOOL)
- DB_CHANGE_TIME (BOOL)
Required functions:
- logE (in /_global/log.php)
*/
$mysqli = mysqli_connect(DB_HOST, DB_USER, DB_PASS);
if ($mysqli === false) {
logE("database", "Could not connect to database\n" . mysqli_connect_error);
die('Error: Could not connect to database');
}
mysqli_select_db($mysqli, DB_DATABASE);
if (DB_USE_UTF8) {
mysqli_set_charset($mysqli, 'utf8');
}
function db_get_data($mysqli, $table, $fields = '*', $where = false, $limit = false) {
$rest = '';
if ($where != false) {
$rest .= ' WHERE ' . $where;
}
if ($limit != false) {
$rest .= sprintf(' LIMIT %d', $limit);
}
$query = 'SELECT ' . $fields . ' FROM ' . mysqli_real_escape_string($mysqli, $table) . $rest . ';';
$response = mysqli_query($mysqli, $query);
if ($response !== false) {
$result = array();
if ($response->num_rows > 0) {
$i = 0;
while ($row = $response->fetch_assoc()) {
if (isset($row['id'])) {
$id = $row['id'];
} else {
$id = $i;
$i ++;
}
foreach ($row as $key => $value) {
$result[$id][$key] = $value;
}
}
}
return $result;
} else {
logE("database", "get_data\nInvalid request\n" . $query . "\n" . mysqli_error($mysqli));
return false;
}
}
function db_update_data($mysqli, $table, $data, $where, $limit = false) {
$rest = '';
if ($where != false) {
$rest .= ' WHERE ' . $where;
}
if ($limit != false) {
$rest .= sprintf(' LIMIT %d', $limit);
}
$set = '';
$first = true;
foreach ($data as $key => $value) {
if ($first) {
$first = false;
} else {
$set .= ', ';
}
if ($value === null) {
$set .= '`' . mysqli_real_escape_string($mysqli, $key) . '`=NULL';
} else {
$set .= '`' . mysqli_real_escape_string($mysqli, $key) . '`="' . mysqli_real_escape_string($mysqli, $value) . '"';
}
}
if (defined('DB_CHANGE_TIME')) $set .= ', `changed`=NOW()';
$query = 'UPDATE ' . mysqli_real_escape_string($mysqli, $table) . ' SET ' . $set . $rest . ';';
$response = mysqli_query($mysqli, $query);
if ($response === false) {
logE("database", "update_data\nInvalid request\n" . $query . "\n" . mysqli_error($mysqli));
} elseif (defined('DB_CHANGE_TIME')) {
mysqli_query($mysqli, 'UPDATE `_updatetimes` SET `update`=NOW() WHERE `table`="' . mysqli_real_escape_string($mysqli, $table) . '";');
}
return $response;
}
function db_insert_data($mysqli, $table, $data) {
$fields = '';
$values = '';
$first = true;
foreach ($data as $key => $value) {
if ($first) {
$first = false;
} else {
$fields .= ', ';
$values .= ', ';
}
$fields .= '`' . mysqli_real_escape_string($mysqli, $key) . '`';
if ($value === null) {
$values .= 'NULL';
} else {
$values .= '"' . mysqli_real_escape_string($mysqli, $value) . '"';
}
}
if (defined('DB_CHANGE_TIME')) {
$fields .= ', `changed`';
$values .= ', NOW()';
}
$query = 'INSERT INTO `' . mysqli_real_escape_string($mysqli, $table) . '` (' . $fields . ') VALUES (' . $values . ');';
$response = mysqli_query($mysqli, $query);
if ($response === false) {
logE("database", "insert_data\nInvalid request\n" . $query . "\n" . mysqli_error($mysqli));
} else {
$response = mysqli_insert_id($mysqli);
if (defined('DB_CHANGE_TIME')) {
mysqli_query($mysqli, 'UPDATE `_updatetimes` SET `update`=NOW() WHERE `table`="' . mysqli_real_escape_string($mysqli, $table) . '";');
}
}
return $response;
}
function db_delete_data($mysqli, $table, $where, $limit = false) {
$rest = '';
if ($where != false) {
$rest .= ' WHERE ' . $where;
}
if ($limit != false) {
$rest .= sprintf(' LIMIT %d', $limit);
}
$query = 'DELETE FROM `' . mysqli_real_escape_string($mysqli, $table) . '`' . $rest . ';';
$response = mysqli_query($mysqli, $query);
if ($response === false) {
logE("database", "delete_data\nInvalid request\n" . $query . "\n" . mysqli_error($mysqli));
} elseif (defined('DB_CHANGE_TIME')) {
mysqli_query($mysqli, 'UPDATE `_updatetimes` SET `update`=NOW() WHERE `table`="' . mysqli_real_escape_string($mysqli, $table) . '";');
}
return $response;
}
?>

View File

@@ -1,450 +0,0 @@
<?php
function get_db_entry($mysqli, $table, $id = false, $order = false) {
if ($id === false) {
return db_get_data($mysqli, $table, '*', ($order !== false ? ('1=1 ORDER BY ' . $order) : false));
} else {
$result = db_get_data($mysqli, $table, '*', '`id` = "' . mysqli_real_escape_string($mysqli, $id) . '"', 1);
if (($result === false) or (count($result) != 1))
return false;
else
return array_values($result)[0];
}
}
function get_club($mysqli, $id = false) {
return get_db_entry($mysqli, DB_TABLE_CLUBS, $id, '`kurz` ASC');
}
function get_boat($mysqli, $id = false) {
return get_db_entry($mysqli, BOATCLASS . DB_TABLE_SUFFIX_BOATS, $id, '`sailnumber` ASC');
}
function get_sailor($mysqli, $id = false) {
return get_db_entry($mysqli, BOATCLASS . DB_TABLE_SUFFIX_SAILORS, $id, '`name` ASC');
}
function get_planning($mysqli, $userId = false, $regattaId = false) {
$where = '';
$limit = false;
if ($userId !== false) {
$where .= '(`user`="' . mysqli_real_escape_string($mysqli, $userId) . '")';
}
if (($userId !== false) and ($regattaId !== false)) {
$where .= ' AND ';
$limit = 1;
}
if ($regattaId !== false) {
$where .= '(`regatta`="' . mysqli_real_escape_string($mysqli, $regattaId) . '")';
}
if ($where == '') $where = false;
if ($limit === false) {
return db_get_data($mysqli, BOATCLASS . DB_TABLE_SUFFIX_PLANNING, '*', $where);
} else {
$result = db_get_data($mysqli, BOATCLASS . DB_TABLE_SUFFIX_PLANNING, '*', $where, 1);
if (($result === false) or (count($result) != 1))
return false;
else
return array_values($result)[0];
}
}
function get_regatta($mysqli, $id = false) {
return get_db_entry($mysqli, BOATCLASS . DB_TABLE_SUFFIX_REGATTAS, $id, '`date` ASC');
}
function get_result($mysqli, $regattaId = false) {
if ($regattaId === false) {
return db_get_data($mysqli, BOATCLASS . DB_TABLE_SUFFIX_RESULTS);
} else {
return db_get_data($mysqli, BOATCLASS . DB_TABLE_SUFFIX_RESULTS, '*', '`regatta` = "' . mysqli_real_escape_string($mysqli, $regattaId) . '"');
}
}
function get_regattas_range($mysqli, $from, $to) {
return db_get_data($mysqli, BOATCLASS . DB_TABLE_SUFFIX_REGATTAS, '*', '(`date` >= "' . date('Y-m-d', $from) . '") AND (`date` <= "' . date('Y-m-d', $to) . '") ORDER BY `date`');
}
function get_regatta_years($mysqli) {
$query = 'SELECT DISTINCT(YEAR(`date`)) as year FROM ' . BOATCLASS . DB_TABLE_SUFFIX_REGATTAS . ' ORDER BY `date`;';
$response = mysqli_query($mysqli, $query);
if ($response !== false) {
$result = array();
if ($response->num_rows > 0) {
while ($row = $response->fetch_assoc()) {
$result[] = $row['year'];
}
}
return $result;
} else {
logE("functions", "get_data\nInvalid request\n" . $query . "\n" . mysqli_error($mysqli));
return false;
}
}
function get_result_calculated($mysqli, $regatta_id) {
$regatta = get_regatta($mysqli, $regatta_id);
if ($regatta === false) {
return false;
}
$results = get_result($mysqli, $regatta_id);
if ($results !== false) {
// *** Replace , with .
foreach ($results as $key => $value) {
for ($i = 1; $i <= $regatta['races']; $i ++) {
$results[$key]['race' . $i] = str_replace(',', '.', $results[$key]['race' . $i]);
}
}
// *** Calculation ***
$gemeldet = count($results);
$sortarray = array();
foreach ($results as $key => $value) {
$results[$key]['finished'] = false;
$results[$key]['values'] = array();
$results[$key]['values_all'] = array();
$results[$key]['texts'] = array();
$copy = array();
for ($i = 1; $i <= $regatta['races']; $i ++) {
if (is_numeric($value['race' . $i])) {
$results[$key]['values'][$i] = $value['race' . $i];
$results[$key]['texts'][$i] = $value['race' . $i];
$copy[$i] = $value['race' . $i];
$results[$key]['finished'] = true;
} else {
switch ($value['race' . $i]) {
// Nicht gestartet
case 'DNC': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; break; // Did not come
case 'DNS': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; break; // Did not started
// Startfehler
case 'OCS': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; /*$results[$key]['finished'] = true;*/ break; // On course site
// Muss v. Hand case 'ZFP': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; $results[$key]['finished'] = true; break; // Z-Flag penalty (20% nach 30.2)
case 'UFD': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; /*$results[$key]['finished'] = true;*/ break; // Uniform Flag Disqualified (disqu. nach 30.3)
case 'BFD': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; /*$results[$key]['finished'] = true;*/ break; // Black Flag Disqualified (disqu. nach 30.4)
// Nicht durch Ziel gegangen
case 'DNF': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; break; // Did not finish
case 'RET': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; break; // Retired (Aufgegeben)
case 'RAF': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; /*$results[$key]['finished'] = true;*/ break; // Retired after finish
// Disqualifizierun
case 'DSQ': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; /*$results[$key]['finished'] = true;*/ break; // Disqualified
case 'DNE': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = -1; /*$results[$key]['finished'] = true;*/ break; // Disqualified, not excludable (disqu. kann nach 90.3(b) nicht gestrichen werden)
case 'DGM': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = -2; /*$results[$key]['finished'] = true;*/ break; // Disqualification Gross Missconduct (kann nach 69.1(b)(2) nicht gestr. werden, grobes Fehlverhalten)
// Wiedergutmachung
// Muss v. Hand case 'RDG': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; $results[$key]['finished'] = true; break; // Redress given (Wiedergutmachung gewährt)
// Strafen
// Muss v. Hand case 'SCP': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; $results[$key]['finished'] = true; break; // Wertungsstrafe nach 44.3(a) (20%)
// Muss v. Hand case 'DPI': $results[$key]['values'][$i] = $gemeldet + 1; $copy[$i] = $gemeldet + 1; $results[$key]['finished'] = true; break; // Punktstrafe nach Ermessen der Jury
// Unbekannt
default: $results[$key]['values'][$i] = 0; $copy[$i] = 0; break;
}
if ($results[$key]['values'][$i] != 0) {
$results[$key]['texts'][$i] = $value['race' . $i] . ' (' . $results[$key]['values'][$i] . ')';
} else {
$results[$key]['texts'][$i] = $value['race' . $i] . ' (Unknown - 0)';
}
}
}
$results[$key]['values_all'] = $results[$key]['values'];
for ($s = 0; $s < $regatta['streicher']; $s ++) {
$max = max($copy);
for ($i = 1; $i <= $regatta['races']; $i ++) {
if ($copy[$i] == $max) {
$copy[$i] = 0;
break;
}
}
}
$brutto = $netto = 0;
for ($i = 1; $i <= $regatta['races']; $i ++) {
$brutto += $results[$key]['values_all'][$i];
if ($copy[$i] == -1) { $results[$key]['values'][$i] = $gemeldet + 1; }
elseif ($copy[$i] == -2) { $results[$key]['values'][$i] = $gemeldet + 1; }
else { $results[$key]['values'][$i] = $copy[$i]; }
if ($results[$key]['values'][$i] == 0) {
$results[$key]['texts'][$i] = '[' . $results[$key]['texts'][$i] . ']';
}
$netto += $results[$key]['values'][$i];
}
$results[$key]['brutto'] = $brutto;
$results[$key]['netto'] = $netto;
if ($results[$key]['finished']) {
$sortarray[$key] = 0;
} else {
$sortarray[$key] = 1;
}
$sortarray[$key] /*.*/= sprintf("%08.2f", $netto);
$temp = $results[$key]['values'];
sort($temp);
$i = 0;
foreach ($temp as $val) {
if ($i < $regatta['races']) {
$sortarray[$key] .= sprintf("%07.2f", $val);
}
$i ++;
}
for ($i = $regatta['races']; $i > 0; $i --) {
$sortarray[$key] .= sprintf("%07.2f", $results[$key]['values_all'][$i]);
}
$results[$key]['sortvalue'] = $sortarray[$key];
}
array_multisort($sortarray, $results);
$i = 1;
foreach ($results as $key => $value) {
if (($i > 1) and ($sortarray[$key] == $sortarray[$lastkey])) {
$results[$key]['place'] = $results[$lastkey]['place'];
} else {
$results[$key]['place'] = $i;
}
$i ++;
$lastkey = $key;
}
unset ($sortarray);
return $results;
} else {
return false;
}
}
function update_result_cache($mysqli, $regatta_id) {
$regatta = get_regatta($mysqli, $regatta_id);
if ($regatta === false) return;
$results = get_result_calculated($mysqli, $regatta['id']);
if ($results === false) return;
// count finished boats
$fb = 0;
foreach ($results as $result) {
if ($result['finished']) {
$fb ++;
}
}
db_update_data($mysqli, BOATCLASS . DB_TABLE_SUFFIX_REGATTAS, ['finishedBoats' => $fb], '`id`="' . $regatta['id'] . '"', 1);
foreach ($results as $result) {
if ($fb == 0) {
$rlp = 0;
} else {
$rlp = 100 * $regatta['rlf'] * (($fb + 1 - $result['place']) / $fb);
}
db_update_data($mysqli, BOATCLASS . DB_TABLE_SUFFIX_RESULTS, ['place' => $result['place'], 'rlp' => $rlp], '`id`="' . $result['id'] . '"', 1);
}
}
function get_ranking($mysqli, $from, $to, $jugend = false, $jugstrict = false) {
global $rankNoResults, $_CLASSES;
$rankNoResults = array();
$sailors = get_sailor($mysqli);
$regattas = get_regattas_range($mysqli, $from, $to);
if (($sailors !== false) and ($regattas !== false)) {
foreach ($sailors as $key => $sailor) {
$sailors[$key]['regattas'] = array();
$sailors[$key]['tmp_rlp'] = array();
}
foreach ($regattas as $regatta) {
$date = strtotime($regatta['date']);
// regatta has to be min. 2 days to be ranking-regatta
if ($regatta['length'] < 2) {
continue;
}
$results = get_result($mysqli, $regatta['id']);
if ($results === false) {
continue;
}
if (count($results) <= 0) {
if (strtotime('+' . ($regatta['length']-1) . ' days', $date) <= time()) {
if (!$regatta['canceled']) {
$rankNoResults[] = $regatta;
}
}
continue;
}
// in one race there must be at least 10 boats started
$ok = false;
for ($i = 1; $i <= $regatta['races']; $i ++) {
$temp = 0;
foreach ($results as $result) {
if (($result['race' . $i] != 'DNC') and ($result['race' . $i] != 'DNS')) {
$temp ++;
}
}
if ($temp >= 10) {
$ok = true;
break;
}
}
if (!$ok) {
continue;
}
$fb = $regatta['finishedBoats'];
// add regatta to each sailor
foreach ($results as $result) {
if ($result['rlp'] == 0) {
continue;
}
// check if crew is youth
//if ($jugend) {
// $crew = explode(',', $result['crew']);
// $okay = true;
// foreach ($crew as $sailor) {
// if (($sailor == '') or !isset($sailors[$sailor])) continue;
// $sailor = $sailors[$sailor];
// if ((($sailor['year'] !== null) and ($sailor['year'] < (date('Y', $date) - $_CLASSES[BOATCLASS]['youth-age']))) or
// (($sailor['year'] === null) and ($jugstrict))) {
// $okay = false;
// break;
// }
// }
// if (!$okay) continue;
//}
// calc m
if ($regatta['m'] > 0) {
$m = $regatta['m'];
} elseif ($regatta['races'] <= 4) {
$m = $regatta['races'];
} else {
if (($regatta['length'] > 2) and ($regatta['races'] >= 6)) {
$m = 5;
} else {
$m = 4;
}
}
$rlp = $result['rlp'];
$sailors[$result['steuermann']]['regattas'][$regatta['id']] = array(
'regatta' => $regatta['id'],
'boat' => $result['boat'],
'crew' => $result['crew'],
'place' => $result['place'],
'fb' => $fb,
'rlp' => $rlp,
'used' => 0,
'm' => $m
);
for ($i = 0; $i < $m; $i ++) {
array_push($sailors[$result['steuermann']]['tmp_rlp'], array($regatta['id'], $rlp));
}
}
}
foreach ($sailors as $key => $sailor) {
if ($sailor['german'] == 0) {
unset($sailors[$key]);
} elseif ($jugend) {
if ((($sailor['year'] !== null) and ($sailor['year'] < (date('Y', $to) - $_CLASSES[BOATCLASS]['youth-age']))) or
(($sailor['year'] === null) and ($jugstrict))) {
unset($sailors[$key]);
}
}
}
$sortarray = array();
foreach ($sailors as $key => $sailor) {
// sort rlps desc
$sort = array();
foreach ($sailor['tmp_rlp'] as $key2 => $value) {
$sort[$key2] = $value[1];
}
array_multisort($sort, SORT_DESC, $sailors[$key]['tmp_rlp']);
// calc mean. rlp
$sum = 0;
$cnt = 0;
foreach ($sailors[$key]['tmp_rlp'] as $value) {
$sum += $value[1];
$sailors[$key]['regattas'][$value[0]]['used'] ++;
$cnt ++;
if ($cnt >= 9) {
break;
}
}
unset($sailors[$key]['tmp_rlp']);
if ($cnt > 0) {
$rlp = $sum / $cnt;
$sailors[$key]['rlp'] = $rlp;
$sailors[$key]['m'] = $cnt;
} else {
unset($sailors[$key]);
continue;
}
if ($rlp == 0) {
$sortarray[$key] = $cnt;
} else {
$sortarray[$key] = $cnt * 1000 + $rlp;
}
}
array_multisort($sortarray, SORT_DESC, $sailors);
unset($sortarray);
$i = 1;
foreach ($sailors as $key => $sailor) {
$sailors[$key]['rank'] = $i;
$i ++;
}
return $sailors;
} else {
return false;
}
}
function get_trim_boat($mysqli, $id = false) {
return get_db_entry($mysqli, DB_TABLE_TRIM_BOATS, $id);
}
function get_trim_boat_users($mysqli, $id) {
$result = db_get_data($mysqli, DB_TABLE_TRIM_USERS, '*', '`boat` = "' . mysqli_real_escape_string($mysqli, $id) . '"');
if ($result === false)
return false;
else
return $result;
}
function get_trim_user_boats($mysqli, $id) {
$boats = db_get_data($mysqli, DB_TABLE_TRIM_USERS, '*', '`user` = "' . mysqli_real_escape_string($mysqli, $id) . '"');
if ($boats === false) {
return false;
} else {
$result = [];
foreach ($boats as $value) {
$result[$value['boat']] = get_trim_boat($mysqli, $value['boat']);
}
return $result;
}
}
function trim_is_boat_user($mysqli, $user, $boat) {
$res = db_get_data($mysqli, DB_TABLE_TRIM_USERS, '*', '`user` = "' . mysqli_real_escape_string($mysqli, $user) . '" AND `boat` = "' . mysqli_real_escape_string($mysqli, $boat) . '"');
return ($res !== false) and (count($res) == 1);
}
function get_trim_trim($mysqli, $id = false) {
return get_db_entry($mysqli, DB_TABLE_TRIM_TRIMS, $id);
}
function get_trim_boat_trims($mysqli, $id) {
$result = db_get_data($mysqli, DB_TABLE_TRIM_TRIMS, '*', '`boat` = "' . mysqli_real_escape_string($mysqli, $id) . '"');
if ($result === false) {
return false;
} else {
return $result;
}
}
?>

View File

@@ -1,466 +0,0 @@
<?php
require_once(__DIR__ . '/../server/config.php');
require_once(__DIR__ . '/config.php');
require_once(__DIR__ . '/../server/log.php');
require_once(__DIR__ . '/database.php');
require_once(__DIR__ . '/login.php');
require_once(__DIR__ . '/functions.php');
$request = false;
if (isset($_GET['request'])) {
$request = explode('/', $_GET['request']);
}
if ($request === false) {
$request = array();
}
if (count($request) >= 1) {
$action = array_shift($request);
} else {
$action = '';
}
define('DONE_OKAY', 0);
define('DONE_EMPTY', 1);
define('DONE_DATABASE', 2);
define('DONE_UNAUTHORIZED', 3);
define('DONE_BAD_REQUEST', 4);
define('DONE_CONFLICT', 5);
define('DONE_SERVER_ERROR', 6);
function done($donecode, $content = null) {
switch ($donecode) {
case DONE_OKAY:
header('HTTP/1.0 200 OK');
break;
case DONE_EMPTY:
header('HTTP/1.0 204 No Content');
break;
case DONE_DATABASE:
header('HTTP/1.0 500 Internal Server Error');
if ($content === null) {
$content = array('error' => 'database error');
}
break;
case DONE_UNAUTHORIZED:
header('HTTP/1.0 401 Unauthorized');
if ($content === null) {
$content = array('error' => 'unauthorized');
}
break;
case DONE_BAD_REQUEST:
header('HTTP/1.0 400 Bad Request');
if ($content === null) {
$content = array('error' => 'bad request');
}
break;
case DONE_CONFLICT:
header('HTTP/1.0 409 Conflict');
break;
case DONE_SERVER_ERROR:
header('HTTP/1.0 500 Internal Server Error');
break;
default:
header('HTTP/1.0 500 Internal Server Error');
break;
}
header('Content-Type: application/json');
if ($content !== null) {
echo json_encode($content);
} else {
echo '{ }';
}
exit;
}
if (isset($_REQUEST['auth']['id'], $_REQUEST['auth']['hash'])) {
$user_id = auth_check($mysqli, $_REQUEST['auth']['id'], $_REQUEST['auth']['hash']);
} else {
$user_id = false;
}
function isLoggedIn() {
global $user_id;
return $user_id !== false;
}
function checkLoggedIn() {
if (!isLoggedIn()) done(DONE_UNAUTHORIZED, ['error' => 'permission denied']);
}
function checkRequest($param) {
if (!isset($_REQUEST[$param])) done(DONE_BAD_REQUEST, ['error' => 'missing parameter: ' . $param]);
}
function replaceChanged($array) {
return array_map(function ($entry) {
unset($entry['changed']);
return $entry;
}, $array);
}
$whereString = false;
if (isset($_REQUEST['index'], $_REQUEST['value'])) {
$whereString = '`' . mysqli_real_escape_string($mysqli, $_REQUEST['index']) . '`="' . mysqli_real_escape_string($mysqli, $_REQUEST['value']) . '"';
}
function sendEntries($table) {
global $mysqli, $whereString;
$response = db_get_data($mysqli, $table, '*', $whereString);
if ($response === false) done(DONE_DATABASE);
$keys = array_keys($response);
if (isset($_REQUEST['changed-after'])) {
$response = db_get_data($mysqli, $table, '*', '`changed` > "' . mysqli_real_escape_string($mysqli, date('Y-m-d H:i:s', $_REQUEST['changed-after'])) . '"' . ($whereString ? (' AND ' . $whereString) : ''));
if ($response === false) done(DONE_DATABASE);
}
$response = array_values($response);
done(DONE_OKAY, array('data' => replaceChanged($response), 'keys' => $keys));
}
function sendEntry($table) {
global $mysqli;
checkRequest('id');
$response = db_get_data($mysqli, $table, '*', '`id` = "' . mysqli_real_escape_string($mysqli, $_REQUEST['id']) . '"');
if ($response === false) done(DONE_DATABASE);
if (count($response) != 1) done(DONE_BAD_REQUEST, ['error' => 'id not found']);
$response = array_values($response)[0];
unset($response['changed']);
done(DONE_OKAY, ['data' => $response]);
}
switch ($action) {
case 'login':
checkRequest('username');
checkRequest('password');
checkRequest('device');
$auth = auth_login($mysqli, $_REQUEST['username'], $_REQUEST['password'], $_REQUEST['device']);
if ($auth === false) done(DONE_UNAUTHORIZED);
done(DONE_OKAY, $auth);
break;
case 'logout':
checkLoggedIn();
auth_logout($mysqli, $_REQUEST['auth']['id']);
done(DONE_OKAY);
break;
case 'get_update_time':
$times = array();
$response = db_get_data($mysqli, DB_TABLE_UPDATETIMES, '`update`', '`table` = "' . DB_TABLE_CLUBS . '"', 1);
if (($response !== false) and (count($response) > 0)) {
$times['clubs'] = strtotime(array_values($response)[0]['update']);
} else {
done(DONE_DATABASE);
}
$response = db_get_data($mysqli, DB_TABLE_UPDATETIMES, '`update`', '`table` = "' . BOATCLASS . DB_TABLE_SUFFIX_BOATS . '"', 1);
if (($response !== false) and (count($response) > 0)) {
$times['boats'] = strtotime(array_values($response)[0]['update']);
} else {
done(DONE_DATABASE);
}
$response = db_get_data($mysqli, DB_TABLE_UPDATETIMES, '`update`', '`table` = "' . BOATCLASS . DB_TABLE_SUFFIX_SAILORS . '"', 1);
if (($response !== false) and (count($response) > 0)) {
$times['sailors'] = strtotime(array_values($response)[0]['update']);
} else {
done(DONE_DATABASE);
}
$response = db_get_data($mysqli, DB_TABLE_UPDATETIMES, '`update`', '`table` = "' . BOATCLASS . DB_TABLE_SUFFIX_REGATTAS . '"', 1);
if (($response !== false) and (count($response) > 0)) {
$times['regattas'] = strtotime(array_values($response)[0]['update']);
} else {
done(DONE_DATABASE);
}
$response = db_get_data($mysqli, DB_TABLE_UPDATETIMES, '`update`', '`table` = "' . BOATCLASS . DB_TABLE_SUFFIX_RESULTS . '"', 1);
if (($response !== false) and (count($response) > 0)) {
$times['results'] = strtotime(array_values($response)[0]['update']);
} else {
done(DONE_DATABASE);
}
$response = db_get_data($mysqli, DB_TABLE_UPDATETIMES, '`update`', '`table` = "' . BOATCLASS . DB_TABLE_SUFFIX_PLANNING . '"', 1);
if (($response !== false) and (count($response) > 0)) {
$times['plannings'] = strtotime(array_values($response)[0]['update']);
} else {
done(DONE_DATABASE);
}
$response = db_get_data($mysqli, DB_TABLE_UPDATETIMES, '`update`', '`table` = "' . DB_TABLE_TRIM_BOATS . '"', 1);
if (($response !== false) and (count($response) > 0)) {
$times['trim_boats'] = strtotime(array_values($response)[0]['update']);
} else {
done(DONE_DATABASE);
}
$response = db_get_data($mysqli, DB_TABLE_UPDATETIMES, '`update`', '`table` = "' . DB_TABLE_TRIM_USERS . '"', 1);
if (($response !== false) and (count($response) > 0)) {
$times['trim_users'] = strtotime(array_values($response)[0]['update']);
} else {
done(DONE_DATABASE);
}
$response = db_get_data($mysqli, DB_TABLE_UPDATETIMES, '`update`', '`table` = "' . DB_TABLE_TRIM_TRIMS . '"', 1);
if (($response !== false) and (count($response) > 0)) {
$times['trim_trims'] = strtotime(array_values($response)[0]['update']);
} else {
done(DONE_DATABASE);
}
$response = db_get_data($mysqli, DB_TABLE_UPDATETIMES, '`update`', '`table` = "' . DB_TABLE_USERS . '"', 1);
if (($response !== false) and (count($response) > 0)) {
$times['users'] = strtotime(array_values($response)[0]['update']);
} else {
done(DONE_DATABASE);
}
done(DONE_OKAY, $times);
break;
case 'get_clubs':
sendEntries(DB_TABLE_CLUBS);
break;
case 'get_club':
sendEntry(DB_TABLE_CLUBS);
break;
case 'get_boats':
sendEntries(BOATCLASS . DB_TABLE_SUFFIX_BOATS);
break;
case 'get_boat':
sendEntry(BOATCLASS . DB_TABLE_SUFFIX_BOATS);
break;
case 'get_sailors':
sendEntries(BOATCLASS . DB_TABLE_SUFFIX_SAILORS);
break;
case 'get_sailor':
sendEntry(BOATCLASS . DB_TABLE_SUFFIX_SAILORS);
break;
case 'get_years':
$response = get_regatta_years($mysqli);
if ($response === false) done(DONE_DATABASE);
foreach ($response as $key => $value)
$response[$key] = ['year' => $value];
done(DONE_OKAY, ['data' => $response]);
break;
case 'get_regattas':
sendEntries(BOATCLASS . DB_TABLE_SUFFIX_REGATTAS);
break;
case 'get_regatta':
sendEntry(BOATCLASS . DB_TABLE_SUFFIX_REGATTAS);
break;
case 'get_results':
sendEntries(BOATCLASS . DB_TABLE_SUFFIX_RESULTS);
break;
case 'get_result':
sendEntry(BOATCLASS . DB_TABLE_SUFFIX_RESULTS);
break;
case 'get_plannings':
$response = db_get_data($mysqli, BOATCLASS . DB_TABLE_SUFFIX_PLANNING, '*', $whereString);
if ($response === false) done(DONE_DATABASE);
$keys = array_keys($response);
if (isset($_REQUEST['changed-after'])) {
$response = db_get_data($mysqli, BOATCLASS . DB_TABLE_SUFFIX_PLANNING, '*', '`changed` > "' . mysqli_real_escape_string($mysqli, date('Y-m-d H:i:s', $_REQUEST['changed-after'])) . '"' . ($whereString ? (' AND ' . $whereString) : ''));
if ($response === false) done(DONE_DATABASE);
}
$response = array_map(function ($entry) {
global $user_id;
if (($user_id === false) or ($entry['user'] != $user_id)) {
unset($entry['gemeldet'], $entry['bezahlt']);
}
return $entry;
}, $response);
$response = array_values($response);
done(DONE_OKAY, array('data' => replaceChanged($response), 'keys' => $keys));
break;
case 'get_planning':
checkRequest('id');
$response = db_get_data($mysqli, BOATCLASS . DB_TABLE_SUFFIX_PLANNING, '*', '`id` = "' . mysqli_real_escape_string($mysqli, $_REQUEST['id']) . '"');
if ($response === false) done(DONE_DATABASE);
if (count($response) != 1) done(DONE_BAD_REQUEST, ['error' => 'id not found']);
$response = array_values($response)[0];
if (($user_id === false) or ($response['user'] != $user_id)) {
unset($response['gemeldet'], $response['bezahlt']);
}
unset($response['changed']);
done(DONE_OKAY, ['data' => $response]);
break;
case 'get_trim_boats':
checkLoggedIn();
$users = db_get_data($mysqli, DB_TABLE_TRIM_USERS, 'boat', '`user`="' . $user_id . '"');
$boats = implode(',', array_column($users, 'boat'));
if ($boats == '') {
done(DONE_OKAY, array('data' => [], 'keys' => []));
}
$response = db_get_data($mysqli, DB_TABLE_TRIM_BOATS, '*', '`id` IN (' . $boats . ')' . ($whereString ? (' AND ' . $whereString) : ''));
if ($response === false) done(DONE_DATABASE);
$keys = array_keys($response);
if (isset($_REQUEST['changed-after'])) {
$response = db_get_data($mysqli, DB_TABLE_TRIM_BOATS, '*', '`id` IN (' . $boats . ') AND `changed` > "' . mysqli_real_escape_string($mysqli, date('Y-m-d H:i:s', $_REQUEST['changed-after'])) . '"' . ($whereString ? (' AND ' . $whereString) : ''));
if ($response === false) done(DONE_DATABASE);
}
$response = array_values($response);
done(DONE_OKAY, array('data' => replaceChanged($response), 'keys' => $keys));
break;
case 'get_trim_boat':
checkLoggedIn();
checkRequest('id');
$response = db_get_data($mysqli, DB_TABLE_TRIM_BOATS, '*', '`id` = "' . mysqli_real_escape_string($mysqli, $_REQUEST['id']) . '"');
if ($response === false) done(DONE_DATABASE);
if (count($response) != 1) done(DONE_BAD_REQUEST, ['error' => 'id not found']);
$response = array_values($response)[0];
if (count(db_get_data($mysqli, DB_TABLE_TRIM_USERS, 'id', '`user`="' . $user_id . '" AND `boat`="' . $response['id'] . '"')) != 1)
done(DONE_BAD_REQUEST, ['error' => 'id not found']);
unset($response['changed']);
done(DONE_OKAY, ['data' => $response]);
break;
case 'get_trim_users':
checkLoggedIn();
$users = db_get_data($mysqli, DB_TABLE_TRIM_USERS, 'boat', '`user`="' . $user_id . '"');
$boats = implode(',', array_column($users, 'boat'));
if ($boats == '') {
done(DONE_OKAY, array('data' => [], 'keys' => []));
}
$response = db_get_data($mysqli, DB_TABLE_TRIM_USERS, '*', '`boat` IN (' . $boats . ')' . ($whereString ? (' AND ' . $whereString) : ''));
if ($response === false) done(DONE_DATABASE);
$keys = array_keys($response);
if (isset($_REQUEST['changed-after'])) {
$response = db_get_data($mysqli, DB_TABLE_TRIM_USERS, '*', '`boat` IN (' . $boats . ') AND `changed` > "' . mysqli_real_escape_string($mysqli, date('Y-m-d H:i:s', $_REQUEST['changed-after'])) . '"' . ($whereString ? (' AND ' . $whereString) : ''));
if ($response === false) done(DONE_DATABASE);
}
$response = array_values($response);
done(DONE_OKAY, array('data' => replaceChanged($response), 'keys' => $keys));
break;
case 'get_trim_user':
checkLoggedIn();
checkRequest('id');
$response = db_get_data($mysqli, DB_TABLE_TRIM_USERS, '*', '`id` = "' . mysqli_real_escape_string($mysqli, $_REQUEST['id']) . '"');
if ($response === false) done(DONE_DATABASE);
if (count($response) != 1) done(DONE_BAD_REQUEST, ['error' => 'id not found']);
$response = array_values($response)[0];
if (count(db_get_data($mysqli, DB_TABLE_TRIM_USERS, 'id', '`user`="' . $user_id . '" AND `boat`="' . $response['boat'] . '"')) != 1)
done(DONE_BAD_REQUEST, ['error' => 'id not found']);
unset($response['changed']);
done(DONE_OKAY, ['data' => $response]);
break;
case 'get_trim_trims':
checkLoggedIn();
$users = db_get_data($mysqli, DB_TABLE_TRIM_USERS, 'boat', '`user`="' . $user_id . '"');
$boats = implode(',', array_column($users, 'boat'));
if ($boats == '') {
done(DONE_OKAY, array('data' => [], 'keys' => []));
}
$response = db_get_data($mysqli, DB_TABLE_TRIM_TRIMS, '*', '`boat` IN (' . $boats . ')' . ($whereString ? (' AND ' . $whereString) : ''));
if ($response === false) done(DONE_DATABASE);
$keys = array_keys($response);
if (isset($_REQUEST['changed-after'])) {
$response = db_get_data($mysqli, DB_TABLE_TRIM_TRIMS, '*', '`boat` IN (' . $boats . ') AND `changed` > "' . mysqli_real_escape_string($mysqli, date('Y-m-d H:i:s', $_REQUEST['changed-after'])) . '"' . ($whereString ? (' AND ' . $whereString) : ''));
if ($response === false) done(DONE_DATABASE);
}
$response = array_values($response);
done(DONE_OKAY, array('data' => replaceChanged($response), 'keys' => $keys));
break;
case 'get_trim_trim':
checkLoggedIn();
checkRequest('id');
$response = db_get_data($mysqli, DB_TABLE_TRIM_TRIMS, '*', '`id` = "' . mysqli_real_escape_string($mysqli, $_REQUEST['id']) . '"');
if ($response === false) done(DONE_DATABASE);
if (count($response) != 1) done(DONE_BAD_REQUEST, ['error' => 'id not found']);
$response = array_values($response)[0];
if (count(db_get_data($mysqli, DB_TABLE_TRIM_USERS, 'id', '`user`="' . $user_id . '" AND `boat`="' . $response['boat'] . '"')) != 1)
done(DONE_BAD_REQUEST, ['error' => 'id not found']);
unset($response['changed']);
done(DONE_OKAY, ['data' => $response]);
break;
case 'get_users':
$followFields = '';
for ($i = 1; $i <= 5; $i ++) $followFields .= ',' . BOATCLASS . '_sailor' . $i . ' AS sailor' . $i;
$response = db_get_data($mysqli, DB_TABLE_USERS, 'id,username,email' . $followFields, $whereString);
if ($response === false) done(DONE_DATABASE);
$keys = array_keys($response);
if (isset($_REQUEST['changed-after'])) {
$response = db_get_data($mysqli, DB_TABLE_USERS, 'id,username,email,' . $followFields, '`changed` > "' . mysqli_real_escape_string($mysqli, date('Y-m-d H:i:s', $_REQUEST['changed-after'])) . '"' . ($whereString ? (' AND ' . $whereString) : ''));
if ($response === false) done(DONE_DATABASE);
}
$response = array_map(function ($entry) {
global $user_id;
if ($entry['id'] != $user_id) {
$entry = ['id' => $entry['id'], 'username' => $entry['username']];
}
return $entry;
}, $response);
$response = array_values($response);
done(DONE_OKAY, array('data' => replaceChanged($response), 'keys' => $keys));
break;
case 'get_user':
checkRequest('id');
$followFields = '';
for ($i = 1; $i <= 5; $i ++) $followFields .= ',' . BOATCLASS . '_sailor' . $i . ' AS sailor' . $i;
$response = db_get_data($mysqli, DB_TABLE_USERS, 'id,username,email' . $followFields, '`id` = "' . mysqli_real_escape_string($mysqli, $_REQUEST['id']) . '"');
if ($response === false) done(DONE_DATABASE);
if (count($response) != 1) done(DONE_BAD_REQUEST, ['error' => 'id not found']);
$response = array_values($response)[0];
if ($response['id'] != $user_id) {
$response = ['id' => $response['id'], 'username' => $response['username']];
}
unset($response['changed']);
done(DONE_OKAY, ['data' => $response]);
break;
case 'add_subscription':
checkRequest('subscription');
$data = [
'auth' => PUSH_AUTH,
'subscription' => $_REQUEST['subscription']
];
$ch = curl_init('https://push.ostertun.net/add_subscription');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result = curl_exec($ch);
curl_close($ch);
if ($result == "OK")
done(DONE_OKAY);
else {
logE('add_subscription', $result);
done(DONE_SERVER_ERROR);
}
break;
case 'remove_subscription':
checkRequest('subscription');
$data = [
'auth' => PUSH_AUTH,
'subscription' => $_REQUEST['subscription']
];
$ch = curl_init('https://push.ostertun.net/remove_subscription');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result = curl_exec($ch);
curl_close($ch);
if ($result == "OK")
done(DONE_OKAY);
else {
logE('remove_subscription', $result);
done(DONE_SERVER_ERROR);
}
break;
default:
done(DONE_BAD_REQUEST, ['error' => 'action invalid']);
}
?>

View File

@@ -1,107 +0,0 @@
<?php
function get_user($mysqli, $username = null) {
if ($username === null) {
return db_get_data($mysqli, DB_TABLE_USERS);
} else {
$user = db_get_data($mysqli, DB_TABLE_USERS, '*', '`username` = "' . mysqli_real_escape_string($mysqli, $username) . '"', 1);
if (($user === false) or (count($user) != 1)) return false;
return array_values($user)[0];
}
}
function get_user_by_id($mysqli, $user_id) {
$res = db_get_data($mysqli, DB_TABLE_USERS, '*', '`id` = "' . mysqli_real_escape_string($mysqli, $user_id) . '"', 1);
if (($res !== false) and (count($res) == 1)) {
return array_values($res)[0];
}
return false;
}
//function signup($mysqli, $username, $email, $password) {
// if (($username == '') or ($email == '') or ($password == '')) {
// return 1;
// }
// if (get_user($mysqli, $username) !== false) {
// return 1;
// }
// $salt = hash('sha512', uniqid(openssl_random_pseudo_bytes(16), true));
// $hashpassword = hash('sha512', $password . $salt);
//
// $user = array();
// $user['username'] = $username;
// $user['email'] = $email;
// $user['password'] = $hashpassword;
// $user['salt'] = $salt;
// if (db_insert_data($mysqli, DB_TABLE_USERS, $user) !== false) {
// $values = array();
// $values['USERNAME'] = $username;
// $message = createMail('signup', STRING_SIGNUP_EMAIL_SUBJECT, $values);
// smtp_send_mail(['Regatten.net', MAIL_FROM_ADDRESS], [[$username, $email]], [], [], STRING_SIGNUP_EMAIL_SUBJECT, $message, [['Content-Type', 'text/html; charset="UTF-8"']]);
// // Analytics
// matomo_event('Login', 'SignUp', $username);
// return true;
// } else {
// return 2;
// }
//}
function get_perm($mysqli, $user_id) {
if ($user_id !== false) {
$result = get_user_by_id($mysqli, $user_id);
if ($result !== false) {
return $result[DB_FIELD_PERM];
} else {
return 0;
}
} else {
return 0;
}
}
// ### NEW LOGIN ####################################
function auth_login($mysqli, $username, $password, $device) {
$user = get_user($mysqli, $username);
if ($user === false) {
// User does not exist
return false;
}
$hashpassword = hash('sha512', $password . $user['salt']);
if ($hashpassword !== $user['password']) {
// Password incorrect
return false;
}
// All correct
$auth = [];
$auth['user'] = $user['id'];
$auth['username'] = $user['username'];
$auth['auth'] = str_replace('/', '-', str_replace('+', '_', base64_encode(openssl_random_pseudo_bytes(24))));
$salt = base64_encode(openssl_random_pseudo_bytes(24));
$hash = hash('sha512', $auth['auth'] . $salt);
$data = [
'user' => $user['id'],
'salt' => $salt,
'authhash' => $hash,
'device' => $device
];
$auth['id'] = db_insert_data($mysqli, DB_TABLE_LOGINS, $data);
return $auth;
}
function auth_logout($mysqli, $id) {
db_delete_data($mysqli, DB_TABLE_LOGINS, 'id = "' . mysqli_real_escape_string($mysqli, $id) . '"', 1);
return true;
}
function auth_check($mysqli, $id, $hash) {
$auth = db_get_data($mysqli, DB_TABLE_LOGINS, '*', 'id="' . mysqli_real_escape_string($mysqli, $id) . '"', 1);
if (($auth === false) or (count($auth) != 1)) return false;
$auth = array_values($auth)[0];
$hash = hash('sha512', $hash . $auth['salt']);
if ($hash != $auth['authhash']) return false;
db_update_data($mysqli, DB_TABLE_LOGINS, ['id' => $auth['id']], 'id="' . $auth['id'] . '"', 1); // update changed field => last login
return $auth['user'];
}
?>

View File

@@ -188,7 +188,7 @@ $(document).ready(function(){
});
//Generating Cookies
function createCookie(e, t, n) {if (n) {var o = new Date;o.setTime(o.getTime() + 48 * n * 60 * 3600 * 1e3);var r = "; expires=" + o.toGMTString()} else var r = "";document.cookie = e + "=" + t + r + "; path=/"}
function createCookie(e, t, n) {if (n) {var o = new Date;o.setTime(o.getTime() + n * 365 * 24 * 3600 * 1e3);var r = "; expires=" + o.toGMTString()} else var r = "";document.cookie = e + "=" + t + r + "; path=/"}
function readCookie(e) {for (var t = e + "=", n = document.cookie.split(";"), o = 0; o < n.length; o++) {for (var r = n[o];" " == r.charAt(0);) r = r.substring(1, r.length);if (0 == r.indexOf(t)) return r.substring(t.length, r.length)}return null}
function eraseCookie(e) {createCookie(e, "", -1)}
@@ -215,8 +215,8 @@ $(document).ready(function(){
}
},150);
})
if (readCookie('sticky_dark_mode')) {darkSwitch.prop('checked', true); $('body').removeClass('detect-theme').removeClass('theme-light').addClass('theme-dark');}
if (readCookie('sticky_light_mode')) {darkSwitch.prop('checked', false); $('body').removeClass('detect-theme').removeClass('theme-dark').addClass('theme-light');}
if (readCookie('sticky_dark_mode')) {createCookie('sticky_dark_mode', true, 1); darkSwitch.prop('checked', true); $('body').removeClass('detect-theme').removeClass('theme-light').addClass('theme-dark');}
if (readCookie('sticky_light_mode')) {createCookie('sticky_light_mode', true, 1); darkSwitch.prop('checked', false); $('body').removeClass('detect-theme').removeClass('theme-dark').addClass('theme-light');}
//Auto Dark Mode
@@ -1331,6 +1331,20 @@ $(document).ready(function(){
colorsArray.forEach(function (gradientBodyValue) {$('.generated-styles').append('.body-'+gradientBodyValue[0]+'{background-image: linear-gradient(to bottom, '+gradientBodyValue[1]+' 0, '+gradientBodyValue[3]+' 100%)}')});
}
function welcomeOk() {
createCookie('sticky_welcome_banner', true, 1);
$('#menu-welcome').hideMenu();
$('.menu-hider').removeClass('no-click');
}
function showWelcome() {
if (!readCookie('sticky_welcome_banner')) {
$('.menu-hider').addClass('no-click');
$('#menu-welcome').showMenu();
}
}
$('#menu-welcome-a-okay').click(welcomeOk);
showWelcome();
initRegatten();
hideLoader();

View File

@@ -1,4 +1,4 @@
const DB_VERSION = 3;
const DB_VERSION = 6;
const USER_ID = localStorage.getItem('auth_user');
const USER_NAME = localStorage.getItem('auth_username');
@@ -256,6 +256,167 @@ function dbGetResultCalculated(regatta) {
});
}
function dbGetRanking(minDate, maxDate, jugend, jugstrict) {
return new Promise(async function(resolve) {
var rankNoResults = [];
var sailors = await dbGetData('sailors');
var regattas = await dbGetRegattasRange(minDate, maxDate);
var sailorIds = {};
for (s in sailors) {
sailorIds[sailors[s].id] = s;
}
for (var i in sailors) {
sailors[i].regattas = {};
sailors[i].tmp_rlp = [];
}
for (var i in regattas) {
var regatta = regattas[i];
// regatta has to be min. 2 days to be ranking regatta
if (regatta.length < 2) continue;
var results = await dbGetDataIndex('results', 'regatta', regatta.id);
if (results.length <= 0) {
if (regatta.dateTo <= getToday()) {
if (regatta.canceled == '0') {
rankNoResults.push(regatta);
}
}
continue;
}
// in one race there must be at least 10 boats started
var ok = false;
for (var j = 1; j <= regatta.races; j ++) {
var temp = 0;
for (var r in results) {
if ((results[r]['race' + j] != 'DNC') && (results[r]['race' + j] != 'DNS')) {
temp ++;
}
}
if (temp >= 10) {
ok = true;
break;
}
}
if (!ok) continue;
var fb = regatta.finishedBoats;
// calc m
var m;
if (regatta.m > 0) {
m = regatta.m;
} else if (regatta.races <= 4) {
m = regatta.races;
} else {
if ((regatta.length > 2) && (regatta.races >= 6)) {
m = 5;
} else {
m = 4;
}
}
// add regatta to each sailor
for (var r in results) {
var result = results[r];
if (result.rlp == 0) continue;
// check if crew is youth
// TODO: not used
sailors[sailorIds[result.steuermann]].regattas[regatta.id] = {
regatta: regatta.id,
boat: result.boat,
crew: result.crew,
place: result.place,
fb: fb,
rlp: result.rlp,
used: 0,
m: m
};
for (var j = 0; j < m; j ++) {
sailors[sailorIds[result.steuermann]].tmp_rlp.push([regatta.id, result.rlp]);
}
}
}
// remove not german or not youth sailors
for (var i = sailors.length - 1; i >= 0; i --) {
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))) ||
((sailors[i].year == null) && (jugstrict))) {
sailors.splice(i, 1);
}
}
}
for (var i = sailors.length - 1; i >= 0; i --) {
// sort rlps desc
sailors[i].tmp_rlp.sort(function (a,b) {
return b[1] - a[1];
});
// calc mean rlp
var sum = 0;
var cnt = 0;
for (var t in sailors[i].tmp_rlp) {
var r = sailors[i].tmp_rlp[t];
sum += parseFloat(r[1]);
sailors[i].regattas[r[0]].used ++;
cnt ++;
if (cnt >= 9) break;
}
delete sailors[i].tmp_rlp;
if (cnt > 0) {
var rlp = sum / cnt;
sailors[i].rlp = rlp;
sailors[i].m = cnt;
} else {
sailors.splice(i, 1);
}
}
sailors.sort(function (a,b) {
if (a.m != b.m) return b.m - a.m;
return b.rlp - a.rlp;
});
for (var i = 0; i < sailors.length; i ++) {
sailors[i].rank = (i + 1);
}
resolve([sailors, rankNoResults]);
});
}
function dbSettingsGet(key) {
return new Promise(function(resolve) {
if (canUseLocalDB) {
var request = db.transaction('settings').objectStore('settings').get(key);
request.onsuccess = function (event) {
resolve(typeof request.result != 'undefined' ? request.result.value : null);
}
} else {
resolve(null);
}
});
}
function dbSettingsSet(key, value) {
if (canUseLocalDB) {
var os = db.transaction('settings', 'readwrite').objectStore('settings');
os.put({ key: key, value: value});
}
}
async function updateSyncStatus() { // TODO
// var syncStatus = document.getElementById('syncstatus');
// var lastSync = await dbGetData('update_times', 'last_sync');
@@ -283,7 +444,21 @@ async function updateSyncStatus() { // TODO
async function runPageScript() {
if (canUseLocalDB) {
var osUpdateTimes = db.transaction('update_times').objectStore('update_times');
osUpdateTimes.get('loggedin').onsuccess = function (event) {
var status = event.target.result.status;
if (status != isLoggedIn()) {
resetDb();
location.reload();
}
};
updateSyncStatus();
if (isLoggedIn()) {
var plannings = await dbGetDataIndex('plannings', 'user', USER_ID);
plannings = plannings.map(function (e) { return e.regatta; });
dbSettingsSet('myregattas_' + BOATCLASS, plannings);
}
}
if (typeof updateSyncStatusTimer == 'undefined') { // TODO
// var syncStatus = document.getElementById('syncstatus');
@@ -291,6 +466,7 @@ async function runPageScript() {
updateSyncStatusTimer = window.setInterval(updateSyncStatus, 10000);
} else {
// syncStatus.innerHTML = 'Keine Offline-Nutzung möglich.';
$('#i-sync').parent().hide();
updateSyncStatusTimer = null;
}
// syncStatus.style.display = 'block';
@@ -315,7 +491,7 @@ function sync() {
localTimes[entry['table']] = entry['time'];
});
syncInProgress = 10;
syncInProgress = 11;
var syncOkay = true;
console.log("Sync Start");
$('#i-sync').addClass('fa-spin');
@@ -332,6 +508,9 @@ function sync() {
$('#i-sync').removeClass('fa-spin');
}, 500);
if (typeof onAfterSync === 'function') {
onAfterSync();
}
runPageScript();
}
}, 100);
@@ -341,7 +520,7 @@ function sync() {
// CLUBS
if (localTimes['clubs'] < serverTimes['clubs']) {
getJSON(QUERY_URL + 'get_clubs?changer-after=' + localTimes['clubs'], function (code, data) {
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);
@@ -373,7 +552,7 @@ function sync() {
// BOATS
if (localTimes['boats'] < serverTimes['boats']) {
getJSON(QUERY_URL + 'get_boats?changer-after=' + localTimes['boats'], function (code, data) {
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);
@@ -405,7 +584,7 @@ function sync() {
// SAILORS
if (localTimes['sailors'] < serverTimes['sailors']) {
getJSON(QUERY_URL + 'get_sailors?changer-after=' + localTimes['sailors'], function (code, data) {
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);
@@ -437,7 +616,7 @@ function sync() {
// REGATTAS
if (localTimes['regattas'] < serverTimes['regattas']) {
getJSON(QUERY_URL + 'get_regattas?changer-after=' + localTimes['regattas'], function (code, data) {
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);
@@ -485,7 +664,7 @@ function sync() {
// RESULTS
if (localTimes['results'] < serverTimes['results']) {
getJSON(QUERY_URL + 'get_results?changer-after=' + localTimes['results'], function (code, data) {
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);
@@ -517,7 +696,7 @@ function sync() {
// PLANNINGS
if (localTimes['plannings'] < serverTimes['plannings']) {
getJSON(QUERY_URL + 'get_plannings?changer-after=' + localTimes['plannings'], function (code, data) {
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);
@@ -550,7 +729,7 @@ function sync() {
if (isLoggedIn()) {
// TRIM_BOATS
if (localTimes['trim_boats'] < serverTimes['trim_boats']) {
getJSON(QUERY_URL + 'get_trim_boats?changer-after=' + localTimes['trim_boats'], function (code, data) {
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);
@@ -582,7 +761,7 @@ function sync() {
// TRIM_USERS
if (localTimes['trim_users'] < serverTimes['trim_users']) {
getJSON(QUERY_URL + 'get_trim_users?changer-after=' + localTimes['trim_users'], function (code, data) {
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);
@@ -614,7 +793,7 @@ function sync() {
// TRIM_TRIMS
if (localTimes['trim_trims'] < serverTimes['trim_trims']) {
getJSON(QUERY_URL + 'get_trim_trims?changer-after=' + localTimes['trim_trims'], function (code, data) {
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);
@@ -648,9 +827,41 @@ function sync() {
syncInProgress -= 3;
}
// NEWS
if (localTimes['news'] < serverTimes['news']) {
getJSON(QUERY_URL + 'get_news?changed-after=' + localTimes['news'], function (code, data) {
if (code == 200) {
var os = db.transaction('news', 'readwrite').objectStore('news');
console.log(data);
data.data.forEach(function (entry) {
os.put(entry);
});
os.openCursor().onsuccess = function (event) {
var cursor = event.target.result;
if (cursor) {
if (!data.keys.includes(parseInt(cursor.key))) {
os.delete(cursor.key);
}
cursor.continue();
} else {
var osUpdateTimes = db.transaction('update_times', 'readwrite').objectStore('update_times');
osUpdateTimes.put({ table: 'news', time: serverTimes['news'] });
syncInProgress --;
}
};
} else {
console.log("Something went wrong (HTTP " + code + ")");
syncOkay = false;
syncInProgress --;
}
});
} else {
syncInProgress --;
}
// USERS
if (localTimes['users'] < serverTimes['users']) {
getJSON(QUERY_URL + 'get_users?changer-after=' + localTimes['users'], function (code, data) {
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);
@@ -728,10 +939,14 @@ function initDatabase() {
canUseLocalDB = true;
if (typeof onDatabaseLoaded == 'function') onDatabaseLoaded();
db.transaction('update_times').objectStore('update_times').get('last_sync').onsuccess = function (event) {
var lastSync = event.target.result.time;
if (lastSync > 0) {
runPageScript();
} else {
db.transaction('update_times', 'readwrite').objectStore('update_times').put({ table: 'loggedin', status: isLoggedIn() });
}
};
@@ -795,6 +1010,24 @@ function initDatabase() {
osUpdateTimes.put({ table: 'regattas', time: 0 });
}
if ((oldVersion < 4) && (newVersion >= 4)) {
console.log('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');
var osPushes = db.createObjectStore('settings', { keyPath: 'key' });
}
if ((oldVersion < 6) && (newVersion >= 6)) {
console.log('to version 6');
var osNews = db.createObjectStore('news', { keyPath: 'id' });
var osUpdateTimes = upgradeTransaction.objectStore('update_times');
osUpdateTimes.add({ table: 'news', time: 0 });
}
var osUpdateTimes = upgradeTransaction.objectStore('update_times');
osUpdateTimes.put({ table: 'last_sync', time: 0 });
}
@@ -802,3 +1035,24 @@ function initDatabase() {
runPageScript();
}
}
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: 'clubs', time: 0 });
osUpdateTimes.put({ table: 'boats', time: 0 });
osUpdateTimes.put({ table: 'sailors', time: 0 });
osUpdateTimes.put({ table: 'regattas', time: 0 });
osUpdateTimes.put({ table: 'results', time: 0 });
osUpdateTimes.put({ table: 'plannings', time: 0 });
osUpdateTimes.put({ table: 'trim_boats', time: 0 });
osUpdateTimes.put({ table: 'trim_users', time: 0 });
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');
hideLoader();
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -2,13 +2,16 @@
header('Content-Type: text/javascript');
require_once(__DIR__ . '/../../server/version.php');
require_once(__DIR__ . '/../../server/config.php');
?>
//Loading the Service Worker
var swRegistration = null;
if ('serviceWorker' in navigator) {
window.addEventListener('load', function() {
navigator.serviceWorker.register('<?php echo SERVER_ADDR; ?>/service-worker.js.php');
window.addEventListener('load', async function() {
swRegistration = await navigator.serviceWorker.register('<?php echo SERVER_ADDR; ?>/service-worker.js.php');
if (typeof onServiceWorkerLoaded === 'function') onServiceWorkerLoaded();
});
}
@@ -25,7 +28,7 @@ $(document).ready(function(){
//Creating Cookie System for PWA Hide
function createCookie(e, t, n) {if (n) {var o = new Date;o.setTime(o.getTime() + 48 * n * 60 * 60 * 1e3);var r = "; expires=" + o.toGMTString()} else var r = "";document.cookie = e + "=" + t + r + "; path=/"}
function createCookie(e, t, n) {if (n) {var o = new Date;o.setTime(o.getTime() + n * 365 * 24 * 3600 * 1e3);var r = "; expires=" + o.toGMTString()} else var r = "";document.cookie = e + "=" + t + r + "; path=/"}
function readCookie(e) {for (var t = e + "=", n = document.cookie.split(";"), o = 0; o < n.length; o++) {for (var r = n[o];" " == r.charAt(0);) r = r.substring(1, r.length);if (0 == r.indexOf(t)) return r.substring(t.length, r.length)}return null}
function eraseCookie(e) {createCookie(e, "", -1)}

View File

@@ -6,9 +6,12 @@
?>
const QUERY_URL = '<?php echo SERVER_ADDR; ?>/api/';
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 randomId = function() { return '_' + Math.random().toString(36).substr(2, 9); }
@@ -67,7 +70,7 @@ var updateBadge = function (name, val) {
var makeToast = function (color, icon, text, time) {
var id = 'snackbar' + randomId();
var delay = (time > 0 ? 'data-delay="' + time + '" data-autohide="true"' : 'data-autohide="false"');
var div = '<div id="' + id + '" class="snackbar-toast ' + color + '" ' + delay + '>';
var div = '<div id="' + id + '" class="snackbar-toast pt-3 pb-3 ' + color + '" ' + delay + ' style="line-height: 2em;">';
div += '<i class="fa ' + icon + ' mr-3"></i>' + text + '</div>';
$('#page').append(div);
$('#' + id).toast('show');
@@ -119,8 +122,8 @@ var login = function() {
showLoader();
var username = $('#input-login-username').val();
var password = $('#input-login-password').val();
$('#input-login-username').val('');
$('#input-login-password').val('');
$('#input-login-username').val('').trigger('focusin').trigger('focusout');
$('#input-login-password').val('').trigger('focusin').trigger('focusout');
$.ajax({
url: QUERY_URL + 'login',
method: 'POST',
@@ -132,7 +135,7 @@ var login = function() {
error: function (xhr, status, error) {
if (xhr.status == 401) {
toastError('Benutzername oder Passwort falsch');
$('#input-login-username').val(username);
$('#input-login-username').val(username).trigger('focusin').trigger('focusout');
} else if (xhr.status == 0) {
toastError('Du bist momentan offline.<br>Stelle eine Internetverbindung her, um Dich anzumelden');
$('#menu-login').hideMenu();
@@ -200,27 +203,28 @@ var logout = function() {
});
}
function resetDb() {
function deleteDb() {
$('#menu-developer').hideMenu();
if (canUseLocalDB) {
showLoader();
var request = window.indexedDB.deleteDatabase('regatten_app_db_' + BOATCLASS);
request.onerror = function (event) {
console.log("Cannot open DB: " + event.target.errorCode);
toastError('There was an error deleting your database.<br>Please report this to <a href="mailto:dev@regatten.net">dev@regatten.net</a>');
hideLoader();
};
request.onsuccess = function (event) {
console.log('DB deleted');
toastInfo('The database was deleted. Please reload or close this tab.<br>At the next visit, a new database will be created.');
console.log('Cannot delete DB: ', event.target.errorCode);
toastError('Beim Löschen der Datenbank ist ein Fehler aufgetreten.<br>Bitte melde diesen Fehler. (Dev-Menu => Problem melden)', 5000);
hideLoader();
}
request.onsuccess = function (event) {
console.log('DB deleted');
toastInfo('Die Datenbank wurde gelöscht. Die Seite lädt in wenigen Sekunden neu und erstellt damit eine neue Datenbank.', 10000);
hideLoader();
setTimeout(function(){ location.reload(); }, 3000);
}
} else {
toastWarn('Your device does not support storing data locally. All data is fetched directly from our server.<br>As a result, you can not reset your database.');
toastWarn('Dein Gerät unterstützt kein lokales Speichern der Daten. Alle Daten werden direkt vom Server gezogen.<br>Entsprechend kannst Du die Datenbank auch nicht zurücksetzen.', 10000);
}
}
function resetCache() {
function deleteCache() {
$('#menu-developer').hideMenu();
navigator.serviceWorker.getRegistrations().then(function (registrations) {
for (let registration of registrations) {
@@ -234,7 +238,190 @@ function resetCache() {
return caches.delete(key);
}));
});
toastInfo('The serviceWorker and the cache were deleted. A new serviceWorker will be generated on the next refresh.');
toastInfo('Der serviceWorker und alle Caches wurden gelöscht. Die Seite lädt in wenigen Sekunden neu und erstellt damit neue Caches.', 10000);
setTimeout(function(){ location.reload(); }, 3000);
}
var pushesPossible = false;
function urlB64ToUint8Array(base64String) {
const padding = '='.repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, '+')
.replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function pushesSubscribe() {
console.log('Subscribing');
const applicationServerKey = urlB64ToUint8Array(PUSH_SERVER_KEY);
swRegistration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: applicationServerKey
})
.then(function(subscription) {
pushesUpdateServerSubscription(subscription, true);
updatePushSwitches();
updatePushBadge();
})
.catch(function(err) {
console.log('Failed to subscribe the user: ', err);
toastError('Da ist leider etwas schief gelaufen. Bitte stelle sicher, dass Du mit dem Internet verbunden bist und versuche es erneut.', 5000);
pushesUnSubscribe(true);
});
}
function pushesUnSubscribe(silent = false) {
console.log('Unsubscribing');
swRegistration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
pushesUpdateServerSubscription(subscription, false);
subscription.unsubscribe();
$('#menu-pushes').hideMenu();
updatePushBadge();
hideLoader();
}
})
.catch(function(error) {
console.log('Error unsubscribing', error);
$('#menu-pushes').hideMenu();
if (!silent) toastError('Da ist leider etwas schief gelaufen. Bitte versuche es erneut oder wende Dich an unseren Support.', 5000);
updatePushBadge();
hideLoader();
});
}
function pushesUpdateServerSubscription(subscription, enabled) {
console.log('updateServer', enabled, subscription);
$.ajax({
url: QUERY_URL + (enabled ? 'add' : 'remove') + '_subscription',
type: 'POST',
data: { subscription: JSON.stringify(subscription) },
success: function (data, textStatus, jqXHR) {
if (!enabled) {
toastOk('Du erhältst ab sofort keine Benachrichtigungen mehr von uns.');
}
hideLoader();
},
error: function (jqXHR, textStatus, errorThrown) {
throw 'Cannot update server subscription';
}
});
}
async function initPushSettings() {
var items = [
['notify_channel_' + BOATCLASS + '_news', true],
['notify_channel_' + BOATCLASS + '_regatta_changed_my', true],
['notify_channel_' + BOATCLASS + '_regatta_changed_all', false],
['notify_channel_' + BOATCLASS + '_result_ready_my', true],
['notify_channel_' + BOATCLASS + '_result_ready_all', true],
['notify_channel_' + BOATCLASS + '_meldeschluss', true]
];
for (var i in items) {
var item = items[i];
if ((await dbSettingsGet(item[0])) == null) dbSettingsSet(item[0], item[1]);
}
}
async function updatePushSwitches() {
$('#switch-pushes-news').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_news'));
$('#switch-pushes-regatta-changed-my').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_regatta_changed_my'));
$('#switch-pushes-regatta-changed-all').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_regatta_changed_all'));
$('#switch-pushes-result-ready-my').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_result_ready_my'));
$('#switch-pushes-result-ready-all').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_result_ready_all'));
$('#switch-pushes-meldeschluss').prop('checked', await dbSettingsGet('notify_channel_' + BOATCLASS + '_meldeschluss'));
if ($('#switch-pushes').prop('checked')) {
$('#p-pushes-info').show();
$('.a-switch-pushes-channel-all').show();
$('.a-switch-pushes-channel-my').show();
if (!isLoggedIn()) {
$('.a-switch-pushes-channel-my').find('div').remove();
$('.a-switch-pushes-channel-my').find('.badge').text('nicht angemeldet');
}
} else {
$('#p-pushes-info').hide();
$('.a-switch-pushes-channel-all').hide();
$('.a-switch-pushes-channel-my').hide();
}
}
function pushesSubscribeClicked() {
showLoader();
if ($('#switch-pushes').prop('checked')) {
pushesSubscribe();
} else {
pushesUnSubscribe();
}
}
function pushesChannelClicked() {
dbSettingsSet('notify_channel_' + BOATCLASS + '_news', $('#switch-pushes-news').prop('checked'));
dbSettingsSet('notify_channel_' + BOATCLASS + '_regatta_changed_my', $('#switch-pushes-regatta-changed-my').prop('checked'));
dbSettingsSet('notify_channel_' + BOATCLASS + '_regatta_changed_all', $('#switch-pushes-regatta-changed-all').prop('checked'));
dbSettingsSet('notify_channel_' + BOATCLASS + '_result_ready_my', $('#switch-pushes-result-ready-my').prop('checked'));
dbSettingsSet('notify_channel_' + BOATCLASS + '_result_ready_all', $('#switch-pushes-result-ready-all').prop('checked'));
dbSettingsSet('notify_channel_' + BOATCLASS + '_meldeschluss', $('#switch-pushes-meldeschluss').prop('checked'));
}
function pushesOpenMenu() {
$('#menu-settings').hideMenu();
if (!pushesPossible) {
toastWarn('Dein Browser unterst&uuml;tzt leider keine Benachrichtigungen.', 5000);
return;
}
if (Notification.permission == 'denied') {
toastWarn('Benachrichtigungen werden von Deinem Browser blockiert.', 5000);
return;
}
swRegistration.pushManager.getSubscription().then(function(subscription) {
var isSub = (subscription !== null);
$('#switch-pushes').prop('checked', isSub);
updatePushSwitches();
$('#menu-pushes').showMenu();
});
}
function updatePushBadge() {
if (!pushesPossible) return;
if (Notification.permission == 'denied') {
$('#badge-pushes').removeClass('bg-green2-dark').addClass('bg-red2-dark').text('BLOCKED');
return;
}
swRegistration.pushManager.getSubscription().then(function(subscription) {
var isSub = (subscription !== null);
if (isSub) {
$('#badge-pushes').removeClass('bg-red2-dark').addClass('bg-green2-dark').text('AN');
} else {
$('#badge-pushes').removeClass('bg-green2-dark').addClass('bg-red2-dark').text('AUS');
}
});
}
async function updateNewsBadge() {
var newsRead = await dbSettingsGet('news_read_' + BOATCLASS);
if (newsRead === null) dbSettingsSet('news_read_' + BOATCLASS, newsRead = new Date());
var news = await dbGetData('news');
var now = new Date();
var sum = 0;
for (var n in news) {
var newsEntry = news[n];
newsEntry.date = new Date(Date.parse(newsEntry.date));
if (newsEntry.date > now) continue;
if (newsEntry.date < newsRead) continue;
sum ++;
}
updateBadge('more/news', sum);
}
var initRegatten = function() {
@@ -253,4 +440,51 @@ var initRegatten = function() {
$('.show-loggedin').hide();
$('.show-notloggedin').show();
}
// Pushes
$('#a-switch-pushes').click(pushesSubscribeClicked);
$('.a-switch-pushes-channel-all').click(pushesChannelClicked);
$('.a-switch-pushes-channel-my').click(pushesChannelClicked);
}
var onServiceWorkerLoaded = function() {
if ((swRegistration !== null) && canUseLocalDB) {
pushesPossible = true;
updatePushBadge();
} else {
$('#badge-pushes').removeClass('bg-green2-dark').addClass('bg-red2-dark').text('NOT SUPPORTED');
}
}
var onDatabaseLoaded = function() {
onServiceWorkerLoaded();
initPushSettings();
updateNewsBadge();
}
var onAfterSync = function() {
updateNewsBadge();
}
// Add console opener to preloader
var addConsoleOpenerToPreloader = function() {
addConsoleOpenerToPreloader = function(){};
var preloader = document.getElementById('preloader');
var button = document.createElement('a');
button.href = '#';
button.classList = 'btn btn-full rounded-s text-uppercase font-900 shadow-m bg-highlight m-3';
button.style.position = 'fixed';
button.style.bottom = 0;
button.style.left = 0;
button.style.right = 0;
button.innerHTML = 'Show Console';
button.onclick = function(){
mobileConsole.displayConsole();
return false;
}
setTimeout(function(){
preloader.appendChild(button);
}, 5000);
}
addConsoleOpenerToPreloader();

View File

@@ -43,6 +43,143 @@
text-align: right;
}
/*** RANKING LIST ***/
.ranking-list > div {
padding-top: 1rem;
padding-bottom: 1rem;
border-bottom: 1px solid #dee2e6;
cursor: pointer;
}
.ranking-list > div:last-child {
border: 0;
padding-bottom: 0;
}
.ranking-list div {
white-space: nowrap;
}
.ranking-list > div > div > div {
display: inline-block;
}
.ranking-list > div > div:nth-child(1) > div:nth-child(1) {
width: 25%;
}
.ranking-list > div > div:nth-child(1) > div:nth-child(2) {
width: 50%;
text-align: right;
}
.ranking-list > div > div:nth-child(1) > div:nth-child(3) {
width: 25%;
text-align: right;
}
.ranking-list > div > div:nth-child(2) > div:nth-child(1) {
width: 75%;
}
.ranking-list > div > div:nth-child(2) > div:nth-child(2) {
width: 25%;
text-align: right;
}
/*** RANKING DETAIL LIST ***/
.ranking-detail-list > div {
padding-top: 1rem;
padding-bottom: 1rem;
border-bottom: 1px solid #dee2e6;
cursor: pointer;
}
.ranking-detail-list > div:last-child {
border: 0;
padding-bottom: 0;
}
.ranking-detail-list div {
white-space: nowrap;
}
.ranking-detail-list > div > div > div {
display: inline-block;
}
.ranking-detail-list > div > div:nth-child(2) > div:nth-child(1) {
width: 50%;
}
.ranking-detail-list > div > div:nth-child(2) > div:nth-child(2) {
width: 25%;
text-align: right;
}
.ranking-detail-list > div > div:nth-child(2) > div:nth-child(3) {
width: 25%;
text-align: right;
}
.ranking-detail-list > div > div:nth-child(3) {
border-bottom: 1px dashed #dee2e6;
}
.ranking-detail-list > div > div:nth-child(3) > div:nth-child(1) {
width: 50%;
}
.ranking-detail-list > div > div:nth-child(3) > div:nth-child(2) {
width: 50%;
text-align: right;
}
.ranking-detail-list > div > div:nth-child(4) > div:nth-child(1) {
width: 50%;
}
.ranking-detail-list > div > div:nth-child(4) > div:nth-child(2) {
width: 50%;
text-align: right;
}
.ranking-detail-list > div > div:nth-child(n+5) > div:nth-child(1) {
width: 75%;
}
.ranking-detail-list > div > div:nth-child(n+5) > div:nth-child(2) {
width: 25%;
text-align: right;
}
/*** NORMAL LIST ***/
.normal-list > div {
padding-top: 1rem;
padding-bottom: 1rem;
border-bottom: 1px solid #dee2e6;
cursor: pointer;
}
.normal-list > div:last-child {
border: 0;
padding-bottom: 0;
}
.normal-list div {
white-space: nowrap;
}
.normal-list > div > div > div {
display: inline-block;
}
.normal-list > div > div:nth-child(2) > div:nth-child(1) {
width: 50%;
}
.normal-list > div > div:nth-child(2) > div:nth-child(2) {
width: 50%;
text-align: right;
}
/*** BLOCKQUOTE ***/
blockquote {
border-left: 0.5em solid rgba(0, 0, 0, 0.125);
font-style: italic;
padding-left: 1em;
}
/*** BLINKING ICONS ***/
@keyframes fa-blink {
0% { opacity: 1; }

View File

@@ -1220,6 +1220,7 @@ img.mx-auto {
bottom: 0px;
z-index: 99999;
transition: all 150ms ease;
background-color: #0f1117;
}
#preloader .spinner-border {
@@ -4253,7 +4254,7 @@ code {
}
/*Contact Form*/
.menu input[type="text"] {
/*.menu input[type="text"] {
height: 35px;
line-height: 35px;
}
@@ -4270,7 +4271,7 @@ code {
.menu .form-field label {
font-size: 12px;
margin-bottom: -10px;
}
}*/
.form-field span {
position: absolute;

View File

@@ -1,5 +1,6 @@
<?php
require_once(__DIR__ . '/server/version.php');
require_once(__DIR__ . '/server/config.php');
require_once(__DIR__ . '/server/log.php');
require_once(__DIR__ . '/server/templates.php');
@@ -24,7 +25,7 @@
exit;
}
if (!file_exists(__DIR__ . '/content/' . $site . '.php')) {
if (!file_exists(__DIR__ . '/server/content/' . $site . '.php')) {
$site = '404';
}
@@ -40,7 +41,7 @@
$tpl = new Templates(__DIR__ . '/server/templates/');
$scripts = new Scripts(__DIR__ . '/server/scripts/');
require_once(__DIR__ . '/content/' . $site . '.php');
require_once(__DIR__ . '/server/content/' . $site . '.php');
require_once(__DIR__ . '/server/buildpage.php');

View File

@@ -2,6 +2,7 @@
header('Content-Type: application/json');
require_once(__DIR__ . '/server/version.php');
require_once(__DIR__ . '/server/config.php');
?>

View File

@@ -4,20 +4,18 @@
error_reporting(0); // disable error reporting in browser
define('SEND_ERRORS', true); // send errors via log
define('BOATCLASS', 'pirat');
date_default_timezone_set('Europe/Berlin');
define('SERVER_PATH', '/subfolder'); // path to root directory
define('SERVER_ADDR', 'https://' . $_SERVER['SERVER_NAME'] . SERVER_PATH); // path to root directory
define('QUERY_URL', 'http://' . $_SERVER['SERVER_NAME'] . '/api/' . BOATCLASS . '/'); // url to api backend
define('LOGGING_APIKEY', 'xxx'); // Apikey for Logging API -> get from ostertun.net/logging
define('PWA_VERSION', '1.0');
// PUSH
define('PUSH_SERVER_KEY', '');
// PUSH SERVER
define('PUSH_AUTH', 'xxxxxxx'); // auth string for push.ostertun.net
define('PUSH_SERVERKEY', 'xxxxxxx'); // server key from push.ostertun.net
define('BOATCLASS', 'pirat');
// BOAT CLASSES
// BOAT CLASS
$_CLASS = array(
'name' => 'Pirat',
'desc' => 'eine vom DSV gef&ouml;rderte Jugendmeisterschaftsklasse',

View File

@@ -1,6 +1,6 @@
<?php
$sp['title'] = 'Fehler 404 - Regatten.net Pirat';
$sp['title'] = 'Fehler 404 - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$content = $tpl->load('error', ['404', 'Seite nicht gefunden']);

View File

@@ -0,0 +1,19 @@
<?php
// TODO: Create site
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$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' => 'text-center pt-3']);
?>

46
server/content/boats.php Normal file
View File

@@ -0,0 +1,46 @@
<?php
$sp['title'] = 'Boote - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = 'index';
$sp['activenav'] = 4;
// Title
$content = "<h1>Boote</h1>";
$sp['output'] .= $tpl->load('card', [$content]);
// Info Years
$content = '<h2>Bootsnamen</h2>';
$content .= '<p>';
$content .= 'Genauso wie bei den Jahrg&auml;ngen der Segler fehlen uns auch viele Bootsnamen.<br>';
$content .= 'Kennst Du ein Boot, dessen Name hier noch nicht hinterlegt ist oder das vielleicht umgetauft wurde, <b>hilf uns bitte</b>, indem Du den Namen eintr&auml;gst!<br>';
$content .= 'Klicke dazu einfach auf das entsprechende Boot und w&auml;hle Bootsnamen bearbeiten aus.<br>';
$content .= 'Vielen Dank f&uuml;r Deine Unterst&uuml;tzung!';
$content .= '</p>';
$sp['output'] .= $tpl->load('card', [$content]);
// List
$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-list" class="normal-list mb-0"></div>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-list']);
// Pagination
$sp['output'] .= $tpl->load('pagination', ['html-id' => 'pagination']);
// Menu
$items = $tpl->load('menu/item-icon', ['', '#', 'html-id' => 'menu-item-boatname', '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-boat', 'title' => 'Boots-Details', 'height' => 200]);
$items = '<p class="mb-2 mt-1" style="line-height: 1.5em;">Bitte trage hier den Bootsnamen ein:</p>';
$items .= $tpl->load('input', ['html-id' => 'input-editboatname', 'placeholder' => 'Bootsname', 'type' => 'text']);
$items .= $tpl->load('button', ['Speichern', '#', 'html-id' => 'button-editboatname']);
$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-editboatname', 'height' => 240]);
$sp['scripts'] .= $scripts->load('pagination', ['pageChange', 'page', 'pageCount', 'pagination']);
$sp['scripts'] .= $scripts->load('boats');
?>

65
server/content/calc.php Normal file
View File

@@ -0,0 +1,65 @@
<?php
$sp['title'] = 'RLP Rechner - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = 'index';
$sp['activenav'] = 5;
// Title
$content = "<h1>RLP Rechner</h1>";
$content .= '<p>Einfach Ranglistenpunkte berechnen</p>';
$sp['output'] .= $tpl->load('card', [$content]);
// Inputs
$content = $tpl->load('input', ['html-id' => 'input-rlf', 'placeholder' => 'Ranglistenfaktor (rlf)', 'type' => 'number']);
$content .= $tpl->load('input', ['html-id' => 'input-m', 'placeholder' => 'Multiplikator (m)', 'type' => 'number']);
$content .= $tpl->load('input', ['html-id' => 'input-fb', 'placeholder' => 'Gezeitete Boote (fb)', 'type' => 'number']);
$content .= $tpl->load('input', ['html-id' => 'input-pl', 'placeholder' => 'Platzierung (pl)', 'type' => 'number']);
$content .= $tpl->load('button', ['Hinzuf&uuml;gen', '#', 'html-id' => 'button-add']);
$sp['output'] .= $tpl->load('card', [$content]);
// Table
$thead = '<tr><th>RLF</th><th>m</th><th>fb</th><th>pl</th><th>RLP</th><th></th></tr>';
$content = $tpl->load('table', [$thead, 'html-id' => 'table-races']);
$content .= '<p id="p-result"></p>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-races']);
// Infos
$content = '<h2>Hinweise zum Ausf&uuml;llen</h2>';
$content .= '<p><b>Ranglistenfaktor (RLF)</b><br>';
$content .= 'Der Ranglistenfaktor ist ein von der KV vorgegebener Faktor zwischen 1,0 und 1,6 zur Gewichtung der Regatten.<br>';
$content .= 'Du findest ihn in der <a href="' . LINK_PRE . 'regattas">Regatten-Liste</a>.';
$content .= '</p>';
$content .= '<p><b>Multiplikator (m)</b><br>';
$content .= 'Der Multiplikator gibt an, wie oft eine Regatta in die Wertung eingeht.<br>';
$content .= 'Er ist abh&auml;ngig von den tats&auml;chlich gesegelten Wettfahrten. Dabei gilt:<br>';
$content .= '<b>1</b> Wettfahrt => <b>m = 1</b><br>';
$content .= '<b>2</b> Wettfahrten => <b>m = 2</b><br>';
$content .= '<b>3</b> Wettfahrten => <b>m = 3</b><br>';
$content .= '<b>4 oder mehr</b> Wettfahrten => <b>m = 4</b><br>';
$content .= 'Ist die Regatta f&uuml;r mehr als 2 Tage ausgeschrieben, gilt au&szlig;erdem:<br>';
$content .= '<b>6 oder mehr</b> Wettfahrten => <b>m = 5</b>';
$content .= '</p>';
$content .= '<p><b>Gezeitete Boote (fb)</b><br>';
$content .= 'Die Anzahl der Boote, die in mindestens einer Wettfahrt ins Ziel gefahren sind.';
$content .= '</p>';
$content .= '<p><b>Platzierung (pl)</b><br>';
$content .= 'Deine Platzierung in den Endergebnissen';
$content .= '</p>';
$sp['output'] .= $tpl->load('card', [$content]);
$content = '<h2>Berechnung</h2>';
$content .= '<p>Die Ranglistenpunkte (RLP) f&uuml;r eine Regatta berechnen sich nach folgender Formel:<br>';
$content .= '<i>RLP = RLF * 100 * ((fb + 1 - pl) / fb)</i><br>';
$content .= 'Diese Ranglistenpunkte k&ouml;nnen je nach Multiplikator bis zu 5 mal in die Wertung eingehen.<br>';
$content .= 'Der Mittelwert der 9 besten Wertungen ergibt die Ranglistenpunkte.';
$content .= '</p>';
$sp['output'] .= $tpl->load('card', [$content]);
$sp['scripts'] .= $scripts->load('calc');
?>

29
server/content/clubs.php Normal file
View File

@@ -0,0 +1,29 @@
<?php
$sp['title'] = 'Vereine - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = 'index';
$sp['activenav'] = 4;
// Title
$content = "<h1>Vereine</h1>";
$sp['output'] .= $tpl->load('card', [$content]);
// List
$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-list" class="normal-list mb-0"></div>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-list']);
// Pagination
$sp['output'] .= $tpl->load('pagination', ['html-id' => 'pagination']);
// Menu
$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-club', 'title' => 'Vereins-Details', 'height' => 160]);
$sp['scripts'] .= $scripts->load('pagination', ['pageChange', 'page', 'pageCount', 'pagination']);
$sp['scripts'] .= $scripts->load('clubs');
?>

View File

@@ -0,0 +1,38 @@
<?php
$sp['title'] = 'Kontakt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$sp['activenav'] = 5;
// TITLE
$content = '<h1>Kontakt</h1>';
$sp['output'] .= $tpl->load('card', [$content]);
// Info
$content = '<p>';
$content .= 'Du hast eine Frage? Du hast einen Fehler in unserer Software oder in den gespeicherten Daten gefunden? Du willst Regatten.net auch f&uuml;r Deine Bootsklasse nutzen?<br>';
$content .= 'Egal was es ist, lass es uns wissen! Schreibe uns eine Mail an <a href="mailto:info@regatten.net">info@regatten.net</a> oder nutze einfach dieses Kontakt-Formular.<br>';
$content .= 'Wir werden Deine Anfrage so schnell wie m&ouml;glich bearbeiten.';
$content .= '</p>';
$content .= '<p>';
$content .= 'Alternativ erreichst Du uns auch telefonisch unter <a href="tel:+4941039659768">+49 (0) 4103 965 976 8</a><br>';
$content .= 'Mo-Fr: 7-20 Uhr<br>';
$content .= 'Sa: 9-17 Uhr';
$content .= '</p>';
$sp['output'] .= $tpl->load('card', [$content]);
// Formular
$content = '<h2>Kontakt-Formular</h2>';
$content .= $tpl->load('input', ['html-id' => 'input-name', 'placeholder' => 'Dein Name', 'type' => 'text']);
$content .= $tpl->load('input', ['html-id' => 'input-email', 'placeholder' => 'Email-Adresse', 'type' => 'email']);
$content .= $tpl->load('input', ['html-id' => 'input-subject', 'placeholder' => 'Betreff', 'type' => 'text']);
$content .= $tpl->load('textarea', ['html-id' => 'input-message', 'placeholder' => 'Deine Nachricht']);
$content .= $tpl->load('button', ['Senden', '#', 'html-id' => 'button-send']);
$sp['output'] .= $tpl->load('card', [$content]);
$sp['scripts'] .= $scripts->load('contact');
?>

View File

@@ -1,6 +1,6 @@
<?php
$sp['title'] = 'Startseite - Regatten.net Pirat';
$sp['title'] = 'Startseite - Regatten.net ' . $_CLASS['name'];
$sp['activenav'] = 1;
// Title
@@ -22,8 +22,7 @@
// Planning next
$content = '<h2>Deine n&auml;chsten Regatten</h2>';
$thead = '<tr><th>Datum</th><th>Regatta</th><th>Informationen</th><th>RLF</th><th>Segler</th></tr>';
$content .= $tpl->load('table', [$thead, 'html-id' => 'table-yournext', 'css-class' => 'mb-0 mt-3']);
$content .= '<div id="div-yournext" class="regattas-list mb-0"></div>';
$content .= '<p id="p-yournext" class="mt-3">';
$content .= 'Du f&auml;hrst in den n&auml;chsten vier Wochen auf keine Regatta!';
$content .= '</p>';
@@ -41,8 +40,7 @@
// Next
$content = '<h2>N&auml;chste Regatten</h2>';
$thead = '<tr><th>Datum</th><th>Regatta</th><th>Informationen</th><th>RLF</th></tr>';
$content .= $tpl->load('table', [$thead, 'html-id' => 'table-next', 'css-class' => 'mb-0 mt-3']);
$content .= '<div id="div-next" class="regattas-list mb-0"></div>';
$content .= '<p id="p-next" class="mt-3">';
$content .= 'Keine Regatten in den n&auml;chsten zwei Wochen!';
$content .= '</p>';
@@ -51,8 +49,7 @@
// Last
$content = '<h2>Letzte Regatten</h2>';
$thead = '<tr><th>Datum</th><th>Regatta</th><th>Ergebnisse</th><th>RLF</th></tr>';
$content .= $tpl->load('table', [$thead, 'html-id' => 'table-last', 'css-class' => 'mb-0 mt-3']);
$content .= '<div id="div-last" class="regattas-list mb-0"></div>';
$content .= '<p id="p-last" class="mt-3">';
$content .= 'Keine Regatten in den letzten zwei Wochen!';
$content .= '</p>';
@@ -63,14 +60,26 @@
$content = '<h2>Regatta-Kalender</h2>';
$content .= '<p>Du willst alle Regatta-Termine in deinem Kalender, aber nicht alles abtippen?<br>Kein Problem! Abonniere einfach unseren ics-Kalender.</p>';
$content .= '<p><b>Nur die Regatten, zu denen Du gehst?</b><br>Auch kein Problem! ';
$content .= '<span class="show-loggedin">Erstelle einfach eine <a href="' . LINK_PRE . 'planning">Saison-Planung</a> und abonniere Deinen persönlichen Kalender.</span>';
$content .= '<span class="show-notloggedin"><a href="#" data-menu="menu-signup">Registriere Dich einfach kostenlos</a>, erstelle eine Saison-Planung und wir erstellen Dir einen pers&ouml;nlichen Kalender.</span>';
$content .= '<font class="show-loggedin">Erstelle einfach eine <a href="' . LINK_PRE . 'planning">Saison-Planung</a> und abonniere Deinen persönlichen Kalender.</font>';
$content .= '<font class="show-notloggedin"><a href="#" data-menu="menu-signup">Registriere Dich einfach kostenlos</a>, erstelle eine Saison-Planung und wir erstellen Dir einen pers&ouml;nlichen Kalender.</font>';
$content .= '</p>';
$content .= $tpl->load('button', ['<i class="fas fa-calendar-alt"></i> Regatta-Kalender', 'https://regatten.net/client/calendar/' . BOATCLASS . '/everything.ics', 'css-class' => 'mb-2']);
$content .= $tpl->load('button', ['<i class="fas fa-calendar-alt"></i> Kalender f&uuml;r <span class="replace-username"></span>', 'https://regatten.net/client/calendar/' . BOATCLASS . '/user_%USERID%.ics', 'css-class' => 'show-loggedin replace-userid-href']);
$content .= $tpl->load('button', ['<i class="fas fa-calendar-alt"></i> Kalender f&uuml;r <font class="replace-username"></font>', 'https://regatten.net/client/calendar/' . BOATCLASS . '/user_%USERID%.ics', 'css-class' => 'show-loggedin replace-userid-href']);
$sp['output'] .= $tpl->load('card', [$content]);
$sp['scripts'] = $scripts->load('index');
// Regattas Menu
$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('index');
?>

22
server/content/news.php Normal file
View File

@@ -0,0 +1,22 @@
<?php
$sp['title'] = 'News - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$sp['activenav'] = 5;
// Title
$content = "<h1>Neuigkeiten</h1>";
$content .= '<p>Aktuelles der letzten zw&ouml;lf Monate</p>';
$sp['output'] .= $tpl->load('card', [$content]);
// Menu
$sp['menus'] .= $tpl->load('menu/modal', ['html-id' => 'menu-news', 'title' => 'Details']);
$cardTemplate = $tpl->load('card', ['%CONTENT%', 'html-id' => '%ID%', 'css-class' => 'card-news']);
$cardTemplate = str_replace("\n", '', $cardTemplate);
$cardTemplate = str_replace("\r", '', $cardTemplate);
$sp['scripts'] .= "<script>const cardTemplate = '" . $cardTemplate . "';</script>";
$sp['scripts'] .= $scripts->load('news');
?>

View File

@@ -0,0 +1,19 @@
<?php
// TODO: Create site
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$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' => 'text-center pt-3']);
?>

View File

@@ -0,0 +1,19 @@
<?php
// TODO: Create site
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$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' => 'text-center pt-3']);
?>

View File

@@ -0,0 +1,19 @@
<?php
// TODO: Create site
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$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' => 'text-center pt-3']);
?>

View File

@@ -0,0 +1,19 @@
<?php
// TODO: Create site
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$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' => 'text-center pt-3']);
?>

46
server/content/rank.php Normal file
View File

@@ -0,0 +1,46 @@
<?php
$sp['title'] = 'Ranglisten - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = 'index';
$sp['activenav'] = 3;
// Title, Inputs
$content = "<h1>Ranglisten</h1>";
$options = '<option value="year">Jahres-Rangliste</option>';
$options .= '<option value="youth">Jugend-Rangliste</option>';
$options .= '<option value="idjm">' . $_CLASS['youth-german-name'] . '-Rangliste</option>';
$options .= '<option value="user">Benutzerdefiniert</option>';
$content .= $tpl->load('select', ['html-id' => 'select-type', 'placeholder' => 'Rangliste', 'options' => $options, 'css-class' => 'mt-3 mb-0']);
$content .= $tpl->load('select', ['html-id' => 'select-year', 'placeholder' => 'Jahr', 'css-class' => 'mt-3 mb-0']);
$content .= $tpl->load('input', ['html-id' => 'input-from', 'placeholder' => 'Von', 'type' => 'date', 'css-class' => 'mt-3']);
$content .= $tpl->load('input', ['html-id' => 'input-to', 'placeholder' => 'Bis', 'type' => 'date']);
$chbox = $tpl->load('checkbox', ['html-id' => 'input-jugend', 'placeholder' => 'Jugend']);
$content .= '<div class="mb-3" style="display:inline-block; width:50%;">' . $chbox . '</div>';
$chbox = $tpl->load('checkbox', ['html-id' => 'input-jugstrict', 'placeholder' => 'Streng']);
$content .= '<div class="mb-3" style="display:inline-block; width:50%;">' . $chbox . '</div>';
$content .= $tpl->load('button', ['Anzeigen', '#', 'html-id' => 'button-show']);
$sp['output'] .= $tpl->load('card', [$content]);
// No Results
$content = '<h2 class="color-white">ACHTUNG</h2>';
$content .= '<p class="color-white">Zu folgenden Regatten wurden noch keine Ergebnisse hinterlegt:</p>';
$content .= '<ul id="ul-noresults"></ul>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-noresults', 'css-class' => 'bg-red2-dark']);
// Ranking
$content = $tpl->load('input', ['html-id' => 'input-search', 'placeholder' => 'Suche', 'type' => 'text']);
$content .= '<div id="div-rank" class="ranking-list mb-0"></div>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-rank']);
// Menu
$items = '<p id="menu-item-text" class="mb-2 mt-1" style="line-height: 1.5em;"></p>';
$items .= '<div id="div-details" class="ranking-detail-list mb-3" style="line-height: 2em;"></div>';
$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-rank', 'title' => 'Ranglisten-Details', 'height' => 500]);
$sp['scripts'] .= $scripts->load('rank');
?>

View File

@@ -0,0 +1,31 @@
<?php
$sp['title'] = 'Saison-Planung - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = 'regattas';
$sp['activenav'] = 2;
// Title, Inputs
$content = '<h1 id="h1-title"></h1>';
$content .= '<p id="p-title"></p>';
$sp['output'] .= $tpl->load('card', [$content]);
// Plannings
$content = '<p id="p-info" class="mb-0"></p>';
$thead = '<tr><th>Benutzer</th><th>Steuermann/-frau</th><th>Crew</th></tr>';
$content .= $tpl->load('table', [$thead, 'html-id' => 'table-plannings', 'css-class' => 'mb-0 text-nowrap']);
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-plannings']);
// Info
$content = '<p>Du planst, hier hinzufahren, aber stehst nicht auf dieser Liste?<br>';
$content .= 'Das kannst Du &auml;ndern! ';
$content .= '<font class="show-loggedin">Erstelle einfach <a href="' . LINK_PRE . 'planning">hier</a> Deine eigene Saison-Planung.</font>';
$content .= '<font class="show-notloggedin"><a href="#" data-menu="menu-login">Melde Dich an</a> oder <a href="#" data-menu="menu-signup">registriere Dich kostenlos</a> und erstelle Deine eigene Saison-Planung.</font>';
$content .= '</p>';
$sp['output'] .= $tpl->load('card', [$content]);
$sp['scripts'] .= $scripts->load('regatta_plan');
?>

View File

@@ -1,6 +1,6 @@
<?php
$sp['title'] = 'Regatten - Regatten.net Pirat';
$sp['title'] = 'Regatten - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = 'index';
$sp['activenav'] = 2;
@@ -22,7 +22,9 @@
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-regattas']);
// Menu
$items = $tpl->load('menu/item-icon', ['Ergebnisse', '', 'html-id' => 'menu-item-results', 'icon' => 'fa-poll']);
$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']);
@@ -30,6 +32,7 @@
$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('regattas');
?>

21
server/content/result.php Normal file
View File

@@ -0,0 +1,21 @@
<?php
$sp['title'] = 'Ergebnisse - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$sp['activenav'] = 2;
// Title, Inputs
$content = '<h1 id="h1-title"></h1>';
$content .= '<p id="p-title"></p>';
$sp['output'] .= $tpl->load('card', [$content]);
// Results
$content = '<p id="p-info" class="mb-0"></p>';
$content .= $tpl->load('table', ['html-id' => 'table-results', 'css-class' => 'mb-0 text-nowrap']);
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-results']);
$sp['scripts'] .= $scripts->load('result');
?>

View File

@@ -0,0 +1,46 @@
<?php
$sp['title'] = 'Segler - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = 'index';
$sp['activenav'] = 4;
// Title
$content = "<h1>Segler</h1>";
$sp['output'] .= $tpl->load('card', [$content]);
// Info Years
$content = '<h2>Jahrg&auml;nge</h2>';
$content .= '<p>';
$content .= 'Zu vielen Seglern fehlen uns leider noch die Jahrg&auml;nge. Diese ben&ouml;tigen wir jedoch, um die Ranglisten vern&uuml;nftig zu erstellen.<br>';
$content .= 'Solltest Du jemanden kennen, dessen Jahrgang hier in der Liste noch nicht hinterlegt ist oder der wom&ouml;glich falsch ist, <b>hilf uns bitte</b>, indem Du diesen eintr&auml;gst!<br>';
$content .= 'Klicke dazu einfach auf den entsprechenden Segler und w&auml;hle Jahrgang bearbeiten aus.<br>';
$content .= 'Vielen Dank f&uuml;r Deine Unterst&uuml;tzung!';
$content .= '</p>';
$sp['output'] .= $tpl->load('card', [$content]);
// List
$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-list" class="normal-list mb-0"></div>';
$sp['output'] .= $tpl->load('card', [$content, 'html-id' => 'card-list']);
// Pagination
$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-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]);
$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']);
$items .= $tpl->load('button', ['Speichern', '#', 'html-id' => 'button-edityear']);
$sp['menus'] .= $tpl->load('menu/bottom', [$items, 'html-id' => 'menu-edityear', 'height' => 240]);
$sp['scripts'] .= $scripts->load('pagination', ['pageChange', 'page', 'pageCount', 'pagination']);
$sp['scripts'] .= $scripts->load('sailors');
?>

View File

@@ -0,0 +1,19 @@
<?php
// TODO: Create site
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$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' => 'text-center pt-3']);
?>

View File

@@ -0,0 +1,19 @@
<?php
// TODO: Create site
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$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' => 'text-center pt-3']);
?>

View File

@@ -0,0 +1,19 @@
<?php
// TODO: Create site
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$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' => 'text-center pt-3']);
?>

View File

@@ -0,0 +1,19 @@
<?php
// TODO: Create site
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$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' => 'text-center pt-3']);
?>

View File

@@ -0,0 +1,19 @@
<?php
// TODO: Create site
$sp['title'] = 'Seite noch nicht unterstuuml;tzt - Regatten.net ' . $_CLASS['name'];
$sp['backbutton'] = true;
$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' => 'text-center pt-3']);
?>

View File

@@ -1,6 +1,6 @@
<!-- Install Prompt for Android -->
<div id="menu-install-pwa-android" class="menu menu-box-bottom menu-box-detached rounded-l"
data-menu-height="350"
data-menu-height="400"
data-menu-effect="menu-parallax">
<div class="boxed-text-l mt-4">
<img class="rounded-l mb-3" src="<?php echo SERVER_ADDR; ?>/client/app/icons/icon-128x128.png" alt="img" width="90">
@@ -17,7 +17,7 @@
<!-- Install instructions for iOS -->
<div id="menu-install-pwa-ios"
class="menu menu-box-bottom menu-box-detached rounded-l"
data-menu-height="320"
data-menu-height="360"
data-menu-effect="menu-parallax">
<div class="boxed-text-xl mt-4">
<img class="rounded-l mb-3" src="<?php echo SERVER_ADDR; ?>/client/app/icons/icon-128x128.png" alt="img" width="90">
@@ -26,7 +26,6 @@
Installiere Regatten.net auf Deinem Startbildschirm und greife wie bei einer normalen App darauf zu. &Ouml;ffne Dein Safari-Men&uuml; und tippe auf &quot;Zum Startbildschirm hinzuf&uuml;gen&quot;.
</p>
<div class="clear"></div>
<a href="#" class="pwa-dismiss close-menu color-highlight uppercase ultrabold opacity-80 top-25">Vielleicht sp&auml;ter</a>
<i class="fa-ios-arrow fa fa-caret-down font-40"></i>
<a href="#" class="pwa-dismiss close-menu color-highlight text-uppercase font-900 opacity-60 font-10">Vielleicht sp&auml;ter</a>
</div>
</div>

View File

@@ -92,7 +92,7 @@
</div>
</div>
<div id="menu-settings" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="270">
<div id="menu-settings" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="310">
<div class="menu-title"><h1>Einstellungen</h1><p class="color-highlight">&nbsp;</p><a href="#" class="close-menu"><i class="fa fa-times"></i></a></div>
<div class="divider divider-margins mb-n2"></div>
<div class="content">
@@ -110,7 +110,7 @@
<span>Login</span>
<i class="fa fa-angle-right"></i>
</a>
<a href="#" data-menu="menu-signup" class="show-notloggedin border-0">
<a href="#" data-menu="menu-signup" class="show-notloggedin">
<i class="fa font-14 fa-user-plus rounded-s bg-highlight color-white"></i>
<span>Registrieren</span>
<span class="badge bg-red2-dark color-white">FREE</span>
@@ -120,40 +120,125 @@
<span>Account</span>
<i class="fa fa-angle-right"></i>
</a>
<a href="#" onclick="logout();" class="show-loggedin border-0">
<a href="#" onclick="logout();" class="show-loggedin">
<i class="fa font-14 fa-sign-out-alt rounded-s bg-highlight color-white"></i>
<span>Logout</span>
<i class="fa fa-angle-right"></i>
</a>
<a href="#" onclick="pushesOpenMenu()" class="border-0">
<i class="fa font-14 fa-bell rounded-s bg-highlight color-white"></i>
<span>Benachrichtigungen</span>
<span id="badge-pushes" class="badge color-white"></span>
<i class="fa fa-angle-right"></i>
</a>
</div>
</div>
</div>
<div id="menu-developer" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="310">
<div class="menu-title"><h1>Entwickler-Optionen</h1><p class="color-highlight">&nbsp;</p><a href="#" class="close-menu"><i class="fa fa-times"></i></a></div>
<div id="menu-pushes" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="500">
<div class="menu-title"><h1>Benachrichtigungen</h1><p class="color-highlight">Bleibe immer auf dem aktuellen Stand</p><a href="#" class="close-menu"><i class="fa fa-times"></i></a></div>
<div class="divider divider-margins mb-n2"></div>
<div class="content">
<div class="list-group list-custom-small">
<a href="https://info.ostertun.net/regatten/beta">
<a id="a-switch-pushes" href="#" data-trigger-switch="switch-pushes" class="pb-2">
<i class="fa font-14 fa-bell rounded-s bg-highlight color-white"></i>
<span>Benachrichtigungen aktivieren</span>
<div class="custom-control scale-switch ios-switch">
<input type="checkbox" class="ios-input" id="switch-pushes">
<label class="custom-control-label" for="switch-pushes"></label>
</div>
</a>
<div class="divider"></div>
<p style="line-height: 1.5em;" id="p-pushes-info">
W&auml;hle hier, &uuml;ber was Du informiert werden m&ouml;chtest.<br>
(meine) bezieht sich auf die Regatten, die in Deiner Saison-Planung sind,<br>
(alle) informiert Dich &uuml;ber alle Regatten
</p>
<a href="#" data-trigger-switch="switch-pushes-news" class="pb-2 a-switch-pushes-channel-all">
<i class="fa font-14 fa-newspaper rounded-s bg-highlight color-white"></i>
<span>Neuigkeiten</span>
<div class="custom-control scale-switch ios-switch">
<input type="checkbox" class="ios-input" id="switch-pushes-news">
<label class="custom-control-label" for="switch-pushes-news"></label>
</div>
</a>
<a href="#" data-trigger-switch="switch-pushes-regatta-changed-my" class="pb-2 a-switch-pushes-channel-my">
<i class="fa font-14 fa-calendar-check rounded-s bg-highlight color-white"></i>
<span>Regatta verschoben (meine)</span>
<span class="badge bg-red2-dark color-white"></span>
<div class="custom-control scale-switch ios-switch">
<input type="checkbox" class="ios-input" id="switch-pushes-regatta-changed-my">
<label class="custom-control-label" for="switch-pushes-regatta-changed-my"></label>
</div>
</a>
<a href="#" data-trigger-switch="switch-pushes-regatta-changed-all" class="pb-2 a-switch-pushes-channel-all">
<i class="fa font-14 fa-calendar-check rounded-s bg-highlight color-white"></i>
<span>Regatta verschoben (alle)</span>
<div class="custom-control scale-switch ios-switch">
<input type="checkbox" class="ios-input" id="switch-pushes-regatta-changed-all">
<label class="custom-control-label" for="switch-pushes-regatta-changed-all"></label>
</div>
</a>
<a href="#" data-trigger-switch="switch-pushes-result-ready-my" class="pb-2 a-switch-pushes-channel-my">
<i class="fa font-14 fa-poll rounded-s bg-highlight color-white"></i>
<span>Ergebnisse verf&uuml;gbar (meine)</span>
<span class="badge bg-red2-dark color-white"></span>
<div class="custom-control scale-switch ios-switch">
<input type="checkbox" class="ios-input" id="switch-pushes-result-ready-my">
<label class="custom-control-label" for="switch-pushes-result-ready-my"></label>
</div>
</a>
<a href="#" data-trigger-switch="switch-pushes-result-ready-all" class="pb-2 a-switch-pushes-channel-all">
<i class="fa font-14 fa-poll rounded-s bg-highlight color-white"></i>
<span>Ergebnisse verf&uuml;gbar (alle)</span>
<div class="custom-control scale-switch ios-switch">
<input type="checkbox" class="ios-input" id="switch-pushes-result-ready-all">
<label class="custom-control-label" for="switch-pushes-result-ready-all"></label>
</div>
</a>
<a href="#" data-trigger-switch="switch-pushes-meldeschluss" class="pb-2 a-switch-pushes-channel-my">
<i class="fa font-14 fa-file-signature rounded-s bg-highlight color-white"></i>
<span>Melde-Erinnerungen</span>
<span class="badge bg-red2-dark color-white"></span>
<div class="custom-control scale-switch ios-switch">
<input type="checkbox" class="ios-input" id="switch-pushes-meldeschluss">
<label class="custom-control-label" for="switch-pushes-meldeschluss"></label>
</div>
</a>
</div>
</div>
</div>
<div id="menu-developer" class="menu menu-box-bottom menu-box-detached rounded-m" data-menu-height="360">
<div class="menu-title"><h1>Entwickler-Optionen</h1><p class="color-highlight">Version <?php echo PWA_VERSION; ?></p><a href="#" class="close-menu"><i class="fa fa-times"></i></a></div>
<div class="divider divider-margins mb-n2"></div>
<div class="content">
<div class="list-group list-custom-small">
<a href="https://github.com/ostertun/RegattenApp/wiki">
<i class="fa font-14 fa-info rounded-s bg-highlight color-white"></i>
<span>Infos zur BETA</span>
<span>App-Wiki</span>
<i class="fa fa-angle-right"></i>
</a>
<a href="javascript:resetDb();">
<a href="javascript:deleteDb();">
<i class="fa font-14 fa-database rounded-s bg-highlight color-white"></i>
<span>Reset Database</span>
<i class="fa fa-angle-right"></i>
</a>
<a href="javascript:resetCache();">
<a href="javascript:deleteCache();">
<i class="fa font-14 fa-trash-alt rounded-s bg-highlight color-white"></i>
<span>Reset Cache</span>
<i class="fa fa-angle-right"></i>
</a>
<a href="https://report.regatten.net/" class="border-0">
<a href="https://github.com/ostertun/RegattenApp/issues">
<i class="fa font-14 fa-bug rounded-s bg-highlight color-white"></i>
<span>Problem melden</span>
<i class="fa fa-angle-right"></i>
</a>
<a href="#" onclick="mobileConsole.displayConsole(); return false;" class="border-0 menu-close">
<i class="fa font-14 fa-terminal rounded-s bg-highlight color-white"></i>
<span>Console anzeigen</span>
<i class="fa fa-angle-right"></i>
</a>
</div>
</div>
</div>
@@ -187,6 +272,25 @@
</div>
</div>
<div id="menu-welcome" class="menu menu-box-bottom" style="height: 70vh">
<div class="content bottom-0">
<h1 class="text-center font-900">Willkommen</h1>
<p>
Diese App befindet sich zur Zeit noch in der Entwicklungs-Phase.<br>
Dadurch kann es vorkommen, dass bestimmte Funktionen noch nicht richtig funktionieren.<br>
Wenn Dir etwas ungew&ouml;hnlich vorkommt, melde uns dies bitte. Klicke dazu auf das Entwickler-Icon oben links und w&auml;hle &quot;Problem melden&quot;.<br>
Vielen Dank f&uuml;r Deine Unterst&uuml;tzung!
</p>
<p>
Mehr Informationen findest Du <a href="https://info.ostertun.net/regatten/beta">hier</a>.
</p>
<p>
Mit der Nutzung dieser App erkl&auml;rst Du Dich au&szlig;erdem damit einverstanden, dass wir Cookies einsetzen.
</p>
<a id="menu-welcome-a-okay" class="btn btn-m mt-2 mb-3 btn-full bg-green2-dark text-uppercase font-900" href="#">Alles klar</a>
</div>
</div>
<div id="menu-update">
<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>

View File

@@ -2,6 +2,7 @@
<html lang="de">
<head>
<script type="text/javascript" src="<?php echo SERVER_ADDR; ?>/client/scripts/mobileconsole.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">

197
server/scripts/boats.js Normal file
View File

@@ -0,0 +1,197 @@
var firstCall = true;
var rows = [];
var displayed = [];
var page = 1;
var pageCount = 0;
const showCount = 25;
async function onEditBoatnameClick() {
var id = $('#button-editboatname').attr('data-boat-id');
var name = $('#input-editboatname').val();
if (name != '') {
showLoader();
$.ajax({
url: QUERY_URL + 'add_boatname',
method: 'POST',
data: {
boat: id,
name: name
},
error: function (xhr, status, error) {
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);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
hideLoader();
},
success: function (data, status, xhr) {
if ('status' in data) {
if (data.status == 'added') {
toastOk('Bootsnamen erfolgreich hinzugefügt');
sync();
} else {
toastInfo('Wir prüfen Deine Anfrage und korrigieren den Bootsnamen schnellstmöglich', 5000);
}
} else {
toastOk('Erfolgreich');
}
hideLoader();
}
});
}
$('#menu-editboatname').hideMenu();
}
async function onListClicked(id) {
var boat = await dbGetData('boats', id);
$('#menu-boat').find('.menu-title').find('p').text(boat.sailnumber);
// Edit Boatname
$('#button-editboatname').attr('data-boat-id', boat.id);
$('#menu-editboatname').find('.menu-title').find('p').text(boat.sailnumber);
if (boat['name'] == '') {
$('#menu-item-boatname').find('span').text('Bootsnamen hinzufügen');
$('#menu-editboatname').find('.menu-title').find('h1').text('Bootsnamen hinzufügen');
$('#input-editboatname').val('');
} else {
$('#menu-item-boatname').find('span').text('Bootsnamen bearbeiten');
$('#menu-editboatname').find('.menu-title').find('h1').text('Bootsnamen bearbeiten');
$('#input-editboatname').val(boat.name);
}
$('#input-editboatname').trigger('focusin').trigger('focusout');
// club website
var clubwebsite = '';
if (boat['club'] != null) {
clubwebsite = (await dbGetData('clubs', boat['club'])).website;
}
if (clubwebsite != '') {
$('#menu-item-clubwebsite').show();
$('#menu-item-clubwebsite').attr('href', clubwebsite);
$('#menu-item-clubwebsite').attr('target', '_blank');
} else {
$('#menu-item-clubwebsite').hide();
}
$('#menu-boat').showMenu();
$('#menu-boat').scrollTop(0);
}
function pageChange() {
$('#p-count')[0].scrollIntoView({ behavior: "smooth" });
drawList();
}
async function drawList() {
window.setTimeout(function () {
var list = '';
if (displayed.length > 0) {
var offset = (page - 1) * showCount;
var count = (page == pageCount ? (displayed.length % showCount) : showCount);
if (count == 0) count = showCount;
for (i = 0; i < count; i ++) {
list += displayed[i + offset];
}
} else {
list = '<div><div>Keine Ergebnisse, die der Suche entsprechen</div></div>';
}
$('#div-list').html(list);
}, 0);
}
async function reSearch() {
window.setTimeout(function () {
displayed = [];
rows.forEach(function (entry) {
if (search($('#input-search').val(), entry.keywords)) {
displayed.push(entry.content);
}
});
pageCount = Math.ceil(displayed.length / showCount);
if ((page < 1) || (page > pageCount)) {
if (page < 1) {
page = 1;
} else {
page = pageCount;
}
}
drawPagination();
drawList();
}, 0);
}
var siteScript = async function() {
if (firstCall) {
firstCall = false;
initPagination();
$('#input-search').on('input', reSearch);
$('#menu-item-boatname').click(function(){ $('#menu-boat').hideMenu(); $('#menu-editboatname').showMenu(); });
$('#button-editboatname').click(onEditBoatnameClick);
}
var results = await dbGetData('boats');
var count = results.length;
if (count > 0) {
if (count == 1) {
$('#p-count').html('Es wurde 1 Boot gefunden!');
} else {
$('#p-count').html('Es wurden ' + count + ' Boote gefunden!');
}
$('#div-list').show();
$('#input-search').parent().show();
results.sort(function (a, b) {
return a.sailnumber.localeCompare(b.sailnumber);
});
rows = [];
for (id in results) {
var entry = results[id];
var club = null;
if (entry['club'] != null)
club = await dbGetData('clubs', entry['club']);
var row = { keywords: [], content: '' };
row.keywords.push(entry['sailnumber']);
if (entry['name'] != '') row.keywords.push(entry['name']);
if (club != null) row.keywords.push(club['kurz'], club['name']);
row.content += '<div onclick="onListClicked(' + entry['id'] + ');">';
// ZEILE 1
// Sailnumber
row.content += '<div><b>' + entry['sailnumber'] + '</b></div>';
// ZEILE 2
row.content += '<div>';
// Name
row.content += '<div>' + entry['name'] + '</div>';
// Club
row.content += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
row.content += '</div></div>';
rows.push(row);
}
reSearch();
} else {
$('#p-count').html('Keine Boote gefunden!');
$('#div-list').hide();
$('#input-search').parent().hide();
}
hideLoader();
}

92
server/scripts/calc.js Normal file
View File

@@ -0,0 +1,92 @@
var races = [];
var firstCall = true;
function reCalc() {
setTimeout(function(){
if (races.length > 0) {
$('#card-races').show();
$('#p-result').text('Berechne...');
var rlps = [];
var tbody = '';
for (var i = 0; i < races.length; i ++) {
tbody += '<tr>';
tbody += '<td>' + races[i].rlf + '</td>';
tbody += '<td>' + races[i].m + '</td>';
tbody += '<td>' + races[i].fb + '</td>';
tbody += '<td>' + races[i].pl + '</td>';
tbody += '<td>' + races[i].rlp.toFixed(3) + '</td>';
tbody += '<td><a href="#" onclick="removeRace(' + i + ')" class="btn rounded-s text-uppercase font-900 shadow-m bg-highlight"><i class="fas fa-times"></i></a></td>';
tbody += '</tr>';
for (var j = 0; j < races[i].m; j ++) {
rlps.push(races[i].rlp);
}
}
$('#table-races').find('tbody').html(tbody);
rlps.sort(function (a,b) {
return b-a;
});
var sum = 0;
var cnt = Math.min(rlps.length, 9);
for (var i = 0; i < cnt; i ++) {
sum += rlps[i];
}
$('#p-result').html('<b>' + (sum / cnt).toFixed(3) + '</b> Punkte aus <b>' + cnt + '</b> Wertungen.');
} else {
$('#card-races').hide();
}
}, 0);
}
function addRace() {
var rlf = parseFloat($('#input-rlf').val().replace(',', '.'));
var m = parseFloat($('#input-m').val());
var fb = parseFloat($('#input-fb').val());
var pl = parseFloat($('#input-pl').val().replace(',', '.'));
if (isNaN(rlf) || (rlf < 1) || (rlf > 1.6)) {
toastError('RLF ungültig');
return;
}
if (isNaN(m) || (m < 1) || (m > 5)) {
toastError('m ungültig');
return;
}
if (isNaN(fb) || (fb < 1)) {
toastError('fb ungültig');
return;
}
if (isNaN(pl) || (pl < 1) || (pl > (fb + 1))) {
toastError('pl ungültig');
return;
}
var race = {
rlf: rlf,
m: m,
fb: fb,
pl: pl,
rlp: (100 * rlf * ((fb + 1 - pl) / fb))
};
$('#input-rlf').val('').trigger('focusin').trigger('focusout');
$('#input-m').val('').trigger('focusin').trigger('focusout');
$('#input-fb').val('').trigger('focusin').trigger('focusout');
$('#input-pl').val('').trigger('focusin').trigger('focusout');
races.push(race);
reCalc();
}
function removeRace(id) {
if ((id >= 0) && (id < races.length)) races.splice(id, 1);
reCalc();
}
var siteScript = async function () {
if (firstCall) {
firstCall = false;
$('#button-add').click(addRace);
}
reCalc();
hideLoader();
}

136
server/scripts/clubs.js Normal file
View File

@@ -0,0 +1,136 @@
var firstCall = true;
var rows = [];
var displayed = [];
var page = 1;
var pageCount = 0;
const showCount = 25;
async function onListClicked(id) {
var club = await dbGetData('clubs', id);
$('#menu-club').find('.menu-title').find('p').text(club.name);
// club website
if (club.website != '') {
$('#menu-item-clubwebsite').show();
$('#menu-item-clubwebsite').attr('href', club.website);
$('#menu-item-clubwebsite').attr('target', '_blank');
} else {
$('#menu-item-clubwebsite').hide();
}
$('#menu-club').showMenu();
$('#menu-club').scrollTop(0);
}
function pageChange() {
$('#p-count')[0].scrollIntoView({ behavior: "smooth" });
drawList();
}
async function drawList() {
window.setTimeout(function () {
var list = '';
if (displayed.length > 0) {
var offset = (page - 1) * showCount;
var count = (page == pageCount ? (displayed.length % showCount) : showCount);
if (count == 0) count = showCount;
for (i = 0; i < count; i ++) {
list += displayed[i + offset];
}
} else {
list = '<div><div>Keine Ergebnisse, die der Suche entsprechen</div></div>';
}
$('#div-list').html(list);
}, 0);
}
async function reSearch() {
window.setTimeout(function () {
displayed = [];
rows.forEach(function (entry) {
if (search($('#input-search').val(), entry.keywords)) {
displayed.push(entry.content);
}
});
pageCount = Math.ceil(displayed.length / showCount);
if ((page < 1) || (page > pageCount)) {
if (page < 1) {
page = 1;
} else {
page = pageCount;
}
}
drawPagination();
drawList();
}, 0);
}
var siteScript = async function() {
if (firstCall) {
firstCall = false;
initPagination();
$('#input-search').on('input', reSearch);
}
var results = await dbGetData('clubs');
var count = results.length;
if (count > 0) {
if (count == 1) {
$('#p-count').html('Es wurde 1 Verein gefunden!');
} else {
$('#p-count').html('Es wurden ' + count + ' Vereine gefunden!');
}
$('#div-list').show();
$('#input-search').parent().show();
results.sort(function (a, b) {
var comp = a.kurz.localeCompare(b.kurz);
if (comp == 0)
comp = a.name.localeCompare(b.name);
return comp;
});
rows = [];
for (id in results) {
var entry = results[id];
var row = { keywords: [], content: '' };
row.keywords.push(entry['dsv'], entry['kurz'], entry['name']);
if (entry['website'] != '') row.keywords.push(entry['website']);
row.content += '<div onclick="onListClicked(' + entry['id'] + ');">';
// ZEILE 1
// Name
row.content += '<div><b>' + entry['name'] + '</b></div>';
// ZEILE 2
row.content += '<div>';
// DSV
row.content += '<div>' + entry['dsv'] + '</div>';
// Kurz
row.content += '<div>' + entry['kurz'] + '</div>';
row.content += '</div></div>';
rows.push(row);
}
reSearch();
} else {
$('#p-count').html('Keine Vereine gefunden!');
$('#div-list').hide();
$('#input-search').parent().hide();
}
hideLoader();
}

49
server/scripts/contact.js Normal file
View File

@@ -0,0 +1,49 @@
function sendMessage() {
var name = $('#input-name').val();
var email = $('#input-email').val();
var subject = $('#input-subject').val();
var message = $('#input-message').val();
if ((name == '') || (email == '') || (subject == '') || (message == '')) {
toastError('Bitte f&uuml;lle alle Felder aus!');
return;
}
showLoader();
$.ajax({
url: QUERY_URL + 'contact',
method: 'POST',
data: {
name: name,
email: email,
subject: subject,
message: message
},
error: function (xhr, status, error) {
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);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
hideLoader();
},
success: function (data, status, xhr) {
toastOk('Nachricht erfolgreich versandt!');
$('#input-subject').val('').trigger('focusin').trigger('focusout');
$('#input-message').val('').trigger('focusin').trigger('focusout');
hideLoader();
}
});
}
var siteScript = async function () {
if (isLoggedIn()) {
var user = await dbGetData('users', USER_ID);
$('#input-name').val(user.username).trigger('focusin').trigger('focusout');
$('#input-email').val(user.email).trigger('focusin').trigger('focusout');
}
$('#button-send').click(sendMessage);
hideLoader();
}

View File

@@ -1,9 +1,12 @@
var today;
var siteScript = async function() {
today = getToday();
if (isLoggedIn()) {
$('#card-notloggedin').hide();
var user = await dbGetData('users', localStorage.getItem('auth_user'));
var today = getToday();
// Favorites
var watched = [];
@@ -16,14 +19,23 @@ var siteScript = async function() {
if (watched.length > 0) {
var year = (new Date()).getFullYear();
$('#th-ranking').html('Rangliste ' + year);
// TODO: get ranking
var ranking = (await dbGetRanking(parseDate('01.12.' + (year - 1)), parseDate('30.11.' + year), false, false))[0];
tbody = '';
for (i in watched) {
sailor = watched[i];
tbody += '<tr><td>' + sailor.name + '</td><td>';
// TODO: check if ranking and output
//tbody += '<i>nicht in der Rangliste</i>';
tbody += '<i>Ranglisten werden aktuell noch nicht unterst&uuml;tzt</i>';
var rank = null;
for (r in ranking) {
if (ranking[r].id == sailor.id) {
rank = ranking[r].rank;
break;
}
}
if (rank == null) {
tbody += '<i>nicht in der Rangliste</i>';
} else {
tbody += '<b>' + rank + '.</b> Platz';
}
tbody += '</td></tr>';
}
$('#table-favorites').find('tbody').html(tbody);
@@ -59,100 +71,90 @@ var siteScript = async function() {
return 0;
});
if (plannings.length > 0) {
tbody = '';
list = '';
for (i in plannings) {
var planning = plannings[i];
var regatta = planning.regatta;
if (regatta['length'] < 1) continue;
var club = null;
if (regatta['club'] != null)
club = await dbGetData('clubs', regatta['club']);
var dateFrom = regatta['dateFrom'];
var dateTo = regatta['dateTo'];
// TODO: get steuermann and crew
var steuermann = '<i>noch unklar</i>';
if (planning.steuermann !== null) {
steuermann = (await dbGetData('sailors', planning.steuermann)).name;
}
var crew = [];
if (planning.crew !== '') {
crewIds = planning.crew.split(',');
for (j in crewIds) {
crew.push((await dbGetData('sailors', crewIds[j])).name);
}
}
// output
tbody += '<tr>';
tbody += '<td><span style="white-space:nowrap;">' + formatDate("j. M 'y", dateFrom) + '<br>' + formatDate("j. M 'y", dateTo) + '</span></td>';
list += '<div onclick="onRegattaClicked(' + regatta['id'] + ');">';
var content = '';
if (club != null) {
content = club['kurz'];
if (club['website'] != '') {
content = '<a href="' + club['website'] + '" target="_blank">' + content + '</a>';
}
}
tbody += '<td>' + content + '<br>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</td>';
// ZEILE 1
// Name
list += '<div><b>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</b></div>';
var buf = '';
if (regatta['info'] != '') {
buf += '<a target="_blank" href="' + regatta['info'] + '">Informationen</a>';
}
if ((regatta['meldung'] != '') && (dateTo >= today)) {
buf += '<br><a target="_blank" href="' + regatta['meldung'] + '">Meldung</a>';
// ZEILE 2
list += '<div>';
if ((planning != null) && (planning['gemeldet'] == "1")) {
buf += ' <i>(du hast gemeldet)</i>';
} else if (regatta['meldungOffen'] == "0") {
buf += ' <i>(geschlossen)</i>';
} else if (regatta['meldungSchluss'] != null) {
early = false;
if (regatta['meldungEarly'] != null) {
ms = parseDate(regatta['meldungEarly']);
if (ms >= today) {
early = true;
// Number
list += '<div>' + ((regatta['number'] != null) ? ('# ' + regatta['number']) : '') + '</div>';
// Club
list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special
list += '<div>' + regatta['special'] + '</div>';
// Icons
var icons = [];
if (regatta['info'] != '')
icons.push('<i class="fas fa-info"></i>');
if ((regatta['meldung'] != '') && (dateTo >= today) && (regatta['meldungOffen'] == '1')) {
var color = '';
if (regatta['meldungSchluss'] != null) {
if (planning['gemeldet'] == '0') {
var ms = 0;
if (regatta['meldungEarly'] != null) {
ms = parseDate(regatta['meldungEarly']);
}
if (ms < today) {
ms = parseDate(regatta['meldungSchluss']);
}
var diff = Math.round((ms - today) / 86400000);
if (ms < today) {
color = ' color-red2-dark';
} else if (diff < 7) {
color = ' color-yellow2-dark';
}
}
if (!early)
ms = parseDate(regatta['meldungSchluss']);
if (ms >= today) {
diff = Math.round((ms - today) / 86400000);
red = (diff < 7);
if (diff <= 14) {
txt = 'noch ' + diff + ' Tag' + (diff != 1 ? 'e' : '');
} else if (diff < 35) {
diff = Math.floor(diff / 7);
txt = 'noch ' + diff + ' Woche' + (diff != 1 ? 'n' : '');
} else {
diff = Math.floor(diff / 30.5);
txt = 'noch ' + diff + ' Monat' + (diff != 1 ? 'e' : '');
}
buf += ' <i>' + (red ? '<b><font style="color:red;">(' : '(') + txt + (early ? ' verg&uuml;nstigt' : '') + (red ? ')</font></b>' : ')') + '</i>';
} else {
buf += ' <i>(Meldeschluss abgelaufen)</i>';
}
}
if (planning['gemeldet'] == '0') {
color += ' fa-blink';
}
icons.push('<i class="fas fa-file-signature' + color + '"></i>');
}
if (regatta['bericht'] != '') {
buf += '<br><a target="_blank" href="' + regatta['bericht'] + '">Bericht</a>';
if (regatta['canceled'] == '1') {
icons.push('<i class="fas fa-times color-red2-dark"></i>');
}
if (regatta['oresults'] != '') {
buf += '<br><a target="_blank" href="' + regatta['oresults'] + '">off. Ergebnisse</a>';
}
tbody += '<td>' + buf + '</td>';
list += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>';
tbody += '<td><span style="white-space:nowrap;">' + parseFloat(regatta['rlf']).toFixed(2) + '</span></td>';
list += '</div>';
tbody += '<td>' + steuermann + '<br>' + crew.join('<br>') + '</td>';
// ZEILE 3
list += '<div>';
tbody += '</tr>';
// Date
list += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>';
// RLF
list += '<div>' + parseFloat(regatta['rlf']).toFixed(2) + '</div>';
list += '</div></div>';
}
$('#table-yournext').find('tbody').html(tbody);
$('#div-yournext').html(list);
$('#p-yournext').hide();
$('#table_yournext').show();
$('#div-yournext').show();
} else {
$('#table-yournext').hide();
$('#div-yournext').hide();
$('#p-yournext').show();
}
$('#card-yournext').show();
@@ -169,9 +171,12 @@ var siteScript = async function() {
maxDate.setDate(maxDate.getDate() + 14);
var regattas = await dbGetRegattasRange(minDate, maxDate);
if (regattas.length > 0) {
tbody = '';
list = '';
for (i in regattas) {
var regatta = regattas[i];
if (regatta['length'] < 1) continue;
var club = null;
if (regatta['club'] != null)
club = await dbGetData('clubs', regatta['club']);
@@ -180,27 +185,33 @@ var siteScript = async function() {
var dateTo = regatta['dateTo'];
// output
tbody += '<tr>';
list += '<div onclick="onRegattaClicked(' + regatta['id'] + ');">';
tbody += '<td><span style="white-space:nowrap;">' + formatDate("j. M 'y", dateFrom) + '<br>' + formatDate("j. M 'y", dateTo) + '</span></td>';
// ZEILE 1
// Name
list += '<div><b>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</b></div>';
var content = '';
if (club != null) {
content = club['kurz'];
if (club['website'] != '') {
content = '<a href="' + club['website'] + '" target="_blank">' + content + '</a>';
}
}
tbody += '<td>' + content + '<br>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</td>';
// ZEILE 2
list += '<div>';
var buf = '';
if (regatta['info'] != '') {
buf += '<a target="_blank" href="' + regatta['info'] + '">Informationen</a>';
}
if ((regatta['meldung'] != '') && (dateTo >= today)) {
buf += '<br><a target="_blank" href="' + regatta['meldung'] + '">Meldung</a>';
// Number
list += '<div>' + ((regatta['number'] != null) ? ('# ' + regatta['number']) : '') + '</div>';
// Club
list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special
list += '<div>' + regatta['special'] + '</div>';
// Icons
var icons = [];
if (regatta['info'] != '')
icons.push('<i class="fas fa-info"></i>');
if ((regatta['meldung'] != '') && (dateTo >= today) && (regatta['meldungOffen'] == '1')) {
var color = '';
var planning = null;
if (isLoggedIn()) {
var plannings = await dbGetDataIndex('plannings', 'regatta', regatta['id']);
for (id in plannings) {
if (plannings[id]['user'] == USER_ID) {
planning = plannings[id];
@@ -208,56 +219,51 @@ var siteScript = async function() {
}
}
}
if ((planning != null) && (planning['gemeldet'] == "1")) {
buf += ' <i>(du hast gemeldet)</i>';
} else if (regatta['meldungOffen'] == "0") {
buf += ' <i>(geschlossen)</i>';
} else if (regatta['meldungSchluss'] != null) {
early = false;
if (regatta['meldungEarly'] != null) {
ms = parseDate(regatta['meldungEarly']);
if (ms >= today) {
early = true;
if (regatta['meldungSchluss'] != null) {
if ((planning == null) || (planning['gemeldet'] == '0')) {
var ms = 0;
if (regatta['meldungEarly'] != null) {
ms = parseDate(regatta['meldungEarly']);
}
}
if (!early)
ms = parseDate(regatta['meldungSchluss']);
if (ms >= today) {
diff = Math.round((ms - today) / 86400000);
red = (diff < 7);
if (diff <= 14) {
txt = 'noch ' + diff + ' Tag' + (diff != 1 ? 'e' : '');
} else if (diff < 35) {
diff = Math.floor(diff / 7);
txt = 'noch ' + diff + ' Woche' + (diff != 1 ? 'n' : '');
} else {
diff = Math.floor(diff / 30.5);
txt = 'noch ' + diff + ' Monat' + (diff != 1 ? 'e' : '');
if (ms < today) {
ms = parseDate(regatta['meldungSchluss']);
}
var diff = Math.round((ms - today) / 86400000);
if (ms < today) {
color = ' color-red2-dark';
} else if (diff < 7) {
color = ' color-yellow2-dark';
}
buf += ' <i>' + (red ? '<b><font style="color:red;">(' : '(') + txt + (early ? ' verg&uuml;nstigt' : '') + (red ? ')</font></b>' : ')') + '</i>';
} else {
buf += ' <i>(Meldeschluss abgelaufen)</i>';
}
}
if ((planning != null) && (planning['gemeldet'] == '0')) {
color += ' fa-blink';
}
icons.push('<i class="fas fa-file-signature' + color + '"></i>');
}
if (regatta['bericht'] != '') {
buf += '<br><a target="_blank" href="' + regatta['bericht'] + '">Bericht</a>';
if (regatta['canceled'] == '1') {
icons.push('<i class="fas fa-times color-red2-dark"></i>');
}
if (regatta['oresults'] != '') {
buf += '<br><a target="_blank" href="' + regatta['oresults'] + '">off. Ergebnisse</a>';
}
tbody += '<td>' + buf + '</td>';
list += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>';
tbody += '<td><span style="white-space:nowrap;">' + parseFloat(regatta['rlf']).toFixed(2) + '</span></td>';
list += '</div>';
tbody += '</tr>';
// ZEILE 3
list += '<div>';
// Date
list += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>';
// RLF
list += '<div>' + parseFloat(regatta['rlf']).toFixed(2) + '</div>';
list += '</div></div>';
}
$('#table-next').find('tbody').html(tbody);
$('#div-next').html(list);
$('#p-next').hide();
$('#table-next').show();
$('#div-next').show();
} else {
$('#table-next').hide();
$('#div-next').hide();
$('#p-next').show();
}
@@ -274,9 +280,12 @@ var siteScript = async function() {
regattaResults[entry['id']] = (results.length > 0);
}
if (regattas.length > 0) {
tbody = '';
list = '';
for (i in regattas) {
var regatta = regattas[i];
if (regatta['length'] < 1) continue;
var club = null;
if (regatta['club'] != null)
club = await dbGetData('clubs', regatta['club']);
@@ -284,40 +293,56 @@ var siteScript = async function() {
var dateTo = regatta['dateTo'];
// output
tbody += '<tr>';
tbody += '<td><span style="white-space:nowrap;">' + formatDate("j. M 'y", dateFrom) + '<br>' + formatDate("j. M 'y", dateTo) + '</span></td>';
list += '<div onclick="onRegattaClicked(' + regatta['id'] + ');">';
var content = '';
if (club != null) {
content = club['kurz'];
if (club['website'] != '') {
content = '<a href="' + club['website'] + '" target="_blank">' + content + '</a>';
}
// ZEILE 1
// Name
list += '<div><b>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</b></div>';
// ZEILE 2
list += '<div>';
// Number
list += '<div>' + ((regatta['number'] != null) ? ('# ' + regatta['number']) : '') + '</div>';
// Club
list += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
// Special
list += '<div>' + regatta['special'] + '</div>';
// Icons
var icons = [];
if (regatta['info'] != '')
icons.push('<i class="fas fa-info"></i>');
if (regatta['bericht'] != '')
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']]) {
icons.push('<i class="fas fa-poll"></i>');
}
tbody += '<td>' + content + '<br>' + (regatta['canceled'] == 1 ? '<s>' : '') + regatta['name'] + (regatta['canceled'] == 1 ? '</s>' : '') + '</td>';
list += '<div class="color-green2-dark">' + icons.join('&ensp;') + '</div>';
var buf = '';
if (regatta['canceled'] == "1") {
buf = '<i style="color:red;" class="fas fa-times"></i> Ausgefallen</td>';
} else {
if (regattaResults[regatta['id']]) {
buf = '<i style="color:green;" class="fas fa-check"></i> <a href="' + LINK_PRE + 'result?regatta=' + regatta['id'] + '">Ergebnisse</a></td>';
} else {
buf = 'Nicht verf&uuml;gbar';
}
}
tbody += '<td>' + buf + '</td>';
list += '</div>';
tbody += '<td><span style="white-space:nowrap;">' + parseFloat(regatta['rlf']).toFixed(2) + '</span></td>';
// ZEILE 3
list += '<div>';
tbody += '</tr>';
// Date
list += '<div>' + formatDate("d.m.Y", dateFrom) + ' - ' + formatDate("d.m.Y", dateTo) + '</div>';
// RLF
list += '<div>' + parseFloat(regatta['rlf']).toFixed(2) + '</div>';
list += '</div></div>';
}
$('#table-last').find('tbody').html(tbody);
$('#div-last').html(list);
$('#p-last').hide();
$('#table-last').show();
$('#div-last').show();
} else {
$('#table-last').hide();
$('#div-last').hide();
$('#p-last').show();
}

44
server/scripts/news.js Normal file
View File

@@ -0,0 +1,44 @@
async function onNewsClicked(id) {
var newsEntry = await dbGetData('news', id);
if (newsEntry == null) return;
$('#menu-news').css('height', '80%');
$('#menu-news').css('width', '90%');
$('#menu-news').find('.menu-title').find('p').text(newsEntry.title);
$('#menu-news').find('.content').addClass('pb-3');
$('#menu-news').find('.content').html(newsEntry.html);
$('#menu-news').showMenu();
}
function addCard(newsEntry) {
var content = '<h2>' + newsEntry.title + '</h2>';
content += '<p class="mb-2"><i>' + formatDate('d.m.Y', newsEntry.date) + '</i></p>';
content += '<p class="mb-0">' + newsEntry.description.replace('\n', '<br>') + '</p>';
if (newsEntry.html != '') {
content += '<a class="btn btn-full rounded-s text-uppercase font-900 shadow-m bg-highlight mt-3" href="#" onclick="onNewsClicked(' + newsEntry.id + '); return false;">Mehr lesen</a>';
}
$('.page-content').append(cardTemplate.replace('%ID%', 'card-news-' + newsEntry.id).replace('%CONTENT%', content));
}
var siteScript = async function() {
$('.card-news').remove();
var news = await dbGetData('news');
news.sort(function (a,b) {
return b.date.localeCompare(a.date);
});
var now = new Date();
var lastYear = new Date();
lastYear.setFullYear(lastYear.getFullYear() - 1);
for (var n in news) {
var newsEntry = news[n];
newsEntry.date = new Date(Date.parse(newsEntry.date));
if (newsEntry.date > now) continue;
if (newsEntry.date < lastYear) break;
addCard(newsEntry);
}
dbSettingsSet('news_read_' + BOATCLASS, now);
updateNewsBadge();
hideLoader();
}

View File

@@ -0,0 +1,157 @@
async function onRegattaClicked(id) {
var regatta = await dbGetData('regattas', id);
$('#menu-regatta').find('.menu-title').find('p').text(regatta.name);
var dateTo = parseDate(regatta['date']);
dateTo.setDate(dateTo.getDate() + Math.max(parseInt(regatta['length']) - 1, 0));
var plannings = await dbGetDataIndex('plannings', 'regatta', regatta['id']);
var planning = null;
if (isLoggedIn()) {
for (id in plannings) {
if (plannings[id]['user'] == USER_ID) {
planning = plannings[id];
break;
}
}
}
// Your Planning
if (planning != null) {
$('#menu-item-yourplanning').show();
var steuermann = null;
if (planning.steuermann != null) {
steuermann = (await dbGetData('sailors', planning.steuermann)).name;
}
var crew = [steuermann == null ? '[noch unklar]' : steuermann];
crewA = planning.crew.split(',');
for (i in crewA) {
var sailor = await dbGetData('sailors', crewA[i]);
if (sailor != null) {
crew.push(sailor.name);
}
}
$('#menu-item-yourplanning').html(crew.join('<br>'));
} else {
$('#menu-item-yourplanning').hide();
}
// Planning
if ((plannings.length > 0) && (dateTo >= today)) {
$('#menu-item-plannings').show();
$('#menu-item-plannings').attr('href', LINK_PRE + 'regatta_plan?regatta=' + regatta['id']);
} else {
$('#menu-item-plannings').hide();
}
// Results
var results = await dbGetDataIndex('results', 'regatta', regatta['id']);
if (results.length > 0) {
$('#menu-item-results').show();
$('#menu-item-results').attr('href', LINK_PRE + 'result?regatta=' + regatta['id']);
} else {
$('#menu-item-results').hide();
}
// Bericht
if (regatta['bericht'] != '') {
$('#menu-item-bericht').show();
$('#menu-item-bericht').attr('href', regatta['bericht']);
$('#menu-item-bericht').attr('target', '_blank');
} else {
$('#menu-item-bericht').hide();
}
// Info
if (regatta['info'] != '') {
$('#menu-item-info').show();
$('#menu-item-info').attr('href', regatta['info']);
$('#menu-item-info').attr('target', '_blank');
} else {
$('#menu-item-info').hide();
}
// Meldung
if ((regatta['meldung'] != '') && (dateTo >= today)) {
$('#menu-item-meldung').show();
$('#menu-item-meldung').attr('href', regatta['meldung']);
$('#menu-item-meldung').attr('target', '_blank');
if ((planning != null) && (planning['gemeldet'] == '1')) {
$('#badge-regatta-meldung').text('schon gemeldet');
$('#badge-regatta-meldung').addClass('bg-green2-dark').removeClass('bg-highlight bg-red2-dark bg-yellow2-dark');
} else if (regatta['meldungOffen'] == '0') {
$('#badge-regatta-meldung').text('geschlossen');
$('#badge-regatta-meldung').addClass('bg-highlight').removeClass('bg-green2-dark bg-red2-dark bg-yellow2-dark');
} else if (regatta['meldungSchluss'] != null) {
var early = false;
var ms;
if (regatta['meldungEarly'] != null) {
ms = parseDate(regatta['meldungEarly']);
if (ms >= today) {
early = true;
}
}
if (!early)
ms = parseDate(regatta['meldungSchluss']);
if (ms >= today) {
var diff = Math.round((ms - today) / 86400000);
var red = (diff < 7);
var txt;
if (diff <= 14) {
txt = diff + ' Tag' + (diff != 1 ? 'e' : '');
} else if (diff < 35) {
diff = Math.floor(diff / 7);
txt = diff + ' Woche' + (diff != 1 ? 'n' : '');
} else {
diff = Math.floor(diff / 30.5);
txt = diff + ' Monat' + (diff != 1 ? 'e' : '');
}
if (early)
txt += ' vergünstigt';
$('#badge-regatta-meldung').text(txt);
if (red) {
if (early) {
$('#badge-regatta-meldung').addClass('bg-yellow2-dark').removeClass('bg-highlight bg-green2-dark bg-red2-dark');
} else {
$('#badge-regatta-meldung').addClass('bg-red2-dark').removeClass('bg-highlight bg-green2-dark bg-yellow2-dark');
}
} else {
$('#badge-regatta-meldung').addClass('bg-highlight').removeClass('bg-green2-dark bg-red2-dark bg-yellow2-dark');
}
} else {
$('#badge-regatta-meldung').text('Meldeschluss abgelaufen');
$('#badge-regatta-meldung').addClass('bg-highlight').removeClass('bg-green2-dark bg-red2-dark bg-yellow2-dark');
}
} else {
$('#badge-regatta-meldung').text('');
}
} else {
$('#menu-item-meldung').hide();
}
// off. results
if (regatta['oresults'] != '') {
$('#menu-item-oresults').show();
$('#menu-item-oresults').attr('href', regatta['oresults']);
$('#menu-item-oresults').attr('target', '_blank');
} else {
$('#menu-item-oresults').hide();
}
// club website
var clubwebsite = '';
if (regatta['club'] != null) {
clubwebsite = (await dbGetData('clubs', regatta['club'])).website;
}
if (clubwebsite != '') {
$('#menu-item-clubwebsite').show();
$('#menu-item-clubwebsite').attr('href', clubwebsite);
$('#menu-item-clubwebsite').attr('target', '_blank');
} else {
$('#menu-item-clubwebsite').hide();
}
$('#menu-regatta').showMenu();
$('#menu-regatta').scrollTop(0);
}

View File

@@ -0,0 +1,75 @@
// $$0; - site script for redraw content
// $$1; - current page
// $$2; - count of pages
// $$3; - pagination id
var paginationButtons = [];
function paginationSetActive() {
for (i = 1; i <= 7; i ++) {
if ($$1; == $('#$$3;-' + i).text()) {
$('#$$3;-' + i).addClass('active');
} else {
$('#$$3;-' + i).removeClass('active');
}
}
}
function drawPagination() {
if ($$2; > 1) {
$('#$$3;').show();
paginationButtons[6].text($$2;);
if ($$2; <= 7) {
for (i = 2; i <= $$2; - 1; i ++) {
paginationButtons[i-1].text(i);
$('#$$3;-' + i).show();
}
for (i = $$2;; i < 7; i ++) {
$('#$$3;-' + i).hide();
}
} else if ($$1; <= 4) {
for (i = 2; i <= 5; i ++) {
paginationButtons[i-1].text(i);
$('#$$3;-' + i).show();
}
paginationButtons[5].text('...');
$('#$$3;-6').show();
} else if ($$1; > $$2; - 4) {
paginationButtons[1].text('...');
$('#$$3;-2').show();
for (i = 3; i <= 6; i ++) {
paginationButtons[i-1].text($$2; + i - 7);
$('#$$3;-' + i).show();
}
} else {
paginationButtons[1].text('...');
$('#$$3;-2').show();
for (i = 3; i <= 5; i ++) {
paginationButtons[i-1].text($$1; + i - 4);
$('#$$3;-' + i).show();
}
paginationButtons[5].text('...');
$('#$$3;-6').show();
}
paginationSetActive();
} else {
$('#$$3;').hide();
}
}
function onPaginationClick(paginationButton) {
var newPage = parseInt($(paginationButton).text());
if (!isNaN(newPage)) {
$$1; = newPage;
drawPagination();
$$0;();
}
}
function initPagination() {
paginationButtons = [];
for (i = 1; i <= 7; i ++) {
paginationButtons.push($('#$$3;-' + i).find('a'));
}
drawPagination();
}

384
server/scripts/rank.js Normal file
View File

@@ -0,0 +1,384 @@
function onDetailClicked(regatta) {
location.href = LINK_PRE + 'result?regatta=' + regatta;
}
async function onRankingClicked(id) {
var sailor = null;
for (var i in ranking) {
if (ranking[i].id == id) {
sailor = ranking[i];
break;
}
}
if (sailor == null) return;
$('#menu-rank').find('.menu-title').find('p').text(sailor.name);
if (lastRanking != null) {
var lastRank;
if (sailor.id in lastRanking) {
lastRank = lastRanking[sailor.id] + '.';
} else {
lastRank = 'nicht in der Rangliste';
}
$('#menu-item-text').text('Vorheriges Jahr: ' + lastRank);
$('#menu-item-text').show();
} else {
$('#menu-item-text').hide();
}
list = '';
for (var i in sailor.regattas) {
var entry = sailor.regattas[i];
var regatta = entry.regatta;
var boat = await dbGetData('boats', entry.boat);
var dateFrom = parseDate(regatta.date);
var dateTo = parseDate(regatta.date);
dateTo.setDate(dateTo.getDate() + Math.max(parseInt(regatta.length) - 1, 0));
list += '<div onclick="onDetailClicked(' + regatta.id + ')">';
// ZEILE 1
list += '<div><b>' + regatta.name + '</b></div>';
// ZEILE 2
list += '<div>';
// DATE
list += '<div>' + formatDate('d.m.Y', dateFrom) + ' - ' + formatDate('d.m.Y', dateTo) + '</div>';
// m
list += '<div>m: ' + entry.m + '</div>';
// rlf
list += '<div>RLF: ' + parseFloat(regatta.rlf).toFixed(2) + '</div>';
list += '</div>';
// ZEILE 3
list += '<div>';
// Place
list += '<div>Platz ' + entry.place + ' / ' + entry.fb + '</div>';
// rlp
var color;
if (entry.used == 0) { color = 'color-red2-dark'; }
else if (entry.used == entry.m) { color = 'color-green2-dark'; }
else { color = 'color-yellow2-dark'; }
list += '<div>Punkte: ' + entry.used + ' x <b class="' + color + '">' + parseFloat(entry.rlp).toFixed(2) + '</b></div>';
list += '</div>';
// ZEILE 4
list += '<div>';
// Sailnumber
list += '<div>' + boat.sailnumber + '</div>';
// Boatname
list += '<div>' + boat.name + '</div>';
list += '</div>';
// ZEILE 5...
var crew = entry.crew.split(',');
for (var c in crew) {
var cr = await dbGetData('sailors', crew[c]);
if (cr != null) {
list += '<div>';
// Name
list += '<div>' + cr.name + '</div>';
// Year
list += '<div>' + ((cr.year != null) ? ('(' + cr.year + ')') : '') + '</div>';
list += '</div>';
}
}
list += '</div>';
}
$('#div-details').html(list);
$('#menu-rank').showMenu();
$('#menu-rank').scrollTop(0);
}
async function selectChange(callSiteScript = true) {
var type = $('#select-type').val();
var year = parseInt($('#select-year').val());
if (type == "user") {
$('#select-year').parent().hide();
$('#input-from').trigger('focusin').trigger('focusout').parent().show();
$('#input-to').trigger('focusin').trigger('focusout').parent().show();
$('#input-jugend').parent().parent().show();
$('#input-jugstrict').parent().parent().show();
$('#button-show').show();
} else {
$('#select-year').parent().show();
$('#input-from').parent().hide();
$('#input-to').parent().hide();
$('#input-jugend').parent().parent().hide();
$('#input-jugstrict').parent().parent().hide();
$('#button-show').hide();
var from, to, jugend, jugstrict;
switch (type) {
case 'year':
from = (year - 1) + '-12-01';
to = year + '-11-30';
jugend = jugstrict = false;
break;
case 'youth':
from = (year - 1) + '-12-01';
to = year + '-11-30';
jugend = jugstrict = true;
break;
case 'idjm':
var beginn = null;
var regattas = await dbGetData('regattas');
regattas.sort(function(a,b){ return b.date.localeCompare(a.date); });
for (var r in regattas) {
var regatta = regattas[r];
var date = parseDate(regatta.date);
if ((date < parseDate('01.01.' + year)) || (date > parseDate('31.12.' + year))) {
continue;
}
if (regatta.name.indexOf(YOUTH_GERMAN_NAME) >= 0) {
beginn = ((regatta.meldungSchluss != null) ? parseDate(regatta.meldungSchluss) : date);
break;
}
}
if (beginn != null) {
from = new Date(beginn);
from.setFullYear(from.getFullYear() - 1);
from.setDate(from.getDate() - 13);
from = formatDate('Y-m-d', from);
to = new Date(beginn);
to.setDate(to.getDate() - 14);
to = formatDate('Y-m-d', to);
jugend = true;
jugstrict = false;
} else {
$('#div-rank').html('Keine ' + YOUTH_GERMAN_NAME + ' gefunden!');
$('#input-search').parent().hide();
return;
}
break;
}
$('#input-from').val(from);
$('#input-to').val(to);
$('#input-jugend').prop('checked', jugend);
$('#input-jugstrict').prop('checked', jugstrict);
if (callSiteScript && (typeof siteScript === 'function')) {
history.replaceState(null, '', '?type=' + type + '&year=' + year)
siteScript();
}
}
}
function buttonShowPressed() {
if (typeof siteScript === 'function') {
var chboxes = '';
if ($('#input-jugend').prop('checked')) chboxes += '&jugend=on'
if ($('#input-jugstrict').prop('checked')) chboxes += '&jugstrict=on'
history.replaceState(null, '', '?type=user&from=' + $('#input-from').val() + "&to=" + $('#input-to').val() + chboxes)
siteScript();
}
}
function initSelects() {
var type = findGetParameter('type');
var year = findGetParameter('year');
if (type === null) type = 'year';
if (year === null) year = new Date().getFullYear();
$('#select-type').val(type);
$('#select-year').html('<option value="' + year + '">' + year + '</option>');
$('#select-year').val(year);
if (type == "user") {
var from = findGetParameter('from');
var to = findGetParameter('to');
if (from === null) from = formatDate('Y-m-d')
if (to === null) to = formatDate('Y-m-d')
$('#input-from').val(from).trigger('focusin').trigger('focusout');
$('#input-to').val(to).trigger('focusin').trigger('focusout');
var jugend = findGetParameter('jugend');
var jugstrict = findGetParameter('jugstrict');
$('#input-jugend').prop('checked', jugend !== null);
$('#input-jugstrict').prop('checked', jugstrict !== null);
}
selectChange(false);
}
var firstCall = true;
var rows = [];
var ranking;
var lastRanking;
async function drawList () {
window.setTimeout(function () {
var list = '';
rows.forEach(function (entry) {
if (entry == null) {
list += '<div><div align="center" class="color-highlight" style="white-space:normal;"><b>Ende der Rangliste gem&auml;&szlig; DSV-Ranglistenverordnung (min. m = 9 Wertungen)</b></div></div>';
} else if (search($('#input-search').val(), entry.keywords)) {
list += entry.content;
}
});
$('#div-rank').html(list);
}, 0);
}
var siteScript = async function() {
if (firstCall) {
firstCall = false;
initSelects();
$('#select-type').change(selectChange);
$('#select-year').change(selectChange);
$('#button-show').click(buttonShowPressed);
$('#input-search').on('input', drawList);
}
var minDate = parseDate($('#input-from').val());
var maxDate = parseDate($('#input-to').val());
var jugend = $('#input-jugend').prop('checked');
var jugstrict = $('#input-jugstrict').prop('checked');
var dbRanking = await dbGetRanking(minDate, maxDate, jugend, jugstrict);
ranking = dbRanking[0];
lastRanking = null;
if (($('#select-type').val() == 'year') || ($('#select-type').val() == 'youth')) {
lastRanking = {};
var lYear = parseInt($('#select-year').val()) - 1;
var lMinDate = parseDate((lYear - 1) + '-12-01');
var lMaxDate = parseDate(lYear + '-11-30');
var lDbRanking = (await dbGetRanking(lMinDate, lMaxDate, jugend, jugstrict))[0];
for (var i in lDbRanking) {
lastRanking[lDbRanking[i].id] = lDbRanking[i].rank;
}
}
var selectedYear = $('#select-year').val();
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);
if (dbRanking[1].length > 0) {
$('#card-noresults').show();
list = '';
for (id in dbRanking[1]) {
list += '<li>';
list += dbRanking[1][id].name;
list += '</li>';
}
$('#ul-noresults').html(list);
} else {
$('#card-noresults').hide();
}
var count = ranking.length;
if (count > 0) {
$('#input-search').parent().show();
var dsvEnd = false;
rows = [];
for (id in ranking) {
var entry = ranking[id];
for (var i in entry.regattas) {
entry.regattas[i].regatta = await dbGetData('regattas', entry.regattas[i].regatta);
}
entry.regattas = Object.values(entry.regattas);
entry.regattas.sort(function (a,b) {
return a.regatta.date.localeCompare(b.regatta.date);
});
var club = null;
if (entry['club'] != null)
club = await dbGetData('clubs', entry['club']);
var row = { keywords: [], content: '' };
row.keywords.push(entry['name']);
if (entry['year'] != null) row.keywords.push(entry['year']);
if (club != null) row.keywords.push(club['kurz'], club['name']);
if (!dsvEnd && (entry.m < 9)) {
rows.push(null);
dsvEnd = true;
}
row.content += '<div onclick="onRankingClicked(' + entry['id'] + ');">';
// ZEILE 1
row.content += '<div>';
// Rank
var icon = '';
if (lastRanking != null) {
if (entry.id in lastRanking) {
if (entry.rank < lastRanking[entry.id]) { icon = 'color-green2-dark fa-caret-up'; }
else if (entry.rank > lastRanking[entry.id]) { icon = 'color-red2-dark fa-caret-down'; }
else { icon = 'color-yellow2-dark fa-minus'; }
} else {
icon = 'color-green2-dark fa-caret-up';
}
icon = '<i class="font-16 fas ' + icon + '" style="width: 1.1em; text-align: center;"></i> ';
}
row.content += '<div>' + icon + '<b>' + entry.rank + '.</b></div>';
// m
row.content += '<div>m = ' + entry.m + '</div>';
// rlp
row.content += '<div>' + entry.rlp.toFixed(3) + '</div>';
row.content += '</div>';
// ZEILE 2
row.content += '<div>';
// Name
row.content += '<div><b>' + entry.name + '</b></div>';
// Year
row.content += '<div>' + ((entry.year != null) ? ('(' + entry.year + ')') : '') + '</div>';
row.content += '</div></div>';
rows.push(row);
}
if (!dsvEnd) {
rows.push(null);
}
drawList();
} else {
$('#div-rank').html('Keine Ergebnisse gefunden!');
$('#input-search').parent().hide();
}
hideLoader();
}

View File

@@ -0,0 +1,65 @@
var siteScript = async function() {
var regattaId = findGetParameter('regatta');
if (regattaId == null) {
$('#h1-title').text('Regatta nicht gefunden');
hideLoader();
return;
}
var regatta = await dbGetData('regattas', regattaId);
if (regatta == null) {
$('#h1-title').text('Regatta nicht gefunden');
hideLoader();
return;
}
var dateFrom = parseDate(regatta['date']);
var dateTo = parseDate(regatta['date']);
dateTo.setDate(dateTo.getDate() + Math.max(parseInt(regatta['length']) - 1, 0));
$('#h1-title').text(regatta.name);
if (regatta.length < 1) {
if (formatDate('d.m', dateFrom) == '01.01') {
$('#p-title').html('<font class="color-red2-dark">Datum noch unklar</font>');
} else {
$('#p-title').html(formatDate('d.m.Y', dateFrom) + ' - <font class="color-red2-dark">Datum nicht final</font>');
}
} else {
$('#p-title').html(formatDate('d.m.Y', dateFrom) + ' - ' + formatDate('d.m.Y', dateTo));
}
var plannings = await dbGetDataIndex('plannings', 'regatta', regatta.id);
if (plannings.length > 0) {
$('#table-plannings').show();
$('#p-info').hide();
var tbody = '';
for (var p in plannings) {
var planning = plannings[p];
tbody += '<tr>';
tbody += '<td>' + (await dbGetData('users', planning.user)).username + '</td>';
if (planning.steuermann != null) {
tbody += '<td>' + (await dbGetData('sailors', planning.steuermann)).name + '</td>';
} else {
tbody += '<td>(noch unklar)</td>';
}
var crew = [];
var cr = planning.crew.split(',');
for (c in cr) {
var s = await dbGetData('sailors', cr[c]);
if (s != null) crew.push(s.name);
}
tbody += '<td>' + crew.join('<br>') + '</td>';
tbody += '</tr>';
}
$('#table-plannings').find('tbody').html(tbody);
} else {
$('#p-info').text('Niemand plant bisher, hier hinzufahren!');
$('#p-info').show();
$('#table-plannings').hide();
}
hideLoader();
}

View File

@@ -1,8 +1,8 @@
function selectChange(callSiteScript = true) {
var val = $('#select-year').val();
if (val == "user") {
$('#input-from').parent().show();
$('#input-to').parent().show();
$('#input-from').trigger('focusin').trigger('focusout').parent().show();
$('#input-to').trigger('focusin').trigger('focusout').parent().show();
$('#button-show').show();
} else {
$('#input-from').parent().hide();
@@ -12,8 +12,17 @@ function selectChange(callSiteScript = true) {
$('#input-from').val(val + '-01-01');
$('#input-to').val(val + '-12-31');
if (callSiteScript && (typeof siteScript === 'function'))
if (callSiteScript && (typeof siteScript === 'function')) {
history.replaceState(null, '', '?year=' + val);
siteScript();
}
}
}
function buttonShowPressed() {
if (typeof siteScript === 'function') {
history.replaceState(null, '', '?year=user&from=' + $('#input-from').val() + "&to=" + $('#input-to').val())
siteScript();
}
}
@@ -24,6 +33,15 @@ function initYear() {
$('#select-year').html('<option value="' + year + '">' + year + '</option>');
$('#select-year').val(year);
if (year == "user") {
var from = findGetParameter('from');
var to = findGetParameter('to');
if (from === null) from = formatDate('Y-m-d')
if (to === null) to = formatDate('Y-m-d')
$('#input-from').val(from).trigger('focusin').trigger('focusout');
$('#input-to').val(to).trigger('focusin').trigger('focusout');
}
selectChange(false);
}
@@ -31,7 +49,7 @@ var firstCall = true;
var rows = [];
var today;
async function drawTable () {
async function drawList () {
window.setTimeout(function () {
var list = '';
rows.forEach(function (entry) {
@@ -45,141 +63,13 @@ async function drawTable () {
}, 0);
}
async function regattaClicked(id) {
var regatta = await dbGetData('regattas', id);
$('#menu-regatta').find('.menu-title').find('p').text(regatta.name);
// Results
var results = await dbGetDataIndex('results', 'regatta', regatta['id']);
if (results.length > 0) {
$('#menu-item-results').show();
$('#menu-item-results').attr('href', LINK_PRE + 'result/' + regatta['id']);
} else {
$('#menu-item-results').hide();
}
// Bericht
if (regatta['bericht'] != '') {
$('#menu-item-bericht').show();
$('#menu-item-bericht').attr('href', regatta['bericht']);
$('#menu-item-bericht').attr('target', '_blank');
} else {
$('#menu-item-bericht').hide();
}
// Info
if (regatta['info'] != '') {
$('#menu-item-info').show();
$('#menu-item-info').attr('href', regatta['info']);
$('#menu-item-info').attr('target', '_blank');
} else {
$('#menu-item-info').hide();
}
// Meldung
var dateTo = parseDate(regatta['date']);
dateTo.setDate(dateTo.getDate() + Math.max(parseInt(regatta['length']) - 1, 0));
if ((regatta['meldung'] != '') && (dateTo >= today)) {
$('#menu-item-meldung').show();
$('#menu-item-meldung').attr('href', regatta['meldung']);
$('#menu-item-meldung').attr('target', '_blank');
var planning = null;
if (isLoggedIn()) {
var plannings = await dbGetDataIndex('plannings', 'regatta', regatta['id']);
for (id in plannings) {
if (plannings[id]['user'] == USER_ID) {
planning = plannings[id];
break;
}
}
}
if ((planning != null) && (planning['gemeldet'] == '1')) {
$('#badge-regatta-meldung').text('schon gemeldet');
$('#badge-regatta-meldung').addClass('bg-green2-dark').removeClass('bg-highlight bg-red2-dark bg-yellow2-dark');
} else if (regatta['meldungOffen'] == '0') {
$('#badge-regatta-meldung').text('geschlossen');
$('#badge-regatta-meldung').addClass('bg-highlight').removeClass('bg-green2-dark bg-red2-dark bg-yellow2-dark');
} else if (regatta['meldungSchluss'] != null) {
var early = false;
var ms;
if (regatta['meldungEarly'] != null) {
ms = parseDate(regatta['meldungEarly']);
if (ms >= today) {
early = true;
}
}
if (!early)
ms = parseDate(regatta['meldungSchluss']);
if (ms >= today) {
var diff = Math.round((ms - today) / 86400000);
var red = (diff < 7);
var txt;
if (diff <= 14) {
txt = diff + ' Tag' + (diff != 1 ? 'e' : '');
} else if (diff < 35) {
diff = Math.floor(diff / 7);
txt = diff + ' Woche' + (diff != 1 ? 'n' : '');
} else {
diff = Math.floor(diff / 30.5);
txt = diff + ' Monat' + (diff != 1 ? 'e' : '');
}
if (early)
txt += ' vergünstigt';
$('#badge-regatta-meldung').text(txt);
if (red) {
if (early) {
$('#badge-regatta-meldung').addClass('bg-yellow2-dark').removeClass('bg-highlight bg-green2-dark bg-red2-dark');
} else {
$('#badge-regatta-meldung').addClass('bg-red2-dark').removeClass('bg-highlight bg-green2-dark bg-yellow2-dark');
}
} else {
$('#badge-regatta-meldung').addClass('bg-highlight').removeClass('bg-green2-dark bg-red2-dark bg-yellow2-dark');
}
} else {
$('#badge-regatta-meldung').text('Meldeschluss abgelaufen');
$('#badge-regatta-meldung').addClass('bg-highlight').removeClass('bg-green2-dark bg-red2-dark bg-yellow2-dark');
}
} else {
$('#badge-regatta-meldung').text('');
}
} else {
$('#menu-item-meldung').hide();
}
// off. results
if (regatta['oresults'] != '') {
$('#menu-item-oresults').show();
$('#menu-item-oresults').attr('href', regatta['oresults']);
$('#menu-item-oresults').attr('target', '_blank');
} else {
$('#menu-item-oresults').hide();
}
// club website
var clubwebsite = '';
if (regatta['club'] != null) {
clubwebsite = (await dbGetData('clubs', regatta['club'])).website;
}
if (clubwebsite != '') {
$('#menu-item-clubwebsite').show();
$('#menu-item-clubwebsite').attr('href', clubwebsite);
$('#menu-item-clubwebsite').attr('target', '_blank');
} else {
$('#menu-item-clubwebsite').hide();
}
$('#menu-regatta').showMenu();
$('#menu-regatta').scrollTop(0);
}
var siteScript = async function() {
if (firstCall) {
firstCall = false;
initYear();
$('#select-year').change(selectChange);
$('#button-show').click(siteScript);
$('#input-search').on('input', drawTable);
$('#button-show').click(buttonShowPressed);
$('#input-search').on('input', drawList);
}
today = getToday();
@@ -244,7 +134,7 @@ var siteScript = async function() {
heute = true;
}
row.content += '<div onclick="regattaClicked(' + entry['id'] + ');">';
row.content += '<div onclick="onRegattaClicked(' + entry['id'] + ');">';
// ZEILE 1
// Name
@@ -268,17 +158,17 @@ var siteScript = async function() {
icons.push('<i class="fas fa-info"></i>');
if ((entry['meldung'] != '') && (dateTo >= today) && (entry['meldungOffen'] == '1')) {
var color = '';
if (entry['meldungSchluss'] != null) {
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;
}
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) {
@@ -288,14 +178,16 @@ var siteScript = async function() {
ms = parseDate(entry['meldungSchluss']);
}
var diff = Math.round((ms - today) / 86400000);
if ((ms >= today) && (diff < 7)) {
if (ms < today) {
color = ' color-red2-dark';
if (planning != null) {
color += ' fa-blink';
}
} 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'] != '')
@@ -335,7 +227,7 @@ var siteScript = async function() {
rows.push(null);
}
drawTable();
drawList();
} else {
$('#p-count').html('Keine Regatten gefunden!');

77
server/scripts/result.js Normal file
View File

@@ -0,0 +1,77 @@
var siteScript = async function() {
var regattaId = findGetParameter('regatta');
if (regattaId == null) {
$('#h1-title').text('Regatta nicht gefunden');
hideLoader();
return;
}
var regatta = await dbGetData('regattas', regattaId);
if (regatta == null) {
$('#h1-title').text('Regatta nicht gefunden');
hideLoader();
return;
}
var dateFrom = parseDate(regatta['date']);
var dateTo = parseDate(regatta['date']);
dateTo.setDate(dateTo.getDate() + Math.max(parseInt(regatta['length']) - 1, 0));
$('#h1-title').text(regatta.name);
$('#p-title').text(formatDate('d.m.Y', dateFrom) + ' - ' + formatDate('d.m.Y', dateTo));
var results = await dbGetResultCalculated(regatta);
if (results.length > 0) {
var m;
if (regatta.m > 0) {
m = regatta.m;
} else if (regatta.races <= 4) {
m = regatta.races;
} else {
if ((regatta.length > 2) && (regatta.races >= 6)) {
m = 5;
} else {
m = 4;
}
}
$('#p-info').text(regatta.races + ' Wettfahrten, ' + regatta.streicher + ' Streicher, m = ' + m);
$('#table-results').show();
var thead = '<tr><th>#</th><th>Boot</th><th>Crew</th><th></th>';
for (var i = 1; i <= regatta.races; i ++) thead += '<th>WF ' + i + '</th>';
thead += '<th></th><th>Summe</th><th>Netto</th><th>#</th><th>RLP</th></tr>';
$('#table-results').find('thead').html(thead);
var tbody = '';
for (var r in results) {
var result = results[r];
var boat = await dbGetData('boats', result.boat);
var steuermann = (await dbGetData('sailors', result.steuermann)).name;
var cr = result.crew.split(',');
var crew = [];
for (c in cr) {
var s = await dbGetData('sailors', cr[c]);
if (s != null) crew.push(s.name);
}
tbody += '<tr>';
tbody += '<td>' + result.place + '.</td>';
tbody += '<td>' + boat.sailnumber + '<br>' + boat.name + '</td>';
tbody += '<td>' + steuermann + '<br>' + crew.join('<br>') + '</td>';
tbody += '<td></td>';
for (var i = 0; i < regatta.races; i ++) {
tbody += '<td>' + result.texts[i] + '</td>';
}
tbody += '<td></td>';
tbody += '<td>' + result.brutto + '</td>';
tbody += '<td>' + result.netto + '</td>';
tbody += '<td>' + result.place + '.</td>';
tbody += '<td>' + parseFloat(result.rlp).toFixed(2) + '</td>';
tbody += '</tr>';
}
$('#table-results').find('tbody').html(tbody);
} else {
$('#p-info').text('Keine Ergebnisse gefunden.');
$('#table-results').hide();
}
hideLoader();
}

197
server/scripts/sailors.js Normal file
View File

@@ -0,0 +1,197 @@
var firstCall = true;
var rows = [];
var displayed = [];
var page = 1;
var pageCount = 0;
const showCount = 25;
async function onEditYearClick() {
var id = $('#button-edityear').attr('data-sailor-id');
var year = $('#input-edityear').val();
if (year != '') {
showLoader();
$.ajax({
url: QUERY_URL + 'add_year',
method: 'POST',
data: {
sailor: id,
year: year
},
error: function (xhr, status, error) {
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);
toastError('Ein unbekannter Fehler ist aufgetreten. Bitte versuche es noch einmal', 5000);
}
hideLoader();
},
success: function (data, status, xhr) {
if ('status' in data) {
if (data.status == 'added') {
toastOk('Jahrgang erfolgreich hinzugefügt');
sync();
} else {
toastInfo('Wir prüfen Deine Anfrage und korrigieren den Jahrgang schnellstmöglich', 5000);
}
} else {
toastOk('Erfolgreich');
}
hideLoader();
}
});
}
$('#menu-edityear').hideMenu();
}
async function onListClicked(id) {
var sailor = await dbGetData('sailors', id);
$('#menu-sailor').find('.menu-title').find('p').text(sailor.name);
// Edit Year
$('#button-edityear').attr('data-sailor-id', sailor.id);
$('#menu-edityear').find('.menu-title').find('p').text(sailor.name);
if (sailor['year'] == null) {
$('#menu-item-year').find('span').text('Jahrgang hinzufügen');
$('#menu-edityear').find('.menu-title').find('h1').text('Jahrgang hinzufügen');
$('#input-edityear').val('');
} else {
$('#menu-item-year').find('span').text('Jahrgang bearbeiten');
$('#menu-edityear').find('.menu-title').find('h1').text('Jahrgang bearbeiten');
$('#input-edityear').val(sailor.year);
}
$('#input-edityear').trigger('focusin').trigger('focusout');
// club website
var clubwebsite = '';
if (sailor['club'] != null) {
clubwebsite = (await dbGetData('clubs', sailor['club'])).website;
}
if (clubwebsite != '') {
$('#menu-item-clubwebsite').show();
$('#menu-item-clubwebsite').attr('href', clubwebsite);
$('#menu-item-clubwebsite').attr('target', '_blank');
} else {
$('#menu-item-clubwebsite').hide();
}
$('#menu-sailor').showMenu();
$('#menu-sailor').scrollTop(0);
}
function pageChange() {
$('#p-count')[0].scrollIntoView({ behavior: "smooth" });
drawList();
}
async function drawList() {
window.setTimeout(function () {
var list = '';
if (displayed.length > 0) {
var offset = (page - 1) * showCount;
var count = (page == pageCount ? (displayed.length % showCount) : showCount);
if (count == 0) count = showCount;
for (i = 0; i < count; i ++) {
list += displayed[i + offset];
}
} else {
list = '<div><div>Keine Ergebnisse, die der Suche entsprechen</div></div>';
}
$('#div-list').html(list);
}, 0);
}
async function reSearch() {
window.setTimeout(function () {
displayed = [];
rows.forEach(function (entry) {
if (search($('#input-search').val(), entry.keywords)) {
displayed.push(entry.content);
}
});
pageCount = Math.ceil(displayed.length / showCount);
if ((page < 1) || (page > pageCount)) {
if (page < 1) {
page = 1;
} else {
page = pageCount;
}
}
drawPagination();
drawList();
}, 0);
}
var siteScript = async function() {
if (firstCall) {
firstCall = false;
initPagination();
$('#input-search').on('input', reSearch);
$('#menu-item-year').click(function(){ $('#menu-sailor').hideMenu(); $('#menu-edityear').showMenu(); });
$('#button-edityear').click(onEditYearClick);
}
var results = await dbGetData('sailors');
var count = results.length;
if (count > 0) {
if (count == 1) {
$('#p-count').html('Es wurde 1 Segler gefunden!');
} else {
$('#p-count').html('Es wurden ' + count + ' Segler gefunden!');
}
$('#div-list').show();
$('#input-search').parent().show();
results.sort(function (a, b) {
return a.name.localeCompare(b.name);
});
rows = [];
for (id in results) {
var entry = results[id];
var club = null;
if (entry['club'] != null)
club = await dbGetData('clubs', entry['club']);
var row = { keywords: [], content: '' };
row.keywords.push(entry['name']);
if (entry['year'] != null) row.keywords.push(entry['year']);
if (club != null) row.keywords.push(club['kurz'], club['name']);
row.content += '<div onclick="onListClicked(' + entry['id'] + ');">';
// ZEILE 1
// Name
row.content += '<div><b>' + entry['name'] + '</b></div>';
// ZEILE 2
row.content += '<div>';
// Year
row.content += '<div>' + ((entry['year'] != null) ? (entry['year']) : '') + '</div>';
// Club
row.content += '<div>' + ((club != null) ? club['kurz'] : '') + '</div>';
row.content += '</div></div>';
rows.push(row);
}
reSearch();
} else {
$('#p-count').html('Keine Segler gefunden!');
$('#div-list').hide();
$('#input-search').parent().hide();
}
hideLoader();
}

View File

@@ -1,5 +1,5 @@
<div id="$$html-id;" class="card card-style">
<div class="content $$css-class;">
<div id="$$html-id;" class="card card-style $$css-class;">
<div class="content">
$$0;
</div>
</div>

View File

@@ -0,0 +1,5 @@
<div class="fac fac-checkbox fac-blue $$css-class;">
<span></span>
<input id="$$html-id;" type="checkbox" $$checked; />
<label for="$$html-id;">$$placeholder;</label>
</div>

View File

@@ -1,4 +1,4 @@
<div class="input-style input-style-2 input-required">
<div class="input-style input-style-2 input-required $$css-class;">
<span class="color-highlight">$$placeholder;</span>
<input id="$$html-id;" class="form-control $$css-class;" type="$$type;" placeholder="$$placeholder;" value="$$value;" />
<input id="$$html-id;" class="form-control" type="$$type;" placeholder="$$placeholder;" value="$$value;" />
</div>

View File

@@ -0,0 +1,11 @@
<nav id="$$html-id;">
<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>
<li id="$$html-id;-3" class="page-item"><a onclick="onPaginationClick(this)" class="page-link color-black bg-theme rounded-xs shadow-x1 border-0" style="cursor: pointer;">3</a></li>
<li id="$$html-id;-4" class="page-item"><a onclick="onPaginationClick(this)" class="page-link color-black bg-theme rounded-xs shadow-x1 border-0" style="cursor: pointer;">4</a></li>
<li id="$$html-id;-5" class="page-item"><a onclick="onPaginationClick(this)" class="page-link color-black bg-theme rounded-xs shadow-x1 border-0" style="cursor: pointer;">5</a></li>
<li id="$$html-id;-6" class="page-item"><a onclick="onPaginationClick(this)" class="page-link color-black bg-theme rounded-xs shadow-x1 border-0" style="cursor: pointer;">6</a></li>
<li id="$$html-id;-7" class="page-item"><a onclick="onPaginationClick(this)" class="page-link color-black bg-theme rounded-xs shadow-x1 border-0" style="cursor: pointer;">7</a></li>
</ul>
</nav>

View File

@@ -1,6 +1,6 @@
<div class="input-style input-style-2 input-required">
<div class="input-style input-style-2 input-required $$css-class;">
<span class="color-highlight input-style-1-active">$$placeholder;</span>
<select id="$$html-id;" class="form-control $$css-class;">
<select id="$$html-id;" class="form-control">
$$options;
</select>
</div>

View File

@@ -1,4 +1,4 @@
<div class="input-style input-style-2 input-required">
<div class="input-style input-style-2 input-required $$css-class;">
<span class="color-highlight">$$placeholder;</span>
<textarea id="$$html-id;" class="form-control $$css-class;" placeholder="$$placeholder;">$$value;</textarea>
<textarea id="$$html-id;" class="form-control pt-3 pb-3" placeholder="$$placeholder;" style="height: 10em; line-height: 1.5em;">$$value;</textarea>
</div>

5
server/version.php Normal file
View File

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

View File

@@ -42,7 +42,7 @@ workbox.precaching.precacheAndRoute([
}
$hash = md5(getDirHash(__DIR__));
$path = __DIR__ . '/content/';
$path = __DIR__ . '/server/content/';
$dir = opendir($path);
while ($file = readdir($dir)) {
if (($file == '.') or ($file == '..') or (pathinfo($file, PATHINFO_EXTENSION) != 'php')) continue;
@@ -56,15 +56,19 @@ workbox.precaching.precacheAndRoute([
'/manifest.json.php',
];
$dirsToCache = [
'/client',
'/client/app',
'/client/fonts/css',
'/client/fonts/webfonts',
'/client/images',
'/client/scripts',
'/client/styles',
];
function addDir($path) {
global $filesToCache;
if ($dir = opendir(__DIR__ . $path)) {
while (($file = readdir($dir)) !== false) {
if ($file == '.') continue;
if ($file == '..') continue;
if (substr($file, 0, 1) == '.') continue;
if (is_dir(__DIR__ . $path . '/' . $file)) {
addDir($path . '/' . $file);
} else {
@@ -105,3 +109,204 @@ workbox.routing.registerRoute(
//Learn more about Service Workers and Configurations
//https://developers.google.com/web/tools/workbox/
// DB
function openDb() {
return new Promise(function(resolve) {
if (indexedDB) {
var request = indexedDB.open('regatten_app_db_<?php echo BOATCLASS; ?>');
request.onerror = function (e) {
console.log('[sW] Cannot open DB:', e.targer.errorCode);
resolve(null);
};
request.onupgradeneeded = function (e) {
console.log('[sW] DB does not exist');
e.target.transaction.abort();
resolve(null);
};
request.onsuccess = function (e) {
console.log('[sW] DB loaded');
var db = e.target.result;
db.onerror = function (e) {
console.log('[sW] DB Error:', e);
};
resolve(db);
}
} else {
resolve(null);
}
});
}
function dbSettingsGet(key) {
return new Promise(async function(resolve) {
var db = await openDb();
if (db !== null) {
var request = db.transaction('settings').objectStore('settings').get(key);
request.onsuccess = function (event) {
db.close();
console.log('[sW] DB closed');
resolve(typeof request.result != 'undefined' ? request.result.value : null);
}
} else {
resolve(null);
}
});
}
async function dbSettingsSet(key, value) {
var db = await openDb();
if (db != null) {
var os = db.transaction('settings', 'readwrite').objectStore('settings');
var request = os.put({ key: key, value: value});
request.onerror = function (event) {
console.log('[sW] Error while saving data to DB:', e);
db.close();
console.log('[sW] DB closed');
}
request.onsuccess = function (event) {
db.close();
console.log('[sW] DB closed');
}
}
}
// PUSHES
function getEntry(data, index, defaultValue) {
return ((typeof data[index] !== "undefined") ? data[index] : defaultValue);
}
function isMyRegatta(id) {
return new Promise(async function (resolve) {
var regattas = await dbSettingsGet('myregattas_<?php echo BOATCLASS; ?>');
if (regattas == null) resolve(false);
else resolve(regattas.includes(id.toString()));
});
}
self.addEventListener('push', async function(event) {
console.log('[sW] Push received:', event.data.text());
var data;
try {
data = JSON.parse(event.data.text());
} catch(e) {
console.log(e);
data = undefined;
}
if (typeof data.type !== "undefined") {
switch (data.type) {
case 'notification':
if (typeof data.title === "undefined") break;
if (typeof data.body === "undefined") break;
if (typeof data.channel === "undefined") break;
// check channel
var okay = false;
switch (data.channel) {
case 'news':
if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_news')) okay = true;
break;
case 'regatta_changed':
if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_regatta_changed_all')) okay = true;
else if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_regatta_changed_my')) {
if (await isMyRegatta(getEntry(data, 'id', ''))) okay = true;
}
break;
case 'result_ready':
if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_result_ready_all')) okay = true;
else if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_result_ready_my')) {
if (await isMyRegatta(getEntry(data, 'id', ''))) okay = true;
}
break;
case 'meldeschluss':
if (await dbSettingsGet('notify_channel_<?php echo BOATCLASS; ?>_meldeschluss')) {
if (await isMyRegatta(getEntry(data, 'id', ''))) okay = true;
}
break;
default:
console.log('Unknown channel:', data.channel);
break;
}
if (!okay) {
console.log('Notification channel not subscribed');
return;
}
const options = {
data: data,
body: data.body,
icon: getEntry(data, 'icon', '<?php echo SERVER_ADDR; ?>/client/app/icons/icon-512x512.png'),
badge: '<?php echo SERVER_ADDR; ?>/client/app/icons/badge-128x128.png',
vibrate: [500,100,500]
};
if ((image = getEntry(data, 'image', null)) !== null) {
options.image = image;
}
// Force refresh on next app open
var db = await openDb();
if (db != null) {
var os = db.transaction('update_times', 'readwrite').objectStore('update_times');
var request = os.put({ table: 'last_sync', time: 0 });
request.onerror = function (event) {
console.log('[sW] Error while saving data to DB:', e);
db.close();
console.log('[sW] DB closed');
}
request.onsuccess = function (event) {
db.close();
console.log('[sW] DB closed');
}
}
console.log('Showing notification');
self.registration.showNotification(data.title, options);
break;
case 'forcesync':
// Force refresh on next app open
var db = await openDb();
if (db != null) {
var os = db.transaction('update_times', 'readwrite').objectStore('update_times');
var request = os.put({ table: 'last_sync', time: 0 });
request.onerror = function (event) {
console.log('[sW] Error while saving data to DB:', e);
db.close();
console.log('[sW] DB closed');
}
request.onsuccess = function (event) {
console.log('[sW] Data successfully saved');
db.close();
console.log('[sW] DB closed');
}
}
break;
default:
console.log('[sW] Push type unknown:', data.type);
break;
}
} else {
console.log('[sW] No push type given!');
}
});
self.addEventListener('notificationclick', function(event) {
var data = event.notification.data;
event.notification.close();
var url = '<?php echo SERVER_ADDR; ?>' + getEntry(data, 'url', '');
event.waitUntil(
clients.openWindow(url)
);
});