]> Untitled Git - lemmy.git/commitdiff
Adding post and user details paging.
authorDessalines <tyhou13@gmx.com>
Wed, 17 Apr 2019 18:30:13 +0000 (11:30 -0700)
committerDessalines <tyhou13@gmx.com>
Wed, 17 Apr 2019 18:30:13 +0000 (11:30 -0700)
- Fixes #52
- Fixes #34

server/src/actions/comment_view.rs
server/src/actions/community_view.rs
server/src/actions/moderator_views.rs
server/src/actions/post_view.rs
server/src/lib.rs
server/src/websocket_server/server.rs
ui/src/components/post-listings.tsx
ui/src/components/user.tsx
ui/src/interfaces.ts
ui/src/utils.ts

index d6d9e40173d856b9cf94ccc2c42bc2c609927b2e..0848ee1c15370bccd9084fc5f2b7b47057c1dd65 100644 (file)
@@ -3,7 +3,7 @@ use diesel::*;
 use diesel::result::Error;
 use diesel::dsl::*;
 use serde::{Deserialize, Serialize};
-use { SortType };
+use { SortType, limit_and_offset };
 
 // The faked schema since diesel doesn't do views
 table! {
@@ -57,10 +57,15 @@ impl CommentView {
               for_post_id: Option<i32>, 
               for_creator_id: Option<i32>, 
               my_user_id: Option<i32>, 
-              limit: i64) -> Result<Vec<Self>, Error> {
+              page: Option<i64>,
+              limit: Option<i64>,
+              ) -> Result<Vec<Self>, Error> {
     use actions::comment_view::comment_view::dsl::*;
 
-    let mut query = comment_view.limit(limit).into_boxed();
+    let (limit, offset) = limit_and_offset(page, limit);
+
+    // TODO no limits here?
+    let mut query = comment_view.into_boxed();
 
     // The view lets you pass a null user_id, if you're not logged in
     if let Some(my_user_id) = my_user_id {
@@ -96,7 +101,10 @@ impl CommentView {
               _ => query.order_by(published.desc())
     };
 
-    query.load::<Self>(conn) 
+    query
+      .limit(limit)
+      .offset(offset)
+      .load::<Self>(conn) 
   }
 
   pub fn read(conn: &PgConnection, from_comment_id: i32, my_user_id: Option<i32>) -> Result<Self, Error> {
@@ -230,8 +238,8 @@ mod tests {
       am_mod: None,
     };
 
-    let read_comment_views_no_user = CommentView::list(&conn, &SortType::New, Some(inserted_post.id), None, None, 999).unwrap();
-    let read_comment_views_with_user = CommentView::list(&conn, &SortType::New, Some(inserted_post.id), None, Some(inserted_user.id), 999).unwrap();
+    let read_comment_views_no_user = CommentView::list(&conn, &SortType::New, Some(inserted_post.id), None, None, None, None).unwrap();
+    let read_comment_views_with_user = CommentView::list(&conn, &SortType::New, Some(inserted_post.id), None, Some(inserted_user.id), None, None).unwrap();
     let like_removed = CommentLike::remove(&conn, &comment_like_form).unwrap();
     let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap();
     Post::delete(&conn, inserted_post.id).unwrap();
index 078e7a6ea644caa85f41a341176419069d396f15..a754c2e8280a9f2fe878a98d35175ccbdf146a08 100644 (file)
@@ -2,7 +2,7 @@ extern crate diesel;
 use diesel::*;
 use diesel::result::Error;
 use serde::{Deserialize, Serialize};
-use {SortType};
+use {SortType, limit_and_offset};
 
 table! {
   community_view (id) {
@@ -114,14 +114,18 @@ impl CommunityView {
     query.first::<Self>(conn)
   }
 
-  pub fn list(conn: &PgConnection, from_user_id: Option<i32>, sort: SortType, limit: Option<i64>) -> Result<Vec<Self>, Error> {
+  pub fn list(conn: &PgConnection, 
+              from_user_id: Option<i32>, 
+              sort: SortType, 
+              page: Option<i64>,
+              limit: Option<i64>,
+              ) -> Result<Vec<Self>, Error> {
     use actions::community_view::community_view::dsl::*;
     let mut query = community_view.into_boxed();
 
-
+    let (limit, offset) = limit_and_offset(page, limit);
 
     // The view lets you pass a null user_id, if you're not logged in
-
     match sort {
       SortType::New => query = query.order_by(published.desc()).filter(user_id.is_null()),
       SortType::TopAll => {
@@ -133,11 +137,11 @@ impl CommunityView {
       _ => ()
     };
 
-    if let Some(limit) = limit {
-      query = query.limit(limit);
-    };
-
-    query.filter(removed.eq(false)).load::<Self>(conn) 
+    query
+      .limit(limit)
+      .offset(offset)
+      .filter(removed.eq(false))
+      .load::<Self>(conn) 
   }
 }
 
index 2e2435682164fcdb3c3de946eb59ac4c4e890efd..89418277102ae2662ddcf1f2b9b2b88e5169bb60 100644 (file)
@@ -2,6 +2,7 @@ extern crate diesel;
 use diesel::*;
 use diesel::result::Error;
 use serde::{Deserialize, Serialize};
+use {limit_and_offset};
 
 table! {
   mod_remove_post_view (id) {
@@ -37,14 +38,13 @@ impl ModRemovePostView {
   pub fn list(conn: &PgConnection, 
               from_community_id: Option<i32>, 
               from_mod_user_id: Option<i32>, 
+              page: Option<i64>,
               limit: Option<i64>, 
-              page: Option<i64>) -> Result<Vec<Self>, Error> {
+              ) -> Result<Vec<Self>, Error> {
     use actions::moderator_views::mod_remove_post_view::dsl::*;
     let mut query = mod_remove_post_view.into_boxed();
 
-    let page = page.unwrap_or(1);
-    let limit = limit.unwrap_or(10);
-    let offset = limit * (page - 1);
+    let (limit, offset) = limit_and_offset(page, limit);
 
     if let Some(from_community_id) = from_community_id {
       query = query.filter(community_id.eq(from_community_id));
@@ -91,14 +91,13 @@ impl ModLockPostView {
   pub fn list(conn: &PgConnection, 
               from_community_id: Option<i32>, 
               from_mod_user_id: Option<i32>, 
+              page: Option<i64>,
               limit: Option<i64>, 
-              page: Option<i64>) -> Result<Vec<Self>, Error> {
+              ) -> Result<Vec<Self>, Error> {
     use actions::moderator_views::mod_lock_post_view::dsl::*;
     let mut query = mod_lock_post_view.into_boxed();
 
-    let page = page.unwrap_or(1);
-    let limit = limit.unwrap_or(10);
-    let offset = limit * (page - 1);
+    let (limit, offset) = limit_and_offset(page, limit);
 
     if let Some(from_community_id) = from_community_id {
       query = query.filter(community_id.eq(from_community_id));
@@ -154,14 +153,13 @@ impl ModRemoveCommentView {
   pub fn list(conn: &PgConnection, 
               from_community_id: Option<i32>, 
               from_mod_user_id: Option<i32>, 
+              page: Option<i64>,
               limit: Option<i64>, 
-              page: Option<i64>) -> Result<Vec<Self>, Error> {
+             ) -> Result<Vec<Self>, Error> {
     use actions::moderator_views::mod_remove_comment_view::dsl::*;
     let mut query = mod_remove_comment_view.into_boxed();
 
-    let page = page.unwrap_or(1);
-    let limit = limit.unwrap_or(10);
-    let offset = limit * (page - 1);
+    let (limit, offset) = limit_and_offset(page, limit);
 
     if let Some(from_community_id) = from_community_id {
       query = query.filter(community_id.eq(from_community_id));
@@ -206,14 +204,13 @@ pub struct ModRemoveCommunityView {
 impl ModRemoveCommunityView {
   pub fn list(conn: &PgConnection, 
               from_mod_user_id: Option<i32>, 
+              page: Option<i64>,
               limit: Option<i64>, 
-              page: Option<i64>) -> Result<Vec<Self>, Error> {
+              ) -> Result<Vec<Self>, Error> {
     use actions::moderator_views::mod_remove_community_view::dsl::*;
     let mut query = mod_remove_community_view.into_boxed();
 
-    let page = page.unwrap_or(1);
-    let limit = limit.unwrap_or(10);
-    let offset = limit * (page - 1);
+    let (limit, offset) = limit_and_offset(page, limit);
 
     if let Some(from_mod_user_id) = from_mod_user_id {
       query = query.filter(mod_user_id.eq(from_mod_user_id));
@@ -260,14 +257,13 @@ impl ModBanFromCommunityView {
   pub fn list(conn: &PgConnection, 
               from_community_id: Option<i32>, 
               from_mod_user_id: Option<i32>, 
+              page: Option<i64>,
               limit: Option<i64>, 
-              page: Option<i64>) -> Result<Vec<Self>, Error> {
+              ) -> Result<Vec<Self>, Error> {
     use actions::moderator_views::mod_ban_from_community_view::dsl::*;
     let mut query = mod_ban_from_community_view.into_boxed();
 
-    let page = page.unwrap_or(1);
-    let limit = limit.unwrap_or(10);
-    let offset = limit * (page - 1);
+    let (limit, offset) = limit_and_offset(page, limit);
 
     if let Some(from_community_id) = from_community_id {
       query = query.filter(community_id.eq(from_community_id));
@@ -312,14 +308,13 @@ pub struct ModBanView {
 impl ModBanView {
   pub fn list(conn: &PgConnection, 
               from_mod_user_id: Option<i32>, 
+              page: Option<i64>,
               limit: Option<i64>, 
-              page: Option<i64>) -> Result<Vec<Self>, Error> {
+              ) -> Result<Vec<Self>, Error> {
     use actions::moderator_views::mod_ban_view::dsl::*;
     let mut query = mod_ban_view.into_boxed();
 
-    let page = page.unwrap_or(1);
-    let limit = limit.unwrap_or(10);
-    let offset = limit * (page - 1);
+    let (limit, offset) = limit_and_offset(page, limit);
 
     if let Some(from_mod_user_id) = from_mod_user_id {
       query = query.filter(mod_user_id.eq(from_mod_user_id));
@@ -361,14 +356,13 @@ impl ModAddCommunityView {
   pub fn list(conn: &PgConnection, 
               from_community_id: Option<i32>, 
               from_mod_user_id: Option<i32>, 
+              page: Option<i64>,
               limit: Option<i64>, 
-              page: Option<i64>) -> Result<Vec<Self>, Error> {
+              ) -> Result<Vec<Self>, Error> {
     use actions::moderator_views::mod_add_community_view::dsl::*;
     let mut query = mod_add_community_view.into_boxed();
 
-    let page = page.unwrap_or(1);
-    let limit = limit.unwrap_or(10);
-    let offset = limit * (page - 1);
+    let (limit, offset) = limit_and_offset(page, limit);
 
     if let Some(from_community_id) = from_community_id {
       query = query.filter(community_id.eq(from_community_id));
@@ -409,14 +403,13 @@ pub struct ModAddView {
 impl ModAddView {
   pub fn list(conn: &PgConnection, 
               from_mod_user_id: Option<i32>, 
+              page: Option<i64>,
               limit: Option<i64>, 
-              page: Option<i64>) -> Result<Vec<Self>, Error> {
+              ) -> Result<Vec<Self>, Error> {
     use actions::moderator_views::mod_add_view::dsl::*;
     let mut query = mod_add_view.into_boxed();
 
-    let page = page.unwrap_or(1);
-    let limit = limit.unwrap_or(10);
-    let offset = limit * (page - 1);
+    let (limit, offset) = limit_and_offset(page, limit);
 
     if let Some(from_mod_user_id) = from_mod_user_id {
       query = query.filter(mod_user_id.eq(from_mod_user_id));
index f95c0177167644086ed97ed2b3038832fe37270f..7ab490aacb45e292f795c06b204e24bec9621415 100644 (file)
@@ -3,7 +3,7 @@ use diesel::*;
 use diesel::result::Error;
 use diesel::dsl::*;
 use serde::{Deserialize, Serialize};
-use { SortType };
+use { SortType, limit_and_offset };
 
 #[derive(EnumString,ToString,Debug, Serialize, Deserialize)]
 pub enum PostListingType {
@@ -71,10 +71,14 @@ impl PostView {
               for_community_id: Option<i32>, 
               for_creator_id: Option<i32>, 
               my_user_id: Option<i32>, 
-              limit: i64) -> Result<Vec<Self>, Error> {
+              page: Option<i64>,
+              limit: Option<i64>,
+              ) -> Result<Vec<Self>, Error> {
     use actions::post_view::post_view::dsl::*;
 
-    let mut query = post_view.limit(limit).into_boxed();
+    let (limit, offset) = limit_and_offset(page, limit);
+
+    let mut query = post_view.into_boxed();
 
     if let Some(for_community_id) = for_community_id {
       query = query.filter(community_id.eq(for_community_id));
@@ -119,7 +123,10 @@ impl PostView {
 
     // TODO make sure community removed isn't fetched either
 
-    query = query.filter(removed.eq(false));
+    query = query
+      .limit(limit)
+      .offset(offset)
+      .filter(removed.eq(false));
 
     query.load::<Self>(conn) 
   }
@@ -271,8 +278,8 @@ mod tests {
     };
 
 
-    let read_post_listings_with_user = PostView::list(&conn, PostListingType::Community, &SortType::New, Some(inserted_community.id), None, Some(inserted_user.id), 10).unwrap();
-    let read_post_listings_no_user = PostView::list(&conn, PostListingType::Community, &SortType::New, Some(inserted_community.id), None, None, 10).unwrap();
+    let read_post_listings_with_user = PostView::list(&conn, PostListingType::Community, &SortType::New, Some(inserted_community.id), None, Some(inserted_user.id), None, None).unwrap();
+    let read_post_listings_no_user = PostView::list(&conn, PostListingType::Community, &SortType::New, Some(inserted_community.id), None, None, None, None).unwrap();
     let read_post_listing_no_user = PostView::read(&conn, inserted_post.id, None).unwrap();
     let read_post_listing_with_user = PostView::read(&conn, inserted_post.id, Some(inserted_user.id)).unwrap();
 
index ab971edd9f215b98548678449ab9eab0d79df7b0..3390dbdc5e8d721db21160eed7fe7d948e6dcfcc 100644 (file)
@@ -109,6 +109,13 @@ pub fn has_slurs(test: &str) -> bool {
   SLUR_REGEX.is_match(test)
 }
 
+pub fn limit_and_offset(page: Option<i64>, limit: Option<i64>) -> (i64, i64) {
+    let page = page.unwrap_or(1);
+    let limit = limit.unwrap_or(10);
+    let offset = limit * (page - 1);
+    (limit, offset)
+}
+
 #[cfg(test)]
 mod tests {
   use {Settings, is_email_regex, remove_slurs, has_slurs};
index 6b91a76b60fbc177742ac943fed094bbfec2bd5a..4f0efb094160d2b4e96c5d4f92272783d8d6310b 100644 (file)
@@ -116,6 +116,7 @@ pub struct CommunityResponse {
 #[derive(Serialize, Deserialize)]
 pub struct ListCommunities {
   sort: String,
+  page: Option<i64>,
   limit: Option<i64>,
   auth: Option<String>
 }
@@ -170,7 +171,8 @@ pub struct GetPostResponse {
 pub struct GetPosts {
   type_: String,
   sort: String,
-  limit: i64,
+  page: Option<i64>,
+  limit: Option<i64>,
   community_id: Option<i32>,
   auth: Option<String>
 }
@@ -292,7 +294,8 @@ pub struct GetFollowedCommunitiesResponse {
 pub struct GetUserDetails {
   user_id: i32,
   sort: String,
-  limit: i64,
+  page: Option<i64>,
+  limit: Option<i64>,
   community_id: Option<i32>,
   auth: Option<String>
 }
@@ -313,8 +316,8 @@ pub struct GetUserDetailsResponse {
 pub struct GetModlog {
   mod_user_id: Option<i32>,
   community_id: Option<i32>,
-  limit: Option<i64>,
   page: Option<i64>,
+  limit: Option<i64>,
 }
 
 #[derive(Serialize, Deserialize)]
@@ -465,7 +468,9 @@ impl ChatServer {
                                Some(community_id), 
                                None,
                                None, 
-                               999).unwrap();
+                               None,
+                               Some(9999))
+      .unwrap();
     for post in posts {
       self.send_room_message(post.id, message, skip_id);
     }
@@ -871,7 +876,7 @@ impl Perform for ListCommunities {
 
     let sort = SortType::from_str(&self.sort).expect("listing sort");
 
-    let communities: Vec<CommunityView> = CommunityView::list(&conn, user_id, sort, self.limit).unwrap();
+    let communities: Vec<CommunityView> = CommunityView::list(&conn, user_id, sort, self.page, self.limit).unwrap();
 
     // Return the jwt
     serde_json::to_string(
@@ -1026,7 +1031,7 @@ impl Perform for GetPost {
 
     chat.rooms.get_mut(&self.id).unwrap().insert(addr);
 
-    let comments = CommentView::list(&conn, &SortType::New, Some(self.id), None, user_id, 999).unwrap();
+    let comments = CommentView::list(&conn, &SortType::New, Some(self.id), None, user_id, None, Some(9999)).unwrap();
 
     let community = CommunityView::read(&conn, post_view.community_id, user_id).unwrap();
 
@@ -1372,7 +1377,7 @@ impl Perform for GetPosts {
     let type_ = PostListingType::from_str(&self.type_).expect("listing type");
     let sort = SortType::from_str(&self.sort).expect("listing sort");
 
-    let posts = match PostView::list(&conn, type_, &sort, self.community_id, None, user_id, self.limit) {
+    let posts = match PostView::list(&conn, type_, &sort, self.community_id, None, user_id, self.page, self.limit) {
       Ok(posts) => posts,
       Err(_e) => {
         return self.error("Couldn't get posts");
@@ -1758,8 +1763,8 @@ impl Perform for GetUserDetails {
     let sort = SortType::from_str(&self.sort).expect("listing sort");
 
     let user_view = UserView::read(&conn, self.user_id).unwrap();
-    let posts = PostView::list(&conn, PostListingType::All, &sort, self.community_id, Some(self.user_id), user_id, self.limit).unwrap();
-    let comments = CommentView::list(&conn, &sort, None, Some(self.user_id), user_id, self.limit).unwrap();
+    let posts = PostView::list(&conn, PostListingType::All, &sort, self.community_id, Some(self.user_id), user_id, self.page, self.limit).unwrap();
+    let comments = CommentView::list(&conn, &sort, None, Some(self.user_id), user_id, self.page, self.limit).unwrap();
     let follows = CommunityFollowerView::for_user(&conn, self.user_id).unwrap();
     let moderates = CommunityModeratorView::for_user(&conn, self.user_id).unwrap();
 
@@ -1789,11 +1794,11 @@ impl Perform for GetModlog {
 
     let conn = establish_connection();
 
-    let removed_posts = ModRemovePostView::list(&conn, self.community_id, self.mod_user_id, self.limit, self.page).unwrap();
-    let locked_posts = ModLockPostView::list(&conn, self.community_id, self.mod_user_id, self.limit, self.page).unwrap();
-    let removed_comments = ModRemoveCommentView::list(&conn, self.community_id, self.mod_user_id, self.limit, self.page).unwrap();
-    let banned_from_community = ModBanFromCommunityView::list(&conn, self.community_id, self.mod_user_id, self.limit, self.page).unwrap();
-    let added_to_community = ModAddCommunityView::list(&conn, self.community_id, self.mod_user_id, self.limit, self.page).unwrap();
+    let removed_posts = ModRemovePostView::list(&conn, self.community_id, self.mod_user_id, self.page, self.limit).unwrap();
+    let locked_posts = ModLockPostView::list(&conn, self.community_id, self.mod_user_id, self.page, self.limit).unwrap();
+    let removed_comments = ModRemoveCommentView::list(&conn, self.community_id, self.mod_user_id, self.page, self.limit).unwrap();
+    let banned_from_community = ModBanFromCommunityView::list(&conn, self.community_id, self.mod_user_id, self.page, self.limit).unwrap();
+    let added_to_community = ModAddCommunityView::list(&conn, self.community_id, self.mod_user_id, self.page, self.limit).unwrap();
 
     // These arrays are only for the full modlog, when a community isn't given
     let mut removed_communities = Vec::new();
index 34814400833f0cf80159ca85b70220274f38ca02..5fbb6cbf861b998797c9f378f6da4109e62d3c02 100644 (file)
@@ -5,8 +5,7 @@ import { retryWhen, delay, take } from 'rxjs/operators';
 import { UserOperation, Community as CommunityI, Post, GetPostsForm, SortType, ListingType, GetPostsResponse, CreatePostLikeResponse, CommunityUser} from '../interfaces';
 import { WebSocketService, UserService } from '../services';
 import { PostListing } from './post-listing';
-import { msgOp } from '../utils';
-
+import { msgOp, fetchLimit } from '../utils';
 
 interface PostListingsProps {
   communityId?: number;
@@ -18,6 +17,7 @@ interface PostListingsState {
   posts: Array<Post>;
   sortType: SortType;
   type_: ListingType;
+  page: number;
   loading: boolean;
 }
 
@@ -46,6 +46,7 @@ export class PostListings extends Component<PostListingsProps, PostListingsState
     : UserService.Instance.user
     ? ListingType.Subscribed 
     : ListingType.All,
+    page: 1,
     loading: true
   }
 
@@ -63,13 +64,7 @@ export class PostListings extends Component<PostListingsProps, PostListingsState
         () => console.log('complete')
       );
 
-    let getPostsForm: GetPostsForm = {
-      type_: ListingType[this.state.type_],
-      community_id: this.props.communityId,
-      limit: 10,
-      sort: SortType[SortType.Hot],
-    }
-    WebSocketService.Instance.getPosts(getPostsForm);
+      this.refetch();
   }
 
   componentWillUnmount() {
@@ -82,12 +77,13 @@ export class PostListings extends Component<PostListingsProps, PostListingsState
         {this.state.loading ? 
         <h4><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h4> : 
         <div>
-          <div>{this.selects()}</div>
+          {this.selects()}
           {this.state.posts.length > 0 
             ? this.state.posts.map(post => 
               <PostListing post={post} showCommunity={!this.props.communityId}/>) 
                 : <div>No Listings. {!this.props.communityId && <span>Subscribe to some <Link to="/communities">forums</Link>.</span>}</div>
           }
+          {this.paginator()}
         </div>
         }
       </div>
@@ -119,17 +115,44 @@ export class PostListings extends Component<PostListingsProps, PostListingsState
         }
       </div>
     )
+  }
 
+  paginator() {
+    return (
+      <div class="mt-2">
+        {this.state.page > 1 && 
+          <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}>Prev</button>
+        }
+        <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}>Next</button>
+      </div>
+    );
+  }
+
+  nextPage(i: PostListings) { 
+    i.state.page++;
+    i.setState(i.state);
+    i.refetch();
+  }
+
+  prevPage(i: PostListings) { 
+    i.state.page--;
+    i.setState(i.state);
+    i.refetch();
   }
 
   handleSortChange(i: PostListings, event: any) {
     i.state.sortType = Number(event.target.value);
+    i.state.page = 1;
     i.setState(i.state);
+    i.refetch();
+  }
 
+  refetch() {
     let getPostsForm: GetPostsForm = {
-      community_id: i.state.community.id,
-      limit: 10,
-      sort: SortType[i.state.sortType],
+      community_id: this.state.community.id,
+      page: this.state.page,
+      limit: fetchLimit,
+      sort: SortType[this.state.sortType],
       type_: ListingType[ListingType.Community]
     }
     WebSocketService.Instance.getPosts(getPostsForm);
@@ -137,14 +160,9 @@ export class PostListings extends Component<PostListingsProps, PostListingsState
 
   handleTypeChange(i: PostListings, event: any) {
     i.state.type_ = Number(event.target.value);
+    i.state.page = 1;
     i.setState(i.state);
-
-    let getPostsForm: GetPostsForm = {
-      limit: 10,
-      sort: SortType[i.state.sortType],
-      type_: ListingType[i.state.type_]
-    }
-    WebSocketService.Instance.getPosts(getPostsForm);
+    i.refetch();
   }
 
   parseMessage(msg: any) {
index b899686a69ba851a1302065e60c541e8ed2ee1cc..fdcd378e0b7cd1580fd9cd81013c65fade50242a 100644 (file)
@@ -4,7 +4,7 @@ import { Subscription } from "rxjs";
 import { retryWhen, delay, take } from 'rxjs/operators';
 import { UserOperation, Post, Comment, CommunityUser, GetUserDetailsForm, SortType, UserDetailsResponse, UserView } from '../interfaces';
 import { WebSocketService } from '../services';
-import { msgOp } from '../utils';
+import { msgOp, fetchLimit } from '../utils';
 import { PostListing } from './post-listing';
 import { CommentNodes } from './comment-nodes';
 import { MomentTime } from './moment-time';
@@ -15,6 +15,7 @@ enum View {
 
 interface UserState {
   user: UserView;
+  user_id: number;
   follows: Array<CommunityUser>;
   moderates: Array<CommunityUser>;
   comments: Array<Comment>;
@@ -22,6 +23,7 @@ interface UserState {
   saved?: Array<Post>;
   view: View;
   sort: SortType;
+  page: number;
 }
 
 export class User extends Component<any, UserState> {
@@ -38,12 +40,14 @@ export class User extends Component<any, UserState> {
       number_of_comments: null,
       comment_score: null,
     },
+    user_id: null,
     follows: [],
     moderates: [],
     comments: [],
     posts: [],
     view: View.Overview,
-    sort: SortType.New
+    sort: SortType.New,
+    page: 1,
   }
 
   constructor(props: any, context: any) {
@@ -51,7 +55,7 @@ export class User extends Component<any, UserState> {
 
     this.state = this.emptyState;
 
-    let userId = Number(this.props.match.params.id);
+    this.state.user_id = Number(this.props.match.params.id);
 
     this.subscription = WebSocketService.Instance.subject
     .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
@@ -61,12 +65,7 @@ export class User extends Component<any, UserState> {
         () => console.log('complete')
     );
 
-    let form: GetUserDetailsForm = {
-      user_id: userId,
-      sort: SortType[this.state.sort],
-      limit: 999
-    };
-    WebSocketService.Instance.getUserDetails(form);
+    this.refetch();
   }
 
   componentWillUnmount() {
@@ -89,6 +88,7 @@ export class User extends Component<any, UserState> {
             {this.state.view == View.Posts &&
               this.posts()
             }
+            {this.paginator()}
           </div>
           <div class="col-12 col-md-3">
             {this.userInfo()}
@@ -230,21 +230,51 @@ export class User extends Component<any, UserState> {
     )
   }
 
-  handleSortChange(i: User, event: any) {
-    i.state.sort = Number(event.target.value);
+  paginator() {
+    return (
+      <div class="mt-2">
+        {this.state.page > 1 && 
+          <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}>Prev</button>
+        }
+        <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}>Next</button>
+      </div>
+    );
+  }
+
+  nextPage(i: User) { 
+    i.state.page++;
+    i.setState(i.state);
+    i.refetch();
+  }
+
+  prevPage(i: User) { 
+    i.state.page--;
     i.setState(i.state);
+    i.refetch();
+  }
 
+  refetch() {
     let form: GetUserDetailsForm = {
-      user_id: i.state.user.id,
-      sort: SortType[i.state.sort],
-      limit: 999
+      user_id: this.state.user_id,
+      sort: SortType[this.state.sort],
+      page: this.state.page,
+      limit: fetchLimit,
     };
     WebSocketService.Instance.getUserDetails(form);
   }
 
+  handleSortChange(i: User, event: any) {
+    i.state.sort = Number(event.target.value);
+    i.state.page = 1;
+    i.setState(i.state);
+    i.refetch();
+  }
+
   handleViewChange(i: User, event: any) {
     i.state.view = Number(event.target.value);
+    i.state.page = 1;
     i.setState(i.state);
+    i.refetch();
   }
 
   parseMessage(msg: any) {
index 869fb60bd7396b6c5ca1aee5a92a4d4d5814a264..6affc0e126150bd8cee33ae14ad3929583437570 100644 (file)
@@ -134,7 +134,8 @@ export interface GetFollowedCommunitiesResponse {
 export interface GetUserDetailsForm {
   user_id: number;
   sort: string; // TODO figure this one out
-  limit: number;
+  page?: number;
+  limit?: number;
   community_id?: number;
   auth?: string;
 }
@@ -179,8 +180,8 @@ export interface AddModToCommunityResponse {
 export interface GetModlogForm {
   mod_user_id?: number;
   community_id?: number;
-  limit?: number;
   page?: number;
+  limit?: number;
 }
 
 export interface GetModlogResponse {
@@ -343,6 +344,7 @@ export interface CommunityResponse {
 
 export interface ListCommunitiesForm {
   sort: string;
+  page?: number;
   limit?: number;
   auth?: string;
 }
@@ -356,6 +358,7 @@ export interface ListCategoriesResponse {
   op: string;
   categories: Array<Category>;
 }
+
 export interface PostForm {
   name: string;
   url?: string;
@@ -414,7 +417,8 @@ export interface CommentNode {
 export interface GetPostsForm {
   type_: string;
   sort: string;
-  limit: number;
+  page?: number;
+  limit?: number;
   community_id?: number;
   auth?: string;
 }
index 4bd0d90dfc9acd1da8282010202cfa4861ba3893..c7f3bad8060432bc310745d76b1948c3b112599f 100644 (file)
@@ -39,3 +39,5 @@ export function getUnixTime(text: string): number {
 export function addTypeInfo<T>(arr: Array<T>, name: string): Array<{type_: string, data: T}> {  
   return arr.map(e => {return {type_: name, data: e}});
 }
+
+export let fetchLimit: number = 20;