mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-26 11:35:35 +00:00
78 lines
1.9 KiB
JavaScript
78 lines
1.9 KiB
JavaScript
|
// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved.
|
||
|
// Use of this source code is governed by a BSD-style
|
||
|
// license that can be found in the LICENSE file.
|
||
|
|
||
|
import { Terminal } from "xterm"
|
||
|
|
||
|
export function showSSHPeers(peers, ipn) {
|
||
|
const peersNode = document.getElementById("peers")
|
||
|
peersNode.innerHTML = ""
|
||
|
|
||
|
const sshPeers = peers.filter((p) => p.tailscaleSSHEnabled)
|
||
|
if (!sshPeers.length) {
|
||
|
peersNode.textContent = "No machines have Tailscale SSH installed."
|
||
|
return
|
||
|
}
|
||
|
|
||
|
for (const peer of sshPeers) {
|
||
|
const peerNode = document.createElement("div")
|
||
|
peerNode.className = "peer"
|
||
|
const nameNode = document.createElement("div")
|
||
|
nameNode.className = "name"
|
||
|
nameNode.textContent = peer.name
|
||
|
peerNode.appendChild(nameNode)
|
||
|
|
||
|
const sshButtonNode = document.createElement("button")
|
||
|
sshButtonNode.className = "ssh"
|
||
|
sshButtonNode.addEventListener("click", function () {
|
||
|
ssh(peer.name, ipn)
|
||
|
})
|
||
|
sshButtonNode.textContent = "SSH"
|
||
|
peerNode.appendChild(sshButtonNode)
|
||
|
|
||
|
peersNode.appendChild(peerNode)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
export function hideSSHPeers() {
|
||
|
const peersNode = document.getElementById("peers")
|
||
|
peersNode.innerHTML = ""
|
||
|
}
|
||
|
|
||
|
function ssh(hostname, ipn) {
|
||
|
const termContainerNode = document.createElement("div")
|
||
|
termContainerNode.className = "term-container"
|
||
|
document.body.appendChild(termContainerNode)
|
||
|
|
||
|
const term = new Terminal({
|
||
|
cursorBlink: true,
|
||
|
})
|
||
|
term.open(termContainerNode)
|
||
|
|
||
|
// Cancel wheel events from scrolling the page if the terminal has scrollback
|
||
|
termContainerNode.addEventListener("wheel", (e) => {
|
||
|
if (term.buffer.active.baseY > 0) {
|
||
|
e.preventDefault()
|
||
|
}
|
||
|
})
|
||
|
|
||
|
let onDataHook
|
||
|
term.onData((e) => {
|
||
|
onDataHook?.(e)
|
||
|
})
|
||
|
|
||
|
term.focus()
|
||
|
|
||
|
ipn.ssh(
|
||
|
hostname,
|
||
|
(input) => term.write(input),
|
||
|
(hook) => (onDataHook = hook),
|
||
|
term.rows,
|
||
|
term.cols,
|
||
|
() => {
|
||
|
term.dispose()
|
||
|
termContainerNode.remove()
|
||
|
}
|
||
|
)
|
||
|
}
|