2023-06-21 22:28:24 +00:00
|
|
|
import { selectableLanguages } from "@utils/app";
|
|
|
|
import { randomStr } from "@utils/helpers";
|
2022-09-22 15:14:58 +00:00
|
|
|
import classNames from "classnames";
|
|
|
|
import { Component, linkEvent } from "inferno";
|
|
|
|
import { Language } from "lemmy-js-client";
|
2023-06-22 00:54:35 +00:00
|
|
|
import { I18NextService, UserService } from "../../services";
|
2022-09-22 15:14:58 +00:00
|
|
|
import { Icon } from "./icon";
|
|
|
|
|
|
|
|
interface LanguageSelectProps {
|
|
|
|
allLanguages: Language[];
|
2022-12-19 15:57:29 +00:00
|
|
|
siteLanguages: number[];
|
2023-01-04 16:56:24 +00:00
|
|
|
selectedLanguageIds?: number[];
|
2023-04-04 12:40:00 +00:00
|
|
|
multiple?: boolean;
|
2022-09-22 15:14:58 +00:00
|
|
|
onChange(val: number[]): any;
|
2022-12-19 15:57:29 +00:00
|
|
|
showAll?: boolean;
|
|
|
|
showSite?: boolean;
|
|
|
|
iconVersion?: boolean;
|
2023-04-04 12:40:00 +00:00
|
|
|
disabled?: boolean;
|
2023-06-09 03:29:24 +00:00
|
|
|
showLanguageWarning?: boolean;
|
2022-09-22 15:14:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export class LanguageSelect extends Component<LanguageSelectProps, any> {
|
|
|
|
private id = `language-select-${randomStr()}`;
|
|
|
|
|
|
|
|
constructor(props: any, context: any) {
|
|
|
|
super(props, context);
|
|
|
|
}
|
|
|
|
|
|
|
|
componentDidMount() {
|
|
|
|
this.setSelectedValues();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Necessary because there is no HTML way to set selected for multiple in value=
|
|
|
|
setSelectedValues() {
|
2023-06-05 21:31:12 +00:00
|
|
|
const ids = this.props.selectedLanguageIds?.map(toString);
|
2023-01-04 16:56:24 +00:00
|
|
|
if (ids) {
|
2023-06-05 21:31:12 +00:00
|
|
|
const select = (document.getElementById(this.id) as HTMLSelectElement)
|
2023-01-04 16:56:24 +00:00
|
|
|
.options;
|
|
|
|
for (let i = 0; i < select.length; i++) {
|
2023-06-05 21:31:12 +00:00
|
|
|
const o = select[i];
|
2023-01-04 16:56:24 +00:00
|
|
|
if (ids.includes(o.value)) {
|
|
|
|
o.selected = true;
|
2022-09-22 15:14:58 +00:00
|
|
|
}
|
2023-01-04 16:56:24 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-22 15:14:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
2022-12-19 15:57:29 +00:00
|
|
|
return this.props.iconVersion ? (
|
|
|
|
this.selectBtn
|
|
|
|
) : (
|
2023-06-20 18:46:16 +00:00
|
|
|
<div className="language-select">
|
2023-06-09 03:29:24 +00:00
|
|
|
{this.props.multiple && this.props.showLanguageWarning && (
|
2023-02-22 13:03:04 +00:00
|
|
|
<div className="alert alert-warning" role="alert">
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("undetermined_language_warning")}
|
2023-02-22 13:03:04 +00:00
|
|
|
</div>
|
|
|
|
)}
|
2023-06-20 12:01:29 +00:00
|
|
|
<div className="mb-3 row">
|
2023-02-21 20:53:35 +00:00
|
|
|
<label
|
2023-04-04 12:40:00 +00:00
|
|
|
className={classNames(
|
|
|
|
"col-form-label",
|
|
|
|
`col-sm-${this.props.multiple ? 3 : 2}`
|
|
|
|
)}
|
2023-02-21 20:53:35 +00:00
|
|
|
htmlFor={this.id}
|
|
|
|
>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t(
|
|
|
|
this.props.multiple ? "language_plural" : "language"
|
|
|
|
)}
|
2023-02-21 20:53:35 +00:00
|
|
|
</label>
|
|
|
|
<div
|
2023-06-21 04:20:05 +00:00
|
|
|
className={classNames(`col-sm-${this.props.multiple ? 9 : 10}`, {
|
|
|
|
"input-group": this.props.multiple,
|
|
|
|
})}
|
2023-02-21 20:53:35 +00:00
|
|
|
>
|
|
|
|
{this.selectBtn}
|
|
|
|
{this.props.multiple && (
|
2023-06-20 12:01:29 +00:00
|
|
|
<button
|
|
|
|
className="btn btn-outline-secondary"
|
|
|
|
onClick={linkEvent(this, this.handleDeselectAll)}
|
|
|
|
>
|
|
|
|
<Icon icon="x" />
|
|
|
|
</button>
|
2023-02-21 20:53:35 +00:00
|
|
|
)}
|
|
|
|
</div>
|
2022-09-22 15:14:58 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-12-19 15:57:29 +00:00
|
|
|
get selectBtn() {
|
2023-04-04 12:40:00 +00:00
|
|
|
const selectedLangs = this.props.selectedLanguageIds;
|
|
|
|
const filteredLangs = selectableLanguages(
|
2022-12-19 15:57:29 +00:00
|
|
|
this.props.allLanguages,
|
|
|
|
this.props.siteLanguages,
|
|
|
|
this.props.showAll,
|
|
|
|
this.props.showSite,
|
|
|
|
UserService.Instance.myUserInfo
|
|
|
|
);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<select
|
2023-06-20 12:01:29 +00:00
|
|
|
className={classNames("form-select w-auto", {
|
|
|
|
"d-inline-block": !this.props.iconVersion,
|
2023-06-16 21:47:42 +00:00
|
|
|
})}
|
2022-12-19 15:57:29 +00:00
|
|
|
id={this.id}
|
|
|
|
onChange={linkEvent(this, this.handleLanguageChange)}
|
2023-06-22 00:54:35 +00:00
|
|
|
aria-label={I18NextService.i18n.t("language_select_placeholder")}
|
2022-12-19 15:57:29 +00:00
|
|
|
multiple={this.props.multiple}
|
2023-04-04 12:40:00 +00:00
|
|
|
disabled={this.props.disabled}
|
2022-12-19 15:57:29 +00:00
|
|
|
>
|
2023-05-13 20:07:05 +00:00
|
|
|
{!this.props.multiple && (
|
|
|
|
<option selected disabled hidden>
|
2023-06-22 00:54:35 +00:00
|
|
|
{I18NextService.i18n.t("language_select_placeholder")}
|
2023-05-13 20:07:05 +00:00
|
|
|
</option>
|
|
|
|
)}
|
2022-12-19 15:57:29 +00:00
|
|
|
{filteredLangs.map(l => (
|
|
|
|
<option
|
|
|
|
key={l.id}
|
|
|
|
value={l.id}
|
2023-01-04 16:56:24 +00:00
|
|
|
selected={selectedLangs?.includes(l.id)}
|
2022-12-19 15:57:29 +00:00
|
|
|
>
|
|
|
|
{l.name}
|
|
|
|
</option>
|
|
|
|
))}
|
|
|
|
</select>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2022-09-22 15:14:58 +00:00
|
|
|
handleLanguageChange(i: LanguageSelect, event: any) {
|
2023-06-05 21:31:12 +00:00
|
|
|
const options: HTMLOptionElement[] = Array.from(event.target.options);
|
|
|
|
const selected: number[] = options
|
2022-09-22 15:14:58 +00:00
|
|
|
.filter(o => o.selected)
|
|
|
|
.map(o => Number(o.value));
|
|
|
|
|
|
|
|
i.props.onChange(selected);
|
|
|
|
}
|
|
|
|
|
|
|
|
handleDeselectAll(i: LanguageSelect, event: any) {
|
|
|
|
event.preventDefault();
|
|
|
|
i.props.onChange([]);
|
|
|
|
}
|
|
|
|
}
|