You've already forked AstralRinth
forked from didirus/AstralRinth
Add notification for project status updates (#511)
* Add notification for project status updates * aaaaaa * cargo sqlx prepare * use friendly name of statuses * Update src/models/projects.rs Co-authored-by: triphora <emma@modrinth.com> * only send notifications to accepted users * only send notifications for people not on the team * cargo sqlx prepare * != * fully address pr comments Co-authored-by: triphora <emma@modrinth.com> Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
34af33607b
commit
161dee89ec
@@ -7186,6 +7186,26 @@
|
|||||||
},
|
},
|
||||||
"query": "\n UPDATE mods\n SET status = $1\n WHERE (id = $2)\n "
|
"query": "\n UPDATE mods\n SET status = $1\n WHERE (id = $2)\n "
|
||||||
},
|
},
|
||||||
|
"ea1525cbe7460d0d9e9da8f448c661f7209bc1a7a04e2ea0026fa69c3f550a14": {
|
||||||
|
"describe": {
|
||||||
|
"columns": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"ordinal": 0,
|
||||||
|
"type_info": "Int8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"nullable": [
|
||||||
|
false
|
||||||
|
],
|
||||||
|
"parameters": {
|
||||||
|
"Left": [
|
||||||
|
"Int8"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"query": "\n SELECT tm.user_id id\n FROM team_members tm\n WHERE tm.team_id = $1 AND tm.accepted\n "
|
||||||
|
},
|
||||||
"ebef881a0dae70e990814e567ed3de9565bb29b772782bc974c953af195fd6d7": {
|
"ebef881a0dae70e990814e567ed3de9565bb29b772782bc974c953af195fd6d7": {
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
|
|||||||
@@ -319,6 +319,20 @@ impl ProjectStatus {
|
|||||||
ProjectStatus::Private => "private",
|
ProjectStatus::Private => "private",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn as_friendly_str(&self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
ProjectStatus::Approved => "Listed",
|
||||||
|
ProjectStatus::Rejected => "Rejected",
|
||||||
|
ProjectStatus::Draft => "Draft",
|
||||||
|
ProjectStatus::Unlisted => "Unlisted",
|
||||||
|
ProjectStatus::Processing => "Under review",
|
||||||
|
ProjectStatus::Unknown => "Unknown",
|
||||||
|
ProjectStatus::Archived => "Archived",
|
||||||
|
ProjectStatus::Withheld => "Withheld",
|
||||||
|
ProjectStatus::Scheduled => "Scheduled",
|
||||||
|
ProjectStatus::Private => "Private",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn iterator() -> impl Iterator<Item = ProjectStatus> {
|
pub fn iterator() -> impl Iterator<Item = ProjectStatus> {
|
||||||
[
|
[
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
use crate::database;
|
use crate::database;
|
||||||
|
use crate::database::models::notification_item::NotificationBuilder;
|
||||||
use crate::file_hosting::FileHost;
|
use crate::file_hosting::FileHost;
|
||||||
use crate::models;
|
use crate::models;
|
||||||
use crate::models::ids::UserId;
|
use crate::models::ids::UserId;
|
||||||
@@ -13,7 +14,7 @@ use crate::util::routes::read_from_payload;
|
|||||||
use crate::util::validate::validation_errors_to_string;
|
use crate::util::validate::validation_errors_to_string;
|
||||||
use actix_web::{delete, get, patch, post, web, HttpRequest, HttpResponse};
|
use actix_web::{delete, get, patch, post, web, HttpRequest, HttpResponse};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use futures::StreamExt;
|
use futures::{StreamExt, TryStreamExt};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use sqlx::{PgPool, Row};
|
use sqlx::{PgPool, Row};
|
||||||
@@ -395,7 +396,7 @@ pub async fn project_edit(
|
|||||||
|
|
||||||
if user.role.is_admin() {
|
if user.role.is_admin() {
|
||||||
permissions = Some(Permissions::ALL)
|
permissions = Some(Permissions::ALL)
|
||||||
} else if let Some(member) = team_member {
|
} else if let Some(ref member) = team_member {
|
||||||
permissions = Some(member.permissions)
|
permissions = Some(member.permissions)
|
||||||
} else if user.role.is_mod() {
|
} else if user.role.is_mod() {
|
||||||
permissions =
|
permissions =
|
||||||
@@ -551,6 +552,40 @@ pub async fn project_edit(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if team_member.map(|x| !x.accepted).unwrap_or(true) {
|
||||||
|
let notified_members = sqlx::query!(
|
||||||
|
"
|
||||||
|
SELECT tm.user_id id
|
||||||
|
FROM team_members tm
|
||||||
|
WHERE tm.team_id = $1 AND tm.accepted
|
||||||
|
",
|
||||||
|
project_item.inner.team_id as database::models::ids::TeamId
|
||||||
|
)
|
||||||
|
.fetch_many(&mut *transaction)
|
||||||
|
.try_filter_map(|e| async { Ok(e.right().map(|c| database::models::UserId(c.id))) })
|
||||||
|
.try_collect::<Vec<_>>()
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
NotificationBuilder {
|
||||||
|
notification_type: Some("status_update".to_string()),
|
||||||
|
title: format!("**{}**'s status has changed!", project_item.inner.title),
|
||||||
|
text: format!(
|
||||||
|
"The project {}'s status has changed from {} to {}",
|
||||||
|
project_item.inner.title,
|
||||||
|
project_item.inner.status.as_friendly_str(),
|
||||||
|
status.as_friendly_str()
|
||||||
|
),
|
||||||
|
link: format!(
|
||||||
|
"/{}/{}",
|
||||||
|
project_item.project_type,
|
||||||
|
ProjectId::from(id)
|
||||||
|
),
|
||||||
|
actions: vec![],
|
||||||
|
}
|
||||||
|
.insert_many(notified_members, &mut transaction)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
sqlx::query!(
|
sqlx::query!(
|
||||||
"
|
"
|
||||||
UPDATE mods
|
UPDATE mods
|
||||||
|
|||||||
Reference in New Issue
Block a user