]> Untitled Git - lemmy-ui.git/blobdiff - src/shared/components/community/communities.tsx
Make pages use query params instead of route params where appropriate (#977)
[lemmy-ui.git] / src / shared / components / community / communities.tsx
index e6cdc454eaf7b267dc74d4ff9d88dee60ef52e9b..2589d5e8c5c99424b54d57e82c85d8544a2ffae2 100644 (file)
@@ -17,11 +17,14 @@ import { InitialFetchRequest } from "shared/interfaces";
 import { i18n } from "../../i18next";
 import { WebSocketService } from "../../services";
 import {
-  getListingTypeFromPropsNoDefault,
-  getPageFromProps,
+  getPageFromString,
+  getQueryParams,
+  getQueryString,
   isBrowser,
   myAuth,
   numToSI,
+  QueryParams,
+  routeListingTypeToEnum,
   setIsoData,
   showLocal,
   toast,
@@ -38,16 +41,52 @@ const communityLimit = 50;
 
 interface CommunitiesState {
   listCommunitiesResponse?: ListCommunitiesResponse;
-  page: number;
   loading: boolean;
   siteRes: GetSiteResponse;
   searchText: string;
-  listingType: ListingType;
 }
 
 interface CommunitiesProps {
-  listingType?: ListingType;
-  page?: number;
+  listingType: ListingType;
+  page: number;
+}
+
+function getCommunitiesQueryParams() {
+  return getQueryParams<CommunitiesProps>({
+    listingType: getListingTypeFromQuery,
+    page: getPageFromString,
+  });
+}
+
+function getListingTypeFromQuery(listingType?: string): ListingType {
+  return routeListingTypeToEnum(listingType ?? "", ListingType.Local);
+}
+
+function toggleSubscribe(community_id: number, follow: boolean) {
+  const auth = myAuth();
+  if (auth) {
+    const form: FollowCommunity = {
+      community_id,
+      follow,
+      auth,
+    };
+
+    WebSocketService.Instance.send(wsClient.followCommunity(form));
+  }
+}
+
+function refetch() {
+  const { listingType, page } = getCommunitiesQueryParams();
+
+  const listCommunitiesForm: ListCommunities = {
+    type_: listingType,
+    sort: SortType.TopMonth,
+    limit: communityLimit,
+    page,
+    auth: myAuth(false),
+  };
+
+  WebSocketService.Instance.send(wsClient.listCommunities(listCommunitiesForm));
 }
 
 export class Communities extends Component<any, CommunitiesState> {
@@ -55,8 +94,6 @@ export class Communities extends Component<any, CommunitiesState> {
   private isoData = setIsoData(this.context);
   state: CommunitiesState = {
     loading: true,
-    page: getPageFromProps(this.props),
-    listingType: getListingTypeFromPropsNoDefault(this.props),
     siteRes: this.isoData.site_res,
     searchText: "",
   };
@@ -70,15 +107,15 @@ export class Communities extends Component<any, CommunitiesState> {
     this.subscription = wsSubscribe(this.parseMessage);
 
     // Only fetch the data if coming from another route
-    if (this.isoData.path == this.context.router.route.match.url) {
-      let listRes = this.isoData.routeData[0] as ListCommunitiesResponse;
+    if (this.isoData.path === this.context.router.route.match.url) {
+      const listRes = this.isoData.routeData[0] as ListCommunitiesResponse;
       this.state = {
         ...this.state,
         listCommunitiesResponse: listRes,
         loading: false,
       };
     } else {
-      this.refetch();
+      refetch();
     }
   }
 
@@ -88,23 +125,6 @@ export class Communities extends Component<any, CommunitiesState> {
     }
   }
 
-  static getDerivedStateFromProps(props: any): CommunitiesProps {
-    return {
-      listingType: getListingTypeFromPropsNoDefault(props),
-      page: getPageFromProps(props),
-    };
-  }
-
-  componentDidUpdate(_: any, lastState: CommunitiesState) {
-    if (
-      lastState.page !== this.state.page ||
-      lastState.listingType !== this.state.listingType
-    ) {
-      this.setState({ loading: true });
-      this.refetch();
-    }
-  }
-
   get documentTitle(): string {
     return `${i18n.t("communities")} - ${
       this.state.siteRes.site_view.site.name
@@ -112,6 +132,8 @@ export class Communities extends Component<any, CommunitiesState> {
   }
 
   render() {
+    const { listingType, page } = getCommunitiesQueryParams();
+
     return (
       <div className="container-lg">
         <HtmlTags
@@ -129,7 +151,7 @@ export class Communities extends Component<any, CommunitiesState> {
                 <h4>{i18n.t("list_of_communities")}</h4>
                 <span className="mb-2">
                   <ListingTypeSelect
-                    type_={this.state.listingType}
+                    type_={listingType}
                     showLocal={showLocal(this.isoData)}
                     showSubscribed
                     onChange={this.handleListingTypeChange}
@@ -192,7 +214,7 @@ export class Communities extends Component<any, CommunitiesState> {
                             {i18n.t("unsubscribe")}
                           </button>
                         )}
-                        {cv.subscribed == SubscribedType.NotSubscribed && (
+                        {cv.subscribed === SubscribedType.NotSubscribed && (
                           <button
                             className="btn btn-link d-inline-block"
                             onClick={linkEvent(
@@ -203,7 +225,7 @@ export class Communities extends Component<any, CommunitiesState> {
                             {i18n.t("subscribe")}
                           </button>
                         )}
-                        {cv.subscribed == SubscribedType.Pending && (
+                        {cv.subscribed === SubscribedType.Pending && (
                           <div className="text-warning d-inline-block">
                             {i18n.t("subscribe_pending")}
                           </div>
@@ -214,10 +236,7 @@ export class Communities extends Component<any, CommunitiesState> {
                 </tbody>
               </table>
             </div>
-            <Paginator
-              page={this.state.page}
-              onChange={this.handlePageChange}
-            />
+            <Paginator page={page} onChange={this.handlePageChange} />
           </div>
         )}
       </div>
@@ -250,12 +269,18 @@ export class Communities extends Component<any, CommunitiesState> {
     );
   }
 
-  updateUrl(paramUpdates: CommunitiesProps) {
-    const page = paramUpdates.page || this.state.page;
-    const listingTypeStr = paramUpdates.listingType || this.state.listingType;
-    this.props.history.push(
-      `/communities/listing_type/${listingTypeStr}/page/${page}`
-    );
+  updateUrl({ listingType, page }: Partial<CommunitiesProps>) {
+    const { listingType: urlListingType, page: urlPage } =
+      getCommunitiesQueryParams();
+
+    const queryParams: QueryParams<CommunitiesProps> = {
+      listingType: listingType ?? urlListingType,
+      page: (page ?? urlPage)?.toString(),
+    };
+
+    this.props.history.push(`/communities${getQueryString(queryParams)}`);
+
+    refetch();
   }
 
   handlePageChange(page: number) {
@@ -270,27 +295,11 @@ export class Communities extends Component<any, CommunitiesState> {
   }
 
   handleUnsubscribe(communityId: number) {
-    let auth = myAuth();
-    if (auth) {
-      let form: FollowCommunity = {
-        community_id: communityId,
-        follow: false,
-        auth,
-      };
-      WebSocketService.Instance.send(wsClient.followCommunity(form));
-    }
+    toggleSubscribe(communityId, false);
   }
 
   handleSubscribe(communityId: number) {
-    let auth = myAuth();
-    if (auth) {
-      let form: FollowCommunity = {
-        community_id: communityId,
-        follow: true,
-        auth,
-      };
-      WebSocketService.Instance.send(wsClient.followCommunity(form));
-    }
+    toggleSubscribe(communityId, true);
   }
 
   handleSearchChange(i: Communities, event: any) {
@@ -299,61 +308,50 @@ export class Communities extends Component<any, CommunitiesState> {
 
   handleSearchSubmit(i: Communities) {
     const searchParamEncoded = encodeURIComponent(i.state.searchText);
-    i.context.router.history.push(
-      `/search/q/${searchParamEncoded}/type/Communities/sort/TopAll/listing_type/All/community_id/0/creator_id/0/page/1`
-    );
-  }
-
-  refetch() {
-    let listCommunitiesForm: ListCommunities = {
-      type_: this.state.listingType,
-      sort: SortType.TopMonth,
-      limit: communityLimit,
-      page: this.state.page,
-      auth: myAuth(false),
-    };
-
-    WebSocketService.Instance.send(
-      wsClient.listCommunities(listCommunitiesForm)
-    );
+    i.context.router.history.push(`/search?q=${searchParamEncoded}`);
   }
 
-  static fetchInitialData(req: InitialFetchRequest): Promise<any>[] {
-    let pathSplit = req.path.split("/");
-    let type_: ListingType = pathSplit[3]
-      ? ListingType[pathSplit[3]]
-      : ListingType.Local;
-    let page = pathSplit[5] ? Number(pathSplit[5]) : 1;
-    let listCommunitiesForm: ListCommunities = {
-      type_,
+  static fetchInitialData({
+    query: { listingType, page },
+    client,
+    auth,
+  }: InitialFetchRequest<QueryParams<CommunitiesProps>>): Promise<any>[] {
+    const listCommunitiesForm: ListCommunities = {
+      type_: getListingTypeFromQuery(listingType),
       sort: SortType.TopMonth,
       limit: communityLimit,
-      page,
-      auth: req.auth,
+      page: getPageFromString(page),
+      auth: auth,
     };
 
-    return [req.client.listCommunities(listCommunitiesForm)];
+    return [client.listCommunities(listCommunitiesForm)];
   }
 
   parseMessage(msg: any) {
-    let op = wsUserOp(msg);
+    const op = wsUserOp(msg);
     console.log(msg);
     if (msg.error) {
       toast(i18n.t(msg.error), "danger");
-      return;
-    } else if (op == UserOperation.ListCommunities) {
-      let data = wsJsonToRes<ListCommunitiesResponse>(msg);
+    } else if (op === UserOperation.ListCommunities) {
+      const data = wsJsonToRes<ListCommunitiesResponse>(msg);
       this.setState({ listCommunitiesResponse: data, loading: false });
       window.scrollTo(0, 0);
-    } else if (op == UserOperation.FollowCommunity) {
-      let data = wsJsonToRes<CommunityResponse>(msg);
-      let res = this.state.listCommunitiesResponse;
-      let found = res?.communities.find(
-        c => c.community.id == data.community_view.community.id
+    } else if (op === UserOperation.FollowCommunity) {
+      const {
+        community_view: {
+          community,
+          subscribed,
+          counts: { subscribers },
+        },
+      } = wsJsonToRes<CommunityResponse>(msg);
+      const res = this.state.listCommunitiesResponse;
+      const found = res?.communities.find(
+        ({ community: { id } }) => id == community.id
       );
+
       if (found) {
-        found.subscribed = data.community_view.subscribed;
-        found.counts.subscribers = data.community_view.counts.subscribers;
+        found.subscribed = subscribed;
+        found.counts.subscribers = subscribers;
         this.setState(this.state);
       }
     }