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('

' + kanbanLang.empty + '

'); + } + 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;