1<template> 2 <div :class="isFullWindow ? 'full-window-container' : 'terminal-container'"> 3 <b-row class="d-flex"> 4 <b-col sm="4" md="6"> 5 <alert 6 v-if="connection ? false : true" 7 variant="warning" 8 :small="true" 9 class="mt-4" 10 > 11 <p class="col-form-label"> 12 {{ $t('pageSerialOverLan.alert.disconnectedAlertMessage') }} 13 </p> 14 </alert> 15 </b-col> 16 </b-row> 17 <b-row class="d-flex"> 18 <b-col class="d-flex flex-column justify-content-end"> 19 <dl class="mb-2" sm="6" md="6"> 20 <dt class="d-inline font-weight-bold mr-1"> 21 {{ $t('pageSerialOverLan.status') }}: 22 </dt> 23 <dd class="d-inline"> 24 <status-icon :status="serverStatusIcon" /> 25 {{ 26 connection 27 ? $t('pageSerialOverLan.connected') 28 : $t('pageSerialOverLan.disconnected') 29 }} 30 </dd> 31 </dl> 32 </b-col> 33 34 <b-col v-if="!isFullWindow" class="d-flex justify-content-end"> 35 <b-button variant="link" type="button" @click="openConsoleWindow()"> 36 <icon-launch /> 37 {{ $t('pageSerialOverLan.openNewTab') }} 38 </b-button> 39 </b-col> 40 </b-row> 41 <div id="terminal" ref="panel"></div> 42 </div> 43</template> 44 45<script> 46import Alert from '@/components/Global/Alert'; 47import { AttachAddon } from 'xterm-addon-attach'; 48import { FitAddon } from 'xterm-addon-fit'; 49import { Terminal } from 'xterm'; 50import { throttle } from 'lodash'; 51import IconLaunch from '@carbon/icons-vue/es/launch/20'; 52import StatusIcon from '@/components/Global/StatusIcon'; 53 54export default { 55 name: 'SerialOverLanConsole', 56 components: { 57 Alert, 58 IconLaunch, 59 StatusIcon, 60 }, 61 props: { 62 isFullWindow: { 63 type: Boolean, 64 default: true, 65 }, 66 }, 67 data() { 68 return { 69 resizeConsoleWindow: null, 70 }; 71 }, 72 computed: { 73 serverStatus() { 74 return this.$store.getters['global/serverStatus']; 75 }, 76 connection() { 77 return this.serverStatus === 'off' ? false : true; 78 }, 79 serverStatusIcon() { 80 return this.connection ? 'success' : 'danger'; 81 }, 82 }, 83 created() { 84 this.$store.dispatch('global/getSystemInfo'); 85 }, 86 mounted() { 87 this.openTerminal(); 88 }, 89 beforeDestroy() { 90 window.removeEventListener('resize', this.resizeConsoleWindow); 91 this.closeTerminal(); 92 }, 93 methods: { 94 openTerminal() { 95 const token = this.$store.getters['authentication/token']; 96 this.ws = new WebSocket(`wss://${window.location.host}/console/default`, [ 97 token, 98 ]); 99 100 // Refer https://github.com/xtermjs/xterm.js/ for xterm implementation and addons. 101 102 this.term = new Terminal({ 103 fontSize: 15, 104 fontFamily: 105 'SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace', 106 }); 107 108 const attachAddon = new AttachAddon(this.ws); 109 this.term.loadAddon(attachAddon); 110 111 const fitAddon = new FitAddon(); 112 this.term.loadAddon(fitAddon); 113 114 const SOL_THEME = { 115 background: '#19273c', 116 cursor: 'rgba(83, 146, 255, .5)', 117 scrollbar: 'rgba(83, 146, 255, .5)', 118 }; 119 this.term.setOption('theme', SOL_THEME); 120 121 this.term.open(this.$refs.panel); 122 fitAddon.fit(); 123 124 this.resizeConsoleWindow = throttle(() => { 125 fitAddon.fit(); 126 }, 1000); 127 window.addEventListener('resize', this.resizeConsoleWindow); 128 129 try { 130 this.ws.onopen = function () { 131 console.log('websocket console/default opened'); 132 }; 133 this.ws.onclose = function (event) { 134 console.log( 135 'websocket console/default closed. code: ' + 136 event.code + 137 ' reason: ' + 138 event.reason, 139 ); 140 }; 141 } catch (error) { 142 console.log(error); 143 } 144 }, 145 closeTerminal() { 146 console.log('closeTerminal'); 147 this.term.dispose(); 148 this.term = null; 149 this.ws.close(); 150 this.ws = null; 151 }, 152 openConsoleWindow() { 153 window.open( 154 '#/console/serial-over-lan-console', 155 '_blank', 156 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=yes,width=600,height=550', 157 ); 158 }, 159 }, 160}; 161</script> 162 163<style lang="scss" scoped> 164@import '~xterm/css/xterm.css'; 165 166#terminal { 167 overflow: auto; 168} 169 170.full-window-container { 171 width: 97%; 172 margin: 1.5%; 173} 174</style> 175