Merge branch 'master' of https://gitlab.zcorp.cc/easycorp/zentaopms into sprint/master_lanzongjun_fixbug

This commit is contained in:
lanzongjun
2022-06-14 13:58:52 +08:00
52 changed files with 504 additions and 77 deletions
+2
View File
@@ -9,3 +9,5 @@ ALTER TABLE `zt_review` ADD docVersion smallint(6) NOT NULL AFTER `doc`;
DELETE FROM `zt_workflowaction` WHERE `module`='story' AND `action`='browse';
DELETE FROM `zt_workflowaction` WHERE `module`='task' AND `action`='browse';
DELETE FROM `zt_workflowaction` WHERE `module`='build' AND `action`='browse';
ALTER TABLE `zt_projectproduct` MODIFY COLUMN `plan` varchar(255) NOT NULL;
+1 -1
View File
@@ -1159,7 +1159,7 @@ CREATE TABLE IF NOT EXISTS `zt_projectproduct` (
`project` mediumint(8) unsigned NOT NULL,
`product` mediumint(8) unsigned NOT NULL,
`branch` mediumint(8) unsigned NOT NULL,
`plan` mediumint(8) unsigned NOT NULL,
`plan` varchar(255) NOT NULL,
PRIMARY KEY (`project`, `product`, `branch`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
-- DROP TABLE IF EXISTS `zt_projectspec`;
+5 -4
View File
@@ -115,7 +115,7 @@ public function getKanban4Group($executionID, $browseType, $groupBy, $searchValu
if($browseType == 'task')
{
if($searchValue != '' and strpos($object->name, $searchValue) === false) continue;
$cardData['name'] = $object->name;
$cardData['name'] = $object->name;
$cardData['status'] = $object->status;
$cardData['left'] = $object->left;
}
@@ -195,9 +195,10 @@ public function getCardGroupByExecution($executionID, $browseType = 'all', $orde
if($cell->type == 'task')
{
$cardData['name'] = $object->name;
$cardData['status'] = $object->status;
$cardData['left'] = $object->left;
$cardData['name'] = $object->name;
$cardData['status'] = $object->status;
$cardData['left'] = $object->left;
$cardData['estStarted'] = $object->estStarted;
}
else
{
+2 -1
View File
@@ -13,6 +13,7 @@
<style>
.table .c-progress {width: 60px;}
.table .c-estimate {width: 85px;}
.table .c-burn {width: 150px;}
</style>
<?php if(empty($executionStats)): ?>
<div class='empty-tip'><?php echo $lang->block->emptyTip;?></div>
@@ -32,7 +33,7 @@
<?php endif;?>
<th class="c-progress"><?php echo $lang->execution->progress;?></th>
<?php if($longBlock):?>
<th><?php echo $lang->execution->burn;?></th>
<th class='c-burn'><?php echo $lang->execution->burn;?></th>
<?php endif;?>
</tr>
</thead>
+1 -1
View File
@@ -3119,7 +3119,7 @@ class bugModel extends model
$showBranch = isset($this->config->bug->browse->showBranch) ? $this->config->bug->browse->showBranch : 1;
if(isset($branches[$bug->branch]) and $showBranch) echo "<span class='label label-outline label-badge' title={$branches[$bug->branch]}>{$branches[$bug->branch]}</span> ";
if($bug->module and isset($modulePairs[$bug->module])) echo "<span class='label label-gray label-badge'>{$modulePairs[$bug->module]}</span> ";
echo $canView ? html::a($bugLink, $bug->title, null, "style='color: $bug->color'") : "<span style='color: $bug->color'>{$bug->title}</span>";
echo $canView ? html::a($bugLink, $bug->title, null, "style='color: $bug->color' data-app={$this->app->tab}") : "<span style='color: $bug->color'>{$bug->title}</span>";
if($bug->case) echo html::a(helper::createLink('testcase', 'view', "caseID=$bug->case&version=$bug->caseVersion"), "[" . $this->lang->testcase->common . "#$bug->case]", '', "class='bug' title='$bug->case'");
break;
case 'branch':
+35 -3
View File
@@ -1251,6 +1251,40 @@ function createBugMenu(options)
return items;
}
/**
* Handle sort cards.
*
* @param object event
* @access public
* @return void
*/
function handleSortCards(event)
{
if(window.sortableDisabled || groupBy != 'default') return;
var newLaneID = event.element.closest('.kanban-lane').data('id');
var newColID = event.element.closest('.kanban-col').data('id');
var cards = event.element.closest('.kanban-lane-items').data('cards');
var orders = cards.map(function(card){return card.id});
var fromID = String(event.element.data('id'));
var toID = String(event.target.data('id'));
orders.splice(orders.indexOf(fromID), 1);
orders.splice(orders.indexOf(toID) + (event.insert === 'before' ? 0 : 1), 0, fromID);
var url = createLink('kanban', 'sortCard', 'kanbanID=' + executionID + '&laneID=' + newLaneID + '&columnID=' + newColID + '&cards=' + orders.join(','));
$.getJSON(url, function(response)
{
if(response.result === 'fail')
{
if(typeof response.message === 'string' && response.message.length)
{
bootbox.alert(response.message);
}
setTimeout(function(){return location.reload()}, 3000);
}
});
}
/* Define menu creators */
window.menuCreators =
{
@@ -1262,9 +1296,6 @@ window.menuCreators =
bug: createBugMenu,
};
/**
* init Kanban
*/
/**
* Init kanban.
*
@@ -1295,6 +1326,7 @@ function initKanban($kanban)
onRenderHeaderCol: renderHeaderCol,
onRenderCount: renderCount,
droppable: {target: findDropColumns, finish:handleFinishDrop},
sortable: handleSortCards,
virtualize: true,
virtualCardList: true,
virtualRenderOptions: {container: $(window).add($('#kanbanContainer'))}
+1 -1
View File
@@ -51,7 +51,7 @@ $lang->execution->canceledBy = 'CanceledBy';
$lang->execution->canceledDate = 'CanceledDate';
$lang->execution->begin = 'Planned Begin';
$lang->execution->end = 'Planned End';
$lang->execution->dateRange = 'Duration';
$lang->execution->dateRange = 'Plan Duration';
$lang->execution->realBeganAB = 'Actual Begin';
$lang->execution->realEndAB = 'Actual End';
$lang->execution->realBegan = 'Actual Begin';
+2 -1
View File
@@ -59,7 +59,8 @@ $account = $this->app->user->account;
<thead>
<tr>
<?php foreach ($cols as $col):?>
<th class='c-board s-<?php echo $col?>'><?php echo $lang->story->stageList[$col];?></th>
<?php $storiesCount = empty($stories[$col]) ? 0 : count($stories[$col]);?>
<th class='c-board s-<?php echo $col?>'><?php echo $lang->story->stageList[$col] . ' (' . $storiesCount . ')';?></th>
<?php endforeach;?>
</tr>
</thead>
+2
View File
@@ -971,6 +971,7 @@ $lang->resource->testcase->createBug = 'createBug';
$lang->resource->testcase->view = 'view';
$lang->resource->testcase->edit = 'edit';
$lang->resource->testcase->linkCases = 'linkCases';
$lang->resource->testcase->linkBugs = 'linkBugs';
$lang->resource->testcase->batchEdit = 'batchEdit';
$lang->resource->testcase->delete = 'deleteAction';
$lang->resource->testcase->batchDelete = 'batchDelete';
@@ -1008,6 +1009,7 @@ $lang->testcase->methodOrder[65] = 'batchDelete';
$lang->testcase->methodOrder[70] = 'batchChangeModule';
$lang->testcase->methodOrder[75] = 'batchChangeBranch';
$lang->testcase->methodOrder[80] = 'linkCases';
$lang->testcase->methodOrder[82] = 'linkBugs';
$lang->testcase->methodOrder[90] = 'bugs';
$lang->testcase->methodOrder[95] = 'review';
$lang->testcase->methodOrder[100] = 'batchReview';
+1 -1
View File
@@ -21,7 +21,7 @@ class kanban extends control
* @access public
* @return void
*/
public function space($browseType = 'private', $recTotal = 0, $recPerPage = 15, $pageID = 1)
public function space($browseType = 'involved', $recTotal = 0, $recPerPage = 15, $pageID = 1)
{
/* Load pager. */
$this->app->loadClass('pager', $static = true);
+6 -5
View File
@@ -3,15 +3,15 @@
#spaceList .spaceTitle > div {display: inline-block;}
#spaceList .spaceTitle .label-closed {background: #AAA !important; color: #FFF;}
#spaceList .spaceTitle .icon-zone {color: #838a9d; margin-top:100px;}
#spaceList .spaceActions {margin-top: 10px;}
#spaceList .spaceActions {margin-top: -4px;}
#spaceList .spaceActions > a{margin-left: 10px;}
.space .menu {margin-left: 5px; margin-right:5px;}
.space .table-empty-tip {padding: 40px 10px;}
.space .spaceTitle.pull-left {overflow: hidden; white-space: nowrap; max-width: calc(100% - 155px)}
.space .spaceTitle.pull-left {overflow: hidden; white-space: nowrap; max-width: calc(100% - 220px)}
.spaceName {font-size: 16px; font-weight: bold;}
.spaceTitle .icon-cube {font-size: 16px;}
.spaceDesc {font-size: 13px; color: #838A9D; margin: -5px 0 5px 18px;}
#more .setting {margin-left: -25px; min-width: 80px}
.spaceDesc {font-size: 13px; color: #838A9D; margin: -5px 0 5px 0;}
#setting .setting {margin-left: -25px; min-width: 80px}
.kanbans > .col {width: 25% !important;}
@media screen and (max-width: 1500px) {.kanbans > .col {width: 25%;}}
@@ -43,4 +43,5 @@
a.disabled {pointer-events: none;}
.noBorder{border: 0px;}
.noBorder {border: 0px;}
.position {padding-right: 5px;}
+4
View File
@@ -47,6 +47,10 @@ $lang->kanban->deleteCard = 'Delete Card';
$lang->kanban->removeCard = 'Remove Card';
$lang->kanban->assigntoCard = 'Assign';
$lang->kanban->setting = 'Setting';
$lang->kanban->settingSpace = 'Setting Space';
$lang->kanban->activateSpace = 'Activate Space';
$lang->kanban->closeSpace = 'Close Space';
$lang->kanban->deleteSpace = 'Delete Space';
$lang->kanban->enableArchived = 'Enable Archived';
$lang->kanban->archive = 'Archive';
$lang->kanban->performable = 'Set progress management';
+4
View File
@@ -47,6 +47,10 @@ $lang->kanban->deleteCard = '删除卡片';
$lang->kanban->removeCard = '移除卡片';
$lang->kanban->assigntoCard = '指派';
$lang->kanban->setting = '设置';
$lang->kanban->settingSpace = '设置空间';
$lang->kanban->activateSpace = '激活空间';
$lang->kanban->closeSpace = '关闭空间';
$lang->kanban->deleteSpace = '删除空间';
$lang->kanban->enableArchived = '设置归档功能';
$lang->kanban->archive = '归档功能';
$lang->kanban->performable = '设置进度管理';
+2 -1
View File
@@ -1499,6 +1499,7 @@ class kanbanModel extends model
if(empty($column->cards)) continue;
foreach($cardList as $card)
{
if($card->assignedTo == '') $card->assignedTo = 0;
if(strpos($column->cards, ",$card->id,") !== false) $cardGroup[$column->columnType][$card->id] = $card;
}
}
@@ -1551,7 +1552,7 @@ class kanbanModel extends model
$cardData = array();
if(in_array($groupBy, array('module', 'story', 'pri', 'severity')) and (int)$object->$groupBy !== $laneID) continue;
if(in_array($groupBy, array('assignedTo', 'type', 'category', 'source')) and $object->$groupBy != $laneID) continue;
if(in_array($groupBy, array('assignedTo', 'type', 'category', 'source')) and $object->$groupBy !== $laneID) continue;
$cardData['id'] = $object->id;
$cardData['order'] = $cardOrder;
+1 -1
View File
@@ -21,7 +21,7 @@
<table class='table table-form'>
<tr>
<th><?php echo $lang->kanbanspace->type;?></th>
<td><?php echo html::select('type', $typeList, $type, "onchange='changeValue({$spaceID}, this.value)' class='form-control chosen'");?></td>
<td><?php echo html::radio('type', $typeList, $type, "onchange='changeValue({$spaceID}, this.value)'");?></td>
<td></td>
</tr>
<tr>
+8 -8
View File
@@ -52,17 +52,17 @@
</div>
<div class='spaceActions pull-right'>
<?php $class = $space->status == 'closed' ? 'disabled' : '';?>
<?php if($space->status != 'closed' and $browseType != 'involved' and !empty($unclosedSpace)) common::printLink('kanban', 'create', "spaceID={$space->id}&type={$space->type}", '<i class="icon icon-plus"></i> ' . $lang->kanban->create, '', "class='iframe' data-width='75%'", '', true);?>
<div class="btn-group" id="more">
<a href="javascript:;" data-toggle="dropdown" class="btn btn-link " style="border-radius: 4px;"><?php echo $lang->kanban->setting;?><span class="caret"></span></a>
<ul class="dropdown-menu setting">
<li><?php common::printLink('kanban', 'editSpace', "spaceID={$space->id}", '<i class="icon icon-cog-outline"></i> ' . $lang->kanban->setting, '', "class='iframe' data-width='75%'", '', true);?></li>
<?php if($space->status != 'closed' and $browseType != 'involved' and !empty($unclosedSpace)) common::printLink('kanban', 'create', "spaceID={$space->id}&type={$space->type}", '<i class="icon icon-plus"></i> ' . $lang->kanban->create, '', "class='iframe btn btn-link' data-width='75%'", '', true);?>
<div class="btn-group" id="setting?">
<a href="javascript:;" data-toggle="dropdown" class="btn btn-link " style="border-radius: 4px;"><i class="icon icon-cog-outline position"></i><?php echo $lang->kanban->setting;?><span class="caret"></span></a>
<ul class="dropdown-menu setting pull-right">
<li><?php common::printLink('kanban', 'editSpace', "spaceID={$space->id}", '<i class="icon icon-cog-outline"></i> ' . $lang->kanban->settingSpace, '', "class='iframe' data-width='75%'", '', true);?></li>
<li><?php if($class == 'disabled'):?>
<?php common::printLink('kanban', 'activateSpace', "spaceID={$space->id}", '<i class="icon icon-magic"></i> ' . $lang->activate, '', "class='iframe'", '', true);?>
<?php common::printLink('kanban', 'activateSpace', "spaceID={$space->id}", '<i class="icon icon-magic"></i> ' . $lang->kanban->activateSpace, '', "class='iframe'", '', true);?>
<?php else:?>
<?php common::printLink('kanban', 'closeSpace', "spaceID={$space->id}", '<i class="icon icon-off"></i> ' . $lang->close, '', "class='iframe'", '', true);?>
<?php common::printLink('kanban', 'closeSpace', "spaceID={$space->id}", '<i class="icon icon-off"></i> ' . $lang->kanban->closeSpace, '', "class='iframe'", '', true);?>
<?php endif;?></li>
<li><?php common::printLink('kanban', 'deleteSpace', "spaceID={$space->id}", '<i class="icon icon-trash"></i> ' . $lang->delete, 'hiddenwin', '', '', true);?></li>
<li><?php common::printLink('kanban', 'deleteSpace', "spaceID={$space->id}", '<i class="icon icon-trash"></i> ' . $lang->kanban->deleteSpace, 'hiddenwin', '', '', true);?></li>
<ul>
</div>
</div>
+5 -4
View File
@@ -1047,10 +1047,11 @@ class product extends control
*/
public function ajaxGetPlans($productID, $branch = 0, $planID = 0, $fieldID = '', $needCreate = false, $expired = '', $param = '')
{
$param = strtolower($param);
$plans = $this->loadModel('productplan')->getPairs($productID, $branch == 0 ? '' : $branch, $expired, strpos($param, 'skipparent') !== false);
$field = $fieldID ? "plans[$fieldID]" : 'plan';
$output = html::select($field, $plans, $planID, "class='form-control chosen'");
$param = strtolower($param);
$plans = $this->loadModel('productplan')->getPairs($productID, $branch == 0 ? '' : $branch, $expired, strpos($param, 'skipparent') !== false);
$field = $fieldID ? "plans[$fieldID]" : 'plan';
$multiple = strpos($param, 'multiple') === false ? '' : 'multiple';
$output = html::select($field, $plans, $planID, "class='form-control chosen' $multiple");
if($branch == 0 and strpos($param, 'edit')) $output = html::select($field, $plans, $planID, "class='form-control chosen' multiple");
+2 -2
View File
@@ -429,7 +429,7 @@ class program extends control
if($productCount) return print(js::alert($this->lang->program->hasProduct));
$program = $this->dao->select('*')->from(TABLE_PROGRAM)->where('id')->eq($programID)->fetch();
if($confirm == 'no') return print(js::confirm($this->lang->program->confirmDelete, $this->createLink('program', 'delete', "programID=$programID&confirm=yes")));
if($confirm == 'no') return print(js::confirm(sprintf($this->lang->program->confirmDelete, $program->name), $this->createLink('program', 'delete', "programID=$programID&confirm=yes")));
$this->dao->update(TABLE_PROGRAM)->set('deleted')->eq(1)->where('id')->eq($programID)->exec();
$this->loadModel('action')->create('program', $programID, 'deleted', '', ACTIONMODEL::CAN_UNDELETED);
@@ -543,7 +543,7 @@ class program extends control
{
if($confirm == 'no')
{
return print(js::confirm($this->lang->program->confirmDelete, $this->inlink('unlinkStakeholder', "stakeholderID=$stakeholderID&programID=$programID&confirm=yes")));
return print(js::confirm($this->lang->program->unlinkStakeholder, $this->inlink('unlinkStakeholder', "stakeholderID=$stakeholderID&programID=$programID&confirm=yes")));
}
else
{
+2 -1
View File
@@ -106,7 +106,8 @@ $lang->program->endLetterChild = "Child latest end: %s, parent end date >
$lang->program->closeErrorMessage = 'There are subprograms or projects that are not closed';
$lang->program->hasChildren = 'The program has a child program or the project exists and can not be deleted.';
$lang->program->hasProduct = 'The program has products exist and can not be deleted.';
$lang->program->confirmDelete = "Do you want to delete it?";
$lang->program->confirmDelete = 'Do you want to delete the \"%s\" Program?';
$lang->program->unlinkStakeholder = 'Do you want to remove the Stakeholder?';
$lang->program->readjustTime = 'Change the program begin&end date.';
$lang->program->accessDenied = 'You have no access to the program.';
$lang->program->beyondParentBudget = 'The remaining budget of the owned program has been exceeded.';
+2 -1
View File
@@ -106,7 +106,8 @@ $lang->program->endLetterChild = "子项目的最大完成日期:%s,父
$lang->program->closeErrorMessage = '存在子项目集或项目为未关闭状态';
$lang->program->hasChildren = '该项目集有子项目集或项目存在,不能删除。';
$lang->program->hasProduct = '该项目集有产品存在,不能删除。';
$lang->program->confirmDelete = "您确定要删除吗?";
$lang->program->confirmDelete = '您确定要删除\“%s\”项目集吗?';
$lang->program->unlinkStakeholder = '您确定要移除干系人吗?';
$lang->program->readjustTime = '重新调整项目集起止时间';
$lang->program->accessDenied = '你无权访问该项目集';
$lang->program->beyondParentBudget = '已超出所属项目集的剩余预算';
+22 -3
View File
@@ -401,7 +401,13 @@ class project extends control
$planIdList = array();
foreach($_POST['plans'] as $plans)
{
foreach($plans as $planID) $planIdList[$planID] = $planID;
foreach($plans as $planList)
{
foreach($planList as $planID)
{
$planIdList[$planID] = $planID;
}
}
}
$planStoryGroup = $this->loadModel('story')->getStoriesByPlanIdList($planIdList);
@@ -557,7 +563,17 @@ class project extends control
if($_POST)
{
$oldPlans = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->andWhere('plan')->ne(0)->fetchPairs('plan');
$oldPlanList = $this->dao->select('plan')->from(TABLE_PROJECTPRODUCT)->where('project')->eq($projectID)->andWhere('plan')->ne(0)->fetchPairs('plan');
$oldPlans = array();
foreach($oldPlanList as $oldPlanIDList)
{
if(is_numeric($oldPlanIDList)) $oldPlans[$oldPlanIDList] = $oldPlanIDList;
if(!is_numeric($oldPlanIDList))
{
$oldPlanIDList = explode(',', $oldPlanIDList);
foreach($oldPlanIDList as $oldPlanID) $oldPlans[$oldPlanID] = $oldPlanID;
}
}
$changes = $this->project->update($projectID);
if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));
@@ -574,7 +590,10 @@ class project extends control
{
foreach($_POST['plans'] as $plans)
{
foreach($plans as $planID) $newPlans[$planID] = $planID;
foreach($plans as $planIDList)
{
foreach($planIDList as $planID) $newPlans[$planID] = $planID;
}
}
}
+3
View File
@@ -13,6 +13,9 @@
#budgetUnit {border-left: 0px;}
#projectName {display: inline-block; width: 32%;}
#productsBox a {border-radius: 2px !important;}
#productsBox .col-sm-4 {padding-right: 5px;}
#productsBox .addProduct {padding-left: 0px !important;}
#productsBox > .required:after{right: -6px !important;}
#productsBox .input-group-addon > div {display: inline-block !important;}
#plansBox .row {display: inline-table; width: 102%;}
#plansBox .col-sm-4 {float: none; display: inline-block; padding-right: 5px;}
+2
View File
@@ -1,2 +1,4 @@
#budget {border-right: 0px;}
#budgetUnit {border-left: 0px;}
#plansBox .row {display: inline-table; width: 102%;}
#plansBox .col-sm-4 {float: none; display: inline-block;}
+1
View File
@@ -1,2 +1,3 @@
.block-dynamic .panel-body {height: 230px; overflow: auto; position: relative;}
.block-team div.col-xs-6 {white-space: nowrap; overflow: hidden;}
.cell .detail .row-grid {display: list-item;}
+12 -7
View File
@@ -196,12 +196,12 @@ function loadPlans(product, branchID)
$("input[name='products[" + index + "]']").remove();
$("input[name='branch[" + index + "]']").remove();
$.get(createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=0,' + branchID + '&planID=0&fieldID&needCreate=&expired=' + (config.currentMethod == 'create' ? 'unexpired' : '') + '&param=skipParent'), function(data)
$.get(createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=0,' + branchID + '&planID=0&fieldID&needCreate=&expired=unexpired&param=skipParent,multiple'), function(data)
{
if(data)
{
if($("div#plan" + index).size() == 0) $("#plansBox .row").append('<div class="col-sm-4" id="plan' + index + '"></div>');
$("div#plan" + index).html(data).find('select').attr('name', 'plans[' + productID + ']' + '[' + branchID + ']').attr('id', 'plans' + productID).chosen();
$("div#plan" + index).html(data).find('select').attr('name', 'plans[' + productID + ']' + '[' + branchID + '][]').attr('id', 'plans' + productID).chosen();
adjustPlanBoxMargin();
}
@@ -323,12 +323,17 @@ $(document).on('change', "#plansBox select[name^='plans']", function()
var $plan = $(this);
$("#plansBox select[name^='plans']").each(function()
{
if($plan.val() != 0 && $plan.val() == $(this).val() && $plan.closest('div').attr('id') != $(this).closest('div').attr('id'))
var planIDList = $plan.val() == null ? 0 : $plan.val();
for(var i = 0; i < planIDList.length; i++)
{
bootbox.alert(errorSamePlans);
$plan.val(0);
$plan.trigger("chosen:updated");
return false;
var planID = planIDList[i];
if(planID != 0 && $(this).val() && $(this).val().includes(planID) && $plan.closest('div').attr('id') != $(this).closest('div').attr('id'))
{
bootbox.alert(errorSamePlans);
$plan.val(0);
$plan.trigger("chosen:updated");
return false;
}
}
});
});
+2 -2
View File
@@ -224,12 +224,12 @@ function loadPlans(product, branchID)
if(productID != 0)
{
$.get(createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=0,' + branchID + '&planID=0&fieldID&needCreate=&expired=unexpired,noclosed&param=skipParent'), function(data)
$.get(createLink('product', 'ajaxGetPlans', "productID=" + productID + '&branch=0,' + branchID + '&planID=0&fieldID&needCreate=&expired=unexpired,noclosed&param=skipParent,multiple'), function(data)
{
if(data)
{
if($("div#plan" + index).size() == 0) $("#plansBox .row").append('<div class="col-sm-4" id="plan' + index + '"></div>');
$("div#plan" + index).html(data).find('select').attr('name', 'plans[' + productID + '][' + branchID + ']').attr('id', 'plans' + productID).chosen();
$("div#plan" + index).html(data).find('select').attr('name', 'plans[' + productID + '][' + branchID + '][]').attr('id', 'plans' + productID).chosen();
adjustPlanBoxMargin();
}
+1 -1
View File
@@ -119,7 +119,7 @@ $lang->project->estimate = 'Estimates';
$lang->project->consume = 'Cost';
$lang->project->surplus = 'Left';
$lang->project->progress = 'Progress';
$lang->project->dateRange = 'Duration';
$lang->project->dateRange = 'Plan Duration';
$lang->project->to = ' to ';
$lang->project->realBeganAB = 'Actual Begin';
$lang->project->realEndAB = 'Actual End';
+1 -1
View File
@@ -119,7 +119,7 @@ $lang->project->estimate = '预计';
$lang->project->consume = '消耗';
$lang->project->surplus = '剩余';
$lang->project->progress = '进度';
$lang->project->dateRange = '起止日期';
$lang->project->dateRange = '计划起止日期';
$lang->project->to = '至';
$lang->project->realBeganAB = '实际开始';
$lang->project->realEndAB = '实际完成';
+2 -2
View File
@@ -2120,14 +2120,14 @@ class projectModel extends model
if(isset($oldProjectProducts[$productID][$branch]))
{
$oldProjectProduct = $oldProjectProducts[$productID][$branch];
$oldPlan = $oldProjectProduct->plan;
if($this->app->rawMethod != 'edit') $oldPlan = $oldProjectProduct->plan;
}
$data = new stdclass();
$data->project = $projectID;
$data->product = $productID;
$data->branch = $branch;
$data->plan = isset($plans[$productID][$branch]) ? $plans[$productID][$branch] : $oldPlan;
$data->plan = isset($plans[$productID][$branch]) ? implode(',', $plans[$productID][$branch]) : $oldPlan;
$this->dao->insert(TABLE_PROJECTPRODUCT)->data($data)->exec();
$existedProducts[$productID][$branch] = true;
}
+4 -4
View File
@@ -41,7 +41,7 @@
<form class='form-indicator main-form form-ajax' method='post' target='hiddenwin' id='dataform'>
<table class='table table-form'>
<tr>
<th class='w-120px'><?php echo $lang->project->parent;?></th>
<th class='w-130px'><?php echo $lang->project->parent;?></th>
<?php $disabled = $this->app->tab == 'product' ? 'disabled' : '';?>
<td><?php echo html::select('parent', $programList, $programID, "class='form-control chosen' onchange='setParentProgram(this.value)' $disabled");?></td>
<?php if($disabled) echo html::hidden('parent', $programID);?>
@@ -56,7 +56,7 @@
</tr>
<tr>
<th><?php echo $lang->project->code;?></th>
<td><?php echo html::input('code', '', "class='form-control' required");?></td>
<td><?php echo html::input('code', $code, "class='form-control' required");?></td>
</tr>
<tr>
<th><?php echo $lang->project->PM;?></th>
@@ -147,11 +147,11 @@
<?php $i = 0;?>
<?php foreach($products as $product):?>
<?php $plans = zget($productPlans, $product->id, array(0 => ''));?>
<div class="col-sm-4" id="plan<?php echo $i;?>"><?php echo html::select("plans[" . $product->id . "]", $plans, '', "class='form-control chosen'");?></div>
<div class="col-sm-4" id="plan<?php echo $i;?>"><?php echo html::select("plans[" . $product->id . "]", $plans, '', "class='form-control chosen' multiple");?></div>
<?php $i++;?>
<?php endforeach;?>
<?php else:?>
<div class="col-sm-4" id="plan0" style="padding-right: 6px;"><?php echo html::select("plans[][]", '', '', "class='form-control chosen'");?></div>
<div class="col-sm-4" id="plan0" style="padding-right: 6px;"><?php echo html::select("plans[][]", '', '', "class='form-control chosen' multiple");?></div>
<?php endif;?>
</div>
</td>
+3 -3
View File
@@ -37,7 +37,7 @@
<table class='table table-form'>
<?php if($project->model != 'kanban'):?>
<tr>
<th><?php echo $lang->project->model;?></th>
<th class='w-130px'><?php echo $lang->project->model;?></th>
<td><?php echo html::select('model', $lang->project->modelList, $model, "class='form-control chosen' required $disableModel");?></td>
</tr>
<?php endif;?>
@@ -156,11 +156,11 @@
<?php foreach($linkedProducts as $product):?>
<?php foreach($linkedBranches[$product->id] as $branchID => $branch):?>
<?php $plans = isset($productPlans[$product->id][$branchID]) ? $productPlans[$product->id][$branchID] : array();?>
<div class="col-sm-4" id="plan<?php echo $i;?>" style="padding-right: 6px;"><?php echo html::select("plans[{$product->id}][{$branchID}]", $plans, $branches[$product->id][$branchID]->plan, "class='form-control chosen'");?></div>
<div class="col-sm-4" id="plan<?php echo $i;?>" style="padding-right: 6px;"><?php echo html::select("plans[{$product->id}][{$branchID}][]", $plans, $branches[$product->id][$branchID]->plan, "class='form-control chosen' multiple");?></div>
<?php $i++;?>
<?php endforeach;?>
<?php endforeach;?>
<div class="col-sm-4" id="planDefault" style="padding-right: 6px;"><?php echo html::select("plans[0][0]", array(), 0, "class='form-control chosen'");?></div>
<div class="col-sm-4" id="planDefault" style="padding-right: 6px;"><?php echo html::select("plans[0][0][]", array(), 0, "class='form-control chosen' multiple");?></div>
</div>
</td>
</tr>
@@ -71,7 +71,6 @@
<div class="detail text-center form-actions">
<?php echo html::hidden("post", 'post');?>
<?php echo html::submitButton();?>
<?php echo html::backButton();?>
</div>
</form>
</div>
+4 -1
View File
@@ -146,12 +146,15 @@
<div class="detail-content">
<div class="row row-grid">
<?php foreach($products as $productID => $product):?>
<?php foreach($product->plans as $planID):?>
<?php foreach($product->plans as $planIDList):?>
<?php $planIDList = explode(',', $planIDList);?>
<?php foreach($planIDList as $planID):?>
<?php if(isset($planGroup[$productID][$planID])):?>
<div class="col-xs-12"><?php echo html::a($this->createLink('productplan', 'view', "planID={$planID}"), $product->name . '/' . $planGroup[$productID][$planID]);?></div>
<?php endif;?>
<?php endforeach;?>
<?php endforeach;?>
<?php endforeach;?>
</div>
</div>
</div>
+1
View File
@@ -1170,6 +1170,7 @@ class task extends control
}
$this->executeHooks($taskID);
$this->loadModel('common')->syncPPEStatus($taskID);
if($this->task->needUpdateBugStatus($task))
{
+36
View File
@@ -1334,6 +1334,42 @@ class testcase extends control
$this->display();
}
/**
* Link related bugs.
*
* @param int $caseID
* @param string $browseType
* @param int $param
* @access public
* @return void
*/
public function linkBugs($caseID, $browseType = '', $param = 0)
{
$this->loadModel('bug');
/* Get case and queryID. */
$case = $this->testcase->getById($caseID);
$queryID = ($browseType == 'bySearch') ? (int)$param : 0;
/* Build the search form. */
$actionURL = $this->createLink('testcase', 'linkBugs', "caseID=$caseID&browseType=bySearch&queryID=myQueryID", '', true);
$objectID = 0;
if($this->app->tab == 'project') $objectID = $case->project;
if($this->app->tab == 'execution') $objectID = $case->execution;
$this->bug->buildSearchForm($case->product, $this->products, $queryID, $actionURL, $objectID);
/* Get cases to link. */
$bugs2Link = $this->testcase->getBugs2Link($caseID, $browseType, $queryID);
/* Assign. */
$this->view->position[] = $this->lang->testcase->linkBugs;
$this->view->case = $case;
$this->view->bugs2Link = $bugs2Link;
$this->view->users = $this->loadModel('user')->getPairs('noletter');
$this->display();
}
/**
* Confirm testcase changed.
*
+3
View File
@@ -43,6 +43,9 @@ $lang->testcase->files = 'Files';
$lang->testcase->linkCase = 'Linked Cases';
$lang->testcase->linkCases = 'Link Case';
$lang->testcase->unlinkCase = 'Unlink Cases';
$lang->testcase->linkBug = 'Linked Bugs';
$lang->testcase->linkBugs = 'Link Bug';
$lang->testcase->unlinkBug = 'Unlink Bugs';
$lang->testcase->stage = 'Phase';
$lang->testcase->scriptedBy = 'ScriptedBy';
$lang->testcase->scriptedDate = 'ScriptedDate';
+3
View File
@@ -43,6 +43,9 @@ $lang->testcase->files = '附件';
$lang->testcase->linkCase = '相关用例';
$lang->testcase->linkCases = '关联相关用例';
$lang->testcase->unlinkCase = '移除相关用例';
$lang->testcase->linkBug = '相关Bug';
$lang->testcase->linkBugs = '关联相关Bug';
$lang->testcase->unlinkBug = '移除相关Bug';
$lang->testcase->stage = '适用阶段';
$lang->testcase->scriptedBy = '脚本由谁创建';
$lang->testcase->scriptedDate = '脚本创建日期';
+47 -1
View File
@@ -771,7 +771,7 @@ class testcaseModel extends model
->setForce('status', $status)
->cleanInt('story,product,branch,module')
->stripTags($this->config->testcase->editor->edit['id'], $this->config->allowedTags)
->remove('comment,steps,expects,files,labels,stepType')
->remove('comment,steps,expects,files,labels,linkBug,stepType')
->get();
$requiredFields = $this->config->testcase->edit->requiredFields;
@@ -835,6 +835,24 @@ class testcaseModel extends model
}
}
/* Link bugs to case. */
if($this->post->linkBug)
{
$linkedBugs = array_keys($oldCase->toBugs);
$linkBugs = $this->post->linkBug;
$newBugs = array_diff($linkBugs, $linkedBugs);
$removeBugs = array_diff($linkedBugs, $linkBugs);
if($newBugs)
{
foreach($newBugs as $bugID) $this->dao->update(TABLE_BUG)->set('`case`')->eq($caseID)->set('caseVersion')->eq($case->version)->where('id')->eq($bugID)->exec();
}
if($removeBugs)
{
foreach($removeBugs as $bugID) $this->dao->update(TABLE_BUG)->set('`case`')->eq(0)->set('caseVersion')->eq(0)->where('id')->eq($bugID)->exec();
}
}
/* Join the steps to diff. */
if($stepChanged and $this->post->steps)
@@ -960,6 +978,34 @@ class testcaseModel extends model
}
}
/**
* Get bugs to link.
*
* @param int $caseID
* @param string $browseType
* @param int $queryID
* @access public
* @return array
*/
public function getBugs2Link($caseID, $browseType = 'bySearch', $queryID = 0)
{
$this->loadModel('bug');
if($browseType == 'bySearch')
{
$case = $this->getById($caseID);
$bugs2Link = $this->bug->getBySearch($case->product, $case->branch, $queryID, 'id');
foreach($bugs2Link as $key => $bug2Link)
{
if($bug2Link->case != 0) unset($bugs2Link[$key]);
}
return $bugs2Link;
}
else
{
return array();
}
}
/**
* Batch update testcases.
*
+30 -2
View File
@@ -233,12 +233,13 @@
<th><?php echo $lang->testcase->keywords;?></th>
<td><?php echo html::input('keywords', $case->keywords, "class='form-control'");?></td>
</tr>
<?php if(!$isLibCase):?>
<?php if(!$isLibCase and common::hasPriv('testcase', 'linkCases')):?>
<tr>
<th><?php echo $lang->testcase->linkCase;?></th>
<td><?php echo html::a($this->createLink('testcase', 'linkCases', "caseID=$case->id", '', true), $lang->testcase->linkCases, '', "data-type='iframe' data-toggle='modal' data-width='95%'");?></td>
</tr>
<tr>
<?php $class = isset($case->linkCaseTitles) ? '' : 'hide';?>
<tr class=<?php echo $class;?>>
<th></th>
<td>
<ul class='list-unstyled'>
@@ -259,6 +260,33 @@
</td>
</tr>
<?php endif;?>
<?php if(!$isLibCase and common::hasPriv('testcase', 'linkBugs')):?>
<tr>
<th><?php echo $lang->testcase->linkBug;?></th>
<td><?php echo html::a($this->createLink('testcase', 'linkBugs', "caseID=$case->id", '', true), $lang->testcase->linkBugs, '', "data-type='iframe' data-toggle='modal' data-width='95%'");?></td>
</tr>
<?php $class = !empty($case->toBugs) ? '' : 'hide';?>
<tr class=<?php echo $class;?>>
<th></th>
<td>
<ul class='list-unstyled'>
<?php
if(isset($case->toBugs))
{
foreach($case->toBugs as $bugID => $bugTitle)
{
echo "<li><div class='checkbox-primary'>";
echo "<input type='checkbox' checked='checked' name='linkBug[]' value=$bugID />";
echo "<label>#{$bugID} {$bugTitle}</label>";
echo '</div></li>';
}
}
?>
<span id='linkBugBox'></span>
</ul>
</td>
</tr>
<?php endif;?>
</table>
</div>
<?php $this->printExtendFields($case, 'div', 'position=right');?>
+97
View File
@@ -0,0 +1,97 @@
<?php
/**
* The linkbugs view file of testcase module of ZenTaoPMS.
*
* @copyright Copyright 2009-2015 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
* @license ZPL(http://zpl.pub/page/zplv12.html) or AGPL(https://www.gnu.org/licenses/agpl-3.0.en.html)
* @author Fei Chen <chenfei@cnezsoft.com>
* @package testcase
* @version $Id: linkbugs.html.php 4411 2016-03-09 11:02:04Z Chen Fei $
* @link http://www.zentao.net
*/
?>
<?php include '../../common/view/header.html.php';?>
<?php include '../../common/view/tablesorter.html.php';?>
<div id="mainContent" class="main-content">
<div class='main-header'>
<h2>
<span class='label label-id'><?php echo $case->id;?></span>
<?php echo html::a($this->createLink('case', 'view', "caseID={$case->id}"), $case->title, '_blank');?>
<small class='text-muted'> <?php echo $lang->arrow . $lang->testcase->linkBugs;?></small>
</h2>
</div>
<div id='queryBox' data-module='bug' class='show divider'></div>
<?php if($bugs2Link):?>
<form class='main-table' method='post' target='hiddenwin' id='linkBugsForm' data-ride='table'>
<table class='table tablesorter' id='caseList'>
<thead>
<tr>
<th class='c-id'>
<div class="checkbox-primary check-all" title="<?php echo $lang->selectAll?>">
<label></label>
</div>
<?php echo $lang->idAB;?>
</th>
<th class='c-pri' title=<?php echo $lang->pri;?>><?php echo $lang->priAB;?></th>
<th><?php echo $lang->bug->product;?></th>
<th><?php echo $lang->bug->title;?></th>
<th class='c-type'><?php echo $lang->bug->type;?></th>
<th class='c-user'><?php echo $lang->openedByAB;?></th>
<th class='c-status'><?php echo $lang->statusAB;?></th>
</tr>
</thead>
<tbody>
<?php $bugCount = 0;?>
<?php foreach($bugs2Link as $bug2Link):?>
<tr>
<td class='c-id'>
<div class="checkbox-primary">
<input type='checkbox' name='bugs[]' value='<?php echo $bug2Link->id;?>' />
<label></label>
</div>
<?php printf('%03d', $bug2Link->id);?>
</td>
<td><span class='<?php echo 'pri' . zget($lang->bug->priList, $bug2Link->pri, $bug2Link->pri)?>'><?php echo zget($lang->bug->priList, $bug2Link->pri, $bug2Link->pri)?></span></td>
<td><?php echo html::a($this->createLink('product', 'browse', "productID={$bug2Link->product}&branch={$bug2Link->branch}"), $products[$bug2Link->product], '_blank');?></td>
<td class='text-left' title='<?php echo $bug2Link->title;?>'><?php echo html::a($this->createLink('bug', 'view', "bugID=$bug2Link->id"), $bug2Link->title, '_blank');?></td>
<td><?php echo zget($lang->bug->typeList, $bug2Link->type);?></td>
<td><?php echo zget($users, $bug2Link->openedBy);?></td>
<td class='status-<?php echo $bug2Link->status?>'><?php echo $this->bug->processStatus('bug', $bug2Link);?></td>
</tr>
<?php $bugCount ++;?>
<?php endforeach;?>
</tbody>
</table>
<div class='table-footer'>
<div class="checkbox-primary check-all"><label><?php echo $lang->selectAll?></label></div>
<div class="table-actions btn-toolbar"><?php if($bugCount) echo html::submitButton('', '', 'btn btn-default');?></div>
<?php echo html::hidden('case', $case->id);?>
</div>
</form>
<?php endif;?>
</div>
<script>
$(function()
{
<?php if($bugs2Link):?>
$('#linkBugsForm').table();
setTimeout(function(){$('#linkBugsForm .table-footer').removeClass('fixed-footer');}, 100);
<?php endif;?>
$('#submit').click(function(){
var output = '';
$('#linkBugsForm').find('tr.checked').each(function(){
var bugID = $(this).find('td.c-id').find('div.checkbox-primary input').attr('value');
var bugTitle = "#" + bugID + ' ' + $(this).find('td').eq(3).attr('title');
var checkbox = "<li><div class='checkbox-primary'><input type='checkbox' checked='checked' name='linkBug[]' " + "value=" + bugID + " /><label>" + bugTitle + "</label></div></li>";
output += checkbox;
});
$.closeModal();
parent.$('#linkBugBox').html(output);
parent.$('#linkBugBox').closest('tr').removeClass('hide');
return false;
});
});
</script>
<?php include '../../common/view/footer.html.php';?>
+1
View File
@@ -89,6 +89,7 @@ $(function()
});
$.closeModal();
parent.$('#linkCaseBox').html(output);
parent.$('#linkCaseBox').closest('tr').removeClass('hide');
return false;
});
});
+39
View File
@@ -104,6 +104,24 @@ class testsuiteModel extends model
->fetchAll('id');
}
/**
* Get test suites pairs of a product.
*
* @param int $productID
* @access public
* @return array
*/
public function getSuitePairs($productID)
{
return $this->dao->select("id, name")->from(TABLE_TESTSUITE)
->where('product')->eq((int)$productID)
->beginIF($this->config->systemMode == 'new' and $this->lang->navGroup->testsuite != 'qa')->andWhere('project')->eq($this->session->project)->fi()
->andWhere('deleted')->eq(0)
->andWhere("(`type` = 'public' OR (`type` = 'private' and addedBy = '{$this->app->user->account}'))")
->orderBy('id_desc')
->fetchPairs();
}
/**
* Get unit suite.
*
@@ -220,6 +238,27 @@ class testsuiteModel extends model
return $this->loadModel('testcase')->appendData($cases);
}
/**
* Get linked cases pairs of suite.
*
* @param int $suiteID
* @access public
* @return array
*/
public function getLinkedCasePairs($suiteID)
{
$suite = $this->getById($suiteID);
return $this->dao->select('t1.id, t1.title')->from(TABLE_CASE)->alias('t1')
->leftJoin(TABLE_SUITECASE)->alias('t2')->on('t1.id=t2.case')
->where('t2.suite')->eq($suiteID)
->beginIF($this->config->systemMode == 'new' and $this->lang->navGroup->testsuite != 'qa')->andWhere('t1.project')->eq($this->session->project)->fi()
->andWhere('t1.product')->eq($suite->product)
->andWhere('t1.product')->eq($suite->product)
->andWhere('t1.deleted')->eq(0)
->orderBy('id_desc')
->fetchPairs('id');
}
/**
* Get unlinked cases for suite.
*
+4 -1
View File
@@ -503,10 +503,11 @@ class testtask extends control
if($browseType == 'bymodule') setcookie('taskCaseModule', (int)$param, 0, $this->config->webRoot, '', $this->config->cookieSecure, true);
if($browseType != 'bymodule') $this->session->set('taskCaseBrowseType', $browseType);
if($browseType == 'bysuite') $suiteName = $this->loadModel('testsuite')->getById($param)->name;
/* Set the browseType, moduleID and queryID. */
$moduleID = ($browseType == 'bymodule') ? (int)$param : ($browseType == 'bysearch' ? 0 : ($this->cookie->taskCaseModule ? $this->cookie->taskCaseModule : 0));
$queryID = ($browseType == 'bysearch') ? (int)$param : 0;
$queryID = ($browseType == 'bysearch' or $browseType == 'bysuite') ? (int)$param : 0;
/* Get execution type and set assignedToList. */
$execution = $this->execution->getById($task->execution);
@@ -568,6 +569,8 @@ class testtask extends control
$this->view->pager = $pager;
$this->view->branches = $this->loadModel('branch')->getPairs($productID);
$this->view->setModule = false;
$this->view->suites = $this->loadModel('testsuite')->getSuitePairs($productID);
$this->view->suiteName = isset($suiteName) ? $suiteName : $this->lang->testtask->browseBySuite;
$this->view->canBeChanged = $canBeChanged;
$this->display();
+1
View File
@@ -128,6 +128,7 @@ $lang->testtask->linkByBuild = 'Copy from build';
$lang->testtask->linkByStory = 'Link by Story';
$lang->testtask->linkByBug = 'Link by Bug';
$lang->testtask->linkBySuite = 'Link by Suite';
$lang->testtask->browseBySuite = 'Browse by Suite';
$lang->testtask->passAll = 'Pass All';
$lang->testtask->pass = 'Pass';
$lang->testtask->fail = 'Failed';
+1
View File
@@ -128,6 +128,7 @@ $lang->testtask->linkByBuild = '复制测试单';
$lang->testtask->linkByStory = "{$lang->SRCommon}关联";
$lang->testtask->linkByBug = '按Bug关联';
$lang->testtask->linkBySuite = '按套件关联';
$lang->testtask->browseBySuite = '按套件查看';
$lang->testtask->passAll = '全部通过';
$lang->testtask->pass = '通过';
$lang->testtask->fail = '失败';
+34
View File
@@ -948,6 +948,36 @@ class testtaskModel extends model
->fetchAll('id');
}
/**
* Get test runs of a suite.
*
* @param int $taskID
* @param int $suiteID
* @param string $orderBy
* @param object $pager
* @access public
* @return array
*/
public function getRunsBySuite($taskID, $suiteID, $orderBy, $pager = null)
{
/* Select the table for these special fields. */
$specialFields = ',assignedTo,status,lastRunResult,lastRunner,lastRunDate,';
$fieldToSort = substr($orderBy, 0, strpos($orderBy, '_'));
$orderBy = strpos($specialFields, ',' . $fieldToSort . ',') !== false ? ('t1.' . $orderBy) : ('t2.' . $orderBy);
$cases = $this->loadModel('testsuite')->getLinkedCasePairs($suiteID);
return $this->dao->select('t2.*,t1.*,t2.version as caseVersion,t3.title as storyTitle,t2.status as caseStatus')->from(TABLE_TESTRUN)->alias('t1')
->leftJoin(TABLE_CASE)->alias('t2')->on('t1.case = t2.id')
->leftJoin(TABLE_STORY)->alias('t3')->on('t2.story = t3.id')
->where('t1.task')->eq((int)$taskID)
->andWhere('t2.deleted')->eq(0)
->andWhere('t2.id')->in(array_keys($cases))
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
}
/**
* Get test runs of a user.
*
@@ -1000,6 +1030,10 @@ class testtaskModel extends model
{
$runs = $this->getRuns($task->id, $modules, $sort, $pager);
}
elseif($browseType == 'bysuite')
{
$runs = $this->getRunsBySuite($task->id, $queryID, $sort, $pager);
}
elseif($browseType == 'assignedtome')
{
$runs = $this->getUserRuns($task->id, $this->session->user->account, $modules, $sort, $pager);
+13 -2
View File
@@ -30,9 +30,20 @@
echo html::a($this->createLink('testtask', 'groupCase', "taskID=$taskID&groupBy=story"), "<span class='text'>{$lang->testcase->groupByStories}</span>", '', "class='btn btn-link $active' data-app='{$app->tab}'");
echo '</div>';
}
if($this->methodName == 'cases') echo "<a class='btn btn-link querybox-toggle' id='bysearchTab'><i class='icon icon-search muted'></i>{$lang->testcase->bySearch}</a>";
?>
<?php if($this->methodName == 'cases'):?>
<div class='btn-group'>
<?php $active = $suiteName == $lang->testtask->browseBySuite ? '' : 'btn-active-text';?>
<a href='javascript:;' class='btn btn-link btn-limit <?php echo $active;?>' data-toggle='dropdown'><span class='text' title='<?php echo $suiteName;?>'><?php echo $suiteName;?></span> <span class='caret'></span></a>
<ul class='dropdown-menu' style='max-height:240px; max-width: 300px; overflow-y:auto'>
<?php
foreach($suites as $key => $name) echo "<li>" . html::a(inlink('cases', "taskID=$taskID&browseType=bysuite&param=$key"), $name) . "</li>";
?>
</ul>
</div>
<?php echo "<a class='btn btn-link querybox-toggle' id='bysearchTab'><i class='icon icon-search muted'></i> {$lang->testcase->bySearch}</a>";?>
<?php endif;?>
</div>
<div class='btn-toolbar pull-right'>
<?php
+39
View File
@@ -511,6 +511,9 @@ class upgradeModel extends model
case '17_0_beta2':
$this->changeStoryNeedReview();
break;
case '17_0':
$this->replaceSetLanePriv();
break;
}
$this->deletePatch();
@@ -6319,4 +6322,40 @@ class upgradeModel extends model
$this->setting->deleteItems('owner=system&module=story&section=&key=forceReviewAll');
}
/**
* The setlane permission is deleted. We need to replace setlane with editlanename and editlanecolor.
*
* @access public
* @return void
*/
public function replaceSetLanePriv()
{
$groupIDList = $this->dao->select('`group`')->from(TABLE_GROUPPRIV)
->where('module')->eq('kanban')
->andWhere('method')->eq('setLane')
->fetchAll();
if(!empty($groupIDList))
{
$this->dao->delete()->from(TABLE_GROUPPRIV)
->where('module')->eq('kanban')
->andWhere('method')->eq('setLane')
->exec();
}
foreach($groupIDList as $groupID)
{
$data = new stdClass();
$data->group = $groupID->group;
$data->module = 'kanban';
$data->method = 'editLaneName';
$this->dao->insert(TABLE_GROUPPRIV)->data($data)->exec();
$data->method = 'editLaneColor';
$this->dao->insert(TABLE_GROUPPRIV)->data($data)->exec();
}
return true;
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
/*!
* ZUI: ZUI Kanban View - v1.10.0 - 2022-06-08
* ZUI: ZUI Kanban View - v1.10.0 - 2022-06-14
* http://openzui.com
* GitHub: https://github.com/easysoft/zui.git
* Copyright (c) 2022 cnezsoft.com; Licensed MIT
File diff suppressed because one or more lines are too long
+4 -4
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long