summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSanto Cariotti <santo@dcariotti.me>2025-02-03 17:03:43 +0100
committerSanto Cariotti <santo@dcariotti.me>2025-02-03 17:03:43 +0100
commit885393c445dd014dbb4a9a90aa23966db4b29711 (patch)
tree27668c2f6874ed2c17fc216569ab1720f1141cc3
parentb158fada12aaab33b83e65d8253d603384474456 (diff)
Show notifications list for alerts
-rw-r--r--src/graphql/query.rs2
-rw-r--r--src/graphql/types/alert.rs180
-rw-r--r--src/graphql/types/notification.rs12
3 files changed, 125 insertions, 69 deletions
diff --git a/src/graphql/query.rs b/src/graphql/query.rs
index ccade65..4ce767b 100644
--- a/src/graphql/query.rs
+++ b/src/graphql/query.rs
@@ -74,7 +74,7 @@ impl Query {
/// curl http://localhost:8000/graphql
/// -H 'authorization: Bearer ***'
/// -H 'content-type: application/json'
- /// -d '{"query":"{alerts(id: 12) {id, userId, createdAt, area, areaLevel2, areaLevel3, text1, text2, text3}}"}'
+ /// -d '{"query":"{alerts(id: 12) {id, userId, createdAt, area, areaLevel2, areaLevel3, text1, text2, text3, notifications {userId, latitude, longitude }}"}'
/// ```
async fn alerts<'ctx>(
&self,
diff --git a/src/graphql/types/alert.rs b/src/graphql/types/alert.rs
index 2f06225..61e9acf 100644
--- a/src/graphql/types/alert.rs
+++ b/src/graphql/types/alert.rs
@@ -33,6 +33,7 @@ pub struct Alert {
pub audio2: Vec<u8>,
pub audio3: Vec<u8>,
pub reached_users: i32,
+ pub notifications: Vec<Notification>,
}
#[derive(InputObject)]
@@ -73,72 +74,123 @@ pub mod query {
Authentication::NotLogged => Err(AppError::Unauthorized),
Authentication::Logged(_) => {
let rows = match id {
- Some(id) => {
- client
- .query(
- "SELECT id,
- user_id,
- extract(epoch from created_at)::double precision as created_at,
- ST_AsText(area) as area,
- ST_AsText(ST_Buffer(area::geography, 1000)) as area_level2,
- ST_AsText(ST_Buffer(area::geography, 2000)) as area_level3,
- text1,
- text2,
- text3,
- audio1,
- audio2,
- audio3,
- reached_users
- FROM alerts
- WHERE id = $1",
- &[&id],
- )
- .await?
+ Some(id) => {
+ client
+ .query(
+ "SELECT a.id,
+ a.user_id,
+ extract(epoch from a.created_at)::double precision as created_at,
+ ST_AsText(a.area) as area,
+ ST_AsText(ST_Buffer(a.area::geography, 1000)) as area_level2,
+ ST_AsText(ST_Buffer(a.area::geography, 2000)) as area_level3,
+ a.text1,
+ a.text2,
+ a.text3,
+ a.audio1,
+ a.audio2,
+ a.audio3,
+ a.reached_users,
+ n.id as notification_id,
+ n.alert_id as notification_alert_id,
+ n.seen as notification_seen,
+ extract(epoch from n.created_at)::double precision as notification_created_at,
+ ST_Y(n.location::geometry) AS notification_latitude,
+ ST_X(n.location::geometry) AS notification_longitude,
+ n.activity as notification_activity,
+ n.level as notification_level,
+ n.user_id as notification_user_id
+ FROM alerts a
+ LEFT JOIN notifications n ON n.alert_id = a.id
+ WHERE a.id = $1",
+ &[&id],
+ )
+ .await?
+ }
+ None => {
+ client
+ .query(
+ "SELECT a.id,
+ a.user_id,
+ extract(epoch from a.created_at)::double precision as created_at,
+ ST_AsText(a.area) as area,
+ ST_AsText(ST_Buffer(a.area::geography, 1000)) as area_level2,
+ ST_AsText(ST_Buffer(a.area::geography, 2000)) as area_level3,
+ a.text1,
+ a.text2,
+ a.text3,
+ a.audio1,
+ a.audio2,
+ a.audio3,
+ a.reached_users,
+ n.id as notification_id,
+ n.alert_id as notification_alert_id,
+ n.seen as notification_seen,
+ extract(epoch from n.created_at)::double precision as notification_created_at,
+ ST_Y(n.location::geometry) AS notification_latitude,
+ ST_X(n.location::geometry) AS notification_longitude,
+ n.activity as notification_activity,
+ n.level as notification_level,
+ n.user_id as notification_user_id
+ FROM alerts a
+ LEFT JOIN notifications n ON n.alert_id = a.id
+ ORDER BY a.id DESC
+ LIMIT $1
+ OFFSET $2",
+ &[&limit.unwrap_or(20), &offset.unwrap_or(0)],
+ )
+ .await?
+ }
+ };
+
+ let mut alerts: Vec<Alert> = vec![];
+ let mut current_alert_id = None;
+ let mut current_alert = None;
+
+ for row in rows {
+ let alert_id: i32 = row.get("id");
+ if current_alert_id != Some(alert_id) {
+ if let Some(alert) = current_alert.take() {
+ alerts.push(alert);
+ }
+ current_alert_id = Some(alert_id);
+ current_alert = Some(Alert {
+ id: row.get("id"),
+ user_id: row.get("user_id"),
+ created_at: row.get::<_, f64>("created_at") as i64,
+ area: row.get("area"),
+ area_level2: row.get("area_level2"),
+ area_level3: row.get("area_level3"),
+ text1: row.get("text1"),
+ text2: row.get("text2"),
+ text3: row.get("text3"),
+ audio1: row.get("audio1"),
+ audio2: row.get("audio2"),
+ audio3: row.get("audio3"),
+ reached_users: row.get("reached_users"),
+ notifications: vec![],
+ });
}
- None => {
- client
- .query(
- "SELECT id,
- user_id,
- extract(epoch from created_at)::double precision as created_at,
- ST_AsText(area) as area,
- ST_AsText(ST_Buffer(area::geography, 1000)) as area_level2,
- ST_AsText(ST_Buffer(area::geography, 2000)) as area_level3,
- text1,
- text2,
- text3,
- audio1,
- audio2,
- audio3,
- reached_users
- FROM alerts
- ORDER BY id DESC
- LIMIT $1
- OFFSET $2",
- &[&limit.unwrap_or(20), &offset.unwrap_or(0)],
- )
- .await?
+
+ // Add the notification data to the notifications list
+ if let Some(alert) = current_alert.as_mut() {
+ let notification = Notification {
+ id: row.get("notification_id"),
+ alert: None,
+ user_id: row.get("notification_user_id"),
+ latitude: row.get("notification_latitude"),
+ longitude: row.get("notification_longitude"),
+ moving_activity: row.get("notification_activity"),
+ level: row.get("notification_level"),
+ seen: row.get("notification_seen"),
+ created_at: row.get::<_, f64>("notification_created_at") as i64,
+ };
+ alert.notifications.push(notification);
}
- };
+ }
- let alerts: Vec<Alert> = rows
- .iter()
- .map(|row| Alert {
- id: row.get("id"),
- user_id: row.get("user_id"),
- created_at: row.get::<_, f64>("created_at") as i64,
- area: row.get("area"),
- area_level2: row.get("area_level2"),
- area_level3: row.get("area_level3"),
- text1: row.get("text1"),
- text2: row.get("text2"),
- text3: row.get("text3"),
- audio1: row.get("audio1"),
- audio2: row.get("audio2"),
- audio3: row.get("audio3"),
- reached_users: row.get("reached_users"),
- })
- .collect();
+ if let Some(alert) = current_alert {
+ alerts.push(alert);
+ }
Ok(Some(alerts))
}
@@ -224,6 +276,7 @@ pub mod mutations {
audio2: row.get("audio2"),
audio3: row.get("audio3"),
reached_users: row.get("reached_users"),
+ notifications: vec![],
})
.collect::<Vec<Alert>>()
.first()
@@ -299,6 +352,7 @@ pub mod mutations {
audio2: row.get("audio2"),
audio3: row.get("audio3"),
reached_users: row.get("reached_users"),
+ notifications: vec![],
})
.collect::<Vec<Alert>>()
.first()
diff --git a/src/graphql/types/notification.rs b/src/graphql/types/notification.rs
index 45d8234..0d1d472 100644
--- a/src/graphql/types/notification.rs
+++ b/src/graphql/types/notification.rs
@@ -81,7 +81,7 @@ impl ToSql for LevelAlert {
/// Notification struct
pub struct Notification {
pub id: i32,
- pub alert: Alert,
+ pub alert: Option<Alert>,
pub user_id: i32,
pub latitude: f64,
pub longitude: f64,
@@ -223,7 +223,7 @@ pub mod query {
.iter()
.map(|row| Notification {
id: row.get("id"),
- alert: Alert {
+ alert: Some(Alert {
id: row.get("alert_id"),
user_id: row.get("alert_user_id"),
created_at: row.get::<_, f64>("alert_created_at") as i64,
@@ -237,7 +237,8 @@ pub mod query {
audio2: row.get("alert_audio2"),
audio3: row.get("alert_audio3"),
reached_users: row.get("alert_reached_users"),
- },
+ notifications: vec![],
+ }),
seen: row.get("seen"),
level: row.get("level"),
user_id: row.get("user_id"),
@@ -303,7 +304,7 @@ pub mod mutations {
.iter()
.map(|row| Notification {
id: row.get("id"),
- alert: Alert {
+ alert: Some(Alert {
id: row.get("alert_id"),
user_id: row.get("alert_user_id"),
created_at: row.get::<_, f64>("alert_created_at") as i64,
@@ -317,7 +318,8 @@ pub mod mutations {
audio2: row.get("alert_audio2"),
audio3: row.get("alert_audio3"),
reached_users: row.get("alert_reached_users"),
- },
+ notifications: vec![],
+ }),
seen: row.get("seen"),
level: row.get("level"),
user_id: row.get("user_id"),