diff --git a/ui/src/components/communities.tsx b/ui/src/components/communities.tsx index b5233c2..1b4ec70 100644 --- a/ui/src/components/communities.tsx +++ b/ui/src/components/communities.tsx @@ -45,7 +45,7 @@ export class Communities extends Component { } componentDidMount() { - document.title = "Forums - Lemmy"; + document.title = "Communities - Lemmy"; let table = document.querySelector('#community_table'); Sortable.initTable(table); } @@ -56,7 +56,7 @@ export class Communities extends Component { {this.state.loading ?
:
-
Forums
+
Communities
@@ -73,7 +73,7 @@ export class Communities extends Component { {this.state.communities.map(community => - + diff --git a/ui/src/components/community-form.tsx b/ui/src/components/community-form.tsx index 5effa73..66071a3 100644 --- a/ui/src/components/community-form.tsx +++ b/ui/src/components/community-form.tsx @@ -120,10 +120,7 @@ export class CommunityForm extends Component; admins: Array; loading: boolean; + posts: Array; + sort: SortType; + page: number; } export class Community extends Component { @@ -38,7 +41,20 @@ export class Community extends Component { admins: [], communityId: Number(this.props.match.params.id), communityName: this.props.match.params.name, - loading: true + loading: true, + posts: [], + sort: this.getSortTypeFromProps(this.props), + page: this.getPageFromProps(this.props), + } + + getSortTypeFromProps(props: any): SortType { + return (props.match.params.sort) ? + routeSortTypeToEnum(props.match.params.sort) : + SortType.Hot; + } + + getPageFromProps(props: any): number { + return (props.match.params.page) ? Number(props.match.params.page) : 1; } constructor(props: any, context: any) { @@ -66,6 +82,16 @@ export class Community extends Component { this.subscription.unsubscribe(); } + // Necessary for back button for some reason + componentWillReceiveProps(nextProps: any) { + if (nextProps.history.action == 'POP') { + this.state = this.emptyState; + this.state.sort = this.getSortTypeFromProps(nextProps); + this.state.page = this.getPageFromProps(nextProps); + this.fetchPosts(); + } + } + render() { return (
@@ -78,7 +104,9 @@ export class Community extends Component { removed } - {this.state.community && } + {this.selects()} + + {this.paginator()}
{ ) } + selects() { + return ( +
+ +
+ ) + } + + paginator() { + return ( +
+ {this.state.page > 1 && + + } + +
+ ); + } + + nextPage(i: Community) { + i.state.page++; + i.setState(i.state); + i.updateUrl(); + i.fetchPosts(); + } + + prevPage(i: Community) { + i.state.page--; + i.setState(i.state); + i.updateUrl(); + i.fetchPosts(); + } + + handleSortChange(i: Community, event: any) { + i.state.sort = Number(event.target.value); + i.state.page = 1; + i.setState(i.state); + i.updateUrl(); + i.fetchPosts(); + } + + updateUrl() { + let sortStr = SortType[this.state.sort].toLowerCase(); + this.props.history.push(`/c/${this.state.community.name}/sort/${sortStr}/page/${this.state.page}`); + } + + fetchPosts() { + let getPostsForm: GetPostsForm = { + page: this.state.page, + limit: fetchLimit, + sort: SortType[this.state.sort], + type_: ListingType[ListingType.Community], + community_id: this.state.community.id, + } + WebSocketService.Instance.getPosts(getPostsForm); + } parseMessage(msg: any) { console.log(msg); @@ -105,9 +199,9 @@ export class Community extends Component { this.state.community = res.community; this.state.moderators = res.moderators; this.state.admins = res.admins; - this.state.loading = false; - document.title = `/f/${this.state.community.name} - Lemmy`; + document.title = `/c/${this.state.community.name} - Lemmy`; this.setState(this.state); + this.fetchPosts(); } else if (op == UserOperation.EditCommunity) { let res: CommunityResponse = msg; this.state.community = res.community; @@ -117,6 +211,19 @@ export class Community extends Component { this.state.community.subscribed = res.community.subscribed; this.state.community.number_of_subscribers = res.community.number_of_subscribers; this.setState(this.state); + } else if (op == UserOperation.GetPosts) { + let res: GetPostsResponse = msg; + this.state.posts = res.posts; + this.state.loading = false; + this.setState(this.state); + } else if (op == UserOperation.CreatePostLike) { + let res: CreatePostLikeResponse = msg; + let found = this.state.posts.find(c => c.id == res.post.id); + found.my_vote = res.post.my_vote; + found.score = res.post.score; + found.upvotes = res.post.upvotes; + found.downvotes = res.post.downvotes; + this.setState(this.state); } } } diff --git a/ui/src/components/create-community.tsx b/ui/src/components/create-community.tsx index 04ef6d3..a9345f7 100644 --- a/ui/src/components/create-community.tsx +++ b/ui/src/components/create-community.tsx @@ -10,7 +10,7 @@ export class CreateCommunity extends Component { } componentDidMount() { - document.title = "Create Forum - Lemmy"; + document.title = "Create Community - Lemmy"; } render() { @@ -18,7 +18,7 @@ export class CreateCommunity extends Component {
-
Create Forum
+
Create Community
@@ -27,7 +27,7 @@ export class CreateCommunity extends Component { } handleCommunityCreate(community: Community) { - this.props.history.push(`/f/${community.name}`); + this.props.history.push(`/c/${community.name}`); } } diff --git a/ui/src/components/home.tsx b/ui/src/components/home.tsx index cebe222..e69de29 100644 --- a/ui/src/components/home.tsx +++ b/ui/src/components/home.tsx @@ -1,24 +0,0 @@ -import { Component } from 'inferno'; -import { Main } from './main'; -import { ListingType } from '../interfaces'; - -export class Home extends Component { - - constructor(props: any, context: any) { - super(props, context); - } - - render() { - return ( -
- ) - } - - componentDidMount() { - document.title = "Lemmy"; - } - - listType(): ListingType { - return (this.props.match.path == '/all') ? ListingType.All : ListingType.Subscribed; - } -} diff --git a/ui/src/components/main.tsx b/ui/src/components/main.tsx index 6911ca4..88eed60 100644 --- a/ui/src/components/main.tsx +++ b/ui/src/components/main.tsx @@ -2,16 +2,11 @@ import { Component, linkEvent } from 'inferno'; import { Link } from 'inferno-router'; import { Subscription } from "rxjs"; import { retryWhen, delay, take } from 'rxjs/operators'; -import { UserOperation, CommunityUser, GetFollowedCommunitiesResponse, ListCommunitiesForm, ListCommunitiesResponse, Community, SortType, GetSiteResponse, ListingType, SiteResponse } from '../interfaces'; +import { UserOperation, CommunityUser, GetFollowedCommunitiesResponse, ListCommunitiesForm, ListCommunitiesResponse, Community, SortType, GetSiteResponse, ListingType, SiteResponse, GetPostsResponse, CreatePostLikeResponse, Post, GetPostsForm } from '../interfaces'; import { WebSocketService, UserService } from '../services'; import { PostListings } from './post-listings'; import { SiteForm } from './site-form'; -import { msgOp, repoUrl, mdToHtml } from '../utils'; - - -interface MainProps { - type: ListingType; -} +import { msgOp, repoUrl, mdToHtml, fetchLimit, routeSortTypeToEnum, routeListingTypeToEnum } from '../utils'; interface MainState { subscribedCommunities: Array; @@ -19,9 +14,13 @@ interface MainState { site: GetSiteResponse; showEditSite: boolean; loading: boolean; + posts: Array; + type_: ListingType; + sort: SortType; + page: number; } -export class Main extends Component { +export class Main extends Component { private subscription: Subscription; private emptyState: MainState = { @@ -43,7 +42,29 @@ export class Main extends Component { banned: [], }, showEditSite: false, - loading: true + loading: true, + posts: [], + type_: this.getListingTypeFromProps(this.props), + sort: this.getSortTypeFromProps(this.props), + page: this.getPageFromProps(this.props), + } + + getListingTypeFromProps(props: any): ListingType { + return (props.match.params.type) ? + routeListingTypeToEnum(props.match.params.type) : + UserService.Instance.user ? + ListingType.Subscribed : + ListingType.All; + } + + getSortTypeFromProps(props: any): SortType { + return (props.match.params.sort) ? + routeSortTypeToEnum(props.match.params.sort) : + SortType.Hot; + } + + getPageFromProps(props: any): number { + return (props.match.params.page) ? Number(props.match.params.page) : 1; } constructor(props: any, context: any) { @@ -72,37 +93,51 @@ export class Main extends Component { WebSocketService.Instance.listCommunities(listCommunitiesForm); - this.handleEditCancel = this.handleEditCancel.bind(this); + this.fetchPosts(); } componentWillUnmount() { this.subscription.unsubscribe(); } + componentDidMount() { + document.title = "Lemmy"; + } + + // Necessary for back button for some reason + componentWillReceiveProps(nextProps: any) { + if (nextProps.history.action == 'POP') { + this.state = this.emptyState; + this.state.type_ = this.getListingTypeFromProps(nextProps); + this.state.sort = this.getSortTypeFromProps(nextProps); + this.state.page = this.getPageFromProps(nextProps); + this.fetchPosts(); + } + } + render() { return (
- + {this.posts()}
- {this.state.loading ? -
: -
- {this.trendingCommunities()} - {UserService.Instance.user && this.state.subscribedCommunities.length > 0 && -
-
Subscribed forums
-
    - {this.state.subscribedCommunities.map(community => -
  • {community.community_name}
  • - )} -
-
- } - {this.sidebar()} -
+ {!this.state.loading && +
+ {this.trendingCommunities()} + {UserService.Instance.user && this.state.subscribedCommunities.length > 0 && +
+
Subscribed communities
+
    + {this.state.subscribedCommunities.map(community => +
  • {community.community_name}
  • + )} +
+
+ } + {this.sidebar()} +
}
@@ -113,10 +148,10 @@ export class Main extends Component { trendingCommunities() { return (
-
Trending forums
+
Trending communities
    {this.state.trendingCommunities.map(community => -
  • {community.name}
  • +
  • {community.name}
  • )}
@@ -138,6 +173,12 @@ export class Main extends Component { ) } + updateUrl() { + let typeStr = ListingType[this.state.type_].toLowerCase(); + let sortStr = SortType[this.state.sort].toLowerCase(); + this.props.history.push(`/home/type/${typeStr}/sort/${sortStr}/page/${this.state.page}`); + } + siteInfo() { return (
@@ -185,9 +226,61 @@ export class Main extends Component {

Suggest new features or report bugs here.

Made with Rust, Actix, Inferno, Typescript.

+ ) + } + + posts() { + return ( +
+ {this.state.loading ? +
: +
+ {this.selects()} + + {this.paginator()} +
+ } +
) } + selects() { + return ( +
+ + { UserService.Instance.user && + + + } +
+ ) + } + + paginator() { + return ( +
+ {this.state.page > 1 && + + } + +
+ ); + } + get canAdmin(): boolean { return UserService.Instance.user && this.state.site.admins.map(a => a.id).includes(UserService.Instance.user.id); } @@ -202,6 +295,46 @@ export class Main extends Component { this.setState(this.state); } + nextPage(i: Main) { + i.state.page++; + i.setState(i.state); + i.updateUrl(); + i.fetchPosts(); + } + + prevPage(i: Main) { + i.state.page--; + i.setState(i.state); + i.updateUrl(); + i.fetchPosts(); + } + + handleSortChange(i: Main, event: any) { + i.state.sort = Number(event.target.value); + i.state.page = 1; + i.setState(i.state); + i.updateUrl(); + i.fetchPosts(); + } + + handleTypeChange(i: Main, event: any) { + i.state.type_ = Number(event.target.value); + i.state.page = 1; + i.setState(i.state); + i.updateUrl(); + i.fetchPosts(); + } + + fetchPosts() { + let getPostsForm: GetPostsForm = { + page: this.state.page, + limit: fetchLimit, + sort: SortType[this.state.sort], + type_: ListingType[this.state.type_] + } + WebSocketService.Instance.getPosts(getPostsForm); + } + parseMessage(msg: any) { console.log(msg); let op: UserOperation = msgOp(msg); @@ -211,12 +344,10 @@ export class Main extends Component { } else if (op == UserOperation.GetFollowedCommunities) { let res: GetFollowedCommunitiesResponse = msg; this.state.subscribedCommunities = res.communities; - this.state.loading = false; this.setState(this.state); } else if (op == UserOperation.ListCommunities) { let res: ListCommunitiesResponse = msg; this.state.trendingCommunities = res.communities; - this.state.loading = false; this.setState(this.state); } else if (op == UserOperation.GetSite) { let res: GetSiteResponse = msg; @@ -234,6 +365,19 @@ export class Main extends Component { this.state.site.site = res.site; this.state.showEditSite = false; this.setState(this.state); + } else if (op == UserOperation.GetPosts) { + let res: GetPostsResponse = msg; + this.state.posts = res.posts; + this.state.loading = false; + this.setState(this.state); + } else if (op == UserOperation.CreatePostLike) { + let res: CreatePostLikeResponse = msg; + let found = this.state.posts.find(c => c.id == res.post.id); + found.my_vote = res.post.my_vote; + found.score = res.post.score; + found.upvotes = res.post.upvotes; + found.downvotes = res.post.downvotes; + this.setState(this.state); } } } diff --git a/ui/src/components/modlog.tsx b/ui/src/components/modlog.tsx index f644b16..853bdd2 100644 --- a/ui/src/components/modlog.tsx +++ b/ui/src/components/modlog.tsx @@ -110,7 +110,7 @@ export class Modlog extends Component { {i.type_ == 'removed_communities' && <> {(i.data as ModRemoveCommunity).removed ? 'Removed' : 'Restored'} - Community {(i.data as ModRemoveCommunity).community_name} + Community {(i.data as ModRemoveCommunity).community_name}
{(i.data as ModRemoveCommunity).reason && ` reason: ${(i.data as ModRemoveCommunity).reason}`}
{(i.data as ModRemoveCommunity).expires && ` expires: ${moment.utc((i.data as ModRemoveCommunity).expires).fromNow()}`}
@@ -120,7 +120,7 @@ export class Modlog extends Component { {(i.data as ModBanFromCommunity).banned ? 'Banned ' : 'Unbanned '} {(i.data as ModBanFromCommunity).other_user_name} from the community - {(i.data as ModBanFromCommunity).community_name} + {(i.data as ModBanFromCommunity).community_name}
{(i.data as ModBanFromCommunity).reason && ` reason: ${(i.data as ModBanFromCommunity).reason}`}
{(i.data as ModBanFromCommunity).expires && ` expires: ${moment.utc((i.data as ModBanFromCommunity).expires).fromNow()}`}
@@ -130,7 +130,7 @@ export class Modlog extends Component { {(i.data as ModAddCommunity).removed ? 'Removed ' : 'Appointed '} {(i.data as ModAddCommunity).other_user_name} as a mod to the community - {(i.data as ModAddCommunity).community_name} + {(i.data as ModAddCommunity).community_name} } {i.type_ == 'banned' && @@ -165,7 +165,7 @@ export class Modlog extends Component {
:
- {this.state.communityName && /f/{this.state.communityName} } + {this.state.communityName && /c/{this.state.communityName} } Modlog
diff --git a/ui/src/components/navbar.tsx b/ui/src/components/navbar.tsx index 88d270e..31dab61 100644 --- a/ui/src/components/navbar.tsx +++ b/ui/src/components/navbar.tsx @@ -63,17 +63,17 @@ export class Navbar extends Component { navbar() { return (
{community.name}{community.name} {community.title} {community.category_name} {community.number_of_subscribers}