Use VueX store for searching and better testabillity

This commit is contained in:
Grzegorz Leoniec 2019-02-19 12:30:02 +01:00
parent 01c470a36e
commit 61a00feb60
No known key found for this signature in database
GPG Key ID: 3AA43686D4EB1377
3 changed files with 125 additions and 67 deletions

View File

@ -88,7 +88,7 @@
</template>
<script>
import gql from 'graphql-tag'
// import gql from 'graphql-tag'
import { isEmpty } from 'lodash'
export default {
@ -102,20 +102,26 @@ export default {
type: String,
default: ''
},
results: {
type: Array,
default: () => []
},
delay: {
type: Number,
default: 700
default: 300
},
pending: {
type: Boolean,
default: false
}
},
data() {
return {
searchProcess: null,
isOpen: false,
inProgress: false,
lastSearchTerm: '',
unprocessedSearchInput: '',
searchValue: '',
results: []
searchValue: ''
}
},
computed: {
@ -124,7 +130,7 @@ export default {
return !isEmpty(this.lastSearchTerm)
},
emptyText() {
return this.isActive && !this.inProgress
return this.isActive && !this.pending
? this.$t('search.failed')
: this.$t('search.hint')
}
@ -141,40 +147,41 @@ export default {
}
},
methods: {
query(value) {
async query(value) {
if (isEmpty(value) || value.length < 3) {
this.results = []
this.clear()
return
}
this.inProgress = true
this.$apollo
.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 => {
this.results = res.data.findPosts || []
this.inProgress = false
})
this.$emit('search', value)
// this.pending = true
// this.$apollo
// .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 => {
// this.results = res.data.findPosts || []
// this.pending = false
// })
},
handleInput(e) {
clearTimeout(this.searchProcess)
@ -184,7 +191,7 @@ export default {
this.searchProcess = setTimeout(() => {
this.lastSearchTerm = value
this.query(value)
}, 300)
}, this.delay)
},
onFocus(e) {
clearTimeout(this.searchProcess)
@ -208,9 +215,7 @@ export default {
// console.log('res', this.unprocessedSearchInput)
// this.isOpen = false
clearTimeout(this.searchProcess)
// e.stopImmediatePropagation()
// e.preventDefault()
if (!this.inProgress) {
if (!this.pending) {
// this.lastSearchTerm = this.unprocessedSearchInput
this.query(this.unprocessedSearchInput)
}
@ -220,7 +225,7 @@ export default {
this.isOpen = false
this.searchValue = null
this.lastSearchTerm = null
this.results = []
this.$emit('clear')
}
}
}

View File

@ -11,18 +11,13 @@
</a>
</div>
<div class="main-navigation-center hc-navbar-search">
<!-- avoid querying for dev -- search-input
id="nav-search"
class="is-hidden-mobile"
:value="searchQuery"
:style="{ height: '100%' }"
@search="onSearch"
/ -->
<search-input
id="nav-search"
class="is-hidden-mobile"
:style="{ height: '100%' }"
@search="onSearch"
:delay="300"
:pending="quickSearchPending"
:results="quickSearchResults"
@clear="quickSearchClear"
@search="quickSearch"
/>
</div>
<div class="main-navigation-right">
@ -142,7 +137,9 @@ export default {
user: 'auth/user',
isLoggedIn: 'auth/isLoggedIn',
isModerator: 'auth/isModerator',
isAdmin: 'auth/isAdmin'
isAdmin: 'auth/isAdmin',
quickSearchResults: 'search/quickResults',
quickSearchPending: 'search/quickPending'
//-- avoid querying for dev -- searchQuery: 'search/query'
}),
routes() {
@ -186,21 +183,12 @@ export default {
}
return this.$route.path.indexOf(url) === 0
},
// #: Is executet at listener of DOM event "search" is triggered. Set by tag "search-input" above by '@search="onSearch"' is short of 'v-on:search="onSearch"'.
onSearch(value) {
//-- avoid querying for dev -- this.$store.commit('search/query', value)
quickSearch(value) {
this.$store.dispatch('search/quickSearch', { value })
},
quickSearchClear() {
this.$store.dispatch('search/quickClear')
}
// #: Used for "hc-dropdown" in Aplpha for mobile mode.
// opened() {
// // setTimeout(() => {
// this.mobileSearchVisible = true
// // }, 25)
// },
// closed() {
// // setTimeout(() => {
// this.mobileSearchVisible = false
// // }, 100)
// }
}
}
</script>

65
store/search.js Normal file
View File

@ -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', [])
}
}