Skip to content

Commit 3e61bfd

Browse files
committed
Replace console view with proper ts
1 parent d7ce62c commit 3e61bfd

File tree

6 files changed

+194
-185
lines changed

6 files changed

+194
-185
lines changed

resources/assets/scripts/components/server/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
export {default as Server} from './Server';
22
export {default as ServerAllocations} from './ServerAllocations.vue';
3-
export {default as ConsolePage} from './subpages/Console.vue';
3+
export {default as ConsolePage} from './subpages/Console';
44
export {default as DatabasesPage} from './subpages/Databases.vue';
55
export {default as FileManagerPage} from './subpages/FileManager.vue';
66
export {default as ServerSchedules} from './ServerSchedules.vue';
Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
import Vue from 'vue';
2+
import {mapState} from "vuex";
3+
import {Terminal} from 'xterm';
4+
import * as TerminalFit from 'xterm/lib/addons/fit/fit';
5+
import {Socketio} from "@/mixins/socketio";
6+
7+
type DataStructure = {
8+
terminal: Terminal | null,
9+
command: string,
10+
commandHistory: Array<string>,
11+
commandHistoryIndex: number,
12+
}
13+
14+
export default Vue.component('server-console', {
15+
mixins: [Socketio],
16+
computed: {
17+
...mapState('socket', ['connected']),
18+
},
19+
20+
watch: {
21+
/**
22+
* Watch the connected variable and when it becomes true request the server logs.
23+
*/
24+
connected: function (state: boolean) {
25+
if (state) {
26+
this.$nextTick(() => {
27+
this.mountTerminal();
28+
});
29+
} else {
30+
this.terminal && this.terminal.clear();
31+
}
32+
},
33+
},
34+
35+
/**
36+
* Listen for specific socket.io emits from the server.
37+
*/
38+
sockets: {
39+
'server log': function (data: string) {
40+
data.split(/\n/g).forEach((line: string): void => {
41+
if (this.terminal) {
42+
this.terminal.writeln(line + '\u001b[0m');
43+
}
44+
});
45+
},
46+
47+
'console': function (data: { line: string }) {
48+
data.line.split(/\n/g).forEach((line: string): void => {
49+
if (this.terminal) {
50+
this.terminal.writeln(line + '\u001b[0m');
51+
}
52+
});
53+
},
54+
},
55+
56+
/**
57+
* Mount the component and setup all of the terminal actions. Also fetches the initial
58+
* logs from the server to populate into the terminal if the socket is connected. If the
59+
* socket is not connected this will occur automatically when it connects.
60+
*/
61+
mounted: function () {
62+
if (this.connected) {
63+
this.mountTerminal();
64+
}
65+
},
66+
67+
data: function (): DataStructure {
68+
return {
69+
terminal: null,
70+
command: '',
71+
commandHistory: [],
72+
commandHistoryIndex: -1,
73+
};
74+
},
75+
76+
methods: {
77+
/**
78+
* Mount the terminal and grab the most recent server logs.
79+
*/
80+
mountTerminal: function () {
81+
// Get a new instance of the terminal setup.
82+
this.terminal = this._terminalInstance();
83+
84+
this.terminal.open((this.$refs.terminal as HTMLElement));
85+
// @ts-ignore
86+
this.terminal.fit();
87+
this.terminal.clear();
88+
89+
this.$socket().instance().emit('send server log');
90+
},
91+
92+
/**
93+
* Send a command to the server using the configured websocket.
94+
*/
95+
sendCommand: function () {
96+
this.commandHistoryIndex = -1;
97+
// this.commandHistory.unshift(this.command);
98+
this.commandHistory.unshift();
99+
this.$socket().instance().emit('send command', this.command);
100+
this.command = '';
101+
},
102+
103+
/**
104+
* Handle a user pressing up/down arrows when in the command field to scroll through thier
105+
* command history for this server.
106+
*/
107+
handleArrowKey: function (e: KeyboardEvent) {
108+
if (['ArrowUp', 'ArrowDown'].indexOf(e.key) < 0 || e.key === 'ArrowDown' && this.commandHistoryIndex < 0) {
109+
return;
110+
}
111+
112+
e.preventDefault();
113+
e.stopPropagation();
114+
115+
if (e.key === 'ArrowUp' && (this.commandHistoryIndex + 1 > (this.commandHistory.length - 1))) {
116+
return;
117+
}
118+
119+
this.commandHistoryIndex += (e.key === 'ArrowUp') ? 1 : -1;
120+
this.command = this.commandHistoryIndex < 0 ? '' : this.commandHistory[this.commandHistoryIndex];
121+
},
122+
123+
/**
124+
* Returns a new instance of the terminal to be used.
125+
*
126+
* @private
127+
*/
128+
_terminalInstance() {
129+
Terminal.applyAddon(TerminalFit);
130+
131+
return new Terminal({
132+
disableStdin: true,
133+
cursorStyle: 'underline',
134+
allowTransparency: true,
135+
fontSize: 12,
136+
fontFamily: 'Menlo, Monaco, Consolas, monospace',
137+
rows: 30,
138+
theme: {
139+
background: 'transparent',
140+
cursor: 'transparent',
141+
black: '#000000',
142+
red: '#E54B4B',
143+
green: '#9ECE58',
144+
yellow: '#FAED70',
145+
blue: '#396FE2',
146+
magenta: '#BB80B3',
147+
cyan: '#2DDAFD',
148+
white: '#d0d0d0',
149+
brightBlack: 'rgba(255, 255, 255, 0.2)',
150+
brightRed: '#FF5370',
151+
brightGreen: '#C3E88D',
152+
brightYellow: '#FFCB6B',
153+
brightBlue: '#82AAFF',
154+
brightMagenta: '#C792EA',
155+
brightCyan: '#89DDFF',
156+
brightWhite: '#ffffff',
157+
},
158+
});
159+
}
160+
},
161+
162+
template: `
163+
<div class="content-box animate fadein">
164+
<div class="text-xs font-mono">
165+
<div class="rounded-t p-2 bg-black overflow-scroll w-full" style="min-height: 16rem;max-height:64rem;">
166+
<div class="mb-2 text-grey-light" ref="terminal" v-if="connected"></div>
167+
<div v-else>
168+
<div class="spinner spinner-xl mt-24"></div>
169+
</div>
170+
</div>
171+
<div class="rounded-b bg-grey-darkest text-white flex">
172+
<div class="flex-no-shrink p-2">
173+
<span class="font-bold">$</span>
174+
</div>
175+
<div class="w-full">
176+
<input type="text" aria-label="Send console command" class="bg-transparent text-white p-2 pl-0 w-full" placeholder="enter command and press enter to send"
177+
ref="command"
178+
v-model="command"
179+
v-on:keyup.enter="sendCommand"
180+
v-on:keydown="handleArrowKey"
181+
>
182+
</div>
183+
</div>
184+
</div>
185+
</div>
186+
`,
187+
});

resources/assets/scripts/components/server/subpages/Console.vue

Lines changed: 0 additions & 183 deletions
This file was deleted.

resources/assets/scripts/pterodactyl-shims.d.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ declare module 'vue/types/options' {
2727
[s: string]: (data: any) => void,
2828
}
2929
},
30+
sockets?: {
31+
[s: string]: (data: any) => void,
32+
}
3033
}
3134
}
3235

resources/assets/styles/main.css

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
@import "tailwindcss/preflight";
55
@import "tailwindcss/components";
66

7+
@import "xterm/src/xterm.css";
8+
79
/**
810
* Pterodactyl Specific CSS
911
*/

0 commit comments

Comments
 (0)