From f452875fbe4301ab1938ca1b9978a4b0d2e22d89 Mon Sep 17 00:00:00 2001 From: trisua Date: Sun, 13 Apr 2025 12:44:08 -0400 Subject: [PATCH] add: question reactions --- crates/app/src/public/html/components.html | 68 ++++++++++++------- .../database/drivers/sql/create_questions.sql | 5 +- crates/core/src/database/questions.rs | 14 +++- crates/core/src/database/reactions.rs | 66 ++++++++++++------ crates/core/src/model/communities.rs | 7 ++ crates/core/src/model/reactions.rs | 2 + sql_changes/questions_likes.sql | 5 ++ 7 files changed, 122 insertions(+), 45 deletions(-) create mode 100644 sql_changes/questions_likes.sql diff --git a/crates/app/src/public/html/components.html b/crates/app/src/public/html/components.html index f815249..443eeed 100644 --- a/crates/app/src/public/html/components.html +++ b/crates/app/src/public/html/components.html @@ -66,10 +66,11 @@ community %} {% if user.settings.display_name %} {{ user.settings.display_name }} {% else %} {{ user.username }} {% endif %} -{%- endmacro %} {% macro likes(id, asset_type, likes=0, dislikes=0) -%} +{%- endmacro %} {% macro likes(id, asset_type, likes=0, dislikes=0, +secondary=false) -%} - {% endif %} {% endif %} +
+ + {{ icon "external-link" }} {% if user %} + {{ text "requests:label.answer" }} + {% else %} + {{ text "general:action.open" }} + {% endif %} + + + {% if user %} {% if can_manage_questions or is_helper or + question[1].id == user.id %} + + {% endif %} {% endif %} +
{%- endmacro %} diff --git a/crates/core/src/database/drivers/sql/create_questions.sql b/crates/core/src/database/drivers/sql/create_questions.sql index ebea0cc..d7dba2c 100644 --- a/crates/core/src/database/drivers/sql/create_questions.sql +++ b/crates/core/src/database/drivers/sql/create_questions.sql @@ -6,5 +6,8 @@ CREATE TABLE IF NOT EXISTS questions ( content TEXT NOT NULL, is_global INT NOT NULL, answer_count INT NOT NULL, - community BIGINT NOT NULL + community BIGINT NOT NULL, + -- likes + likes INT NOT NULL, + dislikes INT NOT NULL ) diff --git a/crates/core/src/database/questions.rs b/crates/core/src/database/questions.rs index 0044caa..5c221bc 100644 --- a/crates/core/src/database/questions.rs +++ b/crates/core/src/database/questions.rs @@ -33,6 +33,9 @@ impl DataManager { is_global: get!(x->5(i32)) as i8 == 1, answer_count: get!(x->6(i32)) as usize, community: get!(x->7(i64)) as usize, + // likes + likes: get!(x->8(i32)) as isize, + dislikes: get!(x->9(i32)) as isize, } } @@ -283,7 +286,7 @@ impl DataManager { let res = execute!( &conn, - "INSERT INTO questions VALUES ($1, $2, $3, $4, $5, $6, $7, $8)", + "INSERT INTO questions VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)", params![ &(data.id as i64), &(data.created as i64), @@ -292,7 +295,9 @@ impl DataManager { &data.content, &{ if data.is_global { 1 } else { 0 } }, &0_i32, - &(data.community as i64) + &(data.community as i64), + &0_i32, + &0_i32 ] ); @@ -396,4 +401,9 @@ impl DataManager { auto_method!(incr_question_answer_count() -> "UPDATE questions SET answer_count = answer_count + 1 WHERE id = $1" --cache-key-tmpl="atto.question:{}" --incr); auto_method!(decr_question_answer_count() -> "UPDATE questions SET answer_count = answer_count - 1 WHERE id = $1" --cache-key-tmpl="atto.question:{}" --decr); + + auto_method!(incr_question_likes() -> "UPDATE questions SET likes = likes + 1 WHERE id = $1" --cache-key-tmpl="atto.question:{}" --incr); + auto_method!(incr_question_dislikes() -> "UPDATE questions SET dislikes = dislikes + 1 WHERE id = $1" --cache-key-tmpl="atto.question:{}" --incr); + auto_method!(decr_question_likes() -> "UPDATE questions SET likes = likes - 1 WHERE id = $1" --cache-key-tmpl="atto.question:{}" --decr); + auto_method!(decr_question_dislikes() -> "UPDATE questions SET dislikes = dislikes - 1 WHERE id = $1" --cache-key-tmpl="atto.question:{}" --decr); } diff --git a/crates/core/src/database/reactions.rs b/crates/core/src/database/reactions.rs index d806a37..9549125 100644 --- a/crates/core/src/database/reactions.rs +++ b/crates/core/src/database/reactions.rs @@ -125,14 +125,39 @@ impl DataManager { let post = self.get_post_by_id(data.asset).await.unwrap(); if post.owner != user.id { + self.create_notification(Notification::new( + "Your post has received a like!".to_string(), + format!( + "[@{}](/api/v1/auth/user/find/{}) has liked your [post](/post/{})!", + user.username, user.id, data.asset + ), + post.owner, + )) + .await? + } + } + } + AssetType::Question => { + if let Err(e) = { + if data.is_like { + self.incr_question_likes(data.asset).await + } else { + self.incr_question_dislikes(data.asset).await + } + } { + return Err(e); + } else if data.is_like { + let question = self.get_question_by_id(data.asset).await.unwrap(); + + if question.owner != user.id { self .create_notification(Notification::new( - "Your post has received a like!".to_string(), + "Your question has received a like!".to_string(), format!( - "[@{}](/api/v1/auth/user/find/{}) has liked your [post](/post/{})!", + "[@{}](/api/v1/auth/user/find/{}) has liked your [question](/question/{})!", user.username, user.id, data.asset ), - post.owner, + question.owner, )) .await? } @@ -174,23 +199,26 @@ impl DataManager { // decr corresponding match reaction.asset_type { AssetType::Community => { - { - if reaction.is_like { - self.decr_community_likes(reaction.asset).await - } else { - self.decr_community_dislikes(reaction.asset).await - } - }? - } + if reaction.is_like { + self.decr_community_likes(reaction.asset).await + } else { + self.decr_community_dislikes(reaction.asset).await + } + }?, AssetType::Post => { - { - if reaction.is_like { - self.decr_post_likes(reaction.asset).await - } else { - self.decr_post_dislikes(reaction.asset).await - } - }? - } + if reaction.is_like { + self.decr_post_likes(reaction.asset).await + } else { + self.decr_post_dislikes(reaction.asset).await + } + }?, + AssetType::Question => { + if reaction.is_like { + self.decr_question_likes(reaction.asset).await + } else { + self.decr_question_dislikes(reaction.asset).await + } + }?, AssetType::User => { return Err(Error::NotAllowed); } diff --git a/crates/core/src/model/communities.rs b/crates/core/src/model/communities.rs index ec96876..57a4ae6 100644 --- a/crates/core/src/model/communities.rs +++ b/crates/core/src/model/communities.rs @@ -302,6 +302,11 @@ pub struct Question { /// The ID of the community this question is asked to. This should only be > 0 /// if `is_global` is set to true. pub community: usize, + // likes + #[serde(default)] + pub likes: isize, + #[serde(default)] + pub dislikes: isize, } impl Question { @@ -319,6 +324,8 @@ impl Question { is_global, answer_count: 0, community: 0, + likes: 0, + dislikes: 0, } } } diff --git a/crates/core/src/model/reactions.rs b/crates/core/src/model/reactions.rs index d78190e..e615874 100644 --- a/crates/core/src/model/reactions.rs +++ b/crates/core/src/model/reactions.rs @@ -8,6 +8,8 @@ pub enum AssetType { Community, #[serde(alias = "post")] Post, + #[serde(alias = "question")] + Question, #[serde(alias = "user")] User, } diff --git a/sql_changes/questions_likes.sql b/sql_changes/questions_likes.sql new file mode 100644 index 0000000..3825820 --- /dev/null +++ b/sql_changes/questions_likes.sql @@ -0,0 +1,5 @@ +ALTER TABLE questions +ADD COLUMN likes INT NOT NULL DEFAULT 0; + +ALTER TABLE questions +ADD COLUMN dislikes INT NOT NULL DEFAULT 0;