]> Untitled Git - lemmy-ui.git/blobdiff - src/shared/components/common/language-select.tsx
component classes v2
[lemmy-ui.git] / src / shared / components / common / language-select.tsx
index 746fea4a188f8fee088db200b3d3d25f962e598f..619e1a5a6203adb04e9cf7bdbeef7cb4b68ffd01 100644 (file)
@@ -1,16 +1,22 @@
-import { Option } from "@sniptt/monads";
 import classNames from "classnames";
 import { Component, linkEvent } from "inferno";
 import { Language } from "lemmy-js-client";
 import { i18n } from "../../i18next";
-import { randomStr } from "../../utils";
+import { UserService } from "../../services/UserService";
+import { randomStr, selectableLanguages } from "../../utils";
 import { Icon } from "./icon";
 
 interface LanguageSelectProps {
   allLanguages: Language[];
-  selectedLanguageIds: Option<number[]>;
-  multiple: boolean;
+  siteLanguages: number[];
+  selectedLanguageIds?: number[];
+  multiple?: boolean;
   onChange(val: number[]): any;
+  showAll?: boolean;
+  showSite?: boolean;
+  iconVersion?: boolean;
+  disabled?: boolean;
+  showLanguageWarning?: boolean;
 }
 
 export class LanguageSelect extends Component<LanguageSelectProps, any> {
@@ -26,76 +32,102 @@ export class LanguageSelect extends Component<LanguageSelectProps, any> {
 
   // Necessary because there is no HTML way to set selected for multiple in value=
   setSelectedValues() {
-    this.props.selectedLanguageIds.map(toString).match({
-      some: ids => {
-        var select = (document.getElementById(this.id) as HTMLSelectElement)
-          .options;
-        for (let i = 0; i < select.length; i++) {
-          let o = select[i];
-          if (ids.includes(o.value)) {
-            o.selected = true;
-          }
+    const ids = this.props.selectedLanguageIds?.map(toString);
+    if (ids) {
+      const select = (document.getElementById(this.id) as HTMLSelectElement)
+        .options;
+      for (let i = 0; i < select.length; i++) {
+        const o = select[i];
+        if (ids.includes(o.value)) {
+          o.selected = true;
         }
-      },
-      none: void 0,
-    });
+      }
+    }
   }
 
   render() {
-    let selectedLangs = this.props.selectedLanguageIds;
-
-    return (
-      <div className="form-group row">
-        <label
-          className={classNames("col-form-label", {
-            "col-sm-3": this.props.multiple,
-            "col-sm-2": !this.props.multiple,
-          })}
-          htmlFor={this.id}
-        >
-          {i18n.t(this.props.multiple ? "language_plural" : "language")}
-        </label>
-        <div
-          className={classNames("input-group", {
-            "col-sm-9": this.props.multiple,
-            "col-sm-10": !this.props.multiple,
-          })}
-        >
-          <select
-            className="form-control custom-select"
-            id={this.id}
-            onChange={linkEvent(this, this.handleLanguageChange)}
-            aria-label="action"
-            multiple={this.props.multiple}
+    return this.props.iconVersion ? (
+      this.selectBtn
+    ) : (
+      <div className="language-select">
+        {this.props.multiple && this.props.showLanguageWarning && (
+          <div className="alert alert-warning" role="alert">
+            {i18n.t("undetermined_language_warning")}
+          </div>
+        )}
+        <div className="mb-3 row">
+          <label
+            className={classNames(
+              "col-form-label",
+              `col-sm-${this.props.multiple ? 3 : 2}`
+            )}
+            htmlFor={this.id}
           >
-            {this.props.allLanguages.map(l => (
-              <option
-                key={l.id}
-                value={l.id}
-                selected={selectedLangs.unwrapOr([]).includes(l.id)}
-              >
-                {l.name}
-              </option>
-            ))}
-          </select>
-          {this.props.multiple && (
-            <div className="input-group-append">
+            {i18n.t(this.props.multiple ? "language_plural" : "language")}
+          </label>
+          <div
+            className={classNames(
+              "input-group",
+              `col-sm-${this.props.multiple ? 9 : 10}`
+            )}
+          >
+            {this.selectBtn}
+            {this.props.multiple && (
               <button
-                className="input-group-text"
+                className="btn btn-outline-secondary"
                 onClick={linkEvent(this, this.handleDeselectAll)}
               >
                 <Icon icon="x" />
               </button>
-            </div>
-          )}
+            )}
+          </div>
         </div>
       </div>
     );
   }
 
+  get selectBtn() {
+    const selectedLangs = this.props.selectedLanguageIds;
+    const filteredLangs = selectableLanguages(
+      this.props.allLanguages,
+      this.props.siteLanguages,
+      this.props.showAll,
+      this.props.showSite,
+      UserService.Instance.myUserInfo
+    );
+
+    return (
+      <select
+        className={classNames("form-select w-auto", {
+          "d-inline-block": !this.props.iconVersion,
+        })}
+        id={this.id}
+        onChange={linkEvent(this, this.handleLanguageChange)}
+        aria-label={i18n.t("language_select_placeholder")}
+        multiple={this.props.multiple}
+        disabled={this.props.disabled}
+      >
+        {!this.props.multiple && (
+          <option selected disabled hidden>
+            {i18n.t("language_select_placeholder")}
+          </option>
+        )}
+        {filteredLangs.map(l => (
+          <option
+            key={l.id}
+            value={l.id}
+            selected={selectedLangs?.includes(l.id)}
+          >
+            {l.name}
+          </option>
+        ))}
+      </select>
+    );
+  }
+
   handleLanguageChange(i: LanguageSelect, event: any) {
-    let options: HTMLOptionElement[] = Array.from(event.target.options);
-    let selected: number[] = options
+    const options: HTMLOptionElement[] = Array.from(event.target.options);
+    const selected: number[] = options
       .filter(o => o.selected)
       .map(o => Number(o.value));