home · contact · privacy
Initial commit.
authorChristian Heller <c.heller@plomlompom.de>
Sat, 7 Nov 2020 18:33:05 +0000 (19:33 +0100)
committerChristian Heller <c.heller@plomlompom.de>
Sat, 7 Nov 2020 18:33:05 +0000 (19:33 +0100)
guiltcards.py [new file with mode: 0755]
requirements.txt [new file with mode: 0644]
run.sh [new file with mode: 0755]
views/card.tpl [new file with mode: 0644]
views/card_form.tpl [new file with mode: 0644]
views/cards.tpl [new file with mode: 0644]
views/delete_card.tpl [new file with mode: 0644]
views/intro.tpl [new file with mode: 0644]

diff --git a/guiltcards.py b/guiltcards.py
new file mode 100755 (executable)
index 0000000..8bf3cb4
--- /dev/null
@@ -0,0 +1,101 @@
+#!/usr/bin/env python3
+from bottle import debug, run, default_app, get, view, request, post, redirect
+import os
+import json
+
+web_path = ''
+#web_path = '/guiltcards'
+cards_dir = 'cards/'
+
+def get_card_data(card_id):
+    if not os.path.exists(cards_dir):
+        os.makedirs(cards_dir)
+    path_card = cards_dir + card_id
+    if os.path.exists(path_card):
+        with open(path_card, 'r') as f:
+            data = json.loads(f.read())#f.read()
+    else:
+        data = {'title': '?',
+                'prompt':'?',
+                'answers': ['?', '?']}
+    return data
+
+@get(web_path + '/')
+@view('intro')
+def intro():
+    return dict()
+
+@get(web_path + '/cards')
+@view('cards')
+def list_cards():
+    if not os.path.exists(cards_dir):
+        os.makedirs(cards_dir)
+    card_ids = os.listdir(cards_dir)
+    return dict(web_path=web_path,
+                card_ids=card_ids)
+
+@get(web_path + '/cards/')
+def new_card():
+    card_id = request.query.get('card_id')
+    redirect(web_path + '/cards/' + card_id + '/form')
+
+@get(web_path + '/cards/<card_id>/view')
+@view('card')
+def show_card(card_id):
+    data = get_card_data(card_id)
+    return dict(web_path=web_path,
+                title=data['title'],
+                prompt=data['prompt'],
+                answers=data['answers'])
+
+@post(web_path + '/cards/<card_id>')
+def update_card(card_id):
+    if not os.path.exists(cards_dir):
+        os.makedirs(cards_dir)
+    path_card = cards_dir + card_id
+    json_dict = {
+        'title': request.forms.get('title'),
+        'prompt': request.forms.get('prompt'),
+        'answers': request.forms.getall('answer')
+    }
+    json_dict['answers'] = [answer for answer in json_dict['answers']
+                            if answer.strip() != '']
+    with open(path_card, 'w') as f:
+        f.write(json.dumps(json_dict, indent=4))
+    redirect(web_path + '/cards/' + card_id + '/view')
+
+@get(web_path + '/cards/<card_id>/form')
+@view('card_form')
+def card_form(card_id):
+    data = get_card_data(card_id)
+    card_path = cards_dir + '/' + card_id
+    deletable = False
+    if os.path.exists(card_path):
+        deletable = True
+    return dict(web_path=web_path,
+                card_id=card_id,
+                title=data['title'],
+                prompt=data['prompt'],
+                answers=data['answers'],
+                deletable=deletable)
+
+@get(web_path + '/cards/<card_id>/delete')
+@view('delete_card')
+def delete_card_ask(card_id):
+    return dict(web_path=web_path,
+                card_id=card_id)
+
+@post(web_path + '/cards/<card_id>/delete')
+def delete_card_do(card_id):
+    card_path = cards_dir + '/' + card_id
+    if os.path.exists(card_path):
+        os.remove(card_path)
+    redirect(web_path + '/cards')
+
+# App running.
+
+if __name__ == "__main__":
+    debug(True)
+    run(port=8000)
+else:
+    app = application = default_app()
diff --git a/requirements.txt b/requirements.txt
new file mode 100644 (file)
index 0000000..310dc0b
--- /dev/null
@@ -0,0 +1 @@
+bottle
diff --git a/run.sh b/run.sh
new file mode 100755 (executable)
index 0000000..ba51215
--- /dev/null
+++ b/run.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+# This script runs the guilt cards web app
+# in a virtual environment with temporarily
+# installed required external Python libraries.
+set -e
+
+DIR_ENV=.temp_env
+
+python3 -m venv $DIR_ENV 
+source $DIR_ENV/bin/activate
+pip install -r requirements.txt
+echo
+set +e
+uwsgi --socket 127.0.0.1:9000 --wsgi-file guiltcards.py 
+set -e
+deactivate
+rm -rf $DIR_ENV 
diff --git a/views/card.tpl b/views/card.tpl
new file mode 100644 (file)
index 0000000..8e89f50
--- /dev/null
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html>
+<style>
+  #card {
+      box-sizing: border-box;
+      border: 30px solid #aaaaaa;
+      width: 200px;
+      height: 400px; }
+</style>
+<body>
+  <div id="card">
+    <h1 id="title">{{ title }}</h1>
+    <p id="prompt">{{ prompt }}</p>
+    <ul id="answers">
+    % for answer in answers:
+      <li>{{ answer }}</li>
+    % end
+    <ul/>
+  </div>
+<a href="{{ web_path }}/cards">back to overview</a>
+</body>
+</html>
diff --git a/views/card_form.tpl b/views/card_form.tpl
new file mode 100644 (file)
index 0000000..a2aa551
--- /dev/null
@@ -0,0 +1,25 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<form action="{{ web_path }}/cards/{{ card_id }}" method="POST">
+title: <input type="text" name="title" value="{{ title }}" /><br />
+prompt: <input type="text" name="prompt" value="{{ prompt }}" /><br />
+% for answer in answers:
+answer: <input type="text" name="answer" value="{{ answer }}" /><br />
+% end
+answer: <input type="text" name="answer" /><br />
+answer: <input type="text" name="answer" /><br />
+answer: <input type="text" name="answer" /><br />
+<input type="submit" value="OK" />
+</form>
+<p>
+(leave specific answer fields empty to remove them as answer options)
+</p>
+% if deletable:
+<p>
+Or would you rather <a href="{{ web_path }}/cards/{{ card_id }}/delete">DELETE</a> this card?
+</p>
+% end
+</form>
+</body>
+</html>
diff --git a/views/cards.tpl b/views/cards.tpl
new file mode 100644 (file)
index 0000000..dbf5ea6
--- /dev/null
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<ul>
+% for card_id in card_ids:
+<li><a href="{{ web_path }}/cards/{{card_id}}/view">{{card_id}}</a> (<a href="{{ web_path }}/cards/{{card_id}}/form">edit</a>)</li>
+% end
+</ul>
+<form action="{{ web_path }}/cards/" method="GET">
+add another? name: <input type="text" name="card_id" />
+</form>
+</body>
+</html>
diff --git a/views/delete_card.tpl b/views/delete_card.tpl
new file mode 100644 (file)
index 0000000..45b6449
--- /dev/null
@@ -0,0 +1,9 @@
+<!DOCTYPE HTML>
+<html>
+<body>
+<form action="{{ web_path }}/cards/{{ card_id }}/delete" method="POST">
+<input type="submit" value="delete {{card_id}}?" />
+</form>
+<a href="{{ web_path }}/cards">Nah, better not …</a>
+</body>
+</html>
diff --git a/views/intro.tpl b/views/intro.tpl
new file mode 100644 (file)
index 0000000..e24a7a0
--- /dev/null
@@ -0,0 +1,5 @@
+<html>
+<body>
+Hey there!
+</body>
+</html>