ajaxgeteditorcontent.html.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369
  1. <?php
  2. /**
  3. * The create view file of repo module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2023 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
  6. * @author Yanyi Cao
  7. * @package repo
  8. * @version $Id: create.html.php $
  9. */
  10. ?>
  11. <?php
  12. include '../../common/view/header.lite.html.php';
  13. $canLinkStory = common::hasPriv('repo', 'linkStory');
  14. $canLinkBug = common::hasPriv('repo', 'linkBug');
  15. $canLinkTask = common::hasPriv('repo', 'linkTask');
  16. $canUnlinkObject = common::hasPriv('repo', 'unlink');
  17. js::set('jsRoot', $jsRoot);
  18. js::set('clientLang', $app->clientLang);
  19. js::set('fileExt', $this->config->repo->fileExt);
  20. js::set('file', $pathInfo);
  21. js::set('blameTmpl', $lang->repo->blameTmpl);
  22. js::set('repoID', $repoID);
  23. js::set('showEditor', $showEditor);
  24. js::set('canLinkStory', $canLinkStory);
  25. js::set('canLinkBug', $canLinkBug);
  26. js::set('canLinkTask', $canLinkTask);
  27. js::set('objectID', 0);
  28. js::set('objectType', 'story');
  29. js::set('pageType', $type);
  30. js::set('revision', $revision);
  31. js::set('sourceRevision', $oldRevision);
  32. js::set('encodePath', $this->repo->encodePath($entry));
  33. if($showEditor) js::set('codeContent', $content);
  34. js::import($jsRoot . 'zui/tabs/tabs.min.js');
  35. js::import($jsRoot . 'monaco-editor/min/vs/loader.js');
  36. ?>
  37. <div id="monacoEditor" class='repoCode'>
  38. <?php if(strpos($config->repo->images, "|$suffix|") !== false):?>
  39. <div class='image'><img src='data:image/<?php echo $suffix?>;base64,<?php echo $content?>' /></div>
  40. <?php elseif($suffix == 'binary'):?>
  41. <div class='binary'><?php echo html::a($this->repo->createLink('download', "repoID=$repoID&path=" . $this->repo->encodePath($entry) . "&fromRevision=$revision"), "<i class='icon-download'></i>", 'hiddenwin', "title='{$lang->repo->download}'"); ?></div>
  42. <?php else:?>
  43. <div id="codeContainer"></div>
  44. <?php endif;?>
  45. <div id="log">
  46. <div class="history"></div>
  47. <div class="action-btn pull-right">
  48. <div class="btn btn-close pull-right"><i class="icon icon-close"></i></div>
  49. <?php if($canLinkStory or $canLinkBug or $canLinkTask):?>
  50. <div class="dropdown pull-right">
  51. <button class="btn" type="button" data-toggle="context-dropdown"><i class="icon icon-ellipsis-v icon-rotate-90"></i></button>
  52. <ul class="dropdown-menu">
  53. <?php
  54. if($canLinkStory) echo '<li id="linkStory">' . html::a('javascript:;', '<i class="icon icon-lightbulb"></i> ' . $lang->repo->linkStory) . '</li>';
  55. if($canLinkBug) echo '<li id="linkBug">' . html::a('javascript:;', '<i class="icon icon-bug"></i> ' . $lang->repo->linkBug) . '</li>';
  56. if($canLinkTask) echo '<li id="linkTask">' . html::a('javascript:;', '<i class="icon icon-todo"></i> ' . $lang->repo->linkTask) . '</li>';
  57. ?>
  58. </ul>
  59. </div>
  60. <?php endif;?>
  61. </div>
  62. </div>
  63. <div id="related">
  64. <div class="main-col main">
  65. <div class="content panel">
  66. <div class='btn-toolbar'>
  67. <div class="btn btn-left pull-left"><i class="icon icon-chevron-left"></i></div>
  68. <div class="btn btn-right pull-right"><i class="icon icon-chevron-right"></i></div>
  69. <div class='panel-title'>
  70. <div class="tabs w-10" id="relationTabs"></div>
  71. </div>
  72. </div>
  73. </div>
  74. </div>
  75. <div class="table-empty-tip">
  76. <p><?php echo $lang->repo->notRelated;?></p>
  77. </div>
  78. </div>
  79. </div>
  80. <?php include '../../common/view/footer.lite.html.php';?>
  81. <script>
  82. var editor = null;
  83. var modifiedEditor = null;
  84. var diffContent = null;
  85. var blames = null;
  86. var globalCommit = '';
  87. var codeHeight = $(window).innerHeight() - $('#mainHeader').height() - $('#appsBar').height() - $('#fileTabs .tabs-navbar').height();
  88. if(codeHeight > 0) $.cookie('codeContainerHeight', codeHeight);
  89. $('#codeContainer').css('height', $.cookie('codeContainerHeight'));
  90. /**
  91. * Get relation by commit.
  92. *
  93. * @param string $commit
  94. * @access public
  95. * @return void
  96. */
  97. function getRelation(commit)
  98. {
  99. $('.table-empty-tip').show();
  100. $('#codeContainer').css('height', codeHeight / 5 * 3);
  101. var relatedHeight = codeHeight / 5 * 2 - $('#log').height() - 10;
  102. $('#related').css('height', relatedHeight);
  103. $tabs = $('#relationTabs').data('zui.tabs');
  104. if($tabs) $tabs.closeAll();
  105. $.post(createLink('repo', 'ajaxGetCommitRelation', 'repoID=' + repoID + '&commit=' + commit), function(data)
  106. {
  107. var titleList = JSON.parse(data).titleList;
  108. var tabs = [];
  109. $.each(titleList, function(i, titleObj)
  110. {
  111. var tab = setTab(titleObj);
  112. if($tabs)
  113. {
  114. $tabs.open(tab);
  115. }
  116. else
  117. {
  118. tabs.push(tab);
  119. }
  120. });
  121. if(titleList.length > 0)
  122. {
  123. if($tabs)
  124. {
  125. $tabs.open(setTab(titleList[0]));
  126. }
  127. else
  128. {
  129. $('#relationTabs').tabs({tabs: tabs});
  130. }
  131. $('.table-empty-tip').hide();
  132. $('#related button').show();
  133. }
  134. else
  135. {
  136. if(!canLinkStory && !canLinkBug && !canLinkTask) $('#related button').hide();
  137. }
  138. arrowTabs('relationTabs', 1);
  139. });
  140. globalCommit = commit;
  141. var linkStory = createLink('repo', 'linkStory', 'repoID=' + repoID + '&commit=' + commit, '', true);
  142. var linkBug = createLink('repo', 'linkBug', 'repoID=' + repoID + '&commit=' + commit, '', true);
  143. var linkTask = createLink('repo', 'linkTask', 'repoID=' + repoID + '&commit=' + commit, '', true);
  144. $('#linkStory a').attr('data-link', linkStory);
  145. $('#linkBug a').attr('data-link', linkBug);
  146. $('#linkTask a').attr('data-link', linkTask);
  147. $('#related').show();
  148. }
  149. <?php if($canUnlinkObject):?>
  150. $('#relationTabs').on('onLoad', function(event, tab) {
  151. var objectInfo = tab.id.split('-');
  152. objectID = objectInfo[0];
  153. objectType = objectInfo[1];
  154. unlink = createLink('repo', 'unlink', 'repoID=' + repoID + '&commit=' + globalCommit + '&objectID=' + objectID + '&objectType=' + objectType);
  155. $('#relationTabs ul li[data-id=' + tab.id + '] span.title').after('<a title="<?php echo $lang->repo->unlink;?>" class="unlinks" data-link="' + unlink + '"><i class="icon-unlink"></i></a>');
  156. });
  157. <?php endif;?>
  158. /**
  159. * Set tab data.
  160. *
  161. * @param object $titleObj
  162. * @access public
  163. * @return object
  164. */
  165. function setTab(titleObj)
  166. {
  167. return {
  168. id: titleObj.type + '-' + titleObj.id,
  169. title: titleObj.title,
  170. icon: titleObj.type == 'story' ? 'icon-lightbulb' : (titleObj.type == 'task' ? 'icon-check-sign' : 'icon-bug'),
  171. type: 'iframe',
  172. url: createLink('repo', 'ajaxGetRelationInfo', 'objectID=' + titleObj.id + '&objectType=' + titleObj.type)
  173. };
  174. }
  175. /**
  176. * Update diff editor inline style.
  177. *
  178. * @param bool display
  179. * @access public
  180. * @return void
  181. */
  182. function updateEditorInline(display){
  183. modifiedEditor.updateOptions({renderSideBySide: display});
  184. }
  185. /**
  186. * Show commit info.
  187. *
  188. * @access public
  189. * @return void
  190. */
  191. function showCommitInfo()
  192. {
  193. var link = createLink('repo', 'ajaxGetCommitInfo');
  194. var data = {
  195. repoID : repoID,
  196. entry : encodePath,
  197. revision : revision,
  198. sourceRevision: sourceRevision,
  199. line : 0,
  200. returnType : 'json'
  201. };
  202. $.post(link, data, function(res)
  203. {
  204. res = JSON.parse(res);
  205. blames = res.blames;
  206. })
  207. }
  208. /**
  209. * Show blame info and relations.
  210. *
  211. * @param int line
  212. * @access public
  213. * @return void
  214. */
  215. function showBlameAndRelation(line)
  216. {
  217. if(!blames) return;
  218. if(pageType == 'diff') line = diffContent.line.new[line -1];
  219. var blame = blames[line];
  220. if(!blame) return;
  221. var p_line = parseInt(line);
  222. while(!blame.revision)
  223. {
  224. p_line--;
  225. blame = blames[p_line];
  226. }
  227. if($('#log').data('line') == line) return;
  228. var time = blame.time != 'unknown' ? blame.time : '';
  229. var user = blame.committer != 'unknown' ? blame.committer : '';
  230. var version = blame.revision.toString().substring(0, 10);
  231. var content = blameTmpl.replace('%line', line).replace('%time', time).replace('%name', user).replace('%version', version).replace('%comment', blame.message);
  232. $('.history').html(content);
  233. $('#log').data('line', line);
  234. $('#log').css('display', 'flex');
  235. getRelation(blame.revision);
  236. }
  237. $(function()
  238. {
  239. $('.btn-left').click(function() {arrowTabs('relationTabs', 1);});
  240. $('.btn-right').click(function() {arrowTabs('relationTabs', -2);});
  241. if(showEditor)
  242. {
  243. require.config({
  244. paths: {vs: jsRoot + 'monaco-editor/min/vs'},
  245. 'vs/nls': {
  246. availableLanguages: {
  247. '*': clientLang
  248. }
  249. }
  250. });
  251. require(['vs/editor/editor.main'], function ()
  252. {
  253. var lang = 'php';
  254. $.each(fileExt, function(langName, ext)
  255. {
  256. if(ext.indexOf('.' + file.extension) !== -1) lang = langName;
  257. });
  258. if(pageType == 'diff')
  259. {
  260. diffContent = parent.getDiffs(file.dirname + '/' + file.basename);
  261. modifiedEditor = monaco.editor.createDiffEditor(document.getElementById('codeContainer'),
  262. {
  263. readOnly: true,
  264. language: lang,
  265. autoIndent: true,
  266. inDiffEditor: true,
  267. contextmenu: true,
  268. automaticLayout: true,
  269. renderSideBySide: false,
  270. EditorMinimapOptions: {enabled: false},
  271. lineNumbers: function(number)
  272. {
  273. var newlc = diffContent.line.new;
  274. var oldlc = diffContent.line.old;
  275. return newlc[number - 1];
  276. }
  277. });
  278. modifiedEditor.setModel({
  279. original: monaco.editor.createModel(diffContent.code.old.trim("\n"), lang),
  280. modified: monaco.editor.createModel(diffContent.code.new.trim("\n"), lang),
  281. });
  282. editor = modifiedEditor.getModifiedEditor();
  283. var getOriginalEditor = modifiedEditor.getOriginalEditor();
  284. getOriginalEditor.onMouseDown(function(obj)
  285. {
  286. showBlameAndRelation(obj.target.position.lineNumber);
  287. })
  288. }
  289. else
  290. {
  291. editor = monaco.editor.create(document.getElementById('codeContainer'),
  292. {
  293. value: codeContent.toString(),
  294. language: lang,
  295. readOnly: true,
  296. autoIndent: true,
  297. contextmenu: true,
  298. automaticLayout: true,
  299. EditorMinimapOptions: {enabled: false}
  300. });
  301. }
  302. editor.onMouseDown(function(obj)
  303. {
  304. showBlameAndRelation(obj.target.position.lineNumber);
  305. })
  306. });
  307. }
  308. $('#linkStory a, #linkBug a, #linkTask a').on('click', function()
  309. {
  310. var link = $(this).attr('data-link');
  311. parent.loadLinkPage(link);
  312. });
  313. $('#relationTabs').on('click', '.unlinks', function()
  314. {
  315. var link = $(this).attr('data-link');
  316. $.post(link, function(data)
  317. {
  318. data = JSON.parse(data);
  319. if(data.result)
  320. {
  321. getRelation(data.revision);
  322. }
  323. else
  324. {
  325. alert(data.message);
  326. }
  327. })
  328. })
  329. $('#relationTabs').on('onOpen', function(event, tab)
  330. {
  331. $('#tab-nav-item-' + tab.id).attr('title', tab.title);
  332. var relatedHeight = codeHeight / 5 * 2 - $('#log').height() - 45;
  333. $('#relationTabs iframe').css('height', relatedHeight);
  334. });
  335. /* Get file commits. */
  336. showCommitInfo();
  337. });
  338. </script>