From 3c3c14b04e5b57ed998babbaaed4493416ed794f Mon Sep 17 00:00:00 2001 From: riggraz Date: Thu, 5 Sep 2019 17:11:07 +0200 Subject: [PATCH] Add search to post list --- app/controllers/posts_controller.rb | 7 +++-- .../components/Board/SearchFilter.tsx | 20 +++++++++++++ app/javascript/components/Board/index.tsx | 29 +++++++++++++++---- app/javascript/helpers/debounce.js | 4 +++ app/models/post.rb | 6 ++++ 5 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 app/javascript/components/Board/SearchFilter.tsx create mode 100644 app/javascript/helpers/debounce.js diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 21830286..838a5a45 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -6,6 +6,7 @@ class PostsController < ApplicationController .left_outer_joins(:post_status) .select('posts.title, posts.description, post_statuses.name as post_status_name, post_statuses.color as post_status_color') .where(filter_params) + .search(params[:search]) .page(params[:page]) render json: posts @@ -26,12 +27,12 @@ class PostsController < ApplicationController private def filter_params - defaults = { board_id: Board.first.id, page: 1 } + defaults = { board_id: Board.first.id } params - .permit(:board_id, :post_status_id, :page) + .permit(:board_id, :post_status_id, :page, :search) .with_defaults(defaults) - .except(:page) # do not return page param + .except(:page, :search) # permit, but do not return page and search params end def post_params diff --git a/app/javascript/components/Board/SearchFilter.tsx b/app/javascript/components/Board/SearchFilter.tsx new file mode 100644 index 00000000..a9b9d958 --- /dev/null +++ b/app/javascript/components/Board/SearchFilter.tsx @@ -0,0 +1,20 @@ +import * as React from 'react'; + +interface Props { + searchQuery: string; + handleChange(newSearchQuery: string): void; +} + +const SearchFilter = ({ searchQuery, handleChange }: Props) => ( +
+ + handleChange(e.target.value)} + id="searchPostInput" + className="form-control" + /> +
+); + +export default SearchFilter; \ No newline at end of file diff --git a/app/javascript/components/Board/index.tsx b/app/javascript/components/Board/index.tsx index 987e7645..a1f06e5c 100644 --- a/app/javascript/components/Board/index.tsx +++ b/app/javascript/components/Board/index.tsx @@ -1,6 +1,7 @@ import * as React from 'react'; import NewPost from './NewPost'; +import SearchFilter from './SearchFilter'; import PostStatusFilter from './PostStatusFilter'; import PostList from './PostList'; @@ -8,6 +9,8 @@ import IBoard from '../../interfaces/IBoard'; import IPost from '../../interfaces/IPost'; import IPostStatus from '../../interfaces/IPostStatus'; +import debounce from '../../helpers/debounce.js'; + import '../../stylesheets/components/Board.scss'; interface Props { @@ -19,6 +22,7 @@ interface Props { interface State { filters: { byPostStatus: number; + searchQuery: string; }; posts: { items: Array; @@ -42,6 +46,7 @@ class Board extends React.Component { this.state = { filters: { byPostStatus: 0, + searchQuery: '', }, posts: { items: [], @@ -61,8 +66,9 @@ class Board extends React.Component { this.requestPosts = this.requestPosts.bind(this); this.loadMorePosts = this.loadMorePosts.bind(this); this.requestPostStatuses = this.requestPostStatuses.bind(this); - this.setPostStatusFilter = this.setPostStatusFilter.bind(this); + this.setSearchFilter = this.setSearchFilter.bind(this); + this.setPostStatusFilter = this.setPostStatusFilter.bind(this); } componentDidMount() { @@ -82,12 +88,13 @@ class Board extends React.Component { }); const boardId = this.props.board.id; - const { byPostStatus } = this.state.filters; + const { byPostStatus, searchQuery } = this.state.filters; let params = ''; params += `page=${page}`; params += `&board_id=${boardId}`; if (byPostStatus) params += `&post_status_id=${byPostStatus}`; + if (searchQuery) params += `&search=${searchQuery}`; try { let res = await fetch(`/posts?${params}`); @@ -137,9 +144,17 @@ class Board extends React.Component { } } + setSearchFilter(searchQuery: string) { + debounce(() => ( + this.setState({ + filters: { ...this.state.filters, searchQuery }, + }, this.requestPosts) + ), 1000)(); + } + setPostStatusFilter(postStatusId: number) { this.setState({ - filters: { byPostStatus: postStatusId }, + filters: { ...this.state.filters, byPostStatus: postStatusId }, }, this.requestPosts); } @@ -172,7 +187,7 @@ class Board extends React.Component { render() { const { board, isLoggedIn, authenticityToken } = this.props; - const { posts, postStatuses } = this.state; + const { posts, postStatuses, filters } = this.state; return (
@@ -182,13 +197,17 @@ class Board extends React.Component { isLoggedIn={isLoggedIn} authenticityToken={authenticityToken} /> +