]> Untitled Git - lemmy-ui.git/commitdiff
Make admin UI for allowing/blocking instances easier to work with (#1012)
authorSleeplessOne1917 <abias1122@gmail.com>
Tue, 16 May 2023 13:08:52 +0000 (13:08 +0000)
committerGitHub <noreply@github.com>
Tue, 16 May 2023 13:08:52 +0000 (09:08 -0400)
* Make admin UI for allowing/blocking instances easier to work with

* Tweak styles

* Remove log statements

* Trim instance names and slight refactor

* Use linkEvent

src/assets/symbols.svg
src/shared/components/home/site-form.tsx
webpack.config.js

index 43efa4b966465b935429c00d0510e31a0c3e2bec..2fb8eac7b8e7215ccb6d0b8516458c4b22e6bc52 100644 (file)
     <symbol id="icon-refresh-cw" viewBox="0 0 24 24">
       <path d="M4.453 9.334c0.737-2.083 2.247-3.669 4.096-4.552s4.032-1.059 6.114-0.322c1.186 0.42 2.206 1.088 2.983 1.88l2.83 2.66h-3.476c-0.552 0-1 0.448-1 1s0.448 1 1 1h5.997c0.005 0 0.009 0 0.014 0 0.137-0.001 0.268-0.031 0.386-0.082 0.119-0.051 0.229-0.126 0.324-0.225 0.012-0.013 0.024-0.026 0.036-0.039 0.075-0.087 0.133-0.183 0.173-0.285s0.064-0.211 0.069-0.326c0.001-0.015 0.001-0.029 0.001-0.043v-6c0-0.552-0.448-1-1-1s-1 0.448-1 1v3.689l-2.926-2.749c-0.992-1.010-2.271-1.843-3.743-2.364-2.603-0.921-5.335-0.699-7.643 0.402s-4.199 3.086-5.12 5.689c-0.185 0.52 0.088 1.091 0.608 1.276s1.092-0.088 1.276-0.609zM2 16.312l2.955 2.777c1.929 1.931 4.49 2.908 7.048 2.909s5.119-0.975 7.072-2.927c1.104-1.104 1.901-2.407 2.361-3.745 0.18-0.522-0.098-1.091-0.621-1.271s-1.091 0.098-1.271 0.621c-0.361 1.050-0.993 2.091-1.883 2.981-1.563 1.562-3.609 2.342-5.657 2.342s-4.094-0.782-5.679-2.366l-2.8-2.633h3.475c0.552 0 1-0.448 1-1s-0.448-1-1-1h-5.997c-0.005 0-0.009 0-0.014 0-0.137 0.001-0.268 0.031-0.386 0.082-0.119 0.051-0.229 0.126-0.324 0.225-0.012 0.013-0.024 0.026-0.036 0.039-0.075 0.087-0.133 0.183-0.173 0.285s-0.064 0.211-0.069 0.326c-0.001 0.015-0.001 0.029-0.001 0.043v6c0 0.552 0.448 1 1 1s1-0.448 1-1z"></path>
     </symbol>
+    <symbol id="icon-add" viewBox="0 0 32 32" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
+      <path d="M14.5,14.501l-10.502,0c-0.828,0 -1.5,0.673 -1.5,1.5c0,0.828 0.672,1.5 1.5,1.5l10.502,0l-0.001,10.502c0,0.828 0.672,1.5 1.5,1.501c0.828,-0 1.5,-0.673 1.5,-1.5l0.001,-10.503l10.502,0c0.828,0 1.5,-0.672 1.5,-1.5c0,-0.827 -0.672,-1.5 -1.5,-1.5l-10.502,0l0.001,-10.501c-0,-0.828 -0.672,-1.501 -1.5,-1.501c-0.828,0 -1.5,0.672 -1.5,1.5l-0.001,10.502Z"/>
+    </symbol>
     <symbol id="icon-play" viewBox="0 0 24 24">
       <path d="M5.541 2.159c-0.153-0.1-0.34-0.159-0.541-0.159-0.552 0-1 0.448-1 1v18c-0.001 0.182 0.050 0.372 0.159 0.541 0.299 0.465 0.917 0.599 1.382 0.3l14-9c0.114-0.072 0.219-0.174 0.3-0.3 0.299-0.465 0.164-1.083-0.3-1.382zM6 4.832l11.151 7.168-11.151 7.168z"></path>
     </symbol>
index ec37af6daf0c6320b7b45d62db8d039b7f2d298c..ea4d25e8d02ea8da41649718ad9eeac4323e8796 100644 (file)
@@ -1,4 +1,9 @@
-import { Component, InfernoMouseEvent, linkEvent } from "inferno";
+import {
+  Component,
+  InfernoKeyboardEvent,
+  InfernoMouseEvent,
+  linkEvent,
+} from "inferno";
 import { Prompt } from "inferno-router";
 import {
   CreateSite,
@@ -15,7 +20,7 @@ import {
   myAuth,
   wsClient,
 } from "../../utils";
-import { Spinner } from "../common/icon";
+import { Icon, Spinner } from "../common/icon";
 import { ImageUploadForm } from "../common/image-upload-form";
 import { LanguageSelect } from "../common/language-select";
 import { ListingTypeSelect } from "../common/listing-type-select";
@@ -31,14 +36,24 @@ interface SiteFormState {
   siteForm: EditSite;
   loading: boolean;
   themeList?: string[];
+  instance_select: {
+    allowed_instances: string;
+    blocked_instances: string;
+  };
 }
 
+type InstanceKey = "allowed_instances" | "blocked_instances";
+
 export class SiteForm extends Component<SiteFormProps, SiteFormState> {
   state: SiteFormState = {
     siteForm: {
       auth: "TODO",
     },
     loading: false,
+    instance_select: {
+      allowed_instances: "",
+      blocked_instances: "",
+    },
   };
 
   constructor(props: any, context: any) {
@@ -554,44 +569,8 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
           {this.state.siteForm.federation_enabled && (
             <>
               <div className="form-group row">
-                <label
-                  className="col-12 col-form-label"
-                  htmlFor="create-site-allowed-instances"
-                >
-                  {i18n.t("allowed_instances")}
-                </label>
-                <div className="col-12">
-                  <input
-                    type="text"
-                    placeholder="instance1.tld,instance2.tld"
-                    id="create-site-allowed-instances"
-                    className="form-control"
-                    value={this.instancesToString(
-                      this.state.siteForm.allowed_instances
-                    )}
-                    onInput={linkEvent(this, this.handleSiteAllowedInstances)}
-                  />
-                </div>
-              </div>
-              <div className="form-group row">
-                <label
-                  className="col-12 col-form-label"
-                  htmlFor="create-site-blocked-instances"
-                >
-                  {i18n.t("blocked_instances")}
-                </label>
-                <div className="col-12">
-                  <input
-                    type="text"
-                    placeholder="instance1.tld,instance2.tld"
-                    id="create-site-blocked-instances"
-                    className="form-control"
-                    value={this.instancesToString(
-                      this.state.siteForm.blocked_instances
-                    )}
-                    onInput={linkEvent(this, this.handleSiteBlockedInstances)}
-                  />
-                </div>
+                {this.federatedInstanceSelect("allowed_instances")}
+                {this.federatedInstanceSelect("blocked_instances")}
               </div>
               <div className="form-group row">
                 <div className="col-12">
@@ -930,6 +909,86 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
     );
   }
 
+  federatedInstanceSelect(key: InstanceKey) {
+    const id = `create_site_${key}`;
+    const value = this.state.instance_select[key];
+    const selectedInstances = this.state.siteForm[key];
+    return (
+      <div className="col-12 col-md-6">
+        <label className="col-form-label" htmlFor={id}>
+          {i18n.t(key)}
+        </label>
+        <div className="d-flex justify-content-between align-items-center">
+          <input
+            type="text"
+            placeholder="instance.tld"
+            id={id}
+            className="form-control"
+            value={value}
+            onInput={linkEvent(key, this.handleInstanceTextChange)}
+            onKeyUp={linkEvent(key, this.handleInstanceEnterPress)}
+          />
+          <button
+            type="button"
+            className="btn btn-sm bg-success ml-2"
+            onClick={linkEvent(key, this.handleAddInstance)}
+            tabIndex={
+              -1 /* Making this untabble because handling enter key in text input makes keyboard support for this button redundant */
+            }
+          >
+            <Icon icon="add" classes="icon-inline text-light m-auto" />
+          </button>
+        </div>
+        {selectedInstances && selectedInstances.length > 0 && (
+          <ul className="mt-3 list-unstyled w-100 d-flex flex-column justify-content-around align-items-center">
+            {selectedInstances.map(instance => (
+              <li
+                key={instance}
+                className="my-1 w-100 w-md-75 d-flex align-items-center justify-content-between"
+              >
+                <label className="d-block m-0 w-100 " htmlFor={instance}>
+                  <strong>{instance}</strong>
+                </label>
+                <button
+                  id={instance}
+                  type="button"
+                  className="btn btn-sm bg-danger"
+                  onClick={linkEvent(
+                    { key, instance },
+                    this.handleRemoveInstance
+                  )}
+                >
+                  <Icon icon="x" classes="icon-inline text-light m-auto" />
+                </button>
+              </li>
+            ))}
+          </ul>
+        )}
+      </div>
+    );
+  }
+
+  handleInstanceTextChange(type: InstanceKey, event: any) {
+    this.setState(s => ({
+      ...s,
+      instance_select: {
+        ...s.instance_select,
+        [type]: event.target.value,
+      },
+    }));
+  }
+
+  handleInstanceEnterPress(
+    key: InstanceKey,
+    event: InfernoKeyboardEvent<HTMLInputElement>
+  ) {
+    if (event.code.toLowerCase() === "enter") {
+      event.preventDefault();
+
+      this.handleAddInstance(key);
+    }
+  }
+
   handleCreateSiteSubmit(i: SiteForm, event: any) {
     event.preventDefault();
     i.setState({ loading: true });
@@ -986,18 +1045,43 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
     i.setState(i.state);
   }
 
-  instancesToString(opt?: string[]): string {
-    return opt ? opt.join(",") : "";
-  }
-
-  handleSiteAllowedInstances(i: SiteForm, event: any) {
-    let list = splitToList(event.target.value);
-    i.setState(s => ((s.siteForm.allowed_instances = list), s));
+  handleAddInstance(key: InstanceKey) {
+    const instance = this.state.instance_select[key].trim();
+    if (!this.state.siteForm[key]?.includes(instance)) {
+      this.setState(s => ({
+        ...s,
+        siteForm: {
+          ...s.siteForm,
+          [key]: [...(s.siteForm[key] ?? []), instance],
+        },
+        instance_select: {
+          ...s.instance_select,
+          [key]: "",
+        },
+      }));
+
+      const oppositeKey: InstanceKey =
+        key === "allowed_instances" ? "blocked_instances" : "allowed_instances";
+      if (this.state.siteForm[oppositeKey]?.includes(instance)) {
+        this.handleRemoveInstance({ key: oppositeKey, instance });
+      }
+    }
   }
 
-  handleSiteBlockedInstances(i: SiteForm, event: any) {
-    let list = splitToList(event.target.value);
-    i.setState(s => ((s.siteForm.blocked_instances = list), s));
+  handleRemoveInstance({
+    key,
+    instance,
+  }: {
+    key: InstanceKey;
+    instance: string;
+  }) {
+    this.setState(s => ({
+      ...s,
+      siteForm: {
+        ...s.siteForm,
+        [key]: s.siteForm[key]?.filter(i => i !== instance),
+      },
+    }));
   }
 
   handleSiteNameChange(i: SiteForm, event: any) {
@@ -1259,12 +1343,3 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
     this.setState(s => ((s.siteForm.default_post_listing_type = val), s));
   }
 }
-
-function splitToList(commaList: string): string[] {
-  if (commaList !== "") {
-    let list = commaList.trim().split(",");
-    return list;
-  } else {
-    return [];
-  }
-}
index ef5717fef35646c1cc1f5dd97b44628316b87a65..51ca81db3e6ce11c21b2d1075f5ccbb515479f58 100644 (file)
@@ -123,9 +123,12 @@ const createClientConfig = (_env, mode) => {
               urlPattern: ({ url: { pathname, host }, sameOrigin }) =>
                 (sameOrigin || host.includes("localhost")) &&
                 pathname.includes("static"),
-              handler: "CacheFirst",
+              handler: mode === "development" ? "NetworkFirst" : "CacheFirst",
               options: {
                 cacheName: "static-cache",
+                expiration: {
+                  maxAgeSeconds: 60 * 60 * 24,
+                },
               },
             },
             {