From dba48e90b73f2481b68b5f9a9ae0588c12a2b73d Mon Sep 17 00:00:00 2001 From: Ian Keane Date: Thu, 11 Jun 2026 17:28:14 -0400 Subject: [PATCH] Add term column --- app.js | 23 ++++++++++++++++++++++- index.html | 9 +++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/app.js b/app.js index df4dc48..5e15bb7 100644 --- a/app.js +++ b/app.js @@ -10,6 +10,7 @@ let allMusicians = []; let allInstruments = []; let allTunings = []; let allReferenceSites = []; +let allTerms = []; let sortCol = 'name'; let sortDir = 'asc'; @@ -43,6 +44,7 @@ const sourceDatalist = $('source-list'); const musicianDatalist = $('musician-list'); const instrumentSelect = $('instrument-select'); const tuningDatalist = $('tuning-list'); +const termDatalist = $('term-list'); const btnDeleteTune = $('btn-delete-tune'); const btnEditNotes = $('btn-edit-notes'); const btnBulkEdit = $('btn-bulk-edit'); @@ -116,18 +118,20 @@ function setStatus(msg, isError = false) { async function loadAll() { setStatus('Loading…'); try { - [allTunes, allSources, allMusicians, allInstruments, allTunings, allReferenceSites] = await Promise.all([ + [allTunes, allSources, allMusicians, allInstruments, allTunings, allReferenceSites, allTerms] = await Promise.all([ apiFetch('/tunes/'), apiFetch('/sources/'), apiFetch('/musicians/'), apiFetch('/instruments'), apiFetch('/tunings/'), apiFetch('/reference_sites/'), + apiFetch('/terms/'), ]); populateFilterOptions(); populateDatalist(sourceDatalist, allSources); populateDatalist(musicianDatalist, allMusicians); populateDatalist(tuningDatalist, allTunings); + populateDatalist(termDatalist, allTerms); populateDatalist(refSiteDatalist, allReferenceSites); populateInstrumentSelect(); renderTable(); @@ -204,6 +208,12 @@ $('btn-quick-add-tuning').addEventListener('click', async () => { }); }); +$('btn-quick-add-term').addEventListener('click', async () => { + await quickAdd('/terms/', 'New term name:', allTerms, termDatalist, item => { + tuneForm.elements.inst_term.value = item.name; + }); +}); + $('btn-quick-add-instrument').addEventListener('click', async () => { const item = await quickAdd('/instruments', 'New instrument name:', allInstruments, null); if (item) { @@ -231,6 +241,11 @@ function resolveTuningId(name) { return allTunings.find(x => x.name.toLowerCase() === name.toLowerCase())?.id ?? null; } +function resolveTermId(name) { + if (!name) return null; + return allTerms.find(x => x.name.toLowerCase() === name.toLowerCase())?.id ?? null; +} + // ── Rows: one per instrument entry ──────────────────────────── // For tunes with no instrument entries, emit one row with empty instrument cols function buildRows(tunes) { @@ -550,6 +565,7 @@ async function openEdit(tuneId, entryId) { populateInstrumentSelect(entry?.instrument_id ?? null); if (entry) { tuneForm.elements.inst_tuning.value = entry.tuning ?? ''; + tuneForm.elements.inst_term.value = entry.term ?? ''; tuneForm.elements.inst_learned_from.value = entry.learned_from ?? ''; tuneForm.elements.inst_date_learned.value = entry.date_learned ?? ''; tuneForm.elements.inst_status.value = entry.status ?? ''; @@ -708,6 +724,7 @@ async function saveTune() { const instBody = instId ? { instrument_id: instId, tuning_id: resolveTuningId(f.inst_tuning.value), + term_id: resolveTermId(f.inst_term.value), learned_from_id: resolveMusicianId(f.inst_learned_from.value), date_learned: f.inst_date_learned.value || null, status: f.inst_status.value || null, @@ -1432,6 +1449,7 @@ async function importCSVRows(rows) { const tunCache = new Map(); // name.lower → id (tunings) const musCache = new Map(); // name.lower → id (musicians) const instCache = new Map(); // name.lower → id (instruments) + const termCache = new Map(); // name.lower → id (terms) const tuneCache = new Map(); // name.lower → id (tunes created this run) const results = { created: 0, skipped: 0, errors: [] }; @@ -1455,6 +1473,7 @@ async function importCSVRows(rows) { const tuningId = await resolveOrCreate('/tunings/', allTunings, tunCache, row.tuning?.trim() || null); const learnedFromId = await resolveOrCreate('/musicians/', allMusicians, musCache, row.learned_from?.trim() || null); const instId = await resolveOrCreate('/instruments', allInstruments, instCache, row.instrument?.trim() || null); + const termId = await resolveOrCreate('/terms/', allTerms, termCache, row.term?.trim() || null); // Find existing tune or create new const lower = tuneName.toLowerCase(); @@ -1481,6 +1500,7 @@ async function importCSVRows(rows) { body: JSON.stringify({ instrument_id: instId, tuning_id: tuningId, + term_id: termId, learned_from_id: learnedFromId, date_learned: row.date_learned?.trim() || null, status, @@ -1537,6 +1557,7 @@ function attachTabAutocomplete(input, datalist) { attachTabAutocomplete(sourceInput, sourceDatalist); attachTabAutocomplete(tuneForm.elements.inst_tuning, tuningDatalist); +attachTabAutocomplete(tuneForm.elements.inst_term, termDatalist); attachTabAutocomplete(tuneForm.elements.inst_learned_from, musicianDatalist); // ── Boot ───────────────────────────────────────────────────── diff --git a/index.html b/index.html index 064659d..ebbd75d 100644 --- a/index.html +++ b/index.html @@ -121,6 +121,14 @@ +