diff --git a/models/repo.go b/models/repo.go index 5f90f97fc..6b3df9fe0 100755 --- a/models/repo.go +++ b/models/repo.go @@ -1133,6 +1133,9 @@ func IsUsableRepoAlias(name string) error { // CreateRepository creates a repository for the user/organization. func CreateRepository(ctx DBContext, doer, u *User, repo *Repository, opts ...CreateRepoOptions) (err error) { + if repo.Alias == "" { + repo.Alias = repo.Name + } repo.LowerAlias = strings.ToLower(repo.Alias) if err = IsUsableRepoName(repo.Name); err != nil { return err diff --git a/modules/context/auth.go b/modules/context/auth.go index 9877657eb..61a7b029b 100755 --- a/modules/context/auth.go +++ b/modules/context/auth.go @@ -64,6 +64,11 @@ func Toggle(options *ToggleOptions) macaron.Handler { ctx.Redirect(setting.AppSubURL + "/") return } + + if ctx.QueryBool("course") { + ctx.Redirect(setting.AppSubURL + "/" + setting.Course.OrgName) + return + } } // Redirect to dashboard if user tries to visit any non-login page. diff --git a/modules/context/context.go b/modules/context/context.go index fd980fc6d..65f4b3f5d 100755 --- a/modules/context/context.go +++ b/modules/context/context.go @@ -45,8 +45,8 @@ type Context struct { IsSigned bool IsBasicAuth bool - Repo *Repository - Org *Organization + Repo *Repository + Org *Organization Cloudbrain *models.Cloudbrain } @@ -347,9 +347,9 @@ func Contexter() macaron.Handler { ctx.Data["EnableSwagger"] = setting.API.EnableSwagger ctx.Data["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn - notice, _ := notice.GetNewestNotice() - if notice != nil { - ctx.Data["notice"] = *notice + notices, _ := notice.GetNewestNotice() + if notices != nil { + ctx.Data["notices"] = notices } c.Map(ctx) } diff --git a/modules/storage/obs.go b/modules/storage/obs.go index a68bb7771..8e6b4201b 100755 --- a/modules/storage/obs.go +++ b/modules/storage/obs.go @@ -57,8 +57,8 @@ func ObsHasObject(path string) (bool, error) { return hasObject, nil } -func GetObsPartInfos(uuid string, uploadID string) (string, error) { - key := strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, uuid)), "/") +func GetObsPartInfos(uuid, uploadID, fileName string) (string, error) { + key := strings.TrimPrefix(path.Join(setting.BasePath, path.Join(uuid[0:1], uuid[1:2], uuid, fileName)), "/") output, err := ObsCli.ListParts(&obs.ListPartsInput{ Bucket: setting.Bucket, diff --git a/modules/structs/repo.go b/modules/structs/repo.go index e290488a4..6e9ece4b0 100755 --- a/modules/structs/repo.go +++ b/modules/structs/repo.go @@ -100,6 +100,10 @@ type CreateRepoOption struct { // required: true // unique: true Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(100)"` + // Alias of the repository to create + // required: false + // unique: true + Alias string `json:"alias" binding:"AlphaDashDotChinese;MaxSize(100)"` // Description of the repository to create Description string `json:"description" binding:"MaxSize(255)"` // Whether the repository is private diff --git a/modules/validation/binding.go b/modules/validation/binding.go index b608cdea2..d52919475 100644 --- a/modules/validation/binding.go +++ b/modules/validation/binding.go @@ -128,6 +128,9 @@ func addAlphaDashDotChineseRule() { return strings.HasPrefix(rule, "AlphaDashDotChinese") }, IsValid: func(errs binding.Errors, name string, val interface{}) (bool, binding.Errors) { + if val == "" { + return true, errs + } if !ValidAlphaDashDotChinese(fmt.Sprintf("%v", val)) { errs.Add([]string{name}, ErrAlphaDashDotChinese, "ErrAlphaDashDotChinese") return false, errs diff --git a/routers/api/v1/repo/repo.go b/routers/api/v1/repo/repo.go index a724ebcc3..a85f88cb8 100755 --- a/routers/api/v1/repo/repo.go +++ b/routers/api/v1/repo/repo.go @@ -232,6 +232,7 @@ func CreateUserRepo(ctx *context.APIContext, owner *models.User, opt api.CreateR } repo, err := repo_service.CreateRepository(ctx.User, owner, models.CreateRepoOptions{ Name: opt.Name, + Alias: opt.Alias, Description: opt.Description, IssueLabels: opt.IssueLabels, Gitignores: opt.Gitignores, diff --git a/routers/notice/notice.go b/routers/notice/notice.go index f1e996e2d..5a39ee684 100644 --- a/routers/notice/notice.go +++ b/routers/notice/notice.go @@ -16,27 +16,31 @@ const ( ) type Notice struct { - Title string - Link string - Visible int //0 invisible, 1 visible + Title string + Link string + Visible int //0 invisible, 1 visible +} + +type NoticeResponse struct { + Notices []*Notice CommitId string } var lock int32 = 0 -func GetNewestNotice() (*Notice, error) { +func GetNewestNotice() (*NoticeResponse, error) { defer func() { if err := recover(); err != nil { log.Error("recover error", err) } }() - var notice *Notice + var notice *NoticeResponse var err error if setting.CacheOn { - notice, err = getNewestNoticeFromCacheAndDisk() + notice, err = getNewestNoticesFromCacheAndDisk() } else { - notice, err = getNewestNoticeFromDisk() + notice, err = getNewestNoticesFromDisk() } if err != nil { @@ -49,34 +53,39 @@ func getNoticeTimeout() time.Duration { return time.Duration(setting.CacheTimeOutSecond) * time.Second } -func getNewestNoticeFromDisk() (*Notice, error) { +func getNewestNoticesFromDisk() (*NoticeResponse, error) { log.Debug("Get notice from disk") - repoFile, err := models.ReadLatestFileInRepo(setting.UserNameOfNoticeRepo, setting.RepoNameOfNoticeRepo, setting.RefNameOfNoticeRepo, setting.TreePathOfNoticeRepo) + repo, err := models.GetRepositoryByOwnerAndAlias(setting.UserNameOfNoticeRepo, setting.RepoNameOfNoticeRepo) + if err != nil { + log.Error("get notice repo failed, error=%v", err) + return nil, err + } + repoFile, err := models.ReadLatestFileInRepo(repo.OwnerName, repo.Name, setting.RefNameOfNoticeRepo, setting.TreePathOfNoticeRepo) if err != nil { log.Error("GetNewestNotice failed, error=%v", err) return nil, err } - notice := &Notice{} - json.Unmarshal(repoFile.Content, notice) - if notice.Title == "" { + res := &NoticeResponse{} + json.Unmarshal(repoFile.Content, res) + if res == nil || len(res.Notices) == 0 { return nil, err } - notice.CommitId = repoFile.CommitId - return notice, nil + res.CommitId = repoFile.CommitId + return res, nil } -func getNewestNoticeFromCacheAndDisk() (*Notice, error) { +func getNewestNoticesFromCacheAndDisk() (*NoticeResponse, error) { v, success := noticeCache.Get(NOTICE_CACHE_KEY) if success { log.Debug("Get notice from cache,value = %v", v) if v == nil { return nil, nil } - n := v.(*Notice) + n := v.(*NoticeResponse) return n, nil } - notice, err := getNewestNoticeFromDisk() + notice, err := getNewestNoticesFromDisk() if err != nil { log.Error("GetNewestNotice failed, error=%v", err) noticeCache.Set(NOTICE_CACHE_KEY, nil, 30*time.Second) diff --git a/routers/repo/attachment.go b/routers/repo/attachment.go index 8443d6488..c2d096416 100755 --- a/routers/repo/attachment.go +++ b/routers/repo/attachment.go @@ -542,7 +542,7 @@ func GetSuccessChunks(ctx *context.Context) { log.Error("GetPartInfos failed:%v", err.Error()) } } else { - chunks, err = storage.GetObsPartInfos(fileChunk.UUID, fileChunk.UploadID) + chunks, err = storage.GetObsPartInfos(fileChunk.UUID, fileChunk.UploadID, fileName) if err != nil { log.Error("GetObsPartInfos failed:%v", err.Error()) } diff --git a/routers/user/auth.go b/routers/user/auth.go index 16af84b66..a02cf24dc 100755 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -116,8 +116,16 @@ func checkAutoLogin(ctx *context.Context) bool { } if isSucceed { + + isCourse := ctx.QueryBool("course") ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true) - ctx.RedirectToFirst(redirectTo, setting.AppSubURL+string(setting.LandingPageURL)) + if redirectTo == "" && isCourse { + redirectToCourse := setting.AppSubURL + "/" + setting.Course.OrgName + ctx.RedirectToFirst(redirectToCourse) + } else { + ctx.RedirectToFirst(redirectTo, setting.AppSubURL+string(setting.LandingPageURL)) + + } return true } @@ -143,6 +151,7 @@ func SignIn(ctx *context.Context) { ctx.Data["Title"] = ctx.Tr("sign_in") ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login" ctx.Data["PageIsSignIn"] = true + ctx.Data["IsCourse"] = ctx.QueryBool("course") ctx.Data["PageIsLogin"] = true ctx.Data["EnableSSPI"] = models.IsSSPIEnabled() ctx.Data["EnableCloudBrain"] = true @@ -182,6 +191,7 @@ func SignInPost(ctx *context.Context, form auth.SignInForm) { ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login" ctx.Data["PageIsSignIn"] = true ctx.Data["PageIsLogin"] = true + ctx.Data["IsCourse"] = ctx.QueryBool("course") ctx.Data["EnableSSPI"] = models.IsSSPIEnabled() if ctx.HasError() { @@ -565,6 +575,12 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR return setting.AppSubURL + "/dashboard" } + isCourse := ctx.QueryBool("course") + if isCourse { + redirectToCourse := setting.AppSubURL + "/" + setting.Course.OrgName + ctx.RedirectToFirst(redirectToCourse) + return redirectToCourse + } if redirectTo := ctx.GetCookie("redirect_to"); len(redirectTo) > 0 && !util.IsExternalURL(redirectTo) { ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true) if obeyRedirect { diff --git a/templates/base/head.tmpl b/templates/base/head.tmpl index 859cacb62..10015a61b 100755 --- a/templates/base/head.tmpl +++ b/templates/base/head.tmpl @@ -200,16 +200,7 @@ var _hmt = _hmt || []; - - - + {{template "base/head_notice" .}} {{end}} {{/* @@ -233,7 +224,15 @@ var _hmt = _hmt || []; }else{ isNewNotice=false; } - if (JSON.parse("{{.notice.Visible}}")){ + let isShowNoticeTag = false; + let notices= {{.notices.Notices}} + for (i =0;i {{template "base/head_navbar_fluid" .}} - + {{template "base/head_notice" .}} {{end}} {{/* @@ -232,7 +225,15 @@ var _hmt = _hmt || []; }else{ isNewNotice=false; } - if (JSON.parse("{{.notice.Visible}}")){ + let isShowNoticeTag = false; + let notices= {{.notices.Notices}} + for (i =0;i {{template "base/head_navbar" .}} - + {{template "base/head_notice" .}} {{end}} {{/* @@ -236,7 +229,15 @@ var _hmt = _hmt || []; }else{ isNewNotice=false; } - if (JSON.parse("{{.notice.Visible}}")){ + let isShowNoticeTag = false; + let notices= {{.notices.Notices}} + for (i =0;i {{if .ShowRegistrationButton}} - - {{svg "octicon-person" 16}} {{.i18n.Tr "register"}} + {{if .IsCourse}} + + {{svg "octicon-person" 16}} {{.i18n.Tr "register"}} + + {{else}} + + {{svg "octicon-person" 16}} {{.i18n.Tr "register"}} + + {{end}} + {{end}} + {{if .IsCourse}} + + {{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} + + {{else}} + + {{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} {{end}} - - {{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} - {{end}} diff --git a/templates/base/head_notice.tmpl b/templates/base/head_notice.tmpl new file mode 100644 index 000000000..88615cc38 --- /dev/null +++ b/templates/base/head_notice.tmpl @@ -0,0 +1,32 @@ +{{if not .IsCourse}} + {{ if .notices}} +
+
+ + {{ $firstTag := true }} + {{range .notices.Notices}} + {{if eq .Visible 1}} + {{if $firstTag}} + + + {{.Title}} + + {{else}} + + + {{.Title}} + + {{end}} + {{ $firstTag = false }} + {{end}} + {{end}} + + +
+ +
+
+ +
+ {{end}} +{{end}} \ No newline at end of file diff --git a/templates/base/head_pro.tmpl b/templates/base/head_pro.tmpl index e6dbfc03e..85719cf9b 100644 --- a/templates/base/head_pro.tmpl +++ b/templates/base/head_pro.tmpl @@ -201,14 +201,7 @@ var _hmt = _hmt || []; - + {{template "base/head_notice" .}} {{end}} {{/* @@ -233,7 +226,15 @@ var _hmt = _hmt || []; }else{ isNewNotice=false; } - if (JSON.parse("{{.notice.Visible}}")){ + let isShowNoticeTag = false; + let notices= {{.notices.Notices}} + for (i =0;i {{range .Topics}} - {{if ne . "" }}{{.}}{{end}} + {{if ne . "" }}{{.}}{{end}} {{end}} diff --git a/templates/org/home_courses.tmpl b/templates/org/home_courses.tmpl index df164bd89..dd287c87f 100644 --- a/templates/org/home_courses.tmpl +++ b/templates/org/home_courses.tmpl @@ -136,11 +136,7 @@ @@ -209,7 +205,7 @@ {{if .IsSigned}} {{.i18n.Tr "org.teams.join_teams"}} {{else}} - {{.i18n.Tr "org.teams.join_teams"}} + {{.i18n.Tr "org.teams.join_teams"}} {{end}} diff --git a/templates/user/auth/signin_inner.tmpl b/templates/user/auth/signin_inner.tmpl index a827bde9e..bdcd6a5c6 100644 --- a/templates/user/auth/signin_inner.tmpl +++ b/templates/user/auth/signin_inner.tmpl @@ -29,7 +29,11 @@
-
+ {{if .IsCourse}} + + {{else}} + + {{end}} {{.CsrfTokenHtml}}
diff --git a/web_src/js/components/ObsUploader.vue b/web_src/js/components/ObsUploader.vue index 3b5bd3162..b20594b86 100755 --- a/web_src/js/components/ObsUploader.vue +++ b/web_src/js/components/ObsUploader.vue @@ -350,6 +350,16 @@ export default { etags[currentChunk] = res.headers.etag; } + async function uploadMinioNewMethod(url,e){ + var xhr = new XMLHttpRequest(); + xhr.open('PUT', url, false); + xhr.setRequestHeader('Content-Type', '') + xhr.send(e.target.result); + var etagValue = xhr.getResponseHeader('ETag'); + //console.log(etagValue); + etags[currentChunk] = etagValue; + } + async function updateChunk(currentChunk) { await axios.post( '/attachments/update_chunk', @@ -372,7 +382,7 @@ export default { await getUploadChunkUrl(currentChunk, partSize); if (urls[currentChunk] != '') { // 上传到minio - await uploadMinio(urls[currentChunk], e); + await uploadMinioNewMethod(urls[currentChunk], e); if (etags[currentChunk] != '') { // 更新数据库:分片上传结果 //await updateChunk(currentChunk); diff --git a/web_src/less/openi.less b/web_src/less/openi.less index 39789d9d9..1d165dda8 100644 --- a/web_src/less/openi.less +++ b/web_src/less/openi.less @@ -604,10 +604,13 @@ display: block; font-weight: bold !important; } .a_width{ - width: 50% !important; - display:inline-block !important; + // width: 50% !important; + margin-left: 20em; + // display:inline-block !important; +} +.a_width i{ + vertical-align:middle!important; } - .footer_icon{ display: inline-block !important; vertical-align: middle !important;