Add navigation prompt to other pages

This commit is contained in:
abias 2023-06-08 17:46:49 -04:00
parent 3162959da1
commit 8ee02da559
5 changed files with 887 additions and 935 deletions

View file

@ -8,6 +8,7 @@ interface NavigationPromptProps {
interface NavigationPromptState {
promptState: "hidden" | "show" | "approved";
calls: number;
}
export default class NavigationPrompt extends Component<
@ -16,6 +17,7 @@ export default class NavigationPrompt extends Component<
> {
state: NavigationPromptState = {
promptState: "hidden",
calls: 0,
};
constructor(props: NavigationPromptProps, context: any) {
@ -23,15 +25,21 @@ export default class NavigationPrompt extends Component<
}
componentDidMount(): void {
const unblock = HistoryService.history.block(({ retry }) => {
console.log("mounted");
const unblock = HistoryService.history.block(tx => {
this.setState(prev => ({ ...prev, calls: prev.calls + 1 }));
if (!this.props.when || window.confirm(i18n.t("block_leaving"))) {
console.log("Not blocked");
console.log(this.state.calls);
unblock();
retry();
}
});
}
componentWillUnmount(): void {
console.log("unmounted");
}
render() {
return null;
}

View file

@ -1,18 +1,17 @@
import { Component, linkEvent } from "inferno";
import { Prompt } from "inferno-router";
import {
CommunityView,
CreateCommunity,
EditCommunity,
Language,
} from "lemmy-js-client";
import { Subscription } from "rxjs";
import { i18n } from "../../i18next";
import { capitalizeFirstLetter, myAuthRequired, randomStr } from "../../utils";
import { Icon, Spinner } from "../common/icon";
import { ImageUploadForm } from "../common/image-upload-form";
import { LanguageSelect } from "../common/language-select";
import { MarkdownTextArea } from "../common/markdown-textarea";
import NavigationPrompt from "../common/navigation-prompt";
interface CommunityFormProps {
community_view?: CommunityView; // If a community is given, that means this is an edit
@ -43,7 +42,6 @@ export class CommunityForm extends Component<
CommunityFormState
> {
private id = `community-form-${randomStr()}`;
private subscription?: Subscription;
state: CommunityFormState = {
form: {},
@ -84,75 +82,29 @@ export class CommunityForm extends Component<
}
}
componentDidUpdate() {
if (
!this.state.loading &&
(this.state.form.name ||
this.state.form.title ||
this.state.form.description)
) {
window.onbeforeunload = () => true;
} else {
window.onbeforeunload = null;
}
}
componentWillUnmount() {
this.subscription?.unsubscribe();
window.onbeforeunload = null;
}
render() {
return (
<>
<Prompt
<form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
<NavigationPrompt
when={
!this.state.loading &&
(this.state.form.name ||
!!(
this.state.form.name ||
this.state.form.title ||
this.state.form.description)
this.state.form.description
)
}
message={i18n.t("block_leaving")}
/>
<form onSubmit={linkEvent(this, this.handleCreateCommunitySubmit)}>
{!this.props.community_view && (
<div className="form-group row">
<label
className="col-12 col-sm-2 col-form-label"
htmlFor="community-name"
>
{i18n.t("name")}
<span
className="position-absolute pointer unselectable ml-2 text-muted"
data-tippy-content={i18n.t("name_explain")}
>
<Icon icon="help-circle" classes="icon-inline" />
</span>
</label>
<div className="col-12 col-sm-10">
<input
type="text"
id="community-name"
className="form-control"
value={this.state.form.name}
onInput={linkEvent(this, this.handleCommunityNameChange)}
required
minLength={3}
pattern="[a-z0-9_]+"
title={i18n.t("community_reqs")}
/>
</div>
</div>
)}
{!this.props.community_view && (
<div className="form-group row">
<label
className="col-12 col-sm-2 col-form-label"
htmlFor="community-title"
htmlFor="community-name"
>
{i18n.t("display_name")}
{i18n.t("name")}
<span
className="position-absolute pointer unselectable ml-2 text-muted"
data-tippy-content={i18n.t("display_name_explain")}
data-tippy-content={i18n.t("name_explain")}
>
<Icon icon="help-circle" classes="icon-inline" />
</span>
@ -160,127 +112,155 @@ export class CommunityForm extends Component<
<div className="col-12 col-sm-10">
<input
type="text"
id="community-title"
value={this.state.form.title}
onInput={linkEvent(this, this.handleCommunityTitleChange)}
id="community-name"
className="form-control"
value={this.state.form.name}
onInput={linkEvent(this, this.handleCommunityNameChange)}
required
minLength={3}
maxLength={100}
pattern="[a-z0-9_]+"
title={i18n.t("community_reqs")}
/>
</div>
</div>
<div className="form-group row">
<label className="col-12 col-sm-2">{i18n.t("icon")}</label>
<div className="col-12 col-sm-10">
<ImageUploadForm
uploadTitle={i18n.t("upload_icon")}
imageSrc={this.state.form.icon}
onUpload={this.handleIconUpload}
onRemove={this.handleIconRemove}
rounded
/>
</div>
)}
<div className="form-group row">
<label
className="col-12 col-sm-2 col-form-label"
htmlFor="community-title"
>
{i18n.t("display_name")}
<span
className="position-absolute pointer unselectable ml-2 text-muted"
data-tippy-content={i18n.t("display_name_explain")}
>
<Icon icon="help-circle" classes="icon-inline" />
</span>
</label>
<div className="col-12 col-sm-10">
<input
type="text"
id="community-title"
value={this.state.form.title}
onInput={linkEvent(this, this.handleCommunityTitleChange)}
className="form-control"
required
minLength={3}
maxLength={100}
/>
</div>
<div className="form-group row">
<label className="col-12 col-sm-2">{i18n.t("banner")}</label>
<div className="col-12 col-sm-10">
<ImageUploadForm
uploadTitle={i18n.t("upload_banner")}
imageSrc={this.state.form.banner}
onUpload={this.handleBannerUpload}
onRemove={this.handleBannerRemove}
/>
</div>
</div>
<div className="form-group row">
<label className="col-12 col-sm-2">{i18n.t("icon")}</label>
<div className="col-12 col-sm-10">
<ImageUploadForm
uploadTitle={i18n.t("upload_icon")}
imageSrc={this.state.form.icon}
onUpload={this.handleIconUpload}
onRemove={this.handleIconRemove}
rounded
/>
</div>
<div className="form-group row">
<label className="col-12 col-sm-2 col-form-label" htmlFor={this.id}>
{i18n.t("sidebar")}
</label>
<div className="col-12 col-sm-10">
<MarkdownTextArea
initialContent={this.state.form.description}
placeholder={i18n.t("description")}
onContentChange={this.handleCommunityDescriptionChange}
allLanguages={[]}
siteLanguages={[]}
/>
</div>
</div>
<div className="form-group row">
<label className="col-12 col-sm-2">{i18n.t("banner")}</label>
<div className="col-12 col-sm-10">
<ImageUploadForm
uploadTitle={i18n.t("upload_banner")}
imageSrc={this.state.form.banner}
onUpload={this.handleBannerUpload}
onRemove={this.handleBannerRemove}
/>
</div>
</div>
<div className="form-group row">
<label className="col-12 col-sm-2 col-form-label" htmlFor={this.id}>
{i18n.t("sidebar")}
</label>
<div className="col-12 col-sm-10">
<MarkdownTextArea
initialContent={this.state.form.description}
placeholder={i18n.t("description")}
onContentChange={this.handleCommunityDescriptionChange}
hideNavigationWarnings
allLanguages={[]}
siteLanguages={[]}
/>
</div>
</div>
{this.props.enableNsfw && (
<div className="form-group row">
<legend className="col-form-label col-sm-2 pt-0">
{i18n.t("nsfw")}
</legend>
<div className="col-10">
<div className="form-check">
<input
className="form-check-input position-static"
id="community-nsfw"
type="checkbox"
checked={this.state.form.nsfw}
onChange={linkEvent(this, this.handleCommunityNsfwChange)}
/>
</div>
</div>
</div>
)}
{this.props.enableNsfw && (
<div className="form-group row">
<legend className="col-form-label col-6 pt-0">
{i18n.t("only_mods_can_post_in_community")}
<legend className="col-form-label col-sm-2 pt-0">
{i18n.t("nsfw")}
</legend>
<div className="col-6">
<div className="col-10">
<div className="form-check">
<input
className="form-check-input position-static"
id="community-only-mods-can-post"
id="community-nsfw"
type="checkbox"
checked={this.state.form.posting_restricted_to_mods}
onChange={linkEvent(
this,
this.handleCommunityPostingRestrictedToMods
)}
checked={this.state.form.nsfw}
onChange={linkEvent(this, this.handleCommunityNsfwChange)}
/>
</div>
</div>
</div>
<LanguageSelect
allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages}
showSite
selectedLanguageIds={this.state.form.discussion_languages}
multiple={true}
onChange={this.handleDiscussionLanguageChange}
/>
<div className="form-group row">
<div className="col-12">
<button
type="submit"
className="btn btn-secondary mr-2"
disabled={this.state.loading}
>
{this.state.loading ? (
<Spinner />
) : this.props.community_view ? (
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t("create"))
)}
<div className="form-group row">
<legend className="col-form-label col-6 pt-0">
{i18n.t("only_mods_can_post_in_community")}
</legend>
<div className="col-6">
<div className="form-check">
<input
className="form-check-input position-static"
id="community-only-mods-can-post"
type="checkbox"
checked={this.state.form.posting_restricted_to_mods}
onChange={linkEvent(
this,
this.handleCommunityPostingRestrictedToMods
)}
</button>
{this.props.community_view && (
<button
type="button"
className="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
{i18n.t("cancel")}
</button>
)}
/>
</div>
</div>
</form>
</>
</div>
<LanguageSelect
allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages}
showSite
selectedLanguageIds={this.state.form.discussion_languages}
multiple={true}
onChange={this.handleDiscussionLanguageChange}
/>
<div className="form-group row">
<div className="col-12">
<button
type="submit"
className="btn btn-secondary mr-2"
disabled={this.state.loading}
>
{this.state.loading ? (
<Spinner />
) : this.props.community_view ? (
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t("create"))
)}
</button>
{this.props.community_view && (
<button
type="button"
className="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
{i18n.t("cancel")}
</button>
)}
</div>
</div>
</form>
);
}

View file

@ -4,7 +4,6 @@ import {
InfernoMouseEvent,
linkEvent,
} from "inferno";
import { Prompt } from "inferno-router";
import {
CreateSite,
EditSite,
@ -19,6 +18,7 @@ import { ImageUploadForm } from "../common/image-upload-form";
import { LanguageSelect } from "../common/language-select";
import { ListingTypeSelect } from "../common/listing-type-select";
import { MarkdownTextArea } from "../common/markdown-textarea";
import NavigationPrompt from "../common/navigation-prompt";
interface SiteFormProps {
blockedInstances?: Instance[];
@ -115,538 +115,510 @@ export class SiteForm extends Component<SiteFormProps, SiteFormState> {
this.setState({ loading: false });
}
componentDidUpdate() {
if (
!this.state.loading &&
!this.props.siteRes.site_view.local_site.site_setup &&
(this.state.siteForm.name ||
this.state.siteForm.sidebar ||
this.state.siteForm.application_question ||
this.state.siteForm.description)
) {
window.onbeforeunload = () => true;
} else {
window.onbeforeunload = null;
}
}
componentWillUnmount() {
window.onbeforeunload = null;
}
render() {
const siteSetup = this.props.siteRes.site_view.local_site.site_setup;
return (
<>
<Prompt
<form onSubmit={linkEvent(this, this.handleSaveSiteSubmit)}>
<NavigationPrompt
when={
!this.state.loading &&
!siteSetup &&
(this.state.siteForm.name ||
!!(
this.state.siteForm.name ||
this.state.siteForm.sidebar ||
this.state.siteForm.application_question ||
this.state.siteForm.description)
this.state.siteForm.description
)
}
message={i18n.t("block_leaving")}
/>
<form onSubmit={linkEvent(this, this.handleSaveSiteSubmit)}>
<h5>{`${
siteSetup
? capitalizeFirstLetter(i18n.t("save"))
: capitalizeFirstLetter(i18n.t("name"))
} ${i18n.t("your_site")}`}</h5>
<div className="form-group row">
<label className="col-12 col-form-label" htmlFor="create-site-name">
{i18n.t("name")}
</label>
<div className="col-12">
<input
type="text"
id="create-site-name"
className="form-control"
value={this.state.siteForm.name}
onInput={linkEvent(this, this.handleSiteNameChange)}
required
minLength={3}
maxLength={20}
/>
</div>
</div>
<div className="form-group">
<label>{i18n.t("icon")}</label>
<ImageUploadForm
uploadTitle={i18n.t("upload_icon")}
imageSrc={this.state.siteForm.icon}
onUpload={this.handleIconUpload}
onRemove={this.handleIconRemove}
rounded
<h5>{`${
siteSetup
? capitalizeFirstLetter(i18n.t("save"))
: capitalizeFirstLetter(i18n.t("name"))
} ${i18n.t("your_site")}`}</h5>
<div className="form-group row">
<label className="col-12 col-form-label" htmlFor="create-site-name">
{i18n.t("name")}
</label>
<div className="col-12">
<input
type="text"
id="create-site-name"
className="form-control"
value={this.state.siteForm.name}
onInput={linkEvent(this, this.handleSiteNameChange)}
required
minLength={3}
maxLength={20}
/>
</div>
<div className="form-group">
<label>{i18n.t("banner")}</label>
<ImageUploadForm
uploadTitle={i18n.t("upload_banner")}
imageSrc={this.state.siteForm.banner}
onUpload={this.handleBannerUpload}
onRemove={this.handleBannerRemove}
</div>
<div className="form-group">
<label>{i18n.t("icon")}</label>
<ImageUploadForm
uploadTitle={i18n.t("upload_icon")}
imageSrc={this.state.siteForm.icon}
onUpload={this.handleIconUpload}
onRemove={this.handleIconRemove}
rounded
/>
</div>
<div className="form-group">
<label>{i18n.t("banner")}</label>
<ImageUploadForm
uploadTitle={i18n.t("upload_banner")}
imageSrc={this.state.siteForm.banner}
onUpload={this.handleBannerUpload}
onRemove={this.handleBannerRemove}
/>
</div>
<div className="form-group row">
<label className="col-12 col-form-label" htmlFor="site-desc">
{i18n.t("description")}
</label>
<div className="col-12">
<input
type="text"
className="form-control"
id="site-desc"
value={this.state.siteForm.description}
onInput={linkEvent(this, this.handleSiteDescChange)}
maxLength={150}
/>
</div>
<div className="form-group row">
<label className="col-12 col-form-label" htmlFor="site-desc">
{i18n.t("description")}
</label>
<div className="col-12">
</div>
<div className="form-group row">
<label className="col-12 col-form-label">{i18n.t("sidebar")}</label>
<div className="col-12">
<MarkdownTextArea
initialContent={this.state.siteForm.sidebar}
onContentChange={this.handleSiteSidebarChange}
hideNavigationWarnings
allLanguages={[]}
siteLanguages={[]}
/>
</div>
</div>
<div className="form-group row">
<label className="col-12 col-form-label">
{i18n.t("legal_information")}
</label>
<div className="col-12">
<MarkdownTextArea
initialContent={this.state.siteForm.legal_information}
onContentChange={this.handleSiteLegalInfoChange}
hideNavigationWarnings
allLanguages={[]}
siteLanguages={[]}
/>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
type="text"
className="form-control"
id="site-desc"
value={this.state.siteForm.description}
onInput={linkEvent(this, this.handleSiteDescChange)}
maxLength={150}
className="form-check-input"
id="create-site-downvotes"
type="checkbox"
checked={this.state.siteForm.enable_downvotes}
onChange={linkEvent(this, this.handleSiteEnableDownvotesChange)}
/>
<label
className="form-check-label"
htmlFor="create-site-downvotes"
>
{i18n.t("enable_downvotes")}
</label>
</div>
</div>
<div className="form-group row">
<label className="col-12 col-form-label">{i18n.t("sidebar")}</label>
<div className="col-12">
<MarkdownTextArea
initialContent={this.state.siteForm.sidebar}
onContentChange={this.handleSiteSidebarChange}
hideNavigationWarnings
allLanguages={[]}
siteLanguages={[]}
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-enable-nsfw"
type="checkbox"
checked={this.state.siteForm.enable_nsfw}
onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
/>
<label
className="form-check-label"
htmlFor="create-site-enable-nsfw"
>
{i18n.t("enable_nsfw")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<label
className="form-check-label mr-2"
htmlFor="create-site-registration-mode"
>
{i18n.t("registration_mode")}
</label>
<select
id="create-site-registration-mode"
value={this.state.siteForm.registration_mode}
onChange={linkEvent(this, this.handleSiteRegistrationModeChange)}
className="custom-select w-auto"
>
<option value={"RequireApplication"}>
{i18n.t("require_registration_application")}
</option>
<option value={"Open"}>{i18n.t("open_registration")}</option>
<option value={"Closed"}>{i18n.t("close_registration")}</option>
</select>
</div>
</div>
{this.state.siteForm.registration_mode == "RequireApplication" && (
<div className="form-group row">
<label className="col-12 col-form-label">
{i18n.t("legal_information")}
{i18n.t("application_questionnaire")}
</label>
<div className="col-12">
<MarkdownTextArea
initialContent={this.state.siteForm.legal_information}
onContentChange={this.handleSiteLegalInfoChange}
initialContent={this.state.siteForm.application_question}
onContentChange={this.handleSiteApplicationQuestionChange}
hideNavigationWarnings
allLanguages={[]}
siteLanguages={[]}
/>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-downvotes"
type="checkbox"
checked={this.state.siteForm.enable_downvotes}
onChange={linkEvent(
this,
this.handleSiteEnableDownvotesChange
)}
/>
<label
className="form-check-label"
htmlFor="create-site-downvotes"
>
{i18n.t("enable_downvotes")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-enable-nsfw"
type="checkbox"
checked={this.state.siteForm.enable_nsfw}
onChange={linkEvent(this, this.handleSiteEnableNsfwChange)}
/>
<label
className="form-check-label"
htmlFor="create-site-enable-nsfw"
>
{i18n.t("enable_nsfw")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<label
className="form-check-label mr-2"
htmlFor="create-site-registration-mode"
>
{i18n.t("registration_mode")}
</label>
<select
id="create-site-registration-mode"
value={this.state.siteForm.registration_mode}
)}
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-community-creation-admin-only"
type="checkbox"
checked={this.state.siteForm.community_creation_admin_only}
onChange={linkEvent(
this,
this.handleSiteRegistrationModeChange
this.handleSiteCommunityCreationAdminOnly
)}
className="custom-select w-auto"
/>
<label
className="form-check-label"
htmlFor="create-site-community-creation-admin-only"
>
<option value={"RequireApplication"}>
{i18n.t("require_registration_application")}
</option>
<option value={"Open"}>{i18n.t("open_registration")}</option>
<option value={"Closed"}>{i18n.t("close_registration")}</option>
</select>
{i18n.t("community_creation_admin_only")}
</label>
</div>
</div>
{this.state.siteForm.registration_mode == "RequireApplication" && (
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-require-email-verification"
type="checkbox"
checked={this.state.siteForm.require_email_verification}
onChange={linkEvent(
this,
this.handleSiteRequireEmailVerification
)}
/>
<label
className="form-check-label"
htmlFor="create-site-require-email-verification"
>
{i18n.t("require_email_verification")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-application-email-admins"
type="checkbox"
checked={this.state.siteForm.application_email_admins}
onChange={linkEvent(
this,
this.handleSiteApplicationEmailAdmins
)}
/>
<label
className="form-check-label"
htmlFor="create-site-email-admins"
>
{i18n.t("application_email_admins")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-reports-email-admins"
type="checkbox"
checked={this.state.siteForm.reports_email_admins}
onChange={linkEvent(this, this.handleSiteReportsEmailAdmins)}
/>
<label
className="form-check-label"
htmlFor="create-site-reports-email-admins"
>
{i18n.t("reports_email_admins")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<label
className="form-check-label mr-2"
htmlFor="create-site-default-theme"
>
{i18n.t("theme")}
</label>
<select
id="create-site-default-theme"
value={this.state.siteForm.default_theme}
onChange={linkEvent(this, this.handleSiteDefaultTheme)}
className="custom-select w-auto"
>
<option value="browser">{i18n.t("browser_default")}</option>
{this.props.themeList?.map(theme => (
<option key={theme} value={theme}>
{theme}
</option>
))}
</select>
</div>
</div>
{this.props.showLocal && (
<form className="form-group row">
<label className="col-sm-3">{i18n.t("listing_type")}</label>
<div className="col-sm-9">
<ListingTypeSelect
type_={this.state.siteForm.default_post_listing_type ?? "Local"}
showLocal
showSubscribed={false}
onChange={this.handleDefaultPostListingTypeChange}
/>
</div>
</form>
)}
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-private-instance"
type="checkbox"
checked={this.state.siteForm.private_instance}
onChange={linkEvent(this, this.handleSitePrivateInstance)}
/>
<label
className="form-check-label"
htmlFor="create-site-private-instance"
>
{i18n.t("private_instance")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-hide-modlog-mod-names"
type="checkbox"
checked={this.state.siteForm.hide_modlog_mod_names}
onChange={linkEvent(this, this.handleSiteHideModlogModNames)}
/>
<label
className="form-check-label"
htmlFor="create-site-hide-modlog-mod-names"
>
{i18n.t("hide_modlog_mod_names")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<label
className="col-12 col-form-label"
htmlFor="create-site-slur-filter-regex"
>
{i18n.t("slur_filter_regex")}
</label>
<div className="col-12">
<input
type="text"
id="create-site-slur-filter-regex"
placeholder="(word1|word2)"
className="form-control"
value={this.state.siteForm.slur_filter_regex}
onInput={linkEvent(this, this.handleSiteSlurFilterRegex)}
minLength={3}
/>
</div>
</div>
<LanguageSelect
allLanguages={this.props.siteRes.all_languages}
siteLanguages={this.props.siteRes.discussion_languages}
selectedLanguageIds={this.state.siteForm.discussion_languages}
multiple={true}
onChange={this.handleDiscussionLanguageChange}
showAll
/>
<div className="form-group row">
<label
className="col-12 col-form-label"
htmlFor="create-site-actor-name"
>
{i18n.t("actor_name_max_length")}
</label>
<div className="col-12">
<input
type="number"
id="create-site-actor-name"
className="form-control"
min={5}
value={this.state.siteForm.actor_name_max_length}
onInput={linkEvent(this, this.handleSiteActorNameMaxLength)}
/>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-federation-enabled"
type="checkbox"
checked={this.state.siteForm.federation_enabled}
onChange={linkEvent(this, this.handleSiteFederationEnabled)}
/>
<label
className="form-check-label"
htmlFor="create-site-federation-enabled"
>
{i18n.t("federation_enabled")}
</label>
</div>
</div>
</div>
{this.state.siteForm.federation_enabled && (
<>
<div className="form-group row">
<label className="col-12 col-form-label">
{i18n.t("application_questionnaire")}
{this.federatedInstanceSelect("allowed_instances")}
{this.federatedInstanceSelect("blocked_instances")}
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-federation-debug"
type="checkbox"
checked={this.state.siteForm.federation_debug}
onChange={linkEvent(this, this.handleSiteFederationDebug)}
/>
<label
className="form-check-label"
htmlFor="create-site-federation-debug"
>
{i18n.t("federation_debug")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<label
className="col-12 col-form-label"
htmlFor="create-site-federation-worker-count"
>
{i18n.t("federation_worker_count")}
</label>
<div className="col-12">
<MarkdownTextArea
initialContent={this.state.siteForm.application_question}
onContentChange={this.handleSiteApplicationQuestionChange}
hideNavigationWarnings
allLanguages={[]}
siteLanguages={[]}
/>
</div>
</div>
)}
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-community-creation-admin-only"
type="checkbox"
checked={this.state.siteForm.community_creation_admin_only}
onChange={linkEvent(
type="number"
id="create-site-federation-worker-count"
className="form-control"
min={0}
value={this.state.siteForm.federation_worker_count}
onInput={linkEvent(
this,
this.handleSiteCommunityCreationAdminOnly
this.handleSiteFederationWorkerCount
)}
/>
<label
className="form-check-label"
htmlFor="create-site-community-creation-admin-only"
>
{i18n.t("community_creation_admin_only")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-require-email-verification"
type="checkbox"
checked={this.state.siteForm.require_email_verification}
onChange={linkEvent(
this,
this.handleSiteRequireEmailVerification
)}
/>
<label
className="form-check-label"
htmlFor="create-site-require-email-verification"
>
{i18n.t("require_email_verification")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-application-email-admins"
type="checkbox"
checked={this.state.siteForm.application_email_admins}
onChange={linkEvent(
this,
this.handleSiteApplicationEmailAdmins
)}
/>
<label
className="form-check-label"
htmlFor="create-site-email-admins"
>
{i18n.t("application_email_admins")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-reports-email-admins"
type="checkbox"
checked={this.state.siteForm.reports_email_admins}
onChange={linkEvent(this, this.handleSiteReportsEmailAdmins)}
/>
<label
className="form-check-label"
htmlFor="create-site-reports-email-admins"
>
{i18n.t("reports_email_admins")}
</label>
</div>
</>
)}
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-captcha-enabled"
type="checkbox"
checked={this.state.siteForm.captcha_enabled}
onChange={linkEvent(this, this.handleSiteCaptchaEnabled)}
/>
<label
className="form-check-label"
htmlFor="create-site-captcha-enabled"
>
{i18n.t("captcha_enabled")}
</label>
</div>
</div>
</div>
{this.state.siteForm.captcha_enabled && (
<div className="form-group row">
<div className="col-12">
<label
className="form-check-label mr-2"
htmlFor="create-site-default-theme"
htmlFor="create-site-captcha-difficulty"
>
{i18n.t("theme")}
{i18n.t("captcha_difficulty")}
</label>
<select
id="create-site-default-theme"
value={this.state.siteForm.default_theme}
onChange={linkEvent(this, this.handleSiteDefaultTheme)}
id="create-site-captcha-difficulty"
value={this.state.siteForm.captcha_difficulty}
onChange={linkEvent(this, this.handleSiteCaptchaDifficulty)}
className="custom-select w-auto"
>
<option value="browser">{i18n.t("browser_default")}</option>
{this.props.themeList?.map(theme => (
<option key={theme} value={theme}>
{theme}
</option>
))}
<option value="easy">{i18n.t("easy")}</option>
<option value="medium">{i18n.t("medium")}</option>
<option value="hard">{i18n.t("hard")}</option>
</select>
</div>
</div>
{this.props.showLocal && (
<form className="form-group row">
<label className="col-sm-3">{i18n.t("listing_type")}</label>
<div className="col-sm-9">
<ListingTypeSelect
type_={
this.state.siteForm.default_post_listing_type ?? "Local"
}
showLocal
showSubscribed={false}
onChange={this.handleDefaultPostListingTypeChange}
/>
</div>
</form>
)}
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-private-instance"
type="checkbox"
checked={this.state.siteForm.private_instance}
onChange={linkEvent(this, this.handleSitePrivateInstance)}
/>
<label
className="form-check-label"
htmlFor="create-site-private-instance"
>
{i18n.t("private_instance")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-hide-modlog-mod-names"
type="checkbox"
checked={this.state.siteForm.hide_modlog_mod_names}
onChange={linkEvent(this, this.handleSiteHideModlogModNames)}
/>
<label
className="form-check-label"
htmlFor="create-site-hide-modlog-mod-names"
>
{i18n.t("hide_modlog_mod_names")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<label
className="col-12 col-form-label"
htmlFor="create-site-slur-filter-regex"
)}
<div className="form-group row">
<div className="col-12">
<button
type="submit"
className="btn btn-secondary mr-2"
disabled={this.state.loading}
>
{i18n.t("slur_filter_regex")}
</label>
<div className="col-12">
<input
type="text"
id="create-site-slur-filter-regex"
placeholder="(word1|word2)"
className="form-control"
value={this.state.siteForm.slur_filter_regex}
onInput={linkEvent(this, this.handleSiteSlurFilterRegex)}
minLength={3}
/>
</div>
{this.state.loading ? (
<Spinner />
) : siteSetup ? (
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t("create"))
)}
</button>
</div>
<LanguageSelect
allLanguages={this.props.siteRes.all_languages}
siteLanguages={this.props.siteRes.discussion_languages}
selectedLanguageIds={this.state.siteForm.discussion_languages}
multiple={true}
onChange={this.handleDiscussionLanguageChange}
showAll
/>
<div className="form-group row">
<label
className="col-12 col-form-label"
htmlFor="create-site-actor-name"
>
{i18n.t("actor_name_max_length")}
</label>
<div className="col-12">
<input
type="number"
id="create-site-actor-name"
className="form-control"
min={5}
value={this.state.siteForm.actor_name_max_length}
onInput={linkEvent(this, this.handleSiteActorNameMaxLength)}
/>
</div>
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-federation-enabled"
type="checkbox"
checked={this.state.siteForm.federation_enabled}
onChange={linkEvent(this, this.handleSiteFederationEnabled)}
/>
<label
className="form-check-label"
htmlFor="create-site-federation-enabled"
>
{i18n.t("federation_enabled")}
</label>
</div>
</div>
</div>
{this.state.siteForm.federation_enabled && (
<>
<div className="form-group row">
{this.federatedInstanceSelect("allowed_instances")}
{this.federatedInstanceSelect("blocked_instances")}
</div>
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-federation-debug"
type="checkbox"
checked={this.state.siteForm.federation_debug}
onChange={linkEvent(this, this.handleSiteFederationDebug)}
/>
<label
className="form-check-label"
htmlFor="create-site-federation-debug"
>
{i18n.t("federation_debug")}
</label>
</div>
</div>
</div>
<div className="form-group row">
<label
className="col-12 col-form-label"
htmlFor="create-site-federation-worker-count"
>
{i18n.t("federation_worker_count")}
</label>
<div className="col-12">
<input
type="number"
id="create-site-federation-worker-count"
className="form-control"
min={0}
value={this.state.siteForm.federation_worker_count}
onInput={linkEvent(
this,
this.handleSiteFederationWorkerCount
)}
/>
</div>
</div>
</>
)}
<div className="form-group row">
<div className="col-12">
<div className="form-check">
<input
className="form-check-input"
id="create-site-captcha-enabled"
type="checkbox"
checked={this.state.siteForm.captcha_enabled}
onChange={linkEvent(this, this.handleSiteCaptchaEnabled)}
/>
<label
className="form-check-label"
htmlFor="create-site-captcha-enabled"
>
{i18n.t("captcha_enabled")}
</label>
</div>
</div>
</div>
{this.state.siteForm.captcha_enabled && (
<div className="form-group row">
<div className="col-12">
<label
className="form-check-label mr-2"
htmlFor="create-site-captcha-difficulty"
>
{i18n.t("captcha_difficulty")}
</label>
<select
id="create-site-captcha-difficulty"
value={this.state.siteForm.captcha_difficulty}
onChange={linkEvent(this, this.handleSiteCaptchaDifficulty)}
className="custom-select w-auto"
>
<option value="easy">{i18n.t("easy")}</option>
<option value="medium">{i18n.t("medium")}</option>
<option value="hard">{i18n.t("hard")}</option>
</select>
</div>
</div>
)}
<div className="form-group row">
<div className="col-12">
<button
type="submit"
className="btn btn-secondary mr-2"
disabled={this.state.loading}
>
{this.state.loading ? (
<Spinner />
) : siteSetup ? (
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t("create"))
)}
</button>
</div>
</div>
</form>
</>
</div>
</form>
);
}

View file

@ -36,6 +36,7 @@ import {
import { Icon, Spinner } from "../common/icon";
import { LanguageSelect } from "../common/language-select";
import { MarkdownTextArea } from "../common/markdown-textarea";
import NavigationPrompt from "../common/navigation-prompt";
import { SearchableSelect } from "../common/searchable-select";
import { PostListings } from "./post-listings";
@ -166,245 +167,240 @@ export class PostForm extends Component<PostFormProps, PostFormState> {
const url = this.state.form.url;
return (
<div>
{/* <Prompt
<form onSubmit={linkEvent(this, this.handlePostSubmit)}>
<NavigationPrompt
when={
!(
!!(
this.state.form.name ||
this.state.form.url ||
this.state.form.body
)
}
message={i18n.t("block_leaving")}
/> */}
<form onSubmit={linkEvent(this, this.handlePostSubmit)}>
<div className="form-group row">
<label className="col-sm-2 col-form-label" htmlFor="post-url">
{i18n.t("url")}
</label>
<div className="col-sm-10">
<input
type="url"
id="post-url"
className="form-control"
value={this.state.form.url}
onInput={linkEvent(this, this.handlePostUrlChange)}
onPaste={linkEvent(this, this.handleImageUploadPaste)}
/>
{this.renderSuggestedTitleCopy()}
<form>
<label
htmlFor="file-upload"
className={`${
UserService.Instance.myUserInfo && "pointer"
} d-inline-block float-right text-muted font-weight-bold`}
data-tippy-content={i18n.t("upload_image")}
>
<Icon icon="image" classes="icon-inline" />
</label>
<input
id="file-upload"
type="file"
accept="image/*,video/*"
name="file"
className="d-none"
disabled={!UserService.Instance.myUserInfo}
onChange={linkEvent(this, this.handleImageUpload)}
/>
</form>
{url && validURL(url) && (
<div>
<a
href={`${webArchiveUrl}/save/${encodeURIComponent(url)}`}
className="mr-2 d-inline-block float-right text-muted small font-weight-bold"
rel={relTags}
>
archive.org {i18n.t("archive_link")}
</a>
<a
href={`${ghostArchiveUrl}/search?term=${encodeURIComponent(
url
)}`}
className="mr-2 d-inline-block float-right text-muted small font-weight-bold"
rel={relTags}
>
ghostarchive.org {i18n.t("archive_link")}
</a>
<a
href={`${archiveTodayUrl}/?run=1&url=${encodeURIComponent(
url
)}`}
className="mr-2 d-inline-block float-right text-muted small font-weight-bold"
rel={relTags}
>
archive.today {i18n.t("archive_link")}
</a>
</div>
)}
{this.state.imageLoading && <Spinner />}
{url && isImage(url) && (
<img src={url} className="img-fluid" alt="" />
)}
{this.props.crossPosts && this.props.crossPosts.length > 0 && (
<>
<div className="my-1 text-muted small font-weight-bold">
{i18n.t("cross_posts")}
</div>
<PostListings
showCommunity
posts={this.props.crossPosts}
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages}
viewOnly
// All of these are unused, since its view only
onPostVote={() => {}}
onPostReport={() => {}}
onBlockPerson={() => {}}
onLockPost={() => {}}
onDeletePost={() => {}}
onRemovePost={() => {}}
onSavePost={() => {}}
onFeaturePost={() => {}}
onPurgePerson={() => {}}
onPurgePost={() => {}}
onBanPersonFromCommunity={() => {}}
onBanPerson={() => {}}
onAddModToCommunity={() => {}}
onAddAdmin={() => {}}
onTransferCommunity={() => {}}
/>
</>
)}
</div>
</div>
<div className="form-group row">
<label className="col-sm-2 col-form-label" htmlFor="post-title">
{i18n.t("title")}
</label>
<div className="col-sm-10">
<textarea
value={this.state.form.name}
id="post-title"
onInput={linkEvent(this, this.handlePostNameChange)}
className={`form-control ${
!validTitle(this.state.form.name) && "is-invalid"
}`}
required
rows={1}
minLength={3}
maxLength={MAX_POST_TITLE_LENGTH}
/>
{!validTitle(this.state.form.name) && (
<div className="invalid-feedback">
{i18n.t("invalid_post_title")}
</div>
)}
{this.renderSuggestedPosts()}
</div>
</div>
<div className="form-group row">
<label className="col-sm-2 col-form-label">{i18n.t("body")}</label>
<div className="col-sm-10">
<MarkdownTextArea
initialContent={this.state.form.body}
onContentChange={this.handlePostBodyChange}
allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages}
/>
</div>
</div>
{!this.props.post_view && (
<div className="form-group row">
/>
<div className="form-group row">
<label className="col-sm-2 col-form-label" htmlFor="post-url">
{i18n.t("url")}
</label>
<div className="col-sm-10">
<input
type="url"
id="post-url"
className="form-control"
value={this.state.form.url}
onInput={linkEvent(this, this.handlePostUrlChange)}
onPaste={linkEvent(this, this.handleImageUploadPaste)}
/>
{this.renderSuggestedTitleCopy()}
<form>
<label
className="col-sm-2 col-form-label"
htmlFor="post-community"
htmlFor="file-upload"
className={`${
UserService.Instance.myUserInfo && "pointer"
} d-inline-block float-right text-muted font-weight-bold`}
data-tippy-content={i18n.t("upload_image")}
>
{i18n.t("community")}
<Icon icon="image" classes="icon-inline" />
</label>
<div className="col-sm-10">
<SearchableSelect
id="post-community"
value={this.state.form.community_id}
options={[
{
label: i18n.t("select_a_community"),
value: "",
disabled: true,
} as Choice,
].concat(this.state.communitySearchOptions)}
loading={this.state.communitySearchLoading}
onChange={this.handleCommunitySelect}
onSearch={this.handleCommunitySearch}
<input
id="file-upload"
type="file"
accept="image/*,video/*"
name="file"
className="d-none"
disabled={!UserService.Instance.myUserInfo}
onChange={linkEvent(this, this.handleImageUpload)}
/>
</form>
{url && validURL(url) && (
<div>
<a
href={`${webArchiveUrl}/save/${encodeURIComponent(url)}`}
className="mr-2 d-inline-block float-right text-muted small font-weight-bold"
rel={relTags}
>
archive.org {i18n.t("archive_link")}
</a>
<a
href={`${ghostArchiveUrl}/search?term=${encodeURIComponent(
url
)}`}
className="mr-2 d-inline-block float-right text-muted small font-weight-bold"
rel={relTags}
>
ghostarchive.org {i18n.t("archive_link")}
</a>
<a
href={`${archiveTodayUrl}/?run=1&url=${encodeURIComponent(
url
)}`}
className="mr-2 d-inline-block float-right text-muted small font-weight-bold"
rel={relTags}
>
archive.today {i18n.t("archive_link")}
</a>
</div>
)}
{this.state.imageLoading && <Spinner />}
{url && isImage(url) && (
<img src={url} className="img-fluid" alt="" />
)}
{this.props.crossPosts && this.props.crossPosts.length > 0 && (
<>
<div className="my-1 text-muted small font-weight-bold">
{i18n.t("cross_posts")}
</div>
<PostListings
showCommunity
posts={this.props.crossPosts}
enableDownvotes={this.props.enableDownvotes}
enableNsfw={this.props.enableNsfw}
allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages}
viewOnly
// All of these are unused, since its view only
onPostVote={() => {}}
onPostReport={() => {}}
onBlockPerson={() => {}}
onLockPost={() => {}}
onDeletePost={() => {}}
onRemovePost={() => {}}
onSavePost={() => {}}
onFeaturePost={() => {}}
onPurgePerson={() => {}}
onPurgePost={() => {}}
onBanPersonFromCommunity={() => {}}
onBanPerson={() => {}}
onAddModToCommunity={() => {}}
onAddAdmin={() => {}}
onTransferCommunity={() => {}}
/>
</>
)}
</div>
</div>
<div className="form-group row">
<label className="col-sm-2 col-form-label" htmlFor="post-title">
{i18n.t("title")}
</label>
<div className="col-sm-10">
<textarea
value={this.state.form.name}
id="post-title"
onInput={linkEvent(this, this.handlePostNameChange)}
className={`form-control ${
!validTitle(this.state.form.name) && "is-invalid"
}`}
required
rows={1}
minLength={3}
maxLength={MAX_POST_TITLE_LENGTH}
/>
{!validTitle(this.state.form.name) && (
<div className="invalid-feedback">
{i18n.t("invalid_post_title")}
</div>
)}
{this.renderSuggestedPosts()}
</div>
</div>
<div className="form-group row">
<label className="col-sm-2 col-form-label">{i18n.t("body")}</label>
<div className="col-sm-10">
<MarkdownTextArea
initialContent={this.state.form.body}
onContentChange={this.handlePostBodyChange}
allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages}
hideNavigationWarnings
/>
</div>
</div>
{!this.props.post_view && (
<div className="form-group row">
<label className="col-sm-2 col-form-label" htmlFor="post-community">
{i18n.t("community")}
</label>
<div className="col-sm-10">
<SearchableSelect
id="post-community"
value={this.state.form.community_id}
options={[
{
label: i18n.t("select_a_community"),
value: "",
disabled: true,
} as Choice,
].concat(this.state.communitySearchOptions)}
loading={this.state.communitySearchLoading}
onChange={this.handleCommunitySelect}
onSearch={this.handleCommunitySearch}
/>
</div>
</div>
)}
{this.props.enableNsfw && (
<div className="form-group row">
<legend className="col-form-label col-sm-2 pt-0">
{i18n.t("nsfw")}
</legend>
<div className="col-sm-10">
<div className="form-check">
<input
className="form-check-input position-static"
id="post-nsfw"
type="checkbox"
checked={this.state.form.nsfw}
onChange={linkEvent(this, this.handlePostNsfwChange)}
/>
</div>
</div>
)}
{this.props.enableNsfw && (
<div className="form-group row">
<legend className="col-form-label col-sm-2 pt-0">
{i18n.t("nsfw")}
</legend>
<div className="col-sm-10">
<div className="form-check">
<input
className="form-check-input position-static"
id="post-nsfw"
type="checkbox"
checked={this.state.form.nsfw}
onChange={linkEvent(this, this.handlePostNsfwChange)}
/>
</div>
</div>
</div>
)}
<LanguageSelect
allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages}
selectedLanguageIds={selectedLangs}
multiple={false}
onChange={this.handleLanguageChange}
/>
<input
tabIndex={-1}
autoComplete="false"
name="a_password"
type="text"
className="form-control honeypot"
id="register-honey"
value={this.state.form.honeypot}
onInput={linkEvent(this, this.handleHoneyPotChange)}
/>
<div className="form-group row">
<div className="col-sm-10">
<button
disabled={!this.state.form.community_id || this.state.loading}
type="submit"
className="btn btn-secondary mr-2"
>
{this.state.loading ? (
<Spinner />
) : this.props.post_view ? (
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t("create"))
)}
</button>
{this.props.post_view && (
<button
type="button"
className="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
{i18n.t("cancel")}
</button>
)}
</div>
</div>
</form>
</div>
)}
<LanguageSelect
allLanguages={this.props.allLanguages}
siteLanguages={this.props.siteLanguages}
selectedLanguageIds={selectedLangs}
multiple={false}
onChange={this.handleLanguageChange}
/>
<input
tabIndex={-1}
autoComplete="false"
name="a_password"
type="text"
className="form-control honeypot"
id="register-honey"
value={this.state.form.honeypot}
onInput={linkEvent(this, this.handleHoneyPotChange)}
/>
<div className="form-group row">
<div className="col-sm-10">
<button
disabled={!this.state.form.community_id || this.state.loading}
type="submit"
className="btn btn-secondary mr-2"
>
{this.state.loading ? (
<Spinner />
) : this.props.post_view ? (
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t("create"))
)}
</button>
{this.props.post_view && (
<button
type="button"
className="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
{i18n.t("cancel")}
</button>
)}
</div>
</div>
</form>
);
}

View file

@ -1,6 +1,5 @@
import { Component, InfernoNode, linkEvent } from "inferno";
import { T } from "inferno-i18next-dess";
import { Prompt } from "inferno-router";
import {
CreatePrivateMessage,
EditPrivateMessage,
@ -16,6 +15,7 @@ import {
} from "../../utils";
import { Icon, Spinner } from "../common/icon";
import { MarkdownTextArea } from "../common/markdown-textarea";
import NavigationPrompt from "../common/navigation-prompt";
import { PersonListing } from "../person/person-listing";
interface PrivateMessageFormProps {
@ -66,94 +66,90 @@ export class PrivateMessageForm extends Component<
render() {
return (
<div>
<Prompt
when={!this.state.loading && this.state.content}
message={i18n.t("block_leaving")}
/>
<form onSubmit={linkEvent(this, this.handlePrivateMessageSubmit)}>
{!this.props.privateMessageView && (
<div className="form-group row">
<label className="col-sm-2 col-form-label">
{capitalizeFirstLetter(i18n.t("to"))}
</label>
<div className="col-sm-10 form-control-plaintext">
<PersonListing person={this.props.recipient} />
</div>
</div>
)}
<form onSubmit={linkEvent(this, this.handlePrivateMessageSubmit)}>
<NavigationPrompt when={!this.state.loading && !!this.state.content} />
{!this.props.privateMessageView && (
<div className="form-group row">
<label className="col-sm-2 col-form-label">
{i18n.t("message")}
<button
className="btn btn-link text-warning d-inline-block"
onClick={linkEvent(this, this.handleShowDisclaimer)}
data-tippy-content={i18n.t("private_message_disclaimer")}
aria-label={i18n.t("private_message_disclaimer")}
>
<Icon icon="alert-triangle" classes="icon-inline" />
</button>
{capitalizeFirstLetter(i18n.t("to"))}
</label>
<div className="col-sm-10">
<MarkdownTextArea
initialContent={this.state.content}
onContentChange={this.handleContentChange}
allLanguages={[]}
siteLanguages={[]}
/>
<div className="col-sm-10 form-control-plaintext">
<PersonListing person={this.props.recipient} />
</div>
</div>
)}
<div className="form-group row">
<label className="col-sm-2 col-form-label">
{i18n.t("message")}
<button
className="btn btn-link text-warning d-inline-block"
onClick={linkEvent(this, this.handleShowDisclaimer)}
data-tippy-content={i18n.t("private_message_disclaimer")}
aria-label={i18n.t("private_message_disclaimer")}
>
<Icon icon="alert-triangle" classes="icon-inline" />
</button>
</label>
<div className="col-sm-10">
<MarkdownTextArea
initialContent={this.state.content}
onContentChange={this.handleContentChange}
allLanguages={[]}
siteLanguages={[]}
hideNavigationWarnings
/>
</div>
</div>
{this.state.showDisclaimer && (
<div className="form-group row">
<div className="offset-sm-2 col-sm-10">
<div className="alert alert-danger" role="alert">
<T i18nKey="private_message_disclaimer">
#
<a
className="alert-link"
rel={relTags}
href="https://element.io/get-started"
>
#
</a>
</T>
</div>
</div>
</div>
)}
{this.state.showDisclaimer && (
<div className="form-group row">
<div className="offset-sm-2 col-sm-10">
<button
type="submit"
className="btn btn-secondary mr-2"
disabled={this.state.loading}
>
{this.state.loading ? (
<Spinner />
) : this.props.privateMessageView ? (
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t("send_message"))
)}
</button>
{this.props.privateMessageView && (
<button
type="button"
className="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
{i18n.t("cancel")}
</button>
)}
<ul className="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
<li className="list-inline-item"></li>
</ul>
<div className="alert alert-danger" role="alert">
<T i18nKey="private_message_disclaimer">
#
<a
className="alert-link"
rel={relTags}
href="https://element.io/get-started"
>
#
</a>
</T>
</div>
</div>
</div>
</form>
</div>
)}
<div className="form-group row">
<div className="offset-sm-2 col-sm-10">
<button
type="submit"
className="btn btn-secondary mr-2"
disabled={this.state.loading}
>
{this.state.loading ? (
<Spinner />
) : this.props.privateMessageView ? (
capitalizeFirstLetter(i18n.t("save"))
) : (
capitalizeFirstLetter(i18n.t("send_message"))
)}
</button>
{this.props.privateMessageView && (
<button
type="button"
className="btn btn-secondary"
onClick={linkEvent(this, this.handleCancel)}
>
{i18n.t("cancel")}
</button>
)}
<ul className="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
<li className="list-inline-item"></li>
</ul>
</div>
</div>
</form>
);
}