forked from Trustie/forgeplus
Compare commits
573 Commits
master
...
dev_educod
Author | SHA1 | Date |
---|---|---|
|
0c85516a56 | |
|
f4183a42cf | |
|
44dea80793 | |
|
52f386802d | |
|
0656827d86 | |
|
2280bf02ac | |
|
d0cb7eb269 | |
|
7f5e00b516 | |
|
f2a0a22469 | |
|
489385ffae | |
|
b7c8649507 | |
|
4fe7196d40 | |
|
7a7b93c4af | |
|
202d091ff5 | |
|
3f1ffcdb34 | |
|
bdd9885a41 | |
|
3285c89698 | |
|
6afd275814 | |
|
0fb519c963 | |
|
0840f632aa | |
|
59b72f9122 | |
|
1201607a39 | |
|
1ce6070138 | |
|
cb9230a1a5 | |
|
a76079ee8e | |
|
9bd43d80c6 | |
|
f50c9eb9d2 | |
|
89db4e35ac | |
|
9cd4c876ff | |
|
ac1a4cc7b7 | |
|
c475760518 | |
|
88ef03d5d7 | |
|
3470fa262c | |
|
0fa3361e69 | |
|
2191102fa8 | |
|
033d36406e | |
|
6e62aecbbc | |
|
fb44955a5f | |
|
6454c375ed | |
|
534fdec9f2 | |
|
dfa0f1161d | |
|
bc6f5cec4d | |
|
ee27c90205 | |
|
534ee80523 | |
|
daf7514afe | |
|
4b1f1c697e | |
|
77c7acd582 | |
|
025a6a53e9 | |
|
6b846b10bb | |
|
763d7b499e | |
|
9b39446dfb | |
|
c6e77ac7ee | |
|
f5cdb6f02d | |
|
f7ca03db81 | |
|
8da8b021f6 | |
|
70ba78a9b5 | |
|
6191ddd233 | |
|
35cf298f5d | |
|
ee5d959404 | |
|
7f47cd8d46 | |
|
06c0ac65bf | |
|
8f8dab10c3 | |
|
a6923bf7ed | |
![]() |
667dca0553 | |
![]() |
f23f02cb80 | |
|
38a8191b74 | |
|
e183f48c02 | |
![]() |
a1731f91a9 | |
|
ea7cf1cd1f | |
|
255b615327 | |
|
64c6f69f56 | |
|
49abadfa3f | |
|
4cde7c374e | |
|
b56930b9ab | |
|
f98886b3a0 | |
|
30572aa41c | |
|
ef83697cb8 | |
|
570f664c27 | |
|
e24921bba3 | |
|
e4d62c5335 | |
|
6d9cf8aad2 | |
|
e3179dfd6e | |
|
7817487ab7 | |
|
83b46fcb50 | |
![]() |
7cc9d207b6 | |
![]() |
abfb62f342 | |
![]() |
ccbbab0741 | |
|
3e5c1da2c5 | |
|
07aefa79eb | |
|
423d5a9316 | |
|
9664ca001e | |
|
e15809c186 | |
|
7d4c0df691 | |
|
e72dfa4973 | |
|
84a8339a04 | |
|
3d5b2e76d7 | |
|
8b14ee3c72 | |
|
3f7366fbcd | |
|
cfdbc5a682 | |
|
9b880e3209 | |
|
c2ef23b746 | |
|
8a33ea6707 | |
|
9ee4c85b7c | |
|
e9b23d6577 | |
|
64d9c334ce | |
|
cad7e24299 | |
|
3b15dd84fc | |
|
58a43a8b80 | |
|
e25231738a | |
|
35965f542a | |
|
fa48e3f5ca | |
|
13e2738fb5 | |
|
30437d828c | |
|
dcc7ab6738 | |
|
57a7a17f73 | |
|
5196f33f24 | |
![]() |
b3cbed2963 | |
![]() |
dd1af6712c | |
|
8807be6e4d | |
|
8d41c27044 | |
|
53fe554d1e | |
![]() |
4e02dbe06b | |
![]() |
620ddff9bb | |
|
630a7aadeb | |
|
6383384287 | |
|
83f1263f85 | |
|
9c11cd79e8 | |
|
a7384bc1c3 | |
|
55170c7693 | |
|
2cde13eabb | |
|
d68e7f38a3 | |
|
649d9c4ea6 | |
![]() |
fce8166ba7 | |
![]() |
ae0efc1115 | |
![]() |
dfc2edd62d | |
![]() |
fcdbf4ec7f | |
![]() |
1068168968 | |
|
d7f3a21add | |
|
ef9592ef30 | |
|
cc42683316 | |
|
70f1e6827f | |
|
b5188e3272 | |
|
ff881732d2 | |
![]() |
2adf87a289 | |
![]() |
6954a860af | |
![]() |
bb8e6aeaf8 | |
![]() |
6d7b7dd058 | |
|
007b90c284 | |
|
481d1b7db0 | |
|
733f64eaec | |
|
383660c778 | |
|
4bd77a870b | |
|
b1f460d760 | |
|
a438ab6f3e | |
![]() |
3a34d8682c | |
![]() |
60894f00b1 | |
![]() |
925b05e004 | |
|
4878d66620 | |
|
632ade9d25 | |
|
5acd45bf85 | |
|
d03b45eecf | |
![]() |
32a9d762d8 | |
![]() |
0a79950046 | |
![]() |
4b7c58b13f | |
![]() |
7148957368 | |
|
aa50c50254 | |
|
60b3c7925d | |
|
0f41cabe71 | |
![]() |
d04ed7e008 | |
![]() |
7993a89ce3 | |
|
6168256897 | |
|
4b167dacbb | |
|
911c47df8d | |
|
a37d7b9840 | |
![]() |
217ab920a9 | |
![]() |
98ae62d181 | |
![]() |
98f1723411 | |
|
68a38e75bc | |
|
ee29c6be5c | |
|
c0ee0a694c | |
![]() |
25fa6f427b | |
![]() |
467d722d25 | |
|
3e352d3c7c | |
|
13472b2311 | |
![]() |
bdddd655bf | |
![]() |
6ec7a13293 | |
![]() |
716b29c25f | |
![]() |
5c4930a362 | |
![]() |
ad8fed9440 | |
![]() |
964bef7896 | |
![]() |
7e48e5e8b8 | |
![]() |
48846a7e31 | |
|
32db15aad5 | |
![]() |
8ec3e4bbaa | |
|
4b05838498 | |
|
b8be0c23cb | |
|
d20a7b1318 | |
|
f8268accc0 | |
|
a9811768d4 | |
|
024bc289de | |
|
96d34d0237 | |
|
fea11bdc2e | |
|
ab5d273f98 | |
![]() |
8bf4e9b8d2 | |
|
096b0b954d | |
|
df57312056 | |
![]() |
f12cfabee3 | |
![]() |
b22909a654 | |
![]() |
579b45dfa4 | |
![]() |
fbc1f95cd1 | |
![]() |
4ccf8ea5ff | |
|
d5c141f892 | |
|
35c6cb98db | |
|
f417e42864 | |
|
6e54203ebb | |
![]() |
79a6841bbc | |
![]() |
b3d78741a3 | |
|
935f3ddf7f | |
|
a2549f7ff1 | |
|
d6b5dc326a | |
![]() |
003bfe7884 | |
![]() |
df5efa0dc6 | |
|
a35db9fe80 | |
|
6183f1f76d | |
|
e72273f3b2 | |
|
cc09f724cc | |
|
7a54c5f536 | |
![]() |
bb3f5cec76 | |
![]() |
19ffd9fea1 | |
![]() |
5877474f59 | |
![]() |
1bbde165c2 | |
|
3f5754a3a5 | |
|
5463c22518 | |
|
5db43bf768 | |
|
1feb166fd5 | |
|
0df1e5fdd0 | |
|
8ba70a33be | |
![]() |
b21f44b59e | |
![]() |
1c56f21c96 | |
|
7793eacf75 | |
|
25afedcdfd | |
|
d95a689815 | |
|
b386dc51e4 | |
|
1882120df3 | |
|
274cd81655 | |
|
6273349334 | |
|
e8deb83004 | |
|
52701d1c2f | |
|
b248f770f1 | |
|
04b9e43382 | |
|
3580a8653d | |
|
d9653e461e | |
|
d9a1d32ec8 | |
|
b5dfd83527 | |
|
df7b91a8ba | |
|
8dae15225e | |
|
5fcf789e63 | |
|
ed0655452c | |
|
0dd062ce1c | |
|
bd3cbf33fd | |
|
b8d4b15b40 | |
|
24d83133e7 | |
|
4ed3a9d478 | |
|
fbbacfa983 | |
|
d47708dc1c | |
|
625ed024e2 | |
|
60842e64e5 | |
|
993135602f | |
|
35e8f1d423 | |
|
dbea2e1c3d | |
|
f1fdf0c37f | |
|
d0988e42b4 | |
|
ef8f33e1cd | |
|
b380b61873 | |
|
6730466230 | |
|
94d6cac626 | |
|
640d841242 | |
|
6a0066b71c | |
|
aafbb8011b | |
|
72a87ea909 | |
|
abf909d0e7 | |
|
a2321d5370 | |
|
d154f0aecc | |
|
68e4c8ad5a | |
|
cf533f49cc | |
|
29d9410e42 | |
|
2a9a835939 | |
|
d756646b1a | |
|
3b62f09669 | |
|
5864352049 | |
|
1d6d48fc94 | |
|
484c91a581 | |
|
7b91ad37e5 | |
|
9dbb9a42d6 | |
|
a608803aa8 | |
|
76cc185a1d | |
|
e76503ae26 | |
|
50991f503f | |
|
acd031ca7d | |
|
b59b76be4a | |
|
211581cef0 | |
|
7cad953413 | |
|
fe58175ee0 | |
|
5d0849a148 | |
|
d14bf35ca1 | |
|
d7dd3901b8 | |
|
aefd6c08dc | |
|
3c2c742121 | |
|
9221e55752 | |
|
ba1fa8b685 | |
|
29e3a55a0c | |
|
c426467a68 | |
|
9fe8df3c1b | |
|
531495429c | |
|
bed2469014 | |
|
45b7f70d9f | |
|
1ebb6cb561 | |
|
21ccedab9c | |
|
8f45bcf959 | |
|
1f9caeece5 | |
|
5b4e6f4902 | |
|
3d0e323801 | |
|
f6fb50529c | |
|
c42f3d5928 | |
|
42d2b51f7f | |
|
66c40d4791 | |
|
ce467736a7 | |
|
3e4dd90e17 | |
|
8ae5587516 | |
|
0b543f7dda | |
|
a07204111a | |
|
038df804c0 | |
|
877948b0cd | |
|
9a17c4865f | |
|
9427db3e5a | |
|
81da71d478 | |
|
169dc84e22 | |
|
d6fd85f536 | |
|
6448a30e03 | |
|
17fb43cea8 | |
|
a6e50d2a25 | |
|
bd16ca476d | |
|
3dfe5d5d0f | |
|
eadc517a25 | |
|
1652e615be | |
|
2ea78b4f20 | |
|
e36c7a4b6a | |
|
8e8ec821f2 | |
|
5cf257c3cc | |
|
aa18fe0ad4 | |
|
1358c23ca6 | |
|
c27cc063e6 | |
|
b0092487e6 | |
|
fbebd0a623 | |
|
fe23c2afbf | |
|
779c86108a | |
|
83e43f0c97 | |
|
e545424b7d | |
|
e237fd46f7 | |
|
ca3c564529 | |
|
9cd18397f7 | |
|
7574071445 | |
|
77620f7735 | |
|
50dc5cce5d | |
|
a6cee63d17 | |
|
000197b0d1 | |
|
6aa3321d17 | |
|
d44308fc82 | |
|
ae7d0d1329 | |
|
55c74de8e4 | |
|
7c88ea3d67 | |
|
f15cd44dff | |
|
3abd6037d9 | |
|
ec3a556a6f | |
|
793cbb372a | |
|
396ac55429 | |
|
088c617cc1 | |
|
17314b9164 | |
|
e6521ffdd2 | |
|
fc3cf01d3f | |
|
8f5bb0e2d9 | |
|
ef559b11a0 | |
|
7f59f6739f | |
|
d6937f195c | |
|
2dfd69ae21 | |
|
720c073f32 | |
|
0076468a15 | |
|
910ae48556 | |
|
eac7331070 | |
|
551f333261 | |
|
dec264d169 | |
|
7055974443 | |
|
3536918938 | |
|
56278b84f2 | |
|
882a50cf56 | |
|
db4031b8bf | |
|
ecfc39565c | |
|
9ced678f91 | |
|
7951ca28d5 | |
|
4bbb843edf | |
|
747646cd9d | |
|
d0d906d04c | |
|
bc639488aa | |
|
99fbecc834 | |
|
8d0a6d267a | |
|
b1c03ed5e8 | |
|
ef12f85687 | |
|
e120c4dac2 | |
|
e1cf2fcdeb | |
|
c4f380873e | |
|
5cb2e55f74 | |
|
1dd3fbc69a | |
|
b97c42d0ae | |
|
a2612d8009 | |
|
2f2655525f | |
|
1a93477635 | |
|
7c664addbd | |
|
c6b79f82bc | |
|
4e3f9cc019 | |
|
5ed7b3e4ad | |
|
4e2c46260c | |
|
9ba00b21c9 | |
|
b11f5fd228 | |
|
90dbe0730a | |
|
d6633cb73a | |
|
a7a6abd22a | |
|
c956667ce0 | |
|
5701c818ed | |
|
1ac2ddfaa5 | |
|
4aac05d4e1 | |
|
84b56bfcb8 | |
|
7485564bb9 | |
|
b5acf2308a | |
|
e3f4313c80 | |
|
b223abe229 | |
|
b3bede308c | |
|
2f170a54c6 | |
|
22293572ac | |
|
8720cab1e9 | |
|
959c1e8d95 | |
|
29dc3fff39 | |
|
298abdd1b1 | |
|
26f87fba16 | |
|
1e9a32a93e | |
|
2dc79052c2 | |
|
380ca3a066 | |
|
237b0afb08 | |
|
e14936e820 | |
|
655c85851f | |
|
1c7e414aa4 | |
|
099fc52e00 | |
|
490957ec3b | |
|
b1884d30d5 | |
|
98d8ee1fb6 | |
|
2ca77732c8 | |
|
70d22f7c4f | |
|
25d0e784bb | |
|
5d45b24299 | |
|
b6b8befde7 | |
|
f33b9559cd | |
|
f9bc2258ec | |
|
2a09ced1ce | |
|
7a1e6cfbad | |
|
47d1f727ce | |
|
a7665df0ea | |
|
84f12adce8 | |
|
7fde1e0e12 | |
|
499734ebf9 | |
|
f339df699e | |
|
cfd94cb3b7 | |
|
43e0617429 | |
|
d6b66d5324 | |
|
0c1df3b2cb | |
|
fa86d3ea10 | |
|
8c99b754fb | |
|
f3cf2c87c9 | |
|
8e4e6fc0ac | |
|
75f3166ffa | |
|
04bf423fcb | |
|
51e8c9d908 | |
|
4304a35b80 | |
|
076375633a | |
|
dbf5e711a5 | |
|
4432e65683 | |
|
dcf44a78f0 | |
|
12edc620df | |
|
4ce03145df | |
|
3e04a37ece | |
|
78f464ccba | |
|
64423f1999 | |
|
05c3f60dab | |
|
0083ef33cb | |
|
36b68df273 | |
|
e1a5918c22 | |
|
26ae9b35df | |
|
8e79b43aaf | |
|
d28eba6423 | |
|
688be1bb7d | |
|
df69dee282 | |
|
45a77e5c07 | |
|
7849bd0ebf | |
|
3649bf1fd0 | |
|
6ffc2938a1 | |
|
aa60de1dac | |
|
29f98513e2 | |
|
e35cdf39fb | |
|
e51b86538b | |
|
da4fd3a762 | |
|
efc82b9841 | |
|
e3df503dd2 | |
|
6a2ad67386 | |
|
3d12db3a07 | |
|
1faaf1d7d1 | |
|
f8a6f62342 | |
|
66d1246a6c | |
|
f79beef3f9 | |
|
81e6691632 | |
|
38d6519381 | |
|
16418675ac | |
|
102858bc8c | |
|
0d64768e4b | |
|
beccac652f | |
|
30eb1958c1 | |
|
33e17e8439 | |
|
e0c47c2abd | |
|
422549f9e7 | |
|
0358229b95 | |
|
c4586fbb36 | |
|
f94006abfd | |
|
4d61e7618a | |
|
36286d9003 | |
|
51356da7f3 | |
|
ebe893022f | |
|
c5f22e6c70 | |
|
922561afb1 | |
|
6f7899d16f | |
|
4e3c8e414c | |
|
d588a78f62 | |
|
a7d681c4dd | |
|
7a93db9ed2 | |
|
74e5fa0e31 | |
|
de995c8714 | |
|
ea156cec7e | |
|
7499d8af89 | |
|
f8654edc3b | |
|
d16f290aa6 | |
|
9385d346f1 | |
|
22f3371090 | |
|
c0a4f8f4ec | |
|
7586a0fb21 | |
|
c0e3a91a46 | |
|
7ebd8681fa | |
|
72553dec57 | |
|
dee68808b1 | |
|
96d7917bbf | |
|
abca0fe432 | |
|
d7612a0921 | |
|
c54950a95f | |
|
be0f68cede | |
|
1b92b53099 | |
|
5634413cac | |
|
1a9ed1425e | |
|
f9d4316a8e | |
|
6f7f815fd4 | |
|
ddb826733b | |
|
1f989d0a37 | |
|
d63626424e | |
|
55ab694505 | |
|
0885575cc4 | |
|
a188648287 | |
|
8011dabaac | |
|
88a08e73c0 | |
|
6713f9b280 |
|
@ -23,7 +23,7 @@
|
|||
* Fix 版本库中附件下载400(#51625)
|
||||
* Fix loading页面优化(#51588)
|
||||
* Fix 提交详情页面优化(#51577)
|
||||
* Fix 修复易修复制功能(#51569)
|
||||
* Fix 修复疑修复制功能(#51569)
|
||||
* Fix 修复新建发行版用户信息显示错误的问题(#51665)
|
||||
* Fix 修复查看文件详细信息报错的问题(#51561)
|
||||
* Fix 修复提交记录中时间显示格式问题(#51526)
|
||||
|
@ -62,7 +62,7 @@
|
|||
## [v3.0.3](https://forgeplus.trustie.net/projects/jasder/forgeplus/releases) - 2021-05-08
|
||||
|
||||
* BUGFIXES
|
||||
* Fix 解决易修标题过长导致的排版问题(45469)
|
||||
* Fix 解决疑修标题过长导致的排版问题(45469)
|
||||
* Fix 解决合并请求详情页面排版错误的问题(45457)
|
||||
* FIX 解决转移仓库界面专有名词描述错误的问题(45455)
|
||||
* Fix 解决markdown格式文件自动生成数字排序的问题(45454)
|
||||
|
|
16
Gemfile
16
Gemfile
|
@ -1,4 +1,5 @@
|
|||
source 'https://gems.ruby-china.com'
|
||||
#source 'https://gems.ruby-china.com'
|
||||
source 'https://mirrors.cloud.tencent.com/rubygems/'
|
||||
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
|
||||
|
||||
gem 'rails', '~> 5.2.0'
|
||||
|
@ -101,6 +102,7 @@ gem 'rails-i18n', '~> 5.1'
|
|||
gem 'sidekiq'
|
||||
gem 'sinatra'
|
||||
gem "sidekiq-cron", "~> 1.1"
|
||||
gem 'sidekiq-failures'
|
||||
|
||||
# batch insert
|
||||
gem 'bulk_insert'
|
||||
|
@ -118,6 +120,10 @@ gem 'deep_cloneable', '~> 3.0.0'
|
|||
# oauth2
|
||||
gem 'omniauth', '~> 1.9.0'
|
||||
gem 'omniauth-oauth2', '~> 1.6.0'
|
||||
gem "omniauth-github"
|
||||
gem "omniauth-rails_csrf_protection"
|
||||
gem 'omniauth-gitee', '~> 1.0.0'
|
||||
gem "omniauth-wechat-oauth2"
|
||||
|
||||
# global var
|
||||
gem 'request_store'
|
||||
|
@ -128,3 +134,11 @@ gem 'harmonious_dictionary', '~> 0.0.1'
|
|||
gem 'parallel', '~> 1.19', '>= 1.19.1'
|
||||
|
||||
gem 'letter_avatar'
|
||||
|
||||
gem 'jwt'
|
||||
|
||||
gem 'doorkeeper'
|
||||
|
||||
gem 'doorkeeper-jwt'
|
||||
|
||||
gem 'gitea-client', '~> 0.10.6'
|
|
@ -106,6 +106,10 @@ GEM
|
|||
activerecord (>= 3.1.0, < 7)
|
||||
diff-lcs (1.3)
|
||||
diffy (3.3.0)
|
||||
doorkeeper (5.5.1)
|
||||
railties (>= 5)
|
||||
doorkeeper-jwt (0.4.1)
|
||||
jwt (>= 2.1)
|
||||
e2mmap (0.1.0)
|
||||
elasticsearch (7.5.0)
|
||||
elasticsearch-api (= 7.5.0)
|
||||
|
@ -450,6 +454,8 @@ DEPENDENCIES
|
|||
chromedriver-helper
|
||||
deep_cloneable (~> 3.0.0)
|
||||
diffy
|
||||
doorkeeper
|
||||
doorkeeper-jwt
|
||||
enumerize
|
||||
faraday (~> 0.15.4)
|
||||
font-awesome-sass (= 4.7.0)
|
||||
|
@ -458,6 +464,7 @@ DEPENDENCIES
|
|||
harmonious_dictionary (~> 0.0.1)
|
||||
jbuilder (~> 2.5)
|
||||
jquery-rails
|
||||
jwt
|
||||
kaminari (~> 1.1, >= 1.1.1)
|
||||
letter_avatar
|
||||
listen (>= 3.0.5, < 3.2)
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
//= require bootstrap-datepicker
|
||||
//= require bootstrap-datetimepicker
|
||||
//= require bootstrap.viewer
|
||||
//= require bootstrap/bootstrap-toggle
|
||||
//= require jquery.mloading
|
||||
//= require jquery-confirm.min
|
||||
//= require common
|
||||
|
|
|
@ -0,0 +1,180 @@
|
|||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap-toggle.js v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// TOGGLE PUBLIC CLASS DEFINITION
|
||||
// ==============================
|
||||
|
||||
var Toggle = function (element, options) {
|
||||
this.$element = $(element)
|
||||
this.options = $.extend({}, this.defaults(), options)
|
||||
this.render()
|
||||
}
|
||||
|
||||
Toggle.VERSION = '2.2.0'
|
||||
|
||||
Toggle.DEFAULTS = {
|
||||
on: 'On',
|
||||
off: 'Off',
|
||||
onstyle: 'primary',
|
||||
offstyle: 'default',
|
||||
size: 'normal',
|
||||
style: '',
|
||||
width: null,
|
||||
height: null
|
||||
}
|
||||
|
||||
Toggle.prototype.defaults = function() {
|
||||
return {
|
||||
on: this.$element.attr('data-on') || Toggle.DEFAULTS.on,
|
||||
off: this.$element.attr('data-off') || Toggle.DEFAULTS.off,
|
||||
onstyle: this.$element.attr('data-onstyle') || Toggle.DEFAULTS.onstyle,
|
||||
offstyle: this.$element.attr('data-offstyle') || Toggle.DEFAULTS.offstyle,
|
||||
size: this.$element.attr('data-size') || Toggle.DEFAULTS.size,
|
||||
style: this.$element.attr('data-style') || Toggle.DEFAULTS.style,
|
||||
width: this.$element.attr('data-width') || Toggle.DEFAULTS.width,
|
||||
height: this.$element.attr('data-height') || Toggle.DEFAULTS.height
|
||||
}
|
||||
}
|
||||
|
||||
Toggle.prototype.render = function () {
|
||||
this._onstyle = 'btn-' + this.options.onstyle
|
||||
this._offstyle = 'btn-' + this.options.offstyle
|
||||
var size = this.options.size === 'large' ? 'btn-lg'
|
||||
: this.options.size === 'small' ? 'btn-sm'
|
||||
: this.options.size === 'mini' ? 'btn-xs'
|
||||
: ''
|
||||
var $toggleOn = $('<label class="btn">').html(this.options.on)
|
||||
.addClass(this._onstyle + ' ' + size)
|
||||
var $toggleOff = $('<label class="btn">').html(this.options.off)
|
||||
.addClass(this._offstyle + ' ' + size + ' active')
|
||||
var $toggleHandle = $('<span class="toggle-handle btn btn-default">')
|
||||
.addClass(size)
|
||||
var $toggleGroup = $('<div class="toggle-group">')
|
||||
.append($toggleOn, $toggleOff, $toggleHandle)
|
||||
var $toggle = $('<div class="toggle btn" data-toggle="toggle">')
|
||||
.addClass( this.$element.prop('checked') ? this._onstyle : this._offstyle+' off' )
|
||||
.addClass(size).addClass(this.options.style)
|
||||
|
||||
this.$element.wrap($toggle)
|
||||
$.extend(this, {
|
||||
$toggle: this.$element.parent(),
|
||||
$toggleOn: $toggleOn,
|
||||
$toggleOff: $toggleOff,
|
||||
$toggleGroup: $toggleGroup
|
||||
})
|
||||
this.$toggle.append($toggleGroup)
|
||||
|
||||
var width = this.options.width || Math.max($toggleOn.outerWidth(), $toggleOff.outerWidth())+($toggleHandle.outerWidth()/2)
|
||||
var height = this.options.height || Math.max($toggleOn.outerHeight(), $toggleOff.outerHeight())
|
||||
$toggleOn.addClass('toggle-on')
|
||||
$toggleOff.addClass('toggle-off')
|
||||
this.$toggle.css({ width: width, height: height })
|
||||
if (this.options.height) {
|
||||
$toggleOn.css('line-height', $toggleOn.height() + 'px')
|
||||
$toggleOff.css('line-height', $toggleOff.height() + 'px')
|
||||
}
|
||||
this.update(true)
|
||||
this.trigger(true)
|
||||
}
|
||||
|
||||
Toggle.prototype.toggle = function () {
|
||||
if (this.$element.prop('checked')) this.off()
|
||||
else this.on()
|
||||
}
|
||||
|
||||
Toggle.prototype.on = function (silent) {
|
||||
if (this.$element.prop('disabled')) return false
|
||||
this.$toggle.removeClass(this._offstyle + ' off').addClass(this._onstyle)
|
||||
this.$element.prop('checked', true)
|
||||
if (!silent) this.trigger()
|
||||
}
|
||||
|
||||
Toggle.prototype.off = function (silent) {
|
||||
if (this.$element.prop('disabled')) return false
|
||||
this.$toggle.removeClass(this._onstyle).addClass(this._offstyle + ' off')
|
||||
this.$element.prop('checked', false)
|
||||
if (!silent) this.trigger()
|
||||
}
|
||||
|
||||
Toggle.prototype.enable = function () {
|
||||
this.$toggle.removeAttr('disabled')
|
||||
this.$element.prop('disabled', false)
|
||||
}
|
||||
|
||||
Toggle.prototype.disable = function () {
|
||||
this.$toggle.attr('disabled', 'disabled')
|
||||
this.$element.prop('disabled', true)
|
||||
}
|
||||
|
||||
Toggle.prototype.update = function (silent) {
|
||||
if (this.$element.prop('disabled')) this.disable()
|
||||
else this.enable()
|
||||
if (this.$element.prop('checked')) this.on(silent)
|
||||
else this.off(silent)
|
||||
}
|
||||
|
||||
Toggle.prototype.trigger = function (silent) {
|
||||
this.$element.off('change.bs.toggle')
|
||||
if (!silent) this.$element.change()
|
||||
this.$element.on('change.bs.toggle', $.proxy(function() {
|
||||
this.update()
|
||||
}, this))
|
||||
}
|
||||
|
||||
Toggle.prototype.destroy = function() {
|
||||
this.$element.off('change.bs.toggle')
|
||||
this.$toggleGroup.remove()
|
||||
this.$element.removeData('bs.toggle')
|
||||
this.$element.unwrap()
|
||||
}
|
||||
|
||||
// TOGGLE PLUGIN DEFINITION
|
||||
// ========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.toggle')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data) $this.data('bs.toggle', (data = new Toggle(this, options)))
|
||||
if (typeof option == 'string' && data[option]) data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.bootstrapToggle
|
||||
|
||||
$.fn.bootstrapToggle = Plugin
|
||||
$.fn.bootstrapToggle.Constructor = Toggle
|
||||
|
||||
// TOGGLE NO CONFLICT
|
||||
// ==================
|
||||
|
||||
$.fn.toggle.noConflict = function () {
|
||||
$.fn.bootstrapToggle = old
|
||||
return this
|
||||
}
|
||||
|
||||
// TOGGLE DATA-API
|
||||
// ===============
|
||||
|
||||
$(function() {
|
||||
$('input[type=checkbox][data-toggle^=toggle]').bootstrapToggle()
|
||||
})
|
||||
|
||||
$(document).on('click.bs.toggle', 'div[data-toggle^=toggle]', function(e) {
|
||||
var $checkbox = $(this).find('input[type=checkbox]')
|
||||
$checkbox.bootstrapToggle('toggle')
|
||||
e.preventDefault()
|
||||
})
|
||||
|
||||
}(jQuery);
|
|
@ -0,0 +1,9 @@
|
|||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap-toggle.js v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-lg":"small"===this.options.size?"btn-sm":"mini"===this.options.size?"btn-xs":"",c=a('<label class="btn">').html(this.options.on).addClass(this._onstyle+" "+b),d=a('<label class="btn">').html(this.options.off).addClass(this._offstyle+" "+b+" active"),e=a('<span class="toggle-handle btn btn-default">').addClass(b),f=a('<div class="toggle-group">').append(c,d,e),g=a('<div class="toggle btn" data-toggle="toggle">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(b).addClass(this.options.style);this.$element.wrap(g),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:c,$toggleOff:d,$toggleGroup:f}),this.$toggle.append(f);var h=this.options.width||Math.max(c.outerWidth(),d.outerWidth())+e.outerWidth()/2,i=this.options.height||Math.max(c.outerHeight(),d.outerHeight());c.addClass("toggle-on"),d.addClass("toggle-off"),this.$toggle.css({width:h,height:i}),this.options.height&&(c.css("line-height",c.height()+"px"),d.css("line-height",d.height()+"px")),this.update(!0),this.trigger(!0)},c.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},c.prototype.on=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),void(a||this.trigger()))},c.prototype.off=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),void(a||this.trigger()))},c.prototype.enable=function(){this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},c.prototype.disable=function(){this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},c.prototype.update=function(a){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(a):this.off(a)},c.prototype.trigger=function(b){this.$element.off("change.bs.toggle"),b||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},c.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var d=a.fn.bootstrapToggle;a.fn.bootstrapToggle=b,a.fn.bootstrapToggle.Constructor=c,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=d,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(b){var c=a(this).find("input[type=checkbox]");c.bootstrapToggle("toggle"),b.preventDefault()})}(jQuery);
|
||||
//# sourceMappingURL=bootstrap-toggle.min.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"bootstrap-toggle.min.js","sources":["bootstrap-toggle.js"],"names":["$","Plugin","option","this","each","$this","data","options","Toggle","element","$element","extend","defaults","render","VERSION","DEFAULTS","on","off","onstyle","offstyle","size","style","width","height","prototype","attr","_onstyle","_offstyle","$toggleOn","html","addClass","$toggleOff","$toggleHandle","$toggleGroup","append","$toggle","prop","wrap","parent","Math","max","outerWidth","outerHeight","css","update","trigger","toggle","silent","removeClass","enable","removeAttr","disable","change","proxy","destroy","remove","removeData","unwrap","old","fn","bootstrapToggle","Constructor","noConflict","document","e","$checkbox","find","preventDefault","jQuery"],"mappings":";;;;;;;CASE,SAAUA,GACV,YAoID,SAASC,GAAOC,GACf,MAAOC,MAAKC,KAAK,WAChB,GAAIC,GAAUL,EAAEG,MACZG,EAAUD,EAAMC,KAAK,aACrBC,EAA2B,gBAAVL,IAAsBA,CAEtCI,IAAMD,EAAMC,KAAK,YAAcA,EAAO,GAAIE,GAAOL,KAAMI,IACvC,gBAAVL,IAAsBI,EAAKJ,IAASI,EAAKJ,OAtItD,GAAIM,GAAS,SAAUC,EAASF,GAC/BJ,KAAKO,SAAYV,EAAES,GACnBN,KAAKI,QAAYP,EAAEW,UAAWR,KAAKS,WAAYL,GAC/CJ,KAAKU,SAGNL,GAAOM,QAAW,QAElBN,EAAOO,UACNC,GAAI,KACJC,IAAK,MACLC,QAAS,UACTC,SAAU,UACVC,KAAM,SACNC,MAAO,GACPC,MAAO,KACPC,OAAQ,MAGTf,EAAOgB,UAAUZ,SAAW,WAC3B,OACCI,GAAIb,KAAKO,SAASe,KAAK,YAAcjB,EAAOO,SAASC,GACrDC,IAAKd,KAAKO,SAASe,KAAK,aAAejB,EAAOO,SAASE,IACvDC,QAASf,KAAKO,SAASe,KAAK,iBAAmBjB,EAAOO,SAASG,QAC/DC,SAAUhB,KAAKO,SAASe,KAAK,kBAAoBjB,EAAOO,SAASI,SACjEC,KAAMjB,KAAKO,SAASe,KAAK,cAAgBjB,EAAOO,SAASK,KACzDC,MAAOlB,KAAKO,SAASe,KAAK,eAAiBjB,EAAOO,SAASM,MAC3DC,MAAOnB,KAAKO,SAASe,KAAK,eAAiBjB,EAAOO,SAASO,MAC3DC,OAAQpB,KAAKO,SAASe,KAAK,gBAAkBjB,EAAOO,SAASQ,SAI/Df,EAAOgB,UAAUX,OAAS,WACzBV,KAAKuB,SAAW,OAASvB,KAAKI,QAAQW,QACtCf,KAAKwB,UAAY,OAASxB,KAAKI,QAAQY,QACvC,IAAIC,GAA6B,UAAtBjB,KAAKI,QAAQa,KAAmB,SAClB,UAAtBjB,KAAKI,QAAQa,KAAmB,SACV,SAAtBjB,KAAKI,QAAQa,KAAkB,SAC/B,GACCQ,EAAY5B,EAAE,uBAAuB6B,KAAK1B,KAAKI,QAAQS,IACzDc,SAAS3B,KAAKuB,SAAW,IAAMN,GAC7BW,EAAa/B,EAAE,uBAAuB6B,KAAK1B,KAAKI,QAAQU,KAC1Da,SAAS3B,KAAKwB,UAAY,IAAMP,EAAO,WACrCY,EAAgBhC,EAAE,gDACpB8B,SAASV,GACPa,EAAejC,EAAE,8BACnBkC,OAAON,EAAWG,EAAYC,GAC5BG,EAAUnC,EAAE,iDACd8B,SAAU3B,KAAKO,SAAS0B,KAAK,WAAajC,KAAKuB,SAAWvB,KAAKwB,UAAU,QACzEG,SAASV,GAAMU,SAAS3B,KAAKI,QAAQc,MAEvClB,MAAKO,SAAS2B,KAAKF,GACnBnC,EAAEW,OAAOR,MACRgC,QAAShC,KAAKO,SAAS4B,SACvBV,UAAWA,EACXG,WAAYA,EACZE,aAAcA,IAEf9B,KAAKgC,QAAQD,OAAOD,EAEpB,IAAIX,GAAQnB,KAAKI,QAAQe,OAASiB,KAAKC,IAAIZ,EAAUa,aAAcV,EAAWU,cAAeT,EAAcS,aAAa,EACpHlB,EAASpB,KAAKI,QAAQgB,QAAUgB,KAAKC,IAAIZ,EAAUc,cAAeX,EAAWW,cACjFd,GAAUE,SAAS,aACnBC,EAAWD,SAAS,cACpB3B,KAAKgC,QAAQQ,KAAMrB,MAAOA,EAAOC,OAAQA,IACrCpB,KAAKI,QAAQgB,SAChBK,EAAUe,IAAI,cAAef,EAAUL,SAAW,MAClDQ,EAAWY,IAAI,cAAeZ,EAAWR,SAAW,OAErDpB,KAAKyC,QAAO,GACZzC,KAAK0C,SAAQ,IAGdrC,EAAOgB,UAAUsB,OAAS,WACrB3C,KAAKO,SAAS0B,KAAK,WAAYjC,KAAKc,MACnCd,KAAKa,MAGXR,EAAOgB,UAAUR,GAAK,SAAU+B,GAC/B,MAAI5C,MAAKO,SAAS0B,KAAK,aAAoB,GAC3CjC,KAAKgC,QAAQa,YAAY7C,KAAKwB,UAAY,QAAQG,SAAS3B,KAAKuB,UAChEvB,KAAKO,SAAS0B,KAAK,WAAW,QACzBW,GAAQ5C,KAAK0C,aAGnBrC,EAAOgB,UAAUP,IAAM,SAAU8B,GAChC,MAAI5C,MAAKO,SAAS0B,KAAK,aAAoB,GAC3CjC,KAAKgC,QAAQa,YAAY7C,KAAKuB,UAAUI,SAAS3B,KAAKwB,UAAY,QAClExB,KAAKO,SAAS0B,KAAK,WAAW,QACzBW,GAAQ5C,KAAK0C,aAGnBrC,EAAOgB,UAAUyB,OAAS,WACzB9C,KAAKgC,QAAQe,WAAW,YACxB/C,KAAKO,SAAS0B,KAAK,YAAY,IAGhC5B,EAAOgB,UAAU2B,QAAU,WAC1BhD,KAAKgC,QAAQV,KAAK,WAAY,YAC9BtB,KAAKO,SAAS0B,KAAK,YAAY,IAGhC5B,EAAOgB,UAAUoB,OAAS,SAAUG,GAC/B5C,KAAKO,SAAS0B,KAAK,YAAajC,KAAKgD,UACpChD,KAAK8C,SACN9C,KAAKO,SAAS0B,KAAK,WAAYjC,KAAKa,GAAG+B,GACtC5C,KAAKc,IAAI8B,IAGfvC,EAAOgB,UAAUqB,QAAU,SAAUE,GACpC5C,KAAKO,SAASO,IAAI,oBACb8B,GAAQ5C,KAAKO,SAAS0C,SAC3BjD,KAAKO,SAASM,GAAG,mBAAoBhB,EAAEqD,MAAM,WAC5ClD,KAAKyC,UACHzC,QAGJK,EAAOgB,UAAU8B,QAAU,WAC1BnD,KAAKO,SAASO,IAAI,oBAClBd,KAAK8B,aAAasB,SAClBpD,KAAKO,SAAS8C,WAAW,aACzBrD,KAAKO,SAAS+C,SAiBf,IAAIC,GAAM1D,EAAE2D,GAAGC,eAEf5D,GAAE2D,GAAGC,gBAA8B3D,EACnCD,EAAE2D,GAAGC,gBAAgBC,YAAcrD,EAKnCR,EAAE2D,GAAGb,OAAOgB,WAAa,WAExB,MADA9D,GAAE2D,GAAGC,gBAAkBF,EAChBvD,MAMRH,EAAE,WACDA,EAAE,6CAA6C4D,oBAGhD5D,EAAE+D,UAAU/C,GAAG,kBAAmB,2BAA4B,SAASgD,GACtE,GAAIC,GAAYjE,EAAEG,MAAM+D,KAAK,uBAC7BD,GAAUL,gBAAgB,UAC1BI,EAAEG,oBAGFC"}
|
|
@ -0,0 +1,180 @@
|
|||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap2-toggle.js v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// TOGGLE PUBLIC CLASS DEFINITION
|
||||
// ==============================
|
||||
|
||||
var Toggle = function (element, options) {
|
||||
this.$element = $(element)
|
||||
this.options = $.extend({}, this.defaults(), options)
|
||||
this.render()
|
||||
}
|
||||
|
||||
Toggle.VERSION = '2.2.0'
|
||||
|
||||
Toggle.DEFAULTS = {
|
||||
on: 'On',
|
||||
off: 'Off',
|
||||
onstyle: 'primary',
|
||||
offstyle: 'default',
|
||||
size: 'normal',
|
||||
style: '',
|
||||
width: null,
|
||||
height: null
|
||||
}
|
||||
|
||||
Toggle.prototype.defaults = function() {
|
||||
return {
|
||||
on: this.$element.attr('data-on') || Toggle.DEFAULTS.on,
|
||||
off: this.$element.attr('data-off') || Toggle.DEFAULTS.off,
|
||||
onstyle: this.$element.attr('data-onstyle') || Toggle.DEFAULTS.onstyle,
|
||||
offstyle: this.$element.attr('data-offstyle') || Toggle.DEFAULTS.offstyle,
|
||||
size: this.$element.attr('data-size') || Toggle.DEFAULTS.size,
|
||||
style: this.$element.attr('data-style') || Toggle.DEFAULTS.style,
|
||||
width: this.$element.attr('data-width') || Toggle.DEFAULTS.width,
|
||||
height: this.$element.attr('data-height') || Toggle.DEFAULTS.height
|
||||
}
|
||||
}
|
||||
|
||||
Toggle.prototype.render = function () {
|
||||
this._onstyle = 'btn-' + this.options.onstyle
|
||||
this._offstyle = 'btn-' + this.options.offstyle
|
||||
var size = this.options.size === 'large' ? 'btn-large'
|
||||
: this.options.size === 'small' ? 'btn-small'
|
||||
: this.options.size === 'mini' ? 'btn-mini'
|
||||
: ''
|
||||
var $toggleOn = $('<label class="btn">').html(this.options.on)
|
||||
.addClass(this._onstyle + ' ' + size)
|
||||
var $toggleOff = $('<label class="btn">').html(this.options.off)
|
||||
.addClass(this._offstyle + ' ' + size + ' active')
|
||||
var $toggleHandle = $('<span class="toggle-handle btn btn-default">')
|
||||
.addClass(size)
|
||||
var $toggleGroup = $('<div class="toggle-group">')
|
||||
.append($toggleOn, $toggleOff, $toggleHandle)
|
||||
var $toggle = $('<div class="toggle btn" data-toggle="toggle">')
|
||||
.addClass( this.$element.prop('checked') ? this._onstyle : this._offstyle+' off' )
|
||||
.addClass(size).addClass(this.options.style)
|
||||
|
||||
this.$element.wrap($toggle)
|
||||
$.extend(this, {
|
||||
$toggle: this.$element.parent(),
|
||||
$toggleOn: $toggleOn,
|
||||
$toggleOff: $toggleOff,
|
||||
$toggleGroup: $toggleGroup
|
||||
})
|
||||
this.$toggle.append($toggleGroup)
|
||||
|
||||
var width = this.options.width || Math.max($toggleOn.width(), $toggleOff.width())+($toggleHandle.outerWidth()/2)
|
||||
var height = this.options.height || Math.max($toggleOn.height(), $toggleOff.height())
|
||||
$toggleOn.addClass('toggle-on')
|
||||
$toggleOff.addClass('toggle-off')
|
||||
this.$toggle.css({ width: width, height: height })
|
||||
if (this.options.height) {
|
||||
$toggleOn.css('line-height', $toggleOn.height() + 'px')
|
||||
$toggleOff.css('line-height', $toggleOff.height() + 'px')
|
||||
}
|
||||
this.update(true)
|
||||
this.trigger(true)
|
||||
}
|
||||
|
||||
Toggle.prototype.toggle = function () {
|
||||
if (this.$element.prop('checked')) this.off()
|
||||
else this.on()
|
||||
}
|
||||
|
||||
Toggle.prototype.on = function (silent) {
|
||||
if (this.$element.prop('disabled')) return false
|
||||
this.$toggle.removeClass(this._offstyle + ' off').addClass(this._onstyle)
|
||||
this.$element.prop('checked', true)
|
||||
if (!silent) this.trigger()
|
||||
}
|
||||
|
||||
Toggle.prototype.off = function (silent) {
|
||||
if (this.$element.prop('disabled')) return false
|
||||
this.$toggle.removeClass(this._onstyle).addClass(this._offstyle + ' off')
|
||||
this.$element.prop('checked', false)
|
||||
if (!silent) this.trigger()
|
||||
}
|
||||
|
||||
Toggle.prototype.enable = function () {
|
||||
this.$toggle.removeAttr('disabled')
|
||||
this.$element.prop('disabled', false)
|
||||
}
|
||||
|
||||
Toggle.prototype.disable = function () {
|
||||
this.$toggle.attr('disabled', 'disabled')
|
||||
this.$element.prop('disabled', true)
|
||||
}
|
||||
|
||||
Toggle.prototype.update = function (silent) {
|
||||
if (this.$element.prop('disabled')) this.disable()
|
||||
else this.enable()
|
||||
if (this.$element.prop('checked')) this.on(silent)
|
||||
else this.off(silent)
|
||||
}
|
||||
|
||||
Toggle.prototype.trigger = function (silent) {
|
||||
this.$element.off('change.bs.toggle')
|
||||
if (!silent) this.$element.change()
|
||||
this.$element.on('change.bs.toggle', $.proxy(function() {
|
||||
this.update()
|
||||
}, this))
|
||||
}
|
||||
|
||||
Toggle.prototype.destroy = function() {
|
||||
this.$element.off('change.bs.toggle')
|
||||
this.$toggleGroup.remove()
|
||||
this.$element.removeData('bs.toggle')
|
||||
this.$element.unwrap()
|
||||
}
|
||||
|
||||
// TOGGLE PLUGIN DEFINITION
|
||||
// ========================
|
||||
|
||||
function Plugin(option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.toggle')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data) $this.data('bs.toggle', (data = new Toggle(this, options)))
|
||||
if (typeof option == 'string' && data[option]) data[option]()
|
||||
})
|
||||
}
|
||||
|
||||
var old = $.fn.bootstrapToggle
|
||||
|
||||
$.fn.bootstrapToggle = Plugin
|
||||
$.fn.bootstrapToggle.Constructor = Toggle
|
||||
|
||||
// TOGGLE NO CONFLICT
|
||||
// ==================
|
||||
|
||||
$.fn.toggle.noConflict = function () {
|
||||
$.fn.bootstrapToggle = old
|
||||
return this
|
||||
}
|
||||
|
||||
// TOGGLE DATA-API
|
||||
// ===============
|
||||
|
||||
$(function() {
|
||||
$('input[type=checkbox][data-toggle^=toggle]').bootstrapToggle()
|
||||
})
|
||||
|
||||
$(document).on('click.bs.toggle', 'div[data-toggle^=toggle]', function(e) {
|
||||
var $checkbox = $(this).find('input[type=checkbox]')
|
||||
$checkbox.bootstrapToggle('toggle')
|
||||
e.preventDefault()
|
||||
})
|
||||
|
||||
}(jQuery);
|
|
@ -0,0 +1,9 @@
|
|||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap2-toggle.js v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-large":"small"===this.options.size?"btn-small":"mini"===this.options.size?"btn-mini":"",c=a('<label class="btn">').html(this.options.on).addClass(this._onstyle+" "+b),d=a('<label class="btn">').html(this.options.off).addClass(this._offstyle+" "+b+" active"),e=a('<span class="toggle-handle btn btn-default">').addClass(b),f=a('<div class="toggle-group">').append(c,d,e),g=a('<div class="toggle btn" data-toggle="toggle">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(b).addClass(this.options.style);this.$element.wrap(g),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:c,$toggleOff:d,$toggleGroup:f}),this.$toggle.append(f);var h=this.options.width||Math.max(c.width(),d.width())+e.outerWidth()/2,i=this.options.height||Math.max(c.height(),d.height());c.addClass("toggle-on"),d.addClass("toggle-off"),this.$toggle.css({width:h,height:i}),this.options.height&&(c.css("line-height",c.height()+"px"),d.css("line-height",d.height()+"px")),this.update(!0),this.trigger(!0)},c.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},c.prototype.on=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),void(a||this.trigger()))},c.prototype.off=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),void(a||this.trigger()))},c.prototype.enable=function(){this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},c.prototype.disable=function(){this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},c.prototype.update=function(a){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(a):this.off(a)},c.prototype.trigger=function(b){this.$element.off("change.bs.toggle"),b||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},c.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var d=a.fn.bootstrapToggle;a.fn.bootstrapToggle=b,a.fn.bootstrapToggle.Constructor=c,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=d,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(b){var c=a(this).find("input[type=checkbox]");c.bootstrapToggle("toggle"),b.preventDefault()})}(jQuery);
|
||||
//# sourceMappingURL=bootstrap2-toggle.min.js.map
|
|
@ -0,0 +1 @@
|
|||
{"version":3,"file":"bootstrap2-toggle.min.js","sources":["bootstrap2-toggle.js"],"names":["$","Plugin","option","this","each","$this","data","options","Toggle","element","$element","extend","defaults","render","VERSION","DEFAULTS","on","off","onstyle","offstyle","size","style","width","height","prototype","attr","_onstyle","_offstyle","$toggleOn","html","addClass","$toggleOff","$toggleHandle","$toggleGroup","append","$toggle","prop","wrap","parent","Math","max","outerWidth","css","update","trigger","toggle","silent","removeClass","enable","removeAttr","disable","change","proxy","destroy","remove","removeData","unwrap","old","fn","bootstrapToggle","Constructor","noConflict","document","e","$checkbox","find","preventDefault","jQuery"],"mappings":";;;;;;;CASE,SAAUA,GACV,YAoID,SAASC,GAAOC,GACf,MAAOC,MAAKC,KAAK,WAChB,GAAIC,GAAUL,EAAEG,MACZG,EAAUD,EAAMC,KAAK,aACrBC,EAA2B,gBAAVL,IAAsBA,CAEtCI,IAAMD,EAAMC,KAAK,YAAcA,EAAO,GAAIE,GAAOL,KAAMI,IACvC,gBAAVL,IAAsBI,EAAKJ,IAASI,EAAKJ,OAtItD,GAAIM,GAAS,SAAUC,EAASF,GAC/BJ,KAAKO,SAAYV,EAAES,GACnBN,KAAKI,QAAYP,EAAEW,UAAWR,KAAKS,WAAYL,GAC/CJ,KAAKU,SAGNL,GAAOM,QAAW,QAElBN,EAAOO,UACNC,GAAI,KACJC,IAAK,MACLC,QAAS,UACTC,SAAU,UACVC,KAAM,SACNC,MAAO,GACPC,MAAO,KACPC,OAAQ,MAGTf,EAAOgB,UAAUZ,SAAW,WAC3B,OACCI,GAAIb,KAAKO,SAASe,KAAK,YAAcjB,EAAOO,SAASC,GACrDC,IAAKd,KAAKO,SAASe,KAAK,aAAejB,EAAOO,SAASE,IACvDC,QAASf,KAAKO,SAASe,KAAK,iBAAmBjB,EAAOO,SAASG,QAC/DC,SAAUhB,KAAKO,SAASe,KAAK,kBAAoBjB,EAAOO,SAASI,SACjEC,KAAMjB,KAAKO,SAASe,KAAK,cAAgBjB,EAAOO,SAASK,KACzDC,MAAOlB,KAAKO,SAASe,KAAK,eAAiBjB,EAAOO,SAASM,MAC3DC,MAAOnB,KAAKO,SAASe,KAAK,eAAiBjB,EAAOO,SAASO,MAC3DC,OAAQpB,KAAKO,SAASe,KAAK,gBAAkBjB,EAAOO,SAASQ,SAI/Df,EAAOgB,UAAUX,OAAS,WACzBV,KAAKuB,SAAW,OAASvB,KAAKI,QAAQW,QACtCf,KAAKwB,UAAY,OAASxB,KAAKI,QAAQY,QACvC,IAAIC,GAA6B,UAAtBjB,KAAKI,QAAQa,KAAmB,YAClB,UAAtBjB,KAAKI,QAAQa,KAAmB,YACV,SAAtBjB,KAAKI,QAAQa,KAAkB,WAC/B,GACCQ,EAAY5B,EAAE,uBAAuB6B,KAAK1B,KAAKI,QAAQS,IACzDc,SAAS3B,KAAKuB,SAAW,IAAMN,GAC7BW,EAAa/B,EAAE,uBAAuB6B,KAAK1B,KAAKI,QAAQU,KAC1Da,SAAS3B,KAAKwB,UAAY,IAAMP,EAAO,WACrCY,EAAgBhC,EAAE,gDACpB8B,SAASV,GACPa,EAAejC,EAAE,8BACnBkC,OAAON,EAAWG,EAAYC,GAC5BG,EAAUnC,EAAE,iDACd8B,SAAU3B,KAAKO,SAAS0B,KAAK,WAAajC,KAAKuB,SAAWvB,KAAKwB,UAAU,QACzEG,SAASV,GAAMU,SAAS3B,KAAKI,QAAQc,MAEvClB,MAAKO,SAAS2B,KAAKF,GACnBnC,EAAEW,OAAOR,MACRgC,QAAShC,KAAKO,SAAS4B,SACvBV,UAAWA,EACXG,WAAYA,EACZE,aAAcA,IAEf9B,KAAKgC,QAAQD,OAAOD,EAEpB,IAAIX,GAAQnB,KAAKI,QAAQe,OAASiB,KAAKC,IAAIZ,EAAUN,QAASS,EAAWT,SAAUU,EAAcS,aAAa,EAC1GlB,EAASpB,KAAKI,QAAQgB,QAAUgB,KAAKC,IAAIZ,EAAUL,SAAUQ,EAAWR,SAC5EK,GAAUE,SAAS,aACnBC,EAAWD,SAAS,cACpB3B,KAAKgC,QAAQO,KAAMpB,MAAOA,EAAOC,OAAQA,IACrCpB,KAAKI,QAAQgB,SAChBK,EAAUc,IAAI,cAAed,EAAUL,SAAW,MAClDQ,EAAWW,IAAI,cAAeX,EAAWR,SAAW,OAErDpB,KAAKwC,QAAO,GACZxC,KAAKyC,SAAQ,IAGdpC,EAAOgB,UAAUqB,OAAS,WACrB1C,KAAKO,SAAS0B,KAAK,WAAYjC,KAAKc,MACnCd,KAAKa,MAGXR,EAAOgB,UAAUR,GAAK,SAAU8B,GAC/B,MAAI3C,MAAKO,SAAS0B,KAAK,aAAoB,GAC3CjC,KAAKgC,QAAQY,YAAY5C,KAAKwB,UAAY,QAAQG,SAAS3B,KAAKuB,UAChEvB,KAAKO,SAAS0B,KAAK,WAAW,QACzBU,GAAQ3C,KAAKyC,aAGnBpC,EAAOgB,UAAUP,IAAM,SAAU6B,GAChC,MAAI3C,MAAKO,SAAS0B,KAAK,aAAoB,GAC3CjC,KAAKgC,QAAQY,YAAY5C,KAAKuB,UAAUI,SAAS3B,KAAKwB,UAAY,QAClExB,KAAKO,SAAS0B,KAAK,WAAW,QACzBU,GAAQ3C,KAAKyC,aAGnBpC,EAAOgB,UAAUwB,OAAS,WACzB7C,KAAKgC,QAAQc,WAAW,YACxB9C,KAAKO,SAAS0B,KAAK,YAAY,IAGhC5B,EAAOgB,UAAU0B,QAAU,WAC1B/C,KAAKgC,QAAQV,KAAK,WAAY,YAC9BtB,KAAKO,SAAS0B,KAAK,YAAY,IAGhC5B,EAAOgB,UAAUmB,OAAS,SAAUG,GAC/B3C,KAAKO,SAAS0B,KAAK,YAAajC,KAAK+C,UACpC/C,KAAK6C,SACN7C,KAAKO,SAAS0B,KAAK,WAAYjC,KAAKa,GAAG8B,GACtC3C,KAAKc,IAAI6B,IAGftC,EAAOgB,UAAUoB,QAAU,SAAUE,GACpC3C,KAAKO,SAASO,IAAI,oBACb6B,GAAQ3C,KAAKO,SAASyC,SAC3BhD,KAAKO,SAASM,GAAG,mBAAoBhB,EAAEoD,MAAM,WAC5CjD,KAAKwC,UACHxC,QAGJK,EAAOgB,UAAU6B,QAAU,WAC1BlD,KAAKO,SAASO,IAAI,oBAClBd,KAAK8B,aAAaqB,SAClBnD,KAAKO,SAAS6C,WAAW,aACzBpD,KAAKO,SAAS8C,SAiBf,IAAIC,GAAMzD,EAAE0D,GAAGC,eAEf3D,GAAE0D,GAAGC,gBAA8B1D,EACnCD,EAAE0D,GAAGC,gBAAgBC,YAAcpD,EAKnCR,EAAE0D,GAAGb,OAAOgB,WAAa,WAExB,MADA7D,GAAE0D,GAAGC,gBAAkBF,EAChBtD,MAMRH,EAAE,WACDA,EAAE,6CAA6C2D,oBAGhD3D,EAAE8D,UAAU9C,GAAG,kBAAmB,2BAA4B,SAAS+C,GACtE,GAAIC,GAAYhE,EAAEG,MAAM8D,KAAK,uBAC7BD,GAAUL,gBAAgB,UAC1BI,EAAEG,oBAGFC"}
|
|
@ -8,6 +8,7 @@
|
|||
@import "jquery.mloading";
|
||||
@import "jquery-confirm.min";
|
||||
@import "bootstrap-datetimepicker.min";
|
||||
@import "bootstrap/bootstrap-toggle.min";
|
||||
|
||||
@import "codemirror/lib/codemirror";
|
||||
@import "editormd/css/editormd.min";
|
||||
|
@ -204,3 +205,13 @@ input.form-control {
|
|||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.table th, .table td {
|
||||
padding: 0.75rem 0.1rem;
|
||||
vertical-align: top;
|
||||
border-top: 1px solid #dee2e6;
|
||||
}
|
||||
|
||||
.table .thead-light th{
|
||||
white-space: nowrap;
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap-toggle.css v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
.checkbox label .toggle,
|
||||
.checkbox-inline .toggle {
|
||||
margin-left: -20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.toggle {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.toggle input[type="checkbox"] {
|
||||
display: none;
|
||||
}
|
||||
.toggle-group {
|
||||
position: absolute;
|
||||
width: 200%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
transition: left 0.35s;
|
||||
-webkit-transition: left 0.35s;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.toggle.off .toggle-group {
|
||||
left: -100%;
|
||||
}
|
||||
.toggle-on {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 50%;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.toggle-off {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.toggle-handle {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
height: 100%;
|
||||
width: 0px;
|
||||
border-width: 0 1px;
|
||||
}
|
||||
|
||||
.toggle.btn { min-width: 59px; min-height: 34px; }
|
||||
.toggle-on.btn { padding-right: 24px; }
|
||||
.toggle-off.btn { padding-left: 24px; }
|
||||
|
||||
.toggle.btn-lg { min-width: 79px; min-height: 45px; }
|
||||
.toggle-on.btn-lg { padding-right: 31px; }
|
||||
.toggle-off.btn-lg { padding-left: 31px; }
|
||||
.toggle-handle.btn-lg { width: 40px; }
|
||||
|
||||
.toggle.btn-sm { min-width: 50px; min-height: 30px;}
|
||||
.toggle-on.btn-sm { padding-right: 20px; }
|
||||
.toggle-off.btn-sm { padding-left: 20px; }
|
||||
|
||||
.toggle.btn-xs { min-width: 35px; min-height: 22px;}
|
||||
.toggle-on.btn-xs { padding-right: 12px; }
|
||||
.toggle-off.btn-xs { padding-left: 12px; }
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap-toggle.css v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
.checkbox label .toggle,.checkbox-inline .toggle{margin-left:-20px;margin-right:5px}
|
||||
.toggle{position:relative;overflow:hidden}
|
||||
.toggle input[type=checkbox]{display:none}
|
||||
.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none}
|
||||
.toggle.off .toggle-group{left:-100%}
|
||||
.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0}
|
||||
.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0}
|
||||
.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px}
|
||||
.toggle.btn{min-width:59px;min-height:34px}
|
||||
.toggle-on.btn{padding-right:24px}
|
||||
.toggle-off.btn{padding-left:24px}
|
||||
.toggle.btn-lg{min-width:79px;min-height:45px}
|
||||
.toggle-on.btn-lg{padding-right:31px}
|
||||
.toggle-off.btn-lg{padding-left:31px}
|
||||
.toggle-handle.btn-lg{width:40px}
|
||||
.toggle.btn-sm{min-width:50px;min-height:30px}
|
||||
.toggle-on.btn-sm{padding-right:20px}
|
||||
.toggle-off.btn-sm{padding-left:20px}
|
||||
.toggle.btn-xs{min-width:35px;min-height:22px}
|
||||
.toggle-on.btn-xs{padding-right:12px}
|
||||
.toggle-off.btn-xs{padding-left:12px}
|
|
@ -0,0 +1,85 @@
|
|||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap2-toggle.css v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
label.checkbox .toggle,
|
||||
label.checkbox.inline .toggle {
|
||||
margin-left: -20px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.toggle {
|
||||
min-width: 40px;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
.toggle input[type="checkbox"] {
|
||||
display: none;
|
||||
}
|
||||
.toggle-group {
|
||||
position: absolute;
|
||||
width: 200%;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
transition: left 0.35s;
|
||||
-webkit-transition: left 0.35s;
|
||||
-moz-user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.toggle.off .toggle-group {
|
||||
left: -100%;
|
||||
}
|
||||
.toggle-on {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 50%;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.toggle-off {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
.toggle-handle {
|
||||
position: relative;
|
||||
margin: 0 auto;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 0px;
|
||||
height: 100%;
|
||||
width: 0px;
|
||||
border-width: 0 1px;
|
||||
}
|
||||
.toggle-handle.btn-mini {
|
||||
top: -1px;
|
||||
}
|
||||
.toggle.btn { min-width: 30px; }
|
||||
.toggle-on.btn { padding-right: 24px; }
|
||||
.toggle-off.btn { padding-left: 24px; }
|
||||
|
||||
.toggle.btn-large { min-width: 40px; }
|
||||
.toggle-on.btn-large { padding-right: 35px; }
|
||||
.toggle-off.btn-large { padding-left: 35px; }
|
||||
|
||||
.toggle.btn-small { min-width: 25px; }
|
||||
.toggle-on.btn-small { padding-right: 20px; }
|
||||
.toggle-off.btn-small { padding-left: 20px; }
|
||||
|
||||
.toggle.btn-mini { min-width: 20px; }
|
||||
.toggle-on.btn-mini { padding-right: 12px; }
|
||||
.toggle-off.btn-mini { padding-left: 12px; }
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*! ========================================================================
|
||||
* Bootstrap Toggle: bootstrap2-toggle.css v2.2.0
|
||||
* http://www.bootstraptoggle.com
|
||||
* ========================================================================
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
label.checkbox .toggle,label.checkbox.inline .toggle{margin-left:-20px;margin-right:5px}
|
||||
.toggle{min-width:40px;height:20px;position:relative;overflow:hidden}
|
||||
.toggle input[type=checkbox]{display:none}
|
||||
.toggle-group{position:absolute;width:200%;top:0;bottom:0;left:0;transition:left .35s;-webkit-transition:left .35s;-moz-user-select:none;-webkit-user-select:none}
|
||||
.toggle.off .toggle-group{left:-100%}
|
||||
.toggle-on{position:absolute;top:0;bottom:0;left:0;right:50%;margin:0;border:0;border-radius:0}
|
||||
.toggle-off{position:absolute;top:0;bottom:0;left:50%;right:0;margin:0;border:0;border-radius:0}
|
||||
.toggle-handle{position:relative;margin:0 auto;padding-top:0;padding-bottom:0;height:100%;width:0;border-width:0 1px}
|
||||
.toggle-handle.btn-mini{top:-1px}
|
||||
.toggle.btn{min-width:30px}
|
||||
.toggle-on.btn{padding-right:24px}
|
||||
.toggle-off.btn{padding-left:24px}
|
||||
.toggle.btn-large{min-width:40px}
|
||||
.toggle-on.btn-large{padding-right:35px}
|
||||
.toggle-off.btn-large{padding-left:35px}
|
||||
.toggle.btn-small{min-width:25px}
|
||||
.toggle-on.btn-small{padding-right:20px}
|
||||
.toggle-off.btn-small{padding-left:20px}
|
||||
.toggle.btn-mini{min-width:20px}
|
||||
.toggle-on.btn-mini{padding-right:12px}
|
||||
.toggle-off.btn-mini{padding-left:12px}
|
|
@ -1,14 +1,45 @@
|
|||
class AccountsController < ApplicationController
|
||||
before_action :require_login, only: [:login_check, :simple_update]
|
||||
include ApplicationHelper
|
||||
|
||||
#skip_before_action :check_account, :only => [:logout]
|
||||
|
||||
def simple_update
|
||||
simple_update_params.merge!(username: params[:username]&.gsub(/\s+/, ""))
|
||||
simple_update_params.merge!(email: params[:email]&.gsub(/\s+/, ""))
|
||||
simple_update_params.merge!(platform: (params[:platform] || 'forge')&.gsub(/\s+/, ""))
|
||||
Register::RemoteForm.new(simple_update_params).validate!
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
result = auto_update(current_user, simple_update_params)
|
||||
if result[:message].blank?
|
||||
render_ok
|
||||
else
|
||||
render_error(result[:message])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def index
|
||||
render json: session
|
||||
end
|
||||
|
||||
# 为了同步平台上未注册gitea的用户
|
||||
def gitea_register
|
||||
user = User.find_by(login: sync_gitea_params[:login])
|
||||
Users::SyncGiteaForm.new(sync_gitea_params.merge(user: user)).validate!
|
||||
return render_error("该用户已同步协作平台") if user.gitea_token.present? && user.gitea_uid.present?
|
||||
|
||||
result = create_gitea_user!(user, sync_gitea_params[:login], sync_gitea_params[:email], sync_gitea_params[:password])
|
||||
result[:user] ? render_ok : render_error(result[:message])
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(-1, e.message)
|
||||
end
|
||||
|
||||
# 其他平台同步注册的用户
|
||||
def remote_register
|
||||
Register::RemoteForm.new(remote_register_params).validate!
|
||||
username = params[:username]&.gsub(/\s+/, "")
|
||||
tip_exception("无法使用以下关键词:#{username},请重新命名") if ReversedKeyword.check_exists?(username)
|
||||
email = params[:email]&.gsub(/\s+/, "")
|
||||
|
@ -93,7 +124,9 @@ class AccountsController < ApplicationController
|
|||
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: @user.mail
|
||||
email: @user.mail,
|
||||
login_name: @user.login,
|
||||
source_id: 0
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||
|
@ -124,7 +157,6 @@ class AccountsController < ApplicationController
|
|||
password = register_params[:password].strip
|
||||
|
||||
# gitea用户注册, email, username, password
|
||||
|
||||
interactor = Gitea::RegisterInteractor.call({username: user.login, email: user.mail, password: password})
|
||||
if interactor.success?
|
||||
gitea_user = interactor.result
|
||||
|
@ -139,7 +171,6 @@ class AccountsController < ApplicationController
|
|||
else
|
||||
tip_exception(-1, interactor.error)
|
||||
end
|
||||
|
||||
rescue Register::BaseForm::EmailError => e
|
||||
render_error(-2, e.message)
|
||||
rescue Register::BaseForm::LoginError => e
|
||||
|
@ -193,7 +224,9 @@ class AccountsController < ApplicationController
|
|||
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: @user.mail
|
||||
email: @user.mail,
|
||||
login_name: @user.login,
|
||||
source_id: 0
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(@user.login, sync_params)
|
||||
|
@ -316,6 +349,11 @@ class AccountsController < ApplicationController
|
|||
render_ok
|
||||
end
|
||||
|
||||
def login_check
|
||||
Register::LoginCheckColumnsForm.new(check_params.merge(user: current_user)).validate!
|
||||
render_ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# type 事件类型 1:用户注册 2:忘记密码 3: 绑定手机 4: 绑定邮箱, 5: 验证手机号是否有效 # 如果有新的继续后面加
|
||||
|
@ -354,6 +392,10 @@ class AccountsController < ApplicationController
|
|||
{ login: pre + code, email: email, phone: phone }
|
||||
end
|
||||
|
||||
def sync_gitea_params
|
||||
params.permit(:login, :email, :password)
|
||||
end
|
||||
|
||||
def user_params
|
||||
params.require(:user).permit(:login, :email, :phone)
|
||||
end
|
||||
|
@ -370,4 +412,11 @@ class AccountsController < ApplicationController
|
|||
params.permit(:login, :namespace, :password, :code)
|
||||
end
|
||||
|
||||
def remote_register_params
|
||||
params.permit(:username, :email, :password, :platform)
|
||||
end
|
||||
|
||||
def simple_update_params
|
||||
params.permit(:username, :email, :password, :platform)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,10 +1,33 @@
|
|||
class Admins::DashboardsController < Admins::BaseController
|
||||
def index
|
||||
@active_user_count = User.where(last_login_on: today).count
|
||||
@weekly_active_user_count = User.where(last_login_on: current_week).count
|
||||
@month_active_user_count = User.where(last_login_on: current_month).count
|
||||
# 用户活跃数
|
||||
day_user_ids = CommitLog.where(created_at: today).pluck(:user_id).uniq
|
||||
weekly_user_ids = CommitLog.where(created_at: current_week).pluck(:user_id).uniq
|
||||
month_user_ids = CommitLog.where(created_at: current_month).pluck(:user_id).uniq
|
||||
@active_user_count = User.where(last_login_on: today).or(User.where(id: day_user_ids)).count
|
||||
@weekly_active_user_count = User.where(last_login_on: current_week).or(User.where(id: weekly_user_ids)).count
|
||||
@month_active_user_count = User.where(last_login_on: current_month).or(User.where(id: month_user_ids)).count
|
||||
user_ids = User.where(created_on: pre_week).pluck(:id).uniq
|
||||
weekly_keep_user_count = User.where(id: user_ids).where(last_login_on: current_week).count
|
||||
@weekly_keep_rate = format("%.2f", user_ids.size > 0 ? weekly_keep_user_count.to_f / user_ids.size : 0)
|
||||
|
||||
@new_user_count = User.where(created_on: current_month).count
|
||||
# 新用户注册数
|
||||
@day_new_user_count = User.where(created_on: today).count
|
||||
@weekly_new_user_count = User.where(created_on: current_week).count
|
||||
@month_new_user_count = User.where(created_on: current_month).count
|
||||
|
||||
# 活跃项目数
|
||||
day_project_ids = (CommitLog.where(created_at: today).pluck(:project_id).uniq + Issue.where(created_on: today).pluck(:project_id).uniq).uniq
|
||||
weekly_project_ids = (CommitLog.where(created_at: current_week).pluck(:project_id).uniq + Issue.where(created_on: current_week).pluck(:project_id).uniq).uniq
|
||||
month_project_ids = (CommitLog.where(created_at: current_month).pluck(:project_id).uniq + Issue.where(created_on: current_month).pluck(:project_id).uniq).uniq
|
||||
@day_active_project_count = Project.where(updated_on: today).or(Project.where(id: day_project_ids)).count
|
||||
@weekly_active_project_count = Project.where(updated_on: current_week).or(Project.where(id: weekly_project_ids)).count
|
||||
@month_active_project_count = Project.where(updated_on: current_month).or(Project.where(id: month_project_ids)).count
|
||||
|
||||
# 新增项目数
|
||||
@day_new_project_count = Project.where(created_on: today).count
|
||||
@weekly_new_project_count = Project.where(created_on: current_week).count
|
||||
@month_new_project_count = Project.where(created_on: current_month).count
|
||||
end
|
||||
|
||||
def month_active_user
|
||||
|
@ -42,10 +65,14 @@ class Admins::DashboardsController < Admins::BaseController
|
|||
end
|
||||
|
||||
def current_week
|
||||
7.days.ago.beginning_of_day..Time.now.end_of_day
|
||||
7.days.ago.end_of_day..Time.now.end_of_day
|
||||
end
|
||||
|
||||
def current_month
|
||||
30.days.ago.beginning_of_day..Time.now.end_of_day
|
||||
30.days.ago.end_of_day..Time.now.end_of_day
|
||||
end
|
||||
|
||||
def pre_week
|
||||
14.days.ago.end_of_day..7.days.ago.end_of_day
|
||||
end
|
||||
end
|
|
@ -0,0 +1,49 @@
|
|||
class Admins::FeedbacksController < Admins::BaseController
|
||||
before_action :get_feedback, only: [:new_history, :create_history, :destroy]
|
||||
|
||||
def index
|
||||
sort_by = Feedback.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
|
||||
sort_direction = %w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
|
||||
feedbacks = Feedback.order("#{sort_by} #{sort_direction}")
|
||||
@feedbacks = paginate(feedbacks)
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @feedback.destroy
|
||||
redirect_to admins_feedbacks_path
|
||||
flash[:success] = "反馈意见删除成功"
|
||||
else
|
||||
redirect_to admins_feedbacks_path
|
||||
flash[:danger] = "反馈意见删除失败"
|
||||
end
|
||||
end
|
||||
|
||||
def new_history
|
||||
@feedback_message_history = FeedbackMessageHistory.new
|
||||
end
|
||||
|
||||
def create_history
|
||||
@feedback_message_history = @feedback.feedback_message_histories.new(feedback_message_history_params)
|
||||
@feedback_message_history.user = current_user
|
||||
if @feedback_message_history.save
|
||||
redirect_to admins_feedbacks_path
|
||||
flash[:success] = "发送通知成功"
|
||||
else
|
||||
redirect_to admins_feedbacks_path
|
||||
flash[:danger] = @feedback_message_history.errors.full_messages.join(", ")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def feedback_params
|
||||
params.require(:feedback).permit!
|
||||
end
|
||||
|
||||
def feedback_message_history_params
|
||||
params.require(:feedback_message_history).permit(:title, :content)
|
||||
end
|
||||
|
||||
def get_feedback
|
||||
@feedback = Feedback.find_by_id(params[:id])
|
||||
end
|
||||
end
|
|
@ -2,7 +2,7 @@ class Admins::ImportUsersController < Admins::BaseController
|
|||
def create
|
||||
return render_error('请上传正确的文件') if params[:file].blank? || !params[:file].is_a?(ActionDispatch::Http::UploadedFile)
|
||||
|
||||
result = Admins::ImportUserService.call(params[:file].to_io)
|
||||
result = Admins::ImportUserFromExcelService.call(params[:file].to_io)
|
||||
render_ok(result)
|
||||
rescue Admins::ImportUserService::Error => ex
|
||||
render_error(ex)
|
||||
|
|
|
@ -2,8 +2,24 @@ class Admins::MessageTemplatesController < Admins::BaseController
|
|||
before_action :get_template, only: [:edit, :update, :destroy]
|
||||
|
||||
def index
|
||||
message_templates = MessageTemplate.group(:type).count.keys
|
||||
@message_templates = kaminari_array_paginate(message_templates)
|
||||
message_templates = MessageTemplate.ransack(sys_notice_or_email_or_email_title_cont: params[:search]).result
|
||||
@message_templates = kaminari_paginate(message_templates)
|
||||
end
|
||||
|
||||
def new
|
||||
@message_template = MessageTemplate.new
|
||||
end
|
||||
|
||||
def create
|
||||
@message_template = MessageTemplate::CustomTip.new(message_template_params)
|
||||
@message_template.type = "MessageTemplate::CustomTip"
|
||||
if @message_template.save!
|
||||
redirect_to admins_message_templates_path
|
||||
flash[:success] = "创建消息模板成功"
|
||||
else
|
||||
render :new
|
||||
flash[:danger] = "创建消息模板失败"
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
|
@ -31,7 +47,9 @@ class Admins::MessageTemplatesController < Admins::BaseController
|
|||
|
||||
private
|
||||
def message_template_params
|
||||
params.require(@message_template.type.split("::").join("_").underscore.to_sym).permit!
|
||||
# type = @message_template.present? ? @message_template.type : "MessageTemplate::CustomTip"
|
||||
# params.require(type.split("::").join("_").underscore.to_sym).permit!
|
||||
params.require(:message_template).permit!
|
||||
end
|
||||
|
||||
def get_template
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
class Admins::NpsController < Admins::BaseController
|
||||
def index
|
||||
@on_off_switch = EduSetting.get("nps-on-off-switch").to_s == 'true'
|
||||
@user_nps = UserNp.joins(:user).order(created_at: :desc)
|
||||
keyword = params[:keyword].to_s.strip.presence
|
||||
if keyword
|
||||
sql = 'CONCAT(users.lastname, users.firstname) LIKE :keyword OR users.nickname LIKE :keyword OR users.login LIKE :keyword OR users.mail LIKE :keyword OR users.phone LIKE :keyword'
|
||||
@user_nps = @user_nps.where(sql, keyword: "%#{keyword}%")
|
||||
end
|
||||
@user_nps = @user_nps.where("action_type != 'close'") if params[:done_score].present?
|
||||
@min_score = @user_nps.where("action_type != 'close'").minimum("score")
|
||||
@max_score = @user_nps.where("action_type != 'close'").maximum("score")
|
||||
@score_total_count = UserNp.where("action_type !='close'").count
|
||||
@user_nps = paginate @user_nps.includes(:user)
|
||||
end
|
||||
|
||||
def switch_change
|
||||
edu_setting = EduSetting.find_by(name: "nps-on-off-switch")
|
||||
if edu_setting.blank?
|
||||
edu_setting = EduSetting.new(name: "nps-on-off-switch")
|
||||
end
|
||||
edu_setting.value = params[:switch].to_s
|
||||
edu_setting.save
|
||||
render_ok
|
||||
end
|
||||
end
|
|
@ -1,6 +1,6 @@
|
|||
class Admins::ProjectIgnoresController < Admins::BaseController
|
||||
before_action :set_ignore, only: [:edit,:update, :destroy,:show]
|
||||
before_action :validate_params, only: [:create, :update]
|
||||
# before_action :validate_params, only: [:create, :update]
|
||||
|
||||
def index
|
||||
sort_by = Ignore.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
|
||||
|
@ -31,12 +31,12 @@ class Admins::ProjectIgnoresController < Admins::BaseController
|
|||
# }
|
||||
@project_ignore = Ignore.new(ignore_params)
|
||||
|
||||
if @project_ignore.save!
|
||||
if @project_ignore.save
|
||||
redirect_to admins_project_ignores_path
|
||||
flash[:success] = "创建成功"
|
||||
else
|
||||
render :new
|
||||
flash[:danger] = "创建失败"
|
||||
redirect_to admins_project_ignores_path
|
||||
flash[:danger] = @project_ignore.errors.full_messages.join(",")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -58,8 +58,8 @@ class Admins::ProjectIgnoresController < Admins::BaseController
|
|||
redirect_to admins_project_ignores_path
|
||||
flash[:success] = "更新成功"
|
||||
else
|
||||
render :edit
|
||||
flash[:danger] = "更新失败"
|
||||
redirect_to admins_project_ignores_path
|
||||
flash[:danger] = @project_ignore.errors.full_messages.join(",")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -98,23 +98,23 @@ class Admins::ProjectIgnoresController < Admins::BaseController
|
|||
params.require(:ignore).permit(:name,:content)
|
||||
end
|
||||
|
||||
def validate_params
|
||||
name = params[:ignore][:name]
|
||||
if name.blank?
|
||||
flash[:danger] = "名称不允许为空"
|
||||
redirect_to admins_project_ignores_path
|
||||
elsif check_ignore_present?(name) && @project_ignore.blank?
|
||||
flash[:danger] = "创建失败:名称已存在"
|
||||
redirect_to admins_project_ignores_path
|
||||
end
|
||||
end
|
||||
# def validate_params
|
||||
# name = params[:ignore][:name]
|
||||
# if name.blank?
|
||||
# flash[:danger] = "名称不允许为空"
|
||||
# redirect_to admins_project_ignores_path
|
||||
# elsif check_ignore_present?(name) && @project_ignore.blank?
|
||||
# flash[:danger] = "创建失败:名称已存在"
|
||||
# redirect_to admins_project_ignores_path
|
||||
# end
|
||||
# end
|
||||
|
||||
def check_ignore_present?(name)
|
||||
return true if name.blank?
|
||||
name_downcase = name.downcase
|
||||
name_upcase = name.upcase
|
||||
name_first_big = name.capitalize
|
||||
Ignore.exists?(name: name_downcase) || Ignore.exists?(name: name_upcase) || Ignore.exists?(name: name_first_big)
|
||||
end
|
||||
# def check_ignore_present?(name)
|
||||
# return true if name.blank?
|
||||
# name_downcase = name.downcase
|
||||
# name_upcase = name.upcase
|
||||
# name_first_big = name.capitalize
|
||||
# Ignore.exists?(name: name_downcase) || Ignore.exists?(name: name_upcase) || Ignore.exists?(name: name_first_big)
|
||||
# end
|
||||
|
||||
end
|
||||
|
|
|
@ -27,17 +27,18 @@ class Admins::ProjectLanguagesController < Admins::BaseController
|
|||
flash[:success] = '创建成功'
|
||||
else
|
||||
redirect_to admins_project_languages_path
|
||||
flash[:danger] = '创建失败'
|
||||
flash[:danger] = @project_language.errors.full_messages.join(",")
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
if @project_language.update_attribute(:name, @name)
|
||||
@project_language.attributes = {name: @name}
|
||||
if @project_language.save
|
||||
redirect_to admins_project_languages_path
|
||||
flash[:success] = '更新成功'
|
||||
else
|
||||
redirect_to admins_project_languages_path
|
||||
flash[:success] = '更新失败'
|
||||
flash[:danger] = @project_language.errors.full_messages.join(",")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
class Admins::ProjectLicensesController < Admins::BaseController
|
||||
before_action :set_license, only: [:edit,:update, :destroy,:show]
|
||||
before_action :validate_params, only: [:create, :update]
|
||||
# before_action :validate_params, only: [:create, :update]
|
||||
|
||||
def index
|
||||
sort_by = License.column_names.include?(params[:sort_by]) ? params[:sort_by] : 'created_at'
|
||||
|
@ -30,13 +30,12 @@ class Admins::ProjectLicensesController < Admins::BaseController
|
|||
# position: max_position
|
||||
# }
|
||||
@project_license = License.new(license_params)
|
||||
|
||||
if @project_license.save!
|
||||
if @project_license.save
|
||||
redirect_to admins_project_licenses_path
|
||||
flash[:success] = "创建成功"
|
||||
else
|
||||
render :new
|
||||
flash[:danger] = "创建失败"
|
||||
redirect_to admins_project_licenses_path
|
||||
flash[:danger] = @project_license.errors.full_messages.join(",")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -54,12 +53,13 @@ class Admins::ProjectLicensesController < Admins::BaseController
|
|||
# permissions: permissions.to_s,
|
||||
# limitations: limitations.to_s
|
||||
# }
|
||||
if @project_license.update_attributes(license_params)
|
||||
@project_license.attributes = license_params
|
||||
if @project_license.save
|
||||
redirect_to admins_project_licenses_path
|
||||
flash[:success] = "更新成功"
|
||||
else
|
||||
render :edit
|
||||
flash[:danger] = "更新失败"
|
||||
render admins_project_licenses_path
|
||||
flash[:danger] = @project_license.errors.full_messages.join(",")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -98,23 +98,23 @@ class Admins::ProjectLicensesController < Admins::BaseController
|
|||
params.require(:license).permit(:name,:content)
|
||||
end
|
||||
|
||||
def validate_params
|
||||
name = params[:license][:name]
|
||||
if name.blank?
|
||||
flash[:danger] = "名称不允许为空"
|
||||
redirect_to admins_project_licenses_path
|
||||
elsif check_license_present?(name) && @project_license.blank?
|
||||
flash[:danger] = "创建失败:名称已存在"
|
||||
redirect_to admins_project_licenses_path
|
||||
end
|
||||
end
|
||||
# def validate_params
|
||||
# name = params[:license][:name]
|
||||
# if name.blank?
|
||||
# flash[:danger] = "名称不允许为空"
|
||||
# redirect_to admins_project_licenses_path
|
||||
# elsif check_license_present?(name) && @project_license.blank?
|
||||
# flash[:danger] = "创建失败:名称已存在"
|
||||
# redirect_to admins_project_licenses_path
|
||||
# end
|
||||
# end
|
||||
|
||||
def check_license_present?(name)
|
||||
return true if name.blank?
|
||||
name_downcase = name.downcase
|
||||
name_upcase = name.upcase
|
||||
name_first_big = name.capitalize
|
||||
License.exists?(name: name_downcase) || License.exists?(name: name_upcase) || License.exists?(name: name_first_big)
|
||||
end
|
||||
# def check_license_present?(name)
|
||||
# return true if name.blank?
|
||||
# name_downcase = name.downcase
|
||||
# name_upcase = name.upcase
|
||||
# name_first_big = name.capitalize
|
||||
# License.exists?(name: name_downcase) || License.exists?(name: name_upcase) || License.exists?(name: name_first_big)
|
||||
# end
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
class Api::V1::BaseController < ApplicationController
|
||||
|
||||
include Api::ProjectHelper
|
||||
include Api::UserHelper
|
||||
include Api::PullHelper
|
||||
|
||||
# before_action :doorkeeper_authorize!
|
||||
# skip_before_action :user_setup
|
||||
|
||||
protected
|
||||
# def current_user
|
||||
# #client方法对接,需要一直带着用户标识uid
|
||||
# Rails.logger.info doorkeeper_token
|
||||
# if doorkeeper_token && doorkeeper_token.resource_owner_id.blank?
|
||||
# # return User.anonymous if params[:uid].nil?
|
||||
# # tip_exception("2222")
|
||||
# # return render_error('缺少用户标识!') if params[:uid].nil?
|
||||
# User.current = User.find(params[:uid])
|
||||
# else
|
||||
# User.find(doorkeeper_token.resource_owner_id) if doorkeeper_token
|
||||
# end
|
||||
# end
|
||||
|
||||
def limit
|
||||
params.fetch(:limit, 15)
|
||||
end
|
||||
def page
|
||||
params.fetch(:page, 1)
|
||||
end
|
||||
|
||||
# 具有对仓库的管理权限
|
||||
def require_manager_above
|
||||
@project = load_project
|
||||
return render_forbidden if !current_user.admin? && !@project.manager?(current_user)
|
||||
end
|
||||
|
||||
# 具有对仓库的操作权限
|
||||
def require_operate_above
|
||||
@project = load_project
|
||||
return render_forbidden if !current_user.admin? && !@project.operator?(current_user)
|
||||
end
|
||||
|
||||
# 具有仓库的操作权限或者fork仓库的操作权限
|
||||
def require_operate_above_or_fork_project
|
||||
@project = load_project
|
||||
puts !current_user.admin? && !@project.operator?(current_user) && !(@project.fork_project.present? && @project.fork_project.operator?(current_user))
|
||||
return render_forbidden if !current_user.admin? && !@project.operator?(current_user) && !(@project.fork_project.present? && @project.fork_project.operator?(current_user))
|
||||
end
|
||||
|
||||
# 具有对仓库的访问权限
|
||||
def require_public_and_member_above
|
||||
@project = load_project
|
||||
return render_forbidden if !@project.is_public && !current_user.admin? && !@project.member?(current_user)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,18 @@
|
|||
class Api::V1::Projects::BranchesController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:all]
|
||||
|
||||
def all
|
||||
@result_object = Api::V1::Projects::Branches::AllListService.call(@project, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
before_action :require_operate_above, only: [:create]
|
||||
|
||||
def create
|
||||
@result_object = Api::V1::Projects::Branches::CreateService.call(@project, branch_params, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
private
|
||||
def branch_params
|
||||
params.require(:branch).permit(:new_branch_name, :old_branch_name)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,8 @@
|
|||
class Api::V1::Projects::CodeStatsController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:index]
|
||||
|
||||
def index
|
||||
@result_object = Api::V1::Projects::CodeStats::ListService.call(@project, {ref: params[:ref]}, @project.owner&.gitea_token)
|
||||
# puts @result_object
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
class Api::V1::Projects::CommitsController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:index, :diff]
|
||||
|
||||
def index
|
||||
@result_object = Api::V1::Projects::Commits::ListService.call(@project, {page: page, limit: limit, sha: params[:sha]}, current_user&.gitea_token)
|
||||
puts @result_object
|
||||
end
|
||||
|
||||
def diff
|
||||
@result_object = Api::V1::Projects::Commits::DiffService.call(@project, params[:sha], current_user&.gitea_token)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
class Api::V1::Projects::ContentsController < Api::V1::BaseController
|
||||
before_action :require_operate_above_or_fork_project, only: [:batch]
|
||||
|
||||
def batch
|
||||
@batch_content_params = batch_content_params
|
||||
# 处理下author和committer信息,如果没传则默认为当前用户信息
|
||||
@batch_content_params.merge!(author_email: current_user.mail, author_name: current_user.login) if batch_content_params[:author_email].blank? && batch_content_params[:author_name].blank?
|
||||
@batch_content_params.merge!(committer_email: current_user.mail, committer_name: current_user.login) if batch_content_params[:committer_email].blank? && batch_content_params[:committer_name].blank?
|
||||
|
||||
@result_object = Api::V1::Projects::Contents::BatchCreateService.call(@project, @batch_content_params, @project.owner.gitea_token)
|
||||
end
|
||||
|
||||
private
|
||||
def batch_content_params
|
||||
params.require(:content).permit(:author_email, :author_name, :author_timeunix, :branch, :committer_email, :committer_name, :committer_timeunix, :message, :new_branch, files: [ :action_type, :content, :encoding, :file_path])
|
||||
end
|
||||
end
|
|
@ -0,0 +1,12 @@
|
|||
class Api::V1::Projects::GitController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:trees, :blobs]
|
||||
|
||||
def trees
|
||||
@result_object = Api::V1::Projects::Git::TreesService.call(@project, params[:sha], {recursive: params[:recursive], page: page, limit: limit}, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def blobs
|
||||
@result_object = Api::V1::Projects::Git::BlobsService.call(@project, params[:sha], current_user&.gitea_token)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
class Api::V1::Projects::Pulls::BaseController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above
|
||||
before_action :load_pull_request
|
||||
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
class Api::V1::Projects::Pulls::JournalsController < Api::V1::Projects::Pulls::BaseController
|
||||
|
||||
def index
|
||||
@journals = Api::V1::Projects::Pulls::Journals::ListService.call(@project, @pull_request, params, current_user)
|
||||
@journals = @journals.limit(200)
|
||||
end
|
||||
|
||||
def create
|
||||
@journal = Api::V1::Projects::Pulls::Journals::CreateService.call(@project, @pull_request, create_params, current_user)
|
||||
end
|
||||
|
||||
before_action :find_journal, only: [:update, :destroy]
|
||||
|
||||
def update
|
||||
@journal = Api::V1::Projects::Pulls::Journals::UpdateService.call(@project, @pull_request, @journal, update_params, current_user)
|
||||
end
|
||||
|
||||
def destroy
|
||||
if @journal.destroy
|
||||
render_ok
|
||||
else
|
||||
render_error("删除评论失败!")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def create_params
|
||||
params.permit(:parent_id, :line_code, :note, :commit_id, :path, :type, :review_id, :diff => {})
|
||||
end
|
||||
|
||||
def update_params
|
||||
params.permit(:note, :commit_id, :state)
|
||||
end
|
||||
|
||||
def find_journal
|
||||
@journal = @pull_request.journals.find_by_id(params[:id])
|
||||
return render_not_found unless @journal.present?
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,20 @@
|
|||
class Api::V1::Projects::Pulls::PullsController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above
|
||||
|
||||
def index
|
||||
@pulls = Api::V1::Projects::Pulls::ListService.call(@project, query_params)
|
||||
@pulls = kaminari_paginate(@pulls)
|
||||
end
|
||||
|
||||
before_action :load_pull_request, only: [:show]
|
||||
|
||||
def show
|
||||
@result_object = Api::V1::Projects::Pulls::GetService.call(@project, @pull_request, current_user&.gitea_token)
|
||||
@last_review = @pull_request.reviews.order(created_at: :desc).take
|
||||
end
|
||||
|
||||
private
|
||||
def query_params
|
||||
params.permit(:status, :keyword, :priority_id, :issue_tag_id, :version_id, :reviewer_id, :sort_by, :sort_direction)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
class Api::V1::Projects::Pulls::ReviewsController < Api::V1::Projects::Pulls::BaseController
|
||||
|
||||
def index
|
||||
@reviews = @pull_request.reviews
|
||||
@reviews = @reviews.where(status: params[:status]) if params[:status].present?
|
||||
# @reviews = kaminari_paginate(@reviews)
|
||||
end
|
||||
|
||||
before_action :require_reviewer, only: [:create]
|
||||
|
||||
def create
|
||||
@review = Api::V1::Projects::Pulls::Reviews::CreateService.call(@project, @pull_request, review_params, current_user)
|
||||
end
|
||||
|
||||
private
|
||||
def require_reviewer
|
||||
return render_forbidden('您没有审查权限,请联系项目管理员') if !current_user.admin? && !@pull_request.reviewers.exists?(current_user.id) && !@project.manager?(current_user)
|
||||
end
|
||||
|
||||
def review_params
|
||||
params.require(:review).permit(:content, :commit_id, :status)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,10 @@
|
|||
class Api::V1::Projects::Pulls::VersionsController < Api::V1::Projects::Pulls::BaseController
|
||||
|
||||
def index
|
||||
@result_object = Api::V1::Projects::Pulls::Versions::ListService.call(@project, @pull_request, {page: page, limit: limit}, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def diff
|
||||
@result_object = Api::V1::Projects::Pulls::Versions::GetDiffService.call(@project, @pull_request, params[:id], {filepath: params[:filepath]}, current_user&.gitea_token)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,61 @@
|
|||
class Api::V1::Projects::WebhooksController < Api::V1::BaseController
|
||||
before_action :require_manager_above
|
||||
before_action :find_webhook, only: [:show, :update, :destroy, :tests, :hooktasks]
|
||||
|
||||
def index
|
||||
# @result_object = Api::V1::Projects::Webhooks::ListService.call(@project, current_user&.gitea_token)
|
||||
@webhooks = @project.webhooks
|
||||
@webhooks = @webhooks.where(type: params[:type]) if params[:type].present?
|
||||
@webhooks = kaminari_paginate(@webhooks)
|
||||
end
|
||||
|
||||
def create
|
||||
return render_error("webhooks数量已到上限!请删除暂不使用的webhooks以进行添加操作") if @project.webhooks.size > 49
|
||||
@result_object = Api::V1::Projects::Webhooks::CreateService.call(@project, create_webhook_params, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def show
|
||||
@result_object = Api::V1::Projects::Webhooks::GetService.call(@project, params[:id], current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def update
|
||||
@result_object = Api::V1::Projects::Webhooks::UpdateService.call(@project, params[:id], webhook_params, current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@result_object = Api::V1::Projects::Webhooks::DeleteService.call(@project, params[:id], current_user&.gitea_token)
|
||||
if @result_object
|
||||
return render_ok
|
||||
else
|
||||
return render_error('删除失败!')
|
||||
end
|
||||
end
|
||||
|
||||
def tests
|
||||
@result_object = Api::V1::Projects::Webhooks::TestsService.call(@project, params[:id], current_user&.gitea_token)
|
||||
if @result_object
|
||||
return render_ok
|
||||
else
|
||||
return render_error('推送失败!')
|
||||
end
|
||||
end
|
||||
|
||||
def hooktasks
|
||||
@hooktasks = @webhook.tasks.where(is_delivered: true).order("delivered desc")
|
||||
@hooktasks = kaminari_paginate(@hooktasks)
|
||||
end
|
||||
|
||||
private
|
||||
def create_webhook_params
|
||||
params.require(:webhook).permit(:active, :branch_filter, :http_method, :url, :content_type, :secret, :type, events: [])
|
||||
end
|
||||
|
||||
def webhook_params
|
||||
params.require(:webhook).permit(:active, :branch_filter, :http_method, :url, :content_type, :secret, events: [])
|
||||
end
|
||||
|
||||
def find_webhook
|
||||
@webhook = Gitea::Webhook.find_by_id(params[:id])
|
||||
return render_not_found unless @webhook.present?
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
class Api::V1::ProjectsController < Api::V1::BaseController
|
||||
before_action :require_public_and_member_above, only: [:show, :compare, :blame]
|
||||
|
||||
def index
|
||||
render_ok
|
||||
end
|
||||
|
||||
def show
|
||||
@result_object = Api::V1::Projects::GetService.call(@project, current_user.gitea_token)
|
||||
end
|
||||
|
||||
def compare
|
||||
@result_object = Api::V1::Projects::CompareService.call(@project, params[:from], params[:to], current_user&.gitea_token)
|
||||
end
|
||||
|
||||
def blame
|
||||
@result_object = Api::V1::Projects::BlameService.call(@project, params[:sha], params[:filepath], current_user&.gitea_token)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,16 @@
|
|||
class Api::V1::Users::FeedbacksController < Api::V1::BaseController
|
||||
|
||||
before_action :load_observe_user
|
||||
before_action :check_auth_for_observe_user
|
||||
|
||||
def create
|
||||
@result = Api::V1::Users::Feedbacks::CreateService.call(@observe_user, feedback_params)
|
||||
return render_error("反馈意见创建失败.") if @result.nil?
|
||||
return render_ok
|
||||
end
|
||||
|
||||
private
|
||||
def feedback_params
|
||||
params.permit(:content)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
class Api::V1::Users::ProjectsController < Api::V1::BaseController
|
||||
before_action :load_observe_user
|
||||
|
||||
def index
|
||||
@object_results = Api::V1::Users::Projects::ListService.call(@observe_user, query_params, current_user)
|
||||
@projects = kaminari_paginate(@object_results)
|
||||
end
|
||||
|
||||
private
|
||||
def query_params
|
||||
params.permit(:category, :is_public, :project_type, :sort_by, :sort_direction, :search)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,81 @@
|
|||
class Api::V1::UsersController < Api::V1::BaseController
|
||||
|
||||
before_action :load_observe_user
|
||||
before_action :check_auth_for_observe_user
|
||||
|
||||
def send_email_vefify_code
|
||||
code = %W(0 1 2 3 4 5 6 7 8 9)
|
||||
verification_code = code.sample(6).join
|
||||
mail = params[:email]
|
||||
code_type = params[:code_type]
|
||||
|
||||
sign = Digest::MD5.hexdigest("#{OPENKEY}#{mail}")
|
||||
Rails.logger.info sign
|
||||
|
||||
tip_exception(501, "请求不合理") if sign != params[:smscode]
|
||||
|
||||
# 60s内不能重复发送
|
||||
send_email_limit_cache_key = "send_email_60_second_limit:#{mail}"
|
||||
tip_exception(-2, '请勿频繁操作') if Rails.cache.exist?(send_email_limit_cache_key)
|
||||
send_email_control = LimitForbidControl::SendEmailCode.new(mail)
|
||||
tip_exception(-2, '邮件发送太频繁,请稍后再试') if send_email_control.forbid?
|
||||
begin
|
||||
UserMailer.update_email(mail, verification_code).deliver_now
|
||||
|
||||
Rails.cache.write(send_email_limit_cache_key, 1, expires_in: 1.minute)
|
||||
send_email_control.increment!
|
||||
rescue Exception => e
|
||||
logger_error(e)
|
||||
tip_exception(-2,"邮件发送失败,请稍后重试")
|
||||
end
|
||||
ver_params = {code_type: code_type, code: verification_code, email: mail}
|
||||
last_code = VerificationCode.where(code_type: code_type, email: mail).last
|
||||
last_code.update_attributes!({created_at: Time.current - 10.minute}) if last_code.present?
|
||||
data = VerificationCode.new(ver_params)
|
||||
if data.save!
|
||||
render_ok
|
||||
else
|
||||
tip_exception(-1, "创建数据失败")
|
||||
end
|
||||
end
|
||||
|
||||
def check_password
|
||||
password = params[:password]
|
||||
return tip_exception(-5, "8~16位密码,支持字母数字和符号") unless password =~ CustomRegexp::PASSWORD
|
||||
return tip_exception(-5, "密码错误") unless @observe_user.check_password?(password)
|
||||
render_ok
|
||||
end
|
||||
|
||||
def check_email
|
||||
mail = strip(params[:email])
|
||||
return tip_exception(-2, "邮件格式有误") unless mail =~ CustomRegexp::EMAIL
|
||||
|
||||
exist_owner = Owner.find_by(mail: mail)
|
||||
return tip_exception(-2, '邮箱已被使用') if exist_owner
|
||||
render_ok
|
||||
end
|
||||
|
||||
def check_email_verify_code
|
||||
code = strip(params[:code])
|
||||
mail = strip(params[:email])
|
||||
code_type = params[:code_type]
|
||||
|
||||
return tip_exception(-2, "邮件格式有误") unless mail =~ CustomRegexp::EMAIL
|
||||
|
||||
verifi_code = VerificationCode.where(email: mail, code: code, code_type: code_type).last
|
||||
return render_ok if code == "123123" && EduSetting.get("code_debug") # 万能验证码,用于测试 # TODO 万能验证码,用于测试
|
||||
|
||||
return tip_exception(-6, "验证码不正确") if verifi_code&.code != code
|
||||
return tip_exception(-6, "验证码已失效") if !verifi_code&.effective?
|
||||
render_ok
|
||||
end
|
||||
|
||||
def update_email
|
||||
@result_object = Api::V1::Users::UpdateEmailService.call(@observe_user, params, current_user.gitea_token)
|
||||
if @result_object
|
||||
return render_ok
|
||||
else
|
||||
return render_error('更改邮箱失败!')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -174,11 +174,11 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def require_profile_completed
|
||||
tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed?
|
||||
# tip_exception(411, "请完善资料后再操作") unless User.current.profile_is_completed?
|
||||
end
|
||||
|
||||
def require_user_profile_completed(user)
|
||||
tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed?
|
||||
# tip_exception(412, "请用户完善资料后再操作") unless user.profile_is_completed?
|
||||
end
|
||||
|
||||
# 异常提醒
|
||||
|
@ -248,42 +248,57 @@ class ApplicationController < ActionController::Base
|
|||
#return if params[:controller] == "main"
|
||||
# Find the current user
|
||||
#Rails.logger.info("current_laboratory is #{current_laboratory} domain is #{request.subdomain}")
|
||||
User.current = find_current_user
|
||||
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
|
||||
|
||||
# 开放课程通过链接访问的用户
|
||||
if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
|
||||
content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
|
||||
|
||||
if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
|
||||
user = open_class_user
|
||||
if user
|
||||
start_user_session(user)
|
||||
set_autologin_cookie(user)
|
||||
if request.headers["Authorization"].present? && request.headers["Authorization"].start_with?('Bearer')
|
||||
tip_exception(401, "请登录后再操作!") unless valid_doorkeeper_token?
|
||||
if @doorkeeper_token.present?
|
||||
# client方法对接,需要一直带着用户标识uid
|
||||
if @doorkeeper_token.resource_owner_id.blank?
|
||||
tip_exception(-1, "缺少用户标识!") if params[:uid].nil?
|
||||
User.current = User.find(params[:uid])
|
||||
else
|
||||
User.current = User.find_by(id: @doorkeeper_token.resource_owner_id)
|
||||
end
|
||||
User.current = user
|
||||
end
|
||||
else
|
||||
User.current = find_current_user
|
||||
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
|
||||
|
||||
# 开放课程通过链接访问的用户
|
||||
if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
|
||||
content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
|
||||
|
||||
if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
|
||||
user = open_class_user
|
||||
if user
|
||||
start_user_session(user)
|
||||
set_autologin_cookie(user)
|
||||
end
|
||||
User.current = user
|
||||
end
|
||||
end
|
||||
|
||||
if !User.current.logged? && Rails.env.development?
|
||||
user = User.find 1
|
||||
User.current = user
|
||||
start_user_session(user)
|
||||
end
|
||||
|
||||
|
||||
# 测试版前端需求
|
||||
# logger.info("subdomain:#{request.subdomain}")
|
||||
# if request.subdomain != "www"
|
||||
# if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
|
||||
# User.current = User.find 81403
|
||||
# elsif params[:debug] == 'student'
|
||||
# User.current = User.find 8686
|
||||
# elsif params[:debug] == 'admin'
|
||||
# logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
|
||||
# user = User.find 36480
|
||||
# User.current = user
|
||||
# cookies.signed[:user_id] = user.id
|
||||
# end
|
||||
# end
|
||||
end
|
||||
|
||||
if !User.current.logged? && Rails.env.development?
|
||||
User.current = User.find 104
|
||||
end
|
||||
|
||||
|
||||
# 测试版前端需求
|
||||
logger.info("subdomain:#{request.subdomain}")
|
||||
# if request.subdomain != "www"
|
||||
# if params[:debug] == 'teacher' #todo 为了测试,记得讲debug删除
|
||||
# User.current = User.find 81403
|
||||
# elsif params[:debug] == 'student'
|
||||
# User.current = User.find 8686
|
||||
# elsif params[:debug] == 'admin'
|
||||
# logger.info "@@@@@@@@@@@@@@@@@@@@@@ debug mode....."
|
||||
# user = User.find 36480
|
||||
# User.current = user
|
||||
# cookies.signed[:user_id] = user.id
|
||||
# end
|
||||
# end
|
||||
# User.current = User.find 81403
|
||||
end
|
||||
|
||||
|
@ -686,7 +701,7 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
@project, @owner = Project.find_with_namespace(namespace, id)
|
||||
|
||||
if @project and current_user.can_read_project?(@project)
|
||||
if @project and (current_user.can_read_project?(@project) || controller_path == "projects/project_invite_links")
|
||||
logger.info "###########: has project and can read project"
|
||||
@project
|
||||
# elsif @project && current_user.is_a?(AnonymousUser)
|
||||
|
@ -694,9 +709,15 @@ class ApplicationController < ActionController::Base
|
|||
# @project = nil if !@project.is_public?
|
||||
# render_forbidden and return
|
||||
else
|
||||
logger.info "###########:project not found"
|
||||
@project = nil
|
||||
render_not_found and return
|
||||
if @project.present?
|
||||
logger.info "###########: has project and but can't read project"
|
||||
@project = nil
|
||||
render_forbidden and return
|
||||
else
|
||||
logger.info "###########:project not found"
|
||||
@project = nil
|
||||
render_not_found and return
|
||||
end
|
||||
end
|
||||
@project
|
||||
end
|
||||
|
@ -709,14 +730,20 @@ class ApplicationController < ActionController::Base
|
|||
Rails.application.config_for(:configuration)['platform_url'] || request.base_url
|
||||
end
|
||||
|
||||
def image_type?(str)
|
||||
default_type = %w(png jpg gif tif psd svg bmp webp jpeg ico psd)
|
||||
default_type.include?(str&.downcase)
|
||||
end
|
||||
|
||||
def convert_image!
|
||||
@image = params[:image]
|
||||
@image = @image.nil? && params[:user].present? ? params[:user][:image] : @image
|
||||
return unless @image.present?
|
||||
max_size = EduSetting.get('upload_avatar_max_size') || 2 * 1024 * 1024 # 2M
|
||||
if @image.class == ActionDispatch::Http::UploadedFile
|
||||
render_error('请上传文件') if @image.size.zero?
|
||||
render_error('文件大小超过限制') if @image.size > max_size.to_i
|
||||
return render_error('请上传文件') if @image.size.zero?
|
||||
return render_error('文件大小超过限制') if @image.size > max_size.to_i
|
||||
return render_error('头像格式不正确!') unless image_type?(File.extname(@image.original_filename.to_s)[1..-1])
|
||||
else
|
||||
image = @image.to_s.strip
|
||||
return render_error('请上传正确的图片') if image.blank?
|
||||
|
|
|
@ -31,11 +31,11 @@ class AttachmentsController < ApplicationController
|
|||
|
||||
def get_file
|
||||
normal_status(-1, "参数缺失") if params[:download_url].blank?
|
||||
url = URI.encode(params[:download_url].to_s.gsub("http:", "https:"))
|
||||
if url.starts_with?(base_url)
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
url = url.split(base_url)[1].gsub("api", "repos").gsub('?filepath=', '/').gsub('&', '?')
|
||||
url = base_url.starts_with?("https:") ? URI.encode(params[:download_url].to_s.gsub("http:", "https:")) : URI.encode(params[:download_url].to_s)
|
||||
if url.starts_with?(base_url) && !url.starts_with?("#{base_url}/repo")
|
||||
domain = GiteaService.gitea_config[:domain]
|
||||
api_url = GiteaService.gitea_config[:base_url]
|
||||
url = ("/repos"+url.split(base_url + "/api")[1]).gsub('?filepath=', '/').gsub('&', '?')
|
||||
request_url = [domain, api_url, url, "?ref=#{params[:ref]}&access_token=#{current_user&.gitea_token}"].join
|
||||
response = Faraday.get(request_url)
|
||||
filename = url.to_s.split("/").pop()
|
||||
|
@ -213,20 +213,17 @@ class AttachmentsController < ApplicationController
|
|||
def attachment_candown
|
||||
unless current_user.admin? || current_user.business?
|
||||
candown = true
|
||||
unless params[:type] == 'history'
|
||||
if @file.container && current_user.logged?
|
||||
if @file.container.is_a?(Issue)
|
||||
course = @file.container.project
|
||||
candown = course.member?(current_user)
|
||||
elsif @file.container.is_a?(Journal)
|
||||
course = @file.container.issue.project
|
||||
candown = course.member?(current_user)
|
||||
else
|
||||
course = nil
|
||||
end
|
||||
tip_exception(403, "您没有权限进入") if course.present? && !candown
|
||||
tip_exception(403, "您没有权限进入") if @file.container.is_a?(ApplyUserAuthentication)
|
||||
if @file.container
|
||||
if @file.container.is_a?(Issue)
|
||||
project = @file.container.project
|
||||
candown = project.is_public || (current_user.logged? && project.member?(current_user))
|
||||
elsif @file.container.is_a?(Journal)
|
||||
project = @file.container.issue.project
|
||||
candown = project.is_public || (current_user.logged? && project.member?(current_user))
|
||||
else
|
||||
project = nil
|
||||
end
|
||||
tip_exception(403, "您没有权限进入") if project.present? && !candown
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ class Ci::BaseController < ApplicationController
|
|||
namespace = params[:owner]
|
||||
id = params[:repo] || params[:id]
|
||||
|
||||
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id)
|
||||
@ci_user, @repo = Ci::Repo.find_with_namespace(namespace, id, current_user.login)
|
||||
end
|
||||
|
||||
def load_all_repo
|
||||
|
|
|
@ -14,12 +14,12 @@ class Ci::CloudAccountsController < Ci::BaseController
|
|||
|
||||
def create
|
||||
flag, msg = check_bind_cloud_account!
|
||||
return render_error(msg) if flag === true
|
||||
return tip_exception(msg) if flag === true
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
@cloud_account = bind_account!
|
||||
if @cloud_account.blank?
|
||||
render_error('激活失败, 请检查你的云服务器信息是否正确.')
|
||||
tip_exception('激活失败, 请检查你的云服务器信息是否正确.')
|
||||
raise ActiveRecord::Rollback
|
||||
else
|
||||
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
||||
|
@ -27,17 +27,17 @@ class Ci::CloudAccountsController < Ci::BaseController
|
|||
end
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def activate
|
||||
return render_error('请先认证') unless current_user.ci_certification?
|
||||
return tip_exception('请先认证') unless current_user.ci_certification?
|
||||
|
||||
begin
|
||||
@cloud_account = Ci::CloudAccount.find params[:id]
|
||||
ActiveRecord::Base.transaction do
|
||||
if @repo
|
||||
return render_error('该项目已经激活') if @repo.repo_active?
|
||||
return tip_exception('该项目已经激活') if @repo.repo_active?
|
||||
@repo.activate!(@project)
|
||||
else
|
||||
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
||||
|
@ -50,7 +50,7 @@ class Ci::CloudAccountsController < Ci::BaseController
|
|||
end
|
||||
render_ok
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -59,39 +59,39 @@ class Ci::CloudAccountsController < Ci::BaseController
|
|||
|
||||
def bind
|
||||
flag, msg = check_bind_cloud_account!
|
||||
return render_error(msg) if flag === true
|
||||
return tip_exception(msg) if flag === true
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
@cloud_account = bind_account!
|
||||
if @cloud_account.blank?
|
||||
render_error('激活失败, 请检查你的云服务器信息是否正确.')
|
||||
tip_exception('激活失败, 请检查你的云服务器信息是否正确.')
|
||||
raise ActiveRecord::Rollback
|
||||
else
|
||||
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
||||
end
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def trustie_bind
|
||||
account = params[:account].to_s
|
||||
return render_error("account不能为空.") if account.blank?
|
||||
return tip_exception("account不能为空.") if account.blank?
|
||||
|
||||
flag, msg = check_trustie_bind_cloud_account!
|
||||
return render_error(msg) if flag === true
|
||||
return tip_exception(msg) if flag === true
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
@cloud_account = trustie_bind_account!
|
||||
if @cloud_account.blank?
|
||||
render_error('激活失败, 请检查你的云服务器信息是否正确.')
|
||||
tip_exception('激活失败, 请检查你的云服务器信息是否正确.')
|
||||
raise ActiveRecord::Rollback
|
||||
else
|
||||
current_user.set_drone_step!(User::DEVOPS_UNVERIFIED)
|
||||
end
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def unbind
|
||||
|
@ -107,18 +107,18 @@ class Ci::CloudAccountsController < Ci::BaseController
|
|||
render_ok
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def oauth_grant
|
||||
password = params[:password].to_s
|
||||
return render_error('你输入的密码不正确.') unless current_user.check_password?(password)
|
||||
return tip_exception('你输入的密码不正确.') unless current_user.check_password?(password)
|
||||
|
||||
oauth = current_user.oauths.last
|
||||
return render_error("服务器出小差了.") if oauth.blank?
|
||||
return tip_exception("服务器出小差了.") if oauth.blank?
|
||||
|
||||
result = gitea_oauth_grant!(password, oauth)
|
||||
return render_error('授权失败.') unless result === true
|
||||
return tip_exception('授权失败.') unless result === true
|
||||
current_user.set_drone_step!(User::DEVOPS_CERTIFICATION)
|
||||
end
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
ActiveRecord::Base.transaction do
|
||||
size = Ci::Pipeline.where('branch=? and identifier=? and owner=?', params[:branch], params[:repo], params[:owner]).size
|
||||
if size > 0
|
||||
render_error("#{params[:branch]}分支已经存在流水线!")
|
||||
tip_exception("#{params[:branch]}分支已经存在流水线!")
|
||||
return
|
||||
end
|
||||
pipeline = Ci::Pipeline.new(pipeline_name: params[:pipeline_name], file_name: params[:file_name],owner: params[:owner],
|
||||
|
@ -53,7 +53,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
render_ok({id: pipeline.id})
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
# 在代码库创建文件
|
||||
|
@ -81,6 +81,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
repo_branch: pipeline.branch,
|
||||
repo_config: pipeline.file_name
|
||||
}
|
||||
Rails.logger.info("########create_params===#{create_params.to_json}")
|
||||
repo = Ci::Repo.create_repo(create_params)
|
||||
repo
|
||||
end
|
||||
|
@ -118,7 +119,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
end
|
||||
render_ok
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -132,7 +133,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
end
|
||||
render_ok
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def content
|
||||
|
@ -182,7 +183,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
render_ok
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def update_stage
|
||||
|
@ -192,7 +193,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
end
|
||||
render_ok
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def delete_stage
|
||||
|
@ -205,7 +206,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
render_ok
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def update_stage_index(pipeline_id, show_index, diff)
|
||||
|
@ -229,7 +230,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
unless steps.empty?
|
||||
steps.each do |step|
|
||||
unless step[:template_id]
|
||||
render_error('请选择模板!')
|
||||
tip_exception('请选择模板!')
|
||||
return
|
||||
end
|
||||
if !step[:id]
|
||||
|
@ -246,7 +247,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
render_ok
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def create_stage_step
|
||||
|
@ -262,7 +263,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
render_ok
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def update_stage_step
|
||||
|
@ -279,7 +280,7 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
render_ok
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def delete_stage_step
|
||||
|
@ -289,6 +290,6 @@ class Ci::PipelinesController < Ci::BaseController
|
|||
end
|
||||
render_ok
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -30,19 +30,19 @@ class Ci::ProjectsController < Ci::BaseController
|
|||
@file = interactor.result
|
||||
render_result(1, "更新成功")
|
||||
else
|
||||
render_error(interactor.error)
|
||||
tip_exception(interactor.error)
|
||||
end
|
||||
end
|
||||
|
||||
def activate
|
||||
return render_error('你还未认证') unless current_user.ci_certification?
|
||||
return tip_exception('你还未认证') unless current_user.ci_certification?
|
||||
|
||||
begin
|
||||
ActiveRecord::Base.transaction do
|
||||
if @repo
|
||||
return render_error('该项目已经激活') if @repo.repo_active?
|
||||
@repo.destroy! if @repo&.repo_user_id == 0
|
||||
return tip_exception('该项目已经激活') if @repo.repo_active?
|
||||
@repo.activate!(@project)
|
||||
return render_ok
|
||||
else
|
||||
@repo = Ci::Repo.auto_create!(@ci_user, @project)
|
||||
@ci_user.update_column(:user_syncing, false)
|
||||
|
@ -55,12 +55,12 @@ class Ci::ProjectsController < Ci::BaseController
|
|||
end
|
||||
render_ok
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
end
|
||||
|
||||
def deactivate
|
||||
return render_error('该项目已经取消激活') if !@repo.repo_active?
|
||||
return tip_exception('该项目已经取消激活') if !@repo.repo_active?
|
||||
|
||||
@project.update_column(:open_devops, false)
|
||||
@repo.deactivate_repos!
|
||||
|
|
|
@ -20,14 +20,14 @@ class Ci::SecretsController < Ci::BaseController
|
|||
if result["id"]
|
||||
render_ok
|
||||
else
|
||||
render_error(result["message"])
|
||||
tip_exception(result["message"])
|
||||
end
|
||||
else
|
||||
result = Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], options).create_secret
|
||||
if result["id"]
|
||||
render_ok
|
||||
else
|
||||
render_error(result["message"])
|
||||
tip_exception(result["message"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -39,14 +39,14 @@ class Ci::SecretsController < Ci::BaseController
|
|||
Ci::Drone::API.new(@ci_user.user_hash, ci_drone_url, params[:owner], params[:repo], {name: name}).delete_secret
|
||||
render_ok
|
||||
else
|
||||
render_error("参数名不能为空")
|
||||
tip_exception("参数名不能为空")
|
||||
end
|
||||
rescue Exception => ex
|
||||
render_ok
|
||||
end
|
||||
|
||||
def ci_drone_url
|
||||
user = User.find_by(login: params[:owner])
|
||||
user = User.find_by(login: params[:owner]) || User.find_by(login: current_user.login)
|
||||
user&.ci_cloud_account.drone_url
|
||||
end
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ class Ci::TemplatesController < Ci::BaseController
|
|||
end
|
||||
render_ok
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def update
|
||||
|
@ -63,7 +63,7 @@ class Ci::TemplatesController < Ci::BaseController
|
|||
)
|
||||
render_ok
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -73,7 +73,7 @@ class Ci::TemplatesController < Ci::BaseController
|
|||
end
|
||||
render_ok
|
||||
rescue Exception => ex
|
||||
render_error(ex.message)
|
||||
tip_exception(ex.message)
|
||||
end
|
||||
|
||||
#======流水线模板查询=====#
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
class CommitLogsController < ApplicationController
|
||||
|
||||
def create
|
||||
tip_exception "未认证" unless params[:token].to_s == "7917908927b6f1b792f2027a08a8b24a2de42c1692c2fd45da0dee5cf90a5af5"
|
||||
ref = params[:ref]
|
||||
user_name = params[:pusher][:login]
|
||||
user_mail = params[:pusher][:email]
|
||||
user = User.find_by(mail: user_mail)
|
||||
user = User.find_by(login: user_name) if user.blank?
|
||||
|
||||
repository_id = params[:repository][:id]
|
||||
repository_name = params[:repository][:name]
|
||||
repository_full_name = params[:repository][:full_name]
|
||||
owner_name = repository_full_name.split("/")[0]
|
||||
owner = User.find_by(login: owner_name)
|
||||
project = Project.where(identifier: repository_name).where(user_id: owner&.id)&.first
|
||||
project = Project.where(identifier: repository_name).where(gpid: repository_id)&.first if project.blank?
|
||||
project.update_column(:updated_on, Time.now) if project.present?
|
||||
params[:commits].each do |commit|
|
||||
commit_id = commit[:id]
|
||||
message = commit[:message]
|
||||
CommitLog.create(user: user, project: project, repository_id: repository_id,
|
||||
name: repository_name, full_name: repository_full_name,
|
||||
ref: ref, commit_id: commit_id, message: message)
|
||||
# 统计数据新增
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {commits: 1}, project.id)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
|
@ -6,22 +6,33 @@ class CompareController < ApplicationController
|
|||
end
|
||||
|
||||
def show
|
||||
load_compare_params
|
||||
compare
|
||||
@merge_status, @merge_message = get_merge_message
|
||||
if params[:type] == "sha"
|
||||
load_compare_params
|
||||
@compare_result ||= gitea_compare(@base, @head)
|
||||
else
|
||||
load_compare_params
|
||||
compare
|
||||
@merge_status, @merge_message = get_merge_message
|
||||
end
|
||||
@page_size = page_size <= 0 ? 1 : page_size
|
||||
@page_limit = page_limit <=0 ? 15 : page_limit
|
||||
@page_offset = (@page_size -1) * @page_limit
|
||||
Rails.logger.info("+========#{@page_size}-#{@page_limit}-#{@page_offset}")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_merge_message
|
||||
if @base.blank? || @head.blank?
|
||||
return -2, "请选择分支"
|
||||
else
|
||||
return -2, "目标仓库未开启合并请求(PR)功能" unless @project.has_menu_permission("pulls")
|
||||
if @head.include?(":")
|
||||
fork_project = @project.forked_projects.joins(:owner).where(users: {login: @head.to_s.split("/")[0]}).take
|
||||
fork_project = @project.forked_projects.joins(:owner).where(users: { login: @head.to_s.split("/")[0] }).take
|
||||
return -2, "请选择正确的仓库" unless fork_project.present?
|
||||
@exist_pullrequest = @project.pull_requests.where(is_original: true, head: @head.to_s.split(":")[1], base: @base, status: 0, fork_project_id: fork_project.id).take
|
||||
else
|
||||
@exist_pullrequest = @project.pull_requests.where(is_original: false, head: @base, base: @head, status: 0).take
|
||||
@exist_pullrequest = @project.pull_requests.where(is_original: false, head: @base, base: @head, status: 0).last
|
||||
end
|
||||
if @exist_pullrequest.present?
|
||||
return -2, "在这些分支之间的合并请求已存在:<a href='/#{@owner.login}/#{@project.identifier}/pulls/#{@exist_pullrequest.id}'>#{@exist_pullrequest.try(:title)}</a>"
|
||||
|
@ -42,12 +53,22 @@ class CompareController < ApplicationController
|
|||
end
|
||||
|
||||
def load_compare_params
|
||||
@base = Addressable::URI.unescape(params[:base])
|
||||
@head = params[:head].include?('json') ? params[:head]&.split('.json')[0] : params[:head]
|
||||
|
||||
# @base = Addressable::URI.unescape(params[:base])
|
||||
@base = params[:base].include?(":") ? Addressable::URI.unescape(params[:base].split(":")[0]) + ':' + Base64.decode64(params[:base].split(":")[1]) : Base64.decode64(params[:base])
|
||||
@head = params[:head].include?('.json') ? params[:head][0..-6] : params[:head]
|
||||
# @head = Addressable::URI.unescape(@head)
|
||||
@head = @head.include?(":") ? Addressable::URI.unescape(@head.split(":")[0]) + ':' + Base64.decode64(@head.split(":")[1]) : Base64.decode64(@head)
|
||||
end
|
||||
|
||||
def gitea_compare(base, head)
|
||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, base, head, current_user.gitea_token)
|
||||
Gitea::Repository::Commits::CompareService.call(@owner.login, @project.identifier, Addressable::URI.escape(base), Addressable::URI.escape(head), current_user.gitea_token)
|
||||
end
|
||||
|
||||
def page_size
|
||||
params.fetch(:page, 1).to_i
|
||||
end
|
||||
|
||||
def page_limit
|
||||
params.fetch(:limit, 15).to_i
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,15 +18,15 @@ module Acceleratorable
|
|||
end
|
||||
|
||||
def accelerator_domain
|
||||
Gitea.gitea_config[:accelerator]["domain"]
|
||||
GiteaService.gitea_config[:accelerator]["domain"]
|
||||
end
|
||||
|
||||
def accelerator_username
|
||||
Gitea.gitea_config[:accelerator]["access_key_id"]
|
||||
GiteaService.gitea_config[:accelerator]["access_key_id"]
|
||||
end
|
||||
|
||||
def config_accelerator?
|
||||
Gitea.gitea_config[:accelerator].present?
|
||||
GiteaService.gitea_config[:accelerator].present?
|
||||
end
|
||||
|
||||
def is_foreign_url?(clone_addr)
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
module Api::ProjectHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def load_project
|
||||
namespace = params[:owner]
|
||||
repo = params[:repo]
|
||||
|
||||
@project, @owner = Project.find_with_namespace(namespace, repo)
|
||||
|
||||
if @project
|
||||
logger.info "###########:project founded"
|
||||
@project
|
||||
else
|
||||
logger.info "###########:project not found"
|
||||
@project = nil
|
||||
render_not_found and return
|
||||
end
|
||||
@project
|
||||
end
|
||||
end
|
|
@ -0,0 +1,19 @@
|
|||
module Api::PullHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def load_pull_request
|
||||
pull_request_id = params[:pull_id] || params[:id]
|
||||
@pull_request = @project.pull_requests.where(gitea_number: pull_request_id).where.not(id: pull_request_id).take || PullRequest.find_by_id(pull_request_id)
|
||||
@issue = @pull_request&.issue
|
||||
if @pull_request
|
||||
logger.info "###########pull_request founded"
|
||||
@pull_request
|
||||
else
|
||||
logger.info "###########pull_request not found"
|
||||
@pull_request = nil
|
||||
render_not_found and return
|
||||
end
|
||||
|
||||
@pull_request
|
||||
end
|
||||
end
|
|
@ -0,0 +1,28 @@
|
|||
module Api::UserHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def load_observe_user
|
||||
username = params[:owner]
|
||||
|
||||
@observe_user = User.find_by(login: username)
|
||||
|
||||
if @observe_user
|
||||
logger.info "###########observe_user not founded"
|
||||
@observe_user
|
||||
else
|
||||
logger.info "###########observe_user not found"
|
||||
@observe_user = nil
|
||||
render_not_found and return
|
||||
end
|
||||
@observe_user
|
||||
end
|
||||
|
||||
# 是否具有查看用户或编辑用户的权限
|
||||
def check_auth_for_observe_user
|
||||
return render_forbidden unless current_user.admin? || @observe_user.id == current_user.id
|
||||
end
|
||||
|
||||
def strip(str)
|
||||
str.to_s.strip.presence
|
||||
end
|
||||
end
|
|
@ -160,9 +160,9 @@ module Ci::CloudAccountManageable
|
|||
state = SecureRandom.hex(8)
|
||||
# redirect_uri eg:
|
||||
# https://localhost:3000/login/oauth/authorize?client_id=94976481-ad0e-4ed4-9247-7eef106007a2&redirect_uri=http%3A%2F%2F121.69.81.11%3A80%2Flogin&response_type=code&state=9cab990b9cfb1805
|
||||
redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login")
|
||||
clientId = client_id(oauth)
|
||||
grant_url = "#{Gitea.gitea_config[:domain]}/login/oauth/authorize?client_id=#{clientId}&redirect_uri=#{redirect_uri}&response_type=code&state=#{state}"
|
||||
# redirect_uri = CGI.escape("#{@cloud_account.drone_url}/login")
|
||||
# clientId = client_id(oauth)
|
||||
grant_url = "#{@cloud_account.drone_url}/login"
|
||||
logger.info "[gitea] grant_url: #{grant_url}"
|
||||
|
||||
conn = Faraday.new(url: grant_url) do |req|
|
||||
|
@ -188,6 +188,7 @@ module Ci::CloudAccountManageable
|
|||
response = conn.get
|
||||
logger.info "[drone] response headers: #{response.headers}"
|
||||
|
||||
# true
|
||||
response.headers['location'].include?('error') ? false : true
|
||||
end
|
||||
|
||||
|
|
|
@ -35,15 +35,15 @@ module LaboratoryHelper
|
|||
# my_projects: "/users/#{current_user.try(:login)}/projects",
|
||||
# my_projects: "https://www.trustie.net/users/#{current_user.try(:login)}/user_projectlist",
|
||||
{
|
||||
new_syllabuses: "https://www.trustie.net/syllabuses/new",
|
||||
new_course: "https://www.trustie.net/courses/new",
|
||||
edit_account: "https://www.trustie.net/my/account",
|
||||
my_courses: "https://www.trustie.net/users/#{current_user.try(:login)}/user_courselist",
|
||||
new_syllabuses: "https://forge.educoder.net/syllabuses/new",
|
||||
new_course: "https://forge.educoder.net/courses/new",
|
||||
edit_account: "https://forge.educoder.net/my/account",
|
||||
my_courses: "https://forge.educoder.net/users/#{current_user.try(:login)}/user_courselist",
|
||||
my_projects: "/users/#{current_user.try(:login)}/projects",
|
||||
my_organ: "https://www.trustie.net/users/#{current_user.try(:login)}/user_organizations",
|
||||
default_url: Rails.application.config_for(:configuration)['platform_url'],
|
||||
tiding_url: "https://www.trustie.net/users/#{current_user.try(:login)}/user_messages",
|
||||
register_url: "https://www.trustie.net/login?login=false"
|
||||
my_organ: "https://forge.educoder.net/users/#{current_user.try(:login)}/user_organizations",
|
||||
default_url: "https://www.educoder.net/",
|
||||
tiding_url: "https://www.educoder.net/users/#{current_user.try(:login)}/user_tidings",
|
||||
register_url: "https://www.educoder.net/user/register"
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -11,7 +11,7 @@ module LoginHelper
|
|||
|
||||
def set_autologin_cookie(user)
|
||||
token = Token.get_or_create_permanent_login_token(user, "autologin")
|
||||
sync_user_token_to_trustie(user.login, token.value)
|
||||
# sync_user_token_to_trustie(user.login, token.value)
|
||||
|
||||
Rails.logger.info "###### def set_autologin_cookie and get_or_create_permanent_login_token result: #{token&.value}"
|
||||
cookie_options = {
|
||||
|
@ -108,10 +108,15 @@ module LoginHelper
|
|||
def sync_pwd_to_gitea!(user, hash={})
|
||||
return true if user.is_sync_pwd?
|
||||
|
||||
sync_params = { email: user.mail }
|
||||
sync_params = {
|
||||
login_name: user.name,
|
||||
source_id: 0,
|
||||
email: user.mail
|
||||
}
|
||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params.merge(hash))
|
||||
if interactor.success?
|
||||
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea success _########"
|
||||
user.update_column(:is_sync_pwd, true)
|
||||
true
|
||||
else
|
||||
Rails.logger.info "########_ login is #{user.login} sync_pwd_to_gitea fail!: #{interactor.error}"
|
||||
|
|
|
@ -1,30 +1,82 @@
|
|||
module RegisterHelper
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def autologin_register(username, email, password, platform= 'forge')
|
||||
def autologin_register(username, email, password, platform = 'forge', phone = nil, nickname =nil, need_edit_info = false)
|
||||
result = {message: nil, user: nil}
|
||||
email = email.blank? ? "#{username}@example.org" : email
|
||||
|
||||
user = User.new(admin: false, login: username, mail: email, type: "User")
|
||||
user.password = password
|
||||
user.platform = platform
|
||||
user.activate
|
||||
user.phone = phone if phone.present?
|
||||
user.nickname = nickname if nickname.present?
|
||||
if need_edit_info
|
||||
user.need_edit_info
|
||||
else
|
||||
user.activate
|
||||
end
|
||||
|
||||
return unless user.valid?
|
||||
|
||||
create_gitea_user!(user, username, email, password)
|
||||
end
|
||||
|
||||
def create_gitea_user!(forge_user, username, email, password=random_password)
|
||||
|
||||
interactor = Gitea::RegisterInteractor.call({username: username, email: email, password: password})
|
||||
if interactor.success?
|
||||
gitea_user = interactor.result
|
||||
result = Gitea::User::GenerateTokenService.call(username, password)
|
||||
user.gitea_token = result['sha1']
|
||||
user.gitea_uid = gitea_user[:body]['id']
|
||||
if user.save!
|
||||
UserExtension.create!(user_id: user.id)
|
||||
result[:user] = {id: user.id, token: user.gitea_token}
|
||||
result = {}
|
||||
if interactor.success? || interactor.result[:message].to_s.include?("已被注册")
|
||||
gitea_user = interactor.result[:message].to_s.include?("已被注册") ? Gitea::User::GetService.call(username, password) : interactor.result
|
||||
Rails.logger.info "##### [gitea] create_gitea_user result: #{gitea_user}"
|
||||
if gitea_user[:body].present?
|
||||
result = Gitea::User::GenerateTokenService.call(username, password)
|
||||
forge_user.gitea_token = result['sha1']
|
||||
forge_user.gitea_uid = gitea_user[:body]['id'] if gitea_user[:body].present? && gitea_user[:body]['id'] !=0
|
||||
forge_user.mail = email
|
||||
if forge_user.save
|
||||
UserExtension.create!(user_id: forge_user.id) if forge_user.user_extension.blank?
|
||||
result[:user] = {id: forge_user.id, token: forge_user.gitea_token}
|
||||
end
|
||||
else
|
||||
result[:message] = interactor.result[:message]
|
||||
end
|
||||
else
|
||||
result[:message] = interactor.error
|
||||
Rails.logger.info "##### [gitea] create_gitea_user result: #{interactor.result[:message]}"
|
||||
result[:message] = interactor.result[:message]
|
||||
end
|
||||
result
|
||||
end
|
||||
|
||||
def random_password
|
||||
"#{Random.rand(11111111)}"
|
||||
end
|
||||
|
||||
def auto_update(user, params={})
|
||||
return if params.blank?
|
||||
result = {message: nil, user: nil}
|
||||
before_login = user.login
|
||||
user.login = params[:username]
|
||||
user.password = params[:password]
|
||||
user.mail = params[:email]
|
||||
|
||||
if user.save!
|
||||
sync_params = {
|
||||
password: params[:password].to_s,
|
||||
email: params[:email],
|
||||
login_name: params[:username],
|
||||
new_name: params[:username],
|
||||
source_id: 0
|
||||
}
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(before_login, sync_params)
|
||||
if interactor.success?
|
||||
result[:user] = user
|
||||
else
|
||||
result[:message] = '用户同步Gitea失败!'
|
||||
end
|
||||
else
|
||||
result[:message] = user.errors.full_messages.join(",")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ module RenderHelper
|
|||
render json: { status: 0, message: 'success' }.merge(data)
|
||||
end
|
||||
|
||||
def render_error(status = -1, message = '')
|
||||
def render_error(message = '', status=-1)
|
||||
render json: { status: status, message: message }
|
||||
end
|
||||
|
||||
|
|
|
@ -5,7 +5,26 @@ module Repository::LanguagesPercentagable
|
|||
result = Gitea::Repository::Languages::ListService.call(@owner.login,
|
||||
@repository.identifier, current_user&.gitea_token)
|
||||
|
||||
result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil
|
||||
@transform_language = @transform_language = result[:status] === :success ? hash_transform_precentagable(result[:body]) : nil
|
||||
update_project_language(@transform_language) unless @transform_language.nil?
|
||||
@transform_language
|
||||
end
|
||||
|
||||
def update_project_language(language)
|
||||
return if @project.project_language.present?
|
||||
db_language = ProjectLanguage.find_or_create_by!(name: language.keys.first.downcase.upcase_first)
|
||||
@project.update_column(:project_language_id, db_language.id)
|
||||
rescue
|
||||
return
|
||||
update_project_language(@transform_language) unless @transform_language.nil?
|
||||
@transform_language
|
||||
end
|
||||
|
||||
def update_project_language(language)
|
||||
db_language = ProjectLanguage.find_or_create_by!(name: language.keys.first.downcase.upcase_first)
|
||||
@project.update_column(:project_language_id, db_language.id) if @project.project_language_id.nil?
|
||||
rescue
|
||||
return
|
||||
end
|
||||
|
||||
# hash eq:{"JavaScript": 301681522,"Ruby": 1444004,"Roff": 578781}
|
||||
|
|
|
@ -6,14 +6,23 @@ class ForksController < ApplicationController
|
|||
|
||||
def create
|
||||
@new_project = Projects::ForkService.new(current_user, @project, params[:organization]).call
|
||||
|
||||
# TODO: fix Educoder shixun
|
||||
if @new_project.persisted?
|
||||
ProjectScore.create(:project_id => @new_project.id, :score => 0) if @new_project.project_score.nil?
|
||||
project_info = ProjectInfo.new(:user_id => current_user.id, :project_id => @new_project.id)
|
||||
@project.project_infos << project_info
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def authenticate_project!
|
||||
Rails.logger.info "authenticate_project1=======================#{current_user&.id},#{@project.user_id}"
|
||||
Rails.logger.info "authenticate_project2=======================#{current_user&.id == @project.user_id}"
|
||||
if current_user&.id == @project.user_id
|
||||
render_result(-1, "自己不能fork自己的项目")
|
||||
elsif Project.exists?(user_id: current_user.id, identifier: @project.identifier)
|
||||
render_result(-1, "fork失败,你已拥有了这个项目")
|
||||
render_result(0, "fork失败,你已拥有了这个项目")
|
||||
end
|
||||
# return if current_user != @project.owner
|
||||
# render_result(-1, "自己不能fork自己的项目")
|
||||
|
|
|
@ -2,12 +2,12 @@ class IssueTagsController < ApplicationController
|
|||
before_action :require_login, except: [:index]
|
||||
before_action :load_repository
|
||||
before_action :set_user
|
||||
before_action :check_issue_permission, except: :index
|
||||
before_action :check_issue_tags_permission
|
||||
before_action :set_issue_tag, only: [:edit, :update, :destroy]
|
||||
|
||||
|
||||
def index
|
||||
issue_tags = @project.issue_tags.reorder("#{order_name} #{order_type}")
|
||||
issue_tags = @project.issue_tags.includes(:issues).reorder("issue_tags.#{order_name} #{order_type}")
|
||||
@user_admin_or_member = current_user.present? && (current_user.admin || @project.member?(current_user))
|
||||
@page = params[:page] || 1
|
||||
@limit = params[:limit] || 15
|
||||
|
@ -17,7 +17,7 @@ class IssueTagsController < ApplicationController
|
|||
|
||||
|
||||
def create
|
||||
title = params[:name].to_s.strip.first(10)
|
||||
title = params[:name].to_s.strip.first(15)
|
||||
desc = params[:description].to_s.first(30)
|
||||
color = params[:color] || "#ccc"
|
||||
|
||||
|
@ -29,7 +29,7 @@ class IssueTagsController < ApplicationController
|
|||
|
||||
if title.present?
|
||||
if IssueTag.exists?(name: title, project_id: @project.id)
|
||||
normal_status(-1, "标签已存在")
|
||||
normal_status(-1, "项目标记已存在")
|
||||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
begin
|
||||
|
@ -37,12 +37,12 @@ class IssueTagsController < ApplicationController
|
|||
if issue_tag.save
|
||||
# gitea_tag = Gitea::Labels::CreateService.new(current_user, @repository.try(:identifier), tag_params).call
|
||||
# if gitea_tag && issue_tag.update_attributes(gid: gitea_tag["id"], gitea_url: gitea_tag["url"])
|
||||
# normal_status(0, "标签创建成功")
|
||||
normal_status(0, "项目标记创建成功!")
|
||||
# else
|
||||
# normal_status(-1, "标签创建失败")
|
||||
# normal_status(-1, "项目标记创建失败")
|
||||
# end
|
||||
else
|
||||
normal_status(-1, "标签创建失败")
|
||||
normal_status(-1, "项目标记创建失败")
|
||||
end
|
||||
rescue => e
|
||||
puts "create version release error: #{e.message}"
|
||||
|
@ -51,7 +51,7 @@ class IssueTagsController < ApplicationController
|
|||
end
|
||||
end
|
||||
else
|
||||
normal_status(-1, "标签名称不能为空")
|
||||
normal_status(-1, "项目标记名称不能为空")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -60,8 +60,8 @@ class IssueTagsController < ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
title = params[:name]
|
||||
desc = params[:description]
|
||||
title = params[:name].to_s.strip.first(15)
|
||||
desc = params[:description].to_s.first(30)
|
||||
color = params[:color] || "#ccc"
|
||||
|
||||
tag_params = {
|
||||
|
@ -71,19 +71,19 @@ class IssueTagsController < ApplicationController
|
|||
}
|
||||
if title.present?
|
||||
if IssueTag.exists?(name: title, project_id: @project.id) && (@issue_tag.name != title)
|
||||
normal_status(-1, "标签已存在")
|
||||
normal_status(-1, "项目标记已存在")
|
||||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
begin
|
||||
if @issue_tag.update_attributes(tag_params)
|
||||
# gitea_tag = Gitea::Labels::UpdateService.new(current_user, @repository.try(:identifier),@issue_tag.try(:gid), tag_params).call
|
||||
# if gitea_tag
|
||||
# normal_status(0, "标签更新成功")
|
||||
# normal_status(0, "项目标记更新成功")
|
||||
# else
|
||||
# normal_status(-1, "标签更新失败")
|
||||
# normal_status(-1, "项目标记更新失败")
|
||||
# end
|
||||
else
|
||||
normal_status(-1, "标签更新失败")
|
||||
normal_status(-1, "项目标记更新失败")
|
||||
end
|
||||
rescue => e
|
||||
puts "create version release error: #{e.message}"
|
||||
|
@ -92,7 +92,7 @@ class IssueTagsController < ApplicationController
|
|||
end
|
||||
end
|
||||
else
|
||||
normal_status(-1, "标签名称不能为空")
|
||||
normal_status(-1, "项目标记名称不能为空")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -102,12 +102,12 @@ class IssueTagsController < ApplicationController
|
|||
if @issue_tag.destroy
|
||||
# issue_tag = Gitea::Labels::DeleteService.new(@user, @repository.try(:identifier), @issue_tag.try(:gid)).call
|
||||
# if issue_tag
|
||||
# normal_status(0, "标签删除成功")
|
||||
# normal_status(0, "项目标记删除成功")
|
||||
# else
|
||||
# normal_status(-1, "标签删除失败")
|
||||
# normal_status(-1, "项目标记删除失败")
|
||||
# end
|
||||
else
|
||||
normal_status(-1, "标签删除失败")
|
||||
normal_status(-1, "项目标记删除失败")
|
||||
end
|
||||
rescue => e
|
||||
puts "create version release error: #{e.message}"
|
||||
|
@ -122,16 +122,16 @@ class IssueTagsController < ApplicationController
|
|||
@user = @project.owner
|
||||
end
|
||||
|
||||
def check_issue_permission
|
||||
unless @project.member?(current_user) || current_user.admin?
|
||||
normal_status(-1, "您没有权限")
|
||||
def check_issue_tags_permission
|
||||
unless @project.manager?(current_user) || current_user.admin?
|
||||
return render_forbidden('你不是管理员,没有权限操作')
|
||||
end
|
||||
end
|
||||
|
||||
def set_issue_tag
|
||||
@issue_tag = IssueTag.find_by_id(params[:id])
|
||||
unless @issue_tag.present?
|
||||
normal_status(-1, "标签不存在")
|
||||
normal_status(-1, "项目标记不存在")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ class IssuesController < ApplicationController
|
|||
include TagChosenHelper
|
||||
|
||||
def index
|
||||
@user_operate_issue = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user))
|
||||
@user_admin_or_member = current_user.present? && current_user.logged? && (current_user.admin || @project.member?(current_user) || @project.is_public?)
|
||||
issues = @project.issues.issue_issue.issue_index_includes
|
||||
issues = issues.where(is_private: false) unless @user_admin_or_member
|
||||
|
@ -23,13 +24,13 @@ class IssuesController < ApplicationController
|
|||
@filter_issues = @all_issues
|
||||
@filter_issues = @filter_issues.where.not(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::ADD
|
||||
@filter_issues = @filter_issues.where(status_id: IssueStatus::CLOSED) if params[:status_type].to_i == IssueStatus::SOLVING
|
||||
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@open_issues = @all_issues.where.not(status_id: IssueStatus::CLOSED)
|
||||
@close_issues = @all_issues.where(status_id: IssueStatus::CLOSED)
|
||||
@assign_to_me = @filter_issues.where(assigned_to_id: current_user&.id)
|
||||
@my_published = @filter_issues.where(author_id: current_user&.id)
|
||||
scopes = Issues::ListQueryService.call(issues,params.delete_if{|k,v| v.blank?}, "Issue")
|
||||
@issues_size = scopes.size
|
||||
@assign_to_me = scopes.where(assigned_to_id: current_user&.id)
|
||||
@my_published = scopes.where(author_id: current_user&.id)
|
||||
@issues = paginate(scopes)
|
||||
|
||||
respond_to do |format|
|
||||
|
@ -108,7 +109,7 @@ class IssuesController < ApplicationController
|
|||
|
||||
def create
|
||||
issue_params = issue_send_params(params)
|
||||
Issues::CreateForm.new({subject:issue_params[:subject]}).validate!
|
||||
Issues::CreateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate!
|
||||
@issue = Issue.new(issue_params)
|
||||
if @issue.save!
|
||||
SendTemplateMessageJob.perform_later('IssueAssigned', current_user.id, @issue&.id) if Site.has_notice_menu?
|
||||
|
@ -125,8 +126,14 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
end
|
||||
if params[:issue_tag_ids].present?
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
|
||||
return normal_status(-1, "最多只能创建一个标记。")
|
||||
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||
end
|
||||
else
|
||||
return normal_status(-1, "请输入正确的标记。")
|
||||
end
|
||||
end
|
||||
if params[:assigned_to_id].present?
|
||||
|
@ -142,11 +149,13 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
|
||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
@issue.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: ProjectTrend::CLOSE) if params[:status_id].to_i == 5
|
||||
|
||||
|
||||
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||
AtmeService.call(current_user, @atme_receivers, @issue) if @atme_receivers.size > 0
|
||||
|
||||
render json: {status: 0, message: "创建成", id: @issue.id}
|
||||
render json: {status: 0, message: "创建成功", id: @issue.id}
|
||||
else
|
||||
normal_status(-1, "创建失败")
|
||||
end
|
||||
|
@ -165,10 +174,17 @@ class IssuesController < ApplicationController
|
|||
last_token = @issue.token
|
||||
last_status_id = @issue.status_id
|
||||
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
||||
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
|
||||
@issue&.issue_tags_relates&.destroy_all
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
|
||||
if params[:issue_tag_ids].present?
|
||||
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
|
||||
return normal_status(-1, "最多只能创建一个标记。")
|
||||
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
|
||||
@issue&.issue_tags_relates&.destroy_all
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
next if tag == [""]
|
||||
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||
end
|
||||
else
|
||||
return normal_status(-1, "请输入正确的标记。")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -207,7 +223,7 @@ class IssuesController < ApplicationController
|
|||
normal_status(-1, "不允许修改为关闭状态")
|
||||
else
|
||||
issue_params = issue_send_params(params).except(:issue_classify, :author_id, :project_id)
|
||||
Issues::UpdateForm.new({subject:issue_params[:subject]}).validate!
|
||||
Issues::UpdateForm.new({subject: issue_params[:subject], description: issue_params[:description].blank? ? issue_params[:description] : issue_params[:description].b}).validate!
|
||||
if @issue.update_attributes(issue_params)
|
||||
if @issue&.pull_request.present?
|
||||
SendTemplateMessageJob.perform_later('PullRequestChanged', current_user.id, @issue&.pull_request&.id, @issue.previous_changes.slice(:assigned_to_id, :priority_id, :fixed_version_id, :issue_tags_value)) if Site.has_notice_menu?
|
||||
|
@ -231,7 +247,7 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
if params[:status_id].to_i == 5 #任务由非关闭状态到关闭状态时
|
||||
@issue.issue_times.update_all(end_time: Time.now)
|
||||
@issue.update_closed_issues_count_in_project!
|
||||
# @issue.update_closed_issues_count_in_project!
|
||||
if @issue.issue_type.to_s == "2" && last_status_id != 5
|
||||
if @issue.assigned_to_id.present? && last_status_id == 3 #只有当用户完成100%时,才给token
|
||||
post_to_chain("add", @issue.token, @issue.get_assign_user.try(:login))
|
||||
|
@ -473,7 +489,8 @@ class IssuesController < ApplicationController
|
|||
end
|
||||
|
||||
def operate_issue_permission
|
||||
return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || @project.is_public?)
|
||||
@issue = Issue.find_by_id(params[:id]) unless @issue.present?
|
||||
return render_forbidden("您没有权限进行此操作.") unless current_user.present? && current_user.logged? && (current_user.admin? || @project.member?(current_user) || (@project.is_public && @issue.nil?) || (@project.is_public && @issue.present? && @issue.author_id == current_user.id))
|
||||
end
|
||||
|
||||
def export_issues(issues)
|
||||
|
|
|
@ -23,6 +23,7 @@ class JournalsController < ApplicationController
|
|||
normal_status(-1, "评论内容不能为空")
|
||||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
Journals::CreateForm.new({notes: notes.to_s.strip.blank? ? notes.to_s.strip : notes.to_s.strip.b}).validate!
|
||||
journal_params = {
|
||||
journalized_id: @issue.id ,
|
||||
journalized_type: "Issue",
|
||||
|
@ -53,6 +54,9 @@ class JournalsController < ApplicationController
|
|||
end
|
||||
end
|
||||
end
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def destroy
|
||||
|
@ -71,6 +75,7 @@ class JournalsController < ApplicationController
|
|||
def update
|
||||
content = params[:content]
|
||||
if content.present?
|
||||
Journals::UpdateForm.new({notes: notes.to_s.strip.blank? ? notes.to_s.strip : notes.to_s.strip.b}).validate!
|
||||
if @journal.update_attribute(:notes, content)
|
||||
normal_status(0, "更新成功")
|
||||
else
|
||||
|
@ -79,7 +84,9 @@ class JournalsController < ApplicationController
|
|||
else
|
||||
normal_status(-1, "评论的内容不能为空")
|
||||
end
|
||||
|
||||
rescue Exception => exception
|
||||
puts exception.message
|
||||
normal_status(-1, exception.message)
|
||||
end
|
||||
|
||||
def get_children_journals
|
||||
|
|
|
@ -21,6 +21,14 @@ class MainController < ApplicationController
|
|||
uid_logger("main start is #{cookies[:_educoder_session]}")
|
||||
end
|
||||
|
||||
if params[:path] && params[:path].start_with?('projects/')
|
||||
project_id = params[:path].split("/")[1]
|
||||
project = Project.find_by_id(project_id)
|
||||
if project.present?
|
||||
return redirect_to("/projects/#{project.owner.login}/#{project.identifier}", status: 301)
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: 这块之后需要整合,者架构重新变化,统一跳转到index后再路由分发
|
||||
if params[:path] && params[:path]&.include?("h5educoderbuild") && params[:path].split("/").first == "h5educoderbuild"
|
||||
render file: 'public/h5educoderbuild/index.html', :layout => false, :content_type=> 'text/html'
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
class MarkFilesController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :load_project
|
||||
before_action :load_pull_request
|
||||
|
||||
def index
|
||||
@files_result = Gitea::PullRequest::FilesService.call(@owner.login, @project.identifier, @pull_request.gitea_number, current_user&.gitea_token, { "only-file-name": true })
|
||||
@mark_files = MarkFile.where(pull_request_id: @pull_request.id)
|
||||
end
|
||||
|
||||
def create
|
||||
# unless @pull_request.mark_files.present?
|
||||
# MarkFile.bulk_insert(*%i[pull_request_id, file_path_sha file_path created_at updated_at]) do |worker|
|
||||
# @files_result['Files'].each do |file|
|
||||
# worker.add(pull_request_id: @pull_request.id, file_path_sha: SecureRandom.uuid.gsub("-", ""), file_path: file['Name'])
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
end
|
||||
|
||||
def mark_file_as_unread
|
||||
tip_exception "参数错误" if params[:file_path_sha].blank?
|
||||
file_path = Base64.strict_decode64(params[:file_path_sha].to_s)
|
||||
mark_file = @pull_request.mark_files.find_or_initialize_by(file_path_sha: params[:file_path_sha])
|
||||
mark_file.file_path = file_path
|
||||
mark_file.user_id = current_user.id
|
||||
mark_file.mark_as_read = false
|
||||
mark_file.save
|
||||
render_ok
|
||||
rescue Exception => e
|
||||
tip_exception "参数解析错误"
|
||||
end
|
||||
|
||||
def mark_file_as_read
|
||||
tip_exception "参数错误" if params[:file_path_sha].blank?
|
||||
file_path = Base64.strict_decode64(params[:file_path_sha].to_s)
|
||||
mark_file = @pull_request.mark_files.find_or_initialize_by(file_path_sha: params[:file_path_sha])
|
||||
mark_file.file_path = file_path
|
||||
mark_file.user_id = current_user.id
|
||||
mark_file.mark_as_read = true
|
||||
mark_file.save
|
||||
render_ok
|
||||
rescue Exception => e
|
||||
tip_exception "参数解析错误"
|
||||
end
|
||||
|
||||
private
|
||||
def review_params
|
||||
params.require(:review).permit(:content, :commit_id, :status)
|
||||
end
|
||||
|
||||
def load_pull_request
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
end
|
|
@ -3,11 +3,19 @@ class MembersController < ApplicationController
|
|||
before_action :load_project
|
||||
before_action :find_user_with_id, only: %i[create remove change_role]
|
||||
before_action :check_user_profile_completed, only: [:create]
|
||||
before_action :operate!, except: %i[index]
|
||||
before_action :operate!
|
||||
before_action :check_member_exists!, only: %i[create]
|
||||
before_action :check_member_not_exists!, only: %i[remove change_role]
|
||||
|
||||
def create
|
||||
if @user.gitea_token.blank?
|
||||
result = Gitea::User::GetService.call(@user.login)
|
||||
if result[:status] == :error
|
||||
# gitea不存在用户@user,直接注册
|
||||
user_result = create_gitea_user!(@user, @user.login, @user.mail)
|
||||
return render_error(user_result[:message]) if user_result[:message]
|
||||
end
|
||||
end
|
||||
interactor = Projects::AddMemberInteractor.call(@project.owner, @project, @user)
|
||||
SendTemplateMessageJob.perform_later('ProjectJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
|
||||
SendTemplateMessageJob.perform_later('ProjectMemberJoined', current_user.id, @user.id, @project.id) if Site.has_notice_menu?
|
||||
|
@ -26,6 +34,9 @@ class MembersController < ApplicationController
|
|||
|
||||
@total_count = scope.size
|
||||
@members = paginate(scope)
|
||||
if @project.owner.is_a?(Organization) && (params[:page].to_i == 1 || params[:page].blank?) && !@project.members.exists?(user_id: current_user.id)
|
||||
@current_user_header_team = Team.joins(:team_users, :team_projects).where(team_projects: {project_id: @project.id}, team_users: {user_id: current_user.id}).order(authorize: :desc).take
|
||||
end
|
||||
end
|
||||
|
||||
def remove
|
||||
|
@ -61,11 +72,14 @@ class MembersController < ApplicationController
|
|||
end
|
||||
|
||||
def check_member_exists!
|
||||
return render_error("user_id为#{params[:user_id]}的用户已经是项目成员") if member_exists?
|
||||
@current_user_header_team = Team.joins(:team_users, :team_projects).where(team_projects: {project_id: @project.id}, team_users: {user_id: current_user.id}).order(authorize: :desc).take
|
||||
return render_error("#{@user&.nickname}已经是项目成员") if member_exists? || (params[:user_id].to_i == current_user.id && @current_user_header_team.present?)
|
||||
end
|
||||
|
||||
def check_member_not_exists!
|
||||
return render_error("user_id为#{params[:user_id]}的用户还不是项目成员") unless member_exists?
|
||||
@current_user_header_team = Team.joins(:team_users, :team_projects).where(team_projects: {project_id: @project.id}, team_users: {user_id: current_user.id}).order(authorize: :desc).take
|
||||
return render_error("用户为组织成员,请到组织下操作!") if (params[:user_id].to_i == current_user.id && @current_user_header_team.present?) && !member_exists?
|
||||
return render_error("#{@user&.nickname}还不是项目成员") unless member_exists?
|
||||
end
|
||||
|
||||
def check_user_profile_completed
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
class NoticesController < ApplicationController
|
||||
|
||||
def create
|
||||
return tip_exception("参数有误") if params["source"].blank?
|
||||
user_id = params[:user_id]
|
||||
|
||||
if params["source"] == "CompetitionBegin"
|
||||
competition_id = params[:competition_id]
|
||||
SendTemplateMessageJob.perform_later('CompetitionBegin', user_id, competition_id)
|
||||
elsif params["source"] == "CompetitionResult"
|
||||
competition_id = params[:competition_id]
|
||||
SendTemplateMessageJob.perform_later('CompetitionResult', user_id, competition_id)
|
||||
elsif params["source"] == "CompetitionReview"
|
||||
competition_id = params[:competition_id]
|
||||
SendTemplateMessageJob.perform_later('CompetitionReview', user_id, competition_id)
|
||||
elsif params["source"] == "CustomTip"
|
||||
users_id = params[:users_id]
|
||||
props = params[:props].to_unsafe_hash
|
||||
return tip_exception("参数有误") unless props.is_a?(Hash) && users_id.is_a?(Array)
|
||||
template_id = params[:template_id]
|
||||
SendTemplateMessageJob.perform_later('CustomTip', users_id, template_id, props)
|
||||
else
|
||||
tip_exception("#{params["source"]}未配置")
|
||||
end
|
||||
render_ok
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def params_props
|
||||
params.require(:notice).permit(:props)
|
||||
end
|
||||
end
|
|
@ -0,0 +1,17 @@
|
|||
class NpsController < ApplicationController
|
||||
|
||||
before_action :require_login
|
||||
|
||||
# close,关闭
|
||||
# createIssue,创建issue
|
||||
# createPullRequest,创建PR
|
||||
# auditPullRequest,审核PR
|
||||
# indexProject,项目主页
|
||||
# createProject,创建项目
|
||||
# createOrganization,创建组织
|
||||
def create
|
||||
tip_exception "缺少参数" if params[:action_id].blank? || params[:action_type].blank?
|
||||
UserNp.create(:action_id => params[:action_id].to_i, :action_type => params[:action_type], :user_id => User.current.id, :score => params[:score].to_f, memo: params[:memo])
|
||||
render_ok
|
||||
end
|
||||
end
|
|
@ -2,6 +2,7 @@ class Oauth::BaseController < ActionController::Base
|
|||
include RenderHelper
|
||||
include LoginHelper
|
||||
include ControllerRescueHandler
|
||||
include RegisterHelper
|
||||
# include LaboratoryHelper
|
||||
|
||||
skip_before_action :verify_authenticity_token
|
||||
|
@ -22,7 +23,7 @@ class Oauth::BaseController < ActionController::Base
|
|||
end
|
||||
|
||||
def auth_hash
|
||||
Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
|
||||
# Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
|
||||
request.env['omniauth.auth']
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
class Oauth::CallbacksController < Oauth::BaseController
|
||||
def create
|
||||
process_callback
|
||||
rescue Exception => e
|
||||
Rails.logger.info "授权失败:#{e}"
|
||||
tip_exception("授权失败")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def config_providers
|
||||
config = Rails.application.config_for(:configuration)
|
||||
config.dig("oauth").keys
|
||||
end
|
||||
|
||||
# QQ: {"ret":0,"msg":"","is_lost":0,"nickname":"颜值不算太高","gender":"男","gender_type":1,"province":"","city":"","year":"2013","constellation":"","figureurl":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/30","figureurl_1":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/50","figureurl_2":"http://qzapp.qlogo.cn/qzapp/101508858/0F860F4B329768F47B22341C5FD9089C/100","figureurl_qq_1":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=40\u0026t=1568887757","figureurl_qq_2":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=100\u0026t=1568887757","figureurl_qq":"http://thirdqq.qlogo.cn/g?b=oidb\u0026k=My3segFVHFqVmauibJQUltw\u0026s=140\u0026t=1568887757","figureurl_type":"1","is_yellow_vip":"0","vip":"0","yellow_vip_level":"0","level":"0","is_yellow_year_vip":"0"}
|
||||
def process_callback
|
||||
Rails.logger.info("[OAuth2] omniauth.auth -> #{request.env['omniauth.auth'].inspect}")
|
||||
if auth_hash.blank?
|
||||
redirect_to("/login") && return
|
||||
end
|
||||
|
||||
new_user = false
|
||||
platform = auth_hash[:provider]
|
||||
uid = auth_hash[:uid]
|
||||
mail = auth_hash.info.email || nil
|
||||
nickname = ["gitee", "github"].include?(platform) ? auth_hash.info.name : auth_hash.info.nickname
|
||||
|
||||
open_user = "OpenUsers::#{platform.to_s.capitalize}".constantize.find_by(uid: uid)
|
||||
if open_user.present? && open_user.user.present?
|
||||
successful_authentication(open_user.user)
|
||||
else
|
||||
if current_user.blank? || !current_user.logged?
|
||||
has_user = User.find_by(mail: mail)
|
||||
if has_user.present?
|
||||
"OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user_id: has_user.id, uid: uid, extra: auth_hash.extra)
|
||||
successful_authentication(has_user)
|
||||
else
|
||||
new_user = true
|
||||
login = build_login_name(platform, auth_hash.info.nickname)
|
||||
mail = "#{login}@example.org" if mail.blank?
|
||||
code = %W(0 1 2 3 4 5 6 7 8 9)
|
||||
rand_password = code.sample(10).join
|
||||
reg_result = autologin_register(login, mail, rand_password, platform, nil, nickname)
|
||||
Rails.logger.info("[OAuth2] omniauth.auth [reg_result] #{reg_result} ")
|
||||
if reg_result[:message].blank?
|
||||
open_user = "OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user_id: reg_result[:user][:id], uid: uid, extra: auth_hash.extra)
|
||||
successful_authentication(open_user.user)
|
||||
else
|
||||
tip_exception(reg_result.present? ? reg_result[:message] : "授权失败")
|
||||
end
|
||||
end
|
||||
else
|
||||
"OpenUsers::#{platform.to_s.capitalize}".constantize.create!(user: current_user, uid: login, extra: auth_hash.extra)
|
||||
end
|
||||
end
|
||||
redirect_to root_path(new_user: new_user)
|
||||
end
|
||||
|
||||
# gitee,github nickname=login,如果系统未占用保留原用户名
|
||||
def build_login_name(provider, nickname)
|
||||
if ["gitee", "github"].include?(provider) && User.find_by(login: nickname).blank?
|
||||
nickname
|
||||
else
|
||||
User.generate_user_login('p')
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,130 @@
|
|||
class ObRepositorySyncsController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :load_project
|
||||
before_action :load_ob_repository_sync, except: [:create]
|
||||
before_action :authenticate_user!
|
||||
|
||||
def index
|
||||
render_ok(data: @ob_repository_sync)
|
||||
end
|
||||
|
||||
|
||||
def create
|
||||
tip_exception "参数错误" if params[:github_address].blank? && params[:gitee_address].blank?
|
||||
project_name ="#{@project.owner.name}:#{@project.identifier}"
|
||||
service = ObRepositorySync::ApiService.new(project_name)
|
||||
domain = GiteaService.gitea_config[:domain]
|
||||
project_params = params.merge({ "gitlink_address": "#{domain}/#{@project.owner&.login}/#{@project.identifier}.git" })
|
||||
res = service.create_projects(project_params)
|
||||
tip_exception "保存失败: #{res["msg"]}" if res["code"].to_s != "200"
|
||||
sync_id = res["data"]["id"]
|
||||
ob_repository_sync = ObRepositorySync.find_or_initialize_by(project_id: @project.id)
|
||||
ob_repository_sync.project_id = @project.id
|
||||
ob_repository_sync.user_id = current_user.id
|
||||
ob_repository_sync.name = project_name
|
||||
ob_repository_sync.github_address = "#{params[:github_address]}"
|
||||
ob_repository_sync.gitee_address = "#{params[:gitee_address]}"
|
||||
ob_repository_sync.github_token = "#{params[:github_token]}"
|
||||
ob_repository_sync.gitee_token = "#{params[:gitee_token]}"
|
||||
ob_repository_sync.sync_id = sync_id
|
||||
ob_repository_sync.save!
|
||||
render_ok
|
||||
end
|
||||
|
||||
def delete
|
||||
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||
res = service.delete_project @ob_repository_sync.sync_id
|
||||
tip_exception "删除失败: #{res["msg"]}" if res["code"].to_s != "200"
|
||||
if res["code"].to_s == "200"
|
||||
@ob_repository_sync.destroy!
|
||||
end
|
||||
render_ok
|
||||
end
|
||||
|
||||
def jobs
|
||||
tip_exception "该项目未创建同步任务" if @ob_repository_sync.blank?
|
||||
page = params[:page] || 1
|
||||
limit = params[:limit] || 10
|
||||
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||
source = ""
|
||||
if params[:type] && params[:type].to_s.downcase == "github"
|
||||
source = "github_branch"
|
||||
elsif params[:type] && params[:type].to_s.downcase == "gitee"
|
||||
source = "gitee_branch"
|
||||
end
|
||||
res = service.get_projects_jobs(source, page, limit)
|
||||
data = res["data"]["list"]
|
||||
render_ok(count: res["data"]["total"], data: data)
|
||||
end
|
||||
|
||||
def create_jobs
|
||||
tip_exception "必须配置一个分支" if params[:github_branch].blank? && params[:gitee_branch].blank? && params[:gitlink_branch].blank?
|
||||
ob_jobs = ObRepositorySyncJob.where(ob_repository_sync_id: @ob_repository_sync.id)
|
||||
ob_jobs = ob_jobs.where(job_type: params[:job_type]) if params[:job_type].present?
|
||||
ob_jobs = ob_jobs.where(github_branch: params[:github_branch]) if params[:github_branch].present?
|
||||
ob_jobs = ob_jobs.where(gitee_branch: params[:gitee_branch]) if params[:gitee_branch].present?
|
||||
ob_jobs = ob_jobs.where(gitlink_branch: params[:gitlink_branch]) if params[:gitlink_branch].present?
|
||||
tip_exception "该分支组合已配置,不能重复!" if ob_jobs.count > 0
|
||||
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||
res = service.create_projects_jobs(params)
|
||||
tip_exception "保存失败: #{res["msg"]}" if res["code"].to_s != "200"
|
||||
job_id = res["data"]["id"]
|
||||
job = ObRepositorySyncJob.new
|
||||
job.ob_repository_sync_id = @ob_repository_sync.id
|
||||
job.github_branch = "#{params[:github_branch]}"
|
||||
job.gitee_branch = "#{params[:gitee_branch]}"
|
||||
job.gitlink_branch = "#{params[:gitlink_branch]}"
|
||||
job.job_type = "#{params[:job_type]}"
|
||||
job.base = "#{params[:base]}"
|
||||
job.job_id = job_id
|
||||
job.save
|
||||
render_ok
|
||||
end
|
||||
|
||||
|
||||
def delete_job
|
||||
tip_exception "缺少参数job_id" if params[:job_id].blank?
|
||||
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||
res = service.delete_job params[:job_id]
|
||||
tip_exception "删除失败: #{res["msg"]}" if res["code"].to_s != "200"
|
||||
job = ObRepositorySyncJob.find_by(ob_repository_sync_id: @ob_repository_sync.id, job_id: params[:job_id])
|
||||
job.destroy! if job.present?
|
||||
render_ok
|
||||
end
|
||||
|
||||
def start_job
|
||||
tip_exception "缺少参数job_id" if params[:job_id].blank?
|
||||
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||
res = service.start_job params[:job_id]
|
||||
tip_exception "启动错误: #{res["msg"]}" if res["code"].to_s != "200"
|
||||
render_ok
|
||||
end
|
||||
|
||||
def stop_job
|
||||
tip_exception "缺少参数job_id" if params[:job_id].blank?
|
||||
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||
res = service.stop_job params[:job_id]
|
||||
tip_exception "停止错误: #{res["msg"]}" if res["code"].to_s != "200"
|
||||
render_ok
|
||||
end
|
||||
|
||||
def job_logs
|
||||
tip_exception "该项目未创建同步任务" if @ob_repository_sync.blank?
|
||||
tip_exception "缺少参数job_id" if params[:job_id].blank?
|
||||
service = ObRepositorySync::ApiService.new(@ob_repository_sync.name)
|
||||
res = service.job_logs params[:job_id]
|
||||
tip_exception "请求错误: #{res["msg"]}" if res["code"].to_s != "200"
|
||||
render_ok(count: res["data"]["total"], data: res["data"]["list"])
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_ob_repository_sync
|
||||
@ob_repository_sync = ObRepositorySync.find_by(project_id: @project.id)
|
||||
end
|
||||
|
||||
def authenticate_user!
|
||||
return if @project.member?(current_user) || current_user.admin?
|
||||
render_forbidden('你没有权限操作')
|
||||
end
|
||||
end
|
|
@ -4,8 +4,14 @@ class Organizations::OrganizationUsersController < Organizations::BaseController
|
|||
|
||||
def index
|
||||
@organization_users = @organization.organization_users.includes(:user)
|
||||
search = params[:search].to_s.downcase
|
||||
@organization_users = @organization_users.joins(:user).merge(User.like(search))
|
||||
if params[:search].present?
|
||||
search = params[:search].to_s.downcase
|
||||
user_condition_users = User.like(search).to_sql
|
||||
team_condition_teams = User.joins(:teams).merge(@organization.teams.like(search)).to_sql
|
||||
users = User.from("( #{user_condition_users} UNION #{team_condition_teams }) AS users")
|
||||
|
||||
@organization_users = @organization_users.where(user_id: users).distinct
|
||||
end
|
||||
|
||||
@organization_users = kaminari_paginate(@organization_users)
|
||||
end
|
||||
|
|
|
@ -28,9 +28,10 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
|||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
tip_exception("无法使用以下关键词:#{organization_params[:name]},请重新命名") if ReversedKeyword.check_exists?(organization_params[:name])
|
||||
Organizations::CreateForm.new(organization_params).validate!
|
||||
Organizations::CreateForm.new(organization_params.merge(original_name: "")).validate!
|
||||
@organization = Organizations::CreateService.call(current_user, organization_params)
|
||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||
Cache::V2::OwnerCommonService.new(@organization.id).reset
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
@ -39,15 +40,16 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
|||
|
||||
def update
|
||||
ActiveRecord::Base.transaction do
|
||||
Organizations::CreateForm.new(organization_params).validate!
|
||||
Organizations::CreateForm.new(organization_params.merge(original_name: @organization.login)).validate!
|
||||
login = @organization.login
|
||||
@organization.login = organization_params[:name] if organization_params[:name].present?
|
||||
@organization.nickname = organization_params[:nickname] if organization_params[:nickname].present?
|
||||
@organization.save!
|
||||
sync_organization_extension!
|
||||
|
||||
Gitea::Organization::UpdateService.call(@organization.gitea_token, login, @organization.reload)
|
||||
Gitea::Organization::UpdateService.call(current_user.gitea_token, login, @organization.reload)
|
||||
Util.write_file(@image, avatar_path(@organization)) if params[:image].present?
|
||||
Cache::V2::OwnerCommonService.new(@organization.id).reset
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
@ -57,10 +59,16 @@ class Organizations::OrganizationsController < Organizations::BaseController
|
|||
def destroy
|
||||
tip_exception("密码不正确") unless current_user.check_password?(password)
|
||||
ActiveRecord::Base.transaction do
|
||||
Gitea::Organization::DeleteService.call(@organization.gitea_token, @organization.login)
|
||||
@organization.destroy!
|
||||
gitea_destroy = Gitea::Organization::DeleteService.call(current_user.gitea_token, @organization.login)
|
||||
if gitea_destroy[:status] == 204
|
||||
@organization.destroy!
|
||||
render_ok
|
||||
elsif gitea_destroy[:status] == 500
|
||||
tip_exception("当组织内含有仓库时,无法删除此组织")
|
||||
else
|
||||
tip_exception("")
|
||||
end
|
||||
end
|
||||
render_ok
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
|
|
|
@ -14,22 +14,6 @@ class Organizations::ProjectsController < Organizations::BaseController
|
|||
@projects = paginate(@projects)
|
||||
end
|
||||
|
||||
#######################change#################################
|
||||
def organizationBadge
|
||||
watchers_count = @organization.watchers_count
|
||||
|
||||
@watchered = judge_level(watchers_count, 10, 20, 100)
|
||||
|
||||
@badge = organizationBadge.find_or_create_by(organization_id: @organization.id)
|
||||
|
||||
if @watchered != @badge.watched
|
||||
@badge.watched = @watchered
|
||||
@badge.save
|
||||
end
|
||||
render :json => {list: [{watchered: @watchered}], count: 1}
|
||||
end
|
||||
#######################change#################################
|
||||
|
||||
def search
|
||||
tip_exception("请输入搜索关键词") if params[:search].nil?
|
||||
public_projects_sql = @organization.projects.where(is_public: true).to_sql
|
||||
|
@ -58,17 +42,4 @@ class Organizations::ProjectsController < Organizations::BaseController
|
|||
def sort_direction
|
||||
%w(desc asc).include?(params[:sort_direction]) ? params[:sort_direction] : 'desc'
|
||||
end
|
||||
|
||||
|
||||
def judge_level(judged, low, mid, high)
|
||||
if judged < low
|
||||
return 0
|
||||
elsif judged < mid
|
||||
return 1
|
||||
elsif judged < high
|
||||
return 2
|
||||
else
|
||||
return 3
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,6 +6,7 @@ class Organizations::TeamProjectsController < Organizations::BaseController
|
|||
|
||||
def index
|
||||
@team_projects = @team.team_projects
|
||||
|
||||
@team_projects = paginate(@team_projects)
|
||||
end
|
||||
|
||||
|
@ -20,6 +21,17 @@ class Organizations::TeamProjectsController < Organizations::BaseController
|
|||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def create_all
|
||||
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
|
||||
ActiveRecord::Base.transaction do
|
||||
@organization.projects.each do |project|
|
||||
TeamProject.build(@organization.id, @team.id, project.id)
|
||||
end
|
||||
Gitea::Organization::TeamProject::CreateAllService.call(@organization.gitea_token, @team.gtid, @organization.login)
|
||||
render_ok
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
|
||||
ActiveRecord::Base.transaction do
|
||||
|
@ -32,6 +44,17 @@ class Organizations::TeamProjectsController < Organizations::BaseController
|
|||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def destroy_all
|
||||
tip_exception("该组织团队项目包括组织所有项目,不允许更改") if @team.includes_all_project
|
||||
ActiveRecord::Base.transaction do
|
||||
@team.team_projects.each do |project|
|
||||
project.destroy!
|
||||
end
|
||||
Gitea::Organization::TeamProject::DeleteAllService.call(@organization.gitea_token, @team.gtid, @organization.login)
|
||||
render_ok
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def load_organization
|
||||
@organization = Organization.find_by(login: params[:organization_id]) || Organization.find_by(id: params[:organization_id])
|
||||
|
@ -46,7 +69,7 @@ class Organizations::TeamProjectsController < Organizations::BaseController
|
|||
end
|
||||
|
||||
def load_operate_project
|
||||
@operate_project = Project.find_by(id: project_mark) || Project.find_by(identifier: project_mark)
|
||||
@operate_project = @organization.projects.where(id: project_mark).take || @organization.projects.where(identifier: project_mark).take
|
||||
tip_exception("项目不存在") if @operate_project.nil?
|
||||
end
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
|
|||
ActiveRecord::Base.transaction do
|
||||
@team_user = TeamUser.build(@organization.id, @operate_user.id, @team.id)
|
||||
@organization_user = OrganizationUser.build(@organization.id, @operate_user.id)
|
||||
SendTemplateMessageJob.perform_later('OrganizationRole', @operate_user.id, @organization.id, @team.authorize_name) if Site.has_notice_menu?
|
||||
SendTemplateMessageJob.perform_later('TeamJoined', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu?
|
||||
Gitea::Organization::TeamUser::CreateService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
||||
end
|
||||
rescue Exception => e
|
||||
|
@ -31,6 +31,7 @@ class Organizations::TeamUsersController < Organizations::BaseController
|
|||
ActiveRecord::Base.transaction do
|
||||
@team_user.destroy!
|
||||
Gitea::Organization::TeamUser::DeleteService.call(@organization.gitea_token, @team.gtid, @operate_user.login)
|
||||
SendTemplateMessageJob.perform_later('TeamLeft', @operate_user.id, @organization.id, @team.id) if Site.has_notice_menu?
|
||||
org_team_users = @organization.team_users.where(user_id: @operate_user.id)
|
||||
unless org_team_users.present?
|
||||
@organization.organization_users.find_by(user_id: @operate_user.id).destroy!
|
||||
|
|
|
@ -4,15 +4,24 @@ class Organizations::TeamsController < Organizations::BaseController
|
|||
before_action :check_user_can_edit_org, only: [:create, :update, :destroy]
|
||||
|
||||
def index
|
||||
#if @organization.is_owner?(current_user) || current_user.admin?
|
||||
@teams = @organization.teams
|
||||
#else
|
||||
# @teams = @organization.teams.joins(:team_users).where(team_users: {user_id: current_user.id})
|
||||
#end
|
||||
@is_admin = can_edit_org?
|
||||
@teams = @teams.includes(:team_units, :team_users)
|
||||
|
||||
@teams = kaminari_paginate(@teams)
|
||||
if params[:is_full].present?
|
||||
if can_edit_org?
|
||||
@teams = @organization.teams
|
||||
else
|
||||
@teams = []
|
||||
end
|
||||
else
|
||||
#if @organization.is_owner?(current_user) || current_user.admin?
|
||||
@teams = @organization.teams
|
||||
#else
|
||||
# @teams = @organization.teams.joins(:team_users).where(team_users: {user_id: current_user.id})
|
||||
#end
|
||||
@is_admin = can_edit_org?
|
||||
@teams = @teams.includes(:team_units, :team_users)
|
||||
|
||||
@teams = kaminari_paginate(@teams)
|
||||
end
|
||||
end
|
||||
|
||||
def search
|
||||
|
@ -34,8 +43,12 @@ class Organizations::TeamsController < Organizations::BaseController
|
|||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
Organizations::CreateTeamForm.new(team_params).validate!
|
||||
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
||||
if @organization.teams.count >= 50
|
||||
return tip_exception("组织的团队数量已超过限制!")
|
||||
else
|
||||
Organizations::CreateTeamForm.new(team_params).validate!
|
||||
@team = Organizations::Teams::CreateService.call(current_user, @organization, team_params)
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
|
|
@ -20,7 +20,7 @@ class OwnersController < ApplicationController
|
|||
@is_admin = current_user.admin? || @owner.is_owner?(current_user.id)
|
||||
@is_member = @owner.is_member?(current_user.id)
|
||||
# 用户
|
||||
else
|
||||
elsif @owner.is_a?(User)
|
||||
#待办事项,现在未做
|
||||
if User.current.admin? || User.current.login == @owner.login
|
||||
@waiting_applied_messages = @owner.applied_messages.waiting
|
||||
|
@ -45,7 +45,6 @@ class OwnersController < ApplicationController
|
|||
@projects_common_count = user_projects.common.size
|
||||
@projects_mirrior_count = user_projects.mirror.size
|
||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||
puts @owner.as_json
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ class PraiseTreadController < ApplicationController
|
|||
begin
|
||||
return normal_status(2, "你已点过赞了") if current_user.liked?(@project)
|
||||
current_user.like!(@project)
|
||||
SendTemplateMessageJob.perform_later('ProjectPraised', current_user.id, @project.id) if Site.has_notice_menu?
|
||||
render_ok({praises_count: @project.praises_count, praised: current_user.liked?(@project)})
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
|
|
@ -10,7 +10,7 @@ class ProjectCategoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def group_list
|
||||
@project_categories = ProjectCategory.where('projects_count > 0').order(projects_count: :desc)
|
||||
@project_categories = ProjectCategory.select("id, name, projects_count, private_projects_count, (projects_count - private_projects_count) as public_projects_count").having('public_projects_count > 0').order(public_projects_count: :desc)
|
||||
# projects = Project.no_anomory_projects.visible
|
||||
# @category_group_list = projects.joins(:project_category).group("project_categories.id", "project_categories.name").size
|
||||
end
|
||||
|
|
|
@ -3,7 +3,7 @@ class ProjectTrendsController < ApplicationController
|
|||
before_action :check_project_public
|
||||
|
||||
def index
|
||||
project_trends = @project.project_trends.preload(:user, trend: :user)
|
||||
project_trends = @project.project_trends.preload(:user, trend: :user, project: :owner)
|
||||
|
||||
check_time = params[:time] #时间的筛选
|
||||
check_type = params[:type] #动态类型的筛选,目前已知的有 Issue, PullRequest, Version
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
class Projects::ProjectInviteLinksController < Projects::BaseController
|
||||
before_action :require_manager!, except: [:show_link, :redirect_link]
|
||||
before_action :require_login
|
||||
|
||||
def current_link
|
||||
role = params[:role]
|
||||
is_apply = params[:is_apply]
|
||||
return render_error('请输入正确的参数!') unless role.present? && is_apply.present?
|
||||
@project_invite_link = ProjectInviteLink.find_by(user_id: current_user.id, project_id: @project.id, role: role, is_apply: is_apply)
|
||||
@project_invite_link = ProjectInviteLink.build!(@project, current_user, role, is_apply) unless @project_invite_link.present?
|
||||
end
|
||||
|
||||
def generate_link
|
||||
ActiveRecord::Base.transaction do
|
||||
params_data = link_params.merge({user_id: current_user.id, project_id: @project.id})
|
||||
Projects::ProjectInviteLinks::CreateForm.new(params_data).validate!
|
||||
@project_invite_link = ProjectInviteLink.build!(project, user, params_data[:role], params_data[:is_apply])
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def show_link
|
||||
@project_invite_link = ProjectInviteLink.find_by(sign: params[:invite_sign])
|
||||
return render_not_found unless @project_invite_link.present?
|
||||
end
|
||||
|
||||
def redirect_link
|
||||
Projects::LinkJoinService.call(current_user, @project, params[:invite_sign])
|
||||
render_ok
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
normal_status(-1, e.message)
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def link_params
|
||||
params.require(:project_invite_link).permit(:role, :is_apply)
|
||||
end
|
||||
end
|
|
@ -9,7 +9,7 @@ class Projects::WebhooksController < Projects::BaseController
|
|||
|
||||
def create
|
||||
ActiveRecord::Base.transaction do
|
||||
return render_error("webhooks数量已到上限!请删除暂不使用的webhooks以进行添加操作") if @project.webhooks.size > 19
|
||||
return render_error("webhooks数量已到上限!请删除暂不使用的webhooks以进行添加操作") if @project.webhooks.size > 49
|
||||
return render_error("参数错误.") unless webhook_params.present?
|
||||
form = Projects::Webhooks::CreateForm.new(webhook_params)
|
||||
return render json: {status: -1, message: form.errors} unless form.validate!
|
||||
|
|
|
@ -13,16 +13,20 @@ class ProjectsController < ApplicationController
|
|||
def menu_list
|
||||
menu = []
|
||||
|
||||
user_is_admin = current_user.admin? || @project.manager?(current_user)
|
||||
|
||||
menu.append(menu_hash_by_name("home"))
|
||||
menu.append(menu_hash_by_name("code")) if @project.has_menu_permission("code")
|
||||
menu.append(menu_hash_by_name("issues")) if @project.has_menu_permission("issues")
|
||||
menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls")
|
||||
menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki")
|
||||
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops")
|
||||
menu.append(menu_hash_by_name("pulls")) if @project.has_menu_permission("pulls") && @project.forge?
|
||||
menu.append(menu_hash_by_name("devops")) if @project.has_menu_permission("devops") && @project.forge?
|
||||
menu.append(menu_hash_by_name("versions")) if @project.has_menu_permission("versions")
|
||||
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources")
|
||||
menu.append(menu_hash_by_name("wiki")) if @project.has_menu_permission("wiki") && @project.forge?
|
||||
menu.append(menu_hash_by_name("resources")) if @project.has_menu_permission("resources") && @project.forge?
|
||||
menu.append(menu_hash_by_name("activity"))
|
||||
menu.append(menu_hash_by_name("settings")) if current_user.admin? || @project.manager?(current_user)
|
||||
menu.append(menu_hash_by_name("sonar"))
|
||||
menu.append(menu_hash_by_name("settings")) if user_is_admin && @project.forge?
|
||||
menu.append(menu_hash_by_name("quit")) if !user_is_admin && @project.member(current_user.id) && @project.forge?
|
||||
|
||||
render json: menu
|
||||
end
|
||||
|
@ -36,8 +40,9 @@ class ProjectsController < ApplicationController
|
|||
category_id = params[:category_id]
|
||||
@total_count =
|
||||
if category_id.blank?
|
||||
ps = ProjectStatistic.first
|
||||
ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
|
||||
# ps = ProjectStatistic.first
|
||||
# ps.common_projects_count + ps.mirror_projects_count unless ps.blank?
|
||||
@projects.total_count
|
||||
else
|
||||
cate = ProjectCategory.find_by(id: category_id)
|
||||
cate&.projects_count || 0
|
||||
|
@ -49,6 +54,13 @@ class ProjectsController < ApplicationController
|
|||
Projects::CreateForm.new(project_params).validate!
|
||||
@project = Projects::CreateService.new(current_user, project_params).call
|
||||
|
||||
# TODO: fix Educoder shixun
|
||||
if @project.persisted?
|
||||
ProjectScore.create(:project_id => @project.id, :score => 0) if @project.project_score.nil?
|
||||
|
||||
project_info = ProjectInfo.new(:user_id => current_user.id, :project_id => @project.id)
|
||||
@project.project_infos << project_info
|
||||
end
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
|
@ -59,7 +71,7 @@ class ProjectsController < ApplicationController
|
|||
Projects::MigrateForm.new(mirror_params).validate!
|
||||
|
||||
@project =
|
||||
if enable_accelerator?(mirror_params[:clone_addr])
|
||||
if EduSetting.get("mirror_address").to_s.include?("github") && enable_accelerator?(mirror_params[:clone_addr])
|
||||
source_clone_url = mirror_params[:clone_addr]
|
||||
uid_logger("########## 已动加速器 ##########")
|
||||
result = Gitea::Accelerator::MigrateService.call(mirror_params)
|
||||
|
@ -71,6 +83,11 @@ class ProjectsController < ApplicationController
|
|||
else
|
||||
Projects::MigrateService.call(current_user, mirror_params)
|
||||
end
|
||||
elsif EduSetting.get("mirror_address").to_s.include?("cnpmjs") && mirror_params[:clone_addr].include?("github.com")
|
||||
source_clone_url = mirror_params[:clone_addr]
|
||||
clone_url = source_clone_url.gsub('github.com', 'github.com.cnpmjs.org')
|
||||
uid_logger("########## 更改clone_addr ##########")
|
||||
Projects::MigrateService.call(current_user, mirror_params.merge(source_clone_url: source_clone_url, clone_addr: clone_url))
|
||||
else
|
||||
Projects::MigrateService.call(current_user, mirror_params)
|
||||
end
|
||||
|
@ -82,8 +99,9 @@ class ProjectsController < ApplicationController
|
|||
def branches
|
||||
return @branches = [] unless @project.forge?
|
||||
|
||||
result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
|
||||
@branches = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
# result = Gitea::Repository::Branches::ListService.call(@owner, @project.identifier)
|
||||
result = Gitea::Repository::Branches::ListNameService.call(@owner, @project.identifier, params[:name])
|
||||
@branches = result.is_a?(Hash) ? (result.key?(:status) ? [] : result["branch_name"]) : result
|
||||
end
|
||||
|
||||
def branches_slice
|
||||
|
@ -94,18 +112,18 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def group_type_list
|
||||
project_statics = ProjectStatistic.first
|
||||
# project_statics = ProjectStatistic.first
|
||||
|
||||
@project_statics_list = [
|
||||
{
|
||||
project_type: 'common',
|
||||
name: '开源托管项目',
|
||||
projects_count: project_statics&.common_projects_count || 0
|
||||
projects_count: Project.common.size || 0
|
||||
},
|
||||
{
|
||||
project_type: 'mirror',
|
||||
name: '开源镜像项目',
|
||||
projects_count: project_statics&.mirror_projects_count || 0
|
||||
projects_count: Project.sync_mirror.size + Project.mirror.size || 0
|
||||
}
|
||||
]
|
||||
|
||||
|
@ -129,7 +147,7 @@ class ProjectsController < ApplicationController
|
|||
validate_params = project_params.slice(:name, :description,
|
||||
:project_category_id, :project_language_id, :private, :identifier)
|
||||
|
||||
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier)).validate!
|
||||
Projects::UpdateForm.new(validate_params.merge(user_id: @project.user_id, project_identifier: @project.identifier, project_name: @project.name)).validate!
|
||||
|
||||
private = @project.forked_from_project.present? ? !@project.forked_from_project.is_public : params[:private] || false
|
||||
|
||||
|
@ -144,6 +162,15 @@ class ProjectsController < ApplicationController
|
|||
}
|
||||
gitea_repo = Gitea::Repository::UpdateService.call(@owner, @project&.repository&.identifier, gitea_params)
|
||||
@project.repository.update_attributes({hidden: gitea_repo["private"], identifier: gitea_repo["name"]})
|
||||
# 更新对应所属分类下的项目数量(私有)
|
||||
before_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][0] : @project.is_public
|
||||
after_is_public = @project.previous_changes[:is_public].present? ? @project.previous_changes[:is_public][1] : @project.is_public
|
||||
before_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][0] : @project.project_category_id
|
||||
after_pc_id = @project.previous_changes[:project_category_id].present? ? @project.previous_changes[:project_category_id][1] : @project.project_category_id
|
||||
before_pc = ProjectCategory.find_by_id(before_pc_id)
|
||||
after_pc = ProjectCategory.find_by_id(after_pc_id)
|
||||
before_pc.decrement!(:private_projects_count, 1) if before_pc.present? && !before_is_public
|
||||
after_pc.increment!(:private_projects_count, 1) if after_pc.present? && !after_is_public
|
||||
end
|
||||
SendTemplateMessageJob.perform_later('ProjectSettingChanged', current_user.id, @project&.id, @project.previous_changes.slice(:name, :description, :project_category_id, :project_language_id, :is_public, :identifier)) if Site.has_notice_menu?
|
||||
end
|
||||
|
@ -161,6 +188,8 @@ class ProjectsController < ApplicationController
|
|||
Gitea::Repository::DeleteService.new(@project.owner, @project.identifier).call
|
||||
@project.destroy!
|
||||
@project.forked_projects.update_all(forked_from_project_id: nil)
|
||||
# 如果该项目有所属的项目分类以及为私有项目,需要更新对应数量
|
||||
@project.project_category.decrement!(:private_projects_count, 1) if @project.project_category.present? && !@project.is_public
|
||||
render_ok
|
||||
end
|
||||
else
|
||||
|
@ -171,6 +200,22 @@ class ProjectsController < ApplicationController
|
|||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def quit
|
||||
user_is_admin = current_user.admin? || @project.manager?(current_user)
|
||||
if !user_is_admin && @project.member(current_user.id) && @project.forge?
|
||||
ActiveRecord::Base.transaction do
|
||||
Projects::DeleteMemberInteractor.call(@project.owner, @project, current_user)
|
||||
SendTemplateMessageJob.perform_later('ProjectMemberLeft', current_user.id, current_user.id, @project.id) if Site.has_notice_menu?
|
||||
render_ok
|
||||
end
|
||||
else
|
||||
render_forbidden('你不能退出该仓库')
|
||||
end
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
tip_exception(e.message)
|
||||
end
|
||||
|
||||
def watch_users
|
||||
watchers = @project.watchers.includes(:user).order("watchers.created_at desc").distinct
|
||||
@watchers_count = watchers.size
|
||||
|
@ -184,7 +229,7 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def fork_users
|
||||
fork_users = @project.fork_users.includes(:user, :project, :fork_project).order("fork_users.created_at desc").distinct
|
||||
fork_users = @project.fork_users.includes(:owner, :project, :fork_project).order("fork_users.created_at desc").distinct
|
||||
@forks_count = fork_users.size
|
||||
@fork_users = paginate(fork_users)
|
||||
end
|
||||
|
|
|
@ -2,7 +2,7 @@ class PullRequestsController < ApplicationController
|
|||
before_action :require_login, except: [:index, :show, :files, :commits]
|
||||
before_action :require_profile_completed, only: [:create]
|
||||
before_action :load_repository
|
||||
before_action :check_menu_authorize
|
||||
before_action :check_menu_authorize, only: [:index, :show, :create, :update, :refuse_merge, :pr_merge]
|
||||
before_action :find_pull_request, except: [:index, :new, :create, :check_can_merge,:get_branches,:create_merge_infos, :files, :commits]
|
||||
before_action :load_pull_request, only: [:files, :commits]
|
||||
before_action :find_atme_receivers, only: [:create, :update]
|
||||
|
@ -16,7 +16,7 @@ class PullRequestsController < ApplicationController
|
|||
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
|
||||
@all_issues = issues.distinct
|
||||
@filter_issues = @all_issues
|
||||
@filter_issues = @filter_issues.where("subject LIKE ? OR description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@filter_issues = @filter_issues.where("issues.subject LIKE ? OR issues.description LIKE ? ", "%#{params[:search]}%", "%#{params[:search]}%") if params[:search].present?
|
||||
@open_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::OPEN})
|
||||
@close_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::CLOSED})
|
||||
@merged_issues = @filter_issues.joins(:pull_request).where(pull_requests: {status: PullRequest::MERGED})
|
||||
|
@ -29,7 +29,7 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
@all_branches = Branches::ListService.call(@owner, @project)
|
||||
@all_branches = Branches::ListService.call(@owner, @project, params[:branch_name])
|
||||
@is_fork = @project.forked_from_project_id.present?
|
||||
@projects_names = [{
|
||||
project_user_login: @owner.try(:login),
|
||||
|
@ -50,16 +50,20 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def get_branches
|
||||
branch_result = Branches::ListService.call(@owner, @project)
|
||||
branch_result = Branches::ListService.call(@owner, @project, params[:name])
|
||||
render json: branch_result
|
||||
# return json: branch_result
|
||||
end
|
||||
|
||||
def create
|
||||
# return normal_status(-1, "您不是目标分支开发者,没有权限,请联系目标分支作者.") unless @project.operator?(current_user)
|
||||
ActiveRecord::Base.transaction do
|
||||
Issues::CreateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
|
||||
@pull_request, @gitea_pull_request = PullRequests::CreateService.call(current_user, @owner, @project, params)
|
||||
if @gitea_pull_request[:status] == :success
|
||||
@pull_request.bind_gitea_pull_request!(@gitea_pull_request[:body]["number"], @gitea_pull_request[:body]["id"])
|
||||
reviewers = User.where(id: params[:reviewer_ids])
|
||||
@pull_request.reviewers = reviewers
|
||||
SendTemplateMessageJob.perform_later('PullRequestAssigned', current_user.id, @pull_request&.id) if Site.has_notice_menu?
|
||||
SendTemplateMessageJob.perform_later('ProjectPullRequest', current_user.id, @pull_request&.id) if Site.has_notice_menu?
|
||||
Rails.logger.info "[ATME] maybe to at such users: #{@atme_receivers.pluck(:login)}"
|
||||
|
@ -69,6 +73,8 @@ class PullRequestsController < ApplicationController
|
|||
raise ActiveRecord::Rollback
|
||||
end
|
||||
end
|
||||
rescue => e
|
||||
normal_status(-1, e.message)
|
||||
end
|
||||
|
||||
def edit
|
||||
|
@ -78,6 +84,7 @@ class PullRequestsController < ApplicationController
|
|||
end
|
||||
|
||||
def update
|
||||
return render_forbidden("你没有权限操作.") unless @project.operator?(current_user)
|
||||
if params[:title].nil?
|
||||
normal_status(-1, "名称不能为空")
|
||||
elsif params[:issue_tag_ids].nil?
|
||||
|
@ -85,15 +92,11 @@ class PullRequestsController < ApplicationController
|
|||
else
|
||||
ActiveRecord::Base.transaction do
|
||||
begin
|
||||
Issues::UpdateForm.new({subject: params[:title], description: params[:body].blank? ? params[:body] : params[:body].b}).validate!
|
||||
merge_params
|
||||
|
||||
@issue&.issue_tags_relates&.destroy_all if params[:issue_tag_ids].blank?
|
||||
if params[:issue_tag_ids].present? && !@issue&.issue_tags_relates.where(issue_tag_id: params[:issue_tag_ids]).exists?
|
||||
@issue&.issue_tags_relates&.destroy_all
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
|
||||
end
|
||||
end
|
||||
reviewers = User.where(id: params[:reviewer_ids])
|
||||
@pull_request.reviewers = reviewers
|
||||
|
||||
if @issue.update_attributes(@issue_params)
|
||||
if @pull_request.update_attributes(@local_params.compact)
|
||||
|
@ -102,8 +105,15 @@ class PullRequestsController < ApplicationController
|
|||
|
||||
if gitea_pull[:status] === :success
|
||||
if params[:issue_tag_ids].present?
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
|
||||
if params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size > 1
|
||||
return normal_status(-1, "最多只能创建一个标记。")
|
||||
elsif params[:issue_tag_ids].is_a?(Array) && params[:issue_tag_ids].size == 1
|
||||
@issue&.issue_tags_relates&.destroy_all
|
||||
params[:issue_tag_ids].each do |tag|
|
||||
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
|
||||
end
|
||||
else
|
||||
return normal_status(-1, "请输入正确的标记。")
|
||||
end
|
||||
end
|
||||
if params[:status_id].to_i == 5
|
||||
|
@ -136,6 +146,8 @@ class PullRequestsController < ApplicationController
|
|||
colsed = PullRequests::CloseService.call(@owner, @repository, @pull_request, current_user)
|
||||
if colsed === true
|
||||
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::CLOSE)
|
||||
# 合并请求下issue处理为关闭
|
||||
@issue&.update_attributes!({status_id:5})
|
||||
SendTemplateMessageJob.perform_later('PullRequestClosed', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
||||
normal_status(1, "已拒绝")
|
||||
else
|
||||
|
@ -157,6 +169,7 @@ class PullRequestsController < ApplicationController
|
|||
@issue_assign_to = @issue.get_assign_user
|
||||
@gitea_pull = Gitea::PullRequest::GetService.call(@owner.login,
|
||||
@repository.identifier, @pull_request.gitea_number, current_user&.gitea_token)
|
||||
# @last_review = @pull_request.reviews.take
|
||||
end
|
||||
|
||||
def pr_merge
|
||||
|
@ -180,6 +193,8 @@ class PullRequestsController < ApplicationController
|
|||
# @pull_request.project_trend_status!
|
||||
@pull_request.project_trends.create!(user: current_user, project: @project,action_type: ProjectTrend::MERGE)
|
||||
@issue&.custom_journal_detail("merge", "", "该合并请求已被合并", current_user&.id)
|
||||
# 合并请求下issue处理为关闭
|
||||
@issue&.update_attributes!({status_id:5})
|
||||
SendTemplateMessageJob.perform_later('PullRequestMerged', current_user.id, @pull_request.id) if Site.has_notice_menu?
|
||||
normal_status(1, "合并成功")
|
||||
else
|
||||
|
@ -197,7 +212,7 @@ class PullRequestsController < ApplicationController
|
|||
def check_can_merge
|
||||
target_head = params[:head] #源分支
|
||||
target_base = params[:base] #目标分支
|
||||
is_original = params[:is_original]
|
||||
is_original = params[:is_original] || false
|
||||
if target_head.blank? || target_base.blank?
|
||||
normal_status(-2, "请选择分支")
|
||||
elsif target_head === target_base && !is_original
|
||||
|
@ -228,11 +243,11 @@ class PullRequestsController < ApplicationController
|
|||
|
||||
private
|
||||
def load_pull_request
|
||||
@pull_request = PullRequest.find params[:id]
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
def find_pull_request
|
||||
@pull_request = PullRequest.find_by_id(params[:id])
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
|
||||
@issue = @pull_request&.issue
|
||||
if @pull_request.blank?
|
||||
normal_status(-1, "合并请求不存在")
|
||||
|
@ -243,7 +258,7 @@ class PullRequestsController < ApplicationController
|
|||
|
||||
def get_relatived
|
||||
@project_tags = @project.issue_tags&.select(:id,:name, :color).as_json
|
||||
@project_versions = @project.versions&.select(:id,:name, :status).as_json
|
||||
@project_versions = @project.versions.opening&.select(:id,:name, :status).as_json
|
||||
@project_members = @project.all_developers
|
||||
@project_priories = IssuePriority&.select(:id,:name, :position).as_json
|
||||
end
|
||||
|
@ -256,12 +271,12 @@ class PullRequestsController < ApplicationController
|
|||
base: params[:base], #目标分支
|
||||
milestone: 0, #里程碑,未与本地的里程碑关联
|
||||
}
|
||||
assignee_login = User.find_by_id(params[:assigned_to_id])&.login
|
||||
@requests_params = @local_params.merge({
|
||||
assignee: current_user.try(:login),
|
||||
# assignees: ["#{params[:assigned_login].to_s}"],
|
||||
assignees: ["#{current_user.try(:login).to_s}"],
|
||||
labels: params[:issue_tag_ids],
|
||||
due_date: Time.now
|
||||
assignees: ["#{assignee_login.to_s}"],
|
||||
labels: params[:issue_tag_ids]
|
||||
# due_date: Time.now
|
||||
})
|
||||
@issue_params = {
|
||||
author_id: current_user.id,
|
||||
|
@ -271,7 +286,7 @@ class PullRequestsController < ApplicationController
|
|||
assigned_to_id: params[:assigned_to_id],
|
||||
fixed_version_id: params[:fixed_version_id],
|
||||
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
|
||||
priority_id: params[:priority_id] || "2",
|
||||
priority_id: params[:priority_id],
|
||||
issue_classify: "pull_request",
|
||||
issue_type: params[:issue_type] || "1",
|
||||
tracker_id: 2,
|
||||
|
|
|
@ -9,61 +9,15 @@ class RepositoriesController < ApplicationController
|
|||
before_action :load_repository
|
||||
before_action :authorizate!, except: [:sync_mirror, :tags, :commit, :archive]
|
||||
before_action :authorizate_user_can_edit_repo!, only: %i[sync_mirror]
|
||||
before_action :get_ref, only: %i[entries sub_entries top_counts file archive]
|
||||
before_action :get_ref, only: %i[entries sub_entries top_counts files archive]
|
||||
before_action :get_latest_commit, only: %i[entries sub_entries top_counts]
|
||||
before_action :get_statistics, only: %i[top_counts]
|
||||
before_action :preload_badge, only: [:badges]
|
||||
|
||||
def files
|
||||
result = @project.educoder? ? nil : Gitea::Repository::Files::GetService.call(@owner, @project.identifier, @ref, params[:search], @owner.gitea_token)
|
||||
render json: result
|
||||
end
|
||||
|
||||
|
||||
def preload_badge
|
||||
@praised_cache = "praised"
|
||||
@forked_cache = "forked"
|
||||
@watchered_cache = "watchered"
|
||||
@badge = RepositoryBadge.find_or_create_by(user_id: observed_user.id)
|
||||
$redis_cache.hset(project_statistic_key, @many_projects_cache, @badge.many_projects)
|
||||
$redis_cache.hset(project_statistic_key, @manyParisesProject_cache, @badge.manyParisesProject)
|
||||
$redis_cache.hset(project_statistic_key, @parises_project_cache, @badge.parises_project)
|
||||
end
|
||||
|
||||
####################change for repository############################
|
||||
|
||||
|
||||
def badges
|
||||
preload_badge
|
||||
@badges_dic = Hash.new(0)
|
||||
praises_count = @project.praises_count.to_i
|
||||
forked_count = @project.forked_count.to_i
|
||||
watchers_count = @project.watchers_count.to_i
|
||||
|
||||
@praised = judge_level(praises_count, 10, 20,100)
|
||||
redis_judge_reload @praised_cache, @praised
|
||||
@badges_dic["praised_cache"] = $redis_cache.hget(project_statistic_key, @praised_cache).to_i
|
||||
|
||||
@forked = judge_level(forked_count, 5, 10,100)
|
||||
redis_judge_reload @forked_cache, @forked
|
||||
@badges_dic["forked_cache"] = $redis_cache.hget(project_statistic_key, @forked_cache).to_i
|
||||
|
||||
@watchered = judge_level(watchers_count, 10, 20,100)
|
||||
redis_judge_reload @watchered_cache, @watchered
|
||||
@badges_dic["forked_cache"] = $redis_cache.hget(project_statistic_key, @forked_cache).to_i
|
||||
|
||||
|
||||
badges_visable = Array.new
|
||||
@badges_dic.each do |key,value|
|
||||
if value > 0
|
||||
badges_visable.append({"#{key}":value})
|
||||
end
|
||||
end
|
||||
render :json => {list: badges_visable, count: badges_visable.size}
|
||||
end
|
||||
|
||||
##########################################################
|
||||
|
||||
# 新版项目详情
|
||||
def detail
|
||||
@user = current_user
|
||||
|
@ -93,14 +47,19 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def entries
|
||||
@project.increment!(:visits)
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
|
||||
@week_project_visit_record, @month_project_visit_record = TimeableVisitRecord.build(@project.id)
|
||||
if @week_project_visit_record.visits < 300 && @month_project_visit_record.visits < 1000
|
||||
@week_project_visit_record.increment!(:visits)
|
||||
@month_project_visit_record.increment!(:visits)
|
||||
@project.increment!(:visits)
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {visits: 1}, @project.id)
|
||||
end
|
||||
if @project.educoder?
|
||||
@entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder.repo_name)
|
||||
else
|
||||
@entries = Gitea::Repository::Entries::ListService.new(@owner, @project.identifier, ref: @ref).call
|
||||
@entries = @entries.present? ? @entries.sort_by{ |hash| hash['type'] } : []
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
@path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -109,8 +68,7 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def sub_entries
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
@path = Gitea.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
file_path_uri = URI.escape(URI.encode(params[:filepath].to_s.strip))
|
||||
|
||||
if @project.educoder?
|
||||
if params[:type] === 'file'
|
||||
|
@ -118,18 +76,35 @@ class RepositoriesController < ApplicationController
|
|||
logger.info "######### sub_entries: #{@sub_entries}"
|
||||
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||
|
||||
tmp_entries = [{
|
||||
tmp_entries = {
|
||||
"content" => @sub_entries['data']['content'],
|
||||
"type" => "blob"
|
||||
}]
|
||||
}
|
||||
@sub_entries = {
|
||||
"trees"=>tmp_entries,
|
||||
"commits" => [{}]
|
||||
}
|
||||
else
|
||||
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
|
||||
begin
|
||||
@sub_entries = Educoder::Repository::Entries::ListService.call(@project&.project_educoder&.repo_name, {path: file_path_uri})
|
||||
if @sub_entries.blank? || @sub_entries['status'].to_i === -1
|
||||
@sub_entries = Educoder::Repository::Entries::GetService.call(@project&.project_educoder&.repo_name, file_path_uri)
|
||||
return render_error('该文件暂未开放,敬请期待.') if @sub_entries['status'].to_i === -1
|
||||
tmp_entries = {
|
||||
"content" => @sub_entries['data']['content'],
|
||||
"type" => "blob"
|
||||
}
|
||||
@sub_entries = {
|
||||
"trees"=>tmp_entries,
|
||||
"commits" => [{}]
|
||||
}
|
||||
end
|
||||
rescue
|
||||
return render_error('该文件暂未开放,敬请期待.')
|
||||
end
|
||||
end
|
||||
else
|
||||
@path = GiteaService.gitea_config[:domain]+"/#{@project.owner.login}/#{@project.identifier}/raw/branch/#{@ref}/"
|
||||
interactor = Repositories::EntriesInteractor.call(@owner, @project.identifier, file_path_uri, ref: @ref)
|
||||
if interactor.success?
|
||||
result = interactor.result
|
||||
|
@ -141,13 +116,17 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def commits
|
||||
if params[:filepath].present?
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||
if @project.educoder?
|
||||
@commits = Educoder::Repository::Commits::ListService.call(@project&.project_educoder&.repo_name)
|
||||
else
|
||||
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: current_user&.gitea_token).call
|
||||
if params[:filepath].present?
|
||||
file_path_uri = URI.escape(URI.encode(params[:filepath].to_s.strip))
|
||||
@hash_commit = Gitea::Repository::Commits::FileListService.new(@owner.login, @project.identifier, file_path_uri,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: @owner&.gitea_token).call
|
||||
else
|
||||
@hash_commit = Gitea::Repository::Commits::ListService.new(@owner.login, @project.identifier,
|
||||
sha: params[:sha], page: params[:page], limit: params[:limit], token: @owner&.gitea_token).call
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -158,22 +137,40 @@ class RepositoriesController < ApplicationController
|
|||
|
||||
def commit
|
||||
@sha = params[:sha]
|
||||
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token)
|
||||
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, current_user&.gitea_token, {diff: true})
|
||||
if @project.educoder?
|
||||
return render_error('暂未开放,敬请期待.')
|
||||
else
|
||||
@commit = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, @owner&.gitea_token)
|
||||
@commit_diff = Gitea::Repository::Commits::GetService.call(@owner.login, @repository.identifier, @sha, @owner&.gitea_token, {diff: true})
|
||||
render_error(@commit[:message], @commit[:status]) if @commit.has_key?(:status) || @commit_diff.has_key?(:status)
|
||||
end
|
||||
end
|
||||
|
||||
def tags
|
||||
result = Gitea::Repository::Tags::ListService.call(current_user&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
|
||||
if params[:only_name].present?
|
||||
result = Gitea::Repository::Tags::ListNameService.call(@owner, @project.identifier, params[:name])
|
||||
|
||||
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
else
|
||||
name_result = Gitea::Repository::Tags::ListNameService.call(@owner, @project.identifier, params[:name])
|
||||
|
||||
@tag_names = result.is_a?(Hash) && result.key?(:status) ? [] : name_result
|
||||
|
||||
result = Gitea::Repository::Tags::ListService.call(@owner&.gitea_token, @owner.login, @project.identifier, {page: params[:page], limit: params[:limit]})
|
||||
|
||||
@tags = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
end
|
||||
end
|
||||
|
||||
def contributors
|
||||
if params[:filepath].present?
|
||||
if params[:filepath].present? || @project.educoder?
|
||||
@contributors = []
|
||||
else
|
||||
@contributors = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
||||
result = Gitea::Repository::Contributors::GetService.call(@owner, @repository.identifier)
|
||||
@contributors = result.is_a?(Hash) && result.key?(:status) ? [] : result
|
||||
end
|
||||
rescue
|
||||
@contributors = []
|
||||
end
|
||||
|
||||
def edit
|
||||
|
@ -237,28 +234,34 @@ class RepositoriesController < ApplicationController
|
|||
|
||||
def readme
|
||||
if params[:filepath].present?
|
||||
result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], current_user&.gitea_token)
|
||||
result = Gitea::Repository::Readme::DirService.call(@owner.login, @repository.identifier, params[:filepath], params[:ref], @owner&.gitea_token)
|
||||
else
|
||||
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], current_user&.gitea_token)
|
||||
result = Gitea::Repository::Readme::GetService.call(@owner.login, @repository.identifier, params[:ref], @owner&.gitea_token)
|
||||
end
|
||||
@path = GiteaService.gitea_config[:domain]+"/#{@owner.login}/#{@repository.identifier}/raw/branch/#{params[:ref]}/"
|
||||
@readme = result[:status] === :success ? result[:body] : nil
|
||||
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref])
|
||||
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha")
|
||||
@readme['content'] = decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||
@readme['replace_content'] = readme_decode64_content(@readme, @owner, @repository, params[:ref], @path)
|
||||
render json: @readme.slice("type", "encoding", "size", "name", "path", "content", "sha", "replace_content")
|
||||
rescue
|
||||
render json: nil
|
||||
end
|
||||
|
||||
def languages
|
||||
render json: languages_precentagable
|
||||
if @project.educoder?
|
||||
render json: {}
|
||||
else
|
||||
render json: languages_precentagable
|
||||
end
|
||||
end
|
||||
|
||||
def archive
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{params[:archive]}"
|
||||
domain = GiteaService.gitea_config[:domain]
|
||||
api_url = GiteaService.gitea_config[:base_url]
|
||||
archive_url = "/repos/#{@owner.login}/#{@repository.identifier}/archive/#{Addressable::URI.escape(params[:archive])}"
|
||||
|
||||
file_path = [domain, api_url, archive_url].join
|
||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("?") if @repository.hidden?
|
||||
file_path = [file_path, "access_token=#{@owner&.gitea_token}"].join("?")
|
||||
|
||||
return render_not_found if !request.format.zip? && !request.format.gzip?
|
||||
|
||||
|
@ -266,14 +269,14 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
|
||||
def raw
|
||||
domain = Gitea.gitea_config[:domain]
|
||||
api_url = Gitea.gitea_config[:base_url]
|
||||
domain = GiteaService.gitea_config[:domain]
|
||||
api_url = GiteaService.gitea_config[:base_url]
|
||||
|
||||
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{params[:filepath]}?ref=#{params[:ref]}"
|
||||
url = "/repos/#{@owner.login}/#{@repository.identifier}/raw/#{CGI.escape(params[:filepath])}?ref=#{CGI.escape(params[:ref])}"
|
||||
file_path = [domain, api_url, url].join
|
||||
file_path = [file_path, "access_token=#{current_user&.gitea_token}"].join("&") if @repository.hidden?
|
||||
file_path = [file_path, "access_token=#{@owner&.gitea_token}"].join("&")
|
||||
|
||||
redirect_to URI.escape(file_path)
|
||||
redirect_to file_path
|
||||
end
|
||||
|
||||
private
|
||||
|
@ -297,18 +300,18 @@ class RepositoriesController < ApplicationController
|
|||
# TODO 获取最新commit信息
|
||||
def project_commits
|
||||
if params[:filepath].present?
|
||||
file_path_uri = URI.parse(URI.encode(params[:filepath].to_s.strip))
|
||||
file_path_uri = URI.escape(URI.encode(params[:filepath].to_s.strip))
|
||||
Gitea::Repository::Commits::FileListService.new(@project.owner.login, @project.identifier, file_path_uri,
|
||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||
sha: get_ref, page: 1, limit: 1, token: @project&.owner&.gitea_token).call
|
||||
else
|
||||
Gitea::Repository::Commits::ListService.new(@project.owner.login, @project.identifier,
|
||||
sha: get_ref, page: 1, limit: 1, token: current_user&.gitea_token).call
|
||||
sha: get_ref, page: 1, limit: 1, token: @project&.owner&.gitea_token).call
|
||||
end
|
||||
end
|
||||
|
||||
def get_statistics
|
||||
@branches_count = @project.educoder? ? 0 : Gitea::Repository::Branches::ListService.new(@project.owner, @project.identifier).call&.size
|
||||
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(current_user&.gitea_token, @project.owner.login, @project.identifier).call&.size
|
||||
@tags_count = @project.educoder? ? 0 : Gitea::Repository::Tags::ListService.new(@project&.owner&.gitea_token, @project.owner.login, @project.identifier).call&.size
|
||||
end
|
||||
|
||||
def get_ref
|
||||
|
@ -393,7 +396,7 @@ class RepositoriesController < ApplicationController
|
|||
local_requests = PullRequest.new(local_params.merge(user_id: current_user.try(:id), project_id: @project.id, issue_id: @pull_issue.id))
|
||||
if local_requests.save
|
||||
gitea_request = Gitea::PullRequest::CreateService.new(current_user.try(:gitea_token), @owner.login, @project.try(:identifier), requests_params).call
|
||||
if gitea_request[:status] == :success && local_requests.update_attributes(gpid: gitea_request["body"]["number"])
|
||||
if gitea_request[:status] == :success && local_requests.update_attributes(gitea_number: gitea_request["body"]["number"])
|
||||
local_requests.project_trends.create(user_id: current_user.id, project_id: @project.id, action_type: "create")
|
||||
end
|
||||
end
|
||||
|
@ -401,37 +404,4 @@ class RepositoriesController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
def judge_level(judged, low, mid, high)
|
||||
if judged < low
|
||||
return 0
|
||||
elsif judged < mid
|
||||
return 1
|
||||
elsif judged < high
|
||||
return 2
|
||||
else
|
||||
return 3
|
||||
end
|
||||
end
|
||||
|
||||
def redis_judge_reload(judge_cache, new_value)
|
||||
if $redis_cache.hget(project_statistic_key, judge_cache).to_i != new_value
|
||||
$redis_cache.del(project_statistic_key)
|
||||
updateService judge_cache, new_value
|
||||
load_redis
|
||||
end
|
||||
end
|
||||
|
||||
def project_statistic_key
|
||||
"project:#{@project.id}"
|
||||
end
|
||||
|
||||
def updateService(update_name, update_value)
|
||||
@badge = RepositoryBadge.find_or_create_by(user_id: observed_user.id)
|
||||
@badge.update_attribute(update_name,update_value)
|
||||
@badge.save
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
class ReviewsController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :load_project
|
||||
before_action :load_pull_request
|
||||
|
||||
def create
|
||||
return render_forbidden('您不是审查人员,无法进行审查!') if current_user&.id != @pull_request.issue.assigned_to_id
|
||||
@review = Api::V1::Projects::Pulls::Reviews::CreateService.call(@project, @pull_request, review_params, current_user)
|
||||
end
|
||||
|
||||
private
|
||||
def review_params
|
||||
params.require(:review).permit(:content, :commit_id, :status)
|
||||
end
|
||||
|
||||
def load_pull_request
|
||||
@pull_request = @project.pull_requests.where(gitea_number: params[:id]).where.not(id: params[:id]).take || PullRequest.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
end
|
|
@ -1,13 +1,23 @@
|
|||
class SettingsController < ApplicationController
|
||||
def show
|
||||
@old_projects_url = nil
|
||||
get_navbar
|
||||
get_add_menu
|
||||
get_common_menu
|
||||
get_personal_menu
|
||||
get_top_system_notification
|
||||
get_banner
|
||||
end
|
||||
|
||||
private
|
||||
def get_navbar
|
||||
@navbar = default_laboratory.navbar
|
||||
if User.current.logged?
|
||||
pernal_index = {"name"=>"个人主页", "link"=>get_site_url("url", "#{Rails.application.config_for(:configuration)['platform_url']}/current_user"), "hidden"=>false}
|
||||
@navbar << pernal_index
|
||||
end
|
||||
end
|
||||
|
||||
def get_add_menu
|
||||
@add = []
|
||||
Site.add.select(:id, :name, :url, :key).to_a.map(&:serializable_hash).each do |site|
|
||||
|
@ -58,4 +68,14 @@ class SettingsController < ApplicationController
|
|||
def append_http(url)
|
||||
url.to_s.start_with?("http") ? url : [request.protocol, request.host_with_port, url].join('')
|
||||
end
|
||||
|
||||
def get_banner
|
||||
@banner = {
|
||||
title: EduSetting.get("banner_title") || '大学开源',
|
||||
sub_title: EduSetting.get("banner_sub_title") || '让大学绽放开源之花',
|
||||
content: EduSetting.get("banner_content") || "Powered by Trustie and GitLink"
|
||||
}
|
||||
|
||||
@banner
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
class SonarTasksController < ApplicationController
|
||||
before_action :require_login
|
||||
before_action :load_project
|
||||
before_action :authenticate_user!
|
||||
|
||||
def index
|
||||
@sonar_task = SonarTask.find_by(project_id: @project.id)
|
||||
tip_exception(-1, "代码未检测,请点击开始检测按钮检测!") if @sonar_task.blank?
|
||||
if @sonar_task.complete_status == 0
|
||||
service = Sonar::ApiService.new(@project.id)
|
||||
service.task_result(@sonar_task.task_id)
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
Sonar::ApiService.call(@project.id)
|
||||
render_ok
|
||||
end
|
||||
|
||||
def type_detail
|
||||
service = Sonar::ApiService.new(@project.id)
|
||||
@data = service.type_detail(params[:task_id], params[:type])
|
||||
end
|
||||
|
||||
def code_source
|
||||
service = Sonar::ApiService.new(@project.id)
|
||||
@data = service.source_code(params[:task_id], params[:component])
|
||||
Rails.logger.info "data=======#{@data}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def authenticate_user!
|
||||
return if @project.member?(current_user) || current_user.admin? || current_user.business? || educoder_auth_teacher?(current_user)
|
||||
render_forbidden('你没有权限操作')
|
||||
end
|
||||
|
||||
def educoder_auth_teacher?(user)
|
||||
user.user_extension&.identity == 'teacher' && user.professional_certification?
|
||||
end
|
||||
end
|
|
@ -2,24 +2,24 @@ class StatisticController < ApplicationController
|
|||
|
||||
# 平台概况
|
||||
def platform_profile
|
||||
@platform_user_query = Statistic::PlatformUserQuery.new(params).call
|
||||
@platform_project_query = Statistic::PlatformProjectQuery.new(params).call
|
||||
@platform_course_query = Statistic::PlatformCourseQuery.new(params).call
|
||||
@platform_user_query = Statistic::PlatformUserQuery.new(params).call rescue [0, 0, 0]
|
||||
@platform_project_query = Statistic::PlatformProjectQuery.new(params).call rescue [0, 0, 0]
|
||||
@platform_course_query = Statistic::PlatformCourseQuery.new(params).call rescue [0, 0, 0]
|
||||
end
|
||||
|
||||
# 平台代码提交数据
|
||||
def platform_code
|
||||
@platform_pull_request_query = Statistic::PlatformPullRequestQuery.new(params).call
|
||||
@platform_commit_query = Statistic::PlatformCommitQuery.new(params,current_user).call
|
||||
@platform_pull_request_query = Statistic::PlatformPullRequestQuery.new(params).call rescue [0, 0]
|
||||
@platform_commit_query = Statistic::PlatformCommitQuery.new(params,current_user).call rescue [0, 0]
|
||||
end
|
||||
|
||||
# 项目案例活跃度排行榜
|
||||
def active_project_rank
|
||||
@active_project_rank_query = Statistic::ActiveProjectRankQuery.new(params, current_user).call
|
||||
@active_project_rank_query = Statistic::ActiveProjectRankQuery.new(params, current_user).call rescue []
|
||||
end
|
||||
|
||||
# 开发者活跃度排行榜
|
||||
def active_developer_rank
|
||||
@active_developer_rank_query = Statistic::ActiveDeveloperRankQuery.new(params, current_user).call
|
||||
@active_developer_rank_query = Statistic::ActiveDeveloperRankQuery.new(params, current_user).call rescue []
|
||||
end
|
||||
end
|
|
@ -0,0 +1,26 @@
|
|||
class Traces::BaseController < ApplicationController
|
||||
|
||||
helper_method :observed_logged_user?, :observed_user
|
||||
before_action :check_trace_system
|
||||
|
||||
def observed_user
|
||||
@_observed_user ||= (User.find_by_login(params[:user_id]) || User.find_by_id(params[:user_id]))
|
||||
end
|
||||
|
||||
def observed_logged_user?
|
||||
observed_user.id == User.current&.id
|
||||
end
|
||||
|
||||
protected
|
||||
def check_auth
|
||||
return render_forbidden unless current_user.admin? || observed_logged_user?
|
||||
end
|
||||
|
||||
def check_trace_system
|
||||
code, data, error = Trace::SystemInfoService.call(current_user.trace_token)
|
||||
return render_ok({code: 501, data: {operate_time: data['operate_time']}, message: '系统维护中'}) if data['status'] === 0
|
||||
rescue
|
||||
# 这里根据需求跳转到404
|
||||
return render_not_found
|
||||
end
|
||||
end
|
|
@ -1,7 +1,10 @@
|
|||
class Users::IsPinnedProjectsController < Users::BaseController
|
||||
before_action :private_user_resources!, only: [:pin]
|
||||
def index
|
||||
@is_pinned_projects = observed_user.pinned_projects.order(position: :desc, created_at: :asc).includes(project: [:project_category, :project_language, :repository]).order(position: :desc)
|
||||
@is_pinned_projects = observed_user.pinned_projects.left_joins(:project)
|
||||
.where("projects.is_public = TRUE")
|
||||
.order(position: :desc, created_at: :asc)
|
||||
.includes(project: [:project_category, :project_language, :repository]).order(position: :desc)
|
||||
@is_pinned_projects = kaminari_paginate(@is_pinned_projects)
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
class Users::StatisticsController < Users::BaseController
|
||||
before_action :preload_develop_data, only: [:develop]
|
||||
before_action :preload_badge_data, only: [:badges]
|
||||
|
||||
# 近期活动统计
|
||||
def activity
|
||||
|
@ -13,7 +12,7 @@ class Users::StatisticsController < Users::BaseController
|
|||
@commit_data = []
|
||||
date_range.each do |date|
|
||||
@date_data << date.strftime("%Y.%m.%d")
|
||||
@issue_data << observed_user.issues.where("DATE(created_on) = ?", date).size
|
||||
@issue_data << observed_user.issues.issue_issue.where("DATE(created_on) = ?", date).size
|
||||
@pull_request_data << observed_user.pull_requests.where("DATE(created_at) = ?", date).size
|
||||
date_commit_data = commit_data.blank? ? nil : commit_data.select{|item| item["timestamp"] == date.to_time.to_i}
|
||||
@commit_data << (date_commit_data.blank? ? 0 : date_commit_data[0]["contributions"].to_i)
|
||||
|
@ -21,35 +20,6 @@ class Users::StatisticsController < Users::BaseController
|
|||
render :json => {dates: @date_data, issues_count: @issue_data, pull_requests_count: @pull_request_data, commits_count: @commit_data}
|
||||
end
|
||||
|
||||
###############change###############
|
||||
# 用户badges 接口 url 路径为/api/users/:user_id/statistic/badges
|
||||
|
||||
# 三类
|
||||
# 第一类 贡献类
|
||||
# 1. 用户累积获得高星
|
||||
# 2. 用户关注数超过10人
|
||||
# 3. 用户的累积获赞人数
|
||||
# 4. 用户连续一周有commit
|
||||
# 5. 用户累积pr数
|
||||
|
||||
# 第二类 活动类
|
||||
# 第三类 特殊类
|
||||
def badges
|
||||
badges_visable = Array.new
|
||||
@badges_dic.each do |key,value|
|
||||
if value > 0
|
||||
#与describe同理,此处应该再增加一个 url字典
|
||||
describe = @badges_describe_dic[key]
|
||||
badges_visable.append({"#{key}":value, "describe":describe})
|
||||
end
|
||||
end
|
||||
render :json => {list: badges_visable, count: badges_visable.size}
|
||||
|
||||
end
|
||||
###############change###############
|
||||
|
||||
|
||||
|
||||
# 开发能力
|
||||
def develop
|
||||
if params[:start_time].present? && params[:end_time].present?
|
||||
|
@ -247,206 +217,3 @@ class Users::StatisticsController < Users::BaseController
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def count_filter(collection, count_field, countf)
|
||||
return collection.where("#{count_field} >= ?", countf)
|
||||
end
|
||||
|
||||
# 判断是否拥有
|
||||
def judge_have(judged, count)
|
||||
return judged >= count ? 1 : 0
|
||||
end
|
||||
|
||||
# 判断等级
|
||||
def judge_level(judged, low, mid, high)
|
||||
if judged < low
|
||||
return 0
|
||||
elsif judged < mid
|
||||
return 1
|
||||
elsif judged < high
|
||||
return 2
|
||||
else
|
||||
return 3
|
||||
end
|
||||
end
|
||||
|
||||
###############change###############
|
||||
# 用户badges 接口 url 路径为/api/users/:user_id/statistic/badges
|
||||
|
||||
# 三类
|
||||
# 第一类 贡献类
|
||||
# 2.用户有项目获得高星
|
||||
# 3.用户有数个高星项目
|
||||
# 4.用户拥有一个点赞数很高的项目
|
||||
# 5.用户拥有数个点赞数很高的项目
|
||||
# 6. 用户关注数超过10人
|
||||
# 7. 用户的累积获赞人数
|
||||
# 8. 用户累积pr数
|
||||
|
||||
# 第二类 活动类
|
||||
# 第三类 活跃类
|
||||
# 1. 用户拥有10个项目以上
|
||||
# 2. 用户连续一周/月有commit
|
||||
# 3. 用户涨粉迅速
|
||||
|
||||
|
||||
|
||||
def preload_badge_data
|
||||
badge_describe
|
||||
cache_describe
|
||||
#加载缓存资源
|
||||
load_redis
|
||||
#存放用户获得的徽章字典
|
||||
@badges_dic = Hash.new(0)
|
||||
# 有些数据可以考虑直接从缓存中读取,由于题目要求不能破坏原本的函数,暂时缓存写了直接查询,
|
||||
# 例如 Watcher.where(watchable: observed_user).count 可以用@user_result["follow-count"]来替代
|
||||
#
|
||||
@user_result = Cache::V2::UserStatisticService.new(observed_user.id).read
|
||||
|
||||
# 用户项目获得的徽章
|
||||
|
||||
#用户语言数量 y
|
||||
|
||||
# 用户项目数量 y
|
||||
project_count = @user_result["project-count"].to_i
|
||||
if project_count > 10
|
||||
@badges_dic["project_count"] = project_count
|
||||
end
|
||||
# 用户点赞数量 y
|
||||
|
||||
# 用户项目被follow数量
|
||||
praises_project_count = count_filter(Project.where(user_id:observed_user.id), 'praises_count' , 10).count
|
||||
praises_project = Project.where(user_id:observed_user.id).maximum('praises_count')
|
||||
watchers_project_count = count_filter(Project.where(user_id:observed_user.id), 'watchers_count' , 10).count
|
||||
watchers_project = Project.where(user_id:observed_user.id).maximum('watchers_count')
|
||||
|
||||
# 项目数
|
||||
@many_projects = judge_have(project_count, 5)
|
||||
redis_judge_reload @many_projects_cache, @many_projects
|
||||
@badges_dic["many_projects"] = $redis_cache.hget(user_statistic_key, @many_projects_cache).to_i
|
||||
|
||||
|
||||
# 用户有超过五个以上的高点赞项目
|
||||
@manyParisesProject = judge_have(praises_project_count, 5)
|
||||
redis_judge_reload @manyParisesProject_cache, @manyParisesProject
|
||||
@badges_dic["manyParisesProject"] = $redis_cache.hget(user_statistic_key, @manyParisesProject_cache).to_i
|
||||
|
||||
#用户有一个点赞数很高的项目 金/银/铜
|
||||
@parises_project = judge_level(praises_project, 3, 5, 10)
|
||||
redis_judge_reload @many_projects_cache, @parises_project
|
||||
@badges_dic["parises_project"] = $redis_cache.hget(user_statistic_key, @parises_project_cache).to_i
|
||||
|
||||
# 用户有超过五个以上的高关注项目
|
||||
@manyWatchersProject = judge_have(watchers_project_count, 5)
|
||||
redis_judge_reload @manyWatchersProject_cache, @manyWatchersProject
|
||||
@badges_dic["manyWatchersProject"] = $redis_cache.hget(user_statistic_key, @manyWatchersProject_cache).to_i
|
||||
|
||||
#用户有一个关注数很高的项目 金/银/铜
|
||||
@watchers_project = judge_level(watchers_project, 3, 5, 10)
|
||||
redis_judge_reload @watchers_project_cache, @watchers_project
|
||||
@badges_dic["watchers_project"] = $redis_cache.hget(user_statistic_key, @watchers_project_cache).to_i
|
||||
|
||||
|
||||
|
||||
# 用户被follow数量 y
|
||||
fans = Watcher.where(watchable: observed_user).count
|
||||
# 用户pr数量 y
|
||||
pr = PullRequest.where(user_id: observed_user.id).count
|
||||
# 用户issue数量 y
|
||||
issue = Issue.where(author_id: observed_user.id).count
|
||||
|
||||
#用户有关注数很多 金/银/铜
|
||||
@many_fans = judge_level(fans, 5, 50, 100)
|
||||
redis_judge_reload @many_fans_cache, @many_fans
|
||||
@badges_dic["many_fans"] = $redis_cache.hget(user_statistic_key, @many_fans_cache).to_i
|
||||
|
||||
#用户pr很多 金/银/铜
|
||||
@many_pr = judge_level(pr, 5, 50, 100)
|
||||
redis_judge_reload @many_pr_cache, @many_pr
|
||||
@badges_dic["many_pr"] = $redis_cache.hget(user_statistic_key, @many_pr_cache).to_i
|
||||
|
||||
#用户issue很多 金/银/铜
|
||||
@many_issue = judge_level(issue, 5, 50, 100)
|
||||
redis_judge_reload @many_issue_cache, @many_issue
|
||||
@badges_dic["many_issue"] = $redis_cache.hget(user_statistic_key, @many_issue_cache).to_i
|
||||
|
||||
#一周内活跃
|
||||
commit_request = Gitea::User::HeadmapService.call(observed_user.login, 1.week.ago.to_date.to_time.to_i, Date.today.to_time.to_i)
|
||||
commit_data = commit_request[2]
|
||||
active_commit = commit_data.select{|item| item["contributions"] >= 1}.size
|
||||
@active_in_week = active_commit == 7 ? 1 : 0
|
||||
|
||||
@badges_dic["active_in_week"] = $redis_cache.hget(user_statistic_key, @active_in_week_cache).to_i
|
||||
|
||||
#TODO fans_raise_quickly
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
def user_statistic_key
|
||||
"user:#{@user_id}"
|
||||
end
|
||||
|
||||
def redis_judge_reload(judge_cache, new_value)
|
||||
if $redis_cache.hget(user_statistic_key, judge_cache).to_i != new_value
|
||||
$redis_cache.del(user_statistic_key)
|
||||
updateService judge_cache, new_value
|
||||
load_redis
|
||||
end
|
||||
end
|
||||
|
||||
def cache_describe
|
||||
@many_projects_cache = "many_projects"
|
||||
@manyParisesProject_cache = "manyParisesProject"
|
||||
@parises_project_cache = "parises_project"
|
||||
@manyWatchersProject_cache = "manyWatchersProject"
|
||||
@watchers_project_cache = "watchers_project"
|
||||
@many_fans_cache = "many_fans"
|
||||
@many_pr_cache = "many_pr"
|
||||
@many_issue_cache = "many_issue"
|
||||
@active_in_week_cache = "active_in_week"
|
||||
end
|
||||
|
||||
|
||||
def badge_describe
|
||||
|
||||
@badges_describe_dic = Hash.new(0)
|
||||
@badges_describe_dic["many_projects"] = "参与了多个project!"
|
||||
@badges_describe_dic["manyParisesProject"] = "有多个点赞数高的project!"
|
||||
@badges_describe_dic["parises_project"] = "有一个项目获得了很高的点赞数!"
|
||||
@badges_describe_dic["manyWatchersProject"] = "有多个关注三诉讼诉讼诉讼诉讼诉讼诉讼数高的project!"
|
||||
@badges_describe_dic["watchers_project"] = "有一个项目获得了很高的关注数!"
|
||||
@badges_describe_dic["watchers_project"] = "有一个项目获得了很高的关注数!"
|
||||
@badges_describe_dic["many_fans"] = "粉丝数很多!"
|
||||
@badges_describe_dic["many_fans"] = "贡献了很多pr!"
|
||||
@badges_describe_dic["many_pr"] = "贡献了很多issue!"
|
||||
@badges_describe_dic["many_issue"] = "粉丝数很多!"
|
||||
@badges_describe_dic["active_in_week"] = "一周活跃打卡成就!"
|
||||
|
||||
end
|
||||
|
||||
|
||||
def load_redis
|
||||
@badge = Badge.find_or_create_by(user_id: observed_user.id)
|
||||
$redis_cache.hset(user_statistic_key, @many_projects_cache, @badge.many_projects)
|
||||
$redis_cache.hset(user_statistic_key, @manyParisesProject_cache, @badge.manyParisesProject)
|
||||
$redis_cache.hset(user_statistic_key, @parises_project_cache, @badge.parises_project)
|
||||
$redis_cache.hset(user_statistic_key, @manyWatchersProject_cache, @badge.manyWatchersProject)
|
||||
$redis_cache.hset(user_statistic_key, @watchers_project_cache, @badge.watchers_project)
|
||||
$redis_cache.hset(user_statistic_key, @many_fans_cache, @badge.many_fans)
|
||||
$redis_cache.hset(user_statistic_key, @many_pr_cache, @badge.many_pr)
|
||||
$redis_cache.hset(user_statistic_key, @many_issue_cache, @badge.many_issue)
|
||||
$redis_cache.hset(user_statistic_key, @active_in_week_cache, @badge.active_in_week)
|
||||
end
|
||||
|
||||
def updateService(update_name, update_value)
|
||||
#添加事务,如果更新失败则回滚
|
||||
ActiveRecord::Base.transaction do
|
||||
@badge = Badge.find_or_create_by!(user_id: observed_user.id)
|
||||
@badge.update_attributes!(update_name => update_value)
|
||||
@badge.save!
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -23,6 +23,8 @@ class Users::TemplateMessageSettingsController < Users::BaseController
|
|||
def get_current_setting
|
||||
@current_setting = @_observed_user.user_template_message_setting
|
||||
@current_setting = UserTemplateMessageSetting.build(@_observed_user.id) if @current_setting.nil?
|
||||
@current_setting.notification_body.merge!(UserTemplateMessageSetting.init_notification_body.except(*@current_setting.notification_body.keys))
|
||||
@current_setting.email_body.merge!(UserTemplateMessageSetting.init_email_body.except(*@current_setting.email_body.keys))
|
||||
end
|
||||
|
||||
def setting_params
|
||||
|
|
|
@ -4,7 +4,7 @@ class UsersController < ApplicationController
|
|||
|
||||
before_action :load_user, only: [:show, :homepage_info, :sync_token, :sync_gitea_pwd, :projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :check_user_exist, only: [:show, :homepage_info,:projects, :watch_users, :fan_users, :hovercard]
|
||||
before_action :require_login, only: %i[me list sync_user_info]
|
||||
before_action :require_login, only: %i[me list]
|
||||
before_action :connect_to_ci_db, only: [:get_user_info]
|
||||
before_action :convert_image!, only: [:update]
|
||||
skip_before_action :check_sign, only: [:attachment_show]
|
||||
|
@ -51,8 +51,6 @@ class UsersController < ApplicationController
|
|||
@projects_common_count = user_projects.common.size
|
||||
@projects_mirrior_count = user_projects.mirror.size
|
||||
@projects_sync_mirrior_count = user_projects.sync_mirror.size
|
||||
# 为了缓存活跃用户的基本信息,后续删除
|
||||
Cache::V2::OwnerCommonService.new(@user.id).read
|
||||
end
|
||||
|
||||
def watch_users
|
||||
|
@ -85,6 +83,24 @@ class UsersController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def update_image
|
||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
|
||||
Util.write_file(@image, avatar_path(@user))
|
||||
return render_ok({message: '头像修改成功'})
|
||||
rescue Exception => e
|
||||
uid_logger_error(e.message)
|
||||
render_error(-1, '头像修改失败!')
|
||||
end
|
||||
|
||||
def get_image
|
||||
return render_not_found unless @user = User.find_by(login: params[:id]) || User.find_by_id(params[:id])
|
||||
return render_forbidden unless User.current.logged? && (current_user&.admin? || current_user.id == @user.id)
|
||||
|
||||
redirect_to Rails.application.config_for(:configuration)['platform_url'] + "/" + url_to_avatar(@user).to_s
|
||||
end
|
||||
|
||||
def me
|
||||
@user = current_user
|
||||
end
|
||||
|
@ -193,7 +209,7 @@ class UsersController < ApplicationController
|
|||
def trustie_related_projects
|
||||
projects = Project.includes(:owner, :members, :project_score).where(id: params[:ids]).order("updated_on desc")
|
||||
projects_json = []
|
||||
domain_url = EduSetting.get('host_name')
|
||||
domain_url = EduSetting.get('host_name') + '/projects'
|
||||
if projects.present?
|
||||
projects.each do |p|
|
||||
project_url = "/#{p.owner.login}/#{p.identifier}"
|
||||
|
@ -262,26 +278,70 @@ class UsersController < ApplicationController
|
|||
render_ok
|
||||
end
|
||||
|
||||
def sync_user_info
|
||||
# TODO: For Educoder
|
||||
def change_password
|
||||
user = User.find_by_login params[:login]
|
||||
return render_forbidden unless user === current_user
|
||||
return render_error("用户 #{params[:login]} 不存在.") if user.nil?
|
||||
|
||||
form_params= {
|
||||
login: params[:login],
|
||||
email: user&.mail,
|
||||
password: params[:password],
|
||||
user: user
|
||||
}
|
||||
Gitea::User::ChangePasswordForm.new(form_params).validate!
|
||||
|
||||
sync_params = {
|
||||
email: params[:email],
|
||||
password: params[:password]
|
||||
password: params[:password].to_s,
|
||||
email: user.mail,
|
||||
login_name: user.login,
|
||||
source_id: 0
|
||||
}
|
||||
|
||||
Users::UpdateInfoForm.new(sync_params.merge(login: params[:login])).validate!
|
||||
|
||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
||||
if interactor.success?
|
||||
user.update!(password: params[:password], mail: params[:email], status: User::STATUS_EDIT_INFO)
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
if sync_params.present?
|
||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
||||
if interactor.success?
|
||||
user.update!(password: params[:password], is_sync_pwd: true)
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# TODO: For Educoder
|
||||
def change_email
|
||||
user = User.find_by_login params[:login]
|
||||
return render_error("用户 #{rq_params[:login]} 不存在.") if user.nil?
|
||||
|
||||
form_params= {
|
||||
login: params[:login],
|
||||
email: user&.mail,
|
||||
user: user
|
||||
}
|
||||
|
||||
Gitea::User::ChangeEmailForm.new(form_params).validate!
|
||||
|
||||
sync_params = {
|
||||
email: params[:email]
|
||||
}
|
||||
|
||||
if sync_params.present?
|
||||
interactor = Gitea::User::UpdateInteractor.call(user.login, sync_params)
|
||||
if interactor.success?
|
||||
user.update!(mail: params[:email])
|
||||
render_ok
|
||||
else
|
||||
render_error(interactor.error)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def email_search
|
||||
return render_error('请输入email') if params[:email].blank?
|
||||
@user = User.find_by(mail: params[:email])
|
||||
end
|
||||
|
||||
private
|
||||
def load_user
|
||||
@user = User.find_by_login(params[:id]) || User.find_by(id: params[:id])
|
||||
|
@ -294,6 +354,7 @@ class UsersController < ApplicationController
|
|||
:occupation, :technical_title,
|
||||
:school_id, :department_id, :province, :city,
|
||||
:custom_department, :identity, :student_id, :description,
|
||||
:show_super_description, :super_description,
|
||||
:show_email, :show_location, :show_department]
|
||||
)
|
||||
end
|
||||
|
|
|
@ -14,7 +14,7 @@ class VersionReleasesController < ApplicationController
|
|||
def new
|
||||
#获取所有的分支
|
||||
@all_branches = []
|
||||
get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier)).call
|
||||
get_all_branches = Gitea::Repository::Branches::ListService.new(@user, @repository.try(:identifier), params[:branch_name]).call
|
||||
if get_all_branches && get_all_branches.size > 0
|
||||
get_all_branches.each do |b|
|
||||
@all_branches.push(b["name"])
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
---
|
||||
title: Trustie API Reference
|
||||
title: GitLink API Reference
|
||||
|
||||
language_tabs: # must be one of https://git.io/vQNgJ
|
||||
- shell: Shell
|
||||
- javascript: JavaScript
|
||||
|
||||
toc_footers:
|
||||
- <a href='https://www.trustie.net/login?login=false'>Sign Up for a User</a>
|
||||
- <a href='https://www.trustie.net'>Powered by Trustie</a>
|
||||
- <a href='https://www.gitlink.org.cn/login'>Sign In for a User</a>
|
||||
- <a href='https://www.gitlink.org.cn'>Powered by GitLink</a>
|
||||
|
||||
includes:
|
||||
- licenses
|
||||
|
@ -30,8 +30,8 @@ code_clipboard: true
|
|||
|
||||
# Introduction
|
||||
|
||||
Welcome to the Trustie API! You can use our API to access Trustie API endpoints, which can get information on projects, repository, and users in our platform.
|
||||
Welcome to the GitLink API! You can use our API to access GitLink API endpoints, which can get information on projects, repository, and users in our platform.
|
||||
|
||||
We have language bindings in Shell,avaScript! You can view code examples in the dark area to the right, and you can switch the programming language of the examples with the tabs in the top right.
|
||||
|
||||
This example API documentation page was created with [Trustie](https://www.trustie.net). Feel free to edit it and use it as a base for your own API's documentation.
|
||||
This example API documentation page was created with [GitLink](https://www.gitlink.org.cn). Feel free to edit it and use it as a base for your own API's documentation.
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 13 KiB |
|
@ -1,4 +1,278 @@
|
|||
# Projects
|
||||
## 获取项目邀请链接(项目管理员)
|
||||
当前登录(管理员)用户获取项目邀请链接的接口(第一次请求会默认生成role类型为developer和is_apply为true的链接)
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:3000/api/yystopf/kellect/project_invite_links/current_link.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('GET /api/yystopf/kellect/project_invite_links/current_link.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`GET /api/:owner/:repo/project_invite_links/current_link.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|role |是| |string |项目权限,reporter: 报告者, developer: 开发者,manager:管理员 |
|
||||
|is_apply |是| |boolean |是否需要审核 |
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |链接id |
|
||||
|role |string |邀请角色|
|
||||
|is_apply |boolean |是否需要审核 |
|
||||
|sign |string |邀请标识(放在链接后面即可)|
|
||||
|expired_at |string |链接过期时间|
|
||||
|user.id |int |链接创建者的id |
|
||||
|user.type |string |链接创建者的类型 |
|
||||
|user.name |string |链接创建者的名称 |
|
||||
|user.login |string |链接创建者的标识 |
|
||||
|user.image_url |string |链接创建者头像 |
|
||||
|project.id |int |链接关联项目的id |
|
||||
|project.identifier |string |链接关联项目的标识 |
|
||||
|project.name |string |链接关联项目的名称 |
|
||||
|project.description |string |链接关联项目的描述 |
|
||||
|project.is_public |bool |链接关联项目是否公开 |
|
||||
|project.owner.id |bool |链接关联项目拥有者id |
|
||||
|project.owner.type |string |链接关联项目拥有者类型 |
|
||||
|project.owner.name |string |链接关联项目拥有者昵称 |
|
||||
|project.owner.login |string |链接关联项目拥有者标识 |
|
||||
|project.owner.image_url|string |链接关联项目拥有者头像 |
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 7,
|
||||
"role": "developer",
|
||||
"is_apply": false,
|
||||
"sign": "6b6b454843c291d4e52e60853cb8ad9f",
|
||||
"expired_at": "2022-06-23 10:08",
|
||||
"user": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
},
|
||||
"project": {
|
||||
"id": 474,
|
||||
"identifier": "kellect",
|
||||
"name": "kellect",
|
||||
"description": null,
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
## 生成项目邀请链接(项目管理员)
|
||||
当前登录(管理员)用户生成的项目邀请链接,可选role和is_apply参数
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/yystopf/kellect/project_invite_links/generate_link.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/yystopf/kellect/project_invite_links/generate_link.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/project_invite_links/generate_link.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|role |是| |string |项目权限,reporter: 报告者, developer: 开发者,manager:管理员 |
|
||||
|is_apply |是| |boolean |是否需要审核 |
|
||||
|
||||
|
||||
> 请求的JSON示例
|
||||
|
||||
```json
|
||||
{
|
||||
"role": "developer",
|
||||
"is_apply": false
|
||||
}
|
||||
```
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |链接id |
|
||||
|role |string |邀请角色|
|
||||
|is_apply |boolean |是否需要审核 |
|
||||
|sign |string |邀请标识(放在链接后面即可)|
|
||||
|expired_at |string |链接过期时间|
|
||||
|user.id |int |链接创建者的id |
|
||||
|user.type |string |链接创建者的类型 |
|
||||
|user.name |string |链接创建者的名称 |
|
||||
|user.login |string |链接创建者的标识 |
|
||||
|user.image_url |string |链接创建者头像 |
|
||||
|project.id |int |链接关联项目的id |
|
||||
|project.identifier |string |链接关联项目的标识 |
|
||||
|project.name |string |链接关联项目的名称 |
|
||||
|project.description |string |链接关联项目的描述 |
|
||||
|project.is_public |bool |链接关联项目是否公开 |
|
||||
|project.owner.id |bool |链接关联项目拥有者id |
|
||||
|project.owner.type |string |链接关联项目拥有者类型 |
|
||||
|project.owner.name |string |链接关联项目拥有者昵称 |
|
||||
|project.owner.login |string |链接关联项目拥有者标识 |
|
||||
|project.owner.image_url|string |链接关联项目拥有者头像 |
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 7,
|
||||
"role": "developer",
|
||||
"is_apply": false,
|
||||
"sign": "6b6b454843c291d4e52e60853cb8ad9f",
|
||||
"expired_at": "2022-06-23 10:08",
|
||||
"user": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
},
|
||||
"project": {
|
||||
"id": 474,
|
||||
"identifier": "kellect",
|
||||
"name": "kellect",
|
||||
"description": null,
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 获取邀请链接信息(被邀请用户)
|
||||
用户请求邀请链接时,通过该接口来获取链接的信息
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X GET http://localhost:3000/api/yystopf/kellect/project_invite_links/show_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/yystopf/kellect/project_invite_links/show_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/project_invite_links/show_link.json?invite_sign=xxx`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|invite_sign |是| |string |项目邀请链接的标识 |
|
||||
|
||||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
|id |int |链接id |
|
||||
|role |string |邀请角色|
|
||||
|is_apply |boolean |是否需要审核 |
|
||||
|sign |string |邀请标识(放在链接后面即可)|
|
||||
|expired_at |string |链接过期时间|
|
||||
|user.id |int |链接创建者的id |
|
||||
|user.type |string |链接创建者的类型 |
|
||||
|user.name |string |链接创建者的名称 |
|
||||
|user.login |string |链接创建者的标识 |
|
||||
|user.image_url |string |链接创建者头像 |
|
||||
|project.id |int |链接关联项目的id |
|
||||
|project.identifier |string |链接关联项目的标识 |
|
||||
|project.name |string |链接关联项目的名称 |
|
||||
|project.description |string |链接关联项目的描述 |
|
||||
|project.is_public |bool |链接关联项目是否公开 |
|
||||
|project.owner.id |bool |链接关联项目拥有者id |
|
||||
|project.owner.type |string |链接关联项目拥有者类型 |
|
||||
|project.owner.name |string |链接关联项目拥有者昵称 |
|
||||
|project.owner.login |string |链接关联项目拥有者标识 |
|
||||
|project.owner.image_url|string |链接关联项目拥有者头像 |
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 7,
|
||||
"role": "developer",
|
||||
"is_apply": false,
|
||||
"sign": "6b6b454843c291d4e52e60853cb8ad9f",
|
||||
"expired_at": "2022-06-23 10:08",
|
||||
"user": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
},
|
||||
"project": {
|
||||
"id": 474,
|
||||
"identifier": "kellect",
|
||||
"name": "kellect",
|
||||
"description": null,
|
||||
"is_public": true,
|
||||
"owner": {
|
||||
"id": 2,
|
||||
"type": "User",
|
||||
"name": "heh",
|
||||
"login": "yystopf",
|
||||
"image_url": "system/lets/letter_avatars/2/H/188_239_142/120.png"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 接受项目邀请链接(被邀请用户)
|
||||
当前登录(非项目)用户加入项目的接口,如果项目链接不需要审核,请求成功后即加入项目,如果需要审核,那么会提交一个申请,需要项目管理员审核
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/yystopf/kellect/project_invite_links/redirect_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/yystopf/kellect/project_invite_links/redirect_link.json?invite_sign=d612df03aad63760445c187bcf83f2e6')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/project_invite_links/redirect_link.json?invite_sign=xxx`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|invite_sign |是| |string |项目邀请链接的标识 |
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
||||
|
||||
## 申请加入项目
|
||||
申请加入项目
|
||||
|
@ -280,7 +554,7 @@ repo |是| |string |项目标识identifier
|
|||
### 返回字段说明
|
||||
参数 | 类型 | 字段说明
|
||||
--------- | ----------- | -----------
|
||||
menu_name |string|导航名称, home:主页,code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
|
||||
menu_name |string|导航名称, home:主页,code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑,activity:动态,setting:仓库设置
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
@ -408,7 +682,7 @@ await octokit.request('POST /api/yystopf/ceshi/project_units')
|
|||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:易修,pulls:合并请求,devops:工作流,versions:里程碑 |
|
||||
|unit_types |是| |array | 项目模块内容, 支持以下参数:code:代码库,issues:疑修,pulls:合并请求,devops:工作流,versions:里程碑 |
|
||||
|
||||
|
||||
### 返回字段说明:
|
||||
|
@ -850,3 +1124,35 @@ await octokit.request('POST /api/:owner/:repo/applied_transfer_projects/cancel.j
|
|||
"time_ago": "1分钟前"
|
||||
}
|
||||
```
|
||||
|
||||
## 退出项目
|
||||
供项目成员(开发者、报告者)退出项目用
|
||||
|
||||
> 示例:
|
||||
|
||||
```shell
|
||||
curl -X POST http://localhost:3000/api/ceshi1/ceshi_repo1/quit.json
|
||||
```
|
||||
|
||||
```javascript
|
||||
await octokit.request('POST /api/:owner/:repo/quit.json')
|
||||
```
|
||||
|
||||
### HTTP 请求
|
||||
`POST /api/:owner/:repo/quit.json`
|
||||
|
||||
### 请求参数
|
||||
参数 | 必选 | 默认 | 类型 | 字段说明
|
||||
--------- | ------- | ------- | -------- | ----------
|
||||
|owner |是| |string |用户登录名 |
|
||||
|repo |是| |string |项目标识identifier |
|
||||
|
||||
|
||||
> 返回的JSON示例:
|
||||
|
||||
```json
|
||||
{
|
||||
"status": 0,
|
||||
"message": "success"
|
||||
}
|
||||
```
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue