blob: 43dc7271101acb685dea30fb1bbc08c490559a95 [file] [log] [blame]
Mateusz Gapski632de222020-07-09 09:21:33 +02001<template>
Mateusz Gapski96b37af2020-09-04 14:11:55 +02002 <div :class="marginClass">
3 <div ref="toolbar" class="kvm-toolbar">
4 <b-row class="d-flex">
5 <b-col class="d-flex flex-column justify-content-end" cols="4">
6 <dl class="mb-2" sm="2" md="2">
7 <dt class="d-inline font-weight-bold mr-1">
8 {{ $t('pageKvm.status') }}:
9 </dt>
10 <dd class="d-inline">
11 <status-icon :status="hostStatusIcon" />
12 <span class="d-none d-md-inline"> {{ hostStatus }}</span>
13 </dd>
14 </dl>
15 </b-col>
16
17 <b-col class="d-flex justify-content-end">
18 <b-button
19 v-if="isConnected"
20 variant="link"
21 type="button"
22 class="pr-0 button-launch"
23 @click="sendCtrlAltDel"
24 >
25 <icon-arrow-down aria-hidden="true" />
26 {{ $t('pageKvm.buttonCtrlAltDelete') }}
27 </b-button>
28 <b-button
29 v-if="!isFullWindow"
30 variant="link"
31 type="button"
32 class="pr-0 button-launch"
33 @click="openConsoleWindow()"
34 >
35 <icon-launch aria-hidden="true" />
36 <span class="d-none d-md-inline">
37 {{ $t('pageKvm.openNewTab') }}
38 </span>
39 </b-button>
40 </b-col>
41 </b-row>
42 </div>
43 <div id="terminal-kvm" ref="panel" :class="terminalClass"></div>
Mateusz Gapski632de222020-07-09 09:21:33 +020044 </div>
45</template>
46
47<script>
48import RFB from '@novnc/novnc/core/rfb';
Mateusz Gapski96b37af2020-09-04 14:11:55 +020049import StatusIcon from '@/components/Global/StatusIcon';
50import IconLaunch from '@carbon/icons-vue/es/launch/20';
51import IconArrowDown from '@carbon/icons-vue/es/arrow--down/16';
52
53const Connecting = 0;
54const Connected = 1;
55const Disconnected = 2;
Mateusz Gapski632de222020-07-09 09:21:33 +020056
57export default {
58 name: 'KvmConsole',
Mateusz Gapski96b37af2020-09-04 14:11:55 +020059 components: { StatusIcon, IconLaunch, IconArrowDown },
60 props: {
61 isFullWindow: {
62 type: Boolean,
Derick Montague602e98a2020-10-21 16:20:00 -050063 default: true,
64 },
Mateusz Gapski96b37af2020-09-04 14:11:55 +020065 },
Mateusz Gapski632de222020-07-09 09:21:33 +020066 data() {
67 return {
68 rfb: null,
69 isConnected: false,
Mateusz Gapski96b37af2020-09-04 14:11:55 +020070 terminalClass: this.isFullWindow ? 'full-window' : '',
71 marginClass: this.isFullWindow ? 'margin-left-full-window' : '',
72 status: Connecting,
Derick Montague602e98a2020-10-21 16:20:00 -050073 convasRef: null,
Mateusz Gapski632de222020-07-09 09:21:33 +020074 };
75 },
Mateusz Gapski96b37af2020-09-04 14:11:55 +020076 computed: {
77 hostStatusIcon() {
78 if (this.status === Connected) {
79 return 'success';
80 } else if (this.status === Disconnected) {
81 return 'danger';
82 }
83 return 'secondary';
84 },
85 hostStatus() {
86 if (this.status === Connected) {
87 return this.$t('pageKvm.connected');
88 } else if (this.status === Disconnected) {
89 return this.$t('pageKvm.disconnected');
90 }
91 return this.$t('pageKvm.connecting');
Derick Montague602e98a2020-10-21 16:20:00 -050092 },
Mateusz Gapski96b37af2020-09-04 14:11:55 +020093 },
Mateusz Gapski632de222020-07-09 09:21:33 +020094 mounted() {
95 this.openTerminal();
96 },
97 methods: {
98 sendCtrlAltDel() {
99 this.rfb.sendCtrlAltDel();
100 },
101 openTerminal() {
102 const token = this.$store.getters['authentication/token'];
103 this.rfb = new RFB(
104 this.$refs.panel,
105 `wss://${window.location.host}/kvm/0`,
106 { wsProtocols: [token] }
107 );
108
109 this.rfb.scaleViewport = true;
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200110 this.rfb.clipViewport = true;
Mateusz Gapski632de222020-07-09 09:21:33 +0200111 const that = this;
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200112
113 window.addEventListener('resize', () => {
114 setTimeout(that.setWidthToolbar, 0);
115 });
116
Mateusz Gapski632de222020-07-09 09:21:33 +0200117 this.rfb.addEventListener('connect', () => {
118 that.isConnected = true;
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200119 that.status = Connected;
120 that.setWidthToolbar();
Mateusz Gapski632de222020-07-09 09:21:33 +0200121 });
122
123 this.rfb.addEventListener('disconnect', () => {
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200124 this.isConnected = false;
125 that.status = Disconnected;
Mateusz Gapski632de222020-07-09 09:21:33 +0200126 });
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200127 },
128 setWidthToolbar() {
129 if (
130 this.$refs.panel.children &&
131 this.$refs.panel.children.length > 0 &&
132 this.$refs.panel.children[0].children.length > 0
133 ) {
134 this.$refs.toolbar.style.width =
135 this.$refs.panel.children[0].children[0].clientWidth - 10 + 'px';
136 }
137 },
138 openConsoleWindow() {
139 window.open(
140 '#/console/kvm',
141 '_blank',
142 'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=yes,width=700,height=550'
143 );
Derick Montague602e98a2020-10-21 16:20:00 -0500144 },
145 },
Mateusz Gapski632de222020-07-09 09:21:33 +0200146};
147</script>
148
149<style scoped lang="scss">
Mateusz Gapski632de222020-07-09 09:21:33 +0200150.button-ctrl-alt-delete {
151 float: right;
152}
153
154.kvm-status {
155 padding-top: $spacer / 2;
156 padding-left: $spacer / 4;
157 display: inline-block;
158}
Mateusz Gapski96b37af2020-09-04 14:11:55 +0200159
160.margin-left-full-window {
161 margin-left: 5px;
162}
Mateusz Gapski632de222020-07-09 09:21:33 +0200163</style>