Newer
Older
<div class="search_container">
<div class="lang_select_container">
<v-radio-group row v-model="lang" @change="update_lang_form">
<template v-slot:label tabindex="1">
<span aria-label="Vis resultat i begge ordbøkene eller bruk radioknapp for bokmålsordboka eller radioknapp for nynorskordboka">VIS</span>
begge{{$vuetify.breakpoint.smAndDown ? '' : ' ordbøkene'}}
{{$vuetify.breakpoint.xs ? 'bm' : 'bokmål (bm)'}}
{{$vuetify.breakpoint.xs ? 'nn' : 'nynorsk (nn)'}}
</template>
</v-radio>
</v-radio-group>
</div>
<Autocomplete v-on:submit="select_result" :api="get_search_endpoint">
<div id="spinner" v-if="waiting">
<v-progress-circular indeterminate color="secondary" size="120"></v-progress-circular>
<SearchResults :hits="search_results"
:lang="lang"
@article-click="article_link_click"
@details-click="details_click"
v-if="search_results.length && ! waiting && ! article" />
<div class="return_to_results" v-if="search_results && search_results.length">
<router-link :to="article.source" @click.native="return_to_results()">
<v-icon class="nav_arrow">arrow_left</v-icon>Tilbake til {{article.dictionary == 'bob' ? 'søkeresultater' : 'søkjeresultat'}}
</router-link>
</div>
<Article :key="article_key" :article="article" @article-click="article_link_click" />
</div>
<div class="welcome" v-if="! (article || error || search_results.length || waiting)">
<div class="monthly" :class="$vuetify.breakpoint.name">
<div>
<Article :article="monthly_bm" @article-click="article_link_click" />
</div>
<div>
<Article :article="monthly_nn" @article-click="article_link_click" />
</div>
</div>
</div>
<p v-if="error[0]">{{error[0]}}</p>
<p v-if="error[1]">{{error[1]}}</p>
</main>
</template>
<script>
import axios from "axios"
import entities from '../utils/entities.js'
import Article from './Article.vue'
import SearchResults from './SearchResults.vue'
import Autocomplete from './Autocomplete.vue'
const SEARCH_ENDPOINT = process.env.VUE_APP_SEARCH_ENDPOINT
const ARTICLE_ENDPOINT= process.env.VUE_APP_ARTICLE_ENDPOINT
const API_STAGE = process.env.VUE_APP_API_STAGE
const dicts = {'nob': 'Nynorskorboka',
'bob': 'Bokmålsordboka',
'bob,nob': 'ordbøkene'}
paths: ["articles"] // Disable caching for articles
if ((self.$route.query.nocache || '').toLowerCase() == 'true') {
config.headers.cachebuster = Date.now()
axios.get(ARTICLE_ENDPOINT + self.$route.params.lang + '/article/' + self.$route.params.id + ".json")
self.article = Object.assign(response.data, {'dictionary': self.$route.params.lang, results: self.search_results})
})
.catch(function(error){
if (error.response && error.response.status == 404) {
self.error = ["Vi har ingen artikkel med id " + self.$route.params.id]
if (self.lang !== 'bob') self.error.push(`Noko gjekk gale...`)
if (self.lang !== 'nob') self.error.push(`Noe gikk galt...`)
}
})
.then(function(response){
self.waiting_for_articles = false
history.replaceState({article: self.article, search_results: [], lang: self.lang, error: self.error}, '')
if (source) {
self.$plausible.trackEvent('internal link incoming', {props: {origin: source}})
}
})
}
axios.get(self.api_pref + 'search?q=' + query, { headers: {"x-api-key":"ZkYiyRVXxH86ijsvhx3cH4SY5Iik2ijI3BKVJGMm"}}) // API-key to be removed or reimplemented with a ci-variable with the new API
.then(function(response){
self.search_results = response.data
if (! self.search_results.length) {
self.error = `Søk på «${query}» gir ingen treff i ${dicts[self.lang]}. Søk med * inne i ordet dersom du er usikker på skrivemåten. Bruk knappen «begge ordbøkene» om du har søkt i feil ordbok.`
if (error.response && error.response.status == 400) {
}
})
.then(function(_){
self.waiting_for_articles = false
history.replaceState({article: self.article, search_results: self.search_results, lang: self.lang, error: self.error}, '')
function navigate_to_query(self, word) {
let query = self.event ? self.event : {q: word}
// Get article IDs
api.get('articles?', {params: {w: query.match || query.q, dict: self.lang, scope: "w", stage: self.stage}}).then((response) => {
let article_ids = response.data
let unwrapped = []
for (const d in article_ids) {
article_ids[d].forEach(i => unwrapped.push({
// Get individual articles
return axios.get(`${ARTICLE_ENDPOINT}${article.dictionary}/article/${article.id}.json`)
}))
.then((response) => {
self.search_results = response.map((element, index) => {
return Object.assign(element.data, {
dictionary: unwrapped[index].dictionary
})
})
self.article = null
if (! self.search_results.length) {
self.error = []
if (self.lang !== 'bob') {
self.error.push(`Ordet «${query.match}» finst ikkje i Nynorskordboka. Bruk knappen «bokmål (bm)» om du har søkt i feil ordbok.`)
}
if (self.lang !== 'nob') self.error.push(`Ordet «${query.match}» finnes ikke i Bokmålsordboka. Bruk knappen «nynorsk (nn)» om du har søkt i feil ordbok.`)
self.error = [`Søk på «${query.q}» gir ingen treff i ${dicts[self.lang]}.`]
// If not advanced search
if (query.search != 2) self.error[0] += " Søk med * eller % dersom du er usikker på skrivemåten. Søketips kan du finne i «OM ORDBØKENE»."
if (self.lang == "bob") self.error[0] += ` Bruk knappen «nynorsk (nn)» om du har søkt i feil ordbok.`
if (self.lang == "nob") self.error[0] += ` Bruk knappen «bokmål (nn)» om du har søkt i feil ordbok.`
}
else {
self.error = null
}
})
.then(() => {
self.waiting_for_articles = false
history.replaceState({
article: self.article,
search_results: self.search_results,
lang: self.lang,
error: self.error
}, '')
})
}).catch(error =>{
self.connection_error(error)
})
}
export default {
name: 'DictionaryView',
data: function() {
return {
article_key: 0,
search_results: [],
lang: 'bob,nob',
waiting_for_articles: true,
waiting_for_metadata: true,
article: null,
error: null,
monthly_bm: null,
monthly_nn: null,
}
},
computed: {
waiting: function() {
return (this.waiting_for_articles || this.waiting_for_metadata) && this.$route.name != 'root'
},
get_search_endpoint: function() {
return api
},
},
components: {
Article,
Autocomplete,
SearchResults
},
methods: {
connection_error: function(error) {
this.search_results = []
if (error.response) {
this.error = []
if (this.lang !== 'bob') this.error.push(`Noko gjekk gale på serversida`)
if (this.lang !== 'nob') this.error.push(`Noe gikk galt på serversiden"`)
} else {
this.error = []
if (this.lang !== 'bob') this.error.push(`Nettverksproblem, prøv igjen`)
if (this.lang !== 'nob') this.error.push(`Nettverksproblemer, prøv igjen`)
}
},
select_result: function (event) {
this.event = event
let name = event.search ? 'search' : 'w'
let route = `/${this.lang}/${name}/${event.match || event.q}`
this.$router.push(route)
navigate_to_query(this)
// Tracking
let track_props = {query: event.q}
if (event.match) track_props.match = event.match
this.$plausible.trackEvent(event.update_lang ? "language" : 'dropdown selection', {
update_lang_form: function (lang) {
this.lang = lang
if(this.$route.name == 'word') {
name = "w"
query = this.$route.params.word
this.$router.push(`/${this.lang}/${name}/${query}`)
navigate_to_query(this, query)
}
else if (this.$route.name == 'search') {
name = "search"
query = this.$route.params.query
this.$router.push(`/${this.lang}/${name}/${query}`)
navigate_to_query(this, query)
if (this.article && this.article.article_id == item.article_id){
history.replaceState({article: this.article, search_results: this.search_results, lang: this.lang, error: this.error}, '')
}else{
navigate_to_article(this, item.source)
}
},
details_click: function(item) {
this.article = item.article
history.replaceState({article: this.article, search_results: [], lang: this.lang, error: null}, '')
},
return_to_results: function() {
this.article = null
}
},
mounted: function(){
let self = this
this.lang = 'bob,nob'
Promise.all([
axios.get(ARTICLE_ENDPOINT + 'bob/concepts.json').then(function(response){
let concepts = response.data.concepts
entities.bob = concepts
}),
axios.get(ARTICLE_ENDPOINT + 'nob/concepts.json').then(function(response){
let concepts = response.data.concepts
entities.nob = concepts
})
]).then(function(_) {
self.waiting_for_metadata = false
navigate_to_query(self, self.$route.params.query)
}
else if(self.$route.name == 'word') {
self.lang = self.$route.params.lang
navigate_to_query(self, self.$route.params.word)
navigate_to_article(self, self.$route.path)
}
else {
self.lang = self.$route.params.lang || 'bob,nob'
self.waiting_for_articles = false
history.replaceState({article: self.article, search_results: self.search_results, lang: self.lang, error: self.error}, '')
axios.get(ARTICLE_ENDPOINT + 'bob/article/5607.json').then(function(response){
self.monthly_bm = Object.assign(response.data, {dictionary: 'bob'})
})
axios.get(ARTICLE_ENDPOINT + 'nob/article/78569.json').then(function(response){
self.monthly_nn = Object.assign(response.data, {dictionary: 'nob'})
})
}).catch(function(_){
self.error = []
if (self.lang !== 'bob') self.error.push(`Eit nettverksproblem hindra lasting av sida. Prøv å laste sida på nytt`)
if (self.lang !== 'nob') self.error.push(`Et nettverksproblem hindret lasting av siden. Prøv å laste siden på nytt`)
self.waiting_for_metadata = false
self.waiting_for_articles = false
})
},
created: function() {
let self = this
window.onpopstate = function (event) {
if (event.state) {
self.article = event.state.article
self.search_results = event.state.search_results
self.lang = event.state.lang
}
}
}
}
</script>
<style>
main {
flex: 1 0 auto;
background-color: var(--v-tertiary-base);
display: flex;
flex-direction: column;
flex-grow: 10;
background-image: url('../assets/books.jpg');
background-repeat: no-repeat;
}
div.welcome article {
border-style: none;
}
.search_container {
background-color: var(--v-tertiary-base);
padding-top: 1px;
padding-bottom: 10px;
}
#search_results, #spinner, #single_article_container, div.welcome, div.search_container, .error {
padding-left: calc((100vw - 1200px) / 2);
padding-right: calc((100vw - 1200px) / 2);
.error > p {
margin-left: 15px;
}
#spinner {
padding-top: 40px;
}
div.monthly {
display: flex;
width: 100%;
}
div.monthly > div {
flex: 50%;
}
div.monthly.sm, div.monthly.xs {
flex-direction: column;
}
content: "fra ";
}
div.monthly article.nob .dict-label::before {
content: "frå ";
div.monthly details, div.monthly h3 {
display: none;
}
.v-label span {
color: var(--v-primary-base);
}
.lang_select_container {
padding-left: 10px;
li.suggestion {
font-weight: bold;
padding-left: 20px;
padding-top: 5px;
padding-bottom: 5px;
border: 0px;
background-image: none;
}
::selection {
background: var(--v-secondary-base);
color: white;
}
.return_to_results {
display: table-cell;
}
.return_to_results a {
color: var(--v-primary-base) !important;
}
vertical-align: top !important;
color: var(--v-primary-base) !important;
}