@@ -58,7 +58,7 @@ func createOutdatedPR(t *testing.T, actor, forkOrg *models.User) *models.PullReq | |||||
assert.NoError(t, err) | assert.NoError(t, err) | ||||
assert.NotEmpty(t, baseRepo) | 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.NoError(t, err) | ||||
assert.NotEmpty(t, headRepo) | assert.NotEmpty(t, headRepo) | ||||
@@ -164,12 +164,24 @@ func (a *Action) GetRepoName() string { | |||||
return a.Repo.Name | 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 | // ShortRepoName returns the name of the action repository | ||||
// trimmed to max 33 chars. | // trimmed to max 33 chars. | ||||
func (a *Action) ShortRepoName() string { | func (a *Action) ShortRepoName() string { | ||||
return base.EllipsisString(a.GetRepoName(), 33) | 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. | // GetRepoPath returns the virtual path to the action repository. | ||||
func (a *Action) GetRepoPath() string { | func (a *Action) GetRepoPath() string { | ||||
return path.Join(a.GetRepoUserName(), a.GetRepoName()) | return path.Join(a.GetRepoUserName(), a.GetRepoName()) | ||||
@@ -181,6 +193,12 @@ func (a *Action) ShortRepoPath() string { | |||||
return path.Join(a.ShortRepoUserName(), a.ShortRepoName()) | 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. | // GetRepoLink returns relative link to action repository. | ||||
func (a *Action) GetRepoLink() string { | func (a *Action) GetRepoLink() string { | ||||
if len(setting.AppSubURL) > 0 { | if len(setting.AppSubURL) > 0 { | ||||
@@ -12,6 +12,7 @@ import ( | |||||
"errors" | "errors" | ||||
"fmt" | "fmt" | ||||
"html/template" | "html/template" | ||||
"math/rand" | |||||
"xorm.io/xorm" | "xorm.io/xorm" | ||||
"code.gitea.io/gitea/modules/blockchain" | "code.gitea.io/gitea/modules/blockchain" | ||||
@@ -221,8 +222,10 @@ type Repository struct { | |||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | ||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | 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 | // SanitizedOriginalURL returns a sanitized OriginalURL | ||||
@@ -233,6 +236,14 @@ func (repo *Repository) SanitizedOriginalURL() string { | |||||
return util.SanitizeURLCredentials(repo.OriginalURL, false) | 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 | // ColorFormat returns a colored string to represent this repo | ||||
func (repo *Repository) ColorFormat(s fmt.State) { | func (repo *Repository) ColorFormat(s fmt.State) { | ||||
var ownerName interface{} | var ownerName interface{} | ||||
@@ -286,6 +297,11 @@ func (repo *Repository) FullName() string { | |||||
return repo.OwnerName + "/" + repo.Name | 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 | // HTMLURL returns the repository HTML URL | ||||
func (repo *Repository) HTMLURL() string { | func (repo *Repository) HTMLURL() string { | ||||
return setting.AppURL + repo.FullName() | return setting.AppURL + repo.FullName() | ||||
@@ -385,7 +401,9 @@ func (repo *Repository) innerAPIFormat(e Engine, mode AccessMode, isParent bool) | |||||
ID: repo.ID, | ID: repo.ID, | ||||
Owner: repo.Owner.APIFormat(), | Owner: repo.Owner.APIFormat(), | ||||
Name: repo.Name, | Name: repo.Name, | ||||
Alias: repo.Alias, | |||||
FullName: repo.FullName(), | FullName: repo.FullName(), | ||||
FullDisplayName: repo.FullDisplayName(), | |||||
Description: repo.Description, | Description: repo.Description, | ||||
Private: repo.IsPrivate, | Private: repo.IsPrivate, | ||||
Template: repo.IsTemplate, | Template: repo.IsTemplate, | ||||
@@ -921,17 +939,50 @@ func (repo *Repository) DescriptionHTML() template.HTML { | |||||
return template.HTML(markup.Sanitize(string(desc))) | 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. | // 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. | // 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 | // 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() { | if !doer.CanCreateRepo() { | ||||
return ErrReachLimitOfRepo{u.MaxRepoCreation} | return ErrReachLimitOfRepo{u.MaxRepoCreation} | ||||
} | } | ||||
if err := IsUsableRepoName(name); err != nil { | |||||
if err := IsUsableRepoName(repoName); err != nil { | |||||
return err | 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 { | if err != nil { | ||||
return fmt.Errorf("IsRepositoryExist: %v", err) | return fmt.Errorf("IsRepositoryExist: %v", err) | ||||
} else if has { | } else if has { | ||||
return ErrRepoAlreadyExist{u.Name, name} | |||||
return ErrRepoAlreadyExist{u.Name, repoName} | |||||
} | } | ||||
return nil | return nil | ||||
} | } | ||||
@@ -996,6 +1051,7 @@ func CheckCreateRepository(doer, u *User, name string) error { | |||||
// CreateRepoOptions contains the create repository options | // CreateRepoOptions contains the create repository options | ||||
type CreateRepoOptions struct { | type CreateRepoOptions struct { | ||||
Name string | Name string | ||||
Alias string | |||||
Description string | Description string | ||||
OriginalURL string | OriginalURL string | ||||
GitServiceType api.GitServiceType | GitServiceType api.GitServiceType | ||||
@@ -1036,8 +1092,10 @@ func GetRepoInitFile(tp, name string) ([]byte, error) { | |||||
} | } | ||||
var ( | var ( | ||||
reservedRepoNames = []string{".", ".."} | |||||
reservedRepoPatterns = []string{"*.git", "*.wiki"} | |||||
reservedRepoNames = []string{".", ".."} | |||||
reservedRepoPatterns = []string{"*.git", "*.wiki"} | |||||
reservedRepoAliasNames = []string{} | |||||
reservedRepoAliasPatterns = []string{} | |||||
) | ) | ||||
// IsUsableRepoName returns true when repository is usable | // IsUsableRepoName returns true when repository is usable | ||||
@@ -1045,13 +1103,22 @@ func IsUsableRepoName(name string) error { | |||||
return isUsableName(reservedRepoNames, reservedRepoPatterns, name) | 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. | // CreateRepository creates a repository for the user/organization. | ||||
func CreateRepository(ctx DBContext, doer, u *User, repo *Repository) (err error) { | func CreateRepository(ctx DBContext, doer, u *User, repo *Repository) (err error) { | ||||
repo.LowerAlias = strings.ToLower(repo.Alias) | |||||
if err = IsUsableRepoName(repo.Name); err != nil { | if err = IsUsableRepoName(repo.Name); err != nil { | ||||
return err | 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 { | if err != nil { | ||||
return fmt.Errorf("IsRepositoryExist: %v", err) | return fmt.Errorf("IsRepositoryExist: %v", err) | ||||
} else if has { | } 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. | // 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 { | if err != nil { | ||||
return fmt.Errorf("IsRepositoryExist: %v", err) | return fmt.Errorf("IsRepositoryExist: %v", err) | ||||
} else if has { | } else if has { | ||||
@@ -1366,7 +1433,7 @@ func ChangeRepositoryName(doer *User, repo *Repository, newRepoName string) (err | |||||
return err | return err | ||||
} | } | ||||
has, err := IsRepositoryExist(repo.Owner, newRepoName) | |||||
has, err := IsRepositoryExist(repo.Owner, newRepoName, "") | |||||
if err != nil { | if err != nil { | ||||
return fmt.Errorf("IsRepositoryExist: %v", err) | return fmt.Errorf("IsRepositoryExist: %v", err) | ||||
} else if has { | } else if has { | ||||
@@ -1848,6 +1915,26 @@ func getRepositoryByOwnerAndName(e Engine, ownerName, repoName string) (*Reposit | |||||
return &repo, nil | 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. | // GetRepositoryByName returns the repository by given name under user if exists. | ||||
func GetRepositoryByName(ownerID int64, name string) (*Repository, error) { | func GetRepositoryByName(ownerID int64, name string) (*Repository, error) { | ||||
repo := &Repository{ | repo := &Repository{ | ||||
@@ -2521,6 +2608,14 @@ func UpdateRepositoryCommitNum(repo *Repository) error { | |||||
return nil | 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 { | type RepoFile struct { | ||||
CommitId string | CommitId string | ||||
Content []byte | Content []byte | ||||
@@ -19,6 +19,7 @@ import ( | |||||
// GenerateRepoOptions contains the template units to generate | // GenerateRepoOptions contains the template units to generate | ||||
type GenerateRepoOptions struct { | type GenerateRepoOptions struct { | ||||
Name string | Name string | ||||
Alias string | |||||
Description string | Description string | ||||
Private bool | Private bool | ||||
GitContent bool | GitContent bool | ||||
@@ -200,8 +200,8 @@ const ( | |||||
SearchOrderByForks SearchOrderBy = "num_forks ASC" | SearchOrderByForks SearchOrderBy = "num_forks ASC" | ||||
SearchOrderByForksReverse SearchOrderBy = "num_forks DESC" | SearchOrderByForksReverse SearchOrderBy = "num_forks DESC" | ||||
SearchOrderByDownloadTimes SearchOrderBy = "download_times 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 | // SearchRepositoryCondition creates a query condition according search repository options | ||||
@@ -321,6 +321,7 @@ func SearchRepositoryCondition(opts *SearchRepoOptions) builder.Cond { | |||||
var likes = builder.NewCond() | var likes = builder.NewCond() | ||||
for _, v := range strings.Split(opts.Keyword, ",") { | for _, v := range strings.Split(opts.Keyword, ",") { | ||||
likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)}) | likes = likes.Or(builder.Like{"lower_name", strings.ToLower(v)}) | ||||
likes = likes.Or(builder.Like{"alias", v}) | |||||
if opts.IncludeDescription { | if opts.IncludeDescription { | ||||
likes = likes.Or(builder.Like{"LOWER(description)", strings.ToLower(v)}) | likes = likes.Or(builder.Like{"LOWER(description)", strings.ToLower(v)}) | ||||
} | } | ||||
@@ -28,6 +28,7 @@ type OfficialTagRepos struct { | |||||
type TagReposBrief struct { | type TagReposBrief struct { | ||||
RepoID int64 | RepoID int64 | ||||
RepoName string | RepoName string | ||||
Alias string | |||||
TagID int64 | TagID int64 | ||||
} | } | ||||
@@ -97,7 +98,7 @@ func UpdateTagReposByID(tagID, orgID int64, repoIdList []int64) error { | |||||
func GetTagRepos(tagID, orgID int64) ([]TagReposSelected, error) { | func GetTagRepos(tagID, orgID int64) ([]TagReposSelected, error) { | ||||
t := make([]TagReposBrief, 0) | 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 { | if err := x.SQL(SQLCmd, tagID, orgID).Find(&t); err != nil { | ||||
return nil, err | return nil, err | ||||
@@ -108,9 +109,13 @@ func GetTagRepos(tagID, orgID int64) ([]TagReposSelected, error) { | |||||
if v.TagID > 0 { | if v.TagID > 0 { | ||||
selected = true | selected = true | ||||
} | } | ||||
repoName := v.Alias | |||||
if v.Alias == "" { | |||||
repoName = v.RepoName | |||||
} | |||||
r = append(r, TagReposSelected{ | r = append(r, TagReposSelected{ | ||||
RepoID: v.RepoID, | RepoID: v.RepoID, | ||||
RepoName: v.RepoName, | |||||
RepoName: repoName, | |||||
Selected: selected, | 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)) | data["ErrorMsg"] = trName + l.Tr("form.include_error", GetInclude(field)) | ||||
case validation.ErrGlobPattern: | case validation.ErrGlobPattern: | ||||
data["ErrorMsg"] = trName + l.Tr("form.glob_pattern_error", errs[0].Message) | 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: | default: | ||||
data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification | data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification | ||||
} | } | ||||
@@ -29,6 +29,7 @@ import ( | |||||
type CreateRepoForm struct { | type CreateRepoForm struct { | ||||
UID int64 `binding:"Required"` | UID int64 `binding:"Required"` | ||||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"` | RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"` | ||||
Alias string `binding:"Required;MaxSize(100);AlphaDashDotChinese"` | |||||
Private bool | Private bool | ||||
Description string `binding:"MaxSize(1024)"` | Description string `binding:"MaxSize(1024)"` | ||||
DefaultBranch string `binding:"GitRefName;MaxSize(100)"` | DefaultBranch string `binding:"GitRefName;MaxSize(100)"` | ||||
@@ -62,6 +63,7 @@ type MigrateRepoForm struct { | |||||
UID int64 `json:"uid" binding:"Required"` | UID int64 `json:"uid" binding:"Required"` | ||||
// required: true | // required: true | ||||
RepoName string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"` | RepoName string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"` | ||||
Alias string `json:"alias" binding:"Required;AlphaDashDotChinese;MaxSize(100)"` | |||||
Mirror bool `json:"mirror"` | Mirror bool `json:"mirror"` | ||||
Private bool `json:"private"` | Private bool `json:"private"` | ||||
Description string `json:"description" binding:"MaxSize(255)"` | 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 | // RepoSettingForm form for changing repository settings | ||||
type RepoSettingForm struct { | type RepoSettingForm struct { | ||||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"` | RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"` | ||||
Alias string `binding:"Required;AlphaDashDotChinese;MaxSize(100)"` | |||||
Description string `binding:"MaxSize(255)"` | Description string `binding:"MaxSize(255)"` | ||||
Website string `binding:"ValidUrl;MaxSize(255)"` | Website string `binding:"ValidUrl;MaxSize(255)"` | ||||
Interval string | 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) { | func (a *actionNotifier) NotifyTransferRepository(doer *models.User, repo *models.Repository, oldOwnerName string) { | ||||
if err := models.NotifyWatchers(&models.Action{ | if err := models.NotifyWatchers(&models.Action{ | ||||
ActUserID: doer.ID, | ActUserID: doer.ID, | ||||
@@ -18,6 +18,7 @@ type Notifier interface { | |||||
NotifyDeleteRepository(doer *models.User, repo *models.Repository) | NotifyDeleteRepository(doer *models.User, repo *models.Repository) | ||||
NotifyForkRepository(doer *models.User, oldRepo, repo *models.Repository) | NotifyForkRepository(doer *models.User, oldRepo, repo *models.Repository) | ||||
NotifyRenameRepository(doer *models.User, repo *models.Repository, oldRepoName string) | 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) | NotifyTransferRepository(doer *models.User, repo *models.Repository, oldOwnerName string) | ||||
NotifyNewIssue(*models.Issue) | 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 (*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 | // NotifyTransferRepository places a place holder function | ||||
func (*NullNotifier) NotifyTransferRepository(doer *models.User, repo *models.Repository, oldOwnerName string) { | 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, | Owner: u, | ||||
OwnerName: u.Name, | OwnerName: u.Name, | ||||
Name: opts.Name, | Name: opts.Name, | ||||
Alias: opts.Alias, | |||||
LowerName: strings.ToLower(opts.Name), | LowerName: strings.ToLower(opts.Name), | ||||
Description: opts.Description, | Description: opts.Description, | ||||
OriginalURL: opts.OriginalURL, | OriginalURL: opts.OriginalURL, | ||||
@@ -15,7 +15,7 @@ import ( | |||||
) | ) | ||||
// ForkRepository forks a repository | // 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) | forkedRepo, err := oldRepo.GetUserFork(owner.ID) | ||||
if err != nil { | if err != nil { | ||||
return nil, err | return nil, err | ||||
@@ -33,6 +33,7 @@ func ForkRepository(doer, owner *models.User, oldRepo *models.Repository, name, | |||||
Owner: owner, | Owner: owner, | ||||
OwnerName: owner.Name, | OwnerName: owner.Name, | ||||
Name: name, | Name: name, | ||||
Alias: alias, | |||||
LowerName: strings.ToLower(name), | LowerName: strings.ToLower(name), | ||||
Description: desc, | Description: desc, | ||||
DefaultBranch: oldRepo.DefaultBranch, | DefaultBranch: oldRepo.DefaultBranch, | ||||
@@ -18,7 +18,7 @@ func TestForkRepository(t *testing.T) { | |||||
user := models.AssertExistsAndLoadBean(t, &models.User{ID: 13}).(*models.User) | user := models.AssertExistsAndLoadBean(t, &models.User{ID: 13}).(*models.User) | ||||
repo := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 10}).(*models.Repository) | 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.Nil(t, fork) | ||||
assert.Error(t, err) | assert.Error(t, err) | ||||
assert.True(t, models.IsErrForkAlreadyExist(err)) | assert.True(t, models.IsErrForkAlreadyExist(err)) | ||||
@@ -236,6 +236,7 @@ func GenerateRepository(ctx models.DBContext, doer, owner *models.User, template | |||||
Owner: owner, | Owner: owner, | ||||
OwnerName: owner.Name, | OwnerName: owner.Name, | ||||
Name: opts.Name, | Name: opts.Name, | ||||
Alias: opts.Alias, | |||||
LowerName: strings.ToLower(opts.Name), | LowerName: strings.ToLower(opts.Name), | ||||
Description: opts.Description, | Description: opts.Description, | ||||
IsPrivate: opts.Private, | IsPrivate: opts.Private, | ||||
@@ -51,7 +51,7 @@ func prepareRepoCommit(ctx models.DBContext, repo *models.Repository, tmpDir, re | |||||
cloneLink := repo.CloneLink() | cloneLink := repo.CloneLink() | ||||
match := map[string]string{ | match := map[string]string{ | ||||
"Name": repo.Name, | |||||
"Name": repo.DisplayName(), | |||||
"Description": repo.Description, | "Description": repo.Description, | ||||
"CloneURL.SSH": cloneLink.SSH, | "CloneURL.SSH": cloneLink.SSH, | ||||
"CloneURL.HTTPS": cloneLink.HTTPS, | "CloneURL.HTTPS": cloneLink.HTTPS, | ||||
@@ -46,31 +46,33 @@ type ExternalWiki struct { | |||||
// Repository represents a repository | // Repository represents a repository | ||||
type Repository struct { | 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 | // swagger:strfmt date-time | ||||
Created time.Time `json:"created_at"` | Created time.Time `json:"created_at"` | ||||
// swagger:strfmt date-time | // swagger:strfmt date-time | ||||
@@ -217,6 +219,7 @@ type MigrateRepoOption struct { | |||||
UID int `json:"uid" binding:"Required"` | UID int `json:"uid" binding:"Required"` | ||||
// required: true | // required: true | ||||
RepoName string `json:"repo_name" binding:"Required"` | RepoName string `json:"repo_name" binding:"Required"` | ||||
Alias string `json:"alias" binding:"Required"` | |||||
Mirror bool `json:"mirror"` | Mirror bool `json:"mirror"` | ||||
Private bool `json:"private"` | Private bool `json:"private"` | ||||
Description string `json:"description"` | 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{ | repo, err := repo_module.CreateRepository(doer, u, models.CreateRepoOptions{ | ||||
Name: opts.RepoName, | Name: opts.RepoName, | ||||
Alias: opts.Alias, | |||||
Description: opts.Description, | Description: opts.Description, | ||||
OriginalURL: opts.OriginalURL, | OriginalURL: opts.OriginalURL, | ||||
GitServiceType: opts.GitServiceType, | GitServiceType: opts.GitServiceType, | ||||
@@ -19,6 +19,8 @@ const ( | |||||
// ErrGlobPattern is returned when glob pattern is invalid | // ErrGlobPattern is returned when glob pattern is invalid | ||||
ErrGlobPattern = "GlobPattern" | ErrGlobPattern = "GlobPattern" | ||||
ErrAlphaDashDotChinese = "AlphaDashDotChineseError" | |||||
) | ) | ||||
var ( | 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 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 | // They cannot have question-mark ?, asterisk *, or open bracket [ anywhere | ||||
GitRefNamePatternInvalid = regexp.MustCompile(`[\000-\037\177 \\~^:?*[]+`) | GitRefNamePatternInvalid = regexp.MustCompile(`[\000-\037\177 \\~^:?*[]+`) | ||||
AlphaDashDotChinese = regexp.MustCompile("^[\u4e00-\u9fa5\\.\\-_A-Za-z0-9]+$") | |||||
) | ) | ||||
// CheckGitRefAdditionalRulesValid check name is valid on additional rules | // CheckGitRefAdditionalRulesValid check name is valid on additional rules | ||||
@@ -53,6 +57,7 @@ func AddBindingRules() { | |||||
addGitRefNameBindingRule() | addGitRefNameBindingRule() | ||||
addValidURLBindingRule() | addValidURLBindingRule() | ||||
addGlobPatternRule() | addGlobPatternRule() | ||||
addAlphaDashDotChineseRule() | |||||
} | } | ||||
func addGitRefNameBindingRule() { | 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 { | func portOnly(hostport string) string { | ||||
colon := strings.IndexByte(hostport, ':') | colon := strings.IndexByte(hostport, ':') | ||||
if colon == -1 { | if colon == -1 { | ||||
@@ -139,3 +159,7 @@ func validPort(p string) bool { | |||||
} | } | ||||
return true | return true | ||||
} | } | ||||
func ValidAlphaDashDotChinese(value string) bool { | |||||
return AlphaDashDotChinese.MatchString(value) | |||||
} |
@@ -348,7 +348,9 @@ modify = Update | |||||
[form] | [form] | ||||
UserName = Username | UserName = Username | ||||
RepoName = Repository name | |||||
Alias = Repository name | |||||
RepoPath = Repository path | |||||
RepoAdress = Repository Adress | |||||
Email = Email address | Email = Email address | ||||
Password = Password | Password = Password | ||||
Retype = Re-Type Password | Retype = Re-Type Password | ||||
@@ -372,7 +374,10 @@ SSPIDefaultLanguage = Default Language | |||||
require_error = ` cannot be empty.` | require_error = ` cannot be empty.` | ||||
alpha_dash_error = ` should contain only alphanumeric, dash ('-') and underscore ('_') characters.` | alpha_dash_error = ` should contain only alphanumeric, dash ('-') and underscore ('_') characters.` | ||||
alpha_dash_dot_error = ` should contain only alphanumeric, dash ('-'), underscore ('_') and dot ('.') 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.` | 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.` | size_error = ` must be size %s.` | ||||
min_size_error = ` must contain at least %s characters.` | min_size_error = ` must contain at least %s characters.` | ||||
max_size_error = ` must contain at most %s characters.` | max_size_error = ` must contain at most %s characters.` | ||||
@@ -386,7 +391,7 @@ password_not_match = The passwords do not match. | |||||
lang_select_error = Select a language from the list. | lang_select_error = Select a language from the list. | ||||
username_been_taken = The username is already taken. | 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. | visit_rate_limit = Remote visit addressed rate limitation. | ||||
2fa_auth_required = Remote visit required two factors authentication. | 2fa_auth_required = Remote visit required two factors authentication. | ||||
org_name_been_taken = The organization name is already taken. | org_name_been_taken = The organization name is already taken. | ||||
@@ -899,7 +904,7 @@ modelarts.train_job.description=Description | |||||
modelarts.train_job.parameter_setting=Parameter setting | modelarts.train_job.parameter_setting=Parameter setting | ||||
modelarts.train_job.parameter_setting_info=Parameter Info | modelarts.train_job.parameter_setting_info=Parameter Info | ||||
modelarts.train_job.fast_parameter_setting=fast_parameter_setting | 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.fast_parameter_setting_config_link=fast_parameter_setting_config_link | ||||
modelarts.train_job.frames=frames | modelarts.train_job.frames=frames | ||||
modelarts.train_job.algorithm_origin=Algorithm Origin | modelarts.train_job.algorithm_origin=Algorithm Origin | ||||
@@ -974,6 +979,9 @@ template.avatar = Avatar | |||||
template.issue_labels = Issue Labels | template.issue_labels = Issue Labels | ||||
template.one_item = Must select at least one template item | template.one_item = Must select at least one template item | ||||
template.invalid = Must select a template repository | 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.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. | archive.issue.nocomment = This repo is archived. You cannot comment on issues. | ||||
@@ -1194,7 +1202,7 @@ issues.filter_label_exclude = `Use <code>alt</code> + <code>click/enter</code> t | |||||
issues.filter_label_no_select = All labels | issues.filter_label_no_select = All labels | ||||
issues.filter_milestone = Milestone | issues.filter_milestone = Milestone | ||||
issues.filter_milestone_no_select = All milestones | 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_assignee = Assignee | ||||
issues.filter_assginee_no_select = All assignees | issues.filter_assginee_no_select = All assignees | ||||
issues.filter_type = Type | issues.filter_type = Type | ||||
@@ -350,7 +350,10 @@ modify=更新 | |||||
[form] | [form] | ||||
UserName=用户名 | UserName=用户名 | ||||
RepoName=项目名称 | |||||
RepoName=项目路径 | |||||
Alias=项目名称 | |||||
RepoPath=项目路径 | |||||
RepoAdress=项目地址 | |||||
Email=邮箱地址 | Email=邮箱地址 | ||||
Password=密码 | Password=密码 | ||||
Retype=重新输入密码 | Retype=重新输入密码 | ||||
@@ -374,7 +377,10 @@ SSPIDefaultLanguage=默认语言 | |||||
require_error=不能为空。 | require_error=不能为空。 | ||||
alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。 | alpha_dash_error=应该只包含字母数字、破折号 ('-') 和下划线 ('_') 字符。 | ||||
alpha_dash_dot_error=应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。 | alpha_dash_dot_error=应该只包含字母数字, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。 | ||||
reponame_dash_dot_error=请输入中文、字母、数字和-_ .,最多100个字符。 | |||||
repoadd_dash_dot_error=路径只允许字母、数字和-_ .,最多100个字符。 | |||||
git_ref_name_error=` 必须是格式良好的 git 引用名称。` | git_ref_name_error=` 必须是格式良好的 git 引用名称。` | ||||
alpha_dash_dot_chinese_error=应该只包含字母数字中文, 破折号 ('-'), 下划线 ('_') 和点 ('. ') 。 | |||||
size_error=长度必须为 %s。 | size_error=长度必须为 %s。 | ||||
min_size_error=长度最小为 %s 个字符。 | min_size_error=长度最小为 %s 个字符。 | ||||
max_size_error=长度最大为 %s 个字符。 | max_size_error=长度最大为 %s 个字符。 | ||||
@@ -388,7 +394,7 @@ password_not_match=密码不匹配。 | |||||
lang_select_error=从列表中选出语言 | lang_select_error=从列表中选出语言 | ||||
username_been_taken=用户名已被使用。 | username_been_taken=用户名已被使用。 | ||||
repo_name_been_taken=项目名称已被使用。 | |||||
repo_name_been_taken=项目名称或项目路径已被使用。 | |||||
visit_rate_limit=远程访问达到速度限制。 | visit_rate_limit=远程访问达到速度限制。 | ||||
2fa_auth_required=远程访问需要双重验证。 | 2fa_auth_required=远程访问需要双重验证。 | ||||
org_name_been_taken=组织名称已被使用。 | org_name_been_taken=组织名称已被使用。 | ||||
@@ -984,6 +990,9 @@ template.avatar=头像 | |||||
template.issue_labels=任务标签 | template.issue_labels=任务标签 | ||||
template.one_item=必须至少选择一个模板项 | template.one_item=必须至少选择一个模板项 | ||||
template.invalid=必须选择一个模板项目 | template.invalid=必须选择一个模板项目 | ||||
template.repo_adress=项目地址 | |||||
template.repo_path=项目地址 | |||||
template.repo_name=项目名称 | |||||
archive.title=此项目已存档。您可以查看文件和克隆,但不能推送或创建任务/合并请求。 | archive.title=此项目已存档。您可以查看文件和克隆,但不能推送或创建任务/合并请求。 | ||||
archive.issue.nocomment=此项目已存档,您不能在此任务添加评论。 | archive.issue.nocomment=此项目已存档,您不能在此任务添加评论。 | ||||
@@ -4,7 +4,6 @@ if(isEmpty(token)){ | |||||
var meta = $("meta[name=_uid]"); | var meta = $("meta[name=_uid]"); | ||||
if(!isEmpty(meta)){ | if(!isEmpty(meta)){ | ||||
token = meta.attr("content"); | 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"); | 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"; | var url = "ws://" + document.location.host + "/action/notification"; | ||||
if(document.location.host == "git.openi.org.cn" || document.URL.startsWith("https")){ | if(document.location.host == "git.openi.org.cn" || document.URL.startsWith("https")){ | ||||
url = "wss://" + document.location.host + "/action/notification" | url = "wss://" + document.location.host + "/action/notification" | ||||
@@ -51,18 +48,14 @@ var html =document.documentElement; | |||||
var lang = html.attributes["lang"] | var lang = html.attributes["lang"] | ||||
var isZh = true; | var isZh = true; | ||||
if(lang != null && lang.nodeValue =="en-US" ){ | if(lang != null && lang.nodeValue =="en-US" ){ | ||||
console.log("the language is " + lang.nodeValue); | |||||
isZh=false; | isZh=false; | ||||
}else{ | }else{ | ||||
console.log("default lang=zh"); | |||||
} | } | ||||
socket.onmessage = function (e) { | socket.onmessage = function (e) { | ||||
var data =JSON.parse(e.data) | var data =JSON.parse(e.data) | ||||
console.log("recevie data=" + e.data) | |||||
var html = ""; | var html = ""; | ||||
if (data != null){ | if (data != null){ | ||||
console.log("queue length=" + messageQueue.length); | |||||
if(messageQueue.length > maxSize){ | if(messageQueue.length > maxSize){ | ||||
delete messageQueue[0]; | delete messageQueue[0]; | ||||
}else{ | }else{ | ||||
@@ -71,38 +64,38 @@ socket.onmessage = function (e) { | |||||
var currentTime = new Date().getTime(); | var currentTime = new Date().getTime(); | ||||
for(var i = 0; i < messageQueue.length; i++){ | for(var i = 0; i < messageQueue.length; i++){ | ||||
var record = messageQueue[i]; | var record = messageQueue[i]; | ||||
var recordPrefix = getMsg(record); | var recordPrefix = getMsg(record); | ||||
var actionName = getAction(record.OpType,isZh); | var actionName = getAction(record.OpType,isZh); | ||||
if(record.OpType == "6" || record.OpType == "10" || record.OpType == "12" || record.OpType == "13"){ | if(record.OpType == "6" || record.OpType == "10" || record.OpType == "12" || record.OpType == "13"){ | ||||
html += recordPrefix + actionName; | 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" | else if(record.OpType == "7" || record.OpType == "11" || record.OpType == "14" || record.OpType == "15" || record.OpType == "22" | ||||
|| record.OpType == "23"){ | || record.OpType == "23"){ | ||||
html += recordPrefix + actionName; | 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"){ | else if(record.OpType == "1"){ | ||||
html += recordPrefix + actionName; | 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"){ | else if(record.OpType == "9" || record.OpType == "5"){ | ||||
branch = "<a href=\"" + getRepoLink(record) + "/src/branch/" + record.RefName + "\" rel=\"nofollow\">" + record.RefName + "</a>" | branch = "<a href=\"" + getRepoLink(record) + "/src/branch/" + record.RefName + "\" rel=\"nofollow\">" + record.RefName + "</a>" | ||||
actionName = actionName.replace("{branch}",branch); | actionName = actionName.replace("{branch}",branch); | ||||
html += recordPrefix + actionName; | 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"){ | }else if(record.OpType == "17"){ | ||||
actionName = actionName.replace("{deleteBranchName}",record.RefName); | 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); | actionName = actionName.replace("{repoName}",repoLink); | ||||
html += recordPrefix + actionName; | html += recordPrefix + actionName; | ||||
} | } | ||||
else if(record.OpType == "2"){ | else if(record.OpType == "2"){ | ||||
actionName = actionName.replace("{oldRepoName}",record.Content); | actionName = actionName.replace("{oldRepoName}",record.Content); | ||||
html += recordPrefix + actionName; | html += recordPrefix + actionName; | ||||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>" | |||||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepotext(record) + "</a>" | |||||
} | } | ||||
else{ | else{ | ||||
continue; | continue; | ||||
@@ -115,17 +108,8 @@ socket.onmessage = function (e) { | |||||
html += "</div>"; | html += "</div>"; | ||||
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; | output.innerHTML = html; | ||||
swiperNewMessage.updateSlides(); | swiperNewMessage.updateSlides(); | ||||
swiperNewMessage.updateProgress(); | swiperNewMessage.updateProgress(); | ||||
@@ -136,15 +120,20 @@ function getMsg(record){ | |||||
html += "<div class=\"swiper-slide item\">"; | html += "<div class=\"swiper-slide item\">"; | ||||
html += " <img class=\"ui avatar image\" src=\"/user/avatar/" + record.ActUser.Name + "/-1\" alt=\"\">" | html += " <img class=\"ui avatar image\" src=\"/user/avatar/" + record.ActUser.Name + "/-1\" alt=\"\">" | ||||
html += " <div class=\"middle aligned content nowrap\">" | 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; | 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){ | function getRepoLink(record){ | ||||
return record.Repo.OwnerName + "/" + record.Repo.Name; | return record.Repo.OwnerName + "/" + record.Repo.Name; | ||||
} | } | ||||
function getTime(UpdatedUnix,currentTime){ | function getTime(UpdatedUnix,currentTime){ | ||||
@@ -154,8 +143,7 @@ function getTime(UpdatedUnix,currentTime){ | |||||
if( timeEscSecond < 0){ | if( timeEscSecond < 0){ | ||||
timeEscSecond = 1; | timeEscSecond = 1; | ||||
} | } | ||||
console.log("currentTime=" + currentTime + " updateUnix=" + UpdatedUnix); | |||||
var hours= Math.floor(timeEscSecond / 3600); | var hours= Math.floor(timeEscSecond / 3600); | ||||
//计算相差分钟数 | //计算相差分钟数 | ||||
var leave2 = 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); | return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/pulls/" + getIssueId(record); | ||||
} | } | ||||
function getPRText(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){ | function getIssueLink(record){ | ||||
return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/issues/" + getIssueId(record); | return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/issues/" + getIssueId(record); | ||||
} | } | ||||
@@ -204,7 +197,12 @@ function getIssueId(record){ | |||||
} | } | ||||
function getIssueText(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); | |||||
} | |||||
} | } | ||||
/* | /* | ||||
@@ -289,7 +287,7 @@ var repoAndOrgEN={ | |||||
"2":"Member ", | "2":"Member ", | ||||
"3":"Team", | "3":"Team", | ||||
"11":"Repositories", | "11":"Repositories", | ||||
"22":"Members ", | |||||
"21":"Members ", | |||||
"31":"Teams", | "31":"Teams", | ||||
"4":" hour ago", | "4":" hour ago", | ||||
"5":" minute ago", | "5":" minute ago", | ||||
@@ -320,11 +318,9 @@ function queryRecommendData(){ | |||||
dataType:"json", | dataType:"json", | ||||
async:false, | async:false, | ||||
success:function(json){ | success:function(json){ | ||||
console.log(json); | |||||
displayOrg(json); | displayOrg(json); | ||||
}, | }, | ||||
error:function(response) { | error:function(response) { | ||||
console.log(response); | |||||
} | } | ||||
}); | }); | ||||
@@ -337,40 +333,14 @@ function queryRecommendData(){ | |||||
dataType:"json", | dataType:"json", | ||||
async:false, | async:false, | ||||
success:function(json){ | success:function(json){ | ||||
console.log(json); | |||||
displayRepo(json); | displayRepo(json); | ||||
}, | }, | ||||
error:function(response) { | 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){ | function displayRepo(json){ | ||||
var orgRepo = document.getElementById("recommendrepo"); | var orgRepo = document.getElementById("recommendrepo"); | ||||
var html = ""; | 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 += " <i class=\"ri-star-line\"></i>" + record["NumStars"] + "<i class=\"ri-git-branch-line am-ml-10\"></i>" + record["NumForks"]; | ||||
html += " </span>"; | html += " </span>"; | ||||
html += " <img class=\"left floated mini ui image\" src=\"" + record["Avatar"] + "\">"; | 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=\"description nowrap-2\">" + record["Description"] + " </div>"; | ||||
html += " <div class=\"ui tags nowrap am-mt-10\">" | html += " <div class=\"ui tags nowrap am-mt-10\">" | ||||
if(record["Topics"] != null){ | if(record["Topics"] != null){ | ||||
@@ -405,27 +375,6 @@ function displayRepo(json){ | |||||
swiperRepo.updateProgress(); | 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){ | function getRepoOrOrg(key,isZhLang,numbers=1){ | ||||
if(numbers > 1){ | if(numbers > 1){ | ||||
@@ -437,7 +386,6 @@ function getRepoOrOrg(key,isZhLang,numbers=1){ | |||||
return repoAndOrgEN[key]; | return repoAndOrgEN[key]; | ||||
} | } | ||||
} | } | ||||
function displayOrg(json){ | function displayOrg(json){ | ||||
var orgDiv = document.getElementById("recommendorg"); | var orgDiv = document.getElementById("recommendorg"); | ||||
var html = ""; | var html = ""; | ||||
@@ -460,4 +408,4 @@ function displayOrg(json){ | |||||
} | } | ||||
} | } | ||||
orgDiv.innerHTML = html; | orgDiv.innerHTML = html; | ||||
} | |||||
} |
@@ -118,7 +118,7 @@ func CreateFork(ctx *context.APIContext, form api.CreateForkOption) { | |||||
forker = org | 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 { | if err != nil { | ||||
ctx.Error(http.StatusInternalServerError, "ForkRepository", err) | ctx.Error(http.StatusInternalServerError, "ForkRepository", err) | ||||
return | return | ||||
@@ -625,11 +625,12 @@ func RecommendRepoFromPromote(ctx *context.Context) { | |||||
} else { | } else { | ||||
ownerName := strings.Trim(repoName[0:tmpIndex], " ") | ownerName := strings.Trim(repoName[0:tmpIndex], " ") | ||||
repoName := strings.Trim(repoName[tmpIndex+1:], " ") | repoName := strings.Trim(repoName[tmpIndex+1:], " ") | ||||
repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName) | |||||
repo, err := models.GetRepositoryByOwnerAndAlias(ownerName, repoName) | |||||
if err == nil { | if err == nil { | ||||
repoMap := make(map[string]interface{}) | repoMap := make(map[string]interface{}) | ||||
repoMap["ID"] = fmt.Sprint(repo.ID) | repoMap["ID"] = fmt.Sprint(repo.ID) | ||||
repoMap["Name"] = repo.Name | repoMap["Name"] = repo.Name | ||||
repoMap["Alias"] = repo.Alias | |||||
repoMap["OwnerName"] = repo.OwnerName | repoMap["OwnerName"] = repo.OwnerName | ||||
repoMap["NumStars"] = repo.NumStars | repoMap["NumStars"] = repo.NumStars | ||||
repoMap["NumForks"] = repo.NumForks | repoMap["NumForks"] = repo.NumForks | ||||
@@ -143,7 +143,7 @@ func TeamsRepoAction(ctx *context.Context) { | |||||
case "add": | case "add": | ||||
repoName := path.Base(ctx.Query("repo_name")) | repoName := path.Base(ctx.Query("repo_name")) | ||||
var repo *models.Repository | 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 err != nil { | ||||
if models.IsErrRepoNotExist(err) { | if models.IsErrRepoNotExist(err) { | ||||
ctx.Flash.Error(ctx.Tr("org.teams.add_nonexistent_repo")) | ctx.Flash.Error(ctx.Tr("org.teams.add_nonexistent_repo")) | ||||
@@ -336,6 +336,11 @@ func CloudBrainRestart(ctx *context.Context) { | |||||
} | } | ||||
func CloudBrainBenchMarkShow(ctx *context.Context) { | func CloudBrainBenchMarkShow(ctx *context.Context) { | ||||
if benchmarkTypes == nil { | |||||
if err := json.Unmarshal([]byte(setting.BenchmarkTypes), &benchmarkTypes); err != nil { | |||||
log.Error("json.Unmarshal BenchmarkTypes(%s) failed:%v", setting.BenchmarkTypes, err, ctx.Data["MsgID"]) | |||||
} | |||||
} | |||||
cloudBrainShow(ctx, tplCloudBrainBenchmarkShow) | cloudBrainShow(ctx, tplCloudBrainBenchmarkShow) | ||||
} | } | ||||
@@ -400,6 +405,21 @@ func cloudBrainShow(ctx *context.Context, tpName base.TplName) { | |||||
} else { | } else { | ||||
duration = int64(task.UpdatedUnix) - int64(task.CreatedUnix) | duration = int64(task.UpdatedUnix) - int64(task.CreatedUnix) | ||||
} | } | ||||
if benchmarkTypes != nil { | |||||
for _, benchmarkType := range benchmarkTypes.BenchmarkType { | |||||
if task.BenchmarkTypeID == benchmarkType.Id { | |||||
ctx.Data["BenchmarkTypeName"] = benchmarkType.First | |||||
for _, benchmarkChildType := range benchmarkType.Second { | |||||
if task.BenchmarkChildTypeID == benchmarkChildType.Id { | |||||
ctx.Data["BenchmarkChildTypeName"] = benchmarkChildType.Value | |||||
break | |||||
} | |||||
} | |||||
break | |||||
} | |||||
} | |||||
} | |||||
ctx.Data["duration"] = util.AddZero(duration/3600000) + ":" + util.AddZero(duration%3600000/60000) + ":" + util.AddZero(duration%60000/1000) | ctx.Data["duration"] = util.AddZero(duration/3600000) + ":" + util.AddZero(duration%3600000/60000) + ":" + util.AddZero(duration%60000/1000) | ||||
ctx.Data["task"] = task | ctx.Data["task"] = task | ||||
ctx.Data["jobID"] = jobID | ctx.Data["jobID"] = jobID | ||||
@@ -445,7 +465,7 @@ func CloudBrainStop(ctx *context.Context) { | |||||
task := ctx.Cloudbrain | task := ctx.Cloudbrain | ||||
for { | for { | ||||
if task.Status == string(models.JobStopped) || task.Status == string(models.JobFailed) || task.Status == string(models.JobSucceeded){ | |||||
if task.Status == string(models.JobStopped) || task.Status == string(models.JobFailed) || task.Status == string(models.JobSucceeded) { | |||||
log.Error("the job(%s) has been stopped", task.JobName, ctx.Data["msgID"]) | log.Error("the job(%s) has been stopped", task.JobName, ctx.Data["msgID"]) | ||||
resultCode = "-1" | resultCode = "-1" | ||||
errorMsg = "system error" | errorMsg = "system error" | ||||
@@ -1180,6 +1200,7 @@ func CloudBrainBenchmarkCreate(ctx *context.Context, form auth.CreateCloudBrainF | |||||
benchmarkChildTypeID := form.BenchmarkChildTypeID | benchmarkChildTypeID := form.BenchmarkChildTypeID | ||||
if !jobNamePattern.MatchString(jobName) { | if !jobNamePattern.MatchString(jobName) { | ||||
cloudBrainNewDataPrepare(ctx) | |||||
ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplCloudBrainBenchmarkNew, &form) | ctx.RenderWithErr(ctx.Tr("repo.cloudbrain_jobname_err"), tplCloudBrainBenchmarkNew, &form) | ||||
return | return | ||||
} | } | ||||
@@ -105,6 +105,7 @@ func getForkRepository(ctx *context.Context) *models.Repository { | |||||
return nil | return nil | ||||
} | } | ||||
ctx.Data["ForkFrom"] = forkRepo.Owner.Name + "/" + forkRepo.Name | ctx.Data["ForkFrom"] = forkRepo.Owner.Name + "/" + forkRepo.Name | ||||
ctx.Data["ForkDisplayName"] = forkRepo.FullDisplayName() | |||||
ctx.Data["ForkFromOwnerID"] = forkRepo.Owner.ID | ctx.Data["ForkFromOwnerID"] = forkRepo.Owner.ID | ||||
if err := ctx.User.GetOwnedOrganizations(); err != nil { | 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 { | if err != nil { | ||||
ctx.Data["Err_RepoName"] = true | ctx.Data["Err_RepoName"] = true | ||||
switch { | switch { | ||||
@@ -6,11 +6,14 @@ | |||||
package repo | package repo | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/modules/validation" | |||||
"fmt" | "fmt" | ||||
"net/url" | "net/url" | ||||
"os" | "os" | ||||
"path" | "path" | ||||
"regexp" | |||||
"strings" | "strings" | ||||
"unicode/utf8" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/auth" | "code.gitea.io/gitea/modules/auth" | ||||
@@ -201,6 +204,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { | |||||
if form.RepoTemplate > 0 { | if form.RepoTemplate > 0 { | ||||
opts := models.GenerateRepoOptions{ | opts := models.GenerateRepoOptions{ | ||||
Name: form.RepoName, | Name: form.RepoName, | ||||
Alias: form.Alias, | |||||
Description: form.Description, | Description: form.Description, | ||||
Private: form.Private, | Private: form.Private, | ||||
GitContent: form.GitContent, | GitContent: form.GitContent, | ||||
@@ -235,6 +239,7 @@ func CreatePost(ctx *context.Context, form auth.CreateRepoForm) { | |||||
} else { | } else { | ||||
repo, err = repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{ | repo, err = repo_service.CreateRepository(ctx.User, ctxUser, models.CreateRepoOptions{ | ||||
Name: form.RepoName, | Name: form.RepoName, | ||||
Alias: form.Alias, | |||||
Description: form.Description, | Description: form.Description, | ||||
Gitignores: form.Gitignores, | Gitignores: form.Gitignores, | ||||
IssueLabels: form.IssueLabels, | IssueLabels: form.IssueLabels, | ||||
@@ -358,6 +363,7 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) { | |||||
GitServiceType: gitServiceType, | GitServiceType: gitServiceType, | ||||
CloneAddr: remoteAddr, | CloneAddr: remoteAddr, | ||||
RepoName: form.RepoName, | RepoName: form.RepoName, | ||||
Alias: form.Alias, | |||||
Description: form.Description, | Description: form.Description, | ||||
Private: form.Private || setting.Repository.ForcePrivate, | Private: form.Private || setting.Repository.ForcePrivate, | ||||
Mirror: form.Mirror, | Mirror: form.Mirror, | ||||
@@ -380,7 +386,7 @@ func MigratePost(ctx *context.Context, form auth.MigrateRepoForm) { | |||||
opts.Releases = false | opts.Releases = false | ||||
} | } | ||||
err = models.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName) | |||||
err = models.CheckCreateRepository(ctx.User, ctxUser, opts.RepoName, opts.Alias) | |||||
if err != nil { | if err != nil { | ||||
handleMigrateError(ctx, ctxUser, err, "MigratePost", tplMigrate, &form) | handleMigrateError(ctx, ctxUser, err, "MigratePost", tplMigrate, &form) | ||||
return | return | ||||
@@ -552,3 +558,27 @@ func Status(ctx *context.Context) { | |||||
"err": task.Errors, | "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 | package repo | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/modules/notification" | |||||
"errors" | "errors" | ||||
"fmt" | "fmt" | ||||
"io/ioutil" | "io/ioutil" | ||||
@@ -70,6 +71,30 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||||
return | 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 | newRepoName := form.RepoName | ||||
// Check if repository name has been changed. | // Check if repository name has been changed. | ||||
if repo.LowerName != strings.ToLower(newRepoName) { | 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) | 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. | // In case it's just a case change. | ||||
repo.Name = newRepoName | repo.Name = newRepoName | ||||
repo.LowerName = strings.ToLower(newRepoName) | repo.LowerName = strings.ToLower(newRepoName) | ||||
repo.Description = form.Description | repo.Description = form.Description | ||||
repo.Website = form.Website | repo.Website = form.Website | ||||
repo.IsTemplate = form.Template | repo.IsTemplate = form.Template | ||||
repo.Alias = newAlias | |||||
repo.LowerAlias = strings.ToLower(newAlias) | |||||
// Visibility of forked repository is forced sync with base repository. | // Visibility of forked repository is forced sync with base repository. | ||||
if repo.IsFork { | if repo.IsFork { | ||||
@@ -380,7 +412,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||||
ctx.Error(404) | ctx.Error(404) | ||||
return | return | ||||
} | } | ||||
if repo.Name != form.RepoName { | |||||
if repo.Alias != form.RepoName { | |||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | ||||
return | return | ||||
} | } | ||||
@@ -407,7 +439,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||||
ctx.Error(404) | ctx.Error(404) | ||||
return | return | ||||
} | } | ||||
if repo.Name != form.RepoName { | |||||
if repo.Alias != form.RepoName { | |||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | ||||
return | return | ||||
} | } | ||||
@@ -445,7 +477,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||||
ctx.Error(404) | ctx.Error(404) | ||||
return | return | ||||
} | } | ||||
if repo.Name != form.RepoName { | |||||
if repo.Alias != form.RepoName { | |||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | ||||
return | return | ||||
} | } | ||||
@@ -465,7 +497,7 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) { | |||||
ctx.Error(404) | ctx.Error(404) | ||||
return | return | ||||
} | } | ||||
if repo.Name != form.RepoName { | |||||
if repo.Alias != form.RepoName { | |||||
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil) | ||||
return | return | ||||
} | } | ||||
@@ -718,6 +718,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Combo("/:repoid").Get(repo.Fork). | m.Combo("/:repoid").Get(repo.Fork). | ||||
Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost) | Post(bindIgnErr(auth.CreateRepoForm{}), repo.ForkPost) | ||||
}, context.RepoIDAssignment(), context.UnitTypes(), reqRepoCodeReader) | }, context.RepoIDAssignment(), context.UnitTypes(), reqRepoCodeReader) | ||||
m.Get("/check_name", repo.CheckName) | |||||
}, reqSignIn) | }, reqSignIn) | ||||
// ***** Release Attachment Download without Signin | // ***** Release Attachment Download without Signin | ||||
@@ -31,8 +31,8 @@ func CreateRepository(doer, owner *models.User, opts models.CreateRepoOptions) ( | |||||
} | } | ||||
// ForkRepository forks a repository | // 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 err != nil { | ||||
if repo != nil { | if repo != nil { | ||||
if errDelete := models.DeleteRepository(doer, u.ID, repo.ID); errDelete != 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. | // ChangeRepositoryName changes all corresponding setting from old repository name to new one. | ||||
func ChangeRepositoryName(doer *models.User, repo *models.Repository, newRepoName string) error { | 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 | // 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 | // 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)) | repoWorkingPool.CheckOut(com.ToStr(repo.ID)) | ||||
notification.NotifyRenameRepository(doer, repo, oldRepoName) | |||||
//notification.NotifyRenameRepository(doer, repo, oldRepoName) | |||||
return nil | return nil | ||||
} | } |
@@ -36,7 +36,7 @@ | |||||
<span class="text gold">{{svg "octicon-lock" 16}}</span> | <span class="text gold">{{svg "octicon-lock" 16}}</span> | ||||
{{end}} | {{end}} | ||||
</td> | </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><i class="fa fa{{if .IsPrivate}}-check{{end}}-square-o"></i></td> | ||||
<td>{{.NumWatches}}</td> | <td>{{.NumWatches}}</td> | ||||
<td>{{.NumStars}}</td> | <td>{{.NumStars}}</td> | ||||
@@ -25,7 +25,7 @@ | |||||
<div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | <div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000; white-space: nowrap;" class=" item" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -55,7 +55,7 @@ | |||||
<div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | <div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "issues"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "issues"}}</a> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000; white-space: nowrap;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -25,7 +25,7 @@ | |||||
<div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | <div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000; white-space: nowrap;" class=" item" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -54,7 +54,7 @@ | |||||
<div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | <div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "issues"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "issues"}}</a> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000; white-space: nowrap;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -17,7 +17,7 @@ | |||||
<div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | <div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000; white-space: nowrap;" class=" item" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -46,7 +46,7 @@ | |||||
<div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | <div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "issues"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "issues"}}</a> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000; white-space: nowrap;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -26,7 +26,7 @@ | |||||
<div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | <div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;white-space: nowrap;" class=" item" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -56,7 +56,7 @@ | |||||
<div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | <div class="dropdown-content" style="min-width: 110px;border-radius:4px"> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "issues"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "issues"}}</a> | ||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;white-space: nowrap;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a> | <a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -5,7 +5,7 @@ | |||||
border-radius: 0.8rem; | border-radius: 0.8rem; | ||||
margin-bottom: 1.0rem; | margin-bottom: 1.0rem; | ||||
padding: 1.0rem !important; | padding: 1.0rem !important; | ||||
} | |||||
} | |||||
.ui.repository.list>.item .header { | .ui.repository.list>.item .header { | ||||
font-size: 1.4rem !important; | font-size: 1.4rem !important; | ||||
font-weight: 200; | font-weight: 200; | ||||
@@ -24,7 +24,7 @@ | |||||
content: ""; | content: ""; | ||||
height: 1px; | height: 1px; | ||||
background-color: #E1E3E6; | background-color: #E1E3E6; | ||||
bottom: 2.8rem; | |||||
bottom: 2.8rem; | |||||
} | } | ||||
.repository .ui.mini.menu{ | .repository .ui.mini.menu{ | ||||
font-size: .6rem; | 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}}"> | <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"> | <svg class="svg octicon-repo" width="16" height="16" aria-hidden="true"> | ||||
<use xlink:href="#octicon-repo" /> | <use xlink:href="#octicon-repo" /> | ||||
</svg> | |||||
</svg> | |||||
热门{{.i18n.Tr "explore.repos"}} | 热门{{.i18n.Tr "explore.repos"}} | ||||
</a> | </a> | ||||
<a class="{{if eq .SortType "active"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=active&tab={{$.TabName}}"> | <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"> | <svg class="svg octicon-inbox" width="16" height="16" aria-hidden="true"> | ||||
<use xlink:href="#octicon-inbox" /> | <use xlink:href="#octicon-inbox" /> | ||||
</svg> | |||||
</svg> | |||||
活跃{{.i18n.Tr "explore.repos"}} | 活跃{{.i18n.Tr "explore.repos"}} | ||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
@@ -93,7 +93,7 @@ | |||||
<div class="ui grid"> | <div class="ui grid"> | ||||
<div class="ui sixteen wide mobile ten wide tablet twelve wide computer column"> | <div class="ui sixteen wide mobile ten wide tablet twelve wide computer column"> | ||||
<a class="name" href="{{.Link}}"> | <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}} | {{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}} | ||||
</a> | </a> | ||||
{{if .IsPrivate}} | {{if .IsPrivate}} | ||||
@@ -114,7 +114,7 @@ | |||||
<a class="item"> | <a class="item"> | ||||
<svg class="svg octicon-inbox" width="16" height="16" viewBox="0 0 24 24"> | <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" /> | <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}} | {{.Hot}} | ||||
</a> | </a> | ||||
{{else if eq $.SortType "active"}} | {{else if eq $.SortType "active"}} | ||||
@@ -130,7 +130,7 @@ | |||||
<a class="item"> | <a class="item"> | ||||
{{svg "octicon-git-branch" 16}} {{.NumForks}} | {{svg "octicon-git-branch" 16}} {{.NumForks}} | ||||
</a> | </a> | ||||
{{end}} | |||||
{{end}} | |||||
<a class="item"> | <a class="item"> | ||||
{{svg "octicon-star" 16}} {{.NumStars}} | {{svg "octicon-star" 16}} {{.NumStars}} | ||||
</a> | </a> | ||||
@@ -33,7 +33,7 @@ | |||||
<img class="ui avatar image" src="{{.RelAvatarLink}}"> | <img class="ui avatar image" src="{{.RelAvatarLink}}"> | ||||
{{end}} | {{end}} | ||||
<a class="name" href="{{.Link}}"> | <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}} | {{if .IsArchived}}<i class="archive icon archived-icon"></i>{{end}} | ||||
</a> | </a> | ||||
{{if .IsPrivate}} | {{if .IsPrivate}} | ||||
@@ -70,4 +70,4 @@ | |||||
{{$.i18n.Tr "explore.repo_no_results"}} | {{$.i18n.Tr "explore.repo_no_results"}} | ||||
</div> | </div> | ||||
{{end}} | {{end}} | ||||
</div> | |||||
</div> |
@@ -89,7 +89,7 @@ | |||||
<div class="extra full_height cor" > | <div class="extra full_height cor" > | ||||
<div class=" header header_card omit" > | <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> | ||||
<div class='content descript_height nowrap-2'> | <div class='content descript_height nowrap-2'> | ||||
@@ -167,6 +167,7 @@ | |||||
</div> | </div> | ||||
<script> | <script> | ||||
console.log({{.tags}}) | |||||
var data; | var data; | ||||
var filterData=[]; | var filterData=[]; | ||||
var num=0; | var num=0; | ||||
@@ -50,7 +50,7 @@ | |||||
{{else}} | {{else}} | ||||
{{svg "octicon-repo" 16}} | {{svg "octicon-repo" 16}} | ||||
{{end}} | {{end}} | ||||
<strong>{{$.Org.Name}}/{{.Name}}</strong> | |||||
<strong>{{$.Org.Name}}/{{.Alias}}</strong> | |||||
</a> | </a> | ||||
</div> | </div> | ||||
{{else}} | {{else}} | ||||
@@ -150,7 +150,7 @@ | |||||
</form> | </form> | ||||
<a class="ui basic blue button" href="{{$.RepoLink}}/cloudbrain/{{.JobID}}/rate" target="_blank"> | |||||
<a class="ui basic button {{if $.IsSigned}} blue{{else}} disabled{{end}}" href="{{$.RepoLink}}/cloudbrain/{{.JobID}}/rate" target="_blank"> | |||||
评分 | 评分 | ||||
</a> | </a> | ||||
@@ -116,7 +116,7 @@ | |||||
<div class="required unite min_title inline field"> | <div class="required unite min_title inline field"> | ||||
<label style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_mirror"}}</label> | <label style="font-weight: normal;">{{.i18n.Tr "repo.cloudbrain.benchmark.evaluate_mirror"}}</label> | ||||
<span> </span> | <span> </span> | ||||
<input type="text" list="cloudbrain_image" placeholder="选择镜像" name="image" class="required autofocus" style='width:492px;' maxlength="254"> | |||||
<input type="text" list="cloudbrain_image" placeholder="选择镜像" name="image" value="{{.image}}" class="required autofocus" style='width:492px;' maxlength="254"> | |||||
<i class="times circle outline icon icons" style="visibility: hidden;" onclick="clearValue()"></i> | <i class="times circle outline icon icons" style="visibility: hidden;" onclick="clearValue()"></i> | ||||
<datalist class="ui search" id="cloudbrain_image" style='width:385px;' name="image"> | <datalist class="ui search" id="cloudbrain_image" style='width:385px;' name="image"> | ||||
{{range .images}} | {{range .images}} | ||||
@@ -205,16 +205,6 @@ | |||||
on: 'blur', | on: 'blur', | ||||
inline:true, | inline:true, | ||||
fields: { | fields: { | ||||
job_name:{ | |||||
identifier : 'job_name', | |||||
rules: [ | |||||
{ | |||||
type: 'regExp[/^[a-zA-Z0-9-_]{1,36}$/]', | |||||
prompt : '只包含大小写字母、数字、_和-,最长36个字符。' | |||||
} | |||||
] | |||||
}, | |||||
image:{ | image:{ | ||||
identifier : 'image', | identifier : 'image', | ||||
rules: [ | rules: [ | ||||
@@ -277,7 +277,17 @@ td, th { | |||||
</div> | </div> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
<tr class="ti-no-ng-animate"> | |||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||||
类型 | |||||
</td> | |||||
<td class="ti-text-form-content"> | |||||
<div class="text-span text-span-w" id="{{.VersionName}}-BenchmarkTypeName"> | |||||
{{$.BenchmarkTypeName}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
</tbody> | </tbody> | ||||
@@ -346,6 +356,17 @@ td, th { | |||||
</div> | </div> | ||||
</td> | </td> | ||||
</tr> | </tr> | ||||
<tr class="ti-no-ng-animate"> | |||||
<td class="ti-no-ng-animate ti-text-form-label text-width80"> | |||||
子类型 | |||||
</td> | |||||
<td class="ti-text-form-content"> | |||||
<div class="text-span text-span-w" id="{{.VersionName}}-BenchmarkChildTypeName"> | |||||
{{$.BenchmarkChildTypeName}} | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
</tbody> | </tbody> | ||||
</table> | </table> | ||||
</div> | </div> | ||||
@@ -2,43 +2,15 @@ | |||||
<div class="repository new repo" style="margin-top: 40px;"> | <div class="repository new repo" style="margin-top: 40px;"> | ||||
<div class="ui middle very relaxed page grid"> | <div class="ui middle very relaxed page grid"> | ||||
<div class="column"> | <div class="column"> | ||||
<form class="ui form" action="{{.Link}}" method="post"> | |||||
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form"> | |||||
{{.CsrfTokenHtml}} | {{.CsrfTokenHtml}} | ||||
<h3 class="ui top attached header"> | <h3 class="ui top attached header"> | ||||
{{.i18n.Tr "new_repo"}} | {{.i18n.Tr "new_repo"}} | ||||
</h3> | </h3> | ||||
<div class="ui attached segment"> | <div class="ui attached segment"> | ||||
{{template "base/alert" .}} | {{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"> | <div class="inline field"> | ||||
<label>{{.i18n.Tr "repo.visibility"}}</label> | <label>{{.i18n.Tr "repo.visibility"}}</label> | ||||
<div class="ui checkbox"> | <div class="ui checkbox"> | ||||
@@ -172,7 +144,7 @@ | |||||
<br/> | <br/> | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label></label> | <label></label> | ||||
<button class="ui green button"> | |||||
<button class="ui green button" id="submit_reponame"> | |||||
{{.i18n.Tr "repo.create_repo"}} | {{.i18n.Tr "repo.create_repo"}} | ||||
</button> | </button> | ||||
<a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a> | <a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a> | ||||
@@ -24,7 +24,7 @@ | |||||
{{end}} | {{end}} | ||||
<a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a> | <a href="{{AppSubUrl}}/{{.Owner.Name}}">{{.Owner.Name}}</a> | ||||
<div class="divider"> / </div> | <div class="divider"> / </div> | ||||
<a href="{{$.RepoLink}}">{{.Name}}</a> | |||||
<a href="{{$.RepoLink}}">{{.DisplayName}}</a> | |||||
{{if .RelAvatarLink}} | {{if .RelAvatarLink}} | ||||
{{if .IsTemplate}} | {{if .IsTemplate}} | ||||
{{if .IsPrivate}} | {{if .IsPrivate}} | ||||
@@ -46,7 +46,7 @@ | |||||
{{end}} | {{end}} | ||||
{{if .IsArchived}}<i class="archive icon archived-icon"></i>{{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 .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}} | {{if .IsGenerated}}<div class="fork-flag">{{$.i18n.Tr "repo.generated_from"}} <a href="{{.TemplateRepo.Link}}">{{SubStr .TemplateRepo.RelLink 1 -1}}</a></div>{{end}} | ||||
</div> | </div> | ||||
{{if not .IsBeingCreated}} | {{if not .IsBeingCreated}} | ||||
@@ -114,9 +114,9 @@ | |||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
</div> | </div> | ||||
{{end}} | {{end}} | ||||
{{if .Permission.CanRead $.UnitTypeIssues}} | {{if .Permission.CanRead $.UnitTypeIssues}} | ||||
@@ -152,7 +152,7 @@ | |||||
{{if .Permission.CanRead $.UnitTypeCloudBrain}} | {{if .Permission.CanRead $.UnitTypeCloudBrain}} | ||||
<a class="{{if .PageIsCloudBrain}}active{{end}} item" href="{{.RepoLink}}/debugjob?debugListType=all"> | <a class="{{if .PageIsCloudBrain}}active{{end}} item" href="{{.RepoLink}}/debugjob?debugListType=all"> | ||||
<span> | <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"}} | {{.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> | <i class="question circle icon link cloudbrain-question" data-content={{.i18n.Tr "repo.cloudbrain_helper"}} data-position="top center" data-variation="mini"></i> | ||||
</span> | </span> | ||||
@@ -256,11 +256,8 @@ | |||||
</div> | </div> | ||||
<div class="ui six wide tablet four wide computer column"> | <div class="ui six wide tablet four wide computer column"> | ||||
<div id="repo-desc"> | <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> | <p> | ||||
{{if .Repository.DescriptionHTML}} | {{if .Repository.DescriptionHTML}} | ||||
<span class="description" style="word-break:break-all">{{.Repository.DescriptionHTML}}</span> | <span class="description" style="word-break:break-all">{{.Repository.DescriptionHTML}}</span> | ||||
@@ -286,14 +283,8 @@ | |||||
<i class="grey bookmark icon"></i> | <i class="grey bookmark icon"></i> | ||||
<div id="repo-topics1" style="flex: 1;"> | <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}} | {{range .Topics}} | ||||
<a class="ui repo-topic small label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=">{{.Name}}</a> | <a class="ui repo-topic small label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=">{{.Name}}</a> | ||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
<div> | <div> | ||||
@@ -2,7 +2,7 @@ | |||||
<div class="repository new migrate" style="margin-top: 40px;"> | <div class="repository new migrate" style="margin-top: 40px;"> | ||||
<div class="ui middle very relaxed page grid"> | <div class="ui middle very relaxed page grid"> | ||||
<div class="column"> | <div class="column"> | ||||
<form class="ui form" action="{{.Link}}" method="post"> | |||||
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form"> | |||||
{{.CsrfTokenHtml}} | {{.CsrfTokenHtml}} | ||||
<h3 class="ui top attached header"> | <h3 class="ui top attached header"> | ||||
{{.i18n.Tr "new_migrate"}} | {{.i18n.Tr "new_migrate"}} | ||||
@@ -37,35 +37,7 @@ | |||||
</div> | </div> | ||||
<div class="ui divider"></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"> | <div class="inline field"> | ||||
<label>{{.i18n.Tr "repo.visibility"}}</label> | <label>{{.i18n.Tr "repo.visibility"}}</label> | ||||
<div class="ui checkbox"> | <div class="ui checkbox"> | ||||
@@ -127,7 +99,7 @@ | |||||
<div class="inline field"> | <div class="inline field"> | ||||
<label></label> | <label></label> | ||||
<button class="ui green button"> | |||||
<button class="ui green button" id="submit_reponame"> | |||||
{{.i18n.Tr "repo.migrate_repo"}} | {{.i18n.Tr "repo.migrate_repo"}} | ||||
</button> | </button> | ||||
<a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a> | <a class="ui button" href="{{AppSubUrl}}/">{{.i18n.Tr "cancel"}}</a> | ||||
@@ -2,47 +2,18 @@ | |||||
<div class="repository new fork"> | <div class="repository new fork"> | ||||
<div class="ui middle very relaxed page grid"> | <div class="ui middle very relaxed page grid"> | ||||
<div class="column"> | <div class="column"> | ||||
<form class="ui form" action="{{.Link}}" method="post"> | |||||
<form class="ui form" action="{{.Link}}" method="post" id="create_repo_form"> | |||||
{{.CsrfTokenHtml}} | {{.CsrfTokenHtml}} | ||||
<h3 class="ui top attached header"> | <h3 class="ui top attached header"> | ||||
{{.i18n.Tr "new_fork"}} | {{.i18n.Tr "new_fork"}} | ||||
</h3> | </h3> | ||||
<div class="ui attached segment"> | <div class="ui attached segment"> | ||||
{{template "base/alert" .}} | {{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"> | <div class="inline field"> | ||||
<label>{{.i18n.Tr "repo.fork_from"}}</label> | <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> | </div> | ||||
{{template "repo/repo_name" .}} | |||||
<div class="inline field"> | <div class="inline field"> | ||||
<label>{{.i18n.Tr "repo.visibility"}}</label> | <label>{{.i18n.Tr "repo.visibility"}}</label> | ||||
<div class="ui read-only checkbox"> | <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"}} | {{.i18n.Tr "repo.settings.basic_settings"}} | ||||
</h4> | </h4> | ||||
<div class="ui attached segment"> | <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}} | {{.CsrfTokenHtml}} | ||||
<input type="hidden" name="action" value="update"> | <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> | <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> | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label>{{.i18n.Tr "repo.repo_size"}}</label> | <label>{{.i18n.Tr "repo.repo_size"}}</label> | ||||
@@ -41,7 +75,7 @@ | |||||
{{end}} | {{end}} | ||||
<div class="field {{if .Err_Description}}error{{end}}"> | <div class="field {{if .Err_Description}}error{{end}}"> | ||||
<label for="description">{{$.i18n.Tr "repo.repo_desc"}}</label> | <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> | ||||
<div class="field {{if .Err_Website}}error{{end}}"> | <div class="field {{if .Err_Website}}error{{end}}"> | ||||
<label for="website">{{.i18n.Tr "repo.settings.site"}}</label> | <label for="website">{{.i18n.Tr "repo.settings.site"}}</label> | ||||
@@ -152,7 +186,7 @@ | |||||
{{$isModelMangeEnabled := .Repository.UnitEnabled $.UnitTypeModelManage }} | {{$isModelMangeEnabled := .Repository.UnitEnabled $.UnitTypeModelManage }} | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label>{{.i18n.Tr "repo.model_manager"}}</label> | <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}}> | <input class="enable-system" name="enable_model_manager" type="checkbox" {{if $isModelMangeEnabled}}checked{{end}}> | ||||
<label>{{.i18n.Tr "repo.settings.model_desc"}}</label> | <label>{{.i18n.Tr "repo.settings.model_desc"}}</label> | ||||
</div> | </div> | ||||
@@ -160,7 +194,7 @@ | |||||
{{$isCloudBrainEnabled := .Repository.UnitEnabled $.UnitTypeCloudBrain }} | {{$isCloudBrainEnabled := .Repository.UnitEnabled $.UnitTypeCloudBrain }} | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label>{{.i18n.Tr "repo.cloudbrain"}}</label> | <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}}> | <input class="enable-system" name="enable_cloud_brain" type="checkbox" {{if $isCloudBrainEnabled}}checked{{end}}> | ||||
<label>{{.i18n.Tr "repo.settings.cloudbrain_desc"}}</label> | <label>{{.i18n.Tr "repo.settings.cloudbrain_desc"}}</label> | ||||
</div> | </div> | ||||
@@ -475,7 +509,7 @@ | |||||
<div class="field"> | <div class="field"> | ||||
<label> | <label> | ||||
{{.i18n.Tr "repo.settings.transfer_form_title"}} | {{.i18n.Tr "repo.settings.transfer_form_title"}} | ||||
<span class="text red">{{.Repository.Name}}</span> | |||||
<span class="text red">{{.Repository.Alias}}</span> | |||||
</label> | </label> | ||||
</div> | </div> | ||||
<div class="required field"> | <div class="required field"> | ||||
@@ -507,7 +541,7 @@ | |||||
<div class="field"> | <div class="field"> | ||||
<label> | <label> | ||||
{{.i18n.Tr "repo.settings.transfer_form_title"}} | {{.i18n.Tr "repo.settings.transfer_form_title"}} | ||||
<span class="text red">{{.Repository.Name}}</span> | |||||
<span class="text red">{{.Repository.Alias}}</span> | |||||
</label> | </label> | ||||
</div> | </div> | ||||
<div class="required field"> | <div class="required field"> | ||||
@@ -534,7 +568,7 @@ | |||||
<div class="content"> | <div class="content"> | ||||
<div class="ui warning message text left"> | <div class="ui warning message text left"> | ||||
{{.i18n.Tr "repo.settings.delete_notices_1" | Safe}}<br> | {{.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> | {{if .Repository.NumForks}}<br> | ||||
{{.i18n.Tr "repo.settings.delete_notices_fork_1"}} | {{.i18n.Tr "repo.settings.delete_notices_fork_1"}} | ||||
{{end}} | {{end}} | ||||
@@ -545,7 +579,7 @@ | |||||
<div class="field"> | <div class="field"> | ||||
<label> | <label> | ||||
{{.i18n.Tr "repo.settings.transfer_form_title"}} | {{.i18n.Tr "repo.settings.transfer_form_title"}} | ||||
<span class="text red">{{.Repository.Name}}</span> | |||||
<span class="text red">{{.Repository.Alias}}</span> | |||||
</label> | </label> | ||||
</div> | </div> | ||||
<div class="required field"> | <div class="required field"> | ||||
@@ -569,7 +603,7 @@ | |||||
<div class="content"> | <div class="content"> | ||||
<div class="ui warning message text left"> | <div class="ui warning message text left"> | ||||
{{.i18n.Tr "repo.settings.delete_notices_1" | Safe}}<br> | {{.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> | </div> | ||||
<form class="ui form" action="{{.Link}}" method="post"> | <form class="ui form" action="{{.Link}}" method="post"> | ||||
{{.CsrfTokenHtml}} | {{.CsrfTokenHtml}} | ||||
@@ -577,7 +611,7 @@ | |||||
<div class="field"> | <div class="field"> | ||||
<label> | <label> | ||||
{{.i18n.Tr "repo.settings.transfer_form_title"}} | {{.i18n.Tr "repo.settings.transfer_form_title"}} | ||||
<span class="text red">{{.Repository.Name}}</span> | |||||
<span class="text red">{{.Repository.Alias}}</span> | |||||
</label> | </label> | ||||
</div> | </div> | ||||
<div class="required field"> | <div class="required field"> | ||||
@@ -625,4 +659,4 @@ | |||||
{{end}} | {{end}} | ||||
{{end}} | {{end}} | ||||
{{template "base/footer" .}} | |||||
{{template "base/footer" .}} |
@@ -13,63 +13,63 @@ | |||||
{{.ShortActUserName}} | {{.ShortActUserName}} | ||||
{{end}} | {{end}} | ||||
{{if eq .GetOpType 1}} | {{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}} | {{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}} | {{else if eq .GetOpType 5}} | ||||
{{ $branchLink := .GetBranch | EscapePound | Escape}} | {{ $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}} | {{else if eq .GetOpType 6}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{else if eq .GetOpType 7}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{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}} | {{else if eq .GetOpType 9}} | ||||
{{ $branchLink := .GetBranch | EscapePound | Escape}} | {{ $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}} | {{else if eq .GetOpType 10}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{else if eq .GetOpType 11}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{else if eq .GetOpType 12}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{else if eq .GetOpType 13}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{else if eq .GetOpType 14}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{else if eq .GetOpType 15}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{else if eq .GetOpType 16}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{else if eq .GetOpType 17}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{else if eq .GetOpType 18}} | ||||
{{ $branchLink := .GetBranch | EscapePound}} | {{ $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}} | {{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}} | {{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}} | {{else if eq .GetOpType 21}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{else if eq .GetOpType 22}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $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}} | {{else if eq .GetOpType 23}} | ||||
{{ $index := index .GetIssueInfos 0}} | {{ $index := index .GetIssueInfos 0}} | ||||
{{$.i18n.Tr "action.comment_pull" .GetRepoLink $index .ShortRepoPath | Str2html}} | |||||
{{$.i18n.Tr "action.comment_pull" .GetRepoLink $index .ShortRepoFullDisplayName | Str2html}} | |||||
{{end}} | {{end}} | ||||
</p> | </p> | ||||
{{if or (eq .GetOpType 5) (eq .GetOpType 18)}} | {{if or (eq .GetOpType 5) (eq .GetOpType 18)}} | ||||
@@ -107,7 +107,7 @@ | |||||
{{ $timeStr:= TimeSinceUnix .CreatedUnix $.Lang }} | {{ $timeStr:= TimeSinceUnix .CreatedUnix $.Lang }} | ||||
{{if .Repo}} | {{if .Repo}} | ||||
<li class="item"> | <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> | <a class="title" href="{{.HTMLURL}}">{{RenderEmoji .Title}}</a> | ||||
{{if .IsPull}} | {{if .IsPull}} | ||||
@@ -208,3 +208,6 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{{template "base/footer" .}} | {{template "base/footer" .}} | ||||
<script> | |||||
console.log({{.Issues}}) | |||||
</script> |
@@ -65,7 +65,7 @@ | |||||
<div class="milestone list"> | <div class="milestone list"> | ||||
{{range .Milestones}} | {{range .Milestones}} | ||||
<li class="item"> | <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> | {{svg "octicon-milestone" 16}} <a href="{{.Repo.Link }}/milestone/{{.ID}}">{{.Name}}</a> | ||||
<div class="ui right green progress" data-percent="{{.Completeness}}"> | <div class="ui right green progress" data-percent="{{.Completeness}}"> | ||||
<div class="bar" {{if not .Completeness}}style="background-color: transparent"{{end}}> | <div class="bar" {{if not .Completeness}}style="background-color: transparent"{{end}}> | ||||
@@ -117,3 +117,6 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{{template "base/footer" .}} | {{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)"> | <li v-for="repo in repos" :class="{'private': repo.private}" v-show="showRepo(repo)"> | ||||
<a :href="suburl + '/' + repo.full_name"> | <a :href="suburl + '/' + repo.full_name"> | ||||
<svg :class="'svg ' + repoClass(repo)" width="16" height="16" aria-hidden="true"><use :xlink:href="'#' + repoClass(repo)" /></svg> | <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> | <i v-if="repo.archived" class="archive icon archived-icon"></i> | ||||
<span class="ui right text light grey"> | <span class="ui right text light grey"> | ||||
${repo.stars_count} <span class="rear">{{svg "octicon-star" 16}}</span> | ${repo.stars_count} <span class="rear">{{svg "octicon-star" 16}}</span> | ||||
@@ -51,7 +51,7 @@ | |||||
<li>{{svg "octicon-clock" 16}} {{.i18n.Tr "user.join_on"}} {{.Owner.CreatedUnix.FormatShort}}</li> | <li>{{svg "octicon-clock" 16}} {{.i18n.Tr "user.join_on"}} {{.Owner.CreatedUnix.FormatShort}}</li> | ||||
{{if and .Orgs .HasOrgsVisible}} | {{if and .Orgs .HasOrgsVisible}} | ||||
<li style="border-bottom: none;padding-bottom: 0;"><div style="border-bottom: 1px solid #eaeaea;padding-top: 5px;padding-bottom:5px"> <b> 组织</b></div></li> | |||||
<li style="border-bottom: none;padding-bottom: 0;"><div style="border-bottom: 1px solid #eaeaea;padding-top: 5px;padding-bottom:5px"> <b>{{.i18n.Tr "organization"}} </b></div></li> | |||||
<li style="padding-bottom: 0px;"> | <li style="padding-bottom: 0px;"> | ||||
<!-- <ul class="user-orgs"> | <!-- <ul class="user-orgs"> | ||||
{{range .Orgs}} | {{range .Orgs}} | ||||
@@ -79,11 +79,11 @@ | |||||
<li class="infor" style="width: 25%;display: table-cell"> | <li class="infor" style="width: 25%;display: table-cell"> | ||||
<img style="width: 16px;height:16px;border: none;" src="/img/member.svg" > | |||||
<img style="width: 16px;height:16px;border: none;margin-top: -2px" src="/img/member.svg" > | |||||
<span style="color: rgba(0,0,0,.4);vertical-align: middle;">{{.NumMembers}}</span> | <span style="color: rgba(0,0,0,.4);vertical-align: middle;">{{.NumMembers}}</span> | ||||
</li> | </li> | ||||
<li class="infor" style="width: 25%;display: table-cell"> | |||||
<img style="width: 16px;height: 16px;" src="/img/pro_num.svg" > | |||||
<li class="infor" style="width: 25%;display: table-cell;"> | |||||
<img style="width: 16px;height: 16px;margin-top: -2px" src="/img/pro_num.svg" > | |||||
<span style="color: rgba(0,0,0,.4);vertical-align: middle;">{{.NumRepos}}</span> | <span style="color: rgba(0,0,0,.4);vertical-align: middle;">{{.NumRepos}}</span> | ||||
</li> | </li> | ||||
{{end}} | {{end}} | ||||
@@ -21,7 +21,7 @@ | |||||
{{else}} | {{else}} | ||||
<span class="iconFloat">{{svg "octicon-repo" 16}}</span> | <span class="iconFloat">{{svg "octicon-repo" 16}}</span> | ||||
{{end}} | {{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> | <span>{{SizeFmt .Size}}</span> | ||||
{{if .IsFork}} | {{if .IsFork}} | ||||
{{$.i18n.Tr "repo.forked_from"}} | {{$.i18n.Tr "repo.forked_from"}} | ||||
@@ -52,6 +52,7 @@ export default { | |||||
desc: '', | desc: '', | ||||
index_web: '', | index_web: '', | ||||
repo_name_name: '', | repo_name_name: '', | ||||
alias:'' | |||||
}, | }, | ||||
// rule1:[{min:3,max:5,message:'1',trigger:"blur"}], | // rule1:[{min:3,max:5,message:'1',trigger:"blur"}], | ||||
rule: { | rule: { | ||||
@@ -76,6 +77,7 @@ export default { | |||||
getRepoName() { | getRepoName() { | ||||
const el = this.url.split('/')[2]; | const el = this.url.split('/')[2]; | ||||
this.info.repo_name = el; | this.info.repo_name = el; | ||||
this.info.alias = $('input#edit-alias').val() | |||||
}, | }, | ||||
initForm(diaolog) { | initForm(diaolog) { | ||||
if (diaolog === false) { | if (diaolog === false) { | ||||
@@ -95,6 +97,7 @@ export default { | |||||
data: this.qs.stringify({ | data: this.qs.stringify({ | ||||
_csrf: csrf, | _csrf: csrf, | ||||
action: 'update', | action: 'update', | ||||
alias:this.info.alias, | |||||
repo_name: this.info.repo_name, | repo_name: this.info.repo_name, | ||||
description: this.info.desc, | description: this.info.desc, | ||||
website: this.info.index_web | website: this.info.index_web | ||||
@@ -2411,8 +2411,8 @@ function searchRepositories() { | |||||
const items = []; | const items = []; | ||||
$.each(response.data, (_i, item) => { | $.each(response.data, (_i, item) => { | ||||
items.push({ | 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 | // Parse the response from the api to work with our dropdown | ||||
$.each(response.data, (_r, repo) => { | $.each(response.data, (_r, repo) => { | ||||
filteredResponse.results.push({ | filteredResponse.results.push({ | ||||
name: htmlEncode(repo.full_name), | |||||
name: htmlEncode(repo.full_display_name), | |||||
value: repo.id | value: repo.id | ||||
}); | }); | ||||
}); | }); | ||||
@@ -2966,10 +2966,21 @@ $(document).ready(async () => { | |||||
const $cloneAddr = $('#clone_addr'); | const $cloneAddr = $('#clone_addr'); | ||||
$cloneAddr.on('change', () => { | $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) { | if ($cloneAddr.val().length > 0 && $repoName.val().length === 0) { | ||||
// Only modify if repo_name input is blank | // Only modify if repo_name input is blank | ||||
const repoValue = $cloneAddr.val().match(/^(.*\/)?((.+?)(\.git)?)$/)[3] | |||||
$repoName.val($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')) | $(".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 { | .help { | ||||
color: #999999; | color: #999999; | ||||
padding-top: .6em; | padding-top: .6em; | ||||
padding-bottom: .6em; | |||||
display: inline-block; | display: inline-block; | ||||
} | } | ||||
} | } | ||||