@@ -46,3 +46,6 @@ | |||||
- 点击[这里](https://git.openi.org.cn/OpenI/aiforge/issues)在线提交问题(点击页面右上角绿色按钮**创建任务**) | - 点击[这里](https://git.openi.org.cn/OpenI/aiforge/issues)在线提交问题(点击页面右上角绿色按钮**创建任务**) | ||||
- 加入微信群实时交流,获得进一步的支持 | - 加入微信群实时交流,获得进一步的支持 | ||||
<img src="https://git.openi.org.cn/OpenI/aiforge/wiki/raw/img/wechatgroup.jpg" width=200px /> | <img src="https://git.openi.org.cn/OpenI/aiforge/wiki/raw/img/wechatgroup.jpg" width=200px /> | ||||
## 启智社区小白训练营: | |||||
- 结合案例给大家详细讲解如何使用社区平台,帮助无技术背景的小白成长为启智社区达人 (https://git.openi.org.cn/zeizei/OpenI_Learning) |
@@ -24,11 +24,27 @@ | |||||
.am-pt-20{ padding-top: 2.0rem !important;} | .am-pt-20{ padding-top: 2.0rem !important;} | ||||
.am-pt-30{ padding-top: 3.0rem !important;} | .am-pt-30{ padding-top: 3.0rem !important;} | ||||
.am-pl-30{ padding-left: 3.0rem !important;} | .am-pl-30{ padding-left: 3.0rem !important;} | ||||
.am-pl-50{ padding-left: 5.0em !important;} | |||||
.am-ml-10{ margin-left: 1.0rem !important;} | |||||
.am-ml-30{ margin-left: 3.0rem !important;} | .am-ml-30{ margin-left: 3.0rem !important;} | ||||
.am-pr-30{ padding-right: 3.0rem !important;} | .am-pr-30{ padding-right: 3.0rem !important;} | ||||
.am-mr-30{ margin-right: 3.0rem !important;} | .am-mr-30{ margin-right: 3.0rem !important;} | ||||
.am-lh-18{ line-height: 1.8em;} | .am-lh-18{ line-height: 1.8em;} | ||||
.nowrap{ | |||||
white-space: nowrap; | |||||
overflow: hidden; | |||||
text-overflow: ellipsis; | |||||
} | |||||
.nowrap-2 { | |||||
max-height: 2.837em; | |||||
line-height: 1.4285em; | |||||
overflow: hidden; | |||||
display: -webkit-box; | |||||
-webkit-line-clamp: 2; | |||||
-webkit-box-orient: vertical; | |||||
} | |||||
.opacity5{ opacity:0.5;} | .opacity5{ opacity:0.5;} | ||||
.radius15{ border-radius:1.5rem !important; } | .radius15{ border-radius:1.5rem !important; } | ||||
.radius10{ border-radius:1.0rem !important; } | .radius10{ border-radius:1.0rem !important; } | ||||
@@ -42,12 +58,15 @@ | |||||
box-shadow: 0 2px 4px 0 rgba(34,36,38,.3); | box-shadow: 0 2px 4px 0 rgba(34,36,38,.3); | ||||
} | } | ||||
.ui.blue { | |||||
color: #0366d6; | |||||
} | |||||
.ui.secondary.hometop.segment{ | .ui.secondary.hometop.segment{ | ||||
background: #DFE9F0; | background: #DFE9F0; | ||||
padding-top: 0; | padding-top: 0; | ||||
border: none; | border: none; | ||||
margin-bottom: 90px; | |||||
margin-bottom: 11em; | |||||
} | } | ||||
.ui.secondary.hometop.segment #navbar{ | .ui.secondary.hometop.segment #navbar{ | ||||
z-index: 10; | z-index: 10; | ||||
@@ -68,6 +87,7 @@ | |||||
.homebanner{ | .homebanner{ | ||||
position: relative; | position: relative; | ||||
padding: 100px 32px 80px; | padding: 100px 32px 80px; | ||||
padding-bottom: 0; | |||||
z-index: 9; | z-index: 9; | ||||
} | } | ||||
.homebanner .ui.header .sub.header{ | .homebanner .ui.header .sub.header{ | ||||
@@ -75,10 +95,15 @@ | |||||
} | } | ||||
.bannerpic{ | .bannerpic{ | ||||
position: absolute; | position: absolute; | ||||
right: 50px; | |||||
right: 0px; | |||||
bottom: -64px; | bottom: -64px; | ||||
width: 560px; | width: 560px; | ||||
z-index: 6; | |||||
} | |||||
.homebanner .ui.button{ | |||||
font-weight: normal; | |||||
} | } | ||||
.ui[class*="very padded"].segment.i-code{ | .ui[class*="very padded"].segment.i-code{ | ||||
padding-left: 6.0rem; | padding-left: 6.0rem; | ||||
} | } | ||||
@@ -115,25 +140,141 @@ | |||||
.i-env .ui.cards>.card>.content{ | .i-env .ui.cards>.card>.content{ | ||||
border-top: none; | border-top: none; | ||||
} | } | ||||
.leftline01{ | |||||
#homenews{ | |||||
position: relative; | |||||
z-index: 9; | |||||
bottom: -6em; | |||||
} | |||||
#homenews > p{ | |||||
color: #BBBBBB; | |||||
margin-left: 2.3em; | |||||
} | |||||
.homenews{ | |||||
border-radius: 2em; | |||||
background-color: rgba(16, 16, 16, .9); | |||||
position: relative; | |||||
padding-left: 2.3em !important; | |||||
} | |||||
.homeorg, .homepro, .homemodel, .i-env{ | |||||
position: relative; | |||||
padding-bottom: 5em; | |||||
} | |||||
.homenews::before{ | |||||
content: ''; | |||||
position: absolute; | position: absolute; | ||||
left: 3.0rem; | |||||
left: 3em; | |||||
top: 0; | top: 0; | ||||
bottom: 0; | bottom: 0; | ||||
border-left: 2px solid #505559; | |||||
border-bottom: 2px solid #505559; | |||||
border-radius: 0 0 0 2.0rem; | |||||
width: 2.0rem; | |||||
background-color: rgba(105, 192, 255, .4); | |||||
width: 2px; | |||||
} | |||||
.homenews .time-since{ | |||||
padding-left: 1em; | |||||
color: #888888; | |||||
} | |||||
.homenews a{ | |||||
color: #69C0FF; | |||||
} | } | ||||
.leftline02{ | |||||
.homenews .ui.list>.item>.content{ | |||||
color: #E8E8E8; | |||||
line-height: 1.8em; | |||||
width: calc(100% - 3.25em) !important; | |||||
} | |||||
.homenews .ui.list>.item{ | |||||
padding: 0; | |||||
} | |||||
.newslist{ | |||||
height: 325px; | |||||
overflow: hidden; | |||||
} | |||||
.leftline01, .leftline03, .leftline04{ | |||||
position: absolute; | position: absolute; | ||||
left: 5rem; | |||||
top: calc(-5.0rem - 2px); | |||||
border-top: 2px solid #505559; | |||||
border-right: 2px solid #505559; | |||||
border-radius: 0 2.0rem 0 0; | |||||
width: 17.5rem; | |||||
height: 6.0rem; | |||||
width: 5em; | |||||
border-radius: 0 0 0 4.0em; | |||||
border-left: 2px solid #3291F8; | |||||
border-bottom: 2px solid #3291F8; | |||||
top: -5em; | |||||
bottom: 0; | |||||
left: 2em; | |||||
z-index: 6; | |||||
} | |||||
.leftline02, .leftline02-2 { | |||||
position: absolute; | |||||
left: 7.0em; | |||||
top: -2px; | |||||
bottom: 2px; | |||||
height: auto; | |||||
border-top: 2px solid #3291F8; | |||||
border-right: 2px solid #3291F8; | |||||
border-bottom: 2px solid #3291F8; | |||||
border-radius: 0 4.0em 4.0em 0; | |||||
width: 10em; | |||||
z-index: 6; | |||||
} | |||||
.leftline03{ | |||||
border-radius: 4.0em 0 0 0; | |||||
border-top: 2px solid #3291F8; | |||||
border-bottom:none; | |||||
top: -2.0em; | |||||
} | |||||
.leftline02-2{ | |||||
border-color: rgba(105, 192, 255, .4); | |||||
width: 7em; | |||||
z-index: 5; | |||||
} | |||||
.leftline04{ | |||||
border-radius: 0; | |||||
border-top: none; | |||||
border-bottom: none; | |||||
} | |||||
.homeorg-tit{ | |||||
padding-left: 5em !important; | |||||
} | |||||
.homeorg-tit::after{ | |||||
content: ''; | |||||
position: absolute; | |||||
width: 1.6em; | |||||
height: 1.6em; | |||||
background-color: #FFF; | |||||
border: 2px solid #3291F8; | |||||
left: 2.3em; | |||||
top: 1.3em; | |||||
border-radius: 1em; | |||||
z-index: 9; | |||||
} | |||||
.homeorg-list .card{ | |||||
background-image: linear-gradient(#FFF, #FFF 60%, #DFF0EF) !important; | |||||
box-shadow: none !important; | |||||
} | |||||
.homeorg-list .card .ui.small.header .content{ | |||||
width: calc(100% - 3.25em); | |||||
} | |||||
.homepro-list{ | |||||
position: relative; | |||||
z-index: 9; | |||||
padding: 1.0em 1.0em 3.0em; | |||||
overflow: hidden; | |||||
} | |||||
.homepro-list .ui.card{ | |||||
border-radius: 15px; | |||||
background-color: #FFF; | |||||
box-shadow: 0px 5px 10px 0px rgba(105, 192, 255, 30); | |||||
border: 1px solid rgba(105, 192, 255, 40); | |||||
min-height: 10.8em; | |||||
} | |||||
.homepro-list .ui.card>.content>.header{ | |||||
line-height: 40px !important; | |||||
} | |||||
.homepro-list .swiper-pagination-bullet-active{ | |||||
width: 40px; | |||||
border-radius: 4px; | |||||
} | |||||
.i-env > div{ | |||||
position: relative; | |||||
} | } | ||||
@media only screen and (max-width: 767px) { | @media only screen and (max-width: 767px) { | ||||
@@ -32,6 +32,7 @@ require ( | |||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible | github.com/dgrijalva/jwt-go v3.2.0+incompatible | ||||
github.com/dustin/go-humanize v1.0.0 | github.com/dustin/go-humanize v1.0.0 | ||||
github.com/editorconfig/editorconfig-core-go/v2 v2.1.1 | github.com/editorconfig/editorconfig-core-go/v2 v2.1.1 | ||||
github.com/elliotchance/orderedmap v1.4.0 | |||||
github.com/emirpasic/gods v1.12.0 | github.com/emirpasic/gods v1.12.0 | ||||
github.com/ethantkoenig/rupture v0.0.0-20180203182544-0a76f03a811a | github.com/ethantkoenig/rupture v0.0.0-20180203182544-0a76f03a811a | ||||
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 // indirect | github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 // indirect | ||||
@@ -87,6 +88,7 @@ require ( | |||||
github.com/niklasfasching/go-org v0.1.9 | github.com/niklasfasching/go-org v0.1.9 | ||||
github.com/oliamb/cutter v0.2.2 | github.com/oliamb/cutter v0.2.2 | ||||
github.com/olivere/elastic/v7 v7.0.9 | github.com/olivere/elastic/v7 v7.0.9 | ||||
github.com/patrickmn/go-cache v2.1.0+incompatible | |||||
github.com/pkg/errors v0.9.1 | github.com/pkg/errors v0.9.1 | ||||
github.com/pquerna/otp v1.2.0 | github.com/pquerna/otp v1.2.0 | ||||
github.com/prometheus/client_golang v1.1.0 | github.com/prometheus/client_golang v1.1.0 | ||||
@@ -99,7 +101,7 @@ require ( | |||||
github.com/sergi/go-diff v1.1.0 | github.com/sergi/go-diff v1.1.0 | ||||
github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b // indirect | github.com/shurcooL/httpfs v0.0.0-20190527155220-6a4d4a70508b // indirect | ||||
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd | github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd | ||||
github.com/stretchr/testify v1.4.0 | |||||
github.com/stretchr/testify v1.7.0 | |||||
github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 // indirect | github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 // indirect | ||||
github.com/tinylib/msgp v1.1.2 // indirect | github.com/tinylib/msgp v1.1.2 // indirect | ||||
github.com/tstranex/u2f v1.0.0 | github.com/tstranex/u2f v1.0.0 | ||||
@@ -39,11 +39,9 @@ gitea.com/macaron/inject v0.0.0-20190803172902-8375ba841591/go.mod h1:h6E4kLao1Y | |||||
gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a h1:aOKEXkDTnh4euoH0so/THLXeHtQuqHmDPb1xEk6Ehok= | gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a h1:aOKEXkDTnh4euoH0so/THLXeHtQuqHmDPb1xEk6Ehok= | ||||
gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM= | gitea.com/macaron/inject v0.0.0-20190805023432-d4c86e31027a/go.mod h1:h6E4kLao1Yko6DOU6QDnQPcuoNzvbZqzj2mtPcEn1aM= | ||||
gitea.com/macaron/macaron v1.3.3-0.20190803174002-53e005ff4827/go.mod h1:/rvxMjIkOq4BM8uPUb+VHuU02ZfAO6R4+wD//tiCiRw= | gitea.com/macaron/macaron v1.3.3-0.20190803174002-53e005ff4827/go.mod h1:/rvxMjIkOq4BM8uPUb+VHuU02ZfAO6R4+wD//tiCiRw= | ||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb h1:amL0md6orTj1tXY16ANzVU9FmzQB+W7aJwp8pVDbrmA= | |||||
gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb/go.mod h1:0coI+mSPSwbsyAbOuFllVS38awuk9mevhLD52l50Gjs= | gitea.com/macaron/macaron v1.3.3-0.20190821202302-9646c0587edb/go.mod h1:0coI+mSPSwbsyAbOuFllVS38awuk9mevhLD52l50Gjs= | ||||
gitea.com/macaron/macaron v1.4.0 h1:FY1QDGqyuUzs21K6ChkbYbRUfwL7v2aUrhNEJ0IgsAw= | gitea.com/macaron/macaron v1.4.0 h1:FY1QDGqyuUzs21K6ChkbYbRUfwL7v2aUrhNEJ0IgsAw= | ||||
gitea.com/macaron/macaron v1.4.0/go.mod h1:P7hfDbQjcW22lkYkXlxdRIfWOXxH2+K4EogN4Q0UlLY= | gitea.com/macaron/macaron v1.4.0/go.mod h1:P7hfDbQjcW22lkYkXlxdRIfWOXxH2+K4EogN4Q0UlLY= | ||||
gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705 h1:mvkQGAlON1Z6Y8pqa/+FpYIskk54mazuECUfZK5oTg0= | |||||
gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705/go.mod h1:1ujH0jD6Ca4iK9NL0Q2a7fG2chvXx5hVa7hBfABwpkA= | gitea.com/macaron/session v0.0.0-20190821211443-122c47c5f705/go.mod h1:1ujH0jD6Ca4iK9NL0Q2a7fG2chvXx5hVa7hBfABwpkA= | ||||
gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d h1:XLww3CvnFZkXVwauN67fniDaIpIqsE+9KVcxlZKlvLU= | gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d h1:XLww3CvnFZkXVwauN67fniDaIpIqsE+9KVcxlZKlvLU= | ||||
gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d/go.mod h1:FanKy3WjWb5iw/iZBPk4ggoQT9FcM6bkBPvmDmsH6tY= | gitea.com/macaron/session v0.0.0-20191207215012-613cebf0674d/go.mod h1:FanKy3WjWb5iw/iZBPk4ggoQT9FcM6bkBPvmDmsH6tY= | ||||
@@ -70,7 +68,6 @@ github.com/RichardKnop/machinery v1.6.9 h1:dQu1c7ENgPFrN9qWweEe7xDDvNYGSqEyprK0G | |||||
github.com/RichardKnop/machinery v1.6.9/go.mod h1:BO7MG/5tvdpgMVkOT8V94SEf8x8H8aceRzTt8Tx1IMc= | github.com/RichardKnop/machinery v1.6.9/go.mod h1:BO7MG/5tvdpgMVkOT8V94SEf8x8H8aceRzTt8Tx1IMc= | ||||
github.com/RichardKnop/redsync v1.2.0 h1:gK35hR3zZkQigHKm8wOGb9MpJ9BsrW6MzxezwjTcHP0= | github.com/RichardKnop/redsync v1.2.0 h1:gK35hR3zZkQigHKm8wOGb9MpJ9BsrW6MzxezwjTcHP0= | ||||
github.com/RichardKnop/redsync v1.2.0/go.mod h1:9b8nBGAX3bE2uCfJGSnsDvF23mKyHTZzmvmj5FH3Tp0= | github.com/RichardKnop/redsync v1.2.0/go.mod h1:9b8nBGAX3bE2uCfJGSnsDvF23mKyHTZzmvmj5FH3Tp0= | ||||
github.com/RoaringBitmap/roaring v0.4.21 h1:WJ/zIlNX4wQZ9x8Ey33O1UaD9TCTakYsdLFSBcTwH+8= | |||||
github.com/RoaringBitmap/roaring v0.4.21/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= | github.com/RoaringBitmap/roaring v0.4.21/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= | ||||
github.com/RoaringBitmap/roaring v0.4.23 h1:gpyfd12QohbqhFO4NVDUdoPOCXsyahYRQhINmlHxKeo= | github.com/RoaringBitmap/roaring v0.4.23 h1:gpyfd12QohbqhFO4NVDUdoPOCXsyahYRQhINmlHxKeo= | ||||
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= | github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= | ||||
@@ -140,11 +137,9 @@ github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7 | |||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= | github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= | ||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= | github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= | ||||
github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiGOEoyzgHt9i7k= | github.com/couchbase/ghistogram v0.1.0/go.mod h1:s1Jhy76zqfEecpNWJfWUiKZookAFaiGOEoyzgHt9i7k= | ||||
github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d h1:XMf4E1U+b9E3ElF0mjvfXZdflBRZz4gLp16nQ/QSHQM= | |||||
github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= | github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= | ||||
github.com/couchbase/gomemcached v0.0.0-20191004160342-7b5da2ec40b2 h1:vZryARwW4PSFXd9arwegEywvMTvPuXL3/oa+4L5NTe8= | github.com/couchbase/gomemcached v0.0.0-20191004160342-7b5da2ec40b2 h1:vZryARwW4PSFXd9arwegEywvMTvPuXL3/oa+4L5NTe8= | ||||
github.com/couchbase/gomemcached v0.0.0-20191004160342-7b5da2ec40b2/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= | github.com/couchbase/gomemcached v0.0.0-20191004160342-7b5da2ec40b2/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= | ||||
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b h1:bZ9rKU2/V8sY+NulSfxDOnXTWcs1rySqdF1sVepihvo= | |||||
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= | github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= | ||||
github.com/couchbase/goutils v0.0.0-20191018232750-b49639060d85 h1:0WMIDtuXCKEm4wtAJgAAXa/qtM5O9MariLwgHaRlYmk= | github.com/couchbase/goutils v0.0.0-20191018232750-b49639060d85 h1:0WMIDtuXCKEm4wtAJgAAXa/qtM5O9MariLwgHaRlYmk= | ||||
github.com/couchbase/goutils v0.0.0-20191018232750-b49639060d85/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= | github.com/couchbase/goutils v0.0.0-20191018232750-b49639060d85/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= | ||||
@@ -169,7 +164,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs | |||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= | github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM= | ||||
github.com/denisenkom/go-mssqldb v0.0.0-20190924004331-208c0a498538 h1:bpWCJ5MddHsv4Xtl3azkK89mZzd/vvut32mvAnKbyUA= | |||||
github.com/denisenkom/go-mssqldb v0.0.0-20190924004331-208c0a498538/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= | github.com/denisenkom/go-mssqldb v0.0.0-20190924004331-208c0a498538/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= | ||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg= | github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc h1:VRRKCwnzqk8QCaRC4os14xoKDdbHqqlJtJA0oc1ZAjg= | ||||
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= | github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= | ||||
@@ -185,8 +179,9 @@ github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1 | |||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= | github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= | ||||
github.com/editorconfig/editorconfig-core-go/v2 v2.1.1 h1:mhPg/0hGebcpiiQLqJD2PWWyoHRLEdZ3sXKaEvT1EQU= | github.com/editorconfig/editorconfig-core-go/v2 v2.1.1 h1:mhPg/0hGebcpiiQLqJD2PWWyoHRLEdZ3sXKaEvT1EQU= | ||||
github.com/editorconfig/editorconfig-core-go/v2 v2.1.1/go.mod h1:/LuhWJiQ9Gvo1DhVpa4ssm5qeg8rrztdtI7j/iCie2k= | github.com/editorconfig/editorconfig-core-go/v2 v2.1.1/go.mod h1:/LuhWJiQ9Gvo1DhVpa4ssm5qeg8rrztdtI7j/iCie2k= | ||||
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw= | |||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= | github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= | ||||
github.com/elliotchance/orderedmap v1.4.0 h1:wZtfeEONCbx6in1CZyE6bELEt/vFayMvsxqI5SgsR+A= | |||||
github.com/elliotchance/orderedmap v1.4.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= | |||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= | github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= | ||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= | github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= | ||||
github.com/ethantkoenig/rupture v0.0.0-20180203182544-0a76f03a811a h1:M1bRpaZAn4GSsqu3hdK2R8H0AH9O6vqCTCbm2oAFGfE= | github.com/ethantkoenig/rupture v0.0.0-20180203182544-0a76f03a811a h1:M1bRpaZAn4GSsqu3hdK2R8H0AH9O6vqCTCbm2oAFGfE= | ||||
@@ -306,7 +301,6 @@ github.com/go-swagger/go-swagger v0.21.0 h1:AX9mdfzp6eJtUe92nFrWmbK7ocRgkCDPJs0F | |||||
github.com/go-swagger/go-swagger v0.21.0/go.mod h1:tDb8PdDVFcaE8EPXkMOsuxpL3UEPiwu1UDZar9Z/1RY= | github.com/go-swagger/go-swagger v0.21.0/go.mod h1:tDb8PdDVFcaE8EPXkMOsuxpL3UEPiwu1UDZar9Z/1RY= | ||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0= | github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0= | ||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0= | github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0= | ||||
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y= | |||||
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM= | github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM= | ||||
github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= | github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= | ||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= | github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= | ||||
@@ -330,13 +324,11 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb | |||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= | ||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= | |||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= | ||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= | ||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= | ||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= | ||||
github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ= | |||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | ||||
github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= | github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= | ||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= | ||||
@@ -349,7 +341,6 @@ github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Z | |||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= | ||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= | ||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | ||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= | |||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | ||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= | github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= | ||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
@@ -375,7 +366,6 @@ github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+ | |||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= | ||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | ||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | ||||
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4= | |||||
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | ||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw= | github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw= | ||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= | ||||
@@ -406,7 +396,6 @@ github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVo | |||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= | github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= | ||||
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= | github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI= | ||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= | github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ= | ||||
github.com/hashicorp/go-retryablehttp v0.6.4 h1:BbgctKO892xEyOXnGiaAwIoSq1QZ/SS4AhjoAh9DnfY= | |||||
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= | github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= | ||||
github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM= | github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM= | ||||
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= | github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY= | ||||
@@ -458,7 +447,6 @@ github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4 h1:cTxwSmnaqLoo+ | |||||
github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= | github.com/keybase/go-crypto v0.0.0-20200123153347-de78d2cb44f4/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M= | ||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= | github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= | ||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= | ||||
github.com/klauspost/compress v1.9.2 h1:LfVyl+ZlLlLDeQ/d2AqfGIIH4qEDu0Ed2S5GyhCWIWY= | |||||
github.com/klauspost/compress v1.9.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= | github.com/klauspost/compress v1.9.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= | ||||
github.com/klauspost/compress v1.10.2 h1:Znfn6hXZAHaLPNnlqUYRrBSReFHYybslgv4PTiyz6P0= | github.com/klauspost/compress v1.10.2 h1:Znfn6hXZAHaLPNnlqUYRrBSReFHYybslgv4PTiyz6P0= | ||||
github.com/klauspost/compress v1.10.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= | github.com/klauspost/compress v1.10.2/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= | ||||
@@ -472,7 +460,6 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN | |||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||||
github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= | github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= | ||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= | |||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | ||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= | ||||
@@ -545,7 +532,6 @@ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9 | |||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= | github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8= | ||||
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA= | github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA= | ||||
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= | github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM= | ||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY= | |||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= | github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= | ||||
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= | github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= | ||||
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= | github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= | ||||
@@ -580,6 +566,8 @@ github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFSt | |||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= | github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= | ||||
github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= | github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8= | ||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= | github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= | ||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= | |||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= | |||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= | github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= | ||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= | github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= | ||||
github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg= | github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg= | ||||
@@ -588,7 +576,6 @@ github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ= | |||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= | github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= | ||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= | github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= | ||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= | |||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||
@@ -715,12 +702,13 @@ github.com/streadway/amqp v0.0.0-20190214183023-884228600bc9 h1:wR6aLKdbJ5E8m+NZ | |||||
github.com/streadway/amqp v0.0.0-20190214183023-884228600bc9/go.mod h1:1WNBiOZtZQLpVAyu0iTduoJL9hEsMloAK5XWrtW0xdY= | github.com/streadway/amqp v0.0.0-20190214183023-884228600bc9/go.mod h1:1WNBiOZtZQLpVAyu0iTduoJL9hEsMloAK5XWrtW0xdY= | ||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48= | |||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= | github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= | ||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= | github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= | ||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | ||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | |||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM= | github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM= | ||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8= | github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8= | ||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= | github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= | ||||
@@ -731,7 +719,6 @@ github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481/go.mod h1:ahpPrc7 | |||||
github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= | github.com/tidwall/pretty v0.0.0-20180105212114-65a9db5fad51/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= | ||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= | github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4= | ||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= | github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= | ||||
github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU= | |||||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= | github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= | ||||
github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= | github.com/tinylib/msgp v1.1.2 h1:gWmO7n0Ys2RBEb7GPYB9Ujq8Mk5p2U08lRnmMcGy6BQ= | ||||
github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= | github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= | ||||
@@ -746,7 +733,6 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr | |||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= | github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= | ||||
github.com/unknwon/cae v1.0.0 h1:i39lOFaBXZxhGjQOy/RNbi8uzettCs6OQxpR0xXohGU= | github.com/unknwon/cae v1.0.0 h1:i39lOFaBXZxhGjQOy/RNbi8uzettCs6OQxpR0xXohGU= | ||||
github.com/unknwon/cae v1.0.0/go.mod h1:QaSeRctcea9fK6piJpAMCCPKxzJ01+xFcr2k1m3WRPU= | github.com/unknwon/cae v1.0.0/go.mod h1:QaSeRctcea9fK6piJpAMCCPKxzJ01+xFcr2k1m3WRPU= | ||||
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e h1:GSGeB9EAKY2spCABz6xOX5DbxZEXolK+nBSvmsQwRjM= | |||||
github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= | github.com/unknwon/com v0.0.0-20190804042917-757f69c95f3e/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= | ||||
github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs= | github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs= | ||||
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= | github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM= | ||||
@@ -772,7 +758,6 @@ github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1: | |||||
github.com/yohcop/openid-go v1.0.0 h1:EciJ7ZLETHR3wOtxBvKXx9RV6eyHZpCaSZ1inbBaUXE= | github.com/yohcop/openid-go v1.0.0 h1:EciJ7ZLETHR3wOtxBvKXx9RV6eyHZpCaSZ1inbBaUXE= | ||||
github.com/yohcop/openid-go v1.0.0/go.mod h1:/408xiwkeItSPJZSTPF7+VtZxPkPrRRpRNK2vjGh6yI= | github.com/yohcop/openid-go v1.0.0/go.mod h1:/408xiwkeItSPJZSTPF7+VtZxPkPrRRpRNK2vjGh6yI= | ||||
github.com/yuin/goldmark v1.1.7/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | github.com/yuin/goldmark v1.1.7/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||
github.com/yuin/goldmark v1.1.25 h1:isv+Q6HQAmmL2Ofcmg8QauBmDPlUUnSoNhEcC940Rds= | |||||
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||
github.com/yuin/goldmark v1.1.27 h1:nqDD4MMMQA0lmWq03Z2/myGPYLQoXtmi0rGVs95ntbo= | github.com/yuin/goldmark v1.1.27 h1:nqDD4MMMQA0lmWq03Z2/myGPYLQoXtmi0rGVs95ntbo= | ||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||
@@ -813,16 +798,15 @@ golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8U | |||||
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||
golang.org/x/crypto v0.0.0-20190907121410-71b5226ff739/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | golang.org/x/crypto v0.0.0-20190907121410-71b5226ff739/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad h1:5E5raQxcv+6CZ11RrBYQe5WRbUIWpScjh0kvHZkZIrQ= | |||||
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM= | |||||
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88= | golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79 h1:IaQbIIB2X/Mp/DKctl6ROxz1KyMlKp4uyvL6+kQ7C88= | ||||
golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | golang.org/x/crypto v0.0.0-20200429183012-4b2356b1ed79/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= | ||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= | ||||
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a h1:gHevYm0pO4QUbwy8Dmdr01R5r1BuKtfYqRqF0h/Cbh0= | |||||
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= | golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= | ||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | ||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= | ||||
@@ -832,9 +816,7 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk | |||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | ||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= | ||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= | ||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E= | |||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | ||||
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ= | |||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= | golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= | ||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
@@ -865,7 +847,6 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL | |||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a h1:GuSPYbZzB5/dcLNCwLQLsg3obCJtX9IJhpXkvY7kzk0= | |||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120 h1:EZ3cVSzKOlJxAd8e8YAJ7no8nNypTxexh/YE/xW3ZEY= | golang.org/x/net v0.0.0-20200513185701-a91f0712d120 h1:EZ3cVSzKOlJxAd8e8YAJ7no8nNypTxexh/YE/xW3ZEY= | ||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= | ||||
@@ -876,7 +857,6 @@ golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAG | |||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | ||||
golang.org/x/oauth2 v0.0.0-20190220154721-9b3c75971fc9/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | golang.org/x/oauth2 v0.0.0-20190220154721-9b3c75971fc9/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0= | |||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= | ||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||
@@ -915,13 +895,10 @@ golang.org/x/sys v0.0.0-20190730183949-1393eb018365/go.mod h1:h1NjWce9XRLGQEsW7w | |||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20190907184412-d223b2b6db03/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190907184412-d223b2b6db03/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= | |||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So= | |||||
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884= | |||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f h1:mOhmO9WsBaJCNmaZHPtHs9wOcdqdKCjF6OPJlmDM3KI= | golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f h1:mOhmO9WsBaJCNmaZHPtHs9wOcdqdKCjF6OPJlmDM3KI= | ||||
golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200509044756-6aff5f38e54f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
@@ -932,7 +909,6 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | |||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs= | |||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= | golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI= | ||||
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||
@@ -955,14 +931,11 @@ golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgw | |||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= | ||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||||
golang.org/x/tools v0.0.0-20200225230052-807dcd883420 h1:4RJNOV+2rLxMEfr6QIpC7GEv9MjD6ApGXTCLrNF9+eA= | |||||
golang.org/x/tools v0.0.0-20200225230052-807dcd883420/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= | golang.org/x/tools v0.0.0-20200225230052-807dcd883420/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= | ||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224 h1:azwY/v0y0K4mFHVsg5+UrTgchqALYWpqVo6vL5OmkmI= | |||||
golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= | golang.org/x/tools v0.0.0-20200325010219-a49f79bcc224/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= | ||||
golang.org/x/tools v0.0.0-20200515220128-d3bf790afa53 h1:vmsb6v0zUdmUlXfwKaYrHPPRCV0lHq/IwNIf0ASGjyQ= | golang.org/x/tools v0.0.0-20200515220128-d3bf790afa53 h1:vmsb6v0zUdmUlXfwKaYrHPPRCV0lHq/IwNIf0ASGjyQ= | ||||
golang.org/x/tools v0.0.0-20200515220128-d3bf790afa53/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= | golang.org/x/tools v0.0.0-20200515220128-d3bf790afa53/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= | ||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA= | |||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= | ||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
@@ -984,7 +957,6 @@ google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 | |||||
google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | google.golang.org/appengine v1.6.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= | ||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= | ||||
google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= | google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= | ||||
google.golang.org/appengine v1.6.4 h1:WiKh4+/eMB2HaY7QhCfW/R7MuRAoA8QMCSJA6jP5/fo= | |||||
google.golang.org/appengine v1.6.4/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= | google.golang.org/appengine v1.6.4/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= | ||||
google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= | google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= | ||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= | ||||
@@ -1016,7 +988,6 @@ google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLY | |||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | ||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | ||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= | ||||
google.golang.org/protobuf v1.21.0 h1:qdOKuR/EIArgaWNjetjgTzgVTAZ+S/WXVrq9HW9zimw= | |||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= | ||||
google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY= | google.golang.org/protobuf v1.22.0 h1:cJv5/xdbk1NnMPR1VP9+HU6gupuG9MLBoH1r6RHZ2MY= | ||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||
@@ -1027,7 +998,6 @@ gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 h1:nn6Zav2sOQHCFJHEspya8 | |||||
gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= | gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw= | ||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= | |||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= | ||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
@@ -1058,12 +1028,12 @@ gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= | |||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= | gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= | ||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= | gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= | ||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= | |||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= | |||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= | gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= | ||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | |||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | |||||
grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= | grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= | ||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | ||||
honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | honnef.co/go/tools v0.0.0-20180920025451-e3ad64cb4ed3/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= | ||||
@@ -1078,13 +1048,11 @@ sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2 | |||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= | sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0= | ||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs= | strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs= | ||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY= | strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY= | ||||
xorm.io/builder v0.3.6 h1:ha28mQ2M+TFx96Hxo+iq6tQgnkC9IZkM6D8w9sKHHF8= | |||||
xorm.io/builder v0.3.6/go.mod h1:LEFAPISnRzG+zxaxj2vPicRwz67BdhFreKg8yv8/TgU= | xorm.io/builder v0.3.6/go.mod h1:LEFAPISnRzG+zxaxj2vPicRwz67BdhFreKg8yv8/TgU= | ||||
xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI= | xorm.io/builder v0.3.7 h1:2pETdKRK+2QG4mLX4oODHEhn5Z8j1m8sXa7jfu+/SZI= | ||||
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= | xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE= | ||||
xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw= | xorm.io/core v0.7.2 h1:mEO22A2Z7a3fPaZMk6gKL/jMD80iiyNwRrX5HOv3XLw= | ||||
xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM= | xorm.io/core v0.7.2/go.mod h1:jJfd0UAEzZ4t87nbQYtVjmqpIODugN6PD2D9E+dJvdM= | ||||
xorm.io/xorm v0.8.0 h1:iALxgJrX8O00f8Jk22GbZwPmxJNgssV5Mv4uc2HL9PM= | |||||
xorm.io/xorm v0.8.0/go.mod h1:ZkJLEYLoVyg7amJK/5r779bHyzs2AU8f8VMiP6BM7uY= | xorm.io/xorm v0.8.0/go.mod h1:ZkJLEYLoVyg7amJK/5r779bHyzs2AU8f8VMiP6BM7uY= | ||||
xorm.io/xorm v1.0.1 h1:/lITxpJtkZauNpdzj+L9CN/3OQxZaABrbergMcJu+Cw= | xorm.io/xorm v1.0.1 h1:/lITxpJtkZauNpdzj+L9CN/3OQxZaABrbergMcJu+Cw= | ||||
xorm.io/xorm v1.0.1/go.mod h1:o4vnEsQ5V2F1/WK6w4XTwmiWJeGj82tqjAnHe44wVHY= | xorm.io/xorm v1.0.1/go.mod h1:o4vnEsQ5V2F1/WK6w4XTwmiWJeGj82tqjAnHe44wVHY= |
@@ -346,6 +346,25 @@ func GetFeeds(opts GetFeedsOptions) ([]*Action, error) { | |||||
return actions, nil | return actions, nil | ||||
} | } | ||||
func GetLast20PublicFeeds() ([]*Action, error) { | |||||
cond := builder.NewCond() | |||||
cond = cond.And(builder.Eq{"is_private": false}) | |||||
cond = cond.And(builder.Eq{"is_deleted": false}) | |||||
actions := make([]*Action, 0, 20) | |||||
if err := x.Limit(20).Desc("id").Where(cond).Find(&actions); err != nil { | |||||
return nil, fmt.Errorf("Find: %v", err) | |||||
} | |||||
if err := ActionList(actions).LoadAttributes(); err != nil { | |||||
return nil, fmt.Errorf("LoadAttributes: %v", err) | |||||
} | |||||
return actions, nil | |||||
} | |||||
func GetUnTransformedActions() ([]*Action, error) { | func GetUnTransformedActions() ([]*Action, error) { | ||||
actions := make([]*Action, 0, 10) | actions := make([]*Action, 0, 10) | ||||
err := x.Where("op_type = ?", ActionCommitRepo). | err := x.Where("op_type = ?", ActionCommitRepo). | ||||
@@ -439,6 +439,19 @@ func GetModelArtsUserAttachments(userID int64) ([]*AttachmentUsername, error) { | |||||
return getModelArtsUserAttachments(x, userID) | return getModelArtsUserAttachments(x, userID) | ||||
} | } | ||||
func getModelArtsTrainAttachments(e Engine, userID int64) ([]*AttachmentUsername, error) { | |||||
attachments := make([]*AttachmentUsername, 0, 10) | |||||
if err := e.Table("attachment").Join("LEFT", "`user`", "attachment.uploader_id "+ | |||||
"= `user`.id").Where("attachment.type = ? and (uploader_id= ? or is_private = ?) and attachment.decompress_state = ?", TypeCloudBrainTwo, userID, false, DecompressStateDone).Find(&attachments); err != nil { | |||||
return nil, err | |||||
} | |||||
return attachments, nil | |||||
} | |||||
func GetModelArtsTrainAttachments(userID int64) ([]*AttachmentUsername, error) { | |||||
return getModelArtsTrainAttachments(x, userID) | |||||
} | |||||
func CanDelAttachment(isSigned bool, user *User, attach *Attachment) bool { | func CanDelAttachment(isSigned bool, user *User, attach *Attachment) bool { | ||||
if !isSigned { | if !isSigned { | ||||
return false | return false | ||||
@@ -19,6 +19,9 @@ type JobType string | |||||
type ModelArtsJobStatus string | type ModelArtsJobStatus string | ||||
const ( | const ( | ||||
NPUResource = "NPU" | |||||
GPUResource = "CPU/GPU" | |||||
JobWaiting CloudbrainStatus = "WAITING" | JobWaiting CloudbrainStatus = "WAITING" | ||||
JobStopped CloudbrainStatus = "STOPPED" | JobStopped CloudbrainStatus = "STOPPED" | ||||
JobSucceeded CloudbrainStatus = "SUCCEEDED" | JobSucceeded CloudbrainStatus = "SUCCEEDED" | ||||
@@ -88,6 +91,9 @@ type Cloudbrain struct { | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` | ||||
Duration int64 | Duration int64 | ||||
TrainJobDuration string | TrainJobDuration string | ||||
Image string //GPU镜像名称 | |||||
GpuQueue string //GPU类型即GPU队列 | |||||
ResourceSpecId int //GPU规格id | |||||
DeletedAt time.Time `xorm:"deleted"` | DeletedAt time.Time `xorm:"deleted"` | ||||
CanDebug bool `xorm:"-"` | CanDebug bool `xorm:"-"` | ||||
CanDel bool `xorm:"-"` | CanDel bool `xorm:"-"` | ||||
@@ -204,6 +210,7 @@ type CloudbrainsOptions struct { | |||||
JobType string | JobType string | ||||
VersionName string | VersionName string | ||||
IsLatestVersion string | IsLatestVersion string | ||||
JobTypeNot bool | |||||
} | } | ||||
type TaskPod struct { | type TaskPod struct { | ||||
@@ -888,9 +895,15 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { | |||||
} | } | ||||
if (opts.JobType) != "" { | if (opts.JobType) != "" { | ||||
cond = cond.And( | |||||
builder.Eq{"cloudbrain.job_type": opts.JobType}, | |||||
) | |||||
if opts.JobTypeNot { | |||||
cond = cond.And( | |||||
builder.Neq{"cloudbrain.job_type": opts.JobType}, | |||||
) | |||||
} else { | |||||
cond = cond.And( | |||||
builder.Eq{"cloudbrain.job_type": opts.JobType}, | |||||
) | |||||
} | |||||
} | } | ||||
if (opts.IsLatestVersion) != "" { | if (opts.IsLatestVersion) != "" { | ||||
@@ -962,7 +975,9 @@ func QueryModelTrainJobList(repoId int64) ([]*CloudbrainInfo, int, error) { | |||||
cond = cond.And( | cond = cond.And( | ||||
builder.Eq{"Status": "COMPLETED"}, | builder.Eq{"Status": "COMPLETED"}, | ||||
) | ) | ||||
cond = cond.And( | |||||
builder.Eq{"job_type": "TRAIN"}, | |||||
) | |||||
cloudbrains := make([]*CloudbrainInfo, 0) | cloudbrains := make([]*CloudbrainInfo, 0) | ||||
if err := sess.Select("job_id,job_name").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC"). | if err := sess.Select("job_id,job_name").Table(&Cloudbrain{}).Where(cond).OrderBy("created_unix DESC"). | ||||
Find(&cloudbrains); err != nil { | Find(&cloudbrains); err != nil { | ||||
@@ -1195,3 +1210,28 @@ func GetCloudbrainTrainJobCountByUserID(userID int64) (int, error) { | |||||
And("job_type = ? and user_id = ? and type = ?", JobTypeTrain, userID, TypeCloudBrainTwo).Count(new(Cloudbrain)) | And("job_type = ? and user_id = ? and type = ?", JobTypeTrain, userID, TypeCloudBrainTwo).Count(new(Cloudbrain)) | ||||
return int(count), err | return int(count), err | ||||
} | } | ||||
func RestartCloudbrain(old *Cloudbrain, new *Cloudbrain) (err error) { | |||||
sess := x.NewSession() | |||||
defer sess.Close() | |||||
if err = sess.Begin(); err != nil { | |||||
return err | |||||
} | |||||
if _, err = sess.Delete(old); err != nil { | |||||
sess.Rollback() | |||||
return err | |||||
} | |||||
if _, err = sess.Insert(new); err != nil { | |||||
sess.Rollback() | |||||
return err | |||||
} | |||||
if err = sess.Commit(); err != nil { | |||||
return err | |||||
} | |||||
return nil | |||||
} |
@@ -1999,3 +1999,16 @@ func IsErrJobNotExist(err error) bool { | |||||
func (err ErrJobNotExist) Error() string { | func (err ErrJobNotExist) Error() string { | ||||
return fmt.Sprintf("the job does not exist") | return fmt.Sprintf("the job does not exist") | ||||
} | } | ||||
type ErrTagNotExist struct { | |||||
TagID int64 | |||||
} | |||||
func (err ErrTagNotExist) Error() string { | |||||
return fmt.Sprintf("the tag does not exist") | |||||
} | |||||
func IsErrTagNotExist(err error) bool { | |||||
_, ok := err.(ErrTagNotExist) | |||||
return ok | |||||
} |
@@ -134,6 +134,8 @@ func init() { | |||||
new(BlockChain), | new(BlockChain), | ||||
new(RecommendOrg), | new(RecommendOrg), | ||||
new(AiModelManage), | new(AiModelManage), | ||||
new(OfficialTag), | |||||
new(OfficialTagRepos), | |||||
) | ) | ||||
tablesStatistic = append(tablesStatistic, | tablesStatistic = append(tablesStatistic, | ||||
@@ -141,6 +143,12 @@ func init() { | |||||
new(SummaryStatistic), | new(SummaryStatistic), | ||||
new(UserBusinessAnalysis), | new(UserBusinessAnalysis), | ||||
new(UserBusinessAnalysisAll), | new(UserBusinessAnalysisAll), | ||||
new(UserBusinessAnalysisCurrentYear), | |||||
new(UserBusinessAnalysisLast30Day), | |||||
new(UserBusinessAnalysisLastMonth), | |||||
new(UserBusinessAnalysisCurrentMonth), | |||||
new(UserBusinessAnalysisCurrentWeek), | |||||
new(UserBusinessAnalysisYesterday), | |||||
new(UserLoginLog), | new(UserLoginLog), | ||||
) | ) | ||||
@@ -6,6 +6,7 @@ | |||||
package models | package models | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/modules/git" | |||||
"context" | "context" | ||||
"crypto/md5" | "crypto/md5" | ||||
"errors" | "errors" | ||||
@@ -2519,3 +2520,53 @@ func UpdateRepositoryCommitNum(repo *Repository) error { | |||||
return nil | return nil | ||||
} | } | ||||
type RepoFile struct { | |||||
CommitId string | |||||
Content []byte | |||||
} | |||||
// ReadLatestFileInRepo read latest version of file in repository | |||||
// return a RepoFile | |||||
func ReadLatestFileInRepo(userName, repoName, refName, treePath string) (*RepoFile, error) { | |||||
var err error | |||||
repoPath := RepoPath(userName, repoName) | |||||
gitRepo, err := git.OpenRepository(repoPath) | |||||
if err != nil { | |||||
log.Error("ReadLatestFileInRepo error when OpenRepository,error=%v", err) | |||||
return nil, err | |||||
} | |||||
commitID, err := gitRepo.GetBranchCommitID(refName) | |||||
if err != nil { | |||||
log.Error("ReadLatestFileInRepo error when GetBranchCommitID,error=%v", err) | |||||
return nil, err | |||||
} | |||||
commit, err := gitRepo.GetBranchCommit(refName) | |||||
if err != nil { | |||||
log.Error("ReadLatestFileInRepo error when GetBranchCommit,error=%v", err) | |||||
return nil, err | |||||
} | |||||
blob, err := commit.GetBlobByPath(treePath) | |||||
if err != nil { | |||||
log.Error("ReadLatestFileInRepo error when GetBlobByPath,error=%v", err) | |||||
return nil, err | |||||
} | |||||
reader, err := blob.DataAsync() | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
defer func() { | |||||
if err = reader.Close(); err != nil { | |||||
log.Error("ReadLatestFileInRepo: Close: %v", err) | |||||
} | |||||
}() | |||||
buf := make([]byte, 1024) | |||||
n, _ := reader.Read(buf) | |||||
if n >= 0 { | |||||
buf = buf[:n] | |||||
} | |||||
return &RepoFile{CommitId: commitID, Content: buf}, nil | |||||
} |
@@ -0,0 +1,163 @@ | |||||
package models | |||||
import ( | |||||
"code.gitea.io/gitea/modules/log" | |||||
"code.gitea.io/gitea/modules/timeutil" | |||||
"fmt" | |||||
) | |||||
type OfficialTag struct { | |||||
ID int64 `xorm:"pk autoincr"` | |||||
Name string `xorm:"NOT NULL"` | |||||
Code string `xorm:"NOT NULL"` | |||||
Limit int `xorm:"NOT NULL default(-1)"` | |||||
Status int `xorm:"NOT NULL default(0)"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||||
} | |||||
type OfficialTagRepos struct { | |||||
ID int64 `xorm:"pk autoincr"` | |||||
OrgID int64 `xorm:"NOT NULL INDEX"` | |||||
TagID int64 `xorm:"NOT NULL"` | |||||
RepoID int64 `xorm:"NOT NULL INDEX"` | |||||
CreatedUnix timeutil.TimeStamp `xorm:"created"` | |||||
UpdatedUnix timeutil.TimeStamp `xorm:"updated"` | |||||
} | |||||
type TagReposBrief struct { | |||||
RepoID int64 | |||||
RepoName string | |||||
TagID int64 | |||||
} | |||||
type TagReposSelected struct { | |||||
RepoID int64 | |||||
RepoName string | |||||
Selected bool | |||||
} | |||||
type TagsDetail struct { | |||||
TagId int64 | |||||
TagName string | |||||
TagLimit int | |||||
RepoList []Repository | |||||
} | |||||
func GetTagByID(id int64) (*OfficialTag, error) { | |||||
r := &OfficialTag{ | |||||
ID: id, | |||||
} | |||||
has, err := x.Get(r) | |||||
if err != nil { | |||||
return nil, err | |||||
} else if !has { | |||||
return nil, ErrTagNotExist{0} | |||||
} | |||||
return r, nil | |||||
} | |||||
func UpdateTagReposByID(tagID, orgID int64, repoIdList []int64) error { | |||||
sess := x.NewSession() | |||||
defer sess.Close() | |||||
if err := sess.Begin(); err != nil { | |||||
return fmt.Errorf("UpdateTagReposByID[tagId: %d, orgID: %d,error:%v", tagID, orgID, err) | |||||
} | |||||
//delete old tag repos | |||||
r := &OfficialTagRepos{ | |||||
TagID: tagID, | |||||
OrgID: orgID, | |||||
} | |||||
_, err := sess.Delete(r) | |||||
if err != nil { | |||||
return err | |||||
} | |||||
if len(repoIdList) == 0 { | |||||
return sess.Commit() | |||||
} | |||||
//add new tag repos | |||||
data := make([]*OfficialTagRepos, 0) | |||||
for _, repoId := range repoIdList { | |||||
data = append(data, &OfficialTagRepos{ | |||||
OrgID: orgID, | |||||
TagID: tagID, | |||||
RepoID: repoId, | |||||
}) | |||||
} | |||||
_, err = sess.Insert(&data) | |||||
if err != nil { | |||||
sess.Rollback() | |||||
return err | |||||
} | |||||
return sess.Commit() | |||||
} | |||||
func GetTagRepos(tagID, orgID int64) ([]TagReposSelected, error) { | |||||
t := make([]TagReposBrief, 0) | |||||
const SQLCmd = "select t1.id as repo_id,t1.name as repo_name,t2.id as tag_id from repository t1 left join official_tag_repos t2 on (t1.id = t2.repo_id and t2.tag_id = ?) where t1.owner_id = ? and t1.is_private = false order by t1.updated_unix desc" | |||||
if err := x.SQL(SQLCmd, tagID, orgID).Find(&t); err != nil { | |||||
return nil, err | |||||
} | |||||
r := make([]TagReposSelected, 0) | |||||
for _, v := range t { | |||||
selected := false | |||||
if v.TagID > 0 { | |||||
selected = true | |||||
} | |||||
r = append(r, TagReposSelected{ | |||||
RepoID: v.RepoID, | |||||
RepoName: v.RepoName, | |||||
Selected: selected, | |||||
}) | |||||
} | |||||
return r, nil | |||||
} | |||||
func GetAllOfficialTagRepos(orgID int64, isOwner bool) ([]TagsDetail, error) { | |||||
result := make([]TagsDetail, 0) | |||||
tags, err := GetAllOfficialTags() | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
for _, tag := range tags { | |||||
repos, err := GetOfficialTagDetail(orgID, tag.ID) | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
if len(repos) == 0 && !isOwner { | |||||
continue | |||||
} | |||||
result = append(result, TagsDetail{ | |||||
TagId: tag.ID, | |||||
TagName: tag.Name, | |||||
TagLimit: tag.Limit, | |||||
RepoList: repos, | |||||
}) | |||||
} | |||||
return result, nil | |||||
} | |||||
func GetOfficialTagDetail(orgID, tagId int64) ([]Repository, error) { | |||||
t := make([]Repository, 0) | |||||
const SQLCmd = "select t2.* from official_tag_repos t1 inner join repository t2 on t1.repo_id = t2.id where t1.org_id = ? and t1.tag_id=? order by t2.updated_unix desc" | |||||
if err := x.SQL(SQLCmd, orgID, tagId).Find(&t); err != nil { | |||||
return nil, err | |||||
} | |||||
return t, nil | |||||
} | |||||
func GetAllOfficialTags() ([]OfficialTag, error) { | |||||
//todo redis? | |||||
o := make([]OfficialTag, 0) | |||||
err := x.Where("status = ?", 0).OrderBy("updated_unix desc").Find(&o) | |||||
if err != nil { | |||||
log.Error("GetAllOfficialTags error,%v", err) | |||||
return nil, err | |||||
} | |||||
return o, nil | |||||
} |
@@ -280,13 +280,16 @@ func notifyWatchers(e Engine, actions ...*Action) error { | |||||
// NotifyWatchers creates batch of actions for every watcher. | // NotifyWatchers creates batch of actions for every watcher. | ||||
func NotifyWatchers(actions ...*Action) error { | func NotifyWatchers(actions ...*Action) error { | ||||
error := notifyWatchers(x, actions...) | |||||
producer(actions...) | producer(actions...) | ||||
return notifyWatchers(x, actions...) | |||||
return error | |||||
} | } | ||||
func producer(actions ...*Action) { | func producer(actions ...*Action) { | ||||
for _, action := range actions { | for _, action := range actions { | ||||
ActionChan <- action | |||||
if !action.IsPrivate{ | |||||
ActionChan <- action | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -10,10 +10,12 @@ import ( | |||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/timeutil" | "code.gitea.io/gitea/modules/timeutil" | ||||
"xorm.io/builder" | "xorm.io/builder" | ||||
"xorm.io/xorm" | |||||
) | ) | ||||
const ( | const ( | ||||
Page_SIZE = 2000 | |||||
PAGE_SIZE = 2000 | |||||
BATCH_INSERT_SIZE = 50 | |||||
) | ) | ||||
type UserBusinessAnalysisAll struct { | type UserBusinessAnalysisAll struct { | ||||
@@ -163,14 +165,6 @@ func (ulist UserBusinessAnalysisList) Less(i, j int) bool { | |||||
return ulist[i].ID > ulist[j].ID | return ulist[i].ID > ulist[j].ID | ||||
} | } | ||||
type UserBusinessAnalysisAllList []*UserBusinessAnalysisAll | |||||
func (ulist UserBusinessAnalysisAllList) Swap(i, j int) { ulist[i], ulist[j] = ulist[j], ulist[i] } | |||||
func (ulist UserBusinessAnalysisAllList) Len() int { return len(ulist) } | |||||
func (ulist UserBusinessAnalysisAllList) Less(i, j int) bool { | |||||
return ulist[i].ID > ulist[j].ID | |||||
} | |||||
func getLastCountDate() int64 { | func getLastCountDate() int64 { | ||||
statictisSess := xStatistic.NewSession() | statictisSess := xStatistic.NewSession() | ||||
defer statictisSess.Close() | defer statictisSess.Close() | ||||
@@ -189,6 +183,29 @@ func getLastCountDate() int64 { | |||||
return pageStartTime.Unix() | return pageStartTime.Unix() | ||||
} | } | ||||
func QueryUserStaticDataByTableName(start int, pageSize int, tableName string, queryObj interface{}, userName string) ([]*UserBusinessAnalysisAll, int64) { | |||||
statictisSess := xStatistic.NewSession() | |||||
defer statictisSess.Close() | |||||
var cond = builder.NewCond() | |||||
if len(userName) > 0 { | |||||
cond = cond.And( | |||||
builder.Like{"name", userName}, | |||||
) | |||||
} | |||||
allCount, err := statictisSess.Where(cond).Count(queryObj) | |||||
if err != nil { | |||||
log.Info("query error." + err.Error()) | |||||
return nil, 0 | |||||
} | |||||
log.Info("query return total:" + fmt.Sprint(allCount)) | |||||
userBusinessAnalysisAllList := make([]*UserBusinessAnalysisAll, 0) | |||||
if err := statictisSess.Table(tableName).Where(cond).OrderBy("commit_count desc,id desc").Limit(pageSize, start). | |||||
Find(&userBusinessAnalysisAllList); err != nil { | |||||
return nil, 0 | |||||
} | |||||
return userBusinessAnalysisAllList, allCount | |||||
} | |||||
func QueryUserStaticDataAll(opts *UserBusinessAnalysisQueryOptions) ([]*UserBusinessAnalysisAll, int64) { | func QueryUserStaticDataAll(opts *UserBusinessAnalysisQueryOptions) ([]*UserBusinessAnalysisAll, int64) { | ||||
log.Info("query startTime =" + fmt.Sprint(opts.StartTime) + " endTime=" + fmt.Sprint(opts.EndTime) + " isAll=" + fmt.Sprint(opts.IsAll)) | log.Info("query startTime =" + fmt.Sprint(opts.StartTime) + " endTime=" + fmt.Sprint(opts.EndTime) + " isAll=" + fmt.Sprint(opts.IsAll)) | ||||
@@ -202,9 +219,9 @@ func QueryUserStaticDataAll(opts *UserBusinessAnalysisQueryOptions) ([]*UserBusi | |||||
} | } | ||||
log.Info("query return total:" + fmt.Sprint(allCount)) | log.Info("query return total:" + fmt.Sprint(allCount)) | ||||
pageSize := 1000 | |||||
pageSize := PAGE_SIZE | |||||
totalPage := int(allCount) / pageSize | totalPage := int(allCount) / pageSize | ||||
userBusinessAnalysisReturnList := UserBusinessAnalysisAllList{} | |||||
userBusinessAnalysisReturnList := make([]*UserBusinessAnalysisAll, 0) | |||||
for i := 0; i <= int(totalPage); i++ { | for i := 0; i <= int(totalPage); i++ { | ||||
userBusinessAnalysisAllList := make([]*UserBusinessAnalysisAll, 0) | userBusinessAnalysisAllList := make([]*UserBusinessAnalysisAll, 0) | ||||
if err := statictisSess.Table("user_business_analysis_all").OrderBy("id desc").Limit(pageSize, i*pageSize). | if err := statictisSess.Table("user_business_analysis_all").OrderBy("id desc").Limit(pageSize, i*pageSize). | ||||
@@ -217,7 +234,6 @@ func QueryUserStaticDataAll(opts *UserBusinessAnalysisQueryOptions) ([]*UserBusi | |||||
} | } | ||||
} | } | ||||
sort.Sort(userBusinessAnalysisReturnList) | |||||
log.Info("return size=" + fmt.Sprint(len(userBusinessAnalysisReturnList))) | log.Info("return size=" + fmt.Sprint(len(userBusinessAnalysisReturnList))) | ||||
return userBusinessAnalysisReturnList, allCount | return userBusinessAnalysisReturnList, allCount | ||||
} | } | ||||
@@ -337,28 +353,24 @@ func QueryUserStaticDataPage(opts *UserBusinessAnalysisQueryOptions) ([]*UserBus | |||||
return userBusinessAnalysisReturnList, count | return userBusinessAnalysisReturnList, count | ||||
} | } | ||||
func RefreshUserStaticAllTabel(wikiCountMap map[string]int, CommitCodeSizeMap map[string]*git.UserKPIStats) { | |||||
func refreshUserStaticTable(wikiCountMap map[string]int, CommitCodeSizeMap map[string]*git.UserKPIStats, tableName string, pageStartTime time.Time, pageEndTime time.Time) { | |||||
sess := x.NewSession() | sess := x.NewSession() | ||||
defer sess.Close() | defer sess.Close() | ||||
statictisSess := xStatistic.NewSession() | statictisSess := xStatistic.NewSession() | ||||
defer statictisSess.Close() | defer statictisSess.Close() | ||||
log.Info("truncate all data from table: user_business_analysis_all") | |||||
statictisSess.Exec("TRUNCATE TABLE user_business_analysis_all") | |||||
log.Info("truncate all data from table: " + tableName) | |||||
statictisSess.Exec("TRUNCATE TABLE " + tableName) | |||||
currentTimeNow := time.Now() | |||||
startTime := currentTimeNow.AddDate(0, 0, -1) | |||||
pageStartTime := time.Date(2021, 11, 5, 0, 0, 0, 0, currentTimeNow.Location()) | |||||
log.Info("pageStartTime:" + pageStartTime.Format("2006-01-02 15:04:05")) | log.Info("pageStartTime:" + pageStartTime.Format("2006-01-02 15:04:05")) | ||||
pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location()) | |||||
log.Info("pageEndTime time:" + pageEndTime.Format("2006-01-02 15:04:05")) | log.Info("pageEndTime time:" + pageEndTime.Format("2006-01-02 15:04:05")) | ||||
start_unix := pageStartTime.Unix() | start_unix := pageStartTime.Unix() | ||||
end_unix := pageEndTime.Unix() | end_unix := pageEndTime.Unix() | ||||
currentTimeNow := time.Now() | |||||
startTime := currentTimeNow.AddDate(0, 0, -1) | |||||
CodeMergeCountMap := queryPullRequest(start_unix, end_unix) | CodeMergeCountMap := queryPullRequest(start_unix, end_unix) | ||||
CommitCountMap := queryCommitAction(start_unix, end_unix, 5) | CommitCountMap := queryCommitAction(start_unix, end_unix, 5) | ||||
IssueCountMap := queryCreateIssue(start_unix, end_unix) | IssueCountMap := queryCreateIssue(start_unix, end_unix) | ||||
@@ -385,12 +397,14 @@ func RefreshUserStaticAllTabel(wikiCountMap map[string]int, CommitCodeSizeMap ma | |||||
} | } | ||||
var indexTotal int64 | var indexTotal int64 | ||||
indexTotal = 0 | indexTotal = 0 | ||||
insertCount := 0 | |||||
dateRecordBatch := make([]UserBusinessAnalysisAll, 0) | |||||
for { | for { | ||||
sess.Select("`user`.*").Table("user").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
sess.Select("`user`.*").Table("user").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
userList := make([]*User, 0) | userList := make([]*User, 0) | ||||
sess.Find(&userList) | sess.Find(&userList) | ||||
for i, userRecord := range userList { | |||||
log.Info("insert all static, i=" + fmt.Sprint(i) + " userName=" + userRecord.Name) | |||||
for _, userRecord := range userList { | |||||
var dateRecordAll UserBusinessAnalysisAll | var dateRecordAll UserBusinessAnalysisAll | ||||
dateRecordAll.ID = userRecord.ID | dateRecordAll.ID = userRecord.ID | ||||
dateRecordAll.Email = userRecord.Email | dateRecordAll.Email = userRecord.Email | ||||
@@ -484,18 +498,85 @@ func RefreshUserStaticAllTabel(wikiCountMap map[string]int, CommitCodeSizeMap ma | |||||
} | } | ||||
dateRecordAll.CommitModelCount = 0 | dateRecordAll.CommitModelCount = 0 | ||||
_, err = statictisSess.Insert(&dateRecordAll) | |||||
if err != nil { | |||||
log.Info("insert all data failed." + err.Error()) | |||||
dateRecordBatch = append(dateRecordBatch, dateRecordAll) | |||||
if len(dateRecordBatch) >= BATCH_INSERT_SIZE { | |||||
insertTable(dateRecordBatch, tableName, statictisSess) | |||||
insertCount += BATCH_INSERT_SIZE | |||||
if err != nil { | |||||
log.Info("insert all data failed." + err.Error()) | |||||
} | |||||
dateRecordBatch = make([]UserBusinessAnalysisAll, 0) | |||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
} | } | ||||
if len(dateRecordBatch) > 0 { | |||||
insertTable(dateRecordBatch, tableName, statictisSess) | |||||
insertCount += len(dateRecordBatch) | |||||
if err != nil { | |||||
log.Info("insert all data failed." + err.Error()) | |||||
} | |||||
} | |||||
log.Info("refresh data finished.tableName=" + tableName + " total record:" + fmt.Sprint(insertCount)) | |||||
} | |||||
func insertTable(dateRecords []UserBusinessAnalysisAll, tableName string, statictisSess *xorm.Session) { | |||||
insertBatchSql := "INSERT INTO public." + tableName + | |||||
"(id, count_date, code_merge_count, commit_count, issue_count, comment_count, focus_repo_count, star_repo_count, watched_count, gitea_age_month, commit_code_size, commit_dataset_size, " + | |||||
"commit_model_count, solve_issue_count, encyclopedias_count, regist_date, create_repo_count, login_count, open_i_index, email, name, data_date) " + | |||||
"VALUES" | |||||
for i, record := range dateRecords { | |||||
insertBatchSql += "(" + fmt.Sprint(record.ID) + ", " + fmt.Sprint(record.CountDate) + ", " + fmt.Sprint(record.CodeMergeCount) + ", " + fmt.Sprint(record.CommitCount) + | |||||
", " + fmt.Sprint(record.IssueCount) + ", " + fmt.Sprint(record.CommentCount) + ", " + fmt.Sprint(record.FocusRepoCount) + ", " + fmt.Sprint(record.StarRepoCount) + | |||||
", " + fmt.Sprint(record.WatchedCount) + ", " + fmt.Sprint(record.GiteaAgeMonth) + ", " + fmt.Sprint(record.CommitCodeSize) + ", " + fmt.Sprint(record.CommitDatasetSize) + | |||||
", " + fmt.Sprint(record.CommitModelCount) + ", " + fmt.Sprint(record.SolveIssueCount) + ", " + fmt.Sprint(record.EncyclopediasCount) + ", " + fmt.Sprint(record.RegistDate) + | |||||
", " + fmt.Sprint(record.CreateRepoCount) + ", " + fmt.Sprint(record.LoginCount) + ", " + fmt.Sprint(record.OpenIIndex) + ", '" + record.Email + "', '" + record.Name + "', '" + record.DataDate + "')" | |||||
if i < (len(dateRecords) - 1) { | |||||
insertBatchSql += "," | |||||
} | |||||
} | |||||
statictisSess.Exec(insertBatchSql) | |||||
} | |||||
func RefreshUserStaticAllTabel(wikiCountMap map[string]int, CommitCodeSizeMap map[string]*git.UserKPIStats) { | |||||
currentTimeNow := time.Now() | |||||
pageStartTime := time.Date(2021, 11, 5, 0, 0, 0, 0, currentTimeNow.Location()) | |||||
pageEndTime := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location()) | |||||
refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_all", pageStartTime, pageEndTime) | |||||
log.Info("refresh all data finished.") | log.Info("refresh all data finished.") | ||||
pageStartTime = time.Date(currentTimeNow.Year(), 1, 1, 0, 0, 0, 0, currentTimeNow.Location()) | |||||
refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_current_year", pageStartTime, pageEndTime) | |||||
thisMonth := time.Date(currentTimeNow.Year(), currentTimeNow.Month(), 1, 0, 0, 0, 0, currentTimeNow.Location()) | |||||
refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_current_month", thisMonth, pageEndTime) | |||||
offset := int(time.Monday - currentTimeNow.Weekday()) | |||||
if offset > 0 { | |||||
offset = -6 | |||||
} | |||||
pageStartTime = time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, offset) | |||||
refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_current_week", pageStartTime, pageEndTime) | |||||
pageStartTime = time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, -30) | |||||
refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_last30_day", pageStartTime, pageEndTime) | |||||
pageStartTime = time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 0, 0, 0, 0, time.Local).AddDate(0, 0, -1) | |||||
pageEndTime = time.Date(currentTimeNow.Year(), currentTimeNow.Month(), currentTimeNow.Day(), 23, 59, 59, 0, currentTimeNow.Location()).AddDate(0, 0, -1) | |||||
refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_yesterday", pageStartTime, pageEndTime) | |||||
pageStartTime = thisMonth.AddDate(0, -1, 0) | |||||
pageEndTime = time.Date(currentTimeNow.Year(), currentTimeNow.Month(), 1, 23, 59, 59, 0, currentTimeNow.Location()).AddDate(0, 0, -1) | |||||
refreshUserStaticTable(wikiCountMap, CommitCodeSizeMap, "user_business_analysis_last_month", pageStartTime, pageEndTime) | |||||
} | } | ||||
func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, endTime time.Time, isReCount bool) error { | func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, endTime time.Time, isReCount bool) error { | ||||
@@ -550,7 +631,7 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||||
var indexTotal int64 | var indexTotal int64 | ||||
indexTotal = 0 | indexTotal = 0 | ||||
for { | for { | ||||
sess.Select("`user`.*").Table("user").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
sess.Select("`user`.*").Table("user").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
userList := make([]*User, 0) | userList := make([]*User, 0) | ||||
sess.Find(&userList) | sess.Find(&userList) | ||||
@@ -660,7 +741,7 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, | |||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -700,7 +781,7 @@ func querySolveIssue(start_unix int64, end_unix int64) map[int64]int { | |||||
issueAssigneesList := make([]*IssueAssignees, 0) | issueAssigneesList := make([]*IssueAssignees, 0) | ||||
sess.Select("issue_assignees.*").Table("issue_assignees"). | sess.Select("issue_assignees.*").Table("issue_assignees"). | ||||
Join("inner", "issue", "issue.id=issue_assignees.issue_id"). | Join("inner", "issue", "issue.id=issue_assignees.issue_id"). | ||||
Where(cond).OrderBy("issue_assignees.id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
Where(cond).OrderBy("issue_assignees.id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
sess.Find(&issueAssigneesList) | sess.Find(&issueAssigneesList) | ||||
@@ -712,7 +793,7 @@ func querySolveIssue(start_unix int64, end_unix int64) map[int64]int { | |||||
resultMap[issueAssigneesRecord.AssigneeID] += 1 | resultMap[issueAssigneesRecord.AssigneeID] += 1 | ||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -735,7 +816,7 @@ func queryPullRequest(start_unix int64, end_unix int64) map[int64]int { | |||||
indexTotal = 0 | indexTotal = 0 | ||||
for { | for { | ||||
issueList := make([]*Issue, 0) | issueList := make([]*Issue, 0) | ||||
sess.Select("issue.*").Table("issue").Join("inner", "pull_request", "issue.id=pull_request.issue_id").Where(cond).OrderBy("issue.id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
sess.Select("issue.*").Table("issue").Join("inner", "pull_request", "issue.id=pull_request.issue_id").Where(cond).OrderBy("issue.id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
sess.Find(&issueList) | sess.Find(&issueList) | ||||
log.Info("query issue(PR) size=" + fmt.Sprint(len(issueList))) | log.Info("query issue(PR) size=" + fmt.Sprint(len(issueList))) | ||||
for _, issueRecord := range issueList { | for _, issueRecord := range issueList { | ||||
@@ -745,7 +826,7 @@ func queryPullRequest(start_unix int64, end_unix int64) map[int64]int { | |||||
resultMap[issueRecord.PosterID] += 1 | resultMap[issueRecord.PosterID] += 1 | ||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -768,7 +849,7 @@ func queryCommitAction(start_unix int64, end_unix int64, actionType int64) map[i | |||||
var indexTotal int64 | var indexTotal int64 | ||||
indexTotal = 0 | indexTotal = 0 | ||||
for { | for { | ||||
sess.Select("id,user_id,op_type,act_user_id").Table("action").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
sess.Select("id,user_id,op_type,act_user_id").Table("action").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
actionList := make([]*Action, 0) | actionList := make([]*Action, 0) | ||||
sess.Find(&actionList) | sess.Find(&actionList) | ||||
@@ -781,7 +862,7 @@ func queryCommitAction(start_unix int64, end_unix int64, actionType int64) map[i | |||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -805,7 +886,7 @@ func queryCreateIssue(start_unix int64, end_unix int64) map[int64]int { | |||||
var indexTotal int64 | var indexTotal int64 | ||||
indexTotal = 0 | indexTotal = 0 | ||||
for { | for { | ||||
sess.Select("id,poster_id").Table("issue").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
sess.Select("id,poster_id").Table("issue").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
issueList := make([]*Issue, 0) | issueList := make([]*Issue, 0) | ||||
sess.Find(&issueList) | sess.Find(&issueList) | ||||
log.Info("query issue size=" + fmt.Sprint(len(issueList))) | log.Info("query issue size=" + fmt.Sprint(len(issueList))) | ||||
@@ -816,7 +897,7 @@ func queryCreateIssue(start_unix int64, end_unix int64) map[int64]int { | |||||
resultMap[issueRecord.PosterID] += 1 | resultMap[issueRecord.PosterID] += 1 | ||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -839,7 +920,7 @@ func queryComment(start_unix int64, end_unix int64) map[int64]int { | |||||
var indexTotal int64 | var indexTotal int64 | ||||
indexTotal = 0 | indexTotal = 0 | ||||
for { | for { | ||||
sess.Select("id,type,poster_id").Table("comment").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
sess.Select("id,type,poster_id").Table("comment").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
commentList := make([]*Comment, 0) | commentList := make([]*Comment, 0) | ||||
sess.Find(&commentList) | sess.Find(&commentList) | ||||
log.Info("query Comment size=" + fmt.Sprint(len(commentList))) | log.Info("query Comment size=" + fmt.Sprint(len(commentList))) | ||||
@@ -850,7 +931,7 @@ func queryComment(start_unix int64, end_unix int64) map[int64]int { | |||||
resultMap[commentRecord.PosterID] += 1 | resultMap[commentRecord.PosterID] += 1 | ||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -875,7 +956,7 @@ func queryWatch(start_unix int64, end_unix int64) map[int64]int { | |||||
indexTotal = 0 | indexTotal = 0 | ||||
for { | for { | ||||
watchList := make([]*Watch, 0) | watchList := make([]*Watch, 0) | ||||
sess.Select("id,user_id,repo_id").Table("watch").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
sess.Select("id,user_id,repo_id").Table("watch").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
sess.Find(&watchList) | sess.Find(&watchList) | ||||
log.Info("query Watch size=" + fmt.Sprint(len(watchList))) | log.Info("query Watch size=" + fmt.Sprint(len(watchList))) | ||||
@@ -887,7 +968,7 @@ func queryWatch(start_unix int64, end_unix int64) map[int64]int { | |||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -913,7 +994,7 @@ func queryStar(start_unix int64, end_unix int64) map[int64]int { | |||||
var indexTotal int64 | var indexTotal int64 | ||||
indexTotal = 0 | indexTotal = 0 | ||||
for { | for { | ||||
sess.Select("id,uid,repo_id").Table("star").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
sess.Select("id,uid,repo_id").Table("star").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
starList := make([]*Star, 0) | starList := make([]*Star, 0) | ||||
sess.Find(&starList) | sess.Find(&starList) | ||||
@@ -926,7 +1007,7 @@ func queryStar(start_unix int64, end_unix int64) map[int64]int { | |||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -949,7 +1030,7 @@ func queryFollow(start_unix int64, end_unix int64) map[int64]int { | |||||
var indexTotal int64 | var indexTotal int64 | ||||
indexTotal = 0 | indexTotal = 0 | ||||
for { | for { | ||||
sess.Select("id,user_id,follow_id").Table("follow").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
sess.Select("id,user_id,follow_id").Table("follow").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
followList := make([]*Follow, 0) | followList := make([]*Follow, 0) | ||||
sess.Find(&followList) | sess.Find(&followList) | ||||
@@ -962,7 +1043,7 @@ func queryFollow(start_unix int64, end_unix int64) map[int64]int { | |||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -985,7 +1066,7 @@ func queryDatasetSize(start_unix int64, end_unix int64) map[int64]int { | |||||
var indexTotal int64 | var indexTotal int64 | ||||
indexTotal = 0 | indexTotal = 0 | ||||
for { | for { | ||||
sess.Select("id,uploader_id,size").Table("attachment").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
sess.Select("id,uploader_id,size").Table("attachment").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
attachmentList := make([]*Attachment, 0) | attachmentList := make([]*Attachment, 0) | ||||
sess.Find(&attachmentList) | sess.Find(&attachmentList) | ||||
@@ -998,7 +1079,7 @@ func queryDatasetSize(start_unix int64, end_unix int64) map[int64]int { | |||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -1021,7 +1102,7 @@ func queryUserCreateRepo(start_unix int64, end_unix int64) map[int64]int { | |||||
var indexTotal int64 | var indexTotal int64 | ||||
indexTotal = 0 | indexTotal = 0 | ||||
for { | for { | ||||
sess.Select("id,owner_id,name").Table("repository").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
sess.Select("id,owner_id,name").Table("repository").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
repoList := make([]*Repository, 0) | repoList := make([]*Repository, 0) | ||||
sess.Find(&repoList) | sess.Find(&repoList) | ||||
log.Info("query Repository size=" + fmt.Sprint(len(repoList))) | log.Info("query Repository size=" + fmt.Sprint(len(repoList))) | ||||
@@ -1032,7 +1113,7 @@ func queryUserCreateRepo(start_unix int64, end_unix int64) map[int64]int { | |||||
resultMap[repoRecord.OwnerID] += 1 | resultMap[repoRecord.OwnerID] += 1 | ||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -1111,7 +1192,7 @@ func queryLoginCount(start_unix int64, end_unix int64) map[int64]int { | |||||
var indexTotal int64 | var indexTotal int64 | ||||
indexTotal = 0 | indexTotal = 0 | ||||
for { | for { | ||||
statictisSess.Select("id,u_id").Table("user_login_log").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) | |||||
statictisSess.Select("id,u_id").Table("user_login_log").Where(cond).OrderBy("id asc").Limit(PAGE_SIZE, int(indexTotal)) | |||||
userLoginLogList := make([]*UserLoginLog, 0) | userLoginLogList := make([]*UserLoginLog, 0) | ||||
statictisSess.Find(&userLoginLogList) | statictisSess.Find(&userLoginLogList) | ||||
log.Info("query user login size=" + fmt.Sprint(len(userLoginLogList))) | log.Info("query user login size=" + fmt.Sprint(len(userLoginLogList))) | ||||
@@ -1122,7 +1203,7 @@ func queryLoginCount(start_unix int64, end_unix int64) map[int64]int { | |||||
resultMap[loginRecord.UId] += 1 | resultMap[loginRecord.UId] += 1 | ||||
} | } | ||||
} | } | ||||
indexTotal += Page_SIZE | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | if indexTotal >= count { | ||||
break | break | ||||
} | } | ||||
@@ -0,0 +1,267 @@ | |||||
package models | |||||
import "code.gitea.io/gitea/modules/timeutil" | |||||
type UserBusinessAnalysisCurrentYear struct { | |||||
ID int64 `xorm:"pk"` | |||||
CountDate int64 `xorm:"pk"` | |||||
//action :ActionMergePullRequest // 11 | |||||
CodeMergeCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//action :ActionCommitRepo | |||||
CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue // 10 | |||||
IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//comment table current date | |||||
CommentCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//watch table current date | |||||
FocusRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//star table current date | |||||
StarRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//follow table | |||||
WatchedCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
// user table | |||||
GiteaAgeMonth int `xorm:"NOT NULL DEFAULT 0"` | |||||
// | |||||
CommitCodeSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//attachement table | |||||
CommitDatasetSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//0 | |||||
CommitModelCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue, issueassignees | |||||
SolveIssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//baike | |||||
EncyclopediasCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||||
//repo | |||||
CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//login count, from elk | |||||
LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//openi index | |||||
OpenIIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
Email string `xorm:"NOT NULL"` | |||||
//user | |||||
Name string `xorm:"NOT NULL"` | |||||
DataDate string `xorm:"NULL"` | |||||
} | |||||
type UserBusinessAnalysisLast30Day struct { | |||||
ID int64 `xorm:"pk"` | |||||
CountDate int64 `xorm:"pk"` | |||||
//action :ActionMergePullRequest // 11 | |||||
CodeMergeCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//action :ActionCommitRepo | |||||
CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue // 10 | |||||
IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//comment table current date | |||||
CommentCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//watch table current date | |||||
FocusRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//star table current date | |||||
StarRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//follow table | |||||
WatchedCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
// user table | |||||
GiteaAgeMonth int `xorm:"NOT NULL DEFAULT 0"` | |||||
// | |||||
CommitCodeSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//attachement table | |||||
CommitDatasetSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//0 | |||||
CommitModelCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue, issueassignees | |||||
SolveIssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//baike | |||||
EncyclopediasCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||||
//repo | |||||
CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//login count, from elk | |||||
LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//openi index | |||||
OpenIIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
Email string `xorm:"NOT NULL"` | |||||
//user | |||||
Name string `xorm:"NOT NULL"` | |||||
DataDate string `xorm:"NULL"` | |||||
} | |||||
type UserBusinessAnalysisLastMonth struct { | |||||
ID int64 `xorm:"pk"` | |||||
CountDate int64 `xorm:"pk"` | |||||
//action :ActionMergePullRequest // 11 | |||||
CodeMergeCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//action :ActionCommitRepo | |||||
CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue // 10 | |||||
IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//comment table current date | |||||
CommentCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//watch table current date | |||||
FocusRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//star table current date | |||||
StarRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//follow table | |||||
WatchedCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
// user table | |||||
GiteaAgeMonth int `xorm:"NOT NULL DEFAULT 0"` | |||||
// | |||||
CommitCodeSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//attachement table | |||||
CommitDatasetSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//0 | |||||
CommitModelCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue, issueassignees | |||||
SolveIssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//baike | |||||
EncyclopediasCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||||
//repo | |||||
CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//login count, from elk | |||||
LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//openi index | |||||
OpenIIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
Email string `xorm:"NOT NULL"` | |||||
//user | |||||
Name string `xorm:"NOT NULL"` | |||||
DataDate string `xorm:"NULL"` | |||||
} | |||||
type UserBusinessAnalysisCurrentMonth struct { | |||||
ID int64 `xorm:"pk"` | |||||
CountDate int64 `xorm:"pk"` | |||||
//action :ActionMergePullRequest // 11 | |||||
CodeMergeCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//action :ActionCommitRepo | |||||
CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue // 10 | |||||
IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//comment table current date | |||||
CommentCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//watch table current date | |||||
FocusRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//star table current date | |||||
StarRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//follow table | |||||
WatchedCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
// user table | |||||
GiteaAgeMonth int `xorm:"NOT NULL DEFAULT 0"` | |||||
// | |||||
CommitCodeSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//attachement table | |||||
CommitDatasetSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//0 | |||||
CommitModelCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue, issueassignees | |||||
SolveIssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//baike | |||||
EncyclopediasCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||||
//repo | |||||
CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//login count, from elk | |||||
LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//openi index | |||||
OpenIIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
Email string `xorm:"NOT NULL"` | |||||
//user | |||||
Name string `xorm:"NOT NULL"` | |||||
DataDate string `xorm:"NULL"` | |||||
} | |||||
type UserBusinessAnalysisCurrentWeek struct { | |||||
ID int64 `xorm:"pk"` | |||||
CountDate int64 `xorm:"pk"` | |||||
//action :ActionMergePullRequest // 11 | |||||
CodeMergeCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//action :ActionCommitRepo | |||||
CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue // 10 | |||||
IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//comment table current date | |||||
CommentCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//watch table current date | |||||
FocusRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//star table current date | |||||
StarRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//follow table | |||||
WatchedCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
// user table | |||||
GiteaAgeMonth int `xorm:"NOT NULL DEFAULT 0"` | |||||
// | |||||
CommitCodeSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//attachement table | |||||
CommitDatasetSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//0 | |||||
CommitModelCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue, issueassignees | |||||
SolveIssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//baike | |||||
EncyclopediasCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||||
//repo | |||||
CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//login count, from elk | |||||
LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//openi index | |||||
OpenIIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
Email string `xorm:"NOT NULL"` | |||||
//user | |||||
Name string `xorm:"NOT NULL"` | |||||
DataDate string `xorm:"NULL"` | |||||
} | |||||
type UserBusinessAnalysisYesterday struct { | |||||
ID int64 `xorm:"pk"` | |||||
CountDate int64 `xorm:"pk"` | |||||
//action :ActionMergePullRequest // 11 | |||||
CodeMergeCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//action :ActionCommitRepo | |||||
CommitCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue // 10 | |||||
IssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//comment table current date | |||||
CommentCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//watch table current date | |||||
FocusRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//star table current date | |||||
StarRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//follow table | |||||
WatchedCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
// user table | |||||
GiteaAgeMonth int `xorm:"NOT NULL DEFAULT 0"` | |||||
// | |||||
CommitCodeSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//attachement table | |||||
CommitDatasetSize int `xorm:"NOT NULL DEFAULT 0"` | |||||
//0 | |||||
CommitModelCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//issue, issueassignees | |||||
SolveIssueCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//baike | |||||
EncyclopediasCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
RegistDate timeutil.TimeStamp `xorm:"NOT NULL"` | |||||
//repo | |||||
CreateRepoCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//login count, from elk | |||||
LoginCount int `xorm:"NOT NULL DEFAULT 0"` | |||||
//openi index | |||||
OpenIIndex float64 `xorm:"NOT NULL DEFAULT 0"` | |||||
//user | |||||
Email string `xorm:"NOT NULL"` | |||||
//user | |||||
Name string `xorm:"NOT NULL"` | |||||
DataDate string `xorm:"NULL"` | |||||
} |
@@ -70,3 +70,7 @@ type CreateTeamForm struct { | |||||
func (f *CreateTeamForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | func (f *CreateTeamForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { | ||||
return validate(errs, ctx.Data, f, ctx.Locale) | return validate(errs, ctx.Data, f, ctx.Locale) | ||||
} | } | ||||
type SubmitReposOfTagForm struct { | |||||
RepoList []int64 | |||||
} |
@@ -1,6 +1,8 @@ | |||||
package cloudbrain | package cloudbrain | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/modules/storage" | |||||
"encoding/json" | |||||
"errors" | "errors" | ||||
"strconv" | "strconv" | ||||
@@ -80,7 +82,7 @@ func AdminOrOwnerOrJobCreaterRight(ctx *context.Context) { | |||||
var jobID = ctx.Params(":jobid") | var jobID = ctx.Params(":jobid") | ||||
job, err := models.GetCloudbrainByJobID(jobID) | job, err := models.GetCloudbrainByJobID(jobID) | ||||
ctx.Cloudbrain = job | |||||
if !isAdminOrOwnerOrJobCreater(ctx, job, err) { | if !isAdminOrOwnerOrJobCreater(ctx, job, err) { | ||||
ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | ||||
@@ -92,6 +94,7 @@ func AdminOrJobCreaterRight(ctx *context.Context) { | |||||
var jobID = ctx.Params(":jobid") | var jobID = ctx.Params(":jobid") | ||||
job, err := models.GetCloudbrainByJobID(jobID) | job, err := models.GetCloudbrainByJobID(jobID) | ||||
ctx.Cloudbrain = job | |||||
if !isAdminOrJobCreater(ctx, job, err) { | if !isAdminOrJobCreater(ctx, job, err) { | ||||
ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | ctx.NotFound(ctx.Req.URL.RequestURI(), nil) | ||||
@@ -107,6 +110,9 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, | |||||
uuid | uuid | ||||
var resourceSpec *models.ResourceSpec | var resourceSpec *models.ResourceSpec | ||||
if ResourceSpecs == nil { | |||||
json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) | |||||
} | |||||
for _, spec := range ResourceSpecs.ResourceSpec { | for _, spec := range ResourceSpecs.ResourceSpec { | ||||
if resourceSpecId == spec.Id { | if resourceSpecId == spec.Id { | ||||
resourceSpec = spec | resourceSpec = spec | ||||
@@ -185,25 +191,29 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, | |||||
}, | }, | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
log.Error("CreateJob failed:", err.Error()) | |||||
log.Error("CreateJob failed:", err.Error(), ctx.Data["MsgID"]) | |||||
return err | return err | ||||
} | } | ||||
if jobResult.Code != Success { | if jobResult.Code != Success { | ||||
log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg) | |||||
log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg, ctx.Data["MsgID"]) | |||||
return errors.New(jobResult.Msg) | return errors.New(jobResult.Msg) | ||||
} | } | ||||
var jobID = jobResult.Payload["jobId"].(string) | var jobID = jobResult.Payload["jobId"].(string) | ||||
err = models.CreateCloudbrain(&models.Cloudbrain{ | err = models.CreateCloudbrain(&models.Cloudbrain{ | ||||
Status: string(models.JobWaiting), | |||||
UserID: ctx.User.ID, | |||||
RepoID: ctx.Repo.Repository.ID, | |||||
JobID: jobID, | |||||
JobName: jobName, | |||||
SubTaskName: SubTaskName, | |||||
JobType: jobType, | |||||
Type: models.TypeCloudBrainOne, | |||||
Uuid: uuid, | |||||
Status: string(models.JobWaiting), | |||||
UserID: ctx.User.ID, | |||||
RepoID: ctx.Repo.Repository.ID, | |||||
JobID: jobID, | |||||
JobName: jobName, | |||||
SubTaskName: SubTaskName, | |||||
JobType: jobType, | |||||
Type: models.TypeCloudBrainOne, | |||||
Uuid: uuid, | |||||
Image: image, | |||||
GpuQueue: gpuQueue, | |||||
ResourceSpecId: resourceSpecId, | |||||
ComputeResource: models.GPUResource, | |||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
@@ -212,3 +222,129 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, | |||||
return nil | return nil | ||||
} | } | ||||
func RestartTask(ctx *context.Context, task *models.Cloudbrain, newJobID *string) error { | |||||
dataActualPath := setting.Attachment.Minio.RealPath + | |||||
setting.Attachment.Minio.Bucket + "/" + | |||||
setting.Attachment.Minio.BasePath + | |||||
models.AttachmentRelativePath(task.Uuid) + | |||||
task.Uuid | |||||
jobName := task.JobName | |||||
var resourceSpec *models.ResourceSpec | |||||
if ResourceSpecs == nil { | |||||
json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) | |||||
} | |||||
for _, spec := range ResourceSpecs.ResourceSpec { | |||||
if task.ResourceSpecId == spec.Id { | |||||
resourceSpec = spec | |||||
} | |||||
} | |||||
if resourceSpec == nil { | |||||
log.Error("no such resourceSpecId(%d)", task.ResourceSpecId, ctx.Data["MsgID"]) | |||||
return errors.New("no such resourceSpec") | |||||
} | |||||
jobResult, err := CreateJob(jobName, models.CreateJobParams{ | |||||
JobName: jobName, | |||||
RetryCount: 1, | |||||
GpuType: task.GpuQueue, | |||||
Image: task.Image, | |||||
TaskRoles: []models.TaskRole{ | |||||
{ | |||||
Name: SubTaskName, | |||||
TaskNumber: 1, | |||||
MinSucceededTaskCount: 1, | |||||
MinFailedTaskCount: 1, | |||||
CPUNumber: resourceSpec.CpuNum, | |||||
GPUNumber: resourceSpec.GpuNum, | |||||
MemoryMB: resourceSpec.MemMiB, | |||||
ShmMB: resourceSpec.ShareMemMiB, | |||||
Command: Command, | |||||
NeedIBDevice: false, | |||||
IsMainRole: false, | |||||
UseNNI: false, | |||||
}, | |||||
}, | |||||
Volumes: []models.Volume{ | |||||
{ | |||||
HostPath: models.StHostPath{ | |||||
Path: storage.GetMinioPath(jobName, CodeMountPath + "/"), | |||||
MountPath: CodeMountPath, | |||||
ReadOnly: false, | |||||
}, | |||||
}, | |||||
{ | |||||
HostPath: models.StHostPath{ | |||||
Path: dataActualPath, | |||||
MountPath: DataSetMountPath, | |||||
ReadOnly: true, | |||||
}, | |||||
}, | |||||
{ | |||||
HostPath: models.StHostPath{ | |||||
Path: storage.GetMinioPath(jobName, ModelMountPath + "/"), | |||||
MountPath: ModelMountPath, | |||||
ReadOnly: false, | |||||
}, | |||||
}, | |||||
{ | |||||
HostPath: models.StHostPath{ | |||||
Path: storage.GetMinioPath(jobName, BenchMarkMountPath + "/"), | |||||
MountPath: BenchMarkMountPath, | |||||
ReadOnly: true, | |||||
}, | |||||
}, | |||||
{ | |||||
HostPath: models.StHostPath{ | |||||
Path: storage.GetMinioPath(jobName, Snn4imagenetMountPath + "/"), | |||||
MountPath: Snn4imagenetMountPath, | |||||
ReadOnly: true, | |||||
}, | |||||
}, | |||||
{ | |||||
HostPath: models.StHostPath{ | |||||
Path: storage.GetMinioPath(jobName, BrainScoreMountPath + "/"), | |||||
MountPath: BrainScoreMountPath, | |||||
ReadOnly: true, | |||||
}, | |||||
}, | |||||
}, | |||||
}) | |||||
if err != nil { | |||||
log.Error("CreateJob failed:%v", err.Error(), ctx.Data["MsgID"]) | |||||
return err | |||||
} | |||||
if jobResult.Code != Success { | |||||
log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg, ctx.Data["MsgID"]) | |||||
return errors.New(jobResult.Msg) | |||||
} | |||||
var jobID = jobResult.Payload["jobId"].(string) | |||||
newTask := &models.Cloudbrain{ | |||||
Status: string(models.JobWaiting), | |||||
UserID: task.UserID, | |||||
RepoID: task.RepoID, | |||||
JobID: jobID, | |||||
JobName: task.JobName, | |||||
SubTaskName: task.SubTaskName, | |||||
JobType: task.JobType, | |||||
Type: task.Type, | |||||
Uuid: task.Uuid, | |||||
Image: task.Image, | |||||
GpuQueue: task.GpuQueue, | |||||
ResourceSpecId: task.ResourceSpecId, | |||||
ComputeResource: task.ComputeResource, | |||||
} | |||||
err = models.RestartCloudbrain(task, newTask) | |||||
if err != nil { | |||||
log.Error("RestartCloudbrain(%s) failed:%v", jobName, err.Error(), ctx.Data["MsgID"]) | |||||
return err | |||||
} | |||||
*newJobID = jobID | |||||
return nil | |||||
} |
@@ -6,6 +6,7 @@ | |||||
package context | package context | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/routers/notice" | |||||
"html" | "html" | ||||
"html/template" | "html/template" | ||||
"io" | "io" | ||||
@@ -46,6 +47,7 @@ type Context struct { | |||||
Repo *Repository | Repo *Repository | ||||
Org *Organization | Org *Organization | ||||
Cloudbrain *models.Cloudbrain | |||||
} | } | ||||
// IsUserSiteAdmin returns true if current user is a site admin | // IsUserSiteAdmin returns true if current user is a site admin | ||||
@@ -345,6 +347,10 @@ 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 | |||||
} | |||||
c.Map(ctx) | c.Map(ctx) | ||||
} | } | ||||
} | } |
@@ -11,6 +11,7 @@ import ( | |||||
"net/url" | "net/url" | ||||
"path" | "path" | ||||
"strings" | "strings" | ||||
"time" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/cache" | "code.gitea.io/gitea/modules/cache" | ||||
@@ -517,6 +518,7 @@ func RepoAssignment() macaron.Handler { | |||||
return | return | ||||
} | } | ||||
startTime := time.Now() | |||||
tags, err := ctx.Repo.GitRepo.GetTags() | tags, err := ctx.Repo.GitRepo.GetTags() | ||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("GetTags", err) | ctx.ServerError("GetTags", err) | ||||
@@ -524,11 +526,17 @@ func RepoAssignment() macaron.Handler { | |||||
} | } | ||||
ctx.Data["Tags"] = tags | ctx.Data["Tags"] = tags | ||||
duration := time.Since(startTime) | |||||
log.Info("GetTags cost: %v seconds", duration.Seconds()) | |||||
brs, _, err := ctx.Repo.GitRepo.GetBranches(0, 0) | brs, _, err := ctx.Repo.GitRepo.GetBranches(0, 0) | ||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("GetBranches", err) | ctx.ServerError("GetBranches", err) | ||||
return | return | ||||
} | } | ||||
duration = time.Since(startTime) | |||||
log.Info("GetBranches cost: %v seconds", duration.Seconds()) | |||||
ctx.Data["Branches"] = brs | ctx.Data["Branches"] = brs | ||||
ctx.Data["BranchesCount"] = len(brs) | ctx.Data["BranchesCount"] = len(brs) | ||||
@@ -48,12 +48,8 @@ const ( | |||||
PerPage = 10 | PerPage = 10 | ||||
IsLatestVersion = "1" | IsLatestVersion = "1" | ||||
NotLatestVersion = "0" | NotLatestVersion = "0" | ||||
// ComputeResource = "NPU" | |||||
NPUResource = "NPU" | |||||
GPUResource = "CPU/GPU" | |||||
AllResource = "all" | |||||
DebugType = -1 | |||||
VersionCount = 1 | |||||
DebugType = -1 | |||||
VersionCount = 1 | |||||
SortByCreateTime = "create_time" | SortByCreateTime = "create_time" | ||||
ConfigTypeCustom = "custom" | ConfigTypeCustom = "custom" | ||||
@@ -215,14 +211,15 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description, flavor strin | |||||
} | } | ||||
err = models.CreateCloudbrain(&models.Cloudbrain{ | err = models.CreateCloudbrain(&models.Cloudbrain{ | ||||
Status: string(models.JobWaiting), | |||||
UserID: ctx.User.ID, | |||||
RepoID: ctx.Repo.Repository.ID, | |||||
JobID: jobResult.ID, | |||||
JobName: jobName, | |||||
JobType: string(models.JobTypeDebug), | |||||
Type: models.TypeCloudBrainTwo, | |||||
Uuid: uuid, | |||||
Status: string(models.JobWaiting), | |||||
UserID: ctx.User.ID, | |||||
RepoID: ctx.Repo.Repository.ID, | |||||
JobID: jobResult.ID, | |||||
JobName: jobName, | |||||
JobType: string(models.JobTypeDebug), | |||||
Type: models.TypeCloudBrainTwo, | |||||
Uuid: uuid, | |||||
ComputeResource: models.NPUResource, | |||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
@@ -277,7 +274,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error | |||||
DatasetName: attach.Name, | DatasetName: attach.Name, | ||||
CommitID: req.CommitID, | CommitID: req.CommitID, | ||||
IsLatestVersion: req.IsLatestVersion, | IsLatestVersion: req.IsLatestVersion, | ||||
ComputeResource: NPUResource, | |||||
ComputeResource: models.NPUResource, | |||||
EngineID: req.EngineID, | EngineID: req.EngineID, | ||||
TrainUrl: req.TrainUrl, | TrainUrl: req.TrainUrl, | ||||
BranchName: req.BranchName, | BranchName: req.BranchName, | ||||
@@ -360,7 +357,7 @@ func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, job | |||||
CommitID: req.CommitID, | CommitID: req.CommitID, | ||||
IsLatestVersion: req.IsLatestVersion, | IsLatestVersion: req.IsLatestVersion, | ||||
PreVersionName: req.PreVersionName, | PreVersionName: req.PreVersionName, | ||||
ComputeResource: NPUResource, | |||||
ComputeResource: models.NPUResource, | |||||
EngineID: req.EngineID, | EngineID: req.EngineID, | ||||
TrainUrl: req.TrainUrl, | TrainUrl: req.TrainUrl, | ||||
BranchName: req.BranchName, | BranchName: req.BranchName, | ||||
@@ -174,7 +174,7 @@ sendjob: | |||||
return &result, nil | return &result, nil | ||||
} | } | ||||
func StopJob(jobID string, param models.NotebookAction) (*models.NotebookActionResult, error) { | |||||
func ManageNotebook(jobID string, param models.NotebookAction) (*models.NotebookActionResult, error) { | |||||
checkSetting() | checkSetting() | ||||
client := getRestyClient() | client := getRestyClient() | ||||
var result models.NotebookActionResult | var result models.NotebookActionResult | ||||
@@ -207,8 +207,8 @@ sendjob: | |||||
} | } | ||||
if len(response.ErrorCode) != 0 { | if len(response.ErrorCode) != 0 { | ||||
log.Error("StopJob failed(%s): %s", response.ErrorCode, response.ErrorMsg) | |||||
return &result, fmt.Errorf("StopJob failed(%s): %s", response.ErrorCode, response.ErrorMsg) | |||||
log.Error("ManageNotebook failed(%s): %s", response.ErrorCode, response.ErrorMsg) | |||||
return &result, fmt.Errorf("ManageNotebook failed(%s): %s", response.ErrorCode, response.ErrorMsg) | |||||
} | } | ||||
return &result, nil | return &result, nil | ||||
@@ -21,7 +21,8 @@ type Fields struct { | |||||
Format string `json:"format"` | Format string `json:"format"` | ||||
} | } | ||||
type MatchPhrase struct { | type MatchPhrase struct { | ||||
Message string `json:"message"` | |||||
Message string `json:"message,omitempty"` | |||||
TagName string `json:"tagName.keyword,omitempty"` | |||||
} | } | ||||
type Should struct { | type Should struct { | ||||
MatchPhrase MatchPhrase `json:"match_phrase"` | MatchPhrase MatchPhrase `json:"match_phrase"` | ||||
@@ -144,7 +145,7 @@ func ProjectViewInit(User string, Project string, Gte string, Lte string) (proje | |||||
inputStruct.Batch[0].Request.Params.Body.Fields = make([]Fields, 1) | inputStruct.Batch[0].Request.Params.Body.Fields = make([]Fields, 1) | ||||
inputStruct.Batch[0].Request.Params.Body.Fields[0].Field = setting.TimeField | inputStruct.Batch[0].Request.Params.Body.Fields[0].Field = setting.TimeField | ||||
inputStruct.Batch[0].Request.Params.Body.Fields[0].Format = setting.ElkTimeFormat | inputStruct.Batch[0].Request.Params.Body.Fields[0].Format = setting.ElkTimeFormat | ||||
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter = make([]Filter, 3) | |||||
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter = make([]Filter, 4) | |||||
//限定查询时间 | //限定查询时间 | ||||
var timeRange Range | var timeRange Range | ||||
timeRange.Timestamptest.Gte = Gte | timeRange.Timestamptest.Gte = Gte | ||||
@@ -159,6 +160,13 @@ func ProjectViewInit(User string, Project string, Gte string, Lte string) (proje | |||||
var projectName FilterMatchPhrase | var projectName FilterMatchPhrase | ||||
projectName.ProjectName = Project | projectName.ProjectName = Project | ||||
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[2].FilterMatchPhrase = &projectName | inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[2].FilterMatchPhrase = &projectName | ||||
//限定页面 | |||||
var bool Bool | |||||
bool.Should = make([]Should, len(setting.PROJECT_LIMIT_PAGES)) | |||||
for i, pageName := range setting.PROJECT_LIMIT_PAGES { | |||||
bool.Should[i].MatchPhrase.TagName = pageName | |||||
} | |||||
inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[3].Bool = &bool | |||||
return inputStruct | return inputStruct | ||||
} | } | ||||
@@ -435,8 +435,14 @@ var ( | |||||
//home page | //home page | ||||
RecommentRepoAddr string | RecommentRepoAddr string | ||||
ESSearchURL string | |||||
ESSearchURL string | |||||
//notice config | |||||
UserNameOfNoticeRepo string | |||||
RepoNameOfNoticeRepo string | |||||
RefNameOfNoticeRepo string | |||||
TreePathOfNoticeRepo string | |||||
CacheTimeOutSecond int | |||||
CacheOn bool | |||||
//labelsystem config | //labelsystem config | ||||
LabelTaskName string | LabelTaskName string | ||||
@@ -510,12 +516,13 @@ var ( | |||||
TrainJobFLAVORINFOS string | TrainJobFLAVORINFOS string | ||||
//elk config | //elk config | ||||
ElkUrl string | |||||
ElkUser string | |||||
ElkPassword string | |||||
Index string | |||||
TimeField string | |||||
ElkTimeFormat string | |||||
ElkUrl string | |||||
ElkUser string | |||||
ElkPassword string | |||||
Index string | |||||
TimeField string | |||||
ElkTimeFormat string | |||||
PROJECT_LIMIT_PAGES []string | |||||
//nginx proxy | //nginx proxy | ||||
PROXYURL string | PROXYURL string | ||||
@@ -1238,6 +1245,14 @@ func NewContext() { | |||||
RecommentRepoAddr = sec.Key("Address").MustString("https://git.openi.org.cn/OpenIOSSG/promote/raw/branch/master/") | RecommentRepoAddr = sec.Key("Address").MustString("https://git.openi.org.cn/OpenIOSSG/promote/raw/branch/master/") | ||||
ESSearchURL = sec.Key("ESSearchURL").MustString("http://192.168.207.94:9200") | ESSearchURL = sec.Key("ESSearchURL").MustString("http://192.168.207.94:9200") | ||||
sec = Cfg.Section("notice") | |||||
UserNameOfNoticeRepo = sec.Key("USER_NAME").MustString("OpenIOSSG") | |||||
RepoNameOfNoticeRepo = sec.Key("REPO_NAME").MustString("promote") | |||||
RefNameOfNoticeRepo = sec.Key("REF_NAME").MustString("master") | |||||
TreePathOfNoticeRepo = sec.Key("TREE_PATH").MustString("notice.json") | |||||
CacheTimeOutSecond = sec.Key("CACHE_TIME_OUT_SECOND").MustInt(60) | |||||
CacheOn = sec.Key("CACHE_ON").MustBool(true) | |||||
sec = Cfg.Section("cloudbrain") | sec = Cfg.Section("cloudbrain") | ||||
CBAuthUser = sec.Key("USER").MustString("") | CBAuthUser = sec.Key("USER").MustString("") | ||||
CBAuthPassword = sec.Key("PWD").MustString("") | CBAuthPassword = sec.Key("PWD").MustString("") | ||||
@@ -1311,6 +1326,7 @@ func NewContext() { | |||||
Index = sec.Key("INDEX").MustString("") | Index = sec.Key("INDEX").MustString("") | ||||
TimeField = sec.Key("TIMEFIELD").MustString(" @timestamptest") | TimeField = sec.Key("TIMEFIELD").MustString(" @timestamptest") | ||||
ElkTimeFormat = sec.Key("ELKTIMEFORMAT").MustString("date_time") | ElkTimeFormat = sec.Key("ELKTIMEFORMAT").MustString("date_time") | ||||
PROJECT_LIMIT_PAGES = strings.Split(sec.Key("project_limit_pages").MustString(""), ",") | |||||
SetRadarMapConfig() | SetRadarMapConfig() | ||||
@@ -80,3 +80,7 @@ func (l *LocalStorage) HasObject(path string) (bool, error) { | |||||
func (l *LocalStorage) UploadObject(fileName, filePath string) error { | func (l *LocalStorage) UploadObject(fileName, filePath string) error { | ||||
return nil | return nil | ||||
} | } | ||||
func (l *LocalStorage) DeleteDir(dir string) error { | |||||
return nil | |||||
} |
@@ -11,6 +11,9 @@ import ( | |||||
"strings" | "strings" | ||||
"time" | "time" | ||||
"code.gitea.io/gitea/modules/log" | |||||
"code.gitea.io/gitea/modules/setting" | |||||
"github.com/minio/minio-go" | "github.com/minio/minio-go" | ||||
) | ) | ||||
@@ -76,6 +79,27 @@ func (m *MinioStorage) Delete(path string) error { | |||||
return m.client.RemoveObject(m.bucket, m.buildMinioPath(path)) | return m.client.RemoveObject(m.bucket, m.buildMinioPath(path)) | ||||
} | } | ||||
// Delete delete a file | |||||
func (m *MinioStorage) DeleteDir(dir string) error { | |||||
objectsCh := make(chan string) | |||||
// Send object names that are needed to be removed to objectsCh | |||||
go func() { | |||||
defer close(objectsCh) | |||||
// List all objects from a bucket-name with a matching prefix. | |||||
for object := range m.client.ListObjects(m.bucket, dir, true, nil) { | |||||
if object.Err != nil { | |||||
log.Error("ListObjects failed:%v", object.Err) | |||||
} | |||||
objectsCh <- object.Key | |||||
} | |||||
}() | |||||
m.client.RemoveObjects(m.bucket, objectsCh) | |||||
return nil | |||||
} | |||||
//Get Presigned URL for get object | //Get Presigned URL for get object | ||||
func (m *MinioStorage) PresignedGetURL(path string, fileName string) (string, error) { | func (m *MinioStorage) PresignedGetURL(path string, fileName string) (string, error) { | ||||
// Set request parameters for content-disposition. | // Set request parameters for content-disposition. | ||||
@@ -128,3 +152,7 @@ func (m *MinioStorage) UploadObject(fileName, filePath string) error { | |||||
_, err := m.client.FPutObject(m.bucket, fileName, filePath, minio.PutObjectOptions{}) | _, err := m.client.FPutObject(m.bucket, fileName, filePath, minio.PutObjectOptions{}) | ||||
return err | return err | ||||
} | } | ||||
func GetMinioPath(jobName, suffixPath string) string { | |||||
return setting.Attachment.Minio.RealPath + setting.Attachment.Minio.Bucket + "/" + setting.CBCodePathPrefix + jobName + suffixPath | |||||
} |
@@ -23,6 +23,7 @@ type ObjectStorage interface { | |||||
Save(path string, r io.Reader) (int64, error) | Save(path string, r io.Reader) (int64, error) | ||||
Open(path string) (io.ReadCloser, error) | Open(path string) (io.ReadCloser, error) | ||||
Delete(path string) error | Delete(path string) error | ||||
DeleteDir(dir string) error | |||||
PresignedGetURL(path string, fileName string) (string, error) | PresignedGetURL(path string, fileName string) (string, error) | ||||
PresignedPutURL(path string) (string, error) | PresignedPutURL(path string) (string, error) | ||||
HasObject(path string) (bool, error) | HasObject(path string) (bool, error) | ||||
@@ -6,6 +6,7 @@ package util | |||||
import ( | import ( | ||||
"bytes" | "bytes" | ||||
"strconv" | |||||
"strings" | "strings" | ||||
) | ) | ||||
@@ -100,3 +101,12 @@ func NormalizeEOL(input []byte) []byte { | |||||
} | } | ||||
return tmp[:pos] | return tmp[:pos] | ||||
} | } | ||||
func AddZero(t int64) (m string) { | |||||
if t < 10 { | |||||
m = "0" + strconv.FormatInt(t, 10) | |||||
return m | |||||
} else { | |||||
return strconv.FormatInt(t, 10) | |||||
} | |||||
} |
@@ -220,8 +220,40 @@ show_only_public = Showing only public | |||||
issues.in_your_repos = In your repositories | issues.in_your_repos = In your repositories | ||||
contributors = Contributors | contributors = Contributors | ||||
page_title=Explore Better AI | |||||
page_small_title=OpenI AI development cooperation platform | |||||
page_description=The one-stop collaborative development environment for AI field provides AI development pipeline integrating code development, data management, model debugging, reasoning and evaluation | |||||
page_use=Use Now | |||||
page_only_dynamic=Show only open source project dynamics | |||||
page_recommend_org=Recommended organization | |||||
page_recommend_org_desc=These excellent organizations are using Qizhi AI to develop collaboration platforms; Your organization also wants to show here, | |||||
page_recommend_org_commit=Click here to submit | |||||
page_recommend_org_more=More organizations | |||||
page_recommend_repo=Recommended projects | |||||
page_recommend_repo_desc=Excellent AI project recommendation; Your project also wants to show here, | |||||
page_recommend_repo_commit=Click here to submit | |||||
page_recommend_repo_go=. Click here | |||||
page_recommend_repo_more=Project Square | |||||
page_dev_env=Collaborative development environment | |||||
page_dev_env_desc=The biggest difference between Qizhi AI collaborative development platform and traditional git platform is that it provides a collaborative development environment for AI development | |||||
page_dev_env_desc_title=Unified management of development elements | |||||
page_dev_env_desc_desc=The platform provides four elements of AI development: unified management of model code, data set, model and execution environment | |||||
page_dev_env_desc1_title=Data collaboration and sharing | |||||
page_dev_env_desc1_desc=By uploading data sets in the project, many project members cooperate to complete data preprocessing; You can also establish a better model with community developers by setting the data as a public dataset | |||||
page_dev_env_desc2_title=Model management and sharing | |||||
page_dev_env_desc2_desc=Associate the model with the code version, adjust the model in different ways based on the code history version, and save the results; The trained model can be open and shared, so that more people can use the model to test and give feedback | |||||
page_dev_env_desc3_title=One configuration, multiple use | |||||
page_dev_env_desc3_desc=Provide execution environment sharing, one-time configuration and multiple use, reduce the threshold of model development, and avoid spending repeated time configuring complex environments | |||||
page_dev_yunlao=PengCheng Cloudbrain open source collaboration | |||||
page_dev_yunlao_desc1=The platform has been connected with Pengcheng Cloudbrain and can use the rich computing resources of Pengcheng Cloudbrain to complete AI development tasks | |||||
page_dev_yunlao_desc2=Pengcheng Cloudbrain's existing AI computing power is 100p FLOPS@FP16 (billions of half precision floating-point calculations per second), the main hardware infrastructure is composed of GPU server equipped with NVIDIA Tesla V100 and Atlas 900 AI cluster equipped with Kunpeng and shengteng processors | |||||
page_dev_yunlao_desc3=Developers can freely choose the corresponding computing resources according to the use requirements, and can test the adaptability, performance and stability of the model in different hardware environments | |||||
page_dev_yunlao_desc4=If your model needs more computing resources, you can also apply separately | |||||
page_dev_yunlao_apply=Separate apply | |||||
[explore] | [explore] | ||||
repos = Repositories | repos = Repositories | ||||
select_repos = Select the project | |||||
users = Users | users = Users | ||||
organizations = Organizations | organizations = Organizations | ||||
images = CloudImages | images = CloudImages | ||||
@@ -234,6 +266,8 @@ org_no_results = No matching organizations found. | |||||
code_no_results = No source code matching your search term found. | code_no_results = No source code matching your search term found. | ||||
code_search_results = Search results for '%s' | code_search_results = Search results for '%s' | ||||
code_last_indexed_at = Last indexed %s | code_last_indexed_at = Last indexed %s | ||||
save=save | |||||
cancel=cancel | |||||
[auth] | [auth] | ||||
create_new_account = Register Account | create_new_account = Register Account | ||||
@@ -421,7 +455,13 @@ static.openiindex=OpenI Index | |||||
static.registdate=Regist Date | static.registdate=Regist Date | ||||
static.countdate=Count Date | static.countdate=Count Date | ||||
static.all=All | static.all=All | ||||
static.public.user_business_analysis_current_month=Current_Month | |||||
static.public.user_business_analysis_current_week=Current_Week | |||||
static.public.user_business_analysis_current_year=Current_Year | |||||
static.public.user_business_analysis_last30_day=Last_30_day | |||||
static.public.user_business_analysis_last_month=Last_Month | |||||
static.public.user_business_analysis_yesterday=Yesterday | |||||
static.public.user_business_analysis_all=All | |||||
[settings] | [settings] | ||||
profile = Profile | profile = Profile | ||||
account = Account | account = Account | ||||
@@ -841,6 +881,7 @@ modelarts.current_version=Current version | |||||
modelarts.parent_version=Parent Version | modelarts.parent_version=Parent Version | ||||
modelarts.run_version=Run Version | modelarts.run_version=Run Version | ||||
modelarts.train_job.compute_node=Compute Node | modelarts.train_job.compute_node=Compute Node | ||||
modelarts.create_model = Create Model | |||||
modelarts.train_job.basic_info=Basic Info | modelarts.train_job.basic_info=Basic Info | ||||
@@ -900,6 +941,8 @@ model.manage.F1 = F1 | |||||
model.manage.Precision = Precision | model.manage.Precision = Precision | ||||
model.manage.Recall = Recall | model.manage.Recall = Recall | ||||
model.manage.sava_model = Sava Model | model.manage.sava_model = Sava Model | ||||
model.manage.model_manage = ModelManage | |||||
model.manage.model_accuracy = Model Accuracy | |||||
template.items = Template Items | template.items = Template Items | ||||
template.git_content = Git Content (Default Branch) | template.git_content = Git Content (Default Branch) | ||||
@@ -2654,3 +2697,5 @@ foot.member_news = Member news | |||||
foot.industry_advisory = Industry Advisory | foot.industry_advisory = Industry Advisory | ||||
foot.help = help | foot.help = help | ||||
foot.copyright= Copyright: New Generation Artificial Intelligence Open Source Open Platform (OpenI) | foot.copyright= Copyright: New Generation Artificial Intelligence Open Source Open Platform (OpenI) | ||||
Platform_Tutorial=Platform Tutorial | |||||
foot.advice_feedback=advice feedback |
@@ -222,8 +222,40 @@ issues.in_your_repos=属于该用户项目的 | |||||
contributors=贡献者 | contributors=贡献者 | ||||
page_title=探索更好的AI | |||||
page_small_title=启智AI开发协作平台 | |||||
page_description=面向AI领域的一站式协同开发环境,提供集代码开发、数据管理、模型调试、推理和评测为一体的AI开发流水线 | |||||
page_use=立即使用 | |||||
page_only_dynamic=仅展示开源项目动态 | |||||
page_recommend_org=推荐组织 | |||||
page_recommend_org_desc=这些优秀的组织正在使用启智AI开发协作平台;你的组织也想展示到这里, | |||||
page_recommend_org_commit=点此提交 | |||||
page_recommend_org_more=更多组织 | |||||
page_recommend_repo=推荐项目 | |||||
page_recommend_repo_desc=优秀的AI项目推荐;你的项目也想展示到这里, | |||||
page_recommend_repo_commit=点此提交 | |||||
page_recommend_repo_go=。进入 | |||||
page_recommend_repo_more=项目广场 | |||||
page_dev_env=协同开发环境 | |||||
page_dev_env_desc=启智AI协作开发平台与传统git平台最大的不同就在于提供了面向AI开发的协同开发环境 | |||||
page_dev_env_desc_title=开发要素统一管理 | |||||
page_dev_env_desc_desc=平台提供了AI开发四大要素:模型代码、数据集、模型和执行环境的统一管理 | |||||
page_dev_env_desc1_title=数据协同与共享 | |||||
page_dev_env_desc1_desc=通过在项目中上传数据集,项目成员多人协作完成数据预处理;也可以通过将数据设置为公有数据集,与社区开发者共同建立更好的模型 | |||||
page_dev_env_desc2_title=模型管理与共享 | |||||
page_dev_env_desc2_desc=将模型与代码版本建立关联,可以基于代码历史版本,使用不同的方式调整模型,并将结果保存下来;训练好的模型可以开放共享,让更多人的使用模型测试并提出反馈 | |||||
page_dev_env_desc3_title=一次配置,多次使用 | |||||
page_dev_env_desc3_desc=提供执行环境共享,一次配置,多次使用,降低模型开发门槛,避免花费重复的时间配置复杂的环境 | |||||
page_dev_yunlao=鹏城云脑开源协同 | |||||
page_dev_yunlao_desc1=平台已经与鹏城云脑打通,可以利用鹏城云脑的丰富算力资源,完成AI开发任务 | |||||
page_dev_yunlao_desc2=鹏城云脑现有AI算力100P FLOPS@FP16(每秒十亿亿次半精度浮点计算),主要硬件基础设施由搭载英伟达Tesla V100 的GPU服务器和搭载鲲鹏、昇腾处理器的Atlas 900 AI集群构成 | |||||
page_dev_yunlao_desc3=开发者可以根据使用需求,自由选择相应计算资源,可以测试模型在不同硬件环境下的适配能力、性能、稳定性等 | |||||
page_dev_yunlao_desc4=如果您的模型需要更多的计算资源,也可以单独申请 | |||||
page_dev_yunlao_apply=单独申请 | |||||
[explore] | [explore] | ||||
repos=项目 | repos=项目 | ||||
select_repos=精选项目 | |||||
users=用户 | users=用户 | ||||
organizations=组织 | organizations=组织 | ||||
images = 云脑镜像 | images = 云脑镜像 | ||||
@@ -238,6 +270,8 @@ org_no_results=未找到匹配的组织。 | |||||
code_no_results=未找到与搜索字词匹配的源代码。 | code_no_results=未找到与搜索字词匹配的源代码。 | ||||
code_search_results=“%s” 的搜索结果是 | code_search_results=“%s” 的搜索结果是 | ||||
code_last_indexed_at=最后索引于 %s | code_last_indexed_at=最后索引于 %s | ||||
save=保存 | |||||
cancel=取消 | |||||
[auth] | [auth] | ||||
create_new_account=注册帐号 | create_new_account=注册帐号 | ||||
@@ -425,6 +459,13 @@ static.openiindex=OpenI指数 | |||||
static.registdate=用户注册时间 | static.registdate=用户注册时间 | ||||
static.countdate=系统统计时间 | static.countdate=系统统计时间 | ||||
static.all=所有 | static.all=所有 | ||||
static.public.user_business_analysis_current_month=本月 | |||||
static.public.user_business_analysis_current_week=本周 | |||||
static.public.user_business_analysis_current_year=今年 | |||||
static.public.user_business_analysis_last30_day=近30天 | |||||
static.public.user_business_analysis_last_month=上月 | |||||
static.public.user_business_analysis_yesterday=昨天 | |||||
static.public.user_business_analysis_all=所有 | |||||
[settings] | [settings] | ||||
profile=个人信息 | profile=个人信息 | ||||
account=账号 | account=账号 | ||||
@@ -787,6 +828,7 @@ model_noright=无权限操作 | |||||
model_rename=模型名称重复,请修改模型名称 | model_rename=模型名称重复,请修改模型名称 | ||||
debug=调试 | debug=调试 | ||||
debug_again=再次调试 | |||||
stop=停止 | stop=停止 | ||||
delete=删除 | delete=删除 | ||||
model_download=模型下载 | model_download=模型下载 | ||||
@@ -845,6 +887,7 @@ modelarts.modify=修改 | |||||
modelarts.current_version=当前版本 | modelarts.current_version=当前版本 | ||||
modelarts.parent_version=父版本 | modelarts.parent_version=父版本 | ||||
modelarts.run_version=运行版本 | modelarts.run_version=运行版本 | ||||
modelarts.create_model=创建模型 | |||||
@@ -909,6 +952,8 @@ model.manage.F1 = F1值 | |||||
model.manage.Precision = 精确率 | model.manage.Precision = 精确率 | ||||
model.manage.Recall = 召回率 | model.manage.Recall = 召回率 | ||||
model.manage.sava_model = 保存模型 | model.manage.sava_model = 保存模型 | ||||
model.manage.model_manage = 模型管理 | |||||
model.manage.model_accuracy = 模型精度 | |||||
template.items=模板选项 | template.items=模板选项 | ||||
template.git_content=Git数据(默认分支) | template.git_content=Git数据(默认分支) | ||||
@@ -1424,7 +1469,7 @@ milestones.open_tab=%d 开启中 | |||||
milestones.close_tab=%d 已关闭 | milestones.close_tab=%d 已关闭 | ||||
milestones.closed=于 %s关闭 | milestones.closed=于 %s关闭 | ||||
milestones.no_due_date=暂无截止日期 | milestones.no_due_date=暂无截止日期 | ||||
milestones.open=开启中 | |||||
milestones.open=开启 | |||||
milestones.close=关闭 | milestones.close=关闭 | ||||
milestones.new_subheader=里程碑组织任务,合并请求和跟踪进度。 | milestones.new_subheader=里程碑组织任务,合并请求和跟踪进度。 | ||||
milestones.completeness=%d%% 完成 | milestones.completeness=%d%% 完成 | ||||
@@ -2661,3 +2706,5 @@ foot.member_news=成员动态 | |||||
foot.industry_advisory=行业资讯 | foot.industry_advisory=行业资讯 | ||||
foot.help=帮助 | foot.help=帮助 | ||||
foot.copyright= 版权所有:新一代人工智能开源开放平台(OpenI) | foot.copyright= 版权所有:新一代人工智能开源开放平台(OpenI) | ||||
Platform_Tutorial=新手指引 | |||||
foot.advice_feedback = 意见反馈 |
@@ -11655,6 +11655,11 @@ | |||||
"autolinker": "~0.28.0" | "autolinker": "~0.28.0" | ||||
} | } | ||||
}, | }, | ||||
"remixicon": { | |||||
"version": "2.5.0", | |||||
"resolved": "https://registry.npmjs.org/remixicon/-/remixicon-2.5.0.tgz", | |||||
"integrity": "sha512-q54ra2QutYDZpuSnFjmeagmEiN9IMo56/zz5dDNitzKD23oFRw77cWo4TsrAdmdkPiEn8mxlrTqxnkujDbEGww==" | |||||
}, | |||||
"remove-bom-buffer": { | "remove-bom-buffer": { | ||||
"version": "3.0.0", | "version": "3.0.0", | ||||
"resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", | "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", | ||||
@@ -42,6 +42,7 @@ | |||||
"postcss-preset-env": "6.7.0", | "postcss-preset-env": "6.7.0", | ||||
"postcss-safe-parser": "4.0.2", | "postcss-safe-parser": "4.0.2", | ||||
"qs": "6.9.4", | "qs": "6.9.4", | ||||
"remixicon": "2.5.0", | |||||
"spark-md5": "3.0.1", | "spark-md5": "3.0.1", | ||||
"svg-sprite-loader": "5.0.0", | "svg-sprite-loader": "5.0.0", | ||||
"svgo": "1.3.2", | "svgo": "1.3.2", | ||||
@@ -0,0 +1,442 @@ | |||||
var token; | |||||
if(isEmpty(token)){ | |||||
var meta = $("meta[name=_uid]"); | |||||
if(!isEmpty(meta)){ | |||||
token = meta.attr("content"); | |||||
console.log("token is uid:" + token); | |||||
} | |||||
} | |||||
var swiperNewMessage = new Swiper(".newslist", { | |||||
direction: "vertical", | |||||
slidesPerView: 10, | |||||
loop: true, | |||||
autoplay: { | |||||
delay: 2500, | |||||
disableOnInteraction: false, | |||||
}, | |||||
}); | |||||
var swiperRepo = new Swiper(".homepro-list", { | |||||
slidesPerView: 3, | |||||
slidesPerColumn: 2, | |||||
slidesPerColumnFill:'row', | |||||
spaceBetween: 30, | |||||
pagination: { | |||||
el: ".swiper-pagination", | |||||
clickable: true, | |||||
}, | |||||
autoplay: { | |||||
delay: 2500, | |||||
disableOnInteraction: false, | |||||
}, | |||||
}); | |||||
var output = document.getElementById("newmessage"); | |||||
var socket = new WebSocket("ws://" + document.location.host + "/action/notification"); | |||||
socket.onopen = function () { | |||||
console.log("message has connected."); | |||||
}; | |||||
var messageQueue = []; | |||||
var maxSize = 20; | |||||
var html =document.documentElement; | |||||
var lang = html.attributes["lang"] | |||||
var isZh = true; | |||||
if(lang != null && lang.nodeValue =="en-US" ){ | |||||
console.log("the language is " + lang.nodeValue); | |||||
isZh=false; | |||||
}else{ | |||||
console.log("default lang=zh"); | |||||
} | |||||
socket.onmessage = function (e) { | |||||
var data =JSON.parse(e.data) | |||||
console.log("recevie data=" + e.data) | |||||
var html = ""; | |||||
if (data != null){ | |||||
console.log("queue length=" + messageQueue.length); | |||||
if(messageQueue.length > maxSize){ | |||||
delete messageQueue[0]; | |||||
}else{ | |||||
messageQueue.push(data); | |||||
} | |||||
var currentTime = new Date().getTime(); | |||||
for(var i = 0; i < messageQueue.length; i++){ | |||||
var record = messageQueue[i]; | |||||
var recordPrefix = getMsg(record); | |||||
var actionName = getAction(record.OpType,isZh); | |||||
if(record.OpType == "6" || record.OpType == "10" || record.OpType == "12" || record.OpType == "13"){ | |||||
html += recordPrefix + actionName; | |||||
html += " <a href=\"" + getIssueLink(record) + "\" rel=\"nofollow\">" + getIssueText(record) + "</a>" | |||||
} | |||||
else if(record.OpType == "7" || record.OpType == "11" || record.OpType == "14" || record.OpType == "15" || record.OpType == "22" | |||||
|| record.OpType == "23"){ | |||||
html += recordPrefix + actionName; | |||||
html += " <a href=\"" + getPRLink(record) + "\" rel=\"nofollow\">" + getPRText(record) + "</a>" | |||||
} | |||||
else if(record.OpType == "1"){ | |||||
html += recordPrefix + actionName; | |||||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>" | |||||
} | |||||
else if(record.OpType == "9" || record.OpType == "5"){ | |||||
branch = "<a href=\"" + getRepoLink(record) + "/src/branch/" + record.RefName + "\" rel=\"nofollow\">" + record.RefName + "</a>" | |||||
actionName = actionName.replace("{branch}",branch); | |||||
html += recordPrefix + actionName; | |||||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>" | |||||
}else if(record.OpType == "17"){ | |||||
actionName = actionName.replace("{deleteBranchName}",record.RefName); | |||||
var repoLink = "<a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>" | |||||
actionName = actionName.replace("{repoName}",repoLink); | |||||
html += recordPrefix + actionName; | |||||
} | |||||
else if(record.OpType == "2"){ | |||||
actionName = actionName.replace("{oldRepoName}",record.Content); | |||||
html += recordPrefix + actionName; | |||||
html += " <a href=\"" + getRepoLink(record) + "\" rel=\"nofollow\">" + getRepoLink(record) + "</a>" | |||||
} | |||||
else{ | |||||
continue; | |||||
} | |||||
if(record.Repo != null){ | |||||
var time = getTime(record.CreatedUnix,currentTime); | |||||
html += " " + time; | |||||
} | |||||
html += "</div>"; | |||||
html += "</div>"; | |||||
} | |||||
/* | |||||
<div class="swiper-slide item"> | |||||
<img class="ui avatar image" src="/user/avatar/zhoupzh/-1" alt=""> | |||||
<div class="middle aligned content"> | |||||
<a href="/zhoupzh" title="">zhoupzh</a> 合并了合并请求 <a href="/OpenI/aiforge/pulls/1168" rel="nofollow">OpenI/aiforge#1168</a><span class="time-since">22 分钟前</span> | |||||
</div> | |||||
</div> | |||||
*/ | |||||
} | |||||
console.log("html=" + html) | |||||
output.innerHTML = html; | |||||
swiperNewMessage.updateSlides(); | |||||
swiperNewMessage.updateProgress(); | |||||
}; | |||||
function getMsg(record){ | |||||
var html =""; | |||||
html += "<div class=\"swiper-slide item\">"; | |||||
html += " <img class=\"ui avatar image\" src=\"/user/avatar/" + record.ActUser.Name + "/-1\" alt=\"\">" | |||||
html += " <div class=\"middle aligned content nowrap\">" | |||||
html += " <a href=\"/" + record.ActUser.Name + "\" title=\"\">" + record.ActUser.Name + "</a>" | |||||
return html; | |||||
} | |||||
function getRepoLink(record){ | |||||
return "/" + record.Repo.OwnerName + "/" + record.Repo.Name; | |||||
} | |||||
function getRepoLink(record){ | |||||
return record.Repo.OwnerName + "/" + record.Repo.Name; | |||||
} | |||||
function getTime(UpdatedUnix,currentTime){ | |||||
UpdatedUnix = UpdatedUnix; | |||||
currentTime = currentTime / 1000; | |||||
var timeEscSecond = currentTime - UpdatedUnix; | |||||
if( timeEscSecond < 0){ | |||||
timeEscSecond = 1; | |||||
} | |||||
console.log("currentTime=" + currentTime + " updateUnix=" + UpdatedUnix); | |||||
var hours= Math.floor(timeEscSecond / 3600); | |||||
//计算相差分钟数 | |||||
var leave2 = Math.floor(timeEscSecond % (3600)); //计算小时数后剩余的秒数 | |||||
var minutes= Math.floor(leave2 / 60);//计算相差分钟数 | |||||
var leave3=Math.floor(leave2 % 60); //计算分钟数后剩余的秒数 | |||||
var seconds= leave3; | |||||
if(hours == 0 && minutes == 0){ | |||||
return seconds + getRepoOrOrg(6,isZh); | |||||
}else{ | |||||
if(hours > 0){ | |||||
return hours + getRepoOrOrg(4,isZh); | |||||
}else{ | |||||
return minutes + getRepoOrOrg(5,isZh); | |||||
} | |||||
} | |||||
} | |||||
function getPRLink(record){ | |||||
return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/pulls/" + getIssueId(record); | |||||
} | |||||
function getPRText(record){ | |||||
return record.Repo.OwnerName + "/" + record.Repo.Name + "#" + getIssueId(record); | |||||
} | |||||
function getIssueLink(record){ | |||||
return "/" + record.Repo.OwnerName + "/" + record.Repo.Name + "/issues/" + getIssueId(record); | |||||
} | |||||
function getIssueId(record){ | |||||
var Id = "1"; | |||||
if(!isEmpty(record.Comment) && !isEmpty(record.Comment.Issue)){ | |||||
Id = record.Comment.Issue.Index; | |||||
}else{ | |||||
if(!isEmpty(record.Content)){ | |||||
var content = record.Content; | |||||
var index = content.indexOf("|"); | |||||
if(index != -1){ | |||||
Id = content.substring(0,index); | |||||
} | |||||
} | |||||
} | |||||
return Id; | |||||
} | |||||
function getIssueText(record){ | |||||
return record.Repo.OwnerName + "/" + record.Repo.Name + "#" + getIssueId(record); | |||||
} | |||||
/* | |||||
ActionCreateRepo ActionType = iota + 1 // 1 | |||||
ActionRenameRepo // 2 | |||||
ActionStarRepo // 3 | |||||
ActionWatchRepo // 4 | |||||
ActionCommitRepo // 5 | |||||
ActionCreateIssue // 6 | |||||
ActionCreatePullRequest // 7 | |||||
ActionTransferRepo // 8 | |||||
ActionPushTag // 9 | |||||
ActionCommentIssue // 10 | |||||
ActionMergePullRequest // 11 | |||||
ActionCloseIssue // 12 | |||||
ActionReopenIssue // 13 | |||||
ActionClosePullRequest // 14 | |||||
ActionReopenPullRequest // 15 | |||||
ActionDeleteTag // 16 | |||||
ActionDeleteBranch // 17 | |||||
ActionMirrorSyncPush // 18 | |||||
ActionMirrorSyncCreate // 19 | |||||
ActionMirrorSyncDelete // 20 | |||||
ActionApprovePullRequest // 21 | |||||
ActionRejectPullRequest // 22 | |||||
ActionCommentPull // 23 | |||||
*/ | |||||
var actionNameZH={ | |||||
"1":"创建了项目", | |||||
"2":"重命名项目 {oldRepoName} 为", | |||||
"5":"推送了 {branch} 分支的代码到", | |||||
"6":"创建了任务", | |||||
"7":"创建了合并请求", | |||||
"9":"推送了 {branch} 分支的代码到", | |||||
"10":"评论了任务", | |||||
"11":"合并了合并请求", | |||||
"12":"关闭了任务", | |||||
"13":"重新开启了任务", | |||||
"14":"关闭了合并请求", | |||||
"15":"重新开启了合并请求", | |||||
"17":"从 {repoName} 删除分支 {deleteBranchName}", | |||||
"22":"拒绝了合并请求", | |||||
"23":"评论了合并请求" | |||||
}; | |||||
var actionNameEN={ | |||||
"1":" created repository", | |||||
"2":" renamed repository from {oldRepoName} to ", | |||||
"5":" pushed to {branch} at", | |||||
"6":" opened issue", | |||||
"7":" created pull request", | |||||
"9":" pushed to {branch} at", | |||||
"10":" commented on issue", | |||||
"11":" merged pull request", | |||||
"12":" closed issue", | |||||
"13":" reopened issue", | |||||
"14":" closed pull request", | |||||
"15":" reopened pull request", | |||||
"17":" deleted branch {deleteBranchName} from {repoName}", | |||||
"22":" rejected pull request", | |||||
"23":" commented on pull request" | |||||
}; | |||||
var repoAndOrgZH={ | |||||
"1":"项目", | |||||
"2":"成员", | |||||
"3":"团队", | |||||
"4":"小时前", | |||||
"5":"分钟前", | |||||
"6":"秒前" | |||||
}; | |||||
var repoAndOrgEN={ | |||||
"1":"repository", | |||||
"2":"Members ", | |||||
"3":"Teams", | |||||
"4":" hours ago", | |||||
"5":" minutes ago", | |||||
"6":" seconds ago" | |||||
}; | |||||
function getAction(opType,isZh){ | |||||
if(isZh){ | |||||
return actionNameZH[opType] | |||||
}else{ | |||||
return actionNameEN[opType] | |||||
} | |||||
} | |||||
queryRecommendData(); | |||||
function queryRecommendData(){ | |||||
$.ajax({ | |||||
type:"GET", | |||||
url:"/recommend/org", | |||||
headers: { | |||||
authorization:token, | |||||
}, | |||||
dataType:"json", | |||||
async:false, | |||||
success:function(json){ | |||||
console.log(json); | |||||
displayOrg(json); | |||||
}, | |||||
error:function(response) { | |||||
console.log(response); | |||||
} | |||||
}); | |||||
$.ajax({ | |||||
type:"GET", | |||||
url:"/recommend/repo", | |||||
headers: { | |||||
authorization:token, | |||||
}, | |||||
dataType:"json", | |||||
async:false, | |||||
success:function(json){ | |||||
console.log(json); | |||||
displayRepo(json); | |||||
}, | |||||
error:function(response) { | |||||
console.log(response); | |||||
} | |||||
}); | |||||
} | |||||
/* | |||||
<div class="swiper-slide"> | |||||
<div class="ui fluid card"> | |||||
<div class="content"> | |||||
<span class="right floated meta"> | |||||
<i class="star icon"></i>276 <i class="star icon"></i>32 | |||||
</span> | |||||
<img class="left floated mini ui image" src="/repo-avatars/278-a9f45e21b92b86dbf969c9f70dff1efc"> | |||||
<a class="header nowrap" href="/OpenI/aiforge">aiforge </a> | |||||
<div class="description nowrap-2"> | |||||
本项目是群体化方法与技术的开源实现案例,在基于Gitea的基础上,进一步支持社交化的协同开发、协同学习、协同研究等群体创新实践服务,特别是针对新一代人工智能技术特点,重点支持项目管理、git代码管理、大数据集存储管理与智能计算平台接入。 | |||||
</div> | |||||
<div class="ui tags nowrap am-mt-10"> | |||||
<a class="ui small label topic" href="/explore/repos?q=ai%e5%bc%80%e5%8f%91%e5%b7%a5%e5%85%b7&topic=">ai开发工具</a> | |||||
<a class="ui small label topic" href="/explore/repos?q=openi&topic=">openi</a> | |||||
<a class="ui small label topic" href="/explore/repos?q=golang&topic=">golang</a> | |||||
<a class="ui small label topic" href="/explore/repos?q=git&topic=">git</a> | |||||
<a class="ui small label topic" href="/explore/repos?q=pcl&topic=">pcl</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
*/ | |||||
function displayRepo(json){ | |||||
var orgRepo = document.getElementById("recommendrepo"); | |||||
var html = ""; | |||||
if (json != null && json.length > 0){ | |||||
for(var i = 0; i < json.length;i++){ | |||||
var record = json[i] | |||||
html += "<div class=\"swiper-slide\">"; | |||||
html += " <div class=\"ui fluid card\">"; | |||||
html += " <div class=\"content\">"; | |||||
html += " <span class=\"right floated meta\">"; | |||||
html += " <i class=\"ri-star-line\"></i>" + record["NumStars"] + "<i class=\"ri-git-branch-line am-ml-10\"></i>" + record["NumForks"]; | |||||
html += " </span>"; | |||||
html += " <img class=\"left floated mini ui image\" src=\"" + record["Avatar"] + "\">"; | |||||
html += " <a class=\"header nowrap\" href=\"/" + record["OwnerName"] + "/" + record["Name"] + "\">" + record["Name"] +"</a>"; | |||||
html += " <div class=\"description nowrap-2\">" + record["Description"] + " </div>"; | |||||
html += " <div class=\"ui tags nowrap am-mt-10\">" | |||||
if(record["Topics"] != null){ | |||||
for(var j = 0; j < record["Topics"].length; j++){ | |||||
topic = record["Topics"][j]; | |||||
url = "/explore/repos?q=" + (topic) + "&topic=" | |||||
html += "<a class=\"ui small label topic\" href=\"" + url + "\">" + topic + "</a>"; | |||||
} | |||||
} | |||||
html += " </div>"; | |||||
html += " </div>"; | |||||
html += " </div>"; | |||||
html += "</div>"; | |||||
} | |||||
} | |||||
orgRepo.innerHTML = html; | |||||
swiperRepo.updateSlides(); | |||||
swiperRepo.updateProgress(); | |||||
} | |||||
/** | |||||
* | |||||
* <div class="column"> | |||||
<div class="ui fluid card"> | |||||
<div class="content"> | |||||
<div class="ui small header"> | |||||
<img class="ui image" src="/user/avatar/OpenI/-1"> | |||||
<div class="content nowrap"> | |||||
<a href="/OpenI">OpenI</a> 启智社区 | |||||
<div class="sub header">39 项目 ・ 60 成员 ・ 23 团队</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
*/ | |||||
//var repoAndOrgZH = new Map([['1', "项目"], ['2', "成员"], ['3', "团队"]]); | |||||
//var repoAndOrgEN = new Map([['1', "Repository"], ['2', "Members"], ['3', "Teams"]]); | |||||
function getRepoOrOrg(key,isZhLang){ | |||||
if(isZhLang){ | |||||
return repoAndOrgZH[key]; | |||||
}else{ | |||||
return repoAndOrgEN[key]; | |||||
} | |||||
} | |||||
function displayOrg(json){ | |||||
var orgDiv = document.getElementById("recommendorg"); | |||||
var html = ""; | |||||
if (json != null && json.length > 0){ | |||||
for(var i = 0; i < json.length;i++){ | |||||
var record = json[i] | |||||
html += "<div class=\"column\">"; | |||||
html += " <a href=\"/" + record["Name"] + "\" class=\"ui fluid card\">"; | |||||
html += " <div class=\"content\">"; | |||||
html += " <div class=\"ui small header\">"; | |||||
html += " <img class=\"ui image\" src=\"" + record["Avatar"] + "\">"; | |||||
html += " <div class=\"content nowrap\">"; | |||||
html += " <span class=\"ui blue\">" + record["Name"] + "</span> " + record["FullName"]; | |||||
html += " <div class=\"sub header\">" + record["NumRepos"] +" " + getRepoOrOrg(1,isZh) + " ・ " + record["NumMembers"] +" " + getRepoOrOrg(2,isZh) + " ・ " + record["NumTeams"] + " " + getRepoOrOrg(3,isZh) + "</div>"; | |||||
html += " </div>"; | |||||
html += " </div>"; | |||||
html += " </div>"; | |||||
html += " </a>"; | |||||
html += "</div>"; | |||||
} | |||||
} | |||||
orgDiv.innerHTML = html; | |||||
} |
@@ -1,6 +1,8 @@ | |||||
package routers | package routers | ||||
import ( | import ( | ||||
"net/http" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
@@ -11,6 +13,9 @@ import ( | |||||
var upgrader = websocket.Upgrader{ | var upgrader = websocket.Upgrader{ | ||||
ReadBufferSize: 1024, | ReadBufferSize: 1024, | ||||
WriteBufferSize: 1024, | WriteBufferSize: 1024, | ||||
CheckOrigin: func(r *http.Request) bool { | |||||
return true | |||||
}, | |||||
} | } | ||||
var SocketManager = socketwrap.NewClientsManager() | var SocketManager = socketwrap.NewClientsManager() | ||||
@@ -24,7 +29,7 @@ func ActionNotification(ctx *context.Context) { | |||||
} | } | ||||
client := &socketwrap.Client{Manager: SocketManager, Conn: conn, Send: make(chan *models.Action, 256)} | client := &socketwrap.Client{Manager: SocketManager, Conn: conn, Send: make(chan *models.Action, 256)} | ||||
WriteLastTenActionsIfHave(conn) | |||||
WriteLastActionsIfHave(conn) | |||||
client.Manager.Register <- client | client.Manager.Register <- client | ||||
@@ -32,22 +37,20 @@ func ActionNotification(ctx *context.Context) { | |||||
} | } | ||||
func WriteLastTenActionsIfHave(conn *websocket.Conn) { | |||||
socketwrap.LastTenActionsQueue.Mutex.RLock() | |||||
func WriteLastActionsIfHave(conn *websocket.Conn) { | |||||
socketwrap.LastActionsQueue.Mutex.RLock() | |||||
{ | { | ||||
size := socketwrap.LastTenActionsQueue.Queue.Len() | |||||
size := socketwrap.LastActionsQueue.Queue.Len() | |||||
if size > 0 { | if size > 0 { | ||||
tempE := socketwrap.LastTenActionsQueue.Queue.Front() | |||||
conn.WriteJSON(tempE) | |||||
tempE := socketwrap.LastActionsQueue.Queue.Front() | |||||
conn.WriteJSON(tempE.Value) | |||||
for i := 1; i < size; i++ { | for i := 1; i < size; i++ { | ||||
tempE = tempE.Next() | tempE = tempE.Next() | ||||
conn.WriteJSON(tempE) | |||||
conn.WriteJSON(tempE.Value) | |||||
} | } | ||||
} | } | ||||
} | } | ||||
socketwrap.LastTenActionsQueue.Mutex.RUnlock() | |||||
socketwrap.LastActionsQueue.Mutex.RUnlock() | |||||
} | } | ||||
@@ -524,7 +524,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
Get(notify.GetThread). | Get(notify.GetThread). | ||||
Patch(notify.ReadThread) | Patch(notify.ReadThread) | ||||
}, reqToken()) | }, reqToken()) | ||||
operationReq := context.Toggle(&context.ToggleOptions{SignInRequired: true, OperationRequired: true}) | operationReq := context.Toggle(&context.ToggleOptions{SignInRequired: true, OperationRequired: true}) | ||||
//Project board | //Project board | ||||
m.Group("/projectboard", func() { | m.Group("/projectboard", func() { | ||||
@@ -544,7 +544,13 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
}, operationReq) | }, operationReq) | ||||
m.Get("/query_user_static_page", operationReq, repo_ext.QueryUserStaticDataPage) | m.Get("/query_user_static_page", operationReq, repo_ext.QueryUserStaticDataPage) | ||||
m.Get("/query_user_current_month", operationReq, repo_ext.QueryUserStaticCurrentMonth) | |||||
m.Get("/query_user_current_week", operationReq, repo_ext.QueryUserStaticCurrentWeek) | |||||
m.Get("/query_user_current_year", operationReq, repo_ext.QueryUserStaticCurrentYear) | |||||
m.Get("/query_user_last30_day", operationReq, repo_ext.QueryUserStaticLast30Day) | |||||
m.Get("/query_user_last_month", operationReq, repo_ext.QueryUserStaticLastMonth) | |||||
m.Get("/query_user_yesterday", operationReq, repo_ext.QueryUserStaticYesterday) | |||||
m.Get("/query_user_all", operationReq, repo_ext.QueryUserStaticAll) | |||||
// Users | // Users | ||||
m.Group("/users", func() { | m.Group("/users", func() { | ||||
m.Get("/search", user.Search) | m.Get("/search", user.Search) | ||||
@@ -6,6 +6,7 @@ | |||||
package repo | package repo | ||||
import ( | import ( | ||||
"code.gitea.io/gitea/modules/util" | |||||
"net/http" | "net/http" | ||||
"strconv" | "strconv" | ||||
"strings" | "strings" | ||||
@@ -15,6 +16,7 @@ import ( | |||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/modelarts" | "code.gitea.io/gitea/modules/modelarts" | ||||
"code.gitea.io/gitea/modules/storage" | "code.gitea.io/gitea/modules/storage" | ||||
routerRepo "code.gitea.io/gitea/routers/repo" | |||||
) | ) | ||||
func GetModelArtsNotebook(ctx *context.APIContext) { | func GetModelArtsNotebook(ctx *context.APIContext) { | ||||
@@ -105,7 +107,7 @@ func GetModelArtsTrainJobVersion(ctx *context.APIContext) { | |||||
job.TrainJobDuration = result.TrainJobDuration | job.TrainJobDuration = result.TrainJobDuration | ||||
if result.Duration != 0 { | if result.Duration != 0 { | ||||
job.TrainJobDuration = addZero(result.Duration/3600000) + ":" + addZero(result.Duration%3600000/60000) + ":" + addZero(result.Duration%60000/1000) | |||||
job.TrainJobDuration = util.AddZero(result.Duration/3600000) + ":" + util.AddZero(result.Duration%3600000/60000) + ":" + util.AddZero(result.Duration%60000/1000) | |||||
} else { | } else { | ||||
job.TrainJobDuration = "00:00:00" | job.TrainJobDuration = "00:00:00" | ||||
@@ -124,15 +126,6 @@ func GetModelArtsTrainJobVersion(ctx *context.APIContext) { | |||||
} | } | ||||
func addZero(t int64) (m string) { | |||||
if t < 10 { | |||||
m = "0" + strconv.FormatInt(t, 10) | |||||
return m | |||||
} else { | |||||
return strconv.FormatInt(t, 10) | |||||
} | |||||
} | |||||
func TrainJobGetLog(ctx *context.APIContext) { | func TrainJobGetLog(ctx *context.APIContext) { | ||||
var ( | var ( | ||||
err error | err error | ||||
@@ -237,7 +230,7 @@ func DelTrainJobVersion(ctx *context.APIContext) { | |||||
JobID: jobID, | JobID: jobID, | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("get VersionListCount faild", err) | |||||
ctx.ServerError("get VersionListCount failed", err) | |||||
return | return | ||||
} | } | ||||
if VersionListCount > 0 { | if VersionListCount > 0 { | ||||
@@ -255,6 +248,8 @@ func DelTrainJobVersion(ctx *context.APIContext) { | |||||
return | return | ||||
} | } | ||||
} | } | ||||
} else { //已删除该任务下的所有版本 | |||||
routerRepo.DeleteJobStorage(task.JobName) | |||||
} | } | ||||
ctx.JSON(http.StatusOK, map[string]interface{}{ | ctx.JSON(http.StatusOK, map[string]interface{}{ | ||||
@@ -44,9 +44,52 @@ const ( | |||||
func Home(ctx *context.Context) { | func Home(ctx *context.Context) { | ||||
ctx.Data["PageIsHome"] = true | ctx.Data["PageIsHome"] = true | ||||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | ||||
setRecommendURL(ctx) | |||||
ctx.HTML(200, tplHome) | ctx.HTML(200, tplHome) | ||||
} | } | ||||
func setRecommendURL(ctx *context.Context) { | |||||
addr := setting.RecommentRepoAddr[10:] | |||||
start := strings.Index(addr, "/") | |||||
end := strings.Index(addr, "raw") | |||||
if start != -1 && end != -1 { | |||||
ctx.Data["RecommendURL"] = addr[start:end] | |||||
} else { | |||||
ctx.Data["RecommendURL"] = setting.RecommentRepoAddr | |||||
} | |||||
ctx.Data["page_title"] = ctx.Tr("home.page_title") | |||||
ctx.Data["page_small_title"] = ctx.Tr("home.page_small_title") | |||||
ctx.Data["page_description"] = ctx.Tr("home.page_description") | |||||
ctx.Data["page_use"] = ctx.Tr("home.page_use") | |||||
ctx.Data["page_only_dynamic"] = ctx.Tr("home.page_only_dynamic") | |||||
ctx.Data["page_recommend_org"] = ctx.Tr("home.page_recommend_org") | |||||
ctx.Data["page_recommend_org_desc"] = ctx.Tr("home.page_recommend_org_desc") | |||||
ctx.Data["page_recommend_org_commit"] = ctx.Tr("home.page_recommend_org_commit") | |||||
ctx.Data["page_recommend_org_more"] = ctx.Tr("home.page_recommend_org_more") | |||||
ctx.Data["page_recommend_repo"] = ctx.Tr("home.page_recommend_repo") | |||||
ctx.Data["page_recommend_repo_desc"] = ctx.Tr("home.page_recommend_repo_desc") | |||||
ctx.Data["page_recommend_repo_commit"] = ctx.Tr("home.page_recommend_repo_commit") | |||||
ctx.Data["page_recommend_repo_go"] = ctx.Tr("home.page_recommend_repo_go") | |||||
ctx.Data["page_recommend_repo_more"] = ctx.Tr("home.page_recommend_repo_more") | |||||
ctx.Data["page_dev_env"] = ctx.Tr("home.page_dev_env") | |||||
ctx.Data["page_dev_env_desc"] = ctx.Tr("home.page_dev_env_desc") | |||||
ctx.Data["page_dev_env_desc_title"] = ctx.Tr("home.page_dev_env_desc_title") | |||||
ctx.Data["page_dev_env_desc_desc"] = ctx.Tr("home.page_dev_env_desc_desc") | |||||
ctx.Data["page_dev_env_desc1_title"] = ctx.Tr("home.page_dev_env_desc1_title") | |||||
ctx.Data["page_dev_env_desc1_desc"] = ctx.Tr("home.page_dev_env_desc1_desc") | |||||
ctx.Data["page_dev_env_desc2_title"] = ctx.Tr("home.page_dev_env_desc2_title") | |||||
ctx.Data["page_dev_env_desc2_desc"] = ctx.Tr("home.page_dev_env_desc2_desc") | |||||
ctx.Data["page_dev_env_desc3_title"] = ctx.Tr("home.page_dev_env_desc3_title") | |||||
ctx.Data["page_dev_env_desc3_desc"] = ctx.Tr("home.page_dev_env_desc3_desc") | |||||
ctx.Data["page_dev_yunlao"] = ctx.Tr("home.page_dev_yunlao") | |||||
ctx.Data["page_dev_yunlao_desc1"] = ctx.Tr("home.page_dev_yunlao_desc1") | |||||
ctx.Data["page_dev_yunlao_desc2"] = ctx.Tr("home.page_dev_yunlao_desc2") | |||||
ctx.Data["page_dev_yunlao_desc3"] = ctx.Tr("home.page_dev_yunlao_desc3") | |||||
ctx.Data["page_dev_yunlao_desc4"] = ctx.Tr("home.page_dev_yunlao_desc4") | |||||
ctx.Data["page_dev_yunlao_apply"] = ctx.Tr("home.page_dev_yunlao_apply") | |||||
} | |||||
func Dashboard(ctx *context.Context) { | func Dashboard(ctx *context.Context) { | ||||
if ctx.IsSigned { | if ctx.IsSigned { | ||||
if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm { | if !ctx.User.IsActive && setting.Service.RegisterEmailConfirm { | ||||
@@ -77,7 +120,7 @@ func Dashboard(ctx *context.Context) { | |||||
ctx.Redirect(setting.AppSubURL + "/user/login") | ctx.Redirect(setting.AppSubURL + "/user/login") | ||||
return | return | ||||
} | } | ||||
setRecommendURL(ctx) | |||||
ctx.Data["PageIsHome"] = true | ctx.Data["PageIsHome"] = true | ||||
ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled | ||||
ctx.HTML(200, tplHome) | ctx.HTML(200, tplHome) | ||||
@@ -527,6 +570,8 @@ func RecommendOrgFromPromote(ctx *context.Context) { | |||||
if err == nil { | if err == nil { | ||||
userMap := make(map[string]interface{}) | userMap := make(map[string]interface{}) | ||||
userMap["Name"] = user.Name | userMap["Name"] = user.Name | ||||
userMap["Description"] = user.Description | |||||
userMap["FullName"] = user.FullName | |||||
userMap["ID"] = user.ID | userMap["ID"] = user.ID | ||||
userMap["Avatar"] = user.RelAvatarLink() | userMap["Avatar"] = user.RelAvatarLink() | ||||
userMap["NumRepos"] = user.NumRepos | userMap["NumRepos"] = user.NumRepos | ||||
@@ -558,14 +603,8 @@ func recommendFromPromote(url string) ([]string, error) { | |||||
lines := strings.Split(allLineStr, "\n") | lines := strings.Split(allLineStr, "\n") | ||||
result := make([]string, len(lines)) | result := make([]string, len(lines)) | ||||
for i, line := range lines { | for i, line := range lines { | ||||
tmpIndex := strings.Index(line, ".") | |||||
log.Info("i=" + fmt.Sprint(i) + " line=" + line + " tmpIndex=" + fmt.Sprint(tmpIndex)) | |||||
if tmpIndex == -1 { | |||||
result[i] = strings.Trim(line, " ") | |||||
} else { | |||||
result[i] = strings.Trim(line[tmpIndex+1:], " ") | |||||
} | |||||
log.Info("i=" + fmt.Sprint(i) + " line=" + line) | |||||
result[i] = strings.Trim(line, " ") | |||||
} | } | ||||
return result, nil | return result, nil | ||||
} | } | ||||
@@ -0,0 +1,87 @@ | |||||
package notice | |||||
import ( | |||||
"code.gitea.io/gitea/models" | |||||
"code.gitea.io/gitea/modules/log" | |||||
"code.gitea.io/gitea/modules/setting" | |||||
"encoding/json" | |||||
"github.com/patrickmn/go-cache" | |||||
"time" | |||||
) | |||||
var noticeCache = cache.New(2*time.Minute, 1*time.Minute) | |||||
const ( | |||||
NOTICE_CACHE_KEY = "notice" | |||||
) | |||||
type Notice struct { | |||||
Title string | |||||
Link string | |||||
Visible int //0 invisible, 1 visible | |||||
CommitId string | |||||
} | |||||
var lock int32 = 0 | |||||
func GetNewestNotice() (*Notice, error) { | |||||
defer func() { | |||||
if err := recover(); err != nil { | |||||
log.Error("recover error", err) | |||||
} | |||||
}() | |||||
var notice *Notice | |||||
var err error | |||||
if setting.CacheOn { | |||||
notice, err = getNewestNoticeFromCacheAndDisk() | |||||
} else { | |||||
notice, err = getNewestNoticeFromDisk() | |||||
} | |||||
if err != nil { | |||||
return nil, err | |||||
} | |||||
return notice, nil | |||||
} | |||||
func getNoticeTimeout() time.Duration { | |||||
return time.Duration(setting.CacheTimeOutSecond) * time.Second | |||||
} | |||||
func getNewestNoticeFromDisk() (*Notice, error) { | |||||
log.Debug("Get notice from disk") | |||||
repoFile, err := models.ReadLatestFileInRepo(setting.UserNameOfNoticeRepo, setting.RepoNameOfNoticeRepo, setting.RefNameOfNoticeRepo, setting.TreePathOfNoticeRepo) | |||||
if err != nil { | |||||
log.Error("GetNewestNotice failed, error=%v", err) | |||||
return nil, err | |||||
} | |||||
notice := &Notice{} | |||||
json.Unmarshal(repoFile.Content, notice) | |||||
if notice.Title == "" { | |||||
return nil, err | |||||
} | |||||
notice.CommitId = repoFile.CommitId | |||||
return notice, nil | |||||
} | |||||
func getNewestNoticeFromCacheAndDisk() (*Notice, error) { | |||||
v, success := noticeCache.Get(NOTICE_CACHE_KEY) | |||||
if success { | |||||
log.Debug("Get notice from cache,value = %v", v) | |||||
if v == nil { | |||||
return nil, nil | |||||
} | |||||
n := v.(*Notice) | |||||
return n, nil | |||||
} | |||||
notice, err := getNewestNoticeFromDisk() | |||||
if err != nil { | |||||
log.Error("GetNewestNotice failed, error=%v", err) | |||||
noticeCache.Set(NOTICE_CACHE_KEY, nil, 30*time.Second) | |||||
return nil, err | |||||
} | |||||
noticeCache.Set(NOTICE_CACHE_KEY, notice, getNoticeTimeout()) | |||||
return notice, nil | |||||
} |
@@ -130,5 +130,13 @@ func Home(ctx *context.Context) { | |||||
pager.SetDefaultParams(ctx) | pager.SetDefaultParams(ctx) | ||||
ctx.Data["Page"] = pager | ctx.Data["Page"] = pager | ||||
//find org tag info | |||||
tags, err := models.GetAllOfficialTagRepos(org.ID, ctx.Org.IsOwner) | |||||
if err != nil { | |||||
ctx.ServerError("GetAllOfficialTagRepos", err) | |||||
return | |||||
} | |||||
ctx.Data["tags"] = tags | |||||
ctx.HTML(200, tplOrgHome) | ctx.HTML(200, tplOrgHome) | ||||
} | } |
@@ -0,0 +1,90 @@ | |||||
// Copyright 2014 The Gogs Authors. All rights reserved. | |||||
// Copyright 2020 The Gitea Authors. | |||||
// Use of this source code is governed by a MIT-style | |||||
// license that can be found in the LICENSE file. | |||||
package org | |||||
import ( | |||||
"code.gitea.io/gitea/models" | |||||
"code.gitea.io/gitea/modules/auth" | |||||
"code.gitea.io/gitea/modules/context" | |||||
"errors" | |||||
"strconv" | |||||
) | |||||
const DefaultOrgTagLimit = -1 | |||||
// SubmitTags submit repos of org tag | |||||
func SubmitTags(ctx *context.Context, form auth.SubmitReposOfTagForm) { | |||||
if !ctx.Org.IsOwner { | |||||
ctx.ServerError("UpdateTagReposByID", errors.New("no access to submit tags")) | |||||
return | |||||
} | |||||
tag := getTagFromContext(ctx) | |||||
if ctx.Written() { | |||||
return | |||||
} | |||||
if tag.Limit != DefaultOrgTagLimit && len(form.RepoList) > tag.Limit { | |||||
ctx.ServerError("UpdateTagReposByID", errors.New("tags size over limit")) | |||||
return | |||||
} | |||||
err := models.UpdateTagReposByID(tag.ID, ctx.Org.Organization.ID, form.RepoList) | |||||
if err != nil { | |||||
ctx.ServerError("UpdateTagReposByID", err) | |||||
return | |||||
} | |||||
ctx.JSON(200, map[string]interface{}{ | |||||
"code": "00", | |||||
"msg": "success", | |||||
}) | |||||
} | |||||
// GetTagRepos get repos under org tag | |||||
func GetTagRepos(ctx *context.Context) { | |||||
if !ctx.Org.IsOwner { | |||||
ctx.ServerError("GetTagRepos", errors.New("no access to get tags")) | |||||
return | |||||
} | |||||
tag := getTagFromContext(ctx) | |||||
if ctx.Written() { | |||||
return | |||||
} | |||||
r, err := models.GetTagRepos(tag.ID, ctx.Org.Organization.ID) | |||||
if err != nil { | |||||
ctx.ServerError("GetTagRepos", err) | |||||
return | |||||
} | |||||
ctx.JSON(200, map[string]interface{}{ | |||||
"code": "00", | |||||
"msg": "success", | |||||
"data": r, | |||||
}) | |||||
} | |||||
// getTagFromContext finds out tag info From context. | |||||
func getTagFromContext(ctx *context.Context) *models.OfficialTag { | |||||
var tag *models.OfficialTag | |||||
var err error | |||||
tagIdStr := ctx.Query("tagId") | |||||
if len(tagIdStr) == 0 { | |||||
ctx.ServerError("GetTagInfo", errors.New("tag is not exist")) | |||||
return nil | |||||
} | |||||
tagId, _ := strconv.ParseInt(tagIdStr, 10, 32) | |||||
tag, err = models.GetTagByID(tagId) | |||||
if err != nil { | |||||
if models.IsErrTagNotExist(err) { | |||||
ctx.NotFound("GetTagInfo", err) | |||||
} else { | |||||
ctx.ServerError("GetTagInfo", err) | |||||
} | |||||
return nil | |||||
} | |||||
return tag | |||||
} |
@@ -99,6 +99,18 @@ func saveModelByParameters(jobId string, versionName string, name string, versio | |||||
//udpate status and version count | //udpate status and version count | ||||
models.ModifyModelNewProperty(lastNewModelId, MODEL_NOT_LATEST, 0) | models.ModifyModelNewProperty(lastNewModelId, MODEL_NOT_LATEST, 0) | ||||
} | } | ||||
var units []models.RepoUnit | |||||
var deleteUnitTypes []models.UnitType | |||||
units = append(units, models.RepoUnit{ | |||||
RepoID: ctx.Repo.Repository.ID, | |||||
Type: models.UnitTypeModelManage, | |||||
Config: &models.ModelManageConfig{ | |||||
EnableModelManage: true, | |||||
}, | |||||
}) | |||||
deleteUnitTypes = append(deleteUnitTypes, models.UnitTypeModelManage) | |||||
models.UpdateRepositoryUnits(ctx.Repo.Repository, units, deleteUnitTypes) | |||||
log.Info("save model end.") | log.Info("save model end.") | ||||
@@ -130,10 +142,13 @@ func SaveModel(ctx *context.Context) { | |||||
version := ctx.Query("Version") | version := ctx.Query("Version") | ||||
label := ctx.Query("Label") | label := ctx.Query("Label") | ||||
description := ctx.Query("Description") | description := ctx.Query("Description") | ||||
trainTaskCreate := ctx.QueryBool("trainTaskCreate") | |||||
if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { | |||||
ctx.ServerError("No right.", errors.New(ctx.Tr("repo.model_noright"))) | |||||
return | |||||
if !trainTaskCreate { | |||||
if !ctx.Repo.CanWrite(models.UnitTypeModelManage) { | |||||
ctx.ServerError("No right.", errors.New(ctx.Tr("repo.model_noright"))) | |||||
return | |||||
} | |||||
} | } | ||||
if JobId == "" || VersionName == "" { | if JobId == "" || VersionName == "" { | ||||
@@ -474,6 +489,23 @@ func ShowOneVersionOtherModel(ctx *context.Context) { | |||||
func ShowModelTemplate(ctx *context.Context) { | func ShowModelTemplate(ctx *context.Context) { | ||||
ctx.Data["isModelManage"] = true | ctx.Data["isModelManage"] = true | ||||
repoId := ctx.Repo.Repository.ID | |||||
Type := -1 | |||||
_, count, _ := models.QueryModel(&models.AiModelQueryOptions{ | |||||
ListOptions: models.ListOptions{ | |||||
Page: 1, | |||||
PageSize: 2, | |||||
}, | |||||
RepoID: repoId, | |||||
Type: Type, | |||||
New: MODEL_LATEST, | |||||
}) | |||||
ctx.Data["MODEL_COUNT"] = count | |||||
_, trainCount, _ := models.QueryModelTrainJobList(repoId) | |||||
log.Info("query train count=" + fmt.Sprint(trainCount)) | |||||
ctx.Data["TRAIN_COUNT"] = trainCount | |||||
ctx.HTML(200, tplModelManageIndex) | ctx.HTML(200, tplModelManageIndex) | ||||
} | } | ||||
@@ -626,7 +658,6 @@ func QueryModelListForPredict(ctx *context.Context) { | |||||
func QueryModelFileForPredict(ctx *context.Context) { | func QueryModelFileForPredict(ctx *context.Context) { | ||||
id := ctx.Query("ID") | id := ctx.Query("ID") | ||||
parentDir := ctx.Query("parentDir") | |||||
model, err := models.QueryModelById(id) | model, err := models.QueryModelById(id) | ||||
if err != nil { | if err != nil { | ||||
log.Error("no such model!", err.Error()) | log.Error("no such model!", err.Error()) | ||||
@@ -634,9 +665,20 @@ func QueryModelFileForPredict(ctx *context.Context) { | |||||
return | return | ||||
} | } | ||||
prefix := model.Path[len(setting.Bucket)+1:] | prefix := model.Path[len(setting.Bucket)+1:] | ||||
if parentDir != "" { | |||||
prefix = prefix + parentDir | |||||
} | |||||
fileinfos, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, prefix) | fileinfos, err := storage.GetAllObjectByBucketAndPrefix(setting.Bucket, prefix) | ||||
ctx.JSON(http.StatusOK, fileinfos) | ctx.JSON(http.StatusOK, fileinfos) | ||||
} | } | ||||
func QueryOneLevelModelFile(ctx *context.Context) { | |||||
id := ctx.Query("ID") | |||||
parentDir := ctx.Query("parentDir") | |||||
model, err := models.QueryModelById(id) | |||||
if err != nil { | |||||
log.Error("no such model!", err.Error()) | |||||
ctx.ServerError("no such model:", err) | |||||
return | |||||
} | |||||
prefix := model.Path[len(setting.Bucket)+1:] | |||||
fileinfos, err := storage.GetOneLevelAllObjectUnderDir(setting.Bucket, prefix, parentDir) | |||||
ctx.JSON(http.StatusOK, fileinfos) | |||||
} |
@@ -6,13 +6,6 @@ package repo | |||||
import ( | import ( | ||||
"bytes" | "bytes" | ||||
"container/list" | |||||
"fmt" | |||||
"html" | |||||
gotemplate "html/template" | |||||
"net/url" | |||||
"strings" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
@@ -22,6 +15,12 @@ import ( | |||||
"code.gitea.io/gitea/modules/markup" | "code.gitea.io/gitea/modules/markup" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/timeutil" | "code.gitea.io/gitea/modules/timeutil" | ||||
"container/list" | |||||
"fmt" | |||||
"html" | |||||
gotemplate "html/template" | |||||
"net/url" | |||||
"strings" | |||||
) | ) | ||||
const ( | const ( | ||||
@@ -35,7 +34,52 @@ func RefBlame(ctx *context.Context) { | |||||
ctx.NotFound("Blame FileName", nil) | ctx.NotFound("Blame FileName", nil) | ||||
return | return | ||||
} | } | ||||
//get repo contributors info | |||||
contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath(), ctx.Repo.BranchName) | |||||
if err == nil && contributors != nil { | |||||
var contributorInfos []*ContributorInfo | |||||
contributorInfoHash := make(map[string]*ContributorInfo) | |||||
count := 0 | |||||
for _, c := range contributors { | |||||
if count >= 25 { | |||||
continue | |||||
} | |||||
if strings.Compare(c.Email, "") == 0 { | |||||
continue | |||||
} | |||||
// get user info from committer email | |||||
user, err := models.GetUserByActivateEmail(c.Email) | |||||
if err == nil { | |||||
// committer is system user, get info through user's primary email | |||||
if existedContributorInfo, ok := contributorInfoHash[user.Email]; ok { | |||||
// existed: same primary email, different committer name | |||||
existedContributorInfo.CommitCnt += c.CommitCnt | |||||
} else { | |||||
// new committer info | |||||
var newContributor = &ContributorInfo{ | |||||
user, user.RelAvatarLink(), user.Name, user.Email, c.CommitCnt, | |||||
} | |||||
count++ | |||||
contributorInfos = append(contributorInfos, newContributor) | |||||
contributorInfoHash[user.Email] = newContributor | |||||
} | |||||
} else { | |||||
// committer is not system user | |||||
if existedContributorInfo, ok := contributorInfoHash[c.Email]; ok { | |||||
// existed: same primary email, different committer name | |||||
existedContributorInfo.CommitCnt += c.CommitCnt | |||||
} else { | |||||
var newContributor = &ContributorInfo{ | |||||
user, "", "", c.Email, c.CommitCnt, | |||||
} | |||||
count++ | |||||
contributorInfos = append(contributorInfos, newContributor) | |||||
contributorInfoHash[c.Email] = newContributor | |||||
} | |||||
} | |||||
} | |||||
ctx.Data["ContributorInfo"] = contributorInfos | |||||
} | |||||
userName := ctx.Repo.Owner.Name | userName := ctx.Repo.Owner.Name | ||||
repoName := ctx.Repo.Repository.Name | repoName := ctx.Repo.Repository.Name | ||||
commitID := ctx.Repo.CommitID | commitID := ctx.Repo.CommitID | ||||
@@ -14,18 +14,17 @@ import ( | |||||
"strings" | "strings" | ||||
"time" | "time" | ||||
"code.gitea.io/gitea/modules/modelarts" | |||||
"code.gitea.io/gitea/modules/git" | |||||
"code.gitea.io/gitea/modules/storage" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/auth" | "code.gitea.io/gitea/modules/auth" | ||||
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/cloudbrain" | "code.gitea.io/gitea/modules/cloudbrain" | ||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/git" | |||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/modelarts" | |||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/storage" | |||||
"code.gitea.io/gitea/modules/util" | |||||
) | ) | ||||
const ( | const ( | ||||
@@ -206,7 +205,7 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||||
} | } | ||||
repo := ctx.Repo.Repository | repo := ctx.Repo.Repository | ||||
downloadCode(repo, codePath) | downloadCode(repo, codePath) | ||||
uploadCodeToMinio(codePath+"/", jobName, "/code/") | |||||
uploadCodeToMinio(codePath+"/", jobName, cloudbrain.CodeMountPath+"/") | |||||
modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath + "/" | modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath + "/" | ||||
mkModelPath(modelPath) | mkModelPath(modelPath) | ||||
@@ -220,7 +219,7 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||||
gpuType = gpuInfo.Value | gpuType = gpuInfo.Value | ||||
} | } | ||||
} | } | ||||
downloadRateCode(repo, jobName, setting.BenchmarkOwner, setting.BrainScoreName, benchmarkPath, form.BenchmarkCategory, gpuType) | |||||
downloadRateCode(repo, jobName, setting.BenchmarkOwner, setting.BenchmarkName, benchmarkPath, form.BenchmarkCategory, gpuType) | |||||
uploadCodeToMinio(benchmarkPath+"/", jobName, cloudbrain.BenchMarkMountPath+"/") | uploadCodeToMinio(benchmarkPath+"/", jobName, cloudbrain.BenchMarkMountPath+"/") | ||||
} | } | ||||
@@ -236,15 +235,79 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { | |||||
uploadCodeToMinio(brainScorePath+"/", jobName, cloudbrain.BrainScoreMountPath+"/") | uploadCodeToMinio(brainScorePath+"/", jobName, cloudbrain.BrainScoreMountPath+"/") | ||||
} | } | ||||
err = cloudbrain.GenerateTask(ctx, jobName, image, command, uuid, codePath, getMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | |||||
getMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), getMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | |||||
getMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, resourceSpecId) | |||||
err = cloudbrain.GenerateTask(ctx, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), | |||||
storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), | |||||
storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), | |||||
storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, resourceSpecId) | |||||
if err != nil { | if err != nil { | ||||
cloudBrainNewDataPrepare(ctx) | cloudBrainNewDataPrepare(ctx) | ||||
ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) | ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) | ||||
return | return | ||||
} | } | ||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||||
} | |||||
func CloudBrainRestart(ctx *context.Context) { | |||||
var jobID = ctx.Params(":jobid") | |||||
var resultCode = "0" | |||||
var errorMsg = "" | |||||
var status = string(models.JobWaiting) | |||||
task := ctx.Cloudbrain | |||||
for { | |||||
if task.Status != string(models.JobStopped) && task.Status != string(models.JobSucceeded) && task.Status != string(models.JobFailed) { | |||||
log.Error("the job(%s) is not stopped", task.JobName, ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "the job is not stopped" | |||||
break | |||||
} | |||||
if task.Image == "" || task.GpuQueue == "" || task.Type != models.TypeCloudBrainOne { | |||||
log.Error("the job(%s) version is too old", task.JobName, ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "the job's version is too old and can not be restarted" | |||||
break | |||||
} | |||||
if !ctx.IsSigned || (ctx.User.ID != task.UserID && !ctx.IsUserSiteAdmin()) { | |||||
log.Error("the user has no right ro restart the job", task.JobName, ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "you have no right to restart the job" | |||||
break | |||||
} | |||||
count, err := models.GetCloudbrainCountByUserID(ctx.User.ID) | |||||
if err != nil { | |||||
log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "system error" | |||||
break | |||||
} else { | |||||
if count >= 1 { | |||||
log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "you have already a running or waiting task, can not create more" | |||||
break | |||||
} | |||||
} | |||||
err = cloudbrain.RestartTask(ctx, task, &jobID) | |||||
if err != nil { | |||||
log.Error("RestartTask failed:%v", err.Error(), ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "system error" | |||||
break | |||||
} | |||||
break | |||||
} | |||||
ctx.JSON(200, map[string]string{ | |||||
"result_code": resultCode, | |||||
"error_msg": errorMsg, | |||||
"status": status, | |||||
"job_id": jobID, | |||||
}) | |||||
} | } | ||||
func CloudBrainShow(ctx *context.Context) { | func CloudBrainShow(ctx *context.Context) { | ||||
@@ -296,46 +359,19 @@ func CloudBrainShow(ctx *context.Context) { | |||||
} | } | ||||
func CloudBrainDebug(ctx *context.Context) { | func CloudBrainDebug(ctx *context.Context) { | ||||
var jobID = ctx.Params(":jobid") | |||||
if !ctx.IsSigned { | |||||
log.Error("the user has not signed in") | |||||
ctx.Error(http.StatusForbidden, "", "the user has not signed in") | |||||
return | |||||
} | |||||
task, err := models.GetCloudbrainByJobID(jobID) | |||||
if err != nil { | |||||
ctx.ServerError("GetCloudbrainByJobID failed", err) | |||||
return | |||||
} | |||||
debugUrl := setting.DebugServerHost + "jpylab_" + task.JobID + "_" + task.SubTaskName | |||||
debugUrl := setting.DebugServerHost + "jpylab_" + ctx.Cloudbrain.JobID + "_" + ctx.Cloudbrain.SubTaskName | |||||
ctx.Redirect(debugUrl) | ctx.Redirect(debugUrl) | ||||
} | } | ||||
func CloudBrainCommitImage(ctx *context.Context, form auth.CommitImageCloudBrainForm) { | func CloudBrainCommitImage(ctx *context.Context, form auth.CommitImageCloudBrainForm) { | ||||
var jobID = ctx.Params(":jobid") | |||||
if !ctx.IsSigned { | |||||
log.Error("the user has not signed in") | |||||
ctx.Error(http.StatusForbidden, "", "the user has not signed in") | |||||
return | |||||
} | |||||
task, err := models.GetCloudbrainByJobID(jobID) | |||||
if err != nil { | |||||
ctx.JSON(200, map[string]string{ | |||||
"result_code": "-1", | |||||
"error_msg": "GetCloudbrainByJobID failed", | |||||
}) | |||||
return | |||||
} | |||||
err = cloudbrain.CommitImage(jobID, models.CommitImageParams{ | |||||
Ip: task.ContainerIp, | |||||
TaskContainerId: task.ContainerID, | |||||
err := cloudbrain.CommitImage(ctx.Cloudbrain.JobID, models.CommitImageParams{ | |||||
Ip: ctx.Cloudbrain.ContainerIp, | |||||
TaskContainerId: ctx.Cloudbrain.ContainerID, | |||||
ImageDescription: form.Description, | ImageDescription: form.Description, | ||||
ImageTag: form.Tag, | ImageTag: form.Tag, | ||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
log.Error("CommitImage(%s) failed:%v", task.JobName, err.Error(), ctx.Data["msgID"]) | |||||
log.Error("CommitImage(%s) failed:%v", ctx.Cloudbrain.JobName, err.Error(), ctx.Data["msgID"]) | |||||
ctx.JSON(200, map[string]string{ | ctx.JSON(200, map[string]string{ | ||||
"result_code": "-1", | "result_code": "-1", | ||||
"error_msg": "CommitImage failed", | "error_msg": "CommitImage failed", | ||||
@@ -351,32 +387,46 @@ func CloudBrainCommitImage(ctx *context.Context, form auth.CommitImageCloudBrain | |||||
func CloudBrainStop(ctx *context.Context) { | func CloudBrainStop(ctx *context.Context) { | ||||
var jobID = ctx.Params(":jobid") | var jobID = ctx.Params(":jobid") | ||||
task, err := models.GetCloudbrainByJobID(jobID) | |||||
if err != nil { | |||||
ctx.ServerError("GetCloudbrainByJobID failed", err) | |||||
return | |||||
} | |||||
var resultCode = "0" | |||||
var errorMsg = "" | |||||
var status = "" | |||||
if task.Status == string(models.JobStopped) || task.Status == string(models.JobFailed) { | |||||
log.Error("the job(%s) has been stopped", task.JobName, ctx.Data["msgID"]) | |||||
ctx.ServerError("the job has been stopped", errors.New("the job has been stopped")) | |||||
return | |||||
} | |||||
task := ctx.Cloudbrain | |||||
for { | |||||
if task.Status == string(models.JobStopped) || task.Status == string(models.JobFailed) { | |||||
log.Error("the job(%s) has been stopped", task.JobName, ctx.Data["msgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "system error" | |||||
break | |||||
} | |||||
err = cloudbrain.StopJob(jobID) | |||||
if err != nil { | |||||
log.Error("StopJob(%s) failed:%v", task.JobName, err.Error(), ctx.Data["msgID"]) | |||||
ctx.ServerError("StopJob failed", err) | |||||
return | |||||
} | |||||
err := cloudbrain.StopJob(jobID) | |||||
if err != nil { | |||||
log.Error("StopJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "system error" | |||||
break | |||||
} | |||||
task.Status = string(models.JobStopped) | |||||
err = models.UpdateJob(task) | |||||
if err != nil { | |||||
ctx.ServerError("UpdateJob failed", err) | |||||
return | |||||
task.Status = string(models.JobStopped) | |||||
err = models.UpdateJob(task) | |||||
if err != nil { | |||||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "system error" | |||||
break | |||||
} | |||||
status = task.Status | |||||
break | |||||
} | } | ||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||||
ctx.JSON(200, map[string]string{ | |||||
"result_code": resultCode, | |||||
"error_msg": errorMsg, | |||||
"status": status, | |||||
"job_id": jobID, | |||||
}) | |||||
} | } | ||||
func StopJobsByUserID(userID int64) { | func StopJobsByUserID(userID int64) { | ||||
@@ -423,7 +473,7 @@ func StopJobs(cloudBrains []*models.Cloudbrain) { | |||||
Action: models.ActionStop, | Action: models.ActionStop, | ||||
} | } | ||||
err := retry(3, time.Second*30, func() error { | err := retry(3, time.Second*30, func() error { | ||||
_, err := modelarts.StopJob(taskInfo.JobID, param) | |||||
_, err := modelarts.ManageNotebook(taskInfo.JobID, param) | |||||
return err | return err | ||||
}) | }) | ||||
logErrorAndUpdateJobStatus(err, taskInfo) | logErrorAndUpdateJobStatus(err, taskInfo) | ||||
@@ -460,12 +510,7 @@ func logErrorAndUpdateJobStatus(err error, taskInfo *models.Cloudbrain) { | |||||
} | } | ||||
func CloudBrainDel(ctx *context.Context) { | func CloudBrainDel(ctx *context.Context) { | ||||
var jobID = ctx.Params(":jobid") | |||||
task, err := models.GetCloudbrainByJobID(jobID) | |||||
if err != nil { | |||||
ctx.ServerError("GetCloudbrainByJobID failed", err) | |||||
return | |||||
} | |||||
task := ctx.Cloudbrain | |||||
if task.Status != string(models.JobStopped) && task.Status != string(models.JobFailed) { | if task.Status != string(models.JobStopped) && task.Status != string(models.JobFailed) { | ||||
log.Error("the job(%s) has not been stopped", task.JobName, ctx.Data["msgID"]) | log.Error("the job(%s) has not been stopped", task.JobName, ctx.Data["msgID"]) | ||||
@@ -473,12 +518,14 @@ func CloudBrainDel(ctx *context.Context) { | |||||
return | return | ||||
} | } | ||||
err = models.DeleteJob(task) | |||||
err := models.DeleteJob(task) | |||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("DeleteJob failed", err) | ctx.ServerError("DeleteJob failed", err) | ||||
return | return | ||||
} | } | ||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||||
deleteJobStorage(task.JobName, models.TypeCloudBrainOne) | |||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||||
} | } | ||||
func CloudBrainShowModels(ctx *context.Context) { | func CloudBrainShowModels(ctx *context.Context) { | ||||
@@ -560,7 +607,7 @@ func getImages(ctx *context.Context, imageType string) { | |||||
func GetModelDirs(jobName string, parentDir string) (string, error) { | func GetModelDirs(jobName string, parentDir string) (string, error) { | ||||
var req string | var req string | ||||
modelActualPath := getMinioPath(jobName, cloudbrain.ModelMountPath+"/") | |||||
modelActualPath := storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/") | |||||
if parentDir == "" { | if parentDir == "" { | ||||
req = "baseDir=" + modelActualPath | req = "baseDir=" + modelActualPath | ||||
} else { | } else { | ||||
@@ -570,10 +617,6 @@ func GetModelDirs(jobName string, parentDir string) (string, error) { | |||||
return getDirs(req) | return getDirs(req) | ||||
} | } | ||||
func getMinioPath(jobName, suffixPath string) string { | |||||
return setting.Attachment.Minio.RealPath + setting.Attachment.Minio.Bucket + "/" + setting.CBCodePathPrefix + jobName + suffixPath | |||||
} | |||||
func CloudBrainDownloadModel(ctx *context.Context) { | func CloudBrainDownloadModel(ctx *context.Context) { | ||||
parentDir := ctx.Query("parentDir") | parentDir := ctx.Query("parentDir") | ||||
fileName := ctx.Query("fileName") | fileName := ctx.Query("fileName") | ||||
@@ -756,6 +799,35 @@ func mkModelPath(modelPath string) error { | |||||
return nil | return nil | ||||
} | } | ||||
func deleteJobStorage(jobName string, cloudbrainType int) error { | |||||
//delete local | |||||
localJobPath := setting.JobPath + jobName | |||||
err := os.RemoveAll(localJobPath) | |||||
if err != nil { | |||||
log.Error("RemoveAll(%s) failed:%v", localJobPath, err) | |||||
} | |||||
//delete oss | |||||
if cloudbrainType == models.TypeCloudBrainOne { | |||||
dirPath := setting.CBCodePathPrefix + jobName + "/" | |||||
err = storage.Attachments.DeleteDir(dirPath) | |||||
if err != nil { | |||||
log.Error("DeleteDir(%s) failed:%v", localJobPath, err) | |||||
} | |||||
} else if cloudbrainType == models.TypeCloudBrainTwo { | |||||
//dirPath := setting.CodePathPrefix + jobName + "/" | |||||
//err = storage.ObsRemoveObject(setting.Bucket, dirPath) | |||||
//if err != nil { | |||||
// log.Error("ObsRemoveObject(%s) failed:%v", localJobPath, err) | |||||
//} | |||||
log.Info("no need to delete") | |||||
} else { | |||||
log.Error("cloudbrainType(%d) error", cloudbrainType) | |||||
} | |||||
return nil | |||||
} | |||||
func SyncCloudbrainStatus() { | func SyncCloudbrainStatus() { | ||||
cloudBrains, err := models.GetCloudBrainUnStoppedJob() | cloudBrains, err := models.GetCloudBrainUnStoppedJob() | ||||
if err != nil { | if err != nil { | ||||
@@ -827,6 +899,13 @@ func SyncCloudbrainStatus() { | |||||
task.Duration = result.Duration | task.Duration = result.Duration | ||||
task.TrainJobDuration = result.TrainJobDuration | task.TrainJobDuration = result.TrainJobDuration | ||||
if result.Duration != 0 { | |||||
task.TrainJobDuration = util.AddZero(result.Duration/3600000) + ":" + util.AddZero(result.Duration%3600000/60000) + ":" + util.AddZero(result.Duration%60000/1000) | |||||
} else { | |||||
task.TrainJobDuration = "00:00:00" | |||||
} | |||||
err = models.UpdateJob(task) | err = models.UpdateJob(task) | ||||
if err != nil { | if err != nil { | ||||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | log.Error("UpdateJob(%s) failed:%v", task.JobName, err) | ||||
@@ -13,6 +13,7 @@ import ( | |||||
"net/http" | "net/http" | ||||
"strconv" | "strconv" | ||||
"strings" | "strings" | ||||
"time" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/auth" | "code.gitea.io/gitea/modules/auth" | ||||
@@ -336,6 +337,7 @@ func issues(ctx *context.Context, milestoneID int64, isPullOption util.OptionalB | |||||
// Issues render issues page | // Issues render issues page | ||||
func Issues(ctx *context.Context) { | func Issues(ctx *context.Context) { | ||||
startTime := time.Now() | |||||
isPullList := ctx.Params(":type") == "pulls" | isPullList := ctx.Params(":type") == "pulls" | ||||
if isPullList { | if isPullList { | ||||
MustAllowPulls(ctx) | MustAllowPulls(ctx) | ||||
@@ -366,6 +368,9 @@ func Issues(ctx *context.Context) { | |||||
ctx.Data["CanWriteIssuesOrPulls"] = ctx.Repo.CanWriteIssuesOrPulls(isPullList) | ctx.Data["CanWriteIssuesOrPulls"] = ctx.Repo.CanWriteIssuesOrPulls(isPullList) | ||||
duration := time.Since(startTime) | |||||
log.Info("Issues cost: %v seconds", duration.Seconds()) | |||||
ctx.HTML(200, tplIssues) | ctx.HTML(200, tplIssues) | ||||
} | } | ||||
@@ -11,11 +11,10 @@ import ( | |||||
"strings" | "strings" | ||||
"time" | "time" | ||||
"code.gitea.io/gitea/modules/cloudbrain" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/auth" | "code.gitea.io/gitea/modules/auth" | ||||
"code.gitea.io/gitea/modules/base" | "code.gitea.io/gitea/modules/base" | ||||
"code.gitea.io/gitea/modules/cloudbrain" | |||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/git" | "code.gitea.io/gitea/modules/git" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
@@ -42,6 +41,7 @@ const ( | |||||
func DebugJobIndex(ctx *context.Context) { | func DebugJobIndex(ctx *context.Context) { | ||||
debugListType := ctx.Query("debugListType") | debugListType := ctx.Query("debugListType") | ||||
ctx.Data["ListType"] = debugListType | |||||
MustEnableCloudbrain(ctx) | MustEnableCloudbrain(ctx) | ||||
repo := ctx.Repo.Repository | repo := ctx.Repo.Repository | ||||
page := ctx.QueryInt("page") | page := ctx.QueryInt("page") | ||||
@@ -49,12 +49,9 @@ func DebugJobIndex(ctx *context.Context) { | |||||
page = 1 | page = 1 | ||||
} | } | ||||
debugType := modelarts.DebugType | debugType := modelarts.DebugType | ||||
jobType := string(models.JobTypeDebug) | |||||
if debugListType == modelarts.GPUResource { | |||||
if debugListType == models.GPUResource { | |||||
debugType = models.TypeCloudBrainOne | debugType = models.TypeCloudBrainOne | ||||
jobType = "" | |||||
} | |||||
if debugListType == modelarts.NPUResource { | |||||
} else if debugListType == models.NPUResource { | |||||
debugType = models.TypeCloudBrainTwo | debugType = models.TypeCloudBrainTwo | ||||
} | } | ||||
@@ -63,9 +60,10 @@ func DebugJobIndex(ctx *context.Context) { | |||||
Page: page, | Page: page, | ||||
PageSize: setting.UI.IssuePagingNum, | PageSize: setting.UI.IssuePagingNum, | ||||
}, | }, | ||||
RepoID: repo.ID, | |||||
Type: debugType, | |||||
JobType: jobType, | |||||
RepoID: repo.ID, | |||||
Type: debugType, | |||||
JobTypeNot: true, | |||||
JobType: string(models.JobTypeTrain), | |||||
}) | }) | ||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("Get debugjob faild:", err) | ctx.ServerError("Get debugjob faild:", err) | ||||
@@ -73,21 +71,13 @@ func DebugJobIndex(ctx *context.Context) { | |||||
} | } | ||||
for i, task := range ciTasks { | for i, task := range ciTasks { | ||||
if task.Cloudbrain.Type == models.TypeCloudBrainOne { | |||||
ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) | |||||
ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||||
ciTasks[i].Cloudbrain.ComputeResource = modelarts.GPUResource | |||||
} | |||||
if task.Cloudbrain.Type == models.TypeCloudBrainTwo { | |||||
ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) | |||||
ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||||
ciTasks[i].Cloudbrain.ComputeResource = modelarts.NPUResource | |||||
} | |||||
ciTasks[i].CanDebug = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) | |||||
ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | |||||
ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource | |||||
} | } | ||||
pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | ||||
pager.SetDefaultParams(ctx) | |||||
pager.AddParam(ctx, "debugListType", "ListType") | |||||
ctx.Data["Page"] = pager | ctx.Data["Page"] = pager | ||||
ctx.Data["PageIsCloudBrain"] = true | ctx.Data["PageIsCloudBrain"] = true | ||||
ctx.Data["Tasks"] = ciTasks | ctx.Data["Tasks"] = ciTasks | ||||
@@ -150,13 +140,27 @@ func NotebookCreate(ctx *context.Context, form auth.CreateModelArtsNotebookForm) | |||||
return | return | ||||
} | } | ||||
} | } | ||||
_, err = models.GetCloudbrainByName(jobName) | |||||
if err == nil { | |||||
log.Error("the job name did already exist", ctx.Data["MsgID"]) | |||||
cloudBrainNewDataPrepare(ctx) | |||||
ctx.RenderWithErr("the job name did already exist", tplModelArtsNotebookNew, &form) | |||||
return | |||||
} else { | |||||
if !models.IsErrJobNotExist(err) { | |||||
log.Error("system error, %v", err, ctx.Data["MsgID"]) | |||||
cloudBrainNewDataPrepare(ctx) | |||||
ctx.RenderWithErr("system error", tplModelArtsNotebookNew, &form) | |||||
return | |||||
} | |||||
} | |||||
err = modelarts.GenerateTask(ctx, jobName, uuid, description, flavor) | err = modelarts.GenerateTask(ctx, jobName, uuid, description, flavor) | ||||
if err != nil { | if err != nil { | ||||
ctx.RenderWithErr(err.Error(), tplModelArtsNotebookNew, &form) | ctx.RenderWithErr(err.Error(), tplModelArtsNotebookNew, &form) | ||||
return | return | ||||
} | } | ||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||||
} | } | ||||
func NotebookShow(ctx *context.Context) { | func NotebookShow(ctx *context.Context) { | ||||
@@ -202,11 +206,6 @@ func NotebookShow(ctx *context.Context) { | |||||
func NotebookDebug(ctx *context.Context) { | func NotebookDebug(ctx *context.Context) { | ||||
var jobID = ctx.Params(":jobid") | var jobID = ctx.Params(":jobid") | ||||
_, err := models.GetCloudbrainByJobID(jobID) | |||||
if err != nil { | |||||
ctx.ServerError("GetCloudbrainByJobID failed", err) | |||||
return | |||||
} | |||||
result, err := modelarts.GetJob(jobID) | result, err := modelarts.GetJob(jobID) | ||||
if err != nil { | if err != nil { | ||||
@@ -232,55 +231,118 @@ func NotebookDebug(ctx *context.Context) { | |||||
ctx.Redirect(debugUrl) | ctx.Redirect(debugUrl) | ||||
} | } | ||||
func NotebookStop(ctx *context.Context) { | |||||
func NotebookManage(ctx *context.Context) { | |||||
var jobID = ctx.Params(":jobid") | var jobID = ctx.Params(":jobid") | ||||
log.Info(jobID) | |||||
task, err := models.GetCloudbrainByJobID(jobID) | |||||
if err != nil { | |||||
ctx.ServerError("GetCloudbrainByJobID failed", err) | |||||
return | |||||
} | |||||
var action = ctx.Params(":action") | |||||
var resultCode = "0" | |||||
var errorMsg = "" | |||||
var status = "" | |||||
if task.Status != string(models.JobRunning) { | |||||
log.Error("the job(%s) is not running", task.JobName) | |||||
ctx.ServerError("the job is not running", errors.New("the job is not running")) | |||||
return | |||||
} | |||||
for { | |||||
task, err := models.GetCloudbrainByJobID(jobID) | |||||
if err != nil { | |||||
log.Error("GetCloudbrainByJobID failed:%v", err, ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "system error" | |||||
break | |||||
} | |||||
param := models.NotebookAction{ | |||||
Action: models.ActionStop, | |||||
} | |||||
res, err := modelarts.StopJob(jobID, param) | |||||
if err != nil { | |||||
log.Error("StopJob(%s) failed:%v", task.JobName, err.Error()) | |||||
ctx.ServerError("StopJob failed", err) | |||||
return | |||||
} | |||||
if action == models.ActionStop { | |||||
if task.Status != string(models.ModelArtsRunning) { | |||||
log.Error("the job(%s) is not running", task.JobName, ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "the job is not running" | |||||
break | |||||
} | |||||
task.Status = res.CurrentStatus | |||||
err = models.UpdateJob(task) | |||||
if err != nil { | |||||
ctx.ServerError("UpdateJob failed", err) | |||||
return | |||||
if !ctx.IsSigned || (ctx.User.ID != task.UserID && !ctx.IsUserSiteAdmin() && !ctx.IsUserRepoOwner()) { | |||||
log.Error("the user has no right ro stop the job", task.JobName, ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "you have no right to stop the job" | |||||
break | |||||
} | |||||
} else if action == models.ActionRestart { | |||||
if task.Status != string(models.ModelArtsStopped) && task.Status != string(models.ModelArtsStartFailed) && task.Status != string(models.ModelArtsCreateFailed) { | |||||
log.Error("the job(%s) is not stopped", task.JobName, ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "the job is not stopped" | |||||
break | |||||
} | |||||
if !ctx.IsSigned || (ctx.User.ID != task.UserID && !ctx.IsUserSiteAdmin()) { | |||||
log.Error("the user has no right ro restart the job", task.JobName, ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "you have no right to restart the job" | |||||
break | |||||
} | |||||
count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) | |||||
if err != nil { | |||||
log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "system error" | |||||
break | |||||
} else { | |||||
if count >= 1 { | |||||
log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "you have already a running or waiting task, can not create more" | |||||
break | |||||
} | |||||
} | |||||
action = models.ActionStart | |||||
} else { | |||||
log.Error("the action(%s) is illegal", action, ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "非法操作" | |||||
break | |||||
} | |||||
param := models.NotebookAction{ | |||||
Action: action, | |||||
} | |||||
res, err := modelarts.ManageNotebook(jobID, param) | |||||
if err != nil { | |||||
log.Error("ManageNotebook(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "启动失败" | |||||
break | |||||
} | |||||
task.Status = res.CurrentStatus | |||||
err = models.UpdateJob(task) | |||||
if err != nil { | |||||
log.Error("UpdateJob(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) | |||||
resultCode = "-1" | |||||
errorMsg = "system error" | |||||
break | |||||
} | |||||
status = task.Status | |||||
break | |||||
} | } | ||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||||
ctx.JSON(200, map[string]string{ | |||||
"result_code": resultCode, | |||||
"error_msg": errorMsg, | |||||
"status": status, | |||||
"job_id": jobID, | |||||
}) | |||||
} | } | ||||
func NotebookDel(ctx *context.Context) { | func NotebookDel(ctx *context.Context) { | ||||
var jobID = ctx.Params(":jobid") | var jobID = ctx.Params(":jobid") | ||||
task, err := models.GetCloudbrainByJobID(jobID) | |||||
if err != nil { | |||||
ctx.ServerError("GetCloudbrainByJobID failed", err) | |||||
return | |||||
} | |||||
task := ctx.Cloudbrain | |||||
if task.Status != string(models.ModelArtsCreateFailed) && task.Status != string(models.ModelArtsStartFailed) && task.Status != string(models.ModelArtsStopped){ | |||||
if task.Status != string(models.ModelArtsCreateFailed) && task.Status != string(models.ModelArtsStartFailed) && task.Status != string(models.ModelArtsStopped) { | |||||
log.Error("the job(%s) has not been stopped", task.JobName) | log.Error("the job(%s) has not been stopped", task.JobName) | ||||
ctx.ServerError("the job has not been stopped", errors.New("the job has not been stopped")) | ctx.ServerError("the job has not been stopped", errors.New("the job has not been stopped")) | ||||
return | return | ||||
} | } | ||||
_, err = modelarts.DelNotebook(jobID) | |||||
_, err := modelarts.DelNotebook(jobID) | |||||
if err != nil { | if err != nil { | ||||
log.Error("DelJob(%s) failed:%v", task.JobName, err.Error()) | log.Error("DelJob(%s) failed:%v", task.JobName, err.Error()) | ||||
ctx.ServerError("DelJob failed", err) | ctx.ServerError("DelJob failed", err) | ||||
@@ -293,7 +355,7 @@ func NotebookDel(ctx *context.Context) { | |||||
return | return | ||||
} | } | ||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") | |||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") | |||||
} | } | ||||
func TrainJobIndex(ctx *context.Context) { | func TrainJobIndex(ctx *context.Context) { | ||||
@@ -312,6 +374,7 @@ func TrainJobIndex(ctx *context.Context) { | |||||
}, | }, | ||||
RepoID: repo.ID, | RepoID: repo.ID, | ||||
Type: models.TypeCloudBrainTwo, | Type: models.TypeCloudBrainTwo, | ||||
JobTypeNot: false, | |||||
JobType: string(models.JobTypeTrain), | JobType: string(models.JobTypeTrain), | ||||
IsLatestVersion: modelarts.IsLatestVersion, | IsLatestVersion: modelarts.IsLatestVersion, | ||||
}) | }) | ||||
@@ -323,6 +386,7 @@ func TrainJobIndex(ctx *context.Context) { | |||||
for i, task := range tasks { | for i, task := range tasks { | ||||
tasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | tasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) | ||||
tasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) | tasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) | ||||
tasks[i].ComputeResource = models.NPUResource | |||||
} | } | ||||
pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) | ||||
@@ -364,7 +428,7 @@ func trainJobNewDataPrepare(ctx *context.Context) error { | |||||
var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | ||||
ctx.Data["job_name"] = jobName | ctx.Data["job_name"] = jobName | ||||
attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||||
attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("GetAllUserAttachments failed:", err) | ctx.ServerError("GetAllUserAttachments failed:", err) | ||||
return err | return err | ||||
@@ -433,7 +497,7 @@ func trainJobErrorNewDataPrepare(ctx *context.Context, form auth.CreateModelArts | |||||
var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | ||||
ctx.Data["job_name"] = jobName | ctx.Data["job_name"] = jobName | ||||
attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||||
attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("GetAllUserAttachments failed:", err) | ctx.ServerError("GetAllUserAttachments failed:", err) | ||||
return err | return err | ||||
@@ -521,7 +585,7 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { | |||||
var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | ||||
ctx.Data["job_name"] = task.JobName | ctx.Data["job_name"] = task.JobName | ||||
attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||||
attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("GetAllUserAttachments failed:", err) | ctx.ServerError("GetAllUserAttachments failed:", err) | ||||
return err | return err | ||||
@@ -610,7 +674,7 @@ func versionErrorDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrai | |||||
var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] | ||||
ctx.Data["job_name"] = task.JobName | ctx.Data["job_name"] = task.JobName | ||||
attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) | |||||
attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) | |||||
if err != nil { | if err != nil { | ||||
ctx.ServerError("GetAllUserAttachments failed:", err) | ctx.ServerError("GetAllUserAttachments failed:", err) | ||||
return err | return err | ||||
@@ -1192,6 +1256,10 @@ func paramCheckCreateTrainJob(form auth.CreateModelArtsTrainJobForm) error { | |||||
log.Error("the WorkServerNumber(%d) must be in (1,25)", form.WorkServerNumber) | log.Error("the WorkServerNumber(%d) must be in (1,25)", form.WorkServerNumber) | ||||
return errors.New("计算节点数必须在1-25之间") | return errors.New("计算节点数必须在1-25之间") | ||||
} | } | ||||
if form.BranchName == "" { | |||||
log.Error("the branch must not be null!", form.BranchName) | |||||
return errors.New("代码分支不能为空!") | |||||
} | |||||
return nil | return nil | ||||
} | } | ||||
@@ -1352,19 +1420,19 @@ func TrainJobDel(ctx *context.Context) { | |||||
} | } | ||||
} | } | ||||
//删除存储 | |||||
if len(VersionListTasks) > 0 { | |||||
DeleteJobStorage(VersionListTasks[0].JobName) | |||||
} | |||||
ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") | ||||
} | } | ||||
func TrainJobStop(ctx *context.Context) { | func TrainJobStop(ctx *context.Context) { | ||||
var jobID = ctx.Params(":jobid") | var jobID = ctx.Params(":jobid") | ||||
task, err := models.GetCloudbrainByJobID(jobID) | |||||
if err != nil { | |||||
log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err.Error()) | |||||
ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobIndex, nil) | |||||
return | |||||
} | |||||
task := ctx.Cloudbrain | |||||
_, err = modelarts.StopTrainJob(jobID, strconv.FormatInt(task.VersionID, 10)) | |||||
_, err := modelarts.StopTrainJob(jobID, strconv.FormatInt(task.VersionID, 10)) | |||||
if err != nil { | if err != nil { | ||||
log.Error("StopTrainJob(%s) failed:%v", task.JobName, err.Error()) | log.Error("StopTrainJob(%s) failed:%v", task.JobName, err.Error()) | ||||
ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobIndex, nil) | ctx.RenderWithErr(err.Error(), tplModelArtsTrainJobIndex, nil) | ||||
@@ -1477,3 +1545,21 @@ func ModelDownload(ctx *context.Context) { | |||||
} | } | ||||
http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) | http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) | ||||
} | } | ||||
func DeleteJobStorage(jobName string) error { | |||||
//delete local | |||||
localJobPath := setting.JobPath + jobName | |||||
err := os.RemoveAll(localJobPath) | |||||
if err != nil { | |||||
log.Error("RemoveAll(%s) failed:%v", localJobPath, err) | |||||
} | |||||
//delete oss | |||||
dirPath := setting.CodePathPrefix + jobName + "/" | |||||
err = storage.ObsRemoveObject(setting.Bucket, dirPath) | |||||
if err != nil { | |||||
log.Error("ObsRemoveObject(%s) failed:%v", localJobPath, err) | |||||
} | |||||
return nil | |||||
} |
@@ -15,6 +15,132 @@ import ( | |||||
"github.com/360EntSecGroup-Skylar/excelize/v2" | "github.com/360EntSecGroup-Skylar/excelize/v2" | ||||
) | ) | ||||
const ( | |||||
PAGE_SIZE = 2000 | |||||
) | |||||
func queryUserDataPage(ctx *context.Context, tableName string, queryObj interface{}) { | |||||
page := ctx.QueryInt("page") | |||||
if page <= 0 { | |||||
page = 1 | |||||
} | |||||
pageSize := ctx.QueryInt("pageSize") | |||||
if pageSize <= 0 { | |||||
pageSize = setting.UI.IssuePagingNum | |||||
} | |||||
userName := ctx.Query("userName") | |||||
IsReturnFile := ctx.QueryBool("IsReturnFile") | |||||
if IsReturnFile { | |||||
//writer exec file. | |||||
xlsx := excelize.NewFile() | |||||
sheetName := ctx.Tr("user.static.sheetname") | |||||
index := xlsx.NewSheet(sheetName) | |||||
xlsx.DeleteSheet("Sheet1") | |||||
dataHeader := map[string]string{ | |||||
"A1": ctx.Tr("user.static.id"), | |||||
"B1": ctx.Tr("user.static.name"), | |||||
"C1": ctx.Tr("user.static.codemergecount"), | |||||
"D1": ctx.Tr("user.static.commitcount"), | |||||
"E1": ctx.Tr("user.static.issuecount"), | |||||
"F1": ctx.Tr("user.static.commentcount"), | |||||
"G1": ctx.Tr("user.static.focusrepocount"), | |||||
"H1": ctx.Tr("user.static.starrepocount"), | |||||
"I1": ctx.Tr("user.static.logincount"), | |||||
"J1": ctx.Tr("user.static.watchedcount"), | |||||
"K1": ctx.Tr("user.static.commitcodesize"), | |||||
"L1": ctx.Tr("user.static.solveissuecount"), | |||||
"M1": ctx.Tr("user.static.encyclopediascount"), | |||||
"N1": ctx.Tr("user.static.createrepocount"), | |||||
"O1": ctx.Tr("user.static.openiindex"), | |||||
"P1": ctx.Tr("user.static.registdate"), | |||||
"Q1": ctx.Tr("user.static.countdate"), | |||||
} | |||||
for k, v := range dataHeader { | |||||
//设置单元格的值 | |||||
xlsx.SetCellValue(sheetName, k, v) | |||||
} | |||||
_, count := models.QueryUserStaticDataByTableName(1, 1, tableName, queryObj, userName) | |||||
var indexTotal int64 | |||||
indexTotal = 0 | |||||
for { | |||||
re, _ := models.QueryUserStaticDataByTableName(int(indexTotal), PAGE_SIZE, tableName, queryObj, "") | |||||
log.Info("return count=" + fmt.Sprint(count)) | |||||
for i, userRecord := range re { | |||||
rows := fmt.Sprint(i + 2) | |||||
xlsx.SetCellValue(sheetName, "A"+rows, userRecord.ID) | |||||
xlsx.SetCellValue(sheetName, "B"+rows, userRecord.Name) | |||||
xlsx.SetCellValue(sheetName, "C"+rows, userRecord.CodeMergeCount) | |||||
xlsx.SetCellValue(sheetName, "D"+rows, userRecord.CommitCount) | |||||
xlsx.SetCellValue(sheetName, "E"+rows, userRecord.IssueCount) | |||||
xlsx.SetCellValue(sheetName, "F"+rows, userRecord.CommentCount) | |||||
xlsx.SetCellValue(sheetName, "G"+rows, userRecord.FocusRepoCount) | |||||
xlsx.SetCellValue(sheetName, "H"+rows, userRecord.StarRepoCount) | |||||
xlsx.SetCellValue(sheetName, "I"+rows, userRecord.LoginCount) | |||||
xlsx.SetCellValue(sheetName, "J"+rows, userRecord.WatchedCount) | |||||
xlsx.SetCellValue(sheetName, "K"+rows, userRecord.CommitCodeSize) | |||||
xlsx.SetCellValue(sheetName, "L"+rows, userRecord.SolveIssueCount) | |||||
xlsx.SetCellValue(sheetName, "M"+rows, userRecord.EncyclopediasCount) | |||||
xlsx.SetCellValue(sheetName, "N"+rows, userRecord.CreateRepoCount) | |||||
xlsx.SetCellValue(sheetName, "O"+rows, fmt.Sprintf("%.2f", userRecord.OpenIIndex)) | |||||
formatTime := userRecord.RegistDate.Format("2006-01-02 15:04:05") | |||||
xlsx.SetCellValue(sheetName, "P"+rows, formatTime[0:len(formatTime)-3]) | |||||
formatTime = userRecord.DataDate | |||||
xlsx.SetCellValue(sheetName, "Q"+rows, formatTime+" 00:01") | |||||
} | |||||
//设置默认打开的表单 | |||||
xlsx.SetActiveSheet(index) | |||||
filename := sheetName + "_" + ctx.Tr("user.static."+tableName) + ".xlsx" | |||||
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename="+url.QueryEscape(filename)) | |||||
ctx.Resp.Header().Set("Content-Type", "application/octet-stream") | |||||
if _, err := xlsx.WriteTo(ctx.Resp); err != nil { | |||||
log.Info("writer exel error." + err.Error()) | |||||
} | |||||
indexTotal += PAGE_SIZE | |||||
if indexTotal >= count { | |||||
break | |||||
} | |||||
} | |||||
} else { | |||||
re, count := models.QueryUserStaticDataByTableName((page-1)*pageSize, pageSize, tableName, queryObj, userName) | |||||
mapInterface := make(map[string]interface{}) | |||||
mapInterface["data"] = re | |||||
mapInterface["count"] = count | |||||
ctx.JSON(http.StatusOK, mapInterface) | |||||
} | |||||
} | |||||
func QueryUserStaticCurrentMonth(ctx *context.Context) { | |||||
queryUserDataPage(ctx, "public.user_business_analysis_current_month", new(models.UserBusinessAnalysisCurrentMonth)) | |||||
} | |||||
func QueryUserStaticCurrentWeek(ctx *context.Context) { | |||||
queryUserDataPage(ctx, "public.user_business_analysis_current_week", new(models.UserBusinessAnalysisCurrentWeek)) | |||||
} | |||||
func QueryUserStaticCurrentYear(ctx *context.Context) { | |||||
queryUserDataPage(ctx, "public.user_business_analysis_current_year", new(models.UserBusinessAnalysisCurrentYear)) | |||||
} | |||||
func QueryUserStaticLast30Day(ctx *context.Context) { | |||||
queryUserDataPage(ctx, "public.user_business_analysis_last30_day", new(models.UserBusinessAnalysisLast30Day)) | |||||
} | |||||
func QueryUserStaticLastMonth(ctx *context.Context) { | |||||
queryUserDataPage(ctx, "public.user_business_analysis_last_month", new(models.UserBusinessAnalysisLastMonth)) | |||||
} | |||||
func QueryUserStaticYesterday(ctx *context.Context) { | |||||
queryUserDataPage(ctx, "public.user_business_analysis_yesterday", new(models.UserBusinessAnalysisYesterday)) | |||||
} | |||||
func QueryUserStaticAll(ctx *context.Context) { | |||||
queryUserDataPage(ctx, "public.user_business_analysis_all", new(models.UserBusinessAnalysisAll)) | |||||
} | |||||
func QueryUserStaticDataPage(ctx *context.Context) { | func QueryUserStaticDataPage(ctx *context.Context) { | ||||
startDate := ctx.Query("startDate") | startDate := ctx.Query("startDate") | ||||
endDate := ctx.Query("endDate") | endDate := ctx.Query("endDate") | ||||
@@ -628,6 +628,10 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Group("/org", func() { | m.Group("/org", func() { | ||||
m.Group("/:org", func() { | m.Group("/:org", func() { | ||||
m.Get("/members", org.Members) | m.Get("/members", org.Members) | ||||
m.Group("/org_tag", func() { | |||||
m.Get("/repo_list", org.GetTagRepos) | |||||
m.Post("/repo_submit", bindIgnErr(auth.SubmitReposOfTagForm{}), org.SubmitTags) | |||||
}) | |||||
}, context.OrgAssignment()) | }, context.OrgAssignment()) | ||||
}) | }) | ||||
m.Group("/org", func() { | m.Group("/org", func() { | ||||
@@ -965,20 +969,21 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Group("/cloudbrain", func() { | m.Group("/cloudbrain", func() { | ||||
m.Group("/:jobid", func() { | m.Group("/:jobid", func() { | ||||
m.Get("", reqRepoCloudBrainReader, repo.CloudBrainShow) | m.Get("", reqRepoCloudBrainReader, repo.CloudBrainShow) | ||||
m.Get("/debug", reqRepoCloudBrainWriter, repo.CloudBrainDebug) | |||||
m.Post("/commit_image", cloudbrain.AdminOrOwnerOrJobCreaterRight, bindIgnErr(auth.CommitImageCloudBrainForm{}), repo.CloudBrainCommitImage) | |||||
m.Get("/debug", cloudbrain.AdminOrJobCreaterRight, repo.CloudBrainDebug) | |||||
m.Post("/commit_image", cloudbrain.AdminOrJobCreaterRight, bindIgnErr(auth.CommitImageCloudBrainForm{}), repo.CloudBrainCommitImage) | |||||
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainStop) | m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainStop) | ||||
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainDel) | m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainDel) | ||||
m.Post("/restart", cloudbrain.AdminOrJobCreaterRight, repo.CloudBrainRestart) | |||||
m.Get("/rate", reqRepoCloudBrainReader, repo.GetRate) | m.Get("/rate", reqRepoCloudBrainReader, repo.GetRate) | ||||
m.Get("/models", reqRepoCloudBrainReader, repo.CloudBrainShowModels) | m.Get("/models", reqRepoCloudBrainReader, repo.CloudBrainShowModels) | ||||
m.Get("/download_model", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainDownloadModel) | |||||
m.Get("/download_model", cloudbrain.AdminOrJobCreaterRight, repo.CloudBrainDownloadModel) | |||||
}) | }) | ||||
m.Get("/create", reqRepoCloudBrainWriter, repo.CloudBrainNew) | m.Get("/create", reqRepoCloudBrainWriter, repo.CloudBrainNew) | ||||
m.Post("/create", reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainCreate) | m.Post("/create", reqRepoCloudBrainWriter, bindIgnErr(auth.CreateCloudBrainForm{}), repo.CloudBrainCreate) | ||||
}, context.RepoRef()) | }, context.RepoRef()) | ||||
m.Group("/modelmanage", func() { | m.Group("/modelmanage", func() { | ||||
m.Post("/create_model", reqRepoModelManageWriter, repo.SaveModel) | m.Post("/create_model", reqRepoModelManageWriter, repo.SaveModel) | ||||
m.Post("/create_new_model", reqRepoModelManageWriter, repo.SaveNewNameModel) | |||||
m.Post("/create_new_model", repo.SaveNewNameModel) | |||||
m.Delete("/delete_model", repo.DeleteModel) | m.Delete("/delete_model", repo.DeleteModel) | ||||
m.Put("/modify_model", repo.ModifyModelInfo) | m.Put("/modify_model", repo.ModifyModelInfo) | ||||
m.Get("/show_model", reqRepoModelManageReader, repo.ShowModelTemplate) | m.Get("/show_model", reqRepoModelManageReader, repo.ShowModelTemplate) | ||||
@@ -990,6 +995,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Get("/query_train_job_version", reqRepoCloudBrainReader, repo.QueryTrainJobVersionList) | m.Get("/query_train_job_version", reqRepoCloudBrainReader, repo.QueryTrainJobVersionList) | ||||
m.Get("/query_model_for_predict", reqRepoCloudBrainReader, repo.QueryModelListForPredict) | m.Get("/query_model_for_predict", reqRepoCloudBrainReader, repo.QueryModelListForPredict) | ||||
m.Get("/query_modelfile_for_predict", reqRepoCloudBrainReader, repo.QueryModelFileForPredict) | m.Get("/query_modelfile_for_predict", reqRepoCloudBrainReader, repo.QueryModelFileForPredict) | ||||
m.Get("/query_onelevel_modelfile", reqRepoCloudBrainReader, repo.QueryOneLevelModelFile) | |||||
m.Group("/:ID", func() { | m.Group("/:ID", func() { | ||||
m.Get("", repo.ShowSingleModel) | m.Get("", repo.ShowSingleModel) | ||||
m.Get("/downloadsingle", repo.DownloadSingleModelFile) | m.Get("/downloadsingle", repo.DownloadSingleModelFile) | ||||
@@ -1005,8 +1011,8 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Group("/notebook", func() { | m.Group("/notebook", func() { | ||||
m.Group("/:jobid", func() { | m.Group("/:jobid", func() { | ||||
m.Get("", reqRepoCloudBrainReader, repo.NotebookShow) | m.Get("", reqRepoCloudBrainReader, repo.NotebookShow) | ||||
m.Get("/debug", reqRepoCloudBrainWriter, repo.NotebookDebug) | |||||
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookStop) | |||||
m.Get("/debug", cloudbrain.AdminOrJobCreaterRight, repo.NotebookDebug) | |||||
m.Post("/:action", reqRepoCloudBrainWriter, repo.NotebookManage) | |||||
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookDel) | m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookDel) | ||||
}) | }) | ||||
m.Get("/create", reqRepoCloudBrainWriter, repo.NotebookNew) | m.Get("/create", reqRepoCloudBrainWriter, repo.NotebookNew) | ||||
@@ -1019,7 +1025,7 @@ func RegisterRoutes(m *macaron.Macaron) { | |||||
m.Get("", reqRepoCloudBrainReader, repo.TrainJobShow) | m.Get("", reqRepoCloudBrainReader, repo.TrainJobShow) | ||||
m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.TrainJobStop) | m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.TrainJobStop) | ||||
m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.TrainJobDel) | m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.TrainJobDel) | ||||
m.Get("/model_download", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.ModelDownload) | |||||
m.Get("/model_download", cloudbrain.AdminOrJobCreaterRight, repo.ModelDownload) | |||||
m.Get("/create_version", cloudbrain.AdminOrJobCreaterRight, repo.TrainJobNewVersion) | m.Get("/create_version", cloudbrain.AdminOrJobCreaterRight, repo.TrainJobNewVersion) | ||||
m.Post("/create_version", cloudbrain.AdminOrJobCreaterRight, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion) | m.Post("/create_version", cloudbrain.AdminOrJobCreaterRight, bindIgnErr(auth.CreateModelArtsTrainJobForm{}), repo.TrainJobCreateVersion) | ||||
}) | }) | ||||
@@ -5,13 +5,12 @@ | |||||
package repository | package repository | ||||
import ( | import ( | ||||
"fmt" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/notification" | "code.gitea.io/gitea/modules/notification" | ||||
repo_module "code.gitea.io/gitea/modules/repository" | repo_module "code.gitea.io/gitea/modules/repository" | ||||
pull_service "code.gitea.io/gitea/services/pull" | pull_service "code.gitea.io/gitea/services/pull" | ||||
"fmt" | |||||
) | ) | ||||
// CreateRepository creates a repository for the user/organization. | // CreateRepository creates a repository for the user/organization. | ||||
@@ -14,6 +14,11 @@ type Client struct { | |||||
Send chan *models.Action | Send chan *models.Action | ||||
} | } | ||||
func (c *Client) Close() { | |||||
close(c.Send) | |||||
c.Conn.Close() | |||||
} | |||||
func (c *Client) WritePump() { | func (c *Client) WritePump() { | ||||
defer func() { | defer func() { | ||||
@@ -1,11 +1,17 @@ | |||||
package socketwrap | package socketwrap | ||||
import ( | import ( | ||||
"os" | |||||
"os/signal" | |||||
"syscall" | |||||
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/log" | |||||
"github.com/elliotchance/orderedmap" | |||||
) | ) | ||||
type ClientsManager struct { | type ClientsManager struct { | ||||
Clients map[*Client]bool | |||||
Clients *orderedmap.OrderedMap | |||||
Register chan *Client | Register chan *Client | ||||
Unregister chan *Client | Unregister chan *Client | ||||
} | } | ||||
@@ -14,33 +20,62 @@ func NewClientsManager() *ClientsManager { | |||||
return &ClientsManager{ | return &ClientsManager{ | ||||
Register: make(chan *Client), | Register: make(chan *Client), | ||||
Unregister: make(chan *Client), | Unregister: make(chan *Client), | ||||
Clients: make(map[*Client]bool), | |||||
Clients: orderedmap.NewOrderedMap(), | |||||
} | } | ||||
} | } | ||||
var LastTenActionsQueue = NewSyncQueue(10) | |||||
const MaxClients = 100 | |||||
var LastActionsQueue = NewSyncQueue(20) | |||||
func (h *ClientsManager) Run() { | func (h *ClientsManager) Run() { | ||||
initActionQueue() | |||||
sig := make(chan os.Signal, 1) | |||||
signal.Notify(sig, os.Interrupt, syscall.SIGTERM) | |||||
var signalsReceived uint | |||||
for { | for { | ||||
select { | select { | ||||
case client := <-h.Register: | case client := <-h.Register: | ||||
h.Clients[client] = true | |||||
h.Clients.Set(client, true) | |||||
if h.Clients.Len() > MaxClients { | |||||
h.Clients.Delete(h.Clients.Front().Key) | |||||
} | |||||
case client := <-h.Unregister: | case client := <-h.Unregister: | ||||
if _, ok := h.Clients[client]; ok { | |||||
delete(h.Clients, client) | |||||
if _, ok := h.Clients.Get(client); ok { | |||||
h.Clients.Delete(client) | |||||
close(client.Send) | close(client.Send) | ||||
} | } | ||||
case message := <-models.ActionChan: | case message := <-models.ActionChan: | ||||
LastTenActionsQueue.Push(message) | |||||
for client := range h.Clients { | |||||
LastActionsQueue.Push(message) | |||||
for _, client := range h.Clients.Keys() { | |||||
select { | select { | ||||
case client.Send <- message: | |||||
case client.(*Client).Send <- message: | |||||
default: | default: | ||||
close(client.Send) | |||||
delete(h.Clients, client) | |||||
close(client.(*Client).Send) | |||||
h.Clients.Delete(client) | |||||
} | |||||
} | |||||
case s := <-sig: | |||||
log.Info("received signal", s) | |||||
signalsReceived++ | |||||
if signalsReceived < 2 { | |||||
for _, client := range h.Clients.Keys() { | |||||
h.Clients.Delete(client) | |||||
client.(*Client).Close() | |||||
} | } | ||||
break | |||||
} | } | ||||
} | |||||
} | |||||
} | |||||
func initActionQueue() { | |||||
actions, err := models.GetLast20PublicFeeds() | |||||
if err == nil { | |||||
for i := len(actions) - 1; i >= 0; i-- { | |||||
LastActionsQueue.Push(actions[i]) | |||||
} | } | ||||
} | } | ||||
} | } |
@@ -26,7 +26,14 @@ | |||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<a href="https://git.openi.org.cn/zeizei/OpenI_Learning" class="ui item" target="_blank">{{.i18n.Tr "custom.Platform_Tutorial"}}</a> | |||||
{{if .EnableSwagger}}<a href="/api/swagger" class="ui item">API</a>{{end}} | {{if .EnableSwagger}}<a href="/api/swagger" class="ui item">API</a>{{end}} | ||||
{{if .IsSigned}} | |||||
<a href="https://git.openi.org.cn/zeizei/OpenI_Learning/issues/new" class="ui item" target="_blank">{{.i18n.Tr "custom.foot.advice_feedback"}}</a> | |||||
{{else}} | |||||
<a href="{{AppSubUrl}}/user/login" class="ui item">{{.i18n.Tr "custom.foot.advice_feedback"}}</a> | |||||
{{end}} | |||||
{{template "custom/extra_links_footer" .}} | {{template "custom/extra_links_footer" .}} | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -26,7 +26,13 @@ | |||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<a href="https://git.openi.org.cn/zeizei/OpenI_Learning" class="ui item" target="_blank">{{.i18n.Tr "custom.Platform_Tutorial"}}</a> | |||||
{{if .EnableSwagger}}<a href="/api/swagger" class="ui item">API</a>{{end}} | {{if .EnableSwagger}}<a href="/api/swagger" class="ui item">API</a>{{end}} | ||||
{{if .IsSigned}} | |||||
<a href="https://git.openi.org.cn/zeizei/OpenI_Learning/issues/new" class="ui item" target="_blank">{{.i18n.Tr "custom.foot.advice_feedback"}}</a> | |||||
{{else}} | |||||
<a href="{{AppSubUrl}}/user/login" class="ui item">{{.i18n.Tr "custom.foot.advice_feedback"}}</a> | |||||
{{end}} | |||||
{{template "custom/extra_links_footer" .}} | {{template "custom/extra_links_footer" .}} | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -186,7 +186,6 @@ var _hmt = _hmt || []; | |||||
})(); | })(); | ||||
</script> | </script> | ||||
<script src="/self/func.js" type="text/javascript"></script> | <script src="/self/func.js" type="text/javascript"></script> | ||||
</head> | </head> | ||||
<body> | <body> | ||||
{{template "custom/body_outer_pre" .}} | {{template "custom/body_outer_pre" .}} | ||||
@@ -195,14 +194,57 @@ var _hmt = _hmt || []; | |||||
<noscript>{{.i18n.Tr "enable_javascript"}}</noscript> | <noscript>{{.i18n.Tr "enable_javascript"}}</noscript> | ||||
{{template "custom/body_inner_pre" .}} | {{template "custom/body_inner_pre" .}} | ||||
{{if not .PageIsInstall}} | {{if not .PageIsInstall}} | ||||
<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" > | |||||
<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> | |||||
{{end}} | {{end}} | ||||
{{/* | {{/* | ||||
</div> | </div> | ||||
</body> | </body> | ||||
</html> | </html> | ||||
*/}} | */}} | ||||
<script> | |||||
function closeNoice(){ | |||||
document.getElementById("notic_content").style.display='none' | |||||
localStorage.setItem("isCloseNotice",true) | |||||
} | |||||
function isShowNotice(){ | |||||
var current_notice = localStorage.getItem("notice") | |||||
if (current_notice != "{{.notice.CommitId}}"){ | |||||
localStorage.setItem('notice',"{{.notice.CommitId}}"); | |||||
isNewNotice=true; | |||||
localStorage.setItem("isCloseNotice",false) | |||||
}else{ | |||||
isNewNotice=false; | |||||
} | |||||
if ("{{.notice.Visible}}"){ | |||||
if(isNewNotice){ | |||||
document.getElementById("notic_content").style.display='block' | |||||
}else{ | |||||
isCloseNotice = localStorage.getItem("isCloseNotice") | |||||
if (JSON.parse(isCloseNotice)){ | |||||
document.getElementById("notic_content").style.display='none' | |||||
}else{ | |||||
document.getElementById("notic_content").style.display='block' | |||||
} | |||||
} | |||||
}else{ | |||||
document.getElementById("notic_content").style.display='none' | |||||
} | |||||
} | |||||
isShowNotice(); | |||||
</script> |
@@ -200,9 +200,52 @@ 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" > | |||||
<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> | |||||
{{end}} | {{end}} | ||||
{{/* | {{/* | ||||
</div> | </div> | ||||
</body> | </body> | ||||
</html> | </html> | ||||
*/}} | */}} | ||||
<script> | |||||
function closeNoice(){ | |||||
document.getElementById("notic_content").style.display='none' | |||||
localStorage.setItem("isCloseNotice",true) | |||||
} | |||||
function isShowNotice(){ | |||||
var current_notice = localStorage.getItem("notice") | |||||
if (current_notice != "{{.notice.CommitId}}"){ | |||||
localStorage.setItem('notice',"{{.notice.CommitId}}"); | |||||
isNewNotice=true; | |||||
localStorage.setItem("isCloseNotice",false) | |||||
}else{ | |||||
isNewNotice=false; | |||||
} | |||||
if ("{{.notice.Visible}}"){ | |||||
if(isNewNotice){ | |||||
document.getElementById("notic_content").style.display='block' | |||||
}else{ | |||||
isCloseNotice = localStorage.getItem("isCloseNotice") | |||||
if (JSON.parse(isCloseNotice)){ | |||||
document.getElementById("notic_content").style.display='none' | |||||
}else{ | |||||
document.getElementById("notic_content").style.display='block' | |||||
} | |||||
} | |||||
}else{ | |||||
document.getElementById("notic_content").style.display='none' | |||||
} | |||||
} | |||||
isShowNotice(); | |||||
</script> |
@@ -186,24 +186,27 @@ var _hmt = _hmt || []; | |||||
s.parentNode.insertBefore(hm, s); | s.parentNode.insertBefore(hm, s); | ||||
})(); | })(); | ||||
</script> | </script> | ||||
<script src="/self/func.js" type="text/javascript"></script> | |||||
<!--RemixIcon Fonts v2.5.0--> | |||||
<link rel="stylesheet" href="/RemixIcon_Fonts_v2.5.0/fonts/remixicon.css"> | |||||
<!-- Swiper --> | |||||
<link rel="stylesheet" href="/swiper/swiper-bundle.min.css"> | |||||
<script src="/swiper/swiper-bundle.min.js"></script> | |||||
</head> | </head> | ||||
<body> | <body> | ||||
{{template "custom/body_outer_pre" .}} | {{template "custom/body_outer_pre" .}} | ||||
<div class="full height"> | <div class="full height"> | ||||
<noscript>{{.i18n.Tr "enable_javascript"}}</noscript> | <noscript>{{.i18n.Tr "enable_javascript"}}</noscript> | ||||
<div class="ui vertical masthead secondary hometop segment"> | |||||
{{template "custom/body_inner_pre" .}} | |||||
{{if not .PageIsInstall}} | |||||
<div class="ui container"> | |||||
<div class="ui top secondary stackable main menu following bar"> | |||||
{{template "base/head_navbar_home" .}} | |||||
</div><!-- end bar --> | |||||
</div> | |||||
{{end}} | |||||
{{template "custom/body_inner_pre" .}} | |||||
{{if not .PageIsInstall}} | |||||
<div class="ui top secondary stackable main menu following bar dark"> | |||||
{{template "base/head_navbar" .}} | |||||
</div><!-- end bar --> | |||||
{{end}} | |||||
{{/* | {{/* | ||||
</div> | |||||
</div> | </div> | ||||
</body> | </body> | ||||
</html> | </html> | ||||
@@ -168,6 +168,14 @@ | |||||
{{svg "octicon-question" 16}} | {{svg "octicon-question" 16}} | ||||
{{.i18n.Tr "help"}}<!-- Help --> | {{.i18n.Tr "help"}}<!-- Help --> | ||||
</a--> | </a--> | ||||
<a class="item" href="https://git.openi.org.cn/zeizei/OpenI_Learning" target="_blank"> | |||||
<i class="tutorial_icon"> | |||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||||
<path fill="none" d="M0 0h24v24H0z"/><path d="M2 3.993A1 1 0 0 1 2.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 0 1-.992.993H2.992A.993.993 0 0 1 2 20.007V3.993zM12 5v14h8V5h-8zm1 2h6v2h-6V7zm0 3h6v2h-6v-2z"/> | |||||
</svg> | |||||
</i> | |||||
{{.i18n.Tr "custom.Platform_Tutorial"}} | |||||
</a> | |||||
{{if .IsAdmin}} | {{if .IsAdmin}} | ||||
<div class="divider"></div> | <div class="divider"></div> | ||||
@@ -213,4 +221,6 @@ | |||||
</div><!-- end anonymous right menu --> | </div><!-- end anonymous right menu --> | ||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
@@ -166,6 +166,14 @@ | |||||
{{svg "octicon-question" 16}} | {{svg "octicon-question" 16}} | ||||
{{.i18n.Tr "help"}}<!-- Help --> | {{.i18n.Tr "help"}}<!-- Help --> | ||||
</a--> | </a--> | ||||
<a class="item" href="https://git.openi.org.cn/zeizei/OpenI_Learning" target="_blank"> | |||||
<i class="tutorial_icon"> | |||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||||
<path fill="none" d="M0 0h24v24H0z"/><path d="M2 3.993A1 1 0 0 1 2.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 0 1-.992.993H2.992A.993.993 0 0 1 2 20.007V3.993zM12 5v14h8V5h-8zm1 2h6v2h-6V7zm0 3h6v2h-6v-2z"/> | |||||
</svg> | |||||
</i> | |||||
{{.i18n.Tr "custom.Platform_Tutorial"}} | |||||
</a> | |||||
{{if .IsAdmin}} | {{if .IsAdmin}} | ||||
<div class="divider"></div> | <div class="divider"></div> | ||||
@@ -148,6 +148,14 @@ | |||||
{{svg "octicon-question" 16}} | {{svg "octicon-question" 16}} | ||||
{{.i18n.Tr "help"}}<!-- Help --> | {{.i18n.Tr "help"}}<!-- Help --> | ||||
</a--> | </a--> | ||||
<a class="item" href="https://git.openi.org.cn/zeizei/OpenI_Learning" target="_blank"> | |||||
<i class="tutorial_icon"> | |||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||||
<path fill="none" d="M0 0h24v24H0z"/><path d="M2 3.993A1 1 0 0 1 2.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 0 1-.992.993H2.992A.993.993 0 0 1 2 20.007V3.993zM12 5v14h8V5h-8zm1 2h6v2h-6V7zm0 3h6v2h-6v-2z"/> | |||||
</svg> | |||||
</i> | |||||
{{.i18n.Tr "custom.Platform_Tutorial"}} | |||||
</a> | |||||
{{if .IsAdmin}} | {{if .IsAdmin}} | ||||
<div class="divider"></div> | <div class="divider"></div> | ||||
@@ -169,6 +169,14 @@ | |||||
{{svg "octicon-question" 16}} | {{svg "octicon-question" 16}} | ||||
{{.i18n.Tr "help"}}<!-- Help --> | {{.i18n.Tr "help"}}<!-- Help --> | ||||
</a--> | </a--> | ||||
<a class="item" href="https://git.openi.org.cn/zeizei/OpenI_Learning" target="_blank"> | |||||
<i class="tutorial_icon"> | |||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="16" height="16"> | |||||
<path fill="none" d="M0 0h24v24H0z"/><path d="M2 3.993A1 1 0 0 1 2.992 3h18.016c.548 0 .992.445.992.993v16.014a1 1 0 0 1-.992.993H2.992A.993.993 0 0 1 2 20.007V3.993zM12 5v14h8V5h-8zm1 2h6v2h-6V7zm0 3h6v2h-6v-2z"/> | |||||
</svg> | |||||
</i> | |||||
{{.i18n.Tr "custom.Platform_Tutorial"}} | |||||
</a> | |||||
{{if .IsAdmin}} | {{if .IsAdmin}} | ||||
<div class="divider"></div> | <div class="divider"></div> | ||||
@@ -200,9 +200,53 @@ 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" > | |||||
<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> | |||||
{{end}} | {{end}} | ||||
{{/* | {{/* | ||||
</div> | </div> | ||||
</body> | </body> | ||||
</html> | </html> | ||||
*/}} | */}} | ||||
<script> | |||||
function closeNoice(){ | |||||
document.getElementById("notic_content").style.display='none' | |||||
localStorage.setItem("isCloseNotice",true) | |||||
} | |||||
function isShowNotice(){ | |||||
var current_notice = localStorage.getItem("notice") | |||||
if (current_notice != "{{.notice.CommitId}}"){ | |||||
localStorage.setItem('notice',"{{.notice.CommitId}}"); | |||||
isNewNotice=true; | |||||
localStorage.setItem("isCloseNotice",false) | |||||
}else{ | |||||
isNewNotice=false; | |||||
} | |||||
if ("{{.notice.Visible}}"){ | |||||
if(isNewNotice){ | |||||
document.getElementById("notic_content").style.display='block' | |||||
}else{ | |||||
isCloseNotice = localStorage.getItem("isCloseNotice") | |||||
if (JSON.parse(isCloseNotice)){ | |||||
document.getElementById("notic_content").style.display='none' | |||||
}else{ | |||||
document.getElementById("notic_content").style.display='block' | |||||
} | |||||
} | |||||
}else{ | |||||
document.getElementById("notic_content").style.display='none' | |||||
} | |||||
} | |||||
isShowNotice(); | |||||
</script> |
@@ -1,7 +1,7 @@ | |||||
{{$paginationLink := .Page.GetParams}} | {{$paginationLink := .Page.GetParams}} | ||||
{{with .Page.Paginater}} | {{with .Page.Paginater}} | ||||
{{if gt .TotalPages 1}} | {{if gt .TotalPages 1}} | ||||
<div class="center page buttons"> | |||||
<div class="center page buttons" style="margin: 0px auto 15px"> | |||||
<div class="ui borderless pagination menu"> | <div class="ui borderless pagination menu"> | ||||
<a class="{{if .IsFirst}}disabled{{end}} item navigation" {{if not .IsFirst}}href="{{$.Link}}{{if $paginationLink}}?{{$paginationLink}}{{end}}"{{end}}><i class="angle double left icon"></i><span class="navigation_label"> {{$.i18n.Tr "admin.first_page"}}</span></a> | <a class="{{if .IsFirst}}disabled{{end}} item navigation" {{if not .IsFirst}}href="{{$.Link}}{{if $paginationLink}}?{{$paginationLink}}{{end}}"{{end}}><i class="angle double left icon"></i><span class="navigation_label"> {{$.i18n.Tr "admin.first_page"}}</span></a> | ||||
<a class="{{if not .HasPrevious}}disabled{{end}} item navigation" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}{{if $paginationLink}}&{{$paginationLink}}{{end}}"{{end}}> | <a class="{{if not .HasPrevious}}disabled{{end}} item navigation" {{if .HasPrevious}}href="{{$.Link}}?page={{.Previous}}{{if $paginationLink}}&{{$paginationLink}}{{end}}"{{end}}> | ||||
@@ -40,20 +40,20 @@ | |||||
<div class="ui secondary pointing tabular top attached borderless menu navbar"> | <div class="ui secondary pointing tabular top attached borderless menu navbar"> | ||||
{{if .PageIsExplore}} | {{if .PageIsExplore}} | ||||
<a class="{{if eq .SortType "hot"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=hot"> | |||||
<a class="{{if eq .SortType "hot"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=hot&tab={{$.TabName}}"> | |||||
<svg class="svg octicon-repo" width="16" height="16" aria-hidden="true"> | <svg class="svg octicon-repo" width="16" height="16" aria-hidden="true"> | ||||
<use xlink:href="#octicon-repo" /> | <use xlink:href="#octicon-repo" /> | ||||
</svg> | </svg> | ||||
热门{{.i18n.Tr "explore.repos"}} | 热门{{.i18n.Tr "explore.repos"}} | ||||
</a> | </a> | ||||
<a class="{{if eq .SortType "active"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=active"> | |||||
<a class="{{if eq .SortType "active"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=active&tab={{$.TabName}}"> | |||||
<svg class="svg octicon-inbox" width="16" height="16" aria-hidden="true"> | <svg class="svg octicon-inbox" width="16" height="16" aria-hidden="true"> | ||||
<use xlink:href="#octicon-inbox" /> | <use xlink:href="#octicon-inbox" /> | ||||
</svg> | </svg> | ||||
活跃{{.i18n.Tr "explore.repos"}} | 活跃{{.i18n.Tr "explore.repos"}} | ||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=recentupdate"> | |||||
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?q={{$.Keyword}}&topic={{$.Topic}}&sort=recentupdate&tab={{$.TabName}}"> | |||||
<svg class="svg octicon-organization" width="16" height="16" aria-hidden="true"> | <svg class="svg octicon-organization" width="16" height="16" aria-hidden="true"> | ||||
<use xlink:href="#octicon-organization" /> | <use xlink:href="#octicon-organization" /> | ||||
</svg> {{.i18n.Tr "repo.issues.filter_sort.recentupdate"}} | </svg> {{.i18n.Tr "repo.issues.filter_sort.recentupdate"}} | ||||
@@ -67,16 +67,16 @@ | |||||
<i class="dropdown icon"></i> | <i class="dropdown icon"></i> | ||||
</span> | </span> | ||||
<div class="menu"> | <div class="menu"> | ||||
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a> | |||||
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> | |||||
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> | |||||
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> | |||||
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a> | |||||
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a> | |||||
<a class="{{if eq .SortType "moststars"}}active{{end}} item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.moststars"}}</a> | |||||
<a class="{{if eq .SortType "feweststars"}}active{{end}} item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.feweststars"}}</a> | |||||
<a class="{{if eq .SortType "mostforks"}}active{{end}} item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.mostforks"}}</a> | |||||
<a class="{{if eq .SortType "fewestforks"}}active{{end}} item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}&topic={{$.Topic}}">{{.i18n.Tr "repo.issues.filter_sort.fewestforks"}}</a> | |||||
<a class="{{if eq .SortType "newest"}}active{{end}} item" href="{{$.Link}}?sort=newest&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.latest"}}</a> | |||||
<a class="{{if eq .SortType "oldest"}}active{{end}} item" href="{{$.Link}}?sort=oldest&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.oldest"}}</a> | |||||
<a class="{{if eq .SortType "alphabetically"}}active{{end}} item" href="{{$.Link}}?sort=alphabetically&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.alphabetically"}}</a> | |||||
<a class="{{if eq .SortType "reversealphabetically"}}active{{end}} item" href="{{$.Link}}?sort=reversealphabetically&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.label.filter_sort.reverse_alphabetically"}}</a> | |||||
<a class="{{if eq .SortType "recentupdate"}}active{{end}} item" href="{{$.Link}}?sort=recentupdate&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.recentupdate"}}</a> | |||||
<a class="{{if eq .SortType "leastupdate"}}active{{end}} item" href="{{$.Link}}?sort=leastupdate&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.leastupdate"}}</a> | |||||
<a class="{{if eq .SortType "moststars"}}active{{end}} item" href="{{$.Link}}?sort=moststars&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.moststars"}}</a> | |||||
<a class="{{if eq .SortType "feweststars"}}active{{end}} item" href="{{$.Link}}?sort=feweststars&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.feweststars"}}</a> | |||||
<a class="{{if eq .SortType "mostforks"}}active{{end}} item" href="{{$.Link}}?sort=mostforks&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.mostforks"}}</a> | |||||
<a class="{{if eq .SortType "fewestforks"}}active{{end}} item" href="{{$.Link}}?sort=fewestforks&q={{$.Keyword}}&topic={{$.Topic}}&tab={{$.TabName}}">{{.i18n.Tr "repo.issues.filter_sort.fewestforks"}}</a> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -59,7 +59,7 @@ | |||||
</div> | </div> | ||||
<div class="swiper-slide"> | <div class="swiper-slide"> | ||||
<div class="ui card"> | <div class="ui card"> | ||||
<a class="image" href="https://git.openi.org.cn/TensorLayer"> | |||||
<a class="image" href="https://git.openi.org.cn/OpenI/TensorLayerX"> | |||||
<img src="/img/org-tensorlayer@2x-80.jpg" alt="TensorLayer" title="TensorLayer"> | <img src="/img/org-tensorlayer@2x-80.jpg" alt="TensorLayer" title="TensorLayer"> | ||||
</a> | </a> | ||||
</div> | </div> | ||||
@@ -10,6 +10,7 @@ | |||||
<div class="ui fluid action input"> | <div class="ui fluid action input"> | ||||
<input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus> | <input name="q" value="{{.Keyword}}" placeholder="{{.i18n.Tr "explore.search"}}..." autofocus> | ||||
<input type="hidden" name="topic" value="{{$.Topic}}"> | <input type="hidden" name="topic" value="{{$.Topic}}"> | ||||
<input type="hidden" name="tab" value="{{$.TabName}}"> | |||||
<input type="hidden" name="sort" value="{{$.SortType}}"> | <input type="hidden" name="sort" value="{{$.SortType}}"> | ||||
<button class="ui green button">{{.i18n.Tr "explore.search"}}</button> | <button class="ui green button">{{.i18n.Tr "explore.search"}}</button> | ||||
</div> | </div> | ||||
@@ -1,221 +1,161 @@ | |||||
{{template "base/head_home" .}} | {{template "base/head_home" .}} | ||||
<div class="ui container homebanner"> | |||||
<h1 class="ui header"> | |||||
启智AI开发协作平台 | |||||
<div class="sub header"> | |||||
面向AI领域的一站式协同开发环境 | |||||
</div> | |||||
</h1> | |||||
<p class="am-lh-18">免费私有代码仓库,免费计算资源,大容量数据存储,<br>多类型硬件环境(GPU、NPU),AI开发流水线(开发-调试-训练-迭代)</p> | |||||
{{if .IsSigned}} | |||||
<a class="circular ui secondary button" href="{{AppSubUrl}}/dashboard">立即使用 <i class="right arrow icon"></i></a> | |||||
{{else}} | |||||
<a class="circular ui secondary button" href="{{AppSubUrl}}/user/login">立即使用 <i class="right arrow icon"></i></a> | |||||
{{end}} | |||||
<div class="bannerpic"><img class="ui fluid image" src="/img/gitopeni-index-01.svg"></div> | |||||
</div> | |||||
</div><!-- end segment --> | |||||
<div class="explore repositories"> | |||||
<div class="ui sticky container"> | |||||
<div class="ui secondary pointing fluid five item menu" style="background-color: #FFF;"> | |||||
<a class="item" href="#first">代码</a> | |||||
<a class="item" href="#second">数据</a> | |||||
<a class="item" href="#third">AI流水线</a> | |||||
<a class="item" href="#fourth">协同开发</a> | |||||
<a class="item" href="#fifth">云脑协同</a> | |||||
</div> | |||||
</div> | |||||
<div id="railContent"> | |||||
<a name="first"></a> | |||||
<div class="ui container am-mt-30 basic tab i-code active" style="position: relative;"> | |||||
<div class="ui inverted very padded segment radius15 am-pl-30"> | |||||
<div class="ui mobile reversed stackable grid am-pl-30"> | |||||
<div class="six wide column"> | |||||
<h2 class="ui huge blue header">代码管理</h2> | |||||
<p class="am-lh-18">在这里为你和你的团队创建项目,基于Git工具,提交记录或者回滚代码修改。<br> | |||||
不论是公开或者私有仓库,都可免费使用所有功能。<br> | |||||
尽情将你喜欢的代码都放在这里,仓库数量、存储容量不受限</p> | |||||
{{if .IsSigned}} | |||||
<a class="ui blue basic button am-mt-20" href="{{AppSubUrl}}/dashboard">立即使用 </a> | |||||
{{else}} | |||||
<a class="ui blue basic button am-mt-20" href="{{AppSubUrl}}/user/login">立即使用 </a> | |||||
{{end}} | |||||
</div> | |||||
<div class="ten wide column computer only i-code-pic am-pt-30"> | |||||
<img class="ui fluid rounded image am-shadow-2 am-mt-10" src="/img/i-code-pic.jpg" style="position: absolute;"> | |||||
<div class="ui vertical masthead secondary hometop segment"> | |||||
<div class="ui container" style="position: relative;"> | |||||
<div class="ui center homebanner"> | |||||
<h1 class="ui huge header"> | |||||
{{.page_title}} | |||||
<div class="sub header"> | |||||
{{.page_small_title}} | |||||
</div> | </div> | ||||
</div> | |||||
</h1> | |||||
<p class="ui am-lh-18">{{.page_description}}</p> | |||||
{{if .IsSigned}} | |||||
<a class="circular huge ui secondary button" href="{{AppSubUrl}}/dashboard">{{.page_use}} <i class="right arrow icon"></i></a> | |||||
{{else}} | |||||
<a class="circular huge ui secondary button" href="{{AppSubUrl}}/user/login">{{.page_use}} <i class="right arrow icon"></i></a> | |||||
{{end}} | |||||
</div> | </div> | ||||
<div class="am-mt-30 am-pt-30 am-pl-30"> | |||||
<div class="am-pl-30 am-pb-30"> | |||||
<h2 class="ui huge header am-bw">协作开发</h2> | |||||
<p class="am-lh-18">鼓励通过创建合并请求(PR)的方式,更好的进行团队协作<br> | |||||
代码评审让每一次的代码修改得以二次确认,提高代码质量<br> | |||||
创建并指派任务(Issue),让每一个任务的进展有迹可循,规范管理<br> | |||||
被合并的PR,可获得奖励积分;积分总额可以显示出你在项目中的贡献度,也许有一天会有人愿意为此付费<br> | |||||
</p> | |||||
</div> | |||||
</div> | |||||
<div class="leftline01"></div> | |||||
</div> | |||||
<a name="second"></a> | |||||
<div class="ui basic tab active am-mt-30 bg-gray am-pt-30"> | |||||
<div class="ui container i-data" style="position: relative;"> | |||||
<div class="leftline02"></div> | |||||
<div class="ui stackable grid"> | |||||
<div class="nine wide column"> | |||||
<img class="ui centered medium rounded large image" src="/img/gitopeni-index-02.svg"> | |||||
<div class="i-code-pic" style="margin-top: -4.0rem;"> | |||||
<img class="ui fluid rounded image am-shadow-2" src="/img/i-data-pic.jpg"> | |||||
<div class="bannerpic"><img class="ui fluid image" src="/img/gitopeni-index-01.svg"></div> | |||||
<div id="homenews" class="ui container"> | |||||
<p>* {{.page_only_dynamic}}</p> | |||||
<div class="ui grid"> | |||||
<div class="twelve wide tablet ten wide computer column homenews"> | |||||
<div class="newslist"> | |||||
<div class="ui mini aligned list swiper-wrapper" id="newmessage"> | |||||
</div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="seven wide column am-pt-30"> | |||||
<h2 class="ui huge blue header">数据集管理</h2> | |||||
<p class="am-lh-18"> | |||||
数据是重要的生产要素,AI开发更是离不开数据;<br> | |||||
- 数据与模型代码的协同,可在项目中上传关联的数据集;<br> | |||||
- 数据存储免费,不限制文件大小;<br> | |||||
- 数据可共享,标注清洗过的公开数据集,用户可设置为公有数据,供社区用户下载; | |||||
</p> | |||||
<div class="am-mt-30 am-pt-20"></div> | |||||
<h2 class="ui huge header">使用数据集</h2> | |||||
<p class="am-lh-18"> | |||||
数据集可以直接用于训练或者推理任务中<br> | |||||
创建任务时选择对应的数据集,启动任务执行环境(Docker)后,即可在Docker内访问到你的代码和数据,就像在你本地执行一样 | |||||
</p> | |||||
</div> | |||||
</div> | |||||
</div><!-- end homenews --> | |||||
</div> | |||||
</div><!-- end segment --> | |||||
<!--组织--> | |||||
<div class="ui container homeorg"> | |||||
<div class="ui stackable grid"> | |||||
<div class="sixteen wide tablet four wide computer column homeorg-tit"> | |||||
<h2>{{.page_recommend_org}}</h2> | |||||
<p><span class="ui text grey">{{.page_recommend_org_desc}}</span><a href="{{.RecommendURL}}">{{.page_recommend_org_commit}}</a></p> | |||||
<a href="{{AppSubUrl}}/explore/organizations" class="circular ui primary basic button">{{.page_recommend_org_more}} <i class="arrow circle right icon"></i></a> | |||||
</div> | |||||
<div class="sixteen wide tablet twelve wide computer column"> | |||||
<div class="ui stackable three column grid homeorg-list" id="recommendorg"> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | |||||
</div> | |||||
<div class="leftline01"></div> | |||||
</div> | |||||
<!--项目--> | |||||
<div class="ui container homepro"> | |||||
<div class="leftline02"></div> | |||||
<div class="leftline02-2"></div> | |||||
<div class="ui center homepro-tit am-mb-20"> | |||||
<h2>{{.page_recommend_repo}}</h2> | |||||
<p><span class="ui text grey">{{.page_recommend_repo_desc}}</span><a href="{{.RecommendURL}}">{{.page_recommend_repo_commit}}</a>{{.page_recommend_repo_go}}<a href="{{AppSubUrl}}/explore/">{{.page_recommend_repo_more}}</a></p> | |||||
</div> | |||||
<a name="third"></a> | |||||
<div class="ui basic tab active container am-mt-30 am-pt-30"> | |||||
<h2 class="ui center aligned huge blue header am-pt-30"> | |||||
AI流水线 | |||||
<div class="sub header am-mt-10">提供集代码开发、数据管理、模型调试、推理和评测为一体的AI开发流水线</div> | |||||
</h2> | |||||
<div class="ui divider"></div> | |||||
<div class="ui centered grid"> | |||||
<div class="fourteen wide column"> | |||||
<div class="ui two column grid"> | |||||
<div class="column"> | |||||
<div class="ui small header">调试任务:</div> | |||||
<div class="ui bulleted list"> | |||||
<div class="item">配置模型运行环境;</div> | |||||
<div class="item">可在线编辑和调试模型代码,并将改动更新至代码仓库;</div> | |||||
<div class="item">基于编辑好的脚本,开展模型评测任务;</div> | |||||
</div> | |||||
</div> | |||||
<div class="column"> | |||||
<div class="ui small header">作业任务:</div> | |||||
<div class="ui bulleted list"> | |||||
<div class="item">利用已配置好的模型运行环境;</div> | |||||
<div class="item">基于编辑好的脚本,一键运行,开展模型训练或模型推理任务;</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="homepro-list"> | |||||
<div class="swiper-wrapper" id="recommendrepo"> | |||||
</div> | </div> | ||||
<div class="ui divider"></div> | |||||
<img class="ui centered image" src="/img/develop.svg"> | |||||
<div class="swiper-pagination"></div> | |||||
</div> | </div> | ||||
</div> | |||||
<a name="fourth"></a> | |||||
<div class="ui basic tab active container am-mt-30 am-pt-30 i-env"> | |||||
<h2 class="ui center aligned huge blue header am-pt-30"> | |||||
协同开发环境 | |||||
<div class="sub header am-mt-10">启智AI协作开发平台与传统git平台最大的不同就在于提供了面向AI开发的协同开发环境</div> | |||||
</h2> | |||||
<div class="ui four stackable cards am-mt-20"> | |||||
<div class="card"> | |||||
<div class="image"> | |||||
<img src="/img/i-pic-01.svg"> | |||||
<a name="fourth"></a> | |||||
<div class="ui container i-env"> | |||||
<div class="ui center am-pb-30"> | |||||
<div class="leftline03"></div> | |||||
<h2>{{.page_dev_env}}</h2> | |||||
<p><span class="ui text grey">{{.page_dev_env_desc}}</p> | |||||
</div> | |||||
<div class="ui four stackable cards"> | |||||
<div class="card"> | |||||
<div class="image"> | |||||
<img src="/img/i-pic-01.svg"> | |||||
</div> | |||||
<div class="content"> | |||||
<h3 class="ui centered small header">{{.page_dev_env_desc_title}}</h3> | |||||
<div class="description"> | |||||
{{.page_dev_env_desc_desc}} | |||||
</div> | </div> | ||||
<div class="content"> | |||||
<h3 class="ui centered header">开发要素统一管理</h3> | |||||
<div class="description"> | |||||
平台提供了AI开发四大要素:模型代码、数据集、模型和执行环境的统一管理 | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<div class="card"> | |||||
<div class="image"> | |||||
<img src="/img/i-pic-02.svg"> | |||||
</div> | |||||
<div class="content"> | |||||
<h3 class="ui centered small header">{{.page_dev_env_desc1_title}}</h3> | |||||
<div class="description"> | |||||
{{.page_dev_env_desc1_desc}} | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | |||||
<div class="card"> | <div class="card"> | ||||
<div class="image"> | |||||
<img src="/img/i-pic-02.svg"> | |||||
</div> | |||||
<div class="content"> | |||||
<h3 class="ui centered header">数据协同与共享</h3> | |||||
<div class="description"> | |||||
通过在项目中上传数据集,项目成员多人协作完成数据预处理;也可以通过将数据设置为公有数据集,与社区开发者共同建立更好的模型 | |||||
</div> | |||||
</div> | |||||
<div class="image"> | |||||
<img src="/img/i-pic-03.svg"> | |||||
</div> | </div> | ||||
<div class="card"> | |||||
<div class="image"> | |||||
<img src="/img/i-pic-03.svg"> | |||||
</div> | |||||
<div class="content"> | |||||
<h3 class="ui centered header">模型管理与共享</h3> | |||||
<div class="description"> | |||||
将模型与代码版本建立关联,可以基于代码历史版本,使用不同的方式调整模型,并将结果保存下来;训练好的模型可以开放共享,让更多人的使用模型测试并提出反馈 | |||||
</div> | |||||
<div class="content"> | |||||
<h3 class="ui centered small header">{{.page_dev_env_desc2_title}}</h3> | |||||
<div class="description"> | |||||
{{.page_dev_env_desc2_desc}} | |||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="card"> | |||||
<div class="image"> | |||||
<img src="/img/i-pic-04.svg"> | |||||
</div> | |||||
<div class="content"> | |||||
<h3 class="ui centered header">一次配置,多次使用</h3> | |||||
<div class="description"> | |||||
提供执行环境共享,一次配置,多次使用,降低模型开发门槛,避免花费重复的时间配置复杂的环境 | |||||
</div> | |||||
</div> | |||||
<div class="card"> | |||||
<div class="image"> | |||||
<img src="/img/i-pic-04.svg"> | |||||
</div> | |||||
<div class="content"> | |||||
<h3 class="ui centered small header">{{.page_dev_env_desc3_title}}</h3> | |||||
<div class="description"> | |||||
{{.page_dev_env_desc3_desc}} | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | |||||
<a name="fifth"></a> | |||||
<div class="ui basic tab active container am-mt-30 am-pt-30"> | |||||
<div class="ui very padded black inverted segment radius15"> | |||||
<div class="ui stackable grid"> | |||||
<div class="six wide column"> | |||||
<img class="ui centered large image" src="/img/i-yunnao.svg"> | |||||
</div> | |||||
<div class="ten wide column am-pt-30"> | |||||
<h2 class="ui huge blue header">鹏城云脑开源协同</h2> | |||||
<p class="am-lh-18"> | |||||
平台已经与鹏城云脑打通,可以利用鹏城云脑的丰富算力资源,完成AI开发任务<br> | |||||
鹏城云脑现有AI算力100P FLOPS@FP16(每秒十亿亿次半精度浮点计算),主要硬件基础设施由搭载英伟达Tesla V100 的GPU服务器和搭载鲲鹏、昇腾处理器的Atlas 900 AI集群构成<br> | |||||
开发者可以根据使用需求,自由选择相应计算资源,可以测试模型在不同硬件环境下的适配能力、性能、稳定性等<br> | |||||
如果您的模型需要更多的计算资源,也可以单独申请<br> | |||||
</p> | |||||
{{if .IsSigned}} | |||||
<a class="ui blue basic button am-mt-20" href="{{AppSubUrl}}/dashboard">立即使用 </a><a class="ui grey basic button am-mt-20" href="mailto:aiforge@openi.org.cn">单独申请</a> | |||||
{{else}} | |||||
<a class="ui blue basic button am-mt-20" href="{{AppSubUrl}}/user/login">立即使用 </a><a class="ui grey basic button am-mt-20" href="mailto:aiforge@openi.org.cn">单独申请</a> | |||||
{{end}} | |||||
</div> | |||||
<a name="fifth"></a> | |||||
<div class="ui container"> | |||||
<div class="ui very padded inverted segment radius15"> | |||||
<div class="ui stackable grid"> | |||||
<div class="six wide column"> | |||||
<img class="ui centered large image" src="/img/i-yunnao.svg"> | |||||
</div> | |||||
<div class="ten wide column am-pt-30"> | |||||
<h2 class="ui grey inverted header">{{.page_dev_yunlao}}</h2> | |||||
<p class="am-lh-18 ui text grey"> | |||||
{{.page_dev_yunlao_desc1}}<br> | |||||
{{.page_dev_yunlao_desc2}}<br> | |||||
{{.page_dev_yunlao_desc3}}<br> | |||||
{{.page_dev_yunlao_desc4}}<br> | |||||
</p> | |||||
{{if .IsSigned}} | |||||
<a class="ui blue basic button am-mt-20" href="{{AppSubUrl}}/dashboard">{{.page_use}}</a> | |||||
{{else}} | |||||
<a class="ui blue basic button am-mt-20" href="{{AppSubUrl}}/user/login">{{.page_use}}</a> | |||||
{{end}} | |||||
<a class="ui grey basic button am-mt-20" href="mailto:aiforge@openi.org.cn">{{.page_dev_yunlao_apply}}</a> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="am-mt-30"></div> | |||||
</div><!-- end railContent --> | |||||
</div> | |||||
<div class="am-mt-30"></div> | |||||
<script src="/self/js/jquery.min.js" type="text/javascript"></script> | |||||
<script src="/home/home.js?v={{MD5 AppVer}}" type="text/javascript"></script> | |||||
</div><!-- end explore --> | |||||
<script> | |||||
$('.menu .item') | |||||
.tab(); | |||||
$('.ui.sticky') | |||||
.sticky({ | |||||
context: '#railContent', | |||||
observeChanges: true, | |||||
}) | |||||
.sticky('refresh'); | |||||
</script> | |||||
{{template "base/footer" .}} | {{template "base/footer" .}} |
@@ -20,10 +20,11 @@ | |||||
</div> | </div> | ||||
<div class="ui container"> | <div class="ui container"> | ||||
<div class="ui stackable grid"> | |||||
{{template "org/navber" .}} | |||||
<div class="ui fourteen wide computer column"> | |||||
{{template "org/navber" .}} | |||||
{{template "org/select_pro" .}} | |||||
<div class="ui stackable grid"> | |||||
<div class="ui sixteen wide computer column"> | |||||
<div class="ui mobile reversed stackable grid"> | <div class="ui mobile reversed stackable grid"> | ||||
<div class="ui ten wide tablet eleven wide computer column"> | <div class="ui ten wide tablet eleven wide computer column"> | ||||
{{if .CanCreateOrgRepo}} | {{if .CanCreateOrgRepo}} | ||||
@@ -3,10 +3,11 @@ | |||||
{{template "org/header" .}} | {{template "org/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
{{template "base/alert" .}} | {{template "base/alert" .}} | ||||
{{template "org/navber" .}} | |||||
<div class="ui stackable grid"> | <div class="ui stackable grid"> | ||||
{{template "org/navber" .}} | |||||
<div class="ui fourteen wide computer column list"> | |||||
<div class="ui sixteen wide computer column list"> | |||||
{{ range .Members}} | {{ range .Members}} | ||||
<div class="item ui grid"> | <div class="item ui grid"> | ||||
<div class="ui two wide column"> | <div class="ui two wide column"> | ||||
@@ -1,4 +1,4 @@ | |||||
<div class="tablet only mobile only sixteen wide mobile sixteen wide tablet column row"> | |||||
<!-- <div class="tablet only mobile only sixteen wide mobile sixteen wide tablet column row"> | |||||
<div class="ui secondary pointing tabular top attached borderless menu navbar"> | <div class="ui secondary pointing tabular top attached borderless menu navbar"> | ||||
<a class="{{if $.PageIsOrgHome}}active{{end}} item" href="{{.HomeLink}}"> | <a class="{{if $.PageIsOrgHome}}active{{end}} item" href="{{.HomeLink}}"> | ||||
{{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | {{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | ||||
@@ -12,10 +12,10 @@ | |||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
</div> | |||||
</div> --> | |||||
<!--平板、移动端--> | <!--平板、移动端--> | ||||
<div class="computer only two wide computer column"> | |||||
<!-- <div class="computer only two wide computer column"> | |||||
<div class="ui grid"> | <div class="ui grid"> | ||||
<div class="sixteen wide column ui secondary sticky pointing tabular vertical menu"> | <div class="sixteen wide column ui secondary sticky pointing tabular vertical menu"> | ||||
{{with .Org}} | {{with .Org}} | ||||
@@ -33,5 +33,37 @@ | |||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | |||||
<!--电脑、宽屏--> | |||||
</div> --> | |||||
<!--电脑、宽屏--> | |||||
<style> | |||||
.dis{ | |||||
margin-bottom: 10px; | |||||
} | |||||
.active{ | |||||
color:#0366D6 !important; | |||||
} | |||||
.mleft{ | |||||
margin-left: 30% !important; | |||||
} | |||||
.mbom{ | |||||
margin-bottom: 10px !important; | |||||
} | |||||
</style> | |||||
<div class="row"> | |||||
<div class="ui secondary pointing tabular top attached borderless menu navbar mbom"> | |||||
{{with .Org}} | |||||
<a class="{{if $.PageIsOrgHome}}active{{end}} item mleft" href="{{.HomeLink}}"> | |||||
{{svg "octicon-home" 16}} {{$.i18n.Tr "org.home"}} | |||||
</a> | |||||
{{end}} | |||||
<a class="{{if $.PageIsOrgMembers}}active{{end}} item" href="{{$.OrgLink}}/members"> | |||||
{{svg "octicon-organization" 16}} {{$.i18n.Tr "org.people"}} | |||||
</a> | |||||
{{if or ($.IsOrganizationMember) ($.IsOrganizationOwner)}} | |||||
<a class="{{if $.PageIsOrgTeams}}active{{end}} item" href="{{$.OrgLink}}/teams"> | |||||
{{svg "octicon-jersey" 16}} {{$.i18n.Tr "org.teams"}} | |||||
</a> | |||||
{{end}} | |||||
</div> | |||||
</div> |
@@ -0,0 +1,319 @@ | |||||
<style> | |||||
.text-right{ | |||||
float:right !important; | |||||
} | |||||
.header{ | |||||
font-weight:bold; | |||||
font-size: 18px; | |||||
font-family: SourceHanSansSC-medium; | |||||
} | |||||
.cor{ | |||||
color:#0366D6 !important; | |||||
} | |||||
.header_card{ | |||||
/* color:#003A8C !important; */ | |||||
color:#0366D6 !important; | |||||
margin: 10px 0 0px 0; | |||||
height: 25px; | |||||
} | |||||
.marg{ | |||||
margin: 0 5px !important; | |||||
} | |||||
.content_list{ | |||||
max-height: 130px; | |||||
overflow: auto; | |||||
} | |||||
.Relist{ | |||||
color:#0366D6 !important; | |||||
} | |||||
.descript_height{ | |||||
color: #101010 !important; | |||||
margin: 10px 0; | |||||
height: 40px !important; | |||||
word-break:break-all; | |||||
line-height: 20px; | |||||
overflow: hidden; | |||||
/* overflow: hidden!important; | |||||
word-wrap:break-word!important; */ | |||||
} | |||||
.tags_height{ | |||||
height: 30px !important; | |||||
} | |||||
.full_height{ | |||||
height: 100%; | |||||
} | |||||
.omit{ | |||||
overflow: hidden; white-space: nowrap; text-overflow: ellipsis; | |||||
} | |||||
/deep/ ui.checkbox input[type=checkbox]::after{ | |||||
border: 1px solid #0366D6 !important; | |||||
} | |||||
.nowrap-2 { | |||||
/* height: 2.837em; */ | |||||
/* line-height: 1.4285em; */ | |||||
overflow: hidden; | |||||
overflow: hidden; | |||||
display: -webkit-box; | |||||
-webkit-line-clamp: 2; | |||||
-webkit-box-orient: vertical; | |||||
} | |||||
</style> | |||||
<div class="ui stackable grid"> | |||||
<div style="width: 100%;margin:15px 0;"> | |||||
{{if .tags}} | |||||
<span class="header"> | |||||
精选项目 | |||||
</span> | |||||
<!-- {{.IsOrganizationOwner}} --> | |||||
{{if .IsOrganizationOwner}} | |||||
<a class="text-right" id="model" onclick="showcreate()" >{{svg "octicon-gear" 16}}自定义</a> | |||||
{{end}} | |||||
{{end}} | |||||
</div> | |||||
<div style="width: 100%;"> | |||||
{{ range .tags}} | |||||
{{if eq .TagName "精选项目"}} | |||||
<div class="ui three cards" style="margin-bottom: 10px;"> | |||||
{{ range .RepoList}} | |||||
<div class="card" > | |||||
<div class="extra full_height cor" > | |||||
<div class=" header header_card omit" > | |||||
<a class="header_card image poping up " href="{{.Link}}" data-content="{{.Name}}" data-position="top left" data-variation="tiny inverted"> {{.Name}}</a> | |||||
</div> | |||||
<div class='content descript_height nowrap-2'> | |||||
{{.Description}} | |||||
</div> | |||||
<div class="content " > | |||||
{{if .Topics }} | |||||
<div class=" tags " style="position: relative;"> | |||||
{{range .Topics}} | |||||
{{if ne . "" }}<a style="max-width:100%;margin: 5px 0;display:inline-flex;" href="{{AppSubUrl}}/explore/repos?q={{.}}&topic={{$.Topic}}" ><span class="ui small label topic omit" >{{.}}</span></a>{{end}} | |||||
{{end}} | |||||
</div> | |||||
{{end}} | |||||
</div> | |||||
</div> | |||||
<div class=" extra " style="color:#888888;border-top: none !important"> | |||||
<div class="ui mini right compact marg" > | |||||
<a class="item marg "> | |||||
{{svg "octicon-eye" 16}} {{.NumWatches}} | |||||
</a> | |||||
<a class="item marg"> | |||||
{{svg "octicon-star" 16}} {{.NumStars}} | |||||
</a> | |||||
<a class="item marg"> | |||||
{{svg "octicon-git-branch" 16}} {{.NumForks}} | |||||
</a> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
{{end}} | |||||
</div> | |||||
{{end}} | |||||
{{end}} | |||||
</div> | |||||
</div> | |||||
<div class="ui modal"> | |||||
<div class="header" style="padding: 1rem;background-color: rgba(240, 240, 240, 100);"> | |||||
<h4 id="model_header">自定义精选项目</h4> | |||||
</div> | |||||
<div class="content content-padding" style="color: black;"> | |||||
<p>最多可选9个公开项目</p> | |||||
<div class="ui search" > | |||||
<div class="ui input" style="width: 100%;"> | |||||
<input type="text" id = 'search_selectPro' placeholder="Search ..." value = '' oninput="search()"> | |||||
</div> | |||||
</div> | |||||
<div style="margin: 10px ;"> | |||||
<div id ='org_list' style="margin-bottom: 20px;"class="content_list" > | |||||
</div> | |||||
</div> | |||||
<p id='recommend'></p> | |||||
<div class="inline field" style="margin-left: 37%;"> | |||||
<div class="actions"> | |||||
<button id="submitId" type="button" class="ui create_train_job green deny button" onclick="saveSeletedPro(1)"> | |||||
{{.i18n.Tr "explore.save"}} | |||||
</button> | |||||
<button class="ui button cancel" >{{.i18n.Tr "explore.cancel"}}</button> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
<script> | |||||
var data; | |||||
var filterData=[]; | |||||
var num=0; | |||||
function showcreate(obj){ | |||||
document.getElementById("search_selectPro").value='' | |||||
$('.ui.modal') | |||||
.modal({ | |||||
centered: false, | |||||
onShow:function(){ | |||||
$("#org_list").empty() | |||||
getPro(1) | |||||
}, | |||||
onHide:function(){ | |||||
} | |||||
}) | |||||
.modal('show') | |||||
} | |||||
function getPro(typeTag){ | |||||
$.ajax({ | |||||
type:"GET", | |||||
url:"/org/{{.Org.Name}}/org_tag/repo_list?tagId="+typeTag, | |||||
dataType:"json", | |||||
async:false, | |||||
success:function(json){ | |||||
data = json.data; | |||||
var n_length = data.length | |||||
pro_html = getHTML(data) | |||||
$("#org_list").append(pro_html) | |||||
// console.log('原始',data) | |||||
checkedNum(0) | |||||
} | |||||
}); | |||||
} | |||||
function getHTML(data){ | |||||
let pro_html='' | |||||
for (let i=0;i<data.length;i++){ | |||||
if (data[i].Selected==true){ | |||||
console.log("data[i]:",data[i]) | |||||
pro_html += `<div class="ui checkbox" style="width: 33%;margin-bottom:10px" > <input type="checkbox" id = " ${i}" checked="" onclick="checkedNum(${i})" class="Relist" name ='select_pro_name' data-repoid="${data[i].RepoID}" data-reponame="${data[i].RepoName}" data-selected=${data[i].Selected} > <label class='omit image poping up' data-content=${data[i].RepoName} data-position="top left " data-variation="mini"> ${data[i].RepoName}</label></div>` | |||||
pro_html += '</div>' | |||||
} | |||||
else{ | |||||
pro_html += `<div class="ui checkbox" style="width: 33%;margin-bottom:10px" > <input type="checkbox" id = "${i}" onclick="checkedNum(${i})" class="Relist" name ='select_pro_name' data-repoid="${data[i].RepoID}" data-reponame="${data[i].RepoName}" data-selected= ${data[i].Selected}> <label class='omit image poping up' data-content=${data[i].RepoName} data-position="top left " data-variation="mini"> ${data[i].RepoName} </label></div>` | |||||
pro_html += '</div>' | |||||
} | |||||
} | |||||
return pro_html | |||||
} | |||||
function saveSeletedPro(typeTag){ | |||||
var saveData=[]; | |||||
$('input[name="select_pro_name"]:checked').each(function(){ | |||||
console.log('值',this.dataset.repoid) | |||||
saveData.push(parseInt(this.dataset.repoid)); | |||||
}) | |||||
if(saveData.length>9){ | |||||
alert("最多可选9个,保存失败") | |||||
return | |||||
} | |||||
// saveData = getSelecteDataID(); | |||||
// console.log("数据:",saveData) | |||||
$.ajax({ | |||||
type:"POST", | |||||
url:"/org/{{.Org.Name}}/org_tag/repo_submit?tagId="+typeTag, | |||||
contentType:'application/json', | |||||
dataType:"json", | |||||
async:false, | |||||
data:JSON.stringify({'repoList':saveData | |||||
}), | |||||
success:function(res){ | |||||
console.log('保存成功'); | |||||
location.reload() | |||||
} | |||||
}); | |||||
} | |||||
function getSelecteData(){ | |||||
var selectedData=[]; | |||||
$('input[name="select_pro_name"]:checked').each(function(){ | |||||
// console.log(this) | |||||
// console.log('值',this.dataset.selected) | |||||
selectedData.push({"RepoID":parseInt(this.dataset.repoid),"RepoName":this.dataset.reponame,"Selected":JSON.parse(this.dataset.selected)}); | |||||
}) | |||||
return selectedData | |||||
} | |||||
function search(){ | |||||
var selectedData = getSelecteData(); | |||||
var searchValue = document.getElementById("search_selectPro").value; | |||||
filterData=[]; | |||||
console.log("searchValue:",searchValue) | |||||
for (let i=0;i<data.length;i++){ | |||||
var isInclude=false; | |||||
if(data[i].RepoName.toLowerCase().includes(searchValue.toLowerCase())){ | |||||
filterData.push(data[i]) | |||||
} | |||||
} | |||||
console.log("选中的值:",selectedData) | |||||
console.log("筛选包括选中的值:",filterData) | |||||
var showData=[]; | |||||
for(i=0;i<selectedData.length;i++){ | |||||
filterData =filterData.filter((item)=>{ | |||||
return item.RepoID!=selectedData[i].RepoID | |||||
}); | |||||
} | |||||
console.log("筛选后不包括选中的值:",filterData) | |||||
$("#org_list").empty() | |||||
if(searchValue!=""){ | |||||
if (filterData.length!=0){ | |||||
var pro_html = getHTML(selectedData); | |||||
console.log("selectedData_pro_html:",pro_html) | |||||
$("#org_list").append(pro_html) | |||||
pro_html= getHTML(filterData); | |||||
$("#org_list").append(pro_html) | |||||
}else{ | |||||
var pro_html = getHTML(selectedData); | |||||
$("#org_list").append(pro_html) | |||||
} | |||||
}else{ | |||||
var pro_html = getHTML(data); | |||||
$("#org_list").append(pro_html) | |||||
} | |||||
} | |||||
function checkedNum(id){ | |||||
num=0; | |||||
var inputs = document.getElementsByName("select_pro_name") | |||||
for (var i=0;i<inputs.length;i++){ | |||||
if(inputs[i].checked){ | |||||
num++ | |||||
if(num>9){ | |||||
document.getElementById(id).checked=false | |||||
alert("选择超过9个,请重新选择!") | |||||
return | |||||
} | |||||
} | |||||
} | |||||
var show_num = 9-num; | |||||
document.getElementById("recommend").innerHTML="还能推荐"+show_num+"个" | |||||
} | |||||
</script> |
@@ -3,12 +3,12 @@ | |||||
{{template "org/header" .}} | {{template "org/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
{{template "base/alert" .}} | {{template "base/alert" .}} | ||||
{{template "org/navber" .}} | |||||
<div class="ui stackable grid"> | <div class="ui stackable grid"> | ||||
{{template "org/navber" .}} | |||||
<div class="ui fourteen wide computer column list"> | |||||
<div class="ui sixteen wide computer column list"> | |||||
<div class="ui two column grid"> | <div class="ui two column grid"> | ||||
{{range .Teams}} | {{range .Teams}} | ||||
<div class="column"> | <div class="column"> | ||||
@@ -93,6 +93,14 @@ | |||||
display: none; | display: none; | ||||
} | } | ||||
.icons{ | |||||
/* position: absolute !important; | |||||
right: 150px; | |||||
top: 14px; | |||||
z-index: 2; */ | |||||
} | |||||
</style> | </style> | ||||
<div id="mask"> | <div id="mask"> | ||||
@@ -182,9 +190,10 @@ | |||||
</select> | </select> | ||||
</div> | </div> | ||||
<div class="inline required field"> | |||||
<div class="inline required field" style="position: relative;"> | |||||
<label>镜像</label> | <label>镜像</label> | ||||
<input type="text" list="cloudbrain_image" placeholder="选择镜像" name="image" required autofocus maxlength="254"> | <input type="text" list="cloudbrain_image" placeholder="选择镜像" name="image" required autofocus maxlength="254"> | ||||
<i class="times circle outline icon icons" style="visibility: hidden;" onclick="clearValue()"></i> | |||||
<datalist class="ui search" id="cloudbrain_image" style='width:385px;' name="image"> | <datalist class="ui search" id="cloudbrain_image" style='width:385px;' name="image"> | ||||
{{range .images}} | {{range .images}} | ||||
<option name="image" value="{{.Place}}">{{.PlaceView}}</option> | <option name="image" value="{{.Place}}">{{.PlaceView}}</option> | ||||
@@ -261,9 +270,17 @@ | |||||
<script> | <script> | ||||
let form = document.getElementById('form_id'); | let form = document.getElementById('form_id'); | ||||
$('#messageInfo').css('display','none') | |||||
let inputs = document.querySelectorAll('input[list]'); | |||||
inputs[0].addEventListener('change', function() { | |||||
$(".icon.icons").css("visibility","visible") | |||||
}); | |||||
$('#messageInfo').css('display','none') | |||||
function clearValue(){ | |||||
context=inputs[0] | |||||
context.value='' | |||||
$(".icon.icons").css("visibility","hidden") | |||||
} | |||||
form.onsubmit = function(e){ | form.onsubmit = function(e){ | ||||
let value_task = $("input[name='job_name']").val() | let value_task = $("input[name='job_name']").val() | ||||
let value_image = $("input[name='image']").val() | let value_image = $("input[name='image']").val() | ||||
@@ -202,14 +202,17 @@ | |||||
<div class="rect5"></div> | <div class="rect5"></div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<!-- 提示框 --> | |||||
<div class="alert"></div> | |||||
<div class="alert"></div> | |||||
<div class="repository release dataset-list view"> | <div class="repository release dataset-list view"> | ||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
{{template "base/alert" .}} | |||||
<!-- 提示框 --> | |||||
<!-- 列表容器 --> | <!-- 列表容器 --> | ||||
<div class="ui container"> | <div class="ui container"> | ||||
<div class="ui two column stackable grid "> | |||||
<div class="ui two column stackable grid"> | |||||
<div class="column"> | <div class="column"> | ||||
<div class="ui blue small menu compact selectcloudbrain"> | <div class="ui blue small menu compact selectcloudbrain"> | ||||
<a class="active item" href="{{.RepoLink}}/debugjob?debugListType=all">{{$.i18n.Tr "repo.modelarts.notebook"}}</a> | <a class="active item" href="{{.RepoLink}}/debugjob?debugListType=all">{{$.i18n.Tr "repo.modelarts.notebook"}}</a> | ||||
@@ -282,7 +285,7 @@ | |||||
<div class="row"> | <div class="row"> | ||||
<!-- 任务名 --> | <!-- 任务名 --> | ||||
<div class="four wide column"> | <div class="four wide column"> | ||||
<a class="title" href='{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}' title="{{.JobName}}" style="font-size: 14px;"> | |||||
<a class="title" href='{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}' title="{{.JobName}}" style="font-size: 14px;"> | |||||
<span class="fitted text_over" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | <span class="fitted text_over" style="width: 90%;vertical-align: middle;">{{.JobName}}</span> | ||||
</a> | </a> | ||||
</div> | </div> | ||||
@@ -315,34 +318,49 @@ | |||||
</a> | </a> | ||||
{{end}} --> | {{end}} --> | ||||
<!-- 调试 --> | <!-- 调试 --> | ||||
{{if .CanDebug}} | |||||
{{if eq .ComputeResource "CPU/GPU"}} | |||||
<a id="model-debug-{{.JobID}}" class='ui basic {{if ne .Status "RUNNING"}} disabled {{else}}blue {{end}}button' href="{{$.RepoLink}}/cloudbrain/{{.JobID}}/debug" target="_blank"> | |||||
{{$.i18n.Tr "repo.debug"}} | |||||
</a> | |||||
<form id="debugAgainForm-{{.JobID}}"> | |||||
{{$.CsrfTokenHtml}} | |||||
{{if .CanDebug}} | |||||
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} | |||||
<a style="margin: 0 1rem;" id="model-debug-{{.JobID}}" class='ui basic {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}}disabled {{else}}blue {{end}}button' onclick='debugAgain("{{.JobID}}","{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}/")'> | |||||
{{$.i18n.Tr "repo.debug"}} | |||||
</a> | |||||
{{else}} | |||||
<a id="model-debug-{{.JobID}}" class='ui basic {{if eq .Status "CREATING" "STOPPING" "WAITING" "STARTING"}} disabled {{else}}blue {{end}}button' onclick='debugAgain("{{.JobID}}","{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}/")'> | |||||
{{$.i18n.Tr "repo.debug_again"}} | |||||
</a> | |||||
{{end}} | |||||
{{else}} | {{else}} | ||||
<a id="model-debug-{{.JobID}}" class='ui basic {{if ne .Status "RUNNING"}} disabled {{else}}blue {{end}}button' href="{{$.RepoLink}}/modelarts/notebook/{{.JobID}}/debug" target="_blank"> | |||||
{{$.i18n.Tr "repo.debug"}} | |||||
</a> | |||||
{{if eq .Status "RUNNING" "WAITING" "CREATING" "STARTING"}} | |||||
<a class="ui basic disabled button"> | |||||
{{$.i18n.Tr "repo.debug"}} | |||||
</a> | |||||
{{else}} | |||||
<a class="ui basic disabled button"> | |||||
{{$.i18n.Tr "repo.debug_again"}} | |||||
</a> | |||||
{{end}} | |||||
{{end}} | {{end}} | ||||
{{else}} | |||||
<a class="ui basic disabled button"> | |||||
{{$.i18n.Tr "repo.debug"}} | |||||
</a> | |||||
{{end}} | |||||
</form> | |||||
<!-- 停止 --> | <!-- 停止 --> | ||||
<form id="stopForm-{{.JobID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}/stop" method="post" style="margin-left:-1px;"> | |||||
<form id="stopForm-{{.JobID}}" style="margin-left:-1px;"> | |||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
{{if .CanDel}} | {{if .CanDel}} | ||||
<a id="stop-model-debug-{{.JobID}}" class='ui basic {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING"}}disabled {{else}}blue {{end}}button' onclick="document.getElementById('stopForm-{{.JobID}}').submit();"> | |||||
{{$.i18n.Tr "repo.stop"}} | |||||
</a> | |||||
{{if eq .ComputeResource "CPU/GPU" }} | |||||
<a id="stop-model-debug-{{.JobID}}" class='ui basic {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING" "SUCCEEDED"}}disabled {{else}}blue {{end}}button' onclick='stopDebug("{{.JobID}}","{{$.RepoLink}}/cloudbrain/{{.JobID}}/stop")'> | |||||
{{$.i18n.Tr "repo.stop"}} | |||||
</a> | |||||
{{else}} | |||||
<a id="stop-model-debug-{{.JobID}}" class='ui basic {{if eq .Status "STOPPED" "FAILED" "START_FAILED" "STOPPING" "CREATING" "STARTING" "SUCCEEDED"}}disabled {{else}}blue {{end}}button' onclick='stopDebug("{{.JobID}}","{{$.RepoLink}}/modelarts/notebook/{{.JobID}}/stop")'> | |||||
{{$.i18n.Tr "repo.stop"}} | |||||
</a> | |||||
{{end}} | |||||
{{else}} | {{else}} | ||||
<a class="ui basic disabled button" onclick="document.getElementById('stopForm-{{.JobID}}').submit();"> | |||||
<a class="ui basic disabled button"> | |||||
{{$.i18n.Tr "repo.stop"}} | {{$.i18n.Tr "repo.stop"}} | ||||
</a> | </a> | ||||
{{end}} | {{end}} | ||||
<input type="hidden" name="debugListType" value="all"> | |||||
</form> | </form> | ||||
<!-- 删除 --> | <!-- 删除 --> | ||||
<form id="delForm-{{.JobID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}/del" method="post"> | <form id="delForm-{{.JobID}}" action="{{if eq .ComputeResource "CPU/GPU"}}{{$.RepoLink}}/cloudbrain{{else}}{{$.RepoLink}}/modelarts/notebook{{end}}/{{.JobID}}/del" method="post"> | ||||
@@ -384,6 +402,13 @@ | |||||
<a class="ui basic disabled button">{{$.i18n.Tr "repo.download"}}</a> | <a class="ui basic disabled button">{{$.i18n.Tr "repo.download"}}</a> | ||||
{{end}} | {{end}} | ||||
</div> | </div> | ||||
{{if and (ne .JobType "DEBUG") (eq .Cloudbrain.Type 0)}} | |||||
<div class="item" style="padding: 0 !important;"> | |||||
<a class="ui basic blue button" href="{{$.RepoLink}}/cloudbrain/{{.JobID}}/rate" target="_blank"> | |||||
评分 | |||||
</a> | |||||
</div> | |||||
{{end}} | |||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -463,10 +488,21 @@ | |||||
<script> | <script> | ||||
// 调试和评分新开窗口 | // 调试和评分新开窗口 | ||||
const {AppSubUrl, StaticUrlPrefix, csrf} = window.config; | |||||
let url={{.RepoLink}} | let url={{.RepoLink}} | ||||
let getParam=location.search.split('?debugListType=').pop() | |||||
let getParam=getQueryVariable('debugListType') | |||||
let dropdownValue = getParam==='all'||getParam==='' ? '全部' : getParam | let dropdownValue = getParam==='all'||getParam==='' ? '全部' : getParam | ||||
localStorage.setItem('all',location.href) | localStorage.setItem('all',location.href) | ||||
function getQueryVariable(variable) | |||||
{ | |||||
let query = window.location.search.substring(1); | |||||
let vars = query.split("&"); | |||||
for (let i=0;i<vars.length;i++) { | |||||
let pair = vars[i].split("="); | |||||
if(pair[0] == variable){return pair[1];} | |||||
} | |||||
return(false); | |||||
} | |||||
function stop(obj) { | function stop(obj) { | ||||
if (obj.style.color != "rgb(204, 204, 204)") { | if (obj.style.color != "rgb(204, 204, 204)") { | ||||
obj.target = '_blank' | obj.target = '_blank' | ||||
@@ -489,6 +525,7 @@ | |||||
onApprove: function() { | onApprove: function() { | ||||
document.getElementById(delId).submit() | document.getElementById(delId).submit() | ||||
flag = true | flag = true | ||||
$('.alert').html('操作成功!').removeClass('alert-danger').addClass('alert-success').show().delay(1500).fadeOut(); | |||||
}, | }, | ||||
onHidden: function() { | onHidden: function() { | ||||
if (flag == false) { | if (flag == false) { | ||||
@@ -499,7 +536,68 @@ | |||||
.modal('show') | .modal('show') | ||||
} | } | ||||
} | } | ||||
function debugAgain(JobID,debugUrl){ | |||||
if($('#' + JobID+ '-text').text()==="RUNNING"){ | |||||
window.open(debugUrl+'debug') | |||||
}else{ | |||||
$.ajax({ | |||||
type:"POST", | |||||
url:debugUrl+'restart', | |||||
data:$('#debugAgainForm-'+JobID).serialize(), | |||||
success:function(res){ | |||||
if(res.result_code==="0"){ | |||||
if(res.job_id!==JobID){ | |||||
location.reload() | |||||
}else{ | |||||
$('#' + JobID+'-icon').removeClass().addClass(res.status) | |||||
$('#' + JobID+ '-text').text(res.status) | |||||
$('#model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||||
$('#model-delete-'+JobID).removeClass('blue').addClass('disabled') | |||||
$('#model-debug-'+JobID).text("调试").css("margin","0 1rem") | |||||
} | |||||
}else{ | |||||
$('.alert').html(res.error_msg).removeClass('alert-success').addClass('alert-danger').show().delay(2000).fadeOut(); | |||||
} | |||||
}, | |||||
error :function(res){ | |||||
console.log(res) | |||||
} | |||||
}) | |||||
} | |||||
} | |||||
function stopDebug(JobID,stopUrl){ | |||||
$.ajax({ | |||||
type:"POST", | |||||
url:stopUrl, | |||||
data:$('#stopForm-'+JobID).serialize(), | |||||
success:function(res){ | |||||
if(res.result_code==="0"){ | |||||
$('#' + JobID+'-icon').removeClass().addClass(res.status) | |||||
$('#' + JobID+ '-text').text(res.status) | |||||
if(res.status==="STOPPED"){ | |||||
$('#model-debug-'+JobID).removeClass('disabled').addClass('blue').text("再次调试").css("margin","0") | |||||
$('#model-image-'+JobID).removeClass('blue').addClass('disabled') | |||||
$('#stop-model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||||
$('#model-delete-'+JobID).removeClass('disabled').addClass('blue') | |||||
} | |||||
else{ | |||||
$('#model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||||
$('#stop-model-debug-'+JobID).removeClass('blue').addClass('disabled') | |||||
} | |||||
}else{ | |||||
$('.alert').html(res.error_msg).removeClass('alert-success').addClass('alert-danger').show().delay(2000).fadeOut(); | |||||
} | |||||
}, | |||||
error :function(res){ | |||||
console.log(res) | |||||
} | |||||
}) | |||||
} | |||||
// 加载任务状态 | // 加载任务状态 | ||||
var timeid = window.setInterval(loadJobStatus, 15000); | var timeid = window.setInterval(loadJobStatus, 15000); | ||||
$(document).ready(loadJobStatus); | $(document).ready(loadJobStatus); | ||||
@@ -508,8 +606,9 @@ | |||||
const jobID = job.dataset.jobid; | const jobID = job.dataset.jobid; | ||||
const repoPath = job.dataset.repopath; | const repoPath = job.dataset.repopath; | ||||
const computeResource = job.dataset.resource | const computeResource = job.dataset.resource | ||||
const initArray = ['STOPPED','FAILED','START_FAILED','CREATE_FAILED'] | |||||
const initArray = ['STOPPED','FAILED','START_FAILED','CREATE_FAILED','SUCCEEDED'] | |||||
if (initArray.includes(job.textContent.trim())) { | if (initArray.includes(job.textContent.trim())) { | ||||
return | return | ||||
} | } | ||||
const diffResource = computeResource == "NPU" ? 'modelarts/notebook' : 'cloudbrain' | const diffResource = computeResource == "NPU" ? 'modelarts/notebook' : 'cloudbrain' | ||||
@@ -521,32 +620,30 @@ | |||||
$('#' + jobID+ '-text').text(status) | $('#' + jobID+ '-text').text(status) | ||||
} | } | ||||
if(status==="RUNNING"){ | if(status==="RUNNING"){ | ||||
$('#model-debug-'+jobID).removeClass('disabled') | |||||
$('#model-debug-'+jobID).addClass('blue') | |||||
$('#model-image-'+jobID).removeClass('disabled') | |||||
$('#model-image-'+jobID).addClass('blue') | |||||
$('#model-debug-'+jobID).removeClass('disabled').addClass('blue').text('调试').css("margin","0 1rem") | |||||
$('#model-image-'+jobID).removeClass('disabled').addClass('blue') | |||||
} | } | ||||
if(status!=="RUNNING"){ | if(status!=="RUNNING"){ | ||||
$('#model-debug-'+jobID).removeClass('blue') | |||||
$('#model-debug-'+jobID).addClass('disabled') | |||||
$('#model-image-'+jobID).removeClass('blue') | |||||
$('#model-image-'+jobID).addClass('disabled') | |||||
// $('#model-debug-'+jobID).removeClass('blue') | |||||
// $('#model-debug-'+jobID).addClass('disabled') | |||||
$('#model-image-'+jobID).removeClass('blue').addClass('disabled') | |||||
} | |||||
if(["CREATING","STOPPING","WAITING","STARTING"].includes(status)){ | |||||
$('#model-debug-'+jobID).removeClass('blue').addClass('disabled') | |||||
} | |||||
if(['STOPPED','FAILED','START_FAILED','CREATE_FAILED','SUCCEEDED'].includes(status)){ | |||||
$('#model-debug-'+jobID).removeClass('disabled').addClass('blue').text('再次调试').css("margin","0") | |||||
} | } | ||||
if(["RUNNING","WAITING"].includes(status)){ | if(["RUNNING","WAITING"].includes(status)){ | ||||
$('#stop-model-debug-'+jobID).removeClass('disabled') | |||||
$('#stop-model-debug-'+jobID).addClass('blue') | |||||
$('#stop-model-debug-'+jobID).removeClass('disabled').addClass('blue') | |||||
} | } | ||||
if(["CREATING","STOPPING","STARTING","STOPPED","FAILED","START_FAILED"].includes(status)){ | |||||
$('#stop-model-debug-'+jobID).removeClass('blue') | |||||
$('#stop-model-debug-'+jobID).addClass('disabled') | |||||
if(["CREATING","STOPPING","STARTING","STOPPED","FAILED","START_FAILED","SUCCEEDED"].includes(status)){ | |||||
$('#stop-model-debug-'+jobID).removeClass('blue').addClass('disabled') | |||||
} | } | ||||
if(status==="STOPPED" || status==="FAILED"|| status==="START_FAILED"){ | if(status==="STOPPED" || status==="FAILED"|| status==="START_FAILED"){ | ||||
$('#model-delete-'+jobID).removeClass('disabled') | |||||
$('#model-delete-'+jobID).addClass('blue') | |||||
$('#model-delete-'+jobID).removeClass('disabled').addClass('blue') | |||||
}else{ | }else{ | ||||
$('#model-delete-'+jobID).removeClass('blue') | |||||
$('#model-delete-'+jobID).addClass('disabled') | |||||
$('#model-delete-'+jobID).removeClass('blue').addClass('disabled') | |||||
} | } | ||||
}).fail(function(err) { | }).fail(function(err) { | ||||
console.log(err); | console.log(err); | ||||
@@ -554,6 +651,7 @@ | |||||
}); | }); | ||||
}; | }; | ||||
$(document).ready(function(){ | $(document).ready(function(){ | ||||
dropdownValue = dropdownValue==="CPU%2FGPU"? 'CPU/GPU' : dropdownValue | |||||
$('.default.text').text(dropdownValue) | $('.default.text').text(dropdownValue) | ||||
$('.ui.dropdown') | $('.ui.dropdown') | ||||
.dropdown({ | .dropdown({ | ||||
@@ -564,6 +662,12 @@ | |||||
location.href = `${url}/debugjob?debugListType=${value}` | location.href = `${url}/debugjob?debugListType=${value}` | ||||
} | } | ||||
}) | }) | ||||
$('.message .close') | |||||
.on('click', function() { | |||||
$(this) | |||||
.closest('.message') | |||||
.transition('fade') | |||||
}) | |||||
}) | }) | ||||
@@ -601,7 +705,6 @@ | |||||
// 显示弹窗,弹出相应的信息 | // 显示弹窗,弹出相应的信息 | ||||
function showmask() { | function showmask() { | ||||
var image_tag = !$('#image_tag').val() | var image_tag = !$('#image_tag').val() | ||||
console.log("image_tag",image_tag) | |||||
if(image_tag){ | if(image_tag){ | ||||
return | return | ||||
} | } | ||||
@@ -612,8 +715,6 @@ | |||||
var responseText = $("iframe")[0].contentDocument.body.getElementsByTagName("pre")[0].innerHTML; | var responseText = $("iframe")[0].contentDocument.body.getElementsByTagName("pre")[0].innerHTML; | ||||
var json1 = JSON.parse(responseText) | var json1 = JSON.parse(responseText) | ||||
$('#mask').css('display', 'none') | $('#mask').css('display', 'none') | ||||
parent.location.href | |||||
if (json1.result_code === "0") { | if (json1.result_code === "0") { | ||||
$('.alert').html('操作成功!').removeClass('alert-danger').addClass('alert-success').show().delay(1500).fadeOut(); | $('.alert').html('操作成功!').removeClass('alert-danger').addClass('alert-success').show().delay(1500).fadeOut(); | ||||
} else { | } else { | ||||
@@ -51,7 +51,7 @@ | |||||
</div> | </div> | ||||
{{if not .IsBeingCreated}} | {{if not .IsBeingCreated}} | ||||
<div class="repo-buttons"> | <div class="repo-buttons"> | ||||
<form method="post" action="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}un{{end}}watch?redirect_to={{$.Link}}"> | |||||
<form method="post" style="margin: 0;" action="{{$.RepoLink}}/action/{{if $.IsWatchingRepo}}un{{end}}watch?redirect_to={{$.Link}}"> | |||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
<div class="ui labeled button" tabindex="0"> | <div class="ui labeled button" tabindex="0"> | ||||
<button type="submit" class="ui compact basic button"> | <button type="submit" class="ui compact basic button"> | ||||
@@ -62,7 +62,7 @@ | |||||
</a> | </a> | ||||
</div> | </div> | ||||
</form> | </form> | ||||
<form method="post" action="{{$.RepoLink}}/action/{{if $.IsStaringRepo}}un{{end}}star?redirect_to={{$.Link}}"> | |||||
<form method="post" style="margin: 0;" action="{{$.RepoLink}}/action/{{if $.IsStaringRepo}}un{{end}}star?redirect_to={{$.Link}}"> | |||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
<div class="ui labeled button" tabindex="0"> | <div class="ui labeled button" tabindex="0"> | ||||
<button type="submit" class="ui compact basic button"> | <button type="submit" class="ui compact basic button"> | ||||
@@ -181,4 +181,4 @@ | |||||
</div> | </div> | ||||
<script src="https://cdn.jsdelivr.net/npm/jquery@3.2.1/dist/jquery.min.js"></script> | |||||
<script src="{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}"></script> |
@@ -4,6 +4,7 @@ | |||||
} | } | ||||
.ovfl{ | .ovfl{ | ||||
overflow-y:hidden !important; | overflow-y:hidden !important; | ||||
min-width: 140px!important; | |||||
} | } | ||||
</style> | </style> | ||||
{{template "base/head" .}} | {{template "base/head" .}} | ||||
@@ -121,7 +121,7 @@ | |||||
</div> | </div> | ||||
<!-- 任务运行时间 --> | <!-- 任务运行时间 --> | ||||
<div class="two wide column text center padding0"> | <div class="two wide column text center padding0"> | ||||
<span style="font-size: 12px;" id="duration-{{.JobID}}"></span> | |||||
<span style="font-size: 12px;" id="duration-{{.JobID}}">{{.TrainJobDuration}}</span> | |||||
</div> | </div> | ||||
<!-- 计算资源 --> | <!-- 计算资源 --> | ||||
<div class="two wide column text center padding0"> | <div class="two wide column text center padding0"> | ||||
@@ -253,35 +253,18 @@ | |||||
} | } | ||||
} | } | ||||
function loadJobDuration() { | |||||
$(".job-status").each((index, job) => { | |||||
const jobID = job.dataset.jobid; | |||||
const repoPath = job.dataset.repopath; | |||||
const versionname = job.dataset.version | |||||
$.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}?version_name=${versionname}`, (data) => { | |||||
console.log(data) | |||||
const duration = data.JobDuration | |||||
const jobID = data.JobID | |||||
$('#duration-'+jobID).text(duration) | |||||
}) | |||||
}) | |||||
} | |||||
$(document).ready(loadJobDuration); | |||||
// 加载任务状态 | // 加载任务状态 | ||||
var timeid = window.setInterval(loadJobStatus, 15000); | var timeid = window.setInterval(loadJobStatus, 15000); | ||||
$(document).ready(loadJobStatus); | $(document).ready(loadJobStatus); | ||||
function loadJobStatus() { | function loadJobStatus() { | ||||
$(".job-status").each((index, job) => { | $(".job-status").each((index, job) => { | ||||
const jobID = job.dataset.jobid; | |||||
const repoPath = job.dataset.repopath; | |||||
const jobID = job.dataset.jobid | |||||
const repoPath = job.dataset.repopath | |||||
const versionname = job.dataset.version | const versionname = job.dataset.version | ||||
if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED' | |||||
|| job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED' | |||||
|| job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') { | |||||
return | |||||
const status_text = $(`#${jobID}-text`).text() | |||||
if(['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED'].includes(status_text)){ | |||||
return | |||||
} | } | ||||
$.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}?version_name=${versionname}`, (data) => { | $.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}?version_name=${versionname}`, (data) => { | ||||
const jobID = data.JobID | const jobID = data.JobID | ||||
const status = data.JobStatus | const status = data.JobStatus | ||||
@@ -329,7 +312,6 @@ | |||||
} | } | ||||
} | } | ||||
function stopVersion(version_name,jobID){ | function stopVersion(version_name,jobID){ | ||||
const url = '/api/v1/repos/{{$.RepoRelPath}}/modelarts/train-job/'+jobID+'/stop_version' | const url = '/api/v1/repos/{{$.RepoRelPath}}/modelarts/train-job/'+jobID+'/stop_version' | ||||
$.post(url,{version_name:version_name},(data)=>{ | $.post(url,{version_name:version_name},(data)=>{ | ||||
if(data.StatusOK===0){ | if(data.StatusOK===0){ | ||||
@@ -161,6 +161,15 @@ td, th { | |||||
padding-top: 0.5rem ; | padding-top: 0.5rem ; | ||||
} | } | ||||
</style> | </style> | ||||
<div id="mask"> | |||||
<div id="loadingPage"> | |||||
<div class="rect1"></div> | |||||
<div class="rect2"></div> | |||||
<div class="rect3"></div> | |||||
<div class="rect4"></div> | |||||
<div class="rect5"></div> | |||||
</div> | |||||
</div> | |||||
<div class="repository"> | <div class="repository"> | ||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<div class="ui container"> | <div class="ui container"> | ||||
@@ -186,6 +195,12 @@ td, th { | |||||
<span class="accordion-panel-title-content"> | <span class="accordion-panel-title-content"> | ||||
<span> | <span> | ||||
<div style="float: right;"> | <div style="float: right;"> | ||||
{{$.CsrfTokenHtml}} | |||||
{{if .CanModify}} | |||||
<a class="ti-action-menu-item" onclick="showcreate({{.}})">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||||
{{else}} | |||||
<a class="ti-action-menu-item disabled">{{$.i18n.Tr "repo.modelarts.create_model"}}</a> | |||||
{{end}} | |||||
{{$.CsrfTokenHtml}} | {{$.CsrfTokenHtml}} | ||||
{{if .CanModify}} | {{if .CanModify}} | ||||
<a class="ti-action-menu-item" href="{{$.RepoLink}}/modelarts/train-job/{{.JobID}}/create_version?version_name={{.VersionName}}">{{$.i18n.Tr "repo.modelarts.modify"}}</a> | <a class="ti-action-menu-item" href="{{$.RepoLink}}/modelarts/train-job/{{.JobID}}/create_version?version_name={{.VersionName}}">{{$.i18n.Tr "repo.modelarts.modify"}}</a> | ||||
@@ -446,11 +461,66 @@ td, th { | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<!-- 创建模型 --> | |||||
<div id="newmodel"> | |||||
<div class="ui modal second"> | |||||
<div class="header" style="padding: 1rem;background-color: rgba(240, 240, 240, 100);"> | |||||
<h4 id="model_header">导入新模型</h4> | |||||
</div> | |||||
<div class="content content-padding"> | |||||
<form id="formId" method="POST" class="ui form"> | |||||
<div class="ui error message"> | |||||
</div> | |||||
{{$.CsrfTokenHtml}} | |||||
<input type="hidden" name="trainTaskCreate" value="true"> | |||||
<div class="two inline fields "> | |||||
<div class="required ten wide field"> | |||||
<label style="margin-left: -23px;">选择训练任务</label> | |||||
<input type="hidden" class="width83" id="JobId" name="JobId" readonly required> | |||||
<input class="width83" id="JobName" readonly required> | |||||
</div> | |||||
<div class="required six widde field"> | |||||
<label>版本</label> | |||||
<input class="width70" id="VersionName" name="VersionName" readonly required> | |||||
</div> | |||||
</div> | |||||
<div class="required inline field" id="modelname"> | |||||
<label>模型名称</label> | |||||
<input style="width: 45%;" id="name" name="Name" required maxlength="25" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | |||||
</div> | |||||
<div class="required inline field" id="verionname"> | |||||
<label>模型版本</label> | |||||
<input style="width: 45%;" id="version" name="Version" value="" readonly required maxlength="255"> | |||||
</div> | |||||
<div class="inline field"> | |||||
<label>模型标签</label> | |||||
<input style="width: 83%;margin-left: 7px;" id="label" name="Label" maxlength="255" placeholder='{{.i18n.Tr "repo.modelarts.train_job.label_place"}}'> | |||||
</div> | |||||
<div class="inline field"> | |||||
<label for="description">模型描述</label> | |||||
<textarea style="width: 83%;margin-left: 7px;" id="Description" name="Description" rows="3" maxlength="255" placeholder='{{.i18n.Tr "repo.modelarts.train_job.new_place"}}' onchange="this.value=this.value.substring(0, 255)" onkeydown="this.value=this.value.substring(0, 255)" onkeyup="this.value=this.value.substring(0, 256)"></textarea> | |||||
</div> | |||||
<div class="inline field" style="margin-left: 75px;"> | |||||
<button onclick="createModel()" id="submitId" type="button" class="ui create_train_job green button" style="position: absolute;"> | |||||
{{.i18n.Tr "repo.model.manage.sava_model"}} | |||||
</button> | |||||
</div> | |||||
</form> | |||||
<div class="actions" style="display: inline-block;margin-left: 180px;"> | |||||
<button class="ui button cancel" >{{.i18n.Tr "repo.cloudbrain.cancel"}}</button> | |||||
</div> | |||||
</div> | |||||
</div> | |||||
</div> | </div> | ||||
{{template "base/footer" .}} | {{template "base/footer" .}} | ||||
<script> | <script> | ||||
console.log({{.version_list_task}}) | |||||
$('.menu .item').tab() | $('.menu .item').tab() | ||||
$(document).ready(function(){ | $(document).ready(function(){ | ||||
@@ -480,7 +550,61 @@ td, th { | |||||
} | } | ||||
let timeid = window.setInterval(loadJobStatus, 30000); | let timeid = window.setInterval(loadJobStatus, 30000); | ||||
$(document).ready(loadJobStatus); | $(document).ready(loadJobStatus); | ||||
function showcreate(obj){ | |||||
$('.ui.modal.second') | |||||
.modal({ | |||||
centered: false, | |||||
onShow:function(){ | |||||
$('input[name="Version"]').addClass('model_disabled') | |||||
// $('input[name="JobId"]').text(obj.JobName) | |||||
$('#JobName').val(obj.JobName).addClass('model_disabled') | |||||
$('input[name="JobId"]').val(obj.JobID) | |||||
$('input[name="VersionName"]').val(obj.VersionName).addClass('model_disabled') | |||||
$('.ui.dimmer').css({"background-color":"rgb(136, 136, 136,0.7)"}) | |||||
createModelName() | |||||
}, | |||||
onHide:function(){ | |||||
document.getElementById("formId").reset(); | |||||
$('.ui.dimmer').css({"background-color":""}) | |||||
$('.ui.error.message').text() | |||||
$('.ui.error.message').css('display','none') | |||||
} | |||||
}) | |||||
.modal('show') | |||||
} | |||||
function createModel(){ | |||||
let url_href = `/${userName}/${repoPath}/modelmanage/create_new_model` | |||||
let data = $("#formId").serialize() | |||||
$("#mask").css({"display":"block","z-index":"9999"}) | |||||
$.ajax({ | |||||
url:url_href, | |||||
type:'POST', | |||||
data:data, | |||||
success:function(res){ | |||||
location.href=`/${userName}/${repoPath}/modelmanage/show_model` | |||||
$('.ui.modal.second').modal('hide') | |||||
}, | |||||
error: function(xhr){ | |||||
// 隐藏 loading | |||||
// 只有请求不正常(状态码不为200)才会执行 | |||||
$('.ui.error.message').text(xhr.responseText) | |||||
$('.ui.error.message').css('display','block') | |||||
}, | |||||
complete:function(xhr){ | |||||
$("#mask").css({"display":"none","z-index":"1"}) | |||||
} | |||||
}) | |||||
} | |||||
function createModelName(){ | |||||
let repoName = location.pathname.split('/')[2] | |||||
let modelName = repoName + '_model_' + Math.random().toString(36).substr(2, 4) | |||||
$('#name').val(modelName) | |||||
$('#version').val("0.0.1") | |||||
} | |||||
function renderSize(value){ | function renderSize(value){ | ||||
if(null==value||value==''){ | if(null==value||value==''){ | ||||
return "0 Bytes"; | return "0 Bytes"; | ||||
@@ -495,14 +619,19 @@ td, th { | |||||
} | } | ||||
function loadJobStatus() { | function loadJobStatus() { | ||||
$(".ui.accordion.border-according").each((index, job) => { | $(".ui.accordion.border-according").each((index, job) => { | ||||
const jobID = job.dataset.jobid; | const jobID = job.dataset.jobid; | ||||
const repoPath = job.dataset.repopath; | const repoPath = job.dataset.repopath; | ||||
const versionname = job.dataset.version | const versionname = job.dataset.version | ||||
if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED' | |||||
|| job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED' | |||||
|| job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') { | |||||
return | |||||
// ['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED'] | |||||
// if (job.textContent.trim() == 'IMAGE_FAILED' || job.textContent.trim() == 'SUBMIT_FAILED' || job.textContent.trim() == 'DELETE_FAILED' | |||||
// || job.textContent.trim() == 'KILLED' || job.textContent.trim() == 'COMPLETED' || job.textContent.trim() == 'FAILED' | |||||
// || job.textContent.trim() == 'CANCELED' || job.textContent.trim() == 'LOST') { | |||||
// return | |||||
// } | |||||
let status = $(`#${versionname}-status-span`).text() | |||||
if(['IMAGE_FAILED','SUBMIT_FAILED','DELETE_FAILED','KILLED','COMPLETED','FAILED','CANCELED','LOST','START_FAILED'].includes(status)){ | |||||
return | |||||
} | } | ||||
let stopArray=["KILLED","FAILED","START_FAILED","KILLING","COMPLETED"] | let stopArray=["KILLED","FAILED","START_FAILED","KILLING","COMPLETED"] | ||||
$.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}?version_name=${versionname}`, (data) => { | $.get(`/api/v1/repos/${repoPath}/modelarts/train-job/${jobID}?version_name=${versionname}`, (data) => { | ||||
@@ -663,7 +792,12 @@ td, th { | |||||
html += "</span>" | html += "</span>" | ||||
html += "</td>" | html += "</td>" | ||||
html += "<td class='message seven wide'>" | html += "<td class='message seven wide'>" | ||||
html += "<span class='truncate has-emoji'>"+ `${dirs_size}` + "</span>" | |||||
if(data.Dirs[i].IsDir){ | |||||
html += "<span class='truncate has-emoji'></span>" | |||||
}else{ | |||||
html += "<span class='truncate has-emoji'>"+ `${dirs_size}` + "</span>" | |||||
} | |||||
html += "</td>" | html += "</td>" | ||||
html += "<td class='text right age three wide'>" | html += "<td class='text right age three wide'>" | ||||
@@ -17,16 +17,30 @@ | |||||
<div class="repository release dataset-list view"> | <div class="repository release dataset-list view"> | ||||
{{template "repo/header" .}} | {{template "repo/header" .}} | ||||
<!-- 列表容器 --> | <!-- 列表容器 --> | ||||
<div class="ui container active loader" id="loadContainer"> | |||||
<div class="ui container {{if ne $.MODEL_COUNT 0}}active loader {{end}}" id="loadContainer"> | |||||
{{template "base/alert" .}} | {{template "base/alert" .}} | ||||
<div class="ui two column stackable grid" style="display: none;"> | |||||
<div class="ui two column stackable grid"> | |||||
<div class="column"></div> | <div class="column"></div> | ||||
<div class="column right aligned"> | <div class="column right aligned"> | ||||
<!-- --> | <!-- --> | ||||
<a class="ui button {{if .Permission.CanWrite $.UnitTypeCloudBrain}} green {{else}} disabled {{end}}" onclick="showcreate(this)">{{$.i18n.Tr "repo.model.manage.import_new_model"}}</a> | <a class="ui button {{if .Permission.CanWrite $.UnitTypeCloudBrain}} green {{else}} disabled {{end}}" onclick="showcreate(this)">{{$.i18n.Tr "repo.model.manage.import_new_model"}}</a> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
{{if eq $.MODEL_COUNT 0}} | |||||
<div class="ui placeholder segment bgtask-none"> | |||||
<div class="ui icon header bgtask-header-pic"></div> | |||||
<div class="bgtask-content-header">未创建过模型</div> | |||||
<div class="bgtask-content"> | |||||
{{if $.RepoIsEmpty}} | |||||
<div class="bgtask-content-txt">代码版本:您还没有初始化代码仓库,请先<a href="{{.RepoLink}}">创建代码版本;</a></div> | |||||
{{end}} | |||||
{{if eq $.TRAIN_COUNT 0}} | |||||
<div class="bgtask-content-txt">训练任务:您还没创建过训练任务,请先创建<a href="{{.RepoLink}}/modelarts/train-job">训练任务</a>。</div> | |||||
{{end}} | |||||
<div class="bgtask-content-txt">使用说明:可以参考启智AI协作平台<a href="https://git.openi.org.cn/zeizei/OpenI_Learning">小白训练营课程。</a></div> | |||||
</div> | |||||
</div> | |||||
{{else}} | |||||
<!-- 中下列表展示区 --> | <!-- 中下列表展示区 --> | ||||
<div class="ui grid" style="display: none;"> | <div class="ui grid" style="display: none;"> | ||||
<div class="row" style="padding-top: 0;"> | <div class="row" style="padding-top: 0;"> | ||||
@@ -38,6 +52,7 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
{{end}} | |||||
</div> | </div> | ||||
@@ -89,7 +104,6 @@ | |||||
<div class="menu" id="job-name"> | <div class="menu" id="job-name"> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="required six widde field"> | <div class="required six widde field"> | ||||
<label>版本</label> | <label>版本</label> | ||||
@@ -103,7 +117,6 @@ | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
<div class="required inline field" id="modelname"> | <div class="required inline field" id="modelname"> | ||||
<label>模型名称</label> | <label>模型名称</label> | ||||
<input style="width: 45%;" id="name" name="Name" required maxlength="25" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | <input style="width: 45%;" id="name" name="Name" required maxlength="25" onkeyup="this.value=this.value.replace(/[, ]/g,'')"> | ||||
@@ -141,7 +154,6 @@ | |||||
<script> | <script> | ||||
let repolink = {{.RepoLink}} | let repolink = {{.RepoLink}} | ||||
let repoId = {{$repository}} | let repoId = {{$repository}} | ||||
let url_href = window.location.pathname.split('show_model')[0] + 'create_model' | |||||
const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config; | const {_AppSubUrl, _StaticUrlPrefix, csrf} = window.config; | ||||
$('input[name="_csrf"]').val(csrf) | $('input[name="_csrf"]').val(csrf) | ||||
@@ -69,7 +69,7 @@ | |||||
<!-- <a href="javascript:window.history.back();"><i class="arrow left icon"></i>返回</a> --> | <!-- <a href="javascript:window.history.back();"><i class="arrow left icon"></i>返回</a> --> | ||||
<div class="ui breadcrumb"> | <div class="ui breadcrumb"> | ||||
<a class="section" href="{{$.RepoLink}}/modelmanage/show_model"> | <a class="section" href="{{$.RepoLink}}/modelmanage/show_model"> | ||||
模型管理 | |||||
{{$.i18n.Tr "repo.model.manage.model_manage"}} | |||||
</a> | </a> | ||||
<div class="divider"> / </div> | <div class="divider"> / </div> | ||||
<div class="active section">{{.name}}</div> | <div class="active section">{{.name}}</div> | ||||
@@ -78,67 +78,121 @@ | |||||
</select> | </select> | ||||
</h4> | </h4> | ||||
<div id="showInfo" style="border:1px solid #e2e2e2;padding: 20px 60px;margin-top:24px"> | <div id="showInfo" style="border:1px solid #e2e2e2;padding: 20px 60px;margin-top:24px"> | ||||
<div class="half-table"> | |||||
<span class="model_header_text">基本信息</span> | |||||
<table class="tableStyle" style="margin-top:20px;"> | |||||
<tbody> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">模型名称</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="ModelName" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">版本</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="Version" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">标签</td> | |||||
<td class="ti-text-form-content"> | |||||
<div id="Label" style="overflow: hidden;width: 95%;"> | |||||
<div class="ui pointing secondary menu" style="border-bottom: 1px solid rgba(34,36,38,.15);"> | |||||
<a class="active item" data-tab="first">{{$.i18n.Tr "repo.modelarts.train_job.config"}}</a> | |||||
<a class="item" data-tab="second">{{$.i18n.Tr "repo.model_download"}}</a> | |||||
</div> | |||||
<div class="ui tab active" data-tab="first"> | |||||
<div class="half-table"> | |||||
<span class="model_header_text">基本信息</span> | |||||
<table class="tableStyle" style="margin-top:20px;"> | |||||
<tbody> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.model_name"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="ModelName" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.version"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="Version" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.migrate_items_labels"}}</td> | |||||
<td class="ti-text-form-content"> | |||||
<div id="Label" style="overflow: hidden;width: 95%;"> | |||||
</div> | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">大小</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="Size" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">创建时间</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="CreateTime" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">模型描述</td> | |||||
<td class="ti-text-form-content" ><div id="edit-td" style="display:flex"><span id="Description" title="" class="iword-elipsis"></span><i id="edit-pencil" data-id="" data-desc="" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div></td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.model_size"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="Size" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.createtime"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="CreateTime" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.description"}}</td> | |||||
<td class="ti-text-form-content" > | |||||
<div id="edit-td" style="display:flex"> | |||||
<span id="Description" title="" class="iword-elipsis"></span> | |||||
<i id="edit-pencil" data-id="" data-desc="" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></i> | |||||
</div> | |||||
</td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.code_version"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="CodeBranch" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.start_file"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="BootFile" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.train_dataset"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="DatasetName" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.run_parameter"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="Parameters" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.AI_driver"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="EngineName" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.standard"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="FlavorName" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.modelarts.train_job.compute_node"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="WorkServerNumber" title=""></span></td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
<div class="half-table"> | |||||
<span class="model_header_text">{{$.i18n.Tr "repo.model.manage.model_accuracy"}}</span> | |||||
<table class="tableStyle" style="margin-top:20px;"> | |||||
<tbody> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Accuracy"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="Accuracy" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">F1</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="F1" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Precision"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="Precision" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">{{$.i18n.Tr "repo.model.manage.Recall"}}</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="Recall" title=""></span></td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
</div> | |||||
<div style="clear: both;"></div> | |||||
</div> | </div> | ||||
<div class="half-table"> | |||||
<span class="model_header_text">模型精度</span> | |||||
<table class="tableStyle" style="margin-top:20px;"> | |||||
<tbody> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">准确率</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="Accuracy" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">F1</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="F1" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">精确率</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="Precision" title=""></span></td> | |||||
</tr> | |||||
<tr> | |||||
<td class="ti-text-form-label text-width80">召回率</td> | |||||
<td class="ti-text-form-content word-elipsis"><span id="Recall" title=""></span></td> | |||||
</tr> | |||||
</tbody> | |||||
</table> | |||||
<div class="ui tab" data-tab="second"> | |||||
<input type="hidden" name="model" value="-1"> | |||||
<input type="hidden" name="modelback" value="-1"> | |||||
<div class='ui breadcrumb model_file_bread' id='file_breadcrumb'> | |||||
<div class="active section"></div> | |||||
<div class="divider"> / </div> | |||||
</div> | |||||
<div id="dir_list"> | |||||
</div> | |||||
</div> | </div> | ||||
<div style="clear: both;"></div> | |||||
</div> | </div> | ||||
</div> | </div> | ||||
</div> | </div> | ||||
@@ -146,6 +200,9 @@ | |||||
<script> | <script> | ||||
let url = location.href.split('show_model')[0] | let url = location.href.split('show_model')[0] | ||||
let ID = location.search.split('?name=').pop() | let ID = location.search.split('?name=').pop() | ||||
$(document).ready(function(){ | |||||
$('.secondary.menu .item').tab(); | |||||
}); | |||||
$(document).ready(loadInfo); | $(document).ready(loadInfo); | ||||
function changeInfo(version){ | function changeInfo(version){ | ||||
$.get(`${url}show_model_info_api?name=${ID}`,(data)=>{ | $.get(`${url}show_model_info_api?name=${ID}`,(data)=>{ | ||||
@@ -155,7 +212,9 @@ function changeInfo(version){ | |||||
let returnArray = [] | let returnArray = [] | ||||
returnArray = transObj(versionData) | returnArray = transObj(versionData) | ||||
let [initObj,initModelAcc,id] = returnArray | let [initObj,initModelAcc,id] = returnArray | ||||
editorCancel('','') | |||||
renderInfo(initObj,initModelAcc,id) | renderInfo(initObj,initModelAcc,id) | ||||
loadModelFile(versionData[0].ID,versionData[0].Version,'','','init') | |||||
}) | }) | ||||
} | } | ||||
function loadInfo(){ | function loadInfo(){ | ||||
@@ -172,11 +231,17 @@ function loadInfo(){ | |||||
returnArray = transObj(data) | returnArray = transObj(data) | ||||
let [initObj,initModelAcc,id] = returnArray | let [initObj,initModelAcc,id] = returnArray | ||||
renderInfo(initObj,initModelAcc,id) | renderInfo(initObj,initModelAcc,id) | ||||
loadModelFile(data[0].ID,data[0].Version,'','','init') | |||||
}) | }) | ||||
} | } | ||||
function transObj(data){ | function transObj(data){ | ||||
let {ID,Name,Version,Label,Size,Description,CreatedUnix,Accuracy} = data[0] | |||||
let {ID,Name,Version,Label,Size,Description,CreatedUnix,Accuracy,CodeBranch,CodeCommitID,TrainTaskInfo} = data[0] | |||||
let modelAcc = JSON.parse(Accuracy) | let modelAcc = JSON.parse(Accuracy) | ||||
TrainTaskInfo = JSON.parse(TrainTaskInfo) | |||||
// Parameters = JSON.parse(Parameters) | |||||
let {Parameters,EngineName} = TrainTaskInfo | |||||
Parameters = JSON.parse(Parameters) | |||||
Parameters = Parameters.parameter.length === 0 ? '--':Parameters.parameter | |||||
let size = tranSize(Size) | let size = tranSize(Size) | ||||
let time = transTime(CreatedUnix) | let time = transTime(CreatedUnix) | ||||
let initObj = { | let initObj = { | ||||
@@ -186,6 +251,15 @@ function transObj(data){ | |||||
Size:size, | Size:size, | ||||
CreateTime:time, | CreateTime:time, | ||||
Description:Description || '--', | Description:Description || '--', | ||||
CodeBranch:CodeBranch || '--', | |||||
CodeCommitID:CodeCommitID || '--', | |||||
BootFile:TrainTaskInfo.BootFile || '--', | |||||
DatasetName:TrainTaskInfo.DatasetName || '--', | |||||
Parameters:TrainTaskInfo.Parameters || '--', | |||||
FlavorName:TrainTaskInfo.FlavorName || '--', | |||||
WorkServerNumber:TrainTaskInfo.WorkServerNumber || '--', | |||||
Parameters:Parameters, | |||||
EngineName:EngineName, | |||||
} | } | ||||
let initModelAcc = { | let initModelAcc = { | ||||
Accuracy: modelAcc.Accuracy || '--', | Accuracy: modelAcc.Accuracy || '--', | ||||
@@ -221,15 +295,16 @@ function tranSize(value){ | |||||
function editorFn(context){ | function editorFn(context){ | ||||
let id= context.dataset.id | let id= context.dataset.id | ||||
let text = context.dataset.desc | let text = context.dataset.desc | ||||
console.log(id,text) | |||||
$('#edit-td').replaceWith("<div id='edit-div' style='width:80%;display: inline-block;'><textarea id='textarea-value' value='' rows='3' maxlength='255' style='width:80%;' id='edit-text'>"+text+"</textarea><i class='check icon' style='color: #50d4ab;' onclick='editorSure(\"" + text + "\",\"" + id + "\")'></i><i class='times icon' style='color: #f66f6a;' onclick='editorCancel(\"" + text + "\",\"" + id + "\")'></i></div>"); | |||||
let textValue = text.replace(/enter;/g,'\r\n') | |||||
$('#edit-td').replaceWith(`<div id='edit-div' style='width:80%;display: inline-block;'><textarea id='textarea-value' value='' rows='3' maxlength='255' style='width:80%;white-space: nowrap;' id='edit-text'>${textValue}</textarea><i class='check icon' style='color: #50d4ab;' onclick='editorSure("${text}","${id}")'></i><i class='times icon' style='color: #f66f6a;' onclick='editorCancel("${text}","${id}")'></i></div>`); | |||||
} | } | ||||
function editorCancel(text,id){ | function editorCancel(text,id){ | ||||
$('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${text}" class="iword-elipsis">${text}</span><i id="edit-pencil" data-id="${id}" data-desc="${text}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||||
let objkey = text.replace(/enter;/g,'\r\n') | |||||
$('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${objkey}" class="iword-elipsis">${objkey}</span><i id="edit-pencil" data-id="${id}" data-desc="${text}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||||
} | } | ||||
function editorSure(text,id){ | function editorSure(text,id){ | ||||
let description=$('#textarea-value').val() | let description=$('#textarea-value').val() | ||||
let sourcetext = $('#textarea-value').val().replace(/\n/g,'enter;') | |||||
let data = { | let data = { | ||||
ID:id, | ID:id, | ||||
Description:description | Description:description | ||||
@@ -239,16 +314,17 @@ function editorSure(text,id){ | |||||
type:'PUT', | type:'PUT', | ||||
data:data | data:data | ||||
}).done((res)=>{ | }).done((res)=>{ | ||||
$('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${description}" class="iword-elipsis">${description}</span><i id="edit-pencil" data-id="${id}" data-desc="${description}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||||
$('#edit-div').replaceWith(`<div id="edit-td" style="display:flex;"><span id="Description" title="${description}" class="iword-elipsis">${description}</span><i id="edit-pencil" data-id="${id}" data-desc="${sourcetext}" class="pencil alternate icon" style="cursor:pointer;vertical-align: top;" id="editor" onclick="editorFn(this)"></div>`) | |||||
}) | }) | ||||
} | } | ||||
function renderInfo(obj,accObj,id){ | function renderInfo(obj,accObj,id){ | ||||
for(let key in obj){ | for(let key in obj){ | ||||
if(key==="Description"){ | if(key==="Description"){ | ||||
let descriptionText=obj[key].replace(/\r\n|\n/g,'enter;') | |||||
$(`#${key}`).text(obj[key]) | $(`#${key}`).text(obj[key]) | ||||
$(`#${key}`).attr("title",obj[key]) | $(`#${key}`).attr("title",obj[key]) | ||||
$('#edit-pencil').attr("data-id",id) | $('#edit-pencil').attr("data-id",id) | ||||
$('#edit-pencil').attr("data-desc",obj[key]) | |||||
$('#edit-pencil').attr("data-desc",descriptionText) | |||||
} | } | ||||
else if(key==="Label"){ | else if(key==="Label"){ | ||||
$('#Label').empty() | $('#Label').empty() | ||||
@@ -264,6 +340,25 @@ function renderInfo(obj,accObj,id){ | |||||
$('#Label').append(html) | $('#Label').append(html) | ||||
} | } | ||||
} | } | ||||
else if(key==="CodeCommitID"){ | |||||
let codeCommit = obj[key].slice(0,10) | |||||
let html = `<a style="margin-left:1rem" class="ui label" title="${codeCommit}">${codeCommit}</a>` | |||||
$('#CodeBranch').append(html) | |||||
} | |||||
else if(key==="Parameters"){ | |||||
if(obj[key]==='--'){ | |||||
$(`#${key}`).text(obj[key]) | |||||
}else{ | |||||
const parameterArray = obj[key].map(element => { | |||||
let labelValue = `${element.label}=${element.value}` | |||||
return labelValue | |||||
}); | |||||
const parameter = parameterArray.join('; ') | |||||
$(`#${key}`).text(parameter) | |||||
$(`#${key}`).attr("title",parameter) | |||||
} | |||||
} | |||||
else{ | else{ | ||||
$(`#${key}`).text(obj[key]) | $(`#${key}`).text(obj[key]) | ||||
$(`#${key}`).attr("title",obj[key]) | $(`#${key}`).attr("title",obj[key]) | ||||
@@ -276,4 +371,108 @@ function renderInfo(obj,accObj,id){ | |||||
} | } | ||||
} | } | ||||
function loadModelFile(ID,version_name,parents,filename,init){ | |||||
$.get(`${url}query_onelevel_modelfile?ID=${ID}&parentDir=${parents}`, (data) => { | |||||
$('#dir_list').empty() | |||||
renderDir(data,ID,version_name) | |||||
if(init==="init"){ | |||||
$('input[name=model]').val("") | |||||
$('input[name=modelback]').val(version_name) | |||||
$('#file_breadcrumb').empty() | |||||
let htmlBread = "" | |||||
htmlBread += `<div class='active section'>${version_name}</div>` | |||||
htmlBread += "<div class='divider'> / </div>" | |||||
$('#file_breadcrumb').append(htmlBread) | |||||
}else{ | |||||
renderBrend(ID,version_name,parents,filename,init) | |||||
} | |||||
}) | |||||
} | |||||
function renderSize(value){ | |||||
if(null==value||value==''){ | |||||
return "0 Bytes"; | |||||
} | |||||
var unitArr = new Array("Bytes","KB","MB","GB","TB","PB","EB","ZB","YB"); | |||||
var index=0; | |||||
var srcsize = parseFloat(value); | |||||
index=Math.floor(Math.log(srcsize)/Math.log(1024)); | |||||
var size =srcsize/Math.pow(1024,index); | |||||
size=size.toFixed(2);//保留的小数位数 | |||||
return size+unitArr[index]; | |||||
} | |||||
function renderBrend(ID,version_name,parents,filename,init){ | |||||
if(init=="folder"){ | |||||
let htmlBrend = "" | |||||
let sectionName=$('#file_breadcrumb .active.section').text() | |||||
let parents1 = $('input[name=model]').val() | |||||
let filename1 = $('input[name=modelback]').val() | |||||
if(parents1===""){ | |||||
$('#file_breadcrumb .active.section').replaceWith(`<a class='section' onclick="loadModelFile('${ID}','${version_name}','${parents1}','','init')">${sectionName}</a>`) | |||||
}else{ | |||||
$('#file_breadcrumb .active.section').replaceWith(`<a class='section' onclick="loadModelFile('${ID}','${version_name}','${parents1}','${filename1}')">${sectionName}</a>`) | |||||
} | |||||
htmlBrend += `<div class='active section'>${filename}</div>` | |||||
htmlBrend += "<div class='divider'> / </div>" | |||||
$('#file_breadcrumb').append(htmlBrend) | |||||
$('input[name=model]').val(parents) | |||||
$('input[name=modelback]').val(filename) | |||||
}else{ | |||||
$('input[name=model]').val(parents) | |||||
$('input[name=modelbac]').val(filename) | |||||
$('#file_breadcrumb a.section:contains(${filename})').nextAll().remove() | |||||
$('#file_breadcrumb a.section:contains(${filename})').replaceWith(`<div class='active section'>${filename}</div>`) | |||||
$('#file_breadcrumb div.section:contains(${filename})').append("<div class='divider'> / </div>") | |||||
} | |||||
} | |||||
function renderDir(data,ID,version_name){ | |||||
let html="" | |||||
html += "<div class='ui grid' style='margin:0;'>" | |||||
html += "<div class='row' style='padding: 0;'>" | |||||
html += "<div class='ui sixteen wide column' style='padding:1rem;'>" | |||||
html += "<div class='dir list'>" | |||||
html += "<table id='repo-files-table' class='ui single line table pad20'>" | |||||
html += '<tbody>' | |||||
for(let i=0;i<data.length;i++){ | |||||
let dirs_size = renderSize(data[i].Size) | |||||
html += "<tr>" | |||||
html += "<td class='name six wid'>" | |||||
html += "<span class='truncate'>" | |||||
html += "<span class='octicon octicon-file-directory'>" | |||||
html += "</span>" | |||||
if(data[i].IsDir){ | |||||
html += `<a onclick="loadModelFile('${ID}','${version_name}','${data[i].ParenDir}','${data[i].FileName}','folder')">` | |||||
html += "<span class='fitted'><i class='folder icon' width='16' height='16' aria-hidden='true'></i>" + data[i].FileName + "</span>" | |||||
}else{ | |||||
html += `<a href="${url}${ID}/downloadsingle?parentDir=${data[i].ParenDir}&fileName=${data[i].FileName}">` | |||||
html += "<span class='fitted'><i class='file icon' width='16' height='16' aria-hidden='true'></i>" + data[i].FileName + "</span>" | |||||
} | |||||
html += '</a>' | |||||
html += "</span>" | |||||
html += "</td>" | |||||
html += "<td class='message seven wide'>" | |||||
if(data[i].IsDir){ | |||||
html += "<span class='truncate has-emoji'></span>" | |||||
}else{ | |||||
html += "<span class='truncate has-emoji'>"+ `${dirs_size}` + "</span>" | |||||
} | |||||
html += "</td>" | |||||
html += "<td class='text right age three wide'>" | |||||
html += "<span class='truncate has-emoji'>" + data[i].ModTime + "</span>" | |||||
html += "</td>" | |||||
html += "</tr>" | |||||
} | |||||
html += "</tbody>" | |||||
html += "</table>" | |||||
html += "</div>" | |||||
html += "</div>" | |||||
html += "</div>" | |||||
html += "</div>" | |||||
$('#dir_list').append(html) | |||||
} | |||||
</script> | </script> |
@@ -0,0 +1,12 @@ | |||||
root = true | |||||
[*] | |||||
charset = utf-8 | |||||
end_of_line = lf | |||||
insert_final_newline = true | |||||
trim_trailing_whitespace = true | |||||
[*.go] | |||||
indent_style = tab | |||||
indent_size = 4 | |||||
max_line_length = 80 |
@@ -0,0 +1 @@ | |||||
/.idea |
@@ -0,0 +1,9 @@ | |||||
language: go | |||||
go: | |||||
- 1.11.x | |||||
- 1.12.x | |||||
- master | |||||
script: | |||||
- env GO111MODULE=on go test |
@@ -0,0 +1,21 @@ | |||||
MIT License | |||||
Copyright (c) 2020 Elliot Chance | |||||
Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
of this software and associated documentation files (the "Software"), to deal | |||||
in the Software without restriction, including without limitation the rights | |||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
copies of the Software, and to permit persons to whom the Software is | |||||
furnished to do so, subject to the following conditions: | |||||
The above copyright notice and this permission notice shall be included in all | |||||
copies or substantial portions of the Software. | |||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||||
SOFTWARE. |
@@ -0,0 +1,102 @@ | |||||
# 🔃 github.com/elliotchance/orderedmap [](https://godoc.org/github.com/elliotchance/orderedmap) [](https://travis-ci.org/elliotchance/orderedmap) | |||||
## Installation | |||||
```bash | |||||
go get -u github.com/elliotchance/orderedmap | |||||
``` | |||||
## Basic Usage | |||||
An `*OrderedMap` is a high performance ordered map that maintains amortized O(1) | |||||
for `Set`, `Get`, `Delete` and `Len`: | |||||
```go | |||||
m := orderedmap.NewOrderedMap() | |||||
m.Set("foo", "bar") | |||||
m.Set("qux", 1.23) | |||||
m.Set(123, true) | |||||
m.Delete("qux") | |||||
``` | |||||
Internally an `*OrderedMap` uses a combination of a map and linked list. | |||||
## Iterating | |||||
Be careful using `Keys()` as it will create a copy of all of the keys so it's | |||||
only suitable for a small number of items: | |||||
```go | |||||
for _, key := range m.Keys() { | |||||
value, _:= m.Get(key) | |||||
fmt.Println(key, value) | |||||
} | |||||
``` | |||||
For larger maps you should use `Front()` or `Back()` to iterate per element: | |||||
```go | |||||
// Iterate through all elements from oldest to newest: | |||||
for el := m.Front(); el != nil; el = el.Next() { | |||||
fmt.Println(el.Key, el.Value) | |||||
} | |||||
// You can also use Back and Prev to iterate in reverse: | |||||
for el := m.Back(); el != nil; el = el.Prev() { | |||||
fmt.Println(el.Key, el.Value) | |||||
} | |||||
``` | |||||
The iterator is safe to use bidirectionally, and will return `nil` once it goes | |||||
beyond the first or last item. | |||||
If the map is changing while the iteration is in-flight it may produce | |||||
unexpected behavior. | |||||
## Performance | |||||
CPU: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz | |||||
RAM: 8GB | |||||
System: Windows 10 | |||||
```shell | |||||
$go test -benchmem -run=^$ github.com/elliotchance/orderedmap -bench BenchmarkAll | |||||
``` | |||||
map[int]bool | |||||
| | map | orderedmap | | |||||
| ------- | ------------------- | ------------------- | | |||||
| set | 198 ns/op, 44 B/op | 722 ns/op, 211 B/op | | |||||
| get | 18 ns/op, 0 B/op | 37.3 ns/op, 0 B/op | | |||||
| delete | 888 ns/op, 211 B/op | 280 ns/op, 44 B/op | | |||||
| Iterate | 206 ns/op, 44 B/op | 693 ns/op, 259 B/op | | |||||
map[string]bool(PS : Use strconv.Itoa()) | |||||
| | map | orderedmap | | |||||
| ----------- | ------------------- | ----------------------- | | |||||
| set | 421 ns/op, 86 B/op | 1048 ns/op, 243 B/op | | |||||
| get | 81.1 ns/op, 2 B/op | 97.8 ns/op, 2 B/op | | |||||
| delete | 737 ns/op, 122 B/op | 1188 ns/op, 251 B/op | | |||||
| Iterate all | 14706 ns/op, 1 B/op | 52671 ns/op, 16391 B/op | | |||||
Big map[int]bool (10000000 keys) | |||||
| | map | orderedmap | | |||||
| ----------- | -------------------------------- | ------------------------------- | | |||||
| set all | 1.834559 s/op, 423.9470291 MB/op | 7.5564667 s/op, 1784.1483 MB/op | | |||||
| get all | 2.6367878 s/op, 423.9698 MB/op | 9.0232475 s/op, 1784.1086 MB/op | | |||||
| Iterate all | 1.9526784 s/op, 423.9042 MB/op | 8.2495265 s/op, 1936.7619 MB/op | | |||||
Big map[string]bool (10000000 keys) | |||||
| | map | orderedmap | | |||||
| ----------- | --------------------------------- | ----------------------------------- | | |||||
| set all | 4.8893923 s/op, 921.33435 MB/op | 10.4405527 s/op, 2089.0144 MB/op | | |||||
| get all | 7.122791 s/op, 997.3802643 MB/op | 13.2613692 s/op, 2165.09521 MB/op | | |||||
| Iterate all | 5.1688922 s/op, 921.4619293 MB/op | 12.6623711 s/op, 2241.5272064 MB/op | |
@@ -0,0 +1,33 @@ | |||||
package orderedmap | |||||
import "container/list" | |||||
type Element struct { | |||||
Key, Value interface{} | |||||
element *list.Element | |||||
} | |||||
func newElement(e *list.Element) *Element { | |||||
if e == nil { | |||||
return nil | |||||
} | |||||
element := e.Value.(*orderedMapElement) | |||||
return &Element{ | |||||
element: e, | |||||
Key: element.key, | |||||
Value: element.value, | |||||
} | |||||
} | |||||
// Next returns the next element, or nil if it finished. | |||||
func (e *Element) Next() *Element { | |||||
return newElement(e.element.Next()) | |||||
} | |||||
// Prev returns the previous element, or nil if it finished. | |||||
func (e *Element) Prev() *Element { | |||||
return newElement(e.element.Prev()) | |||||
} |
@@ -0,0 +1,5 @@ | |||||
module github.com/elliotchance/orderedmap | |||||
go 1.12 | |||||
require github.com/stretchr/testify v1.7.0 |
@@ -0,0 +1,15 @@ | |||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= | |||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | |||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= | |||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | |||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= | |||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | |||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= | |||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | |||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
@@ -0,0 +1,150 @@ | |||||
package orderedmap | |||||
import "container/list" | |||||
type orderedMapElement struct { | |||||
key, value interface{} | |||||
} | |||||
type OrderedMap struct { | |||||
kv map[interface{}]*list.Element | |||||
ll *list.List | |||||
} | |||||
func NewOrderedMap() *OrderedMap { | |||||
return &OrderedMap{ | |||||
kv: make(map[interface{}]*list.Element), | |||||
ll: list.New(), | |||||
} | |||||
} | |||||
// Get returns the value for a key. If the key does not exist, the second return | |||||
// parameter will be false and the value will be nil. | |||||
func (m *OrderedMap) Get(key interface{}) (interface{}, bool) { | |||||
value, ok := m.kv[key] | |||||
if ok { | |||||
return value.Value.(*orderedMapElement).value, true | |||||
} | |||||
return nil, false | |||||
} | |||||
// Set will set (or replace) a value for a key. If the key was new, then true | |||||
// will be returned. The returned value will be false if the value was replaced | |||||
// (even if the value was the same). | |||||
func (m *OrderedMap) Set(key, value interface{}) bool { | |||||
_, didExist := m.kv[key] | |||||
if !didExist { | |||||
element := m.ll.PushBack(&orderedMapElement{key, value}) | |||||
m.kv[key] = element | |||||
} else { | |||||
m.kv[key].Value.(*orderedMapElement).value = value | |||||
} | |||||
return !didExist | |||||
} | |||||
// GetOrDefault returns the value for a key. If the key does not exist, returns | |||||
// the default value instead. | |||||
func (m *OrderedMap) GetOrDefault(key, defaultValue interface{}) interface{} { | |||||
if value, ok := m.kv[key]; ok { | |||||
return value.Value.(*orderedMapElement).value | |||||
} | |||||
return defaultValue | |||||
} | |||||
// GetElement returns the element for a key. If the key does not exist, the | |||||
// pointer will be nil. | |||||
func (m *OrderedMap) GetElement(key interface{}) *Element { | |||||
value, ok := m.kv[key] | |||||
if ok { | |||||
element := value.Value.(*orderedMapElement) | |||||
return &Element{ | |||||
element: value, | |||||
Key: element.key, | |||||
Value: element.value, | |||||
} | |||||
} | |||||
return nil | |||||
} | |||||
// Len returns the number of elements in the map. | |||||
func (m *OrderedMap) Len() int { | |||||
return len(m.kv) | |||||
} | |||||
// Keys returns all of the keys in the order they were inserted. If a key was | |||||
// replaced it will retain the same position. To ensure most recently set keys | |||||
// are always at the end you must always Delete before Set. | |||||
func (m *OrderedMap) Keys() (keys []interface{}) { | |||||
keys = make([]interface{}, m.Len()) | |||||
element := m.ll.Front() | |||||
for i := 0; element != nil; i++ { | |||||
keys[i] = element.Value.(*orderedMapElement).key | |||||
element = element.Next() | |||||
} | |||||
return keys | |||||
} | |||||
// Delete will remove a key from the map. It will return true if the key was | |||||
// removed (the key did exist). | |||||
func (m *OrderedMap) Delete(key interface{}) (didDelete bool) { | |||||
element, ok := m.kv[key] | |||||
if ok { | |||||
m.ll.Remove(element) | |||||
delete(m.kv, key) | |||||
} | |||||
return ok | |||||
} | |||||
// Front will return the element that is the first (oldest Set element). If | |||||
// there are no elements this will return nil. | |||||
func (m *OrderedMap) Front() *Element { | |||||
front := m.ll.Front() | |||||
if front == nil { | |||||
return nil | |||||
} | |||||
element := front.Value.(*orderedMapElement) | |||||
return &Element{ | |||||
element: front, | |||||
Key: element.key, | |||||
Value: element.value, | |||||
} | |||||
} | |||||
// Back will return the element that is the last (most recent Set element). If | |||||
// there are no elements this will return nil. | |||||
func (m *OrderedMap) Back() *Element { | |||||
back := m.ll.Back() | |||||
if back == nil { | |||||
return nil | |||||
} | |||||
element := back.Value.(*orderedMapElement) | |||||
return &Element{ | |||||
element: back, | |||||
Key: element.key, | |||||
Value: element.value, | |||||
} | |||||
} | |||||
// Copy returns a new OrderedMap with the same elements. | |||||
// Using Copy while there are concurrent writes may mangle the result. | |||||
func (m *OrderedMap) Copy() *OrderedMap { | |||||
m2 := NewOrderedMap() | |||||
for el := m.Front(); el != nil; el = el.Next() { | |||||
m2.Set(el.Key, el.Value) | |||||
} | |||||
return m2 | |||||
} |
@@ -0,0 +1,9 @@ | |||||
This is a list of people who have contributed code to go-cache. They, or their | |||||
employers, are the copyright holders of the contributed code. Contributed code | |||||
is subject to the license restrictions listed in LICENSE (as they were when the | |||||
code was contributed.) | |||||
Dustin Sallings <dustin@spy.net> | |||||
Jason Mooberry <jasonmoo@me.com> | |||||
Sergey Shepelev <temotor@gmail.com> | |||||
Alex Edwards <ajmedwards@gmail.com> |
@@ -0,0 +1,19 @@ | |||||
Copyright (c) 2012-2017 Patrick Mylund Nielsen and the go-cache contributors | |||||
Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
of this software and associated documentation files (the "Software"), to deal | |||||
in the Software without restriction, including without limitation the rights | |||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||||
copies of the Software, and to permit persons to whom the Software is | |||||
furnished to do so, subject to the following conditions: | |||||
The above copyright notice and this permission notice shall be included in | |||||
all copies or substantial portions of the Software. | |||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |||||
THE SOFTWARE. |