Finished Vue single file component implementation
This commit is contained in:
parent
7ae2f49ee8
commit
e2ba4e0d4c
|
@ -46,7 +46,7 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="navigation tabs">
|
<div class="navigation tabs">
|
||||||
<router-link to="/" class="button" active-class="active" exact="true">{{ $t('status.tabTitle') }}</router-link><router-link to="/connection" class="button" active-class="active">{{ $t('connection.tabTitle') }}</router-link><router-link to="/system" class="button" active-class="active">{{ $t('system.tabTitle') }}</router-link>
|
<router-link to="/" class="button" active-class="active" :exact="true">{{ $t('status.tabTitle') }}</router-link><router-link to="/connection" class="button" active-class="active">{{ $t('connection.tabTitle') }}</router-link><router-link to="/system" class="button" active-class="active">{{ $t('system.tabTitle') }}</router-link>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
@ -66,8 +66,11 @@
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import LoadingIndicator from '@/components/loadingIndicator.vue';
|
import LoadingIndicator from '@/components/loadingIndicator.vue';
|
||||||
|
import BaseVM from '@/BaseVM';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [BaseVM],
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
LoadingIndicator
|
LoadingIndicator
|
||||||
},
|
},
|
||||||
|
@ -117,7 +120,6 @@ export default {
|
||||||
|
|
||||||
computed: {
|
computed: {
|
||||||
notification() { return this.$store.state.notification; },
|
notification() { return this.$store.state.notification; },
|
||||||
saving() { return this.$store.state.saving; },
|
|
||||||
|
|
||||||
hasResetError()
|
hasResetError()
|
||||||
{
|
{
|
||||||
|
@ -199,7 +201,7 @@ export default {
|
||||||
|
|
||||||
updateStatus()
|
updateStatus()
|
||||||
{
|
{
|
||||||
var self = this;
|
const self = this;
|
||||||
|
|
||||||
return axios.get('/api/status', { retry: 10, retryDelay: 1000 })
|
return axios.get('/api/status', { retry: 10, retryDelay: 1000 })
|
||||||
.then(response =>
|
.then(response =>
|
||||||
|
@ -259,12 +261,6 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
handleAPIError(messageId, error)
|
|
||||||
{
|
|
||||||
this.$store.dispatch('notifyAPIError', { message: this.$i18n.t(messageId), error });
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
hideNotification()
|
hideNotification()
|
||||||
{
|
{
|
||||||
this.$store.dispatch('hideNotification');
|
this.$store.dispatch('hideNotification');
|
||||||
|
@ -276,6 +272,7 @@ export default {
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@import "variables.scss";
|
@import "variables.scss";
|
||||||
|
|
||||||
|
// TODO check which parts are app-wide and which should be moved to components/view
|
||||||
|
|
||||||
html
|
html
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
export default {
|
||||||
|
computed: {
|
||||||
|
saving() { return this.$store.state.saving; }
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
setSaving(value)
|
||||||
|
{
|
||||||
|
self.$store.commit('saving', value);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
showNotification(message, isError)
|
||||||
|
{
|
||||||
|
this.$store.dispatch('showNotification', {
|
||||||
|
message: message,
|
||||||
|
isError: isError || false
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
handleAPIError(messageId, error)
|
||||||
|
{
|
||||||
|
this.$store.dispatch('notifyAPIError', { message: this.$i18n.t(messageId), error });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
147
web/src/app.js
147
web/src/app.js
|
@ -1,147 +0,0 @@
|
||||||
function startApp()
|
|
||||||
{
|
|
||||||
var app = new Vue({
|
|
||||||
el: '#app',
|
|
||||||
|
|
||||||
data: {
|
|
||||||
},
|
|
||||||
|
|
||||||
created: function()
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
self.notificationTimer = null;
|
|
||||||
|
|
||||||
// Sequential loading of all the settings makes sure
|
|
||||||
// we don't overload the ESP8266 with requests, as that
|
|
||||||
// can cause it to run out of memory easily.
|
|
||||||
// This is a horrible way to implement it, but I don't feel like
|
|
||||||
// including a big library or working out a clean short solution
|
|
||||||
// at the moment, and it works :)
|
|
||||||
self.loadStatus().then(function()
|
|
||||||
{
|
|
||||||
self.loadConnection().then(function()
|
|
||||||
{
|
|
||||||
self.loadSystem().then(function()
|
|
||||||
{
|
|
||||||
self.stopLoadingIndicator();
|
|
||||||
self.loading = false;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
methods: {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
loadConnection: function()
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
return axios.get('/api/connection', { retry: 10, retryDelay: 1000 })
|
|
||||||
.then(function(response)
|
|
||||||
{
|
|
||||||
if (typeof response.data == 'object')
|
|
||||||
self.connection = response.data;
|
|
||||||
})
|
|
||||||
.catch(self.handleAPIError.bind(self, 'error.loadConnection'));
|
|
||||||
},
|
|
||||||
|
|
||||||
loadSystem: function()
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
return axios.get('/api/system', { retry: 10, retryDelay: 1000 })
|
|
||||||
.then(function(response)
|
|
||||||
{
|
|
||||||
if (typeof response.data == 'object')
|
|
||||||
self.system = response.data;
|
|
||||||
})
|
|
||||||
.catch(self.handleAPIError.bind(self, 'error.loadSystem'));
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
applyConnection: function()
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
if (self.saving) return;
|
|
||||||
|
|
||||||
self.saving = true;
|
|
||||||
|
|
||||||
axios.post('/api/connection', {
|
|
||||||
hostname: self.connection.hostname,
|
|
||||||
accesspoint: self.connection.accesspoint,
|
|
||||||
station: self.connection.station,
|
|
||||||
ssid: self.connection.ssid,
|
|
||||||
password: self.connection.password,
|
|
||||||
dhcp: self.connection.dhcp,
|
|
||||||
ip: self.connection.ip,
|
|
||||||
subnetmask: self.connection.subnetmask,
|
|
||||||
gateway: self.connection.gateway,
|
|
||||||
}, { retry: 10, retryDelay: 1000, headers: { 'Content-Type': 'application/json' } })
|
|
||||||
.then(function(response)
|
|
||||||
{
|
|
||||||
})
|
|
||||||
.catch(self.handleAPIError.bind(self, 'error.applyConnection'))
|
|
||||||
.then(function()
|
|
||||||
{
|
|
||||||
self.saving = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
applySystem: function()
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
if (self.saving) return;
|
|
||||||
|
|
||||||
self.saving = true;
|
|
||||||
|
|
||||||
axios.post('/api/system', self.system, { retry: 10, retryDelay: 1000, headers: { 'Content-Type': 'application/json' } })
|
|
||||||
.then(function(response)
|
|
||||||
{
|
|
||||||
self.showNotification(i18n.t('rebootPending'));
|
|
||||||
})
|
|
||||||
.catch(self.handleAPIError.bind(self, 'error.applySystem'))
|
|
||||||
.then(function()
|
|
||||||
{
|
|
||||||
self.saving = false;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
uploadFirmware: function()
|
|
||||||
{
|
|
||||||
var self = this;
|
|
||||||
if (self.saving) return;
|
|
||||||
|
|
||||||
self.saving = true;
|
|
||||||
self.uploadProgress = 0;
|
|
||||||
|
|
||||||
|
|
||||||
var data = new FormData();
|
|
||||||
data.append('file', document.getElementById('firmwareFile').files[0]);
|
|
||||||
|
|
||||||
var config = {
|
|
||||||
timeout: 360000,
|
|
||||||
onUploadProgress: function(progressEvent)
|
|
||||||
{
|
|
||||||
self.uploadProgress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
axios.post('/api/firmware', data, config)
|
|
||||||
.then(function(response)
|
|
||||||
{
|
|
||||||
self.showNotification(i18n.t('rebootPending'));
|
|
||||||
})
|
|
||||||
.catch(self.handleAPIError.bind(self, 'error.uploadFirmware'))
|
|
||||||
.then(function()
|
|
||||||
{
|
|
||||||
self.uploadProgress = false;
|
|
||||||
self.saving = false;
|
|
||||||
|
|
||||||
document.getElementById('firmware').reset();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -69,7 +69,9 @@ export default {
|
||||||
pinLEDSTA: 'Station Mode status LED pin (+3.3v)',
|
pinLEDSTA: 'Station Mode status LED pin (+3.3v)',
|
||||||
pinAPButton: 'Enable Access Point button pin (active low)',
|
pinAPButton: 'Enable Access Point button pin (active low)',
|
||||||
|
|
||||||
ledCount: 'Number of LEDs on strip'
|
ledCount: 'Number of LEDs on strip',
|
||||||
|
|
||||||
|
noFileSelected: 'No firmware file selected'
|
||||||
},
|
},
|
||||||
|
|
||||||
error: {
|
error: {
|
||||||
|
|
|
@ -69,7 +69,9 @@ export default {
|
||||||
pinLEDSTA: 'WiFi status LED pin (+3.3v)',
|
pinLEDSTA: 'WiFi status LED pin (+3.3v)',
|
||||||
pinAPButton: 'Access Point inschakelen knop pin (actief laag)',
|
pinAPButton: 'Access Point inschakelen knop pin (actief laag)',
|
||||||
|
|
||||||
ledCount: 'Aantal LEDs op strip'
|
ledCount: 'Aantal LEDs op strip',
|
||||||
|
|
||||||
|
noFileSelected: 'Geen firmware bestand geselecteerd'
|
||||||
},
|
},
|
||||||
|
|
||||||
error: {
|
error: {
|
||||||
|
|
|
@ -1,127 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<title>RGBWifi</title>
|
|
||||||
<meta name="theme-color" content="#000000">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
||||||
<link rel="stylesheet" href="bundle.css">
|
|
||||||
<script src="bundle.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div id="app">
|
|
||||||
<div v-cloak>
|
|
||||||
|
|
||||||
|
|
||||||
<div v-if="activeTab == 'status'">
|
|
||||||
<!--
|
|
||||||
|
|
||||||
Status tab
|
|
||||||
|
|
||||||
-->
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="activeTab == 'connection'">
|
|
||||||
<!--
|
|
||||||
|
|
||||||
Connection tab
|
|
||||||
|
|
||||||
-->
|
|
||||||
<form @submit.prevent="applyConnection">
|
|
||||||
<h3>{{ $t('connection.title') }}</h3>
|
|
||||||
|
|
||||||
<check v-model.boolean="connection.accesspoint" :title="$t('connection.accesspoint')"></check>
|
|
||||||
<span class="hint">{{ $t('connection.accesspointHint') }}</span>
|
|
||||||
|
|
||||||
<check v-model.boolean="connection.station" :title="$t('connection.stationmode')"></check>
|
|
||||||
<span class="hint">{{ $t('connection.stationmodeHint') }}</span>
|
|
||||||
|
|
||||||
<label for="ssid">{{ $t('connection.ssid') }}</label>
|
|
||||||
<input type="text" id="ssid" v-model="connection.ssid" :disabled="!connection.station">
|
|
||||||
|
|
||||||
<label for="password">{{ $t('connection.password') }}</label>
|
|
||||||
<input type="password" id="password" v-model="connection.password" :disabled="!connection.station">
|
|
||||||
|
|
||||||
<check v-model.boolean="connection.dhcp" :disabled="!connection.station" :title="$t('connection.dhcp')" class="form-control"></check>
|
|
||||||
<span class="hint">{{ $t('connection.dhcpHint') }}</span>
|
|
||||||
|
|
||||||
|
|
||||||
<div class="suboptions">
|
|
||||||
<label for="ip">{{ $t('connection.ipaddress') }}</label>
|
|
||||||
<input type="text" id="ip" v-model="connection.ip" :disabled="!connection.station || connection.dhcp">
|
|
||||||
|
|
||||||
<label for="subnetmask">{{ $t('connection.subnetmask') }}</label>
|
|
||||||
<input type="text" id="subnetmask" v-model="connection.subnetmask" :disabled="!connection.station || connection.dhcp">
|
|
||||||
|
|
||||||
<label for="gateway">{{ $t('connection.gateway') }}</label>
|
|
||||||
<input type="text" id="gateway" v-model="connection.gateway" :disabled="!connection.station || connection.dhcp">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<label for="hostname">{{ $t('connection.hostname') }}</label>
|
|
||||||
<input type="text" :placeholder="$t('connection.hostnamePlaceholder')" id="hostname" v-model="connection.hostname" :disabled="!connection.station">
|
|
||||||
<span class="hint">{{ $t('connection.hostnameHint') }}</span>
|
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
<input type="submit" :disabled="saving" :value="saving ? $t('applyButtonSaving') : $t('applyButton')">
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="activeTab == 'system'">
|
|
||||||
<!--
|
|
||||||
|
|
||||||
System tab
|
|
||||||
|
|
||||||
-->
|
|
||||||
<form @submit.prevent="uploadFirmware">
|
|
||||||
<h3>{{ $t('system.firmwareTitle') }}</h3>
|
|
||||||
|
|
||||||
<input type="file" id="firmwareFile">
|
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
<input type="submit" :disabled="saving" :value="saving ? $t('applyButtonSaving') : $t('applyButton')">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-if="uploadProgress !== false">
|
|
||||||
{{ uploadProgress }}%
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
|
|
||||||
<form @submit.prevent="applySystem">
|
|
||||||
<h3>{{ $t('system.pinsTitle') }}</h3>
|
|
||||||
|
|
||||||
<div class="horizontal">
|
|
||||||
<label for="pinLEDAP">{{ $t('system.pinLEDAP') }}</label>
|
|
||||||
<input type="number" id="pinLEDAP" v-model.number="system.pins.ledAP">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="horizontal">
|
|
||||||
<label for="pinLEDSTA">{{ $t('system.pinLEDSTA') }}</label>
|
|
||||||
<input type="number" id="pinLEDSTA" v-model.number="system.pins.ledSTA">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="horizontal">
|
|
||||||
<label for="pinAPButton">{{ $t('system.pinAPButton') }}</label>
|
|
||||||
<input type="number" id="pinAPButton" v-model.number="system.pins.apButton">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<h3>{{ $t('system.ledStripTitle') }}</h3>
|
|
||||||
|
|
||||||
<div class="horizontal">
|
|
||||||
<label for="ledCount">{{ $t('system.ledCount') }}</label>
|
|
||||||
<input type="number" id="ledCount" v-model.number="system.ledCount">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="buttons">
|
|
||||||
<input type="submit" :disabled="saving" :value="saving ? $t('applyButtonSaving') : $t('applyButton')">
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
<script language="javascript">
|
|
||||||
startApp();
|
|
||||||
</script>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -1,8 +1,8 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import VueRouter from 'vue-router'
|
import VueRouter from 'vue-router'
|
||||||
import Status from '../views/Status.vue'
|
import Status from '../views/Status.vue'
|
||||||
//import Connection from '../views/Connection.vue'
|
import Connection from '../views/Connection.vue'
|
||||||
//import System from '../views/System.vue'
|
import System from '../views/System.vue'
|
||||||
|
|
||||||
Vue.use(VueRouter)
|
Vue.use(VueRouter)
|
||||||
|
|
||||||
|
@ -12,6 +12,16 @@ const routes = [
|
||||||
path: '/',
|
path: '/',
|
||||||
name: 'Status',
|
name: 'Status',
|
||||||
component: Status
|
component: Status
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/connection',
|
||||||
|
name: 'Connection',
|
||||||
|
component: Connection
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/system',
|
||||||
|
name: 'System',
|
||||||
|
component: System
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -7,46 +7,17 @@ export default new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
notification: null,
|
notification: null,
|
||||||
notificationTimeout: null,
|
notificationTimeout: null,
|
||||||
saving: false,
|
saving: false
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
connection: {
|
mutations: {
|
||||||
hostname: null,
|
saving(state, value)
|
||||||
accesspoint: true,
|
{
|
||||||
station: false,
|
state.saving = value;
|
||||||
ssid: null,
|
|
||||||
password: null,
|
|
||||||
dhcp: true,
|
|
||||||
ip: null,
|
|
||||||
subnetmask: null,
|
|
||||||
gateway: null
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
system: {
|
|
||||||
pins: {
|
|
||||||
ledAP: null,
|
|
||||||
ledSTA: null,
|
|
||||||
apButton: null,
|
|
||||||
},
|
|
||||||
ledCount: null
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
settingStatic: false,
|
|
||||||
loadingIndicator: '|',
|
|
||||||
uploadProgress: false,
|
|
||||||
|
|
||||||
static: {
|
|
||||||
r: 0,
|
|
||||||
g: 0,
|
|
||||||
b: 0,
|
|
||||||
w: 0
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
},
|
|
||||||
|
|
||||||
mutations: {
|
|
||||||
_setNotification(state, payload)
|
_setNotification(state, payload)
|
||||||
{
|
{
|
||||||
state.notification = payload.notification;
|
state.notification = payload.notification;
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
<template>
|
||||||
|
<form @submit.prevent="save">
|
||||||
|
<h3>{{ $t('connection.title') }}</h3>
|
||||||
|
|
||||||
|
<div v-if="connection === null" class="loading">
|
||||||
|
<LoadingIndicator></LoadingIndicator>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else>
|
||||||
|
<check v-model.boolean="connection.accesspoint" :title="$t('connection.accesspoint')"></check>
|
||||||
|
<span class="hint">{{ $t('connection.accesspointHint') }}</span>
|
||||||
|
|
||||||
|
<check v-model.boolean="connection.station" :title="$t('connection.stationmode')"></check>
|
||||||
|
<span class="hint">{{ $t('connection.stationmodeHint') }}</span>
|
||||||
|
|
||||||
|
<label for="ssid">{{ $t('connection.ssid') }}</label>
|
||||||
|
<input type="text" id="ssid" v-model="connection.ssid" :disabled="!connection.station">
|
||||||
|
|
||||||
|
<label for="password">{{ $t('connection.password') }}</label>
|
||||||
|
<input type="password" id="password" v-model="connection.password" :disabled="!connection.station">
|
||||||
|
|
||||||
|
<check v-model.boolean="connection.dhcp" :disabled="!connection.station" :title="$t('connection.dhcp')" class="form-control"></check>
|
||||||
|
<span class="hint">{{ $t('connection.dhcpHint') }}</span>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="suboptions">
|
||||||
|
<label for="ip">{{ $t('connection.ipaddress') }}</label>
|
||||||
|
<input type="text" id="ip" v-model="connection.ip" :disabled="!connection.station || connection.dhcp">
|
||||||
|
|
||||||
|
<label for="subnetmask">{{ $t('connection.subnetmask') }}</label>
|
||||||
|
<input type="text" id="subnetmask" v-model="connection.subnetmask" :disabled="!connection.station || connection.dhcp">
|
||||||
|
|
||||||
|
<label for="gateway">{{ $t('connection.gateway') }}</label>
|
||||||
|
<input type="text" id="gateway" v-model="connection.gateway" :disabled="!connection.station || connection.dhcp">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<label for="hostname">{{ $t('connection.hostname') }}</label>
|
||||||
|
<input type="text" :placeholder="$t('connection.hostnamePlaceholder')" id="hostname" v-model="connection.hostname" :disabled="!connection.station">
|
||||||
|
<span class="hint">{{ $t('connection.hostnameHint') }}</span>
|
||||||
|
|
||||||
|
<div class="buttons">
|
||||||
|
<input type="submit" :disabled="saving" :value="saving ? $t('applyButtonSaving') : $t('applyButton')">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from 'axios';
|
||||||
|
import LoadingIndicator from '@/components/loadingIndicator.vue';
|
||||||
|
import check from '@/components/check.vue';
|
||||||
|
import BaseVM from '@/BaseVM';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [BaseVM],
|
||||||
|
|
||||||
|
components: {
|
||||||
|
LoadingIndicator,
|
||||||
|
check
|
||||||
|
},
|
||||||
|
|
||||||
|
data()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
connection: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
mounted()
|
||||||
|
{
|
||||||
|
this.load();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
load()
|
||||||
|
{
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
return axios.get('/api/connection', { retry: 10, retryDelay: 1000 })
|
||||||
|
.then(response =>
|
||||||
|
{
|
||||||
|
if (typeof response.data == 'object')
|
||||||
|
self.connection = response.data;
|
||||||
|
})
|
||||||
|
.catch(e => self.handleAPIError('error.loadConnection', e));
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
save()
|
||||||
|
{
|
||||||
|
const self = this;
|
||||||
|
if (self.saving)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self.setSaving(true);
|
||||||
|
|
||||||
|
axios.post('/api/connection', {
|
||||||
|
hostname: self.connection.hostname,
|
||||||
|
accesspoint: self.connection.accesspoint,
|
||||||
|
station: self.connection.station,
|
||||||
|
ssid: self.connection.ssid,
|
||||||
|
password: self.connection.password,
|
||||||
|
dhcp: self.connection.dhcp,
|
||||||
|
ip: self.connection.ip,
|
||||||
|
subnetmask: self.connection.subnetmask,
|
||||||
|
gateway: self.connection.gateway,
|
||||||
|
}, { retry: 10, retryDelay: 1000, headers: { 'Content-Type': 'application/json' } })
|
||||||
|
.then(response => {})
|
||||||
|
.catch(e => self.handleAPIError('error.applyConnection', e))
|
||||||
|
.then(() =>
|
||||||
|
{
|
||||||
|
self.setSaving(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -30,8 +30,11 @@
|
||||||
<script>
|
<script>
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import LoadingIndicator from '@/components/loadingIndicator.vue';
|
import LoadingIndicator from '@/components/loadingIndicator.vue';
|
||||||
|
import BaseVM from '@/BaseVM';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
mixins: [BaseVM],
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
LoadingIndicator
|
LoadingIndicator
|
||||||
},
|
},
|
||||||
|
@ -51,22 +54,34 @@ export default {
|
||||||
self.disableSetStatic = false;
|
self.disableSetStatic = false;
|
||||||
self.setStaticTimer = false;
|
self.setStaticTimer = false;
|
||||||
|
|
||||||
// TODO load current settings (no API for it yet)
|
self.load()
|
||||||
self.static = {
|
.then(() =>
|
||||||
r: 0,
|
{
|
||||||
g: 0,
|
self.$watch('static', () =>
|
||||||
b: 0,
|
{
|
||||||
w: 0
|
self.staticChanged();
|
||||||
};
|
}, { deep: true });
|
||||||
|
});
|
||||||
self.$watch('static', () =>
|
|
||||||
{
|
|
||||||
self.staticChanged();
|
|
||||||
}, { deep: true });
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
load()
|
||||||
|
{
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
// TODO load current settings (no API for it yet)
|
||||||
|
self.static = {
|
||||||
|
r: 0,
|
||||||
|
g: 0,
|
||||||
|
b: 0,
|
||||||
|
w: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
return Promise.resolve(true);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
staticOff()
|
staticOff()
|
||||||
{
|
{
|
||||||
this.static = {
|
this.static = {
|
||||||
|
@ -80,7 +95,7 @@ export default {
|
||||||
|
|
||||||
staticChanged()
|
staticChanged()
|
||||||
{
|
{
|
||||||
var self = this;
|
const self = this;
|
||||||
console.log(self.setStaticTimer);
|
console.log(self.setStaticTimer);
|
||||||
|
|
||||||
if (self.setStaticTimer === false)
|
if (self.setStaticTimer === false)
|
||||||
|
@ -93,7 +108,7 @@ export default {
|
||||||
|
|
||||||
setStatic()
|
setStatic()
|
||||||
{
|
{
|
||||||
var self = this;
|
const self = this;
|
||||||
|
|
||||||
if (self.settingStatic)
|
if (self.settingStatic)
|
||||||
{
|
{
|
||||||
|
@ -118,12 +133,6 @@ export default {
|
||||||
{
|
{
|
||||||
self.settingStatic = false;
|
self.settingStatic = false;
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
handleAPIError(messageId, error)
|
|
||||||
{
|
|
||||||
this.$store.dispatch('notifyAPIError', { message: this.$i18n.t(messageId), error });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<h3>{{ $t('system.firmwareTitle') }}</h3>
|
||||||
|
|
||||||
|
<div v-if="system === null" class="loading">
|
||||||
|
<LoadingIndicator></LoadingIndicator>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else>
|
||||||
|
<form @submit.prevent="uploadFirmware">
|
||||||
|
<input type="file" id="firmwareFile">
|
||||||
|
|
||||||
|
<div class="buttons">
|
||||||
|
<input type="submit" :disabled="saving" :value="saving ? $t('applyButtonSaving') : $t('applyButton')">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="uploadProgress !== false">
|
||||||
|
{{ uploadProgress }}%
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<form @submit.prevent="applySystem">
|
||||||
|
<h3>{{ $t('system.pinsTitle') }}</h3>
|
||||||
|
|
||||||
|
<div class="horizontal">
|
||||||
|
<label for="pinLEDAP">{{ $t('system.pinLEDAP') }}</label>
|
||||||
|
<input type="number" id="pinLEDAP" v-model.number="system.pins.ledAP">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="horizontal">
|
||||||
|
<label for="pinLEDSTA">{{ $t('system.pinLEDSTA') }}</label>
|
||||||
|
<input type="number" id="pinLEDSTA" v-model.number="system.pins.ledSTA">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="horizontal">
|
||||||
|
<label for="pinAPButton">{{ $t('system.pinAPButton') }}</label>
|
||||||
|
<input type="number" id="pinAPButton" v-model.number="system.pins.apButton">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>{{ $t('system.ledStripTitle') }}</h3>
|
||||||
|
|
||||||
|
<div class="horizontal">
|
||||||
|
<label for="ledCount">{{ $t('system.ledCount') }}</label>
|
||||||
|
<input type="number" id="ledCount" v-model.number="system.ledCount">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="buttons">
|
||||||
|
<input type="submit" :disabled="saving" :value="saving ? $t('applyButtonSaving') : $t('applyButton')">
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import axios from 'axios';
|
||||||
|
import LoadingIndicator from '@/components/loadingIndicator.vue';
|
||||||
|
import BaseVM from '@/BaseVM';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [BaseVM],
|
||||||
|
|
||||||
|
components: {
|
||||||
|
LoadingIndicator
|
||||||
|
},
|
||||||
|
|
||||||
|
data()
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
system: null,
|
||||||
|
uploadProgress: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
mounted()
|
||||||
|
{
|
||||||
|
this.load();
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
load()
|
||||||
|
{
|
||||||
|
const self = this;
|
||||||
|
|
||||||
|
return axios.get('/api/system', { retry: 10, retryDelay: 1000 })
|
||||||
|
.then(response =>
|
||||||
|
{
|
||||||
|
if (typeof response.data == 'object')
|
||||||
|
self.system = response.data;
|
||||||
|
})
|
||||||
|
.catch(e => self.handleAPIError('error.loadSystem', e));
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
save()
|
||||||
|
{
|
||||||
|
const self = this;
|
||||||
|
if (self.saving)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self.setSaving(true);
|
||||||
|
|
||||||
|
axios.post('/api/system', self.system, { retry: 10, retryDelay: 1000, headers: { 'Content-Type': 'application/json' } })
|
||||||
|
.then(response =>
|
||||||
|
{
|
||||||
|
self.showNotification(i18n.t('rebootPending'));
|
||||||
|
})
|
||||||
|
.catch(e => self.handleAPIError('error.applySystem', e))
|
||||||
|
.then(() =>
|
||||||
|
{
|
||||||
|
self.setSaving(false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
uploadFirmware()
|
||||||
|
{
|
||||||
|
const self = this;
|
||||||
|
if (self.saving) return;
|
||||||
|
|
||||||
|
const fileElement = document.getElementById('firmwareFile');
|
||||||
|
if (fileElement.files.length == 0)
|
||||||
|
{
|
||||||
|
self.showNotification(self.$i18n.t('system.noFileSelected'), true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.saving = true;
|
||||||
|
self.uploadProgress = 0;
|
||||||
|
|
||||||
|
const data = new FormData();
|
||||||
|
|
||||||
|
data.append('file', fileElement.files[0]);
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
timeout: 360000,
|
||||||
|
onUploadProgress: progressEvent =>
|
||||||
|
{
|
||||||
|
self.uploadProgress = Math.round((progressEvent.loaded * 100) / progressEvent.total);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
axios.post('/api/firmware', data, config)
|
||||||
|
.then(response =>
|
||||||
|
{
|
||||||
|
self.showNotification(self.$i18n.t('rebootPending'));
|
||||||
|
})
|
||||||
|
.catch(e => self.handleAPIError('error.uploadFirmware', e))
|
||||||
|
.then(() =>
|
||||||
|
{
|
||||||
|
self.uploadProgress = false;
|
||||||
|
self.saving = false;
|
||||||
|
|
||||||
|
document.getElementById('firmware').reset();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -8,7 +8,7 @@ module.exports = merge(config, {
|
||||||
historyApiFallback: true,
|
historyApiFallback: true,
|
||||||
proxy:{
|
proxy:{
|
||||||
'/api': {
|
'/api': {
|
||||||
target: 'http://localhost:3000'
|
target: 'http://127.0.0.1:3000'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue