Fix word name collision, add two new user-related features
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit changes the primary key of words to a serial number. That way, two words with the same normalized value will not collide with one another. It also adds two new tables in the database: - Users following languages - Users learning words The former can represent two stages of learning a word: - Either the user is currently learning it - Or they consider they know it and don’t need to work on it anymore These two new tables now have their API query available through the GraphQL API. This commit also fixes the issue of word-related tables and types not being dropped when resetting the database.
This commit is contained in:
@@ -13,7 +13,7 @@ use super::users::User;
|
||||
|
||||
use std::convert::Into;
|
||||
|
||||
use schema::{langandagents, langtranslatesto, languages};
|
||||
use schema::{langandagents, langtranslatesto, languages, userfollowlanguage};
|
||||
|
||||
#[derive(
|
||||
diesel_derive_enum::DbEnum, Debug, Clone, PartialEq, Eq, GraphQLEnum,
|
||||
@@ -209,7 +209,7 @@ impl Language {
|
||||
"Failed to retrieve owner {} of language {}: {e:?}",
|
||||
self.owner, self.name
|
||||
),
|
||||
"Database reading error",
|
||||
"Database error",
|
||||
)
|
||||
})?),
|
||||
Err(e) => Err(DatabaseError::new(
|
||||
@@ -235,6 +235,42 @@ impl Language {
|
||||
self.relationship(&context.db, AgentLanguageRelation::Publisher)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
#[graphql(description = "People following the language")]
|
||||
fn followers(&self, context: &Context) -> FieldResult<Vec<User>> {
|
||||
use schema::userfollowlanguage::dsl;
|
||||
match &mut context.db.conn() {
|
||||
Ok(conn) => {
|
||||
Ok(dsl::userfollowlanguage
|
||||
.filter(dsl::lang.eq(self.id))
|
||||
.load::<UserFollowLanguage>(conn)
|
||||
.map_err(|e| {
|
||||
DatabaseError::new(format!("Failed to retrieve language followers for language {}: {e:?}", self.id),
|
||||
"Database error")
|
||||
})?
|
||||
.into_iter()
|
||||
.filter_map(|follow| {
|
||||
use schema::users::dsl;
|
||||
match dsl::users
|
||||
.find(follow.userid.clone())
|
||||
.first::<User>(conn) {
|
||||
Ok(user) => Some(user),
|
||||
Err(e) => {
|
||||
info!("Failed to retrieve user {} from database: {e:?}", follow.userid);
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Vec<User>>()
|
||||
)
|
||||
}
|
||||
Err(e) => Err(DatabaseError::new(
|
||||
format!("Failed to connect to the database: {e:?}"),
|
||||
"Database connection failure",
|
||||
)
|
||||
.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)]
|
||||
@@ -253,3 +289,11 @@ pub struct LangTranslatesTo {
|
||||
langfrom: Uuid,
|
||||
langto: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Insertable, Debug, Clone, PartialEq, Eq)]
|
||||
#[diesel(table_name = userfollowlanguage)]
|
||||
pub struct UserFollowLanguage {
|
||||
id: i32,
|
||||
lang: Uuid,
|
||||
userid: String,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user