diff --git a/module/execution/control.php b/module/execution/control.php
index e89d613e03..6c0e162839 100644
--- a/module/execution/control.php
+++ b/module/execution/control.php
@@ -3820,17 +3820,18 @@ class execution extends control
* @param string $browseType
* @param string $groupBy
* @param string $from execution|RD
+ * @param string $searchValue
* @access public
* @return array
*/
- public function ajaxUpdateKanban($executionID = 0, $enterTime = '', $browseType = '', $groupBy = '', $from = 'execution')
+ public function ajaxUpdateKanban($executionID = 0, $enterTime = '', $browseType = '', $groupBy = '', $from = 'execution', $searchValue = '')
{
$enterTime = date('Y-m-d H:i:s', $enterTime);
$lastEditedTime = $this->dao->select("max(lastEditedTime) as lastEditedTime")->from(TABLE_KANBANLANE)->where('execution')->eq($executionID)->fetch('lastEditedTime');
- if($lastEditedTime > $enterTime or $groupBy != 'default')
+ if($lastEditedTime > $enterTime or $groupBy != 'default' or !empty($searchValue))
{
- $kanbanGroup = $from == 'execution' ? $this->loadModel('kanban')->getExecutionKanban($executionID, $browseType, $groupBy) : $this->loadModel('kanban')->getRDKanban($executionID, $browseType, 'id_asc', 0, $groupBy);
+ $kanbanGroup = $from == 'execution' ? $this->loadModel('kanban')->getExecutionKanban($executionID, $browseType, $groupBy) : $this->loadModel('kanban')->getRDKanban($executionID, $browseType, 'id_asc', 0, $groupBy, $searchValue);
return print(json_encode($kanbanGroup));
}
}
diff --git a/module/execution/css/kanban.css b/module/execution/css/kanban.css
index bb8b8d5bbd..8c3aff303c 100644
--- a/module/execution/css/kanban.css
+++ b/module/execution/css/kanban.css
@@ -110,3 +110,7 @@
#mainMenu .divider {margin: 10px}
.modal-header {padding: 15px 0;}
+#rdKanbanSearch.input-group {float: left; width: min-content;}
+#rdKanbanSearchInput {width: 150px;}
+#rdSearchBox {display: none; width: 150px;}
+.btn-link.querybox-toggle {background-color: rgba(0,0,0,0);}
diff --git a/module/execution/js/kanban.js b/module/execution/js/kanban.js
index 0ae0cece62..500a765daa 100644
--- a/module/execution/js/kanban.js
+++ b/module/execution/js/kanban.js
@@ -478,7 +478,8 @@ function renderStoryItem(item, $item, col)
.attr('href', $.createLink('story', 'view', 'storyID=' + item.id + '&version=0¶m=' + execution.id, '', true)).attr('data-toggle', 'modal').attr('data-width', '95%');
$title.appendTo($item);
}
- $title.attr('title', item.title).find('.text').text(item.title);
+ var title = rdSearchValue != '' ? "" + item.title.replaceAll(rdSearchValue, "" + rdSearchValue + "") + "": "" + item.title + "";
+ $title.attr('title', item.title).find('.text').replaceWith(title);
}
if(scaleSize <= 2)
@@ -542,7 +543,8 @@ function renderBugItem(item, $item, col)
.attr('href', $.createLink('bug', 'view', 'bugID=' + item.id, '', true)).attr('data-toggle', 'modal').attr('data-width', '80%');
$title.appendTo($item);
}
- $title.attr('title', item.title).find('.text').text(item.title);
+ var title = rdSearchValue != '' ? "" + item.title.replaceAll(rdSearchValue, "" + rdSearchValue + "") + "": "" + item.title + "";
+ $title.attr('title', item.title).find('.text').replaceWith(title);
}
if(scaleSize <= 2)
@@ -608,7 +610,8 @@ function renderTaskItem(item, $item, col)
.attr('href', $.createLink('task', 'view', 'taskID=' + item.id, '', true)).attr('data-toggle', 'modal').attr('data-width', '80%');
$title.appendTo($item);
}
- $title.attr('title', item.name).find('.text').text(item.name);
+ var name = rdSearchValue != '' ? "" + item.name.replaceAll(rdSearchValue, "" + rdSearchValue + "") + "": "" + item.name + "";
+ $title.attr('title', item.name).find('.text').replaceWith(name);
}
if(scaleSize <= 2)
@@ -792,6 +795,16 @@ function updateRegion(regionID, regionData = [])
if(!regionData) regionData = regions[regionID];
var data = groupBy == 'default' ? regionData.groups : regionData;
+ if(data == null)
+ {
+ $("div[data-id^=" + regionID + "].region").hide();
+ return false;
+ }
+ else
+ {
+ $("div[data-id^=" + regionID + "].region").show();
+ }
+ $region.empty();
$region.data('zui.kanban').render(data);
resetRegionHeight('open');
return true;
@@ -1504,7 +1517,7 @@ $(function()
var lastUpdateData;
setInterval(function()
{
- $.get(createLink('execution', 'ajaxUpdateKanban', "executionID=" + executionID + "&entertime=" + entertime + "&browseType=" + browseType + "&groupBy=" + groupBy + '&from=RD'), function(data)
+ $.get(createLink('execution', 'ajaxUpdateKanban', "executionID=" + executionID + "&entertime=" + entertime + "&browseType=" + browseType + "&groupBy=" + groupBy + '&from=RD&searchValue' + rdSearchValue), function(data)
{
if(data && lastUpdateData !== data)
{
@@ -1580,3 +1593,56 @@ function resetRegionHeight(fold)
$('.region').css('height', regionHeaderHeight);
}
}
+
+/**
+ * Toggle RDSearchBox.
+ *
+ * @access public
+ * @return void
+ */
+function toggleRDSearchBox()
+{
+ rdSearchValue = '';
+ $('#rdSearchBox').toggle();
+ if($('#rdSearchBox').css('display') == 'block')
+ {
+ $(".querybox-toggle").css("color", "#0c64eb");
+ }
+ else
+ {
+ $(".querybox-toggle").css("color", "");
+ }
+}
+
+/**
+ * Search all cards.
+ *
+ * @param string $value
+ * @access public
+ * @return void
+ */
+function searchCards(value)
+{
+ rdSearchValue = value;
+ $.get(createLink('execution', 'ajaxUpdateKanban', "executionID=" + executionID + "&entertime=0&browseType=" + browseType + "&groupBy=" + groupBy + '&from=RD&searchValue=' + value), function(data)
+ {
+ var kanbanData = $.parseJSON(data);
+ var hideAll = true;
+ $('#kanban').children('.region').children("div[id^='kanban']").each(function()
+ {
+ var regionID = $(this).attr('data-id');
+ if(kanbanData != null) data = groupBy == 'default' ? kanbanData[regionID] : kanbanData[groupBy];
+
+ hideAll = hideAll && !updateRegion(regionID, data);
+ });
+
+ if(hideAll && rdSearchValue != '')
+ {
+ if($('.table-empty-tip').length == 0) $('#kanban').append('
');
+ }
+ else
+ {
+ $('.table-empty-tip').remove();
+ }
+ });
+}
diff --git a/module/execution/lang/en.php b/module/execution/lang/en.php
index a4b945d24e..a6653e2522 100644
--- a/module/execution/lang/en.php
+++ b/module/execution/lang/en.php
@@ -396,6 +396,7 @@ $lang->execution->projectNotEmpty = 'Project cannot be empty.';
$lang->execution->confirmStoryToTask = $lang->SRCommon . '%s are converted to tasks in the current. Do you want to convert them anyways?';
$lang->execution->ge = "『%s』should be >= actual begin『%s』.";
$lang->execution->storyDragError = "The {$lang->SRCommon} is still a draft or has been changed, please drag it after the review";
+$lang->execution->pleaseInput = "Enter";
/* Statistics. */
$lang->execution->charts = new stdclass();
diff --git a/module/execution/lang/zh-cn.php b/module/execution/lang/zh-cn.php
index 66c76615ea..42264d001a 100644
--- a/module/execution/lang/zh-cn.php
+++ b/module/execution/lang/zh-cn.php
@@ -396,6 +396,7 @@ $lang->execution->projectNotEmpty = '所属项目不能为空。';
$lang->execution->confirmStoryToTask = '%s' . $lang->SRCommon . '已经在当前' . $lang->execution->common . '中转了任务,请确认是否重复转任务。';
$lang->execution->ge = "『%s』应当不小于实际开始时间『%s』。";
$lang->execution->storyDragError = "该{$lang->SRCommon}还是草稿或已变更状态,请评审通过后再拖动";
+$lang->execution->pleaseInput = "请输入";
/* 统计。*/
$lang->execution->charts = new stdclass();
diff --git a/module/execution/view/kanban.html.php b/module/execution/view/kanban.html.php
index ea835a478e..a1c1615e0a 100644
--- a/module/execution/view/kanban.html.php
+++ b/module/execution/view/kanban.html.php
@@ -52,6 +52,7 @@ js::set('vision', $this->config->vision);
js::set('productCount', count($productNames));
js::set('executionID', $execution->id);
js::set('reviewStoryParis', $reviewStoryParis);
+js::set('rdSearchValue', '');
$canSortRegion = commonModel::hasPriv('kanban', 'sortRegion') && count($regions) > 1;
$canEditRegion = commonModel::hasPriv('kanban', 'editRegion');
@@ -136,7 +137,13 @@ js::set('hasTaskButton', $hasTaskButton);
+
" . $lang->searchAB, '', "class='btn btn-link querybox-toggle'");
echo html::a('javascript:fullScreen()', "
" . $lang->kanban->fullScreen, '', "class='btn btn-link'");
$actions = '';
$printCreateRegion = (common::hasPriv('kanban', 'createRegion') and $groupBy == 'default');
diff --git a/module/kanban/model.php b/module/kanban/model.php
index 0f814a8a07..3e38a35088 100644
--- a/module/kanban/model.php
+++ b/module/kanban/model.php
@@ -808,13 +808,14 @@ class kanbanModel extends model
* @param string $orderBy
* @param int $regionID
* @param string $groupBy
+ * @param string $searchValue
*
* @access public
* @return array
*/
- public function getRDKanban($executionID, $browseType = 'all', $orderBy = 'id_desc', $regionID = 0, $groupBy = 'default')
+ public function getRDKanban($executionID, $browseType = 'all', $orderBy = 'id_desc', $regionID = 0, $groupBy = 'default', $searchValue = '')
{
- if($groupBy != 'default') return $this->getKanban4Group($executionID, $browseType, $groupBy);
+ if($groupBy != 'default') return $this->getKanban4Group($executionID, $browseType, $groupBy, $searchValue);
$kanbanData = array();
$actions = array('sortGroup');
@@ -823,7 +824,7 @@ class kanbanModel extends model
$groupGroup = $this->getGroupGroupByRegions($regionIDList);
$laneGroup = $this->getLaneGroupByRegions($regionIDList, $browseType);
$columnGroup = $this->getRDColumnGroupByRegions($regionIDList, array_keys($laneGroup));
- $cardGroup = $this->getCardGroupByExecution($executionID, $browseType, $orderBy);
+ $cardGroup = $this->getCardGroupByExecution($executionID, $browseType, $orderBy, $searchValue);
foreach($regions as $regionID => $regionName)
{
@@ -838,13 +839,16 @@ class kanbanModel extends model
$lanes = zget($laneGroup, $group->id, array());
if(!$lanes) continue;
- foreach($lanes as $lane)
+ foreach($lanes as $key => $lane)
{
$this->refreshCards($lane);
$lane->items = isset($cardGroup[$lane->id]) ? $cardGroup[$lane->id] : array();
$lane->defaultCardType = $lane->type;
+ if(!empty($searchValue) and count($lane->items) == 0) unset($lanes[$key]);
}
+ $lanes = array_values($lanes);
+ if(!empty($searchValue) and empty($lanes)) continue;
$group->columns = zget($columnGroup, $group->id, array());
$group->lanes = $lanes;
$group->actions = array();
@@ -1250,10 +1254,12 @@ class kanbanModel extends model
* @param int $kanbanID
* @param string $browseType all|task|bug|story
* @param string $orderBy
+ * @param string $searchValue
+ *
* @access public
* @return array
*/
- public function getCardGroupByExecution($executionID, $browseType = 'all', $orderBy = 'id_asc')
+ public function getCardGroupByExecution($executionID, $browseType = 'all', $orderBy = 'id_asc', $searchValue = '')
{
$cards = $this->dao->select('t1.*, t2.type as columnType')
->from(TABLE_KANBANCELL)->alias('t1')
@@ -1297,12 +1303,14 @@ class kanbanModel extends model
if($cell->type == 'task')
{
+ if(!empty($searchValue) and strpos($object->name, $searchValue) === false) continue;
$cardData['name'] = $object->name;
$cardData['status'] = $object->status;
$cardData['left'] = $object->left;
}
else
{
+ if(!empty($searchValue) and strpos($object->title, $searchValue) === false) continue;
$cardData['title'] = $object->title;
}
$cardGroup[$laneID][$cell->columnType][] = $cardData;
@@ -1406,12 +1414,14 @@ class kanbanModel extends model
if($lane->type == 'task')
{
+ if(!empty($searchValue) and strpos($object->name, $searchValue) === false) continue;
$cardData['name'] = $object->name;
$cardData['status'] = $object->status;
$cardData['left'] = $object->left;
}
else
{
+ if(!empty($searchValue) and strpos($object->title, $searchValue) === false) continue;
$cardData['title'] = $object->title;
}
@@ -1440,10 +1450,12 @@ class kanbanModel extends model
* @param int $executionID
* @param string $browseType
* @param string $groupBy
+ * @param string $searchValue
+ *
* @access public
* @return array
*/
- public function getKanban4Group($executionID, $browseType, $groupBy)
+ public function getKanban4Group($executionID, $browseType, $groupBy, $searchValue = '')
{
/* Get card data. */
$cardList = array();
@@ -1551,21 +1563,24 @@ class kanbanModel extends model
if($browseType == 'task')
{
+ if(!empty($searchValue) and strpos($object->name, $searchValue) === false) continue;
$cardData['name'] = $object->name;
$cardData['status'] = $object->status;
$cardData['left'] = $object->left;
}
else
{
+ if(!empty($searchValue) and strpos($object->title, $searchValue) === false) continue;
$cardData['title'] = $object->title;
}
$laneData['cards'][$column->columnType][] = $cardData;
$cardOrder ++;
}
- if(!isset($laneData['cards'][$column->columnType])) $laneData['cards'][$column->columnType] = array();
+ if(empty($searchValue) and !isset($laneData['cards'][$column->columnType])) $laneData['cards'][$column->columnType] = array();
}
+ if(!empty($searchValue) and empty($laneData['cards'])) continue;;
$kanbanGroup[$groupBy]['id'] = $groupBy . $laneID;
$kanbanGroup[$groupBy]['columns'] = array_values($columnData);
$kanbanGroup[$groupBy]['lanes'][] = $laneData;