From b451043d51358aaa8843f7ed51fe2c9547fe332e Mon Sep 17 00:00:00 2001 From: Asher Morgan <59518073+ashermorgan@users.noreply.github.com> Date: Thu, 11 Jul 2024 15:24:38 -0700 Subject: [PATCH] Save custom song lyrics in localStorage --- songs2slides/static/create.css | 4 ++ songs2slides/static/create.js | 55 +++++++++++++++++++++-- songs2slides/templates/create-step-1.html | 2 +- songs2slides/templates/create-step-2.html | 27 +++++------ tests/test_e2e.py | 29 +++++++++--- 5 files changed, 89 insertions(+), 28 deletions(-) diff --git a/songs2slides/static/create.css b/songs2slides/static/create.css index 78880e7..1d8b1e5 100644 --- a/songs2slides/static/create.css +++ b/songs2slides/static/create.css @@ -75,7 +75,11 @@ textarea { .missing summary { color: var(--error); } +summary span { + display: none; +} .missing summary span { + display: inline; float: right; font-weight: bold; } diff --git a/songs2slides/static/create.js b/songs2slides/static/create.js index 6d3a3e1..fe5b135 100644 --- a/songs2slides/static/create.js +++ b/songs2slides/static/create.js @@ -1,11 +1,16 @@ // Global Songs2Slides localStorage prefix const PREFIX = 's2s' +// HTML form +let form = null + // Page load/reload handler addEventListener('pageshow', () => { // Correct page state after returning via browser back button document.getElementById('post-submit').hidden = true + form = document.getElementById('create-form') + if (STEP === 1) { // Load songs for (let row of document.querySelectorAll('tbody tr')) { @@ -18,9 +23,10 @@ addEventListener('pageshow', () => { raw_song.children[1].children[0].value = song.title raw_song.children[2].children[0].value = song.artist } + } else if (STEP === 2) { + load_lyrics() } else if (STEP === 3) { // Load settings - const form = document.getElementById('create-form') form['title-slides'].checked = storage_get('title-slides', true) form['blank-slides'].checked = storage_get('blank-slides', true) form['output-type'].value = storage_get('output-type', 'html') @@ -32,9 +38,10 @@ addEventListener('submit', () => { // Show loading spinner document.getElementById('post-submit').hidden = false - if (STEP === 3) { + if (STEP === 2) { + save_lyrics() + } else if (STEP === 3) { // Save settings - const form = document.getElementById('create-form') storage_set('title-slides', form['title-slides'].checked) storage_set('blank-slides', form['blank-slides'].checked) storage_set('output-type', form['output-type'].value) @@ -86,7 +93,47 @@ function save_songs() { storage_set('songs', songs) } -// Step 3 helper functions +// Step 2 functions +function get_song_key(title, artist) { + return 'lyrics-' + artist.toLowerCase().replaceAll(' ', '-') + + '-' + title.toLowerCase().replaceAll(' ', '-') +} + +function save_lyrics() { + for (let i = 1; `title-${i}` in form; i++) { + const title = form[`title-${i}`].value + const artist = form[`artist-${i}`].value + const lyrics = form[`lyrics-${i}`].value + const key = get_song_key(title, artist) + storage_set(key, lyrics) + } +} + +function load_lyrics() { + songs = document.getElementsByTagName('details') + for (let i = 1; `title-${i}` in form; i++) { + const title = form[`title-${i}`].value + const artist = form[`artist-${i}`].value + const key = get_song_key(title, artist) + const saved_lyrics = storage_get(key, '') + if (saved_lyrics !== '') { + form[`lyrics-${i}`].value = saved_lyrics + songs[i - 1].classList.remove('missing') + songs[i - 1].open = false + } + } + + // Update missing label + const number = document.getElementsByClassName('missing').length + document.getElementById('missing-count').textContent = number + if (number === 0) { + document.getElementById('missing-message').hidden = true + } else { + document.getElementById('missing-message').hidden = false + } +} + +// Local storage helper functions function storage_get(key, default_value) { try { value = JSON.parse(localStorage.getItem(`${PREFIX}.${key}`)) diff --git a/songs2slides/templates/create-step-1.html b/songs2slides/templates/create-step-1.html index e529284..58922aa 100644 --- a/songs2slides/templates/create-step-1.html +++ b/songs2slides/templates/create-step-1.html @@ -8,7 +8,7 @@ {% endblock head %} {% block main %} -
+

Step 1: Select Songs

diff --git a/songs2slides/templates/create-step-2.html b/songs2slides/templates/create-step-2.html index 82211ab..213ddc1 100644 --- a/songs2slides/templates/create-step-2.html +++ b/songs2slides/templates/create-step-2.html @@ -14,7 +14,7 @@ %} {% block main %} - +

Step 2: Review Lyrics

Review the parsed song lyrics below and make any necessary corrections. @@ -23,12 +23,10 @@

Step 2: Review Lyrics

{{ format_hint }}

- {% if missing > 0 %} -

- Lyrics must be entered manually for {{ missing }} - song{% if missing != 1 %}s{% endif %}. +

- {% endif %}
{% for song in songs %} @@ -48,19 +46,16 @@

Step 2: Review Lyrics

({{ song.artist }}) {% endif %} - {% if not song.lyrics %} - lyrics not found - {% endif %} + - {% if song.lyrics %} - - {% else %} - {% endif %} + 'Lyrics not found, please enter them here manually.\n\n' + if not songs.lyrics else '' }}{{ format_hint }}" + aria-label="{{ song.title }} Lyrics" + >{{ song.lyrics or '' }} {% endfor %}
diff --git a/tests/test_e2e.py b/tests/test_e2e.py index ac30b50..a0e489c 100644 --- a/tests/test_e2e.py +++ b/tests/test_e2e.py @@ -20,11 +20,12 @@ def test_basic(page: Page): expect(page).to_have_url('http://localhost:5002/create/step-2/') # Assert missing song message is correct - expect(page.get_by_text('Lyrics must be entered manually for 1 song.')).to_be_visible() + expect(page.get_by_text('Lyrics must be entered manually for 1 song(s).')).to_be_visible() # Assert songs are loaded expect(page.get_by_text('Song 1 (Artist A)')).to_be_visible() - expect(page.get_by_text('Song 1 (Artist A) lyrics not found')).to_be_hidden() + expect(page.get_by_text('lyrics not found').first).to_be_hidden() + expect(page.get_by_text('lyrics not found').last).to_be_visible() expect(page.get_by_text('Song 5 lyrics not found')).to_be_visible() # Assert song lyrics are loaded (Song 1 lyrics still collapsed) @@ -127,7 +128,9 @@ def test_localStorage(page: Page): page.get_by_role('button', name='Next').click() expect(page).to_have_url('http://localhost:5002/create/step-2/') - # Fill in missing lyrics + # Update lyrics + page.get_by_text('Song 1 (Artist A)').click() + page.get_by_role('textbox').first.fill('custom song 1 lyrics') page.get_by_role('textbox').last.fill('custom song 5 lyrics') # Click Next @@ -166,8 +169,18 @@ def test_localStorage(page: Page): page.get_by_role('button', name='Next').click() expect(page).to_have_url('http://localhost:5002/create/step-2/') - # Fill in missing lyrics - page.get_by_role('textbox').last.fill('custom song 5 lyrics') + # Assert song lyrics are collapsed and not missing + expect(page.get_by_role('textbox')).to_have_count(0) + expect(page.get_by_text('lyrics not found').first).to_be_hidden() + expect(page.get_by_text('lyrics not found').last).to_be_hidden() + + # Uncollapse songs + page.get_by_text('Song 1 (Artist A)').click() + page.get_by_text('Song 5').click() + + # Assert song lyrics are prefilled + expect(page.get_by_role('textbox').first).to_have_value('custom song 1 lyrics') + expect(page.get_by_role('textbox').last).to_have_value('custom song 5 lyrics') # Click Next page.get_by_role('button', name='Next').click() @@ -231,7 +244,8 @@ def test_back(page: Page): # Assert songs are loaded expect(page.get_by_text('Song 1 (Artist A)')).to_be_visible() - expect(page.get_by_text('Song 1 (Artist A) lyrics not found')).to_be_hidden() + expect(page.get_by_text('lyrics not found').first).to_be_hidden() + expect(page.get_by_text('lyrics not found').last).to_be_visible() expect(page.get_by_text('Song 5 lyrics not found')).to_be_visible() # Uncollapse Song 1 @@ -253,8 +267,9 @@ def test_back(page: Page): page.get_by_role('button', name='Back').click() expect(page).to_have_url('http://localhost:5002/create/step-2/') - # Uncollapse Song 1 + # Uncollapse songs page.get_by_text('Song 1 (Artist A)').click() + page.get_by_text('Song 5').click() # Assert bad song lyrics are still loaded expect(page.get_by_role('textbox')).to_have_count(2)