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