]> Untitled Git - lemmy-ui.git/blobdiff - src/shared/components/home/rate-limit-form.tsx
component classes v2
[lemmy-ui.git] / src / shared / components / home / rate-limit-form.tsx
index b99c263061b428809b2b86e78198db40174e9f21..1b2e281b243402bd7802269e7c07a22a379493ce 100644 (file)
-import { Component } from "inferno";
+import { Component, FormEventHandler, linkEvent } from "inferno";
+import { EditSite, LocalSiteRateLimit } from "lemmy-js-client";
+import { i18n } from "../../i18next";
+import { capitalizeFirstLetter, myAuthRequired } from "../../utils";
+import { Spinner } from "../common/icon";
+import Tabs from "../common/tabs";
 
-export default class RateLimitForm extends Component {
-  constructor(props, context) {
+const rateLimitTypes = [
+  "message",
+  "post",
+  "image",
+  "comment",
+  "search",
+  "register",
+] as const;
+
+interface RateLimitsProps {
+  handleRateLimit: FormEventHandler<HTMLInputElement>;
+  handleRateLimitPerSecond: FormEventHandler<HTMLInputElement>;
+  rateLimitValue?: number;
+  rateLimitPerSecondValue?: number;
+}
+
+interface RateLimitFormProps {
+  rateLimits: LocalSiteRateLimit;
+  onSaveSite(form: EditSite): void;
+  loading: boolean;
+}
+
+interface RateLimitFormState {
+  form: {
+    message?: number;
+    message_per_second?: number;
+    post?: number;
+    post_per_second?: number;
+    comment?: number;
+    comment_per_second?: number;
+    image?: number;
+    image_per_second?: number;
+    search?: number;
+    search_per_second?: number;
+    register?: number;
+    register_per_second?: number;
+  };
+}
+
+function RateLimits({
+  handleRateLimit,
+  handleRateLimitPerSecond,
+  rateLimitPerSecondValue,
+  rateLimitValue,
+}: RateLimitsProps) {
+  return (
+    <div className="mb-3 row">
+      <div className="col-md-6">
+        <label htmlFor="rate-limit">{i18n.t("rate_limit")}</label>
+        <input
+          type="number"
+          id="rate-limit"
+          className="form-control"
+          min={0}
+          value={rateLimitValue}
+          onInput={handleRateLimit}
+        />
+      </div>
+      <div className="col-md-6">
+        <label htmlFor="rate-limit-per-second">{i18n.t("per_second")}</label>
+        <input
+          type="number"
+          id="rate-limit-per-second"
+          className="form-control"
+          min={0}
+          value={rateLimitPerSecondValue}
+          onInput={handleRateLimitPerSecond}
+        />
+      </div>
+    </div>
+  );
+}
+
+function handleRateLimitChange(
+  { rateLimitType, ctx }: { rateLimitType: string; ctx: RateLimitsForm },
+  event: any
+) {
+  ctx.setState(prev => ({
+    ...prev,
+    form: {
+      ...prev.form,
+      [rateLimitType]: Number(event.target.value),
+    },
+  }));
+}
+
+function handlePerSecondChange(
+  { rateLimitType, ctx }: { rateLimitType: string; ctx: RateLimitsForm },
+  event: any
+) {
+  ctx.setState(prev => ({
+    ...prev,
+    form: {
+      ...prev.form,
+      [`${rateLimitType}_per_second`]: Number(event.target.value),
+    },
+  }));
+}
+
+function submitRateLimitForm(i: RateLimitsForm, event: any) {
+  event.preventDefault();
+  const auth = myAuthRequired();
+  const form: EditSite = Object.entries(i.state.form).reduce(
+    (acc, [key, val]) => {
+      acc[`rate_limit_${key}`] = val;
+      return acc;
+    },
+    {
+      auth,
+    }
+  );
+
+  i.props.onSaveSite(form);
+}
+
+export default class RateLimitsForm extends Component<
+  RateLimitFormProps,
+  RateLimitFormState
+> {
+  state: RateLimitFormState = {
+    form: this.props.rateLimits,
+  };
+  constructor(props: RateLimitFormProps, context: any) {
     super(props, context);
   }
 
   render() {
-    return <></>;
+    return (
+      <form
+        className="rate-limit-form"
+        onSubmit={linkEvent(this, submitRateLimitForm)}
+      >
+        <h5>{i18n.t("rate_limit_header")}</h5>
+        <Tabs
+          tabs={rateLimitTypes.map(rateLimitType => ({
+            key: rateLimitType,
+            label: i18n.t(`rate_limit_${rateLimitType}`),
+            getNode: () => (
+              <RateLimits
+                handleRateLimit={linkEvent(
+                  { rateLimitType, ctx: this },
+                  handleRateLimitChange
+                )}
+                handleRateLimitPerSecond={linkEvent(
+                  { rateLimitType, ctx: this },
+                  handlePerSecondChange
+                )}
+                rateLimitValue={this.state.form[rateLimitType]}
+                rateLimitPerSecondValue={
+                  this.state.form[`${rateLimitType}_per_second`]
+                }
+              />
+            ),
+          }))}
+        />
+        <div className="col-12 mb-3">
+          <button
+            type="submit"
+            className="btn btn-secondary me-2"
+            disabled={this.props.loading}
+          >
+            {this.props.loading ? (
+              <Spinner />
+            ) : (
+              capitalizeFirstLetter(i18n.t("save"))
+            )}
+          </button>
+        </div>
+      </form>
+    );
   }
 }