Merge remote-tracking branch 'upstream/master'

merge code for develop 20160607
This commit is contained in:
yhua 2016-06-07 15:02:45 +08:00
commit 2c9ff58a81
32 changed files with 1285 additions and 1232 deletions

View File

@ -33,7 +33,7 @@ type ProjectMemberAPI struct {
}
type memberReq struct {
Username string `json:"user_name"`
Username string `json:"username"`
UserID int `json:"user_id"`
Roles []int `json:"roles"`
}
@ -104,7 +104,7 @@ func (pma *ProjectMemberAPI) Get() {
log.Errorf("Error occurred in GetUser, error: %v", err)
pma.CustomAbort(http.StatusInternalServerError, "Internal error.")
}
result["user_name"] = user.Username
result["username"] = user.Username
result["user_id"] = pma.memberID
result["roles"] = roleList
pma.Data["json"] = result

View File

@ -4,7 +4,7 @@ swagger: '2.0'
info:
title: Harbor API
description: These APIs provide services for manipulating Harbor project.
version: "0.1.0"
version: "0.1.1"
# the domain of the service
host: localhost
# array of all schemes that your API supports
@ -167,7 +167,7 @@ paths:
- name: access_log
in: body
schema:
$ref: '#/definitions/AccessLog'
$ref: '#/definitions/AccessLogFilter'
description: Search results of access logs.
tags:
- Products
@ -204,7 +204,7 @@ paths:
schema:
type: array
items:
$ref: '#/definitions/Role'
$ref: '#/definitions/User'
400:
description: Illegal format of provided ID value.
401:
@ -517,7 +517,7 @@ paths:
schema:
type: array
items:
$ref: '#/definitions/Repository'
type: string
400:
description: Invalid project ID.
403:
@ -605,12 +605,41 @@ definitions:
description: Search results of the projects that matched the filter keywords.
type: array
items:
$ref: '#/definitions/Project'
$ref: '#/definitions/SearchProject'
repositories:
description: Search results of the repositories that matched the filter keywords.
type: array
items:
$ref: '#/definitions/Repository'
$ref: '#/definitions/SearchRepository'
SearchProject:
type: object
properties:
id:
type: integer
format: int64
description: The ID of project
name:
type: string
description: The name of the project
public:
type: integer
format: int
description: The flag to indicate the publicity of the project (1 is public, 0 is non-public)
SearchRepository:
type: object
properties:
repository_name:
type: string
description: The name of the repository
project_name:
type: string
description: The name of the project that the repository belongs to
project_id:
type: integer
description: The ID of the project that the repository belongs to
project_public:
type: integer
description: The flag to indicate the publicity of the project that the repository belongs to (1 is public, 0 is not)
Project:
type: object
properties:
@ -622,30 +651,39 @@ definitions:
type: integer
format: int32
description: The owner ID of the project always means the creator of the project.
project_name:
name:
type: string
description: The name of the project.
creation_time:
type: string
description: The creation time of the project.
update_time:
type: string
description: The update time of the project.
deleted:
type: integer
format: int32
description: A deletion mark of the project.
description: A deletion mark of the project (1 means it's deleted, 0 is not)
user_id:
type: integer
format: int32
description: A relation field to the user table.
owner_name:
type: string
description: The owner name of tthe project always means the creator of the project.
description: The owner name of the project.
public:
type: boolean
format: boolean
description: The public status of the project.
togglable:
type: boolean
description: Correspond to the UI about showing the public status of the project.
description: Correspond to the UI about whether the project's publicity is updatable (for UI)
current_user_role_id:
type: integer
description: The role ID of the current user who triggered the API (for UI)
repo_count:
type: integer
description: The number of the repositories under this project.
Repository:
type: object
properties:
@ -680,6 +718,7 @@ definitions:
user_id:
type: integer
format: int32
description: The ID of the user.
username:
type: string
email:
@ -702,7 +741,7 @@ definitions:
new_password:
type: string
description: New password for marking as to be updated.
AccessLog:
AccessLogFilter:
type: object
properties:
username:
@ -711,14 +750,32 @@ definitions:
keywords:
type: string
description: Operation name specified when project created.
beginTimestamp:
begin_timestamp:
type: integer
format: int32
format: int64
description: Begin timestamp for querying access logs.
endTimestamp:
end_timestamp:
type: integer
format: int32
format: int64
description: End timestamp for querying accessl logs.
AccessLog:
type: object
properties:
log_id:
type: integer
description: The ID of the log entry.
repo_name:
type: string
description: Name of the repository in this log entry.
repo_tag:
type: string
description: Tag of the repository in this log entry.
operation:
type: string
description: The operation against the repository in this log entry.
op_time:
type: time
description: The time when this operation is triggered.
Role:
type: object
properties:
@ -741,6 +798,6 @@ definitions:
type: integer
format: int32
description: Role ID for updating project role member.
user_name:
username:
type: string
description: Username relevant to a project role member.

View File

@ -21,19 +21,19 @@ import (
// AccessLog holds information about logs which are used to record the actions that user take to the resourses.
type AccessLog struct {
LogID int `orm:"column(log_id)" json:"LogId"`
UserID int `orm:"column(user_id)" json:"UserId"`
ProjectID int64 `orm:"column(project_id)" json:"ProjectId"`
RepoName string `orm:"column(repo_name)"`
RepoTag string `orm:"column(repo_tag)"`
GUID string `orm:"column(GUID)" json:"Guid"`
Operation string `orm:"column(operation)"`
OpTime time.Time `orm:"column(op_time)"`
Username string
Keywords string
LogID int `orm:"column(log_id)" json:"log_id"`
UserID int `orm:"column(user_id)" json:"user_id"`
ProjectID int64 `orm:"column(project_id)" json:"project_id"`
RepoName string `orm:"column(repo_name)" json:"repo_name"`
RepoTag string `orm:"column(repo_tag)" json:"repo_tag"`
GUID string `orm:"column(GUID)" json:"guid"`
Operation string `orm:"column(operation)" json:"operation"`
OpTime time.Time `orm:"column(op_time)" json:"op_time"`
Username string `json:"username"`
Keywords string `json:"keywords"`
BeginTime time.Time
BeginTimestamp int64
BeginTimestamp int64 `json:"begin_timestamp"`
EndTime time.Time
EndTimestamp int64
EndTimestamp int64 `json:"end_timestamp"`
}

View File

@ -21,19 +21,19 @@ import (
// Project holds the details of a project.
type Project struct {
ProjectID int64 `orm:"column(project_id)" json:"ProjectId"`
OwnerID int `orm:"column(owner_id)" json:"OwnerId"`
Name string `orm:"column(name)"`
CreationTime time.Time `orm:"column(creation_time)"`
CreationTimeStr string
Deleted int `orm:"column(deleted)"`
UserID int `json:"UserId"`
OwnerName string
Public int `orm:"column(public)"`
ProjectID int64 `orm:"column(project_id)" json:"project_id"`
OwnerID int `orm:"column(owner_id)" json:"owner_id"`
Name string `orm:"column(name)" json:"name"`
CreationTime time.Time `orm:"column(creation_time)" json:"creation_time"`
CreationTimeStr string `json:"creation_time_str"`
Deleted int `orm:"column(deleted)" json:"deleted"`
//UserID int `json:"UserId"`
OwnerName string `json:"owner_name"`
Public int `orm:"column(public)" json:"public"`
//This field does not have correspondent column in DB, this is just for UI to disable button
Togglable bool
UpdateTime time.Time `orm:"update_time" json:"update_time"`
Role int `json:"role_id"`
Role int `json:"current_user_role_id"`
RepoCount int `json:"repo_count"`
}

View File

@ -21,18 +21,18 @@ import (
// User holds the details of a user.
type User struct {
UserID int `orm:"column(user_id)" json:"UserId"`
Username string `orm:"column(username)" json:"username"`
Email string `orm:"column(email)" json:"email"`
Password string `orm:"column(password)" json:"password"`
Realname string `orm:"column(realname)" json:"realname"`
Comment string `orm:"column(comment)" json:"comment"`
Deleted int `orm:"column(deleted)"`
Rolename string
RoleID int `json:"RoleId"`
RoleList []Role
HasAdminRole int `orm:"column(sysadmin_flag)"`
ResetUUID string `orm:"column(reset_uuid)" json:"ResetUuid"`
UserID int `orm:"column(user_id)" json:"user_id"`
Username string `orm:"column(username)" json:"username"`
Email string `orm:"column(email)" json:"email"`
Password string `orm:"column(password)" json:"password"`
Realname string `orm:"column(realname)" json:"realname"`
Comment string `orm:"column(comment)" json:"comment"`
Deleted int `orm:"column(deleted)" json:"deleted"`
Rolename string `json:"role_name"`
RoleID int `json:"role_id"`
// RoleList []Role `json:"role_list"`
HasAdminRole int `orm:"column(sysadmin_flag)" json:"has_admin_role"`
ResetUUID string `orm:"column(reset_uuid)" json:"reset_uuid"`
Salt string `orm:"column(salt)"`
CreationTime time.Time `orm:"creation_time" json:"creation_time"`

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -23,461 +23,451 @@ jQuery(function(){
if(jqXhr.status == 403){
return false;
}
}
}
}
}).exec()
).then(function(){
noNeedToLoginCallback();
needToLoginCallback();
}).fail(function(){
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){
).then(function(){
noNeedToLoginCallback();
needToLoginCallback();
}).fail(function(){
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){
$("#divErrMsg").hide();
new AjaxUtil({
url: "/api/repositories?project_id=" + $("#projectId").val() + "&q=" + repoName,
type: "get",
success: function(data, status, xhr){
if(xhr && xhr.status == 200){
$("#accordionRepo").children().remove();
if(data == null){
$("#divErrMsg").show();
$("#divErrMsg center").html(i18n.getMessage("no_repo_exists"));
return;
}
$.each(data, function(i, e){
var targetId = e.replace(/\//g, "------").replace(/\./g, "---");
var row = '<div class="panel panel-default" targetId="' + targetId + '">' +
new AjaxUtil({
url: "/api/repositories?project_id=" + $("#projectId").val() + "&q=" + repoName,
type: "get",
success: function(data, status, xhr){
if(xhr && xhr.status == 200){
$("#accordionRepo").children().remove();
if(data == null){
$("#divErrMsg").show();
$("#divErrMsg center").html(i18n.getMessage("no_repo_exists"));
return;
}
$.each(data, function(i, e){
var targetId = e.replace(/\//g, "------");
var row = '<div class="panel panel-default" targetId="' + targetId + '">' +
'<div class="panel-heading" role="tab" id="heading' + i + '"+ >' +
'<h4 class="panel-title">' +
'<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>' +
'</a>' +
'</h4>' +
'</div>' +
'<div id="collapse' + i + '" targetId="' + targetId + '" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading' + i + '">' +
'<div class="panel-body" id="' + targetId + '">' +
'<div class="table-responsive" style="height: auto;">' +
'<table class="table table-striped table-bordered table-condensed">' +
'<thead>' +
'<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("pull_command") + ' </th>' +
'</tr>' +
'</thead>' +
'<tbody>' +
'</tbody>' +
'</table>'
'</div>' +
'</div>' +
'</div>' +
'</div>';
$("#accordionRepo").append(row);
});
if(repoName != ""){
$("#txtRepoName").val(repoName);
$("#accordionRepo #heading0 a").trigger("click");
'<h4 class="panel-title">' +
'<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>' +
'</a>' +
'</h4>' +
'</div>' +
'<div id="collapse' + i + '" targetId="' + targetId + '" class="panel-collapse collapse" role="tabpanel" aria-labelledby="heading' + i + '">' +
'<div class="panel-body" id="' + targetId + '">' +
'<div class="table-responsive" style="height: auto;">' +
'<table class="table table-striped table-bordered table-condensed">' +
'<thead>' +
'<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("pull_command") + ' </th>' +
'</tr>' +
'</thead>' +
'<tbody>' +
'</tbody>' +
'</table>'
'</div>' +
'</div>' +
'</div>' +
'</div>';
$("#accordionRepo").append(row);
});
if(repoName != ""){
$("#txtRepoName").val(repoName);
$("#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(/[-]{6}/g, "/").replace(/[-]{3}/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();
}
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);
$("#btnSearchRepo").on("click", function(){
listRepo($.trim($("#txtRepoName").val()));
});
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(),
$('#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, "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.getUTCDate(),
t.getUTCHours(),
t.getUTCMinutes(),
t.getUTCSeconds());
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);
return utcTime.getTime() / 1000;
}
}
}).exec();
});
$("#spnFilterOption input[name=chkAll]").on("click", function(){
$("#spnFilterOption input[name=chkOperation]").prop("checked", $(this).prop("checked"));
});
$("#spnFilterOption input[name=chkOperation]").on("click", function(){
if(!$(this).prop("checked")){
$("#spnFilterOption input[name=chkAll]").prop("checked", false);
}
var selectedAll = true;
$("#spnFilterOption input[name=chkOperation]").each(function(i, e){
if(!$(e).prop("checked")){
selectedAll = false;
}
});
if(selectedAll){
$("#spnFilterOption input[name=chkAll]").prop("checked", true);
}
});
function getKeyWords(){
var keywords = "";
var checkedItemList=$("#spnFilterOption input[name=chkOperation]:checked");
var keywords = [];
$.each(checkedItemList, function(i, e){
var itemValue = $(e).val();
if(itemValue == "others" && $.trim($("#txtOthers").val()).length > 0){
keywords.push($("#txtOthers").val());
}else{
keywords.push($(e).val());
}
});
return keywords.join("/");
}
$('#datetimepicker1').datetimepicker({
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");
}
$("#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" : Number(projectId), "keywords" : getKeyWords() , "begin_timestamp" : beginTimestamp, "end_timestamp" : endTimestamp},
type: "post",
success: function(data, status, xhr){
if(xhr && xhr.status == 200){
searchAccessLogCallback(data);
}
}
}).exec();
});
$("#spnFilterOption input[name=chkAll]").on("click", function(){
$("#spnFilterOption input[name=chkOperation]").prop("checked", $(this).prop("checked"));
});
$("#spnFilterOption input[name=chkOperation]").on("click", function(){
if(!$(this).prop("checked")){
$("#spnFilterOption input[name=chkAll]").prop("checked", false);
}
var selectedAll = true;
$("#spnFilterOption input[name=chkOperation]").each(function(i, e){
if(!$(e).prop("checked")){
selectedAll = false;
}
});
if(selectedAll){
$("#spnFilterOption input[name=chkAll]").prop("checked", true);
}
});
function getKeyWords(){
var keywords = "";
var checkedItemList=$("#spnFilterOption input[name=chkOperation]:checked");
var keywords = [];
$.each(checkedItemList, function(i, e){
var itemValue = $(e).val();
if(itemValue == "others" && $.trim($("#txtOthers").val()).length > 0){
keywords.push($("#txtOthers").val());
}else{
keywords.push($(e).val());
}
});
return keywords.join("/");
}
$('#datetimepicker1').datetimepicker({
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){
if(jqXhr.status == 401)
return false;
return false;
}
}).exec();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,25 +13,25 @@
limitations under the License.
-->
<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
<div class="container">
<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>
</div>
</div>
<div class="jumbotron">
<div class="container">
<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>
</div>
</div>
<div class="container">
<!-- Example row of columns -->
<div class="row">
<div class="col-md-12">
<p>{{i18n .Lang "index_desc"}}</p>
<p>{{i18n .Lang "index_desc_0"}}</p>
<p>{{i18n .Lang "index_desc_1"}}</p>
<p>{{i18n .Lang "index_desc_2"}}</p>
<p>{{i18n .Lang "index_desc_3"}}</p>
<p>{{i18n .Lang "index_desc_4"}}</p>
<p>{{i18n .Lang "index_desc_5"}}</p>
</div>
</div>
</div> <!-- /container -->
<div class="container">
<!-- Example row of columns -->
<div class="row">
<div class="col-md-12">
<p>{{i18n .Lang "index_desc"}}</p>
<p>{{i18n .Lang "index_desc_0"}}</p>
<p>{{i18n .Lang "index_desc_1"}}</p>
<p>{{i18n .Lang "index_desc_2"}}</p>
<p>{{i18n .Lang "index_desc_3"}}</p>
<p>{{i18n .Lang "index_desc_4"}}</p>
<p>{{i18n .Lang "index_desc_5"}}</p>
</div>
</div>
</div> <!-- /container -->
<script src="static/resources/js/login.js"></script>

View File

@ -18,7 +18,7 @@
<li>{{.ProjectName}}</li>
</ol>
<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 row="tabpanel">
<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>
</ul>
</div>
<div class="col-md-10">
<input type="hidden" id="projectId" value="{{.ProjectId}}">
<input type="hidden" id="projectName" value="{{.ProjectName}}">
<input type="hidden" id="userId" value="{{.UserId}}">
<input type="hidden" id="ownerId" value="{{.OwnerId}}">
<input type="hidden" id="roleId" value="{{.RoleId}}">
<input type="hidden" id="harborRegUrl" value="{{.HarborRegUrl}}">
<input type="hidden" id="public" value="{{.Public}}">
<input type="hidden" id="repoName" value="{{.RepoName}}">
<!-- tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane" id="tabRepoInfo">
<form class="form-inline">
<div class="form-group">
<label class="sr-only" for="txtRepoName">{{i18n .Lang "repo_name"}}:</label>
<div class="input-group">
<div class="input-group-addon">{{i18n .Lang "repo_name"}}:</div>
<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">
<div class="col-md-10">
<input type="hidden" id="projectId" value="{{.ProjectId}}">
<input type="hidden" id="projectName" value="{{.ProjectName}}">
<input type="hidden" id="userId" value="{{.UserId}}">
<input type="hidden" id="ownerId" value="{{.OwnerId}}">
<input type="hidden" id="roleId" value="{{.RoleId}}">
<input type="hidden" id="harborRegUrl" value="{{.HarborRegUrl}}">
<input type="hidden" id="public" value="{{.Public}}">
<input type="hidden" id="repoName" value="{{.RepoName}}">
<!-- tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane" id="tabRepoInfo">
<form class="form-inline">
<div class="form-group">
<label class="sr-only" for="txtRepoName">{{i18n .Lang "repo_name"}}:</label>
<div class="input-group">
<div class="input-group-addon">{{i18n .Lang "repo_name"}}:</div>
<input type="text" class="form-control" id="txtRepoName">
<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>
</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>
<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-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 role="tabpanel" class="tab-pane" id="tabUserInfo">
<form class="form-inline">
<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-addon">{{i18n .Lang "operation"}}:</div>
<span class="input-group-addon" id="spnFilterOption">
<input type="checkbox" name="chkAll" value="0"> {{i18n .Lang "all"}}
<input type="checkbox" name="chkOperation" value="create"> Create
<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">
<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>
<p></p>
<div class="form-group">
<label for="begindatepicker" class="sr-only">{{i18n .Lang "start_date"}}:</label>
<div class="input-group">
<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 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>
<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>
</div>
<p/>
<div class="collapse" id="collapseAdvance">
<form class="form">
<div class="form-group">
<label for="txtUserName" class="sr-only">{{i18n .Lang "operation"}}:</label>
<div class="input-group">
<div class="input-group-addon">{{i18n .Lang "operation"}}:</div>
<span class="input-group-addon" id="spnFilterOption">
<input type="checkbox" name="chkAll" value="0"> {{i18n .Lang "all"}}
<input type="checkbox" name="chkOperation" value="create"> Create
<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>
</div>
</div>
<p></p>
<div class="form-group">
<label for="begindatepicker" class="sr-only">{{i18n .Lang "start_date"}}:</label>
<div class="input-group">
<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 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 class="modal fade" id="dlgUser" tabindex="-1" role="dialog" aria-labelledby="User" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">

View File

@ -25,24 +25,24 @@
<!-- tab panes -->
<div class="tab-content">
<div role="tabpanel" class="tab-pane" id="tabMyProject" style="margin-top: 15px;">
<form class="form-inline">
<label class="sr-only" for="txtProjectName">{{i18n .Lang "project_name"}}:</label>
<div class="input-group">
<div class="input-group-addon">{{i18n .Lang "project_name"}}:</div>
<input type="text" class="form-control" id="txtSearchProject">
<span class="input-group-btn">
<button id="btnSearch" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button>
</span>
</div>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#dlgAddProject" id="btnAddProject">{{i18n .Lang "add_project"}}</button>
</form>
<form class="form-inline">
<label class="sr-only" for="txtProjectName">{{i18n .Lang "project_name"}}:</label>
<div class="input-group">
<div class="input-group-addon">{{i18n .Lang "project_name"}}:</div>
<input type="text" class="form-control" id="txtSearchProject">
<span class="input-group-btn">
<button id="btnSearch" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button>
</span>
</div>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#dlgAddProject" id="btnAddProject">{{i18n .Lang "add_project"}}</button>
</form>
<div class="table-responsive div-height">
<table id="tblProject" class="table table-hover">
<thead>
<tr>
<th width="35%">{{i18n .Lang "project_name"}}</th>
<th width="45%">{{i18n .Lang "creation_time"}}</th>
<th width="20%">{{i18n .Lang "publicity"}}</th>
<th width="20%">{{i18n .Lang "publicity"}}</th>
</tr>
</thead>
<tbody>
@ -51,65 +51,65 @@
</div>
</div>
<div role="tabpanel" class="tab-pane" id="tabAdminOption" style="visibility: hidden; margin-top: 15px;">
<form class="form-inline">
<label class="sr-only" for="txtProjectName">{{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="btnSearchUsername" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button>
</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>
<form class="form-inline">
<label class="sr-only" for="txtProjectName">{{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="btnSearchUsername" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-search"></span></button>
</span>
</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>
</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>
</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/project.js"></script>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -13,11 +13,11 @@
limitations under the License.
-->
<footer class="footer">
<div class="container">
<div class="row">
<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>
</div>
</div>
</div>
<div class="container">
<div class="row">
<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>
</div>
</div>
</div>
</footer>

View File

@ -11,80 +11,83 @@
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
-->
<input type="hidden" id="currentLanguage" value="{{.Lang}}">
<input type="hidden" id="isAdmin" value="{{.IsAdmin}}">
<nav class="navbar navbar-default" role="navigation" style="margin-bottom: 0;">
<div class="navbar-header">
<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="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<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">
<form class="navbar-form navbar-right">
<div class="form-group">
<div class="input-group">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-globe"></span>
{{i18n .Lang "language"}}
<span class="caret"></span></a>
<ul class="dropdown-menu">
<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=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=ja-JP">{{i18n .Lang "language_ja-JP"}}</a></li>
</ul>
</li>
</ul>
</div>
<div class="input-group" >
<span class="input-group-addon"><span class="input-group glyphicon glyphicon-search"></span></span>
<input type="text" class="form-control" id="txtCommonSearch" size="50" placeholder="{{i18n .Lang "search_placeholder"}}">
</div>
</div>
{{ if .Username }}
<div class="input-group">
<ul class="nav navbar-nav">
<li class="dropdown">
<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>
<ul class="dropdown-menu">
{{ if eq .AuthMode "db_auth" }}
<li><a id="aChangePassword" href="/changePassword" target="_blank"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{{i18n .Lang "change_password"}}</a></li>
<li role="separator" class="divider"></li>
{{ end }}
{{ if eq .IsLdapAdminUser true }}
<li><a id="aChangePassword" href="/changePassword" target="_blank"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{{i18n .Lang "change_password"}}</a></li>
<li role="separator" class="divider"></li>
{{ end }}
{{ if eq .AuthMode "db_auth" }}
{{ if eq .IsAdmin true }}
<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>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-globe"></span>
{{i18n .Lang "language"}}
<span class="caret"></span></a>
<ul class="dropdown-menu">
<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=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=ja-JP">{{i18n .Lang "language_ja-JP"}}</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
{{ else if eq .AuthMode "db_auth" }}
<div class="input-group">
&nbsp;<button type="button" class="btn btn-default" id="btnSignIn">{{i18n .Lang "sign_in"}}</button>
{{ if eq .SelfRegistration true }}
&nbsp;<button type="button" class="btn btn-success" id="btnSignUp">{{i18n .Lang "sign_up"}}</button>
</div>
<div class="input-group" >
<span class="input-group-addon"><span class="input-group glyphicon glyphicon-search"></span></span>
<input type="text" class="form-control" id="txtCommonSearch" size="50" placeholder="{{i18n .Lang "search_placeholder"}}">
</div>
</div>
{{ if .Username }}
<div class="input-group">
<ul class="nav navbar-nav">
<li class="dropdown">
<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>
<ul class="dropdown-menu">
{{ if eq .AuthMode "db_auth" }}
<li><a id="aChangePassword" href="/changePassword" target="_blank"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{{i18n .Lang "change_password"}}</a></li>
<li role="separator" class="divider"></li>
{{ end }}
{{ if eq .IsLdapAdminUser true }}
<li><a id="aChangePassword" href="/changePassword" target="_blank"><span class="glyphicon glyphicon-pencil"></span>&nbsp;&nbsp;{{i18n .Lang "change_password"}}</a></li>
<li role="separator" class="divider"></li>
{{ end }}
{{ if eq .AuthMode "db_auth" }}
{{ if eq .IsAdmin true }}
<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>
</ul>
</li>
</ul>
</div>
{{ else if eq .AuthMode "db_auth" }}
<div class="input-group">
&nbsp;<button type="button" class="btn btn-default" id="btnSignIn">{{i18n .Lang "sign_in"}}</button>
{{ if eq .SelfRegistration true }}
&nbsp;<button type="button" class="btn btn-success" id="btnSignUp">{{i18n .Lang "sign_up"}}</button>
{{ end }}
</div>
{{ else }}
<div class="input-group">
&nbsp;<button type="button" class="btn btn-default" id="btnSignIn">{{i18n .Lang "sign_in"}}</button>
</div>
{{ end }}
</div>
{{ else }}
<div class="input-group">
&nbsp;<button type="button" class="btn btn-default" id="btnSignIn">{{i18n .Lang "sign_in"}}</button>
</div>
{{ end }}
</form>
</div>
</nav>
</form>
</div>
</nav>

View File

@ -13,26 +13,26 @@
limitations under the License.
-->
<style>
.center {
margin-left: auto;
margin-right: auto;
top: 10%;
}
.center {
margin-left: auto;
margin-right: auto;
top: 10%;
}
</style>
<!-- Modal -->
<div class="center modal fade" id="dlgModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<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>
</div>
<div class="modal-body" id="dlgBody">
</div>
<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="dlgCancel" data-dismiss="modal" style="display: none;">{{i18n .Lang "dlg_button_cancel"}}</button>
</div>
</div>
</div>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<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>
</div>
<div class="modal-body" id="dlgBody">
</div>
<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="dlgCancel" data-dismiss="modal" style="display: none;">{{i18n .Lang "dlg_button_cancel"}}</button>
</div>
</div>
</div>
</div>

View File

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