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