UI bugfixes with boss

This commit is contained in:
Константин Лебединский
2026-04-30 19:53:49 +05:00
parent df6e770f90
commit b72b485fce
17 changed files with 469 additions and 250 deletions
@@ -39,18 +39,6 @@
<p id="attempt-error" class="callout callout--error attempt-error-box" style="display:none;"></p>
<div id="attempt-result" class="surface-card attempt-result-card" style="display:none;"></div>
<dialog id="hint-modal" class="save-modal attempt-hint-dialog">
<div class="save-modal__inner attempt-hint-inner">
<h3 class="font-headline text-base font-semibold mb-2" id="hint-title">Подсказка</h3>
<p id="hint-verdict" class="attempt-hint-verdict"></p>
<p id="hint-correct" class="text-sm text-ink-600 mb-2"></p>
<p id="hint-explanation" class="text-sm text-ink-800 leading-relaxed"></p>
<div class="mt-4 flex justify-end">
<button type="button" class="btn btn-primary btn--sm" id="hint-close-btn">Понятно</button>
</div>
</div>
</dialog>
</div>
{% endblock %}
@@ -5,6 +5,14 @@
<div class="test-detail-page attempt-review-page">
<p class="link-back"><a href="/tests">← к списку тестов</a></p>
<h1 class="font-headline" style="font-size:1.35rem;margin-top:0;">Разбор: {{ review.testTitle }}</h1>
{% set tl = review.timeLimit %}
{% set timestr = 'без ограничения' if tl is none or tl == 0 else (tl|string ~ ' мин') %}
{% set rm = review.resultMode or 'end' %}
{% set res = 'сразу' if rm == 'immediate' else 'в конце' %}
{% set hint = 'недоступны' if rm != 'immediate' else ('вкл' if review.hintsEnabled else 'выкл') %}
<p class="text-sm text-muted" style="margin:0.35rem 0 0.75rem;line-height:1.45;">
Порог: {{ review.passingThreshold }}% · Вопросов: {{ review.totalQuestions }} · Время: {{ timestr }} · Результат: {{ res }} · Подсказки: {{ hint }}
</p>
<p>
Правильно: <strong>{{ review.correctCount }}</strong> из {{ review.totalQuestions }}
({{ review.percent }}%). Порог: {{ review.passingThreshold }}%.
+60 -71
View File
@@ -12,9 +12,6 @@
<textarea id="test-title" maxlength="200" rows="1" placeholder="Название теста"
class="hero-brick__title font-headline"></textarea>
<textarea id="test-title" maxlength="200" rows="1" placeholder="Название теста"
class="hero-brick__title font-headline"></textarea>
<textarea id="test-description" rows="2" placeholder="Краткое описание (необязательно)"
class="hero-brick__desc"></textarea>
@@ -33,6 +30,12 @@
<span class="hero-brick__sep">·</span>
<span>Вопросов: <b id="q-count">0</b></span>
<span class="hero-brick__sep">·</span>
<span>Время: <b id="editor-hero-time-val"></b></span>
<span class="hero-brick__sep">·</span>
<span>Результат: <b id="editor-hero-result-val"></b></span>
<span class="hero-brick__sep">·</span>
<span>Подсказки: <b id="editor-hero-hints-val"></b></span>
<span class="hero-brick__sep">·</span>
<span id="chain-active-display">Активна в каталоге</span>
</div>
@@ -55,7 +58,7 @@
<summary class="cabinet-disclosure__summary">
<span class="cabinet-disclosure__summary-text">
<span class="cabinet-disclosure__summary-title font-headline">Параметры теста</span>
<span class="cabinet-disclosure__summary-sub">Порог, таймер, режим показа результата и подсказок</span>
<span class="cabinet-disclosure__summary-sub">Порог, таймер, режим результата, подсказки и шаблон структуры вопросов</span>
</span>
</summary>
<div class="cabinet-disclosure__body">
@@ -79,24 +82,56 @@
<legend class="settings-row__label">Когда показывать результат</legend>
<label class="settings-radio">
<input type="radio" name="result-mode" value="end" />
<span>В конце теста <span class="settings-row__hint">(подсказок не будет)</span></span>
<span>В конце теста</span>
</label>
<label class="settings-radio">
<input type="radio" name="result-mode" value="immediate" />
<span>Сразу после ответа <span class="settings-row__hint">(с подсказкой)</span></span>
<span>Сразу после ответа</span>
</label>
</fieldset>
<label class="settings-row settings-row--toggle" id="test-hints-row" style="display:none;">
<span class="settings-row__label">
Показывать подсказку после ответа
<span class="settings-row__hint">Краткое объяснение во всплывающем окне</span>
<span class="settings-row__hint">Краткое объяснение под вариантами ответа</span>
</span>
<input id="test-hints-enabled" type="checkbox" />
</label>
<div class="settings-row settings-row--block" id="test-hints-actions" style="display:none;">
<button id="btn-generate-hints" class="btn btn-ghost btn--sm" type="button">Сгенерировать подсказки</button>
<p id="hints-status" class="settings-row__hint" style="margin-top:0.35rem;"></p>
<div class="settings-row settings-row--block">
<span class="settings-row__label">Шаблон структуры вопросов</span>
<p class="settings-row__hint" style="margin-bottom:0.5rem;">
Задаёт сетку для автосборки пустых вопросов и для генерации через ИИ. При смене чисел список вопросов пересобирается (с подтверждением, если уже есть текст).
</p>
<div class="flex flex-wrap items-end gap-3">
<label class="block">
<span class="form-label">Вопросов</span>
<input id="ai-q-count" type="number" min="1" max="30" step="1" value="7"
class="form-input" style="width:90px;" />
</label>
<label class="block">
<span class="form-label">Вариантов</span>
<input id="ai-o-count" type="number" min="2" max="8" step="1" value="3"
class="form-input" style="width:90px;" />
</label>
</div>
<div class="mt-3 grid gap-2 sm:grid-cols-3 items-end">
<label class="inline-flex items-center gap-2 min-h-9">
<input id="template-global-multi" type="checkbox"
class="rounded border-ink-300 text-brand-600 focus:ring-brand-500" />
<span class="text-sm">Несколько правильных ответов (все вопросы)</span>
</label>
<label class="block">
<span class="form-label">Правильных: от</span>
<input id="template-min-correct" type="number" min="1" max="8" step="1" value="1"
class="form-input" style="width:90px;" />
</label>
<label class="block">
<span class="form-label">до</span>
<input id="template-max-correct" type="number" min="1" max="8" step="1" value="1"
class="form-input" style="width:90px;" />
</label>
</div>
</div>
<div class="settings-row settings-row--block" style="padding-top:0.75rem; border-top:1px solid var(--outline-variant); margin-top:0.25rem;">
@@ -108,60 +143,18 @@
</div>
</details>
<details class="cabinet-disclosure cabinet-brick" open>
<details class="cabinet-disclosure cabinet-brick">
<summary class="cabinet-disclosure__summary">
<span class="cabinet-disclosure__summary-text">
<span class="cabinet-disclosure__summary-title font-headline">Вопросы</span>
<span class="cabinet-disclosure__summary-sub">Тексты, варианты и при необходимости загрузка из файла</span>
<span class="cabinet-disclosure__summary-title font-headline">Инструменты генерации</span>
<span class="cabinet-disclosure__summary-sub">Генерация через ИИ, проверка, улучшение и импорт документа</span>
</span>
</summary>
<div class="cabinet-disclosure__body">
<section class="rounded-2xl bg-brand-50/60 border border-brand-100 p-4 sm:p-5 test-detail-ai-panel">
{# ── Создать шаблон ──────────────────────────────────────── #}
<div class="question-editor-block question-editor-block--first">
<h3 class="test-detail-subsection__title">Структура теста</h3>
<p class="muted text-xs mb-3">
Укажите количество вопросов и вариантов — создайте шаблон и заполните его вручную или через ИИ.
</p>
<div class="flex flex-wrap items-end gap-3">
<label class="block">
<span class="form-label">Вопросов</span>
<input id="ai-q-count" type="number" min="1" max="30" step="1" value="7"
class="form-input" style="width:90px;" />
</label>
<label class="block">
<span class="form-label">Вариантов</span>
<input id="ai-o-count" type="number" min="2" max="8" step="1" value="3"
class="form-input" style="width:90px;" />
</label>
<button id="create-template"
class="btn btn-ghost" type="button" style="min-height:43px;">
<span class="material-symbols-outlined text-base" style="vertical-align:-3px;">grid_view</span>
Создать шаблон
</button>
</div>
<div class="mt-3 grid gap-2 sm:grid-cols-3 items-end">
<label class="inline-flex items-center gap-2 min-h-9">
<input id="template-global-multi" type="checkbox"
class="rounded border-ink-300 text-brand-600 focus:ring-brand-500" />
<span class="text-sm">Несколько правильных ответов (все вопросы)</span>
</label>
<label class="block">
<span class="form-label">Правильных: от</span>
<input id="template-min-correct" type="number" min="1" max="8" step="1" value="1"
class="form-input" style="width:90px;" />
</label>
<label class="block">
<span class="form-label">до</span>
<input id="template-max-correct" type="number" min="1" max="8" step="1" value="1"
class="form-input" style="width:90px;" />
</label>
</div>
</div>
{# ── Заполнить через ИИ по теме ──────────────────────────── #}
<div class="question-editor-block">
<div class="question-editor-block question-editor-block--first">
<h3 class="test-detail-subsection__title">Заполнить через ИИ</h3>
<label class="block">
<span class="form-label">Тема / промпт</span>
@@ -233,7 +226,17 @@
<p id="ai-status" class="mt-3 text-sm text-ink-500 min-h-[1.25rem]"></p>
</section>
{# ── 3. Вопросы ─────────────────────────────────────────────── #}
</div>
</details>
<details class="cabinet-disclosure cabinet-brick" open>
<summary class="cabinet-disclosure__summary">
<span class="cabinet-disclosure__summary-text">
<span class="cabinet-disclosure__summary-title font-headline">Вопросы</span>
<span class="cabinet-disclosure__summary-sub">Тексты, варианты ответов и подсказки по каждому вопросу</span>
</span>
</summary>
<div class="cabinet-disclosure__body">
<section class="mt-1">
<div class="flex items-center gap-2">
<h2 class="font-semibold text-ink-900">Вопросы (<span id="q-count-mirror">0</span>)</h2>
@@ -249,20 +252,6 @@
</button>
</div>
{# Кнопка «Сохранить» под вопросами #}
<div class="mt-5 flex items-center gap-3">
<button id="save-draft-inline"
class="inline-flex items-center gap-2 px-5 py-2.5 rounded-lg
bg-brand-600 hover:bg-brand-700 text-white font-medium min-h-11 btn btn-primary">
<span class="material-symbols-outlined text-base">save</span>
Сохранить
</button>
<button id="btn-cancel-inline"
class="inline-flex px-3 py-2 rounded-lg text-ink-700 hover:bg-ink-100 text-sm btn btn-ghost">
Отмена
</button>
<p id="save-status-inline" class="text-xs text-ink-500"></p>
</div>
</section>
</div>
</details>
+23 -3
View File
@@ -1,6 +1,21 @@
{% extends "base.html" %}
{% block title %}Тесты — каталог{% endblock %}
{% macro catalog_test_params_line(t) -%}
{%- set tl = t.time_limit -%}
{%- set timestr = 'без ограничения' if tl is none or tl == 0 else (tl|string ~ ' мин') -%}
{%- set rm = t.result_mode or 'end' -%}
{%- set res = 'сразу' if rm == 'immediate' else 'в конце' -%}
{%- if rm != 'immediate' -%}
{%- set hint = 'недоступны' -%}
{%- elif t.hints_enabled -%}
{%- set hint = 'вкл' -%}
{%- else -%}
{%- set hint = 'выкл' -%}
{%- endif -%}
Порог: {{ t.passing_threshold }}% · Вопросов: {{ t.questions_count }} · Время: {{ timestr }} · Результат: {{ res }} · Подсказки: {{ hint }}
{%- endmacro %}
{% block content %}
{% if ui_variant == 'legacy' %}
<section class="legacy-list-shell">
@@ -22,6 +37,7 @@
{{ t.author_full_name or '—' }}
<span class="list-row__meta-tail"> · Версия {{ t.version }}</span>
</span>
<span class="list-row__params muted" style="display:block;font-size:0.78rem;margin-top:0.2rem;line-height:1.35;">{{ catalog_test_params_line(t) }}</span>
</a>
</div>
<div class="list-row__side">
@@ -48,6 +64,7 @@
{{ t.author_full_name or '—' }}
<span class="list-row__meta-tail"> · Версия {{ t.version }} · скрыт</span>
</span>
<span class="list-row__params muted" style="display:block;font-size:0.78rem;margin-top:0.2rem;line-height:1.35;">{{ catalog_test_params_line(t) }}</span>
</a>
</div>
<div class="list-row__side">
@@ -96,6 +113,7 @@
Открыть
</span>
</div>
<p class="mt-1.5 text-xs text-ink-500 leading-snug">{{ catalog_test_params_line(t) }}</p>
</a>
</li>
{% endfor %}
@@ -111,10 +129,12 @@
</summary>
<ul class="mt-3 space-y-2">
{% for t in hidden %}
<li class="flex items-center justify-between gap-2 text-sm">
<span>{{ t.title }} <span class="text-ink-500">· v{{ t.version }}</span></span>
<li class="flex flex-col gap-1 sm:flex-row sm:items-start sm:justify-between text-sm">
<span class="min-w-0">{{ t.title }} <span class="text-ink-500">· v{{ t.version }}</span>
<span class="block text-xs text-ink-500 mt-0.5 leading-snug">{{ catalog_test_params_line(t) }}</span>
</span>
<a href="{{ url_for('tests.tests_editor_page', test_id=t.id) }}"
class="text-brand-700 hover:underline">Открыть</a>
class="text-brand-700 hover:underline shrink-0">Открыть</a>
</li>
{% endfor %}
</ul>