| @@ -2,7 +2,7 @@ | |||||
| <h1><img src="public/img/favicon.png" alt="logo" width="30" height="30">AiForge - 启智AI开发协作平台</h1> | <h1><img src="public/img/favicon.png" alt="logo" width="30" height="30">AiForge - 启智AI开发协作平台</h1> | ||||
| [](https://git.openi.org.cn/OpenI/aiforge/releases/latest) | |||||
| [](https://git.openi.org.cn/OpenI/aiforge/releases/latest) | |||||
| [](https://opensource.org/licenses/MIT) | [](https://opensource.org/licenses/MIT) | ||||
| @@ -1556,6 +1556,18 @@ func GetUserByActivateEmail(email string) (*User, error) { | |||||
| if len(users) >= 1 { | if len(users) >= 1 { | ||||
| return &users[0],nil | return &users[0],nil | ||||
| }else { | }else { | ||||
| // Finally, if email address is the protected email address:用户邮件地址设置为隐藏电子邮件地址 | |||||
| if strings.HasSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress)) { | |||||
| username := strings.TrimSuffix(email, fmt.Sprintf("@%s", setting.Service.NoReplyAddress)) | |||||
| user := &User{LowerName: username} | |||||
| has, err := ctx.e.Get(user) | |||||
| if err != nil { | |||||
| return nil, err | |||||
| } | |||||
| if has { | |||||
| return user, nil | |||||
| } | |||||
| } | |||||
| return nil, errors.New("cannot find user by email") | return nil, errors.New("cannot find user by email") | ||||
| } | } | ||||
| } | } | ||||
| @@ -831,6 +831,7 @@ fork = Fork | |||||
| download_archive = Download Repository | download_archive = Download Repository | ||||
| no_desc = No Description | no_desc = No Description | ||||
| no_label = No labels | |||||
| quick_guide = Quick Guide | quick_guide = Quick Guide | ||||
| clone_this_repo = Clone this repository | clone_this_repo = Clone this repository | ||||
| create_new_repo_command = Creating a new repository on the command line | create_new_repo_command = Creating a new repository on the command line | ||||
| @@ -833,6 +833,7 @@ fork=派生 | |||||
| download_archive=下载此项目 | download_archive=下载此项目 | ||||
| no_desc=暂无描述 | no_desc=暂无描述 | ||||
| no_label = 暂无标签 | |||||
| quick_guide=快速帮助 | quick_guide=快速帮助 | ||||
| clone_this_repo=克隆当前项目 | clone_this_repo=克隆当前项目 | ||||
| create_new_repo_command=从命令行创建一个新的项目 | create_new_repo_command=从命令行创建一个新的项目 | ||||
| @@ -154,7 +154,7 @@ | |||||
| {{svg "octicon-person" 16}} {{.i18n.Tr "register"}} | {{svg "octicon-person" 16}} {{.i18n.Tr "register"}} | ||||
| </a> | </a> | ||||
| {{end}} | {{end}} | ||||
| <a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login?redirect_to={{.Link}}"> | |||||
| <a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login"> | |||||
| {{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} | {{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} | ||||
| </a> | </a> | ||||
| </div><!-- end anonymous right menu --> | </div><!-- end anonymous right menu --> | ||||
| @@ -154,7 +154,7 @@ | |||||
| {{svg "octicon-person" 16}} {{.i18n.Tr "register"}} | {{svg "octicon-person" 16}} {{.i18n.Tr "register"}} | ||||
| </a> | </a> | ||||
| {{end}} | {{end}} | ||||
| <a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login?redirect_to={{.Link}}"> | |||||
| <a class="item{{if .PageIsSignIn}} active{{end}}" rel="nofollow" href="{{AppSubUrl}}/user/login"> | |||||
| {{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} | {{svg "octicon-sign-in" 16}} {{.i18n.Tr "sign_in"}} | ||||
| </a> | </a> | ||||
| </div><!-- end anonymous right menu --> | </div><!-- end anonymous right menu --> | ||||
| @@ -187,6 +187,12 @@ | |||||
| cursor: pointer; | cursor: pointer; | ||||
| pointer-events: none; | pointer-events: none; | ||||
| } | } | ||||
| .time-show{ | |||||
| font-size: 10px; | |||||
| margin-top: 0.4rem; | |||||
| display: inline-block; | |||||
| } | |||||
| </style> | </style> | ||||
| <!-- 弹窗 --> | <!-- 弹窗 --> | ||||
| @@ -265,11 +271,21 @@ | |||||
| <div class="three wide column"> | <div class="three wide column"> | ||||
| <!--任务状态 --> | <!--任务状态 --> | ||||
| <span class="ui compact button job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}"> | |||||
| <!-- <span class="ui compact button job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}"> | |||||
| {{.Status}} | {{.Status}} | ||||
| </span> | |||||
| </span> --> | |||||
| {{if eq .Status "STOPPED"}} | |||||
| <span style="display:flex;position: relative; justify-content: flex-start;"><i class="i-round i-bg-stop"></i><span style="margin-left: 0.4em;font-size: 12px;">已停止</span></span> | |||||
| {{else if eq .Status "RUNNING"}} | |||||
| <span style="display:flex;position: relative; justify-content: flex-start;"><i class="i-round i-bg-running"></i><span style="margin-left: 0.4em;font-size: 12px;">运行中</span></span> | |||||
| {{else if eq .Status "FAILED"}} | |||||
| <span style="display:flex;position: relative; justify-content: flex-start;"><i class="i-round i-bg-running"></i><span style="margin-left: 0.4em;font-size: 12px;">运行失败</span></span> | |||||
| {{else if eq .Status "WAITING"}} | |||||
| <span style="display:flex;position: relative; justify-content: flex-start;"><i class="showCircle"></i><span style="margin-left: 0.4em;font-size: 12px;">初始化等待</span></span> | |||||
| {{end}} | |||||
| <!-- 任务创建时间 --> | <!-- 任务创建时间 --> | ||||
| <span class="">{{TimeSinceUnix .CreatedUnix $.Lang}}</span> | |||||
| <span class="time-show">{{TimeSinceUnix .CreatedUnix $.Lang}}</span> | |||||
| </div> | </div> | ||||
| <div class="seven wide column text right"> | <div class="seven wide column text right"> | ||||
| @@ -1,63 +1,52 @@ | |||||
| <style> | |||||
| </style> | |||||
| {{if .Attachments}} | {{if .Attachments}} | ||||
| {{range .Attachments}} | {{range .Attachments}} | ||||
| <div class="ui grid item" id="{{.UUID}}"> | <div class="ui grid item" id="{{.UUID}}"> | ||||
| <div class="row"> | <div class="row"> | ||||
| <div class="{{if $.Permission.CanWrite $.UnitTypeDatasets}}five{{else}}nine{{end}} wide column"> | |||||
| <div class="eight wide column"> | |||||
| <span class="ui right">{{.Size | FileSize}}</span> | |||||
| <a class="title" href="{{.DownloadURL}}?type={{$.Type}}"> | <a class="title" href="{{.DownloadURL}}?type={{$.Type}}"> | ||||
| <span class="fitted">{{svg "octicon-cloud-download" 16}}</span> {{.Name}} | |||||
| {{svg "octicon-cloud-download" 16}} {{.Name}} | |||||
| </a> | </a> | ||||
| </div> | </div> | ||||
| <div class="two wide column"> | |||||
| {{.Size | FileSize}} | |||||
| </div> | |||||
| <div class="two wide column"> | |||||
| <span class="ui text center" data-tooltip='{{$.i18n.Tr "dataset.download_count"}}' data-position="bottom right">{{svg "octicon-flame" 16}} {{(.DownloadCount | PrettyNumber)}}</span> | |||||
| </div> | |||||
| <div class="one wide column" style="{{if ne $.Type 0}}visibility: hidden;{{end}}"> | |||||
| <span class="ui text center clipboard" data-clipboard-text="{{.DownloadURL}}" data-tooltip='{{$.i18n.Tr "dataset.copy_url"}}' data-clipboard-action="copy">{{svg "octicon-file" 16}}</span> | |||||
| </div> | |||||
| <div class="one wide column"> | |||||
| <span class="ui text center clipboard" data-clipboard-text="{{.FileChunk.Md5}}" data-tooltip='{{$.i18n.Tr "dataset.copy_md5"}}' data-clipboard-action="copy">{{svg "octicon-file-binary" 16}}</span> | |||||
| </div> | |||||
| <div class="wide column one" style="{{if ne .DecompressState 1}}visibility: hidden;{{end}}"> | |||||
| <a class="ui text center" href="datasets/dirs/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.directory"}}'>{{svg "octicon-file-directory" 16}}</a> | |||||
| </div> | |||||
| {{if $.IsSigned}} | |||||
| <div class="wide column one" style="{{if ne .DecompressState 1}}visibility: hidden;{{end}}"> | |||||
| <a class="ui text center" href="datasets/label/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.create_label_task"}}'><i class="fa fa-pencil-square-o" aria-hidden="true"></i></a> | |||||
| <div class="eight wide column right aligned"> | |||||
| <div class="ui left mini icon buttons"> | |||||
| <span class="ui basic button" data-tooltip='{{$.i18n.Tr "dataset.download_count"}}' data-position="bottom right">{{svg "octicon-flame" 16}} {{(.DownloadCount | PrettyNumber)}}</span> | |||||
| <span class="ui basic basic button clipboard" data-clipboard-text="{{.DownloadURL}}" data-tooltip='{{$.i18n.Tr "dataset.copy_url"}}' data-clipboard-action="copy"{{if ne $.Type 0}} style="display:none;"{{end}}>{{svg "octicon-file" 16}}</span> | |||||
| <span class="ui basic basic button clipboard" data-clipboard-text="{{.FileChunk.Md5}}" data-tooltip='{{$.i18n.Tr "dataset.copy_md5"}}' data-clipboard-action="copy">{{svg "octicon-file-binary" 16}}</span> | |||||
| </div> | </div> | ||||
| {{end}} | |||||
| {{if not .CanDel}} | |||||
| <div class="two wide column"> | |||||
| <a class="ui button mini" disabled='true'>{{if .IsPrivate}} {{$.i18n.Tr "dataset.private"}} {{else}} {{$.i18n.Tr "dataset.public"}} {{end}}</a> | |||||
| {{if ne .DecompressState 0}} | |||||
| <div class="ui left mini icon buttons"> | |||||
| <a class="ui basic blue button" href="datasets/dirs/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.directory"}}'>{{svg "octicon-file-directory" 16}}</a> | |||||
| {{if $.IsSigned}} | |||||
| <a class="ui basic blue button" href="datasets/label/{{.UUID}}?type={{$.Type}}" data-tooltip='{{$.i18n.Tr "dataset.create_label_task"}}'>{{svg "octicon-pencil" 16}}</a> | |||||
| {{end}} | |||||
| </div> | </div> | ||||
| {{else}} | |||||
| {{if $.Permission.CanWrite $.UnitTypeDatasets}} | |||||
| {{end}} | |||||
| {{if not .CanDel}} | |||||
| <a class="ui right small disabled button">{{$.i18n.Tr "dataset.delete"}}</a> | |||||
| <span style="margin-right: 10px;line-height: 34px;" class="ui text{{if .IsPrivate}} red{{else}} green{{end}}">{{if .IsPrivate}} {{$.i18n.Tr "dataset.private"}} {{else}} {{$.i18n.Tr "dataset.public"}} {{end}}</span> | |||||
| {{else}} | |||||
| {{if $.Permission.CanWrite $.UnitTypeDatasets}} | |||||
| <a class="ui right small red button" href="javascript:void(0)" data-uuid={{.UUID}} data-dataset-delete data-remove-url="{{AppSubUrl}}/attachments/delete" data-csrf="{{$.CsrfToken}}">{{$.i18n.Tr "dataset.delete"}}</a> | |||||
| {{if $.Repository.IsPrivate}} | {{if $.Repository.IsPrivate}} | ||||
| <div class="two wide column"> | |||||
| <a class="ui button mini" disabled='true' data-tooltip='{{$.i18n.Tr "dataset.how_to_public"}}'>{{$.i18n.Tr "dataset.private"}}</a> | |||||
| </div> | |||||
| {{ else }} | |||||
| <div class="two wide column"> | |||||
| <div class="ui buttons mini"> | |||||
| <a class="ui button mini {{if .IsPrivate}}positive active{{end}}" href="javascript:void(0)" data-dataset-status="true-{{.UUID}}" data-csrf="{{$.CsrfToken}}" data-url="{{AppSubUrl}}/attachments/private" data-uuid={{.UUID}} data-private="true" data-is-private={{.IsPrivate}}>{{$.i18n.Tr "dataset.private"}}</a> | |||||
| <span data-tooltip='{{$.i18n.Tr "dataset.how_to_public"}}' style="margin-right: 10px; line-height: 34px;" class="ui text red">{{$.i18n.Tr "dataset.private"}}</span> | |||||
| {{else}} | |||||
| <div class="compact small ui buttons" style="margin-right: 10px;"> | |||||
| <a class="ui button{{if .IsPrivate}} positive active{{end}}" href="javascript:void(0)" data-dataset-status="true-{{.UUID}}" data-csrf="{{$.CsrfToken}}" data-url="{{AppSubUrl}}/attachments/private" data-uuid={{.UUID}} data-private="true" data-is-private={{.IsPrivate}}>{{$.i18n.Tr "dataset.private"}}</a> | |||||
| <div class="or"></div> | <div class="or"></div> | ||||
| <a class="ui button mini {{if not .IsPrivate}}positive active{{end}}" href="javascript:void(0)" data-dataset-status="false-{{.UUID}}" data-csrf="{{$.CsrfToken}}" data-url="{{AppSubUrl}}/attachments/private" data-uuid={{.UUID}} data-private="false" data-is-private={{.IsPrivate}}>{{$.i18n.Tr "dataset.public"}}</a> | |||||
| <a class="ui button{{if not .IsPrivate}} positive active{{end}}" href="javascript:void(0)" data-dataset-status="false-{{.UUID}}" data-csrf="{{$.CsrfToken}}" data-url="{{AppSubUrl}}/attachments/private" data-uuid={{.UUID}} data-private="false" data-is-private={{.IsPrivate}}>{{$.i18n.Tr "dataset.public"}}</a> | |||||
| </div> | </div> | ||||
| </div> | |||||
| {{end}} | |||||
| {{else}} | |||||
| <a class="ui right small disabled button">{{$.i18n.Tr "dataset.delete"}}</a> | |||||
| <span style="margin-right: 10px;line-height: 34px;" class="ui text{{if .IsPrivate}} red{{else}} green{{end}}">{{if .IsPrivate}} {{$.i18n.Tr "dataset.private"}} {{else}} {{$.i18n.Tr "dataset.public"}} {{end}}</span> | |||||
| {{end}} | {{end}} | ||||
| <div class="two wide column right aligned"> | |||||
| <a class="ui red button mini" href="javascript:void(0)" data-uuid={{.UUID}} data-dataset-delete data-remove-url="{{AppSubUrl}}/attachments/delete" data-csrf="{{$.CsrfToken}}">{{$.i18n.Tr "dataset.delete"}}</a> | |||||
| </div> | |||||
| {{else}} | |||||
| <div class="two wide column"> | |||||
| <a class="ui button mini" disabled='true'>{{if .IsPrivate}} {{$.i18n.Tr "dataset.private"}} {{else}} {{$.i18n.Tr "dataset.public"}} {{end}}</a> | |||||
| </div> | |||||
| {{end}} | {{end}} | ||||
| {{end}} | |||||
| </div> | |||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{end}} | {{end}} | ||||
| @@ -80,7 +80,7 @@ | |||||
| <div class="ui sixteen wide column"> | <div class="ui sixteen wide column"> | ||||
| <div class="ui two column stackable grid"> | <div class="ui two column stackable grid"> | ||||
| <div class="column"> | <div class="column"> | ||||
| <h2>{{if eq .Type 0}}{{.i18n.Tr "repo.cloudbrain1"}}{{else}}{{.i18n.Tr "repo.cloudbrain2"}}{{end}}-{{.i18n.Tr "datasets"}}</h2> | |||||
| <strong>{{if eq .Type 0}}{{.i18n.Tr "repo.cloudbrain1"}}{{else}}{{.i18n.Tr "repo.cloudbrain2"}}{{end}}-{{.i18n.Tr "datasets"}}</strong> | |||||
| </div> | </div> | ||||
| <div class="column right aligned" style="z-index:1"> | <div class="column right aligned" style="z-index:1"> | ||||
| <div class="ui right dropdown type jump item"> | <div class="ui right dropdown type jump item"> | ||||
| @@ -55,6 +55,40 @@ | |||||
| #contributorInfo > a.circular:nth-child(9n+8){ | #contributorInfo > a.circular:nth-child(9n+8){ | ||||
| background-color: #bfd0aa; | background-color: #bfd0aa; | ||||
| } | } | ||||
| .vue_menu { | |||||
| cursor: auto; | |||||
| position: absolute; | |||||
| outline: none; | |||||
| top: 100%; | |||||
| margin: 0em; | |||||
| padding: 0em 0em; | |||||
| background: #fff; | |||||
| font-size: 1em; | |||||
| text-shadow: none; | |||||
| text-align: left; | |||||
| /* -webkit-box-shadow: 0px 2px 3px 0px rgb(34 36 38 / 15%); */ | |||||
| box-shadow: 0px 2px 3px 0px rgba(34, 36, 38, 0.15); | |||||
| border: 1px solid rgba(34,36,38,0.15); | |||||
| border-radius: 0.28571429rem; | |||||
| -webkit-transition: opacity 0.1s ease; | |||||
| transition: opacity 0.1s ease; | |||||
| z-index: 11; | |||||
| will-change: transform, opacity; | |||||
| width: 100% !important; | |||||
| -webkit-animation-iteration-count: 1; | |||||
| animation-iteration-count: 1; | |||||
| -webkit-animation-duration: 300ms; | |||||
| animation-duration: 300ms; | |||||
| -webkit-animation-timing-function: ease; | |||||
| animation-timing-function: ease; | |||||
| -webkit-animation-fill-mode: both; | |||||
| animation-fill-mode: both; | |||||
| } | |||||
| </style> | </style> | ||||
| <div class="repository file list"> | <div class="repository file list"> | ||||
| {{template "repo/header" .}} | {{template "repo/header" .}} | ||||
| @@ -62,7 +96,7 @@ | |||||
| {{template "base/alert" .}} | {{template "base/alert" .}} | ||||
| {{if and .Permission.IsAdmin (not .Repository.IsArchived)}} | {{if and .Permission.IsAdmin (not .Repository.IsArchived)}} | ||||
| <div class="ui repo-topic-edit grid form segment error" id="topic_edit" style="display:none"> | |||||
| <!-- <div class="ui repo-topic-edit grid form segment error" id="topic_edit" style="display:none"> | |||||
| <div class="fourteen wide column"> | <div class="fourteen wide column"> | ||||
| <div class="field"> | <div class="field"> | ||||
| <div class="ui fluid multiple search selection dropdown"> | <div class="ui fluid multiple search selection dropdown"> | ||||
| @@ -78,7 +112,8 @@ | |||||
| <a class="ui button primary" href="javascript:;" id="save_topic" | <a class="ui button primary" href="javascript:;" id="save_topic" | ||||
| data-link="{{.RepoLink}}/topics">{{.i18n.Tr "repo.topic.done"}}</a> | data-link="{{.RepoLink}}/topics">{{.i18n.Tr "repo.topic.done"}}</a> | ||||
| </div> | </div> | ||||
| </div> | |||||
| </div> --> | |||||
| {{end}} | {{end}} | ||||
| <div class="hide" id="validate_prompt"> | <div class="hide" id="validate_prompt"> | ||||
| <span id="count_prompt">{{.i18n.Tr "repo.topic.count_prompt"}}</span> | <span id="count_prompt">{{.i18n.Tr "repo.topic.count_prompt"}}</span> | ||||
| @@ -232,11 +267,30 @@ | |||||
| {{end}} | {{end}} | ||||
| <p class="ui" id="repo-topics"> | |||||
| <i class="grey bookmark icon"></i> | |||||
| {{range .Topics}}<a class="ui repo-topic small label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=1">{{.Name}}</a>{{end}} | |||||
| {{if and .Permission.IsAdmin (not .Repository.IsArchived)}}<a id="manage_topic">{{.i18n.Tr "repo.topic.manage_topics"}}</a>{{end}} | |||||
| </p> | |||||
| <div class="ui" id="repo-topics" style="display: flex;position: relative;margin-bottom: 1.0rem;"> | |||||
| <i class="grey bookmark icon"></i> | |||||
| <div id="repo-topics1" style="flex: 1;"> | |||||
| <!-- {{if not .Topics}} | |||||
| <span class="no-description text-italic">{{.i18n.Tr "repo.no_desc"}}</span> | |||||
| {{end}} --> | |||||
| {{range .Topics}} | |||||
| <a class="ui repo-topic small label topic" href="{{AppSubUrl}}/explore/repos?q={{.Name}}&topic=1">{{.Name}}</a> | |||||
| {{end}} | |||||
| </div> | |||||
| <div> | |||||
| {{if and .Permission.IsAdmin (not .Repository.IsArchived)}}<i id="manage_topic" style="cursor: pointer;" class="plus icon"></i>{{end}} | |||||
| </div> | |||||
| <div id="topic_edit" class="vue_menu" style="display:none"> | |||||
| <div id="topic_edit1"> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| <p class="ui"> | <p class="ui"> | ||||
| @@ -0,0 +1,468 @@ | |||||
| <template> | |||||
| <div> | |||||
| <div class="input-search"> | |||||
| <el-input v-model="input" clearable :autofocus="true" @input="changeValue" id="topics_input" @keyup.enter.native="postTopic" placeholder="搜索或创建标签"> | |||||
| </el-input> | |||||
| <div class="scrolling-menu"> | |||||
| <div v-if="showSearchTopic" class="item-text" v-for="(arr,i) in array" @click="addTopics(i,arr)"> | |||||
| <div class="icon-wrapper"> | |||||
| <i style="line-height: 1.5;color: #303643;font-weight: 900;" v-if="showInitTopic[i]" class="el-icon-check" ></i> | |||||
| </div> | |||||
| <div class="text">{{arr.topic_name}} </div> | |||||
| </div> | |||||
| <div v-if="showInputValue" class="addition item-text" @click="postTopic"> | |||||
| 点击或回车添加<b class="user-add-label-text">{{input}}</b>标签 | |||||
| </div> | |||||
| <div v-if="showAddTopic" class="item-text" @click="addPostTopic"> | |||||
| <div class="icon-wrapper"> | |||||
| <i style="line-height: 1.5;color: #303643;font-weight: 900;" v-if="showAddFlage" class="el-icon-check" ></i> | |||||
| </div> | |||||
| <div class="text">{{input}}</div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </div> | |||||
| </template> | |||||
| <script> | |||||
| const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; | |||||
| import $ from 'jquery' | |||||
| export default { | |||||
| data() { | |||||
| return { | |||||
| input:'', | |||||
| params:{}, | |||||
| showInputValue:false, | |||||
| showFlag:-1, | |||||
| array:[], | |||||
| showAddTopic:false, | |||||
| showAddFlage:false, | |||||
| showSearchTopic:true, | |||||
| postUrl:'', | |||||
| arrayTopics:[], | |||||
| showInitTopic:[], | |||||
| }; | |||||
| }, | |||||
| methods: { | |||||
| addTopics(item,array){ | |||||
| if(!this.showInitTopic[item]){ | |||||
| this.arrayTopics.push(array.topic_name) | |||||
| let topics = this.arrayTopics | |||||
| let strTopics = topics.join(',') | |||||
| let data = this.qs.stringify({ | |||||
| _csrf:csrf, | |||||
| topics:strTopics | |||||
| }) | |||||
| this.Post(data,topics) | |||||
| this.$set(this.showInitTopic,item,true) | |||||
| $('#repo-topics1').children('span').remove() | |||||
| }else{ | |||||
| this.arrayTopics=this.arrayTopics.filter(ele=>{ | |||||
| return ele !== array.topic_name | |||||
| }) | |||||
| let topics = this.arrayTopics | |||||
| let strTopics = topics.join(',') | |||||
| let data = this.qs.stringify({ | |||||
| _csrf:csrf, | |||||
| topics:strTopics | |||||
| }) | |||||
| this.Post(data,topics) | |||||
| this.$set(this.showInitTopic,item,false) | |||||
| if(this.arrayTopics.length===0){ | |||||
| console.log("set empty") | |||||
| $('#repo-topics1').append('<span class="no-description text-italic">暂无标签</span>') | |||||
| }else{ | |||||
| $('#repo-topics1').children('span').remove() | |||||
| } | |||||
| } | |||||
| }, | |||||
| changeValue(){ | |||||
| if (this.input === ''){ | |||||
| this.array = this.arrayTopics | |||||
| let data = [] | |||||
| this.showInitTopic = [] | |||||
| this.array.forEach((element,index) => { | |||||
| let item = {} | |||||
| item.topic_name = element | |||||
| data.push(item) | |||||
| this.showInitTopic.push(true) | |||||
| }); | |||||
| this.array = data | |||||
| this.showInputValue = false | |||||
| this.showSearchTopic = true | |||||
| } | |||||
| else if(this.arrayTopics.indexOf(this.input)>-1){ | |||||
| this.showInputValue = false | |||||
| this.showSearchTopic = false | |||||
| }else{ | |||||
| this.showInitTopic = [] | |||||
| let timestamp=new Date().getTime() | |||||
| this.params.q = this.input | |||||
| this.params._ = timestamp | |||||
| this.$axios.get('/api/v1/topics/search',{ | |||||
| params:this.params | |||||
| }).then((res)=>{ | |||||
| this.array = res.data.topics | |||||
| this.array.forEach((element,index) => { | |||||
| if (this.arrayTopics.indexOf(element.topic_name)>-1){ | |||||
| this.showInitTopic.push(true) | |||||
| }else{ | |||||
| this.showInitTopic.push(false) | |||||
| } | |||||
| }); | |||||
| }) | |||||
| this.showInputValue = true | |||||
| this.showSearchTopic = true | |||||
| } | |||||
| this.showAddTopic = false | |||||
| }, | |||||
| Post(data,topics){ | |||||
| this.$axios.post(this.postUrl,data).then(res=>{ | |||||
| const viewDiv = $('#repo-topics1'); | |||||
| viewDiv.children('.topic').remove(); | |||||
| if (topics.length) { | |||||
| const topicArray = topics; | |||||
| const last = viewDiv.children('a').last(); | |||||
| for (let i = 0; i < topicArray.length; i++) { | |||||
| const link = $('<a class="ui repo-topic small label topic"></a>'); | |||||
| link.attr( | |||||
| 'href', | |||||
| `${AppSubUrl}/explore/repos?q=${encodeURIComponent( | |||||
| topicArray[i] | |||||
| )}&topic=1` | |||||
| ); | |||||
| link.text(topicArray[i]); | |||||
| // link.insertBefore(last); | |||||
| viewDiv.append(link) | |||||
| } | |||||
| } | |||||
| viewDiv.show(); | |||||
| }) | |||||
| }, | |||||
| postTopic(){ | |||||
| const patter = /^[\u4e00-\u9fa5a-z0-9][\u4e00-\u9fa5a-zA-Z0-9-]{0,35}$/ | |||||
| let regexp = patter.test(this.input) | |||||
| console.log("regexp",regexp) | |||||
| if(!regexp){ | |||||
| this.$notify({ | |||||
| message: '主题必须以中文、字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符', | |||||
| duration: 3000, | |||||
| type:'error' | |||||
| }); | |||||
| return | |||||
| }else{ | |||||
| let topic = this.input | |||||
| this.arrayTopics.push(topic) | |||||
| let topics = this.arrayTopics | |||||
| let strTopics = topics.join(',') | |||||
| let data = this.qs.stringify({ | |||||
| _csrf:csrf, | |||||
| topics:strTopics | |||||
| }) | |||||
| this.Post(data,topics) | |||||
| $('#repo-topics1').children('span').remove() | |||||
| this.showInputValue = false | |||||
| this.showAddTopic = true | |||||
| this.showAddFlage = true | |||||
| } | |||||
| }, | |||||
| addPostTopic(){ | |||||
| if(this.showAddFlage){ | |||||
| this.arrayTopics.pop() | |||||
| let topics = this.arrayTopics | |||||
| let strTopics = topics.join(',') | |||||
| let data = this.qs.stringify({ | |||||
| _csrf:csrf, | |||||
| topics:strTopics | |||||
| }) | |||||
| this.Post(data,topics) | |||||
| if(this.arrayTopics.length===0){ | |||||
| console.log("add postTopic") | |||||
| $('#repo-topics1').append('<span class="no-description text-italic">暂无标签</span>') | |||||
| }else{ | |||||
| $('#repo-topics1').children('span').remove() | |||||
| } | |||||
| } | |||||
| else if(!this.showAddFlage){ | |||||
| let topic = this.input | |||||
| this.arrayTopics.push(topic) | |||||
| let topics = this.arrayTopics | |||||
| let strTopics = topics.join(',') | |||||
| let data = this.qs.stringify({ | |||||
| _csrf:csrf, | |||||
| topics:strTopics | |||||
| }) | |||||
| this.Post(data,topics) | |||||
| $('#repo-topics1').children('span').remove() | |||||
| } | |||||
| this.showAddFlage = !this.showAddFlage | |||||
| }, | |||||
| initTopics(){ | |||||
| const mgrBtn = $('#manage_topic'); | |||||
| const editDiv = $('#topic_edit'); | |||||
| mgrBtn.on('click', (e) => { | |||||
| // viewDiv.hide(); | |||||
| editDiv.css('display', ''); // show Semantic UI Grid | |||||
| this.input = '' | |||||
| if (this.input === ''){ | |||||
| this.array = this.arrayTopics | |||||
| let data = [] | |||||
| this.showInitTopic = [] | |||||
| this.array.forEach((element,index) => { | |||||
| let item = {} | |||||
| item.topic_name = element | |||||
| data.push(item) | |||||
| this.showInitTopic.push(true) | |||||
| }); | |||||
| this.array = data | |||||
| this.showInputValue = false | |||||
| this.showSearchTopic = true | |||||
| } | |||||
| stopPropagation(e); | |||||
| }); | |||||
| $(document).bind('click',function(){ | |||||
| editDiv.css('display','none'); | |||||
| }) | |||||
| editDiv.click(function(e){ | |||||
| stopPropagation(e); | |||||
| }) | |||||
| function stopPropagation(e) { | |||||
| var ev = e || window.event; | |||||
| if (ev.stopPropagation) { | |||||
| ev.stopPropagation(); | |||||
| } | |||||
| else if (window.event) { | |||||
| window.event.cancelBubble = true;//兼容IE | |||||
| } | |||||
| } | |||||
| } | |||||
| }, | |||||
| computed:{ | |||||
| }, | |||||
| watch: { | |||||
| input(newValue){ | |||||
| if (newValue === ''){ | |||||
| this.array = this.arrayTopics | |||||
| let data = [] | |||||
| this.showInitTopic = [] | |||||
| this.array.forEach((element,index) => { | |||||
| let item = {} | |||||
| item.topic_name = element | |||||
| data.push(item) | |||||
| this.showInitTopic.push(true) | |||||
| }); | |||||
| this.array = data | |||||
| this.showInputValue = false | |||||
| this.showSearchTopic = true | |||||
| } | |||||
| } | |||||
| }, | |||||
| mounted() { | |||||
| const context = this | |||||
| this.postUrl = `${window.location.pathname}/topics`; | |||||
| $('#repo-topics1').children('a').each(function(){ | |||||
| context.arrayTopics.push($(this).text()) | |||||
| }); | |||||
| if(this.arrayTopics.length===0){ | |||||
| $('#repo-topics1').append('<span class="no-description text-italic">暂无标签</span>') | |||||
| } | |||||
| this.changeValue() | |||||
| } , | |||||
| created(){ | |||||
| this.initTopics(); | |||||
| this.input='' | |||||
| } | |||||
| }; | |||||
| </script> | |||||
| <style scoped> | |||||
| .input-search { | |||||
| width: 100%; | |||||
| display: -webkit-box; | |||||
| display: -ms-flexbox; | |||||
| display: flex; | |||||
| min-width: 10rem; | |||||
| white-space: nowrap; | |||||
| font-size: 1rem; | |||||
| position: relative; | |||||
| display: inline-block; | |||||
| color: rgba(0,0,0,0.8); | |||||
| padding: 8px; | |||||
| } | |||||
| /deep/ .el-input__inner{ | |||||
| border-color: #409eff; | |||||
| } | |||||
| .scrolling-menu{ | |||||
| border-top: none !important; | |||||
| padding-top: 0 !important; | |||||
| padding-bottom: 0 !important; | |||||
| display: block; | |||||
| position: static; | |||||
| overflow-y: auto; | |||||
| border: none; | |||||
| -webkit-box-shadow: none !important; | |||||
| box-shadow: none !important; | |||||
| border-radius: 0 !important; | |||||
| margin: 0 !important; | |||||
| min-width: 100% !important; | |||||
| width: auto !important; | |||||
| border-top: 1px solid rgba(34,36,38,0.15); | |||||
| } | |||||
| .item-text{ | |||||
| border-top: none; | |||||
| padding-right: calc(1.14285714rem + 17px ) !important; | |||||
| line-height: 1.333; | |||||
| padding-top: 0.7142857rem !important; | |||||
| padding-bottom: 0.7142857rem !important; | |||||
| position: relative; | |||||
| cursor: pointer; | |||||
| display: block; | |||||
| border: none; | |||||
| height: auto; | |||||
| text-align: left; | |||||
| border-top: none; | |||||
| line-height: 1em; | |||||
| color: rgba(0,0,0,0.87); | |||||
| padding: 0.78571429rem 1.14285714rem !important; | |||||
| font-size: 1rem; | |||||
| text-transform: none; | |||||
| font-weight: normal; | |||||
| -webkit-box-shadow: none; | |||||
| box-shadow: none; | |||||
| -webkit-touch-callout: none; | |||||
| display: -webkit-box; | |||||
| display: -ms-flexbox; | |||||
| display: flex; | |||||
| -webkit-box-align: center; | |||||
| -ms-flex-align: center; | |||||
| align-items: center; | |||||
| display: -webkit-box !important; | |||||
| display: -ms-flexbox !important; | |||||
| display: flex !important; | |||||
| } | |||||
| .icon-wrapper{ | |||||
| text-align: left; | |||||
| width: 24px; | |||||
| height: 20px; | |||||
| -ms-flex-negative: 0; | |||||
| flex-shrink: 0; | |||||
| } | |||||
| .text{ | |||||
| max-width: 80%; | |||||
| overflow: hidden; | |||||
| text-overflow: ellipsis; | |||||
| white-space: nowrap; | |||||
| font-size: 12px; | |||||
| font-weight: 400; | |||||
| color: #40485b; | |||||
| } | |||||
| .addition{ | |||||
| background: #f6f6f6; | |||||
| } | |||||
| .user-add-label-text{ | |||||
| max-width: 80%; | |||||
| overflow: hidden; | |||||
| text-overflow: ellipsis; | |||||
| white-space: nowrap; | |||||
| margin: 0 4px; | |||||
| } | |||||
| </style> | |||||
| @@ -1,17 +1,16 @@ | |||||
| <template> | <template> | ||||
| <div class="dropzone-wrapper dataset-files"> | <div class="dropzone-wrapper dataset-files"> | ||||
| <div class="ui pointing below red basic label"> | |||||
| <i class="icon info circle"></i>只有zip格式的数据集才能发起云脑任务 | |||||
| </div> | |||||
| <div | <div | ||||
| id="dataset" | id="dataset" | ||||
| class="dropzone" | class="dropzone" | ||||
| /> | /> | ||||
| <p class="upload-info"> | <p class="upload-info"> | ||||
| {{ file_status_text }} | {{ file_status_text }} | ||||
| <span class="success">{{ status }}</span> | |||||
| <strong class="success text red">{{ status }}</strong> | |||||
| </p> | </p> | ||||
| <p>云脑1提供 <span class="text blue">CPU / GPU</span> 资源,云脑2提供 <span class="text blue">Ascend NPU</span> 资源;调试使用的数据集也需要上传到对应的环境。</p> | |||||
| <p>说明:<br> | |||||
| - 只有zip格式的数据集才能发起云脑任务;<br> | |||||
| - 云脑1提供 <span class="text blue">CPU / GPU</span> 资源,云脑2提供 <span class="text blue">Ascend NPU</span> 资源;调试使用的数据集也需要上传到对应的环境。</p> | |||||
| </div> | </div> | ||||
| </template> | </template> | ||||
| @@ -6,9 +6,12 @@ | |||||
| /> | /> | ||||
| <p class="upload-info"> | <p class="upload-info"> | ||||
| {{ file_status_text }} | {{ file_status_text }} | ||||
| <span class="success">{{ status }}</span> | |||||
| <strong class="success text red">{{ status }}</strong> | |||||
| </p> | |||||
| <p>说明:<br> | |||||
| - 只有zip格式的数据集才能发起云脑任务;<br> | |||||
| - 云脑1提供 <span class="text blue">CPU / GPU</span> 资源,云脑2提供 <span class="text blue">Ascend NPU</span> 资源;调试使用的数据集也需要上传到对应的环境。 | |||||
| </p> | </p> | ||||
| <p>云脑1提供 <span class="text blue">CPU / GPU</span> 资源,云脑2提供 <span class="text blue">Ascend NPU</span> 资源;调试使用的数据集也需要上传到对应的环境。</p> | |||||
| </div> | </div> | ||||
| </template> | </template> | ||||
| @@ -36,6 +36,7 @@ import MinioUploader from './components/MinioUploader.vue'; | |||||
| import ObsUploader from './components/ObsUploader.vue'; | import ObsUploader from './components/ObsUploader.vue'; | ||||
| import EditAboutInfo from './components/EditAboutInfo.vue'; | import EditAboutInfo from './components/EditAboutInfo.vue'; | ||||
| import Images from './components/Images.vue' | import Images from './components/Images.vue' | ||||
| import EditTopics from './components/EditTopics.vue' | |||||
| Vue.use(ElementUI); | Vue.use(ElementUI); | ||||
| Vue.prototype.$axios = axios; | Vue.prototype.$axios = axios; | ||||
| @@ -2967,11 +2968,13 @@ $(document).ready(async () => { | |||||
| initVueUploader(); | initVueUploader(); | ||||
| initObsUploader(); | initObsUploader(); | ||||
| initVueEditAbout(); | initVueEditAbout(); | ||||
| initVueEditTopic(); | |||||
| initVueImages(); | initVueImages(); | ||||
| initTeamSettings(); | initTeamSettings(); | ||||
| initCtrlEnterSubmit(); | initCtrlEnterSubmit(); | ||||
| initNavbarContentToggle(); | initNavbarContentToggle(); | ||||
| initTopicbar(); | |||||
| // initTopicbar(); | |||||
| // closeTopicbar(); | |||||
| initU2FAuth(); | initU2FAuth(); | ||||
| initU2FRegister(); | initU2FRegister(); | ||||
| initIssueList(); | initIssueList(); | ||||
| @@ -3666,7 +3669,19 @@ function initVueEditAbout() { | |||||
| }); | }); | ||||
| } | } | ||||
| function initVueEditTopic() { | |||||
| const el = document.getElementById('topic_edit1'); | |||||
| if (!el) { | |||||
| return; | |||||
| } | |||||
| new Vue({ | |||||
| el:'#topic_edit1', | |||||
| render:h=>h(EditTopics) | |||||
| }) | |||||
| } | |||||
| function initVueImages() { | function initVueImages() { | ||||
| const el = document.getElementById('images'); | const el = document.getElementById('images'); | ||||
| console.log("el",el) | console.log("el",el) | ||||
| @@ -3677,6 +3692,7 @@ function initVueImages() { | |||||
| new Vue({ | new Vue({ | ||||
| el: '#images', | el: '#images', | ||||
| render: h => h(Images) | render: h => h(Images) | ||||
| }); | }); | ||||
| } | } | ||||
| @@ -3932,218 +3948,243 @@ function initNavbarContentToggle() { | |||||
| }); | }); | ||||
| } | } | ||||
| function initTopicbar() { | |||||
| const mgrBtn = $('#manage_topic'); | |||||
| const editDiv = $('#topic_edit'); | |||||
| const viewDiv = $('#repo-topics'); | |||||
| const saveBtn = $('#save_topic'); | |||||
| const topicDropdown = $('#topic_edit .dropdown'); | |||||
| const topicForm = $('#topic_edit.ui.form'); | |||||
| const topicPrompts = getPrompts(); | |||||
| mgrBtn.on('click', () => { | |||||
| viewDiv.hide(); | |||||
| editDiv.css('display', ''); // show Semantic UI Grid | |||||
| }); | |||||
| function getPrompts() { | |||||
| const hidePrompt = $('div.hide#validate_prompt'); | |||||
| const prompts = { | |||||
| countPrompt: hidePrompt.children('#count_prompt').text(), | |||||
| formatPrompt: hidePrompt.children('#format_prompt').text() | |||||
| }; | |||||
| hidePrompt.remove(); | |||||
| return prompts; | |||||
| } | |||||
| saveBtn.on('click', () => { | |||||
| const topics = $('input[name=topics]').val(); | |||||
| $.post( | |||||
| saveBtn.data('link'), | |||||
| { | |||||
| _csrf: csrf, | |||||
| topics | |||||
| }, | |||||
| (_data, _textStatus, xhr) => { | |||||
| if (xhr.responseJSON.status === 'ok') { | |||||
| viewDiv.children('.topic').remove(); | |||||
| if (topics.length) { | |||||
| const topicArray = topics.split(','); | |||||
| const last = viewDiv.children('a').last(); | |||||
| for (let i = 0; i < topicArray.length; i++) { | |||||
| const link = $('<a class="ui repo-topic small label topic"></a>'); | |||||
| link.attr( | |||||
| 'href', | |||||
| `${AppSubUrl}/explore/repos?q=${encodeURIComponent( | |||||
| topicArray[i] | |||||
| )}&topic=1` | |||||
| ); | |||||
| link.text(topicArray[i]); | |||||
| link.insertBefore(last); | |||||
| } | |||||
| } | |||||
| editDiv.css('display', 'none'); | |||||
| viewDiv.show(); | |||||
| } | |||||
| } | |||||
| ) | |||||
| .fail((xhr) => { | |||||
| if (xhr.status === 422) { | |||||
| if (xhr.responseJSON.invalidTopics.length > 0) { | |||||
| topicPrompts.formatPrompt = xhr.responseJSON.message; | |||||
| const {invalidTopics} = xhr.responseJSON; | |||||
| const topicLables = topicDropdown.children('a.ui.label'); | |||||
| topics.split(',').forEach((value, index) => { | |||||
| for (let i = 0; i < invalidTopics.length; i++) { | |||||
| if (invalidTopics[i] === value) { | |||||
| topicLables | |||||
| .eq(index) | |||||
| .removeClass('green') | |||||
| .addClass('red'); | |||||
| } | |||||
| } | |||||
| }); | |||||
| } else { | |||||
| topicPrompts.countPrompt = xhr.responseJSON.message; | |||||
| } | |||||
| } | |||||
| }) | |||||
| .always(() => { | |||||
| topicForm.form('validate form'); | |||||
| }); | |||||
| }); | |||||
| topicDropdown.dropdown({ | |||||
| allowAdditions: true, | |||||
| forceSelection: false, | |||||
| fields: {name: 'description', value: 'data-value'}, | |||||
| saveRemoteData: false, | |||||
| label: { | |||||
| transition: 'horizontal flip', | |||||
| duration: 200, | |||||
| variation: false, | |||||
| blue: true, | |||||
| basic: true | |||||
| }, | |||||
| className: { | |||||
| label: 'ui small label' | |||||
| }, | |||||
| apiSettings: { | |||||
| url: `${AppSubUrl}/api/v1/topics/search?q={query}`, | |||||
| throttle: 500, | |||||
| cache: false, | |||||
| onResponse(res) { | |||||
| const formattedResponse = { | |||||
| success: false, | |||||
| results: [] | |||||
| }; | |||||
| const stripTags = function (text) { | |||||
| return text.replace(/<[^>]*>?/gm, ''); | |||||
| }; | |||||
| const query = stripTags(this.urlData.query.trim()); | |||||
| let found_query = false; | |||||
| const current_topics = []; | |||||
| topicDropdown | |||||
| .find('div.label.visible.topic,a.label.visible') | |||||
| .each((_, e) => { | |||||
| current_topics.push(e.dataset.value); | |||||
| }); | |||||
| if (res.topics) { | |||||
| let found = false; | |||||
| for (let i = 0; i < res.topics.length; i++) { | |||||
| // skip currently added tags | |||||
| if (current_topics.includes(res.topics[i].topic_name)) { | |||||
| continue; | |||||
| } | |||||
| if ( | |||||
| res.topics[i].topic_name.toLowerCase() === query.toLowerCase() | |||||
| ) { | |||||
| found_query = true; | |||||
| } | |||||
| formattedResponse.results.push({ | |||||
| description: res.topics[i].topic_name, | |||||
| 'data-value': res.topics[i].topic_name | |||||
| }); | |||||
| found = true; | |||||
| } | |||||
| formattedResponse.success = found; | |||||
| } | |||||
| if (query.length > 0 && !found_query) { | |||||
| formattedResponse.success = true; | |||||
| formattedResponse.results.unshift({ | |||||
| description: query, | |||||
| 'data-value': query | |||||
| }); | |||||
| } else if (query.length > 0 && found_query) { | |||||
| formattedResponse.results.sort((a, b) => { | |||||
| if (a.description.toLowerCase() === query.toLowerCase()) return -1; | |||||
| if (b.description.toLowerCase() === query.toLowerCase()) return 1; | |||||
| if (a.description > b.description) return -1; | |||||
| if (a.description < b.description) return 1; | |||||
| return 0; | |||||
| }); | |||||
| } | |||||
| return formattedResponse; | |||||
| } | |||||
| }, | |||||
| onLabelCreate(value) { | |||||
| value = value.toLowerCase().trim(); | |||||
| this.attr('data-value', value) | |||||
| .contents() | |||||
| .first() | |||||
| .replaceWith(value); | |||||
| return $(this); | |||||
| }, | |||||
| onAdd(addedValue, _addedText, $addedChoice) { | |||||
| addedValue = addedValue.toLowerCase().trim(); | |||||
| $($addedChoice).attr('data-value', addedValue); | |||||
| $($addedChoice).attr('data-text', addedValue); | |||||
| } | |||||
| }); | |||||
| $.fn.form.settings.rules.validateTopic = function (_values, regExp) { | |||||
| const topics = topicDropdown.children('a.ui.label'); | |||||
| const status = | |||||
| topics.length === 0 || (topics.last().attr('data-value').match(regExp) !== null && topics.last().attr('data-value').length <= 35); | |||||
| if (!status) { | |||||
| topics | |||||
| .last() | |||||
| .removeClass('green') | |||||
| .addClass('red'); | |||||
| } | |||||
| return status && topicDropdown.children('a.ui.label.red').length === 0; | |||||
| }; | |||||
| topicForm.form({ | |||||
| on: 'change', | |||||
| inline: true, | |||||
| fields: { | |||||
| topics: { | |||||
| identifier: 'topics', | |||||
| rules: [ | |||||
| { | |||||
| type: 'validateTopic', | |||||
| value: /^[\u4e00-\u9fa5a-z0-9][\u4e00-\u9fa5a-z0-9-]{0,105}$/, | |||||
| prompt: topicPrompts.formatPrompt | |||||
| }, | |||||
| { | |||||
| type: 'maxCount[25]', | |||||
| prompt: topicPrompts.countPrompt | |||||
| } | |||||
| ] | |||||
| } | |||||
| } | |||||
| }); | |||||
| } | |||||
| // function initTopicbar() { | |||||
| // const mgrBtn = $('#manage_topic'); | |||||
| // const editDiv = $('#topic_edit'); | |||||
| // const viewDiv = $('#repo-topics'); | |||||
| // const saveBtn = $('#save_topic'); | |||||
| // const topicDropdown = $('#topic_edit .dropdown'); | |||||
| // const topicForm = $('#topic_edit.ui.form'); | |||||
| // const topicInput = $("#topics_input") | |||||
| // const topicPrompts = getPrompts(); | |||||
| // mgrBtn.on('click', (e) => { | |||||
| // // viewDiv.hide(); | |||||
| // editDiv.css('display', ''); // show Semantic UI Grid | |||||
| // topicInput.val('') | |||||
| // console.log("-----------------asdasd",$("#topics_input"),$("#topics_input").val()) | |||||
| // stopPropagation(e); | |||||
| // }); | |||||
| // $(document).bind('click',function(){ | |||||
| // editDiv.css('display','none'); | |||||
| // }) | |||||
| // editDiv.click(function(e){ | |||||
| // stopPropagation(e); | |||||
| // }) | |||||
| // function getPrompts() { | |||||
| // const hidePrompt = $('div.hide#validate_prompt'); | |||||
| // const prompts = { | |||||
| // countPrompt: hidePrompt.children('#count_prompt').text(), | |||||
| // formatPrompt: hidePrompt.children('#format_prompt').text() | |||||
| // }; | |||||
| // hidePrompt.remove(); | |||||
| // return prompts; | |||||
| // } | |||||
| // function stopPropagation(e) { | |||||
| // var ev = e || window.event; | |||||
| // if (ev.stopPropagation) { | |||||
| // ev.stopPropagation(); | |||||
| // } | |||||
| // else if (window.event) { | |||||
| // window.event.cancelBubble = true;//兼容IE | |||||
| // } | |||||
| // } | |||||
| // saveBtn.on('click', () => { | |||||
| // const topics = $('input[name=topics]').val(); | |||||
| // $.post( | |||||
| // saveBtn.data('link'), | |||||
| // { | |||||
| // _csrf: csrf, | |||||
| // topics | |||||
| // }, | |||||
| // (_data, _textStatus, xhr) => { | |||||
| // if (xhr.responseJSON.status === 'ok') { | |||||
| // console.log("--------saveBtn------------") | |||||
| // viewDiv.children('.topic').remove(); | |||||
| // if (topics.length) { | |||||
| // const topicArray = topics.split(','); | |||||
| // const last = viewDiv.children('a').last(); | |||||
| // for (let i = 0; i < topicArray.length; i++) { | |||||
| // const link = $('<a class="ui repo-topic small label topic"></a>'); | |||||
| // link.attr( | |||||
| // 'href', | |||||
| // `${AppSubUrl}/explore/repos?q=${encodeURIComponent( | |||||
| // topicArray[i] | |||||
| // )}&topic=1` | |||||
| // ); | |||||
| // link.text(topicArray[i]); | |||||
| // link.insertBefore(last); | |||||
| // } | |||||
| // } | |||||
| // editDiv.css('display', 'none'); | |||||
| // viewDiv.show(); | |||||
| // } | |||||
| // } | |||||
| // ) | |||||
| // .fail((xhr) => { | |||||
| // if (xhr.status === 422) { | |||||
| // if (xhr.responseJSON.invalidTopics.length > 0) { | |||||
| // topicPrompts.formatPrompt = xhr.responseJSON.message; | |||||
| // const {invalidTopics} = xhr.responseJSON; | |||||
| // const topicLables = topicDropdown.children('a.ui.label'); | |||||
| // topics.split(',').forEach((value, index) => { | |||||
| // for (let i = 0; i < invalidTopics.length; i++) { | |||||
| // if (invalidTopics[i] === value) { | |||||
| // topicLables | |||||
| // .eq(index) | |||||
| // .removeClass('green') | |||||
| // .addClass('red'); | |||||
| // } | |||||
| // } | |||||
| // }); | |||||
| // } else { | |||||
| // topicPrompts.countPrompt = xhr.responseJSON.message; | |||||
| // } | |||||
| // } | |||||
| // }) | |||||
| // .always(() => { | |||||
| // topicForm.form('validate form'); | |||||
| // }); | |||||
| // }); | |||||
| // topicDropdown.dropdown({ | |||||
| // allowAdditions: true, | |||||
| // forceSelection: false, | |||||
| // fields: {name: 'description', value: 'data-value'}, | |||||
| // saveRemoteData: false, | |||||
| // label: { | |||||
| // transition: 'horizontal flip', | |||||
| // duration: 200, | |||||
| // variation: false, | |||||
| // blue: true, | |||||
| // basic: true | |||||
| // }, | |||||
| // className: { | |||||
| // label: 'ui small label' | |||||
| // }, | |||||
| // apiSettings: { | |||||
| // url: `${AppSubUrl}/api/v1/topics/search?q={query}`, | |||||
| // throttle: 500, | |||||
| // cache: false, | |||||
| // onResponse(res) { | |||||
| // const formattedResponse = { | |||||
| // success: false, | |||||
| // results: [] | |||||
| // }; | |||||
| // const stripTags = function (text) { | |||||
| // return text.replace(/<[^>]*>?/gm, ''); | |||||
| // }; | |||||
| // const query = stripTags(this.urlData.query.trim()); | |||||
| // let found_query = false; | |||||
| // const current_topics = []; | |||||
| // topicDropdown | |||||
| // .find('div.label.visible.topic,a.label.visible') | |||||
| // .each((_, e) => { | |||||
| // current_topics.push(e.dataset.value); | |||||
| // }); | |||||
| // if (res.topics) { | |||||
| // let found = false; | |||||
| // for (let i = 0; i < res.topics.length; i++) { | |||||
| // // skip currently added tags | |||||
| // if (current_topics.includes(res.topics[i].topic_name)) { | |||||
| // continue; | |||||
| // } | |||||
| // if ( | |||||
| // res.topics[i].topic_name.toLowerCase() === query.toLowerCase() | |||||
| // ) { | |||||
| // found_query = true; | |||||
| // } | |||||
| // formattedResponse.results.push({ | |||||
| // description: res.topics[i].topic_name, | |||||
| // 'data-value': res.topics[i].topic_name | |||||
| // }); | |||||
| // found = true; | |||||
| // } | |||||
| // formattedResponse.success = found; | |||||
| // } | |||||
| // if (query.length > 0 && !found_query) { | |||||
| // formattedResponse.success = true; | |||||
| // formattedResponse.results.unshift({ | |||||
| // description: query, | |||||
| // 'data-value': query | |||||
| // }); | |||||
| // } else if (query.length > 0 && found_query) { | |||||
| // formattedResponse.results.sort((a, b) => { | |||||
| // if (a.description.toLowerCase() === query.toLowerCase()) return -1; | |||||
| // if (b.description.toLowerCase() === query.toLowerCase()) return 1; | |||||
| // if (a.description > b.description) return -1; | |||||
| // if (a.description < b.description) return 1; | |||||
| // return 0; | |||||
| // }); | |||||
| // } | |||||
| // return formattedResponse; | |||||
| // } | |||||
| // }, | |||||
| // onLabelCreate(value) { | |||||
| // value = value.toLowerCase().trim(); | |||||
| // this.attr('data-value', value) | |||||
| // .contents() | |||||
| // .first() | |||||
| // .replaceWith(value); | |||||
| // return $(this); | |||||
| // }, | |||||
| // onAdd(addedValue, _addedText, $addedChoice) { | |||||
| // addedValue = addedValue.toLowerCase().trim(); | |||||
| // $($addedChoice).attr('data-value', addedValue); | |||||
| // $($addedChoice).attr('data-text', addedValue); | |||||
| // } | |||||
| // }); | |||||
| // $.fn.form.settings.rules.validateTopic = function (_values, regExp) { | |||||
| // const topics = topicDropdown.children('a.ui.label'); | |||||
| // const status = | |||||
| // topics.length === 0 || (topics.last().attr('data-value').match(regExp) !== null && topics.last().attr('data-value').length <= 35); | |||||
| // if (!status) { | |||||
| // topics | |||||
| // .last() | |||||
| // .removeClass('green') | |||||
| // .addClass('red'); | |||||
| // } | |||||
| // return status && topicDropdown.children('a.ui.label.red').length === 0; | |||||
| // }; | |||||
| // topicForm.form({ | |||||
| // on: 'change', | |||||
| // inline: true, | |||||
| // fields: { | |||||
| // topics: { | |||||
| // identifier: 'topics', | |||||
| // rules: [ | |||||
| // { | |||||
| // type: 'validateTopic', | |||||
| // value: /^[\u4e00-\u9fa5a-z0-9][\u4e00-\u9fa5a-z0-9-]{0,105}$/, | |||||
| // prompt: topicPrompts.formatPrompt | |||||
| // }, | |||||
| // { | |||||
| // type: 'maxCount[25]', | |||||
| // prompt: topicPrompts.countPrompt | |||||
| // } | |||||
| // ] | |||||
| // } | |||||
| // } | |||||
| // }); | |||||
| // } | |||||
| window.toggleDeadlineForm = function () { | window.toggleDeadlineForm = function () { | ||||
| $('#deadlineForm').fadeToggle(150); | $('#deadlineForm').fadeToggle(150); | ||||
| @@ -140,19 +140,32 @@ | |||||
| border: 1px solid #ffffff; | border: 1px solid #ffffff; | ||||
| } | } | ||||
| } | } | ||||
| } | |||||
| } | |||||
| } | } | ||||
| .item { | .item { | ||||
| border-bottom: 1px solid rgba(34,36,38,.15); | border-bottom: 1px solid rgba(34,36,38,.15); | ||||
| .ui.buttons { | |||||
| .button { | |||||
| box-shadow: none !important; | |||||
| } | |||||
| } | |||||
| } | } | ||||
| .ui.grid > .row { | .ui.grid > .row { | ||||
| align-items: center; | align-items: center; | ||||
| } | } | ||||
| .title { | .title { | ||||
| font-size: 16px; | font-size: 16px; | ||||
| font-weight: bold; | font-weight: bold; | ||||
| margin: 0 6px; | |||||
| margin: 0 6px; | |||||
| overflow: hidden; | |||||
| padding-right: 15px; | |||||
| white-space: nowrap; | |||||
| text-overflow: ellipsis; | |||||
| display: block; | |||||
| } | } | ||||
| .directory-seperator { | .directory-seperator { | ||||
| padding: 0 4px; | padding: 0 4px; | ||||
| @@ -220,3 +220,16 @@ footer .column{margin-bottom:0!important; padding-bottom:0!important;} | |||||
| .ui.vertical.menu .dropdown.item .menu { | .ui.vertical.menu .dropdown.item .menu { | ||||
| left: 50%; | left: 50%; | ||||
| } | } | ||||
| // icon cloudbrain | |||||
| .i-round{display:inline-block;width:18px;height:18px;background:url("/img/icons.svg");background-position: -496px -52px;} | |||||
| .i-bg-organ{background-position: -496px -52px;} | |||||
| .i-bg-stop{background-position: -459px -52px;} | |||||
| .i-bg-running{background-position: -478px -52px;} | |||||
| .i-bg-orange{background-position: -495px -51px;} | |||||
| .i-bg-red{background-position: -532px -52px;} | |||||
| .i-bg-green{background-position: -441px -52px;} | |||||
| .i-bg-used{background-position: -514px -52px;} | |||||
| .icon-bind{background-position: -550px -52px;} | |||||
| .icon-unbind{background-position: -568px -52px;} | |||||
| .showCircle{display:inline-block;background-image:url('/img/loading.gif');background-repeat:no-repeat;width:16px;height:16px;background-size:16px 16px;margin-right:5px;} | |||||