|
|
@ -17,6 +17,7 @@ import ( |
|
|
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
var ( |
|
|
|
ErrIssueNotExist = errors.New("Issue does not exist") |
|
|
|
ErrIssueNotExist = errors.New("Issue does not exist") |
|
|
|
|
|
|
|
ErrLabelNotExist = errors.New("Label does not exist") |
|
|
|
ErrMilestoneNotExist = errors.New("Milestone does not exist") |
|
|
|
ErrMilestoneNotExist = errors.New("Milestone does not exist") |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
@ -28,14 +29,15 @@ type Issue struct { |
|
|
|
Name string |
|
|
|
Name string |
|
|
|
Repo *Repository `xorm:"-"` |
|
|
|
Repo *Repository `xorm:"-"` |
|
|
|
PosterId int64 |
|
|
|
PosterId int64 |
|
|
|
Poster *User `xorm:"-"` |
|
|
|
Poster *User `xorm:"-"` |
|
|
|
|
|
|
|
LabelIds string `xorm:"TEXT"` |
|
|
|
|
|
|
|
Labels []*Label `xorm:"-"` |
|
|
|
MilestoneId int64 |
|
|
|
MilestoneId int64 |
|
|
|
AssigneeId int64 |
|
|
|
AssigneeId int64 |
|
|
|
Assignee *User `xorm:"-"` |
|
|
|
Assignee *User `xorm:"-"` |
|
|
|
IsRead bool `xorm:"-"` |
|
|
|
IsRead bool `xorm:"-"` |
|
|
|
IsPull bool // Indicates whether is a pull request or not.
|
|
|
|
IsPull bool // Indicates whether is a pull request or not.
|
|
|
|
IsClosed bool |
|
|
|
IsClosed bool |
|
|
|
Labels string `xorm:"TEXT"` |
|
|
|
|
|
|
|
Content string `xorm:"TEXT"` |
|
|
|
Content string `xorm:"TEXT"` |
|
|
|
RenderedContent string `xorm:"-"` |
|
|
|
RenderedContent string `xorm:"-"` |
|
|
|
Priority int |
|
|
|
Priority int |
|
|
@ -54,11 +56,37 @@ func (i *Issue) GetPoster() (err error) { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (i *Issue) GetLabels() error { |
|
|
|
|
|
|
|
if len(i.LabelIds) < 3 { |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
strIds := strings.Split(strings.TrimSuffix(i.LabelIds[1:], "|"), "|$") |
|
|
|
|
|
|
|
i.Labels = make([]*Label, 0, len(strIds)) |
|
|
|
|
|
|
|
for _, strId := range strIds { |
|
|
|
|
|
|
|
id, _ := base.StrTo(strId).Int64() |
|
|
|
|
|
|
|
if id > 0 { |
|
|
|
|
|
|
|
l, err := GetLabelById(id) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
if err == ErrLabelNotExist { |
|
|
|
|
|
|
|
continue |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
i.Labels = append(i.Labels, l) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (i *Issue) GetAssignee() (err error) { |
|
|
|
func (i *Issue) GetAssignee() (err error) { |
|
|
|
if i.AssigneeId == 0 { |
|
|
|
if i.AssigneeId == 0 { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
i.Assignee, err = GetUserById(i.AssigneeId) |
|
|
|
i.Assignee, err = GetUserById(i.AssigneeId) |
|
|
|
|
|
|
|
if err == ErrUserNotExist { |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
} |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -108,7 +136,7 @@ func GetIssueById(id int64) (*Issue, error) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// GetIssues returns a list of issues by given conditions.
|
|
|
|
// GetIssues returns a list of issues by given conditions.
|
|
|
|
func GetIssues(uid, rid, pid, mid int64, page int, isClosed bool, labels, sortType string) ([]Issue, error) { |
|
|
|
func GetIssues(uid, rid, pid, mid int64, page int, isClosed bool, labelIds, sortType string) ([]Issue, error) { |
|
|
|
sess := orm.Limit(20, (page-1)*20) |
|
|
|
sess := orm.Limit(20, (page-1)*20) |
|
|
|
|
|
|
|
|
|
|
|
if rid > 0 { |
|
|
|
if rid > 0 { |
|
|
@ -127,9 +155,9 @@ func GetIssues(uid, rid, pid, mid int64, page int, isClosed bool, labels, sortTy |
|
|
|
sess.And("milestone_id=?", mid) |
|
|
|
sess.And("milestone_id=?", mid) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if len(labels) > 0 { |
|
|
|
if len(labelIds) > 0 { |
|
|
|
for _, label := range strings.Split(labels, ",") { |
|
|
|
for _, label := range strings.Split(labelIds, ",") { |
|
|
|
sess.And("labels like '%$" + label + "|%'") |
|
|
|
sess.And("label_ids like '%$" + label + "|%'") |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -155,6 +183,13 @@ func GetIssues(uid, rid, pid, mid int64, page int, isClosed bool, labels, sortTy |
|
|
|
return issues, err |
|
|
|
return issues, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// GetIssuesByLabel returns a list of issues by given label and repository.
|
|
|
|
|
|
|
|
func GetIssuesByLabel(repoId int64, label string) ([]*Issue, error) { |
|
|
|
|
|
|
|
issues := make([]*Issue, 0, 10) |
|
|
|
|
|
|
|
err := orm.Where("repo_id=?", repoId).And("label_ids like '%$" + label + "|%'").Find(&issues) |
|
|
|
|
|
|
|
return issues, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// GetIssueCountByPoster returns number of issues of repository by poster.
|
|
|
|
// GetIssueCountByPoster returns number of issues of repository by poster.
|
|
|
|
func GetIssueCountByPoster(uid, rid int64, isClosed bool) int64 { |
|
|
|
func GetIssueCountByPoster(uid, rid int64, isClosed bool) int64 { |
|
|
|
count, _ := orm.Where("repo_id=?", rid).And("poster_id=?", uid).And("is_closed=?", isClosed).Count(new(Issue)) |
|
|
|
count, _ := orm.Where("repo_id=?", rid).And("poster_id=?", uid).And("is_closed=?", isClosed).Count(new(Issue)) |
|
|
@ -175,7 +210,6 @@ type IssueUser struct { |
|
|
|
IssueId int64 |
|
|
|
IssueId int64 |
|
|
|
RepoId int64 |
|
|
|
RepoId int64 |
|
|
|
MilestoneId int64 |
|
|
|
MilestoneId int64 |
|
|
|
Labels string `xorm:"TEXT"` |
|
|
|
|
|
|
|
IsRead bool |
|
|
|
IsRead bool |
|
|
|
IsAssigned bool |
|
|
|
IsAssigned bool |
|
|
|
IsMentioned bool |
|
|
|
IsMentioned bool |
|
|
@ -400,6 +434,98 @@ func UpdateIssueUserPairsByMentions(uids []int64, iid int64) error { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// .____ ___. .__
|
|
|
|
|
|
|
|
// | | _____ \_ |__ ____ | |
|
|
|
|
|
|
|
|
// | | \__ \ | __ \_/ __ \| |
|
|
|
|
|
|
|
|
// | |___ / __ \| \_\ \ ___/| |__
|
|
|
|
|
|
|
|
// |_______ (____ /___ /\___ >____/
|
|
|
|
|
|
|
|
// \/ \/ \/ \/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Label represents a label of repository for issues.
|
|
|
|
|
|
|
|
type Label struct { |
|
|
|
|
|
|
|
Id int64 |
|
|
|
|
|
|
|
RepoId int64 `xorm:"INDEX"` |
|
|
|
|
|
|
|
Name string |
|
|
|
|
|
|
|
Color string `xorm:"VARCHAR(7)"` |
|
|
|
|
|
|
|
NumIssues int |
|
|
|
|
|
|
|
NumClosedIssues int |
|
|
|
|
|
|
|
NumOpenIssues int `xorm:"-"` |
|
|
|
|
|
|
|
IsChecked bool `xorm:"-"` |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// CalOpenIssues calculates the open issues of label.
|
|
|
|
|
|
|
|
func (m *Label) CalOpenIssues() { |
|
|
|
|
|
|
|
m.NumOpenIssues = m.NumIssues - m.NumClosedIssues |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// NewLabel creates new label of repository.
|
|
|
|
|
|
|
|
func NewLabel(l *Label) error { |
|
|
|
|
|
|
|
_, err := orm.Insert(l) |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// GetLabelById returns a label by given ID.
|
|
|
|
|
|
|
|
func GetLabelById(id int64) (*Label, error) { |
|
|
|
|
|
|
|
l := &Label{Id: id} |
|
|
|
|
|
|
|
has, err := orm.Get(l) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return nil, err |
|
|
|
|
|
|
|
} else if !has { |
|
|
|
|
|
|
|
return nil, ErrLabelNotExist |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return l, nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// GetLabels returns a list of labels of given repository ID.
|
|
|
|
|
|
|
|
func GetLabels(repoId int64) ([]*Label, error) { |
|
|
|
|
|
|
|
labels := make([]*Label, 0, 10) |
|
|
|
|
|
|
|
err := orm.Where("repo_id=?", repoId).Find(&labels) |
|
|
|
|
|
|
|
return labels, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// UpdateLabel updates label information.
|
|
|
|
|
|
|
|
func UpdateLabel(l *Label) error { |
|
|
|
|
|
|
|
_, err := orm.Id(l.Id).Update(l) |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// DeleteLabel delete a label of given repository.
|
|
|
|
|
|
|
|
func DeleteLabel(repoId int64, strId string) error { |
|
|
|
|
|
|
|
id, _ := base.StrTo(strId).Int64() |
|
|
|
|
|
|
|
l, err := GetLabelById(id) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
if err == ErrLabelNotExist { |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
issues, err := GetIssuesByLabel(repoId, strId) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sess := orm.NewSession() |
|
|
|
|
|
|
|
defer sess.Close() |
|
|
|
|
|
|
|
if err = sess.Begin(); err != nil { |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for _, issue := range issues { |
|
|
|
|
|
|
|
issue.LabelIds = strings.Replace(issue.LabelIds, "$"+strId+"|", "", -1) |
|
|
|
|
|
|
|
if _, err = sess.Id(issue.Id).AllCols().Update(issue); err != nil { |
|
|
|
|
|
|
|
sess.Rollback() |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if _, err = sess.Delete(l); err != nil { |
|
|
|
|
|
|
|
sess.Rollback() |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return sess.Commit() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// _____ .__.__ __
|
|
|
|
// _____ .__.__ __
|
|
|
|
// / \ |__| | ____ _______/ |_ ____ ____ ____
|
|
|
|
// / \ |__| | ____ _______/ |_ ____ ____ ____
|
|
|
|
// / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \
|
|
|
|
// / \ / \| | | _/ __ \ / ___/\ __\/ _ \ / \_/ __ \
|
|
|
@ -611,42 +737,6 @@ func DeleteMilestone(m *Milestone) (err error) { |
|
|
|
return sess.Commit() |
|
|
|
return sess.Commit() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// .____ ___. .__
|
|
|
|
|
|
|
|
// | | _____ \_ |__ ____ | |
|
|
|
|
|
|
|
|
// | | \__ \ | __ \_/ __ \| |
|
|
|
|
|
|
|
|
// | |___ / __ \| \_\ \ ___/| |__
|
|
|
|
|
|
|
|
// |_______ (____ /___ /\___ >____/
|
|
|
|
|
|
|
|
// \/ \/ \/ \/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Label represents a label of repository for issues.
|
|
|
|
|
|
|
|
type Label struct { |
|
|
|
|
|
|
|
Id int64 |
|
|
|
|
|
|
|
RepoId int64 `xorm:"INDEX"` |
|
|
|
|
|
|
|
Name string |
|
|
|
|
|
|
|
Color string `xorm:"VARCHAR(7)"` |
|
|
|
|
|
|
|
NumIssues int |
|
|
|
|
|
|
|
NumClosedIssues int |
|
|
|
|
|
|
|
NumOpenIssues int `xorm:"-"` |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// CalOpenIssues calculates the open issues of label.
|
|
|
|
|
|
|
|
func (m *Label) CalOpenIssues() { |
|
|
|
|
|
|
|
m.NumOpenIssues = m.NumIssues - m.NumClosedIssues |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// NewLabel creates new label of repository.
|
|
|
|
|
|
|
|
func NewLabel(l *Label) error { |
|
|
|
|
|
|
|
_, err := orm.Insert(l) |
|
|
|
|
|
|
|
return err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// GetLabels returns a list of labels of given repository ID.
|
|
|
|
|
|
|
|
func GetLabels(repoId int64) ([]*Label, error) { |
|
|
|
|
|
|
|
labels := make([]*Label, 0, 10) |
|
|
|
|
|
|
|
err := orm.Where("repo_id=?", repoId).Find(&labels) |
|
|
|
|
|
|
|
return labels, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// _________ __
|
|
|
|
// _________ __
|
|
|
|
// \_ ___ \ ____ _____ _____ ____ _____/ |_
|
|
|
|
// \_ ___ \ ____ _____ _____ ____ _____/ |_
|
|
|
|
// / \ \/ / _ \ / \ / \_/ __ \ / \ __\
|
|
|
|
// / \ \/ / _ \ / \ / \_/ __ \ / \ __\
|
|
|
|