summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2014-03-14 23:54:16 +0800
committerLunny Xiao <xiaolunwen@gmail.com>2014-03-14 23:54:16 +0800
commitb27e8e87f8be2d11468e9057254b6c8933e0af33 (patch)
treebbfb32d7e248ae6f2ec63164722523d96447848a
parent607303e4dee3ddf9ba3d9d67b0186fc5213b167b (diff)
parentd18237850c6a4ae855b3f8592994c91462fcdb0a (diff)
downloadgitea-b27e8e87f8be2d11468e9057254b6c8933e0af33.tar.gz
gitea-b27e8e87f8be2d11468e9057254b6c8933e0af33.zip
add tree view
-rw-r--r--.gitignore3
-rw-r--r--README.md5
-rw-r--r--conf/app.ini4
-rw-r--r--conf/gitignore/C18
-rw-r--r--conf/license/BSD (3-Clause) License27
-rw-r--r--gogs.go2
-rw-r--r--models/repo.go34
-rw-r--r--models/user.go6
-rw-r--r--modules/auth/auth.go9
-rw-r--r--modules/auth/user.go78
-rw-r--r--modules/base/tool.go63
-rw-r--r--modules/log/log.go12
-rwxr-xr-xpublic/css/gogs.css79
-rw-r--r--public/js/app.js1
-rw-r--r--routers/repo/repo.go19
-rw-r--r--routers/repo/single.go23
-rw-r--r--routers/user/setting.go76
-rw-r--r--routers/user/user.go23
-rw-r--r--templates/repo/nav.tmpl11
-rw-r--r--templates/repo/single.tmpl59
-rw-r--r--templates/repo/toolbar.tmpl60
-rw-r--r--templates/status/200.tmpl (renamed from templates/base/error.tmpl)0
-rw-r--r--templates/user/delete.tmpl6
-rw-r--r--templates/user/notification.tmpl19
-rw-r--r--templates/user/password.tmpl51
-rw-r--r--templates/user/profile.tmpl12
-rw-r--r--templates/user/publickey.tmpl6
-rw-r--r--templates/user/publickey_add.tmpl26
-rw-r--r--templates/user/publickey_added.tmpl8
-rw-r--r--templates/user/publickey_list.tmpl12
-rw-r--r--templates/user/security.tmpl19
-rw-r--r--templates/user/setting.tmpl49
-rw-r--r--templates/user/signup.tmpl2
-rw-r--r--web.go60
34 files changed, 716 insertions, 166 deletions
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/
diff --git a/README.md b/README.md
index abb0b8ce20..0e354a9d47 100644
--- a/README.md
+++ b/README.md
@@ -3,6 +3,8 @@ Gogs - Go Git Service [![wercker status](https://app.wercker.com/status/ad0bdb0b
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
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..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.6.0313"
+const APP_VER = "0.0.7.0314"
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
diff --git a/models/repo.go b/models/repo.go
index a44bf69ad3..c5fa899f4d 100644
--- a/models/repo.go
+++ b/models/repo.go
@@ -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
diff --git a/models/user.go b/models/user.go
index c59e4ae152..8f7a37cba9 100644
--- a/models/user.go
+++ b/models/user.go
@@ -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
}
diff --git a/modules/auth/auth.go b/modules/auth/auth.go
index e4748650c2..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)"`
}
@@ -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..ef595c6000 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,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)
+}
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()
+}
diff --git a/modules/log/log.go b/modules/log/log.go
index 0634bde655..b3a3e0a63c 100644
--- a/modules/log/log.go
+++ b/modules/log/log.go
@@ -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)
+}
diff --git a/public/css/gogs.css b/public/css/gogs.css
index a44d4a9380..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;
@@ -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;
} \ No newline at end of file
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/routers/repo/repo.go b/routers/repo/repo.go
index a12b45d7b9..b25ce1899c 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"
@@ -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
}
diff --git a/routers/repo/single.go b/routers/repo/single.go
index 1d5e601aa3..bc35b98e71 100644
--- a/routers/repo/single.go
+++ b/routers/repo/single.go
@@ -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
diff --git a/routers/user/setting.go b/routers/user/setting.go
index 0669784be0..8b5a2d18df 100644
--- a/routers/user/setting.go
+++ b/routers/user/setting.go
@@ -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)
+}
diff --git a/routers/user/user.go b/routers/user/user.go
index 59177a47b9..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,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
}
}
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 c83fcd93cd..292f8cbddd 100644
--- a/templates/repo/single.tmpl
+++ b/templates/repo/single.tmpl
@@ -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&nbsp;&nbsp;
+ <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>&nbsp;
+ {{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" .}} \ No newline at end of file
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>
diff --git a/templates/base/error.tmpl b/templates/status/200.tmpl
index 8f64494201..8f64494201 100644
--- a/templates/base/error.tmpl
+++ b/templates/status/200.tmpl
diff --git a/templates/user/delete.tmpl b/templates/user/delete.tmpl
index af0e1fbc06..904201772e 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/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>
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/password.tmpl b/templates/user/password.tmpl
new file mode 100644
index 0000000000..a8b1e21e04
--- /dev/null
+++ b/templates/user/password.tmpl
@@ -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>&nbsp;&nbsp;
+ <a href="/forget-password/">Forgot your password?</a>
+ </div>
+ </div>
+ </form>
+ </div>
+ </div>
+</div>
+{{template "base/footer" .}} \ No newline at end of file
diff --git a/templates/user/profile.tmpl b/templates/user/profile.tmpl
index 79e6062bcb..c10bfcb0f3 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="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>
diff --git a/templates/user/publickey.tmpl b/templates/user/publickey.tmpl
index 0bd76593e7..60d2c2464a 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/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>
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/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/templates/user/setting.tmpl b/templates/user/setting.tmpl
index 79de58fe75..edbeeb22a9 100644
--- a/templates/user/setting.tmpl
+++ b/templates/user/setting.tmpl
@@ -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" .}} \ No newline at end of file
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>
diff --git a/web.go b/web.go
index 475b662b39..c60a262b00 100644
--- a/web.go
+++ b/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)