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