update for fine-grained 401 filtering and other refinements.

This commit is contained in:
kunw 2016-07-06 12:56:44 +08:00
parent a502635de1
commit be3110634a
14 changed files with 121 additions and 81 deletions

View File

@ -44,7 +44,7 @@
} }
function getProjectSuccess(data, status) { function getProjectSuccess(data, status) {
vm.projects = data; vm.projects = data || [];
if(!angular.isDefined(vm.projects)) { if(!angular.isDefined(vm.projects)) {
vm.isPublic = 1; vm.isPublic = 1;
@ -77,11 +77,11 @@
}); });
} }
function getProjectFailed(response) { function getProjectFailed() {
$scope.$emit('modalTitle', $filter('tr')('error')); // $scope.$emit('modalTitle', $filter('tr')('error'));
$scope.$emit('modalMessage', $filter('tr')('failed_to_get_project')); // $scope.$emit('modalMessage', $filter('tr')('failed_to_get_project'));
$scope.$emit('raiseError', true); // $scope.$emit('raiseError', true);
console.log('Failed to list projects:' + response); console.log('Failed to list projects.');
} }
function selectItem(item) { function selectItem(item) {

View File

@ -1,5 +1,3 @@
<a href="javascript:void(0)" role="button" tab-index="0" <a role="button" tab-index="0" data-trigger="focus" data-toggle="popover" data-placement="right" data-title="//vm.helpTitle//">
data-trigger="focus" data-toggle="popover" data-placement="right"
data-title="//vm.helpTitle//">
<span class="glyphicon glyphicon-info-sign"></span> <span class="glyphicon glyphicon-info-sign"></span>
</a> </a>

View File

@ -2,7 +2,7 @@
<td width="45%"><switch-role roles="vm.roles" edit-mode="vm.editMode" user-id="vm.userId" role-name="vm.roleName"></switch-role></td> <td width="45%"><switch-role roles="vm.roles" edit-mode="vm.editMode" user-id="vm.userId" role-name="vm.roleName"></switch-role></td>
<td width="25%"> <td width="25%">
<a ng-show="vm.userId != vm.currentUserId" href="javascript:void(0);" ng-click="vm.updateProjectMember({projectId: vm.projectId, userId: vm.userId, roleId: vm.roleId})"> <a ng-show="vm.userId != vm.currentUserId" href="javascript:void(0);" ng-click="vm.updateProjectMember({projectId: vm.projectId, userId: vm.userId, roleId: vm.roleId})">
<span ng-if="!vm.editMode" class="glyphicon glyphicon-pencil" title="// 'edit' | tr //"></span><span ng-if="vm.editMode" class="glyphicon glyphicon-ok" title="Confirm"> <span ng-if="!vm.editMode" class="glyphicon glyphicon-pencil" title="// 'edit' | tr //"></span><span ng-if="vm.editMode" class="glyphicon glyphicon-ok" title="// 'confirm' | tr //">
</a> </a>
<a ng-show="vm.userId != vm.currentUserId" href="javascript:void(0);" ng-click="vm.cancelUpdate()" title="// 'cancel' | tr //"> <a ng-show="vm.userId != vm.currentUserId" href="javascript:void(0);" ng-click="vm.cancelUpdate()" title="// 'cancel' | tr //">
<span ng-if="vm.editMode" class="glyphicon glyphicon-remove"></span> <span ng-if="vm.editMode" class="glyphicon glyphicon-remove"></span>

View File

@ -14,7 +14,7 @@
</div> </div>
<div class="form-group" style="margin-top: 5px;"> <div class="form-group" style="margin-top: 5px;">
<input type="checkbox" ng-model="vm.isPublic">&nbsp;// 'public' | tr // <input type="checkbox" ng-model="vm.isPublic">&nbsp;// 'public' | tr //
<inline-help help-title="// 'inline_help_publicity_title' | tr //" content="// 'inline_help_publicity' | tr //"></inline-help> <inline-help help-title="//'inline_help_publicity_title' | tr//" content="//'inline_help_publicity' | tr//"></inline-help>
</div> </div>
</div> </div>
<div class="col-xs-2 col-md-2"> <div class="col-xs-2 col-md-2">

View File

@ -6,19 +6,38 @@
.module('harbor.project') .module('harbor.project')
.directive('publicityButton', publicityButton); .directive('publicityButton', publicityButton);
PublicityButtonController.$inject = ['ToggleProjectPublicityService']; PublicityButtonController.$inject = ['$scope', 'ToggleProjectPublicityService', '$filter', 'trFilter'];
function PublicityButtonController(ToggleProjectPublicityService) { function PublicityButtonController($scope, ToggleProjectPublicityService, $filter, trFilter) {
var vm = this; var vm = this;
vm.toggle = toggle; vm.toggle = toggle;
if(vm.isPublic === 1) { function toggle() {
vm.isPublic = true; if(vm.isPublic) {
}else{ vm.isPublic = false;
vm.isPublic = false; }else{
vm.isPublic = true;
}
ToggleProjectPublicityService(vm.projectId, vm.isPublic)
.success(toggleProjectPublicitySuccess)
.error(toggleProjectPublicityFailed);
} }
function toggle() { function toggleProjectPublicitySuccess(data, status) {
console.log('Successful toggle project publicity.');
}
function toggleProjectPublicityFailed(e, status) {
$scope.$emit('modalTitle', $filter('tr')('error'));
var message;
if(status === 403) {
message = $filter('tr')('failed_to_toggle_publicity_insuffient_permissions');
}else{
message = $filter('tr')('failed_to_toggle_publicity');
}
$scope.$emit('modalMessage', message);
$scope.$emit('raiseError', true);
if(vm.isPublic) { if(vm.isPublic) {
vm.isPublic = false; vm.isPublic = false;
@ -26,16 +45,6 @@
vm.isPublic = true; vm.isPublic = true;
} }
ToggleProjectPublicityService(vm.projectId, vm.isPublic)
.success(toggleProjectPublicitySuccess)
.error(toggleProjectPublicityFailed);
}
function toggleProjectPublicitySuccess(data, status) {
console.log('Successful toggle project publicity.');
}
function toggleProjectPublicityFailed(e) {
console.log('Failed to toggle project publicity:' + e); console.log('Failed to toggle project publicity:' + e);
} }
} }
@ -57,7 +66,11 @@
return directive; return directive;
function link(scope, element, attr, ctrl) { function link(scope, element, attr, ctrl) {
scope.$watch('vm.isPublic', function(current, origin) {
if(current) {
ctrl.isPublic = current;
}
});
} }
} }

View File

@ -31,13 +31,13 @@
function retrieve() { function retrieve() {
ListTagService(vm.repoName) ListTagService(vm.repoName)
.then(getTagComplete) .success(getTagSuccess)
.catch(getTagFailed); .error(getTagFailed);
} }
function getTagComplete(response) { function getTagSuccess(data) {
vm.tags = response.data; vm.tags = data || [];
vm.tagCount[vm.repoName] = vm.tags.length; vm.tagCount[vm.repoName] = vm.tags.length;
$scope.$emit('tags', vm.tags); $scope.$emit('tags', vm.tags);
@ -48,11 +48,11 @@
}); });
} }
function getTagFailed(response) { function getTagFailed(data) {
$scope.$emit('modalTitle', $filter('tr')('error')); $scope.$emit('modalTitle', $filter('tr')('error'));
$scope.$emit('modalMessage', $filter('tr')('failed_to_get_tag') + response); $scope.$emit('modalMessage', $filter('tr')('failed_to_get_tag') + response);
$scope.$emit('raiseError', true); $scope.$emit('raiseError', true);
console.log('Failed to get tag:' + response); console.log('Failed to get tag:' + data);
} }
function deleteTag(e) { function deleteTag(e) {

View File

@ -49,7 +49,7 @@
<div class="form-group col-md-12 form-group-custom"> <div class="form-group col-md-12 form-group-custom">
<div class="col-md-3"></div> <div class="col-md-3"></div>
<div class="col-md-9"> <div class="col-md-9">
<button type="submit" class="btn btn-default" ng-disabled="vm.notAvailable || !vm.pingAvailable" ng-click="form.$valid && vm.pingDestination()" loading-progress hide-target="false" toggle-in-progress="vm.pingTIP">// 'test_connection' | tr //</button> <button type="button" class="btn btn-default" ng-disabled="vm.notAvailable || !vm.pingAvailable" ng-click="vm.pingDestination()" loading-progress hide-target="false" toggle-in-progress="vm.pingTIP">// 'test_connection' | tr //</button>
</div> </div>
</div> </div>
<div class="form-group col-md-12 form-group-custom"> <div class="form-group col-md-12 form-group-custom">

View File

@ -21,7 +21,7 @@
vm.pingDestination = pingDestination; vm.pingDestination = pingDestination;
vm.editable = true; vm.editable = true;
vm.notAvailable = true; vm.notAvailable = false;
vm.pingAvailable = true; vm.pingAvailable = true;
vm.pingMessage = ''; vm.pingMessage = '';
@ -40,7 +40,6 @@
}); });
function addNew() { function addNew() {
vm.editable = true;
vm.modalTitle = $filter('tr')('add_new_destination', []); vm.modalTitle = $filter('tr')('add_new_destination', []);
vm0.name = ''; vm0.name = '';
vm0.endpoint = ''; vm0.endpoint = '';
@ -153,7 +152,7 @@
function pingDestinationFailed(data, status) { function pingDestinationFailed(data, status) {
vm.pingTIP = false; vm.pingTIP = false;
vm.pingMessage = $filter('tr')('failed_to_ping_target', []) + (data && data.length > 0 ? ':' + data : '.'); vm.pingMessage = $filter('tr')('failed_to_ping_target', []) + (data && data.length > 0 ? ':' + data : '');
} }
} }
@ -176,34 +175,34 @@
function link(scope, element, attrs, ctrl) { function link(scope, element, attrs, ctrl) {
element.find('#createDestinationModal').on('show.bs.modal', function() { element.find('#createDestinationModal').on('show.bs.modal', function() {
scope.$apply(function(){
scope.form.$setPristine(); scope.form.$setPristine();
scope.form.$setUntouched(); scope.form.$setUntouched();
ctrl.notAvailble = true; ctrl.notAvailble = false;
ctrl.pingAvailable = true; ctrl.pingAvailable = true;
ctrl.pingMessage = ''; ctrl.pingMessage = '';
ctrl.pingTIP = false; ctrl.pingTIP = false;
ctrl.toggleErrorMessage = false; ctrl.toggleErrorMessage = false;
ctrl.errorMessages = []; ctrl.errorMessages = [];
switch(ctrl.action) { switch(ctrl.action) {
case 'ADD_NEW': case 'ADD_NEW':
ctrl.addNew(); ctrl.addNew();
break; break;
case 'EDIT': case 'EDIT':
ctrl.edit(ctrl.targetId); ctrl.edit(ctrl.targetId);
break; break;
}
scope.$watch('vm.errorMessages', function(current) {
if(current && current.length > 0) {
ctrl.toggleErrorMessage = true;
} }
}, true);
scope.$watch('vm.errorMessages', function(current) {
scope.$apply(); if(current && current.length > 0) {
ctrl.toggleErrorMessage = true;
}
}, true);
});
}); });
ctrl.save = save; ctrl.save = save;

View File

@ -33,9 +33,9 @@
<td width="30%">//r.endpoint//</td> <td width="30%">//r.endpoint//</td>
<td width="35%">//r.creation_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td> <td width="35%">//r.creation_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td>
<td width="15%"> <td width="15%">
<a href="javascript:void(0);" data-toggle="modal" data-target="#createDestinationModal" ng-click="vm.editDestination(r.id)"><span class="glyphicon glyphicon-pencil"></span></a> <a href="javascript:void(0);" data-toggle="modal" data-target="#createDestinationModal" ng-click="vm.editDestination(r.id)" title="// 'edit' | tr //" ><span class="glyphicon glyphicon-pencil"></span></a>
&nbsp; &nbsp;
<a href="javascript:void(0);" ng-click="vm.confirmToDelete(r.id)"><span class="glyphicon glyphicon-trash"></span></a> <a href="javascript:void(0);" ng-click="vm.confirmToDelete(r.id)" title="// 'delete' | tr //"><span class="glyphicon glyphicon-trash"></span></a>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View File

@ -42,11 +42,11 @@
</td> </td>
<td width="12%"> <td width="12%">
<div class="display-inline-block" ng-switch on="//r.enabled//"> <div class="display-inline-block" ng-switch on="//r.enabled//">
<a href="javascript:void(0);" ng-click="vm.togglePolicy(r.id, 0)"><span ng-switch-when="1" class="glyphicon glyphicon-stop color-danger"></span></a> <a href="javascript:void(0);" ng-click="vm.togglePolicy(r.id, 0)" title="// 'disable' | tr //"><span ng-switch-when="1" class="glyphicon glyphicon-stop color-danger"></span></a>
<a href="javascript:void(0);" ng-click="vm.togglePolicy(r.id, 1)"><span ng-switch-when="0" class="glyphicon glyphicon-play color-success"></span></a> <a href="javascript:void(0);" ng-click="vm.togglePolicy(r.id, 1)" title="// 'enable' | tr //"><span ng-switch-when="0" class="glyphicon glyphicon-play color-success"></span></a>
</div> </div>
&nbsp; &nbsp;
<a href="javascript:void(0);" data-toggle="modal" data-target="#createPolicyModal" ng-click="vm.editReplication(r.id)"><span class="glyphicon glyphicon-pencil"></span></a> <a href="javascript:void(0);" data-toggle="modal" data-target="#createPolicyModal" ng-click="vm.editReplication(r.id)" title="// 'edit_policy' | tr //"><span class="glyphicon glyphicon-pencil"></span></a>
&nbsp; &nbsp;
<!--a href="javascript:void(0);"><span class="glyphicon glyphicon-trash"></span></a--> <!--a href="javascript:void(0);"><span class="glyphicon glyphicon-trash"></span></a-->
</td> </td>

View File

@ -34,6 +34,11 @@
$scope.$emit('modalTitle', $filter('tr')('error')); $scope.$emit('modalTitle', $filter('tr')('error'));
$scope.$emit('modalMessage', $filter('tr')('failed_to_toggle_admin')); $scope.$emit('modalMessage', $filter('tr')('failed_to_toggle_admin'));
$scope.$emit('raiseError', true); $scope.$emit('raiseError', true);
if(vm.isAdmin) {
vm.isAdmin = false;
}else{
vm.isAdmin = true;
}
console.log('Failed to toggle admin:' + data); console.log('Failed to toggle admin:' + data);
} }
} }

View File

@ -20,17 +20,36 @@
function RedirectInterceptorService($q, $window) { function RedirectInterceptorService($q, $window) {
return { return {
'responseError': function(rejection) { 'responseError': function(rejection) {
var pathname = $window.location.pathname; var url = rejection.config.url;
var exclusion = ['/', '/search', '/reset_password', '/sign_up', '/forgot_password', '/repository']; console.log('url:' + url);
var exclusion = [
'/',
'/search',
'/reset_password',
'/sign_up',
'/forgot_password',
'/api/targets/ping',
'/api/users/current',
'/api/repositories',
/^\/api\/projects\/[0-9]+\/members\/current$/
];
var isExcluded = false; var isExcluded = false;
for(var i in exclusion) { for(var i in exclusion) {
if(exclusion[i] === pathname) { switch(typeof(exclusion[i])) {
isExcluded = true; case 'string':
isExcluded = (exclusion[i] === url);
break;
case 'object':
isExcluded = exclusion[i].test(url);
break; break;
} }
} if(isExcluded) {
if(rejection.status === 401 && !isExcluded) { break;
}
}
if(!isExcluded && rejection.status === 401) {
$window.location.href = '/'; $window.location.href = '/';
return;
} }
return $q.reject(rejection); return $q.reject(rejection);
} }

View File

@ -79,6 +79,7 @@ var locale_messages = {
'new_project': 'New Project', 'new_project': 'New Project',
'save': 'Save', 'save': 'Save',
'cancel': 'Cancel', 'cancel': 'Cancel',
'confirm': 'Confirm',
'items': 'items', 'items': 'items',
'add_member': 'Add Member', 'add_member': 'Add Member',
'operation': 'Operation', 'operation': 'Operation',
@ -188,9 +189,9 @@ var locale_messages = {
'successful_added': 'Added new user successfully.', 'successful_added': 'Added new user successfully.',
'copyright': 'Copyright', 'copyright': 'Copyright',
'all_rights_reserved': 'All Rights Reserved.', 'all_rights_reserved': 'All Rights Reserved.',
'pinging_target': 'Testing connection, please wait...', 'pinging_target': 'Testing connection, please stand by...',
'successful_ping_target': 'Test connection successfully.', 'successful_ping_target': 'Test connection successfully.',
'failed_to_ping_target': 'Faild to connect target.', 'failed_to_ping_target': 'Cannot connect to the target.',
'policy_already_exists': 'Policy alreay exists.', 'policy_already_exists': 'Policy alreay exists.',
'destination_already_exists': 'Destination already exists.', 'destination_already_exists': 'Destination already exists.',
'refresh': 'Refresh', 'refresh': 'Refresh',
@ -238,6 +239,8 @@ var locale_messages = {
'failed_to_delete_destination': 'Failed to delete destination.', 'failed_to_delete_destination': 'Failed to delete destination.',
'failed_to_create_destination': 'Failed to create destination.', 'failed_to_create_destination': 'Failed to create destination.',
'failed_to_update_destination': 'Failed to update destination.', 'failed_to_update_destination': 'Failed to update destination.',
'failed_to_toggle_publicity_insuffient_permissions': 'Failed to toggle project publicity, insuffient permissions.',
'failed_to_toggle_publicity': 'Failed to toggle project publicity.',
'project_admin': 'Project Admin', 'project_admin': 'Project Admin',
'developer': 'Developer', 'developer': 'Developer',
'guest': 'Guest', 'guest': 'Guest',
@ -247,6 +250,6 @@ var locale_messages = {
'<strong>Guest</strong>: Guest has read-only privilege for a specified project.', '<strong>Guest</strong>: Guest has read-only privilege for a specified project.',
'inline_help_publicity_title': '<strong>Publicity of Project</strong>', 'inline_help_publicity_title': '<strong>Publicity of Project</strong>',
'inline_help_publicity': 'Setting the project as public.', 'inline_help_publicity': 'Setting the project as public.',
'alert_job_contains_error': 'There contain errors in current replication jobs results, please look into it.', 'alert_job_contains_error': 'Found errors in the current replication jobs, please look into it.',
'caution': 'Caution' 'caution': 'Caution'
}; };

View File

@ -79,6 +79,7 @@ var locale_messages = {
'new_project': '新增项目', 'new_project': '新增项目',
'save': '保存', 'save': '保存',
'cancel': '取消', 'cancel': '取消',
'confirm': '确认',
'items': '条记录', 'items': '条记录',
'add_member': '新增成员', 'add_member': '新增成员',
'operation': '操作', 'operation': '操作',
@ -237,6 +238,8 @@ var locale_messages = {
'failed_to_delete_destination': '删除目标失败。', 'failed_to_delete_destination': '删除目标失败。',
'failed_to_create_destination': '创建目标失败。', 'failed_to_create_destination': '创建目标失败。',
'failed_to_update_destination': '修改目标失败。', 'failed_to_update_destination': '修改目标失败。',
'failed_to_toggle_publicity_insuffient_permissions': '切换项目公开失败,权限不足。',
'failed_to_toggle_publicity': '切换项目公开失败。',
'project_admin': '项目管理员', 'project_admin': '项目管理员',
'developer': '开发人员', 'developer': '开发人员',
'guest': '来宾用户', 'guest': '来宾用户',