Finished making dashboards
This commit is contained in:
parent
23d6f833d7
commit
4aad0c1213
@ -42,10 +42,10 @@
|
|||||||
aria-labelledby="dropdown-account"
|
aria-labelledby="dropdown-account"
|
||||||
>
|
>
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ url_for('admin_views.users') }}" id="link-users" class="dropdown-item">Manage Users</a>
|
<a href="{{ url_for('admin_views.users') }}" id="link-users" class="dropdown-item">Users</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="{{ url_for('admin_views.questions') }}" id="link-questions" class="dropdown-item">Manage Questions</a>
|
<a href="{{ url_for('admin_views.questions') }}" id="link-questions" class="dropdown-item">Question Datasets</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
@ -1 +1,93 @@
|
|||||||
{% extends "admin/components/base.html" %}
|
{% extends "admin/components/base.html" %}
|
||||||
|
{% block title %}Settings — SKA Referee Test | Admin Console{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<h1>
|
||||||
|
Settings
|
||||||
|
</h1>
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm">
|
||||||
|
<div class="card m-3">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Admin Users</h5>
|
||||||
|
<div class="card-text">
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
Username
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Email Address
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for user in users %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<a href="
|
||||||
|
{% if user._id == get_id_from_cookie() %}
|
||||||
|
{{ url_for('admin_auth.account') }}
|
||||||
|
{% else %}
|
||||||
|
{{ url_for('admin_views.update_user', _id=user._id) }}
|
||||||
|
{% endif%}
|
||||||
|
">{{ user.username }}</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<a href="mailto:{{ user.email }}">{{ user.email }}</a>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<a href="{{ url_for('admin_views.users') }}" class="btn btn-primary">Manage Users</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm">
|
||||||
|
<div class="card m-3">
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">Question Datasets</h5>
|
||||||
|
{% if datasets %}
|
||||||
|
<div class="card-text">
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
File Name
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
Exams
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for dataset in datasets %}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
{{ dataset.filename }}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{ dataset.use }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<a href="{{ url_for('admin_views.questions') }}" class="btn btn-primary">Manage Datasets</a>
|
||||||
|
{% else %}
|
||||||
|
<div class="alert alert-primary">
|
||||||
|
There are currently no question datasets uploaded.
|
||||||
|
</div>
|
||||||
|
<a href="{{ url_for('admin_views.questions') }}" class="btn btn-primary">Upload Dataset</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -16,7 +16,7 @@ import secrets
|
|||||||
from main import mail
|
from main import mail
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
from .models.tests import Test
|
from .models.tests import Test
|
||||||
from common.data_tools import get_default_dataset, get_time_options, available_datasets
|
from common.data_tools import get_default_dataset, get_time_options, available_datasets, get_datasets
|
||||||
|
|
||||||
views = Blueprint(
|
views = Blueprint(
|
||||||
'admin_views',
|
'admin_views',
|
||||||
@ -76,13 +76,26 @@ def disable_if_logged_in(function):
|
|||||||
@admin_account_required
|
@admin_account_required
|
||||||
@login_required
|
@login_required
|
||||||
def home():
|
def home():
|
||||||
return render_template('/admin/index.html')
|
tests = db.tests.find()
|
||||||
|
results = decrypt_find(db.entries, {})
|
||||||
|
current_tests = [ test for test in tests if test['expiry_date'].date() >= date.today() and test['start_date'].date() <= date.today() ]
|
||||||
|
current_tests.sort(key= lambda x: x['expiry_date'], reverse=True)
|
||||||
|
upcoming_tests = [ test for test in tests if test['start_date'].date() > date.today()]
|
||||||
|
upcoming_tests.sort(key= lambda x: x['start_date'])
|
||||||
|
recent_results = [result for result in results if 'submission_time' in result ]
|
||||||
|
recent_results.sort(key= lambda x: x['submission_time'], reverse=True)
|
||||||
|
for result in recent_results:
|
||||||
|
result['percent'] = round(100*result['results']['score']/result['results']['max'])
|
||||||
|
return render_template('/admin/index.html', current_tests = current_tests[:5], upcomimg_tests = upcoming_tests[:5], recent_results = recent_results[:5])
|
||||||
|
|
||||||
@views.route('/settings/')
|
@views.route('/settings/')
|
||||||
@admin_account_required
|
@admin_account_required
|
||||||
@login_required
|
@login_required
|
||||||
def settings():
|
def settings():
|
||||||
return render_template('/admin/settings/index.html')
|
users = decrypt_find(db.users, {})
|
||||||
|
users.sort(key= lambda x: x['username'])
|
||||||
|
datasets = get_datasets()
|
||||||
|
return render_template('/admin/settings/index.html', users=users[:5], datasets=datasets[:5])
|
||||||
|
|
||||||
@views.route('/settings/users/', methods=['GET','POST'])
|
@views.route('/settings/users/', methods=['GET','POST'])
|
||||||
@admin_account_required
|
@admin_account_required
|
||||||
@ -245,22 +258,7 @@ def questions():
|
|||||||
from common.data_tools import check_json_format, validate_json_contents, store_data_file
|
from common.data_tools import check_json_format, validate_json_contents, store_data_file
|
||||||
form = UploadDataForm()
|
form = UploadDataForm()
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
files = glob(os.path.join(app.config["DATA_FILE_DIRECTORY"],'*.json'))
|
data = get_datasets()
|
||||||
data = []
|
|
||||||
if files:
|
|
||||||
for file in files:
|
|
||||||
filename = file.rsplit('/')[-1]
|
|
||||||
with open(file) as _file:
|
|
||||||
load = loads(_file.read())
|
|
||||||
_author = load['meta']['author']
|
|
||||||
author = decrypt_find_one(db.users, {'_id': _author})['username']
|
|
||||||
data_element = {
|
|
||||||
'filename': filename,
|
|
||||||
'timestamp': datetime.strptime(load['meta']['timestamp'], '%Y-%m-%d %H%M%S'),
|
|
||||||
'author': author,
|
|
||||||
'use': len(load['meta']['tests'])
|
|
||||||
}
|
|
||||||
data.append(data_element)
|
|
||||||
default = get_default_dataset()
|
default = get_default_dataset()
|
||||||
return render_template('/admin/settings/questions.html', form=form, data=data, default=default)
|
return render_template('/admin/settings/questions.html', form=form, data=data, default=default)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
|
@ -3,13 +3,12 @@ import pathlib
|
|||||||
from json import dump, loads
|
from json import dump, loads
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
||||||
from flask.json import jsonify
|
|
||||||
from main import app
|
|
||||||
from random import shuffle
|
from random import shuffle
|
||||||
|
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
|
|
||||||
|
from main import app, db
|
||||||
|
from .security.database import decrypt_find_one
|
||||||
|
|
||||||
def check_data_folder_exists():
|
def check_data_folder_exists():
|
||||||
if not os.path.exists(app.config['DATA_FILE_DIRECTORY']):
|
if not os.path.exists(app.config['DATA_FILE_DIRECTORY']):
|
||||||
pathlib.Path(app.config['DATA_FILE_DIRECTORY']).mkdir(parents='True', exist_ok='True')
|
pathlib.Path(app.config['DATA_FILE_DIRECTORY']).mkdir(parents='True', exist_ok='True')
|
||||||
@ -199,4 +198,23 @@ def get_time_options():
|
|||||||
('90', '1 hour 30 minutes'),
|
('90', '1 hour 30 minutes'),
|
||||||
('120', '2 hours')
|
('120', '2 hours')
|
||||||
]
|
]
|
||||||
return time_options
|
return time_options
|
||||||
|
|
||||||
|
def get_datasets():
|
||||||
|
files = glob(os.path.join(app.config["DATA_FILE_DIRECTORY"],'*.json'))
|
||||||
|
data = []
|
||||||
|
if files:
|
||||||
|
for file in files:
|
||||||
|
filename = file.rsplit('/')[-1]
|
||||||
|
with open(file) as _file:
|
||||||
|
load = loads(_file.read())
|
||||||
|
_author = load['meta']['author']
|
||||||
|
author = decrypt_find_one(db.users, {'_id': _author})['username']
|
||||||
|
data_element = {
|
||||||
|
'filename': filename,
|
||||||
|
'timestamp': datetime.strptime(load['meta']['timestamp'], '%Y-%m-%d %H%M%S'),
|
||||||
|
'author': author,
|
||||||
|
'use': len(load['meta']['tests'])
|
||||||
|
}
|
||||||
|
data.append(data_element)
|
||||||
|
return data
|
Loading…
Reference in New Issue
Block a user