* Add units concept for modulable functions of a repository * remove unused comment codes & fix lints and tests * remove unused comment codes * use struct config instead of map * fix lint * rm wrong files * fix teststags/v1.21.12.1
| @@ -441,7 +441,7 @@ func runWeb(ctx *cli.Context) error { | |||
| }, func(ctx *context.Context) { | |||
| ctx.Data["PageIsSettings"] = true | |||
| }) | |||
| }, context.UnitTypes()) | |||
| }, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.RepoRef()) | |||
| m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), repo.Action) | |||
| @@ -535,7 +535,7 @@ func runWeb(ctx *cli.Context) error { | |||
| return | |||
| } | |||
| }) | |||
| }, reqSignIn, context.RepoAssignment(), repo.MustBeNotBare) | |||
| }, reqSignIn, context.RepoAssignment(), repo.MustBeNotBare, context.UnitTypes()) | |||
| m.Group("/:username/:reponame", func() { | |||
| m.Group("", func() { | |||
| @@ -581,7 +581,7 @@ func runWeb(ctx *cli.Context) error { | |||
| m.Get("/commit/:sha([a-f0-9]{7,40})\\.:ext(patch|diff)", repo.RawDiff) | |||
| m.Get("/compare/:before([a-z0-9]{40})\\.\\.\\.:after([a-z0-9]{40})", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.CompareDiff) | |||
| }, ignSignIn, context.RepoAssignment(), repo.MustBeNotBare) | |||
| }, ignSignIn, context.RepoAssignment(), repo.MustBeNotBare, context.UnitTypes()) | |||
| m.Group("/:username/:reponame", func() { | |||
| m.Get("/stars", repo.Stars) | |||
| m.Get("/watchers", repo.Watchers) | |||
| @@ -591,7 +591,7 @@ func runWeb(ctx *cli.Context) error { | |||
| m.Group("/:reponame", func() { | |||
| m.Get("", repo.SetEditorconfigIfExists, repo.Home) | |||
| m.Get("\\.git$", repo.SetEditorconfigIfExists, repo.Home) | |||
| }, ignSignIn, context.RepoAssignment(true), context.RepoRef()) | |||
| }, ignSignIn, context.RepoAssignment(true), context.RepoRef(), context.UnitTypes()) | |||
| m.Group("/:reponame", func() { | |||
| m.Group("/info/lfs", func() { | |||
| @@ -76,10 +76,12 @@ var migrations = []Migration{ | |||
| // v13 -> v14:v0.9.87 | |||
| NewMigration("set comment updated with created", setCommentUpdatedWithCreated), | |||
| // v14 | |||
| // v14 -> v15 | |||
| NewMigration("create user column diff view style", createUserColumnDiffViewStyle), | |||
| // v15 | |||
| // v15 -> v16 | |||
| NewMigration("create user column allow create organization", createAllowCreateOrganizationColumn), | |||
| // V16 -> v17 | |||
| NewMigration("create repo unit table and add units for all repos", addUnitsToTables), | |||
| } | |||
| // Migrate database to current version | |||
| @@ -0,0 +1,117 @@ | |||
| package migrations | |||
| import ( | |||
| "fmt" | |||
| "time" | |||
| "code.gitea.io/gitea/modules/markdown" | |||
| "github.com/go-xorm/xorm" | |||
| ) | |||
| // RepoUnit describes all units of a repository | |||
| type RepoUnit struct { | |||
| ID int64 | |||
| RepoID int64 `xorm:"INDEX(s)"` | |||
| Type int `xorm:"INDEX(s)"` | |||
| Index int | |||
| Config map[string]string `xorm:"JSON"` | |||
| CreatedUnix int64 `xorm:"INDEX CREATED"` | |||
| Created time.Time `xorm:"-"` | |||
| } | |||
| // Enumerate all the unit types | |||
| const ( | |||
| UnitTypeCode = iota + 1 // 1 code | |||
| UnitTypeIssues // 2 issues | |||
| UnitTypePRs // 3 PRs | |||
| UnitTypeCommits // 4 Commits | |||
| UnitTypeReleases // 5 Releases | |||
| UnitTypeWiki // 6 Wiki | |||
| UnitTypeSettings // 7 Settings | |||
| UnitTypeExternalWiki // 8 ExternalWiki | |||
| UnitTypeExternalTracker // 9 ExternalTracker | |||
| ) | |||
| // Repo describes a repository | |||
| type Repo struct { | |||
| ID int64 | |||
| EnableWiki, EnableExternalWiki, EnableIssues, EnableExternalTracker, EnablePulls bool | |||
| ExternalWikiURL, ExternalTrackerURL, ExternalTrackerFormat, ExternalTrackerStyle string | |||
| } | |||
| func addUnitsToTables(x *xorm.Engine) error { | |||
| var repos []Repo | |||
| err := x.Table("repository").Find(&repos) | |||
| if err != nil { | |||
| return fmt.Errorf("Query repositories: %v", err) | |||
| } | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| if err := sess.Begin(); err != nil { | |||
| return err | |||
| } | |||
| var repoUnit RepoUnit | |||
| if err := sess.CreateTable(&repoUnit); err != nil { | |||
| return fmt.Errorf("CreateTable RepoUnit: %v", err) | |||
| } | |||
| if err := sess.CreateUniques(&repoUnit); err != nil { | |||
| return fmt.Errorf("CreateUniques RepoUnit: %v", err) | |||
| } | |||
| if err := sess.CreateIndexes(&repoUnit); err != nil { | |||
| return fmt.Errorf("CreateIndexes RepoUnit: %v", err) | |||
| } | |||
| for _, repo := range repos { | |||
| for i := 1; i <= 9; i++ { | |||
| if (i == UnitTypeWiki || i == UnitTypeExternalWiki) && !repo.EnableWiki { | |||
| continue | |||
| } | |||
| if i == UnitTypeExternalWiki && !repo.EnableExternalWiki { | |||
| continue | |||
| } | |||
| if i == UnitTypePRs && !repo.EnablePulls { | |||
| continue | |||
| } | |||
| if (i == UnitTypeIssues || i == UnitTypeExternalTracker) && !repo.EnableIssues { | |||
| continue | |||
| } | |||
| if i == UnitTypeExternalTracker && !repo.EnableExternalTracker { | |||
| continue | |||
| } | |||
| var config = make(map[string]string) | |||
| switch i { | |||
| case UnitTypeExternalTracker: | |||
| config["ExternalTrackerURL"] = repo.ExternalTrackerURL | |||
| config["ExternalTrackerFormat"] = repo.ExternalTrackerFormat | |||
| if len(repo.ExternalTrackerStyle) == 0 { | |||
| repo.ExternalTrackerStyle = markdown.IssueNameStyleNumeric | |||
| } | |||
| config["ExternalTrackerStyle"] = repo.ExternalTrackerStyle | |||
| case UnitTypeExternalWiki: | |||
| config["ExternalWikiURL"] = repo.ExternalWikiURL | |||
| } | |||
| if _, err = sess.Insert(&RepoUnit{ | |||
| RepoID: repo.ID, | |||
| Type: i, | |||
| Index: i, | |||
| Config: config, | |||
| }); err != nil { | |||
| return fmt.Errorf("Insert repo unit: %v", err) | |||
| } | |||
| } | |||
| } | |||
| if err := sess.Commit(); err != nil { | |||
| return err | |||
| } | |||
| return nil | |||
| } | |||
| @@ -106,6 +106,7 @@ func init() { | |||
| new(IssueUser), | |||
| new(LFSMetaObject), | |||
| new(TwoFactor), | |||
| new(RepoUnit), | |||
| ) | |||
| gonicNames := []string{"SSL", "UID"} | |||
| @@ -200,17 +200,8 @@ type Repository struct { | |||
| IsMirror bool `xorm:"INDEX"` | |||
| *Mirror `xorm:"-"` | |||
| // Advanced settings | |||
| EnableWiki bool `xorm:"NOT NULL DEFAULT true"` | |||
| EnableExternalWiki bool | |||
| ExternalWikiURL string | |||
| EnableIssues bool `xorm:"NOT NULL DEFAULT true"` | |||
| EnableExternalTracker bool | |||
| ExternalTrackerURL string | |||
| ExternalTrackerFormat string | |||
| ExternalTrackerStyle string | |||
| ExternalMetas map[string]string `xorm:"-"` | |||
| EnablePulls bool `xorm:"NOT NULL DEFAULT true"` | |||
| ExternalMetas map[string]string `xorm:"-"` | |||
| Units []*RepoUnit `xorm:"-"` | |||
| IsFork bool `xorm:"INDEX NOT NULL DEFAULT false"` | |||
| ForkID int64 `xorm:"INDEX"` | |||
| @@ -247,10 +238,6 @@ func (repo *Repository) AfterSet(colName string, _ xorm.Cell) { | |||
| repo.NumOpenPulls = repo.NumPulls - repo.NumClosedPulls | |||
| case "num_closed_milestones": | |||
| repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones | |||
| case "external_tracker_style": | |||
| if len(repo.ExternalTrackerStyle) == 0 { | |||
| repo.ExternalTrackerStyle = markdown.IssueNameStyleNumeric | |||
| } | |||
| case "created_unix": | |||
| repo.Created = time.Unix(repo.CreatedUnix, 0).Local() | |||
| case "updated_unix": | |||
| @@ -307,6 +294,72 @@ func (repo *Repository) APIFormat(mode AccessMode) *api.Repository { | |||
| } | |||
| } | |||
| func (repo *Repository) getUnits(e Engine) (err error) { | |||
| if repo.Units != nil { | |||
| return nil | |||
| } | |||
| repo.Units, err = getUnitsByRepoID(e, repo.ID) | |||
| return err | |||
| } | |||
| func getUnitsByRepoID(e Engine, repoID int64) (units []*RepoUnit, err error) { | |||
| return units, e.Where("repo_id = ?", repoID).Find(&units) | |||
| } | |||
| // EnableUnit if this repository enabled some unit | |||
| func (repo *Repository) EnableUnit(tp UnitType) bool { | |||
| repo.getUnits(x) | |||
| for _, unit := range repo.Units { | |||
| if unit.Type == tp { | |||
| return true | |||
| } | |||
| } | |||
| return false | |||
| } | |||
| var ( | |||
| // ErrUnitNotExist organization does not exist | |||
| ErrUnitNotExist = errors.New("Unit does not exist") | |||
| ) | |||
| // MustGetUnit always returns a RepoUnit object | |||
| func (repo *Repository) MustGetUnit(tp UnitType) *RepoUnit { | |||
| ru, err := repo.GetUnit(tp) | |||
| if err == nil { | |||
| return ru | |||
| } | |||
| if tp == UnitTypeExternalWiki { | |||
| return &RepoUnit{ | |||
| Type: tp, | |||
| Config: new(ExternalWikiConfig), | |||
| } | |||
| } else if tp == UnitTypeExternalTracker { | |||
| return &RepoUnit{ | |||
| Type: tp, | |||
| Config: new(ExternalTrackerConfig), | |||
| } | |||
| } | |||
| return &RepoUnit{ | |||
| Type: tp, | |||
| Config: new(UnitConfig), | |||
| } | |||
| } | |||
| // GetUnit returns a RepoUnit object | |||
| func (repo *Repository) GetUnit(tp UnitType) (*RepoUnit, error) { | |||
| if err := repo.getUnits(x); err != nil { | |||
| return nil, err | |||
| } | |||
| for _, unit := range repo.Units { | |||
| if unit.Type == tp { | |||
| return unit, nil | |||
| } | |||
| } | |||
| return nil, ErrUnitNotExist | |||
| } | |||
| func (repo *Repository) getOwner(e Engine) (err error) { | |||
| if repo.Owner != nil { | |||
| return nil | |||
| @@ -334,15 +387,18 @@ func (repo *Repository) mustOwner(e Engine) *User { | |||
| // ComposeMetas composes a map of metas for rendering external issue tracker URL. | |||
| func (repo *Repository) ComposeMetas() map[string]string { | |||
| if !repo.EnableExternalTracker { | |||
| unit, err := repo.GetUnit(UnitTypeExternalTracker) | |||
| if err != nil { | |||
| return nil | |||
| } else if repo.ExternalMetas == nil { | |||
| } | |||
| if repo.ExternalMetas == nil { | |||
| repo.ExternalMetas = map[string]string{ | |||
| "format": repo.ExternalTrackerFormat, | |||
| "format": unit.ExternalTrackerConfig().ExternalTrackerFormat, | |||
| "user": repo.MustOwner().Name, | |||
| "repo": repo.Name, | |||
| } | |||
| switch repo.ExternalTrackerStyle { | |||
| switch unit.ExternalTrackerConfig().ExternalTrackerStyle { | |||
| case markdown.IssueNameStyleAlphanumeric: | |||
| repo.ExternalMetas["style"] = markdown.IssueNameStyleAlphanumeric | |||
| default: | |||
| @@ -359,6 +415,8 @@ func (repo *Repository) DeleteWiki() { | |||
| for _, wikiPath := range wikiPaths { | |||
| RemoveAllWithNotice("Delete repository wiki", wikiPath) | |||
| } | |||
| x.Where("repo_id = ?", repo.ID).And("type = ?", UnitTypeWiki).Delete(new(RepoUnit)) | |||
| } | |||
| func (repo *Repository) getAssignees(e Engine) (_ []*User, err error) { | |||
| @@ -482,7 +540,7 @@ func (repo *Repository) CanEnablePulls() bool { | |||
| // AllowsPulls returns true if repository meets the requirements of accepting pulls and has them enabled. | |||
| func (repo *Repository) AllowsPulls() bool { | |||
| return repo.CanEnablePulls() && repo.EnablePulls | |||
| return repo.CanEnablePulls() && repo.EnableUnit(UnitTypePullRequests) | |||
| } | |||
| // CanEnableEditor returns true if repository meets the requirements of web editor. | |||
| @@ -997,6 +1055,20 @@ func createRepository(e *xorm.Session, u *User, repo *Repository) (err error) { | |||
| return err | |||
| } | |||
| // insert units for repo | |||
| var units = make([]RepoUnit, 0, len(defaultRepoUnits)) | |||
| for i, tp := range defaultRepoUnits { | |||
| units = append(units, RepoUnit{ | |||
| RepoID: repo.ID, | |||
| Type: tp, | |||
| Index: i, | |||
| }) | |||
| } | |||
| if _, err = e.Insert(&units); err != nil { | |||
| return err | |||
| } | |||
| u.NumRepos++ | |||
| // Remember visibility preference. | |||
| u.LastRepoVisibility = repo.IsPrivate | |||
| @@ -1035,15 +1107,12 @@ func CreateRepository(u *User, opts CreateRepoOptions) (_ *Repository, err error | |||
| } | |||
| repo := &Repository{ | |||
| OwnerID: u.ID, | |||
| Owner: u, | |||
| Name: opts.Name, | |||
| LowerName: strings.ToLower(opts.Name), | |||
| Description: opts.Description, | |||
| IsPrivate: opts.IsPrivate, | |||
| EnableWiki: true, | |||
| EnableIssues: true, | |||
| EnablePulls: true, | |||
| OwnerID: u.ID, | |||
| Owner: u, | |||
| Name: opts.Name, | |||
| LowerName: strings.ToLower(opts.Name), | |||
| Description: opts.Description, | |||
| IsPrivate: opts.IsPrivate, | |||
| } | |||
| sess := x.NewSession() | |||
| @@ -1380,6 +1449,25 @@ func UpdateRepository(repo *Repository, visibilityChanged bool) (err error) { | |||
| return sess.Commit() | |||
| } | |||
| // UpdateRepositoryUnits updates a repository's units | |||
| func UpdateRepositoryUnits(repo *Repository, units []RepoUnit) (err error) { | |||
| sess := x.NewSession() | |||
| defer sess.Close() | |||
| if err = sess.Begin(); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Where("repo_id = ?", repo.ID).Delete(new(RepoUnit)); err != nil { | |||
| return err | |||
| } | |||
| if _, err = sess.Insert(units); err != nil { | |||
| return err | |||
| } | |||
| return sess.Commit() | |||
| } | |||
| // DeleteRepository deletes a repository for a user or organization. | |||
| func DeleteRepository(uid, repoID int64) error { | |||
| repo := &Repository{ID: repoID, OwnerID: uid} | |||
| @@ -1467,6 +1555,10 @@ func DeleteRepository(uid, repoID int64) error { | |||
| return err | |||
| } | |||
| if _, err = sess.Where("repo_id = ?", repoID).Delete(new(RepoUnit)); err != nil { | |||
| return err | |||
| } | |||
| if repo.IsFork { | |||
| if _, err = sess.Exec("UPDATE `repository` SET num_forks=num_forks-1 WHERE id=?", repo.ForkID); err != nil { | |||
| return fmt.Errorf("decrease fork count: %v", err) | |||
| @@ -14,34 +14,42 @@ func TestRepo(t *testing.T) { | |||
| repo.Name = "testrepo" | |||
| repo.Owner = new(User) | |||
| repo.Owner.Name = "testuser" | |||
| repo.ExternalTrackerFormat = "https://someurl.com/{user}/{repo}/{issue}" | |||
| externalTracker := RepoUnit{ | |||
| Type: UnitTypeExternalTracker, | |||
| Config: &ExternalTrackerConfig{ | |||
| ExternalTrackerFormat: "https://someurl.com/{user}/{repo}/{issue}", | |||
| }, | |||
| } | |||
| repo.Units = []*RepoUnit{ | |||
| &externalTracker, | |||
| } | |||
| Convey("When no external tracker is configured", func() { | |||
| Convey("It should be nil", func() { | |||
| repo.EnableExternalTracker = false | |||
| repo.Units = nil | |||
| So(repo.ComposeMetas(), ShouldEqual, map[string]string(nil)) | |||
| }) | |||
| Convey("It should be nil even if other settings are present", func() { | |||
| repo.EnableExternalTracker = false | |||
| repo.ExternalTrackerFormat = "http://someurl.com/{user}/{repo}/{issue}" | |||
| repo.ExternalTrackerStyle = markdown.IssueNameStyleNumeric | |||
| repo.Units = nil | |||
| So(repo.ComposeMetas(), ShouldEqual, map[string]string(nil)) | |||
| }) | |||
| }) | |||
| Convey("When an external issue tracker is configured", func() { | |||
| repo.EnableExternalTracker = true | |||
| repo.Units = []*RepoUnit{ | |||
| &externalTracker, | |||
| } | |||
| Convey("It should default to numeric issue style", func() { | |||
| metas := repo.ComposeMetas() | |||
| So(metas["style"], ShouldEqual, markdown.IssueNameStyleNumeric) | |||
| }) | |||
| Convey("It should pass through numeric issue style setting", func() { | |||
| repo.ExternalTrackerStyle = markdown.IssueNameStyleNumeric | |||
| externalTracker.ExternalTrackerConfig().ExternalTrackerStyle = markdown.IssueNameStyleNumeric | |||
| metas := repo.ComposeMetas() | |||
| So(metas["style"], ShouldEqual, markdown.IssueNameStyleNumeric) | |||
| }) | |||
| Convey("It should pass through alphanumeric issue style setting", func() { | |||
| repo.ExternalTrackerStyle = markdown.IssueNameStyleAlphanumeric | |||
| externalTracker.ExternalTrackerConfig().ExternalTrackerStyle = markdown.IssueNameStyleAlphanumeric | |||
| metas := repo.ComposeMetas() | |||
| So(metas["style"], ShouldEqual, markdown.IssueNameStyleAlphanumeric) | |||
| }) | |||
| @@ -0,0 +1,137 @@ | |||
| // Copyright 2017 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package models | |||
| import ( | |||
| "encoding/json" | |||
| "time" | |||
| "github.com/Unknwon/com" | |||
| "github.com/go-xorm/core" | |||
| "github.com/go-xorm/xorm" | |||
| ) | |||
| // RepoUnit describes all units of a repository | |||
| type RepoUnit struct { | |||
| ID int64 | |||
| RepoID int64 `xorm:"INDEX(s)"` | |||
| Type UnitType `xorm:"INDEX(s)"` | |||
| Index int | |||
| Config core.Conversion `xorm:"TEXT"` | |||
| CreatedUnix int64 `xorm:"INDEX CREATED"` | |||
| Created time.Time `xorm:"-"` | |||
| } | |||
| // UnitConfig describes common unit config | |||
| type UnitConfig struct { | |||
| } | |||
| // FromDB fills up a UnitConfig from serialized format. | |||
| func (cfg *UnitConfig) FromDB(bs []byte) error { | |||
| return json.Unmarshal(bs, &cfg) | |||
| } | |||
| // ToDB exports a UnitConfig to a serialized format. | |||
| func (cfg *UnitConfig) ToDB() ([]byte, error) { | |||
| return json.Marshal(cfg) | |||
| } | |||
| // ExternalWikiConfig describes external wiki config | |||
| type ExternalWikiConfig struct { | |||
| ExternalWikiURL string | |||
| } | |||
| // FromDB fills up a ExternalWikiConfig from serialized format. | |||
| func (cfg *ExternalWikiConfig) FromDB(bs []byte) error { | |||
| return json.Unmarshal(bs, &cfg) | |||
| } | |||
| // ToDB exports a ExternalWikiConfig to a serialized format. | |||
| func (cfg *ExternalWikiConfig) ToDB() ([]byte, error) { | |||
| return json.Marshal(cfg) | |||
| } | |||
| // ExternalTrackerConfig describes external tracker config | |||
| type ExternalTrackerConfig struct { | |||
| ExternalTrackerURL string | |||
| ExternalTrackerFormat string | |||
| ExternalTrackerStyle string | |||
| } | |||
| // FromDB fills up a ExternalTrackerConfig from serialized format. | |||
| func (cfg *ExternalTrackerConfig) FromDB(bs []byte) error { | |||
| return json.Unmarshal(bs, &cfg) | |||
| } | |||
| // ToDB exports a ExternalTrackerConfig to a serialized format. | |||
| func (cfg *ExternalTrackerConfig) ToDB() ([]byte, error) { | |||
| return json.Marshal(cfg) | |||
| } | |||
| // 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 { | |||
| case "type": | |||
| switch UnitType(Cell2Int64(val)) { | |||
| case UnitTypeCode, UnitTypeIssues, UnitTypePullRequests, UnitTypeCommits, UnitTypeReleases, | |||
| UnitTypeWiki, UnitTypeSettings: | |||
| r.Config = new(UnitConfig) | |||
| case UnitTypeExternalWiki: | |||
| r.Config = new(ExternalWikiConfig) | |||
| case UnitTypeExternalTracker: | |||
| r.Config = new(ExternalTrackerConfig) | |||
| default: | |||
| panic("unrecognized repo unit type: " + com.ToStr(*val)) | |||
| } | |||
| } | |||
| } | |||
| // AfterSet is invoked from XORM after setting the value of a field of this object. | |||
| func (r *RepoUnit) AfterSet(colName string, _ xorm.Cell) { | |||
| switch colName { | |||
| case "created_unix": | |||
| r.Created = time.Unix(r.CreatedUnix, 0).Local() | |||
| } | |||
| } | |||
| // Unit returns Unit | |||
| func (r *RepoUnit) Unit() Unit { | |||
| return Units[r.Type] | |||
| } | |||
| // CodeConfig returns config for UnitTypeCode | |||
| func (r *RepoUnit) CodeConfig() *UnitConfig { | |||
| return r.Config.(*UnitConfig) | |||
| } | |||
| // IssuesConfig returns config for UnitTypeIssues | |||
| func (r *RepoUnit) IssuesConfig() *UnitConfig { | |||
| return r.Config.(*UnitConfig) | |||
| } | |||
| // PullRequestsConfig returns config for UnitTypePullRequests | |||
| func (r *RepoUnit) PullRequestsConfig() *UnitConfig { | |||
| return r.Config.(*UnitConfig) | |||
| } | |||
| // CommitsConfig returns config for UnitTypeCommits | |||
| func (r *RepoUnit) CommitsConfig() *UnitConfig { | |||
| return r.Config.(*UnitConfig) | |||
| } | |||
| // ReleasesConfig returns config for UnitTypeReleases | |||
| func (r *RepoUnit) ReleasesConfig() *UnitConfig { | |||
| return r.Config.(*UnitConfig) | |||
| } | |||
| // ExternalWikiConfig returns config for UnitTypeExternalWiki | |||
| func (r *RepoUnit) ExternalWikiConfig() *ExternalWikiConfig { | |||
| return r.Config.(*ExternalWikiConfig) | |||
| } | |||
| // ExternalTrackerConfig returns config for UnitTypeExternalTracker | |||
| func (r *RepoUnit) ExternalTrackerConfig() *ExternalTrackerConfig { | |||
| return r.Config.(*ExternalTrackerConfig) | |||
| } | |||
| @@ -0,0 +1,137 @@ | |||
| // Copyright 2017 The Gitea Authors. All rights reserved. | |||
| // Use of this source code is governed by a MIT-style | |||
| // license that can be found in the LICENSE file. | |||
| package models | |||
| // UnitType is Unit's Type | |||
| type UnitType int | |||
| // Enumerate all the unit types | |||
| const ( | |||
| UnitTypeCode UnitType = iota + 1 // 1 code | |||
| UnitTypeIssues // 2 issues | |||
| UnitTypePullRequests // 3 PRs | |||
| UnitTypeCommits // 4 Commits | |||
| UnitTypeReleases // 5 Releases | |||
| UnitTypeWiki // 6 Wiki | |||
| UnitTypeSettings // 7 Settings | |||
| UnitTypeExternalWiki // 8 ExternalWiki | |||
| UnitTypeExternalTracker // 9 ExternalTracker | |||
| ) | |||
| // Unit is a tab page of one repository | |||
| type Unit struct { | |||
| Type UnitType | |||
| NameKey string | |||
| URI string | |||
| DescKey string | |||
| Idx int | |||
| } | |||
| // Enumerate all the units | |||
| var ( | |||
| UnitCode = Unit{ | |||
| UnitTypeCode, | |||
| "repo.code", | |||
| "/", | |||
| "repo.code_desc", | |||
| 0, | |||
| } | |||
| UnitIssues = Unit{ | |||
| UnitTypeIssues, | |||
| "repo.issues", | |||
| "/issues", | |||
| "repo.issues_desc", | |||
| 1, | |||
| } | |||
| UnitExternalTracker = Unit{ | |||
| UnitTypeExternalTracker, | |||
| "repo.issues", | |||
| "/issues", | |||
| "repo.issues_desc", | |||
| 1, | |||
| } | |||
| UnitPullRequests = Unit{ | |||
| UnitTypePullRequests, | |||
| "repo.pulls", | |||
| "/pulls", | |||
| "repo.pulls_desc", | |||
| 2, | |||
| } | |||
| UnitCommits = Unit{ | |||
| UnitTypeCommits, | |||
| "repo.commits", | |||
| "/commits/master", | |||
| "repo.commits_desc", | |||
| 3, | |||
| } | |||
| UnitReleases = Unit{ | |||
| UnitTypeReleases, | |||
| "repo.releases", | |||
| "/releases", | |||
| "repo.releases_desc", | |||
| 4, | |||
| } | |||
| UnitWiki = Unit{ | |||
| UnitTypeWiki, | |||
| "repo.wiki", | |||
| "/wiki", | |||
| "repo.wiki_desc", | |||
| 5, | |||
| } | |||
| UnitExternalWiki = Unit{ | |||
| UnitTypeExternalWiki, | |||
| "repo.wiki", | |||
| "/wiki", | |||
| "repo.wiki_desc", | |||
| 5, | |||
| } | |||
| UnitSettings = Unit{ | |||
| UnitTypeSettings, | |||
| "repo.settings", | |||
| "/settings", | |||
| "repo.settings_desc", | |||
| 6, | |||
| } | |||
| // defaultRepoUnits contains all the default unit types | |||
| defaultRepoUnits = []UnitType{ | |||
| UnitTypeCode, | |||
| UnitTypeIssues, | |||
| UnitTypePullRequests, | |||
| UnitTypeCommits, | |||
| UnitTypeReleases, | |||
| UnitTypeWiki, | |||
| UnitTypeSettings, | |||
| } | |||
| // MustRepoUnits contains the units could be disabled currently | |||
| MustRepoUnits = []UnitType{ | |||
| UnitTypeCode, | |||
| UnitTypeCommits, | |||
| UnitTypeReleases, | |||
| UnitTypeSettings, | |||
| } | |||
| // Units contains all the units | |||
| Units = map[UnitType]Unit{ | |||
| UnitTypeCode: UnitCode, | |||
| UnitTypeIssues: UnitIssues, | |||
| UnitTypeExternalTracker: UnitExternalTracker, | |||
| UnitTypePullRequests: UnitPullRequests, | |||
| UnitTypeCommits: UnitCommits, | |||
| UnitTypeReleases: UnitReleases, | |||
| UnitTypeWiki: UnitWiki, | |||
| UnitTypeExternalWiki: UnitExternalWiki, | |||
| UnitTypeSettings: UnitSettings, | |||
| } | |||
| ) | |||
| @@ -477,3 +477,18 @@ func GitHookService() macaron.Handler { | |||
| } | |||
| } | |||
| } | |||
| // UnitTypes returns a macaron middleware to set unit types to context variables. | |||
| func UnitTypes() macaron.Handler { | |||
| return func(ctx *Context) { | |||
| ctx.Data["UnitTypeCode"] = models.UnitTypeCode | |||
| ctx.Data["UnitTypeIssues"] = models.UnitTypeIssues | |||
| ctx.Data["UnitTypePullRequests"] = models.UnitTypePullRequests | |||
| ctx.Data["UnitTypeCommits"] = models.UnitTypeCommits | |||
| ctx.Data["UnitTypeReleases"] = models.UnitTypeReleases | |||
| ctx.Data["UnitTypeWiki"] = models.UnitTypeWiki | |||
| ctx.Data["UnitTypeSettings"] = models.UnitTypeSettings | |||
| ctx.Data["UnitTypeExternalWiki"] = models.UnitTypeExternalWiki | |||
| ctx.Data["UnitTypeExternalTracker"] = models.UnitTypeExternalTracker | |||
| } | |||
| } | |||
| @@ -205,7 +205,7 @@ func orgAssignment(args ...bool) macaron.Handler { | |||
| } | |||
| func mustEnableIssues(ctx *context.APIContext) { | |||
| if !ctx.Repo.Repository.EnableIssues || ctx.Repo.Repository.EnableExternalTracker { | |||
| if !ctx.Repo.Repository.EnableUnit(models.UnitTypeIssues) { | |||
| ctx.Status(404) | |||
| return | |||
| } | |||
| @@ -59,13 +59,15 @@ var ( | |||
| // MustEnableIssues check if repository enable internal issues | |||
| func MustEnableIssues(ctx *context.Context) { | |||
| if !ctx.Repo.Repository.EnableIssues { | |||
| if !ctx.Repo.Repository.EnableUnit(models.UnitTypeIssues) && | |||
| !ctx.Repo.Repository.EnableUnit(models.UnitTypeExternalTracker) { | |||
| ctx.Handle(404, "MustEnableIssues", nil) | |||
| return | |||
| } | |||
| if ctx.Repo.Repository.EnableExternalTracker { | |||
| ctx.Redirect(ctx.Repo.Repository.ExternalTrackerURL) | |||
| unit, err := ctx.Repo.Repository.GetUnit(models.UnitTypeExternalTracker) | |||
| if err == nil { | |||
| ctx.Redirect(unit.ExternalTrackerConfig().ExternalTrackerURL) | |||
| return | |||
| } | |||
| } | |||
| @@ -143,18 +143,70 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||
| ctx.Redirect(repo.Link() + "/settings") | |||
| case "advanced": | |||
| repo.EnableWiki = form.EnableWiki | |||
| repo.EnableExternalWiki = form.EnableExternalWiki | |||
| repo.ExternalWikiURL = form.ExternalWikiURL | |||
| repo.EnableIssues = form.EnableIssues | |||
| repo.EnableExternalTracker = form.EnableExternalTracker | |||
| repo.ExternalTrackerURL = form.ExternalTrackerURL | |||
| repo.ExternalTrackerFormat = form.TrackerURLFormat | |||
| repo.ExternalTrackerStyle = form.TrackerIssueStyle | |||
| repo.EnablePulls = form.EnablePulls | |||
| if err := models.UpdateRepository(repo, false); err != nil { | |||
| ctx.Handle(500, "UpdateRepository", err) | |||
| var units []models.RepoUnit | |||
| for _, tp := range models.MustRepoUnits { | |||
| units = append(units, models.RepoUnit{ | |||
| RepoID: repo.ID, | |||
| Type: tp, | |||
| Index: int(tp), | |||
| Config: new(models.UnitConfig), | |||
| }) | |||
| } | |||
| if form.EnableWiki { | |||
| if form.EnableExternalWiki { | |||
| units = append(units, models.RepoUnit{ | |||
| RepoID: repo.ID, | |||
| Type: models.UnitTypeExternalWiki, | |||
| Index: int(models.UnitTypeExternalWiki), | |||
| Config: &models.ExternalWikiConfig{ | |||
| ExternalWikiURL: form.ExternalWikiURL, | |||
| }, | |||
| }) | |||
| } else { | |||
| units = append(units, models.RepoUnit{ | |||
| RepoID: repo.ID, | |||
| Type: models.UnitTypeWiki, | |||
| Index: int(models.UnitTypeWiki), | |||
| Config: new(models.UnitConfig), | |||
| }) | |||
| } | |||
| } | |||
| if form.EnableIssues { | |||
| if form.EnableExternalTracker { | |||
| units = append(units, models.RepoUnit{ | |||
| RepoID: repo.ID, | |||
| Type: models.UnitTypeExternalWiki, | |||
| Index: int(models.UnitTypeExternalWiki), | |||
| Config: &models.ExternalTrackerConfig{ | |||
| ExternalTrackerURL: form.ExternalTrackerURL, | |||
| ExternalTrackerFormat: form.TrackerURLFormat, | |||
| ExternalTrackerStyle: form.TrackerIssueStyle, | |||
| }, | |||
| }) | |||
| } else { | |||
| units = append(units, models.RepoUnit{ | |||
| RepoID: repo.ID, | |||
| Type: models.UnitTypeIssues, | |||
| Index: int(models.UnitTypeIssues), | |||
| Config: new(models.UnitConfig), | |||
| }) | |||
| } | |||
| } | |||
| if form.EnablePulls { | |||
| units = append(units, models.RepoUnit{ | |||
| RepoID: repo.ID, | |||
| Type: models.UnitTypePullRequests, | |||
| Index: int(models.UnitTypePullRequests), | |||
| Config: new(models.UnitConfig), | |||
| }) | |||
| } | |||
| if err := models.UpdateRepositoryUnits(repo, units); err != nil { | |||
| ctx.Handle(500, "UpdateRepositoryUnits", err) | |||
| return | |||
| } | |||
| log.Trace("Repository advanced settings updated: %s/%s", ctx.Repo.Owner.Name, repo.Name) | |||
| @@ -281,12 +333,6 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||
| repo.DeleteWiki() | |||
| log.Trace("Repository wiki deleted: %s/%s", ctx.Repo.Owner.Name, repo.Name) | |||
| repo.EnableWiki = false | |||
| if err := models.UpdateRepository(repo, false); err != nil { | |||
| ctx.Handle(500, "UpdateRepository", err) | |||
| return | |||
| } | |||
| ctx.Flash.Success(ctx.Tr("repo.settings.wiki_deletion_success")) | |||
| ctx.Redirect(ctx.Repo.RepoLink + "/settings") | |||
| @@ -27,13 +27,15 @@ const ( | |||
| // MustEnableWiki check if wiki is enabled, if external then redirect | |||
| func MustEnableWiki(ctx *context.Context) { | |||
| if !ctx.Repo.Repository.EnableWiki { | |||
| if !ctx.Repo.Repository.EnableUnit(models.UnitTypeWiki) && | |||
| !ctx.Repo.Repository.EnableUnit(models.UnitTypeExternalWiki) { | |||
| ctx.Handle(404, "MustEnableWiki", nil) | |||
| return | |||
| } | |||
| if ctx.Repo.Repository.EnableExternalWiki { | |||
| ctx.Redirect(ctx.Repo.Repository.ExternalWikiURL) | |||
| unit, err := ctx.Repo.Repository.GetUnit(models.UnitTypeExternalWiki) | |||
| if err == nil { | |||
| ctx.Redirect(unit.ExternalWikiConfig().ExternalWikiURL) | |||
| return | |||
| } | |||
| } | |||
| @@ -236,7 +236,7 @@ func Issues(ctx *context.Context) { | |||
| for _, repo := range repos { | |||
| if (isPullList && repo.NumPulls == 0) || | |||
| (!isPullList && | |||
| (!repo.EnableIssues || repo.EnableExternalTracker || repo.NumIssues == 0)) { | |||
| (!repo.EnableUnit(models.UnitTypeIssues) || repo.NumIssues == 0)) { | |||
| continue | |||
| } | |||
| @@ -49,30 +49,48 @@ | |||
| {{if not (or .IsBareRepo .IsDiffCompare)}} | |||
| <div class="ui tabs container"> | |||
| <div class="ui tabular menu navbar"> | |||
| {{if .Repository.EnableUnit $.UnitTypeCode}} | |||
| <a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}"> | |||
| <i class="octicon octicon-code"></i> {{.i18n.Tr "repo.code"}} | |||
| </a> | |||
| {{if .Repository.EnableIssues}} | |||
| {{end}} | |||
| {{if .Repository.EnableUnit $.UnitTypeIssues}} | |||
| <a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues"> | |||
| <i class="octicon octicon-issue-opened"></i> {{.i18n.Tr "repo.issues"}} <span class="ui {{if not .Repository.NumOpenIssues}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenIssues}}</span> | |||
| </a> | |||
| {{end}} | |||
| {{if .Repository.EnableUnit $.UnitTypeExternalTracker}} | |||
| <a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues"> | |||
| <i class="octicon octicon-issue-opened"></i> {{.i18n.Tr "repo.issues"}} {{if not .Repository.EnableExternalTracker}}<span class="ui {{if not .Repository.NumOpenIssues}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenIssues}}{{end}}</span> | |||
| <i class="octicon octicon-issue-opened"></i> {{.i18n.Tr "repo.issues"}} </span> | |||
| </a> | |||
| {{end}} | |||
| {{if .Repository.AllowsPulls}} | |||
| <a class="{{if .PageIsPullList}}active{{end}} item" href="{{.RepoLink}}/pulls"> | |||
| <i class="octicon octicon-git-pull-request"></i> {{.i18n.Tr "repo.pulls"}} <span class="ui {{if not .Repository.NumOpenPulls}}gray{{else}}blue{{end}} small label">{{.Repository.NumOpenPulls}}</span> | |||
| </a> | |||
| {{end}} | |||
| {{if .Repository.EnableUnit $.UnitTypeCommits}} | |||
| <a class="{{if (or (.PageIsCommits) (.PageIsDiff))}}active{{end}} item" href="{{.RepoLink}}/commits/{{EscapePound .BranchName}}"> | |||
| <i class="octicon octicon-history"></i> {{.i18n.Tr "repo.commits"}} <span class="ui {{if not .CommitsCount}}gray{{else}}blue{{end}} small label">{{.CommitsCount}}</span> | |||
| </a> | |||
| {{end}} | |||
| {{if .Repository.EnableUnit $.UnitTypeReleases}} | |||
| <a class="{{if .PageIsReleaseList}}active{{end}} item" href="{{.RepoLink}}/releases"> | |||
| <i class="octicon octicon-tag"></i> {{.i18n.Tr "repo.releases"}} <span class="ui {{if not .Repository.NumTags}}gray{{else}}blue{{end}} small label">{{.Repository.NumTags}}</span> | |||
| </a> | |||
| {{if .Repository.EnableWiki}} | |||
| {{end}} | |||
| {{if or (.Repository.EnableUnit $.UnitTypeWiki) (.Repository.EnableUnit $.UnitTypeExternalWiki)}} | |||
| <a class="{{if .PageIsWiki}}active{{end}} item" href="{{.RepoLink}}/wiki"> | |||
| <i class="octicon octicon-book"></i> {{.i18n.Tr "repo.wiki"}} | |||
| </a> | |||
| {{end}} | |||
| {{if .IsRepositoryAdmin}} | |||
| <div class="right menu"> | |||
| <a class="{{if .PageIsSettings}}active{{end}} item" href="{{.RepoLink}}/settings"> | |||
| @@ -114,26 +114,26 @@ | |||
| <div class="inline field"> | |||
| <label>{{.i18n.Tr "repo.wiki"}}</label> | |||
| <div class="ui checkbox"> | |||
| <input class="enable-system" name="enable_wiki" type="checkbox" data-target="#wiki_box" {{if .Repository.EnableWiki}}checked{{end}}> | |||
| <input class="enable-system" name="enable_wiki" type="checkbox" data-target="#wiki_box" {{if or (.Repository.EnableUnit $.UnitTypeWiki) (.Repository.EnableUnit $.UnitTypeExternalWiki)}}checked{{end}}> | |||
| <label>{{.i18n.Tr "repo.settings.wiki_desc"}}</label> | |||
| </div> | |||
| </div> | |||
| <div class="field {{if not .Repository.EnableWiki}}disabled{{end}}" id="wiki_box"> | |||
| <div class="field {{if not (.Repository.EnableUnit $.UnitTypeWiki)}}disabled{{end}}" id="wiki_box"> | |||
| <div class="field"> | |||
| <div class="ui radio checkbox"> | |||
| <input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="false" data-target="#external_wiki_box" {{if not .Repository.EnableExternalWiki}}checked{{end}}/> | |||
| <input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="false" data-target="#external_wiki_box" {{if not (.Repository.EnableUnit $.UnitTypeExternalWiki)}}checked{{end}}/> | |||
| <label>{{.i18n.Tr "repo.settings.use_internal_wiki"}}</label> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="ui radio checkbox"> | |||
| <input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="true" data-target="#external_wiki_box" {{if .Repository.EnableExternalWiki}}checked{{end}}/> | |||
| <input class="hidden enable-system-radio" tabindex="0" name="enable_external_wiki" type="radio" value="true" data-target="#external_wiki_box" {{if .Repository.EnableUnit $.UnitTypeExternalWiki}}checked{{end}}/> | |||
| <label>{{.i18n.Tr "repo.settings.use_external_wiki"}}</label> | |||
| </div> | |||
| </div> | |||
| <div class="field {{if not .Repository.EnableExternalWiki}}disabled{{end}}" id="external_wiki_box"> | |||
| <div class="field {{if not (.Repository.EnableUnit $.UnitTypeExternalWiki)}}disabled{{end}}" id="external_wiki_box"> | |||
| <label for="external_wiki_url">{{.i18n.Tr "repo.settings.external_wiki_url"}}</label> | |||
| <input id="external_wiki_url" name="external_wiki_url" type="url" value="{{.Repository.ExternalWikiURL}}"> | |||
| <input id="external_wiki_url" name="external_wiki_url" type="url" value="{{(.Repository.MustGetUnit $.UnitTypeExternalWiki).ExternalWikiConfig.ExternalWikiURL}}"> | |||
| <p class="help">{{.i18n.Tr "repo.settings.external_wiki_url_desc"}}</p> | |||
| </div> | |||
| </div> | |||
| @@ -143,45 +143,47 @@ | |||
| <div class="inline field"> | |||
| <label>{{.i18n.Tr "repo.issues"}}</label> | |||
| <div class="ui checkbox"> | |||
| <input class="enable-system" name="enable_issues" type="checkbox" data-target="#issue_box" {{if .Repository.EnableIssues}}checked{{end}}> | |||
| <input class="enable-system" name="enable_issues" type="checkbox" data-target="#issue_box" {{if or (.Repository.EnableUnit $.UnitTypeIssues) (.Repository.EnableUnit $.UnitTypeExternalTracker)}}checked{{end}}> | |||
| <label>{{.i18n.Tr "repo.settings.issues_desc"}}</label> | |||
| </div> | |||
| </div> | |||
| <div class="field {{if not .Repository.EnableIssues}}disabled{{end}}" id="issue_box"> | |||
| <div class="field {{if not (.Repository.EnableUnit $.UnitTypeIssues)}}disabled{{end}}" id="issue_box"> | |||
| <div class="field"> | |||
| <div class="ui radio checkbox"> | |||
| <input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="false" data-target="#external_issue_box" {{if not .Repository.EnableExternalTracker}}checked{{end}}/> | |||
| <input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="false" data-target="#external_issue_box" {{if not (.Repository.EnableUnit $.UnitTypeExternalTracker)}}checked{{end}}/> | |||
| <label>{{.i18n.Tr "repo.settings.use_internal_issue_tracker"}}</label> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="ui radio checkbox"> | |||
| <input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="true" data-target="#external_issue_box" {{if .Repository.EnableExternalTracker}}checked{{end}}/> | |||
| <input class="hidden enable-system-radio" tabindex="0" name="enable_external_tracker" type="radio" value="true" data-target="#external_issue_box" {{if .Repository.EnableUnit $.UnitTypeExternalTracker}}checked{{end}}/> | |||
| <label>{{.i18n.Tr "repo.settings.use_external_issue_tracker"}}</label> | |||
| </div> | |||
| </div> | |||
| <div class="field {{if not .Repository.EnableExternalTracker}}disabled{{end}}" id="external_issue_box"> | |||
| <div class="field {{if not (.Repository.EnableUnit $.UnitTypeExternalTracker)}}disabled{{end}}" id="external_issue_box"> | |||
| <div class="field"> | |||
| <label for="external_tracker_url">{{.i18n.Tr "repo.settings.external_tracker_url"}}</label> | |||
| <input id="external_tracker_url" name="external_tracker_url" type="url" value="{{.Repository.ExternalTrackerURL}}"> | |||
| <input id="external_tracker_url" name="external_tracker_url" type="url" value="{{(.Repository.MustGetUnit $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerURL}}"> | |||
| <p class="help">{{.i18n.Tr "repo.settings.external_tracker_url_desc"}}</p> | |||
| </div> | |||
| <div class="field"> | |||
| <label for="tracker_url_format">{{.i18n.Tr "repo.settings.tracker_url_format"}}</label> | |||
| <input id="tracker_url_format" name="tracker_url_format" type="url" value="{{.Repository.ExternalTrackerFormat}}" placeholder="e.g. https://github.com/{user}/{repo}/issues/{index}"> | |||
| <input id="tracker_url_format" name="tracker_url_format" type="url" value="{{(.Repository.MustGetUnit $.UnitTypeExternalTracker).ExternalTrackerConfig.ExternalTrackerFormat}}" placeholder="e.g. https://github.com/{user}/{repo}/issues/{index}"> | |||
| <p class="help">{{.i18n.Tr "repo.settings.tracker_url_format_desc" | Str2html}}</p> | |||
| </div> | |||
| <div class="inline fields"> | |||
| <label for="issue_style">{{.i18n.Tr "repo.settings.tracker_issue_style"}}</label> | |||
| <div class="field"> | |||
| <div class="ui radio checkbox"> | |||
| <input class="hidden" tabindex="0" name="tracker_issue_style" type="radio" value="numeric" {{if eq .Repository.ExternalTrackerStyle "numeric"}}checked=""{{end}}/> | |||
| {{$externalTracker := (.Repository.MustGetUnit $.UnitTypeExternalTracker)}} | |||
| {{$externalTrackerStyle := $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle}} | |||
| <input class="hidden" tabindex="0" name="tracker_issue_style" type="radio" value="numeric" {{if $externalTrackerStyle}}{{if eq $externalTrackerStyle "numeric"}}checked=""{{end}}{{end}}/> | |||
| <label>{{.i18n.Tr "repo.settings.tracker_issue_style.numeric"}} <span class="ui light grey text">(#1234)</span></label> | |||
| </div> | |||
| </div> | |||
| <div class="field"> | |||
| <div class="ui radio checkbox"> | |||
| <input class="hidden" tabindex="0" name="tracker_issue_style" type="radio" value="alphanumeric" {{if eq .Repository.ExternalTrackerStyle "alphanumeric"}}checked=""{{end}}/> | |||
| <input class="hidden" tabindex="0" name="tracker_issue_style" type="radio" value="alphanumeric" {{if $externalTrackerStyle}}{{if eq $externalTracker.ExternalTrackerConfig.ExternalTrackerStyle "alphanumeric"}}checked=""{{end}}{{end}} /> | |||
| <label>{{.i18n.Tr "repo.settings.tracker_issue_style.alphanumeric"}} <span class="ui light grey text">(ABC-123, DEFG-234)</span></label> | |||
| </div> | |||
| </div> | |||
| @@ -195,7 +197,7 @@ | |||
| <div class="inline field"> | |||
| <label>{{.i18n.Tr "repo.pulls"}}</label> | |||
| <div class="ui checkbox"> | |||
| <input name="enable_pulls" type="checkbox" {{if .Repository.EnablePulls}}checked{{end}}> | |||
| <input name="enable_pulls" type="checkbox" {{if .Repository.EnableUnit $.UnitTypePullRequests}}checked{{end}}> | |||
| <label>{{.i18n.Tr "repo.settings.pulls_desc"}}</label> | |||
| </div> | |||
| </div> | |||
| @@ -236,7 +238,7 @@ | |||
| </div> | |||
| </div> | |||
| {{if .Repository.EnableWiki}} | |||
| {{if .Repository.EnableUnit $.UnitTypeWiki}} | |||
| <div class="ui divider"></div> | |||
| <div class="item"> | |||
| @@ -370,7 +372,7 @@ | |||
| </div> | |||
| </div> | |||
| {{if .Repository.EnableWiki}} | |||
| {{if .Repository.EnableUnit $.UnitTypeWiki}} | |||
| <div class="ui small modal" id="delete-wiki-modal"> | |||
| <div class="header"> | |||
| {{.i18n.Tr "repo.settings.wiki-delete"}} | |||