diff --git a/module/bug/js/batchcreate.js b/module/bug/js/batchcreate.js
index 07d1e30920..fd4a92d797 100644
--- a/module/bug/js/batchcreate.js
+++ b/module/bug/js/batchcreate.js
@@ -22,6 +22,7 @@ $(function()
var link = createLink('custom', 'ajaxSaveCustomFields', 'module=bug§ion=custom&key=batchCreateFields');
$.post(link, {'fields' : fields}, function()
{
+ showFields = fields;
showCheckedFields(fields);
$('#formSetting').parent().removeClass('open');
@@ -55,8 +56,6 @@ $(function()
*/
function showCheckedFields(fields)
{
- showFields = fields;
-
var fieldList = ',' + fields + ',';
$('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function()
{
@@ -77,22 +76,6 @@ function showCheckedFields(fields)
});
}
-/**
- * Hidden require field.
- *
- * @access public
- * @return void
- */
-function hiddenRequireFields()
-{
- $('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function()
- {
- var field = ',' + $(this).val() + ',';
- var required = ',' + requiredFields + ',';
- if(required.indexOf(field) >= 0) $(this).closest('div').addClass('hidden');
- });
-}
-
/**
* Set opened builds.
*
diff --git a/module/bug/js/batchedit.js b/module/bug/js/batchedit.js
index 26a3876963..42770c7cfc 100644
--- a/module/bug/js/batchedit.js
+++ b/module/bug/js/batchedit.js
@@ -72,4 +72,9 @@ $(document).on('change', 'select', function()
$(function()
{
$('#subNavbar li[data-id="bug"]').addClass('active');
+
+ $('#customField').click(function()
+ {
+ hiddenRequireFields();
+ });
});
diff --git a/module/bug/js/common.js b/module/bug/js/common.js
index 166e71d0d1..e100d8755c 100644
--- a/module/bug/js/common.js
+++ b/module/bug/js/common.js
@@ -887,20 +887,18 @@ function setBranchRelated(branchID, productID, num)
}
}
-$(document).ready(function()
+/**
+ * Hidden require field.
+ *
+ * @access public
+ * @return void
+ */
+function hiddenRequireFields()
{
- $('#customField').click(function()
+ $('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function()
{
- $('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function()
- {
- var field = ',' + $(this).val() + ',';
- var required = ',' + requiredFields + ',';
- if(required.indexOf(field) >= 0) $(this).attr('disabled', 'disabled');
- });
+ var field = ',' + $(this).val() + ',';
+ var required = ',' + requiredFields + ',';
+ if(required.indexOf(field) >= 0) $(this).closest('div').addClass('hidden');
});
-
- $('#formSettingForm .btn-primary').click(function()
- {
- $('#formSettingForm > .checkboxes > .checkbox-primary > input').removeAttr('disabled');
- });
-});
+}
diff --git a/module/bug/view/batchedit.html.php b/module/bug/view/batchedit.html.php
index 8562d126e3..625c95320d 100644
--- a/module/bug/view/batchedit.html.php
+++ b/module/bug/view/batchedit.html.php
@@ -13,6 +13,8 @@
lang->bug->dittoNotice);?>
+
+bug->edit->requiredFields);?>
bug->common . $lang->colon . $lang->bug->batchEdit;?>
diff --git a/module/bug/view/create.html.php b/module/bug/view/create.html.php
index db37565d41..aafefbfd9c 100644
--- a/module/bug/view/create.html.php
+++ b/module/bug/view/create.html.php
@@ -28,6 +28,7 @@ js::set('blockID', $blockID);
js::set('moduleID', $moduleID);
js::set('tab', $this->app->tab);
js::set('requiredFields', $config->bug->create->requiredFields);
+js::set('showFields', $showFields);
if($this->app->tab == 'execution') js::set('objectID', $executionID);
if($this->app->tab == 'project') js::set('objectID', $projectID);
?>
diff --git a/module/common/view/customfield.html.php b/module/common/view/customfield.html.php
index 2ccfe0b5d9..d7d158141a 100644
--- a/module/common/view/customfield.html.php
+++ b/module/common/view/customfield.html.php
@@ -37,7 +37,7 @@
var $formSetting = $('#formSetting');
$formSetting.on('click', '.close-dropdown', function()
{
- if(showFields != undefined)
+ if(typeof showFields != 'undefined')
{
var fieldList = ',' + showFields + ',';
$('#formSettingForm > .checkboxes > .checkbox-primary > input:visible').each(function()
diff --git a/module/execution/control.php b/module/execution/control.php
index 1cc1c84b54..e81ff05f8b 100644
--- a/module/execution/control.php
+++ b/module/execution/control.php
@@ -1324,12 +1324,16 @@ class execution extends control
list($begin, $end) = $this->execution->getBeginEnd4CFD($execution);
$dateList = date::getDateList($begin, $end, 'Y-m-d', '');
+ list($cycleTimeAvg, $throughput) = $this->execution->getCFDStatistics($executionID, $dateList, $type);
+
$this->view->title = $this->lang->execution->CFD;
$this->view->type = $type;
$this->view->execution = $execution;
$this->view->executionName = $execution->name;
$this->view->executionID = $executionID;
$this->view->chartData = $this->execution->buildCFDData($executionID, $dateList, $type);
+ $this->view->cycleTimeAvg = $cycleTimeAvg;
+ $this->view->throughput = $throughput;
$this->display();
}
diff --git a/module/execution/css/cfd.css b/module/execution/css/cfd.css
index fd514e009f..a4b56cf4df 100644
--- a/module/execution/css/cfd.css
+++ b/module/execution/css/cfd.css
@@ -1,6 +1,21 @@
.main-content > h2 {font-size: 16px;}
-#cfdWrapper {max-width: 1400px; margin: 0 auto; padding: 25px 100px 10px; position: relative;}
-#cfdYUnit {position: absolute; color: #CBD0DB; top: 27px; left: 130px;}
-#cfdXUnit {position: absolute; color: #CBD0DB; bottom: 35px; right: 60px;}
.pull-left .input-control {margin-right: 10px;}
+
+@media screen and (max-width: 1920px)
+{
+#cfdWrapper {max-width: 1400px; margin: 0 auto; padding: 25px 0px 10px; position: relative}
+#cfdChart {width:1400px !important; height:600px !important}
+#cfdYUnit {position: absolute; color: #CBD0DB; top: 40px; left: 30px}
+#cfdXUnit {position: absolute; color: #CBD0DB; bottom: 20px; right: 0px}
+}
+@media screen and (max-width: 1366px)
+{
+#cfdChart {width:1150px !important; height:400px !important};
+}
+
+#mainContent {min-width: 1400px;}
+#burnStatistics {position: absolute; left: 1200px; width: 180px; height: 200px; top: 20%; margin-top: -30px; line-height: 30px; color: #838A9D; font-size: 12px; border: 1px solid #dcdcdc; background-color: #F8F8F8; padding: 15px 20px; color: #3c4353; border-radius: 8px;}
+#burnStatistics .bg-primary {margin-right: 5px;}
+#burnStatistics .icon-help {color: black;}
+#burnStatistics h3 {margin-top: 10px; text-indent: 10px; margin-bottom: 30px;}
\ No newline at end of file
diff --git a/module/execution/css/cfd.zh-cn.css b/module/execution/css/cfd.zh-cn.css
new file mode 100644
index 0000000000..10fd34d04a
--- /dev/null
+++ b/module/execution/css/cfd.zh-cn.css
@@ -0,0 +1 @@
+#burnStatistics {width : 160px;}
diff --git a/module/execution/js/cfd.js b/module/execution/js/cfd.js
index e69de29bb2..58c7daec4d 100644
--- a/module/execution/js/cfd.js
+++ b/module/execution/js/cfd.js
@@ -0,0 +1,95 @@
+$(function()
+{
+ $('[data-toggle=tooltip]').tooltip();
+
+ if(chartData)
+ {
+ var i = 0;
+ var series = [];
+ var colors = ['#33B4DB', '#7ECF69', '#FFC73A', '#FF5A61', '#50C8D0', '#AF5AFF', '#4EA3FF', '#FF8C5A', '#6C73FF'];
+ //var background = ['#E1F4FA', '#ECF8E9', '#FFF7E2', '#FFE7E8', '#E5F7F8', '#F3E7FF', '#E5F1FF', '#FFEEE7', '#E9EAFF'];
+
+ $.each(chartData['line'], function(label, set)
+ {
+ series.push({
+ name: label,
+ type: 'line',
+ stack: 'Total',
+ color: colors[i],
+ areaStyle: {
+ color: colors[i],
+ opacity: 0.2
+ },
+ emphasis: {
+ focus: 'series'
+ },
+ data: eval(set)
+ })
+ i ++;
+ })
+
+ var chartDom = document.getElementById('cfdChart');
+ var CFD = echarts.init(chartDom);
+ var option;
+
+ option = {
+ tooltip: {
+ trigger: 'axis',
+ axisPointer: {
+ type: 'cross',
+ label: {
+ backgroundColor: '#6a7985'
+ }
+ }
+ },
+ legend: {
+ data: Object.keys(chartData['line'])
+ },
+ grid: {
+ left: '3%',
+ right: '4%',
+ bottom: '3%',
+ containLabel: true
+ },
+ xAxis: [
+ {
+ type: 'category',
+ boundaryGap: false,
+ data: chartData['labels'],
+ axisLine:
+ {
+ show: true,
+ lineStyle:
+ {
+ color: '#999',
+ width:1
+ }
+ }
+ }],
+ yAxis: [
+ {
+ type: 'value',
+ minInterval: 1,
+ axisLine:
+ {
+ show: true,
+ lineStyle:
+ {
+ color: ['#999'],
+ width: 1
+ }
+ }
+ }
+ ],
+ series: series,
+ };
+
+ option && CFD.setOption(option);
+ window.addEventListener('resize', CFD.resize);
+ }
+
+ $('#type').change(function()
+ {
+ location.href = createLink('execution', 'cfd', 'executionID=' + executionID + '&type=' + $(this).val());
+ });
+});
diff --git a/module/execution/lang/de.php b/module/execution/lang/de.php
index 41d14ce627..7ebbf823ef 100644
--- a/module/execution/lang/de.php
+++ b/module/execution/lang/de.php
@@ -412,6 +412,7 @@ $lang->execution->ge = "『%s』should be >= actual beg
$lang->execution->storyDragError = "The {$lang->SRCommon} is still a draft or has been changed, please drag it after the review";
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
+$lang->execution->week = 'week';
/* Statistics. */
$lang->execution->charts = new stdclass();
@@ -429,6 +430,12 @@ $lang->execution->charts->burn->graph->reference = 'Referenz';
$lang->execution->charts->burn->graph->actuality = 'Aktualität';
$lang->execution->charts->burn->graph->delay = 'Delay';
+$lang->execution->charts->cfd = new stdclass();
+$lang->execution->charts->cfd->cycleTime = 'Average cycle time';
+$lang->execution->charts->cfd->cycleTimeTip = 'Average cycle time of each card from development start to completion';
+$lang->execution->charts->cfd->throughput = 'Throughput Rate';
+$lang->execution->charts->cfd->throughputTip = 'Throughput Rate = WIP / Average cycle time';
+
$lang->execution->placeholder = new stdclass();
$lang->execution->placeholder->code = 'Abkurzung des Projektnamens';
$lang->execution->placeholder->totalLeft = 'Schätzungen zu Beginn des Projekts.';
diff --git a/module/execution/lang/en.php b/module/execution/lang/en.php
index 9595d15d66..3d8b3f8888 100644
--- a/module/execution/lang/en.php
+++ b/module/execution/lang/en.php
@@ -412,6 +412,7 @@ $lang->execution->ge = "『%s』should be >= actual beg
$lang->execution->storyDragError = "The {$lang->SRCommon} is still a draft or has been changed, please drag it after the review";
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
+$lang->execution->week = 'week';
/* Statistics. */
$lang->execution->charts = new stdclass();
@@ -429,6 +430,12 @@ $lang->execution->charts->burn->graph->reference = 'Ideal';
$lang->execution->charts->burn->graph->actuality = 'Actual';
$lang->execution->charts->burn->graph->delay = 'Delay';
+$lang->execution->charts->cfd = new stdclass();
+$lang->execution->charts->cfd->cycleTime = 'Average cycle time';
+$lang->execution->charts->cfd->cycleTimeTip = 'Average cycle time of each card from development start to completion';
+$lang->execution->charts->cfd->throughput = 'Throughput Rate';
+$lang->execution->charts->cfd->throughputTip = 'Throughput Rate = WIP / Average cycle time';
+
$lang->execution->placeholder = new stdclass();
$lang->execution->placeholder->code = "Abbreviation of {$lang->executionCommon} name";
$lang->execution->placeholder->totalLeft = "Hours estimated on the first day of the {$lang->executionCommon}.";
diff --git a/module/execution/lang/fr.php b/module/execution/lang/fr.php
index 984b261d54..ca0ae9c74a 100644
--- a/module/execution/lang/fr.php
+++ b/module/execution/lang/fr.php
@@ -415,6 +415,7 @@ $lang->execution->ge = "『%s』should be >= actual beg
$lang->execution->storyDragError = "The {$lang->SRCommon} is still a draft or has been changed, please drag it after the review";
$lang->execution->countTip = ' (%s member)';
$lang->execution->pleaseInput = "Enter";
+$lang->execution->week = 'week';
/* Statistics. */
$lang->execution->charts = new stdclass();
@@ -432,6 +433,12 @@ $lang->execution->charts->burn->graph->reference = 'Idéal';
$lang->execution->charts->burn->graph->actuality = 'Actuel';
$lang->execution->charts->burn->graph->delay = 'Delay';
+$lang->execution->charts->cfd = new stdclass();
+$lang->execution->charts->cfd->cycleTime = 'Average cycle time';
+$lang->execution->charts->cfd->cycleTimeTip = 'Average cycle time of each card from development start to completion';
+$lang->execution->charts->cfd->throughput = 'Throughput Rate';
+$lang->execution->charts->cfd->throughputTip = 'Throughput Rate = WIP / Average cycle time';
+
$lang->execution->placeholder = new stdclass();
$lang->execution->placeholder->code = "Abréviation du nom du {$lang->executionCommon}";
$lang->execution->placeholder->totalLeft = "Heures estimées le premier jour du {$lang->executionCommon}.";
diff --git a/module/execution/lang/zh-cn.php b/module/execution/lang/zh-cn.php
index 4438833e1e..1586eb9f0b 100644
--- a/module/execution/lang/zh-cn.php
+++ b/module/execution/lang/zh-cn.php
@@ -412,6 +412,7 @@ $lang->execution->ge = "『%s』应当不小于实际
$lang->execution->storyDragError = "该{$lang->SRCommon}还是草稿或已变更状态,请评审通过后再拖动";
$lang->execution->countTip = '(%s人)';
$lang->execution->pleaseInput = "请输入";
+$lang->execution->week = '周';
/* 统计。*/
$lang->execution->charts = new stdclass();
@@ -429,6 +430,12 @@ $lang->execution->charts->burn->graph->reference = '参考';
$lang->execution->charts->burn->graph->actuality = '实际';
$lang->execution->charts->burn->graph->delay = '延期';
+$lang->execution->charts->cfd = new stdclass();
+$lang->execution->charts->cfd->cycleTime = '平均周期时间';
+$lang->execution->charts->cfd->cycleTimeTip = '平均每个卡片从开发启动到完成的周期时间';
+$lang->execution->charts->cfd->throughput = '吞吐率';
+$lang->execution->charts->cfd->throughputTip = '吞吐率 = 在制品 / 平均周期时间';
+
$lang->execution->placeholder = new stdclass();
$lang->execution->placeholder->code = '团队内部的简称';
$lang->execution->placeholder->totalLeft = "{$lang->executionCommon}开始时的总预计工时";
diff --git a/module/execution/model.php b/module/execution/model.php
index 5a82330dfb..b4e6f3e89f 100644
--- a/module/execution/model.php
+++ b/module/execution/model.php
@@ -3094,8 +3094,8 @@ class executionModel extends model
/**
* Get begin and end for CFD.
- *
- * @param object $execution
+ *
+ * @param object $execution
* @access public
* @return void
*/
@@ -3110,12 +3110,12 @@ class executionModel extends model
}
elseif((helper::today() >= $execution->begin) and (helper::today() <= $execution->end))
{
- $begin = (date('Y-m-d', strtotime('-14 days')) < $execution->begin) ? $execution->begin : date('Y-m-d', strtotime('-14 days'));
+ $begin = (date('Y-m-d', strtotime('-13 days')) < $execution->begin) ? $execution->begin : date('Y-m-d', strtotime('-13 days'));
$end = helper::today();
}
elseif((helper::today() > $execution->end))
{
- $begin = date($execution->end, strtotime('-14 days')) > $execution->begin ? date($execution->end, strtotime('-14 days')) : $execution->begin;
+ $begin = date($execution->end, strtotime('-13 days')) > $execution->begin ? date($execution->end, strtotime('-13 days')) : $execution->begin;
$end = $execution->end;
}
@@ -3236,7 +3236,7 @@ class executionModel extends model
/**
* Build CFD data.
- *
+ *
* @param int $executionID
* @param string $type
* @param array $dateList
@@ -3294,6 +3294,44 @@ class executionModel extends model
return $data;
}
+ /**
+ * Get CFD statistics.
+ *
+ * @param int $executionID
+ * @param array $dateList
+ * @param string $type
+ * @access public
+ * @return void
+ */
+ public function getCFDStatistics($executionID, $dateList, $type)
+ {
+ $kanbanData = $this->loadModel('kanban')->getRDKanban($executionID, $type);
+ $kanbanData = array_shift($kanbanData);
+
+ $cycleTime = array();
+ foreach($kanbanData->groups as $group)
+ {
+ foreach($group->lanes as $lane)
+ {
+ if(!isset($lane->items['closed'])) continue;
+
+ foreach($lane->items['closed'] as $item)
+ {
+ $diffTime = $type == 'story' ? strtotime($item['lastEditedDate']) - strtotime($item['openedDate']) : strtotime($item['closedDate']) - strtotime($item['openedDate']);
+ $day = floor($diffTime / (3600 * 24));
+ if($day > 0) $cycleTime[$item['id']] = $day;
+ }
+ }
+ }
+
+ $itemCount = count($cycleTime);
+ if(!$itemCount) return array('', '');
+ $cycleTimeAvg = round(array_sum($cycleTime) / $itemCount);
+ $throughput = round(($itemCount * 7) / $cycleTimeAvg, 1) . "{$this->lang->execution->kanbanCardsUnit}/" . $this->lang->execution->week;
+
+ return array($cycleTimeAvg, $throughput);
+ }
+
/**
* Get taskes by search.
*
diff --git a/module/execution/view/cfd.html.php b/module/execution/view/cfd.html.php
index ee86dc4d81..57c8e38580 100644
--- a/module/execution/view/cfd.html.php
+++ b/module/execution/view/cfd.html.php
@@ -14,6 +14,7 @@
+
execution->count;?>
execution->burnXUnit;?>
+
+
execution->charts->cfd->cycleTime;?>
+
day) : $lang->noData;?>
+
execution->charts->cfd->throughput;?>
+
noData;?>
+
-
-
-
-
-
diff --git a/module/index/js/index.js b/module/index/js/index.js
index 3963a1a809..d8dfe59d94 100644
--- a/module/index/js/index.js
+++ b/module/index/js/index.js
@@ -461,6 +461,7 @@
if(!notTriggerEvent) app.$app.trigger('reloadapp', app);
+ if(url) $(iframe.contentWindow.document.body).hide(); // Code for task #59703.
app.$app.addClass('loading');
if(app._loadTimer) clearTimeout(app._loadTimer);
app._loadTimer = setTimeout(function()
diff --git a/module/kanban/model.php b/module/kanban/model.php
index 248dce117b..c246cd74a1 100644
--- a/module/kanban/model.php
+++ b/module/kanban/model.php
@@ -1302,16 +1302,19 @@ class kanbanModel extends model
if(empty($object)) continue;
- $cardData['id'] = $object->id;
- $cardData['order'] = $cardOrder++;
- $cardData['pri'] = $object->pri ? $object->pri : '';
- $cardData['estimate'] = $cell->type == 'bug' ? '' : $object->estimate;
- $cardData['assignedTo'] = $object->assignedTo;
- $cardData['deadline'] = $cell->type == 'story' ? '' : $object->deadline;
- $cardData['severity'] = $cell->type == 'bug' ? $object->severity : '';
- $cardData['acl'] = 'open';
- $cardData['lane'] = $laneID;
- $cardData['column'] = $cell->column;
+ $cardData['id'] = $object->id;
+ $cardData['order'] = $cardOrder++;
+ $cardData['pri'] = $object->pri ? $object->pri : '';
+ $cardData['estimate'] = $cell->type == 'bug' ? '' : $object->estimate;
+ $cardData['assignedTo'] = $object->assignedTo;
+ $cardData['deadline'] = $cell->type == 'story' ? '' : $object->deadline;
+ $cardData['severity'] = $cell->type == 'bug' ? $object->severity : '';
+ $cardData['acl'] = 'open';
+ $cardData['lane'] = $laneID;
+ $cardData['column'] = $cell->column;
+ $cardData['openedDate'] = $object->openedDate;
+ $cardData['closedDate'] = $object->closedDate;
+ $cardData['lastEditedDate'] = $object->lastEditedDate;
if($cell->type == 'task')
{
diff --git a/module/search/control.php b/module/search/control.php
index 22e5935e0e..ab95db6333 100644
--- a/module/search/control.php
+++ b/module/search/control.php
@@ -60,7 +60,7 @@ class search extends control
$this->view->searchFields = $fields;
$this->view->actionURL = $actionURL;
$this->view->fieldParams = $this->search->setDefaultParams($fields, $params);
- $this->view->queries = $this->search->getQueryPairs($module);
+ $this->view->queries = $this->search->getQueryList($module);
$this->view->queryID = $queryID;
$this->view->style = empty($style) ? 'full' : $style;
$this->view->onMenuBar = empty($onMenuBar) ? 'no' : $onMenuBar;
@@ -148,13 +148,13 @@ class search extends control
{
$query = $queryID ? $queryID : '';
$module = empty($module) ? $this->session->searchParams['module'] : $module;
- $queries = $this->search->getQueryPairs($module);
-
+ $queries = $this->search->getQueryList($module);
$html = '';
- foreach($queries as $queryID => $queryName)
+ foreach($queries as $query)
{
- if(empty($queryID)) continue;
- $html .= '
' . html::a("javascript:executeQuery({$queryID})", $queryName . (common::hasPriv('search', 'deleteQuery') ? '' : ''), '', "class='label user-query' data-query-id='$queryID'") . '';
+ if(empty($query->id)) continue;
+
+ $html .= '
' . html::a("javascript:executeQuery({$query->id})", $query->title . ((common::hasPriv('search', 'deleteQuery') and $this->app->user->account == $query->account) ? '' : ''), '', "class='label user-query' data-query-id='$query->id' title='{$query->title}'") . '';
}
echo $html;
}
diff --git a/module/search/model.php b/module/search/model.php
index eb39f7832f..7896fc839b 100644
--- a/module/search/model.php
+++ b/module/search/model.php
@@ -439,6 +439,30 @@ class searchModel extends model
return $queries;
}
+ /**
+ * Get query list.
+ *
+ * @param string $module
+ * @access public
+ * @return array
+ */
+ public function getQueryList($module)
+ {
+ $queries = $this->dao->select('id, account, title')
+ ->from(TABLE_USERQUERY)
+ ->where()
+ ->markLeft(1)
+ ->where('account')->eq($this->app->user->account)
+ ->orWhere('common')->eq(1)
+ ->markRight(1)
+ ->andWhere('module')->eq($module)
+ ->orderBy('id_desc')
+ ->fetchAll();
+ if(!$queries) return array('' => $this->lang->search->myQuery);
+ $queries = array('' => $this->lang->search->myQuery) + $queries;
+ return $queries;
+ }
+
/**
* Get records by the condition.
*
diff --git a/module/search/view/buildform.html.php b/module/search/view/buildform.html.php
index f8b92d3422..4010442081 100644
--- a/module/search/view/buildform.html.php
+++ b/module/search/view/buildform.html.php
@@ -227,10 +227,9 @@ foreach($fieldParams as $fieldName => $param)
search->savedQuery;?>
- $queryName):?>
-
- search->getByID($queryID);?>
- - app->user->account == $query->account) ? '' : ''), '', "class='label user-query' data-query-id='$queryID' title='{$queryName}'");?>
+
+ id)) continue;?>
+ - id)", $query->title . ((common::hasPriv('search', 'deleteQuery') and $this->app->user->account == $query->account) ? '' : ''), '', "class='label user-query' data-query-id='$query->id' title='{$query->title}'");?>
|
diff --git a/module/story/model.php b/module/story/model.php
index e514fcb1da..175726a30b 100644
--- a/module/story/model.php
+++ b/module/story/model.php
@@ -3927,7 +3927,7 @@ class storyModel extends model
if($story->stage == 'projected') $title = $this->lang->story->subDivideTip['projected'];
}
}
- $menu .= $this->buildMenu('story', 'batchCreate', "productID=$story->product&branch=$story->branch&module=$story->module&$params&executionID={$this->session->project}", $story, $type, 'split', '', 'showinonlybody', '', '', $title);
+ $menu .= $this->buildMenu('story', 'batchCreate', "productID=$story->product&branch=$story->branch&module=$story->module&$params&executionID={$this->session->project}&plan={$story->plan}&type={$story->type}", $story, $type, 'split', '', 'showinonlybody', '', '', $title);
}
if($this->app->rawModule == 'projectstory' and $this->config->vision != 'lite') $menu .= $this->buildMenu('projectstory', 'unlinkStory', "projectID={$this->session->project}&$params", $story, $type, 'unlink', 'hiddenwin', 'showinonlybody');
@@ -4089,7 +4089,11 @@ class storyModel extends model
foreach($stories as $story)
{
- if(!isset($group[$story->id])) continue;
+ if(!isset($group[$story->id]))
+ {
+ unset($stories[$story->id]);
+ continue;
+ }
$story->children = $this->getByList($group[$story->id]);
}
}
@@ -4373,7 +4377,7 @@ class storyModel extends model
{
$showBranch = isset($this->config->product->browse->showBranch) ? $this->config->product->browse->showBranch : 1;
}
- if($storyType == 'requirement') echo '
SR ';
+ if($storyType == 'requirement') echo '
' .$this->lang->story->childrenAB. ' ';
if($story->parent > 0 and isset($story->parentName)) $story->title = "{$story->parentName} / {$story->title}";
if(isset($branches[$story->branch]) and $showBranch and $this->config->vision == 'rnd') echo "
branch]}>{$branches[$story->branch]} ";
if($story->module and isset($modulePairs[$story->module])) echo "
{$modulePairs[$story->module]} ";
diff --git a/module/task/js/batchcreate.js b/module/task/js/batchcreate.js
index b5fa1c0978..e5503a3714 100755
--- a/module/task/js/batchcreate.js
+++ b/module/task/js/batchcreate.js
@@ -23,6 +23,7 @@ $(function()
var link = createLink('custom', 'ajaxSaveCustomFields', 'module=task§ion=custom&key=batchCreateFields');
$.post(link, {'fields' : fields}, function()
{
+ showFields = fields;
showCheckedFields(fields);
$('#formSetting').parent().removeClass('open');
diff --git a/module/task/js/batchedit.js b/module/task/js/batchedit.js
index 32dd170945..73af9a1c12 100644
--- a/module/task/js/batchedit.js
+++ b/module/task/js/batchedit.js
@@ -49,4 +49,9 @@ $(document).on('change', 'select', function()
$(function()
{
$('#subNavbar li[data-id="task"]').addClass('active');
+
+ $('#customField').click(function()
+ {
+ hiddenRequireFields();
+ });
});
diff --git a/module/task/js/common.js b/module/task/js/common.js
index 0d683835b2..fe129b6afe 100644
--- a/module/task/js/common.js
+++ b/module/task/js/common.js
@@ -29,8 +29,6 @@ function setStoryModule()
*/
function showCheckedFields(fields)
{
- showFields = fields;
-
var fieldList = ',' + fields + ',';
$('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function()
{
diff --git a/module/task/view/batchedit.html.php b/module/task/view/batchedit.html.php
index 67e01fe081..611ddbb728 100755
--- a/module/task/view/batchedit.html.php
+++ b/module/task/view/batchedit.html.php
@@ -15,6 +15,8 @@
lang->task->dittoNotice, $lang->executionCommon);
js::set('dittoNotice', $dittoNotice);
+js::set('showFields', $showFields);
+js::set('requiredFields', $config->task->edit->requiredFields);
?>
diff --git a/module/testcase/css/batchcreate.css b/module/testcase/css/batchcreate.css
index 2704eb6794..993b9e8647 100644
--- a/module/testcase/css/batchcreate.css
+++ b/module/testcase/css/batchcreate.css
@@ -9,8 +9,10 @@
#batchCreateForm .input-group .colorpicker.open {z-index: 5;}
.c-id {width: 50px;}
-.c-pri, .c-keywords, .c-review {width: 100px;}
+.c-pri, .c-keywords {width: 100px;}
.c-branch, .c-type {width: 120px;}
.c-stage {width: 140px;}
.c-precondition {width: 150px;}
.c-story {width: 180px;}
+.c-review{width: 105px;}
+.c-actions {width: 60px;}
diff --git a/module/testcase/css/create.css b/module/testcase/css/create.css
index c11942bc27..2ad82ff52e 100644
--- a/module/testcase/css/create.css
+++ b/module/testcase/css/create.css
@@ -40,5 +40,6 @@
.title-group.required > .required:after {display: block; right: 29px; top: 5px;}
.pri-selector > .btn {padding: 5px 8px !important; width: 100%;}
.pri-selector > .dropdown-menu {padding: 10px;}
+.stageBox {padding-left: 15px !important;}
-#refresh {margin-left: 7px;}
+#refresh {margin-left: 7px;}
\ No newline at end of file
diff --git a/module/testcase/js/batchcreate.js b/module/testcase/js/batchcreate.js
index 8a788bd65a..055bf93804 100644
--- a/module/testcase/js/batchcreate.js
+++ b/module/testcase/js/batchcreate.js
@@ -29,16 +29,73 @@ $(document).ready(function()
$('#customField').click(function()
{
- $('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function()
- {
- var field = ',' + $(this).val() + ',';
- var required = ',' + requiredFields + ',';
- if(required.indexOf(field) >= 0) $(this).attr('disabled', 'disabled');
- });
+ hiddenRequireFields();
});
+ /* Implement a custom form without feeling refresh. */
$('#formSettingForm .btn-primary').click(function()
{
- $('#formSettingForm > .checkboxes > .checkbox-primary > input').removeAttr('disabled');
+ var fields = '';
+ $('#formSettingForm > .checkboxes > .checkbox-primary > input:checked').each(function()
+ {
+ fields += ',' + $(this).val();
+ });
+
+ var link = createLink('custom', 'ajaxSaveCustomFields', 'module=testcase§ion=custom&key=batchCreateFields');
+ $.post(link, {'fields' : fields}, function()
+ {
+ showCheckedFields(fields);
+ $('#formSetting').parent().removeClass('open');
+
+ var fieldCount = $('#batchCreateForm .table thead>tr>th:visible').length;
+ $('.form-actions').attr('colspan', fieldCount);
+
+ if(fieldCount > 8)
+ {
+ $('#batchCreateForm > .table-responsive').removeClass('scroll-none');
+ $('#batchCreateForm > .table-responsive').css('overflow', 'auto');
+ }
+ else
+ {
+ $('#batchCreateForm > .table-responsive').addClass('scroll-none');
+ $('#batchCreateForm > .table-responsive').css('overflow', 'visible');
+ }
+
+ if($('#batchCreateForm table thead tr th.c-title').width() < 170) $('#batchCreateForm table thead tr th.c-title').width('170');
+ });
+
+ return false;
});
});
+
+/**
+ * Add item.
+ *
+ * @param object $obj
+ * @access public
+ * @return void
+ */
+function addItem(obj)
+{
+ var item = $('#addItem').html().replace(/%i%/g, itemIndex + 1);
+ $('
' + item + '
').insertAfter($(obj).closest('tr'));
+
+ $(obj).closest('tr').next().find('div[id$=_chosen]').remove();
+ $(obj).closest('tr').next().find('.picker').remove();
+ $(obj).closest('tr').next().find('.chosen').chosen();
+ $(obj).closest('tr').next().find('.picker-select').picker();
+
+ itemIndex ++;
+}
+
+/**
+ * Delete item.
+ *
+ * @param object $obj
+ * @access public
+ * @return void
+ */
+function deleteItem(obj)
+{
+ $(obj).closest('tr').remove();
+}
diff --git a/module/testcase/js/batchedit.js b/module/testcase/js/batchedit.js
index 280f5d2e45..e82c364e91 100644
--- a/module/testcase/js/batchedit.js
+++ b/module/testcase/js/batchedit.js
@@ -116,17 +116,7 @@ $(function()
$('#customField').click(function()
{
- $('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function()
- {
- var field = ',' + $(this).val() + ',';
- var required = ',' + requiredFields + ',';
- if(required.indexOf(field) >= 0) $(this).attr('disabled', 'disabled');
- });
- });
-
- $('#formSettingForm .btn-primary').click(function()
- {
- $('#formSettingForm > .checkboxes > .checkbox-primary > input').removeAttr('disabled');
+ hiddenRequireFields();
});
});
diff --git a/module/testcase/js/common.js b/module/testcase/js/common.js
index e15400f349..cd380b77b7 100644
--- a/module/testcase/js/common.js
+++ b/module/testcase/js/common.js
@@ -370,7 +370,7 @@ function loadStories(productID, moduleID, num)
if(!stories) stories = '
';
if(config.currentMethod == 'batchcreate')
{
- for(var i = num; i < 10 ; i ++)
+ for(var i = num; i <= itemIndex ; i ++)
{
if(i != num && $('#module' + i).val() != 'ditto') break;
var nowStories = stories.replaceAll('story' + num, 'story' + i);
@@ -426,3 +426,50 @@ function setModules(branchID, productID, num)
$('#plan' + (num + 1)).trigger("chosen:updated");
}
}
+
+/**
+ * Show checked fields.
+ *
+ * @param string fields
+ * @access public
+ * @return void
+ */
+function showCheckedFields(fields)
+{
+ showFields = fields;
+
+ var fieldList = ',' + fields + ',';
+ $('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function()
+ {
+ var field = ',' + $(this).val() + ',';
+ var $field = config.currentMethod == 'create' ? $('#' + $(this).val()) : $('[name^=' + $(this).val() + ']');
+ var required = ',' + requiredFields + ',';
+ var $fieldBox = $('.' + $(this).val() + 'Box' );
+ if(fieldList.indexOf(field) >= 0 || required.indexOf(field) >= 0)
+ {
+ $fieldBox.removeClass('hidden');
+ $field.removeAttr('disabled');
+ }
+ else if(!$fieldBox.hasClass('hidden'))
+ {
+ $fieldBox.addClass('hidden');
+ $field.attr('disabled', true);
+ }
+ });
+}
+
+/**
+ * Hidden require field.
+ *
+ * @access public
+ * @return void
+ */
+function hiddenRequireFields()
+{
+ $('#formSettingForm > .checkboxes > .checkbox-primary > input').each(function()
+ {
+ var field = ',' + $(this).val() + ',';
+ var required = ',' + requiredFields + ',';
+ if(required.indexOf(field) >= 0) $(this).closest('div').addClass('hidden');
+ });
+}
diff --git a/module/testcase/js/create.js b/module/testcase/js/create.js
index 5a525a8ba6..9acacae0da 100644
--- a/module/testcase/js/create.js
+++ b/module/testcase/js/create.js
@@ -156,4 +156,28 @@ $(function()
});
$('#subNavbar li[data-id="testcase"]').addClass('active');
+
+ $('#customField').click(function()
+ {
+ hiddenRequireFields();
+ });
+
+ /* Implement a custom form without feeling refresh. */
+ $('#formSettingForm .btn-primary').click(function()
+ {
+ var fields = '';
+ $('#formSettingForm > .checkboxes > .checkbox-primary > input:checked').each(function()
+ {
+ fields += ',' + $(this).val();
+ });
+
+ var link = createLink('custom', 'ajaxSaveCustomFields', 'module=testcase§ion=custom&key=createFields');
+ $.post(link, {'fields' : fields}, function()
+ {
+ showCheckedFields(fields);
+ $('#formSetting').parent().removeClass('open');
+ });
+
+ return false;
+ });
});
diff --git a/module/testcase/view/batchcreate.html.php b/module/testcase/view/batchcreate.html.php
index 0584fdb584..1362b59908 100644
--- a/module/testcase/view/batchcreate.html.php
+++ b/module/testcase/view/batchcreate.html.php
@@ -15,6 +15,7 @@
testcase->create->requiredFields)?>
+
@@ -54,16 +55,16 @@
| idAB;?> |
- '>product->branch;?> |
- '>testcase->module;?> |
- '> testcase->story;?> |
+ branchBox'>product->branch;?> |
+ moduleBox'>testcase->module;?> |
+ storyBox'> testcase->story;?> |
testcase->title;?> |
testcase->type;?> |
- '>testcase->pri;?> |
- '>testcase->precondition;?> |
- '>testcase->keywords;?> |
- '>testcase->stage;?> |
- '>testcase->review;?> |
+ priBox'>testcase->pri;?> |
+ preconditionBox'>testcase->precondition;?> |
+ keywordsBox'>testcase->keywords;?> |
+ stageBox'>testcase->stage;?> |
+ reviewBox'>testcase->review;?> |
testcase->getFlowExtendFields();
foreach($extendFields as $extendField)
@@ -72,23 +73,24 @@
echo "{$extendField->name} | ";
}
?>
+ actions;?> |
testcase->typeList['']);?>
- testcase->batchCreate; $i++):?>
+ testcase->batchCreate; $i++):?>
testcase->typeList['ditto'] = $lang->testcase->ditto;
- if($i != 0) $lang->testcase->priList['ditto'] = $lang->testcase->ditto;
- $type = $i == 0 ? 'feature' : 'ditto';
- $pri = $i == 0 ? 3 : 'ditto';
+ if($i != 1) $currentModuleID = 'ditto';
+ if($i != 1) $lang->testcase->typeList['ditto'] = $lang->testcase->ditto;
+ if($i != 1) $lang->testcase->priList['ditto'] = $lang->testcase->ditto;
+ $type = $i == 1 ? 'feature' : 'ditto';
+ $pri = $i == 1 ? 3 : 'ditto';
?>
- |
- '> |
- ' style='overflow:visible'> |
- ' style='overflow:visible'> id : '', 'class="form-control chosen"');?> |
+ |
+ branchBox'> |
+ moduleBox' style='overflow:visible'> |
+ storyBox' style='overflow:visible'> id : '', 'class="form-control chosen"');?> |
@@ -102,15 +104,21 @@
|
testcase->typeList, $type, "class='form-control chosen'");?> |
- '> testcase->priList, $pri, "class='form-control chosen'");?> |
- '> |
- '> |
- ' style='overflow:visible'>testcase->stageList, '', "class='form-control chosen' multiple");?> |
- '>testcase->reviewList, $needReview, "class='form-control'");?> |
+ priBox'>testcase->priList, $pri, "class='form-control chosen'");?> |
+ preconditionBox'> |
+ keywordsBox'> |
+ stageBox' style='overflow:visible'>testcase->stageList, '', "class='form-control chosen' multiple");?> |
+ reviewBox'>testcase->reviewList, $needReview, "class='form-control chosen'");?> |
loadModel('flow');
foreach($extendFields as $extendField) echo "control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[$i]") . " | ";
?>
+
+
+
+
+
+ |
@@ -126,13 +134,14 @@
+
| %s |
- '> |
- ' style='overflow:visible'> |
- ' style='overflow:visible'> |
+ branchBox'> |
+ moduleBox' style='overflow:visible'> |
+ storyBox' style='overflow:visible'> |
@@ -146,17 +155,60 @@
|
testcase->typeList, $type, "class='form-control chosen'");?> |
- '> testcase->priList, $pri, "class='form-control chosen'");?> |
- '> |
- '> |
- ' style='overflow:visible'>testcase->stageList, '', "class='form-control chosen' multiple");?> |
- '>testcase->reviewList, $needReview, "class='form-control chosen'");?> |
+ priBox'>testcase->priList, $pri, "class='form-control chosen'");?> |
+ preconditionBox'> |
+ keywordsBox'> |
+ stageBox' style='overflow:visible'>testcase->stageList, '', "class='form-control chosen' multiple");?> |
+ reviewBox'>testcase->reviewList, $needReview, "class='form-control chosen'");?> |
loadModel('flow');
foreach($extendFields as $extendField) echo "control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[%s]") . " | ";
?>
+
+
+
+
+
+ |
+
+
+
+
+ |
+ branchBox'> |
+ moduleBox' style='overflow:visible'> |
+ storyBox' style='overflow:visible'> id : '', 'class="form-control chosen"');?> |
+
+
+ |
+ testcase->typeList, $type, "class='form-control chosen'");?> |
+ priBox'>testcase->priList, $pri, "class='form-control chosen'");?> |
+ preconditionBox'> |
+ keywordsBox'> |
+ stageBox' style='overflow:visible'>testcase->stageList, '', "class='form-control chosen' multiple");?> |
+ reviewBox'>testcase->reviewList, $needReview, "class='form-control chosen'");?> |
+ loadModel('flow');
+ foreach($extendFields as $extendField) echo "control == 'select' or $extendField->control == 'multi-select') ? " style='overflow:visible'" : '') . ">" . $this->flow->getFieldControl($extendField, '', $extendField->field . "[$i]") . " | ";
+ ?>
+
+
+
+ |
+
+
+
diff --git a/module/testcase/view/batchedit.html.php b/module/testcase/view/batchedit.html.php
index d2427ba8a4..a3a38b0cf0 100644
--- a/module/testcase/view/batchedit.html.php
+++ b/module/testcase/view/batchedit.html.php
@@ -17,6 +17,7 @@
testcase->confirmUnlinkTesttask);?>
testcase->edit->requiredFields)?>
+
testcase->common . $lang->colon . $lang->testcase->batchEdit;?>
diff --git a/module/testcase/view/create.html.php b/module/testcase/view/create.html.php
index dcf447e638..4bfecdb21c 100644
--- a/module/testcase/view/create.html.php
+++ b/module/testcase/view/create.html.php
@@ -21,6 +21,14 @@
app->tab);?>
app->tab == 'execution') js::set('objectID', $executionID);?>
app->tab == 'project') js::set('objectID', $projectID);?>
+testcase->create->requiredFields) as $field)
+{
+ if($field and strpos($showFields, $field) === false) $showFields .= ',' . $field;
+}
+?>
+testcase->create->requiredFields);?>
+
- testcase->create->requiredFields) as $field)
- {
- if($field and strpos($showFields, $field) === false) $showFields .= ',' . $field;
- }
- ?>