Add CSV export & scientific graph

This commit is contained in:
Darko Lukic 2018-03-24 11:04:03 +01:00
parent 3bbd7430be
commit 272f2cfc1a
8 changed files with 128 additions and 25 deletions

20
ui/package-lock.json generated
View file

@ -5436,11 +5436,6 @@
"is-object": "1.0.1" "is-object": "1.0.1"
} }
}, },
"jquery": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.3.1.tgz",
"integrity": "sha512-Ubldcmxp5np52/ENotGxlLe6aGMvmF4R8S6tZjsP6Knsaxd/xp3Zrh50cG93lR6nPXyUFwzN3ZSOQI0wRJNdGg=="
},
"js-base64": { "js-base64": {
"version": "2.4.3", "version": "2.4.3",
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz",
@ -6030,6 +6025,11 @@
"yallist": "2.1.2" "yallist": "2.1.2"
} }
}, },
"luxon": {
"version": "0.5.8",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-0.5.8.tgz",
"integrity": "sha512-TQImsQkWWXqiF43cWbcLN6CxaTzsJJD+8lvgrG8bs0Hc5YBLn+2dAmqUt+BKp2n5+mK0ABJ07Ss7V28H2sYF+w=="
},
"macaddress": { "macaddress": {
"version": "0.2.8", "version": "0.2.8",
"resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz", "resolved": "https://registry.npmjs.org/macaddress/-/macaddress-0.2.8.tgz",
@ -10932,6 +10932,11 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-2.5.16.tgz", "resolved": "https://registry.npmjs.org/vue/-/vue-2.5.16.tgz",
"integrity": "sha512-/ffmsiVuPC8PsWcFkZngdpas19ABm5mh2wA7iDqcltyCTwlgZjHGeJYOXkBMo422iPwIcviOtrTCUpSfXmToLQ==" "integrity": "sha512-/ffmsiVuPC8PsWcFkZngdpas19ABm5mh2wA7iDqcltyCTwlgZjHGeJYOXkBMo422iPwIcviOtrTCUpSfXmToLQ=="
}, },
"vue-datetime": {
"version": "1.0.0-beta.3",
"resolved": "https://registry.npmjs.org/vue-datetime/-/vue-datetime-1.0.0-beta.3.tgz",
"integrity": "sha1-JlIuZYmynFMncmQ1t3DivcH4W4Y="
},
"vue-hot-reload-api": { "vue-hot-reload-api": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz", "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.0.tgz",
@ -11443,6 +11448,11 @@
"integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==", "integrity": "sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg==",
"dev": true "dev": true
}, },
"weekstart": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/weekstart/-/weekstart-1.0.0.tgz",
"integrity": "sha1-4K7jWNRa2ZgCJUdp17KjTJOA9Tk="
},
"whet.extend": { "whet.extend": {
"version": "0.9.9", "version": "0.9.9",
"resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz", "resolved": "https://registry.npmjs.org/whet.extend/-/whet.extend-0.9.9.tgz",

View file

@ -21,12 +21,14 @@
"bootstrap": "^4.0.0", "bootstrap": "^4.0.0",
"chart.js": "^2.7.2", "chart.js": "^2.7.2",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"jquery": "^3.3.1", "luxon": "^0.5.8",
"moment": "^2.21.0", "moment": "^2.21.0",
"vue": "^2.5.16", "vue": "^2.5.16",
"vue-datetime": "^1.0.0-beta.3",
"vue-resource": "^1.5.0", "vue-resource": "^1.5.0",
"vue-router": "^3.0.1", "vue-router": "^3.0.1",
"vuex": "^3.0.1" "vuex": "^3.0.1",
"weekstart": "^1.0.0"
}, },
"devDependencies": { "devDependencies": {
"babel-loader": "^7.1.4", "babel-loader": "^7.1.4",

View file

@ -19,6 +19,12 @@
<span class="hideable">Dashboard</span> <span class="hideable">Dashboard</span>
</router-link> </router-link>
</li> </li>
<li>
<router-link to="/science">
<i class="fa fa-flask"></i>
<span class="hideable">Science</span>
</router-link>
</li>
<li> <li>
<router-link to="/settings"> <router-link to="/settings">
<i class="fa fa-gears"></i> <i class="fa fa-gears"></i>

View file

@ -112,4 +112,11 @@ hr {
#sidebar .hideable { #sidebar .hideable {
display: none; display: none;
} }
} }
.box {
border: 1px solid #ddd;
background-color: #f5f5f5;
padding: 20px;
border-radius: 5px;
}

View file

@ -62,12 +62,3 @@ export default {
}, },
} }
</script> </script>
<style>
.box {
border: 1px solid #ddd;
background-color: #f5f5f5;
padding: 20px;
border-radius: 5px;
}
</style>

View file

@ -0,0 +1,83 @@
<template>
<div class="row">
<div class="col-md-8 offset-md-2 col-sm-12 box">
<h3>Export Data</h3>
<hr />
<div class="row">
<div class="form-group col">
<label for="fromDate">From date:</label>
<datetime @input="rangeUpdated" v-model="from" id="fromDate" type="datetime" input-class="form-control"></datetime>
</div>
<div class="form-group col">
<label for="toDate">To date:</label>
<datetime @input="rangeUpdated" v-model="to" id="toDate" type="datetime" input-class="form-control"></datetime>
</div>
</div>
<div class="row">
<img ref="graph" style="width: 100%; height: 100%" />
</div>
<div class="row">
<div class="col">
<a href="#" target="_blank" ref="csvButton" class="btn btn-primary btn-block">Download CSV</a>
</div>
</div>
</div>
</div>
</template>
<script>
import { Datetime } from 'vue-datetime'
import moment from 'moment';
const FROM_DEFAULT = moment().add('-24', 'hours').toISOString();
const TO_DEFAULT = moment().toISOString();
export default {
name: 'Science',
data() {
return {
from: FROM_DEFAULT,
to: TO_DEFAULT,
lastFrom: FROM_DEFAULT,
lastTo: TO_DEFAULT,
}
},
components: {
Datetime: Datetime
},
mounted() {
this.loadGraphImage();
this.updateDownloadUrl();
},
methods: {
rangeUpdated() {
if (this.lastFrom != this.from || this.lastTo != this.to) {
this.lastFrom = this.from;
this.lastTo = this.to;
this.loadGraphImage();
this.updateDownloadUrl();
}
},
updateDownloadUrl() {
let from = moment(this.from).unix();
let to = moment(this.to).unix();
let root = this.$http.options.root;
let url = `${root}series?format=csv&from=${from}&to=${to}`;
this.$refs.csvButton.href = url;
},
loadGraphImage() {
let from = moment(this.from).unix();
let to = moment(this.to).unix();
let root = this.$http.options.root;
let binSize = 1;
let imageUrl = `${root}histogram.png?from=${from}&to=${to}&bin_size=${binSize}`;
this.$refs.graph.src = imageUrl;
},
},
}
</script>

View file

@ -1,22 +1,19 @@
import Vue from 'vue' import Vue from 'vue'
import VueResource from 'vue-resource'; import VueResource from 'vue-resource';
import { Settings } from 'luxon'
import router from './router.js' import router from './router.js'
import store from './store.js'; import store from './store.js';
import App from './App.vue' import App from './App.vue'
import './assets/css/main.css' import './assets/css/main.css'
import '../node_modules/bootstrap/dist/css/bootstrap.css' import 'bootstrap/dist/css/bootstrap.css'
import '../node_modules/font-awesome/css/font-awesome.css' import 'font-awesome/css/font-awesome.css'
import 'vue-datetime/dist/vue-datetime.css'
/*
import $ from 'jquery';
window.jQuery = $;
window.$ = $;
*/
Vue.use(VueResource); Vue.use(VueResource);
Vue.http.options.root = 'http://192.168.1.26:5000/api/'; Vue.http.options.root = 'http://192.168.1.26:5000/api/';
Settings.defaultLocale = 'en'
Vue.prototype.$bus = new Vue();
new Vue({ new Vue({
el: '#app', el: '#app',

View file

@ -3,6 +3,7 @@ import Router from 'vue-router'
import Dashboard from './components/dashboard/Dashboard.vue' import Dashboard from './components/dashboard/Dashboard.vue'
import About from './components/About.vue' import About from './components/About.vue'
import Settings from './components/settings/Settings.vue' import Settings from './components/settings/Settings.vue'
import Science from './components/Science.vue'
Vue.use(Router) Vue.use(Router)
@ -27,5 +28,11 @@ export default new Router({
main: Settings main: Settings
} }
}, },
{
path: '/science',
components: {
main: Science
}
},
] ]
}) })