diff --git a/README.md b/README.md index 064b5488a..ac2f30957 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ More importantly, Gogs only needs one binary to setup your own project hosting o ## Features - Activity timeline -- SSH/HTTPS protocol support. +- SSH/HTTPS(Clone only) protocol support. - Register/delete account. - Create/delete/watch public repository. - User profile page. diff --git a/README_ZH.md b/README_ZH.md index 002d9d788..34f5dfde5 100644 --- a/README_ZH.md +++ b/README_ZH.md @@ -23,7 +23,7 @@ Gogs 完全使用 Go 语言来实现对 Git 数据的操作,实现 **零** 依 ## 功能特性 - 活动时间线 -- SSH/HTTPS 协议支持 +- SSH/HTTPS(仅限 Clone) 协议支持 - 注册/删除用户 - 创建/删除/关注公开仓库 - 用户个人信息页面 diff --git a/gogs.go b/gogs.go index ba443c6e6..57d9d62c6 100644 --- a/gogs.go +++ b/gogs.go @@ -19,7 +19,7 @@ import ( // Test that go1.2 tag above is included in builds. main.go refers to this definition. const go12tag = true -const APP_VER = "0.1.8.0326 Alpha" +const APP_VER = "0.1.8.0327 Alpha" func init() { base.AppVer = APP_VER diff --git a/models/access.go b/models/access.go index 36d9405f5..84cad17a3 100644 --- a/models/access.go +++ b/models/access.go @@ -15,7 +15,7 @@ const ( AU_WRITABLE ) -// Access represents the accessibility of user and repository. +// Access represents the accessibility of user to repository. type Access struct { Id int64 UserName string `xorm:"unique(s)"` @@ -30,7 +30,7 @@ func AddAccess(access *Access) error { return err } -// HasAccess returns true if someone can read or write given repository. +// HasAccess returns true if someone can read or write to given repository. func HasAccess(userName, repoName string, mode int) (bool, error) { return orm.Get(&Access{ Id: 0, diff --git a/models/action.go b/models/action.go index edf1bf58f..46704eef0 100644 --- a/models/action.go +++ b/models/action.go @@ -23,7 +23,8 @@ const ( OP_PULL_REQUEST ) -// Action represents user operation type and information to the repository. +// Action represents user operation type and other information to repository., +// it implemented interface base.Actioner so that can be used in template render. type Action struct { Id int64 UserId int64 // Receiver user id. @@ -57,7 +58,7 @@ func (a Action) GetContent() string { return a.Content } -// CommitRepoAction records action for commit repository. +// CommitRepoAction adds new action for committing repository. func CommitRepoAction(userId int64, userName string, repoId int64, repoName string, refName string, commits *base.PushCommits) error { log.Trace("action.CommitRepoAction(start): %d/%s", userId, repoName) @@ -68,12 +69,13 @@ func CommitRepoAction(userId int64, userName string, return err } - if err = NotifyWatchers(userId, repoId, OP_COMMIT_REPO, userName, repoName, refName, string(bs)); err != nil { + if err = NotifyWatchers(&Action{ActUserId: userId, ActUserName: userName, OpType: OP_COMMIT_REPO, + Content: string(bs), RepoId: repoId, RepoName: repoName, RefName: refName}); err != nil { log.Error("action.CommitRepoAction(notify watchers): %d/%s", userId, repoName) return err } - // Update repository last update time. + // Change repository bare status and update last updated time. repo, err := GetRepositoryByName(userId, repoName) if err != nil { log.Error("action.CommitRepoAction(GetRepositoryByName): %d/%s", userId, repoName) diff --git a/models/repo.go b/models/repo.go index e74643577..1f638fe14 100644 --- a/models/repo.go +++ b/models/repo.go @@ -485,30 +485,21 @@ func GetWatches(repoId int64) ([]Watch, error) { } // NotifyWatchers creates batch of actions for every watcher. -func NotifyWatchers(userId, repoId int64, opType int, userName, repoName, refName, content string) error { +func NotifyWatchers(act *Action) error { // Add feeds for user self and all watchers. - watches, err := GetWatches(repoId) + watches, err := GetWatches(act.RepoId) if err != nil { return errors.New("repo.NotifyWatchers(get watches): " + err.Error()) } - watches = append(watches, Watch{UserId: userId}) + watches = append(watches, Watch{UserId: act.ActUserId}) for i := range watches { - if userId == watches[i].UserId && i > 0 { + if act.ActUserId == watches[i].UserId && i > 0 { continue // Do not add twice in case author watches his/her repository. } - _, err = orm.InsertOne(&Action{ - UserId: watches[i].UserId, - ActUserId: userId, - ActUserName: userName, - OpType: opType, - Content: content, - RepoId: repoId, - RepoName: repoName, - RefName: refName, - }) - if err != nil { + act.UserId = watches[i].UserId + if _, err = orm.InsertOne(act); err != nil { return errors.New("repo.NotifyWatchers(create action): " + err.Error()) } } diff --git a/public/css/gogs.css b/public/css/gogs.css index 436067ed8..d4976460e 100755 --- a/public/css/gogs.css +++ b/public/css/gogs.css @@ -854,6 +854,10 @@ html, body { min-width: 180px; } +.commit-list .sha a { + font-family: Consolas, Menlo, Monaco, "Lucida Console", monospace; +} + .guide-box pre, .guide-box .input-group { margin-top: 20px; margin-bottom: 30px; @@ -1119,7 +1123,7 @@ html, body { #issue .issue-head .info { width: 99%; margin-top: 10px; - padding-left: 64px; + padding-left: 74px; margin-bottom: 16px; padding-bottom: 20px; border-bottom: 1px solid #CCC; @@ -1169,6 +1173,21 @@ html, body { border-color: #CCC; } +#issue .issue-head .info .btn { + margin-top: -8px; + margin-left: 8px; +} + +#issue .issue-action { + padding-left: 8px; + color: #888; + width: 24px; +} + +#issue-edit-title { + width: 60%; +} + /* wrapper and footer */ #wrapper { diff --git a/public/js/app.js b/public/js/app.js index 5bebeaf87..9299a6b7a 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -50,6 +50,14 @@ var Gogits = { } } }); + $.fn.extend({ + toggleHide: function () { + $(this).addClass("hidden"); + }, + toggleShow: function () { + $(this).removeClass("hidden"); + } + }) }(jQuery)); (function ($) { @@ -352,7 +360,8 @@ function initRepository() { }()); } -function initInstall(){ +function initInstall() { + // database type change $('#install-database').on("change", function () { var val = $(this).val(); if (val != "sqlite") { @@ -370,6 +379,35 @@ function initInstall(){ }); } +function initIssue() { + // close button + (function () { + var $closeBtn = $('#issue-close-btn'); + var $openBtn = $('#issue-open-btn'); + $('#issue-reply-content').on("keyup", function () { + if ($(this).val().length) { + $closeBtn.text($closeBtn.data("text")); + $openBtn.text($openBtn.data("text")); + } else { + $closeBtn.text($closeBtn.data("origin")); + $openBtn.text($openBtn.data("origin")); + } + }); + }()); + + // issue edit mode + (function () { + $("#issue-edit-btn").on("click", function () { + $('#issue h1.title,#issue .issue-main > .issue-content .content,#issue-edit-btn').toggleHide(); + $('#issue-edit-title,#issue-edit-content,.issue-edit-cancel,.issue-edit-save').toggleShow(); + }); + $('.issue-edit-cancel').on("click", function () { + $('#issue h1.title,#issue .issue-main > .issue-content .content,#issue-edit-btn').toggleShow(); + $('#issue-edit-title,#issue-edit-content,.issue-edit-cancel,.issue-edit-save').toggleHide(); + }) + }()); +} + (function ($) { $(function () { initCore(); @@ -383,8 +421,11 @@ function initInstall(){ if ($('.repo-nav').length) { initRepository(); } - if($('#install-card').length){ + if ($('#install-card').length) { initInstall(); } + if ($('#issue').length) { + initIssue(); + } }); })(jQuery); diff --git a/routers/repo/issue.go b/routers/repo/issue.go index e53aebf63..49a098d6d 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -78,8 +78,9 @@ func CreateIssue(ctx *middleware.Context, params martini.Params, form auth.Creat } // Notify watchers. - if err = models.NotifyWatchers(ctx.User.Id, ctx.Repo.Repository.Id, models.OP_CREATE_ISSUE, - ctx.User.Name, ctx.Repo.Repository.Name, "", fmt.Sprintf("%d|%s", issue.Index, issue.Name)); err != nil { + if err = models.NotifyWatchers(&models.Action{ActUserId: ctx.User.Id, ActUserName: ctx.User.Name, + OpType: models.OP_CREATE_ISSUE, Content: fmt.Sprintf("%d|%s", issue.Index, issue.Name), + RepoId: ctx.Repo.Repository.Id, RepoName: ctx.Repo.Repository.Name, RefName: ""}); err != nil { ctx.Handle(200, "issue.CreateIssue", err) return } @@ -120,6 +121,7 @@ func ViewIssue(ctx *middleware.Context, params martini.Params) { return } issue.Poster = u + issue.Content = string(base.RenderMarkdown([]byte(issue.Content), "")) // Get comments. comments, err := models.GetIssueComments(issue.Id) @@ -136,6 +138,7 @@ func ViewIssue(ctx *middleware.Context, params martini.Params) { return } comments[i].Poster = u + comments[i].Content = string(base.RenderMarkdown([]byte(comments[i].Content), "")) } ctx.Data["Title"] = issue.Name diff --git a/templates/issue/view.tmpl b/templates/issue/view.tmpl index 6b282513a..4d053930b 100644 --- a/templates/issue/view.tmpl +++ b/templates/issue/view.tmpl @@ -4,12 +4,16 @@ {{template "repo/toolbar" .}}
-
+
#{{.Issue.Index}}

{{.Issue.Name}}

+

+ Edit + + {{if .Issue.IsClosed}}Closed{{else}}Open{{end}} {{.Issue.Poster.Name}} opened this issue {{TimeSince .Issue.Created}} · {{.Issue.NumComments}} comments @@ -18,18 +22,24 @@

-

{{.Issue.Content}}

+
+ {{str2html .Issue.Content}} +
+
{{range .Comments}} -
+
{{.Poster.Name}} commented {{TimeSince .Created}} + + + Owner
-

{{.Content}}

+ {{str2html .Content}}
@@ -52,7 +62,7 @@
- +
preview
@@ -61,7 +71,9 @@
- +    +    +
diff --git a/web.go b/web.go index 3c7abc58c..4ed273ea9 100644 --- a/web.go +++ b/web.go @@ -138,6 +138,10 @@ func runWeb(*cli.Context) { r.Any("/:userid/delete", admin.DeleteUser) }, adminReq) + if martini.Env == martini.Dev { + m.Get("/template/**", dev.TemplatePreview) + } + m.Group("/:username/:reponame", func(r martini.Router) { r.Post("/settings", repo.SettingPost) r.Get("/settings", repo.Setting) @@ -168,10 +172,6 @@ func runWeb(*cli.Context) { r.Any("/:reponame/**", repo.Http) }, ignSignIn) - if martini.Env == martini.Dev { - m.Get("/template/**", dev.TemplatePreview) - } - // Not found handler. m.NotFound(routers.NotFound)