updated html
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
{# Override left nav to include course switcher #}
|
{# Override left nav to include course switcher #}
|
||||||
{% block nav_left_extra %}
|
{% block nav_left_extra %}
|
||||||
{{ course_switcher(courses, active_course_name, '/admin/switch_course') }}
|
{{ course_switcher(courses, active_course_name, '/admin/switch_course', '-admin') }}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block admin_content %}
|
{% block admin_content %}
|
||||||
|
|||||||
@@ -19,6 +19,28 @@
|
|||||||
<script src="https://cdn.jsdelivr.net/npm/flowbite@3.1.2/dist/flowbite.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/flowbite@3.1.2/dist/flowbite.min.js"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function toggleCourseSwitcher(btn) {
|
||||||
|
const root = document.getElementById(btn.dataset.csRoot);
|
||||||
|
const menu = document.getElementById(btn.dataset.csMenu);
|
||||||
|
const chevron = document.getElementById(btn.dataset.csChevron);
|
||||||
|
const isOpen = !menu.classList.contains('hidden');
|
||||||
|
|
||||||
|
menu.classList.toggle('hidden', isOpen);
|
||||||
|
chevron.style.transform = isOpen ? '' : 'rotate(180deg)';
|
||||||
|
|
||||||
|
if (!isOpen) {
|
||||||
|
document.addEventListener('click', function handler(e) {
|
||||||
|
if (!root.contains(e.target)) {
|
||||||
|
menu.classList.add('hidden');
|
||||||
|
chevron.style.transform = '';
|
||||||
|
document.removeEventListener('click', handler);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
{% block scripts_extra %}{% endblock %}
|
{% block scripts_extra %}{% endblock %}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
{% block scripts_extra %}
|
{% block scripts_extra %}
|
||||||
<script>
|
<script>
|
||||||
const notifList = document.getElementById("notif-list");
|
const notifList = document.getElementById("notif-list");
|
||||||
const socket = io({ transports: ['websocket'] });
|
const socket = io();
|
||||||
|
|
||||||
socket.on("confused", data => {
|
socket.on("confused", data => {
|
||||||
if (notifList.children.length === 1 &&
|
if (notifList.children.length === 1 &&
|
||||||
|
|||||||
@@ -27,9 +27,9 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Col 2: course switcher (perfectly centered) #}
|
{# Desktop header, Col 2 #}
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
{{ course_switcher(courses, active_course_name, '/switch_course') }}
|
{{ course_switcher(courses, active_course_name, '/switch_course', '-desktop') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{# Col 3: social + admin (right-aligned) #}
|
{# Col 3: social + admin (right-aligned) #}
|
||||||
@@ -59,9 +59,6 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-3">
|
<div class="flex items-center gap-3">
|
||||||
<a href="https://zulip.in.tum.de/#narrow/channel/3234-ITSec-Tutorium-Simon-Bu.C3.9Fmann" target="_blank">
|
|
||||||
<img src="{{ url_for('static', filename='zulip_icon.svg') }}" class="h-7 w-7">
|
|
||||||
</a>
|
|
||||||
<a href="https://discordapp.com/users/306086176585154560" target="_blank">
|
<a href="https://discordapp.com/users/306086176585154560" target="_blank">
|
||||||
<img src="{{ url_for('static', filename='discord_icon.svg') }}" class="h-7 w-7">
|
<img src="{{ url_for('static', filename='discord_icon.svg') }}" class="h-7 w-7">
|
||||||
</a>
|
</a>
|
||||||
@@ -87,10 +84,13 @@
|
|||||||
</section>
|
</section>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
|
|
||||||
|
{# Mobile, below the banner #}
|
||||||
<div class="flex justify-center md:hidden">
|
<div class="flex justify-center md:hidden">
|
||||||
{{ course_switcher(courses, active_course_name, '/switch_course') }}
|
{{ course_switcher(courses, active_course_name, '/switch_course', '-mobile') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
{# ── Password Form ─────────────────────────────────────────── #}
|
{# ── Password Form ─────────────────────────────────────────── #}
|
||||||
<section class="flex justify-center">
|
<section class="flex justify-center">
|
||||||
<div class="w-full max-w-md">
|
<div class="w-full max-w-md">
|
||||||
|
|||||||
@@ -76,24 +76,31 @@
|
|||||||
|
|
||||||
|
|
||||||
{# Course-switcher dropdown (used in admin and index pages). #}
|
{# Course-switcher dropdown (used in admin and index pages). #}
|
||||||
{% macro course_switcher(courses, active_course_name, switch_url_prefix) %}
|
{% macro course_switcher(courses, active_course_name, switch_url_prefix, id_suffix='') %}
|
||||||
<div class="relative" id="course-switcher">
|
{% set root_id = 'course-switcher' ~ id_suffix %}
|
||||||
|
{% set menu_id = 'course-switcher-menu' ~ id_suffix %}
|
||||||
|
{% set chevron_id = 'course-switcher-chevron' ~ id_suffix %}
|
||||||
|
|
||||||
|
<div class="relative" id="{{ root_id }}">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
onclick="toggleCourseSwitcher()"
|
data-cs-root="{{ root_id }}"
|
||||||
|
data-cs-menu="{{ menu_id }}"
|
||||||
|
data-cs-chevron="{{ chevron_id }}"
|
||||||
|
onclick="toggleCourseSwitcher(this)"
|
||||||
class="flex items-center gap-2 px-4 py-1.5 rounded-full
|
class="flex items-center gap-2 px-4 py-1.5 rounded-full
|
||||||
bg-surface shadow-md ring-1 ring-border
|
bg-surface shadow-md ring-1 ring-border
|
||||||
text-sm font-medium text-text
|
text-sm font-medium text-text
|
||||||
hover:ring-primary hover:text-primary
|
hover:ring-primary hover:text-primary
|
||||||
transition whitespace-nowrap">
|
transition whitespace-nowrap">
|
||||||
<span id="course-switcher-label">{{ active_course_name }}</span>
|
<span>{{ active_course_name }}</span>
|
||||||
<svg class="w-3.5 h-3.5 text-muted transition-transform duration-200" id="course-switcher-chevron"
|
<svg class="w-3.5 h-3.5 text-muted transition-transform duration-200" id="{{ chevron_id }}"
|
||||||
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div id="course-switcher-menu"
|
<div id="{{ menu_id }}"
|
||||||
class="hidden absolute left-1/2 -translate-x-1/2 mt-2 w-52 z-50
|
class="hidden absolute left-1/2 -translate-x-1/2 mt-2 w-52 z-50
|
||||||
bg-surface border border-border rounded-xl shadow-lg overflow-hidden whitespace-nowrap">
|
bg-surface border border-border rounded-xl shadow-lg overflow-hidden whitespace-nowrap">
|
||||||
{% for course in courses %}
|
{% for course in courses %}
|
||||||
@@ -112,25 +119,4 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
|
||||||
function toggleCourseSwitcher() {
|
|
||||||
const menu = document.getElementById('course-switcher-menu');
|
|
||||||
const chevron = document.getElementById('course-switcher-chevron');
|
|
||||||
const isOpen = !menu.classList.contains('hidden');
|
|
||||||
menu.classList.toggle('hidden', isOpen);
|
|
||||||
chevron.style.transform = isOpen ? '' : 'rotate(180deg)';
|
|
||||||
|
|
||||||
if (!isOpen) {
|
|
||||||
// Close when clicking outside
|
|
||||||
document.addEventListener('click', function handler(e) {
|
|
||||||
if (!document.getElementById('course-switcher').contains(e.target)) {
|
|
||||||
menu.classList.add('hidden');
|
|
||||||
chevron.style.transform = '';
|
|
||||||
document.removeEventListener('click', handler);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ services:
|
|||||||
depends_on:
|
depends_on:
|
||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
redis:
|
|
||||||
condition: service_started
|
|
||||||
restart: on-failure
|
restart: on-failure
|
||||||
|
|
||||||
prometheus:
|
prometheus:
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ scrape_configs:
|
|||||||
static_configs:
|
static_configs:
|
||||||
- targets:
|
- targets:
|
||||||
- db:5432
|
- db:5432
|
||||||
- redis:6379
|
|
||||||
- tutortool:5000
|
- tutortool:5000
|
||||||
relabel_configs:
|
relabel_configs:
|
||||||
- source_labels: [__address__]
|
- source_labels: [__address__]
|
||||||
|
|||||||
@@ -18,6 +18,5 @@ dependencies = [
|
|||||||
"markdown>=3.9",
|
"markdown>=3.9",
|
||||||
"psycopg2-binary>=2.9.11",
|
"psycopg2-binary>=2.9.11",
|
||||||
"pytz>=2025.2",
|
"pytz>=2025.2",
|
||||||
"redis>=7.0.1",
|
|
||||||
"xkcdpass>=1.20.0",
|
"xkcdpass>=1.20.0",
|
||||||
]
|
]
|
||||||
|
|||||||
Reference in New Issue
Block a user