Initial redesigned UI for repo listings w/ stars.
This commit is contained in:
parent
97b605ca8d
commit
5a484cfe11
10 changed files with 308 additions and 103 deletions
|
@ -778,9 +778,9 @@ def get_visible_repository_count(username=None, include_public=True,
|
|||
|
||||
|
||||
def get_visible_repositories(username=None, include_public=True, page=None,
|
||||
limit=None, sort=False, namespace=None):
|
||||
limit=None, sort=False, namespace=None, include_starred=True):
|
||||
query = _visible_repository_query(username=username, include_public=include_public, page=page,
|
||||
limit=limit, namespace=namespace,
|
||||
limit=limit, namespace=namespace, include_starred=include_starred,
|
||||
select_models=[Repository, Namespace, Visibility])
|
||||
|
||||
if sort:
|
||||
|
@ -793,7 +793,7 @@ def get_visible_repositories(username=None, include_public=True, page=None,
|
|||
|
||||
|
||||
def _visible_repository_query(username=None, include_public=True, limit=None,
|
||||
page=None, namespace=None, select_models=[]):
|
||||
page=None, namespace=None, include_starred=True, select_models=[]):
|
||||
query = (Repository
|
||||
.select(*select_models) # MySQL/RDS complains is there are selected models for counts.
|
||||
.distinct()
|
||||
|
@ -803,8 +803,7 @@ def _visible_repository_query(username=None, include_public=True, limit=None,
|
|||
.switch(Repository)
|
||||
.join(RepositoryPermission, JOIN_LEFT_OUTER))
|
||||
|
||||
query = _filter_to_repos_for_user(query, username, namespace, include_public)
|
||||
|
||||
query = _filter_to_repos_for_user(query, username, namespace, include_public, include_starred)
|
||||
if page:
|
||||
query = query.paginate(page, limit)
|
||||
elif limit:
|
||||
|
@ -814,7 +813,7 @@ def _visible_repository_query(username=None, include_public=True, limit=None,
|
|||
|
||||
|
||||
def _filter_to_repos_for_user(query, username=None, namespace=None,
|
||||
include_public=True):
|
||||
include_public=True, include_starred=True):
|
||||
if not include_public and not username:
|
||||
return Repository.select().where(Repository.id == '-1')
|
||||
|
||||
|
@ -825,6 +824,7 @@ def _filter_to_repos_for_user(query, username=None, namespace=None,
|
|||
AdminTeam = Team.alias()
|
||||
AdminTeamMember = TeamMember.alias()
|
||||
AdminUser = User.alias()
|
||||
UserThroughStar = User.alias()
|
||||
|
||||
query = (query
|
||||
.switch(RepositoryPermission)
|
||||
|
@ -844,6 +844,9 @@ def _filter_to_repos_for_user(query, username=None, namespace=None,
|
|||
where_clause = ((User.username == username) | (UserThroughTeam.username == username) |
|
||||
((AdminUser.username == username) & (TeamRole.name == 'admin')))
|
||||
|
||||
if not include_starred:
|
||||
subquery = Repository.select().join(Star).join(User).where(User.username == username).alias()
|
||||
where_clause = where_clause & ~(Repository.id << subquery)
|
||||
if namespace:
|
||||
where_clause = where_clause & (Namespace.username == namespace)
|
||||
|
||||
|
|
|
@ -107,6 +107,7 @@ class RepositoryList(ApiResource):
|
|||
@query_param('sort', 'Whether to sort the results.', type=truthy_bool, default=False)
|
||||
@query_param('count', 'Whether to include a count of the total number of results available.',
|
||||
type=truthy_bool, default=False)
|
||||
@query_param('starred', 'Whether or not to include starred repositories', type=truthy_bool, default=True)
|
||||
def get(self, args):
|
||||
"""Fetch the list of repositories under a variety of situations."""
|
||||
username = None
|
||||
|
@ -123,7 +124,7 @@ class RepositoryList(ApiResource):
|
|||
|
||||
repo_query = model.get_visible_repositories(username, limit=args['limit'], page=args['page'],
|
||||
include_public=args['public'], sort=args['sort'],
|
||||
namespace=args['namespace'])
|
||||
namespace=args['namespace'], include_starred=args['starred'])
|
||||
|
||||
response['repositories'] = [repo_view(repo) for repo in repo_query
|
||||
if (repo.visibility.name == 'public' or
|
||||
|
|
|
@ -4,6 +4,7 @@ import json
|
|||
from flask import request
|
||||
from flask.ext.login import logout_user
|
||||
from flask.ext.principal import identity_changed, AnonymousIdentity
|
||||
from peewee import IntegrityError
|
||||
|
||||
from app import app, billing as stripe, authentication, avatar
|
||||
from endpoints.api import (ApiResource, nickname, resource, validate_json_request, request_error,
|
||||
|
@ -713,10 +714,17 @@ class StarredRepositoryList(ApiResource):
|
|||
namespace = req['namespace']
|
||||
repository = req['repository']
|
||||
repo = model.get_repository(namespace, repository)
|
||||
|
||||
if repo:
|
||||
model.star_repository(user, repo)
|
||||
log_action('star_repository', user.username, namespace,
|
||||
{'repo': repository, 'namespace': namespace})
|
||||
try:
|
||||
model.star_repository(user, repo)
|
||||
except IntegrityError:
|
||||
pass
|
||||
|
||||
#TODO(jzelinskie): log this action
|
||||
#log_action('star_repository', user.username, namespace,
|
||||
# {'repo': repository, 'namespace': namespace})
|
||||
|
||||
return {
|
||||
'namespace': namespace,
|
||||
'repository': repository,
|
||||
|
@ -732,10 +740,13 @@ class StarredRepository(RepositoryParamResource):
|
|||
def delete(self, namespace, repository):
|
||||
user = get_authenticated_user()
|
||||
repo = model.get_repository(namespace, repository)
|
||||
|
||||
if repo:
|
||||
model.unstar_repository(user, repo)
|
||||
log_action('unstar_repository', user.username, namespace,
|
||||
{'repo': repository, 'namespace': namespace})
|
||||
|
||||
#TODO(jzelinskie): log this action
|
||||
#log_action('unstar_repository', user.username, namespace,
|
||||
# {'repo': repository, 'namespace': namespace})
|
||||
return 'Deleted', 204
|
||||
|
||||
raise NotFound()
|
||||
|
|
|
@ -139,6 +139,11 @@ def confirm_invite():
|
|||
def repository(path):
|
||||
return index('')
|
||||
|
||||
@web.route('/starred/')
|
||||
@no_cache
|
||||
def starred():
|
||||
return index('')
|
||||
|
||||
|
||||
@web.route('/security/')
|
||||
@no_cache
|
||||
|
|
|
@ -932,6 +932,8 @@ i.toggle-icon:hover {
|
|||
}
|
||||
|
||||
.repo-circle {
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
background: #eee;
|
||||
padding: 4px;
|
||||
|
@ -939,7 +941,6 @@ i.toggle-icon:hover {
|
|||
display: inline-block;
|
||||
width: 46px;
|
||||
height: 46px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.repo-circle.no-background {
|
||||
|
@ -950,11 +951,11 @@ i.toggle-icon:hover {
|
|||
}
|
||||
|
||||
.repo-circle .fa-hdd-o {
|
||||
font-size: 36px;
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
.repo-circle.no-background .fa-hdd-o {
|
||||
font-size: 30px;
|
||||
font-size: 1.7em;
|
||||
}
|
||||
|
||||
.repo-circle .fa-lock {
|
||||
|
@ -962,18 +963,18 @@ i.toggle-icon:hover {
|
|||
bottom: -2px;
|
||||
right: -4px;
|
||||
background: rgb(253, 191, 191);
|
||||
width: 20px;
|
||||
width: 16px;
|
||||
display: inline-block;
|
||||
border-radius: 50%;
|
||||
text-align: center;
|
||||
height: 20px;
|
||||
line-height: 21px;
|
||||
font-size: 16px !important;
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
font-size: 12px !important;
|
||||
}
|
||||
|
||||
.repo-circle.no-background .fa-lock {
|
||||
bottom: -2px;
|
||||
right: -6px;
|
||||
bottom: 5px;
|
||||
right: 7px;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
|
@ -2480,10 +2481,41 @@ p.editable:hover i {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.empty-primary-msg {
|
||||
font-size: 18px;
|
||||
margin-bottom: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.empty-secondary-msg {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
text-align: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.repo-list {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.repo-list-title {
|
||||
margin-bottom: 30px;
|
||||
margin-top: 10px;
|
||||
line-height: 24px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.repo-list-title a {
|
||||
font-size: 18px;
|
||||
margin: 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.repo-list-title i {
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.repo-list .button-bar-right {
|
||||
float: right;
|
||||
}
|
||||
|
@ -2503,11 +2535,42 @@ p.editable:hover i {
|
|||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.repo-panel {
|
||||
padding: 20px;
|
||||
border: 1px solid #eee;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.panel-body.starred {
|
||||
background: -moz-linear-gradient(top, rgba(255,240,188,1) 0%, rgba(255,255,255,0.5) 50%, rgba(255,255,255,0.49) 51%, rgba(255,255,255,0) 100%); /* FF3.6+ */
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,240,188,1)), color-stop(50%,rgba(255,255,255,0.5)), color-stop(51%,rgba(255,255,255,0.49)), color-stop(100%,rgba(255,255,255,0))); /* Chrome,Safari4+ */
|
||||
background: -webkit-linear-gradient(top, rgba(255,240,188,1) 0%,rgba(255,255,255,0.5) 50%,rgba(255,255,255,0.49) 51%,rgba(255,255,255,0) 100%); /* Chrome10+,Safari5.1+ */
|
||||
background: -o-linear-gradient(top, rgba(255,240,188,1) 0%,rgba(255,255,255,0.5) 50%,rgba(255,255,255,0.49) 51%,rgba(255,255,255,0) 100%); /* Opera 11.10+ */
|
||||
background: -ms-linear-gradient(top, rgba(255,240,188,1) 0%,rgba(255,255,255,0.5) 50%,rgba(255,255,255,0.49) 51%,rgba(255,255,255,0) 100%); /* IE10+ */
|
||||
background: linear-gradient(to bottom, rgba(255,240,188,1) 0%,rgba(255,255,255,0.5) 50%,rgba(255,255,255,0.49) 51%,rgba(255,255,255,0) 100%); /* W3C */
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fff0bc', endColorstr='#00ffffff',GradientType=0 ); /* IE6-9 */
|
||||
}
|
||||
|
||||
.star-icon {
|
||||
color: #ddd;
|
||||
display: block;
|
||||
font-size: 1.2em;
|
||||
text-align: right;
|
||||
line-height: 2em;
|
||||
}
|
||||
|
||||
.star-icon:hover {
|
||||
cursor: pointer;
|
||||
cursor: hand;
|
||||
}
|
||||
|
||||
.star-icon.starred {
|
||||
color: #ffba6d;
|
||||
}
|
||||
|
||||
.repo-listing {
|
||||
display: block;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
line-height: normal;
|
||||
}
|
||||
|
@ -2521,18 +2584,13 @@ p.editable:hover i {
|
|||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.repo-listing a {
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.repo-listing i {
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
margin-right: 6px;
|
||||
.repo-panel-repo-link {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
.repo-listing .description {
|
||||
padding-left: 44px;
|
||||
font-size: 0.91em;
|
||||
padding-top: 13px;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2267,6 +2267,7 @@ quayApp = angular.module('quay', quayDependencies, function($provide, cfpLoading
|
|||
|
||||
when('/', {title: 'Hosted Private Docker Registry', templateUrl: '/static/partials/landing.html', controller: LandingCtrl,
|
||||
pageClass: 'landing-page'}).
|
||||
when ('/starred/', {title: 'Starred Repositories', templateUrl: '/static/partials/starred.html', controller: StarCtrl}).
|
||||
otherwise({redirectTo: '/'});
|
||||
}]).
|
||||
config(function(RestangularProvider) {
|
||||
|
|
|
@ -237,14 +237,52 @@ function RepoListCtrl($scope, $sanitize, Restangular, UserService, ApiService) {
|
|||
$scope.publicPageCount = null;
|
||||
|
||||
// Monitor changes in the user.
|
||||
UserService.updateUserIn($scope, function() {
|
||||
loadMyRepos($scope.namespace);
|
||||
UserService.load(function() {
|
||||
console.log("updateUserIn");
|
||||
var user = UserService.currentUser();
|
||||
$scope.namespaces = [user];
|
||||
for (var i = 0; i < user.organizations.length; i++) {
|
||||
$scope.namespaces.push(user.organizations[i]);
|
||||
}
|
||||
loadStarredRepos();
|
||||
loadRepos();
|
||||
console.log($scope.namespaces);
|
||||
});
|
||||
|
||||
|
||||
// Monitor changes in the namespace.
|
||||
$scope.$watch('namespace', function(namespace) {
|
||||
loadMyRepos(namespace);
|
||||
});
|
||||
//$scope.$watch('namespace', function(namespace) {
|
||||
// loadStarredRepos($scope.namespace)
|
||||
// loadRepos();
|
||||
//});
|
||||
|
||||
|
||||
$scope.starRepo = function(repo) {
|
||||
var data = {
|
||||
'namespace': repo.namespace,
|
||||
'repository': repo.name
|
||||
};
|
||||
ApiService.createStar(data).then(function(result) {
|
||||
loadStarredRepos($scope.namespace);
|
||||
loadRepos($scope.namespace);
|
||||
}, function(result) {
|
||||
loadStarredRepos();
|
||||
loadRepos();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.unstarRepo = function(repo) {
|
||||
var data = {
|
||||
'repository': repo.namespace + '/' + repo.name
|
||||
};
|
||||
ApiService.deleteStar(null, data).then(function(result) {
|
||||
loadStarredRepos($scope.namespace);
|
||||
loadRepos($scope.namespace);
|
||||
}, function(result) {
|
||||
loadStarredRepos($scope.namespace);
|
||||
loadRepos();
|
||||
});
|
||||
};
|
||||
|
||||
$scope.movePublicPage = function(increment) {
|
||||
if ($scope.publicPageCount == null) {
|
||||
|
@ -263,18 +301,36 @@ function RepoListCtrl($scope, $sanitize, Restangular, UserService, ApiService) {
|
|||
loadPublicRepos();
|
||||
};
|
||||
|
||||
var loadMyRepos = function(namespace) {
|
||||
if (!$scope.user || $scope.user.anonymous || !namespace) {
|
||||
var loadStarredRepos = function() {
|
||||
if (!$scope.user || $scope.user.anonymous) {
|
||||
return;
|
||||
}
|
||||
|
||||
var options = {'public': false, 'sort': true, 'namespace': namespace};
|
||||
|
||||
$scope.user_repositories = ApiService.listReposAsResource().withOptions(options).get(function(resp) {
|
||||
$scope.starred_repositories = ApiService.listStarredReposAsResource().get(function(resp) {
|
||||
return resp.repositories;
|
||||
});
|
||||
};
|
||||
|
||||
var loadRepos = function() {
|
||||
if ($scope.namespaces.length == 0 || $scope.user.anonymous) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < $scope.namespaces.length; i++) {
|
||||
var namespace = $scope.namespaces[i];
|
||||
var namespaceName = namespace.username || namespace.name;
|
||||
var options = {
|
||||
'public': false,
|
||||
'sort': true,
|
||||
'namespace': namespaceName,
|
||||
'starred': false,
|
||||
};
|
||||
namespace.repositories = ApiService.listReposAsResource().withOptions(options).get(function(resp) {
|
||||
return resp.repositories;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
var loadPublicRepos = function() {
|
||||
var options = {
|
||||
'public': true,
|
||||
|
@ -293,7 +349,7 @@ function RepoListCtrl($scope, $sanitize, Restangular, UserService, ApiService) {
|
|||
});
|
||||
};
|
||||
|
||||
loadPublicRepos();
|
||||
//loadPublicRepos();
|
||||
}
|
||||
|
||||
function LandingCtrl($scope, UserService, ApiService, Features, Config) {
|
||||
|
@ -401,6 +457,10 @@ function LandingCtrl($scope, UserService, ApiService, Features, Config) {
|
|||
};
|
||||
}
|
||||
|
||||
function StarCtrl($scope) {
|
||||
$scope.test = "hello";
|
||||
}
|
||||
|
||||
function RepoCtrl($scope, $sanitize, Restangular, ImageMetadataService, ApiService, $routeParams, $rootScope, $location, $timeout, Config) {
|
||||
$scope.Config = Config;
|
||||
|
||||
|
|
|
@ -1,73 +1,136 @@
|
|||
<div class="container">
|
||||
<div class="repo-list" ng-show="!user.anonymous">
|
||||
<div ng-class="user.organizations.length ? 'section-header' : ''">
|
||||
<div class="button-bar-right">
|
||||
<a href="/new/">
|
||||
<button class="btn btn-success">
|
||||
<i class="fa fa-upload user-tool" data-title="Create new repository"></i>
|
||||
Create Repository
|
||||
</button>
|
||||
</a>
|
||||
|
||||
<a href="/organization/{{ namespace }}" ng-show="namespace != user.username">
|
||||
<button class="btn btn-default">
|
||||
<i class="fa fa-group user-tool"></i>
|
||||
View Organization
|
||||
</button>
|
||||
<div class="row">
|
||||
<div class="col-lg-3 col-lg-push-9 col-md-3 col-md-push-9 col-sm-4 col-sm-push-8 col-xs-12">
|
||||
<div class="button-bar-right">
|
||||
<a href="/new/">
|
||||
<button class="btn btn-success">
|
||||
<i class="fa fa-upload user-tool" data-title="Create new repository"></i>
|
||||
Create Repository
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Users
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<a href="javascript:void(0)">
|
||||
<span class="avatar" size="24" hash="user.avatar"></span>
|
||||
{{ user.username }}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<span class="namespace-selector" user="user" namespace="namespace" ng-show="user.organizations"></span>
|
||||
</div>
|
||||
|
||||
<h3 ng-show="namespace == user.username">Your Repositories</h3>
|
||||
<h3 ng-show="namespace != user.username">Repositories</h3>
|
||||
|
||||
<div class="resource-view" resource="user_repositories">
|
||||
<!-- User/Org has repositories -->
|
||||
<div ng-show="user_repositories.value.length > 0">
|
||||
<div class="repo-listing" ng-repeat="repository in user_repositories.value">
|
||||
<span class="repo-circle no-background" repo="repository"></span>
|
||||
<a ng-href="/repository/{{repository.namespace}}/{{ repository.name }}"
|
||||
data-repo="{{repository.namespace}}/{{ repository.name }}">
|
||||
{{repository.namespace}}/{{repository.name}}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Organizations
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div ng-repeat="org in user.organizations">
|
||||
<a href="/organization/{{ org.name }}">
|
||||
<span class="avatar" size="24" hash="org.avatar"></span>
|
||||
{{ org.name }}
|
||||
</a>
|
||||
<a href="/organization/{{ org.name }}/admin">
|
||||
<i class="fa fa-gear" style="color:#000"></i>
|
||||
</a>
|
||||
<div class="description markdown-view" content="repository.description" first-line-only="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- User/Org has no repositories -->
|
||||
<div ng-show="user_repositories.value.length == 0" style="padding:20px;">
|
||||
<div class="alert alert-info">
|
||||
<h4 ng-show="namespace == user.username">You don't have any repositories yet!</h4>
|
||||
<h4 ng-show="namespace != user.username">This organization doesn't have any repositories, or you have not been provided access.</h4>
|
||||
<a href="http://docs.quay.io/solution/getting-started.html"><b>Click here</b> to learn how to create a repository</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="repo-list">
|
||||
<h3>Top Public Repositories</h3>
|
||||
<div class="resource-view" resource="public_repositories">
|
||||
<div class="repo-listing" ng-repeat="repository in public_repositories.value">
|
||||
<span class="repo-circle no-background" repo="repository"></span>
|
||||
<a ng-href="/repository/{{repository.namespace}}/{{ repository.name }}"
|
||||
data-repo="{{repository.namespace}}/{{ repository.name }}">
|
||||
{{repository.namespace}}/{{repository.name}}
|
||||
</a>
|
||||
<div class="description markdown-view" content="repository.description" first-line-only="true"></div>
|
||||
<div class="col-lg-9 col-lg-pull-3 col-md-9 col-md-pull-3 col-sm-8 col-sm-pull-4 col-xs-12">
|
||||
<div class="resource-view" resource="starred_repositories">
|
||||
<div class="repo-listing">
|
||||
<div class="repo-list-title">
|
||||
<i class="fa fa-star"></i>
|
||||
Starred
|
||||
</div>
|
||||
<div>
|
||||
<div class="row">
|
||||
<div class="col-lg-4 col-md-6 col-sm-12 col-xs-12" ng-repeat="repository in starred_repositories.value">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body starred">
|
||||
<div class="row">
|
||||
<div class="col-lg-10 col-md-10 col-sm-10 col-xs-10">
|
||||
<span class="repo-icon repo-circle no-background" repo="repository"></span>
|
||||
<a ng-href="/repository/{{repository.namespace}}/{{ repository.name }}" class="repo-panel-repo-link"
|
||||
data-repo="{{repository.namespace}}/{{ repository.name }}">
|
||||
{{repository.namespace}}/{{repository.name}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-2 col-sm-2 col-xs-2">
|
||||
<i class="star-icon starred fa fa-star" ng-click="unstarRepo(repository)"></i>
|
||||
</div>
|
||||
</div>
|
||||
<!-- The description automatically gets put in a <p> which adds margin that throws off our .repo-panel padding -->
|
||||
<div class="description markdown-view" content="repository.description" first-line-only="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="starred_repositories.value.length == 0">
|
||||
<div class="empty-primary-msg">You haven't starred any repositories yet.</div>
|
||||
<div class="empty-secondary-msg">Stars allow you to easily access your favorite repositories.</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="page-controls">
|
||||
<button class="btn btn-default" data-title="Previous Page" bs-tooltip="title" ng-show="page > 1"
|
||||
ng-click="movePublicPage(-1)">
|
||||
<i class="fa fa-chevron-left"></i>
|
||||
</button>
|
||||
<button class="btn btn-default" data-title="Next Page" bs-tooltip="title" ng-show="page < publicPageCount"
|
||||
ng-click="movePublicPage(1)">
|
||||
<i class="fa fa-chevron-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Repo listings for User and Orgs -->
|
||||
<div ng-repeat="namespace in namespaces">
|
||||
<div class="resource-view" resource="namespace">
|
||||
<div class="repo-listing">
|
||||
<div class="repo-list-title" ng-show="user.username == namespace.username">
|
||||
<i class="fa fa-user"></i>
|
||||
{{ namespace.username }}
|
||||
</div>
|
||||
<div class="repo-list-title" ng-show="user.username != namespace.username">
|
||||
<i class="fa fa-sitemap"></i>
|
||||
<a href="/organization/{{ namespace.name }}">{{ namespace.name }}</a>
|
||||
</div>
|
||||
<div ng-show="namespace.repositories.value.length > 0">
|
||||
<div class="row">
|
||||
<div class="col-lg-4 col-md-6 col-sm-6 col-xs-12" ng-repeat="repository in namespace.repositories.value">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-body">
|
||||
<div class="row">
|
||||
<div class="col-lg-10 col-md-10 col-sm-10 col-xs-10">
|
||||
<span class="repo-icon repo-circle no-background" repo="repository"></span>
|
||||
<a ng-href="/repository/{{repository.namespace}}/{{ repository.name }}" class="repo-panel-repo-link"
|
||||
data-repo="{{repository.namespace}}/{{ repository.name }}">
|
||||
{{repository.namespace}}/{{repository.name}}
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-lg-2 col-md-2 col-sm-2 col-xs-2">
|
||||
<i class="star-icon fa fa-star-o" ng-click="starRepo(repository)"></i>
|
||||
</div>
|
||||
</div>
|
||||
<!-- The description automatically gets put in a <p> which adds margin that throws off our .repo-panel padding -->
|
||||
<div class="description markdown-view" content="repository.description" first-line-only="true"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div ng-show="namespace.value.length == 0">
|
||||
<div class="empty-primary-msg">There aren't any repositories yet.</div>
|
||||
<div class="empty-secondary-msg">This origanization does't have any repositories, or you have not been provided access. <a href="/new">Create a new repository</a>
|
||||
</div>
|
||||
|
||||
<!-- User/Org has no repositories -->
|
||||
<div ng-show="namespace.repositories.value.length == 0" style="padding:20px;">
|
||||
<div class="alert alert-info">
|
||||
<h4 ng-show="namespace == user.username">You don't have any repositories yet!</h4>
|
||||
<h4 ng-show="namespace != user.username">This organization doesn't have any repositories, or you have not been provided access.</h4>
|
||||
<a href="http://docs.quay.io/solution/getting-started.html"><b>Click here</b> to learn how to create a repository</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
3
static/partials/starred.html
Normal file
3
static/partials/starred.html
Normal file
|
@ -0,0 +1,3 @@
|
|||
<div ng-show="test">
|
||||
{{ test }}
|
||||
</div>
|
Binary file not shown.
Reference in a new issue