From 4744a22ef68cb851c50ed898c0791b2935827950 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Wed, 2 Apr 2025 17:40:14 +1300 Subject: [PATCH] Add search field --- pug/album_grid.pug | 6 +++--- pug/artist_grid.pug | 6 +++--- pug/includes/layout.pug | 25 +++++++++++++++++++++---- pug/label_grid.pug | 6 +++--- pug/tag_grid.pug | 1 + routes/app.js | 15 ++++++++------- 6 files changed, 39 insertions(+), 20 deletions(-) diff --git a/pug/album_grid.pug b/pug/album_grid.pug index cc6c64e..2744267 100644 --- a/pug/album_grid.pug +++ b/pug/album_grid.pug @@ -9,16 +9,16 @@ block view img(loading="lazy" src=item.item_art_url width=210 height=210) p.fs-body3.mb8= item.item_title .d-flex.fw-wrap.g4 - a.s-tag.s-tag__xs(href=and({arrange: "track", filter_field: "item_id", filter: item.item_id})) + a.s-tag.s-tag__xs(href=and({arrange: "track", filter_field: "item_id", filter: item.item_id, filter_fuzzy: null})) span.s-tag--sponsor!= icons.get("music-note", 16) = item.track_count span.s-tag.s-tag__xs span.s-tag--sponsor!= icons.get("compact-disc", 16) = item.total_duration - a.s-tag.s-tag__xs(href=and({filter_field: "band_name", filter: item.band_name})) + a.s-tag.s-tag__xs(href=and({filter_field: "band_name", filter: item.band_name, filter_fuzzy: null})) span.s-tag--sponsor!= icons.get("people-tag", 16) = item.band_name - let label = item.band_url.replace(/https?:\/\/(.*?)\.bandcamp\.com.*/, "$1") - a.s-tag.s-tag__xs(href=and({filter_field: "band_url", filter: label})) + a.s-tag.s-tag__xs(href=and({filter_field: "band_url", filter: label, filter_fuzzy: null})) span.s-tag--sponsor!= icons.get("flower", 16) = label diff --git a/pug/artist_grid.pug b/pug/artist_grid.pug index 816f065..86e69af 100644 --- a/pug/artist_grid.pug +++ b/pug/artist_grid.pug @@ -8,10 +8,10 @@ block view .fl-grow1.pb12 .fs-headline1= item.band_name .d-flex.fw-wrap.g4 - a.s-tag.s-tag__xs(href=and({arrange: "album", filter_field: "band_name", filter: item.band_name})) + a.s-tag.s-tag__xs(href=and({arrange: "album", filter_field: "band_name", filter: item.band_name, filter_fuzzy: null})) span.s-tag--sponsor!= icons.get("album", 16) = item.album_count - a.s-tag.s-tag__xs(href=and({arrange: "track", filter_field: "band_name", filter: item.band_name})) + a.s-tag.s-tag__xs(href=and({arrange: "track", filter_field: "band_name", filter: item.band_name, filter_fuzzy: null})) span.s-tag--sponsor!= icons.get("music-note", 16) = item.track_count span.s-tag.s-tag__xs @@ -19,7 +19,7 @@ block view = item.total_duration - let labels = item.labels.split("|").map(x => x.replace(/https?:\/\/(.*?)\.bandcamp\.com.*/, "$1")) each label in labels - a.s-tag.s-tag__xs(href=and({filter_field: "band_url", filter: label})) + a.s-tag.s-tag__xs(href=and({filter_field: "band_url", filter: label, filter_fuzzy: null})) span.s-tag--sponsor!= icons.get("flower", 16) = label each preview in item.previews diff --git a/pug/includes/layout.pug b/pug/includes/layout.pug index 013f458..6e6bb4d 100644 --- a/pug/includes/layout.pug +++ b/pug/includes/layout.pug @@ -25,7 +25,7 @@ html --theme-dark-primary-color-s: 45%; --theme-dark-primary-color-l: 60%; } - .s-navigation--item.is-loading svg, .s-tag.is-loading svg { + .s-navigation--item.is-loading svg, .s-tag.is-loading svg, .s-sidebarwidget.is-loading svg { visibility: hidden; } .s-navigation__toggle.s-navigation { @@ -52,6 +52,9 @@ html color: blue; outline: 1px solid black; } + svg { + flex-shrink: 0; + } body.themed.theme-system.overflow-y-scroll(hx-boost="true") header.s-topbar.ps-sticky.t0 .s-topbar--container.wmx9 @@ -84,15 +87,29 @@ html .ps-sticky.d-flex.fd-column.g12.wmx4(style="top: 80px") if arrange === "tag" include tag-status.pug - if filter + + if filter && filter_field .s-sidebarwidget.s-sidebarwidget__blue.d-flex.ai-center.gx16.jc-space-between.p8.pl16 - .fl-shrink0!= icons.get("search") + != icons.get("search") .fl-grow1= `Searching for ` if filter_field === "item_id" strong= items[0].item_title else strong= filter - a.s-btn.s-notice--btn(href=and({filter: null, filter_field: null})) Clear + a.s-btn.s-notice--btn(href=and({filter: null, filter_field: null, filter_fuzzy: null})) Clear + else + form.d-flex.ai-stretch.gx8.jc-space-between.baw0 + input.s-input(name="filter" placeholder="Search" autocomplete="off").fl-grow1 + input(type="hidden" name="filter_field" value= + ( arrange === "artist" ? "band_name" + : arrange === "label" ? "band_url" + : arrange === "tag" ? "tag" + : "item_title")) + input(type="hidden" name="filter_fuzzy" value="true") + input(type="hidden" name="arrange" value=arrange) + input(type="hidden" name="shape" value=shape) + button.s-btn.s-btn__xs.s-btn__outlined.s-btn__muted!= icons.get("search") + .s-sidebarwidget.wmn3 .s-sidebarwidget--header Collection a.s-sidebarwidget--action Refresh diff --git a/pug/label_grid.pug b/pug/label_grid.pug index 299a683..4f46b0e 100644 --- a/pug/label_grid.pug +++ b/pug/label_grid.pug @@ -10,13 +10,13 @@ block view - let label = item.display_name.replace(/https?:\/\/(.*?)\.bandcamp\.com.*/, "$1") .fs-headline1= label .d-flex.fw-wrap.g4 - a.s-tag.s-tag__xs(href=and({arrange: "album", filter_field: "band_url", filter: minBandURL})) + a.s-tag.s-tag__xs(href=and({arrange: "album", filter_field: "band_url", filter: minBandURL, filter_fuzzy: null})) span.s-tag--sponsor!= icons.get("album", 16) = item.album_count - a.s-tag.s-tag__xs(href=and({arrange: "artist", filter_field: "band_url", filter: minBandURL})) + a.s-tag.s-tag__xs(href=and({arrange: "artist", filter_field: "band_url", filter: minBandURL, filter_fuzzy: null})) span.s-tag--sponsor!= icons.get("people-tag", 16) = item.artist_count - a.s-tag.s-tag__xs(href=and({arrange: "track", filter_field: "band_url", filter: minBandURL})) + a.s-tag.s-tag__xs(href=and({arrange: "track", filter_field: "band_url", filter: minBandURL, filter_fuzzy: null})) span.s-tag--sponsor!= icons.get("music-note", 16) = item.track_count span.s-tag.s-tag__xs diff --git a/pug/tag_grid.pug b/pug/tag_grid.pug index d21e482..e1f8849 100644 --- a/pug/tag_grid.pug +++ b/pug/tag_grid.pug @@ -27,6 +27,7 @@ block view const newURL = new URL(location) newURL.searchParams.set("filter", highlightedItem) newURL.searchParams.set("filter_field", "tag") + newURL.searchParams.delete("filter_fuzzy") newURL.searchParams.set("arrange", filter_field ? "album" : "label") location = newURL } diff --git a/routes/app.js b/routes/app.js index 95dcdd5..06230e6 100644 --- a/routes/app.js +++ b/routes/app.js @@ -32,12 +32,12 @@ const sqls = { track_list: "SELECT * FROM track INNER JOIN item USING (account, item_id) {JOIN TAG} WHERE account = ? {WHERE} ORDER BY band_url, item_title COLLATE NOCASE, track_number" } -function loadPreviews(locals, field, number, whereClause, account, filter_field, filter) { +function loadPreviews(locals, field, number, whereClause, account, filter_field, filter, filter_fuzzy) { const params = [account, number] let sql = `SELECT ${field}, item_url, item_art_url FROM (SELECT ${field}, item_url, item_art_url, row_number() OVER (PARTITION BY ${field} ORDER BY purchased DESC) AS row_number FROM item {JOIN TAG} WHERE account = ? {WHERE}) WHERE row_number <= ?` sql = sql.replace("{WHERE}", whereClause) if (whereClause) { - if (filter_field === "band_url") { + if (filter_field === "band_url" || filter_fuzzy) { params.splice(1, 0, `%${filter}%`) } else { params.splice(1, 0, filter) @@ -66,7 +66,8 @@ const schema = { arrange: z.enum(["album", "artist", "label", "tag", "track"]), shape: z.enum(["grid", "list"]), filter_field: z.enum(["band_name", "band_url", "item_id", "tag"]).optional(), - filter: z.string().optional() + filter: z.string().optional(), + filter_fuzzy: z.enum(["true"]).optional() }), params: z.object({ account: z.string() @@ -78,7 +79,7 @@ router.get("/:account/", defineEventHandler({ handler: async event => { try { var {account} = await getValidatedRouterParams(event, schema.params.parse) - var {arrange, shape, filter, filter_field} = await getValidatedQuery(event, schema.query.parse) + var {arrange, shape, filter, filter_field, filter_fuzzy} = await getValidatedQuery(event, schema.query.parse) } catch (e) { return sendRedirect(event, "?arrange=album&shape=grid", 302) } @@ -93,7 +94,7 @@ router.get("/:account/", defineEventHandler({ let whereClause = "" if (filter_field && filter) { let operator = "=" - if (filter_field === "band_url") { + if (filter_field === "band_url" || filter_fuzzy) { operator = "LIKE" params.push(`%${filter}%`) } else { @@ -148,9 +149,9 @@ router.get("/:account/", defineEventHandler({ } } if (mode === "artist_grid") { - loadPreviews(locals, "band_name", 4, whereClause, account, filter_field, filter) + loadPreviews(locals, "band_name", 4, whereClause, account, filter_field, filter, filter_fuzzy) } else if (mode === "label_grid") { - loadPreviews(locals, "band_url", 6, whereClause, account, filter_field, filter) + loadPreviews(locals, "band_url", 6, whereClause, account, filter_field, filter, filter_fuzzy) } else if (arrange === "tag") { locals.downloadManager = loadTags.downloadManager locals.downloader = loadTags.downloadManager.check(account)