Summarize images per year and month.

This commit is contained in:
Rasmus Kaj 2016-01-31 21:15:44 +01:00
parent 84987eca40
commit b340bb5f9d
4 changed files with 138 additions and 31 deletions

View File

@ -19,7 +19,7 @@ use hyper::header::{Expires, HttpDate};
use nickel::{MediaType, Nickel, StaticFilesHandler}; use nickel::{MediaType, Nickel, StaticFilesHandler};
use plugin::{Pluggable}; use plugin::{Pluggable};
use rustc_serialize::Encodable; use rustc_serialize::Encodable;
use rustorm::query::Query; use rustorm::query::{Query, Filter};
use time::Duration; use time::Duration;
mod models; mod models;
@ -69,6 +69,32 @@ fn orm_get_related<T: Entity, Src: Entity>(src: &Src, rel_table: &str)
q q
} }
#[derive(Debug, Clone, RustcEncodable)]
struct Group {
title: String,
url: String,
count: i64,
photo: Photo,
}
fn monthname(n: u8) -> &'static str {
match n {
1 => "january",
2 => "february",
3 => "march",
4 => "april",
5 => "may",
6 => "june",
7 => "july",
8 => "august",
9 => "september",
10 => "october",
11 => "november",
12 => "december",
_ => "non-month"
}
}
fn main() { fn main() {
env_logger::init().unwrap(); env_logger::init().unwrap();
info!("Initalized logger"); info!("Initalized logger");
@ -80,12 +106,32 @@ fn main() {
server.utilize(RustormMiddleware::new(&dburl())); server.utilize(RustormMiddleware::new(&dburl()));
server.utilize(router! { server.utilize(router! {
get "/" => |req, res| { get "/" => |req, res| {
return render!(res, "templates/index.tpl", { return render!(res, "templates/groups.tpl", {
photos: Vec<Photo> = query_for::<Photo>() title: &'static str = "All photos",
.desc_nulls_last("grade") groups: Vec<Group> = {
.desc_nulls_last("date") query_for::<Photo>()
.limit(24) .columns(vec!("extract(year from date) y", "count(*) c"))
.collect(req.db_conn()).unwrap() .add_filter(Filter::is_not_null("date"))
.group_by(vec!("y")).asc("y")
.retrieve(req.db_conn()).expect("Get images per year")
.dao.iter().map(|dao| {
debug!("Got a pregroup: {:?}", dao);
let year = dao.get::<f64>("y") as u16;
let count : i64 = dao.get("c");
let photo : Photo = query_for::<Photo>()
.filter_eq("extract(year from date)", &(year as f64))
.desc_nulls_last("grade")
.asc_nulls_last("date")
.limit(1)
.collect_one(req.db_conn()).unwrap();
Group {
title: format!("{}", year),
url: format!("/{}/", year),
count: count,
photo: photo
}
}).collect()
}
}); });
} }
get "/details/:id" => |req, res| { get "/details/:id" => |req, res| {
@ -189,40 +235,79 @@ fn main() {
} }
get "/:year/" => |req, res| { get "/:year/" => |req, res| {
if let Ok(year) = req.param("year").unwrap().parse::<i32>() { if let Ok(year) = req.param("year").unwrap().parse::<i32>() {
let date = UTC.ymd(year, 1, 1).and_hms(0,0,0); return render!(res, "templates/groups.tpl", {
return render!(res, "templates/index.tpl", { title: String = format!("Photos from {}", year),
photos: Vec<Photo> = query_for::<Photo>() groups: Vec<Group> = {
.filter_gte("date", &date) let m = query_for::<Photo>()
.filter_lt("date", &(date + ChDuration::days(366))) .columns(vec!("extract(month from date) m", "count(*) c"))
.desc_nulls_last("grade") .filter_eq("extract(year from date)", &(year as f64))
.asc_nulls_last("date") .group_by(vec!("m")).asc("m")
.limit(36) .retrieve(req.db_conn()).expect("Get images per month");
.collect(req.db_conn()).unwrap() m.dao.iter().map(|dao| {
let month = dao.get::<f64>("m") as u8;
let count : i64 = dao.get("c");
let photo : Photo = query_for::<Photo>()
.filter_eq("extract(year from date)", &(year as f64))
.filter_eq("extract(month from date)", &(month as f64))
.desc_nulls_last("grade")
.asc_nulls_last("date")
.limit(1)
.collect_one(req.db_conn()).unwrap();
Group {
title: monthname(month).to_string(),
url: format!("/{}/{}/", year, month),
count: count,
photo: photo
}
}).collect()
}
}); });
} }
} }
get "/:year/:month/" => |req, res| { get "/:year/:month/" => |req, res| {
if let Ok(year) = req.param("year").unwrap().parse::<i32>() { if let Ok(year) = req.param("year").unwrap().parse::<i32>() {
if let Ok(month) = req.param("month").unwrap().parse::<u32>() { if let Ok(month) = req.param("month").unwrap().parse::<u8>() {
let date = UTC.ymd(year, month, 1).and_hms(0,0,0); return render!(res, "templates/groups.tpl", {
return render!(res, "templates/index.tpl", { title: String = format!("Photos from {} {}", monthname(month),
photos: Vec<Photo> = query_for::<Photo>() year),
.filter_gte("date", &date) groups: Vec<Group> = {
.filter_lt("date", &(date + ChDuration::days(31))) let m = query_for::<Photo>()
.desc_nulls_last("grade") .columns(vec!("extract(day from date) d", "count(*) c"))
.asc_nulls_last("date") .filter_eq("extract(year from date)", &(year as f64))
.limit(36) .filter_eq("extract(month from date)", &(month as f64))
.collect(req.db_conn()).unwrap() .group_by(vec!("d")).asc("d")
.retrieve(req.db_conn()).expect("Get images per day");
m.dao.iter().map(|dao| {
let day = dao.get::<f64>("d") as u8;
let count : i64 = dao.get("c");
let photo : Photo = query_for::<Photo>()
.filter_eq("extract(year from date)", &(year as f64))
.filter_eq("extract(month from date)", &(month as f64))
.filter_eq("extract(day from date)", &(day as f64))
.desc_nulls_last("grade")
.asc_nulls_last("date")
.limit(1)
.collect_one(req.db_conn()).unwrap();
Group {
title: format!("{}/{}", day, month),
url: format!("/{}/{}/{}", year, month, day),
count: count,
photo: photo
}
}).collect()
}
}); });
} }
} }
} }
get "/:year/:month/:day" => |req, res| { get "/:year/:month/:day" => |req, res| {
if let Ok(year) = req.param("year").unwrap().parse::<i32>() { if let Ok(year) = req.param("year").unwrap().parse::<i32>() {
if let Ok(month) = req.param("month").unwrap().parse::<u32>() { if let Ok(month) = req.param("month").unwrap().parse::<u8>() {
if let Ok(day) = req.param("day").unwrap().parse::<u32>() { if let Ok(day) = req.param("day").unwrap().parse::<u32>() {
let date = UTC.ymd(year, month, day).and_hms(0,0,0); let date = UTC.ymd(year, month as u32, day).and_hms(0,0,0);
return render!(res, "templates/index.tpl", { return render!(res, "templates/index.tpl", {
title: String = format!("Photos from {} {} {}",
day, monthname(month), year),
photos: Vec<Photo> = query_for::<Photo>() photos: Vec<Photo> = query_for::<Photo>()
.filter_gte("date", &date) .filter_gte("date", &date)
.filter_lt("date", &(date + ChDuration::days(1))) .filter_lt("date", &(date + ChDuration::days(1)))

View File

@ -5,10 +5,11 @@ header {
border-bottom: 1px solid #aaa; border-bottom: 1px solid #aaa;
} }
div.photos { div.groups, div.photos {
display: flex; display: flex;
flex-flow: row wrap; flex-flow: row wrap;
} }
div.groups div.group,
div.photos p { div.photos p {
border: 1px solid #666; border: 1px solid #666;
flex-basis: 210px; flex-basis: 210px;

21
templates/groups.tpl Normal file
View File

@ -0,0 +1,21 @@
<!doctype html>
<html>
<head>
<title>{{title}}</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="/static/photos.css" type="text/css"/>
</head>
<body>
{{> head}}
<h1>{{title}}</h1>
<div class="groups">
{{#groups}}
<div class="group"><h2>{{title}}</h2>
<p><a href="{{url}}"><img src="/img/{{photo.id}}/s"></a></p>
<p>{{count}} pictures</p>
</div>
{{/groups}}
</div>
</body>
</html>

View File

@ -1,13 +1,13 @@
<!doctype html> <!doctype html>
<html> <html>
<head> <head>
<title>Photo index</title> <title>{{title}}</title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<link rel="stylesheet" href="/static/photos.css" type="text/css"/> <link rel="stylesheet" href="/static/photos.css" type="text/css"/>
</head> </head>
<body> <body>
{{> head}} {{> head}}
<h1>Photo index</h1> <h1>{{title}}</h1>
<div class="photos"> <div class="photos">
{{#photos}} {{#photos}}