From cf58a0c4515f4c8ba772c00ca02a9f928fe749fc Mon Sep 17 00:00:00 2001 From: abias <abias1122@gmail.com> Date: Sun, 21 May 2023 12:40:22 -0400 Subject: [PATCH] Allow user to submit rate limit changes --- src/shared/components/common/tabs.tsx | 1 + src/shared/components/home/admin-settings.tsx | 4 + .../components/home/rate-limit-form.tsx | 173 ++++++++++++------ 3 files changed, 124 insertions(+), 54 deletions(-) diff --git a/src/shared/components/common/tabs.tsx b/src/shared/components/common/tabs.tsx index 36e1a01..61ed396 100644 --- a/src/shared/components/common/tabs.tsx +++ b/src/shared/components/common/tabs.tsx @@ -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" : "" }`} diff --git a/src/shared/components/home/admin-settings.tsx b/src/shared/components/home/admin-settings.tsx index 8370bec..d266db5 100644 --- a/src/shared/components/home/admin-settings.tsx +++ b/src/shared/components/home/admin-settings.tsx @@ -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 + } /> ), }, diff --git a/src/shared/components/home/rate-limit-form.tsx b/src/shared/components/home/rate-limit-form.tsx index 95f7fee..db37090 100644 --- a/src/shared/components/home/rate-limit-form.tsx +++ b/src/shared/components/home/rate-limit-form.tsx @@ -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 - )} - handleRateLimitPerSecond={linkEvent( - { rateLimitType, ctx: this }, - handlePerSecondChange + <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")) )} - 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 }); + } + } } -- 2.44.1