]> Untitled Git - lemmy.git/blob - ui/src/components/modlog.tsx
Merge branch 'replies' into dev
[lemmy.git] / ui / src / components / modlog.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, GetModlogForm, GetModlogResponse, ModRemovePost, ModLockPost, ModRemoveComment, ModRemoveCommunity, ModBanFromCommunity, ModBan, ModAddCommunity, ModAdd } from '../interfaces';
6 import { WebSocketService } from '../services';
7 import { msgOp, addTypeInfo, fetchLimit } from '../utils';
8 import { MomentTime } from './moment-time';
9 import * as moment from 'moment';
10
11 interface ModlogState {
12   combined: Array<{type_: string, data: ModRemovePost | ModLockPost | ModRemoveCommunity | ModAdd | ModBan}>,
13   communityId?: number,
14   communityName?: string,
15   page: number;
16   loading: boolean;
17 }
18
19 export class Modlog extends Component<any, ModlogState> {
20   private subscription: Subscription;
21   private emptyState: ModlogState = {
22     combined: [],
23     page: 1,
24     loading: true,
25   }
26
27   constructor(props: any, context: any) {
28     super(props, context);
29
30     this.state = this.emptyState;
31     this.state.communityId = this.props.match.params.community_id ? Number(this.props.match.params.community_id) : undefined;
32     this.subscription = WebSocketService.Instance.subject
33     .pipe(retryWhen(errors => errors.pipe(delay(3000), take(10))))
34     .subscribe(
35       (msg) => this.parseMessage(msg),
36         (err) => console.error(err),
37         () => console.log('complete')
38     );
39
40     this.refetch();
41   }
42
43   componentWillUnmount() {
44     this.subscription.unsubscribe();
45   }
46
47   setCombined(res: GetModlogResponse) {
48     let removed_posts = addTypeInfo(res.removed_posts, "removed_posts");
49     let locked_posts = addTypeInfo(res.locked_posts, "locked_posts");
50     let removed_comments = addTypeInfo(res.removed_comments, "removed_comments");
51     let removed_communities = addTypeInfo(res.removed_communities, "removed_communities");
52     let banned_from_community = addTypeInfo(res.banned_from_community, "banned_from_community");
53     let added_to_community = addTypeInfo(res.added_to_community, "added_to_community");
54     let added = addTypeInfo(res.added, "added");
55     let banned = addTypeInfo(res.banned, "banned");
56     this.state.combined = [];
57
58     this.state.combined.push(...removed_posts);
59     this.state.combined.push(...locked_posts);
60     this.state.combined.push(...removed_comments);
61     this.state.combined.push(...removed_communities);
62     this.state.combined.push(...banned_from_community);
63     this.state.combined.push(...added_to_community);
64     this.state.combined.push(...added);
65     this.state.combined.push(...banned);
66
67     if (this.state.communityId && this.state.combined.length > 0) {
68       this.state.communityName = (this.state.combined[0].data as ModRemovePost).community_name;
69     }
70
71     // Sort them by time
72     this.state.combined.sort((a, b) => b.data.when_.localeCompare(a.data.when_));
73
74     this.setState(this.state);
75   }
76
77   combined() {
78     return (
79       <tbody>
80         {this.state.combined.map(i =>
81           <tr>
82             <td><MomentTime data={i.data} /></td>
83             <td><Link to={`/user/${i.data.mod_user_id}`}>{i.data.mod_user_name}</Link></td>
84             <td>
85               {i.type_ == 'removed_posts' && 
86                 <>
87                   {(i.data as ModRemovePost).removed? 'Removed' : 'Restored'} 
88                   <span> Post <Link to={`/post/${(i.data as ModRemovePost).post_id}`}>{(i.data as ModRemovePost).post_name}</Link></span>
89                   <div>{(i.data as ModRemovePost).reason && ` reason: ${(i.data as ModRemovePost).reason}`}</div>
90                 </>
91               }
92               {i.type_ == 'locked_posts' && 
93                 <>
94                   {(i.data as ModLockPost).locked? 'Locked' : 'Unlocked'} 
95                   <span> Post <Link to={`/post/${(i.data as ModLockPost).post_id}`}>{(i.data as ModLockPost).post_name}</Link></span>
96                 </>
97               }
98               {i.type_ == 'removed_comments' && 
99                 <>
100                   {(i.data as ModRemoveComment).removed? 'Removed' : 'Restored'} 
101                   <span> Comment <Link to={`/post/${(i.data as ModRemoveComment).post_id}/comment/${(i.data as ModRemoveComment).comment_id}`}>{(i.data as ModRemoveComment).comment_content}</Link></span>
102                   <span> by <Link to={`/user/${(i.data as ModRemoveComment).comment_user_id}`}>{(i.data as ModRemoveComment).comment_user_name}</Link></span>
103                   <div>{(i.data as ModRemoveComment).reason && ` reason: ${(i.data as ModRemoveComment).reason}`}</div>
104                 </>
105               }
106               {i.type_ == 'removed_communities' && 
107                 <>
108                   {(i.data as ModRemoveCommunity).removed ? 'Removed' : 'Restored'} 
109                   <span> Community <Link to={`/community/${(i.data as ModRemoveCommunity).community_id}`}>{(i.data as ModRemoveCommunity).community_name}</Link></span>
110                   <div>{(i.data as ModRemoveCommunity).reason && ` reason: ${(i.data as ModRemoveCommunity).reason}`}</div>
111                   <div>{(i.data as ModRemoveCommunity).expires && ` expires: ${moment.utc((i.data as ModRemoveCommunity).expires).fromNow()}`}</div>
112                 </>
113               }
114               {i.type_ == 'banned_from_community' && 
115                 <>
116                   <span>{(i.data as ModBanFromCommunity).banned ? 'Banned ' : 'Unbanned '} </span>
117                   <span><Link to={`/user/${(i.data as ModBanFromCommunity).other_user_id}`}>{(i.data as ModBanFromCommunity).other_user_name}</Link></span>
118                   <span> from the community </span>
119                   <span><Link to={`/community/${(i.data as ModBanFromCommunity).community_id}`}>{(i.data as ModBanFromCommunity).community_name}</Link></span>
120                   <div>{(i.data as ModBanFromCommunity).reason && ` reason: ${(i.data as ModBanFromCommunity).reason}`}</div>
121                   <div>{(i.data as ModBanFromCommunity).expires && ` expires: ${moment.utc((i.data as ModBanFromCommunity).expires).fromNow()}`}</div>
122                 </>
123               }
124               {i.type_ == 'added_to_community' && 
125                 <>
126                   <span>{(i.data as ModAddCommunity).removed ? 'Removed ' : 'Appointed '} </span>
127                   <span><Link to={`/user/${(i.data as ModAddCommunity).other_user_id}`}>{(i.data as ModAddCommunity).other_user_name}</Link></span>
128                   <span> as a mod to the community </span>
129                   <span><Link to={`/community/${(i.data as ModAddCommunity).community_id}`}>{(i.data as ModAddCommunity).community_name}</Link></span>
130                 </>
131               }
132               {i.type_ == 'banned' && 
133                 <>
134                   <span>{(i.data as ModBan).banned ? 'Banned ' : 'Unbanned '} </span>
135                   <span><Link to={`/user/${(i.data as ModBan).other_user_id}`}>{(i.data as ModBan).other_user_name}</Link></span>
136                   <div>{(i.data as ModBan).reason && ` reason: ${(i.data as ModBan).reason}`}</div>
137                   <div>{(i.data as ModBan).expires && ` expires: ${moment.utc((i.data as ModBan).expires).fromNow()}`}</div>
138                 </>
139               }
140               {i.type_ == 'added' && 
141                 <>
142                   <span>{(i.data as ModAdd).removed ? 'Removed ' : 'Appointed '} </span>
143                   <span><Link to={`/user/${(i.data as ModAdd).other_user_id}`}>{(i.data as ModAdd).other_user_name}</Link></span>
144                   <span> as an admin </span>
145                 </>
146               }
147             </td>
148           </tr>
149                                 )
150         }
151
152       </tbody>
153     );
154
155   }
156
157   render() {
158     return (
159       <div class="container">
160         {this.state.loading ? 
161         <h5 class=""><svg class="icon icon-spinner spin"><use xlinkHref="#icon-spinner"></use></svg></h5> : 
162         <div>
163           <h5>
164             {this.state.communityName && <Link className="text-white" to={`/community/${this.state.communityId}`}>/f/{this.state.communityName} </Link>}
165             <span>Modlog</span>
166           </h5>
167           <div class="table-responsive">
168             <table id="modlog_table" class="table table-sm table-hover">
169               <thead class="pointer">
170                 <tr>
171                   <th>Time</th>
172                   <th>Mod</th>
173                   <th>Action</th>
174                 </tr>
175               </thead>
176               {this.combined()}
177             </table>
178             {this.paginator()}
179           </div>
180         </div>
181         }
182       </div>
183     );
184   }
185
186   paginator() {
187     return (
188       <div class="mt-2">
189         {this.state.page > 1 && 
190           <button class="btn btn-sm btn-secondary mr-1" onClick={linkEvent(this, this.prevPage)}>Prev</button>
191         }
192         <button class="btn btn-sm btn-secondary" onClick={linkEvent(this, this.nextPage)}>Next</button>
193       </div>
194     );
195   }
196
197   nextPage(i: Modlog) { 
198     i.state.page++;
199     i.setState(i.state);
200     i.refetch();
201   }
202
203   prevPage(i: Modlog) { 
204     i.state.page--;
205     i.setState(i.state);
206     i.refetch();
207   }
208
209   refetch(){
210     let modlogForm: GetModlogForm = {
211       community_id: this.state.communityId,
212       page: this.state.page,
213       limit: fetchLimit,
214     };
215     WebSocketService.Instance.getModlog(modlogForm);
216   }
217
218   parseMessage(msg: any) {
219     console.log(msg);
220     let op: UserOperation = msgOp(msg);
221     if (msg.error) {
222       alert(msg.error);
223       return;
224     } else if (op == UserOperation.GetModlog) {
225       let res: GetModlogResponse = msg;
226       this.state.loading = false;
227       this.setCombined(res);
228     } 
229   }
230 }