mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	#13 finish user and repository search
Both are possible on explore and admin panel
This commit is contained in:
		| @@ -3,7 +3,7 @@ Gogs - Go Git Service [ |  | ||||||
|  |  | ||||||
| ##### Current version: 0.9.5 | ##### Current version: 0.9.6 | ||||||
|  |  | ||||||
| | Web | UI  | Preview  | | | Web | UI  | Preview  | | ||||||
| |:-------------:|:-------:|:-------:| | |:-------------:|:-------:|:-------:| | ||||||
|   | |||||||
| @@ -193,7 +193,10 @@ func runWeb(ctx *cli.Context) { | |||||||
| 	// Especially some AJAX requests, we can reduce middleware number to improve performance. | 	// Especially some AJAX requests, we can reduce middleware number to improve performance. | ||||||
| 	// Routers. | 	// Routers. | ||||||
| 	m.Get("/", ignSignIn, routers.Home) | 	m.Get("/", ignSignIn, routers.Home) | ||||||
| 	m.Get("/explore", ignSignIn, routers.Explore) | 	m.Group("/explore", func() { | ||||||
|  | 		m.Get("/repos", routers.ExploreRepos) | ||||||
|  | 		m.Get("/users", routers.ExploreUsers) | ||||||
|  | 	}, ignSignIn) | ||||||
| 	m.Combo("/install", routers.InstallInit).Get(routers.Install). | 	m.Combo("/install", routers.InstallInit).Get(routers.Install). | ||||||
| 		Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost) | 		Post(bindIgnErr(auth.InstallForm{}), routers.InstallPost) | ||||||
| 	m.Get("/^:type(issues|pulls)$", reqSignIn, user.Issues) | 	m.Get("/^:type(issues|pulls)$", reqSignIn, user.Issues) | ||||||
|   | |||||||
| @@ -44,13 +44,6 @@ issues = Issues | |||||||
|  |  | ||||||
| cancel = Cancel | cancel = Cancel | ||||||
|  |  | ||||||
| [search] |  | ||||||
| search = Search... |  | ||||||
| repository = Repository |  | ||||||
| user = User |  | ||||||
| issue = Issue |  | ||||||
| code = Code |  | ||||||
|  |  | ||||||
| [install] | [install] | ||||||
| install = Installation | install = Installation | ||||||
| title = Install Steps For First-time Run | title = Install Steps For First-time Run | ||||||
| @@ -140,6 +133,8 @@ issues.in_your_repos = In your repositories | |||||||
|  |  | ||||||
| [explore] | [explore] | ||||||
| repos = Repositories | repos = Repositories | ||||||
|  | users = Users | ||||||
|  | search = Search | ||||||
|  |  | ||||||
| [auth] | [auth] | ||||||
| create_new_account = Create New Account | create_new_account = Create New Account | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							| @@ -17,7 +17,7 @@ import ( | |||||||
| 	"github.com/gogits/gogs/modules/setting" | 	"github.com/gogits/gogs/modules/setting" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const APP_VER = "0.9.5.0311" | const APP_VER = "0.9.6.0311" | ||||||
|  |  | ||||||
| func init() { | func init() { | ||||||
| 	runtime.GOMAXPROCS(runtime.NumCPU()) | 	runtime.GOMAXPROCS(runtime.NumCPU()) | ||||||
|   | |||||||
| @@ -169,7 +169,7 @@ func GetOrgByName(name string) (*User, error) { | |||||||
| 	} | 	} | ||||||
| 	u := &User{ | 	u := &User{ | ||||||
| 		LowerName: strings.ToLower(name), | 		LowerName: strings.ToLower(name), | ||||||
| 		Type:      ORGANIZATION, | 		Type:      USER_TYPE_ORGANIZATION, | ||||||
| 	} | 	} | ||||||
| 	has, err := x.Get(u) | 	has, err := x.Get(u) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|   | |||||||
| @@ -1049,11 +1049,16 @@ func CountPublicRepositories() int64 { | |||||||
| 	return countRepositories(false) | 	return countRepositories(false) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func Repositories(page, pageSize int) (_ []*Repository, err error) { | ||||||
|  | 	repos := make([]*Repository, 0, pageSize) | ||||||
|  | 	return repos, x.Limit(pageSize, (page-1)*pageSize).Asc("id").Find(&repos) | ||||||
|  | } | ||||||
|  |  | ||||||
| // RepositoriesWithUsers returns number of repos in given page. | // RepositoriesWithUsers returns number of repos in given page. | ||||||
| func RepositoriesWithUsers(page, pageSize int) (_ []*Repository, err error) { | func RepositoriesWithUsers(page, pageSize int) (_ []*Repository, err error) { | ||||||
| 	repos := make([]*Repository, 0, pageSize) | 	repos, err := Repositories(page, pageSize) | ||||||
| 	if err = x.Limit(pageSize, (page-1)*pageSize).Asc("id").Find(&repos); err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, fmt.Errorf("Repositories: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for i := range repos { | 	for i := range repos { | ||||||
| @@ -1474,9 +1479,9 @@ func GetRepositories(uid int64, private bool) ([]*Repository, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // GetRecentUpdatedRepositories returns the list of repositories that are recently updated. | // GetRecentUpdatedRepositories returns the list of repositories that are recently updated. | ||||||
| func GetRecentUpdatedRepositories(page int) (repos []*Repository, err error) { | func GetRecentUpdatedRepositories(page, pageSize int) (repos []*Repository, err error) { | ||||||
| 	return repos, x.Limit(setting.ExplorePagingNum, (page-1)*setting.ExplorePagingNum). | 	return repos, x.Limit(pageSize, (page-1)*pageSize). | ||||||
| 		Where("is_private=?", false).Limit(setting.ExplorePagingNum).Desc("updated_unix").Find(&repos) | 		Where("is_private=?", false).Limit(pageSize).Desc("updated_unix").Find(&repos) | ||||||
| } | } | ||||||
|  |  | ||||||
| func getRepositoryCount(e Engine, u *User) (int64, error) { | func getRepositoryCount(e Engine, u *User) (int64, error) { | ||||||
| @@ -1488,32 +1493,52 @@ func GetRepositoryCount(u *User) (int64, error) { | |||||||
| 	return getRepositoryCount(x, u) | 	return getRepositoryCount(x, u) | ||||||
| } | } | ||||||
|  |  | ||||||
| type SearchOption struct { | type SearchRepoOptions struct { | ||||||
| 	Keyword string | 	Keyword  string | ||||||
| 	Uid     int64 | 	OwnerID  int64 | ||||||
| 	Limit   int | 	OrderBy  string | ||||||
| 	Private bool | 	Private  bool // Include private repositories in results | ||||||
|  | 	Page     int | ||||||
|  | 	PageSize int // Can be smaller than or equal to setting.ExplorePagingNum | ||||||
| } | } | ||||||
|  |  | ||||||
| // SearchRepositoryByName returns given number of repositories whose name contains keyword. | // SearchRepositoryByName takes keyword and part of repository name to search, | ||||||
| func SearchRepositoryByName(opt SearchOption) (repos []*Repository, err error) { | // it returns results in given range and number of total results. | ||||||
| 	if len(opt.Keyword) == 0 { | func SearchRepositoryByName(opts *SearchRepoOptions) (repos []*Repository, _ int64, _ error) { | ||||||
| 		return repos, nil | 	if len(opts.Keyword) == 0 { | ||||||
|  | 		return repos, 0, nil | ||||||
| 	} | 	} | ||||||
| 	opt.Keyword = strings.ToLower(opt.Keyword) | 	opts.Keyword = strings.ToLower(opts.Keyword) | ||||||
|  |  | ||||||
| 	repos = make([]*Repository, 0, opt.Limit) | 	if opts.PageSize <= 0 || opts.PageSize > setting.ExplorePagingNum { | ||||||
|  | 		opts.PageSize = setting.ExplorePagingNum | ||||||
| 	// Append conditions. |  | ||||||
| 	sess := x.Limit(opt.Limit) |  | ||||||
| 	if opt.Uid > 0 { |  | ||||||
| 		sess.Where("owner_id=?", opt.Uid) |  | ||||||
| 	} | 	} | ||||||
| 	if !opt.Private { | 	if opts.Page <= 0 { | ||||||
|  | 		opts.Page = 1 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	repos = make([]*Repository, 0, opts.PageSize) | ||||||
|  |  | ||||||
|  | 	// Append conditions | ||||||
|  | 	sess := x.Where("lower_name like ?", "%"+opts.Keyword+"%") | ||||||
|  | 	if opts.OwnerID > 0 { | ||||||
|  | 		sess.And("owner_id = ?", opts.OwnerID) | ||||||
|  | 	} | ||||||
|  | 	if !opts.Private { | ||||||
| 		sess.And("is_private=?", false) | 		sess.And("is_private=?", false) | ||||||
| 	} | 	} | ||||||
| 	sess.And("lower_name like ?", "%"+opt.Keyword+"%").Find(&repos) | 	if len(opts.OrderBy) > 0 { | ||||||
| 	return repos, err | 		sess.OrderBy(opts.OrderBy) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var countSess xorm.Session | ||||||
|  | 	countSess = *sess | ||||||
|  | 	count, err := countSess.Count(new(Repository)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, 0, fmt.Errorf("Count: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return repos, count, sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).Find(&repos) | ||||||
| } | } | ||||||
|  |  | ||||||
| // DeleteRepositoryArchives deletes all repositories' archives. | // DeleteRepositoryArchives deletes all repositories' archives. | ||||||
|   | |||||||
| @@ -36,8 +36,8 @@ import ( | |||||||
| type UserType int | type UserType int | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| 	INDIVIDUAL UserType = iota // Historic reason to make it starts at 0. | 	USER_TYPE_INDIVIDUAL UserType = iota // Historic reason to make it starts at 0. | ||||||
| 	ORGANIZATION | 	USER_TYPE_ORGANIZATION | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var ( | var ( | ||||||
| @@ -389,7 +389,7 @@ func (u *User) IsWriterOfRepo(repo *Repository) bool { | |||||||
|  |  | ||||||
| // IsOrganization returns true if user is actually a organization. | // IsOrganization returns true if user is actually a organization. | ||||||
| func (u *User) IsOrganization() bool { | func (u *User) IsOrganization() bool { | ||||||
| 	return u.Type == ORGANIZATION | 	return u.Type == USER_TYPE_ORGANIZATION | ||||||
| } | } | ||||||
|  |  | ||||||
| // IsUserOrgOwner returns true if user is in the owner team of given organization. | // IsUserOrgOwner returns true if user is in the owner team of given organization. | ||||||
| @@ -1114,16 +1114,45 @@ func GetUserByEmail(email string) (*User, error) { | |||||||
| 	return nil, ErrUserNotExist{0, email} | 	return nil, ErrUserNotExist{0, email} | ||||||
| } | } | ||||||
|  |  | ||||||
| // SearchUserByName returns given number of users whose name contains keyword. | type SearchUserOptions struct { | ||||||
| func SearchUserByName(opt SearchOption) (us []*User, err error) { | 	Keyword  string | ||||||
| 	if len(opt.Keyword) == 0 { | 	Type     UserType | ||||||
| 		return us, nil | 	OrderBy  string | ||||||
| 	} | 	Page     int | ||||||
| 	opt.Keyword = strings.ToLower(opt.Keyword) | 	PageSize int // Can be smaller than or equal to setting.ExplorePagingNum | ||||||
|  | } | ||||||
|  |  | ||||||
| 	us = make([]*User, 0, opt.Limit) | // SearchUserByName takes keyword and part of user name to search, | ||||||
| 	err = x.Limit(opt.Limit).Where("type=0").And("lower_name like ?", "%"+opt.Keyword+"%").Find(&us) | // it returns results in given range and number of total results. | ||||||
| 	return us, err | func SearchUserByName(opts *SearchUserOptions) (users []*User, _ int64, _ error) { | ||||||
|  | 	if len(opts.Keyword) == 0 { | ||||||
|  | 		return users, 0, nil | ||||||
|  | 	} | ||||||
|  | 	opts.Keyword = strings.ToLower(opts.Keyword) | ||||||
|  |  | ||||||
|  | 	if opts.PageSize <= 0 || opts.PageSize > setting.ExplorePagingNum { | ||||||
|  | 		opts.PageSize = setting.ExplorePagingNum | ||||||
|  | 	} | ||||||
|  | 	if opts.Page <= 0 { | ||||||
|  | 		opts.Page = 1 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	users = make([]*User, 0, opts.PageSize) | ||||||
|  | 	// Append conditions | ||||||
|  | 	fmt.Println(opts.Type) | ||||||
|  | 	sess := x.Where("lower_name like ?", "%"+opts.Keyword+"%").And("type = ?", opts.Type) | ||||||
|  | 	if len(opts.OrderBy) > 0 { | ||||||
|  | 		sess.OrderBy(opts.OrderBy) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var countSess xorm.Session | ||||||
|  | 	countSess = *sess | ||||||
|  | 	count, err := countSess.Count(new(User)) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, 0, fmt.Errorf("Count: %v", err) | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return users, count, sess.Limit(opts.PageSize, (opts.Page-1)*opts.PageSize).Find(&users) | ||||||
| } | } | ||||||
|  |  | ||||||
| // ___________    .__  .__ | // ___________    .__  .__ | ||||||
|   | |||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @@ -441,30 +441,30 @@ | |||||||
| 		"outputStyle": 1, | 		"outputStyle": 1, | ||||||
| 		"syntaxCheckerStyle": 1 | 		"syntaxCheckerStyle": 1 | ||||||
| 		}, | 		}, | ||||||
| 	"\/plugins\/highlight-9.1.0\/default.css": { | 	"\/plugins\/highlight-9.2.0\/default.css": { | ||||||
| 		"fileType": 16, | 		"fileType": 16, | ||||||
| 		"ignore": 0, | 		"ignore": 0, | ||||||
| 		"ignoreWasSetByUser": 0, | 		"ignoreWasSetByUser": 0, | ||||||
| 		"inputAbbreviatedPath": "\/plugins\/highlight-9.1.0\/default.css", | 		"inputAbbreviatedPath": "\/plugins\/highlight-9.2.0\/default.css", | ||||||
| 		"outputAbbreviatedPath": "No Output Path", | 		"outputAbbreviatedPath": "No Output Path", | ||||||
| 		"outputPathIsOutsideProject": 0, | 		"outputPathIsOutsideProject": 0, | ||||||
| 		"outputPathIsSetByUser": 0 | 		"outputPathIsSetByUser": 0 | ||||||
| 		}, | 		}, | ||||||
| 	"\/plugins\/highlight-9.1.0\/github.css": { | 	"\/plugins\/highlight-9.2.0\/github.css": { | ||||||
| 		"fileType": 16, | 		"fileType": 16, | ||||||
| 		"ignore": 0, | 		"ignore": 0, | ||||||
| 		"ignoreWasSetByUser": 0, | 		"ignoreWasSetByUser": 0, | ||||||
| 		"inputAbbreviatedPath": "\/plugins\/highlight-9.1.0\/github.css", | 		"inputAbbreviatedPath": "\/plugins\/highlight-9.2.0\/github.css", | ||||||
| 		"outputAbbreviatedPath": "No Output Path", | 		"outputAbbreviatedPath": "No Output Path", | ||||||
| 		"outputPathIsOutsideProject": 0, | 		"outputPathIsOutsideProject": 0, | ||||||
| 		"outputPathIsSetByUser": 0 | 		"outputPathIsSetByUser": 0 | ||||||
| 		}, | 		}, | ||||||
| 	"\/plugins\/highlight-9.1.0\/highlight.pack.js": { | 	"\/plugins\/highlight-9.2.0\/highlight.pack.js": { | ||||||
| 		"fileType": 64, | 		"fileType": 64, | ||||||
| 		"ignore": 0, | 		"ignore": 0, | ||||||
| 		"ignoreWasSetByUser": 0, | 		"ignoreWasSetByUser": 0, | ||||||
| 		"inputAbbreviatedPath": "\/plugins\/highlight-9.1.0\/highlight.pack.js", | 		"inputAbbreviatedPath": "\/plugins\/highlight-9.2.0\/highlight.pack.js", | ||||||
| 		"outputAbbreviatedPath": "\/plugins\/highlight-9.1.0\/min\/highlight.pack-min.js", | 		"outputAbbreviatedPath": "\/plugins\/highlight-9.2.0\/min\/highlight.pack-min.js", | ||||||
| 		"outputPathIsOutsideProject": 0, | 		"outputPathIsOutsideProject": 0, | ||||||
| 		"outputPathIsSetByUser": 0, | 		"outputPathIsSetByUser": 0, | ||||||
| 		"outputStyle": 1, | 		"outputStyle": 1, | ||||||
|   | |||||||
| @@ -2594,6 +2594,10 @@ footer .container .links > *:first-child { | |||||||
|   padding-top: 15px; |   padding-top: 15px; | ||||||
|   padding-bottom: 80px; |   padding-bottom: 80px; | ||||||
| } | } | ||||||
|  | .explore .navbar .octicon { | ||||||
|  |   width: 16px; | ||||||
|  |   text-align: center; | ||||||
|  | } | ||||||
| .ui.repository.list .item { | .ui.repository.list .item { | ||||||
|   padding-bottom: 25px; |   padding-bottom: 25px; | ||||||
| } | } | ||||||
| @@ -2620,3 +2624,26 @@ footer .container .links > *:first-child { | |||||||
|   font-size: 12px; |   font-size: 12px; | ||||||
|   color: #808080; |   color: #808080; | ||||||
| } | } | ||||||
|  | .ui.user.list .item { | ||||||
|  |   padding-bottom: 25px; | ||||||
|  | } | ||||||
|  | .ui.user.list .item:not(:first-child) { | ||||||
|  |   border-top: 1px solid #eee; | ||||||
|  |   padding-top: 25px; | ||||||
|  | } | ||||||
|  | .ui.user.list .item .ui.avatar.image { | ||||||
|  |   width: 40px; | ||||||
|  |   height: 40px; | ||||||
|  | } | ||||||
|  | .ui.user.list .item .description { | ||||||
|  |   margin-top: 5px; | ||||||
|  | } | ||||||
|  | .ui.user.list .item .description .octicon:not(:first-child) { | ||||||
|  |   margin-left: 5px; | ||||||
|  | } | ||||||
|  | .ui.user.list .item .description a { | ||||||
|  |   color: #333; | ||||||
|  | } | ||||||
|  | .ui.user.list .item .description a:hover { | ||||||
|  |   text-decoration: underline; | ||||||
|  | } | ||||||
|   | |||||||
| @@ -1,6 +1,13 @@ | |||||||
| .explore { | .explore { | ||||||
| 	padding-top: 15px; | 	padding-top: 15px; | ||||||
| 	padding-bottom: @footer-margin * 2; | 	padding-bottom: @footer-margin * 2; | ||||||
|  |  | ||||||
|  | 	.navbar { | ||||||
|  | 		.octicon { | ||||||
|  | 			width: 16px; | ||||||
|  | 			text-align: center; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| .ui.repository.list { | .ui.repository.list { | ||||||
| @@ -35,3 +42,34 @@ | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .ui.user.list { | ||||||
|  | 	.item { | ||||||
|  | 		padding-bottom: 25px; | ||||||
|  |  | ||||||
|  | 		&:not(:first-child) { | ||||||
|  | 			border-top: 1px solid #eee; | ||||||
|  | 			padding-top: 25px; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.ui.avatar.image { | ||||||
|  | 			width: 40px; | ||||||
|  | 			height: 40px; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		.description { | ||||||
|  | 			margin-top: 5px; | ||||||
|  |  | ||||||
|  | 			.octicon:not(:first-child) { | ||||||
|  | 				margin-left: 5px; | ||||||
|  | 			} | ||||||
|  |  | ||||||
|  | 			a { | ||||||
|  | 				color: #333; | ||||||
|  | 				&:hover { | ||||||
|  | 					text-decoration: underline; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @@ -5,12 +5,11 @@ | |||||||
| package admin | package admin | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/Unknwon/paginater" |  | ||||||
|  |  | ||||||
| 	"github.com/gogits/gogs/models" | 	"github.com/gogits/gogs/models" | ||||||
| 	"github.com/gogits/gogs/modules/base" | 	"github.com/gogits/gogs/modules/base" | ||||||
| 	"github.com/gogits/gogs/modules/context" | 	"github.com/gogits/gogs/modules/context" | ||||||
| 	"github.com/gogits/gogs/modules/setting" | 	"github.com/gogits/gogs/modules/setting" | ||||||
|  | 	"github.com/gogits/gogs/routers" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| @@ -22,22 +21,6 @@ func Organizations(ctx *context.Context) { | |||||||
| 	ctx.Data["PageIsAdmin"] = true | 	ctx.Data["PageIsAdmin"] = true | ||||||
| 	ctx.Data["PageIsAdminOrganizations"] = true | 	ctx.Data["PageIsAdminOrganizations"] = true | ||||||
|  |  | ||||||
| 	total := models.CountOrganizations() | 	routers.RenderUserSearch(ctx, models.USER_TYPE_ORGANIZATION, models.CountOrganizations, models.Organizations, | ||||||
| 	page := ctx.QueryInt("page") | 		setting.AdminOrgPagingNum, "id ASC", ORGS) | ||||||
| 	if page <= 1 { |  | ||||||
| 		page = 1 |  | ||||||
| 	} |  | ||||||
| 	ctx.Data["Page"] = paginater.New(int(total), setting.AdminOrgPagingNum, page, 5) |  | ||||||
|  |  | ||||||
| 	orgs, err := models.Organizations(page, setting.AdminOrgPagingNum) |  | ||||||
|  |  | ||||||
| 	if err != nil { |  | ||||||
| 		ctx.Handle(500, "Organizations", err) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	ctx.Data["Orgs"] = orgs |  | ||||||
| 	ctx.Data["Total"] = total |  | ||||||
|  |  | ||||||
| 	ctx.HTML(200, ORGS) |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -5,13 +5,12 @@ | |||||||
| package admin | package admin | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/Unknwon/paginater" |  | ||||||
|  |  | ||||||
| 	"github.com/gogits/gogs/models" | 	"github.com/gogits/gogs/models" | ||||||
| 	"github.com/gogits/gogs/modules/base" | 	"github.com/gogits/gogs/modules/base" | ||||||
| 	"github.com/gogits/gogs/modules/context" | 	"github.com/gogits/gogs/modules/context" | ||||||
| 	"github.com/gogits/gogs/modules/log" | 	"github.com/gogits/gogs/modules/log" | ||||||
| 	"github.com/gogits/gogs/modules/setting" | 	"github.com/gogits/gogs/modules/setting" | ||||||
|  | 	"github.com/gogits/gogs/routers" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| @@ -23,22 +22,8 @@ func Repos(ctx *context.Context) { | |||||||
| 	ctx.Data["PageIsAdmin"] = true | 	ctx.Data["PageIsAdmin"] = true | ||||||
| 	ctx.Data["PageIsAdminRepositories"] = true | 	ctx.Data["PageIsAdminRepositories"] = true | ||||||
|  |  | ||||||
| 	total := models.CountRepositories() | 	routers.RenderRepoSearch(ctx, models.CountRepositories, models.Repositories, | ||||||
| 	page := ctx.QueryInt("page") | 		setting.AdminRepoPagingNum, "id ASC", REPOS) | ||||||
| 	if page <= 1 { |  | ||||||
| 		page = 1 |  | ||||||
| 	} |  | ||||||
| 	ctx.Data["Page"] = paginater.New(int(total), setting.AdminRepoPagingNum, page, 5) |  | ||||||
|  |  | ||||||
| 	repos, err := models.RepositoriesWithUsers(page, setting.AdminRepoPagingNum) |  | ||||||
| 	if err != nil { |  | ||||||
| 		ctx.Handle(500, "RepositoriesWithUsers", err) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	ctx.Data["Repos"] = repos |  | ||||||
|  |  | ||||||
| 	ctx.Data["Total"] = total |  | ||||||
| 	ctx.HTML(200, REPOS) |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func DeleteRepo(ctx *context.Context) { | func DeleteRepo(ctx *context.Context) { | ||||||
|   | |||||||
| @@ -8,7 +8,6 @@ import ( | |||||||
| 	"strings" | 	"strings" | ||||||
|  |  | ||||||
| 	"github.com/Unknwon/com" | 	"github.com/Unknwon/com" | ||||||
| 	"github.com/Unknwon/paginater" |  | ||||||
|  |  | ||||||
| 	"github.com/gogits/gogs/models" | 	"github.com/gogits/gogs/models" | ||||||
| 	"github.com/gogits/gogs/modules/auth" | 	"github.com/gogits/gogs/modules/auth" | ||||||
| @@ -17,6 +16,7 @@ import ( | |||||||
| 	"github.com/gogits/gogs/modules/log" | 	"github.com/gogits/gogs/modules/log" | ||||||
| 	"github.com/gogits/gogs/modules/mailer" | 	"github.com/gogits/gogs/modules/mailer" | ||||||
| 	"github.com/gogits/gogs/modules/setting" | 	"github.com/gogits/gogs/modules/setting" | ||||||
|  | 	"github.com/gogits/gogs/routers" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| const ( | const ( | ||||||
| @@ -30,22 +30,8 @@ func Users(ctx *context.Context) { | |||||||
| 	ctx.Data["PageIsAdmin"] = true | 	ctx.Data["PageIsAdmin"] = true | ||||||
| 	ctx.Data["PageIsAdminUsers"] = true | 	ctx.Data["PageIsAdminUsers"] = true | ||||||
|  |  | ||||||
| 	total := models.CountUsers() | 	routers.RenderUserSearch(ctx, models.USER_TYPE_INDIVIDUAL, models.CountUsers, models.Users, | ||||||
| 	page := ctx.QueryInt("page") | 		setting.AdminUserPagingNum, "id ASC", USERS) | ||||||
| 	if page <= 1 { |  | ||||||
| 		page = 1 |  | ||||||
| 	} |  | ||||||
| 	ctx.Data["Page"] = paginater.New(int(total), setting.AdminUserPagingNum, page, 5) |  | ||||||
|  |  | ||||||
| 	users, err := models.Users(page, setting.AdminUserPagingNum) |  | ||||||
| 	if err != nil { |  | ||||||
| 		ctx.Handle(500, "Users", err) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	ctx.Data["Users"] = users |  | ||||||
|  |  | ||||||
| 	ctx.Data["Total"] = total |  | ||||||
| 	ctx.HTML(200, USERS) |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func NewUser(ctx *context.Context) { | func NewUser(ctx *context.Context) { | ||||||
|   | |||||||
| @@ -27,7 +27,7 @@ func CreateOrg(ctx *context.Context, form api.CreateOrgOption) { | |||||||
| 		Website:     form.Website, | 		Website:     form.Website, | ||||||
| 		Location:    form.Location, | 		Location:    form.Location, | ||||||
| 		IsActive:    true, | 		IsActive:    true, | ||||||
| 		Type:        models.ORGANIZATION, | 		Type:        models.USER_TYPE_ORGANIZATION, | ||||||
| 	} | 	} | ||||||
| 	if err := models.CreateOrganization(org, u); err != nil { | 	if err := models.CreateOrganization(org, u); err != nil { | ||||||
| 		if models.IsErrUserAlreadyExist(err) || | 		if models.IsErrUserAlreadyExist(err) || | ||||||
|   | |||||||
| @@ -21,21 +21,21 @@ import ( | |||||||
|  |  | ||||||
| // https://github.com/gogits/go-gogs-client/wiki/Repositories#search-repositories | // https://github.com/gogits/go-gogs-client/wiki/Repositories#search-repositories | ||||||
| func Search(ctx *context.Context) { | func Search(ctx *context.Context) { | ||||||
| 	opt := models.SearchOption{ | 	opts := &models.SearchRepoOptions{ | ||||||
| 		Keyword: path.Base(ctx.Query("q")), | 		Keyword:  path.Base(ctx.Query("q")), | ||||||
| 		Uid:     com.StrTo(ctx.Query("uid")).MustInt64(), | 		OwnerID:  com.StrTo(ctx.Query("uid")).MustInt64(), | ||||||
| 		Limit:   com.StrTo(ctx.Query("limit")).MustInt(), | 		PageSize: com.StrTo(ctx.Query("limit")).MustInt(), | ||||||
| 	} | 	} | ||||||
| 	if opt.Limit == 0 { | 	if opts.PageSize == 0 { | ||||||
| 		opt.Limit = 10 | 		opts.PageSize = 10 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Check visibility. | 	// Check visibility. | ||||||
| 	if ctx.IsSigned && opt.Uid > 0 { | 	if ctx.IsSigned && opts.OwnerID > 0 { | ||||||
| 		if ctx.User.Id == opt.Uid { | 		if ctx.User.Id == opts.OwnerID { | ||||||
| 			opt.Private = true | 			opts.Private = true | ||||||
| 		} else { | 		} else { | ||||||
| 			u, err := models.GetUserByID(opt.Uid) | 			u, err := models.GetUserByID(opts.OwnerID) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				ctx.JSON(500, map[string]interface{}{ | 				ctx.JSON(500, map[string]interface{}{ | ||||||
| 					"ok":    false, | 					"ok":    false, | ||||||
| @@ -44,13 +44,13 @@ func Search(ctx *context.Context) { | |||||||
| 				return | 				return | ||||||
| 			} | 			} | ||||||
| 			if u.IsOrganization() && u.IsOwnedBy(ctx.User.Id) { | 			if u.IsOrganization() && u.IsOwnedBy(ctx.User.Id) { | ||||||
| 				opt.Private = true | 				opts.Private = true | ||||||
| 			} | 			} | ||||||
| 			// FIXME: how about collaborators? | 			// FIXME: how about collaborators? | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	repos, err := models.SearchRepositoryByName(opt) | 	repos, _, err := models.SearchRepositoryByName(opts) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.JSON(500, map[string]interface{}{ | 		ctx.JSON(500, map[string]interface{}{ | ||||||
| 			"ok":    false, | 			"ok":    false, | ||||||
|   | |||||||
| @@ -15,15 +15,16 @@ import ( | |||||||
|  |  | ||||||
| // https://github.com/gogits/go-gogs-client/wiki/Users#search-users | // https://github.com/gogits/go-gogs-client/wiki/Users#search-users | ||||||
| func Search(ctx *context.Context) { | func Search(ctx *context.Context) { | ||||||
| 	opt := models.SearchOption{ | 	opts := &models.SearchUserOptions{ | ||||||
| 		Keyword: ctx.Query("q"), | 		Keyword:  ctx.Query("q"), | ||||||
| 		Limit:   com.StrTo(ctx.Query("limit")).MustInt(), | 		Type:     models.USER_TYPE_INDIVIDUAL, | ||||||
|  | 		PageSize: com.StrTo(ctx.Query("limit")).MustInt(), | ||||||
| 	} | 	} | ||||||
| 	if opt.Limit == 0 { | 	if opts.PageSize == 0 { | ||||||
| 		opt.Limit = 10 | 		opts.PageSize = 10 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	us, err := models.SearchUserByName(opt) | 	users, _, err := models.SearchUserByName(opts) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.JSON(500, map[string]interface{}{ | 		ctx.JSON(500, map[string]interface{}{ | ||||||
| 			"ok":    false, | 			"ok":    false, | ||||||
| @@ -32,16 +33,16 @@ func Search(ctx *context.Context) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	results := make([]*api.User, len(us)) | 	results := make([]*api.User, len(users)) | ||||||
| 	for i := range us { | 	for i := range users { | ||||||
| 		results[i] = &api.User{ | 		results[i] = &api.User{ | ||||||
| 			ID:        us[i].Id, | 			ID:        users[i].Id, | ||||||
| 			UserName:  us[i].Name, | 			UserName:  users[i].Name, | ||||||
| 			AvatarUrl: us[i].AvatarLink(), | 			AvatarUrl: users[i].AvatarLink(), | ||||||
| 			FullName:  us[i].FullName, | 			FullName:  users[i].FullName, | ||||||
| 		} | 		} | ||||||
| 		if ctx.IsSigned { | 		if ctx.IsSigned { | ||||||
| 			results[i].Email = us[i].Email | 			results[i].Email = users[i].Email | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										105
									
								
								routers/home.go
									
									
									
									
									
								
							
							
						
						
									
										105
									
								
								routers/home.go
									
									
									
									
									
								
							| @@ -19,6 +19,7 @@ import ( | |||||||
| const ( | const ( | ||||||
| 	HOME          base.TplName = "home" | 	HOME          base.TplName = "home" | ||||||
| 	EXPLORE_REPOS base.TplName = "explore/repos" | 	EXPLORE_REPOS base.TplName = "explore/repos" | ||||||
|  | 	EXPLORE_USERS base.TplName = "explore/users" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func Home(ctx *context.Context) { | func Home(ctx *context.Context) { | ||||||
| @@ -43,23 +44,44 @@ func Home(ctx *context.Context) { | |||||||
| 	ctx.HTML(200, HOME) | 	ctx.HTML(200, HOME) | ||||||
| } | } | ||||||
|  |  | ||||||
| func Explore(ctx *context.Context) { | func RenderRepoSearch(ctx *context.Context, | ||||||
| 	ctx.Data["Title"] = ctx.Tr("explore") | 	counter func() int64, ranger func(int, int) ([]*models.Repository, error), | ||||||
| 	ctx.Data["PageIsExplore"] = true | 	pagingNum int, orderBy string, tplName base.TplName) { | ||||||
| 	ctx.Data["PageIsExploreRepositories"] = true |  | ||||||
|  |  | ||||||
| 	page := ctx.QueryInt("page") | 	page := ctx.QueryInt("page") | ||||||
| 	if page <= 1 { | 	if page <= 1 { | ||||||
| 		page = 1 | 		page = 1 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ctx.Data["Page"] = paginater.New(int(models.CountPublicRepositories()), setting.ExplorePagingNum, page, 5) | 	var ( | ||||||
|  | 		repos []*models.Repository | ||||||
|  | 		count int64 | ||||||
|  | 		err   error | ||||||
|  | 	) | ||||||
|  |  | ||||||
| 	repos, err := models.GetRecentUpdatedRepositories(page) | 	keyword := ctx.Query("q") | ||||||
| 	if err != nil { | 	if len(keyword) == 0 { | ||||||
| 		ctx.Handle(500, "GetRecentUpdatedRepositories", err) | 		repos, err = ranger(page, pagingNum) | ||||||
| 		return | 		if err != nil { | ||||||
|  | 			ctx.Handle(500, "ranger", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		count = counter() | ||||||
|  | 	} else { | ||||||
|  | 		repos, count, err = models.SearchRepositoryByName(&models.SearchRepoOptions{ | ||||||
|  | 			Keyword:  keyword, | ||||||
|  | 			OrderBy:  orderBy, | ||||||
|  | 			Page:     page, | ||||||
|  | 			PageSize: pagingNum, | ||||||
|  | 		}) | ||||||
|  | 		if err != nil { | ||||||
|  | 			ctx.Handle(500, "SearchRepositoryByName", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
|  | 	ctx.Data["Keyword"] = keyword | ||||||
|  | 	ctx.Data["Total"] = count | ||||||
|  | 	ctx.Data["Page"] = paginater.New(int(count), pagingNum, page, 5) | ||||||
|  |  | ||||||
| 	for _, repo := range repos { | 	for _, repo := range repos { | ||||||
| 		if err = repo.GetOwner(); err != nil { | 		if err = repo.GetOwner(); err != nil { | ||||||
| 			ctx.Handle(500, "GetOwner", fmt.Errorf("%d: %v", repo.ID, err)) | 			ctx.Handle(500, "GetOwner", fmt.Errorf("%d: %v", repo.ID, err)) | ||||||
| @@ -68,7 +90,68 @@ func Explore(ctx *context.Context) { | |||||||
| 	} | 	} | ||||||
| 	ctx.Data["Repos"] = repos | 	ctx.Data["Repos"] = repos | ||||||
|  |  | ||||||
| 	ctx.HTML(200, EXPLORE_REPOS) | 	ctx.HTML(200, tplName) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ExploreRepos(ctx *context.Context) { | ||||||
|  | 	ctx.Data["Title"] = ctx.Tr("explore") | ||||||
|  | 	ctx.Data["PageIsExplore"] = true | ||||||
|  | 	ctx.Data["PageIsExploreRepositories"] = true | ||||||
|  |  | ||||||
|  | 	RenderRepoSearch(ctx, models.CountPublicRepositories, models.GetRecentUpdatedRepositories, | ||||||
|  | 		setting.ExplorePagingNum, "updated_unix DESC", EXPLORE_REPOS) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func RenderUserSearch(ctx *context.Context, userType models.UserType, | ||||||
|  | 	counter func() int64, ranger func(int, int) ([]*models.User, error), | ||||||
|  | 	pagingNum int, orderBy string, tplName base.TplName) { | ||||||
|  | 	page := ctx.QueryInt("page") | ||||||
|  | 	if page <= 1 { | ||||||
|  | 		page = 1 | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var ( | ||||||
|  | 		users []*models.User | ||||||
|  | 		count int64 | ||||||
|  | 		err   error | ||||||
|  | 	) | ||||||
|  |  | ||||||
|  | 	keyword := ctx.Query("q") | ||||||
|  | 	if len(keyword) == 0 { | ||||||
|  | 		users, err = ranger(page, pagingNum) | ||||||
|  | 		if err != nil { | ||||||
|  | 			ctx.Handle(500, "ranger", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		count = counter() | ||||||
|  | 	} else { | ||||||
|  | 		users, count, err = models.SearchUserByName(&models.SearchUserOptions{ | ||||||
|  | 			Keyword:  keyword, | ||||||
|  | 			Type:     userType, | ||||||
|  | 			OrderBy:  orderBy, | ||||||
|  | 			Page:     page, | ||||||
|  | 			PageSize: pagingNum, | ||||||
|  | 		}) | ||||||
|  | 		if err != nil { | ||||||
|  | 			ctx.Handle(500, "SearchUserByName", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	ctx.Data["Keyword"] = keyword | ||||||
|  | 	ctx.Data["Total"] = count | ||||||
|  | 	ctx.Data["Page"] = paginater.New(int(count), pagingNum, page, 5) | ||||||
|  | 	ctx.Data["Users"] = users | ||||||
|  |  | ||||||
|  | 	ctx.HTML(200, tplName) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func ExploreUsers(ctx *context.Context) { | ||||||
|  | 	ctx.Data["Title"] = ctx.Tr("explore") | ||||||
|  | 	ctx.Data["PageIsExplore"] = true | ||||||
|  | 	ctx.Data["PageIsExploreUsers"] = true | ||||||
|  |  | ||||||
|  | 	RenderUserSearch(ctx, models.USER_TYPE_INDIVIDUAL, models.CountUsers, models.Users, | ||||||
|  | 		setting.ExplorePagingNum, "updated_unix DESC", EXPLORE_USERS) | ||||||
| } | } | ||||||
|  |  | ||||||
| func NotFound(ctx *context.Context) { | func NotFound(ctx *context.Context) { | ||||||
|   | |||||||
| @@ -33,7 +33,7 @@ func CreatePost(ctx *context.Context, form auth.CreateOrgForm) { | |||||||
| 	org := &models.User{ | 	org := &models.User{ | ||||||
| 		Name:     form.OrgName, | 		Name:     form.OrgName, | ||||||
| 		IsActive: true, | 		IsActive: true, | ||||||
| 		Type:     models.ORGANIZATION, | 		Type:     models.USER_TYPE_ORGANIZATION, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := models.CreateOrganization(org, ctx.User); err != nil { | 	if err := models.CreateOrganization(org, ctx.User); err != nil { | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| 0.9.5.0311 | 0.9.6.0311 | ||||||
							
								
								
									
										23
									
								
								templates/admin/base/page.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								templates/admin/base/page.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | |||||||
|  | 	{{with .Page}} | ||||||
|  | 		{{if gt .TotalPages 1}} | ||||||
|  | 			<div class="center page buttons"> | ||||||
|  | 				<div class="ui borderless pagination menu"> | ||||||
|  | 					<a class="{{if .IsFirst}}disabled{{end}} item" href="{{$.Link}}?q={{$.Keyword}}"><i class="angle double left icon"></i> {{$.i18n.Tr "admin.first_page"}}</a> | ||||||
|  | 					<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}&q={{$.Keyword}}"{{end}}> | ||||||
|  | 						<i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} | ||||||
|  | 					</a> | ||||||
|  | 					{{range .Pages}} | ||||||
|  | 						{{if eq .Num -1}} | ||||||
|  | 							<a class="disabled item">...</a> | ||||||
|  | 						{{else}} | ||||||
|  | 							<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}&q={{$.Keyword}}"{{end}}>{{.Num}}</a> | ||||||
|  | 						{{end}} | ||||||
|  | 					{{end}} | ||||||
|  | 					<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}&q={{$.Keyword}}"{{end}}> | ||||||
|  | 						{{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i> | ||||||
|  | 					</a> | ||||||
|  | 					<a class="{{if .IsLast}}disabled{{end}} item" href="{{$.Link}}?page={{.TotalPages}}&q={{$.Keyword}}">{{$.i18n.Tr "admin.last_page"}} <i class="angle double right icon"></i></a> | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		{{end}} | ||||||
|  | 	{{end}} | ||||||
							
								
								
									
										6
									
								
								templates/admin/base/search.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								templates/admin/base/search.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | |||||||
|  | <form class="ui form"> | ||||||
|  | 	<div class="ui fluid action input"> | ||||||
|  | 	  <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus> | ||||||
|  | 	  <button class="ui blue button">{{.i18n.Tr "explore.search"}}</button> | ||||||
|  | 	</div> | ||||||
|  | </form> | ||||||
| @@ -8,6 +8,9 @@ | |||||||
| 				<h4 class="ui top attached header"> | 				<h4 class="ui top attached header"> | ||||||
| 					{{.i18n.Tr "admin.orgs.org_manage_panel"}} ({{.i18n.Tr "admin.total" .Total}}) | 					{{.i18n.Tr "admin.orgs.org_manage_panel"}} ({{.i18n.Tr "admin.total" .Total}}) | ||||||
| 				</h4> | 				</h4> | ||||||
|  | 				<div class="ui attached segment"> | ||||||
|  | 					{{template "admin/base/search" .}} | ||||||
|  | 				</div> | ||||||
| 				<div class="ui attached table segment"> | 				<div class="ui attached table segment"> | ||||||
| 					<table class="ui very basic striped table"> | 					<table class="ui very basic striped table"> | ||||||
| 						<thead> | 						<thead> | ||||||
| @@ -22,7 +25,7 @@ | |||||||
| 							</tr> | 							</tr> | ||||||
| 						</thead> | 						</thead> | ||||||
| 						<tbody> | 						<tbody> | ||||||
| 							{{range .Orgs}} | 							{{range .Users}} | ||||||
| 								<tr> | 								<tr> | ||||||
| 									<td>{{.Id}}</td> | 									<td>{{.Id}}</td> | ||||||
| 									<td><a href="{{.HomeLink}}">{{.Name}}</a></td> | 									<td><a href="{{.HomeLink}}">{{.Name}}</a></td> | ||||||
| @@ -37,29 +40,7 @@ | |||||||
| 					</table> | 					</table> | ||||||
| 				</div> | 				</div> | ||||||
|  |  | ||||||
| 				{{with .Page}} | 				{{template "admin/base/page" .}} | ||||||
| 					{{if gt .TotalPages 1}} |  | ||||||
| 						<div class="center page buttons"> |  | ||||||
| 							<div class="ui borderless pagination menu"> |  | ||||||
| 								<a class="{{if .IsFirst}}disabled{{end}} item" href="{{$.Link}}"><i class="angle double left icon"></i> {{$.i18n.Tr "admin.first_page"}}</a> |  | ||||||
| 								<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}"{{end}}> |  | ||||||
| 									<i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} |  | ||||||
| 								</a> |  | ||||||
| 								{{range .Pages}} |  | ||||||
| 									{{if eq .Num -1}} |  | ||||||
| 										<a class="disabled item">...</a> |  | ||||||
| 									{{else}} |  | ||||||
| 										<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}"{{end}}>{{.Num}}</a> |  | ||||||
| 									{{end}} |  | ||||||
| 								{{end}} |  | ||||||
| 								<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}"{{end}}> |  | ||||||
| 									{{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i> |  | ||||||
| 								</a> |  | ||||||
| 								<a class="{{if .IsLast}}disabled{{end}} item" href="{{$.Link}}?page={{.TotalPages}}">{{$.i18n.Tr "admin.last_page"}} <i class="angle double right icon"></i></a> |  | ||||||
| 							</div> |  | ||||||
| 						</div> |  | ||||||
| 					{{end}} |  | ||||||
| 				{{end}} |  | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
|   | |||||||
| @@ -8,6 +8,9 @@ | |||||||
| 				<h4 class="ui top attached header"> | 				<h4 class="ui top attached header"> | ||||||
| 					{{.i18n.Tr "admin.repos.repo_manage_panel"}} ({{.i18n.Tr "admin.total" .Total}}) | 					{{.i18n.Tr "admin.repos.repo_manage_panel"}} ({{.i18n.Tr "admin.total" .Total}}) | ||||||
| 				</h4> | 				</h4> | ||||||
|  | 				<div class="ui attached segment"> | ||||||
|  | 					{{template "admin/base/search" .}} | ||||||
|  | 				</div> | ||||||
| 				<div class="ui attached table segment"> | 				<div class="ui attached table segment"> | ||||||
| 					<table class="ui very basic striped table"> | 					<table class="ui very basic striped table"> | ||||||
| 						<thead> | 						<thead> | ||||||
| @@ -41,29 +44,7 @@ | |||||||
| 					</table> | 					</table> | ||||||
| 				</div> | 				</div> | ||||||
|  |  | ||||||
| 				{{with .Page}} | 				{{template "admin/base/page" .}} | ||||||
| 					{{if gt .TotalPages 1}} |  | ||||||
| 						<div class="center page buttons"> |  | ||||||
| 							<div class="ui borderless pagination menu"> |  | ||||||
| 								<a class="{{if .IsFirst}}disabled{{end}} item" href="{{$.Link}}"><i class="angle double left icon"></i> {{$.i18n.Tr "admin.first_page"}}</a> |  | ||||||
| 								<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}"{{end}}> |  | ||||||
| 									<i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} |  | ||||||
| 								</a> |  | ||||||
| 								{{range .Pages}} |  | ||||||
| 									{{if eq .Num -1}} |  | ||||||
| 										<a class="disabled item">...</a> |  | ||||||
| 									{{else}} |  | ||||||
| 										<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}"{{end}}>{{.Num}}</a> |  | ||||||
| 									{{end}} |  | ||||||
| 								{{end}} |  | ||||||
| 								<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}"{{end}}> |  | ||||||
| 									{{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i> |  | ||||||
| 								</a> |  | ||||||
| 								<a class="{{if .IsLast}}disabled{{end}} item" href="{{$.Link}}?page={{.TotalPages}}">{{$.i18n.Tr "admin.last_page"}} <i class="angle double right icon"></i></a> |  | ||||||
| 							</div> |  | ||||||
| 						</div> |  | ||||||
| 					{{end}} |  | ||||||
| 				{{end}} |  | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
|   | |||||||
| @@ -8,9 +8,12 @@ | |||||||
| 				<h4 class="ui top attached header"> | 				<h4 class="ui top attached header"> | ||||||
| 					{{.i18n.Tr "admin.users.user_manage_panel"}} ({{.i18n.Tr "admin.total" .Total}}) | 					{{.i18n.Tr "admin.users.user_manage_panel"}} ({{.i18n.Tr "admin.total" .Total}}) | ||||||
| 					<div class="ui right"> | 					<div class="ui right"> | ||||||
| 						<a class="ui blue tiny button" href="{{AppSubUrl}}/admin/users/new">{{.i18n.Tr "admin.users.new_account"}}</a> | 						<a class="ui black tiny button" href="{{AppSubUrl}}/admin/users/new">{{.i18n.Tr "admin.users.new_account"}}</a> | ||||||
| 					</div> | 					</div> | ||||||
| 				</h4> | 				</h4> | ||||||
|  | 				<div class="ui attached segment"> | ||||||
|  | 					{{template "admin/base/search" .}} | ||||||
|  | 				</div> | ||||||
| 				<div class="ui attached table segment"> | 				<div class="ui attached table segment"> | ||||||
| 					<table class="ui very basic striped table"> | 					<table class="ui very basic striped table"> | ||||||
| 						<thead> | 						<thead> | ||||||
| @@ -42,29 +45,7 @@ | |||||||
| 					</table> | 					</table> | ||||||
| 				</div> | 				</div> | ||||||
|  |  | ||||||
| 				{{with .Page}} | 				{{template "admin/base/page" .}} | ||||||
| 					{{if gt .TotalPages 1}} |  | ||||||
| 						<div class="center page buttons"> |  | ||||||
| 							<div class="ui borderless pagination menu"> |  | ||||||
| 								<a class="{{if .IsFirst}}disabled{{end}} item" href="{{$.Link}}"><i class="angle double left icon"></i> {{$.i18n.Tr "admin.first_page"}}</a> |  | ||||||
| 								<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}"{{end}}> |  | ||||||
| 									<i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} |  | ||||||
| 								</a> |  | ||||||
| 								{{range .Pages}} |  | ||||||
| 									{{if eq .Num -1}} |  | ||||||
| 										<a class="disabled item">...</a> |  | ||||||
| 									{{else}} |  | ||||||
| 										<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}"{{end}}>{{.Num}}</a> |  | ||||||
| 									{{end}} |  | ||||||
| 								{{end}} |  | ||||||
| 								<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}"{{end}}> |  | ||||||
| 									{{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i> |  | ||||||
| 								</a> |  | ||||||
| 								<a class="{{if .IsLast}}disabled{{end}} item" href="{{$.Link}}?page={{.TotalPages}}">{{$.i18n.Tr "admin.last_page"}} <i class="angle double right icon"></i></a> |  | ||||||
| 							</div> |  | ||||||
| 						</div> |  | ||||||
| 					{{end}} |  | ||||||
| 				{{end}} |  | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
|   | |||||||
| @@ -59,7 +59,7 @@ | |||||||
| 									<a class="item{{if .PageIsHome}} active{{end}}" href="{{AppSubUrl}}/">{{.i18n.Tr "home"}}</a> | 									<a class="item{{if .PageIsHome}} active{{end}}" href="{{AppSubUrl}}/">{{.i18n.Tr "home"}}</a> | ||||||
| 								{{end}} | 								{{end}} | ||||||
|  |  | ||||||
| 								<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore">{{.i18n.Tr "explore"}}</a> | 								<a class="item{{if .PageIsExplore}} active{{end}}" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "explore"}}</a> | ||||||
| 								{{/*<div class="item"> | 								{{/*<div class="item"> | ||||||
| 									<div class="ui icon input"> | 									<div class="ui icon input"> | ||||||
| 									<input class="searchbox" type="text" placeholder="{{.i18n.Tr "search_project"}}"> | 									<input class="searchbox" type="text" placeholder="{{.i18n.Tr "search_project"}}"> | ||||||
|   | |||||||
| @@ -1,8 +1,11 @@ | |||||||
| <div class="four wide column"> | <div class="four wide column"> | ||||||
| 	<div class="ui vertical menu"> | 	<div class="ui vertical menu navbar"> | ||||||
| 		<div class="header item">{{.i18n.Tr "explore"}}</div> | 		<div class="header item">{{.i18n.Tr "explore"}}</div> | ||||||
| 		<a class="{{if .PageIsExploreRepositories}}active{{end}} item" href="{{AppSubUrl}}/explore"> | 		<a class="{{if .PageIsExploreRepositories}}active{{end}} item" href="{{AppSubUrl}}/explore/repos"> | ||||||
| 			{{.i18n.Tr "explore.repos"}} | 			<span class="octicon octicon-repo"></span> {{.i18n.Tr "explore.repos"}} | ||||||
|  | 		</a> | ||||||
|  | 		<a class="{{if .PageIsExploreUsers}}active{{end}} item" href="{{AppSubUrl}}/explore/users"> | ||||||
|  | 			<span class="octicon octicon-person"></span> {{.i18n.Tr "explore.users"}} | ||||||
| 		</a> | 		</a> | ||||||
| 	</div> | 	</div> | ||||||
| </div> | </div> | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								templates/explore/page.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								templates/explore/page.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | {{with .Page}} | ||||||
|  | 	{{if gt .TotalPages 1}} | ||||||
|  | 		<div class="center page buttons"> | ||||||
|  | 			<div class="ui borderless pagination menu"> | ||||||
|  | 				<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}&q={{$.Keyword}}"{{end}}> | ||||||
|  | 					<i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} | ||||||
|  | 				</a> | ||||||
|  | 				{{range .Pages}} | ||||||
|  | 					{{if eq .Num -1}} | ||||||
|  | 						<a class="disabled item">...</a> | ||||||
|  | 					{{else}} | ||||||
|  | 						<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}&q={{$.Keyword}}"{{end}}>{{.Num}}</a> | ||||||
|  | 					{{end}} | ||||||
|  | 				{{end}} | ||||||
|  | 				<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}&q={{$.Keyword}}"{{end}}> | ||||||
|  | 					{{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i> | ||||||
|  | 				</a> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	{{end}} | ||||||
|  | {{end}} | ||||||
| @@ -4,29 +4,9 @@ | |||||||
| 		<div class="ui grid"> | 		<div class="ui grid"> | ||||||
| 			{{template "explore/navbar" .}} | 			{{template "explore/navbar" .}} | ||||||
| 			<div class="twelve wide column content"> | 			<div class="twelve wide column content"> | ||||||
|  | 				{{template "explore/search" .}} | ||||||
| 				{{template "explore/repo_list" .}} | 				{{template "explore/repo_list" .}} | ||||||
|  | 				{{template "explore/page" .}} | ||||||
| 				{{with .Page}} |  | ||||||
| 					{{if gt .TotalPages 1}} |  | ||||||
| 						<div class="center page buttons"> |  | ||||||
| 							<div class="ui borderless pagination menu"> |  | ||||||
| 								<a class="{{if not .HasPrevious}}disabled{{end}} item" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}"{{end}}> |  | ||||||
| 									<i class="left arrow icon"></i> {{$.i18n.Tr "repo.issues.previous"}} |  | ||||||
| 								</a> |  | ||||||
| 								{{range .Pages}} |  | ||||||
| 									{{if eq .Num -1}} |  | ||||||
| 										<a class="disabled item">...</a> |  | ||||||
| 									{{else}} |  | ||||||
| 										<a class="{{if .IsCurrent}}active{{end}} item" {{if not .IsCurrent}}href="{{$.Link}}?page={{.Num}}"{{end}}>{{.Num}}</a> |  | ||||||
| 									{{end}} |  | ||||||
| 								{{end}} |  | ||||||
| 								<a class="{{if not .HasNext}}disabled{{end}} item" {{if .HasNext}}href="{{$.Link}}?page={{.Next}}"{{end}}> |  | ||||||
| 									{{$.i18n.Tr "repo.issues.next"}} <i class="icon right arrow"></i> |  | ||||||
| 								</a> |  | ||||||
| 							</div> |  | ||||||
| 						</div> |  | ||||||
| 					{{end}} |  | ||||||
| 				{{end}} |  | ||||||
| 			</div> | 			</div> | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
|   | |||||||
							
								
								
									
										7
									
								
								templates/explore/search.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								templates/explore/search.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | |||||||
|  | <form class="ui form"> | ||||||
|  | 	<div class="ui fluid action input"> | ||||||
|  | 	  <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus> | ||||||
|  | 	  <button class="ui blue button">{{.i18n.Tr "explore.search"}}</button> | ||||||
|  | 	</div> | ||||||
|  | </form> | ||||||
|  | <div class="ui divider"></div> | ||||||
							
								
								
									
										35
									
								
								templates/explore/users.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								templates/explore/users.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | {{template "base/head" .}} | ||||||
|  | <div class="explore users"> | ||||||
|  | 	<div class="ui container"> | ||||||
|  | 		<div class="ui grid"> | ||||||
|  | 			{{template "explore/navbar" .}} | ||||||
|  | 			<div class="twelve wide column content"> | ||||||
|  | 				{{template "explore/search" .}} | ||||||
|  |  | ||||||
|  | 				<div class="ui user list"> | ||||||
|  | 					{{range .Users}} | ||||||
|  | 						<div class="item"> | ||||||
|  | 						  <img class="ui avatar image" src="{{.AvatarLink}}"> | ||||||
|  | 						  <div class="content"> | ||||||
|  | 						  	<span class="header"><a href="{{.HomeLink}}">{{.Name}}</a> {{.FullName}}</span> | ||||||
|  | 						    <div class="description"> | ||||||
|  | 									{{if .Location}} | ||||||
|  | 										<i class="octicon octicon-location"></i> {{.Location}} | ||||||
|  | 									{{end}} | ||||||
|  | 									{{if and .Email $.IsSigned}} | ||||||
|  | 										<i class="octicon octicon-mail"></i> | ||||||
|  | 										<a href="mailto:{{.Email}}" rel="nofollow">{{.Email}}</a> | ||||||
|  | 									{{end}} | ||||||
|  | 									<i class="octicon octicon-clock"></i> {{$.i18n.Tr "user.join_on"}} {{DateFmtShort .Created}} | ||||||
|  | 						    </div> | ||||||
|  | 						  </div> | ||||||
|  | 						</div> | ||||||
|  | 					{{end}} | ||||||
|  | 				</div> | ||||||
|  |  | ||||||
|  | 				{{template "explore/page" .}} | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | </div> | ||||||
|  | {{template "base/footer" .}} | ||||||
		Reference in New Issue
	
	Block a user
	 Unknwon
					Unknwon