예제 #1
0
파일: issue.go 프로젝트: yweber/gogs
// GetIssueStats returns issue statistic information by given conditions.
func GetIssueStats(opts *IssueStatsOptions) *IssueStats {
	stats := &IssueStats{}

	countSession := func(opts *IssueStatsOptions) *xorm.Session {
		sess := x.Where("issue.repo_id = ?", opts.RepoID).And("is_pull = ?", opts.IsPull)

		if len(opts.Labels) > 0 && opts.Labels != "0" {
			labelIDs := base.StringsToInt64s(strings.Split(opts.Labels, ","))
			if len(labelIDs) > 0 {
				sess.Join("INNER", "issue_label", "issue.id = issue_id").In("label_id", labelIDs)
			}
		}

		if opts.MilestoneID > 0 {
			sess.And("issue.milestone_id = ?", opts.MilestoneID)
		}

		if opts.AssigneeID > 0 {
			sess.And("assignee_id = ?", opts.AssigneeID)
		}

		return sess
	}

	switch opts.FilterMode {
	case FM_ALL, FM_ASSIGN:
		stats.OpenCount, _ = countSession(opts).
			And("is_closed = ?", false).
			Count(&Issue{})

		stats.ClosedCount, _ = countSession(opts).
			And("is_closed = ?", true).
			Count(&Issue{})
	case FM_CREATE:
		stats.OpenCount, _ = countSession(opts).
			And("poster_id = ?", opts.UserID).
			And("is_closed = ?", false).
			Count(&Issue{})

		stats.ClosedCount, _ = countSession(opts).
			And("poster_id = ?", opts.UserID).
			And("is_closed = ?", true).
			Count(&Issue{})
	case FM_MENTION:
		stats.OpenCount, _ = countSession(opts).
			Join("INNER", "issue_user", "issue.id = issue_user.issue_id").
			And("issue_user.uid = ?", opts.UserID).
			And("issue_user.is_mentioned = ?", true).
			And("issue.is_closed = ?", false).
			Count(&Issue{})

		stats.ClosedCount, _ = countSession(opts).
			Join("INNER", "issue_user", "issue.id = issue_user.issue_id").
			And("issue_user.uid = ?", opts.UserID).
			And("issue_user.is_mentioned = ?", true).
			And("issue.is_closed = ?", true).
			Count(&Issue{})
	}
	return stats
}
예제 #2
0
파일: issue.go 프로젝트: rothgar/gogs
func ValidateRepoMetas(ctx *middleware.Context, form auth.CreateIssueForm) ([]int64, int64, int64) {
	var (
		repo = ctx.Repo.Repository
		err  error
	)

	labels := RetrieveRepoMetas(ctx, ctx.Repo.Repository)
	if ctx.Written() {
		return nil, 0, 0
	}

	if !ctx.Repo.IsAdmin() {
		return nil, 0, 0
	}

	// Check labels.
	labelIDs := base.StringsToInt64s(strings.Split(form.LabelIDs, ","))
	labelIDMark := base.Int64sToMap(labelIDs)
	hasSelected := false
	for i := range labels {
		if labelIDMark[labels[i].ID] {
			labels[i].IsChecked = true
			hasSelected = true
		}
	}
	ctx.Data["HasSelectedLabel"] = hasSelected
	ctx.Data["label_ids"] = form.LabelIDs
	ctx.Data["Labels"] = labels

	// Check milestone.
	milestoneID := form.MilestoneID
	if milestoneID > 0 {
		ctx.Data["Milestone"], err = repo.GetMilestoneByID(milestoneID)
		if err != nil {
			ctx.Handle(500, "GetMilestoneByID: %v", err)
			return nil, 0, 0
		}
		ctx.Data["milestone_id"] = milestoneID
	}

	// Check assignee.
	assigneeID := form.AssigneeID
	if assigneeID > 0 {
		ctx.Data["Assignee"], err = repo.GetAssigneeByID(assigneeID)
		if err != nil {
			ctx.Handle(500, "GetAssigneeByID: %v", err)
			return nil, 0, 0
		}
		ctx.Data["assignee_id"] = assigneeID
	}

	return labelIDs, milestoneID, assigneeID
}
예제 #3
0
파일: issue.go 프로젝트: chadoe/gogs
// Issues returns a list of issues by given conditions.
func Issues(opts *IssuesOptions) ([]*Issue, error) {
	sess := x.Limit(setting.IssuePagingNum, (opts.Page-1)*setting.IssuePagingNum)

	if opts.RepoID > 0 {
		sess.Where("issue.repo_id=?", opts.RepoID).And("issue.is_closed=?", opts.IsClosed)
	} else if opts.RepoIDs != nil {
		// In case repository IDs are provided but actually no repository has issue.
		if len(opts.RepoIDs) == 0 {
			return make([]*Issue, 0), nil
		}
		sess.Where("issue.repo_id IN ("+strings.Join(base.Int64sToStrings(opts.RepoIDs), ",")+")").And("issue.is_closed=?", opts.IsClosed)
	} else {
		sess.Where("issue.is_closed=?", opts.IsClosed)
	}

	if opts.AssigneeID > 0 {
		sess.And("issue.assignee_id=?", opts.AssigneeID)
	} else if opts.PosterID > 0 {
		sess.And("issue.poster_id=?", opts.PosterID)
	}

	if opts.MilestoneID > 0 {
		sess.And("issue.milestone_id=?", opts.MilestoneID)
	}

	sess.And("issue.is_pull=?", opts.IsPull)

	switch opts.SortType {
	case "oldest":
		sess.Asc("created")
	case "recentupdate":
		sess.Desc("updated")
	case "leastupdate":
		sess.Asc("updated")
	case "mostcomment":
		sess.Desc("num_comments")
	case "leastcomment":
		sess.Asc("num_comments")
	case "priority":
		sess.Desc("priority")
	default:
		sess.Desc("created")
	}

	labelIDs := base.StringsToInt64s(strings.Split(opts.Labels, ","))
	if len(labelIDs) > 0 {
		validJoin := false
		queryStr := "issue.id=issue_label.issue_id"
		for _, id := range labelIDs {
			if id == 0 {
				continue
			}
			validJoin = true
			queryStr += " AND issue_label.label_id=" + com.ToStr(id)
		}
		if validJoin {
			sess.Join("INNER", "issue_label", queryStr)
		}
	}

	if opts.IsMention {
		queryStr := "issue.id=issue_user.issue_id AND issue_user.is_mentioned=1"
		if opts.UserID > 0 {
			queryStr += " AND issue_user.uid=" + com.ToStr(opts.UserID)
		}
		sess.Join("INNER", "issue_user", queryStr)
	}

	issues := make([]*Issue, 0, setting.IssuePagingNum)
	return issues, sess.Find(&issues)
}
예제 #4
0
파일: issue.go 프로젝트: yweber/gogs
// Issues returns a list of issues by given conditions.
func Issues(opts *IssuesOptions) ([]*Issue, error) {
	if opts.Page <= 0 {
		opts.Page = 1
	}

	sess := x.Limit(setting.UI.IssuePagingNum, (opts.Page-1)*setting.UI.IssuePagingNum)

	if opts.RepoID > 0 {
		sess.Where("issue.repo_id=?", opts.RepoID).And("issue.is_closed=?", opts.IsClosed)
	} else if opts.RepoIDs != nil {
		// In case repository IDs are provided but actually no repository has issue.
		if len(opts.RepoIDs) == 0 {
			return make([]*Issue, 0), nil
		}
		sess.In("issue.repo_id", base.Int64sToStrings(opts.RepoIDs)).And("issue.is_closed=?", opts.IsClosed)
	} else {
		sess.Where("issue.is_closed=?", opts.IsClosed)
	}

	if opts.AssigneeID > 0 {
		sess.And("issue.assignee_id=?", opts.AssigneeID)
	} else if opts.PosterID > 0 {
		sess.And("issue.poster_id=?", opts.PosterID)
	}

	if opts.MilestoneID > 0 {
		sess.And("issue.milestone_id=?", opts.MilestoneID)
	}

	sess.And("issue.is_pull=?", opts.IsPull)

	switch opts.SortType {
	case "oldest":
		sess.Asc("issue.created_unix")
	case "recentupdate":
		sess.Desc("issue.updated_unix")
	case "leastupdate":
		sess.Asc("issue.updated_unix")
	case "mostcomment":
		sess.Desc("issue.num_comments")
	case "leastcomment":
		sess.Asc("issue.num_comments")
	case "priority":
		sess.Desc("issue.priority")
	default:
		sess.Desc("issue.created_unix")
	}

	if len(opts.Labels) > 0 && opts.Labels != "0" {
		labelIDs := base.StringsToInt64s(strings.Split(opts.Labels, ","))
		if len(labelIDs) > 0 {
			sess.Join("INNER", "issue_label", "issue.id = issue_label.issue_id").In("issue_label.label_id", labelIDs)
		}
	}

	if opts.IsMention {
		sess.Join("INNER", "issue_user", "issue.id = issue_user.issue_id").And("issue_user.is_mentioned = ?", true)

		if opts.UserID > 0 {
			sess.And("issue_user.uid = ?", opts.UserID)
		}
	}

	issues := make([]*Issue, 0, setting.UI.IssuePagingNum)
	return issues, sess.Find(&issues)
}
예제 #5
0
파일: issue.go 프로젝트: peterhadlaw/gogs
func NewIssuePost(ctx *middleware.Context, form auth.CreateIssueForm) {
	ctx.Data["Title"] = ctx.Tr("repo.issues.new")
	ctx.Data["PageIsIssueList"] = true
	ctx.Data["RequireDropzone"] = true
	ctx.Data["IsAttachmentEnabled"] = setting.AttachmentEnabled
	ctx.Data["AttachmentAllowedTypes"] = setting.AttachmentAllowedTypes
	ctx.Data["AttachmentMaxFiles"] = setting.AttachmentMaxFiles

	var (
		repo        = ctx.Repo.Repository
		labelIDs    []int64
		milestoneID int64
		assigneeID  int64
		attachments []string
	)
	if ctx.User.IsAdmin {
		// Check labels.
		labelIDs = base.StringsToInt64s(strings.Split(form.LabelIDs, ","))
		labelIDMark := base.Int64sToMap(labelIDs)
		labels, err := models.GetLabelsByRepoID(repo.ID)
		if err != nil {
			ctx.Handle(500, "GetLabelsByRepoID: %v", err)
			return
		}
		hasSelected := false
		for i := range labels {
			if labelIDMark[labels[i].ID] {
				labels[i].IsChecked = true
				hasSelected = true
			}
		}
		ctx.Data["HasSelectedLabel"] = hasSelected
		ctx.Data["label_ids"] = form.LabelIDs
		ctx.Data["Labels"] = labels

		// Check milestone.
		milestoneID = form.MilestoneID
		if milestoneID > 0 {
			ctx.Data["OpenMilestones"], err = models.GetMilestones(repo.ID, -1, false)
			if err != nil {
				ctx.Handle(500, "GetMilestones: %v", err)
				return
			}
			ctx.Data["ClosedMilestones"], err = models.GetMilestones(repo.ID, -1, true)
			if err != nil {
				ctx.Handle(500, "GetMilestones: %v", err)
				return
			}
			ctx.Data["Milestone"], err = repo.GetMilestoneByID(milestoneID)
			if err != nil {
				ctx.Handle(500, "GetMilestoneByID: %v", err)
				return
			}
			ctx.Data["milestone_id"] = milestoneID
		}

		// Check assignee.
		assigneeID = form.AssigneeID
		if assigneeID > 0 {
			ctx.Data["Assignees"], err = repo.GetAssignees()
			if err != nil {
				ctx.Handle(500, "GetAssignees: %v", err)
				return
			}
			ctx.Data["Assignee"], err = repo.GetAssigneeByID(assigneeID)
			if err != nil {
				ctx.Handle(500, "GetAssigneeByID: %v", err)
				return
			}
			ctx.Data["assignee_id"] = assigneeID
		}
	}

	if setting.AttachmentEnabled {
		attachments = ctx.QueryStrings("attachments")
	}

	if ctx.HasError() {
		ctx.HTML(200, ISSUE_NEW)
		return
	}

	issue := &models.Issue{
		RepoID:      ctx.Repo.Repository.ID,
		Index:       int64(repo.NumIssues) + 1,
		Name:        form.Title,
		PosterID:    ctx.User.Id,
		Poster:      ctx.User,
		MilestoneID: milestoneID,
		AssigneeID:  assigneeID,
		Content:     form.Content,
	}
	if err := models.NewIssue(repo, issue, labelIDs, attachments); err != nil {
		ctx.Handle(500, "NewIssue", err)
		return
	}

	// Update mentions.
	mentions := base.MentionPattern.FindAllString(issue.Content, -1)
	if len(mentions) > 0 {
		for i := range mentions {
			mentions[i] = mentions[i][1:]
		}

		if err := models.UpdateMentions(mentions, issue.ID); err != nil {
			ctx.Handle(500, "UpdateMentions", err)
			return
		}
	}

	// Mail watchers and mentions.
	if setting.Service.EnableNotifyMail {
		tos, err := mailer.SendIssueNotifyMail(ctx.User, ctx.Repo.Owner, ctx.Repo.Repository, issue)
		if err != nil {
			ctx.Handle(500, "SendIssueNotifyMail", err)
			return
		}

		tos = append(tos, ctx.User.LowerName)
		newTos := make([]string, 0, len(mentions))
		for _, m := range mentions {
			if com.IsSliceContainsStr(tos, m) {
				continue
			}

			newTos = append(newTos, m)
		}
		if err = mailer.SendIssueMentionMail(ctx.Render, ctx.User, ctx.Repo.Owner,
			ctx.Repo.Repository, issue, models.GetUserEmailsByNames(newTos)); err != nil {
			ctx.Handle(500, "SendIssueMentionMail", err)
			return
		}
	}

	log.Trace("Issue created: %d/%d", ctx.Repo.Repository.ID, issue.ID)
	ctx.Redirect(ctx.Repo.RepoLink + "/issues/" + com.ToStr(issue.Index))
}
예제 #6
0
파일: issue.go 프로젝트: noikiy/gogs
// Issues returns a list of issues by given conditions.
func Issues(uid, assigneeID, repoID, posterID, milestoneID int64, page int, isClosed, isMention bool, labels, sortType string) ([]*Issue, error) {
	sess := x.Limit(setting.IssuePagingNum, (page-1)*setting.IssuePagingNum)

	if repoID > 0 {
		sess.Where("issue.repo_id=?", repoID).And("issue.is_closed=?", isClosed)
	} else {
		sess.Where("issue.is_closed=?", isClosed)
	}

	if assigneeID > 0 {
		sess.And("issue.assignee_id=?", assigneeID)
	} else if posterID > 0 {
		sess.And("issue.poster_id=?", posterID)
	}

	if milestoneID > 0 {
		sess.And("issue.milestone_id=?", milestoneID)
	}

	switch sortType {
	case "oldest":
		sess.Asc("created")
	case "recentupdate":
		sess.Desc("updated")
	case "leastupdate":
		sess.Asc("updated")
	case "mostcomment":
		sess.Desc("num_comments")
	case "leastcomment":
		sess.Asc("num_comments")
	case "priority":
		sess.Desc("priority")
	default:
		sess.Desc("created")
	}

	labelIDs := base.StringsToInt64s(strings.Split(labels, ","))
	if len(labelIDs) > 0 {
		validJoin := false
		queryStr := "issue.id=issue_label.issue_id"
		for _, id := range labelIDs {
			if id == 0 {
				continue
			}
			validJoin = true
			queryStr += " AND issue_label.label_id=" + com.ToStr(id)
		}
		if validJoin {
			sess.Join("INNER", "issue_label", queryStr)
		}
	}

	if isMention {
		queryStr := "issue.id=issue_user.issue_id AND issue_user.is_mentioned=1"
		if uid > 0 {
			queryStr += " AND issue_user.uid=" + com.ToStr(uid)
		}
		sess.Join("INNER", "issue_user", queryStr)
	}

	issues := make([]*Issue, 0, setting.IssuePagingNum)
	return issues, sess.Find(&issues)
}