Finished common section of app
This commit is contained in:
		@@ -1,32 +0,0 @@
 | 
			
		||||
from main import app, Config
 | 
			
		||||
from .data import data
 | 
			
		||||
from .modules import db
 | 
			
		||||
from .tools.data import save
 | 
			
		||||
from .tools.logs import write
 | 
			
		||||
 | 
			
		||||
from os import mkdir, path, system
 | 
			
		||||
from cryptography.fernet import Fernet
 | 
			
		||||
 | 
			
		||||
from sqlalchemy_utils import database_exists, create_database
 | 
			
		||||
 | 
			
		||||
def install_scripts():
 | 
			
		||||
    if not path.isdir(f'./{data}'): mkdir(f'./{data}')
 | 
			
		||||
    if not path.isdir(f'./{data}/questions'): mkdir(f'./{data}/questions')
 | 
			
		||||
    if not path.isfile(f'./{data}/.gitignore'):
 | 
			
		||||
        with open(f'./{data}/.gitignore', 'a+') as file: file.write(f'*')
 | 
			
		||||
    if not path.isfile(f'./{data}/config.json'): save({}, 'config.json')
 | 
			
		||||
    if not path.isdir(f'./{data}/logs'): mkdir(f'./{data}/logs')
 | 
			
		||||
    if not path.isfile(f'./{data}/logs/users.log'): write('users.log', 'Log file created.')
 | 
			
		||||
    if not path.isfile(f'./{data}/logs/system.log'): write('system.log', 'Log file created.')
 | 
			
		||||
    if not path.isfile(f'./{data}/logs/tests.log'): write('tests.log', 'Log file created.')
 | 
			
		||||
    if not database_exists(Config.SQLALCHEMY_DATABASE_URI):       
 | 
			
		||||
        create_database(Config.SQLALCHEMY_DATABASE_URI)
 | 
			
		||||
        write('system.log', 'No database found. Creating a new database.')
 | 
			
		||||
        from .models import Entry, Test, User
 | 
			
		||||
        with app.app_context(): db.create_all()
 | 
			
		||||
        write('system.log', 'Creating database schema.')
 | 
			
		||||
    if not path.isfile(f'./{data}/.encryption.key'):
 | 
			
		||||
        write('system.log', 'No encryption key found. Generating new encryption key.')
 | 
			
		||||
        with open(f'./{data}/.encryption.key', 'wb') as key_file:
 | 
			
		||||
            key = Fernet.generate_key()
 | 
			
		||||
            key_file.write(key)
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
{% extends "quiz/components/base.html" %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
    <h1>Privacy Policy</h1>
 | 
			
		||||
 | 
			
		||||
    This web app stores data using cookies. The web site only stores the minimum information it needs to function.
 | 
			
		||||
    <h5>Site Administrators</h5>
 | 
			
		||||
 | 
			
		||||
    <ul>
 | 
			
		||||
        <li>For site administrators, this web site uses encrypted cookies to store data from your log-in session.</li>
 | 
			
		||||
        <li>User information for administrators is encrypted and stored in a secure database, and are expunged when an account is deleted.</li>
 | 
			
		||||
    </ul>
 | 
			
		||||
    
 | 
			
		||||
    <h5>Test Candidates</h5>
 | 
			
		||||
    <ul>
 | 
			
		||||
        <li>The web site will not be trackin your log in, and all information about your test attempt will be stored on your device until you submit it to the server.</li>
 | 
			
		||||
        <li>Data from your test, including identifying information such as your name and email address, will be recorded by the Scottish Korfball Association in order to oversee the training and qualification of referees.</li>
 | 
			
		||||
        <li>These records will be kept for three years or until the expiration of the theory exam qualification (whichever is later), and will be expunged securely thereafter.</li>
 | 
			
		||||
        <li>All identifying information about candidates will be encrypted and stored in a secure database.</li>
 | 
			
		||||
    </ul>
 | 
			
		||||
 | 
			
		||||
    <h5>Requests to Delete Data</h5>
 | 
			
		||||
    <ul>
 | 
			
		||||
        <li>You can request to have any of your data that is held here deleted by emailing <a href="mailto:refereeing@scotlandkorfball.co.uk">refereeing@scotlandkorfball.co.uk</a>.</li>
 | 
			
		||||
    </ul>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
							
								
								
									
										218
									
								
								ref-test/app/root/css/style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								ref-test/app/root/css/style.css
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,218 @@
 | 
			
		||||
body {
 | 
			
		||||
    padding: 80px 0;
 | 
			
		||||
    line-height: 1.5;
 | 
			
		||||
    font-size: 14pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#cookie-alert {
 | 
			
		||||
    padding-right: 16px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#dismiss-cookie-alert {
 | 
			
		||||
    margin-top: 16px;
 | 
			
		||||
    width: fit-content;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-container {
 | 
			
		||||
    margin: 2rem auto;
 | 
			
		||||
    width: fit-content;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.instruction-container {
 | 
			
		||||
    margin: 2rem auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.site-footer {
 | 
			
		||||
    background-color: lightgray;
 | 
			
		||||
    font-size: small;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.site-footer p {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.quiz-container {
 | 
			
		||||
    max-width: 720px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-container {
 | 
			
		||||
    display: -ms-flexbox;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    -ms-flex-align: center;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
    padding-top: 40px;
 | 
			
		||||
    padding-bottom: 40px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-quiz-start {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    max-width: 420px;
 | 
			
		||||
    padding: 15px;
 | 
			
		||||
    margin: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-heading {
 | 
			
		||||
    margin-bottom: 2rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-label-group {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    margin-bottom: 2rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-label-group input,
 | 
			
		||||
.form-label-group label {
 | 
			
		||||
    padding: var(--input-padding-y) var(--input-padding-x);
 | 
			
		||||
    font-size: 16pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-label-group label {
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    top: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
    display: block;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    margin-bottom: 0; /* Override default `<label>` margin */
 | 
			
		||||
    line-height: 1.5;
 | 
			
		||||
    color: #495057;
 | 
			
		||||
    cursor: text; /* Match the input under the label */
 | 
			
		||||
    border: 1px solid transparent;
 | 
			
		||||
    border-radius: .25rem;
 | 
			
		||||
    transition: all .1s ease-in-out;
 | 
			
		||||
    z-index: -1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-label-group input {
 | 
			
		||||
    background-color: transparent;
 | 
			
		||||
    border: none;
 | 
			
		||||
    border-radius: 0%;
 | 
			
		||||
    border-bottom: 2px solid #585858;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-label-group input:active, .form-label-group input:focus {
 | 
			
		||||
    background-color: transparent;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-label-group input::-webkit-input-placeholder {
 | 
			
		||||
    color: transparent;
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
.form-label-group input:-ms-input-placeholder {
 | 
			
		||||
    color: transparent;
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
.form-label-group input::-ms-input-placeholder {
 | 
			
		||||
    color: transparent;
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
.form-label-group input::-moz-placeholder {
 | 
			
		||||
    color: transparent;
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
.form-label-group input::placeholder {
 | 
			
		||||
    color: transparent;
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
.form-label-group input:not(:placeholder-shown) {
 | 
			
		||||
    padding-top: calc(var(--input-padding-y) + var(--input-padding-y) * (2 / 3));
 | 
			
		||||
    padding-bottom: calc(var(--input-padding-y) / 3);
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
.form-label-group input:not(:placeholder-shown) ~ label {
 | 
			
		||||
    padding-top: calc(var(--input-padding-y) / 3);
 | 
			
		||||
    padding-bottom: calc(var(--input-padding-y) / 3);
 | 
			
		||||
    font-size: 12px;
 | 
			
		||||
    color: #777;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-check-margin {
 | 
			
		||||
    margin-bottom: 2rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.checkbox input {
 | 
			
		||||
    transform: scale(1.5);
 | 
			
		||||
    margin-right: 1rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.signin-forgot-password {
 | 
			
		||||
    font-size: 14pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-submission-button {
 | 
			
		||||
    margin-bottom: 2rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-submission-button button, .form-submission-button a {
 | 
			
		||||
    margin: 1rem;
 | 
			
		||||
    vertical-align: middle;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form-submission-button button span, .form-submission-button button svg, .form-submission-button a span, .form-submission-button a svg {
 | 
			
		||||
    margin: 0 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.results-name {
 | 
			
		||||
    margin: 3rem auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.results-name .surname {
 | 
			
		||||
    font-variant: small-caps;
 | 
			
		||||
    font-size: 24pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.results-score {
 | 
			
		||||
    margin: 2rem auto;
 | 
			
		||||
    width: fit-content;
 | 
			
		||||
    font-size: 36pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.results-score::after {
 | 
			
		||||
    content: '%';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.results-grade {
 | 
			
		||||
    margin: 2rem auto;
 | 
			
		||||
    width: fit-content;
 | 
			
		||||
    font-size: 26pt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.button-icon {
 | 
			
		||||
    font-size: 20px;
 | 
			
		||||
    margin-right: 2px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Change Autocomplete styles in Chrome*/
 | 
			
		||||
input:-webkit-autofill,
 | 
			
		||||
input:-webkit-autofill:hover, 
 | 
			
		||||
input:-webkit-autofill:focus,
 | 
			
		||||
textarea:-webkit-autofill,
 | 
			
		||||
textarea:-webkit-autofill:hover,
 | 
			
		||||
textarea:-webkit-autofill:focus,
 | 
			
		||||
select:-webkit-autofill,
 | 
			
		||||
select:-webkit-autofill:hover,
 | 
			
		||||
select:-webkit-autofill:focus {
 | 
			
		||||
  transition: background-color 5000s ease-in-out 0s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Fallback for Edge
 | 
			
		||||
-------------------------------------------------- */
 | 
			
		||||
@supports (-ms-ime-align: auto) {
 | 
			
		||||
    .form-label-group label {
 | 
			
		||||
      display: none;
 | 
			
		||||
    }
 | 
			
		||||
    .form-label-group input::-ms-input-placeholder {
 | 
			
		||||
      color: #777;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
  /* Fallback for IE
 | 
			
		||||
  -------------------------------------------------- */
 | 
			
		||||
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
 | 
			
		||||
    .form-label-group label {
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
    .form-label-group input:-ms-input-placeholder {
 | 
			
		||||
        color: #777;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
  
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								ref-test/app/root/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ref-test/app/root/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 15 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								ref-test/app/root/favicon.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								ref-test/app/root/favicon.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 84 KiB  | 
							
								
								
									
										2
									
								
								ref-test/app/root/js/jquery-3.6.0.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								ref-test/app/root/js/jquery-3.6.0.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										86
									
								
								ref-test/app/root/js/script.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								ref-test/app/root/js/script.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
$(document).ready(function() {
 | 
			
		||||
    $("#od-font-test").click(function(){
 | 
			
		||||
        $("body").css("font-family", "opendyslexic3regular")
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    $('.test-code-input').keyup(function() {
 | 
			
		||||
        var input = $(this).val().split("-").join("").split("—").join("");
 | 
			
		||||
        if (input.length > 0) {
 | 
			
		||||
          input = input.match(new RegExp('.{1,4}', 'g')).join("—");
 | 
			
		||||
        }
 | 
			
		||||
        $(this).val(input);
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
$('form[name=form-quiz-start]').submit(function(event) {
 | 
			
		||||
    
 | 
			
		||||
    var $form = $(this);
 | 
			
		||||
    var data = $form.serialize();
 | 
			
		||||
 | 
			
		||||
    $.ajax({
 | 
			
		||||
        url: window.location.pathname,
 | 
			
		||||
        type: 'POST',
 | 
			
		||||
        data: data,
 | 
			
		||||
        dataType: 'json',
 | 
			
		||||
        success: function(response) {
 | 
			
		||||
            var id = response.id
 | 
			
		||||
            window.localStorage.setItem('id', id);
 | 
			
		||||
            window.location.href = `/quiz/`;
 | 
			
		||||
        },
 | 
			
		||||
        error: function(response) {
 | 
			
		||||
            error_response(response);
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    event.preventDefault();
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
function error_response(response) {
 | 
			
		||||
 | 
			
		||||
    const $alert = $("#alert-box");
 | 
			
		||||
    $alert.html('');
 | 
			
		||||
 | 
			
		||||
    if (typeof response.responseJSON.error === 'string' || response.responseJSON.error instanceof String) {
 | 
			
		||||
        $alert.html(`
 | 
			
		||||
        <div class="alert alert-danger alert-dismissible fade show" role="alert">
 | 
			
		||||
            <i class="bi bi-exclamation-triangle-fill" title="Danger"></i>
 | 
			
		||||
            ${response.responseJSON.error}
 | 
			
		||||
            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
 | 
			
		||||
        </div>
 | 
			
		||||
        `);
 | 
			
		||||
    } else if (response.responseJSON.error instanceof Array) {
 | 
			
		||||
        var output = ''
 | 
			
		||||
        for (var i = 0; i < response.responseJSON.error.length; i ++) {
 | 
			
		||||
            output += `
 | 
			
		||||
            <div class="alert alert-danger alert-dismissible fade show" role="alert">
 | 
			
		||||
                <i class="bi bi-exclamation-triangle-fill" title="Danger"></i>
 | 
			
		||||
                ${response.responseJSON.error[i]}
 | 
			
		||||
                <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
 | 
			
		||||
            </div>
 | 
			
		||||
            `;
 | 
			
		||||
            $alert.html(output);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Dismiss Cookie Alert
 | 
			
		||||
$('#dismiss-cookie-alert').click(function(event){
 | 
			
		||||
 | 
			
		||||
    $.ajax({
 | 
			
		||||
        url: '/cookies/',
 | 
			
		||||
        type: 'POST',
 | 
			
		||||
        data: {
 | 
			
		||||
            time: Date.now()
 | 
			
		||||
        },
 | 
			
		||||
        dataType: 'json',
 | 
			
		||||
        success: function(response){
 | 
			
		||||
            console.log(response);
 | 
			
		||||
        },
 | 
			
		||||
        error: function(response){
 | 
			
		||||
            console.log(response);
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    event.preventDefault();
 | 
			
		||||
 | 
			
		||||
})
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
{% extends "quiz/components/base.html" %}
 | 
			
		||||
{% extends "components/base.html" %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
    <h1>Page Not Found</h1>
 | 
			
		||||
							
								
								
									
										78
									
								
								ref-test/app/templates/components/base.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								ref-test/app/templates/components/base.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
    <head>
 | 
			
		||||
        <meta charset="utf8" />
 | 
			
		||||
        <meta name="viewport" content="width=device-width, initial-scale=1" />
 | 
			
		||||
        <link
 | 
			
		||||
            href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
 | 
			
		||||
            rel="stylesheet"
 | 
			
		||||
            integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
 | 
			
		||||
            crossorigin="anonymous">
 | 
			
		||||
        <link
 | 
			
		||||
            rel="stylesheet"
 | 
			
		||||
            href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.1/font/bootstrap-icons.css">
 | 
			
		||||
        <link 
 | 
			
		||||
            rel="stylesheet"
 | 
			
		||||
            href="{{ url_for('.static', filename='css/style.css') }}"
 | 
			
		||||
        />
 | 
			
		||||
        {% block style %}
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
        <title>{% block title %} SKA Referee Test Beta {% endblock %}</title>
 | 
			
		||||
        {% include "components/og-meta.html" %}
 | 
			
		||||
    </head>
 | 
			
		||||
    <body class="bg-light">
 | 
			
		||||
 | 
			
		||||
        {% block navbar %}
 | 
			
		||||
            {% include "components/navbar.html" %}
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
        
 | 
			
		||||
        <div class="container quiz-container">
 | 
			
		||||
            {% block top_alerts %}
 | 
			
		||||
                {% include "components/server-alerts.html" %}
 | 
			
		||||
            {% endblock %}
 | 
			
		||||
            {% block content %}{% endblock %}
 | 
			
		||||
 | 
			
		||||
            <footer class="container site-footer">
 | 
			
		||||
                {% include "components/footer.html" %}
 | 
			
		||||
            </footer>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <!-- JQuery, Popper, and Bootstrap js dependencies -->
 | 
			
		||||
        <script
 | 
			
		||||
            src="https://code.jquery.com/jquery-3.6.0.min.js"
 | 
			
		||||
            integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4="
 | 
			
		||||
            crossorigin="anonymous">
 | 
			
		||||
        </script>
 | 
			
		||||
        <script>
 | 
			
		||||
            window.jQuery || document.write(`<script src="{{ url_for('.static', filename='js/jquery-3.6.0.min.js') }}"><\/script>`)
 | 
			
		||||
        </script>
 | 
			
		||||
        <script
 | 
			
		||||
            src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.10.2/dist/umd/popper.min.js"
 | 
			
		||||
            integrity="sha384-7+zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB"
 | 
			
		||||
            crossorigin="anonymous">
 | 
			
		||||
        </script>
 | 
			
		||||
        <script
 | 
			
		||||
            src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js"
 | 
			
		||||
            integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13"
 | 
			
		||||
            crossorigin="anonymous"
 | 
			
		||||
        ></script>
 | 
			
		||||
        <!-- Custom js -->
 | 
			
		||||
        <script type="text/javascript">
 | 
			
		||||
            var csrf_token = "{{ csrf_token() }}";
 | 
			
		||||
        
 | 
			
		||||
            $.ajaxSetup({
 | 
			
		||||
                beforeSend: function(xhr, settings) {
 | 
			
		||||
                    if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
 | 
			
		||||
                        xhr.setRequestHeader("X-CSRFToken", csrf_token);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        </script>
 | 
			
		||||
        <script
 | 
			
		||||
            type="text/javascript"
 | 
			
		||||
            src="{{ url_for('.static', filename='js/script.js') }}"
 | 
			
		||||
        ></script>
 | 
			
		||||
        {% block script %}
 | 
			
		||||
        {% endblock %}
 | 
			
		||||
    </body>
 | 
			
		||||
</html>
 | 
			
		||||
							
								
								
									
										3
									
								
								ref-test/app/templates/components/footer.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								ref-test/app/templates/components/footer.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
<p>This web app was developed by Vivek Santayana. The source code for the web app, excluding any data pertaining to the questions in the quiz, is freely available at <a href="https://git.vsnt.uk/viveksantayana/ska-referee-test">Vivek’s personal GIT repository</a> under an MIT License.</p>
 | 
			
		||||
<p>All questions in the test are © The Scottish Korfball Association {{ now.year }}. All rights are reserved.</p>
 | 
			
		||||
<p>OpenDyslexic 3 is an open source typeface created by Abbie Gonzalez, licensed under a <a href="https://scripts.sil.org/OFL">SIL-OFL</a>. More information about OpenDyslexic is available <a href="https://opendyslexic.org/">on the project web site</a>.</p>
 | 
			
		||||
							
								
								
									
										14
									
								
								ref-test/app/templates/components/navbar.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								ref-test/app/templates/components/navbar.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
<nav class="navbar fixed-top navbar-expand-md navbar-dark bg-dark" id="primary-nav">
 | 
			
		||||
    <div class="container">
 | 
			
		||||
        <p class="navbar-brand mb-0 h1">SKA Refereeing Test (Beta)</p>
 | 
			
		||||
        <div class="quiz-console w-100" style="display: none;" id="q-topbar">
 | 
			
		||||
            <div class="d-flex justify-content align-middle">
 | 
			
		||||
                <div class="container d-flex justify-content-center">
 | 
			
		||||
                    <span class="text-light q-timer" id="q-timer-widget" style="display: none;"><i class="bi bi-stopwatch-fill"></i> <span id="q-timer-display"></span></span>
 | 
			
		||||
                </div>
 | 
			
		||||
                <a href="#" class="btn btn-warning" aria-title="Question Grid" title="Question Grid" id="btn-toggle-navigator"><i class="bi bi-table"></i></a>
 | 
			
		||||
                <a href="#" class="btn btn-danger" aria-title="Settings" title="Settings" id="btn-toggle-settings"><i class="bi bi-gear-fill"></i></a>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</nav>
 | 
			
		||||
							
								
								
									
										17
									
								
								ref-test/app/templates/components/og-meta.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								ref-test/app/templates/components/og-meta.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,17 @@
 | 
			
		||||
<meta name="description" content="A web app for taking the Scottish Korfball Association Refereeing Theory Exam on-line." />
 | 
			
		||||
<meta property="og:locale" content="en_UK" />
 | 
			
		||||
<meta property="og:type" content="website" />
 | 
			
		||||
<meta property="og:description" content="A web app for taking the Scottish Korfball Association Refereeing Theory Exam on-line." />
 | 
			
		||||
<meta property="og:url" content="{{ url_for(request.endpoint, _external = True, **request.view_args) }}" />
 | 
			
		||||
<meta property="og:site_name" content="Scottish Korfball Association Referee Theory Exam" />
 | 
			
		||||
<meta property="og:image" content="{{ url_for('static', filename='favicon.png', _external = True) }}" />
 | 
			
		||||
<meta property="og:image:alt" content="Logo of the SKA Refereeing Exam App" />
 | 
			
		||||
<meta property="og:image:width" content="512" />
 | 
			
		||||
<meta property="og:image:height" content="512" />
 | 
			
		||||
<meta name="twitter:card" content="summary" />
 | 
			
		||||
<meta name="twitter:description" content="A web app for taking the Scottish Korfball Association Refereeing Theory Exam on-line." />
 | 
			
		||||
<meta name="twitter:image" content="{{ url_for('static', filename='favicon.png', _external = True) }}" />
 | 
			
		||||
<meta name="twitter:image:alt" content="Logo of the SKA Refereeing Exam App" />
 | 
			
		||||
<meta name="twitter:creator" content="@viveksantayana" />
 | 
			
		||||
<meta name="twitter:site" content="@viveksantayana" />
 | 
			
		||||
<meta name="theme-color" content="#343a40" />
 | 
			
		||||
							
								
								
									
										43
									
								
								ref-test/app/templates/components/server-alerts.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								ref-test/app/templates/components/server-alerts.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
{% with messages = get_flashed_messages(with_categories=true) %}
 | 
			
		||||
    {% if messages %}
 | 
			
		||||
        {% set cookie_flash_flag = namespace(value=False) %}
 | 
			
		||||
        {% for category, message in messages %}
 | 
			
		||||
            {% if category == "error" %}
 | 
			
		||||
                <div class="alert alert-danger alert-dismissible fade show" role="alert">
 | 
			
		||||
                    <i class="bi bi-exclamation-triangle-fill" title="Error" aria-title="Error"></i>
 | 
			
		||||
                    {{ message|safe }}
 | 
			
		||||
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
 | 
			
		||||
                </div>
 | 
			
		||||
            {% elif category == "success" %}
 | 
			
		||||
                <div class="alert alert-success alert-dismissible fade show" role="alert">
 | 
			
		||||
                    <i class="bi bi-check2-circle" title="Success" aria-title="Success"></i>
 | 
			
		||||
                    {{ message|safe }}
 | 
			
		||||
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
 | 
			
		||||
                </div>
 | 
			
		||||
            {% elif category == "warning" %}
 | 
			
		||||
                <div class="alert alert-warning alert-dismissible fade show" role="alert">
 | 
			
		||||
                    <i class="bi bi-info-circle-fill" aria-title="Warning" title="Warning"></i>
 | 
			
		||||
                    {{ message|safe }}
 | 
			
		||||
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
 | 
			
		||||
                </div>
 | 
			
		||||
            {% elif category == "cookie_alert" %}
 | 
			
		||||
                {% if not cookie_flash_flag.value %}
 | 
			
		||||
                    <div class="alert alert-primary alert-dismissible fade show" id="cookie-alert" role="alert">
 | 
			
		||||
                        <i class="bi bi-info-circle-fill" title="Cookie Alert" aria-title="Cookie Alert"></i>
 | 
			
		||||
                        {{ message|safe }}
 | 
			
		||||
                        <div class="d-flex justify-content-center w-100">
 | 
			
		||||
                            <button type="button" id="dismiss-cookie-alert" class="btn btn-success" data-bs-dismiss="alert" aria-label="Close">Accept</button>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    {% set cookie_flash_flag.value = True %}
 | 
			
		||||
                {% endif %}
 | 
			
		||||
            {% else %}
 | 
			
		||||
                <div class="alert alert-primary alert-dismissible fade show" role="alert">
 | 
			
		||||
                    <i class="bi bi-info-circle-fill" title="Alert"></i>
 | 
			
		||||
                    {{ message|safe }}
 | 
			
		||||
                    <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
 | 
			
		||||
                </div>
 | 
			
		||||
            {% endif %}
 | 
			
		||||
        {% endfor %}
 | 
			
		||||
    {% endif %}
 | 
			
		||||
{% endwith %}
 | 
			
		||||
@@ -1 +1,26 @@
 | 
			
		||||
<h1>Privacy Policy</h1>
 | 
			
		||||
{% extends "components/base.html" %}
 | 
			
		||||
 | 
			
		||||
{% block content %}
 | 
			
		||||
    <h1>Privacy Policy</h1>
 | 
			
		||||
 | 
			
		||||
    This web app stores data using cookies. The web site only stores the minimum information it needs to function.
 | 
			
		||||
    <h5>Site Administrators</h5>
 | 
			
		||||
 | 
			
		||||
    <ul>
 | 
			
		||||
        <li>For site administrators, this web site uses encrypted cookies to store data from your log-in session.</li>
 | 
			
		||||
        <li>User information for administrators is encrypted and stored in a secure database, and are expunged when an account is deleted.</li>
 | 
			
		||||
    </ul>
 | 
			
		||||
    
 | 
			
		||||
    <h5>Test Candidates</h5>
 | 
			
		||||
    <ul>
 | 
			
		||||
        <li>The web site will not be trackin your log in, and all information about your test attempt will be stored on your device until you submit it to the server.</li>
 | 
			
		||||
        <li>Data from your test, including identifying information such as your name and email address, will be recorded by the Scottish Korfball Association in order to oversee the training and qualification of referees.</li>
 | 
			
		||||
        <li>These records will be kept for three years or until the expiration of the theory exam qualification (whichever is later), and will be expunged securely thereafter.</li>
 | 
			
		||||
        <li>All identifying information about candidates will be encrypted and stored in a secure database.</li>
 | 
			
		||||
    </ul>
 | 
			
		||||
 | 
			
		||||
    <h5>Requests to Delete Data</h5>
 | 
			
		||||
    <ul>
 | 
			
		||||
        <li>You can request to have any of your data that is held here deleted by emailing <a href="mailto:refereeing@scotlandkorfball.co.uk">refereeing@scotlandkorfball.co.uk</a>.</li>
 | 
			
		||||
    </ul>
 | 
			
		||||
{% endblock %}
 | 
			
		||||
@@ -8,7 +8,7 @@ views = Blueprint(
 | 
			
		||||
    name='views',
 | 
			
		||||
    import_name=__name__,
 | 
			
		||||
    template_folder='templates',
 | 
			
		||||
    static_folder='static'
 | 
			
		||||
    static_folder='root',
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@views.route('/privacy/')
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user