V20220110.patch
into V20220125
2 years ago
@@ -58,7 +58,7 @@ func createOutdatedPR(t *testing.T, actor, forkOrg *models.User) *models.PullReq | |||
assert.NoError(t, err) | |||
assert.NotEmpty(t, baseRepo) | |||
headRepo, err := repo_module.ForkRepository(actor, forkOrg, baseRepo, "repo-pr-update", "desc") | |||
headRepo, err := repo_module.ForkRepository(actor, forkOrg, baseRepo, "repo-pr-update", "desc", "") | |||
assert.NoError(t, err) | |||
assert.NotEmpty(t, headRepo) | |||
@@ -164,12 +164,24 @@ func (a *Action) GetRepoName() string { | |||
return a.Repo.Name | |||
} | |||
// GetRepoName returns the name of the action repository. | |||
func (a *Action) GetRepoDisplayName() string { | |||
a.loadRepo() | |||
return a.Repo.DisplayName() | |||
} | |||
// ShortRepoName returns the name of the action repository | |||
// trimmed to max 33 chars. | |||
func (a *Action) ShortRepoName() string { | |||
return base.EllipsisString(a.GetRepoName(), 33) | |||
} | |||
// ShortRepoName returns the name of the action repository | |||
// trimmed to max 33 chars. | |||
func (a *Action) ShortRepoDisplayName() string { | |||
return base.EllipsisString(a.GetRepoDisplayName(), 33) | |||
} | |||
// GetRepoPath returns the virtual path to the action repository. | |||
func (a *Action) GetRepoPath() string { | |||
return path.Join(a.GetRepoUserName(), a.GetRepoName()) | |||
@@ -181,6 +193,12 @@ func (a *Action) ShortRepoPath() string { | |||
return path.Join(a.ShortRepoUserName(), a.ShortRepoName()) | |||
} | |||
// ShortRepoPath returns the virtual path to the action repository | |||
// trimmed to max 20 + 1 + 33 chars. | |||
func (a *Action) ShortRepoFullDisplayName() string { | |||
return path.Join(a.ShortRepoUserName(), a.ShortRepoDisplayName()) | |||
} | |||
// GetRepoLink returns relative link to action repository. | |||
func (a *Action) GetRepoLink() string { | |||
if len(setting.AppSubURL) > 0 { | |||
@@ -12,6 +12,7 @@ import ( | |||
"errors" | |||
"fmt" | |||
"html/template" | |||
"math/rand" | |||
"xorm.io/xorm" | |||
"code.gitea.io/gitea/modules/blockchain" | |||
@@ -221,8 +222,10 @@ type Repository struct { | |||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||
Hot int64 `xorm:"-"` | |||
Active int64 `xorm:"-"` | |||
Hot int64 `xorm:"-"` | |||
Active int64 `xorm:"-"` | |||
Alias string `xorm:"INDEX"` | |||
LowerAlias string `xorm:"INDEX"` | |||
} | |||
// SanitizedOriginalURL returns a sanitized OriginalURL | |||
@@ -233,6 +236,14 @@ func (repo *Repository) SanitizedOriginalURL() string { | |||
return util.SanitizeURLCredentials(repo.OriginalURL, false) | |||
} | |||
// GetAlias returns a sanitized OriginalURL | |||
func (repo *Repository) DisplayName() string { | |||
if repo.Alias == "" { | |||
return repo.Name | |||
} | |||
return repo.Alias | |||
} | |||
// ColorFormat returns a colored string to represent this repo | |||
func (repo *Repository) ColorFormat(s fmt.State) { | |||
var ownerName interface{} | |||
@@ -286,6 +297,11 @@ func (repo *Repository) FullName() string { | |||
return repo.OwnerName + "/" + repo.Name | |||
} | |||
// FullDisplayName returns the repository full display name | |||
func (repo *Repository) FullDisplayName() string { | |||
return repo.OwnerName + "/" + repo.DisplayName() | |||
} | |||
// HTMLURL returns the repository HTML URL | |||
func (repo *Repository) HTMLURL() string { | |||
return setting.AppURL + repo.FullName() | |||
@@ -385,7 +401,9 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) | |||
ID: repo.ID, | |||
Owner: repo.Owner.APIFormat(), | |||
Name: repo.Name, | |||
Alias: repo.Alias, | |||
FullName: repo.FullName(), | |||
FullDisplayName: repo.FullDisplayName(), | |||
Description: repo.Description, | |||
Private: repo.IsPrivate, | |||
Template: repo.IsTemplate, | |||
@@ -921,17 +939,50 @@ func (repo *Repository) DescriptionHTML() template.HTML { | |||
return template.HTML(markup.Sanitize(string(desc))) | |||
} | |||
func isRepositoryExist(e Engine, u *User, repoName string) (bool, error) { | |||
has, err := e.Get(&Repository{ | |||
OwnerID: u.ID, | |||
LowerName: strings.ToLower(repoName), | |||
}) | |||
return has && com.IsDir(RepoPath(u.Name, repoName)), err | |||
func isRepositoryExist(e Engine, u *User, repoName string, alias string) (bool, error) { | |||
var cond = builder.NewCond() | |||
cond = cond.And(builder.Eq{"owner_id": u.ID}) | |||
if alias != "" { | |||
subCon := builder.NewCond() | |||
subCon = subCon.Or(builder.Eq{"lower_alias": strings.ToLower(alias)}, builder.Eq{"lower_name": strings.ToLower(repoName)}) | |||
cond = cond.And(subCon) | |||
} else { | |||
cond = cond.And(builder.Eq{"lower_name": strings.ToLower(repoName)}) | |||
} | |||
count, err := e.Where(cond).Count(&Repository{}) | |||
return count > 0 || com.IsDir(RepoPath(u.Name, repoName)), err | |||
} | |||
// IsRepositoryExist returns true if the repository with given name under user has already existed. | |||
func IsRepositoryExist(u *User, repoName string) (bool, error) { | |||
return isRepositoryExist(x, u, repoName) | |||
func IsRepositoryExist(u *User, repoName string, alias string) (bool, error) { | |||
return isRepositoryExist(x, u, repoName, alias) | |||
} | |||
// IsRepositoryAliasExist returns true if the repository with given alias under user has already existed. | |||
func IsRepositoryAliasExist(u *User, alias string) (bool, error) { | |||
return isRepositoryAliasExist(x, u, alias) | |||
} | |||
func isRepositoryAliasExist(e Engine, u *User, alias string) (bool, error) { | |||
var cond = builder.NewCond() | |||
cond = cond.And(builder.Eq{"owner_id": u.ID}) | |||
cond = cond.And(builder.Eq{"lower_alias": strings.ToLower(alias)}) | |||
count, err := e.Where(cond).Count(&Repository{}) | |||
return count > 0, err | |||
} | |||
func IsRepositoryAliasAvailable(doer *User, alias string) error { | |||
if err := IsUsableRepoAlias(alias); err != nil { | |||
return err | |||
} | |||
has, err := IsRepositoryAliasExist(doer, alias) | |||
if err != nil { | |||
return fmt.Errorf("IsRepositoryExist: %v", err) | |||
} else if has { | |||
return ErrRepoAlreadyExist{doer.Name, alias} | |||
} | |||
return nil | |||
} | |||
// CloneLink represents different types of clone URLs of repository. | |||
@@ -975,20 +1026,24 @@ func (repo *Repository) CloneLink() (cl *CloneLink) { | |||
} | |||
// CheckCreateRepository check if could created a repository | |||
func CheckCreateRepository(doer, u *User, name string) error { | |||
func CheckCreateRepository(doer, u *User, repoName, alias string) error { | |||
if !doer.CanCreateRepo() { | |||
return ErrReachLimitOfRepo{u.MaxRepoCreation} | |||
} | |||
if err := IsUsableRepoName(name); err != nil { | |||
if err := IsUsableRepoName(repoName); err != nil { | |||
return err | |||
} | |||
has, err := isRepositoryExist(x, u, name) | |||
if err := IsUsableRepoAlias(alias); err != nil { | |||
return err | |||
} | |||
has, err := isRepositoryExist(x, u, repoName, alias) | |||
if err != nil { | |||
return fmt.Errorf("IsRepositoryExist: %v", err) | |||
} else if has { | |||
return ErrRepoAlreadyExist{u.Name, name} | |||
return ErrRepoAlreadyExist{u.Name, repoName} | |||
} | |||
return nil | |||
} | |||
@@ -996,6 +1051,7 @@ func CheckCreateRepository(doer, u *User, name string) error { | |||
// CreateRepoOptions contains the create repository options | |||
type CreateRepoOptions struct { | |||
Name string | |||
Alias string | |||
Description string | |||
OriginalURL string | |||
GitServiceType api.GitServiceType | |||
@@ -1036,8 +1092,10 @@ func GetRepoInitFile(tp, name string) ([]byte, error) { | |||
} | |||
var ( | |||
reservedRepoNames = []string{".", ".."} | |||
reservedRepoPatterns = []string{"*.git", "*.wiki"} | |||
reservedRepoNames = []string{".", ".."} | |||
reservedRepoPatterns = []string{"*.git", "*.wiki"} | |||
reservedRepoAliasNames = []string{} | |||
reservedRepoAliasPatterns = []string{} | |||
) | |||
// IsUsableRepoName returns true when repository is usable | |||
@@ -1045,13 +1103,22 @@ func IsUsableRepoName(name string) error { | |||
return isUsableName(reservedRepoNames, reservedRepoPatterns, name) | |||
} | |||
// IsUsableRepoAlias returns true when repository alias is usable | |||
func IsUsableRepoAlias(name string) error { | |||
return isUsableName(reservedRepoAliasNames, reservedRepoAliasPatterns, name) | |||
} | |||
// CreateRepository creates a repository for the user/organization. | |||
func CreateRepository(ctx DBContext, doer, u *User, repo *Repository) (err error) { | |||
repo.LowerAlias = strings.ToLower(repo.Alias) | |||
if err = IsUsableRepoName(repo.Name); err != nil { | |||
return err | |||
} | |||
has, err := isRepositoryExist(ctx.e, u, repo.Name) | |||
if err := IsUsableRepoAlias(repo.Alias); err != nil { | |||
return err | |||
} | |||
has, err := isRepositoryExist(ctx.e, u, repo.Name, repo.Alias) | |||
if err != nil { | |||
return fmt.Errorf("IsRepositoryExist: %v", err) | |||
} else if has { | |||
@@ -1233,7 +1300,7 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error | |||
} | |||
// Check if new owner has repository with same name. | |||
has, err := IsRepositoryExist(newOwner, repo.Name) | |||
has, err := IsRepositoryExist(newOwner, repo.Name, repo.Alias) | |||
if err != nil { | |||
return fmt.Errorf("IsRepositoryExist: %v", err) | |||
} else if has { | |||
@@ -1366,7 +1433,7 @@ func ChangeRepositoryName(doer *User, repo *Repository, newRepoName string) (err | |||
return err | |||
} | |||
has, err := IsRepositoryExist(repo.Owner, newRepoName) | |||
has, err := IsRepositoryExist(repo.Owner, newRepoName, "") | |||
if err != nil { | |||
return fmt.Errorf("IsRepositoryExist: %v", err) | |||
} else if has { | |||
@@ -1848,6 +1915,26 @@ func getRepositoryByOwnerAndName(e Engine, ownerName, repoName string) (*Reposit | |||
return &repo, nil | |||
} | |||
// GetRepositoryByOwnerAndAlias returns the repository by given ownername and reponame. | |||
func GetRepositoryByOwnerAndAlias(ownerName, alias string) (*Repository, error) { | |||
return getRepositoryByOwnerAndAlias(x, ownerName, alias) | |||
} | |||
func getRepositoryByOwnerAndAlias(e Engine, ownerName, alias string) (*Repository, error) { | |||
var repo Repository | |||
has, err := e.Table("repository").Select("repository.*"). | |||
Join("INNER", "`user`", "`user`.id = repository.owner_id"). | |||
Where("repository.lower_alias = ?", strings.ToLower(alias)). | |||
And("`user`.lower_name = ?", strings.ToLower(ownerName)). | |||
Get(&repo) | |||
if err != nil { | |||
return nil, err | |||
} else if !has { | |||
return nil, ErrRepoNotExist{0, 0, ownerName, alias} | |||
} | |||
return &repo, nil | |||
} | |||
// GetRepositoryByName returns the repository by given name under user if exists. | |||
func GetRepositoryByName(ownerID int64, name string) (*Repository, error) { | |||
repo := &Repository{ | |||
@@ -2521,6 +2608,14 @@ func UpdateRepositoryCommitNum(repo *Repository) error { | |||
return nil | |||
} | |||
func GenerateDefaultRepoName(ownerName string) string { | |||
if len(ownerName) > 5 { | |||
ownerName = ownerName[:5] | |||
} | |||
now := time.Now().Format("20060102150405") | |||
return ownerName + now + fmt.Sprint(rand.Intn(10)) | |||
} | |||
type RepoFile struct { | |||
CommitId string | |||
Content []byte | |||
@@ -19,6 +19,7 @@ import ( | |||
// GenerateRepoOptions contains the template units to generate | |||
type GenerateRepoOptions struct { | |||
Name string | |||
Alias string | |||
Description string | |||
Private bool | |||
GitContent bool | |||
@@ -200,8 +200,8 @@ const ( | |||
SearchOrderByForks SearchOrderBy = "num_forks ASC" | |||
SearchOrderByForksReverse SearchOrderBy = "num_forks DESC" | |||
SearchOrderByDownloadTimes SearchOrderBy = "download_times DESC" | |||
SearchOrderByHot SearchOrderBy = "(num_watches + num_stars + num_forks + clone_cnt) DESC" | |||
SearchOrderByActive SearchOrderBy = "(num_issues + num_pulls + num_commit) DESC" | |||
SearchOrderByHot SearchOrderBy = "(num_watches + num_stars + num_forks + clone_cnt) DESC" | |||
SearchOrderByActive SearchOrderBy = "(num_issues + num_pulls + num_commit) DESC" | |||
) | |||
// SearchRepositoryCondition creates a query condition according search repository options | |||
@@ -321,6 +321,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { | |||
var likes = builder.NewCond() | |||
for _, v := range strings.Split(opts.Keyword, ",") { | |||
likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)}) | |||
likes = likes.Or(builder.Like{"alias", v}) | |||
if opts.IncludeDescription { | |||
likes = likes.Or(builder.Like{"LOWER(description)", strings.ToLower(v)}) | |||
} | |||
@@ -28,6 +28,7 @@ type OfficialTagRepos struct { | |||
type TagReposBrief struct { | |||
RepoID int64 | |||
RepoName string | |||
Alias string | |||
TagID int64 | |||
} | |||
@@ -97,7 +98,7 @@ func UpdateTagReposByID(tagID, orgID int64, repoIdList []int64) error { | |||
func GetTagRepos(tagID, orgID int64) ([]TagReposSelected, error) { | |||
t := make([]TagReposBrief, 0) | |||
const SQLCmd = "select t1.id as repo_id,t1.name as repo_name,t2.id as tag_id from repository t1 left join official_tag_repos t2 on (t1.id = t2.repo_id and t2.tag_id = ?) where t1.owner_id = ? and t1.is_private = false order by t1.updated_unix desc" | |||
const SQLCmd = "select t1.id as repo_id,t1.name as repo_name,t1.alias,t2.id as tag_id from repository t1 left join official_tag_repos t2 on (t1.id = t2.repo_id and t2.tag_id = ?) where t1.owner_id = ? and t1.is_private = false order by t1.updated_unix desc" | |||
if err := x.SQL(SQLCmd, tagID, orgID).Find(&t); err != nil { | |||
return nil, err | |||
@@ -108,9 +109,13 @@ func GetTagRepos(tagID, orgID int64) ([]TagReposSelected, error) { | |||
if v.TagID > 0 { | |||
selected = true | |||
} | |||
repoName := v.Alias | |||
if v.Alias == "" { | |||
repoName = v.RepoName | |||
} | |||
r = append(r, TagReposSelected{ | |||
RepoID: v.RepoID, | |||
RepoName: v.RepoName, | |||
RepoName: repoName, | |||
Selected: selected, | |||
}) | |||
} | |||
@@ -186,6 +186,8 @@ func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaro | |||
data["ErrorMsg"] = trName + l.Tr("form.include_error", GetInclude(field)) | |||
case validation.ErrGlobPattern: | |||
data["ErrorMsg"] = trName + l.Tr("form.glob_pattern_error", errs[0].Message) | |||
case validation.ErrAlphaDashDotChinese: | |||
data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_chinese_error") | |||
default: | |||
data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification | |||
} | |||
@@ -29,6 +29,7 @@ import ( | |||
type CreateRepoForm struct { | |||
UID int64 `binding:"Required"` | |||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"` | |||
Alias string `binding:"Required;MaxSize(100);AlphaDashDotChinese"` | |||
Private bool | |||
Description string `binding:"MaxSize(1024)"` | |||
DefaultBranch string `binding:"GitRefName;MaxSize(100)"` | |||
@@ -62,6 +63,7 @@ type MigrateRepoForm struct { | |||
UID int64 `json:"uid" binding:"Required"` | |||
// required: true | |||
RepoName string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"` | |||
Alias string `json:"alias" binding:"Required;AlphaDashDotChinese;MaxSize(100)"` | |||
Mirror bool `json:"mirror"` | |||
Private bool `json:"private"` | |||
Description string `json:"description" binding:"MaxSize(255)"` | |||
@@ -109,6 +111,7 @@ func (f MigrateRepoForm) ParseRemoteAddr(user *models.User) (string, error) { | |||
// RepoSettingForm form for changing repository settings | |||
type RepoSettingForm struct { | |||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"` | |||
Alias string `binding:"Required;AlphaDashDotChinese;MaxSize(100)"` | |||
Description string `binding:"MaxSize(255)"` | |||
Website string `binding:"ValidUrl;MaxSize(255)"` | |||
Interval string | |||
@@ -154,6 +154,22 @@ func (a *actionNotifier) NotifyRenameRepository(doer *models.User, repo *models. | |||
} | |||
} | |||
func (a *actionNotifier) NotifyAliasRepository(doer *models.User, repo *models.Repository, oldAlias string) { | |||
log.Trace("action.ChangeRepositoryAlias: %s/%s", doer.Name, repo.Alias) | |||
if err := models.NotifyWatchers(&models.Action{ | |||
ActUserID: doer.ID, | |||
ActUser: doer, | |||
OpType: models.ActionRenameRepo, | |||
RepoID: repo.ID, | |||
Repo: repo, | |||
IsPrivate: repo.IsPrivate, | |||
Content: oldAlias, | |||
}); err != nil { | |||
log.Error("NotifyWatchers: %v", err) | |||
} | |||
} | |||
func (a *actionNotifier) NotifyTransferRepository(doer *models.User, repo *models.Repository, oldOwnerName string) { | |||
if err := models.NotifyWatchers(&models.Action{ | |||
ActUserID: doer.ID, | |||
@@ -18,6 +18,7 @@ type Notifier interface { | |||
NotifyDeleteRepository(doer *models.User, repo *models.Repository) | |||
NotifyForkRepository(doer *models.User, oldRepo, repo *models.Repository) | |||
NotifyRenameRepository(doer *models.User, repo *models.Repository, oldRepoName string) | |||
NotifyAliasRepository(doer *models.User, repo *models.Repository, oldAlias string) | |||
NotifyTransferRepository(doer *models.User, repo *models.Repository, oldOwnerName string) | |||
NotifyNewIssue(*models.Issue) | |||
@@ -135,6 +135,10 @@ func (*NullNotifier) NotifyDeleteRef(doer *models.User, repo *models.Repository, | |||
func (*NullNotifier) NotifyRenameRepository(doer *models.User, repo *models.Repository, oldRepoName string) { | |||
} | |||
func (a *NullNotifier) NotifyAliasRepository(doer *models.User, repo *models.Repository, oldAlias string) { | |||
} | |||
// NotifyTransferRepository places a place holder function | |||
func (*NullNotifier) NotifyTransferRepository(doer *models.User, repo *models.Repository, oldOwnerName string) { | |||
} | |||
@@ -28,6 +28,7 @@ func CreateRepository(doer, u *models.User, opts models.CreateRepoOptions) (_ *m | |||
Owner: u, | |||
OwnerName: u.Name, | |||
Name: opts.Name, | |||
Alias: opts.Alias, | |||
LowerName: strings.ToLower(opts.Name), | |||
Description: opts.Description, | |||
OriginalURL: opts.OriginalURL, | |||
@@ -15,7 +15,7 @@ import ( | |||
) | |||
// ForkRepository forks a repository | |||
func ForkRepository(doer, owner *models.User, oldRepo *models.Repository, name, desc string) (_ *models.Repository, err error) { | |||
func ForkRepository(doer, owner *models.User, oldRepo *models.Repository, name, desc, alias string) (_ *models.Repository, err error) { | |||
forkedRepo, err := oldRepo.GetUserFork(owner.ID) | |||
if err != nil { | |||
return nil, err | |||
@@ -33,6 +33,7 @@ func ForkRepository(doer, owner *models.User, oldRepo *models.Repository, name, | |||
Owner: owner, | |||
OwnerName: owner.Name, | |||
Name: name, | |||
Alias: alias, | |||
LowerName: strings.ToLower(name), | |||
Description: desc, | |||
DefaultBranch: oldRepo.DefaultBranch, | |||
@@ -18,7 +18,7 @@ func TestForkRepository(t *testing.T) { | |||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 13}).(*models.User) | |||
repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 10}).(*models.Repository) | |||
fork, err := ForkRepository(user, user, repo, "test", "test") | |||
fork, err := ForkRepository(user, user, repo, "test", "test", "test") | |||
assert.Nil(t, fork) | |||
assert.Error(t, err) | |||
assert.True(t, models.IsErrForkAlreadyExist(err)) | |||
@@ -236,6 +236,7 @@ func GenerateRepository(ctx models.DBContext, doer, owner *models.User, template | |||
Owner: owner, | |||
OwnerName: owner.Name, | |||
Name: opts.Name, | |||
Alias: opts.Alias, | |||
LowerName: strings.ToLower(opts.Name), | |||
Description: opts.Description, | |||
IsPrivate: opts.Private, | |||
@@ -51,7 +51,7 @@ func prepareRepoCommit(ctx models.DBContext, repo *models.Repository, tmpDir, re | |||
cloneLink := repo.CloneLink() | |||
match := map[string]string{ | |||
"Name": repo.Name, | |||
"Name": repo.DisplayName(), | |||
"Description": repo.Description, | |||
"CloneURL.SSH": cloneLink.SSH, | |||
"CloneURL.HTTPS": cloneLink.HTTPS, | |||
@@ -46,31 +46,33 @@ type ExternalWiki struct { | |||
// Repository represents a repository | |||
type Repository struct { | |||
ID int64 `json:"id"` | |||
Owner *User `json:"owner"` | |||
Name string `json:"name"` | |||
FullName string `json:"full_name"` | |||
Description string `json:"description"` | |||
Empty bool `json:"empty"` | |||
Private bool `json:"private"` | |||
Fork bool `json:"fork"` | |||
Template bool `json:"template"` | |||
Parent *Repository `json:"parent"` | |||
Mirror bool `json:"mirror"` | |||
Size int `json:"size"` | |||
HTMLURL string `json:"html_url"` | |||
SSHURL string `json:"ssh_url"` | |||
CloneURL string `json:"clone_url"` | |||
OriginalURL string `json:"original_url"` | |||
Website string `json:"website"` | |||
Stars int `json:"stars_count"` | |||
Forks int `json:"forks_count"` | |||
Watchers int `json:"watchers_count"` | |||
OpenIssues int `json:"open_issues_count"` | |||
OpenPulls int `json:"open_pr_counter"` | |||
Releases int `json:"release_counter"` | |||
DefaultBranch string `json:"default_branch"` | |||
Archived bool `json:"archived"` | |||
ID int64 `json:"id"` | |||
Owner *User `json:"owner"` | |||
Name string `json:"name"` | |||
Alias string `json:"alias"` | |||
FullName string `json:"full_name"` | |||
FullDisplayName string `json:"full_display_name"` | |||
Description string `json:"description"` | |||
Empty bool `json:"empty"` | |||
Private bool `json:"private"` | |||
Fork bool `json:"fork"` | |||
Template bool `json:"template"` | |||
Parent *Repository `json:"parent"` | |||
Mirror bool `json:"mirror"` | |||
Size int `json:"size"` | |||
HTMLURL string `json:"html_url"` | |||
SSHURL string `json:"ssh_url"` | |||
CloneURL string `json:"clone_url"` | |||
OriginalURL string `json:"original_url"` | |||
Website string `json:"website"` | |||
Stars int `json:"stars_count"` | |||
Forks int `json:"forks_count"` | |||
Watchers int `json:"watchers_count"` | |||
OpenIssues int `json:"open_issues_count"` | |||
OpenPulls int `json:"open_pr_counter"` | |||
Releases int `json:"release_counter"` | |||
DefaultBranch string `json:"default_branch"` | |||
Archived bool `json:"archived"` | |||
// swagger:strfmt date-time | |||
Created time.Time `json:"created_at"` | |||
// swagger:strfmt date-time | |||
@@ -217,6 +219,7 @@ type MigrateRepoOption struct { | |||
UID int `json:"uid" binding:"Required"` | |||
// required: true | |||
RepoName string `json:"repo_name" binding:"Required"` | |||
Alias string `json:"alias" binding:"Required"` | |||
Mirror bool `json:"mirror"` | |||
Private bool `json:"private"` | |||
Description string `json:"description"` | |||
@@ -84,6 +84,7 @@ func CreateMigrateTask(doer, u *models.User, opts base.MigrateOptions) (*models. | |||
repo, err := repo_module.CreateRepository(doer, u, models.CreateRepoOptions{ | |||
Name: opts.RepoName, | |||
Alias: opts.Alias, | |||
Description: opts.Description, | |||
OriginalURL: opts.OriginalURL, | |||
GitServiceType: opts.GitServiceType, | |||
@@ -19,6 +19,8 @@ const ( | |||
// ErrGlobPattern is returned when glob pattern is invalid | |||
ErrGlobPattern = "GlobPattern" | |||
ErrAlphaDashDotChinese = "AlphaDashDotChineseError" | |||
) | |||
var ( | |||
@@ -26,6 +28,8 @@ var ( | |||
// They cannot have ASCII control characters (i.e. bytes whose values are lower than \040, or \177 DEL), space, tilde ~, caret ^, or colon : anywhere. | |||
// They cannot have question-mark ?, asterisk *, or open bracket [ anywhere | |||
GitRefNamePatternInvalid = regexp.MustCompile(`[\000-\037\177 \\~^:?*[]+`) | |||
AlphaDashDotChinese = regexp.MustCompile("^[\u4e00-\u9fa5\\.\\-_A-Za-z0-9]+$") | |||
) | |||
// CheckGitRefAdditionalRulesValid check name is valid on additional rules | |||
@@ -53,6 +57,7 @@ func AddBindingRules() { | |||
addGitRefNameBindingRule() | |||
addValidURLBindingRule() | |||
addGlobPatternRule() | |||
addAlphaDashDotChineseRule() | |||
} | |||
func addGitRefNameBindingRule() { | |||
@@ -117,6 +122,21 @@ func addGlobPatternRule() { | |||
}) | |||
} | |||
func addAlphaDashDotChineseRule() { | |||
binding.AddRule(&binding.Rule{ | |||
IsMatch: func(rule string) bool { | |||
return strings.HasPrefix(rule, "AlphaDashDotChinese") | |||
}, | |||
IsValid: func(errs binding.Errors, name string, val interface{}) (bool, binding.Errors) { | |||
if !ValidAlphaDashDotChinese(fmt.Sprintf("%v", val)) { | |||
errs.Add([]string{name}, ErrAlphaDashDotChinese, "ErrAlphaDashDotChinese") | |||
return false, errs | |||
} | |||
return true, errs | |||
}, | |||
}) | |||
} | |||
func portOnly(hostport string) string { | |||
colon := strings.IndexByte(hostport, ':') | |||
if colon == -1 { | |||
@@ -139,3 +159,7 @@ func validPort(p string) bool { | |||
} | |||
return true | |||
} | |||
func ValidAlphaDashDotChinese(value string) bool { | |||
return AlphaDashDotChinese.MatchString(value) | |||
} |
@@ -346,7 +346,9 @@ modify = Update | |||
[form] | |||
UserName = Username | |||
RepoName = Repository name | |||
Alias = Repository name | |||
RepoPath = Repository path | |||
RepoAdress = Repository Adress | |||
Email = Email address | |||
Password = Password | |||
Retype = Re-Type Password | |||
@@ -370,7 +372,10 @@ SSPIDefaultLanguage = Default Language | |||
require_error = ` cannot be empty.` | |||
alpha_dash_error = ` should contain only alphanumeric, dash ('-') and underscore ('_') characters.` | |||
alpha_dash_dot_error = ` should contain only alphanumeric, dash ('-'), underscore ('_') and dot ('.') characters.` | |||
reponame_dash_dot_error=` Please enter Chinese, alphanumeric, dash ('-') ,underscore ('_') and dot ('.')characters, up to 100 characters. ` | |||
repoadd_dash_dot_error=` Path only allows input alphanumeric, dash ('-') ,underscore ('_') and dot ('.')characters, up to 100 characters. ` | |||
git_ref_name_error = ` must be a well-formed Git reference name.` | |||
alpha_dash_dot_chinese_error= ` should contain only alphanumeric, chinese, dash ('-') and underscore ('_') characters.` | |||
size_error = ` must be size %s.` | |||
min_size_error = ` must contain at least %s characters.` | |||
max_size_error = ` must contain at most %s characters.` | |||
@@ -384,7 +389,7 @@ password_not_match = The passwords do not match. | |||
lang_select_error = Select a language from the list. | |||
username_been_taken = The username is already taken. | |||
repo_name_been_taken = The repository name is already used. | |||
repo_name_been_taken = The repository name or path is already used. | |||
visit_rate_limit = Remote visit addressed rate limitation. | |||
2fa_auth_required = Remote visit required two factors authentication. | |||
org_name_been_taken = The organization name is already taken. | |||
@@ -897,7 +902,7 @@ modelarts.train_job.description=Description | |||
modelarts.train_job.parameter_setting=Parameter setting | |||
modelarts.train_job.parameter_setting_info=Parameter Info | |||
modelarts.train_job.fast_parameter_setting=fast_parameter_setting | |||
modelarts.train_job.fast_parameter_setting_config=fast_parameter_setting_config | |||
modelarts.train_job.fast_parameter_setting_config=fast_parameter_setting_config | |||
modelarts.train_job.fast_parameter_setting_config_link=fast_parameter_setting_config_link | |||
modelarts.train_job.frames=frames | |||
modelarts.train_job.algorithm_origin=Algorithm Origin | |||
@@ -964,6 +969,9 @@ template.avatar = Avatar | |||
template.issue_labels = Issue Labels | |||
template.one_item = Must select at least one template item | |||
template.invalid = Must select a template repository | |||
template.repo_adress=Adress | |||
template.repo_path=path | |||
template.repo_name=Name | |||
archive.title = This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests. | |||
archive.issue.nocomment = This repo is archived. You cannot comment on issues. | |||
@@ -1184,7 +1192,7 @@ issues.filter_label_exclude = `Use <code>alt</code> + <code>click/enter</code> t | |||
issues.filter_label_no_select = All labels | |||
issues.filter_milestone = Milestone | |||
issues.filter_milestone_no_select = All milestones | |||
issues.filter_milestone_no_add = Not add milestones | |||
issues.filter_milestone_no_add = Not add milestones | |||
issues.filter_assignee = Assignee | |||
issues.filter_assginee_no_select = All assignees | |||
issues.filter_type = Type | |||
@@ -350,7 +350,10 @@ modify=更新 | |||
[form] | |||
UserName=用户名 | |||
RepoName=项目名称 | |||
RepoName=项目路径 | |||
Alias=项目名称 | |||
RepoPath=项目路径 | |||
RepoAdress=项目地址 | |||
Email=邮箱地址 | |||
Password=密码 | |||
Retype=重新输入密码 | |||
@@ -374,7 +377,10 @@ SSPIDefaultLanguage=默认语言 | |||
require_error=不能为空。 | |||
alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。 | |||
alpha_dash_dot_error=应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。 | |||
reponame_dash_dot_error=请输入中文、字母、数字和-_ .,最多100个字符。 | |||
repoadd_dash_dot_error=路径只允许字母、数字和-_ .,最多100个字符。 | |||
git_ref_name_error=` 必须是格式良好的 git 引用名称。` | |||
alpha_dash_dot_chinese_error=应该只包含字母数字中文, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。 | |||
size_error=长度必须为 %s。 | |||
min_size_error=长度最小为 %s 个字符。 | |||
max_size_error=长度最大为 %s 个字符。 | |||
@@ -388,7 +394,7 @@ password_not_match=密码不匹配。 | |||
lang_select_error=从列表中选出语言 | |||
username_been_taken=用户名已被使用。 | |||
repo_name_been_taken=项目名称已被使用。 | |||
repo_name_been_taken=项目名称或项目路径已被使用。 | |||
visit_rate_limit=远程访问达到速度限制。 | |||
2fa_auth_required=远程访问需要双重验证。 | |||
org_name_been_taken=组织名称已被使用。 | |||
@@ -976,6 +982,9 @@ template.avatar=头像 | |||
template.issue_labels=任务标签 | |||
template.one_item=必须至少选择一个模板项 | |||
template.invalid=必须选择一个模板项目 | |||
template.repo_adress=项目地址 | |||
template.repo_path=项目地址 | |||
template.repo_name=项目名称 | |||
archive.title=此项目已存档。您可以查看文件和克隆,但不能推送或创建任务/合并请求。 | |||
archive.issue.nocomment=此项目已存档,您不能在此任务添加评论。 | |||
@@ -4,7 +4,6 @@ if(isEmpty(token)){ | |||
var meta = $("meta[name=_uid]"); | |||
if(!isEmpty(meta)){ | |||
token = meta.attr("content"); | |||
console.log("token is uid:" + token); | |||
} | |||
} | |||
@@ -33,8 +32,6 @@ var swiperRepo = new Swiper(".homepro-list", { | |||
}); | |||
var output = document.getElementById("newmessage"); | |||
console.log("document.location.host="+document.location.host); | |||
console.log("document.URL="+document.URL); | |||
var url = "ws://" + document.location.host + "/action/notification"; | |||
if(document.location.host == "git.openi.org.cn" || document.URL.startsWith("https")){ | |||
url = "wss://" + document.location.host + "/action/notification" | |||
@@ -51,18 +48,14 @@ var html =document.documentElement; | |||
var lang = html.attributes["lang"] | |||
var isZh = true; | |||
if(lang != null && lang.nodeValue =="en-US" ){ | |||
console.log("the language is " + lang.nodeValue); | |||
isZh=false; | |||
}else{ | |||
console.log("default lang=zh"); | |||
} | |||
socket.onmessage = function (e) { | |||
var data =JSON.parse(e.data) | |||
console.log("recevie data=" + e.data) | |||
var html = ""; | |||
if (data != null){ | |||
console.log("queue length=" + messageQueue.length); | |||
if(messageQueue.length > maxSize){ | |||
delete messageQueue[0]; | |||
}else{ | |||
@@ -71,38 +64,38 @@ socket.onmessage = function (e) { | |||
var currentTime = new Date().getTime(); | |||
for(var i = 0; i < messageQueue.length; i++){ | |||
var record = messageQueue[i]; | |||
var recordPrefix = getMsg(record); | |||
var actionName = getAction(record.OpType,isZh); | |||
if(record.OpType == "6" || record.OpType == "10" || record.OpType == "12" || record.OpType == "13"){ | |||
html += recordPrefix + actionName; | |||
html += " <a href=\"" + getIssueLink(record) + "\" rel=\"nofollow\">" + getIssueText(record) + "</a>" | |||
html += " <a href=\"" + getIssueLink(record) + "\" rel=\"nofollow\">" + getIssueText(record) + "</a>" | |||
} | |||
else if(record.OpType == "7" || record.OpType == "11" || record.OpType == "14" || record.OpType == "15" || record.OpType == "22" | |||
|| record.OpType == "23"){ | |||
html += recordPrefix + actionName; | |||
html += " <a href=\"" + getPRLink(record) + "\" rel=\"nofollow\">" + getPRText(record) + "</a>" | |||
html += " <a href=\"" + getPRLink(record) + "\" rel=\"nofollow\">" + getPRText(record) + "</a>" | |||
} | |||
else if(record.OpType == "1"){ | |||
html += recordPrefix + actionName; | |||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>" | |||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" +getRepotext(record) + "</a>" | |||
} | |||
else if(record.OpType == "9" || record.OpType == "5"){ | |||
branch = "<a href=\"" + getRepoLink(record) + "/src/branch/" + record.RefName + "\" rel=\"nofollow\">" + record.RefName + "</a>" | |||
actionName = actionName.replace("{branch}",branch); | |||
html += recordPrefix + actionName; | |||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>" | |||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>" | |||
}else if(record.OpType == "17"){ | |||
actionName = actionName.replace("{deleteBranchName}",record.RefName); | |||
var repoLink = "<a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>" | |||
var repoLink = "<a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>" | |||
actionName = actionName.replace("{repoName}",repoLink); | |||
html += recordPrefix + actionName; | |||
} | |||
else if(record.OpType == "2"){ | |||
actionName = actionName.replace("{oldRepoName}",record.Content); | |||
html += recordPrefix + actionName; | |||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>" | |||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>" | |||
} | |||
else{ | |||
continue; | |||
@@ -115,17 +108,8 @@ socket.onmessage = function (e) { | |||
html += "</div>"; | |||
html += "</div>"; | |||
} | |||
/* | |||
<div class="swiper-slide item"> | |||
<img class="ui avatar image" src="/user/avatar/zhoupzh/-1" alt=""> | |||
<div class="middle aligned content"> | |||
<a href="/zhoupzh" title="">zhoupzh</a> 合并了合并请求 <a href="/OpenI/aiforge/pulls/1168" rel="nofollow">OpenI/aiforge#1168</a><span class="time-since">22 分钟前</span> | |||
</div> | |||
</div> | |||
*/ | |||
} | |||
console.log("html=" + html) | |||
output.innerHTML = html; | |||
swiperNewMessage.updateSlides(); | |||
swiperNewMessage.updateProgress(); | |||
@@ -136,15 +120,20 @@ function getMsg(record){ | |||
html += "<div class=\"swiper-slide item\">"; | |||
html += " <img class=\"ui avatar image\" src=\"/user/avatar/" + record.ActUser.Name + "/-1\" alt=\"\">" | |||
html += " <div class=\"middle aligned content nowrap\">" | |||
html += " <a href=\"/" + record.ActUser.Name + "\" title=\"\">" + record.ActUser.Name + "</a>" | |||
html += " <a href=\"/" + record.ActUser.Name + "\" title=\"\">" + record.ActUser.Name + "</a>" | |||
return html; | |||
} | |||
function getRepoLink(record){ | |||
return "/" + record.Repo.OwnerName + "/" + record.Repo.Name; | |||
function getRepotext(record){ | |||
if(record.Repo.Alias){ | |||
return record.Repo.OwnerName + "/" + record.Repo.Alias; | |||
}else{ | |||
return record.Repo.OwnerName + "/" + record.Repo.Name; | |||
} | |||
} | |||
function getRepoLink(record){ | |||
return record.Repo.OwnerName + "/" + record.Repo.Name; | |||
} | |||
function getTime(UpdatedUnix,currentTime){ | |||
@@ -154,8 +143,7 @@ function getTime(UpdatedUnix,currentTime){ | |||
if( timeEscSecond < 0){ | |||
timeEscSecond = 1; | |||
} | |||
console.log("currentTime=" + currentTime + " updateUnix=" + UpdatedUnix); | |||
var hours= Math.floor(timeEscSecond / 3600); | |||
//计算相差分钟数 | |||
var leave2 = Math.floor(timeEscSecond % (3600)); //计算小时数后剩余的秒数 | |||
@@ -179,11 +167,16 @@ function getPRLink(record){ | |||
return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/pulls/" + getIssueId(record); | |||
} | |||
function getPRText(record){ | |||
return record.Repo.OwnerName + "/" + record.Repo.Name + "#" + getIssueId(record); | |||
if(record.Repo.Alias){ | |||
return record.Repo.OwnerName + "/" + record.Repo.Alias + "#" + getIssueId(record); | |||
}else{ | |||
return record.Repo.OwnerName + "/" + record.Repo.Name + "#" + getIssueId(record); | |||
} | |||
} | |||
function getIssueLink(record){ | |||
return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/issues/" + getIssueId(record); | |||
} | |||
@@ -204,7 +197,12 @@ function getIssueId(record){ | |||
} | |||
function getIssueText(record){ | |||
return record.Repo.OwnerName + "/" + record.Repo.Name + "#" + getIssueId(record); | |||
if(record.Repo.Alias){ | |||
return record.Repo.OwnerName + "/" + record.Repo.Alias + "#" + getIssueId(record); | |||
}else{ | |||
return record.Repo.OwnerName + "/" + record.Repo.Name + "#" + getIssueId(record); | |||
} | |||
} | |||
/* | |||
@@ -320,11 +318,9 @@ function queryRecommendData(){ | |||
dataType:"json", | |||
async:false, | |||
success:function(json){ | |||
console.log(json); | |||
displayOrg(json); | |||
}, | |||
error:function(response) { | |||
console.log(response); | |||
} | |||
}); | |||
@@ -337,40 +333,14 @@ function queryRecommendData(){ | |||
dataType:"json", | |||
async:false, | |||
success:function(json){ | |||
console.log(json); | |||
displayRepo(json); | |||
}, | |||
error:function(response) { | |||
console.log(response); | |||
} | |||
}); | |||
} | |||
/* | |||
<div class="swiper-slide"> | |||
<div class="ui fluid card"> | |||
<div class="content"> | |||
<span class="right floated meta"> | |||
<i class="star icon"></i>276 <i class="star icon"></i>32 | |||
</span> | |||
<img class="left floated mini ui image" src="/repo-avatars/278-a9f45e21b92b86dbf969c9f70dff1efc"> | |||
<a class="header nowrap" href="/OpenI/aiforge">aiforge </a> | |||
<div class="description nowrap-2"> | |||
本项目是群体化方法与技术的开源实现案例,在基于Gitea的基础上,进一步支持社交化的协同开发、协同学习、协同研究等群体创新实践服务,特别是针对新一代人工智能技术特点,重点支持项目管理、git代码管理、大数据集存储管理与智能计算平台接入。 | |||
</div> | |||
<div class="ui tags nowrap am-mt-10"> | |||
<a class="ui small label topic" href="/explore/repos?q=ai%e5%bc%80%e5%8f%91%e5%b7%a5%e5%85%b7&topic=">ai开发工具</a> | |||
<a class="ui small label topic" href="/explore/repos?q=openi&topic=">openi</a> | |||
<a class="ui small label topic" href="/explore/repos?q=golang&topic=">golang</a> | |||
<a class="ui small label topic" href="/explore/repos?q=git&topic=">git</a> | |||
<a class="ui small label topic" href="/explore/repos?q=pcl&topic=">pcl</a> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
*/ | |||
function displayRepo(json){ | |||
var orgRepo = document.getElementById("recommendrepo"); | |||
var html = ""; | |||
@@ -384,7 +354,7 @@ function displayRepo(json){ | |||
html += " <i class=\"ri-star-line\"></i>" + record["NumStars"] + "<i class=\"ri-git-branch-line am-ml-10\"></i>" + record["NumForks"]; | |||
html += " </span>"; | |||
html += " <img class=\"left floated mini ui image\" src=\"" + record["Avatar"] + "\">"; | |||
html += " <a class=\"header nowrap\" href=\"/" + record["OwnerName"] + "/" + record["Name"] + "\">" + record["Name"] +"</a>"; | |||
html += " <a class=\"header nowrap\" href=\"/" + record["OwnerName"] + "/" + record["Name"] + "\">" + record["Alias"] +"</a>"; | |||
html += " <div class=\"description nowrap-2\">" + record["Description"] + " </div>"; | |||
html += " <div class=\"ui tags nowrap am-mt-10\">" | |||
if(record["Topics"] != null){ | |||
@@ -405,27 +375,6 @@ function displayRepo(json){ | |||
swiperRepo.updateProgress(); | |||
} | |||
/** | |||
* | |||
* <div class="column"> | |||
<div class="ui fluid card"> | |||
<div class="content"> | |||
<div class="ui small header"> | |||
<img class="ui image" src="/user/avatar/OpenI/-1"> | |||
<div class="content nowrap"> | |||
<a href="/OpenI">OpenI</a> 启智社区 | |||
<div class="sub header">39 项目 ・ 60 成员 ・ 23 团队</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
</div> | |||
*/ | |||
//var repoAndOrgZH = new Map([['1', "项目"], ['2', "成员"], ['3', "团队"]]); | |||
//var repoAndOrgEN = new Map([['1', "Repository"], ['2', "Members"], ['3', "Teams"]]); | |||
function getRepoOrOrg(key,isZhLang,numbers=1){ | |||
if(numbers > 1){ | |||
@@ -437,7 +386,6 @@ function getRepoOrOrg(key,isZhLang,numbers=1){ | |||
return repoAndOrgEN[key]; | |||
} | |||
} | |||
function displayOrg(json){ | |||
var orgDiv = document.getElementById("recommendorg"); | |||
var html = ""; | |||
@@ -460,4 +408,4 @@ function displayOrg(json){ | |||
} | |||
} | |||
orgDiv.innerHTML = html; | |||
} | |||
} |
@@ -118,7 +118,7 @@ func CreateFork(ctx *context.APIContext, form api.CreateForkOption) { | |||
forker = org | |||
} | |||
fork, err := repo_service.ForkRepository(ctx.User, forker, repo, repo.Name, repo.Description) | |||
fork, err := repo_service.ForkRepository(ctx.User, forker, repo, repo.Name, repo.Description, repo.Alias) | |||
if err != nil { | |||
ctx.Error(http.StatusInternalServerError, "ForkRepository", err) | |||
return | |||
@@ -625,11 +625,12 @@ func RecommendRepoFromPromote(ctx *context.Context) { | |||
} else { | |||
ownerName := strings.Trim(repoName[0:tmpIndex], " ") | |||
repoName := strings.Trim(repoName[tmpIndex+1:], " ") | |||
repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName) | |||
repo, err := models.GetRepositoryByOwnerAndAlias(ownerName, repoName) | |||
if err == nil { | |||
repoMap := make(map[string]interface{}) | |||
repoMap["ID"] = fmt.Sprint(repo.ID) | |||
repoMap["Name"] = repo.Name | |||
repoMap["Alias"] = repo.Alias | |||
repoMap["OwnerName"] = repo.OwnerName | |||
repoMap["NumStars"] = repo.NumStars | |||
repoMap["NumForks"] = repo.NumForks | |||
@@ -143,7 +143,7 @@ func TeamsRepoAction(ctx *context.Context) { | |||
case "add": | |||
repoName := path.Base(ctx.Query("repo_name")) | |||
var repo *models.Repository | |||
repo, err = models.GetRepositoryByName(ctx.Org.Organization.ID, repoName) | |||
repo, err = models.GetRepositoryByOwnerAndAlias(ctx.Org.Organization.Name, repoName) | |||
if err != nil { | |||
if models.IsErrRepoNotExist(err) { | |||
ctx.Flash.Error(ctx.Tr("org.teams.add_nonexistent_repo")) | |||
@@ -105,6 +105,7 @@ func getForkRepository(ctx *context.Context) *models.Repository { | |||
return nil | |||
} | |||
ctx.Data["ForkFrom"] = forkRepo.Owner.Name + "/" + forkRepo.Name | |||
ctx.Data["ForkDisplayName"] = forkRepo.FullDisplayName() | |||
ctx.Data["ForkFromOwnerID"] = forkRepo.Owner.ID | |||
if err := ctx.User.GetOwnedOrganizations(); err != nil { | |||
@@ -221,7 +222,7 @@ func ForkPost(ctx *context.Context, form auth.CreateRepoForm) { | |||
} | |||
} | |||
repo, err := repo_service.ForkRepository(ctx.User, ctxUser, forkRepo, form.RepoName, form.Description) | |||
repo, err := repo_service.ForkRepository(ctx.User, ctxUser, forkRepo, form.RepoName, form.Description, form.Alias) | |||
if err != nil { | |||
ctx.Data["Err_RepoName"] = true | |||
switch { | |||
@@ -6,11 +6,14 @@ | |||
package repo | |||
import ( | |||
"code.gitea.io/gitea/modules/validation" | |||
"fmt" | |||
"net/url" | |||
"os" | |||
"path" | |||
"regexp" | |||
"strings" | |||
"unicode/utf8" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/auth" | |||
@@ -201,6 +204,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { | |||
if form.RepoTemplate > 0 { | |||
opts := models.GenerateRepoOptions{ | |||
Name: form.RepoName, | |||
Alias: form.Alias, | |||
Description: form.Description, | |||
Private: form.Private, | |||
GitContent: form.GitContent, | |||
@@ -235,6 +239,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { | |||
} else { | |||
repo, err = repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{ | |||
Name: form.RepoName, | |||
Alias: form.Alias, | |||
Description: form.Description, | |||
Gitignores: form.Gitignores, | |||
IssueLabels: form.IssueLabels, | |||
@@ -358,6 +363,7 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) { | |||
GitServiceType: gitServiceType, | |||
CloneAddr: remoteAddr, | |||
RepoName: form.RepoName, | |||
Alias: form.Alias, | |||
Description: form.Description, | |||
Private: form.Private || setting.Repository.ForcePrivate, | |||
Mirror: form.Mirror, | |||
@@ -380,7 +386,7 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) { | |||
opts.Releases = false | |||
} | |||
err = models.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName) | |||
err = models.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName, opts.Alias) | |||
if err != nil { | |||
handleMigrateError(ctx, ctxUser, err, "MigratePost", tplMigrate, &form) | |||
return | |||
@@ -552,3 +558,27 @@ func Status(ctx *context.Context) { | |||
"err": task.Errors, | |||
}) | |||
} | |||
var repoNamePattern = regexp.MustCompile("^[0-9a-zA-Z\\.\\-_]{1,100}$") | |||
var repoAliasPattern = regexp.MustCompile("^[\u4e00-\u9fa5\\.\\-_A-Za-z0-9]{1,100}$") | |||
// CheckName returns repository's default name(by given alias) | |||
func CheckName(ctx *context.Context) { | |||
var r = make(map[string]string, 1) | |||
q := ctx.Query("q") | |||
owner := ctx.Query("owner") | |||
if q == "" || owner == "" || utf8.RuneCountInString(q) > 100 || !validation.ValidAlphaDashDotChinese(q) { | |||
r["name"] = "" | |||
ctx.JSON(200, r) | |||
return | |||
} | |||
if repoNamePattern.MatchString(q) { | |||
r["name"] = q | |||
ctx.JSON(200, r) | |||
return | |||
} | |||
n := models.GenerateDefaultRepoName(owner) | |||
r["name"] = n | |||
ctx.JSON(200, r) | |||
return | |||
} |
@@ -6,6 +6,7 @@ | |||
package repo | |||
import ( | |||
"code.gitea.io/gitea/modules/notification" | |||
"errors" | |||
"fmt" | |||
"io/ioutil" | |||
@@ -70,6 +71,30 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||
return | |||
} | |||
newAlias := form.Alias | |||
var aliasChanged = false | |||
// Check if repository alias has been changed. | |||
if strings.ToLower(repo.Alias) != strings.ToLower(newAlias) { | |||
aliasChanged = true | |||
//check new alias is available or not | |||
if err := models.IsRepositoryAliasAvailable(ctx.Repo.Owner, newAlias); err != nil { | |||
ctx.Data["Err_Alias"] = true | |||
switch { | |||
case models.IsErrRepoAlreadyExist(err): | |||
ctx.RenderWithErr(ctx.Tr("form.repo_name_been_taken"), tplSettingsOptions, &form) | |||
case models.IsErrNameReserved(err): | |||
ctx.RenderWithErr(ctx.Tr("repo.form.name_reserved", err.(models.ErrNameReserved).Name), tplSettingsOptions, &form) | |||
case models.IsErrNamePatternNotAllowed(err): | |||
ctx.RenderWithErr(ctx.Tr("repo.form.name_pattern_not_allowed", err.(models.ErrNamePatternNotAllowed).Pattern), tplSettingsOptions, &form) | |||
default: | |||
ctx.ServerError("ChangeRepositoryName", err) | |||
} | |||
return | |||
} | |||
log.Trace("Repository alias changed: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Alias, newAlias) | |||
} | |||
newRepoName := form.RepoName | |||
// Check if repository name has been changed. | |||
if repo.LowerName != strings.ToLower(newRepoName) { | |||
@@ -95,12 +120,19 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||
log.Trace("Repository name changed: %s/%s -> %s", ctx.Repo.Owner.Name, repo.Name, newRepoName) | |||
} | |||
//notify | |||
if aliasChanged { | |||
notification.NotifyRenameRepository(ctx.Repo.Owner, repo, repo.Alias) | |||
} | |||
// In case it's just a case change. | |||
repo.Name = newRepoName | |||
repo.LowerName = strings.ToLower(newRepoName) | |||
repo.Description = form.Description | |||
repo.Website = form.Website | |||
repo.IsTemplate = form.Template | |||
repo.Alias = newAlias | |||
repo.LowerAlias = strings.ToLower(newAlias) | |||
// Visibility of forked repository is forced sync with base repository. | |||
if repo.IsFork { | |||
@@ -380,7 +412,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||
ctx.Error(404) | |||
return | |||
} | |||
if repo.Name != form.RepoName { | |||
if repo.Alias != form.RepoName { | |||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | |||
return | |||
} | |||
@@ -407,7 +439,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||
ctx.Error(404) | |||
return | |||
} | |||
if repo.Name != form.RepoName { | |||
if repo.Alias != form.RepoName { | |||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | |||
return | |||
} | |||
@@ -445,7 +477,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||
ctx.Error(404) | |||
return | |||
} | |||
if repo.Name != form.RepoName { | |||
if repo.Alias != form.RepoName { | |||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | |||
return | |||
} | |||
@@ -465,7 +497,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||
ctx.Error(404) | |||
return | |||
} | |||
if repo.Name != form.RepoName { | |||
if repo.Alias != form.RepoName { | |||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | |||
return | |||
} | |||
@@ -718,6 +718,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
m.Combo("/:repoid").Get(repo.Fork). | |||
Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost) | |||
}, context.RepoIDAssignment(), context.UnitTypes(), reqRepoCodeReader) | |||
m.Get("/check_name", repo.CheckName) | |||
}, reqSignIn) | |||
// ***** Release Attachment Download without Signin | |||
@@ -31,8 +31,8 @@ func CreateRepository(doer, owner *models.User, opts models.CreateRepoOptions) ( | |||
} | |||
// ForkRepository forks a repository | |||
func ForkRepository(doer, u *models.User, oldRepo *models.Repository, name, desc string) (*models.Repository, error) { | |||
repo, err := repo_module.ForkRepository(doer, u, oldRepo, name, desc) | |||
func ForkRepository(doer, u *models.User, oldRepo *models.Repository, name, desc, alias string) (*models.Repository, error) { | |||
repo, err := repo_module.ForkRepository(doer, u, oldRepo, name, desc, alias) | |||
if err != nil { | |||
if repo != nil { | |||
if errDelete := models.DeleteRepository(doer, u.ID, repo.ID); errDelete != nil { | |||
@@ -55,7 +55,7 @@ func TransferOwnership(doer, newOwner *models.User, repo *models.Repository, tea | |||
// ChangeRepositoryName changes all corresponding setting from old repository name to new one. | |||
func ChangeRepositoryName(doer *models.User, repo *models.Repository, newRepoName string) error { | |||
oldRepoName := repo.Name | |||
//oldRepoName := repo.Name | |||
// Change repository directory name. We must lock the local copy of the | |||
// repo so that we can atomically rename the repo path and updates the | |||
@@ -68,7 +68,7 @@ func ChangeRepositoryName(doer *models.User, repo *models.Repository, newRepoNam | |||
} | |||
repoWorkingPool.CheckOut(com.ToStr(repo.ID)) | |||
notification.NotifyRenameRepository(doer, repo, oldRepoName) | |||
//notification.NotifyRenameRepository(doer, repo, oldRepoName) | |||
return nil | |||
} |
@@ -36,7 +36,7 @@ | |||
<span class="text gold">{{svg "octicon-lock" 16}}</span> | |||
{{end}} | |||
</td> | |||
<td><a href="{{AppSubUrl}}/{{.Owner.Name}}/{{.Name}}">{{.Name}}</a></td> | |||
<td><a href="{{AppSubUrl}}/{{.Owner.Name}}/{{.Name}}">{{.Alias}}</a></td> | |||
<td><i class="fa fa{{if .IsPrivate}}-check{{end}}-square-o"></i></td> | |||
<td>{{.NumWatches}}</td> | |||
<td>{{.NumStars}}</td> | |||
@@ -5,7 +5,7 @@ | |||
border-radius: 0.8rem; | |||
margin-bottom: 1.0rem; | |||
padding: 1.0rem !important; | |||
} | |||
} | |||
.ui.repository.list>.item .header { | |||
font-size: 1.4rem !important; | |||
font-weight: 200; | |||
@@ -24,7 +24,7 @@ | |||
content: ""; | |||
height: 1px; | |||
background-color: #E1E3E6; | |||
bottom: 2.8rem; | |||
bottom: 2.8rem; | |||
} | |||
.repository .ui.mini.menu{ | |||
font-size: .6rem; | |||
@@ -43,13 +43,13 @@ | |||
<a class="{{if eq .SortType "hot"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=hot&tab={{$.TabName}}"> | |||
<svg class="svg octicon-repo" width="16" height="16" aria-hidden="true"> | |||
<use xlink:href="#octicon-repo" /> | |||
</svg> | |||
</svg> | |||
热门{{.i18n.Tr "explore.repos"}} | |||
</a> | |||
<a class="{{if eq .SortType "active"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=active&tab={{$.TabName}}"> | |||
<svg class="svg octicon-inbox" width="16" height="16" aria-hidden="true"> | |||
<use xlink:href="#octicon-inbox" /> | |||
</svg> | |||
</svg> | |||
活跃{{.i18n.Tr "explore.repos"}} | |||
</a> | |||
{{end}} | |||
@@ -93,7 +93,7 @@ | |||
<div class="ui grid"> | |||
<div class="ui sixteen wide mobile ten wide tablet twelve wide computer column"> | |||
<a class="name" href="{{.Link}}"> | |||
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} <span>/</span> {{end}}{{end}}<strong>{{.Name}}</strong> | |||
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} <span>/</span> {{end}}{{end}}<strong>{{.DisplayName}}</strong> | |||
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}} | |||
</a> | |||
{{if .IsPrivate}} | |||
@@ -114,7 +114,7 @@ | |||
<a class="item"> | |||
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> | |||
<path fill="currentColor" d="M17.66 11.2C17.43 10.9 17.15 10.64 16.89 10.38C16.22 9.78 15.46 9.35 14.82 8.72C13.33 7.26 13 4.85 13.95 3C13 3.23 12.17 3.75 11.46 4.32C8.87 6.4 7.85 10.07 9.07 13.22C9.11 13.32 9.15 13.42 9.15 13.55C9.15 13.77 9 13.97 8.8 14.05C8.57 14.15 8.33 14.09 8.14 13.93C8.08 13.88 8.04 13.83 8 13.76C6.87 12.33 6.69 10.28 7.45 8.64C5.78 10 4.87 12.3 5 14.47C5.06 14.97 5.12 15.47 5.29 15.97C5.43 16.57 5.7 17.17 6 17.7C7.08 19.43 8.95 20.67 10.96 20.92C13.1 21.19 15.39 20.8 17.03 19.32C18.86 17.66 19.5 15 18.56 12.72L18.43 12.46C18.22 12 17.66 11.2 17.66 11.2M14.5 17.5C14.22 17.74 13.76 18 13.4 18.1C12.28 18.5 11.16 17.94 10.5 17.28C11.69 17 12.4 16.12 12.61 15.23C12.78 14.43 12.46 13.77 12.33 13C12.21 12.26 12.23 11.63 12.5 10.94C12.69 11.32 12.89 11.7 13.13 12C13.9 13 15.11 13.44 15.37 14.8C15.41 14.94 15.43 15.08 15.43 15.23C15.46 16.05 15.1 16.95 14.5 17.5H14.5Z" /> | |||
</svg> | |||
</svg> | |||
{{.Hot}} | |||
</a> | |||
{{else if eq $.SortType "active"}} | |||
@@ -130,7 +130,7 @@ | |||
<a class="item"> | |||
{{svg "octicon-git-branch" 16}} {{.NumForks}} | |||
</a> | |||
{{end}} | |||
{{end}} | |||
<a class="item"> | |||
{{svg "octicon-star" 16}} {{.NumStars}} | |||
</a> | |||
@@ -33,7 +33,7 @@ | |||
<img class="ui avatar image" src="{{.RelAvatarLink}}"> | |||
{{end}} | |||
<a class="name" href="{{.Link}}"> | |||
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} / {{end}}{{end}}{{.Name}} | |||
{{if or $.PageIsExplore $.PageIsProfileStarList }}{{if .Owner}}{{.Owner.Name}} / {{end}}{{end}}{{if .Alias}}{{.Alias}}{{else}}{{.Name}}{{end}} | |||
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}} | |||
</a> | |||
{{if .IsPrivate}} | |||
@@ -70,4 +70,4 @@ | |||
{{$.i18n.Tr "explore.repo_no_results"}} | |||
</div> | |||
{{end}} | |||
</div> | |||
</div> |
@@ -89,7 +89,7 @@ | |||
<div class="extra full_height cor" > | |||
<div class=" header header_card omit" > | |||
<a class="header_card image poping up " href="{{.Link}}" data-content="{{.Name}}" data-position="top left" data-variation="tiny inverted"> {{.Name}}</a> | |||
<a class="header_card image poping up " href="{{.Link}}" data-content="{{if .Alias}}{{.Alias}}{{else}}{{.Name}}{{end}}" data-position="top left" data-variation="tiny inverted">{{if .Alias}}{{.Alias}}{{else}}{{.Name}}{{end}}</a> | |||
</div> | |||
<div class='content descript_height nowrap-2'> | |||
@@ -167,6 +167,7 @@ | |||
</div> | |||
<script> | |||
console.log({{.tags}}) | |||
var data; | |||
var filterData=[]; | |||
var num=0; | |||
@@ -50,7 +50,7 @@ | |||
{{else}} | |||
{{svg "octicon-repo" 16}} | |||
{{end}} | |||
<strong>{{$.Org.Name}}/{{.Name}}</strong> | |||
<strong>{{$.Org.Name}}/{{.Alias}}</strong> | |||
</a> | |||
</div> | |||
{{else}} | |||
@@ -2,43 +2,15 @@ | |||
<div class="repository new repo" style="margin-top: 40px;"> | |||
<div class="ui middle very relaxed page grid"> | |||
<div class="column"> | |||
<form class="ui form" action="{{.Link}}" method="post"> | |||
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form"> | |||
{{.CsrfTokenHtml}} | |||
<h3 class="ui top attached header"> | |||
{{.i18n.Tr "new_repo"}} | |||
</h3> | |||
<div class="ui attached segment"> | |||
{{template "base/alert" .}} | |||
<div class="inline required field {{if .Err_Owner}}error{{end}}"> | |||
<label>{{.i18n.Tr "repo.owner"}}</label> | |||
<div class="ui selection owner dropdown"> | |||
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | |||
<span class="text" title="{{.ContextUser.Name}}"> | |||
<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}"> | |||
{{.ContextUser.ShortName 20}} | |||
</span> | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}"> | |||
<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}"> | |||
{{.SignedUser.ShortName 20}} | |||
</div> | |||
{{range .Orgs}} | |||
<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | |||
<img class="ui mini image" src="{{.RelAvatarLink}}"> | |||
{{.ShortName 20}} | |||
</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
<span class="help">{{.i18n.Tr "repo.repo_owner_helper"}}</span> | |||
</div> | |||
<div class="inline required field {{if .Err_RepoName}}error{{end}}"> | |||
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label> | |||
<input id="repo_name" name="repo_name" value="{{.repo_name}}" autofocus required> | |||
<span class="help"></span> | |||
</div> | |||
{{template "repo/repo_name" .}} | |||
<!-- <div class="js-project-full-path" id="repoAdress" ></div> --> | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "repo.visibility"}}</label> | |||
<div class="ui checkbox"> | |||
@@ -172,7 +144,7 @@ | |||
<br/> | |||
<div class="inline field"> | |||
<label></label> | |||
<button class="ui green button"> | |||
<button class="ui green button" id="submit_reponame"> | |||
{{.i18n.Tr "repo.create_repo"}} | |||
</button> | |||
<a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a> | |||
@@ -24,7 +24,7 @@ | |||
{{end}} | |||
<a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a> | |||
<div class="divider"> / </div> | |||
<a href="{{$.RepoLink}}">{{.Name}}</a> | |||
<a href="{{$.RepoLink}}">{{.DisplayName}}</a> | |||
{{if .RelAvatarLink}} | |||
{{if .IsTemplate}} | |||
{{if .IsPrivate}} | |||
@@ -46,7 +46,7 @@ | |||
{{end}} | |||
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}} | |||
{{if .IsMirror}}<div class="fork-flag">{{$.i18n.Tr "repo.mirror_from"}} <a target="_blank" rel="noopener noreferrer" href="{{if .SanitizedOriginalURL}}{{.SanitizedOriginalURL}}{{else}}{{MirrorAddress $.Mirror}}{{end}}">{{if .SanitizedOriginalURL}}{{.SanitizedOriginalURL}}{{else}}{{MirrorAddress $.Mirror}}{{end}}</a></div>{{end}} | |||
{{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{SubStr .BaseRepo.RelLink 1 -1}}</a></div>{{end}} | |||
{{if .IsFork}}<div class="fork-flag">{{$.i18n.Tr "repo.forked_from"}} <a href="{{.BaseRepo.Link}}">{{.BaseRepo.FullDisplayName}}</a></div>{{end}} | |||
{{if .IsGenerated}}<div class="fork-flag">{{$.i18n.Tr "repo.generated_from"}} <a href="{{.TemplateRepo.Link}}">{{SubStr .TemplateRepo.RelLink 1 -1}}</a></div>{{end}} | |||
</div> | |||
{{if not .IsBeingCreated}} | |||
@@ -114,9 +114,9 @@ | |||
{{end}} | |||
</div> | |||
</div> | |||
{{end}} | |||
{{if .Permission.CanRead $.UnitTypeIssues}} | |||
@@ -152,7 +152,7 @@ | |||
{{if .Permission.CanRead $.UnitTypeCloudBrain}} | |||
<a class="{{if .PageIsCloudBrain}}active{{end}} item" href="{{.RepoLink}}/debugjob?debugListType=all"> | |||
<span> | |||
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"/><path d="M4 3h16a1 1 0 0 1 1 1v7H3V4a1 1 0 0 1 1-1zM3 13h18v7a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-7zm4 3v2h3v-2H7zM7 6v2h3V6H7z"/></svg> | |||
<svg class="svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"><path fill="none" d="M0 0h24v24H0z"/><path d="M4 3h16a1 1 0 0 1 1 1v7H3V4a1 1 0 0 1 1-1zM3 13h18v7a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-7zm4 3v2h3v-2H7zM7 6v2h3V6H7z"/></svg> | |||
{{.i18n.Tr "repo.cloudbrain"}} | |||
<i class="question circle icon link cloudbrain-question" data-content={{.i18n.Tr "repo.cloudbrain_helper"}} data-position="top center" data-variation="mini"></i> | |||
</span> | |||
@@ -256,11 +256,8 @@ | |||
</div> | |||
<div class="ui six wide tablet four wide computer column"> | |||
<div id="repo-desc"> | |||
<h4 id="about-desc" class="ui header">简介 | |||
<!-- <a class="edit-icon" href="javascript:void(0)"> | |||
<i class="gray edit outline icon"></i> | |||
</a> --> | |||
</h4> | |||
<h4 id="about-desc" class="ui header">简介</h4> | |||
<input type="hidden" id="edit-alias" value="{{.Repository.Alias}}"> | |||
<p> | |||
{{if .Repository.DescriptionHTML}} | |||
<span class="description" style="word-break:break-all">{{.Repository.DescriptionHTML}}</span> | |||
@@ -286,14 +283,8 @@ | |||
<i class="grey bookmark icon"></i> | |||
<div id="repo-topics1" style="flex: 1;"> | |||
<!-- {{if not .Topics}} | |||
<span class="no-description text-italic">{{.i18n.Tr "repo.no_desc"}}</span> | |||
{{end}} --> | |||
{{range .Topics}} | |||
<a class="ui repo-topic small label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=">{{.Name}}</a> | |||
{{end}} | |||
</div> | |||
<div> | |||
@@ -2,7 +2,7 @@ | |||
<div class="repository new migrate" style="margin-top: 40px;"> | |||
<div class="ui middle very relaxed page grid"> | |||
<div class="column"> | |||
<form class="ui form" action="{{.Link}}" method="post"> | |||
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form"> | |||
{{.CsrfTokenHtml}} | |||
<h3 class="ui top attached header"> | |||
{{.i18n.Tr "new_migrate"}} | |||
@@ -37,35 +37,7 @@ | |||
</div> | |||
<div class="ui divider"></div> | |||
<div class="inline required field {{if .Err_Owner}}error{{end}}"> | |||
<label>{{.i18n.Tr "repo.owner"}}</label> | |||
<div class="ui selection owner dropdown"> | |||
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | |||
<span class="text" title="{{.ContextUser.Name}}"> | |||
<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}"> | |||
{{.ContextUser.ShortName 20}} | |||
</span> | |||
<i class="dropdown icon"></i> | |||
<div class="menu" title="{{.SignedUser.Name}}"> | |||
<div class="item" data-value="{{.SignedUser.ID}}"> | |||
<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}"> | |||
{{.SignedUser.ShortName 20}} | |||
</div> | |||
{{range .Orgs}} | |||
<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | |||
<img class="ui mini image" src="{{.RelAvatarLink}}"> | |||
{{.ShortName 20}} | |||
</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="inline required field {{if .Err_RepoName}}error{{end}}"> | |||
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label> | |||
<input id="repo_name" name="repo_name" value="{{.repo_name}}" required> | |||
</div> | |||
{{template "repo/repo_name" .}} | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "repo.visibility"}}</label> | |||
<div class="ui checkbox"> | |||
@@ -127,7 +99,7 @@ | |||
<div class="inline field"> | |||
<label></label> | |||
<button class="ui green button"> | |||
<button class="ui green button" id="submit_reponame"> | |||
{{.i18n.Tr "repo.migrate_repo"}} | |||
</button> | |||
<a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a> | |||
@@ -2,47 +2,18 @@ | |||
<div class="repository new fork"> | |||
<div class="ui middle very relaxed page grid"> | |||
<div class="column"> | |||
<form class="ui form" action="{{.Link}}" method="post"> | |||
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form"> | |||
{{.CsrfTokenHtml}} | |||
<h3 class="ui top attached header"> | |||
{{.i18n.Tr "new_fork"}} | |||
</h3> | |||
<div class="ui attached segment"> | |||
{{template "base/alert" .}} | |||
<div class="inline required field {{if .Err_Owner}}error{{end}}"> | |||
<label>{{.i18n.Tr "repo.owner"}}</label> | |||
<div class="ui selection owner dropdown"> | |||
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | |||
<span class="text" title="{{.ContextUser.Name}}"> | |||
<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}"> | |||
{{.ContextUser.ShortName 20}} | |||
</span> | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
{{if .CanForkToUser}} | |||
<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}"> | |||
<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}"> | |||
{{.SignedUser.ShortName 20}} | |||
</div> | |||
{{end}} | |||
{{range .Orgs}} | |||
<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | |||
<img class="ui mini image" src="{{.RelAvatarLink}}"> | |||
{{.ShortName 20}} | |||
</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "repo.fork_from"}}</label> | |||
<a href="{{AppSubUrl}}/{{.ForkFrom}}">{{.ForkFrom}}</a> | |||
</div> | |||
<div class="inline required field {{if .Err_RepoName}}error{{end}}"> | |||
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label> | |||
<input id="repo_name" name="repo_name" value="{{.repo_name}}" required> | |||
<a href="{{AppSubUrl}}/{{.ForkFrom}}">{{.ForkDisplayName}}</a> | |||
</div> | |||
{{template "repo/repo_name" .}} | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "repo.visibility"}}</label> | |||
<div class="ui read-only checkbox"> | |||
@@ -0,0 +1,57 @@ | |||
<div class="inline required field {{if .Err_RepoName}}error{{end}}" > | |||
<label for="Alias">{{.i18n.Tr "form.Alias"}}</label> | |||
<input id="alias" name="alias" value="{{.alias}}" autofocus required maxlength="100"> | |||
<span class="help">{{.i18n.Tr "form.reponame_dash_dot_error"}}</span> | |||
</div> | |||
<div class="inline required fields" style="margin-bottom: 0;"> | |||
<label style="text-align: right;width: 250px!important;word-wrap: break-word;">{{.i18n.Tr "form.RepoPath"}}</label> | |||
<div class="required field {{if .Err_Owner}}error{{end}}" style="padding: 0;"> | |||
<!-- <label>{{.i18n.Tr "repo.owner"}}</label> --> | |||
<div class="ui selection owner dropdown" id="ownerDropdown"> | |||
<input type="hidden" id="uid" name="uid" value="{{.ContextUser.ID}}" required> | |||
<div class="text" title="{{.ContextUser.Name}}"> | |||
<img class="ui mini image" src="{{.ContextUser.RelAvatarLink}}"> | |||
{{.ContextUser.ShortName 20}} | |||
</div> | |||
<i class="dropdown icon"></i> | |||
<div class="menu"> | |||
<div class="item" data-value="{{.SignedUser.ID}}" title="{{.SignedUser.Name}}"> | |||
<img class="ui mini image" src="{{.SignedUser.RelAvatarLink}}"> | |||
{{.SignedUser.ShortName 20}} | |||
</div> | |||
{{range .Orgs}} | |||
<div class="item" data-value="{{.ID}}" title="{{.Name}}"> | |||
<img class="ui mini image" src="{{.RelAvatarLink}}"> | |||
{{.ShortName 20}} | |||
</div> | |||
{{end}} | |||
</div> | |||
</div> | |||
<!-- <span class="help">{{.i18n.Tr "repo.repo_owner_helper"}}</span> --> | |||
</div> | |||
<!-- <div class="required field {{if .Err_RepoName}}error{{end}}"> | |||
<input id="repo_name" name="repo_name" value="{{.repo_name}}" autofocus required> | |||
</div> --> | |||
<div class="ui interval" style="width: 0.6em;font-size: 2rem;line-height: 0px;text-align: center;">/</div> | |||
<div class="required field {{if .Err_RepoName}}error{{end}}"> | |||
<!-- <label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label> --> | |||
<input style="width: 100% !important;" id="repo_name" name="repo_name" value="{{.repo_name}}" maxlength="100" autofocus required> | |||
</div> | |||
</div> | |||
<span style="display: block;margin-bottom: 1em;" class="help">{{.i18n.Tr "form.repoadd_dash_dot_error"}}</span> | |||
<div class="inline field" id="repoAdress" style="display: none;word-break: break-all;"> | |||
<label for="">{{.i18n.Tr "form.RepoAdress"}}:</label> | |||
<span style="flex: 1;"></span> | |||
</div> | |||
<script> | |||
console.log({{$.Err_Alias}}) | |||
</script> |
@@ -8,12 +8,46 @@ | |||
{{.i18n.Tr "repo.settings.basic_settings"}} | |||
</h4> | |||
<div class="ui attached segment"> | |||
<form class="ui form" action="{{.Link}}" method="post"> | |||
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form"> | |||
{{.CsrfTokenHtml}} | |||
<input type="hidden" name="action" value="update"> | |||
<div class="required field {{if .Err_RepoName}}error{{end}}"> | |||
<!-- <div class="required field {{if .Err_RepoName}}error{{end}}"> | |||
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label> | |||
<input id="repo_name" name="repo_name" value="{{.Repository.Name}}" data-repo-name="{{.Repository.Name}}" autofocus required> | |||
<input id="repo_name" name="alias" value="{{.Repository.Alias}}" data-repo-name="{{.Repository.Alias}}" autofocus required> | |||
<input type="hidden" name="repo_name" value="{{.Repository.Name}}" data-repo-name="{{.Repository.Name}}" autofocus required> | |||
</div> --> | |||
<div class="required field {{if .Err_Alias}}error{{end}}"> | |||
<label for="Alias">{{.i18n.Tr "form.Alias"}}</label> | |||
<input name="alias" value="{{.Repository.Alias}}" data-repo-name="{{.Repository.Alias}}" autofocus required> | |||
<span class="help">{{.i18n.Tr "form.reponame_dash_dot_error"}}</span> | |||
</div> | |||
<div class="required field"> | |||
<label>{{.i18n.Tr "form.RepoPath"}}</label> | |||
<div class="fields"> | |||
<div class="eight wide required field {{if .Err_Owner}}error{{end}}"> | |||
<div class="ui selection owner dropdown" id="ownerDropdown"> | |||
<input type="hidden" id="uid" name="uid" value="{{.Owner.Name}}" required> | |||
<div class="text" title="{{.Owner.Name}}"> | |||
<img class="ui mini image" src="{{.Owner.RelAvatarLink}}"> | |||
{{.Owner.ShortName 40}} | |||
</div> | |||
</div> | |||
</div> | |||
<div class="ui interval" style="width: 0.6em;font-size: 2rem;line-height: 38px;text-align: center;">/</div> | |||
<div class="eight wide required field {{if .Err_Alias}}error{{end}}"> | |||
<!-- <label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label> --> | |||
<input style="width: 100% !important;" id="repo_name" name="repo_name" value="{{.Repository.Name}}" data-repo-name="{{.Repository.Name}}" autofocus required> | |||
<span class="help">{{.i18n.Tr "form.repoadd_dash_dot_error"}}</span> | |||
</div> | |||
</div> | |||
</div> | |||
<div class="inline field" id="repoAdress" style="display: none;"> | |||
<label for="">{{.i18n.Tr "form.RepoAdress"}}:</label> | |||
<span></span> | |||
</div> | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "repo.repo_size"}}</label> | |||
@@ -41,7 +75,7 @@ | |||
{{end}} | |||
<div class="field {{if .Err_Description}}error{{end}}"> | |||
<label for="description">{{$.i18n.Tr "repo.repo_desc"}}</label> | |||
<textarea id="description" name="description" rows="2" maxlength="255">{{.Repository.Description}}</textarea> | |||
<textarea id="description" name="description" rows="2" maxlength="254">{{.Repository.Description}}</textarea> | |||
</div> | |||
<div class="field {{if .Err_Website}}error{{end}}"> | |||
<label for="website">{{.i18n.Tr "repo.settings.site"}}</label> | |||
@@ -152,7 +186,7 @@ | |||
{{$isModelMangeEnabled := .Repository.UnitEnabled $.UnitTypeModelManage }} | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "repo.model_manager"}}</label> | |||
<div class="ui checkbox {{if ne $.MODEL_COUNT 0}}disabled{{end}}"> | |||
<div class="ui checkbox"> | |||
<input class="enable-system" name="enable_model_manager" type="checkbox" {{if $isModelMangeEnabled}}checked{{end}}> | |||
<label>{{.i18n.Tr "repo.settings.model_desc"}}</label> | |||
</div> | |||
@@ -160,7 +194,7 @@ | |||
{{$isCloudBrainEnabled := .Repository.UnitEnabled $.UnitTypeCloudBrain }} | |||
<div class="inline field"> | |||
<label>{{.i18n.Tr "repo.cloudbrain"}}</label> | |||
<div class="ui checkbox {{if ne $.jobCount 0}}disabled{{end}}"> | |||
<div class="ui checkbox"> | |||
<input class="enable-system" name="enable_cloud_brain" type="checkbox" {{if $isCloudBrainEnabled}}checked{{end}}> | |||
<label>{{.i18n.Tr "repo.settings.cloudbrain_desc"}}</label> | |||
</div> | |||
@@ -475,7 +509,7 @@ | |||
<div class="field"> | |||
<label> | |||
{{.i18n.Tr "repo.settings.transfer_form_title"}} | |||
<span class="text red">{{.Repository.Name}}</span> | |||
<span class="text red">{{.Repository.Alias}}</span> | |||
</label> | |||
</div> | |||
<div class="required field"> | |||
@@ -507,7 +541,7 @@ | |||
<div class="field"> | |||
<label> | |||
{{.i18n.Tr "repo.settings.transfer_form_title"}} | |||
<span class="text red">{{.Repository.Name}}</span> | |||
<span class="text red">{{.Repository.Alias}}</span> | |||
</label> | |||
</div> | |||
<div class="required field"> | |||
@@ -534,7 +568,7 @@ | |||
<div class="content"> | |||
<div class="ui warning message text left"> | |||
{{.i18n.Tr "repo.settings.delete_notices_1" | Safe}}<br> | |||
{{.i18n.Tr "repo.settings.delete_notices_2" .Repository.FullName | Safe}} | |||
{{.i18n.Tr "repo.settings.delete_notices_2" .Repository.Alias | Safe}} | |||
{{if .Repository.NumForks}}<br> | |||
{{.i18n.Tr "repo.settings.delete_notices_fork_1"}} | |||
{{end}} | |||
@@ -545,7 +579,7 @@ | |||
<div class="field"> | |||
<label> | |||
{{.i18n.Tr "repo.settings.transfer_form_title"}} | |||
<span class="text red">{{.Repository.Name}}</span> | |||
<span class="text red">{{.Repository.Alias}}</span> | |||
</label> | |||
</div> | |||
<div class="required field"> | |||
@@ -569,7 +603,7 @@ | |||
<div class="content"> | |||
<div class="ui warning message text left"> | |||
{{.i18n.Tr "repo.settings.delete_notices_1" | Safe}}<br> | |||
{{.i18n.Tr "repo.settings.wiki_delete_notices_1" .Repository.Name | Safe}} | |||
{{.i18n.Tr "repo.settings.wiki_delete_notices_1" .Repository.Alias | Safe}} | |||
</div> | |||
<form class="ui form" action="{{.Link}}" method="post"> | |||
{{.CsrfTokenHtml}} | |||
@@ -577,7 +611,7 @@ | |||
<div class="field"> | |||
<label> | |||
{{.i18n.Tr "repo.settings.transfer_form_title"}} | |||
<span class="text red">{{.Repository.Name}}</span> | |||
<span class="text red">{{.Repository.Alias}}</span> | |||
</label> | |||
</div> | |||
<div class="required field"> | |||
@@ -625,4 +659,4 @@ | |||
{{end}} | |||
{{end}} | |||
{{template "base/footer" .}} | |||
{{template "base/footer" .}} |
@@ -13,63 +13,63 @@ | |||
{{.ShortActUserName}} | |||
{{end}} | |||
{{if eq .GetOpType 1}} | |||
{{$.i18n.Tr "action.create_repo" .GetRepoLink .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.create_repo" .GetRepoLink .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 2}} | |||
{{$.i18n.Tr "action.rename_repo" .GetContent .GetRepoLink .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.rename_repo" .GetContent .GetRepoLink .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 5}} | |||
{{ $branchLink := .GetBranch | EscapePound | Escape}} | |||
{{$.i18n.Tr "action.commit_repo" .GetRepoLink $branchLink (Escape .GetBranch) .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.commit_repo" .GetRepoLink $branchLink (Escape .GetBranch) .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 6}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.create_issue" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.create_issue" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 7}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.create_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.create_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 8}} | |||
{{$.i18n.Tr "action.transfer_repo" .GetContent .GetRepoLink .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.transfer_repo" .GetContent .GetRepoLink .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 9}} | |||
{{ $branchLink := .GetBranch | EscapePound | Escape}} | |||
{{$.i18n.Tr "action.push_tag" .GetRepoLink $branchLink .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.push_tag" .GetRepoLink $branchLink .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 10}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.comment_issue" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.comment_issue" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 11}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.merge_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.merge_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 12}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.close_issue" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.close_issue" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 13}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.reopen_issue" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.reopen_issue" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 14}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.close_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.close_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 15}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.reopen_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.reopen_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 16}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.delete_tag" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.delete_tag" .GetRepoLink .GetBranch .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 17}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.delete_branch" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.delete_branch" .GetRepoLink .GetBranch .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 18}} | |||
{{ $branchLink := .GetBranch | EscapePound}} | |||
{{$.i18n.Tr "action.mirror_sync_push" .GetRepoLink $branchLink .GetBranch .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.mirror_sync_push" .GetRepoLink $branchLink .GetBranch .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 19}} | |||
{{$.i18n.Tr "action.mirror_sync_create" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.mirror_sync_create" .GetRepoLink .GetBranch .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 20}} | |||
{{$.i18n.Tr "action.mirror_sync_delete" .GetRepoLink .GetBranch .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.mirror_sync_delete" .GetRepoLink .GetBranch .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 21}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.approve_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.approve_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 22}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.reject_pull_request" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.reject_pull_request" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||
{{else if eq .GetOpType 23}} | |||
{{ $index := index .GetIssueInfos 0}} | |||
{{$.i18n.Tr "action.comment_pull" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||
{{$.i18n.Tr "action.comment_pull" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||
{{end}} | |||
</p> | |||
{{if or (eq .GetOpType 5) (eq .GetOpType 18)}} | |||
@@ -107,7 +107,7 @@ | |||
{{ $timeStr:= TimeSinceUnix .CreatedUnix $.Lang }} | |||
{{if .Repo}} | |||
<li class="item"> | |||
<div class="ui label">{{.Repo.FullName}}#{{.Index}}</div> | |||
<div class="ui label">{{.Repo.OwnerName}}/{{.Repo.Alias}}#{{.Index}}</div> | |||
<a class="title" href="{{.HTMLURL}}">{{RenderEmoji .Title}}</a> | |||
{{if .IsPull}} | |||
@@ -208,3 +208,6 @@ | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} | |||
<script> | |||
console.log({{.Issues}}) | |||
</script> |
@@ -65,7 +65,7 @@ | |||
<div class="milestone list"> | |||
{{range .Milestones}} | |||
<li class="item"> | |||
<div class="ui label">{{.Repo.FullName}}</div> | |||
<div class="ui label">{{.Repo.OwnerName}}/{{.Repo.Alias}}</div> | |||
{{svg "octicon-milestone" 16}} <a href="{{.Repo.Link }}/milestone/{{.ID}}">{{.Name}}</a> | |||
<div class="ui right green progress" data-percent="{{.Completeness}}"> | |||
<div class="bar" {{if not .Completeness}}style="background-color: transparent"{{end}}> | |||
@@ -117,3 +117,6 @@ | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} | |||
<script> | |||
console.log({{.Milestones}}) | |||
</script> |
@@ -104,7 +104,7 @@ | |||
<li v-for="repo in repos" :class="{'private': repo.private}" v-show="showRepo(repo)"> | |||
<a :href="suburl + '/' + repo.full_name"> | |||
<svg :class="'svg ' + repoClass(repo)" width="16" height="16" aria-hidden="true"><use :xlink:href="'#' + repoClass(repo)" /></svg> | |||
<strong class="text truncate item-name">${repo.full_name}</strong> | |||
<strong class="text truncate item-name">${repo.full_display_name}</strong> | |||
<i v-if="repo.archived" class="archive icon archived-icon"></i> | |||
<span class="ui right text light grey"> | |||
${repo.stars_count} <span class="rear">{{svg "octicon-star" 16}}</span> | |||
@@ -21,7 +21,7 @@ | |||
{{else}} | |||
<span class="iconFloat">{{svg "octicon-repo" 16}}</span> | |||
{{end}} | |||
<a class="name" href="{{AppSubUrl}}/{{$.Owner.Name}}/{{.Name}}">{{$.Owner.Name}}/{{.Name}}</a> | |||
<a class="name" href="{{AppSubUrl}}/{{$.Owner.Name}}/{{.Name}}">{{$.Owner.Name}}/{{.DisplayName}}</a> | |||
<span>{{SizeFmt .Size}}</span> | |||
{{if .IsFork}} | |||
{{$.i18n.Tr "repo.forked_from"}} | |||
@@ -52,6 +52,7 @@ export default { | |||
desc: '', | |||
index_web: '', | |||
repo_name_name: '', | |||
alias:'' | |||
}, | |||
// rule1:[{min:3,max:5,message:'1',trigger:"blur"}], | |||
rule: { | |||
@@ -76,6 +77,7 @@ export default { | |||
getRepoName() { | |||
const el = this.url.split('/')[2]; | |||
this.info.repo_name = el; | |||
this.info.alias = $('input#edit-alias').val() | |||
}, | |||
initForm(diaolog) { | |||
if (diaolog === false) { | |||
@@ -95,6 +97,7 @@ export default { | |||
data: this.qs.stringify({ | |||
_csrf: csrf, | |||
action: 'update', | |||
alias:this.info.alias, | |||
repo_name: this.info.repo_name, | |||
description: this.info.desc, | |||
website: this.info.index_web | |||
@@ -2411,8 +2411,8 @@ function searchRepositories() { | |||
const items = []; | |||
$.each(response.data, (_i, item) => { | |||
items.push({ | |||
title: item.full_name.split('/')[1], | |||
description: item.full_name | |||
title: item.full_display_name.split('/')[1], | |||
description: item.full_display_name | |||
}); | |||
}); | |||
@@ -2677,7 +2677,7 @@ function initTemplateSearch() { | |||
// Parse the response from the api to work with our dropdown | |||
$.each(response.data, (_r, repo) => { | |||
filteredResponse.results.push({ | |||
name: htmlEncode(repo.full_name), | |||
name: htmlEncode(repo.full_display_name), | |||
value: repo.id | |||
}); | |||
}); | |||
@@ -2966,10 +2966,21 @@ $(document).ready(async () => { | |||
const $cloneAddr = $('#clone_addr'); | |||
$cloneAddr.on('change', () => { | |||
const $repoName = $('#repo_name'); | |||
const $repoName = $('#alias'); | |||
const $owner = $('#ownerDropdown div.text').attr("title") | |||
const $urlAdd = location.href.split('/')[0] + '//' + location.href.split('/')[2] | |||
if ($cloneAddr.val().length > 0 && $repoName.val().length === 0) { | |||
// Only modify if repo_name input is blank | |||
const repoValue = $cloneAddr.val().match(/^(.*\/)?((.+?)(\.git)?)$/)[3] | |||
$repoName.val($cloneAddr.val().match(/^(.*\/)?((.+?)(\.git)?)$/)[3]); | |||
$.get(`${window.config.AppSubUrl}/repo/check_name?q=${repoValue}&owner=${$owner}`,(data)=>{ | |||
const repo_name = data.name | |||
$('#repo_name').val(repo_name) | |||
repo_name && $('#repo_name').parent().removeClass('error') | |||
$('#repoAdress').css("display","flex") | |||
$('#repoAdress span').text($urlAdd+'/'+$owner+'/'+$('#repo_name').val()+'.git') | |||
$('#repo_name').attr("placeholder","") | |||
}) | |||
} | |||
}); | |||
@@ -4136,4 +4147,85 @@ $('.question.circle.icon.cloudbrain-question').hover(function(){ | |||
//云脑详情页面跳转回上一个页面 | |||
$(".section.backTodeBug").attr("href",localStorage.getItem('all')) | |||
//新建调试取消跳转 | |||
$(".ui.button.cancel").attr("href",localStorage.getItem('all')) | |||
$(".ui.button.cancel").attr("href",localStorage.getItem('all')) | |||
function initcreateRepo(){ | |||
let timeout; | |||
let keydown_flag = false | |||
const urlAdd = location.href.split('/')[0] + '//' + location.href.split('/')[2] | |||
let owner = $('#ownerDropdown div.text').attr("title") | |||
$(document).ready(function(){ | |||
$('#ownerDropdown').dropdown({ | |||
onChange:function(value,text,$choice){ | |||
owner = $choice[0].getAttribute("title") | |||
$('#repoAdress').css("display","flex") | |||
$('#repoAdress span').text(urlAdd+'/'+owner+'/'+$('#repo_name').val()+'.git') | |||
} | |||
}); | |||
}) | |||
$('#repo_name').keyup(function(){ | |||
keydown_flag = $('#repo_name').val() ? true : false | |||
if(keydown_flag){ | |||
$('#repoAdress').css("display","flex") | |||
$('#repoAdress span').text(urlAdd+'/'+owner+'/'+$('#repo_name').val()+'.git') | |||
} | |||
else{ | |||
$('#repoAdress').css("display","none") | |||
$('#repo_name').attr("placeholder","") | |||
} | |||
}) | |||
$("#create_repo_form") | |||
.form({ | |||
on: 'blur', | |||
// inline:true, | |||
fields: { | |||
alias: { | |||
identifier : 'alias', | |||
rules: [ | |||
{ | |||
type: 'regExp[/^[\u4E00-\u9FA5A-Za-z0-9_.-]{1,100}$/]', | |||
} | |||
] | |||
}, | |||
repo_name:{ | |||
identifier : 'repo_name', | |||
rules: [ | |||
{ | |||
type: 'regExp[/^[A-Za-z0-9_.-]{1,100}$/]', | |||
} | |||
] | |||
}, | |||
}, | |||
onFailure: function(e){ | |||
return false; | |||
} | |||
}) | |||
$('#alias').bind('input propertychange', function (event) { | |||
clearTimeout(timeout) | |||
timeout = setTimeout(() => { | |||
//在此处写调用的方法,可以实现仅最后一次操作生效 | |||
const aliasValue = $('#alias').val() | |||
if(keydown_flag){ | |||
$('#repo_name').attr("placeholder","") | |||
} | |||
else if(aliasValue){ | |||
$('#repo_name').attr("placeholder","正在获取路径...") | |||
$.get(`${window.config.AppSubUrl}/repo/check_name?q=${aliasValue}&owner=${owner}`,(data)=>{ | |||
const repo_name = data.name | |||
$('#repo_name').val(repo_name) | |||
repo_name && $('#repo_name').parent().removeClass('error') | |||
$('#repoAdress').css("display","flex") | |||
$('#repoAdress span').text(urlAdd+'/'+owner+'/'+$('#repo_name').val()+'.git') | |||
$('#repo_name').attr("placeholder","") | |||
}) | |||
}else{ | |||
$('#repo_name').val('') | |||
$('#repo_name').attr("placeholder","") | |||
$('#repoAdress').css("display","none") | |||
} | |||
}, 500) | |||
}); | |||
} | |||
initcreateRepo() |
@@ -2,7 +2,7 @@ | |||
.help { | |||
color: #999999; | |||
padding-top: .6em; | |||
padding-bottom: .6em; | |||
display: inline-block; | |||
} | |||
} | |||
Dear OpenI User
Thank you for your continuous support to the Openl Qizhi Community AI Collaboration Platform. In order to protect your usage rights and ensure network security, we updated the Openl Qizhi Community AI Collaboration Platform Usage Agreement in January 2024. The updated agreement specifies that users are prohibited from using intranet penetration tools. After you click "Agree and continue", you can continue to use our services. Thank you for your cooperation and understanding.
For more agreement content, please refer to the《Openl Qizhi Community AI Collaboration Platform Usage Agreement》