diff --git a/crates/app/storyteller_web/src/database/query_builders/list_categories_query_builder.rs b/crates/app/storyteller_web/src/database/query_builders/list_categories_query_builder.rs index 4fe812c300..45fb053720 100644 --- a/crates/app/storyteller_web/src/database/query_builders/list_categories_query_builder.rs +++ b/crates/app/storyteller_web/src/database/query_builders/list_categories_query_builder.rs @@ -57,6 +57,16 @@ pub struct ListCategoriesQueryBuilder { // will want to see them. show_deleted: bool, + // Filter out approved records. + // Useful as a moderation filter. + // Doesn't make sense to use with `show_unapproved`, but don't want to refactor atm. + hide_approved: bool, + + // Filter out records with a non-deleted timestamp. + // Useful as a moderation filter. + // Doesn't make sense to use with `show_deleted`, but don't want to refactor atm. + hide_non_deleted: bool, + // Useful for showing categories a user themselves has suggested // We don't want users spamming creation. scope_creator_user_token: Option, @@ -71,6 +81,8 @@ impl ListCategoriesQueryBuilder { Self { show_unapproved: false, show_deleted: false, + hide_approved: false, + hide_non_deleted: false, scope_creator_user_token: None, scope_model_type: None, } @@ -86,6 +98,16 @@ impl ListCategoriesQueryBuilder { self } + pub fn hide_approved(mut self, hide_approved: bool) -> Self { + self.hide_approved = hide_approved; + self + } + + pub fn hide_non_deleted(mut self, hide_non_deleted: bool) -> Self { + self.hide_non_deleted = hide_non_deleted; + self + } + pub fn scope_creator_user_token(mut self, scope_creator_user_token: Option<&str>) -> Self { self.scope_creator_user_token = scope_creator_user_token.map(|u| u.to_string()); self @@ -244,6 +266,24 @@ LEFT OUTER JOIN users } } + if self.hide_approved { + if !first_predicate_added { + query.push_str(" WHERE (model_categories.is_mod_approved IS NULL OR model_categories.is_mod_approved IS FALSE) "); + first_predicate_added = true; + } else { + query.push_str(" AND (model_categories.is_mod_approved IS NULL OR model_categories.is_mod_approved IS FALSE) "); + } + } + + if self.hide_non_deleted { + if !first_predicate_added { + query.push_str(" WHERE model_categories.deleted_at IS NOT NULL"); + first_predicate_added = true; + } else { + query.push_str(" AND model_categories.deleted_at IS NOT NULL"); + } + } + query } } diff --git a/crates/app/storyteller_web/src/http_server/endpoints/moderation/categories/list_tts_categories_for_moderation.rs b/crates/app/storyteller_web/src/http_server/endpoints/moderation/categories/list_tts_categories_for_moderation.rs index 6b97bbf76c..d6f9476232 100644 --- a/crates/app/storyteller_web/src/http_server/endpoints/moderation/categories/list_tts_categories_for_moderation.rs +++ b/crates/app/storyteller_web/src/http_server/endpoints/moderation/categories/list_tts_categories_for_moderation.rs @@ -29,6 +29,26 @@ use sqlx::mysql::MySqlDatabaseError; use std::fmt; use std::sync::Arc; +// =============== Request =============== + +#[derive(Deserialize, Copy, Clone, Debug)] +#[serde(rename_all = "snake_case")] +pub enum ViewState { + /// 'exclude'; keep the objects out + Exclude, + /// 'include'; include the objects + Include, + /// 'only'; limit to just the objects + Only, +} + +// Only show approved&non-deleted , only show un-approved, only show deleted +#[derive(Deserialize)] +pub struct QueryParams { + deleted: Option, + unapproved: Option, +} + // =============== Success Response =============== #[derive(Serialize)] @@ -98,6 +118,7 @@ impl fmt::Display for ListTtsCategoriesForModerationError { pub async fn list_tts_categories_for_moderation_handler( http_request: HttpRequest, + query: web::Query, server_state: web::Data>) -> Result { let maybe_user_session = server_state @@ -123,11 +144,25 @@ pub async fn list_tts_categories_for_moderation_handler( return Err(ListTtsCategoriesForModerationError::NotAuthorized); } - let query_builder = ListCategoriesQueryBuilder::new() - .show_deleted(true) - .show_unapproved(true) + // The objects we'll show or hide + let delete_state = query.deleted.unwrap_or(ViewState::Exclude); + let unapproved_state = query.unapproved.unwrap_or(ViewState::Include); + + let mut query_builder = ListCategoriesQueryBuilder::new() .scope_model_type(Some("tts")); - + + query_builder = match delete_state { + ViewState::Exclude => query_builder.show_deleted(false), + ViewState::Include => query_builder.show_deleted(true), + ViewState::Only => query_builder.show_deleted(true).hide_non_deleted(true), + }; + + query_builder = match unapproved_state { + ViewState::Exclude => query_builder.show_unapproved(false), + ViewState::Include => query_builder.show_unapproved(true), + ViewState::Only => query_builder.show_unapproved(true).hide_approved(true), + }; + let query_result = query_builder.perform_query(&server_state.mysql_pool).await;