Browse Source

Merge branch 'V20211018' of https://git.openi.org.cn/OpenI/aiforge into issue426

tags/v1.21.12.1
avadesian 3 years ago
parent
commit
b1f9b0e23d
16 changed files with 2533 additions and 282 deletions
  1. +1
    -0
      options/locale/locale_en-US.ini
  2. +1
    -0
      options/locale/locale_zh-CN.ini
  3. +1653
    -0
      public/img/icons.svg
  4. BIN
      public/img/loading.gif
  5. +1
    -1
      templates/base/head_navbar.tmpl
  6. +1
    -1
      templates/base/head_navbar_home.tmpl
  7. +19
    -3
      templates/repo/cloudbrain/index.tmpl
  8. +35
    -46
      templates/repo/datasets/dataset_list.tmpl
  9. +1
    -1
      templates/repo/datasets/index.tmpl
  10. +61
    -7
      templates/repo/home.tmpl
  11. +468
    -0
      web_src/js/components/EditTopics.vue
  12. +4
    -5
      web_src/js/components/MinioUploader.vue
  13. +5
    -2
      web_src/js/components/ObsUploader.vue
  14. +255
    -214
      web_src/js/index.js
  15. +15
    -2
      web_src/less/_dataset.less
  16. +13
    -0
      web_src/less/openi.less

+ 1
- 0
options/locale/locale_en-US.ini View File

@@ -831,6 +831,7 @@ fork = Fork
download_archive = Download Repository

no_desc = No Description
no_label = No labels
quick_guide = Quick Guide
clone_this_repo = Clone this repository
create_new_repo_command = Creating a new repository on the command line


+ 1
- 0
options/locale/locale_zh-CN.ini View File

@@ -833,6 +833,7 @@ fork=派生
download_archive=下载此项目

no_desc=暂无描述
no_label = 暂无标签
quick_guide=快速帮助
clone_this_repo=克隆当前项目
create_new_repo_command=从命令行创建一个新的项目


+ 1653
- 0
public/img/icons.svg
File diff suppressed because it is too large
View File


BIN
public/img/loading.gif View File

Before After
Width: 16  |  Height: 16  |  Size: 2.9 kB

+ 1
- 1
templates/base/head_navbar.tmpl View File

@@ -154,7 +154,7 @@
{{svg "octicon-person" 16}} {{.i18n.Tr "register"}}
</a>
{{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"}}
</a>
</div><!-- end anonymous right menu -->


+ 1
- 1
templates/base/head_navbar_home.tmpl View File

@@ -154,7 +154,7 @@
{{svg "octicon-person" 16}} {{.i18n.Tr "register"}}
</a>
{{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"}}
</a>
</div><!-- end anonymous right menu -->


+ 19
- 3
templates/repo/cloudbrain/index.tmpl View File

@@ -187,6 +187,12 @@
cursor: pointer;
pointer-events: none;
}
.time-show{
font-size: 10px;
margin-top: 0.4rem;
display: inline-block;
}
</style>

<!-- 弹窗 -->
@@ -265,11 +271,21 @@

<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}}
</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 class="seven wide column text right">


+ 35
- 46
templates/repo/datasets/dataset_list.tmpl View File

@@ -1,63 +1,52 @@
<style>

</style>
{{if .Attachments}}
{{range .Attachments}}
<div class="ui grid item" id="{{.UUID}}">
<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}}">
<span class="fitted">{{svg "octicon-cloud-download" 16}}</span> {{.Name}}
{{svg "octicon-cloud-download" 16}} {{.Name}}
</a>
</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>
{{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>
{{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}}
<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>
<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>
{{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}}
<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}}
</div>

</div>
</div>
{{end}}


+ 1
- 1
templates/repo/datasets/index.tmpl View File

@@ -80,7 +80,7 @@
<div class="ui sixteen wide column">
<div class="ui two column stackable grid">
<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 class="column right aligned" style="z-index:1">
<div class="ui right dropdown type jump item">


+ 61
- 7
templates/repo/home.tmpl View File

@@ -55,6 +55,40 @@
#contributorInfo > a.circular:nth-child(9n+8){
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>
<div class="repository file list">
{{template "repo/header" .}}
@@ -62,7 +96,7 @@
{{template "base/alert" .}}
{{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="field">
<div class="ui fluid multiple search selection dropdown">
@@ -78,7 +112,8 @@
<a class="ui button primary" href="javascript:;" id="save_topic"
data-link="{{.RepoLink}}/topics">{{.i18n.Tr "repo.topic.done"}}</a>
</div>
</div>
</div> -->
{{end}}
<div class="hide" id="validate_prompt">
<span id="count_prompt">{{.i18n.Tr "repo.topic.count_prompt"}}</span>
@@ -243,11 +278,30 @@
{{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">


+ 468
- 0
web_src/js/components/EditTopics.vue View File

@@ -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>

+ 4
- 5
web_src/js/components/MinioUploader.vue View File

@@ -1,17 +1,16 @@
<template>
<div class="dropzone-wrapper dataset-files">
<div class="ui pointing below red basic label">
<i class="icon info circle"></i>只有zip格式的数据集才能发起云脑任务
</div>
<div
id="dataset"
class="dropzone"
/>
<p class="upload-info">
{{ file_status_text }}
<span class="success">{{ status }}</span>
<strong class="success text red">{{ status }}</strong>
</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>
</template>



+ 5
- 2
web_src/js/components/ObsUploader.vue View File

@@ -6,9 +6,12 @@
/>
<p class="upload-info">
{{ 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>云脑1提供 <span class="text blue">CPU / GPU</span> 资源,云脑2提供 <span class="text blue">Ascend NPU</span> 资源;调试使用的数据集也需要上传到对应的环境。</p>
</div>
</template>



+ 255
- 214
web_src/js/index.js View File

@@ -36,6 +36,7 @@ import MinioUploader from './components/MinioUploader.vue';
import ObsUploader from './components/ObsUploader.vue';
import EditAboutInfo from './components/EditAboutInfo.vue';
import Images from './components/Images.vue'
import EditTopics from './components/EditTopics.vue'

Vue.use(ElementUI);
Vue.prototype.$axios = axios;
@@ -2967,11 +2968,13 @@ $(document).ready(async () => {
initVueUploader();
initObsUploader();
initVueEditAbout();
initVueEditTopic();
initVueImages();
initTeamSettings();
initCtrlEnterSubmit();
initNavbarContentToggle();
initTopicbar();
// initTopicbar();
// closeTopicbar();
initU2FAuth();
initU2FRegister();
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() {
const el = document.getElementById('images');
console.log("el",el)
@@ -3677,6 +3692,7 @@ function initVueImages() {

new Vue({
el: '#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 () {
$('#deadlineForm').fadeToggle(150);


+ 15
- 2
web_src/less/_dataset.less View File

@@ -140,19 +140,32 @@
border: 1px solid #ffffff;
}
}
}
}
}

.item {
border-bottom: 1px solid rgba(34,36,38,.15);
.ui.buttons {
.button {
box-shadow: none !important;
}
}
}
.ui.grid > .row {
align-items: center;
}
.title {
font-size: 16px;
font-weight: bold;
margin: 0 6px;
margin: 0 6px;
overflow: hidden;
padding-right: 15px;
white-space: nowrap;
text-overflow: ellipsis;
display: block;
}
.directory-seperator {
padding: 0 4px;


+ 13
- 0
web_src/less/openi.less View File

@@ -220,3 +220,16 @@ footer .column{margin-bottom:0!important; padding-bottom:0!important;}
.ui.vertical.menu .dropdown.item .menu {
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;}

Loading…
Cancel
Save