Skip to content

Commit

Permalink
refactor: improve timeseries UI + error handling
Browse files Browse the repository at this point in the history
- distinguish between server error responses (40x/50x responses from the
server) and client errors
https://www.intricatecloud.io/2020/03/how-to-handle-api-errors-in-your-web-app-using-axios/
- add spinners and loading state
- still need to set up timeouts with user feedback for #42

resolves #50
  • Loading branch information
alee committed Oct 7, 2020
1 parent 8b96a50 commit 6859530
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 23 deletions.
60 changes: 42 additions & 18 deletions app/components/TimeSeries.vue
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
<template>
<client-only placeholder="Loading...">
<div style="width: 100%">
<Plotly
v-if="requestMessage.length === 0"
ref="plot"
:data="timeseriesData"
:layout="layoutMetadata"
:options="options"
></Plotly>
<v-alert v-else type="error">{{ requestMessage }}</v-alert>
<v-btn @click.native="download">Download Chart</v-btn>
<div v-if="isLoadingData" class="justify-center">
<v-progress-circular
v-if="isLoadingData"
indeterminate
color="primary"
/>
Loading . . .
</div>
<div v-else-if="hasData">
<Plotly
ref="plot"
:data="timeseriesData"
:layout="layoutMetadata"
:options="options"
></Plotly>
<v-btn @click.native="download">Download Chart</v-btn>
</div>
<v-alert v-else type="error"
>Sorry, we couldn't build a graph from the given parameters.</v-alert
>
</div>
</client-only>
</template>
Expand All @@ -20,12 +31,11 @@ import _ from 'lodash'
import { Component } from 'nuxt-property-decorator'
import * as queryString from 'query-string'
import { Prop, Watch } from 'vue-property-decorator'
import { TIMESERIES_ENDPOINT } from '@/store/constants'
import JSZip from 'jszip'
import { saveAs } from 'file-saver'
import { Plotly } from 'vue-plotly'
// const Plotly = () => import('@statnett/vue-plotly')
const { Parser } = require('json2csv')
import { TIMESERIES_ENDPOINT } from '@/store/constants'
// Would need to make a custom debounce decorator so
// that debounced methods can exist in a vue-class-component
Expand All @@ -38,6 +48,7 @@ const updateDataset = _.debounce(async function (
minYear,
maxYear
) {
vue.isLoadingData = true
const start = minYear.toString().padStart(4, '0')
const end = maxYear.toString().padStart(4, '0')
if (start > end) {
Expand All @@ -57,7 +68,6 @@ const updateDataset = _.debounce(async function (
boundaryGeometry: geometry,
}
const url = `${TIMESERIES_ENDPOINT}${datasetUri}?${queryString.stringify(qs)}`
try {
const response = await vue.$axios.$post(url, body)
const timeZeroOffset = vue.timeZero
Expand All @@ -70,15 +80,28 @@ const updateDataset = _.debounce(async function (
type: 'scatter',
}
vue.timeseries = timeseries
console.log('Clearing messages')
vue.hasData = true
vue.$store.dispatch('clearMessages')
} catch (e) {
console.error(e)
vue.$store.dispatch(
'error',
vue.$store.dispatch('clearMessages')
vue.hasData = false
let errorMessage =
'Unable to load data from the timeseries service, please try selecting a smaller area or contact us if the error persists.'
)
if (e.response) {
console.error('received error response from server: ', e)
const responseData = e.response.data
if (responseData.status === 400) {
// bad request
errorMessage = responseData.message
}
} else if (e.request) {
// browser made a request but didn't see a response, likely a timeout / client network error
console.log('did not receive a server response: ', { e })
errorMessage += ` Cause: ${e.message}`
}
vue.$store.dispatch('error', errorMessage)
}
vue.isLoadingData = false
},
300)
Expand Down Expand Up @@ -112,7 +135,8 @@ class TimeSeries extends Vue {
type: 'scatter',
}
requestMessage = ''
hasData = false
isLoadingData = false
mounted() {
updateDataset(
Expand Down
11 changes: 9 additions & 2 deletions app/pages/dataset/_id/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
<client-only placeholder="Loading map, please wait...">
<l-map
ref="layerMap"
:zoom="selectedDataset.region.zoom"
:min-zoom="3"
:zoom="4"
:center="selectedDataset.region.center"
>
<l-control-attribution position="topright" />
Expand Down Expand Up @@ -618,7 +619,13 @@ class DatasetDetail extends Vue {
this.updateSelectedGeometry(l)
})
this.enableEditOnly(map)
map.fitBounds(this.drawnItems.getBounds(), { padding: [5, 5] })
let padding = [5, 5]
console.log(geoJsonLayer)
if (geoJsonLayer instanceof L.Marker) {
console.log('Setting padding for marker')
padding = [30, 30]
}
map.fitBounds(this.drawnItems.getBounds(), { padding })
}
getSavedGeometry() {
Expand Down
3 changes: 0 additions & 3 deletions app/plugins/axios.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
const DEFAULT_TIMEOUT = 10000
export default function ({ route, $axios, store }) {
$axios.defaults.timeout = DEFAULT_TIMEOUT
$axios.onError((error) => {
store.dispatch('error', error)
})
}

0 comments on commit 6859530

Please sign in to comment.