]> Untitled Git - lemmy-ui.git/blob - src/shared/components/home/rate-limit-form.tsx
feat: Bootstrap 5 (#1378)
[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 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="col-12 mb-3">
161           <button
162             type="submit"
163             className="btn btn-secondary me-2"
164             disabled={this.props.loading}
165           >
166             {this.props.loading ? (
167               <Spinner />
168             ) : (
169               capitalizeFirstLetter(i18n.t("save"))
170             )}
171           </button>
172         </div>
173       </form>
174     );
175   }
176 }