mirror of
https://github.com/bingohuang/docker-labs.git
synced 2025-07-14 10:17:26 +08:00
It fixes lots of bugs, can fallback to long polling, resize viewport of terminals and share clients state of the session, so they all see the same thing.
207 lines
6.4 KiB
JavaScript
207 lines
6.4 KiB
JavaScript
(function () {
|
|
'use strict';
|
|
|
|
var app = angular.module('DockerPlay', ['ngMaterial']);
|
|
|
|
app.controller('PlayController', ['$scope', '$log', '$http', '$location', '$timeout', '$mdDialog', '$window', function($scope, $log, $http, $location, $timeout, $mdDialog, $window) {
|
|
$scope.sessionId = window.location.pathname.replace('/p/', '');
|
|
$scope.instances = [];
|
|
$scope.idx = {};
|
|
$scope.selectedInstance = null;
|
|
$scope.isAlive = true;
|
|
|
|
angular.element($window).bind('resize', function(){
|
|
if ($scope.selectedInstance) {
|
|
$scope.resize($scope.selectedInstance.term.proposeGeometry());
|
|
}
|
|
});
|
|
|
|
|
|
$scope.showAlert = function(title, content, parent) {
|
|
$mdDialog.show(
|
|
$mdDialog.alert()
|
|
.parent(angular.element(document.querySelector(parent || '#popupContainer')))
|
|
.clickOutsideToClose(true)
|
|
.title(title)
|
|
.textContent(content)
|
|
.ok('Got it!')
|
|
);
|
|
}
|
|
|
|
$scope.resize = function(geometry) {
|
|
$scope.socket.emit('viewport resize', geometry.cols, geometry.rows);
|
|
}
|
|
|
|
$scope.upsertInstance = function(info) {
|
|
var i = info;
|
|
if (!$scope.idx[i.name]) {
|
|
$scope.instances.push(i);
|
|
i.buffer = '';
|
|
$scope.idx[i.name] = i;
|
|
} else {
|
|
$scope.idx[i.name].ip = i.ip;
|
|
}
|
|
|
|
return $scope.idx[i.name];
|
|
}
|
|
|
|
$scope.newInstance = function() {
|
|
$http({
|
|
method: 'POST',
|
|
url: '/sessions/' + $scope.sessionId + '/instances',
|
|
}).then(function(response) {
|
|
var i = $scope.upsertInstance(response.data);
|
|
$scope.showInstance(i);
|
|
}, function(response) {
|
|
if (response.status == 409) {
|
|
$scope.showAlert('Max instances reached', 'Maximum number of instances reached')
|
|
}
|
|
});
|
|
}
|
|
|
|
$scope.getSession = function(sessionId) {
|
|
$http({
|
|
method: 'GET',
|
|
url: '/sessions/' + $scope.sessionId,
|
|
}).then(function(response) {
|
|
var socket = io({path: '/sessions/' + sessionId + '/ws'});
|
|
|
|
socket.on('terminal out', function(name, data) {
|
|
var instance = $scope.idx[name];
|
|
|
|
if (!instance) {
|
|
// instance is new and was created from another client, we should add it
|
|
$scope.upsertInstance({name: name});
|
|
instance = $scope.idx[name];
|
|
}
|
|
if (!instance.term) {
|
|
instance.buffer += data;
|
|
} else {
|
|
instance.term.write(data);
|
|
}
|
|
});
|
|
|
|
socket.on('session end', function() {
|
|
$scope.showAlert('Session timedout!', 'Your session has expire and all your instances has been deleted.', '#sessionEnd')
|
|
$scope.isAlive = false;
|
|
});
|
|
|
|
socket.on('viewport', function(rows, cols) {
|
|
});
|
|
|
|
socket.on('new instance', function(name, ip) {
|
|
$scope.upsertInstance({name: name, ip: ip});
|
|
$scope.$apply(function() {
|
|
if ($scope.instances.length == 1) {
|
|
$scope.showInstance($scope.instances[0]);
|
|
}
|
|
});
|
|
});
|
|
|
|
socket.on('delete instance', function(name) {
|
|
$scope.removeInstance(name);
|
|
$scope.$apply();
|
|
});
|
|
|
|
socket.on('viewport resize', function(cols, rows) {
|
|
// viewport has changed, we need to resize all terminals
|
|
|
|
$scope.instances.forEach(function(instance) {
|
|
instance.term.resize(cols, rows);
|
|
});
|
|
});
|
|
|
|
$scope.socket = socket;
|
|
|
|
var i = response.data;
|
|
for (var k in i.instances) {
|
|
var instance = i.instances[k];
|
|
$scope.instances.push(instance);
|
|
$scope.idx[instance.name] = instance;
|
|
}
|
|
if ($scope.instances.length) {
|
|
$scope.showInstance($scope.instances[0]);
|
|
}
|
|
}, function(response) {
|
|
if (response.status == 404) {
|
|
document.write('session not found');
|
|
return
|
|
}
|
|
});
|
|
}
|
|
|
|
$scope.showInstance = function(instance) {
|
|
$scope.selectedInstance = instance;
|
|
if (!instance.creatingTerminal) {
|
|
instance.creatingTerminal = true;
|
|
if (!instance.term) {
|
|
$timeout(function() {
|
|
createTerminal(instance);
|
|
instance.term.focus();
|
|
}, 0, false);
|
|
} else {
|
|
$timeout(function() {
|
|
instance.term.focus();
|
|
}, 0, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
$scope.removeInstance = function(name) {
|
|
if ($scope.idx[name]) {
|
|
delete $scope.idx[name];
|
|
$scope.instances = $scope.instances.filter(function(i) {
|
|
return i.name != name;
|
|
});
|
|
if ($scope.instances.length) {
|
|
$scope.showInstance($scope.instances[0]);
|
|
}
|
|
}
|
|
}
|
|
|
|
$scope.deleteInstance = function(instance) {
|
|
$http({
|
|
method: 'DELETE',
|
|
url: '/sessions/' + $scope.sessionId + '/instances/' + instance.name,
|
|
}).then(function(response) {
|
|
$scope.removeInstance(instance.name);
|
|
}, function(response) {
|
|
console.log('error', response);
|
|
});
|
|
}
|
|
|
|
$scope.getSession($scope.sessionId);
|
|
|
|
function createTerminal(instance, cb) {
|
|
if (instance.term) {
|
|
return instance.term;
|
|
}
|
|
|
|
var terminalContainer = document.getElementById('terminal-'+ instance.name);
|
|
|
|
var term = new Terminal({
|
|
cursorBlink: false
|
|
});
|
|
|
|
term.open(terminalContainer);
|
|
|
|
$scope.resize(term.proposeGeometry());
|
|
|
|
term.on('data', function(d) {
|
|
$scope.socket.emit('terminal in', instance.name, d);
|
|
});
|
|
|
|
instance.term = term;
|
|
|
|
if (instance.buffer) {
|
|
term.write(instance.buffer);
|
|
instance.buffer = '';
|
|
}
|
|
|
|
if (cb) {
|
|
cb();
|
|
}
|
|
}
|
|
}]);
|
|
})();
|