474 lines
22 KiB
HTML
474 lines
22 KiB
HTML
<!DOCTYPE HTML>
|
|
{% load static %}
|
|
{% load django_htmx %}
|
|
{% load crispy_forms_tags %}
|
|
{% load auth_extras %}
|
|
{% load help_tags %}
|
|
<html data-bs-theme="dark">
|
|
|
|
<head>
|
|
<title>
|
|
{% block title %}
|
|
PENRA Courses
|
|
{% endblock %}
|
|
</title>
|
|
<meta name="htmx-config" content='{"selfRequestsOnly": false}' />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
{% comment %} <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" /> {% endcomment %}
|
|
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
|
|
|
|
<link href="{% static 'css/widgets.css' %}" type="text/css" media="all" rel="stylesheet">
|
|
<link rel="stylesheet" href="{% static 'css/dicomViewer.css' %}">
|
|
<link rel="stylesheet" href="{% static 'css/toastr.min.css' %}">
|
|
<link rel="stylesheet" href="{% static 'css/bootstrap-icons.css' %}">
|
|
|
|
<link rel="apple-touch-icon" sizes="180x180" href="{% static 'favicon/apple-touch-icon.png' %}">
|
|
<link rel="icon" type="image/png" sizes="32x32" href="{% static 'favicon/favicon-32x32.png' %}">
|
|
<link rel="icon" type="image/png" sizes="16x16" href="{% static 'favicon/favicon-16x16.png' %}">
|
|
<link rel="manifest" href="{% static 'favicon/site.webmanifest' %}">
|
|
<link rel="mask-icon" href="{% static 'favicon/safari-pinned-tab.svg' %}" color="#5bbad5">
|
|
<meta name="msapplication-TileColor" content="#da532c">
|
|
<meta name="theme-color" content="#ffffff">
|
|
|
|
|
|
<link href="/static/css/widgets.css" type="text/css" media="all" rel="stylesheet">
|
|
<link href="/static/admin/css/vendor/select2/select2.min.css" type="text/css" media="screen" rel="stylesheet">
|
|
<link href="/static/admin/css/autocomplete.css" type="text/css" media="screen" rel="stylesheet">
|
|
<link href="/static/autocomplete_light/select2.css" type="text/css" media="screen" rel="stylesheet">
|
|
|
|
<script src="{% static 'js/crypto-js/core.min.js' %}"></script>
|
|
<script src="{% static 'js/crypto-js/md5.min.js' %}"></script>
|
|
|
|
{% comment %} <script src="https://unpkg.com/alpinejs" defer></script> {% endcomment %}
|
|
<script src="{% static 'js/_hyperscript.min.js' %}"></script>
|
|
<script src="{% static 'js/htmx.min.js' %}"></script>
|
|
{% django_htmx_script %}
|
|
<script src="{% static 'js/jquery-3.7.1.min.js' %}"></script>
|
|
<script src="{% static 'admin/js/core.js' %}"></script>
|
|
<script src="{% static 'admin/js/SelectBox.js' %}"></script>
|
|
<script src="{% static 'admin/js/SelectFilter2.js' %}"></script>
|
|
<script src="{% static 'jsi18n.js' %}"></script>
|
|
<script src="{% static 'admin/js/vendor/select2/select2.full.js' %}"></script>
|
|
<script src="{% static 'autocomplete_light/autocomplete_light.min.js' %}"></script>
|
|
<script src="{% static 'tesseract.min.js' %}"></script>
|
|
<script src="{% static 'autocomplete_light/select2.min.js' %}"></script>
|
|
<script src="{% static 'autocomplete_light/i18n/en.js' %}"></script>
|
|
{% comment %} mathjax {% endcomment %}
|
|
<script src="{% static 'js/tex-mml-chtml.js' %}"></script>
|
|
<script src="{% static 'js/dexie.js' %}"></script>
|
|
<script src="{% static 'js/html5sortable.min.js' %}"></script>
|
|
<script src="{% static 'atlas/js/markup_inserter.js' %}"></script>
|
|
{% comment %} <script src="{% static 'tesseract.min.js' %}"></script> {% endcomment %}
|
|
<script src='https://cdn.jsdelivr.net/npm/tesseract.js@5/dist/tesseract.min.js'></script>
|
|
<script src="{% static 'js/toastr.min.js' %}"></script>
|
|
<script src="{% static 'js/bootstrap.bundle.min.js' %}"></script>
|
|
<script src="{% static 'js/sorttable.js' %}"></script>
|
|
|
|
<script src="{% static 'js/cornerstone/hammer.js' %}"></script>
|
|
<script src="{% static 'js/cornerstone/cornerstone.min.js' %}"></script>
|
|
<script src="{% static 'js/cornerstone/dicomParser.min.js' %}"></script>
|
|
<script src="{% static 'js/cornerstone/cornerstoneMath.min.js' %}"></script>
|
|
<script src="{% static 'js/cornerstone/cornerstoneTools.min.js' %}"></script>
|
|
<script src="{% static 'js/cornerstone/cornerstoneWebImageLoader.min.js' %}"></script>
|
|
<script src="{% static 'js/cornerstone/cornerstoneWADOImageLoader.min.js' %}"></script>
|
|
<script src="{% static 'js/cornerstone/cornerstone-base64-image-loader.umd.js' %}"></script>
|
|
<script src="{% static 'js/anatomy.js' %}" defer="defer" type="module"></script>
|
|
<script src="{% static 'dv3d/index.js' %}" type="module" defer="defer" type="module"></script>
|
|
|
|
{% block js %}
|
|
{% endblock %}
|
|
<link rel="stylesheet" href="{% static 'css/anatomy.css' %}">
|
|
<link rel="stylesheet" href="{% static 'css/forms.css' %}">
|
|
<link rel="stylesheet" href="{% static 'css/responsive-utils.css' %}">
|
|
<style>
|
|
|
|
:root {
|
|
--penra-submenu-bg: rgba(13, 22, 35, 0.92);
|
|
--penra-submenu-border: rgba(173, 216, 230, 0.24);
|
|
}
|
|
|
|
body {
|
|
overflow-x: hidden;
|
|
}
|
|
|
|
.dropdown-menu {
|
|
background-color: rgb(28, 25, 25);
|
|
max-width: min(94vw, 30rem);
|
|
}
|
|
|
|
.dropdown-item {
|
|
color: lightblue;
|
|
white-space: normal;
|
|
}
|
|
|
|
.submenu {
|
|
background: var(--penra-submenu-bg);
|
|
border: 1px solid var(--penra-submenu-border);
|
|
border-radius: 0.5rem;
|
|
margin: 0.5rem 0 0.75rem;
|
|
}
|
|
|
|
.submenu .navbar-brand,
|
|
.submenu .nav-link {
|
|
color: #d3e9ff;
|
|
}
|
|
|
|
.submenu .nav-link:hover,
|
|
.submenu .nav-link:focus,
|
|
.submenu .nav-link.active {
|
|
color: #ffffff;
|
|
}
|
|
|
|
/* Allow the correct-answer badge to wrap if the text is long */
|
|
.correct-badge {
|
|
white-space: normal !important;
|
|
display: inline-block;
|
|
word-break: break-word;
|
|
max-width: 100%;
|
|
}
|
|
|
|
.content.content-read {
|
|
max-width: 1280px;
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
}
|
|
|
|
.content.content-wide {
|
|
max-width: min(98vw, 2200px);
|
|
margin-left: auto;
|
|
margin-right: auto;
|
|
}
|
|
|
|
@media (max-width: 1210px) {
|
|
.container,
|
|
.container-fluid {
|
|
padding-left: .5rem !important;
|
|
padding-right: .5rem !important;
|
|
}
|
|
|
|
.content {
|
|
padding-left: .5rem !important;
|
|
padding-right: .5rem !important;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 991.98px) {
|
|
.container,
|
|
.container-fluid {
|
|
padding-left: .75rem !important;
|
|
padding-right: .75rem !important;
|
|
}
|
|
|
|
.content {
|
|
padding-left: .75rem !important;
|
|
padding-right: .75rem !important;
|
|
}
|
|
|
|
.navbar {
|
|
padding-top: .35rem;
|
|
padding-bottom: .35rem;
|
|
}
|
|
|
|
.navbar-toggler {
|
|
padding: .5rem .65rem;
|
|
border-color: rgba(255, 255, 255, 0.3);
|
|
}
|
|
|
|
.navbar-toggler .bi {
|
|
font-size: 1.2rem;
|
|
line-height: 1;
|
|
}
|
|
|
|
.navbar-collapse {
|
|
padding-top: .5rem;
|
|
}
|
|
|
|
.navbar-nav .nav-link {
|
|
min-height: 44px;
|
|
display: flex;
|
|
align-items: center;
|
|
padding: .625rem .75rem;
|
|
margin: .125rem 0;
|
|
border-radius: .375rem;
|
|
}
|
|
|
|
.navbar-nav .dropdown-menu {
|
|
position: static !important;
|
|
float: none !important;
|
|
width: 100%;
|
|
max-width: 100%;
|
|
margin: .25rem 0 .5rem;
|
|
}
|
|
|
|
.navbar-nav .dropdown-menu:not(.show) {
|
|
display: none !important;
|
|
}
|
|
|
|
.navbar-nav .dropdown-menu.show {
|
|
display: block !important;
|
|
}
|
|
|
|
.navbar-nav .dropdown-menu .dropdown-item {
|
|
padding: .625rem .75rem;
|
|
}
|
|
|
|
.submenu .nav-item.dropdown .nav-link.d-inline {
|
|
display: inline-flex !important;
|
|
}
|
|
|
|
.submenu .dropdown-toggle-split {
|
|
min-width: 2.5rem;
|
|
justify-content: center;
|
|
}
|
|
|
|
.content table {
|
|
display: block;
|
|
width: 100%;
|
|
overflow-x: auto;
|
|
-webkit-overflow-scrolling: touch;
|
|
}
|
|
|
|
.content table.table {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.content .card[style*="min-width"] {
|
|
min-width: 0 !important;
|
|
}
|
|
|
|
.content img,
|
|
.content video,
|
|
.content iframe,
|
|
.content svg {
|
|
max-width: 100%;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
</style>
|
|
{% block css %}
|
|
{% endblock %}
|
|
</head>
|
|
|
|
|
|
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
|
|
<nav class="navbar navbar-expand-lg bg-body-tertiary py-0">
|
|
<div class="container-fluid">
|
|
<a class="navbar-brand pt-0" href="/">Home</a>
|
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
|
<span class="navbar-toggler-icon"><i class="bi bi-text-indent-right"></i></span>
|
|
</button>
|
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
|
<ul class="navbar-nav ms-auto ">
|
|
{% if request.user.is_authenticated %}
|
|
<li id="atlas-link" class="nav-item">
|
|
<a class="nav-link active" href="{% url 'atlas:index' %}">Atlas</a>
|
|
</li>
|
|
<li id="messages-link" class="nav-item dropdown">
|
|
<a class="nav-link dropdown-toggle active" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
|
Activity
|
|
</a>
|
|
<ul class="dropdown-menu">
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'atlas:user_messages_inbox' %}">Messages</a>
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'atlas:collection_supervision' %}">Supervision</a>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
<li class="nav-item dropdown pt-0">
|
|
<a class="nav-link dropdown-toggle" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
|
FRCR
|
|
</a>
|
|
<ul class="dropdown-menu">
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'rapids:index' %}">Rapids</a>
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'shorts:index' %}">Shorts</a>
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'longs:index' %}">Longs</a>
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'anatomy:index' %}">Anatomy</a>
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'physics:index' %}">Physics</a>
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'sbas:index' %}">SBAs</a>
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item d-flex justify-content-between align-items-center" href="{% url 'generic:examcollection_list' %}">
|
|
<span><i class="bi bi-collection me-1" aria-hidden="true"></i> Exam Collections</span>
|
|
<span class="badge bg-secondary ms-2">Manage</span>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
{% if request.user|has_group:"cid_user_manager" %}
|
|
<li id="candidate-link" class="nav-item">
|
|
<a class="nav-link active" href="{% url 'people' %}">People</a>
|
|
</li>
|
|
{% endif %}
|
|
{% if request.user.supervisor %}
|
|
<li id="supervisor-link" class="nav-item">
|
|
<a class="nav-link active" href="{% url 'generic:supervisor_overview' request.user.supervisor.pk %}">Supervisor</a>
|
|
</li>
|
|
{% endif %}
|
|
<li id="profile-link" class=" nav-item">
|
|
<a class="nav-link active" href="{% url 'profile' %}">Profile</a>
|
|
</li>
|
|
{% endif %}
|
|
|
|
{% if request.user.is_staff or request.user|has_group:"cid_user_manager" %}
|
|
<li class="nav-item dropdown">
|
|
<a class="nav-link dropdown-toggle active" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
|
Admin
|
|
</a>
|
|
<ul class="dropdown-menu dropdown-menu-end">
|
|
{% if request.user.is_staff %}
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'admin:index' %}">Django admin</a>
|
|
</li>
|
|
{% endif %}
|
|
{% if request.user.is_superuser %}
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'logs_view' %}">Logs</a>
|
|
</li>
|
|
{% endif %}
|
|
{% if request.user.is_superuser or request.user|has_group:"cid_user_manager" %}
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'survey:survey_list' %}"><i class="bi bi-patch-question me-1"></i> Feedback/Surveys</a>
|
|
</li>
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'media_cleanup' %}">Unused media cleanup</a>
|
|
</li>
|
|
{% endif %}
|
|
{% if request.user.is_superuser or request.user|has_group:"atlas_editor" %}
|
|
<li>
|
|
<a class="dropdown-item" href="{% url 'atlas:task_overview' %}">Atlas tasks overview</a>
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
</li>
|
|
{% endif %}
|
|
{% if request.user.is_authenticated %}
|
|
<li id="logout-link" class="nav-item">
|
|
<form id="logout-form" method="post" action="{% url 'logout' %}">
|
|
{% csrf_token %}
|
|
<button class="nav-link btn btn-link" type="submit">Log out</button>
|
|
</form>
|
|
{% comment %} <a href="{% url 'logout' %}">Logout</a> {% endcomment %}
|
|
</li>
|
|
{% endif %}
|
|
</ul>
|
|
{% comment %} <form class="d-flex" role="search">
|
|
<input class="form-control me-2" type="search" placeholder="Search" aria-label="Search">
|
|
<button class="btn btn-outline-success" type="submit">Search</button>
|
|
</form> {% endcomment %}
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
<div class="content {% block content_container_class %}container content-read{% endblock %}">
|
|
{% block navigation %}
|
|
{% endblock %}
|
|
<div class="row clear-both">
|
|
<div class="col-md-12">
|
|
<div id="htmx-error"></div>
|
|
|
|
<span
|
|
id="cimar-login-needed"
|
|
hx-get='{% url "cimar_status" %}'
|
|
hx-trigger="cimar-login-needed from:body"
|
|
>
|
|
</span>
|
|
{% block content %}
|
|
{% endblock %}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<footer class="d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top">
|
|
<div class="col-md-4 d-flex align-items-center">
|
|
<a href="/" class="mb-3 me-2 mb-md-0 text-muted text-decoration-none lh-1">
|
|
<svg class="bi" width="30" height="24"><use xlink:href="#bootstrap"></use></svg>
|
|
</a>
|
|
<span class="text-muted">PenraCourses</span>
|
|
</div>
|
|
|
|
<ul class="nav col-md-4 justify-content-end list-unstyled d-flex">
|
|
<li class="ms-3"><a class="text-muted" href="{% url 'privacy' %}">Privacy</a></li>
|
|
<li class="ms-3"><a class="text-muted" href="{% url 'cookie_consent_cookie_group_list' %}">Cookies</a></li>
|
|
<li class="ms-3"><a class="text-muted" href="{% url 'about' %}">About</a></li>
|
|
</ul>
|
|
</footer>
|
|
<!-- Close review modal after HTMX reviewSaved trigger -->
|
|
<script>
|
|
document.body.addEventListener('reviewSaved', function () {
|
|
try {
|
|
var modalEl = document.getElementById('reviewModal');
|
|
if (!modalEl) return;
|
|
var modal = bootstrap.Modal.getInstance(modalEl);
|
|
if (modal) {
|
|
modal.hide();
|
|
} else {
|
|
// If no instance exists, create one and hide it
|
|
var m = new bootstrap.Modal(modalEl);
|
|
m.hide();
|
|
}
|
|
} catch (err) {
|
|
console.error('Error hiding review modal', err);
|
|
}
|
|
});
|
|
|
|
</script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Wire up all row-selection control blocks to the nearest .js-row-selectable table.
|
|
function findTableForControl(elem) {
|
|
// Walk up ancestors and look for a table that either has the
|
|
// `js-row-selectable` class or contains a checkbox named 'selection'.
|
|
//var ancestor = elem.closest('div, section, main, article, form, body');
|
|
//while (ancestor) {
|
|
// // Prefer explicit selectable class
|
|
// var tbl = ancestor.querySelector && ancestor.querySelector('table.js-row-selectable');
|
|
// if (tbl) return tbl;
|
|
// // Otherwise look for any table in this ancestor that contains a
|
|
// // checkbox input named 'selection' (or any checkbox as a fallback).
|
|
// var tables = ancestor.querySelectorAll && ancestor.querySelectorAll('table');
|
|
// if (tables && tables.length) {
|
|
// for (var i = 0; i < tables.length; i++) {
|
|
// var t = tables[i];
|
|
// if (t.querySelector && (t.querySelector('input[name="selection"]') || t.querySelector('input[type="checkbox"]'))) return t;
|
|
// }
|
|
// }
|
|
// ancestor = ancestor.parentElement;
|
|
//}
|
|
// fallback to any table on the page that looks like it has selection
|
|
var any = document.querySelector('table.js-row-selectable') //|| Array.from(document.querySelectorAll('table')).find(function(t){ return t.querySelector && (t.querySelector('input[name="selection"]') || t.querySelector('input[type="checkbox"]')); });
|
|
return any || null;
|
|
}
|
|
|
|
// Selection wiring has been moved into per-table initializers
|
|
// emitted by `SelectionTable.row_selection_controls`.
|
|
try {
|
|
if (window.__selection_inits) {
|
|
Object.keys(window.__selection_inits).forEach(function(k){
|
|
try { window.__selection_inits[k](); } catch (e) { console.error('selection init failed', k, e); }
|
|
try { delete window.__selection_inits[k]; } catch (e) {}
|
|
});
|
|
}
|
|
} catch (err) {
|
|
console.error('Error running selection initializers', err);
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
|
|
|
|
|
|
</html> |