@@ -11,30 +11,30 @@ import ( | |||||
) | ) | ||||
type AiModelManage struct { | type AiModelManage struct { | ||||
ID string `xorm:"pk"` | |||||
Name string `xorm:"NOT NULL"` | |||||
Version string `xorm:"NOT NULL"` | |||||
VersionCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
New int `xorm:"NOT NULL"` | |||||
Type int `xorm:"NOT NULL"` | |||||
Size int64 `xorm:"NOT NULL"` | |||||
Description string `xorm:"varchar(2000)"` | |||||
Label string `xorm:"varchar(1000)"` | |||||
Path string `xorm:"varchar(400) NOT NULL"` | |||||
DownloadCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
Engine int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
Status int `xorm:"NOT NULL DEFAULT 0"` | |||||
Accuracy string `xorm:"varchar(1000)"` | |||||
AttachmentId string `xorm:"NULL"` | |||||
RepoId int64 `xorm:"NULL"` | |||||
CodeBranch string `xorm:"varchar(400) NULL"` | |||||
CodeCommitID string `xorm:"NULL"` | |||||
UserId int64 `xorm:"NOT NULL"` | |||||
UserName string `xorm:"NULL"` | |||||
ID string `xorm:"pk"` | |||||
Name string `xorm:"INDEX NOT NULL"` | |||||
Version string `xorm:"NOT NULL"` | |||||
VersionCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
New int `xorm:"NOT NULL"` | |||||
Type int `xorm:"NOT NULL"` | |||||
Size int64 `xorm:"NOT NULL"` | |||||
Description string `xorm:"varchar(2000)"` | |||||
Label string `xorm:"varchar(1000)"` | |||||
Path string `xorm:"varchar(400) NOT NULL"` | |||||
DownloadCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
Engine int64 `xorm:"NOT NULL DEFAULT 0"` | |||||
Status int `xorm:"NOT NULL DEFAULT 0"` | |||||
Accuracy string `xorm:"varchar(1000)"` | |||||
AttachmentId string `xorm:"NULL"` | |||||
RepoId int64 `xorm:"INDEX NULL"` | |||||
CodeBranch string `xorm:"varchar(400) NULL"` | |||||
CodeCommitID string `xorm:"NULL"` | |||||
UserId int64 `xorm:"NOT NULL"` | |||||
UserName string | |||||
UserRelAvatarLink string `xorm:"NULL"` | UserRelAvatarLink string `xorm:"NULL"` | ||||
TrainTaskInfo string `xorm:"text NULL"` | TrainTaskInfo string `xorm:"text NULL"` | ||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | CreatedUnix timeutil.TimeStamp `xorm:"created"` | ||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||||
IsCanOper bool | IsCanOper bool | ||||
} | } | ||||
@@ -197,7 +197,6 @@ func QueryModel(opts *AiModelQueryOptions) ([]*AiModelManage, int64, error) { | |||||
Find(&aiModelManages); err != nil { | Find(&aiModelManages); err != nil { | ||||
return nil, 0, fmt.Errorf("Find: %v", err) | return nil, 0, fmt.Errorf("Find: %v", err) | ||||
} | } | ||||
sess.Close() | |||||
return aiModelManages, count, nil | return aiModelManages, count, nil | ||||
} | } |
@@ -1110,7 +1110,8 @@ func UpdateJob(job *Cloudbrain) error { | |||||
func updateJob(e Engine, job *Cloudbrain) error { | func updateJob(e Engine, job *Cloudbrain) error { | ||||
var sess *xorm.Session | var sess *xorm.Session | ||||
sess = e.Where("job_id = ?", job.JobID) | sess = e.Where("job_id = ?", job.JobID) | ||||
_, err := sess.Cols("status", "container_id", "container_ip").Update(job) | |||||
//_, err := sess.Cols("status", "container_id", "container_ip").Update(job) | |||||
_, err := sess.Update(job) | |||||
return err | return err | ||||
} | } | ||||
@@ -93,6 +93,7 @@ type SearchDatasetOptions struct { | |||||
IncludePublic bool | IncludePublic bool | ||||
ListOptions | ListOptions | ||||
SearchOrderBy | SearchOrderBy | ||||
IsOwner bool | |||||
} | } | ||||
func CreateDataset(dataset *Dataset) (err error) { | func CreateDataset(dataset *Dataset) (err error) { | ||||
@@ -150,6 +151,9 @@ func SearchDatasetCondition(opts *SearchDatasetOptions) builder.Cond { | |||||
} | } | ||||
} else if opts.OwnerID > 0 { | } else if opts.OwnerID > 0 { | ||||
cond = cond.And(builder.Eq{"repository.owner_id": opts.OwnerID}) | cond = cond.And(builder.Eq{"repository.owner_id": opts.OwnerID}) | ||||
if !opts.IsOwner { | |||||
cond = cond.And(builder.Eq{"dataset.status": DatasetStatusPublic}) | |||||
} | |||||
} | } | ||||
return cond | return cond | ||||
@@ -11,6 +11,7 @@ import ( | |||||
"errors" | "errors" | ||||
"fmt" | "fmt" | ||||
"html/template" | "html/template" | ||||
"xorm.io/xorm" | |||||
"code.gitea.io/gitea/modules/blockchain" | "code.gitea.io/gitea/modules/blockchain" | ||||
@@ -1632,6 +1633,9 @@ func DeleteRepository(doer *User, uid, repoID int64) error { | |||||
releaseAttachments = append(releaseAttachments, attachments[i].RelativePath()) | releaseAttachments = append(releaseAttachments, attachments[i].RelativePath()) | ||||
} | } | ||||
// Delete dataset attachment record and remove related files | |||||
deleteDatasetAttachmentByRepoId(sess, repoID) | |||||
if err = deleteBeans(sess, | if err = deleteBeans(sess, | ||||
&Access{RepoID: repo.ID}, | &Access{RepoID: repo.ID}, | ||||
&Action{RepoID: repo.ID}, | &Action{RepoID: repo.ID}, | ||||
@@ -1817,6 +1821,20 @@ func DeleteRepository(doer *User, uid, repoID int64) error { | |||||
return nil | return nil | ||||
} | } | ||||
func deleteDatasetAttachmentByRepoId(sess *xorm.Session, repoId int64) error { | |||||
attachments := make([]*Attachment, 0) | |||||
if err := sess.Join("INNER", "dataset", "dataset.id = attachment.dataset_id"). | |||||
Where("dataset.repo_id = ?", repoId). | |||||
Find(&attachments); err != nil { | |||||
return err | |||||
} | |||||
if len(attachments) == 0 { | |||||
return nil | |||||
} | |||||
_, err := DeleteAttachments(attachments, true) | |||||
return err | |||||
} | |||||
// GetRepositoryByOwnerAndName returns the repository by given ownername and reponame. | // GetRepositoryByOwnerAndName returns the repository by given ownername and reponame. | ||||
func GetRepositoryByOwnerAndName(ownerName, repoName string) (*Repository, error) { | func GetRepositoryByOwnerAndName(ownerName, repoName string) (*Repository, error) { | ||||
return getRepositoryByOwnerAndName(x, ownerName, repoName) | return getRepositoryByOwnerAndName(x, ownerName, repoName) | ||||
@@ -929,7 +929,7 @@ var ( | |||||
"template", | "template", | ||||
"user", | "user", | ||||
"vendor", | "vendor", | ||||
"dashbord", | |||||
"dashboard", | |||||
"operation", | "operation", | ||||
"blockchain", | "blockchain", | ||||
"avatar", | "avatar", | ||||
@@ -2,6 +2,7 @@ package cloudbrain | |||||
import ( | import ( | ||||
"errors" | "errors" | ||||
"strconv" | |||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
@@ -30,29 +31,30 @@ var ( | |||||
) | ) | ||||
func isAdminOrOwnerOrJobCreater(ctx *context.Context, job *models.Cloudbrain, err error) bool { | func isAdminOrOwnerOrJobCreater(ctx *context.Context, job *models.Cloudbrain, err error) bool { | ||||
if !ctx.IsSigned { | |||||
return false | |||||
} | |||||
log.Info("is repo owner:" + strconv.FormatBool(ctx.IsUserRepoOwner())) | |||||
log.Info("is user admin:" + strconv.FormatBool(ctx.IsUserSiteAdmin())) | |||||
if err != nil { | if err != nil { | ||||
return ctx.IsUserRepoOwner() || ctx.IsUserSiteAdmin() | return ctx.IsUserRepoOwner() || ctx.IsUserSiteAdmin() | ||||
} else { | } else { | ||||
log.Info("is job creator:" + strconv.FormatBool(ctx.User.ID == job.UserID)) | |||||
return ctx.IsUserRepoOwner() || ctx.IsUserSiteAdmin() || ctx.User.ID == job.UserID | return ctx.IsUserRepoOwner() || ctx.IsUserSiteAdmin() || ctx.User.ID == job.UserID | ||||
} | } | ||||
} | } | ||||
func CanDeleteDebugJob(ctx *context.Context, job *models.Cloudbrain) bool { | |||||
if job.Status != string(models.JobStopped) && job.Status != string(models.JobFailed) && job.Status != string(models.ModelArtsStartFailed) && job.Status != string(models.ModelArtsCreateFailed) { | |||||
return false | |||||
} | |||||
return isAdminOrOwnerOrJobCreater(ctx, job, nil) | |||||
} | |||||
func CanDeleteTrainJob(ctx *context.Context, job *models.Cloudbrain) bool { | |||||
func CanDeleteJob(ctx *context.Context, job *models.Cloudbrain) bool { | |||||
return isAdminOrOwnerOrJobCreater(ctx, job, nil) | return isAdminOrOwnerOrJobCreater(ctx, job, nil) | ||||
} | } | ||||
func CanCreateOrDebugJob(ctx *context.Context) bool { | func CanCreateOrDebugJob(ctx *context.Context) bool { | ||||
if !ctx.IsSigned { | |||||
return false | |||||
} | |||||
return ctx.Repo.CanWrite(models.UnitTypeCloudBrain) | return ctx.Repo.CanWrite(models.UnitTypeCloudBrain) | ||||
} | } | ||||
@@ -62,7 +64,9 @@ func CanModifyJob(ctx *context.Context, job *models.Cloudbrain) bool { | |||||
} | } | ||||
func isAdminOrJobCreater(ctx *context.Context, job *models.Cloudbrain, err error) bool { | func isAdminOrJobCreater(ctx *context.Context, job *models.Cloudbrain, err error) bool { | ||||
if !ctx.IsSigned { | |||||
return false | |||||
} | |||||
if err != nil { | if err != nil { | ||||
return ctx.IsUserSiteAdmin() | return ctx.IsUserSiteAdmin() | ||||
} else { | } else { | ||||
@@ -113,7 +117,7 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, | |||||
log.Error("no such resourceSpecId(%d)", resourceSpecId, ctx.Data["MsgID"]) | log.Error("no such resourceSpecId(%d)", resourceSpecId, ctx.Data["MsgID"]) | ||||
return errors.New("no such resourceSpec") | return errors.New("no such resourceSpec") | ||||
} | } | ||||
jobResult, err := CreateJob(jobName, models.CreateJobParams{ | jobResult, err := CreateJob(jobName, models.CreateJobParams{ | ||||
JobName: jobName, | JobName: jobName, | ||||
RetryCount: 1, | RetryCount: 1, | ||||
@@ -198,8 +202,8 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, | |||||
JobName: jobName, | JobName: jobName, | ||||
SubTaskName: SubTaskName, | SubTaskName: SubTaskName, | ||||
JobType: jobType, | JobType: jobType, | ||||
Type: models.TypeCloudBrainOne, | |||||
Uuid: uuid, | |||||
Type: models.TypeCloudBrainOne, | |||||
Uuid: uuid, | |||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
@@ -134,7 +134,7 @@ func registerHandleBlockChainUnSuccessRepos() { | |||||
RegisterTaskFatal("handle_blockchain_unsuccess_repos", &BaseConfig{ | RegisterTaskFatal("handle_blockchain_unsuccess_repos", &BaseConfig{ | ||||
Enabled: true, | Enabled: true, | ||||
RunAtStart: true, | RunAtStart: true, | ||||
Schedule: "@every 1m", | |||||
Schedule: "@every 10m", | |||||
}, func(ctx context.Context, _ *models.User, _ Config) error { | }, func(ctx context.Context, _ *models.User, _ Config) error { | ||||
repo.HandleBlockChainUnSuccessRepos() | repo.HandleBlockChainUnSuccessRepos() | ||||
return nil | return nil | ||||
@@ -145,7 +145,7 @@ func registerHandleBlockChainMergedPulls() { | |||||
RegisterTaskFatal("handle_blockchain_merged_pull", &BaseConfig{ | RegisterTaskFatal("handle_blockchain_merged_pull", &BaseConfig{ | ||||
Enabled: true, | Enabled: true, | ||||
RunAtStart: true, | RunAtStart: true, | ||||
Schedule: "@every 1m", | |||||
Schedule: "@every 10m", | |||||
}, func(ctx context.Context, _ *models.User, _ Config) error { | }, func(ctx context.Context, _ *models.User, _ Config) error { | ||||
repo.HandleBlockChainMergedPulls() | repo.HandleBlockChainMergedPulls() | ||||
return nil | return nil | ||||
@@ -156,7 +156,7 @@ func registerHandleBlockChainUnSuccessCommits() { | |||||
RegisterTaskFatal("handle_blockchain_unsuccess_commits", &BaseConfig{ | RegisterTaskFatal("handle_blockchain_unsuccess_commits", &BaseConfig{ | ||||
Enabled: true, | Enabled: true, | ||||
RunAtStart: true, | RunAtStart: true, | ||||
Schedule: "@every 3m", | |||||
Schedule: "@every 10m", | |||||
}, func(ctx context.Context, _ *models.User, _ Config) error { | }, func(ctx context.Context, _ *models.User, _ Config) error { | ||||
repo.HandleBlockChainUnSuccessCommits() | repo.HandleBlockChainUnSuccessCommits() | ||||
return nil | return nil | ||||
@@ -433,6 +433,9 @@ var ( | |||||
AuthUser string | AuthUser string | ||||
AuthPassword string | AuthPassword string | ||||
//home page | |||||
RecommentRepoAddr string | |||||
//labelsystem config | //labelsystem config | ||||
LabelTaskName string | LabelTaskName string | ||||
LabelDatasetDeleteQueue string | LabelDatasetDeleteQueue string | ||||
@@ -448,21 +451,25 @@ var ( | |||||
GpuTypes string | GpuTypes string | ||||
DebugServerHost string | DebugServerHost string | ||||
ResourceSpecs string | ResourceSpecs string | ||||
MaxDuration int64 | |||||
//benchmark config | //benchmark config | ||||
IsBenchmarkEnabled bool | IsBenchmarkEnabled bool | ||||
BenchmarkCode string | |||||
BenchmarkOwner string | |||||
BenchmarkName string | |||||
BenchmarkServerHost string | BenchmarkServerHost string | ||||
BenchmarkCategory string | BenchmarkCategory string | ||||
//snn4imagenet config | //snn4imagenet config | ||||
IsSnn4imagenetEnabled bool | IsSnn4imagenetEnabled bool | ||||
Snn4imagenetCode string | |||||
Snn4imagenetOwner string | |||||
Snn4imagenetName string | |||||
Snn4imagenetServerHost string | Snn4imagenetServerHost string | ||||
//snn4imagenet config | //snn4imagenet config | ||||
IsBrainScoreEnabled bool | IsBrainScoreEnabled bool | ||||
BrainScoreCode string | |||||
BrainScoreOwner string | |||||
BrainScoreName string | |||||
BrainScoreServerHost string | BrainScoreServerHost string | ||||
//blockchain config | //blockchain config | ||||
@@ -1225,6 +1232,9 @@ func NewContext() { | |||||
LabelDatasetDeleteQueue = sec.Key("LabelDatasetDeleteQueue").MustString("LabelDatasetDeleteQueue") | LabelDatasetDeleteQueue = sec.Key("LabelDatasetDeleteQueue").MustString("LabelDatasetDeleteQueue") | ||||
DecompressOBSTaskName = sec.Key("DecompressOBSTaskName").MustString("LabelDecompressOBSQueue") | DecompressOBSTaskName = sec.Key("DecompressOBSTaskName").MustString("LabelDecompressOBSQueue") | ||||
sec = Cfg.Section("homepage") | |||||
RecommentRepoAddr = sec.Key("Address").MustString("https://git.openi.org.cn/OpenIOSSG/promote/raw/branch/master/") | |||||
sec = Cfg.Section("cloudbrain") | sec = Cfg.Section("cloudbrain") | ||||
CBAuthUser = sec.Key("USER").MustString("") | CBAuthUser = sec.Key("USER").MustString("") | ||||
CBAuthPassword = sec.Key("PWD").MustString("") | CBAuthPassword = sec.Key("PWD").MustString("") | ||||
@@ -1235,21 +1245,25 @@ func NewContext() { | |||||
JobType = sec.Key("GPU_TYPE_DEFAULT").MustString("openidebug") | JobType = sec.Key("GPU_TYPE_DEFAULT").MustString("openidebug") | ||||
GpuTypes = sec.Key("GPU_TYPES").MustString("") | GpuTypes = sec.Key("GPU_TYPES").MustString("") | ||||
ResourceSpecs = sec.Key("RESOURCE_SPECS").MustString("") | ResourceSpecs = sec.Key("RESOURCE_SPECS").MustString("") | ||||
MaxDuration = sec.Key("MAX_DURATION").MustInt64(14400) | |||||
sec = Cfg.Section("benchmark") | sec = Cfg.Section("benchmark") | ||||
IsBenchmarkEnabled = sec.Key("ENABLED").MustBool(false) | IsBenchmarkEnabled = sec.Key("ENABLED").MustBool(false) | ||||
BenchmarkCode = sec.Key("BENCHMARKCODE").MustString("") | |||||
BenchmarkOwner = sec.Key("OWNER").MustString("") | |||||
BenchmarkName = sec.Key("NAME").MustString("") | |||||
BenchmarkServerHost = sec.Key("HOST").MustString("") | BenchmarkServerHost = sec.Key("HOST").MustString("") | ||||
BenchmarkCategory = sec.Key("CATEGORY").MustString("") | BenchmarkCategory = sec.Key("CATEGORY").MustString("") | ||||
sec = Cfg.Section("snn4imagenet") | sec = Cfg.Section("snn4imagenet") | ||||
IsSnn4imagenetEnabled = sec.Key("ENABLED").MustBool(false) | IsSnn4imagenetEnabled = sec.Key("ENABLED").MustBool(false) | ||||
Snn4imagenetCode = sec.Key("SNN4IMAGENETCODE").MustString("") | |||||
Snn4imagenetOwner = sec.Key("OWNER").MustString("") | |||||
Snn4imagenetName = sec.Key("NAME").MustString("") | |||||
Snn4imagenetServerHost = sec.Key("HOST").MustString("") | Snn4imagenetServerHost = sec.Key("HOST").MustString("") | ||||
sec = Cfg.Section("brainscore") | sec = Cfg.Section("brainscore") | ||||
IsBrainScoreEnabled = sec.Key("ENABLED").MustBool(false) | IsBrainScoreEnabled = sec.Key("ENABLED").MustBool(false) | ||||
BrainScoreCode = sec.Key("BRAINSCORECODE").MustString("") | |||||
BrainScoreOwner = sec.Key("OWNER").MustString("") | |||||
BrainScoreName = sec.Key("NAME").MustString("") | |||||
BrainScoreServerHost = sec.Key("HOST").MustString("") | BrainScoreServerHost = sec.Key("HOST").MustString("") | ||||
sec = Cfg.Section("blockchain") | sec = Cfg.Section("blockchain") | ||||
@@ -778,6 +778,8 @@ datasets = Datasets | |||||
datasets.desc = Enable Dataset | datasets.desc = Enable Dataset | ||||
cloudbrain_helper=Use GPU/NPU resources to open notebooks, model training tasks, etc. | cloudbrain_helper=Use GPU/NPU resources to open notebooks, model training tasks, etc. | ||||
model_manager = Model | |||||
debug=Debug | debug=Debug | ||||
stop=Stop | stop=Stop | ||||
delete=Delete | delete=Delete | ||||
@@ -782,7 +782,7 @@ datasets=数据集 | |||||
datasets.desc=数据集功能 | datasets.desc=数据集功能 | ||||
cloudbrain_helper=使用GPU/NPU资源,开启Notebook、模型训练任务等 | cloudbrain_helper=使用GPU/NPU资源,开启Notebook、模型训练任务等 | ||||
model_manager = 模型管理 | |||||
model_manager = 模型 | |||||
model_noright=无权限操作 | model_noright=无权限操作 | ||||
debug=调试 | debug=调试 | ||||
@@ -857,7 +857,7 @@ modelarts.train_job.description=任务描述 | |||||
modelarts.train_job.parameter_setting=参数设置 | modelarts.train_job.parameter_setting=参数设置 | ||||
modelarts.train_job.parameter_setting_info=参数信息 | modelarts.train_job.parameter_setting_info=参数信息 | ||||
modelarts.train_job.fast_parameter_setting=一键式参数配置 | modelarts.train_job.fast_parameter_setting=一键式参数配置 | ||||
modelarts.train_job.fast_parameter_setting_config=如您已保存过参数配置,可单击 | |||||
modelarts.train_job.fast_parameter_setting_config=如您已保存过参数配置,可单击 | |||||
modelarts.train_job.fast_parameter_setting_config_link=这里 | modelarts.train_job.fast_parameter_setting_config_link=这里 | ||||
modelarts.train_job.frames=常用框架 | modelarts.train_job.frames=常用框架 | ||||
modelarts.train_job.algorithm_origin=算法来源 | modelarts.train_job.algorithm_origin=算法来源 | ||||
@@ -1987,7 +1987,7 @@ team_unit_desc=允许访问项目单元 | |||||
team_unit_disabled=(已禁用) | team_unit_disabled=(已禁用) | ||||
form.name_reserved=组织名称 '%s' 是被保留的。 | form.name_reserved=组织名称 '%s' 是被保留的。 | ||||
form.name_pattern_not_allowed=项目名称中不允许使用 "%s"。 | |||||
form.name_pattern_not_allowed=组织名称中不允许使用 "%s"。 | |||||
form.create_org_not_allowed=此账号禁止创建组织 | form.create_org_not_allowed=此账号禁止创建组织 | ||||
settings=组织设置 | settings=组织设置 | ||||
@@ -0,0 +1 @@ | |||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="120" height="120"><path fill="none" d="M0 0h24v24H0z"/><path d="M20 22h-2v-2a3 3 0 0 0-3-3H9a3 3 0 0 0-3 3v2H4v-2a5 5 0 0 1 5-5h6a5 5 0 0 1 5 5v2zm-8-9a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8z" fill="rgba(0,0,0,0.4)"/></svg> |
@@ -0,0 +1 @@ | |||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="120" height="120"><path fill="none" d="M0 0h24v24H0z"/><path d="M20 3l2 4v13a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V7.004L4 3h16zm0 6H4v10h16V9zm-8 1l4 4h-3v4h-2v-4H8l4-4zm6.764-5H5.236l-.999 2h15.527l-1-2z" fill="rgba(0,0,0,0.4)"/></svg> |
@@ -7,6 +7,8 @@ package routers | |||||
import ( | import ( | ||||
"bytes" | "bytes" | ||||
"fmt" | |||||
"io/ioutil" | |||||
"net/http" | "net/http" | ||||
"strings" | "strings" | ||||
@@ -511,3 +513,43 @@ func NotFound(ctx *context.Context) { | |||||
ctx.Data["Title"] = "Page Not Found" | ctx.Data["Title"] = "Page Not Found" | ||||
ctx.NotFound("home.NotFound", nil) | ctx.NotFound("home.NotFound", nil) | ||||
} | } | ||||
func RecommendOrgFromPromote(ctx *context.Context) { | |||||
url := setting.RecommentRepoAddr + "organizations" | |||||
recommendFromPromote(ctx, url) | |||||
} | |||||
func recommendFromPromote(ctx *context.Context, url string) { | |||||
resp, err := http.Get(url) | |||||
if err != nil { | |||||
log.Info("Get organizations url error=" + err.Error()) | |||||
ctx.ServerError("QueryTrainJobList:", err) | |||||
return | |||||
} | |||||
bytes, err := ioutil.ReadAll(resp.Body) | |||||
resp.Body.Close() | |||||
if err != nil { | |||||
log.Info("Get organizations url error=" + err.Error()) | |||||
ctx.ServerError("QueryTrainJobList:", err) | |||||
return | |||||
} | |||||
allLineStr := string(bytes) | |||||
lines := strings.Split(allLineStr, "\n") | |||||
result := make([]string, len(lines)) | |||||
for i, line := range lines { | |||||
tmpIndex := strings.Index(line, ".") | |||||
log.Info("i=" + fmt.Sprint(i) + " line=" + line + " tmpIndex=" + fmt.Sprint(tmpIndex)) | |||||
if tmpIndex == -1 { | |||||
result[i] = strings.Trim(line, " ") | |||||
} else { | |||||
result[i] = strings.Trim(line[tmpIndex+1:], " ") | |||||
} | |||||
} | |||||
ctx.JSON(http.StatusOK, result) | |||||
} | |||||
func RecommendRepoFromPromote(ctx *context.Context) { | |||||
url := setting.RecommentRepoAddr + "projects" | |||||
recommendFromPromote(ctx, url) | |||||
} |
@@ -28,7 +28,6 @@ const ( | |||||
func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, ctx *context.Context) error { | func saveModelByParameters(jobId string, versionName string, name string, version string, label string, description string, ctx *context.Context) error { | ||||
aiTask, err := models.GetCloudbrainByJobIDAndVersionName(jobId, versionName) | aiTask, err := models.GetCloudbrainByJobIDAndVersionName(jobId, versionName) | ||||
//aiTask, err := models.GetCloudbrainByJobID(jobId) | |||||
if err != nil { | if err != nil { | ||||
log.Info("query task error." + err.Error()) | log.Info("query task error." + err.Error()) | ||||
return err | return err | ||||
@@ -56,7 +55,7 @@ func saveModelByParameters(jobId string, versionName string, name string, versio | |||||
cloudType = aiTask.Type | cloudType = aiTask.Type | ||||
//download model zip //train type | //download model zip //train type | ||||
if cloudType == models.TypeCloudBrainTwo { | if cloudType == models.TypeCloudBrainTwo { | ||||
modelPath, modelSize, err = downloadModelFromCloudBrainTwo(id, aiTask.JobName, "") | |||||
modelPath, modelSize, err = downloadModelFromCloudBrainTwo(id, aiTask.JobName, "", aiTask.TrainUrl) | |||||
if err != nil { | if err != nil { | ||||
log.Info("download model from CloudBrainTwo faild." + err.Error()) | log.Info("download model from CloudBrainTwo faild." + err.Error()) | ||||
return err | return err | ||||
@@ -71,7 +70,6 @@ func saveModelByParameters(jobId string, versionName string, name string, versio | |||||
log.Info("accuracyJson=" + string(accuracyJson)) | log.Info("accuracyJson=" + string(accuracyJson)) | ||||
aiTaskJson, _ := json.Marshal(aiTask) | aiTaskJson, _ := json.Marshal(aiTask) | ||||
//taskConfigInfo,err := models.GetCloudbrainByJobIDAndVersionName(jobId,aiTask.VersionName) | |||||
model := &models.AiModelManage{ | model := &models.AiModelManage{ | ||||
ID: id, | ID: id, | ||||
Version: version, | Version: version, | ||||
@@ -86,7 +84,6 @@ func saveModelByParameters(jobId string, versionName string, name string, versio | |||||
AttachmentId: aiTask.Uuid, | AttachmentId: aiTask.Uuid, | ||||
RepoId: aiTask.RepoID, | RepoId: aiTask.RepoID, | ||||
UserId: ctx.User.ID, | UserId: ctx.User.ID, | ||||
UserName: ctx.User.Name, | |||||
UserRelAvatarLink: ctx.User.RelAvatarLink(), | UserRelAvatarLink: ctx.User.RelAvatarLink(), | ||||
CodeBranch: aiTask.BranchName, | CodeBranch: aiTask.BranchName, | ||||
CodeCommitID: aiTask.CommitID, | CodeCommitID: aiTask.CommitID, | ||||
@@ -144,9 +141,12 @@ func SaveModel(ctx *context.Context) { | |||||
log.Info("save model end.") | log.Info("save model end.") | ||||
} | } | ||||
func downloadModelFromCloudBrainTwo(modelUUID string, jobName string, parentDir string) (string, int64, error) { | |||||
func downloadModelFromCloudBrainTwo(modelUUID string, jobName string, parentDir string, trainUrl string) (string, int64, error) { | |||||
objectkey := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir), "/") | objectkey := strings.TrimPrefix(path.Join(setting.TrainJobModelPath, jobName, setting.OutPutPath, parentDir), "/") | ||||
if trainUrl != "" { | |||||
objectkey = strings.Trim(trainUrl[len(setting.Bucket)+1:], "/") | |||||
} | |||||
modelDbResult, err := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, objectkey, "") | modelDbResult, err := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, objectkey, "") | ||||
log.Info("bucket=" + setting.Bucket + " objectkey=" + objectkey) | log.Info("bucket=" + setting.Bucket + " objectkey=" + objectkey) | ||||
if err != nil { | if err != nil { | ||||
@@ -395,15 +395,42 @@ func ShowSingleModel(ctx *context.Context) { | |||||
ctx.JSON(http.StatusOK, models) | ctx.JSON(http.StatusOK, models) | ||||
} | } | ||||
func queryUserName(intSlice []int64) map[int64]string { | |||||
keys := make(map[int64]string) | |||||
uniqueElements := []int64{} | |||||
for _, entry := range intSlice { | |||||
if _, value := keys[entry]; !value { | |||||
keys[entry] = "" | |||||
uniqueElements = append(uniqueElements, entry) | |||||
} | |||||
} | |||||
userNames, err := models.GetUserNamesByIDs(uniqueElements) | |||||
if err == nil { | |||||
for i, userName := range userNames { | |||||
keys[uniqueElements[i]] = userName | |||||
} | |||||
} | |||||
return keys | |||||
} | |||||
func ShowOneVersionOtherModel(ctx *context.Context) { | func ShowOneVersionOtherModel(ctx *context.Context) { | ||||
repoId := ctx.Repo.Repository.ID | repoId := ctx.Repo.Repository.ID | ||||
name := ctx.Query("name") | name := ctx.Query("name") | ||||
aimodels := models.QueryModelByName(name, repoId) | aimodels := models.QueryModelByName(name, repoId) | ||||
for _, model := range aimodels { | |||||
userIds := make([]int64, len(aimodels)) | |||||
for i, model := range aimodels { | |||||
log.Info("model=" + model.Name) | log.Info("model=" + model.Name) | ||||
log.Info("model.UserId=" + fmt.Sprint(model.UserId)) | log.Info("model.UserId=" + fmt.Sprint(model.UserId)) | ||||
model.IsCanOper = isOper(ctx, model.UserId) | model.IsCanOper = isOper(ctx, model.UserId) | ||||
userIds[i] = model.UserId | |||||
} | |||||
userNameMap := queryUserName(userIds) | |||||
for _, model := range aimodels { | |||||
model.UserName = userNameMap[model.UserId] | |||||
} | } | ||||
if len(aimodels) > 0 { | if len(aimodels) > 0 { | ||||
ctx.JSON(200, aimodels[1:]) | ctx.JSON(200, aimodels[1:]) | ||||
} else { | } else { | ||||
@@ -431,7 +458,7 @@ func isOper(ctx *context.Context, modelUserId int64) bool { | |||||
if ctx.User == nil { | if ctx.User == nil { | ||||
return false | return false | ||||
} | } | ||||
if ctx.User.IsAdmin || ctx.Repo.IsAdmin() || ctx.Repo.IsOwner() || ctx.User.ID == modelUserId { | |||||
if ctx.User.IsAdmin || ctx.Repo.IsOwner() || ctx.User.ID == modelUserId { | |||||
return true | return true | ||||
} | } | ||||
return false | return false | ||||
@@ -463,10 +490,17 @@ func ShowModelPageInfo(ctx *context.Context) { | |||||
return | return | ||||
} | } | ||||
for _, model := range modelResult { | |||||
userIds := make([]int64, len(modelResult)) | |||||
for i, model := range modelResult { | |||||
log.Info("model=" + model.Name) | log.Info("model=" + model.Name) | ||||
log.Info("model.UserId=" + fmt.Sprint(model.UserId)) | log.Info("model.UserId=" + fmt.Sprint(model.UserId)) | ||||
model.IsCanOper = isOper(ctx, model.UserId) | model.IsCanOper = isOper(ctx, model.UserId) | ||||
userIds[i] = model.UserId | |||||
} | |||||
userNameMap := queryUserName(userIds) | |||||
for _, model := range modelResult { | |||||
model.UserName = userNameMap[model.UserId] | |||||
} | } | ||||
mapInterface := make(map[string]interface{}) | mapInterface := make(map[string]interface{}) | ||||
@@ -8,7 +8,6 @@ import ( | |||||
"io" | "io" | ||||
"net/http" | "net/http" | ||||
"os" | "os" | ||||
"os/exec" | |||||
"regexp" | "regexp" | ||||
"sort" | "sort" | ||||
"strconv" | "strconv" | ||||
@@ -71,15 +70,9 @@ func CloudBrainIndex(ctx *context.Context) { | |||||
return | return | ||||
} | } | ||||
timestamp := time.Now().Unix() | |||||
for i, task := range ciTasks { | for i, task := range ciTasks { | ||||
if task.Status == string(models.JobRunning) && (timestamp-int64(task.Cloudbrain.CreatedUnix) > 10) { | |||||
ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) | |||||
} else { | |||||
ciTasks[i].CanDebug = false | |||||
} | |||||
ciTasks[i].CanDel = cloudbrain.CanDeleteDebugJob(ctx, &task.Cloudbrain) | |||||
ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) | |||||
ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||||
} | } | ||||
@@ -251,13 +244,9 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||||
downloadCode(repo, codePath) | downloadCode(repo, codePath) | ||||
uploadCodeToMinio(codePath + "/", jobName, "/code/") | uploadCodeToMinio(codePath + "/", jobName, "/code/") | ||||
modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath | |||||
err = os.MkdirAll(modelPath, os.ModePerm) | |||||
if err != nil { | |||||
cloudBrainNewDataPrepare(ctx) | |||||
ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) | |||||
return | |||||
} | |||||
modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath + "/" | |||||
mkModelPath(modelPath) | |||||
uploadCodeToMinio(modelPath, jobName, cloudbrain.ModelMountPath + "/") | |||||
benchmarkPath := setting.JobPath + jobName + cloudbrain.BenchMarkMountPath | benchmarkPath := setting.JobPath + jobName + cloudbrain.BenchMarkMountPath | ||||
if setting.IsBenchmarkEnabled && jobType == string(models.JobTypeBenchmark) { | if setting.IsBenchmarkEnabled && jobType == string(models.JobTypeBenchmark) { | ||||
@@ -267,23 +256,25 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||||
gpuType = gpuInfo.Value | gpuType = gpuInfo.Value | ||||
} | } | ||||
} | } | ||||
downloadRateCode(repo, jobName, setting.BenchmarkCode, benchmarkPath, form.BenchmarkCategory, gpuType) | |||||
downloadRateCode(repo, jobName, setting.BenchmarkOwner, setting.BrainScoreName, benchmarkPath, form.BenchmarkCategory, gpuType) | |||||
uploadCodeToMinio(benchmarkPath + "/", jobName, cloudbrain.BenchMarkMountPath + "/") | uploadCodeToMinio(benchmarkPath + "/", jobName, cloudbrain.BenchMarkMountPath + "/") | ||||
} | } | ||||
snn4imagenetPath := setting.JobPath + jobName + cloudbrain.Snn4imagenetMountPath | snn4imagenetPath := setting.JobPath + jobName + cloudbrain.Snn4imagenetMountPath | ||||
if setting.IsSnn4imagenetEnabled && jobType == string(models.JobTypeSnn4imagenet) { | if setting.IsSnn4imagenetEnabled && jobType == string(models.JobTypeSnn4imagenet) { | ||||
downloadRateCode(repo, jobName, setting.Snn4imagenetCode, snn4imagenetPath, "", "") | |||||
downloadRateCode(repo, jobName, setting.Snn4imagenetOwner, setting.Snn4imagenetName, snn4imagenetPath, "", "") | |||||
uploadCodeToMinio(snn4imagenetPath + "/", jobName, cloudbrain.Snn4imagenetMountPath + "/") | uploadCodeToMinio(snn4imagenetPath + "/", jobName, cloudbrain.Snn4imagenetMountPath + "/") | ||||
} | } | ||||
brainScorePath := setting.JobPath + jobName + cloudbrain.BrainScoreMountPath | brainScorePath := setting.JobPath + jobName + cloudbrain.BrainScoreMountPath | ||||
if setting.IsBrainScoreEnabled && jobType == string(models.JobTypeBrainScore) { | if setting.IsBrainScoreEnabled && jobType == string(models.JobTypeBrainScore) { | ||||
downloadRateCode(repo, jobName, setting.BrainScoreCode, brainScorePath, "", "") | |||||
downloadRateCode(repo, jobName, setting.BrainScoreOwner, setting.BrainScoreName, brainScorePath, "", "") | |||||
uploadCodeToMinio(brainScorePath + "/", jobName, cloudbrain.BrainScoreMountPath + "/") | uploadCodeToMinio(brainScorePath + "/", jobName, cloudbrain.BrainScoreMountPath + "/") | ||||
} | } | ||||
err = cloudbrain.GenerateTask(ctx, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, resourceSpecId) | |||||
err = cloudbrain.GenerateTask(ctx, jobName, image, command, uuid, codePath, getMinioPath(jobName, cloudbrain.ModelMountPath + "/"), | |||||
getMinioPath(jobName, cloudbrain.BenchMarkMountPath + "/"), getMinioPath(jobName, cloudbrain.Snn4imagenetMountPath + "/"), | |||||
getMinioPath(jobName, cloudbrain.BrainScoreMountPath + "/"), jobType, gpuQueue, resourceSpecId) | |||||
if err != nil { | if err != nil { | ||||
cloudBrainNewDataPrepare(ctx) | cloudBrainNewDataPrepare(ctx) | ||||
ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) | ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) | ||||
@@ -607,7 +598,7 @@ func getImages(ctx *context.Context, imageType string) { | |||||
func GetModelDirs(jobName string, parentDir string) (string, error) { | func GetModelDirs(jobName string, parentDir string) (string, error) { | ||||
var req string | var req string | ||||
modelActualPath := setting.JobPath + jobName + "/model/" | |||||
modelActualPath := getMinioPath(jobName, cloudbrain.ModelMountPath + "/") | |||||
if parentDir == "" { | if parentDir == "" { | ||||
req = "baseDir=" + modelActualPath | req = "baseDir=" + modelActualPath | ||||
} else { | } else { | ||||
@@ -617,6 +608,10 @@ func GetModelDirs(jobName string, parentDir string) (string, error) { | |||||
return getDirs(req) | return getDirs(req) | ||||
} | } | ||||
func getMinioPath(jobName, suffixPath string) string { | |||||
return setting.Attachment.Minio.RealPath + setting.Attachment.Minio.Bucket + "/" + setting.CBCodePathPrefix + jobName + suffixPath | |||||
} | |||||
func CloudBrainDownloadModel(ctx *context.Context) { | func CloudBrainDownloadModel(ctx *context.Context) { | ||||
parentDir := ctx.Query("parentDir") | parentDir := ctx.Query("parentDir") | ||||
fileName := ctx.Query("fileName") | fileName := ctx.Query("fileName") | ||||
@@ -698,19 +693,21 @@ func downloadCode(repo *models.Repository, codePath string) error { | |||||
return nil | return nil | ||||
} | } | ||||
func downloadRateCode(repo *models.Repository, taskName, gitPath, codePath, benchmarkCategory, gpuType string) error { | |||||
func downloadRateCode(repo *models.Repository, taskName, rateOwnerName, rateRepoName, codePath, benchmarkCategory, gpuType string) error { | |||||
err := os.MkdirAll(codePath, os.ModePerm) | err := os.MkdirAll(codePath, os.ModePerm) | ||||
if err != nil { | if err != nil { | ||||
log.Error("mkdir codePath failed", err.Error()) | log.Error("mkdir codePath failed", err.Error()) | ||||
return err | return err | ||||
} | } | ||||
command := "git clone " + gitPath + " " + codePath | |||||
cmd := exec.Command("/bin/bash", "-c", command) | |||||
_, err = cmd.Output() | |||||
repoExt, err := models.GetRepositoryByOwnerAndName(rateOwnerName, rateRepoName) | |||||
if err != nil { | if err != nil { | ||||
log.Error("exec.Command(%s) failed:%v", command, err) | |||||
log.Error("GetRepositoryByOwnerAndName(%s) failed", rateRepoName, err.Error()) | |||||
return err | |||||
} | |||||
if err := git.Clone(repoExt.RepoPath(), codePath, git.CloneRepoOptions{}); err != nil { | |||||
log.Error("Failed to clone repository: %s (%v)", repoExt.FullName(), err) | |||||
return err | return err | ||||
} | } | ||||
@@ -772,6 +769,32 @@ func uploadCodeToMinio(codePath, jobName, parentDir string) error { | |||||
return nil | return nil | ||||
} | } | ||||
func mkModelPath(modelPath string) error { | |||||
err := os.MkdirAll(modelPath, os.ModePerm) | |||||
if err != nil { | |||||
log.Error("MkdirAll(%s) failed:%v", modelPath, err) | |||||
return err | |||||
} | |||||
fileName := modelPath + "README" | |||||
f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, os.ModePerm) | |||||
if err != nil { | |||||
log.Error("OpenFile failed", err.Error()) | |||||
return err | |||||
} | |||||
defer f.Close() | |||||
_, err = f.WriteString("You can put the model file into this directory and download it by the web page.") | |||||
if err != nil { | |||||
log.Error("WriteString failed", err.Error()) | |||||
return err | |||||
} | |||||
return nil | |||||
} | |||||
func SyncCloudbrainStatus() { | func SyncCloudbrainStatus() { | ||||
cloudBrains, err := models.GetCloudBrainUnStoppedJob() | cloudBrains, err := models.GetCloudBrainUnStoppedJob() | ||||
if err != nil { | if err != nil { | ||||
@@ -793,10 +816,24 @@ func SyncCloudbrainStatus() { | |||||
taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | taskRes, _ := models.ConvertToTaskPod(taskRoles[cloudbrain.SubTaskName].(map[string]interface{})) | ||||
task.Status = taskRes.TaskStatuses[0].State | task.Status = taskRes.TaskStatuses[0].State | ||||
if task.Status != string(models.JobWaiting) { | if task.Status != string(models.JobWaiting) { | ||||
task.Duration = time.Now().Unix() - taskRes.TaskStatuses[0].StartAt.Unix() | |||||
err = models.UpdateJob(task) | err = models.UpdateJob(task) | ||||
if err != nil { | if err != nil { | ||||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | ||||
continue | |||||
} | |||||
if task.Duration >= setting.MaxDuration { | |||||
log.Info("begin to stop job(%s), because of the duration", task.JobName) | |||||
err = cloudbrain.StopJob(task.JobID) | |||||
if err != nil { | |||||
log.Error("StopJob(%s) failed:%v", task.JobName, err) | |||||
continue | |||||
} | |||||
task.Status = string(models.JobStopped) | |||||
err = models.UpdateJob(task) | |||||
if err != nil { | |||||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -69,12 +69,9 @@ func NotebookIndex(ctx *context.Context) { | |||||
} | } | ||||
for i, task := range ciTasks { | for i, task := range ciTasks { | ||||
if task.Status == string(models.JobRunning) { | |||||
ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) | |||||
} else { | |||||
ciTasks[i].CanDebug = false | |||||
} | |||||
ciTasks[i].CanDel = cloudbrain.CanDeleteDebugJob(ctx, &task.Cloudbrain) | |||||
ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) | |||||
ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||||
} | } | ||||
pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | ||||
@@ -306,7 +303,7 @@ func TrainJobIndex(ctx *context.Context) { | |||||
} | } | ||||
for i, task := range tasks { | for i, task := range tasks { | ||||
tasks[i].CanDel = cloudbrain.CanDeleteTrainJob(ctx, &task.Cloudbrain) | |||||
tasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||||
tasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) | tasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) | ||||
} | } | ||||
@@ -532,6 +532,7 @@ func Download(ctx *context.Context) { | |||||
} | } | ||||
ctx.Repo.Repository.IncreaseCloneCnt() | ctx.Repo.Repository.IncreaseCloneCnt() | ||||
ctx.Repo.Repository.IncreaseGitCloneCnt() | |||||
ctx.ServeFile(archivePath, ctx.Repo.Repository.Name+"-"+refName+ext) | ctx.ServeFile(archivePath, ctx.Repo.Repository.Name+"-"+refName+ext) | ||||
} | } | ||||
@@ -148,11 +148,6 @@ func QueryUserStaticDataPage(ctx *context.Context) { | |||||
func TimingCountDataByDateAndReCount(date string, isReCount bool) { | func TimingCountDataByDateAndReCount(date string, isReCount bool) { | ||||
if date == "refreshAll" { | |||||
models.RefreshUserStaticAllTabel() | |||||
return | |||||
} | |||||
t, _ := time.Parse("2006-01-02", date) | t, _ := time.Parse("2006-01-02", date) | ||||
startTime := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) | startTime := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()) | ||||
@@ -205,10 +200,9 @@ func TimingCountDataByDateAndReCount(date string, isReCount bool) { | |||||
log.Error("count user info error." + err.Error()) | log.Error("count user info error." + err.Error()) | ||||
mailer.SendWarnNotifyMail(setting.Warn_Notify_Mails, warnEmailMessage) | mailer.SendWarnNotifyMail(setting.Warn_Notify_Mails, warnEmailMessage) | ||||
} | } | ||||
if isReCount { | |||||
models.RefreshUserStaticAllTabel() | |||||
} | |||||
log.Info("start to count all user info data") | |||||
//models.RefreshUserStaticAllTabel(wikiMap) | |||||
log.Info("end to count all user info data") | |||||
} | } | ||||
func TimingCountDataByDate(date string) { | func TimingCountDataByDate(date string) { | ||||
@@ -315,6 +315,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
}) | }) | ||||
m.Get("/", routers.Home) | m.Get("/", routers.Home) | ||||
m.Get("/dashboard", routers.Dashboard) | m.Get("/dashboard", routers.Dashboard) | ||||
m.Get("/recommend/org", routers.RecommendOrgFromPromote) | |||||
m.Get("/recommend/repo", routers.RecommendRepoFromPromote) | |||||
m.Group("/explore", func() { | m.Group("/explore", func() { | ||||
m.Get("", func(ctx *context.Context) { | m.Get("", func(ctx *context.Context) { | ||||
ctx.Redirect(setting.AppSubURL + "/explore/repos") | ctx.Redirect(setting.AppSubURL + "/explore/repos") | ||||
@@ -214,10 +214,15 @@ func Profile(ctx *context.Context) { | |||||
total = int(count) | total = int(count) | ||||
case "datasets": | case "datasets": | ||||
var isOwner = false | |||||
if ctx.User != nil && ctx.User.ID == ctxUser.ID { | |||||
isOwner = true | |||||
} | |||||
datasetSearchOptions := &models.SearchDatasetOptions{ | datasetSearchOptions := &models.SearchDatasetOptions{ | ||||
Keyword: keyword, | Keyword: keyword, | ||||
OwnerID: ctxUser.ID, | OwnerID: ctxUser.ID, | ||||
SearchOrderBy: orderBy, | SearchOrderBy: orderBy, | ||||
IsOwner: isOwner, | |||||
ListOptions: models.ListOptions{ | ListOptions: models.ListOptions{ | ||||
Page: page, | Page: page, | ||||
PageSize: setting.UI.ExplorePagingNum, | PageSize: setting.UI.ExplorePagingNum, | ||||
@@ -17,7 +17,7 @@ | |||||
{{if .IsSigned}} | {{if .IsSigned}} | ||||
<div class=" item" > | |||||
<div class=" item edge"> | |||||
<div class="dropdown-menu"> | <div class="dropdown-menu"> | ||||
<a class=" item" href="/dashboard"> | <a class=" item" href="/dashboard"> | ||||
<span > {{.i18n.Tr "index"}}   <i class="dropdown icon"></i></span> | <span > {{.i18n.Tr "index"}}   <i class="dropdown icon"></i></span> | ||||
@@ -47,7 +47,7 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{{else if .IsLandingPageHome}} | {{else if .IsLandingPageHome}} | ||||
<div class=" item"> | |||||
<div class="item edge"> | |||||
<div class="dropdown-menu"> | <div class="dropdown-menu"> | ||||
<a class=" item" href="/user/login"> | <a class=" item" href="/user/login"> | ||||
<span > {{.i18n.Tr "home"}}   <i class="dropdown icon"></i></span> | <span > {{.i18n.Tr "home"}}   <i class="dropdown icon"></i></span> | ||||
@@ -94,13 +94,13 @@ | |||||
*/}} | */}} | ||||
{{if .IsSigned}} | {{if .IsSigned}} | ||||
<div class="right stackable menu"> | |||||
<div class="right stackable menu"> | |||||
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | <form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | ||||
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | <div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | ||||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | ||||
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | ||||
<input type="hidden" name="tab" value="{{$.TabName}}"> | <input type="hidden" name="tab" value="{{$.TabName}}"> | ||||
<input type="hidden" name="sort" value="{{$.SortType}}"> | |||||
<input type="hidden" name="sort" value="hot"> | |||||
<button style="border: none;background-color: #363840;outline: none;border-radius:5px"><img type = "submit" style="width: 25px; height: 25px;margin: auto;" src="/img/search.svg" > | <button style="border: none;background-color: #363840;outline: none;border-radius:5px"><img type = "submit" style="width: 25px; height: 25px;margin: auto;" src="/img/search.svg" > | ||||
</button> | </button> | ||||
<!-- <button class="ui green button">{{.i18n.Tr "explore.search"}}</button> --> | <!-- <button class="ui green button">{{.i18n.Tr "explore.search"}}</button> --> | ||||
@@ -190,12 +190,13 @@ | |||||
<!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a--> | <!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a--> | ||||
<div class="right stackable menu"> | <div class="right stackable menu"> | ||||
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | <form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | ||||
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | <div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | ||||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | ||||
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | ||||
<input type="hidden" name="tab" value="{{$.TabName}}"> | <input type="hidden" name="tab" value="{{$.TabName}}"> | ||||
<input type="hidden" name="sort" value="{{$.SortType}}"> | |||||
<input type="hidden" name="sort" value="hot"> | |||||
<button style="border: none;background-color: #363840;outline: none;border-radius:5px"><img type = "submit" style="width: 25px; height: 25px;margin: auto;" src="/img/search.svg" > | <button style="border: none;background-color: #363840;outline: none;border-radius:5px"><img type = "submit" style="width: 25px; height: 25px;margin: auto;" src="/img/search.svg" > | ||||
</button> | </button> | ||||
<!-- <button class="ui green button">{{.i18n.Tr "explore.search"}}</button> --> | <!-- <button class="ui green button">{{.i18n.Tr "explore.search"}}</button> --> | ||||
@@ -17,7 +17,7 @@ | |||||
{{if .IsSigned}} | {{if .IsSigned}} | ||||
<div class="item" > | |||||
<div class="item edge" > | |||||
<div class="dropdown-menu"> | <div class="dropdown-menu"> | ||||
<a class=" item" href="/dashboard"> | <a class=" item" href="/dashboard"> | ||||
<span > {{.i18n.Tr "index"}}   <i class="dropdown icon"></i></span> | <span > {{.i18n.Tr "index"}}   <i class="dropdown icon"></i></span> | ||||
@@ -46,7 +46,7 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{{else if .IsLandingPageHome}} | {{else if .IsLandingPageHome}} | ||||
<div class="item" > | |||||
<div class="item edge" > | |||||
<div class="dropdown-menu"> | <div class="dropdown-menu"> | ||||
<a class=" item" href="/user/login"> | <a class=" item" href="/user/login"> | ||||
<span > {{.i18n.Tr "home"}}   <i class="dropdown icon"></i></span> | <span > {{.i18n.Tr "home"}}   <i class="dropdown icon"></i></span> | ||||
@@ -9,7 +9,7 @@ | |||||
</div> | </div> | ||||
{{if .IsSigned}} | {{if .IsSigned}} | ||||
<div class="item" > | |||||
<div class="item edge" > | |||||
<div class="dropdown-menu"> | <div class="dropdown-menu"> | ||||
<a class=" item" href="/dashboard"> | <a class=" item" href="/dashboard"> | ||||
<span > {{.i18n.Tr "index"}}   <i class="dropdown icon"></i></span> | <span > {{.i18n.Tr "index"}}   <i class="dropdown icon"></i></span> | ||||
@@ -38,7 +38,7 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{{else if .IsLandingPageHome}} | {{else if .IsLandingPageHome}} | ||||
<div class="item" > | |||||
<div class="item edge" > | |||||
<div class="dropdown-menu"> | <div class="dropdown-menu"> | ||||
<a class=" item" href="/user/login"> | <a class=" item" href="/user/login"> | ||||
<span > {{.i18n.Tr "home"}}   <i class="dropdown icon"></i></span> | <span > {{.i18n.Tr "home"}}   <i class="dropdown icon"></i></span> | ||||
@@ -0,0 +1,216 @@ | |||||
<div class="ui container" id="navbar"> | |||||
<div class="item brand" style="justify-content: space-between;"> | |||||
<a href="https://openi.org.cn/"> | |||||
<img class="ui mini image" src="{{StaticUrlPrefix}}/img/logo-w.svg"> | |||||
</a> | |||||
<div class="ui basic icon button mobile-only" id="navbar-expand-toggle"> | |||||
<i class="sidebar icon"></i> | |||||
</div> | |||||
</div> | |||||
<div style="width:1px;background:#606266;height:80%;margin:auto 0.5rem"></div> | |||||
<div class="item brand" style="margin-left: 0.9rem;"> | |||||
<a href="/"> | |||||
<img class="ui mini image" style="height: 1.3rem;" src="{{StaticUrlPrefix}}/img/git-logo.svg"> | |||||
</a> | |||||
</div> | |||||
{{if .IsSigned}} | |||||
<div class=" item edge" > | |||||
<div class="dropdown-menu"> | |||||
<a class=" item" href="/dashboard"> | |||||
<span > {{.i18n.Tr "index"}}   <i class="dropdown icon"></i></span> | |||||
</a> | |||||
<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}}/pulls">{{.i18n.Tr "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||||
<div class="ui dropdown item" id='dropdown_explore'> | |||||
{{.i18n.Tr "explore"}} | |||||
<i class="dropdown icon"></i> | |||||
<div class="menu"> | |||||
<a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | |||||
{{if .IsOperator}} | |||||
<a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||||
{{end}} | |||||
<a class="item" href="{{AppSubUrl}}/OpenI">{{.i18n.Tr "custom.head.openi"}}</a> | |||||
</div> | |||||
</div> | |||||
{{else if .IsLandingPageHome}} | |||||
<div class="item edge"> | |||||
<div class="dropdown-menu"> | |||||
<a class=" item" href="/user/login"> | |||||
<span > {{.i18n.Tr "home"}}   <i class="dropdown icon"></i></span> | |||||
</a> | |||||
<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 "pull_requests"}}</a> | |||||
<a style="border: none;color: #000;" class=" item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<a class="item" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "custom.head.project"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/datasets">{{.i18n.Tr "custom.head.dataset"}}</a> | |||||
<div class="ui dropdown item" id='dropdown_PageHome'> | |||||
{{.i18n.Tr "explore"}} | |||||
<i class="dropdown icon"></i> | |||||
<div class="menu" > | |||||
<a class="item" href="{{AppSubUrl}}/explore/users">{{.i18n.Tr "explore.users"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "explore.organizations"}}</a> | |||||
<a class="item" href="{{AppSubUrl}}/explore/images">{{.i18n.Tr "explore.images"}}</a> | |||||
{{if .IsOperator}} | |||||
<a class="item" href="{{AppSubUrl}}/explore/data_analysis">{{.i18n.Tr "explore.data_analysis"}}</a> | |||||
{{end}} | |||||
<a class="item" href="{{AppSubUrl}}/OpenI">{{.i18n.Tr "custom.head.openi"}}</a> | |||||
</div> | |||||
</div> | |||||
{{else if .IsLandingPageExplore}} | |||||
<a class="item {{if .PageIsExplore}}active{{end}}" href="{{AppSubUrl}}/explore/repos">{{.i18n.Tr "home"}}</a> | |||||
{{else if .IsLandingPageOrganizations}} | |||||
<a class="item {{if .PageIsExplore}}active{{end}}" href="{{AppSubUrl}}/explore/organizations">{{.i18n.Tr "home"}}</a> | |||||
{{end}} | |||||
{{template "custom/extra_links" .}} | |||||
{{/* | |||||
<div class="item"> | |||||
<div class="ui icon input"> | |||||
<input class="searchbox" type="text" placeholder="{{.i18n.Tr "search_project"}}"> | |||||
<i class="search icon"></i> | |||||
</div> | |||||
</div> | |||||
*/}} | |||||
{{if .IsSigned}} | |||||
<div class="right stackable menu"> | |||||
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||||
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||||
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||||
<input type="hidden" name="tab" value="{{$.TabName}}"> | |||||
<input type="hidden" name="sort" value="{{$.SortType}}"> | |||||
<button style="border: none;background-color: #363840;outline: none;border-radius:5px"><img type = "submit" style="width: 25px; height: 25px;margin: auto;" src="/img/search.svg" > | |||||
</button> | |||||
<!-- <button class="ui green button">{{.i18n.Tr "explore.search"}}</button> --> | |||||
</div> | |||||
</form> | |||||
<a href="{{AppSubUrl}}/notifications" class="item poping up" data-content='{{.i18n.Tr "notifications"}}' data-variation="tiny inverted"> | |||||
<span class="text"> | |||||
<span class="fitted">{{svg "octicon-bell" 16}}</span> | |||||
<span class="sr-mobile-only">{{.i18n.Tr "notifications"}}</span> | |||||
{{$notificationUnreadCount := 0}} | |||||
{{if .NotificationUnreadCount}}{{$notificationUnreadCount = call .NotificationUnreadCount}}{{end}} | |||||
<span class="ui red label {{if not $notificationUnreadCount}}hidden{{end}} notification_count"> | |||||
{{$notificationUnreadCount}} | |||||
</span> | |||||
</span> | |||||
</a> | |||||
<div class="ui dropdown jump item poping up" data-content="{{.i18n.Tr "create_new"}}" data-variation="tiny inverted"> | |||||
<span class="text"> | |||||
<span class="fitted">{{svg "octicon-plus" 16}}</span> | |||||
<span class="sr-mobile-only">{{.i18n.Tr "create_new"}}</span> | |||||
<span class="fitted not-mobile">{{svg "octicon-triangle-down" 16}}</span> | |||||
</span> | |||||
<div class="menu"> | |||||
<a class="item" href="{{AppSubUrl}}/repo/create"> | |||||
<span class="fitted">{{svg "octicon-plus" 16}}</span> {{.i18n.Tr "new_repo"}} | |||||
</a> | |||||
<a class="item" href="{{AppSubUrl}}/repo/migrate"> | |||||
<span class="fitted">{{svg "octicon-repo-clone" 16}}</span> {{.i18n.Tr "new_migrate"}} | |||||
</a> | |||||
{{if .SignedUser.CanCreateOrganization}} | |||||
<a class="item" href="{{AppSubUrl}}/org/create"> | |||||
<span class="fitted">{{svg "octicon-organization" 16}}</span> {{.i18n.Tr "new_org"}} | |||||
</a> | |||||
{{end}} | |||||
</div><!-- end content create new menu --> | |||||
</div><!-- end dropdown menu create new --> | |||||
<div class="ui dropdown jump item poping up" tabindex="-1" data-content="{{.i18n.Tr "user_profile_and_more"}}" data-variation="tiny inverted"> | |||||
<span class="text"> | |||||
<img class="ui tiny avatar image" width="24" height="24" src="{{.SignedUser.RelAvatarLink}}"> | |||||
<span class="sr-only">{{.i18n.Tr "user_profile_and_more"}}</span> | |||||
<span class="mobile-only">{{.SignedUser.Name}}</span> | |||||
<span class="fitted not-mobile" tabindex="-1">{{svg "octicon-triangle-down" 16}}</span> | |||||
</span> | |||||
<div class="menu user-menu" tabindex="-1"> | |||||
<div class="ui header"> | |||||
{{.i18n.Tr "signed_in_as"}} <strong>{{.SignedUser.Name}}</strong> | |||||
</div> | |||||
<div class="divider"></div> | |||||
<a class="item" href="{{AppSubUrl}}/{{.SignedUser.Name}}"> | |||||
{{svg "octicon-person" 16}} | |||||
{{.i18n.Tr "your_profile"}}<!-- Your profile --> | |||||
</a> | |||||
<a class="item" href="{{AppSubUrl}}/{{.SignedUser.Name}}?tab=stars"> | |||||
{{svg "octicon-star" 16}} | |||||
{{.i18n.Tr "your_starred"}} | |||||
</a> | |||||
<a class="{{if .PageIsUserSettings}}active{{end}} item" href="{{AppSubUrl}}/user/settings"> | |||||
{{svg "octicon-settings" 16}} | |||||
{{.i18n.Tr "your_settings"}}<!-- Your settings --> | |||||
</a> | |||||
<!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io"> | |||||
{{svg "octicon-question" 16}} | |||||
{{.i18n.Tr "help"}}<!-- Help --> | |||||
</a--> | |||||
{{if .IsAdmin}} | |||||
<div class="divider"></div> | |||||
<a class="{{if .PageIsAdmin}}active{{end}} item" href="{{AppSubUrl}}/admin"> | |||||
<i class="icon settings"></i> | |||||
{{.i18n.Tr "admin_panel"}}<!-- Admin Panel --> | |||||
</a> | |||||
{{end}} | |||||
<div class="divider"></div> | |||||
<a class="item link-action" href data-url="{{AppSubUrl}}/user/logout" data-redirect="{{AppSubUrl}}/"> | |||||
{{svg "octicon-sign-out" 16}} | |||||
{{.i18n.Tr "sign_out"}}<!-- Sign Out --> | |||||
</a> | |||||
</div><!-- end content avatar menu --> | |||||
</div><!-- end dropdown avatar menu --> | |||||
</div><!-- end signed user right menu --> | |||||
{{else}} | |||||
<!--a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.io">{{.i18n.Tr "help"}}</a--> | |||||
<div class="right stackable menu"> | |||||
<form class="fourteen wide mobile ten wide tablet ten wide computer column ui form ignore-dirty" style="margin:auto" action="/explore/repos"> | |||||
<div class="ui fluid action input" style="background:#363840 ;border-radius: 5px;width: 200px;height:30px;border: #888888 solid 1px;"> | |||||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search_pro"}}..." | |||||
style="transition: background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#888888;background:#363840 ;color:#888888;border: none;outline: none;"> | |||||
<input type="hidden" name="tab" value="{{$.TabName}}"> | |||||
<input type="hidden" name="sort" value="{{$.SortType}}"> | |||||
<button style="border: none;background-color: #363840;outline: none;border-radius:5px"><img type = "submit" style="width: 25px; height: 25px;margin: auto;" src="/img/search.svg" > | |||||
</button> | |||||
<!-- <button class="ui green button">{{.i18n.Tr "explore.search"}}</button> --> | |||||
</div> | |||||
</form> | |||||
{{if .ShowRegistrationButton}} | |||||
<a class="item{{if .PageIsSignUp}} active{{end}}" href="{{AppSubUrl}}/user/sign_up"> | |||||
{{svg "octicon-person" 16}} {{.i18n.Tr "register"}} | |||||
</a> | |||||
{{end}} | |||||
<a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login"> | |||||
{{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} | |||||
</a> | |||||
</div><!-- end anonymous right menu --> | |||||
{{end}} | |||||
</div> |
@@ -0,0 +1,208 @@ | |||||
<!DOCTYPE html> | |||||
<html lang="{{.Language}}"> | |||||
<head data-suburl="{{AppSubUrl}}"> | |||||
<meta charset="utf-8"> | |||||
<meta name="viewport" content="width=device-width, initial-scale=1"> | |||||
<meta http-equiv="x-ua-compatible" content="ie=edge"> | |||||
<title>{{if .Title}}{{.Title}} - {{end}} {{if .Repository.Name}}{{.Repository.Name}} - {{end}}{{AppName}}</title> | |||||
<link rel="manifest" href="{{AppSubUrl}}/manifest.json" crossorigin="use-credentials"> | |||||
{{if UseServiceWorker}} | |||||
<script> | |||||
if ('serviceWorker' in navigator) { | |||||
navigator.serviceWorker.register('{{AppSubUrl}}/serviceworker.js').then(function(registration) { | |||||
// Registration was successful | |||||
console.info('ServiceWorker registration successful with scope: ', registration.scope); | |||||
}, function(err) { | |||||
// registration failed :( | |||||
console.info('ServiceWorker registration failed: ', err); | |||||
}); | |||||
} | |||||
</script> | |||||
{{else}} | |||||
<script> | |||||
if ('serviceWorker' in navigator) { | |||||
navigator.serviceWorker.getRegistrations().then(function(registrations) { | |||||
registrations.forEach(function(registration) { | |||||
registration.unregister(); | |||||
console.info('ServiceWorker unregistered'); | |||||
}); | |||||
}); | |||||
} | |||||
</script> | |||||
{{end}} | |||||
<meta name="theme-color" content="{{ThemeColorMetaTag}}"> | |||||
<meta name="author" content="{{if .Repository}}{{.Owner.Name}}{{else}}{{MetaAuthor}}{{end}}" /> | |||||
<meta name="description" content="{{if .Repository}}{{.Repository.Name}}{{if .Repository.Description}} - {{.Repository.Description}}{{end}}{{else}}{{MetaDescription}}{{end}}" /> | |||||
<meta name="keywords" content="{{MetaKeywords}}"> | |||||
<meta name="referrer" content="no-referrer" /> | |||||
<meta name="_csrf" content="{{.CsrfToken}}" /> | |||||
{{if .IsSigned}} | |||||
<meta name="_uid" content="{{.SignedUser.ID}}" /> | |||||
{{end}} | |||||
{{if .ContextUser}} | |||||
<meta name="_context_uid" content="{{.ContextUser.ID}}" /> | |||||
{{end}} | |||||
{{if .SearchLimit}} | |||||
<meta name="_search_limit" content="{{.SearchLimit}}" /> | |||||
{{end}} | |||||
{{if .GoGetImport}} | |||||
<meta name="go-import" content="{{.GoGetImport}} git {{.CloneLink.HTTPS}}"> | |||||
<meta name="go-source" content="{{.GoGetImport}} _ {{.GoDocDirectory}} {{.GoDocFile}}"> | |||||
{{end}} | |||||
<script> | |||||
{{SafeJS `/* | |||||
@licstart The following is the entire license notice for the | |||||
JavaScript code in this page. | |||||
Copyright (c) 2016 The Gitea Authors | |||||
Copyright (c) 2015 The Gogs Authors | |||||
Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
of this software and associated documentation files (the "Software"), to deal | |||||
in the Software without restriction, including without limitation the rights | |||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
copies of the Software, and to permit persons to whom the Software is | |||||
furnished to do so, subject to the following conditions: | |||||
The above copyright notice and this permission notice shall be included in | |||||
all copies or substantial portions of the Software. | |||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||||
THE SOFTWARE. | |||||
--- | |||||
Licensing information for additional javascript libraries can be found at: | |||||
{{StaticUrlPrefix}}/vendor/librejs.html | |||||
@licend The above is the entire license notice | |||||
for the JavaScript code in this page. | |||||
*/`}} | |||||
</script> | |||||
<script> | |||||
window.config = { | |||||
AppSubUrl: '{{AppSubUrl}}', | |||||
StaticUrlPrefix: '{{StaticUrlPrefix}}', | |||||
csrf: '{{.CsrfToken}}', | |||||
HighlightJS: {{if .RequireHighlightJS}}true{{else}}false{{end}}, | |||||
Minicolors: {{if .RequireMinicolors}}true{{else}}false{{end}}, | |||||
SimpleMDE: {{if .RequireSimpleMDE}}true{{else}}false{{end}}, | |||||
Tribute: {{if .RequireTribute}}true{{else}}false{{end}}, | |||||
U2F: {{if .RequireU2F}}true{{else}}false{{end}}, | |||||
Heatmap: {{if .EnableHeatmap}}true{{else}}false{{end}}, | |||||
heatmapUser: {{if .HeatmapUser}}'{{.HeatmapUser}}'{{else}}null{{end}}, | |||||
NotificationSettings: { | |||||
MinTimeout: {{NotificationSettings.MinTimeout}}, | |||||
TimeoutStep: {{NotificationSettings.TimeoutStep}}, | |||||
MaxTimeout: {{NotificationSettings.MaxTimeout}}, | |||||
EventSourceUpdateTime: {{NotificationSettings.EventSourceUpdateTime}}, | |||||
}, | |||||
{{if .RequireTribute}} | |||||
tributeValues: [ | |||||
{{ range .Assignees }} | |||||
{key: '{{.Name}} {{.FullName}}', value: '{{.Name}}', | |||||
name: '{{.Name}}', fullname: '{{.FullName}}', avatar: '{{.RelAvatarLink}}'}, | |||||
{{ end }} | |||||
], | |||||
{{end}} | |||||
}; | |||||
</script> | |||||
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png"> | |||||
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg" color="#609926"> | |||||
<link rel="fluid-icon" href="{{StaticUrlPrefix}}/img/gitea-lg.png" title="{{AppName}}"> | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/assets/font-awesome/css/font-awesome.min.css"> | |||||
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/icons.woff2" type="font/woff2" crossorigin="anonymous"> | |||||
<link rel="preload" as="font" href="{{StaticUrlPrefix}}/fomantic/themes/default/assets/fonts/outline-icons.woff2" type="font/woff2" crossorigin="anonymous"> | |||||
{{if .RequireSimpleMDE}} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.css"> | |||||
{{end}} | |||||
{{if .RequireTribute}} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css"> | |||||
{{end}} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}"> | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}"> | |||||
<noscript> | |||||
<style> | |||||
.dropdown:hover > .menu { display: block; } | |||||
.ui.secondary.menu .dropdown.item > .menu { margin-top: 0; } | |||||
</style> | |||||
</noscript> | |||||
{{if .RequireMinicolors}} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.css"> | |||||
{{end}} | |||||
<style class="list-search-style"></style> | |||||
{{if .PageIsUserProfile}} | |||||
<meta property="og:title" content="{{.Owner.Name}}" /> | |||||
<meta property="og:type" content="profile" /> | |||||
<meta property="og:image" content="{{.Owner.AvatarLink}}" /> | |||||
<meta property="og:url" content="{{.Owner.HTMLURL}}" /> | |||||
{{if .Owner.Description}} | |||||
<meta property="og:description" content="{{.Owner.Description}}"> | |||||
{{end}} | |||||
{{else if .Repository}} | |||||
{{if .Issue}} | |||||
<meta property="og:title" content="{{.Issue.Title}}" /> | |||||
<meta property="og:url" content="{{.Issue.HTMLURL}}" /> | |||||
{{if .Issue.Content}} | |||||
<meta property="og:description" content="{{.Issue.Content}}" /> | |||||
{{end}} | |||||
{{else}} | |||||
<meta property="og:title" content="{{.Repository.Name}}" /> | |||||
<meta property="og:url" content="{{.Repository.HTMLURL}}" /> | |||||
{{if .Repository.Description}} | |||||
<meta property="og:description" content="{{.Repository.Description}}" /> | |||||
{{end}} | |||||
{{end}} | |||||
<meta property="og:type" content="object" /> | |||||
<meta property="og:image" content="{{.Repository.Owner.AvatarLink}}" /> | |||||
{{else}} | |||||
<meta property="og:title" content="{{AppName}}"> | |||||
<meta property="og:type" content="website" /> | |||||
<meta property="og:image" content="{{StaticUrlPrefix}}/img/gitea-lg.png" /> | |||||
<meta property="og:url" content="{{AppUrl}}" /> | |||||
<meta property="og:description" content="{{MetaDescription}}"> | |||||
{{end}} | |||||
<meta property="og:site_name" content="{{AppName}}" /> | |||||
{{if .IsSigned }} | |||||
{{ if ne .SignedUser.Theme "gitea" }} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{.SignedUser.Theme}}.css?v={{MD5 AppVer}}"> | |||||
{{end}} | |||||
{{else if ne DefaultTheme "gitea"}} | |||||
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/theme-{{DefaultTheme}}.css?v={{MD5 AppVer}}"> | |||||
{{end}} | |||||
{{template "custom/header" .}} | |||||
<script> | |||||
var _hmt = _hmt || []; | |||||
(function() { | |||||
var hm = document.createElement("script"); | |||||
hm.src = "https://hm.baidu.com/hm.js?46149a0b61fdeddfe427ff4de63794ba"; | |||||
var s = document.getElementsByTagName("script")[0]; | |||||
s.parentNode.insertBefore(hm, s); | |||||
})(); | |||||
</script> | |||||
<script src="/self/func.js" type="text/javascript"></script> | |||||
</head> | |||||
<body> | |||||
{{template "custom/body_outer_pre" .}} | |||||
<div class="full height"> | |||||
<noscript>{{.i18n.Tr "enable_javascript"}}</noscript> | |||||
{{template "custom/body_inner_pre" .}} | |||||
{{if not .PageIsInstall}} | |||||
<div class="ui top secondary stackable main menu following bar dark"> | |||||
{{template "base/head_navbar_pro" .}} | |||||
</div><!-- end bar --> | |||||
{{end}} | |||||
{{/* | |||||
</div> | |||||
</body> | |||||
</html> | |||||
*/}} |
@@ -1,4 +1,4 @@ | |||||
{{template "base/head" .}} | |||||
{{template "base/head_pro" .}} | |||||
<div class="explore repositories"> | <div class="explore repositories"> | ||||
{{template "explore/repo_search" .}} | {{template "explore/repo_search" .}} | ||||
@@ -134,7 +134,8 @@ | |||||
{{if .Permission.CanRead $.UnitTypeDatasets}} | {{if .Permission.CanRead $.UnitTypeDatasets}} | ||||
<a class="{{if .PageIsDataset}}active{{end}} item" href="{{.RepoLink}}/datasets?type=0"> | <a class="{{if .PageIsDataset}}active{{end}} item" href="{{.RepoLink}}/datasets?type=0"> | ||||
{{svg "octicon-inbox" 16}} {{.i18n.Tr "datasets"}} | |||||
<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="M20.083 15.2l1.202.721a.5.5 0 0 1 0 .858l-8.77 5.262a1 1 0 0 1-1.03 0l-8.77-5.262a.5.5 0 0 1 0-.858l1.202-.721L12 20.05l8.083-4.85zm0-4.7l1.202.721a.5.5 0 0 1 0 .858L12 17.65l-9.285-5.571a.5.5 0 0 1 0-.858l1.202-.721L12 15.35l8.083-4.85zm-7.569-9.191l8.771 5.262a.5.5 0 0 1 0 .858L12 13 2.715 7.429a.5.5 0 0 1 0-.858l8.77-5.262a1 1 0 0 1 1.03 0zM12 3.332L5.887 7 12 10.668 18.113 7 12 3.332z"/></svg> | |||||
{{.i18n.Tr "datasets"}} | |||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
{{if .Permission.CanRead $.UnitTypeModelManage}} | {{if .Permission.CanRead $.UnitTypeModelManage}} | ||||
@@ -145,7 +146,11 @@ | |||||
{{end}} | {{end}} | ||||
{{if .Permission.CanRead $.UnitTypeCloudBrain}} | {{if .Permission.CanRead $.UnitTypeCloudBrain}} | ||||
<a class="{{if .PageIsCloudBrain}}active{{end}} item" href="{{.RepoLink}}/cloudbrain"> | <a class="{{if .PageIsCloudBrain}}active{{end}} item" href="{{.RepoLink}}/cloudbrain"> | ||||
<span>{{svg "octicon-server" 16}} {{.i18n.Tr "repo.cloudbrain"}}<i class="question circle icon link cloudbrain-question" data-content={{.i18n.Tr "repo.cloudbrain_helper"}} data-position="top center" data-variation="mini"></i></span> | |||||
<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> | |||||
{{.i18n.Tr "repo.cloudbrain"}} | |||||
<i class="question circle icon link cloudbrain-question" data-content={{.i18n.Tr "repo.cloudbrain_helper"}} data-position="top center" data-variation="mini"></i> | |||||
</span> | |||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
<!-- {{if .IsSigned}} | <!-- {{if .IsSigned}} | ||||
@@ -149,15 +149,6 @@ | |||||
<label>{{.i18n.Tr "repo.settings.dataset_desc"}}</label> | <label>{{.i18n.Tr "repo.settings.dataset_desc"}}</label> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
{{$isCloudBrainEnabled := .Repository.UnitEnabled $.UnitTypeCloudBrain }} | |||||
<div class="inline field"> | |||||
<label>{{.i18n.Tr "repo.cloudbrain"}}</label> | |||||
<div class="ui checkbox"> | |||||
<input class="enable-system" name="enable_cloud_brain" type="checkbox" {{if $isCloudBrainEnabled}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.cloudbrain_desc"}}</label> | |||||
</div> | |||||
</div> | |||||
{{$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> | ||||
@@ -166,6 +157,14 @@ | |||||
<label>{{.i18n.Tr "repo.settings.model_desc"}}</label> | <label>{{.i18n.Tr "repo.settings.model_desc"}}</label> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
{{$isCloudBrainEnabled := .Repository.UnitEnabled $.UnitTypeCloudBrain }} | |||||
<div class="inline field"> | |||||
<label>{{.i18n.Tr "repo.cloudbrain"}}</label> | |||||
<div class="ui checkbox"> | |||||
<input class="enable-system" name="enable_cloud_brain" type="checkbox" {{if $isCloudBrainEnabled}}checked{{end}}> | |||||
<label>{{.i18n.Tr "repo.settings.cloudbrain_desc"}}</label> | |||||
</div> | |||||
</div> | |||||
{{$isWikiEnabled := or (.Repository.UnitEnabled $.UnitTypeWiki) (.Repository.UnitEnabled $.UnitTypeExternalWiki)}} | {{$isWikiEnabled := or (.Repository.UnitEnabled $.UnitTypeWiki) (.Repository.UnitEnabled $.UnitTypeExternalWiki)}} | ||||
<div class="inline field"> | <div class="inline field"> | ||||
<label>{{.i18n.Tr "repo.wiki"}}</label> | <label>{{.i18n.Tr "repo.wiki"}}</label> | ||||
@@ -50,16 +50,46 @@ | |||||
{{end}} | {{end}} | ||||
<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> | |||||
<ul class="user-orgs"> | |||||
<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="padding-bottom: 0px;"> | |||||
<!-- <ul class="user-orgs"> | |||||
{{range .Orgs}} | {{range .Orgs}} | ||||
{{if (or .Visibility.IsPublic (and ($.SignedUser) (or .Visibility.IsLimited (and (.IsUserPartOfOrg $.SignedUserID) .Visibility.IsPrivate) ($.IsAdmin))))}} | {{if (or .Visibility.IsPublic (and ($.SignedUser) (or .Visibility.IsLimited (and (.IsUserPartOfOrg $.SignedUserID) .Visibility.IsPrivate) ($.IsAdmin))))}} | ||||
<li> | <li> | ||||
<a href="{{.HomeLink}}"><img class="ui image poping up" src="{{.RelAvatarLink}}" data-content="{{.Name}}" data-position="top center" data-variation="tiny inverted"></a> | |||||
<ul> | |||||
<a href="{{.HomeLink}}"><img class="ui image poping up" src="{{.RelAvatarLink}}" data-content="{{.Name}}" data-position="top center" data-variation="tiny inverted"></a> | |||||
<span>{{.Name}}</span> | |||||
</ul> | |||||
</li> | </li> | ||||
{{end}} | {{end}} | ||||
{{end}} | {{end}} | ||||
</ul> | |||||
</ul> --> | |||||
{{range .Orgs}} | |||||
<ul class="user-orgs"> | |||||
{{if (or .Visibility.IsPublic (and ($.SignedUser) (or .Visibility.IsLimited (and (.IsUserPartOfOrg $.SignedUserID) .Visibility.IsPrivate) ($.IsAdmin))))}} | |||||
<li class="infor" style="width: 15%;" > | |||||
<a href="{{.HomeLink}}"><img class="ui image poping up" src="{{.RelAvatarLink}}" data-content="{{.Name}}" data-position="top center" data-variation="tiny inverted"></a> | |||||
</li> | |||||
<li class="infor" style="width: 35%;"> | |||||
<a class="ui image poping up" style="color: #0366D6;overflow: hidden; white-space: nowrap; text-overflow: ellipsis;" href="{{.HomeLink}}" data-content="{{.Name}}" data-position="top center" data-variation="tiny inverted">{{.Name}}</a> | |||||
</li> | |||||
<li class="infor" style="width: 25%;"> | |||||
<img style="width: 14px; height: 14px;border: none;" src="/img/member.svg" > | |||||
<span style="color: rgba(0,0,0,.4);padding-left: 5px;">{{.NumMembers}}</span> | |||||
</li> | |||||
<li class="infor" style="width: 25%;"> | |||||
<img style="width: 14px; height: 14px" src="/img/pro_num.svg" > | |||||
<span style="color: rgba(0,0,0,.4);padding-left: 5px;">{{.NumRepos}}</span> | |||||
</li> | |||||
{{end}} | |||||
</ul> | |||||
{{end}} | |||||
</li> | </li> | ||||
{{end}} | {{end}} | ||||
{{if and .IsSigned (ne .SignedUserName .Owner.Name)}} | {{if and .IsSigned (ne .SignedUserName .Owner.Name)}} | ||||
@@ -79,13 +109,6 @@ | |||||
{{end}} | {{end}} | ||||
</ul> | </ul> | ||||
</div> | </div> | ||||
<div > | |||||
<ul> | |||||
<li> | |||||
<ul></ul><ul></ul> | |||||
</li> | |||||
</ul> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="ui eleven wide column"> | <div class="ui eleven wide column"> | ||||
@@ -155,3 +178,22 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
{{template "base/footer" .}} | {{template "base/footer" .}} | ||||
<style> | |||||
.infor{ | |||||
margin: auto 0; | |||||
} | |||||
.user-orgs{ | |||||
padding: 10px 0px; | |||||
} | |||||
.user-orgs li{ | |||||
max-width: 50%; | |||||
float: right; | |||||
} | |||||
.user.profile .ui.card .extra.content ul { | |||||
padding: 5px 0; | |||||
} | |||||
</style> |
@@ -518,4 +518,10 @@ display: block; | |||||
} | } | ||||
.letf2{ | .letf2{ | ||||
margin-left: -2px; | margin-left: -2px; | ||||
} | |||||
} | |||||
.edge{ | |||||
margin-left:0 !important; | |||||
margin-right: 0 !important; | |||||
padding-left:0 !important; | |||||
padding-right:0 !important; | |||||
} |