feat(materials): Фаза 5 — заметка в флешкарты
Кнопка «В флешкарты» на карточке-заметке: выбор колоды (или новая «Из материалов») → создание карточки (front=заголовок, back=текст) через существующий API флешкард. Хелперы fcListDecks/fcCreateDeck/fcAddCard в js/api.js. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -108,6 +108,8 @@
|
||||
const edit = `<button class="mm-btn" onclick="editMaterial(${m.id})" title="Изменить"><i data-lucide="pencil"></i></button>`;
|
||||
const ann = (m.kind === 'board' || m.kind === 'image')
|
||||
? `<button class="mm-btn" onclick="annotate(${m.id})" title="Аннотировать (рисовать поверх)"><i data-lucide="pencil-ruler"></i></button>` : '';
|
||||
const fc = (m.kind === 'note')
|
||||
? `<button class="mm-btn" onclick="toFlashcard(${m.id})" title="В флешкарты"><i data-lucide="copy"></i></button>` : '';
|
||||
const mv = moveSelect(m);
|
||||
if (m.kind === 'board' || m.kind === 'image') {
|
||||
return `<div class="mm-card">
|
||||
@@ -132,7 +134,7 @@
|
||||
<div class="mm-card-body">
|
||||
<div class="mm-card-title">${esc(m.title || kind)}</div>
|
||||
<div class="mm-card-meta">${meta}</div>
|
||||
<div class="mm-card-actions">${mv}${edit}${del}</div>
|
||||
<div class="mm-card-actions">${mv}${fc}${edit}${del}</div>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
@@ -351,6 +353,38 @@
|
||||
}
|
||||
window.annotate = annotate;
|
||||
|
||||
/* ── Заметка → флешкарта ── */
|
||||
async function toFlashcard(id) {
|
||||
const mt = _mats.find(x => x.id === id);
|
||||
if (!mt) return;
|
||||
let decks = [];
|
||||
try { const d = await LS.fcListDecks(); decks = d.decks || []; } catch (e) {}
|
||||
const opts = ['<option value="__new">+ Новая колода «Из материалов»</option>']
|
||||
.concat(decks.map(d => `<option value="${d.id}">${esc(d.title)}</option>`)).join('');
|
||||
const front = (mt.title || '').trim() || (mt.body || '').slice(0, 80);
|
||||
const back = (mt.body || '').trim() || (mt.title || '');
|
||||
const content = `<div style="display:flex;flex-direction:column;gap:8px">
|
||||
<label style="font-size:.8rem;color:var(--text-3)">Колода</label>
|
||||
<select id="fc-deck" style="${FLD}">${opts}</select>
|
||||
<label style="font-size:.8rem;color:var(--text-3)">Вопрос (лицевая сторона)</label>
|
||||
<input id="fc-front" value="${esc(front)}" style="${FLD}" />
|
||||
<label style="font-size:.8rem;color:var(--text-3)">Ответ (оборот)</label>
|
||||
<textarea id="fc-back" rows="4" style="${FLD};resize:vertical">${esc(back)}</textarea>
|
||||
</div>`;
|
||||
const m = LS.modal({ title: 'В флешкарты', content, size: 'sm', actions: [
|
||||
{ label: 'Отмена', onClick: () => m.close() },
|
||||
{ label: 'Создать карточку', primary: true, onClick: async () => {
|
||||
try {
|
||||
let deckId = m.body.querySelector('#fc-deck').value;
|
||||
if (deckId === '__new') { const nd = await LS.fcCreateDeck({ title: 'Из материалов' }); deckId = nd.id; }
|
||||
await LS.fcAddCard(deckId, { front: m.body.querySelector('#fc-front').value, back: m.body.querySelector('#fc-back').value });
|
||||
m.close(); LS.toast('Карточка добавлена в флешкарты', 'success');
|
||||
} catch (e) { LS.toast(e.message || 'Ошибка', 'error'); }
|
||||
} },
|
||||
] });
|
||||
}
|
||||
window.toFlashcard = toFlashcard;
|
||||
|
||||
load();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -1050,6 +1050,7 @@ window.LS = {
|
||||
crAdminGetAllHistory, crAdminGetTeachersList,
|
||||
listMaterials, saveMaterial, updateMaterial, deleteMaterial,
|
||||
createMaterialCollection, updateMaterialCollection, deleteMaterialCollection,
|
||||
fcListDecks, fcCreateDeck, fcAddCard,
|
||||
escapeHtml, esc,
|
||||
parseDate, fmtRelTime, safeHref,
|
||||
initPage,
|
||||
@@ -1251,6 +1252,9 @@ async function deleteMaterial(id) { return req('DELETE', `/materials/${id}`)
|
||||
async function createMaterialCollection(d) { return req('POST', '/materials/collections', d); }
|
||||
async function updateMaterialCollection(id,d){ return req('PATCH', `/materials/collections/${id}`, d); }
|
||||
async function deleteMaterialCollection(id) { return req('DELETE', `/materials/collections/${id}`); }
|
||||
async function fcListDecks() { return req('GET', '/flashcards/decks'); }
|
||||
async function fcCreateDeck(d) { return req('POST', '/flashcards/decks', d); }
|
||||
async function fcAddCard(deckId, d) { return req('POST', `/flashcards/decks/${deckId}/cards`, d); }
|
||||
async function deleteFile(id) { return req('DELETE', `/files/${id}`); }
|
||||
async function getFileAccess(id) { return req('GET', `/files/${id}/access`); }
|
||||
async function assignFile(id, data) { return req('POST', `/files/${id}/assign`, data); }
|
||||
|
||||
Reference in New Issue
Block a user