1 import { Component, linkEvent } from 'inferno';
2 import { Link } from 'inferno-router';
3 import { Subscription } from 'rxjs';
13 ModRemoveCommunityView,
14 ModBanFromCommunityView,
18 } from 'lemmy-js-client';
19 import { WebSocketService } from '../services';
30 import { MomentTime } from './moment-time';
31 import { HtmlTags } from './html-tags';
32 import moment from 'moment';
33 import { i18n } from '../i18next';
34 import { InitialFetchRequest } from 'shared/interfaces';
35 import { UserListing } from './user-listing';
36 import { CommunityLink } from './community-link';
57 | ModRemoveCommentView
58 | ModRemoveCommunityView
59 | ModBanFromCommunityView
66 interface ModlogState {
67 res: GetModlogResponse;
69 communityName?: string;
75 export class Modlog extends Component<any, ModlogState> {
76 private isoData = setIsoData(this.context);
77 private subscription: Subscription;
78 private emptyState: ModlogState = {
84 removed_communities: [],
85 banned_from_community: [],
87 added_to_community: [],
92 site_view: this.isoData.site_res.site_view,
95 constructor(props: any, context: any) {
96 super(props, context);
98 this.state = this.emptyState;
99 this.state.communityId = this.props.match.params.community_id
100 ? Number(this.props.match.params.community_id)
103 this.parseMessage = this.parseMessage.bind(this);
104 this.subscription = wsSubscribe(this.parseMessage);
106 // Only fetch the data if coming from another route
107 if (this.isoData.path == this.context.router.route.match.url) {
108 let data = this.isoData.routeData[0];
109 this.state.res = data;
110 this.state.loading = false;
116 componentWillUnmount() {
118 this.subscription.unsubscribe();
122 buildCombined(res: GetModlogResponse): ModlogType[] {
123 let removed_posts: ModlogType[] = res.removed_posts.map(r => ({
124 id: r.mod_remove_post.id,
125 type_: ModlogEnum.ModRemovePost,
127 when_: r.mod_remove_post.when_,
130 let locked_posts: ModlogType[] = res.locked_posts.map(r => ({
131 id: r.mod_lock_post.id,
132 type_: ModlogEnum.ModLockPost,
134 when_: r.mod_lock_post.when_,
137 let stickied_posts: ModlogType[] = res.stickied_posts.map(r => ({
138 id: r.mod_sticky_post.id,
139 type_: ModlogEnum.ModStickyPost,
141 when_: r.mod_sticky_post.when_,
144 let removed_comments: ModlogType[] = res.removed_comments.map(r => ({
145 id: r.mod_remove_comment.id,
146 type_: ModlogEnum.ModRemoveComment,
148 when_: r.mod_remove_comment.when_,
151 let removed_communities: ModlogType[] = res.removed_communities.map(r => ({
152 id: r.mod_remove_community.id,
153 type_: ModlogEnum.ModRemoveCommunity,
155 when_: r.mod_remove_community.when_,
158 let banned_from_community: ModlogType[] = res.banned_from_community.map(
160 id: r.mod_ban_from_community.id,
161 type_: ModlogEnum.ModBanFromCommunity,
163 when_: r.mod_ban_from_community.when_,
167 let added_to_community: ModlogType[] = res.added_to_community.map(r => ({
168 id: r.mod_add_community.id,
169 type_: ModlogEnum.ModAddCommunity,
171 when_: r.mod_add_community.when_,
174 let added: ModlogType[] = res.added.map(r => ({
176 type_: ModlogEnum.ModAdd,
178 when_: r.mod_add.when_,
181 let banned: ModlogType[] = res.banned.map(r => ({
183 type_: ModlogEnum.ModBan,
185 when_: r.mod_ban.when_,
188 let combined: ModlogType[] = [];
190 combined.push(...removed_posts);
191 combined.push(...locked_posts);
192 combined.push(...stickied_posts);
193 combined.push(...removed_comments);
194 combined.push(...removed_communities);
195 combined.push(...banned_from_community);
196 combined.push(...added_to_community);
197 combined.push(...added);
198 combined.push(...banned);
200 if (this.state.communityId && combined.length > 0) {
201 this.state.communityName = (combined[0]
202 .view as ModRemovePostView).community.name;
206 combined.sort((a, b) => b.when_.localeCompare(a.when_));
211 renderModlogType(i: ModlogType) {
213 case ModlogEnum.ModRemovePost:
214 let mrpv = i.view as ModRemovePostView;
216 mrpv.mod_remove_post.removed ? 'Removed ' : 'Restored ',
218 Post <Link to={`/post/${mrpv.post.id}`}>{mrpv.post.name}</Link>
220 mrpv.mod_remove_post.reason &&
221 ` reason: ${mrpv.mod_remove_post.reason}`,
223 case ModlogEnum.ModLockPost:
224 let mlpv = i.view as ModLockPostView;
226 mlpv.mod_lock_post.locked ? 'Locked ' : 'Unlocked ',
228 Post <Link to={`/post/${mlpv.post.id}`}>{mlpv.post.name}</Link>
231 case ModlogEnum.ModStickyPost:
232 let mspv = i.view as ModStickyPostView;
234 mspv.mod_sticky_post.stickied ? 'Stickied ' : 'Unstickied ',
236 Post <Link to={`/post/${mspv.post.id}`}>{mspv.post.name}</Link>
239 case ModlogEnum.ModRemoveComment:
240 let mrc = i.view as ModRemoveCommentView;
242 mrc.mod_remove_comment.removed ? 'Removed ' : 'Restored ',
245 <Link to={`/post/${mrc.post.id}/comment/${mrc.comment.id}`}>
246 {mrc.comment.content}
251 by <UserListing user={mrc.commenter} />
253 mrc.mod_remove_comment.reason &&
254 ` reason: ${mrc.mod_remove_comment.reason}`,
256 case ModlogEnum.ModRemoveCommunity:
257 let mrco = i.view as ModRemoveCommunityView;
259 mrco.mod_remove_community.removed ? 'Removed ' : 'Restored ',
261 Community <CommunityLink community={mrco.community} />
263 mrco.mod_remove_community.reason &&
264 ` reason: ${mrco.mod_remove_community.reason}`,
265 mrco.mod_remove_community.expires &&
267 .utc(mrco.mod_remove_community.expires)
270 case ModlogEnum.ModBanFromCommunity:
271 let mbfc = i.view as ModBanFromCommunityView;
274 {mbfc.mod_ban_from_community.banned ? 'Banned ' : 'Unbanned '}{' '}
277 <UserListing user={mbfc.banned_user} />
279 <span> from the community </span>,
281 <CommunityLink community={mbfc.community} />
284 {mbfc.mod_ban_from_community.reason &&
285 ` reason: ${mbfc.mod_ban_from_community.reason}`}
288 {mbfc.mod_ban_from_community.expires &&
290 .utc(mbfc.mod_ban_from_community.expires)
294 case ModlogEnum.ModAddCommunity:
295 let mac = i.view as ModAddCommunityView;
298 {mac.mod_add_community.removed ? 'Removed ' : 'Appointed '}{' '}
301 <UserListing user={mac.modded_user} />
303 <span> as a mod to the community </span>,
305 <CommunityLink community={mac.community} />
308 case ModlogEnum.ModBan:
309 let mb = i.view as ModBanView;
311 <span>{mb.mod_ban.banned ? 'Banned ' : 'Unbanned '} </span>,
313 <UserListing user={mb.banned_user} />
315 <div>{mb.mod_ban.reason && ` reason: ${mb.mod_ban.reason}`}</div>,
317 {mb.mod_ban.expires &&
318 ` expires: ${moment.utc(mb.mod_ban.expires).fromNow()}`}
321 case ModlogEnum.ModAdd:
322 let ma = i.view as ModAddView;
324 <span>{ma.mod_add.removed ? 'Removed ' : 'Appointed '} </span>,
326 <UserListing user={ma.modded_user} />
328 <span> as an admin </span>,
336 let combined = this.buildCombined(this.state.res);
343 <MomentTime data={i} />
346 <UserListing user={i.view.moderator} />
348 <td>{this.renderModlogType(i)}</td>
355 get documentTitle(): string {
356 return `Modlog - ${this.state.site_view.site.name}`;
361 <div class="container">
363 title={this.documentTitle}
364 path={this.context.router.route.match.url}
366 {this.state.loading ? (
368 <svg class="icon icon-spinner spin">
369 <use xlinkHref="#icon-spinner"></use>
375 {this.state.communityName && (
377 className="text-body"
378 to={`/c/${this.state.communityName}`}
380 /c/{this.state.communityName}{' '}
383 <span>{i18n.t('modlog')}</span>
385 <div class="table-responsive">
386 <table id="modlog_table" class="table table-sm table-hover">
387 <thead class="pointer">
389 <th> {i18n.t('time')}</th>
390 <th>{i18n.t('mod')}</th>
391 <th>{i18n.t('action')}</th>
407 {this.state.page > 1 && (
409 class="btn btn-secondary mr-1"
410 onClick={linkEvent(this, this.prevPage)}
416 class="btn btn-secondary"
417 onClick={linkEvent(this, this.nextPage)}
425 nextPage(i: Modlog) {
431 prevPage(i: Modlog) {
438 let modlogForm: GetModlog = {
439 community_id: this.state.communityId,
440 page: this.state.page,
443 WebSocketService.Instance.send(wsClient.getModlog(modlogForm));
446 static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
447 let pathSplit = req.path.split('/');
448 let communityId = pathSplit[3];
449 let promises: Promise<any>[] = [];
451 let modlogForm: GetModlog = {
457 modlogForm.community_id = Number(communityId);
460 promises.push(req.client.getModlog(modlogForm));
464 parseMessage(msg: any) {
465 let op = wsUserOp(msg);
467 toast(i18n.t(msg.error), 'danger');
469 } else if (op == UserOperation.GetModlog) {
470 let data = wsJsonToRes<GetModlogResponse>(msg).data;
471 this.state.loading = false;
472 window.scrollTo(0, 0);
473 this.state.res = data;
474 this.setState(this.state);