From 93bda14a25a4fd971cdf660deefe4975dd2da779 Mon Sep 17 00:00:00 2001 From: "Henrik.Askjer" <henrik.askjer@uib.no> Date: Mon, 30 Aug 2021 11:47:20 +0200 Subject: [PATCH] Replace suggestion api --- src/components/Autocomplete.vue | 104 ++++++++++++++++++------------ src/components/DictionaryView.vue | 12 +++- 2 files changed, 71 insertions(+), 45 deletions(-) diff --git a/src/components/Autocomplete.vue b/src/components/Autocomplete.vue index 300ec15a..4140eb89 100644 --- a/src/components/Autocomplete.vue +++ b/src/components/Autocomplete.vue @@ -26,7 +26,10 @@ :dense="$vuetify.breakpoint.smAndDown" > <template v-slot:item="data"> - <span class="search-hit">{{data.item.label}} </span> ({{data.item.lang_set ? Array.from(data.item.lang_set).sort().join(', ') : 'fritekstsøk'}}) + <span class="search-hit"> + {{data.item.label}} + </span> + ({{data.item.lang? data.item.lang[1] ? "bm, nn" : {"bob": "bm", "nob": "nn"}[data.item.lang[0]] : 'fritekstsøk'}}) </template> </v-combobox> </div> @@ -49,44 +52,26 @@ suggesting: null, debounced: debounce(function(q, self) { self.loading = true - return axios.get(self.endpoint + 'suggest?q=' + encodeURIComponent(q)) + return axios.get(self.endpoint + 'suggest?', { params: {q: q, + dict: self.$parent.lang, + n: 9}} ) .then( function(response) { - if (self.suggesting) { - let hits = [] - if (q == self.$refs.autocomplete.searchInput) { + if (self.$refs.autocomplete.searchInput == q & self.suggesting) { + + let hits = [] response.data.forEach((item, i) => { - let match = encodeURIComponent(item.match) + let hit = {q: q, match: item[0], label: item[0], articles: []} + hit.lang = item[1] + hits.push(hit) - if (! hits[0] || hits[0].word != match) { - hits.splice(0, 0, {q: encodeURIComponent(q), lang_set: new Set(), word: match, articles: []}) - } - hits[0].lang_set.add(item.dictionary == 'bob' ? 'bm' : 'nn') - hits[0].articles.push(item) - }); - hits.forEach(function (hit) { - if (hit.lang_set) { - hit.label = decodeURIComponent(hit.word) - } }); - hits.reverse() - hits = hits.slice(0, 9) - - hits.sort( (h1, h2) => { - let val1 = h1.label.length * 10 + (h1.label[0].toLowerCase() === h1.label[0] ? 0 : 1) - let val2 = h2.label.length * 10 + (h2.label[0].toLowerCase() === h2.label[0] ? 0 : 1) - return val1 - val2 - - }) - let currentSearch = self.$refs.autocomplete.searchInput - if (q == currentSearch) { + // whitespace necessary because duplicates aren't allowed in the dropdown + hits.push({q: q, label: q + ' '}) self.items = hits } - self.items.push({currentSearch: encodeURIComponent(currentSearch), label: currentSearch + ' '}) - - } - } - self.loading = false + + self.loading = false }) }, 100) } @@ -101,24 +86,59 @@ }, select(item) { if (item) { - if (typeof item === 'string') { - item = {"q": encodeURIComponent(item)} - } - this.items = [] - this.suggesting = false + if (typeof item != 'string') { + let self = this + if (item.articles) { + axios.get(self.endpoint + 'articles?', {params: {lord: item.match, + dict: self.$parent.lang}}) + .then( + function(response) { + ['bob', 'nob'].forEach((dict_tag) => { + response.data[dict_tag].forEach((article_id) => { + let article = {} + article.article_id = article_id + article.dictionary = dict_tag + article.match = item.match + item.articles.push(article) + }) + }) + } + ) + } + this.items = [] + this.suggesting = false + + self.$emit('submit', item) - this.$emit('submit', item) - let self = this - setTimeout(() => self.$refs.autocomplete.$refs.input.select(), 1) + setTimeout(() => { + self.$refs.autocomplete.$refs.input.select() + this.items = [] + this.suggesting = false + }, 1) + + } + // If blurred + else { + this.items = [] + } } } }, methods: { run_query(q) { - this.items = [] this.suggesting = true + // Put full text search in the list while processing suggestions + if (this.items[0]) { + if (this.items[0].lang) { + this.items.unshift({q: q, label: q}) + } + else { + this.items[0] = {q: q, label: q} + } + } this.debounced(q, this) - } + }, + }, } </script> diff --git a/src/components/DictionaryView.vue b/src/components/DictionaryView.vue index a4509ad4..6182d3b0 100644 --- a/src/components/DictionaryView.vue +++ b/src/components/DictionaryView.vue @@ -29,7 +29,7 @@ </v-radio> </v-radio-group> </div> - <Autocomplete @submit="select_result" :endpoint="api_pref"> + <Autocomplete @submit="select_result" :endpoint="oda_endpoint"> </Autocomplete> </div> <div id="spinner" v-if="waiting"> @@ -74,6 +74,7 @@ import SearchResults from './SearchResults.vue' import Autocomplete from './Autocomplete.vue' var api_endpoint = process.env.VUE_APP_API_PREFIX + '/api/dict' +const oda_endpoint = 'https://oda.uib.no/opal-api/' function compare_by_hgno(lemma_text) { return function(art1, art2) { @@ -188,6 +189,9 @@ export default { }, api_pref: function() { return api_endpoint + '/' + this.lang + '/article/' + }, + oda_endpoint: function() { + return oda_endpoint } }, components: { @@ -199,12 +203,14 @@ export default { select_result: function(event) { this.event = event if(event.articles){ - let source = '/' + this.lang + '/w/' + event.word + let source = '/' + this.lang + '/w/' + event.match this.$router.push(source) - this.search_results = event.articles.sort(compare_by_hgno(decodeURIComponent(event.word))).map(a => Object.assign(a, {source: source})) + this.search_results = event.articles.map(a => Object.assign(a, {source: source})) this.article = null this.error = null + this.waiting_for_articles = true history.replaceState({article: this.article, search_results: this.search_results, lang: this.lang, error: this.error}, '') + navigate_to_word(this, event.match) this.$plausible.trackEvent('dropdown selection', {props: {query: event.label, match: event.match}}) }else{ this.waiting_for_articles = true -- GitLab