Get the main repo page design working

This commit is contained in:
Joseph Schorr 2015-03-10 17:22:46 -07:00
parent 3d3c8ca198
commit 002dc083f2
18 changed files with 299 additions and 18 deletions

View file

@ -2537,6 +2537,26 @@ def cancel_repository_build(build, work_queue):
build.delete_instance()
return True
def get_repository_pushes(repository, time_delta):
since = date.today() - time_delta
push_repo = LogEntryKind.get(name = 'push_repo')
return (LogEntry.select()
.where(LogEntry.repository == repository)
.where(LogEntry.kind == push_repo)
.where(LogEntry.datetime >= since)
.count())
def get_repository_pulls(repository, time_delta):
since = date.today() - time_delta
repo_pull = LogEntryKind.get(name = 'pull_repo')
repo_verb = LogEntryKind.get(name = 'repo_verb')
return (LogEntry.select()
.where(LogEntry.repository == repository)
.where((LogEntry.kind == repo_pull) | (LogEntry.kind == repo_verb))
.where(LogEntry.datetime >= since)
.count())
def get_repository_usage():
one_month_ago = date.today() - timedelta(weeks=4)
repo_pull = LogEntryKind.get(name = 'pull_repo')

View file

@ -1,6 +1,7 @@
import logging
import json
import datetime
from datetime import timedelta
from flask import request
@ -213,7 +214,17 @@ class Repository(RepositoryParamResource):
'is_building': len(list(active_builds)) > 0,
'is_organization': bool(organization),
'is_starred': is_starred,
'status_token': repo.badge_token if not is_public else ''
'status_token': repo.badge_token if not is_public else '',
'stats': {
'pulls': {
'today': model.get_repository_pulls(repo, timedelta(days=1)),
'thirty_day': model.get_repository_pulls(repo, timedelta(days=30))
},
'pushes': {
'today': model.get_repository_pushes(repo, timedelta(days=1)),
'thirty_day': model.get_repository_pushes(repo, timedelta(days=30))
}
}
}
raise NotFound()

View file

@ -86,7 +86,7 @@
width: 100%;
display: table-cell;
float: none;
padding: 20px;
padding: 30px;
}
.co-tabs li {

View file

@ -0,0 +1,63 @@
.repo-panel-info-element .stat-col {
border-right: 2px solid #eee;
}
.repo-panel-info-element .stat-title {
text-align: center;
display: block;
font-size: 20px;
margin-bottom: 10px;
}
.repo-panel-info-element .stat {
text-align: center;
margin-bottom: 20px;
}
.repo-panel-info-element .stat .stat-value {
font-size: 46px;
}
.repo-panel-info-element .stat .stat-subtitle {
font-size: 12px;
color: #ccc;
text-transform: uppercase;
}
.repo-panel-info-element .description-container {
margin-top: 30px;
border-top: 2px solid #eee;
padding-top: 18px;
}
.repo-panel-info-element .description {
padding-bottom: 0px;
position: relative;
}
.repo-panel-info-element .description p {
font-size: 16px !important;
}
.repo-panel-info-element .description-container h4:before {
content: "\f02d";
color: #black;
font-size: 20px;
font-family: FontAwesome;
margin-right: 6px;
}
.repo-panel-info-element .description .fa-edit {
display: none;
}
.repo-panel-info-element .build-mini-status {
margin-top: 10px;
margin-bottom: 10px;
}
.repo-panel-info-element .view-all {
display: block;
padding: 10px;
text-align: center;
}

View file

@ -31,4 +31,8 @@
.build-info-bar-element .build-side-info .timing {
text-align: right;
}
.build-info-bar-element .source-commit-link {
margin-left: 4px;
}

View file

@ -0,0 +1,53 @@
.build-mini-status {
display: block;
padding: 4px;
position: relative;
border: 1px solid #eee;
}
.build-mini-status-element {
color: black;
text-decoration: none !important;
}
.build-mini-status .build-status-icon {
width: 42px;
padding: 4px;
text-align: center;
display: inline-block;
font-size: 18px;
}
.build-mini-status .timing {
display: inline-block;
margin-left: 30px;
margin-right: 20px;
}
.build-mini-status .timing .fa {
display: inline-block;
margin-right: 4px;
}
.build-mini-status .build-description {
position: absolute;
top: 4px;
right: 4px;
left: 250px;
bottom: 4px;
line-height: 33px;
overflow: hidden;
text-overflow: ellipsis;
}
.build-mini-status .build-status-icon.error {
color: red;
}
.build-mini-status .build-status-icon.internalerror {
color: #DFFF00;
}
.build-mini-status .build-status-icon.complete {
color: #2fcc66;
}

View file

@ -5,7 +5,7 @@
<!-- Side information -->
<div class="build-side-info">
<!-- Build ID -->
<div class="build-side-id">{{ build.id }}</div>
<div class="build-side-id" ng-if="!hideId">{{ build.id }}</div>
<!-- Timing -->
<div class="timing" ng-if="showTime">

View file

@ -0,0 +1,18 @@
<a class="build-mini-status-element" href="/repository/{{ build.repository.namespace }}/{{ build.repository.name }}/build/{{ build.id }}">
<div>
<span class="build-status-icon" ng-class="build.phase">
<span class="cor-loader-inline" ng-if="isBuilding(build)"></span>
<span ng-if="!isBuilding(build)">
<i class="fa fa-check-circle" ng-if="build.phase == 'complete'"></i>
<i class="fa fa-times-circle" ng-if="build.phase == 'error'"></i>
<i class="fa fa-exclamation-circle" ng-if="build.phase == 'internalerror'"></i>
</span>
</span>
<span class="timing">
<i class="fa fa-clock-o"></i><span am-time-ago="build.started || 0"></span>
</span>
<div class="build-description triggered-build-description" build="build" ng-if="build.trigger"></div>
<div class="build-description" ng-if="!build.trigger">Manually Started Build</div>
</div>
</a>

View file

@ -1,3 +1,4 @@
<!-- NOTE: DEPRECATED -->
<div id="build-status-container" class="build-status-container">
<div>
<span class="phase-icon" ng-class="build.phase"></span>

View file

@ -1,3 +1,3 @@
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-6">
<div class="col-lg-3 col-md-3 col-sm-3 col-xs-1">
<span class="co-nav-title-action co-fx-text-shadow" ng-transclude></span>
</div>

View file

@ -1,7 +1,7 @@
<div class="markdown-input-container">
<p ng-class="'lead ' + (canWrite ? 'editable' : 'noteditable')" ng-click="editContent()">
<span class="markdown-view" content="content"></span>
<span class="empty" ng-show="!content && canWrite">(Click to set {{ fieldTitle }})</span>
<span class="empty" ng-show="!content && canWrite">Click to set {{ fieldTitle }}</span>
<i class="fa fa-edit"></i>
</p>

View file

@ -1,9 +1,72 @@
<div class="repo-panel-info-element">
<!-- Repository Description -->
<div class="description markdown-input"
content="repository.description"
can-write="repository.can_write"
content-changed="updateDescription"
field-title="'repository description'">
</div>
<!-- Repository stats and builds summary -->
<div class="repository-stats row">
<!-- Pull Stats -->
<div class="col-sm-3 stat-col">
<div class="stat-title">Repo Pulls</div>
<div class="stat">
<div class="stat-value">{{ repository.stats.pulls.today }}</div>
<div class="stat-subtitle">Last 24 hours</div>
</div>
<div class="stat">
<div class="stat-value">{{ repository.stats.pulls.thirty_day }}</div>
<div class="stat-subtitle">Last 30 days</div>
</div>
</div>
<!-- Push Stats -->
<div class="col-sm-3 stat-col">
<div class="stat-title">Repo Pushes</div>
<div class="stat">
<div class="stat-value">{{ repository.stats.pushes.today }}</div>
<div class="stat-subtitle">Last 24 hours</div>
</div>
<div class="stat">
<div class="stat-value">{{ repository.stats.pushes.thirty_day }}</div>
<div class="stat-subtitle">Last 30 days</div>
</div>
</div>
<!-- Builds -->
<div class="col-sm-6">
<div class="stat-title">Recent Repo Builds</div>
<!-- Loading -->
<div class="cor-loader" ng-if="!builds"></div>
<!-- No Builds -->
<div class="empty" ng-if="builds && !builds.length">
<div class="empty-primary-msg">No builds have been run for this repository.</div>
<div class="empty-secondary-msg" ng-if="repository.can_admin">
Click on the <i class="fa fa-tasks" style="margin-left: 6px"></i> Builds tab to start a new build.
</div>
</div>
<!-- Builds -->
<div ng-if="builds && builds.length">
<div class="build-mini-status" ng-repeat="build in builds" build="build"></div>
</div>
<!-- View All -->
<a href="/repository/{{ repository.namespace }}/{{ repository.name }}?tab=builds"
class="view-all" ng-if="repository.can_admin && builds.length">
View Build History
</a>
</div>
</div>
<!-- Repository Description -->
<div class="description-container">
<h4 style="font-size:20px;">Description</h4>
<div class="description markdown-input"
content="repository.description"
can-write="repository.can_write"
content-changed="updateDescription"
field-title="'repository description'">
</div>
</div>
</div>

View file

@ -9,7 +9,8 @@ angular.module('quay').directive('repoPanelInfo', function () {
transclude: false,
restrict: 'C',
scope: {
'repository': '=repository'
'repository': '=repository',
'builds': '=builds'
},
controller: function($scope, $element, ApiService) {
$scope.updateDescription = function(content) {

View file

@ -10,7 +10,8 @@ angular.module('quay').directive('buildInfoBar', function () {
restrict: 'C',
scope: {
'build': '=build',
'showTime': '=showTime'
'showTime': '=showTime',
'hideId': '=hideId'
},
controller: function($scope, $element) {
}

View file

@ -0,0 +1,22 @@
/**
* An element which displays the status of a build as a mini-bar.
*/
angular.module('quay').directive('buildMiniStatus', function () {
var directiveDefinitionObject = {
priority: 0,
templateUrl: '/static/directives/build-mini-status.html',
replace: false,
transclude: false,
restrict: 'C',
scope: {
'build': '=build'
},
controller: function($scope, $element) {
$scope.isBuilding = function(build) {
if (!build) { return true; }
return build.phase != 'complete' && build.phase != 'error';
};
}
};
return directiveDefinitionObject;
});

View file

@ -1,5 +1,5 @@
/**
* An element which displays the status of a build.
* DEPRECATED: An element which displays the status of a build.
*/
angular.module('quay').directive('buildStatus', function () {
var directiveDefinitionObject = {

View file

@ -13,12 +13,14 @@
}, ['old-layout']);
}]);
function RepoViewCtrl($scope, $routeParams, ApiService, UserService) {
function RepoViewCtrl($scope, $routeParams, ApiService, UserService, AngularPollChannel) {
$scope.namespace = $routeParams.namespace;
$scope.name = $routeParams.name;
$scope.logsShown = 0;
var buildPollChannel = null;
// Make sure we track the current user.
UserService.updateUserIn($scope);
@ -30,12 +32,32 @@
$scope.repositoryResource = ApiService.getRepoAsResource(params).get(function(repo) {
$scope.repository = repo;
$scope.setTag($routeParams.tag);
// Track builds.
buildPollChannel = AngularPollChannel.create($scope, loadRepositoryBuilds, 5000 /* 5s */);
buildPollChannel.start();
});
};
var loadRepositoryBuilds = function(callback) {
var params = {
'repository': $scope.namespace + '/' + $scope.name
};
var errorHandler = function() {
callback(false);
};
$scope.repositoryBuildsResource = ApiService.getRepoBuildsAsResource(params, /* background */true).get(function(resp) {
$scope.builds = resp.builds;
callback(false);
}, errorHandler);
};
// Load the repository.
loadRepository();
$scope.setTag = function(tagName) {
window.console.log('set tag')
};

View file

@ -1,4 +1,6 @@
<div class="resource-view repository-view" resource="repositoryResource" error-message="'Repository not found'">
<div class="resource-view repository-view"
resource="repositoryResource"
error-message="'Repository not found'">
<div class="page-content">
<div class="cor-title">
<span class="cor-title-link"></span>
@ -42,7 +44,7 @@
<div class="cor-tab-content">
<!-- Information -->
<div id="info" class="tab-pane active">
<div class="repo-panel-info" repository="repository"></div>
<div class="repo-panel-info" repository="repository" builds="builds"></div>
</div>
<!-- Tags -->