Add UX to note people in pictures.
This commit is contained in:
parent
328074c0b6
commit
884ffe7e02
91
admin.js
91
admin.js
@ -31,11 +31,12 @@ function rpadmin() {
|
||||
|
||||
var list;
|
||||
|
||||
function tag_form(event) {
|
||||
function tag_form(event, category) {
|
||||
event.target.disabled = true;
|
||||
var imgid = details.dataset.imgid;
|
||||
var f = document.createElement("form");
|
||||
f.action = "/adm/tag";
|
||||
f.className = category;
|
||||
f.action = "/adm/" + category;
|
||||
f.method = "post";
|
||||
var i = document.createElement("input");
|
||||
i.type="hidden";
|
||||
@ -46,8 +47,43 @@ function rpadmin() {
|
||||
i.type = "text";
|
||||
i.autocomplete="off";
|
||||
i.tabindex="1";
|
||||
i.name = "tag";
|
||||
i.addEventListener('keyup', do_complete);
|
||||
i.name = category;
|
||||
i.addEventListener('keyup', e => {
|
||||
let c = e.code;
|
||||
if (c == 'ArrowUp' || c == 'ArrowDown' || c == 'Escape' || c == 'Enter') {
|
||||
return true;
|
||||
}
|
||||
let i = e.target, v = i.value;
|
||||
if (v.length > 0) {
|
||||
let r = new XMLHttpRequest();
|
||||
r.onload = function() {
|
||||
let t = JSON.parse(this.responseText);
|
||||
list.innerHTML = '';
|
||||
t.map(x => {
|
||||
let a = document.createElement('a');
|
||||
a.innerHTML = x;
|
||||
a.tabIndex = 2;
|
||||
a.href = "#";
|
||||
a.onclick = function(e) {
|
||||
i.value = x;
|
||||
list.innerHTML = '';
|
||||
i.focus();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
list.appendChild(a)
|
||||
})
|
||||
};
|
||||
r.open('GET', document.location.origin + '/ac/' + category + '?q=' + encodeURIComponent(v));
|
||||
r.send(null);
|
||||
} else {
|
||||
list.innerHTML = '';
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
f.appendChild(i);
|
||||
list = document.createElement("div");
|
||||
list.className = "completions";
|
||||
@ -76,43 +112,6 @@ function rpadmin() {
|
||||
i.focus();
|
||||
}
|
||||
|
||||
function do_complete(e) {
|
||||
let c = e.code;
|
||||
if (c == 'ArrowUp' || c == 'ArrowDown' || c == 'Escape' || c == 'Enter') {
|
||||
return true;
|
||||
}
|
||||
let i = e.target, v = i.value;
|
||||
if (v.length > 0) {
|
||||
let r = new XMLHttpRequest();
|
||||
r.onload = function() {
|
||||
let t = JSON.parse(this.responseText);
|
||||
list.innerHTML = '';
|
||||
t.map(x => {
|
||||
let a = document.createElement('a');
|
||||
a.innerHTML = x;
|
||||
a.tabIndex = 2;
|
||||
a.href = "#";
|
||||
a.onclick = function(e) {
|
||||
i.value = x;
|
||||
list.innerHTML = '';
|
||||
i.focus();
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return true;
|
||||
}
|
||||
list.appendChild(a)
|
||||
})
|
||||
};
|
||||
r.open('GET', document.location.origin + '/ac?q=' + encodeURIComponent(v));
|
||||
r.send(null);
|
||||
} else {
|
||||
list.innerHTML = '';
|
||||
}
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
var meta = details.querySelector('.meta');
|
||||
if (meta) {
|
||||
p = document.createElement("p");
|
||||
@ -132,11 +131,19 @@ function rpadmin() {
|
||||
|
||||
p.appendChild(document.createTextNode(" "));
|
||||
r = document.createElement("button");
|
||||
r.onclick = tag_form;
|
||||
r.onclick = e => tag_form(e, 'tag');
|
||||
r.innerHTML = "🏷";
|
||||
r.title = "Tag photo";
|
||||
r.accessKey = "T";
|
||||
p.appendChild(r);
|
||||
|
||||
p.appendChild(document.createTextNode(" "));
|
||||
r = document.createElement("button");
|
||||
r.onclick = e => tag_form(e, 'person');
|
||||
r.innerHTML = "\u263a";
|
||||
r.title = "Person in picture";
|
||||
r.accessKey = "P";
|
||||
p.appendChild(r);
|
||||
meta.appendChild(p);
|
||||
}
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ fn rotate_params(req: &mut Request) -> QResult<(Option<i32>, Option<i16>)> {
|
||||
))
|
||||
}
|
||||
|
||||
pub fn tag<'mw>(
|
||||
pub fn set_tag<'mw>(
|
||||
req: &mut Request,
|
||||
res: Response<'mw>,
|
||||
) -> MiddlewareResult<'mw> {
|
||||
@ -101,6 +101,59 @@ fn tag_params(req: &mut Request) -> QResult<(Option<i32>, Option<String>)> {
|
||||
))
|
||||
}
|
||||
|
||||
pub fn set_person<'mw>(
|
||||
req: &mut Request,
|
||||
res: Response<'mw>,
|
||||
) -> MiddlewareResult<'mw> {
|
||||
if !req.authorized_user().is_some() {
|
||||
return res.error(StatusCode::Unauthorized, "permission denied");
|
||||
}
|
||||
if let (Some(image), Some(name)) = try_with!(res, person_params(req)) {
|
||||
let c: &PgConnection = &req.db_conn();
|
||||
use diesel;
|
||||
use models::{NewPerson, NewPhotoPerson, Person, PhotoPerson};
|
||||
let person = {
|
||||
use schema::people::dsl::*;
|
||||
people
|
||||
.filter(person_name.ilike(&name))
|
||||
.first::<Person>(c)
|
||||
.or_else(|_| {
|
||||
diesel::insert(&NewPerson {
|
||||
person_name: &name,
|
||||
slug: &slugify(&name),
|
||||
}).into(people)
|
||||
.get_result::<Person>(c)
|
||||
})
|
||||
.expect("Find or create tag")
|
||||
};
|
||||
use schema::photo_people::dsl::*;
|
||||
let q = photo_people
|
||||
.filter(photo_id.eq(image))
|
||||
.filter(person_id.eq(person.id));
|
||||
if q.first::<PhotoPerson>(c).is_ok() {
|
||||
info!("Photo #{} already has {:?}", image, person);
|
||||
} else {
|
||||
info!("Add {:?} on photo #{}!", person, image);
|
||||
diesel::insert(
|
||||
&NewPhotoPerson { photo_id: image, person_id: person.id },
|
||||
).into(photo_people)
|
||||
.execute(c)
|
||||
.expect("Name person in photo");
|
||||
}
|
||||
return res.redirect(format!("/img/{}", image));
|
||||
}
|
||||
info!("Missing image and/or angle to rotate or image not found");
|
||||
res.not_found("")
|
||||
}
|
||||
|
||||
fn person_params(req: &mut Request) -> QResult<(Option<i32>, Option<String>)> {
|
||||
let data = req.form_body()?;
|
||||
Ok((
|
||||
data.get("image").and_then(|s| s.parse().ok()),
|
||||
data.get("person").map(String::from),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn slugify(val: &str) -> String {
|
||||
val.chars()
|
||||
.map(|c| match c {
|
||||
|
@ -33,6 +33,7 @@ use photosdirmiddleware::{PhotosDirMiddleware, PhotosDirRequestExtensions};
|
||||
use memcachemiddleware::*;
|
||||
|
||||
use pidfiles::handle_pid_file;
|
||||
use rustc_serialize::json::ToJson;
|
||||
use templates;
|
||||
|
||||
use self::nickelext::{FromSlug, MyResponse, far_expires};
|
||||
@ -74,10 +75,12 @@ pub fn run(args: &ArgMatches) -> Result<(), Error> {
|
||||
wrap3!(server.post "/login", do_login);
|
||||
wrap3!(server.get "/logout", logout);
|
||||
wrap3!(server.get "/", all_years);
|
||||
use self::admin::{rotate, tag};
|
||||
wrap3!(server.get "/ac", auto_complete);
|
||||
use self::admin::{rotate, set_person, set_tag};
|
||||
wrap3!(server.get "/ac/tag", auto_complete_tag);
|
||||
wrap3!(server.get "/ac/person", auto_complete_person);
|
||||
wrap3!(server.post "/adm/rotate", rotate);
|
||||
wrap3!(server.post "/adm/tag", tag);
|
||||
wrap3!(server.post "/adm/tag", set_tag);
|
||||
wrap3!(server.post "/adm/person", set_person);
|
||||
wrap3!(server.get "/img/{}[-]{}\\.jpg", show_image: id, size);
|
||||
wrap3!(server.get "/img/{}", photo_details: id);
|
||||
wrap3!(server.get "/tag/", tag_all);
|
||||
@ -609,12 +612,11 @@ impl Link {
|
||||
}
|
||||
}
|
||||
|
||||
fn auto_complete<'mw>(
|
||||
fn auto_complete_tag<'mw>(
|
||||
req: &mut Request,
|
||||
res: Response<'mw>,
|
||||
) -> MiddlewareResult<'mw> {
|
||||
if let Some(q) = req.query().get("q").map(String::from) {
|
||||
use rustc_serialize::json::ToJson;
|
||||
use schema::tags::dsl::{tag_name, tags};
|
||||
let c: &PgConnection = &req.db_conn();
|
||||
let q = tags.select(tag_name)
|
||||
@ -626,3 +628,21 @@ fn auto_complete<'mw>(
|
||||
res.not_found("No such tag")
|
||||
}
|
||||
}
|
||||
|
||||
fn auto_complete_person<'mw>(
|
||||
req: &mut Request,
|
||||
res: Response<'mw>,
|
||||
) -> MiddlewareResult<'mw> {
|
||||
if let Some(q) = req.query().get("q").map(String::from) {
|
||||
use schema::people::dsl::{people, person_name};
|
||||
let c: &PgConnection = &req.db_conn();
|
||||
let q = people
|
||||
.select(person_name)
|
||||
.filter(person_name.ilike(q + "%"))
|
||||
.order(person_name)
|
||||
.limit(15);
|
||||
res.send(q.load::<String>(c).unwrap().to_json())
|
||||
} else {
|
||||
res.not_found("No such tag")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user