]> Untitled Git - lemmy-ui.git/blob - src/shared/components/common/language-select.tsx
Adding a warning for deselecting the undetermined language. (#945)
[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         <div className="alert alert-warning" role="alert">
52           {i18n.t("undetermined_language_warning")}
53         </div>
54         <div className="form-group row">
55           <label
56             className={classNames("col-form-label", {
57               "col-sm-3": this.props.multiple,
58               "col-sm-2": !this.props.multiple,
59             })}
60             htmlFor={this.id}
61           >
62             {i18n.t(this.props.multiple ? "language_plural" : "language")}
63           </label>
64           <div
65             className={classNames("input-group", {
66               "col-sm-9": this.props.multiple,
67               "col-sm-10": !this.props.multiple,
68             })}
69           >
70             {this.selectBtn}
71             {this.props.multiple && (
72               <div className="input-group-append">
73                 <button
74                   className="input-group-text"
75                   onClick={linkEvent(this, this.handleDeselectAll)}
76                 >
77                   <Icon icon="x" />
78                 </button>
79               </div>
80             )}
81           </div>
82         </div>
83       </div>
84     );
85   }
86
87   get selectBtn() {
88     let selectedLangs = this.props.selectedLanguageIds;
89     let filteredLangs = selectableLanguages(
90       this.props.allLanguages,
91       this.props.siteLanguages,
92       this.props.showAll,
93       this.props.showSite,
94       UserService.Instance.myUserInfo
95     );
96
97     return (
98       <select
99         className={classNames("lang-select-action", {
100           "form-control custom-select": !this.props.iconVersion,
101           "btn btn-sm text-muted": this.props.iconVersion,
102         })}
103         id={this.id}
104         onChange={linkEvent(this, this.handleLanguageChange)}
105         aria-label="action"
106         multiple={this.props.multiple}
107       >
108         {filteredLangs.map(l => (
109           <option
110             key={l.id}
111             value={l.id}
112             selected={selectedLangs?.includes(l.id)}
113           >
114             {l.name}
115           </option>
116         ))}
117       </select>
118     );
119   }
120
121   handleLanguageChange(i: LanguageSelect, event: any) {
122     let options: HTMLOptionElement[] = Array.from(event.target.options);
123     let selected: number[] = options
124       .filter(o => o.selected)
125       .map(o => Number(o.value));
126
127     i.props.onChange(selected);
128   }
129
130   handleDeselectAll(i: LanguageSelect, event: any) {
131     event.preventDefault();
132     i.props.onChange([]);
133   }
134 }