Merge remote-tracking branch 'upstream/api-attribute-rename' into api-attributes

This commit is contained in:
Tan Jiang 2016-06-03 18:51:26 +08:00
commit 884f496854
28 changed files with 1175 additions and 1180 deletions

View File

@ -48,7 +48,7 @@ func hasProjectAdminRole(userID int, projectID int64) bool {
//sysadmin has all privileges to all projects //sysadmin has all privileges to all projects
func listRoles(userID int, projectID int64) ([]models.Role, error) { func listRoles(userID int, projectID int64) ([]models.Role, error) {
roles := make([]models.Role, 1) roles := make([]models.Role, 0, 1)
isSysAdmin, err := dao.IsAdminRole(userID) isSysAdmin, err := dao.IsAdminRole(userID)
if err != nil { if err != nil {
return roles, err return roles, err

View File

@ -13,7 +13,6 @@
limitations under the License. limitations under the License.
*/ */
.footer { .footer {
margin-top: 60px;
width: 100%; width: 100%;
/* Set the fixed height of the footer here */ /* Set the fixed height of the footer here */
height: 60px; height: 60px;

View File

@ -24,7 +24,7 @@ jQuery(function(){
error: function(jqXhr){ error: function(jqXhr){
if(jqXhr && jqXhr.status == 401){ if(jqXhr && jqXhr.status == 401){
document.location = "/signIn"; document.location = "/signIn";
} }
} }
}).exec(); }).exec();
@ -36,12 +36,12 @@ jQuery(function(){
function bindEnterKey(){ function bindEnterKey(){
$(document).on("keydown", function(e){ $(document).on("keydown", function(e){
if(e.keyCode == 13){ if(e.keyCode == 13){
e.preventDefault(); e.preventDefault();
if($("#txtCommonSearch").is(":focus")){ if($("#txtCommonSearch").is(":focus")){
document.location = "/search?q=" + $("#txtCommonSearch").val(); document.location = "/search?q=" + $("#txtCommonSearch").val();
}else{ }else{
$("#btnSubmit").trigger("click"); $("#btnSubmit").trigger("click");
} }
} }
}); });
} }
@ -61,35 +61,35 @@ jQuery(function(){
type: "put", type: "put",
data: {"old_password": oldPassword, "new_password" : password}, data: {"old_password": oldPassword, "new_password" : password},
beforeSend: function(e){ beforeSend: function(e){
unbindEnterKey(); unbindEnterKey();
$("h1").append(spinner.el); $("h1").append(spinner.el);
$("#btnSubmit").prop("disabled", true); $("#btnSubmit").prop("disabled", true);
}, },
complete: function(xhr, status){ complete: function(xhr, status){
spinner.stop(); spinner.stop();
$("#btnSubmit").prop("disabled", false); $("#btnSubmit").prop("disabled", false);
if(xhr && xhr.status == 200){ if(xhr && xhr.status == 200){
$("#dlgModal") $("#dlgModal")
.dialogModal({ .dialogModal({
"title": i18n.getMessage("title_change_password"), "title": i18n.getMessage("title_change_password"),
"content": i18n.getMessage("change_password_successfully"), "content": i18n.getMessage("change_password_successfully"),
"callback": function(){ "callback": function(){
window.close(); window.close();
} }
}); });
} }
}, },
error: function(jqXhr, status, error){ error: function(jqXhr, status, error){
if(jqXhr && jqXhr.responseText.length){ if(jqXhr && jqXhr.responseText.length){
$("#dlgModal") $("#dlgModal")
.dialogModal({ .dialogModal({
"title": i18n.getMessage("title_change_password"), "title": i18n.getMessage("title_change_password"),
"content": i18n.getMessage(jqXhr.responseText), "content": i18n.getMessage(jqXhr.responseText),
"callback": function(){ "callback": function(){
bindEnterKey(); bindEnterKey();
return; return;
} }
}); });
} }
} }
}).exec(); }).exec();

View File

@ -12,8 +12,9 @@
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
var AjaxUtil = function(params){ var AjaxUtil = function(params){
this.url = params.url; this.url = params.url;
this.data = params.data; this.data = params.data;
this.dataRaw = params.dataRaw; this.dataRaw = params.dataRaw;
@ -31,39 +32,39 @@ AjaxUtil.prototype.exec = function(){
var self = this; var self = this;
return $.ajax({ return $.ajax({
url: self.url, url: self.url,
contentType: (self.dataRaw ? "application/x-www-form-urlencoded; charset=UTF-8" : "application/json; charset=utf-8"), contentType: (self.dataRaw ? "application/x-www-form-urlencoded; charset=UTF-8" : "application/json; charset=utf-8"),
data: JSON.stringify(self.data) || self.dataRaw, data: JSON.stringify(self.data) || self.dataRaw,
type: self.type, type: self.type,
dataType: "json", dataType: "json",
success: function(data, status, xhr){ success: function(data, status, xhr){
if(self.success != null){ if(self.success != null){
self.success(data, status, xhr); self.success(data, status, xhr);
} }
}, },
complete: function(jqXhr, status) { complete: function(jqXhr, status) {
if(self.complete != null){ if(self.complete != null){
self.complete(jqXhr, status); self.complete(jqXhr, status);
} }
}, },
error: function(jqXhr){ error: function(jqXhr){
if(self.error != null){ if(self.error != null){
self.error(jqXhr); self.error(jqXhr);
}else{ }else{
var errorMessage = self.errors[jqXhr.status] || jqXhr.responseText; var errorMessage = self.errors[jqXhr.status] || jqXhr.responseText;
if(jqXhr.status == 401){ if(jqXhr.status == 401){
var lastUri = location.pathname + location.search; var lastUri = location.pathname + location.search;
if(lastUri != ""){ if(lastUri != ""){
document.location = "/signIn?uri=" + encodeURIComponent(lastUri); document.location = "/signIn?uri=" + encodeURIComponent(lastUri);
}else{ }else{
document.location = "/signIn"; document.location = "/signIn";
}
}else if($.trim(errorMessage).length > 0){
$("#dlgModal").dialogModal({"title": i18n.getMessage("operation_failed"), "content": errorMessage});
} }
}else if($.trim(errorMessage).length > 0){
$("#dlgModal").dialogModal({"title": i18n.getMessage("operation_failed"), "content": errorMessage});
} }
} }
} });
});
}; };
var SUPPORT_LANGUAGES = { var SUPPORT_LANGUAGES = {
@ -133,7 +134,7 @@ jQuery(function(){
var self = this; var self = this;
$("#dlgLabel", self).text(settings.title); $("#dlgLabel", self).text(settings.title);
if(options.text){ if(options.text){
$("#dlgBody", self).html(settings.content); $("#dlgBody", self).html(settings.content);
}else if(typeof settings.content == "object"){ }else if(typeof settings.content == "object"){
@ -141,9 +142,9 @@ jQuery(function(){
var lines = ['<form class="form-horizontal">']; var lines = ['<form class="form-horizontal">'];
for(var item in settings.content){ for(var item in settings.content){
lines.push('<div class="form-group">'+ lines.push('<div class="form-group">'+
'<label class="col-sm-2 control-label">'+ item +'</label>' + '<label class="col-sm-2 control-label">'+ item +'</label>' +
'<div class="col-sm-10"><p class="form-control-static">' + settings.content[item] + '</p></div>' + '<div class="col-sm-10"><p class="form-control-static">' + settings.content[item] + '</p></div>' +
'</div>'); '</div>');
} }
lines.push('</form>'); lines.push('</form>');
$("#dlgBody", self).html(lines.join("")); $("#dlgBody", self).html(lines.join(""));
@ -153,10 +154,15 @@ jQuery(function(){
} }
if(settings.callback != null){ if(settings.callback != null){
$("#dlgConfirm").on("click", function(){ var hasEntered = false;
settings.callback(); $("#dlgConfirm").on("click", function(e){
if(!hasEntered) {
hasEntered = true;
settings.callback();
}
}); });
} }
$(self).modal('show'); $(self).modal('show');
} }
}); });

View File

@ -13,26 +13,26 @@
limitations under the License. limitations under the License.
*/ */
jQuery(function(){ jQuery(function(){
$("#divErrMsg").css({"display": "none"}); $("#divErrMsg").css({"display": "none"});
validateOptions.Items = ["#EmailF"]; validateOptions.Items = ["#EmailF"];
function bindEnterKey(){ function bindEnterKey(){
$(document).on("keydown", function(e){ $(document).on("keydown", function(e){
if(e.keyCode == 13){ if(e.keyCode == 13){
e.preventDefault(); e.preventDefault();
if($("#txtCommonSearch").is(":focus")){ if($("#txtCommonSearch").is(":focus")){
document.location = "/search?q=" + $("#txtCommonSearch").val(); document.location = "/search?q=" + $("#txtCommonSearch").val();
}else{ }else{
$("#btnSubmit").trigger("click"); $("#btnSubmit").trigger("click");
} }
} }
}); });
} }
function unbindEnterKey(){ function unbindEnterKey(){
$(document).off("keydown"); $(document).off("keydown");
} }
bindEnterKey(); bindEnterKey();
var spinner = new Spinner({scale:1}).spin(); var spinner = new Spinner({scale:1}).spin();
$("#btnSubmit").on("click", function(){ $("#btnSubmit").on("click", function(){
@ -44,20 +44,20 @@ jQuery(function(){
"type": "get", "type": "get",
"data": {"username": username, "email": email}, "data": {"username": username, "email": email},
"beforeSend": function(e){ "beforeSend": function(e){
unbindEnterKey(); unbindEnterKey();
$("h1").append(spinner.el); $("h1").append(spinner.el);
$("#btnSubmit").prop("disabled", true); $("#btnSubmit").prop("disabled", true);
}, },
"success": function(data, status, xhr){ "success": function(data, status, xhr){
if(xhr && xhr.status == 200){ if(xhr && xhr.status == 200){
$("#dlgModal") $("#dlgModal")
.dialogModal({ .dialogModal({
"title": i18n.getMessage("title_forgot_password"), "title": i18n.getMessage("title_forgot_password"),
"content": i18n.getMessage("email_has_been_sent"), "content": i18n.getMessage("email_has_been_sent"),
"callback": function(){ "callback": function(){
document.location="/"; document.location="/";
} }
}); });
} }
}, },
@ -68,14 +68,14 @@ jQuery(function(){
"error": function(jqXhr, status, error){ "error": function(jqXhr, status, error){
if(jqXhr){ if(jqXhr){
$("#dlgModal") $("#dlgModal")
.dialogModal({ .dialogModal({
"title": i18n.getMessage("title_forgot_password"), "title": i18n.getMessage("title_forgot_password"),
"content": i18n.getMessage(jqXhr.responseText), "content": i18n.getMessage(jqXhr.responseText),
"callback": function(){ "callback": function(){
bindEnterKey(); bindEnterKey();
return; return;
} }
}); });
} }
} }
}); });

View File

@ -13,20 +13,20 @@
limitations under the License. limitations under the License.
*/ */
jQuery(function(){ jQuery(function(){
$("#btnSignUp").css({"visibility": "visible"}); $("#btnSignUp").css({"visibility": "visible"});
$(document).on("keydown", function(e){ $(document).on("keydown", function(e){
if(e.keyCode == 13){ if(e.keyCode == 13){
e.preventDefault(); e.preventDefault();
if($("#txtCommonSearch").is(":focus")){ if($("#txtCommonSearch").is(":focus")){
document.location = "/search?q=" + $("#txtCommonSearch").val(); document.location = "/search?q=" + $("#txtCommonSearch").val();
} }
} }
}); });
$("#btnSignIn").on("click", function(){ $("#btnSignIn").on("click", function(){
document.location = "/signIn"; document.location = "/signIn";
}); });
$("#btnSignUp").on("click", function(){ $("#btnSignUp").on("click", function(){
document.location = "/register"; document.location = "/register";
}); });
}); });

View File

@ -23,461 +23,451 @@ jQuery(function(){
if(jqXhr.status == 403){ if(jqXhr.status == 403){
return false; return false;
} }
} }
} }
}).exec() }).exec()
).then(function(){ ).then(function(){
noNeedToLoginCallback(); noNeedToLoginCallback();
needToLoginCallback(); needToLoginCallback();
}).fail(function(){ }).fail(function(){
noNeedToLoginCallback(); noNeedToLoginCallback();
}); });
function noNeedToLoginCallback(){
$("#tabItemDetail a:first").tab("show");
$("#btnFilterOption button:first").addClass("active");
$("#divErrMsg").hide();
if($("#public").val() == 1){
$("#tabItemDetail li:eq(1)").hide();
$("#tabItemDetail li:eq(2)").hide();
}
listRepo($("#repoName").val());
function listRepo(repoName){
function noNeedToLoginCallback(){
$("#tabItemDetail a:first").tab("show");
$("#btnFilterOption button:first").addClass("active");
$("#divErrMsg").hide(); $("#divErrMsg").hide();
if($("#public").val() == 1){
$("#tabItemDetail li:eq(1)").hide();
$("#tabItemDetail li:eq(2)").hide();
}
listRepo($("#repoName").val());
function listRepo(repoName){
$("#divErrMsg").hide();
new AjaxUtil({ new AjaxUtil({
url: "/api/repositories?project_id=" + $("#projectId").val() + "&q=" + repoName, url: "/api/repositories?project_id=" + $("#projectId").val() + "&q=" + repoName,
type: "get", type: "get",
success: function(data, status, xhr){ success: function(data, status, xhr){
if(xhr && xhr.status == 200){ if(xhr && xhr.status == 200){
$("#accordionRepo").children().remove(); $("#accordionRepo").children().remove();
if(data == null){ if(data == null){
$("#divErrMsg").show(); $("#divErrMsg").show();
$("#divErrMsg center").html(i18n.getMessage("no_repo_exists")); $("#divErrMsg center").html(i18n.getMessage("no_repo_exists"));
return; return;
} }
$.each(data, function(i, e){ $.each(data, function(i, e){
var targetId = e.replace(/\//g, "------"); var targetId = e.replace(/\//g, "------");
var row = '<div class="panel panel-default" targetId="' + targetId + '">' + var row = '<div class="panel panel-default" targetId="' + targetId + '">' +
'<div class="panel-heading" role="tab" id="heading' + i + '"+ >' + '<div class="panel-heading" role="tab" id="heading' + i + '"+ >' +
'<h4 class="panel-title">' + '<h4 class="panel-title">' +
'<a data-toggle="collapse" data-parent="#accordion" href="#collapse'+ i + '" aria-expanded="true" aria-controls="collapse' + i + '">' + '<a data-toggle="collapse" data-parent="#accordion" href="#collapse'+ i + '" aria-expanded="true" aria-controls="collapse' + i + '">' +
'<span class="list-group-item-heading"> <span class="glyphicon glyphicon-book blue"></span> ' + e + ' </span>' + '<span class="list-group-item-heading"> <span class="glyphicon glyphicon-book blue"></span> ' + e + ' </span>' +
'</a>' + '</a>' +
'</h4>' + '</h4>' +
'</div>' + '</div>' +
'<div id="collapse' + i + '" targetId="' + targetId + '" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading' + i + '">' + '<div id="collapse' + i + '" targetId="' + targetId + '" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading' + i + '">' +
'<div class="panel-body" id="' + targetId + '">' + '<div class="panel-body" id="' + targetId + '">' +
'<div class="table-responsive" style="height: auto;">' + '<div class="table-responsive" style="height: auto;">' +
'<table class="table table-striped table-bordered table-condensed">' + '<table class="table table-striped table-bordered table-condensed">' +
'<thead>' + '<thead>' +
'<tr>' + '<tr>' +
'<th class="st-sort-ascent" st-sort="name" st-sort-default=""><span class="glyphicon glyphicon-tag blue"></span> ' + i18n.getMessage("tag")+ ' </th>' + '<th class="st-sort-ascent" st-sort="name" st-sort-default=""><span class="glyphicon glyphicon-tag blue"></span> ' + i18n.getMessage("tag")+ ' </th>' +
'<th class="st-sort-ascent" st-sort="name" st-sort-default=""><span class="glyphicon glyphicon-tag blue"></span> ' + i18n.getMessage("pull_command") + ' </th>' + '<th class="st-sort-ascent" st-sort="name" st-sort-default=""><span class="glyphicon glyphicon-tag blue"></span> ' + i18n.getMessage("pull_command") + ' </th>' +
'</tr>' + '</tr>' +
'</thead>' + '</thead>' +
'<tbody>' + '<tbody>' +
'</tbody>' + '</tbody>' +
'</table>' '</table>'
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>' + '</div>' +
'</div>'; '</div>';
$("#accordionRepo").append(row); $("#accordionRepo").append(row);
}); });
if(repoName != ""){ if(repoName != ""){
$("#txtRepoName").val(repoName); $("#txtRepoName").val(repoName);
$("#accordionRepo #heading0 a").trigger("click"); $("#accordionRepo #heading0 a").trigger("click");
}
} }
} }
}
}).exec();
}
$("#btnSearchRepo").on("click", function(){
listRepo($.trim($("#txtRepoName").val()));
});
$('#accordionRepo').on('show.bs.collapse', function (e) {
$('#accordionRepo .in').collapse('hide');
var targetId = $(e.target).attr("targetId");
var repoName = targetId.replace(/------/g, "/");
new AjaxUtil({
url: "/api/repositories/tags?repo_name=" + repoName,
type: "get",
success: function(data, status, xhr){
$('#' + targetId +' table tbody tr').remove();
var row = [];
for(var i in data){
var tagName = data[i]
row.push('<tr><td><a href="#" imageId="' + tagName + '" repoName="' + repoName + '">' + tagName + '</a></td><td><input type="text" style="width:100%" readonly value=" docker pull '+ $("#harborRegUrl").val() +'/'+ repoName + ':' + tagName +'"></td></tr>');
}
$('#' + targetId +' table tbody').append(row.join(""));
$('#' + targetId +' table tbody tr a').on("click", function(e){
var imageId = $(this).attr("imageId");
var repoName = $(this).attr("repoName");
new AjaxUtil({
url: "/api/repositories/manifests?repo_name=" + repoName + "&tag=" + imageId,
type: "get",
success: function(data, status, xhr){
if(data){
for(var i in data){
if(data[i] == ""){
data[i] = "N/A";
}
}
data.Created = moment(new Date(data.Created)).format("YYYY-MM-DD HH:mm:ss");
$("#dlgModal").dialogModal({"title": i18n.getMessage("image_details"), "content": data});
}
}
}).exec();
});
}
}).exec();
});
}
function needToLoginCallback(){
var hasAuthorization = false;
$.when(
new AjaxUtil({
url: "/api/projects/" + $("#projectId").val() + "/members/current",
type: "get",
success: function(data, status, xhr){
if(xhr && xhr.status == 200 && data.roles != null && data.roles.length > 0){
hasAuthorization = true;
}
}
}).exec())
.done(function(){
if(!hasAuthorization) return false;
$("#tabItemDetail a:eq(1)").css({"visibility": "visible"});
$("#tabItemDetail a:eq(2)").css({"visibility": "visible"});
$(".glyphicon .glyphicon-pencil", "#tblUser").on("click", function(e){
$("#txtUserName").hide();
$("#lblUserName").show();
$("#dlgUserTitle").text(i18n.getMessage("edit_members"));
});
$("#btnAddUser").on("click", function(){
$("#operationType").val("add");
$("#spnSearch").show();
$("#txtUserName").prop("disabled", false)
$("#txtUserName").val("");
$("#lstRole input[name=chooseRole]:radio").prop("checked", false);
$("#dlgUserTitle").text(i18n.getMessage("add_members"));
});
$("#btnSave").on("click", function(){
var username = $("#txtUserName").val();
if($.trim(username).length == 0){
$("#dlgModal").dialogModal({"title": i18n.getMessage("add_member_failed"), "content": i18n.getMessage("please_input_username")});
return;
}
var projectId = $("#projectId").val();
var operationType = $("#operationType").val();
var userId = $("#editUserId").val();
var checkedRole = $("#lstRole input[name='chooseRole']:checked")
if(checkedRole.length == 0){
$("#dlgModal").dialogModal({"title": i18n.getMessage("add_member_failed"), "content": i18n.getMessage("please_assign_a_role_to_user")});
return;
}
var checkedRoleItemList = [];
$.each(checkedRole, function(i, e){
checkedRoleItemList.push(new Number($(this).val()));
});
var ajaxOpts = {};
if(operationType == "add"){
ajaxOpts.url = "/api/projects/" + projectId + "/members/";
ajaxOpts.type = "post";
ajaxOpts.data = {"roles" : checkedRoleItemList, "user_name": username};
}else if(operationType == "edit"){
ajaxOpts.url = "/api/projects/" + projectId + "/members/" + userId;
ajaxOpts.type = "put";
ajaxOpts.data = {"roles" : checkedRoleItemList};
}
new AjaxUtil({
url: ajaxOpts.url,
data: ajaxOpts.data,
type: ajaxOpts.type,
complete: function(jqXhr, status){
if(jqXhr && jqXhr.status == 200){
$("#btnCancel").trigger("click");
listUser(null);
}
},
errors: {
404: i18n.getMessage("user_id_does_not_exist"),
409: i18n.getMessage("user_id_exists"),
403: i18n.getMessage("insufficient_privileges")
}
}).exec();
});
var name_mapping = {
"projectAdmin": "Project Admin",
"developer": "Developer",
"guest": "Guest"
}
function listUserByProjectCallback(userList){
var loginedUserId = $("#userId").val();
var loginedUserRoleId = $("#roleId").val();
var ownerId = $("#ownerId").val();
$("#tblUser tbody tr").remove();
for(var i = 0; i < userList.length; ){
var userId = userList[i].UserId;
var roleId = userList[i].RoleId;
var username = userList[i].username;
var roleNameList = [];
for(var j = i; j < userList.length; i++, j++){
if(userList[j].UserId == userId){
roleNameList.push(name_mapping[userList[j].Rolename]);
}else{
break;
}
}
var row = '<tr>' +
'<td>' + username + '</td>' +
'<td>' + roleNameList.join(",") + '</td>' +
'<td>';
var isShowOperations = true;
if(loginedUserRoleId >= 3 /*role: developer guest*/){
isShowOperations = false;
}else if(ownerId == userId){
isShowOperations = false;
}else if (loginedUserId == userId){
isShowOperations = false;
}
if(isShowOperations){
row += '<a href="#" userid="' + userId + '" class="glyphicon glyphicon-pencil" data-toggle="modal" data-target="#dlgUser"></a>&nbsp;' +
'<a href="#" userid="' + userId + '" roleid="' + roleId + '" class="glyphicon glyphicon-trash"></a>';
}
row += '</td></tr>';
$("#tblUser tbody").append(row);
}
}
function searchAccessLogCallback(LogList){
$("#tabOperationLog tbody tr").remove();
$.each(LogList || [], function(i, e){
$("#tabOperationLog tbody").append(
'<tr>' +
'<td>' + e.Username + '</td>' +
'<td>' + e.RepoName + '</td>' +
'<td>' + e.RepoTag + '</td>' +
'<td>' + e.Operation + '</td>' +
'<td>' + moment(new Date(e.OpTime)).format("YYYY-MM-DD HH:mm:ss") + '</td>' +
'</tr>');
});
}
function getUserRoleCallback(userId){
new AjaxUtil({
url: "/api/projects/" + $("#projectId").val() + "/members/" + userId,
type: "get",
success: function(data, status, xhr){
var user = data;
$("#operationType").val("edit");
$("#editUserId").val(user.user_id);
$("#spnSearch").hide();
$("#txtUserName").val(user.user_name);
$("#txtUserName").prop("disabled", true);
$("#btnSave").removeClass("disabled");
$("#dlgUserTitle").text(i18n.getMessage("edit_members"));
$("#lstRole input[name=chooseRole]:radio").not('[value=' + user.role_id + ']').prop("checked", false)
$.each(user.roles, function(i, e){
$("#lstRole input[name=chooseRole]:radio").filter('[value=' + e.role_id + ']').prop("checked", "checked");
});
}
}).exec(); }).exec();
} }
function listUser(username){ $("#btnSearchRepo").on("click", function(){
$.when( listRepo($.trim($("#txtRepoName").val()));
new AjaxUtil({
url: "/api/projects/" + $("#projectId").val() + "/members?username=" + (username == null ? "" : username),
type: "get",
errors: {
403: ""
},
success: function(data, status, xhr){
return data || [];
}
}).exec()
).done(function(userList){
listUserByProjectCallback(userList || []);
$("#tblUser .glyphicon-pencil").on("click", function(e){
var userId = $(this).attr("userid")
getUserRoleCallback(userId);
});
$("#tblUser .glyphicon-trash").on("click", function(){
var userId = $(this).attr("userid");
new AjaxUtil({
url: "/api/projects/" + $("#projectId").val() + "/members/" + userId,
type: "delete",
complete: function(jqXhr, status){
if(jqXhr && jqXhr.status == 200){
listUser(null);
}
}
}).exec();
});
});
}
listUser(null);
listOperationLogs();
function listOperationLogs(){
var projectId = $("#projectId").val();
$.when(
new AjaxUtil({
url : "/api/projects/" + projectId + "/logs/filter",
data: {},
type: "post",
success: function(data){
return data || [];
}
}).exec()
).done(function(operationLogs){
searchAccessLogCallback(operationLogs);
});
}
$("#btnSearchUser").on("click", function(){
var username = $("#txtSearchUser").val();
if($.trim(username).length == 0){
username = null;
}
listUser(username);
}); });
function toUTCSeconds(date, hour, min, sec) { $('#accordionRepo').on('show.bs.collapse', function (e) {
var t = new Date(date); $('#accordionRepo .in').collapse('hide');
t.setHours(hour); var targetId = $(e.target).attr("targetId");
t.setMinutes(min); var repoName = targetId.replace(/------/g, "/");
t.setSeconds(sec); new AjaxUtil({
var utcTime = new Date(t.getUTCFullYear(), url: "/api/repositories/tags?repo_name=" + repoName,
type: "get",
success: function(data, status, xhr){
$('#' + targetId +' table tbody tr').remove();
var row = [];
for(var i in data){
var tagName = data[i]
row.push('<tr><td><a href="#" imageId="' + tagName + '" repoName="' + repoName + '">' + tagName + '</a></td><td><input type="text" style="width:100%" readonly value=" docker pull '+ $("#harborRegUrl").val() +'/'+ repoName + ':' + tagName +'"></td></tr>');
}
$('#' + targetId +' table tbody').append(row.join(""));
$('#' + targetId +' table tbody tr a').on("click", function(e){
var imageId = $(this).attr("imageId");
var repoName = $(this).attr("repoName");
new AjaxUtil({
url: "/api/repositories/manifests?repo_name=" + repoName + "&tag=" + imageId,
type: "get",
success: function(data, status, xhr){
if(data){
for(var i in data){
if(data[i] == ""){
data[i] = "N/A";
}
}
data.Created = moment(new Date(data.Created)).format("YYYY-MM-DD HH:mm:ss");
$("#dlgModal").dialogModal({"title": i18n.getMessage("image_details"), "content": data});
}
}
}).exec();
});
}
}).exec();
});
}
function needToLoginCallback(){
var hasAuthorization = false;
$.when(
new AjaxUtil({
url: "/api/projects/" + $("#projectId").val() + "/members/current",
type: "get",
success: function(data, status, xhr){
if(xhr && xhr.status == 200 && data.roles != null && data.roles.length > 0){
hasAuthorization = true;
}
}
}).exec())
.done(function(){
if(!hasAuthorization) return false;
$("#tabItemDetail a:eq(1)").css({"visibility": "visible"});
$("#tabItemDetail a:eq(2)").css({"visibility": "visible"});
$(".glyphicon .glyphicon-pencil", "#tblUser").on("click", function(e){
$("#txtUserName").hide();
$("#lblUserName").show();
$("#dlgUserTitle").text(i18n.getMessage("edit_members"));
});
$("#btnAddUser").on("click", function(){
$("#operationType").val("add");
$("#spnSearch").show();
$("#txtUserName").prop("disabled", false)
$("#txtUserName").val("");
$("#lstRole input[name=chooseRole]:radio").prop("checked", false);
$("#dlgUserTitle").text(i18n.getMessage("add_members"));
});
$("#btnSave").on("click", function(){
var username = $("#txtUserName").val();
if($.trim(username).length == 0){
$("#dlgModal").dialogModal({"title": i18n.getMessage("add_member_failed"), "content": i18n.getMessage("please_input_username")});
return;
}
var projectId = $("#projectId").val();
var operationType = $("#operationType").val();
var userId = $("#editUserId").val();
var checkedRole = $("#lstRole input[name='chooseRole']:checked")
if(checkedRole.length == 0){
$("#dlgModal").dialogModal({"title": i18n.getMessage("add_member_failed"), "content": i18n.getMessage("please_assign_a_role_to_user")});
return;
}
var checkedRoleItemList = [];
$.each(checkedRole, function(i, e){
checkedRoleItemList.push(new Number($(this).val()));
});
var ajaxOpts = {};
if(operationType == "add"){
ajaxOpts.url = "/api/projects/" + projectId + "/members/";
ajaxOpts.type = "post";
ajaxOpts.data = {"roles" : checkedRoleItemList, "username": username};
}else if(operationType == "edit"){
ajaxOpts.url = "/api/projects/" + projectId + "/members/" + userId;
ajaxOpts.type = "put";
ajaxOpts.data = {"roles" : checkedRoleItemList};
}
new AjaxUtil({
url: ajaxOpts.url,
data: ajaxOpts.data,
type: ajaxOpts.type,
complete: function(jqXhr, status){
if(jqXhr && jqXhr.status == 200){
$("#btnCancel").trigger("click");
listUser(null);
}
},
errors: {
404: i18n.getMessage("user_id_does_not_exist"),
409: i18n.getMessage("user_id_exists"),
403: i18n.getMessage("insufficient_privileges")
}
}).exec();
});
var name_mapping = {
"projectAdmin": "Project Admin",
"developer": "Developer",
"guest": "Guest"
}
function listUserByProjectCallback(userList){
var loginedUserId = $("#userId").val();
var loginedUserRoleId = $("#roleId").val();
var ownerId = $("#ownerId").val();
$("#tblUser tbody tr").remove();
for(var i = 0; i < userList.length; i++){
var userId = userList[i].user_id;
var roleId = userList[i].role_id;
var username = userList[i].username;
var row = '<tr>' +
'<td>' + username + '</td>' +
'<td>' + name_mapping[userList[i].role_name] + '</td>' +
'<td>';
var isShowOperations = true;
if(loginedUserRoleId >= 3 /*role: developer guest*/){
isShowOperations = false;
}else if(ownerId == userId){
isShowOperations = false;
}else if (loginedUserId == userId){
isShowOperations = false;
}
if(isShowOperations){
row += '<a href="#" userid="' + userId + '" class="glyphicon glyphicon-pencil" data-toggle="modal" data-target="#dlgUser"></a>&nbsp;' +
'<a href="#" userid="' + userId + '" roleid="' + roleId + '" class="glyphicon glyphicon-trash"></a>';
}
row += '</td></tr>';
$("#tblUser tbody").append(row);
}
}
function searchAccessLogCallback(LogList){
$("#tabOperationLog tbody tr").remove();
$.each(LogList || [], function(i, e){
$("#tabOperationLog tbody").append(
'<tr>' +
'<td>' + e.username + '</td>' +
'<td>' + e.repo_name + '</td>' +
'<td>' + e.repo_tag + '</td>' +
'<td>' + e.operation + '</td>' +
'<td>' + moment(new Date(e.op_time)).format("YYYY-MM-DD HH:mm:ss") + '</td>' +
'</tr>');
});
}
function getUserRoleCallback(userId){
new AjaxUtil({
url: "/api/projects/" + $("#projectId").val() + "/members/" + userId,
type: "get",
success: function(data, status, xhr){
var user = data;
$("#operationType").val("edit");
$("#editUserId").val(user.user_id);
$("#spnSearch").hide();
$("#txtUserName").val(user.username);
$("#txtUserName").prop("disabled", true);
$("#btnSave").removeClass("disabled");
$("#dlgUserTitle").text(i18n.getMessage("edit_members"));
$("#lstRole input[name=chooseRole]:radio").not('[value=' + user.role_id + ']').prop("checked", false)
$.each(user.roles, function(i, e){
$("#lstRole input[name=chooseRole]:radio").filter('[value=' + e.role_id + ']').prop("checked", "checked");
});
}
}).exec();
}
function listUser(username){
$.when(
new AjaxUtil({
url: "/api/projects/" + $("#projectId").val() + "/members?username=" + (username == null ? "" : username),
type: "get",
errors: {
403: ""
},
success: function(data, status, xhr){
return data || [];
}
}).exec()
).done(function(userList){
listUserByProjectCallback(userList || []);
$("#tblUser .glyphicon-pencil").on("click", function(e){
var userId = $(this).attr("userid")
getUserRoleCallback(userId);
});
$("#tblUser .glyphicon-trash").on("click", function(){
var userId = $(this).attr("userid");
new AjaxUtil({
url: "/api/projects/" + $("#projectId").val() + "/members/" + userId,
type: "delete",
complete: function(jqXhr, status){
if(jqXhr && jqXhr.status == 200){
listUser(null);
}
}
}).exec();
});
});
}
listUser(null);
listOperationLogs();
function listOperationLogs(){
var projectId = $("#projectId").val();
$.when(
new AjaxUtil({
url : "/api/projects/" + projectId + "/logs/filter",
data: {},
type: "post",
success: function(data){
return data || [];
}
}).exec()
).done(function(operationLogs){
searchAccessLogCallback(operationLogs);
});
}
$("#btnSearchUser").on("click", function(){
var username = $("#txtSearchUser").val();
if($.trim(username).length == 0){
username = null;
}
listUser(username);
});
function toUTCSeconds(date, hour, min, sec) {
var t = new Date(date);
t.setHours(hour);
t.setMinutes(min);
t.setSeconds(sec);
var utcTime = new Date(t.getUTCFullYear(),
t.getUTCMonth(), t.getUTCMonth(),
t.getUTCDate(), t.getUTCDate(),
t.getUTCHours(), t.getUTCHours(),
t.getUTCMinutes(), t.getUTCMinutes(),
t.getUTCSeconds()); t.getUTCSeconds());
return utcTime.getTime() / 1000; return utcTime.getTime() / 1000;
}
$("#btnFilterLog").on("click", function(){
var projectId = $("#projectId").val();
var username = $("#txtSearchUserName").val();
var beginTimestamp = 0;
var endTimestamp = 0;
if($("#begindatepicker").val() != ""){
beginTimestamp = toUTCSeconds($("#begindatepicker").val(), 0, 0, 0);
}
if($("#enddatepicker").val() != ""){
endTimestamp = toUTCSeconds($("#enddatepicker").val(), 23, 59, 59);
}
new AjaxUtil({
url: "/api/projects/" + projectId + "/logs/filter",
data:{"username":username, "project_id" : projectId, "keywords" : getKeyWords() , "beginTimestamp" : beginTimestamp, "endTimestamp" : endTimestamp},
type: "post",
success: function(data, status, xhr){
if(xhr && xhr.status == 200){
searchAccessLogCallback(data);
} }
}
}).exec(); $("#btnFilterLog").on("click", function(){
});
var projectId = $("#projectId").val();
$("#spnFilterOption input[name=chkAll]").on("click", function(){ var username = $("#txtSearchUserName").val();
$("#spnFilterOption input[name=chkOperation]").prop("checked", $(this).prop("checked"));
}); var beginTimestamp = 0;
var endTimestamp = 0;
$("#spnFilterOption input[name=chkOperation]").on("click", function(){
if(!$(this).prop("checked")){ if($("#begindatepicker").val() != ""){
$("#spnFilterOption input[name=chkAll]").prop("checked", false); beginTimestamp = toUTCSeconds($("#begindatepicker").val(), 0, 0, 0);
} }
if($("#enddatepicker").val() != ""){
var selectedAll = true; endTimestamp = toUTCSeconds($("#enddatepicker").val(), 23, 59, 59);
}
$("#spnFilterOption input[name=chkOperation]").each(function(i, e){
if(!$(e).prop("checked")){ new AjaxUtil({
selectedAll = false; url: "/api/projects/" + projectId + "/logs/filter",
} data:{"username":username, "project_id" : Number(projectId), "keywords" : getKeyWords() , "begin_timestamp" : beginTimestamp, "end_timestamp" : endTimestamp},
}); type: "post",
success: function(data, status, xhr){
if(selectedAll){ if(xhr && xhr.status == 200){
$("#spnFilterOption input[name=chkAll]").prop("checked", true); searchAccessLogCallback(data);
} }
}); }
}).exec();
function getKeyWords(){ });
var keywords = "";
var checkedItemList=$("#spnFilterOption input[name=chkOperation]:checked"); $("#spnFilterOption input[name=chkAll]").on("click", function(){
var keywords = []; $("#spnFilterOption input[name=chkOperation]").prop("checked", $(this).prop("checked"));
$.each(checkedItemList, function(i, e){ });
var itemValue = $(e).val();
if(itemValue == "others" && $.trim($("#txtOthers").val()).length > 0){ $("#spnFilterOption input[name=chkOperation]").on("click", function(){
keywords.push($("#txtOthers").val()); if(!$(this).prop("checked")){
}else{ $("#spnFilterOption input[name=chkAll]").prop("checked", false);
keywords.push($(e).val()); }
}
}); var selectedAll = true;
return keywords.join("/");
} $("#spnFilterOption input[name=chkOperation]").each(function(i, e){
if(!$(e).prop("checked")){
$('#datetimepicker1').datetimepicker({ selectedAll = false;
locale: i18n.getLocale(), }
ignoreReadonly: true, });
format: 'L',
showClear: true if(selectedAll){
}); $("#spnFilterOption input[name=chkAll]").prop("checked", true);
$('#datetimepicker2').datetimepicker({ }
locale: i18n.getLocale(), });
ignoreReadonly: true,
format: 'L', function getKeyWords(){
showClear: true var keywords = "";
}); var checkedItemList=$("#spnFilterOption input[name=chkOperation]:checked");
}); var keywords = [];
} $.each(checkedItemList, function(i, e){
var itemValue = $(e).val();
$(document).on("keydown", function(e){ if(itemValue == "others" && $.trim($("#txtOthers").val()).length > 0){
if(e.keyCode == 13){ keywords.push($("#txtOthers").val());
e.preventDefault(); }else{
if($("#tabItemDetail li:eq(0)").is(":focus") || $("#txtRepoName").is(":focus")){ keywords.push($(e).val());
$("#btnSearchRepo").trigger("click"); }
}else if($("#tabItemDetail li:eq(1)").is(":focus") || $("#txtSearchUser").is(":focus")){ });
$("#btnSearchUser").trigger("click"); return keywords.join("/");
}else if($("#tabItemDetail li:eq(2)").is(":focus") || $("#txtSearchUserName").is(":focus")){ }
$("#btnFilterLog").trigger("click");
}else if($("#txtUserName").is(":focus") || $("#lstRole :radio").is(":focus")){ $('#datetimepicker1').datetimepicker({
$("#btnSave").trigger("click"); locale: i18n.getLocale(),
} ignoreReadonly: true,
format: 'L',
showClear: true
});
$('#datetimepicker2').datetimepicker({
locale: i18n.getLocale(),
ignoreReadonly: true,
format: 'L',
showClear: true
});
});
}
$(document).on("keydown", function(e){
if(e.keyCode == 13){
e.preventDefault();
if($("#tabItemDetail li:eq(0)").is(":focus") || $("#txtRepoName").is(":focus")){
$("#btnSearchRepo").trigger("click");
}else if($("#tabItemDetail li:eq(1)").is(":focus") || $("#txtSearchUser").is(":focus")){
$("#btnSearchUser").trigger("click");
}else if($("#tabItemDetail li:eq(2)").is(":focus") || $("#txtSearchUserName").is(":focus")){
$("#btnFilterLog").trigger("click");
}else if($("#txtUserName").is(":focus") || $("#lstRole :radio").is(":focus")){
$("#btnSave").trigger("click");
} }
}); }
});
}) })

View File

@ -24,7 +24,7 @@ jQuery(function(){
}, },
error: function(jqXhr){ error: function(jqXhr){
if(jqXhr.status == 401) if(jqXhr.status == 401)
return false; return false;
} }
}).exec(); }).exec();

View File

@ -13,13 +13,13 @@
limitations under the License. limitations under the License.
*/ */
jQuery(function(){ jQuery(function(){
new AjaxUtil({ new AjaxUtil({
url: "/api/users/current", url: "/api/users/current",
type: "get", type: "get",
success: function(data, status, xhr){ success: function(data, status, xhr){
if(xhr && xhr.status == 200){ if(xhr && xhr.status == 200){
if(data.HasAdminRole == 1) { if(data.has_admin_role == 1) {
renderForAdminRole(); renderForAdminRole();
} }
renderForAnyRole(); renderForAnyRole();
@ -29,57 +29,57 @@ jQuery(function(){
function renderForAnyRole(){ function renderForAnyRole(){
$("#tabProject a:first").tab("show"); $("#tabProject a:first").tab("show");
$(document).on("keydown", function(e){ $(document).on("keydown", function(e){
if(e.keyCode == 13){ if(e.keyCode == 13){
e.preventDefault(); e.preventDefault();
if($("#tabProject li:eq(0)").is(":focus") || $("#txtSearchProject").is(":focus")){ if($("#tabProject li:eq(0)").is(":focus") || $("#txtSearchProject").is(":focus")){
$("#btnSearch").trigger("click"); $("#btnSearch").trigger("click");
}else if($("#tabProject li:eq(1)").is(":focus") || $("#txtSearchPublicProjects").is(":focus")){ }else if($("#tabProject li:eq(1)").is(":focus") || $("#txtSearchPublicProjects").is(":focus")){
$("#btnSearchPublicProjects").trigger("click"); $("#btnSearchPublicProjects").trigger("click");
}else if($("#tabProject li:eq(1)").is(":focus") || $("#txtSearchUsername").is(":focus")){ }else if($("#tabProject li:eq(1)").is(":focus") || $("#txtSearchUsername").is(":focus")){
$("#btnSearchUsername").trigger("click"); $("#btnSearchUsername").trigger("click");
}else if($("#dlgAddProject").is(":focus") || $("#projectName").is(":focus")){ }else if($("#dlgAddProject").is(":focus") || $("#projectName").is(":focus")){
$("#btnSave").trigger("click"); $("#btnSave").trigger("click");
} }
} }
}); });
function listProject(projectName, isPublic){ function listProject(projectName, isPublic){
currentPublic = isPublic; currentPublic = isPublic;
$.when( $.when(
new AjaxUtil({ new AjaxUtil({
url: "/api/projects?is_public=" + isPublic + "&project_name=" + (projectName == null ? "" : projectName) + "&timestamp=" + new Date().getTime(), url: "/api/projects?is_public=" + isPublic + "&project_name=" + (projectName == null ? "" : projectName) + "&timestamp=" + new Date().getTime(),
type: "get", type: "get",
success: function(data, status, xhr){ success: function(data, status, xhr){
$("#tblProject tbody tr").remove(); $("#tblProject tbody tr").remove();
$.each(data || [], function(i, e){ $.each(data || [], function(i, e){
var row = '<tr>' + var row = '<tr>' +
'<td style="vertical-align: middle;"><a href="/registry/detail?project_id=' + e.ProjectId + '">' + e.Name + '</a></td>' + '<td style="vertical-align: middle;"><a href="/registry/detail?project_id=' + e.project_id + '">' + e.name + '</a></td>' +
'<td style="vertical-align: middle;">' + moment(new Date(e.CreationTime)).format("YYYY-MM-DD HH:mm:ss") + '</td>'; '<td style="vertical-align: middle;">' + moment(new Date(e.creation_time)).format("YYYY-MM-DD HH:mm:ss") + '</td>';
if(e.Public == 1 && e.Togglable){ if(e.public == 1 && e.Togglable){
row += '<td><button type="button" class="btn btn-success" projectid="' + e.ProjectId + '">' + i18n.getMessage("button_on")+ '</button></td>' row += '<td><button type="button" class="btn btn-success" projectid="' + e.project_id + '">' + i18n.getMessage("button_on")+ '</button></td>'
} else if (e.Public == 1) { } else if (e.public == 1) {
row += '<td><button type="button" class="btn btn-success" projectid="' + e.ProjectId + '" disabled>' + i18n.getMessage("button_on")+ '</button></td>'; row += '<td><button type="button" class="btn btn-success" projectid="' + e.project_id + '" disabled>' + i18n.getMessage("button_on")+ '</button></td>';
} else if (e.Public == 0 && e.Togglable) { } else if (e.public == 0 && e.Togglable) {
row += '<td><button type="button" class="btn btn-danger" projectid="' + e.ProjectId + '">' + i18n.getMessage("button_off")+ '</button></td>'; row += '<td><button type="button" class="btn btn-danger" projectid="' + e.project_id + '">' + i18n.getMessage("button_off")+ '</button></td>';
} else if (e.Public == 0) { } else if (e.public == 0) {
row += '<td><button type="button" class="btn btn-danger" projectid="' + e.ProjectId + '" disabled>' + i18n.getMessage("button_off")+ '</button></td>'; row += '<td><button type="button" class="btn btn-danger" projectid="' + e.project_id + '" disabled>' + i18n.getMessage("button_off")+ '</button></td>';
row += '</tr>'; row += '</tr>';
} }
$("#tblProject tbody").append(row); $("#tblProject tbody").append(row);
}); });
} }
}).exec()) }).exec())
.done(function() { .done(function() {
$("#tblProject tbody tr :button").on("click", function(){ $("#tblProject tbody tr :button").on("click", function(){
var projectId = $(this).attr("projectid"); var projectId = $(this).attr("projectid");
var self = this; var self = this;
new AjaxUtil({ new AjaxUtil({
url: "/api/projects/" + projectId, url: "/api/projects/" + projectId,
data: {"public": ($(self).hasClass("btn-success") ? false : true)}, data: {"public": ($(self).hasClass("btn-success") ? false : true)},
type: "put", type: "put",
complete: function(jqXhr, status) { complete: function(jqXhr, status) {
if($(self).hasClass("btn-success")){ if($(self).hasClass("btn-success")){
$(self).removeClass("btn-success").addClass("btn-danger"); $(self).removeClass("btn-success").addClass("btn-danger");
$(self).html(i18n.getMessage("button_off")); $(self).html(i18n.getMessage("button_off"));
@ -88,9 +88,9 @@ jQuery(function(){
$(self).html(i18n.getMessage("button_on")); $(self).html(i18n.getMessage("button_on"));
} }
} }
}).exec(); }).exec();
}); });
}); });
} }
listProject(null, 0); listProject(null, 0);
var currentPublic = 0; var currentPublic = 0;
@ -119,7 +119,7 @@ jQuery(function(){
$("#projectName").val(""); $("#projectName").val("");
$("#projectName").parent().addClass("has-feedback"); $("#projectName").parent().addClass("has-feedback");
$("#projectName").siblings("span").removeClass("glyphicon-warning-sign").removeClass("glyphicon-ok"); $("#projectName").siblings("span").removeClass("glyphicon-warning-sign").removeClass("glyphicon-ok");
$("#isPublic").prop('checked', false); $("#isPublic").prop('checked', false);
}); });
$("#btnSave").on("click", function(){ $("#btnSave").on("click", function(){
@ -161,52 +161,52 @@ jQuery(function(){
$("#tblUser tbody tr").remove(); $("#tblUser tbody tr").remove();
$.each(data || [], function(i, e){ $.each(data || [], function(i, e){
var row = '<tr>' + var row = '<tr>' +
'<td style="vertical-align: middle;">' + e.username + '</td>' + '<td style="vertical-align: middle;">' + e.username + '</td>' +
'<td style="vertical-align: middle;">' + e.email + '</td>'; '<td style="vertical-align: middle;">' + e.email + '</td>';
if(e.HasAdminRole == 1){ if(e.has_admin_role == 1){
row += '<td style="padding-left: 30px;"><button type="button" class="btn btn-success" userid="' + e.UserId + '">' + i18n.getMessage("button_on") + '</button></td>'; row += '<td style="padding-left: 30px;"><button type="button" class="btn btn-success" userid="' + e.user_id + '">' + i18n.getMessage("button_on") + '</button></td>';
} else { } else {
row += '<td style="padding-left: 30px;"><button type="button" class="btn btn-danger" userid="' + e.UserId + '">' + i18n.getMessage("button_off") + '</button></td>'; row += '<td style="padding-left: 30px;"><button type="button" class="btn btn-danger" userid="' + e.user_id + '">' + i18n.getMessage("button_off") + '</button></td>';
} }
row += '<td style="padding-left: 30px; vertical-align: middle;"><a href="#" style="visibility: hidden;" class="tdDeleteUser" userid="' + e.UserId + '" username="' + e.Username + '"><span class="glyphicon glyphicon-trash"></span></a></td>'; row += '<td style="padding-left: 30px; vertical-align: middle;"><a href="#" style="visibility: hidden;" class="tdDeleteUser" userid="' + e.user_id + '" username="' + e.username + '"><span class="glyphicon glyphicon-trash"></span></a></td>';
row += '</tr>'; row += '</tr>';
$("#tblUser tbody").append(row); $("#tblUser tbody").append(row);
}); });
} }
}).exec() }).exec()
).done(function(){ ).done(function(){
$("#tblUser tbody tr :button").on("click",function(){ $("#tblUser tbody tr :button").on("click",function(){
var userId = $(this).attr("userid"); var userId = $(this).attr("userid");
var self = this; var self = this;
new AjaxUtil({ new AjaxUtil({
url: "/api/users/" + userId, url: "/api/users/" + userId,
type: "put", type: "put",
complete: function(jqXhr, status){ complete: function(jqXhr, status){
if(jqXhr && jqXhr.status == 200){ if(jqXhr && jqXhr.status == 200){
if($(self).hasClass("btn-success")){ if($(self).hasClass("btn-success")){
$(self).removeClass("btn-success").addClass("btn-danger"); $(self).removeClass("btn-success").addClass("btn-danger");
$(self).html(i18n.getMessage("button_off")); $(self).html(i18n.getMessage("button_off"));
}else{ }else{
$(self).removeClass("btn-danger").addClass("btn-success"); $(self).removeClass("btn-danger").addClass("btn-success");
$(self).html(i18n.getMessage("button_on")); $(self).html(i18n.getMessage("button_on"));
} }
} }
} }
}).exec(); }).exec();
}); });
$("#tblUser tbody tr").on("mouseover", function(){ $("#tblUser tbody tr").on("mouseover", function(e){
$(".tdDeleteUser", this).css({"visibility":"visible"}); $(".tdDeleteUser", this).css({"visibility":"visible"});
}).on("mouseout", function(){ }).on("mouseout", function(e){
$(".tdDeleteUser", this).css({"visibility":"hidden"}); $(".tdDeleteUser", this).css({"visibility":"hidden"});
}); });
$("#tblUser tbody tr .tdDeleteUser").on("click", function(){ $("#tblUser tbody tr .tdDeleteUser").on("click", function(e){
var userId = $(this).attr("userid"); var userId = $(this).attr("userid");
$("#dlgModal") $("#dlgModal")
.dialogModal({ .dialogModal({
"title": i18n.getMessage("delete_user"), "title": i18n.getMessage("delete_user"),
"content": i18n.getMessage("are_you_sure_to_delete_user") + $(this).attr("username") + " ?", "content": i18n.getMessage("are_you_sure_to_delete_user") + $(this).attr("username") + " ?",
"enableCancel": true, "enableCancel": true,
"callback": function(){ "callback": function(){
new AjaxUtil({ new AjaxUtil({
url: "/api/users/" + userId, url: "/api/users/" + userId,
type: "delete", type: "delete",
@ -218,17 +218,18 @@ jQuery(function(){
error: function(jqXhr){} error: function(jqXhr){}
}).exec(); }).exec();
} }
});
}); });
}); });
}
listUserAdminRole(null);
$("#btnSearchUsername").on("click", function(){
var username = $("#txtSearchUsername").val();
if($.trim(username).length == 0){
username = null;
}
listUserAdminRole(username);
}); });
} }
listUserAdminRole(null); })
$("#btnSearchUsername").on("click", function(){
var username = $("#txtSearchUsername").val();
if($.trim(username).length == 0){
username = null;
}
listUserAdminRole(username);
});
}
})

View File

@ -30,14 +30,14 @@ jQuery(function(){
$("#btnPageSignUp").on("click", function(){ $("#btnPageSignUp").on("click", function(){
validateOptions.Validate(function() { validateOptions.Validate(function() {
var username = $.trim($("#Username").val()); var username = $.trim($("#Username").val());
var email = $.trim($("#Email").val()); var email = $.trim($("#Email").val());
var password = $.trim($("#Password").val()); var password = $.trim($("#Password").val());
var confirmedPassword = $.trim($("#ConfirmedPassword").val()); var confirmedPassword = $.trim($("#ConfirmedPassword").val());
var realname = $.trim($("#Realname").val()); var realname = $.trim($("#Realname").val());
var comment = $.trim($("#Comment").val()); var comment = $.trim($("#Comment").val());
var isAdmin = $("#isAdmin").val(); var isAdmin = $("#isAdmin").val();
new AjaxUtil({ new AjaxUtil({
url : "/api/users", url : "/api/users",
data: {"username": username, "password": password, "realname": realname, "comment": comment, "email": email}, data: {"username": username, "password": password, "realname": realname, "comment": comment, "email": email},
@ -47,29 +47,29 @@ jQuery(function(){
}, },
error:function(jqxhr, status, error){ error:function(jqxhr, status, error){
$("#dlgModal") $("#dlgModal")
.dialogModal({ .dialogModal({
"title": i18n.getMessage("title_sign_up"), "title": i18n.getMessage("title_sign_up"),
"content": i18n.getMessage("internal_error"), "content": i18n.getMessage("internal_error"),
"callback": function(){ "callback": function(){
return; return;
} }
}); });
}, },
complete: function(xhr, status){ complete: function(xhr, status){
$("#btnPageSignUp").prop("disabled", false); $("#btnPageSignUp").prop("disabled", false);
if(xhr && xhr.status == 201){ if(xhr && xhr.status == 201){
$("#dlgModal") $("#dlgModal")
.dialogModal({ .dialogModal({
"title": isAdmin == "true" ? i18n.getMessage("title_add_user") : i18n.getMessage("title_sign_up"), "title": isAdmin == "true" ? i18n.getMessage("title_add_user") : i18n.getMessage("title_sign_up"),
"content": isAdmin == "true" ? i18n.getMessage("added_user_successfully") : i18n.getMessage("registered_successfully"), "content": isAdmin == "true" ? i18n.getMessage("added_user_successfully") : i18n.getMessage("registered_successfully"),
"callback": function(){ "callback": function(){
if(isAdmin == "true") { if(isAdmin == "true") {
document.location = "/registry/project"; document.location = "/registry/project";
}else{ }else{
document.location = "/signIn"; document.location = "/signIn";
}
} }
}); }
});
} }
} }
}).exec(); }).exec();

View File

@ -17,11 +17,11 @@ jQuery(function(){
$("#Password,#ConfirmedPassword").on("blur", validateCallback); $("#Password,#ConfirmedPassword").on("blur", validateCallback);
validateOptions.Items = ["#Password", "#ConfirmedPassword"]; validateOptions.Items = ["#Password", "#ConfirmedPassword"];
function bindEnterKey(){ function bindEnterKey(){
$(document).on("keydown", function(e){ $(document).on("keydown", function(e){
if(e.keyCode == 13){ if(e.keyCode == 13){
e.preventDefault(); e.preventDefault();
$("#btnSubmit").trigger("click"); $("#btnSubmit").trigger("click");
} }
}); });
} }
@ -30,7 +30,6 @@ jQuery(function(){
} }
bindEnterKey(); bindEnterKey();
var spinner = new Spinner({scale:1}).spin(); var spinner = new Spinner({scale:1}).spin();
$("#btnSubmit").on("click", function(){ $("#btnSubmit").on("click", function(){
@ -42,20 +41,20 @@ jQuery(function(){
"type": "post", "type": "post",
"data": {"reset_uuid": resetUuid, "password": password}, "data": {"reset_uuid": resetUuid, "password": password},
"beforeSend": function(e){ "beforeSend": function(e){
unbindEnterKey(); unbindEnterKey();
$("h1").append(spinner.el); $("h1").append(spinner.el);
$("#btnSubmit").prop("disabled", true); $("#btnSubmit").prop("disabled", true);
}, },
"success": function(data, status, xhr){ "success": function(data, status, xhr){
if(xhr && xhr.status == 200){ if(xhr && xhr.status == 200){
$("#dlgModal") $("#dlgModal")
.dialogModal({ .dialogModal({
"title": i18n.getMessage("title_reset_password"), "title": i18n.getMessage("title_reset_password"),
"content": i18n.getMessage("reset_password_successfully"), "content": i18n.getMessage("reset_password_successfully"),
"callback": function(){ "callback": function(){
document.location="/signIn"; document.location="/signIn";
} }
}); });
} }
}, },
@ -66,14 +65,14 @@ jQuery(function(){
"error": function(jqXhr, status, error){ "error": function(jqXhr, status, error){
if(jqXhr){ if(jqXhr){
$("#dlgModal") $("#dlgModal")
.dialogModal({ .dialogModal({
"title": i18n.getMessage("title_reset_password"), "title": i18n.getMessage("title_reset_password"),
"content": i18n.getMessage(jqXhr.responseText), "content": i18n.getMessage(jqXhr.responseText),
"callback": function(){ "callback": function(){
bindEnterKey(); bindEnterKey();
return; return;
} }
}); });
} }
} }
}); });

View File

@ -60,12 +60,12 @@ jQuery(function(){
$.each(data, function(i, e){ $.each(data, function(i, e){
var project, description, repoName; var project, description, repoName;
switch(discriminator){ switch(discriminator){
case "project": case "project":
project = new Project(e.id, e.name, e.public); project = new Project(e.id, e.name, e.public);
description = project.name; description = project.name;
repoName = ""; repoName = "";
break; break;
case "repository": case "repository":
project = new Project(e.project_id, e.project_name, e.project_public); project = new Project(e.project_id, e.project_name, e.project_public);
description = e.repository_name; description = e.repository_name;
repoName = e.repository_name.substring(e.repository_name.lastIndexOf("/") + 1); repoName = e.repository_name.substring(e.repository_name.lastIndexOf("/") + 1);

View File

@ -56,7 +56,7 @@ jQuery(function(){
success: function(jqXhr, status){ success: function(jqXhr, status){
var lastUri = location.search; var lastUri = location.search;
if(lastUri != "" && lastUri.indexOf("=") > 0){ if(lastUri != "" && lastUri.indexOf("=") > 0){
document.location = decodeURIComponent(lastUri.split("=")[1]); document.location = decodeURIComponent(lastUri.split("=")[1]);
}else{ }else{
document.location = "/registry/project"; document.location = "/registry/project";
} }
@ -69,10 +69,10 @@ jQuery(function(){
i18nKey = "check_your_username_or_password" i18nKey = "check_your_username_or_password"
} }
$("#dlgModal") $("#dlgModal")
.dialogModal({ .dialogModal({
"title": i18n.getMessage("title_login_failed"), "title": i18n.getMessage("title_login_failed"),
"content": i18n.getMessage(i18nKey) "content": i18n.getMessage(i18nKey)
}); });
} }
}); });
}); });

View File

@ -26,18 +26,18 @@ var validateOptions = {
"Username" :{ "Username" :{
"Required": { "value" : true, "errMsg" : i18n.getMessage("username_is_required")}, "Required": { "value" : true, "errMsg" : i18n.getMessage("username_is_required")},
"CheckExist": { "value" : function(value){ "CheckExist": { "value" : function(value){
var result = true; var result = true;
$.ajax({ $.ajax({
url: "/userExists", url: "/userExists",
data: {"target": "username", "value" : value}, data: {"target": "username", "value" : value},
dataType: "json", dataType: "json",
type: "post", type: "post",
async: false, async: false,
success: function(data){ success: function(data){
result = data; result = data;
} }
}); });
return result; return result;
}, "errMsg" : i18n.getMessage("username_has_been_taken")}, }, "errMsg" : i18n.getMessage("username_has_been_taken")},
"MaxLength": {"value" : 20, "errMsg" : i18n.getMessage("username_is_too_long")}, "MaxLength": {"value" : 20, "errMsg" : i18n.getMessage("username_is_too_long")},
"IllegalChar": {"value": [",","~","#", "$", "%"] , "errMsg": i18n.getMessage("username_contains_illegal_chars")} "IllegalChar": {"value": [",","~","#", "$", "%"] , "errMsg": i18n.getMessage("username_contains_illegal_chars")}
@ -45,40 +45,40 @@ var validateOptions = {
"Email" :{ "Email" :{
"Required": { "value" : true, "errMsg" : i18n.getMessage("email_is_required")}, "Required": { "value" : true, "errMsg" : i18n.getMessage("email_is_required")},
"RegExp": {"value": /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, "RegExp": {"value": /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
"errMsg": i18n.getMessage("email_contains_illegal_chars")}, "errMsg": i18n.getMessage("email_contains_illegal_chars")},
"CheckExist": { "value" : function(value){ "CheckExist": { "value" : function(value){
var result = true; var result = true;
$.ajax({ $.ajax({
url: "/userExists", url: "/userExists",
data: {"target": "email", "value": value}, data: {"target": "email", "value": value},
dataType: "json", dataType: "json",
type: "post", type: "post",
async: false, async: false,
success: function(data){ success: function(data){
result = data; result = data;
} }
}); });
return result; return result;
}, "errMsg" : i18n.getMessage("email_has_been_taken")} }, "errMsg" : i18n.getMessage("email_has_been_taken")}
}, },
"EmailF" :{ "EmailF" :{
"Required": { "value" : true, "errMsg" : i18n.getMessage("email_is_required")}, "Required": { "value" : true, "errMsg" : i18n.getMessage("email_is_required")},
"RegExp": {"value": /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/, "RegExp": {"value": /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
"errMsg": i18n.getMessage("email_content_illegal")}, "errMsg": i18n.getMessage("email_content_illegal")},
"CheckIfNotExist": { "value" : function(value){ "CheckIfNotExist": { "value" : function(value){
var result = true; var result = true;
$.ajax({ $.ajax({
url: "/userExists", url: "/userExists",
data: {"target": "email", "value": value}, data: {"target": "email", "value": value},
dataType: "json", dataType: "json",
type: "post", type: "post",
async: false, async: false,
success: function(data){ success: function(data){
result = data; result = data;
} }
}); });
return result; return result;
}, "errMsg" : i18n.getMessage("email_does_not_exist")} }, "errMsg" : i18n.getMessage("email_does_not_exist")}
}, },
"Realname" :{ "Realname" :{
"Required": { "value" : true, "errMsg" : i18n.getMessage("realname_is_required")}, "Required": { "value" : true, "errMsg" : i18n.getMessage("realname_is_required")},
@ -119,7 +119,7 @@ function validateCallback(target){
var currentId = $(target).attr("id"); var currentId = $(target).attr("id");
var validateItem = validateOptions[currentId]; var validateItem = validateOptions[currentId];
var errMsg = ""; var errMsg = "";
for(var checkTitle in validateItem){ for(var checkTitle in validateItem){

View File

@ -16,32 +16,32 @@
<div class="col-sm-4"></div> <div class="col-sm-4"></div>
<div class="col-sm-4"> <div class="col-sm-4">
<div class="page-header"> <div class="page-header">
<h1>{{i18n .Lang "title_change_password"}}</h1> <h1>{{i18n .Lang "title_change_password"}}</h1>
</div> </div>
<form class="form"> <form class="form">
<div class="alert alert-danger" role="alert" id="divErrMsg"></div> <div class="alert alert-danger" role="alert" id="divErrMsg"></div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="OldPassword" class="control-label">{{i18n .Lang "old_password"}}</label> <label for="OldPassword" class="control-label">{{i18n .Lang "old_password"}}</label>
<input type="password" class="form-control" id="OldPassword"> <input type="password" class="form-control" id="OldPassword">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="Password" class="control-label">{{i18n .Lang "new_password"}}</label> <label for="Password" class="control-label">{{i18n .Lang "new_password"}}</label>
<input type="password" class="form-control" id="Password"> <input type="password" class="form-control" id="Password">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<h6>{{i18n .Lang "password_description"}}</h6> <h6>{{i18n .Lang "password_description"}}</h6>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="ConfirmedPassword" class="control-label">{{i18n .Lang "confirm_password"}}</label> <label for="ConfirmedPassword" class="control-label">{{i18n .Lang "confirm_password"}}</label>
<input type="password" class="form-control" id="ConfirmedPassword"> <input type="password" class="form-control" id="ConfirmedPassword">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<h6>{{i18n .Lang "password_description"}}</h6> <h6>{{i18n .Lang "password_description"}}</h6>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<div class="text-center"> <div class="text-center">
<button type="button" class="btn btn-default" id="btnSubmit">{{i18n .Lang "button_submit"}}</button> <button type="button" class="btn btn-default" id="btnSubmit">{{i18n .Lang "button_submit"}}</button>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
<div class="col-sm-4"></div> <div class="col-sm-4"></div>

View File

@ -19,19 +19,19 @@
<h1>{{i18n .Lang "title_forgot_password"}}</h1> <h1>{{i18n .Lang "title_forgot_password"}}</h1>
</div> </div>
<form class="form"> <form class="form">
<div id="waiting1" class="waiting-nonfluid"></div> <div id="waiting1" class="waiting-nonfluid"></div>
<div class="alert alert-danger" role="alert" id="divErrMsg"></div> <div class="alert alert-danger" role="alert" id="divErrMsg"></div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="EmailF" class="control-label">{{i18n .Lang "email"}}</label> <label for="EmailF" class="control-label">{{i18n .Lang "email"}}</label>
<input type="email" class="form-control" id="EmailF"> <input type="email" class="form-control" id="EmailF">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<h6>{{i18n .Lang "forgot_password_description"}}</h6> <h6>{{i18n .Lang "forgot_password_description"}}</h6>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<div class="text-center"> <div class="text-center">
<button type="button" class="btn btn-default" id="btnSubmit">{{i18n .Lang "button_submit"}}</button> <button type="button" class="btn btn-default" id="btnSubmit">{{i18n .Lang "button_submit"}}</button>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
<div class="col-sm-4"></div> <div class="col-sm-4"></div>

View File

@ -13,25 +13,25 @@
limitations under the License. limitations under the License.
--> -->
<!-- Main jumbotron for a primary marketing message or call to action --> <!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron"> <div class="jumbotron">
<div class="container"> <div class="container">
<img class="pull-left" src="static/resources/image/Harbor_Logo_rec.png" alt="Harbor's Logo" height="180" width="360"/> <img class="pull-left" src="static/resources/image/Harbor_Logo_rec.png" alt="Harbor's Logo" height="180" width="360"/>
<p class="pull-left" style="margin-top: 85px; color: #245580; font-size: 30pt; text-align: center; width: 60%;">{{i18n .Lang "index_title"}}</p> <p class="pull-left" style="margin-top: 85px; color: #245580; font-size: 30pt; text-align: center; width: 60%;">{{i18n .Lang "index_title"}}</p>
</div> </div>
</div> </div>
<div class="container"> <div class="container">
<!-- Example row of columns --> <!-- Example row of columns -->
<div class="row"> <div class="row">
<div class="col-md-12"> <div class="col-md-12">
<p>{{i18n .Lang "index_desc"}}</p> <p>{{i18n .Lang "index_desc"}}</p>
<p>{{i18n .Lang "index_desc_0"}}</p> <p>{{i18n .Lang "index_desc_0"}}</p>
<p>{{i18n .Lang "index_desc_1"}}</p> <p>{{i18n .Lang "index_desc_1"}}</p>
<p>{{i18n .Lang "index_desc_2"}}</p> <p>{{i18n .Lang "index_desc_2"}}</p>
<p>{{i18n .Lang "index_desc_3"}}</p> <p>{{i18n .Lang "index_desc_3"}}</p>
<p>{{i18n .Lang "index_desc_4"}}</p> <p>{{i18n .Lang "index_desc_4"}}</p>
<p>{{i18n .Lang "index_desc_5"}}</p> <p>{{i18n .Lang "index_desc_5"}}</p>
</div> </div>
</div> </div>
</div> <!-- /container --> </div> <!-- /container -->
<script src="static/resources/js/login.js"></script> <script src="static/resources/js/login.js"></script>

View File

@ -18,7 +18,7 @@
<li>{{.ProjectName}}</li> <li>{{.ProjectName}}</li>
</ol> </ol>
<div class="page-header" style="margin-top: -10px;"> <div class="page-header" style="margin-top: -10px;">
<h2>{{.ProjectName}} </h2></h4>{{i18n .Lang "owner"}}: {{.OwnerName}}</h4> <h2>{{.ProjectName}} </h2><h4>{{i18n .Lang "owner"}}: {{.OwnerName}}</h4>
</div> </div>
<div row="tabpanel"> <div row="tabpanel">
<div class="row"> <div class="row">
@ -29,152 +29,150 @@
<li role="presentation" style="visibility: hidden;"><a href="#tabOperationLog" aria-controls="tabOperationLog" role="tab" data-toggle="tab">{{i18n .Lang "logs"}}</a></li> <li role="presentation" style="visibility: hidden;"><a href="#tabOperationLog" aria-controls="tabOperationLog" role="tab" data-toggle="tab">{{i18n .Lang "logs"}}</a></li>
</ul> </ul>
</div> </div>
<div class="col-md-10"> <div class="col-md-10">
<input type="hidden" id="projectId" value="{{.ProjectId}}"> <input type="hidden" id="projectId" value="{{.ProjectId}}">
<input type="hidden" id="projectName" value="{{.ProjectName}}"> <input type="hidden" id="projectName" value="{{.ProjectName}}">
<input type="hidden" id="userId" value="{{.UserId}}"> <input type="hidden" id="userId" value="{{.UserId}}">
<input type="hidden" id="ownerId" value="{{.OwnerId}}"> <input type="hidden" id="ownerId" value="{{.OwnerId}}">
<input type="hidden" id="roleId" value="{{.RoleId}}"> <input type="hidden" id="roleId" value="{{.RoleId}}">
<input type="hidden" id="harborRegUrl" value="{{.HarborRegUrl}}"> <input type="hidden" id="harborRegUrl" value="{{.HarborRegUrl}}">
<input type="hidden" id="public" value="{{.Public}}"> <input type="hidden" id="public" value="{{.Public}}">
<input type="hidden" id="repoName" value="{{.RepoName}}"> <input type="hidden" id="repoName" value="{{.RepoName}}">
<!-- tab panes --> <!-- tab panes -->
<div class="tab-content"> <div class="tab-content">
<div role="tabpanel" class="tab-pane" id="tabRepoInfo"> <div role="tabpanel" class="tab-pane" id="tabRepoInfo">
<form class="form-inline"> <form class="form-inline">
<div class="form-group"> <div class="form-group">
<label class="sr-only" for="txtRepoName">{{i18n .Lang "repo_name"}}:</label> <label class="sr-only" for="txtRepoName">{{i18n .Lang "repo_name"}}:</label>
<div class="input-group"> <div class="input-group">
<div class="input-group-addon">{{i18n .Lang "repo_name"}}:</div> <div class="input-group-addon">{{i18n .Lang "repo_name"}}:</div>
<input type="text" class="form-control" id="txtRepoName"> <input type="text" class="form-control" id="txtRepoName">
<span class="input-group-btn">
<button id="btnSearchRepo" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button>
</span>
</div>
</div>
</form>
<p>
<div class="table-responsive div-height">
<div class="alert alert-danger" role="alert" id="divErrMsg"><center></center></div>
<div class="panel-group" id="accordionRepo" role="tablist" aria-multiselectable="true">
</div>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="tabUserInfo">
<form class="form-inline">
<div class="form-group">
<div class="input-group">
<label class="sr-only" for="txtSearchUser">{{i18n .Lang "username"}}:</label>
<div class="input-group">
<div class="input-group-addon">{{i18n .Lang "username"}}:</div>
<input type="text" class="form-control" id="txtSearchUser">
<span class="input-group-btn"> <span class="input-group-btn">
<button id="btnSearchUser" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button> <button id="btnSearchRepo" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button>
</span> </span>
</div> </div>
</div> </div>
</form>
<p/>
<div class="table-responsive div-height">
<div class="alert alert-danger" role="alert" id="divErrMsg"><center></center></div>
<div class="panel-group" id="accordionRepo" role="tablist" aria-multiselectable="true">
</div>
</div> </div>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#dlgUser" id="btnAddUser">{{i18n .Lang "add_members"}}</button>
</form>
<p>
<div class="table-responsive div-height">
<table id="tblUser" class="table table-hover">
<thead>
<tr>
<th>{{i18n .Lang "username"}}</th>
<th>{{i18n .Lang "role"}}</th>
<th>{{i18n .Lang "operation"}}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div> </div>
</div> <div role="tabpanel" class="tab-pane" id="tabUserInfo">
<div role="tabpanel" class="tab-pane" id="tabOperationLog"> <form class="form-inline">
<form class="form-inline">
<div class="form-group">
<label for="txtUserName" class="sr-only">{{i18n .Lang "username"}}:</label>
<div class="input-group">
<div class="input-group-addon">{{i18n .Lang "username"}}:</div>
<input type="text" class="form-control" id="txtSearchUserName">
<span class="input-group-btn">
<button id="btnFilterLog" type="button" class="btn btn-primary" data-toggle="modal" data-target="#dlgSearch"><span class="glyphicon glyphicon-search"></span></button>
</span>
</div>
</div>
<div class="form-group">
<div class="input-group">
<button class="btn btn-link" type="button" data-toggle="collapse" data-target="#collapseAdvance" aria-expanded="false" aria-controls="collapseAdvance">{{i18n .Lang "advance"}}</button>
</div>
</div>
<form>
<p></p>
<div class="collapse" id="collapseAdvance">
<form class="form">
<div class="form-group"> <div class="form-group">
<label for="txtUserName" class="sr-only">{{i18n .Lang "operation"}}:</label> <div class="input-group">
<label class="sr-only" for="txtSearchUser">{{i18n .Lang "username"}}:</label>
<div class="input-group">
<div class="input-group-addon">{{i18n .Lang "username"}}:</div>
<input type="text" class="form-control" id="txtSearchUser">
<span class="input-group-btn">
<button id="btnSearchUser" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button>
</span>
</div>
</div>
</div>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#dlgUser" id="btnAddUser">{{i18n .Lang "add_members"}}</button>
</form>
<p/>
<div class="table-responsive div-height">
<table id="tblUser" class="table table-hover">
<thead>
<tr>
<th>{{i18n .Lang "username"}}</th>
<th>{{i18n .Lang "role"}}</th>
<th>{{i18n .Lang "operation"}}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<div role="tabpanel" class="tab-pane" id="tabOperationLog">
<form class="form-inline">
<div class="form-group">
<label for="txtUserName" class="sr-only">{{i18n .Lang "username"}}:</label>
<div class="input-group"> <div class="input-group">
<div class="input-group-addon">{{i18n .Lang "operation"}}:</div> <div class="input-group-addon">{{i18n .Lang "username"}}:</div>
<span class="input-group-addon" id="spnFilterOption"> <input type="text" class="form-control" id="txtSearchUserName">
<input type="checkbox" name="chkAll" value="0"> {{i18n .Lang "all"}} <span class="input-group-btn">
<input type="checkbox" name="chkOperation" value="create"> Create <button id="btnFilterLog" type="button" class="btn btn-primary" data-toggle="modal" data-target="#dlgSearch"><span class="glyphicon glyphicon-search"></span></button>
<input type="checkbox" name="chkOperation" value="pull"> Pull
<input type="checkbox" name="chkOperation" value="push"> Push
<input type="checkbox" name="chkOperation" value="delete"> Delete
<input type="checkbox" name="chkOperation" value="others"> {{i18n .Lang "others"}}:
<input type="text" id="txtOthers" size="10">
</span> </span>
</div> </div>
</div> </div>
<p></p>
<div class="form-group"> <div class="form-group">
<label for="begindatepicker" class="sr-only">{{i18n .Lang "start_date"}}:</label> <div class="input-group">
<div class="input-group"> <button class="btn btn-link" type="button" data-toggle="collapse" data-target="#collapseAdvance" aria-expanded="false" aria-controls="collapseAdvance">{{i18n .Lang "advance"}}</button>
<div class="input-group-addon">{{i18n .Lang "start_date"}}:</div>
<div class="input-group date" id="datetimepicker1">
<input type="text" class="form-control" id="begindatepicker" readonly="readonly">
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div> </div>
</div> </div>
<div class="form-group"> <p/>
<div class="input-group"> <div class="collapse" id="collapseAdvance">
<div class="input-group-addon">{{i18n .Lang "end_date"}}:</div> <form class="form">
<div class="input-group date" id="datetimepicker2"> <div class="form-group">
<input type="text" class="form-control" id="enddatepicker" readonly="readonly"> <label for="txtUserName" class="sr-only">{{i18n .Lang "operation"}}:</label>
<span class="input-group-addon"> <div class="input-group">
<span class="glyphicon glyphicon-calendar"></span> <div class="input-group-addon">{{i18n .Lang "operation"}}:</div>
</span> <span class="input-group-addon" id="spnFilterOption">
</div> <input type="checkbox" name="chkAll" value="0"> {{i18n .Lang "all"}}
</div> <input type="checkbox" name="chkOperation" value="create"> Create
<input type="checkbox" name="chkOperation" value="pull"> Pull
</div> <input type="checkbox" name="chkOperation" value="push"> Push
</form> <input type="checkbox" name="chkOperation" value="delete"> Delete
</div> <input type="checkbox" name="chkOperation" value="others"> {{i18n .Lang "others"}}:
<div class="table-responsive div-height"> <input type="text" id="txtOthers" size="10">
<table id="tblAccessLog" class="table table-hover" > </span>
<thead> </div>
<tr> </div>
<th width="15%">{{i18n .Lang "username"}}</th> <p></p>
<th width="30%">{{i18n .Lang "repo_name"}}</th> <div class="form-group">
<th width="15%">{{i18n .Lang "repo_tag"}}</th> <label for="begindatepicker" class="sr-only">{{i18n .Lang "start_date"}}:</label>
<th width="15%">{{i18n .Lang "operation"}}</th> <div class="input-group">
<th width="15%">{{i18n .Lang "timestamp"}}</th> <div class="input-group-addon">{{i18n .Lang "start_date"}}:</div>
</tr> <div class="input-group date" id="datetimepicker1">
</thead> <input type="text" class="form-control" id="begindatepicker" readonly="readonly">
<tbody> <span class="input-group-addon">
</tbody> <span class="glyphicon glyphicon-calendar"></span>
</table> </span>
</div> </div>
</div> </div>
</div>
<div class="form-group">
<div class="input-group">
<div class="input-group-addon">{{i18n .Lang "end_date"}}:</div>
<div class="input-group date" id="datetimepicker2">
<input type="text" class="form-control" id="enddatepicker" readonly="readonly">
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
</div>
</div>
</form>
</div>
<div class="table-responsive div-height">
<table id="tblAccessLog" class="table table-hover" >
<thead>
<tr>
<th width="15%">{{i18n .Lang "username"}}</th>
<th width="30%">{{i18n .Lang "repo_name"}}</th>
<th width="15%">{{i18n .Lang "repo_tag"}}</th>
<th width="15%">{{i18n .Lang "operation"}}</th>
<th width="15%">{{i18n .Lang "timestamp"}}</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</form>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="modal fade" id="dlgUser" tabindex="-1" role="dialog" aria-labelledby="User" aria-hidden="true"> <div class="modal fade" id="dlgUser" tabindex="-1" role="dialog" aria-labelledby="User" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">

View File

@ -25,24 +25,24 @@
<!-- tab panes --> <!-- tab panes -->
<div class="tab-content"> <div class="tab-content">
<div role="tabpanel" class="tab-pane" id="tabMyProject" style="margin-top: 15px;"> <div role="tabpanel" class="tab-pane" id="tabMyProject" style="margin-top: 15px;">
<form class="form-inline"> <form class="form-inline">
<label class="sr-only" for="txtProjectName">{{i18n .Lang "project_name"}}:</label> <label class="sr-only" for="txtProjectName">{{i18n .Lang "project_name"}}:</label>
<div class="input-group"> <div class="input-group">
<div class="input-group-addon">{{i18n .Lang "project_name"}}:</div> <div class="input-group-addon">{{i18n .Lang "project_name"}}:</div>
<input type="text" class="form-control" id="txtSearchProject"> <input type="text" class="form-control" id="txtSearchProject">
<span class="input-group-btn"> <span class="input-group-btn">
<button id="btnSearch" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button> <button id="btnSearch" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button>
</span> </span>
</div> </div>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#dlgAddProject" id="btnAddProject">{{i18n .Lang "add_project"}}</button> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#dlgAddProject" id="btnAddProject">{{i18n .Lang "add_project"}}</button>
</form> </form>
<div class="table-responsive div-height"> <div class="table-responsive div-height">
<table id="tblProject" class="table table-hover"> <table id="tblProject" class="table table-hover">
<thead> <thead>
<tr> <tr>
<th width="35%">{{i18n .Lang "project_name"}}</th> <th width="35%">{{i18n .Lang "project_name"}}</th>
<th width="45%">{{i18n .Lang "creation_time"}}</th> <th width="45%">{{i18n .Lang "creation_time"}}</th>
<th width="20%">{{i18n .Lang "publicity"}}</th> <th width="20%">{{i18n .Lang "publicity"}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -51,65 +51,65 @@
</div> </div>
</div> </div>
<div role="tabpanel" class="tab-pane" id="tabAdminOption" style="visibility: hidden; margin-top: 15px;"> <div role="tabpanel" class="tab-pane" id="tabAdminOption" style="visibility: hidden; margin-top: 15px;">
<form class="form-inline"> <form class="form-inline">
<label class="sr-only" for="txtProjectName">{{i18n .Lang "username"}}:</label> <label class="sr-only" for="txtProjectName">{{i18n .Lang "username"}}:</label>
<div class="input-group"> <div class="input-group">
<div class="input-group-addon">{{i18n .Lang "username"}}:</div> <div class="input-group-addon">{{i18n .Lang "username"}}:</div>
<input type="text" class="form-control" id="txtSearchUsername"> <input type="text" class="form-control" id="txtSearchUsername">
<span class="input-group-btn"> <span class="input-group-btn">
<button id="btnSearchUsername" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button> <button id="btnSearchUsername" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button>
</span> </span>
</div>
</form>
<div class="table-responsive div-height">
<table id="tblUser" class="table table-hover">
<thead>
<tr>
<th width="35%">{{i18n .Lang "username"}}</th>
<th width="45%">{{i18n .Lang "email"}}</th>
<th width="20%">{{i18n .Lang "system_admin"}}</th>
<th></th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div> </div>
</div> </form>
</div> <div class="table-responsive div-height">
</div> <table id="tblUser" class="table table-hover">
</div> <thead>
<div class="modal fade" id="dlgAddProject" tabindex="-1" role="dialog" aria-labelledby="Add Project" aria-hidden="true"> <tr>
<div class="modal-dialog"> <th width="35%">{{i18n .Lang "username"}}</th>
<div class="modal-content"> <th width="45%">{{i18n .Lang "email"}}</th>
<div class="modal-header"> <th width="20%">{{i18n .Lang "system_admin"}}</th>
<a type="button" class="close" data-dismiss="modal" aria-label="Close" id="btnCancel"> <th></th>
<span aria-hidden="true">&times;</span> </tr>
</a> </thead>
<h4 class="modal-title" id="dlgAddProjectTitle">{{i18n .Lang "add_project"}}</h4> <tbody>
</div> </tbody>
<div class="modal-body"> </table>
<form role="form">
<div class="alert alert-danger" role="alert" id="divErrMsg"></div>
<div class="form-group has-feedback">
<label for="projectName" class="control-label">{{i18n .Lang "project_name"}}:</label>
<input type="text" class="form-control" id="projectName">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="isPublic" checked=false> {{i18n .Lang "check_for_publicity"}}
</label>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="btnSave">{{i18n .Lang "button_save"}}</button>
<button type="button" class="btn btn-default" data-dismiss="modal">{{i18n .Lang "button_cancel"}}</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="modal fade" id="dlgAddProject" tabindex="-1" role="dialog" aria-labelledby="Add Project" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<a type="button" class="close" data-dismiss="modal" aria-label="Close" id="btnCancel">
<span aria-hidden="true">&times;</span>
</a>
<h4 class="modal-title" id="dlgAddProjectTitle">{{i18n .Lang "add_project"}}</h4>
</div>
<div class="modal-body">
<form role="form">
<div class="alert alert-danger" role="alert" id="divErrMsg"></div>
<div class="form-group has-feedback">
<label for="projectName" class="control-label">{{i18n .Lang "project_name"}}:</label>
<input type="text" class="form-control" id="projectName">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span>
</div>
<div class="checkbox">
<label>
<input type="checkbox" id="isPublic" checked=false> {{i18n .Lang "check_for_publicity"}}
</label>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" id="btnSave">{{i18n .Lang "button_save"}}</button>
<button type="button" class="btn btn-default" data-dismiss="modal">{{i18n .Lang "button_cancel"}}</button>
</div>
</div>
</div>
</div>
</div>
<script src="static/resources/js/validate-options.js"></script> <script src="static/resources/js/validate-options.js"></script>
<script src="static/resources/js/project.js"></script> <script src="static/resources/js/project.js"></script>

View File

@ -16,65 +16,65 @@
<div class="col-sm-4"></div> <div class="col-sm-4"></div>
<div class="col-sm-4"> <div class="col-sm-4">
<div class="page-header"> <div class="page-header">
{{ if eq .IsAdmin true }} {{ if eq .IsAdmin true }}
<h1>{{i18n .Lang "add_user" }}</h1> <h1>{{i18n .Lang "add_user" }}</h1>
{{ else }} {{ else }}
<h1>{{i18n .Lang "registration"}}</h1> <h1>{{i18n .Lang "registration"}}</h1>
{{ end }} {{ end }}
</div> </div>
<form class="form"> <form class="form">
<div class="alert alert-danger" role="alert" id="divErrMsg"></div> <div class="alert alert-danger" role="alert" id="divErrMsg"></div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="username" class="control-label">{{i18n .Lang "username"}}</label> <label for="username" class="control-label">{{i18n .Lang "username"}}</label>
<p style="display:inline; color: red; font-size: 12pt;">*</p> <p style="display:inline; color: red; font-size: 12pt;">*</p>
<input type="text" class="form-control" id="Username"> <input type="text" class="form-control" id="Username">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<h6>{{i18n .Lang "username_description"}}</h6> <h6>{{i18n .Lang "username_description"}}</h6>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="Email" class="control-label">{{i18n .Lang "email"}}</label> <label for="Email" class="control-label">{{i18n .Lang "email"}}</label>
<p style="display:inline; color: red; font-size: 12pt;">*</p> <p style="display:inline; color: red; font-size: 12pt;">*</p>
<input type="email" class="form-control" id="Email"> <input type="email" class="form-control" id="Email">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<h6>{{i18n .Lang "email_description"}}</h6> <h6>{{i18n .Lang "email_description"}}</h6>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="Realname" class="control-label">{{i18n .Lang "full_name"}}</label> <label for="Realname" class="control-label">{{i18n .Lang "full_name"}}</label>
<p style="display:inline; color: red; font-size: 12pt;">*</p> <p style="display:inline; color: red; font-size: 12pt;">*</p>
<input type="text" class="form-control" id="Realname"> <input type="text" class="form-control" id="Realname">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<h6>{{i18n .Lang "full_name_description"}}</h6> <h6>{{i18n .Lang "full_name_description"}}</h6>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="Password" class="control-label">{{i18n .Lang "password"}}</label> <label for="Password" class="control-label">{{i18n .Lang "password"}}</label>
<p style="display:inline; color: red; font-size: 12pt;">*</p> <p style="display:inline; color: red; font-size: 12pt;">*</p>
<input type="password" class="form-control" id="Password"> <input type="password" class="form-control" id="Password">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<h6>{{i18n .Lang "password_description"}}</h6> <h6>{{i18n .Lang "password_description"}}</h6>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="ConfirmedPassword" class="control-label">{{i18n .Lang "confirm_password"}}</label> <label for="ConfirmedPassword" class="control-label">{{i18n .Lang "confirm_password"}}</label>
<p style="display:inline; color: red; font-size: 12pt;">*</p> <p style="display:inline; color: red; font-size: 12pt;">*</p>
<input type="password" class="form-control" id="ConfirmedPassword"> <input type="password" class="form-control" id="ConfirmedPassword">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<h6>{{i18n .Lang "password_description"}}</h6> <h6>{{i18n .Lang "password_description"}}</h6>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="Comment" class="control-label">{{i18n .Lang "note_to_the_admin"}}</label> <label for="Comment" class="control-label">{{i18n .Lang "note_to_the_admin"}}</label>
<input type="text" class="form-control" id="Comment"> <input type="text" class="form-control" id="Comment">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<div class="text-center"> <div class="text-center">
<button type="button" class="btn btn-default" id="btnPageSignUp"> <button type="button" class="btn btn-default" id="btnPageSignUp">
{{ if eq .IsAdmin true }} {{ if eq .IsAdmin true }}
{{i18n .Lang "add_user" }} {{i18n .Lang "add_user" }}
{{ else }} {{ else }}
{{i18n .Lang "sign_up"}} {{i18n .Lang "sign_up"}}
{{ end }} {{ end }}
</button> </button>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
<div class="col-sm-4"></div> <div class="col-sm-4"></div>

View File

@ -14,8 +14,8 @@
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<body> <body>
<p>{{.Hint}}:</p> <p>{{.Hint}}:</p>
<a href="{{.URL}}/resetPassword?reset_uuid={{.UUID}}">{{.URL}}/resetPassword?reset_uuid={{.UUID}}</a> <a href="{{.URL}}/resetPassword?reset_uuid={{.UUID}}">{{.URL}}/resetPassword?reset_uuid={{.UUID}}</a>
</body> </body>
</html> </html>

View File

@ -17,27 +17,27 @@
<div class="col-sm-4"></div> <div class="col-sm-4"></div>
<div class="col-sm-4"> <div class="col-sm-4">
<div class="page-header"> <div class="page-header">
<h1>{{i18n .Lang "title_reset_password"}}</h1> <h1>{{i18n .Lang "title_reset_password"}}</h1>
</div> </div>
<form class="form"> <form class="form">
<div class="alert alert-danger" role="alert" id="divErrMsg"></div> <div class="alert alert-danger" role="alert" id="divErrMsg"></div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="Password" class="control-label">{{i18n .Lang "password"}}</label> <label for="Password" class="control-label">{{i18n .Lang "password"}}</label>
<input type="password" class="form-control" id="Password"> <input type="password" class="form-control" id="Password">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<h6>{{i18n .Lang "password_description"}}</h6> <h6>{{i18n .Lang "password_description"}}</h6>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<label for="ConfirmedPassword" class="control-label">{{i18n .Lang "confirm_password"}}</label> <label for="ConfirmedPassword" class="control-label">{{i18n .Lang "confirm_password"}}</label>
<input type="password" class="form-control" id="ConfirmedPassword"> <input type="password" class="form-control" id="ConfirmedPassword">
<span class="glyphicon form-control-feedback" aria-hidden="true"></span> <span class="glyphicon form-control-feedback" aria-hidden="true"></span>
<h6>{{i18n .Lang "password_description"}}</h6> <h6>{{i18n .Lang "password_description"}}</h6>
</div> </div>
<div class="form-group has-feedback"> <div class="form-group has-feedback">
<div class="text-center"> <div class="text-center">
<button type="button" class="btn btn-default" id="btnSubmit">{{i18n .Lang "button_submit"}}</button> <button type="button" class="btn btn-default" id="btnSubmit">{{i18n .Lang "button_submit"}}</button>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
<div class="col-sm-4"></div> <div class="col-sm-4"></div>

View File

@ -18,15 +18,15 @@
<li><a href="/">{{i18n .Lang "home"}}</a></li> <li><a href="/">{{i18n .Lang "home"}}</a></li>
<li>{{i18n .Lang "search"}}</li> <li>{{i18n .Lang "search"}}</li>
</ol> </ol>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading" id="panelCommonSearchProjectsHeader">{{i18n .Lang "projects"}}</div> <div class="panel-heading" id="panelCommonSearchProjectsHeader">{{i18n .Lang "projects"}}</div>
<div class="panel-body" id="panelCommonSearchProjectsBody"> <div class="panel-body" id="panelCommonSearchProjectsBody">
</div> </div>
</div> </div>
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading" id="panelCommonSearchRepositoriesHeader">{{i18n .Lang "repositories"}}</div> <div class="panel-heading" id="panelCommonSearchRepositoriesHeader">{{i18n .Lang "repositories"}}</div>
<div class="panel-body" id="panelCommonSearchRepositoriesBody"> <div class="panel-body" id="panelCommonSearchRepositoriesBody">
</div> </div>
</div> </div>
</div> </div>
<script src="static/resources/js/search.js"></script> <script src="static/resources/js/search.js"></script>

View File

@ -14,15 +14,15 @@
--> -->
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
{{.HeaderInc}} {{.HeaderInc}}
<title>{{.PageTitle}}</title> <title>{{.PageTitle}}</title>
</head> </head>
<body> <body>
{{.HeaderContent}} {{.HeaderContent}}
{{.BodyContent}} {{.BodyContent}}
{{.FooterInc}} {{.FooterInc}}
{{.ModalDialog}} {{.ModalDialog}}
{{.FootContent}} {{.FootContent}}
</body> </body>
</html> </html>

View File

@ -13,11 +13,11 @@
limitations under the License. limitations under the License.
--> -->
<footer class="footer"> <footer class="footer">
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-md-5 col-md-offset-4"> <div class="col-md-5 col-md-offset-4">
<p class="text-muted">{{i18n .Lang "copyright"}} © 2015-2016 VMware, Inc. {{i18n .Lang "all_rights_reserved"}}</p> <p class="text-muted">{{i18n .Lang "copyright"}} © 2015-2016 VMware, Inc. {{i18n .Lang "all_rights_reserved"}}</p>
</div> </div>
</div> </div>
</div> </div>
</footer> </footer>

View File

@ -11,79 +11,81 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
--> -->
<input type="hidden" id="currentLanguage" value="{{.Lang}}"> <input type="hidden" id="currentLanguage" value="{{.Lang}}">
<input type="hidden" id="isAdmin" value="{{.IsAdmin}}"> <input type="hidden" id="isAdmin" value="{{.IsAdmin}}">
<nav class="navbar navbar-default" role="navigation" style="margin-bottom: 0;"> <nav class="navbar navbar-default" role="navigation" style="margin-bottom: 0;">
<div class="navbar-header"> <div class="navbar-header">
<button aria-controls="navbar" aria-expanded="false" data-target="#navbar" data-toggle="collapse" class="navbar-toggle collapsed" type="button"> <button aria-controls="navbar" aria-expanded="false" data-target="#navbar" data-toggle="collapse" class="navbar-toggle collapsed" type="button">
<span class="sr-only">Toggle navigation</span> <span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
<span class="icon-bar"></span> <span class="icon-bar"></span>
</button> </button>
<a class="navbar-brand" href="/"><img src="static/resources/image/Harbor_Logo_rec.png" height="40px" width="80px"/></a> <a class="navbar-brand" href="/"><img src="static/resources/image/Harbor_Logo_rec.png" height="40px" width="80px"/></a>
</div> </div>
<div id="navbar" class="navbar-collapse collapse"> <div id="navbar" class="navbar-collapse collapse">
<form class="navbar-form navbar-right"> <form class="navbar-form navbar-right">
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-globe"></span> <span class="glyphicon glyphicon-globe"></span>
{{i18n .Lang "language"}} {{i18n .Lang "language"}}
<span class="caret"></span></a> <span class="caret"></span></a>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li><a href="/language?lang=en-US">{{i18n .Lang "language_en-US"}}</a></li> <li><a href="/language?lang=en-US">{{i18n .Lang "language_en-US"}}</a></li>
<li><a href="/language?lang=zh-CN">{{i18n .Lang "language_zh-CN"}}</a></li> <li><a href="/language?lang=zh-CN">{{i18n .Lang "language_zh-CN"}}</a></li>
<li><a href="/language?lang=de-DE">{{i18n .Lang "language_de-DE"}}</a></li> <li><a href="/language?lang=de-DE">{{i18n .Lang "language_de-DE"}}</a></li>
<li><a href="/language?lang=ru-RU">{{i18n .Lang "language_ru-RU"}}</a></li> <li><a href="/language?lang=ru-RU">{{i18n .Lang "language_ru-RU"}}</a></li>
</ul>
</li>
</ul> </ul>
</li> </div>
</ul>
</div> <div class="input-group" >
<span class="input-group-addon"><span class="input-group glyphicon glyphicon-search"></span></span>
<div class="input-group" > <input type="text" class="form-control" id="txtCommonSearch" size="50" placeholder="{{i18n .Lang "search_placeholder"}}">
<span class="input-group-addon"><span class="input-group glyphicon glyphicon-search"></span></span> </div>
<input type="text" class="form-control" id="txtCommonSearch" size="50" placeholder="{{i18n .Lang "search_placeholder"}}"> </div>
</div> {{ if .Username }}
</div> <div class="input-group">
{{ if .Username }} <ul class="nav navbar-nav">
<div class="input-group"> <li class="dropdown">
<ul class="nav navbar-nav"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-user"></span> {{.Username}}<span class="caret"></span></a>
<li class="dropdown"> <ul class="dropdown-menu">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><span class="glyphicon glyphicon-user"></span> {{.Username}}<span class="caret"></span></a> {{ if eq .AuthMode "db_auth" }}
<ul class="dropdown-menu"> <li><a id="aChangePassword" href="/changePassword" target="_blank"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{{i18n .Lang "change_password"}}</a></li>
{{ if eq .AuthMode "db_auth" }} <li role="separator" class="divider"></li>
<li><a id="aChangePassword" href="/changePassword" target="_blank"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{{i18n .Lang "change_password"}}</a></li> {{ end }}
<li role="separator" class="divider"></li> {{ if eq .IsLdapAdminUser true }}
{{ end }} <li><a id="aChangePassword" href="/changePassword" target="_blank"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{{i18n .Lang "change_password"}}</a></li>
{{ if eq .IsLdapAdminUser true }} <li role="separator" class="divider"></li>
<li><a id="aChangePassword" href="/changePassword" target="_blank"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{{i18n .Lang "change_password"}}</a></li> {{ end }}
<li role="separator" class="divider"></li> {{ if eq .AuthMode "db_auth" }}
{{ end }} {{ if eq .IsAdmin true }}
{{ if eq .AuthMode "db_auth" }} <li><a id="aAddUser" href="/addUser" target="_blank"><span class="glyphicon glyphicon-plus"></span>&nbsp;&nbsp;{{i18n .Lang "add_user"}}</a></li>
{{ if eq .IsAdmin true }} {{ end }}
<li><a id="aAddUser" href="/addUser" target="_blank"><span class="glyphicon glyphicon-plus"></span>&nbsp;&nbsp;{{i18n .Lang "add_user"}}</a></li> {{ end}}
{{ end }} <li><a id="aLogout" href="#"><span class="glyphicon glyphicon-log-in"></span>&nbsp;&nbsp;{{i18n .Lang "log_out"}}</a></li>
{{ end}} </ul>
<li><a id="aLogout" href="#"><span class="glyphicon glyphicon-log-in"></span>&nbsp;&nbsp;{{i18n .Lang "log_out"}}</a></li> </li>
</ul> </ul>
</li> </div>
</ul> {{ else if eq .AuthMode "db_auth" }}
</div> <div class="input-group">
{{ else if eq .AuthMode "db_auth" }} &nbsp;<button type="button" class="btn btn-default" id="btnSignIn">{{i18n .Lang "sign_in"}}</button>
<div class="input-group"> {{ if eq .SelfRegistration true }}
&nbsp;<button type="button" class="btn btn-default" id="btnSignIn">{{i18n .Lang "sign_in"}}</button> &nbsp;<button type="button" class="btn btn-success" id="btnSignUp">{{i18n .Lang "sign_up"}}</button>
{{ if eq .SelfRegistration true }} {{ end }}
&nbsp;<button type="button" class="btn btn-success" id="btnSignUp">{{i18n .Lang "sign_up"}}</button> </div>
{{ else }}
<div class="input-group">
&nbsp;<button type="button" class="btn btn-default" id="btnSignIn">{{i18n .Lang "sign_in"}}</button>
</div>
{{ end }} {{ end }}
</div> </form>
{{ else }} </div>
<div class="input-group"> </nav>
&nbsp;<button type="button" class="btn btn-default" id="btnSignIn">{{i18n .Lang "sign_in"}}</button>
</div>
{{ end }}
</form>
</div>
</nav>

View File

@ -13,26 +13,26 @@
limitations under the License. limitations under the License.
--> -->
<style> <style>
.center { .center {
margin-left: auto; margin-left: auto;
margin-right: auto; margin-right: auto;
top: 10%; top: 10%;
} }
</style> </style>
<!-- Modal --> <!-- Modal -->
<div class="center modal fade" id="dlgModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true"> <div class="center modal fade" id="dlgModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button> <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="dlgLabel"></h4> <h4 class="modal-title" id="dlgLabel"></h4>
</div> </div>
<div class="modal-body" id="dlgBody"> <div class="modal-body" id="dlgBody">
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-primary" id="dlgConfirm" data-dismiss="modal">{{i18n .Lang "dlg_button_ok"}}</button> <button type="button" class="btn btn-primary" id="dlgConfirm" data-dismiss="modal">{{i18n .Lang "dlg_button_ok"}}</button>
<button type="button" class="btn btn-primary" id="dlgCancel" data-dismiss="modal" style="display: none;">{{i18n .Lang "dlg_button_cancel"}}</button> <button type="button" class="btn btn-primary" id="dlgCancel" data-dismiss="modal" style="display: none;">{{i18n .Lang "dlg_button_cancel"}}</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -13,28 +13,28 @@
limitations under the License. limitations under the License.
--> -->
<div class="container"> <div class="container">
<form class="form-signin form-horizontal"> <form class="form-signin form-horizontal">
<div class="form-group"> <div class="form-group">
<label for="Principal" class="col-md-4 control-label">{{i18n .Lang "username_email"}}</label> <label for="Principal" class="col-md-4 control-label">{{i18n .Lang "username_email"}}</label>
<div class="col-md-8"> <div class="col-md-8">
<input type="text" id="Principal" class="form-control" placeholder="{{i18n .Lang "username_email"}}"> <input type="text" id="Principal" class="form-control" placeholder="{{i18n .Lang "username_email"}}">
</div>
</div> </div>
</div> <div class="form-group">
<div class="form-group"> <label for="Password" class="col-md-4 control-label">{{i18n .Lang "password"}}</label>
<label for="Password" class="col-md-4 control-label">{{i18n .Lang "password"}}</label> <div class="col-md-8">
<div class="col-md-8"> <input type="password" id="Password" class="form-control" placeholder="{{i18n .Lang "password"}}">
<input type="password" id="Password" class="form-control" placeholder="{{i18n .Lang "password"}}"> </div>
</div> </div>
</div> <button class="btn btn-lg btn-primary btn-block" type="button" id="btnPageSignIn">{{i18n .Lang "sign_in"}}</button>
<button class="btn btn-lg btn-primary btn-block" type="button" id="btnPageSignIn">{{i18n .Lang "sign_in"}}</button> {{ if eq .AuthMode "db_auth" }}
{{ if eq .AuthMode "db_auth" }} <div class="form-group">
<div class="form-group"> <div class="col-md-12">
<div class="col-md-12"> <button type="button" class="btn btn-link pull-right" id="btnForgot">{{i18n .Lang "forgot_password"}}</button>
<button type="button" class="btn btn-link pull-right" id="btnForgot">{{i18n .Lang "forgot_password"}}</button> </div>
</div> </div>
</div> {{ end }}
{{ end }} </form>
</form>
</div> </div>
<link href="static/resources/css/sign-in.css" type="text/css" rel="stylesheet"> <link href="static/resources/css/sign-in.css" type="text/css" rel="stylesheet">
<script src="static/resources/js/sign-in.js"></script> <script src="static/resources/js/sign-in.js"></script>