summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gopmfile5
-rw-r--r--cmd/web.go5
-rw-r--r--conf/app.ini4
-rw-r--r--conf/locale/locale_en-US.ini11
-rw-r--r--conf/locale/locale_zh-CN.ini11
-rw-r--r--gogs.go2
-rw-r--r--models/org.go94
-rw-r--r--models/user.go10
-rw-r--r--modules/middleware/context.go3
-rw-r--r--modules/middleware/org.go23
-rw-r--r--modules/middleware/repo.go2
-rw-r--r--public/ng/css/gogs.css52
-rw-r--r--public/ng/less/gogs/dashboard.less1
-rw-r--r--public/ng/less/gogs/organization.less61
-rw-r--r--public/ng/less/ui/label.less6
-rw-r--r--routers/org/members.go95
-rw-r--r--routers/repo/repo.go2
-rw-r--r--templates/.VERSION2
-rw-r--r--templates/org/header.tmpl16
-rw-r--r--templates/org/home.tmpl9
-rw-r--r--templates/org/invite.tmpl15
-rw-r--r--templates/org/members.tmpl97
-rw-r--r--templates/org/settings.tmpl130
-rw-r--r--templates/user/dashboard/dashboard.tmpl2
24 files changed, 450 insertions, 208 deletions
diff --git a/.gopmfile b/.gopmfile
index 235a8a436f..25006beb7b 100644
--- a/.gopmfile
+++ b/.gopmfile
@@ -11,14 +11,17 @@ github.com/codegangsta/cli =
github.com/go-sql-driver/mysql =
github.com/go-xorm/core =
github.com/go-xorm/xorm =
-github.com/gogits/cache =
github.com/gogits/gfm =
github.com/gogits/git =
github.com/gogits/oauth2 =
github.com/juju2013/goldap =
github.com/lib/pq =
+github.com/macaron-contrib/cache =
+github.com/macaron-contrib/captcha =
+github.com/macaron-contrib/csrf =
github.com/macaron-contrib/i18n =
github.com/macaron-contrib/session =
+github.com/macaron-contrib/toolbox =
github.com/nfnt/resize =
[res]
diff --git a/cmd/web.go b/cmd/web.go
index 03704c64de..03e5e86066 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -232,6 +232,7 @@ func runWeb(*cli.Context) {
m.Group("/:org", func(r *macaron.Router) {
r.Get("/dashboard", user.Dashboard)
r.Get("/members", org.Members)
+ r.Get("/members/action/:action", org.MembersAction)
r.Get("/teams", org.Teams)
r.Get("/teams/:team", org.SingleTeam)
@@ -248,6 +249,10 @@ func runWeb(*cli.Context) {
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))
}, reqSignIn)
// Repository routers.
diff --git a/conf/app.ini b/conf/app.ini
index ac1c6a3ba9..99ed628ec1 100644
--- a/conf/app.ini
+++ b/conf/app.ini
@@ -254,5 +254,5 @@ DRIVER =
CONN =
[i18n]
-LANGS = en-US,zh-CN
-NAMES = English,简体中文
+LANGS = en-US,zh-CN,de-DE
+NAMES = English,简体中文,Deutsch
diff --git a/conf/locale/locale_en-US.ini b/conf/locale/locale_en-US.ini
index d7b5c45a02..d44dca081b 100644
--- a/conf/locale/locale_en-US.ini
+++ b/conf/locale/locale_en-US.ini
@@ -250,6 +250,17 @@ 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
+members.public = Public
+members.public_helper = make private
+members.private = Private
+members.private_helper = make public
+members.owner = Owner
+members.member = Member
+members.conceal = Conceal
+members.remove = Remove
+members.invite_desc = Start typing a username to invite a new member to %s:
+members.invite_now = Invite Now
+
[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>
diff --git a/conf/locale/locale_zh-CN.ini b/conf/locale/locale_zh-CN.ini
index 2499e12154..b84aca3d9e 100644
--- a/conf/locale/locale_zh-CN.ini
+++ b/conf/locale/locale_zh-CN.ini
@@ -250,6 +250,17 @@ settings.delete_account = 删除当前组织
settings.delete_prompt = 删除操作会永久清除该组织的信息,并且 <strong>不可恢复</strong>!
settings.confirm_delete_account = 确认删除组织
+members.public = 公开成员
+members.public_helper = 设为私有
+members.private = 私有成员
+members.private_helper = 设为公开
+members.owner = 管理员
+members.member = 普通成员
+members.conceal = 隐藏身份
+members.remove = 移除成员
+members.invite_desc = 请输入被邀请到组织 %s 的用户名称:
+members.invite_now = 立即邀请
+
[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 4a3e353cdf..6a9ded37d5 100644
--- a/gogs.go
+++ b/gogs.go
@@ -17,7 +17,7 @@ import (
"github.com/gogits/gogs/modules/setting"
)
-const APP_VER = "0.4.7.0814 Alpha"
+const APP_VER = "0.4.7.0815 Alpha"
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
diff --git a/models/org.go b/models/org.go
index edae828b54..b40b313bc3 100644
--- a/models/org.go
+++ b/models/org.go
@@ -59,6 +59,16 @@ func (org *User) GetMembers() error {
return nil
}
+// AddMember adds new member to organization.
+func (org *User) AddMember(uid int64) error {
+ return AddOrgUser(org.Id, uid)
+}
+
+// RemoveMember removes member from organization.
+func (org *User) RemoveMember(uid int64) error {
+ return RemoveOrgUser(org.Id, uid)
+}
+
// CreateOrganization creates record of a new organization.
func CreateOrganization(org, owner *User) (*User, error) {
if !IsLegalName(org.Name) {
@@ -241,8 +251,7 @@ func NewTeam(t *Team) error {
}
// Update organization number of teams.
- rawSql := "UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?"
- if _, err = sess.Exec(rawSql, t.OrgId); err != nil {
+ if _, err = sess.Exec("UPDATE `user` SET num_teams = num_teams + 1 WHERE id = ?", t.OrgId); err != nil {
sess.Rollback()
return err
}
@@ -270,8 +279,8 @@ func UpdateTeam(t *Team) error {
// OrgUser represents an organization-user relation.
type OrgUser struct {
Id int64
- Uid int64 `xorm:"INDEX"`
- OrgId int64 `xorm:"INDEX"`
+ Uid int64 `xorm:"INDEX UNIQUE(s)"`
+ OrgId int64 `xorm:"INDEX UNIQUE(s)"`
IsPublic bool
IsOwner bool
NumTeam int
@@ -289,6 +298,12 @@ func IsOrganizationMember(orgId, uid int64) bool {
return has
}
+// IsPublicMembership returns ture if given user public his/her membership.
+func IsPublicMembership(orgId, uid int64) bool {
+ has, _ := x.Where("uid=?", uid).And("org_id=?", orgId).And("is_public=?", true).Get(new(OrgUser))
+ return has
+}
+
// GetOrgUsersByUserId returns all organization-user relations by user ID.
func GetOrgUsersByUserId(uid int64) ([]*OrgUser, error) {
ous := make([]*OrgUser, 0, 10)
@@ -303,6 +318,77 @@ func GetOrgUsersByOrgId(orgId int64) ([]*OrgUser, error) {
return ous, err
}
+// ChangeOrgUserStatus changes public or private membership status.
+func ChangeOrgUserStatus(orgId, uid int64, public bool) error {
+ ou := new(OrgUser)
+ has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou)
+ if err != nil {
+ return err
+ } else if !has {
+ return nil
+ }
+
+ ou.IsPublic = public
+ _, err = x.Id(ou.Id).AllCols().Update(ou)
+ return err
+}
+
+// AddOrgUser adds new user to given organization.
+func AddOrgUser(orgId, uid int64) error {
+ if IsOrganizationMember(orgId, uid) {
+ return nil
+ }
+
+ ou := &OrgUser{
+ Uid: uid,
+ OrgId: orgId,
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ if _, err := sess.Insert(ou); err != nil {
+ sess.Rollback()
+ return err
+ } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members + 1 WHERE id = ?", orgId); err != nil {
+ sess.Rollback()
+ return err
+ }
+
+ return sess.Commit()
+}
+
+// RemoveOrgUser removes user from given organization.
+func RemoveOrgUser(orgId, uid int64) error {
+ ou := new(OrgUser)
+
+ has, err := x.Where("uid=?", uid).And("org_id=?", orgId).Get(ou)
+ if err != nil {
+ return err
+ } else if !has {
+ return nil
+ }
+
+ sess := x.NewSession()
+ defer sess.Close()
+ if err := sess.Begin(); err != nil {
+ return err
+ }
+
+ if _, err := sess.Id(ou.Id).Delete(ou); err != nil {
+ sess.Rollback()
+ return err
+ } else if _, err = sess.Exec("UPDATE `user` SET num_members = num_members - 1 WHERE id = ?", orgId); err != nil {
+ sess.Rollback()
+ return err
+ }
+
+ return sess.Commit()
+}
+
// ___________ ____ ___
// \__ ___/___ _____ _____ | | \______ ___________
// | |_/ __ \\__ \ / \| | / ___// __ \_ __ \
diff --git a/models/user.go b/models/user.go
index f4526b51d1..757c290b9c 100644
--- a/models/user.go
+++ b/models/user.go
@@ -128,6 +128,16 @@ func (u *User) IsOrganization() bool {
return u.Type == ORGANIZATION
}
+// IsUserOrgOwner returns true if user is in the owner team of given organization.
+func (u *User) IsUserOrgOwner(orgId int64) bool {
+ return IsOrganizationOwner(orgId, u.Id)
+}
+
+// IsPublicMember returns true if user public his/her membership in give organization.
+func (u *User) IsPublicMember(orgId int64) bool {
+ return IsPublicMembership(orgId, u.Id)
+}
+
// GetOrganizationCount returns count of membership of organization of user.
func (u *User) GetOrganizationCount() (int64, error) {
return x.Where("uid=?", u.Id).Count(new(OrgUser))
diff --git a/modules/middleware/context.go b/modules/middleware/context.go
index aa1266d649..6ce0f6e1f7 100644
--- a/modules/middleware/context.go
+++ b/modules/middleware/context.go
@@ -68,7 +68,9 @@ type Context struct {
Org struct {
IsOwner bool
IsMember bool
+ IsAdminTeam bool // In owner team or team that has admin permission level.
Organization *models.User
+ OrgLink string
}
}
@@ -181,7 +183,6 @@ func Contexter() macaron.Handler {
Flash: f,
Session: sess,
}
-
// Compute current URL for real-time change language.
link := ctx.Req.RequestURI
i := strings.Index(link, "?")
diff --git a/modules/middleware/org.go b/modules/middleware/org.go
index 05316a518f..77e999a328 100644
--- a/modules/middleware/org.go
+++ b/modules/middleware/org.go
@@ -13,8 +13,9 @@ import (
func OrgAssignment(redirect bool, args ...bool) macaron.Handler {
return func(ctx *Context) {
var (
- requireMember bool
- requireOwner bool
+ requireMember bool
+ requireOwner bool
+ requireAdminTeam bool
)
if len(args) >= 1 {
requireMember = args[0]
@@ -22,6 +23,9 @@ func OrgAssignment(redirect bool, args ...bool) macaron.Handler {
if len(args) >= 2 {
requireOwner = args[1]
}
+ if len(args) >= 3 {
+ requireAdminTeam = args[2]
+ }
orgName := ctx.Params(":org")
@@ -43,13 +47,24 @@ func OrgAssignment(redirect bool, args ...bool) macaron.Handler {
ctx.Org.IsOwner = ctx.Org.Organization.IsOrgOwner(ctx.User.Id)
if ctx.Org.IsOwner {
ctx.Org.IsMember = true
+ ctx.Org.IsAdminTeam = true
} else {
- ctx.Org.IsMember = ctx.Org.Organization.IsOrgMember(ctx.User.Id)
+ if ctx.Org.Organization.IsOrgMember(ctx.User.Id) {
+ ctx.Org.IsMember = true
+ // TODO: ctx.Org.IsAdminTeam
+ }
}
}
- if (requireMember && !ctx.Org.IsMember) || (requireOwner && !ctx.Org.IsOwner) {
+ if (requireMember && !ctx.Org.IsMember) ||
+ (requireOwner && !ctx.Org.IsOwner) ||
+ (requireAdminTeam && !ctx.Org.IsAdminTeam) {
ctx.Handle(404, "OrgAssignment", err)
return
}
+ ctx.Data["IsAdminTeam"] = ctx.Org.IsAdminTeam
+ ctx.Data["IsOrganizationOwner"] = ctx.Org.IsOwner
+
+ ctx.Org.OrgLink = "/org/" + ctx.Org.Organization.Name
+ ctx.Data["OrgLink"] = ctx.Org.OrgLink
}
}
diff --git a/modules/middleware/repo.go b/modules/middleware/repo.go
index a028aab802..3db1932af0 100644
--- a/modules/middleware/repo.go
+++ b/modules/middleware/repo.go
@@ -146,6 +146,7 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
}
ctx.Repo.GitRepo = gitRepo
ctx.Repo.RepoLink = "/" + u.Name + "/" + repo.Name
+ ctx.Data["RepoLink"] = ctx.Repo.RepoLink
tags, err := ctx.Repo.GitRepo.GetTags()
if err != nil {
@@ -157,7 +158,6 @@ func RepoAssignment(redirect bool, args ...bool) macaron.Handler {
ctx.Data["Title"] = u.Name + "/" + repo.Name
ctx.Data["Repository"] = repo
ctx.Data["Owner"] = ctx.Repo.Repository.Owner
- ctx.Data["RepoLink"] = ctx.Repo.RepoLink
ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner
ctx.Data["IsRepositoryTrueOwner"] = ctx.Repo.IsTrueOwner
diff --git a/public/ng/css/gogs.css b/public/ng/css/gogs.css
index 93a5d2f8c9..e7a3a66f26 100644
--- a/public/ng/css/gogs.css
+++ b/public/ng/css/gogs.css
@@ -851,6 +851,7 @@ The dashboard page style
margin-left: 1em;
}
#dashboard-news .push-news .news-content li img {
+ vertical-align: inherit;
margin-bottom: -2px;
}
/*
@@ -1691,6 +1692,30 @@ textarea#issue-add-content {
#org-home-header {
min-height: 100px;
}
+#org-header {
+ height: 48px;
+}
+#org-header .org-name {
+ padding-left: 10px;
+ font-size: 1.4em;
+ height: 50px;
+ line-height: 50px;
+ margin-bottom: 0;
+}
+#org-header > div > .menu-line > li.right > a {
+ font-size: 1.2em;
+ color: #444444;
+}
+#org-header > div > .menu-line > li.right > a:hover {
+ background-color: transparent;
+ color: #d9453d;
+}
+#org-header > div > .menu-line > li.right > a .octicon {
+ margin-right: 6px;
+}
+#org-header > div > .menu-line > li.right .current {
+ border-bottom: 2px solid #D26911;
+}
#org-home-header-info {
padding-top: 10px;
}
@@ -1776,3 +1801,30 @@ textarea#issue-add-content {
margin-bottom: 0;
color: #777;
}
+#org-member-toolbar {
+ padding: 10px 0;
+}
+#org-member-list .org-member-item {
+ height: 50px;
+ line-height: 50px;
+ border-top: 1px solid #eee;
+ padding: 15px 20px;
+}
+#org-member-list .org-member-item .member-name {
+ padding-left: 15px;
+}
+#org-member-list .org-member-item ul {
+ list-style: none;
+}
+#org-member-list .org-member-item ul li {
+ text-align: center;
+ display: inline-block;
+}
+.invite-box {
+ padding: 50px 0;
+ min-height: 130px;
+ text-align: center;
+}
+.invite-box input {
+ width: 250px;
+}
diff --git a/public/ng/less/gogs/dashboard.less b/public/ng/less/gogs/dashboard.less
index f8838ae6fd..6bf1150ba7 100644
--- a/public/ng/less/gogs/dashboard.less
+++ b/public/ng/less/gogs/dashboard.less
@@ -251,6 +251,7 @@ The dashboard page style
.news-content li {
margin-left: 1em;
img {
+ vertical-align: inherit;
margin-bottom: -2px;
}
}
diff --git a/public/ng/less/gogs/organization.less b/public/ng/less/gogs/organization.less
index ed8c05397a..cbdec3132e 100644
--- a/public/ng/less/gogs/organization.less
+++ b/public/ng/less/gogs/organization.less
@@ -9,6 +9,38 @@
#org-home-header {
min-height: 100px;
}
+#org-header {
+ height: 48px;
+ .org-name {
+ padding-left: 10px;
+ font-size: 1.4em;
+ height: 50px;
+ line-height: 50px;
+ margin-bottom: 0;
+ }
+ > div {
+ > .menu-line {
+ > li {
+ &.right {
+ > a {
+ font-size: 1.2em;
+ color: @dashboardHeaderLinkColor;
+ &:hover {
+ background-color: transparent;
+ color: @dashboardHeaderLinkHoverColor;
+ }
+ .octicon {
+ margin-right: 6px;
+ }
+ }
+ .current {
+ border-bottom: 2px solid #D26911;
+ }
+ }
+ }
+ }
+ }
+}
#org-home-header-info {
padding-top: 10px;
h2 {
@@ -93,4 +125,33 @@
margin-top: 0;
margin-bottom: 0;
color: #777;
+}
+#org-member-toolbar {
+ padding: 10px 0;
+}
+#org-member-list {
+ .org-member-item {
+ height: 50px;
+ line-height: 50px;
+ border-top: 1px solid #eee;
+ padding: 15px 20px;
+ .member-name {
+ padding-left: 15px;
+ }
+ ul {
+ list-style: none;
+ li {
+ text-align: center;
+ display: inline-block;
+ }
+ }
+ }
+}
+.invite-box {
+ padding: 50px 0;
+ min-height: 130px;
+ text-align: center;
+ input {
+ width: 250px;
+ }
} \ No newline at end of file
diff --git a/public/ng/less/ui/label.less b/public/ng/less/ui/label.less
index 1cf0a81d85..a2a8a67905 100644
--- a/public/ng/less/ui/label.less
+++ b/public/ng/less/ui/label.less
@@ -1,8 +1,8 @@
@import "var";
.label {
- padding: 2px 6px;
- color: @labelFontColor;
+ padding: 2px 6px;
+ color: @labelFontColor;
}
.label-red {
@@ -30,7 +30,7 @@
}
.label-radius{
- border-radius: .2em;
+ border-radius: .2em;
}
.label-link{
diff --git a/routers/org/members.go b/routers/org/members.go
index ac278d4e6d..d98061765a 100644
--- a/routers/org/members.go
+++ b/routers/org/members.go
@@ -5,10 +5,101 @@
package org
import (
+ "github.com/Unknwon/com"
+
+ "github.com/gogits/gogs/models"
+ "github.com/gogits/gogs/modules/base"
+ "github.com/gogits/gogs/modules/log"
"github.com/gogits/gogs/modules/middleware"
)
+const (
+ MEMBERS base.TplName = "org/members"
+ INVITE base.TplName = "org/invite"
+)
+
func Members(ctx *middleware.Context) {
- ctx.Data["Title"] = "Organization " + ctx.Params(":org") + " Members"
- ctx.HTML(200, "org/members")
+ org := ctx.Org.Organization
+ ctx.Data["Title"] = org.Name
+ ctx.Data["PageIsOrgMembers"] = true
+
+ if err := org.GetMembers(); err != nil {
+ ctx.Handle(500, "GetMembers", err)
+ return
+ }
+ ctx.Data["Members"] = org.Members
+
+ ctx.HTML(200, MEMBERS)
+}
+
+func MembersAction(ctx *middleware.Context) {
+ uid := com.StrTo(ctx.Query("uid")).MustInt64()
+ if uid == 0 {
+ ctx.Redirect(ctx.Org.OrgLink + "/members")
+ return
+ }
+
+ org := ctx.Org.Organization
+ var err error
+ switch ctx.Params(":action") {
+ case "private":
+ if ctx.User.Id != uid && !ctx.Org.IsOwner {
+ ctx.Error(404)
+ return
+ }
+ err = models.ChangeOrgUserStatus(org.Id, uid, false)
+ case "public":
+ if ctx.User.Id != uid {
+ ctx.Error(404)
+ return
+ }
+ err = models.ChangeOrgUserStatus(org.Id, uid, true)
+ case "remove":
+ if !ctx.Org.IsOwner {
+ ctx.Error(404)
+ return
+ }
+ err = org.RemoveMember(uid)
+ }
+
+ 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 + "/members")
+}
+
+func Invitation(ctx *middleware.Context) {
+ org := ctx.Org.Organization
+ ctx.Data["Title"] = org.Name
+ ctx.Data["PageIsOrgMembers"] = true
+
+ if ctx.Req.Method == "POST" {
+ uname := ctx.Query("uname")
+ u, err := models.GetUserByName(uname)
+ if err != nil {
+ if err == models.ErrUserNotExist {
+ ctx.Flash.Error(ctx.Tr("form.user_not_exist"))
+ ctx.Redirect(ctx.Org.OrgLink + "/invitations/new")
+ } else {
+ ctx.Handle(500, " GetUserByName", err)
+ }
+ return
+ }
+
+ if err = org.AddMember(u.Id); err != nil {
+ ctx.Handle(500, " AddMember", err)
+ return
+ }
+
+ log.Trace("New member added(%s): %s", org.Name, u.Name)
+ ctx.Redirect(ctx.Org.OrgLink + "/members")
+ return
+ }
+
+ ctx.HTML(200, INVITE)
}
diff --git a/routers/repo/repo.go b/routers/repo/repo.go
index 3450ea76f7..7356f50330 100644
--- a/routers/repo/repo.go
+++ b/routers/repo/repo.go
@@ -227,7 +227,7 @@ func Action(ctx *middleware.Context) {
}
if err != nil {
- log.Error(4, "repo.Action(%s): %v", ctx.Params(":action"), err)
+ log.Error(4, "Action(%s): %v", ctx.Params(":action"), err)
ctx.JSON(200, map[string]interface{}{
"ok": false,
"err": err.Error(),
diff --git a/templates/.VERSION b/templates/.VERSION
index f398e90110..906c01dc84 100644
--- a/templates/.VERSION
+++ b/templates/.VERSION
@@ -1 +1 @@
-0.4.7.0814 Alpha \ No newline at end of file
+0.4.7.0815 Alpha \ No newline at end of file
diff --git a/templates/org/header.tmpl b/templates/org/header.tmpl
new file mode 100644
index 0000000000..8566d0a3c5
--- /dev/null
+++ b/templates/org/header.tmpl
@@ -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/home.tmpl b/templates/org/home.tmpl
index 205318b0e9..d96624010f 100644
--- a/templates/org/home.tmpl
+++ b/templates/org/home.tmpl
@@ -17,7 +17,9 @@
<div class="container">
<div id="org-home-repo-list" class="left grid-2-3">
<div class="clear">
+ {{if .IsAdminTeam}}
<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>
<div id="org-repo-list">
{{range .Repos}}
@@ -45,9 +47,11 @@
<a href="/{{.Name}}"><img src="{{.AvatarLink}}"></a>
{{end}}
</div>
+ {{if .IsAdminTeam}}
<div class="panel-footer">
- <a class="btn btn-medium btn-blue btn-link btn-radius" href="">{{.i18n.Tr "org.invite_someone"}}</a>
+ <a class="btn btn-medium btn-blue btn-link btn-radius" href="/org/{{.Org.LowerName}}/invitations/new">{{.i18n.Tr "org.invite_someone"}}</a>
</div>
+ {{end}}
</div>
<br>
<div class="panel panel-radius">
@@ -65,9 +69,12 @@
{{end}}
</ul>
</div>
+ {{if .IsOrganizationOwner}}
<div class="panel-footer">
<a class="btn btn-medium btn-blue btn-link btn-radius" href="/org/{{$.Org.LowerName}}/teams/new">{{.i18n.Tr "org.create_new_team"}}</a>
</div>
+
+ {{end}}
</div>
</div>
</div>
diff --git a/templates/org/invite.tmpl b/templates/org/invite.tmpl
new file mode 100644
index 0000000000..400622fdd8
--- /dev/null
+++ b/templates/org/invite.tmpl
@@ -0,0 +1,15 @@
+{{template "ng/base/head" .}}
+{{template "ng/base/header" .}}
+{{template "org/header" .}}
+<div class="container">
+ <div class="invite-box">
+ {{template "ng/base/alert" .}}
+ <h3>{{.i18n.Tr "org.members.invite_desc" .Org.FullName}}</h3>
+ <form action="{{.OrgLink}}/invitations/new" method="post">
+ {{.CsrfTokenHtml}}
+ <input class="ipt ipt-large ipt-radius" name="uname" required>
+ <button class="btn btn-blue btn-large btn-radius">{{.i18n.Tr "org.members.invite_now"}}</button>
+ </form>
+ </div>
+</div>
+{{template "ng/base/footer" .}} \ No newline at end of file
diff --git a/templates/org/members.tmpl b/templates/org/members.tmpl
index ba14cb4cc9..bea4340ffb 100644
--- a/templates/org/members.tmpl
+++ b/templates/org/members.tmpl
@@ -1,56 +1,43 @@
-{{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 class="active"><a href="#"><i class="fa fa-users"></i>Members
- <span class="label label-default">5</span></a>
- </li>
- <li><a href="#"><i class="fa fa-tags"></i>Teams
- <span class="label label-default">2</span></a>
- </li>
- </ul>
- <img class="pull-left org-small-logo" src="https://avatars3.githubusercontent.com/u/6656686?s=140" alt="" width="60"/>
- <div id="org-nav-info">
- <h2 class="org-name">Organization Name</h2>
- </div>
- </div>
-
- </div>
+{{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>
-<div id="body" class="container">
- <div id="org">
- <div id="org-members">
- <div class="member">&nbsp;
- <div class="avatar col-md-1">
- <img src="https://avatars3.githubusercontent.com/u/2142787?s=140" alt=""/>
- </div>
- <div class="name col-md-4">
- <a href="#"><strong>fuxiaohei</strong><span class="nick">傅小黑</span></a>
- </div>
- <div class="role col-md-2 pull-right">
- <strong>Member</strong>
- </div>
- <div class="status col-md-1 pull-right">
- <strong>Public</strong>
- </div>
- </div>
- <div class="member">&nbsp;
- <div class="avatar col-md-1">
- <img src="https://avatars3.githubusercontent.com/u/2142787?s=140" alt=""/>
- </div>
- <div class="name col-md-4">
- <a href="#"><strong>fuxiaohei</strong><span class="nick">傅小黑</span></a>
- </div>
- <div class="role col-md-2 pull-right">
- <strong><i class="fa fa-user"></i>Owner</strong>
- </div>
- <div class="status col-md-1 pull-right">
- <i class="fa fa-lock"></i>Private
- </div>
- </div>
- </div>
- </div>
-</div>
-{{template "base/footer" .}}
+{{template "ng/base/footer" .}} \ No newline at end of file
diff --git a/templates/org/settings.tmpl b/templates/org/settings.tmpl
deleted file mode 100644
index fd0d6a1c14..0000000000
--- a/templates/org/settings.tmpl
+++ /dev/null
@@ -1,130 +0,0 @@
-{{template "base/head" .}}
-{{template "base/navbar" .}}
-<div id="body-nav">
- <div class="container">
- <div class="btn-group pull-left" id="dashboard-switch">
- <button type="button" class="btn btn-default">
- <img src="{{.Org.AvatarLink}}?s=28" alt="user-avatar" title="username">
- {{.Org.Name}}
- </button>
- </div>
- <ul class="nav nav-pills pull-right">
- <li><a href="/org/{{.Org.Name}}/dashboard/">News Feed</a></li>
- <li><a href="/org/{{.Org.Name}}/dashboard/issues">Issues</a></li>
- <li class="active"><a href="/org/{{.Org.Name}}/settings">Settings</a></li>
- <!-- <li><a href="/pulls">Pull Requests</a></li>
- <li><a href="/stars">Stars</a></li> -->
- </ul>
- </div>
-</div>
-
-<div id="body" class="container" data-page="org">
- <div id="user-setting-nav" class="col-md-2 repo-setting-nav">
- <ul class="list-group">
- <li class="list-group-item active"><a href="#">Options</a></li>
- </ul>
- </div>
- <div id="repo-setting-container" class="col-md-10">
- {{template "base/alert" .}}
- <div class="panel panel-default">
- <div class="panel-heading">
- Organization Options
- </div>
-
- <div class="panel-body">
- <form action="/org/{{.Org.Name}}/settings" method="post" class="form-horizontal">
- {{.CsrfTokenHtml}}
- <input type="hidden" name="action" value="update">
-
- <div class="form-group{{if .Err_DisplayName}} has-error has-feedback{{end}}">
- <label class="col-md-3 text-right" for="org-setting-name">Display Name</label>
- <div class="col-md-9">
- <input class="form-control" name="display_name" value="{{.Org.FullName}}" title="" id="org-setting-name"/>
- </div>
- </div>
-
- <div class="form-group{{if .Err_Email}} has-error has-feedback{{end}}">
- <label class="col-md-3 text-right" for="org-email">Email</label>
- <div class="col-md-9">
- <input class="form-control" name="email" value="{{.Org.Email}}" title="" id="org-email" type="email"/>
- </div>
- </div>
-
- <div class="form-group{{if .Err_Description}} has-error has-feedback{{end}}">
- <label class="col-md-3 text-right" for="org-desc">Description</label>
- <div class="col-md-9">
- <textarea class="form-control" name="desc" id="org-desc" rows="3">{{.Org.Description}}</textarea>
- </div>
- </div>
-
- <div class="form-group{{if .Err_Website}} has-error has-feedback{{end}}">
- <label class="col-md-3 text-right" for="org-site">Official Site</label>
- <div class="col-md-9">
- <input type="url" class="form-control" name="site" value="{{.Org.Website}}" id="org-site"/>
- </div>
- </div>
-
- <div class="form-group{{if .Err_Location}} has-error has-feedback{{end}}">
- <label class="col-md-3 text-right" for="org-location">Location</label>
- <div class="col-md-9">
- <input class="form-control" name="location" value="{{.Org.Location}}" title="" id="org-location"/>
- </div>
- </div>
-
- <div class="form-group">
- <div class="col-md-9 col-md-offset-3">
- <button class="btn btn-primary" type="submit">Save Options</button>
- </div>
- </div>
- </form>
- </div>
- </div>
-
- <div class="panel panel-warning">
- <div class="panel-heading">
- Danger Zone
- </div>
- <div class="panel-body">
- <button type="button" class="btn btn-default pull-right" href="#delete-org-modal" data-toggle="modal">
- Delete this organization
- </button>
- <dd>
- <dt>Delete this organization</dt>
- <dl>Once you delete this organization and all repositories in, there is no going back. Please be
- certain.
- </dl>
- </dd>
-
- <div class="modal fade" id="delete-org-modal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel"
- aria-hidden="true">
- <div class="modal-dialog">
- <form action="/org/{{.Org.Name}}/settings/delete" method="post"
- class="modal-content">
- {{.CsrfTokenHtml}}
- <div class="modal-header">
- <button type="button" class="close" data-dismiss="modal"
- aria-hidden="true">&times;</button>
- <h4 class="modal-title" id="myModalLabel">Delete organization</h4>
- </div>
-
- <div class="modal-body">
- <div class="form-group">
- <label>Make sure your are owner of this organization. Please enter your password.<strong class="text-danger">*</strong></label>
- <input name="password" class="form-control" type="password" placeholder="Type your account password" required="required">
- </div>
- </div>
-
- <div class="modal-footer">
- <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
- <button class="btn btn-danger btn-lg">I understand the consequences, delete this
- organization
- </button>
- </div>
- </form>
- </div>
- </div>
- </div>
- </div>
- </div>
-</div>
-{{template "base/footer" .}}
diff --git a/templates/user/dashboard/dashboard.tmpl b/templates/user/dashboard/dashboard.tmpl
index c19c177e83..d0789b96d6 100644
--- a/templates/user/dashboard/dashboard.tmpl
+++ b/templates/user/dashboard/dashboard.tmpl
@@ -30,7 +30,7 @@
{{ $push := ActionContent2Commits .}}
{{ $repoLink := .GetRepoLink}}
{{range $push.Commits}}
- <li><img src="{{AvatarLink .AuthorEmail}}?s=16"> <a href="/{{$repoLink}}/commit/{{.Sha1}}">{{ShortSha .Sha1}}</a> {{.Message}}</li>
+ <li><img class="avatar-16" src="{{AvatarLink .AuthorEmail}}?s=16"> <a href="/{{$repoLink}}/commit/{{.Sha1}}">{{ShortSha .Sha1}}</a> {{.Message}}</li>
{{end}}
</ul>
</div>