Start on builds page for repos

This commit is contained in:
Joseph Schorr 2014-02-10 15:15:23 -05:00
parent 9e8f765040
commit 35cfdcaa8c
8 changed files with 192 additions and 39 deletions

View file

@ -524,7 +524,7 @@ i.toggle-icon:hover {
border-bottom: 1px solid #eee;
}
.build-info:hover {
.build-info.clickable:hover {
background: rgba(66, 139, 202, 0.2);
cursor: pointer;
border-radius: 4px;
@ -535,33 +535,36 @@ i.toggle-icon:hover {
border-bottom: 0px;
}
.build-status .phase-icon {
.phase-icon {
border-radius: 50%;
display: inline-block;
width: 12px;
height: 12px;
margin-right: 6px;
}
.build-status .phase-icon {
margin-top: 4px;
float: left;
}
.build-status .phase-icon.error {
.phase-icon.error {
background-color: red;
}
.build-status .phase-icon.waiting, .build-status .phase-icon.starting, .build-status .phase-icon.initializing {
.phase-icon.waiting, .phase-icon.starting, .phase-icon.initializing {
background-color: #ddd;
}
.build-status .phase-icon.building {
.phase-icon.building {
background-color: #f0ad4e;
}
.build-status .phase-icon.pushing {
.phase-icon.pushing {
background-color: #5cb85c;
}
.build-status .phase-icon.complete {
.phase-icon.complete {
background-color: #428bca;
}

View file

@ -0,0 +1 @@
<span class="build-message-element">{{ getBuildMessage(build) }}</span>

View file

@ -0,0 +1,6 @@
<div class="build-progress-element">
<div class="progress" ng-class="getPercentage(build) < 100 ? 'active progress-striped' : ''" ng-show="getPercentage(build) > 0 && getPercentage(build) < 100">
<div class="progress-bar" role="progressbar" aria-valuenow="{{ getPercentage(build) }}" aria-valuemin="0" aria-valuemax="100" style="{{ 'width: ' + getPercentage(build) + '%' }}">
</div>
</div>
</div>

View file

@ -1,14 +1,11 @@
<div id="build-status-container" class="build-status-container">
<div>
<span class="phase-icon" ng-class="build.phase"></span>
<span class="build-message">{{ getBuildMessage(build) }}</span>
<span class="build-message" build="build"></span>
</div>
<div class="timing">
<i class="fa fa-clock-o"></i>
Started: <span am-time-ago="build.started || 0"></span>
</div>
<div class="progress" ng-class="getBuildProgress(build) < 100 ? 'active progress-striped' : ''" ng-show="getBuildProgress(build) > 0 && getBuildProgress(build) < 100">
<div class="progress-bar" role="progressbar" aria-valuenow="{{ getBuildProgress(build) }}" aria-valuemin="0" aria-valuemax="100" style="{{ 'width: ' + getBuildProgress(build) + '%' }}">
</div>
</div>
<div class="build-progress" build="build"></div>
</div>

View file

@ -774,6 +774,7 @@ quayApp = angular.module('quay', ['ngRoute', 'chieffancypants.loadingBar', 'rest
fixFooter: false}).
when('/repository/:namespace/:name/image/:image', {templateUrl: '/static/partials/image-view.html', controller: ImageViewCtrl, reloadOnSearch: false}).
when('/repository/:namespace/:name/admin', {templateUrl: '/static/partials/repo-admin.html', controller:RepoAdminCtrl, reloadOnSearch: false}).
when('/repository/:namespace/:name/build', {templateUrl: '/static/partials/repo-build.html', controller:RepoBuildCtrl, reloadOnSearch: false}).
when('/repository/', {title: 'Repositories', description: 'Public and private docker repositories list',
templateUrl: '/static/partials/repo-list.html', controller: RepoListCtrl}).
when('/user/', {title: 'Account Settings', description:'Account settings for Quay.io', templateUrl: '/static/partials/user-admin.html',
@ -2474,7 +2475,63 @@ quayApp.directive('buildStatus', function () {
'build': '=build'
},
controller: function($scope, $element) {
$scope.getBuildProgress = function(buildInfo) {
}
};
return directiveDefinitionObject;
});
quayApp.directive('buildMessage', function () {
var directiveDefinitionObject = {
priority: 0,
templateUrl: '/static/directives/build-message.html',
replace: false,
transclude: false,
restrict: 'C',
scope: {
'build': '=build'
},
controller: function($scope, $element) {
$scope.getBuildMessage = function (buildInfo) {
switch (buildInfo.phase) {
case 'starting':
case 'initializing':
return 'Starting Dockerfile build';
case 'waiting':
return 'Waiting for available build worker.';
case 'building':
return 'Building image from Dockerfile';
case 'pushing':
return 'Pushing image built from Dockerfile';
case 'complete':
return 'Dockerfile build completed and pushed';
case 'error':
return 'Dockerfile build failed.';
}
};
}
};
return directiveDefinitionObject;
});
quayApp.directive('buildProgress', function () {
var directiveDefinitionObject = {
priority: 0,
templateUrl: '/static/directives/build-progress.html',
replace: false,
transclude: false,
restrict: 'C',
scope: {
'build': '=build'
},
controller: function($scope, $element) {
$scope.getPercentage = function(buildInfo) {
switch (buildInfo.phase) {
case 'building':
return (buildInfo.status.current_command / buildInfo.status.total_commands) * 100;
@ -2497,29 +2554,6 @@ quayApp.directive('buildStatus', function () {
return -1;
};
$scope.getBuildMessage = function(buildInfo) {
switch (buildInfo.phase) {
case 'starting':
case 'initializing':
return 'Starting Dockerfile build';
case 'waiting':
return 'Waiting for available build worker.';
case 'building':
return 'Building image from Dockerfile';
case 'pushing':
return 'Pushing image built from Dockerfile';
case 'complete':
return 'Dockerfile build completed and pushed';
case 'error':
return 'Dockerfile build failed.';
}
};
}
};
return directiveDefinitionObject;

View file

@ -197,6 +197,11 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi
$scope.getFormattedCommand = ImageMetadataService.getFormattedCommand;
$scope.showBuild = function(buildInfo) {
$location.path('/repository/' + namespace + '/' + name + '/build');
$location.search('current', buildInfo.id);
};
$scope.getTooltipCommand = function(image) {
var sanitized = ImageMetadataService.getEscapedFormattedCommand(image);
return '<span class=\'codetooltip\'>' + sanitized + '</span>';
@ -616,6 +621,69 @@ function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiServi
loadViewInfo();
}
function RepoBuildCtrl($scope, Restangular, ApiService, $routeParams, $rootScope, $location) {
var namespace = $routeParams.namespace;
var name = $routeParams.name;
// Watch for changes to the current parameter.
$scope.$on('$routeUpdate', function(){
if ($location.search().current) {
$scope.setCurrentBuild($location.search().current, false);
}
});
$scope.builds = [];
$scope.getShortId = function(id) {
var lastIndex = id.lastIndexOf('-');
return id.substr(lastIndex + 1);
};
$scope.setCurrentBuild = function(buildId, opt_updateURL) {
// Find the build.
for (var i = 0; i < $scope.builds.length; ++i) {
if ($scope.builds[i].id == buildId) {
$scope.setCurrentBuildInternal($scope.builds[i], opt_updateURL);
return;
}
}
};
$scope.setCurrentBuildInternal = function(build, opt_updateURL) {
$scope.currentBuild = build;
if (opt_updateURL) {
$location.search('current', build.id);
}
};
var fetchRepository = function() {
var params = {'repository': namespace + '/' + name};
$rootScope.title = 'Loading Repository...';
$scope.repository = ApiService.getRepoAsResource(params).get(function(repo) {
$scope.repo = repo;
getBuildInfo();
});
};
var getBuildInfo = function(repo) {
// Note: We use restangular manually here because we need to turn off the loading bar.
var buildInfo = Restangular.one('repository/' + namespace + '/' + name + '/build/');
buildInfo.withHttpConfig({
'ignoreLoadingBar': true
});
buildInfo.get().then(function(resp) {
$scope.builds = resp.builds;
if ($location.search().current) {
$scope.setCurrentBuild($location.search().current, false);
}
});
};
fetchRepository();
}
function RepoAdminCtrl($scope, Restangular, ApiService, $routeParams, $rootScope) {
var namespace = $routeParams.namespace;
var name = $routeParams.name;

View file

@ -0,0 +1,44 @@
<div class="resource-view" resource="repository" error-message="'No repository found'"></div>
<div class="container repo repo-build" ng-show="repo && !deleting">
<div class="header row">
<a href="{{ '/repository/' + repo.namespace + '/' + repo.name }}" class="back"><i class="fa fa-chevron-left"></i></a>
<h3>
<span class="repo-circle no-background" repo="repo"></span>
<span class="repo-breadcrumb" repo="repo"></span>
</h3>
</div>
<div class="row" ng-show="!repo.is_building">
There are no active builds for this repository
</div>
<div class="row" ng-show="repo.is_building">
<!-- Side tabs -->
<div class="col-md-2">
<ul class="nav nav-pills nav-stacked">
<li ng-class="currentBuild == build ? 'active' : ''" ng-repeat="build in builds">
<a href="javascript:void(0)" ng-click="setCurrentBuild(build.id, true)">
<span class="phase-icon" ng-class="build.phase"></span>
<span>{{ getShortId(build.id) }}</span>
</a>
</li>
</ul>
</div>
<!-- Content -->
<div class="col-md-10">
<div class="tab-content">
<div ng-repeat="build in builds" class="tab-pane" ng-class="currentBuild == build ? 'active' : ''">
<div>{{ build.id }}</div>
<div>
<span class="phase-icon" ng-class="build.phase"></span>
<span class="build-message" build="build"></span>
<div class="build-progress" build="build"></div>
</div>
</div>
</div>
</div>
</div>
</div>

View file

@ -42,14 +42,14 @@
<div class="dropdown" data-placement="top">
<span class="count" ng-class="buildsInfo ? 'visible' : ''"><span>{{ buildsInfo ? buildsInfo.length : '-' }}</span></span>
<a href="javascript:void(0)" class="dropdown-toggle" data-toggle="dropdown">Building Dockerfile<span ng-show="buildsInfo.length > 1">s</span> <b class="caret"></b></a>
<ul class="dropdown-menu pull-right">
<ul class="dropdown-menu pull-right">
<li ng-repeat="buildInfo in buildsInfo">
<div class="build-info">
<div class="build-info" ng-class="repo.can_write ? 'clickable' : ''" ng-click="showBuild(buildInfo)">
<span class="build-status" build="buildInfo"></span>
</div>
</li>
</ul>
</div>
</div>
</div>
</div>