aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Gareth Coles <[email protected]>2018-04-05 14:14:05 +0100
committerGravatar Gareth Coles <[email protected]>2018-04-05 14:14:05 +0100
commit6a5de7cfdf5b419acd8258d5dbbd0b164662c140 (patch)
tree6a15fb90025330f615c954cb3a3aa7119410061e
parentThat was a little dumb. (diff)
More work towards the wiki
-rw-r--r--pysite/decorators.py2
-rw-r--r--pysite/views/wiki/edit.py14
-rw-r--r--pysite/views/wiki/page.py2
-rw-r--r--pysite/views/wiki/render.py34
-rw-r--r--templates/wiki/page_edit.html46
5 files changed, 91 insertions, 7 deletions
diff --git a/pysite/decorators.py b/pysite/decorators.py
index 653489b4..426d4846 100644
--- a/pysite/decorators.py
+++ b/pysite/decorators.py
@@ -34,7 +34,7 @@ def require_roles(*roles: int):
if data:
for role in roles:
- if role in data["roles"]:
+ if role in data.get("roles", []):
return f(self, *args, **kwargs)
if isinstance(self, APIView):
diff --git a/pysite/views/wiki/edit.py b/pysite/views/wiki/edit.py
index 8f6c22e3..23a281dc 100644
--- a/pysite/views/wiki/edit.py
+++ b/pysite/views/wiki/edit.py
@@ -1,5 +1,5 @@
# coding=utf-8
-from flask import url_for
+from flask import url_for, request
from werkzeug.utils import redirect
from pysite.base_route import RouteView
@@ -17,9 +17,19 @@ class EditView(RouteView, DBMixin):
@require_roles(*ALL_STAFF_ROLES)
def get(self, page):
- return self.render("wiki/page_edit.html", page=page)
+ rst = ""
+ title = ""
+
+ obj = self.db.get(self.table_name, page)
+
+ if obj:
+ rst = obj["rst"]
+ title = obj["title"]
+
+ return self.render("wiki/page_edit.html", page=page, rst=rst, title=title)
@require_roles(*ALL_STAFF_ROLES)
@csrf
def post(self, page):
+ rst = request.form["rst"]
return redirect(url_for("wiki.page", page=page), code=303) # Redirect, ensuring a GET
diff --git a/pysite/views/wiki/page.py b/pysite/views/wiki/page.py
index eb4c2429..01c8fa8a 100644
--- a/pysite/views/wiki/page.py
+++ b/pysite/views/wiki/page.py
@@ -27,7 +27,7 @@ class PageView(RouteView, DBMixin):
if not self.logged_in:
return False
- roles = self.user_data["roles"]
+ roles = self.user_data.get("roles", [])
for role in roles:
if role in ALL_STAFF_ROLES:
diff --git a/pysite/views/wiki/render.py b/pysite/views/wiki/render.py
new file mode 100644
index 00000000..01b5e6fa
--- /dev/null
+++ b/pysite/views/wiki/render.py
@@ -0,0 +1,34 @@
+# coding=utf-8
+from docutils.core import publish_parts
+from flask import jsonify
+from schema import Schema
+
+from pysite.base_route import APIView
+from pysite.constants import ALL_STAFF_ROLES, ValidationTypes
+from pysite.decorators import csrf, require_roles, api_params
+
+SCHEMA = Schema([{
+ "data": str
+}])
+
+
+class RenderView(APIView):
+ path = "/render" # "path" means that it accepts slashes
+ name = "render"
+
+ @csrf
+ @require_roles(*ALL_STAFF_ROLES)
+ @api_params(schema=SCHEMA, validation_type=ValidationTypes.json)
+ def post(self, data):
+ if not len(data):
+ return jsonify({"error": "No data!"})
+
+ data = data[0]["data"]
+ try:
+ html = publish_parts(
+ source=data, writer_name="html5", settings_overrides={"traceback": True, "halt_level": 2}
+ )["html_body"]
+
+ return jsonify({"data": html})
+ except Exception as e:
+ return jsonify({"error": str(e)})
diff --git a/templates/wiki/page_edit.html b/templates/wiki/page_edit.html
index 5601cbbf..97a5161c 100644
--- a/templates/wiki/page_edit.html
+++ b/templates/wiki/page_edit.html
@@ -4,8 +4,48 @@
{% block og_description %}Landing page for the wiki{% endblock %}
{% block content %}
<div class="uk-container uk-section">
- <h1 class="uk-title uk-text-center">
- Placeholder text.
- </h1>
+ <form action="{{ url_for("wiki.edit", page=page) }}" method="post">
+ <label for="title">Title: </label>
+ <input name="title" id="title" value="{{ title }}" class="uk-input" />
+ <label for="rst">Document: </label>
+ <textarea name="rst" id="rst" class="uk-textarea">{{ rst }}</textarea>
+ <button value="Preview" id="preview">Preview</button>
+ <button type="submit" value="Save">Save</button>
+ <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
+ </form>
+
+ <div id="preview-div" style="border: 1px solid grey;">
+ <p>Preview will appear here.</p>
+ </div>
</div>
+
+ <script type="application/javascript">
+ "use strict";
+
+ let csrf_token = "{{ csrf_token() }}";
+
+ document.getElementById("preview").onclick = function(event) {
+ let oReq = new XMLHttpRequest();
+ let data = document.getElementById("rst").value;
+
+ oReq.addEventListener("load", function() {
+ let response = JSON.parse(this.responseText);
+
+ if (response.error !== undefined) {
+ console.log("Error: " + response.error)
+ } else {
+ document.getElementById("preview-div").innerHTML = response.data;
+ }
+ });
+
+ oReq.open("POST", "/render");
+
+ oReq.setRequestHeader("Content-type", "application/json");
+ oReq.setRequestHeader("X-CSRFToken", csrf_token);
+
+ oReq.send(JSON.stringify({"data": data}));
+
+ return false;
+ }
+ </script>
{% endblock %} \ No newline at end of file