Compare commits

...

18 Commits

Author SHA1 Message Date
anika 4d33040ded Merge pull request 'flask-version' (#11) from flask-version into main
Reviewed-on: https://gitea.zenerdio.de/anika/Fetenzentrale/pulls/11
2024-04-28 17:57:57 +02:00
Anika 07b786c7a2 fixed alarms, dicts sind doof 2024-03-30 16:42:34 +01:00
Anika 5e3a3a8272 Alarm einfügen funktioniert wieder, Alarms sind jetzt sortiert 2024-03-29 16:45:44 +01:00
Anika 56cdca0998 mehr hübsch und mehr Doku ist mehr gut? 2024-03-21 20:54:03 +01:00
Anika 94a154c363 checkboxen mit verknüfung 2024-03-21 20:37:21 +01:00
Anika 8d91c63a12 cleanup and bug fixed
upload saved the key of the dict as int not str
2024-03-20 13:28:19 +01:00
Anika 4314f97ee3 alarms können gelöscht werden, checkboxen vorbereitet 2024-03-13 17:58:57 +01:00
Anika 58f7ac960d upload file for predetermined alarms, closes #4 2024-03-08 12:41:45 +01:00
Anika 887c9f6635 let's pretend I get warum dass vorher nicht funktioniert hat 2024-03-05 15:33:23 +01:00
Anika e07f1c9754 looks prettier, mehr erklärung 2024-03-05 14:47:55 +01:00
Anika 64537fe572 finally seems to be working 2024-03-05 14:00:25 +01:00
Anika 8008d0262d works again 2024-03-05 13:40:33 +01:00
Anika acab981293 das ist doch kaputt gewesen 2024-03-04 23:23:37 +01:00
Anika e9f8d3ad28 started adding docs/comments 2024-03-04 23:20:43 +01:00
Anika 43bce4789c closes #2 2024-03-04 22:22:58 +01:00
Anika ed8fc409f8 closes #1,#3 2024-03-04 18:45:02 +01:00
Anika 0b2ff931b1 let's ignore the bugs 2024-02-12 23:41:24 +01:00
Anika 08a85501ce semi working flask version 2024-02-12 12:56:15 +01:00
18 changed files with 11843 additions and 115 deletions

15
.gitignore vendored Normal file
View File

@ -0,0 +1,15 @@
### VirtualEnv ###
# Virtualenv
# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/
.Python
[Bb]in
[Ii]nclude
[Ll]ib
[Ll]ib64
[Ll]ocal
[Ss]cripts
pyvenv.cfg
.venv
pip-selfcheck.json
*.json
__pycache__

View File

@ -1,3 +1,9 @@
# Fetenzentrale
Joa, kann Log schreiben und alerten. Nicht sehr kompliziert.
## Aufsetzen
- am besten in n venv
- `python`>=3.8
- `flask` per `pip` installieren
- `flask run`
- wenn das nicht tut: `export FLASK_APP=app` (`set` statt`export` under Windows)

View File

@ -1,7 +0,0 @@
02/08/24 15:10:56 ~ ters
02/08/24 14:53:07 ~ test
02/08/24 15:53:07 ~ test
02/08/24 15:21:32 ~ asdfjklö sdfjkl
02/08/24 15:27:44 ~ juhu
02/08/24 15:39:49 ~ lds
02/08/24 15:43:17 ~ asfhk ksadf

218
app.py Normal file
View File

@ -0,0 +1,218 @@
import json
import subprocess
from flask import flash, redirect, request, Flask, render_template, url_for
from datetime import datetime, timedelta
app = Flask(__name__)
activeAlarms = dict()
previousAlarms = dict()
logs = list()
todos_dict = dict()
preprocessed = False
alarmIndex = 0
def preprocess():
print('start init alarms and logs')
#versuch beide files zu laden, wenn das fehlschlägt, initiiere beide files als json
try:
alarmsFile = json.load(open('alarms.json'))
logsFile = json.load(open('logs.json'))
todoFile = json.load(open('todos.json'))
except:
alarmsFile = list()
logsFile = list()
todoFile = list()
json.dump(alarmsFile, open('alarms.json','w'), indent=2)
json.dump(logsFile, open('logs.json','w'), indent=2)
json.dump(todoFile, open('todos.json','w'), indent=2)
# schreib alle alarme im File in previousAlarms, wenn sie älter als 2 mins sind
# alle anderen in active alarms
for (alarm) in alarmsFile:
if datetime.strptime(alarmsFile[alarm]['datetime'],"%d.%m.%Y %H:%M") <= datetime.now()-timedelta(minutes=2):
previousAlarms[alarm] = alarmsFile[alarm]
else:
activeAlarms[alarm] = alarmsFile[alarm]
global alarmIndex
if(int(alarm)>alarmIndex):
alarmIndex = int(alarm)
for todo in todoFile:
todos_dict[todo] = todoFile[todo]
if todoFile[todo]['done'] and todo in activeAlarms:
previousAlarms[todo] = activeAlarms[todo]
activeAlarms.pop(todo)
elif not todoFile[todo]['done'] and todo in previousAlarms:
activeAlarms[todo] = previousAlarms[todo]
previousAlarms.pop(todo)
# lies alle log aus dem file ein
for log in logsFile:
logs.append(log)
global preprocessed
preprocessed = True
print("init of alarms and logs done")
@app.route("/", methods=('GET', 'POST'))
def index():
if not preprocessed:
preprocess()
sorted_alarms = dict(sorted(activeAlarms.items(), key=lambda x:x[1]['datetime']))
sorted_prevAlarms = dict(sorted(previousAlarms.items(), key=lambda x:x[1]['datetime']))
return render_template('index.html', logs = logs, alarms = sorted_alarms, previousAlarms=sorted_prevAlarms)
@app.route('/setAlarm', methods=('GET', 'POST'))
def setAlarm():
if request.method == 'POST':
# wenn Datum leer:
# default Datum ist heute
# wenn heute + angegebene Uhrzeit vor jetzt ist -> Alarm für morgen zu der Uhrzeit gesetzt
if request.form['date'] !="" and request.form['time']!="":
time = datetime.strptime(request.form['date']+' '+request.form['time'], "%Y-%m-%d %H:%M")
elif request.form['date'] == "":
time = datetime.combine(datetime.today(),datetime.strptime(request.form['time'], "%H:%M").time())
if time<datetime.now():
time = time + timedelta(days=1)
content = request.form['alarmMessage']
global alarmIndex
alarmIndex += 1
activeAlarms[str(alarmIndex)] = {'datetime':datetime.strftime(time,"%d.%m.%Y %H:%M"),'message':content}
allAlarms = {**activeAlarms, **previousAlarms}
with open('alarms.json', 'w') as f:
json.dump(allAlarms, f, indent=2)
f.close()
return redirect(url_for('index'))
@app.route('/sendLog', methods=('GET', 'POST'))
def sendLog():
if request.method == 'POST':
content = request.form['logMessage']
log = {'datetime':datetime.now().strftime("%d.%m.%Y %H:%M"),'message':content}
logs.append(log)
with open('logs.json', 'w') as f:
json.dump(logs, f, indent=2)
f.close()
return redirect(url_for('index'))
@app.route('/sendTodo', methods=('GET', 'POST'))
def sendTodo():
if request.method == 'POST':
content = request.form['todoMessage']
global alarmIndex
alarmIndex +=1
todos_dict[str(alarmIndex)]= {'done':False, 'message':content}
with open('todos.json', 'w') as f:
json.dump(todos_dict, f, indent=2)
f.close()
return redirect(url_for('todos'))
# sounds the alarm
@app.route('/alarms', methods=('GET','POST'))
def alarm():
if request.method == 'GET':
return json.dumps(activeAlarms)
if request.method == 'POST':
print('ALARM')
subprocess.call(['mpv','./alarm.mp3'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
id = request.data.decode('UTF-8')
alarm = activeAlarms[id]
previousAlarms[id] = alarm
activeAlarms.pop(id)
# what about Todos?
return redirect(url_for('index'))
@app.route('/deletealarm', methods=('GET','POST'))
def deleteAlarm():
if request.method == 'POST':
id = request.data.decode('UTF-8')
alarm = activeAlarms[id]
previousAlarms[id] = alarm
activeAlarms.pop(id)
if id in todos_dict:
todos_dict[id] = {'done': True, 'message': todos_dict[id]['message']}
return redirect(url_for('index'))
# invert todo checkbox
# if alarm attached to checkbox -> move to previous or active alarm accordingly
@app.route('/checktodo', methods=('GET','POST'))
def checktodo():
if request.method == 'POST':
id = request.data.decode('UTF-8')
current_state = todos_dict[id]['done']
todos_dict[id] = {'done': not todos_dict[id]['done'], 'message': todos_dict[id]['message']}
if id in activeAlarms:
previousAlarms[id] = activeAlarms[id]
activeAlarms.pop(id)
elif id in previousAlarms and not current_state:
activeAlarms[id] = previousAlarms[id]
previousAlarms.pop(id)
with open('todos.json', 'w') as f:
json.dump(todos_dict, f, indent=2)
return render_template('todo.html', todos = todos_dict, alarms = activeAlarms)
@app.route('/upload', methods=('GET','POST'))
def upload():
# if upload successful back to index
# else show error und bleib auf der Seite
if request.method == 'POST':
try:
data = json.load(request.files['alarmFile'].stream)
for alarm in data:
content = alarm["message"]
global alarmIndex
alarmIndex += 1
if alarm["type"] != "checkbox":
time = datetime.combine(datetime.today(),datetime.strptime(alarm["time"], "%H:%M").time())
if time<datetime.now():
time = time + timedelta(days=1)
activeAlarms[str(alarmIndex)] = {'datetime':datetime.strftime(time,"%d.%m.%Y %H:%M"),'message':content}
if(alarm["type"]=="both"):
todos_dict[str(alarmIndex)]= {'done':False, 'message':content}
else:
todos_dict[str(alarmIndex)]= {'done':False, 'message':content}
# ja, wir schreiben einfach das ganze File neu, ist aber einfacher
with open('alarms.json', 'w') as f:
json.dump(activeAlarms, f, indent=2)
with open('todos.json', 'w') as g:
json.dump(todos_dict, g, indent=2)
f.close()
g.close()
return redirect(url_for('index'))
except:
return render_template('upload.html', uploadFailed=True)
return render_template('upload.html', uploadFailed=False)
# ab hier statisches gerendere, keine große Logik mehr :D
@app.route('/processAlarm')
def processAlarm():
return render_template('alarms.html', alarms=activeAlarms)
@app.route('/processpAlarm')
def processpAlarm():
return render_template('palarms.html', previousAlarms=previousAlarms)
@app.route('/reloadChecklist')
def reloadChecklist():
return render_template('todolist.html', todos=todos_dict)
@app.route('/todos')
def todos():
if not preprocessed:
preprocess()
return render_template('todo.html', todos = todos_dict, alarms = activeAlarms)
@app.route("/help")
def help():
return render_template('help.html')
@app.route("/about")
def about():
return render_template('about.html')

27
defaultAlarms.json Normal file
View File

@ -0,0 +1,27 @@
[
{
"type": "both",
"time": "20:30",
"message": "Akkuwechsel"
},
{
"type": "alarm",
"time": "21:00",
"message": "Feteneröffnung"
},
{
"type": "alarm",
"time": "02:30",
"message": "Halber Preis"
},
{
"type": "alarm",
"time": "03:00",
"message": "Fete vorbei"
},
{
"type": "checkbox",
"time": "20:30",
"message": "alle T-Shirts ausgegeben"
}
]

104
fete.py
View File

@ -1,104 +0,0 @@
import cmd
import os
import sys
import time
import subprocess
from datetime import datetime, timedelta
alarms_queue = list()
class Fete(cmd.Cmd):
intro = "Willkommen zum Logging und Alarm Skript Ihres Vertrauens. \nBei Fragen help oder ? benutzen."
use_rawinput = False
def do_log(self, toLog):
"Log message with current timestamp"
log = open("log.txt", "a")
datetime_obj = datetime.now()
log_message = datetime_obj.strftime("%x") +", " + datetime_obj.strftime("%X") +" Uhr: "+ toLog
print( log_message )
# log als was besseres als txt, aber meh
log.write(log_message + "\n")
def do_alarm(self, args):
"set an alarm in x minutes for y, example: alarm 30 Cocktail wants stuff"
alarms = open("alarms.txt", "a")
args_arr = args.split()
print("\a")
if len(args_arr) < 2:
print("Heeer! Dir fehlt ein Argument. ")
return
try:
delta = int(args_arr[0])
except ValueError:
print("Das erste Argument muss ne Ganzzahl sein!")
return
args_arr.pop(0)
text = ' '.join(args_arr)
alarm_time = datetime.now() + timedelta(minutes = delta)
print("Alarm set for " + alarm_time.strftime("%X") + " " + text)
alarms.write(alarm_time.strftime("%x") + " " +alarm_time.strftime("%X") + " ~ " + text + "\n")
global alarms_queue
alarms_queue.append((alarm_time,text))
def do_readAlarms(self, minutes):
"read alarms from file into alarm queue that haven't happened or should have happened in the last x minutes (default=5)"
try:
if minutes:
delta = int(minutes)
else:
delta = 5
except ValueError:
print("Zeit bitte in ganzen Minuten!")
return
earliest_alarm_time = datetime.now() - timedelta(minutes = delta)
alarms = open("alarms.txt", "r").readlines()
for line in alarms:
line_sep = line.split(" ~ ")
alarm_time = datetime.strptime(line_sep[0], "%m/%d/%y %H:%M:%S")
if alarm_time > earliest_alarm_time:
global alarms_queue
alarms_queue.append((alarm_time,line_sep[1]))
class NonblockingStdin:
def __init__(self, stdin, idle_callback):
self._stdin = stdin
self._idle_callback = idle_callback
os.set_blocking(self._stdin.fileno(), False)
def readline(self):
buffer = ""
char = self._stdin.read(1)
while char != "\n":
buffer += char
char = self._stdin.read(1)
if char == "":
time.sleep(0.1)
self._idle_callback()
return buffer
def alarm():
alarms_copy = alarms_queue
for alarm_read in alarms_copy:
if datetime.now() >= alarm_read[0]:
subprocess.call(['mpv', './alarm.mp3'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
print("\n\n")
print(alarm_read[1])
print("")
alarms_queue.remove(alarm_read)
def main():
wrapped = NonblockingStdin(sys.stdin, alarm)
fete = Fete(stdin=wrapped)
fete.cmdloop()
if __name__ == '__main__':
main()

View File

@ -1,3 +0,0 @@
02/07/24, 19:18:19Uhr: 02/08/24, 15:18:54Uhr: hilfe, ich habe mein Pasenbrot vergessen
02/08/24, 15:26:12 Uhr: Es ist dumm nen Alarm zusetzen bevor man die alten eingelesen hat
02/08/24, 15:26:52 Uhr: außerdem, doppelte leerzeichen als trennsymbol, das kann nur schief gehen

11196
static/css/style.css Normal file

File diff suppressed because it is too large Load Diff

8
templates/about.html Normal file
View File

@ -0,0 +1,8 @@
{% extends 'base.html' %}
{% block content %}
<h1>{% block title %} About {% endblock %}</h1>
<font color="red">Auf dieser Seite lösen keine Alarme aus!</font><br>
Bei Fragen/Anmerkungen/Problemen hmu: a_luetke17@cs.uni-kl.de
{% endblock %}

6
templates/alarms.html Normal file
View File

@ -0,0 +1,6 @@
<h3>Anstehende Alarme</h3>
{% for alarm in alarms %}
<div>
{{ alarms[alarm].datetime }}: {{ alarms[alarm].message }} <input style="text-align: right;" type="button" value="&#10060;" onclick="deleteAlarm({{alarm}})"/>
</div>
{% endfor %}

46
templates/base.html Normal file
View File

@ -0,0 +1,46 @@
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<title>{% block title %} {% endblock %}</title>
</head>
<body>
<nav class="navbar navbar-expand-md navbar-light bg-light">
<a class="navbar-brand" href="{{ url_for('index')}}">Zentrale</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarNav">
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link" href="{{url_for('todos')}}">ToDos</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{url_for('upload')}}">Upload</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{url_for('help')}}">Hilfe</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{url_for('about')}}">About</a>
</li>
</ul>
</div>
</nav>
<div class="container">
{% block content %} {% endblock %}
</div>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>

77
templates/help.html Normal file
View File

@ -0,0 +1,77 @@
{% extends 'base.html' %}
{% block content %}
<h1>{% block title %} Hilfe! {% endblock %}</h1>
<font color="red">Auf dieser Seite lösen keine Alarme aus!</font>
<h2>Erste Schritte</h2>
<ul>
<li>Schreib was ins log</li>
<li>Lade deine vor-eingestellen Alarme hoch</li>
<li>Trag deinen ersten Alarm ein</li>
<ul>
<li>Schau, dass dein Endgerät nicht stumm geschaltet ist</li>
</ul>
<li>Das war's auch schon</li>
<li>In den Logs, siehst du die bereit geschriebenen Log-Einträge</li>
<li>Die anstehenden Alarme sind Alarme in der Zukunft, bei einem Neustart des Servers werden alle Alarme in der Zukunft <b>und</b> alle Alarme, die in den letzten 2 Minuten stattfinden sollten/stattgefunden haben.</li>
</ul>
<h2>How-To</h2>
<h5><u>Alarme/ToDos hochladen</u></h5>
<p>
Die Datei zum hochladen, sollte folgenden Aufbau haben:
<pre>
[
{
"type": "alarm" | "checkbox" | "both"
"time": "HH:MM",
"message": "Alarm-Text"
},
{
"type": "checkbox"
"message": "Alarm-Text"
}
]
</pre>
Alarme brauchen eine Uhrzeit und eine Alarm Nachricht.
Als Datum wird heute genommen, außer der Zeitpunkt liegt in der Vergangenheit.
Dann wird der Alarm morgen zur angegeben Uhrzeit eingetragen. <br>
Todo-Listeneinträge haben keine Uhrzeit. Wenn was beides hat, braucht es eine Uhrzeit.
<b>Typ "both": sei dir sicher, dass du die zusammen haben willst. Du kannst weder den Alarm löschen ohne das Todo abzuhaken, noch andersrum. </b><br>
Falls ein separates Datumsfeld gewünscht ist, sagt Bescheid, ich sehe da ehrlich gesagt noch keine Notwendikeit.
</p>
<h5><u>Alarm eintragen</u></h5>
<p>
Es braucht eine Uhrzeit und eine Alarm Nachricht. Wenn kein Datum eingetragen ist, wird heute genommen,
außer der Zeitpunkt liegt in der Vergangenheit. Dann wird der Alarm morgen zur angegeben Uhrzeit eingetragen.
</p>
<h5><u>Log eintragen</u></h5>
<p>
Schreibe einen Text, drücke Enter, sei glücklich. Nein, du kannst das nicht korrigieren.
</p>
<h5><u>ToDos</u></h5>
<p>
Abhaken, wenn ein Alarm mit dem ToDo asoziiert ist (über Upload), wird der Alarm automatisch in die vergangenen Alarme geschoben.
Abgehakte ToDos werden grün.
Todos werden automatisch abgehakt, wenn der asoziierte Alarm gelöscht wird.
<br>
<i>"Aber Anika, ich bin doof und hab Fetengehirn und ausversehen das falsche abgehakt. Was mach ich denn jetzt?"</i>
<br>
Fear not, mein junger Padawan. I got you. Unchecking der Checkbox macht den Alarm wieder zurück.
</p>
<h2>Server-Neustart</h2>
Wenn der Server neu gestartet wird, müssen ein paar Kleinigkeiten beachtet werden.
<ul>
<li>Es wird generell alles geladen, der Server vergisst wenig</li>
<li>Überprüf die aktiven Alarme, da stehen jetzt potenziell mehr als du willst. Mach das sofort und unmittelbar,
du hast 15s bis das erste Mal ein Alarm aus den letzten 2 Minuten tönen kann</li>
<li>Bestimmt noch was, das ich nicht weiß</li>
</ul>
<h2>Debugging Hilfe</h2>
Wird gefüllt, sobald ich Probleme/Unklarheiten identifiziere oder gesagt bekomme
{% endblock %}

123
templates/index.html Normal file
View File

@ -0,0 +1,123 @@
{% extends 'base.html' %}
{% block content %}
<h1>{% block title %} Partey! {% endblock %}</h1>
<meta id="my-data" data-alarms="{{alarms}}" data-logs="{{logs}}">
<div class="grid-container">
<div class="savedLogs">
<h3>Logs</h3>
{% for log in logs %}
<div>
{{ log.datetime }}: {{ log.message }}
</div>
{% endfor %}
</div>
<div class="savedAlarms" id="upcomingAlarms">
<h3>Anstehende Alarme</h3>
{% for alarm in alarms %}
<div>
{{ alarms[alarm].datetime }}: {{ alarms[alarm].message }} <input style="text-align: right;" type="button" value="&#10060;" onclick="deleteAlarm({{alarm}})"/>
</div>
{% endfor %}
</div>
<div class="log">
<form method="post" action="/sendLog">
<div class="form-group">
<label for="logMessage">Log:</label>
<input type="text" name="logMessage"
class="form-control"
value="{{ request.form['logMessage'] }}"></input>
<input type="submit" id="saveLog" value="Speichern" style="margin-top: 3mm;"/>
</div>
</form>
</div>
<div class="alarms">
<form method="post" action="/setAlarm">
<div class="form-group">
<div class="datetime" style="padding-left: 3mm;">
<input type="date" name="date"
class="form-control"
value="{{ request.form['date'] }}" style="width: 150px;"></input>
</div>
<div class="datetime">
<input type="time" name="time" class="form-control"
value="{{ request.form['time'] }}" style="width: 85px;" required></input>
</div>
<div style="padding: 3mm;">
<label for="alarmMessage">Alarm-Text</label>
<input type="text" name="alarmMessage"
class="form-control"
value="{{ request.form['alarmMessage'] }}" required></input>
</div>
<input type="submit" id="saveAlarm" value="Speichern" style="padding-left: 3mm; margin-left: 3mm;"/>
</div>
</form>
</div>
<div class="previousAlarms" id="previousAlarms">
<h3>Vergangene Alarme</h3>
<script>
alarms = {{ alarms|tojson }};
async function postAlarm(alarm){
const response = await fetch("http://127.0.0.1:5000/alarms", {
method: "POST",
body: alarm,
});
reloadAlarms();
}
async function deleteAlarm(id){
const response = await fetch("http://127.0.0.1:5000/deletealarm", {
method: "POST",
body: id,
});
reloadAlarms();
}
function reloadAlarms(){
fetch("/processAlarm", {
method: "GET"
}).then(response => {
return response.text();
})
.then(html => {
upcomingAlarms.innerHTML = html
})
fetch("/processpAlarm", {
method: "GET"
}).then(response => {
return response.text();
})
.then(html => {
previousAlarms.innerHTML = html
})
}
function checkAlarms(){
for(var alarmIdx in alarms){
const [dateComponents, timeComponents] = alarms[alarmIdx]['datetime'].split(' ');
const [day, month, year] = dateComponents.split('.');
const [hours, minutes] = timeComponents.split(':');
const date = new Date(+year, +month - 1, +day, +hours, +minutes);
if(date <=new Date()){
postAlarm(alarmIdx);
alert(alarms[alarmIdx].message);
delete alarms[alarmIdx];
}
}
setTimeout(checkAlarms, 15000);
}
checkAlarms();
</script>
{% for alarm in previousAlarms %}
<div>
{{ previousAlarms[alarm].datetime }}: {{ previousAlarms[alarm].message }}
</div>
{% endfor %}
</div>
</div>
{% endblock %}

5
templates/logs.html Normal file
View File

@ -0,0 +1,5 @@
<label id="value_lable">
{% for log in logs %}
{{ log }}<br>
{% endfor %}
</label>

6
templates/palarms.html Normal file
View File

@ -0,0 +1,6 @@
<h3>Previous Alarms</h3>
{% for alarm in previousAlarms %}
<div>
{{ previousAlarms[alarm].datetime }}: {{ previousAlarms[alarm].message }}
</div>
{% endfor %}

69
templates/todo.html Normal file
View File

@ -0,0 +1,69 @@
{% extends 'base.html' %}
{% block content %}
<h1>{% block title %} ToDos {% endblock %}</h1>
<div id="todoList" class="savedTodos">
{% for todo in todos %}
<div>
{% if todos[todo].done%}
<input type="checkbox" style="margin-right: 2mm; " onclick="checkTodo({{todo}})" checked/><font color="green">{{todos[todo].message}}</font>
{% else %}
<input type="checkbox" style="margin-right: 2mm; " onclick="checkTodo({{todo}})"/>{{todos[todo].message}}
{% endif %}
</div>
{% endfor %}
</div>
<form method="post" action="/sendTodo">
<div class="form-group" style="margin-left:2mm">
<label for="todoMessage">Todo:</label>
<input type="text" name="todoMessage" style="width:90%"
class="form-control"
value="{{ request.form['todoMessage'] }}" required></input>
<input type="submit" id="saveTodo" value="Speichern" style="margin-top: 3mm;"/>
</div>
</form>
<script>
async function checkTodo(id){
const response = await fetch("http://127.0.0.1:5000/checktodo", {
method: "POST",
body: id,
});
fetch("/reloadChecklist", {
method: "GET"
}).then(response => {
return response.text();
})
.then(html => {
todoList.innerHTML = html
})
}
// check alarms in here too
alarms = {{ alarms|tojson }};
function checkAlarms(){
for(var alarmIdx in alarms){
const [dateComponents, timeComponents] = alarms[alarmIdx]['datetime'].split(' ');
const [day, month, year] = dateComponents.split('.');
const [hours, minutes] = timeComponents.split(':');
const date = new Date(+year, +month - 1, +day, +hours, +minutes);
if(date <=new Date()){
postAlarm(alarmIdx);
alert(alarms[alarmIdx].message);
delete alarms[alarmIdx];
}
}
setTimeout(checkAlarms, 15000);
}
async function postAlarm(alarm){
const response = await fetch("http://127.0.0.1:5000/alarms", {
method: "POST",
body: alarm,
});
}
checkAlarms();
</script>
{% endblock %}

9
templates/todolist.html Normal file
View File

@ -0,0 +1,9 @@
{% for todo in todos %}
<div>
{% if todos[todo].done%}
<input type="checkbox" style="margin-right: 2mm; " onclick="checkTodo({{todo}})" checked/><font color="green">{{todos[todo].message}}</font>
{% else %}
<input type="checkbox" style="margin-right: 2mm; " onclick="checkTodo({{todo}})"/>{{todos[todo].message}}
{% endif %}
</div>
{% endfor %}

31
templates/upload.html Normal file
View File

@ -0,0 +1,31 @@
{% extends 'base.html' %}
{% block content %}
<h1>{% block title %} Upload {% endblock %}</h1>
<font color="red">Auf dieser Seite lösen keine Alarme aus!</font>
<div>
Akzeptiert .json Dateien. Für den Aufbau der Datei, schau in der Hilfe.
</pre>
</div>
{% if uploadFailed %}
<b>Upload fehlgeschlagen!</b>
{% endif %}
<form method="post" action="/upload" enctype="multipart/form-data">
<div class="form-group">
<div class="upload" >
<input type="file" name="alarmFile"
class="form-control"
value="{{ request.form['alarmFile'] }}"style="padding: 2mm; height: 1.2cm;"
accept=".json"></input>
<input type="submit" id="uploadAlarm" value="Hochladen" style="margin: 2mm;"/>
</div>
</div>
<script>
</script>
</form>
{% endblock %}