Initial commit

This commit is contained in:
Tyler
2017-12-03 17:54:36 -05:00
commit 183542178b
31 changed files with 1063 additions and 0 deletions

80
src/App.vue Normal file
View File

@ -0,0 +1,80 @@
<template>
<div id="app" class="container">
<div class="row" style="padding-bottom: 10px;">
<div class="col-sm">
<h1>Ripper</h1>
</div>
</div>
<status :sensors="sensors"></status>
<temperatures :temperatures="sensors.temperatures"></temperatures>
<job v-for="(job, id) in jobs" :job="job" :key="job.id"></job>
</div>
</template>
<script>
import Vue from 'vue'
import job from './components/Job';
import status from './components/Status';
import temperatures from './components/TempStatus';
import EventWebSocket from './websocket';
let d = {
jobs: {},
sensors: {}
};
let ws = new EventWebSocket('ws://192.168.2.85:8080/ws');
ws.on('jobs', function(data) {
// Create jobs components
d.jobs = data;
});
ws.on('job:create', function(job) {
// Create new job component
Vue.set(d.jobs, job.id, job);
});
ws.on('job:update', function(update) {
let job = d.jobs[update.job_id];
for (let k in update) {
if (k !== 'job_id') {
job[k] = update[k];
}
}
});
ws.on('job:progress', function(progress) {
// Update component status bar for progress.job_id
let job = d.jobs[progress.job_id];
if (!job.progress) {
job.progress = progress;
} else {
for (let k in progress) {
if (k !== 'job_id') {
job.progress[k] = progress[k];
}
}
}
});
ws.on('sensors', function(status) {
d.sensors = status;
});
d.ws = ws;
export default {
name: 'app',
components: {
job: job,
status: status,
temperatures: temperatures,
},
data() {
return d;
}
}
</script>

BIN
src/assets/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

20
src/components/Hello.vue Normal file
View File

@ -0,0 +1,20 @@
<template>
<div class="row">
<job v-for="(job, index) in jobs" :job="job" :key="job_id"></job>
</div>
</template>
<script>
import job from '@/components/Job';
export default {
name: 'hello',
components: {
job: job
},
data () {
return {
msg: 'Welcome to Your Vue.js App'
}
}
}
</script>

36
src/components/Job.vue Normal file
View File

@ -0,0 +1,36 @@
<template>
<div class="row">
<div class="col-sm">
<h3>{{ job.title }} - {{ stageValue }}</h3>
<template v-if="job.progress">
<span class="text-center">{{ job.progress.name }} ({{ job.progress.percentage }}%)</span>
<div class="progress">
<div class="progress-bar bg-success" role="progressbar" :style="'width: ' + job.progress.percentage + '%'" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">{{ job.progress.percentage }}%</div>
</div>
<template v-if="job.progress.totalPercentage">
<span class="text-center">Total Progress ({{ job.progress.totalPercentage }}%)</span>
<div class="progress" v-if="job.progress.totalPercentage > 0">
<div class="progress-bar bg-success" role="progressbar" :style="'width: ' + job.progress.totalPercentage + '%'" aria-valuenow="25" aria-valuemin="0" aria-valuemax="100">{{ job.progress.totalPercentage }}%</div>
</div>
</template>
</template>
</div>
</div>
</template>
<script>
export default {
name: 'job',
props: [ 'job' ],
computed: {
stageValue: function() {
if (this.job.stage === 'rip') {
return 'Ripping';
} else if (this.job.stage === 'transcode') {
return 'Transcoding';
}
return 'Unknown: ' + this.job.stage;
}
}
}
</script>

23
src/components/Status.vue Normal file
View File

@ -0,0 +1,23 @@
<template>
<div class="row" v-if="sensors.cpu || sensors.memory || sensors.storage">
<cpu_status :status="sensors.cpu"></cpu_status>
<memory_status :status="sensors.memory"></memory_status>
<disk_status :status="sensors.disk"></disk_status>
</div>
</template>
<script>
import memory_status from './status/MemoryStatus';
import cpu_status from './status/CPUStatus';
import disk_status from './status/DiskStatus';
export default {
name: 'status',
props: [ 'sensors' ],
components: {
cpu_status: cpu_status,
memory_status: memory_status,
disk_status: disk_status
},
}
</script>

View File

@ -0,0 +1,15 @@
<template>
<div style="padding-top: 10px;">
<template v-for="(temp, id) in temperatures">
<span class="badge badge-info">{{ temp.name }}: {{ temp.temperature }}C</span>&nbsp;
</template>
</div>
</template>
<script>
export default {
name: 'temp_status',
props: [ 'temperatures' ],
components: {},
}
</script>

View File

@ -0,0 +1,28 @@
<template>
<div class="col">
<h4>CPU <span :class="'badge badge-' + percentageClass">{{ formattedPercentage }}%</span></h4>
<div class="progress">
<div :class="'progress-bar bg-' + percentageClass" role="progressbar" :style="{ width : status.UserPct + '%' }" :aria-valuenow="status.UserPct" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</template>
<script>
export default {
name: 'cpu_status',
props: [ 'status' ],
computed: {
formattedPercentage: function() {
return parseFloat(this.status.UserPct).toFixed(2);
},
percentageClass: function() {
if (this.status.UserPct >= 90) {
return 'danger';
} else if (this.status.UserPct >= 80) {
return 'warning';
}
return 'success'
},
}
}
</script>

View File

@ -0,0 +1,32 @@
<template>
<div class="col">
<h4>Disk Space <span :class="'badge badge-' + percentageClass"><formatBytes :bytes="status.used"></formatBytes> of <formatBytes :bytes="status.total"></formatBytes></span></h4>
<div class="progress">
<div :class="'progress-bar bg-' + percentageClass" role="progressbar" :style="{ width : usedPercentage + '%' }" :aria-valuenow="usedPercentage" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</template>
<script>
export default {
name: 'disk_status',
props: [ 'status' ],
computed: {
usedPercentage: function() {
if (!this.status) {
return 0;
}
return parseFloat((this.status.used / this.status.total) * 100).toFixed(1).toString();
},
percentageClass: function() {
let usedPercent = (this.status.used / this.status.total) * 100;
if (usedPercent >= 90) {
return 'danger';
} else if (usedPercent >= 75) {
return 'warning';
}
return 'success'
},
}
}
</script>

View File

@ -0,0 +1,39 @@
<template>
<div class="col">
<h4>Memory <span :class="'badge badge-' + percentageClass"><formatBytes :bytes="(status.MemUsed + status.Buffers + status.Cached) * 1024" /> / <formatBytes :bytes="status.MemTotal * 1024" /></span></h4>
<div class="progress">
<div class="progress-bar bg-success" role="progressbar" :style="{ width: memoryPercentage + '%' }" :aria-valuenow="memoryPercentage" aria-valuemin="0" aria-valuemax="100"></div>
<div class="progress-bar bg-warning" role="progressbar" :style="{ width: memoryBufCachePercentage + '%' }" :aria-valuenow="memoryBufCachePercentage" aria-valuemin="0" aria-valuemax="100"></div>
</div>
</div>
</template>
<script>
export default {
name: 'memory_status',
props: [ 'status' ],
computed: {
memoryPercentage: function() {
if (!this.status) {
return 0;
}
return parseFloat((this.status.MemUsed / this.status.MemTotal) * 100).toFixed(1).toString();
},
memoryBufCachePercentage: function() {
if (!this.status) {
return 0;
}
return parseFloat(((this.status.Buffers + this.status.Cached) / this.status.MemTotal) * 100).toFixed(1).toString();
},
percentageClass: function() {
let usedPercent = (this.status.MemUsed / this.status.MemTotal) * 100;
if (usedPercent >= 90) {
return 'danger';
} else if (usedPercent >= 80) {
return 'warning';
}
return 'success'
},
}
}
</script>

33
src/main.js Normal file
View File

@ -0,0 +1,33 @@
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue/dist/bootstrap-vue.css'
import App from './App'
import BootstrapVue from 'bootstrap-vue'
Vue.use(BootstrapVue);
Vue.component('formatBytes', {
render: function (createElement) {
return createElement(
'span', formatBytes(this.bytes)
)
},
props: {
bytes: {
required: false
}
}
});
function formatBytes(a,b){if(0==a)return"0 Bytes";var c=1024,d=b||2,e=["Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"],f=Math.floor(Math.log(a)/Math.log(c));return parseFloat((a/Math.pow(c,f)).toFixed(d))+" "+e[f]}
Vue.config.productionTip = true;
/* eslint-disable no-new */
new Vue({
el: '#app',
render: h => h(App)
});

65
src/websocket/index.js Normal file
View File

@ -0,0 +1,65 @@
import Emitter from 'tiny-emitter'
import inherits from 'util.inherits';
function WS(url) {
Emitter.call(this);
this.url = url;
this.connected = false;
this.connect();
}
WS.prototype = {
connect: function() {
try {
this.ws = new WebSocket(this.url);
} catch (e) {
this.reconnect();
return;
}
this.ws.onopen = this.onopen.bind(this);
this.ws.onclose = this.onclose.bind(this);
this.ws.onmessage = this.onmessage.bind(this);
},
reconnect: function() {
setTimeout(this.connect.bind(this), 5000);
},
close: function() {
this.closed = true;
this.ws.close();
},
onopen: function() {
this.connected = true;
this.emit('connect');
},
onclose: function() {
this.emit('close');
this.connected = false;
if (!this.closed) {
this.reconnect();
}
},
onmessage: function(data) {
try {
let object = JSON.parse(data.data);
this.emit(object.name, object.data);
} catch(e) {
}
}
};
inherits(WS, Emitter);
export default WS;