From e2be492667febcb5fecdbcac9d97a42977370d6f Mon Sep 17 00:00:00 2001 From: LordMathis Date: Sat, 11 Jan 2020 15:51:14 +0100 Subject: [PATCH] Working implementation of text search --- package.json | 1 + src/components/Blog.js | 41 ++++++++++++++++++++++----- src/components/SearchBox.js | 18 ++++++++++-- src/components/SearchBox.scss | 6 ++-- src/containers/BlogContainer.js | 50 +++++++++++++++++++++++++++++++-- src/stylesheets/globals.scss | 4 +++ src/utils/serverRender.js | 19 +++++++------ yarn.lock | 16 ++++++++++- 8 files changed, 131 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 6bcf455..c6e7054 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "license": "MIT", "dependencies": { "async": "^3.1.0", + "axios": "^0.19.1", "chokidar": "^3.3.0", "express": "^4.13.4", "express-static-gzip": "^2.0.5", diff --git a/src/components/Blog.js b/src/components/Blog.js index 8a5417d..03a5c9f 100644 --- a/src/components/Blog.js +++ b/src/components/Blog.js @@ -10,8 +10,13 @@ export default class Blog extends Component { static propTypes = { isLoading: PropTypes.bool.isRequired, posts: PropTypes.arrayOf(PropTypes.object).isRequired, - searchString: PropTypes.string.isRequired, - handleChange: PropTypes.func.isRequired + searchString: PropTypes.string, + expanded: PropTypes.bool.isRequired, + handleChange: PropTypes.func.isRequired, + handleFocus: PropTypes.func.isRequired, + handleBlur: PropTypes.func.isRequired, + handleEnter: PropTypes.func.isRequired, + handleSearch: PropTypes.func.isRequired } render () { @@ -19,8 +24,17 @@ export default class Blog extends Component { if (this.props.isLoading) { return ( -
- +
+
+
+ +
+
) } @@ -28,7 +42,7 @@ export default class Blog extends Component { const posts = this.props.posts.sort((a, b) => { return new Date(b.published) - new Date(a.published) }) - const postsHTML = posts.map((post) => + let postsHTML = posts.map((post) =>
{post.title} @@ -39,16 +53,29 @@ export default class Blog extends Component {
) + if (postsHTML.length < 1) { + postsHTML = ( +
+ No posts found +
+ ) + } + return (
- +
{postsHTML}
-
) } diff --git a/src/components/SearchBox.js b/src/components/SearchBox.js index b67e55e..d383472 100644 --- a/src/components/SearchBox.js +++ b/src/components/SearchBox.js @@ -6,14 +6,26 @@ import styles from './SearchBox.scss' export default class SearchBox extends Component { static propTypes = { handleChange: PropTypes.func.isRequired, - searchString: PropTypes.string + handleFocus: PropTypes.func.isRequired, + handleBlur: PropTypes.func.isRequired, + handleEnter: PropTypes.func.isRequired, + handleSearch: PropTypes.func.isRequired, + searchString: PropTypes.string, + expanded: PropTypes.bool.isRequired } render () { return (
- - + +
diff --git a/src/components/SearchBox.scss b/src/components/SearchBox.scss index d88a738..83258b5 100644 --- a/src/components/SearchBox.scss +++ b/src/components/SearchBox.scss @@ -21,8 +21,10 @@ transition: width 0.4s ease; outline: none; box-sizing: border-box; - - &:focus{ width: 300px; } +} + +.expanded { + width: 300px; } .icon{ diff --git a/src/containers/BlogContainer.js b/src/containers/BlogContainer.js index 574e4fa..3e2f1ff 100644 --- a/src/containers/BlogContainer.js +++ b/src/containers/BlogContainer.js @@ -1,6 +1,7 @@ import React, { Component } from 'react' import { Blog } from '../components' import PropTypes from 'prop-types' +import axios from 'axios' import '../stylesheets/globals.scss' export default class BlogContainer extends Component { @@ -13,7 +14,8 @@ export default class BlogContainer extends Component { this.state = { isLoading: false, posts: props.posts, - searchString: '' + searchString: '', + expanded: false } } @@ -21,9 +23,53 @@ export default class BlogContainer extends Component { this.setState({ searchString: event.target.value }) } + handleFocus () { + this.setState({ expanded: true }) + } + + handleBlur () { + this.setState({ expanded: false }) + } + + handleEnter (event) { + if (event.key === 'Enter') { + this.handleSearch() + } + } + + handleSearch () { + if (this.state.expanded && this.state.searchString) { + this.search() + } else { + this.setState({ expanded: true }) + } + } + + search () { + this.setState({ + isLoading: true + }, () => { + axios.get(`/api/v1/posts?search=${this.state.searchString}`) + .then((data) => { + this.setState({ + isLoading: false, + posts: data.data + }) + }) + }) + } + render () { return ( - + ) } } diff --git a/src/stylesheets/globals.scss b/src/stylesheets/globals.scss index 7a6923e..ee3de26 100644 --- a/src/stylesheets/globals.scss +++ b/src/stylesheets/globals.scss @@ -16,3 +16,7 @@ font-family: $font-header; } } + +@-ms-viewport{ + width: device-width; +} diff --git a/src/utils/serverRender.js b/src/utils/serverRender.js index 7b9bc2a..c7d3248 100644 --- a/src/utils/serverRender.js +++ b/src/utils/serverRender.js @@ -50,15 +50,16 @@ function renderFullPage (html, head, data, config) { ${config.title} - - - - - - - - - ${head.scripts.join('\n')} + + + + + + + + + + ${head.scripts.join('\n')}
${html}
diff --git a/yarn.lock b/yarn.lock index c5b1bc0..f42a2b4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1222,6 +1222,13 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.0.tgz#24390e6ad61386b0a747265754d2a17219de862c" integrity sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A== +axios@^0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.1.tgz#8a6a04eed23dfe72747e1dd43c604b8f1677b5aa" + integrity sha512-Yl+7nfreYKaLRvAvjNPkvfjnQHJM1yLBY3zhqAwcJSwR/6ETkanUgylgtIvkvz0xJ+p/vZuNw8X7Hnb7Whsbpw== + dependencies: + follow-redirects "1.5.10" + babel-eslint@^10.0.1: version "10.0.3" resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.3.tgz#81a2c669be0f205e19462fed2482d33e4687a88a" @@ -2352,7 +2359,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: dependencies: ms "2.0.0" -debug@3.1.0: +debug@3.1.0, debug@=3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== @@ -3228,6 +3235,13 @@ flush-write-stream@^1.0.0: inherits "^2.0.3" readable-stream "^2.3.6" +follow-redirects@1.5.10: + version "1.5.10" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" + integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== + dependencies: + debug "=3.1.0" + for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"