From 7b34f6f1dac2c0b09b98e937226e43e0a6d09cf1 Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Thu, 13 Mar 2014 02:55:14 -0400 Subject: [PATCH 01/15] Update README --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index abb0b8ce20..05056e20a6 100644 --- a/README.md +++ b/README.md @@ -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.6 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,7 @@ 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. - Git repository manipulation. ## Installation From 57bc2d1ca0bfc3ba90e6d85309dba39415c6db73 Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Thu, 13 Mar 2014 03:39:18 -0400 Subject: [PATCH 02/15] Add update user profile back end, add new gitignore and license, add template data to public profile page --- conf/app.ini | 4 +-- conf/gitignore/C | 18 ++++++++++++ conf/license/BSD (3-Clause) License | 27 +++++++++++++++++ gogs.go | 2 +- models/repo.go | 4 +++ models/user.go | 4 ++- modules/auth/auth.go | 5 ---- modules/auth/user.go | 45 +++++++++++++++++++++++++++++ routers/repo/repo.go | 4 +-- routers/user/setting.go | 24 ++++++++++++++- routers/user/user.go | 3 +- templates/user/profile.tmpl | 12 ++++---- web.go | 2 +- 13 files changed, 133 insertions(+), 21 deletions(-) create mode 100644 conf/gitignore/C create mode 100644 conf/license/BSD (3-Clause) License diff --git a/conf/app.ini b/conf/app.ini index fcfbe9bc2d..aa42129cce 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -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 = diff --git a/conf/gitignore/C b/conf/gitignore/C new file mode 100644 index 0000000000..e7a909e4c6 --- /dev/null +++ b/conf/gitignore/C @@ -0,0 +1,18 @@ +# Object files +*.o +*.ko + +# Libraries +*.lib +*.a + +# Shared objects (inc. Windows DLLs) +*.dll +*.so +*.so.* +*.dylib + +# Executables +*.exe +*.out +*.app \ No newline at end of file diff --git a/conf/license/BSD (3-Clause) License b/conf/license/BSD (3-Clause) License new file mode 100644 index 0000000000..3af16b0724 --- /dev/null +++ b/conf/license/BSD (3-Clause) License @@ -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. \ No newline at end of file diff --git a/gogs.go b/gogs.go index f1a702ed22..96c0f84f2b 100644 --- a/gogs.go +++ b/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.0313" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/models/repo.go b/models/repo.go index 6e45367c09..b7b5ac42b0 100644 --- a/models/repo.go +++ b/models/repo.go @@ -352,6 +352,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 diff --git a/models/user.go b/models/user.go index c59e4ae152..06db7d8ba2 100644 --- a/models/user.go +++ b/models/user.go @@ -48,7 +48,9 @@ type User struct { NumFollowings int NumStars int NumRepos int - Avatar string `xorm:"varchar(2048) not null"` + Avatar string `xorm:"varchar(2048) not null"` + Location string + Website string Created time.Time `xorm:"created"` Updated time.Time `xorm:"updated"` } diff --git a/modules/auth/auth.go b/modules/auth/auth.go index e4748650c2..b085527554 100644 --- a/modules/auth/auth.go +++ b/modules/auth/auth.go @@ -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(") { diff --git a/modules/auth/user.go b/modules/auth/user.go index 4059edfdd3..e868fac23d 100644 --- a/modules/auth/user.go +++ b/modules/auth/user.go @@ -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,43 @@ 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:"AlphaDash;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) +} diff --git a/routers/repo/repo.go b/routers/repo/repo.go index a12b45d7b9..e1809b4b7e 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -46,7 +46,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) @@ -83,7 +83,7 @@ func Delete(form auth.DeleteRepoForm, req *http.Request, r render.Render, data b return } - r.Redirect("/", 200) + r.Redirect("/", 302) } func List(req *http.Request, r render.Render, data base.TmplData, session sessions.Session) { diff --git a/routers/user/setting.go b/routers/user/setting.go index 0669784be0..63e4d8cb7d 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -17,9 +17,31 @@ 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) + if req.Method == "GET" { + data["Owner"] = user + } + + 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) + if err := models.UpdateUser(user); err != nil { + data["ErrorMsg"] = err + log.Error("setting.Setting: %v", err) + r.HTML(200, "base/error", data) + return + } + r.HTML(200, "user/setting", data) } diff --git a/routers/user/user.go b/routers/user/user.go index 59177a47b9..2ce158b641 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -43,8 +43,7 @@ func Profile(params martini.Params, r render.Render, data base.TmplData, session return } - data["Avatar"] = user.Avatar - data["Username"] = user.Name + data["Owner"] = user r.HTML(200, "user/profile", data) } diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index 79e6062bcb..94ec33b696 100644 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -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="#">{{.Owner.Email}}</a></li> + <li class="list-group-item"><i class="fa fa-link"></i><a href="#">{{.Owner.Website}}</a></li> + <li class="list-group-item"><i class="fa fa-clock-o"></i>{{.Owner.Created}}</li> </ul> </div> </div> diff --git a/web.go b/web.go index 475b662b39..856d0f106d 100644 --- a/web.go +++ b/web.go @@ -63,7 +63,7 @@ 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/ssh", auth.SignInRequire(true), binding.BindIgnErr(auth.AddSSHKeyForm{}), user.SettingSSHKeys) m.Get("/user/:username", auth.SignInRequire(false), user.Profile) From 76dae5bf680cd701b1ae9876ecc21486a8721f92 Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Thu, 13 Mar 2014 03:44:56 -0400 Subject: [PATCH 03/15] Bug fix --- routers/user/setting.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/routers/user/setting.go b/routers/user/setting.go index 63e4d8cb7d..5ec4c455ef 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -24,6 +24,8 @@ func Setting(form auth.UpdateProfileForm, r render.Render, data base.TmplData, r user := auth.SignedInUser(session) if req.Method == "GET" { data["Owner"] = user + r.HTML(200, "user/setting", data) + return } if hasErr, ok := data["HasError"]; ok && hasErr.(bool) { From c01f593daa994dddc208f853c1c116c56d2ea397 Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Thu, 13 Mar 2014 04:06:35 -0400 Subject: [PATCH 04/15] Add updatePasswd --- README.md | 3 ++- modules/auth/user.go | 33 +++++++++++++++++++++++++++++++++ routers/user/setting.go | 33 +++++++++++++++++++++++++++++++++ web.go | 1 + 4 files changed, 69 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 05056e20a6..0e354a9d47 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ 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.6 Alpha +##### Current version: 0.0.7 Alpha ## Purpose @@ -18,6 +18,7 @@ Please see [Wiki](https://github.com/gogits/gogs/wiki) for project design, devel - SSH protocal support. - Register/delete account. - Create/delete public repository. +- User/repository home page. - Git repository manipulation. ## Installation diff --git a/modules/auth/user.go b/modules/auth/user.go index e868fac23d..6bc7130626 100644 --- a/modules/auth/user.go +++ b/modules/auth/user.go @@ -128,3 +128,36 @@ func (f *UpdateProfileForm) Validate(errors *binding.Errors, req *http.Request, 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) +} diff --git a/routers/user/setting.go b/routers/user/setting.go index 5ec4c455ef..02a214b2c1 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -47,6 +47,39 @@ func Setting(form auth.UpdateProfileForm, r render.Render, data base.TmplData, r r.HTML(200, "user/setting", data) } +func UpdatePasswd(form auth.UpdatePasswdForm, r render.Render, data base.TmplData, req *http.Request, session sessions.Session) { + data["Title"] = "Setting" + data["PageIsUserSetting"] = true + + user := auth.SignedInUser(session) + newUser := &models.User{Passwd: form.OldPasswd} + if err := newUser.EncodePasswd(); err != nil { + data["ErrorMsg"] = err + log.Error("setting.UpdatePasswd: %v", err) + r.HTML(200, "base/error", data) + 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 { + data["ErrorMsg"] = err + log.Error("setting.Setting: %v", err) + r.HTML(200, "base/error", data) + return + } + } + + data["Owner"] = user + r.HTML(200, "user/setting", data) +} + func SettingSSHKeys(form auth.AddSSHKeyForm, r render.Render, data base.TmplData, req *http.Request, session sessions.Session) { data["Title"] = "SSH Keys" diff --git a/web.go b/web.go index 856d0f106d..a80c4924b9 100644 --- a/web.go +++ b/web.go @@ -64,6 +64,7 @@ func runWeb(*cli.Context) { m.Get("/user/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) m.Any("/user/setting", auth.SignInRequire(true), binding.BindIgnErr(auth.UpdateProfileForm{}), user.Setting) + m.Post("/user/setting/update_passwd", auth.SignInRequire(true), binding.BindIgnErr(auth.UpdatePasswdForm{}), user.UpdatePasswd) m.Any("/user/setting/ssh", auth.SignInRequire(true), binding.BindIgnErr(auth.AddSSHKeyForm{}), user.SettingSSHKeys) m.Get("/user/:username", auth.SignInRequire(false), user.Profile) From 52de63e7bbd500a90a1a8cb62cdb490b0ba623c7 Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Thu, 13 Mar 2014 16:21:16 -0400 Subject: [PATCH 05/15] Allow 1 letter usernames --- modules/auth/auth.go | 4 ++-- public/js/app.js | 1 - templates/user/signup.tmpl | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/modules/auth/auth.go b/modules/auth/auth.go index b085527554..0e87168891 100644 --- a/modules/auth/auth.go +++ b/modules/auth/auth.go @@ -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)"` } diff --git a/public/js/app.js b/public/js/app.js index 69d21020e8..0f0ecc43ea 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -78,7 +78,6 @@ function initRegister() { rules: { "username": { required: true, - minlength: 5, maxlength: 30 }, "email": { diff --git a/templates/user/signup.tmpl b/templates/user/signup.tmpl index ba41b0c9bb..2f1e82c730 100644 --- a/templates/user/signup.tmpl +++ b/templates/user/signup.tmpl @@ -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> From 9c0672e0dd8381558dbae42bb4c49000dc4807c5 Mon Sep 17 00:00:00 2001 From: FuXiaoHei <fuxiaohei@hexiaz.com> Date: Fri, 14 Mar 2014 11:24:08 +0800 Subject: [PATCH 06/15] user update-password page ui --- public/css/gogs.css | 16 ++++----- routers/user/setting.go | 8 +++++ templates/user/delete.tmpl | 6 ++-- templates/user/email_password.tmpl | 53 +++++++++++++++++++++++++++++ templates/user/publickey.tmpl | 6 ++-- templates/user/publickey_add.tmpl | 26 -------------- templates/user/publickey_added.tmpl | 8 ----- templates/user/publickey_list.tmpl | 12 ------- templates/user/setting.tmpl | 8 ++--- web.go | 1 + 10 files changed, 80 insertions(+), 64 deletions(-) create mode 100644 templates/user/email_password.tmpl delete mode 100644 templates/user/publickey_add.tmpl delete mode 100644 templates/user/publickey_added.tmpl delete mode 100644 templates/user/publickey_list.tmpl diff --git a/public/css/gogs.css b/public/css/gogs.css index a44d4a9380..7a05b9abe4 100755 --- a/public/css/gogs.css +++ b/public/css/gogs.css @@ -269,7 +269,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; @@ -429,8 +430,7 @@ body { margin-bottom: 4px; } - -#gogs-repo-toolbar{ +#gogs-repo-toolbar { margin-top: 51px; margin-bottom: -50px; border-bottom: 1px solid #BBB; @@ -438,23 +438,23 @@ body { height: 40px; } -#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; } \ No newline at end of file diff --git a/routers/user/setting.go b/routers/user/setting.go index 02a214b2c1..cf11095bea 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -47,6 +47,14 @@ func Setting(form auth.UpdateProfileForm, r render.Render, data base.TmplData, r r.HTML(200, "user/setting", data) } +func SettingEmailPassword(r render.Render, data base.TmplData, session sessions.Session, req *http.Request) { + data["Title"] = "Email & Password" + data["PageIsUserSetting"] = true + data["IsPwdSuccess"] = (req.FormValue("password") == "true") + + r.HTML(200, "user/email_password", data) +} + func UpdatePasswd(form auth.UpdatePasswdForm, r render.Render, data base.TmplData, req *http.Request, session sessions.Session) { data["Title"] = "Setting" data["PageIsUserSetting"] = true diff --git a/templates/user/delete.tmpl b/templates/user/delete.tmpl index af0e1fbc06..37259f61e5 100644 --- a/templates/user/delete.tmpl +++ b/templates/user/delete.tmpl @@ -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/email_password">Emails and 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> diff --git a/templates/user/email_password.tmpl b/templates/user/email_password.tmpl new file mode 100644 index 0000000000..364bcf398e --- /dev/null +++ b/templates/user/email_password.tmpl @@ -0,0 +1,53 @@ +{{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/email_password">Emails and 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-email"> + <h4>Email</h4> + <p><strong>Your Primary Email</strong> will be used for Account related notifications as well as any web based operations, such as edits and merges made via the web.</p> + <p>// TODO</p><br/> + </div> + <div id="gogs-setting-pwd"> + <h4>Password</h4> + <form class="form-horizontal" id="gogs-password-form" method="post" action="/user/setting/update_passwd">{{if .IsPwdSuccess}} + <p class="alert alert-success">Password is changed successfully. You can sign in via new password.</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="re-type" 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/">Forget Password ?</a> + </div> + </div> + </form> + </div> + </div> +</div> +{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/user/publickey.tmpl b/templates/user/publickey.tmpl index 0bd76593e7..195af75887 100644 --- a/templates/user/publickey.tmpl +++ b/templates/user/publickey.tmpl @@ -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/email_password">Emails and 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> diff --git a/templates/user/publickey_add.tmpl b/templates/user/publickey_add.tmpl deleted file mode 100644 index 634b859ddd..0000000000 --- a/templates/user/publickey_add.tmpl +++ /dev/null @@ -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" .}} \ No newline at end of file diff --git a/templates/user/publickey_added.tmpl b/templates/user/publickey_added.tmpl deleted file mode 100644 index f67da9ed85..0000000000 --- a/templates/user/publickey_added.tmpl +++ /dev/null @@ -1,8 +0,0 @@ -{{template "base/head" .}} -{{template "base/navbar" .}} -<div class="container"> - <div class="form-group"> - publickey added - </div> -</div> -{{template "base/footer" .}} \ No newline at end of file diff --git a/templates/user/publickey_list.tmpl b/templates/user/publickey_list.tmpl deleted file mode 100644 index fbd640b4bf..0000000000 --- a/templates/user/publickey_list.tmpl +++ /dev/null @@ -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" .}} \ No newline at end of file diff --git a/templates/user/setting.tmpl b/templates/user/setting.tmpl index 79de58fe75..380ac88a62 100644 --- a/templates/user/setting.tmpl +++ b/templates/user/setting.tmpl @@ -5,10 +5,10 @@ <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/email_password">Emails and 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> diff --git a/web.go b/web.go index a80c4924b9..4712861763 100644 --- a/web.go +++ b/web.go @@ -64,6 +64,7 @@ func runWeb(*cli.Context) { m.Get("/user/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) m.Any("/user/setting", auth.SignInRequire(true), binding.BindIgnErr(auth.UpdateProfileForm{}), user.Setting) + m.Get("/user/setting/email_password",auth.SignInRequire(true),user.SettingEmailPassword) m.Post("/user/setting/update_passwd", auth.SignInRequire(true), binding.BindIgnErr(auth.UpdatePasswdForm{}), user.UpdatePasswd) m.Any("/user/setting/ssh", auth.SignInRequire(true), binding.BindIgnErr(auth.AddSSHKeyForm{}), user.SettingSSHKeys) From bd4ee75fc3cb5f53e267d4340c67ff50206c2f72 Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Fri, 14 Mar 2014 00:19:07 -0400 Subject: [PATCH 07/15] Update --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0323c29726..6559d61a06 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ gogs .DS_Store *.db *.log -custom/ \ No newline at end of file +custom/ +.vendor/ From 47edf7f4f9d359765764207cbcb6dd82dba36de8 Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Fri, 14 Mar 2014 01:12:07 -0400 Subject: [PATCH 08/15] Finish update password and profile --- gogs.go | 2 +- models/user.go | 2 + modules/auth/user.go | 2 +- routers/user/setting.go | 27 ++++++------ templates/user/delete.tmpl | 2 +- .../{email_password.tmpl => password.tmpl} | 18 ++++---- templates/user/profile.tmpl | 4 +- templates/user/publickey.tmpl | 2 +- templates/user/setting.tmpl | 43 ++++++++++++++++++- web.go | 3 +- 10 files changed, 72 insertions(+), 33 deletions(-) rename templates/user/{email_password.tmpl => password.tmpl} (76%) diff --git a/gogs.go b/gogs.go index 96c0f84f2b..b276490280 100644 --- a/gogs.go +++ b/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.7.0313" +const APP_VER = "0.0.7.0314" func init() { runtime.GOMAXPROCS(runtime.NumCPU()) diff --git a/models/user.go b/models/user.go index 06db7d8ba2..8f7a37cba9 100644 --- a/models/user.go +++ b/models/user.go @@ -49,6 +49,7 @@ type User struct { NumStars int NumRepos int Avatar string `xorm:"varchar(2048) not null"` + AvatarEmail string `xorm:"not null"` Location string Website string Created time.Time `xorm:"created"` @@ -106,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 } diff --git a/modules/auth/user.go b/modules/auth/user.go index 6bc7130626..ef595c6000 100644 --- a/modules/auth/user.go +++ b/modules/auth/user.go @@ -96,7 +96,7 @@ type FeedsForm struct { type UpdateProfileForm struct { Email string `form:"email" binding:"Required;Email;MaxSize(50)"` - Website string `form:"website" binding:"AlphaDash;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)"` } diff --git a/routers/user/setting.go b/routers/user/setting.go index cf11095bea..08879ae4a7 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -22,8 +22,9 @@ func Setting(form auth.UpdateProfileForm, r render.Render, data base.TmplData, r data["PageIsUserSetting"] = true user := auth.SignedInUser(session) + data["Owner"] = user + if req.Method == "GET" { - data["Owner"] = user r.HTML(200, "user/setting", data) return } @@ -37,6 +38,7 @@ func Setting(form auth.UpdateProfileForm, r render.Render, data base.TmplData, r 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 { data["ErrorMsg"] = err log.Error("setting.Setting: %v", err) @@ -44,23 +46,21 @@ func Setting(form auth.UpdateProfileForm, r render.Render, data base.TmplData, r return } + data["IsSuccess"] = true r.HTML(200, "user/setting", data) } -func SettingEmailPassword(r render.Render, data base.TmplData, session sessions.Session, req *http.Request) { - data["Title"] = "Email & Password" +func SettingPassword(form auth.UpdatePasswdForm, r render.Render, data base.TmplData, session sessions.Session, req *http.Request) { + data["Title"] = "Password" data["PageIsUserSetting"] = true - data["IsPwdSuccess"] = (req.FormValue("password") == "true") - r.HTML(200, "user/email_password", data) -} - -func UpdatePasswd(form auth.UpdatePasswdForm, r render.Render, data base.TmplData, req *http.Request, session sessions.Session) { - data["Title"] = "Setting" - data["PageIsUserSetting"] = true + if req.Method == "GET" { + r.HTML(200, "user/password", data) + return + } user := auth.SignedInUser(session) - newUser := &models.User{Passwd: form.OldPasswd} + newUser := &models.User{Passwd: form.NewPasswd} if err := newUser.EncodePasswd(); err != nil { data["ErrorMsg"] = err log.Error("setting.UpdatePasswd: %v", err) @@ -78,14 +78,15 @@ func UpdatePasswd(form auth.UpdatePasswdForm, r render.Render, data base.TmplDat user.Passwd = newUser.Passwd if err := models.UpdateUser(user); err != nil { data["ErrorMsg"] = err - log.Error("setting.Setting: %v", err) + log.Error("setting.UpdatePasswd: %v", err) r.HTML(200, "base/error", data) return } + data["IsSuccess"] = true } data["Owner"] = user - r.HTML(200, "user/setting", data) + r.HTML(200, "user/password", data) } func SettingSSHKeys(form auth.AddSSHKeyForm, r render.Render, data base.TmplData, req *http.Request, session sessions.Session) { diff --git a/templates/user/delete.tmpl b/templates/user/delete.tmpl index 37259f61e5..904201772e 100644 --- a/templates/user/delete.tmpl +++ b/templates/user/delete.tmpl @@ -5,7 +5,7 @@ <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/email_password">Emails and Password</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> diff --git a/templates/user/email_password.tmpl b/templates/user/password.tmpl similarity index 76% rename from templates/user/email_password.tmpl rename to templates/user/password.tmpl index 364bcf398e..a8b1e21e04 100644 --- a/templates/user/email_password.tmpl +++ b/templates/user/password.tmpl @@ -5,7 +5,7 @@ <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/email_password">Emails and Password</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> @@ -13,37 +13,35 @@ </ul> </div> <div id="gogs-user-setting-container" class="col-md-9"> - <div id="gogs-setting-email"> - <h4>Email</h4> - <p><strong>Your Primary Email</strong> will be used for Account related notifications as well as any web based operations, such as edits and merges made via the web.</p> - <p>// TODO</p><br/> - </div> <div id="gogs-setting-pwd"> <h4>Password</h4> - <form class="form-horizontal" id="gogs-password-form" method="post" action="/user/setting/update_passwd">{{if .IsPwdSuccess}} - <p class="alert alert-success">Password is changed successfully. You can sign in via new password.</p>{{end}} + <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="re-type" class="form-control" placeholder="Re-type your new password" required="required"> + <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/">Forget Password ?</a> + <a href="/forget-password/">Forgot your password?</a> </div> </div> </form> diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl index 94ec33b696..c10bfcb0f3 100644 --- a/templates/user/profile.tmpl +++ b/templates/user/profile.tmpl @@ -11,8 +11,8 @@ <div class="profile-info"> <ul class="list-group"> <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="#">{{.Owner.Email}}</a></li> - <li class="list-group-item"><i class="fa fa-link"></i><a href="#">{{.Owner.Website}}</a></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> diff --git a/templates/user/publickey.tmpl b/templates/user/publickey.tmpl index 195af75887..60d2c2464a 100644 --- a/templates/user/publickey.tmpl +++ b/templates/user/publickey.tmpl @@ -5,7 +5,7 @@ <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/email_password">Emails and Password</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="/user/setting/security">Security</a></li> diff --git a/templates/user/setting.tmpl b/templates/user/setting.tmpl index 380ac88a62..edbeeb22a9 100644 --- a/templates/user/setting.tmpl +++ b/templates/user/setting.tmpl @@ -5,7 +5,7 @@ <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="/user/setting/email_password">Emails and Password</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> @@ -13,7 +13,46 @@ </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" .}} \ No newline at end of file diff --git a/web.go b/web.go index 4712861763..1fa19afc17 100644 --- a/web.go +++ b/web.go @@ -64,8 +64,7 @@ func runWeb(*cli.Context) { m.Get("/user/feeds", binding.Bind(auth.FeedsForm{}), user.Feeds) m.Any("/user/setting", auth.SignInRequire(true), binding.BindIgnErr(auth.UpdateProfileForm{}), user.Setting) - m.Get("/user/setting/email_password",auth.SignInRequire(true),user.SettingEmailPassword) - m.Post("/user/setting/update_passwd", auth.SignInRequire(true), binding.BindIgnErr(auth.UpdatePasswdForm{}), user.UpdatePasswd) + 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.Get("/user/:username", auth.SignInRequire(false), user.Profile) From 56cf05be771977abd9ae2e68dd446092c595981c Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Fri, 14 Mar 2014 01:40:34 -0400 Subject: [PATCH 09/15] Add errHandler mid ware --- modules/log/error.go | 32 ++++++++++++++++++++++++++++++++ routers/repo/repo.go | 9 ++++----- web.go | 1 + 3 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 modules/log/error.go diff --git a/modules/log/error.go b/modules/log/error.go new file mode 100644 index 0000000000..cb94ec2473 --- /dev/null +++ b/modules/log/error.go @@ -0,0 +1,32 @@ +// Copyright 2014 The Gogs Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package log + +import ( + "github.com/codegangsta/martini" + "github.com/martini-contrib/render" +) + +// ErrHandler is an interface for custom error handler. +type ErrHandler interface { + Handle(string, render.Render, error) +} + +// ErrHandle is a Middleware that maps a ErrHandler service into the Martini handler chain. +func ErrHandle() martini.Handler { + return func(context martini.Context) { + context.MapTo(&errHandler{}, (*ErrHandler)(nil)) + } +} + +type errHandler struct { +} + +func (eh *errHandler) Handle(title string, r render.Render, err error) { + Error("%s: %v", title, err) + r.HTML(200, "base/error", map[string]interface{}{ + "ErrorMsg": err, + }) +} diff --git a/routers/repo/repo.go b/routers/repo/repo.go index e1809b4b7e..1c9bb0500c 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -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" @@ -15,7 +16,7 @@ import ( "github.com/gogits/gogs/modules/log" ) -func Create(form auth.CreateRepoForm, req *http.Request, r render.Render, data base.TmplData, session sessions.Session) { +func Create(form auth.CreateRepoForm, req *http.Request, r render.Render, data base.TmplData, session sessions.Session, eh log.ErrHandler) { data["Title"] = "Create repository" if req.Method == "GET" { @@ -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) + eh.Handle("repo.Create", r, err) } func Delete(form auth.DeleteRepoForm, req *http.Request, r render.Render, data base.TmplData, session sessions.Session) { diff --git a/web.go b/web.go index 1fa19afc17..30e881bba1 100644 --- a/web.go +++ b/web.go @@ -50,6 +50,7 @@ func runWeb(*cli.Context) { // Middlewares. m.Use(render.Renderer(render.Options{Funcs: []template.FuncMap{AppHelpers}})) m.Use(base.InitContext()) + m.Use(log.ErrHandle()) // TODO: should use other store because cookie store is not secure. store := sessions.NewCookieStore([]byte("secret123")) From 15f8bc417e2b5683e2cd578c9c50f51acfd3daba Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Fri, 14 Mar 2014 01:51:12 -0400 Subject: [PATCH 10/15] Add log.handle --- modules/log/error.go | 32 -------------------------------- modules/log/log.go | 10 ++++++++++ routers/repo/repo.go | 4 ++-- web.go | 1 - 4 files changed, 12 insertions(+), 35 deletions(-) delete mode 100644 modules/log/error.go diff --git a/modules/log/error.go b/modules/log/error.go deleted file mode 100644 index cb94ec2473..0000000000 --- a/modules/log/error.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2014 The Gogs Authors. All rights reserved. -// Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE file. - -package log - -import ( - "github.com/codegangsta/martini" - "github.com/martini-contrib/render" -) - -// ErrHandler is an interface for custom error handler. -type ErrHandler interface { - Handle(string, render.Render, error) -} - -// ErrHandle is a Middleware that maps a ErrHandler service into the Martini handler chain. -func ErrHandle() martini.Handler { - return func(context martini.Context) { - context.MapTo(&errHandler{}, (*ErrHandler)(nil)) - } -} - -type errHandler struct { -} - -func (eh *errHandler) Handle(title string, r render.Render, err error) { - Error("%s: %v", title, err) - r.HTML(200, "base/error", map[string]interface{}{ - "ErrorMsg": err, - }) -} diff --git a/modules/log/log.go b/modules/log/log.go index 0634bde655..f71be7c133 100644 --- a/modules/log/log.go +++ b/modules/log/log.go @@ -6,7 +6,11 @@ package log import ( + "github.com/martini-contrib/render" + "github.com/gogits/logs" + + "github.com/gogits/gogs/modules/base" ) var logger *logs.BeeLogger @@ -35,3 +39,9 @@ func Warn(format string, v ...interface{}) { func Critical(format string, v ...interface{}) { logger.Critical(format, v...) } + +func Handle(status int, title, tmpl string, data base.TmplData, r render.Render, err error) { + data["ErrorMsg"] = err + Error("%s: %v", title, err) + r.HTML(status, tmpl, data) +} diff --git a/routers/repo/repo.go b/routers/repo/repo.go index 1c9bb0500c..706b4f937d 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -16,7 +16,7 @@ import ( "github.com/gogits/gogs/modules/log" ) -func Create(form auth.CreateRepoForm, req *http.Request, r render.Render, data base.TmplData, session sessions.Session, eh log.ErrHandler) { +func Create(form auth.CreateRepoForm, req *http.Request, r render.Render, data base.TmplData, session sessions.Session) { data["Title"] = "Create repository" if req.Method == "GET" { @@ -64,7 +64,7 @@ func Create(form auth.CreateRepoForm, req *http.Request, r render.Render, data b return } - eh.Handle("repo.Create", r, err) + log.Handle(200, "repo.Create", "base/error", data, r, err) } func Delete(form auth.DeleteRepoForm, req *http.Request, r render.Render, data base.TmplData, session sessions.Session) { diff --git a/web.go b/web.go index 30e881bba1..1fa19afc17 100644 --- a/web.go +++ b/web.go @@ -50,7 +50,6 @@ func runWeb(*cli.Context) { // Middlewares. m.Use(render.Renderer(render.Options{Funcs: []template.FuncMap{AppHelpers}})) m.Use(base.InitContext()) - m.Use(log.ErrHandle()) // TODO: should use other store because cookie store is not secure. store := sessions.NewCookieStore([]byte("secret123")) From 1ce17cce764b5c10feeba5a92586be9a45173e26 Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Fri, 14 Mar 2014 01:59:07 -0400 Subject: [PATCH 11/15] Add log.handle --- modules/log/log.go | 6 ++++-- routers/repo/repo.go | 10 +++------- routers/repo/single.go | 4 +--- routers/user/setting.go | 12 +++-------- routers/user/user.go | 20 +++++-------------- .../{base/error.tmpl => status/200.tmpl} | 0 6 files changed, 16 insertions(+), 36 deletions(-) rename templates/{base/error.tmpl => status/200.tmpl} (100%) diff --git a/modules/log/log.go b/modules/log/log.go index f71be7c133..b3a3e0a63c 100644 --- a/modules/log/log.go +++ b/modules/log/log.go @@ -6,6 +6,8 @@ package log import ( + "fmt" + "github.com/martini-contrib/render" "github.com/gogits/logs" @@ -40,8 +42,8 @@ func Critical(format string, v ...interface{}) { logger.Critical(format, v...) } -func Handle(status int, title, tmpl string, data base.TmplData, r render.Render, err error) { +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, tmpl, data) + r.HTML(status, fmt.Sprintf("status/%d", status), data) } diff --git a/routers/repo/repo.go b/routers/repo/repo.go index 706b4f937d..b25ce1899c 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -64,7 +64,7 @@ func Create(form auth.CreateRepoForm, req *http.Request, r render.Render, data b return } - log.Handle(200, "repo.Create", "base/error", data, r, err) + 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) { @@ -76,9 +76,7 @@ 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 } @@ -95,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 } diff --git a/routers/repo/single.go b/routers/repo/single.go index 1d5e601aa3..489666f406 100644 --- a/routers/repo/single.go +++ b/routers/repo/single.go @@ -16,9 +16,7 @@ func Single(params martini.Params, r render.Render, data base.TmplData) { files, err := models.GetReposFiles(params["username"], params["reponame"], "HEAD", "/") 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 } diff --git a/routers/user/setting.go b/routers/user/setting.go index 08879ae4a7..b01d27d845 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -40,9 +40,7 @@ func Setting(form auth.UpdateProfileForm, r render.Render, data base.TmplData, r user.Avatar = base.EncodeMd5(form.Avatar) user.AvatarEmail = form.Avatar if err := models.UpdateUser(user); err != nil { - data["ErrorMsg"] = err - log.Error("setting.Setting: %v", err) - r.HTML(200, "base/error", data) + log.Handle(200, "setting.Setting", data, r, err) return } @@ -62,9 +60,7 @@ func SettingPassword(form auth.UpdatePasswdForm, r render.Render, data base.Tmpl user := auth.SignedInUser(session) newUser := &models.User{Passwd: form.NewPasswd} if err := newUser.EncodePasswd(); err != nil { - data["ErrorMsg"] = err - log.Error("setting.UpdatePasswd: %v", err) - r.HTML(200, "base/error", data) + log.Handle(200, "setting.SettingPassword", data, r, err) return } @@ -77,9 +73,7 @@ func SettingPassword(form auth.UpdatePasswdForm, r render.Render, data base.Tmpl } else { user.Passwd = newUser.Passwd if err := models.UpdateUser(user); err != nil { - data["ErrorMsg"] = err - log.Error("setting.UpdatePasswd: %v", err) - r.HTML(200, "base/error", data) + log.Handle(200, "setting.SettingPassword", data, r, err) return } data["IsSuccess"] = true diff --git a/routers/user/user.go b/routers/user/user.go index 2ce158b641..6095b53808 100644 --- a/routers/user/user.go +++ b/routers/user/user.go @@ -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,9 +35,7 @@ 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 } @@ -70,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 } @@ -129,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 } @@ -155,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 } } diff --git a/templates/base/error.tmpl b/templates/status/200.tmpl similarity index 100% rename from templates/base/error.tmpl rename to templates/status/200.tmpl From 8d1fcdaf2cb647edd1bbc031b601afa99a1f8989 Mon Sep 17 00:00:00 2001 From: FuXiaoHei <fuxiaohei@hexiaz.com> Date: Fri, 14 Mar 2014 14:17:29 +0800 Subject: [PATCH 12/15] repo page ui --- public/css/gogs.css | 63 +++++++++++++++++++++++++++++++++++++ templates/repo/nav.tmpl | 11 +++++++ templates/repo/single.tmpl | 59 ++++++++++++++++++++++++++++++++++ templates/repo/toolbar.tmpl | 60 +++++++++++++++-------------------- 4 files changed, 159 insertions(+), 34 deletions(-) diff --git a/public/css/gogs.css b/public/css/gogs.css index 7a05b9abe4..160f561ca2 100755 --- a/public/css/gogs.css +++ b/public/css/gogs.css @@ -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; @@ -381,6 +386,7 @@ body { } #gogs-feed-right .repo-panel .list-group-item:hover { + background-color: #eafffd; background-color: rgba(65, 131, 196, 0.1); } @@ -392,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; } @@ -436,6 +448,7 @@ body { border-bottom: 1px solid #BBB; background-color: #FFF; height: 40px; + font-size: 14px; } #gogs-repo-toolbar .navbar-default { @@ -457,4 +470,54 @@ body { #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; } \ No newline at end of file diff --git a/templates/repo/nav.tmpl b/templates/repo/nav.tmpl index 5d60d46107..1a9434e860 100644 --- a/templates/repo/nav.tmpl +++ b/templates/repo/nav.tmpl @@ -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"> diff --git a/templates/repo/single.tmpl b/templates/repo/single.tmpl index 42e09b9a2f..54d06aed40 100644 --- a/templates/repo/single.tmpl +++ b/templates/repo/single.tmpl @@ -3,6 +3,65 @@ {{template "repo/nav" .}} {{template "repo/toolbar" .}} <div id="gogs-body" class="container"> + <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> + <li class="dir">Dir</li> + </ol> + </div> + <table id="gogs-source-table" class="table table-hover"> + <thead class="hidden"> + <tr> + <th class="name">Filename</th> + <th class="size">Size</th> + <th class="date">Date modified</th> + <th class="text">Message</th> + </tr> + </thead> + <tbody> + <tr class="is-dir"> + <td class="name" colspan="3"><i class="fa fa-folder"></i><a href="#">dir-1</a></td> + <td class="message">commit message</td> + </tr> + <tr class="is-dir"> + <td class="name" colspan="3"><i class="fa fa-folder"></i><a href="#">dir-2</a></td> + <td class="message"> commit message</td> + </tr> + <tr class="is-dir"> + <td class="name" colspan="3"><i class="fa fa-folder"></i><a href="#">dir-3</a></td> + <td class="message">commit message</td> + </tr> + <tr> + <td class="name"><i class="fa fa-file"></i><a href="#">file-1.txt</a></td> + <td class="size">177 B</td> + <td class="date"><time datetime="2011-10-20T06:51:01+08:00" data-title="true" title="20 October 2011 06:51">3 years ago</time></td> + <td class="text">commit message</td> + </tr> + <tr> + <td class="name"><i class="fa fa-file"></i><a href="#">file-2.txt</a></td> + <td class="size">177 B</td> + <td class="date"><time datetime="2011-10-20T06:51:01+08:00" data-title="true" title="20 October 2011 06:51">3 years ago</time></td> + <td class="text">commit message</td> + </tr><tr> + <td class="name"><i class="fa fa-file"></i><a href="#">file-3.txt</a></td> + <td class="size">177 B</td> + <td class="date"><time datetime="2011-10-20T06:51:01+08:00" data-title="true" title="20 October 2011 06:51">3 years ago</time></td> + <td class="text">commit message</td> + </tr> + + </tbody> + </table> + </div> <h4>Source Files:</h4> <ul> {{range .Files}} diff --git a/templates/repo/toolbar.tmpl b/templates/repo/toolbar.tmpl index a409fcbea7..4a0b60adad 100644 --- a/templates/repo/toolbar.tmpl +++ b/templates/repo/toolbar.tmpl @@ -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> From bd6542c2f1a3b1ebdf09a59ab2187510e6b36bde Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Fri, 14 Mar 2014 02:32:11 -0400 Subject: [PATCH 13/15] Add TimeSince --- modules/base/tool.go | 63 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/modules/base/tool.go b/modules/base/tool.go index eef473f965..445833cebc 100644 --- a/modules/base/tool.go +++ b/modules/base/tool.go @@ -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() +} From 398809b135742ad8a7441f65fa7d0ccec318bd91 Mon Sep 17 00:00:00 2001 From: Unknown <joe2010xtmf@163.com> Date: Fri, 14 Mar 2014 02:40:07 -0400 Subject: [PATCH 14/15] Combine UI and data in repo home page --- templates/repo/single.tmpl | 54 +++++++++----------------------------- web.go | 1 + 2 files changed, 13 insertions(+), 42 deletions(-) diff --git a/templates/repo/single.tmpl b/templates/repo/single.tmpl index 54d06aed40..4a71ad3465 100644 --- a/templates/repo/single.tmpl +++ b/templates/repo/single.tmpl @@ -21,52 +21,22 @@ </div> <table id="gogs-source-table" class="table table-hover"> <thead class="hidden"> - <tr> - <th class="name">Filename</th> - <th class="size">Size</th> - <th class="date">Date modified</th> - <th class="text">Message</th> - </tr> + <tr> + <th class="name">Filename</th> + <th class="date">Date modified</th> + <th class="text">Message</th> + </tr> </thead> <tbody> - <tr class="is-dir"> - <td class="name" colspan="3"><i class="fa fa-folder"></i><a href="#">dir-1</a></td> - <td class="message">commit message</td> - </tr> - <tr class="is-dir"> - <td class="name" colspan="3"><i class="fa fa-folder"></i><a href="#">dir-2</a></td> - <td class="message"> commit message</td> - </tr> - <tr class="is-dir"> - <td class="name" colspan="3"><i class="fa fa-folder"></i><a href="#">dir-3</a></td> - <td class="message">commit message</td> - </tr> - <tr> - <td class="name"><i class="fa fa-file"></i><a href="#">file-1.txt</a></td> - <td class="size">177 B</td> - <td class="date"><time datetime="2011-10-20T06:51:01+08:00" data-title="true" title="20 October 2011 06:51">3 years ago</time></td> - <td class="text">commit message</td> - </tr> - <tr> - <td class="name"><i class="fa fa-file"></i><a href="#">file-2.txt</a></td> - <td class="size">177 B</td> - <td class="date"><time datetime="2011-10-20T06:51:01+08:00" data-title="true" title="20 October 2011 06:51">3 years ago</time></td> - <td class="text">commit message</td> - </tr><tr> - <td class="name"><i class="fa fa-file"></i><a href="#">file-3.txt</a></td> - <td class="size">177 B</td> - <td class="date"><time datetime="2011-10-20T06:51:01+08:00" data-title="true" title="20 October 2011 06:51">3 years ago</time></td> - <td class="text">commit message</td> - </tr> - + {{range .Files}} + <tr {{if .IsDir}}class="is-dir"{{end}}> + <td class="name"><i class="fa fa-file"></i><a href="#">{{.Name}}</a></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> - <h4>Source Files:</h4> - <ul> - {{range .Files}} - <li>{{.Name}} - {{.Message}} - {{.Created}} - {{.IsFile}} - {{.IsDir}}</li> - {{end}} - </ul> </div> {{template "base/footer" .}} \ No newline at end of file diff --git a/web.go b/web.go index 1fa19afc17..f416d96e86 100644 --- a/web.go +++ b/web.go @@ -40,6 +40,7 @@ var AppHelpers template.FuncMap = map[string]interface{}{ "AppVer": func() string { return APP_VER }, + "TimeSince": base.TimeSince, } func runWeb(*cli.Context) { From d18237850c6a4ae855b3f8592994c91462fcdb0a Mon Sep 17 00:00:00 2001 From: FuXiaoHei <fuxiaohei@hexiaz.com> Date: Fri, 14 Mar 2014 17:12:28 +0800 Subject: [PATCH 15/15] add draft page for empty link --- routers/user/setting.go | 14 ++++++++++++++ templates/repo/single.tmpl | 2 +- templates/user/notification.tmpl | 19 +++++++++++++++++++ templates/user/security.tmpl | 19 +++++++++++++++++++ web.go | 2 ++ 5 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 templates/user/notification.tmpl create mode 100644 templates/user/security.tmpl diff --git a/routers/user/setting.go b/routers/user/setting.go index b01d27d845..8b5a2d18df 100644 --- a/routers/user/setting.go +++ b/routers/user/setting.go @@ -154,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) +} diff --git a/templates/repo/single.tmpl b/templates/repo/single.tmpl index 4a71ad3465..fbd05c4ba7 100644 --- a/templates/repo/single.tmpl +++ b/templates/repo/single.tmpl @@ -30,7 +30,7 @@ <tbody> {{range .Files}} <tr {{if .IsDir}}class="is-dir"{{end}}> - <td class="name"><i class="fa fa-file"></i><a href="#">{{.Name}}</a></td> + <td class="name"><i class="fa {{if .IsDir}}fa-folder{{else}}fa-file{{end}}"></i><a href="#">{{.Name}}</a></td> <td class="date"><time datetime="{{.Created}}" data-title="true" title="{{.Created}}">{{TimeSince .Created}}</time></td> <td class="text">{{.Message}}</td> </tr> diff --git a/templates/user/notification.tmpl b/templates/user/notification.tmpl new file mode 100644 index 0000000000..c1abc46fb0 --- /dev/null +++ b/templates/user/notification.tmpl @@ -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" .}} \ No newline at end of file diff --git a/templates/user/security.tmpl b/templates/user/security.tmpl new file mode 100644 index 0000000000..37cd5872aa --- /dev/null +++ b/templates/user/security.tmpl @@ -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" .}} \ No newline at end of file diff --git a/web.go b/web.go index f416d96e86..8f698e39d7 100644 --- a/web.go +++ b/web.go @@ -67,6 +67,8 @@ func runWeb(*cli.Context) { 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)