]> Untitled Git - lemmy-ui.git/blob - src/shared/components/modlog.tsx
Updating translations.
[lemmy-ui.git] / src / shared / components / modlog.tsx
1 import { None, Option, Some } from "@sniptt/monads";
2 import { Component, linkEvent } from "inferno";
3 import { Link } from "inferno-router";
4 import {
5   AdminPurgeCommentView,
6   AdminPurgeCommunityView,
7   AdminPurgePersonView,
8   AdminPurgePostView,
9   CommunityModeratorView,
10   GetCommunity,
11   GetCommunityResponse,
12   GetModlog,
13   GetModlogResponse,
14   GetSiteResponse,
15   ModAddCommunityView,
16   ModAddView,
17   ModBanFromCommunityView,
18   ModBanView,
19   ModLockPostView,
20   ModlogActionType,
21   ModRemoveCommentView,
22   ModRemoveCommunityView,
23   ModRemovePostView,
24   ModStickyPostView,
25   ModTransferCommunityView,
26   PersonSafe,
27   toUndefined,
28   UserOperation,
29   wsJsonToRes,
30   wsUserOp,
31 } from "lemmy-js-client";
32 import moment from "moment";
33 import { Subscription } from "rxjs";
34 import { i18n } from "../i18next";
35 import { InitialFetchRequest } from "../interfaces";
36 import { WebSocketService } from "../services";
37 import {
38   amAdmin,
39   amMod,
40   auth,
41   choicesModLogConfig,
42   debounce,
43   fetchLimit,
44   fetchUsers,
45   isBrowser,
46   setIsoData,
47   toast,
48   wsClient,
49   wsSubscribe,
50 } from "../utils";
51 import { HtmlTags } from "./common/html-tags";
52 import { Spinner } from "./common/icon";
53 import { MomentTime } from "./common/moment-time";
54 import { Paginator } from "./common/paginator";
55 import { CommunityLink } from "./community/community-link";
56 import { PersonListing } from "./person/person-listing";
57 type ModlogType = {
58   id: number;
59   type_: ModlogActionType;
60   moderator: Option<PersonSafe>;
61   view:
62     | ModRemovePostView
63     | ModLockPostView
64     | ModStickyPostView
65     | ModRemoveCommentView
66     | ModRemoveCommunityView
67     | ModBanFromCommunityView
68     | ModBanView
69     | ModAddCommunityView
70     | ModTransferCommunityView
71     | ModAddView
72     | AdminPurgePersonView
73     | AdminPurgeCommunityView
74     | AdminPurgePostView
75     | AdminPurgeCommentView;
76   when_: string;
77 };
78 var Choices: any;
79 if (isBrowser()) {
80   Choices = require("choices.js");
81 }
82
83 interface ModlogState {
84   res: Option<GetModlogResponse>;
85   communityId: Option<number>;
86   communityMods: Option<CommunityModeratorView[]>;
87   communityName: Option<string>;
88   page: number;
89   siteRes: GetSiteResponse;
90   loading: boolean;
91   filter_action: ModlogActionType;
92   filter_user: Option<number>;
93   filter_mod: Option<number>;
94 }
95
96 export class Modlog extends Component<any, ModlogState> {
97   private isoData = setIsoData(
98     this.context,
99     GetModlogResponse,
100     GetCommunityResponse
101   );
102   private subscription: Subscription;
103   private userChoices: any;
104   private modChoices: any;
105   private emptyState: ModlogState = {
106     res: None,
107     communityId: None,
108     communityMods: None,
109     communityName: None,
110     page: 1,
111     loading: true,
112     siteRes: this.isoData.site_res,
113     filter_action: ModlogActionType.All,
114     filter_user: None,
115     filter_mod: None,
116   };
117   constructor(props: any, context: any) {
118     super(props, context);
119     this.state = this.emptyState;
120     this.handlePageChange = this.handlePageChange.bind(this);
121
122     this.state.communityId = this.props.match.params.community_id
123       ? Some(Number(this.props.match.params.community_id))
124       : None;
125
126     this.parseMessage = this.parseMessage.bind(this);
127     this.subscription = wsSubscribe(this.parseMessage);
128
129     // Only fetch the data if coming from another route
130     if (this.isoData.path == this.context.router.route.match.url) {
131       this.state.res = Some(this.isoData.routeData[0] as GetModlogResponse);
132
133       if (this.isoData.routeData[1]) {
134         // Getting the moderators
135         let communityRes = Some(
136           this.isoData.routeData[1] as GetCommunityResponse
137         );
138         this.state.communityMods = communityRes.map(c => c.moderators);
139       }
140
141       this.state.loading = false;
142     } else {
143       this.refetch();
144     }
145   }
146
147   componentDidMount() {
148     this.setupUserFilter();
149     this.setupModFilter();
150   }
151
152   componentWillUnmount() {
153     if (isBrowser()) {
154       this.subscription.unsubscribe();
155     }
156   }
157
158   buildCombined(res: GetModlogResponse): ModlogType[] {
159     let removed_posts: ModlogType[] = res.removed_posts.map(r => ({
160       id: r.mod_remove_post.id,
161       type_: ModlogActionType.ModRemovePost,
162       view: r,
163       moderator: r.moderator,
164       when_: r.mod_remove_post.when_,
165     }));
166
167     let locked_posts: ModlogType[] = res.locked_posts.map(r => ({
168       id: r.mod_lock_post.id,
169       type_: ModlogActionType.ModLockPost,
170       view: r,
171       moderator: r.moderator,
172       when_: r.mod_lock_post.when_,
173     }));
174
175     let stickied_posts: ModlogType[] = res.stickied_posts.map(r => ({
176       id: r.mod_sticky_post.id,
177       type_: ModlogActionType.ModStickyPost,
178       view: r,
179       moderator: r.moderator,
180       when_: r.mod_sticky_post.when_,
181     }));
182
183     let removed_comments: ModlogType[] = res.removed_comments.map(r => ({
184       id: r.mod_remove_comment.id,
185       type_: ModlogActionType.ModRemoveComment,
186       view: r,
187       moderator: r.moderator,
188       when_: r.mod_remove_comment.when_,
189     }));
190
191     let removed_communities: ModlogType[] = res.removed_communities.map(r => ({
192       id: r.mod_remove_community.id,
193       type_: ModlogActionType.ModRemoveCommunity,
194       view: r,
195       moderator: r.moderator,
196       when_: r.mod_remove_community.when_,
197     }));
198
199     let banned_from_community: ModlogType[] = res.banned_from_community.map(
200       r => ({
201         id: r.mod_ban_from_community.id,
202         type_: ModlogActionType.ModBanFromCommunity,
203         view: r,
204         moderator: r.moderator,
205         when_: r.mod_ban_from_community.when_,
206       })
207     );
208
209     let added_to_community: ModlogType[] = res.added_to_community.map(r => ({
210       id: r.mod_add_community.id,
211       type_: ModlogActionType.ModAddCommunity,
212       view: r,
213       moderator: r.moderator,
214       when_: r.mod_add_community.when_,
215     }));
216
217     let transferred_to_community: ModlogType[] =
218       res.transferred_to_community.map(r => ({
219         id: r.mod_transfer_community.id,
220         type_: ModlogActionType.ModTransferCommunity,
221         view: r,
222         moderator: r.moderator,
223         when_: r.mod_transfer_community.when_,
224       }));
225
226     let added: ModlogType[] = res.added.map(r => ({
227       id: r.mod_add.id,
228       type_: ModlogActionType.ModAdd,
229       view: r,
230       moderator: r.moderator,
231       when_: r.mod_add.when_,
232     }));
233
234     let banned: ModlogType[] = res.banned.map(r => ({
235       id: r.mod_ban.id,
236       type_: ModlogActionType.ModBan,
237       view: r,
238       moderator: r.moderator,
239       when_: r.mod_ban.when_,
240     }));
241
242     let purged_persons: ModlogType[] = res.admin_purged_persons.map(r => ({
243       id: r.admin_purge_person.id,
244       type_: ModlogActionType.AdminPurgePerson,
245       view: r,
246       moderator: r.admin,
247       when_: r.admin_purge_person.when_,
248     }));
249
250     let purged_communities: ModlogType[] = res.admin_purged_communities.map(
251       r => ({
252         id: r.admin_purge_community.id,
253         type_: ModlogActionType.AdminPurgeCommunity,
254         view: r,
255         moderator: r.admin,
256         when_: r.admin_purge_community.when_,
257       })
258     );
259
260     let purged_posts: ModlogType[] = res.admin_purged_posts.map(r => ({
261       id: r.admin_purge_post.id,
262       type_: ModlogActionType.AdminPurgePost,
263       view: r,
264       moderator: r.admin,
265       when_: r.admin_purge_post.when_,
266     }));
267
268     let purged_comments: ModlogType[] = res.admin_purged_comments.map(r => ({
269       id: r.admin_purge_comment.id,
270       type_: ModlogActionType.AdminPurgeComment,
271       view: r,
272       moderator: r.admin,
273       when_: r.admin_purge_comment.when_,
274     }));
275
276     let combined: ModlogType[] = [];
277
278     combined.push(...removed_posts);
279     combined.push(...locked_posts);
280     combined.push(...stickied_posts);
281     combined.push(...removed_comments);
282     combined.push(...removed_communities);
283     combined.push(...banned_from_community);
284     combined.push(...added_to_community);
285     combined.push(...transferred_to_community);
286     combined.push(...added);
287     combined.push(...banned);
288     combined.push(...purged_persons);
289     combined.push(...purged_communities);
290     combined.push(...purged_posts);
291     combined.push(...purged_comments);
292
293     // Sort them by time
294     combined.sort((a, b) => b.when_.localeCompare(a.when_));
295
296     return combined;
297   }
298
299   renderModlogType(i: ModlogType) {
300     switch (i.type_) {
301       case ModlogActionType.ModRemovePost: {
302         let mrpv = i.view as ModRemovePostView;
303         return [
304           mrpv.mod_remove_post.removed.unwrapOr(false)
305             ? "Removed "
306             : "Restored ",
307           <span>
308             Post <Link to={`/post/${mrpv.post.id}`}>{mrpv.post.name}</Link>
309           </span>,
310           mrpv.mod_remove_post.reason.match({
311             some: reason => <div>reason: {reason}</div>,
312             none: <></>,
313           }),
314         ];
315       }
316       case ModlogActionType.ModLockPost: {
317         let mlpv = i.view as ModLockPostView;
318         return [
319           mlpv.mod_lock_post.locked.unwrapOr(false) ? "Locked " : "Unlocked ",
320           <span>
321             Post <Link to={`/post/${mlpv.post.id}`}>{mlpv.post.name}</Link>
322           </span>,
323         ];
324       }
325       case ModlogActionType.ModStickyPost: {
326         let mspv = i.view as ModStickyPostView;
327         return [
328           mspv.mod_sticky_post.stickied.unwrapOr(false)
329             ? "Stickied "
330             : "Unstickied ",
331           <span>
332             Post <Link to={`/post/${mspv.post.id}`}>{mspv.post.name}</Link>
333           </span>,
334         ];
335       }
336       case ModlogActionType.ModRemoveComment: {
337         let mrc = i.view as ModRemoveCommentView;
338         return [
339           mrc.mod_remove_comment.removed.unwrapOr(false)
340             ? "Removed "
341             : "Restored ",
342           <span>
343             Comment{" "}
344             <Link to={`/post/${mrc.post.id}/comment/${mrc.comment.id}`}>
345               {mrc.comment.content}
346             </Link>
347           </span>,
348           <span>
349             {" "}
350             by <PersonListing person={mrc.commenter} />
351           </span>,
352           mrc.mod_remove_comment.reason.match({
353             some: reason => <div>reason: {reason}</div>,
354             none: <></>,
355           }),
356         ];
357       }
358       case ModlogActionType.ModRemoveCommunity: {
359         let mrco = i.view as ModRemoveCommunityView;
360         return [
361           mrco.mod_remove_community.removed.unwrapOr(false)
362             ? "Removed "
363             : "Restored ",
364           <span>
365             Community <CommunityLink community={mrco.community} />
366           </span>,
367           mrco.mod_remove_community.reason.match({
368             some: reason => <div>reason: {reason}</div>,
369             none: <></>,
370           }),
371           mrco.mod_remove_community.expires.match({
372             some: expires => (
373               <div>expires: {moment.utc(expires).fromNow()}</div>
374             ),
375             none: <></>,
376           }),
377         ];
378       }
379       case ModlogActionType.ModBanFromCommunity: {
380         let mbfc = i.view as ModBanFromCommunityView;
381         return [
382           <span>
383             {mbfc.mod_ban_from_community.banned.unwrapOr(false)
384               ? "Banned "
385               : "Unbanned "}{" "}
386           </span>,
387           <span>
388             <PersonListing person={mbfc.banned_person} />
389           </span>,
390           <span> from the community </span>,
391           <span>
392             <CommunityLink community={mbfc.community} />
393           </span>,
394           mbfc.mod_ban_from_community.reason.match({
395             some: reason => <div>reason: {reason}</div>,
396             none: <></>,
397           }),
398           mbfc.mod_ban_from_community.expires.match({
399             some: expires => (
400               <div>expires: {moment.utc(expires).fromNow()}</div>
401             ),
402             none: <></>,
403           }),
404         ];
405       }
406       case ModlogActionType.ModAddCommunity: {
407         let mac = i.view as ModAddCommunityView;
408         return [
409           <span>
410             {mac.mod_add_community.removed.unwrapOr(false)
411               ? "Removed "
412               : "Appointed "}{" "}
413           </span>,
414           <span>
415             <PersonListing person={mac.modded_person} />
416           </span>,
417           <span> as a mod to the community </span>,
418           <span>
419             <CommunityLink community={mac.community} />
420           </span>,
421         ];
422       }
423       case ModlogActionType.ModTransferCommunity: {
424         let mtc = i.view as ModTransferCommunityView;
425         return [
426           <span>
427             {mtc.mod_transfer_community.removed.unwrapOr(false)
428               ? "Removed "
429               : "Transferred "}{" "}
430           </span>,
431           <span>
432             <CommunityLink community={mtc.community} />
433           </span>,
434           <span> to </span>,
435           <span>
436             <PersonListing person={mtc.modded_person} />
437           </span>,
438         ];
439       }
440       case ModlogActionType.ModBan: {
441         let mb = i.view as ModBanView;
442         return [
443           <span>
444             {mb.mod_ban.banned.unwrapOr(false) ? "Banned " : "Unbanned "}{" "}
445           </span>,
446           <span>
447             <PersonListing person={mb.banned_person} />
448           </span>,
449           mb.mod_ban.reason.match({
450             some: reason => <div>reason: {reason}</div>,
451             none: <></>,
452           }),
453           mb.mod_ban.expires.match({
454             some: expires => (
455               <div>expires: {moment.utc(expires).fromNow()}</div>
456             ),
457             none: <></>,
458           }),
459         ];
460       }
461       case ModlogActionType.ModAdd: {
462         let ma = i.view as ModAddView;
463         return [
464           <span>
465             {ma.mod_add.removed.unwrapOr(false) ? "Removed " : "Appointed "}{" "}
466           </span>,
467           <span>
468             <PersonListing person={ma.modded_person} />
469           </span>,
470           <span> as an admin </span>,
471         ];
472       }
473       case ModlogActionType.AdminPurgePerson: {
474         let ap = i.view as AdminPurgePersonView;
475         return [
476           <span>Purged a Person</span>,
477           ap.admin_purge_person.reason.match({
478             some: reason => <div>reason: {reason}</div>,
479             none: <></>,
480           }),
481         ];
482       }
483       case ModlogActionType.AdminPurgeCommunity: {
484         let ap = i.view as AdminPurgeCommunityView;
485         return [
486           <span>Purged a Community</span>,
487           ap.admin_purge_community.reason.match({
488             some: reason => <div>reason: {reason}</div>,
489             none: <></>,
490           }),
491         ];
492       }
493       case ModlogActionType.AdminPurgePost: {
494         let ap = i.view as AdminPurgePostView;
495         return [
496           <span>Purged a Post from from </span>,
497           <CommunityLink community={ap.community} />,
498           ap.admin_purge_post.reason.match({
499             some: reason => <div>reason: {reason}</div>,
500             none: <></>,
501           }),
502         ];
503       }
504       case ModlogActionType.AdminPurgeComment: {
505         let ap = i.view as AdminPurgeCommentView;
506         return [
507           <span>
508             Purged a Comment from{" "}
509             <Link to={`/post/${ap.post.id}`}>{ap.post.name}</Link>
510           </span>,
511           ap.admin_purge_comment.reason.match({
512             some: reason => <div>reason: {reason}</div>,
513             none: <></>,
514           }),
515         ];
516       }
517       default:
518         return <div />;
519     }
520   }
521
522   combined() {
523     let combined = this.state.res.map(this.buildCombined).unwrapOr([]);
524
525     return (
526       <tbody>
527         {combined.map(i => (
528           <tr>
529             <td>
530               <MomentTime published={i.when_} updated={None} />
531             </td>
532             <td>
533               {this.amAdminOrMod ? (
534                 <PersonListing person={i.moderator.unwrap()} />
535               ) : (
536                 <div>{this.modOrAdminText(i.moderator)}</div>
537               )}
538             </td>
539             <td>{this.renderModlogType(i)}</td>
540           </tr>
541         ))}
542       </tbody>
543     );
544   }
545
546   get amAdminOrMod(): boolean {
547     return (
548       amAdmin(Some(this.state.siteRes.admins)) ||
549       amMod(this.state.communityMods)
550     );
551   }
552
553   modOrAdminText(person: Option<PersonSafe>): string {
554     return person.match({
555       some: res =>
556         this.isoData.site_res.admins.map(a => a.person.id).includes(res.id)
557           ? i18n.t("admin")
558           : i18n.t("mod"),
559       none: i18n.t("mod"),
560     });
561   }
562
563   get documentTitle(): string {
564     return this.state.siteRes.site_view.match({
565       some: siteView => `Modlog - ${siteView.site.name}`,
566       none: "",
567     });
568   }
569
570   render() {
571     return (
572       <div className="container">
573         <HtmlTags
574           title={this.documentTitle}
575           path={this.context.router.route.match.url}
576           description={None}
577           image={None}
578         />
579         {this.state.loading ? (
580           <h5>
581             <Spinner large />
582           </h5>
583         ) : (
584           <div>
585             <h5>
586               {this.state.communityName.match({
587                 some: name => (
588                   <Link className="text-body" to={`/c/${name}`}>
589                     /c/{name}{" "}
590                   </Link>
591                 ),
592                 none: <></>,
593               })}
594               <span>{i18n.t("modlog")}</span>
595             </h5>
596             <form className="form-inline mr-2">
597               <select
598                 value={this.state.filter_action}
599                 onChange={linkEvent(this, this.handleFilterActionChange)}
600                 className="custom-select col-4 mb-2"
601                 aria-label="action"
602               >
603                 <option disabled aria-hidden="true">
604                   {i18n.t("filter_by_action")}
605                 </option>
606                 <option value={ModlogActionType.All}>{i18n.t("all")}</option>
607                 <option value={ModlogActionType.ModRemovePost}>
608                   Removing Posts
609                 </option>
610                 <option value={ModlogActionType.ModLockPost}>
611                   Locking Posts
612                 </option>
613                 <option value={ModlogActionType.ModStickyPost}>
614                   Stickying Posts
615                 </option>
616                 <option value={ModlogActionType.ModRemoveComment}>
617                   Removing Comments
618                 </option>
619                 <option value={ModlogActionType.ModRemoveCommunity}>
620                   Removing Communities
621                 </option>
622                 <option value={ModlogActionType.ModBanFromCommunity}>
623                   Banning From Communities
624                 </option>
625                 <option value={ModlogActionType.ModAddCommunity}>
626                   Adding Mod to Community
627                 </option>
628                 <option value={ModlogActionType.ModTransferCommunity}>
629                   Transfering Communities
630                 </option>
631                 <option value={ModlogActionType.ModAdd}>
632                   Adding Mod to Site
633                 </option>
634                 <option value={ModlogActionType.ModBan}>
635                   Banning From Site
636                 </option>
637               </select>
638               {this.state.siteRes.site_view.match({
639                 some: site_view =>
640                   !site_view.site.hide_modlog_mod_names.unwrapOr(false) && (
641                     <select
642                       id="filter-mod"
643                       value={toUndefined(this.state.filter_mod)}
644                     >
645                       <option>{i18n.t("filter_by_mod")}</option>
646                     </select>
647                   ),
648                 none: <></>,
649               })}
650               <select
651                 id="filter-user"
652                 value={toUndefined(this.state.filter_user)}
653               >
654                 <option>{i18n.t("filter_by_user")}</option>
655               </select>
656             </form>
657             <div className="table-responsive">
658               <table id="modlog_table" className="table table-sm table-hover">
659                 <thead className="pointer">
660                   <tr>
661                     <th> {i18n.t("time")}</th>
662                     <th>{i18n.t("mod")}</th>
663                     <th>{i18n.t("action")}</th>
664                   </tr>
665                 </thead>
666                 {this.combined()}
667               </table>
668               <Paginator
669                 page={this.state.page}
670                 onChange={this.handlePageChange}
671               />
672             </div>
673           </div>
674         )}
675       </div>
676     );
677   }
678
679   handleFilterActionChange(i: Modlog, event: any) {
680     i.setState({ filter_action: event.target.value });
681     i.refetch();
682   }
683
684   handlePageChange(val: number) {
685     this.setState({ page: val });
686     this.refetch();
687   }
688
689   refetch() {
690     let modlogForm = new GetModlog({
691       community_id: this.state.communityId,
692       page: Some(this.state.page),
693       limit: Some(fetchLimit),
694       auth: auth(false).ok(),
695       type_: this.state.filter_action,
696       other_person_id: this.state.filter_user,
697       mod_person_id: this.state.filter_mod,
698     });
699     WebSocketService.Instance.send(wsClient.getModlog(modlogForm));
700
701     this.state.communityId.match({
702       some: id => {
703         let communityForm = new GetCommunity({
704           id: Some(id),
705           name: None,
706           auth: auth(false).ok(),
707         });
708         WebSocketService.Instance.send(wsClient.getCommunity(communityForm));
709       },
710       none: void 0,
711     });
712   }
713
714   setupUserFilter() {
715     if (isBrowser()) {
716       let selectId: any = document.getElementById("filter-user");
717       if (selectId) {
718         this.userChoices = new Choices(selectId, choicesModLogConfig);
719         this.userChoices.passedElement.element.addEventListener(
720           "choice",
721           (e: any) => {
722             this.state.filter_user = Some(Number(e.detail.choice.value));
723             this.setState(this.state);
724             this.refetch();
725           },
726           false
727         );
728         this.userChoices.passedElement.element.addEventListener(
729           "search",
730           debounce(async (e: any) => {
731             try {
732               let users = (await fetchUsers(e.detail.value)).users;
733               this.userChoices.setChoices(
734                 users.map(u => {
735                   return {
736                     value: u.person.id.toString(),
737                     label: u.person.name,
738                   };
739                 }),
740                 "value",
741                 "label",
742                 true
743               );
744             } catch (err) {
745               console.log(err);
746             }
747           }),
748           false
749         );
750       }
751     }
752   }
753
754   setupModFilter() {
755     if (isBrowser()) {
756       let selectId: any = document.getElementById("filter-mod");
757       if (selectId) {
758         this.modChoices = new Choices(selectId, choicesModLogConfig);
759         this.modChoices.passedElement.element.addEventListener(
760           "choice",
761           (e: any) => {
762             this.state.filter_mod = Some(Number(e.detail.choice.value));
763             this.setState(this.state);
764             this.refetch();
765           },
766           false
767         );
768         this.modChoices.passedElement.element.addEventListener(
769           "search",
770           debounce(async (e: any) => {
771             try {
772               let mods = (await fetchUsers(e.detail.value)).users;
773               this.modChoices.setChoices(
774                 mods.map(u => {
775                   return {
776                     value: u.person.id.toString(),
777                     label: u.person.name,
778                   };
779                 }),
780                 "value",
781                 "label",
782                 true
783               );
784             } catch (err) {
785               console.log(err);
786             }
787           }),
788           false
789         );
790       }
791     }
792   }
793
794   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
795     let pathSplit = req.path.split("/");
796     let communityId = Some(pathSplit[3]).map(Number);
797     let promises: Promise<any>[] = [];
798
799     let modlogForm = new GetModlog({
800       page: Some(1),
801       limit: Some(fetchLimit),
802       community_id: communityId,
803       mod_person_id: None,
804       auth: req.auth,
805       type_: ModlogActionType.All,
806       other_person_id: None,
807     });
808
809     promises.push(req.client.getModlog(modlogForm));
810
811     if (communityId.isSome()) {
812       let communityForm = new GetCommunity({
813         id: communityId,
814         name: None,
815         auth: req.auth,
816       });
817       promises.push(req.client.getCommunity(communityForm));
818     } else {
819       promises.push(Promise.resolve());
820     }
821     return promises;
822   }
823
824   parseMessage(msg: any) {
825     let op = wsUserOp(msg);
826     console.log(msg);
827     if (msg.error) {
828       toast(i18n.t(msg.error), "danger");
829       return;
830     } else if (op == UserOperation.GetModlog) {
831       let data = wsJsonToRes<GetModlogResponse>(msg, GetModlogResponse);
832       this.state.loading = false;
833       window.scrollTo(0, 0);
834       this.state.res = Some(data);
835       this.setState(this.state);
836     } else if (op == UserOperation.GetCommunity) {
837       let data = wsJsonToRes<GetCommunityResponse>(msg, GetCommunityResponse);
838       this.state.communityMods = Some(data.moderators);
839       this.state.communityName = Some(data.community_view.community.name);
840     }
841   }
842 }