Skip to content

Commit

Permalink
fix notification system
Browse files Browse the repository at this point in the history
  • Loading branch information
The-DevBlog committed Mar 1, 2024
1 parent 835478f commit 7a5cf8d
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 41 deletions.
6 changes: 4 additions & 2 deletions devblog/devblog/client/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub enum Api {
EditPost(u32),
GetPage(u32),
GetPagesCount,
GetPageNumber(u32),
GetPost(i32),
GetPostsCount,
GetCurrentUser,
Expand Down Expand Up @@ -74,8 +75,9 @@ impl Api {
}
Api::EditComment(id) => format!("{}comments/{}", URL, id),
Api::EditPost(id) => format!("{}posts/{}", URL, id),
Api::GetPage(num) => format!("{}posts/?page={}", URL, num),
Api::GetPage(num) => format!("{}posts?page={}", URL, num),
Api::GetPagesCount => format!("{}posts/countPages", URL),
Api::GetPageNumber(id) => format!("{}posts/getPageNum/{}", URL, id),
Api::GetPost(id) => format!("{}posts/{}", URL, id),
Api::GetPostsCount => format!("{}posts/countPosts", URL),
Api::GetCurrentUser => format!("{}accounts/user", URL),
Expand All @@ -87,7 +89,7 @@ impl Api {
Api::SignUp => format!("{}accounts/signup", URL),
Api::ToggleSubscribe => format!("{}accounts/subscribe", URL),
Api::UpdateVideoUrl => format!("{}YtVideo/1", URL),
Api::Vote(post_id, vote) => format!("{}posts/{}/{}", URL, post_id, vote),
Api::Vote(id, vote) => format!("{}posts/{}/{}", URL, id, vote),
}
}
}
103 changes: 73 additions & 30 deletions devblog/devblog/client/src/components/notifications.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use crate::{
helpers::{self, CustomCallback},
icons::icons::BellIcon,
router::{PostQuery, Route},
store::Store,
Api, Notification,
};
use gloo_net::http::Method;
use std::{ops::Deref, rc::Rc};
use stylist::Style;
use yew::prelude::*;
use yew_router::hooks::use_location;
use yew_router::hooks::use_navigator;
use yewdux::use_store_value;

const STYLE: &str = include_str!("styles/notifications.css");
Expand All @@ -28,7 +30,7 @@ pub fn notifications(props: &Props) -> Html {
let notifications_cb = CustomCallback::new(&notifications);
let store = use_store_value::<Store>();
let onclick_bell = props.onclick_bell.clone();
let location = use_location();
let navigator = use_navigator();

// get all notifications for user
let token = store.token.clone();
Expand Down Expand Up @@ -61,8 +63,61 @@ pub fn notifications(props: &Props) -> Html {
use_effect_with(notifications.clone(), move |n| {
display_clone.set(if n.len() > 0 { "inline" } else { "none" }.to_string());
});
// let token = store.token.clone();
// let username = store.username.clone();

let nav_to_post = |post_id: u32| -> Callback<MouseEvent> {
let navigator = navigator.clone();
Callback::from(move |_| {
let navigator = navigator.clone().unwrap();
wasm_bindgen_futures::spawn_local(async move {
let response = Api::GetPageNumber(post_id)
.fetch(None, None, Method::GET)
.await;

if let Some(res) = response {
if res.status() == 200 {
let data = res.text().await.unwrap();
let page_num = serde_json::from_str::<u32>(&data).unwrap();

let query = &PostQuery { page: page_num };
let _ = navigator.push_with_query(&Route::Posts, &query);
}
}
});
})
};

let delete_notification = |post_id: u32,
store: Rc<Store>,
notifications: UseStateHandle<Vec<Notification>>|
-> Callback<MouseEvent> {
let store_clone = store.clone();
let notifications = notifications.clone();

Callback::from(move |_| {
let hdrs = helpers::create_auth_header(&store_clone.token);
let username = store_clone.username.clone();
let notifications = notifications.clone();

wasm_bindgen_futures::spawn_local(async move {
let response = Api::DeleteNotification(post_id, username)
.fetch(Some(hdrs), None, Method::DELETE)
.await;

if let Some(res) = response {
// if delete is success, remove the deleted notifications from the notifications vec
if res.status() == 200 {
let mut new_notifications = notifications.deref().clone();
if let Some(idx) =
new_notifications.iter().position(|n| n.post_id == post_id)
{
new_notifications.remove(idx);
notifications.set(new_notifications);
}
}
}
});
})
};

html! {
if store.authenticated {
Expand All @@ -79,34 +134,22 @@ pub fn notifications(props: &Props) -> Html {
<div class="notifications">
if !*loading && props.is_bell_clicked && !props.is_menu_clicked {
{for notifications.iter().enumerate().map(|(_idx, n)| {
let id = n.post_id;

html! {
<div class="">
// thumbnail
<span>
<img src={n.img_url.clone()} alt="post thumbnail"/>
</span>

let store_clone = store.clone();
let id = n.post_id;
let delete_notification = {
Callback::from(move |_| {
let hdrs = helpers::create_auth_header(&store_clone.token);
let username = store_clone.username.clone();

wasm_bindgen_futures::spawn_local(async move {
let response = Api::DeleteNotification(id, username)
.fetch(Some(hdrs), None, Method::DELETE)
.await;
});
})
};

html! {
<div class="">
// thumbnail
<span>
<img src={n.img_url.clone()} alt="post thumbnail"/>
</span>
<div class="notification-txt">
<span>{n.username.clone()}{" posted"}</span>
<span onclick={delete_notification}>{" dismiss"}</span>
<div class="notification-txt">
<span onclick={nav_to_post(id)}>{n.username.clone()}{" posted"}</span>
<span onclick={delete_notification(id, store.clone(), notifications.clone())}>{" dismiss"}</span>
</div>
</div>
</div>
}})}
}
})}
}
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion devblog/devblog/client/src/components/post_edit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub fn edit_post(props: &Props) -> Html {
Callback::from(move |e: SubmitEvent| {
e.prevent_default();
let description = description.clone();
let body = Some(helpers::to_jsvalue(description.deref().clone()));
let body = Some(helpers::to_jsvalue(description.deref()));
let hdrs = helpers::create_auth_header(&token);
hdrs.append("content-type", "application/json");
let on_post_edit = on_post_edit.clone();
Expand Down
2 changes: 1 addition & 1 deletion devblog/devblog/client/src/models.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ pub struct VoteCount {
pub down: usize,
}

#[derive(Serialize, Deserialize, Default, PartialEq)]
#[derive(Serialize, Deserialize, Default, PartialEq, Clone)]
pub struct Notification {
#[serde(rename = "imgUrl")]
pub img_url: String,
Expand Down
24 changes: 20 additions & 4 deletions devblog/devblog/client/src/pages/posts.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
use crate::{
components::{pager::Pager, post::Post},
helpers::{self, CustomCallback},
router::Route,
router::{PostQuery, Route},
store::Store,
Api, PostModel,
};
use gloo_net::http::Method;
use stylist::Style;
use yew::prelude::*;
use yew_router::components::Link;
use yew_router::{
components::Link,
hooks::{use_location, use_navigator},
};
use yewdux::use_store_value;

const STYLE: &str = include_str!("styles/posts.css");
Expand All @@ -26,6 +29,8 @@ pub fn posts() -> Html {
let posts_cb = CustomCallback::new(&posts);
let posts_count_cb = CustomCallback::new(&posts_count);
let pages_count_cb = CustomCallback::new(&pages_count);
let location = use_location();
let navigator = use_navigator();

// get pages count and posts count
let get_count = |posts_ct_cb: Callback<i32>, pages_ct_cb: Callback<i32>| {
Expand All @@ -47,10 +52,18 @@ pub fn posts() -> Html {
// get posts for current page
let page_num_clone = page_num.clone();
let loading_clone = loading.clone();
use_effect_with(trigger.clone(), move |_| {
let location = location.clone();
use_effect_with(page_num_clone.clone(), move |_| {
wasm_bindgen_futures::spawn_local(async move {
loading_clone.set(true);
let num = *page_num_clone as u32;
let mut num = *page_num_clone as u32;

let query = location.unwrap().query::<PostQuery>();
if let Ok(q) = query {
num = q.page;
}

page_num_clone.set(num as i32);
let res = Api::GetPage(num).fetch(None, None, Method::GET).await;
helpers::emit(&posts_cb, res.unwrap()).await;
loading_clone.set(false);
Expand All @@ -60,9 +73,12 @@ pub fn posts() -> Html {
// page left / right callback
let trigger_clone = trigger.clone();
let on_pager_click = {
let navigator = navigator.clone().unwrap();
let page_num = page_num.clone();
Callback::from(move |page: i32| {
trigger_clone.set(!*trigger_clone);
let query = &PostQuery { page: page as u32 };
let _ = navigator.push_with_query(&Route::Posts, &query);
page_num.set(page)
})
};
Expand Down
6 changes: 6 additions & 0 deletions devblog/devblog/client/src/router.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use serde::{Deserialize, Serialize};
use yew::{html, Html};
use yew_router::Routable;

Expand Down Expand Up @@ -41,3 +42,8 @@ pub fn switch(routes: Route) -> Html {
Route::SignOut => html! {<SignOut />},
}
}

#[derive(Serialize, Deserialize)]
pub struct PostQuery {
pub page: u32,
}
17 changes: 14 additions & 3 deletions devblog/devblog/client/src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@ use yewdux::prelude::*;
#[derive(Clone, Serialize, Deserialize, Store, PartialEq, Debug, Default)]
#[store(storage = "local")]
pub struct Store {
pub username: String,
pub token: String,
pub expiration: String,
#[serde(default)]
pub authenticated: bool,
pub admin: bool,
pub expiration: String,
pub token: String,
pub username: String,
#[serde(default)]
pub page_num: i32,
}

#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
pub struct PageNum(u32);

impl Default for PageNum {
fn default() -> Self {
PageNum(1)
}
}

0 comments on commit 7a5cf8d

Please sign in to comment.