Browse Source

Merge branch 'V20211213' into liuzx_trainjob

tags/v1.21.12.1^2
zhoupzh 3 years ago
parent
commit
fe8615b751
11 changed files with 202 additions and 125 deletions
  1. +31
    -31
      custom/conf/app.ini.sample
  2. +8
    -3
      modules/normalization/normalization.go
  3. +34
    -32
      modules/setting/setting.go
  4. +4
    -0
      modules/storage/local.go
  5. +6
    -0
      modules/storage/minio.go
  6. +1
    -0
      modules/storage/storage.go
  7. +33
    -2
      routers/repo/cloudbrain.go
  8. +27
    -21
      templates/base/head_navbar.tmpl
  9. +24
    -17
      templates/base/head_navbar_fluid.tmpl
  10. +25
    -19
      templates/base/head_navbar_home.tmpl
  11. +9
    -0
      web_src/js/index.js

+ 31
- 31
custom/conf/app.ini.sample View File

@@ -1059,50 +1059,50 @@ RESULT_BACKEND = redis://localhost:6379
[cloudbrain]
USERNAME =
PASSWORD =
REST_SERVER_HOST = http://192.168.202.73
JOB_PATH = /datasets/minio/data/opendata/jobs/
DEBUG_SERVER_HOST = http://192.168.202.73/
REST_SERVER_HOST =
JOB_PATH =
DEBUG_SERVER_HOST =
; cloudbrain visit opendata
USER = cW4cMtH24eoWPE7X
PWD = 4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DA.C
GPU_TYPE_DEFAULT = openidebug
GPU_TYPES = {"gpu_type":[{"id":1,"queue":"openidebug","value":"T4"},{"id":2,"queue":"openidgx","value":"V100"}]}
USER =
PWD =
GPU_TYPE_DEFAULT =
GPU_TYPES =

[benchmark]
ENABLED = true
BENCHMARKCODE = https://yangzhx:justfortest123@git.openi.org.cn/yangzhx/detection_benchmark_script.git
HOST = http://192.168.202.90:3366/
ENABLED =
BENCHMARKCODE =
HOST =

[snn4imagenet]
ENABLED = true
SNN4IMAGENETCODE = https://yult:eh2Ten4iLYjFkbj@git.openi.org.cn/ylt/snn4imagenet.git
HOST = http://192.168.202.90:3366/
ENABLED =
SNN4IMAGENETCODE =
HOST =

[decompress]
HOST = http://192.168.207.34:39987
USER = cW4cMtH24eoWPE7X
PASSWORD = 4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DAC
HOST =
USER =
PASSWORD =

[blockchain]
HOST = http://192.168.207.84:3002/
COMMIT_VALID_DATE = 2021-01-15
HOST =
COMMIT_VALID_DATE =

[obs]
ENDPOINT = https://obs.cn-south-222.ai.pcl.cn
ACCESS_KEY_ID = FDP3LRMHLB9S77VWEHE3
SECRET_ACCESS_KEY = LyM82Wk80pgjhs2z7AdDcsdpCWhbsJtSzQ7hkESN
BUCKET = testopendata
LOCATION = cn-south-222
BASE_PATH = attachment/
ENDPOINT =
ACCESS_KEY_ID =
SECRET_ACCESS_KEY =
BUCKET =
LOCATION =
BASE_PATH =

[modelarts]
ORGANIZATION = modelarts
ENDPOINT = https://modelarts.cn-south-222.ai.pcl.cn
PROJECT_ID = edfccf24aace4e17a56da6bcbb55a5aa
PROJECT_NAME = cn-south-222_test
USERNAME = test1
PASSWORD = Qizhi@test.
DOMAIN = cn-south-222
ORGANIZATION =
ENDPOINT =
PROJECT_ID =
PROJECT_NAME =
USERNAME =
PASSWORD =
DOMAIN =

[radar_map]
impact=0.3


+ 8
- 3
modules/normalization/normalization.go View File

@@ -4,6 +4,8 @@ import (
"code.gitea.io/gitea/modules/setting"
)

const MAX_LINES_RECORD = 100

func Normalization(value float64, minValue float64, maxValue float64) float64 {

min := int64(minValue * 100)
@@ -72,9 +74,12 @@ func GetTeamHealthInitValue(contributors int64, keyContributors int64, newContri

}

func GetRepoGrowthInitValue(codelinesGrowth int64, issueGrowth int64, commitsGrowth int64, newContributors int64, commentsGrowth int64) float64 {

return setting.RadarMap.GrowthCodeLines*float64(codelinesGrowth) +
func GetRepoGrowthInitValue(codeLinesGrowth int64, issueGrowth int64, commitsGrowth int64, newContributors int64, commentsGrowth int64) float64 {
codeLinesKB := codeLinesGrowth / 1000
if codeLinesKB > MAX_LINES_RECORD {
codeLinesKB = MAX_LINES_RECORD
}
return setting.RadarMap.GrowthCodeLines*float64(codeLinesKB) +
setting.RadarMap.GrowthIssue*float64(issueGrowth) +
setting.RadarMap.GrowthCommit*float64(commitsGrowth) +
setting.RadarMap.GrowthContributors*float64(newContributors) +


+ 34
- 32
modules/setting/setting.go View File

@@ -439,14 +439,15 @@ var (
DecompressOBSTaskName string

//cloudbrain config
CBAuthUser string
CBAuthPassword string
RestServerHost string
JobPath string
JobType string
GpuTypes string
DebugServerHost string
ResourceSpecs string
CBAuthUser string
CBAuthPassword string
RestServerHost string
JobPath string
CBCodePathPrefix string
JobType string
GpuTypes string
DebugServerHost string
ResourceSpecs string

//benchmark config
IsBenchmarkEnabled bool
@@ -549,7 +550,7 @@ var (
RecordBeginTime string
IgnoreMirrorRepo bool
}{}
Warn_Notify_Mails []string
)

@@ -1216,8 +1217,8 @@ func NewContext() {

sec = Cfg.Section("decompress")
DecompressAddress = sec.Key("HOST").MustString("http://192.168.207.34:39987")
AuthUser = sec.Key("USER").MustString("cW4cMtH24eoWPE7X")
AuthPassword = sec.Key("PASSWORD").MustString("4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DAC")
AuthUser = sec.Key("USER").MustString("")
AuthPassword = sec.Key("PASSWORD").MustString("")

sec = Cfg.Section("labelsystem")
LabelTaskName = sec.Key("LabelTaskName").MustString("LabelRedisQueue")
@@ -1225,10 +1226,11 @@ func NewContext() {
DecompressOBSTaskName = sec.Key("DecompressOBSTaskName").MustString("LabelDecompressOBSQueue")

sec = Cfg.Section("cloudbrain")
CBAuthUser = sec.Key("USER").MustString("cW4cMtH24eoWPE7X")
CBAuthPassword = sec.Key("PWD").MustString("4BPmgvK2hb2Eywwyp4YZRY4B7yQf4DAC")
CBAuthUser = sec.Key("USER").MustString("")
CBAuthPassword = sec.Key("PWD").MustString("")
RestServerHost = sec.Key("REST_SERVER_HOST").MustString("http://192.168.202.73")
JobPath = sec.Key("JOB_PATH").MustString("/datasets/minio/data/opendata/jobs/")
CBCodePathPrefix = sec.Key("CODE_PATH_PREFIX").MustString("jobs/")
DebugServerHost = sec.Key("DEBUG_SERVER_HOST").MustString("http://192.168.202.73")
JobType = sec.Key("GPU_TYPE_DEFAULT").MustString("openidebug")
GpuTypes = sec.Key("GPU_TYPES").MustString("")
@@ -1236,31 +1238,31 @@ func NewContext() {

sec = Cfg.Section("benchmark")
IsBenchmarkEnabled = sec.Key("ENABLED").MustBool(false)
BenchmarkCode = sec.Key("BENCHMARKCODE").MustString("https://yangzhx:justfortest123@git.openi.org.cn/yangzhx/detection_benchmark_script.git")
BenchmarkServerHost = sec.Key("HOST").MustString("http://192.168.202.90:3366/")
BenchmarkCode = sec.Key("BENCHMARKCODE").MustString("")
BenchmarkServerHost = sec.Key("HOST").MustString("")
BenchmarkCategory = sec.Key("CATEGORY").MustString("")

sec = Cfg.Section("snn4imagenet")
IsSnn4imagenetEnabled = sec.Key("ENABLED").MustBool(false)
Snn4imagenetCode = sec.Key("SNN4IMAGENETCODE").MustString("https://yult:19910821ylt@git.openi.org.cn/yult/snn4imagenet_script.git")
Snn4imagenetServerHost = sec.Key("HOST").MustString("http://192.168.207.76:8080/")
Snn4imagenetCode = sec.Key("SNN4IMAGENETCODE").MustString("")
Snn4imagenetServerHost = sec.Key("HOST").MustString("")

sec = Cfg.Section("brainscore")
IsBrainScoreEnabled = sec.Key("ENABLED").MustBool(false)
BrainScoreCode = sec.Key("BRAINSCORECODE").MustString("https://yult:19910821ylt@git.openi.org.cn/yult/brainscore_script.git")
BrainScoreServerHost = sec.Key("HOST").MustString("http://192.168.207.76:8080/")
BrainScoreCode = sec.Key("BRAINSCORECODE").MustString("")
BrainScoreServerHost = sec.Key("HOST").MustString("")

sec = Cfg.Section("blockchain")
BlockChainHost = sec.Key("HOST").MustString("http://192.168.136.66:3302/")
CommitValidDate = sec.Key("COMMIT_VALID_DATE").MustString("2021-01-15")

sec = Cfg.Section("obs")
Endpoint = sec.Key("ENDPOINT").MustString("112.95.163.82")
Endpoint = sec.Key("ENDPOINT").MustString("")
AccessKeyID = sec.Key("ACCESS_KEY_ID").MustString("")
SecretAccessKey = sec.Key("SECRET_ACCESS_KEY").MustString("")
Bucket = sec.Key("BUCKET").MustString("testopendata")
Location = sec.Key("LOCATION").MustString("cn-south-222")
BasePath = sec.Key("BASE_PATH").MustString("attachment/")
Bucket = sec.Key("BUCKET").MustString("")
Location = sec.Key("LOCATION").MustString("")
BasePath = sec.Key("BASE_PATH").MustString("")
TrainJobModelPath = sec.Key("TrainJobModel_Path").MustString("job/")
OutPutPath = sec.Key("Output_Path").MustString("output/")
CodePathPrefix = sec.Key("CODE_PATH_PREFIX").MustString("code/")
@@ -1268,17 +1270,17 @@ func NewContext() {
PROXYURL = sec.Key("PROXY_URL").MustString("")

sec = Cfg.Section("modelarts")
ModelArtsHost = sec.Key("ENDPOINT").MustString("112.95.163.80")
IamHost = sec.Key("IAMHOST").MustString("112.95.163.80")
ModelArtsHost = sec.Key("ENDPOINT").MustString("")
IamHost = sec.Key("IAMHOST").MustString("")
ProjectID = sec.Key("PROJECT_ID").MustString("")
ProjectName = sec.Key("PROJECT_NAME").MustString("")
ModelArtsUsername = sec.Key("USERNAME").MustString("")
ModelArtsPassword = sec.Key("PASSWORD").MustString("")
ModelArtsDomain = sec.Key("DOMAIN").MustString("cn-south-222")
ModelArtsDomain = sec.Key("DOMAIN").MustString("")
AllowedOrg = sec.Key("ORGANIZATION").MustString("")
ProfileID = sec.Key("PROFILE_ID").MustString("")
PoolInfos = sec.Key("POOL_INFOS").MustString("")
Flavor = sec.Key("FLAVOR").MustString("modelarts.bm.910.arm.public.2")
Flavor = sec.Key("FLAVOR").MustString("")
ResourcePools = sec.Key("Resource_Pools").MustString("")
Engines = sec.Key("Engines").MustString("")
EngineVersions = sec.Key("Engine_Versions").MustString("")
@@ -1286,10 +1288,10 @@ func NewContext() {
TrainJobFLAVORINFOS = sec.Key("TrainJob_FLAVOR_INFOS").MustString("")

sec = Cfg.Section("elk")
ElkUrl = sec.Key("ELKURL").MustString("http://192.168.207.35:5601/internal/bsearch")
ElkUser = sec.Key("ELKUSER").MustString("Qizhi")
ElkPassword = sec.Key("ELKPASSWORD").MustString("Pcl2020")
Index = sec.Key("INDEX").MustString("filebeat-7.3.2*")
ElkUrl = sec.Key("ELKURL").MustString("")
ElkUser = sec.Key("ELKUSER").MustString("")
ElkPassword = sec.Key("ELKPASSWORD").MustString("")
Index = sec.Key("INDEX").MustString("")
TimeField = sec.Key("TIMEFIELD").MustString(" @timestamptest")
ElkTimeFormat = sec.Key("ELKTIMEFORMAT").MustString("date_time")

@@ -1313,7 +1315,7 @@ func SetRadarMapConfig() {
RadarMap.CompletenessIssuesClosed = sec.Key("completeness_issues_closed").MustFloat64(0.2)
RadarMap.CompletenessReleases = sec.Key("completeness_releases").MustFloat64(0.3)
RadarMap.CompletenessDevelopAge = sec.Key("completeness_develop_age").MustFloat64(0.1)
RadarMap.CompletenessDataset = sec.Key("completeness_dataset").MustFloat64(0.1)
RadarMap.CompletenessDataset = sec.Key("completeness_dataset").MustFloat64(0)
RadarMap.CompletenessModel = sec.Key("completeness_model").MustFloat64(0.1)
RadarMap.CompletenessWiki = sec.Key("completeness_wiki").MustFloat64(0.1)
RadarMap.Liveness = sec.Key("liveness").MustFloat64(0.3)


+ 4
- 0
modules/storage/local.go View File

@@ -76,3 +76,7 @@ func (l *LocalStorage) PresignedPutURL(path string) (string, error) {
func (l *LocalStorage) HasObject(path string) (bool, error) {
return false, nil
}

func (l *LocalStorage) UploadObject(fileName, filePath string) error {
return nil
}

+ 6
- 0
modules/storage/minio.go View File

@@ -122,3 +122,9 @@ func (m *MinioStorage) HasObject(path string) (bool, error) {

return hasObject, nil
}

//upload object
func (m *MinioStorage) UploadObject(fileName, filePath string) error {
_, err := m.client.FPutObject(m.bucket, fileName, filePath, minio.PutObjectOptions{})
return err
}

+ 1
- 0
modules/storage/storage.go View File

@@ -26,6 +26,7 @@ type ObjectStorage interface {
PresignedGetURL(path string, fileName string) (string, error)
PresignedPutURL(path string) (string, error)
HasObject(path string) (bool, error)
UploadObject(fileName, filePath string) error
}

// Copy copys a file from source ObjectStorage to dest ObjectStorage


+ 33
- 2
routers/repo/cloudbrain.go View File

@@ -250,6 +250,7 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
}
repo := ctx.Repo.Repository
downloadCode(repo, codePath)
uploadCodeToMinio(codePath + "/", jobName, "/code/")

modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath
err = os.MkdirAll(modelPath, os.ModePerm)
@@ -268,16 +269,19 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) {
}
}
downloadRateCode(repo, jobName, setting.BenchmarkCode, benchmarkPath, form.BenchmarkCategory, gpuType)
uploadCodeToMinio(benchmarkPath + "/", jobName, cloudbrain.BenchMarkMountPath + "/")
}

snn4imagenetPath := setting.JobPath + jobName + cloudbrain.Snn4imagenetMountPath
if setting.IsSnn4imagenetEnabled && jobType == string(models.JobTypeSnn4imagenet) {
downloadRateCode(repo, jobName, setting.Snn4imagenetCode, snn4imagenetPath, "", "")
uploadCodeToMinio(snn4imagenetPath + "/", jobName, cloudbrain.Snn4imagenetMountPath + "/")
}

brainScorePath := setting.JobPath + jobName + cloudbrain.BrainScoreMountPath
if setting.IsBrainScoreEnabled && jobType == string(models.JobTypeBrainScore) {
downloadRateCode(repo, jobName, setting.BrainScoreCode, brainScorePath, "", "")
uploadCodeToMinio(brainScorePath + "/", jobName, cloudbrain.BrainScoreMountPath + "/")
}

err = cloudbrain.GenerateTask(ctx, jobName, image, command, uuid, codePath, modelPath, benchmarkPath, snn4imagenetPath, brainScorePath, jobType, gpuQueue, resourceSpecId)
@@ -713,8 +717,8 @@ func downloadRateCode(repo *models.Repository, taskName, gitPath, codePath, benc

command := "git clone " + gitPath + " " + codePath
cmd := exec.Command("/bin/bash", "-c", command)
output, err := cmd.Output()
log.Info(string(output))
_, err = cmd.Output()
if err != nil {
log.Error("exec.Command(%s) failed:%v", command, err)
return err
@@ -751,6 +755,33 @@ func downloadRateCode(repo *models.Repository, taskName, gitPath, codePath, benc
return nil
}

func uploadCodeToMinio(codePath, jobName, parentDir string) error {
files, err := readDir(codePath)
if err != nil {
log.Error("readDir(%s) failed: %s", codePath, err.Error())
return err
}

for _, file := range files {
if file.IsDir() {
if err = uploadCodeToMinio(codePath+file.Name()+"/", jobName, parentDir+file.Name()+"/"); err != nil {
log.Error("uploadCodeToMinio(%s) failed: %s", file.Name(), err.Error())
return err
}
} else {
destObject := setting.CBCodePathPrefix + jobName + parentDir + file.Name()
sourceFile := codePath + file.Name()
err = storage.Attachments.UploadObject(destObject, sourceFile)
if err != nil {
log.Error("UploadObject(%s) failed: %s", file.Name(), err.Error())
return err
}
}
}

return nil
}

func SyncCloudbrainStatus() {
cloudBrains, err := models.GetCloudBrainUnStoppedJob()
if err != nil {


+ 27
- 21
templates/base/head_navbar.tmpl View File

@@ -17,19 +17,23 @@

{{if .IsSigned}}

<div class="ui dropdown item">
{{.i18n.Tr "index"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a>
<a class="item" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a>
<a class="item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a>
<div class=" item" >
<div class="dropdown-menu">
<a class=" item" href="/dashboard">
<span > {{.i18n.Tr "index"}} &nbsp <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">
<div class="ui dropdown item" id='dropdown_explore'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>
<div class="menu">
@@ -43,24 +47,26 @@
</div>
</div>
{{else if .IsLandingPageHome}}


<div class="ui dropdown item">
{{.i18n.Tr "home"}}
<i class="dropdown icon"></i>
<div class="menu">
<!-- 未登录跳转登录界面 -->
<a class="item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "issues"}}</a>
<a class="item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "pull_requests"}}</a>
<a class="item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a>
<div class=" item">
<div class="dropdown-menu">
<a class=" item" href="/user/login">
<span > {{.i18n.Tr "home"}} &nbsp <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">
<div class="ui dropdown item" id='dropdown_PageHome'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>
<div class="menu">
<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>


+ 24
- 17
templates/base/head_navbar_fluid.tmpl View File

@@ -17,18 +17,22 @@

{{if .IsSigned}}
<div class="ui dropdown item">
{{.i18n.Tr "index"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a>
<a class="item" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a>
<a class="item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a>
<div class="item" >
<div class="dropdown-menu">
<a class=" item" href="/dashboard">
<span > {{.i18n.Tr "index"}} &nbsp <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">
<div class="ui dropdown item" id='dropdown_explore'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>
<div class="menu">
@@ -42,19 +46,22 @@
</div>
</div>
{{else if .IsLandingPageHome}}
<div class="ui dropdown item">
{{.i18n.Tr "home"}}
<i class="dropdown icon"></i>
<div class="menu">
<!-- 未登录跳转登录界面 -->
<a class="item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "issues"}}</a>
<a class="item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "pull_requests"}}</a>
<a class="item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a>
<div class="item" >
<div class="dropdown-menu">
<a class=" item" href="/user/login">
<span > {{.i18n.Tr "home"}} &nbsp <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">
<div class="ui dropdown item" id='dropdown_PageHome'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>
<div class="menu">


+ 25
- 19
templates/base/head_navbar_home.tmpl View File

@@ -9,18 +9,22 @@
</div>

{{if .IsSigned}}
<div class="ui dropdown item">
{{.i18n.Tr "index"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="{{AppSubUrl}}/issues">{{.i18n.Tr "issues"}}</a>
<a class="item" href="{{AppSubUrl}}/pulls">{{.i18n.Tr "pull_requests"}}</a>
<a class="item" href="{{AppSubUrl}}/milestones">{{.i18n.Tr "milestones"}}</a>
<div class="item" >
<div class="dropdown-menu">
<a class=" item" href="/dashboard">
<span > {{.i18n.Tr "index"}} &nbsp <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">
<div class="ui dropdown item" id='dropdown_explore'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>
<div class="menu">
@@ -34,21 +38,23 @@
</div>
</div>
{{else if .IsLandingPageHome}}

<div class="ui dropdown item">
{{.i18n.Tr "home"}}
<i class="dropdown icon"></i>
<div class="menu">
<!-- 未登录跳转登录界面 -->
<a class="item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "issues"}}</a>
<a class="item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "pull_requests"}}</a>
<a class="item" href="{{AppSubUrl}}/user/login">{{.i18n.Tr "milestones"}}</a>
<div class="item" >
<div class="dropdown-menu">
<a class=" item" href="/user/login">
<span > {{.i18n.Tr "home"}} &nbsp <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">
<div class="ui dropdown item" id='dropdown_PageHome'>
{{.i18n.Tr "explore"}}
<i class="dropdown icon"></i>
<div class="menu">


+ 9
- 0
web_src/js/index.js View File

@@ -2933,6 +2933,7 @@ $(document).ready(async () => {
initNotificationsTable();
initNotificationCount();
initTribute();
initDropDown();

// Repo clone url.
if ($('#repo-clone-url').length > 0) {
@@ -4100,3 +4101,11 @@ $.get(`${window.config.StaticUrlPrefix}/img/svg/icons.svg`, (data) => {
div.innerHTML = new XMLSerializer().serializeToString(data.documentElement);
document.body.insertBefore(div, document.body.childNodes[0]);
});
function initDropDown() {
$("#dropdown_PageHome").dropdown({
on:'hover' ,//鼠标悬浮显示,默认值是click
});
$("#dropdown_explore").dropdown({
on:'hover' ,//鼠标悬浮显示,默认值是click
});
}

Loading…
Cancel
Save