|  | <template> | 
|  | <div :class="marginClass"> | 
|  | <div ref="toolbar" class="kvm-toolbar"> | 
|  | <b-row class="d-flex"> | 
|  | <b-col class="d-flex flex-column justify-content-end" cols="4"> | 
|  | <dl class="mb-2" sm="2" md="2"> | 
|  | <dt class="d-inline font-weight-bold mr-1"> | 
|  | {{ $t('pageKvm.status') }}: | 
|  | </dt> | 
|  | <dd class="d-inline"> | 
|  | <status-icon :status="serverStatusIcon" /> | 
|  | <span class="d-none d-md-inline"> {{ serverStatus }}</span> | 
|  | </dd> | 
|  | </dl> | 
|  | </b-col> | 
|  |  | 
|  | <b-col class="d-flex justify-content-end pr-1"> | 
|  | <b-button | 
|  | v-if="isConnected" | 
|  | variant="link" | 
|  | type="button" | 
|  | @click="sendCtrlAltDel" | 
|  | > | 
|  | <icon-arrow-down /> | 
|  | {{ $t('pageKvm.buttonCtrlAltDelete') }} | 
|  | </b-button> | 
|  | <b-button | 
|  | v-if="!isFullWindow" | 
|  | variant="link" | 
|  | type="button" | 
|  | @click="openConsoleWindow()" | 
|  | > | 
|  | <icon-launch /> | 
|  | {{ $t('pageKvm.openNewTab') }} | 
|  | </b-button> | 
|  | </b-col> | 
|  | </b-row> | 
|  | </div> | 
|  | <div id="terminal-kvm" ref="panel" :class="terminalClass"></div> | 
|  | </div> | 
|  | </template> | 
|  |  | 
|  | <script> | 
|  | import RFB from '@novnc/novnc/core/rfb'; | 
|  | import StatusIcon from '@/components/Global/StatusIcon'; | 
|  | import IconLaunch from '@carbon/icons-vue/es/launch/20'; | 
|  | import IconArrowDown from '@carbon/icons-vue/es/arrow--down/16'; | 
|  | import { throttle } from 'lodash'; | 
|  |  | 
|  | const Connecting = 0; | 
|  | const Connected = 1; | 
|  | const Disconnected = 2; | 
|  |  | 
|  | export default { | 
|  | name: 'KvmConsole', | 
|  | components: { StatusIcon, IconLaunch, IconArrowDown }, | 
|  | props: { | 
|  | isFullWindow: { | 
|  | type: Boolean, | 
|  | default: true, | 
|  | }, | 
|  | }, | 
|  | data() { | 
|  | return { | 
|  | rfb: null, | 
|  | isConnected: false, | 
|  | terminalClass: this.isFullWindow ? 'full-window' : '', | 
|  | marginClass: this.isFullWindow ? 'margin-left-full-window' : '', | 
|  | status: Connecting, | 
|  | convasRef: null, | 
|  | resizeKvmWindow: null, | 
|  | }; | 
|  | }, | 
|  | computed: { | 
|  | serverStatusIcon() { | 
|  | if (this.status === Connected) { | 
|  | return 'success'; | 
|  | } else if (this.status === Disconnected) { | 
|  | return 'danger'; | 
|  | } | 
|  | return 'secondary'; | 
|  | }, | 
|  | serverStatus() { | 
|  | if (this.status === Connected) { | 
|  | return this.$t('pageKvm.connected'); | 
|  | } else if (this.status === Disconnected) { | 
|  | return this.$t('pageKvm.disconnected'); | 
|  | } | 
|  | return this.$t('pageKvm.connecting'); | 
|  | }, | 
|  | }, | 
|  | created() { | 
|  | this.$store.dispatch('global/getSystemInfo'); | 
|  | }, | 
|  | mounted() { | 
|  | this.openTerminal(); | 
|  | }, | 
|  | beforeDestroy() { | 
|  | window.removeEventListener('resize', this.resizeKvmWindow); | 
|  | this.closeTerminal(); | 
|  | }, | 
|  | methods: { | 
|  | sendCtrlAltDel() { | 
|  | this.rfb.sendCtrlAltDel(); | 
|  | }, | 
|  | closeTerminal() { | 
|  | this.rfb.disconnect(); | 
|  | this.rfb = null; | 
|  | }, | 
|  | openTerminal() { | 
|  | const token = this.$store.getters['authentication/token']; | 
|  | this.rfb = new RFB( | 
|  | this.$refs.panel, | 
|  | `wss://${window.location.host}/kvm/0`, | 
|  | { wsProtocols: [token] }, | 
|  | ); | 
|  |  | 
|  | this.rfb.scaleViewport = true; | 
|  | this.rfb.clipViewport = true; | 
|  | const that = this; | 
|  |  | 
|  | this.resizeKvmWindow = throttle(() => { | 
|  | setTimeout(that.setWidthToolbar, 0); | 
|  | }, 1000); | 
|  | window.addEventListener('resize', this.resizeKvmWindow); | 
|  |  | 
|  | this.rfb.addEventListener('connect', () => { | 
|  | that.isConnected = true; | 
|  | that.status = Connected; | 
|  | that.setWidthToolbar(); | 
|  | }); | 
|  |  | 
|  | this.rfb.addEventListener('disconnect', () => { | 
|  | this.isConnected = false; | 
|  | that.status = Disconnected; | 
|  | }); | 
|  | }, | 
|  | setWidthToolbar() { | 
|  | if ( | 
|  | this.$refs.panel.children && | 
|  | this.$refs.panel.children.length > 0 && | 
|  | this.$refs.panel.children[0].children.length > 0 | 
|  | ) { | 
|  | this.$refs.toolbar.style.width = | 
|  | this.$refs.panel.children[0].children[0].clientWidth - 10 + 'px'; | 
|  | } | 
|  | }, | 
|  | openConsoleWindow() { | 
|  | // If consoleWindow is not null | 
|  | // Check the newly opened window is closed or not | 
|  | if (this.$eventBus.$consoleWindow) { | 
|  | // If window is not closed set focus to new window | 
|  | // If window is closed, do open new window | 
|  | if (!this.$eventBus.$consoleWindow.closed) { | 
|  | this.$eventBus.$consoleWindow.focus(); | 
|  | return; | 
|  | } else { | 
|  | this.openNewWindow(); | 
|  | } | 
|  | } else { | 
|  | // If consoleWindow is null, open new window | 
|  | this.openNewWindow(); | 
|  | } | 
|  | }, | 
|  | openNewWindow() { | 
|  | this.$eventBus.$consoleWindow = window.open( | 
|  | '#/console/kvm', | 
|  | 'kvmConsoleWindow', | 
|  | 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=yes,width=700,height=550', | 
|  | ); | 
|  | }, | 
|  | }, | 
|  | }; | 
|  | </script> | 
|  |  | 
|  | <style scoped lang="scss"> | 
|  | .button-ctrl-alt-delete { | 
|  | float: right; | 
|  | } | 
|  |  | 
|  | .kvm-status { | 
|  | padding-top: $spacer / 2; | 
|  | padding-left: $spacer / 4; | 
|  | display: inline-block; | 
|  | } | 
|  |  | 
|  | .margin-left-full-window { | 
|  | margin-left: 5px; | 
|  | } | 
|  | </style> |