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