]> source.dussan.org Git - gitea.git/commitdiff
Finish team list, create new team, join/leave team page
authorUnknwon <joe2010xtmf@163.com>
Sat, 16 Aug 2014 08:21:17 +0000 (16:21 +0800)
committerUnknwon <joe2010xtmf@163.com>
Sat, 16 Aug 2014 08:21:17 +0000 (16:21 +0800)
41 files changed:
cmd/web.go
conf/locale/locale_en-US.ini
conf/locale/locale_zh-CN.ini
gogs.go
models/org.go
modules/auth/org.go
modules/middleware/context.go
modules/middleware/org.go
public/ng/css/gogs.css
public/ng/less/gogs/organization.less
public/ng/less/gogs/repository.less
routers/org/members.go
routers/org/org.go
routers/org/teams.go
routers/user/auth.go
templates/.VERSION
templates/org/base/header.tmpl [new file with mode: 0644]
templates/org/header.tmpl [deleted file]
templates/org/home.tmpl
templates/org/invite.tmpl [deleted file]
templates/org/member/invite.tmpl [new file with mode: 0644]
templates/org/member/members.tmpl [new file with mode: 0644]
templates/org/members.tmpl [deleted file]
templates/org/settings/delete.tmpl
templates/org/settings/options.tmpl
templates/org/team/new.tmpl [new file with mode: 0644]
templates/org/team/teams.tmpl [new file with mode: 0644]
templates/org/team_new.tmpl [deleted file]
templates/org/teams.tmpl [deleted file]
templates/repo/create.tmpl
templates/user/activate.tmpl [deleted file]
templates/user/auth/activate.tmpl [new file with mode: 0644]
templates/user/auth/forgot_passwd.tmpl [new file with mode: 0644]
templates/user/auth/reset_passwd.tmpl [new file with mode: 0644]
templates/user/auth/signin.tmpl [new file with mode: 0644]
templates/user/auth/signup.tmpl [new file with mode: 0644]
templates/user/forgot_passwd.tmpl [deleted file]
templates/user/reset_passwd.tmpl [deleted file]
templates/user/signin.tmpl [deleted file]
templates/user/signup.tmpl [deleted file]
templates/user/stars.tmpl [deleted file]

index 03e5e86066bdb63a2ae0054b8bed3332b71fa37d..064a0358f934287be56008ea0617a1baca645150 100644 (file)
@@ -236,6 +236,7 @@ func runWeb(*cli.Context) {
 
                        r.Get("/teams", org.Teams)
                        r.Get("/teams/:team", org.SingleTeam)
+                       r.Get("/teams/:team/action/:action", org.TeamsAction)
                }, middleware.OrgAssignment(true, true))
 
                m.Group("/:org", func(r *macaron.Router) {
@@ -248,11 +249,9 @@ func runWeb(*cli.Context) {
                                r.Post("", bindIgnErr(auth.UpdateOrgSettingForm{}), org.SettingsPost)
                                r.Route("/delete", "GET,POST", org.SettingsDelete)
                        })
-               }, middleware.OrgAssignment(true, true, true))
 
-               m.Group("/:org", func(r *macaron.Router) {
                        r.Route("/invitations/new", "GET,POST", org.Invitation)
-               }, middleware.OrgAssignment(true, false, false, true))
+               }, middleware.OrgAssignment(true, true, true))
        }, reqSignIn)
 
        // Repository routers.
index d44dca081b443a0cab1a0a017d7185cff0ba900b..4e191dca406867d51012159b681253cb5f1d8c61 100644 (file)
@@ -79,6 +79,7 @@ Retype = Re-type password
 SSHTitle = SSH key name
 HttpsUrl = HTTPS URL
 PayloadUrl = Payload URL
+TeamName = Team name
 
 require_error = ` cannot be empty.`
 alpha_dash_error = ` must be valid alpha or numeric or dash(-_) characters.`
@@ -94,16 +95,19 @@ password_not_match = Password and re-type password are not same.
 username_been_taken = Username has been already taken.
 repo_name_been_taken = Repository name has been already taken.
 org_name_been_taken = Organization name has been already taken.
+team_name_been_taken = Team name has been already taken.
 email_been_used = E-mail address has been already used.
 ssh_key_been_used = Public key name has been used.
 illegal_username = Your username contains illegal characters.
 illegal_repo_name = Repository name contains illegal characters.
 illegal_org_name = Organization name contains illegal characters.
+illegal_team_name = Team name contains illegal characters.
 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 password is correct.
 user_not_exist = Given user does not exist.
+last_org_owner = The user to remove is the last member in owner team. There must be another owner.
 
 invalid_ssh_key = Sorry, we're not able to verify your SSH key: %s
 auth_failed = Authentication failed: %v
@@ -237,6 +241,11 @@ lower_members = members
 lower_repositories = repositories
 create_new_team = Create New Team
 org_desc = Description
+team_name = Team Name
+team_desc = Description
+team_name_helper = You'll use this name to mention this team in conversations.
+team_desc_helper = What is this team all about?
+team_permission_desc = What permission level should this team have?
 
 settings = Settings
 settings.options = Options
@@ -258,9 +267,19 @@ members.owner = Owner
 members.member = Member
 members.conceal = Conceal
 members.remove = Remove
+members.leave = Leave
 members.invite_desc = Start typing a username to invite a new member to %s:
 members.invite_now = Invite Now
 
+teams.join = Join
+teams.leave = Leave
+teams.read_access = Read Access
+teams.read_access_helper = This team will be able to view and clone its repositories.
+teams.write_access = Write Access
+teams.write_access_helper = This team will be able to read its repositories, as well as push to them.
+teams.admin_access = Admin Access
+teams.admin_access_helper = This team will be able to push/pull to its repositories, as well as add other collaborators to them.
+
 [action]
 create_repo = created repository <a href="/%s">%s</a>
 commit_repo = pushed to <a href="/%s/src/%s">%s</a> at <a href="/%s">%s</a>
index b84aca3d9e8047c21b04fdb2f7e79e7bcc9bd596..e3607d8e6e7c1f0c333a7c454b747a0a80996774 100644 (file)
@@ -79,6 +79,7 @@ Retype = 确认密码
 SSHTitle = SSH 密钥名称
 HttpsUrl = HTTPS URL 地址
 PayloadUrl = 推送地址
+TeamName = 团队名称
 
 require_error = 不能为空。
 alpha_dash_error = 必须为英文字母、阿拉伯数字或横线(-_)。
@@ -94,16 +95,19 @@ password_not_match = 密码与确认密码未匹配。
 username_been_taken = 用户名已经被占用。
 repo_name_been_taken = 仓库名称已经被占用。
 org_name_been_taken = 组织名称已经被占用。
+team_name_been_taken = 团队名称已经被占用。
 email_been_used = 邮箱地址已经被使用。
 ssh_key_been_used = SSH 密钥已经被使用。
 illegal_username = 您的用户名包含非法字符。
 illegal_repo_name = 仓库名称包含非法字符。
 illegal_org_name = 组织名称包含非法字符。
+illegal_team_name = 团队名称包含非法字符。
 username_password_incorrect = 用户名或密码不正确。
 enterred_invalid_repo_name = 请检查您输入的仓库名称是正确。
 enterred_invalid_owner_name = 请检查您输入的新所有者用户名是否正确。
 enterred_invalid_password = 请检查您输入的密码是否正确。
 user_not_exist = 被操作的用户不存在!
+last_org_owner = 被移除用户为最后一位管理员。请添加一位新的管理员再进行移除成员操作!
 
 invalid_ssh_key = 很抱歉,我们无法验证您输入的 SSH 密钥:%s
 auth_failed = 授权验证失败:%v
@@ -237,6 +241,11 @@ lower_members = 名成员
 lower_repositories = 个仓库
 create_new_team = 创建新的团队
 org_desc = 组织描述
+team_name = 团队名称
+team_desc = 团队描述
+team_name_helper = 您可以使用该名称来通知改组全体成员。
+team_desc_helper = 一句话描述这个团队是做什么的。
+team_permission_desc = 请选择该团队所具有的权限等级:
 
 settings = 组织设置
 settings.options = 基本设置
@@ -258,9 +267,19 @@ members.owner = 管理员
 members.member = 普通成员
 members.conceal = 隐藏身份
 members.remove = 移除成员
+members.leave = 离开组织
 members.invite_desc = 请输入被邀请到组织 %s 的用户名称:
 members.invite_now = 立即邀请
 
+teams.join = 加入团队
+teams.leave = 离开团队
+teams.read_access = 读取权限
+teams.read_access_helper = 这个团队将拥有查看和克隆所属仓库的权限。
+teams.write_access =  写入权限
+teams.write_access_helper = 这个团队将拥有查看、克隆和推送所属仓库的权限。
+teams.admin_access = 管理权限
+teams.admin_access_helper = 这个团队将拥有查看、克隆、推送和添加其他组织成员到团队的权限。
+
 [action]
 create_repo = 创建了仓库 <a href="/%s">%s</a>
 commit_repo = 推送了 <a href="/%s/src/%s">%s</a> 分支的代码到 <a href="/%s">%s</a>
diff --git a/gogs.go b/gogs.go
index 6a9ded37d50365fef337322eb27a5b420865cf90..f20f0a10d0449ee304bac0fb36479e2075c7d16f 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.0815 Alpha"
+const APP_VER = "0.4.7.0816 Alpha"
 
 func init() {
        runtime.GOMAXPROCS(runtime.NumCPU())
index b40b313bc37faa3a215ee690eb08e14e86c82cad..b8104222804d7bfcacce2e46a65d7e622c87e650 100644 (file)
@@ -15,6 +15,9 @@ import (
 var (
        ErrOrgNotExist      = errors.New("Organization does not exist")
        ErrTeamAlreadyExist = errors.New("Team already exist")
+       ErrTeamNotExist     = errors.New("Team does not exist")
+       ErrTeamNameIllegal  = errors.New("Team name contains illegal characters")
+       ErrLastOrgOwner     = errors.New("The user to remove is the last member in owner team")
 )
 
 // IsOrgOwner returns true if given user is in the owner team.
@@ -27,14 +30,14 @@ func (org *User) IsOrgMember(uid int64) bool {
        return IsOrganizationMember(org.Id, uid)
 }
 
+// GetTeam returns named team of organization.
+func (org *User) GetTeam(name string) (*Team, error) {
+       return GetTeam(org.Id, name)
+}
+
 // GetOwnerTeam returns owner team of organization.
 func (org *User) GetOwnerTeam() (*Team, error) {
-       t := &Team{
-               OrgId: org.Id,
-               Name:  OWNER_TEAM,
-       }
-       _, err := x.Get(t)
-       return t, err
+       return org.GetTeam(OWNER_TEAM)
 }
 
 // GetTeams returns all teams that belong to organization.
@@ -179,96 +182,6 @@ func DeleteOrganization(org *User) (err error) {
        return sess.Commit()
 }
 
-// ___________
-// \__    ___/___ _____    _____
-//   |    |_/ __ \\__  \  /     \
-//   |    |\  ___/ / __ \|  Y Y  \
-//   |____| \___  >____  /__|_|  /
-//              \/     \/      \/
-
-type AuthorizeType int
-
-const (
-       ORG_READABLE AuthorizeType = iota + 1
-       ORG_WRITABLE
-       ORG_ADMIN
-)
-
-const OWNER_TEAM = "Owners"
-
-// Team represents a organization team.
-type Team struct {
-       Id          int64
-       OrgId       int64 `xorm:"INDEX"`
-       LowerName   string
-       Name        string
-       Description string
-       Authorize   AuthorizeType
-       RepoIds     string `xorm:"TEXT"`
-       NumMembers  int
-       NumRepos    int
-       Members     []*User `xorm:"-"`
-}
-
-// IsTeamMember returns true if given user is a member of team.
-func (t *Team) IsMember(uid int64) bool {
-       return IsTeamMember(t.OrgId, t.Id, uid)
-}
-
-// GetMembers returns all members in given team of organization.
-func (t *Team) GetMembers() (err error) {
-       t.Members, err = GetTeamMembers(t.OrgId, t.Id)
-       return err
-}
-
-// NewTeam creates a record of new team.
-// It's caller's responsibility to assign organization ID.
-func NewTeam(t *Team) error {
-       has, err := x.Id(t.OrgId).Get(new(User))
-       if err != nil {
-               return err
-       } else if !has {
-               return ErrOrgNotExist
-       }
-
-       t.LowerName = strings.ToLower(t.Name)
-       has, err = x.Where("org_id=?", t.OrgId).And("lower_name=?", t.LowerName).Get(new(Team))
-       if err != nil {
-               return err
-       } else if has {
-               return ErrTeamAlreadyExist
-       }
-
-       sess := x.NewSession()
-       defer sess.Close()
-       if err = sess.Begin(); err != nil {
-               return err
-       }
-
-       if _, err = sess.Insert(t); err != nil {
-               sess.Rollback()
-               return err
-       }
-
-       // Update organization number of teams.
-       if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgId); err != nil {
-               sess.Rollback()
-               return err
-       }
-       return sess.Commit()
-}
-
-// UpdateTeam updates information of team.
-func UpdateTeam(t *Team) error {
-       if len(t.Description) > 255 {
-               t.Description = t.Description[:255]
-       }
-
-       t.LowerName = strings.ToLower(t.Name)
-       _, err := x.Id(t.Id).AllCols().Update(t)
-       return err
-}
-
 // ________                ____ ___
 // \_____  \_______  ____ |    |   \______ ___________
 //  /   |   \_  __ \/ ___\|    |   /  ___// __ \_  __ \
@@ -372,6 +285,21 @@ func RemoveOrgUser(orgId, uid int64) error {
                return nil
        }
 
+       // Check if the user to delete is the last member in owner team.
+       if IsOrganizationOwner(orgId, uid) {
+               org, err := GetUserById(orgId)
+               if err != nil {
+                       return err
+               }
+               t, err := org.GetOwnerTeam()
+               if err != nil {
+                       return err
+               }
+               if t.NumMembers == 1 {
+                       return ErrLastOrgOwner
+               }
+       }
+
        sess := x.NewSession()
        defer sess.Close()
        if err := sess.Begin(); err != nil {
@@ -389,6 +317,127 @@ func RemoveOrgUser(orgId, uid int64) error {
        return sess.Commit()
 }
 
+// ___________
+// \__    ___/___ _____    _____
+//   |    |_/ __ \\__  \  /     \
+//   |    |\  ___/ / __ \|  Y Y  \
+//   |____| \___  >____  /__|_|  /
+//              \/     \/      \/
+
+type AuthorizeType int
+
+const (
+       ORG_READABLE AuthorizeType = iota + 1
+       ORG_WRITABLE
+       ORG_ADMIN
+)
+
+const OWNER_TEAM = "Owners"
+
+// Team represents a organization team.
+type Team struct {
+       Id          int64
+       OrgId       int64 `xorm:"INDEX"`
+       LowerName   string
+       Name        string
+       Description string
+       Authorize   AuthorizeType
+       RepoIds     string `xorm:"TEXT"`
+       NumMembers  int
+       NumRepos    int
+       Members     []*User `xorm:"-"`
+}
+
+// IsTeamMember returns true if given user is a member of team.
+func (t *Team) IsMember(uid int64) bool {
+       return IsTeamMember(t.OrgId, t.Id, uid)
+}
+
+// GetMembers returns all members in given team of organization.
+func (t *Team) GetMembers() (err error) {
+       t.Members, err = GetTeamMembers(t.OrgId, t.Id)
+       return err
+}
+
+// NewTeam creates a record of new team.
+// It's caller's responsibility to assign organization ID.
+func NewTeam(t *Team) error {
+       if !IsLegalName(t.Name) {
+               return ErrTeamNameIllegal
+       }
+
+       has, err := x.Id(t.OrgId).Get(new(User))
+       if err != nil {
+               return err
+       } else if !has {
+               return ErrOrgNotExist
+       }
+
+       t.LowerName = strings.ToLower(t.Name)
+       has, err = x.Where("org_id=?", t.OrgId).And("lower_name=?", t.LowerName).Get(new(Team))
+       if err != nil {
+               return err
+       } else if has {
+               return ErrTeamAlreadyExist
+       }
+
+       sess := x.NewSession()
+       defer sess.Close()
+       if err = sess.Begin(); err != nil {
+               return err
+       }
+
+       if _, err = sess.Insert(t); err != nil {
+               sess.Rollback()
+               return err
+       }
+
+       // Update organization number of teams.
+       if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgId); err != nil {
+               sess.Rollback()
+               return err
+       }
+       return sess.Commit()
+}
+
+// GetTeam returns team by given team name and organization.
+func GetTeam(orgId int64, name string) (*Team, error) {
+       t := &Team{
+               OrgId:     orgId,
+               LowerName: strings.ToLower(name),
+       }
+       has, err := x.Get(t)
+       if err != nil {
+               return nil, err
+       } else if !has {
+               return nil, ErrTeamNotExist
+       }
+       return t, nil
+}
+
+// GetTeamById returns team by given ID.
+func GetTeamById(teamId int64) (*Team, error) {
+       t := new(Team)
+       has, err := x.Id(teamId).Get(t)
+       if err != nil {
+               return nil, err
+       } else if !has {
+               return nil, ErrTeamNotExist
+       }
+       return t, nil
+}
+
+// UpdateTeam updates information of team.
+func UpdateTeam(t *Team) error {
+       if len(t.Description) > 255 {
+               t.Description = t.Description[:255]
+       }
+
+       t.LowerName = strings.ToLower(t.Name)
+       _, err := x.Id(t.Id).AllCols().Update(t)
+       return err
+}
+
 // ___________                    ____ ___
 // \__    ___/___ _____    _____ |    |   \______ ___________
 //   |    |_/ __ \\__  \  /     \|    |   /  ___// __ \_  __ \
@@ -427,3 +476,68 @@ func GetTeamMembers(orgId, teamId int64) ([]*User, error) {
        }
        return us, nil
 }
+
+// AddTeamMember adds new member to given team of given organization.
+func AddTeamMember(orgId, teamId, uid int64) error {
+       if !IsOrganizationMember(orgId, uid) || IsTeamMember(orgId, teamId, uid) {
+               return nil
+       }
+
+       // We can use raw SQL here but we also want to vertify there is a such team.
+       t, err := GetTeamById(teamId)
+       if err != nil {
+               return err
+       }
+       t.NumMembers++
+
+       sess := x.NewSession()
+       defer sess.Close()
+       if err = sess.Begin(); err != nil {
+               return err
+       }
+
+       tu := &TeamUser{
+               Uid:    uid,
+               OrgId:  orgId,
+               TeamId: teamId,
+       }
+
+       if _, err = sess.Insert(tu); err != nil {
+               sess.Rollback()
+               return err
+       } else if _, err = sess.Id(t.Id).Update(t); err != nil {
+               sess.Rollback()
+               return err
+       }
+
+       return sess.Commit()
+}
+
+// RemoveMember removes member from given team of given organization.
+func RemoveMember(orgId, teamId, uid int64) error {
+       if !IsTeamMember(orgId, teamId, uid) {
+               return nil
+       }
+
+       sess := x.NewSession()
+       defer sess.Close()
+       if err := sess.Begin(); err != nil {
+               return err
+       }
+
+       tu := &TeamUser{
+               Uid:    uid,
+               OrgId:  orgId,
+               TeamId: teamId,
+       }
+
+       if _, err := sess.Delete(tu); err != nil {
+               sess.Rollback()
+               return err
+       } else if _, err = sess.Exec("UPDATE `team` SET num_members = num_members - 1 WHERE id = ?", teamId); err != nil {
+               sess.Rollback()
+               return err
+       }
+
+       return sess.Commit()
+}
index 9598e6f8342a3ee9645b0a18f40c146c665738dc..6183e8c826691e396ebd30058eb8fe8ac4e97d6d 100644 (file)
@@ -49,7 +49,7 @@ func (f *UpdateOrgSettingForm) Validate(ctx *macaron.Context, errs *binding.Erro
 //              \/     \/      \/
 
 type CreateTeamForm struct {
-       TeamName    string `form:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
+       TeamName    string `form:"team_name" binding:"Required;AlphaDashDot;MaxSize(30)"`
        Description string `form:"desc" binding:"MaxSize(255)"`
        Permission  string `form:"permission"`
 }
index 6ce0f6e1f790809a0525d7f1d320a66916d04755..80975e999e5846557f3fee34f0d6b1a1c2e98bca 100644 (file)
@@ -71,6 +71,8 @@ type Context struct {
                IsAdminTeam  bool // In owner team or team that has admin permission level.
                Organization *models.User
                OrgLink      string
+
+               Team *models.Team
        }
 }
 
index 77e999a328bce54b5d4d76ff1fb219587e71c532..c85221a5abbde0964b86bf3e0ef216288d790476 100644 (file)
@@ -41,15 +41,16 @@ func OrgAssignment(redirect bool, args ...bool) macaron.Handler {
                        }
                        return
                }
-               ctx.Data["Org"] = ctx.Org.Organization
+               org := ctx.Org.Organization
+               ctx.Data["Org"] = org
 
                if ctx.IsSigned {
-                       ctx.Org.IsOwner = ctx.Org.Organization.IsOrgOwner(ctx.User.Id)
+                       ctx.Org.IsOwner = org.IsOrgOwner(ctx.User.Id)
                        if ctx.Org.IsOwner {
                                ctx.Org.IsMember = true
                                ctx.Org.IsAdminTeam = true
                        } else {
-                               if ctx.Org.Organization.IsOrgMember(ctx.User.Id) {
+                               if org.IsOrgMember(ctx.User.Id) {
                                        ctx.Org.IsMember = true
                                        // TODO: ctx.Org.IsAdminTeam
                                }
@@ -64,7 +65,24 @@ func OrgAssignment(redirect bool, args ...bool) macaron.Handler {
                ctx.Data["IsAdminTeam"] = ctx.Org.IsAdminTeam
                ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
 
-               ctx.Org.OrgLink = "/org/" + ctx.Org.Organization.Name
+               ctx.Org.OrgLink = "/org/" + org.Name
                ctx.Data["OrgLink"] = ctx.Org.OrgLink
+
+               // Team.
+               teamName := ctx.Params(":team")
+               if len(teamName) > 0 {
+                       ctx.Org.Team, err = org.GetTeam(teamName)
+                       if err != nil {
+                               if err == models.ErrTeamNotExist {
+                                       ctx.Handle(404, "GetTeam", err)
+                               } else if redirect {
+                                       ctx.Redirect("/")
+                               } else {
+                                       ctx.Handle(500, "GetTeam", err)
+                               }
+                               return
+                       }
+                       ctx.Data["Team"] = ctx.Org.Team
+               }
        }
 }
index 6b400df28c066fc5b8dc97b9c0e703b45c8e759a..3d784fab2196d9783fdfa08ffe70ac40c4b906ba 100644 (file)
@@ -1172,28 +1172,34 @@ The register and sign-in page style
   width: 520px;
 }
 /* repository create */
+#team-create-form,
 #repo-migrate-form,
 #repo-create-form {
   width: 800px;
   margin: 60px auto auto auto;
   background: white;
 }
+#team-create-form h2,
 #repo-migrate-form h2,
 #repo-create-form h2 {
   margin: .5em 1em;
 }
+#team-create-form .field,
 #repo-migrate-form .field,
 #repo-create-form .field {
   margin: 1.2em 0 2em 0;
 }
+#team-create-form .ipt,
 #repo-migrate-form .ipt,
 #repo-create-form .ipt {
   width: 540px;
 }
+#team-create-form textarea,
 #repo-migrate-form textarea,
 #repo-create-form textarea {
   height: 120px;
 }
+#team-create-form .avatar,
 #repo-migrate-form .avatar,
 #repo-create-form .avatar {
   vertical-align: middle;
@@ -1201,6 +1207,7 @@ The register and sign-in page style
   width: 28px;
   height: 28px;
 }
+#team-create-form:hover,
 #repo-migrate-form:hover,
 #repo-create-form:hover {
   box-shadow: 0px 0px 6px #CCC;
@@ -1681,6 +1688,9 @@ textarea#issue-add-content {
   box-sizing: border-box;
   height: 120px;
 }
+.org-header-alert .alert {
+  margin-top: 10px;
+}
 .org-header {
   padding: 16px 0;
   background-color: #FFF;
@@ -1767,10 +1777,10 @@ textarea#issue-add-content {
 .org-sidebar .panel-footer {
   padding: .8em 1.2em;
 }
-#org-member-avatar-group {
+.org-sidebar .member-avatar-group {
   padding: 15px;
 }
-#org-member-avatar-group img {
+.org-sidebar .member-avatar-group img {
   width: 59px;
   height: 59px;
   border-radius: 3px;
@@ -1801,13 +1811,14 @@ textarea#issue-add-content {
   margin-bottom: 0;
   color: #777;
 }
-#org-member-toolbar {
+.org-toolbar {
   padding: 10px 0;
+  border-bottom: 1px solid #eee;
 }
 #org-member-list .org-member-item {
   height: 50px;
   line-height: 50px;
-  border-top: 1px solid #eee;
+  border-bottom: 1px solid #eee;
   padding: 15px 20px;
 }
 #org-member-list .org-member-item .member-name {
@@ -1832,3 +1843,19 @@ textarea#issue-add-content {
 #org-member-list-block {
   padding-top: 2px;
 }
+.org-team-list .org-team-list-item {
+  float: left;
+  padding: 15px;
+  width: 555px;
+}
+.org-team-list .org-team-list-item .member-avatar-group {
+  padding: 5px 15px;
+}
+.org-team-list .org-team-list-item .member-avatar-group img {
+  width: 38px;
+  height: 38px;
+  border-radius: 3px;
+}
+#team-create-form .note {
+  margin-left: 153px;
+}
index 380582953219adfb268e66364952e82522ef70a0..e8063f2328342f77d3a0099581f724d45d531ff8 100644 (file)
@@ -1,3 +1,6 @@
+.org-header-alert .alert {
+       margin-top: 10px;
+}
 .org-header {
        padding: 16px 0;
        background-color: #FFF;
        .panel-footer {
                padding: .8em 1.2em;
        }
-}
-#org-member-avatar-group {
-       padding: 15px;
-       img {
-               width: 59px;
-               height: 59px;
-               border-radius: 3px;
+       .member-avatar-group {
+               padding: 15px;
+               img {
+                       width: 59px;
+                       height: 59px;
+                       border-radius: 3px;
+               }
        }
 }
 #org-home-team-list {
        margin-bottom: 0;
        color: #777;
 }
-#org-member-toolbar {
+.org-toolbar {
        padding: 10px 0;
+       border-bottom: 1px solid #eee;
 }
 #org-member-list {
        .org-member-item {
                height: 50px;
                line-height: 50px;
-               border-top: 1px solid #eee;
+               border-bottom: 1px solid #eee;
                padding: 15px 20px;
                .member-name {
                        padding-left: 15px;
 }
 #org-member-list-block {
        padding-top: 2px;
+}
+.org-team-list {
+       .org-team-list-item {
+               float: left;
+               padding: 15px;
+               width: 555px;
+               .member-avatar-group {
+                       padding: 5px 15px;
+                       img {
+                               width: 38px;
+                               height: 38px;
+                               border-radius: 3px;
+                       }
+               }
+       }
+}
+#team-create-form {
+       .note {
+               margin-left: 153px;
+       }
 }
\ No newline at end of file
index 0aa19a04a940fd6040f8cff667feda786a695721..8f9a97fa02a6c23f3ca74957d8e7115bbd3aab1c 100644 (file)
@@ -310,6 +310,7 @@ border-top-right-radius: .25em;
 }
 /* repository create */
 
+#team-create-form,
 #repo-migrate-form,
 #repo-create-form {
        width: 800px;
index d98061765aea30cec691772c8684f3203b96f710..1e249e8be2e86c4346ee12cf28ceb3792e3f38f2 100644 (file)
@@ -14,13 +14,13 @@ import (
 )
 
 const (
-       MEMBERS base.TplName = "org/members"
-       INVITE  base.TplName = "org/invite"
+       MEMBERS       base.TplName = "org/member/members"
+       MEMBER_INVITE base.TplName = "org/member/invite"
 )
 
 func Members(ctx *middleware.Context) {
        org := ctx.Org.Organization
-       ctx.Data["Title"] = org.Name
+       ctx.Data["Title"] = org.FullName
        ctx.Data["PageIsOrgMembers"] = true
 
        if err := org.GetMembers(); err != nil {
@@ -60,6 +60,18 @@ func MembersAction(ctx *middleware.Context) {
                        return
                }
                err = org.RemoveMember(uid)
+               if err == models.ErrLastOrgOwner {
+                       ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
+                       ctx.Redirect(ctx.Org.OrgLink + "/members")
+                       return
+               }
+       case "leave":
+               err = org.RemoveMember(ctx.User.Id)
+               if err == models.ErrLastOrgOwner {
+                       ctx.Flash.Error(ctx.Tr("form.last_org_owner"))
+                       ctx.Redirect(ctx.Org.OrgLink + "/members")
+                       return
+               }
        }
 
        if err != nil {
@@ -75,7 +87,7 @@ func MembersAction(ctx *middleware.Context) {
 
 func Invitation(ctx *middleware.Context) {
        org := ctx.Org.Organization
-       ctx.Data["Title"] = org.Name
+       ctx.Data["Title"] = org.FullName
        ctx.Data["PageIsOrgMembers"] = true
 
        if ctx.Req.Method == "POST" {
@@ -101,5 +113,5 @@ func Invitation(ctx *middleware.Context) {
                return
        }
 
-       ctx.HTML(200, INVITE)
+       ctx.HTML(200, MEMBER_INVITE)
 }
index 254ba8148f9745405ad4fff51a0143a04af57262..27ccf02d3f2e7f106b7c0cfdf581dc98e19e21e0 100644 (file)
@@ -19,7 +19,7 @@ const (
 
 func Home(ctx *middleware.Context) {
        org := ctx.Org.Organization
-       ctx.Data["Title"] = org.Name
+       ctx.Data["Title"] = org.FullName
 
        repos, err := models.GetRepositories(org.Id, ctx.IsSigned && org.IsOrgMember(ctx.User.Id))
        if err != nil {
index d494ddc04d7e0d548a26cf01891ffb2f7cfaca28..bc12a971604805805f78a72e376d955ea61d2abe 100644 (file)
@@ -13,31 +13,22 @@ import (
 )
 
 const (
-       TEAMS    base.TplName = "org/teams"
-       TEAM_NEW base.TplName = "org/team_new"
+       TEAMS    base.TplName = "org/team/teams"
+       TEAM_NEW base.TplName = "org/team/new"
 )
 
 func Teams(ctx *middleware.Context) {
-       ctx.Data["Title"] = "Organization " + ctx.Params(":org") + " Teams"
+       org := ctx.Org.Organization
+       ctx.Data["Title"] = org.FullName
+       ctx.Data["PageIsOrgTeams"] = true
 
-       org, err := models.GetUserByName(ctx.Params(":org"))
-       if err != nil {
-               if err == models.ErrUserNotExist {
-                       ctx.Handle(404, "org.Teams(GetUserByName)", err)
-               } else {
-                       ctx.Handle(500, "org.Teams(GetUserByName)", err)
-               }
-               return
-       }
-       ctx.Data["Org"] = org
-
-       if err = org.GetTeams(); err != nil {
-               ctx.Handle(500, "org.Teams(GetTeams)", err)
+       if err := org.GetTeams(); err != nil {
+               ctx.Handle(500, "GetTeams", err)
                return
        }
        for _, t := range org.Teams {
-               if err = t.GetMembers(); err != nil {
-                       ctx.Handle(500, "org.Home(GetMembers)", err)
+               if err := t.GetMembers(); err != nil {
+                       ctx.Handle(500, "GetMembers", err)
                        return
                }
        }
@@ -46,44 +37,39 @@ func Teams(ctx *middleware.Context) {
        ctx.HTML(200, TEAMS)
 }
 
-func NewTeam(ctx *middleware.Context) {
-       org, err := models.GetUserByName(ctx.Params(":org"))
-       if err != nil {
-               if err == models.ErrUserNotExist {
-                       ctx.Handle(404, "org.NewTeam(GetUserByName)", err)
-               } else {
-                       ctx.Handle(500, "org.NewTeam(GetUserByName)", err)
-               }
-               return
+func TeamsAction(ctx *middleware.Context) {
+       var err error
+       switch ctx.Params(":action") {
+       case "join":
+               err = models.AddTeamMember(ctx.Org.Organization.Id, ctx.Org.Team.Id, ctx.User.Id)
+       case "leave":
+               err = models.RemoveMember(ctx.Org.Organization.Id, ctx.Org.Team.Id, ctx.User.Id)
        }
-       ctx.Data["Org"] = org
 
-       // Check ownership of organization.
-       if !org.IsOrgOwner(ctx.User.Id) {
-               ctx.Error(403)
+       if err != nil {
+               log.Error(4, "Action(%s): %v", ctx.Params(":action"), err)
+               ctx.JSON(200, map[string]interface{}{
+                       "ok":  false,
+                       "err": err.Error(),
+               })
                return
        }
+       ctx.Redirect(ctx.Org.OrgLink + "/teams")
+}
 
+func NewTeam(ctx *middleware.Context) {
+       ctx.Data["Title"] = ctx.Org.Organization.FullName
+       ctx.Data["PageIsOrgTeams"] = true
+       ctx.Data["PageIsOrgTeamsNew"] = true
+       ctx.Data["Team"] = &models.Team{}
        ctx.HTML(200, TEAM_NEW)
 }
 
 func NewTeamPost(ctx *middleware.Context, form auth.CreateTeamForm) {
-       org, err := models.GetUserByName(ctx.Params(":org"))
-       if err != nil {
-               if err == models.ErrUserNotExist {
-                       ctx.Handle(404, "org.NewTeamPost(GetUserByName)", err)
-               } else {
-                       ctx.Handle(500, "org.NewTeamPost(GetUserByName)", err)
-               }
-               return
-       }
-       ctx.Data["Org"] = org
-
-       // Check ownership of organization.
-       if !org.IsOrgOwner(ctx.User.Id) {
-               ctx.Error(403)
-               return
-       }
+       ctx.Data["Title"] = ctx.Org.Organization.FullName
+       ctx.Data["PageIsOrgTeams"] = true
+       ctx.Data["PageIsOrgTeamsNew"] = true
+       ctx.Data["Team"] = &models.Team{}
 
        if ctx.HasError() {
                ctx.HTML(200, TEAM_NEW)
@@ -104,23 +90,29 @@ func NewTeamPost(ctx *middleware.Context, form auth.CreateTeamForm) {
                return
        }
 
+       org := ctx.Org.Organization
+
        t := &models.Team{
                OrgId:       org.Id,
                Name:        form.TeamName,
                Description: form.Description,
                Authorize:   auth,
        }
-       if err = models.NewTeam(t); err != nil {
-               if err == models.ErrTeamAlreadyExist {
+       if err := models.NewTeam(t); err != nil {
+               switch err {
+               case models.ErrTeamNameIllegal:
+                       ctx.Data["Err_TeamName"] = true
+                       ctx.RenderWithErr(ctx.Tr("form.illegal_team_name"), TEAM_NEW, &form)
+               case models.ErrTeamAlreadyExist:
                        ctx.Data["Err_TeamName"] = true
-                       ctx.RenderWithErr("Team name has already been used", TEAM_NEW, &form)
-               } else {
-                       ctx.Handle(500, "org.NewTeamPost(NewTeam)", err)
+                       ctx.RenderWithErr(ctx.Tr("form.team_name_been_taken"), TEAM_NEW, &form)
+               default:
+                       ctx.Handle(500, "NewTeam", err)
                }
                return
        }
-       log.Trace("%s Team created: %s/%s", ctx.Req.RequestURI, org.Name, t.Name)
-       ctx.Redirect("/org/" + org.LowerName + "/teams/" + t.LowerName)
+       log.Trace("Team created: %s/%s", org.Name, t.Name)
+       ctx.Redirect(ctx.Org.OrgLink + "/teams/" + t.LowerName)
 }
 
 func EditTeam(ctx *middleware.Context) {
index 404b22f24d236f954b79364c9d81a4868a6cdbda..231ee66279b0758d9aeccd07f30756f5d77dd1c3 100644 (file)
@@ -20,12 +20,11 @@ import (
 )
 
 const (
-       SIGNIN          base.TplName = "user/signin"
-       SIGNUP          base.TplName = "user/signup"
-       DELETE          base.TplName = "user/delete"
-       ACTIVATE        base.TplName = "user/activate"
-       FORGOT_PASSWORD base.TplName = "user/forgot_passwd"
-       RESET_PASSWORD  base.TplName = "user/reset_passwd"
+       SIGNIN          base.TplName = "user/auth/signin"
+       SIGNUP          base.TplName = "user/auth/signup"
+       ACTIVATE        base.TplName = "user/auth/activate"
+       FORGOT_PASSWORD base.TplName = "user/auth/forgot_passwd"
+       RESET_PASSWORD  base.TplName = "user/auth/reset_passwd"
 )
 
 func SignIn(ctx *middleware.Context) {
index 906c01dc84b38f461651e515d66f7d018740dc72..48fe58b179c6f584b1da7572aa8c49f6ded2a2b5 100644 (file)
@@ -1 +1 @@
-0.4.7.0815 Alpha
\ No newline at end of file
+0.4.7.0816 Alpha
\ No newline at end of file
diff --git a/templates/org/base/header.tmpl b/templates/org/base/header.tmpl
new file mode 100644 (file)
index 0000000..8566d0a
--- /dev/null
@@ -0,0 +1,16 @@
+<div class="org-header" id="org-header">
+       <div class="container">
+               <a class="text-black left" href="/org/{{.Org.LowerName}}">
+                       <img class="avatar-48 left" src="{{.Org.AvatarLink}}?s=100">
+                       <span class="org-name">{{.Org.FullName}}</span>
+               </a>
+               <ul class="menu menu-line container">
+                       <li class="right">
+                               <a {{if .PageIsOrgTeams}}class="current"{{end}} href="{{.OrgLink}}/teams"><i class="octicon octicon-jersey"></i> {{.i18n.Tr "org.teams"}} <span class="label label-gray label-radius">{{.Org.NumTeams}}</span></a>
+                       </li>
+                       <li class="right">
+                               <a {{if .PageIsOrgMembers}}class="current"{{end}} href="{{.OrgLink}}/members"><i class="octicon octicon-organization"></i> {{.i18n.Tr "org.people"}} <span class="label label-gray label-radius">{{.Org.NumMembers}}</span></a>
+                       </li>
+               </ul>
+       </div>
+</div>
\ No newline at end of file
diff --git a/templates/org/header.tmpl b/templates/org/header.tmpl
deleted file mode 100644 (file)
index 8566d0a..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-<div class="org-header" id="org-header">
-       <div class="container">
-               <a class="text-black left" href="/org/{{.Org.LowerName}}">
-                       <img class="avatar-48 left" src="{{.Org.AvatarLink}}?s=100">
-                       <span class="org-name">{{.Org.FullName}}</span>
-               </a>
-               <ul class="menu menu-line container">
-                       <li class="right">
-                               <a {{if .PageIsOrgTeams}}class="current"{{end}} href="{{.OrgLink}}/teams"><i class="octicon octicon-jersey"></i> {{.i18n.Tr "org.teams"}} <span class="label label-gray label-radius">{{.Org.NumTeams}}</span></a>
-                       </li>
-                       <li class="right">
-                               <a {{if .PageIsOrgMembers}}class="current"{{end}} href="{{.OrgLink}}/members"><i class="octicon octicon-organization"></i> {{.i18n.Tr "org.people"}} <span class="label label-gray label-radius">{{.Org.NumMembers}}</span></a>
-                       </li>
-               </ul>
-       </div>
-</div>
\ No newline at end of file
index d96624010f23718f2fcf2545f2f6331100b325c8..afd695ec7d6b37e5a7be329d9366853a76778aef 100644 (file)
@@ -4,7 +4,10 @@
        <div class="container clear">
                <img class="avatar-100 left" src="{{.Org.AvatarLink}}?s=140"/>
                <div id="org-home-header-info">
-                       <h2>{{.Org.FullName}} <a class="text-grey" href="/org/{{.Org.LowerName}}/settings"><span class="octicon octicon-gear"></span></a></h2>
+                       <h2>
+                               {{.Org.FullName}}
+                               {{if .IsOrganizationOwner}}<a class="text-grey" href="{{.OrgLink}}/settings"><span class="octicon octicon-gear"></span></a>{{end}}
+                       </h2>
                        {{if .Org.Description}}<p>{{.Org.Description}}</p>{{end}}
             <ul class="text-grey">
                 {{if .Org.Location}}<li><span class="octicon octicon-location"></span> <span>{{.Org.Location}}</span></li>{{end}}
@@ -17,7 +20,7 @@
 <div class="container">
     <div id="org-home-repo-list" class="left grid-2-3">
         <div class="clear">
-               {{if .IsAdminTeam}}
+               {{if .IsOrganizationOwner}}
             <a class="btn btn-green btn-large btn-link btn-radius right" href="/repo/create?org={{.Org.Id}}"><i class="octicon octicon-repo-create"></i> {{.i18n.Tr "new_repo"}}</a>
                {{end}}
         </div>
                                <a class="text-grey right" href="/org/{{.Org.LowerName}}/members"><strong>{{.Org.NumMembers}}</strong><span class="octicon octicon-chevron-right"></span></a>
                                <strong>{{.i18n.Tr "org.people"}}</strong>
                        </div>
-                       <div class="panel-body" id="org-member-avatar-group">
+                       <div class="panel-body member-avatar-group">
                                {{range .Members}}
-                               <a href="/{{.Name}}"><img src="{{.AvatarLink}}"></a>
+                               <a href="/{{.Name}}" title="{{.Name}}"><img src="{{.AvatarLink}}"></a>
                                {{end}}
                        </div>
-                       {{if .IsAdminTeam}}
+                       {{if .IsOrganizationOwner}}
                        <div class="panel-footer">
                                <a class="btn btn-medium btn-blue btn-link btn-radius" href="/org/{{.Org.LowerName}}/invitations/new">{{.i18n.Tr "org.invite_someone"}}</a>
                        </div>
diff --git a/templates/org/invite.tmpl b/templates/org/invite.tmpl
deleted file mode 100644 (file)
index b9901ae..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{{template "ng/base/head" .}}
-{{template "ng/base/header" .}}
-{{template "org/header" .}}
-<div class="container">
-       <div class="invite-box" id="invite-box">
-       {{template "ng/base/alert" .}}
-               <h3>{{.i18n.Tr "org.members.invite_desc" .Org.FullName}}</h3>
-               <form id="invite-member-form" action="{{.OrgLink}}/invitations/new" method="post">
-                       {{.CsrfTokenHtml}}
-                       <input class="ipt ipt-large ipt-radius" id="org-member-invite" name="uname" autocomplete="off" required>
-                       <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "org.members.invite_now"}}</button>
-                       <div id="org-member-list-block">
-                               <ul class="menu-down-show menu-vertical menu-radius switching-list user-list" id="org-member-invite-list"></ul>
-                       </div>
-               </form>
-       </div>
-</div>
-{{template "ng/base/footer" .}}
\ No newline at end of file
diff --git a/templates/org/member/invite.tmpl b/templates/org/member/invite.tmpl
new file mode 100644 (file)
index 0000000..bff1b98
--- /dev/null
@@ -0,0 +1,18 @@
+{{template "ng/base/head" .}}
+{{template "ng/base/header" .}}
+{{template "org/base/header" .}}
+<div class="container">
+       <div class="invite-box" id="invite-box">
+       {{template "ng/base/alert" .}}
+               <h3>{{.i18n.Tr "org.members.invite_desc" .Org.FullName}}</h3>
+               <form id="invite-member-form" action="{{.OrgLink}}/invitations/new" method="post">
+                       {{.CsrfTokenHtml}}
+                       <input class="ipt ipt-large ipt-radius" id="org-member-invite" name="uname" autocomplete="off" required>
+                       <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "org.members.invite_now"}}</button>
+                       <div id="org-member-list-block">
+                               <ul class="menu-down-show menu-vertical menu-radius switching-list user-list" id="org-member-invite-list"></ul>
+                       </div>
+               </form>
+       </div>
+</div>
+{{template "ng/base/footer" .}}
\ No newline at end of file
diff --git a/templates/org/member/members.tmpl b/templates/org/member/members.tmpl
new file mode 100644 (file)
index 0000000..3ab92bb
--- /dev/null
@@ -0,0 +1,49 @@
+{{template "ng/base/head" .}}
+{{template "ng/base/header" .}}
+{{template "org/base/header" .}}
+<div class="container">
+       <div class="org-header-alert">
+               {{template "ng/base/alert" .}}
+       </div>
+       <div class="org-toolbar clear">
+               {{if .IsAdminTeam}}
+        <a class="btn btn-green btn-large btn-link btn-radius right" href="{{.OrgLink}}/invitations/new"><i class="octicon octicon-repo-create"></i> {{.i18n.Tr "org.invite_someone"}}</a>
+               {{end}}
+       </div>
+       <div id="org-member-list">
+               {{range .Members}}
+               <div class="org-member-item">
+                       <img class="avatar-48 left" src="{{.AvatarLink}}?s=100">
+                       <a class="text-black" href="/{{.Name}}"><span class="member-name"><strong>{{.FullName}}</strong>({{.Name}})</span></a>
+                       <ul class="grid-6-12 right">
+                               <li class="grid-1-3">
+                               {{ $isPublic := .IsPublicMember $.Org.Id}}
+                               {{if $isPublic}}
+                                       {{$.i18n.Tr "org.members.public"}}
+                                       {{if eq $.SignedUser.Id .Id}}(<a href="{{$.OrgLink}}/members/action/private?uid={{.Id}}">{{$.i18n.Tr "org.members.public_helper"}}</a>){{end}}
+                               {{else}}
+                                       {{$.i18n.Tr "org.members.private"}}
+                                       {{if eq $.SignedUser.Id .Id}}(<a href="{{$.OrgLink}}/members/action/public?uid={{.Id}}">{{$.i18n.Tr "org.members.private_helper"}}</a>){{end}}
+                               {{end}}
+                               </li>
+                               <li class="grid-1-4">{{if .IsUserOrgOwner $.Org.Id}}<strong>{{$.i18n.Tr "org.members.owner"}}</strong>{{else}}{{$.i18n.Tr "org.members.member"}}{{end}}</li>
+                               {{if eq $.SignedUser.Id .Id}}
+                                       <li class="grid-1-6 right">
+                                               <a class="btn btn-red btn-link btn-radius" href="{{$.OrgLink}}/members/action/leave?uid={{.Id}}">{{$.i18n.Tr "org.members.leave"}}</a>
+                                       </li>
+                               {{else if $.IsOrganizationOwner}}
+                                       <li class="grid-1-6 right">
+                                               <a class="btn btn-red btn-link btn-radius" href="{{$.OrgLink}}/members/action/remove?uid={{.Id}}">{{$.i18n.Tr "org.members.remove"}}</a>
+                                       </li>
+                                       {{if $isPublic}}
+                                               <li class="grid-1-6 right">
+                                                       <a class="btn btn-blue btn-link btn-radius" href="{{$.OrgLink}}/members/action/private?uid={{.Id}}">{{$.i18n.Tr "org.members.conceal"}}</a>
+                                               </li>
+                                       {{end}}
+                               {{end}}
+                       </ul>
+               </div>
+               {{end}}
+       </div>
+</div>
+{{template "ng/base/footer" .}}
\ No newline at end of file
diff --git a/templates/org/members.tmpl b/templates/org/members.tmpl
deleted file mode 100644 (file)
index bea4340..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-{{template "ng/base/head" .}}
-{{template "ng/base/header" .}}
-{{template "org/header" .}}
-<div class="container">
-       {{template "ng/base/alert" .}}
-       <div class="clear" id="org-member-toolbar">
-               {{if .IsAdminTeam}}
-        <a class="btn btn-green btn-large btn-link btn-radius right" href="{{.OrgLink}}/invitations/new"><i class="octicon octicon-repo-create"></i> {{.i18n.Tr "org.invite_someone"}}</a>
-               {{end}}
-       </div>
-       <div id="org-member-list">
-               {{range .Members}}
-               <div class="org-member-item">
-                       <img class="avatar-48 left" src="{{.AvatarLink}}?s=100">
-                       <a class="text-black" href="/{{.Name}}"><span class="member-name"><strong>{{.FullName}}</strong>({{.Name}})</span></a>
-                       <ul class="grid-6-12 right">
-                               <li class="grid-1-3">
-                               {{ $isPublic := .IsPublicMember $.Org.Id}}
-                               {{if $isPublic}}
-                                       {{$.i18n.Tr "org.members.public"}}
-                                       {{if eq $.SignedUser.Id .Id}}(<a href="{{$.OrgLink}}/members/action/private?uid={{.Id}}">{{$.i18n.Tr "org.members.public_helper"}}</a>){{end}}
-                               {{else}}
-                                       {{$.i18n.Tr "org.members.private"}}
-                                       {{if eq $.SignedUser.Id .Id}}(<a href="{{$.OrgLink}}/members/action/public?uid={{.Id}}">{{$.i18n.Tr "org.members.private_helper"}}</a>){{end}}
-                               {{end}}
-                               </li>
-                               <li class="grid-1-4">{{if .IsUserOrgOwner $.Org.Id}}<strong>{{$.i18n.Tr "org.members.owner"}}</strong>{{else}}{{$.i18n.Tr "org.members.member"}}{{end}}</li>
-                               {{if $.IsOrganizationOwner}}
-                               <li class="grid-1-6 right">
-                                       <a class="btn btn-red btn-link btn-radius" href="{{$.OrgLink}}/members/action/remove?uid={{.Id}}">{{$.i18n.Tr "org.members.remove"}}</a>
-                               </li>
-                               {{if $isPublic}}
-                               <li class="grid-1-6 right">
-                                       <a class="btn btn-blue btn-link btn-radius" href="{{$.OrgLink}}/members/action/private?uid={{.Id}}">{{$.i18n.Tr "org.members.conceal"}}</a>
-                               </li>
-                               {{end}}
-                               {{end}}
-                       </ul>
-               </div>
-               {{end}}
-       </div>
-</div>
-{{template "ng/base/footer" .}}
\ No newline at end of file
index 7e24f85144c64f84678b59e37a44718ee59f1611..828389d6ffbc61eca130e29cf083189d2cc8fe4a 100644 (file)
@@ -1,5 +1,6 @@
 {{template "ng/base/head" .}}
 {{template "ng/base/header" .}}
+{{template "org/header" .}}
 <div id="setting-wrapper" class="main-wrapper">
     <div id="org-setting" class="container clear">
         {{template "org/settings/nav" .}}
index 7548ad5aef890abf65503b8553f53580622f219e..c5c6a7e221eb096334628a48134eb2c1c0217422 100644 (file)
@@ -1,5 +1,6 @@
 {{template "ng/base/head" .}}
 {{template "ng/base/header" .}}
+{{template "org/header" .}}
 <div id="setting-wrapper" class="main-wrapper">
     <div id="org-setting" class="container clear">
                {{template "org/settings/nav" .}}
diff --git a/templates/org/team/new.tmpl b/templates/org/team/new.tmpl
new file mode 100644 (file)
index 0000000..f02512e
--- /dev/null
@@ -0,0 +1,48 @@
+{{template "ng/base/head" .}}
+{{template "ng/base/header" .}}
+{{template "org/base/header" .}}
+<div id="repo-wrapper">
+    <form id="team-create-form" class="form form-align panel panel-radius" action="{{.OrgLink}}/teams/new" method="post">
+        {{.CsrfTokenHtml}}
+        <div class="panel-header">
+            <h2>{{.i18n.Tr "org.create_new_team"}}</h2>
+        </div>
+        <div class="panel-content">
+            {{template "ng/base/alert" .}}
+            <div class="field">
+                <label class="req" for="team-name">{{.i18n.Tr "org.team_name"}}</label>
+                <input class="ipt ipt-large ipt-radius {{if .Err_TeamName}}ipt-error{{end}}" id="team-name" name="team_name" value="{{.team_name}}" required />
+                <span class="form-label"></span>
+                <span class="help">{{.i18n.Tr "org.team_name_helper"}}</span>
+            </div>
+            <div class="field">
+                <label for="desc">{{.i18n.Tr "org.team_desc"}}</label>
+                <input class="ipt ipt-large ipt-radius {{if .Err_Description}}ipt-error{{end}}" id="desc" name="desc" value="{{.desc}}" />
+                <span class="form-label"></span>
+                <span class="help">{{.i18n.Tr "org.team_desc_helper"}}</span>
+            </div>
+            <div class="field">
+                <h4 class="text-center">{{.i18n.Tr "org.team_permission_desc"}}</h4>
+                <label></label>
+                <input name="permission" type="radio" value="read" {{if or .PageIsOrgTeamsNew (eq .Team.Authorize 1)}}checked{{end}}> {{.i18n.Tr "org.teams.read_access"}} 
+                <label></label>
+                <p class="text-grey note">{{.i18n.Tr "org.teams.read_access_helper"}}</p>
+                <label></label>
+                <input name="permission" type="radio" value="write" {{if eq .Team.Authorize 2}}checked{{end}}> {{.i18n.Tr "org.teams.write_access"}} 
+                <label></label>
+                <p class="text-grey note">{{.i18n.Tr "org.teams.write_access_helper"}}</p>
+                <label></label>
+                <input name="permission" type="radio" value="admin" {{if eq .Team.Authorize 3}}checked{{end}}> {{.i18n.Tr "org.teams.admin_access"}} 
+                <label></label>
+                <p class="text-grey note">{{.i18n.Tr "org.teams.admin_access_helper"}}</p>
+            </div>
+            <hr>
+            <div class="field">
+                <label></label>
+                <button class="btn btn-large btn-blue btn-radius">{{.i18n.Tr "org.create_new_team"}}</button>
+                <a class="btn btn-small btn-gray btn-radius" id="repo-create-cancel" href="{{.OrgLink}}/teams"><strong>{{.i18n.Tr "cancel"}}</strong></a>
+            </div>
+        </div>
+    </form>
+</div>
+{{template "ng/base/footer" .}}
\ No newline at end of file
diff --git a/templates/org/team/teams.tmpl b/templates/org/team/teams.tmpl
new file mode 100644 (file)
index 0000000..3e0846d
--- /dev/null
@@ -0,0 +1,42 @@
+{{template "ng/base/head" .}}
+{{template "ng/base/header" .}}
+{{template "org/base/header" .}}
+<div class="container">
+       <div class="org-header-alert">
+               {{template "ng/base/alert" .}}
+       </div>
+       <div class="org-toolbar clear">
+               {{if .IsAdminTeam}}
+        <a class="btn btn-green btn-large btn-link btn-radius right" href="{{.OrgLink}}/teams/new"><i class="octicon octicon-repo-create"></i> {{.i18n.Tr "org.create_new_team"}}</a>
+               {{end}}
+       </div>
+       <div class="org-team-list">
+               {{range .Teams}}
+               <div class="org-team-list-item">
+                       <div class="panel panel-radius">
+                               <div class="panel-header">
+                                       {{if .IsMember $.SignedUser.Id}}
+                    <a class="btn btn-small btn-red btn-header btn-radius right" href="{{$.OrgLink}}/teams/{{.LowerName}}/action/leave">{{$.i18n.Tr "org.teams.leave"}}</a>
+                    {{else}}
+                    <a class="btn btn-small btn-blue btn-header btn-radius right" href="{{$.OrgLink}}/teams/{{.LowerName}}/action/join">{{$.i18n.Tr "org.teams.join"}}</a>
+                    {{end}}
+                    <a class="text-black" href="{{$.OrgLink}}/teams/{{.LowerName}}"><strong>{{.Name}}</strong></a>
+                               </div>
+                               {{if .NumMembers}}
+                               <div class="panel-body member-avatar-group">
+                                       {{range .Members}}
+                                       <a href="/{{.Name}}" title="{{.Name}}">
+                                               <img src="{{.AvatarLink}}">
+                                       </a>
+                                       {{end}}
+                               </div>
+                               {{end}}
+                               <div class="panel-footer">
+                               <p class="team-meta">{{.NumMembers}} {{$.i18n.Tr "org.lower_members"}} · {{.NumRepos}} {{$.i18n.Tr "org.lower_repositories"}}</p>
+                               </div>
+                       </div>
+               </div>
+               {{end}}
+       </div>
+</div>
+{{template "ng/base/footer" .}}
\ No newline at end of file
diff --git a/templates/org/team_new.tmpl b/templates/org/team_new.tmpl
deleted file mode 100644 (file)
index 0936ec2..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-{{template "base/head" .}}
-{{template "base/navbar" .}}
-<div id="body-nav" class="org-nav org-nav-auto">
-    <div class="container clearfix">
-        <div id="org-nav-wrapper">
-            <ul class="nav nav-pills pull-right">
-                <li><a href="/org/{{.Org.Name}}/members"><i class="fa fa-users"></i>Members
-                    <span class="label label-default">{{.Org.NumMembers}}</span></a>
-                </li>
-                <li class="active"><a href="/org/{{.Org.Name}}/teams"><i class="fa fa-tags"></i>Teams
-                    <span class="label label-default">{{.Org.NumTeams}}</span></a>
-                </li>
-            </ul>
-            <img class="pull-left org-small-logo" src="{{.Org.AvatarLink}}?s=140" alt="" width="60"/>
-            <div id="org-nav-info">
-                <h2 class="org-name">{{.Org.FullName}}</h2>
-            </div>
-        </div>
-    </div>
-</div>
-
-<div id="body" class="container">
-    <div id="org">
-        <form action="/org/{{.Org.Name}}/teams/new" method="post" id="org-teams-create" class="form-horizontal card">
-            {{.CsrfTokenHtml}}
-            <h3>Create new team</h3>
-            {{template "base/alert" .}}
-            <div class="form-group{{if .Err_TeamName}} has-error has-feedback{{end}}">
-                <label class="col-md-2 control-label">Team Name<strong class="text-danger">*</strong></label>
-                <div class="col-md-8">
-                    <input name="name" type="text" class="form-control" placeholder="Type your team name" value="{{.name}}" required="required">
-                    <span class="help-block">You'll use this name to mention this team in conversations.</span>
-                </div>
-            </div>
-
-            <div class="form-group{{if .Err_Description}} has-error has-feedback{{end}}">
-                <label class="col-md-2 control-label">Description</label>
-                <div class="col-md-8">
-                    <input name="desc" type="text" class="form-control" placeholder="Type your team description (optional)" value="{{.desc}}">
-                </div>
-            </div>
-
-            <div class="form-group{{if .Err_Permission}} has-error has-feedback{{end}}">
-                <label class="col-md-2 control-label">Permission</label>
-                <div class="col-md-8">
-                    <div class="radio">
-                        <label>
-                            <input type="radio" name="permission" value="read" checked="">
-                            <strong>Read Access</strong>
-                        </label>
-                        <p>This team will be able to view and clone its repositories.</p>
-                    </div>
-                    <div class="radio">
-                        <label>
-                            <input type="radio" name="permission" value="write">
-                            <strong>Write Access</strong>
-                        </label>
-                        <p>This team will be able to read its repositories, as well as push to them.</p>
-                    </div>
-                    <div class="radio">
-                        <label>
-                            <input type="radio" name="permission" value="admin">
-                            <strong>Admin Access</strong>
-                        </label>
-                        <p>This team will be able to push/pull to its repositories, as well as add other collaborators to them.</p>
-                    </div>
-                </div>
-            </div>
-            <hr/>
-            <div class="form-group">
-                <label class="col-md-2">&nbsp;</label>
-                <div class="col-md-8">
-                    <button class="btn btn-primary">Create team</button>
-                </div>
-            </div>
-        </form>
-    </div>
-</div>
-{{template "base/footer" .}}
diff --git a/templates/org/teams.tmpl b/templates/org/teams.tmpl
deleted file mode 100644 (file)
index 90ee209..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-{{template "base/head" .}}
-{{template "base/navbar" .}}
-<div id="body-nav" class="org-nav org-nav-auto">
-    <div class="container clearfix">
-        <div id="org-nav-wrapper">
-            <ul class="nav nav-pills pull-right">
-                <li><a href="/org/{{.Org.Name}}/members"><i class="fa fa-users"></i>Members
-                    <span class="label label-default">{{.Org.NumMembers}}</span></a>
-                </li>
-                <li class="active"><a href="/org/{{.Org.Name}}/teams"><i class="fa fa-tags"></i>Teams
-                    <span class="label label-default">{{.Org.NumTeams}}</span></a>
-                </li>
-            </ul>
-            <img class="pull-left org-small-logo" src="{{.Org.AvatarLink}}?s=140" alt="" width="60"/>
-            <div id="org-nav-info">
-                <h2 class="org-name">{{.Org.FullName}}</h2>
-            </div>
-        </div>
-    </div>
-</div>
-
-<div id="body" class="container">
-    <div id="org">
-        <div id="org-teams">
-            <div id="org-teams-action">
-                <div class="col-md-12">
-                    <a href="/org/{{.Org.Name}}/teams/new"><button class="btn btn-success"><i class="fa fa-plus-square"></i>New Team</button></a>
-                    <hr/>
-                </div>
-            </div>
-            {{range .Teams}}
-            <div class="org-team col-md-6">
-                <div class="panel panel-default">
-                    <h2 class="panel-heading org-team-name"><a href="/org/{{$.Org.Name}}/teams/{{.LowerName}}"><strong>{{.Name}}</strong></a></h2>
-                    <div class="panel-body">
-                        <p class="org-team-meta">{{.NumMembers}} members · {{.NumRepos}} repositories</p>
-                        <p class="org-team-members">
-                            {{range .Members}}
-                            <a href="/user/{{.LowerName}}">
-                                <img class="img-thumbnail" src="{{.AvatarLink}}?s=60" alt=""/>
-                            </a>
-                            {{end}}
-                        </p>
-                    </div>
-                    <div class="panel-footer">
-                        {{if .IsMember $.SignedUser.Id}}
-                        <a class="pull-right btn btn-danger" href="/org/{{$.Org.Name}}/teams/{{.LowerName}}?action=leave">Leave</a>
-                        {{else}}
-                        <a class="pull-right btn btn-default" href="/org/{{$.Org.Name}}/teams/{{.LowerName}}?action=join">Join</a>
-                        {{end}}
-                    </div>
-                </div>
-            </div>
-            {{end}}
-        </div>
-    </div>
-</div>
-{{template "base/footer" .}}
index b5a8ea4e47ad7621440a5cdd1193b296355c4cae..6baa6d31e086ea461f63a38f451549c4f9422880 100644 (file)
@@ -3,7 +3,9 @@
 <div id="repo-wrapper">
     <form id="repo-create-form" class="form form-align panel panel-radius" action="/repo/create" method="post">
         {{.CsrfTokenHtml}}
-        <div class="panel-header"><h2>{{.i18n.Tr "new_repo"}}</h2></div>
+        <div class="panel-header">
+            <h2>{{.i18n.Tr "new_repo"}}</h2>
+        </div>
         <div class="panel-content">
             {{template "ng/base/alert" .}}
             <div class="field">
diff --git a/templates/user/activate.tmpl b/templates/user/activate.tmpl
deleted file mode 100644 (file)
index acdad9e..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-{{template "ng/base/head" .}} 
-{{template "ng/base/header" .}}
-<div id="sign-wrapper">
-    <form class="form-align form panel sign-panel sign-form container panel-radius" id="sign-up-form" action="/user/activate" method="post">
-        {{.CsrfTokenHtml}}
-        <div class="panel-header">
-            <h2>{{.i18n.Tr "auth.active_your_account"}}</h2>
-        </div>
-        <div class="panel-content">
-        {{if .IsActivatePage}}
-            {{if .ServiceNotEnabled}}
-            <p>{{.i18n.Tr "auth.disable_register_mail"}}</p>
-            {{else if .ResendLimited}}
-            <p>{{.i18n.Tr "auth.resent_limit_prompt"}}</p>
-            {{else}}
-            <p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" .SignedUser.Email .Hours | Str2html}}</p>
-            <hr/>
-            <label></label>
-            <a class="btn btn-green btn-large btn-link btn-radius" href="http://{{Mail2Domain .SignedUser.Email}}">{{.i18n.Tr "auth.sign_in_email"}}</a>
-            {{end}}
-        {{else}}
-            {{if .IsSendRegisterMail}}
-            <p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" .Email .Hours | Str2html}}</p>
-            <hr/>
-            <label></label>
-            <a class="btn btn-green btn-large btn-link btn-radius" href="http://{{Mail2Domain .Email}}">{{.i18n.Tr "auth.sign_in_email"}}</a>
-            {{else if .IsActivateFailed}}
-            <p>{{.i18n.Tr "auth.invalid_code"}}</p>
-            {{else}}
-            <p>{{.i18n.Tr "auth.has_unconfirmed_mail" .SignedUser.Name .SignedUser.Email | Str2html}}</p>
-            <hr/>
-            <label></label>
-            <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "auth.resend_mail"}}</button>
-            {{end}}
-        {{end}}
-        </div>
-    </form>
-</div>
-{{template "ng/base/footer" .}}
diff --git a/templates/user/auth/activate.tmpl b/templates/user/auth/activate.tmpl
new file mode 100644 (file)
index 0000000..acdad9e
--- /dev/null
@@ -0,0 +1,39 @@
+{{template "ng/base/head" .}} 
+{{template "ng/base/header" .}}
+<div id="sign-wrapper">
+    <form class="form-align form panel sign-panel sign-form container panel-radius" id="sign-up-form" action="/user/activate" method="post">
+        {{.CsrfTokenHtml}}
+        <div class="panel-header">
+            <h2>{{.i18n.Tr "auth.active_your_account"}}</h2>
+        </div>
+        <div class="panel-content">
+        {{if .IsActivatePage}}
+            {{if .ServiceNotEnabled}}
+            <p>{{.i18n.Tr "auth.disable_register_mail"}}</p>
+            {{else if .ResendLimited}}
+            <p>{{.i18n.Tr "auth.resent_limit_prompt"}}</p>
+            {{else}}
+            <p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" .SignedUser.Email .Hours | Str2html}}</p>
+            <hr/>
+            <label></label>
+            <a class="btn btn-green btn-large btn-link btn-radius" href="http://{{Mail2Domain .SignedUser.Email}}">{{.i18n.Tr "auth.sign_in_email"}}</a>
+            {{end}}
+        {{else}}
+            {{if .IsSendRegisterMail}}
+            <p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" .Email .Hours | Str2html}}</p>
+            <hr/>
+            <label></label>
+            <a class="btn btn-green btn-large btn-link btn-radius" href="http://{{Mail2Domain .Email}}">{{.i18n.Tr "auth.sign_in_email"}}</a>
+            {{else if .IsActivateFailed}}
+            <p>{{.i18n.Tr "auth.invalid_code"}}</p>
+            {{else}}
+            <p>{{.i18n.Tr "auth.has_unconfirmed_mail" .SignedUser.Name .SignedUser.Email | Str2html}}</p>
+            <hr/>
+            <label></label>
+            <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "auth.resend_mail"}}</button>
+            {{end}}
+        {{end}}
+        </div>
+    </form>
+</div>
+{{template "ng/base/footer" .}}
diff --git a/templates/user/auth/forgot_passwd.tmpl b/templates/user/auth/forgot_passwd.tmpl
new file mode 100644 (file)
index 0000000..3b55126
--- /dev/null
@@ -0,0 +1,32 @@
+{{template "ng/base/head" .}} 
+{{template "ng/base/header" .}}
+<div id="sign-wrapper">
+    <form class="form-align form panel sign-panel sign-form container panel-radius" id="sign-up-form" action="/user/forget_password" method="post">
+        {{.CsrfTokenHtml}}
+        <div class="panel-header">
+            <h2>{{.i18n.Tr "auth.forgot_password"}}</h2>
+        </div>
+        <div class="panel-content">
+            {{template "ng/base/alert" .}}
+            {{if .IsResetSent}}
+            <p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" .Email .Hours | Str2html}}</p>
+            <hr/>
+            <label></label>
+            <a class="btn btn-green btn-large btn-link btn-radius" href="http://{{Mail2Domain .Email}}">{{.i18n.Tr "auth.sign_in_email"}}</a>
+            {{else if .IsResetRequest}}
+            <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="{{.email}}"required/>
+            </div>
+            <hr/>
+            <label></label>
+            <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "auth.send_reset_mail"}}</button>
+            {{else if .IsResetDisable}}
+            <p>{{.i18n.Tr "auth.disable_register_mail"}}</p>
+            {{else if .ResendLimited}}
+            <p>{{.i18n.Tr "auth.resent_limit_prompt"}}</p>
+            {{end}}
+        </div>
+    </form>
+</div>
+{{template "ng/base/footer" .}}
diff --git a/templates/user/auth/reset_passwd.tmpl b/templates/user/auth/reset_passwd.tmpl
new file mode 100644 (file)
index 0000000..d17abde
--- /dev/null
@@ -0,0 +1,25 @@
+{{template "ng/base/head" .}} 
+{{template "ng/base/header" .}}
+<div id="sign-wrapper">
+    <form class="form-align form panel sign-panel sign-form container panel-radius" id="sign-up-form" action="/user/reset_password?code={{.Code}}" method="post">
+        {{.CsrfTokenHtml}}
+        <div class="panel-header">
+            <h2>{{.i18n.Tr "auth.reset_password"}}</h2>
+        </div>
+        <div class="panel-content">
+            {{template "ng/base/alert" .}}
+            {{if .IsResetForm}}
+            <div class="field">
+                <label class="req" for="password">{{.i18n.Tr "password"}}</label>
+                <input class="ipt ipt-large ipt-radius {{if .Err_Password}}ipt-error{{end}}" id="password" name="password" type="password" value="{{.password}}" required/>
+            </div>
+            <hr/>
+            <label></label>
+            <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "auth.reset_password_helper"}}</button>
+            {{else}}
+            <p>{{.i18n.Tr "auth.invalid_code"}}</p>
+            {{end}}
+        </div>
+    </form>
+</div>
+{{template "ng/base/footer" .}}
diff --git a/templates/user/auth/signin.tmpl b/templates/user/auth/signin.tmpl
new file mode 100644 (file)
index 0000000..c2f6ef8
--- /dev/null
@@ -0,0 +1,44 @@
+{{template "ng/base/head" .}}
+{{template "ng/base/header" .}}
+<div id="sign-wrapper">
+    <form class="form-align form panel sign-panel sign-form container panel-radius" id="sign-up-form" action="/user/login" method="post">
+        <div class="panel-header">
+            <h2>{{if .IsSocialLogin}}{{.i18n.Tr "social_sign_in" | Str2html}}{{else}}{{.i18n.Tr "sign_in"}}{{end}}</h2>
+        </div>
+        <div class="panel-content">
+            {{template "ng/base/alert" .}}
+            <div class="field">
+                <label class="req" for="username">{{.i18n.Tr "home.uname_holder"}}</label>
+                <input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="username" name="uname" type="text" value="{{.uname}}" required/>
+            </div>
+            <div class="field">
+                <label class="req" for="password">{{.i18n.Tr "password"}}</label>
+                <input class="ipt ipt-large ipt-radius {{if .Err_Password}}ipt-error{{end}}" id="password" name="password" type="password" required/>
+            </div>
+            {{if not .IsSocialLogin}}
+            <div class="field">
+                <span class="form-label"></span>
+                <input class="ipt-chk" id="remember" name="remember" type="checkbox"/>&nbsp;&nbsp;&nbsp;&nbsp;<strong>{{.i18n.Tr "auth.remember_me"}}</strong>
+            </div>
+            {{end}}
+            <div class="field">
+                <span class="form-label"></span>
+                <button class="btn btn-green btn-large btn-radius">{{.i18n.Tr "sign_in"}}</button>&nbsp;&nbsp;&nbsp;&nbsp;
+                {{if not .IsSocialLogin}}<a href="/user/forget_password">{{.i18n.Tr "auth.forget_password"}}</a>{{end}}
+            </div>
+            {{if not .IsSocialLogin}}
+            <div class="field">
+                <label></label>
+                <a href="/user/sign_up">{{.i18n.Tr "auth.sign_up_now" | Str2html}}</a>
+            </div>
+            {{if .OauthEnabled}}
+            <hr/>
+            <div id="sign-social" class="text-center social-buttons">
+                {{template "ng/base/social" .}}
+            </div>
+            {{end}}
+            {{end}}
+        </div>
+    </form>
+</div>
+{{template "ng/base/footer" .}}
\ No newline at end of file
diff --git a/templates/user/auth/signup.tmpl b/templates/user/auth/signup.tmpl
new file mode 100644 (file)
index 0000000..b4736a0
--- /dev/null
@@ -0,0 +1,49 @@
+{{template "ng/base/head" .}}
+{{template "ng/base/header" .}}
+<div id="sign-wrapper">
+    <form class="form-align form panel panel-radius sign-panel sign-form container" id="sign-up-form" action="/user/sign_up" method="post">
+        <div class="panel-header">
+            <h2>{{if .IsSocialLogin}}{{.i18n.Tr "social_sign_in" | Str2html}}{{else}}{{.i18n.Tr "sign_up"}}{{end}}</h2>
+        </div>
+        <div class="panel-content">
+            {{template "ng/base/alert" .}}
+               {{if .DisableRegistration}}
+               <p>{{.i18n.Tr "auth.disable_register_prompt"}}</p>
+               {{else}}
+            <div class="field">
+                <label class="req" for="username">{{.i18n.Tr "username"}}</label>
+                <input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="username" name="uname" type="text" value="{{.uname}}" required/>
+            </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="{{.email}}"required/>
+            </div>
+            <div class="field">
+                <label class="req" for="password">{{.i18n.Tr "password"}}</label>
+                <input class="ipt ipt-large ipt-radius {{if .Err_Password}}ipt-error{{end}}" id="password" name="password" type="password" value="{{.password}}" required/>
+            </div>
+            <div class="field">
+                <label class="req" for="re-type">{{.i18n.Tr "re_type"}}</label>
+                <input class="ipt ipt-large ipt-radius {{if .Err_Password}}ipt-error{{end}}" id="re-type" name="retype" type="password" required/>
+            </div>
+            <div class="field">
+                <label></label>
+                {{.Captcha.CreateHtml}}
+            </div>
+            <div class="field">
+                <label class="req" for="captcha">{{.i18n.Tr "captcha"}}</label>
+                <input class="ipt ipt-large ipt-radius {{if .Err_Captcha}}ipt-error{{end}}" id="captcha" name="captcha" type="text" required/>
+            </div>
+            <div class="field">
+                <span class="form-label"></span>
+                <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "auth.create_new_account"}}</button>
+            </div>
+            <div class="field">
+                <span class="form-label"></span>
+                <a href="/user/login">{{if .IsSocialLogin}}{{.i18n.Tr "auth.social_register_hepler_msg"}}{{else}}{{.i18n.Tr "auth.register_hepler_msg"}}{{end}}</a>
+            </div>
+               {{end}}
+        </div>
+    </form>
+</div>
+{{template "ng/base/footer" .}}
\ No newline at end of file
diff --git a/templates/user/forgot_passwd.tmpl b/templates/user/forgot_passwd.tmpl
deleted file mode 100644 (file)
index 3b55126..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-{{template "ng/base/head" .}} 
-{{template "ng/base/header" .}}
-<div id="sign-wrapper">
-    <form class="form-align form panel sign-panel sign-form container panel-radius" id="sign-up-form" action="/user/forget_password" method="post">
-        {{.CsrfTokenHtml}}
-        <div class="panel-header">
-            <h2>{{.i18n.Tr "auth.forgot_password"}}</h2>
-        </div>
-        <div class="panel-content">
-            {{template "ng/base/alert" .}}
-            {{if .IsResetSent}}
-            <p>{{.i18n.Tr "auth.confirmation_mail_sent_prompt" .Email .Hours | Str2html}}</p>
-            <hr/>
-            <label></label>
-            <a class="btn btn-green btn-large btn-link btn-radius" href="http://{{Mail2Domain .Email}}">{{.i18n.Tr "auth.sign_in_email"}}</a>
-            {{else if .IsResetRequest}}
-            <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="{{.email}}"required/>
-            </div>
-            <hr/>
-            <label></label>
-            <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "auth.send_reset_mail"}}</button>
-            {{else if .IsResetDisable}}
-            <p>{{.i18n.Tr "auth.disable_register_mail"}}</p>
-            {{else if .ResendLimited}}
-            <p>{{.i18n.Tr "auth.resent_limit_prompt"}}</p>
-            {{end}}
-        </div>
-    </form>
-</div>
-{{template "ng/base/footer" .}}
diff --git a/templates/user/reset_passwd.tmpl b/templates/user/reset_passwd.tmpl
deleted file mode 100644 (file)
index d17abde..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-{{template "ng/base/head" .}} 
-{{template "ng/base/header" .}}
-<div id="sign-wrapper">
-    <form class="form-align form panel sign-panel sign-form container panel-radius" id="sign-up-form" action="/user/reset_password?code={{.Code}}" method="post">
-        {{.CsrfTokenHtml}}
-        <div class="panel-header">
-            <h2>{{.i18n.Tr "auth.reset_password"}}</h2>
-        </div>
-        <div class="panel-content">
-            {{template "ng/base/alert" .}}
-            {{if .IsResetForm}}
-            <div class="field">
-                <label class="req" for="password">{{.i18n.Tr "password"}}</label>
-                <input class="ipt ipt-large ipt-radius {{if .Err_Password}}ipt-error{{end}}" id="password" name="password" type="password" value="{{.password}}" required/>
-            </div>
-            <hr/>
-            <label></label>
-            <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "auth.reset_password_helper"}}</button>
-            {{else}}
-            <p>{{.i18n.Tr "auth.invalid_code"}}</p>
-            {{end}}
-        </div>
-    </form>
-</div>
-{{template "ng/base/footer" .}}
diff --git a/templates/user/signin.tmpl b/templates/user/signin.tmpl
deleted file mode 100644 (file)
index c2f6ef8..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-{{template "ng/base/head" .}}
-{{template "ng/base/header" .}}
-<div id="sign-wrapper">
-    <form class="form-align form panel sign-panel sign-form container panel-radius" id="sign-up-form" action="/user/login" method="post">
-        <div class="panel-header">
-            <h2>{{if .IsSocialLogin}}{{.i18n.Tr "social_sign_in" | Str2html}}{{else}}{{.i18n.Tr "sign_in"}}{{end}}</h2>
-        </div>
-        <div class="panel-content">
-            {{template "ng/base/alert" .}}
-            <div class="field">
-                <label class="req" for="username">{{.i18n.Tr "home.uname_holder"}}</label>
-                <input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="username" name="uname" type="text" value="{{.uname}}" required/>
-            </div>
-            <div class="field">
-                <label class="req" for="password">{{.i18n.Tr "password"}}</label>
-                <input class="ipt ipt-large ipt-radius {{if .Err_Password}}ipt-error{{end}}" id="password" name="password" type="password" required/>
-            </div>
-            {{if not .IsSocialLogin}}
-            <div class="field">
-                <span class="form-label"></span>
-                <input class="ipt-chk" id="remember" name="remember" type="checkbox"/>&nbsp;&nbsp;&nbsp;&nbsp;<strong>{{.i18n.Tr "auth.remember_me"}}</strong>
-            </div>
-            {{end}}
-            <div class="field">
-                <span class="form-label"></span>
-                <button class="btn btn-green btn-large btn-radius">{{.i18n.Tr "sign_in"}}</button>&nbsp;&nbsp;&nbsp;&nbsp;
-                {{if not .IsSocialLogin}}<a href="/user/forget_password">{{.i18n.Tr "auth.forget_password"}}</a>{{end}}
-            </div>
-            {{if not .IsSocialLogin}}
-            <div class="field">
-                <label></label>
-                <a href="/user/sign_up">{{.i18n.Tr "auth.sign_up_now" | Str2html}}</a>
-            </div>
-            {{if .OauthEnabled}}
-            <hr/>
-            <div id="sign-social" class="text-center social-buttons">
-                {{template "ng/base/social" .}}
-            </div>
-            {{end}}
-            {{end}}
-        </div>
-    </form>
-</div>
-{{template "ng/base/footer" .}}
\ No newline at end of file
diff --git a/templates/user/signup.tmpl b/templates/user/signup.tmpl
deleted file mode 100644 (file)
index b4736a0..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-{{template "ng/base/head" .}}
-{{template "ng/base/header" .}}
-<div id="sign-wrapper">
-    <form class="form-align form panel panel-radius sign-panel sign-form container" id="sign-up-form" action="/user/sign_up" method="post">
-        <div class="panel-header">
-            <h2>{{if .IsSocialLogin}}{{.i18n.Tr "social_sign_in" | Str2html}}{{else}}{{.i18n.Tr "sign_up"}}{{end}}</h2>
-        </div>
-        <div class="panel-content">
-            {{template "ng/base/alert" .}}
-               {{if .DisableRegistration}}
-               <p>{{.i18n.Tr "auth.disable_register_prompt"}}</p>
-               {{else}}
-            <div class="field">
-                <label class="req" for="username">{{.i18n.Tr "username"}}</label>
-                <input class="ipt ipt-large ipt-radius {{if .Err_UserName}}ipt-error{{end}}" id="username" name="uname" type="text" value="{{.uname}}" required/>
-            </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="{{.email}}"required/>
-            </div>
-            <div class="field">
-                <label class="req" for="password">{{.i18n.Tr "password"}}</label>
-                <input class="ipt ipt-large ipt-radius {{if .Err_Password}}ipt-error{{end}}" id="password" name="password" type="password" value="{{.password}}" required/>
-            </div>
-            <div class="field">
-                <label class="req" for="re-type">{{.i18n.Tr "re_type"}}</label>
-                <input class="ipt ipt-large ipt-radius {{if .Err_Password}}ipt-error{{end}}" id="re-type" name="retype" type="password" required/>
-            </div>
-            <div class="field">
-                <label></label>
-                {{.Captcha.CreateHtml}}
-            </div>
-            <div class="field">
-                <label class="req" for="captcha">{{.i18n.Tr "captcha"}}</label>
-                <input class="ipt ipt-large ipt-radius {{if .Err_Captcha}}ipt-error{{end}}" id="captcha" name="captcha" type="text" required/>
-            </div>
-            <div class="field">
-                <span class="form-label"></span>
-                <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "auth.create_new_account"}}</button>
-            </div>
-            <div class="field">
-                <span class="form-label"></span>
-                <a href="/user/login">{{if .IsSocialLogin}}{{.i18n.Tr "auth.social_register_hepler_msg"}}{{else}}{{.i18n.Tr "auth.register_hepler_msg"}}{{end}}</a>
-            </div>
-               {{end}}
-        </div>
-    </form>
-</div>
-{{template "ng/base/footer" .}}
\ No newline at end of file
diff --git a/templates/user/stars.tmpl b/templates/user/stars.tmpl
deleted file mode 100644 (file)
index 253efd6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-{{template "base/head" .}}
-{{template "base/navbar" .}}
-<div id="body-nav">
-    <div class="container">
-        <ul class="nav nav-pills pull-right">
-            <li><a href="/">Feed</a></li>
-            <li><a href="/issues">Issues</a></li>
-            <li><a href="/pulls">Pull Requests</a></li>
-            <li class="active"><a href="/stars">Stars</a></li>
-        </ul>
-        <h3>Stars</h3>
-    </div>
-</div>
-<div id="body" class="container" data-page="user">
-    {{if .HasInfo}}<div class="alert alert-info">{{.InfoMsg}}</div>{{end}}
-</div>
-{{template "base/footer" .}}
\ No newline at end of file