Get the tabs working and the UI for the image history. Note that the model changes for the image history are WRONG and need to be fixed
This commit is contained in:
parent
94cba8a0bc
commit
bf926aceee
5 changed files with 89 additions and 16 deletions
|
@ -148,6 +148,13 @@ def get_repository_images(namespace_name, repository_name):
|
||||||
return joined.where(Repository.name == repository_name,
|
return joined.where(Repository.name == repository_name,
|
||||||
Repository.namespace == namespace_name)
|
Repository.namespace == namespace_name)
|
||||||
|
|
||||||
|
def get_tag_images(namespace_name, repository_name, tag_name):
|
||||||
|
joined = Image.select().join(RepositoryTag).join(Repository)
|
||||||
|
fetched = list(joined.where(Repository.name == repository_name,
|
||||||
|
Repository.namespace == namespace_name,
|
||||||
|
RepositoryTag.name == tag_name))
|
||||||
|
|
||||||
|
return fetched
|
||||||
|
|
||||||
def list_repository_tags(namespace_name, repository_name):
|
def list_repository_tags(namespace_name, repository_name):
|
||||||
select = RepositoryTag.select(RepositoryTag, Image)
|
select = RepositoryTag.select(RepositoryTag, Image)
|
||||||
|
@ -158,11 +165,7 @@ def list_repository_tags(namespace_name, repository_name):
|
||||||
|
|
||||||
|
|
||||||
def get_tag_image(namespace_name, repository_name, tag_name):
|
def get_tag_image(namespace_name, repository_name, tag_name):
|
||||||
joined = Image.select().join(RepositoryTag).join(Repository)
|
fetched = get_tag_images(namespace_name, repository_name, tag_name)
|
||||||
fetched = list(joined.where(Repository.name == repository_name,
|
|
||||||
Repository.namespace == namespace_name,
|
|
||||||
RepositoryTag.name == tag_name))
|
|
||||||
|
|
||||||
if not fetched:
|
if not fetched:
|
||||||
raise DataModelException('Unable to find image for tag.')
|
raise DataModelException('Unable to find image for tag.')
|
||||||
|
|
||||||
|
|
|
@ -79,18 +79,20 @@ def update_repo_api(namespace, repository):
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
|
||||||
|
def image_view(image):
|
||||||
|
return {
|
||||||
|
'id': image.image_id,
|
||||||
|
'created': image.created,
|
||||||
|
'comment': image.comment,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/repository/<path:repository>', methods=['GET'])
|
@app.route('/api/repository/<path:repository>', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
@parse_repository_name
|
@parse_repository_name
|
||||||
def get_repo_api(namespace, repository):
|
def get_repo_api(namespace, repository):
|
||||||
logger.debug('Get repo: %s/%s' % (namespace, repository))
|
logger.debug('Get repo: %s/%s' % (namespace, repository))
|
||||||
def image_view(image):
|
|
||||||
return {
|
|
||||||
'id': image.image_id,
|
|
||||||
'created': image.created,
|
|
||||||
'comment': image.comment,
|
|
||||||
}
|
|
||||||
|
|
||||||
def tag_view(tag):
|
def tag_view(tag):
|
||||||
image = model.get_tag_image(namespace, repository, tag.name)
|
image = model.get_tag_image(namespace, repository, tag.name)
|
||||||
if not image:
|
if not image:
|
||||||
|
@ -128,6 +130,21 @@ def role_view(repo_perm_obj):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/api/repository/<path:repository>/tag/<tag>/images', methods=['GET'])
|
||||||
|
@login_required
|
||||||
|
@parse_repository_name
|
||||||
|
def list_tag_images(namespace, repository, tag):
|
||||||
|
permission = ReadRepositoryPermission(namespace, repository)
|
||||||
|
if permission.can():
|
||||||
|
images = model.get_tag_images(namespace, repository, tag)
|
||||||
|
|
||||||
|
return jsonify({
|
||||||
|
'images': [image_view(image) for image in images]
|
||||||
|
})
|
||||||
|
|
||||||
|
abort(403) # Permission denied
|
||||||
|
|
||||||
|
|
||||||
@app.route('/api/repository/<path:repository>/permissions/', methods=['GET'])
|
@app.route('/api/repository/<path:repository>/permissions/', methods=['GET'])
|
||||||
@login_required
|
@login_required
|
||||||
@parse_repository_name
|
@parse_repository_name
|
||||||
|
|
|
@ -182,11 +182,15 @@ p.editable:hover i {
|
||||||
min-width: 300px;
|
min-width: 300px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.repo-admin thead td {
|
.repo thead td {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
color: #999;
|
color: #999;
|
||||||
}
|
}
|
||||||
|
|
||||||
.repo-admin td {
|
.repo td {
|
||||||
padding: 6px;
|
padding: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.repo .images {
|
||||||
|
margin: 10px;
|
||||||
}
|
}
|
|
@ -16,8 +16,24 @@ function LandingCtrl($scope) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function RepoCtrl($scope, Restangular, $routeParams, $rootScope) {
|
function RepoCtrl($scope, Restangular, $routeParams, $rootScope) {
|
||||||
|
var tabs = ['current-image', 'image-history'];
|
||||||
|
|
||||||
$rootScope.title = 'Loading...';
|
$rootScope.title = 'Loading...';
|
||||||
|
|
||||||
|
$scope.showTab = function(tabName) {
|
||||||
|
for (var i = 0; i < tabs.length; ++i) {
|
||||||
|
$('#' + tabs[i]).hide();
|
||||||
|
$('#' + tabs[i] + '-tab').removeClass('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#' + tabName).show();
|
||||||
|
$('#' + tabName + '-tab').addClass('active');
|
||||||
|
|
||||||
|
if (tabName == 'image-history') {
|
||||||
|
$scope.listImages();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
$scope.editDescription = function() {
|
$scope.editDescription = function() {
|
||||||
if (!$scope.repo.can_write) { return; }
|
if (!$scope.repo.can_write) { return; }
|
||||||
$('#descriptionEdit')[0].value = $scope.repo.description || '';
|
$('#descriptionEdit')[0].value = $scope.repo.description || '';
|
||||||
|
@ -33,6 +49,15 @@ function RepoCtrl($scope, Restangular, $routeParams, $rootScope) {
|
||||||
$scope.parseDate = function(dateString) {
|
$scope.parseDate = function(dateString) {
|
||||||
return Date.parse(dateString);
|
return Date.parse(dateString);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
$scope.listImages = function() {
|
||||||
|
if ($scope.imageHistory) { return; }
|
||||||
|
|
||||||
|
var imageFetch = Restangular.one('repository/' + namespace + '/' + name + '/tag/' + $scope.currentTag.name + '/images');
|
||||||
|
imageFetch.get().then(function(resp) {
|
||||||
|
$scope.imageHistory = resp.images;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
var namespace = $routeParams.namespace;
|
var namespace = $routeParams.namespace;
|
||||||
var name = $routeParams.name;
|
var name = $routeParams.name;
|
||||||
|
|
|
@ -52,8 +52,8 @@
|
||||||
</ul>
|
</ul>
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li class="active"><a href="javascript:void(0)">Current Image</a></li>
|
<li id="current-image-tab" class="active" ng-click="showTab('current-image')"><a href="javascript:void(0)">Current Image</a></li>
|
||||||
<li><a href="javascript:void(0)">Image History</a></li>
|
<li id="image-history-tab" ng-click="showTab('image-history')"><a href="javascript:void(0)">Image History</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<div id="current-image">
|
<div id="current-image">
|
||||||
|
@ -73,6 +73,30 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="image-history" style="display: none">
|
||||||
|
<div ng-hide="imageHistory">
|
||||||
|
Loading images...
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div ng-show="imageHistory">
|
||||||
|
<table class="images">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td>Created</td>
|
||||||
|
<td>Comment</td>
|
||||||
|
<td>ID</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tr ng-repeat="image in imageHistory">
|
||||||
|
<td><span am-time-ago="parseDate(image.created)"></span></td>
|
||||||
|
<td>{{ image.comment }}</td>
|
||||||
|
<td>{{ image.id }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Modal edit for the description -->
|
<!-- Modal edit for the description -->
|
||||||
<div class="modal fade" id="editModal">
|
<div class="modal fade" id="editModal">
|
||||||
<div class="modal-dialog">
|
<div class="modal-dialog">
|
||||||
|
|
Reference in a new issue