From 96583bee47733d69dfe584f9a8d83a9c4dce1297 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 23 Jun 2022 15:44:05 -0400 Subject: [PATCH] Adding purging of comments, posts, communities, and users. (#459) * Starting on admin purge. * Updating translations. * Finishing up item purging. --- lemmy-translations | 2 +- package.json | 2 +- .../components/comment/comment-node.tsx | 141 ++++++++++- src/shared/components/common/icon.tsx | 16 ++ src/shared/components/community/community.tsx | 7 + src/shared/components/community/sidebar.tsx | 89 ++++++- src/shared/components/home/home.tsx | 12 + src/shared/components/modlog.tsx | 229 ++++++++++++++---- src/shared/components/person/profile.tsx | 12 + src/shared/components/post/post-listing.tsx | 129 +++++++++- src/shared/components/post/post.tsx | 12 + src/shared/interfaces.ts | 7 + yarn.lock | 8 +- 13 files changed, 578 insertions(+), 88 deletions(-) diff --git a/lemmy-translations b/lemmy-translations index 29c689a..de5d4f3 160000 --- a/lemmy-translations +++ b/lemmy-translations @@ -1 +1 @@ -Subproject commit 29c689af8d16417c1b84d9491f6bcea888720a87 +Subproject commit de5d4f3a758f8e8b41869c90d97e53ab50577f90 diff --git a/package.json b/package.json index 3fa26db..70be154 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "eslint-plugin-prettier": "^4.0.0", "husky": "^7.0.4", "import-sort-style-module": "^6.0.0", - "lemmy-js-client": "0.17.0-rc.32", + "lemmy-js-client": "0.17.0-rc.33", "lint-staged": "^12.4.1", "mini-css-extract-plugin": "^2.6.0", "node-fetch": "^2.6.1", diff --git a/src/shared/components/comment/comment-node.tsx b/src/shared/components/comment/comment-node.tsx index 356a482..27e209e 100644 --- a/src/shared/components/comment/comment-node.tsx +++ b/src/shared/components/comment/comment-node.tsx @@ -17,6 +17,8 @@ import { MarkPersonMentionAsRead, PersonMentionView, PersonViewSafe, + PurgeComment, + PurgePerson, RemoveComment, SaveComment, toUndefined, @@ -24,7 +26,11 @@ import { } from "lemmy-js-client"; import moment from "moment"; import { i18n } from "../../i18next"; -import { BanType, CommentNode as CommentNodeI } from "../../interfaces"; +import { + BanType, + CommentNode as CommentNodeI, + PurgeType, +} from "../../interfaces"; import { UserService, WebSocketService } from "../../services"; import { amCommunityCreator, @@ -42,7 +48,7 @@ import { showScores, wsClient, } from "../../utils"; -import { Icon, Spinner } from "../common/icon"; +import { Icon, PurgeWarning, Spinner } from "../common/icon"; import { MomentTime } from "../common/moment-time"; import { CommunityLink } from "../community/community-link"; import { PersonListing } from "../person/person-listing"; @@ -59,6 +65,10 @@ interface CommentNodeState { banReason: Option; banExpireDays: Option; banType: BanType; + showPurgeDialog: boolean; + purgeReason: Option; + purgeType: PurgeType; + purgeLoading: boolean; showConfirmTransferSite: boolean; showConfirmTransferCommunity: boolean; showConfirmAppointAsMod: boolean; @@ -102,6 +112,10 @@ export class CommentNode extends Component { banReason: None, banExpireDays: None, banType: BanType.Community, + showPurgeDialog: false, + purgeLoading: false, + purgeReason: None, + purgeType: PurgeType.Person, collapsed: false, viewSource: false, showAdvanced: false, @@ -147,6 +161,13 @@ export class CommentNode extends Component { let node = this.props.node; let cv = this.props.node.comment_view; + let purgeTypeText: string; + if (this.state.purgeType == PurgeType.Comment) { + purgeTypeText = i18n.t("purge_comment"); + } else if (this.state.purgeType == PurgeType.Person) { + purgeTypeText = `${i18n.t("purge")} ${cv.creator.name}`; + } + let canMod_ = canMod( this.props.moderators, this.props.admins, @@ -645,30 +666,54 @@ export class CommentNode extends Component { {/* Admins can ban from all, and appoint other admins */} {canAdmin_ && ( <> - {!isAdmin_ && - (!isBanned(cv.creator) ? ( + {!isAdmin_ && ( + <> - ) : ( - ))} + + {!isBanned(cv.creator) ? ( + + ) : ( + + )} + + )} {!isBanned(cv.creator) && cv.creator.local && (!this.state.showConfirmAppointAsAdmin ? ( @@ -848,6 +893,36 @@ export class CommentNode extends Component { )} + + {this.state.showPurgeDialog && ( +
+ + + +
+ {this.state.purgeLoading ? ( + + ) : ( + + )} +
+ + )} {this.state.showReply && ( { i.setState(i.state); } + handlePurgePersonShow(i: CommentNode) { + i.state.showPurgeDialog = true; + i.state.purgeType = PurgeType.Person; + i.state.showRemoveDialog = false; + i.setState(i.state); + } + + handlePurgeCommentShow(i: CommentNode) { + i.state.showPurgeDialog = true; + i.state.purgeType = PurgeType.Comment; + i.state.showRemoveDialog = false; + i.setState(i.state); + } + + handlePurgeReasonChange(i: CommentNode, event: any) { + i.state.purgeReason = Some(event.target.value); + i.setState(i.state); + } + + handlePurgeSubmit(i: CommentNode, event: any) { + event.preventDefault(); + + if (i.state.purgeType == PurgeType.Person) { + let form = new PurgePerson({ + person_id: i.props.node.comment_view.creator.id, + reason: i.state.purgeReason, + auth: auth().unwrap(), + }); + WebSocketService.Instance.send(wsClient.purgePerson(form)); + } else if (i.state.purgeType == PurgeType.Comment) { + let form = new PurgeComment({ + comment_id: i.props.node.comment_view.comment.id, + reason: i.state.purgeReason, + auth: auth().unwrap(), + }); + WebSocketService.Instance.send(wsClient.purgeComment(form)); + } + + i.state.purgeLoading = true; + i.setState(i.state); + } + handleShowConfirmAppointAsMod(i: CommentNode) { i.state.showConfirmAppointAsMod = true; i.setState(i.state); diff --git a/src/shared/components/common/icon.tsx b/src/shared/components/common/icon.tsx index 5de9a3d..91271cf 100644 --- a/src/shared/components/common/icon.tsx +++ b/src/shared/components/common/icon.tsx @@ -1,5 +1,6 @@ import classNames from "classnames"; import { Component } from "inferno"; +import { i18n } from "../../i18next"; interface IconProps { icon: string; @@ -48,3 +49,18 @@ export class Spinner extends Component { ); } } + +export class PurgeWarning extends Component { + constructor(props: any, context: any) { + super(props, context); + } + + render() { + return ( + + ); + } +} diff --git a/src/shared/components/community/community.tsx b/src/shared/components/community/community.tsx index ab00af1..29e3a97 100644 --- a/src/shared/components/community/community.tsx +++ b/src/shared/components/community/community.tsx @@ -19,6 +19,7 @@ import { PostReportResponse, PostResponse, PostView, + PurgeItemResponse, SortType, toOption, UserOperation, @@ -656,6 +657,12 @@ export class Community extends Component { if (data) { toast(i18n.t("report_created")); } + } else if (op == UserOperation.PurgeCommunity) { + let data = wsJsonToRes(msg, PurgeItemResponse); + if (data.success) { + toast(i18n.t("purge_success")); + this.context.router.history.push(`/`); + } } } } diff --git a/src/shared/components/community/sidebar.tsx b/src/shared/components/community/sidebar.tsx index 91c7ba8..0f49ca1 100644 --- a/src/shared/components/community/sidebar.tsx +++ b/src/shared/components/community/sidebar.tsx @@ -1,4 +1,4 @@ -import { Option, Some } from "@sniptt/monads"; +import { None, Option, Some } from "@sniptt/monads"; import { Component, linkEvent } from "inferno"; import { Link } from "inferno-router"; import { @@ -8,6 +8,7 @@ import { DeleteCommunity, FollowCommunity, PersonViewSafe, + PurgeCommunity, RemoveCommunity, SubscribedType, toUndefined, @@ -25,7 +26,7 @@ import { wsClient, } from "../../utils"; import { BannerIconHeader } from "../common/banner-icon-header"; -import { Icon } from "../common/icon"; +import { Icon, PurgeWarning, Spinner } from "../common/icon"; import { CommunityForm } from "../community/community-form"; import { CommunityLink } from "../community/community-link"; import { PersonListing } from "../person/person-listing"; @@ -44,6 +45,9 @@ interface SidebarState { removeExpires: Option; showEdit: boolean; showRemoveDialog: boolean; + showPurgeDialog: boolean; + purgeReason: Option; + purgeLoading: boolean; showConfirmLeaveModTeam: boolean; } @@ -51,8 +55,11 @@ export class Sidebar extends Component { private emptyState: SidebarState = { showEdit: false, showRemoveDialog: false, - removeReason: null, - removeExpires: null, + removeReason: None, + removeExpires: None, + showPurgeDialog: false, + purgeReason: None, + purgeLoading: false, showConfirmLeaveModTeam: false, }; @@ -403,12 +410,19 @@ export class Sidebar extends Component { {i18n.t("restore")} )} + )} {this.state.showRemoveDialog && (
-
+
@@ -426,13 +440,46 @@ export class Sidebar extends Component { {/* */} {/* */} {/*
*/} -
+
)} + {this.state.showPurgeDialog && ( +
+
+ +
+
+ + +
+
+ {this.state.purgeLoading ? ( + + ) : ( + + )} +
+
+ )} ); } @@ -542,13 +589,12 @@ export class Sidebar extends Component { } handleModRemoveReasonChange(i: Sidebar, event: any) { - i.state.removeReason = event.target.value; + i.state.removeReason = Some(event.target.value); i.setState(i.state); } handleModRemoveExpiresChange(i: Sidebar, event: any) { - console.log(event.target.value); - i.state.removeExpires = event.target.value; + i.state.removeExpires = Some(event.target.value); i.setState(i.state); } @@ -566,4 +612,29 @@ export class Sidebar extends Component { i.state.showRemoveDialog = false; i.setState(i.state); } + + handlePurgeCommunityShow(i: Sidebar) { + i.state.showPurgeDialog = true; + i.state.showRemoveDialog = false; + i.setState(i.state); + } + + handlePurgeReasonChange(i: Sidebar, event: any) { + i.state.purgeReason = Some(event.target.value); + i.setState(i.state); + } + + handlePurgeSubmit(i: Sidebar, event: any) { + event.preventDefault(); + + let form = new PurgeCommunity({ + community_id: i.props.community_view.community.id, + reason: i.state.purgeReason, + auth: auth().unwrap(), + }); + WebSocketService.Instance.send(wsClient.purgeCommunity(form)); + + i.state.purgeLoading = true; + i.setState(i.state); + } } diff --git a/src/shared/components/home/home.tsx b/src/shared/components/home/home.tsx index 6baea78..1ff06a0 100644 --- a/src/shared/components/home/home.tsx +++ b/src/shared/components/home/home.tsx @@ -21,6 +21,7 @@ import { PostReportResponse, PostResponse, PostView, + PurgeItemResponse, SiteResponse, SortType, UserOperation, @@ -860,6 +861,17 @@ export class Home extends Component { if (data) { toast(i18n.t("report_created")); } + } else if ( + op == UserOperation.PurgePerson || + op == UserOperation.PurgePost || + op == UserOperation.PurgeComment || + op == UserOperation.PurgeCommunity + ) { + let data = wsJsonToRes(msg, PurgeItemResponse); + if (data.success) { + toast(i18n.t("purge_success")); + this.context.router.history.push(`/`); + } } } } diff --git a/src/shared/components/modlog.tsx b/src/shared/components/modlog.tsx index 0003e54..c90dd64 100644 --- a/src/shared/components/modlog.tsx +++ b/src/shared/components/modlog.tsx @@ -2,6 +2,10 @@ import { None, Option, Some } from "@sniptt/monads"; import { Component } from "inferno"; import { Link } from "inferno-router"; import { + AdminPurgeCommentView, + AdminPurgeCommunityView, + AdminPurgePersonView, + AdminPurgePostView, CommunityModeratorView, GetCommunity, GetCommunityResponse, @@ -57,11 +61,16 @@ enum ModlogEnum { ModTransferCommunity, ModAdd, ModBan, + AdminPurgePerson, + AdminPurgeCommunity, + AdminPurgePost, + AdminPurgeComment, } type ModlogType = { id: number; type_: ModlogEnum; + moderator: PersonSafe; view: | ModRemovePostView | ModLockPostView @@ -72,7 +81,11 @@ type ModlogType = { | ModBanView | ModAddCommunityView | ModTransferCommunityView - | ModAddView; + | ModAddView + | AdminPurgePersonView + | AdminPurgeCommunityView + | AdminPurgePostView + | AdminPurgeCommentView; when_: string; }; @@ -118,11 +131,13 @@ export class Modlog extends Component { if (this.isoData.path == this.context.router.route.match.url) { this.state.res = Some(this.isoData.routeData[0] as GetModlogResponse); - // Getting the moderators - let communityRes = Some( - this.isoData.routeData[1] as GetCommunityResponse - ); - this.state.communityMods = communityRes.map(c => c.moderators); + if (this.isoData.routeData[1]) { + // Getting the moderators + let communityRes = Some( + this.isoData.routeData[1] as GetCommunityResponse + ); + this.state.communityMods = communityRes.map(c => c.moderators); + } this.state.loading = false; } else { @@ -141,6 +156,7 @@ export class Modlog extends Component { id: r.mod_remove_post.id, type_: ModlogEnum.ModRemovePost, view: r, + moderator: r.moderator, when_: r.mod_remove_post.when_, })); @@ -148,6 +164,7 @@ export class Modlog extends Component { id: r.mod_lock_post.id, type_: ModlogEnum.ModLockPost, view: r, + moderator: r.moderator, when_: r.mod_lock_post.when_, })); @@ -155,6 +172,7 @@ export class Modlog extends Component { id: r.mod_sticky_post.id, type_: ModlogEnum.ModStickyPost, view: r, + moderator: r.moderator, when_: r.mod_sticky_post.when_, })); @@ -162,6 +180,7 @@ export class Modlog extends Component { id: r.mod_remove_comment.id, type_: ModlogEnum.ModRemoveComment, view: r, + moderator: r.moderator, when_: r.mod_remove_comment.when_, })); @@ -169,6 +188,7 @@ export class Modlog extends Component { id: r.mod_remove_community.id, type_: ModlogEnum.ModRemoveCommunity, view: r, + moderator: r.moderator, when_: r.mod_remove_community.when_, })); @@ -177,6 +197,7 @@ export class Modlog extends Component { id: r.mod_ban_from_community.id, type_: ModlogEnum.ModBanFromCommunity, view: r, + moderator: r.moderator, when_: r.mod_ban_from_community.when_, }) ); @@ -185,6 +206,7 @@ export class Modlog extends Component { id: r.mod_add_community.id, type_: ModlogEnum.ModAddCommunity, view: r, + moderator: r.moderator, when_: r.mod_add_community.when_, })); @@ -193,6 +215,7 @@ export class Modlog extends Component { id: r.mod_transfer_community.id, type_: ModlogEnum.ModTransferCommunity, view: r, + moderator: r.moderator, when_: r.mod_transfer_community.when_, })); @@ -200,6 +223,7 @@ export class Modlog extends Component { id: r.mod_add.id, type_: ModlogEnum.ModAdd, view: r, + moderator: r.moderator, when_: r.mod_add.when_, })); @@ -207,9 +231,44 @@ export class Modlog extends Component { id: r.mod_ban.id, type_: ModlogEnum.ModBan, view: r, + moderator: r.moderator, when_: r.mod_ban.when_, })); + let purged_persons: ModlogType[] = res.admin_purged_persons.map(r => ({ + id: r.admin_purge_person.id, + type_: ModlogEnum.AdminPurgePerson, + view: r, + moderator: r.admin, + when_: r.admin_purge_person.when_, + })); + + let purged_communities: ModlogType[] = res.admin_purged_communities.map( + r => ({ + id: r.admin_purge_community.id, + type_: ModlogEnum.AdminPurgeCommunity, + view: r, + moderator: r.admin, + when_: r.admin_purge_community.when_, + }) + ); + + let purged_posts: ModlogType[] = res.admin_purged_posts.map(r => ({ + id: r.admin_purge_post.id, + type_: ModlogEnum.AdminPurgePost, + view: r, + moderator: r.admin, + when_: r.admin_purge_post.when_, + })); + + let purged_comments: ModlogType[] = res.admin_purged_comments.map(r => ({ + id: r.admin_purge_comment.id, + type_: ModlogEnum.AdminPurgeComment, + view: r, + moderator: r.admin, + when_: r.admin_purge_comment.when_, + })); + let combined: ModlogType[] = []; combined.push(...removed_posts); @@ -222,6 +281,10 @@ export class Modlog extends Component { combined.push(...transferred_to_community); combined.push(...added); combined.push(...banned); + combined.push(...purged_persons); + combined.push(...purged_communities); + combined.push(...purged_posts); + combined.push(...purged_comments); // Sort them by time combined.sort((a, b) => b.when_.localeCompare(a.when_)); @@ -234,18 +297,22 @@ export class Modlog extends Component { case ModlogEnum.ModRemovePost: { let mrpv = i.view as ModRemovePostView; return [ - mrpv.mod_remove_post.removed ? "Removed " : "Restored ", + mrpv.mod_remove_post.removed.unwrapOr(false) + ? "Removed " + : "Restored ", Post {mrpv.post.name} , - mrpv.mod_remove_post.reason && - ` reason: ${mrpv.mod_remove_post.reason}`, + mrpv.mod_remove_post.reason.match({ + some: reason =>
reason: {reason}
, + none: <>, + }), ]; } case ModlogEnum.ModLockPost: { let mlpv = i.view as ModLockPostView; return [ - mlpv.mod_lock_post.locked ? "Locked " : "Unlocked ", + mlpv.mod_lock_post.locked.unwrapOr(false) ? "Locked " : "Unlocked ", Post {mlpv.post.name} , @@ -254,7 +321,9 @@ export class Modlog extends Component { case ModlogEnum.ModStickyPost: { let mspv = i.view as ModStickyPostView; return [ - mspv.mod_sticky_post.stickied ? "Stickied " : "Unstickied ", + mspv.mod_sticky_post.stickied.unwrapOr(false) + ? "Stickied " + : "Unstickied ", Post {mspv.post.name} , @@ -263,7 +332,9 @@ export class Modlog extends Component { case ModlogEnum.ModRemoveComment: { let mrc = i.view as ModRemoveCommentView; return [ - mrc.mod_remove_comment.removed ? "Removed " : "Restored ", + mrc.mod_remove_comment.removed.unwrapOr(false) + ? "Removed " + : "Restored ", Comment{" "} @@ -274,30 +345,40 @@ export class Modlog extends Component { {" "} by , - mrc.mod_remove_comment.reason && - ` reason: ${mrc.mod_remove_comment.reason}`, + mrc.mod_remove_comment.reason.match({ + some: reason =>
reason: {reason}
, + none: <>, + }), ]; } case ModlogEnum.ModRemoveCommunity: { let mrco = i.view as ModRemoveCommunityView; return [ - mrco.mod_remove_community.removed ? "Removed " : "Restored ", + mrco.mod_remove_community.removed.unwrapOr(false) + ? "Removed " + : "Restored ", Community , - mrco.mod_remove_community.reason.isSome() && - ` reason: ${mrco.mod_remove_community.reason.unwrap()}`, - mrco.mod_remove_community.expires.isSome() && - ` expires: ${moment - .utc(mrco.mod_remove_community.expires.unwrap()) - .fromNow()}`, + mrco.mod_remove_community.reason.match({ + some: reason =>
reason: {reason}
, + none: <>, + }), + mrco.mod_remove_community.expires.match({ + some: expires => ( +
expires: {moment.utc(expires).fromNow()}
+ ), + none: <>, + }), ]; } case ModlogEnum.ModBanFromCommunity: { let mbfc = i.view as ModBanFromCommunityView; return [ - {mbfc.mod_ban_from_community.banned ? "Banned " : "Unbanned "}{" "} + {mbfc.mod_ban_from_community.banned.unwrapOr(false) + ? "Banned " + : "Unbanned "}{" "} , @@ -306,23 +387,25 @@ export class Modlog extends Component { , -
- {mbfc.mod_ban_from_community.reason.isSome() && - ` reason: ${mbfc.mod_ban_from_community.reason.unwrap()}`} -
, -
- {mbfc.mod_ban_from_community.expires.isSome() && - ` expires: ${moment - .utc(mbfc.mod_ban_from_community.expires.unwrap()) - .fromNow()}`} -
, + mbfc.mod_ban_from_community.reason.match({ + some: reason =>
reason: {reason}
, + none: <>, + }), + mbfc.mod_ban_from_community.expires.match({ + some: expires => ( +
expires: {moment.utc(expires).fromNow()}
+ ), + none: <>, + }), ]; } case ModlogEnum.ModAddCommunity: { let mac = i.view as ModAddCommunityView; return [ - {mac.mod_add_community.removed ? "Removed " : "Appointed "}{" "} + {mac.mod_add_community.removed.unwrapOr(false) + ? "Removed " + : "Appointed "}{" "} , @@ -337,7 +420,9 @@ export class Modlog extends Component { let mtc = i.view as ModTransferCommunityView; return [ - {mtc.mod_transfer_community.removed ? "Removed " : "Transferred "}{" "} + {mtc.mod_transfer_community.removed.unwrapOr(false) + ? "Removed " + : "Transferred "}{" "} , @@ -351,27 +436,29 @@ export class Modlog extends Component { case ModlogEnum.ModBan: { let mb = i.view as ModBanView; return [ - {mb.mod_ban.banned ? "Banned " : "Unbanned "} , + + {mb.mod_ban.banned.unwrapOr(false) ? "Banned " : "Unbanned "}{" "} + , , -
- {mb.mod_ban.reason.isSome() && - ` reason: ${mb.mod_ban.reason.unwrap()}`} -
, -
- {mb.mod_ban.expires.isSome() && - ` expires: ${moment.utc(mb.mod_ban.expires.unwrap()).fromNow()}`} -
, + mb.mod_ban.reason.match({ + some: reason =>
reason: {reason}
, + none: <>, + }), + mb.mod_ban.expires.match({ + some: expires => ( +
expires: {moment.utc(expires).fromNow()}
+ ), + none: <>, + }), ]; } case ModlogEnum.ModAdd: { let ma = i.view as ModAddView; return [ - {ma.mod_add.removed.isSome() && ma.mod_add.removed.unwrap() - ? "Removed " - : "Appointed "}{" "} + {ma.mod_add.removed.unwrapOr(false) ? "Removed " : "Appointed "}{" "} , @@ -379,6 +466,50 @@ export class Modlog extends Component { as an admin , ]; } + case ModlogEnum.AdminPurgePerson: { + let ap = i.view as AdminPurgePersonView; + return [ + Purged a Person, + ap.admin_purge_person.reason.match({ + some: reason =>
reason: {reason}
, + none: <>, + }), + ]; + } + case ModlogEnum.AdminPurgeCommunity: { + let ap = i.view as AdminPurgeCommunityView; + return [ + Purged a Community, + ap.admin_purge_community.reason.match({ + some: reason =>
reason: {reason}
, + none: <>, + }), + ]; + } + case ModlogEnum.AdminPurgePost: { + let ap = i.view as AdminPurgePostView; + return [ + Purged a Post from from , + , + ap.admin_purge_post.reason.match({ + some: reason =>
reason: {reason}
, + none: <>, + }), + ]; + } + case ModlogEnum.AdminPurgeComment: { + let ap = i.view as AdminPurgeCommentView; + return [ + + Purged a Comment from{" "} + {ap.post.name} + , + ap.admin_purge_comment.reason.match({ + some: reason =>
reason: {reason}
, + none: <>, + }), + ]; + } default: return
; } @@ -396,9 +527,9 @@ export class Modlog extends Component { {this.amAdminOrMod ? ( - + ) : ( -
{this.modOrAdminText(i.view.moderator)}
+
{this.modOrAdminText(i.moderator)}
)} {this.renderModlogType(i)} @@ -415,7 +546,7 @@ export class Modlog extends Component { ); } - modOrAdminText(person: PersonSafe): Text { + modOrAdminText(person: PersonSafe): string { if ( this.isoData.site_res.admins.map(a => a.person.id).includes(person.id) ) { diff --git a/src/shared/components/person/profile.tsx b/src/shared/components/person/profile.tsx index 053e4b2..9de6d0b 100644 --- a/src/shared/components/person/profile.tsx +++ b/src/shared/components/person/profile.tsx @@ -12,6 +12,7 @@ import { GetPersonDetailsResponse, GetSiteResponse, PostResponse, + PurgeItemResponse, SortType, toUndefined, UserOperation, @@ -897,6 +898,17 @@ export class Profile extends Component { updatePersonBlock(data); this.setPersonBlock(); this.setState(this.state); + } else if ( + op == UserOperation.PurgePerson || + op == UserOperation.PurgePost || + op == UserOperation.PurgeComment || + op == UserOperation.PurgeCommunity + ) { + let data = wsJsonToRes(msg, PurgeItemResponse); + if (data.success) { + toast(i18n.t("purge_success")); + this.context.router.history.push(`/`); + } } } } diff --git a/src/shared/components/post/post-listing.tsx b/src/shared/components/post/post-listing.tsx index eadf48a..cbe84d9 100644 --- a/src/shared/components/post/post-listing.tsx +++ b/src/shared/components/post/post-listing.tsx @@ -15,6 +15,8 @@ import { LockPost, PersonViewSafe, PostView, + PurgePerson, + PurgePost, RemovePost, SavePost, StickyPost, @@ -23,7 +25,7 @@ import { } from "lemmy-js-client"; import { externalHost } from "../../env"; import { i18n } from "../../i18next"; -import { BanType } from "../../interfaces"; +import { BanType, PurgeType } from "../../interfaces"; import { UserService, WebSocketService } from "../../services"; import { amCommunityCreator, @@ -45,7 +47,7 @@ import { showScores, wsClient, } from "../../utils"; -import { Icon } from "../common/icon"; +import { Icon, PurgeWarning, Spinner } from "../common/icon"; import { MomentTime } from "../common/moment-time"; import { PictrsImage } from "../common/pictrs-image"; import { CommunityLink } from "../community/community-link"; @@ -56,6 +58,10 @@ import { PostForm } from "./post-form"; interface PostListingState { showEdit: boolean; showRemoveDialog: boolean; + showPurgeDialog: boolean; + purgeReason: Option; + purgeType: PurgeType; + purgeLoading: boolean; removeReason: Option; showBanDialog: boolean; banReason: Option; @@ -93,6 +99,10 @@ export class PostListing extends Component { private emptyState: PostListingState = { showEdit: false, showRemoveDialog: false, + showPurgeDialog: false, + purgeReason: None, + purgeType: PurgeType.Person, + purgeLoading: false, removeReason: None, showBanDialog: false, banReason: None, @@ -943,24 +953,41 @@ export class PostListing extends Component { {/* Admins can ban from all, and appoint other admins */} {this.canAdmin_ && ( <> - {!this.creatorIsAdmin_ && - (!isBanned(post_view.creator) ? ( + {!this.creatorIsAdmin_ && ( + <> + {!isBanned(post_view.creator) ? ( + + ) : ( + + )} - ) : ( - ))} + + )} {!isBanned(post_view.creator) && post_view.creator.local && ( )} + {this.state.showPurgeDialog && ( +
+ + + + {this.state.purgeLoading ? ( + + ) : ( + + )} + + )} ); } @@ -1411,6 +1474,48 @@ export class PostListing extends Component { i.setState(i.state); } + handlePurgePersonShow(i: PostListing) { + i.state.showPurgeDialog = true; + i.state.purgeType = PurgeType.Person; + i.state.showRemoveDialog = false; + i.setState(i.state); + } + + handlePurgePostShow(i: PostListing) { + i.state.showPurgeDialog = true; + i.state.purgeType = PurgeType.Post; + i.state.showRemoveDialog = false; + i.setState(i.state); + } + + handlePurgeReasonChange(i: PostListing, event: any) { + i.state.purgeReason = Some(event.target.value); + i.setState(i.state); + } + + handlePurgeSubmit(i: PostListing, event: any) { + event.preventDefault(); + + if (i.state.purgeType == PurgeType.Person) { + let form = new PurgePerson({ + person_id: i.props.post_view.creator.id, + reason: i.state.purgeReason, + auth: auth().unwrap(), + }); + WebSocketService.Instance.send(wsClient.purgePerson(form)); + } else if (i.state.purgeType == PurgeType.Post) { + let form = new PurgePost({ + post_id: i.props.post_view.post.id, + reason: i.state.purgeReason, + auth: auth().unwrap(), + }); + WebSocketService.Instance.send(wsClient.purgePost(form)); + } + + i.state.purgeLoading = true; + i.setState(i.state); + } + handleModBanReasonChange(i: PostListing, event: any) { i.state.banReason = Some(event.target.value); i.setState(i.state); diff --git a/src/shared/components/post/post.tsx b/src/shared/components/post/post.tsx index 9b42282..9702c3d 100644 --- a/src/shared/components/post/post.tsx +++ b/src/shared/components/post/post.tsx @@ -19,6 +19,7 @@ import { PostReportResponse, PostResponse, PostView, + PurgeItemResponse, Search, SearchResponse, SearchType, @@ -760,6 +761,17 @@ export class Post extends Component { if (data) { toast(i18n.t("report_created")); } + } else if ( + op == UserOperation.PurgePerson || + op == UserOperation.PurgePost || + op == UserOperation.PurgeComment || + op == UserOperation.PurgeCommunity + ) { + let data = wsJsonToRes(msg, PurgeItemResponse); + if (data.success) { + toast(i18n.t("purge_success")); + this.context.router.history.push(`/`); + } } } } diff --git a/src/shared/interfaces.ts b/src/shared/interfaces.ts index 92fabb8..0a157b5 100644 --- a/src/shared/interfaces.ts +++ b/src/shared/interfaces.ts @@ -73,3 +73,10 @@ export enum PersonDetailsView { Posts, Saved, } + +export enum PurgeType { + Person, + Community, + Post, + Comment, +} diff --git a/yarn.lock b/yarn.lock index a5a342a..41141c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4948,10 +4948,10 @@ lcid@^1.0.0: dependencies: invert-kv "^1.0.0" -lemmy-js-client@0.17.0-rc.32: - version "0.17.0-rc.32" - resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.0-rc.32.tgz#d67f432f1fffc54c267f915278fe260ec554b018" - integrity sha512-qPLybaesu3GVr1DMStsyCYanW4maxHrqX71UHadFMeuh+aUK8taC3zfsLRK9dlIlSDRS283xd8IZkI6ZlcOVEQ== +lemmy-js-client@0.17.0-rc.33: + version "0.17.0-rc.33" + resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.17.0-rc.33.tgz#e05cc88213da3c0c21c7ea53c29054041d619150" + integrity sha512-rG0yCc9AAc5/B+muDfWB7bKizBG7r/xSzHeEw5ms50xF4dN+KOqvRcHTf0+15uAYehBF5B54nyxdlKPRKL9GxQ== levn@^0.4.1: version "0.4.1" -- 2.44.1