add tree view
This commit is contained in:
		
						commit
						b27e8e87f8
					
				
					 34 changed files with 716 additions and 166 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							|  | @ -5,3 +5,4 @@ gogs | |||
| *.db | ||||
| *.log | ||||
| custom/ | ||||
| .vendor/ | ||||
|  |  | |||
|  | @ -3,6 +3,8 @@ Gogs - Go Git Service [ is a GitHub-like clone in the Go Programming Language, it currently supports Linux and Max OS X, but Windows has **NOT** supported yet due to installation problem with [libgit2](http://libgit2.github.com/) in Windows. | ||||
| 
 | ||||
| ##### Current version: 0.0.7 Alpha | ||||
| 
 | ||||
| ## Purpose | ||||
| 
 | ||||
| There are some very good products in this category such as [gitlab](http://gitlab.com), but the environment setup steps often make us crazy. So our goal of Gogs is to build a GitHub-like clone with very easy setup steps, which take advantages of the Go Programming Language. | ||||
|  | @ -15,7 +17,8 @@ Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design, devel | |||
| 
 | ||||
| - SSH protocal support. | ||||
| - Register/delete account. | ||||
| - Create public repository. | ||||
| - Create/delete public repository. | ||||
| - User/repository home page. | ||||
| - Git repository manipulation. | ||||
| 
 | ||||
| ## Installation | ||||
|  |  | |||
|  | @ -3,8 +3,8 @@ RUN_USER = lunny | |||
| 
 | ||||
| [repository] | ||||
| ROOT = /Users/lunny/git/gogs-repositories | ||||
| LANG_IGNS=Google Go | ||||
| LICENSES=Apache v2 License | ||||
| LANG_IGNS=Google Go|C | ||||
| LICENSES=Apache v2 License|BSD (3-Clause) License | ||||
| 
 | ||||
| [server] | ||||
| HTTP_ADDR =  | ||||
|  |  | |||
							
								
								
									
										18
									
								
								conf/gitignore/C
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								conf/gitignore/C
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,18 @@ | |||
| # Object files | ||||
| *.o | ||||
| *.ko | ||||
| 
 | ||||
| # Libraries | ||||
| *.lib | ||||
| *.a | ||||
| 
 | ||||
| # Shared objects (inc. Windows DLLs) | ||||
| *.dll | ||||
| *.so | ||||
| *.so.* | ||||
| *.dylib | ||||
| 
 | ||||
| # Executables | ||||
| *.exe | ||||
| *.out | ||||
| *.app | ||||
							
								
								
									
										27
									
								
								conf/license/BSD (3-Clause) License
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								conf/license/BSD (3-Clause) License
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,27 @@ | |||
| Copyright (c) 2014 | ||||
| All rights reserved. | ||||
| 
 | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are met: | ||||
| 
 | ||||
| * Redistributions of source code must retain the above copyright notice, this | ||||
|   list of conditions and the following disclaimer. | ||||
| 
 | ||||
| * Redistributions in binary form must reproduce the above copyright notice, | ||||
|   this list of conditions and the following disclaimer in the documentation | ||||
|   and/or other materials provided with the distribution. | ||||
| 
 | ||||
| * Neither the name of the {organization} nor the names of its | ||||
|   contributors may be used to endorse or promote products derived from | ||||
|   this software without specific prior written permission. | ||||
| 
 | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
| AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
| IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||
| FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
| DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||
| CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||
| OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
							
								
								
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								gogs.go
									
									
									
									
									
								
							|  | @ -20,7 +20,7 @@ import ( | |||
| // Test that go1.1 tag above is included in builds. main.go refers to this definition.
 | ||||
| const go11tag = true | ||||
| 
 | ||||
| const APP_VER = "0.0.6.0313" | ||||
| const APP_VER = "0.0.7.0314" | ||||
| 
 | ||||
| func init() { | ||||
| 	runtime.GOMAXPROCS(runtime.NumCPU()) | ||||
|  |  | |||
|  | @ -9,6 +9,7 @@ import ( | |||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"os" | ||||
| 	"path" | ||||
| 	"path/filepath" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | @ -270,6 +271,7 @@ type RepoFile struct { | |||
| 	Id      *git.Oid | ||||
| 	Type    int | ||||
| 	Name    string | ||||
| 	Path    string | ||||
| 	Message string | ||||
| 	Created time.Time | ||||
| } | ||||
|  | @ -282,7 +284,7 @@ func (f *RepoFile) IsDir() bool { | |||
| 	return f.Type == git.FilemodeTree | ||||
| } | ||||
| 
 | ||||
| func GetReposFiles(userName, reposName, treeName, rpath string) ([]*RepoFile, error) { | ||||
| func GetReposFiles(userName, reposName, branchName, rpath string) ([]*RepoFile, error) { | ||||
| 	f := RepoPath(userName, reposName) | ||||
| 	repo, err := git.OpenRepository(f) | ||||
| 	if err != nil { | ||||
|  | @ -299,8 +301,28 @@ func GetReposFiles(userName, reposName, treeName, rpath string) ([]*RepoFile, er | |||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	var i uint64 = 0 | ||||
| 	for ; i < tree.EntryCount(); i++ { | ||||
| 	//var i uint64 = 0
 | ||||
| 	if rpath != "" { | ||||
| 		rpath = rpath + "/" | ||||
| 	} | ||||
| 	fmt.Println("...", rpath, "...") | ||||
| 
 | ||||
| 	tree.Walk(func(dirname string, entry *git.TreeEntry) int { | ||||
| 		if dirname == rpath { | ||||
| 			fmt.Println("====", dirname, "==", entry.Name) | ||||
| 			repofiles = append(repofiles, &RepoFile{ | ||||
| 				entry.Id, | ||||
| 				entry.Filemode, | ||||
| 				entry.Name, | ||||
| 				path.Join(dirname, entry.Name), | ||||
| 				lastCommit.Message(), | ||||
| 				lastCommit.Committer().When, | ||||
| 			}) | ||||
| 		} | ||||
| 		return 0 | ||||
| 	}) | ||||
| 
 | ||||
| 	/*for ; i < tree.EntryCount(); i++ { | ||||
| 		entry := tree.EntryByIndex(i) | ||||
| 
 | ||||
| 		repofiles = append(repofiles, &RepoFile{ | ||||
|  | @ -310,7 +332,7 @@ func GetReposFiles(userName, reposName, treeName, rpath string) ([]*RepoFile, er | |||
| 			lastCommit.Message(), | ||||
| 			lastCommit.Committer().When, | ||||
| 		}) | ||||
| 	} | ||||
| 	}*/ | ||||
| 
 | ||||
| 	return repofiles, nil | ||||
| } | ||||
|  | @ -354,6 +376,10 @@ func DeleteRepository(userId, repoId int64, userName string) (err error) { | |||
| 		session.Rollback() | ||||
| 		return err | ||||
| 	} | ||||
| 	if _, err := session.Delete(&Access{UserName: userName, RepoName: repo.Name}); err != nil { | ||||
| 		session.Rollback() | ||||
| 		return err | ||||
| 	} | ||||
| 	if _, err = session.Exec("update user set num_repos = num_repos - 1 where id = ?", userId); err != nil { | ||||
| 		session.Rollback() | ||||
| 		return err | ||||
|  |  | |||
|  | @ -48,7 +48,10 @@ type User struct { | |||
| 	NumFollowings int | ||||
| 	NumStars      int | ||||
| 	NumRepos      int | ||||
| 	Avatar        string    `xorm:"varchar(2048) not null"` | ||||
| 	Avatar        string `xorm:"varchar(2048) not null"` | ||||
| 	AvatarEmail   string `xorm:"not null"` | ||||
| 	Location      string | ||||
| 	Website       string | ||||
| 	Created       time.Time `xorm:"created"` | ||||
| 	Updated       time.Time `xorm:"updated"` | ||||
| } | ||||
|  | @ -104,6 +107,7 @@ func RegisterUser(user *User) (err error) { | |||
| 
 | ||||
| 	user.LowerName = strings.ToLower(user.Name) | ||||
| 	user.Avatar = base.EncodeMd5(user.Email) | ||||
| 	user.AvatarEmail = user.Email | ||||
| 	if err = user.EncodePasswd(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  |  | |||
|  | @ -23,7 +23,7 @@ type Form interface { | |||
| } | ||||
| 
 | ||||
| type RegisterForm struct { | ||||
| 	UserName     string `form:"username" binding:"Required;AlphaDash;MinSize(5);MaxSize(30)"` | ||||
| 	UserName     string `form:"username" binding:"Required;AlphaDash;MaxSize(30)"` | ||||
| 	Email        string `form:"email" binding:"Required;Email;MaxSize(50)"` | ||||
| 	Password     string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"` | ||||
| 	RetypePasswd string `form:"retypepasswd"` | ||||
|  | @ -59,7 +59,7 @@ func (f *RegisterForm) Validate(errors *binding.Errors, req *http.Request, conte | |||
| } | ||||
| 
 | ||||
| type LogInForm struct { | ||||
| 	UserName string `form:"username" binding:"Required;AlphaDash;MinSize(5);MaxSize(30)"` | ||||
| 	UserName string `form:"username" binding:"Required;AlphaDash;MaxSize(30)"` | ||||
| 	Password string `form:"passwd" binding:"Required;MinSize(6);MaxSize(30)"` | ||||
| } | ||||
| 
 | ||||
|  | @ -90,11 +90,6 @@ func (f *LogInForm) Validate(errors *binding.Errors, req *http.Request, context | |||
| 	validate(errors, data, f) | ||||
| } | ||||
| 
 | ||||
| type FeedsForm struct { | ||||
| 	UserId int64 `form:"userid" binding:"Required"` | ||||
| 	Offset int64 `form:"offset"` | ||||
| } | ||||
| 
 | ||||
| func getMinMaxSize(field reflect.StructField) string { | ||||
| 	for _, rule := range strings.Split(field.Tag.Get("binding"), ";") { | ||||
| 		if strings.HasPrefix(rule, "MinSize(") || strings.HasPrefix(rule, "MaxSize(") { | ||||
|  |  | |||
|  | @ -5,10 +5,15 @@ | |||
| package auth | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 	"reflect" | ||||
| 
 | ||||
| 	"github.com/codegangsta/martini" | ||||
| 	"github.com/martini-contrib/render" | ||||
| 	"github.com/martini-contrib/sessions" | ||||
| 
 | ||||
| 	"github.com/gogits/binding" | ||||
| 
 | ||||
| 	"github.com/gogits/gogs/models" | ||||
| 	"github.com/gogits/gogs/modules/base" | ||||
| 	"github.com/gogits/gogs/modules/log" | ||||
|  | @ -83,3 +88,76 @@ func SignOutRequire() martini.Handler { | |||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| type FeedsForm struct { | ||||
| 	UserId int64 `form:"userid" binding:"Required"` | ||||
| 	Offset int64 `form:"offset"` | ||||
| } | ||||
| 
 | ||||
| type UpdateProfileForm struct { | ||||
| 	Email    string `form:"email" binding:"Required;Email;MaxSize(50)"` | ||||
| 	Website  string `form:"website" binding:"MaxSize(50)"` | ||||
| 	Location string `form:"location" binding:"MaxSize(50)"` | ||||
| 	Avatar   string `form:"avatar" binding:"Required;Email;MaxSize(50)"` | ||||
| } | ||||
| 
 | ||||
| func (f *UpdateProfileForm) Name(field string) string { | ||||
| 	names := map[string]string{ | ||||
| 		"Email":    "Email address", | ||||
| 		"Website":  "Website", | ||||
| 		"Location": "Location", | ||||
| 		"Avatar":   "Gravatar Email", | ||||
| 	} | ||||
| 	return names[field] | ||||
| } | ||||
| 
 | ||||
| func (f *UpdateProfileForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) { | ||||
| 	if req.Method == "GET" || errors.Count() == 0 { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | ||||
| 	data["HasError"] = true | ||||
| 
 | ||||
| 	if len(errors.Overall) > 0 { | ||||
| 		for _, err := range errors.Overall { | ||||
| 			log.Error("UpdateProfileForm.Validate: %v", err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	validate(errors, data, f) | ||||
| } | ||||
| 
 | ||||
| type UpdatePasswdForm struct { | ||||
| 	OldPasswd    string `form:"oldpasswd" binding:"Required;MinSize(6);MaxSize(30)"` | ||||
| 	NewPasswd    string `form:"newpasswd" binding:"Required;MinSize(6);MaxSize(30)"` | ||||
| 	RetypePasswd string `form:"retypepasswd"` | ||||
| } | ||||
| 
 | ||||
| func (f *UpdatePasswdForm) Name(field string) string { | ||||
| 	names := map[string]string{ | ||||
| 		"OldPasswd":    "Old password", | ||||
| 		"NewPasswd":    "New password", | ||||
| 		"RetypePasswd": "Re-type password", | ||||
| 	} | ||||
| 	return names[field] | ||||
| } | ||||
| 
 | ||||
| func (f *UpdatePasswdForm) Validate(errors *binding.Errors, req *http.Request, context martini.Context) { | ||||
| 	if req.Method == "GET" || errors.Count() == 0 { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	data := context.Get(reflect.TypeOf(base.TmplData{})).Interface().(base.TmplData) | ||||
| 	data["HasError"] = true | ||||
| 
 | ||||
| 	if len(errors.Overall) > 0 { | ||||
| 		for _, err := range errors.Overall { | ||||
| 			log.Error("UpdatePasswdForm.Validate: %v", err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	validate(errors, data, f) | ||||
| } | ||||
|  |  | |||
|  | @ -7,6 +7,8 @@ package base | |||
| import ( | ||||
| 	"crypto/md5" | ||||
| 	"encoding/hex" | ||||
| 	"fmt" | ||||
| 	"time" | ||||
| ) | ||||
| 
 | ||||
| // Encode string to md5 hex value
 | ||||
|  | @ -15,3 +17,64 @@ func EncodeMd5(str string) string { | |||
| 	m.Write([]byte(str)) | ||||
| 	return hex.EncodeToString(m.Sum(nil)) | ||||
| } | ||||
| 
 | ||||
| // Seconds-based time units
 | ||||
| const ( | ||||
| 	Minute = 60 | ||||
| 	Hour   = 60 * Minute | ||||
| 	Day    = 24 * Hour | ||||
| 	Week   = 7 * Day | ||||
| 	Month  = 30 * Day | ||||
| 	Year   = 12 * Month | ||||
| ) | ||||
| 
 | ||||
| // TimeSince calculates the time interval and generate user-friendly string.
 | ||||
| func TimeSince(then time.Time) string { | ||||
| 	now := time.Now() | ||||
| 
 | ||||
| 	lbl := "ago" | ||||
| 	diff := now.Unix() - then.Unix() | ||||
| 	if then.After(now) { | ||||
| 		lbl = "from now" | ||||
| 		diff = then.Unix() - now.Unix() | ||||
| 	} | ||||
| 
 | ||||
| 	switch { | ||||
| 
 | ||||
| 	case diff <= 0: | ||||
| 		return "now" | ||||
| 	case diff <= 2: | ||||
| 		return fmt.Sprintf("1 second %s", lbl) | ||||
| 	case diff < 1*Minute: | ||||
| 		return fmt.Sprintf("%d seconds %s", diff, lbl) | ||||
| 
 | ||||
| 	case diff < 2*Minute: | ||||
| 		return fmt.Sprintf("1 minute %s", lbl) | ||||
| 	case diff < 1*Hour: | ||||
| 		return fmt.Sprintf("%d minutes %s", diff/Minute, lbl) | ||||
| 
 | ||||
| 	case diff < 2*Hour: | ||||
| 		return fmt.Sprintf("1 hour %s", lbl) | ||||
| 	case diff < 1*Day: | ||||
| 		return fmt.Sprintf("%d hours %s", diff/Hour, lbl) | ||||
| 
 | ||||
| 	case diff < 2*Day: | ||||
| 		return fmt.Sprintf("1 day %s", lbl) | ||||
| 	case diff < 1*Week: | ||||
| 		return fmt.Sprintf("%d days %s", diff/Day, lbl) | ||||
| 
 | ||||
| 	case diff < 2*Week: | ||||
| 		return fmt.Sprintf("1 week %s", lbl) | ||||
| 	case diff < 1*Month: | ||||
| 		return fmt.Sprintf("%d weeks %s", diff/Week, lbl) | ||||
| 
 | ||||
| 	case diff < 2*Month: | ||||
| 		return fmt.Sprintf("1 month %s", lbl) | ||||
| 	case diff < 1*Year: | ||||
| 		return fmt.Sprintf("%d months %s", diff/Month, lbl) | ||||
| 
 | ||||
| 	case diff < 18*Month: | ||||
| 		return fmt.Sprintf("1 year %s", lbl) | ||||
| 	} | ||||
| 	return then.String() | ||||
| } | ||||
|  |  | |||
|  | @ -6,7 +6,13 @@ | |||
| package log | ||||
| 
 | ||||
| import ( | ||||
| 	"fmt" | ||||
| 
 | ||||
| 	"github.com/martini-contrib/render" | ||||
| 
 | ||||
| 	"github.com/gogits/logs" | ||||
| 
 | ||||
| 	"github.com/gogits/gogs/modules/base" | ||||
| ) | ||||
| 
 | ||||
| var logger *logs.BeeLogger | ||||
|  | @ -35,3 +41,9 @@ func Warn(format string, v ...interface{}) { | |||
| func Critical(format string, v ...interface{}) { | ||||
| 	logger.Critical(format, v...) | ||||
| } | ||||
| 
 | ||||
| func Handle(status int, title string, data base.TmplData, r render.Render, err error) { | ||||
| 	data["ErrorMsg"] = err | ||||
| 	Error("%s: %v", title, err) | ||||
| 	r.HTML(status, fmt.Sprintf("status/%d", status), data) | ||||
| } | ||||
|  |  | |||
|  | @ -137,6 +137,11 @@ body { | |||
|     margin-top: 50px; | ||||
| } | ||||
| 
 | ||||
| #gogs-body .btn-default { | ||||
|     background-color: #FFF; | ||||
|     background-image: linear-gradient(to bottom, #FFF 0, #FAFAFA 100%); | ||||
| } | ||||
| 
 | ||||
| #gogs-body-nav { | ||||
|     margin-top: 52px; | ||||
|     margin-bottom: -50px; | ||||
|  | @ -269,7 +274,8 @@ body { | |||
| 
 | ||||
| /* gogits user setting */ | ||||
| 
 | ||||
| #gogs-user-setting-nav > h4, #gogs-user-setting-container > h4, #gogs-ssh-keys > h4, #gogs-user-delete > h4 ,#gogs-repo-setting-container .tab-pane > h4{ | ||||
| #gogs-user-setting-nav > h4, #gogs-user-setting-container > h4, #gogs-user-setting-container > div > h4, | ||||
| #gogs-ssh-keys > h4, #gogs-user-delete > h4, #gogs-repo-setting-container .tab-pane > h4 { | ||||
|     padding-bottom: 18px; | ||||
|     margin-bottom: 18px; | ||||
|     border-bottom: 1px solid #CCC; | ||||
|  | @ -380,6 +386,7 @@ body { | |||
| } | ||||
| 
 | ||||
| #gogs-feed-right .repo-panel .list-group-item:hover { | ||||
|     background-color: #eafffd; | ||||
|     background-color: rgba(65, 131, 196, 0.1); | ||||
| } | ||||
| 
 | ||||
|  | @ -391,6 +398,12 @@ body { | |||
| 
 | ||||
| /* gogits repo single page */ | ||||
| 
 | ||||
| #gogs-body-nav.gogs-repo-nav { | ||||
|     padding-top: 16px; | ||||
|     padding-bottom: 30px; | ||||
|     height: auto; | ||||
| } | ||||
| 
 | ||||
| .gogs-repo-nav h3 .fa { | ||||
|     color: #BBB; | ||||
| } | ||||
|  | @ -429,32 +442,82 @@ body { | |||
|     margin-bottom: 4px; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #gogs-repo-toolbar{ | ||||
| #gogs-repo-toolbar { | ||||
|     margin-top: 51px; | ||||
|     margin-bottom: -50px; | ||||
|     border-bottom: 1px solid #BBB; | ||||
|     background-color: #FFF; | ||||
|     height: 40px; | ||||
|     font-size: 14px; | ||||
| } | ||||
| 
 | ||||
| #gogs-repo-toolbar .navbar-default{ | ||||
| #gogs-repo-toolbar .navbar-default { | ||||
|     border: none; | ||||
|     height: 39px; | ||||
| } | ||||
| 
 | ||||
| #gogs-repo-toolbar .nav > li > a{ | ||||
| #gogs-repo-toolbar .nav > li > a { | ||||
|     height: 39px; | ||||
| } | ||||
| 
 | ||||
| #gogs-repo-toolbar .navbar-toolbar.navbar-default .navbar-nav>.active>a:after{ | ||||
| #gogs-repo-toolbar .navbar-toolbar.navbar-default .navbar-nav > .active > a:after { | ||||
|     border-bottom-color: #999; | ||||
| } | ||||
| 
 | ||||
| #gogs-repo-toolbar .navbar.nav-toolbar{ | ||||
| #gogs-repo-toolbar .navbar.nav-toolbar { | ||||
|     margin-bottom: 0; | ||||
| } | ||||
| 
 | ||||
| #gogs-repo-toolbar .navbar-collapse{ | ||||
| #gogs-repo-toolbar .navbar-collapse { | ||||
|     padding: 0; | ||||
| } | ||||
| 
 | ||||
| /* #gogs-source */ | ||||
| 
 | ||||
| #gogs-source-toolbar:after { | ||||
|     clear: both; | ||||
| } | ||||
| 
 | ||||
| #gogs-source-toolbar .branch-switch { | ||||
|     display: inline-block; | ||||
| } | ||||
| 
 | ||||
| #gogs-source-toolbar .breadcrumb { | ||||
|     margin: 0 .5em; | ||||
|     font-size: 16px; | ||||
|     vertical-align: middle; | ||||
|     display: inline-block; | ||||
|     background-color: transparent; | ||||
| } | ||||
| 
 | ||||
| #gogs-source-table { | ||||
|     margin-top: 1.5em; | ||||
|     font-size: 14px; | ||||
| } | ||||
| 
 | ||||
| #gogs-source-table .fa{ | ||||
|     font-size: 15px; | ||||
|     width: 16px; | ||||
|     text-align: center; | ||||
|     color: #666; | ||||
| } | ||||
| 
 | ||||
| #gogs-source-table .name{ | ||||
|     width: 160px; | ||||
| } | ||||
| 
 | ||||
| #gogs-source-table .size{ | ||||
|     width: 80px; | ||||
| } | ||||
| 
 | ||||
| #gogs-source-table .date{ | ||||
|     width: 120px; | ||||
| } | ||||
| 
 | ||||
| #gogs-source-table .is-dir .name { | ||||
|     font-weight: bold; | ||||
| } | ||||
| 
 | ||||
| #gogs-source-table.table-hover > tbody > tr:hover > td { | ||||
|     background-color: #FEFEFE; | ||||
| } | ||||
|  | @ -78,7 +78,6 @@ function initRegister() { | |||
|             rules: { | ||||
|                 "username": { | ||||
|                     required: true, | ||||
|                     minlength: 5, | ||||
|                     maxlength: 30 | ||||
|                 }, | ||||
|                 "email": { | ||||
|  |  | |||
|  | @ -5,9 +5,10 @@ | |||
| package repo | ||||
| 
 | ||||
| import ( | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/martini-contrib/render" | ||||
| 	"github.com/martini-contrib/sessions" | ||||
| 	"net/http" | ||||
| 
 | ||||
| 	"github.com/gogits/gogs/models" | ||||
| 	"github.com/gogits/gogs/modules/auth" | ||||
|  | @ -46,7 +47,7 @@ func Create(form auth.CreateRepoForm, req *http.Request, r render.Render, data b | |||
| 	if err == nil { | ||||
| 		if _, err = models.CreateRepository(user, | ||||
| 			form.RepoName, form.Description, form.Language, form.License, | ||||
| 			form.Visibility == "private", form.InitReadme == "true"); err == nil { | ||||
| 			form.Visibility == "private", form.InitReadme == "on"); err == nil { | ||||
| 			if err == nil { | ||||
| 				data["RepoName"] = user.Name + "/" + form.RepoName | ||||
| 				r.HTML(200, "repo/created", data) | ||||
|  | @ -63,9 +64,7 @@ func Create(form auth.CreateRepoForm, req *http.Request, r render.Render, data b | |||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	data["ErrorMsg"] = err | ||||
| 	log.Error("repo.Create: %v", err) | ||||
| 	r.HTML(200, "base/error", data) | ||||
| 	log.Handle(200, "repo.Create", data, r, err) | ||||
| } | ||||
| 
 | ||||
| func Delete(form auth.DeleteRepoForm, req *http.Request, r render.Render, data base.TmplData, session sessions.Session) { | ||||
|  | @ -77,13 +76,11 @@ func Delete(form auth.DeleteRepoForm, req *http.Request, r render.Render, data b | |||
| 	} | ||||
| 
 | ||||
| 	if err := models.DeleteRepository(form.UserId, form.RepoId, form.UserName); err != nil { | ||||
| 		data["ErrorMsg"] = err | ||||
| 		log.Error("repo.Delete: %v", err) | ||||
| 		r.HTML(200, "base/error", data) | ||||
| 		log.Handle(200, "repo.Delete", data, r, err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	r.Redirect("/", 200) | ||||
| 	r.Redirect("/", 302) | ||||
| } | ||||
| 
 | ||||
| func List(req *http.Request, r render.Render, data base.TmplData, session sessions.Session) { | ||||
|  | @ -96,9 +93,7 @@ func List(req *http.Request, r render.Render, data base.TmplData, session sessio | |||
| 	data["Title"] = "Repositories" | ||||
| 	repos, err := models.GetRepositories(u) | ||||
| 	if err != nil { | ||||
| 		data["ErrorMsg"] = err | ||||
| 		log.Error("repo.List: %v", err) | ||||
| 		r.HTML(200, "base/error", data) | ||||
| 		log.Handle(200, "repo.List", data, r, err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| package repo | ||||
| 
 | ||||
| import ( | ||||
| 	"strings" | ||||
| 	"github.com/codegangsta/martini" | ||||
| 	"github.com/martini-contrib/render" | ||||
| 
 | ||||
|  | @ -13,15 +14,27 @@ func Single(params martini.Params, r render.Render, data base.TmplData) { | |||
| 	if !data["IsRepositoryValid"].(bool) { | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	files, err := models.GetReposFiles(params["username"], params["reponame"], "HEAD", "/") | ||||
| 	if params["branchname"] == "" { | ||||
| 		params["branchname"] = "master" | ||||
| 	} | ||||
| 	treename := params["_1"] | ||||
| 	files, err := models.GetReposFiles(params["username"], params["reponame"], | ||||
| 		params["branchname"], treename) | ||||
| 	if err != nil { | ||||
| 		data["ErrorMsg"] = err | ||||
| 		log.Error("repo.List: %v", err) | ||||
| 		r.HTML(200, "base/error", data) | ||||
| 		log.Handle(200, "repo.Single", data, r, err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	data["Username"] = params["username"] | ||||
| 	data["Reponame"] = params["reponame"] | ||||
| 	data["Branchname"] = params["branchname"] | ||||
| 	treenames := strings.Split(treename, "/") | ||||
| 	Paths := make([]string, 0) | ||||
| 	for i, _ := range treenames { | ||||
| 		Paths = append(Paths, strings.Join(treenames[0:i+1], "/")) | ||||
| 	} | ||||
| 	data["Paths"] = Paths | ||||
| 	data["Treenames"] = treenames | ||||
| 	data["IsRepoToolbarSource"] = true | ||||
| 	data["Files"] = files | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,12 +17,72 @@ import ( | |||
| 	"github.com/gogits/gogs/modules/log" | ||||
| ) | ||||
| 
 | ||||
| func Setting(r render.Render, data base.TmplData, session sessions.Session) { | ||||
| func Setting(form auth.UpdateProfileForm, r render.Render, data base.TmplData, req *http.Request, session sessions.Session) { | ||||
| 	data["Title"] = "Setting" | ||||
| 	data["PageIsUserSetting"] = true | ||||
| 
 | ||||
| 	user := auth.SignedInUser(session) | ||||
| 	data["Owner"] = user | ||||
| 
 | ||||
| 	if req.Method == "GET" { | ||||
| 		r.HTML(200, "user/setting", data) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if hasErr, ok := data["HasError"]; ok && hasErr.(bool) { | ||||
| 		r.HTML(200, "user/setting", data) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	user.Email = form.Email | ||||
| 	user.Website = form.Website | ||||
| 	user.Location = form.Location | ||||
| 	user.Avatar = base.EncodeMd5(form.Avatar) | ||||
| 	user.AvatarEmail = form.Avatar | ||||
| 	if err := models.UpdateUser(user); err != nil { | ||||
| 		log.Handle(200, "setting.Setting", data, r, err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	data["IsSuccess"] = true | ||||
| 	r.HTML(200, "user/setting", data) | ||||
| } | ||||
| 
 | ||||
| func SettingPassword(form auth.UpdatePasswdForm, r render.Render, data base.TmplData, session sessions.Session, req *http.Request) { | ||||
| 	data["Title"] = "Password" | ||||
| 	data["PageIsUserSetting"] = true | ||||
| 
 | ||||
| 	if req.Method == "GET" { | ||||
| 		r.HTML(200, "user/password", data) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	user := auth.SignedInUser(session) | ||||
| 	newUser := &models.User{Passwd: form.NewPasswd} | ||||
| 	if err := newUser.EncodePasswd(); err != nil { | ||||
| 		log.Handle(200, "setting.SettingPassword", data, r, err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	if user.Passwd != newUser.Passwd { | ||||
| 		data["HasError"] = true | ||||
| 		data["ErrorMsg"] = "Old password is not correct" | ||||
| 	} else if form.NewPasswd != form.RetypePasswd { | ||||
| 		data["HasError"] = true | ||||
| 		data["ErrorMsg"] = "New password and re-type password are not same" | ||||
| 	} else { | ||||
| 		user.Passwd = newUser.Passwd | ||||
| 		if err := models.UpdateUser(user); err != nil { | ||||
| 			log.Handle(200, "setting.SettingPassword", data, r, err) | ||||
| 			return | ||||
| 		} | ||||
| 		data["IsSuccess"] = true | ||||
| 	} | ||||
| 
 | ||||
| 	data["Owner"] = user | ||||
| 	r.HTML(200, "user/password", data) | ||||
| } | ||||
| 
 | ||||
| func SettingSSHKeys(form auth.AddSSHKeyForm, r render.Render, data base.TmplData, req *http.Request, session sessions.Session) { | ||||
| 	data["Title"] = "SSH Keys" | ||||
| 
 | ||||
|  | @ -94,3 +154,17 @@ func SettingSSHKeys(form auth.AddSSHKeyForm, r render.Render, data base.TmplData | |||
| 	data["Keys"] = keys | ||||
| 	r.HTML(200, "user/publickey", data) | ||||
| } | ||||
| 
 | ||||
| func SettingNotification(r render.Render, data base.TmplData) { | ||||
| 	// todo user setting notification
 | ||||
| 	data["Title"] = "Notification" | ||||
| 	data["PageIsUserSetting"] = true | ||||
| 	r.HTML(200, "user/notification", data) | ||||
| } | ||||
| 
 | ||||
| func SettingSecurity(r render.Render, data base.TmplData) { | ||||
| 	// todo user setting security
 | ||||
| 	data["Title"] = "Security" | ||||
| 	data["PageIsUserSetting"] = true | ||||
| 	r.HTML(200, "user/security", data) | ||||
| } | ||||
|  |  | |||
|  | @ -22,9 +22,7 @@ func Dashboard(r render.Render, data base.TmplData, session sessions.Session) { | |||
| 	data["PageIsUserDashboard"] = true | ||||
| 	repos, err := models.GetRepositories(&models.User{Id: auth.SignedInId(session)}) | ||||
| 	if err != nil { | ||||
| 		data["ErrorMsg"] = err | ||||
| 		log.Error("dashboard: %v", err) | ||||
| 		r.HTML(200, "base/error", data) | ||||
| 		log.Handle(200, "user.Dashboard", data, r, err) | ||||
| 		return | ||||
| 	} | ||||
| 	data["MyRepos"] = repos | ||||
|  | @ -37,14 +35,11 @@ func Profile(params martini.Params, r render.Render, data base.TmplData, session | |||
| 	// TODO: Need to check view self or others.
 | ||||
| 	user, err := models.GetUserByName(params["username"]) | ||||
| 	if err != nil { | ||||
| 		data["ErrorMsg"] = err | ||||
| 		log.Error("user.Profile: %v", err) | ||||
| 		r.HTML(200, "base/error", data) | ||||
| 		log.Handle(200, "user.Profile", data, r, err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
| 	data["Avatar"] = user.Avatar | ||||
| 	data["Username"] = user.Name | ||||
| 	data["Owner"] = user | ||||
| 	r.HTML(200, "user/profile", data) | ||||
| } | ||||
| 
 | ||||
|  | @ -71,9 +66,7 @@ func SignIn(form auth.LogInForm, data base.TmplData, req *http.Request, r render | |||
| 			return | ||||
| 		} | ||||
| 
 | ||||
| 		data["ErrorMsg"] = err | ||||
| 		log.Error("user.SignIn: %v", err) | ||||
| 		r.HTML(200, "base/error", data) | ||||
| 		log.Handle(200, "user.SignIn", data, r, err) | ||||
| 		return | ||||
| 	} | ||||
| 
 | ||||
|  | @ -130,9 +123,7 @@ func SignUp(form auth.RegisterForm, data base.TmplData, req *http.Request, r ren | |||
| 			data["ErrorMsg"] = "E-mail address has been already used" | ||||
| 			r.HTML(200, "user/signup", data) | ||||
| 		default: | ||||
| 			data["ErrorMsg"] = err | ||||
| 			log.Error("user.SignUp: %v", data) | ||||
| 			r.HTML(200, "base/error", nil) | ||||
| 			log.Handle(200, "user.SignUp", data, r, err) | ||||
| 		} | ||||
| 		return | ||||
| 	} | ||||
|  | @ -156,9 +147,7 @@ func Delete(data base.TmplData, req *http.Request, session sessions.Session, r r | |||
| 		case models.ErrUserOwnRepos.Error(): | ||||
| 			data["ErrorMsg"] = "Your account still have ownership of repository, you have to delete or transfer them first." | ||||
| 		default: | ||||
| 			data["ErrorMsg"] = err | ||||
| 			log.Error("user.Delete: %v", data) | ||||
| 			r.HTML(200, "base/error", nil) | ||||
| 			log.Handle(200, "user.Delete", data, r, err) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -1,6 +1,17 @@ | |||
| <div id="gogs-body-nav" class="gogs-repo-nav"> | ||||
|     <div class="container"> | ||||
|         <div class="gogs-repo-btns pull-right"> | ||||
|             <div class="btn-group" id="gogs-repo-clone"> | ||||
|                 <button type="button" class="btn btn-default"><i class="fa fa-download"></i>Clone</button> | ||||
|                 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> | ||||
|                     <span class="caret"></span> | ||||
|                     <span class="sr-only">Toggle Dropdown</span> | ||||
|                 </button> | ||||
|                 <div class="dropdown-menu" role="menu"> | ||||
|                     <div data-val="down-http">http link</div> | ||||
|                     <div data-val="down-git">git link</div> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <div class="btn-group" id="gogs-repo-watching"> | ||||
|                 <button type="button" class="btn btn-default"><i class="fa fa-eye"></i>Watch {x}</button> | ||||
|                 <button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown"> | ||||
|  |  | |||
|  | @ -3,11 +3,58 @@ | |||
| {{template "repo/nav" .}} | ||||
| {{template "repo/toolbar" .}} | ||||
| <div id="gogs-body" class="container"> | ||||
|     <h4>Source Files:</h4> | ||||
|     <ul> | ||||
|     {{range .Files}} | ||||
|         <li>{{.Name}} - {{.Id}} - {{.Message}} - {{.Created}} - {{.IsFile}} - {{.IsDir}}</li> | ||||
|     {{end}} | ||||
|     </ul> | ||||
|     <div id="gogs-source"> | ||||
|         <div id="gogs-source-toolbar"> | ||||
|             <button class="btn btn-default pull-right"><i class="fa fa-plus-square"></i>Add File</button> | ||||
|             <div class="dropdown branch-switch"> | ||||
|                 <a href="#" class="btn btn-success dropdown-toggle" data-toggle="dropdown"><i class="fa fa-chain"></i>master   | ||||
|                     <b class="caret"></b></a> | ||||
|                 <ul class="dropdown-menu"> | ||||
|                     <li><a class="current" href="/{{.RepositoryLink}}/branch/master">master</a></li> | ||||
|                     <li><a href="//{{.RepositoryLink}}/branch/develop">develop</a></li> | ||||
|                 </ul> | ||||
|             </div> | ||||
|             <ol class="breadcrumb"> | ||||
|                 <li class="root dir">{{.Repository.Name}}</li> | ||||
|                 {{$paths := .Paths}} | ||||
|                 {{ $username := .Username}} | ||||
|             {{ $reponame := .Reponame}} | ||||
|             {{ $branchname := .Branchname}} | ||||
|             {{ $treenames := .Treenames}} | ||||
|             {{ $n := len $treenames}} | ||||
|             {{ $l := Subtract $n 1}} | ||||
|                 {{range $i, $v := $treenames}} | ||||
|                 <li class="dir"> | ||||
|                 {{if eq $i $l}}{{$v}} | ||||
|                 {{else}} | ||||
|                 <a href="/{{$username}}/{{$reponame}}/tree/{{$branchname}}/{{index $paths $i}}">{{$v}}</a>  | ||||
|                 {{end}}</li> | ||||
|                 {{end}} | ||||
|             </ol> | ||||
|         </div> | ||||
|         <table id="gogs-source-table" class="table table-hover"> | ||||
|             <thead class="hidden"> | ||||
| 	            <tr> | ||||
| 	                <th class="name">Filename</th> | ||||
| 	                <th class="date">Date modified</th> | ||||
| 	                <th class="text">Message</th> | ||||
| 	            </tr> | ||||
|             </thead> | ||||
|             <tbody> | ||||
|     			{{range .Files}} | ||||
| 				<tr {{if .IsDir}}class="is-dir"{{end}}> | ||||
| 	                <td class="name"><i class="fa {{if .IsDir}}fa-folder{{else}}fa-file{{end}}"></i> | ||||
|                     {{if .IsDir}} | ||||
|                     <a href="/{{$username}}/{{$reponame}}/tree/{{$branchname}}/{{.Path}}">{{.Name}}</a> | ||||
|                     {{else}} | ||||
|                     <a href="#">{{.Name}}</a> | ||||
|                     {{end}}</td> | ||||
| 	                <td class="date"><time datetime="{{.Created}}" data-title="true" title="{{.Created}}">{{TimeSince .Created}}</time></td> | ||||
| 	                <td class="text">{{.Message}}</td> | ||||
| 				</tr> | ||||
|     			{{end}} | ||||
|             </tbody> | ||||
|         </table> | ||||
|     </div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|  | @ -1,40 +1,32 @@ | |||
| <div id="gogs-repo-toolbar"> | ||||
|     <div class="container"> | ||||
|         <nav class="navbar navbar-toolbar navbar-default" role="navigation"> | ||||
|             <div class="container-fluid"> | ||||
|                 <div class="collapse navbar-collapse"> | ||||
|                     <ul class="nav navbar-nav"> | ||||
|                         <li class="dropdown"> | ||||
|                             <a href="#" class="dropdown-toggle" data-toggle="dropdown">Branches <b class="caret"></b></a> | ||||
|                             <ul class="dropdown-menu"> | ||||
|                                 <li><a href="#">master</a></li> | ||||
|                                 <li><a href="#">develop</a></li> | ||||
|                             </ul> | ||||
|                         </li> | ||||
|                         <li class="{{if .IsRepoToolbarSource}}active{{end}}"><a href="/{{.RepositoryLink}}">Source</a></li> | ||||
|                         <li><a href="#">Commits</a></li> | ||||
|                         <li><a href="#">Issues <span class="badge">42</span></a></li> | ||||
|                         <li><a href="#">Pull Requests</a></li> | ||||
|                         <li class="dropdown"> | ||||
|                             <a href="#" class="dropdown-toggle" data-toggle="dropdown">More <b class="caret"></b></a> | ||||
|                             <ul class="dropdown-menu"> | ||||
|                                 <li><a href="#">Release</a></li> | ||||
|                                 <li><a href="#">Wiki</a></li> | ||||
|                             </ul> | ||||
|                         </li> | ||||
|                     </ul> | ||||
|                     <ul class="nav navbar-nav navbar-right"> | ||||
|                         <li class="dropdown"> | ||||
|                             <a href="#" class="dropdown-toggle" data-toggle="dropdown">Statistic <b class="caret"></b></a> | ||||
|                             <ul class="dropdown-menu"> | ||||
|                                 <li><a href="#">Graphic</a></li> | ||||
|                                 <li><a href="#">Pulse</a></li> | ||||
|                                 <li><a href="#">Network</a></li> | ||||
|                             </ul> | ||||
|                         </li>{{if .IsRepositoryOwner}} | ||||
|                         <li class="{{if .IsRepoToolbarSetting}}active{{end}}"><a href="/{{.RepositoryLink}}/settings">Settings</a></li>{{end}} | ||||
|                     </ul> | ||||
|                 </div> | ||||
|             <div class="collapse navbar-collapse"> | ||||
|                 <ul class="nav navbar-nav"> | ||||
|                     <li class="{{if .IsRepoToolbarSource}}active{{end}}"><a href="/{{.RepositoryLink}}">Source</a></li> | ||||
|                     <li><a href="/{{.RepositoryLink}}/commits">Commits</a></li> | ||||
|                     <li><a href="/{{.RepositoryLink}}/issues">Issues <!--<span class="badge">42</span>--></a></li> | ||||
|                     <li><a href="/{{.RepositoryLink}}/pulls">Pull Requests</a></li> | ||||
|                     <li class="dropdown"> | ||||
|                         <a href="#" class="dropdown-toggle" data-toggle="dropdown">More <b class="caret"></b></a> | ||||
|                         <ul class="dropdown-menu"> | ||||
|                             <li><a href="/{{.RepositoryLink}}/release">Release</a></li> | ||||
|                             <li><a href="//{{.RepositoryLink}}/wiki">Wiki</a></li> | ||||
|                         </ul> | ||||
|                     </li> | ||||
|                 </ul> | ||||
|                 <ul class="nav navbar-nav navbar-right"> | ||||
|                     <li class="dropdown"> | ||||
|                         <a href="#" class="dropdown-toggle" data-toggle="dropdown">Statistic <b class="caret"></b></a> | ||||
|                         <ul class="dropdown-menu"> | ||||
|                             <li><a href="#">Graphic</a></li> | ||||
|                             <li><a href="#">Pulse</a></li> | ||||
|                             <li><a href="#">Network</a></li> | ||||
|                         </ul> | ||||
|                     </li>{{if .IsRepositoryOwner}} | ||||
|                     <li class="{{if .IsRepoToolbarSetting}}active{{end}}"><a href="/{{.RepositoryLink}}/settings">Settings</a> | ||||
|                     </li>{{end}} | ||||
|                 </ul> | ||||
|             </div> | ||||
|         </nav> | ||||
|     </div> | ||||
|  |  | |||
|  | @ -5,10 +5,10 @@ | |||
|         <h4>Account Setting</h4> | ||||
|         <ul class="list-group"> | ||||
|             <li class="list-group-item"><a href="/user/setting">Account Profile</a></li> | ||||
|             <li class="list-group-item"><a href="#">Emails and Password</a></li> | ||||
|             <li class="list-group-item"><a href="#">Notifications</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/password">Password</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/notification">Notifications</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/ssh/">SSH Keys</a></li> | ||||
|             <li class="list-group-item"><a href="#">Security</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/security">Security</a></li> | ||||
|             <li class="list-group-item list-group-item-success"><a href="/user/delete">Delete Account</a></li> | ||||
|         </ul> | ||||
|     </div> | ||||
|  |  | |||
							
								
								
									
										19
									
								
								templates/user/notification.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								templates/user/notification.tmpl
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| {{template "base/head" .}} | ||||
| {{template "base/navbar" .}} | ||||
| <div id="gogs-body" class="container"> | ||||
|     <div id="gogs-user-setting-nav" class="col-md-3"> | ||||
|         <h4>Account Setting</h4> | ||||
|         <ul class="list-group"> | ||||
|             <li class="list-group-item"><a href="/user/setting">Account Profile</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/password">Password</a></li> | ||||
|             <li class="list-group-item list-group-item-success"><a href="/user/setting/notification">Notifications</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/ssh/">SSH Keys</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/security">Security</a></li> | ||||
|             <li class="list-group-item"><a href="/user/delete">Delete Account</a></li> | ||||
|         </ul> | ||||
|     </div> | ||||
|     <div id="gogs-user-setting-container" class="col-md-9"> | ||||
|         <h4>Notification</h4> | ||||
|     </div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
							
								
								
									
										51
									
								
								templates/user/password.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								templates/user/password.tmpl
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,51 @@ | |||
| {{template "base/head" .}} | ||||
| {{template "base/navbar" .}} | ||||
| <div id="gogs-body" class="container"> | ||||
|     <div id="gogs-user-setting-nav" class="col-md-3"> | ||||
|         <h4>Account Setting</h4> | ||||
|         <ul class="list-group"> | ||||
|             <li class="list-group-item"><a href="/user/setting">Account Profile</a></li> | ||||
|             <li class="list-group-item list-group-item-success"><a href="/user/setting/password">Password</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/notification">Notifications</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/ssh/">SSH Keys</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/security">Security</a></li> | ||||
|             <li class="list-group-item"><a href="/user/delete">Delete Account</a></li> | ||||
|         </ul> | ||||
|     </div> | ||||
|     <div id="gogs-user-setting-container" class="col-md-9"> | ||||
|         <div id="gogs-setting-pwd"> | ||||
|             <h4>Password</h4> | ||||
|             <form class="form-horizontal" id="gogs-password-form" method="post" action="/user/setting/password">{{if .IsSuccess}} | ||||
|                 <p class="alert alert-success">Password is changed successfully. You can now sign in via new password.</p>{{else if .HasError}}<p class="alert alert-danger form-error">{{.ErrorMsg}}</p>{{end}} | ||||
|                 <div class="form-group"> | ||||
|                     <label class="col-md-2 control-label">Old Password<strong class="text-danger">*</strong></label> | ||||
|                     <div class="col-md-8"> | ||||
|                         <input type="password" name="oldpasswd" class="form-control" placeholder="Type your current password" required="required"> | ||||
|                     </div> | ||||
|                 </div> | ||||
| 
 | ||||
|                 <div class="form-group"> | ||||
|                     <label class="col-md-2 control-label">New Password<strong class="text-danger">*</strong></label> | ||||
|                     <div class="col-md-8"> | ||||
|                         <input type="password" name="newpasswd" class="form-control" placeholder="Type your new password" required="required"> | ||||
|                     </div> | ||||
|                 </div> | ||||
| 
 | ||||
|                 <div class="form-group"> | ||||
|                     <label class="col-md-2 control-label">Re-Type<strong class="text-danger">*</strong></label> | ||||
|                     <div class="col-md-8"> | ||||
|                         <input type="password" name="retypepasswd" class="form-control" placeholder="Re-type your new password" required="required"> | ||||
|                     </div> | ||||
|                 </div> | ||||
| 
 | ||||
|                 <div class="form-group"> | ||||
|                     <div class="col-md-offset-2 col-md-8"> | ||||
|                         <button type="submit" class="btn btn-primary">Change Password</button>   | ||||
|                         <a href="/forget-password/">Forgot your password?</a> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </form> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|  | @ -4,16 +4,16 @@ | |||
|     <div id="gogs-user-profile" class="col-md-3"> | ||||
|         <div class="profile-avatar text-center"> | ||||
|             <a href="#" class="center-block" data-toggle="tooltip" data-placement="bottom" title="Change Avatar"> | ||||
|                 <img id="gogs-user-avatar" src="http://1.gravatar.com/avatar/{{.Avatar}}?s=200" alt="user-avatar" title="username"/> | ||||
|                 <img id="gogs-user-avatar" src="http://1.gravatar.com/avatar/{{.Owner.Avatar}}?s=200" alt="user-avatar" title="username"/> | ||||
|             </a> | ||||
|             <span id="gogs-user-name" class="center-block" href="#">{{.Username}}</span> | ||||
|             <span id="gogs-user-name" class="center-block" href="#">{{.Owner.Name}}</span> | ||||
|         </div> | ||||
|         <div class="profile-info"> | ||||
|             <ul class="list-group"> | ||||
|                 <li class="list-group-item"><i class="fa fa-thumb-tack"></i>City, County, State, Nation</li> | ||||
|                 <li class="list-group-item"><i class="fa fa-envelope"></i><a href="#">Email@EmailAddress.com</a></li> | ||||
|                 <li class="list-group-item"><i class="fa fa-link"></i><a href="#">http://yousite/</a></li> | ||||
|                 <li class="list-group-item"><i class="fa fa-clock-o"></i>Joined At 03.02, 2014</li> | ||||
|                 <li class="list-group-item"><i class="fa fa-thumb-tack"></i>{{.Owner.Location}}</li> | ||||
|                 <li class="list-group-item"><i class="fa fa-envelope"></i><a href="mailto:{{.Owner.Email}}">{{.Owner.Email}}</a></li> | ||||
|                 <li class="list-group-item"><i class="fa fa-link"></i><a target="_blank" href="{{.Owner.Website}}">{{.Owner.Website}}</a></li> | ||||
|                 <li class="list-group-item"><i class="fa fa-clock-o"></i>{{.Owner.Created}}</li> | ||||
|             </ul> | ||||
|         </div> | ||||
|     </div> | ||||
|  |  | |||
|  | @ -5,10 +5,10 @@ | |||
|         <h4>Account Setting</h4> | ||||
|         <ul class="list-group"> | ||||
|             <li class="list-group-item"><a href="/user/setting">Account Profile</a></li> | ||||
|             <li class="list-group-item"><a href="#">Emails and Password</a></li> | ||||
|             <li class="list-group-item"><a href="#">Notifications</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/Password">Password</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/notification">Notifications</a></li> | ||||
|             <li class="list-group-item list-group-item-success"><a href="/user/setting/ssh/">SSH Keys</a></li> | ||||
|             <li class="list-group-item"><a href="#">Security</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/security">Security</a></li> | ||||
|             <li class="list-group-item"><a href="/user/delete">Delete Account</a></li> | ||||
|         </ul> | ||||
|     </div> | ||||
|  |  | |||
|  | @ -1,26 +0,0 @@ | |||
| {{template "base/head" .}} | ||||
| {{template "base/navbar" .}} | ||||
| <div class="container" id="gogs-body"> | ||||
| 	<form action="/user/publickey/add" method="post" class="form-horizontal"> | ||||
| 		<div class="form-group"> | ||||
| 			<label class="col-md-4 control-label">Name of this public key: </label> | ||||
| 			<div class="col-md-3"> | ||||
| 				<input name="keyname" class="form-control" placeholder="Type your preferred name" value="{{.KeyName}}"> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 
 | ||||
| 		<div class="form-group"> | ||||
| 			<label class="col-md-4 control-label">Paste your key here: </label> | ||||
| 			<div class="col-md-3"> | ||||
| 				<textarea name="key_content" cols="30" rows="10" class="form-control">{{.KeyContent}}</textarea> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 
 | ||||
| 		<div class="form-group"> | ||||
| 		    <div class="col-md-offset-4 col-md-3"> | ||||
| 		    	<button type="submit" class="btn btn-info">Add public key</button> | ||||
| 		    </div> | ||||
| 		</div> | ||||
| 	</form> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|  | @ -1,8 +0,0 @@ | |||
| {{template "base/head" .}} | ||||
| {{template "base/navbar" .}} | ||||
| <div class="container"> | ||||
| 		<div class="form-group"> | ||||
| 			publickey added | ||||
| 		</div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|  | @ -1,12 +0,0 @@ | |||
| {{template "base/head" .}} | ||||
| {{template "base/navbar" .}} | ||||
| <div class="container" id="gogs-body"> | ||||
| <div><a href="/user/publickey/add">Add publick key</a></div> | ||||
| 	<ul> | ||||
| 	{{range .Keys}} | ||||
| 		<li>{{.Name}}</li> | ||||
| 		<li>{{.Content}}</li> | ||||
| 	{{end}} | ||||
| 	</ul> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
							
								
								
									
										19
									
								
								templates/user/security.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								templates/user/security.tmpl
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,19 @@ | |||
| {{template "base/head" .}} | ||||
| {{template "base/navbar" .}} | ||||
| <div id="gogs-body" class="container"> | ||||
|     <div id="gogs-user-setting-nav" class="col-md-3"> | ||||
|         <h4>Account Setting</h4> | ||||
|         <ul class="list-group"> | ||||
|             <li class="list-group-item"><a href="/user/setting">Account Profile</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/password">Password</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/notification">Notifications</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/ssh/">SSH Keys</a></li> | ||||
|             <li class="list-group-item list-group-item-success"><a href="/user/setting/security">Security</a></li> | ||||
|             <li class="list-group-item"><a href="/user/delete">Delete Account</a></li> | ||||
|         </ul> | ||||
|     </div> | ||||
|     <div id="gogs-user-setting-container" class="col-md-9"> | ||||
|         <h4>Security</h4> | ||||
|     </div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|  | @ -5,15 +5,54 @@ | |||
|         <h4>Account Setting</h4> | ||||
|         <ul class="list-group"> | ||||
|             <li class="list-group-item list-group-item-success"><a href="/user/setting">Account Profile</a></li> | ||||
|             <li class="list-group-item"><a href="#">Emails and Password</a></li> | ||||
|             <li class="list-group-item"><a href="#">Notifications</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/ssh">SSH Keys</a></li> | ||||
|             <li class="list-group-item"><a href="#">Security</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/password">Password</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/notification">Notifications</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/ssh/">SSH Keys</a></li> | ||||
|             <li class="list-group-item"><a href="/user/setting/security">Security</a></li> | ||||
|             <li class="list-group-item"><a href="/user/delete">Delete Account</a></li> | ||||
|         </ul> | ||||
|     </div> | ||||
|     <div id="gogs-user-setting-container" class="col-md-9"> | ||||
|         setting container | ||||
|         <div id="gogs-setting-pwd"> | ||||
|             <h4>Account Profile</h4> | ||||
|             <form class="form-horizontal" id="gogs-password-form" method="post" action="/user/setting">{{if .IsSuccess}} | ||||
|                 <p class="alert alert-success">Your profile has been successfully updated.</p>{{else if .HasError}}<p class="alert alert-danger form-error">{{.ErrorMsg}}</p>{{end}} | ||||
|                 <p>Your Email will be public and used for Account related notifications and any web based operations made via the web.</p> | ||||
|                 <div class="form-group"> | ||||
|                     <label class="col-md-2 control-label">Email</label> | ||||
|                     <div class="col-md-8"> | ||||
|                         <input type="text" name="email" class="form-control" placeholder="Type your e-mail address" value="{{.Owner.Email}}"> | ||||
|                     </div> | ||||
|                 </div> | ||||
| 
 | ||||
|                 <div class="form-group"> | ||||
|                     <label class="col-md-2 control-label">Website</label> | ||||
|                     <div class="col-md-8"> | ||||
|                         <input type="text" name="website" class="form-control" placeholder="Type your website URL" value="{{.Owner.Website}}"> | ||||
|                     </div> | ||||
|                 </div> | ||||
| 
 | ||||
|                 <div class="form-group"> | ||||
|                     <label class="col-md-2 control-label">Location</label> | ||||
|                     <div class="col-md-8"> | ||||
|                         <input type="text" name="location" class="form-control" placeholder="Type your current location" value="{{.Owner.Location}}"> | ||||
|                     </div> | ||||
|                 </div> | ||||
| 
 | ||||
|                 <div class="form-group"> | ||||
|                     <label class="col-md-2 control-label">Gravatar Email<strong class="text-danger">*</strong></label> | ||||
|                     <div class="col-md-8"> | ||||
|                         <input type="text" name="avatar" class="form-control" placeholder="Type your Gravatar e-mail address" required="required" value="{{.Owner.AvatarEmail}}"> | ||||
|                     </div> | ||||
|                 </div> | ||||
| 
 | ||||
|                 <div class="form-group"> | ||||
|                     <div class="col-md-offset-2 col-md-8"> | ||||
|                         <button type="submit" class="btn btn-primary">Update Profile</button> | ||||
|                     </div> | ||||
|                 </div> | ||||
|             </form> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| {{template "base/footer" .}} | ||||
|  | @ -7,7 +7,7 @@ | |||
| 		<div class="form-group {{if .Err_UserName}}has-error has-feedback{{end}}"> | ||||
| 			<label class="col-md-4 control-label">Username: </label> | ||||
| 			<div class="col-md-6"> | ||||
| 				<input name="username" class="form-control" placeholder="Type your username" value="{{.username}}" required="required" title="Username must contain at least 5 characters"> | ||||
| 				<input name="username" class="form-control" placeholder="Type your username" value="{{.username}}" required="required"> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										60
									
								
								web.go
									
									
									
									
									
								
							
							
						
						
									
										60
									
								
								web.go
									
									
									
									
									
								
							|  | @ -33,6 +33,55 @@ gogs web`, | |||
| 	Flags:  []cli.Flag{}, | ||||
| } | ||||
| 
 | ||||
| func Subtract(left interface{}, right interface{}) interface{} { | ||||
| 	var rleft, rright int64 | ||||
| 	var fleft, fright float64 | ||||
| 	var isInt bool = true | ||||
| 	switch left.(type) { | ||||
| 	case int: | ||||
| 		rleft = int64(left.(int)) | ||||
| 	case int8: | ||||
| 		rleft = int64(left.(int8)) | ||||
| 	case int16: | ||||
| 		rleft = int64(left.(int16)) | ||||
| 	case int32: | ||||
| 		rleft = int64(left.(int32)) | ||||
| 	case int64: | ||||
| 		rleft = left.(int64) | ||||
| 	case float32: | ||||
| 		fleft = float64(left.(float32)) | ||||
| 		isInt = false | ||||
| 	case float64: | ||||
| 		fleft = left.(float64) | ||||
| 		isInt = false | ||||
| 	} | ||||
| 
 | ||||
| 	switch right.(type) { | ||||
| 	case int: | ||||
| 		rright = int64(right.(int)) | ||||
| 	case int8: | ||||
| 		rright = int64(right.(int8)) | ||||
| 	case int16: | ||||
| 		rright = int64(right.(int16)) | ||||
| 	case int32: | ||||
| 		rright = int64(right.(int32)) | ||||
| 	case int64: | ||||
| 		rright = right.(int64) | ||||
| 	case float32: | ||||
| 		fright = float64(left.(float32)) | ||||
| 		isInt = false | ||||
| 	case float64: | ||||
| 		fleft = left.(float64) | ||||
| 		isInt = false | ||||
| 	} | ||||
| 
 | ||||
| 	if isInt { | ||||
| 		return rleft - rright | ||||
| 	} else { | ||||
| 		return fleft + float64(rleft) - (fright + float64(rright)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| var AppHelpers template.FuncMap = map[string]interface{}{ | ||||
| 	"AppName": func() string { | ||||
| 		return base.Cfg.MustValue("", "APP_NAME") | ||||
|  | @ -40,6 +89,8 @@ var AppHelpers template.FuncMap = map[string]interface{}{ | |||
| 	"AppVer": func() string { | ||||
| 		return APP_VER | ||||
| 	}, | ||||
| 	"TimeSince": base.TimeSince, | ||||
| 	"Subtract":  Subtract, | ||||
| } | ||||
| 
 | ||||
| func runWeb(*cli.Context) { | ||||
|  | @ -63,8 +114,11 @@ func runWeb(*cli.Context) { | |||
| 	m.Any("/user/delete", auth.SignInRequire(true), user.Delete) | ||||
| 	m.Get("/user/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) | ||||
| 
 | ||||
| 	m.Any("/user/setting", auth.SignInRequire(true), user.Setting) | ||||
| 	m.Any("/user/setting", auth.SignInRequire(true), binding.BindIgnErr(auth.UpdateProfileForm{}), user.Setting) | ||||
| 	m.Any("/user/setting/password", auth.SignInRequire(true), binding.BindIgnErr(auth.UpdatePasswdForm{}), user.SettingPassword) | ||||
| 	m.Any("/user/setting/ssh", auth.SignInRequire(true), binding.BindIgnErr(auth.AddSSHKeyForm{}), user.SettingSSHKeys) | ||||
| 	m.Any("/user/setting/notification", auth.SignInRequire(true), user.SettingNotification) | ||||
| 	m.Any("/user/setting/security", auth.SignInRequire(true), user.SettingSecurity) | ||||
| 
 | ||||
| 	m.Get("/user/:username", auth.SignInRequire(false), user.Profile) | ||||
| 
 | ||||
|  | @ -73,6 +127,10 @@ func runWeb(*cli.Context) { | |||
| 	m.Any("/repo/list", auth.SignInRequire(false), repo.List) | ||||
| 
 | ||||
| 	m.Get("/:username/:reponame/settings", auth.SignInRequire(false), auth.RepoAssignment(true), repo.Setting) | ||||
| 	m.Get("/:username/:reponame/tree/:branchname/**", | ||||
| 		auth.SignInRequire(false), auth.RepoAssignment(true), repo.Single) | ||||
| 	m.Get("/:username/:reponame/tree/:branchname", | ||||
| 		auth.SignInRequire(false), auth.RepoAssignment(true), repo.Single) | ||||
| 	m.Get("/:username/:reponame", auth.SignInRequire(false), auth.RepoAssignment(true), repo.Single) | ||||
| 
 | ||||
| 	//m.Get("/:username/:reponame", repo.Repo)
 | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue