diff options
| -rw-r--r-- | pysite/tables.py | 2 | ||||
| -rw-r--r-- | pysite/views/staff/jams/create.py | 12 | ||||
| -rw-r--r-- | pysite/views/staff/jams/forms/preamble_edit.py | 45 | ||||
| -rw-r--r-- | pysite/views/staff/jams/forms/view.py | 4 | ||||
| -rw-r--r-- | templates/main/jams/join.html | 4 | ||||
| -rw-r--r-- | templates/staff/jams/forms/preamble_edit.html | 148 | ||||
| -rw-r--r-- | templates/staff/jams/forms/view.html | 1 | 
7 files changed, 215 insertions, 1 deletions
| diff --git a/pysite/tables.py b/pysite/tables.py index e99ca989..a9a0dc88 100644 --- a/pysite/tables.py +++ b/pysite/tables.py @@ -60,6 +60,8 @@ TABLES = {          primary_key="number",          keys=sorted([              "number",  # int +            "preamble_rst",  # str +            "preamble_html",  # str              "questions"  # list[dict[str, str]]  {title, type, input_type, options?}          ])      ), diff --git a/pysite/views/staff/jams/create.py b/pysite/views/staff/jams/create.py index e88056c5..ef61cbef 100644 --- a/pysite/views/staff/jams/create.py +++ b/pysite/views/staff/jams/create.py @@ -1,3 +1,5 @@ +import datetime +  from flask import redirect, request, url_for  from werkzeug.exceptions import BadRequest @@ -35,6 +37,16 @@ class StaffView(RouteView, DBMixin):          data["state"] = "planning"          data["number"] = self.get_next_number() +        # Convert given datetime strings into actual objects, adding timezones to keep rethinkdb happy +        date_start = datetime.datetime.strptime(data["date_start"], "%Y-%m-%d %H:%M") +        date_start = date_start.replace(tzinfo=datetime.timezone.utc) + +        date_end = datetime.datetime.strptime(data["date_end"], "%Y-%m-%d %H:%M") +        date_end = date_end.replace(tzinfo=datetime.timezone.utc) + +        data["date_start"] = date_start +        data["date_end"] = date_end +          self.db.insert(self.table_name, data)          return redirect(url_for("staff.jams.index")) diff --git a/pysite/views/staff/jams/forms/preamble_edit.py b/pysite/views/staff/jams/forms/preamble_edit.py new file mode 100644 index 00000000..c17692d3 --- /dev/null +++ b/pysite/views/staff/jams/forms/preamble_edit.py @@ -0,0 +1,45 @@ +import datetime + +from flask import redirect, request, url_for +from werkzeug.exceptions import BadRequest, NotFound + +from pysite.base_route import RouteView +from pysite.constants import ALL_STAFF_ROLES +from pysite.decorators import csrf, require_roles +from pysite.mixins import DBMixin +from pysite.rst import render + + +class StaffView(RouteView, DBMixin): +    path = "/jams/form/<int:jam>/preamble" +    name = "jams.forms.preamble.edit" + +    table_name = "code_jam_forms" +    jams_table = "code_jams" + +    @require_roles(*ALL_STAFF_ROLES) +    def get(self, jam): +        jam_obj = self.db.get(self.jams_table, jam) + +        if not jam_obj: +            return NotFound() + +        form_obj = self.db.get(self.table_name, jam) +        return self.render("staff/jams/forms/preamble_edit.html", jam=jam_obj, form=form_obj) + +    @require_roles(*ALL_STAFF_ROLES) +    @csrf +    def post(self, jam): +        jam_obj = self.db.get(self.table_name, jam) + +        if not jam_obj: +            return NotFound() + +        form_obj = self.db.get(self.table_name, jam) + +        preamble_rst = request.form.get("preamble_rst") + +        form_obj["preamble_rst"] = preamble_rst +        form_obj["preamble_html"] = render(preamble_rst, link_headers=False)["html"] + +        return redirect(url_for("staff.jams.forms.view", jam=jam)) diff --git a/pysite/views/staff/jams/forms/view.py b/pysite/views/staff/jams/forms/view.py index eaa910f2..8d4e16ad 100644 --- a/pysite/views/staff/jams/forms/view.py +++ b/pysite/views/staff/jams/forms/view.py @@ -28,7 +28,9 @@ class StaffView(RouteView, DBMixin):          if not form_obj:              form_obj = {                  "number": jam, -                "questions": [] +                "questions": [], +                "preamble_rst": "", +                "preamble_html": ""              }              self.db.insert(self.forms_table, form_obj) diff --git a/templates/main/jams/join.html b/templates/main/jams/join.html index ffa80cb5..8e762ff2 100644 --- a/templates/main/jams/join.html +++ b/templates/main/jams/join.html @@ -118,6 +118,10 @@          </p>          <hr class="uk-divider-icon" /> +        {{ form.preamble_html }} + +        <hr class="uk-divider-icon" /> +          {% if jam.state != "announced" %}              <p class="uk-alert uk-alert-primary">                  Unfortunately, we're not accepting applications for this code jam right now - but we appreciate your diff --git a/templates/staff/jams/forms/preamble_edit.html b/templates/staff/jams/forms/preamble_edit.html new file mode 100644 index 00000000..6e3fec0d --- /dev/null +++ b/templates/staff/jams/forms/preamble_edit.html @@ -0,0 +1,148 @@ +{% extends "main/base.html" %} +{% block title %}Staff | Forms | Edit Preamble{% endblock %} +{% block og_title %}Staff | Forms | Edit Preamble{% endblock %} +{% block extra_head %} +<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.3.3/ace.js" type="application/javascript"></script> +{% endblock %} +{% block content %} +    <div class="uk-container uk-container-small uk-section"> +        <h1 class="uk-text-center">Form: Edit Preamble</h1> + +        <form action="{{ url_for("staff.jams.forms.preamble.edit", jam=jam.number) }}" method="post" class="uk-form-horizontal"> +            <div> +                <div class="uk-form-label"> +                    <label class="uk-form-label">Preamble (RST)</label> +                </div> + +                <div class="uk-form-controls uk-form-controls-text"> +                    <div id="editor" class="uk-textarea" style="resize: vertical; min-height: 15rem;">{{ form.preamble_rst }}</div> +                </div> + +                <input type="hidden" name="preamble_rst" id="preamble_rst" value="{{ form.preamble_rst }}" /> +            </div> + +            <input type="hidden" name="csrf_token" id="csrf_token" value="{{ csrf_token() }}"/> + +            <div class="uk-align-center uk-text-center"> +                <a id="back" class="uk-button uk-button-default" href="{{ url_for("staff.jams.forms.view", jam=jam.number) }}"> +                    <i class="uk-icon fa-fw far fa-arrow-left"></i>  Back +                </a> +                <button class="uk-button uk-button-secondary" type="button" id="preview"> +                    <i class="uk-icon fa-fw far fa-eye"></i>  Preview +                </button> +                <button id="done" class="uk-button uk-button-primary" type="submit" disabled> +                    <i class="uk-icon fa-fw far fa-check"></i>  Done +                </button> +            </div> +        </form> +    </div> + +     <div id="preview-modal" class="uk-flex-top" uk-modal> +        <div class="uk-modal-dialog"> +            <button class="uk-modal-close-default" type="button" uk-close></button> + +            <div class="uk-modal-body"> +                <h2>Form: {{ jam.number }}</h2> + +                <div id="preview-div"> +                    {{ jam.preamble_html | safe }} +                </div> +            </div> + +            <div class="uk-modal-footer"> +                <div class="uk-text-center"> +                    <button class="uk-button uk-button-default uk-modal-close" type="button" id="state-cancel"> +                        <i class="uk-icon fa-fw far fa-arrow-left"></i>  Close +                    </button> +                </div> +            </div> +        </div> +    </div> + +    <script type="application/javascript"> +        "use strict"; + +        let csrf_token = "{{ csrf_token() }}"; +        let modal = UIkit.modal(document.getElementById("preview-modal")); +        let preview_url = "{{ url_for("staff.render") }}"; + +        function do_preview(callback) { +            let oReq = new XMLHttpRequest(); + +            oReq.addEventListener("load", function() { +                let response = JSON.parse(this.responseText); + +                if (response.error !== undefined) { +                    document.getElementById("done").disabled = true; + +                    if (response.error_lines !== undefined) { +                        editor.session.setAnnotations(response.error_lines); +                        document.getElementById("preview-div").innerHTML ="<h3>Error - see editor margin</h3>"; +                    } else { +                        console.log("Error: " + response.error); +                        document.getElementById("preview-div").innerHTML ="<h3>Error</h3><p>" + response.error + "<p>"; +                    } +                } else { +                    document.getElementById("done").disabled = false; +                    document.getElementById("preview-div").innerHTML = response.data; + +                    editor.session.setAnnotations([]); +                } + +                if (callback !== undefined) { +                    callback(); +                } +            }); + +            let data = editor.getValue(); + +            if (data.replace("\s", "").length < 1) { +                document.getElementById("done").disabled = true; + +                if (callback !== undefined) { +                    UIkit.notification({ +                        "message": "Please enter some text to preview", +                        "status": "danger", +                        "pos": "bottom-center", +                        "timeout": 5000 +                    }); +                } +                return false; +            } + +            oReq.open("POST", preview_url); + +            oReq.setRequestHeader("Content-type", "application/json"); +            oReq.setRequestHeader("X-CSRFToken", csrf_token); + +            oReq.send(JSON.stringify({"data": editor.getValue()})); + +            return false; +        } + +        document.getElementById("preview").onclick = function() { +            do_preview(function() { +                modal.show(); +            }) +        }; + +        let editor = ace.edit("editor"); +        let timer; + +        editor.session.setMode("ace/mode/rst"); +        editor.session.setUseWrapMode(true); + +        editor.setTheme("ace/theme/iplastic"); +        editor.setShowPrintMargin(false); + +        editor.on("input", function() { +            document.getElementById("done").disabled = true; +            document.getElementById("preamble_rst").value = editor.getValue(); + +            if (timer !== undefined) { +                clearTimeout(timer); +            } +            timer = setTimeout(do_preview, 1000); +        }); +    </script> +{% endblock %} diff --git a/templates/staff/jams/forms/view.html b/templates/staff/jams/forms/view.html index 6d0a86af..46474ae9 100644 --- a/templates/staff/jams/forms/view.html +++ b/templates/staff/jams/forms/view.html @@ -10,6 +10,7 @@          <h1>Application Form {{ jam.number }}: {{ jam.title }}</h1>          <a class="uk-button uk-button-default" href="{{ url_for("staff.jams.index") }}"><i class="uk-icon fa-fw far fa-arrow-left"></i>  Back</a> +        <a class="uk-button uk-button-secondary" href="{{ url_for("staff.jams.forms.preamble.edit", jam=jam.number) }}" id="preamble-button"><i class="uk-icon fa-fw far fa-pencil"></i>  Edit Preamble</a>          <button class="uk-button uk-button-primary" id="add-button"><i class="uk-icon fa-fw far fa-plus"></i>  Add Question</button>       {# <a class="uk-button uk-button-secondary" target="_blank" href="{{ url_for("staff.index") }}"><i class="uk-icon fa-fw far fa-eye"></i>  Preview</a>  #} | 
