summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2023-12-15 22:43:58 +0100
committerPřemysl Eric Janouch <p@janouch.name>2023-12-15 22:55:12 +0100
commit11f637e43c120e528a94cb3073883187a8d696b2 (patch)
tree157ddaafa8b20b929b36de2f3980c79bff10dfd1
parent80136f48c9c91ba0bdcd9911a0eaa0aeae565b8a (diff)
downloadgallery-11f637e43c120e528a94cb3073883187a8d696b2.tar.gz
gallery-11f637e43c120e528a94cb3073883187a8d696b2.tar.xz
gallery-11f637e43c120e528a94cb3073883187a8d696b2.zip
Improve web views
-rw-r--r--main.go16
-rw-r--r--public/gallery.js59
2 files changed, 54 insertions, 21 deletions
diff --git a/main.go b/main.go
index b01e687..8c154e8 100644
--- a/main.go
+++ b/main.go
@@ -183,7 +183,6 @@ func handleThumbs(w http.ResponseWriter, r *http.Request) {
func getSubdirectories(tx *sql.Tx, parent int64) (names []string, err error) {
// TODO: This is like dbCollectStrings(), just needs an argument.
- // TODO: Should this return full paths, or not? Clean it up.
rows, err := tx.Query(
`SELECT name FROM directory WHERE IFNULL(parent, 0) = ?`, parent)
if err != nil {
@@ -282,7 +281,7 @@ func getImagePaths(sha1 string) (paths []string, err error) {
UNION ALL
SELECT d.parent, d.name || '/' || p.path
FROM directory AS d JOIN paths AS p ON d.id = p.parent
- ) SELECT '/' || path FROM paths WHERE parent IS NULL`, sha1)
+ ) SELECT path FROM paths WHERE parent IS NULL`, sha1)
if err != nil {
return nil, err
}
@@ -430,16 +429,15 @@ func idForPath(tx *sql.Tx, path []string, create bool) (int64, error) {
}
func decodeWebPath(path string) []string {
- // Trailing slashes don't provide information.
- path = strings.TrimSuffix(path, "/")
-
// Relative paths could be handled differently,
// but right now, they're assumed to start at the root.
- list := strings.Split(path, "/")
- if len(list) > 0 && list[0] == "" {
- list = list[1:]
+ result := []string{}
+ for _, crumb := range strings.Split(path, "/") {
+ if crumb != "" {
+ result = append(result, crumb)
+ }
}
- return list
+ return result
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/public/gallery.js b/public/gallery.js
index d25c544..940b0d2 100644
--- a/public/gallery.js
+++ b/public/gallery.js
@@ -14,35 +14,64 @@ let BrowseModel = {
entries: [],
async reload(path) {
- this.path = path
- this.subdirectories = []
- this.entries = []
+ if (this.path !== path) {
+ this.path = path
+ this.subdirectories = []
+ this.entries = []
+ }
let resp = await call('browse', {path: path})
this.subdirectories = resp.subdirectories
this.entries = resp.entries
},
+
+ joinPath(parent, child) {
+ if (!parent)
+ return child
+ if (!child)
+ return parent
+ return `${parent}/${child}`
+ },
+
+ getBrowseLinks() {
+ if (this.path === undefined)
+ return []
+
+ let links = [{name: "Root", path: "", level: -1}], path
+ for (const crumb of this.path.split('/').filter(s => !!s)) {
+ path = this.joinPath(path, crumb)
+ links.push({name: crumb, path: path, level: -1})
+ }
+
+ links[links.length - 1].level = 0
+
+ for (const sub of this.subdirectories) {
+ links.push(
+ {name: sub, path: this.joinPath(this.path, sub), level: +1})
+ }
+ return links
+ },
}
let Browse = {
- // Reload the model immediately, to improve responsibility.
+ // Reload the model immediately, to improve responsivity.
// But we don't need to: https://mithril.js.org/route.html#preloading-data
// Also see: https://mithril.js.org/route.html#route-cancellation--blocking
oninit(vnode) {
- let path = vnode.attrs.key || "/"
+ let path = vnode.attrs.key || ""
BrowseModel.reload(path)
},
view(vnode) {
return m('.container', {}, [
m('.header', {}, "Browse"),
- m('h1', "Root"),
- m('ul', BrowseModel.subdirectories.map(sd => {
- const name = sd.split('/').pop()
+ m('ul', BrowseModel.getBrowseLinks().map(link => {
+ // TODO: Differentiate the level as CSS classes.
+ // - Last entry (current path) should look selected.
return m('li', m(m.route.Link, {
href: `/browse/:key`,
- params: {key: `${BrowseModel.path}/${sd}`},
- }, name))
+ params: {key: link.path},
+ }, `${link.level} ${link.name}`))
})),
m('.browser', {}, BrowseModel.entries.map(e => {
return m(m.route.Link, {href: `/view/${e.sha1}`},
@@ -76,13 +105,19 @@ let View = {
},
view(vnode) {
- // TODO: Show more information.
return m('.container', {}, [
m('.header', {}, "View"),
- m('ul', ViewModel.paths.map(sd => m('li', sd))),
ViewModel.sha1 !== undefined
? m('img', {src: `/image/${ViewModel.sha1}`})
: "No image.",
+ m('h2', "Locations"),
+ m('ul', ViewModel.paths.map(sd => m('li', sd))),
+ m('h2', "Tags"),
+ Object.entries(ViewModel.tags).map(([group, tags]) => [
+ m("h3", group),
+ m("ul", Object.entries(tags).map(
+ ([tag, weight]) => m("li", `${tag}: ${weight}`))),
+ ]),
])
},
}