diff --git a/module/execution/config.php b/module/execution/config.php
index 0c20808ff2..a0d653269c 100644
--- a/module/execution/config.php
+++ b/module/execution/config.php
@@ -129,3 +129,9 @@ $config->execution->kanbanSetting->colorList['pause'] = '#fdc137';
$config->execution->kanbanSetting->colorList['done'] = '#0BD986';
$config->execution->kanbanSetting->colorList['cancel'] = '#CBD0DB';
$config->execution->kanbanSetting->colorList['closed'] = '#838A9D';
+
+$config->execution->gantt = new stdclass();
+$config->execution->gantt->linkType['end']['begin'] = 0;
+$config->execution->gantt->linkType['begin']['begin'] = 1;
+$config->execution->gantt->linkType['end']['end'] = 2;
+$config->execution->gantt->linkType['begin']['end'] = 3;
diff --git a/module/execution/lang/en.php b/module/execution/lang/en.php
index fdbb61d59d..c9aa6aa2f0 100644
--- a/module/execution/lang/en.php
+++ b/module/execution/lang/en.php
@@ -477,4 +477,16 @@ $lang->execution->statusColorList['doing'] = '#0BD986';
$lang->execution->statusColorList['suspended'] = '#fdc137';
$lang->execution->statusColorList['closed'] = '#838A9D';
+if(!isset($lang->execution->gantt)) $lang->execution->gantt = new stdclass();
+$lang->execution->gantt->color[0] = 'bbb';
+$lang->execution->gantt->color[1] = 'ff5d5d';
+$lang->execution->gantt->color[2] = 'ff9800';
+$lang->execution->gantt->color[3] = '16a8f8';
+$lang->execution->gantt->color[4] = '00da88';
+
+$lang->execution->gantt->exportImg = 'Export as Image';
+$lang->execution->gantt->exportPDF = 'Export as PDF';
+$lang->execution->gantt->exporting = 'Exporting...';
+$lang->execution->gantt->exportFail = 'Failed to export.';
+
$lang->execution->boardColorList = array('#32C5FF', '#006AF1', '#9D28B2', '#FF8F26', '#7FBB00', '#424BAC', '#66c5f8', '#EC2761');
diff --git a/module/execution/lang/zh-cn.php b/module/execution/lang/zh-cn.php
index c896f7b8ae..990d41a1f6 100644
--- a/module/execution/lang/zh-cn.php
+++ b/module/execution/lang/zh-cn.php
@@ -477,4 +477,16 @@ $lang->execution->statusColorList['doing'] = '#0BD986';
$lang->execution->statusColorList['suspended'] = '#fdc137';
$lang->execution->statusColorList['closed'] = '#838A9D';
+if(!isset($lang->execution->gantt)) $lang->execution->gantt = new stdclass();
+$lang->execution->gantt->color[0] = 'bbb';
+$lang->execution->gantt->color[1] = 'ff5d5d';
+$lang->execution->gantt->color[2] = 'ff9800';
+$lang->execution->gantt->color[3] = '16a8f8';
+$lang->execution->gantt->color[4] = '00da88';
+
+$lang->execution->gantt->exportImg = '导出图片';
+$lang->execution->gantt->exportPDF = '导出 PDF';
+$lang->execution->gantt->exporting = '正在导出……';
+$lang->execution->gantt->exportFail = '导出失败。';
+
$lang->execution->boardColorList = array('#32C5FF', '#006AF1', '#9D28B2', '#FF8F26', '#7FBB00', '#424BAC', '#66c5f8', '#EC2761');
diff --git a/module/programplan/control.php b/module/programplan/control.php
index 2e57c04a49..08884b9877 100644
--- a/module/programplan/control.php
+++ b/module/programplan/control.php
@@ -83,7 +83,7 @@ class programplan extends control
$selectCustom = $this->loadModel('setting')->getItem("owner={$owner}&module={$module}§ion={$section}&key={$object}");
if(strpos($selectCustom, 'date') !== false) $dateDetails = 0;
- $plans = $this->programplan->getDataForGantt($projectID, $this->productID, $baselineID);
+ $plans = $this->programplan->getDataForGantt($projectID, $this->productID, $baselineID, $selectCustom, false);
}
if($type == 'lists')
diff --git a/module/programplan/model.php b/module/programplan/model.php
index 61d5044520..89fe560112 100644
--- a/module/programplan/model.php
+++ b/module/programplan/model.php
@@ -169,12 +169,12 @@ class programplanModel extends model
}
$datas = array();
- $planIDList = array();
+ $planIdList = array();
$isMilestone = " ";
$stageIndex = array();
foreach($plans as $plan)
{
- $planIDList[$plan->id] = $plan->id;
+ $planIdList[$plan->id] = $plan->id;
$start = helper::isZeroDate($plan->begin) ? '' : $plan->begin;
$end = helper::isZeroDate($plan->end) ? '' : $plan->end;
@@ -216,10 +216,7 @@ class programplanModel extends model
if(empty($selectCustom)) $selectCustom = $this->loadModel('setting')->getItem("owner={$owner}&module={$module}§ion={$section}&key={$object}");
$tasks = array();
- if(strpos($selectCustom, 'task') !== false)
- {
- $tasks = $this->dao->select('*')->from(TABLE_TASK)->where('deleted')->eq(0)->andWhere('execution')->in($planIDList)->fetchAll('id');
- }
+ if(strpos($selectCustom, 'task') !== false) $tasks = $this->dao->select('*')->from(TABLE_TASK)->where('deleted')->eq(0)->andWhere('execution')->in($planIdList)->fetchAll('id');
if($baselineID)
{
@@ -254,10 +251,12 @@ class programplanModel extends model
$data->deadline = $end;
$data->realBegan = $realBegan;
$data->realEnd = $realEnd;
+ $data->pri = $task->pri;
$data->parent = $task->parent > 0 ? $task->execution . '-' . $task->parent : $task->execution;
$data->open = true;
- $progress = $task->consumed ? round($task->consumed / ($task->left + $task->consumed), 3) * 100 : 0;
- $data->taskProgress = $progress . '%';
+ $progress = $task->consumed ? round($task->consumed / ($task->left + $task->consumed), 3) : 0;
+ $data->progress = $progress;
+ $data->taskProgress = ($progress * 100) . '%';
$data->start_date = $data->realBegan ? $data->realBegan : $data->begin;
$data->endDate = $data->realEnd ? $data->realEnd : $data->deadline;
$data->duration = 0;
@@ -280,11 +279,26 @@ class programplanModel extends model
/* Calculate the progress of the phase. */
foreach($stageIndex as $index => $stage)
{
- $progress = empty($stage['progress']['totalConsumed']) ? 0 : round($stage['progress']['totalConsumed'] / $stage['progress']['totalReal'], 3) * 100;
- $progress .= '%';
+ $progress = empty($stage['progress']['totalConsumed']) ? 0 : round($stage['progress']['totalConsumed'] / $stage['progress']['totalReal'], 3);
+ $datas['data'][$index]->progress = $progress;
+
+ $progress = ($progress * 100) . '%';
$datas['data'][$index]->taskProgress = $progress;
}
+ $datas['links'] = array();
+ if($this->config->edition != 'open')
+ {
+ $relations = $this->dao->select('*')->from(TABLE_RELATIONOFTASKS)->where('execution')->in($planIdList)->orderBy('task,pretask')->fetchAll();
+ foreach($relations as $relation)
+ {
+ $link['source'] = $relation->execution . '-' . $relation->pretask;
+ $link['target'] = $relation->execution . '-' . $relation->task;
+ $link['type'] = $this->config->execution->gantt->linkType[$relation->condition][$relation->action];
+ $datas['links'][] = $link;
+ }
+ }
+
return $returnJson ? json_encode($datas) : $datas;
}
diff --git a/module/programplan/view/gantt.html.php b/module/programplan/view/gantt.html.php
index aa84cbe895..741570d644 100644
--- a/module/programplan/view/gantt.html.php
+++ b/module/programplan/view/gantt.html.php
@@ -22,11 +22,34 @@
.gantt_task_content{display: none;}
.checkbox-primary {margin-top: 0px; margin-left: 10px;}
form {display: block; margin-top: 0em; margin-block-end: 1em;}
-
-.gantt_grid .gantt_grid_scale{width:100% !important;}
-.gantt_grid .gantt_grid_data{width:100% !important;}
-.gantt_grid .gantt_grid_data .gantt_row{width:100% !important;}
-
+.gantt_task_progress {background: rgba(0,0,0,.1)}
+#ganttPris > span {display: inline-block; line-height: 20px; min-width: 20px; border-radius: 2px;}
+.gantt_task_line {background: #execution->gantt->color[0]?>; border-color: #execution->gantt->color[0]?>;}
+.gantt_task_line.pri-1 {background: #execution->gantt->color[1]?>; border-color: #execution->gantt->color[1]?>}
+.gantt_task_line.pri-2 {background: #execution->gantt->color[2]?>; border-color: #execution->gantt->color[2]?>}
+.gantt_task_line.pri-3 {background: #execution->gantt->color[3]?>; border-color: #execution->gantt->color[3]?>}
+.gantt_task_line.pri-4 {background: #execution->gantt->color[4]?>; border-color: #execution->gantt->color[4]?>}
+.gantt_task_line.gantt_selected {box-shadow: 0 1px 1px rgba(0,0,0,.05), 0 2px 6px 0 rgba(0,0,0,.045)}
+.gantt_link_arrow_right {border-left-color: #2196F3;}
+.gantt_link_arrow_left {border-right-color: #2196F3;}
+.gantt_task_link .gantt_line_wrapper div{background-color: #2196F3;}
+.gantt_critical_link .gantt_line_wrapper>div {background-color: #e63030 !important;}
+.gantt_critical_link.start_to_start .gantt_link_arrow_right {border-left-color: #e63030 !important;}
+.gantt_critical_link.finish_to_start .gantt_link_arrow_right {border-left-color: #e63030 !important;}
+.gantt_critical_link.start_to_finish .gantt_link_arrow_left {border-right-color: #e63030 !important;}
+.gantt_critical_link.finish_to_finish .gantt_link_arrow_left {border-right-color: #e63030 !important;}
+.gantt_task_link.start_to_start .gantt_line_wrapper div { background-color: #DD55EA; }
+.gantt_task_link.start_to_start:hover .gantt_line_wrapper div { box-shadow: 0 0 5px 0px #DD55EA; }
+.gantt_task_link.start_to_start .gantt_link_arrow_right { border-left-color: #DD55EA; }
+.gantt_task_link.finish_to_start .gantt_line_wrapper div { background-color: #7576ba; }
+.gantt_task_link.finish_to_start:hover .gantt_line_wrapper div { box-shadow: 0 0 5px 0px #7576ba; }
+.gantt_task_link.finish_to_start .gantt_link_arrow_right { border-left-color: #7576ba; }
+.gantt_task_link.finish_to_finish .gantt_line_wrapper div { background-color: #55d822; }
+.gantt_task_link.finish_to_finish:hover .gantt_line_wrapper div { box-shadow: 0 0 5px 0px #55d822; }
+.gantt_task_link.finish_to_finish .gantt_link_arrow_left { border-right-color: #55d822; }
+.gantt_task_link.start_to_finish .gantt_line_wrapper div { background-color: #975000; }
+.gantt_task_link.start_to_finish:hover .gantt_line_wrapper div { box-shadow: 0 0 5px 0px #975000; }
+.gantt_task_link.start_to_finish .gantt_link_arrow_left { border-right-color: #975000; }
createLink('programplan', 'ajaxCustom'));?>
@@ -35,9 +58,15 @@ form {display: block; margin-top: 0em; margin-block-end: 1em;}
@@ -75,15 +104,14 @@ function drawGanttToCanvas(exportType, successCallback, errorCallback)
var $ganttContainer = $('#ganttContainer');
var $ganttDataArea = $ganttView.find('.gantt_data_area');
var $ganttDridData = $ganttView.find('.gantt_grid_data');
- var ganttHeight = $ganttView.find('.gantt_task_bg').outerHeight() + $ganttView.find('.gantt_grid_scale').outerHeight() + 1;
+
+ var ganttHeight = $ganttView.find('.gantt_grid_scale').outerHeight();
+ ganttHeight += * 25;
var ganttWidth = $ganttDridData.width() - 100;
- var ganttHeight = $ganttView.find('.gantt_grid_scale').outerHeight();
- $ganttDridData.find('.gantt_row').each(function() {ganttHeight += $(this).outerHeight();});
- var ganttWidth = $ganttDataArea.outerWidth() + $ganttDridData.outerWidth();
- var ganttHeight = $ganttView.find('.gantt_task_bg').outerHeight() + $ganttView.find('.gantt_grid_scale').outerHeight() + 1;
+ var ganttWidth = $ganttDataArea.outerWidth() + $ganttDridData.outerWidth();
$ganttContainer.css(
@@ -245,13 +273,14 @@ function updateCriticalPath()
$("#fullScreenBtn").on("click", function()
{
- $("#mainContent").css("z-index", "9999");
- $("#ganttView").css("z-index", "9999");
+ $("#mainContent").css("z-index", "5");
+ $("#ganttView").css("z-index", "5");
});
function exitHandler()
{
- if (module == 'review' && method == 'assess' && !document.fullscreenElement && !document.webkitIsFullScreen && !document.mozFullScreen && !document.msFullscreenElement) {
+ if (module == 'review' && method == 'assess' && !document.fullscreenElement && !document.webkitIsFullScreen && !document.mozFullScreen && !document.msFullscreenElement)
+ {
location.reload();
}
}
@@ -268,7 +297,7 @@ $(function()
$('#ganttView').css('height', Math.max(200, Math.floor($(window).height() - $('#footer').outerHeight() - $('#header').outerHeight() - $('#mainMenu').outerHeight() - 80)));
};
- var ganttData = $.parseJSON();
+ var ganttData = $.parseJSON();
if(!ganttData.data) ganttData.data = [];
gantt.config.readonly = true;
@@ -304,19 +333,7 @@ $(function()
if((module == 'review' && method == 'assess') || dateDetails)
{
- layout = gantt.config.layout;
-
- gantt.config.layout = {
- css: "gantt_container",
- cols: [
- {
- rows:[
- {view: "grid", scrollX: "gridScroll", scrollable: true, scrollY: "scrollVer"},
- {view: "scrollbar", id: "gridScroll", group:"horizontal"}
- ]
- }
- ]
- };
+ gantt.config.show_chart = false;
}
var date2Str = gantt.date.date_to_str(gantt.config.task_date);
@@ -329,11 +346,21 @@ $(function()
title: todayTips + ": " + date2Str(today)
});
+ gantt.templates.task_class = function(start, end, task){return 'pri-' + (task.pri || 0);};
gantt.templates.scale_cell_class = function(date)
{
if(date.getDay() == 0 || date.getDay() == 6) return 'weekend';
};
+ gantt.templates.link_class = function(link)
+ {
+ var types = gantt.config.links;
+ if(link.type == types.finish_to_start) return 'finish_to_start';
+ if(link.type == types.start_to_start) return 'start_to_start';
+ if(link.type == types.finish_to_finish) return 'finish_to_finish';
+ if(link.type == types.start_to_finish) return 'start_to_finish';
+ };
+
gantt.templates.timeline_cell_class = function(item, date)
{
if(date.getDay() == 0 || date.getDay() == 6) return 'weekend';