From 92987951861f877857b4b5ab5bfb57d19e3b6dc7 Mon Sep 17 00:00:00 2001 From: Konrad Langenberg Date: Sat, 26 Aug 2017 18:58:35 +0200 Subject: [PATCH 001/276] Init: * Added models * Added UI * Added Routes Signed-off-by: kolaente --- models/issue_dependency_add.go | 79 +++++++++++++++++++ routers/repo/issue_dependency_add.go | 38 +++++++++ routers/routes/routes.go | 1 + .../repo/issue/view_content/sidebar.tmpl | 37 +++++++++ 4 files changed, 155 insertions(+) create mode 100644 models/issue_dependency_add.go create mode 100644 routers/repo/issue_dependency_add.go diff --git a/models/issue_dependency_add.go b/models/issue_dependency_add.go new file mode 100644 index 000000000000..04db222eee85 --- /dev/null +++ b/models/issue_dependency_add.go @@ -0,0 +1,79 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package models + +import ( + "time" +) + +// IssueDependency is connection request for receiving issue notification. +type IssueDependency struct { + ID int64 `xorm:"pk autoincr"` + UserID int64 `xorm:"UNIQUE(watch) NOT NULL"` + IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"` + DependencyID int64 `xorm:"UNIQUE(watch) NOT NULL"` + Created time.Time `xorm:"-"` + CreatedUnix int64 `xorm:"NOT NULL"` + Updated time.Time `xorm:"-"` + UpdatedUnix int64 `xorm:"NOT NULL"` +} + +// BeforeInsert is invoked from XORM before inserting an object of this type. +func (iw *IssueDependency) BeforeInsert() { + var ( + t = time.Now() + u = t.Unix() + ) + iw.Created = t + iw.CreatedUnix = u + iw.Updated = t + iw.UpdatedUnix = u +} + +// BeforeUpdate is invoked from XORM before updating an object of this type. +func (iw *IssueDependency) BeforeUpdate() { + var ( + t = time.Now() + u = t.Unix() + ) + iw.Updated = t + iw.UpdatedUnix = u +} + +// CreateOrUpdateIssueDependency sets or updates a dependency for an issue +func CreateOrUpdateIssueDependency(userID, issueID int64, dep int64) error { + id, exists, err := getIssueWatch(x, userID, issueID) + if err != nil { + return err + } + + if !exists { + id = &IssueWatch{ + UserID: userID, + IssueID: issueID, + IsWatching: isWatching, + } + + if _, err := x.Insert(iw); err != nil { + return err + } + } else { + iw.IsWatching = isWatching + + if _, err := x.Id(iw.ID).Cols("is_watching", "updated_unix").Update(iw); err != nil { + return err + } + } + return nil +} + +// +func getIssueDep(e Engine, issueID int64) (Dependencies []*IssueDependency, err error) { + id = new(IssueDependency) + err = e. + Where("issue_id = ?", issueID). + Find(&Dependencies) + return +} diff --git a/routers/repo/issue_dependency_add.go b/routers/repo/issue_dependency_add.go new file mode 100644 index 000000000000..384d04aca64b --- /dev/null +++ b/routers/repo/issue_dependency_add.go @@ -0,0 +1,38 @@ +// Copyright 2017 The Gitea Authors. All rights reserved. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package repo + +import ( + "fmt" + "net/http" + "strconv" + + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" +) + +// IssueWatch sets issue watching +func AddDependency(c *context.Context) { + dep, err := strconv.ParseInt(c.Req.PostForm.Get("newDependency"), 10, 64) + if err != nil { + c.Handle(http.StatusInternalServerError, "issue ID is not int", err) + return + } + + issueIndex := c.ParamsInt64("index") + issue, err := models.GetIssueByIndex(c.Repo.Repository.ID, issueIndex) + if err != nil { + c.Handle(http.StatusInternalServerError, "GetIssueByIndex", err) + return + } + + if err := models.CreateOrUpdateIssueDependency(c.User.ID, issue.ID, dep); err != nil { + c.Handle(http.StatusInternalServerError, "CreateOrUpdateIssueWatch", err) + return + } + + url := fmt.Sprintf("%s/issues/%d", c.Repo.RepoLink, issueIndex) + c.Redirect(url, http.StatusSeeOther) +} diff --git a/routers/routes/routes.go b/routers/routes/routes.go index a7a759538f16..8bd5221ba36e 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -467,6 +467,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/content", repo.UpdateIssueContent) m.Post("/watch", repo.IssueWatch) m.Combo("/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment) + m.Post("/addDependency", repo.AddDependency) }) m.Post("/labels", repo.UpdateIssueLabel, reqRepoWriter) diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index cfb6f183b4bf..607446645165 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -121,5 +121,42 @@ {{end}} + +
+ +
+ Dependencies +
+ This issue currently doesn't have any dependencies. +
+
+ +
+
+ + + + + From 0a4925fb1738b711337af85d6dedde090a016714 Mon Sep 17 00:00:00 2001 From: Konrad Langenberg Date: Sat, 26 Aug 2017 22:37:52 +0200 Subject: [PATCH 002/276] Added create new issue method Signed-off-by: Konrad --- models/issue_dependency_add.go | 40 ++++++++++--------- public/js/index.js | 13 +++++- routers/repo/issue_dependency_add.go | 5 ++- routers/routes/routes.go | 2 +- .../repo/issue/view_content/sidebar.tmpl | 1 + 5 files changed, 38 insertions(+), 23 deletions(-) diff --git a/models/issue_dependency_add.go b/models/issue_dependency_add.go index 04db222eee85..5200d57b5d47 100644 --- a/models/issue_dependency_add.go +++ b/models/issue_dependency_add.go @@ -6,6 +6,7 @@ package models import ( "time" + "fmt" ) // IssueDependency is connection request for receiving issue notification. @@ -13,7 +14,7 @@ type IssueDependency struct { ID int64 `xorm:"pk autoincr"` UserID int64 `xorm:"UNIQUE(watch) NOT NULL"` IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"` - DependencyID int64 `xorm:"UNIQUE(watch) NOT NULL"` + DependencyID int64 `xorm:"UNIQUE(watch) NOT NULL"` Created time.Time `xorm:"-"` CreatedUnix int64 `xorm:"NOT NULL"` Updated time.Time `xorm:"-"` @@ -43,37 +44,38 @@ func (iw *IssueDependency) BeforeUpdate() { } // CreateOrUpdateIssueDependency sets or updates a dependency for an issue -func CreateOrUpdateIssueDependency(userID, issueID int64, dep int64) error { - id, exists, err := getIssueWatch(x, userID, issueID) +func CreateOrUpdateIssueDependency(userID, issueID int64, depID int64) error { + err := x.Sync(new(IssueDependency)) + if err != nil { + return err + } + + exists, err := issueDepExists(x, issueID, depID) if err != nil { return err } if !exists { - id = &IssueWatch{ - UserID: userID, - IssueID: issueID, - IsWatching: isWatching, - } + newId := new(IssueDependency) + newId.UserID = userID + newId.IssueID = issueID + newId.DependencyID = depID - if _, err := x.Insert(iw); err != nil { + if _, err := x.Insert(newId); err != nil { return err } } else { - iw.IsWatching = isWatching - - if _, err := x.Id(iw.ID).Cols("is_watching", "updated_unix").Update(iw); err != nil { - return err - } + fmt.Println("Dependency exists") + // TODO: Should display a message on issue page } return nil } // -func getIssueDep(e Engine, issueID int64) (Dependencies []*IssueDependency, err error) { - id = new(IssueDependency) - err = e. - Where("issue_id = ?", issueID). - Find(&Dependencies) +func issueDepExists(e Engine, issueID int64, depID int64) (exists bool, err error) { + var Dependencies = IssueDependency{IssueID: issueID, DependencyID: depID} + + //err = e.Where("issue_id = ?", issueID).Where("dependency_id = ?", depID).Find(&Dependencies) + exists, err = e.Get(&Dependencies) return } diff --git a/public/js/index.js b/public/js/index.js index d79b94b92c7b..4d94354b1164 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -1474,7 +1474,7 @@ $(document).ready(function () { var $this = $(this); var filter = ""; if ($this.attr("id")) { - filter += "#"+$this.attr("id") + filter += "#"+$this.attr("id") } $('.delete.modal'+filter).modal({ closable: false, @@ -1715,3 +1715,14 @@ function initDashboardSearch() { } }); } + +function showAddDependencyModal() { + $('.tiny.modal') + .modal({ + duration: 200, + onApprove: function() { + $('#addDependencyForm').submit(); + } + }).modal('show') + ; +} diff --git a/routers/repo/issue_dependency_add.go b/routers/repo/issue_dependency_add.go index 384d04aca64b..3ebf20285d22 100644 --- a/routers/repo/issue_dependency_add.go +++ b/routers/repo/issue_dependency_add.go @@ -17,7 +17,7 @@ import ( func AddDependency(c *context.Context) { dep, err := strconv.ParseInt(c.Req.PostForm.Get("newDependency"), 10, 64) if err != nil { - c.Handle(http.StatusInternalServerError, "issue ID is not int", err) + c.Handle(http.StatusBadRequest, "issue ID is not int", err) return } @@ -29,7 +29,8 @@ func AddDependency(c *context.Context) { } if err := models.CreateOrUpdateIssueDependency(c.User.ID, issue.ID, dep); err != nil { - c.Handle(http.StatusInternalServerError, "CreateOrUpdateIssueWatch", err) + c.Handle(http.StatusInternalServerError, "CreateOrUpdateIssueDependency", err) + fmt.Println("updateerr") return } diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 8bd5221ba36e..77cf7ff936cf 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -466,8 +466,8 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/title", repo.UpdateIssueTitle) m.Post("/content", repo.UpdateIssueContent) m.Post("/watch", repo.IssueWatch) - m.Combo("/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment) m.Post("/addDependency", repo.AddDependency) + m.Combo("/comments").Post(bindIgnErr(auth.CreateCommentForm{}), repo.NewComment) }) m.Post("/labels", repo.UpdateIssueLabel, reqRepoWriter) diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index 607446645165..d01ee97c91be 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -145,6 +145,7 @@
+ {{$.CsrfTokenHtml}}
From cf7e99fc4c398ec322c08ddf269b72bb177a0a0d Mon Sep 17 00:00:00 2001 From: Konrad Langenberg Date: Sun, 27 Aug 2017 20:23:16 +0200 Subject: [PATCH 003/276] Added basic functionality: * Add new dependecy * Show dependencies Signed-off-by: Konrad --- conf/app.ini | 2 +- models/issue_comment.go | 2 + models/issue_dependency_add.go | 45 ++++++++++----- models/repo.go | 50 +++++++++++++++++ options/locale/locale_en-US.ini | 7 +++ routers/repo/issue.go | 4 ++ routers/repo/issue_dependency_add.go | 8 ++- .../repo/issue/view_content/comments.tmpl | 10 ++++ .../repo/issue/view_content/sidebar.tmpl | 56 ++++++++++++++++--- 9 files changed, 159 insertions(+), 25 deletions(-) diff --git a/conf/app.ini b/conf/app.ini index e704067b3633..a73390a5a5fd 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -379,7 +379,7 @@ MODE = console ; Buffer length of channel, keep it as it is if you don't know what it is. BUFFER_LEN = 10000 ; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace" -LEVEL = Trace +LEVEL = Debug ; For "console" mode only [log.console] diff --git a/models/issue_comment.go b/models/issue_comment.go index 753e79b3d358..ea2210c2e3b4 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -52,6 +52,8 @@ const ( CommentTypeChangeTitle // Delete Branch CommentTypeDeleteBranch + // Dependency added + CommentTypeAddedDependency ) // CommentTag defines comment tag type diff --git a/models/issue_dependency_add.go b/models/issue_dependency_add.go index 5200d57b5d47..702a0a795916 100644 --- a/models/issue_dependency_add.go +++ b/models/issue_dependency_add.go @@ -6,7 +6,6 @@ package models import ( "time" - "fmt" ) // IssueDependency is connection request for receiving issue notification. @@ -43,18 +42,20 @@ func (iw *IssueDependency) BeforeUpdate() { iw.UpdatedUnix = u } -// CreateOrUpdateIssueDependency sets or updates a dependency for an issue -func CreateOrUpdateIssueDependency(userID, issueID int64, depID int64) error { - err := x.Sync(new(IssueDependency)) +// CreateOrUpdateIssueDependency creates a new dependency for an issue +func CreateOrUpdateIssueDependency(userID, issueID int64, depID int64) (err error, exists bool) { + err = x.Sync(new(IssueDependency)) if err != nil { - return err + return err, exists } - exists, err := issueDepExists(x, issueID, depID) + // Check if it aleready exists + exists, err = issueDepExists(x, issueID, depID) if err != nil { - return err + return err, exists } + // If it not exists, create it, otherwise show an error message if !exists { newId := new(IssueDependency) newId.UserID = userID @@ -62,20 +63,36 @@ func CreateOrUpdateIssueDependency(userID, issueID int64, depID int64) error { newId.DependencyID = depID if _, err := x.Insert(newId); err != nil { - return err + return err, exists + } + + // Add comment referencing to the stopwatch + comment := &Comment{ + IssueID: issueID, + PosterID: userID, + Type: CommentTypeAddedDependency, + } + + if _, err := x.Insert(comment); err != nil { + return err, exists } - } else { - fmt.Println("Dependency exists") - // TODO: Should display a message on issue page } - return nil + return nil, exists } -// +// Check if the dependency already exists func issueDepExists(e Engine, issueID int64, depID int64) (exists bool, err error) { var Dependencies = IssueDependency{IssueID: issueID, DependencyID: depID} - //err = e.Where("issue_id = ?", issueID).Where("dependency_id = ?", depID).Find(&Dependencies) exists, err = e.Get(&Dependencies) + + // Check for dependencies the other way around + // Otherwise two issues could block each other which would result in none of them could be closed. + if !exists { + Dependencies.IssueID = depID + Dependencies.DependencyID = issueID + exists, err = e.Get(&Dependencies) + } + return } diff --git a/models/repo.go b/models/repo.go index 60c89836c01b..b89201877f9d 100644 --- a/models/repo.go +++ b/models/repo.go @@ -666,6 +666,40 @@ func (repo *Repository) CanEnableEditor() bool { return !repo.IsMirror } +func (repo *Repository) BlockedByDependencies(issueID int64) (_ []*Issue, err error) { + + issueDeps, err := repo.getBlockedByDependencies(x, issueID) + var issueDepsFull = make([]*Issue, 0) + + for _, issueDep := range issueDeps{ + issueDetails, _ := getIssueByID(x, issueDep.DependencyID) + issueDepsFull = append(issueDepsFull, issueDetails) + } + + if err != nil { + return + } + + return issueDepsFull, nil +} + +func (repo *Repository) BlockingDependencies(issueID int64) (_ []*Issue, err error) { + + issueDeps, err := repo.getBlockingDependencies(x, issueID) + var issueDepsFull = make([]*Issue, 0) + + for _, issueDep := range issueDeps{ + issueDetails, _ := getIssueByID(x, issueDep.IssueID) + issueDepsFull = append(issueDepsFull, issueDetails) + } + + if err != nil { + return + } + + return issueDepsFull, nil +} + // NextIssueIndex returns the next issue index // FIXME: should have a mutex to prevent producing same index for two issues that are created // closely enough. @@ -2367,3 +2401,19 @@ func (repo *Repository) CreateNewBranch(doer *User, oldBranchName, branchName st return nil } + +// Get Blocked By Dependencies, aka all issues this issue is blocked by. +func (repo *Repository) getBlockedByDependencies(e Engine, issueID int64) (_ []IssueDependency, err error) { + var dependencies []IssueDependency + err = e.Where("issue_id = ?", issueID).Find(&dependencies) // + + return dependencies, err +} + +// Get Blocking Dependencies, aka all issues this issue blocks. +func (repo *Repository) getBlockingDependencies(e Engine, issueID int64) (_ []IssueDependency, err error) { + var dependencies []IssueDependency + err = e.Where("dependency_id = ?", issueID).Find(&dependencies) + + return dependencies, err +} diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 7fee0c2a994d..8bdb9227c3ac 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -693,6 +693,13 @@ issues.attachment.open_tab = `Click to see "%s" in a new tab` issues.attachment.download = `Click to download "%s"` issues.subscribe = Subscribe issues.unsubscribe = Unsubscribe +issues.dependency.title = Dependencies +issues.dependency.no_dependencies = This issue currently doesn't have any dependencies. +issues.dependency.add = Add +issues.dependency.cancel = Cancel +issues.dependency.add_header = Add New Dependency +issues.dependency.issue_number = Issuenumber +issues.dependency.added_dependency = `%[2]s added a new dependency %[3]s` pulls.desc = Pulls management your code review and merge requests pulls.new = New Pull Request diff --git a/routers/repo/issue.go b/routers/repo/issue.go index e4ed10d98068..4e15deb12a9f 100644 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -665,6 +665,10 @@ func ViewIssue(ctx *context.Context) { ctx.Data["IsPullBranchDeletable"] = canDelete && pull.HeadRepo != nil && git.IsBranchExist(pull.HeadRepo.RepoPath(), pull.HeadBranch) } + // Get Dependencies + ctx.Data["BlockedByDependencies"], err = repo.BlockedByDependencies(issue.ID) + ctx.Data["BlockingDependencies"], err = repo.BlockingDependencies(issue.ID) + ctx.Data["Participants"] = participants ctx.Data["NumParticipants"] = len(participants) ctx.Data["Issue"] = issue diff --git a/routers/repo/issue_dependency_add.go b/routers/repo/issue_dependency_add.go index 3ebf20285d22..03c4b3db4623 100644 --- a/routers/repo/issue_dependency_add.go +++ b/routers/repo/issue_dependency_add.go @@ -28,12 +28,16 @@ func AddDependency(c *context.Context) { return } - if err := models.CreateOrUpdateIssueDependency(c.User.ID, issue.ID, dep); err != nil { + err, exists := models.CreateOrUpdateIssueDependency(c.User.ID, issue.ID, dep); + if err != nil { c.Handle(http.StatusInternalServerError, "CreateOrUpdateIssueDependency", err) - fmt.Println("updateerr") return } + if exists { + c.Flash.Error("Dependency already exists!") + } + url := fmt.Sprintf("%s/issues/%d", c.Repo.RepoLink, issueIndex) c.Redirect(url, http.StatusSeeOther) } diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index c1b4e7f59960..a4318766e8b2 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -140,5 +140,15 @@ {{.Poster.Name}} {{$.i18n.Tr "repo.issues.delete_branch_at" .CommitSHA $createdStr | Safe}} + {{else if eq .Type 12}} +
+ +
+ + + + + {{$.i18n.Tr "repo.issues.dependency.added_dependency" .Poster.HomeLink .Poster.Name $createdStr | Safe}} + {{end}} {{end}} diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index d01ee97c91be..99a90013d0ba 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -125,13 +125,53 @@
- Dependencies -
- This issue currently doesn't have any dependencies. + {{.i18n.Tr "repo.issues.dependency.title"}} +
+ This issue is blocked by: +
+ {{range .BlockedByDependencies}} +
+
+ {{if .IsClosed}} +
+ +
+ {{else}} +
+ +
+ {{end}} +
+
#{{.Index}}
+ {{.Title}} +
+ {{end}} +
+ +
+ This issue blocks the following issues: + {{range .BlockingDependencies}} +
+
+ {{if .IsClosed}} +
+ +
+ {{else}} +
+ +
+ {{end}} +
+
#{{.Index}}
+ {{.Title}} +
+ {{end}} +

{{.i18n.Tr "repo.issues.dependency.no_dependencies"}}

@@ -141,22 +181,22 @@ + {{end}} + + {{if (and (not .BlockedByDependencies) (not .BlockingDependencies))}} +

{{.i18n.Tr "repo.issues.dependency.no_dependencies"}}

+ {{end}}
-