diff --git a/crates/app/src/public/html/misc/notifications.lisp b/crates/app/src/public/html/misc/notifications.lisp index 7e6dabb..210021b 100644 --- a/crates/app/src/public/html/misc/notifications.lisp +++ b/crates/app/src/public/html/misc/notifications.lisp @@ -54,7 +54,9 @@ (text "{{ text \"notifs:label.mark_all_as_unread\" }}"))))))) (div ("class" "card tertiary flex flex-col gap-4") - (text "{% for notification in notifications %} {{ components::notification(notification=notification) }} {% endfor %}")))) + (text "{% for notification in notifications %} {{ components::notification(notification=notification) }} {% endfor %}"))) + + (text "{{ components::pagination(page=page, items=notifications|length, key=\"&id=\", value=profile.id) }}")) (script (text "async function mark_all_as_read(read) { diff --git a/crates/app/src/public/html/misc/requests.lisp b/crates/app/src/public/html/misc/requests.lisp index 374ee31..1bbd19f 100644 --- a/crates/app/src/public/html/misc/requests.lisp +++ b/crates/app/src/public/html/misc/requests.lisp @@ -128,7 +128,9 @@ ("class" "red quaternary") ("onclick" "trigger('me::ip_block_question', ['{{ question[0].id }}'])") (text "{{ text \"auth:action.ip_block\" }}"))))) - (text "{% endfor %}")))) + (text "{% endfor %}"))) + + (text "{{ components::pagination(page=page, items=requests|length, key=\"&id=\", value=profile.id) }}")) (script (text "async function remove_request(id, linked_asset) { diff --git a/crates/app/src/routes/pages/misc.rs b/crates/app/src/routes/pages/misc.rs index e6c1581..e71d95c 100644 --- a/crates/app/src/routes/pages/misc.rs +++ b/crates/app/src/routes/pages/misc.rs @@ -361,6 +361,8 @@ pub async fn all_questions_request( pub struct NotificationsProps { #[serde(default)] pub id: usize, + #[serde(default)] + pub page: usize, } /// `/notifs` @@ -379,7 +381,7 @@ pub async fn notifications_request( } }; - let profile = if props.id != 0 { + let profile = if props.id != 0 && user.permissions.check(FinePermission::MANAGE_NOTIFICATIONS) { match data.0.get_user_by_id(props.id).await { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &None).await)), @@ -388,7 +390,11 @@ pub async fn notifications_request( user.clone() }; - let notifications = match data.0.get_notifications_by_owner(profile.id).await { + let notifications = match data + .0 + .get_notifications_by_owner_paginated(profile.id, 12, props.page) + .await + { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &Some(user)).await)), }; @@ -396,6 +402,7 @@ pub async fn notifications_request( let lang = get_lang!(jar, data.0); let mut context = initial_context(&data.0.0, lang, &Some(user)).await; + context.insert("page", &props.page); context.insert("profile", &profile); context.insert("notifications", ¬ifications); @@ -421,7 +428,7 @@ pub async fn requests_request( } }; - let profile = if props.id != 0 { + let profile = if props.id != 0 && user.permissions.check(FinePermission::MANAGE_REQUESTS) { match data.0.get_user_by_id(props.id).await { Ok(p) => p, Err(e) => return Err(Html(render_error(e, &jar, &data, &None).await)), @@ -432,7 +439,11 @@ pub async fn requests_request( let requests = match data .0 - .get_requests_by_owner(if props.id != 0 { props.id } else { user.id }) + .get_requests_by_owner_paginated( + if props.id != 0 { props.id } else { user.id }, + 12, + props.page, + ) .await { Ok(p) => p, @@ -481,6 +492,7 @@ pub async fn requests_request( let lang = get_lang!(jar, data.0); let mut context = initial_context(&data.0.0, lang, &Some(user)).await; + context.insert("page", &props.page); context.insert("profile", &profile); context.insert("requests", &requests); context.insert("questions", &questions); diff --git a/crates/core/src/database/notifications.rs b/crates/core/src/database/notifications.rs index 2a23ee5..562f9e7 100644 --- a/crates/core/src/database/notifications.rs +++ b/crates/core/src/database/notifications.rs @@ -53,6 +53,32 @@ impl DataManager { Ok(res.unwrap()) } + /// Get all notifications by `owner` (paginated). + pub async fn get_notifications_by_owner_paginated( + &self, + owner: usize, + batch: usize, + page: usize, + ) -> Result> { + let conn = match self.connect().await { + Ok(c) => c, + Err(e) => return Err(Error::DatabaseConnection(e.to_string())), + }; + + let res = query_rows!( + &conn, + "SELECT * FROM notifications WHERE owner = $1 ORDER BY created DESC LIMIT $2 OFFSET $3", + &[&(owner as i64), &(batch as i64), &((page * batch) as i64)], + |x| { Self::get_notification_from_row(x) } + ); + + if res.is_err() { + return Err(Error::GeneralNotFound("notification".to_string())); + } + + Ok(res.unwrap()) + } + /// Get all notifications by `tag`. pub async fn get_notifications_by_tag(&self, tag: &str) -> Result> { let conn = match self.connect().await { diff --git a/crates/core/src/database/requests.rs b/crates/core/src/database/requests.rs index e554e7d..f633c7c 100644 --- a/crates/core/src/database/requests.rs +++ b/crates/core/src/database/requests.rs @@ -86,6 +86,32 @@ impl DataManager { Ok(res.unwrap()) } + /// Get all action requests by `owner` (paginated). + pub async fn get_requests_by_owner_paginated( + &self, + owner: usize, + batch: usize, + page: usize, + ) -> Result> { + let conn = match self.connect().await { + Ok(c) => c, + Err(e) => return Err(Error::DatabaseConnection(e.to_string())), + }; + + let res = query_rows!( + &conn, + "SELECT * FROM requests WHERE owner = $1 ORDER BY created DESC LIMIT $2 OFFSET $3", + &[&(owner as i64), &(batch as i64), &((page * batch) as i64)], + |x| { Self::get_request_from_row(x) } + ); + + if res.is_err() { + return Err(Error::GeneralNotFound("request".to_string())); + } + + Ok(res.unwrap()) + } + /// Create a new request in the database. /// /// # Arguments