aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cmd/web.go15
-rwxr-xr-xpublic/css/gogs.css25
-rw-r--r--public/js/app.js55
-rw-r--r--routers/repo/issue.go46
-rw-r--r--templates/repo/issue/view.tmpl28
5 files changed, 145 insertions, 24 deletions
diff --git a/cmd/web.go b/cmd/web.go
index 0b7aac33b4..aea0cd86aa 100644
--- a/cmd/web.go
+++ b/cmd/web.go
@@ -238,14 +238,6 @@ func runWeb(*cli.Context) {
r.Post("/:index/label", repo.UpdateIssueLabel)
r.Post("/:index/milestone", repo.UpdateIssueMilestone)
r.Post("/:index/assignee", repo.UpdateAssignee)
-
- m.Group("/:index/attachment", func(r martini.Router) {
- r.Get("/:id", repo.IssueGetAttachment)
- r.Post("/", repo.IssuePostAttachment)
- r.Post("/:comment", repo.IssuePostAttachment)
- r.Delete("/:comment/:id", repo.IssueDeleteAttachment)
- })
-
r.Post("/labels/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
r.Post("/labels/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
r.Post("/labels/delete", repo.DeleteLabel)
@@ -262,6 +254,13 @@ func runWeb(*cli.Context) {
r.Get("/releases/edit/:tagname", repo.EditRelease)
}, reqSignIn, middleware.RepoAssignment(true))
+ m.Group("/:username/:reponame/issues/:index/attachment", func(r martini.Router) {
+ r.Get("/:id", repo.IssueGetAttachment)
+ r.Post("/", repo.IssuePostAttachment)
+ r.Post("/:comment", repo.IssuePostAttachment)
+ r.Delete("/:comment/:id", repo.IssueDeleteAttachment)
+ }, reqSignIn, middleware.RepoAssignment(true), middleware.Toggle(&middleware.ToggleOptions{DisableCsrf: true}))
+
m.Group("/:username/:reponame", func(r martini.Router) {
r.Post("/releases/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost)
r.Post("/releases/edit/:tagname", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost)
diff --git a/public/css/gogs.css b/public/css/gogs.css
index 710d0c20b1..e78d7f940c 100755
--- a/public/css/gogs.css
+++ b/public/css/gogs.css
@@ -1794,4 +1794,29 @@ body {
color: #444;
font-weight: bold;
line-height: 30px;
+}
+
+.issue-main .attachments {
+ margin: 0px 10px 10px 10px;
+}
+
+.issue-main .attachments .attachment-label {
+ margin-right: 5px;
+}
+
+.attachment-preview {
+ position: absolute;
+ top: 0px;
+ bottom: 0px;
+
+ margin: 5px;
+ padding: 8px;
+
+ background: #fff;
+ border: 1px solid #d8d8d8;
+ box-shadow: 0 0 5px 1px #d8d8d8;
+}
+
+.attachment-preview-img {
+ border: 1px solid #d8d8d8;
} \ No newline at end of file
diff --git a/public/js/app.js b/public/js/app.js
index 16d1d5dab1..3d4ed62362 100644
--- a/public/js/app.js
+++ b/public/js/app.js
@@ -520,6 +520,61 @@ function initIssue() {
});
}());
+ // Preview for images.
+ (function() {
+ var $hoverElement = $("<div></div>");
+ var $hoverImage = $("<img />");
+
+ $hoverElement.addClass("attachment-preview");
+ $hoverElement.hide();
+
+ $hoverImage.addClass("attachment-preview-img");
+
+ $hoverElement.append($hoverImage);
+ $(document.body).append($hoverElement);
+
+ var over = function() {
+ var $this = $(this);
+
+ if ($this.text().match(/\.(png|jpg|jpeg|gif)$/) == false) {
+ return;
+ }
+
+ if ($hoverImage.attr("src") != $this.attr("href")) {
+ $hoverImage.attr("src", $this.attr("href"));
+ $hoverImage.load(function() {
+ var height = this.height;
+ var width = this.width;
+
+ if (height > 300) {
+ var factor = 300 / height;
+
+ height = factor * height;
+ width = factor * width;
+ }
+
+ $hoverImage.css({"height": height, "width": width});
+
+ var offset = $this.offset();
+ var left = offset.left, top = offset.top + $this.height() + 5;
+
+ $hoverElement.css({"top": top + "px", "left": left + "px"});
+ $hoverElement.css({"height": height + 16, "width": width + 16});
+ $hoverElement.show();
+ });
+ } else {
+ $hoverElement.show();
+ }
+ };
+
+ var out = function() {
+ $hoverElement.hide();
+ };
+
+ $(".issue-main .attachments .attachment").hover(over, out);
+ }());
+
+ // Upload.
(function() {
var $attached = $("#attached");
var $attachments = $("input[name=attachments]");
diff --git a/routers/repo/issue.go b/routers/repo/issue.go
index 6becb2dff7..903a32d968 100644
--- a/routers/repo/issue.go
+++ b/routers/repo/issue.go
@@ -709,6 +709,12 @@ func Comment(ctx *middleware.Context, params martini.Params) {
attachments := strings.Split(params["attachments"], ",")
for _, a := range attachments {
+ a = strings.Trim(a, " ")
+
+ if len(a) == 0 {
+ continue
+ }
+
aId, err := base.StrTo(a).Int64()
if err != nil {
@@ -1002,12 +1008,23 @@ func UpdateMilestonePost(ctx *middleware.Context, params martini.Params, form au
}
func IssuePostAttachment(ctx *middleware.Context, params martini.Params) {
- issueId, _ := base.StrTo(params["index"]).Int64()
+ index, _ := base.StrTo(params["index"]).Int64()
- if issueId == 0 {
+ if index == 0 {
ctx.JSON(400, map[string]interface{}{
"ok": false,
- "error": "invalid issue id",
+ "error": "invalid issue index",
+ })
+
+ return
+ }
+
+ issue, err := models.GetIssueByIndex(ctx.Repo.Repository.Id, index)
+
+ if err != nil {
+ ctx.JSON(400, map[string]interface{}{
+ "ok": false,
+ "error": "invalid comment id",
})
return
@@ -1089,7 +1106,7 @@ func IssuePostAttachment(ctx *middleware.Context, params martini.Params) {
return
}
- a, err := models.CreateAttachment(issueId, commentId, header.Filename, out.Name())
+ a, err := models.CreateAttachment(issue.Id, commentId, header.Filename, out.Name())
if err != nil {
ctx.JSON(500, map[string]interface{}{
@@ -1121,16 +1138,29 @@ func IssueGetAttachment(ctx *middleware.Context, params martini.Params) {
return
}
+ log.Error("path=%s name=%s", attachment.Path, attachment.Name)
+
ctx.ServeFile(attachment.Path, attachment.Name)
}
func IssueDeleteAttachment(ctx *middleware.Context, params martini.Params) {
- issueId, _ := base.StrTo(params["index"]).Int64()
+ index, _ := base.StrTo(params["index"]).Int64()
- if issueId == 0 {
+ if index == 0 {
ctx.JSON(400, map[string]interface{}{
"ok": false,
- "error": "invalid issue id",
+ "error": "invalid issue index",
+ })
+
+ return
+ }
+
+ issue, err := models.GetIssueByIndex(ctx.Repo.Repository.Id, index)
+
+ if err != nil {
+ ctx.JSON(400, map[string]interface{}{
+ "ok": false,
+ "error": "invalid comment id",
})
return
@@ -1189,7 +1219,7 @@ func IssueDeleteAttachment(ctx *middleware.Context, params martini.Params) {
return
}
- if attachment.IssueId != issueId {
+ if attachment.IssueId != issue.Id {
ctx.JSON(400, map[string]interface{}{
"ok": false,
"error": "attachment not associated with the given issue",
diff --git a/templates/repo/issue/view.tmpl b/templates/repo/issue/view.tmpl
index a336205415..8c90f312c3 100644
--- a/templates/repo/issue/view.tmpl
+++ b/templates/repo/issue/view.tmpl
@@ -45,13 +45,19 @@
<div class="tab-pane issue-preview-content" id="issue-edit-preview">Loading...</div>
</div>
</div>
- </div>
- <div class="attachments">
- {{range .Attachments}}
- <a class="attachment" href="{{.IssueId}}/attachment/{{.Id}}">{{.Name}}</a>
- {{end}}
- </div>
+ </div>
</div>
+ {{with $attachments := .Issue.Attachments}}
+ {{if $attachments}}
+ <div class="attachments">
+ <span class="attachment-label label label-info">Attachments:</span>
+
+ {{range $attachments}}
+ <a class="attachment label label-default" href="{{.IssueId}}/attachment/{{.Id}}">{{.Name}}</a>
+ {{end}}
+ </div>
+ {{end}}
+ {{end}}
</div>
{{range .Comments}}
{{/* 0 = COMMENT, 1 = REOPEN, 2 = CLOSE, 3 = ISSUE, 4 = COMMIT, 5 = PULL */}}
@@ -68,11 +74,17 @@
<div class="panel-body markdown">
{{str2html .Content}}
</div>
+ {{with $attachments := .Attachments}}
+ {{if $attachments}}
<div class="attachments">
- {{range .Attachments}}
- <a class="attachment" href="{{.IssueId}}/attachment/{{.Id}}">{{.Name}}</a>
+ <span class="attachment-label label label-info">Attachments:</span>
+
+ {{range $attachments}}
+ <a class="attachment label label-default" href="{{.IssueId}}/attachment/{{.Id}}">{{.Name}}</a>
{{end}}
</div>
+ {{end}}
+ {{end}}
</div>
</div>
{{else if eq .Type 1}}