Browse Source

Finish new collaboration page

Unknwon 10 years ago
parent
commit
e8c9bb2c66

+ 2 - 3
cmd/web.go

@@ -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)

+ 4 - 0
conf/locale/locale_en-US.ini

@@ -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

+ 4 - 0
conf/locale/locale_zh-CN.ini

@@ -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 = 组织名称

+ 1 - 1
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())

+ 59 - 6
public/ng/css/gogs.css

@@ -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;
 }

+ 9 - 1
public/ng/css/ui.css

@@ -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;
 }

+ 95 - 0
public/ng/js/gogs.js

@@ -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 () {

+ 16 - 0
public/ng/less/gogs/base.less

@@ -214,4 +214,20 @@ 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;
+    }
 }

+ 18 - 3
public/ng/less/gogs/dashboard.less

@@ -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

+ 28 - 1
public/ng/less/gogs/repository.less

@@ -357,7 +357,6 @@
   margin-left: 4em;
 }
 
-#dashboard-switch-menu,
 #repo-create-owner-list {
     top: 30px;
     left: 0;
@@ -442,4 +441,32 @@
 }
 .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;
 }

+ 14 - 6
public/ng/less/ui/menu.less

@@ -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 {

+ 5 - 6
public/ng/less/ui/reset.less

@@ -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;

+ 5 - 0
routers/home.go

@@ -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)
 }

+ 54 - 9
routers/repo/setting.go

@@ -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 {

+ 55 - 55
routers/user/auth.go

@@ -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
templates/.VERSION

@@ -1 +1 @@
-0.4.7.0806 Alpha
+0.4.7.0807 Alpha

+ 5 - 0
templates/.brackets.json

@@ -0,0 +1,5 @@
+{
+    "language.fileExtensions": {
+        "tmpl": "html"
+    }
+}

+ 4 - 5
templates/home.tmpl

@@ -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>

+ 4 - 4
templates/ng/base/social.tmpl

@@ -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&nbsp;</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&nbsp;</a>{{end}}

+ 0 - 47
templates/repo/collaboration.tmpl

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

+ 2 - 1
templates/repo/header.tmpl

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

+ 47 - 0
templates/repo/settings/collaboration.tmpl

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

+ 2 - 0
templates/user/signin.tmpl

@@ -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>