| @@ -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" .}} | ||||