diff --git a/migrations/2023-03-12-100253_create_translation/up.sql b/migrations/2023-03-12-100253_create_translation/up.sql index e6d0c16..1e598a5 100644 --- a/migrations/2023-03-12-100253_create_translation/up.sql +++ b/migrations/2023-03-12-100253_create_translation/up.sql @@ -1,6 +1,7 @@ CREATE TABLE translations ( id serial NOT NULL, uuid uuid DEFAULT uuid_generate_v4 () NOT NULL, + mushaf_id serial NOT NULL, creator_user_id serial NOT NULL, translator_account_id serial NOT NULL, language VARCHAR(5) NOT NULL, @@ -9,6 +10,7 @@ CREATE TABLE translations ( created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT translation_fk_user_id_rel FOREIGN KEY(creator_user_id) REFERENCES app_users(id), + CONSTRAINT translation_mushaf_fk_id_rel FOREIGN KEY(mushaf_id) REFERENCES mushafs(id), CONSTRAINT translation_id PRIMARY KEY (id), CONSTRAINT fk_translator_account_rel FOREIGN KEY(translator_account_id) REFERENCES app_accounts(id) ); diff --git a/src/models.rs b/src/models.rs index 82a1f29..91fc653 100644 --- a/src/models.rs +++ b/src/models.rs @@ -431,6 +431,8 @@ pub struct Translation { pub translator_account_id: i32, + pub mushaf_id: i32, + pub language: String, pub release_date: Option, pub source: Option, diff --git a/src/models_filter.rs b/src/models_filter.rs index 7e8c8d3..6dd293f 100644 --- a/src/models_filter.rs +++ b/src/models_filter.rs @@ -1,7 +1,11 @@ -use crate::models::{QuranMushaf, QuranSurah, Translation}; -use crate::schema::mushafs::{table as quran_mushafs_table, BoxedQuery as MushafBoxedQuery}; -use crate::schema::quran_surahs::{table as quran_surahs_table, BoxedQuery as SurahBoxedQuery}; -use crate::schema::translations::{table as translations_table, BoxedQuery as TranslationBoxedQuery}; +use crate::models::{QuranAyah, QuranMushaf, QuranSurah, QuranWord, Translation}; +use crate::schema::mushafs::BoxedQuery as MushafBoxedQuery; +use crate::schema::quran_ayahs::BoxedQuery as AyahBoxedQuery; +use crate::schema::quran_surahs::BoxedQuery as SurahBoxedQuery; +use crate::schema::quran_words::BoxedQuery as WordBoxedQuery; +use crate::schema::translations::{ + table as translations_table, BoxedQuery as TranslationBoxedQuery, +}; use crate::{ error::RouterError, filter::{Filter, Filters, Order}, @@ -32,7 +36,7 @@ impl Filter for QuranSurah { fn filter(filters: Box) -> Self::Output { use crate::schema::quran_surahs::dsl::*; - let mut _query = quran_surahs_table.into_boxed(); + let mut _query = quran_surahs.into_boxed(); _query = match filters.sort() { Some(sort_str) => match sort_str.as_str() { @@ -46,6 +50,16 @@ impl Filter for QuranSurah { Order::Desc => quran_surahs.order(number.desc()).internal_into_boxed(), }), + "createTime" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => quran_surahs.order(created_at.asc()).internal_into_boxed(), + Order::Desc => quran_surahs.order(created_at.desc()).internal_into_boxed(), + }), + + "updateTime" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => quran_surahs.order(updated_at.asc()).internal_into_boxed(), + Order::Desc => quran_surahs.order(updated_at.desc()).internal_into_boxed(), + }), + value => Err(RouterError::BadRequest(format!( "Sort value {} is not possible!", value @@ -66,13 +80,103 @@ impl Filter for QuranSurah { } } +impl Filter for QuranAyah { + type Output = Result, RouterError>; + + fn filter(filters: Box) -> Self::Output { + use crate::schema::quran_ayahs::dsl::*; + + let mut _query = quran_ayahs.into_boxed(); + + _query = match filters.sort() { + Some(sort_str) => match sort_str.as_str() { + "number" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => quran_ayahs.order(ayah_number.asc()).internal_into_boxed(), + Order::Desc => quran_ayahs.order(ayah_number.desc()).internal_into_boxed(), + }), + + "createTime" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => quran_ayahs.order(created_at.asc()).internal_into_boxed(), + Order::Desc => quran_ayahs.order(created_at.desc()).internal_into_boxed(), + }), + + "updateTime" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => quran_ayahs.order(updated_at.asc()).internal_into_boxed(), + Order::Desc => quran_ayahs.order(updated_at.desc()).internal_into_boxed(), + }), + + value => Err(RouterError::BadRequest(format!( + "Sort value {} is not possible!", + value + ))), + }, + + None => Ok(quran_ayahs.internal_into_boxed()), + }?; + + _query = match filters.to() { + Some(limit) => _query + .limit(limit as i64) + .offset(filters.from().unwrap_or_default() as i64), + None => _query.offset(filters.from().unwrap_or_default() as i64), + }; + + Ok(_query) + } +} + +impl Filter for QuranWord { + type Output = Result, RouterError>; + + fn filter(filters: Box) -> Self::Output { + use crate::schema::quran_words::dsl::*; + + let mut _query = quran_words.into_boxed(); + + _query = match filters.sort() { + Some(sort_str) => match sort_str.as_str() { + "createTime" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => quran_words.order(created_at.asc()).internal_into_boxed(), + Order::Desc => quran_words.order(created_at.desc()).internal_into_boxed(), + }), + + "updateTime" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => quran_words.order(updated_at.asc()).internal_into_boxed(), + Order::Desc => quran_words.order(updated_at.desc()).internal_into_boxed(), + }), + + "word" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => quran_words.order(word.asc()).internal_into_boxed(), + Order::Desc => quran_words.order(word.desc()).internal_into_boxed(), + }), + + value => Err(RouterError::BadRequest(format!( + "Sort value {} is not possible!", + value + ))), + }, + + None => Ok(quran_words.internal_into_boxed()), + }?; + + _query = match filters.to() { + Some(limit) => _query + .limit(limit as i64) + .offset(filters.from().unwrap_or_default() as i64), + None => _query.offset(filters.from().unwrap_or_default() as i64), + }; + + Ok(_query) + } +} + impl Filter for QuranMushaf { type Output = Result, RouterError>; fn filter(filters: Box) -> Self::Output { use crate::schema::mushafs::dsl::*; - let mut _query = quran_mushafs_table.into_boxed(); + let mut _query = mushafs.into_boxed(); _query = match filters.sort() { Some(sort_str) => match sort_str.as_str() { @@ -81,6 +185,16 @@ impl Filter for QuranMushaf { Order::Desc => mushafs.order(name.desc()).internal_into_boxed(), }), + "createTime" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => mushafs.order(created_at.asc()).internal_into_boxed(), + Order::Desc => mushafs.order(created_at.desc()).internal_into_boxed(), + }), + + "updateTime" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => mushafs.order(updated_at.asc()).internal_into_boxed(), + Order::Desc => mushafs.order(updated_at.desc()).internal_into_boxed(), + }), + value => Err(RouterError::BadRequest(format!( "Sort value {} is not possible!", value @@ -116,6 +230,23 @@ impl Filter for Translation { Order::Desc => translations.order(created_at.desc()).internal_into_boxed(), }), + "updateTime" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => translations.order(updated_at.asc()).internal_into_boxed(), + Order::Desc => translations.order(updated_at.desc()).internal_into_boxed(), + }), + + "language" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => translations.order(language.asc()).internal_into_boxed(), + Order::Desc => translations.order(language.desc()).internal_into_boxed(), + }), + + // TODO: This is not working the way we want + // must order the mushaf by mushaf_name + "mushaf" => Ok(match filters.order().unwrap_or_default() { + Order::Asc => translations.order(mushaf_id.asc()).internal_into_boxed(), + Order::Desc => translations.order(mushaf_id.desc()).internal_into_boxed(), + }), + value => Err(RouterError::BadRequest(format!( "Sort value {} is not possible!", value diff --git a/src/routers/quran/ayah/ayah_list.rs b/src/routers/quran/ayah/ayah_list.rs index e93bee8..42a87ed 100644 --- a/src/routers/quran/ayah/ayah_list.rs +++ b/src/routers/quran/ayah/ayah_list.rs @@ -1,18 +1,24 @@ use crate::error::RouterError; +use crate::filter::Filter; use crate::models::QuranAyah; use crate::DbPool; use actix_web::web; use diesel::prelude::*; -/// Returns the list of ayahs -pub async fn ayah_list(pool: web::Data) -> Result>, RouterError> { - use crate::schema::quran_ayahs::dsl::*; +use super::AyahListQuery; +/// Returns the list of ayahs +pub async fn ayah_list( + pool: web::Data, + web::Query(query): web::Query, +) -> Result>, RouterError> { web::block(move || { let mut conn = pool.get().unwrap(); + let filtered_ayahs = QuranAyah::filter(Box::from(query))?; + // Get the list of ayahs from the database - let ayah_list = quran_ayahs.load::(&mut conn)?; + let ayah_list = filtered_ayahs.load::(&mut conn)?; Ok(web::Json(ayah_list)) }) diff --git a/src/routers/quran/ayah/mod.rs b/src/routers/quran/ayah/mod.rs index 1a8fbc2..552f0dc 100644 --- a/src/routers/quran/ayah/mod.rs +++ b/src/routers/quran/ayah/mod.rs @@ -8,6 +8,8 @@ use std::fmt::Display; use serde::{Deserialize, Serialize}; +use crate::filter::{Filters, Order}; + #[derive(Deserialize, Serialize)] #[serde(rename_all = "lowercase")] pub enum Sajdeh { @@ -30,3 +32,30 @@ pub struct SimpleAyah { pub ayah_number: i32, pub sajdeh: Option, } + +#[derive(Deserialize)] +pub struct AyahListQuery { + sort: Option, + order: Option, + + from: Option, + to: Option, +} + +impl Filters for AyahListQuery { + fn sort(&self) -> Option { + self.sort.clone() + } + + fn order(&self) -> Option { + self.order.clone() + } + + fn from(&self) -> Option { + self.from + } + + fn to(&self) -> Option { + self.to + } +} diff --git a/src/routers/quran/word/mod.rs b/src/routers/quran/word/mod.rs index e94d526..9c6cd66 100644 --- a/src/routers/quran/word/mod.rs +++ b/src/routers/quran/word/mod.rs @@ -6,8 +6,37 @@ pub mod word_delete; use serde::Deserialize; use uuid::Uuid; +use crate::filter::{Filters, Order}; + #[derive(Deserialize)] pub struct SimpleWord { pub ayah_uuid: Uuid, pub word: String, } + +#[derive(Deserialize)] +pub struct WordListQuery { + sort: Option, + order: Option, + + from: Option, + to: Option, +} + +impl Filters for WordListQuery { + fn sort(&self) -> Option { + self.sort.clone() + } + + fn order(&self) -> Option { + self.order.clone() + } + + fn from(&self) -> Option { + self.from + } + + fn to(&self) -> Option { + self.to + } +} diff --git a/src/routers/quran/word/word_list.rs b/src/routers/quran/word/word_list.rs index 8229ac4..a5f2325 100644 --- a/src/routers/quran/word/word_list.rs +++ b/src/routers/quran/word/word_list.rs @@ -1,18 +1,24 @@ use crate::error::RouterError; +use crate::filter::Filter; use crate::models::QuranWord; use crate::DbPool; use actix_web::web; use diesel::prelude::*; -/// Returns the list of quran_words -pub async fn word_list(pool: web::Data) -> Result>, RouterError> { - use crate::schema::quran_words::dsl::*; +use super::WordListQuery; +/// Returns the list of quran_words +pub async fn word_list( + pool: web::Data, + web::Query(query): web::Query, +) -> Result>, RouterError> { web::block(move || { let mut conn = pool.get().unwrap(); + let filtered_words = QuranWord::filter(Box::from(query))?; + // Get the list of words from the database - let words_list = quran_words.load::(&mut conn)?; + let words_list = filtered_words.load::(&mut conn)?; Ok(web::Json(words_list)) }) diff --git a/src/routers/translation/mod.rs b/src/routers/translation/mod.rs index e40101e..13575df 100644 --- a/src/routers/translation/mod.rs +++ b/src/routers/translation/mod.rs @@ -31,6 +31,7 @@ pub struct SimpleTranslationText { pub struct TranslationListQuery { mushaf: String, master_account: Option, + language: Option, sort: Option, order: Option, diff --git a/src/routers/translation/translation_list.rs b/src/routers/translation/translation_list.rs index 7e9e3af..ab88f60 100644 --- a/src/routers/translation/translation_list.rs +++ b/src/routers/translation/translation_list.rs @@ -12,12 +12,32 @@ pub async fn translation_list( pool: web::Data, web::Query(query): web::Query, ) -> Result>, RouterError> { + //use crate::schema::app_accounts::dsl::{app_accounts, id as acc_id, uuid as account_uuid}; + use crate::schema::translations::dsl::language; + let result = web::block(move || { let mut conn = pool.get().unwrap(); + // Get the given language or return the default + let lang = match query.language { + Some(ref s) => s.clone(), + None => "en".to_string(), + }; + + // TODO: FIX + //let master_account: Vec = match query.master_account { + // Some(uuid) => vec![app_accounts + // .filter(account_uuid.eq(uuid)) + // .select(acc_id) + // .get_result(&mut conn)?], + // None => vec![], + //}; + // Get the list of translations from the database - let translations_list = - Translation::filter(Box::from(query))?.load::(&mut conn)?; + let translations_list = Translation::filter(Box::from(query))? + .filter(language.eq(lang)) + //.filter(translator_account_id.eq_any::>(master_account)) + .load::(&mut conn)?; Ok(web::Json(translations_list)) }) diff --git a/src/schema.rs b/src/schema.rs index aff819f..9368478 100644 --- a/src/schema.rs +++ b/src/schema.rs @@ -191,6 +191,7 @@ diesel::table! { translations (id) { id -> Int4, uuid -> Uuid, + mushaf_id -> Int4, creator_user_id -> Int4, translator_account_id -> Int4, language -> Varchar, @@ -237,6 +238,7 @@ diesel::joinable!(quran_words -> app_users (creator_user_id)); diesel::joinable!(quran_words -> quran_ayahs (ayah_id)); diesel::joinable!(translations -> app_accounts (translator_account_id)); diesel::joinable!(translations -> app_users (creator_user_id)); +diesel::joinable!(translations -> mushafs (mushaf_id)); diesel::joinable!(translations_text -> app_users (creator_user_id)); diesel::joinable!(translations_text -> quran_ayahs (ayah_id)); diesel::joinable!(translations_text -> translations (translation_id));