Allow user to submit rate limit changes

This commit is contained in:
abias 2023-05-21 12:40:22 -04:00
parent 2e3c1a6cfa
commit cf58a0c451
3 changed files with 124 additions and 54 deletions

View file

@ -35,6 +35,7 @@ export default class Tabs extends Component<TabsProps, TabsState> {
{this.props.tabs.map(({ key, label }) => (
<li key={key} className="nav-item">
<button
type="button"
className={`nav-link btn${
this.state?.currentTab === key ? " active" : ""
}`}

View file

@ -157,6 +157,10 @@ export class AdminSettings extends Component<any, AdminSettingsState> {
localSiteRateLimit={
this.state.siteRes.site_view.local_site_rate_limit
}
applicationQuestion={
this.state.siteRes.site_view.local_site
.application_question
}
/>
),
},

View file

@ -1,6 +1,9 @@
import { Component, FormEventHandler, linkEvent } from "inferno";
import { LocalSiteRateLimit } from "lemmy-js-client";
import { EditSite, LocalSiteRateLimit } from "lemmy-js-client";
import { i18n } from "../../i18next";
import { WebSocketService } from "../../services";
import { capitalizeFirstLetter, myAuth, wsClient } from "../../utils";
import { Spinner } from "../common/icon";
import Tabs from "../common/tabs";
const rateLimitTypes = [
@ -22,21 +25,25 @@ interface RateLimitsProps {
interface RateLimitFormProps {
localSiteRateLimit: LocalSiteRateLimit;
applicationQuestion?: string;
}
interface RateLimitFormState {
message?: number;
message_per_second?: number;
post?: number;
post_per_second?: number;
comment?: number;
comment_per_second?: number;
image?: number;
image_per_second?: number;
search?: number;
search_per_second?: number;
register?: number;
register_per_second?: number;
form: {
message?: number;
message_per_second?: number;
post?: number;
post_per_second?: number;
comment?: number;
comment_per_second?: number;
image?: number;
image_per_second?: number;
search?: number;
search_per_second?: number;
register?: number;
register_per_second?: number;
};
loading: boolean;
}
function RateLimits({
@ -78,25 +85,52 @@ function handleRateLimitChange(
{ rateLimitType, ctx }: { rateLimitType: string; ctx: RateLimitsForm },
event: any
) {
ctx.setState({
[rateLimitType]: Number(event.target.value),
});
ctx.setState(prev => ({
...prev,
form: {
...prev.form,
[rateLimitType]: Number(event.target.value),
},
}));
}
function handlePerSecondChange(
{ rateLimitType, ctx }: { rateLimitType: string; ctx: RateLimitsForm },
event: any
) {
ctx.setState({
[`${rateLimitType}_per_second`]: Number(event.target.value),
});
ctx.setState(prev => ({
...prev,
form: {
...prev.form,
[`${rateLimitType}_per_second`]: Number(event.target.value),
},
}));
}
function submitRateLimitForm(i: RateLimitsForm, event: any) {
event.preventDefault();
const auth = myAuth() ?? "TODO";
const form: EditSite = Object.entries(i.state.form).reduce(
(acc, [key, val]) => {
acc[`rate_limit_${key}`] = val;
return acc;
},
{ auth, application_question: i.props.applicationQuestion }
);
i.setState({ loading: true });
WebSocketService.Instance.send(wsClient.editSite(form));
}
export default class RateLimitsForm extends Component<
RateLimitFormProps,
RateLimitFormState
> {
state: RateLimitFormState = {};
state: RateLimitFormState = {
loading: false,
form: {},
};
constructor(props: RateLimitFormProps, context) {
super(props, context);
@ -116,46 +150,77 @@ export default class RateLimitsForm extends Component<
} = props.localSiteRateLimit;
this.state = {
comment,
comment_per_second,
image,
image_per_second,
message,
message_per_second,
post,
post_per_second,
register,
register_per_second,
search,
search_per_second,
...this.state,
form: {
comment,
comment_per_second,
image,
image_per_second,
message,
message_per_second,
post,
post_per_second,
register,
register_per_second,
search,
search_per_second,
},
};
}
render() {
return (
<Tabs
tabs={rateLimitTypes.map(rateLimitType => ({
key: rateLimitType,
label: rateLimitType,
getNode: () => (
<RateLimits
handleRateLimit={linkEvent(
{ rateLimitType, ctx: this },
handleRateLimitChange
<form onSubmit={linkEvent(this, submitRateLimitForm)}>
<Tabs
tabs={rateLimitTypes.map(rateLimitType => ({
key: rateLimitType,
label: rateLimitType,
getNode: () => (
<RateLimits
handleRateLimit={linkEvent(
{ rateLimitType, ctx: this },
handleRateLimitChange
)}
handleRateLimitPerSecond={linkEvent(
{ rateLimitType, ctx: this },
handlePerSecondChange
)}
rateLimitLabel={i18n.t(`rate_limit_${rateLimitType}`)}
rateLimitValue={this.state.form[rateLimitType]}
rateLimitPerSecondValue={
this.state.form[`${rateLimitType}_per_second`]
}
/>
),
}))}
/>
<div className="form-group row">
<div className="col-12">
<button
type="submit"
className="btn btn-secondary mr-2"
disabled={this.state.loading}
>
{this.state.loading ? (
<Spinner />
) : (
capitalizeFirstLetter(i18n.t("save"))
)}
handleRateLimitPerSecond={linkEvent(
{ rateLimitType, ctx: this },
handlePerSecondChange
)}
rateLimitLabel={i18n.t(`rate_limit_${rateLimitType}`)}
rateLimitValue={this.state[rateLimitType]}
rateLimitPerSecondValue={
this.state[`${rateLimitType}_per_second`]
}
/>
),
}))}
/>
</button>
</div>
</div>
</form>
);
}
componentDidUpdate({ localSiteRateLimit }: RateLimitFormProps) {
if (
this.state.loading &&
Object.entries(localSiteRateLimit).some(
([key, val]) => this.state.form[key] !== val
)
) {
this.setState({ loading: false });
}
}
}