Finish organization homepage
This commit is contained in:
		
							parent
							
								
									6e448b0714
								
							
						
					
					
						commit
						5dbfe3c26c
					
				
					 9 changed files with 179 additions and 109 deletions
				
			
		|  | @ -191,7 +191,7 @@ func runWeb(*cli.Context) { | |||
| 	m.Group("/org", func(r martini.Router) { | ||||
| 		r.Get("/create", org.New) | ||||
| 		r.Post("/create", bindIgnErr(auth.CreateOrgForm{}), org.NewPost) | ||||
| 		r.Get("/:org", org.Organization) | ||||
| 		r.Get("/:org", org.Home) | ||||
| 		r.Get("/:org/dashboard", org.Dashboard) | ||||
| 		r.Get("/:org/members", org.Members) | ||||
| 
 | ||||
|  |  | |||
|  | @ -20,6 +20,28 @@ func (org *User) GetOwnerTeam() (*Team, error) { | |||
| 	return t, err | ||||
| } | ||||
| 
 | ||||
| // GetTeams returns all teams that belong to organization.
 | ||||
| func (org *User) GetTeams() error { | ||||
| 	return x.Where("org_id=?", org.Id).Find(&org.Teams) | ||||
| } | ||||
| 
 | ||||
| // GetMembers returns all members of organization.
 | ||||
| func (org *User) GetMembers() error { | ||||
| 	ous, err := GetOrgUsersByOrgId(org.Id) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	org.Members = make([]*User, len(ous)) | ||||
| 	for i, ou := range ous { | ||||
| 		org.Members[i], err = GetUserById(ou.Uid) | ||||
| 		if err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
| 
 | ||||
| // CreateOrganization creates record of a new organization.
 | ||||
| func CreateOrganization(org, owner *User) (*User, error) { | ||||
| 	if !IsLegalName(org.Name) { | ||||
|  | @ -132,12 +154,13 @@ const ( | |||
| 	ORG_ADMIN | ||||
| ) | ||||
| 
 | ||||
| const OWNER_TEAM = "Owner" | ||||
| 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 | ||||
|  | @ -148,15 +171,19 @@ type Team struct { | |||
| 
 | ||||
| // NewTeam creates a record of new team.
 | ||||
| func NewTeam(t *Team) error { | ||||
| 	// TODO: check if same name team of organization exists.
 | ||||
| 	t.LowerName = strings.ToLower(t.Name) | ||||
| 	_, err := x.Insert(t) | ||||
| 	return err | ||||
| } | ||||
| 
 | ||||
| // 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 | ||||
| } | ||||
|  | @ -192,16 +219,18 @@ func GetOrgUsersByOrgId(orgId int64) ([]*OrgUser, error) { | |||
| 	return ous, err | ||||
| } | ||||
| 
 | ||||
| func GetOrganizationCount(u *User) (int64, error) { | ||||
| 	return x.Where("uid=?", u.Id).Count(new(OrgUser)) | ||||
| } | ||||
| 
 | ||||
| // IsOrganizationOwner returns true if given user ID is in the owner team.
 | ||||
| // IsOrganizationOwner returns true if given user is in the owner team.
 | ||||
| func IsOrganizationOwner(orgId, uid int64) bool { | ||||
| 	has, _ := x.Where("is_owner=?", true).Get(&OrgUser{Uid: uid, OrgId: orgId}) | ||||
| 	return has | ||||
| } | ||||
| 
 | ||||
| // IsOrganizationMember returns true if given user is member of organization.
 | ||||
| func IsOrganizationMember(orgId, uid int64) bool { | ||||
| 	has, _ := x.Get(&OrgUser{Uid: uid, OrgId: orgId}) | ||||
| 	return has | ||||
| } | ||||
| 
 | ||||
| // ___________                    ____ ___
 | ||||
| // \__    ___/___ _____    _____ |    |   \______ ___________
 | ||||
| //   |    |_/ __ \\__  \  /     \|    |   /  ___// __ \_  __ \
 | ||||
|  |  | |||
|  | @ -73,6 +73,8 @@ type User struct { | |||
| 	Description string | ||||
| 	NumTeams    int | ||||
| 	NumMembers  int | ||||
| 	Teams       []*Team `xorm:"-"` | ||||
| 	Members     []*User `xorm:"-"` | ||||
| } | ||||
| 
 | ||||
| // HomeLink returns the user home page link.
 | ||||
|  | @ -110,6 +112,11 @@ func (u *User) IsOrganization() bool { | |||
| 	return u.Type == ORGANIZATION | ||||
| } | ||||
| 
 | ||||
| // GetOrganizationCount returns count of membership of organization of user.
 | ||||
| func (u *User) GetOrganizationCount() (int64, error) { | ||||
| 	return x.Where("uid=?", u.Id).Count(new(OrgUser)) | ||||
| } | ||||
| 
 | ||||
| // GetOrganizations returns all organizations that user belongs to.
 | ||||
| func (u *User) GetOrganizations() error { | ||||
| 	ous, err := GetOrgUsersByUserId(u.Id) | ||||
|  | @ -331,7 +338,7 @@ func DeleteUser(u *User) error { | |||
| 	} | ||||
| 
 | ||||
| 	// Check membership of organization.
 | ||||
| 	count, err = GetOrganizationCount(u) | ||||
| 	count, err = u.GetOrganizationCount() | ||||
| 	if err != nil { | ||||
| 		return errors.New("modesl.GetRepositories(GetOrganizationCount): " + err.Error()) | ||||
| 	} else if count > 0 { | ||||
|  |  | |||
|  | @ -16,13 +16,45 @@ import ( | |||
| ) | ||||
| 
 | ||||
| const ( | ||||
| 	HOME     base.TplName = "org/home" | ||||
| 	NEW      base.TplName = "org/new" | ||||
| 	SETTINGS base.TplName = "org/settings" | ||||
| ) | ||||
| 
 | ||||
| func Organization(ctx *middleware.Context, params martini.Params) { | ||||
| func Home(ctx *middleware.Context, params martini.Params) { | ||||
| 	ctx.Data["Title"] = "Organization " + params["org"] | ||||
| 	ctx.HTML(200, "org/org") | ||||
| 
 | ||||
| 	org, err := models.GetUserByName(params["org"]) | ||||
| 	if err != nil { | ||||
| 		if err == models.ErrUserNotExist { | ||||
| 			ctx.Handle(404, "org.Home(GetUserByName)", err) | ||||
| 		} else { | ||||
| 			ctx.Handle(500, "org.Home(GetUserByName)", err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Org"] = org | ||||
| 
 | ||||
| 	ctx.Data["Repos"], err = models.GetRepositories(org.Id, | ||||
| 		ctx.IsSigned && models.IsOrganizationMember(org.Id, ctx.User.Id)) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(500, "org.Home(GetRepositories)", err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if err = org.GetMembers(); err != nil { | ||||
| 		ctx.Handle(500, "org.Home(GetMembers)", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Members"] = org.Members | ||||
| 
 | ||||
| 	if err = org.GetTeams(); err != nil { | ||||
| 		ctx.Handle(500, "org.Home(GetTeams)", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Teams"] = org.Teams | ||||
| 
 | ||||
| 	ctx.HTML(200, HOME) | ||||
| } | ||||
| 
 | ||||
| func Members(ctx *middleware.Context, params martini.Params) { | ||||
|  | @ -63,7 +95,7 @@ func NewPost(ctx *middleware.Context, form auth.CreateOrgForm) { | |||
| 			ctx.Data["Err_OrgName"] = true | ||||
| 			ctx.RenderWithErr(models.ErrRepoNameIllegal.Error(), NEW, &form) | ||||
| 		default: | ||||
| 			ctx.Handle(500, "user.NewPost(CreateUser)", err) | ||||
| 			ctx.Handle(500, "org.NewPost(CreateUser)", err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
|  |  | |||
|  | @ -37,11 +37,23 @@ func Create(ctx *middleware.Context) { | |||
| 	ctx.Data["LanguageIgns"] = models.LanguageIgns | ||||
| 	ctx.Data["Licenses"] = models.Licenses | ||||
| 
 | ||||
| 	ctxUser := ctx.User | ||||
| 	orgId, _ := base.StrTo(ctx.Query("org")).Int64() | ||||
| 	if orgId > 0 { | ||||
| 		org, err := models.GetUserById(orgId) | ||||
| 		if err != nil && err != models.ErrUserNotExist { | ||||
| 			ctx.Handle(500, "home.Dashboard(GetUserById)", err) | ||||
| 			return | ||||
| 		} | ||||
| 		ctxUser = org | ||||
| 	} | ||||
| 	ctx.Data["ContextUser"] = ctxUser | ||||
| 
 | ||||
| 	if err := ctx.User.GetOrganizations(); err != nil { | ||||
| 		ctx.Handle(500, "home.Dashboard(GetOrganizations)", err) | ||||
| 		return | ||||
| 	} | ||||
| 	ctx.Data["Orgs"] = ctx.User.Orgs | ||||
| 	ctx.Data["AllUsers"] = append([]*models.User{ctx.User}, ctx.User.Orgs...) | ||||
| 
 | ||||
| 	ctx.HTML(200, CREATE) | ||||
| } | ||||
|  | @ -76,6 +88,12 @@ func CreatePost(ctx *middleware.Context, form auth.CreateRepoForm) { | |||
| 			} | ||||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		// Check ownership of organization.
 | ||||
| 		if !models.IsOrganizationOwner(u.Id, ctx.User.Id) { | ||||
| 			ctx.Error(403) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	repo, err := models.CreateRepository(u, form.RepoName, form.Description, | ||||
|  |  | |||
|  | @ -83,6 +83,12 @@ func Profile(ctx *middleware.Context, params martini.Params) { | |||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if u.IsOrganization() { | ||||
| 		ctx.Redirect("/org/" + u.Name) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	// For security reason, hide e-mail address for anonymous visitors.
 | ||||
| 	if !ctx.IsSigned { | ||||
| 		u.Email = "" | ||||
|  |  | |||
							
								
								
									
										70
									
								
								templates/org/home.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								templates/org/home.tmpl
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,70 @@ | |||
| {{template "base/head" .}} | ||||
| {{template "base/navbar" .}} | ||||
| <div id="body-nav" class="org-nav"> | ||||
|     <div class="container clearfix"> | ||||
|         <div class="col-md-8" id="org-nav-wrapper"> | ||||
|             <img class="pull-left org-logo" src="{{.Org.AvatarLink}}?s=140" alt="" width="100"/> | ||||
|             <div id="org-nav-info"> | ||||
|                 <h2 class="org-name">{{.Org.FullName}}</h2> | ||||
|                 {{if .Org.Description}}<p class="org-description">{{.Org.Description}}</p>{{end}} | ||||
|                 <ul class="org-meta list-inline"> | ||||
|                     {{if .Org.Website}}<li><i class="fa fa-link"></i><a target="_blank" href="{{.Org.Website}}">{{.Org.Website}}</a></li>{{end}} | ||||
|                     <li><i class="fa fa-envelope"></i><a href="mailto:{{.Org.Email}}">{{.Org.Email}}</a></li> | ||||
|                 </ul> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| <div id="body" class="container"> | ||||
|     <div id="org"> | ||||
|         <div class="org-main col-md-8"> | ||||
|             <div class="org-toolbar clearfix"> | ||||
|                 <a class="btn pull-right btn-success" href="/repo/create?org={{.Org.Id}}"><i class="fa fa-plus"></i> New Repository</a> | ||||
|             </div> | ||||
|             <hr style="width: 100%;border-color: #DDD"/> | ||||
|             <div class="org-repo-list" id="org-repo-list"> | ||||
|                 {{range .Repos}} | ||||
|                 <div class="org-repo-item"> | ||||
|                     <div class="org-repo-status pull-right"> | ||||
|                         <!-- <ul class="list-inline"> | ||||
|                             <li><strong>Go</strong></li> | ||||
|                             <li><i class="i fa fa-star"></i><strong>6</strong></li> | ||||
|                             <li><i class="fa fa-code-fork"></i><strong>2</strong></li> | ||||
|                         </ul> --> | ||||
|                     </div> | ||||
|                     <h3 class="org-repo-name"><a href="/{{$.Org.Name}}/{{.Name}}">{{.Name}}</a></h3> | ||||
|                     <p class="org-repo-description">{{.Description}}</p> | ||||
|                     <p class="org-repo-update">Updated {{TimeSince .Updated}}</p> | ||||
|                 </div> | ||||
|                 {{end}} | ||||
|             </div> | ||||
|         </div> | ||||
| 
 | ||||
|         <div class="org-sidebar col-md-4"> | ||||
|             <div class="org-panel panel panel-default" id="org-sidebar-members"> | ||||
|                 <div class="panel-heading"><strong><a href="/org/{{$.Org.Name}}/members">Members</a></strong></div> | ||||
|                 <div class="panel-body"> | ||||
|                     {{range .Members}} | ||||
|                     <a class="org-member" href="/user/{{.Name}}" data-toggle="tooltip" title="{{.Name}}" data-placement="bottom"><img src="{{.AvatarLink}}?s=140" alt=""/></a> | ||||
|                     {{end}} | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="org-panel panel panel-default" id="org-sidebar-teams"> | ||||
|                 <div class="panel-heading"><strong><a href="/org/{{$.Org.Name}}/teams">Teams</a></strong></div> | ||||
|                 <div class="panel-body"> | ||||
|                     {{range .Teams}} | ||||
|                     <div class="org-team"> | ||||
|                         <a href="/org/{{$.Org.Name}}/teams/{{.LowerName}}"> | ||||
|                             <p class="org-team-name"><strong>{{.Name}}</strong></p> | ||||
|                             <p class="org-team-meta"> | ||||
|                                 {{.NumMembers}} members · {{.NumRepos}} repositories | ||||
|                             </p> | ||||
|                         </a> | ||||
|                     </div> | ||||
|                     {{end}} | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|  | @ -1,85 +0,0 @@ | |||
| {{template "base/head" .}} | ||||
| {{template "base/navbar" .}} | ||||
| <div id="body-nav" class="org-nav"> | ||||
|     <div class="container clearfix"> | ||||
|         <div class="col-md-8" id="org-nav-wrapper"> | ||||
|             <img class="pull-left org-logo" src="https://avatars3.githubusercontent.com/u/6656686?s=140" alt="" width="100"/> | ||||
|             <div id="org-nav-info"> | ||||
|                 <h2 class="org-name">Organization Name</h2> | ||||
|                 <p class="org-description">Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language.</p> | ||||
|                 <ul class="org-meta list-inline"> | ||||
|                     <li><i class="fa fa-link"></i><a href="#">http://gogs.io</a></li> | ||||
|                     <li><i class="fa fa-envelope"></i><a href="#">info@gogs.io</a></li> | ||||
|                 </ul> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| <div id="body" class="container"> | ||||
|     <div id="org"> | ||||
|         <div class="org-main col-md-8"> | ||||
|             <div class="org-toolbar clearfix"> | ||||
|                 <button class="btn pull-right btn-success"><i class="fa fa-plus"></i> New Repository</button> | ||||
|             </div> | ||||
|             <hr style="width: 100%;border-color: #DDD"/> | ||||
|             <div class="org-repo-list" id="org-repo-list"> | ||||
|                 <div class="org-repo-item"> | ||||
|                     <div class="org-repo-status pull-right"> | ||||
|                         <ul class="list-inline"> | ||||
|                             <li><strong>Go</strong></li> | ||||
|                             <li><i class="i fa fa-star"></i><strong>6</strong></li> | ||||
|                             <li><i class="fa fa-code-fork"></i><strong>2</strong></li> | ||||
|                         </ul> | ||||
|                     </div> | ||||
|                     <h3 class="org-repo-name"><a href="#">gogs</a></h3> | ||||
|                     <p class="org-repo-description">Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language.</p> | ||||
|                     <p class="org-repo-update">Updated 17 hours ago</p> | ||||
|                 </div> | ||||
|                 <div class="org-repo-item"> | ||||
|                     <div class="org-repo-status pull-right"> | ||||
|                         <ul class="list-inline"> | ||||
|                             <li><strong>Go</strong></li> | ||||
|                             <li><i class="i fa fa-star"></i><strong>6</strong></li> | ||||
|                             <li><i class="fa fa-code-fork"></i><strong>2</strong></li> | ||||
|                         </ul> | ||||
|                     </div> | ||||
|                     <h3 class="org-repo-name"><a href="#">gogs</a></h3> | ||||
|                     <p class="org-repo-description">Gogs(Go Git Service) is a Self Hosted Git Service in the Go Programming Language.</p> | ||||
|                     <p class="org-repo-update">Updated 17 hours ago</p> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class="org-sidebar col-md-4"> | ||||
|             <div class="org-panel panel panel-default" id="org-sidebar-members"> | ||||
|                 <div class="panel-heading"><strong>Members</strong></div> | ||||
|                 <div class="panel-body"> | ||||
|                     <a class="org-member" href="#" data-toggle="tooltip" title="username" data-placement="bottom"><img src="https://avatars3.githubusercontent.com/u/6656686?s=140" alt=""/></a> | ||||
|                     <a class="org-member" href="#" data-toggle="tooltip" title="username" data-placement="bottom"><img src="https://avatars3.githubusercontent.com/u/6656686?s=140" alt=""/></a> | ||||
|                     <a class="org-member" href="#" data-toggle="tooltip" title="username" data-placement="bottom"><img src="https://avatars3.githubusercontent.com/u/6656686?s=140" alt=""/></a> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="org-panel panel panel-default" id="org-sidebar-teams"> | ||||
|                 <div class="panel-heading"><strong>Teams</strong></div> | ||||
|                 <div class="panel-body"> | ||||
|                     <div class="org-team"> | ||||
|                         <a href="#"> | ||||
|                             <p class="org-team-name"><strong>Team name</strong></p> | ||||
|                             <p class="org-team-meta"> | ||||
|                                 4 members · 10 repositories | ||||
|                             </p> | ||||
|                         </a> | ||||
|                     </div> | ||||
|                     <div class="org-team"> | ||||
|                         <a href="#"> | ||||
|                             <p class="org-team-name"><strong>Team name</strong></p> | ||||
|                             <p class="org-team-meta"> | ||||
|                                 4 members · 10 repositories | ||||
|                             </p> | ||||
|                         </a> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|  | @ -10,23 +10,16 @@ | |||
|             <div class="col-md-8"> | ||||
|                 <div class="btn-group" id="repo-owner-switch"> | ||||
|                     <button type="button" class="btn btn-default" id="repo-owner-current"> | ||||
|                         <img src="{{.SignedUser.AvatarLink}}?s=28" alt="user-avatar" title="username" id="repo-owner-avatar"> | ||||
|                         <span id="repo-owner-name">{{.SignedUser.Name}}</span> | ||||
|                         <img src="{{.ContextUser.AvatarLink}}?s=28" alt="user-avatar" title="username" id="repo-owner-avatar"> | ||||
|                         <span id="repo-owner-name">{{.ContextUser.Name}}</span> | ||||
|                     </button> | ||||
|                     <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> | ||||
|                         <span class="caret"></span> | ||||
|                     </button> | ||||
|                     <div class="dropdown-menu clone-group-btn no-propagation"> | ||||
|                         <ul id="dashboard-switch-menu" class="list-unstyled"> | ||||
|                             <li data-uid="{{.SignedUser.Id}}" class="checked"> | ||||
|                                 <a> | ||||
|                                     <i class="fa fa-check"></i> | ||||
|                                     <img src="{{.SignedUser.AvatarLink}}?s=28" alt="user-avatar" title="username"> | ||||
|                                     {{.SignedUser.Name}} | ||||
|                                 </a> | ||||
|                             </li> | ||||
|                             {{range .Orgs}} | ||||
|                             <li data-uid="{{.Id}}"> | ||||
|                             {{range .AllUsers}} | ||||
|                             <li data-uid="{{.Id}}"{{if eq .Id $.ContextUser.Id}}class="checked"{{end}}> | ||||
|                                 <a> | ||||
|                                     <i class="fa fa-check"></i> | ||||
|                                     <img src="{{.AvatarLink}}?s=28" alt="user-avatar" title="username"> | ||||
|  | @ -38,7 +31,7 @@ | |||
|                     </div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <input type="hidden" value="{{.SignedUserId}}" name="uid" id="repo-owner-id"/> | ||||
|             <input type="hidden" value="{{.ContextUser.Id}}" name="uid" id="repo-owner-id"/> | ||||
|         </div> | ||||
| 
 | ||||
|         <div class="form-group {{if .Err_RepoName}}has-error has-feedback{{end}}"> | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue