0
0
mirror of https://github.com/dobin/lxd-webgui synced 2025-10-05 15:42:50 +02:00

correctly handle and sync terminal sizes

This commit is contained in:
Dobin Rutishauser
2016-09-11 16:18:30 +02:00
parent ab364b43c7
commit fd1b303b80
4 changed files with 93 additions and 72 deletions

View File

@@ -219,9 +219,15 @@ angular.module('myApp.container', ['ngRoute'])
container.isTerminalShown = true;
TerminalServices.getTerminal2(container.name).then(function(term) {
container.terminal = term;
term.open(document.getElementById('console' + container.name));
// get JS terminal emulator
container.terminal = TerminalServices.getJavascriptTerminal();
container.terminal.open(document.getElementById('console' + container.name));
var initialGeometry = container.terminal.proposeGeometry();
console.log("Rows: " + initialGeometry.rows + " Cols: " + initialGeometry.cols);
TerminalServices.getTerminal2(container.name, container.terminal, initialGeometry).then(function(term) {
container.terminal.fit();
});
};

View File

@@ -10,41 +10,44 @@
</div>
<div class="row bottomline" ng-repeat="container in containers">
<div class="col-md-3 col-xs-3"> {{container.name}} </div>
<div class="col-md-1 col-xs-1"> {{container.status}} </div>
<div class="col-md-2 col-xs-2"> {{container.architecture}} </div>
<div class="col-md-1 col-xs-1"> {{container.stateful}} </div>
<div class="col-md-1 col-xs-1">
<div ng-if="container.status != 'Running'">
<a class="btn btn-sm btn-success" ng-click="changeState(container, 'start')"><i
class="glyphicon glyphicon-play"></i> Start</a>
<div class="row">
<div class="col-md-3 col-xs-3"> {{container.name}} </div>
<div class="col-md-1 col-xs-1"> {{container.status}} </div>
<div class="col-md-2 col-xs-2"> {{container.architecture}} </div>
<div class="col-md-1 col-xs-1"> {{container.stateful}} </div>
<div class="col-md-1 col-xs-1">
<div ng-if="container.status != 'Running'">
<a class="btn btn-sm btn-success" ng-click="changeState(container, 'start')"><i
class="glyphicon glyphicon-play"></i> Start</a>
</div>
<div ng-if="container.status == 'Running'">
<a class="btn btn-sm btn-danger" ng-click="changeState(container, 'stop')"><i
class="glyphicon glyphicon-stop"></i> Stop</a>
</div>
</div>
<div ng-if="container.status == 'Running'">
<a class="btn btn-sm btn-danger" ng-click="changeState(container, 'stop')"><i
class="glyphicon glyphicon-stop"></i> Stop</a>
<div class="col-md-4 col-xs-3">
<a class="btn btn-sm btn-primary" href="#/container-view/{{container.name}}"><i
class="glyphicon glyphicon-edit"></i> Details</a>
<a class="btn btn-sm btn-primary" href="#/container-snapshots/{{container.name}}"><i
class="glyphicon glyphicon-edit"></i> Snapshots</a>
<a class="btn btn-sm btn-danger" ng-click="delete(container)"><i
class="glyphicon glyphicon-remove"></i> Delete</a>
<a ng-show="container.status=='Running'" class="btn btn-sm btn-info" ng-click="showTerminal(container)"><i
class="glyphicon glyphicon-modal-window"></i> Term</a>
<a ng-show="container.status=='Running'" class="btn btn-sm btn-info" href="#/terminal/{{container.name}}"><i
class="glyphicon glyphicon-modal-window"></i> Term Tab</a>
</div>
</div>
<div class="col-md-4 col-xs-3">
<a class="btn btn-sm btn-primary" href="#/container-view/{{container.name}}"><i
class="glyphicon glyphicon-edit"></i> Details</a>
<a class="btn btn-sm btn-primary" href="#/container-snapshots/{{container.name}}"><i
class="glyphicon glyphicon-edit"></i> Snapshots</a>
<a class="btn btn-sm btn-danger" ng-click="delete(container)"><i
class="glyphicon glyphicon-remove"></i> Delete</a>
<a ng-show="container.status=='Running'" class="btn btn-sm btn-info" ng-click="showTerminal(container)"><i
class="glyphicon glyphicon-modal-window"></i> Term</a>
<a ng-show="container.status=='Running'" class="btn btn-sm btn-info" href="#/terminal/{{container.name}}"><i
class="glyphicon glyphicon-modal-window"></i> Term Tab</a>
</div>
<div class="col-md-6">
<div id="console{{container.name}}" style="background-color:black;"></div>
<div class="row">
<div class="col-md-6">
<div class="terminal" id="console{{container.name}}" style="background-color:black;"></div>
</div>
</div>
</div>
</div>

View File

@@ -14,9 +14,18 @@ angular.module('myApp.terminal', ['ngRoute'])
.controller('terminalPageCtrl', function ($scope, $routeParams, $filter, $location,
TerminalServices, SettingServices) {
$scope.containerName = $routeParams.containerName;
var container = {};
TerminalServices.getTerminal2($scope.containerName).then(function(term) {
term.open(document.getElementById('console'));
// get JS terminal emulator
container.terminal = TerminalServices.getJavascriptTerminal();
container.terminal.open(document.getElementById('console'));
var initialGeometry = container.terminal.proposeGeometry();
console.log("Rows: " + initialGeometry.rows + " Cols: " + initialGeometry.cols);
TerminalServices.getTerminal2($scope.containerName, container.terminal, initialGeometry).then(function(term) {
container.terminal.fit();
});
})
;

View File

@@ -5,7 +5,21 @@ angular.module('myApp.remoteimage')
function ($http, $q, SettingServices) {
var obj = {};
obj.getTerminal = function(containerName) {
obj.getJavascriptTerminal = function() {
var term = new Terminal({
cols: 120,
rows: 25,
useStyle: true,
screenKeys: true,
cursorBlink: false
});
return term;
}
obj.getTerminal = function(containerName, geometry) {
var data = {
"command": ["bash"],
"environment": {
@@ -14,7 +28,9 @@ angular.module('myApp.remoteimage')
"USER": "root"
},
"wait-for-websocket": true,
"interactive": true
"interactive": true,
"width": geometry.cols,
"height": geometry.rows
}
return $http.post(SettingServices.getLxdApiUrl() + '/containers/' + containerName + "/exec", data).then(function(data) {
@@ -31,9 +47,8 @@ angular.module('myApp.remoteimage')
}
obj.getTerminal2 = function(containerName) {
return obj.getTerminal(containerName).then(function(data) {
obj.getTerminal2 = function(containerName, term, geometry) {
return obj.getTerminal(containerName, geometry).then(function(data) {
var operationId = data.data.metadata.id;
var secret = data.data.metadata.metadata.fds[0];
@@ -44,48 +59,36 @@ angular.module('myApp.remoteimage')
var sock = new WebSocket(wssurl);
var term = new Terminal({
cols: 120,
rows: 25,
useStyle: true,
screenKeys: true,
cursorBlink: false
});
term.on('data', function (data) {
sock.send(new Blob([data]));
});
sock.onopen = function (e) {
//container.terminal = term;
//term.open(document.getElementById('console'));
sock.onmessage = function (msg) {
if (msg.data instanceof Blob) {
var reader = new FileReader();
reader.addEventListener('loadend', function () {
term.write(reader.result);
});
reader.readAsBinaryString(msg.data);
} else {
term.write(msg.data);
}
sock.onmessage = function (msg) {
if (msg.data instanceof Blob) {
var reader = new FileReader();
reader.addEventListener('loadend', function () {
term.write(reader.result);
});
reader.readAsBinaryString(msg.data);
} else {
term.write(msg.data);
}
};
};
sock.onclose = function (msg) {
console.log('WebSocket closed');
term.destroy();
};
sock.onerror = function (err) {
console.error(err);
};
};
return term;
})
sock.onclose = function (msg) {
console.log('WebSocket closed');
term.destroy();
};
sock.onerror = function (err) {
console.error(err);
};
};
return term;
})
}
return obj;