summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/albums.js89
-rw-r--r--src/connector.js38
-rw-r--r--src/slides.js11
-rw-r--r--src/style.css2
4 files changed, 108 insertions, 32 deletions
diff --git a/src/albums.js b/src/albums.js
index c1d85e3..ff7cd1d 100644
--- a/src/albums.js
+++ b/src/albums.js
@@ -1,30 +1,30 @@
import apiConnector from "./connector.js"
-export default async function initAlbums(albumsPageContainer) {
- const albumsContainer = albumsPageContainer.querySelector("#albums-container")
- const albumTemplate = albumsPageContainer.querySelector("#album-template")
-
- // create albums
- async function createAlbum(res) {
- const albumClone = albumTemplate.content.cloneNode(true)
- albumClone.firstElementChild.dataset.key = res.id
- albumClone.querySelector("a").href = apiConnector.albumSrc(res.id)
- albumClone.querySelector("img").src = apiConnector.assetThumbnailSrc(res.albumThumbnailAssetId)
- albumClone.querySelector(".album-name").textContent = res.albumName
- albumClone.querySelector(".album-assets-count").textContent = res.assetCount.toLocaleString()
- if (!res.shared)
- albumClone.querySelector(".album-shared").remove()
-
- albumsContainer.appendChild(albumClone)
- }
+class Album {
+ static albums = []
+ static albumTemplate = null
+ static albumContainer = null
+
+ constructor(data) {
+ this.data = data
+ // create clone element
+ const e = Album.albumTemplate.content.cloneNode(true)
+ e.firstElementChild.dataset.key = data.id
+ e.querySelector("a").href = apiConnector.albumSrc(data.id)
+ e.querySelector("img").src = apiConnector.assetThumbnailSrc(data.albumThumbnailAssetId)
+ e.querySelector(".album-name").textContent = data.albumName
+ e.querySelector(".album-assets-count").textContent = data.assetCount.toLocaleString()
+ if (!data.shared)
+ e.querySelector(".album-shared").remove()
- const albumsResponse = await apiConnector.fetchAlbums()
+ Album.albums.push(this)
+ Album.albumsContainer.appendChild(e)
+ this.element = Album.albumsContainer.lastElementChild
+ }
- for (const res of albumsResponse)
- createAlbum(res)
+ toggleVisibility(visible) { this.element.classList.toggle("hidden!", !visible) }
- // album selection
- albumsContainer.addEventListener("click", e => {
+ static albumSelect(e) {
// find album element
let album = e.target
while (album && !album.classList.contains("album"))
@@ -33,12 +33,51 @@ export default async function initAlbums(albumsPageContainer) {
if (album === null)
return
- console.log(album)
if (album.dataset.selected)
delete album.dataset.selected
else
album.dataset.selected = "1"
- })
+ }
+
+ static albumsFilter(e) {
+ const q = e.target.value.toLowerCase()
+ for (const album of Album.albums) {
+ const match = album.data.albumName.toLowerCase().includes(q)
+ album.toggleVisibility(match)
+ }
+ }
+
+ static getSelected() {
+ const s = []
+ for (const album of Album.albums)
+ if (album.element.dataset.selected)
+ s.push(album.data.id)
+ return s
+ }
- return true
+ static submitSelected() {
+ apiConnector.updateAlbums(Album.getSelected())
+ }
+
+ static async initAlbums(albumsPageContainer) {
+ Album.albumsContainer = albumsPageContainer.querySelector("#albums-container")
+ Album.albumTemplate = albumsPageContainer.querySelector("#album-template")
+ const albumSearch = albumsPageContainer.querySelector("#album-search")
+ const albumsSubmit = albumsPageContainer.querySelector("#albums-submit")
+
+ // create albums
+ const albumsResponse = await apiConnector.fetchAlbums()
+
+ for (const res of albumsResponse)
+ new Album(res)
+
+ // album selection
+ Album.albumsContainer.addEventListener("click", Album.albumSelect)
+ albumSearch.addEventListener("input", Album.albumsFilter)
+ albumsSubmit.addEventListener("click", Album.submitSelected)
+
+ return true
+ }
}
+
+export default Album.initAlbums
diff --git a/src/connector.js b/src/connector.js
index 29f0cff..5d8b62f 100644
--- a/src/connector.js
+++ b/src/connector.js
@@ -5,18 +5,24 @@ class APIConnector {
this.url = url ?? ""
this.socket = io(url)
- this.asset_index = 0
+ this.assetIndex = 0
this.movement = 0
this.assets = null
+ this.currentAsset = null
this.seekCallbacks = []
this.socket.on("seek", e => {
this.assetIndex = e.asset_index
this.movement = e.movement
this.assets = e.assets
+ this.currentAsset = e.current_asset
for (const cb of this.seekCallbacks)
cb()
})
+
+ this.downloadAnchor = document.createElement("a")
+ this.downloadAnchor.classList = "hidden"
+ document.body.appendChild(this.downloadAnchor)
}
fetch(endpoint, c) {
@@ -34,6 +40,28 @@ class APIConnector {
})
}
+ async assetDownload(key) {
+ const filename = await this.assetFileName(key)
+ console.log(filename)
+ fetch(this.assetFullsizeSrc(key))
+ .then(response => {
+ if (!response.ok)
+ throw new Error(`HTTP error! Status: ${response.status}`)
+ return response.blob()
+ })
+ .then(blob => {
+ const blobUrl = URL.createObjectURL(blob)
+ this.downloadAnchor.href = blobUrl
+ this.downloadAnchor.download = filename
+
+ this.downloadAnchor.click()
+ URL.revokeObjectURL(blobUrl)
+ })
+ .catch(error => {
+ console.error("Fetch error:", error)
+ })
+ }
+
post(endpoint, body) {
return this.fetch(endpoint, {
method: "POST",
@@ -48,11 +76,15 @@ class APIConnector {
fetchAlbums() { return this.fetch("/albums") }
fetchConfig() { return this.fetch("/config") }
+ updateAlbums(albums) { return this.post("/albums/update", albums) }
updateConfig(config) { return this.post("/config/update", config) }
- albumSrc(key) { return `${this.url}/api/redirect/albums/${key}` }
- assetSrc(key) { return `${this.url}/api/asset/${key}` }
+ albumSrc(key) { return `${this.url}/api/redirect/albums/${key}` }
+
+ assetPreviewSrc(key) { return `${this.url}/api/asset/${key}` }
assetThumbnailSrc(key) { return `${this.url}/api/asset/${key}/thumbnail` }
+ assetFullsizeSrc(key) { return `${this.url}/api/asset/${key}/fullsize` }
+ assetFileName(key) { return this.fetch(`/asset/${key}/filename`).then(d => d.filename) }
}
const apiConnector = new APIConnector("http://localhost:5000")
diff --git a/src/slides.js b/src/slides.js
index fad6472..e4f6406 100644
--- a/src/slides.js
+++ b/src/slides.js
@@ -32,14 +32,19 @@ class Slides {
this.initImages()
/* initialize seek buttons */
- const seekPrevButton = this.slidesContainer.querySelector("#prevSlide")
- const seekNextButton = this.slidesContainer.querySelector("#nextSlide")
+ const seekPrevButton = this.slidesContainer.querySelector("#prev-slide")
+ const seekNextButton = this.slidesContainer.querySelector("#next-slide")
seekPrevButton.addEventListener("click", () => { this.flickity.previous() ; this.seek() })
seekNextButton.addEventListener("click", () => { this.flickity.next() ; this.seek() })
/* initialize seek callback */
apiConnector.seekCallbacks.push(c => { this.seekCallback() })
+
+ /* initialize top controls */
+ const assetDownloadButton = this.slidesContainer.querySelector("#download")
+
+ assetDownloadButton.addEventListener("click", () => { apiConnector.assetDownload(apiConnector.currentAsset) })
}
seek() {
@@ -72,7 +77,7 @@ class Slides {
const x = (i + this.selectedIndex + 6) % this.flickity.cells.length
const e = this.flickity.cells[x].element
const img = e.firstElementChild
- img.src = apiConnector.assetSrc(apiConnector.assets[i])
+ img.src = apiConnector.assetPreviewSrc(apiConnector.assets[i])
}
}
diff --git a/src/style.css b/src/style.css
index a41fa4c..b762eb3 100644
--- a/src/style.css
+++ b/src/style.css
@@ -44,5 +44,5 @@
@apply rounded-2xl bg-zinc-800 p-4
}
.rounded-btn {
- @apply rounded-full w-fit bg-blue-200 px-4 py-2 text-black font-medium
+ @apply rounded-full w-fit bg-blue-300 px-4 py-2 text-black fill-black font-medium cursor-pointer flex gap-1
}