Added basic functionality:
* Add new dependecy * Show dependencies Signed-off-by: Konrad <konrad@kola-entertainments.de>
This commit is contained in:
parent
f3c40e8aea
commit
b89a9e9d2e
2
conf/app.ini
vendored
2
conf/app.ini
vendored
|
|
@ -389,7 +389,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]
|
||||
|
|
|
|||
|
|
@ -62,8 +62,6 @@ const (
|
|||
CommentTypeCancelTracking
|
||||
// Dependency added
|
||||
CommentTypeAddedDependency
|
||||
//Dependency removed
|
||||
CommentTypeRemovedDependency
|
||||
)
|
||||
|
||||
// CommentTag defines comment tag type
|
||||
|
|
@ -96,8 +94,6 @@ type Comment struct {
|
|||
OldAssignee *User `xorm:"-"`
|
||||
OldTitle string
|
||||
NewTitle string
|
||||
DependentIssueID int64
|
||||
DependentIssue *Issue `xorm:"-"`
|
||||
|
||||
CommitID int64
|
||||
Line int64
|
||||
|
|
@ -275,18 +271,6 @@ func (c *Comment) LoadAssignees() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Load Dependent Issue Details
|
||||
func (c *Comment) LoadDepIssueDetails() error {
|
||||
var err error
|
||||
if c.DependentIssueID > 0 {
|
||||
c.DependentIssue, err = getIssueByID(x, c.DependentIssueID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MailParticipants sends new comment emails to repository watchers
|
||||
// and mentioned people.
|
||||
func (c *Comment) MailParticipants(e Engine, opType ActionType, issue *Issue) (err error) {
|
||||
|
|
@ -315,12 +299,6 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
|
|||
if opts.Label != nil {
|
||||
LabelID = opts.Label.ID
|
||||
}
|
||||
|
||||
var depId int64 = 0
|
||||
if opts.DependentIssue != nil {
|
||||
depId = opts.DependentIssue.ID
|
||||
}
|
||||
|
||||
comment := &Comment{
|
||||
Type: opts.Type,
|
||||
PosterID: opts.Doer.ID,
|
||||
|
|
@ -337,12 +315,8 @@ func createComment(e *xorm.Session, opts *CreateCommentOptions) (_ *Comment, err
|
|||
Content: opts.Content,
|
||||
OldTitle: opts.OldTitle,
|
||||
NewTitle: opts.NewTitle,
|
||||
DependentIssue: opts.DependentIssue,
|
||||
DependentIssueID: depId,
|
||||
}
|
||||
|
||||
_, err = e.Insert(comment)
|
||||
if err != nil {
|
||||
if _, err = e.Insert(comment); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
@ -514,23 +488,6 @@ func createDeleteBranchComment(e *xorm.Session, doer *User, repo *Repository, is
|
|||
})
|
||||
}
|
||||
|
||||
// Creates issue dependency comment
|
||||
func createIssueDependencyComment(e *xorm.Session, doer *User, issue *Issue, dependantIssue *Issue, added bool) (*Comment, error) {
|
||||
cType := CommentTypeAddedDependency
|
||||
if !added {
|
||||
cType = CommentTypeRemovedDependency
|
||||
}
|
||||
|
||||
return createComment(e, &CreateCommentOptions{
|
||||
Type: cType,
|
||||
Doer: doer,
|
||||
Repo: issue.Repo,
|
||||
Issue: issue,
|
||||
DependentIssue: dependantIssue,
|
||||
Content: dependantIssue.Title,
|
||||
})
|
||||
}
|
||||
|
||||
// CreateCommentOptions defines options for creating comment
|
||||
type CreateCommentOptions struct {
|
||||
Type CommentType
|
||||
|
|
@ -538,7 +495,6 @@ type CreateCommentOptions struct {
|
|||
Repo *Repository
|
||||
Issue *Issue
|
||||
Label *Label
|
||||
DependentIssue *Issue
|
||||
|
||||
OldMilestoneID int64
|
||||
MilestoneID int64
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -693,6 +693,39 @@ func (repo *Repository) getUsersWithAccessMode(e Engine, mode AccessMode) (_ []*
|
|||
return users, nil
|
||||
}
|
||||
|
||||
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.
|
||||
|
|
|
|||
|
|
@ -729,38 +729,10 @@ 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.remove = Remove
|
||||
issues.dependency.add_header = Add New Dependency
|
||||
issues.dependency.issue_number = Issuenumber
|
||||
issues.dependency.added_dependency = `<a href="%[1]s">%[2]s</a> added a new dependency %[3]s`
|
||||
issues.dependency.removed_dependency = `<a href="%[1]s">%[2]s</a> removed a dependency %[3]s`
|
||||
issues.dependency.issue_closing_blockedby = Closing this pull request is blocked by
|
||||
issues.dependency.pr_closing_blockedby = Closing this issue is blocked by
|
||||
issues.dependency.issue_close_blocks = This issue blocks closing of the following issues
|
||||
issues.dependency.pr_close_blocks = This pull request blocks closing of the following issues
|
||||
issues.dependency.remove_header = Remove Dependency
|
||||
issues.dependency.remove_text = This will remove the dependency to this issue. Are you sure? You cannot undo this!
|
||||
issues.dependency.setting = Issues can have dependencies
|
||||
issues.dependency.add_error_same_issue = You cannot make an issue depend on itself!
|
||||
issues.dependency.add_error_dep_not_exist = Dependend issue does not exist!
|
||||
issues.dependency.add_error_dep_exists = Dependency already exists!
|
||||
issues.tracker = Time tracker
|
||||
issues.start_tracking_short = Start
|
||||
issues.start_tracking = Start time tracking
|
||||
issues.start_tracking_history = `started working %s`
|
||||
issues.tracking_already_started = `You have already started time tracking on this <a href="%s">issue</a>!`
|
||||
issues.stop_tracking = Stop
|
||||
issues.stop_tracking_history = `stopped working %s`
|
||||
issues.add_time = Add time manually
|
||||
issues.add_time_short = Add
|
||||
issues.add_time_cancel = Cancel
|
||||
issues.add_time_history = `added spent time %s`
|
||||
issues.add_time_hours = Hours
|
||||
issues.add_time_minutes = Minutes
|
||||
issues.add_time_sum_to_small = No time was entered
|
||||
issues.cancel_tracking = Cancel
|
||||
issues.cancel_tracking_history = `cancelled time tracking %s`
|
||||
issues.time_spent_total = Total time spent
|
||||
|
||||
|
||||
pulls.desc = Pulls management your code review and merge requests
|
||||
pulls.new = New Pull Request
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@ import (
|
|||
"code.gitea.io/gitea/modules/notification"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -684,11 +683,6 @@ func ViewIssue(ctx *context.Context) {
|
|||
ctx.Handle(500, "LoadAssignees", err)
|
||||
return
|
||||
}
|
||||
} else if comment.Type == models.CommentTypeRemovedDependency || comment.Type == models.CommentTypeAddedDependency{
|
||||
if err = comment.LoadDepIssueDetails(); err != nil{
|
||||
ctx.Handle(http.StatusInternalServerError, "LoadDepIssueDetails", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -714,7 +708,6 @@ func ViewIssue(ctx *context.Context) {
|
|||
}
|
||||
|
||||
// Get Dependencies
|
||||
ctx.Data["IssueDependenciesEnabled"] = repo.UnitEnabled(models.UnitTypeIssueDependencies)
|
||||
ctx.Data["BlockedByDependencies"], err = repo.BlockedByDependencies(issue.ID)
|
||||
ctx.Data["BlockingDependencies"], err = repo.BlockingDependencies(issue.ID)
|
||||
|
||||
|
|
@ -919,23 +912,6 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
|
|||
(form.Status == "reopen" || form.Status == "close") &&
|
||||
!(issue.IsPull && issue.PullRequest.HasMerged) {
|
||||
|
||||
// Check for open dependencies
|
||||
if form.Status == "close"{
|
||||
|
||||
canbeClosed := models.IssueNoDependenciesLeft(issue)
|
||||
|
||||
if !canbeClosed {
|
||||
if issue.IsPull{
|
||||
ctx.Flash.Error("You need to close all issues blocking this pull request before you can merge it!")
|
||||
ctx.Redirect(fmt.Sprintf("%s/pulls/%d", ctx.Repo.RepoLink, issue.Index))
|
||||
} else {
|
||||
ctx.Flash.Error("You need to close all issues blocking this issue before you can close it!")
|
||||
ctx.Redirect(fmt.Sprintf("%s/issues/%d", ctx.Repo.RepoLink, issue.Index))
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Duplication and conflict check should apply to reopen pull request.
|
||||
var pr *models.PullRequest
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -182,4 +182,16 @@
|
|||
<span class="text grey"><a href="{{.Poster.HomeLink}}">{{.Poster.Name}}</a> {{$.i18n.Tr "repo.issues.cancel_tracking_history" $createdStr | Safe}}</span>
|
||||
</div>
|
||||
{{end}}
|
||||
{{else if eq .Type 16}}
|
||||
<div class="event">
|
||||
<span class="octicon octicon-primitive-dot"></span>
|
||||
</div>
|
||||
<a class="ui avatar image" href="{{.Poster.HomeLink}}">
|
||||
<img src="{{.Poster.RelAvatarLink}}">
|
||||
</a>
|
||||
<span class="text grey">
|
||||
{{$.i18n.Tr "repo.issues.dependency.added_dependency" .Poster.HomeLink .Poster.Name $createdStr | Safe}}
|
||||
</span>
|
||||
{{end}}
|
||||
|
||||
{{end}}
|
||||
|
|
|
|||
|
|
@ -194,13 +194,53 @@
|
|||
<div class="ui divider"></div>
|
||||
|
||||
<div class="ui depending">
|
||||
<span class="text"><strong>Dependencies</strong></span>
|
||||
<div>
|
||||
This issue currently doesn't have any dependencies.
|
||||
<span class="text"><strong>{{.i18n.Tr "repo.issues.dependency.title"}}</strong></span>
|
||||
<br>
|
||||
<span class="text">This issue is blocked by:</span>
|
||||
<div class="ui relaxed divided list">
|
||||
{{range .BlockedByDependencies}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
{{if .IsClosed}}
|
||||
<div class="ui red mini label">
|
||||
<i class="octicon octicon-issue-closed"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="ui green mini label">
|
||||
<i class="octicon octicon-issue-opened"></i>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui black label">#{{.Index}}</div>
|
||||
<a class="title has-emoji" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
<div class="ui relaxed divided list">
|
||||
<span class="text">This issue blocks the following issues:</span>
|
||||
{{range .BlockingDependencies}}
|
||||
<div class="item">
|
||||
<div class="right floated content">
|
||||
{{if .IsClosed}}
|
||||
<div class="ui red mini label">
|
||||
<i class="octicon octicon-issue-closed"></i>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="ui green mini label">
|
||||
<i class="octicon octicon-issue-opened"></i>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui black label">#{{.Index}}</div>
|
||||
<a class="title has-emoji" href="{{$.RepoLink}}/issues/{{.Index}}">{{.Title}}</a>
|
||||
</div>
|
||||
{{end}}
|
||||
<p>{{.i18n.Tr "repo.issues.dependency.no_dependencies"}}</p>
|
||||
</div>
|
||||
<div>
|
||||
<button class="fluid green ui button" onclick="showAddDependencyModal();">
|
||||
Add
|
||||
{{.i18n.Tr "repo.issues.dependency.add"}}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -210,22 +250,22 @@
|
|||
|
||||
<div class="ui tiny modal">
|
||||
<div class="header">
|
||||
Add new Dependency
|
||||
{{.i18n.Tr "repo.issues.dependency.add_header"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<form method="POST" action="{{$.RepoLink}}/issues/{{.Issue.Index}}/addDependency" id="addDependencyForm">
|
||||
{{$.CsrfTokenHtml}}
|
||||
<div class="ui input">
|
||||
<input type="text" name="newDependency" id="newDependency" placeholder="Issuenumber...">
|
||||
<input type="text" name="newDependency" id="newDependency" placeholder='{{.i18n.Tr "repo.issues.dependency.issue_number"}}'>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="ui negative button">
|
||||
Cancel
|
||||
{{.i18n.Tr "repo.issues.dependency.cancel"}}
|
||||
</div>
|
||||
<div class="ui positive right labeled icon button">
|
||||
Add
|
||||
{{.i18n.Tr "repo.issues.dependency.add"}}
|
||||
<i class="add icon"></i>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user