Show attachments in issues/comments and add preview for images
This commit is contained in:
parent
fa1db64ff0
commit
43e5de7f83
15
cmd/web.go
15
cmd/web.go
|
@ -238,14 +238,6 @@ func runWeb(*cli.Context) {
|
||||||
r.Post("/:index/label", repo.UpdateIssueLabel)
|
r.Post("/:index/label", repo.UpdateIssueLabel)
|
||||||
r.Post("/:index/milestone", repo.UpdateIssueMilestone)
|
r.Post("/:index/milestone", repo.UpdateIssueMilestone)
|
||||||
r.Post("/:index/assignee", repo.UpdateAssignee)
|
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/new", bindIgnErr(auth.CreateLabelForm{}), repo.NewLabel)
|
||||||
r.Post("/labels/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
|
r.Post("/labels/edit", bindIgnErr(auth.CreateLabelForm{}), repo.UpdateLabel)
|
||||||
r.Post("/labels/delete", repo.DeleteLabel)
|
r.Post("/labels/delete", repo.DeleteLabel)
|
||||||
|
@ -262,6 +254,13 @@ func runWeb(*cli.Context) {
|
||||||
r.Get("/releases/edit/:tagname", repo.EditRelease)
|
r.Get("/releases/edit/:tagname", repo.EditRelease)
|
||||||
}, reqSignIn, middleware.RepoAssignment(true))
|
}, 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) {
|
m.Group("/:username/:reponame", func(r martini.Router) {
|
||||||
r.Post("/releases/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost)
|
r.Post("/releases/new", bindIgnErr(auth.NewReleaseForm{}), repo.NewReleasePost)
|
||||||
r.Post("/releases/edit/:tagname", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost)
|
r.Post("/releases/edit/:tagname", bindIgnErr(auth.EditReleaseForm{}), repo.EditReleasePost)
|
||||||
|
|
|
@ -1794,4 +1794,29 @@ body {
|
||||||
color: #444;
|
color: #444;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
line-height: 30px;
|
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;
|
||||||
}
|
}
|
|
@ -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() {
|
(function() {
|
||||||
var $attached = $("#attached");
|
var $attached = $("#attached");
|
||||||
var $attachments = $("input[name=attachments]");
|
var $attachments = $("input[name=attachments]");
|
||||||
|
|
|
@ -709,6 +709,12 @@ func Comment(ctx *middleware.Context, params martini.Params) {
|
||||||
attachments := strings.Split(params["attachments"], ",")
|
attachments := strings.Split(params["attachments"], ",")
|
||||||
|
|
||||||
for _, a := range attachments {
|
for _, a := range attachments {
|
||||||
|
a = strings.Trim(a, " ")
|
||||||
|
|
||||||
|
if len(a) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
aId, err := base.StrTo(a).Int64()
|
aId, err := base.StrTo(a).Int64()
|
||||||
|
|
||||||
if err != nil {
|
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) {
|
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{}{
|
ctx.JSON(400, map[string]interface{}{
|
||||||
"ok": false,
|
"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
|
return
|
||||||
|
@ -1089,7 +1106,7 @@ func IssuePostAttachment(ctx *middleware.Context, params martini.Params) {
|
||||||
return
|
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 {
|
if err != nil {
|
||||||
ctx.JSON(500, map[string]interface{}{
|
ctx.JSON(500, map[string]interface{}{
|
||||||
|
@ -1121,16 +1138,29 @@ func IssueGetAttachment(ctx *middleware.Context, params martini.Params) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Error("path=%s name=%s", attachment.Path, attachment.Name)
|
||||||
|
|
||||||
ctx.ServeFile(attachment.Path, attachment.Name)
|
ctx.ServeFile(attachment.Path, attachment.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func IssueDeleteAttachment(ctx *middleware.Context, params martini.Params) {
|
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{}{
|
ctx.JSON(400, map[string]interface{}{
|
||||||
"ok": false,
|
"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
|
return
|
||||||
|
@ -1189,7 +1219,7 @@ func IssueDeleteAttachment(ctx *middleware.Context, params martini.Params) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if attachment.IssueId != issueId {
|
if attachment.IssueId != issue.Id {
|
||||||
ctx.JSON(400, map[string]interface{}{
|
ctx.JSON(400, map[string]interface{}{
|
||||||
"ok": false,
|
"ok": false,
|
||||||
"error": "attachment not associated with the given issue",
|
"error": "attachment not associated with the given issue",
|
||||||
|
|
|
@ -45,13 +45,19 @@
|
||||||
<div class="tab-pane issue-preview-content" id="issue-edit-preview">Loading...</div>
|
<div class="tab-pane issue-preview-content" id="issue-edit-preview">Loading...</div>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
</div>
|
||||||
{{range .Comments}}
|
{{range .Comments}}
|
||||||
{{/* 0 = COMMENT, 1 = REOPEN, 2 = CLOSE, 3 = ISSUE, 4 = COMMIT, 5 = PULL */}}
|
{{/* 0 = COMMENT, 1 = REOPEN, 2 = CLOSE, 3 = ISSUE, 4 = COMMIT, 5 = PULL */}}
|
||||||
|
@ -68,11 +74,17 @@
|
||||||
<div class="panel-body markdown">
|
<div class="panel-body markdown">
|
||||||
{{str2html .Content}}
|
{{str2html .Content}}
|
||||||
</div>
|
</div>
|
||||||
|
{{with $attachments := .Attachments}}
|
||||||
|
{{if $attachments}}
|
||||||
<div class="attachments">
|
<div class="attachments">
|
||||||
{{range .Attachments}}
|
<span class="attachment-label label label-info">Attachments:</span>
|
||||||
<a class="attachment" href="{{.IssueId}}/attachment/{{.Id}}">{{.Name}}</a>
|
|
||||||
|
{{range $attachments}}
|
||||||
|
<a class="attachment label label-default" href="{{.IssueId}}/attachment/{{.Id}}">{{.Name}}</a>
|
||||||
{{end}}
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
|
{{end}}
|
||||||
|
{{end}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{else if eq .Type 1}}
|
{{else if eq .Type 1}}
|
||||||
|
|
Loading…
Reference in New Issue