From 90ce1f1a3fca5c8d8a13e91f991b23ecb77f1faf Mon Sep 17 00:00:00 2001 From: Dessalines Date: Sun, 20 Oct 2019 21:21:54 -0700 Subject: [PATCH] Adding default sort / filter into user settings. - Fixes #295 --- .../down.sql | 2 + .../up.sql | 2 + server/src/api/post.rs | 2 +- server/src/api/site.rs | 6 +- server/src/api/user.rs | 16 ++++- server/src/apub.rs | 3 + server/src/db/comment.rs | 2 + server/src/db/comment_view.rs | 2 + server/src/db/community.rs | 2 + server/src/db/mod.rs | 7 ++ server/src/db/moderator.rs | 4 ++ server/src/db/post.rs | 2 + server/src/db/post_view.rs | 17 ++--- server/src/db/user.rs | 12 ++++ server/src/db/user_mention.rs | 4 ++ server/src/schema.rs | 2 + server/src/websocket/server.rs | 2 +- ui/src/components/community.tsx | 4 +- ui/src/components/listing-type-select.tsx | 68 +++++++++++++++++++ ui/src/components/main.tsx | 53 +++++---------- ui/src/components/user.tsx | 64 ++++++++++++++++- ui/src/interfaces.ts | 4 ++ 22 files changed, 220 insertions(+), 60 deletions(-) create mode 100644 server/migrations/2019-10-21-011237_add_default_sorts/down.sql create mode 100644 server/migrations/2019-10-21-011237_add_default_sorts/up.sql create mode 100644 ui/src/components/listing-type-select.tsx diff --git a/server/migrations/2019-10-21-011237_add_default_sorts/down.sql b/server/migrations/2019-10-21-011237_add_default_sorts/down.sql new file mode 100644 index 000000000..238c9e796 --- /dev/null +++ b/server/migrations/2019-10-21-011237_add_default_sorts/down.sql @@ -0,0 +1,2 @@ +alter table user_ drop column default_sort_type; +alter table user_ drop column default_listing_type; diff --git a/server/migrations/2019-10-21-011237_add_default_sorts/up.sql b/server/migrations/2019-10-21-011237_add_default_sorts/up.sql new file mode 100644 index 000000000..4bb960094 --- /dev/null +++ b/server/migrations/2019-10-21-011237_add_default_sorts/up.sql @@ -0,0 +1,2 @@ +alter table user_ add column default_sort_type smallint default 0 not null; +alter table user_ add column default_listing_type smallint default 1 not null; diff --git a/server/src/api/post.rs b/server/src/api/post.rs index d53d2064a..5df42990a 100644 --- a/server/src/api/post.rs +++ b/server/src/api/post.rs @@ -235,7 +235,7 @@ impl Perform for Oper { None => false, }; - let type_ = PostListingType::from_str(&data.type_)?; + let type_ = ListingType::from_str(&data.type_)?; let sort = SortType::from_str(&data.sort)?; let posts = match PostView::list( diff --git a/server/src/api/site.rs b/server/src/api/site.rs index 40b1592dd..618295fca 100644 --- a/server/src/api/site.rs +++ b/server/src/api/site.rs @@ -321,7 +321,7 @@ impl Perform for Oper { SearchType::Posts => { posts = PostView::list( &conn, - PostListingType::All, + ListingType::All, &sort, data.community_id, None, @@ -365,7 +365,7 @@ impl Perform for Oper { SearchType::All => { posts = PostView::list( &conn, - PostListingType::All, + ListingType::All, &sort, data.community_id, None, @@ -403,7 +403,7 @@ impl Perform for Oper { SearchType::Url => { posts = PostView::list( &conn, - PostListingType::All, + ListingType::All, &sort, data.community_id, None, diff --git a/server/src/api/user.rs b/server/src/api/user.rs index 563ae0a22..5ac2b4321 100644 --- a/server/src/api/user.rs +++ b/server/src/api/user.rs @@ -22,6 +22,8 @@ pub struct Register { pub struct SaveUserSettings { show_nsfw: bool, theme: String, + default_sort_type: i16, + default_listing_type: i16, auth: String, } @@ -198,6 +200,8 @@ impl Perform for Oper { banned: false, show_nsfw: data.show_nsfw, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; // Create the user @@ -289,6 +293,8 @@ impl Perform for Oper { banned: read_user.banned, show_nsfw: data.show_nsfw, theme: data.theme.to_owned(), + default_sort_type: data.default_sort_type, + default_listing_type: data.default_listing_type, }; let updated_user = match User_::update(&conn, user_id, &user_form) { @@ -346,7 +352,7 @@ impl Perform for Oper { let posts = if data.saved_only { PostView::list( &conn, - PostListingType::All, + ListingType::All, &sort, data.community_id, None, @@ -362,7 +368,7 @@ impl Perform for Oper { } else { PostView::list( &conn, - PostListingType::All, + ListingType::All, &sort, data.community_id, Some(user_details_id), @@ -453,6 +459,8 @@ impl Perform for Oper { banned: read_user.banned, show_nsfw: read_user.show_nsfw, theme: read_user.theme, + default_sort_type: read_user.default_sort_type, + default_listing_type: read_user.default_listing_type, }; match User_::update(&conn, data.user_id, &user_form) { @@ -512,6 +520,8 @@ impl Perform for Oper { banned: data.ban, show_nsfw: read_user.show_nsfw, theme: read_user.theme, + default_sort_type: read_user.default_sort_type, + default_listing_type: read_user.default_listing_type, }; match User_::update(&conn, data.user_id, &user_form) { @@ -751,7 +761,7 @@ impl Perform for Oper { // Posts let posts = PostView::list( &conn, - PostListingType::All, + ListingType::All, &SortType::New, None, Some(user_id), diff --git a/server/src/apub.rs b/server/src/apub.rs index 958a8df18..3c7202b27 100644 --- a/server/src/apub.rs +++ b/server/src/apub.rs @@ -55,6 +55,7 @@ impl User_ { #[cfg(test)] mod tests { use super::User_; + use crate::db::{ListingType, SortType}; use crate::naive_now; #[test] @@ -73,6 +74,8 @@ mod tests { updated: None, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let person = expected_user.person(); diff --git a/server/src/db/comment.rs b/server/src/db/comment.rs index 32aa4de92..64532b838 100644 --- a/server/src/db/comment.rs +++ b/server/src/db/comment.rs @@ -179,6 +179,8 @@ mod tests { updated: None, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let inserted_user = User_::create(&conn, &new_user).unwrap(); diff --git a/server/src/db/comment_view.rs b/server/src/db/comment_view.rs index 88190464c..9f7544731 100644 --- a/server/src/db/comment_view.rs +++ b/server/src/db/comment_view.rs @@ -264,6 +264,8 @@ mod tests { updated: None, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let inserted_user = User_::create(&conn, &new_user).unwrap(); diff --git a/server/src/db/community.rs b/server/src/db/community.rs index 53c238bd3..bfc6089bc 100644 --- a/server/src/db/community.rs +++ b/server/src/db/community.rs @@ -265,6 +265,8 @@ mod tests { updated: None, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let inserted_user = User_::create(&conn, &new_user).unwrap(); diff --git a/server/src/db/mod.rs b/server/src/db/mod.rs index ac3c3ae33..2045692d5 100644 --- a/server/src/db/mod.rs +++ b/server/src/db/mod.rs @@ -106,6 +106,13 @@ pub enum SortType { TopAll, } +#[derive(EnumString, ToString, Debug, Serialize, Deserialize)] +pub enum ListingType { + All, + Subscribed, + Community, +} + #[derive(EnumString, ToString, Debug, Serialize, Deserialize)] pub enum SearchType { All, diff --git a/server/src/db/moderator.rs b/server/src/db/moderator.rs index 82e0a4971..b04c6c623 100644 --- a/server/src/db/moderator.rs +++ b/server/src/db/moderator.rs @@ -447,6 +447,8 @@ mod tests { updated: None, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let inserted_mod = User_::create(&conn, &new_mod).unwrap(); @@ -462,6 +464,8 @@ mod tests { updated: None, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let inserted_user = User_::create(&conn, &new_user).unwrap(); diff --git a/server/src/db/post.rs b/server/src/db/post.rs index 1bc6e11e6..f185bd754 100644 --- a/server/src/db/post.rs +++ b/server/src/db/post.rs @@ -192,6 +192,8 @@ mod tests { updated: None, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let inserted_user = User_::create(&conn, &new_user).unwrap(); diff --git a/server/src/db/post_view.rs b/server/src/db/post_view.rs index 1180a7702..51dea027f 100644 --- a/server/src/db/post_view.rs +++ b/server/src/db/post_view.rs @@ -1,12 +1,5 @@ use super::*; -#[derive(EnumString, ToString, Debug, Serialize, Deserialize)] -pub enum PostListingType { - All, - Subscribed, - Community, -} - // The faked schema since diesel doesn't do views table! { post_view (id) { @@ -83,7 +76,7 @@ pub struct PostView { impl PostView { pub fn list( conn: &PgConnection, - type_: PostListingType, + type_: ListingType, sort: &SortType, for_community_id: Option, for_creator_id: Option, @@ -129,7 +122,7 @@ impl PostView { }; match type_ { - PostListingType::Subscribed => { + ListingType::Subscribed => { query = query.filter(subscribed.eq(true)); } _ => {} @@ -226,6 +219,8 @@ mod tests { banned: false, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let inserted_user = User_::create(&conn, &new_user).unwrap(); @@ -351,7 +346,7 @@ mod tests { let read_post_listings_with_user = PostView::list( &conn, - PostListingType::Community, + ListingType::Community, &SortType::New, Some(inserted_community.id), None, @@ -367,7 +362,7 @@ mod tests { .unwrap(); let read_post_listings_no_user = PostView::list( &conn, - PostListingType::Community, + ListingType::Community, &SortType::New, Some(inserted_community.id), None, diff --git a/server/src/db/user.rs b/server/src/db/user.rs index a37e19c46..a378d3c25 100644 --- a/server/src/db/user.rs +++ b/server/src/db/user.rs @@ -21,6 +21,8 @@ pub struct User_ { pub updated: Option, pub show_nsfw: bool, pub theme: String, + pub default_sort_type: i16, + pub default_listing_type: i16, } #[derive(Insertable, AsChangeset, Clone)] @@ -36,6 +38,8 @@ pub struct UserForm { pub updated: Option, pub show_nsfw: bool, pub theme: String, + pub default_sort_type: i16, + pub default_listing_type: i16, } impl Crud for User_ { @@ -77,6 +81,8 @@ pub struct Claims { pub iss: String, pub show_nsfw: bool, pub theme: String, + pub default_sort_type: i16, + pub default_listing_type: i16, } impl Claims { @@ -98,6 +104,8 @@ impl User_ { iss: self.fedi_name.to_owned(), show_nsfw: self.show_nsfw, theme: self.theme.to_owned(), + default_sort_type: self.default_sort_type, + default_listing_type: self.default_listing_type, }; encode( &Header::default(), @@ -146,6 +154,8 @@ mod tests { updated: None, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let inserted_user = User_::create(&conn, &new_user).unwrap(); @@ -164,6 +174,8 @@ mod tests { updated: None, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let read_user = User_::read(&conn, inserted_user.id).unwrap(); diff --git a/server/src/db/user_mention.rs b/server/src/db/user_mention.rs index d4dc0a51a..668d28fcc 100644 --- a/server/src/db/user_mention.rs +++ b/server/src/db/user_mention.rs @@ -73,6 +73,8 @@ mod tests { updated: None, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let inserted_user = User_::create(&conn, &new_user).unwrap(); @@ -88,6 +90,8 @@ mod tests { updated: None, show_nsfw: false, theme: "darkly".into(), + default_sort_type: SortType::Hot as i16, + default_listing_type: ListingType::Subscribed as i16, }; let inserted_recipient = User_::create(&conn, &recipient_form).unwrap(); diff --git a/server/src/schema.rs b/server/src/schema.rs index 9111c8e30..e087e20e1 100644 --- a/server/src/schema.rs +++ b/server/src/schema.rs @@ -255,6 +255,8 @@ table! { updated -> Nullable, show_nsfw -> Bool, theme -> Varchar, + default_sort_type -> Int2, + default_listing_type -> Int2, } } diff --git a/server/src/websocket/server.rs b/server/src/websocket/server.rs index aeca8c0c1..192742199 100644 --- a/server/src/websocket/server.rs +++ b/server/src/websocket/server.rs @@ -136,7 +136,7 @@ impl ChatServer { let conn = establish_connection(); let posts = PostView::list( &conn, - PostListingType::Community, + ListingType::Community, &SortType::New, Some(*community_id), None, diff --git a/ui/src/components/community.tsx b/ui/src/components/community.tsx index efeaa1b32..8f36178c8 100644 --- a/ui/src/components/community.tsx +++ b/ui/src/components/community.tsx @@ -15,7 +15,7 @@ import { GetPostsResponse, CreatePostLikeResponse, } from '../interfaces'; -import { WebSocketService } from '../services'; +import { WebSocketService, UserService } from '../services'; import { PostListings } from './post-listings'; import { SortSelect } from './sort-select'; import { Sidebar } from './sidebar'; @@ -72,6 +72,8 @@ export class Community extends Component { getSortTypeFromProps(props: any): SortType { return props.match.params.sort ? routeSortTypeToEnum(props.match.params.sort) + : UserService.Instance.user + ? UserService.Instance.user.default_sort_type : SortType.Hot; } diff --git a/ui/src/components/listing-type-select.tsx b/ui/src/components/listing-type-select.tsx new file mode 100644 index 000000000..d583b93cd --- /dev/null +++ b/ui/src/components/listing-type-select.tsx @@ -0,0 +1,68 @@ +import { Component, linkEvent } from 'inferno'; +import { ListingType } from '../interfaces'; +import { UserService } from '../services'; + +import { i18n } from '../i18next'; + +interface ListingTypeSelectProps { + type_: ListingType; + onChange?(val: ListingType): any; +} + +interface ListingTypeSelectState { + type_: ListingType; +} + +export class ListingTypeSelect extends Component< + ListingTypeSelectProps, + ListingTypeSelectState +> { + private emptyState: ListingTypeSelectState = { + type_: this.props.type_, + }; + + constructor(props: any, context: any) { + super(props, context); + this.state = this.emptyState; + } + + render() { + return ( +
+ + +
+ ); + } + + handleTypeChange(i: ListingTypeSelect, event: any) { + i.state.type_ = Number(event.target.value); + i.setState(i.state); + i.props.onChange(i.state.type_); + } +} diff --git a/ui/src/components/main.tsx b/ui/src/components/main.tsx index e4ff5a509..c871db72b 100644 --- a/ui/src/components/main.tsx +++ b/ui/src/components/main.tsx @@ -21,6 +21,7 @@ import { import { WebSocketService, UserService } from '../services'; import { PostListings } from './post-listings'; import { SortSelect } from './sort-select'; +import { ListingTypeSelect } from './listing-type-select'; import { SiteForm } from './site-form'; import { msgOp, @@ -81,13 +82,15 @@ export class Main extends Component { return props.match.params.type ? routeListingTypeToEnum(props.match.params.type) : UserService.Instance.user - ? ListingType.Subscribed + ? UserService.Instance.user.default_listing_type : ListingType.All; } getSortTypeFromProps(props: any): SortType { return props.match.params.sort ? routeSortTypeToEnum(props.match.params.sort) + : UserService.Instance.user + ? UserService.Instance.user.default_sort_type : SortType.Hot; } @@ -101,6 +104,7 @@ export class Main extends Component { this.state = this.emptyState; this.handleEditCancel = this.handleEditCancel.bind(this); this.handleSortChange = this.handleSortChange.bind(this); + this.handleTypeChange = this.handleTypeChange.bind(this); this.subscription = WebSocketService.Instance.subject .pipe( @@ -423,35 +427,10 @@ export class Main extends Component { selects() { return (
-
- - -
+ @@ -527,13 +506,13 @@ export class Main extends Component { window.scrollTo(0, 0); } - handleTypeChange(i: Main, event: any) { - i.state.type_ = Number(event.target.value); - i.state.page = 1; - i.state.loading = true; - i.setState(i.state); - i.updateUrl(); - i.fetchPosts(); + handleTypeChange(val: ListingType) { + this.state.type_ = val; + this.state.page = 1; + this.state.loading = true; + this.setState(this.state); + this.updateUrl(); + this.fetchPosts(); window.scrollTo(0, 0); } diff --git a/ui/src/components/user.tsx b/ui/src/components/user.tsx index 671997b91..3006afc43 100644 --- a/ui/src/components/user.tsx +++ b/ui/src/components/user.tsx @@ -9,6 +9,7 @@ import { CommunityUser, GetUserDetailsForm, SortType, + ListingType, UserDetailsResponse, UserView, CommentResponse, @@ -29,6 +30,7 @@ import { } from '../utils'; import { PostListing } from './post-listing'; import { SortSelect } from './sort-select'; +import { ListingTypeSelect } from './listing-type-select'; import { CommentNodes } from './comment-nodes'; import { MomentTime } from './moment-time'; import { i18n } from '../i18next'; @@ -90,6 +92,8 @@ export class User extends Component { userSettingsForm: { show_nsfw: null, theme: null, + default_sort_type: null, + default_listing_type: null, auth: null, }, userSettingsLoading: null, @@ -105,6 +109,12 @@ export class User extends Component { this.state = this.emptyState; this.handleSortChange = this.handleSortChange.bind(this); + this.handleUserSettingsSortTypeChange = this.handleUserSettingsSortTypeChange.bind( + this + ); + this.handleUserSettingsListingTypeChange = this.handleUserSettingsListingTypeChange.bind( + this + ); this.state.user_id = Number(this.props.match.params.id); this.state.username = this.props.match.params.username; @@ -403,6 +413,32 @@ export class User extends Component {
+
+
+ + +
+
+
+
+ + +
+
@@ -421,9 +457,12 @@ export class User extends Component {
-
+
- +
+
+
+
+