#42 many improvements

pull/1/head
Thomas Ballmann 3 years ago
parent 4db975f0a1
commit abfbb31b5b

@ -1,5 +1,8 @@
<template>
<v-card outlined>
<v-card
outlined_
flat
>
<v-skeleton-loader
type="card-heading, list-item-three-line, list-item-avatar, list-item-avatar, list-item-avatar, list-item-avatar"
:loading="isLoading"
@ -73,6 +76,7 @@
<v-divider />
<v-card-actions>
<!--
<v-btn
:loading="isUpdatingData"
text
@ -80,6 +84,19 @@
>
i8n:update weather data
</v-btn>
-->
<v-spacer />
<v-btn
:loading="isUpdatingData"
depressed
@click="updateData"
>
<v-icon left>
$update
</v-icon>
Update Now
</v-btn>
</v-card-actions>
</v-skeleton-loader>
</v-card>

@ -1,21 +1,21 @@
<template>
<v-autocomplete
ref="input"
v-model="model"
:disabled="!api"
:items="entries"
:loading="isLoading"
:search-input.sync="search"
no-filter
_hide-no-data
_hide-selected
item-text="name"
item-value="id"
label="Location"
placeholder="Start typing to Search"
_return-object
prepend-icon="$place"
>
<template #item="{ item }">
<v-list-item-avatar
v-if="item.weather"
color="grey lighten-2"
class="headline font-weight-light white--text"
>
@ -29,7 +29,7 @@
<v-list-item-title>
{{ item.name }}, {{ item.sys.country }}
</v-list-item-title>
<v-list-item-subtitle>
<v-list-item-subtitle v-if="item.weather">
<img
width="16"
:src="getCountryFlag(item.sys.country)"
@ -37,43 +37,19 @@
{{ item.weather[0].description }}
</v-list-item-subtitle>
</v-list-item-content>
<v-list-item-action>
<v-list-item-action v-if="item.main">
{{ item.main.temp }}°С
</v-list-item-action>
<v-list-item
v-if="0"
two-line
class="pa-0"
>
<v-list-item-icon class="ma-0">
<img
width="64"
:src="getConditionIcon(item.weather[0].icon)"
>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title>
{{ item.name }}, {{ item.sys.country }}
<img :src="getCountryFlag(item.sys.country)">
<strong>{{ item.weather[0].description }}</strong>
</v-list-item-title>
<v-list-item-subtitle>
<v-chip
class="font-weight-bold"
small
>
{{ item.main.temp }}°С
</v-chip>
</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
</template>
<template #selection="{ item }">
{{ item.name }}, {{ item.sys.country }}
</template>
</v-autocomplete>
</template>
<script>
import axios from 'axios'
export default {
props: {
location: {
@ -105,12 +81,17 @@
this.$emit('update:location', val)
},
search (val) {
if (!val || val.length < 3) return
if (!val || val.length < 3) {
return
}
// Items have already been requested
if (this.isLoading) return
if (this.isLoading) {
return
}
this.isLoading = true
this.entries = []
// search
let url = 'https://api.openweathermap.org/data/2.5/find?appid='
@ -120,18 +101,24 @@
url += '&type=like&sort=population&cnt=10'
url += '&q=' + val
fetch(url)
.then(res => res.json())
axios.get(url)
.then(res => {
this.count = res.count
this.entries = res.list
this.entries = res.data.list
this.isLoading = false
})
.catch(err => {
console.log(err)
})
.finally(() => (this.isLoading = false))
},
},
created () {
// TODO
this.entries = [{
name: 'Freilassing',
sys: {
country: 'DE',
},
id: this.location,
}]
this.model = this.location
},
methods: {
getCountryFlag (code) {
return (

@ -50,7 +50,8 @@ const MY_ICONS = {
lock: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/lock/baseline.svg') },
settings: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/settings/baseline.svg') },
storage: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/sd_storage/baseline.svg') },
playlist: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/live_tv/baseline.svg') },
// playlist: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/live_tv/baseline.svg') },
slideshow: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/slideshow/baseline.svg') },
support: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/support/baseline.svg') },
device: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/video_label/baseline.svg') },
update: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/update/baseline.svg') },
@ -62,6 +63,12 @@ const MY_ICONS = {
sentiment_satisfied_alt: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/sentiment_satisfied_alt/baseline.svg') },
file: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/insert_drive_file/baseline.svg') },
calendar_today: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/calendar_today/baseline.svg') },
dashboard: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/dashboard/baseline.svg') },
done: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/done/baseline.svg') },
link: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/link/baseline.svg') },
help: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/help/baseline.svg') },
vpn_key: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/vpn_key/baseline.svg') },
place: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/place/baseline.svg') },
// wifi
signalWifiOff: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_off/baseline.svg') },

@ -3,7 +3,7 @@ import Vuex from 'vuex'
import axios from 'axios'
// import device from '@/api/device'
import { countries, languages } from 'countries-list'
// import { languages } from 'countries-list'
import timezones from 'countries-and-timezones'
Vue.use(Vuex)
@ -26,7 +26,6 @@ const store = new Vuex.Store({
},
updateSettings (state, payload) {
state.settings = { ...state.settings, ...payload }
console.log(state.settings)
},
},
actions: {
@ -91,20 +90,56 @@ const store = new Vuex.Store({
*/
},
getters: {
isSettingSupported: (state) => (key) => {
const getDescendantProp = (obj, path) => {
const arr = path.split(/[.[]['"]?/)
let o = obj
while (arr.length && o) {
o = o[arr.shift().replace(/['"]?]$/, '')]
}
return o
}
return getDescendantProp(state.settings, key) !== undefined
},
getAvailableLanguages () {
return languages
const list = []
// const en = languages.en
list.push({
code: 'EN',
name: 'English',
native: 'English',
})
/*
Object.keys(languages).forEach((code) => {
list.push({
code: code,
name: languages[code].name,
native: languages[code].native,
})
})
*/
return list
},
getAvailableCountries () {
return countries
return Object.values(timezones.getAllCountries())
},
getAvailableTimezones () {
return timezones.getAllTimezones()
return Object.values(timezones.getAllTimezones())
},
getAvailableTimezone: () => (countryCode) => {
return timezones.getCountry(countryCode)
},
getTimezoneByCountry: () => (country) => {
return timezones.getTimezonesForCountry(country)
},
getTimezone: () => (timezone) => {
return timezones.getTimezone(timezone)
},
},
})

@ -3,13 +3,17 @@
class="_grid-list-md _pa-2"
fluid
>
<v-row>
<weather-card />
- update screen in<br>
- update weather in<br>
- show api infos and short how to
<v-row v-if="0">
<v-col
cols="12"
md="6"
>
<screen-card />
<!--
<v-chip
outlined
@ -27,7 +31,6 @@
sm="6"
md="4"
>
<weather-card />
<device-card class="mt-5" />
</v-col>
</v-row>

@ -2,8 +2,6 @@
<div class="pa-5">
<v-card
flat
width="400"
class="mx-auto"
>
<v-card-title class="display-2 mb-12 justify-center text-center">
Device settings
@ -18,58 +16,61 @@
<v-select
v-model="form.theme"
disabled
:items="optionsTheme"
label="Appearance"
prepend-icon="$palette"
/>
<v-select
disabled
:items="getAvailableCountries"
item-text="name"
label="Region"
prepend-icon="$language"
/>
<v-select
v-model="form.language"
disabled
:items="getAvailableLanguages"
item-text="name"
item-text="native"
item-value="code"
label="Language"
prepend-icon="$translate"
/>
<v-select
disabled
:items="getAvailableTimezones"
<v-autocomplete
v-model="form.timezone"
:items="getAvailableTimezonesSorted"
item-value="name"
item-text="name"
label="Timezone"
prepend-icon="$access_time"
/>
return-object
>
<template #item="{ item }">
(GMT{{ item.utcOffsetStr }}) {{ item.name }}
</template>
<template #selection="{item}">
(GMT{{ item.utcOffsetStr }}) {{ item.name }}
</template>
</v-autocomplete>
</v-card-text>
<v-divider class="mt-12" />
<v-card-actions>
<v-btn text>
Cancel
<v-btn
text
@click="resetChanges"
>
Restore
</v-btn>
<v-spacer />
<v-btn
color="primary"
text
:loading="isProcessing"
depressed
@click="commitChanges"
>
Submit
<v-icon left>
$done
</v-icon>
Save
</v-btn>
</v-card-actions>
</v-card>
device settings<br>
- orientation<br>
- theme<br>
- auflösung<br>
- system language<br>
- system time<br>
</div>
</template>
@ -82,6 +83,9 @@
form: {
name: '',
theme: '',
country: '',
timezone: '',
language: '',
},
// 0 thru 3 corresponding to 4 cardinal rotations
@ -109,11 +113,22 @@
'getAvailableCountries',
'getAvailableLanguages',
'getAvailableTimezones',
'getTimezone',
]),
getAvailableTimezonesSorted () {
return this.getAvailableTimezones.slice(0).sort((a, b) => {
// .sort((a,b) => a.time===b.time ? 0 : (a.time < b.time ? -1 : 1));
if (a.utcOffset === b.utcOffset) {
return 0
} else {
return a.utcOffset < b.utcOffset ? -1 : 1
}
// return a.utcOffset < b.utcOffset ? -1 : 1
})
},
},
created () {
this.form.name = this.settings.device.name
this.form.theme = this.settings.device.theme
this.resetChanges()
},
methods: {
...mapMutations(['updateSettings']),
@ -126,12 +141,26 @@
name: this.form.name,
theme: this.form.theme,
},
system: {
country: this.form.country,
language: this.form.language,
timezone: this.form.timezone.name,
utc: this.form.timezone.utcOffset * 60,
dst: this.form.timezone.dstOffset * 60,
},
})
this.saveSettings().then(() => {
this.isProcessing = false
})
},
resetChanges () {
this.form.name = this.settings.device.name
this.form.theme = this.settings.device.theme
this.form.country = this.settings.system.country
this.form.timezone = this.getTimezone(this.settings.system.timezone)
this.form.language = this.settings.system.language
},
},
}
</script>

@ -2,8 +2,6 @@
<div class="pa-5">
<v-card
flat
width="400"
class="mx-auto"
>
<v-card-title class="display-2 mb-12 justify-center text-center">
Playlist settings
@ -23,8 +21,10 @@
class="text-center pb-0"
>
<v-text-field
v-model="settings.playlist.timer"
v-model="form.timer"
:disabled="!isSettingSupported('playlist.timer')"
label="Switch every"
:rules="[rules.minValue]"
type="number"
dense
rounded
@ -41,36 +41,47 @@
<br>Calendar
</v-col>
</v-row>
</v-card-text>
<ul
v-if="0"
class="mt-5"
>
<li>calendar</li>
<li>weather forecast</li>
<li>unsplash.com</li>
</ul>
<v-divider class="mt-12 mx-3" />
<v-card-subtitle>
Service
</v-card-subtitle>
<v-card-text>
<v-combobox
v-model="form.images"
:disabled="!isSettingSupported('playlist.images')"
:items="['https://api.paperdash.io/image/']"
label="Image provider"
prepend-icon="$link"
append-outer-icon="$help"
/>
</v-card-text>
<v-divider class="mt-12" />
<v-card-actions>
<v-btn text>
Cancel
<v-btn
text
@click="resetChanges"
>
Restore
</v-btn>
<v-spacer />
<v-btn
color="primary"
text
:loading="isProcessing"
depressed
@click="commitChanges"
>
Submit
<v-icon left>
$done
</v-icon>
Save
</v-btn>
</v-card-actions>
</v-card>
playlist settings<br>
- switch every x seconds<br>
- rename playlist to faces?
</div>
</template>
@ -81,7 +92,19 @@
components: {
},
data: () => ({
isLoading: false,
isProcessing: false,
form: {
timer: '',
imageProvider: '',
},
rules: {
required: value => !!value || 'Required.',
minValue: value => Number(value) >= 10 || 'Min 10 seconds',
email: value => {
const pattern = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return pattern.test(value) || 'Invalid e-mail.'
},
},
}),
computed: {
...mapState([
@ -89,8 +112,12 @@
'settings',
]),
...mapGetters([
'isSettingSupported',
]),
},
created () {
this.resetChanges()
},
methods: {
...mapMutations(['updateSettings']),
...mapActions(['saveSettings']),
@ -98,9 +125,9 @@
this.isProcessing = true
this.updateSettings({
device: {
name: this.form.name,
theme: this.form.theme,
playlist: {
timer: Number(this.form.timer),
images: this.form.images,
},
})
@ -108,6 +135,10 @@
this.isProcessing = false
})
},
resetChanges () {
this.form.timer = this.settings.playlist.timer
this.form.images = this.settings.playlist.images
},
},
}
</script>

@ -1,454 +0,0 @@
<template>
<v-row class="fluid fill-height">
<template v-if="isLoading">
<v-overlay
:absolute="true"
:value="true"
>
<v-progress-circular
indeterminate
size="64"
/>
</v-overlay>
</template>
<v-container>
<v-snackbar
v-model="isSnackbar"
:timeout="3000"
color="success"
>
i8n:saved
</v-snackbar>
<v-tabs
v-model="tab"
centered
icons-and-text
>
<v-tab>
Device
<v-icon>$tv</v-icon>
</v-tab>
<v-tab>
Playlist
<v-icon>$playlist</v-icon>
</v-tab>
<v-tab>
Weather
<v-icon>$wb_sunny</v-icon>
</v-tab>
<!--
<v-tab>
Cloud
<v-icon>$cloud</v-icon>
</v-tab>
-->
</v-tabs>
<v-card
v-if="settings"
class="mx-auto"
width="400"
>
<v-tabs-items v-model="tab">
<v-tab-item>
<v-card-text>
<v-select
v-model="settings.device.angle"
:items="deviceOrientation"
label="i8n:Orientation"
placeholder
/>
<v-select
v-model="settings.device.theme"
:items="deviceTheme"
label="i8n:Theme"
placeholder
/>
<v-dialog
v-model="dialogSystemUpdate"
max-width="400"
>
<template #activator="{ on }">
<v-btn
class="my-5"
block
small
outlined
color="warning"
v-on="on"
>
System update
</v-btn>
</template>
<v-card :loading="system.updateProgress > 0">
<template #progress>
<v-progress-linear
v-model="system.updateProgress"
:indeterminate="system.updateProgress === 100"
height="10"
/>
</template>
<v-card-title class="headline">
System update
</v-card-title>
<v-card-text>
<v-file-input
v-model="system.firmware"
show-size
accept="application/octet-stream"
label="Firmware"
/>
</v-card-text>
<v-card-actions>
<v-btn
text
href="https://github.com/paperdash"
target="_blank"
>
Get firmware
</v-btn>
<v-spacer />
<v-btn
ref="firmware"
outlined
color="warning"
@click="onSystemUpdate()"
>
Update system
</v-btn>
</v-card-actions>
</v-card>
<v-dialog
:value="system.updateResult !== null"
persistent
max-width="400"
>
<v-card>
<v-card-title class="headline">
update result...
{{ system.updateResult }}
</v-card-title>
<v-card-actions>
<v-spacer />
<v-btn
text
@click="onUpdateDone()"
>
OK
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-dialog>
</v-card-text>
</v-tab-item>
<v-tab-item>
<v-card-text class="pb-0">
<v-row>
<v-col
cols="3"
class="text-center mt-2 pb-0"
>
<v-icon>$wb_sunny</v-icon>
<br>Forecast
</v-col>
<v-col
cols="6"
class="text-center pb-0"
>
<v-text-field
v-model="settings.playlist.timer"
label="Switch every"
type="number"
dense
rounded
filled
suffix="seconds"
class="text-right"
/>
</v-col>
<v-col
cols="3"
class="text-center mt-2 pb-0"
>
<v-icon>$calendar_today</v-icon>
<br>Calendar
</v-col>
</v-row>
<ul
v-if="0"
class="mt-5"
>
<li>calendar</li>
<li>weather forecast</li>
<li>unsplash.com</li>
</ul>
</v-card-text>
</v-tab-item>
<v-tab-item>
<v-card-text>
<v-text-field
v-model="settings.weather.api"
label="i8n:OpenWeatherMap API key"
placeholder="###"
/>
<weather-find-location
:api="settings.weather.api"
:location.sync="settings.weather.location"
:lang="settings.weather.lang"
:unit="settings.weather.unit"
/>
<v-select
v-model="settings.weather.lang"
:items="weatherLang"
label="i8n:Lang"
placeholder
/>
<v-select
v-model="settings.weather.unit"
:items="weatherUnit"
label="i8n:Units"
placeholder
/>
</v-card-text>
</v-tab-item>
<!--
<v-tab-item>
<v-card-text>
<v-select
:items="deviceMode"
v-model="settings.cloud.mode"
label="i8n:Device mode"
placeholder
></v-select>
<v-text-field
label="i8n:Cloud server"
v-model="settings.cloud.url"
placeholder="i8n:https://"
></v-text-field>
<v-text-field
label="i8n:Cloud Token"
v-model="settings.cloud.token"
placeholder="########-####-####-####-############"
></v-text-field>
</v-card-text>
</v-tab-item>
-->
</v-tabs-items>
<v-card-actions>
<v-btn
text
to="/"
>
i8n:cancel
</v-btn>
<v-spacer />
<v-btn
text
color="primary"
@click="onSave()"
>
i8n:Save
</v-btn>
</v-card-actions>
</v-card>
</v-container>
</v-row>
</template>
<script>
import apiDevice from '../api/device'
import weatherFindLocation from './../components/WeatherFindLocation'
import axios from 'axios'
export default {
name: 'Settings',
components: {
weatherFindLocation,
},
data: () => ({
isLoading: true,
isSnackbar: false,
tab: 0,
settings: null,
// 0 thru 3 corresponding to 4 cardinal rotations
deviceOrientation: [
{ text: 'Nord', value: 0 },
{ text: 'East', value: 1 },
{ text: 'South', value: 2 },
{ text: 'West', value: 3 },
],
deviceTheme: [
{ text: 'Black', value: 'black' },
{ text: 'White', value: 'white' },
],
deviceMode: [
{ text: 'Active', value: 'active' },
{ text: 'Passive', value: 'passive' },
],
// @see https://openweathermap.org/current#multi
weatherLang: [
{ text: 'English', value: 'en' },
{ text: 'Deutsch', value: 'de' },
],
weatherUnit: [
{ text: 'Imperial', value: '' },
{ text: 'Metrisch', value: 'metric' },
],
dialogSystemUpdate: false,
system: {
firmware: null,
updateProgress: 0,
updateResult: null,
},
}),
created () {
this.$vuetify.icons.values.tv = {
component: () =>
import(
/* webpackChunkName: "icons" */ '!vue-svg-loader!@material-icons/svg/svg/tv/baseline.svg'
),
}
this.$vuetify.icons.values.playlist = {
component: () =>
import(
/* webpackChunkName: "icons" */ '!vue-svg-loader!@material-icons/svg/svg/live_tv/baseline.svg'
),
} // slideshow | playlist_play | live_tv | queue_play_next
this.$vuetify.icons.values.keys = {
component: () =>
import(
/* webpackChunkName: "icons" */ '!vue-svg-loader!@material-icons/svg/svg/insert_link/baseline.svg'
),
}
this.$vuetify.icons.values.cloud = {
component: () =>
import(
/* webpackChunkName: "icons" */ '!vue-svg-loader!@material-icons/svg/svg/cloud/baseline.svg'
),
}
this.$vuetify.icons.values.calendar_today = {
component: () =>
import(
/* webpackChunkName: "icons" */ '!vue-svg-loader!@material-icons/svg/svg/calendar_today/baseline.svg'
),
}
this.$vuetify.icons.values.wb_sunny = {
component: () =>
import(
/* webpackChunkName: "icons" */ '!vue-svg-loader!@material-icons/svg/svg/wb_sunny/baseline.svg'
),
}
this.$vuetify.icons.values.system_update = {
component: () =>
import(
/* webpackChunkName: "icons" */ '!vue-svg-loader!@material-icons/svg/svg/system_update_alt/baseline.svg'
),
}
this.$vuetify.icons.values.file = {
component: () =>
import(
/* webpackChunkName: "icons" */ '!vue-svg-loader!@material-icons/svg/svg/attach_file/baseline.svg'
),
}
this.$vuetify.icons.values.warning = {
component: () =>
import(
/* webpackChunkName: "icons" */ '!vue-svg-loader!@material-icons/svg/svg/warning/baseline.svg'
),
}
this.$vuetify.icons.values.clear = {
component: () =>
import(
/* webpackChunkName: "icons" */ '!vue-svg-loader!@material-icons/svg/svg/clear/baseline.svg'
),
}
apiDevice.getSettings(settings => {
this.settings = settings
this.isLoading = false
})
},
methods: {
onSave () {
this.isLoading = true
apiDevice.putSettings(this.settings, data => {
console.log(data)
this.isLoading = false
this.isSnackbar = true
this.$router.push('/')
})
},
onSystemUpdate () {
const self = this
self.system.updateProgress = 0
const config = {
onUploadProgress: function (progressEvent) {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total,
)
self.system.updateProgress = percentCompleted
},
}
const formData = new FormData()
formData.append('update', this.system.firmware)
axios
.post('/update', formData, config)
.then(response => {
console.log(response.data)
self.system.updateProgress = null
self.system.updateResult = response.data.success
})
.catch(response => {
console.log(response)
self.system.updateProgress = null
self.system.updateResult = false
})
},
onUpdateDone () {
if (this.system.updateResult === true) {
window.location = '/'
} else {
this.system.firmware = null
this.system.updateProgress = 0
this.system.updateResult = null
}
},
},
}
</script>
<style scoped>
>>> .v-input.text-right .v-text-field__slot > input {
text-align: right;
}
</style>

@ -2,8 +2,6 @@
<div class="pa-5">
<v-card
flat
width="400"
class="mx-auto"
>
<v-card-title class="display-2 mb-12 justify-center text-center">
System info
@ -156,6 +154,16 @@
<strong>{{ Math.ceil(value) }}%</strong>
</template>
</v-progress-linear>
<v-divider class="mt-12" />
<v-card-actions>
<v-btn
depressed
disabled
>
factory reset
</v-btn>
</v-card-actions>
</v-card>
</div>
</template>

@ -2,8 +2,6 @@
<div class="pa-5">
<v-card
flat
width="400"
class="mx-auto"
>
<v-card-title class="display-2 mb-12 justify-center text-center">
Weather settings
@ -11,8 +9,9 @@
<v-card-text>
<v-text-field
v-model="settings.weather.api"
v-model="form.api"
label="OpenWeatherMap API key"
prepend-icon="$vpn_key"
>
<template #append-outer>
<v-btn
@ -26,38 +25,47 @@
</v-text-field>
<weather-find-location
:api="settings.weather.api"
:location.sync="settings.weather.location"
:lang="settings.weather.lang"
:unit="settings.weather.unit"
:api="form.api"
:location.sync="form.location"
:placeholder="form.name"
:lang="form.lang"
:unit="form.unit"
/>
<v-select
v-model="settings.weather.lang"
:disabled="!settings.weather.api"
:items="weatherLang"
label="Language"
/>
<v-select
v-model="settings.weather.unit"
:disabled="!settings.weather.api"
v-model="form.unit"
:disabled="!form.api"
:items="weatherUnit"
label="Units"
prepend-icon=" "
/>
<v-select
v-model="form.lang"
:disabled="!form.api"
:items="weatherLang"
label="Language"
prepend-icon="$translate"
/>
</v-card-text>
<v-divider class="mt-12" />
<v-card-actions>
<v-btn text>
Cancel
<v-btn
text
@click="resetChanges"
>
Restore
</v-btn>
<v-spacer />
<v-btn
color="primary"
text
:loading="isProcessing"
depressed
@click="commitChanges"
>
Submit
<v-icon left>
$done
</v-icon>
Save
</v-btn>
</v-card-actions>
</v-card>
@ -65,15 +73,25 @@
</template>
<script>
import { mapState, mapGetters, mapActions } from 'vuex'
import { mapState, mapActions, mapMutations } from 'vuex'
import WeatherFindLocation from '@/components/WeatherFindLocation'
export default {
components: {
WeatherFindLocation,
},
data: () => ({
isProcessing: false,
form: {
api: '',
location: '',
name: '',
lang: '',
unit: '',
},
// @see https://openweathermap.org/current#multi
weatherLang: [
{ text: 'Use system settings', value: '' },
{ text: 'English', value: 'en' },
{ text: 'Deutsch', value: 'de' },
],
@ -87,13 +105,36 @@
'stats',
'settings',
]),
...mapGetters([
]),
},
created () {
this.resetChanges()
},
methods: {
...mapMutations(['updateSettings']),
...mapActions(['saveSettings']),
commitChanges () {
this.saveSettings()
this.isProcessing = true
// TODO
this.updateSettings({
weather_: {
api: '',
locationId: 0,
},
})
this.saveSettings().then(() => {
this.isProcessing = false
})
},
resetChanges () {
this.form.api = this.settings.weather.api
this.form.location = this.settings.weather.location
this.form.name = 'freilassing' // this.settings.weather.name
this.form.lang = this.settings.weather.lang
this.form.unit = this.settings.weather.unit
},
},
}

@ -2,8 +2,6 @@
<div class="pa-5">
<v-card
flat
width="400"
class="mx-auto"
>
<v-card-title class="display-2 mb-12 justify-center text-center">
Wifi settings

Loading…
Cancel
Save