Add gallery admin and video media support.
This updates gallery handling to support video playback with generated poster thumbnails, adds authenticated admin upload/delete flows, and improves dev/runtime behavior including reliable thumbnail generation and media-safe response handling. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
package templates
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"technical.kiwi/website/internal/gallery"
|
||||
)
|
||||
import "technical.kiwi/website/internal/gallery"
|
||||
|
||||
templ Home(images []gallery.Image, hero gallery.Image, hasHero bool, contactEnabled bool) {
|
||||
@Layout("Technical Kiwi Limited", heroPreload(hero, hasHero), homeContent(images, hero, hasHero, contactEnabled))
|
||||
@@ -20,10 +17,10 @@ templ homeContent(images []gallery.Image, hero gallery.Image, hasHero bool, cont
|
||||
<section class="hero">
|
||||
<div class="hero-copy">
|
||||
<p class="eyebrow">Technical Kiwi Limited</p>
|
||||
<h1>Electronic engineering, DevOps, and interactive art</h1>
|
||||
<h1>Electronic engineering and interactive art</h1>
|
||||
<p class="lead">
|
||||
We design and build lighting installations, embedded systems, and the infrastructure
|
||||
that keeps creative technology running — from workshop bench to stage.
|
||||
We design and build lighting installations, embedded systems, and interactive
|
||||
experiences — from workshop bench to stage.
|
||||
</p>
|
||||
<div class="hero-actions">
|
||||
<a href="#gallery" class="btn btn-primary">View our work</a>
|
||||
@@ -49,105 +46,20 @@ templ homeContent(images []gallery.Image, hero gallery.Image, hasHero bool, cont
|
||||
<h3>Electronic engineering</h3>
|
||||
<p>Custom LED systems, control electronics, PCB design, and fabrication for installations and products.</p>
|
||||
</article>
|
||||
<article class="service-card">
|
||||
<h3>DevOps & infrastructure</h3>
|
||||
<p>Servers, CI/CD, monitoring, and reliable deployments — so your systems stay up when the show goes live.</p>
|
||||
</article>
|
||||
<article class="service-card">
|
||||
<h3>Interactive art</h3>
|
||||
<p>Lighting, sound-reactive visuals, and experiential tech for events, venues, and public spaces.</p>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
<section id="code" class="code-section">
|
||||
<div class="section-head">
|
||||
<h2>Code</h2>
|
||||
<p>
|
||||
All repositories on
|
||||
<a href="https://git.technical.kiwi/" rel="noopener noreferrer" target="_blank">git.technical.kiwi</a>
|
||||
are written and maintained by Technical Kiwi — firmware, lighting control, web services,
|
||||
and the infrastructure behind them.
|
||||
</p>
|
||||
</div>
|
||||
<a
|
||||
href="https://git.technical.kiwi/"
|
||||
class="code-card"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank"
|
||||
>
|
||||
<div class="code-card-copy">
|
||||
<h3>git.technical.kiwi</h3>
|
||||
<p>
|
||||
Source for installations, internal tools, and open components we ship or deploy
|
||||
{ "for" } clients. Browse projects, history, and releases in one place.
|
||||
</p>
|
||||
</div>
|
||||
<span class="btn btn-primary">Browse repositories</span>
|
||||
</a>
|
||||
</section>
|
||||
<section id="gallery" class="gallery-section">
|
||||
<div class="section-head">
|
||||
<h2>Gallery</h2>
|
||||
<p>Installations, prototypes, and behind-the-scenes work.</p>
|
||||
</div>
|
||||
@GalleryControls(images)
|
||||
@GalleryCollectionControls(images)
|
||||
<div id="gallery-grid" class="gallery-grid">
|
||||
@GalleryGrid(images)
|
||||
</div>
|
||||
</section>
|
||||
@ContactForm(contactEnabled)
|
||||
}
|
||||
|
||||
templ GalleryControls(images []gallery.Image) {
|
||||
<div class="gallery-controls">
|
||||
<button
|
||||
type="button"
|
||||
class="filter-btn active"
|
||||
hx-get="/gallery"
|
||||
hx-target="#gallery-grid"
|
||||
hx-swap="innerHTML"
|
||||
>
|
||||
All
|
||||
</button>
|
||||
for _, album := range gallery.Albums(images) {
|
||||
<button
|
||||
type="button"
|
||||
class="filter-btn"
|
||||
hx-get={ fmt.Sprintf("/gallery?album=%s", album) }
|
||||
hx-target="#gallery-grid"
|
||||
hx-swap="innerHTML"
|
||||
>
|
||||
{ gallery.AlbumLabel(album) }
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
|
||||
templ GalleryCollectionControls(images []gallery.Image) {
|
||||
if len(gallery.Collections(images, "templeoftechno")) > 0 {
|
||||
<div class="gallery-controls gallery-controls-collections">
|
||||
<span class="gallery-controls-label">Temple of techno</span>
|
||||
<button
|
||||
type="button"
|
||||
class="filter-btn"
|
||||
hx-get="/gallery?album=templeoftechno"
|
||||
hx-target="#gallery-grid"
|
||||
hx-swap="innerHTML"
|
||||
>
|
||||
All events
|
||||
</button>
|
||||
for _, key := range gallery.Collections(images, "templeoftechno") {
|
||||
<button
|
||||
type="button"
|
||||
class="filter-btn"
|
||||
hx-get={ fmt.Sprintf("/gallery?album=templeoftechno&collection=%s", key) }
|
||||
hx-target="#gallery-grid"
|
||||
hx-swap="innerHTML"
|
||||
>
|
||||
{ gallery.CollectionLabel(key, images) }
|
||||
</button>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user