diff options
-rw-r--r-- | pysite/decorators.py | 2 | ||||
-rw-r--r-- | pysite/views/wiki/edit.py | 14 | ||||
-rw-r--r-- | pysite/views/wiki/page.py | 2 | ||||
-rw-r--r-- | pysite/views/wiki/render.py | 34 | ||||
-rw-r--r-- | templates/wiki/page_edit.html | 46 |
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 |