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';
29 import { MomentTime } from './moment-time';
30 import { HtmlTags } from './html-tags';
31 import moment from 'moment';
32 import { i18n } from '../i18next';
33 import { InitialFetchRequest } from 'shared/interfaces';
34 import { UserListing } from './user-listing';
35 import { CommunityLink } from './community-link';
56 | ModRemoveCommentView
57 | ModRemoveCommunityView
58 | ModBanFromCommunityView
65 interface ModlogState {
66 res: GetModlogResponse;
68 communityName?: string;
74 export class Modlog extends Component<any, ModlogState> {
75 private isoData = setIsoData(this.context);
76 private subscription: Subscription;
77 private emptyState: ModlogState = {
83 removed_communities: [],
84 banned_from_community: [],
86 added_to_community: [],
91 site_view: this.isoData.site_res.site_view,
94 constructor(props: any, context: any) {
95 super(props, context);
97 this.state = this.emptyState;
98 this.state.communityId = this.props.match.params.community_id
99 ? Number(this.props.match.params.community_id)
102 this.parseMessage = this.parseMessage.bind(this);
103 this.subscription = wsSubscribe(this.parseMessage);
105 // Only fetch the data if coming from another route
106 if (this.isoData.path == this.context.router.route.match.url) {
107 let data = this.isoData.routeData[0];
108 this.state.res = data;
109 this.state.loading = false;
115 componentWillUnmount() {
117 this.subscription.unsubscribe();
121 buildCombined(res: GetModlogResponse): ModlogType[] {
122 let removed_posts: ModlogType[] = res.removed_posts.map(r => ({
123 id: r.mod_remove_post.id,
124 type_: ModlogEnum.ModRemovePost,
126 when_: r.mod_remove_post.when_,
129 let locked_posts: ModlogType[] = res.locked_posts.map(r => ({
130 id: r.mod_lock_post.id,
131 type_: ModlogEnum.ModLockPost,
133 when_: r.mod_lock_post.when_,
136 let stickied_posts: ModlogType[] = res.stickied_posts.map(r => ({
137 id: r.mod_sticky_post.id,
138 type_: ModlogEnum.ModStickyPost,
140 when_: r.mod_sticky_post.when_,
143 let removed_comments: ModlogType[] = res.removed_comments.map(r => ({
144 id: r.mod_remove_comment.id,
145 type_: ModlogEnum.ModRemoveComment,
147 when_: r.mod_remove_comment.when_,
150 let removed_communities: ModlogType[] = res.removed_communities.map(r => ({
151 id: r.mod_remove_community.id,
152 type_: ModlogEnum.ModRemoveCommunity,
154 when_: r.mod_remove_community.when_,
157 let banned_from_community: ModlogType[] = res.banned_from_community.map(
159 id: r.mod_ban_from_community.id,
160 type_: ModlogEnum.ModBanFromCommunity,
162 when_: r.mod_ban_from_community.when_,
166 let added_to_community: ModlogType[] = res.added_to_community.map(r => ({
167 id: r.mod_add_community.id,
168 type_: ModlogEnum.ModAddCommunity,
170 when_: r.mod_add_community.when_,
173 let added: ModlogType[] = res.added.map(r => ({
175 type_: ModlogEnum.ModAdd,
177 when_: r.mod_add.when_,
180 let banned: ModlogType[] = res.banned.map(r => ({
182 type_: ModlogEnum.ModBan,
184 when_: r.mod_ban.when_,
187 let combined: ModlogType[] = [];
189 combined.push(...removed_posts);
190 combined.push(...locked_posts);
191 combined.push(...stickied_posts);
192 combined.push(...removed_comments);
193 combined.push(...removed_communities);
194 combined.push(...banned_from_community);
195 combined.push(...added_to_community);
196 combined.push(...added);
197 combined.push(...banned);
199 if (this.state.communityId && combined.length > 0) {
200 this.state.communityName = (combined[0]
201 .view as ModRemovePostView).community.name;
205 combined.sort((a, b) => b.when_.localeCompare(a.when_));
210 renderModlogType(i: ModlogType) {
212 case ModlogEnum.ModRemovePost:
213 let mrpv = i.view as ModRemovePostView;
215 mrpv.mod_remove_post.removed ? 'Removed ' : 'Restored ',
217 Post <Link to={`/post/${mrpv.post.id}`}>{mrpv.post.name}</Link>
219 mrpv.mod_remove_post.reason &&
220 ` reason: ${mrpv.mod_remove_post.reason}`,
222 case ModlogEnum.ModLockPost:
223 let mlpv = i.view as ModLockPostView;
225 mlpv.mod_lock_post.locked ? 'Locked ' : 'Unlocked ',
227 Post <Link to={`/post/${mlpv.post.id}`}>{mlpv.post.name}</Link>
230 case ModlogEnum.ModStickyPost:
231 let mspv = i.view as ModStickyPostView;
233 mspv.mod_sticky_post.stickied ? 'Stickied ' : 'Unstickied ',
235 Post <Link to={`/post/${mspv.post.id}`}>{mspv.post.name}</Link>
238 case ModlogEnum.ModRemoveComment:
239 let mrc = i.view as ModRemoveCommentView;
241 mrc.mod_remove_comment.removed ? 'Removed ' : 'Restored ',
244 <Link to={`/post/${mrc.post.id}/comment/${mrc.comment.id}`}>
245 {mrc.comment.content}
250 by <UserListing user={mrc.commenter} />
252 mrc.mod_remove_comment.reason &&
253 ` reason: ${mrc.mod_remove_comment.reason}`,
255 case ModlogEnum.ModRemoveCommunity:
256 let mrco = i.view as ModRemoveCommunityView;
258 mrco.mod_remove_community.removed ? 'Removed ' : 'Restored ',
260 Community <CommunityLink community={mrco.community} />
262 mrco.mod_remove_community.reason &&
263 ` reason: ${mrco.mod_remove_community.reason}`,
264 mrco.mod_remove_community.expires &&
266 .utc(mrco.mod_remove_community.expires)
269 case ModlogEnum.ModBanFromCommunity:
270 let mbfc = i.view as ModBanFromCommunityView;
273 {mbfc.mod_ban_from_community.banned ? 'Banned ' : 'Unbanned '}{' '}
276 <UserListing user={mbfc.banned_user} />
278 <span> from the community </span>,
280 <CommunityLink community={mbfc.community} />
283 {mbfc.mod_ban_from_community.reason &&
284 ` reason: ${mbfc.mod_ban_from_community.reason}`}
287 {mbfc.mod_ban_from_community.expires &&
289 .utc(mbfc.mod_ban_from_community.expires)
293 case ModlogEnum.ModAddCommunity:
294 let mac = i.view as ModAddCommunityView;
297 {mac.mod_add_community.removed ? 'Removed ' : 'Appointed '}{' '}
300 <UserListing user={mac.modded_user} />
302 <span> as a mod to the community </span>,
304 <CommunityLink community={mac.community} />
307 case ModlogEnum.ModBan:
308 let mb = i.view as ModBanView;
310 <span>{mb.mod_ban.banned ? 'Banned ' : 'Unbanned '} </span>,
312 <UserListing user={mb.banned_user} />
314 <div>{mb.mod_ban.reason && ` reason: ${mb.mod_ban.reason}`}</div>,
316 {mb.mod_ban.expires &&
317 ` expires: ${moment.utc(mb.mod_ban.expires).fromNow()}`}
320 case ModlogEnum.ModAdd:
321 let ma = i.view as ModAddView;
323 <span>{ma.mod_add.removed ? 'Removed ' : 'Appointed '} </span>,
325 <UserListing user={ma.modded_user} />
327 <span> as an admin </span>,
335 let combined = this.buildCombined(this.state.res);
342 <MomentTime data={i} />
345 <UserListing user={i.view.moderator} />
347 <td>{this.renderModlogType(i)}</td>
354 get documentTitle(): string {
355 return `Modlog - ${this.state.site_view.site.name}`;
360 <div class="container">
362 title={this.documentTitle}
363 path={this.context.router.route.match.url}
365 {this.state.loading ? (
367 <svg class="icon icon-spinner spin">
368 <use xlinkHref="#icon-spinner"></use>
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.client.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);