aboutsummaryrefslogtreecommitdiffstats
path: root/pysite
diff options
context:
space:
mode:
authorGravatar Gareth Coles <[email protected]>2018-05-18 23:05:40 +0100
committerGravatar Gareth Coles <[email protected]>2018-05-18 23:05:40 +0100
commitfd147b934ef03a6609bee4efff24967f854f5495 (patch)
tree74f213bb258f662045fe921645d5f25825c2fe76 /pysite
parentAdded 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.py10
-rw-r--r--pysite/database.py2
-rw-r--r--pysite/tables.py6
-rw-r--r--pysite/views/staff/jams/actions.py138
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]})