Compare commits
18 Commits
2ba8ae8772
...
4d33040ded
Author | SHA1 | Date |
---|---|---|
anika | 4d33040ded | |
Anika | 07b786c7a2 | |
Anika | 5e3a3a8272 | |
Anika | 56cdca0998 | |
Anika | 94a154c363 | |
Anika | 8d91c63a12 | |
Anika | 4314f97ee3 | |
Anika | 58f7ac960d | |
Anika | 887c9f6635 | |
Anika | e07f1c9754 | |
Anika | 64537fe572 | |
Anika | 8008d0262d | |
Anika | acab981293 | |
Anika | e9f8d3ad28 | |
Anika | 43bce4789c | |
Anika | ed8fc409f8 | |
Anika | 0b2ff931b1 | |
Anika | 08a85501ce |
|
@ -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__
|
|
@ -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)
|
||||
|
|
|
@ -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
|
|
@ -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')
|
|
@ -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
104
fete.py
|
@ -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()
|
3
log.txt
3
log.txt
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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 %}
|
|
@ -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="❌" onclick="deleteAlarm({{alarm}})"/>
|
||||
</div>
|
||||
{% endfor %}
|
|
@ -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>
|
|
@ -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 %}
|
|
@ -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="❌" 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 %}
|
|
@ -0,0 +1,5 @@
|
|||
<label id="value_lable">
|
||||
{% for log in logs %}
|
||||
{{ log }}<br>
|
||||
{% endfor %}
|
||||
</label>
|
|
@ -0,0 +1,6 @@
|
|||
<h3>Previous Alarms</h3>
|
||||
{% for alarm in previousAlarms %}
|
||||
<div>
|
||||
{{ previousAlarms[alarm].datetime }}: {{ previousAlarms[alarm].message }}
|
||||
</div>
|
||||
{% endfor %}
|
|
@ -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 %}
|
|
@ -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 %}
|
|
@ -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 %}
|
Loading…
Reference in New Issue