]> Untitled Git - lemmy-ui.git/blob - src/shared/components/private_message/private-message-form.tsx
component classes v2
[lemmy-ui.git] / src / shared / components / private_message / private-message-form.tsx
1 import { Component, InfernoNode, linkEvent } from "inferno";
2 import { T } from "inferno-i18next-dess";
3 import {
4   CreatePrivateMessage,
5   EditPrivateMessage,
6   Person,
7   PrivateMessageView,
8 } from "lemmy-js-client";
9 import { i18n } from "../../i18next";
10 import {
11   capitalizeFirstLetter,
12   myAuthRequired,
13   relTags,
14   setupTippy,
15 } from "../../utils";
16 import { Icon, Spinner } from "../common/icon";
17 import { MarkdownTextArea } from "../common/markdown-textarea";
18 import NavigationPrompt from "../common/navigation-prompt";
19 import { PersonListing } from "../person/person-listing";
20
21 interface PrivateMessageFormProps {
22   recipient: Person;
23   privateMessageView?: PrivateMessageView; // If a pm is given, that means this is an edit
24   onCancel?(): any;
25   onCreate?(form: CreatePrivateMessage): void;
26   onEdit?(form: EditPrivateMessage): void;
27 }
28
29 interface PrivateMessageFormState {
30   content?: string;
31   loading: boolean;
32   previewMode: boolean;
33   showDisclaimer: boolean;
34   submitted: boolean;
35 }
36
37 export class PrivateMessageForm extends Component<
38   PrivateMessageFormProps,
39   PrivateMessageFormState
40 > {
41   state: PrivateMessageFormState = {
42     loading: false,
43     previewMode: false,
44     showDisclaimer: false,
45     content: this.props.privateMessageView
46       ? this.props.privateMessageView.private_message.content
47       : undefined,
48     submitted: false,
49   };
50
51   constructor(props: any, context: any) {
52     super(props, context);
53
54     this.handleContentChange = this.handleContentChange.bind(this);
55   }
56
57   componentDidMount() {
58     setupTippy();
59   }
60
61   componentWillReceiveProps(
62     nextProps: Readonly<{ children?: InfernoNode } & PrivateMessageFormProps>
63   ): void {
64     if (this.props != nextProps) {
65       this.setState({ loading: false, content: undefined, previewMode: false });
66     }
67   }
68   // TODO
69   // <Prompt
70   //   when={!this.state.loading && this.state.content}
71   //   message={i18n.t("block_leaving")}
72   // />
73
74   render() {
75     return (
76       <form
77         className="private-message-form"
78         onSubmit={linkEvent(this, this.handlePrivateMessageSubmit)}
79       >
80         <NavigationPrompt
81           when={
82             !this.state.loading && !!this.state.content && !this.state.submitted
83           }
84         />
85         {!this.props.privateMessageView && (
86           <div className="mb-3 row">
87             <label className="col-sm-2 col-form-label">
88               {capitalizeFirstLetter(i18n.t("to"))}
89             </label>
90
91             <div className="col-sm-10 form-control-plaintext">
92               <PersonListing person={this.props.recipient} />
93             </div>
94           </div>
95         )}
96         <div className="mb-3 row">
97           <label className="col-sm-2 col-form-label">
98             {i18n.t("message")}
99             <button
100               className="btn btn-link text-warning d-inline-block"
101               onClick={linkEvent(this, this.handleShowDisclaimer)}
102               data-tippy-content={i18n.t("private_message_disclaimer")}
103               aria-label={i18n.t("private_message_disclaimer")}
104             >
105               <Icon icon="alert-triangle" classes="icon-inline" />
106             </button>
107           </label>
108           <div className="col-sm-10">
109             <MarkdownTextArea
110               initialContent={this.state.content}
111               onContentChange={this.handleContentChange}
112               allLanguages={[]}
113               siteLanguages={[]}
114               hideNavigationWarnings
115             />
116           </div>
117         </div>
118
119         {this.state.showDisclaimer && (
120           <div className="mb-3 row">
121             <div className="offset-sm-2 col-sm-10">
122               <div className="alert alert-danger" role="alert">
123                 <T i18nKey="private_message_disclaimer">
124                   #
125                   <a
126                     className="alert-link"
127                     rel={relTags}
128                     href="https://element.io/get-started"
129                   >
130                     #
131                   </a>
132                 </T>
133               </div>
134             </div>
135           </div>
136         )}
137         <div className="mb-3 row">
138           <div className="offset-sm-2 col-sm-10">
139             <button
140               type="submit"
141               className="btn btn-secondary me-2"
142               disabled={this.state.loading}
143             >
144               {this.state.loading ? (
145                 <Spinner />
146               ) : this.props.privateMessageView ? (
147                 capitalizeFirstLetter(i18n.t("save"))
148               ) : (
149                 capitalizeFirstLetter(i18n.t("send_message"))
150               )}
151             </button>
152             {this.props.privateMessageView && (
153               <button
154                 type="button"
155                 className="btn btn-secondary"
156                 onClick={linkEvent(this, this.handleCancel)}
157               >
158                 {i18n.t("cancel")}
159               </button>
160             )}
161             <ul className="d-inline-block float-right list-inline mb-1 text-muted font-weight-bold">
162               <li className="list-inline-item"></li>
163             </ul>
164           </div>
165         </div>
166       </form>
167     );
168   }
169
170   handlePrivateMessageSubmit(i: PrivateMessageForm, event: any) {
171     event.preventDefault();
172     i.setState({ loading: true, submitted: true });
173     const pm = i.props.privateMessageView;
174     const auth = myAuthRequired();
175     const content = i.state.content ?? "";
176     if (pm) {
177       i.props.onEdit?.({
178         private_message_id: pm.private_message.id,
179         content,
180         auth,
181       });
182     } else {
183       i.props.onCreate?.({
184         content,
185         recipient_id: i.props.recipient.id,
186         auth,
187       });
188     }
189   }
190
191   handleContentChange(val: string) {
192     this.setState({ content: val });
193   }
194
195   handleCancel(i: PrivateMessageForm) {
196     i.props.onCancel?.();
197   }
198
199   handlePreviewToggle(i: PrivateMessageForm, event: any) {
200     event.preventDefault();
201     i.setState({ previewMode: !i.state.previewMode });
202   }
203
204   handleShowDisclaimer(i: PrivateMessageForm) {
205     i.setState({ showDisclaimer: !i.state.showDisclaimer });
206   }
207 }