Add notes to import csv

This commit is contained in:
Ian Keane 2026-06-12 09:57:24 -04:00
parent dba48e90b7
commit b426020a76
2 changed files with 46 additions and 7 deletions

51
app.js
View file

@ -1430,12 +1430,30 @@ function parseCSVLine(line) {
}
function parseCSV(text) {
const lines = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n').split('\n').filter(l => l.trim());
if (lines.length < 2) return [];
const headers = parseCSVLine(lines[0]).map(h => h.trim().toLowerCase().replace(/\s+/g, '_'));
return lines.slice(1)
.map(line => {
const vals = parseCSVLine(line);
text = text.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
// Split into rows respecting quoted multiline fields
const rows = [];
let cur = '', inQ = false;
for (let i = 0; i < text.length; i++) {
const ch = text[i];
if (ch === '"') {
if (inQ && text[i + 1] === '"') { cur += '""'; i++; }
else { inQ = !inQ; cur += ch; }
} else if (ch === '\n' && !inQ) {
rows.push(cur); cur = '';
} else {
cur += ch;
}
}
if (cur.trim()) rows.push(cur);
if (rows.length < 2) return [];
const headers = parseCSVLine(rows[0]).map(h => h.trim().toLowerCase().replace(/\s+/g, '_'));
return rows.slice(1)
.filter(r => r.trim())
.map(r => {
const vals = parseCSVLine(r);
const row = {};
headers.forEach((h, i) => { row[h] = (vals[i] ?? '').trim(); });
return row;
@ -1491,11 +1509,13 @@ async function importCSVRows(rows) {
}
// Add instrument entry (ignore 409 = already exists for that instrument)
// Capture the returned entry so we can attach an instrument note
let entryId = null;
if (instId) {
const status = ['callable', 'review', 'to_learn'].includes(row.status?.trim()) ? row.status.trim() : null;
const difficulty = ['easy', 'hard'].includes(row.difficulty?.trim()?.toLowerCase()) ? row.difficulty.trim().toLowerCase() : null;
try {
await apiFetch(`/tunes/${tuneId}/instruments`, {
const entry = await apiFetch(`/tunes/${tuneId}/instruments`, {
method: 'POST',
body: JSON.stringify({
instrument_id: instId,
@ -1507,11 +1527,28 @@ async function importCSVRows(rows) {
difficulty,
}),
});
entryId = entry.id;
} catch (e) {
if (!e.message.startsWith('409')) throw e;
}
}
// Tune-level note
const tuneNote = row.tune_note?.trim();
if (tuneNote) {
await apiFetch(`/tunes/${tuneId}/notes`, {
method: 'POST', body: JSON.stringify({ note: tuneNote }),
});
}
// Instrument-level note (only if we just created the entry)
const instNote = row.instrument_note?.trim();
if (instNote && entryId) {
await apiFetch(`/tunes/${tuneId}/instruments/${entryId}/notes`, {
method: 'POST', body: JSON.stringify({ note: instNote }),
});
}
results.created++;
} catch (e) {
results.errors.push({ name: tuneName, error: e.message });