@@ -1133,6 +1133,9 @@ func IsUsableRepoAlias(name string) error { | |||||
// CreateRepository creates a repository for the user/organization. | // CreateRepository creates a repository for the user/organization. | ||||
func CreateRepository(ctx DBContext, doer, u *User, repo *Repository, opts ...CreateRepoOptions) (err error) { | 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) | repo.LowerAlias = strings.ToLower(repo.Alias) | ||||
if err = IsUsableRepoName(repo.Name); err != nil { | if err = IsUsableRepoName(repo.Name); err != nil { | ||||
return err | return err | ||||
@@ -64,6 +64,11 @@ func Toggle(options *ToggleOptions) macaron.Handler { | |||||
ctx.Redirect(setting.AppSubURL + "/") | ctx.Redirect(setting.AppSubURL + "/") | ||||
return | 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. | // Redirect to dashboard if user tries to visit any non-login page. | ||||
@@ -45,8 +45,8 @@ type Context struct { | |||||
IsSigned bool | IsSigned bool | ||||
IsBasicAuth bool | IsBasicAuth bool | ||||
Repo *Repository | |||||
Org *Organization | |||||
Repo *Repository | |||||
Org *Organization | |||||
Cloudbrain *models.Cloudbrain | Cloudbrain *models.Cloudbrain | ||||
} | } | ||||
@@ -347,9 +347,9 @@ func Contexter() macaron.Handler { | |||||
ctx.Data["EnableSwagger"] = setting.API.EnableSwagger | ctx.Data["EnableSwagger"] = setting.API.EnableSwagger | ||||
ctx.Data["EnableOpenIDSignIn"] = setting.Service.EnableOpenIDSignIn | 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) | c.Map(ctx) | ||||
} | } | ||||
@@ -57,8 +57,8 @@ func ObsHasObject(path string) (bool, error) { | |||||
return hasObject, nil | 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{ | output, err := ObsCli.ListParts(&obs.ListPartsInput{ | ||||
Bucket: setting.Bucket, | Bucket: setting.Bucket, | ||||
@@ -100,6 +100,10 @@ type CreateRepoOption struct { | |||||
// required: true | // required: true | ||||
// unique: true | // unique: true | ||||
Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(100)"` | 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 of the repository to create | ||||
Description string `json:"description" binding:"MaxSize(255)"` | Description string `json:"description" binding:"MaxSize(255)"` | ||||
// Whether the repository is private | // Whether the repository is private | ||||
@@ -128,6 +128,9 @@ func addAlphaDashDotChineseRule() { | |||||
return strings.HasPrefix(rule, "AlphaDashDotChinese") | return strings.HasPrefix(rule, "AlphaDashDotChinese") | ||||
}, | }, | ||||
IsValid: func(errs binding.Errors, name string, val interface{}) (bool, binding.Errors) { | IsValid: func(errs binding.Errors, name string, val interface{}) (bool, binding.Errors) { | ||||
if val == "" { | |||||
return true, errs | |||||
} | |||||
if !ValidAlphaDashDotChinese(fmt.Sprintf("%v", val)) { | if !ValidAlphaDashDotChinese(fmt.Sprintf("%v", val)) { | ||||
errs.Add([]string{name}, ErrAlphaDashDotChinese, "ErrAlphaDashDotChinese") | errs.Add([]string{name}, ErrAlphaDashDotChinese, "ErrAlphaDashDotChinese") | ||||
return false, errs | return false, errs | ||||
@@ -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{ | repo, err := repo_service.CreateRepository(ctx.User, owner, models.CreateRepoOptions{ | ||||
Name: opt.Name, | Name: opt.Name, | ||||
Alias: opt.Alias, | |||||
Description: opt.Description, | Description: opt.Description, | ||||
IssueLabels: opt.IssueLabels, | IssueLabels: opt.IssueLabels, | ||||
Gitignores: opt.Gitignores, | Gitignores: opt.Gitignores, | ||||
@@ -16,27 +16,31 @@ const ( | |||||
) | ) | ||||
type Notice struct { | 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 | CommitId string | ||||
} | } | ||||
var lock int32 = 0 | var lock int32 = 0 | ||||
func GetNewestNotice() (*Notice, error) { | |||||
func GetNewestNotice() (*NoticeResponse, error) { | |||||
defer func() { | defer func() { | ||||
if err := recover(); err != nil { | if err := recover(); err != nil { | ||||
log.Error("recover error", err) | log.Error("recover error", err) | ||||
} | } | ||||
}() | }() | ||||
var notice *Notice | |||||
var notice *NoticeResponse | |||||
var err error | var err error | ||||
if setting.CacheOn { | if setting.CacheOn { | ||||
notice, err = getNewestNoticeFromCacheAndDisk() | |||||
notice, err = getNewestNoticesFromCacheAndDisk() | |||||
} else { | } else { | ||||
notice, err = getNewestNoticeFromDisk() | |||||
notice, err = getNewestNoticesFromDisk() | |||||
} | } | ||||
if err != nil { | if err != nil { | ||||
@@ -49,34 +53,39 @@ func getNoticeTimeout() time.Duration { | |||||
return time.Duration(setting.CacheTimeOutSecond) * time.Second | return time.Duration(setting.CacheTimeOutSecond) * time.Second | ||||
} | } | ||||
func getNewestNoticeFromDisk() (*Notice, error) { | |||||
func getNewestNoticesFromDisk() (*NoticeResponse, error) { | |||||
log.Debug("Get notice from disk") | 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 { | if err != nil { | ||||
log.Error("GetNewestNotice failed, error=%v", err) | log.Error("GetNewestNotice failed, error=%v", err) | ||||
return nil, 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 | 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) | v, success := noticeCache.Get(NOTICE_CACHE_KEY) | ||||
if success { | if success { | ||||
log.Debug("Get notice from cache,value = %v", v) | log.Debug("Get notice from cache,value = %v", v) | ||||
if v == nil { | if v == nil { | ||||
return nil, nil | return nil, nil | ||||
} | } | ||||
n := v.(*Notice) | |||||
n := v.(*NoticeResponse) | |||||
return n, nil | return n, nil | ||||
} | } | ||||
notice, err := getNewestNoticeFromDisk() | |||||
notice, err := getNewestNoticesFromDisk() | |||||
if err != nil { | if err != nil { | ||||
log.Error("GetNewestNotice failed, error=%v", err) | log.Error("GetNewestNotice failed, error=%v", err) | ||||
noticeCache.Set(NOTICE_CACHE_KEY, nil, 30*time.Second) | noticeCache.Set(NOTICE_CACHE_KEY, nil, 30*time.Second) | ||||
@@ -542,7 +542,7 @@ func GetSuccessChunks(ctx *context.Context) { | |||||
log.Error("GetPartInfos failed:%v", err.Error()) | log.Error("GetPartInfos failed:%v", err.Error()) | ||||
} | } | ||||
} else { | } else { | ||||
chunks, err = storage.GetObsPartInfos(fileChunk.UUID, fileChunk.UploadID) | |||||
chunks, err = storage.GetObsPartInfos(fileChunk.UUID, fileChunk.UploadID, fileName) | |||||
if err != nil { | if err != nil { | ||||
log.Error("GetObsPartInfos failed:%v", err.Error()) | log.Error("GetObsPartInfos failed:%v", err.Error()) | ||||
} | } | ||||
@@ -116,8 +116,16 @@ func checkAutoLogin(ctx *context.Context) bool { | |||||
} | } | ||||
if isSucceed { | if isSucceed { | ||||
isCourse := ctx.QueryBool("course") | |||||
ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true) | 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 | return true | ||||
} | } | ||||
@@ -143,6 +151,7 @@ func SignIn(ctx *context.Context) { | |||||
ctx.Data["Title"] = ctx.Tr("sign_in") | ctx.Data["Title"] = ctx.Tr("sign_in") | ||||
ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login" | ctx.Data["SignInLink"] = setting.AppSubURL + "/user/login" | ||||
ctx.Data["PageIsSignIn"] = true | ctx.Data["PageIsSignIn"] = true | ||||
ctx.Data["IsCourse"] = ctx.QueryBool("course") | |||||
ctx.Data["PageIsLogin"] = true | ctx.Data["PageIsLogin"] = true | ||||
ctx.Data["EnableSSPI"] = models.IsSSPIEnabled() | ctx.Data["EnableSSPI"] = models.IsSSPIEnabled() | ||||
ctx.Data["EnableCloudBrain"] = true | 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["SignInLink"] = setting.AppSubURL + "/user/login" | ||||
ctx.Data["PageIsSignIn"] = true | ctx.Data["PageIsSignIn"] = true | ||||
ctx.Data["PageIsLogin"] = true | ctx.Data["PageIsLogin"] = true | ||||
ctx.Data["IsCourse"] = ctx.QueryBool("course") | |||||
ctx.Data["EnableSSPI"] = models.IsSSPIEnabled() | ctx.Data["EnableSSPI"] = models.IsSSPIEnabled() | ||||
if ctx.HasError() { | if ctx.HasError() { | ||||
@@ -565,6 +575,12 @@ func handleSignInFull(ctx *context.Context, u *models.User, remember bool, obeyR | |||||
return setting.AppSubURL + "/dashboard" | 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) { | if redirectTo := ctx.GetCookie("redirect_to"); len(redirectTo) > 0 && !util.IsExternalURL(redirectTo) { | ||||
ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true) | ctx.SetCookie("redirect_to", "", -1, setting.AppSubURL, "", setting.SessionConfig.Secure, true) | ||||
if obeyRedirect { | if obeyRedirect { | ||||
@@ -200,16 +200,7 @@ var _hmt = _hmt || []; | |||||
<div class="ui top secondary stackable main menu following bar dark"> | <div class="ui top secondary stackable main menu following bar dark"> | ||||
{{template "base/head_navbar" .}} | {{template "base/head_navbar" .}} | ||||
</div><!-- end bar --> | </div><!-- end bar --> | ||||
<!-- {{if not .IsCourse}} --> | |||||
<div class="notic_content" id ="notic_content" style="display: none;"> | |||||
<a href={{.notice.Link}} class="a_width"> | |||||
<marquee behavior="scroll" direction="left"> | |||||
{{.notice.Title}} | |||||
</marquee> | |||||
</a> | |||||
<i class="ri-close-fill x_icon" onclick="closeNoice()"></i> | |||||
</div> | |||||
<!-- {{end}} --> | |||||
{{template "base/head_notice" .}} | |||||
{{end}} | {{end}} | ||||
{{/* | {{/* | ||||
</div> | </div> | ||||
@@ -233,7 +224,15 @@ var _hmt = _hmt || []; | |||||
}else{ | }else{ | ||||
isNewNotice=false; | isNewNotice=false; | ||||
} | } | ||||
if (JSON.parse("{{.notice.Visible}}")){ | |||||
let isShowNoticeTag = false; | |||||
let notices= {{.notices.Notices}} | |||||
for (i =0;i<notices.length;i++){ | |||||
if (notices[i].Visible==1){ | |||||
isShowNoticeTag =true; | |||||
break; | |||||
} | |||||
} | |||||
if (isShowNoticeTag){ | |||||
if(isNewNotice){ | if(isNewNotice){ | ||||
document.getElementById("notic_content").style.display='block' | document.getElementById("notic_content").style.display='block' | ||||
}else{ | }else{ | ||||
@@ -249,6 +248,7 @@ var _hmt = _hmt || []; | |||||
document.getElementById("notic_content").style.display='none' | document.getElementById("notic_content").style.display='none' | ||||
} | } | ||||
} | } | ||||
if(!("{{.IsCourse}}" == true || "{{.IsCourse}}" =='true')) { | if(!("{{.IsCourse}}" == true || "{{.IsCourse}}" =='true')) { | ||||
isShowNotice(); | isShowNotice(); | ||||
} | } | ||||
@@ -201,14 +201,7 @@ var _hmt = _hmt || []; | |||||
<div class="ui top secondary stackable main menu following bar dark"> | <div class="ui top secondary stackable main menu following bar dark"> | ||||
{{template "base/head_navbar_fluid" .}} | {{template "base/head_navbar_fluid" .}} | ||||
</div><!-- end bar --> | </div><!-- end bar --> | ||||
<div class="notic_content" id ="notic_content" style="display: none;"> | |||||
<a href={{.notice.Link}} class="a_width"> | |||||
<marquee behavior="scroll" direction="left"> | |||||
{{.notice.Title}} | |||||
</marquee> | |||||
</a> | |||||
<i class="ri-close-fill x_icon" onclick="closeNoice()"></i> | |||||
</div> | |||||
{{template "base/head_notice" .}} | |||||
{{end}} | {{end}} | ||||
{{/* | {{/* | ||||
</div> | </div> | ||||
@@ -232,7 +225,15 @@ var _hmt = _hmt || []; | |||||
}else{ | }else{ | ||||
isNewNotice=false; | isNewNotice=false; | ||||
} | } | ||||
if (JSON.parse("{{.notice.Visible}}")){ | |||||
let isShowNoticeTag = false; | |||||
let notices= {{.notices.Notices}} | |||||
for (i =0;i<notices.length;i++){ | |||||
if (notices[i].Visible==1){ | |||||
isShowNoticeTag =true; | |||||
break; | |||||
} | |||||
} | |||||
if (isShowNoticeTag){ | |||||
if(isNewNotice){ | if(isNewNotice){ | ||||
document.getElementById("notic_content").style.display='block' | document.getElementById("notic_content").style.display='block' | ||||
}else{ | }else{ | ||||
@@ -248,6 +249,7 @@ var _hmt = _hmt || []; | |||||
document.getElementById("notic_content").style.display='none' | document.getElementById("notic_content").style.display='none' | ||||
} | } | ||||
} | } | ||||
if(!("{{.IsCourse}}" == true || "{{.IsCourse}}" =='true')) { | if(!("{{.IsCourse}}" == true || "{{.IsCourse}}" =='true')) { | ||||
isShowNotice(); | isShowNotice(); | ||||
} | } |
@@ -205,14 +205,7 @@ var _hmt = _hmt || []; | |||||
<div class="ui top secondary stackable main menu following bar dark"> | <div class="ui top secondary stackable main menu following bar dark"> | ||||
{{template "base/head_navbar" .}} | {{template "base/head_navbar" .}} | ||||
</div><!-- end bar --> | </div><!-- end bar --> | ||||
<div class="notic_content" id ="notic_content" style="display: none;" > | |||||
<a href={{.notice.Link}} class="a_width"> | |||||
<marquee behavior="scroll" direction="left"> | |||||
{{.notice.Title}} | |||||
</marquee> | |||||
</a> | |||||
<i class="ri-close-fill x_icon" onclick="closeNoice()"></i> | |||||
</div> | |||||
{{template "base/head_notice" .}} | |||||
{{end}} | {{end}} | ||||
{{/* | {{/* | ||||
</div> | </div> | ||||
@@ -236,7 +229,15 @@ var _hmt = _hmt || []; | |||||
}else{ | }else{ | ||||
isNewNotice=false; | isNewNotice=false; | ||||
} | } | ||||
if (JSON.parse("{{.notice.Visible}}")){ | |||||
let isShowNoticeTag = false; | |||||
let notices= {{.notices.Notices}} | |||||
for (i =0;i<notices.length;i++){ | |||||
if (notices[i].Visible==1){ | |||||
isShowNoticeTag =true; | |||||
break; | |||||
} | |||||
} | |||||
if (isShowNoticeTag){ | |||||
if(isNewNotice){ | if(isNewNotice){ | ||||
document.getElementById("notic_content").style.display='block' | document.getElementById("notic_content").style.display='block' | ||||
}else{ | }else{ | ||||
@@ -252,6 +253,7 @@ var _hmt = _hmt || []; | |||||
document.getElementById("notic_content").style.display='none' | document.getElementById("notic_content").style.display='none' | ||||
} | } | ||||
} | } | ||||
if(!("{{.IsCourse}}" == true || "{{.IsCourse}}" =='true')) { | if(!("{{.IsCourse}}" == true || "{{.IsCourse}}" =='true')) { | ||||
isShowNotice(); | isShowNotice(); | ||||
} | } |
@@ -211,13 +211,25 @@ | |||||
</div> | </div> | ||||
</form> | </form> | ||||
{{if .ShowRegistrationButton}} | {{if .ShowRegistrationButton}} | ||||
<a class="item{{if .PageIsSignUp}} active{{end}}" href="{{AppSubUrl}}/user/sign_up"> | |||||
{{svg "octicon-person" 16}} {{.i18n.Tr "register"}} | |||||
{{if .IsCourse}} | |||||
<a class="item{{if .PageIsSignUp}} active{{end}}" href="https://git.openi.org.cn/user/sign_up" target="_blank"> | |||||
{{svg "octicon-person" 16}} {{.i18n.Tr "register"}} | |||||
</a> | |||||
{{else}} | |||||
<a class="item{{if .PageIsSignUp}} active{{end}}" href="{{AppSubUrl}}/user/sign_up"> | |||||
{{svg "octicon-person" 16}} {{.i18n.Tr "register"}} | |||||
</a> | |||||
{{end}} | |||||
{{end}} | |||||
{{if .IsCourse}} | |||||
<a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="https://git.openi.org.cn/user/login?course=true" target="_blank"> | |||||
{{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} | |||||
</a> | |||||
{{else}} | |||||
<a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login"> | |||||
{{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} | |||||
</a> | </a> | ||||
{{end}} | {{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 --> | </div><!-- end anonymous right menu --> | ||||
{{end}} | {{end}} | ||||
@@ -0,0 +1,32 @@ | |||||
{{if not .IsCourse}} | |||||
{{ if .notices}} | |||||
<div class="notic_content" id ="notic_content" style="display: block; position: relative"> | |||||
<diV class="ui container"> | |||||
<marquee behavior="scroll" direction="left"> | |||||
{{ $firstTag := true }} | |||||
{{range .notices.Notices}} | |||||
{{if eq .Visible 1}} | |||||
{{if $firstTag}} | |||||
<a href={{.Link}} class="a_width" style = 'margin-left: 0px !important;' target="_blank"> | |||||
<i class="ri-arrow-right-s-line"></i> | |||||
{{.Title}} | |||||
</a> | |||||
{{else}} | |||||
<a href={{.Link}} class="a_width" target="_blank"> | |||||
<i class="ri-arrow-right-s-line"></i> | |||||
{{.Title}} | |||||
</a> | |||||
{{end}} | |||||
{{ $firstTag = false }} | |||||
{{end}} | |||||
{{end}} | |||||
</marquee> | |||||
<div class="item right" style="position:absolute;right: 1px;top:0px;"> | |||||
<i class="ri-close-fill x_icon" onclick="closeNoice()"></i> | |||||
</div> | |||||
</diV> | |||||
</div> | |||||
{{end}} | |||||
{{end}} |
@@ -201,14 +201,7 @@ var _hmt = _hmt || []; | |||||
<div class="ui top secondary stackable main menu following bar dark"> | <div class="ui top secondary stackable main menu following bar dark"> | ||||
{{template "base/head_navbar_pro" .}} | {{template "base/head_navbar_pro" .}} | ||||
</div><!-- end bar --> | </div><!-- end bar --> | ||||
<div class="notic_content" id ="notic_content" style="display: none;" > | |||||
<a href={{.notice.Link}} class="a_width"> | |||||
<marquee behavior="scroll" direction="left"> | |||||
{{.notice.Title}} | |||||
</marquee> | |||||
</a> | |||||
<i class="icon icon-octicon x_icon" onclick="closeNoice()">{{svg "octicon-x" 16}}</i> | |||||
</div> | |||||
{{template "base/head_notice" .}} | |||||
{{end}} | {{end}} | ||||
{{/* | {{/* | ||||
</div> | </div> | ||||
@@ -233,7 +226,15 @@ var _hmt = _hmt || []; | |||||
}else{ | }else{ | ||||
isNewNotice=false; | isNewNotice=false; | ||||
} | } | ||||
if (JSON.parse("{{.notice.Visible}}")){ | |||||
let isShowNoticeTag = false; | |||||
let notices= {{.notices.Notices}} | |||||
for (i =0;i<notices.length;i++){ | |||||
if (notices[i].Visible==1){ | |||||
isShowNoticeTag =true; | |||||
break; | |||||
} | |||||
} | |||||
if (isShowNoticeTag){ | |||||
if(isNewNotice){ | if(isNewNotice){ | ||||
document.getElementById("notic_content").style.display='block' | document.getElementById("notic_content").style.display='block' | ||||
}else{ | }else{ | ||||
@@ -249,6 +250,7 @@ var _hmt = _hmt || []; | |||||
document.getElementById("notic_content").style.display='none' | document.getElementById("notic_content").style.display='none' | ||||
} | } | ||||
} | } | ||||
if(!("{{.IsCourse}}" == true || "{{.IsCourse}}" =='true')) { | if(!("{{.IsCourse}}" == true || "{{.IsCourse}}" =='true')) { | ||||
isShowNotice(); | isShowNotice(); | ||||
} | } |
@@ -96,7 +96,7 @@ | |||||
{{if .Topics }} | {{if .Topics }} | ||||
<div class="omit tags " style="position: relative;"> | <div class="omit tags " style="position: relative;"> | ||||
{{range .Topics}} | {{range .Topics}} | ||||
{{if ne . "" }}<a style="max-width:100%;margin: 5px 0;display:inline-flex;" ><span class="ui small label topic course_topic" >{{.}}</span></a>{{end}} | |||||
{{if ne . "" }}<a style="max-width:100%;margin: 5px 0;display:inline-flex;cursor:default" ><span class="ui small label topic course_topic" >{{.}}</span></a>{{end}} | |||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
@@ -136,11 +136,7 @@ | |||||
<div class="ui sixteen wide mobile six wide tablet four wide computer column"> | <div class="ui sixteen wide mobile six wide tablet four wide computer column"> | ||||
<div class=" ui bottom attached segment text center noborder text center" > | <div class=" ui bottom attached segment text center noborder text center" > | ||||
{{if .IsSigned}} | |||||
<a style="width: 80%;" class="ui green button bpadding" href="{{AppSubUrl}}/course/create"><i class="ri-folder-add-line" style="vertical-align: middle;"></i> {{.i18n.Tr "org.release_course"}} </a> | |||||
{{else}} | |||||
<a style="width: 80%;" class="ui green button bpadding" href="{{AppSubUrl}}/user/login"><i class="ri-folder-add-line" style="vertical-align: middle;"></i> {{.i18n.Tr "org.release_course"}} </a> | |||||
{{end}} | |||||
<a style="width: 80%;" class="ui green button bpadding" href="https://git.openi.org.cn/course/create" target="_blank"><i class="ri-folder-add-line" style="vertical-align: middle;"></i> {{.i18n.Tr "org.release_course"}} </a> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -209,7 +205,7 @@ | |||||
{{if .IsSigned}} | {{if .IsSigned}} | ||||
<a class="ui blue basic button" onclick="jion_course_team()" style="width: 80%;"> <i class="ri-user-add-line"></i> {{.i18n.Tr "org.teams.join_teams"}}</a> | <a class="ui blue basic button" onclick="jion_course_team()" style="width: 80%;"> <i class="ri-user-add-line"></i> {{.i18n.Tr "org.teams.join_teams"}}</a> | ||||
{{else}} | {{else}} | ||||
<a class="ui blue basic button" href="{{AppSubUrl}}/user/login" style="width: 80%;"> <i class="ri-user-add-line"></i> {{.i18n.Tr "org.teams.join_teams"}}</a> | |||||
<a class="ui blue basic button" href="https://git.openi.org.cn/user/login?course=true" style="width: 80%;" target="_blank"> <i class="ri-user-add-line"></i> {{.i18n.Tr "org.teams.join_teams"}}</a> | |||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -29,7 +29,11 @@ | |||||
<div class="ui grid"> | <div class="ui grid"> | ||||
<div class="column"> | <div class="column"> | ||||
<form class="ui form" action="{{.SignInLink}}" method="post"> | |||||
{{if .IsCourse}} | |||||
<form class="ui form" action="{{.SignInLink}}?course=true" method="post"> | |||||
{{else}} | |||||
<form class="ui form" action="{{.SignInLink}}" method="post"> | |||||
{{end}} | |||||
{{.CsrfTokenHtml}} | {{.CsrfTokenHtml}} | ||||
<div class="field"> | <div class="field"> | ||||
<div class="ui left icon input {{if and (.Err_UserName) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}"> | <div class="ui left icon input {{if and (.Err_UserName) (or (not .LinkAccountMode) (and .LinkAccountMode .LinkAccountModeSignIn))}}error{{end}}"> | ||||
@@ -350,6 +350,16 @@ export default { | |||||
etags[currentChunk] = res.headers.etag; | 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) { | async function updateChunk(currentChunk) { | ||||
await axios.post( | await axios.post( | ||||
'/attachments/update_chunk', | '/attachments/update_chunk', | ||||
@@ -372,7 +382,7 @@ export default { | |||||
await getUploadChunkUrl(currentChunk, partSize); | await getUploadChunkUrl(currentChunk, partSize); | ||||
if (urls[currentChunk] != '') { | if (urls[currentChunk] != '') { | ||||
// 上传到minio | // 上传到minio | ||||
await uploadMinio(urls[currentChunk], e); | |||||
await uploadMinioNewMethod(urls[currentChunk], e); | |||||
if (etags[currentChunk] != '') { | if (etags[currentChunk] != '') { | ||||
// 更新数据库:分片上传结果 | // 更新数据库:分片上传结果 | ||||
//await updateChunk(currentChunk); | //await updateChunk(currentChunk); | ||||
@@ -604,10 +604,13 @@ display: block; | |||||
font-weight: bold !important; | font-weight: bold !important; | ||||
} | } | ||||
.a_width{ | .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{ | .footer_icon{ | ||||
display: inline-block !important; | display: inline-block !important; | ||||
vertical-align: middle !important; | vertical-align: middle !important; | ||||