Browse Source

webIDE

pull/3374/head
weishao 3 years ago
parent
commit
b44a7334d2
77 changed files with 49083 additions and 49 deletions
  1. +13
    -0
      assets/abandon.svg
  2. +11
    -0
      assets/code1.svg
  3. +11
    -0
      assets/code2.svg
  4. +13
    -0
      assets/codeLog.svg
  5. +11
    -0
      assets/drag.svg
  6. BIN
      assets/drag2.png
  7. +9
    -0
      assets/more.svg
  8. +11
    -0
      assets/submit.svg
  9. +13
    -0
      assets/submit2.svg
  10. +11
    -0
      assets/warehouse.svg
  11. +6
    -0
      modules/repofiles/content.go
  12. +26
    -0
      modules/structs/repo_file.go
  13. +18
    -0
      modules/structs/repo_tree.go
  14. +7
    -0
      package.json
  15. BIN
      public/0acc017d3b9b32f1f61a9af2315d5187.png
  16. BIN
      public/0f1600ced2415ea9530a1a55ec045fef.png
  17. BIN
      public/1f2e7b26b1be5e67e613178f38625008.png
  18. BIN
      public/276e9642cca7e5f8958c004269a6c0d7.png
  19. BIN
      public/41fa1ffe704082c381ae88ea686c9f39.png
  20. BIN
      public/5920c99e273bded4a2c702d4a1ed59ee.png
  21. BIN
      public/6f562e238482d4479212cbf367f6a293.png
  22. BIN
      public/71261d74041a4133ae4b9908d4a8109f.png
  23. BIN
      public/d4f9fbedc79f92e41f984283b6227127.png
  24. +539
    -0
      public/iconfonts1/demo.css
  25. +27651
    -0
      public/iconfonts1/demo_index.html
  26. BIN
      public/iconfonts1/devopicons.e19892d.woff2
  27. BIN
      public/iconfonts1/file-icons.woff2
  28. BIN
      public/iconfonts1/fontawesome.af7ae50.woff2
  29. +4792
    -0
      public/iconfonts1/iconfont.css
  30. +1
    -0
      public/iconfonts1/iconfont.js
  31. +8367
    -0
      public/iconfonts1/iconfont.json
  32. +2407
    -0
      public/iconfonts1/iconfont.svg
  33. BIN
      public/iconfonts1/iconfont.ttf
  34. BIN
      public/iconfonts1/iconfont.woff
  35. BIN
      public/iconfonts1/iconfont.woff2
  36. BIN
      public/iconfonts1/mfixx.0a32a80.woff2
  37. BIN
      public/iconfonts1/octicons.de59a97.woff2
  38. BIN
      public/images/abandon.png
  39. BIN
      public/images/bronze.png
  40. BIN
      public/images/code1.png
  41. BIN
      public/images/code2.png
  42. BIN
      public/images/codeFloder.png
  43. BIN
      public/images/drag.png
  44. BIN
      public/images/gold.png
  45. BIN
      public/images/silver.png
  46. BIN
      public/images/submit.png
  47. BIN
      public/images/submitLog1.png
  48. BIN
      public/images/submitLog2.png
  49. BIN
      public/images/warehouse.png
  50. BIN
      public/img/empty.png
  51. +4
    -0
      routers/api/v1/api.go
  52. +152
    -0
      routers/api/v1/repo/file.go
  53. +100
    -0
      routers/api/v1/repo/tree.go
  54. +220
    -0
      routers/api/v1/utils/utils.go
  55. +13
    -0
      routers/home.go
  56. +11
    -0
      routers/routes/routes.go
  57. +21
    -9
      templates/base/footer_fluid.tmpl
  58. +6
    -6
      templates/base/head.tmpl
  59. +4
    -4
      templates/base/head_course.tmpl
  60. +6
    -6
      templates/base/head_fluid.tmpl
  61. +23
    -0
      templates/explore/ide.tmpl
  62. +6
    -3
      templates/repo/home.tmpl
  63. +20
    -8
      web_src/js/components/Contributors.vue
  64. +0
    -0
      web_src/js/components/IdeProject.vue
  65. +0
    -0
      web_src/js/components/VueTreeList.vue
  66. +299
    -0
      web_src/js/components/db.js
  67. +1089
    -0
      web_src/js/components/icons.js
  68. +0
    -0
      web_src/js/components/monacoeditor.vue
  69. +3024
    -0
      web_src/js/components/treeIcon.css
  70. +0
    -0
      web_src/js/components/vueTree.vue
  71. +20
    -2
      web_src/js/index.js
  72. +16
    -10
      web_src/js/router/index.js
  73. +114
    -0
      web_src/js/utils.js
  74. +1
    -1
      web_src/less/_repository.less
  75. +1
    -0
      web_src/less/_svg.less
  76. +8
    -0
      webpack.config.js
  77. +8
    -0
      webpack_pro.config.js

+ 13
- 0
assets/abandon.svg View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>放弃更改</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Manaco-提交" transform="translate(-414.000000, -114.000000)" fill="#9096A3" fill-rule="nonzero">
<g id="编组-8" transform="translate(90.000000, 114.000000)">
<g id="放弃更改" transform="translate(324.000000, 0.000000)">
<path d="M5.64465565,9.44839769 C3.70098527,7.81473925 1.87574642,6.2803543 0.00696656051,4.7093949 C1.86355494,3.14888535 3.69053543,1.61624204 5.60633957,0.00696656051 L5.60633957,2.18575836 C6.64958201,2.31638137 7.63535032,2.37385549 8.58976911,2.57240247 C10.5734972,2.98342954 12.1549064,3.94655653 12.8445959,5.99472532 C13.8408141,8.95028861 12.6599821,12.2263137 10.0057225,13.8564889 C9.96914809,13.8791302 9.92386545,13.8913217 9.82981688,13.9296377 C10.1851115,13.4959693 10.5282146,13.1267416 10.8173268,12.7174562 C11.3885848,11.9128185 11.7212381,11.0176154 11.7595541,10.0213973 C11.7943869,9.12271099 11.3955514,8.46959594 10.6431628,8.01328623 C9.76363455,7.47860271 8.77786624,7.28876393 7.77816481,7.20516521 C7.08499204,7.14769108 6.38485271,7.19471537 5.64465565,7.19471537 L5.64465565,9.44839769 Z" id="路径"></path>
</g>
</g>
</g>
</g>
</svg>

+ 11
- 0
assets/code1.svg View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="22px" height="24px" viewBox="0 0 22 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>代码1</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Manaco-代码" transform="translate(-24.000000, -54.000000)" fill="#FFFFFF" fill-rule="nonzero">
<g id="编组-2" transform="translate(23.000000, 54.000000)">
<path d="M18.691358,20.6530612 C19.3209877,20.6530612 19.8024691,21.4013605 19.8148148,22.3265306 C19.8148148,23.2380952 19.308642,24 18.7037037,24 L5.2962963,24 C4.67901235,24 4.18518519,23.2517007 4.18518519,22.3265306 C4.18518519,21.414966 4.69135802,20.6530612 5.2962963,20.6530612 L18.691358,20.6530612 Z M21.4320988,1.24344979e-14 C22.2962963,1.24344979e-14 23,0.74829932 23,1.67346939 L23,16.707483 L22.9876543,16.707483 C22.9876543,17.6190476 22.2839506,18.3809524 21.4197531,18.3809524 L2.56790123,18.3809524 C1.7037037,18.3809524 1,17.6326531 1,16.707483 L1,1.67346939 C1,0.761904762 1.7037037,1.24344979e-14 2.56790123,1.24344979e-14 L21.4320988,1.24344979e-14 Z M7.40275426,5.59798965 L4.42406571,7.86899844 C4.2208615,8.02209757 4.09361684,8.24213052 4.07053819,8.48032233 C4.04570362,8.87774887 4.05154704,9.27649576 4.08952935,9.67260195 C4.11436392,9.92346921 4.25168453,10.1518904 4.4693523,10.3024108 L7.45096256,12.4215789 C7.80850744,12.6781677 8.30844535,12.6529526 8.6334608,12.3784779 L8.71752605,12.2974656 L8.71752605,12.2974656 C9.05638834,11.8920818 8.97886013,11.3169104 8.54222314,10.996917 L5.87323641,9.10088868 L8.58750971,7.02925332 C8.99780991,6.70122471 9.06310176,6.14433333 8.73797805,5.74586928 C8.58953291,5.5575319 8.36035163,5.43424637 8.10640394,5.40612098 C7.85245625,5.37799559 7.59712068,5.44761958 7.40275426,5.59798965 Z M13.2750251,5.43601868 C13.041601,5.50337484 12.8462407,5.65606881 12.7322875,5.86022349 L9.67682551,11.2791811 C9.51225291,11.5570107 9.51537327,11.896483 9.68502809,12.1715632 C9.85162755,12.4442956 10.1628838,12.6086547 10.4957167,12.5996479 C10.8286146,12.587652 11.1280084,12.4046164 11.2763291,12.1224175 L14.3331583,6.70475316 C14.4492093,6.49817249 14.4756869,6.25696469 14.4069815,6.03223337 C14.340046,5.80948374 14.182814,5.62076308 13.9695104,5.50715059 L13.9681433,5.50715059 C13.7568457,5.39554401 13.5067057,5.36987315 13.2750251,5.43601868 Z M15.8922987,5.40611327 C15.6385591,5.43425376 15.4096876,5.55776951 15.2618761,5.74633526 C14.9356259,6.14558659 15.0029615,6.70437583 15.4166517,7.0307509 L18.129604,9.10060055 L15.4619162,10.9975227 C15.0590628,11.2928349 14.9620467,11.8055279 15.2158996,12.20143 L15.2866986,12.297779 L15.2866986,12.297779 C15.6035504,12.6462741 16.1627866,12.7017165 16.5526457,12.4205444 L19.5328049,10.3044927 C19.750759,10.1515096 19.8883325,9.92333042 19.912443,9.67482542 C19.9489467,9.27880827 19.9547872,8.87883095 19.9270444,8.48149375 L19.9270444,8.48017369 C19.903977,8.24203541 19.7767943,8.02205192 19.573689,7.86898721 L16.5949899,5.59848887 C16.4011465,5.4478137 16.1460382,5.37797278 15.8922987,5.40611327 Z" id="代码1"></path>
</g>
</g>
</g>
</svg>

+ 11
- 0
assets/code2.svg View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="22px" height="24px" viewBox="0 0 22 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>代码</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Manaco-提交" transform="translate(-24.000000, -54.000000)" fill="#000000" fill-rule="nonzero">
<g id="编组-2" transform="translate(23.000000, 54.000000)">
<path d="M18.691358,20.6530612 C19.3209877,20.6530612 19.8024691,21.4013605 19.8148148,22.3265306 C19.8148148,23.2380952 19.308642,24 18.7037037,24 L5.2962963,24 C4.67901235,24 4.18518519,23.2517007 4.18518519,22.3265306 C4.18518519,21.414966 4.69135802,20.6530612 5.2962963,20.6530612 L18.691358,20.6530612 Z M21.4320988,1.24344979e-14 C22.2962963,1.24344979e-14 23,0.74829932 23,1.67346939 L23,16.707483 L22.9876543,16.707483 C22.9876543,17.6190476 22.2839506,18.3809524 21.4197531,18.3809524 L2.56790123,18.3809524 C1.7037037,18.3809524 1,17.6326531 1,16.707483 L1,1.67346939 C1,0.761904762 1.7037037,1.24344979e-14 2.56790123,1.24344979e-14 L21.4320988,1.24344979e-14 Z M7.40275426,5.59798965 L4.42406571,7.86899844 C4.2208615,8.02209757 4.09361684,8.24213052 4.07053819,8.48032233 C4.04570362,8.87774887 4.05154704,9.27649576 4.08952935,9.67260195 C4.11436392,9.92346921 4.25168453,10.1518904 4.4693523,10.3024108 L7.45096256,12.4215789 C7.80850744,12.6781677 8.30844535,12.6529526 8.6334608,12.3784779 L8.71752605,12.2974656 L8.71752605,12.2974656 C9.05638834,11.8920818 8.97886013,11.3169104 8.54222314,10.996917 L5.87323641,9.10088868 L8.58750971,7.02925332 C8.99780991,6.70122471 9.06310176,6.14433333 8.73797805,5.74586928 C8.58953291,5.5575319 8.36035163,5.43424637 8.10640394,5.40612098 C7.85245625,5.37799559 7.59712068,5.44761958 7.40275426,5.59798965 Z M13.2750251,5.43601868 C13.041601,5.50337484 12.8462407,5.65606881 12.7322875,5.86022349 L9.67682551,11.2791811 C9.51225291,11.5570107 9.51537327,11.896483 9.68502809,12.1715632 C9.85162755,12.4442956 10.1628838,12.6086547 10.4957167,12.5996479 C10.8286146,12.587652 11.1280084,12.4046164 11.2763291,12.1224175 L14.3331583,6.70475316 C14.4492093,6.49817249 14.4756869,6.25696469 14.4069815,6.03223337 C14.340046,5.80948374 14.182814,5.62076308 13.9695104,5.50715059 L13.9681433,5.50715059 C13.7568457,5.39554401 13.5067057,5.36987315 13.2750251,5.43601868 Z M15.8922987,5.40611327 C15.6385591,5.43425376 15.4096876,5.55776951 15.2618761,5.74633526 C14.9356259,6.14558659 15.0029615,6.70437583 15.4166517,7.0307509 L18.129604,9.10060055 L15.4619162,10.9975227 C15.0590628,11.2928349 14.9620467,11.8055279 15.2158996,12.20143 L15.2866986,12.297779 L15.2866986,12.297779 C15.6035504,12.6462741 16.1627866,12.7017165 16.5526457,12.4205444 L19.5328049,10.3044927 C19.750759,10.1515096 19.8883325,9.92333042 19.912443,9.67482542 C19.9489467,9.27880827 19.9547872,8.87883095 19.9270444,8.48149375 L19.9270444,8.48017369 C19.903977,8.24203541 19.7767943,8.02205192 19.573689,7.86898721 L16.5949899,5.59848887 C16.4011465,5.4478137 16.1460382,5.37797278 15.8922987,5.40611327 Z" id="代码"></path>
</g>
</g>
</g>
</svg>

+ 13
- 0
assets/codeLog.svg View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="16px" viewBox="0 0 14 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>代码文件</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Manaco-提交" transform="translate(-90.000000, -169.000000)" fill="#6F6E6E" fill-rule="nonzero">
<g id="编组-8" transform="translate(90.000000, 114.000000)">
<g id="编组-5" transform="translate(0.000000, 55.000000)">
<path d="M9.72883333,0 C10.0462727,0 10.3500145,0.136417787 10.57,0.377846154 L13.6733333,3.78092308 C13.882631,4.01000077 13.9997061,4.31568263 14,4.63384615 L14,14.7692308 C14,15.4489658 13.4776655,16 12.8333333,16 L1.16666667,16 C0.522334459,16 0,15.4489658 0,14.7692308 L0,1.23076923 C0,0.551034154 0.522334459,0 1.16666667,0 L9.72883333,0 Z M6.36548862,5.17542359 C6.11720692,4.93565488 5.72153765,4.94252988 5.48173828,5.19078174 L5.48173828,5.19078174 L3.18299167,7.48923751 C2.93900277,7.73326904 2.93900277,8.1288445 3.18299173,8.37287604 L3.18299173,8.37287604 L5.48173833,10.6750818 C5.72394113,10.908979 6.1079261,10.908979 6.3501289,10.6750818 C6.59841088,10.4353128 6.60528832,10.0396952 6.36548895,9.79144331 L6.36548895,9.79144331 L4.50923605,7.93043799 L6.3808487,6.05906212 C6.62064776,5.81081183 6.61377188,5.41519262 6.36548862,5.17542359 Z M11.009075,5.01869617 C10.6741417,4.93523201 10.3349555,5.13905256 10.2514799,5.47394202 L10.2514799,5.47394202 L9.02147908,10.0608692 C8.9320786,10.3942696 9.12991167,10.7370085 9.46335425,10.8263983 C9.79679682,10.9157874 10.139579,10.7179794 10.2289801,10.384579 L10.2289801,10.384579 L11.4577308,5.79640184 L11.4589816,5.79640005 L11.4643785,5.77619549 C11.5478532,5.44130448 11.3440069,5.10216127 11.009075,5.01869617 Z" id="代码文件"></path>
</g>
</g>
</g>
</g>
</svg>

+ 11
- 0
assets/drag.svg View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="22px" height="10px" viewBox="0 0 22 10" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>左右拖动</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Manaco-代码" transform="translate(-440.000000, -546.000000)" fill="#6F6E6E" fill-rule="nonzero">
<g id="左右拖动" transform="translate(440.000000, 546.000000)">
<path d="M5.89500984,9.90606823 L0.154266811,5.3158823 C0.0566144941,5.23813069 0,5.12195442 0,4.99931775 C0,4.87668107 0.0566144941,4.76050481 0.154266811,4.6827532 L5.89500984,0.0925672631 C6.02101948,-0.00758660268 6.19515807,-0.0282927778 6.34232468,0.0393787107 C6.48949128,0.107050199 6.58336056,0.250994188 6.58344941,0.409131811 L6.58344941,2.76972089 C6.58344941,2.99579905 6.77215853,3.1790716 7.00494302,3.1790716 L14.996462,3.1790716 C15.2292464,3.1790716 15.4179556,2.99579905 15.4179556,2.76972089 L15.4179556,0.410496313 C15.4180444,0.252358691 15.5119137,0.108414701 15.6590803,0.040743213 C15.8062469,-0.0269282754 15.9803855,-0.00622210032 16.1063951,0.0939317654 L21.8457332,4.6841177 C21.9433855,4.76186931 22,4.87804558 22,5.00068225 C22,5.12331893 21.9433855,5.23949519 21.8457332,5.3172468 L16.1063951,9.90743274 C15.9803855,10.0075866 15.8062469,10.0282928 15.6590803,9.96062129 C15.5119137,9.8929498 15.4180444,9.74900581 15.4179556,9.59086819 L15.4179556,7.23027911 C15.4179556,7.00420095 15.2292464,6.8209284 14.996462,6.8209284 L7.00494302,6.8209284 C6.77215853,6.8209284 6.58344941,7.00420095 6.58344941,7.23027911 L6.58344941,9.59086819 C6.58336056,9.74900581 6.48949128,9.8929498 6.34232468,9.96062129 C6.19515807,10.0282928 6.02101948,10.0075866 5.89500984,9.90743274 L5.89500984,9.90606823 Z" id="路径"></path>
</g>
</g>
</g>
</svg>

BIN
assets/drag2.png View File

Before After
Width: 28  |  Height: 28  |  Size: 801 B

+ 9
- 0
assets/more.svg View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>更多</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Manaco-代码" transform="translate(-412.000000, -59.000000)" fill="#9FA5B0">
<path d="M426,59 C427.104569,59 428,59.8954305 428,61 L428,73 C428,74.1045695 427.104569,75 426,75 L414,75 C412.895431,75 412,74.1045695 412,73 L412,61 C412,59.8954305 412.895431,59 414,59 L426,59 Z M416,66 C415.447715,66 415,66.4477153 415,67 C415,67.5522847 415.447715,68 416,68 C416.552285,68 417,67.5522847 417,67 C417,66.4477153 416.552285,66 416,66 Z M420,66 C419.447715,66 419,66.4477153 419,67 C419,67.5522847 419.447715,68 420,68 C420.552285,68 421,67.5522847 421,67 C421,66.4477153 420.552285,66 420,66 Z M424,66 C423.447715,66 423,66.4477153 423,67 C423,67.5522847 423.447715,68 424,68 C424.552285,68 425,67.5522847 425,67 C425,66.4477153 424.552285,66 424,66 Z" id="更多"></path>
</g>
</g>
</svg>

+ 11
- 0
assets/submit.svg View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>提交</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Manaco-代码" transform="translate(-23.000000, -124.000000)" fill="#000000" fill-rule="nonzero">
<g id="编组-3" transform="translate(23.000000, 124.000000)">
<path d="M20.1289472,24 L7.67629341,24 C5.45869754,24 3.92343885,22.0588235 3.92343885,19.7647059 C3.92343885,17.4705882 5.79986613,15.8823529 8.01746202,15.8823529 L8.1880463,15.8823529 C8.35863061,14.2941177 9.5527207,12.882353 11.2585637,13.0588235 C11.7703166,13.0588235 12.1114852,13.2352941 12.6232381,13.4117647 C13.3055753,12 14.6702497,11.117647 16.3760926,11.117647 C18.9348571,11.117647 21.152453,13.2352941 21.152453,15.8823529 L21.152453,16.0588235 C23.1994646,16.5882353 24.3935547,18.8823529 23.8818017,21 C23.3700488,22.7647059 21.8347902,23.8235294 20.1289472,24 Z M16.3760926,9.35294117 C14.4996653,9.35294117 12.7938224,10.2352941 11.5997323,11.6470588 L10.7468108,11.6470588 C9.38213639,11.6470588 8.1880463,12.5294118 7.50570911,13.7647059 L0,13.7647059 L0,7.76470589 L22.5171273,7.76470589 L22.5171273,14.2941176 C21.6642058,12 20.1289472,9.17647058 16.3760926,9.35294117 Z M4.09402315,9.1764706 C3.24110165,9.1764706 2.55876448,9.88235296 2.55876448,10.7647059 C2.55876448,11.6470588 3.24110167,12.3529412 4.09402315,12.3529412 C4.94694463,12.3529412 5.62928185,11.6470588 5.62928185,10.7647059 C5.62928185,9.88235296 4.94694465,9.1764706 4.09402315,9.1764706 Z M1.70584298,-5.32907052e-15 L20.8112844,-5.32907052e-15 C21.8347902,-5.32907052e-15 22.5171273,0.705882356 22.5171273,1.7647059 L22.5171273,6 L0,6 L0,1.7647059 C0,0.882352951 0.682337196,-5.32907052e-15 1.70584298,-5.32907052e-15 Z M4.09402315,4.5882353 C4.94694465,4.5882353 5.62928185,3.88235294 5.62928185,3.00000002 C5.62928185,2.11764709 4.94694465,1.41176471 4.09402315,1.41176471 C3.24110165,1.41176471 2.55876448,2.11764707 2.55876448,3.00000002 C2.55876448,3.88235297 3.24110167,4.5882353 4.09402315,4.5882353 L4.09402315,4.5882353 Z M2.55876448,19.9411765 C2.55876448,21.5294117 3.24110167,23.117647 4.43519176,24 L1.70584298,24 C0.682337196,24 0,23.2941176 0,22.2352941 L0,15.3529412 L5.11752893,15.3529412 C3.58227026,16.2352941 2.55876446,18 2.55876448,19.9411765 Z" id="提交"></path>
</g>
</g>
</g>
</svg>

+ 13
- 0
assets/submit2.svg View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="16px" viewBox="0 0 14 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>提交</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Manaco-提交" transform="translate(-91.000000, -59.000000)" fill="#000000" fill-rule="nonzero">
<g id="编组-17" transform="translate(91.000000, 59.000000)">
<g id="提交" transform="translate(-0.000000, 0.000000)">
<path d="M13.4778367,15.988073 L9.55310265,15.988073 L9.55310265,15.43347 L9.55310265,15.0458442 L12.972039,15.0458442 L12.972039,0.954155797 L6.14056884,0.954155797 L6.14056884,4.72903466 C6.14056884,4.98922102 5.91411232,5.20014909 5.63477113,5.20014909 C5.62509697,5.20014909 5.61549961,5.19983898 5.60595988,5.19933805 C5.59642015,5.19983898 5.5868228,5.20014909 5.57714861,5.20014909 L1.01856687,5.20014909 L1.01856687,15.0458442 L4.43110069,15.0458442 L4.43110069,15.43347 L4.43110069,15.988073 L0.512769174,15.988073 C0.233427991,15.988073 0.00697148198,15.777145 0.00697148198,15.5169586 L0.00697148198,4.52031308 C0.00697148198,4.40469325 0.0517633795,4.29885948 0.125968379,4.21687961 C0.160010492,4.16720388 0.201492303,4.11953783 0.250183335,4.07557511 L4.51104873,0.228985469 C4.60098467,0.0984748438 4.75803806,0.0119269531 4.93689838,0.0119269531 L13.4778367,0.0119269531 C13.7571778,0.0119269531 13.9836343,0.222855016 13.9836343,0.483041375 L13.9836343,15.5169586 C13.9836343,15.777145 13.7571778,15.988073 13.4778367,15.988073 Z M5.12897344,0.983311219 L1.50169969,4.25792023 L5.12897344,4.25792023 L5.12897344,0.983311219 Z M2.5954584,10.7580947 L2.59340321,9.61971525 L11.8174309,9.61904138 L11.8194925,10.7574268 L2.5954584,10.7580947 Z M2.59340321,6.38751248 L11.8174309,6.38683861 L11.8194925,7.525224 L2.5954584,7.52589191 L2.59340321,6.38751248 Z M2.5954584,9.1419933 L2.59340321,8.00361386 L11.8174309,8.00294 L11.8194925,9.14132537 L2.5954584,9.1419933 Z M7.04972419,11.4171182 L8.63383774,12.8930302 L7.63185892,12.8930302 L7.63239672,14.8444696 L6.41020382,14.845054 L6.40966602,12.8930302 L5.46561062,12.8930302 L7.04972419,11.4171182 Z" id="形状"></path>
</g>
</g>
</g>
</g>
</svg>

+ 11
- 0
assets/warehouse.svg View File

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="14px" height="16px" viewBox="0 0 14 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>代码仓库</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Manaco-代码" transform="translate(-90.000000, -59.000000)" fill="#000000" fill-rule="nonzero">
<g id="代码仓库" transform="translate(90.000000, 59.000000)">
<path d="M13.5574941,6.11252215 L7.7074972,0.29324975 L7.70749726,0.293249807 C7.31718961,-0.0974428356 6.68402439,-0.0977943985 6.29328388,0.29246314 C6.29302151,0.292725179 6.2927593,0.292987362 6.29249722,0.293249694 L0.442500285,6.11252209 L0.442500249,6.11252213 C0.159278149,6.3940287 0,6.77683852 0,7.17613743 L0,14.5002084 L0,14.5002082 C0,15.3285311 0.671573248,16.0000193 1.5,16.0000193 L12.5,16.0000193 L12.5,16.0000193 C13.3284268,16.0000193 14,15.3285311 14,14.5002082 C14,14.5002082 14,14.5002082 14,14.5002082 L14,7.17613718 L14,7.17619816 C14,6.77689769 13.8407531,6.39408162 13.5575435,6.11256411 L13.5574941,6.11252215 Z M6.36499767,11.8617945 L6.36499768,11.8617945 C6.60479705,12.1100463 6.5979196,12.505664 6.34963762,12.745433 C6.10743482,12.9793301 5.72344986,12.9793301 5.48124706,12.745433 L3.18250042,10.4432272 L3.18250045,10.4432272 C2.93851149,10.1991957 2.93851149,9.80362021 3.18250039,9.55958868 L5.48124703,7.26113288 L5.481247,7.2611329 C5.72104637,7.01288105 6.11671564,7.00600604 6.36499734,7.24577476 C6.6132806,7.48554379 6.62015648,7.881163 6.38035743,8.12941329 C6.37532678,8.13462123 6.37020601,8.13974136 6.3649974,8.14477137 L4.50874477,10.0007892 L6.36499767,11.8617945 Z M10.978743,7.86855544 L9.74999237,12.4567327 L9.74999239,12.4567326 C9.66059128,12.790133 9.31780908,12.987941 8.98436651,12.8985518 C8.65092393,12.8091621 8.45309086,12.4664232 8.54249134,12.1330228 L9.77249213,7.54609562 L9.77249214,7.54609561 C9.8559678,7.21120616 10.1951539,7.00738561 10.5300873,7.09084977 C10.8650191,7.17431487 11.0688655,7.51345807 10.9853908,7.84834909 C10.9837046,7.85511356 10.9819054,7.86184935 10.9799938,7.86855364 L10.978743,7.86855544 Z" id="形状"></path>
</g>
</g>
</g>
</svg>

+ 6
- 0
modules/repofiles/content.go View File

@@ -5,6 +5,7 @@
package repofiles

import (
"code.gitea.io/gitea/routers/api/v1/utils"
"fmt"
"net/url"
"path"
@@ -95,6 +96,7 @@ func GetContentsOrList(repo *models.Repository, treePath, ref string) (interface
}
fileList = append(fileList, fileContentResponse)
}

return fileList, nil
}

@@ -213,5 +215,9 @@ func GetContents(repo *models.Repository, treePath, ref string, forList bool) (*
contentsResponse.Links.GitURL = &gitURLString
}

// set file language and file type
contentsResponse.Language = utils.JudgeLanguageBySuffix(treePath)
contentsResponse.FileType = utils.JudgeFileTypeBySuffix(treePath)

return contentsResponse, nil
}

+ 26
- 0
modules/structs/repo_file.go View File

@@ -48,6 +48,30 @@ type UpdateFileOptions struct {
FromPath string `json:"from_path" binding:"MaxSize(500)"`
}

// CommitMultiFileOptions options for commit multi files
type CommitMultiFileOptions struct {
Files []CommitFileOptions `json:"files"`
Msg string `json:"msg"`
}

// CommitFileOptions options for commit files
// Note: `author` and `committer` are optional (if only one is given, it will be used for the other, otherwise the authenticated user will be used)
type CommitFileOptions struct {
FileOptions
// file path
FilePath string `json:"filePath"`
// content must be base64 encoded
Content string `json:"content"`
// sha is the SHA for the file that already exists
SHA string `json:"sha"`

// from_path (optional) is the path of the original file which will be moved/renamed to the path in the URL
FromPath string `json:"from_path" binding:"MaxSize(500)"`
// operation: add, update, delete
// required: true
Operation string `json:"operation"`
}

// FileLinksResponse contains the links for a repo's file
type FileLinksResponse struct {
Self *string `json:"self"`
@@ -76,6 +100,8 @@ type ContentsResponse struct {
// `submodule_git_url` is populated when `type` is `submodule`, otherwise null
SubmoduleGitURL *string `json:"submodule_git_url"`
Links *FileLinksResponse `json:"_links"`
Language string `json:"language"`
FileType string `json:"fileType"`
}

// FileCommitResponse contains information generated from a Git commit for a repo's file.


+ 18
- 0
modules/structs/repo_tree.go View File

@@ -14,6 +14,14 @@ type GitEntry struct {
URL string `json:"url"`
}

// GitEntryWithChildren represents a git tree entry with children
type GitEntryWithChildren struct {
GitEntry
Children []GitEntryWithChildren `json:"children"`
Name string `json:"name"`
Suffix string `json:"suffix"`
}

// GitTreeResponse returns a git tree
type GitTreeResponse struct {
SHA string `json:"sha"`
@@ -23,3 +31,13 @@ type GitTreeResponse struct {
Page int `json:"page"`
TotalCount int `json:"total_count"`
}

// GitTreeWithChildrenResponse returns a git tree with children
type GitTreeWithChildrenResponse struct {
SHA string `json:"sha"`
URL string `json:"url"`
Entries []GitEntryWithChildren `json:"tree"`
Truncated bool `json:"truncated"`
Page int `json:"page"`
TotalCount int `json:"total_count"`
}

+ 7
- 0
package.json View File

@@ -51,6 +51,7 @@
"svgo-loader": "2.2.1",
"swagger-ui": "3.25.3",
"terser-webpack-plugin": "3.0.1",
"uuidv1": "1.6.14",
"vue": "2.6.11",
"vue-bar-graph": "1.2.0",
"vue-calendar-heatmap": "0.8.4",
@@ -58,13 +59,16 @@
"vue-loader": "15.9.2",
"vue-router": "3.3.4",
"vue-template-compiler": "2.6.11",
"vue-tree-list": "1.5.0",
"webpack": "4.43.0",
"webpack-cli": "3.3.11",
"webpack-dev-server": "4.9.3",
"webpack-fix-style-only-entries": "0.4.0",
"worker-loader": "2.0.0",
"xlsx": "0.17.3"
},
"devDependencies": {
"@webpack-cli/serve": "1.7.0",
"eslint": "6.8.0",
"eslint-config-airbnb-base": "14.1.0",
"eslint-plugin-import": "2.20.2",
@@ -77,6 +81,9 @@
"typescript": "4.5.5",
"updates": "10.2.11"
},
"scripts": {
"start": "make watch-frontend && ./opendata"
},
"browserslist": [
"defaults"
]


BIN
public/0acc017d3b9b32f1f61a9af2315d5187.png View File

Before After
Width: 44  |  Height: 48  |  Size: 994 B

BIN
public/0f1600ced2415ea9530a1a55ec045fef.png View File

Before After
Width: 28  |  Height: 28  |  Size: 801 B

BIN
public/1f2e7b26b1be5e67e613178f38625008.png View File

Before After
Width: 44  |  Height: 48  |  Size: 1.1 kB

BIN
public/276e9642cca7e5f8958c004269a6c0d7.png View File

Before After
Width: 360  |  Height: 313  |  Size: 25 kB

BIN
public/41fa1ffe704082c381ae88ea686c9f39.png View File

Before After
Width: 44  |  Height: 20  |  Size: 567 B

BIN
public/5920c99e273bded4a2c702d4a1ed59ee.png View File

Before After
Width: 28  |  Height: 32  |  Size: 608 B

BIN
public/6f562e238482d4479212cbf367f6a293.png View File

Before After
Width: 28  |  Height: 32  |  Size: 542 B

BIN
public/71261d74041a4133ae4b9908d4a8109f.png View File

Before After
Width: 48  |  Height: 48  |  Size: 1.1 kB

BIN
public/d4f9fbedc79f92e41f984283b6227127.png View File

Before After
Width: 48  |  Height: 48  |  Size: 1.2 kB

+ 539
- 0
public/iconfonts1/demo.css View File

@@ -0,0 +1,539 @@
/* Logo 字体 */
@font-face {
font-family: "iconfont logo";
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
}

.logo {
font-family: "iconfont logo";
font-size: 160px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

/* tabs */
.nav-tabs {
position: relative;
}

.nav-tabs .nav-more {
position: absolute;
right: 0;
bottom: 0;
height: 42px;
line-height: 42px;
color: #666;
}

#tabs {
border-bottom: 1px solid #eee;
}

#tabs li {
cursor: pointer;
width: 100px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 16px;
border-bottom: 2px solid transparent;
position: relative;
z-index: 1;
margin-bottom: -1px;
color: #666;
}


#tabs .active {
border-bottom-color: #f00;
color: #222;
}

.tab-container .content {
display: none;
}

/* 页面布局 */
.main {
padding: 30px 100px;
width: 960px;
margin: 0 auto;
}

.main .logo {
color: #333;
text-align: left;
margin-bottom: 30px;
line-height: 1;
height: 110px;
margin-top: -50px;
overflow: hidden;
*zoom: 1;
}

.main .logo a {
font-size: 160px;
color: #333;
}

.helps {
margin-top: 40px;
}

.helps pre {
padding: 20px;
margin: 10px 0;
border: solid 1px #e7e1cd;
background-color: #fffdef;
overflow: auto;
}

.icon_lists {
width: 100% !important;
overflow: hidden;
*zoom: 1;
}

.icon_lists li {
width: 100px;
margin-bottom: 10px;
margin-right: 20px;
text-align: center;
list-style: none !important;
cursor: default;
}

.icon_lists li .code-name {
line-height: 1.2;
}

.icon_lists .icon {
display: block;
height: 100px;
line-height: 100px;
font-size: 42px;
margin: 10px auto;
color: #333;
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
-moz-transition: font-size 0.25s linear, width 0.25s linear;
transition: font-size 0.25s linear, width 0.25s linear;
}

.icon_lists .icon:hover {
font-size: 100px;
}

.icon_lists .svg-icon {
/* 通过设置 font-size 来改变图标大小 */
width: 1em;
/* 图标和文字相邻时,垂直对齐 */
vertical-align: -0.15em;
/* 通过设置 color 来改变 SVG 的颜色/fill */
fill: currentColor;
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
normalize.css 中也包含这行 */
overflow: hidden;
}

.icon_lists li .name,
.icon_lists li .code-name {
color: #666;
}

/* markdown 样式 */
.markdown {
color: #666;
font-size: 14px;
line-height: 1.8;
}

.highlight {
line-height: 1.5;
}

.markdown img {
vertical-align: middle;
max-width: 100%;
}

.markdown h1 {
color: #404040;
font-weight: 500;
line-height: 40px;
margin-bottom: 24px;
}

.markdown h2,
.markdown h3,
.markdown h4,
.markdown h5,
.markdown h6 {
color: #404040;
margin: 1.6em 0 0.6em 0;
font-weight: 500;
clear: both;
}

.markdown h1 {
font-size: 28px;
}

.markdown h2 {
font-size: 22px;
}

.markdown h3 {
font-size: 16px;
}

.markdown h4 {
font-size: 14px;
}

.markdown h5 {
font-size: 12px;
}

.markdown h6 {
font-size: 12px;
}

.markdown hr {
height: 1px;
border: 0;
background: #e9e9e9;
margin: 16px 0;
clear: both;
}

.markdown p {
margin: 1em 0;
}

.markdown>p,
.markdown>blockquote,
.markdown>.highlight,
.markdown>ol,
.markdown>ul {
width: 80%;
}

.markdown ul>li {
list-style: circle;
}

.markdown>ul li,
.markdown blockquote ul>li {
margin-left: 20px;
padding-left: 4px;
}

.markdown>ul li p,
.markdown>ol li p {
margin: 0.6em 0;
}

.markdown ol>li {
list-style: decimal;
}

.markdown>ol li,
.markdown blockquote ol>li {
margin-left: 20px;
padding-left: 4px;
}

.markdown code {
margin: 0 3px;
padding: 0 5px;
background: #eee;
border-radius: 3px;
}

.markdown strong,
.markdown b {
font-weight: 600;
}

.markdown>table {
border-collapse: collapse;
border-spacing: 0px;
empty-cells: show;
border: 1px solid #e9e9e9;
width: 95%;
margin-bottom: 24px;
}

.markdown>table th {
white-space: nowrap;
color: #333;
font-weight: 600;
}

.markdown>table th,
.markdown>table td {
border: 1px solid #e9e9e9;
padding: 8px 16px;
text-align: left;
}

.markdown>table th {
background: #F7F7F7;
}

.markdown blockquote {
font-size: 90%;
color: #999;
border-left: 4px solid #e9e9e9;
padding-left: 0.8em;
margin: 1em 0;
}

.markdown blockquote p {
margin: 0;
}

.markdown .anchor {
opacity: 0;
transition: opacity 0.3s ease;
margin-left: 8px;
}

.markdown .waiting {
color: #ccc;
}

.markdown h1:hover .anchor,
.markdown h2:hover .anchor,
.markdown h3:hover .anchor,
.markdown h4:hover .anchor,
.markdown h5:hover .anchor,
.markdown h6:hover .anchor {
opacity: 1;
display: inline-block;
}

.markdown>br,
.markdown>p>br {
clear: both;
}


.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}

.hljs-comment,
.hljs-meta {
color: #969896;
}

.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}

.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}

.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}

.hljs-section,
.hljs-name {
color: #63a35c;
}

.hljs-tag {
color: #333333;
}

.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr,
.hljs-selector-pseudo {
color: #795da3;
}

.hljs-addition {
color: #55a532;
background-color: #eaffea;
}

.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}

.hljs-link {
text-decoration: underline;
}

/* 代码高亮 */
/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;

-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;

-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}

pre[class*="language-"]::-moz-selection,
pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection,
code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}

pre[class*="language-"]::selection,
pre[class*="language-"] ::selection,
code[class*="language-"]::selection,
code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}

@media print {

code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}

/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}

:not(pre)>code[class*="language-"],
pre[class*="language-"] {
background: #f5f2f0;
}

/* Inline code */
:not(pre)>code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}

.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}

.token.punctuation {
color: #999;
}

.namespace {
opacity: .7;
}

.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}

.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}

.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
background: hsla(0, 0%, 100%, .5);
}

.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}

.token.function,
.token.class-name {
color: #DD4A68;
}

.token.regex,
.token.important,
.token.variable {
color: #e90;
}

.token.important,
.token.bold {
font-weight: bold;
}

.token.italic {
font-style: italic;
}

.token.entity {
cursor: help;
}

+ 27651
- 0
public/iconfonts1/demo_index.html
File diff suppressed because it is too large
View File


BIN
public/iconfonts1/devopicons.e19892d.woff2 View File


BIN
public/iconfonts1/file-icons.woff2 View File


BIN
public/iconfonts1/fontawesome.af7ae50.woff2 View File


+ 4792
- 0
public/iconfonts1/iconfont.css
File diff suppressed because it is too large
View File


+ 1
- 0
public/iconfonts1/iconfont.js
File diff suppressed because it is too large
View File


+ 8367
- 0
public/iconfonts1/iconfont.json
File diff suppressed because it is too large
View File


+ 2407
- 0
public/iconfonts1/iconfont.svg
File diff suppressed because it is too large
View File


BIN
public/iconfonts1/iconfont.ttf View File


BIN
public/iconfonts1/iconfont.woff View File


BIN
public/iconfonts1/iconfont.woff2 View File


BIN
public/iconfonts1/mfixx.0a32a80.woff2 View File


BIN
public/iconfonts1/octicons.de59a97.woff2 View File


BIN
public/images/abandon.png View File

Before After
Width: 28  |  Height: 28  |  Size: 801 B

BIN
public/images/bronze.png View File

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

BIN
public/images/code1.png View File

Before After
Width: 44  |  Height: 48  |  Size: 1.1 kB

BIN
public/images/code2.png View File

Before After
Width: 44  |  Height: 48  |  Size: 994 B

BIN
public/images/codeFloder.png View File

Before After
Width: 28  |  Height: 32  |  Size: 717 B

BIN
public/images/drag.png View File

Before After
Width: 44  |  Height: 20  |  Size: 567 B

BIN
public/images/gold.png View File

Before After
Width: 64  |  Height: 64  |  Size: 3.6 kB

BIN
public/images/silver.png View File

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

BIN
public/images/submit.png View File

Before After
Width: 28  |  Height: 32  |  Size: 542 B

BIN
public/images/submitLog1.png View File

Before After
Width: 48  |  Height: 48  |  Size: 1.2 kB

BIN
public/images/submitLog2.png View File

Before After
Width: 48  |  Height: 48  |  Size: 1.1 kB

BIN
public/images/warehouse.png View File

Before After
Width: 28  |  Height: 32  |  Size: 608 B

BIN
public/img/empty.png View File

Before After
Width: 360  |  Height: 313  |  Size: 25 kB

+ 4
- 0
routers/api/v1/api.go View File

@@ -963,9 +963,13 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("/blobs/:sha", context.RepoRef(), repo.GetBlob)
m.Get("/tags/:sha", context.RepoRef(), repo.GetTag)
}, reqRepoReader(models.UnitTypeCode))
m.Group("/git", func() {
m.Get("/codes/:sha", repo.GetCodes)
}, reqRepoWriter(models.UnitTypeCode))
m.Group("/contents", func() {
m.Get("", repo.GetContentsList)
m.Get("/*", repo.GetContents)
m.Post("/commit", bind(api.CommitMultiFileOptions{}), repo.CommitFiles)
m.Group("/*", func() {
m.Post("", bind(api.CreateFileOptions{}), repo.CreateFile)
m.Put("", bind(api.UpdateFileOptions{}), repo.UpdateFile)


+ 152
- 0
routers/api/v1/repo/file.go View File

@@ -440,6 +440,158 @@ func DeleteFile(ctx *context.APIContext, apiOpts api.DeleteFileOptions) {
}
}

// CommitFiles commit a fle in a repository
func CommitFiles(ctx *context.APIContext, commitMultiFileOptions api.CommitMultiFileOptions) {
apiOpts := commitMultiFileOptions.Files
for _, apiOpt := range apiOpts {
switch apiOpt.Operation {
case "add":
if apiOpt.BranchName == "" {
apiOpt.BranchName = ctx.Repo.Repository.DefaultBranch
}

opts := &repofiles.UpdateRepoFileOptions{
Content: apiOpt.Content,
IsNewFile: true,
Message: apiOpt.Message,
TreePath: apiOpt.FilePath,
OldBranch: apiOpt.BranchName,
NewBranch: apiOpt.NewBranchName,
Committer: &repofiles.IdentityOptions{
Name: apiOpt.Committer.Name,
Email: apiOpt.Committer.Email,
},
Author: &repofiles.IdentityOptions{
Name: apiOpt.Author.Name,
Email: apiOpt.Author.Email,
},
Dates: &repofiles.CommitDateOptions{
Author: apiOpt.Dates.Author,
Committer: apiOpt.Dates.Committer,
},
}
if opts.Dates.Author.IsZero() {
opts.Dates.Author = time.Now()
}
if opts.Dates.Committer.IsZero() {
opts.Dates.Committer = time.Now()
}

if opts.Message == "" {
opts.Message = commitMultiFileOptions.Msg
}

if _, err := createOrUpdateFile(ctx, opts); err != nil {
ctx.Error(http.StatusInternalServerError, "CreateFile", err)
}
case "update":
if apiOpt.BranchName == "" {
apiOpt.BranchName = ctx.Repo.Repository.DefaultBranch
}

opts := &repofiles.UpdateRepoFileOptions{
Content: apiOpt.Content,
SHA: apiOpt.SHA,
IsNewFile: false,
Message: apiOpt.Message,
FromTreePath: apiOpt.FromPath,
TreePath: apiOpt.FilePath,
OldBranch: apiOpt.BranchName,
NewBranch: apiOpt.NewBranchName,
Committer: &repofiles.IdentityOptions{
Name: apiOpt.Committer.Name,
Email: apiOpt.Committer.Email,
},
Author: &repofiles.IdentityOptions{
Name: apiOpt.Author.Name,
Email: apiOpt.Author.Email,
},
Dates: &repofiles.CommitDateOptions{
Author: apiOpt.Dates.Author,
Committer: apiOpt.Dates.Committer,
},
}
if opts.Dates.Author.IsZero() {
opts.Dates.Author = time.Now()
}
if opts.Dates.Committer.IsZero() {
opts.Dates.Committer = time.Now()
}

if opts.Message == "" {
opts.Message = commitMultiFileOptions.Msg
}

if _, err := createOrUpdateFile(ctx, opts); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateFile", err)
}
case "delete":
if !canWriteFiles(ctx.Repo) {
ctx.Error(http.StatusForbidden, "DeleteFile", models.ErrUserDoesNotHaveAccessToRepo{
UserID: ctx.User.ID,
RepoName: ctx.Repo.Repository.LowerName,
})
return
}

if apiOpt.BranchName == "" {
apiOpt.BranchName = ctx.Repo.Repository.DefaultBranch
}

opts := &repofiles.DeleteRepoFileOptions{
Message: apiOpt.Message,
OldBranch: apiOpt.BranchName,
NewBranch: apiOpt.NewBranchName,
SHA: apiOpt.SHA,
TreePath: apiOpt.FilePath,
Committer: &repofiles.IdentityOptions{
Name: apiOpt.Committer.Name,
Email: apiOpt.Committer.Email,
},
Author: &repofiles.IdentityOptions{
Name: apiOpt.Author.Name,
Email: apiOpt.Author.Email,
},
Dates: &repofiles.CommitDateOptions{
Author: apiOpt.Dates.Author,
Committer: apiOpt.Dates.Committer,
},
}
if opts.Dates.Author.IsZero() {
opts.Dates.Author = time.Now()
}
if opts.Dates.Committer.IsZero() {
opts.Dates.Committer = time.Now()
}

if opts.Message == "" {
opts.Message = commitMultiFileOptions.Msg
}

if _, err := repofiles.DeleteRepoFile(ctx.Repo.Repository, ctx.User, opts); err != nil {
if git.IsErrBranchNotExist(err) || models.IsErrRepoFileDoesNotExist(err) || git.IsErrNotExist(err) {
ctx.Error(http.StatusNotFound, "DeleteFile", err)
return
} else if models.IsErrBranchAlreadyExists(err) ||
models.IsErrFilenameInvalid(err) ||
models.IsErrSHADoesNotMatch(err) ||
models.IsErrCommitIDDoesNotMatch(err) ||
models.IsErrSHAOrCommitIDNotProvided(err) {
ctx.Error(http.StatusBadRequest, "DeleteFile", err)
return
} else if models.IsErrUserCannotCommit(err) {
ctx.Error(http.StatusForbidden, "DeleteFile", err)
return
}
ctx.Error(http.StatusInternalServerError, "DeleteFile", err)
}
}
}

ctx.JSON(http.StatusOK, struct{ msg string }{"success"})

}

// GetContents Get the metadata and contents (if a file) of an entry in a repository, or a list of entries if a dir
func GetContents(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/contents/{filepath} repository repoGetContents


+ 100
- 0
routers/api/v1/repo/tree.go View File

@@ -5,7 +5,10 @@
package repo

import (
api "code.gitea.io/gitea/modules/structs"
"net/http"
"regexp"
"strings"

"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/repofiles"
@@ -66,3 +69,100 @@ func GetTree(ctx *context.APIContext) {
ctx.JSON(http.StatusOK, tree)
}
}

// GetTree get the tree of a repository.
func GetCodes(ctx *context.APIContext) {
// swagger:operation GET /repos/{owner}/{repo}/git/codes/{sha} repository GetTree
// ---
// summary: Gets the tree of a repository.
// produces:
// - application/json
// parameters:
// - name: owner
// in: path
// description: owner of the repo
// type: string
// required: true
// - name: repo
// in: path
// description: name of the repo
// type: string
// required: true
// - name: sha
// in: path
// description: sha of the commit
// type: string
// required: true
// - name: recursive
// in: query
// description: show all directories and files
// required: false
// type: boolean
// - name: page
// in: query
// description: page number; the 'truncated' field in the response will be true if there are still more items after this page, false if the last page
// required: false
// type: integer
// - name: per_page
// in: query
// description: number of items per page; default is 1000 or what is set in app.ini as DEFAULT_GIT_TREES_PER_PAGE
// required: false
// type: integer
// responses:
// "200":
// "$ref": "#/responses/GitTreeResponse"
// "400":
// "$ref": "#/responses/error"
var sha = "HEAD"
if ctx.Query("sha") != "" {
sha = ctx.Query("sha")
}
if tree, err := repofiles.GetTreeBySHA(ctx.Repo.Repository, sha, ctx.QueryInt("page"), ctx.QueryInt("per_page"), true); err != nil {
ctx.Error(http.StatusBadRequest, "", err.Error())
} else {
// 第一步,反序
var entries = tree.Entries
entriesWithChildren := make([]api.GitEntryWithChildren, len(entries))
slashRegex := regexp.MustCompile(`.*/`)
for i, j := len(entries)-1, 0; i >= 0; i-- {
entriesWithChildren[j].Children = make([]api.GitEntryWithChildren, 0)
entriesWithChildren[j].GitEntry = entries[i]
entriesWithChildren[j].Name = slashRegex.ReplaceAllString(entriesWithChildren[j].Path, "")
tempList := strings.Split(entriesWithChildren[j].Name, ".")
if len(tempList) > 1 {
entriesWithChildren[j].Suffix = tempList[len(tempList)-1]
} else {
entriesWithChildren[j].Suffix = ""
}
j++
}

// 第二步,对包含分隔符的节点,向前寻找路径等于当前路径去除当前文件名的节点,挂到其children下
for i := 0; i < len(entriesWithChildren); i++ {
if strings.Contains(entriesWithChildren[i].Path, "/") {
parentPath := entriesWithChildren[i].Path[0:strings.LastIndex(entriesWithChildren[i].Path, "/")]
for j := i; j < len(entriesWithChildren); j++ {
if entriesWithChildren[j].Path == parentPath && entriesWithChildren[j].Type == "tree" {
entriesWithChildren[j].Children = append(entriesWithChildren[j].Children, entriesWithChildren[i])
}
}
}
}

// 第三步,找到第一层的节点,返回
var treeWithChildren = new(api.GitTreeWithChildrenResponse)
entriesWithChildrenForResponse := make([]api.GitEntryWithChildren, 0)
for i := len(entriesWithChildren) - 1; i >= 0; i-- {
if !strings.Contains(entriesWithChildren[i].Path, "/") {
entriesWithChildrenForResponse = append(entriesWithChildrenForResponse, entriesWithChildren[i])
}
}

treeWithChildren.Entries = entriesWithChildrenForResponse
treeWithChildren.URL = tree.URL
treeWithChildren.SHA = tree.SHA
treeWithChildren.TotalCount = tree.TotalCount

ctx.JSON(http.StatusOK, treeWithChildren)
}
}

+ 220
- 0
routers/api/v1/utils/utils.go View File

@@ -46,3 +46,223 @@ func GetListOptions(ctx *context.APIContext) models.ListOptions {
PageSize: convert.ToCorrectPageSize(ctx.QueryInt("limit")),
}
}

// JudgeLanguageBySuffix get language from fileName
func JudgeLanguageBySuffix(filename string) string {
if len(filename) == 0 {
return "shell"
}
arr := strings.Split(filename, ".")
suffix := strings.ToLower(arr[len(arr)-1])
suffixLanguageMap := map[string]string{
"py": "python",
"c": "cpp",
"h": "cpp",
"g4": "cpp",
"sy": "cpp",
"cc": "cpp",
"cxx": "cpp",
"c++": "cpp",
"cu": "cpp",
"cpp": "cpp",
"dynamips": "cpp",
"java": "java",
"php": "php",
"html": "html",
"css": "css",
"scss": "scss",
"go": "go",
"r": "r",
"graphql": "graphql",
"swift": "swift",
"xml": "xml",
"yaml": "yaml",
"json": "json",
"lua": "lua",
"scheme": "scheme",
"less": "less",
"ini": "ini",
"jpg": "jpg",
"jpeg": "jpeg",
"png": "png",
"gif": "gif",
"webp": "webp",
"bmp": "bmp",
"avi": "avi",
"mp4": "mp4",
"mov": "mov",
"mp3": "mp3",
"wav": "wav",
"ogg": "ogg",
"coffee": "coffeescript",
"litcoffee": "coffeescript",
"js": "javascript",
"vue": "javascript",
"ejs": "html",
"cs": "csharp",
"kt": "kotlin",
"md": "markdown",
"sql": "mysql",
"ctrl": "mysql",
"m": "objective-c",
"mm": "objective-c",
"pas": "pascal",
"perl": "perl",
"pl": "perl",
"rb": "ruby",
"rs": "rust", "rust": "rust",
"tsx": "typescript",
"ipynb": "json",
"sh": "shell",
"bash": "shell",
}

if suffixLanguageMap[suffix] == "" {
return "shell"
} else {
return suffixLanguageMap[suffix]
}

}

// JudgeFileTypeBySuffix get language from fileName
func JudgeFileTypeBySuffix(filename string) string {
if len(filename) == 0 {
return "other"
}
arr := strings.Split(filename, ".")
suffix := strings.ToLower(arr[len(arr)-1])
suffixFileTypeMap := map[string]string{
"py": "txt",
"h": "txt",
"c": "txt",
"cpp": "txt",
"cc": "txt",
"java": "txt",
"php": "txt",
"html": "txt",
"css": "txt",
"scss": "txt",
"go": "txt",
"r": "txt",
"graphql": "txt",
"swift": "txt",
"xml": "txt",
"yaml": "txt",
"json": "txt",
"lua": "txt",
"scheme": "txt",
"less": "txt",
"ini": "txt",
"coffee": "txt",
"litcoffee": "txt",
"js": "txt",
"cs": "txt",
"kt": "txt",
"md": "txt",
"sql": "txt",
"m": "txt",
"mm": "txt",
"pas": "txt",
"perl": "txt",
"ejs": "txt",
"pl": "txt",
"rb": "txt",
"rs": "txt",
"rust": "txt",
"sh": "txt",
"makefile": "txt",
"circ": "txt",
"readme": "txt",
"yml": "txt",
"sml": "txt",
"conf": "txt",
"txt": "txt",
"gitignore": "txt",
"in": "txt",
"cu": "txt",
"gemfile": "txt",
"scala": "txt",
"net": "txt",
"l": "txt",
"v": "txt",
"config": "txt",
"properties": "txt",
"log": "txt",
"htm": "txt",
"cnf": "txt",
"hex": "txt",
"bat": "txt",
"asm": "txt",
"bash": "txt",
"ts": "txt",
"tsx": "txt",
"sass": "txt",
"jsx": "txt",
"jsp": "txt",
"gitkeep": "txt",
"sv": "txt",
"hql": "txt",
"y": "txt",
"jj": "txt",
"pls": "txt",
"sol": "txt",
"ignore": "txt",
"ctrl": "txt",
"vue": "txt",
"tex": "txt",
"bib": "txt",
"cls": "txt",
"bst": "txt",
"toc": "txt",
"sty": "txt",
"g4": "txt",
"sy": "txt",
"jpg": "image",
"jpeg": "image",
"png": "image",
"gif": "image",
"webp": "image",
"bmp": "image",
"avi": "video",
"mp4": "video",
"mov": "video",
"mp3": "audio",
"wav": "audio",
"ogg": "audio",
"pptm": "office",
"pptx": "office",
"ppt": "office",
"pot": "office",
"pps": "office",
"ppa": "office",
"potx": "office",
"ppsx": "office",
"ppam": "office",
"potm": "office",
"ppsm": "office",
"doc": "office",
"docx": "office",
"dot": "office",
"dotx": "office",
"docm": "office",
"dotm": "office",
"xls": "office",
"xlsx": "office",
"csv": "office",
"xlt": "office",
"xla": "office",
"xltx": "office",
"xlsm": "office",
"xltm": "office",
"xlam": "office",
"xlsb": "office",
"pdf": "pdf",
"ipynb": "ipynb",
}
if suffixFileTypeMap[suffix] == "" {
return "other"
} else {
return suffixFileTypeMap[suffix]
}
}

+ 13
- 0
routers/home.go View File

@@ -11,6 +11,7 @@ import (
"net/http"
"strconv"
"strings"
"time"

"code.gitea.io/gitea/services/repository"

@@ -40,6 +41,7 @@ const (
tplExploreCode base.TplName = "explore/code"
tplExploreImages base.TplName = "explore/images"
tplExploreExploreDataAnalysis base.TplName = "explore/data_analysis"
tplIde base.TplName = "explore/ide"
tplHomeTerm base.TplName = "terms"
tplHomePrivacy base.TplName = "privacy"
tplResoruceDesc base.TplName = "resource_desc"
@@ -653,6 +655,17 @@ func ExploreDataAnalysisProAnalysis(ctx *context.Context) {
ctx.Data["url_params"] = "ProAnalysis"
ctx.HTML(200, tplExploreExploreDataAnalysis)
}

func IdeProject(ctx *context.Context) {
ctx.Data["url_params"] = time.Now().Unix()
// Check auto-login.
uname := ctx.GetCookie(setting.CookieUserName)
if len(uname) != 0 {
ctx.Redirect(setting.AppSubURL + "/user/login")
return
}
ctx.HTML(200, tplIde)
}
func ExploreDataAnalysisOverview(ctx *context.Context) {
ctx.Data["url_params"] = "Overview"
ctx.HTML(200, tplExploreExploreDataAnalysis)


+ 11
- 0
routers/routes/routes.go View File

@@ -779,6 +779,17 @@ func RegisterRoutes(m *macaron.Macaron) {
//reqRepoBlockChainReader := context.RequireRepoReader(models.UnitTypeBlockChain)
//reqRepoBlockChainWriter := context.RequireRepoWriter(models.UnitTypeBlockChain)

m.Group("/ide", func() {
m.Get("", func(ctx *context.Context) {
ctx.Redirect(setting.AppSubURL + "/project")
})
m.Get("/project", routers.IdeProject)

}, reqSignIn, func(ctx *context.Context) {
ctx.Data["PageIsUserSettings"] = true
ctx.Data["AllThemes"] = setting.UI.Themes
})

// ***** START: Organization *****
m.Group("/org", func() {
m.Group("/:org", func() {


+ 21
- 9
templates/base/footer_fluid.tmpl View File

@@ -3,15 +3,15 @@
<body>
<div>
*/}}
{{template "custom/body_inner_post" .}}
</div>
{{template "custom/body_outer_post" .}}
{{template "base/footer_content_fluid" .}}
<script src="{{StaticUrlPrefix}}/js/jquery.js?v={{MD5 AppVer}}"></script>
{{if .RequireSimpleMDE}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js"></script>
@@ -21,7 +21,20 @@
CodeMirror.modeURL = "{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/%N/%N.js";
</script>
{{end}}

{{if .RequireSimpleMDE}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/simplemde/simplemde.min.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/addon/mode/loadmode.js"></script>
<script src="{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/meta.js"></script>
<script>
CodeMirror.modeURL = "{{StaticUrlPrefix}}/vendor/plugins/codemirror/mode/%N/%N.js";
</script>
{{end}}





<!-- Third-party libraries -->
{{if .RequireMinicolors}}
<script src="{{StaticUrlPrefix}}/vendor/plugins/jquery.minicolors/jquery.minicolors.min.js"></script>
@@ -40,9 +53,8 @@
{{if .PageIsHome}}
<script rel="stylesheet" src="{{StaticUrlPrefix}}/vendor/plugins/jquery.particleground/jquery.particleground.min.js"></script>
{{end}}
<script src="{{StaticUrlPrefix}}/fomantic/semantic.min.js?v={{MD5 AppVer}}"></script>
<script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}"></script>
<script src="{{StaticUrlPrefix}}/fomantic/semantic.min.js?v={{MD5 AppVer}}{{.url_params}}"></script>
<script src="{{StaticUrlPrefix}}/js/index.js?v={{MD5 AppVer}}{{.url_params}}"></script>
{{template "custom/footer" .}}
</body>
</html>

+ 6
- 6
templates/base/head.tmpl View File

@@ -113,7 +113,7 @@
window.sessionStorage.setItem('_csrf', '{{.CsrfToken}}');
{{else}}
window.sessionStorage.removeItem('_csrf');
{{end}}
{{end}}
</script>
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg" color="#609926">
@@ -129,7 +129,7 @@
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css">
{{end}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}{{.url_params}}">
<noscript>
<style>
.dropdown:hover > .menu { display: block; }
@@ -187,7 +187,7 @@ var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?46149a0b61fdeddfe427ff4de63794ba";
var s = document.getElementsByTagName("script")[0];
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
@@ -200,7 +200,7 @@ var _hmt = _hmt || [];
<noscript>{{.i18n.Tr "enable_javascript"}}</noscript>

{{template "custom/body_inner_pre" .}}
{{if not .PageIsInstall}}
<div class="ui top secondary stackable main menu following bar dark">
{{template "base/head_navbar" .}}
@@ -214,7 +214,7 @@ var _hmt = _hmt || [];
*/}}

<script>
function closeNoice(){
document.getElementById("notic_content").style.display='none'
localStorage.setItem("isCloseNotice",true)
@@ -258,7 +258,7 @@ var _hmt = _hmt || [];
}
}
}
if(!("{{.IsCourse}}" == true || "{{.IsCourse}}" =='true')) {
isShowNotice();
}


+ 4
- 4
templates/base/head_course.tmpl View File

@@ -113,7 +113,7 @@
window.sessionStorage.setItem('_csrf', '{{.CsrfToken}}');
{{else}}
window.sessionStorage.removeItem('_csrf');
{{end}}
{{end}}
</script>
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg" color="#609926">
@@ -129,7 +129,7 @@
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css">
{{end}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}{{.url_params}}">
<noscript>
<style>
.dropdown:hover > .menu { display: block; }
@@ -187,7 +187,7 @@ var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?46149a0b61fdeddfe427ff4de63794ba";
var s = document.getElementsByTagName("script")[0];
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
@@ -200,7 +200,7 @@ var _hmt = _hmt || [];
<noscript>{{.i18n.Tr "enable_javascript"}}</noscript>

{{template "custom/body_inner_pre" .}}
{{if not .PageIsInstall}}
<div class="ui top secondary stackable main menu following bar dark">
{{template "base/head_navbar" .}}


+ 6
- 6
templates/base/head_fluid.tmpl View File

@@ -113,7 +113,7 @@
window.sessionStorage.setItem('_csrf', '{{.CsrfToken}}');
{{else}}
window.sessionStorage.removeItem('_csrf');
{{end}}
{{end}}
</script>
<link rel="shortcut icon" href="{{StaticUrlPrefix}}/img/favicon.png">
<link rel="mask-icon" href="{{StaticUrlPrefix}}/img/openi-safari.svg" color="#609926">
@@ -129,7 +129,7 @@
<link rel="stylesheet" href="{{StaticUrlPrefix}}/vendor/plugins/tribute/tribute.css">
{{end}}
<link rel="stylesheet" href="{{StaticUrlPrefix}}/fomantic/semantic.min.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}">
<link rel="stylesheet" href="{{StaticUrlPrefix}}/css/index.css?v={{MD5 AppVer}}{{.url_params}}">
<noscript>
<style>
.dropdown:hover > .menu { display: block; }
@@ -187,7 +187,7 @@ var _hmt = _hmt || [];
(function() {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?46149a0b61fdeddfe427ff4de63794ba";
var s = document.getElementsByTagName("script")[0];
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
@@ -215,7 +215,7 @@ var _hmt = _hmt || [];
*/}}

<script>
function closeNoice(){
document.getElementById("notic_content").style.display='none'
localStorage.setItem("isCloseNotice",true)
@@ -258,8 +258,8 @@ var _hmt = _hmt || [];
}
}
}
if(!("{{.IsCourse}}" == true || "{{.IsCourse}}" =='true')) {
isShowNotice();
}
</script>
</script>

+ 23
- 0
templates/explore/ide.tmpl View File

@@ -0,0 +1,23 @@
<div style="display:none;">
{{template "base/head_fluid" .}}
{{template "base/footer_fluid" .}}
</div>
<input id="url_params" type="hidden" value={{.url_params}}/>
<div id="initVueIde" style="height: 100%;">
</div>

<!-- <script>
localStorage.setItem("dataAnalysisURL","{{.url_params}}")
</script> -->
<style>
.full.height {
display: flex;
flex-flow: column wrap;
padding-bottom:0px;
/* flex-grow: 1; */
/* padding-bottom: 53px; */
}

</style>

+ 6
- 3
templates/repo/home.tmpl View File

@@ -205,7 +205,7 @@
class="section"><a href="{{EscapePound $.BranchLink}}/{{EscapePound $p}}"
title="{{$v}}">{{EllipsisString $v 30}}</a></span>{{end}}{{end}}</span></div>
{{end}}
<div class="right fitted item" id="file-buttons">
<div class="ui tiny blue buttons">
{{if .Repository.CanEnableEditor}}
@@ -245,6 +245,9 @@
<!-- Only show clone panel in repository home page -->
{{if eq $n 0}}
<div class="ui action tiny input" id="clone-panel">
<div class="ui basic floating button" style="margin-right:10px">
<div class="text"><a href="/ide/project?type=ide&owner={{.Owner.Name}}&project={{.Repository.Name}}&git={{.CloneLink.HTTPS}}" target="_blank">Web IDE</a></div>
</div>
{{if not $.DisableHTTP}}
<button class="ui basic clone button" id="repo-clone-https" data-link="{{.CloneLink.HTTPS}}">
{{if UseHTTPS}}HTTPS{{else}}HTTP{{end}}
@@ -394,7 +397,7 @@
</div>
{{if and (.IsViewFile) (IpynbBool .TreePath)}}
<div id="__vue-root"></div>
<div id="__vue-self-data" data-branch="{{.BranchName}}" data-owner="{{.Repository.OwnerName}}" data-name="{{.SignedUser.Name}}" data-project="{{.Repository.Name}}"
<div id="__vue-self-data" data-branch="{{.BranchName}}" data-owner="{{.Repository.OwnerName}}" data-name="{{.SignedUser.Name}}" data-project="{{.Repository.Name}}"
data-file="{{.TreePath}}">
</div>
{{end}}
@@ -402,4 +405,4 @@
{{if and (.IsViewFile) (IpynbBool .TreePath)}}
<script src="{{StaticUrlPrefix}}/js/vp-notebook-debug.js?v={{MD5 AppVer}}"></script>
{{end}}
{{template "base/footer" .}}
{{template "base/footer" .}}

+ 20
- 8
web_src/js/components/Contributors.vue View File

@@ -14,15 +14,19 @@
<a v-else :href="'mailto:' + contributor.email "><img class="ui avatar s16 image js-popover-card" :avatar="contributor.email"></a>
<div class="content">
<div class="header" >
<a v-if="contributor.user_name" :href="AppSubUrl +'/'+ contributor.user_name">{{contributor.user_name}}</a>
<a v-else :href="'mailto:' + contributor.email ">{{contributor.email}}</a>
<a class="username" v-if="contributor.user_name" :href="AppSubUrl +'/'+ contributor.user_name">
<img src="/images/gold.png" width="24" v-show="contributor.commit_cnt > 1000"/>
<img src="/images/silver.png" width="24" v-show="contributor.commit_cnt > 500 && contributor.commit_cnt < 1000"/>
<img src="/images/bronze.png" width="24" v-show="contributor.commit_cnt > 50 && contributor.commit_cnt < 500"/>
{{contributor.user_name}}</a>
<a v-else :href="'mailto:' + contributor.email ">{{contributor.email}}</a>
</div>
<span class="commit-btn">Commits: {{contributor.commit_cnt}}</span>
</div>
</div>
</div>
</div>
<div class="ui container" style="margin-top:50px;text-align:center">
<el-pagination
background
@@ -36,12 +40,20 @@
</div>
</template>

<style>
.username{
display: flex;
align-items: center;
img{
margin-right: 10px;
}
}</style>
<script>

const {AppSubUrl, StaticUrlPrefix, csrf} = window.config;

export default {
data() {
return {
url:'',
@@ -67,10 +79,10 @@ methods: {
handleCurrentChange(val){
this.contributors_list_page = this.contributors_list.slice((val-1)*this.pageSize,val*this.pageSize)
},
},
computed:{
},
watch: {

@@ -80,12 +92,12 @@ created(){
this.url = url;
let strIndex = this.url.indexOf("contributors")
this.url_code = this.url.substr(0,strIndex)
this.href_ = window.location.href;
let index = this.href_.indexOf("?")
this.url_infor = this.href_.substring(index+1,this.href_.length)
this.getContributorsList()
},

updated(){


+ 0
- 0
web_src/js/components/IdeProject.vue View File


+ 0
- 0
web_src/js/components/VueTreeList.vue View File


+ 299
- 0
web_src/js/components/db.js View File

@@ -0,0 +1,299 @@
let db;
let openRequest;
const indexedDB =
window.indexedDB ||
window.webkitIndexedDb ||
window.mozIndexed ||
window.msIndexedDB;

// transaction 事务处理 意味着一系列操作步骤之中,只要有一步失败,整个事务就都取消,数据库回滚到事务发生之前的状态,不存在只改写一部分数据的情况。

// tableList [{tableName,keyPath,indexName}]
/**
* 初始化数据库
* @param {string} dbName 数据库名
* @param {Array} tableList 数据表列表
*/

// 初始化
export function init({ dbName, tableList }) {
// 存在就打开 不存在新建 第二个参数为db 版本
openRequest = indexedDB.open(dbName);
// 新的数据库创建 或者数据库的版本号被更改会被触发
openRequest.onupgradeneeded = function (e) {
// 表的创建在这个回调里执行
const thisDb = e.target.result;
console.log('running onupgradeneeded' + thisDb);
if (tableList?.length) {
tableList.forEach((table) => {
if (!thisDb.objectStoreNames.contains(table.tableName)) {
console.log('I need to create the objectStore');
// keyPath 主键 autoIncrement 是否自增
const objectStore = thisDb.createObjectStore(table.tableName, {
keyPath: table.keyPath,
...table.attr,
// autoIncrement: true,
});
if (table.indexName) {
// 创建表的时候 可以去指定那些字段是可以被索引的字段
objectStore.createIndex(table.indexName, table.indexName, {
unique: table.unique || false,
});
}
}
});
} else {
console.error('请传入数据表参数');
}
};
// 已经创建好的数据库创建成功的时候
openRequest.onsuccess = function (e) {
db = e.target.result;
window.db = e.target.result;
db.onerror = function (event) {
console.error('Database error: ' + event.target.errorCode);
console.dir(event.target);
};
};
// 打开失败时调用
openRequest.onerror = function (e) {
console.error('openRequest.onerror', e);
};
}

/**
* 添加一行
* @param {string} tableName 表名
* @param {object} data 数据
* @returns {promise}
*/
export function add({ tableName, data }) {
console.log("add:",tableName,data)
return new Promise((suc, fail) => {
const request = window.db
.transaction([tableName], 'readwrite')
.objectStore(tableName)
.add(data);

request.onsuccess = function (event) {
suc();
console.log('数据写入成功', event);
};

request.onerror = function (event) {
// fail();
update({tableName, data })
console.log('数据写入失败', event);
};
});
}

/**
* 遍历所有数据 其实这里有点坑 真正readAll是下面readAllPC这个方法,因为低版本webview手机不兼容objectStore.getAll所以使用游标来实现
* @param {string} tableName 表名
* @returns {promise}
*/
export function readAll(tableName) {
return new Promise((suc, fail) => {
const objectStore = db
.transaction([tableName], 'readwrite')
.objectStore(tableName);
// 我这里做的是把所有的结果全部收集起来 当然我们可以做其他事情此处拿到的value是每条数据的结果、还有primaryKey主键、key、与direction
const result = [];
objectStore.openCursor().onsuccess = function (event) {
const cursor = event.target.result;
if (cursor) {
result.push({ ...cursor.value });
cursor.continue();
} else {
suc(result);
console.log('readAll成功==>' , result);
}
};
objectStore.openCursor().onerror = function (event) {
console.dir(event);
fail();
};
});
}

/**
* 读取所有数据 仅在pc上或者版本高的手机浏览器中使用 readAllPC这个方法 这个在低版本weview的手机浏览器里面不兼容
* @param {string} tableName
* @returns {promise}
*/
export function readAllForHighVersion(tableName) {
return new Promise((suc, fail) => {
const objectStore = db
.transaction([tableName], 'readwrite')
.objectStore(tableName);
const request = objectStore.getAll();

request.onerror = function (event) {
fail();
console.log('readAll--->读取表事务失败', event);
};

request.onsuccess = function () {
suc(request.result || []);
};
});
}

/**
* 根据主键查询对应数据
* @param {string} tableName 表名
* @param {string} key 主键
* @returns {promise}
*/
export function readByMainKey({ tableName, key }) {
return new Promise((suc, fail) => {
if (!key) {
fail();
return;
}
const objectStore = db
.transaction([tableName], 'readwrite')
.objectStore(tableName);
const request = objectStore.get(key);

request.onerror = function (event) {
console.error('根据主键查询对应数据', event);
fail();
};

request.onsuccess = function () {
suc(request.result || {});
};
});
}

/**
* 根据主键删除对应数据
* @param {string} tableName 表名
* @param {string} key 主键
* @returns {promise}
*/
export function remove({ tableName, key }) {
return new Promise((suc, fail) => {
const objectStore = db
.transaction([tableName], 'readwrite')
.objectStore(tableName);
const request = objectStore.delete(key);

request.onerror = function (event) {
console.error('更新失败', event);
fail();
};

request.onsuccess = function (event) {
console.log('删除成功', event);
suc();
};
});
}

/**
* 根据主键更新对应数据
* @param {object} data 对应的主键与值 和 数据
* @param {string} tableName 表名
* @returns {promise}
*/
export function update({ tableName, data }) {
return new Promise((suc, fail) => {
const objectStore = db
.transaction([tableName], 'readwrite')
.objectStore(tableName);
const request = objectStore.put(data);

request.onerror = function (event) {
console.error('更新失败', event);
fail();
};

request.onsuccess = function (event) {
console.log('更新成功', event);
suc();
};
});
}

/**
* 通过索引查找对应数据
* @param {string} indexName 索引名称
* @param {any} indexVal index 索引值
* @param {string} tableName 表名
* @returns {promise}
*/
export function readByIndex({ tableName, indexName, indexVal }) {
return new Promise((suc, fail) => {
const objectStore = db
.transaction([tableName], 'readwrite')
.objectStore(tableName);
// 假定新建表格的时候,对name字段建立了索引。
// objectStore.createIndex('name', 'name', { unique: false });

const index = objectStore.index(indexName);
const request = index.get(indexVal);
request.onerror = function (event) {
console.log('事务失败', event);
fail();
};

request.onsuccess = function (event) {
if (request.result) {
suc(request.result);
} else {
console.log('未获得数据记录', event);
}
};
});
}


/**
* 删除数据库
* @param {string} DB_NAME 数据库名称
* @returns
*/
export async function deleteDB(DB_NAME) {
return indexedDB.deleteDatabase(DB_NAME);
}
/**
* 关闭数据库
* @param {string} DB_NAME 数据库名称
* @returns
*/
export function closeDB(DB_NAME) {
return indexedDB.close(DB_NAME);
}
/**
* 清除表
* @param {string} tableName
* @returns {promise}
*/
export function clearTable(tableName) {
return new Promise((suc, fail) => {
const objectStore = db
.transaction([tableName], 'readwrite')
.objectStore(tableName);
const request = objectStore.clear();

request.onerror = function (event) {
console.log('事务失败', event);
fail();
};

request.onsuccess = function (event) {
console.log('清除成功', event);
suc();
};
});
}

// export default {
// deleteDB,
// updateDB,
// getDataByKey,
// addData
// }

+ 1089
- 0
web_src/js/components/icons.js
File diff suppressed because it is too large
View File


+ 0
- 0
web_src/js/components/monacoeditor.vue View File


+ 3024
- 0
web_src/js/components/treeIcon.css
File diff suppressed because it is too large
View File


+ 0
- 0
web_src/js/components/vueTree.vue View File


+ 20
- 2
web_src/js/index.js View File

@@ -17,6 +17,7 @@ import "jquery.are-you-sure";
import "./vendor/semanticdropdown.js";
import { svg } from "./utils.js";
import echarts from "echarts";
import VueTreeList from 'vue-tree-list'
import initContextPopups from "./features/contextpopup.js";
import initGitGraph from "./features/gitgraph.js";
import initClipboard from "./features/clipboard.js";
@@ -42,6 +43,7 @@ import EditAboutInfo from "./components/EditAboutInfo.vue";
import EditTopics from "./components/EditTopics.vue";
import DataAnalysis from "./components/DataAnalysis.vue";
import Contributors from "./components/Contributors.vue";
import Ide from './components/IdeProject.vue'
import Model from "./components/Model.vue";
import WxAutorize from "./components/WxAutorize.vue";
import initCloudrain from "./features/cloudrbanin.js";
@@ -56,7 +58,7 @@ import { Message } from "element-ui";
import { i18nVue } from "./features/i18nVue.js";
import './features/ad.js';
import { Fancybox } from "./vendor/fancybox.esm.js";
import "../../public/iconfonts1/iconfont";

Vue.prototype.$axios = axios;
Vue.prototype.$Cookies = Cookies;
@@ -69,7 +71,7 @@ const { AppSubUrl, StaticUrlPrefix, csrf } = window.config;

Vue.use(ElementUI, {
locale: lang === 'zh-CN' ? localeZh : localeEn,
});
}).use(VueTreeList);

Object.defineProperty(Vue.prototype, "$echarts", {
value: echarts,
@@ -2913,6 +2915,7 @@ $(document).ready(async () => {
// initVueImages();
initVueModel();
initVueDataAnalysis();
initVueIde();
initVueWxAutorize();
initVueselectDataset();
initVuereferenceDataset();
@@ -4528,6 +4531,21 @@ function initVueDataAnalysis() {
render: (h) => h(DataAnalysis),
});
}

function initVueIde() {
const el = document.getElementById('initVueIde');
if (!el) {
return;
}

new Vue({
el: '#initVueIde',
router,
render: h => h(Ide)
});
}


function initVueWxAutorize() {
const el = document.getElementById("WxAutorize");
if (!el) {


+ 16
- 10
web_src/js/router/index.js View File

@@ -7,6 +7,7 @@ import UserTrend from '../components/UserTrend.vue'
import UserAnalysis from '../components/UserAnalysis.vue'
import BrainAnalysis from '../components/BrainAnalysis.vue'
import Overview from '../components/Overview.vue'
import IdeProject from '../components/IdeProject.vue'

const originalPush = Router.prototype.push

@@ -16,44 +17,49 @@ Router.prototype.push = function push(location) {
Vue.use(Router)

export default new Router({
mode: 'history',
base: '/explore/data_analysis/', //添加根目录
mode: 'history',
base: '/', //添加根目录
scrollBehavior: () => ({ y: 0 }),
routes:[
{
path:'/',redirect:'/ProAnalysis',
path:'/ide/project',
name:'ide',
component:IdeProject,
},
{
path:'/explore/data_analysis/',redirect:'/explore/data_analysis/ProAnalysis',
name:'ProAnalysis',
component:ProAnalysis,
},

{
path:'/Overview',
path:'/explore/data_analysis/Overview',
name:'Overview',
component:Overview,
},
{
path:'/ProTrend',
path:'/explore/data_analysis/ProTrend',
name:'ProTrend',
component:ProTrend,
},
{
path:'/ProAnalysis',
path:'/explore/data_analysis/ProAnalysis',
name:'ProAnalysis',
component:ProAnalysis,
},
{
path:'/UserAnalysis',
path:'/explore/data_analysis/UserAnalysis',
name:'UserAnalysis',
component:UserAnalysis,
},
{
path:'/UserTrend',
path:'/explore/data_analysis/UserTrend',
name:'UserTrend',
component:UserTrend,
},

{
path:'/BrainAnalysis',
path:'/explore/data_analysis/BrainAnalysis',
name:'BrainAnalysis',
component:BrainAnalysis,
},
@@ -61,4 +67,4 @@ export default new Router({
],


})
})

+ 114
- 0
web_src/js/utils.js View File

@@ -1,3 +1,4 @@
import uuidv1 from 'uuidv1';
// retrieve a HTML string for given SVG icon name and size in pixels
export function svg(name, size) {
return `<svg class="svg ${name}" width="${size}" height="${size}" aria-hidden="true"><use xlink:href="#${name}"/></svg>`;
@@ -23,3 +24,116 @@ export function isObject(obj) {
export function isDarkTheme() {
return document.documentElement.classList.contains('theme-arc-green');
}

export function matterTree(data) {
for (let i = 0; i < data.length; i++) {
data[i].label = data[i].name;
data[i].filePath = data[i].path;
data[i].isEdit = true;
if (!data[i].children.length) data[i].isLeaf = true;
if (data[i].children && data[i].children.length > 0) {
// children若不为空数组,则继续 递归调用 本方法
matterTree(data[i].children);
}
}
return data;
}

export function disposeTreeName(data, target) {
for (let i = 0; i < data.length; i++) {
data[i].filePath = `${target}/${data[i].name}`;
data[i].id = uuidv1().replaceAll('-', '');
if (data[i].children && data[i].children.length > 0) {
// children若不为空数组,则继续 递归调用 本方法
matterTree(data[i].children);
}
}
return data;
}

export function RecurveAddNode(treeRootData, treeD, FilePath) {
treeRootData.forEach((item) => {
if (item.filePath === FilePath) {
return item.children.push(treeD);
}
if (item.children?.length) {
RecurveAddNode(item.children, treeD, FilePath);
}
});
return treeRootData;
}

// 递归单个循环操作 判断是否新增
export function RecurveQuery(currentData, filePath) {
currentData.forEach((item, index) => {
if (item.filePath === filePath && item.isLeaf) {
currentData[index].operation = 'delete';
} else if (item.children?.length > 0) {
RecurveQuery(item.children, filePath);
}
});
return currentData;
}

// 递归 对新增的数据进行删除
export function RecurveQueryDelete(data, filePath) {
data.forEach((item, index) => {
if (item.filePath === filePath && item.isLeaf) {
data.splice(index, 1);
} else if (item.children?.length) {
RecurveQueryDelete(item.children, filePath);
}
});
return data;
}

// 循环插入改变的数据
export function RecurveUpdateValue(currentData, fileInfoParams, base64Content) {
currentData.forEach((item, index) => {
if (item.filePath === fileInfoParams.filePath) {
currentData[index].oldContent = base64Content;
currentData[index].content = base64Content;
} else if (item.children?.length > 0) {
RecurveQuery(item.children, fileInfoParams.filePath);
}
});
return currentData;
}



const flattenTree = (data) => {
return data.reduce((arr, currentValue) => {
if (currentValue.children && currentValue.children.length > 0) {
return arr.concat(flattenTree(currentValue.children))
} else {
return arr.concat(currentValue)
}
}, [])
}

export const uniqueArray = (array1, array2) => {
return array1
.concat(array2)
.reduce((prev, cur) => {
const duplicate = prev.filter(x => x.name === cur.name)
if (duplicate.length) {
return prev
} else {
prev.push(cur)
return prev
}
}, [])
}

export const isBase64 = (str) => {
if(!str) return false;
if (str === '' || str.trim() === '') {
return false;
}
try {
return window.btoa(window.atob(str)) == str;
} catch (err) {
return false;
}
}

+ 1
- 1
web_src/less/_repository.less View File

@@ -209,7 +209,7 @@
}

#clone-panel {
width: 350px;
width: 594px;

@media only screen and (max-width: 768px) {
width: 100%;


+ 1
- 0
web_src/less/_svg.less View File

@@ -8,3 +8,4 @@
vertical-align: middle;
}
}


+ 8
- 0
webpack.config.js View File

@@ -225,6 +225,14 @@ module.exports = {
},
],
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader'
},
],
},
{
test: /\.(ttf|woff2?)$/,
use: [


+ 8
- 0
webpack_pro.config.js View File

@@ -225,6 +225,14 @@ module.exports = {
},
],
},
{
test: /\.(png|jpg|gif)$/,
use: [
{
loader: 'file-loader'
},
],
},
{
test: /\.(ttf|woff2?)$/,
use: [


Loading…
Cancel
Save