{% extends "base.html" %} {% block title %}{{ schedule.name }}{% endblock %} {% block nav_extra %}{% endblock %} {% block content %} {% from "macros/metrics.html" import render_metric %} {% set TYPE_SHORT = { 'Лекция': 'Лек', 'Практика': 'Пр', 'Лаб. работа': 'Лаб', 'Лабораторная': 'Лаб', 'Семинар': 'Сем', 'Не указано': '' } %} {# ── Шапка ── #}

{{ schedule.name }}

{% if can_edit and not is_shared_view %} {% endif %}
{% if can_edit and not is_shared_view %} Предметы {% endif %} {% if can_edit and not is_shared_view %} {% endif %}
{# ══════════════════════════════ РАСПИСАНИЕ ══════════════════════════════ #}
{% for i in range(7) %} {% set day_slots = week_view[i] %} {% if day_slots %}
{{ days_display[i] }} {% if i == today_idx %}сегодня{% endif %} {{ week_dates[i].strftime('%d.%m') }}
{% for slot in day_slots %} {% set sid = 'se-' ~ i ~ '-' ~ loop.index0 %} {% if slot.get('_group') %} {# Несколько предметов в одно время — показываем все сразу (фильтруем скрытые) #} {% set visible_slots = [] %} {% for s in slot.slots %} {% set _cfg = configs.get(s.subject) %} {% if not (_cfg and _cfg.hidden) %}{% set _ = visible_slots.append(s) %}{% endif %} {% endfor %} {% if visible_slots %}
{{ slot.time or '—' }} {% if visible_slots | length > 1 %}{{ visible_slots | length }} предмета{% endif %}
{% for s in visible_slots %}
{{ s.subject }} {% if s.classroom %}
{{ s.classroom }}
{% endif %}
{% set t_short = TYPE_SHORT.get(s.type, s.type[:3] if s.type and s.type|length > 4 else s.type) %} {% if t_short %} {{ t_short }} {% endif %}
{% endfor %}
{% endif %}{# visible_slots #} {% else %} {# Обычный слот — пропустить если предмет скрыт #} {% set _slot_cfg = configs.get(slot.subject) %} {% if not (_slot_cfg and _slot_cfg.hidden) %} {% set merged_type = '/' in (slot.type or '') %}
{{ slot.time or '—' }}
{{ slot.subject }}
{% if slot.classroom %}
{{ slot.classroom }}
{% endif %}
{% set t_short = TYPE_SHORT.get(slot.type, slot.type[:3] if slot.type and slot.type|length > 4 else slot.type) %} {% if t_short and slot.type != 'Не указано' %} {{ t_short }} {% endif %} {% if not merged_type %}
{% endif %} ▾
{% if slot.teacher %}
{{ slot.teacher }}
{% endif %} {% if slot.date_range and slot.date_range != 'Весь период' %}
{{ slot.date_range }}
{% endif %} {% set cfg = configs.get(slot.subject) %} {% if cfg and cfg.completion_type %}
{{ cfg.completion_type }} {% if cfg.completed %}Завершён{% endif %}
{% elif cfg and cfg.completed %}
Завершён
{% endif %} {% if cfg and cfg.sdo_url %} {% endif %} {% if cfg and cfg.description %}
{{ cfg.description }}
{% endif %} {% set metrics = cfg.metrics | list if cfg else [] %} {% if metrics %}
{% for m in metrics %} {{ m.label }} {% endfor %}
{% else %}
Трекеры не добавлены
{% endif %}
{% endif %}{# not hidden #} {% endif %}{# _group / regular slot #} {% endfor %}
{% endif %} {% endfor %}
{# ══════════════════════════════ ДЭШБОРД ══════════════════════════════ #} {% if all_metrics %} {# Вычисляем сколько трекеров заполнены #} {% set completed_count = namespace(n=0) %} {% set filled_ids = [] %} {% set total_count = all_metrics | length %} {% for entry in all_metrics %} {% set m = entry.metric %} {% set prog = m.progress or {} %} {% set cfg_m = m.config or {} %} {% set is_full = false %} {% if m.type == 'checkpoints' %} {% set is_full = prog.get('checked', []) | length >= cfg_m.get('total', 1) | int %} {% elif m.type == 'progress_bar' %} {% set is_full = prog.get('current', 0) | float >= cfg_m.get('max', 1) | float %} {% elif m.type == 'counter' %} {% set is_full = cfg_m.get('max') and prog.get('current', 0) | int >= cfg_m.get('max') | int %} {% elif m.type == 'checklist' %} {% set is_full = cfg_m.get('items', []) | length > 0 and prog.get('checked', []) | length >= cfg_m.get('items', []) | length %} {% elif m.type == 'deadlines' %} {% set is_full = cfg_m.get('items', []) | length > 0 and prog.get('completed', []) | length >= cfg_m.get('items', []) | length %} {% elif m.type == 'stages' %} {% set is_full = cfg_m.get('stages', []) | length > 0 and prog.get('current_stage', 0) | int >= cfg_m.get('stages', []) | length %} {% elif m.type == 'effort_hours' %} {% set is_full = cfg_m.get('goal_hours') and prog.get('hours', 0) | float >= cfg_m.get('goal_hours') | float %} {% endif %} {% if is_full %}{% set completed_count.n = completed_count.n + 1 %}{% endif %} {% endfor %}
Трекеры
{% if completed_count.n > 0 %} {% endif %} {% if can_edit and not is_shared_view %} {% endif %}
{% for entry in all_metrics %} {% set m = entry.metric %} {% set prog = m.progress or {} %} {% set cfg_m = m.config or {} %} {% set is_full = false %} {% if m.type == 'checkpoints' %} {% set is_full = prog.get('checked', []) | length >= cfg_m.get('total', 1) | int and cfg_m.get('total', 0) | int > 0 %} {% elif m.type == 'progress_bar' %} {% set is_full = prog.get('current', 0) | float >= cfg_m.get('max', 1) | float and cfg_m.get('max', 0) | float > 0 %} {% elif m.type == 'counter' %} {% set is_full = cfg_m.get('max') and prog.get('current', 0) | int >= cfg_m.get('max') | int %} {% elif m.type == 'checklist' %} {% set is_full = cfg_m.get('items', []) | length > 0 and prog.get('checked', []) | length >= cfg_m.get('items', []) | length %} {% elif m.type == 'deadlines' %} {% set is_full = cfg_m.get('items', []) | length > 0 and prog.get('completed', []) | length >= cfg_m.get('items', []) | length %} {% elif m.type == 'stages' %} {% set is_full = cfg_m.get('stages', []) | length > 0 and prog.get('current_stage', 0) | int >= cfg_m.get('stages', []) | length %} {% elif m.type == 'effort_hours' %} {% set is_full = cfg_m.get('goal_hours') and prog.get('hours', 0) | float >= cfg_m.get('goal_hours') | float %} {% endif %} {% if is_full %}{% set _ = filled_ids.append(m.id) %}{% endif %} {{ render_metric(m, can_edit) }} {% endfor %}
{% if filled_ids %} {% endif %} {% endif %} {# ══ Модальное окно шаринга ══ #} {% if can_edit and not is_shared_view %} {% endif %} {# ══ Модальное окно переименования ══ #} {# ══ Модальное окно изменения времени ══ #} {% endblock %} {% block scripts %} {% if can_edit and not is_shared_view %} {% endif %} {% endblock %}