add photo placeholder, mirrored camera capture, configurable footer, and student .url zip export
This commit is contained in:
@@ -20,6 +20,7 @@
|
||||
</div>
|
||||
<div class="toast" id="toast"></div>
|
||||
<script src="admin.js"></script>
|
||||
<script src="vendor/jszip.min.js"></script>
|
||||
<script>
|
||||
// --- Groups ---
|
||||
const DAYS = ['Вс', 'Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб'];
|
||||
@@ -55,6 +56,7 @@ async function loadGroups() {
|
||||
<div style="display:flex;gap:8px">
|
||||
<button class="save-sched" onclick="saveGroup(${g.id})">Сохранить</button>
|
||||
<button class="btn-link" onclick="exportGroup(${g.id}, '${esc(g.name).replace(/'/g, ''')}')" title="Экспортировать записи группы">CSV</button>
|
||||
<button class="btn-link" onclick="exportGroupUrls(${g.id}, '${esc(g.name).replace(/'/g, ''')}')" title="Скачать .url файлы учеников группы">URL</button>
|
||||
</div>
|
||||
<div class="sched-status">${schedSet ? `${DAYS[g.day_of_week]} ${g.time_start.slice(0,5)}–${g.time_end.slice(0,5)}` : 'Не настроено'}</div>
|
||||
</div>
|
||||
@@ -121,6 +123,15 @@ async function exportGroup(id, name) {
|
||||
showToast(`Экспортировано записей: ${entries.length}`);
|
||||
}
|
||||
|
||||
async function exportGroupUrls(groupId, groupName) {
|
||||
const res = await fetch(`${API}/api/students`, { headers: hdr() });
|
||||
const students = await res.json();
|
||||
const list = students.filter(s => s.group_id === groupId);
|
||||
if (!list.length) { alert('В группе нет учеников'); return; }
|
||||
await exportStudentUrlZip(list, `group_${groupName.replace(/[\\/:*?"<>|]/g, '_')}.zip`);
|
||||
showToast(`Экспортировано: ${list.length}`);
|
||||
}
|
||||
|
||||
document.getElementById('newGroup').addEventListener('keydown', e => { if (e.key === 'Enter') addGroup(); });
|
||||
|
||||
(async () => {
|
||||
|
||||
Reference in New Issue
Block a user