@@ -80,6 +80,18 @@ func GetEmailAddressByID(uid, id int64) (*EmailAddress, error) { | |||||
return email, nil | return email, nil | ||||
} | } | ||||
// GetEmailAddressByIDAndEmail gets a user's email address by ID and email | |||||
func GetEmailAddressByIDAndEmail(uid int64, emailAddr string) (*EmailAddress, error) { | |||||
// User ID is required for security reasons | |||||
email := &EmailAddress{UID: uid, Email: emailAddr} | |||||
if has, err := x.Get(email); err != nil { | |||||
return nil, err | |||||
} else if !has { | |||||
return nil, nil | |||||
} | |||||
return email, nil | |||||
} | |||||
func isEmailActive(e Engine, email string, userID, emailID int64) (bool, error) { | func isEmailActive(e Engine, email string, userID, emailID int64) (bool, error) { | ||||
if len(email) == 0 { | if len(email) == 0 { | ||||
return true, nil | return true, nil | ||||
@@ -590,20 +590,31 @@ func Home(ctx *context.Context) { | |||||
if err == nil && contributors != nil { | if err == nil && contributors != nil { | ||||
var contributorInfos []*ContributorInfo | var contributorInfos []*ContributorInfo | ||||
for _, c := range contributors { | for _, c := range contributors { | ||||
// get user info from committer email | |||||
user, err := models.GetUserByEmail(c.Email) | user, err := models.GetUserByEmail(c.Email) | ||||
if err == nil { | if err == nil { | ||||
// committer is system user, get info through user's primary email | |||||
existedContributorInfo := getContributorInfo(contributorInfos,user.Email) | existedContributorInfo := getContributorInfo(contributorInfos,user.Email) | ||||
if existedContributorInfo != nil { | if existedContributorInfo != nil { | ||||
// existed: same primary email, different committer name | |||||
existedContributorInfo.CommitCnt += c.CommitCnt | existedContributorInfo.CommitCnt += c.CommitCnt | ||||
}else{ | }else{ | ||||
// new committer info | |||||
contributorInfos = append(contributorInfos, &ContributorInfo{ | contributorInfos = append(contributorInfos, &ContributorInfo{ | ||||
user, user.Email,c.CommitCnt, | user, user.Email,c.CommitCnt, | ||||
}) | }) | ||||
} | } | ||||
} else { | } else { | ||||
contributorInfos = append(contributorInfos, &ContributorInfo{ | |||||
nil, c.Email,c.CommitCnt, | |||||
}) | |||||
// committer is not system user | |||||
existedContributorInfo := getContributorInfo(contributorInfos,c.Email) | |||||
if existedContributorInfo != nil { | |||||
// existed: same primary email, different committer name | |||||
existedContributorInfo.CommitCnt += c.CommitCnt | |||||
}else{ | |||||
contributorInfos = append(contributorInfos, &ContributorInfo{ | |||||
nil, c.Email,c.CommitCnt, | |||||
}) | |||||
} | |||||
} | } | ||||
} | } | ||||
ctx.Data["ContributorInfo"] = contributorInfos | ctx.Data["ContributorInfo"] = contributorInfos | ||||
@@ -1266,6 +1266,15 @@ func Activate(ctx *context.Context) { | |||||
log.Error("Error storing session: %v", err) | log.Error("Error storing session: %v", err) | ||||
} | } | ||||
email, err := models.GetEmailAddressByIDAndEmail(user.ID, user.Email) | |||||
if err != nil || email == nil{ | |||||
log.Error("GetEmailAddressByIDAndEmail failed", ctx.Data["MsgID"]) | |||||
} else { | |||||
if err := email.Activate(); err != nil { | |||||
log.Error("Activate failed: %v", err, ctx.Data["MsgID"]) | |||||
} | |||||
} | |||||
ctx.Flash.Success(ctx.Tr("auth.account_activated")) | ctx.Flash.Success(ctx.Tr("auth.account_activated")) | ||||
ctx.Redirect(setting.AppSubURL + "/") | ctx.Redirect(setting.AppSubURL + "/") | ||||
return | return | ||||
@@ -96,6 +96,18 @@ func ProfilePost(ctx *context.Context, form auth.UpdateProfileForm) { | |||||
ctx.User.Location = form.Location | ctx.User.Location = form.Location | ||||
ctx.User.Language = form.Language | ctx.User.Language = form.Language | ||||
ctx.User.Description = form.Description | ctx.User.Description = form.Description | ||||
isUsed, err := models.IsEmailUsed(form.Email) | |||||
if err != nil { | |||||
ctx.ServerError("IsEmailUsed", err) | |||||
return | |||||
} | |||||
if isUsed { | |||||
ctx.Flash.Error(ctx.Tr("form.email_been_used")) | |||||
ctx.Redirect(setting.AppSubURL + "/user/settings") | |||||
return | |||||
} | |||||
if err := models.UpdateUserSetting(ctx.User); err != nil { | if err := models.UpdateUserSetting(ctx.User); err != nil { | ||||
if _, ok := err.(models.ErrEmailAlreadyUsed); ok { | if _, ok := err.(models.ErrEmailAlreadyUsed); ok { | ||||
ctx.Flash.Error(ctx.Tr("form.email_been_used")) | ctx.Flash.Error(ctx.Tr("form.email_been_used")) | ||||
@@ -4,6 +4,48 @@ | |||||
font-size: 1.0em; | font-size: 1.0em; | ||||
margin-bottom: 1.0rem; | margin-bottom: 1.0rem; | ||||
} | } | ||||
#contributorInfo > a:nth-child(n+25){ | |||||
display:none; | |||||
} | |||||
#contributorInfo > a{ | |||||
width: 2.0em; | |||||
float: left; | |||||
margin: .25em; | |||||
} | |||||
#contributorInfo > a.circular{ | |||||
height: 2.0em; | |||||
padding: 0; | |||||
overflow: hidden; | |||||
letter-spacing:1.0em; | |||||
text-indent: 0.6em; | |||||
line-height: 2.0em; | |||||
text-transform:capitalize; | |||||
color: #FFF; | |||||
} | |||||
#contributorInfo > a.circular:nth-child(9n+1){ | |||||
background-color: #4ccdec; | |||||
} | |||||
#contributorInfo > a.circular:nth-child(9n+2){ | |||||
background-color: #e0b265; | |||||
} | |||||
#contributorInfo > a.circular:nth-child(9n+3){ | |||||
background-color: #d884b7; | |||||
} | |||||
#contributorInfo > a.circular:nth-child(9n+4){ | |||||
background-color: #8c6bdc; | |||||
} | |||||
#contributorInfo > a.circular:nth-child(9n+5){ | |||||
background-color: #3cb99f; | |||||
} | |||||
#contributorInfo > a.circular:nth-child(9n+6){ | |||||
background-color: #6995b9; | |||||
} | |||||
#contributorInfo > a.circular:nth-child(9n+7){ | |||||
background-color: #ab91a7; | |||||
} | |||||
#contributorInfo > a.circular:nth-child(9n+8){ | |||||
background-color: #bfd0aa; | |||||
} | |||||
</style> | </style> | ||||
<div class="repository file list"> | <div class="repository file list"> | ||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
@@ -193,17 +235,15 @@ | |||||
<h4 class="ui header"> | <h4 class="ui header"> | ||||
<strong>贡献者 ({{len .ContributorInfo}})</strong> | <strong>贡献者 ({{len .ContributorInfo}})</strong> | ||||
<div class="ui right"> | <div class="ui right"> | ||||
<a class="text grey" href="">全部 {{svg "octicon-chevron-right" 16}}</a> | |||||
<a class="membersmore text grey" href="javascript:;">全部 {{svg "octicon-chevron-right" 16}}</a> | |||||
</div> | </div> | ||||
</h4> | </h4> | ||||
<div class="ui members"> | |||||
<div class="ui members" id="contributorInfo"> | |||||
{{range .ContributorInfo}} | {{range .ContributorInfo}} | ||||
{{/*<img class="ui avatar image" src="{{.UserInfo.RelAvatarLink}}" alt=""/> <a href="{{AppSubUrl}}/{{.UserInfo.Name}}">{{.UserInfo.Name}}</a>*/}} | |||||
{{if .UserInfo}} | {{if .UserInfo}} | ||||
<a href="{{AppSubUrl}}/{{.UserInfo.Name}}"><img class="ui avatar image" src="{{.UserInfo.RelAvatarLink}}" alt=""/></a> | |||||
<a href="{{AppSubUrl}}/{{.UserInfo.Name}}"><img class="ui avatar image" src="{{.UserInfo.RelAvatarLink}}"></a> | |||||
{{else if .Email}} | {{else if .Email}} | ||||
<a href="mailto:{{.Email}}"><img class="ui avatar image" src="{{AvatarLink .Email}}" alt=""/></a> | |||||
<a href="mailto:{{.Email}}" class="circular ui button">{{.Email}}</a> | |||||
{{end}} | {{end}} | ||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
@@ -215,4 +255,12 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<script type="text/javascript"> | |||||
$(document).ready(function(){ | |||||
$(".membersmore").click(function(){ | |||||
$("#contributorInfo > a:nth-child(n+25)").show(); | |||||
}); | |||||
}); | |||||
</script> | |||||
{{template "base/footer" .}} | {{template "base/footer" .}} |