inform participants on UI too (#10473)
* inform participants on UI too * ajust test * refactor getParticipantIDsByIssue
This commit is contained in:
parent
513b962c1d
commit
694f44660f
5 changed files with 54 additions and 28 deletions
|
@ -1275,29 +1275,14 @@ func GetParticipantsIDsByIssueID(issueID int64) ([]int64, error) {
|
||||||
Find(&userIDs)
|
Find(&userIDs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetParticipantsByIssueID returns all users who are participated in comments of an issue.
|
// IsUserParticipantsOfIssue return true if user is participants of an issue
|
||||||
func GetParticipantsByIssueID(issueID int64) ([]*User, error) {
|
func IsUserParticipantsOfIssue(user *User, issue *Issue) bool {
|
||||||
return getParticipantsByIssueID(x, issueID)
|
userIDs, err := issue.getParticipantIDsByIssue(x)
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err.Error())
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
return util.IsInt64InSlice(user.ID, userIDs)
|
||||||
func getParticipantsByIssueID(e Engine, issueID int64) ([]*User, error) {
|
|
||||||
userIDs := make([]int64, 0, 5)
|
|
||||||
if err := e.Table("comment").Cols("poster_id").
|
|
||||||
Where("`comment`.issue_id = ?", issueID).
|
|
||||||
And("`comment`.type in (?,?,?)", CommentTypeComment, CommentTypeCode, CommentTypeReview).
|
|
||||||
And("`user`.is_active = ?", true).
|
|
||||||
And("`user`.prohibit_login = ?", false).
|
|
||||||
Join("INNER", "`user`", "`user`.id = `comment`.poster_id").
|
|
||||||
Distinct("poster_id").
|
|
||||||
Find(&userIDs); err != nil {
|
|
||||||
return nil, fmt.Errorf("get poster IDs: %v", err)
|
|
||||||
}
|
|
||||||
if len(userIDs) == 0 {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
users := make([]*User, 0, len(userIDs))
|
|
||||||
return users, e.In("id", userIDs).Find(&users)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateIssueMentions updates issue-user relations for mentioned users.
|
// UpdateIssueMentions updates issue-user relations for mentioned users.
|
||||||
|
@ -1691,6 +1676,28 @@ type DependencyInfo struct {
|
||||||
Repository `xorm:"extends"`
|
Repository `xorm:"extends"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getParticipantIDsByIssue returns all userIDs who are participated in comments of an issue and issue author
|
||||||
|
func (issue *Issue) getParticipantIDsByIssue(e Engine) ([]int64, error) {
|
||||||
|
if issue == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
userIDs := make([]int64, 0, 5)
|
||||||
|
if err := e.Table("comment").Cols("poster_id").
|
||||||
|
Where("`comment`.issue_id = ?", issue.ID).
|
||||||
|
And("`comment`.type in (?,?,?)", CommentTypeComment, CommentTypeCode, CommentTypeReview).
|
||||||
|
And("`user`.is_active = ?", true).
|
||||||
|
And("`user`.prohibit_login = ?", false).
|
||||||
|
Join("INNER", "`user`", "`user`.id = `comment`.poster_id").
|
||||||
|
Distinct("poster_id").
|
||||||
|
Find(&userIDs); err != nil {
|
||||||
|
return nil, fmt.Errorf("get poster IDs: %v", err)
|
||||||
|
}
|
||||||
|
if !util.IsInt64InSlice(issue.PosterID, userIDs) {
|
||||||
|
return append(userIDs, issue.PosterID), nil
|
||||||
|
}
|
||||||
|
return userIDs, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Get Blocked By Dependencies, aka all issues this issue is blocked by.
|
// Get Blocked By Dependencies, aka all issues this issue is blocked by.
|
||||||
func (issue *Issue) getBlockedByDependencies(e Engine) (issueDeps []*DependencyInfo, err error) {
|
func (issue *Issue) getBlockedByDependencies(e Engine) (issueDeps []*DependencyInfo, err error) {
|
||||||
return issueDeps, e.
|
return issueDeps, e.
|
||||||
|
|
|
@ -61,15 +61,17 @@ func TestGetIssuesByIDs(t *testing.T) {
|
||||||
testSuccess([]int64{1, 2, 3}, []int64{NonexistentID})
|
testSuccess([]int64{1, 2, 3}, []int64{NonexistentID})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetParticipantsByIssueID(t *testing.T) {
|
func TestGetParticipantIDsByIssue(t *testing.T) {
|
||||||
assert.NoError(t, PrepareTestDatabase())
|
assert.NoError(t, PrepareTestDatabase())
|
||||||
|
|
||||||
checkParticipants := func(issueID int64, userIDs []int) {
|
checkParticipants := func(issueID int64, userIDs []int) {
|
||||||
participants, err := GetParticipantsByIssueID(issueID)
|
issue, err := GetIssueByID(issueID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
participants, err := issue.getParticipantIDsByIssue(x)
|
||||||
if assert.NoError(t, err) {
|
if assert.NoError(t, err) {
|
||||||
participantsIDs := make([]int, len(participants))
|
participantsIDs := make([]int, len(participants))
|
||||||
for i, u := range participants {
|
for i, uid := range participants {
|
||||||
participantsIDs[i] = int(u.ID)
|
participantsIDs[i] = int(uid)
|
||||||
}
|
}
|
||||||
sort.Ints(participantsIDs)
|
sort.Ints(participantsIDs)
|
||||||
sort.Ints(userIDs)
|
sort.Ints(userIDs)
|
||||||
|
@ -81,7 +83,7 @@ func TestGetParticipantsByIssueID(t *testing.T) {
|
||||||
// User 2 only labeled issue1 (see fixtures/comment.yml)
|
// User 2 only labeled issue1 (see fixtures/comment.yml)
|
||||||
// Users 3 and 5 made actual comments (see fixtures/comment.yml)
|
// Users 3 and 5 made actual comments (see fixtures/comment.yml)
|
||||||
// User 3 is inactive, thus not active participant
|
// User 3 is inactive, thus not active participant
|
||||||
checkParticipants(1, []int{5})
|
checkParticipants(1, []int{1, 5})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIssue_ClearLabels(t *testing.T) {
|
func TestIssue_ClearLabels(t *testing.T) {
|
||||||
|
|
|
@ -159,6 +159,13 @@ func createOrUpdateIssueNotifications(e Engine, issueID, commentID int64, notifi
|
||||||
for _, id := range repoWatches {
|
for _, id := range repoWatches {
|
||||||
toNotify[id] = struct{}{}
|
toNotify[id] = struct{}{}
|
||||||
}
|
}
|
||||||
|
issueParticipants, err := issue.getParticipantIDsByIssue(e)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, id := range issueParticipants {
|
||||||
|
toNotify[id] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
// dont notify user who cause notification
|
// dont notify user who cause notification
|
||||||
delete(toNotify, notificationAuthorID)
|
delete(toNotify, notificationAuthorID)
|
||||||
|
|
|
@ -45,6 +45,16 @@ func IsStringInSlice(target string, slice []string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsInt64InSlice sequential searches if int64 exists in slice.
|
||||||
|
func IsInt64InSlice(target int64, slice []int64) bool {
|
||||||
|
for i := 0; i < len(slice); i++ {
|
||||||
|
if slice[i] == target {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// IsEqualSlice returns true if slices are equal.
|
// IsEqualSlice returns true if slices are equal.
|
||||||
func IsEqualSlice(target []string, source []string) bool {
|
func IsEqualSlice(target []string, source []string) bool {
|
||||||
if len(target) != len(source) {
|
if len(target) != len(source) {
|
||||||
|
|
|
@ -704,7 +704,7 @@ func ViewIssue(ctx *context.Context) {
|
||||||
iw = &models.IssueWatch{
|
iw = &models.IssueWatch{
|
||||||
UserID: ctx.User.ID,
|
UserID: ctx.User.ID,
|
||||||
IssueID: issue.ID,
|
IssueID: issue.ID,
|
||||||
IsWatching: models.IsWatching(ctx.User.ID, ctx.Repo.Repository.ID),
|
IsWatching: models.IsWatching(ctx.User.ID, ctx.Repo.Repository.ID) || models.IsUserParticipantsOfIssue(ctx.User, issue),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue