From 8e7a9644c0014a03fdbd4cd557e40ab8cb57e3ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Sat, 8 Dec 2018 12:40:34 +0100 Subject: [PATCH 01/38] Split development config from production config in `docker-compose.yml` and `docker-compose.override.yml`. This should speed up builds e.g. on Travis CI, which does not need to sync folders or run `yarn run dev` if the docker image was built recently. Also it should make the build more reliable as it behaves more similar to our deployment. --- docker-compose.override.yml | 11 +++++++++++ docker-compose.yml | 8 ++------ 2 files changed, 13 insertions(+), 6 deletions(-) create mode 100644 docker-compose.override.yml diff --git a/docker-compose.override.yml b/docker-compose.override.yml new file mode 100644 index 000000000..1f35305b6 --- /dev/null +++ b/docker-compose.override.yml @@ -0,0 +1,11 @@ +version: '3.7' + +services: + webapp: + volumes: + - .:/HC-WebApp + - node_modules:/HC-WebApp/node_modules + command: yarn run dev + +volumes: + node_modules: diff --git a/docker-compose.yml b/docker-compose.yml index af6ad1cb7..f7c697889 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,17 +2,13 @@ version: '3.7' services: webapp: - build: - context: . + image: humanconnection/nitro-web:latest + build: . ports: - 3000:3000 - 8080:8080 networks: - hc-network - volumes: - - .:/HC-WebApp - - node_modules:/HC-WebApp/node_modules - command: yarn run dev environment: - HOST=0.0.0.0 - BACKEND_URL=http://backend:4000 From 7f389e493917ce1ef5f055d9e92e51dd3bd3a85a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20Sch=C3=A4fer?= Date: Sat, 8 Dec 2018 15:44:20 +0100 Subject: [PATCH 02/38] Fix wrong folder name --- docker-compose.override.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.override.yml b/docker-compose.override.yml index 1f35305b6..bf4d42841 100644 --- a/docker-compose.override.yml +++ b/docker-compose.override.yml @@ -3,8 +3,8 @@ version: '3.7' services: webapp: volumes: - - .:/HC-WebApp - - node_modules:/HC-WebApp/node_modules + - .:/nitro-web + - node_modules:/nitro-web/node_modules command: yarn run dev volumes: From 049fa2893bc571d17b072cb38e391e7b4cd1271b Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Wed, 30 Jan 2019 11:37:58 -0200 Subject: [PATCH 03/38] Write first cucumber scenario --- cypress/integration/06.Search.feature | 14 ++++++++++++++ package.json | 5 ++++- yarn.lock | 25 +++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 cypress/integration/06.Search.feature diff --git a/cypress/integration/06.Search.feature b/cypress/integration/06.Search.feature new file mode 100644 index 000000000..16078ede3 --- /dev/null +++ b/cypress/integration/06.Search.feature @@ -0,0 +1,14 @@ +Feature: Search + As a user + I would like to be able to search for specific words + In order to find related content + + Background: + Given we have the following posts in our database: + | Author | Title | Content | Slug | + | Brianna Wiest | 101 Essays that will change the way you think | 101 Essays, of course! | 101-essays | + + Scenario: Search for specific words + Given I am logged in as "user" + And I search for a specific word + Then I should posts with that word included diff --git a/package.json b/package.json index 78cbb1e30..8f7eabcf4 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,9 @@ "styleguide": "cd ./styleguide && yarn dev", "styleguide:build": "cd ./styleguide && yarn build:lib && cd ../", "test": "jest", - "precommit": "yarn lint" + "precommit": "yarn lint", + "e2e:local": "cypress run --headed", + "e2e:ci": "npm-run-all --parallel --race start:ci 'cypress:ci --config baseUrl=http://localhost:3000'" }, "cypress-cucumber-preprocessor": { "nonGlobalStepDefinitions": true @@ -46,6 +48,7 @@ "cross-env": "^5.2.0", "date-fns": "^2.0.0-alpha.26", "express": "^4.16.3", + "global": "^4.3.2", "graphql": "^14.1.1", "graphql-tag": "^2.10.1", "jsonwebtoken": "^8.3.0", diff --git a/yarn.lock b/yarn.lock index 240dc412c..2c7c086d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4548,6 +4548,11 @@ dom-serializer@0, dom-serializer@~0.1.0: domelementtype "~1.1.1" entities "~1.1.1" +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= + domain-browser@^1.1.1, domain-browser@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" @@ -5687,6 +5692,14 @@ global-dirs@^0.1.0: dependencies: ini "^1.3.4" +global@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" + integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8= + dependencies: + min-document "^2.19.0" + process "~0.5.1" + globals@^11.1.0, globals@^11.7.0: version "11.9.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.9.0.tgz#bde236808e987f290768a93d065060d78e6ab249" @@ -7777,6 +7790,13 @@ mimic-fn@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= + dependencies: + dom-walk "^0.1.0" + mini-css-extract-plugin@^0.4.5: version "0.4.5" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.4.5.tgz#c99e9e78d54f3fa775633aee5933aeaa4e80719a" @@ -9491,6 +9511,11 @@ process@^0.11.10, process@~0.11.0: resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= +process@~0.5.1: + version "0.5.2" + resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" + integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8= + progress@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.1.tgz#c9242169342b1c29d275889c95734621b1952e31" From f09d3ed6856dfc46cfe8ab84c0eb36d67d3300da Mon Sep 17 00:00:00 2001 From: Matt Rider Date: Sat, 2 Feb 2019 17:22:40 -0200 Subject: [PATCH 04/38] Write steps, start implemenation of search input component --- components/SearchInput.vue | 179 ++++++++++++++++++++++++++ cypress/integration/06.Search.feature | 4 +- cypress/integration/common/search.js | 11 ++ layouts/default.vue | 13 +- 4 files changed, 204 insertions(+), 3 deletions(-) create mode 100644 components/SearchInput.vue create mode 100644 cypress/integration/common/search.js diff --git a/components/SearchInput.vue b/components/SearchInput.vue new file mode 100644 index 000000000..b3c2b161b --- /dev/null +++ b/components/SearchInput.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/cypress/integration/06.Search.feature b/cypress/integration/06.Search.feature index 16078ede3..a3fc69dae 100644 --- a/cypress/integration/06.Search.feature +++ b/cypress/integration/06.Search.feature @@ -10,5 +10,5 @@ Feature: Search Scenario: Search for specific words Given I am logged in as "user" - And I search for a specific word - Then I should posts with that word included + When I search for a specific word + Then I should see posts with that word included diff --git a/cypress/integration/common/search.js b/cypress/integration/common/search.js new file mode 100644 index 000000000..af46becf0 --- /dev/null +++ b/cypress/integration/common/search.js @@ -0,0 +1,11 @@ +import { When, Then } from 'cypress-cucumber-preprocessor/steps' + +When('I search for a specific word', () => { + cy.get('#nav-search').type('Essays') +}) + +Then('I should see posts with that word included', () => { + cy.get('.ds-card-header:first').then(() => { + cy.title().should('include', 'Essays') + }) +}) diff --git a/layouts/default.vue b/layouts/default.vue index 7283bf308..4e33a1755 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -10,6 +10,9 @@ + @@ -38,6 +47,7 @@ export default { type: String, default: '' }, + // #: Delay after typing before calling a search query. delay: { type: Number, default: 700 @@ -50,7 +60,9 @@ export default { data() { return { searchValue: '', + // #: Returned ID value of the timer given by "setTimeout()". searchProcess: null, + // #!: Seems to be unused (unquestioned). searching: false } }, @@ -70,6 +82,7 @@ export default { this.updateValue() }, methods: { + // #: Sets "searchValue" same as "value" if they are different or sets "searchValue" to empty string if "value is undef". updateValue() { if (!this.value) { this.searchValue = '' @@ -78,6 +91,7 @@ export default { } }, onInput() { + // #: Prevent "setTimeout()" to call parameter function after "delay". clearTimeout(this.searchProcess) this.searching = true // skip on less then three letters @@ -88,25 +102,30 @@ export default { if (this.searchValue === this.value) { return } + // #: Calls function in first parameter after a delay of "this.delay" milliseconds. this.searchProcess = setTimeout(() => { this.searching = false - this.$emit('search', this.searchValue.toString()) + //-- avoid querying for dev -- this.$emit('search', this.searchValue.toString()) }, this.delay) }, onEnter() { + // #: Prevent "setTimeout()" to call parameter function after "delay". clearTimeout(this.searchProcess) + // #: "Vue.nextTick()": Defer the callback to be executed after the next DOM update cycle. this.$nextTick(() => { + // #: Prevent "setTimeout()" to call parameter function after "delay". clearTimeout(this.searchProcess) }) this.searching = false - this.$emit('search', this.searchValue.toString()) + //-- avoid querying for dev -- this.$emit('search', this.searchValue.toString()) }, clear() { + // #: Prevent "setTimeout()" to call parameter function after "delay". clearTimeout(this.searchProcess) this.searching = false this.searchValue = '' if (this.value !== this.searchValue) { - this.$emit('search', '') + //-- avoid querying for dev -- this.$emit('search', '') } } } diff --git a/layouts/default.vue b/layouts/default.vue index 4e33a1755..96aaf9d33 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -11,7 +11,19 @@ diff --git a/layouts/default.vue b/layouts/default.vue index 96aaf9d33..5ef77c4fc 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -219,17 +219,20 @@ export default { .main-navigation-left { display: flex; - margin-right: auto; + // margin-right: auto; + margin-right: 40px; } .main-navigation-center { display: flex; - margin-right: auto; + // margin-right: auto; + width: 100%; } .main-navigation-right { display: flex; - margin-left: auto; + // margin-left: auto; + margin-left: 40px; } .avatar-menu-trigger { From 780ff65254b4bf0fb32b70940159e35f515549eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Sat, 16 Feb 2019 12:40:47 +0100 Subject: [PATCH 09/38] Add 'times-circle' as right icon to search etc. --- .gitignore | 3 ++ components/SearchInput.vue | 39 +++++++------------ locales/de.json | 2 +- locales/en.json | 2 +- .../src/system/icons/svg/times-circle.svg | 5 +++ 5 files changed, 24 insertions(+), 27 deletions(-) create mode 100644 styleguide/src/system/icons/svg/times-circle.svg diff --git a/.gitignore b/.gitignore index 0de8272fc..292c993d3 100644 --- a/.gitignore +++ b/.gitignore @@ -79,3 +79,6 @@ static/uploads cypress/videos cypress/screenshots/ + +# Apple macOS folder attribute file +.DS_Store diff --git a/components/SearchInput.vue b/components/SearchInput.vue index d9cd21290..9f5a8e293 100644 --- a/components/SearchInput.vue +++ b/components/SearchInput.vue @@ -6,19 +6,19 @@ :class="{ 'is-active': isActive }" >
-
+
@@ -43,22 +43,20 @@ export default { delay: { type: Number, default: 700 - }, - focus: { - type: Boolean, - default: false } }, data() { return { + // #: Bind to input text. searchValue: '', // #: Returned ID value of the timer given by "setTimeout()". searchProcess: null, // #!: Seems to be unused (unquestioned). - searching: false + typing: false } }, computed: { + // #: Unused at the moment? isActive() { return !isEmpty(this.searchValue) } @@ -82,10 +80,10 @@ export default { this.searchValue = this.value.toString() } }, - onInput() { + handleInput() { // #: Prevent "setTimeout()" to call parameter function after "delay". clearTimeout(this.searchProcess) - this.searching = true + this.typing = true // skip on less then three letters if (this.searchValue && this.searchValue.toString().length < 3) { return @@ -96,7 +94,7 @@ export default { } // #: Calls function in first parameter after a delay of "this.delay" milliseconds. this.searchProcess = setTimeout(() => { - this.searching = false + this.typing = false //-- avoid querying for dev -- this.$emit('search', this.searchValue.toString()) }, this.delay) }, @@ -108,13 +106,14 @@ export default { // #: Prevent "setTimeout()" to call parameter function after "delay". clearTimeout(this.searchProcess) }) - this.searching = false + this.typing = false //-- avoid querying for dev -- this.$emit('search', this.searchValue.toString()) + console.log('Enter !!!!') }, clear() { // #: Prevent "setTimeout()" to call parameter function after "delay". clearTimeout(this.searchProcess) - this.searching = false + this.typing = false this.searchValue = '' if (this.value !== this.searchValue) { //-- avoid querying for dev -- this.$emit('search', '') @@ -187,14 +186,4 @@ export default { color: hsl(0, 0%, 71%); } } - -.input, -.has-icons-left, -.has-icons-right { - .icon, - i { - // color: lighten($grey-light, 15%); - transition: color 150ms ease-out !important; - } -} diff --git a/locales/de.json b/locales/de.json index 8ae7373c9..ae7cb46da 100644 --- a/locales/de.json +++ b/locales/de.json @@ -26,7 +26,7 @@ "commented": "Kommentiert" }, "search": { - "placeholder": "Suchen …" + "placeholder": "Suchen" }, "settings": { "name": "Einstellungen", diff --git a/locales/en.json b/locales/en.json index 611a4a1e0..2bf0affc2 100644 --- a/locales/en.json +++ b/locales/en.json @@ -26,7 +26,7 @@ "commented": "Commented" }, "search": { - "placeholder": "Search …" + "placeholder": "Search" }, "settings": { "name": "Settings", diff --git a/styleguide/src/system/icons/svg/times-circle.svg b/styleguide/src/system/icons/svg/times-circle.svg new file mode 100644 index 000000000..acf70ce3b --- /dev/null +++ b/styleguide/src/system/icons/svg/times-circle.svg @@ -0,0 +1,5 @@ + + +times-circle + + From 5410fd1df99fbe234960126f5407d459d26a1ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wolfgang=20Hu=C3=9F?= Date: Sat, 16 Feb 2019 17:29:08 +0100 Subject: [PATCH 10/38] Add functionality that times-circle disapears if no text in input --- components/SearchInput.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/SearchInput.vue b/components/SearchInput.vue index 9f5a8e293..5dab89177 100644 --- a/components/SearchInput.vue +++ b/components/SearchInput.vue @@ -15,7 +15,7 @@ name="search" type="search" icon="search" - icon-right="times-circle" + :icon-right="isActive ? 'times-circle' : null" :placeholder="$t('search.placeholder')" @input="handleInput" @keyup.native.enter="onEnter" From 34a863424bf0c96236a9f29e33d7c129b40e02c5 Mon Sep 17 00:00:00 2001 From: Grzegorz Leoniec Date: Tue, 19 Feb 2019 10:37:31 +0100 Subject: [PATCH 11/38] Show search results while typing --- components/SearchInput.vue | 338 ++++++++++++------ locales/de.json | 4 +- locales/en.json | 4 +- pages/post/_slug/index.vue | 8 +- .../components/data-input/Select/Select.vue | 50 ++- 5 files changed, 282 insertions(+), 122 deletions(-) diff --git a/components/SearchInput.vue b/components/SearchInput.vue index 5dab89177..6fa761b1e 100644 --- a/components/SearchInput.vue +++ b/components/SearchInput.vue @@ -3,11 +3,21 @@ class="search" aria-label="search" role="search" - :class="{ 'is-active': isActive }" + :class="{ + 'is-active': isActive, + 'is-open': isOpen + }" >
- +   + + + @keypress.enter.prevent.stop.self="onEnter" + @focus.capture.native="onFocus" + @blur.capture.native="onBlur" + @keyup.delete.native="onDelete" + @keyup.esc.native="clear" + @input.native="handleInput" + @click.capture.native="isOpen = true" + > + +
- diff --git a/locales/de.json b/locales/de.json index ae7cb46da..976b39906 100644 --- a/locales/de.json +++ b/locales/de.json @@ -26,7 +26,9 @@ "commented": "Kommentiert" }, "search": { - "placeholder": "Suchen" + "placeholder": "Suchen", + "hint": "Wonach suchst du?", + "failed": "Nichts gefunden" }, "settings": { "name": "Einstellungen", diff --git a/locales/en.json b/locales/en.json index 2bf0affc2..f4261de61 100644 --- a/locales/en.json +++ b/locales/en.json @@ -26,7 +26,9 @@ "commented": "Commented" }, "search": { - "placeholder": "Search" + "placeholder": "Search", + "hint": "What are you searching for?", + "failed": "Nothing found" }, "settings": { "name": "Settings", diff --git a/pages/post/_slug/index.vue b/pages/post/_slug/index.vue index 200a9f472..330d2e38b 100644 --- a/pages/post/_slug/index.vue +++ b/pages/post/_slug/index.vue @@ -156,7 +156,10 @@ export default { }, watch: { Post(post) { - this.post = post[0] + this.post = post[0] || {} + // if (!this.post.title) { + // throw new Error('404') + // } this.title = this.post.title } }, @@ -194,7 +197,7 @@ export default { name } commentsCount - comments(orderBy: createdAt_desc) { + comments(first: 20, orderBy: createdAt_desc) { id contentExcerpt createdAt @@ -233,6 +236,7 @@ export default { slug: this.$route.params.slug } }, + prefetch: true, fetchPolicy: 'cache-and-network' } } diff --git a/styleguide/src/system/components/data-input/Select/Select.vue b/styleguide/src/system/components/data-input/Select/Select.vue index 382e328d1..11753031a 100755 --- a/styleguide/src/system/components/data-input/Select/Select.vue +++ b/styleguide/src/system/components/data-input/Select/Select.vue @@ -111,8 +111,9 @@ v-else-if="!filteredOptions.length"> {{ noOptionsFound }} "{{ searchString }}" -
  • - + @@ -224,6 +225,21 @@ export default { type: Boolean, default: true }, + /** + * Function to filter the results + */ + filter: { + type: Function, + default: (option) => { + const value = option.value || option + return searchParts.every(part => { + if (!part) { + return true + } + return value.toLowerCase().includes(part.toLowerCase()) + }) + } + }, /** * Message to show when no options are available */ @@ -246,15 +262,7 @@ export default { } const searchParts = this.searchString.split(' ') - return this.options.filter(option => { - const value = option.value || option - return searchParts.every(part => { - if (!part) { - return true - } - return value.toLowerCase().includes(part.toLowerCase()) - }) - }) + return this.options.filter(this.filter) }, pointerMax() { return this.filteredOptions.length - 1 @@ -327,7 +335,9 @@ export default { this.pointerNext() }, setPointer(index) { - this.pointer = index + if (!this.hadKeyboardInput) { + this.pointer = index + } }, pointerPrev() { if (this.pointer === 0) { @@ -335,6 +345,7 @@ export default { } else { this.pointer-- } + this.scrollToHighlighted() }, pointerNext() { if (this.pointer === this.pointerMax) { @@ -342,6 +353,19 @@ export default { } else { this.pointer++ } + this.scrollToHighlighted() + }, + scrollToHighlighted() { + clearTimeout(this.hadKeyboardInput) + if (!this.$refs.options || !this.$refs.options.children.length) { + return + } + this.hadKeyboardInput = setTimeout(() => { + this.hadKeyboardInput = null + }, 250) + this.$refs.options.children[this.pointer].scrollIntoView({ + block: 'nearest' + }); }, selectPointerOption() { this.handleSelect(this.filteredOptions[this.pointer]) From f867b53e64dd0e929ad022b6cf742c87c33b5770 Mon Sep 17 00:00:00 2001 From: Grzegorz Leoniec Date: Tue, 19 Feb 2019 12:02:20 +0100 Subject: [PATCH 12/38] Small cleanup --- pages/post/_slug/index.vue | 3 --- 1 file changed, 3 deletions(-) diff --git a/pages/post/_slug/index.vue b/pages/post/_slug/index.vue index 330d2e38b..cec33b0c0 100644 --- a/pages/post/_slug/index.vue +++ b/pages/post/_slug/index.vue @@ -157,9 +157,6 @@ export default { watch: { Post(post) { this.post = post[0] || {} - // if (!this.post.title) { - // throw new Error('404') - // } this.title = this.post.title } }, From 01c470a36e974a92c5eb6d78e8817ee385d7e2cd Mon Sep 17 00:00:00 2001 From: Grzegorz Leoniec Date: Tue, 19 Feb 2019 12:03:05 +0100 Subject: [PATCH 13/38] Removed times-circle.svg --- styleguide/src/system/icons/svg/times-circle.svg | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 styleguide/src/system/icons/svg/times-circle.svg diff --git a/styleguide/src/system/icons/svg/times-circle.svg b/styleguide/src/system/icons/svg/times-circle.svg deleted file mode 100644 index acf70ce3b..000000000 --- a/styleguide/src/system/icons/svg/times-circle.svg +++ /dev/null @@ -1,5 +0,0 @@ - - -times-circle - - From 61a00feb60409b8f9b28cc6bb721dc1d0ae68bb2 Mon Sep 17 00:00:00 2001 From: Grzegorz Leoniec Date: Tue, 19 Feb 2019 12:30:02 +0100 Subject: [PATCH 14/38] Use VueX store for searching and better testabillity --- components/SearchInput.vue | 89 ++++++++++++++++++++------------------ layouts/default.vue | 38 ++++++---------- store/search.js | 65 ++++++++++++++++++++++++++++ 3 files changed, 125 insertions(+), 67 deletions(-) create mode 100644 store/search.js diff --git a/components/SearchInput.vue b/components/SearchInput.vue index 6fa761b1e..1b59d9941 100644 --- a/components/SearchInput.vue +++ b/components/SearchInput.vue @@ -88,7 +88,7 @@ diff --git a/store/search.js b/store/search.js new file mode 100644 index 000000000..a14f2c878 --- /dev/null +++ b/store/search.js @@ -0,0 +1,65 @@ +import gql from 'graphql-tag' + +export const state = () => { + return { + quickResults: [], + quickPending: false + } +} + +export const mutations = { + SET_QUICK_RESULTS(state, results) { + state.quickResults = results || [] + }, + SET_QUICK_PENDING(state, pending) { + state.quickPending = pending + } +} + +export const getters = { + quickResults(state) { + return state.quickResults + }, + quickPending(state) { + return state.quickPending + } +} + +export const actions = { + async quickSearch({ commit, getters }, { value }) { + commit('SET_QUICK_PENDING', true) + await this.app.apolloProvider.defaultClient + .query({ + query: gql(` + query findPosts($filter: String!) { + findPosts(filter: $filter, limit: 10) { + id + slug + label: title + value: title, + shoutedCount + commentsCount + createdAt + author { + id + name + slug + } + } + } + `), + variables: { + filter: value + } + }) + .then(res => { + commit('SET_QUICK_RESULTS', res.data.findPosts || []) + commit('SET_QUICK_PENDING', false) + }) + return getters.quickResults + }, + async quickClear({ commit }) { + commit('SET_QUICK_PENDING', false) + commit('SET_QUICK_RESULTS', []) + } +} From 33cc5d5982c87993bae631680fd043d940374c03 Mon Sep 17 00:00:00 2001 From: Grzegorz Leoniec Date: Tue, 19 Feb 2019 12:42:51 +0100 Subject: [PATCH 15/38] Store last search value in store --- store/search.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/store/search.js b/store/search.js index a14f2c878..5402b9b79 100644 --- a/store/search.js +++ b/store/search.js @@ -1,9 +1,11 @@ import gql from 'graphql-tag' +import isString from 'lodash/isString' export const state = () => { return { quickResults: [], - quickPending: false + quickPending: false, + quickValue: '' } } @@ -13,6 +15,9 @@ export const mutations = { }, SET_QUICK_PENDING(state, pending) { state.quickPending = pending + }, + SET_QUICK_VALUE(state, value) { + state.quickValue = value } } @@ -22,11 +27,20 @@ export const getters = { }, quickPending(state) { return state.quickPending + }, + quickValue(state) { + return state.quickValue } } export const actions = { async quickSearch({ commit, getters }, { value }) { + value = isString(value) ? value.trim() : '' + const lastVal = getters.quickValue + if (value.length < 3 || lastVal.toLowerCase() === value.toLowerCase()) { + return + } + commit('SET_QUICK_VALUE', value) commit('SET_QUICK_PENDING', true) await this.app.apolloProvider.defaultClient .query({ @@ -61,5 +75,6 @@ export const actions = { async quickClear({ commit }) { commit('SET_QUICK_PENDING', false) commit('SET_QUICK_RESULTS', []) + commit('SET_QUICK_VALUE', '') } } From 58cef3ec2162b32062296bb5435625e5dc065b0a Mon Sep 17 00:00:00 2001 From: Grzegorz Leoniec Date: Tue, 19 Feb 2019 12:58:03 +0100 Subject: [PATCH 16/38] Fixed search --- layouts/default.vue | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/layouts/default.vue b/layouts/default.vue index 54a1c011d..f5f8039fb 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -17,7 +17,7 @@ :pending="quickSearchPending" :results="quickSearchResults" @clear="quickSearchClear" - @search="quickSearch" + @search="value => quickSearch({ value })" />