Start on the new build view
This commit is contained in:
parent
5cc1c90021
commit
e227d7e526
30 changed files with 816 additions and 11 deletions
139
static/js/directives/ui/build-logs-view.js
Normal file
139
static/js/directives/ui/build-logs-view.js
Normal file
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* An element which displays and auto-updates the logs from a build.
|
||||
*/
|
||||
angular.module('quay').directive('buildLogsView', function () {
|
||||
var directiveDefinitionObject = {
|
||||
priority: 0,
|
||||
templateUrl: '/static/directives/build-logs-view.html',
|
||||
replace: false,
|
||||
transclude: false,
|
||||
restrict: 'C',
|
||||
scope: {
|
||||
'build': '=build',
|
||||
'buildUpdated': '&buildUpdated'
|
||||
},
|
||||
controller: function($scope, $element, $interval, $sanitize, ansi2html, AngularViewArray,
|
||||
AngularPollChannel, ApiService, Restangular) {
|
||||
|
||||
$scope.logEntries = null;
|
||||
$scope.currentParentEntry = null;
|
||||
$scope.logStartIndex = 0;
|
||||
|
||||
var pollChannel = null;
|
||||
var currentBuild = null;
|
||||
|
||||
var processLogs = function(logs, startIndex, endIndex) {
|
||||
if (!$scope.logEntries) { $scope.logEntries = []; }
|
||||
|
||||
// If the start index given is less than that requested, then we've received a larger
|
||||
// pool of logs, and we need to only consider the new ones.
|
||||
if (startIndex < $scope.logStartIndex) {
|
||||
logs = logs.slice($scope.logStartIndex - startIndex);
|
||||
}
|
||||
|
||||
for (var i = 0; i < logs.length; ++i) {
|
||||
var entry = logs[i];
|
||||
var type = entry['type'] || 'entry';
|
||||
if (type == 'command' || type == 'phase' || type == 'error') {
|
||||
entry['logs'] = AngularViewArray.create();
|
||||
entry['index'] = $scope.logStartIndex + i;
|
||||
|
||||
$scope.logEntries.push(entry);
|
||||
$scope.currentParentEntry = entry;
|
||||
} else if ($scope.currentParentEntry) {
|
||||
$scope.currentParentEntry['logs'].push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
return endIndex;
|
||||
};
|
||||
|
||||
var getBuildStatusAndLogs = function(build, callback) {
|
||||
var params = {
|
||||
'repository': build.repository.namespace + '/' + build.repository.name,
|
||||
'build_uuid': build.id
|
||||
};
|
||||
|
||||
ApiService.getRepoBuildStatus(null, params, true).then(function(resp) {
|
||||
if (resp.id != $scope.build.id) { callback(false); return; }
|
||||
|
||||
// Call the build updated handler.
|
||||
$scope.buildUpdated({'build': resp});
|
||||
|
||||
// Save the current build.
|
||||
currentBuild = resp;
|
||||
|
||||
// Load the updated logs for the build.
|
||||
var options = {
|
||||
'start': $scope.logStartIndex
|
||||
};
|
||||
|
||||
ApiService.getRepoBuildLogsAsResource(params, true).withOptions(options).get(function(resp) {
|
||||
// Process the logs we've received.
|
||||
$scope.logStartIndex = processLogs(resp['logs'], resp['start'], resp['total']);
|
||||
|
||||
// If the build status is an error, open the last two log entries.
|
||||
if (currentBuild['phase'] == 'error' && $scope.logEntries.length > 1) {
|
||||
var openLogEntries = function(entry) {
|
||||
if (entry.logs) {
|
||||
entry.logs.setVisible(true);
|
||||
}
|
||||
};
|
||||
|
||||
openLogEntries($scope.logEntries[$scope.logEntries.length - 2]);
|
||||
openLogEntries($scope.logEntries[$scope.logEntries.length - 1]);
|
||||
}
|
||||
|
||||
// If the build phase is an error or a complete, then we mark the channel
|
||||
// as closed.
|
||||
callback(currentBuild['phase'] != 'error' && currentBuild['phase'] != 'complete');
|
||||
}, function() {
|
||||
callback(false);
|
||||
});
|
||||
}, function() {
|
||||
callback(false);
|
||||
});
|
||||
};
|
||||
|
||||
var startWatching = function(build) {
|
||||
// Create a new channel for polling the build status and logs.
|
||||
var conductStatusAndLogRequest = function(callback) {
|
||||
getBuildStatusAndLogs(build, callback);
|
||||
};
|
||||
|
||||
pollChannel = AngularPollChannel.create($scope, conductStatusAndLogRequest, 5 * 1000 /* 5s */);
|
||||
pollChannel.start();
|
||||
};
|
||||
|
||||
var stopWatching = function() {
|
||||
if (pollChannel) {
|
||||
pollChannel.stop();
|
||||
pollChannel = null;
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$watch('build', function(build) {
|
||||
if (build) {
|
||||
startWatching(build);
|
||||
} else {
|
||||
stopWatching();
|
||||
}
|
||||
});
|
||||
|
||||
$scope.hasLogs = function(container) {
|
||||
return container.logs.hasEntries;
|
||||
};
|
||||
|
||||
$scope.processANSI = function(message, container) {
|
||||
var filter = container.logs._filter = (container.logs._filter || ansi2html.create());
|
||||
|
||||
// Note: order is important here.
|
||||
var setup = filter.getSetupHtml();
|
||||
var stream = filter.addInputToStream(message);
|
||||
var teardown = filter.getTeardownHtml();
|
||||
return setup + stream + teardown;
|
||||
};
|
||||
}
|
||||
};
|
||||
return directiveDefinitionObject;
|
||||
});
|
Reference in a new issue