Finished making dashboards
This commit is contained in:
		@@ -42,10 +42,10 @@
 | 
			
		||||
                            aria-labelledby="dropdown-account"
 | 
			
		||||
                        >
 | 
			
		||||
                            <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>
 | 
			
		||||
                                <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>
 | 
			
		||||
                        </ul>
 | 
			
		||||
                    </li>
 | 
			
		||||
 
 | 
			
		||||
@@ -1 +1,93 @@
 | 
			
		||||
{% 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 datetime import datetime, date
 | 
			
		||||
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(
 | 
			
		||||
    'admin_views',
 | 
			
		||||
@@ -76,13 +76,26 @@ def disable_if_logged_in(function):
 | 
			
		||||
@admin_account_required
 | 
			
		||||
@login_required
 | 
			
		||||
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/')
 | 
			
		||||
@admin_account_required
 | 
			
		||||
@login_required
 | 
			
		||||
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'])
 | 
			
		||||
@admin_account_required
 | 
			
		||||
@@ -245,22 +258,7 @@ def questions():
 | 
			
		||||
    from common.data_tools import check_json_format, validate_json_contents, store_data_file
 | 
			
		||||
    form = UploadDataForm()
 | 
			
		||||
    if request.method == 'GET':
 | 
			
		||||
        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)
 | 
			
		||||
        data = get_datasets()
 | 
			
		||||
        default = get_default_dataset()
 | 
			
		||||
        return render_template('/admin/settings/questions.html', form=form, data=data, default=default)
 | 
			
		||||
    if request.method == 'POST':
 | 
			
		||||
 
 | 
			
		||||
@@ -3,13 +3,12 @@ import pathlib
 | 
			
		||||
from json import dump, loads
 | 
			
		||||
from datetime import datetime, timedelta
 | 
			
		||||
from glob import glob
 | 
			
		||||
 | 
			
		||||
from flask.json import jsonify
 | 
			
		||||
from main import app
 | 
			
		||||
from random import shuffle
 | 
			
		||||
 | 
			
		||||
from werkzeug.utils import secure_filename
 | 
			
		||||
 | 
			
		||||
from main import app, db
 | 
			
		||||
from .security.database import decrypt_find_one
 | 
			
		||||
 | 
			
		||||
def check_data_folder_exists():
 | 
			
		||||
    if not os.path.exists(app.config['DATA_FILE_DIRECTORY']):
 | 
			
		||||
        pathlib.Path(app.config['DATA_FILE_DIRECTORY']).mkdir(parents='True', exist_ok='True')
 | 
			
		||||
@@ -200,3 +199,22 @@ def get_time_options():
 | 
			
		||||
        ('120', '2 hours')
 | 
			
		||||
    ]
 | 
			
		||||
    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
 | 
			
		||||
		Reference in New Issue
	
	Block a user