You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
661 lines
19 KiB
661 lines
19 KiB
4 years ago
|
<template>
|
||
|
<div>
|
||
|
<div class="row">
|
||
|
<div class="col-12 d-flex justify-content-center text-center">
|
||
|
<h4 class="text-info"> Search </h4>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div class="row">
|
||
|
|
||
|
<div class="col-6">
|
||
|
<div class="input-group input-group-sm sm-6">
|
||
|
<!-- --------------------------------------------------------- -->
|
||
|
<!-- -------- date satrt----------------------------------- -->
|
||
|
<!-- --------------------------------------------------------- -->
|
||
|
<div class="input-group input-group-sm mb-3">
|
||
|
<div class="input-group-prepend">
|
||
|
<button class="btn btn-outline-secondary"
|
||
|
type="button"
|
||
|
>Start date </button>
|
||
|
</div>
|
||
|
<date-picker
|
||
|
type="date"
|
||
|
autocomplete="off"
|
||
|
v-model="search.datestart"
|
||
|
format="YYYY-MM-DD"
|
||
|
lang="en"
|
||
|
>
|
||
|
</date-picker>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div> <!-- col -->
|
||
|
|
||
|
<div class="col-6">
|
||
|
<div class="input-group input-group-sm sm-6">
|
||
|
<!-- --------------------------------------------------------- -->
|
||
|
<!-- -------- date ----------------------------------- -->
|
||
|
<!-- --------------------------------------------------------- -->
|
||
|
<div class="input-group input-group-sm mb-3">
|
||
|
<div class="input-group-prepend">
|
||
|
<button class="btn btn-outline-secondary"
|
||
|
type="button"
|
||
|
>End date </button>
|
||
|
</div>
|
||
|
<date-picker
|
||
|
type="date"
|
||
|
autocomplete="off"
|
||
|
v-model="search.dateend"
|
||
|
format="YYYY-MM-DD"
|
||
|
lang="en"
|
||
|
>
|
||
|
</date-picker>
|
||
|
|
||
|
<div class="input-group-append">
|
||
|
<button
|
||
|
class="btn btn-outline-primary"
|
||
|
round
|
||
|
type="button"
|
||
|
@click="setFilter">
|
||
|
Go</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
</div>
|
||
|
</div> <!-- col -->
|
||
|
|
||
|
</div> <!-- row -->
|
||
|
|
||
|
|
||
|
<div class="row">
|
||
|
<div class="col-6">
|
||
|
|
||
|
<div class="input-group input-group-sm sm-6">
|
||
|
<div class="input-group-prepend">
|
||
|
|
||
|
<div class="form-control custom-control custom-switch custom-control-inline">
|
||
|
<input type="checkbox" class="custom-control-input" id="log_logerror"
|
||
|
v-model="logcheck.error"
|
||
|
>
|
||
|
<label class="custom-control-label" for="log_logerror">Error</label>
|
||
|
</div>
|
||
|
|
||
|
<div class="form-control custom-control custom-switch custom-control-inline">
|
||
|
<input type="checkbox" class="custom-control-input" id="log_output"
|
||
|
v-model="logcheck.output"
|
||
|
data-size="large"
|
||
|
data-toggle="toggle"
|
||
|
>
|
||
|
<label class="custom-control-label" for="log_output">Output</label>
|
||
|
</div>
|
||
|
|
||
|
<div class="form-control custom-control custom-switch custom-control-inline">
|
||
|
<input type="checkbox" class="custom-control-input" id="log_log"
|
||
|
v-model="logcheck.log"
|
||
|
>
|
||
|
<label class="custom-control-label" for="log_log">Log</label>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div> <!-- col -->
|
||
|
|
||
|
<div class="col-5">
|
||
|
<div class="input-group input-group-sm sm-5 justify-content-end ">
|
||
|
<div class="input-group-prepend">
|
||
|
<div class="input-group-append">
|
||
|
<button
|
||
|
class="btn btn-outline-warning"
|
||
|
round
|
||
|
type="button"
|
||
|
@click="Clearlog">
|
||
|
Clear</button>
|
||
|
</div>
|
||
|
|
||
|
<div class="input-group-append">
|
||
|
<button
|
||
|
class="btn btn-outline-primary"
|
||
|
round
|
||
|
type="button"
|
||
|
@click="Hotlog">
|
||
|
Hot_log</button>
|
||
|
</div>
|
||
|
|
||
|
</div>
|
||
|
</div>
|
||
|
</div> <!-- col -->
|
||
|
|
||
|
<div class="col-1">
|
||
|
</div> <!-- col -->
|
||
|
|
||
|
</div> <!-- row -->
|
||
|
|
||
|
|
||
|
<div class="row rowlog overflow-auto">
|
||
|
<div class="col-12"
|
||
|
v-for="item in log_path"
|
||
|
>
|
||
|
|
||
|
<b-row
|
||
|
class="border-bottom"
|
||
|
v-if="logview(item) === true"
|
||
|
>
|
||
|
<b-col cols="2">
|
||
|
<span class="badge badge-danger badge-pill"
|
||
|
style="cursor: pointer"
|
||
|
@click="clearLog()"
|
||
|
>Clear</span>
|
||
|
</b-col>
|
||
|
|
||
|
<b-col cols="8"
|
||
|
style="cursor: pointer"
|
||
|
@click="selectPath(item)"
|
||
|
>
|
||
|
{{ item }}
|
||
|
</b-col>
|
||
|
|
||
|
<b-col cols="2">
|
||
|
<span class="badge badge-secondary badge-pill"
|
||
|
v-if="log_path_lenght[item] == log_path_lenghtstatus[item]"
|
||
|
>{{log_path_lenght[item]}}</span>
|
||
|
|
||
|
<span class="badge badge-primary badge-pill"
|
||
|
v-else
|
||
|
>{{log_path_lenght[item]}}</span>
|
||
|
</b-col>
|
||
|
</b-row>
|
||
|
|
||
|
</div> <!-- col -->
|
||
|
</div> <!-- row -->
|
||
|
|
||
|
|
||
|
|
||
|
</div>
|
||
|
</template>
|
||
|
<script>
|
||
|
import {mapState, mapGetters, mapActions,dispatch} from 'vuex'
|
||
|
import Vue from 'vue'
|
||
|
import store from '@/store/index'
|
||
|
import JSZip from 'jszip';
|
||
|
import DatePicker from 'vue2-datepicker'
|
||
|
import 'vue2-datepicker/index.css';
|
||
|
import { DateTime } from "luxon";
|
||
|
import FileSaver from 'file-saver';
|
||
|
export default {
|
||
|
components: {
|
||
|
DatePicker
|
||
|
},
|
||
|
data () {
|
||
|
return {
|
||
|
log_path:[],
|
||
|
log_path_lenght:[],
|
||
|
log_path_lenghtstatus:[],
|
||
|
loglenghttotal:32,
|
||
|
search: {
|
||
|
datestart: "",
|
||
|
dateend: "",
|
||
|
log: "",
|
||
|
output: "",
|
||
|
error: ""
|
||
|
},
|
||
|
logcheck: {
|
||
|
log: true,
|
||
|
error: true,
|
||
|
output: true
|
||
|
},
|
||
|
selected: [],
|
||
|
showlloedit:true,
|
||
|
issocket:'close',
|
||
|
socketdata:'',
|
||
|
logintoken:'',
|
||
|
code:[],
|
||
|
logdata: []
|
||
|
}
|
||
|
},
|
||
|
methods: {
|
||
|
Hotlog() {
|
||
|
this.Clearlog()
|
||
|
var restapi = "off"
|
||
|
var logrestapi = store.dispatch("pipelineLLO/setRestapi",{
|
||
|
restapi:restapi
|
||
|
})
|
||
|
},
|
||
|
Clearlog() {
|
||
|
var log = store.dispatch("pipelineLLO/RMmongolog")
|
||
|
this.log_path = []
|
||
|
//var mongolog = store.getters['pipelineLLO/getmongolog'];
|
||
|
//console.log("rmmongolog "+JSON.stringify(mongolog))
|
||
|
},
|
||
|
logview(item) {
|
||
|
//console.log('path ' + JSON.stringify(item))
|
||
|
if(this.logcheck.log){
|
||
|
if(item.endsWith('-log')){
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
if(this.logcheck.error){
|
||
|
if(item.endsWith('-error')){
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
if(this.logcheck.output){
|
||
|
if(item.endsWith('-output')){
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
async selectPath(path) {
|
||
|
console.log('path ' + JSON.stringify(path))
|
||
|
var statuslenght = this.log_path_lenght[path]
|
||
|
Vue.set(this.log_path_lenghtstatus, path, statuslenght);
|
||
|
// -------------------------------------
|
||
|
// send to AdhocView to view in code
|
||
|
// -------------------------------------
|
||
|
this.$root.$emit('playground_log_in',path)
|
||
|
},
|
||
|
async clearLog(path) {
|
||
|
console.log('path ' + JSON.stringify(path))
|
||
|
Vue.set(this.log_path_lenght, path, 0);
|
||
|
Vue.set(this.log_path_lenghtstatus, path, 0);
|
||
|
var log = store.dispatch("pipelineLLO/rmlog",{
|
||
|
path:path
|
||
|
})
|
||
|
|
||
|
},
|
||
|
async setFilter() {
|
||
|
console.log(JSON.stringify(this.search))
|
||
|
|
||
|
var ddd8 = JSON.stringify(this.search.datestart)
|
||
|
ddd8 = ddd8.replace(/"/g,''); //"
|
||
|
var datestart = DateTime.fromISO(ddd8, { zone: "Europe/Athens" });
|
||
|
//console.log(datestart.zoneName); //=> 'Europe/Paris'
|
||
|
//console.log(datestart.toString()); //=> 'Europe/Paris'
|
||
|
|
||
|
var ddd18 = JSON.stringify(this.search.dateend)
|
||
|
ddd18 = ddd18.replace(/"/g,''); //"
|
||
|
var dateend = DateTime.fromISO(ddd18, { zone: "Europe/Athens" });
|
||
|
|
||
|
var restapi = "on"
|
||
|
var logrestapi = await store.dispatch("pipelineLLO/setRestapi",{
|
||
|
restapi:restapi
|
||
|
})
|
||
|
var swarmlabname = new URL(location.href).searchParams.get('pipelinename');
|
||
|
var log = await store.dispatch("pipelineLLO/get_log",{
|
||
|
datestart:datestart.toISODate(),
|
||
|
dateend:dateend.toISODate(),
|
||
|
swarmlabname:swarmlabname
|
||
|
})
|
||
|
var mongolog = store.getters['pipelineLLO/getmongolog'];
|
||
|
console.log("paramp "+JSON.stringify(mongolog))
|
||
|
|
||
|
//this.$root.$emit('GREP_on_data',mongolog.data.data)
|
||
|
|
||
|
// list files from data
|
||
|
this.log_path = [...new Set(mongolog.map(item => item.tailed_path))];
|
||
|
var loglenght = ''
|
||
|
for (let item of this.log_path) {
|
||
|
loglenght = mongolog.filter(item1 => item1.tailed_path === item).length;
|
||
|
Vue.set(this.log_path_lenght, item, loglenght);
|
||
|
if(loglenght > this.loglenghttotal){
|
||
|
// -------------------------------------
|
||
|
// Save store
|
||
|
// -------------------------------------
|
||
|
var ltotal1 = store.dispatch("pipelineLLO/taillog",{
|
||
|
path:item
|
||
|
})
|
||
|
}
|
||
|
}
|
||
|
|
||
|
},
|
||
|
async resetFilter() {
|
||
|
console.log(JSON.stringify(this.logdata))
|
||
|
},
|
||
|
async socketopen () {
|
||
|
this.$socket.client.open();
|
||
|
},
|
||
|
async socketauthenticate () {
|
||
|
var tokentmp = store.getters['pipelineLLO/gettoken'];
|
||
|
this.$socket.client.emit('authenticate', tokentmp);
|
||
|
},
|
||
|
async socketreconnect () {
|
||
|
var log = await this.socketopen()
|
||
|
this.socketauthenticate()
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* == socketclose()
|
||
|
*
|
||
|
* [source,javascript]
|
||
|
* ----
|
||
|
* this.$socket.client.close();
|
||
|
* ----
|
||
|
*
|
||
|
*/
|
||
|
async socketclose () {
|
||
|
this.$socket.client.close();
|
||
|
}
|
||
|
|
||
|
},
|
||
|
computed: {
|
||
|
},
|
||
|
beforeMount () {
|
||
|
this.socketauthenticate()
|
||
|
console.log('send')
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* == Socket subscribe
|
||
|
*
|
||
|
* [source,javascript]
|
||
|
* ----
|
||
|
* ...
|
||
|
* })
|
||
|
* sdfsf
|
||
|
den to perni sdfsf
|
||
|
* ----
|
||
|
* <1> EventBus is used for parent/child component communication.
|
||
|
*
|
||
|
*/
|
||
|
mounted() {
|
||
|
// from AdhocView
|
||
|
this.$root.$on('SERVER_socket_connect', (v) => {
|
||
|
this.$nextTick(function () {
|
||
|
this.socketreconnect()
|
||
|
})
|
||
|
})
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* == Destroy EventBus
|
||
|
*
|
||
|
* See
|
||
|
* https://www.digitalocean.com/community/tutorials/vuejs-component-lifecycle[Vue.js Lifecycle Hooks^].
|
||
|
*
|
||
|
* *beforeDestroy*
|
||
|
*
|
||
|
* - beforeDestroy is fired right before teardown. Your component will still be fully present and functional.
|
||
|
*
|
||
|
* [source,javascript]
|
||
|
* ----
|
||
|
* ----
|
||
|
* <1> EventBus is used for parent/child component communication.
|
||
|
*
|
||
|
*/
|
||
|
beforeDestroy () {
|
||
|
this.$root.$off('SERVER_socket_socket')
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* == Open a socket
|
||
|
*
|
||
|
* See
|
||
|
* https://www.digitalocean.com/community/tutorials/vuejs-component-lifecycle[ Vue.js Lifecycle Hooks^]
|
||
|
*
|
||
|
* *Created*
|
||
|
*
|
||
|
* - You are able to access reactive data and events that are active with the created hook. Templates and Virtual DOM have not yet been mounted or rendered:
|
||
|
*
|
||
|
* [source,javascript]
|
||
|
* ----
|
||
|
* this.socketopen()
|
||
|
* ----
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
created () {
|
||
|
this.socketopen()
|
||
|
var logintoken = new URL(location.href).searchParams.get('token');
|
||
|
var log = store.dispatch("pipelineLLO/settoken",{
|
||
|
token:logintoken
|
||
|
})
|
||
|
|
||
|
//var tokentmp =store.getters['pipelineLLO/gettoken'];
|
||
|
//console.log("tokennnn "+tokentmp);
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* == Socket events
|
||
|
*
|
||
|
* [source,javascript]
|
||
|
* ----
|
||
|
* this.$socket.client.emit('authenticate', 'logintoken');
|
||
|
* ----
|
||
|
*
|
||
|
*/
|
||
|
sockets: {
|
||
|
connect() {
|
||
|
this.$socket.client.emit('authenticate', 'logintoken');
|
||
|
|
||
|
this.$socket.client.emit('socket_id_get', 'socketdatasend');
|
||
|
//var username = 'username'
|
||
|
//var roomname = 'roomname'
|
||
|
//this.$socket.client.emit('setUsername',{user:username});
|
||
|
//this.$socket.client.emit('createRoom', {user:username,room:roomname});
|
||
|
//this.$socket.client.emit('joinRooom',{room:roomname});
|
||
|
//var msg = {user:username,room:roomname,msg:'hiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii'}
|
||
|
//this.$socket.client.emit('sendMessage',msg);
|
||
|
console.log('socket connected '+ 'socketdatasend' )
|
||
|
this.issocket = 'open'
|
||
|
// send to AdhocView
|
||
|
this.$root.$emit('SERVER_socket_status','on')
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* === onError
|
||
|
*
|
||
|
*/
|
||
|
error(error) {
|
||
|
console.log("socket error "+JSON.stringify(error))
|
||
|
this.issocket = 'close'
|
||
|
// send to AdhocView
|
||
|
this.$root.$emit('SERVER_socket_status','off')
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* === connect_error
|
||
|
*
|
||
|
*/
|
||
|
connect_error(error) {
|
||
|
console.log("socket connect_error "+JSON.stringify(error))
|
||
|
this.issocket = 'close'
|
||
|
// send to AdhocView
|
||
|
this.$root.$emit('SERVER_socket_status','off')
|
||
|
this.socketreconnect()
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* === connect_error
|
||
|
*
|
||
|
*/
|
||
|
disconnect(reason) {
|
||
|
console.log("socket disconnect "+JSON.stringify(reason))
|
||
|
this.issocket = 'close'
|
||
|
// send to AdhocView
|
||
|
this.$root.$emit('SERVER_socket_status','off')
|
||
|
this.socketreconnect()
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* === Socket connect_timeout
|
||
|
*
|
||
|
*/
|
||
|
connect_timeout(reason) {
|
||
|
console.log("socket timeout "+JSON.stringify(reason))
|
||
|
this.issocket = 'close'
|
||
|
// send to AdhocView
|
||
|
this.$root.$emit('SERVER_socket_status','off')
|
||
|
this.socketreconnect()
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* === Socket reconnect
|
||
|
*
|
||
|
*/
|
||
|
reconnect(attemptNumber) {
|
||
|
console.log("socket reconnect attemptNumber "+JSON.stringify(attemptNumber))
|
||
|
// send to AdhocView
|
||
|
this.$root.$emit('SERVER_socket_status','off')
|
||
|
this.socketreconnect()
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* === connect_attempt
|
||
|
*
|
||
|
*/
|
||
|
reconnect_attempt(attemptNumber) {
|
||
|
console.log("socket reconnect_attempt "+JSON.stringify(attemptNumber))
|
||
|
// send to AdhocView
|
||
|
this.$root.$emit('SERVER_socket_status','off')
|
||
|
this.socketreconnect()
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* === Socket reconnecting
|
||
|
*
|
||
|
*/
|
||
|
reconnecting(attemptNumber) {
|
||
|
console.log("socket reconnecting "+JSON.stringify(attemptNumber))
|
||
|
this.$root.$emit('SERVER_socket_status','off')
|
||
|
this.socketreconnect()
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* === reconnect_error
|
||
|
*
|
||
|
*/
|
||
|
reconnect_error(error) {
|
||
|
console.log("socket reconnect_error "+JSON.stringify(error))
|
||
|
this.issocket = 'close'
|
||
|
// send to AdhocView
|
||
|
this.$root.$emit('SERVER_socket_status','off')
|
||
|
this.socketreconnect()
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* === unauthorized
|
||
|
*
|
||
|
*/
|
||
|
unauthorized(val) {
|
||
|
console.log("socket unauthorized "+JSON.stringify(val))
|
||
|
this.issocket = 'close'
|
||
|
// send to AdhocView
|
||
|
this.$root.$emit('SERVER_socket_status','off')
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* === connected
|
||
|
*
|
||
|
*/
|
||
|
socket_id_emit(val) {
|
||
|
console.log("socket id from server "+JSON.stringify(val))
|
||
|
console.log("socket id from serveri saved "+JSON.stringify(socketsave))
|
||
|
this.issocket = 'open'
|
||
|
},
|
||
|
/**
|
||
|
*
|
||
|
* === Socket onMessage
|
||
|
*
|
||
|
*/
|
||
|
/*
|
||
|
async adhocEmit(val) {
|
||
|
console.log("socket from server "+JSON.stringify(val))
|
||
|
this.issocket = 'open'
|
||
|
this.$wait.start('myRunInstance1');
|
||
|
// render begin
|
||
|
this.tryLLO = 'on'
|
||
|
if(this.firstbootstrap === 0 ){
|
||
|
await this.bootsrapllo();
|
||
|
this.firstbootstrap = 1
|
||
|
}
|
||
|
var output = log.data.out
|
||
|
var mydinfunction = `
|
||
|
<div class="row">
|
||
|
<b-col class="" cols="12" sm="12" md="12" >
|
||
|
${output}
|
||
|
</b-col>
|
||
|
</div>`
|
||
|
|
||
|
try {
|
||
|
let divascii = document.createElement('div');
|
||
|
divascii.setAttribute("class", "container-fluid w-100 p-3 llotry")
|
||
|
divascii.innerHTML = mydinfunction
|
||
|
this.addtask(divascii);
|
||
|
}catch (ex) {
|
||
|
console.log(" logi error1 "+JSON.stringify(ex))
|
||
|
return
|
||
|
}
|
||
|
this.$wait.end('myRunInstance1');
|
||
|
},
|
||
|
*/
|
||
|
async logdata(val) {
|
||
|
console.log(" socket from logdata "+JSON.stringify(val))
|
||
|
// -------------------------------------
|
||
|
// Save store
|
||
|
// -------------------------------------
|
||
|
var log = store.dispatch("pipelineLLO/addlog",{
|
||
|
log:val
|
||
|
})
|
||
|
// -------------------------------------
|
||
|
// send to grep rungrep to view
|
||
|
// -------------------------------------
|
||
|
this.$root.$emit('GREP_on_data',val)
|
||
|
// -------------------------------------
|
||
|
// send to AdhocView to view in code
|
||
|
// -------------------------------------
|
||
|
// this.$root.$emit('playground_log_in',val.value)
|
||
|
// -------------------------------------
|
||
|
// send to AdhocView for socket status
|
||
|
// -------------------------------------
|
||
|
this.$root.$emit('SERVER_socket_status','on')
|
||
|
|
||
|
var ltmp = store.getters['pipelineLLO/getlog'];
|
||
|
//console.log('logtmpltmp '+ JSON.stringify(ltmp))
|
||
|
this.log_path = [...new Set(ltmp.map(item => item.tailed_path))];
|
||
|
var loglenght = ''
|
||
|
for (let item of this.log_path) {
|
||
|
//console.log('l1find '+ JSON.stringify(item))
|
||
|
loglenght = ltmp.filter(item1 => item1.tailed_path === item).length;
|
||
|
Vue.set(this.log_path_lenght, item, loglenght);
|
||
|
if(loglenght > this.loglenghttotal){
|
||
|
// -------------------------------------
|
||
|
// Save store
|
||
|
// -------------------------------------
|
||
|
var ltotal1 = store.dispatch("pipelineLLO/taillog",{
|
||
|
path:item
|
||
|
})
|
||
|
}
|
||
|
/*
|
||
|
this.log_path_lenght[item] = ltmp.filter(function(item1){
|
||
|
if (item1.tailed_path === item) {
|
||
|
return true;
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
}).length;/
|
||
|
*/
|
||
|
//console.log('l2 '+ this.log_path_lenght[item] )
|
||
|
}
|
||
|
//console.log('l1 '+ JSON.stringify(this.log_path))
|
||
|
|
||
|
},
|
||
|
async message(val) {
|
||
|
console.log(" socket message "+JSON.stringify(val))
|
||
|
}
|
||
|
}
|
||
|
|
||
|
};
|
||
|
</script>
|
||
|
|
||
|
<style>
|
||
|
.CodeMirror {
|
||
|
|
||
|
|
||
|
font-family: monospace;
|
||
|
height: 750px;
|
||
|
}
|
||
|
.rowlog {
|
||
|
display: flex; /* equal height of the children */
|
||
|
height: 470px;
|
||
|
}
|
||
|
|
||
|
</style>
|