eslint re-formatting

pull/1/head
Thomas Ballmann 4 years ago
parent f47fe28388
commit 20ddc7dc3e

@ -10,6 +10,6 @@ trim_trailing_whitespace = true
# The indent size used in the `package.json` file cannot be changed
# https://github.com/npm/npm/pull/3180#issuecomment-16336516
[{*.yml,*.yaml,package.json,.eslintrc.js}]
[{*.yml,*.yaml,package.json,.eslintrc.js,vue.config.js,*.js}]
indent_style = space
indent_size = 2

@ -1,5 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
'@vue/cli-plugin-babel/preset',
],
}

@ -1,135 +1,109 @@
<template>
<v-app _style="background: #e2e2e2">
<template v-if="isLoading">
<v-overlay :absolute="true" :value="true">
<v-progress-circular indeterminate size="64"></v-progress-circular>
</v-overlay>
<v-app _style="background: #e2e2e2">
<template v-if="isLoading">
<v-overlay
:absolute="true"
:value="true"
>
<v-progress-circular
indeterminate
size="64"
/>
</v-overlay>
</template>
<template v-else>
<v-system-bar
app
dark
color="primary"
_window
_lights-out
>
<span>paperdash.io</span>
<v-spacer />
<span>{{ settings.device.name }}</span>
<v-spacer />
<template v-if="stats.wifi.connected">
<v-icon>{{ stats.wifi.rssi | wifiIcon(0) }}</v-icon>
<span>{{ stats.device.time | moment("LT") }}</span>
</template>
<template v-else>
<!--
<v-navigation-drawer
v-model="drawer"
app
>
</v-navigation-drawer>
-->
<v-system-bar app dark color="primary" _window _lights-out>
<span>paperdash.io</span>
<v-spacer></v-spacer>
<span>{{ settings.device.name }}</span>
<v-spacer></v-spacer>
<template v-if="stats.wifi.connected">
<v-icon>{{ stats.wifi.rssi | wifiIcon(0) }}</v-icon>
<span>{{ stats.device.time | moment("LT") }}</span>
</template>
<template v-else>
<v-btn to="/setup/wifi" icon>
<v-icon color="red">$signalWifiOff</v-icon>
</v-btn>
</template>
</v-system-bar>
<!--
<v-app-bar _bottom dense app color="orange lighten-1" dark _short>
<v-app-bar-nav-icon @click="drawer = !drawer">
<v-icon>$device</v-icon>
</v-app-bar-nav-icon>
<v-toolbar-title>paperdash.io</v-toolbar-title>
<v-spacer></v-spacer>
<template v-for="(link, i) in items">
<v-btn icon :to="link.to" :key="i">
<v-icon v-text="link.icon" />
</v-btn>
</template>
</v-app-bar>
-->
<!--
<v-bottom-navigation
v-model="bottomNav"
dark
shift
app
>
<v-btn>
<span>Device</span>
<v-icon>$device</v-icon>
</v-btn>
<v-btn>
<span>Settings</span>
<v-icon>$settings</v-icon>
</v-btn>
</v-bottom-navigation>
-->
<v-content>
<v-container fluid fill-height class="align-start">
<transition-page>
<router-view></router-view>
</transition-page>
</v-container>
</v-content>
</template>
</v-app>
<template v-else>
<v-btn
to="/setup/wifi"
icon
>
<v-icon color="red">
$signalWifiOff
</v-icon>
</v-btn>
</template>
</v-system-bar>
<v-main>
<v-container
fluid
class="align-start fill-height"
>
<transition-page>
<router-view />
</transition-page>
</v-container>
</v-main>
</template>
</v-app>
</template>
<script>
import apiDevice from './api/device'
import "@/assets/app.css"
import transitionPage from "@/components/TransitionPage"
export default {
components: {
transitionPage
},
data: () => ({
isLoading: true,
settings: null
}),
created () {
apiDevice.getSettings(settings => {
this.settings = settings;
this.autoReloadStats();
});
},
watch: {
stats () {
this.isLoading = false
}
},
computed: {
stats () {
return this.$root._data.stats;
},
},
methods: {
autoReloadStats () {
apiDevice.getStats(stats => {
// give esp some extra time befor fetch new data
stats.playlist.remaining += 2
// reset old so reactive watcher can detect a change
if (this.$root._data.stats) {
this.$root._data.stats.playlist.remaining = 0
}
this.$root._data.stats = stats
setTimeout(() => {
this.autoReloadStats()
}, stats.playlist.remaining * 1000)
})
}
}
};
import apiDevice from './api/device'
import '@/assets/app.css'
import transitionPage from '@/components/TransitionPage'
export default {
components: {
transitionPage,
},
data: () => ({
isLoading: true,
settings: null,
}),
computed: {
stats () {
return this.$root._data.stats
},
},
watch: {
stats () {
this.isLoading = false
},
},
created () {
apiDevice.getSettings(settings => {
this.settings = settings
this.autoReloadStats()
})
},
methods: {
autoReloadStats () {
apiDevice.getStats(stats => {
// give esp some extra time befor fetch new data
stats.playlist.remaining += 2
// reset old so reactive watcher can detect a change
if (this.$root._data.stats) {
this.$root._data.stats.playlist.remaining = 0
}
this.$root._data.stats = stats
setTimeout(() => {
this.autoReloadStats()
}, stats.playlist.remaining * 1000)
})
},
},
}
</script>
<style scoped>
</style>
</style>

@ -2,149 +2,146 @@
* Mocking client-server processing
*/
// eslint-disable-next-line
import axios from 'axios'
// eslint-disable-next-line
const _settings = {
system: {
country: "AT",
language: "de",
timezone: "",
utc: 0,
dst: 0,
wifi: ""
},
device: {
theme: "black",
name: "dummy"
},
playlist: {
timer: 60
},
weather: {
api: "",
location: 2766824,
lang: "de",
unit: "metric"
},
cloud: {
mode: "active",
url: "http://",
token: "###"
}
system: {
country: 'AT',
language: 'de',
timezone: '',
utc: 0,
dst: 0,
wifi: '',
},
device: {
theme: 'black',
name: 'dummy',
},
playlist: {
timer: 60,
},
weather: {
api: '',
location: 2766824,
lang: 'de',
unit: 'metric',
},
cloud: {
mode: 'active',
url: 'http://',
token: '###',
},
}
// eslint-disable-next-line
const _stats = {
"wifi": {
"ssid": "xd-design.info",
"connected": true,
"ip": "192.168.178.62",
"mac": "30:AE:A4:21:20:40",
"channel": 1,
"dns": "192.168.178.1",
"gateway": "192.168.178.1"
},
"device": {
"heap": 120496,
"bootCycle": 1,
"screen": {
"width": 640,
"height": 384
},
"fs": {
"total": 1860161,
"used": 1107663,
"free": 752498
}
},
"playlist": {
"current": "Calendar",
"remaining": 22
},
"capability": [
"png",
"wbmp"
],
"cloud": {
"sleep": 10
}
wifi: {
ssid: 'xd-design.info',
connected: true,
ip: '192.168.178.62',
mac: '30:AE:A4:21:20:40',
channel: 1,
dns: '192.168.178.1',
gateway: '192.168.178.1',
},
device: {
heap: 120496,
bootCycle: 1,
screen: {
width: 640,
height: 384,
},
fs: {
total: 1860161,
used: 1107663,
free: 752498,
},
},
playlist: {
current: 'Calendar',
remaining: 22,
},
capability: [
'png',
'wbmp',
],
cloud: {
sleep: 10,
},
}
// eslint-disable-next-line
const _wifiScan = [{ "rssi": -59, "ssid": "paperdash.io", "bssid": "38:10:D5:34:80:1B", "channel": 11, "secure": 3 }, { "rssi": -75, "ssid": "FRITZ!Box 7430 JI", "bssid": "38:10:D5:5D:FE:7C", "channel": 1, "secure": 3 }, { "rssi": -87, "ssid": "Vodafone Hotspot", "bssid": "AA:0E:14:BD:50:ED", "channel": 1, "secure": 0 }, { "rssi": -88, "ssid": "WLAN-548426", "bssid": "E0:60:66:55:7F:C5", "channel": 1, "secure": 3 }, { "rssi": -89, "ssid": "Familie Kalinowski", "bssid": "C8:0E:14:BD:50:ED", "channel": 1, "secure": 3 }, { "rssi": -91, "ssid": "WLAN-507287", "bssid": "E0:60:66:48:6C:6B", "channel": 1, "secure": 3 }, { "rssi": -94, "ssid": "TP-LINK_7238", "bssid": "A4:2B:B0:D8:72:38", "channel": 3, "secure": 3 }]
import axios from 'axios'
export default {
/**
* @param cb
* @returns {PromiseLike<any> | Promise<any>}
*/
getSettings(cb) {
//return cb(_settings);
// eslint-disable-next-line
return axios
.get('/api/settings')
.then(response => cb(response.data))
},
/**
* @returns {IDBRequest<IDBValidKey> | Promise<void>}
*/
putSettings(settings, cb) {
return axios
.put('/api/settings', settings, {
headers: {
'Content-Type': 'application/json'
}
})
.then(response => cb(response.data))
},
/**
* scan for wifi in range
* @param {*} cb
*/
wifiScan(cb) {
return axios
.get('/api/wifi/scan')
.then(response => cb(response.data))
},
/**
* connect to wifi
* @param {*} ssid
* @param {*} password
* @param {*} cb
*/
wifiConnect(ssid, password, cb) {
return axios
.post('/api/wifi/connect', {
ssid: ssid,
password: password
}, {
headers: {
'Content-Type': 'application/json'
}
})
.then(response => cb(response.data))
},
/**
/**
* @param cb
* @returns {PromiseLike<any> | Promise<any>}
*/
getSettings (cb) {
// return cb(_settings);
// eslint-disable-next-line
return axios
.get('/api/settings')
.then(response => cb(response.data))
},
/**
* @returns {IDBRequest<IDBValidKey> | Promise<void>}
*/
putSettings (settings, cb) {
return axios
.put('/api/settings', settings, {
headers: {
'Content-Type': 'application/json',
},
})
.then(response => cb(response.data))
},
/**
* scan for wifi in range
* @param {*} cb
*/
wifiScan (cb) {
return axios
.get('/api/wifi/scan')
.then(response => cb(response.data))
},
/**
* connect to wifi
* @param {*} ssid
* @param {*} password
* @param {*} cb
*/
wifiConnect (ssid, password, cb) {
return axios
.post('/api/wifi/connect', {
ssid: ssid,
password: password,
}, {
headers: {
'Content-Type': 'application/json',
},
})
.then(response => cb(response.data))
},
/**
* @param cb
* @returns {PromiseLike<any> | Promise<any>}
*/
getStats(cb) {
//return cb(_stats);
// eslint-disable-next-line
return axios
.get('/stats')
.then(response => cb(response.data))
}
getStats (cb) {
// return cb(_stats);
// eslint-disable-next-line
return axios
.get('/stats')
.then(response => cb(response.data))
},
}

@ -2,195 +2,196 @@
* Mocking client-server processing
*/
// eslint-disable-next-line
import axios from 'axios'
// eslint-disable-next-line
const _weather = {
coord: { lon: 13.04, lat: 47.8 },
weather: [
{ id: 800, main: "Clear", description: "Klarer Himmel", icon: "01d" }
],
base: "stations",
main: {
temp: 2.75,
feels_like: 0.09,
temp_min: 0,
temp_max: 6.11,
pressure: 1023,
humidity: 69
},
visibility: 10000,
wind: { speed: 0.5 },
clouds: { all: 9 },
dt: 1584260150,
sys: {
type: 1,
id: 6877,
country: "AT",
sunrise: 1584249628,
sunset: 1584292379
},
timezone: 3600,
id: 2766824,
name: "Salzburg",
cod: 200
coord: { lon: 13.04, lat: 47.8 },
weather: [
{ id: 800, main: 'Clear', description: 'Klarer Himmel', icon: '01d' },
],
base: 'stations',
main: {
temp: 2.75,
feels_like: 0.09,
temp_min: 0,
temp_max: 6.11,
pressure: 1023,
humidity: 69,
},
visibility: 10000,
wind: { speed: 0.5 },
clouds: { all: 9 },
dt: 1584260150,
sys: {
type: 1,
id: 6877,
country: 'AT',
sunrise: 1584249628,
sunset: 1584292379,
},
timezone: 3600,
id: 2766824,
name: 'Salzburg',
cod: 200,
}
// eslint-disable-next-line
const _forecast = {
city: {
id: 2766824,
name: "Salzburg",
coord: { lon: 13.044, lat: 47.7994 },
country: "AT",
population: 0,
timezone: 3600
},
cod: "200",
message: 0.0878612,
cnt: 4,
list: [
{
dt: 1584270000,
sunrise: 1584249627,
sunset: 1584292378,
temp: {
day: 14.02,
min: 1.59,
max: 14.02,
night: 1.59,
eve: 6.4,
morn: 2.88
},
feels_like: { day: 9.75, night: -2.31, eve: 2.85, morn: -0.11 },
pressure: 1021,
humidity: 42,
weather: [
{
id: 801,
main: "Clouds",
description: "Ein paar Wolken",
icon: "02d"
}
],
speed: 3.55,
deg: 105,
clouds: 15
},
{
dt: 1584356400,
sunrise: 1584335904,
sunset: 1584378865,
temp: {
day: 13.15,
min: 0.88,
max: 13.15,
night: 4.3,
eve: 6.25,
morn: 0.88
},
feels_like: { day: 10.56, night: 1.77, eve: 4.16, morn: -2.11 },
pressure: 1022,
humidity: 46,
weather: [
{
id: 800,
main: "Clear",
description: "Klarer Himmel",
icon: "01d"
}
],
speed: 1.26,
deg: 349,
clouds: 0
},
{
dt: 1584442800,
sunrise: 1584422182,
sunset: 1584465351,
temp: {
day: 13.8,
min: 3.73,
max: 14.05,
night: 9.64,
eve: 9.75,
morn: 3.73
},
feels_like: { day: 11.71, night: 7.26, eve: 7.47, morn: 1.33 },
pressure: 1029,
humidity: 53,
weather: [
{ id: 804, main: "Clouds", description: "Bedeckt", icon: "04d" }
],
speed: 1.21,
deg: 331,
clouds: 100
},
{
dt: 1584529200,
sunrise: 1584508459,
sunset: 1584551838,
temp: {
day: 16.55,
min: 6.35,
max: 16.55,
night: 7.1,
eve: 9.94,
morn: 6.35
},
feels_like: { day: 14.61, night: 5.37, eve: 8.03, morn: 4.56 },
pressure: 1028,
humidity: 52,
weather: [
{
id: 800,
main: "Clear",
description: "Klarer Himmel",
icon: "01d"
}
],
speed: 1.67,
deg: 39,
clouds: 7
}
]
city: {
id: 2766824,
name: 'Salzburg',
coord: { lon: 13.044, lat: 47.7994 },
country: 'AT',
population: 0,
timezone: 3600,
},
cod: '200',
message: 0.0878612,
cnt: 4,
list: [
{
dt: 1584270000,
sunrise: 1584249627,
sunset: 1584292378,
temp: {
day: 14.02,
min: 1.59,
max: 14.02,
night: 1.59,
eve: 6.4,
morn: 2.88,
},
feels_like: { day: 9.75, night: -2.31, eve: 2.85, morn: -0.11 },
pressure: 1021,
humidity: 42,
weather: [
{
id: 801,
main: 'Clouds',
description: 'Ein paar Wolken',
icon: '02d',
},
],
speed: 3.55,
deg: 105,
clouds: 15,
},
{
dt: 1584356400,
sunrise: 1584335904,
sunset: 1584378865,
temp: {
day: 13.15,
min: 0.88,
max: 13.15,
night: 4.3,
eve: 6.25,
morn: 0.88,
},
feels_like: { day: 10.56, night: 1.77, eve: 4.16, morn: -2.11 },
pressure: 1022,
humidity: 46,
weather: [
{
id: 800,
main: 'Clear',
description: 'Klarer Himmel',
icon: '01d',
},
],
speed: 1.26,
deg: 349,
clouds: 0,
},
{
dt: 1584442800,
sunrise: 1584422182,
sunset: 1584465351,
temp: {
day: 13.8,
min: 3.73,
max: 14.05,
night: 9.64,
eve: 9.75,
morn: 3.73,
},
feels_like: { day: 11.71, night: 7.26, eve: 7.47, morn: 1.33 },
pressure: 1029,
humidity: 53,
weather: [
{ id: 804, main: 'Clouds', description: 'Bedeckt', icon: '04d' },
],
speed: 1.21,
deg: 331,
clouds: 100,
},
{
dt: 1584529200,
sunrise: 1584508459,
sunset: 1584551838,
temp: {
day: 16.55,
min: 6.35,
max: 16.55,
night: 7.1,
eve: 9.94,
morn: 6.35,
},
feels_like: { day: 14.61, night: 5.37, eve: 8.03, morn: 4.56 },
pressure: 1028,
humidity: 52,
weather: [
{
id: 800,
main: 'Clear',
description: 'Klarer Himmel',
icon: '01d',
},
],
speed: 1.67,
deg: 39,
clouds: 7,
},
],
}
import axios from 'axios'
export default {
/**
* @param cb
* @returns {PromiseLike<any> | Promise<any>}
*/
getCurrent(cb) {
//return cb(_weather);
getCurrent (cb) {
// return cb(_weather);
// eslint-disable-next-line
return axios
.get('/fs/weatherCurrent.json')
.then(response => cb(response.data))
},
// eslint-disable-next-line
return axios
.get('/fs/weatherCurrent.json')
.then(response => cb(response.data))
},
/**
* @param cb
* @returns {PromiseLike<any> | Promise<any>}
*/
getForecast(cb) {
//return cb(_forecast);
getForecast (cb) {
// return cb(_forecast);
// eslint-disable-next-line
return axios
.get('/fs/weatherForecast.json')
.then(response => cb(response.data))
},
// eslint-disable-next-line
return axios
.get('/fs/weatherForecast.json')
.then(response => cb(response.data))
},
/**
/**
* @param cb
* @returns {PromiseLike<any> | Promise<any>}
*/
updateWeather(cb) {
return axios
.get('/api/update?weather=1')
.then(response => cb(response.data))
},
updateWeather (cb) {
return axios
.get('/api/update?weather=1')
.then(response => cb(response.data))
},
}

@ -8,19 +8,27 @@
<v-list-item-title>{{ stats.wifi.ssid }}</v-list-item-title>
</v-list-item-content>
<v-list-item-avatar>
<v-avatar color="secondary lighten-3" size="24">
<v-avatar
color="secondary lighten-3"
size="24"
>
<span class="white--text headline caption">{{ stats.wifi.channel }}</span>
</v-avatar>
</v-list-item-avatar>
</v-list-item>
<v-divider class="mx-4"></v-divider>
<v-divider class="mx-4" />
<v-list dense>
<v-list-item v-for="key in wifiStats" :key="key">
<v-list-item
v-for="key in wifiStats"
:key="key"
>
<v-list-item-title>{{ key }}</v-list-item-title>
<v-list-item-subtitle class="text-right">{{ stats.wifi[key] }}</v-list-item-subtitle>
<v-list-item-subtitle class="text-right">
{{ stats.wifi[key] }}
</v-list-item-subtitle>
</v-list-item>
</v-list>
@ -32,43 +40,56 @@
<v-list-item-title>i8n:Storage</v-list-item-title>
</v-list-item-content>
<v-list-item-avatar>
<v-progress-circular :rotate="-90" :value="fsUsage" class="caption">{{ fsUsage }}</v-progress-circular>
<v-progress-circular
:rotate="-90"
:value="fsUsage"
class="caption"
>
{{ fsUsage }}
</v-progress-circular>
</v-list-item-avatar>
</v-list-item>
<v-divider class="mx-4"></v-divider>
<v-divider class="mx-4" />
<v-list dense class="pb-0">
<v-list
dense
class="pb-0"
>
<v-list-item>
<v-list-item-title>Total</v-list-item-title>
<v-list-item-subtitle class="text-right">{{ fs.total | prettyBytes }}</v-list-item-subtitle>
<v-list-item-subtitle class="text-right">
{{ fs.total | prettyBytes }}
</v-list-item-subtitle>
</v-list-item>
<v-list-item>
<v-list-item-title>Free</v-list-item-title>
<v-list-item-subtitle class="text-right">{{ fs.free | prettyBytes }}</v-list-item-subtitle>
<v-list-item-subtitle class="text-right">
{{ fs.free | prettyBytes }}
</v-list-item-subtitle>
</v-list-item>
</v-list>
</v-card>
</template>
<script>
export default {
data: () => ({
wifiStats: ["ip", "gateway", "dns", "mac"]
}),
computed: {
stats() {
return this.$root._data.stats;
export default {
data: () => ({
wifiStats: ['ip', 'gateway', 'dns', 'mac'],
}),
computed: {
stats () {
return this.$root._data.stats
},
fsUsage () {
return Math.round(
(100 / this.stats.device.fs.total) * this.stats.device.fs.used,
)
},
fs () {
return this.stats.device.fs
},
},
fsUsage() {
return Math.round(
(100 / this.stats.device.fs.total) * this.stats.device.fs.used
);
},
fs() {
return this.stats.device.fs;
}
}
};
</script>

@ -1,10 +1,37 @@
<template>
<v-card color="grey lighten-4" _outlined>
<v-img :aspect-ratio="16/9" :src="device_screen_src"></v-img>
<v-card
color="grey lighten-4"
_outlined
>
<v-img
:aspect-ratio="16/9"
:src="device_screen_src"
>
<template #placeholder>
<v-row
class="fill-height ma-0 grey"
align="center"
justify="center"
>
<v-progress-circular
indeterminate
color="grey lighten-5"
/>
</v-row>
</template>
</v-img>
<v-card-actions style="position: relative">
<router-link to="/settings">
<v-btn color="orange" dark absolute top right fab elevation="2">
<v-btn
color="orange"
dark
absolute
top
right
fab
elevation="2"
>
<v-icon>$settings</v-icon>
</v-btn>
</router-link>
@ -14,46 +41,48 @@
:size="50"
:width="5"
:value="playlistProgress"
>{{ playlistRemainingCountdown }}</v-progress-circular>
>
{{ playlistRemainingCountdown }}
</v-progress-circular>
<span class="headline pl-3">{{ playlistCurrent }}</span>
</v-card-actions>
</v-card>
</template>
<script>
export default {
data: () => ({
device_screen_src: null,
playlistRemainingCountdown: 0
}),
created() {
this.playlistRemainingCountdown = this.playlistRemaining;
this.device_screen_src = "/current-image2?q=10&" + Date.now();
setInterval(() => {
if (this.playlistRemainingCountdown > 0) {
this.playlistRemainingCountdown--;
}
}, 1000);
},
computed: {
playlistProgress() {
return parseInt((100 / 60) * this.playlistRemainingCountdown);
export default {
data: () => ({
device_screen_src: null,
playlistRemainingCountdown: 0,
}),
computed: {
playlistProgress () {
return parseInt((100 / 60) * this.playlistRemainingCountdown)
},
playlistRemaining () {
return this.$root._data.stats.playlist.remaining
},
playlistCurrent () {
return this.$root._data.stats.playlist.current
},
},
watch: {
playlistRemaining (val) {
if (val > 0) {
this.playlistRemainingCountdown = val
this.device_screen_src = '/current-image3?' + Date.now()
}
},
},
playlistRemaining() {
return this.$root._data.stats.playlist.remaining;
created () {
this.playlistRemainingCountdown = this.playlistRemaining
this.device_screen_src = '/current-image3?' + Date.now()
setInterval(() => {
if (this.playlistRemainingCountdown > 0) {
this.playlistRemainingCountdown--
}
}, 1000)
},
playlistCurrent() {
return this.$root._data.stats.playlist.current;
}
},
watch: {
playlistRemaining(val) {
if (val > 0) {
this.playlistRemainingCountdown = val;
this.device_screen_src = "/current-image2?q=10&" + Date.now();
}
}
}
};
</script>

@ -2,46 +2,46 @@
<v-card flat>
<v-card-text>
<v-text-field
label="i8n:OpenWeatherMap API key"
v-model="settings.weather.api"
label="i8n:OpenWeatherMap API key"
placeholder="###"
></v-text-field>
/>
<weather-find-location
:api="settings.weather.api"
:location.sync="settings.weather.location"
:lang="lang"
:unit="unit"
></weather-find-location>
/>
</v-card-text>
</v-card>
</template>
<script>
import weatherFindLocation from "@/components/WeatherFindLocation";
import weatherFindLocation from '@/components/WeatherFindLocation'
export default {
props: {
settings: {
type: Object,
required: true
}
},
components: {
weatherFindLocation
},
data: () => ({
}),
computed: {
lang() {
return this.settings.language || "EN";
export default {
components: {
weatherFindLocation,
},
props: {
settings: {
type: Object,
required: true,
},
},
data: () => ({
}),
computed: {
lang () {
return this.settings.language || 'EN'
},
unit () {
return this.settings.language === 'EN' ? '' : 'metric'
},
},
methods: {
commit () {},
},
unit() {
return this.settings.language === "EN" ? "" : "metric";
}
},
methods: {
commit() {}
}
};
</script>

@ -1,10 +1,19 @@
<template>
<v-card flat>
<v-toolbar dark color="primary">
<v-btn icon dark @click="$emit('cancel')">
<v-toolbar
dark
color="primary"
>
<v-btn
icon
dark
@click="$emit('cancel')"
>
<v-icon>$close</v-icon>
</v-btn>
<v-toolbar-title class="pl-0">Enter the password for "{{ ssid }}"</v-toolbar-title>
<v-toolbar-title class="pl-0">
Enter the password for "{{ ssid }}"
</v-toolbar-title>
<v-progress-linear
:active="isConnecting"
@ -12,7 +21,7 @@
absolute
bottom
color="deep-orange accent-4"
></v-progress-linear>
/>
</v-toolbar>
<v-card-text class="pa-5">
@ -22,37 +31,39 @@
:type="show1 ? 'text' : 'password'"
label="i8n:Password"
@click:append="show1 = !show1"
></v-text-field>
/>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-spacer />
<v-btn
depressed
:disabled="password === ''"
color="primary"
@click="onConnect(ssid, password)"
>i8n:Join</v-btn>
>
i8n:Join
</v-btn>
</v-card-actions>
</v-card>
</template>
<script>
export default {
props: {
ssid: {
type: String,
required: true
export default {
props: {
ssid: {
type: String,
required: true,
},
onConnect: {
type: Function,
required: true,
},
},
onConnect: {
type: Function,
required: true
}
},
data: () => ({
isConnecting: false,
password: "",
show1: false
})
};
data: () => ({
isConnecting: false,
password: '',
show1: false,
}),
}
</script>

@ -12,71 +12,71 @@
</template>
<script>
const DEFAULT_TRANSITION = `fade`;
const DEFAULT_TRANSITION_MODE = `out-in`;
export default {
name: `TransitionPage`,
data() {
return {
prevHeight: 0,
transitionName: DEFAULT_TRANSITION,
transitionMode: DEFAULT_TRANSITION_MODE,
transitionEnterActiveClass: ``
};
},
created() {
this.$router.beforeEach((to, from, next) => {
let transitionName =
to.meta.transitionName ||
from.meta.transitionName ||
DEFAULT_TRANSITION;
if (transitionName === `slide`) {
const toDepth = to.path.split(`/`).length;
const fromDepth = from.path.split(`/`).length;
transitionName = toDepth < fromDepth ? `slide-right` : `slide-left`;
const DEFAULT_TRANSITION = 'fade'
const DEFAULT_TRANSITION_MODE = 'out-in'
export default {
name: 'TransitionPage',
data () {
return {
prevHeight: 0,
transitionName: DEFAULT_TRANSITION,
transitionMode: DEFAULT_TRANSITION_MODE,
transitionEnterActiveClass: '',
}
this.transitionMode = DEFAULT_TRANSITION_MODE;
this.transitionEnterActiveClass = `${transitionName}-enter-active`;
if (to.meta.transitionName === `zoom`) {
this.transitionMode = `in-out`;
this.transitionEnterActiveClass = `zoom-enter-active`;
document.body.style.overflow = `hidden`;
}
if (from.meta.transitionName === `zoom`) {
this.transitionMode = null;
this.transitionEnterActiveClass = null;
document.body.style.overflow = null;
}
this.transitionName = transitionName;
next();
});
},
methods: {
beforeLeave(element) {
this.prevHeight = getComputedStyle(element).height;
},
enter(element) {
const { height } = getComputedStyle(element);
// eslint-disable-next-line no-param-reassign
element.style.height = this.prevHeight;
created () {
this.$router.beforeEach((to, from, next) => {
let transitionName =
to.meta.transitionName ||
from.meta.transitionName ||
DEFAULT_TRANSITION
if (transitionName === 'slide') {
const toDepth = to.path.split('/').length
const fromDepth = from.path.split('/').length
transitionName = toDepth < fromDepth ? 'slide-right' : 'slide-left'
}
this.transitionMode = DEFAULT_TRANSITION_MODE
this.transitionEnterActiveClass = `${transitionName}-enter-active`
if (to.meta.transitionName === 'zoom') {
this.transitionMode = 'in-out'
this.transitionEnterActiveClass = 'zoom-enter-active'
document.body.style.overflow = 'hidden'
}
if (from.meta.transitionName === 'zoom') {
this.transitionMode = null
this.transitionEnterActiveClass = null
document.body.style.overflow = null
}
this.transitionName = transitionName
next()
})
},
methods: {
beforeLeave (element) {
this.prevHeight = getComputedStyle(element).height
},
enter (element) {
const { height } = getComputedStyle(element)
setTimeout(() => {
// eslint-disable-next-line no-param-reassign
element.style.height = height;
});
element.style.height = this.prevHeight
setTimeout(() => {
// eslint-disable-next-line no-param-reassign
element.style.height = height
})
},
afterEnter (element) {
// eslint-disable-next-line no-param-reassign
element.style.height = 'auto'
},
},
afterEnter(element) {
// eslint-disable-next-line no-param-reassign
element.style.height = `auto`;
}
}
};
</script>
<style lang="scss">
@ -136,4 +136,4 @@ export default {
opacity: 1;
}
}
</style>
</style>

@ -6,7 +6,9 @@
>
<v-list-item two-line>
<v-list-item-content v-if="weather">
<v-list-item-title class="headline">{{ weather.name }}</v-list-item-title>
<v-list-item-title class="headline">
{{ weather.name }}
</v-list-item-title>
<v-list-item-subtitle>{{ weather.dt | moment("ddd, h A") }}, {{ weather.weather[0].description }}</v-list-item-subtitle>
</v-list-item-content>
</v-list-item>
@ -14,9 +16,18 @@
<template v-if="weather">
<v-card-text>
<v-row align="center">
<v-col class="display-3" cols="6">{{ currentTemp }} &deg;C</v-col>
<v-col
class="display-3"
cols="6"
>
{{ currentTemp }} &deg;C
</v-col>
<v-col cols="6">
<v-img :src="currentConditionIcon" alt width="92"></v-img>
<v-img
:src="currentConditionIcon"
alt
width="92"
/>
</v-col>
</v-row>
</v-card-text>
@ -35,87 +46,98 @@
<v-list-item-subtitle>{{ weather.main.humidity }}%</v-list-item-subtitle>
</v-list-item>
<v-divider class="mx-4"></v-divider>
<v-divider class="mx-4" />
<template v-if="forecast">
<v-list class="transparent">
<v-list-item v-for="item in forecast.list" :key="item.dt">
<v-list-item
v-for="item in forecast.list"
:key="item.dt"
>
<v-list-item-title>{{ item.dt | moment("dddd") }}</v-list-item-title>
<v-list-item-icon class="ma-0">
<v-img :src="getConditionIcon(item.weather[0].icon)"></v-img>
<v-img :src="getConditionIcon(item.weather[0].icon)" />
</v-list-item-icon>
<v-list-item-subtitle
class="text-right"
>{{ item.temp.max | round }}&deg; / {{ item.temp.min | round }}&deg;</v-list-item-subtitle>
>
{{ item.temp.max | round }}&deg; / {{ item.temp.min | round }}&deg;
</v-list-item-subtitle>
</v-list-item>
</v-list>
</template>
</template>
<v-divider></v-divider>
<v-divider />
<v-card-actions>
<v-btn :loading="isUpdatingData" @click="updateData" text>i8n:update weather data</v-btn>
<v-btn
:loading="isUpdatingData"
text
@click="updateData"
>
i8n:update weather data
</v-btn>
</v-card-actions>
</v-skeleton-loader>
</v-card>
</template>
<script>
import weatherApi from "@/api/weather";
export default {
data: () => ({
isLoading: true,
isUpdatingData: false,
weather: null,
forecast: null
}),
created() {
this.loadData();
},
computed: {
currentTemp() {
return Math.round(this.weather.main.temp);
import weatherApi from '@/api/weather'
export default {
data: () => ({
isLoading: true,
isUpdatingData: false,
weather: null,
forecast: null,
}),
computed: {
currentTemp () {
return Math.round(this.weather.main.temp)
},
currentConditionIcon () {
return (
'http://openweathermap.org/img/wn/' +
this.weather.weather[0].icon +
'@2x.png'
)
},
},
currentConditionIcon() {
return (
"http://openweathermap.org/img/wn/" +
this.weather.weather[0].icon +
"@2x.png"
);
}
},
methods: {
getConditionIcon(code) {
return "http://openweathermap.org/img/wn/" + code + "@2x.png";
created () {
this.loadData()
},
loadData() {
this.isLoading = true;
weatherApi.getCurrent(weather => {
this.weather = weather;
weatherApi.getForecast(forecast => {
this.forecast = forecast;
this.isLoading = false;
});
});
methods: {
getConditionIcon (code) {
return 'http://openweathermap.org/img/wn/' + code + '@2x.png'
},
loadData () {
this.isLoading = true
weatherApi.getCurrent(weather => {
this.weather = weather
weatherApi.getForecast(forecast => {
this.forecast = forecast
this.isLoading = false
})
})
},
updateData () {
this.isUpdatingData = true
weatherApi.updateWeather(() => {
// TODO reload json
this.isUpdatingData = false
this.loadData()
})
},
},
updateData() {
this.isUpdatingData = true;
weatherApi.updateWeather(() => {
// TODO reload json
this.isUpdatingData = false;
this.loadData();
});
}
}
};
</script>

@ -1,7 +1,7 @@
<template>
<v-autocomplete
:disabled="!api"
v-model="model"
:disabled="!api"
:items="entries"
:loading="isLoading"
:search-input.sync="search"
@ -13,95 +13,106 @@
placeholder="i8n:Start typing to Search"
_return-object
>
<template v-slot:item="{ item }">
<v-list-item two-line class="pa-0">
<template #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)" />
<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)" />
<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-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>
<v-list-item />
</template>
</v-autocomplete>
</template>
<script>
export default {
props: {
location: {
type: Number,
required: false
},
api: {
type: String,
required: true
export default {
props: {
location: {
type: Number,
required: false,
},
api: {
type: String,
required: true,
},
lang: {
type: String,
required: true,
},
unit: {
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;
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;
// Items have already been requested
if (this.isLoading) return
this.isLoading = true;
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;
// 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"
);
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'
},
},
getConditionIcon(code) {
return "http://openweathermap.org/img/wn/" + code + "@2x.png";
}
}
};
</script>
</script>

@ -5,13 +5,13 @@ import vuetify from './plugins/vuetify'
Vue.config.productionTip = false
Vue.use(require('vue-moment'));
Vue.use(require('vue-moment'))
new Vue({
vuetify,
router,
data: {
stats: null
},
render: h => h(App)
vuetify,
router,
data: {
stats: null,
},
render: h => h(App),
}).$mount('#app')

@ -6,101 +6,100 @@ import Vuetify from 'vuetify/lib'
// @see https://github.com/vuetifyjs/vuetify/blob/master/packages/vuetify/src/services/icons/presets/mdi-svg.ts
const MY_ICONS = {
// system icons
//complete: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/check/baseline.svg')},
//cancel: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/cancel/baseline.svg')},
close: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/close/baseline.svg')},
//delete: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/delete/baseline.svg')},
//clear: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/clear/baseline.svg')},
//success: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/check_circle/baseline.svg')},
//info: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/info/baseline.svg')},
//warning: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/priority_high/baseline.svg')},
//error: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/warning/baseline.svg')},
prev: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/chevron_left/baseline.svg')},
next: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/chevron_right/baseline.svg')},
//checkboxOn: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/check_box/baseline.svg')},
//checkboxOff: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/check_box_outline_blank/baseline.svg')},
//checkboxIndeterminate: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/indeterminate_check_box/baseline.svg')},
//delimiter: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/fiber_manual_record/baseline.svg')}, // for carousel
//sort: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/arrow_upward/baseline.svg')},
//expand: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/keyboard_arrow_down/baseline.svg')},
//menu: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/menu/baseline.svg')},
//subgroup: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/arrow_drop_down/baseline.svg')},
dropdown: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/arrow_drop_down/baseline.svg')},
radioOn: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/radio_button_checked/baseline.svg')},
radioOff: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/radio_button_unchecked/baseline.svg')},
//edit: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/edit/baseline.svg')},
//ratingEmpty: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/star_border/baseline.svg')},
//ratingFull: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/star/baseline.svg')},
//ratingHalf: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/star_half/baseline.svg')},
//loading: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/cached/baseline.svg')},
//first: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/first_page/baseline.svg')},
//last: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/last_page/baseline.svg')},
//unfold: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/unfold_more/baseline.svg')},
//file: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/attach_file/baseline.svg')},
//plus: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/add/baseline.svg')},
//minus: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/remove/baseline.svg')},
// complete: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/check/baseline.svg')},
// cancel: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/cancel/baseline.svg')},
close: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/close/baseline.svg') },
// delete: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/delete/baseline.svg')},
// clear: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/clear/baseline.svg')},
// success: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/check_circle/baseline.svg')},
// info: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/info/baseline.svg')},
// warning: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/priority_high/baseline.svg')},
// error: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/warning/baseline.svg')},
prev: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/chevron_left/baseline.svg') },
next: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/chevron_right/baseline.svg') },
// checkboxOn: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/check_box/baseline.svg')},
// checkboxOff: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/check_box_outline_blank/baseline.svg')},
// checkboxIndeterminate: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/indeterminate_check_box/baseline.svg')},
// delimiter: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/fiber_manual_record/baseline.svg')}, // for carousel
// sort: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/arrow_upward/baseline.svg')},
// expand: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/keyboard_arrow_down/baseline.svg')},
// menu: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/menu/baseline.svg')},
// subgroup: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/arrow_drop_down/baseline.svg')},
dropdown: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/arrow_drop_down/baseline.svg') },
radioOn: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/radio_button_checked/baseline.svg') },
radioOff: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/radio_button_unchecked/baseline.svg') },
// edit: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/edit/baseline.svg')},
// ratingEmpty: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/star_border/baseline.svg')},
// ratingFull: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/star/baseline.svg')},
// ratingHalf: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/star_half/baseline.svg')},
// loading: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/cached/baseline.svg')},
// first: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/first_page/baseline.svg')},
// last: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/last_page/baseline.svg')},
// unfold: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/unfold_more/baseline.svg')},
// file: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/attach_file/baseline.svg')},
// plus: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/add/baseline.svg')},
// minus: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/remove/baseline.svg')},
// app icons
//save: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/save/baseline.svg')},
//more_vert: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/more_vert/baseline.svg')},
//reorder: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/reorder/baseline.svg')},
//preview: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/remove_red_eye/baseline.svg')},
//search: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/search/baseline.svg')},
memory: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/memory/baseline.svg')},
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')},
// wifi
signalWifiOff: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_off/baseline.svg')},
signalWifi0: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_0_bar/baseline.svg')},
signalWifi1: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_1_bar/baseline.svg')},
signalWifi1Lock: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_1_bar_lock/baseline.svg')},
signalWifi2: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_2_bar/baseline.svg')},
signalWifi2Lock: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_2_bar_lock/baseline.svg')},
signalWifi3: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_3_bar/baseline.svg')},
signalWifi3Lock: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_3_bar_lock/baseline.svg')},
signalWifi4: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_4_bar/baseline.svg')},
signalWifi4Lock: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_4_bar_lock/baseline.svg')},
// setup
wb_sunny: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/wb_sunny/baseline.svg')},
open_in_new: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/open_in_new/baseline.svg')},
face: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/face/baseline.svg')},
autorenew: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/autorenew/baseline.svg')},
check: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/check/baseline.svg')},
visibility: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/visibility/baseline.svg')},
visibility_off: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/visibility_off/baseline.svg')}
// save: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/save/baseline.svg')},
// more_vert: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/more_vert/baseline.svg')},
// reorder: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/reorder/baseline.svg')},
// preview: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/remove_red_eye/baseline.svg')},
// search: {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/search/baseline.svg')},
memory: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/memory/baseline.svg') },
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') },
// wifi
signalWifiOff: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_off/baseline.svg') },
signalWifi0: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_0_bar/baseline.svg') },
signalWifi1: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_1_bar/baseline.svg') },
signalWifi1Lock: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_1_bar_lock/baseline.svg') },
signalWifi2: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_2_bar/baseline.svg') },
signalWifi2Lock: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_2_bar_lock/baseline.svg') },
signalWifi3: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_3_bar/baseline.svg') },
signalWifi3Lock: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_3_bar_lock/baseline.svg') },
signalWifi4: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_4_bar/baseline.svg') },
signalWifi4Lock: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_4_bar_lock/baseline.svg') },
// setup
wb_sunny: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/wb_sunny/baseline.svg') },
open_in_new: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/open_in_new/baseline.svg') },
face: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/face/baseline.svg') },
autorenew: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/autorenew/baseline.svg') },
check: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/check/baseline.svg') },
visibility: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/visibility/baseline.svg') },
visibility_off: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/visibility_off/baseline.svg') },
}
Vue.use(Vuetify)
// usage: {{ file.size | prettyBytes }}
Vue.filter('prettyBytes', function (num) {
// jacked from: https://github.com/sindresorhus/pretty-bytes
if (typeof num !== 'number' || isNaN(num)) {
throw new TypeError('Expected a number');
}
// jacked from: https://github.com/sindresorhus/pretty-bytes
if (typeof num !== 'number' || isNaN(num)) {
throw new TypeError('Expected a number')
}
var exponent;
var unit;
var neg = num < 0;
var units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
var exponent
var unit
var neg = num < 0
var units = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
if (neg) {
num = -num;
}
if (neg) {
num = -num
}
if (num < 1) {
return (neg ? '-' : '') + num + ' B';
}
if (num < 1) {
return (neg ? '-' : '') + num + ' B'
}
exponent = Math.min(Math.floor(Math.log(num) / Math.log(1000)), units.length - 1);
num = (num / Math.pow(1000, exponent)).toFixed(2) * 1;
unit = units[exponent];
exponent = Math.min(Math.floor(Math.log(num) / Math.log(1000)), units.length - 1)
num = (num / Math.pow(1000, exponent)).toFixed(2) * 1
unit = units[exponent]
return (neg ? '-' : '') + num + ' ' + unit;
});
return (neg ? '-' : '') + num + ' ' + unit
})
/**
* Vue filter to round the decimal to the given place.
@ -110,18 +109,17 @@ Vue.filter('prettyBytes', function (num) {
* @param {Number} decimals The number of decimal places.
*/
Vue.filter('round', function (value, decimals) {
if (!value) {
value = 0;
}
if (!decimals) {
decimals = 0;
}
if (!value) {
value = 0
}
value = Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals);
return value;
});
if (!decimals) {
decimals = 0
}
value = Math.round(value * Math.pow(10, decimals)) / Math.pow(10, decimals)
return value
})
/**
* usage: {{ wifi.rssi | wifiIcon(wifi.secure) }}
@ -129,38 +127,34 @@ Vue.filter('round', function (value, decimals) {
* @param {Boolean} secure Is wifi protected
*/
Vue.filter('wifiIcon', function (rssi, secure) {
let icon = '$signalWifi'
// strength
if (rssi >= -67) {
icon += 4
}
else if (rssi >= -70) {
icon += 3
}
else if (rssi >= -80) {
icon += 2
}
else if (rssi >= -90) {
icon += 1
}
else {
icon += 0
}
// secure
if (secure !== 0 && rssi >= -90) {
icon += 'Lock'
}
return icon
});
let icon = '$signalWifi'
// strength
if (rssi >= -67) {
icon += 4
} else if (rssi >= -70) {
icon += 3
} else if (rssi >= -80) {
icon += 2
} else if (rssi >= -90) {
icon += 1
} else {
icon += 0
}
// secure
if (secure !== 0 && rssi >= -90) {
icon += 'Lock'
}
return icon
})
const opts = {
icons: {
iconfont: '',
values: MY_ICONS
}
values: MY_ICONS,
},
}
export default new Vuetify(opts)
export default new Vuetify(opts)

@ -12,22 +12,22 @@ const SetupName = () => import('../views/Setup/Name')
const SetupAppearance = () => import('../views/Setup/Appearance')
const SetupDone = () => import('../views/Setup/Done')
Vue.use(VueRouter);
Vue.use(VueRouter)
export default new VueRouter({
routes: [
{ path: '/', component: Dashboard },
{ path: '/settings', component: Settings, meta: { transitionName: 'slide' } },
{ path: '/', component: Dashboard },
{ path: '/settings', component: Settings, meta: { transitionName: 'slide' } },
// setup wizard
{ path: '/setup/start', component: SetupStart, meta: { transitionName: 'slide' } },
{ path: '/setup/country', component: SetupCountry, meta: { transitionName: 'slide' } },
{ path: '/setup/wifi', component: SetupWifi, meta: { transitionName: 'slide' } },
{ path: '/setup/weather', component: SetupWeather, meta: { transitionName: 'slide' } },
{ path: '/setup/name', component: SetupName, meta: { transitionName: 'slide' } },
{ path: '/setup/appearance', component: SetupAppearance, meta: { transitionName: 'slide' } },
{ path: '/setup/done', component: SetupDone, meta: { transitionName: 'slide' } },
// setup wizard
{ path: '/setup/start', component: SetupStart, meta: { transitionName: 'slide' } },
{ path: '/setup/country', component: SetupCountry, meta: { transitionName: 'slide' } },
{ path: '/setup/wifi', component: SetupWifi, meta: { transitionName: 'slide' } },
{ path: '/setup/weather', component: SetupWeather, meta: { transitionName: 'slide' } },
{ path: '/setup/name', component: SetupName, meta: { transitionName: 'slide' } },
{ path: '/setup/appearance', component: SetupAppearance, meta: { transitionName: 'slide' } },
{ path: '/setup/done', component: SetupDone, meta: { transitionName: 'slide' } },
{ path: '*', redirect: '/' }
{ path: '*', redirect: '/' },
],
});
})

@ -1,33 +1,43 @@
<template>
<v-container fluid _grid-list-md _pa-2>
<v-container
class="_grid-list-md _pa-2"
fluid
>
<v-row>
<v-col cols="12" md="6">
<screen-card></screen-card>
<v-col
cols="12"
md="6"
>
<screen-card />
</v-col>
<v-col cols="12" sm="6" md="4">
<weather-card></weather-card>
<device-card class="mt-5"></device-card>
<v-col
cols="12"
sm="6"
md="4"
>
<weather-card />
<device-card class="mt-5" />
</v-col>
</v-row>
</v-container>
</template>
<script>
import screenCard from "@/components/ScreenCard";
import weatherCard from "@/components/WeatherCard";
import deviceCard from "@/components/DeviceCard";
import screenCard from '@/components/ScreenCard'
import weatherCard from '@/components/WeatherCard'
import deviceCard from '@/components/DeviceCard'
export default {
components: {
screenCard,
weatherCard,
deviceCard
},
data: () => ({
isLoading: false
})
};
export default {
components: {
screenCard,
weatherCard,
deviceCard,
},
data: () => ({
isLoading: false,
}),
}
</script>
<style scoped>
</style>
</style>

@ -1,15 +1,31 @@
<template>
<v-layout fluid fill-height>
<v-row class="fluid fill-height">
<template v-if="isLoading">
<v-overlay :absolute="true" :value="true">
<v-progress-circular indeterminate size="64"></v-progress-circular>
<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-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>
@ -30,69 +46,88 @@
-->
</v-tabs>
<v-card v-if="settings" class="mx-auto" width="400">
<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"
:items="deviceOrientation"
label="i8n:Orientation"
placeholder
></v-select>
/>
<v-select
:items="deviceTheme"
v-model="settings.device.theme"
:items="deviceTheme"
label="i8n:Theme"
placeholder
></v-select>
<v-dialog v-model="dialogSystemUpdate" max-width="400">
<template v-slot:activator="{ on }">
<v-btn class="my-5" block small outlined color="warning" v-on="on">System update</v-btn>
/>
<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 v-slot:progress>
<template #progress>
<v-progress-linear
v-model="system.updateProgress"
:indeterminate="system.updateProgress === 100"
height="10"
></v-progress-linear>
/>
</template>
<v-card-title class="headline">System update</v-card-title>
<v-card-title class="headline">
System update
</v-card-title>
<v-card-text>
<!--
<v-alert border="left" type="warning" outlined>
Sed in libero ut nibh placerat accumsan. Phasellus leo dolor, tempus non, auctor et
</v-alert>
-->
<v-file-input
v-model="system.firmware"
show-size
accept="application/octet-stream"
label="Firmware"
></v-file-input>
/>
</v-card-text>
<v-card-actions>
<v-btn text href="https://github.com/paperdash" target="_blank">Get firmware</v-btn>
<v-spacer></v-spacer>
<v-btn
text
href="https://github.com/paperdash"
target="_blank"
>
Get firmware
</v-btn>
<v-spacer />
<v-btn
ref="firmware"
outlined
color="warning"
ref="firmware"
@click="onSystemUpdate()"
>Update system</v-btn>
<!--
<v-btn color="green darken-1" text @click="dialogSystemUpdate = false">Disagree</v-btn>
<v-btn color="green darken-1" text @click="dialogSystemUpdate = false">Agree</v-btn>
-->
>
Update system
</v-btn>
</v-card-actions>
</v-card>
<v-dialog :value="system.updateResult !== null" persistent max-width="400">
<v-dialog
:value="system.updateResult !== null"
persistent
max-width="400"
>
<v-card>
<v-card-title class="headline">
update result...
@ -100,8 +135,13 @@
</v-card-title>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text @click="onUpdateDone()">OK</v-btn>
<v-spacer />
<v-btn
text
@click="onUpdateDone()"
>
OK
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
@ -111,11 +151,17 @@
<v-tab-item>
<v-card-text class="pb-0">
<v-row>
<v-col cols="3" class="text-center mt-2 pb-0">
<v-col
cols="3"
class="text-center mt-2 pb-0"
>
<v-icon>$wb_sunny</v-icon>
<br />Forecast
<br>Forecast
</v-col>
<v-col cols="6" class="text-center pb-0">
<v-col
cols="6"
class="text-center pb-0"
>
<v-text-field
v-model="settings.playlist.timer"
label="Switch every"
@ -125,15 +171,21 @@
filled
suffix="seconds"
class="text-right"
></v-text-field>
/>
</v-col>
<v-col cols="3" class="text-center mt-2 pb-0">
<v-col
cols="3"
class="text-center mt-2 pb-0"
>
<v-icon>$calendar_today</v-icon>
<br />Calendar
<br>Calendar
</v-col>
</v-row>
<ul class="mt-5" v-if="0">
<ul
v-if="0"
class="mt-5"
>
<li>calendar</li>
<li>weather forecast</li>
<li>unsplash.com</li>
@ -143,30 +195,30 @@
<v-tab-item>
<v-card-text>
<v-text-field
label="i8n:OpenWeatherMap API key"
v-model="settings.weather.api"
label="i8n:OpenWeatherMap API key"
placeholder="###"
></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-select
:items="weatherLang"
v-model="settings.weather.lang"
:items="weatherLang"
label="i8n:Lang"
placeholder
></v-select>
/>
<v-select
:items="weatherUnit"
v-model="settings.weather.unit"
:items="weatherUnit"
label="i8n:Units"
placeholder
></v-select>
/>
</v-card-text>
</v-tab-item>
<!--
@ -196,192 +248,203 @@
</v-tabs-items>
<v-card-actions>
<v-btn text to="/">i8n:cancel</v-btn>
<v-spacer></v-spacer>
<v-btn text color="primary" @click="onSave()">i8n:Save</v-btn>
<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-layout>
</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("/");
});
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'
),
}
onSystemUpdate() {
let self = this;
self.system.updateProgress = 0;
apiDevice.getSettings(settings => {
this.settings = settings
const config = {
onUploadProgress: function(progressEvent) {
let percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total
);
this.isLoading = false
})
},
methods: {
onSave () {
this.isLoading = true
self.system.updateProgress = percentCompleted;
}
};
apiDevice.putSettings(this.settings, data => {
console.log(data)
this.isLoading = false
this.isSnackbar = true
let formData = new FormData();
formData.append("update", this.system.firmware);
this.$router.push('/')
})
},
axios
.post("/update", formData, config)
.then(response => {
console.log(response.data);
onSystemUpdate () {
const self = this
self.system.updateProgress = 0
self.system.updateProgress = null;
self.system.updateResult = response.data.success;
})
.catch(response => {
console.log(response);
const config = {
onUploadProgress: function (progressEvent) {
const percentCompleted = Math.round(
(progressEvent.loaded * 100) / progressEvent.total,
)
self.system.updateProgress = null;
self.system.updateResult = false;
});
},
self.system.updateProgress = percentCompleted
},
}
onUpdateDone() {
if (this.system.updateResult === true) {
window.location = "/";
} else {
this.system.firmware = null;
this.system.updateProgress = 0;
this.system.updateResult = null;
}
}
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>

@ -1,15 +1,30 @@
<template>
<v-container fluid _fill-height>
<v-btn v-if="currentStep > 0" text color="primary" class="pl-0" @click="currentStep--">
<v-container
class="_fill-height"
fluid
>
<v-btn
v-if="currentStep > 0"
text
color="primary"
class="pl-0"
@click="currentStep--"
>
<v-icon>$prev</v-icon>Back
</v-btn>
<template v-if="currentStep === 0">
<!-- 1. hello -->
<v-card flat class="mx-auto" width="520">
<v-card-title class="display-2 mt-12 justify-center text-center">Hello paperdash</v-card-title>
<v-card
flat
class="mx-auto"
width="520"
>
<v-card-title class="display-2 mt-12 justify-center text-center">
Hello paperdash
</v-card-title>
<Case
<case
v-if="0"
id="device_"
:class="[device.theme, device.case, device.front, 'case_orange', 'my-12']"
@ -37,12 +52,19 @@
</defs>
-->
<g id="border" fill="#262626" stroke="none">
<g
id="border"
fill="#262626"
stroke="none"
>
<path
d="M442 5110 c-227 -86 -417 -161 -422 -166 -4 -5 -12 -1063 -16 -2350 -7 -2292 -6 -2342 12 -2352 31 -16 817 -242 844 -242 14 0 1086 158 2383 352 l2358 353 6 25 c9 35 -66 3683 -76 3693 -4 4 -1049 194 -2322 422 -1273 228 -2323 416 -2334 419 -11 2 -206 -67 -433 -154z"
/>
</g>
<g fill="#f3f3f3" stroke="none">
<g
fill="#f3f3f3"
stroke="none"
>
<path
id="front"
d="M860 2630 l0 -2611 33 6 c17 3 1080 163 2360 355 1281 191 2330 350 2332 352 6 6 -70 3666 -76 3672 -4 4 -4627 836 -4645 836 -2 0 -4 -1175 -4 -2610z m2378 1721 c1217 -175 2214 -320 2216 -322 7 -6 69 -3179 63 -3185 -8 -9 -4489 -624 -4499 -618 -10 6 -11 4444 0 4444 4 0 1003 -144 2220 -319z m2249 2 c-4 -3 -7 0 -7 7 0 7 3 10 7 7 3 -4 3 -10 0 -14z m60 -2890 c-4 -3 -7 0 -7 7 0 7 3 10 7 7 3 -4 3 -10 0 -14z"
@ -59,24 +81,40 @@
</svg>
<v-card-actions>
<v-btn depressed block color="primary" @click="currentStep = 1">Continue</v-btn>
<v-btn
depressed
block
color="primary"
@click="currentStep = 1"
>
Continue
</v-btn>
</v-card-actions>
</v-card>
</template>
<template v-else-if="currentStep === 1">
<!-- country -->
<v-card flat class="mx-auto" width="520">
<v-card
flat
class="mx-auto"
width="520"
>
<v-card-title
class="display-2 mb-12 justify-center text-center"
>Select Your Country or Region</v-card-title>
>
Select Your Country or Region
</v-card-title>
<v-list class="ml-5 pa-0">
<template v-for="(country, code) in countries">
<div :key="code">
<v-divider></v-divider>
<v-divider />
<v-list-item class="pl-1" @click="commitCountry(code, country)">
<v-list-item
class="pl-1"
@click="commitCountry(code, country)"
>
<!--<v-list-item-icon>{{ country.emoji }}</v-list-item-icon>-->
<v-list-item-content>{{ country.native }}</v-list-item-content>
@ -92,15 +130,24 @@
<template v-else-if="currentStep === 2">
<!-- timezone if needed -->
<v-card flat class="mx-auto" width="520">
<v-card-title class="display-2 mb-12 justify-center text-center">Select Your Timezone</v-card-title>
<v-card
flat
class="mx-auto"
width="520"
>
<v-card-title class="display-2 mb-12 justify-center text-center">
Select Your Timezone
</v-card-title>
<v-list class="ml-5 pa-0">
<template v-for="(zone, i) in timeZones">
<div :key="i">
<v-divider></v-divider>
<v-divider />
<v-list-item class="pl-1" @click="commitTimezone(zone)">
<v-list-item
class="pl-1"
@click="commitTimezone(zone)"
>
<v-list-item-content>{{ zone }}</v-list-item-content>
<v-list-item-action>
@ -109,96 +156,177 @@
</v-list-item>
</div>
</template>
<v-divider></v-divider>
<v-divider />
</v-list>
</v-card>
</template>
<template v-else-if="currentStep === 3">
<!-- wifi select & reboot -->
<v-card flat class="mx-auto" width="520">
<v-card
flat
class="mx-auto"
width="520"
>
<v-card-title class="display-2 mb-12 justify-center text-center">
Choose a Wi-Fi
<br />Network
<br>Network
</v-card-title>
<v-list class="_ml-5 pa-0">
<v-list-item-group v-model="settings.wifi">
<template v-for="(wifi, i) in wifiAvailable">
<div :key="i">
<v-divider v-if="i > 0"></v-divider>
<v-divider v-if="i > 0" />
<v-list-item class="px-1" :value="wifi.ssid" @click.stop="wifiConnectModal = true">
<v-list-item
class="px-1"
:value="wifi.ssid"
@click.stop="wifiConnectModal = true"
>
<v-list-item-content>
<v-list-item-title v-text="wifi.ssid"></v-list-item-title>
<v-list-item-subtitle v-text="wifi.bssid"></v-list-item-subtitle>
<v-list-item-title v-text="wifi.ssid" />
<v-list-item-subtitle v-text="wifi.bssid" />
</v-list-item-content>
<v-list-item-icon>
<v-icon class="mx-2" v-if="wifi.secure">$lock</v-icon>
<v-icon class="mx-2">{{ wifi.rssi | wifiIcon(0) }}</v-icon>
<v-icon class="ml-3">$next</v-icon>
<v-icon
v-if="wifi.secure"
class="mx-2"
>
$lock
</v-icon>
<v-icon class="mx-2">
{{ wifi.rssi | wifiIcon(0) }}
</v-icon>
<v-icon class="ml-3">
$next
</v-icon>
</v-list-item-icon>
</v-list-item>
</div>
</template>
</v-list-item-group>
<v-divider></v-divider>
<v-divider />
<v-btn text color="primary" class="px-0 my-2">Choose Another Network</v-btn>
<v-btn
text
color="primary"
class="px-0 my-2"
>
Choose Another Network
</v-btn>
</v-list>
<v-dialog v-model="wifiConnectModal" max-width="400">
<v-dialog
v-model="wifiConnectModal"
max-width="400"
>
<setup-wifi-connect
:ssid="settings.wifi"
@connected="commitWifi()"
@cancel="wifiConnectModal = false"
></setup-wifi-connect>
/>
</v-dialog>
<v-divider></v-divider>
<v-divider />
</v-card>
</template>
<template v-else-if="currentStep === 4">
<!-- appearance -->
<v-card flat class="mx-auto" width="520">
<v-card-title class="display-2 mb-12 justify-center text-center">Appearance</v-card-title>
<v-card
flat
class="mx-auto"
width="520"
>
<v-card-title class="display-2 mb-12 justify-center text-center">
Appearance
</v-card-title>
<v-radio-group v-model="settings.theme" row>
<v-radio label="Light" value="white"></v-radio>
<v-radio label="Dark" value="black"></v-radio>
<v-radio-group
v-model="settings.theme"
row
>
<v-radio
label="Light"
value="white"
/>
<v-radio
label="Dark"
value="black"
/>
</v-radio-group>
<v-card-actions>
<v-btn depressed block color="primary" @click="currentStep++">Continue</v-btn>
<v-btn
depressed
block
color="primary"
@click="currentStep++"
>
Continue
</v-btn>
</v-card-actions>
</v-card>
</template>
<template v-else-if="currentStep === 5">
<!-- weather -->
<v-card flat class="mx-auto" width="520">
<v-card-title class="display-2 mb-12 justify-center text-center">Weather</v-card-title>
<v-card
flat
class="mx-auto"
width="520"
>
<v-card-title class="display-2 mb-12 justify-center text-center">
Weather
</v-card-title>
<setup-weather :settings="settings"></setup-weather>
<setup-weather :settings="settings" />
<v-card-actions class="flex-column">
<v-btn depressed block color="primary" @click="currentStep++">Continue</v-btn>
<v-btn class="ma-0 mt-3" text block color="primary">Set Up Later in Settings</v-btn>
<v-btn
depressed
block
color="primary"
@click="currentStep++"
>
Continue
</v-btn>
<v-btn
class="ma-0 mt-3"
text
block
color="primary"
>
Set Up Later in Settings
</v-btn>
</v-card-actions>
</v-card>
</template>
<template v-else-if="currentStep === 6">
<!-- completed -->
<v-card flat class="mx-auto mt-12" width="600">
<v-card
flat
class="mx-auto mt-12"
width="600"
>
<!--<v-card-title class="display-2 mb-12 justify-center text-center">This is Your <br/> paperdash</v-card-title>-->
<v-card-title class="display-2 mb-12 justify-center text-center">Welcome to paperdash</v-card-title>
<v-card-title class="display-2 mb-12 justify-center text-center">
Welcome to paperdash
</v-card-title>
<v-card-actions>
<v-btn depressed block color="primary" to="/">Get Started</v-btn>
<v-btn
depressed
block
color="primary"
to="/"
>
Get Started
</v-btn>
</v-card-actions>
</v-card>
</template>
@ -206,82 +334,82 @@
</template>
<script>
import apiDevice from "@/api/device";
import { countries } from "countries-list";
import timezones from "countries-and-timezones";
import setupWifiConnect from "@/components/SetupWifiConnect";
import setupWeather from "@/components/SetupWeather";
import Case from "!vue-svg-loader!@/assets/case.svg";
export default {
components: {
Case,
setupWifiConnect,
setupWeather
},
data: () => ({
// weather + ggf. image pool
currentStep: 5,
settings: {
country: "DE",
language: "en", // (alpha-2 codes)
timezone: "Europe/Berlin",
wifi: null,
theme: null,
weather: {
api: '883b3c87223430d6f3a399645f8ba12b',
location: null,
lang: null,
unit: null
}
import apiDevice from '@/api/device'
import { countries } from 'countries-list'
import timezones from 'countries-and-timezones'
import setupWifiConnect from '@/components/SetupWifiConnect'
import setupWeather from '@/components/SetupWeather'
import Case from '!vue-svg-loader!@/assets/case.svg'
export default {
components: {
Case,
setupWifiConnect,
setupWeather,
},
device: {
theme: "theme_w",
case: "case_whitey",
front: "front_whitey"
data: () => ({
// weather + ggf. image pool
currentStep: 5,
settings: {
country: 'DE',
language: 'en', // (alpha-2 codes)
timezone: 'Europe/Berlin',
wifi: null,
theme: null,
weather: {
api: '883b3c87223430d6f3a399645f8ba12b',
location: null,
lang: null,
unit: null,
},
},
device: {
theme: 'theme_w',
case: 'case_whitey',
front: 'front_whitey',
},
countries: countries,
timeZones: [],
wifi: {
available: [],
connectSSID: null,
},
wifiAvailable: [],
wifiConnectModal: false,
}),
created () {
apiDevice.wifiScan(list => {
this.wifiAvailable = list
this.isLoading = false
})
},
countries: countries,
timeZones: [],
wifi: {
available: [],
connectSSID: null
},
wifiAvailable: [],
wifiConnectModal: false
}),
created() {
apiDevice.wifiScan(list => {
this.wifiAvailable = list;
this.isLoading = false;
});
},
methods: {
commitCountry(code, country) {
this.settings.country = code;
this.settings.language = country.languages[0];
// get also timezone
let zone = timezones.getCountry(code);
if (zone.timezones.length > 1) {
this.timeZones = zone.timezones;
this.currentStep++;
} else {
this.settings.timezone = zone.timezones[0];
this.currentStep += 2;
}
},
commitTimezone(zone) {
this.settings.timezone = zone;
this.currentStep++;
methods: {
commitCountry (code, country) {
this.settings.country = code
this.settings.language = country.languages[0]
// get also timezone
const zone = timezones.getCountry(code)
if (zone.timezones.length > 1) {
this.timeZones = zone.timezones
this.currentStep++
} else {
this.settings.timezone = zone.timezones[0]
this.currentStep += 2
}
},
commitTimezone (zone) {
this.settings.timezone = zone
this.currentStep++
},
commitWifi () {},
},
commitWifi() {}
}
};
</script>
<style scoped>

@ -1,17 +1,45 @@
<template>
<v-container fluid _fill-height>
<v-row no-gutters justify="center">
<v-col lg="5" md="6" sm="8">
<v-container
class="_fill-height"
fluid
>
<v-row
no-gutters
justify="center"
>
<v-col
lg="5"
md="6"
sm="8"
>
<v-card flat>
<v-card-title class="display-2 mb-12 justify-center text-center">Appearance</v-card-title>
<v-card-title class="display-2 mb-12 justify-center text-center">
Appearance
</v-card-title>
<v-radio-group v-model="settings.device.theme" row>
<v-radio label="Light" value="white"></v-radio>
<v-radio label="Dark" value="black"></v-radio>
<v-radio-group
v-model="settings.device.theme"
row
>
<v-radio
label="Light"
value="white"
/>
<v-radio
label="Dark"
value="black"
/>
</v-radio-group>
<v-card-actions>
<v-btn depressed block color="primary" @click="commitStep()">Continue</v-btn>
<v-btn
depressed
block
color="primary"
@click="commitStep()"
>
Continue
</v-btn>
</v-card-actions>
</v-card>
</v-col>
@ -20,34 +48,34 @@
</template>
<script>
import apiDevice from "@/api/device";
import apiDevice from '@/api/device'
export default {
data: () => ({
isLoading: true,
isSaving: false,
settings: null
}),
created() {
apiDevice.getSettings(settings => {
this.settings = settings;
export default {
data: () => ({
isLoading: true,
isSaving: false,
settings: null,
}),
created () {
apiDevice.getSettings(settings => {
this.settings = settings
this.isLoading = false;
});
},
methods: {
commitStep() {
this.isSaving = true;
this.isLoading = false
})
},
methods: {
commitStep () {
this.isSaving = true
apiDevice.putSettings({ device: this.settings.device }, () => {
this.isSaving = false;
apiDevice.putSettings({ device: this.settings.device }, () => {
this.isSaving = false
this.nextStep();
});
this.nextStep()
})
},
nextStep () {
this.$router.push('/setup/done')
},
},
nextStep() {
this.$router.push("/setup/done");
}
}
};
</script>
</script>

@ -1,20 +1,35 @@
<template>
<v-container fluid _fill-height>
<v-row no-gutters justify="center">
<v-col lg="5" md="6" sm="8">
<v-container
class="_fill-height"
fluid
>
<v-row
no-gutters
justify="center"
>
<v-col
lg="5"
md="6"
sm="8"
>
<template v-if="currentStep === 0">
<!-- country -->
<v-card flat>
<v-card-title
class="display-2 mb-12 justify-center text-center"
>Select Your Country or Region</v-card-title>
>
Select Your Country or Region
</v-card-title>
<v-list class="ml-5 pa-0">
<template v-for="(country, code) in availableCountries">
<div :key="code">
<v-divider></v-divider>
<v-divider />
<v-list-item class="pl-1" @click="commitCountry(code, country)">
<v-list-item
class="pl-1"
@click="commitCountry(code, country)"
>
<!--<v-list-item-icon>{{ country.emoji }}</v-list-item-icon>-->
<v-list-item-content>{{ country.native }}</v-list-item-content>
@ -31,14 +46,19 @@
<template v-else-if="currentStep === 1">
<!-- timezone if needed -->
<v-card flat>
<v-card-title class="display-2 mb-12 justify-center text-center">Select Your Timezone</v-card-title>
<v-card-title class="display-2 mb-12 justify-center text-center">
Select Your Timezone
</v-card-title>
<v-list class="ml-5 pa-0">
<template v-for="(zone, i) in availableTimeZones">
<div :key="i">
<v-divider></v-divider>
<v-divider />
<v-list-item class="pl-1" @click="commitTimezone(zone)">
<v-list-item
class="pl-1"
@click="commitTimezone(zone)"
>
<v-list-item-content>{{ zone }}</v-list-item-content>
<v-list-item-action>
@ -47,7 +67,7 @@
</v-list-item>
</div>
</template>
<v-divider></v-divider>
<v-divider />
</v-list>
</v-card>
</template>
@ -57,64 +77,64 @@
</template>
<script>
import apiDevice from "@/api/device";
import { countries } from "countries-list";
import timezones from "countries-and-timezones";
export default {
data: () => ({
currentStep: 0,
isLoading: true,
isSaving: true,
settings: null,
availableCountries: countries,
availableTimeZones: []
}),
created() {
apiDevice.getSettings(settings => {
this.settings = settings;
this.isLoading = false;
});
},
methods: {
commitCountry(code, country) {
this.settings.system.country = code;
this.settings.system.language = country.languages[0];
// get also timezone
const zone = timezones.getCountry(code);
if (zone.timezones.length > 1) {
this.availableTimeZones = zone.timezones;
this.currentStep = 1;
} else {
this.commitTimezone(zone.timezones[0]);
}
import apiDevice from '@/api/device'
import { countries } from 'countries-list'
import timezones from 'countries-and-timezones'
export default {
data: () => ({
currentStep: 0,
isLoading: true,
isSaving: true,
settings: null,
availableCountries: countries,
availableTimeZones: [],
}),
created () {
apiDevice.getSettings(settings => {
this.settings = settings
this.isLoading = false
})
},
commitTimezone(zone) {
this.settings.system.timezone = zone;
const timezone = timezones.getTimezone(zone);
this.settings.system.utc = timezone.utcOffset * 60;
this.settings.system.dst = timezone.dstOffset * 60;
this.commitStep();
methods: {
commitCountry (code, country) {
this.settings.system.country = code
this.settings.system.language = country.languages[0]
// get also timezone
const zone = timezones.getCountry(code)
if (zone.timezones.length > 1) {
this.availableTimeZones = zone.timezones
this.currentStep = 1
} else {
this.commitTimezone(zone.timezones[0])
}
},
commitTimezone (zone) {
this.settings.system.timezone = zone
const timezone = timezones.getTimezone(zone)
this.settings.system.utc = timezone.utcOffset * 60
this.settings.system.dst = timezone.dstOffset * 60
this.commitStep()
},
commitStep () {
this.isSaving = true
apiDevice.putSettings({ system: this.settings.system }, () => {
this.isSaving = false
this.$router.push('/setup/wifi')
})
},
},
commitStep() {
this.isSaving = true;
apiDevice.putSettings({ system: this.settings.system }, () => {
this.isSaving = false;
this.$router.push("/setup/wifi");
});
}
}
};
</script>
<style scoped>
@ -123,4 +143,4 @@ export default {
.v-card__title {
word-break: normal;
}
</style>
</style>

@ -1,36 +1,52 @@
<template>
<v-container fluid _fill-height>
<v-card flat class="mx-auto" width="540">
<v-container
class="_fill-height"
fluid
>
<v-card
flat
class="mx-auto"
width="540"
>
<!--<v-card-title class="display-2 mb-12 justify-center text-center">Welcome to paperdash</v-card-title>-->
<v-card-title class="display-2 mb-12 justify-center text-center">Hello {{ settings.device.name }}</v-card-title>
<v-card-title class="display-2 mb-12 justify-center text-center">
Hello {{ settings.device.name }}
</v-card-title>
<v-card-actions>
<v-btn outlined block color="primary" @click="onStart">Let's start</v-btn>
<v-btn
outlined
block
color="primary"
@click="onStart"
>
Let's start
</v-btn>
</v-card-actions>
</v-card>
</v-container>
</template>
<script>
import apiDevice from "@/api/device";
import apiDevice from '@/api/device'
export default {
data: () => ({
isLoading: true,
isSaving: false,
settings: null
}),
created() {
apiDevice.getSettings(settings => {
this.settings = settings;
export default {
data: () => ({
isLoading: true,
isSaving: false,
settings: null,
}),
created () {
apiDevice.getSettings(settings => {
this.settings = settings
this.isLoading = false;
});
},
methods: {
onStart() {
this.$router.push("/");
}
this.isLoading = false
})
},
methods: {
onStart () {
this.$router.push('/')
},
},
}
};
</script>
</script>

@ -1,28 +1,56 @@
<template>
<v-container fluid _fill-height>
<v-row no-gutters justify="center">
<v-col lg="5" md="6" sm="8">
<v-container
class="_fill-height"
fluid
>
<v-row
no-gutters
justify="center"
>
<v-col
lg="5"
md="6"
sm="8"
>
<v-card flat>
<div class="justify-center text-center">
<v-icon viewBox="0 0 24 24" style="width: 64px; height: 64px; fill: #FF9800">$face</v-icon>
<v-icon
view-box="0 0 24 24"
style="width: 64px; height: 64px; fill: #FF9800"
>
$face
</v-icon>
</div>
<v-card-title class="display-2 mb-12 justify-center text-center">Give it a name</v-card-title>
<v-card-title class="display-2 mb-12 justify-center text-center">
Give it a name
</v-card-title>
<p
class="text-center"
>TODO:Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam</p>
>
TODO:Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam
</p>
<v-skeleton-loader v-if="isLoading" type="list-item-two-line" class="mx-auto"></v-skeleton-loader>
<v-skeleton-loader
v-if="isLoading"
type="list-item-two-line"
class="mx-auto"
/>
<template v-else>
<v-card-text>
<v-text-field label="i8n:My paperdash name" v-model="settings.device.name">
<template v-slot:append-outer>
<v-text-field
v-model="settings.device.name"
label="i8n:My paperdash name"
>
<template #append-outer>
<v-icon
viewBox="0 0 24 24"
view-box="0 0 24 24"
style="width: 48px; height: 48px;"
@click="setRandomeName()"
>$autorenew</v-icon>
>
$autorenew
</v-icon>
</template>
</v-text-field>
</v-card-text>
@ -35,7 +63,9 @@
block
color="primary"
@click="commitStep()"
>Continue</v-btn>
>
Continue
</v-btn>
</v-card-actions>
</template>
</v-card>
@ -45,53 +75,53 @@
</template>
<script>
import apiDevice from "@/api/device";
import randomNames from "@/assets/fantasyNames.json";
import apiDevice from '@/api/device'
import randomNames from '@/assets/fantasyNames.json'
export default {
data: () => ({
isLoading: true,
isSaving: false,
settings: null
}),
created() {
apiDevice.getSettings(settings => {
this.settings = settings;
export default {
data: () => ({
isLoading: true,
isSaving: false,
settings: null,
}),
computed: {
isStepValid () {
return (
this.settings.device.name !== undefined &&
this.settings.device.name !== ''
)
},
},
created () {
apiDevice.getSettings(settings => {
this.settings = settings
if (!this.isStepValid) {
this.setRandomeName();
}
if (!this.isStepValid) {
this.setRandomeName()
}
this.isLoading = false;
});
},
computed: {
isStepValid() {
return (
this.settings.device.name != undefined &&
this.settings.device.name !== ""
);
}
},
methods: {
commitStep() {
this.isSaving = true;
this.isLoading = false
})
},
methods: {
commitStep () {
this.isSaving = true
apiDevice.putSettings({ device: this.settings.device }, () => {
this.isSaving = false;
apiDevice.putSettings({ device: this.settings.device }, () => {
this.isSaving = false
this.nextStep();
});
},
nextStep() {
this.$router.push("/setup/appearance");
this.nextStep()
})
},
nextStep () {
this.$router.push('/setup/appearance')
},
setRandomeName () {
this.settings.device.name =
randomNames[Math.floor(Math.random() * randomNames.length)]
},
},
setRandomeName() {
this.settings.device.name =
randomNames[Math.floor(Math.random() * randomNames.length)];
}
}
};
</script>
<style scoped>
@ -99,4 +129,4 @@ export default {
font-size: 2.2em;
max-height: inherit;
}
</style>
</style>

@ -1,87 +1,102 @@
<template>
<v-container fluid _fill-height>
<v-row no-gutters justify="center">
<v-col lg="5" md="6" sm="8">
<v-card flat>
<v-card-title class="display-2 mt-12 justify-center text-center">Hello paperdash</v-card-title>
<v-container
class="_fill-height"
fluid
>
<v-row
no-gutters
justify="center"
>
<v-col
lg="5"
md="6"
sm="8"
>
<v-card flat>
<v-card-title class="display-2 mt-12 justify-center text-center">
Hello paperdash
</v-card-title>
<Case
v-if="0"
id="device_"
:class="[device.theme, device.case, device.front, 'case_orange', 'my-12']"
/>
<Case
v-if="0"
id="device_"
:class="[device.theme, device.case, device.front, 'case_orange', 'my-12']"
/>
<svg
id="device"
:class="[device.theme, device.case, device.front, 'case_orange front_orange', 'my-12 mx-auto']"
version="1.0"
xmlns="http://www.w3.org/2000/svg"
_width="561px"
_height="527px"
viewBox="0 0 5610 5270"
preserveAspectRatio="xMidYMid meet"
width="400"
>
<!--
<defs>
<pattern id="pattern_b" width="100%" height="100%">
<image x="0" y="0" height="84%" href="/face-weather-b.png"/>
</pattern>
<pattern id="pattern_w" width="100%" height="100%">
<image x="0" y="0" height="84%" href="/face-weather-w.png"/>
</pattern>
</defs>
-->
<svg
id="device"
:class="[device.theme, device.case, device.front, 'case_orange front_orange', 'my-12 mx-auto']"
version="1.0"
xmlns="http://www.w3.org/2000/svg"
_width="561px"
_height="527px"
viewBox="0 0 5610 5270"
preserveAspectRatio="xMidYMid meet"
width="400"
>
<g id="border" fill="#262626" stroke="none">
<path
d="M442 5110 c-227 -86 -417 -161 -422 -166 -4 -5 -12 -1063 -16 -2350 -7 -2292 -6 -2342 12 -2352 31 -16 817 -242 844 -242 14 0 1086 158 2383 352 l2358 353 6 25 c9 35 -66 3683 -76 3693 -4 4 -1049 194 -2322 422 -1273 228 -2323 416 -2334 419 -11 2 -206 -67 -433 -154z"
/>
</g>
<g fill="#f3f3f3" stroke="none">
<path
id="front"
d="M860 2630 l0 -2611 33 6 c17 3 1080 163 2360 355 1281 191 2330 350 2332 352 6 6 -70 3666 -76 3672 -4 4 -4627 836 -4645 836 -2 0 -4 -1175 -4 -2610z m2378 1721 c1217 -175 2214 -320 2216 -322 7 -6 69 -3179 63 -3185 -8 -9 -4489 -624 -4499 -618 -10 6 -11 4444 0 4444 4 0 1003 -144 2220 -319z m2249 2 c-4 -3 -7 0 -7 7 0 7 3 10 7 7 3 -4 3 -10 0 -14z m60 -2890 c-4 -3 -7 0 -7 7 0 7 3 10 7 7 3 -4 3 -10 0 -14z"
/>
<path
id="image"
d="M1022 4642 c-7 -19 5 -4393 13 -4400 5 -5 4465 605 4472 611 4 4 -59 3161 -63 3166 -3 3 -3200 465 -4387 634 -19 2 -31 -1 -35 -11z"
/>
<path
id="case"
d="M438 5081 c-214 -81 -390 -150 -393 -153 -7 -6 -28 -4658 -22 -4664 2 -2 182 -56 400 -119 218 -64 403 -118 412 -121 13 -6 15 259 15 2600 0 2078 -3 2606 -12 2605 -7 0 -187 -67 -400 -148z"
/>
</g>
</svg>
<g
id="border"
fill="#262626"
stroke="none"
>
<path
d="M442 5110 c-227 -86 -417 -161 -422 -166 -4 -5 -12 -1063 -16 -2350 -7 -2292 -6 -2342 12 -2352 31 -16 817 -242 844 -242 14 0 1086 158 2383 352 l2358 353 6 25 c9 35 -66 3683 -76 3693 -4 4 -1049 194 -2322 422 -1273 228 -2323 416 -2334 419 -11 2 -206 -67 -433 -154z"
/>
</g>
<g
fill="#f3f3f3"
stroke="none"
>
<path
id="front"
d="M860 2630 l0 -2611 33 6 c17 3 1080 163 2360 355 1281 191 2330 350 2332 352 6 6 -70 3666 -76 3672 -4 4 -4627 836 -4645 836 -2 0 -4 -1175 -4 -2610z m2378 1721 c1217 -175 2214 -320 2216 -322 7 -6 69 -3179 63 -3185 -8 -9 -4489 -624 -4499 -618 -10 6 -11 4444 0 4444 4 0 1003 -144 2220 -319z m2249 2 c-4 -3 -7 0 -7 7 0 7 3 10 7 7 3 -4 3 -10 0 -14z m60 -2890 c-4 -3 -7 0 -7 7 0 7 3 10 7 7 3 -4 3 -10 0 -14z"
/>
<path
id="image"
d="M1022 4642 c-7 -19 5 -4393 13 -4400 5 -5 4465 605 4472 611 4 4 -59 3161 -63 3166 -3 3 -3200 465 -4387 634 -19 2 -31 -1 -35 -11z"
/>
<path
id="case"
d="M438 5081 c-214 -81 -390 -150 -393 -153 -7 -6 -28 -4658 -22 -4664 2 -2 182 -56 400 -119 218 -64 403 -118 412 -121 13 -6 15 259 15 2600 0 2078 -3 2606 -12 2605 -7 0 -187 -67 -400 -148z"
/>
</g>
</svg>
<v-card-actions>
<v-btn depressed block color="primary" @click="commitStep()">Continue</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
<v-card-actions>
<v-btn
depressed
block
color="primary"
@click="commitStep()"
>
Continue
</v-btn>
</v-card-actions>
</v-card>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
data: () => ({
device: {
theme: "theme_w",
case: "case_whitey",
front: "front_whitey"
}
}),
methods: {
commitStep() {
// TODO sav
this.$router.push("/setup/country");
}
export default {
data: () => ({
device: {
theme: 'theme_w',
case: 'case_whitey',
front: 'front_whitey',
},
}),
methods: {
commitStep () {
// TODO sav
this.$router.push('/setup/country')
},
},
}
};
</script>
<style scoped>
#device #border,
#device > path {

@ -1,24 +1,46 @@
<template>
<v-container fluid _fill-height>
<v-row no-gutters justify="center">
<v-col lg="5" md="6" sm="8">
<v-container
class="_fill-height"
fluid
>
<v-row
no-gutters
justify="center"
>
<v-col
lg="5"
md="6"
sm="8"
>
<v-card flat>
<div class="justify-center text-center">
<v-icon viewBox="0 0 24 24" style="width: 64px; height: 64px; fill: #FF9800">$wb_sunny</v-icon>
<v-icon
view-box="0 0 24 24"
style="width: 64px; height: 64px; fill: #FF9800"
>
$wb_sunny
</v-icon>
</div>
<v-card-title class="display-2 mb-12 justify-center text-center">Weather</v-card-title>
<v-card-title class="display-2 mb-12 justify-center text-center">
Weather
</v-card-title>
<v-skeleton-loader
v-if="isLoading"
type="list-item-two-line,list-item-two-line"
class="mx-auto"
></v-skeleton-loader>
/>
<template v-else>
<v-card-text>
<v-text-field label="i8n:OpenWeatherMap API key" v-model="settings.weather.api">
<template v-slot:append-outer>
<v-icon @click="registerApiKey()">$open_in_new</v-icon>
<v-text-field
v-model="settings.weather.api"
label="i8n:OpenWeatherMap API key"
>
<template #append-outer>
<v-icon @click="registerApiKey()">
$open_in_new
</v-icon>
</template>
</v-text-field>
@ -27,7 +49,7 @@
:location.sync="settings.weather.location"
:lang="lang"
:unit="unit"
></weather-find-location>
/>
</v-card-text>
<v-card-actions class="flex-column">
@ -37,14 +59,18 @@
block
color="primary"
@click="commitStep()"
>Continue</v-btn>
>
Continue
</v-btn>
<v-btn
class="ma-0 mt-3"
text
block
color="primary"
@click="nextStep()"
>Set Up Later in Settings</v-btn>
>
Set Up Later in Settings
</v-btn>
</v-card-actions>
</template>
</v-card>
@ -54,48 +80,48 @@
</template>
<script>
import apiDevice from "@/api/device";
import weatherFindLocation from "@/components/WeatherFindLocation";
import apiDevice from '@/api/device'
import weatherFindLocation from '@/components/WeatherFindLocation'
export default {
components: {
weatherFindLocation
},
data: () => ({
isLoading: true,
settings: null
}),
created() {
apiDevice.getSettings(settings => {
this.settings = settings;
this.isLoading = false;
});
},
computed: {
lang() {
return this.settings.language || "EN";
export default {
components: {
weatherFindLocation,
},
unit() {
return this.settings.language === "EN" ? "" : "metric";
data: () => ({
isLoading: true,
settings: null,
}),
computed: {
lang () {
return this.settings.language || 'EN'
},
unit () {
return this.settings.language === 'EN' ? '' : 'metric'
},
isLocationValid () {
return this.settings.weather.location > 0
},
},
isLocationValid() {
return this.settings.weather.location > 0;
}
},
methods: {
commitStep() {
// TODO sav
created () {
apiDevice.getSettings(settings => {
this.settings = settings
this.nextStep();
this.isLoading = false
})
},
nextStep() {
this.$router.push("/setup/name");
methods: {
commitStep () {
// TODO sav
this.nextStep()
},
nextStep () {
this.$router.push('/setup/name')
},
registerApiKey () {
window.open('http://openweathermap.org/')
},
},
registerApiKey() {
window.open("http://openweathermap.org/");
}
}
};
</script>
</script>

@ -1,27 +1,42 @@
<template>
<v-container fluid _fill-height>
<v-row no-gutters justify="center">
<v-col lg="5" md="6" sm="8">
<v-container
class="_fill-height"
fluid
>
<v-row
no-gutters
justify="center"
>
<v-col
lg="5"
md="6"
sm="8"
>
<v-card flat>
<v-card-title class="display-2 mb-12 justify-center text-center">
Choose a
<br />Wi-Fi Network
<br>Wi-Fi Network
</v-card-title>
<v-skeleton-loader
v-if="isLoading"
type="list-item-two-line,list-item-two-line,list-item-two-line"
class="mx-auto"
></v-skeleton-loader>
/>
<v-list v-else>
<template v-for="(wifi, i) in wifiAvailable">
<div :key="i">
<v-divider v-if="i > 0"></v-divider>
<v-divider v-if="i > 0" />
<v-list-item class="px-1" @click="onWifiSelect(wifi)">
<v-list-item
class="px-1"
@click="onWifiSelect(wifi)"
>
<v-list-item-icon class="mr-2 ml-2">
<v-icon v-if="wifi.ssid === settings.system.wifi">$check</v-icon>
<v-icon v-if="wifi.ssid === settings.system.wifi">
$check
</v-icon>
<v-progress-circular
v-if="wifi.ssid === connectingSSID"
@ -29,34 +44,52 @@
:width="2"
color="grey "
indeterminate
></v-progress-circular>
/>
</v-list-item-icon>
<v-list-item-content dark>
<v-list-item-title v-text="wifi.ssid"></v-list-item-title>
<v-list-item-subtitle v-text="wifi.bssid"></v-list-item-subtitle>
<v-list-item-title v-text="wifi.ssid" />
<v-list-item-subtitle v-text="wifi.bssid" />
</v-list-item-content>
<v-list-item-icon>
<v-icon class="mx-2" v-if="wifi.secure">$lock</v-icon>
<v-icon class="mx-2">{{ wifi.rssi | wifiIcon(0) }}</v-icon>
<v-icon class="ml-3">$next</v-icon>
<v-icon
v-if="wifi.secure"
class="mx-2"
>
$lock
</v-icon>
<v-icon class="mx-2">
{{ wifi.rssi | wifiIcon(0) }}
</v-icon>
<v-icon class="ml-3">
$next
</v-icon>
</v-list-item-icon>
</v-list-item>
</div>
</template>
<v-divider></v-divider>
<v-divider />
<v-btn text color="primary" class="_px-0 my-2">Choose Another Network</v-btn>
<v-btn
text
color="primary"
class="_px-0 my-2"
>
Choose Another Network
</v-btn>
</v-list>
<v-dialog v-model="wifiPasswordModal" max-width="450">
<v-dialog
v-model="wifiPasswordModal"
max-width="450"
>
<setup-wifi-connect
:ssid="connectSSID"
:onConnect="onWifiConnect"
:on-connect="onWifiConnect"
@cancel="wifiPasswordModal = false"
></setup-wifi-connect>
/>
</v-dialog>
</v-card>
</v-col>
@ -65,49 +98,49 @@
</template>
<script>
import apiDevice from "@/api/device";
import setupWifiConnect from "@/components/SetupWifiConnect";
export default {
components: {
setupWifiConnect
},
data: () => ({
isLoading: true,
settings: null,
connectSSID: null,
connectingSSID: "",
wifiAvailable: [],
wifiPasswordModal: false
}),
created() {
apiDevice.getSettings(settings => {
this.settings = settings;
apiDevice.wifiScan(list => {
this.wifiAvailable = list;
this.isLoading = false;
});
});
},
methods: {
onWifiSelect(wifi) {
if (wifi.secure) {
this.connectSSID = wifi.ssid;
this.wifiPasswordModal = true;
} else {
this.onWifiConnect(wifi.ssid, "");
}
},
onWifiConnect(ssid, password) {
this.connectingSSID = ssid;
this.wifiPasswordModal = false;
import apiDevice from '@/api/device'
import setupWifiConnect from '@/components/SetupWifiConnect'
apiDevice.wifiConnect(ssid, password, () => {});
}
export default {
components: {
setupWifiConnect,
},
data: () => ({
isLoading: true,
settings: null,
connectSSID: null,
connectingSSID: '',
wifiAvailable: [],
wifiPasswordModal: false,
}),
created () {
apiDevice.getSettings(settings => {
this.settings = settings
apiDevice.wifiScan(list => {
this.wifiAvailable = list
this.isLoading = false
})
})
},
methods: {
onWifiSelect (wifi) {
if (wifi.secure) {
this.connectSSID = wifi.ssid
this.wifiPasswordModal = true
} else {
this.onWifiConnect(wifi.ssid, '')
}
},
onWifiConnect (ssid, password) {
this.connectingSSID = ssid
this.wifiPasswordModal = false
apiDevice.wifiConnect(ssid, password, () => {})
},
},
}
};
</script>
</script>

@ -1,235 +1,258 @@
<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>
<template v-if="true">
<v-container>
<v-snackbar
v-model="isSnackbar"
:timeout="3000"
color="success"
>
i8n:saved
</v-snackbar>
<!-- status current wifi -->
<v-card
max-width="344"
class="mx-auto"
>
<v-template v-if="!wifiStats.connected">
<v-card-text>
<v-icon>$signalWifi0</v-icon>
not connected
<v-btn color="primary" depressed small>
i8n:scan
</v-btn>
</v-card-text>
</v-template>
<v-template v-else>
<v-toolbar flat>
<v-toolbar-title class="title font-weight-light">
<v-icon left>$signalWifi3Lock</v-icon>
xd-design.info
</v-toolbar-title>
<v-spacer></v-spacer>
<v-menu offset-y>
<template v-slot:activator="{ on }">
<v-btn icon small v-on="on">
<v-icon>mdi-dots-vertical</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item @click="scan()">
<v-list-item-title>i8n:scan</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-toolbar>
<v-divider class="mx-4"></v-divider>
<v-list dense>
<v-list-item
v-for="(value, key) in wifiStats"
:key="key"
>
<v-list-item-title>{{ key }}</v-list-item-title>
<v-list-item-subtitle class="text-right">
{{ value }}
</v-list-item-subtitle>
</v-list-item>
</v-list>
</v-template>
</v-card>
<br/><br/>
<!-- connect to wifi -->
<v-dialog v-model="wifiConnectModal" max-width="400">
<v-card>
<v-card-title class="headline">
{{ wifiConnectSSID }}
</v-card-title>
<v-card-text>
<v-text-field
v-model="wifiConnectPassword"
:append-icon="show1 ? 'mdi-eye' : 'mdi-eye-off'"
:type="show1 ? 'text' : 'password'"
label="i8n:Password"
@click:append="show1 = !show1"
></v-text-field>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn text @click="wifiConnectModal = false">i8n:Cancel</v-btn>
<v-btn
depressed
:loading="isConnecting"
color="primary darken-1"
@click="onWifiConnect()"
>
i8n:Connect
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-card
class="mx-auto"
max-width="344"
tile
>
<v-list >
<v-subheader>Wifi found</v-subheader>
<v-list-item-group v-model="wifiConnectSSID" color="primary">
<v-list-item
v-for="(wifi, i) in wifiAvailable"
:key="i"
:value="wifi.ssid"
@click.stop="wifiConnectModal = true"
>
<v-list-item-icon>
<v-icon v-text="getWifiIcon(wifi)"></v-icon>
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title v-text="wifi.ssid"></v-list-item-title>
<v-list-item-subtitle v-text="wifi.bssid"></v-list-item-subtitle>
</v-list-item-content>
<v-list-item-avatar>
<v-avatar color="teal" size="24">
<span class="white--text headline caption">{{ wifi.channel }}</span>
</v-avatar>
</v-list-item-avatar>
</v-list-item>
</v-list-item-group>
</v-list>
</v-card>
</v-container>
</template>
</v-layout>
<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>
<template v-if="true">
<v-container>
<v-snackbar
v-model="isSnackbar"
:timeout="3000"
color="success"
>
i8n:saved
</v-snackbar>
<!-- status current wifi -->
<v-card
max-width="344"
class="mx-auto"
>
<v-template v-if="!wifiStats.connected">
<v-card-text>
<v-icon>$signalWifi0</v-icon>
not connected
<v-btn
color="primary"
depressed
small
>
i8n:scan
</v-btn>
</v-card-text>
</v-template>
<v-template v-else>
<v-toolbar flat>
<v-toolbar-title class="title font-weight-light">
<v-icon left>
$signalWifi3Lock
</v-icon>
xd-design.info
</v-toolbar-title>
<v-spacer />
<v-menu offset-y>
<template #activator="{ on }">
<v-btn
icon
small
v-on="on"
>
<v-icon>mdi-dots-vertical</v-icon>
</v-btn>
</template>
<v-list>
<v-list-item @click="scan()">
<v-list-item-title>i8n:scan</v-list-item-title>
</v-list-item>
</v-list>
</v-menu>
</v-toolbar>
<v-divider class="mx-4" />
<v-list dense>
<v-list-item
v-for="(value, key) in wifiStats"
:key="key"
>
<v-list-item-title>{{ key }}</v-list-item-title>
<v-list-item-subtitle class="text-right">
{{ value }}
</v-list-item-subtitle>
</v-list-item>
</v-list>
</v-template>
</v-card>
<br><br>
<!-- connect to wifi -->
<v-dialog
v-model="wifiConnectModal"
max-width="400"
>
<v-card>
<v-card-title class="headline">
{{ wifiConnectSSID }}
</v-card-title>
<v-card-text>
<v-text-field
v-model="wifiConnectPassword"
:append-icon="show1 ? 'mdi-eye' : 'mdi-eye-off'"
:type="show1 ? 'text' : 'password'"
label="i8n:Password"
@click:append="show1 = !show1"
/>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
text
@click="wifiConnectModal = false"
>
i8n:Cancel
</v-btn>
<v-btn
depressed
:loading="isConnecting"
color="primary darken-1"
@click="onWifiConnect()"
>
i8n:Connect
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
<v-card
class="mx-auto"
max-width="344"
tile
>
<v-list>
<v-subheader>Wifi found</v-subheader>
<v-list-item-group
v-model="wifiConnectSSID"
color="primary"
>
<v-list-item
v-for="(wifi, i) in wifiAvailable"
:key="i"
:value="wifi.ssid"
@click.stop="wifiConnectModal = true"
>
<v-list-item-icon>
<v-icon v-text="getWifiIcon(wifi)" />
</v-list-item-icon>
<v-list-item-content>
<v-list-item-title v-text="wifi.ssid" />
<v-list-item-subtitle v-text="wifi.bssid" />
</v-list-item-content>
<v-list-item-avatar>
<v-avatar
color="teal"
size="24"
>
<span class="white--text headline caption">{{ wifi.channel }}</span>
</v-avatar>
</v-list-item-avatar>
</v-list-item>
</v-list-item-group>
</v-list>
</v-card>
</v-container>
</template>
</v-row>
</template>
<script>
import apiDevice from '../api/device'
export default {
name: "Wifi",
data: () => ({
isLoading: true,
isSnackbar: false,
isConnecting: false,
mode: 'AP_initial', // AP_initial, AP_lost, Default
// todo load
wifiStats: {
connected: true,
ip: 'xxx.xxx.xxx.xxx',
mac: 'xxxx-xxxx-xxxx-xxxx',
channel: 11,
dns: 'xxx.xxx.xxx.xxx',
gateway: 'xxx.xxx.xxx.xxx',
},
wifiAvailable: [],
wifiConnectModal: false,
wifiConnectSSID: null,
wifiConnectPassword: null,
show1: false,
}),
created () {
//this.$vuetify.icons.values.signalWifi0 = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_0_bar/baseline.svg')}
//this.$vuetify.icons.values.signalWifi1 = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_1_bar/baseline.svg')}
//this.$vuetify.icons.values.signalWifi1Lock = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_1_bar_lock/baseline.svg')}
//this.$vuetify.icons.values.signalWifi2 = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_2_bar/baseline.svg')}
//this.$vuetify.icons.values.signalWifi2Lock = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_2_bar_lock/baseline.svg')}
//this.$vuetify.icons.values.signalWifi3 = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_3_bar/baseline.svg')}
//this.$vuetify.icons.values.signalWifi3Lock = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_3_bar_lock/baseline.svg')}
//this.$vuetify.icons.values.signalWifi4 = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_4_bar/baseline.svg')}
//this.$vuetify.icons.values.signalWifi4Lock = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_4_bar_lock/baseline.svg')}
apiDevice.wifiScan(list => {
this.wifiAvailable = list
this.isLoading = false
})
},
computed: {
},
methods: {
getWifiIcon(wifi) {
let icon = '$signalWifi'
// strength
if (wifi.rssi >= -67) {
icon += 4
}
else if (wifi.rssi >= -70) {
icon += 3
}
else if (wifi.rssi >= -80) {
icon += 2
}
else if (wifi.rssi >= -90) {
icon += 1
}
else {
icon += 0
}
// secure
if (wifi.secure !== 0 && wifi.rssi >= -90) {
icon += 'Lock'
}
return icon
},
onWifiConnect() {
this.isConnecting = true
apiDevice.wifiConnect(this.wifiConnectSSID, this.wifiConnectPassword)
}
}
}
import apiDevice from '../api/device'
export default {
name: 'Wifi',
data: () => ({
isLoading: true,
isSnackbar: false,
isConnecting: false,
mode: 'AP_initial', // AP_initial, AP_lost, Default
// todo load
wifiStats: {
connected: true,
ip: 'xxx.xxx.xxx.xxx',
mac: 'xxxx-xxxx-xxxx-xxxx',
channel: 11,
dns: 'xxx.xxx.xxx.xxx',
gateway: 'xxx.xxx.xxx.xxx',
},
wifiAvailable: [],
wifiConnectModal: false,
wifiConnectSSID: null,
wifiConnectPassword: null,
show1: false,
}),
computed: {
},
created () {
// this.$vuetify.icons.values.signalWifi0 = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_0_bar/baseline.svg')}
// this.$vuetify.icons.values.signalWifi1 = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_1_bar/baseline.svg')}
// this.$vuetify.icons.values.signalWifi1Lock = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_1_bar_lock/baseline.svg')}
// this.$vuetify.icons.values.signalWifi2 = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_2_bar/baseline.svg')}
// this.$vuetify.icons.values.signalWifi2Lock = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_2_bar_lock/baseline.svg')}
// this.$vuetify.icons.values.signalWifi3 = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_3_bar/baseline.svg')}
// this.$vuetify.icons.values.signalWifi3Lock = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_3_bar_lock/baseline.svg')}
// this.$vuetify.icons.values.signalWifi4 = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_4_bar/baseline.svg')}
// this.$vuetify.icons.values.signalWifi4Lock = {component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_4_bar_lock/baseline.svg')}
apiDevice.wifiScan(list => {
this.wifiAvailable = list
this.isLoading = false
})
},
methods: {
getWifiIcon (wifi) {
let icon = '$signalWifi'
// strength
if (wifi.rssi >= -67) {
icon += 4
} else if (wifi.rssi >= -70) {
icon += 3
} else if (wifi.rssi >= -80) {
icon += 2
} else if (wifi.rssi >= -90) {
icon += 1
} else {
icon += 0
}
// secure
if (wifi.secure !== 0 && wifi.rssi >= -90) {
icon += 'Lock'
}
return icon
},
onWifiConnect () {
this.isConnecting = true
apiDevice.wifiConnect(this.wifiConnectSSID, this.wifiConnectPassword)
},
},
}
</script>
<style scoped>
</style>
</style>

@ -1,39 +1,39 @@
const webpack = require('webpack');
const CompressionPlugin = require('compression-webpack-plugin');
const webpack = require('webpack')
const CompressionPlugin = require('compression-webpack-plugin')
module.exports = {
"outputDir": "../data/dist",
"filenameHashing": false,
"productionSourceMap": false,
"transpileDependencies": [
"vuetify"
],
devServer: {
proxy: {
'^/': {
target: 'http://192.168.178.62:80',
ws: true,
changeOrigin: true
},
}
},
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
// optimize build for esp32
return {
plugins: [
// reduce total size of the app
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1
}),
// use only pre compressed files
new CompressionPlugin({
deleteOriginalAssets: true
})
]
}
} else {
// mutate for development...
}
}
}
outputDir: '../data/dist',
filenameHashing: false,
productionSourceMap: false,
transpileDependencies: [
'vuetify',
],
devServer: {
proxy: {
'^/': {
target: 'http://paperdash-display-2:80',
ws: true,
changeOrigin: true,
},
},
},
configureWebpack: config => {
if (process.env.NODE_ENV === 'production') {
// optimize build for esp32
return {
plugins: [
// reduce total size of the app
new webpack.optimize.LimitChunkCountPlugin({
maxChunks: 1,
}),
// use only pre compressed files
new CompressionPlugin({
deleteOriginalAssets: true,
}),
],
}
} else {
// mutate for development...
}
},
}

Loading…
Cancel
Save