feature/tagging #16

Merged
cameron merged 22 commits from feature/tagging into master 2023-04-10 12:55:28 +00:00
2 changed files with 47 additions and 5 deletions
Showing only changes of commit 8bcd9440bf - Show all commits

View File

@@ -489,6 +489,7 @@ fn main() -> std::io::Result<()> {
.route(web::delete().to(remove_tagged_photo::<SqliteTagDao>)),
)
.service(web::resource("image/tags/all").route(web::get().to(get_all_tags::<SqliteTagDao>)))
.service(web::resource("image/tags/batch").route(web::post().to(update_tags::<SqliteTagDao>)))
.app_data(app_data.clone())
.app_data::<Data<Mutex<SqliteUserDao>>>(Data::new(Mutex::new(user_dao)))
.app_data::<Data<Mutex<Box<dyn FavoriteDao>>>>(Data::new(Mutex::new(Box::new(

View File

@@ -5,7 +5,7 @@ use chrono::Utc;
use diesel::prelude::*;
use log::{debug, info};
use schema::{tagged_photo, tags};
use serde::Serialize;
use serde::{Deserialize, Serialize};
use std::borrow::BorrowMut;
use std::sync::Mutex;
@@ -70,7 +70,42 @@ pub async fn remove_tagged_photo<D: TagDao>(
.into_http_internal_err()
}
#[derive(Serialize, Queryable, Clone, Debug)]
pub async fn update_tags<D: TagDao>(_: Claims, tag_dao: web::Data<Mutex<D>>, request: web::Json<AddTagsRequest>) -> impl Responder {
let mut dao = tag_dao.lock()
.expect("Unable to get TagDao");
return dao.get_tags_for_path(&request.file_name)
.and_then(|existing_tags| {
dao.get_all_tags().map(|all| (existing_tags, all))
})
.and_then(|(existing_tags, all_tags)| {
let tags_to_remove = existing_tags.iter()
.filter(|&t| !request.tag_ids.contains(&t.id))
.collect::<Vec<&Tag>>();
for tag in tags_to_remove {
info!("Removing tag {:?} from file: {:?}", tag.name, request.file_name);
dao.remove_tag(&tag.name, &request.file_name)
.expect(&format!("Unable to remove tag {:?}", &tag.name));
}
let new_tags = all_tags.iter()
.filter(|&t| !existing_tags.contains(t) && request.tag_ids.contains(&t.id))
.collect::<Vec<&Tag>>();
for new_tag in new_tags {
info!("Adding tag {:?} to file: {:?}", new_tag.name, request.file_name);
dao.tag_file(&request.file_name, new_tag.id)
.with_context(|| format!("Unable to tag file {:?} with tag: {:?}", request.file_name, new_tag.name))
.unwrap();
}
Ok(HttpResponse::Ok())
}).into_http_internal_err()
}
#[derive(Serialize, Queryable, Clone, Debug, PartialEq)]
pub struct Tag {
pub id: i32,
pub name: String,
@@ -100,6 +135,12 @@ pub struct TaggedPhoto {
pub created_time: i64,
}
#[derive(Debug, Deserialize)]
pub struct AddTagsRequest {
pub file_name: String,
pub tag_ids: Vec<i32>,
}
pub trait TagDao {
fn get_all_tags(&mut self) -> anyhow::Result<Vec<Tag>>;
fn get_tags_for_path(&mut self, path: &str) -> anyhow::Result<Vec<Tag>>;
@@ -184,9 +225,9 @@ impl TagDao for SqliteTagDao {
.filter(tagged_photo::tag_id.eq(tag.id))
.filter(tagged_photo::photo_name.eq(path)),
)
.execute(&mut self.connection)
.with_context(|| format!("Unable to delete tag: '{}'", &tag.name))
.map(|_| Some(()))
.execute(&mut self.connection)
.with_context(|| format!("Unable to delete tag: '{}'", &tag.name))
.map(|_| Some(()))
} else {
info!("No tag found with name '{}'", tag_name);
Ok(None)