import ProgressBar from "./progress-bar";
interface MarkdownTextAreaProps {
+ /**
+ * Initial content inside the textarea
+ */
initialContent?: string;
+ /**
+ * Numerical ID of the language to select in dropdown
+ */
initialLanguageId?: number;
placeholder?: string;
buttonTitle?: string;
maxLength?: number;
+ /**
+ * Whether this form is for a reply to a Private Message.
+ * If true, a "Cancel" button is shown that will close the reply.
+ */
replyType?: boolean;
focus?: boolean;
disabled?: boolean;
finished?: boolean;
+ /**
+ * Whether to show the language selector
+ */
showLanguage?: boolean;
hideNavigationWarnings?: boolean;
onContentChange?(val: string): void;
{/* A flex expander */}
<div className="flex-grow-1"></div>
- {this.props.buttonTitle && (
- <button
- type="submit"
- className="btn btn-sm btn-secondary ms-2"
- disabled={this.isDisabled}
- >
- {this.state.loading ? (
- <Spinner />
- ) : (
- <span>{this.props.buttonTitle}</span>
- )}
- </button>
- )}
{this.props.replyType && (
<button
type="button"
{I18NextService.i18n.t("cancel")}
</button>
)}
- {this.state.content && (
+ <button
+ type="button"
+ disabled={!this.state.content}
+ className={classNames("btn btn-sm btn-secondary ms-2", {
+ active: this.state.previewMode,
+ })}
+ onClick={linkEvent(this, this.handlePreviewToggle)}
+ >
+ {this.state.previewMode
+ ? I18NextService.i18n.t("edit")
+ : I18NextService.i18n.t("preview")}
+ </button>
+ {this.props.buttonTitle && (
<button
- className={`btn btn-sm btn-secondary ms-2 ${
- this.state.previewMode && "active"
- }`}
- onClick={linkEvent(this, this.handlePreviewToggle)}
+ type="submit"
+ className="btn btn-sm btn-secondary ms-2"
+ disabled={this.isDisabled || !this.state.content}
>
- {this.state.previewMode
- ? I18NextService.i18n.t("edit")
- : I18NextService.i18n.t("preview")}
+ {this.state.loading && <Spinner className="me-1" />}
+ {this.props.buttonTitle}
</button>
)}
</div>
import { myAuthRequired } from "@utils/app";
import { capitalizeFirstLetter } from "@utils/helpers";
-import { Component, InfernoNode, linkEvent } from "inferno";
+import { Component, InfernoNode } from "inferno";
import { T } from "inferno-i18next-dess";
import {
CreatePrivateMessage,
import { relTags } from "../../config";
import { I18NextService } from "../../services";
import { setupTippy } from "../../tippy";
-import { Icon, Spinner } from "../common/icon";
+import { Icon } from "../common/icon";
import { MarkdownTextArea } from "../common/markdown-textarea";
import NavigationPrompt from "../common/navigation-prompt";
import { PersonListing } from "../person/person-listing";
interface PrivateMessageFormProps {
recipient: Person;
privateMessageView?: PrivateMessageView; // If a pm is given, that means this is an edit
+ replyType?: boolean;
onCancel?(): any;
onCreate?(form: CreatePrivateMessage): void;
onEdit?(form: EditPrivateMessage): void;
content?: string;
loading: boolean;
previewMode: boolean;
- showDisclaimer: boolean;
submitted: boolean;
}
state: PrivateMessageFormState = {
loading: false,
previewMode: false,
- showDisclaimer: false,
content: this.props.privateMessageView
? this.props.privateMessageView.private_message.content
: undefined,
render() {
return (
- <form
- className="private-message-form"
- onSubmit={linkEvent(this, this.handlePrivateMessageSubmit)}
- >
+ <form className="private-message-form">
<NavigationPrompt
when={
!this.state.loading && !!this.state.content && !this.state.submitted
}
/>
{!this.props.privateMessageView && (
- <div className="mb-3 row">
+ <div className="mb-3 row align-items-baseline">
<label className="col-sm-2 col-form-label">
{capitalizeFirstLetter(I18NextService.i18n.t("to"))}
</label>
- <div className="col-sm-10 form-control-plaintext">
+ <div className="col-sm-10">
<PersonListing person={this.props.recipient} />
</div>
</div>
)}
+ <div className="alert alert-warning small">
+ <Icon icon="alert-triangle" classes="icon-inline me-1" />
+ <T parent="span" i18nKey="private_message_disclaimer">
+ #
+ <a
+ className="alert-link"
+ rel={relTags}
+ href="https://element.io/get-started"
+ >
+ #
+ </a>
+ </T>
+ </div>
<div className="mb-3 row">
<label className="col-sm-2 col-form-label">
{I18NextService.i18n.t("message")}
- <button
- className="btn btn-link text-warning d-inline-block"
- onClick={linkEvent(this, this.handleShowDisclaimer)}
- data-tippy-content={I18NextService.i18n.t(
- "private_message_disclaimer"
- )}
- aria-label={I18NextService.i18n.t("private_message_disclaimer")}
- >
- <Icon icon="alert-triangle" classes="icon-inline" />
- </button>
</label>
<div className="col-sm-10">
<MarkdownTextArea
+ onSubmit={() => {
+ this.handlePrivateMessageSubmit(this, event);
+ }}
initialContent={this.state.content}
onContentChange={this.handleContentChange}
allLanguages={[]}
siteLanguages={[]}
hideNavigationWarnings
+ onReplyCancel={() => this.handleCancel(this)}
+ replyType={this.props.replyType}
+ buttonTitle={
+ this.props.privateMessageView
+ ? capitalizeFirstLetter(I18NextService.i18n.t("save"))
+ : capitalizeFirstLetter(I18NextService.i18n.t("send_message"))
+ }
/>
</div>
</div>
-
- {this.state.showDisclaimer && (
- <div className="mb-3 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>
- )}
- <div className="mb-3 row">
- <div className="offset-sm-2 col-sm-10">
- <button
- type="submit"
- className="btn btn-secondary me-2"
- disabled={this.state.loading}
- >
- {this.state.loading ? (
- <Spinner />
- ) : this.props.privateMessageView ? (
- capitalizeFirstLetter(I18NextService.i18n.t("save"))
- ) : (
- capitalizeFirstLetter(I18NextService.i18n.t("send_message"))
- )}
- </button>
- {this.props.privateMessageView && (
- <button
- type="button"
- className="btn btn-secondary"
- onClick={linkEvent(this, this.handleCancel)}
- >
- {I18NextService.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>
);
}
event.preventDefault();
i.setState({ previewMode: !i.state.previewMode });
}
-
- handleShowDisclaimer(i: PrivateMessageForm) {
- i.setState({ showDisclaimer: !i.state.showDisclaimer });
- }
}
<>
<li className="list-inline-item">
<button
+ type="button"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleMarkRead)}
data-tippy-content={
<li className="list-inline-item">{this.reportButton}</li>
<li className="list-inline-item">
<button
+ type="button"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleReplyClick)}
data-tippy-content={I18NextService.i18n.t("reply")}
<>
<li className="list-inline-item">
<button
+ type="button"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleEditClick)}
data-tippy-content={I18NextService.i18n.t("edit")}
</li>
<li className="list-inline-item">
<button
+ type="button"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleDeleteClick)}
data-tippy-content={
)}
<li className="list-inline-item">
<button
+ type="button"
className="btn btn-link btn-animate text-muted"
onClick={linkEvent(this, this.handleViewSource)}
data-tippy-content={I18NextService.i18n.t("view_source")}
</form>
)}
{this.state.showReply && (
- <PrivateMessageForm
- recipient={otherPerson}
- onCreate={this.props.onCreate}
- />
+ <div className="row">
+ <div className="col-sm-6">
+ <PrivateMessageForm
+ privateMessageView={message_view}
+ replyType={true}
+ recipient={otherPerson}
+ onCreate={this.props.onCreate}
+ onCancel={this.handleReplyCancel}
+ />
+ </div>
+ </div>
)}
{/* A collapsed clearfix */}
{this.state.collapsed && <div className="row col-12"></div>}
get reportButton() {
return (
<button
+ type="button"
className="btn btn-link btn-animate text-muted py-0"
onClick={linkEvent(this, this.handleShowReportDialog)}
data-tippy-content={I18NextService.i18n.t("show_report_dialog")}