tightening frontend
Some checks failed
test and deploy / Build & Unit Test (push) Failing after 1m21s
test and deploy / Package & Push Container (push) Has been skipped

This commit is contained in:
Andy Pack 2024-10-10 23:45:22 +01:00
parent 38c2e5e430
commit 03e9743abb
Signed by: sarsoo
GPG Key ID: A55BA3536A5E0ED7
8 changed files with 173 additions and 225 deletions

View File

@ -60,7 +60,7 @@ def login():
logger.info(f'success {username}') logger.info(f'success {username}')
session['username'] = username session['username'] = username
return redirect(url_for('app_route')) return redirect(url_for('app_route_redirect'))
else: else:
logger.warning(f'failed attempt {username}') logger.warning(f'failed attempt {username}')
flash('incorrect password') flash('incorrect password')

View File

@ -38,7 +38,7 @@ def create_app():
if 'username' in session: if 'username' in session:
logged_in = True logged_in = True
return redirect(url_for('app_route')) return redirect('/app/playlists')
else: else:
logged_in = False logged_in = False
@ -48,7 +48,15 @@ def create_app():
def privacy(): def privacy():
return render_template('privacy.html', bucket=STATIC_BUCKET) return render_template('privacy.html', bucket=STATIC_BUCKET)
@app.route('/app', defaults={'path': ''}) @app.route('/app')
def app_route_redirect():
if 'username' not in session:
flash('please log in')
return redirect(url_for('index'))
return redirect('/app/playlists')
@app.route('/app/<path:path>') @app.route('/app/<path:path>')
def app_route(path): def app_route(path):

View File

@ -15,9 +15,6 @@
</head> </head>
<body> <body>
<div>
<h1 class="title">Mixonomer</h1>
</div>
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}
{% if messages %} {% if messages %}
@ -29,9 +26,8 @@
{% endif %} {% endif %}
{% endwith %} {% endwith %}
<br><br>
<div id="react"></div> <div id="react"></div>
<script src="{{ url_for('static', filename='js/app.bundle.js') }}"></script> <script src="{{ url_for('static', filename='js/app.bundle.js') }}"></script>
<div id="snackbar">toast</div> <div id="snackbar">toast</div>

View File

@ -18,8 +18,8 @@
</head> </head>
<body> <body>
<div> <div class="title">
<h1 class="title">Mixonomer</h1> <h1>Mixonomer</h1>
</div> </div>
<br><br> <br><br>
<ul class="navbar"> <ul class="navbar">

View File

@ -6,31 +6,30 @@
{% with messages = get_flashed_messages() %} {% with messages = get_flashed_messages() %}
{% if messages %} {% if messages %}
<div>
{% for message in messages %} {% for message in messages %}
<div class="row card pad-12"> <div class="card flash-message">
<p class="center-text" style="color: red">{{ message }}</p> <p class="center-text" style="color: red">{{ message }}</p>
</div> </div>
{% endfor %} {% endfor %}
</div>
{% endif %} {% endif %}
{% endwith %} {% endwith %}
<div class="row"> <div class="index-article">
<div class="{% if logged_in %}pad-12{% else %}pad-9{% endif %} card"> <div class="index-hero-grid">
<!-- <h1 class="center-text">Mixonomer</h1> --> <div class="card index-into-card">
<div>
<p class="center-text">A set of tools using Spotify and Last.fm to create smart playlists and calculate listening statistics</p> <p class="center-text">A set of tools using Spotify and Last.fm to create smart playlists and calculate listening statistics</p>
<p class="center-text">Playlists are updated multiple times a day to keep tracks up to date</p> <p class="center-text">Playlists are updated multiple times a day to keep tracks up to date</p>
<p class="center-text">Written in Python and Javascript, based on the <a href="https://github.com/Sarsoo/spotframework">spotframework</a> and <a href="https://github.com/Sarsoo/pyfmframework">fmframework</a> libraries</p> <p class="center-text">Written in Python and Javascript, based on the <a href="https://github.com/Sarsoo/spotframework">spotframework</a> and <a href="https://github.com/Sarsoo/pyfmframework">fmframework</a> libraries</p>
<div style="padding:10px">
<a class="button" style="padding:15px;width:49%" href="https://github.com/Sarsoo/Mixonomer">View Source</a>
<a class="button" style="padding:15px;width:49%" href="https://github.com/Sarsoo/Mixonomer-iOS">iOS Client Source</a>
</div> </div>
{% if logged_in %} <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 10px">
<a class="button full-width" href="/app">Launch</a> <a class="button" style="width: 100%" href="https://github.com/Sarsoo/Mixonomer">View Source</a>
{% endif %} <a class="button" style="width: 100%" href="https://github.com/Sarsoo/Mixonomer-iOS">iOS Client Source</a>
</div>
</div> </div>
{% if not logged_in %} {% if not logged_in %}
@ -39,11 +38,9 @@
{% endif %} {% endif %}
</div> </div>
<div class="row">
<h1>Smart Playlists</h1> <div class="index-feature-grid">
</div> <div class="card">
<div class="row center-text">
<div class="pad-6 card">
<h1 class="center-text">Sources</h1> <h1 class="center-text">Sources</h1>
<p>Create smart Spotify playlists pulling tracks from</p> <p>Create smart Spotify playlists pulling tracks from</p>
<ul style="text-align:left" > <ul style="text-align:left" >
@ -52,35 +49,29 @@
<li style="padding:10px">Mixonomer Playlists</li> <li style="padding:10px">Mixonomer Playlists</li>
</ul> </ul>
</div> </div>
<div class="pad-6 card"> <div class="card">
<h1 class="center-text">Currents</h1> <h1 class="center-text">Currents</h1>
<p>Currents are mix playlists acting as a snapshot of what's being listened to at the moment</p> <p>Currents are mix playlists acting as a snapshot of what's being listened to at the moment</p>
<p>Includes date filtering on playlist sources for recently added tracks</p> <p>Includes date filtering on playlist sources for recently added tracks</p>
<p>Optionally search for and include "monthly" playlists for the last two months when named e.g february 20</p> <p>Optionally search for and include "monthly" playlists for the last two months when named e.g february 20</p>
</div> </div>
</div> <div class="card">
<div class="row center-text">
<div class="pad-6 card">
<h1 class="center-text">Last.fm Charts</h1> <h1 class="center-text">Last.fm Charts</h1>
<p>Create playlists including Last.fm track charts of varying length and time range</p> <p>Create playlists including Last.fm track charts of varying length and time range</p>
</div> </div>
<div class="pad-6 card"> <div class="card">
<h1 class="center-text">Recommendations</h1> <h1 class="center-text">Recommendations</h1>
<p>Include Spotify recommendations based on the other tracks of the playlist</p> <p>Include Spotify recommendations based on the other tracks of the playlist</p>
</div> </div>
<div class="card">
</div>
<div class="row">
<h1>Tags</h1>
</div>
<div class="row center-text">
<div class="pad-6 card">
<h1 class="center-text">Last.fm Integration</h1> <h1 class="center-text">Last.fm Integration</h1>
<p>Create groups of entries for scrobble summing and listening stats</p> <p>Create groups of entries for scrobble summing and listening stats</p>
</div> </div>
<div class="pad-6 card"> <div class="card">
<h1 class="center-text">Visualise Data</h1> <h1 class="center-text">Visualise Data</h1>
<p>Present listening trends with pie charts</p> <p>Present listening trends with pie charts</p>
</div> </div>
</div> </div>
</div>
{% endblock %} {% endblock %}

View File

@ -2,15 +2,25 @@
{% block form %} {% block form %}
<div class="pad-3 card"> <div class="card">
<form name="login" action="/auth/login" method="POST" onsubmit="return handleLogin()"> <form name="login" action="/auth/login" method="POST" onsubmit="return handleLogin()" style="display: grid; gap: 30px;">
<p class="center-text">Username<br><input type="text" name="username" class="full-width"></p>
<p class="center-text">Password<br><input type="password" name="password" class="full-width"></p> <div>
<p>Username</p>
<input type="text" name="username" class="full-width" />
</div>
<div>
<p>Password</p>
<input type="password" name="password" class="full-width" />
</div>
<p id="status" style="display: none; color: red" class="center-text"></p> <p id="status" style="display: none; color: red" class="center-text"></p>
<div style="display: grid; gap: 15px;">
<button class="button full-width" onclick="handleLogin()" type="submit">Login</button> <button class="button full-width" onclick="handleLogin()" type="submit">Login</button>
<br><br>
<a href="/auth/register" class="button full-width">Register</a> <a href="/auth/register" class="button full-width">Register</a>
</div>
</form> </form>
<script src="{{ url_for('static', filename='js/login.bundle.js') }}"></script> <script src="{{ url_for('static', filename='js/login.bundle.js') }}"></script>

View File

@ -94,13 +94,17 @@ class MusicTools extends Component {
{/* TOP APP BAR */} {/* TOP APP BAR */}
<AppBar position="static"> <AppBar position="sticky">
<Toolbar> <Toolbar>
<IconButton edge="start" color="inherit" aria-label="menu" onClick={(e) => this.setOpen(true)}> <IconButton edge="start" color="inherit" aria-label="menu" onClick={(e) => this.setOpen(true)}>
<MenuIcon /> <MenuIcon />
</IconButton> </IconButton>
<Typography variant="h6"> <Typography variant="h6">
<Link to='/app/playlists' style={{textDecoration: 'none'}}>Mixes</Link> <Link to='/app/playlists' style={{textDecoration: 'none'}}>
<div className="title-small">
<h1 >Mixonomer</h1>
</div>
</Link>
</Typography> </Typography>
</Toolbar> </Toolbar>
</AppBar> </AppBar>
@ -125,12 +129,6 @@ class MusicTools extends Component {
onKeyDown={(e) => this.setOpen(false)} onKeyDown={(e) => this.setOpen(false)}
> >
<List> <List>
{/* HOME */}
<ListItem button key="home" component={Link} to='/app'>
<ListItemIcon><HomeIcon /></ListItemIcon>
<ListItemText primary="Home" />
</ListItem>
{/* PLAYLISTS */} {/* PLAYLISTS */}
<ListItem button key="playlists" component={Link} to='/app/playlists'> <ListItem button key="playlists" component={Link} to='/app/playlists'>
<ListItemIcon><QueueMusic /></ListItemIcon> <ListItemIcon><QueueMusic /></ListItemIcon>

View File

@ -19,6 +19,7 @@ html {
body { body {
background-color: $background-colour; background-color: $background-colour;
margin: 0px;
} }
a { a {
@ -31,7 +32,7 @@ a {
p { p {
color: $text-colour; color: $text-colour;
font-size: 20px; font-size: 20px;
padding: 10px; //padding: 10px;
} }
.ui-text { .ui-text {
@ -46,10 +47,6 @@ p {
width: 100%; width: 100%;
} }
.half-width {
width: 50%;
}
.button { .button {
background-color: $ui-element; background-color: $ui-element;
color: $text-colour; color: $text-colour;
@ -87,25 +84,52 @@ input[type=text], input[type=password], input[type=number], select {
color: white; color: white;
} }
.flash-message {
max-width: 400px;
margin-inline: auto;
margin-block: 40px;
}
.index-hero-grid {
display: grid;
gap: 20px;
margin-block: 30px;
}
.index-into-card {
display: flex;
flex-direction: column;
justify-content: space-between;
}
.index-feature-grid {
display: grid;
gap: 20px;
}
.index-article {
max-width: 1300px;
margin: 10px;
}
@media screen and (min-width: 50rem) {
.index-hero-grid {
grid-template-columns: 3fr 1fr;
}
.index-feature-grid {
grid-template-columns: repeat(3, 1fr);
}
.index-article {
margin-inline: auto;
}
}
.row { .row {
margin: 30px; margin: 30px;
} }
.gallerystrip{
width: 100%;
margin: auto;
margin-top: 15px;
img {
height: auto;
border: 10px solid #313439;
margin: calc($pad-px / 2);
box-shadow: 4px 4px 7px #070707;
}
}
.profile { .profile {
background-color: $ui-colour; background-color: $ui-colour;
height: auto; height: auto;
@ -127,7 +151,8 @@ input[type=text], input[type=password], input[type=number], select {
} }
} }
h1.title { .title {
h1 {
color: black; color: black;
font-size: 4em; font-size: 4em;
font-family: 'Pirata One', arial; font-family: 'Pirata One', arial;
@ -150,15 +175,29 @@ h1.title {
text-align: center; text-align: center;
margin: auto; margin: auto;
box-shadow: 5px 5px 8px #000000; box-shadow: 5px 5px 8px #000000;
}
}
.title-small {
h1 {
color: white;
font-size: 2em;
font-family: 'Pirata One', arial;
text-shadow: 3px 3px 3px black;
font-weight: bold;
padding: 0;
margin-block: 0;
margin-inline: 10px;
}
} }
.card { .card {
/*background-color: grey;*/ /*background-color: grey;*/
background-color: $ui-colour; background-color: $ui-colour;
box-shadow: 4px 4px 8px black; box-shadow: 4px 4px 8px black;
padding: 10px; padding: 20px;
margin: calc($pad-px / 2); //margin: calc($pad-px / 2);
/*border-radius: 3px;*/ /*border-radius: 3px;*/
h1 { h1 {
@ -181,12 +220,6 @@ h1.title {
} }
} }
h1.sectiontitle {
text-align:center;
color: $text-colour;
font-family: 'Megrim', sans-serif;
}
ul.navbar { ul.navbar {
list-style-type: none; list-style-type: none;
background-color: $light-ui; background-color: $light-ui;
@ -238,78 +271,6 @@ ul.navbar {
li.right {float: right;} li.right {float: right;}
} }
.sidebar {
list-style-type: none;
background-color: $light-ui;
margin-left: 10px;
margin-right: 10px;
border-radius: 5px;
// padding-top: 10px;
// padding-bottom: 10px;
user-select: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-webkit-user-drag: none;
-khtml-user-drag: none;
-moz-user-drag: none;
-o-user-drag: none;
box-shadow: 0 9px 12px 0 black, 0 9px 12px 0 black;
tr {
top: 0;
cursor: pointer;
td {
// height: 50px;
text-align: center;
vertical-align: center;
border-radius: 5px;
a {
color: $text-colour;
height: 100%;
width: 100%;
display: inline-block;
vertical-align: center;
padding: 10px;
text-decoration: none;
text-shadow: 1px 1px 1px rgba(0,0,0, 0.5);
-webkit-transition: background-color 0.4s;
transition: background-color 0.4s;
}
&:hover {
background-color: $ui-shadow;
}
}
}
}
.sidebar-selected {
background-color: black;
}
.app-table {
width: 100%;
margin: auto;
td {
padding: 5px;
}
}
.max-width {
max-width: 800px;
}
.text-no-select { .text-no-select {
cursor: default; cursor: default;
user-select: none; user-select: none;
@ -318,22 +279,6 @@ ul.navbar {
-ms-user-select: none; -ms-user-select: none;
} }
footer {
p {
text-align: right;
font-size: 12px;
}
a {
margin-top: 10px;
margin-bottom: 10px;
text-align: right;
display: block;
color: grey;
font-size: 12px;
}
}
#snackbar { #snackbar {
visibility: hidden; visibility: hidden;
min-width: 250px; min-width: 250px;