]> source.dussan.org Git - gitea.git/commitdiff
Page: `/org/:orgname/settings`
authorUnknwon <joe2010xtmf@163.com>
Thu, 14 Aug 2014 06:12:21 +0000 (14:12 +0800)
committerUnknwon <joe2010xtmf@163.com>
Thu, 14 Aug 2014 06:12:21 +0000 (14:12 +0800)
19 files changed:
cmd/web.go
conf/locale/locale_en-US.ini
conf/locale/locale_zh-CN.ini
gogs.go
modules/auth/org.go
modules/auth/user_form.go
modules/middleware/context.go
modules/middleware/org.go [new file with mode: 0644]
modules/middleware/repo.go
public/ng/css/gogs.css
public/ng/js/gogs.js
public/ng/less/gogs/settings.less
routers/org/org.go
routers/org/setting.go [new file with mode: 0644]
routers/user/setting.go
templates/.VERSION
templates/org/settings/delete.tmpl [new file with mode: 0644]
templates/org/settings/nav.tmpl [new file with mode: 0644]
templates/org/settings/options.tmpl [new file with mode: 0644]

index c49ba10540d8cdd48c96e12111171ebd5992f4d1..03704c64debae6e2eaef1bcacf14e546dd46c6ed 100644 (file)
@@ -159,18 +159,16 @@ func runWeb(*cli.Context) {
                r.Get("/reset_password", user.ResetPasswd)
                r.Post("/reset_password", user.ResetPasswdPost)
        }, reqSignOut)
-       m.Group("/user", func(r *macaron.Router) {
-               r.Get("/settings", user.Settings)
-               r.Post("/settings", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
-               m.Group("/settings", func(r *macaron.Router) {
-                       r.Get("/password", user.SettingsPassword)
-                       r.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost)
-                       r.Get("/ssh", user.SettingsSSHKeys)
-                       r.Post("/ssh", bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost)
-                       r.Get("/social", user.SettingsSocial)
-                       r.Get("/orgs", user.SettingsOrgs)
-                       r.Route("/delete", "GET,POST", user.SettingsDelete)
-               })
+       m.Group("/user/settings", func(r *macaron.Router) {
+               r.Get("", user.Settings)
+               r.Post("", bindIgnErr(auth.UpdateProfileForm{}), user.SettingsPost)
+               r.Get("/password", user.SettingsPassword)
+               r.Post("/password", bindIgnErr(auth.ChangePasswordForm{}), user.SettingsPasswordPost)
+               r.Get("/ssh", user.SettingsSSHKeys)
+               r.Post("/ssh", bindIgnErr(auth.AddSSHKeyForm{}), user.SettingsSSHKeysPost)
+               r.Get("/social", user.SettingsSocial)
+               r.Get("/orgs", user.SettingsOrgs)
+               r.Route("/delete", "GET,POST", user.SettingsDelete)
        }, reqSignIn)
        m.Group("/user", func(r *macaron.Router) {
                // r.Get("/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds)
@@ -226,20 +224,30 @@ func runWeb(*cli.Context) {
        m.Group("/org", func(r *macaron.Router) {
                r.Get("/create", org.Create)
                r.Post("/create", bindIgnErr(auth.CreateOrgForm{}), org.CreatePost)
-               r.Get("/:org", org.Home)
-               r.Get("/:org/dashboard", user.Dashboard)
-               r.Get("/:org/members", org.Members)
 
-               r.Get("/:org/teams", org.Teams)
-               r.Get("/:org/teams/new", org.NewTeam)
-               r.Post("/:org/teams/new", bindIgnErr(auth.CreateTeamForm{}), org.NewTeamPost)
-               r.Get("/:org/teams/:team/edit", org.EditTeam)
+               m.Group("/:org", func(r *macaron.Router) {
+                       r.Get("", org.Home)
+               }, middleware.OrgAssignment(true))
 
-               r.Get("/:org/teams/:team", org.SingleTeam)
+               m.Group("/:org", func(r *macaron.Router) {
+                       r.Get("/dashboard", user.Dashboard)
+                       r.Get("/members", org.Members)
 
-               r.Get("/:org/settings", org.Settings)
-               r.Post("/:org/settings", bindIgnErr(auth.OrgSettingForm{}), org.SettingsPost)
-               r.Post("/:org/settings/delete", org.DeletePost)
+                       r.Get("/teams", org.Teams)
+                       r.Get("/teams/:team", org.SingleTeam)
+               }, middleware.OrgAssignment(true, true))
+
+               m.Group("/:org", func(r *macaron.Router) {
+                       r.Get("/teams/new", org.NewTeam)
+                       r.Post("/teams/new", bindIgnErr(auth.CreateTeamForm{}), org.NewTeamPost)
+                       r.Get("/teams/:team/edit", org.EditTeam)
+
+                       m.Group("/settings", func(r *macaron.Router) {
+                               r.Get("", org.Settings)
+                               r.Post("", bindIgnErr(auth.UpdateOrgSettingForm{}), org.SettingsPost)
+                               r.Route("/delete", "GET,POST", org.SettingsDelete)
+                       })
+               }, middleware.OrgAssignment(true, true, true))
        }, reqSignIn)
 
        // Repository routers.
index 5156eaa7c6a4f1ccafde650d1f14c4054e977aa7..e34dfa013baa4b2e1a99e3866baac331b22561aa 100644 (file)
@@ -109,6 +109,7 @@ invalid_ssh_key = Sorry, we're not able to verify your SSH key: %s
 auth_failed = Authentication failed: %v
 
 still_own_repo = Your account still have ownership of repository, you have to delete or transfer them first.
+org_still_own_repo = This organization still have ownership of repository, you have to delete or transfer them first.
 
 [settings]
 profile = Profile
@@ -235,6 +236,19 @@ teams = Teams
 lower_members = members
 lower_repositories = repositories
 create_new_team = Create New Team
+org_desc = Description
+
+settings = Settings
+settings.options = Options
+settings.full_name = Full Name
+settings.website = Website
+settings.location = Location
+settings.update_settings = Update Settings
+settings.update_setting_success = Organization setting has been successfully updated.
+settings.delete = Delete Organization
+settings.delete_account = Delete This Organization
+settings.delete_prompt = The operation will delete this organization permanently, and <strong>CANNOT</strong> be undo!
+settings.confirm_delete_account = Confirm Deletion
 
 [action]
 create_repo = created repository <a href="/%s">%s</a>
index 2c7bb715fe5e5c4d4bd4d1cdd0ad54b5a696abd0..2499e121546312cd72657b603f8c5cf5c21ee190 100644 (file)
@@ -109,6 +109,7 @@ invalid_ssh_key = 很抱歉,我们无法验证您输入的 SSH 密钥:%s
 auth_failed = 授权验证失败:%v
 
 still_own_repo = 您的帐户仍然是某些仓库的拥有者,您必须先转移或删除它们才能执行删除帐户操作!
+org_still_own_repo = 该组织仍然是某些仓库的拥有者,您必须先转移或删除它们才能执行删除组织操作!
 
 [settings]
 profile = 个人信息
@@ -235,6 +236,19 @@ teams = 组织团队
 lower_members = 名成员
 lower_repositories = 个仓库
 create_new_team = 创建新的团队
+org_desc = 组织描述
+
+settings = 组织设置
+settings.options = 基本设置
+settings.full_name = 组织全名
+settings.website = 官方网站
+settings.location = 所在地区
+settings.update_settings = 更新组织设置
+settings.update_setting_success = 组织设置更新成功!
+settings.delete = 删除组织
+settings.delete_account = 删除当前组织
+settings.delete_prompt = 删除操作会永久清除该组织的信息,并且 <strong>不可恢复</strong>!
+settings.confirm_delete_account = 确认删除组织
 
 [action]
 create_repo = 创建了仓库 <a href="/%s">%s</a>
diff --git a/gogs.go b/gogs.go
index 17179d03204ae0753d95f1f1453152970da49867..4a3e353cdf7c31f362ad6317b5ce31c2ea229f50 100644 (file)
--- a/gogs.go
+++ b/gogs.go
@@ -17,7 +17,7 @@ import (
        "github.com/gogits/gogs/modules/setting"
 )
 
-const APP_VER = "0.4.7.0810 Alpha"
+const APP_VER = "0.4.7.0814 Alpha"
 
 func init() {
        runtime.GOMAXPROCS(runtime.NumCPU())
index 0895780e3fe12918e93395e77f1393f48404d0d5..9598e6f8342a3ee9645b0a18f40c146c665738dc 100644 (file)
@@ -27,15 +27,17 @@ func (f *CreateOrgForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i
        validate(errs, ctx.Data, f, l)
 }
 
-type OrgSettingForm struct {
-       DisplayName string `form:"display_name" binding:"Required;MaxSize(100)"`
+type UpdateOrgSettingForm struct {
+       OrgUserName string `form:"uname" binding:"Required;MaxSize(35)"`
+       OrgFullName string `form:"fullname" binding:"MaxSize(100)"`
        Email       string `form:"email" binding:"Required;Email;MaxSize(50)"`
        Description string `form:"desc" binding:"MaxSize(255)"`
-       Website     string `form:"site" binding:"Url;MaxSize(100)"`
+       Website     string `form:"website" binding:"Url;MaxSize(100)"`
        Location    string `form:"location" binding:"MaxSize(50)"`
+       Avatar      string `form:"avatar" binding:"Required;Email;MaxSize(50)"`
 }
 
-func (f *OrgSettingForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
+func (f *UpdateOrgSettingForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n.Locale) {
        validate(errs, ctx.Data, f, l)
 }
 
index df713b570fc58abf24e5443b3c5544db8b7419ab..51a07b91286ddbe08e8c2cb663305ed476f308e8 100644 (file)
@@ -76,9 +76,9 @@ func (f *SignInForm) Validate(ctx *macaron.Context, errs *binding.Errors, l i18n
 
 type UpdateProfileForm struct {
        UserName string `form:"uname" binding:"Required;MaxSize(35)"`
-       FullName string `form:"fullname" binding:"MaxSize(40)"`
+       FullName string `form:"fullname" binding:"MaxSize(100)"`
        Email    string `form:"email" binding:"Required;Email;MaxSize(50)"`
-       Website  string `form:"website" binding:"Url;MaxSize(50)"`
+       Website  string `form:"website" binding:"Url;MaxSize(100)"`
        Location string `form:"location" binding:"MaxSize(50)"`
        Avatar   string `form:"avatar" binding:"Required;Email;MaxSize(50)"`
 }
index 1e6f8e952513be33d4479a331c06170241fb442a..aa1266d6498f555a568324a8051fd2d579a4dd2a 100644 (file)
@@ -64,6 +64,12 @@ type Context struct {
                CommitsCount int
                Mirror       *models.Mirror
        }
+
+       Org struct {
+               IsOwner      bool
+               IsMember     bool
+               Organization *models.User
+       }
 }
 
 // Query querys form parameter.
diff --git a/modules/middleware/org.go b/modules/middleware/org.go
new file mode 100644 (file)
index 0000000..05316a5
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright 2014 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package middleware
+
+import (
+       "github.com/Unknwon/macaron"
+
+       "github.com/gogits/gogs/models"
+)
+
+func OrgAssignment(redirect bool, args ...bool) macaron.Handler {
+       return func(ctx *Context) {
+               var (
+                       requireMember bool
+                       requireOwner  bool
+               )
+               if len(args) >= 1 {
+                       requireMember = args[0]
+               }
+               if len(args) >= 2 {
+                       requireOwner = args[1]
+               }
+
+               orgName := ctx.Params(":org")
+
+               var err error
+               ctx.Org.Organization, err = models.GetUserByName(orgName)
+               if err != nil {
+                       if err == models.ErrUserNotExist {
+                               ctx.Handle(404, "GetUserByName", err)
+                       } else if redirect {
+                               ctx.Redirect("/")
+                       } else {
+                               ctx.Handle(500, "GetUserByName", err)
+                       }
+                       return
+               }
+               ctx.Data["Org"] = ctx.Org.Organization
+
+               if ctx.IsSigned {
+                       ctx.Org.IsOwner = ctx.Org.Organization.IsOrgOwner(ctx.User.Id)
+                       if ctx.Org.IsOwner {
+                               ctx.Org.IsMember = true
+                       } else {
+                               ctx.Org.IsMember = ctx.Org.Organization.IsOrgMember(ctx.User.Id)
+                       }
+               }
+               if (requireMember && !ctx.Org.IsMember) || (requireOwner && !ctx.Org.IsOwner) {
+                       ctx.Handle(404, "OrgAssignment", err)
+                       return
+               }
+       }
+}
index 929850d202fb83bba5216cd9395a3b7441389011..a028aab802e53f0fe52d40299982dbf59d9a25e1 100644 (file)
@@ -20,15 +20,13 @@ import (
 
 func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
        return func(ctx *Context) {
-               // To valid brach name.
-               var validBranch bool
-               // To display bare quick start if it is a bare repo.
-               var displayBare bool
-
+               var (
+                       validBranch bool // To valid brach name.
+                       displayBare bool // To display bare page if it is a bare repo.
+               )
                if len(args) >= 1 {
                        validBranch = args[0]
                }
-
                if len(args) >= 2 {
                        displayBare = args[1]
                }
@@ -60,12 +58,11 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
                        if err != nil {
                                if err == models.ErrUserNotExist {
                                        ctx.Handle(404, "GetUserByName", err)
-                                       return
                                } else if redirect {
                                        ctx.Redirect("/")
-                                       return
+                               } else {
+                                       ctx.Handle(500, "GetUserByName", err)
                                }
-                               ctx.Handle(500, "GetUserByName", err)
                                return
                        }
                } else {
index e69e4b663e071f0410b8192a00ed2a56b05e7a44..93a5d2f8c91487fb201a7eba9deb6fee77dcf84d 100644 (file)
@@ -1348,26 +1348,32 @@ The register and sign-in page style
 .setting-content {
   margin-left: 32px;
 }
+#org-setting-form,
 #repo-setting-form,
 #user-profile-form {
   background-color: #FFF;
   padding: 30px 0;
 }
+#org-setting-form textarea,
 #repo-setting-form textarea,
 #user-profile-form textarea {
   margin-left: 4px;
   height: 100px;
 }
+#org-setting-form label,
 #repo-setting-form label,
 #user-profile-form label,
+#org-setting-form .form-label,
 #repo-setting-form .form-label,
 #user-profile-form .form-label {
   width: 240px;
 }
+#org-setting-form .ipt,
 #repo-setting-form .ipt,
 #user-profile-form .ipt {
   width: 360px;
 }
+#org-setting-form .field,
 #repo-setting-form .field,
 #user-profile-form .field {
   margin-bottom: 24px;
index 473997e9ee96996539bfc9857ae4b3e7bcb918c4..ad8df997169e4a984fbbcd1766a38e2d148569f0 100644 (file)
@@ -225,6 +225,30 @@ function initCore() {
     Gogs.renderCodeView();
 }
 
+function initUserSetting() {
+    // Confirmation of change username in user profile page.
+    $('#user-profile-form').submit(function (e) {
+        var $username = $('#username');
+        if (($username.data('uname') != $username.val()) && !confirm('Username has been changed, do you want to continue?')) {
+            e.preventDefault();
+            return true;
+        }
+    });
+
+    // Show add SSH key panel.
+    $('#ssh-add').click(function () {
+        $('#user-ssh-add-form').removeClass("hide");
+    });
+
+    // Confirmation of delete account.
+    $('#delete-account-button').click(function (e) {
+        if (!confirm('This account is going to be deleted, do you want to continue?')) {
+            e.preventDefault();
+            return true;
+        }
+    });
+}
+
 function initRepoCreate() {
     // Owner switch menu click.
     $('#repo-create-owner-list').on('click', 'li', function () {
@@ -286,21 +310,43 @@ function initRepoSetting() {
     });
 }
 
+function initOrgSetting() {
+    // Options.
+    // Confirmation of changing organization name.
+    $('#org-setting-form').submit(function (e) {
+        var $orgname = $('#orgname');
+        if (($orgname.data('orgname') != $orgname.val()) && !confirm('Organization name has been changed, do you want to continue?')) {
+            e.preventDefault();
+            return true;
+        }
+    });
+    // Confirmation of delete organization.
+    $('#delete-org-button').click(function (e) {
+        if (!confirm('This organization is going to be deleted, do you want to continue?')) {
+            e.preventDefault();
+            return true;
+        }
+    });
+}
+
 $(document).ready(function () {
     initCore();
+    if ($('#user-profile-setting').length) {
+        initUserSetting();
+    }
     if ($('#repo-create-form').length || $('#repo-migrate-form').length) {
         initRepoCreate();
     }
     if ($('#repo-setting').length) {
         initRepoSetting();
     }
+    if ($('#org-setting').length) {
+        initOrgSetting();
+    }
 
     Tabs('#dashboard-sidebar-menu');
 
     homepage();
-    settingsProfile();
-    settingsSSHKeys();
-    settingsDelete();
 
     // Fix language drop-down menu height.
     var l = $('#footer-lang li').length;
@@ -328,32 +374,4 @@ function homepage() {
         }
         $('#promo-form').attr('action', '/user/sign_up');
     });
-}
-
-function settingsProfile() {
-    // Confirmation of change username in user profile page.
-    $('#user-profile-form').submit(function (e) {
-        var $username = $('#username');
-        if (($username.data('uname') != $username.val()) && !confirm('Username has been changed, do you want to continue?')) {
-            e.preventDefault();
-            return true;
-        }
-    });
-}
-
-function settingsSSHKeys() {
-    // Show add SSH key panel.
-    $('#ssh-add').click(function () {
-        $('#user-ssh-add-form').removeClass("hide");
-    });
-}
-
-function settingsDelete() {
-    // Confirmation of delete account.
-    $('#delete-account-button').click(function (e) {
-        if (!confirm('This account is going to deleted, do you want to continue?')) {
-            e.preventDefault();
-            return true;
-        }
-    });
 }
\ No newline at end of file
index 1a492b03c24688b8dda0e95ae07acc899f0063ad..ad50e4ffa8177e57514c8ad1a93b5739fd13adfe 100644 (file)
@@ -31,6 +31,7 @@
   margin-left: 32px;
 }
 
+#org-setting-form,
 #repo-setting-form,
 #user-profile-form {
     background-color: #FFF;
index fed1fd5fbcf2820b8946bbb335b59afe9a8ea67c..254ba8148f9745405ad4fff51a0143a04af57262 100644 (file)
@@ -13,30 +13,20 @@ import (
 )
 
 const (
-       HOME     base.TplName = "org/home"
-       CREATE   base.TplName = "org/create"
-       SETTINGS base.TplName = "org/settings"
+       HOME   base.TplName = "org/home"
+       CREATE base.TplName = "org/create"
 )
 
 func Home(ctx *middleware.Context) {
-       ctx.Data["Title"] = ctx.Params(":org")
+       org := ctx.Org.Organization
+       ctx.Data["Title"] = org.Name
 
-       org, err := models.GetUserByName(ctx.Params(":org"))
-       if err != nil {
-               if err == models.ErrUserNotExist {
-                       ctx.Handle(404, "GetUserByName", err)
-               } else {
-                       ctx.Handle(500, "GetUserByName", err)
-               }
-               return
-       }
-       ctx.Data["Org"] = org
-
-       ctx.Data["Repos"], err = models.GetRepositories(org.Id, ctx.IsSigned && org.IsOrgMember(ctx.User.Id))
+       repos, err := models.GetRepositories(org.Id, ctx.IsSigned && org.IsOrgMember(ctx.User.Id))
        if err != nil {
                ctx.Handle(500, "GetRepositories", err)
                return
        }
+       ctx.Data["Repos"] = repos
 
        if err = org.GetMembers(); err != nil {
                ctx.Handle(500, "GetMembers", err)
@@ -94,97 +84,3 @@ func CreatePost(ctx *middleware.Context, form auth.CreateOrgForm) {
 
        ctx.Redirect("/org/" + form.OrgName + "/dashboard")
 }
-
-func Settings(ctx *middleware.Context) {
-       ctx.Data["Title"] = "Settings"
-
-       org, err := models.GetUserByName(ctx.Params(":org"))
-       if err != nil {
-               if err == models.ErrUserNotExist {
-                       ctx.Handle(404, "org.Settings(GetUserByName)", err)
-               } else {
-                       ctx.Handle(500, "org.Settings(GetUserByName)", err)
-               }
-               return
-       }
-       ctx.Data["Org"] = org
-
-       ctx.HTML(200, SETTINGS)
-}
-
-func SettingsPost(ctx *middleware.Context, form auth.OrgSettingForm) {
-       ctx.Data["Title"] = "Settings"
-
-       org, err := models.GetUserByName(ctx.Params(":org"))
-       if err != nil {
-               if err == models.ErrUserNotExist {
-                       ctx.Handle(404, "org.SettingsPost(GetUserByName)", err)
-               } else {
-                       ctx.Handle(500, "org.SettingsPost(GetUserByName)", err)
-               }
-               return
-       }
-       ctx.Data["Org"] = org
-
-       if ctx.HasError() {
-               ctx.HTML(200, SETTINGS)
-               return
-       }
-
-       org.FullName = form.DisplayName
-       org.Email = form.Email
-       org.Description = form.Description
-       org.Website = form.Website
-       org.Location = form.Location
-       if err = models.UpdateUser(org); err != nil {
-               ctx.Handle(500, "org.SettingsPost(UpdateUser)", err)
-               return
-       }
-       log.Trace("%s Organization setting updated: %s", ctx.Req.RequestURI, org.LowerName)
-       ctx.Flash.Success("Organization profile has been successfully updated.")
-       ctx.Redirect("/org/" + org.Name + "/settings")
-}
-
-func DeletePost(ctx *middleware.Context) {
-       ctx.Data["Title"] = "Settings"
-
-       org, err := models.GetUserByName(ctx.Params(":org"))
-       if err != nil {
-               if err == models.ErrUserNotExist {
-                       ctx.Handle(404, "org.DeletePost(GetUserByName)", err)
-               } else {
-                       ctx.Handle(500, "org.DeletePost(GetUserByName)", err)
-               }
-               return
-       }
-       ctx.Data["Org"] = org
-
-       if !org.IsOrgOwner(ctx.User.Id) {
-               ctx.Error(403)
-               return
-       }
-
-       tmpUser := models.User{
-               Passwd: ctx.Query("password"),
-               Salt:   ctx.User.Salt,
-       }
-       tmpUser.EncodePasswd()
-       if tmpUser.Passwd != ctx.User.Passwd {
-               ctx.Flash.Error("Password is not correct. Make sure you are owner of this account.")
-       } else {
-               if err := models.DeleteOrganization(org); err != nil {
-                       switch err {
-                       case models.ErrUserOwnRepos:
-                               ctx.Flash.Error("This organization still have ownership of repository, you have to delete or transfer them first.")
-                       default:
-                               ctx.Handle(500, "org.DeletePost(DeleteOrganization)", err)
-                               return
-                       }
-               } else {
-                       ctx.Redirect("/")
-                       return
-               }
-       }
-
-       ctx.Redirect("/org/" + org.Name + "/settings")
-}
diff --git a/routers/org/setting.go b/routers/org/setting.go
new file mode 100644 (file)
index 0000000..0ddf006
--- /dev/null
@@ -0,0 +1,99 @@
+// Copyright 2014 The Gogs Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package org
+
+import (
+       "github.com/gogits/gogs/models"
+       "github.com/gogits/gogs/modules/auth"
+       "github.com/gogits/gogs/modules/base"
+       "github.com/gogits/gogs/modules/log"
+       "github.com/gogits/gogs/modules/middleware"
+)
+
+const (
+       SETTINGS_OPTIONS base.TplName = "org/settings/options"
+       SETTINGS_DELETE  base.TplName = "org/settings/delete"
+)
+
+func Settings(ctx *middleware.Context) {
+       ctx.Data["Title"] = ctx.Tr("org.settings")
+       ctx.Data["PageIsSettingsOptions"] = true
+       ctx.HTML(200, SETTINGS_OPTIONS)
+}
+
+func SettingsPost(ctx *middleware.Context, form auth.UpdateOrgSettingForm) {
+       ctx.Data["Title"] = ctx.Tr("org.settings")
+       ctx.Data["PageIsSettingsOptions"] = true
+
+       if ctx.HasError() {
+               ctx.HTML(200, SETTINGS_OPTIONS)
+               return
+       }
+
+       org := ctx.Org.Organization
+
+       // Check if organization name has been changed.
+       if org.Name != form.OrgUserName {
+               isExist, err := models.IsUserExist(form.OrgUserName)
+               if err != nil {
+                       ctx.Handle(500, "IsUserExist", err)
+                       return
+               } else if isExist {
+                       ctx.RenderWithErr(ctx.Tr("form.username_been_taken"), SETTINGS_OPTIONS, &form)
+                       return
+               } else if err = models.ChangeUserName(org, form.OrgUserName); err != nil {
+                       if err == models.ErrUserNameIllegal {
+                               ctx.Flash.Error(ctx.Tr("form.illegal_username"))
+                               ctx.Redirect("/org/" + org.LowerName + "/settings")
+                               return
+                       } else {
+                               ctx.Handle(500, "ChangeUserName", err)
+                       }
+                       return
+               }
+               log.Trace("Organization name changed: %s -> %s", org.Name, form.OrgUserName)
+               org.Name = form.OrgUserName
+       }
+
+       org.FullName = form.OrgFullName
+       org.Email = form.Email
+       org.Description = form.Description
+       org.Website = form.Website
+       org.Location = form.Location
+       org.Avatar = base.EncodeMd5(form.Avatar)
+       org.AvatarEmail = form.Avatar
+       if err := models.UpdateUser(org); err != nil {
+               ctx.Handle(500, "UpdateUser", err)
+               return
+       }
+       log.Trace("Organization setting updated: %s", org.Name)
+       ctx.Flash.Success(ctx.Tr("org.settings.update_setting_success"))
+       ctx.Redirect("/org/" + org.Name + "/settings")
+}
+
+func SettingsDelete(ctx *middleware.Context) {
+       ctx.Data["Title"] = ctx.Tr("org.settings")
+       ctx.Data["PageIsSettingsDelete"] = true
+
+       org := ctx.Org.Organization
+       if ctx.Req.Method == "POST" {
+               // TODO: validate password.
+               if err := models.DeleteOrganization(org); err != nil {
+                       switch err {
+                       case models.ErrUserOwnRepos:
+                               ctx.Flash.Error(ctx.Tr("form.org_still_own_repo"))
+                               ctx.Redirect("/org/" + org.LowerName + "/settings/delete")
+                       default:
+                               ctx.Handle(500, "DeleteOrganization", err)
+                       }
+               } else {
+                       log.Trace("Organization deleted: %s", ctx.User.Name)
+                       ctx.Redirect("/")
+               }
+               return
+       }
+
+       ctx.HTML(200, SETTINGS_DELETE)
+}
index 739a30d032619b378238bdc892c0e91679a693ab..e091bc43815d41fd351ff8c326d622827863ed84 100644 (file)
@@ -252,16 +252,14 @@ func SettingsDelete(ctx *middleware.Context) {
                        case models.ErrUserOwnRepos:
                                ctx.Flash.Error(ctx.Tr("form.still_own_repo"))
                                ctx.Redirect("/user/settings/delete")
-                               return
                        default:
                                ctx.Handle(500, "DeleteUser", err)
-                               return
                        }
                } else {
                        log.Trace("Account deleted: %s", ctx.User.Name)
                        ctx.Redirect("/")
-                       return
                }
+               return
        }
 
        ctx.HTML(200, SETTINGS_DELETE)
index 2575ec6bc38253de14e11c0182cf2c67ec69c8ff..f398e9011070b4ef9532e469c6015f43d929b2a0 100644 (file)
@@ -1 +1 @@
-0.4.7.0810 Alpha
\ No newline at end of file
+0.4.7.0814 Alpha
\ No newline at end of file
diff --git a/templates/org/settings/delete.tmpl b/templates/org/settings/delete.tmpl
new file mode 100644 (file)
index 0000000..7e24f85
--- /dev/null
@@ -0,0 +1,28 @@
+{{template "ng/base/head" .}}
+{{template "ng/base/header" .}}
+<div id="setting-wrapper" class="main-wrapper">
+    <div id="org-setting" class="container clear">
+        {{template "org/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-warning panel-radius">
+                        <p class="panel-header"><strong>{{.i18n.Tr "org.settings.delete_account"}}</strong></p>
+                        <div class="panel-body panel-content">
+                            <span class="alert alert-red alert-radius block"><i class="octicon octicon-alert"></i>{{.i18n.Tr "org.settings.delete_prompt" | Str2html}}</span>
+                            <form  action="/org/{{.Org.LowerName}}/settings/delete" method="post">
+                                {{.CsrfTokenHtml}}
+                                <p class="field">
+                                    <span class="form-label"></span>
+                                    <button class="btn btn-red btn-large btn-radius" id="delete-org-button">{{.i18n.Tr "org.settings.confirm_delete_account"}}</button>
+                                </p>
+                            </form>
+                        </div>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</div>
+{{template "ng/base/footer" .}}
\ No newline at end of file
diff --git a/templates/org/settings/nav.tmpl b/templates/org/settings/nav.tmpl
new file mode 100644 (file)
index 0000000..950569d
--- /dev/null
@@ -0,0 +1,11 @@
+<div id="setting-menu" class="grid-1-5 panel panel-radius left">
+    <div class="panel-header">
+       <strong>{{.i18n.Tr "org.settings"}}</strong>
+    </div>
+    <div class="panel-body">
+        <ul class="menu menu-vertical switching-list grid-1-5 left">
+            <li {{if .PageIsSettingsOptions}}class="current"{{end}}><a href="/org/{{.Org.LowerName}}/settings">{{.i18n.Tr "org.settings.options"}}</a></li>
+            <li {{if .PageIsSettingsDelete}}class="current"{{end}}><a href="/org/{{.Org.LowerName}}/settings/delete">{{.i18n.Tr "org.settings.delete"}}</a></li>
+        </ul>
+    </div>
+</div>
\ No newline at end of file
diff --git a/templates/org/settings/options.tmpl b/templates/org/settings/options.tmpl
new file mode 100644 (file)
index 0000000..7548ad5
--- /dev/null
@@ -0,0 +1,56 @@
+{{template "ng/base/head" .}}
+{{template "ng/base/header" .}}
+<div id="setting-wrapper" class="main-wrapper">
+    <div id="org-setting" class="container clear">
+               {{template "org/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 "org.settings.options"}}</strong>
+                               </div>
+                               <form class="form form-align panel-body" id="org-setting-form" action="/org/{{.Org.LowerName}}/settings" method="post">
+                                   {{.CsrfTokenHtml}}
+                                       <input type="hidden" name="action" value="update">
+                                   <div class="field">
+                                       <label class="req" for="orgname">{{.i18n.Tr "username"}}</label>
+                                       <input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="orgname" name="uname" value="{{.Org.Name}}" data-orgname="{{.Org.Name}}" required />
+                                   </div>
+                                   <div class="field">
+                                       <label for="full-name">{{.i18n.Tr "org.settings.full_name"}}</label>
+                                       <input class="ipt ipt-large ipt-radius {{if .Err_FullName}}ipt-error{{end}}" id="full-name" name="fullname" value="{{.Org.FullName}}" />
+                                   </div>
+                                   <div class="field">
+                                       <label class="req" for="email">{{.i18n.Tr "email"}}</label>
+                                       <input class="ipt ipt-large ipt-radius {{if .Err_Email}}ipt-error{{end}}" id="email" name="email" type="email" value="{{.Org.Email}}" required />
+                                   </div>
+                                                   <div class="field clear">
+                                                       <label class="left" for="desc">{{.i18n.Tr "org.org_desc"}}</label>
+                                                       <textarea class="ipt ipt-large ipt-radius {{if .Err_Description}}ipt-error{{end}}" id="desc" name="desc">{{.Org.Description}}</textarea>
+                                                   </div>
+                                   <div class="field">
+                                       <label for="website">{{.i18n.Tr "org.settings.website"}}</label>
+                                       <input class="ipt ipt-large ipt-radius {{if .Err_Website}}ipt-error{{end}}" id="website" name="website" type="url" value="{{.Org.Website}}" />
+                                   </div>
+                                   <div class="field">
+                                       <label for="location">{{.i18n.Tr "org.settings.location"}}</label>
+                                       <input class="ipt ipt-large ipt-radius {{if .Err_Location}}ipt-error{{end}}" id="location" name="location" type="text" value="{{.Org.Location}}" />
+                                   </div>
+                                   <div class="field">
+                                       <label for="gravatar-email">Gravatar {{.i18n.Tr "email"}}</label>
+                                       <input class="ipt ipt-large ipt-radius {{if .Err_Avatar}}ipt-error{{end}}" id="gravatar-email" name="avatar" type="text" value="{{.Org.AvatarEmail}}" />
+                                   </div>
+                                   <div class="field">
+                                       <span class="form-label"></span>
+                                       <button class="btn btn-green btn-large btn-radius">{{.i18n.Tr "org.settings.update_settings"}}</button>
+                                   </div>
+                               </form>
+                           </div>
+                       </div>
+                   </div>
+           </div>
+       </div>
+</div>
+{{template "ng/base/footer" .}}
\ No newline at end of file