From c1ded8cb7aade1b614c30e7dab0612a7792a9b58 Mon Sep 17 00:00:00 2001 From: Thomas Ballmann Date: Tue, 17 Nov 2020 22:45:40 +0100 Subject: [PATCH] #42 first prototype --- app/.eslintrc.js | 4 + app/package.json | 2 +- app/src/App.vue | 214 +++++++++++--- app/src/components/DeviceCard.vue | 2 +- app/src/layouts/default.vue | 191 +++++++++++++ app/src/layouts/setup.vue | 15 + app/src/main.js | 7 +- app/src/plugins/vuetify.js | 9 +- app/src/router/index.js | 23 +- app/src/store/index.js | 142 ++++++++++ app/src/views/Dashboard.vue | 22 ++ app/src/views/Device.vue | 25 ++ app/src/views/Playlist.vue | 22 ++ app/src/views/Setup.vue | 450 ------------------------------ app/src/views/Setup/Wifi.vue | 1 + app/src/views/System.vue | 147 ++++++++++ app/src/views/Weather.vue | 22 ++ app/src/views/Wifi.vue | 258 ----------------- app/yarn.lock | 17 +- 19 files changed, 805 insertions(+), 768 deletions(-) create mode 100644 app/src/layouts/default.vue create mode 100644 app/src/layouts/setup.vue create mode 100644 app/src/store/index.js create mode 100644 app/src/views/Device.vue create mode 100644 app/src/views/Playlist.vue delete mode 100644 app/src/views/Setup.vue create mode 100644 app/src/views/System.vue create mode 100644 app/src/views/Weather.vue delete mode 100644 app/src/views/Wifi.vue diff --git a/app/.eslintrc.js b/app/.eslintrc.js index 937983d..3868f69 100644 --- a/app/.eslintrc.js +++ b/app/.eslintrc.js @@ -11,4 +11,8 @@ module.exports = { // add your custom rules here rules: { }, + globals: { + __BUILD_TIME__: 'readonly', + __COMMIT_HASH__: 'readonly', + } } diff --git a/app/package.json b/app/package.json index 95c7c3e..9aef27e 100644 --- a/app/package.json +++ b/app/package.json @@ -28,11 +28,11 @@ "sass": "^1.19.0", "sass-loader": "^10.0.2", "vue-cli-plugin-vuetify": "~2.0.4", - "vue-moment": "^4.1.0", "vue-router": "^3.1.5", "vue-svg-loader": "^0.16.0", "vue-template-compiler": "^2.6.11", "vuetify-loader": "^1.3.0", + "vuex": "^3.5.1", "webpack-version-file": "^0.1.6" }, "eslintConfig": { diff --git a/app/src/App.vue b/app/src/App.vue index bcb8c8e..c51a744 100644 --- a/app/src/App.vue +++ b/app/src/App.vue @@ -1,5 +1,166 @@ diff --git a/app/src/components/DeviceCard.vue b/app/src/components/DeviceCard.vue index 785487b..535f57d 100644 --- a/app/src/components/DeviceCard.vue +++ b/app/src/components/DeviceCard.vue @@ -34,7 +34,7 @@ - $memory + $storage i8n:Storage diff --git a/app/src/layouts/default.vue b/app/src/layouts/default.vue new file mode 100644 index 0000000..61ee661 --- /dev/null +++ b/app/src/layouts/default.vue @@ -0,0 +1,191 @@ + + + + + diff --git a/app/src/layouts/setup.vue b/app/src/layouts/setup.vue new file mode 100644 index 0000000..43c81bc --- /dev/null +++ b/app/src/layouts/setup.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/app/src/main.js b/app/src/main.js index ee441de..ff354a4 100644 --- a/app/src/main.js +++ b/app/src/main.js @@ -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') diff --git a/app/src/plugins/vuetify.js b/app/src/plugins/vuetify.js index 1b6ebdf..9daa56d 100644 --- a/app/src/plugins/vuetify.js +++ b/app/src/plugins/vuetify.js @@ -12,7 +12,7 @@ const MY_ICONS = { // 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')}, + 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') }, @@ -23,7 +23,7 @@ const MY_ICONS = { // 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')}, + 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') }, @@ -49,6 +49,11 @@ const MY_ICONS = { 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') }, + storage: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/sd_storage/baseline.svg') }, + playlist: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/live_tv/baseline.svg') }, + support: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/support/baseline.svg') }, + device: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/video_label/baseline.svg') }, + update: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/update/baseline.svg') }, // wifi signalWifiOff: { component: () => import(/* webpackChunkName: "icons" */'!vue-svg-loader!@material-icons/svg/svg/signal_wifi_off/baseline.svg') }, diff --git a/app/src/router/index.js b/app/src/router/index.js index 6c73397..380693b 100644 --- a/app/src/router/index.js +++ b/app/src/router/index.js @@ -3,6 +3,10 @@ import VueRouter from 'vue-router' const Dashboard = () => import('../views/Dashboard') const Settings = () => import('../views/Settings') +const Device = () => import('../views/Device') +const Playlist = () => import('../views/Playlist') +const Weather = () => import('../views/Weather') +const System = () => import('../views/System') const SetupStart = () => import('../views/Setup/Start') const SetupCountry = () => import('../views/Setup/Country') @@ -18,15 +22,20 @@ export default new VueRouter({ routes: [ { path: '/', component: Dashboard }, { path: '/settings', component: Settings, meta: { transitionName: 'slide' } }, + { path: '/device', component: Device, meta: { transitionName: 'slide' } }, + { path: '/playlist', component: Playlist, meta: { transitionName: 'slide' } }, + { path: '/weather', component: Weather, meta: { transitionName: 'slide' } }, + { path: '/system', component: System, 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: '/setup', redirect: '/setup/start' }, + { path: '/setup/start', component: SetupStart, meta: { transitionName: 'slide', layout: 'setup' } }, + { path: '/setup/country', component: SetupCountry, meta: { transitionName: 'slide', layout: 'setup' } }, + { path: '/setup/wifi', component: SetupWifi, meta: { transitionName: 'slide', layout: 'setup' } }, + { path: '/setup/weather', component: SetupWeather, meta: { transitionName: 'slide', layout: 'setup' } }, + { path: '/setup/name', component: SetupName, meta: { transitionName: 'slide', layout: 'setup' } }, + { path: '/setup/appearance', component: SetupAppearance, meta: { transitionName: 'slide', layout: 'setup' } }, + { path: '/setup/done', component: SetupDone, meta: { transitionName: 'slide', layout: 'setup' } }, { path: '*', redirect: '/' }, ], diff --git a/app/src/store/index.js b/app/src/store/index.js new file mode 100644 index 0000000..78d32e9 --- /dev/null +++ b/app/src/store/index.js @@ -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 diff --git a/app/src/views/Dashboard.vue b/app/src/views/Dashboard.vue index a7b664e..c953831 100644 --- a/app/src/views/Dashboard.vue +++ b/app/src/views/Dashboard.vue @@ -9,6 +9,18 @@ md="6" > + + ({ isLoading: false, }), + computed: { + firmware () { + return { + // eslint-disable-next-line no-undef + created: __BUILD_TIME__ || JSON.stringify(new Date().getTime() / 1000 | 0), + // eslint-disable-next-line no-undef + rev: __COMMIT_HASH__ || 'dev-master', + } + }, + }, } diff --git a/app/src/views/Device.vue b/app/src/views/Device.vue new file mode 100644 index 0000000..60979a1 --- /dev/null +++ b/app/src/views/Device.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/app/src/views/Playlist.vue b/app/src/views/Playlist.vue new file mode 100644 index 0000000..048f560 --- /dev/null +++ b/app/src/views/Playlist.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/app/src/views/Setup.vue b/app/src/views/Setup.vue deleted file mode 100644 index 39daa52..0000000 --- a/app/src/views/Setup.vue +++ /dev/null @@ -1,450 +0,0 @@ - - - - - diff --git a/app/src/views/Setup/Wifi.vue b/app/src/views/Setup/Wifi.vue index 4d1f209..8bdb9b5 100644 --- a/app/src/views/Setup/Wifi.vue +++ b/app/src/views/Setup/Wifi.vue @@ -76,6 +76,7 @@ text color="primary" class="_px-0 my-2" + disabled > Choose Another Network diff --git a/app/src/views/System.vue b/app/src/views/System.vue new file mode 100644 index 0000000..e1ffacf --- /dev/null +++ b/app/src/views/System.vue @@ -0,0 +1,147 @@ + + + + + diff --git a/app/src/views/Weather.vue b/app/src/views/Weather.vue new file mode 100644 index 0000000..0da17f1 --- /dev/null +++ b/app/src/views/Weather.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/app/src/views/Wifi.vue b/app/src/views/Wifi.vue deleted file mode 100644 index 4ec06c0..0000000 --- a/app/src/views/Wifi.vue +++ /dev/null @@ -1,258 +0,0 @@ - - - - - diff --git a/app/yarn.lock b/app/yarn.lock index efce44f..5023e8e 100644 --- a/app/yarn.lock +++ b/app/yarn.lock @@ -6967,11 +6967,6 @@ modify-values@^1.0.0: resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== -moment@^2.19.2: - version "2.29.0" - resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.0.tgz#fcbef955844d91deb55438613ddcec56e86a3425" - integrity sha512-z6IJ5HXYiuxvFTI6eiQ9dm77uE0gyy1yXNApVHqTcnIKfY9tIwEjlzsZ6u1LQXvVgKeTnv9Xm7NDvJ7lso3MtA== - move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -10306,13 +10301,6 @@ vue-loader@^15.9.2: vue-hot-reload-api "^2.3.0" vue-style-loader "^4.1.0" -vue-moment@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/vue-moment/-/vue-moment-4.1.0.tgz#092a8ff723a96c6f85a0a8e23ad30f0bf320f3b0" - integrity sha512-Gzisqpg82ItlrUyiD9d0Kfru+JorW2o4mQOH06lEDZNgxci0tv/fua1Hl0bo4DozDV2JK1r52Atn/8QVCu8qQw== - dependencies: - moment "^2.19.2" - vue-router@^3.1.5: version "3.4.5" resolved "https://registry.yarnpkg.com/vue-router/-/vue-router-3.4.5.tgz#d396ec037b35931bdd1e9b7edd86f9788dc15175" @@ -10370,6 +10358,11 @@ vuetify@^2.2.28: resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-2.3.15.tgz#ea148acce8f5bc272f64f03a0d2ace09e58e092c" integrity sha512-YVJN/ld60S2mmFCKxoVFkB8X2kmuLT0E28ql4kr8HQUeCYdK8axoca/N8ZIP1hFH4NIz392f0nVpZKS4ZFZBVA== +vuex@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/vuex/-/vuex-3.5.1.tgz#f1b8dcea649bc25254cf4f4358081dbf5da18b3d" + integrity sha512-w7oJzmHQs0FM9LXodfskhw9wgKBiaB+totOdb8sNzbTB2KDCEEwEs29NzBZFh/lmEK1t5tDmM1vtsO7ubG1DFw== + watchpack-chokidar2@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/watchpack-chokidar2/-/watchpack-chokidar2-2.0.0.tgz#9948a1866cbbd6cb824dea13a7ed691f6c8ddff0"