]> Untitled Git - lemmy-ui.git/blobdiff - src/shared/components/post/create-post.tsx
Merge branch 'LemmyNet:main' into breakout-role-utils
[lemmy-ui.git] / src / shared / components / post / create-post.tsx
index 2d0ba7e06c0a5ca13a8ca8175dc5d826d5838cc7..63ee390f8ad0d85e36b5a040bef25b80c16460a5 100644 (file)
@@ -1,34 +1,29 @@
 import { Component } from "inferno";
-import { Redirect } from "inferno-router";
 import { RouteComponentProps } from "inferno-router/dist/Route";
 import {
+  CreatePost as CreatePostI,
   GetCommunity,
-  GetCommunityResponse,
   GetSiteResponse,
-  PostView,
-  UserOperation,
-  wsJsonToRes,
-  wsUserOp,
+  ListCommunitiesResponse,
 } from "lemmy-js-client";
-import { Subscription } from "rxjs";
-import { InitialFetchRequest, PostFormParams } from "shared/interfaces";
 import { i18n } from "../../i18next";
-import { UserService, WebSocketService } from "../../services";
+import { InitialFetchRequest, PostFormParams } from "../../interfaces";
+import { FirstLoadService } from "../../services/FirstLoadService";
+import {
+  HttpService,
+  RequestState,
+  WrappedLemmyHttp,
+} from "../../services/HttpService";
 import {
   Choice,
-  QueryParams,
   enableDownvotes,
   enableNsfw,
   getIdFromString,
-  getQueryParams,
-  getQueryString,
-  isBrowser,
   myAuth,
   setIsoData,
-  toast,
-  wsClient,
-  wsSubscribe,
 } from "../../utils";
+import { getQueryParams } from "../../utils/helpers/get-query-params";
+import type { QueryParams } from "../../utils/types/query-params";
 import { HtmlTags } from "../common/html-tags";
 import { Spinner } from "../common/icon";
 import { PostForm } from "./post-form";
@@ -43,10 +38,16 @@ function getCreatePostQueryParams() {
   });
 }
 
+function fetchCommunitiesForOptions(client: WrappedLemmyHttp) {
+  return client.listCommunities({ limit: 30, sort: "TopMonth", type_: "All" });
+}
+
 interface CreatePostState {
   siteRes: GetSiteResponse;
   loading: boolean;
   selectedCommunityChoice?: Choice;
+  initialCommunitiesRes: RequestState<ListCommunitiesResponse>;
+  isIsomorphic: boolean;
 }
 
 export class CreatePost extends Component<
@@ -54,10 +55,11 @@ export class CreatePost extends Component<
   CreatePostState
 > {
   private isoData = setIsoData(this.context);
-  private subscription?: Subscription;
   state: CreatePostState = {
     siteRes: this.isoData.site_res,
     loading: true,
+    initialCommunitiesRes: { state: "empty" },
+    isIsomorphic: false,
   };
 
   constructor(props: RouteComponentProps<Record<string, never>>, context: any) {
@@ -67,19 +69,14 @@ export class CreatePost extends Component<
     this.handleSelectedCommunityChange =
       this.handleSelectedCommunityChange.bind(this);
 
-    this.parseMessage = this.parseMessage.bind(this);
-    this.subscription = wsSubscribe(this.parseMessage);
-
     // Only fetch the data if coming from another route
-    if (this.isoData.path === this.context.router.route.match.url) {
-      const communityRes = this.isoData.routeData[0] as
-        | GetCommunityResponse
-        | undefined;
+    if (FirstLoadService.isFirstLoad) {
+      const [communityRes, listCommunitiesRes] = this.isoData.routeData;
 
-      if (communityRes) {
+      if (communityRes?.state === "success") {
         const communityChoice: Choice = {
-          label: communityRes.community_view.community.name,
-          value: communityRes.community_view.community.id.toString(),
+          label: communityRes.data.community_view.community.title,
+          value: communityRes.data.community_view.community.id.toString(),
         };
 
         this.state = {
@@ -91,42 +88,56 @@ export class CreatePost extends Component<
       this.state = {
         ...this.state,
         loading: false,
+        initialCommunitiesRes: listCommunitiesRes,
+        isIsomorphic: true,
       };
-    } else {
-      this.fetchCommunity();
     }
   }
 
-  fetchCommunity() {
+  async fetchCommunity() {
     const { communityId } = getCreatePostQueryParams();
-    const auth = myAuth(false);
+    const auth = myAuth();
 
     if (communityId) {
-      const form: GetCommunity = {
+      const res = await HttpService.client.getCommunity({
         id: communityId,
         auth,
-      };
-
-      WebSocketService.Instance.send(wsClient.getCommunity(form));
+      });
+      if (res.state === "success") {
+        this.setState({
+          selectedCommunityChoice: {
+            label: res.data.community_view.community.name,
+            value: res.data.community_view.community.id.toString(),
+          },
+          loading: false,
+        });
+      }
     }
   }
 
-  componentDidMount(): void {
-    const { communityId } = getCreatePostQueryParams();
+  async componentDidMount() {
+    // TODO test this
+    if (!this.state.isIsomorphic) {
+      const { communityId } = getCreatePostQueryParams();
+
+      const initialCommunitiesRes = await fetchCommunitiesForOptions(
+        HttpService.client
+      );
 
-    if (communityId?.toString() !== this.state.selectedCommunityChoice?.value) {
-      this.fetchCommunity();
-    } else if (!communityId) {
       this.setState({
-        selectedCommunityChoice: undefined,
-        loading: false,
+        initialCommunitiesRes,
       });
-    }
-  }
 
-  componentWillUnmount() {
-    if (isBrowser()) {
-      this.subscription?.unsubscribe();
+      if (
+        communityId?.toString() !== this.state.selectedCommunityChoice?.value
+      ) {
+        await this.fetchCommunity();
+      } else if (!communityId) {
+        this.setState({
+          selectedCommunityChoice: undefined,
+          loading: false,
+        });
+      }
     }
   }
 
@@ -145,7 +156,6 @@ export class CreatePost extends Component<
 
     return (
       <div className="container-lg">
-        {!UserService.Instance.myUserInfo && <Redirect to="/login" />}
         <HtmlTags
           title={this.documentTitle}
           path={this.context.router.route.match.url}
@@ -156,7 +166,10 @@ export class CreatePost extends Component<
           </h5>
         ) : (
           <div className="row">
-            <div className="col-12 col-lg-6 offset-lg-3 mb-4">
+            <div
+              id="createPostForm"
+              className="col-12 col-lg-6 offset-lg-3 mb-4"
+            >
               <h5>{i18n.t("create_post")}</h5>
               <PostForm
                 onCreate={this.handlePostCreate}
@@ -167,6 +180,11 @@ export class CreatePost extends Component<
                 siteLanguages={this.state.siteRes.discussion_languages}
                 selectedCommunityChoice={selectedCommunityChoice}
                 onSelectCommunity={this.handleSelectedCommunityChange}
+                initialCommunities={
+                  this.state.initialCommunitiesRes.state === "success"
+                    ? this.state.initialCommunitiesRes.data.communities
+                    : []
+                }
               />
             </div>
           </div>
@@ -175,23 +193,26 @@ export class CreatePost extends Component<
     );
   }
 
-  updateUrl({ communityId }: Partial<CreatePostProps>) {
+  async updateUrl({ communityId }: Partial<CreatePostProps>) {
     const { communityId: urlCommunityId } = getCreatePostQueryParams();
 
-    const queryParams: QueryParams<CreatePostProps> = {
-      communityId: (communityId ?? urlCommunityId)?.toString(),
-    };
-
     const locationState = this.props.history.location.state as
       | PostFormParams
       | undefined;
 
-    this.props.history.replace(
-      `/create_post${getQueryString(queryParams)}`,
-      locationState
-    );
+    const url = new URL(location.href);
 
-    this.fetchCommunity();
+    const newId = (communityId ?? urlCommunityId)?.toString();
+
+    if (newId !== undefined) {
+      url.searchParams.set("communityId", newId);
+    } else {
+      url.searchParams.delete("communityId");
+    }
+
+    history.replaceState(locationState, "", url);
+
+    await this.fetchCommunity();
   }
 
   handleSelectedCommunityChange(choice: Choice) {
@@ -200,16 +221,27 @@ export class CreatePost extends Component<
     });
   }
 
-  handlePostCreate(post_view: PostView) {
-    this.props.history.replace(`/post/${post_view.post.id}`);
+  async handlePostCreate(form: CreatePostI) {
+    const res = await HttpService.client.createPost(form);
+
+    if (res.state === "success") {
+      const postId = res.data.post_view.post.id;
+      this.props.history.replace(`/post/${postId}`);
+    } else {
+      this.setState({
+        loading: false,
+      });
+    }
   }
 
   static fetchInitialData({
     client,
     query: { communityId },
     auth,
-  }: InitialFetchRequest<QueryParams<CreatePostProps>>): Promise<any>[] {
-    const promises: Promise<any>[] = [];
+  }: InitialFetchRequest<QueryParams<CreatePostProps>>): Promise<
+    RequestState<any>
+  >[] {
+    const promises: Promise<RequestState<any>>[] = [];
 
     if (communityId) {
       const form: GetCommunity = {
@@ -219,31 +251,11 @@ export class CreatePost extends Component<
 
       promises.push(client.getCommunity(form));
     } else {
-      promises.push(Promise.resolve());
+      promises.push(Promise.resolve({ state: "empty" }));
     }
 
-    return promises;
-  }
-
-  parseMessage(msg: any) {
-    const op = wsUserOp(msg);
-    console.log(msg);
-    if (msg.error) {
-      toast(i18n.t(msg.error), "danger");
-      return;
-    }
+    promises.push(fetchCommunitiesForOptions(client));
 
-    if (op === UserOperation.GetCommunity) {
-      const {
-        community_view: {
-          community: { name, id },
-        },
-      } = wsJsonToRes<GetCommunityResponse>(msg);
-
-      this.setState({
-        selectedCommunityChoice: { label: name, value: id.toString() },
-        loading: false,
-      });
-    }
+    return promises;
   }
 }