Only show own accounts on home page

This commit is contained in:
Cadence Ember 2025-04-09 13:21:41 +12:00
parent 2c05140382
commit 924c7395cf
7 changed files with 106 additions and 79 deletions

View file

@ -113,12 +113,18 @@ class From {
}
/**
* @param {Partial<U.Numberish<U.Models[Table]>>} conditions
* @param {Partial<U.ValueOrArray<U.Numberish<U.Models[Table]>>>} conditions
*/
where(conditions) {
const wheres = Object.entries(conditions).map(([col, value]) => {
this.parameters.push(value)
return `"${col}" = ?`
if (Array.isArray(value)) {
this.parameters.push(...value)
return `"${col}" IN (` + Array(value.length).fill("?").join(", ") + ")"
} else {
this.parameters.push(value)
return `"${col}" = ?`
}
})
this.sql += " WHERE " + wheres.join(" AND ")
return this

View file

@ -16,15 +16,15 @@ html
.ml6 BC Explorer
.mx-auto.wmx9.py24.px16.g24
.s-prose
h1 Select profile
- const names = select("account", "account").pluck().all()
ul
each name in names
li: a(href=`/${name}/`)= name
if accounts.length
.s-prose
h1 Select account
ul
each account in accounts
li: a(href=`/${account.account}/`) #{account.account} (#{account.count} items)
form.mt32(hx-post="/api/load-collection" hx-target="#results" hx-indicator="#submit-username")
h2 Add your profile
h1 Add an account
.d-flex.gy4.fd-column.ps-relative
label.s-label(for="username") Bandcamp username
input.s-input.wmx3#username(name="account" placeholder="Enter your Bandcamp username here")

71
routes/_index.js Normal file
View file

@ -0,0 +1,71 @@
// @ts-check
const fs = require("fs")
const {defineEventHandler, defaultContentType, handleCacheHeaders} = require("h3")
const {sync, router} = require("../passthrough")
/** @type {import("../pug-sync")} */
const pugSync = sync.require("../pug-sync")
// Routes
sync.require("./app")
sync.require("./collection-stats")
sync.require("./load-collection")
sync.require("./home")
sync.require("./play")
sync.require("./settings")
// Files
router.get("/static/stacks.min.css", defineEventHandler({
onBeforeResponse: pugSync.compressResponse,
handler: async event => {
handleCacheHeaders(event, {maxAge: 86400})
defaultContentType(event, "text/css")
return fs.promises.readFile(require.resolve("@stackoverflow/stacks/dist/css/stacks.css"), "utf-8")
}
}))
router.get("/static/style.css", defineEventHandler({
onBeforeResponse: pugSync.compressResponse,
handler: async event => {
defaultContentType(event, "text/css")
return fs.promises.readFile("public/style.css", "utf-8")
}
}))
router.get("/static/htmx.js", defineEventHandler({
onBeforeResponse: pugSync.compressResponse,
handler: async event => {
handleCacheHeaders(event, {maxAge: 86400})
defaultContentType(event, "text/javascript")
return Promise.all(["htmx.org/dist/htmx.js"].map(r =>
fs.promises.readFile(require.resolve(r), "utf-8")
)).then(files => files.join("\n\n\n"))
}
}))
router.get("/static/wordcloud.js", defineEventHandler({
onBeforeResponse: pugSync.compressResponse,
handler: async event => {
handleCacheHeaders(event, {maxAge: 86400})
defaultContentType(event, "text/javascript")
return fs.promises.readFile(require.resolve("wordcloud/src/wordcloud2.js"), "utf-8")
}
}))
router.get("/static/player-marker.js", defineEventHandler({
handler: async event => {
defaultContentType(event, "text/javascript")
return fs.promises.readFile("public/player-marker.js")
}
}))
router.get("/favicon.png", defineEventHandler({
handler: async event => {
handleCacheHeaders(event, {maxAge: 86400})
defaultContentType(event, "text/javascript")
return fs.promises.readFile("public/favicon.png")
}
}))

View file

@ -150,7 +150,7 @@ router.get("/:account/", defineEventHandler({
loadPreviews(locals, "band_url", 6, whereClause, account, filter_field, filter, filter_fuzzy)
}
// if there are any untagged items then we don't have full track data
locals.hasFullTrackData = !db.prepare("SELECT * FROM item LEFT JOIN item_tag USING (account, item_id) WHERE account = ? AND item_id = NULL").get(account)
locals.hasFullTrackData = !db.prepare("SELECT * FROM item LEFT JOIN item_tag USING (account, item_id) WHERE account = ? AND tag IS NULL").get(account)
return pugSync.render(event, `${arrange}_${shape}.pug`, locals)
}
}))

15
routes/home.js Normal file
View file

@ -0,0 +1,15 @@
// @ts-check
const {z} = require("zod")
const {defineEventHandler, getQuery, getValidatedQuery, sendRedirect, createError, getValidatedRouterParams, getCookie} = require("h3")
const {router, db, sync, select, from} = require("../passthrough")
const pugSync = sync.require("../pug-sync")
router.get("/", defineEventHandler({
onBeforeResponse: pugSync.compressResponse,
handler: async event => {
const names = (getCookie(event, "accounts") || "").split("|")
const accounts = from("item").selectUnsafe("account", "count(*) AS count").where({account: names}).and("GROUP BY account").all()
return pugSync.render(event, `home.pug`, {accounts})
}
}))

View file

@ -4,7 +4,7 @@ const assert = require("assert/strict")
const fs = require("fs")
const sqlite = require("better-sqlite3")
const domino = require("domino")
const {defineEventHandler, readValidatedBody} = require("h3")
const {defineEventHandler, readValidatedBody, setCookie, getCookie} = require("h3")
const {z} = require("zod")
const {sync, db, router} = require("../passthrough")
@ -95,5 +95,6 @@ const schema = z.object({
router.post("/api/load-collection", defineEventHandler(async event => {
const {account} = await readValidatedBody(event, schema.parse)
const result = await loadCollection(account)
setCookie(event, "accounts", (getCookie(event, "accounts") || "").split("|").concat(account).join("|"))
return pugSync.render(event, "collection-loaded.pug", result)
}))

View file

@ -1,13 +1,10 @@
// @ts-check
const HeatSync = require("heatsync")
const assert = require("assert")
const fs = require("fs")
const sqlite = require("better-sqlite3")
const {createServer} = require("http")
const h3 = require("h3")
const {createApp, createRouter, toNodeListener} = require("h3")
const {defineEventHandler, defaultContentType, getRequestHeader, setResponseHeader, handleCacheHeaders} = h3
const passthrough = require("./passthrough")
const sync = new HeatSync()
@ -27,72 +24,9 @@ const pugSync = sync.require("./pug-sync")
/** @type {import("./icons")} */
const icons = sync.require("./icons")
// Pug
pugSync.addGlobals({h3, select, icons})
pugSync.createRoute(router, "/", "home.pug")
// Routes
sync.require("./routes/app")
sync.require("./routes/load-collection")
sync.require("./routes/play")
sync.require("./routes/settings")
sync.require("./routes/collection-stats")
// Files
router.get("/static/stacks.min.css", defineEventHandler({
onBeforeResponse: pugSync.compressResponse,
handler: async event => {
handleCacheHeaders(event, {maxAge: 86400})
defaultContentType(event, "text/css")
return fs.promises.readFile(require.resolve("@stackoverflow/stacks/dist/css/stacks.css"), "utf-8")
}
}))
router.get("/static/style.css", defineEventHandler({
onBeforeResponse: pugSync.compressResponse,
handler: async event => {
defaultContentType(event, "text/css")
return fs.promises.readFile("public/style.css", "utf-8")
}
}))
router.get("/static/htmx.js", defineEventHandler({
onBeforeResponse: pugSync.compressResponse,
handler: async event => {
handleCacheHeaders(event, {maxAge: 86400})
defaultContentType(event, "text/javascript")
return Promise.all(["htmx.org/dist/htmx.js"].map(r =>
fs.promises.readFile(require.resolve(r), "utf-8")
)).then(files => files.join("\n\n\n"))
}
}))
router.get("/static/wordcloud.js", defineEventHandler({
onBeforeResponse: pugSync.compressResponse,
handler: async event => {
handleCacheHeaders(event, {maxAge: 86400})
defaultContentType(event, "text/javascript")
return fs.promises.readFile(require.resolve("wordcloud/src/wordcloud2.js"), "utf-8")
}
}))
router.get("/static/player-marker.js", defineEventHandler({
handler: async event => {
defaultContentType(event, "text/javascript")
return fs.promises.readFile("public/player-marker.js")
}
}))
router.get("/favicon.png", defineEventHandler({
handler: async event => {
handleCacheHeaders(event, {maxAge: 86400})
defaultContentType(event, "text/javascript")
return fs.promises.readFile("public/favicon.png")
}
}))
sync.require("./routes/_index")
createServer(toNodeListener(app)).listen(2239)
console.log("running on http://localhost:2239")