summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorslene <vslene@gmail.com>2014-03-28 00:32:19 +0800
committerslene <vslene@gmail.com>2014-03-28 00:32:19 +0800
commitbce8586bc66c6827bf2ea6e27440f01476c2d151 (patch)
treec76e8cba33b131e1c6a21a06a57cde51e375a581
parent346db02d89ae0337956607eec43a0cd3f184fda8 (diff)
parent743593f7910d35f46cc18f06de12e59afa36fb65 (diff)
downloadgitea-bce8586bc66c6827bf2ea6e27440f01476c2d151.tar.gz
gitea-bce8586bc66c6827bf2ea6e27440f01476c2d151.zip
Merge branch 'master' of github.com:gogits/gogs
-rw-r--r--README.md2
-rw-r--r--README_ZH.md2
-rw-r--r--gogs.go2
-rw-r--r--models/access.go4
-rw-r--r--models/action.go10
-rw-r--r--models/repo.go21
-rwxr-xr-xpublic/css/gogs.css21
-rw-r--r--public/js/app.js45
-rw-r--r--routers/repo/issue.go7
-rw-r--r--templates/issue/view.tmpl24
-rw-r--r--web.go8
11 files changed, 107 insertions, 39 deletions
diff --git a/README.md b/README.md
index 064b5488af..ac2f309579 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 002d9d788d..34f5dfde5f 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 ba443c6e65..57d9d62c67 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 36d9405f52..84cad17a3f 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 edf1bf58f9..46704eef07 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 e74643577a..1f638fe14f 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 436067ed8c..d4976460e6 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 5bebeaf877..9299a6b7aa 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 e53aebf636..49a098d6d6 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 6b282513aa..4d053930b9 100644
--- a/templates/issue/view.tmpl
+++ b/templates/issue/view.tmpl
@@ -4,12 +4,16 @@
{{template "repo/toolbar" .}}
<div id="body" class="container">
<div id="issue">
- <div id="issue-id" class="issue-whole">
+ <div id="issue-{issue.id}" class="issue-whole">
<div class="issue-head clearfix">
<div class="number pull-right">#{{.Issue.Index}}</div>
<a class="author pull-left" href="/user/{{.Issue.Poster.Name}}"><img class="avatar" src="{{.Issue.Poster.AvatarLink}}" alt="" width="30"/></a>
<h1 class="title pull-left">{{.Issue.Name}}</h1>
+ <input id="issue-edit-title" class="form-control input-lg pull-left hidden" type="text" value="{issue.title}" data-ajax-rel="issue-save"/>
<p class="info pull-left">
+ <a class="btn btn-default pull-right issue-edit" href="#" id="issue-edit-btn">Edit</a>
+ <a class="btn btn-danger pull-right issue-edit-cancel hidden" href="#">Cancel</a>
+ <a class="btn btn-primary pull-right issue-edit-save hidden" href="#" data-ajax="{issue.save.link}" data-ajax-name="issue-save">Save</a>
<span class="status label label-{{if .Issue.IsClosed}}danger{{else}}success{{end}}">{{if .Issue.IsClosed}}Closed{{else}}Open{{end}}</span>
<a href="/user/{{.Issue.Poster.Name}}" class="author"><strong>{{.Issue.Poster.Name}}</strong></a> opened this issue
<span class="time">{{TimeSince .Issue.Created}}</span> · {{.Issue.NumComments}} comments
@@ -18,18 +22,24 @@
<div class="issue-main">
<div class="panel panel-default issue-content">
<div class="panel-body markdown">
- <p>{{.Issue.Content}}</p>
+ <div class="content">
+ {{str2html .Issue.Content}}
+ </div>
+ <textarea class="form-control hidden" name="content" id="issue-edit-content" rows="10" data-ajax-rel="issue-save">content</textarea>
</div>
</div>
{{range .Comments}}
- <div class="issue-child">
+ <div class="issue-child" id="issue-comment-{issue.comment.id}">
<a class="user pull-left" href="/user/{{.Poster.Name}}"><img class="avatar" src="{{.Poster.AvatarLink}}" alt=""/></a>
<div class="issue-content panel panel-default">
<div class="panel-heading">
<a href="/user/{{.Poster.Name}}" class="user">{{.Poster.Name}}</a> commented <span class="time">{{TimeSince .Created}}</span>
+ <a class="issue-comment-del pull-right issue-action" href="#" title="Edit Comment"><i class="fa fa-times-circle"></i></a>
+ <a class="issue-comment-edit pull-right issue-action" href="#" title="Remove Comment" data-url="{remove-link}"><i class="fa fa-edit"></i></a>
+ <span class="role label label-default pull-right">Owner</span>
</div>
<div class="panel-body markdown">
- <p>{{.Content}}</p>
+ {{str2html .Content}}
</div>
</div>
</div>
@@ -52,7 +62,7 @@
<div class="tab-pane" id="issue-textarea">
<div class="form-group">
<input type="hidden" value="{{.Issue.Index}}" name="issueIndex"/>
- <textarea class="form-control" name="content" id="issue-content" rows="10" placeholder="Write some content">{{.content}}</textarea>
+ <textarea class="form-control" name="content" id="issue-reply-content" rows="10" placeholder="Write some content">{{.content}}</textarea>
</div>
</div>
<div class="tab-pane" id="issue-preview">preview</div>
@@ -61,7 +71,9 @@
<div class="text-right">
<div class="form-group">
<input type="hidden" value="id" name="repo-id"/>
- <button class="btn-success btn">Comment</button>
+ <button class="btn-default btn issue-open" id="issue-open-btn" data-origin="Open" data-text="Open & Comment">Open</button>&nbsp;&nbsp;
+ <button class="btn-default btn issue-close" id="issue-close-btn" data-origin="Close" data-text="Close & Comment">Close</button>&nbsp;&nbsp;
+ <button class="btn-success btn" id="issue-reply-btn">Comment</button>
</div>
</div>
</div>
diff --git a/web.go b/web.go
index 3c7abc58cc..4ed273ea99 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)