mirror of
https://github.com/wahyd4/harbor.git
synced 2026-08-23 03:36:35 +10:00
Merge remote-tracking branch 'upstream/new-ui-with-sync-image' into new-ui-with-sync-image
This commit is contained in:
@@ -8,6 +8,7 @@ REGISTRY_URL=http://registry:5000
|
||||
VERIFY_REMOTE_CERT=$verify_remote_cert
|
||||
MAX_JOB_WORKERS=$max_job_workers
|
||||
LOG_LEVEL=debug
|
||||
LOG_DIR=/var/log/jobs
|
||||
GODEBUG=netdns=cgo
|
||||
EXT_ENDPOINT=$ui_url
|
||||
TOKEN_URL=http://ui
|
||||
|
||||
+22
-22
@@ -1139,24 +1139,40 @@ func TestGetRepPolicyByProject(t *testing.T) {
|
||||
func TestGetRepJobByPolicy(t *testing.T) {
|
||||
jobs, err := GetRepJobByPolicy(999)
|
||||
if err != nil {
|
||||
log.Errorf("Error occured in GetRepJobByPolicy: %v, policy ID: %d", err, 999)
|
||||
t.Errorf("Error occured in GetRepJobByPolicy: %v, policy ID: %d", err, 999)
|
||||
return
|
||||
}
|
||||
if len(jobs) > 0 {
|
||||
log.Errorf("Unexpected length of jobs, expected: 0, in fact: %d", len(jobs))
|
||||
t.Errorf("Unexpected length of jobs, expected: 0, in fact: %d", len(jobs))
|
||||
return
|
||||
}
|
||||
jobs, err = GetRepJobByPolicy(policyID)
|
||||
if err != nil {
|
||||
log.Errorf("Error occured in GetRepJobByPolicy: %v, policy ID: %d", err, policyID)
|
||||
t.Errorf("Error occured in GetRepJobByPolicy: %v, policy ID: %d", err, policyID)
|
||||
return
|
||||
}
|
||||
if len(jobs) != 1 {
|
||||
log.Errorf("Unexpected length of jobs, expected: 1, in fact: %d", len(jobs))
|
||||
t.Errorf("Unexpected length of jobs, expected: 1, in fact: %d", len(jobs))
|
||||
return
|
||||
}
|
||||
if jobs[0].ID != jobID {
|
||||
log.Errorf("Unexpected job ID in the result, expected: %d, in fact: %d", jobID, jobs[0].ID)
|
||||
t.Errorf("Unexpected job ID in the result, expected: %d, in fact: %d", jobID, jobs[0].ID)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterRepJobs(t *testing.T) {
|
||||
jobs, err := FilterRepJobs(policyID, "", "", nil, nil, 1000)
|
||||
if err != nil {
|
||||
t.Errorf("Error occured in FilterRepJobs: %v, policy ID: %d", err, policyID)
|
||||
return
|
||||
}
|
||||
if len(jobs) != 1 {
|
||||
t.Errorf("Unexpected length of jobs, expected: 1, in fact: %d", len(jobs))
|
||||
return
|
||||
}
|
||||
if jobs[0].ID != jobID {
|
||||
t.Errorf("Unexpected job ID in the result, expected: %d, in fact: %d", jobID, jobs[0].ID)
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -1179,22 +1195,6 @@ func TestDeleteRepJob(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterRepJobs(t *testing.T) {
|
||||
jobs, err := FilterRepJobs(policyID, "", "", nil, nil, 1000)
|
||||
if err != nil {
|
||||
log.Errorf("Error occured in FilterRepJobs: %v, policy ID: %d", err, policyID)
|
||||
return
|
||||
}
|
||||
if len(jobs) != 1 {
|
||||
log.Errorf("Unexpected length of jobs, expected: 1, in fact: %d", len(jobs))
|
||||
return
|
||||
}
|
||||
if jobs[0].ID != jobID {
|
||||
log.Errorf("Unexpected job ID in the result, expected: %d, in fact: %d", jobID, jobs[0].ID)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetRepoJobToStop(t *testing.T) {
|
||||
jobs := [...]models.RepJob{
|
||||
models.RepJob{
|
||||
@@ -1265,7 +1265,7 @@ func TestDeleteRepTarget(t *testing.T) {
|
||||
func TestFilterRepPolicies(t *testing.T) {
|
||||
_, err := FilterRepPolicies("name", 0)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to filter policy")
|
||||
t.Fatalf("failed to filter policy: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -150,10 +150,13 @@ func FilterRepPolicies(name string, projectID int64) ([]*models.RepPolicy, error
|
||||
|
||||
sql := `select rp.id, rp.project_id, p.name as project_name, rp.target_id,
|
||||
rt.name as target_name, rp.name, rp.enabled, rp.description,
|
||||
rp.cron_str, rp.start_time, rp.creation_time, rp.update_time
|
||||
rp.cron_str, rp.start_time, rp.creation_time, rp.update_time,
|
||||
count(rj.status) as error_job_count
|
||||
from replication_policy rp
|
||||
join project p on rp.project_id=p.project_id
|
||||
join replication_target rt on rp.target_id=rt.id `
|
||||
left join project p on rp.project_id=p.project_id
|
||||
left join replication_target rt on rp.target_id=rt.id
|
||||
left join replication_job rj on rp.id=rj.policy_id and (rj.status="error"
|
||||
or rj.status="retrying") `
|
||||
|
||||
if len(name) != 0 && projectID != 0 {
|
||||
sql += `where rp.name like ? and rp.project_id = ? `
|
||||
@@ -167,7 +170,7 @@ func FilterRepPolicies(name string, projectID int64) ([]*models.RepPolicy, error
|
||||
args = append(args, projectID)
|
||||
}
|
||||
|
||||
sql += `order by rp.creation_time`
|
||||
sql += `group by rp.id order by rp.creation_time`
|
||||
|
||||
var policies []*models.RepPolicy
|
||||
if _, err := o.Raw(sql, args).QueryRows(&policies); err != nil {
|
||||
|
||||
@@ -23,7 +23,7 @@ func retry(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
return isTemporary(err)
|
||||
return isNetworkErr(err)
|
||||
}
|
||||
|
||||
func isTemporary(err error) bool {
|
||||
@@ -32,3 +32,8 @@ func isTemporary(err error) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isNetworkErr(err error) bool {
|
||||
_, ok := err.(net.Error)
|
||||
return ok
|
||||
}
|
||||
|
||||
@@ -56,12 +56,13 @@ type RepPolicy struct {
|
||||
TargetName string `json:"target_name,omitempty"`
|
||||
Name string `orm:"column(name)" json:"name"`
|
||||
// Target RepTarget `orm:"-" json:"target"`
|
||||
Enabled int `orm:"column(enabled)" json:"enabled"`
|
||||
Description string `orm:"column(description)" json:"description"`
|
||||
CronStr string `orm:"column(cron_str)" json:"cron_str"`
|
||||
StartTime time.Time `orm:"column(start_time)" json:"start_time"`
|
||||
CreationTime time.Time `orm:"column(creation_time);auto_now_add" json:"creation_time"`
|
||||
UpdateTime time.Time `orm:"column(update_time);auto_now" json:"update_time"`
|
||||
Enabled int `orm:"column(enabled)" json:"enabled"`
|
||||
Description string `orm:"column(description)" json:"description"`
|
||||
CronStr string `orm:"column(cron_str)" json:"cron_str"`
|
||||
StartTime time.Time `orm:"column(start_time)" json:"start_time"`
|
||||
CreationTime time.Time `orm:"column(creation_time);auto_now_add" json:"creation_time"`
|
||||
UpdateTime time.Time `orm:"column(update_time);auto_now" json:"update_time"`
|
||||
ErrorJobCount int `json:"error_job_count"`
|
||||
}
|
||||
|
||||
// Valid ...
|
||||
|
||||
@@ -110,20 +110,34 @@
|
||||
}
|
||||
|
||||
.popover-header {
|
||||
padding:8px 14px;
|
||||
background-color:#f7f7f7;
|
||||
border-bottom:1px solid #ebebeb;
|
||||
-webkit-border-radius:5px 5px 0 0;
|
||||
-moz-border-radius:5px 5px 0 0;
|
||||
border-radius:5px 5px 0 0;
|
||||
padding:8px 14px;
|
||||
background-color:#f7f7f7;
|
||||
border-bottom:1px solid #ebebeb;
|
||||
-webkit-border-radius:5px 5px 0 0;
|
||||
-moz-border-radius:5px 5px 0 0;
|
||||
border-radius:5px 5px 0 0;
|
||||
}
|
||||
|
||||
.popover-title {
|
||||
height: 2.5em;
|
||||
padding: 8px 14px;
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
border-radius: 5px 5px 0 0;
|
||||
height: 2.5em;
|
||||
padding: 8px 14px;
|
||||
margin: 0;
|
||||
font-size: 14px;
|
||||
background-color: #f7f7f7;
|
||||
border-bottom: 1px solid #ebebeb;
|
||||
border-radius: 5px 5px 0 0;
|
||||
}
|
||||
|
||||
.alert-custom {
|
||||
position: fixed;
|
||||
bottom: 24px;
|
||||
z-index: 99;
|
||||
width: 1110px;
|
||||
padding: 10px;
|
||||
background-color: #f2dede;
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
.alert-custom .close {
|
||||
right: 0;
|
||||
}
|
||||
@@ -44,7 +44,7 @@
|
||||
}
|
||||
|
||||
function getProjectSuccess(data, status) {
|
||||
vm.projects = data;
|
||||
vm.projects = data || [];
|
||||
|
||||
if(!angular.isDefined(vm.projects)) {
|
||||
vm.isPublic = 1;
|
||||
@@ -77,11 +77,11 @@
|
||||
});
|
||||
}
|
||||
|
||||
function getProjectFailed(response) {
|
||||
$scope.$emit('modalTitle', $filter('tr')('error'));
|
||||
$scope.$emit('modalMessage', $filter('tr')('failed_to_get_project'));
|
||||
$scope.$emit('raiseError', true);
|
||||
console.log('Failed to list projects:' + response);
|
||||
function getProjectFailed() {
|
||||
// $scope.$emit('modalTitle', $filter('tr')('error'));
|
||||
// $scope.$emit('modalMessage', $filter('tr')('failed_to_get_project'));
|
||||
// $scope.$emit('raiseError', true);
|
||||
console.log('Failed to list projects.');
|
||||
}
|
||||
|
||||
function selectItem(item) {
|
||||
@@ -91,7 +91,6 @@
|
||||
|
||||
$scope.$on('$locationChangeSuccess', function(e) {
|
||||
var projectId = getParameterByName('project_id', $location.absUrl());
|
||||
vm.checkProjectMember(projectId);
|
||||
vm.isOpen = false;
|
||||
});
|
||||
|
||||
@@ -107,12 +106,7 @@
|
||||
}
|
||||
|
||||
function getCurrentProjectMemberFailed(data, status) {
|
||||
vm.isProjectMember = false;
|
||||
|
||||
// $scope.$emit('modalTitle', $filter('tr')('error'));
|
||||
// $scope.$emit('modalMessage', $filter('tr')('failed_to_get_project_member'));
|
||||
// $scope.$emit('raiseError', true);
|
||||
|
||||
vm.isProjectMember = false;
|
||||
console.log('Current user has no member for the project:' + status + ', location.url:' + $location.url());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<div ng-show="toggleAlert" class="alert alert-danger alert-dismissible alert-custom" role="alert">
|
||||
<button type="button" class="close" ng-click="close()"><span aria-hidden="true">×</span></button>
|
||||
<strong>// 'caution' | tr //</strong> //message//
|
||||
</div>
|
||||
@@ -0,0 +1,34 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('harbor.dismissable.alerts')
|
||||
.directive('dismissableAlerts', dismissableAlerts);
|
||||
|
||||
function dismissableAlerts() {
|
||||
var directive = {
|
||||
'restrict': 'E',
|
||||
'templateUrl': '/static/resources/js/components/dismissable-alerts/dismissable-alerts.directive.html',
|
||||
'link': link
|
||||
};
|
||||
return directive;
|
||||
function link(scope, element, attrs, ctrl) {
|
||||
|
||||
scope.close = function() {
|
||||
scope.toggleAlert = false;
|
||||
}
|
||||
scope.$on('raiseAlert', function(e, val) {
|
||||
console.log('received raiseAlert:' + angular.toJson(val));
|
||||
if(val.show) {
|
||||
scope.message = val.message;
|
||||
scope.toggleAlert = true;
|
||||
}else{
|
||||
scope.message = ''
|
||||
scope.toggleAlert = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,7 @@
|
||||
(function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
angular.module('harbor.dismissable.alerts', []);
|
||||
|
||||
})();
|
||||
@@ -1,5 +1,3 @@
|
||||
<a href="javascript:void(0)" role="button" tab-index="0"
|
||||
data-trigger="focus" data-toggle="popover" data-placement="right"
|
||||
data-title="//vm.helpTitle//">
|
||||
<a role="button" tab-index="0" data-trigger="focus" data-toggle="popover" data-placement="right" data-title="//vm.helpTitle//">
|
||||
<span class="glyphicon glyphicon-info-sign"></span>
|
||||
</a>
|
||||
@@ -37,9 +37,15 @@
|
||||
'projectId': vm.projectId,
|
||||
'username' : vm.username
|
||||
};
|
||||
|
||||
retrieve(vm.queryParams);
|
||||
|
||||
$scope.$on('$locationChangeSuccess', function() {
|
||||
|
||||
if(vm.publicity) {
|
||||
vm.target = 'repositories';
|
||||
}
|
||||
|
||||
vm.projectId = getParameterByName('project_id', $location.absUrl());
|
||||
vm.queryParams = {
|
||||
'beginTimestamp' : vm.beginTimestamp,
|
||||
@@ -128,7 +134,9 @@
|
||||
restrict: 'E',
|
||||
templateUrl: '/static/resources/js/components/log/list-log.directive.html',
|
||||
scope: {
|
||||
'sectionHeight': '='
|
||||
'sectionHeight': '=',
|
||||
'target': '=',
|
||||
'publicity': '='
|
||||
},
|
||||
controller: ListLogController,
|
||||
controllerAs: 'vm',
|
||||
|
||||
@@ -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="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})">
|
||||
<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 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>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
vm.deleteProjectMember = deleteProjectMember;
|
||||
vm.retrieve = retrieve;
|
||||
vm.username = '';
|
||||
|
||||
|
||||
vm.projectId = getParameterByName('project_id', $location.absUrl());
|
||||
vm.retrieve();
|
||||
|
||||
@@ -78,11 +78,7 @@
|
||||
function getProjectMemberFailed(response) {
|
||||
console.log('Failed to get project members:' + response);
|
||||
vm.projectMembers = [];
|
||||
|
||||
$scope.$emit('modalTitle', $filter('tr')('error'));
|
||||
$scope.$emit('modalMessage', $filter('tr')('failed_to_get_project_member'));
|
||||
$scope.$emit('raiseError', true);
|
||||
|
||||
vm.target = 'repositories';
|
||||
$location.url('repositories').search('project_id', vm.projectId);
|
||||
}
|
||||
|
||||
@@ -93,7 +89,8 @@
|
||||
'restrict': 'E',
|
||||
'templateUrl': '/static/resources/js/components/project-member/list-project-member.directive.html',
|
||||
'scope': {
|
||||
'sectionHeight': '='
|
||||
'sectionHeight': '=',
|
||||
'target': '='
|
||||
},
|
||||
'controller': ListProjectMemberController,
|
||||
'controllerAs': 'vm',
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</div>
|
||||
<div class="form-group" style="margin-top: 5px;">
|
||||
<input type="checkbox" ng-model="vm.isPublic"> // '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 class="col-xs-2 col-md-2">
|
||||
|
||||
@@ -6,19 +6,38 @@
|
||||
.module('harbor.project')
|
||||
.directive('publicityButton', publicityButton);
|
||||
|
||||
PublicityButtonController.$inject = ['ToggleProjectPublicityService'];
|
||||
PublicityButtonController.$inject = ['$scope', 'ToggleProjectPublicityService', '$filter', 'trFilter'];
|
||||
|
||||
function PublicityButtonController(ToggleProjectPublicityService) {
|
||||
function PublicityButtonController($scope, ToggleProjectPublicityService, $filter, trFilter) {
|
||||
var vm = this;
|
||||
vm.toggle = toggle;
|
||||
|
||||
if(vm.isPublic === 1) {
|
||||
vm.isPublic = true;
|
||||
}else{
|
||||
vm.isPublic = false;
|
||||
function toggle() {
|
||||
if(vm.isPublic) {
|
||||
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) {
|
||||
vm.isPublic = false;
|
||||
@@ -26,16 +45,6 @@
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -57,7 +66,11 @@
|
||||
return directive;
|
||||
|
||||
function link(scope, element, attr, ctrl) {
|
||||
|
||||
scope.$watch('vm.isPublic', function(current, origin) {
|
||||
if(current) {
|
||||
ctrl.isPublic = current;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,7 @@
|
||||
vm.policy = policy;
|
||||
if(vm.targetEditable) {
|
||||
vm.policy.targetId = vm1.selection.id;
|
||||
saveDestination();
|
||||
saveOrUpdatePolicy();
|
||||
}
|
||||
}
|
||||
@@ -366,6 +367,8 @@
|
||||
ctrl.pingMessage = '';
|
||||
ctrl.pingAvailable = true;
|
||||
|
||||
ctrl.saveTIP = false;
|
||||
ctrl.pingTIP = false;
|
||||
ctrl.toggleErrorMessage = false;
|
||||
ctrl.errorMessages = [];
|
||||
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
</td>
|
||||
<td width="15%">
|
||||
<div class="display-inline-block" ng-switch on="//r.enabled//">
|
||||
<a href="javascript:void(0);" ng-click="vm.togglePolicy(r.id, 0)" title="// 'disabled' | 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)" title="// 'enabled' | tr //"><span ng-switch-when="0" class="glyphicon glyphicon-play color-success"></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)" title="// 'enable' | tr //"><span ng-switch-when="0" class="glyphicon glyphicon-play color-success"></span></a>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
{'key': 'pending', 'value': $filter('tr')('pending')},
|
||||
{'key': 'running', 'value': $filter('tr')('running')},
|
||||
{'key': 'error' , 'value': $filter('tr')('error')},
|
||||
{'key': 'retrying', 'value': $filter('tr')('retrying')},
|
||||
{'key': 'stopped', 'value': $filter('tr')('stopped')},
|
||||
{'key': 'finished', 'value':$filter('tr')('finished')},
|
||||
{'key': 'canceled', 'value': $filter('tr')('canceled')}
|
||||
@@ -28,7 +29,7 @@
|
||||
var vm = this;
|
||||
|
||||
vm.sectionHeight = {'min-height': '1200px'};
|
||||
|
||||
|
||||
$scope.$on('$locationChangeSuccess', function() {
|
||||
vm.projectId = getParameterByName('project_id', $location.absUrl());
|
||||
vm.retrievePolicy();
|
||||
@@ -59,7 +60,7 @@
|
||||
|
||||
vm.searchJobTIP = false;
|
||||
vm.refreshJobTIP = false;
|
||||
|
||||
|
||||
function searchReplicationPolicy() {
|
||||
vm.retrievePolicy();
|
||||
}
|
||||
@@ -102,9 +103,17 @@
|
||||
|
||||
function listReplicationJobSuccess(data, status) {
|
||||
vm.replicationJobs = data || [];
|
||||
var alertInfo = {
|
||||
'show': false,
|
||||
'message': ''
|
||||
};
|
||||
angular.forEach(vm.replicationJobs, function(item) {
|
||||
for(var key in item) {
|
||||
var value = item[key]
|
||||
var value = item[key];
|
||||
if(key === 'status' && (value === 'error' || value === 'retrying')) {
|
||||
alertInfo.show = true;
|
||||
alertInfo.message = $filter('tr')('alert_job_contains_error');
|
||||
}
|
||||
switch(key) {
|
||||
case 'operation':
|
||||
case 'status':
|
||||
@@ -114,6 +123,8 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$scope.$emit('raiseAlert', alertInfo);
|
||||
vm.searchJobTIP = false;
|
||||
vm.refreshJobTIP = false;
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
vm.filterInput = '';
|
||||
vm.toggleInProgress = [];
|
||||
|
||||
|
||||
var hashValue = $location.hash();
|
||||
if(hashValue) {
|
||||
var slashIndex = hashValue.indexOf('/');
|
||||
|
||||
@@ -31,13 +31,13 @@
|
||||
|
||||
function retrieve() {
|
||||
ListTagService(vm.repoName)
|
||||
.then(getTagComplete)
|
||||
.catch(getTagFailed);
|
||||
.success(getTagSuccess)
|
||||
.error(getTagFailed);
|
||||
}
|
||||
|
||||
function getTagComplete(response) {
|
||||
function getTagSuccess(data) {
|
||||
|
||||
vm.tags = response.data;
|
||||
vm.tags = data || [];
|
||||
vm.tagCount[vm.repoName] = vm.tags.length;
|
||||
|
||||
$scope.$emit('tags', vm.tags);
|
||||
@@ -48,11 +48,11 @@
|
||||
});
|
||||
}
|
||||
|
||||
function getTagFailed(response) {
|
||||
function getTagFailed(data) {
|
||||
$scope.$emit('modalTitle', $filter('tr')('error'));
|
||||
$scope.$emit('modalMessage', $filter('tr')('failed_to_get_tag') + response);
|
||||
$scope.$emit('raiseError', true);
|
||||
console.log('Failed to get tag:' + response);
|
||||
console.log('Failed to get tag:' + data);
|
||||
}
|
||||
|
||||
function deleteTag(e) {
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<div class="form-group col-md-12 form-group-custom">
|
||||
<div class="col-md-3"></div>
|
||||
<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 class="form-group col-md-12 form-group-custom">
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
vm.pingDestination = pingDestination;
|
||||
|
||||
vm.editable = true;
|
||||
vm.notAvailable = true;
|
||||
vm.notAvailable = false;
|
||||
vm.pingAvailable = true;
|
||||
vm.pingMessage = '';
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
});
|
||||
|
||||
function addNew() {
|
||||
vm.editable = true;
|
||||
vm.modalTitle = $filter('tr')('add_new_destination', []);
|
||||
vm0.name = '';
|
||||
vm0.endpoint = '';
|
||||
@@ -153,7 +152,7 @@
|
||||
function pingDestinationFailed(data, status) {
|
||||
|
||||
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,33 +175,34 @@
|
||||
function link(scope, element, attrs, ctrl) {
|
||||
|
||||
element.find('#createDestinationModal').on('show.bs.modal', function() {
|
||||
|
||||
scope.form.$setPristine();
|
||||
scope.form.$setUntouched();
|
||||
|
||||
ctrl.notAvailble = true;
|
||||
ctrl.pingAvailable = true;
|
||||
ctrl.pingMessage = '';
|
||||
|
||||
ctrl.toggleErrorMessage = false;
|
||||
ctrl.errorMessages = [];
|
||||
|
||||
switch(ctrl.action) {
|
||||
case 'ADD_NEW':
|
||||
ctrl.addNew();
|
||||
break;
|
||||
case 'EDIT':
|
||||
ctrl.edit(ctrl.targetId);
|
||||
break;
|
||||
}
|
||||
|
||||
scope.$watch('vm.errorMessages', function(current) {
|
||||
if(current && current.length > 0) {
|
||||
ctrl.toggleErrorMessage = true;
|
||||
scope.$apply(function(){
|
||||
scope.form.$setPristine();
|
||||
scope.form.$setUntouched();
|
||||
|
||||
ctrl.notAvailble = false;
|
||||
ctrl.pingAvailable = true;
|
||||
ctrl.pingMessage = '';
|
||||
|
||||
ctrl.pingTIP = false;
|
||||
ctrl.toggleErrorMessage = false;
|
||||
ctrl.errorMessages = [];
|
||||
|
||||
switch(ctrl.action) {
|
||||
case 'ADD_NEW':
|
||||
ctrl.addNew();
|
||||
break;
|
||||
case 'EDIT':
|
||||
ctrl.edit(ctrl.targetId);
|
||||
break;
|
||||
}
|
||||
}, true);
|
||||
|
||||
scope.$apply();
|
||||
|
||||
scope.$watch('vm.errorMessages', function(current) {
|
||||
if(current && current.length > 0) {
|
||||
ctrl.toggleErrorMessage = true;
|
||||
}
|
||||
}, true);
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
ctrl.save = save;
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
<td width="30%">//r.endpoint//</td>
|
||||
<td width="35%">//r.creation_time | dateL : 'YYYY-MM-DD HH:mm:ss'//</td>
|
||||
<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>
|
||||
|
||||
<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>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@@ -42,11 +42,11 @@
|
||||
</td>
|
||||
<td width="12%">
|
||||
<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, 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, 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)" title="// 'enable' | tr //"><span ng-switch-when="0" class="glyphicon glyphicon-play color-success"></span></a>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
||||
<!--a href="javascript:void(0);"><span class="glyphicon glyphicon-trash"></span></a-->
|
||||
</td>
|
||||
|
||||
@@ -34,6 +34,11 @@
|
||||
$scope.$emit('modalTitle', $filter('tr')('error'));
|
||||
$scope.$emit('modalMessage', $filter('tr')('failed_to_toggle_admin'));
|
||||
$scope.$emit('raiseError', true);
|
||||
if(vm.isAdmin) {
|
||||
vm.isAdmin = false;
|
||||
}else{
|
||||
vm.isAdmin = true;
|
||||
}
|
||||
console.log('Failed to toggle admin:' + data);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,17 +20,36 @@
|
||||
function RedirectInterceptorService($q, $window) {
|
||||
return {
|
||||
'responseError': function(rejection) {
|
||||
var pathname = $window.location.pathname;
|
||||
var exclusion = ['/', '/search', '/reset_password', '/sign_up', '/forgot_password', '/repository'];
|
||||
var url = rejection.config.url;
|
||||
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;
|
||||
for(var i in exclusion) {
|
||||
if(exclusion[i] === pathname) {
|
||||
isExcluded = true;
|
||||
switch(typeof(exclusion[i])) {
|
||||
case 'string':
|
||||
isExcluded = (exclusion[i] === url);
|
||||
break;
|
||||
case 'object':
|
||||
isExcluded = exclusion[i].test(url);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(rejection.status === 401 && !isExcluded) {
|
||||
if(isExcluded) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!isExcluded && rejection.status === 401) {
|
||||
$window.location.href = '/';
|
||||
return;
|
||||
}
|
||||
return $q.reject(rejection);
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
'harbor.replication',
|
||||
'harbor.system.management',
|
||||
'harbor.loading.progress',
|
||||
'harbor.inline.help'
|
||||
'harbor.inline.help',
|
||||
'harbor.dismissable.alerts'
|
||||
]);
|
||||
})();
|
||||
@@ -15,7 +15,6 @@
|
||||
vm.isProjectMember = false;
|
||||
|
||||
vm.togglePublicity = togglePublicity;
|
||||
vm.target = 'repositories';
|
||||
|
||||
vm.sectionDefaultHeight = {'min-height': '579px'};
|
||||
|
||||
@@ -55,7 +54,7 @@
|
||||
}
|
||||
});
|
||||
|
||||
function togglePublicity(e) {
|
||||
function togglePublicity(e) {
|
||||
vm.publicity = e.publicity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ var locale_messages = {
|
||||
'new_project': 'New Project',
|
||||
'save': 'Save',
|
||||
'cancel': 'Cancel',
|
||||
'confirm': 'Confirm',
|
||||
'items': 'items',
|
||||
'add_member': 'Add Member',
|
||||
'operation': 'Operation',
|
||||
@@ -153,7 +154,9 @@ var locale_messages = {
|
||||
'status': 'Status',
|
||||
'logs' : 'Logs',
|
||||
'enabled': 'Enabled',
|
||||
'enable': 'Enable',
|
||||
'disabled': 'Disabled',
|
||||
'disable': 'Disable',
|
||||
'no_replication_policies_add_new': 'No replication policies, add new replication policy.',
|
||||
'no_replication_policies': 'No replication policies.',
|
||||
'no_replication_jobs': 'No replication jobs.',
|
||||
@@ -186,9 +189,9 @@ var locale_messages = {
|
||||
'successful_added': 'Added new user successfully.',
|
||||
'copyright': 'Copyright',
|
||||
'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.',
|
||||
'failed_to_ping_target': 'Faild to connect target.',
|
||||
'failed_to_ping_target': 'Cannot connect to the target.',
|
||||
'policy_already_exists': 'Policy alreay exists.',
|
||||
'destination_already_exists': 'Destination already exists.',
|
||||
'refresh': 'Refresh',
|
||||
@@ -205,6 +208,7 @@ var locale_messages = {
|
||||
'finished': 'Finished',
|
||||
'canceled': 'Canceled',
|
||||
'stopped': 'Stopped',
|
||||
'retrying': 'Retrying',
|
||||
'error': 'Error',
|
||||
'failed_to_get_project_member': 'Failed to get current project member.',
|
||||
'failed_to_delete_repo': 'Failed to delete repository. ',
|
||||
@@ -235,6 +239,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 project publicity, insuffient permissions.',
|
||||
'failed_to_toggle_publicity': 'Failed to toggle project publicity.',
|
||||
'project_admin': 'Project Admin',
|
||||
'developer': 'Developer',
|
||||
'guest': 'Guest',
|
||||
@@ -243,6 +249,7 @@ var locale_messages = {
|
||||
'<strong>Developer</strong>: Developer has read and write privileges for a project.<br/>' +
|
||||
'<strong>Guest</strong>: Guest has read-only privilege for a specified project.',
|
||||
'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': 'Found errors in the current replication jobs, please look into it.',
|
||||
'caution': 'Caution'
|
||||
};
|
||||
@@ -79,6 +79,7 @@ var locale_messages = {
|
||||
'new_project': '新增项目',
|
||||
'save': '保存',
|
||||
'cancel': '取消',
|
||||
'confirm': '确认',
|
||||
'items': '条记录',
|
||||
'add_member': '新增成员',
|
||||
'operation': '操作',
|
||||
@@ -150,8 +151,10 @@ var locale_messages = {
|
||||
'actions': '操作',
|
||||
'status': '状态',
|
||||
'logs': '日志',
|
||||
'enabled': '启用',
|
||||
'disabled': '停用',
|
||||
'enabled': '已启用',
|
||||
'enable': '启用',
|
||||
'disabled': '已停用',
|
||||
'disable': '停用',
|
||||
'no_replication_policies_add_new': '没有复制策略,请新增复制策略。',
|
||||
'no_replication_policies': '没有复制策略。',
|
||||
'no_replications': '没有复制策略。',
|
||||
@@ -160,7 +163,6 @@ var locale_messages = {
|
||||
'name_is_required': '名称为必填项',
|
||||
'name_is_too_long': '名称长度超出限制。(最长为20个字符)',
|
||||
'description_is_too_long': '描述内容长度超出限制。(最长为20个字符)',
|
||||
'enable': '启用',
|
||||
'general_setting': '一般设置',
|
||||
'destination_setting': '目标设置',
|
||||
'endpoint': '终端URL',
|
||||
@@ -199,12 +201,13 @@ var locale_messages = {
|
||||
'edit': '修改',
|
||||
'delete': '删除',
|
||||
'all': '全部',
|
||||
'transfer': '传输',
|
||||
'pending': '等待',
|
||||
'transfer': '复制',
|
||||
'pending': '等待中',
|
||||
'running': '进行中',
|
||||
'finished': '已完成',
|
||||
'canceled': '取消',
|
||||
'stopped': '停止',
|
||||
'canceled': '已取消',
|
||||
'stopped': '已终止',
|
||||
'retrying': '重试中',
|
||||
'error': '错误',
|
||||
'failed_to_get_project_member': '无法获取当前项目成员。',
|
||||
'failed_to_delete_repo': '无法删除镜像仓库。',
|
||||
@@ -235,6 +238,8 @@ var locale_messages = {
|
||||
'failed_to_delete_destination': '删除目标失败。',
|
||||
'failed_to_create_destination': '创建目标失败。',
|
||||
'failed_to_update_destination': '修改目标失败。',
|
||||
'failed_to_toggle_publicity_insuffient_permissions': '切换项目公开失败,权限不足。',
|
||||
'failed_to_toggle_publicity': '切换项目公开失败。',
|
||||
'project_admin': '项目管理员',
|
||||
'developer': '开发人员',
|
||||
'guest': '来宾用户',
|
||||
@@ -243,5 +248,7 @@ var locale_messages = {
|
||||
'<strong>开发人员</strong>: “开发人员” 拥有一个项目的读/写权限。<br/>' +
|
||||
'<strong>来宾用户</strong>: “来宾用户”拥有特定项目的只读权限。',
|
||||
'inline_help_publicity_title': '<strong>公开项目</strong>',
|
||||
'inline_help_publicity': '设置该项目为公开。'
|
||||
'inline_help_publicity': '设置该项目为公开。',
|
||||
'alert_job_contains_error': '当前复制任务中包含错误,请检查。',
|
||||
'caution': '注意'
|
||||
};
|
||||
@@ -2,7 +2,7 @@
|
||||
<modal-dialog action="vm.action()" content-type="//vm.contentType//" modal-title="//vm.modalTitle//" modal-message="//vm.modalMessage//" confirm-only="vm.confirmOnly"></modal-dialog>
|
||||
<div class="container container-custom">
|
||||
<div class="row extend-height">
|
||||
<div class="col-xs-12 col-md-12 extend-height">
|
||||
<div class="col-xs-12 col-md-12 extend-height">
|
||||
<div class="section" ng-style="vm.sectionHeight">
|
||||
<h4 class="page-header">
|
||||
<span ng-show="!vm.publicity">// 'my_projects' | tr //</span>
|
||||
@@ -22,10 +22,11 @@
|
||||
<input type="hidden" id="HarborRegUrl" value="{{.HarborRegUrl}}">
|
||||
<list-repository ng-if="vm.target === 'repositories'" section-height="vm.sectionHeight"></list-repository>
|
||||
<list-replication ng-if="vm.target === 'replication'" section-height="vm.sectionHeight"></list-replication>
|
||||
<list-project-member ng-if="vm.target === 'users'" section-height="vm.sectionHeight"></list-project-member>
|
||||
<list-log ng-if="vm.target === 'logs'" section-height="vm.sectionHeight"></list-log>
|
||||
<list-project-member ng-if="vm.target === 'users'" section-height="vm.sectionHeight" target="vm.target"></list-project-member>
|
||||
<list-log ng-if="vm.target === 'logs'" section-height="vm.sectionHeight" target="vm.target" publicity="vm.publicity"></list-log>
|
||||
</div>
|
||||
</div>
|
||||
<dismissable-alerts></dismissable-alerts>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -240,4 +240,7 @@
|
||||
<script src="/static/resources/js/components/loading-progress/loading-progress.directive.js"></script>
|
||||
|
||||
<script src="/static/resources/js/components/inline-help/inline-help.module.js"></script>
|
||||
<script src="/static/resources/js/components/inline-help/inline-help.directive.js"></script>
|
||||
<script src="/static/resources/js/components/inline-help/inline-help.directive.js"></script>
|
||||
|
||||
<script src="/static/resources/js/components/dismissable-alerts/dismissable-alerts.module.js"></script>
|
||||
<script src="/static/resources/js/components/dismissable-alerts/dismissable-alerts.directive.js"></script>
|
||||
Reference in New Issue
Block a user