]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/rate-limit-form.tsx
619e70d8dd501b2adfce1616e2364d6c561b1f13
[lemmy-ui.git] / src / shared / components / home / rate-limit-form.tsx
1 import { myAuthRequired } from "@utils/app";
2 import { capitalizeFirstLetter } from "@utils/helpers";
3 import classNames from "classnames";
4 import { Component, FormEventHandler, linkEvent } from "inferno";
5 import { EditSite, LocalSiteRateLimit } from "lemmy-js-client";
6 import { i18n } from "../../i18next";
7 import { Spinner } from "../common/icon";
8 import Tabs from "../common/tabs";
9
10 const rateLimitTypes = [
11   "message",
12   "post",
13   "image",
14   "comment",
15   "search",
16   "register",
17 ] as const;
18
19 interface RateLimitsProps {
20   handleRateLimit: FormEventHandler<HTMLInputElement>;
21   handleRateLimitPerSecond: FormEventHandler<HTMLInputElement>;
22   rateLimitValue?: number;
23   rateLimitPerSecondValue?: number;
24   className?: string;
25 }
26
27 interface RateLimitFormProps {
28   rateLimits: LocalSiteRateLimit;
29   onSaveSite(form: EditSite): void;
30   loading: boolean;
31 }
32
33 interface RateLimitFormState {
34   form: {
35     message?: number;
36     message_per_second?: number;
37     post?: number;
38     post_per_second?: number;
39     comment?: number;
40     comment_per_second?: number;
41     image?: number;
42     image_per_second?: number;
43     search?: number;
44     search_per_second?: number;
45     register?: number;
46     register_per_second?: number;
47   };
48 }
49
50 function RateLimits({
51   handleRateLimit,
52   handleRateLimitPerSecond,
53   rateLimitPerSecondValue,
54   rateLimitValue,
55   className,
56 }: RateLimitsProps) {
57   return (
58     <div role="tabpanel" className={classNames("mb-3 row", className)}>
59       <div className="col-md-6">
60         <label htmlFor="rate-limit">{i18n.t("rate_limit")}</label>
61         <input
62           type="number"
63           id="rate-limit"
64           className="form-control"
65           min={0}
66           value={rateLimitValue}
67           onInput={handleRateLimit}
68         />
69       </div>
70       <div className="col-md-6">
71         <label htmlFor="rate-limit-per-second">{i18n.t("per_second")}</label>
72         <input
73           type="number"
74           id="rate-limit-per-second"
75           className="form-control"
76           min={0}
77           value={rateLimitPerSecondValue}
78           onInput={handleRateLimitPerSecond}
79         />
80       </div>
81     </div>
82   );
83 }
84
85 function handleRateLimitChange(
86   { rateLimitType, ctx }: { rateLimitType: string; ctx: RateLimitsForm },
87   event: any
88 ) {
89   ctx.setState(prev => ({
90     ...prev,
91     form: {
92       ...prev.form,
93       [rateLimitType]: Number(event.target.value),
94     },
95   }));
96 }
97
98 function handlePerSecondChange(
99   { rateLimitType, ctx }: { rateLimitType: string; ctx: RateLimitsForm },
100   event: any
101 ) {
102   ctx.setState(prev => ({
103     ...prev,
104     form: {
105       ...prev.form,
106       [`${rateLimitType}_per_second`]: Number(event.target.value),
107     },
108   }));
109 }
110
111 function submitRateLimitForm(i: RateLimitsForm, event: any) {
112   event.preventDefault();
113   const auth = myAuthRequired();
114   const form: EditSite = Object.entries(i.state.form).reduce(
115     (acc, [key, val]) => {
116       acc[`rate_limit_${key}`] = val;
117       return acc;
118     },
119     {
120       auth,
121     }
122   );
123
124   i.props.onSaveSite(form);
125 }
126
127 export default class RateLimitsForm extends Component<
128   RateLimitFormProps,
129   RateLimitFormState
130 > {
131   state: RateLimitFormState = {
132     form: this.props.rateLimits,
133   };
134   constructor(props: RateLimitFormProps, context: any) {
135     super(props, context);
136   }
137
138   render() {
139     return (
140       <form
141         className="rate-limit-form"
142         onSubmit={linkEvent(this, submitRateLimitForm)}
143       >
144         <h5>{i18n.t("rate_limit_header")}</h5>
145         <Tabs
146           tabs={rateLimitTypes.map(rateLimitType => ({
147             key: rateLimitType,
148             label: i18n.t(`rate_limit_${rateLimitType}`),
149             getNode: isSelected => (
150               <RateLimits
151                 className={classNames("tab-pane show", {
152                   active: isSelected,
153                 })}
154                 handleRateLimit={linkEvent(
155                   { rateLimitType, ctx: this },
156                   handleRateLimitChange
157                 )}
158                 handleRateLimitPerSecond={linkEvent(
159                   { rateLimitType, ctx: this },
160                   handlePerSecondChange
161                 )}
162                 rateLimitValue={this.state.form[rateLimitType]}
163                 rateLimitPerSecondValue={
164                   this.state.form[`${rateLimitType}_per_second`]
165                 }
166               />
167             ),
168           }))}
169         />
170         <div className="col-12 mb-3">
171           <button
172             type="submit"
173             className="btn btn-secondary me-2"
174             disabled={this.props.loading}
175           >
176             {this.props.loading ? (
177               <Spinner />
178             ) : (
179               capitalizeFirstLetter(i18n.t("save"))
180             )}
181           </button>
182         </div>
183       </form>
184     );
185   }
186 }