feature/tagging #16
@@ -107,7 +107,7 @@ pub struct FilesRequest {
|
||||
pub tag_filter_mode: Option<FilterMode>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Deserialize)]
|
||||
#[derive(Copy, Clone, Deserialize, PartialEq)]
|
||||
pub enum FilterMode {
|
||||
Any,
|
||||
All,
|
||||
|
||||
29
src/files.rs
29
src/files.rs
@@ -16,6 +16,7 @@ use log::{debug, error};
|
||||
use crate::data::{Claims, FilesRequest, FilterMode, PhotosResponse};
|
||||
use crate::AppState;
|
||||
|
||||
use crate::error::IntoHttpError;
|
||||
use crate::tags::TagDao;
|
||||
use path_absolutize::*;
|
||||
|
||||
@@ -28,6 +29,34 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
|
||||
) -> HttpResponse {
|
||||
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) {
|
||||
debug!("Valid path: {:?}", path);
|
||||
|
||||
|
||||
18
src/tags.rs
18
src/tags.rs
@@ -177,6 +177,7 @@ pub trait TagDao {
|
||||
fn create_tag(&mut self, name: &str) -> anyhow::Result<Tag>;
|
||||
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 get_files_with_tag_ids(&mut self, tag_ids: Vec<i32>) -> anyhow::Result<Vec<String>>;
|
||||
}
|
||||
|
||||
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)]
|
||||
@@ -407,6 +421,10 @@ mod tests {
|
||||
Err(NotFound.into())
|
||||
}
|
||||
}
|
||||
|
||||
fn get_files_with_tag_ids(&mut self, _tag_ids: Vec<i32>) -> anyhow::Result<Vec<String>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_rt::test]
|
||||
|
||||
Reference in New Issue
Block a user