diff --git a/static/js/app.js b/static/js/app.js
index 69ee8e886..5fa2993d7 100644
--- a/static/js/app.js
+++ b/static/js/app.js
@@ -2476,6 +2476,119 @@ quayApp.directive('namespaceSelector', function () {
});
+quayApp.directive('buildLogPhase', function () {
+ var directiveDefinitionObject = {
+ priority: 0,
+ templateUrl: '/static/directives/build-log-phase.html',
+ replace: false,
+ transclude: false,
+ restrict: 'C',
+ scope: {
+ 'phase': '=phase'
+ },
+ controller: function($scope, $element) {
+ }
+ };
+ return directiveDefinitionObject;
+});
+
+
+quayApp.directive('buildLogError', function () {
+ var directiveDefinitionObject = {
+ priority: 0,
+ templateUrl: '/static/directives/build-log-error.html',
+ replace: false,
+ transclude: false,
+ restrict: 'C',
+ scope: {
+ 'error': '=error'
+ },
+ controller: function($scope, $element) {
+ }
+ };
+ return directiveDefinitionObject;
+});
+
+
+quayApp.directive('buildLogCommand', function () {
+ var directiveDefinitionObject = {
+ priority: 0,
+ templateUrl: '/static/directives/build-log-command.html',
+ replace: false,
+ transclude: false,
+ restrict: 'C',
+ scope: {
+ 'command': '=command'
+ },
+ controller: function($scope, $element, $sanitize) {
+ var registryHandlers = {
+ 'quay.io': function(pieces) {
+ var rnamespace = pieces[pieces.length - 2];
+ var rname = pieces[pieces.length - 1];
+ return '/repository/' + rnamespace + '/' + rname + '/';
+ },
+
+ '': function(pieces) {
+ var rnamespace = pieces.length == 1 ? '_' : pieces[0];
+ var rname = pieces[pieces.length - 1];
+ return 'https://index.docker.io/' + rnamespace + '/' + rname + '/';
+ }
+ };
+
+ var kindHandlers = {
+ 'FROM': function(title) {
+ var pieces = title.split('/');
+ var registry = pieces.length < 2 ? '' : pieces[0];
+ if (!registryHandlers[registry]) {
+ return title;
+ }
+
+ return '
' + title + '';
+ }
+ };
+
+ $scope.getCommandKind = function(fullTitle) {
+ var colon = fullTitle.indexOf(':');
+ var title = getTitleWithoutStep(fullTitle);
+ if (!title) {
+ return null;
+ }
+
+ var space = title.indexOf(' ');
+ return title.substring(0, space);
+ };
+
+ $scope.getCommandTitleHtml = function(fullTitle) {
+ var title = getTitleWithoutStep(fullTitle) || fullTitle;
+ var space = title.indexOf(' ');
+ if (space <= 0) {
+ return $sanitize(title);
+ }
+
+ var kind = $scope.getCommandKind(fullTitle);
+ var sanitized = $sanitize(title.substring(space + 1));
+
+ var handler = kindHandlers[kind || ''];
+ if (handler) {
+ return handler(sanitized);
+ } else {
+ return sanitized;
+ }
+ };
+
+ var getTitleWithoutStep = function(fullTitle) {
+ var colon = fullTitle.indexOf(':');
+ if (colon <= 0) {
+ return null;
+ }
+
+ return $.trim(fullTitle.substring(colon + 1));
+ };
+ }
+ };
+ return directiveDefinitionObject;
+});
+
quayApp.directive('buildStatus', function () {
var directiveDefinitionObject = {
priority: 0,
@@ -2501,17 +2614,17 @@ quayApp.directive('buildMessage', function () {
transclude: false,
restrict: 'C',
scope: {
- 'build': '=build'
+ 'phase': '=phase'
},
controller: function($scope, $element) {
- $scope.getBuildMessage = function (buildInfo) {
- switch (buildInfo.phase) {
+ $scope.getBuildMessage = function (phase) {
+ switch (phase) {
case 'starting':
case 'initializing':
return 'Starting Dockerfile build';
case 'waiting':
- return 'Waiting for available build worker.';
+ return 'Waiting for available build worker';
case 'building':
return 'Building image from Dockerfile';
@@ -2523,7 +2636,7 @@ quayApp.directive('buildMessage', function () {
return 'Dockerfile build completed and pushed';
case 'error':
- return 'Dockerfile build failed.';
+ return 'Dockerfile build failed';
}
};
}
diff --git a/static/js/controllers.js b/static/js/controllers.js
index 0f8682c91..1dbade8eb 100644
--- a/static/js/controllers.js
+++ b/static/js/controllers.js
@@ -624,32 +624,6 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
var name = $routeParams.name;
var pollTimerHandle = null;
- var registryHandlers = {
- 'quay.io': function(pieces) {
- var rnamespace = pieces[pieces.length - 2];
- var rname = pieces[pieces.length - 1];
- return '/repository/' + rnamespace + '/' + rname + '/';
- },
-
- '': function(pieces) {
- var rnamespace = pieces.length == 1 ? '_' : pieces[0];
- var rname = pieces[pieces.length - 1];
- return 'https://index.docker.io/' + rnamespace + '/' + rname + '/';
- }
- };
-
- var kindHandlers = {
- 'FROM': function(title) {
- var pieces = title.split('/');
- var registry = pieces.length < 2 ? '' : pieces[0];
- if (!registryHandlers[registry]) {
- return title;
- }
-
- return '
' + title + '';
- }
- };
-
$scope.$on('$destroy', function() {
stopPollTimer();
});
@@ -668,43 +642,19 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
$('.build-logs').height($(window).height() - 365);
};
- $scope.getCommandKind = function(fullTitle) {
- var colon = fullTitle.indexOf(':');
- var title = getTitleWithoutStep(fullTitle);
- if (!title) {
- return null;
- }
-
- var space = title.indexOf(' ');
- return title.substring(0, space);
+ $scope.hasLogs = function(container) {
+ return ((container.logs && container.logs.length) || (container._logs && container._logs.length));
};
- $scope.getCommandTitleHtml = function(fullTitle) {
- var title = getTitleWithoutStep(fullTitle) || fullTitle;
- var space = title.indexOf(' ');
- if (space <= 0) {
- return $sanitize(title);
- }
-
- var kind = $scope.getCommandKind(fullTitle);
- var sanitized = $sanitize(title.substring(space + 1));
-
- var handler = kindHandlers[kind || ''];
- if (handler) {
- return handler(sanitized);
+ $scope.toggleLogs = function(container) {
+ if (container._logs) {
+ container.logs = container._logs;
+ container._logs = null;
} else {
- return sanitized;
+ container._logs = container.logs;
+ container.logs = null;
}
- };
-
- $scope.toggleCommand = function(command) {
- command.expanded = !command.expanded;
-
- if (command.expanded && !command.logs) {
- // Load the logs for the command.
- loadCommandLogs(command);
- }
- };
+ };
$scope.setCurrentBuild = function(buildId, opt_updateURL) {
// Find the build.
@@ -721,10 +671,10 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
stopPollTimer();
- $scope.commands = null;
- $scope.commandMap = {};
- $scope.logs = null;
+ $scope.logEntries = null;
$scope.logStartIndex = null;
+ $scope.currentParentEntry = null;
+
$scope.currentBuild = build;
if (opt_updateURL) {
@@ -748,15 +698,6 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
checkPollTimer();
};
- var getTitleWithoutStep = function(fullTitle) {
- var colon = fullTitle.indexOf(':');
- if (colon <= 0) {
- return null;
- }
-
- return $.trim(fullTitle.substring(colon + 1));
- }
-
var checkPollTimer = function() {
var build = $scope.currentBuild;
if (!build) {
@@ -783,65 +724,25 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
};
var processLogs = function(logs, startIndex) {
- var currentCommand = $scope.commands.length > 0 ? $scope.commands[$scope.commands.length - 1] : null;
+ if (!$scope.logEntries) { $scope.logEntries = []; }
+
for (var i = 0; i < logs.length; ++i) {
var entry = logs[i];
- if (entry['is_command']) {
- var index = startIndex + i;
- var existing = $scope.commandMap[index];
- if (existing) {
- currentCommand = existing;
- continue;
+ var type = entry['type'] || 'entry';
+ if (type == 'command' || type == 'phase' || type == 'error') {
+ entry['_logs'] = [];
+ entry['index'] = startIndex + i;
+
+ $scope.logEntries.push(entry);
+ $scope.currentParentEntry = entry;
+ } else if ($scope.currentParentEntry) {
+ if ($scope.currentParentEntry['logs']) {
+ $scope.currentParentEntry['logs'].push(entry);
+ } else {
+ $scope.currentParentEntry['_logs'].push(entry);
}
-
- currentCommand = {
- 'message': entry['message'],
- 'index': index
- };
- $scope.commands.push(currentCommand);
- $scope.commandMap[index] = currentCommand;
- continue;
}
-
- if (!currentCommand.logs) {
- currentCommand.logs = [];
- }
- currentCommand.logs.push(entry);
}
-
- if (currentCommand.expanded == null) {
- currentCommand.expanded = true;
- }
- };
-
- var loadCommandLogs = function(command) {
- var start = command['index'] + 1;
- var end = null;
-
- var currentCommandIndex = jQuery.inArray(command, $scope.commands);
- if (currentCommandIndex >= 0 && currentCommandIndex < $scope.commands.length - 1) {
- var nextCommand = $scope.commands[currentCommandIndex + 1];
- end = nextCommand.index ? nextCommand.index - 1 : null;
- }
-
- var params = {
- 'repository': namespace + '/' + name,
- 'build_uuid': $scope.currentBuild.id
- };
-
- var options = {
- 'start': start
- };
-
- if (end != null) {
- options['end'] = end;
- }
-
- ApiService.getRepoBuildLogsAsResource(params, true).withOptions(options).get(function(resp) {
- if (resp['logs']) {
- command.logs = resp['logs'];
- }
- });
};
var getBuildStatusAndLogs = function() {
@@ -862,20 +763,10 @@ function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope
// Load the updated logs for the build.
var options = {
- 'commands': $scope.commands == null,
'start': $scope.logStartIndex
};
- ApiService.getRepoBuildLogsAsResource(params, true).withOptions(options).get(function(resp) {
- if (resp['commands']) {
- $scope.commands = resp['commands'];
-
- // Add the commands to the map.
- for (var i = 0; i < $scope.commands.length; ++i) {
- var command = $scope.commands[i];
- $scope.commandMap[command['index']] = command;
- }
- }
+ ApiService.getRepoBuildLogsAsResource(params, true).withOptions(options).get(function(resp) {
processLogs(resp['logs'], resp['start']);
$scope.logStartIndex = resp['total'];
$scope.polling = false;
diff --git a/static/partials/repo-build.html b/static/partials/repo-build.html
index 828ce5797..7037363e7 100644
--- a/static/partials/repo-build.html
+++ b/static/partials/repo-build.html
@@ -8,11 +8,11 @@