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';
37 import { Spinner } from './icon';
58 | ModRemoveCommentView
59 | ModRemoveCommunityView
60 | ModBanFromCommunityView
67 interface ModlogState {
68 res: GetModlogResponse;
70 communityName?: string;
76 export class Modlog extends Component<any, ModlogState> {
77 private isoData = setIsoData(this.context);
78 private subscription: Subscription;
79 private emptyState: ModlogState = {
85 removed_communities: [],
86 banned_from_community: [],
88 added_to_community: [],
93 site_view: this.isoData.site_res.site_view,
96 constructor(props: any, context: any) {
97 super(props, context);
99 this.state = this.emptyState;
100 this.state.communityId = this.props.match.params.community_id
101 ? Number(this.props.match.params.community_id)
104 this.parseMessage = this.parseMessage.bind(this);
105 this.subscription = wsSubscribe(this.parseMessage);
107 // Only fetch the data if coming from another route
108 if (this.isoData.path == this.context.router.route.match.url) {
109 let data = this.isoData.routeData[0];
110 this.state.res = data;
111 this.state.loading = false;
117 componentWillUnmount() {
119 this.subscription.unsubscribe();
123 buildCombined(res: GetModlogResponse): ModlogType[] {
124 let removed_posts: ModlogType[] = res.removed_posts.map(r => ({
125 id: r.mod_remove_post.id,
126 type_: ModlogEnum.ModRemovePost,
128 when_: r.mod_remove_post.when_,
131 let locked_posts: ModlogType[] = res.locked_posts.map(r => ({
132 id: r.mod_lock_post.id,
133 type_: ModlogEnum.ModLockPost,
135 when_: r.mod_lock_post.when_,
138 let stickied_posts: ModlogType[] = res.stickied_posts.map(r => ({
139 id: r.mod_sticky_post.id,
140 type_: ModlogEnum.ModStickyPost,
142 when_: r.mod_sticky_post.when_,
145 let removed_comments: ModlogType[] = res.removed_comments.map(r => ({
146 id: r.mod_remove_comment.id,
147 type_: ModlogEnum.ModRemoveComment,
149 when_: r.mod_remove_comment.when_,
152 let removed_communities: ModlogType[] = res.removed_communities.map(r => ({
153 id: r.mod_remove_community.id,
154 type_: ModlogEnum.ModRemoveCommunity,
156 when_: r.mod_remove_community.when_,
159 let banned_from_community: ModlogType[] = res.banned_from_community.map(
161 id: r.mod_ban_from_community.id,
162 type_: ModlogEnum.ModBanFromCommunity,
164 when_: r.mod_ban_from_community.when_,
168 let added_to_community: ModlogType[] = res.added_to_community.map(r => ({
169 id: r.mod_add_community.id,
170 type_: ModlogEnum.ModAddCommunity,
172 when_: r.mod_add_community.when_,
175 let added: ModlogType[] = res.added.map(r => ({
177 type_: ModlogEnum.ModAdd,
179 when_: r.mod_add.when_,
182 let banned: ModlogType[] = res.banned.map(r => ({
184 type_: ModlogEnum.ModBan,
186 when_: r.mod_ban.when_,
189 let combined: ModlogType[] = [];
191 combined.push(...removed_posts);
192 combined.push(...locked_posts);
193 combined.push(...stickied_posts);
194 combined.push(...removed_comments);
195 combined.push(...removed_communities);
196 combined.push(...banned_from_community);
197 combined.push(...added_to_community);
198 combined.push(...added);
199 combined.push(...banned);
201 if (this.state.communityId && combined.length > 0) {
202 this.state.communityName = (combined[0]
203 .view as ModRemovePostView).community.name;
207 combined.sort((a, b) => b.when_.localeCompare(a.when_));
212 renderModlogType(i: ModlogType) {
214 case ModlogEnum.ModRemovePost:
215 let mrpv = i.view as ModRemovePostView;
217 mrpv.mod_remove_post.removed ? 'Removed ' : 'Restored ',
219 Post <Link to={`/post/${mrpv.post.id}`}>{mrpv.post.name}</Link>
221 mrpv.mod_remove_post.reason &&
222 ` reason: ${mrpv.mod_remove_post.reason}`,
224 case ModlogEnum.ModLockPost:
225 let mlpv = i.view as ModLockPostView;
227 mlpv.mod_lock_post.locked ? 'Locked ' : 'Unlocked ',
229 Post <Link to={`/post/${mlpv.post.id}`}>{mlpv.post.name}</Link>
232 case ModlogEnum.ModStickyPost:
233 let mspv = i.view as ModStickyPostView;
235 mspv.mod_sticky_post.stickied ? 'Stickied ' : 'Unstickied ',
237 Post <Link to={`/post/${mspv.post.id}`}>{mspv.post.name}</Link>
240 case ModlogEnum.ModRemoveComment:
241 let mrc = i.view as ModRemoveCommentView;
243 mrc.mod_remove_comment.removed ? 'Removed ' : 'Restored ',
246 <Link to={`/post/${mrc.post.id}/comment/${mrc.comment.id}`}>
247 {mrc.comment.content}
252 by <UserListing user={mrc.commenter} />
254 mrc.mod_remove_comment.reason &&
255 ` reason: ${mrc.mod_remove_comment.reason}`,
257 case ModlogEnum.ModRemoveCommunity:
258 let mrco = i.view as ModRemoveCommunityView;
260 mrco.mod_remove_community.removed ? 'Removed ' : 'Restored ',
262 Community <CommunityLink community={mrco.community} />
264 mrco.mod_remove_community.reason &&
265 ` reason: ${mrco.mod_remove_community.reason}`,
266 mrco.mod_remove_community.expires &&
268 .utc(mrco.mod_remove_community.expires)
271 case ModlogEnum.ModBanFromCommunity:
272 let mbfc = i.view as ModBanFromCommunityView;
275 {mbfc.mod_ban_from_community.banned ? 'Banned ' : 'Unbanned '}{' '}
278 <UserListing user={mbfc.banned_user} />
280 <span> from the community </span>,
282 <CommunityLink community={mbfc.community} />
285 {mbfc.mod_ban_from_community.reason &&
286 ` reason: ${mbfc.mod_ban_from_community.reason}`}
289 {mbfc.mod_ban_from_community.expires &&
291 .utc(mbfc.mod_ban_from_community.expires)
295 case ModlogEnum.ModAddCommunity:
296 let mac = i.view as ModAddCommunityView;
299 {mac.mod_add_community.removed ? 'Removed ' : 'Appointed '}{' '}
302 <UserListing user={mac.modded_user} />
304 <span> as a mod to the community </span>,
306 <CommunityLink community={mac.community} />
309 case ModlogEnum.ModBan:
310 let mb = i.view as ModBanView;
312 <span>{mb.mod_ban.banned ? 'Banned ' : 'Unbanned '} </span>,
314 <UserListing user={mb.banned_user} />
316 <div>{mb.mod_ban.reason && ` reason: ${mb.mod_ban.reason}`}</div>,
318 {mb.mod_ban.expires &&
319 ` expires: ${moment.utc(mb.mod_ban.expires).fromNow()}`}
322 case ModlogEnum.ModAdd:
323 let ma = i.view as ModAddView;
325 <span>{ma.mod_add.removed ? 'Removed ' : 'Appointed '} </span>,
327 <UserListing user={ma.modded_user} />
329 <span> as an admin </span>,
337 let combined = this.buildCombined(this.state.res);
344 <MomentTime data={i} />
347 <UserListing user={i.view.moderator} />
349 <td>{this.renderModlogType(i)}</td>
356 get documentTitle(): string {
357 return `Modlog - ${this.state.site_view.site.name}`;
362 <div class="container">
364 title={this.documentTitle}
365 path={this.context.router.route.match.url}
367 {this.state.loading ? (
374 {this.state.communityName && (
376 className="text-body"
377 to={`/c/${this.state.communityName}`}
379 /c/{this.state.communityName}{' '}
382 <span>{i18n.t('modlog')}</span>
384 <div class="table-responsive">
385 <table id="modlog_table" class="table table-sm table-hover">
386 <thead class="pointer">
388 <th> {i18n.t('time')}</th>
389 <th>{i18n.t('mod')}</th>
390 <th>{i18n.t('action')}</th>
406 {this.state.page > 1 && (
408 class="btn btn-secondary mr-1"
409 onClick={linkEvent(this, this.prevPage)}
415 class="btn btn-secondary"
416 onClick={linkEvent(this, this.nextPage)}
424 nextPage(i: Modlog) {
430 prevPage(i: Modlog) {
437 let modlogForm: GetModlog = {
438 community_id: this.state.communityId,
439 page: this.state.page,
442 WebSocketService.Instance.send(wsClient.getModlog(modlogForm));
445 static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
446 let pathSplit = req.path.split('/');
447 let communityId = pathSplit[3];
448 let promises: Promise<any>[] = [];
450 let modlogForm: GetModlog = {
456 modlogForm.community_id = Number(communityId);
459 promises.push(req.client.getModlog(modlogForm));
463 parseMessage(msg: any) {
464 let op = wsUserOp(msg);
466 toast(i18n.t(msg.error), 'danger');
468 } else if (op == UserOperation.GetModlog) {
469 let data = wsJsonToRes<GetModlogResponse>(msg).data;
470 this.state.loading = false;
471 window.scrollTo(0, 0);
472 this.state.res = data;
473 this.setState(this.state);