]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/rate-limit-form.tsx
Merge branch 'main' into fix-nsfw-blur-spill
[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="form-group row">
55       <label className="col-12 col-form-label" htmlFor="rate-limit">
56         {i18n.t("rate_limit")}
57       </label>
58       <input
59         type="number"
60         id="rate-limit"
61         className="form-control col-12"
62         min={0}
63         value={rateLimitValue}
64         onInput={handleRateLimit}
65       />
66       <label className="col-12 col-form-label" htmlFor="rate-limit-per-second">
67         {i18n.t("per_second")}
68       </label>
69       <input
70         type="number"
71         id="rate-limit-per-second"
72         className="form-control col-12"
73         min={0}
74         value={rateLimitPerSecondValue}
75         onInput={handleRateLimitPerSecond}
76       />
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 onSubmit={linkEvent(this, submitRateLimitForm)}>
137         <h5>{i18n.t("rate_limit_header")}</h5>
138         <Tabs
139           tabs={rateLimitTypes.map(rateLimitType => ({
140             key: rateLimitType,
141             label: i18n.t(`rate_limit_${rateLimitType}`),
142             getNode: () => (
143               <RateLimits
144                 handleRateLimit={linkEvent(
145                   { rateLimitType, ctx: this },
146                   handleRateLimitChange
147                 )}
148                 handleRateLimitPerSecond={linkEvent(
149                   { rateLimitType, ctx: this },
150                   handlePerSecondChange
151                 )}
152                 rateLimitValue={this.state.form[rateLimitType]}
153                 rateLimitPerSecondValue={
154                   this.state.form[`${rateLimitType}_per_second`]
155                 }
156               />
157             ),
158           }))}
159         />
160         <div className="form-group row">
161           <div className="col-12">
162             <button
163               type="submit"
164               className="btn btn-secondary mr-2"
165               disabled={this.props.loading}
166             >
167               {this.props.loading ? (
168                 <Spinner />
169               ) : (
170                 capitalizeFirstLetter(i18n.t("save"))
171               )}
172             </button>
173           </div>
174         </div>
175       </form>
176     );
177   }
178 }