test-platform/server/cgi/view.py

248 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import mariadb as mdb
import json
import os
from test_list import TestList
from question_list import QuestionList
from response_option_list import ResponseOptionList
from httputils import escape_html
def readfile(path):
if os.path.exists(path):
return open(path).read()
class View:
def __init__(self, query_args, connector_data = {}):
self.args = query_args
self.connector_data = connector_data
self.db_connection = None
self.supported_modes = {
"test-list": self.render_test_list,
"create-test": self.render_create_test,
"view-test": self.render_view_test,
"create-question": self.render_create_question,
"edit-question": self.render_edit_question,
"delete-question": self.render_delete_question,
"view-question": self.render_view_question,
"create-response-option": self.render_create_response_option,
"edit-response-option": self.render_edit_response_option,
"delete-response-option": self.render_delete_response_option,
}
def get_db_connection(self):
if not self.db_connection:
args = {"host": "127.0.0.1",
"port": 3306,
"user": "root",
"password": "",
"database": "test_holder"}
settings = json.loads(readfile("cgi/db-settings.json"))
args.update(settings)
args.update(self.connector_data)
self.db_connection = mdb.connect(**args)
return self.db_connection
def format_page(self, header, subheader, content):
base_layout = readfile("html/base_layout.html")
base_layout = base_layout.replace("%HEADER%", header)
base_layout = base_layout.replace("%SUBHEADER%", subheader)
base_layout = base_layout.replace("%CONTENT%", content)
return base_layout
def render_page(self):
dbc = self.get_db_connection()
cur = dbc.cursor()
if 'mode' in self.args:
mode = self.args['mode']
else:
mode = "test-list"
if mode not in self.supported_modes:
header = f"<h2>No such view mode: {mode}</h2>"
subheader = f'<a href="/index.py">Повернутися на головну сторінку</a>'
content = ""
else:
header, subheader, content = self.supported_modes[mode](cur)
dbc.close()
return self.format_page(header, subheader, content)
def render_test_list(self, cur):
cur.execute("SELECT id FROM test;")
test_amount = len(list(cur))
header = f'<h2>Всього тестів: {test_amount}</h2>'
subheader = f'<input placeholder="Шукати тести"><br><a class="generic-button" href="?mode=create-test">Створити новий тест</a>'
content = TestList(cur).render()
return header, subheader, content
def render_create_test(self, cur):
header = f"<h2>Створити новий тест</h2>"
subheader = "<i>Введіть властивості нового тесту нижче</i>"
content = f'''<form action="/create-test.py">
<label for="name">Назва тесту:</label>
<input type="text" name="name" placeholder="Введіть назву..." required><br>
<input type="submit" value="Створити">
</form>'''
return header, subheader, content
def render_view_test(self, cur):
cur.execute(f"SELECT name FROM test WHERE id = {self.args['id']};")
test_name = next(iter(cur), [None])[0]
if not test_name:
header = f"<h2>Такого тесту не існує: {self.args['id']}</h2>"
subheader = f'<a href="/index.py">Повернутися на головну сторінку</a>'
content = ""
return header, subheader, content
header = f'<span class="view-test-id-tag">#{self.args["id"]}</span><span class="view-test-main-tag">{test_name}</span>'
subheader = f'<a class="generic-button" href="?mode=create-question&test_id={self.args["id"]}">Додати запитання</a>'
content = QuestionList(cur).render(self.args['id'])
content += '<div class="return-button-centerer"><a class="return-button" href="/index.py">Назад до переліку тестів</a></div>'
return header, subheader, content
def render_create_question(self, cur):
header = f"<h2>Додати нове запитання</h2>"
subheader = "<i>Введіть властивості нового запитання нижче</i>"
content = f'''<form action="/create-question.py">
<input type="text" name="test_id" value="{self.args["test_id"]}" style="display:none;">
<label for="title">Текст запитання:</label>
<input type="text" name="title" placeholder="Введіть запитання..." required><br>
<label for="mtime">Максимальний час на відповідь (в сек):</label>
<input type="number" name="mtime" placeholder="Наприклад, 120"><br>
<input type="submit" value="Додати">
</form>'''
return header, subheader, content
def render_edit_question(self, cur):
cur.execute(f"SELECT title, mtime FROM question WHERE id = {self.args['id']};")
question_title, question_max_time = next(iter(cur), [None, None])
if not question_title:
header = f"<h2>Такого запитання не існує: {self.args['id']}</h2>"
subheader = f'<a href="/index.py">Повернутися на головну сторінку</a>'
content = ""
return header, subheader, content
header = f"<h2>Змінити запитання</h2>"
subheader = "<i>Відредагуйте властивості запитання нижче</i>"
content = f'''<form action="/edit-question.py">
<input type="text" name="question_id" value="{self.args["id"]}" style="display:none;">
<label for="title">Текст запитання:</label>
<input type="text" name="title" placeholder="Введіть запитання..." value="{escape_html(question_title)}" required><br>
<label for="mtime">Максимальний час на відповідь (в сек):</label>
<input type="number" name="mtime" placeholder="Наприклад, 120" value="{question_max_time}"><br>
<input type="submit" value="Зберегти зміни">
</form>'''
return header, subheader, content
def render_delete_question(self, cur):
cur.execute(f"SELECT title FROM question WHERE id = {self.args['id']};")
question_title = next(iter(cur), [None])[0]
if not question_title:
header = f"<h2>Такого запитання не існує: {self.args['id']}</h2>"
subheader = f'<a href="/index.py">Повернутися на головну сторінку</a>'
content = ""
return header, subheader, content
header = f"<h2>Точно видалити запитання?</h2>"
subheader = f"<i>{question_title}</i>"
cur.execute(f"SELECT test.id FROM test JOIN question ON test.id = question.tstID WHERE question.id = {self.args['id']};")
test_id = iter(cur).__next__()[0]
content = f'''<a class="delete-button" href="/delete-question.py?id={self.args["id"]}">Так, видалити</a><br><a class="cancel-button" href="/index.py?mode=view-test&id={test_id}">Ні, залишити</a>'''
return header, subheader, content
def render_view_question(self, cur):
cur.execute(f"SELECT title FROM question WHERE id = {self.args['id']};")
question_name = next(iter(cur), [None])[0]
if not question_name:
header = f"<h2>Такого запитання не існує: {self.args['id']}</h2>"
subheader = f'<a href="/index.py">Повернутися на головну сторінку</a>'
content = ""
return header, subheader, content
header = f'<span class="view-test-id-tag">#{self.args["id"]}</span><span class="view-test-main-tag">{question_name}</span>'
subheader = f'<a class="generic-button" href="?mode=create-response-option&question_id={self.args["id"]}">Додати варіант відповіді</a>' + \
f'<a class="sub-button" href="?mode=edit-question&id={self.args["id"]}">Редагувати запитання</a>'
content = ResponseOptionList(cur).render(self.args['id'])
cur.execute(f"""SELECT test.id FROM test
JOIN question ON test.id = question.tstID
WHERE question.id = {self.args['id']};""")
test_id = iter(cur).__next__()[0]
content += f'<div class="return-button-centerer"><a class="return-button" href="/index.py?mode=view-test&id={test_id}">Назад до тесту</a></div>'
return header, subheader, content
def render_create_response_option(self, cur):
header = f"<h2>Додати новий варіант відповіді</h2>"
subheader = "<i>Введіть властивості варіанту відповіді нижче</i>"
content = f'''<form action="/create-response-option.py">
<input type="text" name="question_id" value="{self.args["question_id"]}" style="display:none;">
<label for="label">Текст відповіді:</label>
<input type="text" name="label" placeholder="Введіть текст відповіді..." required><br>
<input type="submit" value="Додати">
</form>'''
return header, subheader, content
def render_edit_response_option(self, cur):
cur.execute(f"SELECT label FROM response_option WHERE id = {self.args['id']};")
respose_option_label = next(iter(cur), [None])[0]
header = f"<h2>Редагувати варіант відповіді</h2>"
subheader = "<i>Введіть властивості варіанту відповіді нижче</i>"
content = f'''<form action="/edit-response-option.py">
<input type="text" name="id" value="{self.args["id"]}" style="display:none;">
<label for="label">Текст відповіді:</label>
<input type="text" name="label" placeholder="Введіть текст відповіді..." value="{respose_option_label}" required><br>
<input type="submit" value="Оновити">
</form>'''
return header, subheader, content
def render_delete_response_option(self, cur):
cur.execute(f"SELECT label FROM response_option WHERE id = {self.args['id']};")
response_option_label = next(iter(cur), [None])[0]
header = f"<h2>Точно видалити цей варіант відповіді?</h2>"
subheader = f"<i>{response_option_label}</i>"
cur.execute(f"SELECT question.id FROM question JOIN response_option ON question.id = response_option.qstID WHERE response_option.id = {self.args['id']};")
quest_id = iter(cur).__next__()[0]
content = f'''<a class="delete-button" href="/delete-response-option.py?id={self.args["id"]}">Так, видалити</a><br><a class="cancel-button" href="/index.py?mode=view-question&id={quest_id}">Ні, залишити</a>'''
return header, subheader, content