diff --git a/app/__init__.py b/app/__init__.py index 3a1f54fc14b5e002a08fc4a31be30f8a502f0bd8..aef0c2b69986b21ead737e6326c7673e1162ff1c 100644 --- a/app/__init__.py +++ b/app/__init__.py @@ -48,4 +48,7 @@ def create_app(config_name): from .services import services as services_blueprint app.register_blueprint(services_blueprint, url_prefix='/services') + from .test import test as test_blueprint + app.register_blueprint(test_blueprint, url_prefix='/test') + return app diff --git a/app/templates/test/index.html.j2 b/app/templates/test/index.html.j2 new file mode 100644 index 0000000000000000000000000000000000000000..1dc49c1ed123b0c6624f8f473c885a4652de4f5e --- /dev/null +++ b/app/templates/test/index.html.j2 @@ -0,0 +1,84 @@ +{% extends "limited_width.html.j2" %} + +{% block page_content %} +<div class="col s12"> + <h3>Submit a Test</h3> +</div> + +<div class="col s12"> + <div class="card"> + <form id="test-form"> + {{ test_form.hidden_tag() }} + <div class="card-content"> + <div class="row"> + <div class="col s12 m4"> + <div class="input-field"> + <i class="material-icons prefix">title</i> + {{ test_form.title(data_length='32') }} + {{ test_form.title.label }} + </div> + </div> + <div class="col s12 m8"> + <div class="input-field"> + <i class="material-icons prefix">description</i> + {{ test_form.description(data_length='255') }} + {{ test_form.description.label }} + </div> + </div> + <div class="col s12"> + <div class="file-field input-field"> + <div class="btn"> + <span>{{ test_form.file.label.text }}</span> + {{ test_form.file() }} + </div> + <div class="file-path-wrapper"> + <input class="file-path validate" type="text"> + </div> + </div> + </div> + </div> + </div> + <div class="card-action right-align"> + <button class="btn waves-effect waves-light" name="submit" type="submit">Submit<i class="material-icons right">send</i></button> + </div> + </form> + </div> +</div> + +<script> +var testFormElement = document.getElementById("test-form"); + +testFormElement.addEventListener("submit", function(event) { + event.preventDefault(); + let csrfTokenElement = testFormElement.querySelector("input[name='csrf_token']"), + descriptionElement = testFormElement.querySelector("input[name='description']"), + fileElement = testFormElement.querySelector("input[name='file']"), + titleElement = testFormElement.querySelector("input[name='title']"); + let file = fileElement.files[0]; + let data = {"csrf_token": csrfTokenElement.value, + "description": descriptionElement.value, + "file": {"bytes": file, "name": file.name}, + "title": titleElement.value}; + nopaque.socket.emit("submit-test-form", data); +}); + +nopaque.socket.on("submit-test-form", function(response) { + console.log(response); + if (response.status === "success") { + testFormElement.reset(); + nopaque.toast("Success!"); + for (let helperText of testFormElement.querySelectorAll(".helper-text")) { + helperText.remove(); + } + } else if (response.status === "error") { + let errorElement; + for (let [field, error] of Object.entries(response.msg)) { + errorElement = document.createElement("span"); + errorElement.classList.add("helper-text", "red-text"); + errorElement.innerText = error; + testFormElement.querySelector(`input[name="${field}"]`).closest(".input-field").appendChild(errorElement); + } + } +}); +</script> +{% endblock %} diff --git a/app/test/__init__.py b/app/test/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e01f868c5e4021a894996e6bad6923eb252e89c0 --- /dev/null +++ b/app/test/__init__.py @@ -0,0 +1,5 @@ +from flask import Blueprint + + +test = Blueprint('test', __name__) +from . import events, views diff --git a/app/test/events.py b/app/test/events.py new file mode 100644 index 0000000000000000000000000000000000000000..3400cd4f21218b0224690b3e336b0392c3939479 --- /dev/null +++ b/app/test/events.py @@ -0,0 +1,24 @@ +from app import logger, socketio +from flask_login import login_required +from werkzeug.datastructures import FileStorage +from werkzeug.utils import secure_filename +from .forms import TestForm +import io + + +@socketio.on('submit-test-form') +@login_required +def recv_test_form(data): + filename = secure_filename(data['file']['name']) + stream = io.BytesIO(data['file']['bytes']) + file = FileStorage(stream=stream, filename=filename) + data['file'] = file + test_form = TestForm(data=data) + if test_form.validate(): + logger.warning('test_form is ok!') + socketio.emit('submit-test-form', {'status': 'success', + 'msg': 'test_form is ok!'}) + else: + logger.warning('test_form is not ok!') + socketio.emit('submit-test-form', {'status': 'error', + 'msg': test_form.errors}) diff --git a/app/test/forms.py b/app/test/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..b7dd19d81bed90c6e0a9ef05efabf9d87ca78181 --- /dev/null +++ b/app/test/forms.py @@ -0,0 +1,12 @@ +from flask_wtf import FlaskForm +from flask_wtf.file import FileAllowed, FileField, FileRequired +from wtforms import StringField, SubmitField +from wtforms.validators import DataRequired, Length + + +class TestForm(FlaskForm): + description = StringField('Description', + validators=[DataRequired(), Length(1, 255)]) + file = FileField('File', validators=[FileAllowed(['txt'], 'Plain text only!'), FileRequired()]) + submit = SubmitField() + title = StringField('Title', validators=[DataRequired(), Length(1, 32)]) diff --git a/app/test/views.py b/app/test/views.py new file mode 100644 index 0000000000000000000000000000000000000000..a0e76fc2e00143e004d2302bfb1f2f869830094c --- /dev/null +++ b/app/test/views.py @@ -0,0 +1,12 @@ +from flask import render_template +from flask_login import login_required +from . import test +from .forms import TestForm + + +@test.route('/') +@login_required +def index(): + test_form = TestForm() + return render_template('test/index.html.j2', title='Test', + test_form=test_form)