feature/tagging #16

Merged
cameron merged 22 commits from feature/tagging into master 2023-04-10 12:55:28 +00:00
3 changed files with 48 additions and 1 deletions
Showing only changes of commit a9109fc52d - Show all commits

View File

@@ -107,7 +107,7 @@ pub struct FilesRequest {
pub tag_filter_mode: Option<FilterMode>, pub tag_filter_mode: Option<FilterMode>,
} }
#[derive(Copy, Clone, Deserialize)] #[derive(Copy, Clone, Deserialize, PartialEq)]
pub enum FilterMode { pub enum FilterMode {
Any, Any,
All, All,

View File

@@ -16,6 +16,7 @@ use log::{debug, error};
use crate::data::{Claims, FilesRequest, FilterMode, PhotosResponse}; use crate::data::{Claims, FilesRequest, FilterMode, PhotosResponse};
use crate::AppState; use crate::AppState;
use crate::error::IntoHttpError;
use crate::tags::TagDao; use crate::tags::TagDao;
use path_absolutize::*; use path_absolutize::*;
@@ -28,6 +29,34 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
) -> HttpResponse { ) -> HttpResponse {
let path = &req.path; let path = &req.path;
if let (Some(tag_ids), Some(filter_mode)) = (&req.tag_ids, &req.tag_filter_mode) {
if *filter_mode == FilterMode::All {
let mut dao = tag_dao.lock().expect("Unable to get TagDao");
let tag_ids = tag_ids
.split(',')
.filter_map(|t| t.parse().ok())
.collect::<Vec<i32>>();
return dao
.get_files_with_tag_ids(tag_ids.clone())
.map(|tagged_file| {
tagged_file
.iter()
.map(|photo_name| photo_name.clone())
.collect()
})
.context(format!("Failed to files with tag_ids: {:?}", tag_ids))
.map(|tagged_files| {
HttpResponse::Ok().json(PhotosResponse {
photos: tagged_files,
dirs: vec![],
})
})
.into_http_internal_err()
.unwrap_or_else(|e| e.error_response());
}
}
if let Ok(files) = file_system.get_files_for_path(path) { if let Ok(files) = file_system.get_files_for_path(path) {
debug!("Valid path: {:?}", path); debug!("Valid path: {:?}", path);

View File

@@ -177,6 +177,7 @@ pub trait TagDao {
fn create_tag(&mut self, name: &str) -> anyhow::Result<Tag>; fn create_tag(&mut self, name: &str) -> anyhow::Result<Tag>;
fn remove_tag(&mut self, tag_name: &str, path: &str) -> anyhow::Result<Option<()>>; fn remove_tag(&mut self, tag_name: &str, path: &str) -> anyhow::Result<Option<()>>;
fn tag_file(&mut self, path: &str, tag_id: i32) -> anyhow::Result<TaggedPhoto>; fn tag_file(&mut self, path: &str, tag_id: i32) -> anyhow::Result<TaggedPhoto>;
fn get_files_with_tag_ids(&mut self, tag_ids: Vec<i32>) -> anyhow::Result<Vec<String>>;
} }
pub struct SqliteTagDao { pub struct SqliteTagDao {
@@ -294,6 +295,19 @@ impl TagDao for SqliteTagDao {
}) })
}) })
} }
fn get_files_with_tag_ids(&mut self, tag_ids: Vec<i32>) -> anyhow::Result<Vec<String>> {
use diesel::dsl::*;
tagged_photo::table
.filter(tagged_photo::tag_id.eq_any(tag_ids.clone()))
.group_by(tagged_photo::photo_name)
.select((tagged_photo::photo_name, count(tagged_photo::tag_id)))
.having(count(tagged_photo::tag_id).eq(tag_ids.len() as i64))
.select(tagged_photo::photo_name)
.get_results::<String>(&mut self.connection)
.with_context(|| format!("Unable to get Tagged photos with ids: {:?}", tag_ids))
}
} }
#[cfg(test)] #[cfg(test)]
@@ -407,6 +421,10 @@ mod tests {
Err(NotFound.into()) Err(NotFound.into())
} }
} }
fn get_files_with_tag_ids(&mut self, _tag_ids: Vec<i32>) -> anyhow::Result<Vec<String>> {
todo!()
}
} }
#[actix_rt::test] #[actix_rt::test]