mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-02 20:06:06 +01:00 
			
		
		
		
	This PR split the `Board` into two parts. One is the struct has been renamed to `Column` and the second we have a `Template Type`. But to make it easier to review, this PR will not change the database schemas, they are just renames. The database schema changes could be in future PRs. --------- Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: yp05327 <576951401@qq.com>
		
			
				
	
	
		
			151 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			151 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// Copyright 2023 The Gitea Authors. All rights reserved.
 | 
						|
// SPDX-License-Identifier: MIT
 | 
						|
 | 
						|
package internal
 | 
						|
 | 
						|
import (
 | 
						|
	"code.gitea.io/gitea/models/db"
 | 
						|
	"code.gitea.io/gitea/modules/optional"
 | 
						|
	"code.gitea.io/gitea/modules/timeutil"
 | 
						|
)
 | 
						|
 | 
						|
// IndexerData data stored in the issue indexer
 | 
						|
type IndexerData struct {
 | 
						|
	ID       int64 `json:"id"`
 | 
						|
	RepoID   int64 `json:"repo_id"`
 | 
						|
	IsPublic bool  `json:"is_public"` // If the repo is public
 | 
						|
 | 
						|
	// Fields used for keyword searching
 | 
						|
	Title    string   `json:"title"`
 | 
						|
	Content  string   `json:"content"`
 | 
						|
	Comments []string `json:"comments"`
 | 
						|
 | 
						|
	// Fields used for filtering
 | 
						|
	IsPull             bool               `json:"is_pull"`
 | 
						|
	IsClosed           bool               `json:"is_closed"`
 | 
						|
	LabelIDs           []int64            `json:"label_ids"`
 | 
						|
	NoLabel            bool               `json:"no_label"` // True if LabelIDs is empty
 | 
						|
	MilestoneID        int64              `json:"milestone_id"`
 | 
						|
	ProjectID          int64              `json:"project_id"`
 | 
						|
	ProjectColumnID    int64              `json:"project_board_id"` // the key should be kept as project_board_id to keep compatible
 | 
						|
	PosterID           int64              `json:"poster_id"`
 | 
						|
	AssigneeID         int64              `json:"assignee_id"`
 | 
						|
	MentionIDs         []int64            `json:"mention_ids"`
 | 
						|
	ReviewedIDs        []int64            `json:"reviewed_ids"`
 | 
						|
	ReviewRequestedIDs []int64            `json:"review_requested_ids"`
 | 
						|
	SubscriberIDs      []int64            `json:"subscriber_ids"`
 | 
						|
	UpdatedUnix        timeutil.TimeStamp `json:"updated_unix"`
 | 
						|
 | 
						|
	// Fields used for sorting
 | 
						|
	// UpdatedUnix is both used for filtering and sorting.
 | 
						|
	// ID is used for sorting too, to make the sorting stable.
 | 
						|
	CreatedUnix  timeutil.TimeStamp `json:"created_unix"`
 | 
						|
	DeadlineUnix timeutil.TimeStamp `json:"deadline_unix"`
 | 
						|
	CommentCount int64              `json:"comment_count"`
 | 
						|
}
 | 
						|
 | 
						|
// Match represents on search result
 | 
						|
type Match struct {
 | 
						|
	ID    int64   `json:"id"`
 | 
						|
	Score float64 `json:"score"`
 | 
						|
}
 | 
						|
 | 
						|
// SearchResult represents search results
 | 
						|
type SearchResult struct {
 | 
						|
	Total int64
 | 
						|
	Hits  []Match
 | 
						|
}
 | 
						|
 | 
						|
// SearchOptions represents search options.
 | 
						|
//
 | 
						|
// It has a slightly different design from database query options.
 | 
						|
// In database query options, a field is never a pointer, so it could be confusing when it's zero value:
 | 
						|
// Do you want to find data with a field value of 0, or do you not specify the field in the options?
 | 
						|
// To avoid this confusion, db introduced db.NoConditionID(-1).
 | 
						|
// So zero value means the field is not specified in the search options, and db.NoConditionID means "== 0" or "id NOT IN (SELECT id FROM ...)"
 | 
						|
// It's still not ideal, it trapped developers many times.
 | 
						|
// And sometimes -1 could be a valid value, like issue ID, negative numbers indicate exclusion.
 | 
						|
// Since db.NoConditionID is for "db" (the package name is db), it makes sense not to use it in the indexer:
 | 
						|
// Why do bleve/elasticsearch/meilisearch indexers need to know about db.NoConditionID?
 | 
						|
// So in SearchOptions, we use pointer for fields which could be not specified,
 | 
						|
// and always use the value to filter if it's not nil, even if it's zero or negative.
 | 
						|
// It can handle almost all cases, if there is an exception, we can add a new field, like NoLabelOnly.
 | 
						|
// Unfortunately, we still use db for the indexer and have to convert between db.NoConditionID and nil for legacy reasons.
 | 
						|
type SearchOptions struct {
 | 
						|
	Keyword string // keyword to search
 | 
						|
 | 
						|
	IsFuzzyKeyword bool // if false the levenshtein distance is 0
 | 
						|
 | 
						|
	RepoIDs   []int64 // repository IDs which the issues belong to
 | 
						|
	AllPublic bool    // if include all public repositories
 | 
						|
 | 
						|
	IsPull   optional.Option[bool] // if the issues is a pull request
 | 
						|
	IsClosed optional.Option[bool] // if the issues is closed
 | 
						|
 | 
						|
	IncludedLabelIDs    []int64 // labels the issues have
 | 
						|
	ExcludedLabelIDs    []int64 // labels the issues don't have
 | 
						|
	IncludedAnyLabelIDs []int64 // labels the issues have at least one. It will be ignored if IncludedLabelIDs is not empty. It's an uncommon filter, but it has been supported accidentally by issues.IssuesOptions.IncludedLabelNames.
 | 
						|
	NoLabelOnly         bool    // if the issues have no label, if true, IncludedLabelIDs and ExcludedLabelIDs, IncludedAnyLabelIDs will be ignored
 | 
						|
 | 
						|
	MilestoneIDs []int64 // milestones the issues have
 | 
						|
 | 
						|
	ProjectID       optional.Option[int64] // project the issues belong to
 | 
						|
	ProjectColumnID optional.Option[int64] // project column the issues belong to
 | 
						|
 | 
						|
	PosterID optional.Option[int64] // poster of the issues
 | 
						|
 | 
						|
	AssigneeID optional.Option[int64] // assignee of the issues, zero means no assignee
 | 
						|
 | 
						|
	MentionID optional.Option[int64] // mentioned user of the issues
 | 
						|
 | 
						|
	ReviewedID        optional.Option[int64] // reviewer of the issues
 | 
						|
	ReviewRequestedID optional.Option[int64] // requested reviewer of the issues
 | 
						|
 | 
						|
	SubscriberID optional.Option[int64] // subscriber of the issues
 | 
						|
 | 
						|
	UpdatedAfterUnix  optional.Option[int64]
 | 
						|
	UpdatedBeforeUnix optional.Option[int64]
 | 
						|
 | 
						|
	Paginator *db.ListOptions
 | 
						|
 | 
						|
	SortBy SortBy // sort by field
 | 
						|
}
 | 
						|
 | 
						|
// Copy returns a copy of the options.
 | 
						|
// Be careful, it's not a deep copy, so `SearchOptions.RepoIDs = {...}` is OK while `SearchOptions.RepoIDs[0] = ...` is not.
 | 
						|
func (o *SearchOptions) Copy(edit ...func(options *SearchOptions)) *SearchOptions {
 | 
						|
	if o == nil {
 | 
						|
		return nil
 | 
						|
	}
 | 
						|
	v := *o
 | 
						|
	for _, e := range edit {
 | 
						|
		e(&v)
 | 
						|
	}
 | 
						|
	return &v
 | 
						|
}
 | 
						|
 | 
						|
type SortBy string
 | 
						|
 | 
						|
const (
 | 
						|
	SortByCreatedDesc  SortBy = "-created_unix"
 | 
						|
	SortByUpdatedDesc  SortBy = "-updated_unix"
 | 
						|
	SortByCommentsDesc SortBy = "-comment_count"
 | 
						|
	SortByDeadlineDesc SortBy = "-deadline_unix"
 | 
						|
	SortByCreatedAsc   SortBy = "created_unix"
 | 
						|
	SortByUpdatedAsc   SortBy = "updated_unix"
 | 
						|
	SortByCommentsAsc  SortBy = "comment_count"
 | 
						|
	SortByDeadlineAsc  SortBy = "deadline_unix"
 | 
						|
	// Unsupported sort types which are supported by issues.IssuesOptions.SortType:
 | 
						|
	//
 | 
						|
	//  - "priorityrepo":
 | 
						|
	//                    It's impossible to support it in the indexer.
 | 
						|
	//                    It is based on the specified repository in the request, so we cannot add static field to the indexer.
 | 
						|
	//                    If we do something like that query the issues in the specified repository first then append other issues,
 | 
						|
	//                    it will break the pagination.
 | 
						|
	//
 | 
						|
	// - "project-column-sorting":
 | 
						|
	//                    Although it's possible to support it by adding project.ProjectIssue.Sorting to the indexer,
 | 
						|
	//                    but what if the issue belongs to multiple projects?
 | 
						|
	//                    Since it's unsupported to search issues with keyword in project page, we don't need to support it.
 | 
						|
)
 |