]> Untitled Git - lemmy-ui.git/blob - src/shared/components/common/language-select.tsx
fix: Adds ability to hide language warning
[lemmy-ui.git] / src / shared / components / common / language-select.tsx
1 import classNames from "classnames";
2 import { Component, linkEvent } from "inferno";
3 import { Language } from "lemmy-js-client";
4 import { i18n } from "../../i18next";
5 import { UserService } from "../../services/UserService";
6 import { randomStr, selectableLanguages } from "../../utils";
7 import { Icon } from "./icon";
8
9 interface LanguageSelectProps {
10   allLanguages: Language[];
11   siteLanguages: number[];
12   selectedLanguageIds?: number[];
13   multiple?: boolean;
14   onChange(val: number[]): any;
15   showAll?: boolean;
16   showSite?: boolean;
17   iconVersion?: boolean;
18   disabled?: boolean;
19   hideLanguageWarning?: boolean;
20 }
21
22 export class LanguageSelect extends Component<LanguageSelectProps, any> {
23   private id = `language-select-${randomStr()}`;
24
25   constructor(props: any, context: any) {
26     super(props, context);
27   }
28
29   componentDidMount() {
30     this.setSelectedValues();
31   }
32
33   // Necessary because there is no HTML way to set selected for multiple in value=
34   setSelectedValues() {
35     const ids = this.props.selectedLanguageIds?.map(toString);
36     if (ids) {
37       const select = (document.getElementById(this.id) as HTMLSelectElement)
38         .options;
39       for (let i = 0; i < select.length; i++) {
40         const o = select[i];
41         if (ids.includes(o.value)) {
42           o.selected = true;
43         }
44       }
45     }
46   }
47
48   render() {
49     return this.props.iconVersion ? (
50       this.selectBtn
51     ) : (
52       <div>
53         {this.props.multiple && !this.props.hideLanguageWarning && (
54           <div className="alert alert-warning" role="alert">
55             {i18n.t("undetermined_language_warning")}
56           </div>
57         )}
58         <div className="form-group row">
59           <label
60             className={classNames(
61               "col-form-label",
62               `col-sm-${this.props.multiple ? 3 : 2}`
63             )}
64             htmlFor={this.id}
65           >
66             {i18n.t(this.props.multiple ? "language_plural" : "language")}
67           </label>
68           <div
69             className={classNames(
70               "input-group",
71               `col-sm-${this.props.multiple ? 9 : 10}`
72             )}
73           >
74             {this.selectBtn}
75             {this.props.multiple && (
76               <div className="input-group-append">
77                 <button
78                   className="input-group-text"
79                   onClick={linkEvent(this, this.handleDeselectAll)}
80                 >
81                   <Icon icon="x" />
82                 </button>
83               </div>
84             )}
85           </div>
86         </div>
87       </div>
88     );
89   }
90
91   get selectBtn() {
92     const selectedLangs = this.props.selectedLanguageIds;
93     const filteredLangs = selectableLanguages(
94       this.props.allLanguages,
95       this.props.siteLanguages,
96       this.props.showAll,
97       this.props.showSite,
98       UserService.Instance.myUserInfo
99     );
100
101     return (
102       <select
103         className={classNames(
104           "lang-select-action",
105           this.props.iconVersion
106             ? "btn btn-sm text-muted"
107             : "form-control custom-select"
108         )}
109         id={this.id}
110         onChange={linkEvent(this, this.handleLanguageChange)}
111         aria-label={i18n.t("language_select_placeholder")}
112         multiple={this.props.multiple}
113         disabled={this.props.disabled}
114       >
115         {!this.props.multiple && (
116           <option selected disabled hidden>
117             {i18n.t("language_select_placeholder")}
118           </option>
119         )}
120         {filteredLangs.map(l => (
121           <option
122             key={l.id}
123             value={l.id}
124             selected={selectedLangs?.includes(l.id)}
125           >
126             {l.name}
127           </option>
128         ))}
129       </select>
130     );
131   }
132
133   handleLanguageChange(i: LanguageSelect, event: any) {
134     const options: HTMLOptionElement[] = Array.from(event.target.options);
135     const selected: number[] = options
136       .filter(o => o.selected)
137       .map(o => Number(o.value));
138
139     i.props.onChange(selected);
140   }
141
142   handleDeselectAll(i: LanguageSelect, event: any) {
143     event.preventDefault();
144     i.props.onChange([]);
145   }
146 }