mixit/compiler/src/openweathermap/main.vue

179 lines
5.0 KiB
Vue

<template lang="pug">
.openweathermap
service-header(:emit="emit")
template(#title) OpenWeatherMap
template(#settings)
setting-int(:id="'update'" :title="'Update interval'" :value="update" @change="saveOptionCouple")
setting-int(:id="'forecastLimit'" :title="'Forecast limit'" :value="forecastLimit" @change="saveOptionCouple")
p.setting
button(@click="showAdd = true") Add city
loadable-block(:loadable="weathers")
template(#success)
.list
weather(v-for="(city, id) in weathers.get()" :key="id" :selected="selectedId == id"
:city="city" @select="makeSelect(id)" @remove="removeCity(id)")
input.weather(v-show="showAdd" placeholder="city id" @keyup.enter="addCity(parseInt($event.target.value))")
loadable-block(:loadable="forecast").forecast
template(#success)
chart.chart(:chartData="forecastChart")
template(#error)
form(@submit.prevent="makeAuth")
p
label(for="token") Token:
input#token(v-model="newToken" required)
p
input(type="submit" value="Connect")
</template>
<script>
import baseServiceVue from '../core/baseService.vue'
import Loadable from '../core/loadable/Loadable'
import chartVue from './chart.vue'
import weatherVue from './weather.vue'
export default {
name: 'openweathermap',
extends: baseServiceVue,
components: {
weather: weatherVue,
chart: chartVue
},
props: {
token: String,
cities: {
type: Array,
default: function () {
return []
}
},
timeout: {
default: 5000,
type: Number
},
update: {
default: 10 * 60, //10min
type: Number
},
lang: {
default: 'fr',
type: String
},
forecastLimit: {
default: 9,
type: Number
}
},
data() {
return {
rest: axios.create({
baseURL: 'https://api.openweathermap.org/data/2.5/',
params: {
appid: this.token, units: 'metric', lang: this.lang
},
timeout: this.timeout
}),
newToken: this.token,
weathers: new Loadable(),
forecast: new Loadable(),
selectedId: 0,
showAdd: this.cities.length == 0
};
},
computed: {
forecastChart() { return {
datasets: [{
type: 'line',
label: 'Temperature',
yAxisID: 'y-axis-temp',
borderColor: 'white',
borderWidth: 1,
fill: false,
data: this.forecast.get().map(function (line) { return {
x: line.dt * 1000, y: line.main.temp
} })
},{
type: 'bar',
label: 'Percipitation',
yAxisID: 'y-axis-rain',
borderColor: '#DDDDDD',
backgroundColor: '#DDDDDD33',
borderWidth: 1,
data: this.forecast.get().filter(f => 'rain' in f && '3h' in f.rain).map(function (line) { return {
x: line.dt * 1000, y: line.rain['3h']
} })
}]
} },
selected() {
return this.weathers.isSuccess() ? this.weathers.get()[this.selectedId] : null
},
hasWeathers() {
return this.weathers.isSuccess() && this.weathers.get().length > 0
}
},
methods: {
makeSelect(id) {
this.selectedId = id
this.loadForecast()
},
updateData() {
Lists.for(this.weathers.get(),
(weather, i) => this.getWeather({ id: weather.id })
.then(res => this.$set(this.weathers.get(), i, res.data))
)
this.loadForecast()
},
getWeather(params) {
return this.catchEmit(this.rest.get('weather', { params: params }))
},
loadForecast() {
if(this.selected) {
this.forecast.load(
this.catchEmit(this.rest.get('forecast', { params: {
id: this.selected.id, cnt: this.forecastLimit
}})),
res => res.data.list
)
} else this.forecast.fail('Any selection')
},
formatDate(dt) {
const date = new Date(dt * 1000)
return `${date.toLocaleDateString()} ${date.getHours()}h`
},
addCity(id) {
this.cities.push({ id: id })
this.saveOption('cities', this.cities)
},
removeCity(key) {
Lists.removeAt(this.cities, key)
this.saveOption('cities', this.cities)
},
init() {
if(this.token) {
if(this.cities.length > 0) {
axios.all(this.cities.map(city => this.getWeather(city)))
.then(axios.spread((...ress) =>
this.weathers.success(ress.map(r => r.data))))
.then(this.loadForecast)
.catch(this.weathers.fail)
if(this.update > 0)
setInterval(this.updateData, this.update * 1000)
} else this.weathers.success([])
} else this.weathers.fail('First connection')
},
makeAuth() {
this.catchEmit(axios.get('https://api.openweathermap.org/data/2.5/weather', {
params: { q: 'London', appid: this.newToken },
timeout: this.timeout
})).then(() => {
this.saveOption('token', this.newToken)
this.init()
})
}
},
created() {
this.init()
}
}
</script>