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 fw-bold me-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'; 53import { useI18n } from 'vue-i18n'; 54 55export default { 56 name: 'SerialOverLanConsole', 57 components: { 58 Alert, 59 IconLaunch, 60 StatusIcon, 61 }, 62 props: { 63 isFullWindow: { 64 type: Boolean, 65 default: true, 66 }, 67 }, 68 data() { 69 return { 70 $t: useI18n().t, 71 resizeConsoleWindow: null, 72 }; 73 }, 74 computed: { 75 serverStatus() { 76 return this.$store.getters['global/serverStatus']; 77 }, 78 connection() { 79 return this.serverStatus === 'off' ? false : true; 80 }, 81 serverStatusIcon() { 82 return this.connection ? 'success' : 'danger'; 83 }, 84 }, 85 created() { 86 this.$store.dispatch('global/getSystemInfo'); 87 }, 88 mounted() { 89 this.openTerminal(); 90 }, 91 beforeUnmount() { 92 window.removeEventListener('resize', this.resizeConsoleWindow); 93 this.closeTerminal(); 94 }, 95 methods: { 96 openTerminal() { 97 const token = this.$store.getters['authentication/token']; 98 this.ws = new WebSocket(`wss://${window.location.host}/console/default`, [ 99 token, 100 ]); 101 102 // Refer https://github.com/xtermjs/xterm.js/ for xterm implementation and addons. 103 104 this.term = new Terminal({ 105 fontSize: 15, 106 fontFamily: 107 'SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace', 108 scrollback: 10000, 109 }); 110 111 const attachAddon = new AttachAddon(this.ws); 112 this.term.loadAddon(attachAddon); 113 114 const fitAddon = new FitAddon(); 115 this.term.loadAddon(fitAddon); 116 117 const SOL_THEME = { 118 background: '#19273c', 119 cursor: 'rgba(83, 146, 255, .5)', 120 scrollbar: 'rgba(83, 146, 255, .5)', 121 }; 122 this.term.setOption('theme', SOL_THEME); 123 124 this.term.open(this.$refs.panel); 125 fitAddon.fit(); 126 127 this.resizeConsoleWindow = throttle(() => { 128 fitAddon.fit(); 129 }, 1000); 130 window.addEventListener('resize', this.resizeConsoleWindow); 131 132 try { 133 this.ws.onopen = function () { 134 console.log('websocket console/default opened'); 135 }; 136 this.ws.onclose = function (event) { 137 console.log( 138 'websocket console/default closed. code: ' + 139 event.code + 140 ' reason: ' + 141 event.reason, 142 ); 143 }; 144 } catch (error) { 145 console.log(error); 146 } 147 }, 148 closeTerminal() { 149 console.log('closeTerminal'); 150 this.term.dispose(); 151 this.term = null; 152 this.ws.close(); 153 this.ws = null; 154 }, 155 openConsoleWindow() { 156 window.open( 157 '#/console/serial-over-lan-console', 158 '_blank', 159 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=yes,width=600,height=550', 160 ); 161 }, 162 }, 163}; 164</script> 165 166<style lang="scss" scoped> 167@import '~xterm/css/xterm.css'; 168 169#terminal { 170 overflow: auto; 171} 172 173.full-window-container { 174 width: 97%; 175 margin: 1.5%; 176} 177</style> 178