From d421933e44cf0643c20eccb497ada14d1d689a86 Mon Sep 17 00:00:00 2001
From: "Henrik.Askjer" <henrik.askjer@uib.no>
Date: Thu, 3 Feb 2022 13:03:36 +0000
Subject: [PATCH] Dev

---
 .env.dev_server                   |   4 +-
 .env.local                        |   4 +-
 .env.production                   |   5 +-
 src/components/Autocomplete.vue   |   5 +-
 src/components/DictionaryView.vue | 216 ++++++++++++++++--------------
 5 files changed, 127 insertions(+), 107 deletions(-)

diff --git a/.env.dev_server b/.env.dev_server
index bc9b15ea..de9b0ec6 100644
--- a/.env.dev_server
+++ b/.env.dev_server
@@ -1,4 +1,4 @@
 NODE_ENV=production
-VUE_APP_ARTICLE_ENDPOINT='https://oda.uib.no/opal/dev/'
-VUE_APP_SEARCH_ENDPOINT='https://oda.uib.no/opal/dev/api/'
+VUE_APP_ENDPOINT='https://oda.uib.no/opal/dev/'
+VUE_APP_FALLBACK_ENDPOINT='https://odd.uib.no/opal/dev/'
 VUE_APP_VERSION_LABEL=DEVELOPMENT
diff --git a/.env.local b/.env.local
index 53d6b6d7..a853ca78 100644
--- a/.env.local
+++ b/.env.local
@@ -1,4 +1,4 @@
-VUE_APP_ARTICLE_ENDPOINT='https://oda.uib.no/opal/dev/'
-VUE_APP_SEARCH_ENDPOINT='https://oda.uib.no/opal/dev/api/'
+VUE_APP_ENDPOINT='https://oda.uib.no/opal/dev/'
+VUE_APP_FALLBACK_ENDPOINT='https://odd.uib.no/opal/dev/'
 VUE_APP_VERSION_LABEL=LOCAL
 VUE_APP_RELEASE=test
diff --git a/.env.production b/.env.production
index e67c7aae..8babb079 100644
--- a/.env.production
+++ b/.env.production
@@ -1,4 +1,5 @@
 NODE_ENV=production
 VUE_APP_VERSION_LABEL=Beta
-VUE_APP_ARTICLE_ENDPOINT='https://oda.uib.no/opal/prod/'
-VUE_APP_SEARCH_ENDPOINT='https://oda.uib.no/opal/prod/api/'
+VUE_APP_ENDPOINT='https://oda.uib.no/opal/prod/'
+VUE_APP_FALLBACK_ENDPOINT='https://odd.uib.no/opal/prod/'
+
diff --git a/src/components/Autocomplete.vue b/src/components/Autocomplete.vue
index 202ca88f..9145eba2 100644
--- a/src/components/Autocomplete.vue
+++ b/src/components/Autocomplete.vue
@@ -87,9 +87,6 @@
 
 <script>
   export default {
-    props: {
-      api: Function,
-    },
     data: function() {
       return {
         loading: false,
@@ -157,7 +154,7 @@
         
           let self = this
           let params = {q, dict: self.get_lang(), n: 6, dform: 'int', meta: 'n', include: "e", wc: self.$parent.pos_selected}
-          self.api.get('suggest?', {params})
+          this.$parent.api.get('api/suggest?', {params})
             .then(async (response) => {
                         if (self.$refs.autocomplete.searchInput == q & self.suggesting) {
                           let suggestions = []
diff --git a/src/components/DictionaryView.vue b/src/components/DictionaryView.vue
index a52e3727..b2e1a204 100644
--- a/src/components/DictionaryView.vue
+++ b/src/components/DictionaryView.vue
@@ -2,7 +2,6 @@
   <main>
     <div class="search_container">
       <Autocomplete v-on:submit="select_result"
-                    :api="get_search_endpoint"
                     v-on:update-lang-form="update_lang_form">
       </Autocomplete>
       <SearchToolbar @updatePos="update_pos"
@@ -135,7 +134,7 @@
                articleLookup/>
     </div>
     <div class="welcome"
-         v-show="$route.name=='/' || !$route.name">
+         v-show="!error && ($route.name=='/' || !$route.name)">
       <div class="monthly"
            :class="$vuetify.breakpoint.name">
         <div>
@@ -172,9 +171,9 @@ import SearchResults from './SearchResults.vue'
 import Autocomplete from './Autocomplete.vue'
 import SearchToolbar from './SearchToolbar.vue'
 
-const SEARCH_ENDPOINT = process.env.VUE_APP_SEARCH_ENDPOINT
-const ARTICLE_ENDPOINT= process.env.VUE_APP_ARTICLE_ENDPOINT
-const api = axios.create({baseURL: SEARCH_ENDPOINT})
+const ENDPOINT = process.env.VUE_APP_ENDPOINT
+const FALLBACK_ENDPOINT = process.env.VUE_APP_FALLBACK_ENDPOINT
+
 
 function navigate_to_article(self, origin) {
   self.article = null
@@ -182,14 +181,14 @@ function navigate_to_article(self, origin) {
 
   const lang = self.$route.params.lang
 
-  axios.get(ARTICLE_ENDPOINT + lang + '/article/' + self.$route.params.id + ".json")
-  //axios.get('https://httpstat.us/502')
+  self.api.get(lang + '/article/' + self.$route.params.id + ".json")
+  //self.api.get("https://httpstat.us/502")
   .then(function(response){
     self.article = Object.assign(response.data, {'dictionary': lang, results: self.search_results})
     self.error = null
   })
   .catch(function(error){
-    self.handle_error(error, true)
+    self.handle_error(error, {retry: navigate_to_article, arg: origin, article: true})
   })
   .then(function(response){
     self.waiting_for_articles = false
@@ -217,8 +216,9 @@ async function load_articles(self, query, offset, n, dict) {
     article_IDs = article_IDs.slice(offset, offset + n)
 
     return Promise.all(article_IDs.map((article_id) => {
-      return axios.get(`${ARTICLE_ENDPOINT}${dict}/article/${article_id}.json`)
-      //return axios.get('https://httpstat.us/502')
+      return self.api.get(`${dict}/article/${article_id}.json`)
+     //return self.api.get(`https://httpstat.us/502`)
+
 
     }))
     .then((response) => {
@@ -231,7 +231,7 @@ async function load_articles(self, query, offset, n, dict) {
       self.search_results[dict] = results
     })
     .catch(error => {
-      self.handle_error(error)
+      self.handle_error(error, {})
     })
   }
     else {
@@ -266,12 +266,12 @@ function navigate_to_query(self, word, keep_page) {
   // Get inflections
   if (!advanced_search) {
     let params = {q, dict: self.lang, dform: 'int', include: "i", meta: 'n', wc: self.pos_selected}
-    api.get('suggest?', {params})
-    //axios.get('https://httpstat.us/502')
+    self.api.get('api/suggest?', {params})
+    //self.api.get('https://httpstat.us/502')
       .then((response) => {
                     self.inflection_suggestions = response.data.a.inflect
               }).catch(error =>{
-                    self.handle_error(error)
+                    self.handle_error(error, {retry: navigate_to_query, arg: q})
                     self.replace_history()
                 })
     }
@@ -283,8 +283,9 @@ function navigate_to_query(self, word, keep_page) {
     offset = self.perPage * (self.page -1)
   }
   if (self.pos_selected) params.wc = self.pos_selected
-    api.get('articles?', {params}).then((response) => {
-    //axios.get('https://httpstat.us/502').then((response) => {
+    self.api.get('api/articles?', {params}).then((response) => {
+    //self.api.get('https://httpstat.us/502', {params}).then((response) => {
+
             self.article_info = response.data
             self.search_results = {}
 
@@ -301,13 +302,13 @@ function navigate_to_query(self, word, keep_page) {
                   dict = bm_length == 0? 'bm' : 'nn'
                 }
                 let params = {q, dict, dform: 'int', include: "s", wc: self.pos_selected}
-                api.get('suggest?', {params})
+                self.api.get('api/suggest?', {params})
                 //axios.get('https://httpstat.us/502')
                   .then((response) => {
                     self.similar = response.data.a.similar
                     self.replace_history()
                   }).catch(error => {
-                    self.handle_error(error)
+                    self.handle_error(error, {retry: navigate_to_query, arg: q})
                     self.replace_history()
                   })
             } else {
@@ -320,19 +321,19 @@ function navigate_to_query(self, word, keep_page) {
             self.no_results = true
             if (!self.scope.includes('f')) {
               let params = {q, dict, n: 1, dform: 'int', include: 'f', wc: self.pos_selected}
-              api.get('suggest?', {params}).then((response) => {
+              self.api.get('api/suggest?', {params}).then((response) => {
                       self.suggest_fulltext = response.data.cnt > 0
                     }).catch(error => {
-                      self.handle_error(error)
+                      self.handle_error(error, {retry: navigate_to_query, arg: q})
                       self.replace_history()
                     })
             }
             if (dict != 'bm,nn') {
               let params = {q, n: 1, dict: dict=='bm'?'nn':'bm', dform: 'int', include: 'e', wc: self.pos_selected}
-              api.get('suggest?', {params}).then((response) => {
+              self.api.get('api/suggest?', {params}).then((response) => {
                       self.suggest_other_dict = response.data.cnt > 0 && response.data.a.exact[0][0] == q
                     }).catch(error => {
-                      self.handle_error(error)
+                      self.handle_error(error, {retry: navigate_to_query, arg: q})
                       self.replace_history()
                     })
             }
@@ -351,7 +352,7 @@ function navigate_to_query(self, word, keep_page) {
             })
           }
         }).catch(error =>{
-            self.handle_error(error)
+            self.handle_error(error, {retry: navigate_to_query, arg: q})
             self.replace_history()
         })
 }
@@ -360,6 +361,8 @@ export default {
   name: 'DictionaryView',
   data: function() {
     return {
+      api: null,
+      fallback: false,
       article_key: 0,
       search_results: {},
       lang: this.$store.state.defaultDict,
@@ -381,15 +384,11 @@ export default {
       selected: null,
       suggest_fulltext: false,
       suggest_other_dict: false
-
     }
   },
   computed: {
     waiting: function() {
       return (this.waiting_for_articles || this.waiting_for_metadata) && this.$route.name != 'root'
-    },
-    get_search_endpoint: function() {
-      return api
     }
   },
   metaInfo() {
@@ -419,6 +418,55 @@ export default {
     SearchToolbar
   },
   methods: {
+      load_welcome_and_metadata: function() {
+      let self = this
+        Promise.all([
+      self.api.get('bm/concepts.json').then(function(response){
+        let concepts = response.data.concepts
+        entities.bm = concepts
+      }),
+      self.api.get('nn/concepts.json').then(function(response){
+        let concepts = response.data.concepts
+        entities.nn = concepts
+      })
+    ]).then(function(_) {
+      self.waiting_for_metadata = false
+      if (self.$route.name == 'search') {
+        navigate_to_query(self, self.$route.query.q, true)
+      }
+      else if(self.$route.name == 'lookup'){
+        navigate_to_article(self, self.$route.path)
+      }
+      else {
+        self.waiting_for_articles = false
+        self.replace_history()
+        self.load_monthly_bm()
+        self.load_monthly_nn()
+
+      }
+    }).catch(function(error){
+      if (self.fallback) {
+        if (error.response) {
+          self.error = {title: self.$t('error.server.title'), description: self.$t('error.server.description', {code: error.response.status})}
+        }
+        else if (error.message == "Network Error") {
+          self.error = {title: self.$t('error.network.title'), description: self.$t('error.network.description')}
+        }
+        else {
+          self.error = {title: self.$t('error.generic.title'), description: self.$t('error.generic.description')}
+        }
+        self.waiting_for_metadata = false
+        self.waiting_for_articles = false
+      }
+      else {
+        self.fallback = true
+        self.api = axios.create({baseURL: FALLBACK_ENDPOINT})
+        self.load_welcome_and_metadata()
+      }
+
+    })
+    },
+
     replace_history: function() {
           history.replaceState({article: this.article,
                               search_results: this.search_results,
@@ -452,17 +500,17 @@ export default {
     },
     load_monthly_bm: function() {
       let self = this
-      axios.get(ARTICLE_ENDPOINT + 'bm/article/120608.json').then(function(response){
+      this.api.get('bm/article/120608.json').then(function(response){
         self.monthly_bm = Object.assign(response.data, {dictionary: 'bm'})
       })
     },
     load_monthly_nn: function() {
       let self = this
-      axios.get(ARTICLE_ENDPOINT + 'nn/article/44621.json').then(function(response){
+      this.api.get('nn/article/44621.json').then(function(response){
         self.monthly_nn = Object.assign(response.data, {dictionary: 'nn'})
       })
     },
-    handle_error: function(error, article) {
+    handle_error: function(error, retry_params) {
       this.waiting_for_articles = false
       this.no_results = false
       this.search_results = {}
@@ -470,31 +518,40 @@ export default {
       this.similar = []
       this.suggest_fulltext = false
       this.suggest_other_dict = false
-      if (error.response) {
-        if (error.response.status == 404) {
-          if (article) {
-            this.error = {title: this.$t('error.404.title'), description: this.$t('error.no_article', {id: this.$route.params.id}), article: true}
+      this.api = axios.create({baseURL: FALLBACK_ENDPOINT})
+      if (this.fallback || !retry_params.retry) {
+        this.fallback = true
+        if (error.response) {
+          if (error.response.status == 404) {
+            if (retry_params.article) {
+              this.error = {title: this.$t('error.404.title'), description: this.$t('error.no_article', {id: this.$route.params.id}), article: true}
+            }
+            else {
+              this.error = {title: this.$t('error.404.title'), description: this.$t('error.404.description'), article: retry_params.article}
+            }
+          }
+          else if (error.response.status == 503) {
+            this.error = {title: this.$t('error.503.title'), description: this.$t('error.503.description'), article: retry_params.article}
+          }
+          else if (String(error.response.status)[0] == "5") {
+            this.error = {title: this.$t('error.server.title'), description: this.$t('error.server.description', {code: error.response.status}), article: retry_params.article}
           }
           else {
-            this.error = {title: this.$t('error.404.title'), description: this.$t('error.404.description'), article}
+            this.error = {title: this.$t('error.generic_code.title'), description: this.$t('error.generic_code.description', {code: error.response.status}), article: retry_params.article}
           }
-        }
-        else if (error.response.status == 503) {
-          this.error = {title: this.$t('error.503.title'), description: this.$t('error.503.description'), article}
-        }
-        else if (String(error.response.status)[0] == "5") {
-          this.error = {title: this.$t('error.server.title'), description: this.$t('error.server.description', {code: error.response.status}), article}
+        } else if (error.message == "Network Error") {
+          this.error = {title: this.$t('error.network.title'), description: this.$t('error.network.description'), article: retry_params.article}
         }
         else {
-          this.error = {title: this.$t('error.generic_code.title'), description: this.$t('error.generic_code.description', {code: error.response.status}), article}
+          this.error = {title: this.$t('error.generic.title'), description: this.$t('error.generic.description'), article: retry_params.article}
         }
-      } else if (error.message == "Network Error") {
-        this.error = {title: this.$t('error.network.title'), description: this.$t('error.network.description'), article}
-      }
-      else {
-        this.error = {title: this.$t('error.generic.title'), description: this.$t('error.generic.description'), article}
+      } else {
+        this.fallback = true
+        retry_params.retry(this, retry_params.arg)
       }
+
     },
+
     inflection_link: function (word) {
       this.$plausible.trackEvent('inflection link', {props: {lang: this.previous.params.lang, from: this.previous.query.q, to: word}})
       this.event = null
@@ -658,61 +715,26 @@ export default {
     }
   },
   mounted: function(){
-    let self = this
-    self.lang = self.$route.params.lang || this.$store.state.defaultDict || 'bm,nn'
-    if (self.$route.query.pos) {
-    self.pos_selected = self.$route.query.pos.toUpperCase()
-    } else self.pos_selected = null
-
-    if (self.$route.query.scope) {
-      self.scope = self.$route.query.scope
-      self.set_fulltext_highlight()
+    this.api = axios.create({baseURL: ENDPOINT})
+
+    this.lang = this.$route.params.lang || this.$store.state.defaultDict || 'bm,nn'
+    if (this.$route.query.pos) {
+    this.pos_selected = this.$route.query.pos.toUpperCase()
+    } else this.pos_selected = null
+
+    if (this.$route.query.scope) {
+      this.scope = this.$route.query.scope
+      this.set_fulltext_highlight()
     }
-    if (self.$route.query.page) self.page = parseInt(self.$route.query.page)
-    if (self.$route.query.perPage) {
-      self.perPage = parseInt(self.$route.query.perPage)
+    if (this.$route.query.page) this.page = parseInt(this.$route.query.page)
+    if (this.$route.query.perPage) {
+      this.perPage = parseInt(this.$route.query.perPage)
     }
     else {
-      self.perPage = parseInt(self.$store.state.perPage)
+      this.perPage = parseInt(this.$store.state.perPage)
     }
 
-    Promise.all([
-      axios.get(ARTICLE_ENDPOINT + 'bm/concepts.json').then(function(response){
-        let concepts = response.data.concepts
-        entities.bm = concepts
-      }),
-      axios.get(ARTICLE_ENDPOINT + 'nn/concepts.json').then(function(response){
-        let concepts = response.data.concepts
-        entities.nn = concepts
-      })
-    ]).then(function(_) {
-      self.waiting_for_metadata = false
-      if (self.$route.name == 'search') {
-        navigate_to_query(self, self.$route.query.q, true)
-      }
-      else if(self.$route.name == 'lookup'){
-        navigate_to_article(self, self.$route.path)
-      }
-      else {
-        self.waiting_for_articles = false
-        self.replace_history()
-        self.load_monthly_bm()
-        self.load_monthly_nn()
-
-      }
-    }).catch(function(error){
-      if (error.message == "Network Error") {
-        self.error = self.$t('error.network')
-      }
-      else if (error.response) {
-        self.error = self.$t('error.server', {code: error.response.status})
-      }
-      else {
-        self.error = self.$t('error.generic')
-      }
-      self.waiting_for_metadata = false
-      self.waiting_for_articles = false
-    })
+    this.load_welcome_and_metadata()
   },
   watch: {
     $route(to, from) {
-- 
GitLab