]> Untitled Git - lemmy.git/blobdiff - ui/src/components/search.tsx
routes.api: fix get_captcha endpoint (#1135)
[lemmy.git] / ui / src / components / search.tsx
index 70a9faa2ed66c497b6a0ea6ccfb4760e6a06f0b8..8ab7f599b16426ad42f17838df719e32c9dadfb7 100644 (file)
@@ -1,5 +1,5 @@
 import { Component, linkEvent } from 'inferno';
-import { Link } from 'inferno-router';
+import { Helmet } from 'inferno-helmet';
 import { Subscription } from 'rxjs';
 import { retryWhen, delay, take } from 'rxjs/operators';
 import {
@@ -17,7 +17,7 @@ import {
   WebSocketJsonResponse,
   GetSiteResponse,
   Site,
-} from '../interfaces';
+} from 'lemmy-js-client';
 import { WebSocketService } from '../services';
 import {
   wsJsonToRes,
@@ -28,6 +28,7 @@ import {
   createCommentLikeRes,
   createPostLikeFindRes,
   commentsToFlatNodes,
+  getPageFromProps,
 } from '../utils';
 import { PostListing } from './post-listing';
 import { UserListing } from './user-listing';
@@ -47,13 +48,27 @@ interface SearchState {
   searchText: string;
 }
 
+interface SearchProps {
+  q: string;
+  type_: SearchType;
+  sort: SortType;
+  page: number;
+}
+
+interface UrlParams {
+  q?: string;
+  type_?: SearchType;
+  sort?: SortType;
+  page?: number;
+}
+
 export class Search extends Component<any, SearchState> {
   private subscription: Subscription;
   private emptyState: SearchState = {
     q: Search.getSearchQueryFromProps(this.props),
     type_: Search.getSearchTypeFromProps(this.props),
     sort: Search.getSortTypeFromProps(this.props),
-    page: Search.getPageFromProps(this.props),
+    page: getPageFromProps(this.props),
     searchText: Search.getSearchQueryFromProps(this.props),
     searchResponse: {
       type_: null,
@@ -95,10 +110,6 @@ export class Search extends Component<any, SearchState> {
       : SortType.TopAll;
   }
 
-  static getPageFromProps(props: any): number {
-    return props.match.params.page ? Number(props.match.params.page) : 1;
-  }
-
   constructor(props: any, context: any) {
     super(props, context);
 
@@ -124,16 +135,16 @@ export class Search extends Component<any, SearchState> {
     this.subscription.unsubscribe();
   }
 
-  static getDerivedStateFromProps(props) {
+  static getDerivedStateFromProps(props: any): SearchProps {
     return {
       q: Search.getSearchQueryFromProps(props),
       type_: Search.getSearchTypeFromProps(props),
       sort: Search.getSortTypeFromProps(props),
-      page: Search.getPageFromProps(props),
+      page: getPageFromProps(props),
     };
   }
 
-  componentDidUpdate(_, lastState) {
+  componentDidUpdate(_: any, lastState: SearchState) {
     if (
       lastState.q !== this.state.q ||
       lastState.type_ !== this.state.type_ ||
@@ -145,9 +156,24 @@ export class Search extends Component<any, SearchState> {
     }
   }
 
+  get documentTitle(): string {
+    if (this.state.site.name) {
+      if (this.state.q) {
+        return `${i18n.t('search')} - ${this.state.q} - ${
+          this.state.site.name
+        }`;
+      } else {
+        return `${i18n.t('search')} - ${this.state.site.name}`;
+      }
+    } else {
+      return 'Lemmy';
+    }
+  }
+
   render() {
     return (
       <div class="container">
+        <Helmet title={this.documentTitle} />
         <h5>{i18n.t('search')}</h5>
         {this.selects()}
         {this.searchForm()}
@@ -170,14 +196,14 @@ export class Search extends Component<any, SearchState> {
       >
         <input
           type="text"
-          class="form-control mr-2"
+          class="form-control mr-2 mb-2"
           value={this.state.searchText}
           placeholder={`${i18n.t('search')}...`}
           onInput={linkEvent(this, this.handleQChange)}
           required
           minLength={3}
         />
-        <button type="submit" class="btn btn-secondary mr-2">
+        <button type="submit" class="btn btn-secondary mr-2 mb-2">
           {this.state.loading ? (
             <svg class="icon icon-spinner spin">
               <use xlinkHref="#icon-spinner"></use>
@@ -196,7 +222,7 @@ export class Search extends Component<any, SearchState> {
         <select
           value={this.state.type_}
           onChange={linkEvent(this, this.handleTypeChange)}
-          class="custom-select custom-select-sm w-auto"
+          class="custom-select w-auto mb-2"
         >
           <option disabled>{i18n.t('type')}</option>
           <option value={SearchType.All}>{i18n.t('all')}</option>
@@ -263,6 +289,7 @@ export class Search extends Component<any, SearchState> {
             <div class="col-12">
               {i.type_ == 'posts' && (
                 <PostListing
+                  key={(i.data as Post).id}
                   post={i.data as Post}
                   showCommunity
                   enableDownvotes={this.state.site.enable_downvotes}
@@ -271,6 +298,7 @@ export class Search extends Component<any, SearchState> {
               )}
               {i.type_ == 'comments' && (
                 <CommentNodes
+                  key={(i.data as Comment).id}
                   nodes={[{ comment: i.data as Comment }]}
                   locked
                   noIndent
@@ -283,10 +311,11 @@ export class Search extends Component<any, SearchState> {
               {i.type_ == 'users' && (
                 <div>
                   <span>
-                    @
                     <UserListing
                       user={{
                         name: (i.data as UserView).name,
+                        preferred_username: (i.data as UserView)
+                          .preferred_username,
                         avatar: (i.data as UserView).avatar,
                       }}
                     />
@@ -368,11 +397,11 @@ export class Search extends Component<any, SearchState> {
           <div class="row">
             <div class="col-12">
               <span>
-                @
                 <UserListing
                   user={{
                     name: user.name,
                     avatar: user.avatar,
+                    preferred_username: user.preferred_username,
                   }}
                 />
               </span>
@@ -391,7 +420,7 @@ export class Search extends Component<any, SearchState> {
       <div class="mt-2">
         {this.state.page > 1 && (
           <button
-            class="btn btn-sm btn-secondary mr-1"
+            class="btn btn-secondary mr-1"
             onClick={linkEvent(this, this.prevPage)}
           >
             {i18n.t('prev')}
@@ -400,7 +429,7 @@ export class Search extends Component<any, SearchState> {
 
         {this.resultsCount() > 0 && (
           <button
-            class="btn btn-sm btn-secondary"
+            class="btn btn-secondary"
             onClick={linkEvent(this, this.nextPage)}
           >
             {i18n.t('next')}
@@ -431,8 +460,8 @@ export class Search extends Component<any, SearchState> {
   search() {
     let form: SearchForm = {
       q: this.state.q,
-      type_: SearchType[this.state.type_],
-      sort: SortType[this.state.sort],
+      type_: this.state.type_,
+      sort: this.state.sort,
       page: this.state.page,
       limit: fetchLimit,
     };
@@ -447,7 +476,10 @@ export class Search extends Component<any, SearchState> {
   }
 
   handleTypeChange(i: Search, event: any) {
-    i.updateUrl({ type_: Number(event.target.value), page: 1 });
+    i.updateUrl({
+      type_: SearchType[event.target.value],
+      page: 1,
+    });
   }
 
   handleSearchSubmit(i: Search, event: any) {
@@ -464,22 +496,13 @@ export class Search extends Component<any, SearchState> {
     i.setState({ searchText: event.target.value });
   }
 
-  updateUrl(paramUpdates: {
-    q?: string;
-    type_?: number;
-    sort?: SortType;
-    page?: number;
-  }) {
-    const qStr = paramUpdates.q || Search.getSearchQueryFromProps(this.props);
-    const typeStr =
-      SearchType[paramUpdates.type_] ||
-      SearchType[Search.getSearchTypeFromProps(this.props)];
-    const sortStr =
-      SortType[paramUpdates.sort] ||
-      SortType[Search.getSortTypeFromProps(this.props)];
-    const page = paramUpdates.page || Search.getPageFromProps(this.props);
+  updateUrl(paramUpdates: UrlParams) {
+    const qStr = paramUpdates.q || this.state.q;
+    const typeStr = paramUpdates.type_ || this.state.type_;
+    const sortStr = paramUpdates.sort || this.state.sort;
+    const page = paramUpdates.page || this.state.page;
     this.props.history.push(
-      `/search/q/${qStr}/type/${typeStr.toLowerCase()}/sort/${sortStr.toLowerCase()}/page/${page}`
+      `/search/q/${qStr}/type/${typeStr}/sort/${sortStr}/page/${page}`
     );
   }
 
@@ -493,9 +516,6 @@ export class Search extends Component<any, SearchState> {
       let data = res.data as SearchResponse;
       this.state.searchResponse = data;
       this.state.loading = false;
-      document.title = `${i18n.t('search')} - ${this.state.q} - ${
-        this.state.site.name
-      }`;
       window.scrollTo(0, 0);
       this.setState(this.state);
     } else if (res.op == UserOperation.CreateCommentLike) {
@@ -510,7 +530,6 @@ export class Search extends Component<any, SearchState> {
       let data = res.data as GetSiteResponse;
       this.state.site = data.site;
       this.setState(this.state);
-      document.title = `${i18n.t('search')} - ${data.site.name}`;
     }
   }
 }