commit eeb8a38289cbcd27f7b799bc24bacdcf5f640dc7
parent 2dab6949d1d70c6fb159cb2c4bafe85bdb1dcb7b
Author: ashermorgan <59518073+ashermorgan@users.noreply.github.com>
Date: Wed, 28 Feb 2024 10:44:49 -0800
Implement online view feature
Diffstat:
6 files changed, 99 insertions(+), 6 deletions(-)
diff --git a/songs2slides/routes.py b/songs2slides/routes.py
@@ -71,8 +71,12 @@ def create_slides():
# Assemble slides
slides = core.assemble_slides(songs, lines_per_slide = None)
- # Create and send powerpoint
- with tempfile.NamedTemporaryFile(suffix='.pptx') as f:
- core.create_pptx(slides, f.name)
- return send_file(f.name, as_attachment=True,
- download_name='slides.pptx')
+ if (request.form.get('output-type') == 'pptx'):
+ # Create and send powerpoint
+ with tempfile.NamedTemporaryFile(suffix='.pptx') as f:
+ core.create_pptx(slides, f.name)
+ return send_file(f.name, as_attachment=True,
+ download_name='slides.pptx')
+ else:
+ # Render HTML slides
+ return render_template('slides.html', slides=slides)
diff --git a/songs2slides/static/create.css b/songs2slides/static/create.css
@@ -73,3 +73,11 @@ textarea {
float: right;
font-weight: bold;
}
+
+fieldset {
+ border: none;
+}
+fieldset label {
+ display: block;
+ margin-top: 0.5rem;
+}
diff --git a/songs2slides/static/create.js b/songs2slides/static/create.js
@@ -1,5 +1,8 @@
addEventListener("submit", () => {
- document.getElementById('after-submit').hidden = false
+ if (document.querySelector('input[value=html]:checked]') === null) {
+ // Don't show #after-submit for HTML slide creation
+ document.getElementById('after-submit').hidden = false
+ }
if (document.getElementById('step-2')) {
document.getElementById('step-2').hidden = true
}
diff --git a/songs2slides/templates/create-step-2.html b/songs2slides/templates/create-step-2.html
@@ -53,6 +53,18 @@
{% endfor %}
</div>
+ <fieldset>
+ <legend>Output type:</legend>
+ <label>
+ <input type="radio" name="output-type" value="pptx" checked/>
+ PowerPoint Download
+ </label>
+ <label>
+ <input type="radio" name="output-type" value="html"/>
+ Online View
+ </label>
+ </fieldset>
+
<div id="actions">
<a href="{{ url_for('.create') }}">Back</a>
<button>
diff --git a/songs2slides/templates/slides.html b/songs2slides/templates/slides.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>Online View - SongsSlides</title>
+
+ <link rel="stylesheet" href="https://unpkg.com/reveal.js@^4//dist/reveal.css">
+ <link rel="stylesheet" href="https://unpkg.com/reveal.js@^4//dist/theme/black.css">
+ <script src="https://unpkg.com/reveal.js@^4//dist/reveal.js"></script>
+ </head>
+
+ <body>
+ <div class="reveal">
+ <div class="slides">
+ {% for slide in slides %}
+ <section>
+ {% for line in slide.split('\n') %}
+ <p>{{ line }}</p>
+ {% endfor %}
+ </section>
+ {% endfor %}
+ </div>
+ </div>
+
+ <script>
+ Reveal.initialize({
+ controls: false,
+ help: false,
+ overview: false,
+ progress: false,
+ transition: 'none',
+ });
+ </script>
+ </body>
+</html>
diff --git a/tests/test_routes.py b/tests/test_routes.py
@@ -89,6 +89,7 @@ class TestRoutes(unittest.TestCase):
'title-2': 'T2',
'artist-2': 'A2',
'lyrics-2': 'L2',
+ 'output-type': 'pptx',
})
# Assert mocks called correctly
@@ -112,6 +113,7 @@ class TestRoutes(unittest.TestCase):
'lyrics-1': 'L1',
'title-2': 'T2',
'lyrics-2': 'L2',
+ 'output-type': 'pptx',
})
# Assert response has 400 status code
@@ -119,3 +121,33 @@ class TestRoutes(unittest.TestCase):
# Assert assemble_slides not called
mocked_assemble.assert_not_called()
+
+ def test_create_slides_html_slides(self):
+ with patch('songs2slides.core.assemble_slides') as mocked_assemble, \
+ patch('songs2slides.core.create_pptx') as mocked_create, \
+ patch('songs2slides.routes.render_template') as mocked_render:
+
+ # Mock assemble_slides
+ slides = ['T1', 'L1\nL2', 'L3', 'T2', 'L4']
+ mocked_assemble.return_value = slides
+
+ # Send request
+ self.client.post('/slides/', data={
+ 'title-1': 'T1',
+ 'artist-1': 'A1',
+ 'lyrics-1': 'L1',
+ 'title-2': 'T2',
+ 'artist-2': 'A2',
+ 'lyrics-2': 'L2',
+ 'output-type': 'html',
+ })
+
+ # Assert mocks called correctly
+ mocked_assemble.assert_called_with([
+ core.SongData('T1', 'A1', 'L1'),
+ core.SongData('T2', 'A2', 'L2'),
+ ],
+ lines_per_slide = None
+ )
+ mocked_create.assert_not_called()
+ mocked_render.assert_called_with('slides.html', slides=slides)