Skip to content

Commit

Permalink
Implement search on artists page with htmx
Browse files Browse the repository at this point in the history
  • Loading branch information
fsktom committed Oct 10, 2024
1 parent e8d2594 commit dc5ded0
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 17 deletions.
4 changes: 2 additions & 2 deletions endsong_web/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion endsong_web/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ version = "0.1.0"
edition = "2021"

[dependencies]
axum = "0.7"
axum = { version = "0.7", features = ["form"] }
tower-http = { version = "0.6", features = ["compression-br"] }
endsong = { path = ".." }
itertools = "0.13"
Expand Down
58 changes: 50 additions & 8 deletions endsong_web/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ use axum::{
http::StatusCode,
response::{IntoResponse, Response},
routing::get,
Router,
routing::post,
Form, Router,
};
use endsong::prelude::*;
use rinja_axum::Template;
Expand All @@ -15,7 +16,10 @@ use tracing::debug;
use tracing_subscriber::filter::{EnvFilter, LevelFilter};

/// Tailwind-generated CSS used on this web page
const STYLING: &str = include_str!("../templates/tailwind_style.css");
const STYLING: &str = include_str!("../static/tailwind_style.css");

/// HTMX code (<https://htmx.org/docs/#installing>)
const HTMX: &str = include_str!("../static/htmx.min.2.0.3.js");

#[derive(Clone)]
struct AppState {
Expand Down Expand Up @@ -54,7 +58,9 @@ async fn main() {
let app = Router::new()
.route("/", get(index))
.route("/styles.css", get(styles))
.route("/htmx.js", get(htmx))
.route("/artists", get(artists))
.route("/artists", post(artists_search))
.route("/artist/:artist_name", get(artist))
.with_state(state)
.fallback(not_found)
Expand Down Expand Up @@ -90,6 +96,16 @@ async fn styles() -> impl IntoResponse {
axum_extra::response::Css(STYLING)
}

/// GET `/htmx` - HTMX
///
/// Idk yet how, but should be cached somehow for the future so that
/// it isn't requested on each load in full? idk
async fn htmx() -> impl IntoResponse {
debug!("GET /htmx");

axum_extra::response::JavaScript(HTMX)
}

/// [`Template`] for [`index`]
#[derive(Template)]
#[template(path = "index.html", print = "none")]
Expand All @@ -112,20 +128,46 @@ async fn index(State(state): State<Arc<AppState>>) -> impl IntoResponse {
/// [`Template`] for [`artists`]
#[derive(Template)]
#[template(path = "artists.html", print = "none")]
struct Artists {
struct Artists {}
/// GET `/artists`
///
/// List of artists (HTML Template will call [`artists_search`] on-load)
async fn artists() -> impl IntoResponse {
debug!("GET /artists");

Artists {}
}

#[derive(serde::Deserialize)]
struct ArtistsSearchForm {
search: String,
}
/// [`Template`] for [`artists_search`]
#[derive(Template)]
#[template(path = "artists_search.html", print = "none")]
struct ArtistsSearch {
artist_names: Vec<Arc<str>>,
}
/// GET `/artists`
/// POST `/artists`
///
/// List of artists
async fn artists(State(state): State<Arc<AppState>>) -> impl IntoResponse {
debug!("GET /artists");
async fn artists_search(
State(state): State<Arc<AppState>>,
Form(form): Form<ArtistsSearchForm>,
) -> impl IntoResponse {
debug!(search = form.search, "POST /artists");

let entries = state.entries.read().await;

let artist_names = entries.artists();
let lowercase_search = form.search.to_lowercase();

let artist_names = entries
.artists()
.into_iter()
.filter(|artist| artist.to_lowercase().contains(&lowercase_search))
.collect();

Artists { artist_names }
ArtistsSearch { artist_names }
}

/// To choose an artist if there are multiple with same capitalization
Expand Down
1 change: 1 addition & 0 deletions endsong_web/static/htmx.min.2.0.3.js

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,10 @@ video {
gap: 2rem;
}

.gap-2 {
gap: 0.5rem;
}

.self-center {
align-self: center;
}
Expand All @@ -615,6 +619,16 @@ video {
border-color: rgb(229 231 235 / var(--tw-border-opacity));
}

.border-gray-300 {
--tw-border-opacity: 1;
border-color: rgb(209 213 219 / var(--tw-border-opacity));
}

.bg-gray-50 {
--tw-bg-opacity: 1;
background-color: rgb(249 250 251 / var(--tw-bg-opacity));
}

.bg-slate-100 {
--tw-bg-opacity: 1;
background-color: rgb(241 245 249 / var(--tw-bg-opacity));
Expand All @@ -629,6 +643,10 @@ video {
padding: 0.5rem;
}

.p-4 {
padding: 1rem;
}

.p-6 {
padding: 1.5rem;
}
Expand All @@ -637,6 +655,10 @@ video {
padding: 1.75rem;
}

.ps-10 {
padding-inline-start: 2.5rem;
}

.text-2xl {
font-size: 1.5rem;
line-height: 2rem;
Expand All @@ -652,6 +674,11 @@ video {
line-height: 1.75rem;
}

.text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
}

.text-xl {
font-size: 1.25rem;
line-height: 1.75rem;
Expand All @@ -661,6 +688,11 @@ video {
font-weight: 700;
}

.text-gray-900 {
--tw-text-opacity: 1;
color: rgb(17 24 39 / var(--tw-text-opacity));
}

.shadow {
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
Expand All @@ -676,3 +708,13 @@ https://www.joshwcomeau.com/css/interactive-guide-to-flexbox/
* {
min-width: 0;
}

.focus\:border-blue-500:focus {
--tw-border-opacity: 1;
border-color: rgb(59 130 246 / var(--tw-border-opacity));
}

.focus\:ring-blue-500:focus {
--tw-ring-opacity: 1;
--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity));
}
3 changes: 3 additions & 0 deletions endsong_web/templates/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Templating

`npx tailwindcss -i base_style.css -o ../static/tailwind_style.css --watch`
29 changes: 24 additions & 5 deletions endsong_web/templates/artists.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,28 @@
{% block title %} Artists {% endblock %}
<!-- -->
{% block content %}
<ul>
{% for artist in artist_names %}
<li><a href="/artist/{{ artist|encodeurl }}">{{ artist }}</a></li>
{% endfor %}
</ul>
<section class="flex flex-col items-center gap-2">
<input
id="artist-search"
class="block rounded-lg border border-gray-300 bg-gray-50 p-2 text-lg text-gray-900"
type="search"
name="search"
placeholder="Artist name..."
hx-post="/artists"
hx-trigger="input changed, search, load"
hx-target="#search-results"
/>
<ul id="search-results" class="flex flex-col items-center text-lg"></ul>
</section>
<script>
document.addEventListener("keydown", function (event) {
if (
(event.key === "s" || event.key === "/") &&
!event.target.matches("input, textarea")
) {
event.preventDefault();
document.getElementById("artist-search").focus();
}
});
</script>
{% endblock %}
3 changes: 3 additions & 0 deletions endsong_web/templates/artists_search.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{% for artist in artist_names %}
<li><a href="/artist/{{ artist|encodeurl }}">{{ artist }}</a></li>
{% endfor %}
1 change: 1 addition & 0 deletions endsong_web/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>{% block title %}Endsong Web{% endblock %}- Endsong Web</title>
<link rel="stylesheet" href="/styles.css" />
<script src="/htmx.js"></script>
</head>
<body class="flex flex-col items-center justify-evenly gap-4 bg-slate-100">
<header class="flex w-full items-center justify-around bg-slate-200 p-6">
Expand Down
3 changes: 2 additions & 1 deletion endsong_web/templates/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ module.exports = {
"./index.html",
"./404.html",
"./artists.html",
"./artists_search.html",
"./artist.html",
"./artist_selection.html"
"./artist_selection.html",
],
theme: {
extend: {},
Expand Down

0 comments on commit dc5ded0

Please sign in to comment.