]> 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 }
28
29 interface RateLimitFormState {
30   form: {
31     message?: number;
32     message_per_second?: number;
33     post?: number;
34     post_per_second?: number;
35     comment?: number;
36     comment_per_second?: number;
37     image?: number;
38     image_per_second?: number;
39     search?: number;
40     search_per_second?: number;
41     register?: number;
42     register_per_second?: number;
43   };
44   loading: boolean;
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.setState({ loading: true });
121   i.props.onSaveSite(form);
122 }
123
124 export default class RateLimitsForm extends Component<
125   RateLimitFormProps,
126   RateLimitFormState
127 > {
128   state: RateLimitFormState = {
129     loading: false,
130     form: this.props.rateLimits,
131   };
132   constructor(props: RateLimitFormProps, context: any) {
133     super(props, context);
134   }
135
136   render() {
137     return (
138       <form onSubmit={linkEvent(this, submitRateLimitForm)}>
139         <h5>{i18n.t("rate_limit_header")}</h5>
140         <Tabs
141           tabs={rateLimitTypes.map(rateLimitType => ({
142             key: rateLimitType,
143             label: i18n.t(`rate_limit_${rateLimitType}`),
144             getNode: () => (
145               <RateLimits
146                 handleRateLimit={linkEvent(
147                   { rateLimitType, ctx: this },
148                   handleRateLimitChange
149                 )}
150                 handleRateLimitPerSecond={linkEvent(
151                   { rateLimitType, ctx: this },
152                   handlePerSecondChange
153                 )}
154                 rateLimitValue={this.state.form[rateLimitType]}
155                 rateLimitPerSecondValue={
156                   this.state.form[`${rateLimitType}_per_second`]
157                 }
158               />
159             ),
160           }))}
161         />
162         <div className="form-group row">
163           <div className="col-12">
164             <button
165               type="submit"
166               className="btn btn-secondary mr-2"
167               disabled={this.state.loading}
168             >
169               {this.state.loading ? (
170                 <Spinner />
171               ) : (
172                 capitalizeFirstLetter(i18n.t("save"))
173               )}
174             </button>
175           </div>
176         </div>
177       </form>
178     );
179   }
180 }