diff --git a/res/admin.js b/res/admin.js index f4e7f0b..1df197d 100644 --- a/res/admin.js +++ b/res/admin.js @@ -1,8 +1,8 @@ // Admin functionality for rphotos (function (d) { - var details = d.querySelector('.details'); + var details = d.querySelector('main.details'), p; if (!details) { - return; + return; // Admin is for single image only } function rotate(event) { @@ -32,22 +32,29 @@ r.send("angle=" + angle + "&image=" + imgid) } - function tag_form(event, category) { - event.target.disabled = true; - var imgid = details.dataset.imgid; + function makeform(category) { + let oldform = p.querySelector('form'); + if (oldform) { + oldform.remove(); + } var f = d.createElement("form"); f.className = "admin " + category; f.action = "/adm/" + category; f.method = "post"; + var i = d.createElement("input"); + i.type="hidden"; + i.name="image"; + i.value = details.dataset.imgid; + f.appendChild(i); + return f; + } + function tag_form(event, category) { + //event.target.disabled = true; - FIXME? + var f = makeform(category); var l = d.createElement("label"); l.innerHTML = event.target.title; f.appendChild(l); var i = d.createElement("input"); - i.type="hidden"; - i.name="image"; - i.value = imgid; - f.appendChild(i); - i = d.createElement("input"); i.type = "text"; i.autocomplete="off"; i.tabindex="1"; @@ -139,27 +146,18 @@ event.target.focus(); }; f.appendChild(c); - meta.insertBefore(f, meta.querySelector('#map')); + p.append(f); i.focus(); } function grade_form(event) { - event.target.disabled = true; - var imgid = details.dataset.imgid; + //event.target.disabled = true; - FIXME? var grade = details.dataset.grade; - var f = d.createElement("form"); - f.className = "admin grade"; - f.action = "/adm/grade"; - f.method = "post"; + var f = makeform("grade"); var l = d.createElement("label"); l.innerHTML = event.target.title; f.appendChild(l); var i = d.createElement("input"); - i.type="hidden"; - i.name="image"; - i.value = imgid; - f.appendChild(i); - i = d.createElement("input"); i.type="range"; i.name="grade"; if (grade) { @@ -199,23 +197,14 @@ e.stopPropagation(); return false; }); - meta.insertBefore(f, meta.querySelector('#map')); + p.append(f); i.focus(); } function location_form(event) { - event.target.disabled = true; - var imgid = details.dataset.imgid; + //event.target.disabled = true; - FIXME? var position = details.dataset.position || localStorage.getItem('lastpos'); - var f = d.createElement("form"); - f.className = "admin location"; - f.action = "/adm/locate"; - f.method = "post"; - var i = d.createElement("input"); - i.type="hidden"; - i.name="image"; - i.value = imgid; - f.appendChild(i); + var f = makeform("locate"); var lat = d.createElement("input"); lat.type="hidden"; @@ -303,58 +292,55 @@ }; f.appendChild(c); f.addEventListener('keydown', keyHandler); - meta.insertBefore(f, meta.querySelector('#map')); + p.append(f); } - var meta = details.querySelector('.meta'); - if (meta) { - p = d.createElement("p"); - p.className = 'admbuttons'; - r = d.createElement("button"); - r.onclick = rotate; - r.innerHTML = "\u27f2"; - r.dataset.angle = "-90"; - r.title = "Rotate left"; - p.appendChild(r); - p.appendChild(d.createTextNode(" ")); - r = d.createElement("button"); - r.onclick = rotate; - r.innerHTML = "\u27f3"; - r.dataset.angle = "90"; - r.title = "Rotate right"; - p.appendChild(r); + p = d.createElement("div"); + p.className = 'admbuttons'; + r = d.createElement("button"); + r.onclick = rotate; + r.innerHTML = "\u27f2"; + r.dataset.angle = "-90"; + r.title = "Rotate left"; + p.appendChild(r); + p.appendChild(d.createTextNode(" ")); + r = d.createElement("button"); + r.onclick = rotate; + r.innerHTML = "\u27f3"; + r.dataset.angle = "90"; + r.title = "Rotate right"; + p.appendChild(r); - p.appendChild(d.createTextNode(" ")); - r = d.createElement("button"); - r.onclick = e => tag_form(e, 'tag'); - r.innerHTML = "🏷"; - r.title = "Tag"; - r.accessKey = "t"; - p.appendChild(r); + p.appendChild(d.createTextNode(" ")); + r = d.createElement("button"); + r.onclick = e => tag_form(e, 'tag'); + r.innerHTML = "🏷"; + r.title = "Tag"; + r.accessKey = "t"; + p.appendChild(r); - p.appendChild(d.createTextNode(" ")); - r = d.createElement("button"); - r.onclick = e => tag_form(e, 'person'); - r.innerHTML = "\u263a"; - r.title = "Person"; - r.accessKey = "p"; - p.appendChild(r); + p.appendChild(d.createTextNode(" ")); + r = d.createElement("button"); + r.onclick = e => tag_form(e, 'person'); + r.innerHTML = "\u263a"; + r.title = "Person"; + r.accessKey = "p"; + p.appendChild(r); - p.appendChild(d.createTextNode(" ")); - r = d.createElement("button"); - r.onclick = e => location_form(e); - r.innerHTML = "\u{1f5fa}"; - r.title = "Location"; - r.accessKey = "l"; - p.appendChild(r); + p.appendChild(d.createTextNode(" ")); + r = d.createElement("button"); + r.onclick = e => location_form(e); + r.innerHTML = "\u{1f5fa}"; + r.title = "Location"; + r.accessKey = "l"; + p.appendChild(r); - p.appendChild(d.createTextNode(" ")); - r = d.createElement("button"); - r.onclick = e => grade_form(e); - r.innerHTML = "\u2606"; - r.title = "Grade"; - r.accessKey = "g"; - p.appendChild(r); - meta.appendChild(p); - } + p.appendChild(d.createTextNode(" ")); + r = d.createElement("button"); + r.onclick = e => grade_form(e); + r.innerHTML = "\u2606"; + r.title = "Grade"; + r.accessKey = "g"; + p.appendChild(r); + details.appendChild(p); })(document) diff --git a/res/photos.scss b/res/photos.scss index 321327b..52efb57 100644 --- a/res/photos.scss +++ b/res/photos.scss @@ -15,6 +15,9 @@ body { flex-direction: column; justify-content: space-between; min-height: 100%; + + // FIXME? Only on details? + max-height: 100vh; } h1 { @@ -237,39 +240,79 @@ div.group { justify-content: space-around; } } -div.details { - display: flex; - flex-flow: row wrap; - margin: -1ex; - .item, .meta { - margin: 1ex; - } - .item { - align-self: flex-start; - flex-grow: 4; - text-align: center; - width: 30em; +main.details { + margin: 0; + padding: 1ex; + + img.item { + height: auto; + width: -moz-available; + width: -webkit-fill-available; + width: available; &.zoom { + position: fixed; + top: 0; + left: 0; width: -moz-available; - width: -webkit-fill-available; - width: available; + height: -moz-available; + z-index: 10000; + object-fit: contain; } - img { - width: -moz-available; - width: -webkit-fill-available; - width: available; - height: auto; + } +} + +@media screen and (min-width: 50em) { + main.details { + align-items: start; + display: grid; + flex: content 1 1; + grid-gap: 1ex; + grid-template-columns: 1fr fit-content(29%); + grid-template-rows: min-content 1fr min-content 1fr; + max-height: -moz-available; + overflow: hidden; + + h1 { + grid-column: 2; + margin: 0; + } + img.item { display: block; + grid-row: 1 / -1; + margin: 0 auto auto; + max-width: -moz-available; + max-height: -moz-available; + max-height: calc(100% - 2px); + max-width: calc(100% - 2px); + object-fit: scale-down; + width: auto; + height: auto; + + .zoom { + grid-column: 1 / 3; + } + } + .places a:nth-child(n+2) { + font-size: 80%; + } + .meta { + overflow: auto; + height: -moz-available; + height: 100%; + } + #map { + margin: 0; + height: calc(100% - 2px) !important; + width: -moz-available; + } + .admbuttons { + flex-flow: row wrap; + margin: 0; + button { + margin: 0; + } } - } - .meta { - flex-grow: 1; - flex-basis: 20em; - padding-top: 0; - } - .places a:nth-child(n+2) { - font-size: 80%; } } @@ -285,13 +328,13 @@ ul.alltags, ul.allpeople, ul.allplaces { max-height: 60vh; } -p.admbuttons { +div.admbuttons { display: flex; flex-flow: row wrap; justify-content: space-between; margin: 1ex -.1em 0; button { - flex-grow: .1; + flex: min-content .1 1; margin: .1em; padding: 0; } @@ -310,7 +353,7 @@ form { justify-content: space-between; } label { - padding: .2em 1em .2em 0; + padding: .2em .6em .2em 0; } } @@ -341,15 +384,16 @@ form { // Relevant for admin forms only. Move to separate file? form.admin { - position: relative; - padding: 1.8em 1ex; display: flex; + margin: .3em .1em 0; + padding: 1.6em 1ex 1.2em; + position: relative; width: -moz-available; width: -webkit-fill-available; width: available; input[type="text"], input[type="range"] { - flex-grow: 1; + flex: min-content 1 1; margin-right: 1ex; } button.close { @@ -360,7 +404,7 @@ form.admin { right: -1ex; top: -1ex; } - &.location { + &.locate { background: #eee; box-shadow: .2em .4em 1em rgba(0,0,0,.7); display: flex; diff --git a/res/ux.js b/res/ux.js index 383082f..4c08fb5 100644 --- a/res/ux.js +++ b/res/ux.js @@ -43,7 +43,7 @@ csslink.rel = 'stylesheet'; csslink.href = '/static/l140/leaflet.css'; h.append(csslink); - let m = d.querySelector('.meta') || d.querySelector('main'); + let m = d.querySelector('main'); m.insertAdjacentHTML('beforeend', '
'); var slink = d.createElement('script'); slink.type = 'text/javascript'; diff --git a/templates/base.rs.html b/templates/base.rs.html new file mode 100644 index 0000000..2fea976 --- /dev/null +++ b/templates/base.rs.html @@ -0,0 +1,31 @@ +@use super::statics::{photos_css, admin_js, ux_js}; +@use super::head; +@use crate::server::{Context, Link}; + +@(context: &Context, title: &str, lpath: &[Link], meta: Content, content: Content) + + + + + @title + + + + @if context.is_authorized() { + + } + + @:meta() + + + @:head(context, lpath) + @:content() + + + diff --git a/templates/details.rs.html b/templates/details.rs.html index b464264..3fc9391 100644 --- a/templates/details.rs.html +++ b/templates/details.rs.html @@ -1,16 +1,17 @@ -@use super::page_base; +@use super::base; @use crate::models::{Photo, Person, Place, Tag, Camera, Coord, SizeTag}; @use crate::server::{Context, Link}; @(context: &Context, lpath: &[Link], people: &[Person], places: &[Place], tags: &[Tag], position: &Option, attribution: &Option, camera: &Option, photo: &Photo) -@:page_base(context, "Photo details", lpath, { +@:base(context, "Photo details", lpath, { }, { -
-
+
+

Photo details

+
@if context.is_authorized() {

@photo.path

@@ -29,5 +30,5 @@ @if let Some(ref a) = *attribution {

Av: @a

} @if let Some(ref c) = *camera {

Camera: @c.model (@c.manufacturer)

}
-
+ }) diff --git a/templates/page_base.rs.html b/templates/page_base.rs.html index ce6fe0a..17d66a3 100644 --- a/templates/page_base.rs.html +++ b/templates/page_base.rs.html @@ -1,34 +1,10 @@ -@use super::statics::{photos_css, admin_js, ux_js}; +@use super::base; @use crate::server::{Context, Link}; -@use crate::templates::head; @(context: &Context, title: &str, lpath: &[Link], meta: Content, content: Content) - - - - - @title - - - - @if context.is_authorized() { - - } - - @:meta() - - - @:head(context, lpath) +@:base(context, title, lpath, meta, {

@title

@:content()
- - - +})