Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Filter support for quran related routers #141

Merged
merged 2 commits into from
Jan 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions migrations/2023-03-12-100253_create_translation/up.sql
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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)
);
2 changes: 2 additions & 0 deletions src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,8 @@ pub struct Translation {

pub translator_account_id: i32,

pub mushaf_id: i32,

pub language: String,
pub release_date: Option<NaiveDate>,
pub source: Option<String>,
Expand Down
143 changes: 137 additions & 6 deletions src/models_filter.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand Down Expand Up @@ -32,7 +36,7 @@ impl Filter for QuranSurah {
fn filter(filters: Box<dyn Filters>) -> 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() {
Expand All @@ -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
Expand All @@ -66,13 +80,103 @@ impl Filter for QuranSurah {
}
}

impl Filter for QuranAyah {
type Output = Result<AyahBoxedQuery<'static, Pg>, RouterError>;

fn filter(filters: Box<dyn Filters>) -> 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<WordBoxedQuery<'static, Pg>, RouterError>;

fn filter(filters: Box<dyn Filters>) -> 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<MushafBoxedQuery<'static, Pg>, RouterError>;

fn filter(filters: Box<dyn Filters>) -> 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() {
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
14 changes: 10 additions & 4 deletions src/routers/quran/ayah/ayah_list.rs
Original file line number Diff line number Diff line change
@@ -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<DbPool>) -> Result<web::Json<Vec<QuranAyah>>, RouterError> {
use crate::schema::quran_ayahs::dsl::*;
use super::AyahListQuery;

/// Returns the list of ayahs
pub async fn ayah_list(
pool: web::Data<DbPool>,
web::Query(query): web::Query<AyahListQuery>,
) -> Result<web::Json<Vec<QuranAyah>>, 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::<QuranAyah>(&mut conn)?;
let ayah_list = filtered_ayahs.load::<QuranAyah>(&mut conn)?;

Ok(web::Json(ayah_list))
})
Expand Down
29 changes: 29 additions & 0 deletions src/routers/quran/ayah/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -30,3 +32,30 @@ pub struct SimpleAyah {
pub ayah_number: i32,
pub sajdeh: Option<Sajdeh>,
}

#[derive(Deserialize)]
pub struct AyahListQuery {
sort: Option<String>,
order: Option<Order>,

from: Option<u64>,
to: Option<u64>,
}

impl Filters for AyahListQuery {
fn sort(&self) -> Option<String> {
self.sort.clone()
}

fn order(&self) -> Option<Order> {
self.order.clone()
}

fn from(&self) -> Option<u64> {
self.from
}

fn to(&self) -> Option<u64> {
self.to
}
}
29 changes: 29 additions & 0 deletions src/routers/quran/word/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<String>,
order: Option<Order>,

from: Option<u64>,
to: Option<u64>,
}

impl Filters for WordListQuery {
fn sort(&self) -> Option<String> {
self.sort.clone()
}

fn order(&self) -> Option<Order> {
self.order.clone()
}

fn from(&self) -> Option<u64> {
self.from
}

fn to(&self) -> Option<u64> {
self.to
}
}
14 changes: 10 additions & 4 deletions src/routers/quran/word/word_list.rs
Original file line number Diff line number Diff line change
@@ -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<DbPool>) -> Result<web::Json<Vec<QuranWord>>, RouterError> {
use crate::schema::quran_words::dsl::*;
use super::WordListQuery;

/// Returns the list of quran_words
pub async fn word_list(
pool: web::Data<DbPool>,
web::Query(query): web::Query<WordListQuery>,
) -> Result<web::Json<Vec<QuranWord>>, 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::<QuranWord>(&mut conn)?;
let words_list = filtered_words.load::<QuranWord>(&mut conn)?;

Ok(web::Json(words_list))
})
Expand Down
1 change: 1 addition & 0 deletions src/routers/translation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub struct SimpleTranslationText {
pub struct TranslationListQuery {
mushaf: String,
master_account: Option<Uuid>,
language: Option<String>,

sort: Option<String>,
order: Option<Order>,
Expand Down
24 changes: 22 additions & 2 deletions src/routers/translation/translation_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,32 @@ pub async fn translation_list(
pool: web::Data<DbPool>,
web::Query(query): web::Query<TranslationListQuery>,
) -> Result<web::Json<Vec<Translation>>, 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<i32> = 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::<Translation>(&mut conn)?;
let translations_list = Translation::filter(Box::from(query))?
.filter(language.eq(lang))
//.filter(translator_account_id.eq_any::<Vec<i32>>(master_account))
.load::<Translation>(&mut conn)?;

Ok(web::Json(translations_list))
})
Expand Down
Loading