#42 first prototype
parent
fa6dda4985
commit
c1ded8cb7a
@ -0,0 +1,191 @@
|
||||
<template>
|
||||
<div class="d-flex flex-grow-1">
|
||||
<v-navigation-drawer
|
||||
v-model="drawer"
|
||||
class="grey darken-3"
|
||||
dark
|
||||
app
|
||||
_mini-variant-width="150"
|
||||
_mini-variant
|
||||
:clipped="clipped"
|
||||
>
|
||||
<v-sheet rounded="lg">
|
||||
<v-img
|
||||
:aspect-ratio="16/9"
|
||||
src="/api/device/screen"
|
||||
>
|
||||
<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-sheet>
|
||||
|
||||
<v-list nav>
|
||||
<v-list-item
|
||||
v-for="page in pages"
|
||||
:key="page.label"
|
||||
:to="page.to"
|
||||
link
|
||||
>
|
||||
<v-list-item-content class="text-center">
|
||||
<v-icon>{{ page.icon }}</v-icon>
|
||||
<v-list-item-title>{{ page.label }}</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<v-divider />
|
||||
<v-list-item
|
||||
link
|
||||
to="/setup"
|
||||
>
|
||||
<v-list-item-content class="text-center">
|
||||
<v-icon>$support</v-icon>
|
||||
<v-list-item-title>Assistant</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-navigation-drawer>
|
||||
|
||||
<v-app-bar
|
||||
app
|
||||
color="orange darken-2"
|
||||
dark
|
||||
flat_
|
||||
:clipped-left="clipped"
|
||||
>
|
||||
<v-btn
|
||||
_class="hidden-xs-and-down"
|
||||
to="/"
|
||||
icon
|
||||
color="transparent"
|
||||
>
|
||||
<img
|
||||
width="48"
|
||||
height="48"
|
||||
src="@/assets/logo.png"
|
||||
alt="logo"
|
||||
>
|
||||
</v-btn>
|
||||
|
||||
<v-toolbar-title>paperdash</v-toolbar-title>
|
||||
<v-app-bar-nav-icon
|
||||
@click.stop="drawer = !drawer"
|
||||
/>
|
||||
<v-spacer />
|
||||
<div>box name</div>
|
||||
<v-spacer />
|
||||
|
||||
<v-progress-circular
|
||||
:rotate="-90"
|
||||
:value="40"
|
||||
class="mx-3"
|
||||
size="40"
|
||||
>
|
||||
<v-icon>$playlist</v-icon>
|
||||
</v-progress-circular>
|
||||
|
||||
<v-progress-circular
|
||||
:rotate="-90"
|
||||
:value="40"
|
||||
class="mx-3"
|
||||
size="40"
|
||||
>
|
||||
<v-icon>$storage</v-icon>
|
||||
</v-progress-circular>
|
||||
|
||||
<template v-if="stats.wifi.connected">
|
||||
<v-btn icon>
|
||||
<v-icon>{{ stats.wifi.rssi | wifiIcon(0) }}</v-icon>
|
||||
</v-btn>
|
||||
<span>{{ new Date(stats.device.time * 1000).toLocaleString() }}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<v-btn
|
||||
to="/setup/wifi"
|
||||
icon
|
||||
>
|
||||
<v-icon color="red">
|
||||
$signalWifiOff
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
|
||||
<!--
|
||||
<v-responsive max-width="260">
|
||||
<v-text-field
|
||||
dense
|
||||
flat
|
||||
hide-details
|
||||
rounded
|
||||
solo-inverted
|
||||
/>
|
||||
</v-responsive>
|
||||
-->
|
||||
</v-app-bar>
|
||||
|
||||
<v-main class="grey lighten-3">
|
||||
<v-container>
|
||||
<v-sheet
|
||||
min-height="70vh"
|
||||
rounded="lg"
|
||||
>
|
||||
<router-view />
|
||||
</v-sheet>
|
||||
</v-container>
|
||||
</v-main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
drawer: true,
|
||||
clipped: true,
|
||||
pages: [
|
||||
{
|
||||
label: 'Dashboard',
|
||||
icon: '$lock',
|
||||
to: '/',
|
||||
},
|
||||
{
|
||||
label: 'Device',
|
||||
icon: '$device',
|
||||
to: '/device',
|
||||
},
|
||||
{
|
||||
label: 'Playlist',
|
||||
icon: '$playlist',
|
||||
to: '/playlist',
|
||||
},
|
||||
{
|
||||
label: 'Weather',
|
||||
icon: '$wb_sunny',
|
||||
to: '/weather',
|
||||
},
|
||||
{
|
||||
label: 'System',
|
||||
icon: '$settings',
|
||||
to: '/system',
|
||||
},
|
||||
],
|
||||
}),
|
||||
computed: {
|
||||
...mapState(['stats']),
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<v-main>
|
||||
<router-view />
|
||||
</v-main>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Setup',
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
@ -1,17 +1,14 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import vuetify from './plugins/vuetify'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
|
||||
Vue.use(require('vue-moment'))
|
||||
|
||||
new Vue({
|
||||
vuetify,
|
||||
router,
|
||||
data: {
|
||||
stats: null,
|
||||
},
|
||||
store,
|
||||
render: h => h(App),
|
||||
}).$mount('#app')
|
||||
|
@ -0,0 +1,142 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import axios from 'axios'
|
||||
// import device from '@/api/device'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const store = new Vuex.Store({
|
||||
state: {
|
||||
stats: {},
|
||||
settings: {},
|
||||
notifications: {},
|
||||
},
|
||||
mutations: {
|
||||
setStats (state, payload) {
|
||||
state.stats = payload
|
||||
},
|
||||
setSettings (state, payload) {
|
||||
state.settings = payload
|
||||
},
|
||||
|
||||
/*
|
||||
setSensors (state, payload) {
|
||||
state.sensors = payload
|
||||
},
|
||||
updateSensor (state, payload) {
|
||||
// update sensor
|
||||
const i = state.sensors.findIndex(item => item.id === payload.id)
|
||||
if (i >= 0) {
|
||||
state.sensors[i].temperature = payload.temperature
|
||||
state.sensors[i].humidity = payload.humidity
|
||||
state.sensors[i].last_update = payload.last_update
|
||||
|
||||
if (payload.label) {
|
||||
state.sensors[i].label = payload.label
|
||||
}
|
||||
|
||||
// update state
|
||||
state.sensors = [
|
||||
...state.sensors,
|
||||
]
|
||||
}
|
||||
},
|
||||
deleteSensor (state, id) {
|
||||
// const i = state.sensors.findIndex(item => item.id === id)
|
||||
state.sensors = state.sensors.filter(item => item.id !== id)
|
||||
},
|
||||
setPushUpdate (state, enable) {
|
||||
state.pushUpdate = enable
|
||||
},
|
||||
addSensorHistory (state, payload) {
|
||||
state.sensorHistory.push(payload)
|
||||
if (state.sensorHistory.length > 20) {
|
||||
state.sensorHistory = state.sensorHistory.slice(1)
|
||||
}
|
||||
},
|
||||
notification (state, payload) {
|
||||
state.notifications = payload
|
||||
},
|
||||
*/
|
||||
},
|
||||
actions: {
|
||||
async loadStats ({ commit }) {
|
||||
try {
|
||||
const response = await axios.get('/stats')
|
||||
commit('setStats', response.data)
|
||||
} catch (error) {
|
||||
commit('setStats', {})
|
||||
}
|
||||
},
|
||||
async loadSettings ({ commit }) {
|
||||
try {
|
||||
const response = await axios.get('/api/settings')
|
||||
commit('setSettings', response.data)
|
||||
} catch (error) {
|
||||
commit('setSettings', {})
|
||||
}
|
||||
},
|
||||
/*
|
||||
async getSensors ({ commit }) {
|
||||
try {
|
||||
const response = await axios.get('/api/sensors')
|
||||
commit('setSensors', response.data)
|
||||
} catch (error) {
|
||||
commit('setSensors', [])
|
||||
}
|
||||
},
|
||||
async putSensor ({ commit }, [id, sensor]) {
|
||||
try {
|
||||
await axios.put('/api/sensor/' + id, {
|
||||
label: sensor.label,
|
||||
})
|
||||
commit('updateSensor', sensor)
|
||||
} catch (error) {
|
||||
console.warn(error)
|
||||
}
|
||||
},
|
||||
async deleteSensor ({ commit }, id) {
|
||||
try {
|
||||
await axios.delete('/api/sensor/' + id)
|
||||
commit('deleteSensor', id)
|
||||
commit('notification', 'sensor #' + id + ' deleted')
|
||||
} catch (error) {
|
||||
console.warn(error)
|
||||
}
|
||||
},
|
||||
|
||||
*/
|
||||
},
|
||||
getters: {
|
||||
/*
|
||||
isAuthenticated(state) {
|
||||
return state.user !== null && state.user !== undefined;
|
||||
}
|
||||
*/
|
||||
},
|
||||
})
|
||||
|
||||
// sensor push data
|
||||
/*
|
||||
const connection = new WebSocket('ws://' + window.location.host + '/ws')
|
||||
connection.onmessage = (message) => {
|
||||
const log = JSON.parse(message.data)
|
||||
log.last_update = new Date()
|
||||
|
||||
store.commit('updateSensor', log)
|
||||
store.commit('addSensorHistory', log)
|
||||
store.commit('notification', log)
|
||||
}
|
||||
|
||||
store.watch(
|
||||
state => state.pushUpdate,
|
||||
(value) => {
|
||||
if (value) {
|
||||
console.info('TODO:: enable websocket')
|
||||
} else {
|
||||
console.info('TODO:: disable websocket')
|
||||
}
|
||||
},
|
||||
)
|
||||
*/
|
||||
export default store
|
@ -0,0 +1,25 @@
|
||||
<template>
|
||||
<div class="pa-5">
|
||||
device settings<br>
|
||||
- orientation<br>
|
||||
- theme<br>
|
||||
- auflösung<br>
|
||||
- system time<br>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
data: () => ({
|
||||
isLoading: false,
|
||||
}),
|
||||
computed: {
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div class="pa-5">
|
||||
playlist settings<br>
|
||||
- switch every x seconds<br>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
data: () => ({
|
||||
isLoading: false,
|
||||
}),
|
||||
computed: {
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
@ -1,450 +0,0 @@
|
||||
<template>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
-->
|
||||
|
||||
<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="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-title
|
||||
class="display-2 mb-12 justify-center text-center"
|
||||
>
|
||||
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-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>
|
||||
|
||||
<v-list-item-action>
|
||||
<v-icon>$next</v-icon>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
</div>
|
||||
</template>
|
||||
</v-list>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<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-list class="ml-5 pa-0">
|
||||
<template v-for="(zone, i) in timeZones">
|
||||
<div :key="i">
|
||||
<v-divider />
|
||||
|
||||
<v-list-item
|
||||
class="pl-1"
|
||||
@click="commitTimezone(zone)"
|
||||
>
|
||||
<v-list-item-content>{{ zone }}</v-list-item-content>
|
||||
|
||||
<v-list-item-action>
|
||||
<v-icon>$next</v-icon>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
</div>
|
||||
</template>
|
||||
<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-title class="display-2 mb-12 justify-center text-center">
|
||||
Choose a Wi-Fi
|
||||
<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-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-subtitle v-text="wifi.bssid" />
|
||||
</v-list-item-content>
|
||||
|
||||
<v-list-item-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-btn
|
||||
text
|
||||
color="primary"
|
||||
class="px-0 my-2"
|
||||
>
|
||||
Choose Another Network
|
||||
</v-btn>
|
||||
</v-list>
|
||||
|
||||
<v-dialog
|
||||
v-model="wifiConnectModal"
|
||||
max-width="400"
|
||||
>
|
||||
<setup-wifi-connect
|
||||
:ssid="settings.wifi"
|
||||
@connected="commitWifi()"
|
||||
@cancel="wifiConnectModal = false"
|
||||
/>
|
||||
</v-dialog>
|
||||
|
||||
<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-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-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>
|
||||
|
||||
<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-card-actions>
|
||||
</v-card>
|
||||
</template>
|
||||
|
||||
<template v-else-if="currentStep === 6">
|
||||
<!-- completed -->
|
||||
<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-actions>
|
||||
<v-btn
|
||||
depressed
|
||||
block
|
||||
color="primary"
|
||||
to="/"
|
||||
>
|
||||
Get Started
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</template>
|
||||
</v-container>
|
||||
</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,
|
||||
},
|
||||
},
|
||||
|
||||
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
|
||||
})
|
||||
},
|
||||
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 () {},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#device #border,
|
||||
#device > path {
|
||||
fill: #343434;
|
||||
}
|
||||
|
||||
/* TODO device theme */
|
||||
#device.theme_w #image {
|
||||
fill: url(#pattern_w);
|
||||
}
|
||||
#device.theme_b #image {
|
||||
fill: url(#pattern_b);
|
||||
}
|
||||
|
||||
/* front color */
|
||||
#device.front_blacky #front {
|
||||
fill: #000;
|
||||
}
|
||||
#device.front_whitey #front {
|
||||
fill: #f3f3f3;
|
||||
}
|
||||
#device.front_orange #front {
|
||||
fill: #ee8816;
|
||||
}
|
||||
|
||||
/* case color */
|
||||
#device.case_blacky #case {
|
||||
fill: #000;
|
||||
}
|
||||
#device.case_whitey #case {
|
||||
fill: #f3f3f3;
|
||||
}
|
||||
#device.case_orange #case {
|
||||
fill: #ee8816;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,147 @@
|
||||
<template>
|
||||
<div class="pa-5">
|
||||
<v-card
|
||||
flat
|
||||
width="400"
|
||||
class="mx-auto"
|
||||
>
|
||||
<v-list-item>
|
||||
<v-list-item-icon class="mr-3">
|
||||
<v-icon>$info</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>Software</v-list-item-title>
|
||||
</v-list-item-content>
|
||||
<v-list-item-action>
|
||||
<v-btn
|
||||
outlined
|
||||
color="primary"
|
||||
>
|
||||
Update
|
||||
</v-btn>
|
||||
</v-list-item-action>
|
||||
</v-list-item>
|
||||
<v-divider class="mx-4" />
|
||||
<v-list
|
||||
class="pb-0"
|
||||
>
|
||||
<v-list-item three-line>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>Firmware</v-list-item-title>
|
||||
<v-list-item-subtitle class="text--disabled">
|
||||
Rev: {{ stats.firmware.rev }}
|
||||
</v-list-item-subtitle>
|
||||
<v-list-item-subtitle class="text--disabled">
|
||||
Build: {{ new Date(stats.firmware.created * 1000).toLocaleString() }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item three-line>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>App</v-list-item-title>
|
||||
<v-list-item-subtitle class="text--disabled">
|
||||
Rev: {{ stats.app.rev }}
|
||||
</v-list-item-subtitle>
|
||||
<v-list-item-subtitle class="text--disabled">
|
||||
Build: {{ new Date(stats.app.created * 1000).toLocaleString() }}
|
||||
</v-list-item-subtitle>
|
||||
</v-list-item-content>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
<v-list-item class="mt-10">
|
||||
<v-list-item-icon class="mr-3">
|
||||
<v-icon>$storage</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>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-list-item-avatar>
|
||||
</v-list-item>
|
||||
<v-divider class="mx-4" />
|
||||
<v-list
|
||||
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>
|
||||
|
||||
<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>
|
||||
</v-list>
|
||||
<v-progress-linear
|
||||
height="25"
|
||||
:value="fsUsage"
|
||||
dark
|
||||
rounded
|
||||
>
|
||||
<template #default="{ value }">
|
||||
<strong>{{ Math.ceil(value) }}%</strong>
|
||||
</template>
|
||||
</v-progress-linear>
|
||||
|
||||
<v-list-item class="mt-10">
|
||||
<v-list-item-icon class="mr-3">
|
||||
<v-icon>$memory</v-icon>
|
||||
</v-list-item-icon>
|
||||
<v-list-item-content>
|
||||
<v-list-item-title>Memory</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-list-item-avatar>
|
||||
</v-list-item>
|
||||
|
||||
<v-divider class="mx-4" />
|
||||
</v-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
data: () => ({
|
||||
isLoading: false,
|
||||
}),
|
||||
computed: {
|
||||
...mapState(['stats']),
|
||||
fsUsage () {
|
||||
return Math.round(
|
||||
(100 / this.stats.device.fs.total) * this.stats.device.fs.used,
|
||||
)
|
||||
},
|
||||
fs () {
|
||||
return this.stats.device.fs
|
||||
},
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div class="pa-5">
|
||||
weather settings<br>
|
||||
- input fields<br>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
components: {
|
||||
},
|
||||
data: () => ({
|
||||
isLoading: false,
|
||||
}),
|
||||
computed: {
|
||||
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
@ -1,258 +0,0 @@
|
||||
<template>
|
||||
<v-row
|
||||
class="fluid fill-height"
|
||||
>
|
||||
<template v-if="isLoading">
|
||||
<v-overlay
|
||||
:absolute="true"
|
||||
:value="true"
|
||||
>
|
||||
<v-progress-circular
|
||||
indeterminate
|
||||
size="64"
|
||||
/>
|
||||
</v-overlay>
|
||||
</template>
|
||||
|
||||
<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,
|
||||
}),
|
||||
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>
|
Loading…
Reference in New Issue