diff options
author | 2018-05-18 23:05:40 +0100 | |
---|---|---|
committer | 2018-05-18 23:05:40 +0100 | |
commit | fd147b934ef03a6609bee4efff24967f854f5495 (patch) | |
tree | 74f213bb258f662045fe921645d5f25825c2fe76 /pysite | |
parent | Added SVG file and edited navbar accordingly (#72) (diff) |
[Jams] A bunch more work. That's all for tonight, though.
Diffstat (limited to 'pysite')
-rw-r--r-- | pysite/constants.py | 10 | ||||
-rw-r--r-- | pysite/database.py | 2 | ||||
-rw-r--r-- | pysite/tables.py | 6 | ||||
-rw-r--r-- | pysite/views/staff/jams/actions.py | 138 |
4 files changed, 151 insertions, 5 deletions
diff --git a/pysite/constants.py b/pysite/constants.py index c93a09d1..e30ed10b 100644 --- a/pysite/constants.py +++ b/pysite/constants.py @@ -75,6 +75,16 @@ JAM_STATES = [ "finished" ] +JAM_QUESTION_TYPES = [ + "email", + "number", + "radio", + "range", + "text", + "textarea", + "slider" +] + # PaperTrail logging PAPERTRAIL_ADDRESS = environ.get("PAPERTRAIL_ADDRESS") or None PAPERTRAIL_PORT = int(environ.get("PAPERTRAIL_PORT") or 0) diff --git a/pysite/database.py b/pysite/database.py index 2fb10598..a8c6c559 100644 --- a/pysite/database.py +++ b/pysite/database.py @@ -364,7 +364,7 @@ class RethinkDB: coerce=list ) - def get(self, table_name: str, key: str) -> Optional[Dict[str, Any]]: + def get(self, table_name: str, key: Any) -> Optional[Dict[str, Any]]: """ Get a single document from a table by primary key diff --git a/pysite/tables.py b/pysite/tables.py index 8ec550fb..499172d9 100644 --- a/pysite/tables.py +++ b/pysite/tables.py @@ -65,8 +65,11 @@ TABLES = { "code_jam_questions": Table( # Application form questions primary_key="id", keys=sorted([ + "data", # dict "id", # uuid - "" # TODO + "optional", # bool + "title", # str + "type", # str ]) ), @@ -76,6 +79,7 @@ TABLES = { "id", # uuid "jam", # int "answers", # dict {question, answer, metadata} + "approved" # bool ]) ), diff --git a/pysite/views/staff/jams/actions.py b/pysite/views/staff/jams/actions.py index 93a7f2c7..9aa7e79f 100644 --- a/pysite/views/staff/jams/actions.py +++ b/pysite/views/staff/jams/actions.py @@ -5,23 +5,93 @@ from pysite.constants import ALL_STAFF_ROLES, ErrorCodes from pysite.decorators import csrf, require_roles from pysite.mixins import DBMixin -ACTIONS = ["state"] +GET_ACTIONS = ["questions"] +POST_ACTIONS = ["associate_question", "disassociate_question", "questions", "state"] KEYS = ["action"] +QUESTION_KEYS = ["optional", "title", "type"] + class ActionView(APIView, DBMixin): - path = "/jams/action/" + path = "/jams/action" name = "jams.action" + table_name = "code_jams" + forms_table = "code_jam_forms" + questions_table = "code_jam_questions" + + @csrf + @require_roles(*ALL_STAFF_ROLES) + def get(self): + action = request.args.get("action") + + if action not in GET_ACTIONS: + return self.error(ErrorCodes.incorrect_parameters) + + if action == "questions": + questions = self.db.get_all(self.questions_table) + + print(questions) + return jsonify({"questions": questions}) @csrf @require_roles(*ALL_STAFF_ROLES) def post(self): action = request.args.get("action") - if action not in ACTIONS: + if action not in POST_ACTIONS: return self.error(ErrorCodes.incorrect_parameters) + if action == "associate_question": + form = int(request.args.get("form")) + question = request.args.get("question") + + form_obj = self.db.get(self.forms_table, form) + + if not form_obj: + return self.error(ErrorCodes.incorrect_parameters, f"Unknown form: {form}") + + question_obj = self.db.get(self.questions_table, question) + + if not question_obj: + return self.error(ErrorCodes.incorrect_parameters, f"Unknown question: {question}") + + if question_obj["id"] not in form_obj["questions"]: + form_obj["questions"].append(question_obj["id"]) + self.db.insert(self.forms_table, form_obj, conflict="replace") + + return jsonify({"question": question_obj}) + else: + return self.error( + ErrorCodes.incorrect_parameters, + f"Question {question} already associated with form {form}" + ) + + if action == "disassociate_question": + form = int(request.args.get("form")) + question = request.args.get("question") + + form_obj = self.db.get(self.forms_table, form) + + if not form_obj: + return self.error(ErrorCodes.incorrect_parameters, f"Unknown form: {form}") + + question_obj = self.db.get(self.questions_table, question) + + if not question_obj: + return self.error(ErrorCodes.incorrect_parameters, f"Unknown question: {question}") + + if question_obj["id"] in form_obj["questions"]: + form_obj["questions"].remove(question_obj["id"]) + self.db.insert(self.forms_table, form_obj, conflict="replace") + + return jsonify({"question": question_obj}) + else: + return self.error( + ErrorCodes.incorrect_parameters, + f"Question {question} not already associated with form {form}" + ) + if action == "state": jam = int(request.args.get("jam")) state = request.args.get("state") @@ -34,3 +104,65 @@ class ActionView(APIView, DBMixin): self.db.insert(self.table_name, jam_obj, conflict="update") return jsonify({}) + + if action == "questions": + data = request.get_json(force=True) + + for key in QUESTION_KEYS: + if key not in data: + return self.error(ErrorCodes.incorrect_parameters, f"Missing key: {key}") + + title = data["title"] + optional = data["optional"] + question_type = data["type"] + question_data = data.get("data", {}) + + if question_type in ["number", "range", "slider"]: + if "max" not in question_data or "min" not in question_data: + return self.error( + ErrorCodes.incorrect_parameters, f"{question_type} questions must have both max and min values" + ) + + result = self.db.insert( + self.questions_table, + { + "title": title, + "optional": optional, + "type": question_type, + "data": { + "max": question_data["max"], + "min": question_data["min"] + } + }, + conflict="error" + ) + elif question_type == "radio": + if "options" not in question_data: + return self.error( + ErrorCodes.incorrect_parameters, f"{question_type} questions must have both options" + ) + + result = self.db.insert( + self.questions_table, + { + "title": title, + "optional": optional, + "type": question_type, + "data": { + "options": question_data["options"] + } + }, + conflict="error" + ) + else: + result = self.db.insert( + self.questions_table, + { # No extra data for other types of question + "title": title, + "optional": optional, + "type": question_type + }, + conflict="error" + ) + + return jsonify({"id": result["generated_keys"][0]}) |