mirror of
https://github.com/paperdash/device-epd.git
synced 2024-11-04 12:00:27 +00:00
autocomplete for weather location search #23
This commit is contained in:
parent
d45c978b61
commit
54ed1b27fd
107
app/src/components/WeatherFindLocation.vue
Normal file
107
app/src/components/WeatherFindLocation.vue
Normal file
@ -0,0 +1,107 @@
|
||||
<template>
|
||||
<v-autocomplete
|
||||
:disabled="!api"
|
||||
v-model="model"
|
||||
:items="entries"
|
||||
:loading="isLoading"
|
||||
:search-input.sync="search"
|
||||
hide-no-data
|
||||
hide-selected
|
||||
item-text="name"
|
||||
item-value="id"
|
||||
label="i8n:Location"
|
||||
placeholder="i8n:Start typing to Search"
|
||||
_return-object
|
||||
>
|
||||
<template v-slot:item="{ item }">
|
||||
<v-list-item 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>
|
||||
<v-list-item></v-list-item>
|
||||
</template>
|
||||
</v-autocomplete>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
location: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
api: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
lang: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
unit: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
entries: [],
|
||||
isLoading: false,
|
||||
model: null,
|
||||
search: null
|
||||
}),
|
||||
watch: {
|
||||
model(val) {
|
||||
this.$emit("update:location", val);
|
||||
},
|
||||
search(val) {
|
||||
if (!val || val.length < 3) return;
|
||||
|
||||
// Items have already been requested
|
||||
if (this.isLoading) return;
|
||||
|
||||
this.isLoading = true;
|
||||
|
||||
// search
|
||||
let url = "https://api.openweathermap.org/data/2.5/find?appid=";
|
||||
url += this.api;
|
||||
url += "&lang=" + this.lang;
|
||||
url += "&units=" + this.unit;
|
||||
url += "&type=like&sort=population&cnt=10";
|
||||
url += "&q=" + val;
|
||||
|
||||
fetch(url)
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
this.count = res.count;
|
||||
this.entries = res.list;
|
||||
})
|
||||
.catch(err => {
|
||||
console.log(err);
|
||||
})
|
||||
.finally(() => (this.isLoading = false));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCountryFlag(code) {
|
||||
return (
|
||||
"http://openweathermap.org/images/flags/" + code.toLowerCase() + ".png"
|
||||
);
|
||||
},
|
||||
getConditionIcon(code) {
|
||||
return "http://openweathermap.org/img/wn/" + code + "@2x.png";
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
@ -1,219 +1,255 @@
|
||||
<template>
|
||||
<v-layout fluid fill-height>
|
||||
<template v-if="isLoading">
|
||||
<v-overlay :absolute="true" :value="true">
|
||||
<v-progress-circular indeterminate size="64"></v-progress-circular>
|
||||
</v-overlay>
|
||||
</template>
|
||||
<v-layout fluid fill-height>
|
||||
<template v-if="isLoading">
|
||||
<v-overlay :absolute="true" :value="true">
|
||||
<v-progress-circular indeterminate size="64"></v-progress-circular>
|
||||
</v-overlay>
|
||||
</template>
|
||||
|
||||
<v-container>
|
||||
<v-snackbar
|
||||
v-model="isSnackbar"
|
||||
:timeout="3000"
|
||||
color="success"
|
||||
>
|
||||
i8n:saved
|
||||
</v-snackbar>
|
||||
<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-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
|
||||
:items="deviceOrientation"
|
||||
v-model="settings.device.angle"
|
||||
label="i8n:Orientation"
|
||||
placeholder=""
|
||||
></v-select>
|
||||
<v-card v-if="settings" class="mx-auto" width="400">
|
||||
<v-tabs-items v-model="tab">
|
||||
<v-tab-item>
|
||||
<v-card-text>
|
||||
<v-select
|
||||
:items="deviceOrientation"
|
||||
v-model="settings.device.angle"
|
||||
label="i8n:Orientation"
|
||||
placeholder
|
||||
></v-select>
|
||||
|
||||
<v-select
|
||||
:items="deviceTheme"
|
||||
v-model="settings.device.theme"
|
||||
label="i8n:Theme"
|
||||
placeholder=""
|
||||
></v-select>
|
||||
</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-text-field>
|
||||
</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>
|
||||
<v-select
|
||||
:items="deviceTheme"
|
||||
v-model="settings.device.theme"
|
||||
label="i8n:Theme"
|
||||
placeholder
|
||||
></v-select>
|
||||
</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-text-field>
|
||||
</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 class="mt-5" v-if="0">
|
||||
<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
|
||||
label="i8n:OpenWeatherMap"
|
||||
v-model="settings.weather.api"
|
||||
placeholder="###"
|
||||
></v-text-field>
|
||||
<v-text-field
|
||||
label="i8n:Location"
|
||||
v-model="settings.weather.location"
|
||||
placeholder=""
|
||||
></v-text-field>
|
||||
<v-select
|
||||
:items="weatherLang"
|
||||
v-model="settings.weather.lang"
|
||||
label="i8n:Lang"
|
||||
placeholder=""
|
||||
></v-select>
|
||||
<v-select
|
||||
:items="weatherUnit"
|
||||
v-model="settings.weather.unit"
|
||||
label="i8n:Units"
|
||||
placeholder=""
|
||||
></v-select>
|
||||
</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>
|
||||
<ul class="mt-5" v-if="0">
|
||||
<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
|
||||
label="i8n:OpenWeatherMap"
|
||||
v-model="settings.weather.api"
|
||||
placeholder="###"
|
||||
></v-text-field>
|
||||
|
||||
<v-text-field
|
||||
label="i8n:Cloud server"
|
||||
v-model="settings.cloud.url"
|
||||
placeholder="i8n:https://"
|
||||
></v-text-field>
|
||||
<weather-find-location
|
||||
:api="settings.weather.api"
|
||||
:location.sync="settings.weather.location"
|
||||
:lang="settings.weather.lang"
|
||||
:unit="settings.weather.unit"
|
||||
></weather-find-location>
|
||||
|
||||
<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-select
|
||||
:items="weatherLang"
|
||||
v-model="settings.weather.lang"
|
||||
label="i8n:Lang"
|
||||
placeholder
|
||||
></v-select>
|
||||
<v-select
|
||||
:items="weatherUnit"
|
||||
v-model="settings.weather.unit"
|
||||
label="i8n:Units"
|
||||
placeholder
|
||||
></v-select>
|
||||
</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-card-actions>
|
||||
<v-spacer></v-spacer>
|
||||
<v-text-field
|
||||
label="i8n:Cloud server"
|
||||
v-model="settings.cloud.url"
|
||||
placeholder="i8n:https://"
|
||||
></v-text-field>
|
||||
|
||||
<v-btn
|
||||
text
|
||||
color="primary"
|
||||
@click="onSave()"
|
||||
>
|
||||
i8n:Save
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-container>
|
||||
</v-layout>
|
||||
<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-spacer></v-spacer>
|
||||
|
||||
<v-btn text color="primary" @click="onSave()">i8n:Save</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-container>
|
||||
</v-layout>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import apiDevice from '../api/device'
|
||||
import apiDevice from "../api/device";
|
||||
import weatherFindLocation from "./../components/WeatherFindLocation";
|
||||
|
||||
export default {
|
||||
name: "Settings",
|
||||
data: () => ({
|
||||
isLoading: true,
|
||||
isSnackbar: false,
|
||||
tab: 0,
|
||||
export default {
|
||||
name: "Settings",
|
||||
components: {
|
||||
weatherFindLocation
|
||||
},
|
||||
data: () => ({
|
||||
isLoading: true,
|
||||
isSnackbar: false,
|
||||
tab: 0,
|
||||
|
||||
settings: null,
|
||||
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'}
|
||||
],
|
||||
// 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: 'Deutsch', value: 'de'},
|
||||
{text: 'English', value: 'en'}
|
||||
],
|
||||
weatherUnit: [
|
||||
{text: 'Metrisch', value: 'metric'},
|
||||
{text: 'Imperial', value: ''}
|
||||
],
|
||||
// @see https://openweathermap.org/current#multi
|
||||
weatherLang: [
|
||||
{ text: "English", value: "en" },
|
||||
{ text: "Deutsch", value: "de" }
|
||||
],
|
||||
weatherUnit: [
|
||||
{ text: "Imperial", value: "" },
|
||||
{ text: "Metrisch", value: "metric" }
|
||||
]
|
||||
}),
|
||||
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.update = {
|
||||
component: () =>
|
||||
import(
|
||||
/* webpackChunkName: "icons" */ "!vue-svg-loader!@material-icons/svg/svg/update/baseline.svg"
|
||||
)
|
||||
};
|
||||
|
||||
}),
|
||||
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.update = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/update/baseline.svg')}
|
||||
apiDevice.getSettings(settings => {
|
||||
this.settings = settings;
|
||||
|
||||
apiDevice.getSettings(settings => {
|
||||
this.settings = settings
|
||||
this.isLoading = false;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
onSave() {
|
||||
this.isLoading = true;
|
||||
|
||||
this.isLoading = false
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
onSave () {
|
||||
this.isLoading = true
|
||||
|
||||
apiDevice.putSettings(this.settings, (data) => {
|
||||
console.log(data)
|
||||
this.isLoading = false
|
||||
this.isSnackbar = true
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
apiDevice.putSettings(this.settings, data => {
|
||||
console.log(data);
|
||||
this.isLoading = false;
|
||||
this.isSnackbar = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
>>>.v-input.text-right .v-text-field__slot > input {
|
||||
text-align: right;
|
||||
>>> .v-input.text-right .v-text-field__slot > input {
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
|
Loading…
Reference in New Issue
Block a user