]> Untitled Git - lemmy-ui.git/blob - src/shared/components/post/create-post.tsx
Adding Community Language fixes. #783 (#868)
[lemmy-ui.git] / src / shared / components / post / create-post.tsx
1 import { Either, Left, None, Option, Right, Some } from "@sniptt/monads";
2 import { Component } from "inferno";
3 import {
4   GetCommunity,
5   GetCommunityResponse,
6   GetSiteResponse,
7   ListCommunities,
8   ListCommunitiesResponse,
9   ListingType,
10   PostView,
11   SortType,
12   toOption,
13   UserOperation,
14   wsJsonToRes,
15   wsUserOp,
16 } from "lemmy-js-client";
17 import { Subscription } from "rxjs";
18 import { InitialFetchRequest, PostFormParams } from "shared/interfaces";
19 import { i18n } from "../../i18next";
20 import { UserService, WebSocketService } from "../../services";
21 import {
22   auth,
23   enableDownvotes,
24   enableNsfw,
25   fetchLimit,
26   isBrowser,
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 interface CreatePostState {
37   listCommunitiesResponse: Option<ListCommunitiesResponse>;
38   siteRes: GetSiteResponse;
39   loading: boolean;
40 }
41
42 export class CreatePost extends Component<any, CreatePostState> {
43   private isoData = setIsoData(this.context, ListCommunitiesResponse);
44   private subscription: Subscription;
45   private emptyState: CreatePostState = {
46     siteRes: this.isoData.site_res,
47     listCommunitiesResponse: None,
48     loading: true,
49   };
50
51   constructor(props: any, context: any) {
52     super(props, context);
53     this.state = this.emptyState;
54
55     this.handlePostCreate = this.handlePostCreate.bind(this);
56
57     this.parseMessage = this.parseMessage.bind(this);
58     this.subscription = wsSubscribe(this.parseMessage);
59
60     if (UserService.Instance.myUserInfo.isNone() && isBrowser()) {
61       toast(i18n.t("not_logged_in"), "danger");
62       this.context.router.history.push(`/login`);
63     }
64
65     // Only fetch the data if coming from another route
66     if (this.isoData.path == this.context.router.route.match.url) {
67       this.state = {
68         ...this.state,
69         listCommunitiesResponse: Some(
70           this.isoData.routeData[0] as ListCommunitiesResponse
71         ),
72         loading: false,
73       };
74     } else {
75       this.refetch();
76     }
77   }
78
79   refetch() {
80     this.params.nameOrId.match({
81       some: opt =>
82         opt.match({
83           left: name => {
84             let form = new GetCommunity({
85               name: Some(name),
86               id: None,
87               auth: auth(false).ok(),
88             });
89             WebSocketService.Instance.send(wsClient.getCommunity(form));
90           },
91           right: id => {
92             let form = new GetCommunity({
93               id: Some(id),
94               name: None,
95               auth: auth(false).ok(),
96             });
97             WebSocketService.Instance.send(wsClient.getCommunity(form));
98           },
99         }),
100       none: () => {
101         let listCommunitiesForm = new ListCommunities({
102           type_: Some(ListingType.All),
103           sort: Some(SortType.TopAll),
104           limit: Some(fetchLimit),
105           page: None,
106           auth: auth(false).ok(),
107         });
108         WebSocketService.Instance.send(
109           wsClient.listCommunities(listCommunitiesForm)
110         );
111       },
112     });
113   }
114
115   componentWillUnmount() {
116     if (isBrowser()) {
117       this.subscription.unsubscribe();
118     }
119   }
120
121   get documentTitle(): string {
122     return `${i18n.t("create_post")} - ${
123       this.state.siteRes.site_view.site.name
124     }`;
125   }
126
127   render() {
128     return (
129       <div className="container-lg">
130         <HtmlTags
131           title={this.documentTitle}
132           path={this.context.router.route.match.url}
133           description={None}
134           image={None}
135         />
136         {this.state.loading ? (
137           <h5>
138             <Spinner large />
139           </h5>
140         ) : (
141           this.state.listCommunitiesResponse.match({
142             some: res => (
143               <div className="row">
144                 <div className="col-12 col-lg-6 offset-lg-3 mb-4">
145                   <h5>{i18n.t("create_post")}</h5>
146                   <PostForm
147                     post_view={None}
148                     communities={Some(res.communities)}
149                     onCreate={this.handlePostCreate}
150                     params={Some(this.params)}
151                     enableDownvotes={enableDownvotes(this.state.siteRes)}
152                     enableNsfw={enableNsfw(this.state.siteRes)}
153                     allLanguages={this.state.siteRes.all_languages}
154                     siteLanguages={this.state.siteRes.discussion_languages}
155                   />
156                 </div>
157               </div>
158             ),
159             none: <></>,
160           })
161         )}
162       </div>
163     );
164   }
165
166   get params(): PostFormParams {
167     let urlParams = new URLSearchParams(this.props.location.search);
168     let name = toOption(urlParams.get("community_name")).or(
169       this.prevCommunityName
170     );
171     let id = toOption(urlParams.get("community_id"))
172       .map(Number)
173       .or(this.prevCommunityId);
174     let nameOrId: Option<Either<string, number>>;
175     if (name.isSome()) {
176       nameOrId = Some(Left(name.unwrap()));
177     } else if (id.isSome()) {
178       nameOrId = Some(Right(id.unwrap()));
179     } else {
180       nameOrId = None;
181     }
182
183     let params: PostFormParams = {
184       name: toOption(urlParams.get("title")),
185       nameOrId,
186       body: toOption(urlParams.get("body")),
187       url: toOption(urlParams.get("url")),
188     };
189
190     return params;
191   }
192
193   get prevCommunityName(): Option<string> {
194     if (this.props.match.params.name) {
195       return toOption(this.props.match.params.name);
196     } else if (this.props.location.state) {
197       let lastLocation = this.props.location.state.prevPath;
198       if (lastLocation.includes("/c/")) {
199         return toOption(lastLocation.split("/c/")[1]);
200       }
201     }
202     return None;
203   }
204
205   get prevCommunityId(): Option<number> {
206     if (this.props.match.params.id) {
207       return toOption(this.props.match.params.id);
208     }
209     return None;
210   }
211
212   handlePostCreate(post_view: PostView) {
213     this.props.history.push(`/post/${post_view.post.id}`);
214   }
215
216   static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
217     let listCommunitiesForm = new ListCommunities({
218       type_: Some(ListingType.All),
219       sort: Some(SortType.TopAll),
220       limit: Some(fetchLimit),
221       page: None,
222       auth: req.auth,
223     });
224     return [req.client.listCommunities(listCommunitiesForm)];
225   }
226
227   parseMessage(msg: any) {
228     let op = wsUserOp(msg);
229     console.log(msg);
230     if (msg.error) {
231       toast(i18n.t(msg.error), "danger");
232       return;
233     } else if (op == UserOperation.ListCommunities) {
234       let data = wsJsonToRes<ListCommunitiesResponse>(
235         msg,
236         ListCommunitiesResponse
237       );
238       this.setState({ listCommunitiesResponse: Some(data), loading: false });
239     } else if (op == UserOperation.GetCommunity) {
240       let data = wsJsonToRes<GetCommunityResponse>(msg, GetCommunityResponse);
241       this.setState({
242         listCommunitiesResponse: Some({
243           communities: [data.community_view],
244         }),
245         loading: false,
246       });
247     }
248   }
249 }