Add course outline sidebar to the lesson page
Shows every section and lesson in the course - videos and standalone documents alike - so jumping to a different section no longer means backing out to the course page first. Current lesson is highlighted, its section auto-expands and scrolls into view; sticky on desktop, stacks below the player on narrow viewports. Replaces the old "Lessons in this section" list, which only showed the current section. The tree-rendering markup (shared with the loaded-course dashboard view) is now a single macro in templates/_course_tree.html instead of being duplicated, so both views stay in sync going forward. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
{% import '_icons.html' as icons %}
|
||||
{% import '_course_tree.html' as tree %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -1089,67 +1090,7 @@
|
||||
</div>
|
||||
|
||||
<div class="tree-container">
|
||||
{% macro render_tree_node(node, depth=0) %}
|
||||
{% set stats = section_stats(node) %}
|
||||
<div class="tree-item">
|
||||
<div class="tree-header directory" onclick="toggleTree(this)">
|
||||
<div class="tree-title">
|
||||
<span class="tree-icon">{{ icons.icon('folder', 16) }}</span>
|
||||
<span class="tree-name">{{ node.name }}</span>
|
||||
<span class="tree-stats">
|
||||
{% if stats.total_lessons %}{{ stats.completed_lessons }}/{{ stats.total_lessons }} watched{% else %}Empty{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
{% if node.children or node.lessons %}
|
||||
<button class="tree-toggle">▶</button>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
{% if node.children or node.lessons %}
|
||||
<div class="tree-content">
|
||||
{% for child_name, child_node in node.children.items() %}
|
||||
{{ render_tree_node(child_node, depth + 1) }}
|
||||
{% endfor %}
|
||||
|
||||
{% for lesson in node.lessons %}
|
||||
{% set lesson_relative_path = lesson.path|replace('\\', '/')|replace(course.path|replace('\\', '/'), '')|replace('//', '/')|replace('/', '', 1) %}
|
||||
{% set percent_watched = 100 if lesson.completed else (((100 * lesson.progress_seconds / lesson.duration_seconds)|round|int) if (lesson.duration_seconds and lesson.progress_seconds) else 0) %}
|
||||
<div class="lesson-item {% if lesson.completed %}completed{% elif percent_watched %}in-progress{% endif %}"
|
||||
onclick="window.location.href='/lesson/{{ lesson_relative_path }}/{{ lesson.title|replace(' ', '_') }}'">
|
||||
<div class="lesson-title">
|
||||
<span class="lesson-icon">
|
||||
{% if lesson.lesson_type == 'video' %}{{ icons.icon('video', 16) }}
|
||||
{% elif lesson.lesson_type == 'audio' %}{{ icons.icon('music', 16) }}
|
||||
{% elif lesson.lesson_type == 'quiz' %}{{ icons.icon('clipboard', 16) }}
|
||||
{% elif lesson.lesson_type == 'mixed' %}{{ icons.icon('package', 16) }}
|
||||
{% else %}{{ icons.icon('file-text', 16) }}{% endif %}
|
||||
</span>
|
||||
<span class="lesson-name">{{ lesson.title }}</span>
|
||||
</div>
|
||||
<div class="lesson-meta">
|
||||
<span class="lesson-type {{ lesson.lesson_type }}">{{ lesson.lesson_type|title }}</span>
|
||||
{% if lesson.duration_seconds and lesson.duration_seconds >= 60 %}
|
||||
<span class="lesson-duration">{{ lesson.duration_seconds|format_duration }}</span>
|
||||
{% endif %}
|
||||
{% if lesson.completed %}
|
||||
<span class="status-icon completed">{{ icons.icon('check', 14) }}</span>
|
||||
{% elif percent_watched %}
|
||||
<span class="watched-badge">{{ percent_watched }}% watched</span>
|
||||
{% else %}
|
||||
<span class="status-icon pending">{{ icons.icon('circle', 14) }}</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if percent_watched %}
|
||||
<div class="lesson-progress-track"><div class="lesson-progress-fill" style="width: {{ percent_watched }}%;"></div></div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{{ render_tree_node(course.root_node) }}
|
||||
{{ tree.render_tree_node(course.root_node, course.path) }}
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
|
||||
Reference in New Issue
Block a user