Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue priority #4823

Closed
wants to merge 24 commits into from
Closed
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
329 changes: 22 additions & 307 deletions Gopkg.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ vendor:
@hash dep > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
$(GO) get -u github.com/golang/dep/cmd/dep; \
fi
dep ensure -vendor-only
dep ensure -vendor-only -v

.PHONY: test-vendor
test-vendor: vendor
Expand Down
27 changes: 22 additions & 5 deletions models/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -521,11 +521,11 @@ func (err ErrLastOrgOwner) Error() string {
return fmt.Sprintf("user is the last member of owner team [uid: %d]", err.UID)
}

//.____ ____________________
//| | \_ _____/ _____/
//| | | __) \_____ \
//| |___| \ / \
//|_______ \___ / /_______ /
// .____ ____________________
// | | \_ _____/ _____/
// | | | __) \_____ \
// | |___| \ / \
// |_______ \___ / /_______ /
// \/ \/ \/

// ErrLFSLockNotExist represents a "LFSLockNotExist" kind of error.
Expand Down Expand Up @@ -877,6 +877,23 @@ func (err ErrIssueNotExist) Error() string {
return fmt.Sprintf("issue does not exist [id: %d, repo_id: %d, index: %d]", err.ID, err.RepoID, err.Index)
}

// ErrIssueInvalidPriority represents a "IssueInvalidPriority" kind of error.
type ErrIssueInvalidPriority struct {
ID int64
RepoID int64
DesiredPriority int
}

// IsErrIssueInvalidPriority checks if an error is a ErrIssueInvalidPriority.
func IsErrIssueInvalidPriority(err error) bool {
_, ok := err.(ErrIssueInvalidPriority)
return ok
}

func (err ErrIssueInvalidPriority) Error() string {
return fmt.Sprintf("issue exceeds the threshold priority [id: %d, repo_id: %d, desired_priority: %d]", err.ID, err.RepoID, err.DesiredPriority)
}

// __________ .__ .__ __________ __
// \______ \__ __| | | |\______ \ ____ ________ __ ____ _______/ |_
// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
Expand Down
6 changes: 6 additions & 0 deletions models/fixtures/issue.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
index: 1
poster_id: 1
name: issue1
priority: 0
content: content for the first issue
is_closed: false
is_pull: false
Expand All @@ -17,6 +18,7 @@
index: 2
poster_id: 1
name: issue2
priority: 0
content: content for the second issue
milestone_id: 1
is_closed: false
Expand All @@ -31,6 +33,7 @@
index: 3
poster_id: 1
name: issue3
priority: 0
content: content for the third issue
is_closed: false
is_pull: true
Expand All @@ -43,6 +46,7 @@
index: 1
poster_id: 2
name: issue4
priority: 0
content: content for the fourth issue
is_closed: true
is_pull: false
Expand All @@ -55,6 +59,7 @@
index: 4
poster_id: 2
name: issue5
priority: 0
content: content for the fifth issue
is_closed: true
is_pull: false
Expand All @@ -67,6 +72,7 @@
index: 1
poster_id: 1
name: issue6
priority: 0
content: content6
is_closed: false
is_pull: false
Expand Down
33 changes: 19 additions & 14 deletions models/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ import (

// Issue represents an issue or pull request of repository.
type Issue struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX UNIQUE(repo_index)"`
Repo *Repository `xorm:"-"`
Index int64 `xorm:"UNIQUE(repo_index)"` // Index in one repository.
PosterID int64 `xorm:"INDEX"`
Poster *User `xorm:"-"`
Title string `xorm:"name"`
Content string `xorm:"TEXT"`
RenderedContent string `xorm:"-"`
Labels []*Label `xorm:"-"`
MilestoneID int64 `xorm:"INDEX"`
Milestone *Milestone `xorm:"-"`
Priority int
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX UNIQUE(repo_index)"`
Repo *Repository `xorm:"-"`
Index int64 `xorm:"UNIQUE(repo_index)"` // Index in one repository.
PosterID int64 `xorm:"INDEX"`
Poster *User `xorm:"-"`
Title string `xorm:"name"`
Content string `xorm:"TEXT"`
RenderedContent string `xorm:"-"`
Labels []*Label `xorm:"-"`
MilestoneID int64 `xorm:"INDEX"`
Milestone *Milestone `xorm:"-"`
Priority int `xorm:"priority"` // Indicates priority in list display
AssigneeID int64 `xorm:"-"`
Assignee *User `xorm:"-"`
IsClosed bool `xorm:"INDEX"`
Expand Down Expand Up @@ -665,12 +665,13 @@ func (issue *Issue) changeStatus(e *xorm.Session, doer *User, repo *Repository,

issue.IsClosed = isClosed
if isClosed {
issue.Priority = PriorityDefault
issue.ClosedUnix = util.TimeStampNow()
} else {
issue.ClosedUnix = 0
}

if err = updateIssueCols(e, issue, "is_closed", "closed_unix"); err != nil {
if err = updateIssueCols(e, issue, "is_closed", "closed_unix", "priority"); err != nil {
return err
}

Expand Down Expand Up @@ -1271,6 +1272,10 @@ func Issues(opts *IssuesOptions) ([]*Issue, error) {
if err := opts.setupSession(sess); err != nil {
return nil, err
}
// issues with high-level priorities are first in the result set.
if opts.SortType != "priority" {
sortIssuesSession(sess, "priority")
}
sortIssuesSession(sess, opts.SortType)

issues := make([]*Issue, 0, setting.UI.IssuePagingNum)
Expand Down
63 changes: 63 additions & 0 deletions models/issuse_priority.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright 2018 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 (
"github.com/go-xorm/xorm"
)

const (
// PriorityDefault defines the default priority
PriorityDefault = 0
)

// UpdateIssuePriority updates the priority
func UpdateIssuePriority(issue *Issue) error {
if err := issue.loadRepo(x); err != nil {
return err
}

if issue.Priority < PriorityDefault {
return ErrIssueInvalidPriority{ID: issue.ID, RepoID: issue.Repo.ID, DesiredPriority: issue.Priority}
}

_, err := AutoTransaction(func(session *xorm.Session) (interface{}, error) {
return nil, updateIssueCols(session, &Issue{ID: issue.ID, Priority: issue.Priority}, "priority")
}, x)

return err
}

// PinIssue to pin an issue
func PinIssue(issue *Issue, doer *User) error {
if err := issue.loadRepo(x); err != nil {
return err
}

if has, err := HasAccess(doer.ID, issue.Repo, AccessModeWrite); err != nil {
return err
} else if !has {
return ErrUserDoesNotHaveAccessToRepo{UserID: doer.ID, RepoName: issue.Repo.Name}
}

_, err := AutoTransaction(func(session *xorm.Session) (interface{}, error) {
var p int64
_, err := session.Table("issue").
Select("MAX(priority)").Where("repo_id=? and is_pull=0", issue.Repo.ID).Get(&p)
if err != nil {
return nil, err
}

_, err = session.Table("issue").Where("id = ?", issue.ID).
Update(map[string]interface{}{"priority": p + 10})
if err != nil {
return nil, err
}

return nil, nil
}, x)

return err
}
44 changes: 44 additions & 0 deletions models/issuse_priority_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2018 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 (
"testing"

"github.com/stretchr/testify/assert"
)

func TestUpdateIssuePriority(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())

issue := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)

issue.Priority = 99
err := UpdateIssuePriority(issue)
assert.NoError(t, err)

issue = AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
assert.EqualValues(t, 99, issue.Priority)

issue.Priority = -1
err = UpdateIssuePriority(issue)
assert.Error(t, err)
assert.EqualValues(t, err, ErrIssueInvalidPriority{
ID: issue.ID, RepoID: issue.Repo.ID, DesiredPriority: issue.Priority})
}

func TestPinIssue(t *testing.T) {
assert.NoError(t, PrepareTestDatabase())

issue := AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
repo := AssertExistsAndLoadBean(t, &Repository{ID: issue.RepoID}).(*Repository)
doer := AssertExistsAndLoadBean(t, &User{ID: repo.OwnerID}).(*User)

err := PinIssue(issue, doer)
assert.NoError(t, err)

issue = AssertExistsAndLoadBean(t, &Issue{ID: 1}).(*Issue)
assert.EqualValues(t, 10, issue.Priority)
}
30 changes: 30 additions & 0 deletions models/transaction.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2018 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 (
"github.com/go-xorm/xorm"
)

// AutoTransaction Execute sql wrapped in a transaction(abbr as tx), tx will automatic commit if no errors occurred
func AutoTransaction(f func(*xorm.Session) (interface{}, error), engine *xorm.Engine) (interface{}, error) {
session := engine.NewSession()
defer session.Close()

if err := session.Begin(); err != nil {
return nil, err
}

result, err := f(session)
if err != nil {
return nil, err
}

if err := session.Commit(); err != nil {
return nil, err
}

return result, nil
}
6 changes: 6 additions & 0 deletions modules/auth/repo_form.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,12 @@ type CreateCommentForm struct {
Files []string
}

// EditPriorityForm form for updating priority
type EditPriorityForm struct {
// required:true
Priority int `binding:"Required;Range(1,5)"`
}

// Validate validates the fields
func (f *CreateCommentForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
return validate(errs, ctx.Data, f, ctx.Locale)
Expand Down
22 changes: 22 additions & 0 deletions public/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,14 @@ function updateIssuesMeta(url, action, issueIds, elementId, afterSuccess) {
})
}

function updateIssuePriority(url, afterSuccess) {
$.ajax({
type: "PATCH",
url: url,
success: afterSuccess
})
}

function initReactionSelector(parent) {
var reactions = '';
if (!parent) {
Expand Down Expand Up @@ -1858,6 +1866,20 @@ $(document).ready(function () {
});
});

$('.issue-pin').click(function () {
var url = this.dataset.url
updateIssuePriority(url, function() {
location.reload();
});
});

$('.issue-unpin').click(function () {
var url = this.dataset.url
updateIssuePriority(url, function() {
location.reload();
});
});

buttonsClickOnEnter();
searchUsers();
searchRepositories();
Expand Down
4 changes: 3 additions & 1 deletion routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ func RegisterRoutes(m *macaron.Macaron) {
bind := binding.Bind

if setting.API.EnableSwagger {
m.Get("/swagger", misc.Swagger) //Render V1 by default
m.Get("/swagger", misc.Swagger) // Render V1 by default
}

m.Group("/v1", func() {
Expand Down Expand Up @@ -500,6 +500,8 @@ func RegisterRoutes(m *macaron.Macaron) {
})

m.Combo("/deadline").Post(reqToken(), bind(api.EditDeadlineOption{}), repo.UpdateIssueDeadline)
m.Combo("/pin").Patch(reqToken(), repo.PinIssue)
m.Combo("/unpin").Patch(reqToken(), repo.UnpinIssue)
})
}, mustEnableIssuesOrPulls)
m.Group("/labels", func() {
Expand Down
Loading