Finish new collaboration page
This commit is contained in:
		
							parent
							
								
									99eeb08419
								
							
						
					
					
						commit
						e8c9bb2c66
					
				|  | @ -96,7 +96,6 @@ func newMacaron() *macaron.Macaron { | |||
| 		Secret:    setting.SecretKey, | ||||
| 		SetCookie: true, | ||||
| 	})) | ||||
| 	m.Use(middleware.Contexter()) | ||||
| 	m.Use(toolbox.Toolboxer(m, toolbox.Options{ | ||||
| 		HealthCheckFuncs: []*toolbox.HealthCheckFuncDesc{ | ||||
| 			&toolbox.HealthCheckFuncDesc{ | ||||
|  | @ -105,6 +104,7 @@ func newMacaron() *macaron.Macaron { | |||
| 			}, | ||||
| 		}, | ||||
| 	})) | ||||
| 	m.Use(middleware.Contexter()) | ||||
| 	return m | ||||
| } | ||||
| 
 | ||||
|  | @ -254,8 +254,7 @@ func runWeb(*cli.Context) { | |||
| 		r.Get("/settings", repo.Settings) | ||||
| 		r.Post("/settings", bindIgnErr(auth.RepoSettingForm{}), repo.SettingsPost) | ||||
| 		m.Group("/settings", func(r *macaron.Router) { | ||||
| 			r.Get("/collaboration", repo.Collaboration) | ||||
| 			r.Post("/collaboration", repo.CollaborationPost) | ||||
| 			r.Route("/collaboration", "GET,POST", repo.SettingsCollaboration) | ||||
| 			r.Get("/hooks", repo.WebHooks) | ||||
| 			r.Get("/hooks/add", repo.WebHooksAdd) | ||||
| 			r.Post("/hooks/add", bindIgnErr(auth.NewWebhookForm{}), repo.WebHooksAddPost) | ||||
|  |  | |||
|  | @ -86,6 +86,7 @@ username_password_incorrect = Username or password is not correct. | |||
| enterred_invalid_repo_name = Please make sure you entered repository name is correct. | ||||
| enterred_invalid_owner_name = Please make sure you entered owner name is correct. | ||||
| enterred_invalid_password = Please make sure you entered passord is correct. | ||||
| user_not_exist = Given user does not exist. | ||||
| 
 | ||||
| invalid_ssh_key = Sorry, we're not able to verify your SSH key: %s | ||||
| auth_failed = Authentication failed: %v | ||||
|  | @ -174,6 +175,9 @@ settings.update_settings_success = Repository options has been successfully upda | |||
| settings.transfer_owner = New Owner | ||||
| settings.make_transfer = Make Transfer | ||||
| settings.confirm_delete = Confirm Deletion | ||||
| settings.add_collaborator = Add New Collaborator | ||||
| settings.add_collaborator_success = New collaborator has been added. | ||||
| settings.remove_collaborator_success = Collaborator has been removed. | ||||
| 
 | ||||
| [org] | ||||
| org_name_holder = Organization Name | ||||
|  |  | |||
|  | @ -86,6 +86,7 @@ username_password_incorrect = 用户名或密码不正确。 | |||
| enterred_invalid_repo_name = 请检查您输入的仓库名称是正确。 | ||||
| enterred_invalid_owner_name = 请检查您输入的新所有者用户名是否正确。 | ||||
| enterred_invalid_password = 请检查您输入的密码是否正确。 | ||||
| user_not_exist = 被操作的用户不存在! | ||||
| 
 | ||||
| invalid_ssh_key = 很抱歉,我们无法验证您输入的 SSH 密钥:%s | ||||
| auth_failed = 授权验证失败:%v | ||||
|  | @ -174,6 +175,9 @@ settings.update_settings_success = 仓库设置更新成功! | |||
| settings.transfer_owner = 新拥有者 | ||||
| settings.make_transfer = 确认转移仓库 | ||||
| settings.confirm_delete = 确认删除仓库 | ||||
| settings.add_collaborator = 增加新的协作者 | ||||
| settings.add_collaborator_success = 成功添加新的协作者! | ||||
| settings.remove_collaborator_success = 被操作的协作者已经被收回权限! | ||||
| 
 | ||||
| [org] | ||||
| org_name_holder = 组织名称 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								gogs.go
								
								
								
								
							
							
						
						
									
										2
									
								
								gogs.go
								
								
								
								
							|  | @ -17,7 +17,7 @@ import ( | |||
| 	"github.com/gogits/gogs/modules/setting" | ||||
| ) | ||||
| 
 | ||||
| const APP_VER = "0.4.7.0806 Alpha" | ||||
| const APP_VER = "0.4.7.0807 Alpha" | ||||
| 
 | ||||
| func init() { | ||||
| 	runtime.GOMAXPROCS(runtime.NumCPU()) | ||||
|  |  | |||
|  | @ -198,6 +198,22 @@ img.avatar-48 { | |||
| .main-wrapper { | ||||
|   padding: 20px 0 40px; | ||||
| } | ||||
| .user-list { | ||||
|   width: auto; | ||||
|   min-width: 180px; | ||||
|   max-width: 300px; | ||||
| } | ||||
| .user-list img { | ||||
|   width: 28px; | ||||
|   height: 28px; | ||||
|   margin-right: 1em; | ||||
|   margin-top: 1px; | ||||
|   vertical-align: middle; | ||||
| } | ||||
| .user-list li { | ||||
|   cursor: pointer; | ||||
|   font-weight: bold; | ||||
| } | ||||
| .markdown { | ||||
|   background-color: white; | ||||
|   font-size: 16px; | ||||
|  | @ -753,9 +769,24 @@ The dashboard page style | |||
|   margin-right: 6px; | ||||
|   font-size: 1.1em; | ||||
| } | ||||
| #dashboard-selection-menu { | ||||
|   width: auto; | ||||
|   max-width: 300px; | ||||
| } | ||||
| #dashboard-selection-menu > .drop-down { | ||||
|   top: 56px; | ||||
| } | ||||
| #dashboard-selection-menu li { | ||||
|   white-space: nowrap; | ||||
| } | ||||
| #dashboard-selection-menu li.checked .octicon { | ||||
|   opacity: 1; | ||||
| } | ||||
| #dashboard-selection-menu li a { | ||||
|   text-overflow: ellipsis; | ||||
|   -o-text-overflow: ellipsis; | ||||
|   overflow: hidden; | ||||
| } | ||||
| #dashboard-switch-menu { | ||||
|   border-bottom-left-radius: .3em; | ||||
|   border-bottom-right-radius: .3em; | ||||
|  | @ -1155,32 +1186,26 @@ The register and sign-in page style | |||
| #repo-create-cancel { | ||||
|   margin-left: 4em; | ||||
| } | ||||
| #dashboard-switch-menu, | ||||
| #repo-create-owner-list { | ||||
|   top: 30px; | ||||
|   left: 0; | ||||
|   width: auto; | ||||
|   max-width: 300px; | ||||
| } | ||||
| #dashboard-switch-menu .octicon, | ||||
| #repo-create-owner-list .octicon { | ||||
|   margin-right: 12px; | ||||
|   opacity: 0; | ||||
| } | ||||
| #dashboard-switch-menu .avatar, | ||||
| #repo-create-owner-list .avatar { | ||||
|   width: 20px; | ||||
|   height: 20px; | ||||
| } | ||||
| #dashboard-switch-menu li, | ||||
| #repo-create-owner-list li { | ||||
|   white-space: nowrap; | ||||
| } | ||||
| #dashboard-switch-menu li.checked .octicon, | ||||
| #repo-create-owner-list li.checked .octicon { | ||||
|   opacity: 1; | ||||
| } | ||||
| #dashboard-switch-menu li a, | ||||
| #repo-create-owner-list li a { | ||||
|   text-overflow: ellipsis; | ||||
|   -o-text-overflow: ellipsis; | ||||
|  | @ -1244,6 +1269,34 @@ The register and sign-in page style | |||
| .repo-setting-zone { | ||||
|   padding: 30px; | ||||
| } | ||||
| #repo-collab-list { | ||||
|   list-style: none; | ||||
|   padding: 10px 0 5px 0; | ||||
| } | ||||
| #repo-collab-list li.collab { | ||||
|   clear: both; | ||||
|   height: 50px; | ||||
|   padding: 0 15px 0 15px; | ||||
| } | ||||
| #repo-collab-list a.member { | ||||
|   color: #444; | ||||
|   height: 50px; | ||||
|   line-height: 50px; | ||||
| } | ||||
| #repo-collab-list a.member:hover { | ||||
|   color: #4183C4; | ||||
| } | ||||
| #repo-collab-list .avatar { | ||||
|   margin-right: 1em; | ||||
|   width: 40px; | ||||
| } | ||||
| #repo-collab-list .remove-collab { | ||||
|   color: #DD4B39; | ||||
| } | ||||
| .repo-user-list-block { | ||||
|   position: relative; | ||||
|   top: 5px; | ||||
| } | ||||
| #setting-wrapper { | ||||
|   padding-bottom: 100px; | ||||
| } | ||||
|  |  | |||
|  | @ -59,7 +59,8 @@ audio:not([controls]) { | |||
|   height: 0; | ||||
| } | ||||
| [hidden], | ||||
| template .hidden { | ||||
| template, | ||||
| .hidden { | ||||
|   display: none; | ||||
| } | ||||
| .opacity { | ||||
|  | @ -72,6 +73,7 @@ a, | |||
| .text-link { | ||||
|   color: #428bca; | ||||
|   text-decoration: none; | ||||
|   cursor: pointer; | ||||
| } | ||||
| a:hover, | ||||
| .text-link:hover { | ||||
|  | @ -604,6 +606,12 @@ ul.menu-down { | |||
|   box-shadow: 0 0 2px #666666; | ||||
|   background-color: #ffffff; | ||||
| } | ||||
| ul.menu-down-show { | ||||
|   position: absolute; | ||||
|   z-index: 99; | ||||
|   box-shadow: 0 0 2px #666666; | ||||
|   background-color: #ffffff; | ||||
| } | ||||
| ul.menu-radius { | ||||
|   border-radius: .3em; | ||||
| } | ||||
|  |  | |||
|  | @ -52,6 +52,59 @@ var Gogs = {}; | |||
|             } | ||||
|         } | ||||
|     }); | ||||
|     $.fn.extend({ | ||||
|         toggleHide: function () { | ||||
|             $(this).addClass("hidden"); | ||||
|         }, | ||||
|         toggleShow: function () { | ||||
|             $(this).removeClass("hidden"); | ||||
|         }, | ||||
|         toggleAjax: function (successCallback, errorCallback) { | ||||
|             var url = $(this).data("ajax"); | ||||
|             var method = $(this).data('ajax-method') || 'get'; | ||||
|             var ajaxName = $(this).data('ajax-name'); | ||||
|             var data = {}; | ||||
| 
 | ||||
|             if (ajaxName.endsWith("preview")) { | ||||
|                 data["mode"] = "gfm"; | ||||
|                 data["context"] = $(this).data('ajax-context'); | ||||
|             } | ||||
| 
 | ||||
|             $('[data-ajax-rel=' + ajaxName + ']').each(function () { | ||||
|                 var field = $(this).data("ajax-field"); | ||||
|                 var t = $(this).data("ajax-val"); | ||||
|                 if (t == "val") { | ||||
|                     data[field] = $(this).val(); | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (t == "txt") { | ||||
|                     data[field] = $(this).text(); | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (t == "html") { | ||||
|                     data[field] = $(this).html(); | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (t == "data") { | ||||
|                     data[field] = $(this).data("ajax-data"); | ||||
|                     return true; | ||||
|                 } | ||||
|                 return true; | ||||
|             }); | ||||
|             console.log("toggleAjax:", method, url, data); | ||||
|             $.ajax({ | ||||
|                 url: url, | ||||
|                 method: method.toUpperCase(), | ||||
|                 data: data, | ||||
|                 error: errorCallback, | ||||
|                 success: function (d) { | ||||
|                     if (successCallback) { | ||||
|                         successCallback(d); | ||||
|                     } | ||||
|                 } | ||||
|             }) | ||||
|         } | ||||
|     }); | ||||
| }(jQuery)); | ||||
| 
 | ||||
| (function ($) { | ||||
|  | @ -145,6 +198,26 @@ var Gogs = {}; | |||
|             } | ||||
|         }).trigger('hashchange'); | ||||
|     }; | ||||
| 
 | ||||
|     // Search users by keyword.
 | ||||
|     Gogs.searchUsers = function (val, $target) { | ||||
|         $.ajax({ | ||||
|             url: '/api/v1/users/search?q=' + val, | ||||
|             dataType: "json", | ||||
|             success: function (json) { | ||||
|                 if (json.ok && json.data.length) { | ||||
|                     var html = ''; | ||||
|                     $.each(json.data, function (i, item) { | ||||
|                         html += '<li><a><img src="' + item.avatar + '">' + item.username + '</a></li>'; | ||||
|                     }); | ||||
|                     $target.html(html); | ||||
|                     $target.toggleShow(); | ||||
|                 } else { | ||||
|                     $target.toggleHide(); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| })(jQuery); | ||||
| 
 | ||||
| function initCore() { | ||||
|  | @ -175,6 +248,7 @@ function initRepoCreate() { | |||
| } | ||||
| 
 | ||||
| function initRepoSetting() { | ||||
|     // Options.
 | ||||
|     // Confirmation of changing repository name.
 | ||||
|     $('#repo-setting-form').submit(function (e) { | ||||
|         var $reponame = $('#repo_name'); | ||||
|  | @ -189,6 +263,27 @@ function initRepoSetting() { | |||
|     $('#delete-button').click(function () { | ||||
|         $('#delete-form').show(); | ||||
|     }); | ||||
| 
 | ||||
|     // Collaboration.
 | ||||
|     $('#repo-collab-list hr:last-child').remove(); | ||||
|     var $ul = $('#repo-collaborator').next().next().find('ul'); | ||||
|     $('#repo-collaborator').on('keyup', function () { | ||||
|         var $this = $(this); | ||||
|         if (!$this.val()) { | ||||
|             $ul.toggleHide(); | ||||
|             return; | ||||
|         } | ||||
|         Gogs.searchUsers($this.val(), $ul); | ||||
|     }).on('focus', function () { | ||||
|         if (!$(this).val()) { | ||||
|             $ul.toggleHide(); | ||||
|         } else { | ||||
|             $ul.toggleShow(); | ||||
|         } | ||||
|     }).next().next().find('ul').on("click", 'li', function () { | ||||
|         $('#repo-collaborator').val($(this).text()); | ||||
|         $ul.toggleHide(); | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| $(document).ready(function () { | ||||
|  |  | |||
|  | @ -215,3 +215,19 @@ clear: both; | |||
| .main-wrapper { | ||||
|     padding: 20px 0 40px; | ||||
| } | ||||
| .user-list { | ||||
|     width: auto; | ||||
|     min-width: 180px; | ||||
|     max-width: 300px; | ||||
|     img { | ||||
|         width: 28px; | ||||
|         height: 28px; | ||||
|         margin-right: 1em; | ||||
|         margin-top: 1px; | ||||
|         vertical-align: middle; | ||||
|     } | ||||
|     li { | ||||
|         cursor: pointer; | ||||
|         font-weight: bold; | ||||
|     } | ||||
| } | ||||
|  | @ -176,9 +176,24 @@ The dashboard page style | |||
| } | ||||
| 
 | ||||
| #dashboard-selection-menu { | ||||
|   > .drop-down { | ||||
|     top: 56px; | ||||
|   } | ||||
|     width: auto; | ||||
|     max-width: 300px; | ||||
|     > .drop-down { | ||||
|         top: 56px; | ||||
|     } | ||||
|     li { | ||||
|         white-space: nowrap; | ||||
|         &.checked { | ||||
|             .octicon { | ||||
|                 opacity: 1; | ||||
|             } | ||||
|         } | ||||
|         a { | ||||
|             text-overflow: ellipsis;  | ||||
|             -o-text-overflow: ellipsis;  | ||||
|             overflow: hidden; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| // the drop-down menu of #dashboard-selection-menu | ||||
|  |  | |||
|  | @ -357,7 +357,6 @@ | |||
|   margin-left: 4em; | ||||
| } | ||||
| 
 | ||||
| #dashboard-switch-menu, | ||||
| #repo-create-owner-list { | ||||
|     top: 30px; | ||||
|     left: 0; | ||||
|  | @ -443,3 +442,31 @@ | |||
| .repo-setting-zone { | ||||
|     padding: 30px; | ||||
| } | ||||
| #repo-collab-list { | ||||
|     list-style: none; | ||||
|     padding: 10px 0 5px 0; | ||||
|     li.collab { | ||||
|         clear: both; | ||||
|         height: 50px; | ||||
|         padding: 0 15px 0 15px; | ||||
|     } | ||||
|     a.member { | ||||
|         color: #444; | ||||
|         height: 50px; | ||||
|         line-height: 50px; | ||||
|         &:hover { | ||||
|             color: #4183C4; | ||||
|         } | ||||
|     } | ||||
|     .avatar { | ||||
|         margin-right: 1em; | ||||
|         width: 40px; | ||||
|     } | ||||
|     .remove-collab { | ||||
|         color: #DD4B39; | ||||
|     } | ||||
| } | ||||
| .repo-user-list-block { | ||||
|     position: relative; | ||||
|     top: 5px; | ||||
| } | ||||
|  | @ -94,12 +94,20 @@ ul.menu-down { | |||
|   } | ||||
| } | ||||
| 
 | ||||
| ul.menu-down { | ||||
|   position: absolute; | ||||
|   display: none; | ||||
|   z-index: 99; | ||||
|   box-shadow: 0 0 2px @menuShadowColor; | ||||
|   background-color: @menuDownBgColor; | ||||
| ul { | ||||
|     &.menu-down { | ||||
|         position: absolute; | ||||
|         display: none; | ||||
|         z-index: 99; | ||||
|         box-shadow: 0 0 2px @menuShadowColor; | ||||
|         background-color: @menuDownBgColor; | ||||
|     } | ||||
|     &.menu-down-show { | ||||
|         position: absolute; | ||||
|         z-index: 99; | ||||
|         box-shadow: 0 0 2px @menuShadowColor; | ||||
|         background-color: @menuDownBgColor; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| ul.menu-radius { | ||||
|  |  | |||
|  | @ -81,17 +81,15 @@ audio:not([controls]) { | |||
| // display hidden elements | ||||
| 
 | ||||
| [hidden], | ||||
| template | ||||
| template, | ||||
| .hidden { | ||||
|   display: none; | ||||
|     display: none; | ||||
| } | ||||
| 
 | ||||
| .opacity { | ||||
|   opacity: 0; | ||||
|     opacity: 0; | ||||
| } | ||||
| 
 | ||||
| .opacity-half { | ||||
|   opacity: .5; | ||||
|     opacity: .5; | ||||
| } | ||||
| 
 | ||||
| // links element | ||||
|  | @ -100,6 +98,7 @@ a, | |||
| .text-link { | ||||
|   color: @linkColor; | ||||
|   text-decoration: none; | ||||
|   cursor: pointer; | ||||
|   &:hover { | ||||
|     color: @linkHoverColor; | ||||
|     text-decoration: none; | ||||
|  |  | |||
|  | @ -28,6 +28,11 @@ func Home(ctx *middleware.Context) { | |||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if setting.OauthService != nil { | ||||
| 		ctx.Data["OauthEnabled"] = true | ||||
| 		ctx.Data["OauthService"] = setting.OauthService | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Data["PageIsHome"] = true | ||||
| 	ctx.HTML(200, HOME) | ||||
| } | ||||
|  |  | |||
|  | @ -22,7 +22,7 @@ import ( | |||
| 
 | ||||
| const ( | ||||
| 	SETTINGS_OPTIONS base.TplName = "repo/settings/options" | ||||
| 	COLLABORATION    base.TplName = "repo/collaboration" | ||||
| 	COLLABORATION    base.TplName = "repo/settings/collaboration" | ||||
| 
 | ||||
| 	HOOKS     base.TplName = "repo/hooks" | ||||
| 	HOOK_ADD  base.TplName = "repo/hook_add" | ||||
|  | @ -134,26 +134,71 @@ func SettingsPost(ctx *middleware.Context, form auth.RepoSettingForm) { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| func Collaboration(ctx *middleware.Context) { | ||||
| func SettingsCollaboration(ctx *middleware.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("repo.settings") | ||||
| 	ctx.Data["PageIsSettingsCollaboration"] = true | ||||
| 
 | ||||
| 	repoLink := strings.TrimPrefix(ctx.Repo.RepoLink, "/") | ||||
| 	ctx.Data["IsRepoToolbarCollaboration"] = true | ||||
| 	ctx.Data["Title"] = repoLink + " - collaboration" | ||||
| 
 | ||||
| 	if ctx.Req.Method == "POST" { | ||||
| 		name := strings.ToLower(ctx.Query("collaborator")) | ||||
| 		if len(name) == 0 || ctx.Repo.Owner.LowerName == name { | ||||
| 			ctx.Redirect(ctx.Req.URL.Path) | ||||
| 			return | ||||
| 		} | ||||
| 		has, err := models.HasAccess(name, repoLink, models.WRITABLE) | ||||
| 		if err != nil { | ||||
| 			ctx.Handle(500, "HasAccess", err) | ||||
| 			return | ||||
| 		} else if has { | ||||
| 			ctx.Redirect(ctx.Req.URL.Path) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		u, err := models.GetUserByName(name) | ||||
| 		if err != nil { | ||||
| 			if err == models.ErrUserNotExist { | ||||
| 				ctx.Flash.Error(ctx.Tr("form.user_not_exist")) | ||||
| 				ctx.Redirect(ctx.Req.URL.Path) | ||||
| 			} else { | ||||
| 				ctx.Handle(500, "GetUserByName", err) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		if err = models.AddAccess(&models.Access{UserName: name, RepoName: repoLink, | ||||
| 			Mode: models.WRITABLE}); err != nil { | ||||
| 			ctx.Handle(500, "AddAccess2", err) | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		if setting.Service.EnableNotifyMail { | ||||
| 			if err = mailer.SendCollaboratorMail(ctx.Render, u, ctx.User, ctx.Repo.Repository); err != nil { | ||||
| 				ctx.Handle(500, "SendCollaboratorMail", err) | ||||
| 				return | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		ctx.Flash.Success(ctx.Tr("repo.settings.add_collaborator_success")) | ||||
| 		ctx.Redirect(ctx.Req.URL.Path) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// Delete collaborator.
 | ||||
| 	remove := strings.ToLower(ctx.Query("remove")) | ||||
| 	if len(remove) > 0 && remove != ctx.Repo.Owner.LowerName { | ||||
| 		if err := models.DeleteAccess(&models.Access{UserName: remove, RepoName: repoLink}); err != nil { | ||||
| 			ctx.Handle(500, "setting.Collaboration(DeleteAccess)", err) | ||||
| 			ctx.Handle(500, "DeleteAccess", err) | ||||
| 			return | ||||
| 		} | ||||
| 		ctx.Flash.Success("Collaborator has been removed.") | ||||
| 		ctx.Flash.Success(ctx.Tr("repo.settings.remove_collaborator_success")) | ||||
| 		ctx.Redirect(ctx.Repo.RepoLink + "/settings/collaboration") | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	names, err := models.GetCollaboratorNames(repoLink) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(500, "setting.Collaboration(GetCollaborators)", err) | ||||
| 		ctx.Handle(500, "GetCollaborators", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
|  | @ -161,7 +206,7 @@ func Collaboration(ctx *middleware.Context) { | |||
| 	for i, name := range names { | ||||
| 		us[i], err = models.GetUserByName(name) | ||||
| 		if err != nil { | ||||
| 			ctx.Handle(500, "setting.Collaboration(GetUserByName)", err) | ||||
| 			ctx.Handle(500, "GetUserByName", err) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  | @ -170,7 +215,7 @@ func Collaboration(ctx *middleware.Context) { | |||
| 	ctx.HTML(200, COLLABORATION) | ||||
| } | ||||
| 
 | ||||
| func CollaborationPost(ctx *middleware.Context) { | ||||
| func SettingsCollaborationPost(ctx *middleware.Context) { | ||||
| 	repoLink := strings.TrimPrefix(ctx.Repo.RepoLink, "/") | ||||
| 	name := strings.ToLower(ctx.Query("collaborator")) | ||||
| 	if len(name) == 0 || ctx.Repo.Owner.LowerName == name { | ||||
|  |  | |||
|  | @ -31,16 +31,16 @@ const ( | |||
| func SignIn(ctx *middleware.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("sign_in") | ||||
| 
 | ||||
| 	// if _, ok := ctx.Session.Get("socialId").(int64); ok {
 | ||||
| 	// 		ctx.Data["IsSocialLogin"] = true
 | ||||
| 	// 		ctx.HTML(200, SIGNIN)
 | ||||
| 	// 		return
 | ||||
| 	// 	}
 | ||||
| 	if _, ok := ctx.Session.Get("socialId").(int64); ok { | ||||
| 		ctx.Data["IsSocialLogin"] = true | ||||
| 		ctx.HTML(200, SIGNIN) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// if setting.OauthService != nil {
 | ||||
| 	// 	ctx.Data["OauthEnabled"] = true
 | ||||
| 	// 	ctx.Data["OauthService"] = setting.OauthService
 | ||||
| 	// }
 | ||||
| 	if setting.OauthService != nil { | ||||
| 		ctx.Data["OauthEnabled"] = true | ||||
| 		ctx.Data["OauthService"] = setting.OauthService | ||||
| 	} | ||||
| 
 | ||||
| 	// Check auto-login.
 | ||||
| 	uname := ctx.GetCookie(setting.CookieUserName) | ||||
|  | @ -89,13 +89,13 @@ func SignIn(ctx *middleware.Context) { | |||
| func SignInPost(ctx *middleware.Context, form auth.SignInForm) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("sign_in") | ||||
| 
 | ||||
| 	// sid, isOauth := ctx.Session.Get("socialId").(int64)
 | ||||
| 	// if isOauth {
 | ||||
| 	// 	ctx.Data["IsSocialLogin"] = true
 | ||||
| 	// } else if setting.OauthService != nil {
 | ||||
| 	// 	ctx.Data["OauthEnabled"] = true
 | ||||
| 	// 	ctx.Data["OauthService"] = setting.OauthService
 | ||||
| 	// }
 | ||||
| 	sid, isOauth := ctx.Session.Get("socialId").(int64) | ||||
| 	if isOauth { | ||||
| 		ctx.Data["IsSocialLogin"] = true | ||||
| 	} else if setting.OauthService != nil { | ||||
| 		ctx.Data["OauthEnabled"] = true | ||||
| 		ctx.Data["OauthService"] = setting.OauthService | ||||
| 	} | ||||
| 
 | ||||
| 	if ctx.HasError() { | ||||
| 		ctx.HTML(200, SIGNIN) | ||||
|  | @ -121,18 +121,18 @@ func SignInPost(ctx *middleware.Context, form auth.SignInForm) { | |||
| 	} | ||||
| 
 | ||||
| 	// Bind with social account.
 | ||||
| 	// if isOauth {
 | ||||
| 	// 	if err = models.BindUserOauth2(user.Id, sid); err != nil {
 | ||||
| 	// 		if err == models.ErrOauth2RecordNotExist {
 | ||||
| 	// 			ctx.Handle(404, "user.SignInPost(GetOauth2ById)", err)
 | ||||
| 	// 		} else {
 | ||||
| 	// 			ctx.Handle(500, "user.SignInPost(GetOauth2ById)", err)
 | ||||
| 	// 		}
 | ||||
| 	// 		return
 | ||||
| 	// 	}
 | ||||
| 	// 	ctx.Session.Delete("socialId")
 | ||||
| 	// 	log.Trace("%s OAuth binded: %s -> %d", ctx.Req.RequestURI, form.UserName, sid)
 | ||||
| 	// }
 | ||||
| 	if isOauth { | ||||
| 		if err = models.BindUserOauth2(u.Id, sid); err != nil { | ||||
| 			if err == models.ErrOauth2RecordNotExist { | ||||
| 				ctx.Handle(404, "GetOauth2ById", err) | ||||
| 			} else { | ||||
| 				ctx.Handle(500, "GetOauth2ById", err) | ||||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 		ctx.Session.Delete("socialId") | ||||
| 		log.Trace("%s OAuth binded: %s -> %d", ctx.Req.RequestURI, form.UserName, sid) | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.Session.Set("uid", u.Id) | ||||
| 	ctx.Session.Set("uname", u.Name) | ||||
|  | @ -148,14 +148,34 @@ func SignInPost(ctx *middleware.Context, form auth.SignInForm) { | |||
| func SignOut(ctx *middleware.Context) { | ||||
| 	ctx.Session.Delete("uid") | ||||
| 	ctx.Session.Delete("uname") | ||||
| 	// ctx.Session.Delete("socialId")
 | ||||
| 	// ctx.Session.Delete("socialName")
 | ||||
| 	// ctx.Session.Delete("socialEmail")
 | ||||
| 	ctx.Session.Delete("socialId") | ||||
| 	ctx.Session.Delete("socialName") | ||||
| 	ctx.Session.Delete("socialEmail") | ||||
| 	ctx.SetCookie(setting.CookieUserName, "", -1) | ||||
| 	ctx.SetCookie(setting.CookieRememberName, "", -1) | ||||
| 	ctx.Redirect("/") | ||||
| } | ||||
| 
 | ||||
| func oauthSignUp(ctx *middleware.Context, sid int64) { | ||||
| 	// ctx.Data["Title"] = "OAuth Sign Up"
 | ||||
| 	// ctx.Data["PageIsSignUp"] = true
 | ||||
| 
 | ||||
| 	// if _, err := models.GetOauth2ById(sid); err != nil {
 | ||||
| 	// 	if err == models.ErrOauth2RecordNotExist {
 | ||||
| 	// 		ctx.Handle(404, "user.oauthSignUp(GetOauth2ById)", err)
 | ||||
| 	// 	} else {
 | ||||
| 	// 		ctx.Handle(500, "user.oauthSignUp(GetOauth2ById)", err)
 | ||||
| 	// 	}
 | ||||
| 	// 	return
 | ||||
| 	// }
 | ||||
| 
 | ||||
| 	// ctx.Data["IsSocialLogin"] = true
 | ||||
| 	// ctx.Data["username"] = strings.Replace(ctx.Session.Get("socialName").(string), " ", "", -1)
 | ||||
| 	// ctx.Data["email"] = ctx.Session.Get("socialEmail")
 | ||||
| 	// log.Trace("user.oauthSignUp(social ID): %v", ctx.Session.Get("socialId"))
 | ||||
| 	// ctx.HTML(200, SIGNUP)
 | ||||
| } | ||||
| 
 | ||||
| func SignUp(ctx *middleware.Context) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("sign_up") | ||||
| 
 | ||||
|  | @ -165,34 +185,14 @@ func SignUp(ctx *middleware.Context) { | |||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// if sid, ok := ctx.Session.Get("socialId").(int64); ok {
 | ||||
| 	// 	oauthSignUp(ctx, sid)
 | ||||
| 	// 	return
 | ||||
| 	// }
 | ||||
| 	if sid, ok := ctx.Session.Get("socialId").(int64); ok { | ||||
| 		oauthSignUp(ctx, sid) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	ctx.HTML(200, SIGNUP) | ||||
| } | ||||
| 
 | ||||
| // func oauthSignUp(ctx *middleware.Context, sid int64) {
 | ||||
| // 	ctx.Data["Title"] = "OAuth Sign Up"
 | ||||
| // 	ctx.Data["PageIsSignUp"] = true
 | ||||
| 
 | ||||
| // 	if _, err := models.GetOauth2ById(sid); err != nil {
 | ||||
| // 		if err == models.ErrOauth2RecordNotExist {
 | ||||
| // 			ctx.Handle(404, "user.oauthSignUp(GetOauth2ById)", err)
 | ||||
| // 		} else {
 | ||||
| // 			ctx.Handle(500, "user.oauthSignUp(GetOauth2ById)", err)
 | ||||
| // 		}
 | ||||
| // 		return
 | ||||
| // 	}
 | ||||
| 
 | ||||
| // 	ctx.Data["IsSocialLogin"] = true
 | ||||
| // 	ctx.Data["username"] = strings.Replace(ctx.Session.Get("socialName").(string), " ", "", -1)
 | ||||
| // 	ctx.Data["email"] = ctx.Session.Get("socialEmail")
 | ||||
| // 	log.Trace("user.oauthSignUp(social ID): %v", ctx.Session.Get("socialId"))
 | ||||
| // 	ctx.HTML(200, SIGNUP)
 | ||||
| // }
 | ||||
| 
 | ||||
| func SignUpPost(ctx *middleware.Context, cpt *captcha.Captcha, form auth.RegisterForm) { | ||||
| 	ctx.Data["Title"] = ctx.Tr("sign_up") | ||||
| 
 | ||||
|  |  | |||
|  | @ -1 +1 @@ | |||
| 0.4.7.0806 Alpha | ||||
| 0.4.7.0807 Alpha | ||||
|  | @ -0,0 +1,5 @@ | |||
| { | ||||
|     "language.fileExtensions": { | ||||
|         "tmpl": "html" | ||||
|     } | ||||
| } | ||||
|  | @ -1,17 +1,16 @@ | |||
| {{template "ng/base/head" .}} | ||||
| {{template "ng/base/header" .}} | ||||
| {{template "ng/base/head" .}} {{template "ng/base/header" .}} | ||||
| <div id="promo-wrapper"> | ||||
|     <div class="container clear"> | ||||
|         <div id="promo-logo" class="left"> | ||||
|             <img src="/img/gogs-lg.png" alt="logo"/> | ||||
|             <img src="/img/gogs-lg.png" alt="logo" /> | ||||
|         </div> | ||||
|         <div id="promo-content"> | ||||
|             <h1>Gogs</h1> | ||||
|             <h2>{{.i18n.Tr "app_desc"}}</h2> | ||||
|             <form id="promo-form" action="/user/login" method="post"> | ||||
|                 {{.CsrfTokenHtml}} | ||||
|                 <input class="ipt ipt-large" id="username" name="uname" type="text" placeholder="{{.i18n.Tr "home.uname_holder"}}"/> | ||||
|                 <input class="ipt ipt-large" name="password" type="password" placeholder="{{.i18n.Tr "home.password_holder"}}"/> | ||||
|                 <input class="ipt ipt-large" id="username" name="uname" type="text" placeholder="{{.i18n.Tr " home.uname_holder "}}"/> | ||||
|                 <input class="ipt ipt-large" name="password" type="password" placeholder="{{.i18n.Tr " home.password_holder "}}"/> | ||||
|                 <input name="from" type="hidden" value="home"> | ||||
|                 <button class="btn btn-black btn-large">{{.i18n.Tr "sign_in"}}</button> | ||||
|                 <button class="btn btn-green btn-large" id="register-button">{{.i18n.Tr "register"}}</button> | ||||
|  |  | |||
|  | @ -1,4 +1,4 @@ | |||
| <button class="btn github"><i class="fa fa-github"></i>GitHub</button> | ||||
| <button class="btn google"><i class="fa fa-google"></i>Google +</button> | ||||
| <button class="btn weibo"><i class="fa fa-weibo"></i>新浪微博</button> | ||||
| <button class="btn qq"><i class="fa fa-qq"></i>腾讯 QQ </button> | ||||
| {{if .OauthService.GitHub}}<a class="btn github" href="/user/login/github?next=/user/sign_up"><i class="fa fa-github"></i>GitHub</a>{{end}} | ||||
| {{if .OauthService.Google}}<a class="btn google" href="/user/login/google?next=/user/sign_up"><i class="fa fa-google"></i>Google +</a>{{end}} | ||||
| {{if .OauthService.Weibo}}<a class="btn weibo" href="/user/login/weibo?next=/user/sign_up"><i class="fa fa-weibo"></i>新浪微博</a>{{end}} | ||||
| {{if .OauthService.Tencent}}<a class="btn qq" href="/user/login/qq?next=/user/sign_up"><i class="fa fa-qq"></i>腾讯 QQ </a>{{end}} | ||||
|  | @ -1,47 +0,0 @@ | |||
| {{template "base/head" .}} | ||||
| {{template "base/navbar" .}} | ||||
| {{template "repo/nav" .}} | ||||
| {{template "repo/toolbar" .}} | ||||
| <div id="body" class="container"> | ||||
|     {{template "repo/setting_nav" .}} | ||||
|     <div id="repo-setting-container" class="col-md-10"> | ||||
|         {{template "base/alert" .}} | ||||
|         <div class="panel panel-default"> | ||||
|             <div class="panel-heading"> | ||||
|                 Collaborators | ||||
|             </div> | ||||
|              | ||||
|             <div class="panel-body"> | ||||
|                 <ul id="repo-collab-list" class="list-unstyled"> | ||||
|                     {{range .Collaborators}} | ||||
|                     <li class="collab"> | ||||
|                         {{if not (eq .LowerName $.Owner.LowerName)}}<a href="{{$.RepoLink}}/settings/collaboration?remove={{.Name}}" class="remove-collab pull-right"><i class="fa fa-times"></i></a>{{end}} | ||||
|                         <a class="member" href="/user/{{.Name}}"> | ||||
|                             <img alt="{{.Name}}" class="pull-left avatar" src="{{.AvatarLink}}"> | ||||
|                             <strong class="access-member-fullname">{{.FullName}}</strong><br/> | ||||
|                             {{.Name}} | ||||
|                         </a> | ||||
|                     </li> | ||||
|                     {{end}} | ||||
|                 </ul> | ||||
|             </div> | ||||
| 
 | ||||
|             <div class="panel-footer"> | ||||
|                 <form action="{{.RepoLink}}/settings/collaboration" method="post" class="form-horizontal" id="repo-collab-form"> | ||||
|                     {{.CsrfTokenHtml}} | ||||
|                     <div class="form-group" style="margin-bottom: 0"> | ||||
|                         <div class="col-md-4"> | ||||
|                             <input type="text" name="collaborator" class="form-control dropdown-toggle" id="repo-collaborator" autocomplete="off" required="required" data-toggle="dropdown"/> | ||||
|                             <div class="dropdown-menu"> | ||||
|                                 <ul class="list-unstyled"></ul> | ||||
|                             </div> | ||||
|                         </div> | ||||
|                         <button class="col-md-2 btn btn-primary">Add collaborator</button> | ||||
|                     </div> | ||||
|                 </form> | ||||
|             </div> | ||||
|         </div> | ||||
| 
 | ||||
|     </div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|  | @ -1,10 +1,11 @@ | |||
| <div id="repo-header" class="clear"> | ||||
|     <div class="container clear"> | ||||
|         <h1 id="repo-header-name" class="left public"> | ||||
|             <i class="mega-octicon octicon-{{if .Repository.IsPrivate}}lock{{else}}repo{{end}}"></i> | ||||
|             <i class="mega-octicon octicon-{{if .Repository.IsPrivate}}lock{{else if .Repository.IsMirror}}repo-clone{{else}}repo{{end}}"></i> | ||||
|             <a class="author" href="/{{.Owner.Name}}">{{.Owner.Name}}</a> | ||||
|             <span class="divider">/</span> | ||||
|             <a class="repo text-bold" href="{{.RepoLink}}">{{.Repository.Name}}</a> | ||||
|             {{if .Repository.IsMirror}}<span class="label label-gray">{{.i18n.Tr "mirror"}}</span>{{end}} | ||||
|         </h1> | ||||
|         <ul id="repo-header-meta" class="right menu menu-line"> | ||||
|             <li id="repo-header-download" class="inline-block down drop"> | ||||
|  |  | |||
|  | @ -0,0 +1,47 @@ | |||
| {{template "ng/base/head" .}} | ||||
| {{template "ng/base/header" .}} | ||||
| <div id="repo-wrapper"> | ||||
|     {{template "repo/header" .}} | ||||
| 	<div id="setting-wrapper" class="main-wrapper"> | ||||
| 	    <div id="repo-setting" class="container clear"> | ||||
| 	        {{template "repo/settings/nav" .}} | ||||
| 	        <div class="grid-4-5 left"> | ||||
| 	            <div class="setting-content"> | ||||
| 	                {{template "ng/base/alert" .}} | ||||
| 	                <div id="setting-content"> | ||||
| 	                    <div id="user-profile-setting-content" class="panel panel-radius"> | ||||
| 	                        <div class="panel-header"> | ||||
| 	                        	<strong>{{.i18n.Tr "repo.settings.collaboration"}}</strong> | ||||
| 	                        </div> | ||||
| 	                        <div class="panel-body"> | ||||
| 	                        	<ul id="repo-collab-list"> | ||||
| 	                        		{{range .Collaborators}} | ||||
| 	                        		<li class="collab"> | ||||
| 	                        			{{if not (eq .Id $.Owner.Id)}}<a href="{{$.RepoLink}}/settings/collaboration?remove={{.Name}}" class="remove-collab right"><i class="fa fa-times"></i></a>{{end}} | ||||
| 										<a class="member" href="/{{.Name}}"> | ||||
| 										    <img alt="{{.Name}}" class="pull-left avatar" src="{{.AvatarLink}}"> | ||||
| 										    <strong>{{.FullName}}</strong> ({{.Name}}) | ||||
| 										</a> | ||||
| 	                        		</li> | ||||
| 	                        		<hr> | ||||
| 	                        		{{end}} | ||||
| 	                        	</ul> | ||||
| 							</div> | ||||
| 				            <div class="panel-footer"> | ||||
| 				                <form class="form form-align" action="{{.RepoLink}}/settings/collaboration" method="post" id="repo-collab-form"> | ||||
| 				                    {{.CsrfTokenHtml}} | ||||
| 	                                <input class="ipt ipt-large ipt-radius" id="repo-collaborator" name="collaborator" autocomplete="off" required /> | ||||
| 	                                <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "repo.settings.add_collaborator"}}</button> | ||||
| 									<div class="repo-user-list-block"> | ||||
| 										<ul class="menu-down-show menu-vertical menu-radius switching-list user-list" id="repo-collaborator-list"></ul> | ||||
| 									</div> | ||||
| 				                </form> | ||||
| 				            </div> | ||||
| 	                    </div> | ||||
| 	                </div> | ||||
| 	            </div> | ||||
| 	        </div> | ||||
| 	    </div> | ||||
| 	</div> | ||||
| </div> | ||||
| {{template "ng/base/footer" .}}  | ||||
|  | @ -28,10 +28,12 @@ | |||
|                 <span class="form-label"></span> | ||||
|                 <a href="/user/sign_up">{{.i18n.Tr "auth.sign_up_now" | Str2html}}</a> | ||||
|             </p> | ||||
|             {{if .OauthEnabled}} | ||||
|             <hr/> | ||||
|             <div id="sign-social" class="text-center social-buttons"> | ||||
|                 {{template "ng/base/social" .}} | ||||
|             </div> | ||||
|             {{end}} | ||||
|         </div> | ||||
|     </form> | ||||
| </div> | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue