added state to home page and to recorder page

This commit is contained in:
Tobias Kurze
2020-07-21 15:37:26 +02:00
parent 6a7ee244a2
commit d3df9d5a30
15 changed files with 286 additions and 79 deletions

View File

@@ -1,5 +1,8 @@
<template>
<div id="app">
<div id="bg">
<img src="./assets/lens.jpg" alt="">
</div>
<sync-loader :loading="isLoading"></sync-loader>
<b-alert
:show="dismissCountDown"
@@ -75,7 +78,9 @@
</span>
<span v-else>{{$t('Can\'t renew session please login again!')}}</span>
</div>
<router-view/>
<div id="content_frame">
<router-view :style="main_style"/>
</div>
</div>
</template>
@@ -100,6 +105,7 @@
dismissSecs: 5,
dismissCountDown: 0,
autoRenewSession: true,
main_style: {}
};
},
methods: {
@@ -181,7 +187,30 @@
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
color: #385875;
}
#bg {
z-index: -100;
position: fixed;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
}
#bg img {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
min-width: 50%;
min-height: 50%;
}
h1 {
color: #275d37;
}
#nav {
@@ -223,4 +252,5 @@
height: 100%;
background-color: rgba(0, 0, 0, 0.2);
}
</style>

View File

@@ -0,0 +1,17 @@
// groupRepository.ts
// @ts-ignore
import Repository from './Repository';
const recorderStateResource = '/state/recorder';
export default {
getRecordersStates() {
return Repository.get(`${recorderStateResource}`);
},
getRecorderState(recorderId: number) {
return Repository.get(`${recorderStateResource}/${recorderId}`);
},
};

View File

@@ -0,0 +1,32 @@
// groupRepository.ts
// @ts-ignore
import Repository from './Repository';
const virtualCommandResource = '/virtual_command';
import {dictEmptyValToNull} from '@/utils';
export default {
getVirtualCommands() {
return Repository.get(`${virtualCommandResource}`);
},
getVirtualCommand(virtualCommandId: number) {
return Repository.get(`${virtualCommandResource}/${virtualCommandId}`);
},
deleteVirtualCommand(virtualCommandId: number) {
return Repository.delete(`${virtualCommandResource}/${virtualCommandId}`);
},
createVirtualCommand(virtualCommandData: any) {
return Repository.post(`${virtualCommandResource}`, dictEmptyValToNull(virtualCommandData));
},
updateVirtualCommand(virtualCommandId: number, virtualCommandData: any) {
return Repository.put(`${virtualCommandResource}/${virtualCommandId}`,
dictEmptyValToNull(virtualCommandData));
},
};

BIN
src/assets/background.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 492 KiB

BIN
src/assets/hexagon.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

BIN
src/assets/lens.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 554 KiB

View File

@@ -180,11 +180,11 @@
<hr>
<!--
<div class="column">
<section class="section" id="results">
<div class="box">
<ul>
<!-- loop through all the `form` properties and show their values -->
<li v-for="(item, k) in form">
<strong>{{ k }}:</strong> {{ item }}
</li>
@@ -198,6 +198,7 @@
{{recorders}}
</section>
</div>
-->
</div>
</template>

View File

@@ -1,6 +1,27 @@
<template>
<div v-if="authenticated">
<p>List of recorders in error state... ;)</p>
<div v-if="authenticated && faulty_recorders_states.length > 0">
<h2>Recorders with detected problems:</h2>
<b-card-group deck>
<b-card bg-variant="danger" text-variant="white" v-for="r_s in faulty_recorders_states" class="mb-2" style="max-width: 30rem; min-width:20rem;"
:header="r_s.name"
v-bind:key="r_s.id">
<b-card-text>
<h5 class="card-title">
<strong>{{$t('Problem')}}:</strong>&nbsp;{{r_s.msg}}
</h5>
<b-button :to="{name: 'recorder', params: {recorder_id: r_s.id}}" variant="primary">Go to recorder
</b-button>
</b-card-text>
<div slot="footer">
<small>
<p>
<span v-if="r_s.time_stamp"><strong>{{$t('time stamp')}}:</strong>&nbsp;{{r_s.time_stamp}}</span>
</p>
</small>
</div>
</b-card>
</b-card-group>
<hr/>
</div>
<div v-else>
<p>You must be signed in in order to see recorders!</p>
@@ -9,17 +30,24 @@
<script lang="ts">
import {Component, Prop, Vue} from 'vue-property-decorator';
import StateRepository from '@/api/stateRepository';
import VirtualCommandRepository from "@/api/virtualCommandRepository";
@Component
export default class ErroneousRecorders extends Vue {
@Prop() private msg!: string;
get authenticated() {
return this.$store.getters.isAuthenticated;
}
get recorders() {
return this.$store.state.recorders;
get faulty_recorders_states() {
return this.$store.state.recorderStates.filter((s: any) => {
return !s.state_ok
});
}
private mounted() {
this.$store.dispatch('loadRecorderStates');
}
}
</script>
@@ -40,7 +68,4 @@
margin: 0 10px;
}
a {
color: #42b983;
}
</style>

View File

@@ -8,7 +8,8 @@
<div class="text-center">
<font-awesome-icon class="float-left" icon="arrow-circle-left" @click="previousRecorder()"/>
<input type="number" style="font-size: small; max-width: 48px; text-align: center;"
v-model="new_recorder_id" @blur="manually_set_recorder_id()" @input="manually_set_recorder_id()">
v-model="new_recorder_id" @blur="manually_set_recorder_id()"
@input="manually_set_recorder_id()">
<font-awesome-icon class="float-right" icon="arrow-circle-right" @click="nextRecorder()"/>
</div>
</h3>
@@ -18,7 +19,8 @@
<b-img left style="margin-right: 20px;" src="https://picsum.photos/164/164/?image=58"
alt="Left image"></b-img>
<h2 class="title">
<font-awesome-icon v-if="recorder.locked" style="color: red;" icon="lock" @dblclick="unlock()"/>
<font-awesome-icon v-if="recorder.locked" style="color: red;" icon="lock"
@dblclick="unlock()"/>
<font-awesome-icon v-else icon="lock-open" style="color: green;" @click="lock()"/>
&nbsp;{{recorder.name}}
</h2>
@@ -45,15 +47,30 @@
<strong>{{$t('created_at')}}:&nbsp</strong>{{recorder.created_at}}<br/>
<strong>{{$t('last_time_modified')}}:&nbsp</strong>{{recorder.last_time_modified}}<br/>
<strong>State:&nbsp;</strong>
<span v-if="state">
<font-awesome-icon v-if="state.state_ok" style="color: green;" icon="thumbs-up"/>
<font-awesome-icon v-else icon="thumbs-down" style="color: red;"/>
&nbsp;{{state.msg}} <small>(Last update: {{state.time_stamp}})</small>
</span>
<span v-else>{{$t('State is unknown')}}!</span>
<br/>
<hr/>
<h3 style="color: orangered;" v-if="recorder.offline"><font-awesome-icon icon="wrench"/>&nbsp;
{{recorder.offline ? 'The recorder is in offline / maintenance mode' : ''}}</h3>
<h3 style="color: orangered;" v-if="recorder.offline">
<font-awesome-icon icon="wrench"/>&nbsp;
{{recorder.offline ? 'The recorder is in offline / maintenance mode' : ''}}
</h3>
<hr v-if="recorder.offline"/>
<h3 style="color: red;" v-if="recorder.lock_message"><font-awesome-icon icon="lock"/>&nbsp;
{{recorder.lock_message}}</h3>
<h3 style="color: red;" v-if="recorder.lock_message">
<font-awesome-icon icon="lock"/>&nbsp;
{{recorder.lock_message}}
</h3>
<hr v-if="recorder.lock_message"/>
<div role="tablist">
<b-card no-body class="mb-1">
<b-card-header header-tag="header" class="p-1" role="tab">
@@ -84,15 +101,20 @@
<b-card v-if="recorderModel" no-body class="mb-1">
<b-card-header header-tag="header" class="p-1" role="tab">
<b-button block href="#" v-b-toggle.accordion-2 variant="outline-primary">Model / Recorder Adapter Info</b-button>
<b-button block href="#" v-b-toggle.accordion-2 variant="outline-primary">Model /
Recorder Adapter Info
</b-button>
</b-card-header>
<b-collapse id="accordion-2" accordion="my-accordion" role="tabpanel">
<b-card-body>
<strong>{{$t('name')}}:&nbsp</strong>{{recorderModel.name}}<br/>
<strong>{{$t('created_at')}}:&nbsp</strong>{{recorderModel.created_at}}<br/>
<strong>{{$t('last_time_modified')}}:&nbsp</strong>{{recorderModel.last_time_modified ? recorderModel.last_time_modified : 'never'}}<br/>
<strong>{{$t('requires_username')}}:&nbsp</strong>{{recorderModel.requires_username ? 'Yes' : 'No'}}<br/>
<strong>{{$t('requires_password')}}:&nbsp</strong>{{recorderModel.requires_password ? 'Yes' : 'No'}}<br/>
<strong>{{$t('last_time_modified')}}:&nbsp</strong>{{recorderModel.last_time_modified
? recorderModel.last_time_modified : 'never'}}<br/>
<strong>{{$t('requires_username')}}:&nbsp</strong>{{recorderModel.requires_username
? 'Yes' : 'No'}}<br/>
<strong>{{$t('requires_password')}}:&nbsp</strong>{{recorderModel.requires_password
? 'Yes' : 'No'}}<br/>
<span v-if="recorderModel.notes"><strong>{{$t('notes')}}:&nbsp</strong>{{recorderModel.notes}}<br/></span>
</b-card-body>
</b-collapse>
@@ -109,7 +131,8 @@
<b-collapse id="accordion-3" visible accordion="my-accordion" role="tabpanel">
<b-card-body>
{{cmd_params}}
<b-list-group style="max-height: 400px; overflow-y:scroll;" v-if="!(recorder.locked || recorder.offline)">
<b-list-group style="max-height: 400px; overflow-y:scroll;"
v-if="!(recorder.locked || recorder.offline)">
<b-list-group-item v-for="command in recorderModel.commands"
v-bind:key="command.id">
<h5>{{command.name}}</h5>
@@ -117,18 +140,24 @@
<b-col sm="3" v-for="(a_type, arg) in command.parameters"
v-bind:key="arg"
v-if="command.parameters !== null">
<b-form-input @focus="setup_params(command.id, arg)" @blur="set_param(command.id, arg, $event.target.value)"
<b-form-input @focus="setup_params(command.id, arg)"
@blur="set_param(command.id, arg, $event.target.value)"
:placeholder="arg + ' ('+a_type+')'"
:type="a_type==='int'?'number':'text'" style="margin-right: 10px;">
:type="a_type==='int'?'number':'text'"
style="margin-right: 10px;">
<small>{{arg}}:&nbsp;{{a_type}}</small>
</b-form-input>
</b-col>
</b-row>
<button class="float-right" @click="execute_command(command.id)"><font-awesome-icon icon="play"/></button>
<button class="float-right" @click="execute_command(command.id)">
<font-awesome-icon icon="play"/>
</button>
<p v-if="cmd_res[command.id]">
<font-awesome-icon style="color: green;" v-if="cmd_res[command.id].ok" icon="smile"/>
<font-awesome-icon style="color: green;" v-if="cmd_res[command.id].ok"
icon="smile"/>
<font-awesome-icon style="color: red;" v-else icon="frown"/>
&nbsp;<span>{{cmd_res[command.id].time | moment("HH:mm:ss")}}</span> &nbsp;-&nbsp;Output:
&nbsp;<span>{{cmd_res[command.id].time | moment("HH:mm:ss")}}</span>
&nbsp;-&nbsp;Output:
<strong>
<span v-if="cmd_res[command.id].ok">{{cmd_res[command.id].output}}</span>
<span v-else>{{cmd_res[command.id].error}}</span>
@@ -191,8 +220,9 @@
this.recorder.locked = false;
},
calculate_current_recorder_index() {
this.current_recorder_index = this.recorderIds.findIndex( (id) =>
{ return id === this.current_recorder_id});
this.current_recorder_index = this.recorderIds.findIndex((id) => {
return id === this.current_recorder_id
});
},
previousRecorder() {
if (null == this.current_recorder_index) {
@@ -227,6 +257,7 @@
mounted() {
this.$store.dispatch('loadRecorders');
this.$store.dispatch('loadRecorderModels');
this.$store.dispatch('loadRecorderState', this.current_recorder_id);
},
beforeDestroy() {
EventBus.$off('failedLoadingProfile');
@@ -268,6 +299,11 @@
access_token() {
return this.$store.state.access_token;
},
state() {
return this.$store.state.recorderStates.filter((s) => {
return parseInt(s.id) === this.current_recorder_id
}).pop();
}
},
};
</script>
@@ -277,6 +313,7 @@
color: red;
font-weight: bold;
}
.lang-btn {
padding: 15px;
border: 2px solid green;

View File

@@ -614,11 +614,12 @@
</b-form-group>
<hr>
<!--
<div class="column">
<section class="section" id="results">
<div class="box">
<ul>
<!-- loop through all the `form` properties and show their values -->
<li v-for="(item, k) in form">
<strong>{{ k }}:</strong> {{ item }}
</li>
@@ -627,11 +628,13 @@
</section>
</div>
<div class="column">
<section class="section">
{{recorders}}
</section>
</div>
-->
</div>
</template>

View File

@@ -49,7 +49,10 @@ import {
faPlay,
faFrown,
faSmile,
faUserTag, faExternalLinkAlt,
faUserTag,
faExternalLinkAlt,
faThumbsUp,
faThumbsDown,
} from '@fortawesome/free-solid-svg-icons';
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome';
@@ -64,7 +67,7 @@ const isProduction = process.env.NODE_ENV === 'production';
library.add(faCoffee, faTrash, faPencilAlt, faScroll, faCheck, faCircle, faList, faPlus, faDoorOpen, faCogs, faAt,
faUser, faEnvelope, faUserTag, faExternalLinkAlt, faSync, faHome, faCode, faBarcode, faTag, faTags, faVideo, faLock,
faLockOpen, faArrowCircleLeft, faArrowCircleRight, faWrench, faPlay, faFrown, faSmile);
faLockOpen, faArrowCircleLeft, faArrowCircleRight, faWrench, faPlay, faFrown, faSmile, faThumbsUp, faThumbsDown);
Vue.component('font-awesome-icon', FontAwesomeIcon);

View File

@@ -4,6 +4,8 @@ import createPersistedState from 'vuex-persistedstate';
import getRepository from '@/api/RepositoryFactory';
import RoomRepository from '@/api/roomRepository';
import RecordRepository from '@/api/recorderRepository';
import VirtualCommandRepository from '@/api/virtualCommandRepository';
import StateRepository from '@/api/stateRepository';
// imports of AJAX functions will go here
import {
@@ -27,6 +29,8 @@ const state = {
recorders: [],
recorderModels: [],
recorderCommands: [],
recorderStates: [],
virtualCommands: [],
loginProviders: [],
currentSurvey: {},
profile: {},
@@ -68,6 +72,32 @@ const actions = {
EventBus.$emit('failedLoadingRecorders', error);
});
},
loadRecorderStates(context: any) {
return StateRepository.getRecordersStates()
.then((response: any) => {
Vue.$log.debug(response);
Vue.$log.debug(response.data);
context.commit('setRecorderStates', {recorderStates: response.data});
EventBus.$emit('recorderStatesLoaded', response.data);
})
.catch((error: any) => {
Vue.$log.warn('Error loading recorders states!', error);
EventBus.$emit('failedLoadingRecorderStates', error);
});
},
loadRecorderState(context: any, recorder_id: number) {
return StateRepository.getRecorderState(recorder_id)
.then((response: any) => {
Vue.$log.debug(response);
Vue.$log.debug(response.data);
context.commit('setRecorderState', {recorderState: response.data});
EventBus.$emit('recorderStateLoaded', response.data);
})
.catch((error: any) => {
Vue.$log.warn('Error loading recorders states!', error);
EventBus.$emit('failedLoadingRecorderStates', error);
});
},
loadRecorderModels(context: any) {
return RecordRepository.getRecorderModels()
.then((response: any) => {
@@ -96,16 +126,16 @@ const actions = {
});
},
loadVirtualCommands(context: any) {
return RecordRepository.getRecorderCommands()
return VirtualCommandRepository.getVirtualCommands()
.then((response: any) => {
Vue.$log.debug(response);
Vue.$log.debug(response.data);
context.commit('setRecorderCommands', {recorderCommands: response.data});
EventBus.$emit('recorderCommandsLoaded', response.data);
context.commit('setVirtualCommands', {virtualCommands: response.data});
EventBus.$emit('virtualCommandsLoaded', response.data);
})
.catch((error: any) => {
Vue.$log.warn('Error loading recorder commands!', error);
EventBus.$emit('failedLoadingRecorderCommands', error);
Vue.$log.warn('Error loading virtual commands!', error);
EventBus.$emit('failedLoadingVirtualCommands', error);
});
},
loadCommands(context: any) {
@@ -266,6 +296,27 @@ const mutations = {
setRecorderCommands(sState: any, payload: any) {
sState.recorderCommands = payload.recorderCommands;
},
setRecorderStates(sState: any, payload: any) {
sState.recorderStates = payload.recorderStates;
},
setRecorderState(sState: any, payload: any) {
const n_rec_states = sState.recorderStates.length;
const rec_id = payload.recorderState.id;
let found = false;
for (let i = 0; i < n_rec_states; i++) {
if (sState.recorderStates[i].id === rec_id) {
sState.recorderStates[i] = payload.recorderState;
found = true;
break;
}
}
if(!found){
sState.recorderStates.push(payload.recorderState);
}
},
setVirtualCommands(sState: any, payload: any) {
sState.virtualCommands = payload.virtualCommands;
},
setUsers(sState: any, payload: any) {
sState.users = payload.users;
},

View File

@@ -2,20 +2,19 @@
<div class="home">
<div class="container">
<section class="section">
<HelloWorld v-if="!authenticated" msg="you are not authenticated!"/>
<HelloWorld v-if="!authenticated" msg="You are not authenticated!"/>
<div v-else>
<h1>Welcome <span v-if="profile.last_seen!=null">back</span> {{$store.getters.getUserName}}! <span
v-if="profile.last_seen!=null">(Last seen: {{profile.last_seen | moment("dddd, MMMM Do YYYY")}})</span>
<h1>Welcome <span v-if="profile.last_seen!=null">back</span> {{$store.getters.getUserName}}!
</h1>
<h4 v-if="profile.last_seen!=null">Last login: {{profile.last_seen | moment("dddd, MMMM Do YYYY")}}</h4>
<hr/>
<ErroneousRecorders/>
<h2>{{$t('Favorite recorders:')}}</h2>
<p>{{$t('Add favorite recorder:')}}</p>
<SelectRecorder @recorderSelected="addFavoriteRecorderToProfile"/>
<br/>
<div v-if="profile.favorite_recorders.length >0">
<hr/>
<p>{{$t('Favorite recorders:')}}</p>
<b-card-group deck>
<RecorderState v-for="recorder in profile.favorite_recorders" :recorder="recorder" v-bind:key="recorder.id"/>
</b-card-group>
@@ -81,5 +80,14 @@
</script>
<style>
.container {
border-radius: 25px;
padding: 20px;
margin: auto;
width: 80%;
background-color: hsla(0, 0%, 100%, 0.51);
fill: #044b94;
fill-opacity: 0.9;
}
</style>