Add maps to image lists.
This commit is contained in:
parent
24a7a34025
commit
28032e4026
@ -373,8 +373,8 @@ fn tag_one<'mw>(
|
||||
let photos = Photo::query(req.authorized_user().is_some()).filter(
|
||||
id.eq_any(photo_tags.select(photo_id).filter(tag_id.eq(tag.id))),
|
||||
);
|
||||
let links = links_by_time(req, photos);
|
||||
return res.ok(|o| templates::tag(o, req, &links, &tag));
|
||||
let (links, coords) = links_by_time(req, photos);
|
||||
return res.ok(|o| templates::tag(o, req, &links, &coords, &tag));
|
||||
}
|
||||
res.not_found("Not a tag")
|
||||
}
|
||||
@ -432,8 +432,8 @@ fn place_one<'mw>(
|
||||
Photo::query(req.authorized_user().is_some()).filter(id.eq_any(
|
||||
photo_places.select(photo_id).filter(place_id.eq(place.id)),
|
||||
));
|
||||
let links = links_by_time(req, photos);
|
||||
return res.ok(|o| templates::place(o, req, &links, &place));
|
||||
let (links, coord) = links_by_time(req, photos);
|
||||
return res.ok(|o| templates::place(o, req, &links, &coord, &place));
|
||||
}
|
||||
res.not_found("Not a place")
|
||||
}
|
||||
@ -485,8 +485,8 @@ fn person_one<'mw>(
|
||||
.filter(person_id.eq(person.id)),
|
||||
),
|
||||
);
|
||||
let links = links_by_time(req, photos);
|
||||
return res.ok(|o| templates::person(o, req, &links, &person));
|
||||
let (links, coords) = links_by_time(req, photos);
|
||||
return res.ok(|o| templates::person(o, req, &links, &coords, &person));
|
||||
}
|
||||
res.not_found("Not a person")
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use super::PhotoLink;
|
||||
use super::views_by_date::query_date;
|
||||
use diesel::pg::{Pg, PgConnection};
|
||||
use diesel::prelude::*;
|
||||
use models::Photo;
|
||||
use models::{Coord, Photo};
|
||||
use nickel::Request;
|
||||
use nickel_diesel::DieselRequestExtensions;
|
||||
use schema::photos;
|
||||
@ -10,7 +10,7 @@ use schema::photos;
|
||||
pub fn links_by_time<'a>(
|
||||
req: &mut Request,
|
||||
photos: photos::BoxedQuery<'a, Pg>,
|
||||
) -> Vec<PhotoLink> {
|
||||
) -> (Vec<PhotoLink>, Vec<Coord>) {
|
||||
let c: &PgConnection = &req.db_conn();
|
||||
use schema::photos::dsl::date;
|
||||
let photos = if let Some(from_date) = query_date(req, "from") {
|
||||
@ -24,15 +24,33 @@ pub fn links_by_time<'a>(
|
||||
photos
|
||||
};
|
||||
let photos = photos.order(date.desc().nulls_last()).load(c).unwrap();
|
||||
if let Some(groups) = split_to_groups(&photos) {
|
||||
let path = req.path_without_query().unwrap_or("/");
|
||||
groups
|
||||
.iter()
|
||||
.map(|g| PhotoLink::for_group(g, path))
|
||||
.collect::<Vec<_>>()
|
||||
} else {
|
||||
photos.iter().map(PhotoLink::from).collect::<Vec<_>>()
|
||||
}
|
||||
(
|
||||
if let Some(groups) = split_to_groups(&photos) {
|
||||
let path = req.path_without_query().unwrap_or("/");
|
||||
groups
|
||||
.iter()
|
||||
.map(|g| PhotoLink::for_group(g, path))
|
||||
.collect()
|
||||
} else {
|
||||
photos.iter().map(PhotoLink::from).collect()
|
||||
},
|
||||
get_positions(&photos, c),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_positions(photos: &[Photo], c: &PgConnection) -> Vec<Coord> {
|
||||
use schema::positions::dsl::*;
|
||||
positions
|
||||
.filter(photo_id.eq_any(photos.iter().map(|p| p.id)))
|
||||
.select((latitude, longitude))
|
||||
.load(c)
|
||||
.unwrap_or_default() // TODO Log if there is a problem?
|
||||
.into_iter()
|
||||
.map(|(lat, long): (i32, i32)| Coord {
|
||||
x: f64::from(lat) / 1e6,
|
||||
y: f64::from(long) / 1e6,
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn split_to_groups(photos: &[Photo]) -> Option<Vec<&[Photo]>> {
|
||||
|
@ -190,6 +190,7 @@ pub fn all_null_date<'mw>(
|
||||
.iter()
|
||||
.map(PhotoLink::from)
|
||||
.collect::<Vec<_>>(),
|
||||
&[], // TODO: positions.
|
||||
)
|
||||
})
|
||||
}
|
||||
@ -207,7 +208,7 @@ pub fn all_for_day<'mw>(
|
||||
let photos = Photo::query(req.authorized_user().is_some())
|
||||
.filter(date.ge(thedate))
|
||||
.filter(date.lt(thedate + ChDuration::days(1)));
|
||||
let links = links_by_time(req, photos);
|
||||
let (links, coords) = links_by_time(req, photos);
|
||||
|
||||
if links.is_empty() {
|
||||
res.not_found("No such image")
|
||||
@ -219,6 +220,7 @@ pub fn all_for_day<'mw>(
|
||||
&format!("Photos from {} {} {}", day, monthname(month), year),
|
||||
&[Link::year(year), Link::month(year, month)],
|
||||
&links,
|
||||
&coords,
|
||||
)
|
||||
})
|
||||
}
|
||||
|
5
templates/data_positions.rs.html
Normal file
5
templates/data_positions.rs.html
Normal file
@ -0,0 +1,5 @@
|
||||
@use models::Coord;
|
||||
|
||||
@(coords: &[Coord])
|
||||
@if let Some((c, rest)) = coords.split_first()
|
||||
{ data-positions="[[@c.x,@c.y]@for c in rest {,[@c.x,@c.y]}]"}
|
@ -25,7 +25,6 @@
|
||||
@if let Some(ref pos) = *position {<p>Position: @pos.x @pos.y</p>}
|
||||
@if let Some(ref a) = *attribution {<p>Av: @a</p>}
|
||||
@if let Some(ref c) = *camera{<p>Camera: @c.model (@c.manufacturer)</p>}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
})
|
||||
|
@ -1,12 +1,13 @@
|
||||
@use ::Link;
|
||||
@use models::Coord;
|
||||
@use nickel::Request;
|
||||
@use server::PhotoLink;
|
||||
@use templates::{page_base, photo_link};
|
||||
@use templates::{data_positions, page_base, photo_link};
|
||||
|
||||
@(req: &Request, title: &str, lpath: &[Link], photos: &[PhotoLink])
|
||||
@(req: &Request, title: &str, lpath: &[Link], photos: &[PhotoLink], coords: &[Coord])
|
||||
|
||||
@:page_base(req, title, lpath, {
|
||||
<div class="group">
|
||||
<div class="group"@:data_positions(coords)>
|
||||
@for p in photos {@:photo_link(p)}
|
||||
</div>
|
||||
})
|
||||
|
@ -1,11 +1,11 @@
|
||||
@use nickel::Request;
|
||||
@use models::Person;
|
||||
@use models::{Coord, Person};
|
||||
@use server::PhotoLink;
|
||||
@use templates::{page_base, photo_link};
|
||||
@use templates::{data_positions, page_base, photo_link};
|
||||
|
||||
@(req: &Request, photos: &[PhotoLink], person: &Person)
|
||||
@(req: &Request, photos: &[PhotoLink], coords: &[Coord], person: &Person)
|
||||
@:page_base(req, &format!("Photos with {}", person.person_name), &[], {
|
||||
<div class="group">
|
||||
<div class="group"@:data_positions(coords)>
|
||||
@for p in photos {@:photo_link(p)}
|
||||
</div>
|
||||
})
|
||||
|
@ -1,11 +1,11 @@
|
||||
@use nickel::Request;
|
||||
@use models::{Place};
|
||||
@use models::{Coord, Place};
|
||||
@use server::PhotoLink;
|
||||
@use templates::{page_base, photo_link};
|
||||
@use templates::{data_positions, page_base, photo_link};
|
||||
|
||||
@(req: &Request, photos: &[PhotoLink], place: &Place)
|
||||
@(req: &Request, photos: &[PhotoLink], coords: &[Coord], place: &Place)
|
||||
@:page_base(req, &format!("Photos from {}", place.place_name), &[], {
|
||||
<div class="group">
|
||||
<div class="group"@:data_positions(coords)>
|
||||
@for p in photos {@:photo_link(p)}
|
||||
</div>
|
||||
})
|
||||
|
@ -1,12 +1,12 @@
|
||||
@use nickel::Request;
|
||||
@use models::Tag;
|
||||
@use models::{Coord, Tag};
|
||||
@use server::PhotoLink;
|
||||
@use templates::{page_base, photo_link};
|
||||
@use templates::{data_positions, page_base, photo_link};
|
||||
|
||||
@(req: &Request, photos: &[PhotoLink], tag: &Tag)
|
||||
@(req: &Request, photos: &[PhotoLink], coords: &[Coord], tag: &Tag)
|
||||
|
||||
@:page_base(req, &format!("Photos tagged {}", tag.tag_name), &[], {
|
||||
<div class="group">
|
||||
<div class="group"@:data_positions(coords)>
|
||||
@for p in photos {@:photo_link(p)}
|
||||
</div>
|
||||
})
|
||||
|
46
ux.js
46
ux.js
@ -19,30 +19,46 @@
|
||||
if (i) {
|
||||
i.addEventListener('click', e => { i.classList.toggle('zoom') });
|
||||
}
|
||||
function prepare_map(cb) {
|
||||
let h = d.querySelector('head');
|
||||
let m = d.querySelector('.meta') || d.querySelector('main');
|
||||
m.insertAdjacentHTML('beforeend', '<div id="map"></div>');
|
||||
var map = d.getElementById('map');
|
||||
map.style.height = 3 * map.clientWidth / 4 + "px";
|
||||
var slink = d.createElement('script');
|
||||
slink.type = 'text/javascript';
|
||||
slink.src = 'https://rasmus.krats.se/static/leaflet077c/leaflet.js';
|
||||
slink.async = 'async';
|
||||
slink.onload = cb;
|
||||
h.append(slink);
|
||||
var csslink = d.createElement('link');
|
||||
csslink.rel = 'stylesheet';
|
||||
csslink.href = 'https://rasmus.krats.se/static/leaflet077c/leaflet.css';
|
||||
h.append(csslink);
|
||||
}
|
||||
let details = d.querySelector('.details');
|
||||
let pos = details && details.dataset.position
|
||||
if (pos) {
|
||||
function initmap(pos) {
|
||||
var map = document.getElementById('map');
|
||||
map.style.height = 3 * map.clientWidth / 4 + "px";
|
||||
var map = L.map('map').setView(pos, 16);
|
||||
L.tileLayer('//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
}).addTo(map);
|
||||
L.marker(pos).addTo(map);
|
||||
}
|
||||
let h = d.querySelector('head');
|
||||
let m = d.querySelector('.meta');
|
||||
m.insertAdjacentHTML('beforeend', '<div id="map"></div>');
|
||||
var slink = document.createElement('script');
|
||||
slink.type = 'text/javascript';
|
||||
slink.src = 'https://rasmus.krats.se/static/leaflet077c/leaflet.js';
|
||||
slink.async = 'async';
|
||||
slink.onload = () => initmap(JSON.parse(pos));
|
||||
h.append(slink);
|
||||
var csslink = document.createElement('link');
|
||||
csslink.rel = 'stylesheet';
|
||||
csslink.href = 'https://rasmus.krats.se/static/leaflet077c/leaflet.css';
|
||||
h.append(csslink);
|
||||
prepare_map(() => initmap(JSON.parse(pos)))
|
||||
}
|
||||
let group = d.querySelector('.group');
|
||||
let poss = (details && details.dataset.positions) || (group && group.dataset.positions);
|
||||
if (poss) {
|
||||
function initmap(pos) {
|
||||
var map = L.map('map');
|
||||
map.fitBounds(L.polyline(pos).getBounds())
|
||||
L.tileLayer('//{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
attribution: '© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||
}).addTo(map);
|
||||
pos.forEach(p => L.marker(p).addTo(map));
|
||||
}
|
||||
prepare_map(() => initmap(JSON.parse(poss)))
|
||||
}
|
||||
})(document)
|
||||
|
Loading…
Reference in New Issue
Block a user