From eafa365453b6756272ced185f5d8060fb6bc5f07 Mon Sep 17 00:00:00 2001 From: Justin Date: Thu, 24 Jul 2014 23:19:21 +0200 Subject: Fix #313. Repair broken image extension detection regex. --- public/js/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'public/js/app.js') diff --git a/public/js/app.js b/public/js/app.js index 7ffcbd4a..01341d75 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -536,7 +536,7 @@ function initIssue() { var over = function() { var $this = $(this); - if ($this.text().match(/\.(png|jpg|jpeg|gif)$/i) == false) { + if ((/\.(png|jpg|jpeg|gif)$/i).test($this.text()) == false) { return; } -- cgit v1.2.3 From 8ccde45c5fdfe2993b59d13c38c79f661dee189e Mon Sep 17 00:00:00 2001 From: Andrew Patton Date: Thu, 24 Jul 2014 18:23:46 -0400 Subject: Fix #319 (user not-logged in error) --- public/js/app.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'public/js/app.js') diff --git a/public/js/app.js b/public/js/app.js index 7ffcbd4a..1b4fed7d 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -579,8 +579,11 @@ function initIssue() { var $attachedList = $("#attached-list"); var $addButton = $("#attachments-button"); - var fileInput = $("#attachments-input")[0]; - + var fileInput = document.getElementById("attachments-input"); + + if (fileInput === null) { + return; + } fileInput.addEventListener("change", function(event) { $attachedList.empty(); $attachedList.append("Attachments: "); -- cgit v1.2.3 From 4e2477a1a5ae59ff4cb34d58eab74297b4ea2d24 Mon Sep 17 00:00:00 2001 From: Justin Nuß Date: Fri, 25 Jul 2014 10:47:37 +0200 Subject: Fix #318. Switch to JS(ON) implementation for issue/comment creation. --- public/js/app.js | 79 +++++++++++++++++++++++++++++++-- routers/repo/issue.go | 96 ++++++++++++++++++++++++++-------------- templates/repo/issue/create.tmpl | 5 ++- templates/repo/issue/view.tmpl | 5 ++- 4 files changed, 147 insertions(+), 38 deletions(-) (limited to 'public/js/app.js') diff --git a/public/js/app.js b/public/js/app.js index 62482965..a88c8f6b 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -579,26 +579,97 @@ function initIssue() { var $attachedList = $("#attached-list"); var $addButton = $("#attachments-button"); + var files = []; + var fileInput = document.getElementById("attachments-input"); if (fileInput === null) { return; } - fileInput.addEventListener("change", function(event) { - $attachedList.empty(); - $attachedList.append("Attachments: "); + $attachedList.on("click", "span.attachment-remove", function(event) { + var $parent = $(this).parent(); + + files.splice($parent.data("index"), 1); + $parent.remove(); + }); + + var clickedButton = undefined; + + $("button,input[type=\"submit\"]", fileInput.form).on("click", function() { + clickedButton = this; + }); + + fileInput.form.addEventListener("submit", function(event) { + event.stopImmediatePropagation(); + event.preventDefault(); + + //var data = new FormData(this); + + // Internet Explorer ... -_- + var data = new FormData(); + + $.each($("[name]", this), function(i, e) { + if (e.name == "attachments" || e.type == "submit") { + return; + } + + data.append(e.name, $(e).val()); + }); + + data.append(clickedButton.name, $(clickedButton).val()); + + files.forEach(function(file) { + data.append("attachments", file); + }); + + var xhr = new XMLHttpRequest(); + + xhr.addEventListener("error", function() { + debugger; + }); + + xhr.addEventListener("load", function() { + if (xhr.response.ok === false) { + $("#submit-error").text(xhr.response.error); + return; + } + + window.location.href = xhr.response.data; + }); + + xhr.responseType = "json"; + + xhr.open("POST", this.action, true); + xhr.send(data); + + return false; + }); + + fileInput.addEventListener("change", function(event) { for (var index = 0; index < fileInput.files.length; index++) { var file = fileInput.files[index]; + if (files.indexOf(file) > -1) { + continue; + } + var $span = $(""); $span.addClass("label"); $span.addClass("label-default"); - $span.append(file.name.toLowerCase()); + $span.data("index", files.length); + + $span.append(file.name); + $span.append(" "); + $attachedList.append($span); + + files.push(file); } + + this.value = ""; }); $addButton.on("click", function() { diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 0f03cea5..edfa39b0 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -188,33 +188,45 @@ func CreateIssue(ctx *middleware.Context, params martini.Params) { } func CreateIssuePost(ctx *middleware.Context, params martini.Params, form auth.CreateIssueForm) { - ctx.Data["Title"] = "Create issue" - ctx.Data["IsRepoToolbarIssues"] = true - ctx.Data["IsRepoToolbarIssuesList"] = false - ctx.Data["AttachmentsEnabled"] = setting.AttachmentEnabled + send := func(status int, data interface{}, err error) { + log.Error("issue.Comment(?): %s", err) + + if err != nil { + ctx.JSON(status, map[string]interface{}{ + "ok": false, + "status": status, + "error": err.Error(), + }) + } else { + ctx.JSON(status, map[string]interface{}{ + "ok": true, + "status": status, + "data": data, + }) + } + } var err error // Get all milestones. - ctx.Data["OpenMilestones"], err = models.GetMilestones(ctx.Repo.Repository.Id, false) + _, err = models.GetMilestones(ctx.Repo.Repository.Id, false) if err != nil { - ctx.Handle(500, "issue.ViewIssue(GetMilestones.1): %v", err) + send(500, nil, err) return } - ctx.Data["ClosedMilestones"], err = models.GetMilestones(ctx.Repo.Repository.Id, true) + _, err = models.GetMilestones(ctx.Repo.Repository.Id, true) if err != nil { - ctx.Handle(500, "issue.ViewIssue(GetMilestones.2): %v", err) + send(500, nil, err) return } - us, err := models.GetCollaborators(strings.TrimPrefix(ctx.Repo.RepoLink, "/")) + _, err = models.GetCollaborators(strings.TrimPrefix(ctx.Repo.RepoLink, "/")) if err != nil { - ctx.Handle(500, "issue.CreateIssue(GetCollaborators)", err) + send(500, nil, err) return } - ctx.Data["Collaborators"] = us if ctx.HasError() { - ctx.HTML(200, ISSUE_CREATE) + send(400, nil, errors.New(ctx.Flash.ErrorMsg)) return } @@ -233,11 +245,11 @@ func CreateIssuePost(ctx *middleware.Context, params martini.Params, form auth.C Content: form.Content, } if err := models.NewIssue(issue); err != nil { - ctx.Handle(500, "issue.CreateIssue(NewIssue)", err) + send(500, nil, err) return } else if err := models.NewIssueUserPairs(issue.RepoId, issue.Id, ctx.Repo.Owner.Id, ctx.User.Id, form.AssigneeId, ctx.Repo.Repository.Name); err != nil { - ctx.Handle(500, "issue.CreateIssue(NewIssueUserPairs)", err) + send(500, nil, err) return } @@ -253,7 +265,7 @@ func CreateIssuePost(ctx *middleware.Context, params martini.Params, form auth.C } if err := models.UpdateMentions(ms, issue.Id); err != nil { - ctx.Handle(500, "issue.CreateIssue(UpdateMentions)", err) + send(500, nil, err) return } } @@ -272,7 +284,7 @@ func CreateIssuePost(ctx *middleware.Context, params martini.Params, form auth.C } // Notify watchers. if err := models.NotifyWatchers(act); err != nil { - ctx.Handle(500, "issue.CreateIssue(NotifyWatchers)", err) + send(500, nil, err) return } @@ -280,7 +292,7 @@ func CreateIssuePost(ctx *middleware.Context, params martini.Params, form auth.C if setting.Service.EnableNotifyMail { tos, err := mailer.SendIssueNotifyMail(ctx.User, ctx.Repo.Owner, ctx.Repo.Repository, issue) if err != nil { - ctx.Handle(500, "issue.CreateIssue(SendIssueNotifyMail)", err) + send(500, nil, err) return } @@ -295,13 +307,13 @@ func CreateIssuePost(ctx *middleware.Context, params martini.Params, form auth.C } if err = mailer.SendIssueMentionMail(ctx.Render, ctx.User, ctx.Repo.Owner, ctx.Repo.Repository, issue, models.GetUserEmailsByNames(newTos)); err != nil { - ctx.Handle(500, "issue.CreateIssue(SendIssueMentionMail)", err) + send(500, nil, err) return } } log.Trace("%d Issue created: %d", ctx.Repo.Repository.Id, issue.Id) - ctx.Redirect(fmt.Sprintf("/%s/%s/issues/%d", params["username"], params["reponame"], issue.Index)) + send(200, fmt.Sprintf("/%s/%s/issues/%d", params["username"], params["reponame"], issue.Index), nil) } func checkLabels(labels, allLabels []*models.Label) { @@ -698,19 +710,38 @@ func uploadFiles(ctx *middleware.Context, issueId, commentId int64) { } func Comment(ctx *middleware.Context, params martini.Params) { + send := func(status int, data interface{}, err error) { + log.Error("issue.Comment(?): %s", err) + + if err != nil { + ctx.JSON(status, map[string]interface{}{ + "ok": false, + "status": status, + "error": err.Error(), + }) + } else { + ctx.JSON(status, map[string]interface{}{ + "ok": true, + "status": status, + "data": data, + }) + } + } + index, err := base.StrTo(ctx.Query("issueIndex")).Int64() if err != nil { - ctx.Handle(404, "issue.Comment(get index)", err) + send(404, nil, err) return } issue, err := models.GetIssueByIndex(ctx.Repo.Repository.Id, index) if err != nil { if err == models.ErrIssueNotExist { - ctx.Handle(404, "issue.Comment", err) + send(404, nil, err) } else { - ctx.Handle(200, "issue.Comment(get issue)", err) + send(200, nil, err) } + return } @@ -724,17 +755,17 @@ func Comment(ctx *middleware.Context, params martini.Params) { (strings.Contains(newStatus, "Close") && !issue.IsClosed) { issue.IsClosed = !issue.IsClosed if err = models.UpdateIssue(issue); err != nil { - ctx.Handle(500, "issue.Comment(UpdateIssue)", err) + send(500, nil, err) return } else if err = models.UpdateIssueUserPairsByStatus(issue.Id, issue.IsClosed); err != nil { - ctx.Handle(500, "issue.Comment(UpdateIssueUserPairsByStatus)", err) + send(500, nil, err) return } // Change open/closed issue counter for the associated milestone if issue.MilestoneId > 0 { if err = models.ChangeMilestoneIssueStats(issue); err != nil { - ctx.Handle(500, "issue.Comment(ChangeMilestoneIssueStats)", err) + send(500, nil, err) } } @@ -744,7 +775,7 @@ func Comment(ctx *middleware.Context, params martini.Params) { } if _, err = models.CreateComment(ctx.User.Id, ctx.Repo.Repository.Id, issue.Id, 0, 0, cmtType, "", nil); err != nil { - ctx.Handle(200, "issue.Comment(create status change comment)", err) + send(200, nil, err) return } log.Trace("%s Issue(%d) status changed: %v", ctx.Req.RequestURI, issue.Id, !issue.IsClosed) @@ -760,7 +791,7 @@ func Comment(ctx *middleware.Context, params martini.Params) { switch params["action"] { case "new": if comment, err = models.CreateComment(ctx.User.Id, ctx.Repo.Repository.Id, issue.Id, 0, 0, models.COMMENT, content, nil); err != nil { - ctx.Handle(500, "issue.Comment(create comment)", err) + send(500, nil, err) return } @@ -772,7 +803,7 @@ func Comment(ctx *middleware.Context, params martini.Params) { } if err := models.UpdateMentions(ms, issue.Id); err != nil { - ctx.Handle(500, "issue.CreateIssue(UpdateMentions)", err) + send(500, nil, err) return } } @@ -800,7 +831,7 @@ func Comment(ctx *middleware.Context, params martini.Params) { RepoName: ctx.Repo.Repository.LowerName, } if err = models.NotifyWatchers(act); err != nil { - ctx.Handle(500, "issue.CreateIssue(NotifyWatchers)", err) + send(500, nil, err) return } @@ -809,7 +840,7 @@ func Comment(ctx *middleware.Context, params martini.Params) { issue.Content = content tos, err := mailer.SendIssueNotifyMail(ctx.User, ctx.Repo.Owner, ctx.Repo.Repository, issue) if err != nil { - ctx.Handle(500, "issue.Comment(SendIssueNotifyMail)", err) + send(500, nil, err) return } @@ -824,12 +855,13 @@ func Comment(ctx *middleware.Context, params martini.Params) { } if err = mailer.SendIssueMentionMail(ctx.Render, ctx.User, ctx.Repo.Owner, ctx.Repo.Repository, issue, models.GetUserEmailsByNames(newTos)); err != nil { - ctx.Handle(500, "issue.Comment(SendIssueMentionMail)", err) + send(500, nil, err) return } } - ctx.Redirect(fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, index)) + log.Error("url: %#v", fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, index)) + send(200, fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, index), nil) } func NewLabel(ctx *middleware.Context, form auth.CreateLabelForm) { diff --git a/templates/repo/issue/create.tmpl b/templates/repo/issue/create.tmpl index 77058417..ad86d4ea 100644 --- a/templates/repo/issue/create.tmpl +++ b/templates/repo/issue/create.tmpl @@ -95,6 +95,7 @@
+
@@ -103,7 +104,9 @@
{{if .AttachmentsEnabled}}
-
+
+ Attachments: +
{{end}}
diff --git a/templates/repo/issue/view.tmpl b/templates/repo/issue/view.tmpl index 247931c4..b5d72281 100644 --- a/templates/repo/issue/view.tmpl +++ b/templates/repo/issue/view.tmpl @@ -134,6 +134,7 @@
+
@@ -143,7 +144,9 @@
{{if .AttachmentsEnabled}}
-
+
+ Attachments: +
{{end}}
-- cgit v1.2.3 From 12fb42de5a5b07ed8dffe91d9536615bbadeedea Mon Sep 17 00:00:00 2001 From: Justin Nuß Date: Fri, 25 Jul 2014 11:13:42 +0200 Subject: Fix IE bug and show errors. --- public/css/gogs.css | 7 +++++++ public/js/app.js | 36 ++++++++++++++++++++++++++++++------ routers/repo/issue.go | 9 ++++----- templates/repo/issue/create.tmpl | 2 +- templates/repo/issue/view.tmpl | 2 +- 5 files changed, 43 insertions(+), 13 deletions(-) (limited to 'public/js/app.js') diff --git a/public/css/gogs.css b/public/css/gogs.css index cc48f211..361475bd 100755 --- a/public/css/gogs.css +++ b/public/css/gogs.css @@ -1836,4 +1836,11 @@ body { #issue-create-form #attached { margin-bottom: 0; +} + +#submit-error { + display: none; + padding: 10px 15px 15px 15px; + font-weight: bold; + text-align: center; } \ No newline at end of file diff --git a/public/js/app.js b/public/js/app.js index a88c8f6b..b0dff0ef 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -568,7 +568,7 @@ function initIssue() { }; var out = function() { - $hoverElement.hide(); + //$hoverElement.hide(); }; $(".issue-main .attachments .attachment").hover(over, out); @@ -598,6 +598,13 @@ function initIssue() { $("button,input[type=\"submit\"]", fileInput.form).on("click", function() { clickedButton = this; + + var $button = $(this); + + $button.removeClass("btn-success"); + $button.addClass("btn-warning"); + + $button.text("Submiting..."); }); fileInput.form.addEventListener("submit", function(event) { @@ -630,16 +637,33 @@ function initIssue() { }); xhr.addEventListener("load", function() { - if (xhr.response.ok === false) { - $("#submit-error").text(xhr.response.error); + var response = xhr.response; + + if (typeof response == "string") { + try { + response = JSON.parse(response); + } catch (err) { + response = { ok: false, error: "Could not parse JSON" }; + } + } + + if (response.ok === false) { + $("#submit-error").text(response.error); + $("#submit-error").show(); + + var $button = $(clickedButton); + + $button.removeClass("btn-warning"); + $button.addClass("btn-danger"); + + $button.text("An error encoured!") + return; } - window.location.href = xhr.response.data; + window.location.href = response.data; }); - xhr.responseType = "json"; - xhr.open("POST", this.action, true); xhr.send(data); diff --git a/routers/repo/issue.go b/routers/repo/issue.go index edfa39b0..4465a399 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -189,9 +189,9 @@ func CreateIssue(ctx *middleware.Context, params martini.Params) { func CreateIssuePost(ctx *middleware.Context, params martini.Params, form auth.CreateIssueForm) { send := func(status int, data interface{}, err error) { - log.Error("issue.Comment(?): %s", err) - if err != nil { + log.Error("issue.CreateIssuePost(?): %s", err.Error()) + ctx.JSON(status, map[string]interface{}{ "ok": false, "status": status, @@ -711,9 +711,9 @@ func uploadFiles(ctx *middleware.Context, issueId, commentId int64) { func Comment(ctx *middleware.Context, params martini.Params) { send := func(status int, data interface{}, err error) { - log.Error("issue.Comment(?): %s", err) - if err != nil { + log.Error("issue.Comment(?): %s", err.Error()) + ctx.JSON(status, map[string]interface{}{ "ok": false, "status": status, @@ -860,7 +860,6 @@ func Comment(ctx *middleware.Context, params martini.Params) { } } - log.Error("url: %#v", fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, index)) send(200, fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, index), nil) } diff --git a/templates/repo/issue/create.tmpl b/templates/repo/issue/create.tmpl index ad86d4ea..c0188842 100644 --- a/templates/repo/issue/create.tmpl +++ b/templates/repo/issue/create.tmpl @@ -95,7 +95,7 @@
-
+
diff --git a/templates/repo/issue/view.tmpl b/templates/repo/issue/view.tmpl index b5d72281..aec50ca6 100644 --- a/templates/repo/issue/view.tmpl +++ b/templates/repo/issue/view.tmpl @@ -134,7 +134,7 @@
-
+
-- cgit v1.2.3 From f0da8a68c2c409572902275888fec26689c2b0dd Mon Sep 17 00:00:00 2001 From: Justin Nuß Date: Fri, 25 Jul 2014 15:47:42 +0200 Subject: Remove debug comment. --- public/js/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'public/js/app.js') diff --git a/public/js/app.js b/public/js/app.js index b0dff0ef..d7208119 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -568,7 +568,7 @@ function initIssue() { }; var out = function() { - //$hoverElement.hide(); + $hoverElement.hide(); }; $(".issue-main .attachments .attachment").hover(over, out); -- cgit v1.2.3 From a03a1e87e9f8e8cf98670aa1a64dd91da8e04bd3 Mon Sep 17 00:00:00 2001 From: Justin Nuß Date: Fri, 25 Jul 2014 20:15:58 +0200 Subject: Remove 'None yet' message when adding first label to issue. --- public/js/app.js | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'public/js/app.js') diff --git a/public/js/app.js b/public/js/app.js index d7208119..6f4676f6 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -926,11 +926,17 @@ function initIssue() { $(item).addClass("no-checked"); $("#label-" + id, $labels).remove(); + + if ($labels.children(".label-item").length == 0) { + $labels.append("

None yet

"); + } } else { $(item).prepend(''); $(item).removeClass("no-checked"); $(item).addClass("checked"); + + $("p:not([class])", $labels).remove(); var $l = $("

"); var c = $("span.color", item).css("background-color"); -- cgit v1.2.3 From 09cb8c67cb59a331490fa28cc3b608bfd99c3aad Mon Sep 17 00:00:00 2001 From: Justin Nuß Date: Fri, 25 Jul 2014 20:56:17 +0200 Subject: Save comment/issue drafts in sessionStorage. --- public/js/app.js | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) (limited to 'public/js/app.js') diff --git a/public/js/app.js b/public/js/app.js index d7208119..ef54aaf8 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -520,6 +520,50 @@ function initIssue() { }); }()); + // store unsend text in session storage. + (function() { + var $textArea = $("#issue-content,#issue-reply-content"); + var current = ""; + + if ($textArea == null || !('sessionStorage' in window)) { + return; + } + + var path = location.pathname.split("/"); + var key = "issue-" + path[1] + "-" + path[2] + "-"; + + if (/\/issues\/\d+$/.test(location.pathname)) { + key = key + path[4]; + } else { + key = key + "new"; + } + + if ($textArea.val() !== undefined && $textArea.val() !== "") { + sessionStorage.setItem(key, $textArea.val()); + } else { + $textArea.val(sessionStorage.getItem(key) || ""); + + if ($textArea.attr("id") == "issue-reply-content") { + var $closeBtn = $('#issue-close-btn'); + var $openBtn = $('#issue-open-btn'); + + if ($textArea.val().length) { + $closeBtn.val($closeBtn.data("text")); + $openBtn.val($openBtn.data("text")); + } else { + $closeBtn.val($closeBtn.data("origin")); + $openBtn.val($openBtn.data("origin")); + } + } + } + + $textArea.on("keyup", function() { + if ($textArea.val() !== current) { + sessionStorage.setItem(key, current = $textArea.val()); + } + }); + }()); + // Preview for images. (function() { var $hoverElement = $("
"); @@ -659,8 +703,22 @@ function initIssue() { $button.text("An error encoured!") return; - } + } + + if (!('sessionStorage' in window)) { + return; + } + + var path = location.pathname.split("/"); + var key = "issue-" + path[1] + "-" + path[2] + "-"; + + if (/\/issues\/\d+$/.test(location.pathname)) { + key = key + path[4]; + } else { + key = key + "new"; + } + sessionStorage.removeItem(key); window.location.href = response.data; }); -- cgit v1.2.3