Started the admin site
Can currently view all the questions and search through them
This commit is contained in:
parent
2d18b1b2bf
commit
197164d691
61
admin/admin.py
Normal file
61
admin/admin.py
Normal file
@ -0,0 +1,61 @@
|
||||
import json
|
||||
from flask import render_template, Blueprint, request, jsonify
|
||||
import database
|
||||
from database import get_all_questions, get_question
|
||||
|
||||
|
||||
Admin = Blueprint("admin", __name__, template_folder="templates")
|
||||
|
||||
|
||||
@Admin.route("/admin/")
|
||||
def index():
|
||||
return render_template("admin/index.html", title="admin")
|
||||
|
||||
|
||||
@Admin.route("/admin/questions/")
|
||||
def questions():
|
||||
return render_template("admin/question_list.html")
|
||||
|
||||
|
||||
@Admin.route("/admin/questions/edit/<int:question_id>")
|
||||
def edit_question(question_id):
|
||||
question: database.AllQuestions = get_question(database.AllQuestions, question_id)
|
||||
return render_template("admin/edit_question.html", question=question)
|
||||
|
||||
|
||||
@Admin.route("/admin/question_query")
|
||||
def query_questions():
|
||||
offset = request.args.get("offset", type=int)
|
||||
limit = request.args.get("limit", type=int)
|
||||
sort = request.args.get("sort")
|
||||
order = request.args.get("order")
|
||||
query = parse_question_query(request.args.get("filter"))
|
||||
result = database.query_all_questions(offset, limit, query, sort, order)
|
||||
response_dict = {
|
||||
"total": result[1],
|
||||
"rows": [],
|
||||
}
|
||||
for question in result[0]:
|
||||
response_dict["rows"].append({
|
||||
"id": question.question_id,
|
||||
"question_id": question.question_id,
|
||||
"question": question.question,
|
||||
"answer": question.answer,
|
||||
"multiple_choice": getattr(question, "multiple_choice", None) is not None,
|
||||
"hidden_answer": getattr(question, "hidden_answer", None) is not None,
|
||||
})
|
||||
# question1 = get_question(database.AllQuestions, 0)
|
||||
# question2 = get_question(database.AllQuestions, 1)
|
||||
# question3 = get_question(database.AllQuestions, 2)
|
||||
return jsonify(response_dict)
|
||||
|
||||
|
||||
def parse_question_query(query):
|
||||
if query:
|
||||
query: dict = json.loads(query)
|
||||
if "multiple_choice" in query.keys():
|
||||
query["multiple_choice"] = True if query["multiple_choice"] == "true" else False
|
||||
if "hidden_answer" in query.keys():
|
||||
query["hidden_answer"] = True if query["hidden_answer"] == "true" else False
|
||||
return query
|
||||
return None
|
40
admin/templates/admin/base.html
Normal file
40
admin/templates/admin/base.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="h-100" lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Admin</title>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootswatch/4.5.2/cosmo/bootstrap.min.css">
|
||||
{% block head %}{% endblock %}
|
||||
</head>
|
||||
<body class="d-flex flex-column h-100">
|
||||
<nav class="navbar navbar-expand navbar-dark bg-primary">
|
||||
<a class="navbar-brand" href="{{ url_for('admin.index') }}">Admin Site</a>
|
||||
<button class="navbar-toggler" type="button">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('admin.index') }}">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{{ url_for('admin.questions') }}">Questions</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container">
|
||||
{% block body %}{% endblock %}
|
||||
</div>
|
||||
<footer class="mt-auto py-3">
|
||||
<div class="container text-center">
|
||||
<span class="">Created By ItIsGood.com</span>
|
||||
</div>
|
||||
</footer>
|
||||
</body>
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
{% block scripts %}{% endblock %}
|
||||
</html>
|
5
admin/templates/admin/index.html
Normal file
5
admin/templates/admin/index.html
Normal file
@ -0,0 +1,5 @@
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block body %}
|
||||
<p>This is the admin home page</p>
|
||||
{% endblock %}
|
63
admin/templates/admin/question_list.html
Normal file
63
admin/templates/admin/question_list.html
Normal file
@ -0,0 +1,63 @@
|
||||
{% extends "admin/base.html" %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css">
|
||||
<link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.18.2/dist/bootstrap-table.min.css">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.18.2/extensions/filter-control/bootstrap-table-filter-control.min.css">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<table id="question-table" class="table"></table>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script src="https://unpkg.com/bootstrap-table@1.18.2/dist/bootstrap-table.min.js"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.18.2/extensions/filter-control/bootstrap-table-filter-control.min.js"></script>
|
||||
<script>
|
||||
|
||||
function query_params(params) {
|
||||
console.log(params);
|
||||
return params;
|
||||
}
|
||||
|
||||
var filter_data = [true, false]
|
||||
|
||||
$("#question-table").bootstrapTable({
|
||||
url: "/admin/question_query",
|
||||
pagination: true,
|
||||
sidePagination: "server",
|
||||
filterControl: true,
|
||||
queryParams: query_params,
|
||||
showRefresh: true,
|
||||
searchOnEnterKey: true,
|
||||
columns: [
|
||||
{
|
||||
field: "question_id",
|
||||
title: "Question ID",
|
||||
},
|
||||
{
|
||||
field: "question",
|
||||
title: "Question",
|
||||
filterControl: "input",
|
||||
},
|
||||
{
|
||||
field: "answer",
|
||||
title: "Answer",
|
||||
filterControl: "input",
|
||||
},
|
||||
{
|
||||
field: "multiple_choice",
|
||||
title: "Has Multiple Choice",
|
||||
filterControl: "select",
|
||||
filterData: "var:filter_data",
|
||||
},
|
||||
{
|
||||
field: "hidden_answer",
|
||||
title: "Has Hidden Answer",
|
||||
filterControl: "select",
|
||||
filterData: "var:filter_data",
|
||||
},
|
||||
]
|
||||
})
|
||||
</script>
|
||||
{% endblock %}
|
@ -7,6 +7,7 @@ load_dotenv(".env")
|
||||
|
||||
class Config:
|
||||
SECRET_KEY = environ.get("SECRET_KEY")
|
||||
SECURITY_PASSWORD_SALT = environ.get("SECURITY_PASSWORD_SALT")
|
||||
DB_USER = environ.get("DB_USER")
|
||||
DB_PASSWORD = environ.get("DB_PASSWORD")
|
||||
DB_HOST = environ.get("DB_HOST")
|
||||
|
30
database.py
30
database.py
@ -26,6 +26,9 @@ class AllQuestions(Base):
|
||||
answer = Column(String)
|
||||
addresses = Column(String)
|
||||
|
||||
multiple_choice = relationship("MultipleChoice", uselist=False, back_populates="all_question_relationship")
|
||||
hidden_answer = relationship("HiddenAnswer", uselist=False, back_populates="all_question_relationship")
|
||||
|
||||
def __init__(self, question_id, question, answer, addresses):
|
||||
self.question_id = question_id
|
||||
self.question = question
|
||||
@ -43,7 +46,7 @@ class HiddenAnswer(Base):
|
||||
difficulty = Column(Integer)
|
||||
hint = Column(JSON)
|
||||
|
||||
all_question_relationship = relationship("AllQuestions", foreign_keys=[question_id], lazy="joined", uselist=False)
|
||||
all_question_relationship = relationship("AllQuestions", lazy="joined", back_populates="hidden_answer")
|
||||
question = association_proxy("all_question_relationship", "question")
|
||||
answer = association_proxy("all_question_relationship", "answer")
|
||||
addresses = association_proxy("all_question_relationship", "addresses")
|
||||
@ -66,7 +69,7 @@ class MultipleChoice(Base):
|
||||
hint = Column(JSON)
|
||||
wrong_answers = Column(ARRAY(String))
|
||||
|
||||
all_question_relationship = relationship("AllQuestions", foreign_keys=[question_id], lazy="joined", uselist=False)
|
||||
all_question_relationship = relationship("AllQuestions", lazy="joined", back_populates="multiple_choice")
|
||||
question = association_proxy("all_question_relationship", "question")
|
||||
answer = association_proxy("all_question_relationship", "answer")
|
||||
addresses = association_proxy("all_question_relationship", "addresses")
|
||||
@ -118,7 +121,7 @@ def get_category_count(category: Union[Type[MultipleChoice], Type[HiddenAnswer],
|
||||
return session.query(category).count()
|
||||
|
||||
|
||||
def get_question(category: Union[Type[MultipleChoice], Type[HiddenAnswer], Type[AllQuestions]], question_id: int) -> Optional[Union[Type[MultipleChoice], Type[HiddenAnswer], Type[AllQuestions]]]:
|
||||
def get_question(category: Union[Type[MultipleChoice], Type[HiddenAnswer], Type[AllQuestions]], question_id: int) -> Optional[Union[MultipleChoice, HiddenAnswer, AllQuestions]]:
|
||||
session: sqlalchemy.orm.session.Session = Session()
|
||||
return session.query(category).filter(category.question_id == question_id).one_or_none()
|
||||
|
||||
@ -149,3 +152,24 @@ def check_answer(question_id: int, guess: str) -> Tuple[bool, str]:
|
||||
if question:
|
||||
answer = question.answer
|
||||
return answer == guess, answer
|
||||
|
||||
|
||||
def query_all_questions(offset, limit, query: dict = None, sort=None, order=None) -> Tuple[List[AllQuestions], int]:
|
||||
session: sqlalchemy.orm.session.Session = Session()
|
||||
query_params = []
|
||||
if query is not None:
|
||||
for key in query.keys():
|
||||
if key == "multiple_choice" or key == "hidden_answer":
|
||||
if query[key]:
|
||||
query_params.append(getattr(AllQuestions, key) != None)
|
||||
else:
|
||||
query_params.append(getattr(AllQuestions, key) == None)
|
||||
else:
|
||||
query_params.append(getattr(AllQuestions, key).ilike("%"+query[key]+"%"))
|
||||
order_by = None
|
||||
if sort and order:
|
||||
order_by = getattr(getattr(AllQuestions, sort), order)()
|
||||
q = session.query(AllQuestions).filter(*query_params).order_by(order_by)
|
||||
questions = q.offset(offset).limit(limit).all()
|
||||
count = q.count()
|
||||
return questions, count
|
||||
|
3
main.py
3
main.py
@ -1,8 +1,11 @@
|
||||
import os
|
||||
from flask import Flask, render_template, request, jsonify
|
||||
from flask_security import Security
|
||||
import database
|
||||
from admin import admin
|
||||
|
||||
app = Flask(__name__)
|
||||
app.register_blueprint(admin.Admin)
|
||||
environment_configuration = os.environ['CONFIGURATION_SETUP']
|
||||
app.config.from_object(environment_configuration)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user