songs2slides

A tool that automatically finds song lyrics and creates lyric slideshows
git clone https://git.ashermorgan.net/songs2slides/
Log | Files | Refs | README

commit 5b721aa15e1d9455822128df7335696b66d5928e
parent 1020e70e356e4dfe9ca7ce77a30f5cd3cf60471e
Author: AsherMorgan <59518073+AsherMorgan@users.noreply.github.com>
Date:   Sat, 25 Apr 2020 08:38:35 -0700

Merge pull request #2 from AsherMorgan/feature-review

Implement review lyrics feature in the web interface.
Diffstat:
MSongs2Slides/routes.py | 41++++++++++++++++++++++++++++++-----------
MSongs2Slides/static/index.css | 22++++++++++++++++++++++
MSongs2Slides/static/index.js | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
MSongs2Slides/templates/index.html | 41+++++++++++++++++++++++------------------
4 files changed, 148 insertions(+), 37 deletions(-)

diff --git a/Songs2Slides/routes.py b/Songs2Slides/routes.py @@ -1,5 +1,5 @@ # Import dependencies -from flask import render_template, request, send_file, url_for +from flask import render_template, request, send_file, url_for, jsonify import io import json import os @@ -15,19 +15,21 @@ def index(): -# Powerpoint download +# Get Powerpoint @app.route("/pptx", methods=["POST"]) def pptx(): # Parse POST parameters - data = json.loads(request.form["data"]) - - # Get lyrics - lyrics = [] - for song in data: - try: - lyrics += models.ParseLyrics(song[0], song[1]) - except: - pass + if "songs" in request.json: + # Get lyrics + lyrics = [] + for song in request.json["songs"]: + try: + lyrics += models.ParseLyrics(song[0], song[1]) + except: + pass + elif "lyrics" in request.json: + # Get lyrics + lyrics = request.json["lyrics"] try: # Create powerpoint @@ -44,3 +46,19 @@ def pptx(): # Return powerpoint return send_file(pptx, as_attachment=True, attachment_filename='download.pptx') + + + +# Get lyrics +@app.route("/lyrics", methods=["POST"]) +def lyrics(): + # Get lyrics + lyrics = [] + for song in request.json["songs"]: + try: + lyrics += models.ParseLyrics(song[0], song[1]) + except: + pass + + # Return lyrics + return jsonify({"lyrics": lyrics}) +\ No newline at end of file diff --git a/Songs2Slides/static/index.css b/Songs2Slides/static/index.css @@ -1,9 +1,13 @@ +/******** Body styles ********/ body { text-align: center; font-family: Arial, Helvetica, sans-serif; touch-action: manipulation; } + + +/******** Element styles ********/ button { height: 25px; } @@ -13,6 +17,24 @@ button { font-weight: bold; } + + +/******** Songs styles ********/ .songRemove { cursor: pointer; +} + + + +/******** Lyrics styles ********/ +#lyricsContainer { + width: 100%; + max-width: 500px; + margin: auto; + text-align: left; +} + +#lyrics { + width: 100%; + resize: none; } \ No newline at end of file diff --git a/Songs2Slides/static/index.js b/Songs2Slides/static/index.js @@ -4,7 +4,7 @@ setId = 0; // Next valid song id number // Adds a song -function Add() { +function AddSong() { // Create row var clone = document.getElementById("songTemplate").content.cloneNode(true); @@ -23,8 +23,8 @@ function Add() { -// Prepares form data for a POST request -function PrepareForm() { +// Gets the list of songs +function getSongs() { // Get song info var titles = []; for (title of document.getElementsByClassName("title")) { @@ -35,12 +35,77 @@ function PrepareForm() { artists.push(artist.value); } - // Prepare data - data = [] + // Prepare songs + songs = [] for (var i = 0; i < titles.length; i++) { - data.push([titles[i], artists[i]]) + songs.push([titles[i], artists[i]]) } - // Set data - document.getElementsByName("data")[0].value = JSON.stringify(data) + // Set songs + return songs +} + + + +// Gets the powerpoint by submitting songs +async function SubmitSongs() { + // Get songs + songs = getSongs(); + + // Send POST request + const rawResponse = await fetch("/pptx", { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, body: JSON.stringify({"songs":songs}) + }); + + // Download powerpoint + download(await rawResponse.blob()); +} + + + +// Get the parsed lyrics for the user to review +async function ReviewLyrics() { + // Get songs + songs = getSongs(); + + // Send POST request + const rawResponse = await fetch("/lyrics", { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, body: JSON.stringify({"songs":songs}) + }); + const json = await rawResponse.json(); + + // Set lyrics + document.getElementById("lyrics").value = json["lyrics"].join("\n\n") + + // Show and hide elements + document.getElementById("songs").hidden = true; + document.getElementById("lyricsContainer").hidden = false; +} + + + +// Gets the powerpoint by submitting lyrics +async function SubmitLyrics() { + // Get lyrics + lyrics = document.getElementById("lyrics").value.split('\n\n'); + + // Send POST request + const rawResponse = await fetch("/pptx", { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, body: JSON.stringify({"lyrics":lyrics}) + }); + + // Download powerpoint + download(await rawResponse.blob()); } \ No newline at end of file diff --git a/Songs2Slides/templates/index.html b/Songs2Slides/templates/index.html @@ -5,29 +5,34 @@ <meta name="viewport" content="width=device-width, user-scalable=no"/> <link rel="stylesheet" href="{{ url_for('static', filename='index.css') }}"></link> <script src="{{ url_for('static', filename='index.js') }}"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/downloadjs/1.4.8/download.min.js"></script> </head> - <body onload="Add();"> + <body onload="AddSong()"> <label id="title">Songs2Slides</label> <br/> <label>Create a lyrics powerpoints from a list of songs.</label> <br/><br/> - <form action="/pptx" method="POST" onsubmit="PrepareForm();"> - <input hidden name="data"> - <button type="button" onclick="Add();">Add song</button> - <button type="submit">Create Powerpoint</button> - </form> - - - <template id="songTemplate"> - <div> - <input type="text" class="title" placeholder="Song Title"> - <input type="text" class="artist" placeholder="Song Artist"> - <a id="remove" class="songRemove">╳</a> - </div> - </template> - - <br/> - <div id="songs"></div> + <div id="songs"> + <button onclick="AddSong();">Add song</button> + <button onclick="SubmitSongs();">Create Powerpoint</button> + <button onclick="ReviewLyrics();">Review Lyrics</button><br/><br/> + + <template id="songTemplate"> + <div> + <input type="text" class="title" placeholder="Song Title"/> + <input type="text" class="artist" placeholder="Song Artist"/> + <a id="remove" class="songRemove">╳</a> + </div> + </template> + </div> + + <div id="lyricsContainer" hidden> + Review and edit the parsed lyrics below and then click the create PowerPoint button. + One blank line signifies a new slide and three blank lines signifies a blank slide.<br/><br/> + + <textarea rows="10" id="lyrics">Loading lyrics...</textarea><br/> + <button onclick="SubmitLyrics();">Create Powerpoint</button> + </div> </body> </html> \ No newline at end of file