Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Moderation/content action overhaul #2258

Merged
merged 46 commits into from
Dec 6, 2023
Merged
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2958988
Fix remove post dialog
SleeplessOne1917 Nov 21, 2023
66301f1
Consolidate mod action logic
SleeplessOne1917 Nov 21, 2023
acab311
Make mod action form less janky
SleeplessOne1917 Nov 21, 2023
5739c6a
Move content action dropdown to its own component
SleeplessOne1917 Nov 21, 2023
05e9d69
Make reusable component for content action buttons
SleeplessOne1917 Nov 22, 2023
5db7cad
Finish up mod dropdown
SleeplessOne1917 Nov 22, 2023
02ce5f9
Introduce new content dropdown component to post listing
SleeplessOne1917 Nov 22, 2023
180545d
Fix cancel moderation button bug
SleeplessOne1917 Nov 22, 2023
06f2953
Add icons, tweak UI
SleeplessOne1917 Nov 22, 2023
38f0c8e
Handle delete/undelete icons
SleeplessOne1917 Nov 22, 2023
b5d2289
The thing
SleeplessOne1917 Nov 23, 2023
995e013
Merge branch 'main' into remove-post
SleeplessOne1917 Nov 23, 2023
3d549b7
Fix some of the banning related bugs
SleeplessOne1917 Nov 24, 2023
240e73d
Merge branch 'main' into remove-post
SleeplessOne1917 Nov 24, 2023
19fb9b1
Fix mod form ban bugs
SleeplessOne1917 Nov 24, 2023
3911500
Fix some more bugs
Nov 27, 2023
4001265
Make comments use dropdown menu
Nov 27, 2023
c15ff06
Use mod action form with comments
Nov 27, 2023
e588b9f
Make confirmation modal
Nov 28, 2023
6382122
Make all the mod action dialogs modals
Nov 28, 2023
19aff8c
Merge branch 'main' into remove-post
Nov 28, 2023
c2317b9
Tweak modal
Nov 29, 2023
ec8c5f2
Fix bug with mod form submit
Nov 29, 2023
d2ebda5
Tweak modal more
Nov 29, 2023
506882b
More modal tweaking and some feedback toasts
Nov 30, 2023
4b75025
Use icon pairs for on/off
Nov 30, 2023
b3fad98
Merge branch 'main' into remove-post
SleeplessOne1917 Nov 30, 2023
d6d78dc
Make modals auto focus input
Nov 30, 2023
bde4c84
Merge branch 'remove-post' of https://github.com/LemmyNet/lemmy-ui in…
Nov 30, 2023
df03f4e
Merge branch 'main' into remove-post
SleeplessOne1917 Nov 30, 2023
341c9fd
Merge branch 'main' into remove-post
Nov 30, 2023
6aca865
Merge branch 'remove-post' of https://github.com/LemmyNet/lemmy-ui in…
Nov 30, 2023
80e666a
Implement PR suggestions
Nov 30, 2023
4688abf
Make UI use async functions where needed
Dec 2, 2023
6b53bb0
Merge branch 'main' into remove-post
Dec 2, 2023
3e050da
Make loading state for context action modals
Dec 2, 2023
63292a1
Hide context actions that users should not be able to do
Dec 2, 2023
ff1d836
Add loading state to confirmation modals
Dec 2, 2023
b422292
Merge branch 'main' into remove-post
SleeplessOne1917 Dec 5, 2023
ad0deb6
Merge branch 'main' into remove-post
Dec 5, 2023
d484f62
Merge branch 'remove-post' of https://github.com/LemmyNet/lemmy-ui in…
Dec 5, 2023
93cee04
Use updated translations
Dec 6, 2023
1a621f2
PR feedback
Dec 6, 2023
41ef341
Add forgotten trnslations
Dec 6, 2023
8106aff
Fix scrolling bug
Dec 6, 2023
dac7121
Merge branch 'main' into remove-post
Dec 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Consolidate mod action logic
  • Loading branch information
SleeplessOne1917 committed Nov 21, 2023
commit 66301f152681e35f6dfe6a16af3b726f81b6eb5b
2 changes: 1 addition & 1 deletion src/shared/components/comment/comment-node.tsx
Original file line number Diff line number Diff line change
@@ -971,7 +971,7 @@ export class CommentNode extends Component<CommentNodeProps, CommentNodeState> {
{this.state.showReportDialog && (
<ModerationActionForm
onSubmit={this.handleReportComment}
buttonText={I18NextService.i18n.t("create-report")}
modActionType="report"
/>
)}
{this.state.showBanDialog && (
145 changes: 136 additions & 9 deletions src/shared/components/common/mod-action-form.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,78 @@
import { Component, linkEvent } from "inferno";
import { I18NextService } from "../../services/I18NextService";
import { Spinner } from "./icon";
import { randomStr } from "@utils/helpers";
import { PurgeWarning, Spinner } from "./icon";
import { capitalizeFirstLetter, randomStr } from "@utils/helpers";

interface ModActionFormProps {
export interface BanUpdateForm {
reason?: string;
shouldRemove?: boolean;
daysUntilExpires?: number;
}

interface ModActionFormPropsBan {
modActionType: "ban";
onSubmit: (form: BanUpdateForm) => void;
creatorName: string;
}

interface ModActionFormPropsPurgePerson {
modActionType: "purge-person";
onSubmit: (reason: string) => void;
creatorName: string;
}

interface ModActionFormPropsRemove {
modActionType: "remove";
onSubmit: (reason: string) => void;
isRemoved: boolean;
}

interface ModActionFormPropsRest {
modActionType: "report" | "purge-post";
onSubmit: (reason: string) => void;
buttonText: string;
}

type ModActionFormProps =
| ModActionFormPropsBan
| ModActionFormPropsRest
| ModActionFormPropsPurgePerson
| ModActionFormPropsRemove;

interface ModActionFormFormState {
loading: boolean;
reason: string;
daysUntilExpire?: number;
shouldRemoveData?: boolean;
}

function handleReportReasonChange(i: ModerationActionForm, event: any) {
function handleReasonChange(i: ModerationActionForm, event: any) {
i.setState({ reason: event.target.value });
}

function handleExpiryChange(i: ModerationActionForm, event: any) {
i.setState({ daysUntilExpire: parseInt(event.target.value, 10) });
}

function handleShouldRemoveChange(i: ModerationActionForm) {
i.setState(prev => ({
...prev,
shouldRemoveData: !prev.shouldRemoveData,
}));
}

function handleSubmit(i: ModerationActionForm, event: any) {
event.preventDefault();
i.setState({ loading: true });
i.props.onSubmit(i.state.reason);

if (i.props.modActionType === "ban") {
i.props.onSubmit({
reason: i.state.reason,
daysUntilExpires: i.state.daysUntilExpire!,
shouldRemove: i.state.shouldRemoveData!,
});
} else {
i.props.onSubmit(i.state.reason);
}

i.setState({
loading: false,
@@ -36,16 +88,57 @@ export default class ModerationActionForm extends Component<
loading: false,
reason: "",
};

constructor(props: ModActionFormProps, context: any) {
super(props, context);

if (this.props.modActionType === "ban") {
this.state.daysUntilExpire = 1;
this.state.shouldRemoveData = false;
}
}

render() {
const { loading, reason } = this.state;
const { loading, reason, daysUntilExpire, shouldRemoveData } = this.state;
const id = `mod-form-${randomStr()}`;

let buttonText: string;
switch (this.props.modActionType) {
case "ban": {
buttonText = `${I18NextService.i18n.t("ban")} ${
this.props.creatorName
}`;
break;
}

case "purge-post": {
buttonText = I18NextService.i18n.t("purge");
break;
}

case "purge-person": {
buttonText = `${I18NextService.i18n.t("purge")} ${
this.props.creatorName
}`;
break;
}

case "remove": {
buttonText = I18NextService.i18n.t(
this.props.isRemoved ? "restore" : "remove",
);
break;
}

case "report": {
buttonText = I18NextService.i18n.t("create_report");
break;
}
}

return (
<form className="form-inline" onSubmit={linkEvent(this, handleSubmit)}>
{this.props.modActionType.includes("purge") && <PurgeWarning />}
<label className="visually-hidden" htmlFor={id}>
{I18NextService.i18n.t("reason")}
</label>
@@ -56,10 +149,44 @@ export default class ModerationActionForm extends Component<
placeholder={I18NextService.i18n.t("reason")}
required
value={reason}
onInput={linkEvent(this, handleReportReasonChange)}
onInput={linkEvent(this, handleReasonChange)}
/>
{this.props.modActionType === "ban" && (
<>
<label className="col-form-label" htmlFor="mod-ban-expires">
{I18NextService.i18n.t("expires")}
</label>
<input
type="number"
id="mod-ban-expires"
className="form-control me-2"
placeholder={I18NextService.i18n.t("number_of_days")}
min={1}
value={daysUntilExpire}
onInput={linkEvent(this, handleExpiryChange)}
/>
<div className="input-group mb-3">
<div className="form-check">
<input
className="form-check-input"
id="mod-ban-remove-data"
type="checkbox"
checked={shouldRemoveData}
onChange={linkEvent(this, handleShouldRemoveChange)}
/>
<label
className="form-check-label"
htmlFor="mod-ban-remove-data"
title={I18NextService.i18n.t("remove_content_more")}
>
{I18NextService.i18n.t("remove_content")}
</label>
</div>
</div>
</>
)}
<button type="submit" className="btn btn-secondary">
{loading ? <Spinner /> : this.props.buttonText}
{loading ? <Spinner /> : capitalizeFirstLetter(buttonText)}
</button>
</form>
);
Loading