|
|
@ -98,32 +98,35 @@ var ErrIssueAlreadyChanged = util.NewInvalidArgumentErrorf("the issue is already |
|
|
|
|
|
|
|
|
|
|
|
// Issue represents an issue or pull request of repository.
|
|
|
|
// Issue represents an issue or pull request of repository.
|
|
|
|
type Issue struct { |
|
|
|
type Issue struct { |
|
|
|
ID int64 `xorm:"pk autoincr"` |
|
|
|
ID int64 `xorm:"pk autoincr"` |
|
|
|
RepoID int64 `xorm:"INDEX UNIQUE(repo_index)"` |
|
|
|
RepoID int64 `xorm:"INDEX UNIQUE(repo_index)"` |
|
|
|
Repo *repo_model.Repository `xorm:"-"` |
|
|
|
Repo *repo_model.Repository `xorm:"-"` |
|
|
|
Index int64 `xorm:"UNIQUE(repo_index)"` // Index in one repository.
|
|
|
|
Index int64 `xorm:"UNIQUE(repo_index)"` // Index in one repository.
|
|
|
|
PosterID int64 `xorm:"INDEX"` |
|
|
|
PosterID int64 `xorm:"INDEX"` |
|
|
|
Poster *user_model.User `xorm:"-"` |
|
|
|
Poster *user_model.User `xorm:"-"` |
|
|
|
OriginalAuthor string |
|
|
|
OriginalAuthor string |
|
|
|
OriginalAuthorID int64 `xorm:"index"` |
|
|
|
OriginalAuthorID int64 `xorm:"index"` |
|
|
|
Title string `xorm:"name"` |
|
|
|
Title string `xorm:"name"` |
|
|
|
Content string `xorm:"LONGTEXT"` |
|
|
|
Content string `xorm:"LONGTEXT"` |
|
|
|
RenderedContent template.HTML `xorm:"-"` |
|
|
|
RenderedContent template.HTML `xorm:"-"` |
|
|
|
ContentVersion int `xorm:"NOT NULL DEFAULT 0"` |
|
|
|
ContentVersion int `xorm:"NOT NULL DEFAULT 0"` |
|
|
|
Labels []*Label `xorm:"-"` |
|
|
|
Labels []*Label `xorm:"-"` |
|
|
|
MilestoneID int64 `xorm:"INDEX"` |
|
|
|
isLabelsLoaded bool `xorm:"-"` |
|
|
|
Milestone *Milestone `xorm:"-"` |
|
|
|
MilestoneID int64 `xorm:"INDEX"` |
|
|
|
Project *project_model.Project `xorm:"-"` |
|
|
|
Milestone *Milestone `xorm:"-"` |
|
|
|
Priority int |
|
|
|
isMilestoneLoaded bool `xorm:"-"` |
|
|
|
AssigneeID int64 `xorm:"-"` |
|
|
|
Project *project_model.Project `xorm:"-"` |
|
|
|
Assignee *user_model.User `xorm:"-"` |
|
|
|
Priority int |
|
|
|
IsClosed bool `xorm:"INDEX"` |
|
|
|
AssigneeID int64 `xorm:"-"` |
|
|
|
IsRead bool `xorm:"-"` |
|
|
|
Assignee *user_model.User `xorm:"-"` |
|
|
|
IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not.
|
|
|
|
isAssigneeLoaded bool `xorm:"-"` |
|
|
|
PullRequest *PullRequest `xorm:"-"` |
|
|
|
IsClosed bool `xorm:"INDEX"` |
|
|
|
NumComments int |
|
|
|
IsRead bool `xorm:"-"` |
|
|
|
Ref string |
|
|
|
IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not.
|
|
|
|
PinOrder int `xorm:"DEFAULT 0"` |
|
|
|
PullRequest *PullRequest `xorm:"-"` |
|
|
|
|
|
|
|
NumComments int |
|
|
|
|
|
|
|
Ref string |
|
|
|
|
|
|
|
PinOrder int `xorm:"DEFAULT 0"` |
|
|
|
|
|
|
|
|
|
|
|
DeadlineUnix timeutil.TimeStamp `xorm:"INDEX"` |
|
|
|
DeadlineUnix timeutil.TimeStamp `xorm:"INDEX"` |
|
|
|
|
|
|
|
|
|
|
@ -131,11 +134,12 @@ type Issue struct { |
|
|
|
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` |
|
|
|
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` |
|
|
|
ClosedUnix timeutil.TimeStamp `xorm:"INDEX"` |
|
|
|
ClosedUnix timeutil.TimeStamp `xorm:"INDEX"` |
|
|
|
|
|
|
|
|
|
|
|
Attachments []*repo_model.Attachment `xorm:"-"` |
|
|
|
Attachments []*repo_model.Attachment `xorm:"-"` |
|
|
|
Comments CommentList `xorm:"-"` |
|
|
|
isAttachmentsLoaded bool `xorm:"-"` |
|
|
|
Reactions ReactionList `xorm:"-"` |
|
|
|
Comments CommentList `xorm:"-"` |
|
|
|
TotalTrackedTime int64 `xorm:"-"` |
|
|
|
Reactions ReactionList `xorm:"-"` |
|
|
|
Assignees []*user_model.User `xorm:"-"` |
|
|
|
TotalTrackedTime int64 `xorm:"-"` |
|
|
|
|
|
|
|
Assignees []*user_model.User `xorm:"-"` |
|
|
|
|
|
|
|
|
|
|
|
// IsLocked limits commenting abilities to users on an issue
|
|
|
|
// IsLocked limits commenting abilities to users on an issue
|
|
|
|
// with write access
|
|
|
|
// with write access
|
|
|
@ -187,6 +191,19 @@ func (issue *Issue) LoadRepo(ctx context.Context) (err error) { |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (issue *Issue) LoadAttachments(ctx context.Context) (err error) { |
|
|
|
|
|
|
|
if issue.isAttachmentsLoaded || issue.Attachments != nil { |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
issue.Attachments, err = repo_model.GetAttachmentsByIssueID(ctx, issue.ID) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return fmt.Errorf("getAttachmentsByIssueID [%d]: %w", issue.ID, err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
issue.isAttachmentsLoaded = true |
|
|
|
|
|
|
|
return nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// IsTimetrackerEnabled returns true if the repo enables timetracking
|
|
|
|
// IsTimetrackerEnabled returns true if the repo enables timetracking
|
|
|
|
func (issue *Issue) IsTimetrackerEnabled(ctx context.Context) bool { |
|
|
|
func (issue *Issue) IsTimetrackerEnabled(ctx context.Context) bool { |
|
|
|
if err := issue.LoadRepo(ctx); err != nil { |
|
|
|
if err := issue.LoadRepo(ctx); err != nil { |
|
|
@ -287,11 +304,12 @@ func (issue *Issue) loadReactions(ctx context.Context) (err error) { |
|
|
|
|
|
|
|
|
|
|
|
// LoadMilestone load milestone of this issue.
|
|
|
|
// LoadMilestone load milestone of this issue.
|
|
|
|
func (issue *Issue) LoadMilestone(ctx context.Context) (err error) { |
|
|
|
func (issue *Issue) LoadMilestone(ctx context.Context) (err error) { |
|
|
|
if (issue.Milestone == nil || issue.Milestone.ID != issue.MilestoneID) && issue.MilestoneID > 0 { |
|
|
|
if !issue.isMilestoneLoaded && (issue.Milestone == nil || issue.Milestone.ID != issue.MilestoneID) && issue.MilestoneID > 0 { |
|
|
|
issue.Milestone, err = GetMilestoneByRepoID(ctx, issue.RepoID, issue.MilestoneID) |
|
|
|
issue.Milestone, err = GetMilestoneByRepoID(ctx, issue.RepoID, issue.MilestoneID) |
|
|
|
if err != nil && !IsErrMilestoneNotExist(err) { |
|
|
|
if err != nil && !IsErrMilestoneNotExist(err) { |
|
|
|
return fmt.Errorf("getMilestoneByRepoID [repo_id: %d, milestone_id: %d]: %w", issue.RepoID, issue.MilestoneID, err) |
|
|
|
return fmt.Errorf("getMilestoneByRepoID [repo_id: %d, milestone_id: %d]: %w", issue.RepoID, issue.MilestoneID, err) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
issue.isMilestoneLoaded = true |
|
|
|
} |
|
|
|
} |
|
|
|
return nil |
|
|
|
return nil |
|
|
|
} |
|
|
|
} |
|
|
@ -327,11 +345,8 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { |
|
|
|
return err |
|
|
|
return err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if issue.Attachments == nil { |
|
|
|
if err = issue.LoadAttachments(ctx); err != nil { |
|
|
|
issue.Attachments, err = repo_model.GetAttachmentsByIssueID(ctx, issue.ID) |
|
|
|
return err |
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return fmt.Errorf("getAttachmentsByIssueID [%d]: %w", issue.ID, err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if err = issue.loadComments(ctx); err != nil { |
|
|
|
if err = issue.loadComments(ctx); err != nil { |
|
|
@ -350,6 +365,13 @@ func (issue *Issue) LoadAttributes(ctx context.Context) (err error) { |
|
|
|
return issue.loadReactions(ctx) |
|
|
|
return issue.loadReactions(ctx) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (issue *Issue) ResetAttributesLoaded() { |
|
|
|
|
|
|
|
issue.isLabelsLoaded = false |
|
|
|
|
|
|
|
issue.isMilestoneLoaded = false |
|
|
|
|
|
|
|
issue.isAttachmentsLoaded = false |
|
|
|
|
|
|
|
issue.isAssigneeLoaded = false |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// GetIsRead load the `IsRead` field of the issue
|
|
|
|
// GetIsRead load the `IsRead` field of the issue
|
|
|
|
func (issue *Issue) GetIsRead(ctx context.Context, userID int64) error { |
|
|
|
func (issue *Issue) GetIsRead(ctx context.Context, userID int64) error { |
|
|
|
issueUser := &IssueUser{IssueID: issue.ID, UID: userID} |
|
|
|
issueUser := &IssueUser{IssueID: issue.ID, UID: userID} |
|
|
|