code to call recorder functions from frointend

This commit is contained in:
2019-12-12 18:44:25 +01:00
parent 770942542f
commit bbf30ec6f2
9 changed files with 258 additions and 59 deletions

View File

@@ -99,7 +99,7 @@
langs: ['de', 'en', 'es'],
dismissSecs: 5,
dismissCountDown: 0,
autoRenewSession: false,
autoRenewSession: true,
};
},
methods: {

View File

@@ -8,6 +8,8 @@ import RoomRepository from './roomRepository';
import RecorderRepository from './recorderRepository';
import CommandRepository from './commandRepository';
import ControlRepository from './controlRepository';
export default function get(name: string) {
switch (name) {
@@ -29,6 +31,9 @@ export default function get(name: string) {
case 'command': {
return CommandRepository;
}
case 'control': {
return ControlRepository;
}
default: {
// statements;
break;

View File

@@ -0,0 +1,16 @@
// groupRepository.ts
// @ts-ignore
import Repository from './Repository';
const commandResource = '/control';
import {dictEmptyValToNull} from '@/utils';
export default {
runRecorderCommand(recorderId: any, commandId: any, parameters: any) {
return Repository.post(`${commandResource}?recorder_id=${recorderId}&command_id=${commandId}`,
{parameters: dictEmptyValToNull(parameters)});
},
};

View File

@@ -4,92 +4,217 @@
<section class="hero is-primary">
<div class="hero-body">
<div class="container has-text-centered">
{{cmd_params}}
<h3>
<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()">
<font-awesome-icon class="float-right" icon="arrow-circle-right" @click="nextRecorder()"/>
</div>
</h3>
<div class="clearfix">
ID: {{recorder_id}}
<b-img left style="margin-right: 20px;" src="https://picsum.photos/125/125/?image=58"
<!--Route params: {{$route.params.recorder_id}}-->
<b-img left style="margin-right: 20px;" src="https://picsum.photos/164/164/?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>
<h2 class="title">
<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>
<p>
<font-awesome-icon icon="envelope"/>&nbsp;{{recorder.name}}
<a class="badge badge-pill badge-info">
<font-awesome-icon icon="pencil-alt"/></a>
<font-awesome-icon icon="tag"/>&nbsp;{{recorder.model_name ? recorder.model_name : "undefined"}}<br/>
<font-awesome-icon icon="code"/>&nbsp;{{recorder.firmware_version ? recorder.firmware_version : "undefined"}}<br/>
<font-awesome-icon icon="video"/>&nbsp;{{recorder.additional_camera_connected ? "yes" : "no"}}<br/>
<font-awesome-icon icon="barcode"/>&nbsp;{{recorder.serial_number ? recorder.serial_number : "undefined"}}<br/>
<font-awesome-icon icon="home"/>&nbsp;{{recorder.room ? recorder.room.name : "undefined"}}
</p>
</div>
<strong>{{$t('created_at')}}:&nbsp</strong>{{recorder.created_at}}<br/>
<strong>{{$t('last_time_modified')}}:&nbsp</strong>{{recorder.last_time_modified}}<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>
<hr v-if="recorder.offline" />
<p><strong>{{$t('first_name')}}:&nbsp</strong>{{recorder.name}}</p>
<p><strong>{{$t('last_name')}}:&nbsp</strong>{{recorder.name}}</p>
<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">
<b-button block href="#" v-b-toggle.accordion-1 variant="info">Network</b-button>
</b-card-header>
<b-collapse id="accordion-1" accordion="my-accordion" role="tabpanel">
<b-card-body>
<strong>{{$t('ip')}}:&nbsp</strong>{{recorder.ip}}<br/>
<strong>{{$t('mac')}}:&nbsp</strong>{{recorder.mac}}<br/>
<strong>{{$t('network_name')}}:&nbsp</strong>{{recorder.network_name}}<br/>
<strong>{{$t('ssh_port')}}:&nbsp</strong>{{recorder.ssh_port}}<br/>
<strong>{{$t('telnet_port')}}:&nbsp</strong>{{recorder.telnet_port}}<br/>
</b-card-body>
</b-collapse>
</b-card>
<b-card v-if="recorder.description" 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="info">Description</b-button>
</b-card-header>
<b-collapse id="accordion-2" accordion="my-accordion" role="tabpanel">
<b-card-body>
<b-card-text>{{recorder.description}}</b-card-text>
</b-card-body>
</b-collapse>
</b-card>
<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-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/>
<span v-if="recorderModel.notes"><strong>{{$t('notes')}}:&nbsp</strong>{{recorderModel.notes}}<br/></span>
</b-card-body>
</b-collapse>
</b-card>
<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-3 variant="danger">
<span>Commands</span>
<span v-if="recorder.locked">&nbsp;({{$t('locked')}})</span>
<span v-if="recorder.offline">&nbsp;({{$t('offline')}})</span>
</b-button>
</b-card-header>
<b-collapse id="accordion-3" visible accordion="my-accordion" role="tabpanel">
<b-card-body>
<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>
<b-row>
<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)"
:placeholder="arg + ' ('+a_type+')'"
: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>
<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: red;" v-else icon="frown"/>
&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>
</strong>
</p>
</b-list-group-item>
</b-list-group>
<span v-else>The recorder is either locked or in offline mode commands are disabled!</span>
</b-card-body>
</b-collapse>
</b-card>
</div>
</div>
</div>
</section>
{{recorder}}
</div>
</template>
<script>
import {EventBus} from '@/utils';
import {getRemainingJwtValiditySeconds} from '../utils';
import getRepository from '@/api/RepositoryFactory';
const userRepository = getRepository('user');
const controlRepository = getRepository('control');
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: '',
},
current_recorder_id: this.recorder_id == null ? 1 : parseInt(this.recorder_id),
current_recorder_index: null,
new_recorder_id: this.current_recorder_id,
cmd_params: {},
cmd_res: {}
};
},
methods: {
authenticate() {
this.$store.dispatch('login', {email: this.email, password: this.password})
.then(() => this.$router.push('/'));
setup_params(command_id, argument) {
if (!(command_id in this.cmd_params)) {
this.$set(this.cmd_params, command_id, {});
}
this.$set(this.cmd_params[command_id], argument, null)
},
updateProfile(fieldName) {
set_param(command_id, argument, val){
this.$set(this.cmd_params[command_id], argument, val)
},
manually_set_recorder_id() {
if (this.new_recorder_id == null || this.new_recorder_id === ''){
this.new_recorder_id = this.current_recorder_id;
return;
}
if (this.recorderIds.includes(parseInt(this.new_recorder_id))){
this.current_recorder_id = parseInt(this.new_recorder_id);
}
this.new_recorder_id = this.current_recorder_id;
},
lock() {
this.recorder.locked = true;
},
unlock() {
this.recorder.locked = false;
},
calculate_current_recorder_index() {
this.current_recorder_index = this.recorderIds.findIndex( (id) =>
{ return id === this.current_recorder_id});
},
previousRecorder() {
if (null == this.current_recorder_index) {
this.calculate_current_recorder_index();
}
if (this.current_recorder_index === 0) this.current_recorder_index = this.recorderIds.length - 1;
else this.current_recorder_index = this.current_recorder_index - 1;
this.current_recorder_id = this.recorderIds[this.current_recorder_index];
this.new_recorder_id = this.current_recorder_id;
},
nextRecorder() {
if (null == this.current_recorder_index) {
this.calculate_current_recorder_index();
}
if (this.current_recorder_index === this.recorderIds.length - 1) this.current_recorder_index = 0;
else this.current_recorder_index = this.current_recorder_index + 1;
this.current_recorder_id = this.recorderIds[this.current_recorder_index];
this.new_recorder_id = this.current_recorder_id;
},
execute_command(command_id) {
console.log("recorder: "+ this.current_recorder_id + "; "+ command_id);
console.log(this.cmd_params);
console.log(this.cmd_params[command_id]);
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);
controlRepository.runRecorderCommand(this.current_recorder_id, command_id, this.cmd_params[command_id]).then((out)=>{
this.$parent.$data.isLoading = false;
console.log(out.data);
this.$set(this.cmd_res, command_id, out.data);
});
},
},
mounted() {
console.log('recorder_id: ' + this.id);
this.$store.dispatch('loadRecorders');
this.$store.dispatch('loadRecorderModels');
},
@@ -97,9 +222,36 @@
EventBus.$off('failedLoadingProfile');
},
computed: {
recorder() {
recorders() {
return this.$store.state.recorders;
},
recorderIds() {
let ids = [];
this.recorders.forEach((elem)=>{
ids.push(parseInt(elem.id));
});
return ids;
},
recorder() {
const recorder = this.$store.state.recorders.filter((item) => {
return parseInt(item.id) === this.current_recorder_id;
});
if(recorder.length < 1){
this.$router.replace({name: 'notFound'});
return {};
}
return recorder.shift();
},
recorderModel() {
if(!this.recorder || !this.recorder.recorder_model) return null;
const model = this.recorderModels.filter((item) => {
return parseInt(item.id) === this.recorder.recorder_model.id;
});
if(model.length < 1){
return null;
}
return model.shift();
},
recorderModels() {
return this.$store.state.recorderModels;
},

View File

@@ -29,6 +29,7 @@
</h5>
<p v-if="recorder.offline">{{$t('recorder is in offline mode')}}!</p>
<b-button :to="{name: 'recorder', params: {recorder_id: recorder.id}}" variant="primary">Go to recorder</b-button>
</b-card-text>
<div slot="footer">
<small class="text-muted">

View File

@@ -27,6 +27,8 @@ import {
faPlus,
faScroll,
faCircle,
faArrowCircleLeft,
faArrowCircleRight,
faList,
faTrash,
faPencilAlt,
@@ -34,7 +36,19 @@ import {
faAt,
faUser,
faEnvelope,
faHome,
faSync,
faCode,
faBarcode,
faTag,
faTags,
faVideo,
faLock,
faLockOpen,
faWrench,
faPlay,
faFrown,
faSmile,
faUserTag, faExternalLinkAlt,
} from '@fortawesome/free-solid-svg-icons';
import {FontAwesomeIcon} from '@fortawesome/vue-fontawesome';
@@ -49,7 +63,8 @@ import 'bootstrap-vue/dist/bootstrap-vue.css';
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);
faUser, faEnvelope, faUserTag, faExternalLinkAlt, faSync, faHome, faCode, faBarcode, faTag, faTags, faVideo, faLock,
faLockOpen, faArrowCircleLeft, faArrowCircleRight, faWrench, faPlay, faFrown, faSmile);
Vue.component('font-awesome-icon', FontAwesomeIcon);

View File

@@ -77,8 +77,9 @@ export const router = new Router({
name: 'recorders',
component: Recorders,
}, {
path: '/recorder/:recorder_id',
path: '/recorder/:recorder_id?',
name: 'recorder',
props: true,
component: Recorder,
}, {
path: '/test',

View File

@@ -37,6 +37,7 @@ export function isEmpty(str: string) {
}
export function dictEmptyValToNull(dict: object): object {
if (dict == null) return {};
const newDict: { [key: string]: string | null | object; } = Object.assign({}, dict);
for (const [key, value] of Object.entries(dict)) {
if (typeof value === 'string') {

View File

@@ -1,5 +1,13 @@
<template>
<div>
<p>404 - Not Found -> have you meant... blabla (GT)</p>
</div>
<div>
<p>404 - Not Found -> have you meant... blabla (GT)</p>
</div>
</template>
<script>
export default {
created() {
//window.location.href = "/my-new-404-page.html";
}
};
</script>