Better ui feedback on the repair mode

This commit is contained in:
Johannes Zellner
2017-09-05 23:11:04 +02:00
parent d58e4f58c7
commit f7bcd54ef5
3 changed files with 92 additions and 48 deletions

View File

@@ -1150,6 +1150,13 @@ footer {
.dont-overflow {
overflow: hidden;
}
&.placeholder {
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
}
}
.contextMenuBackdrop {

View File

@@ -84,8 +84,8 @@
<button class="btn btn-default" ng-click="uploadFile()" ng-show="terminalVisible && selected.type === 'app' && !uploadProgress.busy"><i class="fa fa-upload"></i> Upload to /tmp</button>
<button class="btn btn-default" ng-click="uploadProgress.show()" ng-show="uploadProgress.busy"><i class="fa fa-circle-o-notch fa-spin"></i> Uploading...</button>
<button class="btn btn-default" ng-click="downloadFile.show()" ng-show="terminalVisible && selected.type === 'app'"><i class="fa fa-download"></i> Download</button>
<button class="btn btn-default" ng-click="repairApp()" ng-show="terminalVisible && selected.type === 'app' && !selectedAppInfo.debugMode"><i class="fa fa-wrench"></i> Repair</button>
<button class="btn btn-danger" ng-click="repairAppDone()" ng-show="selectedAppInfo.debugMode"><i class="fa fa-wrench"></i> Repair Done</button>
<button class="btn btn-default" ng-click="repairApp()" ng-show="terminalVisible && selected.type === 'app' && !selectedAppInfo.debugMode && !appBusy"><i class="fa fa-wrench"></i> Repair</button>
<button class="btn btn-danger" ng-click="repairAppDone()" ng-show="selectedAppInfo.debugMode && !appBusy"><i class="fa fa-wrench"></i> Repair Done</button>
</div>
<div class="btn-group pull-right" style="margin-left: 10px;">
@@ -94,10 +94,24 @@
<button class="btn btn-default" ng-click="terminalInject('mongodb')" ng-show="terminalVisible && usesAddon('mongodb')">MongoDB</button>
<button class="btn btn-default" ng-click="terminalInject('redis')" ng-show="terminalVisible && usesAddon('redis')">Redis</button>
</div>
</div>
</div>
<div class="logs-and-term-container" ng-class="{ 'dont-overflow': terminalVisible }"></div>
<div class="logs-and-term-container" id="logsAndTerminalContainer" ng-class="{ 'dont-overflow': terminalVisible }" ng-hide="terminalVisible && appBusy"></div>
<div class="logs-and-term-container placeholder" ng-show="terminalVisible && appBusy">
<h4>&nbsp;
<span ng-show="selectedAppInfo.installationState === 'pending_configure' && selectedAppInfo.debugMode">Restarting app for repair...</span>
<span ng-show="selectedAppInfo.installationState === 'pending_configure' && !selectedAppInfo.debugMode ">App is being reconfigured...</span>
<span ng-show="selectedAppInfo.installationState === 'installed' && !selectedAppInfo.debugMode">Waiting for app to start...</span>
<span ng-show="selectedAppInfo.installationState === 'pending_installed'">App is being installed...</span>
</h4>
<div class="progress" ng-show="appBusy" style="width: 80%">
<div class="progress-bar progress-bar-striped active" role="progressbar" style="width: 100%">
</div>
</div>
</div>
<div class="contextMenuBackdrop">
<ul class="dropdown-menu" id="terminalContextMenu" style="position: absolute; display:none;">

View File

@@ -18,6 +18,7 @@ angular.module('Application').controller('DebugController', ['$scope', '$locatio
$scope.terminalSocket = null;
$scope.lines = 10;
$scope.restartAppBusy = false;
$scope.appBusy = false;
$scope.selectedAppInfo = null;
function ab2str(buf) {
@@ -134,7 +135,7 @@ angular.module('Application').controller('DebugController', ['$scope', '$locatio
$scope.activeEventSource = null;
}
var logViewer = $('.logs-and-term-container');
var logViewer = $('#logsAndTerminalContainer');
logViewer.empty();
if ($scope.terminal) {
@@ -186,24 +187,27 @@ angular.module('Application').controller('DebugController', ['$scope', '$locatio
};
$scope.repairAppBegin = function () {
var appId = $scope.selected.value;
$scope.appBusy = true;
Client.debugApp(appId, true, function (error) {
Client.debugApp($scope.selected.value, true, function (error) {
if (error) return console.error(error);
$('#repairAppModal').modal('hide');
Client.refreshInstalledApps(function (error) {
if (error) console.error(error);
$('#repairAppModal').modal('hide');
});
});
};
$scope.repairAppDone = function () {
var appId = $scope.selected.value;
$scope.appBusy = true;
Client.debugApp(appId, false, function (error) {
Client.debugApp($scope.selected.value, false, function (error) {
if (error) return console.error(error);
Client.getApp(appId, function (error, result) {
if (error) return console.error(error);
$scope.selectedAppInfo = result;
Client.refreshInstalledApps(function (error) {
if (error) console.error(error);
});
});
};
@@ -230,7 +234,7 @@ angular.module('Application').controller('DebugController', ['$scope', '$locatio
}
// check if we want to auto scroll (this is before the appending, as that skews the check)
var tmp = $('.logs-and-term-container');
var tmp = $('#logsAndTerminalContainer');
var autoScroll = tmp[0].scrollTop > (tmp[0].scrollTopMax - 24);
var logLine = $('<div class="log-line">');
@@ -252,7 +256,7 @@ angular.module('Application').controller('DebugController', ['$scope', '$locatio
// we can only connect to apps here
if ($scope.selected.type !== 'app') {
var tmp = $('.logs-and-term-container');
var tmp = $('#logsAndTerminalContainer');
var logLine = $('<div class="log-line">');
logLine.html('Terminal is only supported for apps, not for ' + $scope.selected.name);
tmp.append(logLine);
@@ -260,40 +264,39 @@ angular.module('Application').controller('DebugController', ['$scope', '$locatio
}
// fetch current app state
Client.getApp($scope.selected.value, function (error, result) {
if (error) return console.error(error);
$scope.selectedAppInfo = result;
Client.refreshInstalledApps(function (error) {
if (error) console.error(error);
$scope.terminal = new Terminal();
$scope.terminal.open(document.querySelector('#logsAndTerminalContainer'));
$scope.terminal.fit();
try {
// websocket cannot use relative urls
var url = Client.apiOrigin.replace('https', 'wss') + '/api/v1/apps/' + $scope.selected.value + '/execws?tty=true&rows=' + $scope.terminal.rows + '&columns=' + $scope.terminal.cols + '&access_token=' + Client.getToken();
$scope.terminalSocket = new WebSocket(url);
$scope.terminal.attach($scope.terminalSocket);
$scope.terminalSocket.onclose = function () {
// retry in one second only if terminal view is still selected
$scope.terminalReconnectTimeout = setTimeout(function () {
// if the scope was already destroyed, do not reconnect
if ($scope.$$destroyed) return;
if ($scope.terminalVisible) $scope.showTerminal(true);
}, 1000);
};
// Let the browser handle paste
$scope.terminal.attachCustomKeyEventHandler(function (e) {
if (e.key === 'v' && (e.ctrlKey || e.metaKey)) return false;
});
} catch (e) {
console.error(e);
}
if (retry) $scope.terminal.writeln('Reconnecting...');
else $scope.terminal.writeln('Connecting...');
});
$scope.terminal = new Terminal();
$scope.terminal.open(document.querySelector('.logs-and-term-container'));
$scope.terminal.fit();
try {
// websocket cannot use relative urls
var url = Client.apiOrigin.replace('https', 'wss') + '/api/v1/apps/' + $scope.selected.value + '/execws?tty=true&rows=' + $scope.terminal.rows + '&columns=' + $scope.terminal.cols + '&access_token=' + Client.getToken();
$scope.terminalSocket = new WebSocket(url);
$scope.terminal.attach($scope.terminalSocket);
$scope.terminalSocket.onclose = function () {
// retry in one second only if terminal view is still selected
$scope.terminalReconnectTimeout = setTimeout(function () {
// if the scope was already destroyed, do not reconnect
if ($scope.$$destroyed) return;
if ($scope.terminalVisible) $scope.showTerminal(true);
}, 1000);
};
// Let the browser handle paste
$scope.terminal.attachCustomKeyEventHandler(function (e) {
if (e.key === 'v' && (e.ctrlKey || e.metaKey)) return false;
});
} catch (e) {
console.error(e);
}
if (retry) $scope.terminal.writeln('Reconnecting...');
else $scope.terminal.writeln('Connecting...');
};
$scope.terminalInject = function (addon) {
@@ -322,6 +325,26 @@ angular.module('Application').controller('DebugController', ['$scope', '$locatio
Client.onReady($scope.populateLogTypes);
Client.onApps(function () {
if ($scope.$$destroyed) return;
if ($scope.selected.type !== 'app') return $scope.appBusy = false;
var appId = $scope.selected.value;
Client.getApp(appId, function (error, result) {
if (error) return console.error(error);
// we expect this to be called _after_ a reconfigure was issued
if (result.installationState === 'pending_configure') {
$scope.appBusy = true;
} else if (result.installationState === 'installed') {
$scope.appBusy = false;
}
$scope.selectedAppInfo = result;
});
});
$scope.$on('$destroy', function () {
if ($scope.activeEventSource) {
$scope.activeEventSource.onmessage = function () {};
@@ -358,7 +381,7 @@ angular.module('Application').controller('DebugController', ['$scope', '$locatio
$scope.terminal.focus();
});
$('.logs-and-term-container').on('contextmenu', function (e) {
$('#logsAndTerminalContainer').on('contextmenu', function (e) {
if (!$scope.terminal) return true;
e.preventDefault();