]> Untitled Git - lemmy.git/blob - ui/src/components/post-listings.tsx
Fixing issue with front page.
[lemmy.git] / ui / src / components / post-listings.tsx
1 import { Component, linkEvent } from 'inferno';
2 import { Link } from 'inferno-router';
3 import { Subscription } from "rxjs";
4 import { retryWhen, delay, take } from 'rxjs/operators';
5 import { UserOperation, Post, GetPostsForm, SortType, ListingType, GetPostsResponse, CreatePostLikeResponse, CommunityUser} from '../interfaces';
6 import { WebSocketService, UserService } from '../services';
7 import { PostListing } from './post-listing';
8 import { msgOp, fetchLimit } from '../utils';
9
10 interface PostListingsProps {
11   type?: ListingType;
12   communityId?: number;
13 }
14
15 interface PostListingsState {
16   moderators: Array<CommunityUser>;
17   posts: Array<Post>;
18   sortType: SortType;
19   type_: ListingType;
20   page: number;
21   loading: boolean;
22 }
23
24 export class PostListings extends Component<PostListingsProps, PostListingsState> {
25
26   private subscription: Subscription;
27   private emptyState: PostListingsState = {
28     moderators: [],
29     posts: [],
30     sortType: SortType.Hot,
31     type_: (this.props.type !== undefined && UserService.Instance.user) ? this.props.type : 
32       this.props.communityId 
33         ? ListingType.Community 
34         : UserService.Instance.user
35           ? ListingType.Subscribed 
36           : ListingType.All,
37           page: 1,
38           loading: true
39   }
40
41   constructor(props: any, context: any) {
42     super(props, context);
43
44     this.state = this.emptyState;
45
46     this.subscription = WebSocketService.Instance.subject
47       .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
48       .subscribe(
49         (msg) => this.parseMessage(msg),
50         (err) => console.error(err),
51         () => console.log('complete')
52       );
53
54       this.refetch();
55   }
56
57   componentWillUnmount() {
58     this.subscription.unsubscribe();
59   }
60
61   render() {
62     return (
63       <div>
64         {this.state.loading ? 
65         <h5><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> : 
66         <div>
67           {this.selects()}
68           {this.state.posts.length > 0 
69             ? this.state.posts.map(post => 
70               <PostListing post={post} showCommunity={!this.props.communityId}/>) 
71                 : <div>No Listings. {!this.props.communityId && <span>Subscribe to some <Link to="/communities">forums</Link>.</span>}</div>
72           }
73           {this.paginator()}
74         </div>
75         }
76       </div>
77     )
78   }
79
80   selects() {
81     return (
82       <div className="mb-2">
83         <select value={this.state.sortType} onChange={linkEvent(this, this.handleSortChange)} class="custom-select w-auto">
84           <option disabled>Sort Type</option>
85           <option value={SortType.Hot}>Hot</option>
86           <option value={SortType.New}>New</option>
87           <option disabled>──────────</option>
88           <option value={SortType.TopDay}>Top Day</option>
89           <option value={SortType.TopWeek}>Week</option>
90           <option value={SortType.TopMonth}>Month</option>
91           <option value={SortType.TopYear}>Year</option>
92           <option value={SortType.TopAll}>All</option>
93         </select>
94         {!this.props.communityId && 
95           UserService.Instance.user &&
96             <select value={this.state.type_} onChange={linkEvent(this, this.handleTypeChange)} class="ml-2 custom-select w-auto">
97               <option disabled>Type</option>
98               <option value={ListingType.All}>All</option>
99               <option value={ListingType.Subscribed}>Subscribed</option>
100             </select>
101
102         }
103       </div>
104     )
105   }
106
107   paginator() {
108     return (
109       <div class="mt-2">
110         {this.state.page > 1 && 
111           <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}>Prev</button>
112         }
113         <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}>Next</button>
114       </div>
115     );
116   }
117
118   nextPage(i: PostListings) { 
119     i.state.page++;
120     i.setState(i.state);
121     i.refetch();
122   }
123
124   prevPage(i: PostListings) { 
125     i.state.page--;
126     i.setState(i.state);
127     i.refetch();
128   }
129
130   handleSortChange(i: PostListings, event: any) {
131     i.state.sortType = Number(event.target.value);
132     i.state.page = 1;
133     i.setState(i.state);
134     i.refetch();
135   }
136
137   refetch() {
138     let getPostsForm: GetPostsForm = {
139       community_id: this.props.communityId,
140       page: this.state.page,
141       limit: fetchLimit,
142       sort: SortType[this.state.sortType],
143       type_: ListingType[this.state.type_]
144     }
145     WebSocketService.Instance.getPosts(getPostsForm);
146   }
147
148   handleTypeChange(i: PostListings, event: any) {
149     i.state.type_ = Number(event.target.value);
150     i.state.page = 1;
151     if (i.state.type_ == ListingType.All) {
152       i.context.router.history.push('/all');
153     } else {
154       i.context.router.history.push('/');
155     }
156     i.setState(i.state);
157     i.refetch();
158   }
159
160   parseMessage(msg: any) {
161     console.log(msg);
162     let op: UserOperation = msgOp(msg);
163     if (msg.error) {
164       alert(msg.error);
165       return;
166     } else if (op == UserOperation.GetPosts) {
167       let res: GetPostsResponse = msg;
168       this.state.posts = res.posts;
169       this.state.loading = false;
170       this.setState(this.state);
171     } else if (op == UserOperation.CreatePostLike) {
172       let res: CreatePostLikeResponse = msg;
173       let found = this.state.posts.find(c => c.id == res.post.id);
174       found.my_vote = res.post.my_vote;
175       found.score = res.post.score;
176       found.upvotes = res.post.upvotes;
177       found.downvotes = res.post.downvotes;
178       this.setState(this.state);
179     }
180   }
181 }
182
183