mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 21:16:26 +01:00 
			
		
		
		
	Enable/disable owner and repo projects independently (#28805)
Part of #23318 Add menu in repo settings to allow for repo admin to decide not just if projects are enabled or disabled per repo, but also which kind of projects (repo-level/owner-level) are enabled. If repo projects disabled, don't show the projects tab.  --------- Co-authored-by: delvh <dev.lh@web.de>
This commit is contained in:
		
							parent
							
								
									8553b4600e
								
							
						
					
					
						commit
						fe6792dff3
					
				@ -520,6 +520,7 @@
 | 
			
		||||
  id: 75
 | 
			
		||||
  repo_id: 1
 | 
			
		||||
  type: 8
 | 
			
		||||
  config: "{\"ProjectsMode\":\"all\"}"
 | 
			
		||||
  created_unix: 946684810
 | 
			
		||||
 | 
			
		||||
-
 | 
			
		||||
@ -650,12 +651,6 @@
 | 
			
		||||
  type: 2
 | 
			
		||||
  created_unix: 946684810
 | 
			
		||||
 | 
			
		||||
-
 | 
			
		||||
  id: 98
 | 
			
		||||
  repo_id: 1
 | 
			
		||||
  type: 8
 | 
			
		||||
  created_unix: 946684810
 | 
			
		||||
 | 
			
		||||
-
 | 
			
		||||
  id: 99
 | 
			
		||||
  repo_id: 1
 | 
			
		||||
 | 
			
		||||
@ -411,6 +411,11 @@ func (repo *Repository) MustGetUnit(ctx context.Context, tp unit.Type) *RepoUnit
 | 
			
		||||
			Type:   tp,
 | 
			
		||||
			Config: new(ActionsConfig),
 | 
			
		||||
		}
 | 
			
		||||
	} else if tp == unit.TypeProjects {
 | 
			
		||||
		return &RepoUnit{
 | 
			
		||||
			Type:   tp,
 | 
			
		||||
			Config: new(ProjectsConfig),
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &RepoUnit{
 | 
			
		||||
 | 
			
		||||
@ -202,6 +202,53 @@ func (cfg *ActionsConfig) ToDB() ([]byte, error) {
 | 
			
		||||
	return json.Marshal(cfg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ProjectsMode represents the projects enabled for a repository
 | 
			
		||||
type ProjectsMode string
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// ProjectsModeRepo allows only repo-level projects
 | 
			
		||||
	ProjectsModeRepo ProjectsMode = "repo"
 | 
			
		||||
	// ProjectsModeOwner allows only owner-level projects
 | 
			
		||||
	ProjectsModeOwner ProjectsMode = "owner"
 | 
			
		||||
	// ProjectsModeAll allows both kinds of projects
 | 
			
		||||
	ProjectsModeAll ProjectsMode = "all"
 | 
			
		||||
	// ProjectsModeNone doesn't allow projects
 | 
			
		||||
	ProjectsModeNone ProjectsMode = "none"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ProjectsConfig describes projects config
 | 
			
		||||
type ProjectsConfig struct {
 | 
			
		||||
	ProjectsMode ProjectsMode
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FromDB fills up a ProjectsConfig from serialized format.
 | 
			
		||||
func (cfg *ProjectsConfig) FromDB(bs []byte) error {
 | 
			
		||||
	return json.UnmarshalHandleDoubleEncode(bs, &cfg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToDB exports a ProjectsConfig to a serialized format.
 | 
			
		||||
func (cfg *ProjectsConfig) ToDB() ([]byte, error) {
 | 
			
		||||
	return json.Marshal(cfg)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cfg *ProjectsConfig) GetProjectsMode() ProjectsMode {
 | 
			
		||||
	if cfg.ProjectsMode != "" {
 | 
			
		||||
		return cfg.ProjectsMode
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return ProjectsModeNone
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (cfg *ProjectsConfig) IsProjectsAllowed(m ProjectsMode) bool {
 | 
			
		||||
	projectsMode := cfg.GetProjectsMode()
 | 
			
		||||
 | 
			
		||||
	if m == ProjectsModeNone {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return projectsMode == m || projectsMode == ProjectsModeAll
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// BeforeSet is invoked from XORM before setting the value of a field of this object.
 | 
			
		||||
func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) {
 | 
			
		||||
	switch colName {
 | 
			
		||||
@ -217,7 +264,9 @@ func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) {
 | 
			
		||||
			r.Config = new(IssuesConfig)
 | 
			
		||||
		case unit.TypeActions:
 | 
			
		||||
			r.Config = new(ActionsConfig)
 | 
			
		||||
		case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypeProjects, unit.TypePackages:
 | 
			
		||||
		case unit.TypeProjects:
 | 
			
		||||
			r.Config = new(ProjectsConfig)
 | 
			
		||||
		case unit.TypeCode, unit.TypeReleases, unit.TypeWiki, unit.TypePackages:
 | 
			
		||||
			fallthrough
 | 
			
		||||
		default:
 | 
			
		||||
			r.Config = new(UnitConfig)
 | 
			
		||||
@ -265,6 +314,11 @@ func (r *RepoUnit) ActionsConfig() *ActionsConfig {
 | 
			
		||||
	return r.Config.(*ActionsConfig)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ProjectsConfig returns config for unit.ProjectsConfig
 | 
			
		||||
func (r *RepoUnit) ProjectsConfig() *ProjectsConfig {
 | 
			
		||||
	return r.Config.(*ProjectsConfig)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getUnitsByRepoID(ctx context.Context, repoID int64) (units []*RepoUnit, err error) {
 | 
			
		||||
	var tmpUnits []*RepoUnit
 | 
			
		||||
	if err := db.GetEngine(ctx).Where("repo_id = ?", repoID).Find(&tmpUnits); err != nil {
 | 
			
		||||
 | 
			
		||||
@ -93,6 +93,12 @@ func CreateRepositoryByExample(ctx context.Context, doer, u *user_model.User, re
 | 
			
		||||
					AllowRebaseUpdate: true,
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
		} else if tp == unit.TypeProjects {
 | 
			
		||||
			units = append(units, repo_model.RepoUnit{
 | 
			
		||||
				RepoID: repo.ID,
 | 
			
		||||
				Type:   tp,
 | 
			
		||||
				Config: &repo_model.ProjectsConfig{ProjectsMode: repo_model.ProjectsModeAll},
 | 
			
		||||
			})
 | 
			
		||||
		} else {
 | 
			
		||||
			units = append(units, repo_model.RepoUnit{
 | 
			
		||||
				RepoID: repo.ID,
 | 
			
		||||
 | 
			
		||||
@ -90,6 +90,7 @@ type Repository struct {
 | 
			
		||||
	ExternalWiki                  *ExternalWiki    `json:"external_wiki,omitempty"`
 | 
			
		||||
	HasPullRequests               bool             `json:"has_pull_requests"`
 | 
			
		||||
	HasProjects                   bool             `json:"has_projects"`
 | 
			
		||||
	ProjectsMode                  string           `json:"projects_mode"`
 | 
			
		||||
	HasReleases                   bool             `json:"has_releases"`
 | 
			
		||||
	HasPackages                   bool             `json:"has_packages"`
 | 
			
		||||
	HasActions                    bool             `json:"has_actions"`
 | 
			
		||||
@ -180,6 +181,8 @@ type EditRepoOption struct {
 | 
			
		||||
	HasPullRequests *bool `json:"has_pull_requests,omitempty"`
 | 
			
		||||
	// either `true` to enable project unit, or `false` to disable them.
 | 
			
		||||
	HasProjects *bool `json:"has_projects,omitempty"`
 | 
			
		||||
	// `repo` to only allow repo-level projects, `owner` to only allow owner projects, `all` to allow both.
 | 
			
		||||
	ProjectsMode *string `json:"projects_mode,omitempty" binding:"In(repo,owner,all)"`
 | 
			
		||||
	// either `true` to enable releases unit, or `false` to disable them.
 | 
			
		||||
	HasReleases *bool `json:"has_releases,omitempty"`
 | 
			
		||||
	// either `true` to enable packages unit, or `false` to disable them.
 | 
			
		||||
 | 
			
		||||
@ -2090,7 +2090,11 @@ settings.pulls.default_delete_branch_after_merge = Delete pull request branch af
 | 
			
		||||
settings.pulls.default_allow_edits_from_maintainers = Allow edits from maintainers by default
 | 
			
		||||
settings.releases_desc = Enable Repository Releases
 | 
			
		||||
settings.packages_desc = Enable Repository Packages Registry
 | 
			
		||||
settings.projects_desc = Enable Repository Projects
 | 
			
		||||
settings.projects_desc = Enable Projects
 | 
			
		||||
settings.projects_mode_desc = Projects Mode (which kinds of projects to show)
 | 
			
		||||
settings.projects_mode_repo = Repo projects only
 | 
			
		||||
settings.projects_mode_owner = Only user or org projects
 | 
			
		||||
settings.projects_mode_all = All projects
 | 
			
		||||
settings.actions_desc = Enable Repository Actions
 | 
			
		||||
settings.admin_settings = Administrator Settings
 | 
			
		||||
settings.admin_enable_health_check = Enable Repository Health Checks (git fsck)
 | 
			
		||||
 | 
			
		||||
@ -944,13 +944,33 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.HasProjects != nil && !unit_model.TypeProjects.UnitGlobalDisabled() {
 | 
			
		||||
		if *opts.HasProjects {
 | 
			
		||||
	currHasProjects := repo.UnitEnabled(ctx, unit_model.TypeProjects)
 | 
			
		||||
	newHasProjects := currHasProjects
 | 
			
		||||
	if opts.HasProjects != nil {
 | 
			
		||||
		newHasProjects = *opts.HasProjects
 | 
			
		||||
	}
 | 
			
		||||
	if currHasProjects || newHasProjects {
 | 
			
		||||
		if newHasProjects && !unit_model.TypeProjects.UnitGlobalDisabled() {
 | 
			
		||||
			unit, err := repo.GetUnit(ctx, unit_model.TypeProjects)
 | 
			
		||||
			var config *repo_model.ProjectsConfig
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				config = &repo_model.ProjectsConfig{
 | 
			
		||||
					ProjectsMode: repo_model.ProjectsModeAll,
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				config = unit.ProjectsConfig()
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if opts.ProjectsMode != nil {
 | 
			
		||||
				config.ProjectsMode = repo_model.ProjectsMode(*opts.ProjectsMode)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			units = append(units, repo_model.RepoUnit{
 | 
			
		||||
				RepoID: repo.ID,
 | 
			
		||||
				Type:   unit_model.TypeProjects,
 | 
			
		||||
				Config: config,
 | 
			
		||||
			})
 | 
			
		||||
		} else {
 | 
			
		||||
		} else if !newHasProjects && !unit_model.TypeProjects.UnitGlobalDisabled() {
 | 
			
		||||
			deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeProjects)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@ -587,52 +587,63 @@ func retrieveProjects(ctx *context.Context, repo *repo_model.Repository) {
 | 
			
		||||
	if repo.Owner.IsOrganization() {
 | 
			
		||||
		repoOwnerType = project_model.TypeOrganization
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	projectsUnit := repo.MustGetUnit(ctx, unit.TypeProjects)
 | 
			
		||||
 | 
			
		||||
	var openProjects []*project_model.Project
 | 
			
		||||
	var closedProjects []*project_model.Project
 | 
			
		||||
	var err error
 | 
			
		||||
	projects, err := db.Find[project_model.Project](ctx, project_model.SearchOptions{
 | 
			
		||||
		ListOptions: db.ListOptionsAll,
 | 
			
		||||
		RepoID:      repo.ID,
 | 
			
		||||
		IsClosed:    optional.Some(false),
 | 
			
		||||
		Type:        project_model.TypeRepository,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("GetProjects", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	projects2, err := db.Find[project_model.Project](ctx, project_model.SearchOptions{
 | 
			
		||||
		ListOptions: db.ListOptionsAll,
 | 
			
		||||
		OwnerID:     repo.OwnerID,
 | 
			
		||||
		IsClosed:    optional.Some(false),
 | 
			
		||||
		Type:        repoOwnerType,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("GetProjects", err)
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	if projectsUnit.ProjectsConfig().IsProjectsAllowed(repo_model.ProjectsModeRepo) {
 | 
			
		||||
		openProjects, err = db.Find[project_model.Project](ctx, project_model.SearchOptions{
 | 
			
		||||
			ListOptions: db.ListOptionsAll,
 | 
			
		||||
			RepoID:      repo.ID,
 | 
			
		||||
			IsClosed:    optional.Some(false),
 | 
			
		||||
			Type:        project_model.TypeRepository,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.ServerError("GetProjects", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		closedProjects, err = db.Find[project_model.Project](ctx, project_model.SearchOptions{
 | 
			
		||||
			ListOptions: db.ListOptionsAll,
 | 
			
		||||
			RepoID:      repo.ID,
 | 
			
		||||
			IsClosed:    optional.Some(true),
 | 
			
		||||
			Type:        project_model.TypeRepository,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.ServerError("GetProjects", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Data["OpenProjects"] = append(projects, projects2...)
 | 
			
		||||
 | 
			
		||||
	projects, err = db.Find[project_model.Project](ctx, project_model.SearchOptions{
 | 
			
		||||
		ListOptions: db.ListOptionsAll,
 | 
			
		||||
		RepoID:      repo.ID,
 | 
			
		||||
		IsClosed:    optional.Some(true),
 | 
			
		||||
		Type:        project_model.TypeRepository,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("GetProjects", err)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	projects2, err = db.Find[project_model.Project](ctx, project_model.SearchOptions{
 | 
			
		||||
		ListOptions: db.ListOptionsAll,
 | 
			
		||||
		OwnerID:     repo.OwnerID,
 | 
			
		||||
		IsClosed:    optional.Some(true),
 | 
			
		||||
		Type:        repoOwnerType,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		ctx.ServerError("GetProjects", err)
 | 
			
		||||
		return
 | 
			
		||||
	if projectsUnit.ProjectsConfig().IsProjectsAllowed(repo_model.ProjectsModeOwner) {
 | 
			
		||||
		openProjects2, err := db.Find[project_model.Project](ctx, project_model.SearchOptions{
 | 
			
		||||
			ListOptions: db.ListOptionsAll,
 | 
			
		||||
			OwnerID:     repo.OwnerID,
 | 
			
		||||
			IsClosed:    optional.Some(false),
 | 
			
		||||
			Type:        repoOwnerType,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.ServerError("GetProjects", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		openProjects = append(openProjects, openProjects2...)
 | 
			
		||||
		closedProjects2, err := db.Find[project_model.Project](ctx, project_model.SearchOptions{
 | 
			
		||||
			ListOptions: db.ListOptionsAll,
 | 
			
		||||
			OwnerID:     repo.OwnerID,
 | 
			
		||||
			IsClosed:    optional.Some(true),
 | 
			
		||||
			Type:        repoOwnerType,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctx.ServerError("GetProjects", err)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		closedProjects = append(closedProjects, closedProjects2...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ctx.Data["ClosedProjects"] = append(projects, projects2...)
 | 
			
		||||
	ctx.Data["OpenProjects"] = openProjects
 | 
			
		||||
	ctx.Data["ClosedProjects"] = closedProjects
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// repoReviewerSelection items to bee shown
 | 
			
		||||
 | 
			
		||||
@ -14,7 +14,7 @@ import (
 | 
			
		||||
	issues_model "code.gitea.io/gitea/models/issues"
 | 
			
		||||
	"code.gitea.io/gitea/models/perm"
 | 
			
		||||
	project_model "code.gitea.io/gitea/models/project"
 | 
			
		||||
	attachment_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	repo_model "code.gitea.io/gitea/models/repo"
 | 
			
		||||
	"code.gitea.io/gitea/models/unit"
 | 
			
		||||
	"code.gitea.io/gitea/modules/base"
 | 
			
		||||
	"code.gitea.io/gitea/modules/json"
 | 
			
		||||
@ -33,16 +33,17 @@ const (
 | 
			
		||||
	tplProjectsView base.TplName = "repo/projects/view"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// MustEnableProjects check if projects are enabled in settings
 | 
			
		||||
func MustEnableProjects(ctx *context.Context) {
 | 
			
		||||
// MustEnableRepoProjects check if repo projects are enabled in settings
 | 
			
		||||
func MustEnableRepoProjects(ctx *context.Context) {
 | 
			
		||||
	if unit.TypeProjects.UnitGlobalDisabled() {
 | 
			
		||||
		ctx.NotFound("EnableKanbanBoard", nil)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ctx.Repo.Repository != nil {
 | 
			
		||||
		if !ctx.Repo.CanRead(unit.TypeProjects) {
 | 
			
		||||
			ctx.NotFound("MustEnableProjects", nil)
 | 
			
		||||
		projectsUnit := ctx.Repo.Repository.MustGetUnit(ctx, unit.TypeProjects)
 | 
			
		||||
		if !ctx.Repo.CanRead(unit.TypeProjects) || !projectsUnit.ProjectsConfig().IsProjectsAllowed(repo_model.ProjectsModeRepo) {
 | 
			
		||||
			ctx.NotFound("MustEnableRepoProjects", nil)
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@ -325,10 +326,10 @@ func ViewProject(ctx *context.Context) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if project.CardType != project_model.CardTypeTextOnly {
 | 
			
		||||
		issuesAttachmentMap := make(map[int64][]*attachment_model.Attachment)
 | 
			
		||||
		issuesAttachmentMap := make(map[int64][]*repo_model.Attachment)
 | 
			
		||||
		for _, issuesList := range issuesMap {
 | 
			
		||||
			for _, issue := range issuesList {
 | 
			
		||||
				if issueAttachment, err := attachment_model.GetAttachmentsByIssueIDImagesLatest(ctx, issue.ID); err == nil {
 | 
			
		||||
				if issueAttachment, err := repo_model.GetAttachmentsByIssueIDImagesLatest(ctx, issue.ID); err == nil {
 | 
			
		||||
					issuesAttachmentMap[issue.ID] = issueAttachment
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@ -533,6 +533,9 @@ func SettingsPost(ctx *context.Context) {
 | 
			
		||||
			units = append(units, repo_model.RepoUnit{
 | 
			
		||||
				RepoID: repo.ID,
 | 
			
		||||
				Type:   unit_model.TypeProjects,
 | 
			
		||||
				Config: &repo_model.ProjectsConfig{
 | 
			
		||||
					ProjectsMode: repo_model.ProjectsMode(form.ProjectsMode),
 | 
			
		||||
				},
 | 
			
		||||
			})
 | 
			
		||||
		} else if !unit_model.TypeProjects.UnitGlobalDisabled() {
 | 
			
		||||
			deleteUnitTypes = append(deleteUnitTypes, unit_model.TypeProjects)
 | 
			
		||||
 | 
			
		||||
@ -1344,7 +1344,7 @@ func registerRoutes(m *web.Route) {
 | 
			
		||||
					})
 | 
			
		||||
				})
 | 
			
		||||
			}, reqRepoProjectsWriter, context.RepoMustNotBeArchived())
 | 
			
		||||
		}, reqRepoProjectsReader, repo.MustEnableProjects)
 | 
			
		||||
		}, reqRepoProjectsReader, repo.MustEnableRepoProjects)
 | 
			
		||||
 | 
			
		||||
		m.Group("/actions", func() {
 | 
			
		||||
			m.Get("", actions.List)
 | 
			
		||||
 | 
			
		||||
@ -113,8 +113,11 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
 | 
			
		||||
		defaultAllowMaintainerEdit = config.DefaultAllowMaintainerEdit
 | 
			
		||||
	}
 | 
			
		||||
	hasProjects := false
 | 
			
		||||
	if _, err := repo.GetUnit(ctx, unit_model.TypeProjects); err == nil {
 | 
			
		||||
	projectsMode := repo_model.ProjectsModeAll
 | 
			
		||||
	if unit, err := repo.GetUnit(ctx, unit_model.TypeProjects); err == nil {
 | 
			
		||||
		hasProjects = true
 | 
			
		||||
		config := unit.ProjectsConfig()
 | 
			
		||||
		projectsMode = config.ProjectsMode
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	hasReleases := false
 | 
			
		||||
@ -211,6 +214,7 @@ func innerToRepo(ctx context.Context, repo *repo_model.Repository, permissionInR
 | 
			
		||||
		InternalTracker:               internalTracker,
 | 
			
		||||
		HasWiki:                       hasWiki,
 | 
			
		||||
		HasProjects:                   hasProjects,
 | 
			
		||||
		ProjectsMode:                  string(projectsMode),
 | 
			
		||||
		HasReleases:                   hasReleases,
 | 
			
		||||
		HasPackages:                   hasPackages,
 | 
			
		||||
		HasActions:                    hasActions,
 | 
			
		||||
 | 
			
		||||
@ -142,6 +142,7 @@ type RepoSettingForm struct {
 | 
			
		||||
	ExternalTrackerRegexpPattern          string
 | 
			
		||||
	EnableCloseIssuesViaCommitInAnyBranch bool
 | 
			
		||||
	EnableProjects                        bool
 | 
			
		||||
	ProjectsMode                          string
 | 
			
		||||
	EnableReleases                        bool
 | 
			
		||||
	EnablePackages                        bool
 | 
			
		||||
	EnablePulls                           bool
 | 
			
		||||
 | 
			
		||||
@ -174,7 +174,8 @@
 | 
			
		||||
					</a>
 | 
			
		||||
				{{end}}
 | 
			
		||||
 | 
			
		||||
				{{if and (not .UnitProjectsGlobalDisabled) (.Permission.CanRead $.UnitTypeProjects)}}
 | 
			
		||||
				{{$projectsUnit := .Repository.MustGetUnit $.Context $.UnitTypeProjects}}
 | 
			
		||||
				{{if and (not .UnitProjectsGlobalDisabled) (.Permission.CanRead $.UnitTypeProjects) ($projectsUnit.ProjectsConfig.IsProjectsAllowed "repo")}}
 | 
			
		||||
					<a href="{{.RepoLink}}/projects" class="{{if .IsProjectsPage}}active {{end}}item">
 | 
			
		||||
						{{svg "octicon-project"}} {{ctx.Locale.Tr "repo.project_board"}}
 | 
			
		||||
						{{if .Repository.NumOpenProjects}}
 | 
			
		||||
 | 
			
		||||
@ -446,13 +446,45 @@
 | 
			
		||||
 | 
			
		||||
				{{$isProjectsEnabled := .Repository.UnitEnabled $.Context $.UnitTypeProjects}}
 | 
			
		||||
				{{$isProjectsGlobalDisabled := .UnitTypeProjects.UnitGlobalDisabled}}
 | 
			
		||||
				{{$projectsUnit := .Repository.MustGetUnit $.Context $.UnitTypeProjects}}
 | 
			
		||||
				<div class="inline field">
 | 
			
		||||
					<label>{{ctx.Locale.Tr "repo.project_board"}}</label>
 | 
			
		||||
					<div class="ui checkbox{{if $isProjectsGlobalDisabled}} disabled{{end}}"{{if $isProjectsGlobalDisabled}} data-tooltip-content="{{ctx.Locale.Tr "repo.unit_disabled"}}"{{end}}>
 | 
			
		||||
						<input class="enable-system" name="enable_projects" type="checkbox" {{if $isProjectsEnabled}}checked{{end}}>
 | 
			
		||||
						<input class="enable-system" name="enable_projects" type="checkbox" data-target="#projects_box" {{if $isProjectsEnabled}}checked{{end}}>
 | 
			
		||||
						<label>{{ctx.Locale.Tr "repo.settings.projects_desc"}}</label>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
				<div class="field {{if not $isProjectsEnabled}} disabled{{end}} gt-pl-4" id="projects_box">
 | 
			
		||||
					<p>
 | 
			
		||||
						{{ctx.Locale.Tr "repo.settings.projects_mode_desc"}}
 | 
			
		||||
					</p>
 | 
			
		||||
					<div class="ui dropdown selection">
 | 
			
		||||
						<select name="projects_mode">
 | 
			
		||||
							<option value="repo" {{if or (not $isProjectsEnabled) (eq $projectsUnit.ProjectsConfig.ProjectsMode "repo")}}selected{{end}}>{{ctx.Locale.Tr "repo.settings.projects_mode_repo"}}</option>
 | 
			
		||||
							<option value="owner" {{if or (not $isProjectsEnabled) (eq $projectsUnit.ProjectsConfig.ProjectsMode "owner")}}selected{{end}}>{{ctx.Locale.Tr "repo.settings.projects_mode_owner"}}</option>
 | 
			
		||||
							<option value="all" {{if or (not $isProjectsEnabled) (eq $projectsUnit.ProjectsConfig.ProjectsMode "all")}}selected{{end}}>{{ctx.Locale.Tr "repo.settings.projects_mode_all"}}</option>
 | 
			
		||||
						</select>
 | 
			
		||||
						{{svg "octicon-triangle-down" 14 "dropdown icon"}}
 | 
			
		||||
						<div class="default text">
 | 
			
		||||
							{{if (eq $projectsUnit.ProjectsConfig.ProjectsMode "repo")}}
 | 
			
		||||
								{{ctx.Locale.Tr "repo.settings.projects_mode_repo"}}
 | 
			
		||||
							{{end}}
 | 
			
		||||
							{{if (eq $projectsUnit.ProjectsConfig.ProjectsMode "owner")}}
 | 
			
		||||
								{{ctx.Locale.Tr "repo.settings.projects_mode_owner"}}
 | 
			
		||||
							{{end}}
 | 
			
		||||
							{{if (eq $projectsUnit.ProjectsConfig.ProjectsMode "all")}}
 | 
			
		||||
								{{ctx.Locale.Tr "repo.settings.projects_mode_all"}}
 | 
			
		||||
							{{end}}
 | 
			
		||||
						</div>
 | 
			
		||||
						<div class="menu">
 | 
			
		||||
							<div class="item" data-value="repo">{{ctx.Locale.Tr "repo.settings.projects_mode_repo"}}</div>
 | 
			
		||||
							<div class="item" data-value="owner">{{ctx.Locale.Tr "repo.settings.projects_mode_owner"}}</div>
 | 
			
		||||
							<div class="item" data-value="all">{{ctx.Locale.Tr "repo.settings.projects_mode_all"}}</div>
 | 
			
		||||
						</div>
 | 
			
		||||
					</div>
 | 
			
		||||
				</div>
 | 
			
		||||
 | 
			
		||||
				<div class="divider"></div>
 | 
			
		||||
 | 
			
		||||
				{{$isReleasesEnabled := .Repository.UnitEnabled $.Context $.UnitTypeReleases}}
 | 
			
		||||
				{{$isReleasesGlobalDisabled := .UnitTypeReleases.UnitGlobalDisabled}}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										9
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										9
									
								
								templates/swagger/v1_json.tmpl
									
									
									
										generated
									
									
									
								
							@ -19570,6 +19570,11 @@
 | 
			
		||||
          "type": "boolean",
 | 
			
		||||
          "x-go-name": "Private"
 | 
			
		||||
        },
 | 
			
		||||
        "projects_mode": {
 | 
			
		||||
          "description": "`repo` to only allow repo-level projects, `owner` to only allow owner projects, `all` to allow both.",
 | 
			
		||||
          "type": "string",
 | 
			
		||||
          "x-go-name": "ProjectsMode"
 | 
			
		||||
        },
 | 
			
		||||
        "template": {
 | 
			
		||||
          "description": "either `true` to make this repository a template or `false` to make it a normal repository",
 | 
			
		||||
          "type": "boolean",
 | 
			
		||||
@ -22491,6 +22496,10 @@
 | 
			
		||||
          "type": "boolean",
 | 
			
		||||
          "x-go-name": "Private"
 | 
			
		||||
        },
 | 
			
		||||
        "projects_mode": {
 | 
			
		||||
          "type": "string",
 | 
			
		||||
          "x-go-name": "ProjectsMode"
 | 
			
		||||
        },
 | 
			
		||||
        "release_counter": {
 | 
			
		||||
          "type": "integer",
 | 
			
		||||
          "format": "int64",
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user