Files
Web-Parser-Constructor/src/parser_lab/web/templates/admin.html
T
2026-10-01 00:28:16 +10:00

22 lines
8.4 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html><html lang="ru" class="static-site"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Кабинет · Parser Lab</title><link rel="icon" type="image/png" href="/static/favicon.png"><link rel="stylesheet" href="/static/site.css"><meta name="csrf-token" content="{{ csrf }}"><script defer src="/static/admin.js?v=questionnaire-autodetect-1"></script></head>
<body class="admin-body"><aside class="admin-sidebar"><a class="brand" href="/admin"><span class="brand-mark">[ ]</span>Parser Lab</a><p class="muted">Кабинет преподавателя</p><nav><a class="{{ 'active' if screen!='import' }}" href="/admin">Мои коллекции</a><a class="{{ 'active' if screen=='import' }}" href="/admin/import">Импорт файла</a></nav><div class="sidebar-bottom"><a href="/">Учебный сайт ↗</a><p class="muted">{{ username }}</p><form method="post" action="/logout"><input type="hidden" name="csrf" value="{{ csrf }}"><button class="text-button" type="submit">Выйти</button></form></div></aside>
<main class="admin-main" data-screen="{{ screen }}"><div id="status" role="status" hidden></div>
{% if screen=='catalog' %}
<div class="admin-heading"><div><div class="eyebrow">КАБИНЕТ / КОЛЛЕКЦИИ</div><h1>Коллекции данных</h1><p class="muted">Всего коллекций: {{ datasets|length }}</p></div><a class="button" href="/admin/import">Загрузить данные</a></div>
<div class="table-scroll"><table class="dataset-table"><thead><tr><th>Название</th><th>Записи</th><th>Представления</th><th>Статус</th><th></th></tr></thead><tbody>{% for d in datasets %}<tr><td><div class="catalog-title">{{ d.title }}</div><div class="catalog-file">{{ d.filename }}</div></td><td>{{ d.records|length }}</td><td>{{ d.views|length }}</td><td><span class="status {{ 'published' if active[d.id] }}">{{ 'Опубликовано' if active[d.id] else 'Черновик' }}</span></td><td><a href="/admin/datasets/{{ d.id }}" aria-label="Открыть {{ d.title }}">Открыть</a></td></tr>{% else %}<tr><td colspan="5">Коллекций пока нет. Загрузите первый набор данных.</td></tr>{% endfor %}</tbody></table></div>
{% elif screen=='import' %}
<div class="eyebrow">КОЛЛЕКЦИИ / ИМПОРТ</div><h1>Импорт данных</h1><p class="muted">Выберите файл, проверьте структуру и сохраните коллекцию.</p>
<form id="import-form" class="form-panel"><label class="file-drop">CSV, JSON или JSONL · до {{ (max_bytes/1024/1024)|int }} МиБ<input name="file" type="file" accept=".csv,.json,.jsonl" required></label><label>Название коллекции<input name="title" value="{{ replace.title if replace else '' }}" required></label><div class="form-grid"><label>Кодировка CSV<select name="encoding" aria-label="Кодировка CSV"><option value="utf-8-sig">UTF-8</option><option value="cp1251">Windows-1251</option></select></label><label>Разделитель CSV<select name="delimiter" aria-label="Разделитель CSV"><option value="">Автоматически</option><option value=",">Запятая</option><option value=";">Точка с запятой</option><option value="&#9;">Табуляция</option></select></label></div><label>Записи внутри JSON<select name="pointer" aria-label="Записи внутри JSON"><option value="">Весь документ / корневой массив</option></select></label>
{% if replace %}<input type="hidden" name="replace_id" value="{{ replace.id }}"><input type="hidden" name="revision" value="{{ replace.revision }}"><p class="notice">Замена файла сбросит настройки представлений. Опубликованные версии сохранятся.</p>{% endif %}
<label id="root-choice" class="check-label notice" hidden><input type="checkbox" name="root_confirmed" value="1">Использовать весь документ как одну запись</label><div class="toolbar"><button id="inspect" type="button">Проверить файл</button><button id="import-save" type="submit" disabled>Сохранить и настроить →</button><a href="/admin">К коллекциям</a></div></form><div id="import-result"></div>
{% elif screen=='edit' %}
<div class="eyebrow">КОЛЛЕКЦИИ / РЕДАКТОР</div><h1>{{ draft.title }}</h1><p class="muted">{{ draft.records|length }} записей · {{ draft.filename }}</p>
{% if questionnaire_repair %}<section class="notice" id="questionnaire-repair"><strong>Найдены анкеты: {{ questionnaire_repair.records|length }} участников.</strong><p>{% if questionnaire_repair.pointer %}Участники находятся внутри {{ questionnaire_repair.pointer }}. Можно разделить их на отдельные записи и автоматически назначить вопросы и ответы. Настройки представлений черновика будут пересозданы; опубликованные версии сохранятся.{% else %}Можно автоматически назначить заголовки участников, вопросы и ответы.{% endif %}</p><button type="button" id="configure-questionnaire">Настроить анкеты автоматически</button></section>{% endif %}<div class="toolbar editor-toolbar"><button id="save-draft">Сохранить черновик</button><button id="publish">Опубликовать новую версию</button><a id="full-preview" target="_blank" rel="noopener">Предпросмотр ↗</a><a href="/admin/datasets/{{ draft.id }}/versions">Публикации</a><span id="dirty" class="muted" hidden>Есть несохранённые изменения</span></div>
<div class="editor-layout"><div class="editor-settings"><section class="form-panel"><label>Представление<select id="kind" aria-label="Представление">{% for k,label in kinds.items() %}<option value="{{ k }}">{{ label }}</option>{% endfor %}</select></label><label class="check-label"><input id="enabled" type="checkbox">Включить это представление</label><div id="view-controls"></div></section>
<section class="form-panel"><h2>О коллекции</h2><label>Название<input id="title" value="{{ draft.title }}"></label><label>Описание коллекции<textarea id="description" rows="3">{{ draft.description }}</textarea></label><label>Адрес коллекции<input id="slug" value="{{ draft.slug }}"></label><a href="/admin/import?replace={{ draft.id }}">Заменить исходный файл</a></section></div>
<section class="editor-preview-panel"><div class="editor-preview-head"><h2>Предпросмотр изменений</h2><span id="preview-kind"></span></div><div class="editor-preview" id="live-preview"></div><p class="preview-foot">Первые 5 записей · Опубликованные данные изменятся только после создания новой версии.</p></section></div><script id="editor-data" type="application/json">{{ editor_data|tojson }}</script>
{% elif screen=='versions' %}
<div class="eyebrow">КОЛЛЕКЦИИ / ПУБЛИКАЦИИ</div><h1>{{ draft.title }}</h1><div class="toolbar"><a href="/admin/datasets/{{ draft.id }}">← Настройка</a><button id="publish-version" data-id="{{ draft.id }}" data-revision="{{ draft.revision }}">Опубликовать новую версию</button></div>
{% for v in versions %}<section class="form-panel"><h2>Версия {{ v.version }} · {{ 'Доступна' if v.active else 'Снята с публикации' }}</h2>{% for k in v.kinds %}<div class="version-links"><strong>{{ kinds[k] }}</strong><a href="/html/{{ draft.slug }}/v/{{ v.version }}/{{ k }}" target="_blank">HTML · BeautifulSoup ↗</a><a href="/interactive/{{ draft.slug }}/v/{{ v.version }}/{{ k }}" target="_blank">Дозагрузка · Playwright ↗</a></div>{% endfor %}{% if v.active %}<button class="secondary" data-unpublish="{{ v.version }}" data-id="{{ draft.id }}">Снять эту версию с публикации</button>{% endif %}</section>{% else %}<p class="empty">Опубликованных версий пока нет.</p>{% endfor %}
{% endif %}</main></body></html>