diff --git a/src/ui/static/resources/js/components/repository/list-repository.directive.html b/src/ui/static/resources/js/components/repository/list-repository.directive.html index c8f666306..2c4a1ce3b 100644 --- a/src/ui/static/resources/js/components/repository/list-repository.directive.html +++ b/src/ui/static/resources/js/components/repository/list-repository.directive.html @@ -17,13 +17,21 @@
diff --git a/src/ui/static/resources/js/components/repository/list-repository.directive.js b/src/ui/static/resources/js/components/repository/list-repository.directive.js index 44fcefbab..adf45d3a9 100644 --- a/src/ui/static/resources/js/components/repository/list-repository.directive.js +++ b/src/ui/static/resources/js/components/repository/list-repository.directive.js @@ -54,7 +54,7 @@ if(val) { vm.projectId = getParameterByName('project_id', $location.absUrl()); vm.filterInput = ''; - vm.retrieve(); + vm.retrieve(); } }); @@ -72,6 +72,12 @@ } }); + $scope.$watch('vm.tagName', function(current) { + if(current) { + vm.selectedTags = []; + } + }); + $scope.$on('repoName', function(e, val) { vm.repoName = val; }); @@ -87,11 +93,20 @@ $scope.$on('tags', function(e, val) { vm.tags = val; }); - + vm.deleteByRepo = deleteByRepo; vm.deleteByTag = deleteByTag; + + vm.deleteSelectedTagsByRepo = deleteSelectedTagsByRepo; + vm.deleteImage = deleteImage; - + vm.deleteSelectedTags = deleteSelectedTags; + + vm.selectAll = []; + vm.selectAllTags = selectAllTags; + + vm.selectedTags = []; + function retrieve(){ console.log('retrieve repositories, project_id:' + vm.projectId); ListRepositoryService(vm.projectId, vm.filterInput, vm.page, vm.pageSize) @@ -101,6 +116,8 @@ function getRepositoryComplete(response) { vm.repositories = response.data || []; vm.totalCount = response.headers('X-Total-Count'); + vm.selectAll[vm.repoName] = false; + vm.selectedTags = []; } function getRepositoryFailed(response) { @@ -143,7 +160,31 @@ $scope.$emit('raiseInfo', emitInfo); } + + function deleteSelectedTagsByRepo(repo) { + vm.repoName = repo; + $scope.$broadcast('gatherSelectedTags' + vm.repoName, true); + var emitInfo = { + 'confirmOnly': false, + 'contentType': 'text/html', + 'action' : vm.deleteSelectedTags + }; + $scope.$emit('modalTitle', $filter('tr')('alert_delete_tag_title')); + $scope.$emit('modalMessage', $filter('tr')('alert_delete_selected_tag')); + $scope.$emit('raiseInfo', emitInfo); + } + + function selectAllTags(repo) { + vm.selectAll[repo] = !vm.selectAll[repo]; + console.log('send to tags selectAll:' + vm.selectAll[repo]); + $scope.$broadcast('selectAll' + repo, {'status': vm.selectAll[repo], 'repoName': repo}); + } + $scope.$on('selectedAll', function(e, val) { + console.log('received from tags selectedAll:' + angular.toJson(val)); + vm.selectAll[val.repoName] = val.status; + }); + function deleteByTag() { $scope.$emit('modalTitle', $filter('tr')('alert_delete_tag_title', [vm.tag])); var message; @@ -155,26 +196,46 @@ 'contentType': 'text/html', 'action' : vm.deleteImage }; - $scope.$emit('raiseInfo', emitInfo); - } + } function deleteImage() { - console.log('Delete image, repoName:' + vm.repoName + ', tag:' + vm.tag); vm.toggleInProgress[vm.repoName + '|' + vm.tag] = true; DeleteRepositoryService(vm.repoName, vm.tag) .success(deleteRepositorySuccess) .error(deleteRepositoryFailed); } - + + $scope.$on('selectedTags', function(e, val) { + if(val) { + vm.selectedTags[val.repoName] = val.tags; + } + }) + + function deleteSelectedTags() { + console.log('Delete selected tags:' + angular.toJson(vm.selectedTags[vm.repoName]) + ' under repo:' + vm.repoName); + vm.toggleInProgress[vm.repoName + '|'] = true; + for(var i in vm.selectedTags[vm.repoName] || []) { + var tag = vm.selectedTags[vm.repoName][i]; + if(tag !== '') { + vm.toggleInProgress[vm.repoName + '|' + tag] = true; + DeleteRepositoryService(vm.repoName, tag) + .success(deleteRepositorySuccess) + .error(deleteRepositoryFailed); + } + } + } + function deleteRepositorySuccess(data, status) { + vm.toggleInProgress[vm.repoName + '|'] = false; vm.toggleInProgress[vm.repoName + '|' + vm.tag] = false; vm.retrieve(); $scope.$broadcast('refreshTags', true); } function deleteRepositoryFailed(data, status) { + vm.toggleInProgress[vm.repoName + '|'] = false; vm.toggleInProgress[vm.repoName + '|' + vm.tag] = false; $scope.$emit('modalTitle', $filter('tr')('error')); diff --git a/src/ui/static/resources/js/components/repository/list-tag.directive.html b/src/ui/static/resources/js/components/repository/list-tag.directive.html index 029b02a2d..d2239371e 100644 --- a/src/ui/static/resources/js/components/repository/list-tag.directive.html +++ b/src/ui/static/resources/js/components/repository/list-tag.directive.html @@ -1,6 +1,6 @@
-
- +
+
@@ -14,7 +14,11 @@ - +
// 'tag' | tr // // 'image_details' | tr // +    + + +
diff --git a/src/ui/static/resources/js/components/repository/list-tag.directive.js b/src/ui/static/resources/js/components/repository/list-tag.directive.js index 3430f57f0..59b7daa3a 100644 --- a/src/ui/static/resources/js/components/repository/list-tag.directive.js +++ b/src/ui/static/resources/js/components/repository/list-tag.directive.js @@ -28,8 +28,14 @@ vm.tags = []; vm.retrieve = retrieve; + vm.selected = [] + vm.selected[vm.repoName] = []; + + vm.selectedTags = []; + $scope.$watch('vm.repoName', function(current, origin) { if(current) { + console.log('vm.repoName triggered tags retrieval.') vm.retrieve(); } }); @@ -37,10 +43,47 @@ $scope.$on('refreshTags', function(e, val) { if(val) { vm.retrieve(); + vm.selectedCount[vm.repoName] = 0; + vm.selected[val.repoName] = []; + vm.selectedTags = []; } }); - vm.deleteTag = deleteTag; + $scope.$watch('vm.selectedCount[vm.repoName]', function(current, previous) { + if(current !== previous) { + console.log('Watching vm.selectedCount:' + current); + $scope.$emit('selectedAll', {'status': (current === vm.tags.length), 'repoName': vm.repoName}); + } + }); + + $scope.$on('gatherSelectedTags' + vm.repoName, function(e, val) { + if(val) { + console.log('RECEIVED gatherSelectedTags:' + val); + gatherSelectedTags(); + } + }) + + $scope.$on('selectAll' + vm.repoName, function(e, val) { + (val.status) ? vm.selectedCount[val.repoName] = vm.tags.length : vm.selectedCount[val.repoName] = 0; + for(var i = 0; i < vm.tags.length; i++) { + vm.selected[val.repoName][i] = val.status; + } + gatherSelectedTags(); + console.log('received selectAll:' + angular.toJson(val) + ', vm.selected:' + angular.toJson(vm.selected)); + }); + + $scope.$watch('vm.tags', function(current) { + if(current) { + vm.tags = current; + } + }); + + vm.deleteTag = deleteTag; + + vm.selectedCount = []; + vm.selectedCount[vm.repoName] = 0; + + vm.selectOne = selectOne; function retrieve() { ListTagService(vm.repoName) @@ -49,7 +92,6 @@ } function getTagSuccess(data) { - vm.tags = data || []; vm.tagCount[vm.repoName] = vm.tags.length; @@ -59,6 +101,10 @@ angular.forEach(vm.tags, function(item) { vm.toggleInProgress[vm.repoName + '|' + item] = false; }); + + for(var i = 0; i < vm.tags.length; i++) { + vm.selected[vm.repoName][i] = false; + } } function getTagFailed(data) { @@ -72,6 +118,28 @@ $scope.$emit('repoName', e.repoName); $scope.$emit('tag', e.tag); vm.deleteByTag(); + } + + function selectOne(index, tagName) { + vm.selected[vm.repoName][index] = !vm.selected[vm.repoName][index]; + (vm.selected[vm.repoName][index]) ? ++vm.selectedCount[vm.repoName] : --vm.selectedCount[vm.repoName]; + console.log('selectOne, repoName:' + vm.repoName + ', vm.selected:' + vm.selected[vm.repoName][index] + ', index:' + index + ', length:' + vm.selectedCount[vm.repoName]); + gatherSelectedTags(); + } + + function gatherSelectedTags() { + vm.selectedTags[vm.repoName] = []; + for(var i = 0; i < vm.tags.length; i++) { + (vm.selected[vm.repoName][i]) ? vm.selectedTags[vm.repoName][i] = vm.tags[i] : vm.selectedTags[vm.repoName][i] = ''; + } + var tagsToDelete = []; + for(var i in vm.selectedTags[vm.repoName]) { + var tag = vm.selectedTags[vm.repoName][i]; + if(tag !== '') { + tagsToDelete.push(tag); + } + } + $scope.$emit('selectedTags', {'repoName': vm.repoName, 'tags': tagsToDelete}); } } @@ -97,4 +165,4 @@ } -})(); +})(); \ No newline at end of file diff --git a/src/ui/static/resources/js/components/repository/pull-command.directive.html b/src/ui/static/resources/js/components/repository/pull-command.directive.html index 2931b06fc..6b03d4a4c 100644 --- a/src/ui/static/resources/js/components/repository/pull-command.directive.html +++ b/src/ui/static/resources/js/components/repository/pull-command.directive.html @@ -1,7 +1,5 @@
-
-
- -
+
+
\ No newline at end of file diff --git a/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js b/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js index de5a02338..9da2e4ab7 100644 --- a/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js +++ b/src/ui/static/resources/js/services/i18n/locale_messages_en-US.js @@ -142,6 +142,7 @@ var locale_messages = { '
Delete repository "$0" now?', 'alert_delete_tag_title': 'Confirm Deletion', 'alert_delete_tag': 'Note: All tags under this repository will be deleted if they are pointing to this image.

Delete tag "$0" now?', + 'alert_delete_selected_tag': 'Note: All selected tags under this repository will be deleted if they are pointing to this image.

Delete selected tags now?', 'close': 'Close', 'ok': 'OK', 'welcome': 'Welcome to Harbor!', @@ -217,6 +218,7 @@ var locale_messages = { 'select_all': 'Select All', 'delete_tag': 'Delete Tag', 'delete_repo': 'Delete Repo', + 'delete_selected_tag': 'Delete Selected Tag(s)', 'download_log': 'View Logs', 'edit': 'Edit', 'delete': 'Delete', diff --git a/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js b/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js index 451351edf..f25fff0eb 100644 --- a/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js +++ b/src/ui/static/resources/js/services/i18n/locale_messages_zh-CN.js @@ -142,6 +142,7 @@ var locale_messages = { '
是否删除镜像仓库 "$0" ?', 'alert_delete_tag_title': '确认删除', 'alert_delete_tag': '注意:此镜像仓库下所有指向该镜像的标签将会被删除。

删除镜像标签 "$0" ?', + 'alert_delete_selected_tag': '注意:此镜像仓库下选中的指向该镜像的标签将会被删除。

删除选中的镜像标签?', 'close': '关闭', 'ok': '确认', 'welcome': '欢迎使用Harbor!', @@ -217,6 +218,7 @@ var locale_messages = { 'select_all': '全选', 'delete_tag': '删除镜像标签', 'delete_repo': '删除镜像仓库', + 'delete_selected_tag': '删除选中镜像标签', 'download_log': '查看日志', 'edit': '修改', 'delete': '删除',