mirror of https://github.com/portainer/portainer
EE-1976 fix(docker): support copy and paste in container console
parent
93866644c6
commit
ac99b9561e
|
@ -1,6 +1,6 @@
|
|||
import 'bootstrap/dist/css/bootstrap.css';
|
||||
import 'toastr/build/toastr.css';
|
||||
import 'xterm/dist/xterm.css';
|
||||
import 'xterm/css/xterm.css';
|
||||
import 'angularjs-slider/dist/rzslider.css';
|
||||
import 'angular-json-tree/dist/angular-json-tree.css';
|
||||
import 'angular-loading-bar/build/loading-bar.css';
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
import { Terminal } from 'xterm';
|
||||
import * as fit from 'xterm/lib/addons/fit/fit';
|
||||
import { agentInterceptor } from './portainer/services/axios';
|
||||
|
||||
/* @ngInject */
|
||||
|
@ -27,8 +25,6 @@ export function configApp($urlRouterProvider, $httpProvider, localStorageService
|
|||
request: agentInterceptor,
|
||||
}));
|
||||
|
||||
Terminal.applyAddon(fit);
|
||||
|
||||
$uibTooltipProvider.setTriggers({
|
||||
mouseenter: 'mouseleave',
|
||||
click: 'click',
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Terminal } from 'xterm';
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import { baseHref } from '@/portainer/helpers/pathHelper';
|
||||
|
||||
angular.module('portainer.docker').controller('ContainerConsoleController', [
|
||||
|
@ -28,7 +29,7 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
|
|||
CONSOLE_COMMANDS_LABEL_PREFIX,
|
||||
SidebarService
|
||||
) {
|
||||
var socket, term;
|
||||
var socket, term, fitAddon;
|
||||
|
||||
let states = Object.freeze({
|
||||
disconnected: 0,
|
||||
|
@ -138,6 +139,9 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
|
|||
term.write('\n\r(connection closed)');
|
||||
term.dispose();
|
||||
}
|
||||
if (fitAddon) {
|
||||
fitAddon.dispose();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -152,7 +156,7 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
|
|||
function resize(restcall, add) {
|
||||
add = add || 0;
|
||||
|
||||
term.fit();
|
||||
fitAddon.fit();
|
||||
var termWidth = term.cols;
|
||||
var termHeight = 30;
|
||||
term.resize(termWidth, termHeight);
|
||||
|
@ -161,7 +165,7 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
|
|||
}
|
||||
|
||||
function initTerm(url, resizeRestCall) {
|
||||
let resizefun = resize.bind(this, resizeRestCall);
|
||||
let resizeFunc = resize.bind(this, resizeRestCall);
|
||||
|
||||
if ($transition$.params().nodeName) {
|
||||
url += '&nodeName=' + $transition$.params().nodeName;
|
||||
|
@ -176,23 +180,24 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
|
|||
|
||||
socket.onopen = function () {
|
||||
$scope.state = states.connected;
|
||||
term = new Terminal();
|
||||
term = new Terminal({ cursorBlink: true });
|
||||
fitAddon = new FitAddon();
|
||||
term.loadAddon(fitAddon);
|
||||
|
||||
term.on('data', function (data) {
|
||||
term.onData(function (data) {
|
||||
socket.send(data);
|
||||
});
|
||||
var terminal_container = document.getElementById('terminal-container');
|
||||
term.open(terminal_container);
|
||||
term.focus();
|
||||
term.setOption('cursorBlink', true);
|
||||
|
||||
window.onresize = function () {
|
||||
resizefun();
|
||||
resizeFunc();
|
||||
$scope.$apply();
|
||||
};
|
||||
|
||||
$scope.$watch(SidebarService.isSidebarOpen, function () {
|
||||
setTimeout(resizefun, 400);
|
||||
setTimeout(resizeFunc, 400);
|
||||
});
|
||||
|
||||
socket.onmessage = function (e) {
|
||||
|
@ -208,7 +213,7 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
|
|||
$scope.$apply();
|
||||
};
|
||||
|
||||
resizefun(1);
|
||||
resizeFunc(1);
|
||||
$scope.$apply();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { Terminal } from 'xterm';
|
||||
import { fit } from 'xterm/lib/addons/fit/fit';
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import clsx from 'clsx';
|
||||
import { RotateCw, X, Terminal as TerminalIcon } from 'lucide-react';
|
||||
|
@ -29,7 +29,8 @@ interface Props {
|
|||
}
|
||||
|
||||
export function KubeCtlShell({ environmentId, onClose }: Props) {
|
||||
const [terminal] = useState(new Terminal());
|
||||
const [terminal] = useState(new Terminal({ cursorBlink: true }));
|
||||
const [fitAddon] = useState(new FitAddon());
|
||||
|
||||
const [shell, setShell] = useState<ShellState>({
|
||||
socket: null,
|
||||
|
@ -46,22 +47,23 @@ export function KubeCtlShell({ environmentId, onClose }: Props) {
|
|||
terminalClose(); // only css trick
|
||||
socket?.close();
|
||||
terminal.dispose();
|
||||
fitAddon.dispose();
|
||||
onClose();
|
||||
}, [onClose, terminal, socket]);
|
||||
}, [onClose, socket, terminal, fitAddon]);
|
||||
|
||||
const openTerminal = useCallback(() => {
|
||||
if (!terminalElem.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminal.loadAddon(fitAddon);
|
||||
terminal.open(terminalElem.current);
|
||||
terminal.setOption('cursorBlink', true);
|
||||
terminal.focus();
|
||||
fit(terminal);
|
||||
fitAddon.fit();
|
||||
terminal.writeln('#Run kubectl commands inside here');
|
||||
terminal.writeln('#e.g. kubectl get all');
|
||||
terminal.writeln('');
|
||||
}, [terminal]);
|
||||
}, [terminal, fitAddon]);
|
||||
|
||||
// refresh socket listeners on socket updates
|
||||
useEffect(() => {
|
||||
|
@ -106,7 +108,17 @@ export function KubeCtlShell({ environmentId, onClose }: Props) {
|
|||
const socket = new WebSocket(buildUrl(jwt, environmentId));
|
||||
setShell((shell) => ({ ...shell, socket }));
|
||||
|
||||
terminal.onData((data) => socket.send(data));
|
||||
terminal.onData((data) => {
|
||||
if (
|
||||
terminal.modes.bracketedPasteMode &&
|
||||
data.slice(0, 6) === '\x1b[200~' &&
|
||||
data.slice(-6) === '\x1b[201~'
|
||||
) {
|
||||
socket.send(data.slice(6, -6));
|
||||
} else {
|
||||
socket.send(data);
|
||||
}
|
||||
});
|
||||
terminal.onKey(({ domEvent }) => {
|
||||
if (domEvent.ctrlKey && domEvent.code === 'KeyD') {
|
||||
close();
|
||||
|
@ -118,11 +130,12 @@ export function KubeCtlShell({ environmentId, onClose }: Props) {
|
|||
function close() {
|
||||
socket.close();
|
||||
terminal.dispose();
|
||||
fitAddon.dispose();
|
||||
window.removeEventListener('resize', terminalResize);
|
||||
}
|
||||
|
||||
return close;
|
||||
}, [environmentId, jwt, terminal]);
|
||||
}, [environmentId, jwt, terminal, fitAddon]);
|
||||
|
||||
return (
|
||||
<div className={clsx(styles.root, { [styles.minimized]: shell.minimized })}>
|
||||
|
|
|
@ -118,7 +118,9 @@
|
|||
"tippy.js": "^6.3.7",
|
||||
"toastr": "^2.1.4",
|
||||
"uuid": "^3.3.2",
|
||||
"xterm": "^3.8.0",
|
||||
"x256": "^0.0.2",
|
||||
"xterm": "^4.1.3",
|
||||
"xterm-addon-fit": "^0.5.0",
|
||||
"yaml": "^1.10.2",
|
||||
"yup": "^0.32.11",
|
||||
"zustand": "^4.1.1"
|
||||
|
@ -234,4 +236,4 @@
|
|||
}
|
||||
},
|
||||
"browserslist": "last 2 versions"
|
||||
}
|
||||
}
|
13
yarn.lock
13
yarn.lock
|
@ -18932,10 +18932,15 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@^4.0.2, xtend@~4.0.1:
|
|||
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
|
||||
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
|
||||
|
||||
xterm@^3.8.0:
|
||||
version "3.14.5"
|
||||
resolved "https://registry.yarnpkg.com/xterm/-/xterm-3.14.5.tgz#c9d14e48be6873aa46fb429f22f2165557fd2dea"
|
||||
integrity sha512-DVmQ8jlEtL+WbBKUZuMxHMBgK/yeIZwkXB81bH+MGaKKnJGYwA+770hzhXPfwEIokK9On9YIFPRleVp/5G7z9g==
|
||||
xterm-addon-fit@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.npmmirror.com/xterm-addon-fit/-/xterm-addon-fit-0.5.0.tgz#2d51b983b786a97dcd6cde805e700c7f913bc596"
|
||||
integrity sha512-DsS9fqhXHacEmsPxBJZvfj2la30Iz9xk+UKjhQgnYNkrUIN5CYLbw7WEfz117c7+S86S/tpHPfvNxJsF5/G8wQ==
|
||||
|
||||
xterm@^4.1.3:
|
||||
version "4.19.0"
|
||||
resolved "https://registry.npmmirror.com/xterm/-/xterm-4.19.0.tgz#c0f9d09cd61de1d658f43ca75f992197add9ef6d"
|
||||
integrity sha512-c3Cp4eOVsYY5Q839dR5IejghRPpxciGmLWWaP9g+ppfMeBChMeLa1DCA+pmX/jyDZ+zxFOmlJL/82qVdayVoGQ==
|
||||
|
||||
xterm@^4.13.0:
|
||||
version "4.17.0"
|
||||
|
|
Loading…
Reference in New Issue