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