Show simple list of tags in v2 registry's repository

The current implementation is basic only. Basically all columns have
been removed just to show the tag name and that's it.

This will be adjusted further in the near future.
This commit is contained in:
Konrad Kleine 2015-09-03 17:03:40 +02:00
parent 339c8a797f
commit ef70220d0b
7 changed files with 109 additions and 51 deletions

View file

@ -18,7 +18,7 @@ angular
'ngTouch',
'registry-services', // TODO: Maybe the following dependencies are not needed? At least they weren't in the "yo angular" output.
'main-controller',
'repository-controller',
'repository-detail-controller',
'tag-controller',
'repository-list-controller',
'tag-list-directive',
@ -58,9 +58,9 @@ angular
templateUrl: 'repository/repository-list.html',
controller: 'RepositoryListController'
}).
when('/repository/:repositoryUser/:repositoryName/', {
when('/repository/:repositoryUser/:repositoryName', {
templateUrl: 'repository/repository-detail.html',
controller: 'RepositoryController',
controller: 'RepositoryDetailController',
}).
when('/repository/:repositoryUser/:repositoryName/tags/:searchName?', {
templateUrl: 'repository/repository-detail.html',

View file

@ -78,7 +78,7 @@
<script src="app.js"></script>
<script src="main-controller.js"></script>
<script src="repository/repository-controller.js"></script>
<script src="repository/repository-detail-controller.js"></script>
<script src="repository/delete-repository-controller.js"></script>
<script src="repository/repository-list-controller.js"></script>

View file

@ -2,13 +2,13 @@
/**
* @ngdoc function
* @name docker-registry-frontend.controller:RepositoryController
* @name docker-registry-frontend.controller:RepositoryDetailController
* @description
* # RepositoryController
* # RepositoryDetailController
* Controller of the docker-registry-frontend
*/
angular.module('repository-controller', ['registry-services', 'app-mode-services'])
.controller('RepositoryController', ['$scope', '$route', '$routeParams', '$location', '$modal', 'Repository', 'AppMode',
angular.module('repository-detail-controller', ['registry-services', 'app-mode-services'])
.controller('RepositoryDetailController', ['$scope', '$route', '$routeParams', '$location', '$modal', 'Repository', 'AppMode',
function($scope, $route, $routeParams, $location, $modal, Repository, AppMode){
$scope.$route = $route;
@ -25,24 +25,6 @@ angular.module('repository-controller', ['registry-services', 'app-mode-services
// selected repos
$scope.selectedRepositories = [];
// helper method to get selected tags
$scope.selectedRepos = function selectedRepos() {
return filterFilter($scope.repositories.repos, { selected: true });
};
// watch repos for changes
// Actually we would like to monitor the "selected" portion of an object
// in repositories.repos but since there's only one boolean property right
// now it will automatically test for "selected". This can cause trouble
// in the future though.
$scope.$watch('repositories|filter:{$:true}', function(nv) {
if (nv.repos) {
$scope.selectedRepositories = nv.repos.map(function (repo) {
return repo.name;
});
}
}, true);
$scope.openConfirmRepoDeletionDialog = function(size) {
var modalInstance = $modal.open({
animation: true,

View file

@ -0,0 +1,79 @@
'use strict';
/**
* @ngdoc function
* @name docker-registry-frontend.controller:RepositoryListController
* @description
* # RepositoryListController
* Controller of the docker-registry-frontend
*/
angular.module('repository-list-controller', ['registry-services', 'app-mode-services'])
.controller('RepositoryListController', ['$scope', '$route', '$routeParams', '$location', '$modal', 'Repository', 'AppMode',
function($scope, $route, $routeParams, $location, $modal, Repository, AppMode){
$scope.$route = $route;
$scope.$location = $location;
$scope.$routeParams = $routeParams;
$scope.repositoryUser = $route.current.params.repositoryUser;
$scope.repositoryName = $route.current.params.repositoryName;
$scope.repository = $scope.repositoryUser + '/' + $scope.repositoryName;
$scope.appMode = AppMode.query();
// How to query the repository
$scope.reposPerPage = $route.current.params.reposPerPage;
$scope.lastNamespace = $route.current.params.lastNamespace;
$scope.lastRepository = $route.current.params.lastRepository;
var queryObject = {};
if ($scope.reposPerPage) {
queryObject['n'] = $scope.reposPerPage;
}
if ($scope.lastNamespace && $scope.lastRepository) {
queryObject['last'] = ''+$scope.lastNamespace+'/'+$scope.lastRepository;
}
$scope.repositories = Repository.query(queryObject);
// selected repos
$scope.selectedRepositories = [];
// helper method to get selected tags
$scope.selectedRepos = function selectedRepos() {
return filterFilter($scope.repositories.repos, { selected: true });
};
// Watch repos for changes
// To watch for changes on a property inside the object "repositories"
// we first have to make sure the promise is ready.
$scope.repositories.$promise.then(function(data) {
$scope.$watch('repositories.repos|filter:{selected:true}', function(nv) {
$scope.selectedRepositories = nv.map(function (repo) {
return repo.name;
});
}, true);
});
$scope.openConfirmRepoDeletionDialog = function(size) {
var modalInstance = $modal.open({
animation: true,
templateUrl: 'modalConfirmDeleteItems.html',
controller: 'DeleteRepositoryController',
size: size,
resolve: {
items: function () {
return $scope.selectedRepositories;
},
information: function() {
return 'A repository is a collection of tags. \
A tag is basically a reference to an image. \
If no references to an image exist, the image will be scheduled for automatic deletion. \
That said, if you remove a tag, you remove a reference to an image. \
Your image data may get lost, if no other tag references it. \
If you delete a repository, you delete all tags associated with it. \
Are you sure, you want to delete the following repositories?';
}
}
});
};
}]);

View file

@ -101,15 +101,23 @@ angular.module('registry-services', ['ngResource'])
}])
.factory('Tag', ['$resource', function($resource){
// TODO: rename :repo to repoUser/repoString for convenience.
return $resource('/v1/repositories/:repoUser/:repoName/tags', {}, {
// https://github.com/docker/distribution/blob/master/docs/spec/api.md#listing-image-tags
return $resource('/v2/:repoUser/:repoName/tags/list', {}, {
// Response example:
// {"name":"kkleine/docker-registry-frontend","tags":["v2", "v1-deprecated"]}
'query': {
method:'GET',
isArray: true,
transformResponse: function(data/*, headers*/){
var res = [];
console.log(data);
var resp = angular.fromJson(data);
for (var i in resp){
res.push({name: i, imageId: resp[i], selected: false});
for (var idx in resp.tags){
res.push({
name: resp.tags[idx],
imageId: 'ImageIDOf'+resp.tags[idx],
selected: false
});
}
return res;
},

View file

@ -21,6 +21,7 @@ angular.module('tag-controller', ['registry-services'])
$scope.repository = $scope.repositoryUser + '/' + $scope.repositoryName;
$scope.tagName = $route.current.params.tagName;
// How to query the tags
$scope.tags = Tag.query({
repoUser: $scope.repositoryUser,
repoName: $scope.repositoryName

View file

@ -12,23 +12,16 @@
<tr>
<th><span class="glyphicon glyphicon-check" ng-hide="appMode.browseOnly"></span></th>
<th class="" ng-class="{strike: deleted}" st-sort="name" st-sort-default=""><span class="glyphicon glyphicon-tag"></span> Tag</th>
<th class="" st-sort="imageId"><span class="glyphicon glyphicon-qrcode"></span> Image ID</th>
<th class="" st-sort="details.created"><span class="glyphicon glyphicon-calendar"></span> Created</th>
<!--<th class="" st-sort="details.created"><span class="glyphicon glyphicon-calendar"></span> Created</th>
<th class="" st-sort="details.author"><span class="glyphicon glyphicon-user"></span> Author</th>
<th class="" st-sort="details.docker_version"><span class="glyphicon glyphicon-eye-open"></span> Docker version</th>
<th class="" st-sort="details.parent"><span class="glyphicon glyphicon-arrow-up"></span> Parent's ID</th>
<th class="" st-sort="details.Size"><span class="glyphicon glyphicon-compressed"></span> Size (MB)</th>
<th class="" st-sort="details.Size"><span class="glyphicon glyphicon-compressed"></span> Size (MB)</th>-->
</tr>
<tr>
<th>&nbsp;</th>
<th><input st-search="'name'" class="input-sm form-control" placeholder="Tag" type="search"/></th>
<th><input st-search="'imageId'" class="input-sm form-control" placeholder="Image ID" type="search"/></th>
<th colspan="5">&nbsp;</th>
<!--<th><input st-search="'details.created'" class="input-sm form-control" placeholder="Created" type="search"/></th>
<th><input st-search="'details.author'" class="input-sm form-control" placeholder="Author" type="search"/></th>
<th><input st-search="'details.docker_version'" class="input-sm form-control" placeholder="Docker version" type="search"/></th>
<th><input st-search="'details.parent'" class="input-sm form-control" placeholder="Parent's ID" type="search"/></th>
<th><input st-search="'details.Size'" class="input-sm form-control" placeholder="Size" type="search"/></th>-->
<th><input st-search="'name'" class="input-sm form-control" placeholder="Filter tags on this page" type="search"/></th>
<th colspan="4">&nbsp;</th>
</tr>
</thead>
<tbody>
@ -40,9 +33,11 @@
<checkbox name="selectedTags[]" value="{{tag.name}}" ng-model="tag.selected" ng-hide="appMode.browseOnly"></checkbox>
<!--<input type="checkbox" name="selectedTags[]" value="{{tag.name}}" ng-model="tag.selected" ng-hide="appMode.browseOnly">-->
</td>
<td><a href="tag/{{repositoryUser}}/{{repositoryName}}/{{tag.name}}/{{tag.imageId}}" ng-bind-html="tag.name"></a></td>
<td><a href="image/{{tag.imageId}}" ng-bind-html="tag.imageId | limitTo: 12"></a></td>
<td am-time-ago="tag.details.created"></td>
<td>
<!--<a href="tag/{{repositoryUser}}/{{repositoryName}}/{{tag.name}}/{{tag.imageId}}" ng-bind-html="tag.name"></a>-->
<span ng-bind-html="tag.name"></span>
</td>
<!--<td am-time-ago="tag.details.created"></td>
<td><span ng-bind-html="tag.details.author | linky"></span></td>
<td ng-bind-html="tag.details.docker_version"></td>
<td><a href="image/{{tag.details.parent}}" ng-bind-html="tag.details.parent | limitTo: 12"></a></td>
@ -54,15 +49,8 @@
<span ng-show="totalImageSize!==null">
{{totalImageSize / 1024 / 1024 | number: 2}}
</span>
</td>
</td>-->
</tr>
</tbody>
</table>
</div>
<!-- Maybe put this into its own directive? -->
<button type="button" ng-disabled="!selection.length" ng-click="openConfirmTagDeletionDialog()" class="btn btn-danger" ng-hide="appMode.browseOnly">
<span class="glyphicon glyphicon-trash"></span>
<ng-pluralize count="selection.length"
when="{'0': 'Select tags to delete', 'one': 'Delete one tag', 'other': 'Delete {} tags'}">
</ng-pluralize>
</button>