mirror of https://github.com/portainer/portainer
fix(terminal): display os specific copy/paste tooltip EE-1976 (#10835)
parent
fc7d9ca2cd
commit
fe47318e26
|
@ -183,8 +183,11 @@ angular.module('portainer.docker').controller('ContainerConsoleController', [
|
||||||
socket.onopen = function () {
|
socket.onopen = function () {
|
||||||
$scope.state = states.connected;
|
$scope.state = states.connected;
|
||||||
term = new Terminal();
|
term = new Terminal();
|
||||||
|
socket.send('export LANG=C.UTF-8\n');
|
||||||
|
socket.send('export LC_ALL=C.UTF-8\n');
|
||||||
|
socket.send('clear\n');
|
||||||
|
|
||||||
term.on('data', function (data) {
|
term.onData(function (data) {
|
||||||
socket.send(data);
|
socket.send(data);
|
||||||
});
|
});
|
||||||
var terminal_container = document.getElementById('terminal-container');
|
var terminal_container = document.getElementById('terminal-container');
|
||||||
|
|
|
@ -69,9 +69,11 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div ng-if="state !== states.disconnected">
|
<div ng-if="state !== states.disconnected">
|
||||||
<label
|
<label class="control-label text-left"
|
||||||
>Exec into container as <code>{{ ::formValues.user || 'default user' }}</code> using command
|
>Exec into container as <code>{{ ::formValues.user || 'default user' }}</code> using command
|
||||||
<code>{{ formValues.isCustomCommand ? formValues.customCommand : formValues.command }}</code></label
|
<code>{{ formValues.isCustomCommand ? formValues.customCommand : formValues.command }}</code>
|
||||||
|
<terminal-tooltip> </terminal-tooltip>
|
||||||
|
></label
|
||||||
>
|
>
|
||||||
<button type="button" class="btn btn-primary" ng-click="disconnect()">
|
<button type="button" class="btn btn-primary" ng-click="disconnect()">
|
||||||
<span ng-show="state === states.connected">Disconnect</span>
|
<span ng-show="state === states.connected">Disconnect</span>
|
||||||
|
|
|
@ -30,6 +30,7 @@ import { SearchBar } from '@@/datatables/SearchBar';
|
||||||
import { FallbackImage } from '@@/FallbackImage';
|
import { FallbackImage } from '@@/FallbackImage';
|
||||||
import { BadgeIcon } from '@@/BadgeIcon';
|
import { BadgeIcon } from '@@/BadgeIcon';
|
||||||
import { TeamsSelector } from '@@/TeamsSelector';
|
import { TeamsSelector } from '@@/TeamsSelector';
|
||||||
|
import { TerminalTooltip } from '@@/TerminalTooltip';
|
||||||
import { PortainerSelect } from '@@/form-components/PortainerSelect';
|
import { PortainerSelect } from '@@/form-components/PortainerSelect';
|
||||||
import { Slider } from '@@/form-components/Slider';
|
import { Slider } from '@@/form-components/Slider';
|
||||||
import { TagButton } from '@@/TagButton';
|
import { TagButton } from '@@/TagButton';
|
||||||
|
@ -84,6 +85,7 @@ export const ngModule = angular
|
||||||
'portainerTooltip',
|
'portainerTooltip',
|
||||||
r2a(Tooltip, ['message', 'position', 'className', 'setHtmlMessage', 'size'])
|
r2a(Tooltip, ['message', 'position', 'className', 'setHtmlMessage', 'size'])
|
||||||
)
|
)
|
||||||
|
.component('terminalTooltip', r2a(TerminalTooltip, []))
|
||||||
.component('badge', r2a(Badge, ['type', 'className']))
|
.component('badge', r2a(Badge, ['type', 'className']))
|
||||||
.component('fileUploadField', fileUploadField)
|
.component('fileUploadField', fileUploadField)
|
||||||
.component('porSwitchField', switchField)
|
.component('porSwitchField', switchField)
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
import { BROWSER_OS_PLATFORM } from '@/react/constants';
|
||||||
|
|
||||||
|
import { Tooltip } from '@@/Tip/Tooltip';
|
||||||
|
|
||||||
|
const editorConfig = {
|
||||||
|
mac: {
|
||||||
|
tooltip: (
|
||||||
|
<>
|
||||||
|
<div>Within the console:</div>
|
||||||
|
<div>Cmd+C - Copy</div>
|
||||||
|
<div>Cmd+V - Paste</div>
|
||||||
|
<div>or right-click -> Copy/Paste</div>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
lin: {
|
||||||
|
tooltip: (
|
||||||
|
<>
|
||||||
|
<div>Within the console:</div>
|
||||||
|
<div>Ctrl+Insert - Copy</div>
|
||||||
|
<div>Shift+Insert - Paste</div>
|
||||||
|
<div>or right-click -> Copy/Paste</div>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
|
||||||
|
win: {
|
||||||
|
tooltip: (
|
||||||
|
<>
|
||||||
|
<div>Within the console:</div>
|
||||||
|
<div>Ctrl+Insert - Copy</div>
|
||||||
|
<div>Shift+Insert - Paste</div>
|
||||||
|
<div>or right-click -> Copy/Paste</div>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export function TerminalTooltip() {
|
||||||
|
return <Tooltip message={editorConfig[BROWSER_OS_PLATFORM].tooltip} />;
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
export { TerminalTooltip } from './TerminalTooltip';
|
|
@ -5,6 +5,7 @@ import { Terminal } from 'xterm';
|
||||||
|
|
||||||
import { baseHref } from '@/portainer/helpers/pathHelper';
|
import { baseHref } from '@/portainer/helpers/pathHelper';
|
||||||
import { notifyError } from '@/portainer/services/notifications';
|
import { notifyError } from '@/portainer/services/notifications';
|
||||||
|
import { TerminalTooltip } from '@/react/components/TerminalTooltip';
|
||||||
|
|
||||||
import { PageHeader } from '@@/PageHeader';
|
import { PageHeader } from '@@/PageHeader';
|
||||||
import { Widget, WidgetBody } from '@@/Widget';
|
import { Widget, WidgetBody } from '@@/Widget';
|
||||||
|
@ -74,6 +75,9 @@ export function ConsoleView() {
|
||||||
terminal?.setOption('cursorBlink', true);
|
terminal?.setOption('cursorBlink', true);
|
||||||
terminal?.focus();
|
terminal?.focus();
|
||||||
setConnectionStatus('open');
|
setConnectionStatus('open');
|
||||||
|
socket.send('export LANG=C.UTF-8\n');
|
||||||
|
socket.send('export LC_ALL=C.UTF-8\n');
|
||||||
|
socket.send('clear\n');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,7 +97,7 @@ export function ConsoleView() {
|
||||||
}, [disconnectConsole, setConnectionStatus, socket, terminal]);
|
}, [disconnectConsole, setConnectionStatus, socket, terminal]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
terminal?.on('data', (data) => {
|
terminal?.onData((data) => {
|
||||||
socket?.send(data);
|
socket?.send(data);
|
||||||
});
|
});
|
||||||
}, [terminal, socket]);
|
}, [terminal, socket]);
|
||||||
|
@ -118,6 +122,7 @@ export function ConsoleView() {
|
||||||
className="col-sm-3 col-lg-2 control-label m-0 p-0 text-left"
|
className="col-sm-3 col-lg-2 control-label m-0 p-0 text-left"
|
||||||
>
|
>
|
||||||
Command
|
Command
|
||||||
|
<TerminalTooltip />
|
||||||
</label>
|
</label>
|
||||||
<div className="col-sm-8 input-group p-0">
|
<div className="col-sm-8 input-group p-0">
|
||||||
<span className="input-group-addon">
|
<span className="input-group-addon">
|
||||||
|
|
|
@ -46,19 +46,27 @@ export function KubeCtlShell({ environmentId, onClose }: Props) {
|
||||||
onClose();
|
onClose();
|
||||||
}, [onClose, terminal, socket]);
|
}, [onClose, terminal, socket]);
|
||||||
|
|
||||||
const openTerminal = useCallback(() => {
|
const openTerminal = useCallback(
|
||||||
if (!terminalElem.current) {
|
(socket: WebSocket | null) => {
|
||||||
return;
|
if (!terminalElem.current) {
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
terminal.open(terminalElem.current);
|
terminal.open(terminalElem.current);
|
||||||
terminal.setOption('cursorBlink', true);
|
terminal.setOption('cursorBlink', true);
|
||||||
terminal.focus();
|
terminal.focus();
|
||||||
fit(terminal);
|
fit(terminal);
|
||||||
terminal.writeln('#Run kubectl commands inside here');
|
if (socket) {
|
||||||
terminal.writeln('#e.g. kubectl get all');
|
socket.send('export LANG=C.UTF-8\n');
|
||||||
terminal.writeln('');
|
socket.send('export LC_ALL=C.UTF-8\n');
|
||||||
}, [terminal]);
|
socket.send('clear\n');
|
||||||
|
}
|
||||||
|
terminal.writeln('#Run kubectl commands inside here');
|
||||||
|
terminal.writeln('#e.g. kubectl get all');
|
||||||
|
terminal.writeln('');
|
||||||
|
},
|
||||||
|
[terminal]
|
||||||
|
);
|
||||||
|
|
||||||
// refresh socket listeners on socket updates
|
// refresh socket listeners on socket updates
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -66,7 +74,7 @@ export function KubeCtlShell({ environmentId, onClose }: Props) {
|
||||||
return () => {};
|
return () => {};
|
||||||
}
|
}
|
||||||
function onOpen() {
|
function onOpen() {
|
||||||
openTerminal();
|
openTerminal(socket);
|
||||||
}
|
}
|
||||||
function onMessage(e: MessageEvent) {
|
function onMessage(e: MessageEvent) {
|
||||||
terminal.write(e.data);
|
terminal.write(e.data);
|
||||||
|
|
Loading…
Reference in New Issue