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