Skip to content

Add milestone labels #20620

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

Closed
wants to merge 28 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2285197
add milestone labels
bl00mber Aug 2, 2022
ce65597
merge main branch
bl00mber Aug 2, 2022
41cdfff
lint
bl00mber Aug 2, 2022
0da7f38
Merge branch 'main' into milestone-labels
bl00mber Oct 18, 2022
3aec5c6
Update
bl00mber Oct 18, 2022
eaae336
Update (review)
bl00mber Oct 19, 2022
6e8480c
Update
bl00mber Nov 2, 2022
6276a53
Update copyright & Use context in LoadLabels
bl00mber Dec 12, 2022
1700282
Update
bl00mber Dec 17, 2022
8e95c56
Merge branch 'main'
bl00mber Mar 21, 2023
f7343b7
Update to run on latest version
bl00mber Mar 21, 2023
6d6ef92
Merge branch 'main' of github.com:go-gitea/gitea into milestone-labels
bl00mber Apr 4, 2023
da05ac8
Update
bl00mber Apr 22, 2023
089fba6
Merge branch 'main'
bl00mber Apr 22, 2023
ae51db9
Update
bl00mber Apr 27, 2023
e88fe87
Merge branch 'main' into milestone-labels
bl00mber Apr 27, 2023
48f0d53
Merge branch 'main' into milestone-labels
silverwind Apr 30, 2023
71758e4
Update templates/repo/issue/milestone_new.tmpl
silverwind Apr 30, 2023
3f5c334
Update
bl00mber May 12, 2023
e386bf8
Merge branch 'main' into milestone-labels
bl00mber May 12, 2023
f76485e
Update
bl00mber May 17, 2023
d93d63c
Update
bl00mber May 17, 2023
c71bbd8
update migration number
silverwind May 21, 2023
e336a1e
Merge branch 'main' into milestone-labels
silverwind May 21, 2023
cd0979b
move labels inline to title, remove icon
silverwind May 21, 2023
5bee7e5
misc css tweaks
silverwind May 21, 2023
3fe9bcb
Apply grammatic changes from denyskon
bl00mber Aug 15, 2023
09d2600
Merge branch 'main' into milestone-labels
bl00mber Aug 16, 2023
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
8 changes: 8 additions & 0 deletions models/issues/label.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ type Label struct {
Color string `xorm:"VARCHAR(7)"`
NumIssues int
NumClosedIssues int
NumMilestones int
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`

Expand Down Expand Up @@ -523,6 +524,13 @@ func updateLabelCols(ctx context.Context, l *Label, cols ...string) error {
"issue.is_closed": true,
}),
).
SetExpr("num_milestones",
builder.Select("count(*)").From("milestone_label").
InnerJoin("milestone", "milestone_label.milestone_id = milestone.id").
Where(builder.Eq{
"milestone_label.label_id": l.ID,
}),
).
Cols(cols...).Update(l)
return err
}
89 changes: 85 additions & 4 deletions models/issues/milestone.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (

"code.gitea.io/gitea/models/db"
repo_model "code.gitea.io/gitea/models/repo"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/timeutil"
Expand Down Expand Up @@ -47,6 +49,7 @@ type Milestone struct {
ID int64 `xorm:"pk autoincr"`
RepoID int64 `xorm:"INDEX"`
Repo *repo_model.Repository `xorm:"-"`
Labels []*Label `xorm:"-"`
Name string
Content string `xorm:"TEXT"`
RenderedContent string `xorm:"-"`
Expand Down Expand Up @@ -117,6 +120,19 @@ func NewMilestone(m *Milestone) (err error) {
return err
}

if len(m.Labels) > 0 {
for _, label := range m.Labels {
// Silently drop invalid labels.
if label.RepoID != m.RepoID && label.OrgID != m.Repo.OwnerID {
continue
}

if err = m.addLabel(ctx, label, nil); err != nil {
return fmt.Errorf("addLabel [id: %d]: %v", label.ID, err)
}
}
}

if _, err = db.Exec(ctx, "UPDATE `repository` SET num_milestones = num_milestones + 1 WHERE id = ?", m.RepoID); err != nil {
return err
}
Expand All @@ -142,15 +158,15 @@ func GetMilestoneByRepoID(ctx context.Context, repoID, id int64) (*Milestone, er

// GetMilestoneByRepoIDANDName return a milestone if one exist by name and repo
func GetMilestoneByRepoIDANDName(repoID int64, name string) (*Milestone, error) {
var mile Milestone
has, err := db.GetEngine(db.DefaultContext).Where("repo_id=? AND name=?", repoID, name).Get(&mile)
var m Milestone
has, err := db.GetEngine(db.DefaultContext).Where("repo_id=? AND name=?", repoID, name).Get(&m)
if err != nil {
return nil, err
}
if !has {
return nil, ErrMilestoneNotExist{Name: name, RepoID: repoID}
}
return &mile, nil
return &m, nil
}

// UpdateMilestone updates information of given milestone.
Expand All @@ -176,6 +192,44 @@ func UpdateMilestone(m *Milestone, oldIsClosed bool) error {
}
}

if err = m.LoadLabels(ctx); err != nil {
return err
}
dbLabels, err := GetLabelsByMilestoneID(ctx, m.ID)
if err != nil {
return err
}
// delete missing labels associated with repo and milestone from db
for _, dbLabel := range dbLabels {
labelOnMilestone := false
for _, msLabel := range m.Labels {
if msLabel.ID == dbLabel.ID {
labelOnMilestone = true
break
}
}
if !labelOnMilestone {
if err = deleteMilestoneLabel(ctx, m, dbLabel, nil); err != nil {
return fmt.Errorf("deleteMilestoneLabel [id: %d]: %v", dbLabel.ID, err)
}
}
}
// add new labels associated with repo and milestone to db
for _, msLabel := range m.Labels {
labelInDatabase := false
for _, dbLabel := range dbLabels {
if msLabel.ID == dbLabel.ID {
labelInDatabase = true
break
}
}
if !labelInDatabase {
if err = m.addLabel(ctx, msLabel, nil); err != nil {
return fmt.Errorf("addLabel [id: %d]: %v", msLabel.ID, err)
}
}
}

return committer.Commit()
}

Expand Down Expand Up @@ -269,7 +323,7 @@ func changeMilestoneStatus(ctx context.Context, m *Milestone, isClosed bool) err
return updateRepoMilestoneNum(ctx, m.RepoID)
}

// DeleteMilestoneByRepoID deletes a milestone from a repository.
// DeleteMilestoneByRepoID deletes a milestone and associated labels from a repository.
func DeleteMilestoneByRepoID(repoID, id int64) error {
m, err := GetMilestoneByRepoID(db.DefaultContext, repoID, id)
if err != nil {
Expand Down Expand Up @@ -320,6 +374,15 @@ func DeleteMilestoneByRepoID(repoID, id int64) error {
if _, err = db.Exec(ctx, "UPDATE `issue` SET milestone_id = 0 WHERE milestone_id = ?", m.ID); err != nil {
return err
}

if err = m.LoadLabels(ctx); err != nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe just exec a SQL to delete by milestone_id is better.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lunny how it should look like? There seems to be no db.Exec SQL queries that delete in this project

return err
}
for _, label := range m.Labels {
if err = deleteMilestoneLabel(ctx, m, label, nil); err != nil {
return err
}
}
return committer.Commit()
}

Expand All @@ -341,6 +404,7 @@ type GetMilestonesOption struct {
State api.StateType
Name string
SortType string
Labels string
}

func (opts GetMilestonesOption) toCond() builder.Cond {
Expand Down Expand Up @@ -374,6 +438,22 @@ func GetMilestones(opts GetMilestonesOption) (MilestoneList, int64, error) {
sess = db.SetSessionPagination(sess, &opts)
}

if len(opts.Labels) > 0 && opts.Labels != "0" {
labelIDs, err := base.StringsToInt64s(strings.Split(opts.Labels, ","))
if err != nil {
log.Warn("Malformed Labels argument: %s", opts.Labels)
} else {
for i, labelID := range labelIDs {
if labelID > 0 {
sess.Join("INNER", fmt.Sprintf("milestone_label il%d", i),
fmt.Sprintf("milestone.id = il%[1]d.milestone_id AND il%[1]d.label_id = %[2]d", i, labelID))
} else {
sess.Where("milestone.id NOT IN (SELECT milestone_id FROM milestone_label WHERE milestone_id = ?)", -labelID)
}
}
Comment on lines +446 to +453
Copy link
Contributor

@wxiaoguang wxiaoguang May 12, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This SQL seems strange. Could it be replaced by two IN expressions?

label_id IN (match_list) AND label_id NOT IN (not_match_list)

Copy link
Author

@bl00mber bl00mber May 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is the same SQL as in issue.go / getIssueStatsChunk

}
}

switch opts.SortType {
case "furthestduedate":
sess.Desc("deadline_unix")
Expand All @@ -393,6 +473,7 @@ func GetMilestones(opts GetMilestonesOption) (MilestoneList, int64, error) {

miles := make([]*Milestone, 0, opts.PageSize)
total, err := sess.FindAndCount(&miles)

return miles, total, err
}

Expand Down
Loading