* Finish task#38171,#38168.

This commit is contained in:
hufangzhou
2021-05-14 17:10:45 +08:00
parent b2c6bcb6fc
commit c86827e39c
21 changed files with 87 additions and 39 deletions
+2 -2
View File
@@ -249,5 +249,5 @@ $lang->custom->conceptOptions->hourPoint['2'] = 'Function Point';
$lang->custom->scrum = new stdclass();
$lang->custom->scrum->setConcept = 'Set concept';
$lang->custom->reviewRules[1] = 'All passed';
$lang->custom->reviewRules[0] = 'More than half passed';
$lang->custom->reviewRules['allpass'] = 'All passed';
$lang->custom->reviewRules['halfpass'] = 'More than half passed';
+2 -2
View File
@@ -250,5 +250,5 @@ $lang->custom->conceptOptions->hourPoint['2'] = 'Function Point';
$lang->custom->scrum = new stdclass();
$lang->custom->scrum->setConcept = 'Set concept';
$lang->custom->reviewRules[1] = 'All passed';
$lang->custom->reviewRules[0] = 'More than half passed';
$lang->custom->reviewRules['allpass'] = 'All passed';
$lang->custom->reviewRules['halfpass'] = 'More than half passed';
+2 -2
View File
@@ -249,5 +249,5 @@ $lang->custom->conceptOptions->hourPoint['2'] = 'Function Point';
$lang->custom->scrum = new stdclass();
$lang->custom->scrum->setConcept = 'Set concept';
$lang->custom->reviewRules[1] = 'All passed';
$lang->custom->reviewRules[0] = 'More than half passed';
$lang->custom->reviewRules['allpass'] = 'All passed';
$lang->custom->reviewRules['halfpass'] = 'More than half passed';
+2 -2
View File
@@ -249,5 +249,5 @@ $lang->custom->conceptOptions->hourPoint['2'] = 'Function Point';
$lang->custom->scrum = new stdclass();
$lang->custom->scrum->setConcept = 'Set concept';
$lang->custom->reviewRules[1] = 'All passed';
$lang->custom->reviewRules[0] = 'More than half passed';
$lang->custom->reviewRules['allpass'] = 'All passed';
$lang->custom->reviewRules['halfpass'] = 'More than half passed';
+2 -2
View File
@@ -251,5 +251,5 @@ $lang->custom->conceptOptions->hourPoint['2'] = '功能点';
$lang->custom->scrum = new stdclass();
$lang->custom->scrum->setConcept = '设置项目概念';
$lang->custom->reviewRules[1] = '全部通过通过';
$lang->custom->reviewRules[0] = '半数以上通过通过';
$lang->custom->reviewRules['allpass'] = '全部通过通过';
$lang->custom->reviewRules['halfpass'] = '半数以上通过通过';
+2 -2
View File
@@ -250,5 +250,5 @@ $lang->custom->conceptOptions->hourPoint['2'] = '功能點';
$lang->custom->scrum = new stdclass();
$lang->custom->scrum->setConcept = '設置項目概念';
$lang->custom->reviewRules[1] = '全部通過通過';
$lang->custom->reviewRules[0] = '半數以上通過通過';
$lang->custom->reviewRules['allpass'] = '全部通過通過';
$lang->custom->reviewRules['halfpass'] = '半數以上通過通過';
+1
View File
@@ -60,6 +60,7 @@ $lang->my->taskMenu->canceledByMe = 'CancelledByMe';
$lang->my->storyMenu = new stdclass();
$lang->my->storyMenu->assignedToMe = 'AssignedToMe';
$lang->my->storyMenu->reviewByMe = 'ReviewByMe';
$lang->my->storyMenu->openedByMe = 'CreatedByMe';
$lang->my->storyMenu->reviewedByMe = 'ReviewedByMe';
$lang->my->storyMenu->closedByMe = 'ClosedByMe';
+1
View File
@@ -67,6 +67,7 @@ $lang->my->taskMenu->canceledByMe = 'CancelledByMe';
$lang->my->storyMenu = new stdclass();
$lang->my->storyMenu->assignedToMe = 'AssignedToMe';
$lang->my->storyMenu->reviewByMe = 'ReviewByMe';
$lang->my->storyMenu->openedByMe = 'CreatedByMe';
$lang->my->storyMenu->reviewedByMe = 'ReviewedByMe';
$lang->my->storyMenu->closedByMe = 'ClosedByMe';
+1
View File
@@ -60,6 +60,7 @@ $lang->my->taskMenu->canceledByMe = 'CancelledByMe';
$lang->my->storyMenu = new stdclass();
$lang->my->storyMenu->assignedToMe = 'AssignedToMe';
$lang->my->storyMenu->reviewByMe = 'ReviewByMe';
$lang->my->storyMenu->openedByMe = 'CreatedByMe';
$lang->my->storyMenu->reviewedByMe = 'ReviewedByMe';
$lang->my->storyMenu->closedByMe = 'ClosedByMe';
+1
View File
@@ -60,6 +60,7 @@ $lang->my->taskMenu->canceledByMe = 'CancelledByMe';
$lang->my->storyMenu = new stdclass();
$lang->my->storyMenu->assignedToMe = 'AssignedToMe';
$lang->my->storyMenu->reviewByMe = 'ReviewByMe';
$lang->my->storyMenu->openedByMe = 'CreatedByMe';
$lang->my->storyMenu->reviewedByMe = 'ReviewedByMe';
$lang->my->storyMenu->closedByMe = 'ClosedByMe';
+1
View File
@@ -67,6 +67,7 @@ $lang->my->taskMenu->canceledByMe = '由我取消';
$lang->my->storyMenu = new stdclass();
$lang->my->storyMenu->assignedToMe = '指派给我';
$lang->my->storyMenu->reviewByMe = '待我评审';
$lang->my->storyMenu->openedByMe = '由我创建';
$lang->my->storyMenu->reviewedByMe = '由我评审';
$lang->my->storyMenu->closedByMe = '由我关闭';
+1
View File
@@ -67,6 +67,7 @@ $lang->my->taskMenu->canceledByMe = '由我取消';
$lang->my->storyMenu = new stdclass();
$lang->my->storyMenu->assignedToMe = '指派給我';
$lang->my->storyMenu->reviewByMe = '待我評審';
$lang->my->storyMenu->openedByMe = '由我創建';
$lang->my->storyMenu->reviewedByMe = '由我評審';
$lang->my->storyMenu->closedByMe = '由我關閉';
+5
View File
@@ -24,6 +24,11 @@
echo html::a(inlink($app->rawMethod, "mode=story&type=reviewedBy&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "<span class='text'>{$lang->my->storyMenu->reviewedByMe}</span>" . ($type == 'reviewedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'reviewedBy' ? ' btn-active-text' : '') . "'");
echo html::a(inlink($app->rawMethod, "mode=story&type=closedBy&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "<span class='text'>{$lang->my->storyMenu->closedByMe}</span>" . ($type == 'closedBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'closedBy' ? ' btn-active-text' : '') . "'");
}
else
{
echo html::a(inlink($app->rawMethod, "mode=story&type=assignedTo&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "<span class='text'>{$lang->my->storyMenu->assignedToMe}</span>" . ($type == 'assignedTo' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'assignedTo' ? ' btn-active-text' : '') . "'");
echo html::a(inlink($app->rawMethod, "mode=story&type=reviewBy&orderBy=$orderBy&recTotal=$recTotal&recPerPage=$recPerPage&pagerID=$pageID"), "<span class='text'>{$lang->my->storyMenu->reviewByMe}</span>" . ($type == 'reviewBy' ? $recTotalLabel : ''), '', "class='btn btn-link" . ($type == 'reviewBy' ? ' btn-active-text' : '') . "'");
}
?>
</div>
</div>
+1 -1
View File
@@ -16,7 +16,7 @@ $config->story->review = new stdclass();
$config->story->create->requiredFields = 'title';
$config->story->change->requiredFields = 'title';
$config->story->close->requiredFields = 'closedReason';
$config->story->review->requiredFields = 'assignedTo,reviewedBy';
$config->story->review->requiredFields = 'assignedTo';
$config->story->editor = new stdclass();
$config->story->editor->create = array('id' => 'spec,verify', 'tools' => 'simpleTools');
+5 -2
View File
@@ -820,11 +820,16 @@ class story extends control
$this->app->loadLang('testcase');
$this->app->loadLang('execution');
$story = $this->story->getById($storyID);
$reviewer = $this->dao->select('reviewer')->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($story->version)->fetchAll('reviewer');
/* Assign. */
$this->view->title = $this->lang->story->change . "STORY" . $this->lang->colon . $this->view->story->title;
$this->view->users = $this->user->getPairs('pofirst|nodeleted', $this->view->story->assignedTo);
$this->view->position[] = $this->lang->story->change;
$this->view->needReview = ($this->app->user->account == $this->view->product->PO || $this->config->story->needReview == 0) ? "checked='checked'" : "";
$this->view->reviewer = implode(',', array_keys($reviewer));
$this->display();
}
@@ -2187,8 +2192,6 @@ class story extends control
{
$oldStory = $this->dao->findById((int)$params['storyID'])->from(TABLE_STORY)->fetch();
$status = $oldStory->status;
if($params['result'] == 'pass' and $oldStory->status == 'draft') $status = 'active';
if($params['result'] == 'pass' and $oldStory->status == 'changed') $status = 'active';
if($params['result'] == 'revert') $status = 'active';
if($params['result'] == 'reject') $status = 'closed';
}
+1 -1
View File
@@ -2,7 +2,7 @@ $(function()
{
$('#needNotReview').on('change', function()
{
$('#reviewedBy').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated');
$('#reviewer').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated');
getStatus('change', "storyID=" + storyID + ",changed=" + changed + ",needNotReview=" + ($(this).prop('checked') ? 1 : 0));
});
$('#needNotReview').change();
+1 -1
View File
@@ -2,7 +2,7 @@ $(function()
{
$('#needNotReview').on('change', function()
{
$('#reviewedBy').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated');
$('#reviewer').attr('disabled', $(this).is(':checked') ? 'disabled' : null).trigger('chosen:updated');
getStatus('create', "product=" + $('#product').val() + ",execution=" + executionID + ",needNotReview=" + ($(this).prop('checked') ? 1 : 0));
});
$('#needNotReview').change();
+54 -16
View File
@@ -186,7 +186,8 @@ class storyModel extends model
*/
public function create($executionID = 0, $bugID = 0, $from = '')
{
if(!$this->post->needNotReview and empty(array_filter($_POST['reviewedBy'])))
if(isset($_POST['reviewer'])) $_POST['reviewer'] = array_filter($_POST['reviewer']);
if(!$this->post->needNotReview and empty($_POST['reviewer']))
{
dao::$errors[] = $this->lang->story->errorEmptyReviewedBy;
return false;
@@ -202,7 +203,6 @@ class storyModel extends model
->setDefault('plan,verify', '')
->setDefault('openedBy', $this->app->user->account)
->setDefault('openedDate', $now)
->setDefault('reviewedBy', '')
->setIF($this->post->assignedTo != '', 'assignedDate', $now)
->setIF($this->post->needNotReview or $executionID > 0, 'status', 'active')
->setIF($this->post->plan > 0, 'stage', 'planned')
@@ -210,9 +210,8 @@ class storyModel extends model
->setIF($executionID > 0, 'stage', 'projected')
->setIF($bugID > 0, 'fromBug', $bugID)
->join('mailto', ',')
->join('reviewedBy', ',')
->stripTags($this->config->story->editor->create['id'], $this->config->allowedTags)
->remove('files,labels,needNotReview,newStory,uid,contactListMenu,URS')
->remove('files,labels,reviewer,needNotReview,newStory,uid,contactListMenu,URS')
->get();
/* Check repeat story. */
@@ -251,6 +250,19 @@ class storyModel extends model
$data->verify = $story->verify;
$this->dao->insert(TABLE_STORYSPEC)->data($data)->exec();
/* Save the story reviewer to storyreview table. */
if(isset($_POST['reviewer']))
{
foreach($this->post->reviewer as $reviewer)
{
$reviewData = new stdclass();
$reviewData->story = $storyID;
$reviewData->version = 1;
$reviewData->reviewer = $reviewer;
$this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec();
}
}
/* Project or execution linked story. */
if($executionID != 0 and $story->status != 'draft')
{
@@ -528,7 +540,8 @@ class storyModel extends model
return false;
}
if(!$this->post->needNotReview and empty(array_filter($_POST['reviewedBy'])))
if(isset($_POST['reviewer'])) $_POST['reviewer'] = array_filter($_POST['reviewer']);
if(!$this->post->needNotReview and empty($_POST['reviewer']))
{
dao::$errors[] = $this->lang->story->errorEmptyReviewedBy;
return false;
@@ -541,7 +554,6 @@ class storyModel extends model
$story = fixer::input('post')
->callFunc('title', 'trim')
->setDefault('lastEditedBy', $this->app->user->account)
->setDefault('reviewedBy', '')
->add('lastEditedDate', $now)
->setIF($specChanged, 'version', $oldStory->version + 1)
->setIF($specChanged and $oldStory->status == 'active' and $this->post->needNotReview == false, 'status', 'changed')
@@ -552,8 +564,7 @@ class storyModel extends model
->setIF($specChanged and $oldStory->reviewedBy, 'reviewedDate', '0000-00-00')
->setIF($specChanged and $oldStory->closedBy, 'closedDate', '0000-00-00')
->stripTags($this->config->story->editor->change['id'], $this->config->allowedTags)
->join('reviewedBy', ',')
->remove('files,labels,comment,needNotReview,uid')
->remove('files,labels,reviewer,comment,needNotReview,uid')
->get();
if($specChanged and $story->status == 'active' and $this->checkForceReview()) $story->status = 'changed';
$story = $this->loadModel('file')->processImgURL($story, $this->config->story->editor->change['id'], $this->post->uid);
@@ -561,6 +572,7 @@ class storyModel extends model
->autoCheck()
->batchCheck($this->config->story->change->requiredFields, 'notempty')
->where('id')->eq((int)$storyID)->exec();
if(!dao::isError())
{
if($specChanged)
@@ -597,7 +609,23 @@ class storyModel extends model
{
unset($story->spec);
unset($oldStory->spec);
$this->dao->delete()->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($oldStory->version)->andWhere('reviewer')->notin(implode(',', $_POST['reviewer']))->exec();
}
/* Update the reviewer. */
$oldReviewerList = $this->dao->select('reviewer')->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($oldStory->version)->fetchPairs('reviewer');
foreach($_POST['reviewer'] as $reviewer)
{
if(!$specChanged and in_array($reviewer, $oldReviewerList)) continue;
$reviewData = new stdclass();
$reviewData->story = $storyID;
$reviewData->version = $specChanged ? $story->version : $oldStory->version;
$reviewData->reviewer = $reviewer;
$this->dao->insert(TABLE_STORYREVIEW)->data($reviewData)->exec();
}
$this->file->updateObjectID($this->post->uid, $storyID, 'story');
return common::createChanges($oldStory, $story);
}
@@ -1120,12 +1148,10 @@ class storyModel extends model
$now = helper::now();
$date = helper::today();
$story = fixer::input('post')
->add('reviewedBy', $oldStory->reviewedBy . ',' . $this->app->user->account)
->setDefault('reviewedDate', $date)
->setDefault('lastEditedBy', $this->app->user->account)
->setDefault('lastEditedDate', $now)
->setDefault('reviewedBy', '')
->setIF($this->post->result == 'pass' and $oldStory->status == 'draft', 'status', 'active')
->setIF($this->post->result == 'pass' and $oldStory->status == 'changed', 'status', 'active')
->setIF($this->post->result == 'reject', 'closedBy', $this->app->user->account)
->setIF($this->post->result == 'reject', 'closedDate', $now)
->setIF($this->post->result == 'reject', 'assignedTo', 'closed')
@@ -1137,13 +1163,22 @@ class storyModel extends model
->removeIF($this->post->result != 'reject', 'closedReason, duplicateStory, childStories')
->removeIF($this->post->result == 'reject' and $this->post->closedReason != 'duplicate', 'duplicateStory')
->removeIF($this->post->result == 'reject' and $this->post->closedReason != 'subdivided', 'childStories')
->join('reviewedBy', ',')
->remove('result,preVersion,comment')
->get();
/* fix bug #671. */
/* Fix bug #671. */
$this->lang->story->closedReason = $this->lang->story->rejectedReason;
$this->dao->update(TABLE_STORYREVIEW)->set('result')->eq($this->post->result)->set('reviewDate')->eq($now)->where('story')->eq($storyID)->andWhere('version')->eq($oldStory->version)->andWhere('reviewer')->eq($this->app->user->account)->exec();
/* Update the story status by review rules. */
$passCount = 0;
$reviewRule = $this->config->story->reviewRules;
$reviewerList = $this->dao->select('reviewer,result')->from(TABLE_STORYREVIEW)->where('story')->eq($storyID)->andWhere('version')->eq($oldStory->version)->fetchPairs('reviewer', 'result');
foreach($reviewerList as $reviewer => $result) $passCount = $result == 'pass' ? $passCount + 1 : $passCount;
if($reviewRule == 'allpass' and $passCount == count($reviewerList)) $story->status = 'active';
if($reviewRule == 'halfpass' and $passCount >= floor(count($reviewerList) / 2) + 1) $story->status = 'active';
$this->dao->update(TABLE_STORY)->data($story)
->autoCheck()
->batchCheck($this->config->story->review->requiredFields, 'notempty')
@@ -2532,13 +2567,16 @@ class storyModel extends model
*/
public function getUserStories($account, $type = 'assignedTo', $orderBy = 'id_desc', $pager = null, $storyType = 'story')
{
$stories = $this->dao->select('t1.*, t2.name as productTitle')->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id')
->where('t1.deleted')->eq(0)
$sql = $this->dao->select('t1.*, t2.name as productTitle')->from(TABLE_STORY)->alias('t1')
->leftJoin(TABLE_PRODUCT)->alias('t2')->on('t1.product = t2.id');
if($type == 'reviewBy') $sql = $sql->leftJoin(TABLE_STORYREVIEW)->alias('t3')->on('t1.id = t3.story');
$stories = $sql->where('t1.deleted')->eq(0)
->andWhere('t1.type')->eq($storyType)
->beginIF($type != 'closedBy' and $this->app->moduleName == 'block')->andWhere('t1.status')->ne('closed')->fi()
->beginIF($type != 'all')
->beginIF($type == 'assignedTo')->andWhere('assignedTo')->eq($account)->fi()
->beginIF($type == 'reviewBy')->andWhere('t3.reviewer')->eq($account)->andWhere('t3.result')->eq('')->fi()
->beginIF($type == 'openedBy')->andWhere('openedBy')->eq($account)->fi()
->beginIF($type == 'reviewedBy')->andWhere("CONCAT(',', reviewedBy, ',')")->like("%,$account,%")->fi()
->beginIF($type == 'closedBy')->andWhere('closedBy')->eq($account)->fi()
+1 -1
View File
@@ -26,7 +26,7 @@
<th class='w-80px'><?php echo $lang->story->reviewedBy;?></th>
<td colspan="2">
<div class="input-group">
<?php echo html::select('reviewedBy[]', $users, $story->reviewedBy, 'class="form-control chosen" multiple');?>
<?php echo html::select('reviewer[]', $users, $reviewer, 'class="form-control chosen" multiple');?>
<?php if(!$this->story->checkForceReview()):?>
<span class="input-group-addon">
<?php echo html::checkbox('needNotReview', $lang->story->needNotReview, '', "id='needNotReview' {$needReview}");?>
+1 -1
View File
@@ -104,7 +104,7 @@
<td <?php echo $colspan;?>>
<div class="table-row">
<div class="table-col">
<?php echo html::select('reviewedBy[]', $users, empty($needReview) ? $product->PO : '', "class='form-control chosen' multiple");?>
<?php echo html::select('reviewer[]', $users, empty($needReview) ? $product->PO : '', "class='form-control chosen' multiple");?>
</div>
<?php if(!$this->story->checkForceReview()):?>
<div class="table-col w-130px">
-4
View File
@@ -69,10 +69,6 @@ var assignedTo = '<?php $story->lastEditedBy ? print($story->lastEditedBy) : pri
<td><?php echo html::hidden('status', $story->status);?></td>
</tr>
<?php $this->printExtendFields($story, 'table');?>
<tr>
<th><?php echo $lang->story->reviewedBy;?></th>
<td colspan='2'><?php echo html::select('reviewedBy[]', $users, $app->user->account, "class='form-control chosen' multiple data-placeholder='{$lang->story->chosen->reviewedBy}'");?></td>
</tr>
<tr>
<th><?php echo $lang->story->comment;?></th>
<td colspan='2'><?php echo html::textarea('comment', '', "rows='8' class='form-control'");?></td>