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
97      this.ws = new WebSocket(`wss://${window.location.host}/console0`, [
98        token,
99      ]);
100
101      // Refer https://github.com/xtermjs/xterm.js/ for xterm implementation and addons.
102
103      this.term = new Terminal({
104        fontSize: 15,
105        fontFamily:
106          'SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace',
107      });
108
109      const attachAddon = new AttachAddon(this.ws);
110      this.term.loadAddon(attachAddon);
111
112      const fitAddon = new FitAddon();
113      this.term.loadAddon(fitAddon);
114
115      const SOL_THEME = {
116        background: '#19273c',
117        cursor: 'rgba(83, 146, 255, .5)',
118        scrollbar: 'rgba(83, 146, 255, .5)',
119      };
120      this.term.setOption('theme', SOL_THEME);
121
122      this.term.open(this.$refs.panel);
123      fitAddon.fit();
124
125      this.resizeConsoleWindow = throttle(() => {
126        fitAddon.fit();
127      }, 1000);
128      window.addEventListener('resize', this.resizeConsoleWindow);
129
130      try {
131        this.ws.onopen = function () {
132          console.log('websocket console0/ opened');
133        };
134        this.ws.onclose = function (event) {
135          console.log(
136            'websocket console0/ closed. code: ' +
137              event.code +
138              ' reason: ' +
139              event.reason
140          );
141        };
142      } catch (error) {
143        console.log(error);
144      }
145    },
146    closeTerminal() {
147      console.log('closeTerminal');
148      this.term.dispose();
149      this.term = null;
150      this.ws.close();
151      this.ws = null;
152    },
153    openConsoleWindow() {
154      window.open(
155        '#/console/serial-over-lan-console',
156        '_blank',
157        'directories=no,titlebar=no,toolbar=no,location=no,status=no,menubar=no,scrollbars=no,resizable=yes,width=600,height=550'
158      );
159    },
160  },
161};
162</script>
163
164<style lang="scss" scoped>
165@import '~xterm/css/xterm.css';
166
167#terminal {
168  overflow: auto;
169}
170
171.full-window-container {
172  width: 97%;
173  margin: 1.5%;
174}
175</style>
176