feature/tagging #16
@@ -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,
|
||||||
|
|||||||
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::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);
|
||||||
|
|
||||||
|
|||||||
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 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]
|
||||||
|
|||||||
Reference in New Issue
Block a user