1 import { selectableLanguages } from "@utils/app";
2 import { randomStr } from "@utils/helpers";
3 import classNames from "classnames";
4 import { Component, linkEvent } from "inferno";
5 import { Language } from "lemmy-js-client";
6 import { I18NextService, UserService } from "../../services";
7 import { Icon } from "./icon";
9 interface LanguageSelectProps {
10 allLanguages: Language[];
11 siteLanguages: number[];
12 selectedLanguageIds?: number[];
14 onChange(val: number[]): any;
17 iconVersion?: boolean;
19 showLanguageWarning?: boolean;
22 export class LanguageSelect extends Component<LanguageSelectProps, any> {
23 private id = `language-select-${randomStr()}`;
25 constructor(props: any, context: any) {
26 super(props, context);
30 this.setSelectedValues();
33 // Necessary because there is no HTML way to set selected for multiple in value=
35 const ids = this.props.selectedLanguageIds?.map(toString);
37 const select = (document.getElementById(this.id) as HTMLSelectElement)
39 for (let i = 0; i < select.length; i++) {
41 if (ids.includes(o.value)) {
49 return this.props.iconVersion ? (
52 <div className="language-select mb-3">
54 className={classNames(
56 `col-sm-${this.props.multiple ? 3 : 2}`,
60 {I18NextService.i18n.t(
61 this.props.multiple ? "language_plural" : "language",
64 {this.props.multiple && this.props.showLanguageWarning && (
67 className="alert small alert-warning"
70 <Icon icon="alert-triangle" classes="icon-inline me-2" />
71 {I18NextService.i18n.t("undetermined_language_warning")}
75 className={classNames(`col-sm-${this.props.multiple ? 9 : 10}`, {
76 "input-group": this.props.multiple,
80 {this.props.multiple && (
82 className="btn btn-outline-secondary"
83 onClick={linkEvent(this, this.handleDeselectAll)}
94 const selectedLangs = this.props.selectedLanguageIds;
95 const filteredLangs = selectableLanguages(
96 this.props.allLanguages,
97 this.props.siteLanguages,
100 UserService.Instance.myUserInfo,
105 className={classNames("form-select w-auto", {
106 "d-inline-block": !this.props.iconVersion,
109 onChange={linkEvent(this, this.handleLanguageChange)}
110 aria-label={I18NextService.i18n.t("language_select_placeholder")}
112 this.props.multiple && this.props.showLanguageWarning
116 multiple={this.props.multiple}
117 disabled={this.props.disabled}
119 {!this.props.multiple && (
120 <option selected disabled hidden>
121 {I18NextService.i18n.t("language_select_placeholder")}
124 {filteredLangs.map(l => (
128 selected={selectedLangs?.includes(l.id)}
137 handleLanguageChange(i: LanguageSelect, event: any) {
138 const options: HTMLOptionElement[] = Array.from(event.target.options);
139 const selected: number[] = options
140 .filter(o => o.selected)
141 .map(o => Number(o.value));
143 i.props.onChange(selected);
146 handleDeselectAll(i: LanguageSelect, event: any) {
147 event.preventDefault();
148 i.props.onChange([]);