browse.html.php 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. <?php
  2. /**
  3. * The gantt of programplan module of ZenTaoPMS.
  4. *
  5. * @copyright Copyright 2009-2015 禅道软件(青岛)有限公司(ZenTao Software (Qingdao) Co., Ltd. www.cnezsoft.com)
  6. * @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
  7. * @author Chunsheng Wang <chunsheng@cnezsoft.com>
  8. * @package programplan
  9. * @version $Id: gantt.html.php 4903 2013-06-26 05:32:59Z wyd621@gmail.com $
  10. * @link http://www.zentao.net
  11. */
  12. ?>
  13. <?php include $app->getModuleRoot() . 'common/view/header.html.php';?>
  14. <?php include $app->getModuleRoot() . 'common/view/gantt.html.php';?>
  15. <style>
  16. #ganttView {height: 600px;}
  17. #mainContent:before {background: #fff;}
  18. .checkbox-primary {margin-top: 0px; margin-left: 10px;}
  19. form {display: block; margin-top: 0em; margin-block-end: 1em;}
  20. .gantt_task_content span.task-label, .gantt_task_content span.label-pri{display: none;}
  21. #ganttPris > span {display: inline-block; line-height: 20px; min-width: 20px; border-radius: 2px;}
  22. .gantt_task_line.gantt_selected {box-shadow: 0 1px 1px rgba(0,0,0,.05), 0 2px 6px 0 rgba(0,0,0,.045)}
  23. .gantt_link_arrow_right {border-left-color: #2196F3;}
  24. .gantt_link_arrow_left {border-right-color: #2196F3;}
  25. .gantt_task_link .gantt_line_wrapper div{background-color: #2196F3;}
  26. .gantt_critical_link .gantt_line_wrapper>div {background-color: #e63030 !important;}
  27. .gantt_critical_link.start_to_start .gantt_link_arrow_right {border-left-color: #e63030 !important;}
  28. .gantt_critical_link.finish_to_start .gantt_link_arrow_right {border-left-color: #e63030 !important;}
  29. .gantt_critical_link.start_to_finish .gantt_link_arrow_left {border-right-color: #e63030 !important;}
  30. .gantt_critical_link.finish_to_finish .gantt_link_arrow_left {border-right-color: #e63030 !important;}
  31. .gantt_task_link.start_to_start .gantt_line_wrapper div { background-color: #DD55EA; }
  32. .gantt_task_link.start_to_start:hover .gantt_line_wrapper div { box-shadow: 0 0 5px 0px #DD55EA; }
  33. .gantt_task_link.start_to_start .gantt_link_arrow_right { border-left-color: #DD55EA; }
  34. .gantt_task_link.finish_to_start .gantt_line_wrapper div { background-color: #7576ba; }
  35. .gantt_task_link.finish_to_start:hover .gantt_line_wrapper div { box-shadow: 0 0 5px 0px #7576ba; }
  36. .gantt_task_link.finish_to_start .gantt_link_arrow_right { border-left-color: #7576ba; }
  37. .gantt_task_link.finish_to_finish .gantt_line_wrapper div { background-color: #55d822; }
  38. .gantt_task_link.finish_to_finish:hover .gantt_line_wrapper div { box-shadow: 0 0 5px 0px #55d822; }
  39. .gantt_task_link.finish_to_finish .gantt_link_arrow_left { border-right-color: #55d822; }
  40. .gantt_task_link.start_to_finish .gantt_line_wrapper div { background-color: #975000; }
  41. .gantt_task_link.start_to_finish:hover .gantt_line_wrapper div { box-shadow: 0 0 5px 0px #975000; }
  42. .gantt_task_link.start_to_finish .gantt_link_arrow_left { border-right-color: #975000; }
  43. .gantt_critical_task{background:#e63030 !important; border-color:#9d3a3a !important;}
  44. .gantt_marker .gantt_marker_content {left: -15px; background-color: #f51e1e;}
  45. .gantt_row.task-item{cursor: pointer;}
  46. #ganttDownload, #ganttHeader {display: none;}
  47. #ganttContainer {margin-top: 40px;}
  48. #mainContent {padding: 10px 20px 20px 20px;}
  49. #mainContent:before {background: #fff;}
  50. #mainContent.loading {overflow: hidden}
  51. #mainContent.loading #ganttView {overflow: hidden}
  52. #mainContent.loading #ganttHeader {display: block; padding-bottom: 20px; margin: 0; height: 46px;}
  53. #mainContent.loading #ganttDownload {display: inline}
  54. #mainContent.loading #ganttContainer {padding: 40px;}
  55. #mainContent.loading .scrollVer_cell,
  56. #mainContent.loading .scrollVer_cell {display: none;}
  57. .gantt-fullscreen #header,
  58. .gantt-fullscreen #mainMenu,
  59. .gantt-fullscreen #footer {display: none!important;}
  60. .gantt-fullscreen #mainContent {position: fixed; top: 0; right: 0; bottom: 0; left: 0}
  61. .gantt_grid_head_cell.gantt_grid_head_text{overflow:visible;}
  62. .gantt_grid_head_cell, .gantt_scale_cell{color:#000000!important;}
  63. .gantt_tree_content{color:#838A9D;}
  64. .gantt_row > div:first-child .gantt_tree_content{color:#3C4353;}
  65. .gantt_task_line.gantt_task_inline_color{border:0px;}
  66. .gantt_grid_scale, .gantt_task_scale, .gantt_task_vscroll{background-color: #F2F7FF;}
  67. #myCover {display:none;left:12px!important;z-index:10!important;top:9px!important;height:unset!important;}
  68. .button-group{position: relative;}
  69. .flax{display: flex; margin-bottom: 10px;}
  70. .switchBtn > i {padding-left: 7px;}
  71. #mainContent > .pull-left > .btn-group > .text{display: block;margin-top: 7px;}
  72. #mainContent > .pull-left > .btn-group > a > .text{overflow: hidden;display: block;}
  73. #mainContent > .pull-right > .button-group .text{margin-left: 0px;}
  74. .pull-right .icon-plus.icon-sm:before{vertical-align: 4%;}
  75. .gantt_tree_content .btn { display: inline-block; width: 26px; padding: 2px; overflow: hidden; line-height: 20px; color: #18a6fd; background: 0 0; border-color: transparent; }
  76. </style>
  77. <?php js::set('module', $app->rawModule);?>
  78. <?php js::set('method', $app->rawMethod);?>
  79. <?php js::set('ganttType', $ganttType);?>
  80. <?php js::set('vision', $config->vision);?>
  81. <?php js::set('canGanttEdit', common::hasPriv('programplan', 'ganttEdit'));?>
  82. <?php js::set('zooming', isset($zooming) ? $zooming : 'month');?>
  83. <?php js::set('productType', $product->type);?>
  84. <div id='mainContent' class='main-content load-indicator'>
  85. <div class='btn-toolbar pull-left'>
  86. <a href='javascript:fullScreen();' id='fullScreenBtn' class='btn btn-link'><i class='icon icon-fullscreen'></i> <?php echo $lang->programplan->full;?></a>
  87. <div class='btn btn-link'>
  88. <strong><?php echo $lang->execution->gantt->format . ':';?></strong>
  89. <?php echo html::radio('zooming', $lang->roadmap->zooming, 'month', "onchange='zoomTasks(this.value)'");?>
  90. </div>
  91. </div>
  92. <div class="pull-right btn-toolbar flax">
  93. <?php
  94. if(common::hasPriv('roadmap', 'create') and $config->vision == 'or') echo html::a($this->createLink('roadmap', 'create', "productID=$productID"), "<i class='icon icon-plus'></i> " . $this->lang->roadmap->create, '', "class='btn btn-primary'");
  95. ?>
  96. </div>
  97. <div id='ganttContainer'>
  98. <div class='gantt' id='ganttView'></div>
  99. </div>
  100. <?php $fileName = "gantt-export-{$productID}";?>
  101. <a id='ganttDownload' target='hiddenwin' download='<?php echo "{$fileName}.png";?>'></a>
  102. </div>
  103. <div id="myCover">
  104. <div class="gantt_control">
  105. <div class='btn btn-link' id='ganttPris'>
  106. <strong><?php echo $lang->task->pri . " : "?></strong>
  107. <?php foreach($lang->execution->gantt->progressColor as $pri => $color):?>
  108. <?php if($pri <= 4):?>
  109. <span style="background:<?php echo $color?>"><?php echo $pri;?></span> &nbsp;
  110. <?php endif;?>
  111. <?php endforeach;?>
  112. </div>
  113. </div>
  114. <div id="gantt_here"></div>
  115. </div>
  116. <script>
  117. var scriptLoadedMap = {};
  118. var loadingPrefixText = '<?php echo $lang->programplan->exporting;?>';
  119. //After that you have to redefine the getFullscreenElement() method to return a custom root node that will be expanded to full screen:
  120. gantt.ext.fullscreen.getFullscreenElement = function() {
  121. return document.getElementById("myCover");
  122. }
  123. gantt.init("gantt_here");
  124. // before gantt is expanded to full screen
  125. gantt.attachEvent("onBeforeExpand",function(){
  126. $('#myCover').css('display', 'unset');
  127. $('#mainContent .pull-right').css('opacity', '0');
  128. $('.btn-toolbar').css('display', 'none');
  129. return true;
  130. });
  131. // when gantt exited the full screen mode
  132. gantt.attachEvent("onCollapse", function (){
  133. $('#myCover').css('display', 'none');
  134. $('#mainContent .pull-right').css('opacity', '1');
  135. $('.btn-toolbar').css('display', 'flex');
  136. });
  137. /**
  138. * Get remote script for export.
  139. *
  140. * @param string $url
  141. * @param function $successCallback
  142. * @param function $errorCallback
  143. * @access public
  144. * @return void
  145. */
  146. function getRemoteScript(url, successCallback, errorCallback)
  147. {
  148. if(scriptLoadedMap[url]) return successCallback && successCallback();
  149. $.getScript(url, function()
  150. {
  151. scriptLoadedMap[url] = true;
  152. if(successCallback) successCallback();
  153. }).fail(function()
  154. {
  155. if(errorCallback) errorCallback('Cannot load "' + url + '".');
  156. });
  157. }
  158. /**
  159. * Update export progress.
  160. *
  161. * @param int $progress
  162. * @access public
  163. * @return void
  164. */
  165. function updateProgress(progress)
  166. {
  167. var progressText = loadingPrefixText;
  168. if(progress < 1) progressText += Math.floor(progress * 100) + '%';
  169. $('#mainContent').attr('data-loading', progressText);
  170. }
  171. /**
  172. * Draw gantt to canvas.
  173. *
  174. * @param string $exportType
  175. * @param function $successCallback
  176. * @param function $errorCallback
  177. * @access public
  178. * @return void
  179. */
  180. function drawGanttToCanvas(exportType, successCallback, errorCallback)
  181. {
  182. updateProgress(0);
  183. exportType = exportType || 'image';
  184. var $ganttView = $('#ganttView');
  185. var oldHeight = $ganttView.css('height');
  186. var $ganttContainer = $('#ganttContainer');
  187. var $ganttDataArea = $ganttView.find('.gantt_data_area');
  188. var $ganttDridData = $ganttView.find('.gantt_grid_data');
  189. var ganttRowHeight = $ganttView.find('.gantt_row').first().outerHeight() || 25;
  190. var ganttHeight = $ganttView.find('.gantt_task_bg').outerHeight() + $ganttView.find('.gantt_grid_scale').outerHeight() + 1;
  191. var ganttWidth = $ganttDataArea.outerWidth() + $ganttDridData.outerWidth();
  192. $ganttContainer.css(
  193. {
  194. height: ganttHeight + $('#ganttHeader').outerHeight() + 80,
  195. width: ganttWidth + 93
  196. });
  197. $ganttView.css('height', ganttHeight);
  198. gantt.render();
  199. updateProgress(0.1);
  200. getRemoteScript('<?php echo $jsRoot . 'html2canvas/min.js';?>', function()
  201. {
  202. updateProgress(0.2);
  203. var afterFinish = function(canvas)
  204. {
  205. $ganttContainer.css(
  206. {
  207. width: '',
  208. height: ''
  209. });
  210. $ganttView.css('height', oldHeight);
  211. if(canvas)
  212. {
  213. try
  214. {
  215. canvas.removeNode(true)
  216. }
  217. catch(err)
  218. {
  219. canvas.remove()
  220. };
  221. }
  222. };
  223. var delayTime = Math.max(1000, Math.floor(10 * (ganttHeight * ganttWidth) / 100000));
  224. var progressTimer;
  225. if(delayTime > 1500)
  226. {
  227. var startProgress = 0.2;
  228. var deltaProgress = 0.5 / Math.floor(delayTime/1000);
  229. progressTimer = setInterval(function()
  230. {
  231. startProgress += deltaProgress;
  232. updateProgress(Math.min(0.7, startProgress));
  233. }, 1000);
  234. }
  235. setTimeout(function()
  236. {
  237. if(progressTimer) clearInterval(progressTimer);
  238. updateProgress(0.7);
  239. html2canvas($ganttContainer[0], {logging: false}).then(function(canvas)
  240. {
  241. var isExportPDF = exportType === 'pdf';
  242. updateProgress(isExportPDF ? 0.8 : 0.9);
  243. canvas.onerror = function()
  244. {
  245. afterFinish(canvas);
  246. if(errorCallback) errorCallback('Cannot convert image to blob.');
  247. };
  248. if(isExportPDF)
  249. {
  250. var width = canvas.width;
  251. var height = canvas.height;
  252. getRemoteScript('<?php echo $jsRoot . 'pdfjs/min.js';?>', function()
  253. {
  254. updateProgress(0.8);
  255. var pdf = new jsPDF(
  256. {
  257. format: [width, height],
  258. unit: 'px',
  259. orientation: width > height ? 'l' : 'p'
  260. });
  261. pdf.addImage(canvas, 0, 0, pdf.internal.pageSize.getWidth(), pdf.internal.pageSize.getHeight());
  262. pdf.save('<?php echo "$fileName.pdf"?>');
  263. if(successCallback) successCallback(pdf);
  264. afterFinish();
  265. }, function(error)
  266. {
  267. afterFinish(canvas);
  268. if(errorCallback) errorCallback(error);
  269. });
  270. }
  271. else
  272. {
  273. canvas.toBlob(function(blob)
  274. {
  275. updateProgress(0.95);
  276. var imageUrl = URL.createObjectURL(blob);
  277. if(navigator.msSaveBlob)
  278. {
  279. navigator.msSaveOrOpenBlob(blob, '<?php echo $fileName; ?>.png');
  280. }
  281. else
  282. {
  283. $('#ganttDownload').attr({href: imageUrl})[0].click();
  284. }
  285. if(successCallback) successCallback(imageUrl);
  286. afterFinish(canvas);
  287. });
  288. }
  289. }).catch(function(error)
  290. {
  291. afterFinish();
  292. if(errorCallback) errorCallback('Cannot draw graphic to canvas.');
  293. });
  294. }, delayTime);
  295. }, errorCallback);
  296. }
  297. /**
  298. * Export gantt.
  299. *
  300. * @param string $exportType
  301. * @access public
  302. * @return void
  303. */
  304. function exportGantt(exportType)
  305. {
  306. var $mainContent = $('#mainContent');
  307. $mainContent.addClass('loading').css('height', Math.max(200, Math.floor($(window).height() - $('#footer').outerHeight() - $('#header').outerHeight() - $('#mainMenu').outerHeight() - 38)));
  308. $('#ganttExportDate').text(new Date().format('yyyy-MM-dd hh:mm:ss'));
  309. var afterFinish = function(url)
  310. {
  311. setTimeout(function()
  312. {
  313. $mainContent.css('height', '').removeClass('loading');
  314. }, 300);
  315. updateProgress(1);
  316. };
  317. drawGanttToCanvas(exportType, afterFinish, function(errorText)
  318. {
  319. afterFinish();
  320. $.zui.messager.danger('<?php echo $lang->programplan->exportFail;?>' + (errorText || ''));
  321. });
  322. }
  323. /**
  324. * Get by id for gantt.
  325. *
  326. * @param array $list
  327. * @param string $id
  328. * @access public
  329. * @return string
  330. */
  331. function getByIdForGantt(list, id)
  332. {
  333. for (var i = 0; i < list.length; i++)
  334. {
  335. if (list[i].key == id) return list[i].label || "";
  336. }
  337. return id;
  338. }
  339. /**
  340. * Zoom tasks.
  341. *
  342. * @param value
  343. * @access public
  344. * @return void
  345. */
  346. function zoomTasks(value)
  347. {
  348. switch(value)
  349. {
  350. case "month":
  351. gantt.config.min_column_width = 70;
  352. gantt.config.scales = [{unit: "year", step: 1, format: "%Y"}, {unit: 'month', step: 1, format: '%M'}, {unit:"week", step:1, date:"<?php echo $lang->execution->gantt->zooming['week'];?> #%W"}];
  353. gantt.config.scale_height = 22 * gantt.config.scales.length;
  354. break;
  355. case "quarter":
  356. gantt.config.min_column_width = 70;
  357. gantt.config.scales = [{unit: "year", step: 1, format: "%Y"}, { unit: "quarter", step: 1, format: function (date) { var dateToStr = gantt.date.date_to_str("%M"); var endDate = gantt.date.add(gantt.date.add(date, 3, "month"), -1, "day"); return dateToStr(date) + " - " + dateToStr(endDate);}}];
  358. break;
  359. case "year":
  360. gantt.config.min_column_width = 70;
  361. gantt.config.scales = [{unit: "year", step: 1, format: "%Y"}, {unit: 'month', step: 1, format: '%M'}]
  362. gantt.config.scale_height = 22 * gantt.config.scales.length;
  363. break;
  364. }
  365. gantt.render();
  366. $('.gantt_grid_head_cell .sort').addClass(value);
  367. }
  368. window.onload = function () {
  369. zoomTasks(zooming);
  370. }
  371. $("#fullScreenBtn").on("click", function()
  372. {
  373. $("#mainContent").css("z-index", "5");
  374. $("#ganttView").css("z-index", "5");
  375. });
  376. function exitHandler()
  377. {
  378. if (module == 'review' && method == 'assess' && !document.fullscreenElement && !document.webkitIsFullScreen && !document.mozFullScreen && !document.msFullscreenElement)
  379. {
  380. location.reload();
  381. }
  382. }
  383. $(function()
  384. {
  385. document.addEventListener('fullscreenchange', exitHandler);
  386. var layout;
  387. // Set gantt view height
  388. var resizeGanttView = function()
  389. {
  390. if(gantt.getState().fullscreen) return false;
  391. $('#ganttView').css('height', Math.max(200, Math.floor($(window).height() - $('#footer').outerHeight() - $('#header').outerHeight() - $('#mainMenu').outerHeight() - 120)));
  392. };
  393. var ganttData = $.parseJSON(<?php echo json_encode(json_encode($roadmaps));?>);
  394. if(!ganttData.data) ganttData.data = [];
  395. <?php
  396. $userList = array();
  397. if(!empty($users))
  398. {
  399. foreach($users as $account => $realname)
  400. {
  401. $user = array();
  402. $user['key'] = $account;
  403. $user['label'] = $realname;
  404. $userList[] = $user;
  405. }
  406. }
  407. ?>
  408. gantt.serverList("userList", <?php echo json_encode($userList);?>);
  409. gantt.config.readonly = true;
  410. gantt.config.details_on_dblclick = false;
  411. gantt.config.order_branch = ganttType == 'assignedTo' ? false : true;
  412. gantt.config.drag_progress = false;
  413. gantt.config.drag_links = false;
  414. gantt.config.drag_move = false;
  415. gantt.config.drag_resize = true;
  416. gantt.config.smart_rendering = true;
  417. gantt.config.smart_scales = true;
  418. gantt.config.static_background = true;
  419. gantt.config.show_task_cells = false;
  420. gantt.config.row_height = 32;
  421. gantt.config.min_column_width = 40;
  422. gantt.config.details_on_create = false;
  423. gantt.config.scales = [{unit: "year", step: 1, format: "%Y"}, {unit: 'day', step: 1, format: '%m-%d'}];
  424. gantt.config.scale_height = 18 * gantt.config.scales.length;
  425. gantt.config.duration_unit = "day";
  426. gantt.config.columns = [];
  427. gantt.config.columns.push({name: 'text', width: '*', tree: true, resize: true, min_width:120, width:200});
  428. if(productType != 'normal') gantt.config.columns.push({name: 'branch', align: 'center', resize: true, width: 100});
  429. gantt.config.columns.push({name: 'status', align: 'center', resize: true, width: 90});
  430. gantt.config.columns.push({name: 'start_date', align: 'center', resize: true, width: 90});
  431. gantt.config.columns.push({name: 'end_date', align: 'center', resize: true, width: 90});
  432. gantt.config.columns.push({name: 'requirements', align: 'center', resize: true, width: 90});
  433. if(vision == 'or') gantt.config.columns.push({name: 'actions', align: 'center', resize: true, width: 130});
  434. gantt.templates.task_end_date = function(data)
  435. {
  436. return gantt.templates.task_date(new Date(date.valueOf() - 1));
  437. }
  438. var gridDateToStr = gantt.date.date_to_str("%Y-%m-%d");
  439. gantt.templates.grid_date_format = function(date, column)
  440. {
  441. if(column === "end_date")
  442. {
  443. return gridDateToStr(new Date(date.valueOf()));
  444. }
  445. else
  446. {
  447. return gridDateToStr(date);
  448. }
  449. }
  450. endField = gantt.config.columns.pop();
  451. endField.resize = false;
  452. gantt.config.columns.push(endField);
  453. gantt.locale.labels.column_text = "<?php echo $lang->roadmap->name;?>";
  454. gantt.locale.labels.column_status = "<?php echo $lang->roadmap->status;?>";
  455. gantt.locale.labels.column_start_date = "<?php echo $lang->roadmap->begin;?>";
  456. gantt.locale.labels.column_end_date = "<?php echo $lang->roadmap->end;?>";
  457. gantt.locale.labels.column_requirements= "<?php echo $lang->roadmap->requirments;?>";
  458. if(vision == 'or') gantt.locale.labels.column_actions = "<?php echo $lang->roadmap->actions;?>";
  459. if(productType != 'normal') gantt.locale.labels.column_branch = "<?php echo sprintf($lang->roadmap->branch, $lang->product->branchName[$product->type]);?>";
  460. var date2Str = gantt.date.date_to_str(gantt.config.task_date);
  461. var today = new Date();
  462. var todayTips = "<?php echo $lang->programplan->today;?>";
  463. gantt.addMarker({
  464. start_date: today,
  465. css: "today",
  466. text: todayTips,
  467. title: todayTips + ": " + date2Str(today)
  468. });
  469. gantt.templates.task_class = function(start, end, task){return 'pri-' + (task.pri || 0);};
  470. gantt.templates.rightside_text = function(start, end, task)
  471. {
  472. if(typeof task.owner_id == 'undefined') return;
  473. return getByIdForGantt(gantt.serverList('userList'), task.owner_id);
  474. };
  475. gantt.templates.grid_row_class = function (start, end, task)
  476. {
  477. if(task.type == 'task') return 'task-item';
  478. };
  479. gantt.templates.link_class = function(link)
  480. {
  481. var types = gantt.config.links;
  482. if(link.type == types.finish_to_start) return 'finish_to_start';
  483. if(link.type == types.start_to_start) return 'start_to_start';
  484. if(link.type == types.finish_to_finish) return 'finish_to_finish';
  485. if(link.type == types.start_to_finish) return 'start_to_finish';
  486. };
  487. gantt.templates.tooltip_text = function (start, end, task)
  488. {
  489. return '';
  490. };
  491. gantt.attachEvent('onTemplatesReady', function()
  492. {
  493. $('#fullScreenBtn').click(function()
  494. {
  495. gantt.expand();
  496. });
  497. });
  498. var isGanttExpand = false;
  499. var delayTimer = null;
  500. var handleFullscreen = function()
  501. {
  502. if(isGanttExpand)
  503. {
  504. $('body').addClass('gantt-fullscreen');
  505. $('#ganttView').css('height', $(window).height() - 60);
  506. isGanttExpand = false;
  507. }
  508. else
  509. {
  510. $('body').removeClass('gantt-fullscreen');
  511. resizeGanttView();
  512. }
  513. delayTimer = null;
  514. };
  515. var delayHandleFullscreen = function()
  516. {
  517. if(delayTimer) clearTimeout(delayTimer);
  518. delayTimer = setTimeout(handleFullscreen, 50);
  519. };
  520. gantt.attachEvent('onBeforeExpand', function()
  521. {
  522. $('body').addClass('gantt-fullscreen');
  523. isGanttExpand = true;
  524. return true;
  525. });
  526. if(document.addEventListener)
  527. {
  528. document.addEventListener('webkitfullscreenchange', delayHandleFullscreen, false);
  529. document.addEventListener('mozfullscreenchange', delayHandleFullscreen, false);
  530. document.addEventListener('fullscreenchange', delayHandleFullscreen, false);
  531. document.addEventListener('MSFullscreenChange', delayHandleFullscreen, false);
  532. }
  533. resizeGanttView();
  534. $(window).resize(resizeGanttView);
  535. gantt.templates.grid_folder = function(item) {
  536. return "";
  537. };
  538. gantt.templates.grid_file = function(item) {
  539. return "";
  540. };
  541. gantt.init('ganttView');
  542. gantt.parse(ganttData);
  543. gantt.showDate(new Date());
  544. // Show task in modal on click task
  545. gantt.attachEvent('onTaskClick', function(id, e)
  546. {
  547. if($(e.srcElement).hasClass('icon-magic')) return false;
  548. if($(e.srcElement).hasClass('icon-trash')) return false;
  549. if($(e.srcElement).find('a').length > 0) return false;
  550. if(e.target.tagName == 'I' || e.target.tagName == 'A') return false;
  551. if($(e.srcElement).hasClass('gantt_close') || $(e.srcElement).hasClass('gantt_open')) return false;
  552. /* The id of task item is like executionID-taskID. e.g. 1507-37829, 37829 is task id. */
  553. var mapID = id;
  554. if(!isNaN(mapID) && mapID > 0) $.apps.open(createLink('roadmap', 'view', 'mapID=' + mapID, 'html'));
  555. });
  556. // Make folder can open or close by click
  557. $('#ganttView').on('click', '.gantt_close,.gantt_open', function()
  558. {
  559. var $task = $(this).closest('.gantt_row_task');
  560. var task = gantt.getTask($task.attr('task_id'));
  561. if(kask) gantt[task.$open ? 'close' : 'open'](task.id);
  562. });
  563. $(".example .checkbox-primary").on('click', function()
  564. {
  565. var stageCustom = [];
  566. $("input[name='stageCustom[]']:checked").each(function()
  567. {
  568. var custom = $(this).val();
  569. stageCustom.push(custom);
  570. });
  571. if(stageCustom.length == 0) stageCustom = 0;
  572. $.ajax({
  573. url: customUrl,
  574. dataType: "json",
  575. data: {stageCustom: stageCustom},
  576. type: "post",
  577. success: function(result)
  578. {
  579. window.location.reload();
  580. }
  581. });
  582. });
  583. $('#ganttContainer').mouseleave(function()
  584. {
  585. setTimeout(function(){$('.gantt_tooltip').remove()}, 100);
  586. });
  587. $('#ganttContainer').on('click', '.iframe', function()
  588. {
  589. new $.zui.ModalTrigger({iframe : $(this).attr('href'), width: '60%'}).show();
  590. return false;
  591. })
  592. });
  593. </script>