]> Untitled Git - lemmy.git/blob - ui/src/components/communities.tsx
i18n translations first pass.
[lemmy.git] / ui / src / components / communities.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, ListCommunitiesResponse, CommunityResponse, FollowCommunityForm, ListCommunitiesForm, SortType } from '../interfaces';
6 import { WebSocketService } from '../services';
7 import { msgOp } from '../utils';
8 import { T } from 'inferno-i18next';
9
10 declare const Sortable: any;
11
12 interface CommunitiesState {
13   communities: Array<Community>;
14   page: number;
15   loading: boolean;
16 }
17
18 export class Communities extends Component<any, CommunitiesState> {
19   private subscription: Subscription;
20   private emptyState: CommunitiesState = {
21     communities: [],
22     loading: true,
23     page: this.getPageFromProps(this.props),
24   }
25
26   constructor(props: any, context: any) {
27     super(props, context);
28     this.state = this.emptyState;
29     this.subscription = WebSocketService.Instance.subject
30     .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
31     .subscribe(
32       (msg) => this.parseMessage(msg),
33         (err) => console.error(err),
34         () => console.log('complete')
35     );
36
37     this.refetch();
38
39   }
40
41   getPageFromProps(props: any): number {
42     return (props.match.params.page) ? Number(props.match.params.page) : 1;
43   }
44
45   componentWillUnmount() {
46     this.subscription.unsubscribe();
47   }
48
49   componentDidMount() {
50     document.title = `Communities - ${WebSocketService.Instance.site.name}`;
51   }
52
53   // Necessary for back button for some reason
54   componentWillReceiveProps(nextProps: any) {
55     if (nextProps.history.action == 'POP') {
56       this.state = this.emptyState;
57       this.state.page = this.getPageFromProps(nextProps);
58       this.refetch();
59     }
60   }
61
62   render() {
63     return (
64       <div class="container">
65         {this.state.loading ? 
66         <h5 class=""><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> : 
67         <div>
68           <h5><T i18nKey="list_of_communities">#</T></h5>
69           <div class="table-responsive">
70             <table id="community_table" class="table table-sm table-hover">
71               <thead class="pointer">
72                 <tr>
73                   <th><T i18nKey="name">#</T></th>
74                   <th class="d-none d-lg-table-cell"><T i18nKey="title">#</T></th>
75                   <th><T i18nKey="category">#</T></th>
76                   <th class="text-right"><T i18nKey="subscribers">#</T></th>
77                   <th class="text-right d-none d-lg-table-cell"><T i18nKey="posts">#</T></th>
78                   <th class="text-right d-none d-lg-table-cell"><T i18nKey="comments">#</T></th>
79                   <th></th>
80                 </tr>
81               </thead>
82               <tbody>
83                 {this.state.communities.map(community =>
84                   <tr>
85                     <td><Link to={`/c/${community.name}`}>{community.name}</Link></td>
86                     <td class="d-none d-lg-table-cell">{community.title}</td>
87                     <td>{community.category_name}</td>
88                     <td class="text-right">{community.number_of_subscribers}</td>
89                     <td class="text-right d-none d-lg-table-cell">{community.number_of_posts}</td>
90                     <td class="text-right d-none d-lg-table-cell">{community.number_of_comments}</td>
91                     <td class="text-right">
92                       {community.subscribed ? 
93                       <span class="pointer btn-link" onClick={linkEvent(community.id, this.handleUnsubscribe)}><T i18nKey="unsubscribe">#</T></span> : 
94                       <span class="pointer btn-link" onClick={linkEvent(community.id, this.handleSubscribe)}><T i18nKey="subscribe">#</T></span>
95                       }
96                     </td>
97                   </tr>
98                 )}
99               </tbody>
100             </table>
101           </div>
102           {this.paginator()}
103         </div>
104         }
105       </div>
106     );
107   }
108
109   paginator() {
110     return (
111       <div class="mt-2">
112         {this.state.page > 1 && 
113           <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}><T i18nKey="prev">#</T></button>
114         }
115         <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}><T i18nKey="next">#</T></button>
116       </div>
117     );
118   }
119
120   updateUrl() {
121     this.props.history.push(`/communities/page/${this.state.page}`);
122   }
123
124   nextPage(i: Communities) { 
125     i.state.page++;
126     i.setState(i.state);
127     i.updateUrl();
128     i.refetch();
129   }
130
131   prevPage(i: Communities) { 
132     i.state.page--;
133     i.setState(i.state);
134     i.updateUrl();
135     i.refetch();
136   }
137
138   handleUnsubscribe(communityId: number) {
139     let form: FollowCommunityForm = {
140       community_id: communityId,
141       follow: false
142     };
143     WebSocketService.Instance.followCommunity(form);
144   }
145
146   handleSubscribe(communityId: number) {
147     let form: FollowCommunityForm = {
148       community_id: communityId,
149       follow: true
150     };
151     WebSocketService.Instance.followCommunity(form);
152   }
153
154   refetch() {
155     let listCommunitiesForm: ListCommunitiesForm = {
156       sort: SortType[SortType.TopAll],
157       limit: 100,
158       page: this.state.page,
159     }
160
161     WebSocketService.Instance.listCommunities(listCommunitiesForm);
162
163   }
164
165   parseMessage(msg: any) {
166     console.log(msg);
167     let op: UserOperation = msgOp(msg);
168     if (msg.error) {
169       alert(msg.error);
170       return;
171     } else if (op == UserOperation.ListCommunities) {
172       let res: ListCommunitiesResponse = msg;
173       this.state.communities = res.communities;
174       this.state.communities.sort((a, b) => b.number_of_subscribers - a.number_of_subscribers);
175       this.state.loading = false;
176       window.scrollTo(0,0);
177       this.setState(this.state);
178       let table = document.querySelector('#community_table');
179       Sortable.initTable(table);
180     } else if (op == UserOperation.FollowCommunity) {
181       let res: CommunityResponse = msg;
182       let found = this.state.communities.find(c => c.id == res.community.id);
183       found.subscribed = res.community.subscribed;
184       found.number_of_subscribers = res.community.number_of_subscribers;
185       this.setState(this.state);
186     } 
187   }
188 }