Merge branch '18.8.1' into 18.x

This commit is contained in:
tanghucheng
2023-10-27 04:39:19 -04:00
54 changed files with 382 additions and 126 deletions
+2
View File
@@ -1 +1,3 @@
ALTER TABLE `zt_mr` ADD executionID mediumint(8) unsigned NOT NULL DEFAULT 0 AFTER `jobID`;
ALTER TABLE `zt_testtask` ADD COLUMN `members` text NULL;
UPDATE `zt_solutions` SET `deleted` = '0' WHERE `deleted` = '';
+29 -1
View File
@@ -1578,6 +1578,24 @@ class baseSQL
*/
public $conditionIsTrue = false;
/**
* 条件层级。
* The condition level.
*
* @var bool
* @access public;
*/
public $conditionLevel = 0;
/**
* 条件结果,beginIF 中表达式的结果会存储到这个数组中。
* Store the result of the expression.
*
* @var bool
* @access public;
*/
public $conditionResults = array();
/**
* WHERE条件嵌套小括号标记。
* If in mark or not.
@@ -1889,7 +1907,9 @@ class baseSQL
public function beginIF($condition)
{
$this->inCondition = true;
$this->conditionIsTrue = $condition;
$this->conditionLevel += 1;
$this->conditionResults[$this->conditionLevel] = $condition;
$this->conditionIsTrue = !in_array(false, $this->conditionResults);
return $this;
}
@@ -1902,6 +1922,14 @@ class baseSQL
*/
public function fi()
{
unset($this->conditionResults[$this->conditionLevel]);
$this->conditionLevel -= 1;
if($this->conditionLevel > 0)
{
$this->conditionIsTrue = !in_array(false, $this->conditionResults);
return $this;
}
$this->inCondition = false;
$this->conditionIsTrue = false;
return $this;
+8 -5
View File
@@ -980,12 +980,14 @@ class block extends control
$this->app->loadLang('story');
$this->app->loadLang('bug');
$this->loadModel('program')->refreshStats();
/* Set project status and count. */
$status = isset($this->params->type) ? $this->params->type : 'all';
$count = isset($this->params->count) ? (int)$this->params->count : 15;
/* Get projects. */
$projects = $this->project->getOverviewList('byStatus', $status, 'order_asc', $count, '');
$projects = $this->project->getOverviewList('byStatus', $status, 'order_asc', $count, '');
if(empty($projects))
{
$this->view->projects = $projects;
@@ -1031,7 +1033,6 @@ class block extends control
$project->cv = $this->weekly->getCV($project->ev, $project->ac);
$left = (float)$this->weekly->getLeft($project->id, $today);
$project->progress = ($project->ac + $left) ? floor($project->ac / ($project->ac + $left) * 1000) / 1000 * 100 : 0;
$project->progress = $project->progress > 100 ? 100 : $project->progress;
$project->current = $current;
}
@@ -1282,6 +1283,9 @@ class block extends control
public function printWaterfallReportBlock()
{
$this->app->loadLang('programplan');
$this->loadModel('program')->refreshStats();
$project = $this->loadModel('project')->getByID($this->session->project);
$today = helper::today();
$date = date('Ymd', strtotime('this week Monday'));
@@ -1298,9 +1302,8 @@ class block extends control
$this->view->sv = $this->weekly->getSV($this->view->ev, $this->view->pv);
$this->view->cv = $this->weekly->getCV($this->view->ev, $this->view->ac);
$left = (float)$this->weekly->getLeft($this->session->project, $today);
$progress = ($this->view->ac + $left) ? floor($this->view->ac / ($this->view->ac + $left) * 1000) / 1000 * 100 : 0;
$this->view->progress = $progress > 100 ? 100 : $progress;
$left = (float)$this->weekly->getLeft($this->session->project, $today);
$this->view->progress = $project->progress > 100 ? 100 : $project->progress;
$this->view->current = $current;
}
@@ -101,7 +101,7 @@
<div class='col-xs-5 execution-name' title="<?php echo $project->name;?>"><?php echo html::a($this->createLink('execution', 'task', "executionID={$project->id}"), $project->name);?></div>
<div class='col-xs-7'>
<div class="progress progress-text-left">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="<?php echo $project->hours->progress;?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo $project->hours->progress;?>%">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="<?php echo $project->progress;?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo $project->progress;?>%">
<span class="progress-text"><?php echo $project->progress;?>%</span>
</div>
</div>
+4 -4
View File
@@ -529,16 +529,16 @@ class caselib extends control
$columnKey[] = $fields[$title];
}
if(count($columnKey) != count($header) or $this->post->encode != 'utf-8')
if(count($columnKey) <= 3 or $this->post->encode != 'utf-8')
{
$fc = file_get_contents($fileName);
$encode = $this->post->encode != "utf-8" ? $this->post->encode : 'gbk';
$fc = file_get_contents($fileName);
$fc = helper::convertEncoding($fc, $encode, 'utf-8');
file_put_contents($fileName, $fc);
$rows = $this->file->parseCSV($fileName);
$columnKey = array();
$header = array();
$header = array();
foreach($rows[0] as $i => $rowValue)
{
if(empty($rowValue)) break;
@@ -550,7 +550,7 @@ class caselib extends control
if(!isset($fields[$title])) continue;
$columnKey[] = $fields[$title];
}
if(count($columnKey) != count($header)) return print(js::alert($this->lang->testcase->errorEncode));
if(count($columnKey) == 0) return print(js::alert($this->lang->testcase->errorEncode));
}
$this->session->set('fileImport', $fileName);
+8 -7
View File
@@ -29,13 +29,14 @@ $(function()
<thead>
<tr>
<th class='c-number'><?php echo $lang->testcase->id?></th>
<th class='c-title' id='title'> <?php echo $lang->testcase->title?></th>
<th class='c-module' id='module'> <?php echo $lang->testcase->module?></th>
<th class='c-pri' id='pri'> <?php echo $lang->testcase->pri?></th>
<th class='c-type' id='type'> <?php echo $lang->testcase->type?></th>
<th class='c-stage' id='stage'> <?php echo $lang->testcase->stage?></th>
<th class='c-text' id='keywords'> <?php echo $lang->testcase->keywords?></th>
<th class='c-precondition' id='precondition'><?php echo $lang->testcase->precondition?></th>
<th class='c-title <?php if(strpos(",$requiredFields,", ',title,') !== false) echo 'required';?>' id='title'> <?php echo $lang->testcase->title?></th>
<th class='c-module <?php if(strpos(",$requiredFields,", ',module,') !== false) echo 'required';?>' id='module'> <?php echo $lang->testcase->module?></th>
<th class='c-pri <?php if(strpos(",$requiredFields,", ',pri,') !== false) echo 'required';?>' id='pri'> <?php echo $lang->testcase->pri?></th>
<th class='c-type <?php if(strpos(",$requiredFields,", ',type,') !== false) echo 'required';?>' id='type'> <?php echo $lang->testcase->type?></th>
<th class='c-stage <?php if(strpos(",$requiredFields,", ',stage,') !== false) echo 'required';?>' id='stage'> <?php echo $lang->testcase->stage?></th>
<th class='c-text <?php if(strpos(",$requiredFields,", ',text,') !== false) echo 'required';?>' id='keywords'> <?php echo $lang->testcase->keywords?></th>
<th class='c-precondition <?php if(strpos(",$requiredFields,", ',precondition,') !== false) echo 'required';?>' id='precondition'><?php echo $lang->testcase->precondition?></th>
<th class='c-case-step <?php if(strpos(",$requiredFields,", ',step,') !== false) echo 'required';?> col-content'>
<th class='c-case-step col-content'>
<table class='w-p100 table-borderless'>
<tr>
+1 -1
View File
@@ -585,7 +585,7 @@ class commonModel extends model
echo "<li class='text-gray switchTo'>{$lang->switchTo}</li>";
foreach($userVisions as $vision)
{
echo ($currentVision == $vision ? '<li class="active">' : '<li>') . html::a(helper::createLink('my', 'ajaxSwitchVision', "vision=$vision"), $lang->visionList[$vision], '', "data-type='ajax'") . '</li>';
if(isset($lang->visionList[$vision])) echo ($currentVision == $vision ? '<li class="active">' : '<li>') . html::a(helper::createLink('my', 'ajaxSwitchVision', "vision=$vision"), $lang->visionList[$vision], '', "data-type='ajax'") . '</li>';
}
echo '</ul>';
+1 -1
View File
@@ -197,7 +197,7 @@ function renderProjectItem(item, $item)
{
$progress = $('<div class="ring"><span></span></div>').appendTo($item);
}
var progress = Math.max(0, Math.min(100, Math.round(item.hours && !Array.isArray(item.hours) ? Math.round(item.hours.progress || 0) : 0)));
var progress = Math.max(0, Math.min(100, Math.round(item.progress ? Math.round(item.progress || 0) : 0)));
$progress.find('span').text(progress);
$progress.css('background-position-x', -Math.ceil(progress / 2) * 24);
$item.addClass('has-progress');
+1 -1
View File
@@ -38,5 +38,5 @@ body {overflow: hidden;}
#whiteListBox .input-group:last-child {margin-top: 10px;}
#mainContent .main-header h2 {width: 90%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;}
.fullscreen-save, .markdown-fullscreen-save {position: fixed; top: 10px; right: 30px; z-index: 999999;}
.modal-header .fullscreen-save, .markdown-fullscreen-save {top: 5px; right: 60px;}
#dataform .table tr:last-child {position: fixed; top: 47px;}
+10 -3
View File
@@ -591,6 +591,9 @@ class execution extends control
$executions = $this->execution->getPairs(0, 'all', 'nocode');
$this->execution->setMenu($executionID);
$execution = $this->execution->getByID($executionID);
$project = $this->loadModel('project')->getByID($execution->project);
/* Load pager. */
$this->app->loadClass('pager', $static = true);
$pager = new pager($recTotal, $recPerPage, $pageID);
@@ -613,13 +616,18 @@ class execution extends control
->leftJoin(TABLE_EXECUTION)->alias('t2')
->on('t1.project = t2.id')
->where('t1.product')->in(array_keys($products))
->andWhere('t2.type')->in('sprint,stage,kanban')
->fetchPairs('project');
$projects = $this->loadModel('product')->getProjectPairsByProductIDList(array_keys($products));
}
else
{
$executionName = $executions[$executionID];
unset($executions);
$executions[$executionID] = $executionName;
$projects[$project->id] = $project->name;
}
/* Get bugs.*/
@@ -651,9 +659,6 @@ class execution extends control
$bugs = $this->execution->getSearchBugs($products, $executionID, $bugQuery, $pager, 'id_desc');
}
$execution = $this->execution->getByID($executionID);
$project = $this->loadModel('project')->getByID($execution->project);
/* Build the search form. */
$this->config->bug->search['actionURL'] = $this->createLink('execution', 'importBug', "executionID=$executionID&browseType=bySearch&param=myQueryID");
$this->config->bug->search['queryID'] = $queryID;
@@ -687,6 +692,8 @@ class execution extends control
}
$this->config->bug->search['params']['module']['values'] = $bugModules;
$this->config->bug->search['params']['project']['values'] = array('' => '') + $projects;
unset($this->config->bug->search['fields']['resolvedBy']);
unset($this->config->bug->search['fields']['closedBy']);
unset($this->config->bug->search['fields']['status']);
+2
View File
@@ -93,6 +93,8 @@ function setStatistics()
const task = element.getRowInfo(id).data;
if(task.isParent == true) return true;
totalEstimate += Number(task.estimateNum);
totalConsumed += Number(task.consumedNum);
if(task.statusCode != 'cancel' && task.statusCode != 'closed') totalLeft += Number(task.leftNum);
+13
View File
@@ -2665,6 +2665,19 @@ class executionModel extends model
return $execution;
}
/**
* Get execution by build id.
*
* @param int $buildID
* @access public
* @return object
*/
public function getByBuild($buildID)
{
$build = $this->loadModel('build')->getById($buildID);
return $this->getById($build->execution);
}
/**
* Get the default managers for a execution from it's related products.
*
+3 -3
View File
@@ -149,7 +149,7 @@ class file extends control
/* Judge the mode, down or open. */
$mode = 'down';
$fileTypes = 'txt|jpg|jpeg|gif|png|bmp|xml|html';
$fileTypes = 'txt|jpg|jpeg|gif|png|bmp|xml|html|mp4';
if(stripos($fileTypes, $file->extension) !== false && $mouse == 'left') $mode = 'open';
if($file->extension == 'txt')
{
@@ -164,11 +164,11 @@ class file extends control
/* If the mode is open, locate directly. */
if($mode == 'open')
{
if(stripos('txt|jpg|jpeg|gif|png|bmp', $file->extension) !== false)
if(stripos('txt|jpg|jpeg|gif|png|bmp|mp4', $file->extension) !== false)
{
$this->view->file = $file;
$this->view->charset = $this->get->charset ? $this->get->charset : $this->config->charset;
$this->view->fileType = ($file->extension == 'txt') ? 'txt' : 'image';
$this->view->fileType = $file->extension == 'txt' ? 'txt' : ($file->extension == 'mp4' ? 'video' : 'image');
$this->display();
}
else
+1
View File
@@ -38,6 +38,7 @@ $lang->file->beginUpload = 'Upload';
$lang->file->uploadSuccess = 'Hochgeladen!';
$lang->file->batchExport = 'Export in batches';
$lang->file->downloadFile = 'Download';
$lang->file->playFailed = 'Video preview failed, please contact admin';
$lang->file->pathname = 'Pfadname';
$lang->file->title = 'Titel';
+1
View File
@@ -38,6 +38,7 @@ $lang->file->beginUpload = 'Click to Upload';
$lang->file->uploadSuccess = 'Uploaded!';
$lang->file->batchExport = 'Export in batches';
$lang->file->downloadFile = 'Download';
$lang->file->playFailed = 'Video preview failed, please contact admin';
$lang->file->pathname = 'Path Name';
$lang->file->title = 'Title';
+1
View File
@@ -38,6 +38,7 @@ $lang->file->beginUpload = 'Clic pour Charger';
$lang->file->uploadSuccess = 'Chargé !';
$lang->file->batchExport = 'Export in batches';
$lang->file->downloadFile = 'Download';
$lang->file->playFailed = 'Video preview failed, please contact admin';
$lang->file->pathname = 'Nom Chemin';
$lang->file->title = 'Titre';
+1
View File
@@ -33,6 +33,7 @@ $lang->file->addFile = 'Thêm';
$lang->file->beginUpload = 'Click to Upload';
$lang->file->uploadSuccess = 'Uploaded!';
$lang->file->batchExport = 'Export in batches';
$lang->file->playFailed = 'Video preview failed, please contact admin';
$lang->file->pathname = 'Path tên';
$lang->file->title = 'Tiêu đề';
+1
View File
@@ -38,6 +38,7 @@ $lang->file->beginUpload = '开始上传';
$lang->file->uploadSuccess = '上传成功';
$lang->file->batchExport = '分批导出';
$lang->file->downloadFile = '下载';
$lang->file->playFailed = '视频预览失败,请联系管理员';
$lang->file->pathname = '路径';
$lang->file->title = '标题';
+12 -1
View File
@@ -1,8 +1,9 @@
<?php include '../../common/view/header.lite.html.php';?>
<?php js::set('fileID', $file->id);?>
<style>
#imageFile {text-align: center; padding: 0; margin: 0 -10px;}
#imageFile,#videoFile {text-align: center; padding: 0; margin: 0 -10px;}
#imageFile img {max-width: 100%;}
#videoFile video {max-width: 100%;}
#txtFile {padding: 5px 0; margin: 0 -10px;}
#txtFile pre {margin: 0;}
#txtFile div {overflow-x: auto;}
@@ -20,6 +21,11 @@
</div>
<?php if($fileType == 'image'):?>
<div id='imageFile'><?php echo html::image($this->createLink('file', 'read', "fileID=$file->id"));?></div>
<?php elseif($fileType == 'video'):?>
<div id='videoFile'>
<video src=<?php echo $file->webPath;?> autoplay controls controlsList='nodownload' onerror='showError()'></video>
<div class='playfailed hide'><?php echo $lang->file->playFailed;?></div>
</div>
<?php else:?>
<div id='txtFile'>
<?php
@@ -51,6 +57,11 @@
</div>
</main>
<script>
function showError()
{
$('.playfailed').show();
}
function setCharset(charset)
{
var link = createLink('file', 'download', 'fileID=' + fileID + '&mouse=left');
+2 -2
View File
@@ -69,7 +69,7 @@ function deleteFile(fileID, obj)
function downloadFile(fileID, extension, imageWidth, fileTitle, type = 'download')
{
if(!fileID) return;
var fileTypes = 'txt,jpg,jpeg,gif,png,bmp';
var fileTypes = 'txt,jpg,jpeg,gif,png,bmp,mp4';
var windowWidth = $(window).width();
var width = (windowWidth > imageWidth) ? ((imageWidth < windowWidth * 0.5) ? windowWidth * 0.5 : imageWidth) : windowWidth;
var checkExtension = fileTitle.lastIndexOf('.' + extension) == (fileTitle.length - extension.length - 1);
@@ -203,7 +203,7 @@ function setFileName(fileID)
}
/* For the open source version of the file judgment. */
if(stripos('txt|jpg|jpeg|gif|png|bmp', $file->extension) !== false and common::hasPriv('file', 'preview'))
if(stripos('txt|jpg|jpeg|gif|png|bmp|mp4', $file->extension) !== false and common::hasPriv('file', 'preview'))
{
echo html::a($previewLink, "<i class='icon icon-eye'></i>", '_blank', "class='fileAction btn btn-link text-primary' title='{$lang->file->preview}' onclick=\"return downloadFile($file->id, '$file->extension', $imageWidth, '$file->title', 'preview')\"");
}
+1
View File
@@ -2974,6 +2974,7 @@ $config->group->package->reviewcl->privs['reviewcl-view'] =
$config->group->package->reviewcl->privs['reviewcl-waterfallplusBrowse'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 1, 'depend' => array(), 'recommend' => array());
$config->group->package->reviewcl->privs['reviewsetting-version'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 2, 'depend' => array(), 'recommend' => array());
$config->group->package->reviewcl->privs['reviewsetting-waterfallplusVersion'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 3, 'depend' => array(), 'recommend' => array());
$config->group->package->reviewcl->privs['reviewcl-setCategory'] = array('edition' => 'max,ipd', 'vision' => 'rnd', 'order' => 4, 'depend' => array(), 'recommend' => array());
$config->group->package->process = new stdclass();
$config->group->package->process->order = 25;
+9
View File
@@ -219,6 +219,15 @@ class messageModel extends model
$toList = $toList . $ccList;
}
if($objectType == 'testtask')
{
$members = explode(',', $object->members);
$toList = explode(',', $toList);
$toList = array_merge($toList, $members);
$toList = array_filter(array_unique($toList));
$toList = implode(',', $toList);
}
return $toList;
}
-2
View File
@@ -125,8 +125,6 @@ function refreshPivot(pivotInfo, isOrigin = false)
$('#pivot-query').addClass('hidden');
$('#origin-query').removeClass('hidden');
$('.query-outside').addClass('visibility-hidden');
}
});
}
+33 -31
View File
@@ -1326,13 +1326,30 @@ class programModel extends model
}
/* 1. Get summary and members of executions to be refreshed. */
$summary = $this->dao->select('execution, SUM(t1.estimate) AS totalEstimate, SUM(t1.consumed) AS totalConsumed, SUM(t1.`left`) AS totalLeft')->from(TABLE_TASK)->alias('t1')
$tasks = $this->dao->select('t1.id, execution, t1.estimate, t1.consumed, t1.`left`, t1.status')->from(TABLE_TASK)->alias('t1')
->leftJoin(TABLE_PROJECT)->alias('t2')->on('t1.project=t2.id')
->where('t1.deleted')->eq(0)
->andWhere('t1.parent')->le(0) // Ignore child task.
->beginIF(!empty($projects))->andWhere('t1.project')->in(array_keys($projects))->fi()
->groupBy('execution')
->fetchAll();
->fetchAll('id');
$summary = array();
foreach($tasks as $task)
{
if(empty($task->execution)) continue;
if(!isset($summary[$task->execution]))
{
$summary[$task->execution] = new stdclass();
$summary[$task->execution]->totalEstimate = 0;
$summary[$task->execution]->totalConsumed = 0;
$summary[$task->execution]->totalLeft = 0;
}
$summary[$task->execution]->execution = $task->execution;
$summary[$task->execution]->totalEstimate += $task->estimate;
$summary[$task->execution]->totalConsumed += $task->consumed;
$summary[$task->execution]->totalLeft += ($task->status == 'closed' or $task->status == 'cancel') ? 0 : $task->left;
}
$teamMembers = $this->dao->select('t1.root, COUNT(1) AS members')->from(TABLE_TEAM)->alias('t1')
->leftJoin(TABLE_USER)->alias('t2')->on('t1.account=t2.account')
@@ -1362,6 +1379,8 @@ class programModel extends model
$stats[$nodeID]['totalEstimate'] += $execution->totalEstimate;
$stats[$nodeID]['totalConsumed'] += $execution->totalConsumed;
$stats[$nodeID]['totalLeft'] += $execution->totalLeft;
// Check $execution->execution and $nodeID(path) is not deleted.
if(empty($projectsPairs[$execution->execution]) && empty($projectsPairs[$nodeID]))
{
$stats[$nodeID]['totalConsumedNotDel'] += $execution->totalConsumed;
@@ -1370,22 +1389,6 @@ class programModel extends model
}
}
$this->loadModel('project');
foreach($projects as $projectID => $project)
{
if($project->model != 'waterfall') continue;
$projectStats = $this->project->getWaterfallPVEVAC($projectID);
$stats[$projectID]['totalEstimate'] = $projectStats['PV'];
$stats[$projectID]['totalConsumed'] = $projectStats['AC'];
$stats[$projectID]['totalLeft'] = $projectStats['left'];
if(empty($project->deleted))
{
$stats[$projectID]['totalConsumedNotDel'] = $projectStats['AC'];
$stats[$projectID]['totalLeftNotDel'] = $projectStats['left'];
}
}
foreach($teamMembers as $projectID => $teamCount)
{
if(!isset($stats[$projectID])) $stats[$projectID] = array('totalEstimate' => 0, 'totalConsumed' => 0, 'totalLeft' => 0, 'teamCount' => 0, 'totalConsumedNotDel' => 0, 'totalLeftNotDel' => 0);
@@ -1401,14 +1404,14 @@ class programModel extends model
->set('progress')->eq($progress)
->set('teamCount')->eq($project['teamCount'])
->set('estimate')->eq($project['totalEstimate'])
->set('consumed')->eq($project['totalConsumed'])
->set('left')->eq($project['totalLeft'])
->set('consumed')->eq($project['totalConsumedNotDel'])
->set('left')->eq($project['totalLeftNotDel'])
->where('id')->eq($projectID)
->exec();
}
/* 5. Update programStatsTime. */
$projectList = $this->dao->select('id,progress,path')->from(TABLE_PROJECT)
$projectList = $this->dao->select('id,progress,path,consumed,`left`')->from(TABLE_PROJECT)
->where('type')->eq('project')
->andWhere('parent')->ne(0)
->andWhere('deleted')->eq(0)
@@ -1421,19 +1424,18 @@ class programModel extends model
foreach($path as $programID)
{
if($programID == $projectID) continue;
$programProgress[$programID][] = $project->progress;
if(!isset($programProgress[$programID])) $programProgress[$programID] = array('consumed' => 0, 'left' => 0);
$programProgress[$programID]['consumed'] += $project->consumed;
$programProgress[$programID]['left'] += $project->left;
}
}
foreach($programProgress as $programID => $progress)
foreach($programProgress as $programID => $hours)
{
$count = count($progress);
$sum = array_sum($progress);
$average = round($sum / $count, 2);
$this->dao->update(TABLE_PROJECT)
->set('progress')->eq($average)
->where('id')->eq($programID)
->exec();
$progress = ($hours['consumed'] + $hours['left']) ? floor($hours['consumed'] / ($hours['consumed'] + $hours['left']) * 1000) / 1000 * 100 : 0;
$this->dao->update(TABLE_PROJECT)->set('progress')->eq($progress)->where('id')->eq($programID)->exec();
}
/* 6. Update projectStatsTime in config. */
+3 -3
View File
@@ -338,7 +338,7 @@ class programplanModel extends model
if(($today > $end) and $plan->status != 'closed')
{
$data->delay = $this->lang->programplan->delayList[1];
$data->delayDays = helper::diffDate($today, substr($end, 0, 10));
$data->delayDays = helper::diffDate(($task->status == 'done' || $task->status == 'closed') ? substr($task->finishedDate, 0, 10) : $today, substr($end, 0, 10));
}
/* If multi task then show the teams. */
@@ -361,14 +361,14 @@ class programplanModel extends model
{
$stageIndex[$index]['progress']['totalEstimate'] += $task->estimate;
$stageIndex[$index]['progress']['totalConsumed'] += $task->parent == '-1' ? 0 : $task->consumed;
$stageIndex[$index]['progress']['totalReal'] += ($task->left + $task->consumed);
$stageIndex[$index]['progress']['totalReal'] += ((($task->status == 'closed' || $task->status == 'cancel') ? 0 : $task->left) + $task->consumed);
$parent = $stage['parent'];
if(isset($stageIndex[$parent]))
{
$stageIndex[$parent]['progress']['totalEstimate'] += $task->estimate;
$stageIndex[$parent]['progress']['totalConsumed'] += $task->parent == '-1' ? 0 : $task->consumed;
$stageIndex[$parent]['progress']['totalReal'] += ($task->left + $task->consumed);
$stageIndex[$parent]['progress']['totalReal'] += ((($task->status == 'closed' || $task->status == 'cancel') ? 0 : $task->left) + $task->consumed);
}
}
}
+1 -1
View File
@@ -101,7 +101,7 @@ class project extends control
if($this->config->edition != 'open') list($fields, $projects) = $this->loadModel('workflowfield')->appendDataFromFlow($fields, $projects);
$this->post->set('fields', $fields);
$this->post->set('rows', $projects);
$this->post->set('kind', $this->lang->project->common);
$this->post->set('kind', 'project');
$this->fetch('file', 'export2' . $this->post->fileType, $_POST);
}
+24
View File
@@ -0,0 +1,24 @@
$(function()
{
$('#testtaskForm').table(
{
replaceId: 'taskIdList',
statisticCreator: function(table)
{
var $table = table.getTable();
var $checkedRows = $table.find('tbody>tr.checked');
var checkedTotal = $checkedRows.length;
var checkedWait = $checkedRows.filter("[data-status=wait]").length;
var checkedTesting = $checkedRows.filter("[data-status=doing]").length;
var checkedBlocked = $checkedRows.filter("[data-status=blocked]").length;
var checkedDone = $checkedRows.filter("[data-status=done]").length;
var checkedStatistics = checkedAllSummary.replace('%total%', checkedTotal)
.replace('%wait%', checkedWait)
.replace('%testing%', checkedTesting)
.replace('%blocked%', checkedBlocked)
.replace('%done%', checkedDone);
return checkedTotal ? checkedStatistics : pageSummary;
}
});
});
+31 -10
View File
@@ -13,7 +13,7 @@
<?php include '../../common/view/header.html.php';?>
<?php js::set('confirmDelete', $lang->testtask->confirmDelete)?>
<?php if($project->hasProduct):?>
<style>.tfoot {margin-left: 205px}</style>
<style>.table-footer {margin-left: 205px}</style>
<?php endif;?>
<div id="mainMenu" class="clearfix">
<div class="btn-toolbar pull-left">
@@ -36,6 +36,12 @@
<?php endif;?>
</div>
</div>
<?php
$waitCount = 0;
$testingCount = 0;
$blockedCount = 0;
$doneCount = 0;
?>
<div id="mainContent">
<?php if(empty($tasks)):?>
<div class="table-empty-tip">
@@ -47,14 +53,19 @@
</p>
</div>
<?php else:?>
<form class="main-table table-testtask" data-ride="table" data-group="true" method="post" target='hiddenwin' id='testtaskForm'>
<form class="main-table table-testtask" data-group="true" method="post" target='hiddenwin' id='testtaskForm'>
<table class="table table-grouped has-sort-head" id='taskList'>
<thead>
<?php $vars = "projectID=$projectID&orderBy=%s&recTotal={$pager->recTotal}&recPerPage={$pager->recPerPage}&pageID={$pager->pageID}";?>
<?php $canTestReport = ($canBeChanged and common::hasPriv('testreport', 'browse'));?>
<?php $canTestReport = ($canBeChanged and common::hasPriv('testreport', 'browse') and !$project->multiple);?>
<tr class='<?php if($total and $project->hasProduct) echo 'divider'; ?>'>
<th class='c-side text-center <?php if(!$project->hasProduct) echo 'hide';?>'><?php common::printOrderLink('product', $orderBy, $vars, $lang->testtask->product);?></th>
<th class="c-id">
<?php if($canTestReport):?>
<div class="checkbox-primary check-all" title="<?php echo $lang->selectAll?>">
<label></label>
</div>
<?php endif;?>
<?php common::printOrderLink('id', $orderBy, $vars, $lang->idAB);?>
</th>
<th><?php common::printOrderLink('name', $orderBy, $vars, $lang->testtask->name);?></th>
@@ -67,12 +78,6 @@
</tr>
</thead>
<tbody>
<?php
$waitCount = 0;
$testingCount = 0;
$blockedCount = 0;
$doneCount = 0;
?>
<?php foreach($tasks as $product => $productTasks):?>
<?php $productName = zget($products, $product, '');?>
<?php foreach($productTasks as $task):?>
@@ -80,7 +85,7 @@
<?php if($task->status == 'doing') $testingCount ++;?>
<?php if($task->status == 'blocked') $blockedCount ++;?>
<?php if($task->status == 'done') $doneCount ++;?>
<tr data-id='<?php echo $product;?>' <?php if($task == reset($productTasks)) echo "class='divider-top'";?>>
<tr data-id='<?php echo $product;?>' <?php if($task == reset($productTasks)) echo "class='divider-top'";?> data-status='<?php echo $task->status;?>'>
<?php if($task == reset($productTasks)):?>
<td rowspan='<?php echo count($productTasks);?>' class='c-side text-left group-toggle <?php if(!$project->hasProduct) echo 'hide';?>'>
<a class='text-primary' title='<?php echo $productName;?>'><i class='icon icon-caret-down'></i> <?php echo $productName;?></a>
@@ -88,7 +93,11 @@
</td>
<?php endif;?>
<td class="c-id">
<?php if($canTestReport):?>
<?php echo html::checkbox('taskIdList', array($task->id => sprintf('%03d', $task->id)));?>
<?php else:?>
<?php printf('%03d', $task->id);?>
<?php endif;?>
</td>
<td class='text-left' title="<?php echo $task->name?>"><?php echo html::a($this->createLink('testtask', 'cases', "taskID=$task->id"), $task->name, '', "data-app='project'");?></td>
<td title="<?php echo $task->buildName?>">
@@ -139,10 +148,22 @@
</tbody>
</table>
<div class="table-footer">
<?php if($canTestReport):?>
<div class="checkbox-primary check-all"><label><?php echo $lang->selectAll?></label></div>
<div class="table-actions btn-toolbar">
<?php
$actionLink = $this->createLink('project', 'testreport', "objectID=$projectID&objctType=project");
$misc = common::hasPriv('testreport', 'browse') ? "onclick=\"setFormAction('$actionLink', '', '#testtaskForm')\"" : "disabled='disabled'";
echo html::commonButton($lang->testreport->common, $misc);
?>
</div>
<?php endif;?>
<div class="table-statistic"><?php echo sprintf($lang->testtask->allSummary, $total, $waitCount, $testingCount, $blockedCount, $doneCount);?></div>
<?php $pager->show('right', 'pagerjs');?>
</div>
</form>
<?php endif;?>
</div>
<?php js::set('pageSummary', sprintf($lang->testtask->allSummary, $total, $waitCount, $testingCount, $blockedCount, $doneCount));?>
<?php js::set('checkedAllSummary', $lang->testtask->checkedAllSummary);?>
<?php include '../../common/view/footer.html.php';?>
+2 -3
View File
@@ -204,10 +204,9 @@
<tr class='statsTr'><td></td><td></td><td></td><td></td></tr>
<tr>
<td colspan="4">
<?php $progress = $project->model == 'waterfall' ? $this->project->getWaterfallProgress($project->id) : (((float)$workhour->totalConsumed + (float)$workhour->totalLeft) ? floor($workhour->totalConsumed / ((float)$workhour->totalConsumed + (float)$workhour->totalLeft) * 1000) / 1000 * 100 : 0);?>
<?php echo $lang->project->progress;?> <?php echo $progress . $lang->percent;?> &nbsp;
<?php echo $lang->project->progress;?> <?php echo $project->progress . $lang->percent;?> &nbsp;
<div class="progress inline-block">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="<?php echo $progress;?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo $progress . $lang->percent;?>"></div>
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="<?php echo $project->progress;?>" aria-valuemin="0" aria-valuemax="100" style="width: <?php echo $project->progress . $lang->percent;?>"></div>
</div>
</td>
</tr>
+1 -1
View File
@@ -263,7 +263,7 @@ $config->task->datatable->fieldList['mailto']['required'] = 'no';
$config->task->datatable->fieldList['module']['title'] = 'module';
$config->task->datatable->fieldList['module']['control'] = 'select';
$config->task->datatable->fieldList['module']['dataSource'] = array('module' => 'tree', 'method' => 'getTaskOptionMenu', 'params' => '$executionID');
$config->task->datatable->fieldList['module']['dataSource'] = array('module' => 'tree', 'method' => 'getAllModulePairs');
$config->task->datatable->fieldList['module']['display'] = false;
$config->task->datatable->fieldList['execution']['title'] = 'execution';
+1 -1
View File
@@ -226,7 +226,7 @@ class testcase extends control
$this->config->testcase->search['onMenuBar'] = 'yes';
$searchProducts = $this->product->getPairs('', 0, '', 'all');
$this->testcase->buildSearchForm($productID, $searchProducts, $queryID, $actionURL, $projectID);
$this->testcase->buildSearchForm($productID, $searchProducts, $queryID, $actionURL, $projectID, 0, $branch);
$showModule = !empty($this->config->datatable->testcaseBrowse->showModule) ? $this->config->datatable->testcaseBrowse->showModule : '';
+1
View File
@@ -246,6 +246,7 @@ $lang->testcase->mustChooseResult = 'Prüfungsergebnis wird benötigt.';
$lang->testcase->noModule = '<div>Es existieren keine Module</div><div>Jetzt verwalten</div>';
$lang->testcase->noCase = 'Keine Fälle. ';
$lang->testcase->importedCases = 'The case with ID%s has been imported in the same module and has been ignored.';
$lang->testcase->importedFromLib = '%s items imported successfully: %s.';
$lang->testcase->searchStories = 'Story suchen';
$lang->testcase->selectLib = 'Bibliothek wählen';
+1
View File
@@ -246,6 +246,7 @@ $lang->testcase->mustChooseResult = 'Review result is required.';
$lang->testcase->noModule = '<div>You have no modules.</div><div>Manage it now.</div>';
$lang->testcase->noCase = 'No cases yet. ';
$lang->testcase->importedCases = 'The case with ID%s has been imported in the same module and has been ignored.';
$lang->testcase->importedFromLib = '%s items imported successfully: %s.';
$lang->testcase->searchStories = 'Enter to search for stories';
$lang->testcase->selectLib = 'Select Library';
+1
View File
@@ -246,6 +246,7 @@ $lang->testcase->mustChooseResult = 'La Validation du résultat est nécessaire.
$lang->testcase->noModule = "<div>Vous n'avez aucun modules.</div><div>Gérer les modules maintenant.</div>";
$lang->testcase->noCase = "Aucun CasTest pour l'instant. ";
$lang->testcase->importedCases = 'Le cas d\'utilisation avec l\'ID %s est déjà importé dans le même module, il est donc ignoré.';
$lang->testcase->importedFromLib = '%s items imported successfully: %s.';
$lang->testcase->searchStories = 'Rechercher des stories';
$lang->testcase->selectLib = 'Sélectionner Library';
+1
View File
@@ -246,6 +246,7 @@ $lang->testcase->mustChooseResult = '必须选择评审结果';
$lang->testcase->noModule = '<div>您现在还没有模块信息</div><div>请维护测试模块</div>';
$lang->testcase->noCase = '暂时没有用例。';
$lang->testcase->importedCases = 'ID为 %s 的用例在相同模块已经导入,已忽略。';
$lang->testcase->importedFromLib = '导入成功%s项:%s。';
$lang->testcase->searchStories = "键入来搜索{$lang->SRCommon}";
$lang->testcase->selectLib = '请选择库';
+15 -8
View File
@@ -1930,10 +1930,11 @@ class testcaseModel extends model
$caseModules[$branch] = $this->loadModel('testsuite')->getCanImportModules($productID, $libID, $branch);
}
$libCases = $this->dao->select('*')->from(TABLE_CASE)->where('deleted')->eq(0)->andWhere('id')->in($data->caseIdList)->fetchAll('id');
$libSteps = $this->dao->select('*')->from(TABLE_CASESTEP)->where('`case`')->in($data->caseIdList)->orderBy('id')->fetchGroup('case');
$libFiles = $this->dao->select('*')->from(TABLE_FILE)->where('objectID')->in($data->caseIdList)->andWhere('objectType')->eq('testcase')->fetchGroup('objectID', 'id');
$imported = '';
$libCases = $this->dao->select('*')->from(TABLE_CASE)->where('deleted')->eq(0)->andWhere('id')->in($data->caseIdList)->fetchAll('id');
$libSteps = $this->dao->select('*')->from(TABLE_CASESTEP)->where('`case`')->in($data->caseIdList)->orderBy('id')->fetchGroup('case');
$libFiles = $this->dao->select('*')->from(TABLE_FILE)->where('objectID')->in($data->caseIdList)->andWhere('objectType')->eq('testcase')->fetchGroup('objectID', 'id');
$hasImported = '';
$importedCases = array();
foreach($libCases as $libCaseID => $case)
{
$case->fromCaseID = $case->id;
@@ -1946,7 +1947,7 @@ class testcaseModel extends model
$branch = isset($case->branch) ? $case->branch : 0;
if(empty($caseModules[$branch][$case->fromCaseID][$case->module]))
{
$imported .= "$case->fromCaseID,";
$hasImported .= "$case->fromCaseID,";
continue;
}
@@ -1991,12 +1992,18 @@ class testcaseModel extends model
unset($file->id);
$this->dao->insert(TABLE_FILE)->data($file)->exec();
}
$importedCases[] = $libCaseID;
$this->loadModel('action')->create('case', $caseID, 'fromlib', '', $case->lib);
}
if(!empty($imported))
if(!empty($importedCases)) print(js::alert(sprintf($this->lang->testcase->importedFromLib, count($importedCases), implode(',', $importedCases))));
if(!empty($hasImported))
{
$imported = trim($imported, ',');
return print(js::error(sprintf($this->lang->testcase->importedCases, $imported)));
$hasImported = trim($hasImported, ',');
return print(js::error(sprintf($this->lang->testcase->importedCases, $hasImported)));
}
}
+5 -1
View File
@@ -302,9 +302,13 @@ class testreport extends control
list($bugInfo, $bugSummary) = $this->testreport->getBug4Report($tasks, $productIdList, $begin, $end, $builds);
$members = $this->dao->select('DISTINCT lastRunner')->from(TABLE_TESTRUN)->where('task')->in(array_keys($tasks))->fetchPairs('lastRunner', 'lastRunner');
$taskMembers = explode(',', $task->members);
$members = array_merge($members, $taskMembers);
$this->view->begin = $begin;
$this->view->end = $end;
$this->view->members = $this->dao->select('DISTINCT lastRunner')->from(TABLE_TESTRUN)->where('task')->in(array_keys($tasks))->fetchPairs('lastRunner', 'lastRunner');
$this->view->members = $members;
$this->view->owner = $owner;
$this->view->stories = $stories;
+13
View File
@@ -1660,4 +1660,17 @@ class testtask extends control
$result = $this->dao->select('*')->from(TABLE_TESTRESULT)->where('id')->eq((int)$resultID)->fetch();
$this->send(array('result' => 'success', 'message' => '', 'data' => $result));
}
/**
* AJAX: Get executionID by buildID.
*
* @param int $buildID
* @access public
* @return int
*/
public function ajaxGetExecutionByBuild($buildID)
{
$execution = $this->loadModel('execution')->getByBuild($buildID);
return print($execution ? $execution->id : 0);
}
}
+11
View File
@@ -32,6 +32,17 @@ function loadExecutions(productID)
});
}
$('#mainContent').on('change', '#build', function()
{
var buildID = $(this).val();
link = createLink('testtask', 'ajaxGetExecutionByBuild', 'buildID=' + buildID);
$.get(link, function(data)
{
$('#execution').val(data);
$("#execution").trigger("chosen:updated");
});
})
/* If the mouse hover over the manage contacts button, give tip. */
$(function()
{
+11
View File
@@ -3,3 +3,14 @@ $(function()
adjustPriBoxWidth();
if(config.onlybody) $('#ownerAndPriBox .picker-selection').css('width', '123px');
})
$('#mainContent').on('change', '#build', function()
{
var buildID = $(this).val();
link = createLink('testtask', 'ajaxGetExecutionByBuild', 'buildID=' + buildID);
$.get(link, function(data)
{
$('#execution').val(data);
$("#execution").trigger("chosen:updated");
});
})
+3
View File
@@ -58,6 +58,7 @@ $lang->testtask->run = 'Test Run ID';
$lang->testtask->job = 'Job';
$lang->testtask->compile = 'Compile';
$lang->testtask->duration = 'Duration';
$lang->testtask->myInvolved = 'Involved';
$lang->testtask->viewAction = "View Request";
$lang->testtask->casesAction = 'Browse Cases List';
@@ -76,6 +77,7 @@ $lang->testtask->execution = $lang->execution->common;
$lang->testtask->type = 'Typ';
$lang->testtask->build = 'Build';
$lang->testtask->owner = 'Besitzer';
$lang->testtask->members = 'Participant';
$lang->testtask->executor = 'Executor';
$lang->testtask->execTime = 'Exec Time';
$lang->testtask->pri = 'Priorität';
@@ -202,6 +204,7 @@ $lang->testtask->report->options->width = 500;
$lang->testtask->report->options->height = 140;
$lang->testtask->featureBar['browse']['totalStatus'] = $lang->testtask->totalStatus;
$lang->testtask->featureBar['browse']['myinvolved'] = $lang->testtask->myInvolved;
$lang->testtask->featureBar['browse']['wait'] = $lang->testtask->wait;
$lang->testtask->featureBar['browse']['doing'] = $lang->testtask->testing;
$lang->testtask->featureBar['browse']['blocked'] = $lang->testtask->blocked;
+3
View File
@@ -58,6 +58,7 @@ $lang->testtask->run = 'Test Run ID';
$lang->testtask->job = 'Job';
$lang->testtask->compile = 'Compile';
$lang->testtask->duration = 'Duration';
$lang->testtask->myInvolved = 'Involved';
$lang->testtask->viewAction = "View Request";
$lang->testtask->casesAction = 'Browse Cases List';
@@ -76,6 +77,7 @@ $lang->testtask->execution = $lang->execution->common;
$lang->testtask->type = 'Type';
$lang->testtask->build = 'Build';
$lang->testtask->owner = 'Owner';
$lang->testtask->members = 'Participant';
$lang->testtask->executor = 'Executor';
$lang->testtask->execTime = 'Exec Time';
$lang->testtask->pri = 'Priority';
@@ -202,6 +204,7 @@ $lang->testtask->report->options->width = 500;
$lang->testtask->report->options->height = 140;
$lang->testtask->featureBar['browse']['totalStatus'] = $lang->testtask->totalStatus;
$lang->testtask->featureBar['browse']['myinvolved'] = $lang->testtask->myInvolved;
$lang->testtask->featureBar['browse']['wait'] = $lang->testtask->wait;
$lang->testtask->featureBar['browse']['doing'] = $lang->testtask->testing;
$lang->testtask->featureBar['browse']['blocked'] = $lang->testtask->blocked;
+3
View File
@@ -58,6 +58,7 @@ $lang->testtask->run = 'Test Run ID';
$lang->testtask->job = 'Job';
$lang->testtask->compile = 'Compile';
$lang->testtask->duration = 'Duration';
$lang->testtask->myInvolved = 'Involved';
$lang->testtask->viewAction = "View Request";
$lang->testtask->casesAction = 'Browse Cases List';
@@ -76,6 +77,7 @@ $lang->testtask->execution = $lang->execution->common;
$lang->testtask->type = 'Type';
$lang->testtask->build = 'Build';
$lang->testtask->owner = 'Owner';
$lang->testtask->members = 'Participant';
$lang->testtask->executor = 'Executeur';
$lang->testtask->execTime = 'Durée Exec';
$lang->testtask->pri = 'Priorité';
@@ -202,6 +204,7 @@ $lang->testtask->report->options->width = 500;
$lang->testtask->report->options->height = 140;
$lang->testtask->featureBar['browse']['totalStatus'] = $lang->testtask->totalStatus;
$lang->testtask->featureBar['browse']['myinvolved'] = $lang->testtask->myInvolved;
$lang->testtask->featureBar['browse']['wait'] = $lang->testtask->wait;
$lang->testtask->featureBar['browse']['doing'] = $lang->testtask->testing;
$lang->testtask->featureBar['browse']['blocked'] = $lang->testtask->blocked;
+3
View File
@@ -58,6 +58,7 @@ $lang->testtask->run = '执行编号';
$lang->testtask->job = '构建任务';
$lang->testtask->compile = '构建';
$lang->testtask->duration = '持续时间';
$lang->testtask->myInvolved = '由我参与';
$lang->testtask->viewAction = "测试单概况";
$lang->testtask->casesAction = '浏览用例列表';
@@ -76,6 +77,7 @@ $lang->testtask->execution = '所属' . $lang->execution->common;
$lang->testtask->type = '测试类型';
$lang->testtask->build = '版本';
$lang->testtask->owner = '负责人';
$lang->testtask->members = '参与人';
$lang->testtask->executor = '执行人';
$lang->testtask->execTime = '执行时间';
$lang->testtask->pri = '优先级';
@@ -202,6 +204,7 @@ $lang->testtask->report->options->width = 500;
$lang->testtask->report->options->height = 140;
$lang->testtask->featureBar['browse']['totalStatus'] = $lang->testtask->totalStatus;
$lang->testtask->featureBar['browse']['myinvolved'] = $lang->testtask->myInvolved;
$lang->testtask->featureBar['browse']['wait'] = $lang->testtask->wait;
$lang->testtask->featureBar['browse']['doing'] = $lang->testtask->testing;
$lang->testtask->featureBar['browse']['blocked'] = $lang->testtask->blocked;
+28 -5
View File
@@ -20,7 +20,7 @@ class testtaskModel extends model
* @access public
* @return void
*/
function create($projectID = 0)
public function create($projectID = 0)
{
if($this->post->execution)
{
@@ -28,16 +28,25 @@ class testtaskModel extends model
$projectID = $execution->project;
}
if($this->post->build && empty($projectID))
{
$build = $this->loadModel('build')->getById($this->post->build);
$projectID = $build->project;
}
$task = fixer::input('post')
->setDefault('build', '')
->setDefault('project', $projectID)
->setDefault('createdBy', $this->app->user->account)
->setDefault('createdDate', helper::now())
->setDefault('members', '')
->stripTags($this->config->testtask->editor->create['id'], $this->config->allowedTags)
->join('mailto', ',')
->join('type', ',')
->join('members', ',')
->remove('files,labels,uid,contactListMenu')
->get();
$task->members = trim($task->members, ',');
$task = $this->loadModel('file')->processImgURL($task, $this->config->testtask->editor->create['id'], $this->post->uid);
$this->dao->insert(TABLE_TESTTASK)->data($task)
@@ -87,8 +96,9 @@ class testtaskModel extends model
->beginIF(!$this->app->user->admin)->andWhere('t1.execution')->in("0,{$this->app->user->view->sprints}")->fi()
->beginIF($scopeAndStatus[0] == 'local')->andWhere('t1.product')->eq((int)$productID)->fi()
->beginIF($scopeAndStatus[0] == 'all')->andWhere('t1.product')->in($products)->fi()
->beginIF(strtolower($scopeAndStatus[1]) == 'myinvolved')->andWhere("FIND_IN_SET('{$this->app->user->account}', t1.members)")->fi()
->beginIF(strtolower($scopeAndStatus[1]) == 'totalstatus')->andWhere('t1.status')->in('blocked,doing,wait,done')->fi()
->beginIF(!in_array(strtolower($scopeAndStatus[1]), array('totalstatus', 'review'), true))->andWhere('t1.status')->eq($scopeAndStatus[1])->fi()
->beginIF(!in_array(strtolower($scopeAndStatus[1]), array('totalstatus', 'review', 'myinvolved'), true))->andWhere('t1.status')->eq($scopeAndStatus[1])->fi()
->beginIF($branch !== 'all')->andWhere("CONCAT(',', t4.branch, ',')")->like("%,$branch,%")->fi()
->beginIF($beginTime)->andWhere('t1.begin')->ge($beginTime)->fi()
->beginIF($endTime)->andWhere('t1.end')->le($endTime)->fi()
@@ -105,6 +115,7 @@ class testtaskModel extends model
->orderBy($orderBy)
->page($pager)
->fetchAll('id');
foreach($tasks as $taskID => $task)
{
if($task->multiple)
@@ -773,15 +784,26 @@ class testtaskModel extends model
->setDefault('type', '')
->setDefault('mailto', '')
->setDefault('deleteFiles', array())
->setDefault('members', '')
->stripTags($this->config->testtask->editor->edit['id'], $this->config->allowedTags)
->join('mailto', ',')
->join('type', ',')
->join('members', ',')
->remove('files,labels,uid,comment,contactListMenu')
->get();
$task->members = trim($task->members, ',');
/* Fix bug #35419. */
$execution = $this->loadModel('execution')->getByID($task->execution);
$task->project = $execution->project;
$execution = $this->loadModel('execution')->getByID($task->execution);
if(!$execution)
{
$build = $this->loadModel('build')->getById($task->build);
$task->project = $build->project;
}
else
{
$task->project = $execution->project;
}
$task = $this->loadModel('file')->processImgURL($task, $this->config->testtask->editor->edit['id'], $this->post->uid);
@@ -1777,7 +1799,7 @@ class testtaskModel extends model
public function getToAndCcList($testtask)
{
/* Set toList and ccList. */
$toList = $testtask->owner;
$toList = $testtask->owner . ',' . $testtask->members . ',';
$ccList = str_replace(' ', '', trim($testtask->mailto, ','));
if(empty($toList))
@@ -1795,6 +1817,7 @@ class testtaskModel extends model
$ccList = substr($ccList, $commaPos + 1);
}
}
return array($toList, $ccList);
}
+5
View File
@@ -78,6 +78,7 @@ $status = strtolower($status);
<th class='text-left'> <?php common::printOrderLink('execution', $orderBy, $vars, $lang->testtask->execution);?></th>
<th class='c-status text-left'><?php common::printOrderLink('status', $orderBy, $vars, $lang->statusAB);?></th>
<th class='c-user text-left'> <?php common::printOrderLink('owner', $orderBy, $vars, $lang->testtask->owner);?></th>
<th class='c-user text-left'> <?php common::printOrderLink('members', $orderBy, $vars, $lang->testtask->members);?></th>
<th class='c-date text-left'> <?php common::printOrderLink('begin', $orderBy, $vars, $lang->testtask->begin);?></th>
<th class='c-date text-left'> <?php common::printOrderLink('end', $orderBy, $vars, $lang->testtask->end);?></th>
<?php
@@ -114,6 +115,10 @@ $status = strtolower($status);
</span>
</td>
<td title="<?php echo zget($users, $task->owner);?>"><?php echo zget($users, $task->owner);?></td>
<?php $members = array()?>
<?php foreach(explode(',', $task->members) as $member) $members[] = zget($users, $member);?>
<?php $members = implode(',', $members)?>
<td title="<?php echo $members;?>"><?php echo $members;?></td>
<td><?php echo $task->begin?></td>
<td><?php echo $task->end?></td>
<?php foreach($extendFields as $extendField) echo "<td>" . $this->loadModel('flow')->getFieldValue($extendField, $task) . "</td>";?>
+4
View File
@@ -73,6 +73,10 @@
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->testtask->members;?></th>
<td><?php echo html::select('members[]', $users, '', "class='form-control picker-select' multiple")?></td>
</tr>
<tr>
<th><?php echo $lang->testtask->begin;?></th>
<td>
+6
View File
@@ -56,6 +56,12 @@
</div>
</td>
</tr>
<tr>
<th><?php echo $lang->testtask->members;?></th>
<td>
<?php echo html::select('members[]', $users, $task->members, "class='form-control picker-select' multiple");?>
</td>
</tr>
<tr>
<th><?php echo $lang->testtask->begin;?></th>
<td>
+6
View File
@@ -152,6 +152,11 @@ class transfer extends control
{
$filter = '';
if($model == 'task') $filter = 'estimate';
if($model == 'bug')
{
$this->loadModel('bug');
$this->config->bug->datatable->fieldList['execution']['dataSource'] = array('module' => 'product', 'method' =>'getAllExecutionPairsByProduct', 'params' => '$productID&$branch');
}
if($model == 'story' and $this->session->storyType == 'requirement') $this->loadModel('story')->replaceUserRequirementLang();
$this->loadModel($model);
@@ -198,6 +203,7 @@ class transfer extends control
{
$this->loadModel($model);
$fields = $this->config->$model->templateFields;
if($model == 'bug') $this->config->bug->datatable->fieldList['execution']['dataSource'] = array('module' => 'product', 'method' =>'getAllExecutionPairsByProduct', 'params' => '$productID&$branch');
if($this->config->edition != 'open')
{
+24
View File
@@ -707,6 +707,11 @@ class upgradeModel extends model
$this->processHistoryDataForMetric();
$this->loadModel('metric')->updateMetricDate();
break;
case '18_8':
/* Upgrade members for testtask. */
$this->upgradeTesttaskMembers();
$this->loadModel('program')->refreshStats(true);
break;
}
$this->deletePatch();
@@ -9878,4 +9883,23 @@ class upgradeModel extends model
}
$this->dao->commit();
}
/**
* Upgrade testtask members.
*
* @access public
* @return void
*/
public function upgradeTesttaskMembers()
{
$memberGroup = $this->dao->select('task,lastRunner')->from(TABLE_TESTRUN)
->where('lastRunner')->ne('')
->fetchGroup('task', 'lastRunner');
foreach($memberGroup as $taskID => $members)
{
$members = implode(',', array_keys($members));
$this->dao->update(TABLE_TESTTASK)->set('members')->eq($members)->where('id')->eq($taskID)->exec();
}
}
}
+8 -8
View File
@@ -90,15 +90,15 @@ EOD;
$lang->weekly->blockHelpNotice = <<<EOD
<h2>Progress this week</h2>
Calculation method:
<br />1) Progress of this week=total consumed man hours/(total consumed man hours+remaining man hours)
<br />1) Project progress = consumed task hours / (consumed task hours + remaining task hours) * 100%
<p>Statistical range:</p>
1) The total consumed man hours include task, demand, bug, use case, version, test sheet, problem, risk, document and review time
<br />2) To avoid repeated calculation, the task only contains child tasks, not parent tasks
<br />3) Including deleted tasks, requirements, bugs, use cases, versions, test sheets, problems, risks, documents, and consumed man hours in reviews
<br />4) This includes the work hours consumed by deleted tasks, requirements, bugs, use cases, versions, test sheets, and documents
<br />5) Including work hours consumed by cancelled tasks, problems and risks
<br />6) Exclude remaining work on canceled tasks
<br />7) Exclude remaining work for deleted tasks in progress
1) Only the working hour consumption data of the task is counted
<br />2) To avoid repeated calculation, the task working hours only include child tasks, not parent tasks
<br />3) Including the working hours consumed by canceled tasks
<br />4) Excluding the working hours consumed in deleted tasks
<br />5) Excluding the working hours consumed in deleted tasks in progress
<br />6) Excluding the remaining working hours of canceled tasks
<br />7) Excluding the remaining working hours of deleted tasks in progress
<h2>PV Planned Value</h2>
Calculation method:
<br />1) The estimated start date and end date of the task are within the range of the start and end dates of this week, and the estimated work hours are accumulated
+8 -8
View File
@@ -90,15 +90,15 @@ EOD;
$lang->weekly->blockHelpNotice = <<<EOD
<h2>Progress this week</h2>
Calculation method:
<br />1) Progress of this week=total consumed man hours/(total consumed man hours+remaining man hours)
<br />1) Project progress = consumed task hours / (consumed task hours + remaining task hours) * 100%
<p>Statistical range:</p>
1) The total consumed man hours include task, demand, bug, use case, version, test sheet, problem, risk, document and review time
<br />2) To avoid repeated calculation, the task only contains child tasks, not parent tasks
<br />3) Including deleted tasks, requirements, bugs, use cases, versions, test sheets, problems, risks, documents, and consumed man hours in reviews
<br />4) This includes the work hours consumed by deleted tasks, requirements, bugs, use cases, versions, test sheets, and documents
<br />5) Including work hours consumed by cancelled tasks, problems and risks
<br />6) Exclude remaining work on canceled tasks
<br />7) Exclude remaining work for deleted tasks in progress
1) Only the working hour consumption data of the task is counted
<br />2) To avoid repeated calculation, the task working hours only include child tasks, not parent tasks
<br />3) Including the working hours consumed by canceled tasks
<br />4) Excluding the working hours consumed in deleted tasks
<br />5) Excluding the working hours consumed in deleted tasks in progress
<br />6) Excluding the remaining working hours of canceled tasks
<br />7) Excluding the remaining working hours of deleted tasks in progress
<h2>PV Planned Value</h2>
Calculation method:
<br />1) The estimated start date and end date of the task are within the range of the start and end dates of this week, and the estimated work hours are accumulated
+8 -8
View File
@@ -90,15 +90,15 @@ EOD;
$lang->weekly->blockHelpNotice = <<<EOD
<h2>Progress this week</h2>
Calculation method:
<br />1) Progress of this week=total consumed man hours/(total consumed man hours+remaining man hours)
<br />1) Project progress = consumed task hours / (consumed task hours + remaining task hours) * 100%
<p>Statistical range:</p>
1) The total consumed man hours include task, demand, bug, use case, version, test sheet, problem, risk, document and review time
<br />2) To avoid repeated calculation, the task only contains child tasks, not parent tasks
<br />3) Including deleted tasks, requirements, bugs, use cases, versions, test sheets, problems, risks, documents, and consumed man hours in reviews
<br />4) This includes the work hours consumed by deleted tasks, requirements, bugs, use cases, versions, test sheets, and documents
<br />5) Including work hours consumed by cancelled tasks, problems and risks
<br />6) Exclude remaining work on canceled tasks
<br />7) Exclude remaining work for deleted tasks in progress
1) Only the working hour consumption data of the task is counted
<br />2) To avoid repeated calculation, the task working hours only include child tasks, not parent tasks
<br />3) Including the working hours consumed by canceled tasks
<br />4) Excluding the working hours consumed in deleted tasks
<br />5) Excluding the working hours consumed in deleted tasks in progress
<br />6) Excluding the remaining working hours of canceled tasks
<br />7) Excluding the remaining working hours of deleted tasks in progress
<h2>PV Planned Value</h2>
Calculation method:
<br />1) The estimated start date and end date of the task are within the range of the start and end dates of this week, and the estimated work hours are accumulated
+6 -6
View File
@@ -90,13 +90,13 @@ EOD;
$lang->weekly->blockHelpNotice = <<<EOD
<h2>本周进度</h2>
计算方式:
<br />1)本周进度=总消耗工时/(总消耗工时+剩余工时)
<br />1)项目进度=已消耗任务工时 /(已消耗任务工时 + 剩余任务工时)*100%
<p>统计范围:</p>
1)总消耗的工时包括任务、需求、Bug、用例、版本、测试单、问题、风险、文档、评审的耗时
<br />2)为避免重复计算,任务只包含子任务,不包括父任务
<br />3)包括已删除任务、需求、Bug、用例、版本、测试单、问题、风险、文档、评审中已消耗的工时
<br />4)包括已删除执行中任务、需求、Bug、用例、版本、测试单、文档已消耗的工时
<br />5)包括已取消任务、问题、风险已消耗的工时
1)只统计任务的工时消耗数据。
<br />2)为避免重复计算,任务工时只包含子任务,不包括父任务
<br />3)包括已取消任务消耗的工时
<br />4)不包括已删除任务中消耗的工时
<br />5)不包括已删除执行中任务消耗的工时
<br />6)不包括已取消任务的剩余工时
<br />7)不包括已删除执行中任务的剩余工时
<h2>PV 计划完成的工作</h2>