diff --git a/uebung7/uebung07-examples/style.css b/uebung7/uebung07-examples/style.css new file mode 100644 index 0000000..a3457a8 --- /dev/null +++ b/uebung7/uebung07-examples/style.css @@ -0,0 +1,52 @@ +body, html { + font-family: sans-serif; + background-color: #444; + color: white; + text-align: center; +} + +a { + color: white; +} + +input, textarea, table { + max-width: 100%; + width: 100%; + padding: 1em; + margin: 1em auto; + background-color: #fff; + border-radius: 1em; + border: 1px solid darkblue; + color: black; + text-align: justify; + box-sizing: border-box; +} + +form { + max-width: 30em; + width: 100%; + margin: 0 auto; +} + +table { + max-width: 30em; + +} + +.open { + /*...*/ +} + +.done { + text-decoration: line-through; +} + + +td { + width: auto; +} + +td.min { + width: 1%; + +} \ No newline at end of file diff --git a/uebung7/uebung07-examples/tasks-delete.py b/uebung7/uebung07-examples/tasks-delete.py new file mode 100644 index 0000000..5787e53 --- /dev/null +++ b/uebung7/uebung07-examples/tasks-delete.py @@ -0,0 +1,24 @@ +#!/usr/bin/python3 +# coding=utf-8 + +import cgi + +from tasks_lib import enc_print +from tasks_lib import delete_task, redirect, print_header, print_footer, print_exception_page + +try: + # Zugriff auf die Formulardaten + form = cgi.FieldStorage(encoding='utf8') + filename = form.getfirst('timestamp') + + assert filename is not None + + # Task löschen + delete_task(filename) + + # Weiterleitung auf Übersichtsseite + redirect("tasks-show.py") + +# Rudimentäres Error-Handling ... +except Exception as e: + print_exception_page("Fehler", "Fehler beim Löschen!", e) diff --git a/uebung7/uebung07-examples/tasks-show.py b/uebung7/uebung07-examples/tasks-show.py new file mode 100644 index 0000000..fde8acd --- /dev/null +++ b/uebung7/uebung07-examples/tasks-show.py @@ -0,0 +1,32 @@ +#!/usr/bin/python3 +# coding=utf-8 + + +from tasks_lib import read_all_tasks, get_done_tasks, get_open_tasks +from tasks_lib import print_header, print_tasks, print_footer, print_form, print_navigation +import cgi + +form = cgi.FieldStorage(encoding='utf8') + +# Welchen Zustand sollen die angezeigten Tasks haben? Default-Wert: all +state = form.getfirst('state', 'all') + +all_tasks = read_all_tasks() + +# Filtere die Tasks nach dem entsprechenden Zustand +if state == "open": + tasks = get_open_tasks(all_tasks) + prefix = "offene" +elif state == "done": + tasks = get_done_tasks(all_tasks) + prefix = "erledigte" +else: + tasks = all_tasks + prefix = "" + +# Ab hier:Ausgabe des HTML-Codes +print_header("{} {} Aufgaben".format(len(tasks), prefix)) +print_navigation() +print_tasks(tasks) +print_form() +print_footer() diff --git a/uebung7/uebung07-examples/tasks-store.py b/uebung7/uebung07-examples/tasks-store.py new file mode 100644 index 0000000..08ae6d4 --- /dev/null +++ b/uebung7/uebung07-examples/tasks-store.py @@ -0,0 +1,26 @@ +#!/usr/bin/python3 +# coding=utf-8 + +import cgi + +from tasks_lib import enc_print +from tasks_lib import create_task, write_task, redirect, print_exception_page + +try: + # Zugriff auf Formulardaten + form = cgi.FieldStorage(encoding='utf8') + title = form.getfirst('title') + + assert title is not None + + # Task erstellen und speichern + task = create_task(title) + write_task(task["timestamp"], task) + + # Weiterleitung auf Übersichtsseite + redirect("tasks-show.py") + + +# Rudimentäres Error-Handling ... +except Exception as e: + print_exception_page("Fehler", "Fehler beim Hinzufügen!", e) diff --git a/uebung7/uebung07-examples/tasks-update.py b/uebung7/uebung07-examples/tasks-update.py new file mode 100644 index 0000000..3ed6b67 --- /dev/null +++ b/uebung7/uebung07-examples/tasks-update.py @@ -0,0 +1,25 @@ +#!/usr/bin/python3 +# coding=utf-8 + +import cgi + +from tasks_lib import enc_print +from tasks_lib import flip_task_state, read_task, write_task, redirect, print_exception_page + +try: + # Zugriff auf Formulardaten + form = cgi.FieldStorage(encoding='utf8') + filename = form.getfirst('timestamp') + + assert filename is not None + + # Zustand des Tasks ändern und speichern + task = flip_task_state(read_task(filename)) + write_task(filename, task) + + # Weiterleitung auf Übersichtsseite + redirect("tasks-show.py") + +# Rudimentäres Error-Handling ... +except Exception as e: + print_exception_page("Fehler", "Fehler beim Ändern!", e) diff --git a/uebung7/uebung07-examples/tasks/2019-06-14-11-11-14 b/uebung7/uebung07-examples/tasks/2019-06-14-11-11-14 new file mode 100644 index 0000000..2639fba --- /dev/null +++ b/uebung7/uebung07-examples/tasks/2019-06-14-11-11-14 @@ -0,0 +1 @@ +{"timestamp": "2019-06-14-11-11-14", "state": "open", "title": "F\u00fcr die Intech-Klausur lernen"} \ No newline at end of file diff --git a/uebung7/uebung07-examples/tasks/2019-06-14-11-11-27 b/uebung7/uebung07-examples/tasks/2019-06-14-11-11-27 new file mode 100644 index 0000000..a38fa81 --- /dev/null +++ b/uebung7/uebung07-examples/tasks/2019-06-14-11-11-27 @@ -0,0 +1 @@ +{"title": "Intech-\u00dcbungsblatt fertig machen", "state": "done", "timestamp": "2019-06-14-11-11-27"} \ No newline at end of file diff --git a/uebung7/uebung07-examples/tasks_lib.py b/uebung7/uebung07-examples/tasks_lib.py new file mode 100644 index 0000000..1364f26 --- /dev/null +++ b/uebung7/uebung07-examples/tasks_lib.py @@ -0,0 +1,208 @@ +# coding=utf-8 +import datetime +import json +import os +import sys +import time +from os import listdir +from os.path import isfile, join + + +# ------------------------------------------------------------------------------------- +# Hilfsfunktionen +# ------------------------------------------------------------------------------------- + +# enc_print zur Behebung des UTF-Problems mit dem Übungsserver +def enc_print(string='', encoding='utf8'): + sys.stdout.buffer.write(string.encode(encoding) + b'\n') + + +# Erzeugt einen HTTP-Redirect +def redirect(location): + print("Status: 303 See Other") + print("Location: {}".format(location)) + print() + + +# Liefert die aktuelle Uhrzeit im Format Jahr-Monat-Tag-Stunde-Minute-Sekunde +def get_timestamp(): + return time.strftime("%Y-%m-%d-%H-%M-%S") + + +# Konvertiert einene Timestamp im Format Jahr-Monat-Tag-Stunde-Minute-Sekunde in die Form Tag.Monat.Jahr +def readable_timestamp(timestamp): + return datetime.datetime.strptime(timestamp, "%Y-%m-%d-%H-%M-%S").strftime("%d.%m.%Y") + + +# ------------------------------------------------------------------------------------- +# Layout-Funktionen +# ------------------------------------------------------------------------------------- + +# Gibt den Header der Seite mit optionalem Titel aus +def print_header(title=""): + enc_print("Content-type: text/html\n") + + enc_print(""" + + +
+ ++ Alle Aufgaben anzeigen - + Offene Aufgaben anzeigen - + Bereits erledigte Aufgaben anzeigen +
+ """) + + +# Gibt alle Tasks in einer Tabelle aus +def print_tasks(tasks): + if len(tasks) == 0: + enc_print("Noch keine Aufgaben vorhanden ...") + else: + enc_print("{} ({}) | ++ | + |
{}
".format(message)) + + # Exception ausgeben + enc_print(repr(exception)) + + print_footer() + + +# ------------------------------------------------------------------------------------- +# IO-Funktionen +# ------------------------------------------------------------------------------------- + +TASKS_PATH = "tasks/" + + +# Speichert den Task task json-codiert unter dem Namen filename +def write_task(filename, task): + # Speichere das Dictionary JSON-codiert + with open(join(TASKS_PATH, filename), 'w') as outfile: + json.dump(task, outfile) + + +# Liest den json-codiert gespeicherten Task mit Dateiname filename ein +def read_task(filename): + # Öffne den JSON-codierten Task + with open(join(TASKS_PATH, filename), 'r') as json_file: + # Decodiere die JSON-Datei in ein Dictionary + return json.load(json_file) + + +# Liefert alle gespeicherten Tasks +def read_all_tasks(): + # Liefert alle Dateien im Ordner tasks_path + file_names = [f for f in listdir(TASKS_PATH) if isfile(join(TASKS_PATH, f))] + + # Liest alle vorher bestimmten Tasks ein + tasks = [read_task(f) for f in file_names] + + # Sortiert die Tasks aufsteigend nach title (mit reverse=TRUE absteigend) + sorted_tasks = sorted(tasks, key=lambda t: t["title"], reverse=False) + + return sorted_tasks + + +# Löscht den Task mit Dateiname filename +def delete_task(filename): + os.remove(join(TASKS_PATH, filename)) + + +# ------------------------------------------------------------------------------------- +# Task-Funktionen +# ------------------------------------------------------------------------------------- + + +# Erstellt einen neuen Task mit dem Titel title, dem aktuellen timestamp und dem state open +def create_task(title): + # Rufe die aktuelle Uhrzeit ab + timestamp = get_timestamp() + + # Erstelle den Task als Dictionary + task = { + "title": title, + "timestamp": timestamp, + "state": "open" + } + + return task + + +# Flippt den Zustand des Tasks zwischen done und open +def flip_task_state(task): + if task['state'] == 'done': + task['state'] = 'open' + else: + task['state'] = 'done' + + return task + + +# Filtert all_tasks nach allen Tasks state == open +def get_open_tasks(all_tasks): + open_tasks = [t for t in all_tasks if t["state"] == "open"] + + return open_tasks + + +# Filtert all_tasks nach allen Tasks state == done +def get_done_tasks(all_tasks): + open_tasks = [t for t in all_tasks if t["state"] == "done"] + + return open_tasks