Starts on suggest page
This commit is contained in:
parent
1d9ad9d3db
commit
3e3d318134
66
app.py
66
app.py
@ -1,5 +1,7 @@
|
|||||||
import flask
|
import flask
|
||||||
import sqlite3
|
import sqlite3
|
||||||
|
import csv
|
||||||
|
import datetime
|
||||||
|
|
||||||
app = flask.Flask('songbook')
|
app = flask.Flask('songbook')
|
||||||
|
|
||||||
@ -8,7 +10,7 @@ app = flask.Flask('songbook')
|
|||||||
# @app.route('/')
|
# @app.route('/')
|
||||||
# def page():
|
# def page():
|
||||||
|
|
||||||
# db = sqlite3.connect("file:songbook.sqlite?mode=ro", uri=True)
|
# db = openbook()
|
||||||
|
|
||||||
# return flask.render_template('.html',
|
# return flask.render_template('.html',
|
||||||
# )
|
# )
|
||||||
@ -77,6 +79,46 @@ def searchpage():
|
|||||||
searchresult=searchresult
|
searchresult=searchresult
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@app.route('/suggestsearch')
|
||||||
|
def suggestsearchpage():
|
||||||
|
|
||||||
|
db = openbook()
|
||||||
|
|
||||||
|
searchargs = flask.request.args['q']
|
||||||
|
|
||||||
|
if searchargs:
|
||||||
|
searchresult = db.execute('''
|
||||||
|
select
|
||||||
|
'song', id, name, instr(lower(name),lower(?))
|
||||||
|
from
|
||||||
|
song
|
||||||
|
where
|
||||||
|
name
|
||||||
|
like
|
||||||
|
'%' || ? || '%'
|
||||||
|
union all
|
||||||
|
select
|
||||||
|
'motif', id, name, instr(lower(name),lower(?))
|
||||||
|
from
|
||||||
|
motif
|
||||||
|
where
|
||||||
|
name
|
||||||
|
like
|
||||||
|
'%' || ? || '%'
|
||||||
|
order by
|
||||||
|
4
|
||||||
|
limit
|
||||||
|
10
|
||||||
|
''',
|
||||||
|
(searchargs,)*4
|
||||||
|
).fetchall()
|
||||||
|
|
||||||
|
else:
|
||||||
|
searchresult = []
|
||||||
|
|
||||||
|
return flask.render_template('suggestsearchresults.html',
|
||||||
|
searchresult=searchresult
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -364,4 +406,24 @@ def songpage(id):
|
|||||||
album_info=album_info,
|
album_info=album_info,
|
||||||
clip_info=clip_info,
|
clip_info=clip_info,
|
||||||
artist_info=artist_info
|
artist_info=artist_info
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@app.route('/suggest')
|
||||||
|
def suggestpage():
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return flask.render_template('suggest.html',
|
||||||
|
)
|
||||||
|
|
||||||
|
@app.route('/sent', methods=['POST'])
|
||||||
|
def sentpage():
|
||||||
|
|
||||||
|
with open ('suggestions.csv', 'a', newline='') as suggestlog:
|
||||||
|
logwriter = csv.writer(suggestlog)
|
||||||
|
logwriter.writerow([
|
||||||
|
datetime.datetime.now().isoformat(),
|
||||||
|
flask.request.form['suggest-description'],
|
||||||
|
])
|
||||||
|
return flask.render_template('sent.html',
|
||||||
|
)
|
||||||
|
|||||||
@ -1,13 +1,16 @@
|
|||||||
|
// Check for hash on load.
|
||||||
|
|
||||||
window.addEventListener('load', (event) => {
|
window.addEventListener('load', (event) => {
|
||||||
const preclicked = window.location.hash.slice(1);
|
const preclicked = window.location.hash.slice(1);
|
||||||
if (! preclicked) return;
|
if (! preclicked) return;
|
||||||
const albumheader = document.getElementById(preclicked);
|
const albumheader = document.getElementById(preclicked);
|
||||||
if (albumheader){
|
if (albumheader){
|
||||||
albumheader.classList.add('open');
|
albumheader.classList.add('open');
|
||||||
albumheader.scrollIntoView();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Scroll to search result album
|
||||||
|
|
||||||
function albumselect(code){
|
function albumselect(code){
|
||||||
const albumheader = document.getElementById(code);
|
const albumheader = document.getElementById(code);
|
||||||
for (const other of document.querySelectorAll('.sort-header.album.open')){
|
for (const other of document.querySelectorAll('.sort-header.album.open')){
|
||||||
@ -18,9 +21,10 @@ function albumselect(code){
|
|||||||
document.getElementById('search-results').replaceChildren();
|
document.getElementById('search-results').replaceChildren();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Toggle header when clicked
|
||||||
|
|
||||||
function albumHeaderClick(clickevent){
|
function albumHeaderClick(clickevent){
|
||||||
const albumheader = clickevent.target;
|
const albumheader = clickevent.target;
|
||||||
// console.log(albumheader);
|
|
||||||
if (albumheader.classList.contains('open')){
|
if (albumheader.classList.contains('open')){
|
||||||
albumheader.classList.remove('open');
|
albumheader.classList.remove('open');
|
||||||
history.replaceState(null, document.title, `${window.location.origin}${window.location.pathname}${window.location.search}`);
|
history.replaceState(null, document.title, `${window.location.origin}${window.location.pathname}${window.location.search}`);
|
||||||
@ -32,4 +36,29 @@ function albumHeaderClick(clickevent){
|
|||||||
albumheader.classList.add('open');
|
albumheader.classList.add('open');
|
||||||
window.location.hash = albumheader.id;
|
window.location.hash = albumheader.id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fill out form with suggest search result
|
||||||
|
function suggestform1(id, desc){
|
||||||
|
document.getElementById('connection-1').valueAsNumber = id;
|
||||||
|
document.getElementById('connection-1-desc').valueAsNumber = desc;
|
||||||
|
document.getElementById('search-input-suggest-1').value = '';
|
||||||
|
document.getElementById('search-results-1').replaceChildren();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mutually exclusive audio playback
|
||||||
|
function onlyPlayOneIn(container) {
|
||||||
|
container.addEventListener("play", function(event) {
|
||||||
|
audio_elements = container.getElementsByTagName("audio")
|
||||||
|
for(i=0; i < audio_elements.length; i++) {
|
||||||
|
audio_element = audio_elements[i];
|
||||||
|
if (audio_element !== event.target) {
|
||||||
|
audio_element.pause();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
onlyPlayOneIn(document.body);
|
||||||
|
});
|
||||||
@ -226,16 +226,17 @@ header{
|
|||||||
|
|
||||||
/* SEARCH RESULTS */
|
/* SEARCH RESULTS */
|
||||||
|
|
||||||
#search-results{
|
.search-results{
|
||||||
display: flex; flex-direction: column;
|
display: flex; flex-direction: column;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-results h2{
|
.search-results h2{
|
||||||
visibility: collapse;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-results ul{
|
.search-results ul{
|
||||||
background-color: var(--search-back);
|
background-color: var(--search-back);
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
@ -244,13 +245,13 @@ header{
|
|||||||
border-style: solid; border-color: var(--thin-border); border-width: 1px; border-top: 0; border-bottom: 0;
|
border-style: solid; border-color: var(--thin-border); border-width: 1px; border-top: 0; border-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-results li{
|
.search-results li{
|
||||||
display: flex; align-items: center;
|
display: flex; align-items: center;
|
||||||
min-height: 2.4rem;
|
min-height: 2.4rem;
|
||||||
border-style: solid; border-width: 1px; border-color: var(--thin-border); border-left: 0; border-top: 0; border-right: 0;
|
border-style: solid; border-width: 1px; border-color: var(--thin-border); border-left: 0; border-top: 0; border-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#search-results a{
|
.search-results a{
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,6 +278,10 @@ header{
|
|||||||
min-width: 2.6rem;
|
min-width: 2.6rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.search-bar::-webkit-search-cancel-button{
|
||||||
|
color: var(--text)
|
||||||
|
}
|
||||||
|
|
||||||
/* MAIN PAGE */
|
/* MAIN PAGE */
|
||||||
|
|
||||||
main{
|
main{
|
||||||
@ -623,4 +628,40 @@ footer{
|
|||||||
|
|
||||||
.clip-pointer a{
|
.clip-pointer a{
|
||||||
flex-shrink: 1;
|
flex-shrink: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* SUGGEST PAGE */
|
||||||
|
|
||||||
|
.suggestbox{
|
||||||
|
display: flex; flex-wrap: wrap; justify-content: center; gap: 4.8rem;
|
||||||
|
margin-top: 2.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggestbox h2{
|
||||||
|
width: 100%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-items.suggest{
|
||||||
|
width: 20rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggest-desc{
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggest-desc textarea{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.suggest-button{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#connection-1{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#connection-1-desc{
|
||||||
|
display: none;
|
||||||
}
|
}
|
||||||
4
suggestions.csv
Normal file
4
suggestions.csv
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
2023-06-27T15:35:08.245616,Testing the form
|
||||||
|
2023-06-27T15:35:34.195039,testing again
|
||||||
|
2023-06-27T21:54:35.835288,"Hello from Moss and Nat's
|
||||||
|
"
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
src = "{{ url_for('static', filename='clip/') }}{{ '%04d' % song_id }}-{{ '%03d' % motif_id }}.flac" type="audio/flac">
|
src = "{{ url_for('static', filename='clip/') }}{{ '%04d' % song_id }}-{{ '%03d' % motif_id }}.flac" type="audio/flac">
|
||||||
</audio>
|
</audio>
|
||||||
<span class="clip-pointer">
|
<span class="clip-pointer">
|
||||||
|
|
||||||
<img src="{{ url_for('static', filename='motificon.png') }}" alt="Motif Icon" class="connection-icon"/>
|
<img src="{{ url_for('static', filename='motificon.png') }}" alt="Motif Icon" class="connection-icon"/>
|
||||||
<a href = "{{ url_for('motifpage', id=motif_id) }}"> {{ motif }} </a>
|
<a href = "{{ url_for('motifpage', id=motif_id) }}"> {{ motif }} </a>
|
||||||
</span>
|
</span>
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<div class="footer-content">
|
<div class="footer-content">
|
||||||
<span>
|
<span>
|
||||||
Suggest a new connection
|
<a href="{{ url_for('suggestpage') }}"> Suggest a new connection </a>
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
<a href="#" class="top-of-page">↑Top of page↑</a>
|
<a href="#" class="top-of-page">↑Top of page↑</a>
|
||||||
|
|||||||
11
templates/jinja quarantine.html
Normal file
11
templates/jinja quarantine.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<!-- {% macro icon(type) -%}
|
||||||
|
<img src="{{ url_for('static', filename='{0}icon.png'.format(type)) }}" alt='{{ type}} icon' class='connection-icon'>
|
||||||
|
{%- endmacro %}
|
||||||
|
|
||||||
|
{% macro link(type) -%}
|
||||||
|
{{ url_for('{0}page'.format(type), id=) }}"> {{ motif }}
|
||||||
|
{%- endmacro %}
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- {{ icon(type) }}
|
||||||
|
{{ link(type) }} -->
|
||||||
@ -32,8 +32,8 @@
|
|||||||
placeholder="Search..."
|
placeholder="Search..."
|
||||||
hx-get="/search"
|
hx-get="/search"
|
||||||
hx-trigger="keyup changed delay:500ms, search"
|
hx-trigger="keyup changed delay:500ms, search"
|
||||||
hx-target="#search-results"
|
hx-target="#search-results-header"
|
||||||
/>
|
/>
|
||||||
<div id="search-results"></div>
|
<div id="search-results-header" class="search-results header"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
10
templates/sent.html
Normal file
10
templates/sent.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Suggestion sent{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
<!-- Artist info -->
|
<!-- Artist info -->
|
||||||
|
|
||||||
<div class="track-info">
|
<div class="track-info" >
|
||||||
<div class="songpage-detail">
|
<div class="songpage-detail">
|
||||||
<h2 >Artist: </h2>
|
<h2 >Artist: </h2>
|
||||||
<ul>
|
<ul>
|
||||||
@ -75,7 +75,8 @@
|
|||||||
<h2>Motifs Featured: </h2>
|
<h2>Motifs Featured: </h2>
|
||||||
<ul>
|
<ul>
|
||||||
{% for song_id, motif_id, motif in clip_info %}
|
{% for song_id, motif_id, motif in clip_info %}
|
||||||
{% include "songpageclipget.html" %}
|
{% set type = 'motif' %}
|
||||||
|
{% include "clipget.html" %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
41
templates/suggest.html
Normal file
41
templates/suggest.html
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{% extends "base.html" %}
|
||||||
|
|
||||||
|
{% block title %}Suggest a connection{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
|
||||||
|
<p>If you know about a shared motif that you can't find on the website, you can tell me about it here. Just pick the two songs that share a motif - or the motif itself, if it already has a page - and tell me what to listen out for.</p>
|
||||||
|
|
||||||
|
<form action="/sent" method="post" >
|
||||||
|
<div class="suggestbox">
|
||||||
|
<div class="search-items suggest">
|
||||||
|
<h2>Song / Motif 1</h2>
|
||||||
|
<input
|
||||||
|
id="search-input-suggest-1"
|
||||||
|
type="search"
|
||||||
|
name="q"
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder="Search..."
|
||||||
|
hx-get="/suggestsearch"
|
||||||
|
hx-trigger="keyup changed delay:500ms, search"
|
||||||
|
hx-target="#search-results-1"
|
||||||
|
/>
|
||||||
|
<div id="search-results-1" class="search-results"></div>
|
||||||
|
</div>
|
||||||
|
<input type="number" name="connection-1-desc" id="connection-1-desc"/>
|
||||||
|
<input type="number" name="connection-1" id="connection-1" min="1" max="733"/>
|
||||||
|
|
||||||
|
<div class="suggest-desc">
|
||||||
|
<textarea name="suggest-description">
|
||||||
|
Suggest a different connection!
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
<div class="suggest-button">
|
||||||
|
<input type="submit" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
{% endblock %}
|
||||||
22
templates/suggestsearchresults.html
Normal file
22
templates/suggestsearchresults.html
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<h2>Search Results:</h2>
|
||||||
|
<ul>
|
||||||
|
{% for desc, id, name, _ in searchresult %}
|
||||||
|
{% if desc == 'song' %}
|
||||||
|
<li onclick="suggestform('{{ id }}', 1)">
|
||||||
|
<span class="search-icon">
|
||||||
|
<img src="{{ url_for('static', filename='songicon.png') }}" alt="Song Icon"/>
|
||||||
|
</span>
|
||||||
|
<span class="search-type">Song:</span>
|
||||||
|
{{ name }}
|
||||||
|
</li>
|
||||||
|
{% elif desc == 'motif' %}
|
||||||
|
<li onclick="suggestform('{{ id }}', 2)">
|
||||||
|
<span class="search-icon">
|
||||||
|
<img src="{{ url_for('static', filename='motificon.png') }}" alt="Motif Icon"/>
|
||||||
|
</span>
|
||||||
|
<span class="search-type">Motif:</span>
|
||||||
|
{{ name }}
|
||||||
|
</li></a>
|
||||||
|
{% endif %}
|
||||||
|
{% endfor %}
|
||||||
|
</ul>
|
||||||
Loading…
Reference in New Issue
Block a user