]> Untitled Git - lemmy-ui.git/blob - src/shared/components/post/create-post.tsx
Handle when logged out (#986)
[lemmy-ui.git] / src / shared / components / post / create-post.tsx
1 import { Component } from "inferno";
2 import { Redirect } from "inferno-router";
3 import { RouteComponentProps } from "inferno-router/dist/Route";
4 import {
5   GetCommunity,
6   GetCommunityResponse,
7   GetSiteResponse,
8   PostView,
9   UserOperation,
10   wsJsonToRes,
11   wsUserOp,
12 } from "lemmy-js-client";
13 import { Subscription } from "rxjs";
14 import { InitialFetchRequest, PostFormParams } from "shared/interfaces";
15 import { i18n } from "../../i18next";
16 import { UserService, WebSocketService } from "../../services";
17 import {
18   Choice,
19   enableDownvotes,
20   enableNsfw,
21   getIdFromString,
22   getQueryParams,
23   getQueryString,
24   isBrowser,
25   myAuth,
26   QueryParams,
27   setIsoData,
28   toast,
29   wsClient,
30   wsSubscribe,
31 } from "../../utils";
32 import { HtmlTags } from "../common/html-tags";
33 import { Spinner } from "../common/icon";
34 import { PostForm } from "./post-form";
35
36 export interface CreatePostProps {
37   communityId?: number;
38 }
39
40 function getCreatePostQueryParams() {
41   return getQueryParams<CreatePostProps>({
42     communityId: getIdFromString,
43   });
44 }
45
46 interface CreatePostState {
47   siteRes: GetSiteResponse;
48   loading: boolean;
49   selectedCommunityChoice?: Choice;
50 }
51
52 export class CreatePost extends Component<
53   RouteComponentProps<Record<string, never>>,
54   CreatePostState
55 > {
56   private isoData = setIsoData(this.context);
57   private subscription?: Subscription;
58   state: CreatePostState = {
59     siteRes: this.isoData.site_res,
60     loading: true,
61   };
62
63   constructor(props: RouteComponentProps<Record<string, never>>, context: any) {
64     super(props, context);
65
66     this.handlePostCreate = this.handlePostCreate.bind(this);
67     this.handleSelectedCommunityChange =
68       this.handleSelectedCommunityChange.bind(this);
69
70     this.parseMessage = this.parseMessage.bind(this);
71     this.subscription = wsSubscribe(this.parseMessage);
72
73     // Only fetch the data if coming from another route
74     if (this.isoData.path === this.context.router.route.match.url) {
75       const communityRes = this.isoData.routeData[0] as
76         | GetCommunityResponse
77         | undefined;
78
79       if (communityRes) {
80         const communityChoice: Choice = {
81           label: communityRes.community_view.community.name,
82           value: communityRes.community_view.community.id.toString(),
83         };
84
85         this.state = {
86           ...this.state,
87           selectedCommunityChoice: communityChoice,
88         };
89       }
90
91       this.state = {
92         ...this.state,
93         loading: false,
94       };
95     } else {
96       this.fetchCommunity();
97     }
98   }
99
100   fetchCommunity() {
101     const { communityId } = getCreatePostQueryParams();
102     const auth = myAuth(false);
103
104     if (communityId) {
105       const form: GetCommunity = {
106         id: communityId,
107         auth,
108       };
109
110       WebSocketService.Instance.send(wsClient.getCommunity(form));
111     }
112   }
113
114   componentDidMount(): void {
115     const { communityId } = getCreatePostQueryParams();
116
117     if (communityId?.toString() !== this.state.selectedCommunityChoice?.value) {
118       this.fetchCommunity();
119     } else if (!communityId) {
120       this.setState({
121         selectedCommunityChoice: undefined,
122         loading: false,
123       });
124     }
125   }
126
127   componentWillUnmount() {
128     if (isBrowser()) {
129       this.subscription?.unsubscribe();
130     }
131   }
132
133   get documentTitle(): string {
134     return `${i18n.t("create_post")} - ${
135       this.state.siteRes.site_view.site.name
136     }`;
137   }
138
139   render() {
140     const { selectedCommunityChoice } = this.state;
141
142     const locationState = this.props.history.location.state as
143       | PostFormParams
144       | undefined;
145
146     return (
147       <div className="container-lg">
148         {!UserService.Instance.myUserInfo && <Redirect to="/login" />}
149         <HtmlTags
150           title={this.documentTitle}
151           path={this.context.router.route.match.url}
152         />
153         {this.state.loading ? (
154           <h5>
155             <Spinner large />
156           </h5>
157         ) : (
158           <div className="row">
159             <div className="col-12 col-lg-6 offset-lg-3 mb-4">
160               <h5>{i18n.t("create_post")}</h5>
161               <PostForm
162                 onCreate={this.handlePostCreate}
163                 params={locationState}
164                 enableDownvotes={enableDownvotes(this.state.siteRes)}
165                 enableNsfw={enableNsfw(this.state.siteRes)}
166                 allLanguages={this.state.siteRes.all_languages}
167                 siteLanguages={this.state.siteRes.discussion_languages}
168                 selectedCommunityChoice={selectedCommunityChoice}
169                 onSelectCommunity={this.handleSelectedCommunityChange}
170               />
171             </div>
172           </div>
173         )}
174       </div>
175     );
176   }
177
178   updateUrl({ communityId }: Partial<CreatePostProps>) {
179     const { communityId: urlCommunityId } = getCreatePostQueryParams();
180
181     const queryParams: QueryParams<CreatePostProps> = {
182       communityId: (communityId ?? urlCommunityId)?.toString(),
183     };
184
185     const locationState = this.props.history.location.state as
186       | PostFormParams
187       | undefined;
188
189     this.props.history.replace(
190       `/create_post${getQueryString(queryParams)}`,
191       locationState
192     );
193
194     this.fetchCommunity();
195   }
196
197   handleSelectedCommunityChange(choice: Choice) {
198     this.updateUrl({
199       communityId: getIdFromString(choice?.value),
200     });
201   }
202
203   handlePostCreate(post_view: PostView) {
204     this.props.history.replace(`/post/${post_view.post.id}`);
205   }
206
207   static fetchInitialData({
208     client,
209     query: { communityId },
210     auth,
211   }: InitialFetchRequest<QueryParams<CreatePostProps>>): Promise<any>[] {
212     const promises: Promise<any>[] = [];
213
214     if (communityId) {
215       const form: GetCommunity = {
216         auth,
217         id: getIdFromString(communityId),
218       };
219
220       promises.push(client.getCommunity(form));
221     } else {
222       promises.push(Promise.resolve());
223     }
224
225     return promises;
226   }
227
228   parseMessage(msg: any) {
229     const op = wsUserOp(msg);
230     console.log(msg);
231     if (msg.error) {
232       toast(i18n.t(msg.error), "danger");
233       return;
234     }
235
236     if (op === UserOperation.GetCommunity) {
237       const {
238         community_view: {
239           community: { name, id },
240         },
241       } = wsJsonToRes<GetCommunityResponse>(msg);
242
243       this.setState({
244         selectedCommunityChoice: { label: name, value: id.toString() },
245         loading: false,
246       });
247     }
248   }
249 }