working websocket communication for recorder states and added recorder.vue

This commit is contained in:
Tobias Kurze
2019-12-11 08:32:08 +01:00
parent 6b7b9f8f09
commit 770942542f
6 changed files with 215 additions and 10 deletions

124
src/components/Recorder.vue Normal file
View File

@@ -0,0 +1,124 @@
<!-- components/Profile.vue -->
<template>
<div>
<section class="hero is-primary">
<div class="hero-body">
<div class="container has-text-centered">
<div class="clearfix">
ID: {{recorder_id}}
<b-img left style="margin-right: 20px;" src="https://picsum.photos/125/125/?image=58"
alt="Left image"></b-img>
<h2 class="title" v-if="recorder.name">{{recorder.name}}</h2>
<h2 class="title" v-else-if="recorder.name">
{{recorder.name}}&nbsp;{{recorder.name}}</h2>
<h2 class="title" v-else>{{recorder.name}}</h2>
<p>
<font-awesome-icon icon="envelope"/>&nbsp;{{recorder.name}}
<a class="badge badge-pill badge-info">
<font-awesome-icon icon="pencil-alt"/></a>
</p>
</div>
<hr/>
<p><strong>{{$t('first_name')}}:&nbsp</strong>{{recorder.name}}</p>
<p><strong>{{$t('last_name')}}:&nbsp</strong>{{recorder.name}}</p>
</div>
</div>
</section>
{{recorder}}
</div>
</template>
<script>
import {EventBus} from '@/utils';
import {getRemainingJwtValiditySeconds} from '../utils';
import getRepository from '@/api/RepositoryFactory';
const userRepository = getRepository('user');
export default {
props: ['recorder_id'],
data() {
return {
email: '',
errorMsg: '',
tokenValidity: -1,
refreshTokenValidity: -1,
formEditField: {},
languages: [
{flag: 'us', language: 'en', title: 'English'},
{flag: 'es', language: 'es', title: 'Español'},
{flag: 'de', language: 'de', title: 'Deutsch'},
],
form: {
first_name: '',
last_name: '',
nickname: '',
email: '',
},
};
},
methods: {
authenticate() {
this.$store.dispatch('login', {email: this.email, password: this.password})
.then(() => this.$router.push('/'));
},
updateProfile(fieldName) {
this.$parent.$data.isLoading = true;
this.$set(this.formEditField, fieldName, false);
const data = {};
data[fieldName] = this.form[fieldName];
this.$log.debug(this.form);
userRepository.updateProfile(data)
.then(() => {
this.$store.dispatch('loadProfile')
.then(() => {
this.$parent.$data.isLoading = false;
});
});
},
changeLocale(locale) {
this.$i18n.locale = locale;
// Vue.$moment.locale(locale);
},
},
mounted() {
console.log('recorder_id: ' + this.id);
this.$store.dispatch('loadRecorders');
this.$store.dispatch('loadRecorderModels');
},
beforeDestroy() {
EventBus.$off('failedLoadingProfile');
},
computed: {
recorder() {
return this.$store.state.recorders;
},
recorderModels() {
return this.$store.state.recorderModels;
},
access_token() {
return this.$store.state.access_token;
},
},
};
</script>
<style lang="scss">
.error-msg {
color: red;
font-weight: bold;
}
.lang-btn {
padding: 15px;
border: 2px solid green;
font-size: 18px;
margin: 15px;
}
</style>

View File

@@ -4,8 +4,24 @@
v-bind:key="recorder.id"> v-bind:key="recorder.id">
<b-card-text> <b-card-text>
<h5 class="card-title"> <h5 class="card-title">
<strong>{{ $t('name') }}:&nbsp;{{recorder.name}}</strong>&nbsp <strong>{{ $t('State') }}:</strong>&nbsp;<span v-if="recState.state_ok" style="color: green;">OK</span>
<span v-else-if="recState.time_stamp!==''" style="color: red;">ERROR</span><span v-else style="color: orange;">Unknown</span>&nbsp;
<a class=" badge badge-pill badge-info" @click="forceUpdate()">
Update <font-awesome-icon icon="sync"/>
</a><br/>
<span v-if="recState.time_stamp"><strong>{{$t('time stamp')}}:</strong>&nbsp;{{recState.time_stamp}}<br/></span>
<strong v-if="!recState.state_ok">{{$t('Problem')}}:&nbsp;{{recState.msg}}</strong>
<span v-else><strong>{{$t('Message')}}:&nbsp;</strong>{{recState.msg}}</span>
<hr/>
<div v-if="recState.previous"><small>
<strong>{{ $t('Previous State') }}:</strong>&nbsp;<span v-if="recState.previous.state_ok">OK</span>
<span v-else-if="recState.previous.time_stamp!==''">ERROR</span><span v-else>Unknown</span>&nbsp;
<br/>
<span v-if="recState.previous.time_stamp"><strong>{{$t('time stamp')}}:</strong>&nbsp;{{recState.previous.time_stamp}}<br/></span>
<strong v-if="!recState.previous.state_ok">{{$t('Problem')}}:&nbsp;{{recState.previous.msg}}</strong>
<span v-else><strong>{{$t('Message')}}:&nbsp;</strong>{{recState.previous.msg}}</span>
</small>
</div>
<!--<router-link :to="{ name: 'recorders'}"> ({{$t('recorders')}}&nbsp <!--<router-link :to="{ name: 'recorders'}"> ({{$t('recorders')}}&nbsp
<font-awesome-icon icon="external-link-alt"/> <font-awesome-icon icon="external-link-alt"/>
) )
@@ -30,18 +46,24 @@
data() { data() {
return { return {
connectedWebsocket: false, connectedWebsocket: false,
recState: {
state_ok: false,
msg: 'unknown (please wait for server update, might take a few minutes)',
time_stamp: '',
previous: false,
},
}; };
}, },
mounted() { mounted() {
this.$socket.client.on('connect', function(msg) { this.$socket.client.on('connect', (msg) => {
this.$log.debug('We are connected!'); this.$log.debug('We are connected!');
this.$log.debug(msg); this.$log.debug(msg);
this.$socket.client.emit('request_recorder_state_' + this.recorder.id, msg); this.$socket.client.emit('request_recorder_state_updates', this.recorder.id);
// this.$socket.client.on('request_recorder_state_' + this.recorder.id, function(msg) { # non arrow function might be necessary! this.$socket.client.emit('', "unnamed msg!?!");
this.$socket.client.on('request_recorder_state_' + this.recorder.id, (msg) => { console.log('recorder_state_update_' + this.recorder.id);
// TODO: refresh state! this.$socket.client.on('recorder_state_update_' + this.recorder.id, (payload) => {
this.$log.debug(msg); this.handleReply(payload);
}); });
}); });
this.$log.info('mounted called'); this.$log.info('mounted called');
@@ -49,8 +71,15 @@
this.$log.info('connecting websocket...'); this.$log.info('connecting websocket...');
this.connectWebsocket(); this.connectWebsocket();
this.connectedWebsocket = true; this.connectedWebsocket = true;
} else {
this.$socket.client.emit('request_recorder_state_updates', this.recorder.id);
this.$socket.client.emit('', "unnamed msg!?!");
console.log('recorder_state_update_' + this.recorder.id);
this.$socket.client.on('recorder_state_update_' + this.recorder.id, (payload) => {
this.handleReply(payload);
});
} }
this.forceUpdate();
}, },
beforeDestroy() { beforeDestroy() {
@@ -61,10 +90,23 @@
}, },
methods: { methods: {
forceUpdate() {
if (this.$socket.connected){
this.$socket.client.emit('force_recorder_state_update', this.recorder.id);
this.$socket.client.emit('', "unnamed msg!?!");
this.$socket.client.on('recorder_state_update_' + this.recorder.id, (payload) => {
this.handleReply(payload);
});
}
},
connectWebsocket() { connectWebsocket() {
this.$socket.client.connect(); this.$socket.client.connect();
}, },
handleReply(state_reply) {
this.recState = JSON.parse(state_reply);
},
disconnectWebsocket() { disconnectWebsocket() {
if (this.$socket.connected) { if (this.$socket.connected) {
this.$socket.client.disconnect(); this.$socket.client.disconnect();

View File

@@ -17,6 +17,13 @@
<font-awesome-icon icon="list"/>&nbsp;<font-awesome-icon icon="circle"/> <font-awesome-icon icon="list"/>&nbsp;<font-awesome-icon icon="circle"/>
<strong>{{$t('Recorders')}}</strong>&nbsp;{{$t('list')}} <strong>{{$t('Recorders')}}</strong>&nbsp;{{$t('list')}}
</template> </template>
<div class="mt-3">
<b-button-group>
<b-button variant="success" @click="filterShowAllRecorders()">{{$t('All recorders')}}</b-button>
<b-button variant="info" @click="filterOnlyShowOfflineRecorders()">{{$t('Offline recorders')}}</b-button>
<b-button variant="warning" @click="filterOnlyShowNonOfflineRecorders()">{{$t('Non offline recorders')}}</b-button>
</b-button-group>
</div>
<p>{{ $tc('recorders_defined', recorders.length, {num: recorders.length})}}:</p> <p>{{ $tc('recorders_defined', recorders.length, {num: recorders.length})}}:</p>
<b-card-group deck> <b-card-group deck>
<b-card class="mb-2" style="max-width: 30rem; min-width:20rem;" <b-card class="mb-2" style="max-width: 30rem; min-width:20rem;"
@@ -639,6 +646,8 @@
props: [], props: [],
data() { data() {
return { return {
onlyShowOfflineRecorders: false,
onlyShowNonOfflineRecorders: false,
tabIndex: 0, tabIndex: 0,
updateValues: {}, updateValues: {},
formEditField: {}, formEditField: {},
@@ -713,6 +722,18 @@
this.$parent.$data.showAlert = true; this.$parent.$data.showAlert = true;
this.$parent.$data.alertMessage = msg; this.$parent.$data.alertMessage = msg;
}, },
filterShowAllRecorders(){
this.onlyShowOfflineRecorders = false;
this.onlyShowNonOfflineRecorders = false;
},
filterOnlyShowOfflineRecorders(){
this.onlyShowOfflineRecorders = true;
this.onlyShowNonOfflineRecorders = false;
},
filterOnlyShowNonOfflineRecorders(){
this.onlyShowOfflineRecorders = false;
this.onlyShowNonOfflineRecorders = true;
},
}, },
mounted() { mounted() {
this.$parent.$data.isLoading = true; this.$parent.$data.isLoading = true;
@@ -731,6 +752,16 @@
return this.$store.state.rooms; return this.$store.state.rooms;
}, },
recorders() { recorders() {
if(this.onlyShowOfflineRecorders){
return this.$store.state.recorders.filter((item) => {
return item.offline;
});
}
else if(this.onlyShowNonOfflineRecorders){
return this.$store.state.recorders.filter((item) => {
return !item.offline;
});
}
return this.$store.state.recorders; return this.$store.state.recorders;
}, },
recorderModels() { recorderModels() {

View File

@@ -34,6 +34,7 @@ import {
faAt, faAt,
faUser, faUser,
faEnvelope, faEnvelope,
faSync,
faUserTag, faExternalLinkAlt, faUserTag, faExternalLinkAlt,
} from '@fortawesome/free-solid-svg-icons'; } from '@fortawesome/free-solid-svg-icons';
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome'; import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome';
@@ -48,7 +49,7 @@ import 'bootstrap-vue/dist/bootstrap-vue.css';
const isProduction = process.env.NODE_ENV === 'production'; const isProduction = process.env.NODE_ENV === 'production';
library.add(faCoffee, faTrash, faPencilAlt, faScroll, faCheck, faCircle, faList, faPlus, faDoorOpen, faCogs, faAt, library.add(faCoffee, faTrash, faPencilAlt, faScroll, faCheck, faCircle, faList, faPlus, faDoorOpen, faCogs, faAt,
faUser, faEnvelope, faUserTag, faExternalLinkAlt); faUser, faEnvelope, faUserTag, faExternalLinkAlt, faSync);
Vue.component('font-awesome-icon', FontAwesomeIcon); Vue.component('font-awesome-icon', FontAwesomeIcon);

View File

@@ -13,6 +13,7 @@ import Group from '@/components/Group.vue';
import Permission from '@/components/Permission.vue'; import Permission from '@/components/Permission.vue';
import Rooms from '@/components/Rooms.vue'; import Rooms from '@/components/Rooms.vue';
import Recorders from '@/components/Recorders.vue'; import Recorders from '@/components/Recorders.vue';
import Recorder from '@/components/Recorder.vue';
import Commands from '@/components/Commands.vue'; import Commands from '@/components/Commands.vue';
import store from '@/store'; import store from '@/store';
@@ -75,6 +76,10 @@ export const router = new Router({
path: '/recorders', path: '/recorders',
name: 'recorders', name: 'recorders',
component: Recorders, component: Recorders,
}, {
path: '/recorder/:recorder_id',
name: 'recorder',
component: Recorder,
}, { }, {
path: '/test', path: '/test',
name: 'test', name: 'test',

View File

@@ -20,6 +20,8 @@
</div> </div>
</section> </section>
</div> </div>
<router-link :to="{name: 'recorder', params: {recorder_id: 1}}">rec 1</router-link>
</div> </div>
</template> </template>