diff options
author | Santo Cariotti <santo@dcariotti.me> | 2025-02-03 17:03:43 +0100 |
---|---|---|
committer | Santo Cariotti <santo@dcariotti.me> | 2025-02-03 17:03:43 +0100 |
commit | 885393c445dd014dbb4a9a90aa23966db4b29711 (patch) | |
tree | 27668c2f6874ed2c17fc216569ab1720f1141cc3 | |
parent | b158fada12aaab33b83e65d8253d603384474456 (diff) |
Show notifications list for alerts
-rw-r--r-- | src/graphql/query.rs | 2 | ||||
-rw-r--r-- | src/graphql/types/alert.rs | 180 | ||||
-rw-r--r-- | src/graphql/types/notification.rs | 12 |
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"), |