Finished Vue single file component implementation
This commit is contained in:
parent
7ae2f49ee8
commit
e2ba4e0d4c
|
@ -46,7 +46,7 @@
|
|||
|
||||
|
||||
<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>
|
||||
|
||||
|
||||
|
@ -66,8 +66,11 @@
|
|||
<script>
|
||||
import axios from 'axios'
|
||||
import LoadingIndicator from '@/components/loadingIndicator.vue';
|
||||
import BaseVM from '@/BaseVM';
|
||||
|
||||
export default {
|
||||
mixins: [BaseVM],
|
||||
|
||||
components: {
|
||||
LoadingIndicator
|
||||
},
|
||||
|
@ -117,7 +120,6 @@ export default {
|
|||
|
||||
computed: {
|
||||
notification() { return this.$store.state.notification; },
|
||||
saving() { return this.$store.state.saving; },
|
||||
|
||||
hasResetError()
|
||||
{
|
||||
|
@ -199,7 +201,7 @@ export default {
|
|||
|
||||
updateStatus()
|
||||
{
|
||||
var self = this;
|
||||
const self = this;
|
||||
|
||||
return axios.get('/api/status', { retry: 10, retryDelay: 1000 })
|
||||
.then(response =>
|
||||
|
@ -259,12 +261,6 @@ export default {
|
|||
},
|
||||
|
||||
|
||||
handleAPIError(messageId, error)
|
||||
{
|
||||
this.$store.dispatch('notifyAPIError', { message: this.$i18n.t(messageId), error });
|
||||
},
|
||||
|
||||
|
||||
hideNotification()
|
||||
{
|
||||
this.$store.dispatch('hideNotification');
|
||||
|
@ -276,6 +272,7 @@ export default {
|
|||
<style lang="scss">
|
||||
@import "variables.scss";
|
||||
|
||||
// TODO check which parts are app-wide and which should be moved to components/view
|
||||
|
||||
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)',
|
||||
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: {
|
||||
|
|
|
@ -69,7 +69,9 @@ export default {
|
|||
pinLEDSTA: 'WiFi status LED pin (+3.3v)',
|
||||
pinAPButton: 'Access Point inschakelen knop pin (actief laag)',
|
||||
|
||||
ledCount: 'Aantal LEDs op strip'
|
||||
ledCount: 'Aantal LEDs op strip',
|
||||
|
||||
noFileSelected: 'Geen firmware bestand geselecteerd'
|
||||
},
|
||||
|
||||
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 VueRouter from 'vue-router'
|
||||
import Status from '../views/Status.vue'
|
||||
//import Connection from '../views/Connection.vue'
|
||||
//import System from '../views/System.vue'
|
||||
import Connection from '../views/Connection.vue'
|
||||
import System from '../views/System.vue'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
|
@ -12,6 +12,16 @@ const routes = [
|
|||
path: '/',
|
||||
name: '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: {
|
||||
notification: null,
|
||||
notificationTimeout: null,
|
||||
saving: false,
|
||||
saving: false
|
||||
},
|
||||
|
||||
|
||||
connection: {
|
||||
hostname: null,
|
||||
accesspoint: true,
|
||||
station: false,
|
||||
ssid: null,
|
||||
password: null,
|
||||
dhcp: true,
|
||||
ip: null,
|
||||
subnetmask: null,
|
||||
gateway: null
|
||||
mutations: {
|
||||
saving(state, value)
|
||||
{
|
||||
state.saving = value;
|
||||
},
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
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>
|
||||
import axios from 'axios';
|
||||
import LoadingIndicator from '@/components/loadingIndicator.vue';
|
||||
import BaseVM from '@/BaseVM';
|
||||
|
||||
export default {
|
||||
mixins: [BaseVM],
|
||||
|
||||
components: {
|
||||
LoadingIndicator
|
||||
},
|
||||
|
@ -51,22 +54,34 @@ export default {
|
|||
self.disableSetStatic = false;
|
||||
self.setStaticTimer = false;
|
||||
|
||||
// TODO load current settings (no API for it yet)
|
||||
self.static = {
|
||||
r: 0,
|
||||
g: 0,
|
||||
b: 0,
|
||||
w: 0
|
||||
};
|
||||
|
||||
self.$watch('static', () =>
|
||||
{
|
||||
self.staticChanged();
|
||||
}, { deep: true });
|
||||
self.load()
|
||||
.then(() =>
|
||||
{
|
||||
self.$watch('static', () =>
|
||||
{
|
||||
self.staticChanged();
|
||||
}, { deep: true });
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
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()
|
||||
{
|
||||
this.static = {
|
||||
|
@ -80,7 +95,7 @@ export default {
|
|||
|
||||
staticChanged()
|
||||
{
|
||||
var self = this;
|
||||
const self = this;
|
||||
console.log(self.setStaticTimer);
|
||||
|
||||
if (self.setStaticTimer === false)
|
||||
|
@ -93,7 +108,7 @@ export default {
|
|||
|
||||
setStatic()
|
||||
{
|
||||
var self = this;
|
||||
const self = this;
|
||||
|
||||
if (self.settingStatic)
|
||||
{
|
||||
|
@ -118,12 +133,6 @@ export default {
|
|||
{
|
||||
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,
|
||||
proxy:{
|
||||
'/api': {
|
||||
target: 'http://localhost:3000'
|
||||
target: 'http://127.0.0.1:3000'
|
||||
}
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue